diff options
Diffstat (limited to 'LibOVR/Src')
-rw-r--r-- | LibOVR/Src/Kernel/OVR_Math.h | 208 | ||||
-rw-r--r-- | LibOVR/Src/Kernel/OVR_Timer.cpp | 1 | ||||
-rw-r--r-- | LibOVR/Src/Kernel/OVR_Types.h | 14 | ||||
-rw-r--r-- | LibOVR/Src/OVR_HIDDevice.h | 2 | ||||
-rw-r--r-- | LibOVR/Src/OVR_HIDDeviceImpl.h | 13 | ||||
-rw-r--r-- | LibOVR/Src/OVR_LatencyTestImpl.cpp | 68 | ||||
-rw-r--r-- | LibOVR/Src/OVR_LatencyTestImpl.h | 8 | ||||
-rw-r--r-- | LibOVR/Src/OVR_Linux_HIDDevice.cpp | 107 | ||||
-rw-r--r-- | LibOVR/Src/OVR_Linux_HMDDevice.cpp | 105 | ||||
-rw-r--r-- | LibOVR/Src/OVR_Linux_HMDDevice.h | 16 | ||||
-rw-r--r-- | LibOVR/Src/OVR_OSX_HIDDevice.cpp | 272 | ||||
-rw-r--r-- | LibOVR/Src/OVR_OSX_HIDDevice.h | 2 | ||||
-rw-r--r-- | LibOVR/Src/OVR_OSX_HMDDevice.h | 2 | ||||
-rw-r--r-- | LibOVR/Src/OVR_SensorImpl.cpp | 71 | ||||
-rw-r--r-- | LibOVR/Src/OVR_SensorImpl.h | 30 | ||||
-rw-r--r-- | LibOVR/Src/OVR_Win32_HIDDevice.cpp | 3 | ||||
-rw-r--r-- | LibOVR/Src/Util/Util_MagCalibration.cpp | 227 | ||||
-rw-r--r-- | LibOVR/Src/Util/Util_MagCalibration.h | 138 |
18 files changed, 478 insertions, 809 deletions
diff --git a/LibOVR/Src/Kernel/OVR_Math.h b/LibOVR/Src/Kernel/OVR_Math.h index cdcce81..03a6add 100644 --- a/LibOVR/Src/Kernel/OVR_Math.h +++ b/LibOVR/Src/Kernel/OVR_Math.h @@ -57,7 +57,7 @@ enum Axis enum RotateDirection { Rotate_CCW = 1, - Rotate_CW = -1 + Rotate_CW = -1 }; // Constants for right handed and left handed coordinate systems @@ -82,7 +82,7 @@ struct WorldAxes AxisDirection XAxis, YAxis, ZAxis; WorldAxes(AxisDirection x, AxisDirection y, AxisDirection z) - : XAxis(x), YAxis(y), ZAxis(z) + : XAxis(x), YAxis(y), ZAxis(z) { OVR_ASSERT(abs(x) != abs(y) && abs(y) != abs(z) && abs(z) != abs(x));} }; @@ -94,7 +94,7 @@ struct WorldAxes // per type, with Math<float> and Math<double> being distinct. template<class Type> class Math -{ +{ }; // Single-precision Math constants class. @@ -151,18 +151,18 @@ T DegreeToRad(T rads) { return rads * Math<T>::DegreeToRadFactor; } // Numerically stable acos function template<class T> -T Acos(T val) { +T Acos(T val) { if (val > T(1)) return T(0); else if (val < T(-1)) return Math<T>::Pi; - else return acos(val); + else return acos(val); }; // Numerically stable asin function template<class T> -T Asin(T val) { +T Asin(T val) { if (val > T(1)) return Math<T>::PiOver2; else if (val < T(-1)) return Math<T>::PiOver2 * T(3); - else return asin(val); + else return asin(val); }; #ifdef OVR_CC_MSVC @@ -190,7 +190,7 @@ public: bool operator== (const Vector2& b) const { return x == b.x && y == b.y; } bool operator!= (const Vector2& b) const { return x != b.x || y != b.y; } - + Vector2 operator+ (const Vector2& b) const { return Vector2(x + b.x, y + b.y); } Vector2& operator+= (const Vector2& b) { x += b.x; y += b.y; return *this; } Vector2 operator- (const Vector2& b) const { return Vector2(x - b.x, y - b.y); } @@ -212,7 +212,7 @@ public: { return (fabs(b.x-x) < tolerance) && (fabs(b.y-y) < tolerance); } - + // Entrywise product of two vectors Vector2 EntrywiseMultiply(const Vector2& b) const { return Vector2(x * b.x, y * b.y);} @@ -222,8 +222,8 @@ public: T Dot(const Vector2& b) const { return x*b.x + y*b.y; } // Returns the angle from this vector to b, in radians. - T Angle(const Vector2& b) const - { + T Angle(const Vector2& b) const + { T div = LengthSq()*b.LengthSq(); OVR_ASSERT(div != T(0)); T result = Acos((this->Dot(b))/sqrt(div)); @@ -241,19 +241,19 @@ public: // Determine if this a unit vector. bool IsNormalized() const { return fabs(LengthSq() - T(1)) < Math<T>::Tolerance; } - // Normalize, convention vector length to 1. - void Normalize() + // Normalize, convention vector length to 1. + void Normalize() { T l = Length(); OVR_ASSERT(l != T(0)); - *this /= l; + *this /= l; } // Returns normalized (unit) version of the vector without modifying itself. - Vector2 Normalized() const - { + Vector2 Normalized() const + { T l = Length(); OVR_ASSERT(l != T(0)); - return *this / l; + return *this / l; } // Linearly interpolates from this vector to another. @@ -262,11 +262,11 @@ public: // Projects this vector onto the argument; in other words, // A.Project(B) returns projection of vector A onto B. - Vector2 ProjectTo(const Vector2& b) const - { + Vector2 ProjectTo(const Vector2& b) const + { T l2 = b.LengthSq(); OVR_ASSERT(l2 != T(0)); - return b * ( Dot(b) / l2 ); + return b * ( Dot(b) / l2 ); } }; @@ -294,7 +294,7 @@ public: bool operator== (const Vector3& b) const { return x == b.x && y == b.y && z == b.z; } bool operator!= (const Vector3& b) const { return x != b.x || y != b.y || z != b.z; } - + Vector3 operator+ (const Vector3& b) const { return Vector3(x + b.x, y + b.y, z + b.z); } Vector3& operator+= (const Vector3& b) { x += b.x; y += b.y; z += b.z; return *this; } Vector3 operator- (const Vector3& b) const { return Vector3(x - b.x, y - b.y, z - b.z); } @@ -314,14 +314,14 @@ public: // Compare two vectors for equality with tolerance. Returns true if vectors match withing tolerance. bool Compare(const Vector3&b, T tolerance = Mathf::Tolerance) { - return (fabs(b.x-x) < tolerance) && - (fabs(b.y-y) < tolerance) && + return (fabs(b.x-x) < tolerance) && + (fabs(b.y-y) < tolerance) && (fabs(b.z-z) < tolerance); } - + // Entrywise product of two vectors - Vector3 EntrywiseMultiply(const Vector3& b) const { return Vector3(x * b.x, - y * b.y, + Vector3 EntrywiseMultiply(const Vector3& b) const { return Vector3(x * b.x, + y * b.y, z * b.z);} // Dot product @@ -337,7 +337,7 @@ public: x*b.y - y*b.x); } // Returns the angle from this vector to b, in radians. - T Angle(const Vector3& b) const + T Angle(const Vector3& b) const { T div = LengthSq()*b.LengthSq(); OVR_ASSERT(div != T(0)); @@ -352,24 +352,24 @@ public: // Returns distance between two points represented by vectors. T Distance(Vector3& b) const { return (*this - b).Length(); } - + // Determine if this a unit vector. bool IsNormalized() const { return fabs(LengthSq() - T(1)) < Math<T>::Tolerance; } - // Normalize, convention vector length to 1. - void Normalize() + // Normalize, convention vector length to 1. + void Normalize() { T l = Length(); OVR_ASSERT(l != T(0)); - *this /= l; + *this /= l; } // Returns normalized (unit) version of the vector without modifying itself. - Vector3 Normalized() const - { + Vector3 Normalized() const + { T l = Length(); OVR_ASSERT(l != T(0)); - return *this / l; + return *this / l; } // Linearly interpolates from this vector to another. @@ -378,11 +378,11 @@ public: // Projects this vector onto the argument; in other words, // A.Project(B) returns projection of vector A onto B. - Vector3 ProjectTo(const Vector3& b) const - { + Vector3 ProjectTo(const Vector3& b) const + { T l2 = b.LengthSq(); OVR_ASSERT(l2 != T(0)); - return b * ( Dot(b) / l2 ); + return b * ( Dot(b) / l2 ); } // Projects this vector onto a plane defined by a normal vector @@ -412,7 +412,7 @@ public: bool operator== (const Size& b) const { return Width == b.Width && Height == b.Height; } bool operator!= (const Size& b) const { return Width != b.Width || Height != b.Height; } - + Size operator+ (const Size& b) const { return Size(Width + b.Width, Height + b.Height); } Size& operator+= (const Size& b) { Width += b.Width; Height += b.Height; return *this; } Size operator- (const Size& b) const { return Size(Width - b.Width, Height - b.Height); } @@ -425,7 +425,7 @@ public: // Scalar multiplication/division scales both components. Size operator* (T s) const { return Size(Width*s, Height*s); } - Size& operator*= (T s) { Width *= s; Height *= s; return *this; } + Size& operator*= (T s) { Width *= s; Height *= s; return *this; } Size operator/ (T s) const { return Size(Width/s, Height/s); } Size& operator/= (T s) { Width /= s; Height /= s; return *this; } @@ -449,19 +449,19 @@ typedef Size<double> Sized; // The matrix is stored in row-major order in memory, meaning that values // of the first row are stored before the next one. // -// The arrangement of the matrix is chosen to be in Right-Handed +// The arrangement of the matrix is chosen to be in Right-Handed // coordinate system and counterclockwise rotations when looking down // the axis // // Transformation Order: // - Transformations are applied from right to left, so the expression // M1 * M2 * M3 * V means that the vector V is transformed by M3 first, -// followed by M2 and M1. +// followed by M2 and M1. // // Coordinate system: Right Handed // // Rotations: Counterclockwise when looking down the axis. All angles are in radians. -// +// // | sx 01 02 tx | // First column (sx, 10, 20): Axis X basis vector. // | 10 sy 12 ty | // Second column (01, sy, 21): Axis Y basis vector. // | 20 21 sz tz | // Third columnt (02, 12, sz): Axis Z basis vector. @@ -474,7 +474,7 @@ class Matrix4f static Matrix4f IdentityValue; public: - float M[4][4]; + float M[4][4]; enum NoInitType { NoInit }; @@ -484,7 +484,7 @@ public: // By default, we construct identity matrix. Matrix4f() { - SetIdentity(); + SetIdentity(); } Matrix4f(float m11, float m12, float m13, float m14, @@ -670,8 +670,8 @@ public: Matrix4f Adjugated() const { - return Matrix4f(Cofactor(0,0), Cofactor(1,0), Cofactor(2,0), Cofactor(3,0), - Cofactor(0,1), Cofactor(1,1), Cofactor(2,1), Cofactor(3,1), + return Matrix4f(Cofactor(0,0), Cofactor(1,0), Cofactor(2,0), Cofactor(3,0), + Cofactor(0,1), Cofactor(1,1), Cofactor(2,1), Cofactor(3,1), Cofactor(0,2), Cofactor(1,2), Cofactor(2,2), Cofactor(3,2), Cofactor(0,3), Cofactor(1,3), Cofactor(2,3), Cofactor(3,3)); } @@ -722,7 +722,7 @@ public: float psign = -1.0f; if (((A1 + 1) % 3 == A2) && ((A2 + 1) % 3 == A3)) // Determine whether even permutation psign = 1.0f; - + float pm = psign*M[A1][A3]; if (pm < -1.0f + Math<float>::SingularityRadius) { // South pole singularity @@ -754,9 +754,9 @@ public: // rotations are CCW or CW (D) in LH or RH coordinate system (S) template <Axis A1, Axis A2, RotateDirection D, HandedSystem S> void ToEulerAnglesABA(float *a, float *b, float *c) - { + { OVR_COMPILER_ASSERT(A1 != A2); - + // Determine the axis that was not supplied int m = 3 - A1 - A2; @@ -785,21 +785,21 @@ public: } return; } - + // Creates a matrix that converts the vertices from one coordinate system // to another. static Matrix4f AxisConversion(const WorldAxes& to, const WorldAxes& from) - { + { // Holds axis values from the 'to' structure int toArray[3] = { to.XAxis, to.YAxis, to.ZAxis }; // The inverse of the toArray - int inv[4]; + int inv[4]; inv[0] = inv[abs(to.XAxis)] = 0; inv[abs(to.YAxis)] = 1; inv[abs(to.ZAxis)] = 2; - Matrix4f m(0, 0, 0, + Matrix4f m(0, 0, 0, 0, 0, 0, 0, 0, 0); @@ -808,7 +808,7 @@ public: m.M[inv[abs(from.YAxis)]][1] = float(from.YAxis/toArray[inv[abs(from.YAxis)]]); m.M[inv[abs(from.ZAxis)]][2] = float(from.ZAxis/toArray[inv[abs(from.ZAxis)]]); return m; - } + } // Creates a matrix for translation by vector @@ -861,7 +861,7 @@ public: return t; } - + // Creates a rotation matrix rotating around the X axis by 'angle' radians. // Just for quick testing. Not for final API. Need to remove case. @@ -869,19 +869,19 @@ public: { float sina = s * d *sin(angle); float cosa = cos(angle); - + switch(A) { case Axis_X: - return Matrix4f(1, 0, 0, + return Matrix4f(1, 0, 0, 0, cosa, -sina, 0, sina, cosa); case Axis_Y: - return Matrix4f(cosa, 0, sina, + return Matrix4f(cosa, 0, sina, 0, 1, 0, -sina, 0, cosa); case Axis_Z: - return Matrix4f(cosa, -sina, 0, + return Matrix4f(cosa, -sina, 0, sina, cosa, 0, 0, 0, 1); } @@ -899,7 +899,7 @@ public: { float sina = sin(angle); float cosa = cos(angle); - return Matrix4f(1, 0, 0, + return Matrix4f(1, 0, 0, 0, cosa, -sina, 0, sina, cosa); } @@ -915,7 +915,7 @@ public: { float sina = sin(angle); float cosa = cos(angle); - return Matrix4f(cosa, 0, sina, + return Matrix4f(cosa, 0, sina, 0, 1, 0, -sina, 0, cosa); } @@ -931,7 +931,7 @@ public: { float sina = sin(angle); float cosa = cos(angle); - return Matrix4f(cosa, -sina, 0, + return Matrix4f(cosa, -sina, 0, sina, cosa, 0, 0, 0, 1); } @@ -945,12 +945,12 @@ public: // LookAtLH creates a View transformation matrix for left-handed coordinate system. // The resulting matrix points camera from 'eye' towards 'at' direction, with 'up' - // specifying the up vector. + // specifying the up vector. static Matrix4f LookAtLH(const Vector3f& eye, const Vector3f& at, const Vector3f& up); - - + + // PerspectiveRH creates a right-handed perspective projection matrix that can be - // used with the Oculus sample renderer. + // used with the Oculus sample renderer. // yfov - Specifies vertical field of view in radians. // aspect - Screen aspect ration, which is usually width/height for square pixels. // Note that xfov = yfov * aspect. @@ -959,10 +959,10 @@ public: // Even though RHS usually looks in the direction of negative Z, positive values // are expected for znear and zfar. static Matrix4f PerspectiveRH(float yfov, float aspect, float znear, float zfar); - - + + // PerspectiveRH creates a left-handed perspective projection matrix that can be - // used with the Oculus sample renderer. + // used with the Oculus sample renderer. // yfov - Specifies vertical field of view in radians. // aspect - Screen aspect ration, which is usually width/height for square pixels. // Note that xfov = yfov * aspect. @@ -979,7 +979,7 @@ public: // **************************************** Quat **************************************// // // Quatf represents a quaternion class used for rotations. -// +// // Quaternion multiplications are done in right-to-left order, to match the // behavior of matrices. @@ -989,7 +989,7 @@ class Quat { public: // w + Xi + Yj + Zk - T x, y, z, w; + T x, y, z, w; Quat() : x(0), y(0), z(0), w(1) {} Quat(T x_, T y_, T z_, T w_) : x(x_), y(y_), z(z_), w(w_) {} @@ -1029,7 +1029,7 @@ public: *axis = Vector3<T>(x, y, z).Normalized(); *angle = T(2) * Acos(w); } - else + else { *axis = Vector3<T>(1, 0, 0); *angle= 0; @@ -1059,8 +1059,8 @@ public: T LengthSq() const { return (x * x + y * y + z * z + w * w); } // Simple Eulidean distance in R^4 (not SLERP distance, but at least respects Haar measure) - T Distance(const Quat& q) const - { + T Distance(const Quat& q) const + { T d1 = (*this - q).Length(); T d2 = (*this + q).Length(); // Antipodal point check return (d1 < d2) ? d1 : d2; @@ -1076,31 +1076,31 @@ public: // Normalize bool IsNormalized() const { return fabs(LengthSq() - T(1)) < Math<T>::Tolerance; } - void Normalize() + void Normalize() { T l = Length(); OVR_ASSERT(l != T(0)); - *this /= l; + *this /= l; } - Quat Normalized() const - { + Quat Normalized() const + { T l = Length(); OVR_ASSERT(l != T(0)); - return *this / l; + return *this / l; } // Returns conjugate of the quaternion. Produces inverse rotation if quaternion is normalized. Quat Conj() const { return Quat(-x, -y, -z, w); } - // Quaternion multiplication. Combines quaternion rotations, performing the one on the + // Quaternion multiplication. Combines quaternion rotations, performing the one on the // right hand side first. Quat operator* (const Quat& b) const { return Quat(w * b.x + x * b.w + y * b.z - z * b.y, w * b.y - x * b.z + y * b.w + z * b.x, w * b.z + x * b.y - y * b.x + z * b.w, w * b.w - x * b.x - y * b.y - z * b.z); } - // + // // this^p normalized; same as rotating by this p times. Quat PowNormalized(T p) const { @@ -1109,15 +1109,15 @@ public: GetAxisAngle(&v, &a); return Quat(v, a * p); } - + // Rotate transforms vector in a manner that matches Matrix rotations (counter-clockwise, - // assuming negative direction of the axis). Standard formula: q(t) * V * q(t)^-1. + // assuming negative direction of the axis). Standard formula: q(t) * V * q(t)^-1. Vector3<T> Rotate(const Vector3<T>& v) const { return ((*this * Quat<T>(v.x, v.y, v.z, T(0))) * Inverted()).Imag(); } - + // Inversed quaternion rotates in the opposite direction. Quat Inverted() const { @@ -1129,7 +1129,7 @@ public: { *this = Quat(-x, -y, -z, w); } - + // Converting quaternion to matrix. operator Matrix4f() const { @@ -1153,31 +1153,31 @@ public: // In almost all cases, the first part is executed. // However, if the trace is not positive, the other // cases arise. - if (trace > T(0)) + if (trace > T(0)) { T s = sqrt(trace + T(1)) * T(2); // s=4*qw q.w = T(0.25) * s; q.x = (m.M[2][1] - m.M[1][2]) / s; q.y = (m.M[0][2] - m.M[2][0]) / s; - q.z = (m.M[1][0] - m.M[0][1]) / s; - } - else if ((m.M[0][0] > m.M[1][1])&&(m.M[0][0] > m.M[2][2])) + q.z = (m.M[1][0] - m.M[0][1]) / s; + } + else if ((m.M[0][0] > m.M[1][1])&&(m.M[0][0] > m.M[2][2])) { T s = sqrt(T(1) + m.M[0][0] - m.M[1][1] - m.M[2][2]) * T(2); q.w = (m.M[2][1] - m.M[1][2]) / s; q.x = T(0.25) * s; q.y = (m.M[0][1] + m.M[1][0]) / s; q.z = (m.M[2][0] + m.M[0][2]) / s; - } - else if (m.M[1][1] > m.M[2][2]) + } + else if (m.M[1][1] > m.M[2][2]) { T s = sqrt(T(1) + m.M[1][1] - m.M[0][0] - m.M[2][2]) * T(2); // S=4*qy q.w = (m.M[0][2] - m.M[2][0]) / s; q.x = (m.M[0][1] + m.M[1][0]) / s; q.y = T(0.25) * s; q.z = (m.M[1][2] + m.M[2][1]) / s; - } - else + } + else { T s = sqrt(T(1) + m.M[2][2] - m.M[0][0] - m.M[1][1]) * T(2); // S=4*qz q.w = (m.M[1][0] - m.M[0][1]) / s; @@ -1189,7 +1189,7 @@ public: } - + // GetEulerAngles extracts Euler angles from the quaternion, in the specified order of // axis rotations and the specified coordinate system. Right-handed coordinate system // is the default, with CCW rotations while looking in the negative axis direction. @@ -1199,7 +1199,7 @@ public: // is followed by rotation c around axis A3 // rotations are CCW or CW (D) in LH or RH coordinate system (S) template <Axis A1, Axis A2, Axis A3, RotateDirection D, HandedSystem S> - void GetEulerAngles(T *a, T *b, T *c) + void GetEulerAngles(T *a, T *b, T *c) const { OVR_COMPILER_ASSERT((A1 != A2) && (A2 != A3) && (A1 != A3)); @@ -1214,7 +1214,7 @@ public: // Determine whether even permutation if (((A1 + 1) % 3 == A2) && ((A2 + 1) % 3 == A3)) psign = T(1); - + T s2 = psign * T(2) * (psign*w*Q[A2] + Q[A1]*Q[A3]); if (s2 < T(-1) + Math<T>::SingularityRadius) @@ -1238,7 +1238,7 @@ public: *b = S*D*asin(s2); *c = S*D*atan2(T(2)*(w*Q[A3] - psign*Q[A1]*Q[A2]), ww + Q11 - Q22 - Q33); - } + } return; } @@ -1330,7 +1330,7 @@ public: }; Angle() : a(0) {} - + // Fix the range to be between -Pi and Pi Angle(T a_, AngularUnits u = Radians) : a((u == Radians) ? a_ : a_*Math<T>::DegreeToRadFactor) { FixRange(); } @@ -1341,10 +1341,10 @@ public: bool operator== (const Angle& b) const { return a == b.a; } bool operator!= (const Angle& b) const { return a != b.a; } -// bool operator< (const Angle& b) const { return a < a.b; } -// bool operator> (const Angle& b) const { return a > a.b; } -// bool operator<= (const Angle& b) const { return a <= a.b; } -// bool operator>= (const Angle& b) const { return a >= a.b; } +// bool operator< (const Angle& b) const { return a < a.b; } +// bool operator> (const Angle& b) const { return a > a.b; } +// bool operator<= (const Angle& b) const { return a <= a.b; } +// bool operator>= (const Angle& b) const { return a >= a.b; } // bool operator= (const T& x) { a = x; FixRange(); } // These operations assume a is already between -Pi and Pi. @@ -1356,7 +1356,7 @@ public: Angle& operator-= (const T& x) { a = a - x; FixRange(); return *this; } Angle operator- (const Angle& b) const { Angle res = *this; res -= b; return res; } Angle operator- (const T& x) const { Angle res = *this; res -= x; return res; } - + T Distance(const Angle& b) { T c = fabs(a - b.a); return (c <= Math<T>::Pi) ? c : Math<T>::TwoPi - c; } private: @@ -1364,7 +1364,7 @@ private: // The stored angle, which should be maintained between -Pi and Pi T a; - // Fixes the angle range to [-Pi,Pi], but assumes no more than 2Pi away on either side + // Fixes the angle range to [-Pi,Pi], but assumes no more than 2Pi away on either side inline void FastFixRange() { if (a < -Math<T>::Pi) diff --git a/LibOVR/Src/Kernel/OVR_Timer.cpp b/LibOVR/Src/Kernel/OVR_Timer.cpp index 84ff4a1..74b60b0 100644 --- a/LibOVR/Src/Kernel/OVR_Timer.cpp +++ b/LibOVR/Src/Kernel/OVR_Timer.cpp @@ -37,6 +37,7 @@ limitations under the License. #include <sys/time.h> #endif + namespace OVR { diff --git a/LibOVR/Src/Kernel/OVR_Types.h b/LibOVR/Src/Kernel/OVR_Types.h index 6b2922e..3a8fb61 100644 --- a/LibOVR/Src/Kernel/OVR_Types.h +++ b/LibOVR/Src/Kernel/OVR_Types.h @@ -4,7 +4,7 @@ PublicHeader: OVR.h Filename : OVR_Types.h Content : Standard library defines and simple types Created : September 19, 2012 -Notes : +Notes : Copyright : Copyright 2013 Oculus VR, Inc. All Rights reserved. @@ -228,7 +228,7 @@ typedef unsigned long UInt32; typedef __int64 SInt64; // 64 bit Integer (QWord) typedef unsigned __int64 UInt64; - + #elif defined(OVR_OS_MAC) || defined(OVR_OS_IPHONE) || defined(OVR_CC_GNU) typedef int SByte __attribute__((__mode__ (__QI__))); @@ -289,7 +289,7 @@ namespace BaseTypes // OVR_FORCE_INLINE - Forces inline expansion of function // OVR_ASM - Assembly language prefix // OVR_STR - Prefixes string with L"" if building unicode -// +// // OVR_STDCALL - Use stdcall calling convention (Pascal arg order) // OVR_CDECL - Use cdecl calling convention (C argument order) // OVR_FASTCALL - Use fastcall calling convention (registers) @@ -311,7 +311,7 @@ namespace BaseTypes #if defined(OVR_OS_WIN32) - + // ***** Win32 // Byte order @@ -353,12 +353,12 @@ namespace BaseTypes #else # define OVR_BYTE_ORDER OVR_LITTLE_ENDIAN #endif - + // Assembly macros #define OVR_ASM __asm__ #define OVR_ASM_PROC(procname) OVR_ASM #define OVR_ASM_END OVR_ASM - + // Calling convention - goes after function return type but before function name #define OVR_FASTCALL #define OVR_STDCALL @@ -377,7 +377,7 @@ namespace BaseTypes # define OVR_DEBUG_BREAK ((void)0) # define OVR_ASSERT(p) ((void)0) -#else +#else // Microsoft Win32 specific debugging support #if defined(OVR_OS_WIN32) diff --git a/LibOVR/Src/OVR_HIDDevice.h b/LibOVR/Src/OVR_HIDDevice.h index 7fc6fee..a5e1648 100644 --- a/LibOVR/Src/OVR_HIDDevice.h +++ b/LibOVR/Src/OVR_HIDDevice.h @@ -126,7 +126,7 @@ public: class HIDHandler { public: - virtual void OnInputReport(UByte* pData, UInt32 length) + virtual void OnInputReport(const UByte* pData, UInt32 length) { OVR_UNUSED2(pData, length); } virtual UInt64 OnTicks(UInt64 ticksMks) diff --git a/LibOVR/Src/OVR_HIDDeviceImpl.h b/LibOVR/Src/OVR_HIDDeviceImpl.h index 598adba..b134159 100644 --- a/LibOVR/Src/OVR_HIDDeviceImpl.h +++ b/LibOVR/Src/OVR_HIDDeviceImpl.h @@ -29,6 +29,7 @@ limitations under the License. //#include "OVR_Device.h" #include "OVR_DeviceImpl.h" +#include "OVR_HIDDeviceImpl.h" namespace OVR { @@ -56,7 +57,7 @@ class HIDDeviceImpl : public DeviceImpl<B>, public HIDDevice::HIDHandler { public: HIDDeviceImpl(HIDDeviceCreateDesc* createDesc, DeviceBase* parent) - : DeviceImpl<B>(createDesc, parent) + : DeviceImpl<B>(createDesc, parent) { } @@ -93,11 +94,11 @@ public: case Message_DeviceAdded: manager->CallOnDeviceAdded(this->pCreateDesc); break; - + case Message_DeviceRemoved: manager->CallOnDeviceRemoved(this->pCreateDesc); break; - + default:; } } @@ -125,7 +126,7 @@ public: } virtual void Shutdown() - { + { InternalDevice->SetHandler(NULL); // Remove the handler, if any. @@ -159,7 +160,7 @@ public: }; bool SetFeatureReport(UByte* data, UInt32 length) - { + { WriteData writeData(data, length); // Push call with wait. @@ -178,7 +179,7 @@ public: } bool GetFeatureReport(UByte* data, UInt32 length) - { + { bool result = false; ThreadCommandQueue* pQueue = this->GetManagerImpl()->GetThreadQueue(); diff --git a/LibOVR/Src/OVR_LatencyTestImpl.cpp b/LibOVR/Src/OVR_LatencyTestImpl.cpp index 209487c..3f29eb7 100644 --- a/LibOVR/Src/OVR_LatencyTestImpl.cpp +++ b/LibOVR/Src/OVR_LatencyTestImpl.cpp @@ -31,7 +31,7 @@ namespace OVR { //------------------------------------------------------------------------------------- // ***** Oculus Latency Tester specific packet data structures -enum { +enum { LatencyTester_VendorId = Oculus_VendorId, LatencyTester_ProductId = 0x0101, }; @@ -88,7 +88,7 @@ struct LatencyTestSamples SampleCount = buffer[1]; Timestamp = DecodeUInt16(buffer + 2); - + for (UByte i = 0; i < SampleCount; i++) { UnpackSamples(buffer + 4 + (3 * i), &Samples[i].Value[0], &Samples[i].Value[1], &Samples[i].Value[2]); @@ -104,7 +104,7 @@ struct LatencyTestSamplesMessage LatencyTestSamples Samples; }; -bool DecodeLatencyTestSamplesMessage(LatencyTestSamplesMessage* message, UByte* buffer, int size) +bool DecodeLatencyTestSamplesMessage(LatencyTestSamplesMessage* message, const UByte* buffer, int size) { memset(message, 0, sizeof(LatencyTestSamplesMessage)); @@ -157,7 +157,7 @@ struct LatencyTestColorDetectedMessage LatencyTestColorDetected ColorDetected; }; -bool DecodeLatencyTestColorDetectedMessage(LatencyTestColorDetectedMessage* message, UByte* buffer, int size) +bool DecodeLatencyTestColorDetectedMessage(LatencyTestColorDetectedMessage* message, const UByte* buffer, int size) { memset(message, 0, sizeof(LatencyTestColorDetectedMessage)); @@ -206,7 +206,7 @@ struct LatencyTestStartedMessage LatencyTestStarted TestStarted; }; -bool DecodeLatencyTestStartedMessage(LatencyTestStartedMessage* message, UByte* buffer, int size) +bool DecodeLatencyTestStartedMessage(LatencyTestStartedMessage* message, const UByte* buffer, int size) { memset(message, 0, sizeof(LatencyTestStartedMessage)); @@ -253,7 +253,7 @@ struct LatencyTestButtonMessage LatencyTestButton Button; }; -bool DecodeLatencyTestButtonMessage(LatencyTestButtonMessage* message, UByte* buffer, int size) +bool DecodeLatencyTestButtonMessage(LatencyTestButtonMessage* message, const UByte* buffer, int size) { memset(message, 0, sizeof(LatencyTestButtonMessage)); @@ -314,7 +314,7 @@ struct LatencyTestCalibrateImpl UByte Buffer[PacketSize]; Color CalibrationColor; - + LatencyTestCalibrateImpl(const Color& calibrationColor) : CalibrationColor(calibrationColor) { @@ -418,7 +418,7 @@ void LatencyTestDeviceFactory::EnumerateDevices(EnumerateVisitor& visitor) void operator = (const LatencyTestEnumerator&) { } DeviceFactory* pFactory; - EnumerateVisitor& ExternalVisitor; + EnumerateVisitor& ExternalVisitor; public: LatencyTestEnumerator(DeviceFactory* factory, EnumerateVisitor& externalVisitor) : pFactory(factory), ExternalVisitor(externalVisitor) { } @@ -443,10 +443,10 @@ void LatencyTestDeviceFactory::EnumerateDevices(EnumerateVisitor& visitor) bool LatencyTestDeviceFactory::MatchVendorProduct(UInt16 vendorId, UInt16 productId) const { - return ((vendorId == LatencyTester_VendorId) && (productId == LatencyTester_ProductId)); + return ((vendorId == LatencyTester_VendorId) && (productId == LatencyTester_ProductId)); } -bool LatencyTestDeviceFactory::DetectHIDDevice(DeviceManager* pdevMgr, +bool LatencyTestDeviceFactory::DetectHIDDevice(DeviceManager* pdevMgr, const HIDDeviceDesc& desc) { if (MatchVendorProduct(desc.VendorId, desc.ProductId)) @@ -497,7 +497,7 @@ LatencyTestDeviceImpl::LatencyTestDeviceImpl(LatencyTestDeviceCreateDesc* create LatencyTestDeviceImpl::~LatencyTestDeviceImpl() { // Check that Shutdown() was called. - OVR_ASSERT(!pCreateDesc->pDevice); + OVR_ASSERT(!pCreateDesc->pDevice); } // Internal creation APIs. @@ -513,20 +513,20 @@ bool LatencyTestDeviceImpl::Initialize(DeviceBase* parent) } void LatencyTestDeviceImpl::Shutdown() -{ +{ HIDDeviceImpl<OVR::LatencyTestDevice>::Shutdown(); LogText("OVR::LatencyTestDevice - Closed '%s'\n", getHIDDesc()->Path.ToCStr()); } -void LatencyTestDeviceImpl::OnInputReport(UByte* pData, UInt32 length) +void LatencyTestDeviceImpl::OnInputReport(const UByte* pData, UInt32 length) { - + bool processed = false; if (!processed) { - LatencyTestSamplesMessage message; - if (DecodeLatencyTestSamplesMessage(&message, pData, length)) + LatencyTestSamplesMessage message; + if (DecodeLatencyTestSamplesMessage(&message, pData, length)) { processed = true; onLatencyTestSamplesMessage(&message); @@ -535,8 +535,8 @@ void LatencyTestDeviceImpl::OnInputReport(UByte* pData, UInt32 length) if (!processed) { - LatencyTestColorDetectedMessage message; - if (DecodeLatencyTestColorDetectedMessage(&message, pData, length)) + LatencyTestColorDetectedMessage message; + if (DecodeLatencyTestColorDetectedMessage(&message, pData, length)) { processed = true; onLatencyTestColorDetectedMessage(&message); @@ -545,8 +545,8 @@ void LatencyTestDeviceImpl::OnInputReport(UByte* pData, UInt32 length) if (!processed) { - LatencyTestStartedMessage message; - if (DecodeLatencyTestStartedMessage(&message, pData, length)) + LatencyTestStartedMessage message; + if (DecodeLatencyTestStartedMessage(&message, pData, length)) { processed = true; onLatencyTestStartedMessage(&message); @@ -555,8 +555,8 @@ void LatencyTestDeviceImpl::OnInputReport(UByte* pData, UInt32 length) if (!processed) { - LatencyTestButtonMessage message; - if (DecodeLatencyTestButtonMessage(&message, pData, length)) + LatencyTestButtonMessage message; + if (DecodeLatencyTestButtonMessage(&message, pData, length)) { processed = true; onLatencyTestButtonMessage(&message); @@ -565,7 +565,7 @@ void LatencyTestDeviceImpl::OnInputReport(UByte* pData, UInt32 length) } bool LatencyTestDeviceImpl::SetConfiguration(const OVR::LatencyTestConfiguration& configuration, bool waitFlag) -{ +{ bool result = false; ThreadCommandQueue* queue = GetManagerImpl()->GetThreadQueue(); @@ -576,9 +576,9 @@ bool LatencyTestDeviceImpl::SetConfiguration(const OVR::LatencyTestConfiguration return queue->PushCall(this, &LatencyTestDeviceImpl::setConfiguration, configuration); } - if (!queue->PushCallAndWaitResult( this, + if (!queue->PushCallAndWaitResult( this, &LatencyTestDeviceImpl::setConfiguration, - &result, + &result, configuration)) { return false; @@ -597,7 +597,7 @@ bool LatencyTestDeviceImpl::setConfiguration(const OVR::LatencyTestConfiguration } bool LatencyTestDeviceImpl::GetConfiguration(OVR::LatencyTestConfiguration* configuration) -{ +{ bool result = false; ThreadCommandQueue* pQueue = this->GetManagerImpl()->GetThreadQueue(); @@ -630,9 +630,9 @@ bool LatencyTestDeviceImpl::SetCalibrate(const Color& calibrationColor, bool wai return queue->PushCall(this, &LatencyTestDeviceImpl::setCalibrate, calibrationColor); } - if (!queue->PushCallAndWaitResult( this, + if (!queue->PushCallAndWaitResult( this, &LatencyTestDeviceImpl::setCalibrate, - &result, + &result, calibrationColor)) { return false; @@ -657,9 +657,9 @@ bool LatencyTestDeviceImpl::SetStartTest(const Color& targetColor, bool waitFlag return queue->PushCall(this, &LatencyTestDeviceImpl::setStartTest, targetColor); } - if (!queue->PushCallAndWaitResult( this, + if (!queue->PushCallAndWaitResult( this, &LatencyTestDeviceImpl::setStartTest, - &result, + &result, targetColor)) { return false; @@ -684,9 +684,9 @@ bool LatencyTestDeviceImpl::SetDisplay(const OVR::LatencyTestDisplay& display, b return queue->PushCall(this, &LatencyTestDeviceImpl::setDisplay, display); } - if (!queue->PushCallAndWaitResult( this, + if (!queue->PushCallAndWaitResult( this, &LatencyTestDeviceImpl::setDisplay, - &result, + &result, display)) { return false; @@ -711,12 +711,12 @@ void LatencyTestDeviceImpl::onLatencyTestSamplesMessage(LatencyTestSamplesMessag // Call OnMessage() within a lock to avoid conflicts with handlers. Lock::Locker scopeLock(HandlerRef.GetLock()); - + if (HandlerRef.GetHandler()) { MessageLatencyTestSamples samples(this); for (UByte i = 0; i < s.SampleCount; i++) - { + { samples.Samples.PushBack(Color(s.Samples[i].Value[0], s.Samples[i].Value[1], s.Samples[i].Value[2])); } diff --git a/LibOVR/Src/OVR_LatencyTestImpl.h b/LibOVR/Src/OVR_LatencyTestImpl.h index bab0180..63f49c1 100644 --- a/LibOVR/Src/OVR_LatencyTestImpl.h +++ b/LibOVR/Src/OVR_LatencyTestImpl.h @@ -50,7 +50,7 @@ public: virtual bool DetectHIDDevice(DeviceManager* pdevMgr, const HIDDeviceDesc& desc); protected: - DeviceManager* getManager() const { return (DeviceManager*) pManager; } + DeviceManager* getManager() const { return (DeviceManager*) pManager; } }; @@ -60,7 +60,7 @@ class LatencyTestDeviceCreateDesc : public HIDDeviceCreateDesc public: LatencyTestDeviceCreateDesc(DeviceFactory* factory, const HIDDeviceDesc& hidDesc) : HIDDeviceCreateDesc(factory, Device_LatencyTester, hidDesc) { } - + virtual DeviceCreateDesc* Clone() const { return new LatencyTestDeviceCreateDesc(*this); @@ -72,7 +72,7 @@ public: DeviceCreateDesc**) const { if ((other.Type == Device_LatencyTester) && (pFactory == other.pFactory)) - { + { const LatencyTestDeviceCreateDesc& s2 = (const LatencyTestDeviceCreateDesc&) other; if (MatchHIDDevice(s2.HIDDesc)) return Match_Found; @@ -106,7 +106,7 @@ public: virtual void Shutdown(); // DeviceManagerThread::Notifier interface. - virtual void OnInputReport(UByte* pData, UInt32 length); + virtual void OnInputReport(const UByte* pData, UInt32 length); // LatencyTesterDevice interface virtual bool SetConfiguration(const OVR::LatencyTestConfiguration& configuration, bool waitFlag = false); diff --git a/LibOVR/Src/OVR_Linux_HIDDevice.cpp b/LibOVR/Src/OVR_Linux_HIDDevice.cpp index ed4db0e..c96183b 100644 --- a/LibOVR/Src/OVR_Linux_HIDDevice.cpp +++ b/LibOVR/Src/OVR_Linux_HIDDevice.cpp @@ -3,7 +3,7 @@ Filename : OVR_Linux_HIDDevice.cpp Content : Linux HID device implementation. Created : February 26, 2013 Authors : Lee Cooper - + Copyright : Copyright 2013 Oculus VR, Inc. All Rights reserved. Licensed under the Oculus VR SDK License Version 2.0 (the "License"); @@ -34,7 +34,7 @@ limitations under the License. namespace OVR { namespace Linux { static const UInt32 MAX_QUEUED_INPUT_REPORTS = 5; - + //------------------------------------------------------------------------------------- // **** Linux::DeviceManager //----------------------------------------------------------------------------- @@ -58,27 +58,34 @@ bool HIDDeviceManager::initializeManager() return true; } + OVR_DEBUG_LOG(("Attempting to initialize the HID Device Manager")); // Create a udev_monitor handle to watch for device changes (hot-plug detection) HIDMonitor = udev_monitor_new_from_netlink(UdevInstance, "udev"); if (HIDMonitor == NULL) { + LogError("Unable to create udev monitor"); return false; } - udev_monitor_filter_add_match_subsystem_devtype(HIDMonitor, "hidraw", NULL); // filter for hidraw only - - int err = udev_monitor_enable_receiving(HIDMonitor); + int err = udev_monitor_filter_add_match_subsystem_devtype(HIDMonitor, "hidraw", NULL); // filter for hidraw only + if (err) { + LogError("Unable to add hidraw filter %d", err); + } + + err = udev_monitor_enable_receiving(HIDMonitor); if (err) { + LogError("Unable to enable monitor receiving %d", err); udev_monitor_unref(HIDMonitor); HIDMonitor = NULL; return false; } - - // Get the file descriptor (fd) for the monitor. + + // Get the file descriptor (fd) for the monitor. HIDMonHandle = udev_monitor_get_fd(HIDMonitor); if (HIDMonHandle < 0) { + LogError("Unable to open monitor descriptor"); udev_monitor_unref(HIDMonitor); HIDMonitor = NULL; return false; @@ -88,6 +95,7 @@ bool HIDDeviceManager::initializeManager() // Add the handle to the polling list if (!DevManager->pThread->AddSelectFd(this, HIDMonHandle)) { + LogError("Failed to add udev monitor fd to select list"); close(HIDMonHandle); HIDMonHandle = -1; @@ -127,7 +135,7 @@ void HIDDeviceManager::Shutdown() } udev_unref(UdevInstance); // release the library - + LogText("OVR::Linux::HIDDeviceManager - shutting down.\n"); } @@ -213,39 +221,49 @@ bool HIDDeviceManager::getStringProperty(udev_device* device, //----------------------------------------------------------------------------- bool HIDDeviceManager::Enumerate(HIDEnumerateVisitor* enumVisitor) { - if (!initializeManager()) { return false; } - // Get a list of hid devices + OVR_DEBUG_LOG_TEXT(("Attempting to enumerate the HID devices to find the Oculus Rift\n")); + + // Get a list of hid devices udev_enumerate* devices = udev_enumerate_new(UdevInstance); - udev_enumerate_add_match_subsystem(devices, "hidraw"); - udev_enumerate_scan_devices(devices); + if (0 != udev_enumerate_add_match_subsystem(devices, "hidraw") || + 0 != udev_enumerate_scan_devices(devices)) { + LogError("Unable to enumerate/scan hidraw devices"); + return false; + } udev_list_entry* entry = udev_enumerate_get_list_entry(devices); - // Search each device for the matching vid/pid while (entry != NULL) { // Get the device file name const char* sysfs_path = udev_list_entry_get_name(entry); + + OVR_DEBUG_LOG(("Found udev path %s", sysfs_path)); udev_device* hid; // The device's HID udev node. hid = udev_device_new_from_syspath(UdevInstance, sysfs_path); const char* dev_path = udev_device_get_devnode(hid); + OVR_DEBUG_LOG(("Found udev device node %s", dev_path)); // Get the USB device + // FIXME possible descriptor leak... if this returns NULL, the old hid value is lost and never 'unrefed' hid = udev_device_get_parent_with_subsystem_devtype(hid, "usb", "usb_device"); if (hid) { + OVR_DEBUG_LOG(("Found parent USB device %s", udev_device_get_devnode(hid))); HIDDeviceDesc devDesc; // Check the VID/PID for a match + OVR_DEBUG_LOG(("Matching product/vendor ID %d:%d", devDesc.VendorId, devDesc.ProductId)); if (dev_path && initVendorProductVersion(hid, &devDesc) && enumVisitor->MatchVendorProduct(devDesc.VendorId, devDesc.ProductId)) { + OVR_DEBUG_LOG_TEXT(("Found Rift tracker at %s\n", dev_path)); devDesc.Path = dev_path; getFullDesc(hid, &devDesc); @@ -255,10 +273,13 @@ bool HIDDeviceManager::Enumerate(HIDEnumerateVisitor* enumVisitor) // will fail; therefore, we just set Enumerated to 'true' and continue. if (existingDevice && existingDevice->pDevice) { + OVR_DEBUG_LOG(("Rift device already opened in Device Manager")); existingDevice->Enumerated = true; } else - { // open the device temporarily for startup communication + { + OVR_DEBUG_LOG(("Opening Rift tracker device")); + // open the device temporarily for startup communication int device_handle = open(dev_path, O_RDWR); if (device_handle >= 0) { @@ -267,6 +288,8 @@ bool HIDDeviceManager::Enumerate(HIDEnumerateVisitor* enumVisitor) enumVisitor->Visit(device, devDesc); close(device_handle); // close the file handle + } else { + LogError("Error %d opening Rift device at %s", errno, dev_path); } } } @@ -289,7 +312,7 @@ OVR::HIDDevice* HIDDeviceManager::Open(const String& path) if (device->HIDInitialize(path)) { - device->AddRef(); + device->AddRef(); return device; } @@ -299,20 +322,20 @@ OVR::HIDDevice* HIDDeviceManager::Open(const String& path) //----------------------------------------------------------------------------- bool HIDDeviceManager::getFullDesc(udev_device* device, HIDDeviceDesc* desc) { - + if (!initVendorProductVersion(device, desc)) { return false; } - + if (!getStringProperty(device, "serial", &(desc->SerialNumber))) { return false; } - + getStringProperty(device, "manufacturer", &(desc->Manufacturer)); getStringProperty(device, "product", &(desc->Product)); - + return true; } @@ -435,7 +458,7 @@ HIDDevice::HIDDevice(HIDDeviceManager* manager) { DeviceHandle = -1; } - + //----------------------------------------------------------------------------- // This is a minimal constructor used during enumeration for us to pass // a HIDDevice to the visit function (so that it can query feature reports). @@ -462,7 +485,7 @@ bool HIDDevice::HIDInitialize(const String& path) LogText("OVR::Linux::HIDDevice - Failed to open HIDDevice: %s", hid_path); return false; } - + HIDManager->DevManager->pThread->AddTicksNotifier(this); HIDManager->AddNotificationDevice(this); @@ -471,7 +494,7 @@ bool HIDDevice::HIDInitialize(const String& path) DevDesc.Path.ToCStr(), DevDesc.Manufacturer.ToCStr(), DevDesc.Product.ToCStr(), DevDesc.SerialNumber.ToCStr()); - + return true; } @@ -501,7 +524,7 @@ bool HIDDevice::initInfo() OVR_ASSERT_LOG(false, ("Failed to get report descriptor.")); return false; } - + /* // Get report lengths. SInt32 bufferLength; @@ -516,21 +539,21 @@ bool HIDDevice::initInfo() getResult = HIDManager->getIntProperty(Device, CFSTR(kIOHIDMaxFeatureReportSizeKey), &bufferLength); OVR_ASSERT(getResult); FeatureReportBufferLength = (UInt16) bufferLength; - - + + if (ReadBufferSize < InputReportBufferLength) { OVR_ASSERT_LOG(false, ("Input report buffer length is bigger than read buffer.")); return false; } - + // Get device desc. if (!HIDManager->getFullDesc(Device, &DevDesc)) { OVR_ASSERT_LOG(false, ("Failed to get device desc while initializing device.")); return false; } - + return true; */ @@ -539,13 +562,13 @@ bool HIDDevice::initInfo() InputReportBufferLength = 62; OutputReportBufferLength = 0; FeatureReportBufferLength = 69; - + if (ReadBufferSize < InputReportBufferLength) { OVR_ASSERT_LOG(false, ("Input report buffer length is bigger than read buffer.")); return false; } - + return true; } @@ -586,22 +609,22 @@ bool HIDDevice::openDevice(const char* device_path) DeviceHandle = -1; return false; } - + return true; } - + //----------------------------------------------------------------------------- void HIDDevice::HIDShutdown() { HIDManager->DevManager->pThread->RemoveTicksNotifier(this); HIDManager->RemoveNotificationDevice(this); - + if (DeviceHandle >= 0) // Device may already have been closed if unplugged. { closeDevice(false); } - + LogText("OVR::Linux::HIDDevice - HIDShutdown '%s'\n", DevDesc.Path.ToCStr()); } @@ -609,13 +632,13 @@ void HIDDevice::HIDShutdown() void HIDDevice::closeDevice(bool wasUnplugged) { OVR_ASSERT(DeviceHandle >= 0); - + HIDManager->DevManager->pThread->RemoveSelectFd(this, DeviceHandle); close(DeviceHandle); // close the file handle DeviceHandle = -1; - + LogText("OVR::Linux::HIDDevice - HID Device Closed '%s'\n", DevDesc.Path.ToCStr()); } @@ -629,10 +652,10 @@ void HIDDevice::closeDeviceOnIOError() //----------------------------------------------------------------------------- bool HIDDevice::SetFeatureReport(UByte* data, UInt32 length) { - + if (DeviceHandle < 0) return false; - + UByte reportID = data[0]; if (reportID == 0) @@ -663,7 +686,7 @@ UInt64 HIDDevice::OnTicks(UInt64 ticksMks) { return Handler->OnTicks(ticksMks); } - + return DeviceManagerThread::Notifier::OnTicks(ticksMks); } @@ -706,7 +729,7 @@ bool HIDDevice::OnDeviceNotification(MessageType messageType, // A closed device has been re-added. Try to reopen. if (!openDevice(device_path)) { - LogError("OVR::Linux::HIDDevice - Failed to reopen a device '%s' that was re-added.\n", + LogError("OVR::Linux::HIDDevice - Failed to reopen a device '%s' that was re-added.\n", device_path); *error = true; return true; @@ -751,7 +774,7 @@ bool HIDDevice::OnDeviceNotification(MessageType messageType, //----------------------------------------------------------------------------- HIDDeviceManager* HIDDeviceManager::CreateInternal(Linux::DeviceManager* devManager) { - + if (!System::IsInitialized()) { // Use custom message, since Log is not yet installed. @@ -776,7 +799,7 @@ HIDDeviceManager* HIDDeviceManager::CreateInternal(Linux::DeviceManager* devMana return manager.GetPtr(); } - + } // namespace Linux //------------------------------------------------------------------------------------- @@ -786,7 +809,7 @@ HIDDeviceManager* HIDDeviceManager::CreateInternal(Linux::DeviceManager* devMana HIDDeviceManager* HIDDeviceManager::Create() { OVR_ASSERT_LOG(false, ("Standalone mode not implemented yet.")); - + if (!System::IsInitialized()) { // Use custom message, since Log is not yet installed. diff --git a/LibOVR/Src/OVR_Linux_HMDDevice.cpp b/LibOVR/Src/OVR_Linux_HMDDevice.cpp index 633e665..035647a 100644 --- a/LibOVR/Src/OVR_Linux_HMDDevice.cpp +++ b/LibOVR/Src/OVR_Linux_HMDDevice.cpp @@ -30,14 +30,16 @@ limitations under the License. #include "OVR_Profile.h" -#include <X11/Xlib.h> -#include <X11/extensions/Xinerama.h> +#include "edid.h" namespace OVR { namespace Linux { //------------------------------------------------------------------------------------- -HMDDeviceCreateDesc::HMDDeviceCreateDesc(DeviceFactory* factory, const String& displayDeviceName, long dispId) +HMDDeviceCreateDesc::HMDDeviceCreateDesc( + DeviceFactory* factory, + const String& displayDeviceName, + const String& deviceId) : DeviceCreateDesc(factory, Device_HMD), DisplayDeviceName(displayDeviceName), DesktopX(0), DesktopY(0), Contents(0), EyeToScreenDistance(0), @@ -77,15 +79,14 @@ HMDDeviceCreateDesc::MatchResult HMDDeviceCreateDesc::MatchDevice(const DeviceCr const HMDDeviceCreateDesc& s2 = (const HMDDeviceCreateDesc&) other; - if ((DeviceId == s2.DeviceId) && - (DisplayId == s2.DisplayId)) + if (DeviceId == s2.DeviceId) { // Non-null DeviceId may match while size is different if screen size was overwritten // by SensorDisplayInfo in prior iteration. if (!DeviceId.IsEmpty() || ((HScreenSize == s2.HScreenSize) && (VScreenSize == s2.VScreenSize)) ) - { + { *pcandidate = 0; return Match_Found; } @@ -107,10 +108,10 @@ HMDDeviceCreateDesc::MatchResult HMDDeviceCreateDesc::MatchDevice(const DeviceCr *pcandidate = 0; return Match_Found; } - + // SensorDisplayInfo may override resolution settings, so store as candidate. if (s2.DeviceId.IsEmpty()) - { + { *pcandidate = const_cast<DeviceCreateDesc*>((const DeviceCreateDesc*)this); return Match_Candidate; } @@ -120,22 +121,22 @@ HMDDeviceCreateDesc::MatchResult HMDDeviceCreateDesc::MatchDevice(const DeviceCr *pcandidate = const_cast<DeviceCreateDesc*>((const DeviceCreateDesc*)this); return Match_Candidate; } - + return Match_None; } -bool HMDDeviceCreateDesc::UpdateMatchedCandidate(const DeviceCreateDesc& other, +bool HMDDeviceCreateDesc::UpdateMatchedCandidate(const DeviceCreateDesc& other, bool* newDeviceFlag) { // This candidate was the the "best fit" to apply sensor DisplayInfo to. OVR_ASSERT(other.Type == Device_HMD); - + const HMDDeviceCreateDesc& s2 = (const HMDDeviceCreateDesc&) other; // Force screen size on resolution from SensorDisplayInfo. // We do this because USB detection is more reliable as compared to HDMI EDID, - // which may be corrupted by splitter reporting wrong monitor + // which may be corrupted by splitter reporting wrong monitor if (s2.DeviceId.IsEmpty()) { HScreenSize = s2.HScreenSize; @@ -148,14 +149,12 @@ bool HMDDeviceCreateDesc::UpdateMatchedCandidate(const DeviceCreateDesc& other, Contents |= Contents_Distortion; } DeviceId = s2.DeviceId; - DisplayId = s2.DisplayId; DisplayDeviceName = s2.DisplayDeviceName; if (newDeviceFlag) *newDeviceFlag = true; } else if (DeviceId.IsEmpty()) { DeviceId = s2.DeviceId; - DisplayId = s2.DisplayId; DisplayDeviceName = s2.DisplayDeviceName; // ScreenSize and Resolution are NOT assigned here, since they may have @@ -189,44 +188,49 @@ void HMDDeviceFactory::EnumerateDevices(EnumerateVisitor& visitor) // Rift models. bool foundHMD = false; - + RRCrtc crtcId = 0; Display* display = XOpenDisplay(NULL); - if (display && XineramaIsActive(display)) - { - int numberOfScreens; - XineramaScreenInfo* screens = XineramaQueryScreens(display, &numberOfScreens); - - for (int i = 0; i < numberOfScreens; i++) - { - XineramaScreenInfo screenInfo = screens[i]; - - if (screenInfo.width == 1280 && screenInfo.height == 800) - { - String deviceName = "OVR0001"; - - HMDDeviceCreateDesc hmdCreateDesc(this, deviceName, i); - hmdCreateDesc.SetScreenParameters(screenInfo.x_org, screenInfo.y_org, 1280, 800, 0.14976f, 0.0936f); - - OVR_DEBUG_LOG_TEXT(("DeviceManager - HMD Found %s - %d\n", - deviceName.ToCStr(), i)); - - // Notify caller about detected device. This will call EnumerateAddDevice - // if the this is the first time device was detected. - visitor.Visit(hmdCreateDesc); - foundHMD = true; - break; - } + XRRScreenResources *screen = XRRGetScreenResources(display, DefaultRootWindow(display)); + for (int iscres = screen->noutput - 1; iscres >= 0; --iscres) { + RROutput output = screen->outputs[iscres]; + MonitorInfo * mi = read_edid_data(display, output); + if (mi == NULL) { + continue; } - XFree(screens); - } - + XRROutputInfo * info = XRRGetOutputInfo (display, screen, output); + if (0 == memcmp(mi->manufacturer_code, "OVR", 3)) { + int x = -1, y = -1, w = -1, h = -1; + if (info->connection == RR_Connected && info->crtc) { + XRRCrtcInfo * crtc_info = XRRGetCrtcInfo (display, screen, info->crtc); + x = crtc_info->x; + y = crtc_info->y; + w = crtc_info->width; + h = crtc_info->height; + XRRFreeCrtcInfo(crtc_info); + } + char buffer[512]; + sprintf(buffer, "%s%04d", mi->manufacturer_code, mi->product_code); + HMDDeviceCreateDesc hmdCreateDesc(this, info->name, buffer); + hmdCreateDesc.SetScreenParameters(x, y, w, h, 0.14976f, 0.0936f); + // Notify caller about detected device. This will call EnumerateAddDevice + // if the this is the first time device was detected. + visitor.Visit(hmdCreateDesc); + foundHMD = true; + break; + } // if + + OVR_DEBUG_LOG_TEXT(("DeviceManager - HMD Found %s - %d\n", + mi->dsc_product_name, screen->outputs[iscres])); + XRRFreeOutputInfo (info); + delete mi; + } // for + XRRFreeScreenResources(screen); // Real HMD device is not found; however, we still may have a 'fake' HMD // device created via SensorDeviceImpl::EnumerateHMDFromSensorDisplayInfo. // Need to find it and set 'Enumerated' to true to avoid Removal notification. - if (!foundHMD) - { + if (!foundHMD) { Ptr<DeviceCreateDesc> hmdDevDesc = getManager()->FindDevice("", Device_HMD); if (hmdDevDesc) hmdDevDesc->Enumerated = true; @@ -251,8 +255,8 @@ Profile* HMDDeviceCreateDesc::GetProfileAddRef() const const char * profileName = pDevice ? ((HMDDevice*)pDevice)->GetProfileName() : profileManager->GetDefaultProfileName(profileType); - - return profileName ? + + return profileName ? profileManager->LoadProfile(profileType, profileName) : profileManager->GetDeviceDefaultProfile(profileType); } @@ -303,7 +307,7 @@ bool HMDDeviceCreateDesc::GetDeviceInfo(DeviceInfo* info) const hmdInfo->EyeToScreenDistance = EyeToScreenDistance; } else - { + { if (is7Inch) { // 7" screen. @@ -332,7 +336,6 @@ bool HMDDeviceCreateDesc::GetDeviceInfo(DeviceInfo* info) const OVR_strcpy(hmdInfo->DisplayDeviceName, sizeof(hmdInfo->DisplayDeviceName), DisplayDeviceName.ToCStr()); - hmdInfo->DisplayId = DisplayId; } return true; @@ -354,7 +357,7 @@ bool HMDDevice::Initialize(DeviceBase* parent) pParent = parent; // Initialize user profile to default for device. - ProfileManager* profileManager = GetManager()->GetProfileManager(); + ProfileManager* profileManager = GetManager()->GetProfileManager(); ProfileName = profileManager->GetDefaultProfileName(getDesc()->GetProfileType()); return true; @@ -367,7 +370,7 @@ void HMDDevice::Shutdown() } Profile* HMDDevice::GetProfile() const -{ +{ if (!pCachedProfile) pCachedProfile = *getDesc()->GetProfileAddRef(); return pCachedProfile.GetPtr(); diff --git a/LibOVR/Src/OVR_Linux_HMDDevice.h b/LibOVR/Src/OVR_Linux_HMDDevice.h index b5c4bf1..406c857 100644 --- a/LibOVR/Src/OVR_Linux_HMDDevice.h +++ b/LibOVR/Src/OVR_Linux_HMDDevice.h @@ -70,12 +70,14 @@ protected: unsigned Contents; unsigned HResolution, VResolution; float HScreenSize, VScreenSize; - long DisplayId; float DistortionK[4]; float EyeToScreenDistance; public: - HMDDeviceCreateDesc(DeviceFactory* factory, const String& displayDeviceName, long dispId); + HMDDeviceCreateDesc( + DeviceFactory* factory, + const String& displayDeviceName, + const String& displayDeviceId); HMDDeviceCreateDesc(const HMDDeviceCreateDesc& other); virtual DeviceCreateDesc* Clone() const @@ -96,7 +98,7 @@ public: virtual bool GetDeviceInfo(DeviceInfo* info) const; // Requests the currently used default profile. This profile affects the - // settings reported by HMDInfo. + // settings reported by HMDInfo. Profile* GetProfileAddRef() const; ProfileType GetProfileType() const @@ -134,26 +136,26 @@ public: // HMDDevice represents an Oculus HMD device unit. An instance of this class // is typically created from the DeviceManager. -// After HMD device is created, we its sensor data can be obtained by +// After HMD device is created, we its sensor data can be obtained by // first creating a Sensor object and then wrappig it in SensorFusion. class HMDDevice : public DeviceImpl<OVR::HMDDevice> { public: HMDDevice(HMDDeviceCreateDesc* createDesc); - ~HMDDevice(); + ~HMDDevice(); virtual bool Initialize(DeviceBase* parent); virtual void Shutdown(); // Requests the currently used default profile. This profile affects the - // settings reported by HMDInfo. + // settings reported by HMDInfo. virtual Profile* GetProfile() const; virtual const char* GetProfileName() const; virtual bool SetProfileName(const char* name); // Query associated sensor. - virtual OVR::SensorDevice* GetSensor(); + virtual OVR::SensorDevice* GetSensor(); protected: HMDDeviceCreateDesc* getDesc() const { return (HMDDeviceCreateDesc*)pCreateDesc.GetPtr(); } diff --git a/LibOVR/Src/OVR_OSX_HIDDevice.cpp b/LibOVR/Src/OVR_OSX_HIDDevice.cpp index 38b1b3e..650182c 100644 --- a/LibOVR/Src/OVR_OSX_HIDDevice.cpp +++ b/LibOVR/Src/OVR_OSX_HIDDevice.cpp @@ -3,7 +3,7 @@ Filename : OVR_OSX_HIDDevice.cpp Content : OSX HID device implementation. Created : February 26, 2013 Authors : Lee Cooper - + Copyright : Copyright 2013 Oculus VR, Inc. All Rights reserved. Licensed under the Oculus VR SDK License Version 2.0 (the "License"); @@ -30,7 +30,7 @@ limitations under the License. namespace OVR { namespace OSX { static const UInt32 MAX_QUEUED_INPUT_REPORTS = 5; - + //------------------------------------------------------------------------------------- // **** OSX::DeviceManager @@ -60,21 +60,21 @@ bool HIDDeviceManager::initializeManager() { return true; } - + HIDManager = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone); - + if (!HIDManager) { return false; } - + // Create a Matching Dictionary CFMutableDictionaryRef matchDict = CFDictionaryCreateMutable(kCFAllocatorDefault, 2, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - + // Specify a device manufacturer in the Matching Dictionary UInt32 vendorId = Oculus_VendorId; CFNumberRef vendorIdRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &vendorId); @@ -85,15 +85,15 @@ bool HIDDeviceManager::initializeManager() IOHIDManagerSetDeviceMatching(HIDManager, matchDict); CFRelease(vendorIdRef); CFRelease(matchDict); - + // Register a callback for USB device detection with the HID Manager IOHIDManagerRegisterDeviceMatchingCallback(HIDManager, &staticDeviceMatchingCallback, this); - + IOHIDManagerScheduleWithRunLoop(HIDManager, getRunLoop(), kCFRunLoopDefaultMode); return true; } - + bool HIDDeviceManager::Initialize() { return initializeManager(); @@ -103,38 +103,38 @@ void HIDDeviceManager::Shutdown() { OVR_ASSERT_LOG(HIDManager, ("Should have called 'Initialize' before 'Shutdown'.")); CFRelease(HIDManager); - + LogText("OVR::OSX::HIDDeviceManager - shutting down.\n"); } - + bool HIDDeviceManager::getIntProperty(IOHIDDeviceRef device, CFStringRef propertyName, SInt32* pResult) { - + CFTypeRef ref = IOHIDDeviceGetProperty(device, propertyName); if (!ref) { return false; } - + if (CFGetTypeID(ref) != CFNumberGetTypeID()) { return false; } - + CFNumberGetValue((CFNumberRef) ref, kCFNumberSInt32Type, pResult); return true; } - + bool HIDDeviceManager::initVendorProductVersion(IOHIDDeviceRef device, HIDDeviceDesc* pDevDesc) { - + if (!getVendorId(device, &(pDevDesc->VendorId))) { return false; } - + if (!getProductId(device, &(pDevDesc->ProductId))) { return false; @@ -146,30 +146,30 @@ bool HIDDeviceManager::initVendorProductVersion(IOHIDDeviceRef device, HIDDevice return false; } pDevDesc->VersionNumber = result; - + return true; } bool HIDDeviceManager::initUsage(IOHIDDeviceRef device, HIDDeviceDesc* pDevDesc) { - + SInt32 result; - + if (!getIntProperty(device, CFSTR(kIOHIDPrimaryUsagePageKey), &result)) { return false; } - + pDevDesc->UsagePage = result; - + if (!getIntProperty(device, CFSTR(kIOHIDPrimaryUsageKey), &result)) { return false; } - + pDevDesc->Usage = result; - + return true; } @@ -177,14 +177,14 @@ bool HIDDeviceManager::initSerialNumber(IOHIDDeviceRef device, HIDDeviceDesc* pD { return getSerialNumberString(device, &(pDevDesc->SerialNumber)); } - + bool HIDDeviceManager::initStrings(IOHIDDeviceRef device, HIDDeviceDesc* pDevDesc) { // Regardless of whether they fail we'll try and get the remaining. getStringProperty(device, CFSTR(kIOHIDManufacturerKey), &(pDevDesc->Manufacturer)); getStringProperty(device, CFSTR(kIOHIDProductKey), &(pDevDesc->Product)); - + return true; } @@ -192,9 +192,9 @@ bool HIDDeviceManager::getStringProperty(IOHIDDeviceRef device, CFStringRef propertyName, String* pResult) { - + CFStringRef str = (CFStringRef) IOHIDDeviceGetProperty(device, propertyName); - + if (!str) { return false; @@ -202,7 +202,7 @@ bool HIDDeviceManager::getStringProperty(IOHIDDeviceRef device, CFIndex length = CFStringGetLength(str); CFRange range = CFRangeMake(0, length); - + // Test the conversion first to get required buffer size. CFIndex bufferLength; CFIndex numberOfChars = CFStringGetBytes(str, @@ -213,15 +213,15 @@ bool HIDDeviceManager::getStringProperty(IOHIDDeviceRef device, NULL, 0, &bufferLength); - + if (numberOfChars == 0) { return false; } - + // Now allocate buffer. char* buffer = new char[bufferLength+1]; - + numberOfChars = CFStringGetBytes(str, range, kCFStringEncodingUTF8, @@ -234,55 +234,55 @@ bool HIDDeviceManager::getStringProperty(IOHIDDeviceRef device, buffer[bufferLength] = '\0'; *pResult = String(buffer); - + return true; } - + bool HIDDeviceManager::getVendorId(IOHIDDeviceRef device, UInt16* pResult) { SInt32 result; - + if (!getIntProperty(device, CFSTR(kIOHIDVendorIDKey), &result)) { return false; } - + *pResult = result; return true; } - + bool HIDDeviceManager::getProductId(IOHIDDeviceRef device, UInt16* pResult) { SInt32 result; - + if (!getIntProperty(device, CFSTR(kIOHIDProductIDKey), &result)) { return false; } - + *pResult = result; - + return true; } - + bool HIDDeviceManager::getLocationId(IOHIDDeviceRef device, SInt32* pResult) { SInt32 result; - + if (!getIntProperty(device, CFSTR(kIOHIDLocationIDKey), &result)) { return false; } - + *pResult = result; - + return true; } - + bool HIDDeviceManager::getSerialNumberString(IOHIDDeviceRef device, String* pResult) { - + if (!getStringProperty(device, CFSTR(kIOHIDSerialNumberKey), pResult)) { return false; @@ -290,7 +290,7 @@ bool HIDDeviceManager::getSerialNumberString(IOHIDDeviceRef device, String* pRes return true; } - + bool HIDDeviceManager::getPath(IOHIDDeviceRef device, String* pPath) { @@ -299,7 +299,7 @@ bool HIDDeviceManager::getPath(IOHIDDeviceRef device, String* pPath) { return false; } - + UInt16 vendorId; if (!getVendorId(device, &vendorId)) { @@ -311,13 +311,13 @@ bool HIDDeviceManager::getPath(IOHIDDeviceRef device, String* pPath) { return false; } - + String serialNumber; if (!getSerialNumberString(device, &serialNumber)) { return false; } - + StringBuffer buffer; buffer.AppendFormat("%s:vid=%04hx:pid=%04hx:ser=%s", @@ -325,9 +325,9 @@ bool HIDDeviceManager::getPath(IOHIDDeviceRef device, String* pPath) vendorId, productId, serialNumber.ToCStr()); - + *pPath = String(buffer); - + return true; } @@ -337,31 +337,31 @@ bool HIDDeviceManager::Enumerate(HIDEnumerateVisitor* enumVisitor) { return false; } - + CFSetRef deviceSet = IOHIDManagerCopyDevices(HIDManager); if (!deviceSet) return false; - + CFIndex deviceCount = CFSetGetCount(deviceSet); - + // Allocate a block of memory and read the set into it. IOHIDDeviceRef* devices = (IOHIDDeviceRef*) OVR_ALLOC(sizeof(IOHIDDeviceRef) * deviceCount); CFSetGetValues(deviceSet, (const void **) devices); - + // Iterate over devices. for (CFIndex deviceIndex = 0; deviceIndex < deviceCount; deviceIndex++) { IOHIDDeviceRef hidDev = devices[deviceIndex]; - + if (!hidDev) { continue; } - + HIDDeviceDesc devDesc; - + if (getPath(hidDev, &(devDesc.Path)) && initVendorProductVersion(hidDev, &devDesc) && enumVisitor->MatchVendorProduct(devDesc.VendorId, devDesc.ProductId) && @@ -392,10 +392,10 @@ bool HIDDeviceManager::Enumerate(HIDEnumerateVisitor* enumVisitor) } } } - + OVR_FREE(devices); CFRelease(deviceSet); - + return true; } @@ -410,30 +410,30 @@ OVR::HIDDevice* HIDDeviceManager::Open(const String& path) } device->AddRef(); - + return device; } - + bool HIDDeviceManager::getFullDesc(IOHIDDeviceRef device, HIDDeviceDesc* desc) { - + if (!initVendorProductVersion(device, desc)) { return false; } - + if (!initUsage(device, desc)) { return false; } - + if (!initSerialNumber(device, desc)) { return false; } - + initStrings(device, desc); - + return true; } @@ -447,7 +447,7 @@ void HIDDeviceManager::staticDeviceMatchingCallback(void *inContext, HIDDeviceDesc hidDevDesc; hidMgr->getPath(inIOHIDDeviceRef, &hidDevDesc.Path); hidMgr->getFullDesc(inIOHIDDeviceRef, &hidDevDesc); - + hidMgr->DevManager->DetectHIDDevice(hidDevDesc); } @@ -460,7 +460,7 @@ HIDDevice::HIDDevice(HIDDeviceManager* manager) Device = NULL; RepluggedNotificationPort = 0; } - + // This is a minimal constructor used during enumeration for us to pass // a HIDDevice to the visit function (so that it can query feature reports). HIDDevice::HIDDevice(HIDDeviceManager* manager, IOHIDDeviceRef device) @@ -495,16 +495,16 @@ bool HIDDevice::HIDInitialize(const String& path) closeDevice(false); return false; } - + HIDManager->DevManager->pThread->AddTicksNotifier(this); - + LogText("OVR::OSX::HIDDevice - Opened '%s'\n" " Manufacturer:'%s' Product:'%s' Serial#:'%s'\n", DevDesc.Path.ToCStr(), DevDesc.Manufacturer.ToCStr(), DevDesc.Product.ToCStr(), DevDesc.SerialNumber.ToCStr()); - + return true; } @@ -512,8 +512,8 @@ bool HIDDevice::initInfo() { // Device must have been successfully opened. OVR_ASSERT(Device); - - + + // Get report lengths. SInt32 bufferLength; bool getResult = HIDManager->getIntProperty(Device, CFSTR(kIOHIDMaxInputReportSizeKey), &bufferLength); @@ -527,21 +527,21 @@ bool HIDDevice::initInfo() getResult = HIDManager->getIntProperty(Device, CFSTR(kIOHIDMaxFeatureReportSizeKey), &bufferLength); OVR_ASSERT(getResult); FeatureReportBufferLength = (UInt16) bufferLength; - - + + if (ReadBufferSize < InputReportBufferLength) { OVR_ASSERT_LOG(false, ("Input report buffer length is bigger than read buffer.")); return false; } - + // Get device desc. if (!HIDManager->getFullDesc(Device, &DevDesc)) { OVR_ASSERT_LOG(false, ("Failed to get device desc while initializing device.")); return false; } - + return true; } @@ -572,53 +572,53 @@ void HIDDevice::deviceAddedCallback(io_iterator_t iterator) while (IOIteratorNext(iterator)) ; } - + bool HIDDevice::openDevice() { - + // Have to iterate through devices again to generate paths. CFSetRef deviceSet = IOHIDManagerCopyDevices(HIDManager->HIDManager); CFIndex deviceCount = CFSetGetCount(deviceSet); - + // Allocate a block of memory and read the set into it. IOHIDDeviceRef* devices = (IOHIDDeviceRef*) OVR_ALLOC(sizeof(IOHIDDeviceRef) * deviceCount); CFSetGetValues(deviceSet, (const void **) devices); - - + + // Iterate over devices. IOHIDDeviceRef device = NULL; for (CFIndex deviceIndex = 0; deviceIndex < deviceCount; deviceIndex++) { IOHIDDeviceRef tmpDevice = devices[deviceIndex]; - + if (!tmpDevice) { continue; } - + String path; if (!HIDManager->getPath(tmpDevice, &path)) { continue; } - + if (path == DevDesc.Path) { device = tmpDevice; break; } } - - + + OVR_FREE(devices); - + if (!device) { CFRelease(deviceSet); return false; } - + // Attempt to open device. if (IOHIDDeviceOpen(device, kIOHIDOptionsTypeSeizeDevice) != kIOReturnSuccess) @@ -630,11 +630,11 @@ bool HIDDevice::openDevice() // Retain the device before we release the set. CFRetain(device); CFRelease(deviceSet); - - + + Device = device; - + if (!initInfo()) { IOHIDDeviceClose(Device, kIOHIDOptionsTypeSeizeDevice); @@ -642,13 +642,13 @@ bool HIDDevice::openDevice() Device = NULL; return false; } - - + + // Setup the Run Loop and callbacks. IOHIDDeviceScheduleWithRunLoop(Device, HIDManager->getRunLoop(), kCFRunLoopDefaultMode); - + IOHIDDeviceRegisterInputReportCallback(Device, ReadBuffer, ReadBufferSize, @@ -658,15 +658,15 @@ bool HIDDevice::openDevice() IOHIDDeviceRegisterRemovalCallback(Device, staticDeviceRemovedCallback, this); - + return true; } - + void HIDDevice::HIDShutdown() { HIDManager->DevManager->pThread->RemoveTicksNotifier(this); - + if (Device != NULL) // Device may already have been closed if unplugged. { closeDevice(false); @@ -675,25 +675,25 @@ void HIDDevice::HIDShutdown() IOObjectRelease(RepluggedNotification); if (RepluggedNotificationPort) IONotificationPortDestroy(RepluggedNotificationPort); - + LogText("OVR::OSX::HIDDevice - HIDShutdown '%s'\n", DevDesc.Path.ToCStr()); } bool HIDDevice::setupDevicePluggedInNotification() { - + // Setup notification when devices are plugged in. RepluggedNotificationPort = IONotificationPortCreate(kIOMasterPortDefault); - + CFRunLoopSourceRef notificationRunLoopSource = IONotificationPortGetRunLoopSource(RepluggedNotificationPort); - + CFRunLoopAddSource(HIDManager->getRunLoop(), notificationRunLoopSource, kCFRunLoopDefaultMode); - + CFMutableDictionaryRef matchingDict = IOServiceMatching(kIOUSBDeviceClassName); - + // Have to specify vendorId and productId. Doesn't seem to accept additional // things like serial number. SInt32 vendorId = DevDesc.VendorId; @@ -702,14 +702,14 @@ bool HIDDevice::setupDevicePluggedInNotification() &vendorId); CFDictionarySetValue(matchingDict, CFSTR(kUSBVendorID), numberRef); CFRelease(numberRef); - + SInt32 deviceProductId = DevDesc.ProductId; numberRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &deviceProductId); CFDictionarySetValue(matchingDict, CFSTR(kUSBProductID), numberRef); CFRelease(numberRef); - + kern_return_t result = IOServiceAddMatchingNotification(RepluggedNotificationPort, kIOMatchedNotification, @@ -717,26 +717,26 @@ bool HIDDevice::setupDevicePluggedInNotification() staticDeviceAddedCallback, this, &RepluggedNotification); - + if (result != KERN_SUCCESS) { CFRelease(RepluggedNotificationPort); RepluggedNotificationPort = 0; return false; } - + // Iterate through to arm. while (IOIteratorNext(RepluggedNotification)) { } - + return true; } void HIDDevice::closeDevice(bool wasUnplugged) { OVR_ASSERT(Device != NULL); - + if (!wasUnplugged) { // Clear the registered callbacks. @@ -745,18 +745,18 @@ void HIDDevice::closeDevice(bool wasUnplugged) InputReportBufferLength, NULL, this); - + IOHIDDeviceRegisterRemovalCallback(Device, NULL, this); - + IOHIDDeviceUnscheduleFromRunLoop(Device, HIDManager->getRunLoop(), kCFRunLoopDefaultMode); IOHIDDeviceClose(Device, kIOHIDOptionsTypeNone); } - + CFRelease(Device); Device = NULL; - + LogText("OVR::OSX::HIDDevice - HID Device Closed '%s'\n", DevDesc.Path.ToCStr()); } @@ -772,22 +772,22 @@ void HIDDevice::staticHIDReportCallback(void* pContext, return pDevice->hidReportCallback(pReport, (UInt32)reportLength); } -void HIDDevice::hidReportCallback(UByte* pData, UInt32 length) +void HIDDevice::hidReportCallback(const UByte* pData, UInt32 length) { - + // We got data. if (Handler) { Handler->OnInputReport(pData, length); } } - + void HIDDevice::staticDeviceRemovedCallback(void* pContext, IOReturn result, void* pSender) { HIDDevice* pDevice = (HIDDevice*) pContext; pDevice->deviceRemovedCallback(); } - + void HIDDevice::deviceRemovedCallback() { Ptr<HIDDevice> _this(this); // prevent from release @@ -805,16 +805,16 @@ CFStringRef HIDDevice::generateRunLoopModeString(IOHIDDeviceRef device) const UInt32 safeBuffSize = 256; char nameBuff[safeBuffSize]; OVR_sprintf(nameBuff, safeBuffSize, "%016lX", device); - + return CFStringCreateWithCString(NULL, nameBuff, kCFStringEncodingASCII); } - + bool HIDDevice::SetFeatureReport(UByte* data, UInt32 length) { - + if (!Device) return false; - + UByte reportID = data[0]; if (reportID == 0) @@ -823,13 +823,13 @@ bool HIDDevice::SetFeatureReport(UByte* data, UInt32 length) data++; length--; } - + IOReturn result = IOHIDDeviceSetReport( Device, kIOHIDReportTypeFeature, reportID, data, length); - + return (result == kIOReturnSuccess); } @@ -837,29 +837,29 @@ bool HIDDevice::GetFeatureReport(UByte* data, UInt32 length) { if (!Device) return false; - + CFIndex bufferLength = length; - + // Report id is in first byte of the buffer. IOReturn result = IOHIDDeviceGetReport(Device, kIOHIDReportTypeFeature, data[0], data, &bufferLength); - + return (result == kIOReturnSuccess); } - + UInt64 HIDDevice::OnTicks(UInt64 ticksMks) { - + if (Handler) { return Handler->OnTicks(ticksMks); } - + return DeviceManagerThread::Notifier::OnTicks(ticksMks); } HIDDeviceManager* HIDDeviceManager::CreateInternal(OSX::DeviceManager* devManager) { - + if (!System::IsInitialized()) { // Use custom message, since Log is not yet installed. @@ -884,7 +884,7 @@ HIDDeviceManager* HIDDeviceManager::CreateInternal(OSX::DeviceManager* devManage return manager.GetPtr(); } - + } // namespace OSX //------------------------------------------------------------------------------------- @@ -894,7 +894,7 @@ HIDDeviceManager* HIDDeviceManager::CreateInternal(OSX::DeviceManager* devManage HIDDeviceManager* HIDDeviceManager::Create() { OVR_ASSERT_LOG(false, ("Standalone mode not implemented yet.")); - + if (!System::IsInitialized()) { // Use custom message, since Log is not yet installed. @@ -904,7 +904,7 @@ HIDDeviceManager* HIDDeviceManager::Create() } Ptr<OSX::HIDDeviceManager> manager = *new OSX::HIDDeviceManager(NULL); - + if (manager) { if (manager->Initialize()) diff --git a/LibOVR/Src/OVR_OSX_HIDDevice.h b/LibOVR/Src/OVR_OSX_HIDDevice.h index e2fac31..d8476e2 100644 --- a/LibOVR/Src/OVR_OSX_HIDDevice.h +++ b/LibOVR/Src/OVR_OSX_HIDDevice.h @@ -82,7 +82,7 @@ private: uint32_t reportId, uint8_t* pReport, CFIndex reportLength); - void hidReportCallback(UByte* pData, UInt32 length); + void hidReportCallback(const UByte* pData, UInt32 length); static void staticDeviceRemovedCallback(void* pContext, IOReturn result, diff --git a/LibOVR/Src/OVR_OSX_HMDDevice.h b/LibOVR/Src/OVR_OSX_HMDDevice.h index d92aa1f..dbb7d87 100644 --- a/LibOVR/Src/OVR_OSX_HMDDevice.h +++ b/LibOVR/Src/OVR_OSX_HMDDevice.h @@ -28,7 +28,7 @@ limitations under the License. #define OVR_OSX_HMDDevice_h #include "OVR_DeviceImpl.h" -#include <Kernel/OVR_String.h> +#include "Kernel/OVR_String.h" #include "OVR_Profile.h" namespace OVR { namespace OSX { diff --git a/LibOVR/Src/OVR_SensorImpl.cpp b/LibOVR/Src/OVR_SensorImpl.cpp index 1646ee3..f2c9c61 100644 --- a/LibOVR/Src/OVR_SensorImpl.cpp +++ b/LibOVR/Src/OVR_SensorImpl.cpp @@ -30,12 +30,14 @@ limitations under the License. #include "Kernel/OVR_Timer.h" +#include <iostream> + namespace OVR { - + //------------------------------------------------------------------------------------- // ***** Oculus Sensor-specific packet data structures -enum { +enum { Sensor_VendorId = Oculus_VendorId, Sensor_ProductId = 0x0001, @@ -61,8 +63,8 @@ static SInt16 DecodeSInt16(const UByte* buffer) } static UInt32 DecodeUInt32(const UByte* buffer) -{ - return (buffer[0]) | UInt32(buffer[1] << 8) | UInt32(buffer[2] << 16) | UInt32(buffer[3] << 24); +{ + return (buffer[0]) | UInt32(buffer[1] << 8) | UInt32(buffer[2] << 16) | UInt32(buffer[3] << 24); } static float DecodeFloat(const UByte* buffer) @@ -125,9 +127,9 @@ struct TrackerSensors Timestamp = DecodeUInt16(buffer + 2); LastCommandID = DecodeUInt16(buffer + 4); Temperature = DecodeSInt16(buffer + 6); - - //if (SampleCount > 2) - // OVR_DEBUG_LOG_TEXT(("TackerSensor::Decode SampleCount=%d\n", SampleCount)); + + //if (SampleCount > 2) + // OVR_DEBUG_LOG_TEXT(("TackerSensor::Decode SampleCount=%d\n", SampleCount)); // Only unpack as many samples as there actually are UByte iterationCount = (SampleCount > 2) ? 3 : SampleCount; @@ -152,7 +154,7 @@ struct TrackerMessage TrackerSensors Sensors; }; -bool DecodeTrackerMessage(TrackerMessage* message, UByte* buffer, int size) +bool DecodeTrackerMessage(TrackerMessage* message, const UByte* buffer, int size) { memset(message, 0, sizeof(TrackerMessage)); @@ -187,7 +189,7 @@ static const UInt16 MagRangeRamp[] = { 880, 1300, 1900, 2500 }; static UInt16 SelectSensorRampValue(const UInt16* ramp, unsigned count, float val, float factor, const char* label) -{ +{ UInt16 threshold = (UInt16)(val * factor); for (unsigned i = 0; i<count; i++) @@ -208,7 +210,7 @@ struct SensorRangeImpl { enum { PacketSize = 8 }; UByte Buffer[PacketSize]; - + UInt16 CommandId; UInt16 AccelScale; UInt16 GyroScale; @@ -320,7 +322,7 @@ struct SensorConfigImpl PacketInterval = Buffer[4]; KeepAliveIntervalMs= Buffer[5] | (UInt16(Buffer[6]) << 8); } - + }; @@ -401,7 +403,7 @@ void SensorDeviceFactory::EnumerateDevices(EnumerateVisitor& visitor) void operator = (const SensorEnumerator&) { } DeviceFactory* pFactory; - EnumerateVisitor& ExternalVisitor; + EnumerateVisitor& ExternalVisitor; public: SensorEnumerator(DeviceFactory* factory, EnumerateVisitor& externalVisitor) : pFactory(factory), ExternalVisitor(externalVisitor) { } @@ -429,7 +431,7 @@ void SensorDeviceFactory::EnumerateDevices(EnumerateVisitor& visitor) // Check if the sensor returns DisplayInfo. If so, try to use it to override potentially // mismatching monitor information (in case wrong EDID is reported by splitter), // or to create a new "virtualized" HMD Device. - + SensorDisplayInfoImpl displayInfo; if (device.GetFeatureReport(displayInfo.Buffer, SensorDisplayInfoImpl::PacketSize)) @@ -451,7 +453,7 @@ void SensorDeviceFactory::EnumerateDevices(EnumerateVisitor& visitor) SensorEnumerator sensorEnumerator(this, visitor); GetManagerImpl()->GetHIDDeviceManager()->Enumerate(&sensorEnumerator); - //double totalSeconds = Timer::GetProfileSeconds() - start; + //double totalSeconds = Timer::GetProfileSeconds() - start; } bool SensorDeviceFactory::MatchVendorProduct(UInt16 vendorId, UInt16 productId) const @@ -533,7 +535,7 @@ SensorDeviceImpl::SensorDeviceImpl(SensorDeviceCreateDesc* createDesc) SensorDeviceImpl::~SensorDeviceImpl() { // Check that Shutdown() was called. - OVR_ASSERT(!pCreateDesc->pDevice); + OVR_ASSERT(!pCreateDesc->pDevice); } // Internal creation APIs. @@ -592,14 +594,14 @@ void SensorDeviceImpl::closeDeviceOnError() } void SensorDeviceImpl::Shutdown() -{ +{ HIDDeviceImpl<OVR::SensorDevice>::Shutdown(); LogText("OVR::SensorDevice - Closed '%s'\n", getHIDDesc()->Path.ToCStr()); } -void SensorDeviceImpl::OnInputReport(UByte* pData, UInt32 length) +void SensorDeviceImpl::OnInputReport(const UByte* pData, UInt32 length) { bool processed = false; @@ -617,7 +619,6 @@ void SensorDeviceImpl::OnInputReport(UByte* pData, UInt32 length) UInt64 SensorDeviceImpl::OnTicks(UInt64 ticksMks) { - if (ticksMks >= NextKeepAliveTicks) { // Use 3-seconds keep alive by default. @@ -643,10 +644,10 @@ bool SensorDeviceImpl::SetRange(const SensorRange& range, bool waitFlag) { return threadQueue->PushCall(this, &SensorDeviceImpl::setRange, range); } - - if (!threadQueue->PushCallAndWaitResult(this, + + if (!threadQueue->PushCallAndWaitResult(this, &SensorDeviceImpl::setRange, - &result, + &result, range)) { return false; @@ -664,19 +665,19 @@ void SensorDeviceImpl::GetRange(SensorRange* range) const bool SensorDeviceImpl::setRange(const SensorRange& range) { SensorRangeImpl sr(range); - + if (GetInternalDevice()->SetFeatureReport(sr.Buffer, SensorRangeImpl::PacketSize)) { Lock::Locker lockScope(GetLock()); sr.GetSensorRange(&CurrentRange); return true; } - + return false; } void SensorDeviceImpl::SetCoordinateFrame(CoordinateFrame coordframe) -{ +{ // Push call with wait. GetManagerImpl()->GetThreadQueue()-> PushCall(this, &SensorDeviceImpl::setCoordinateFrame, coordframe, true); @@ -703,7 +704,7 @@ Void SensorDeviceImpl::setCoordinateFrame(CoordinateFrame coordframe) scfg.Pack(); GetInternalDevice()->SetFeatureReport(scfg.Buffer, SensorConfigImpl::PacketSize); - + // Re-read the state, in case of older firmware that doesn't support Sensor coordinates. if (GetInternalDevice()->GetFeatureReport(scfg.Buffer, SensorConfigImpl::PacketSize)) { @@ -718,7 +719,7 @@ Void SensorDeviceImpl::setCoordinateFrame(CoordinateFrame coordframe) } void SensorDeviceImpl::SetReportRate(unsigned rateHz) -{ +{ // Push call with wait. GetManagerImpl()->GetThreadQueue()-> PushCall(this, &SensorDeviceImpl::setReportRate, rateHz, true); @@ -766,9 +767,9 @@ void SensorDeviceImpl::SetMessageHandler(MessageHandler* handler) DeviceBase::SetMessageHandler(handler); } else - { + { DeviceBase::SetMessageHandler(handler); - } + } } // Sensor reports data in the following coordinate system: @@ -794,15 +795,15 @@ Vector3f AccelFromBodyFrameUpdate(const TrackerSensors& update, UByte sampleNumb Vector3f MagFromBodyFrameUpdate(const TrackerSensors& update, bool convertHMDToSensor = false) -{ - // Note: Y and Z are swapped in comparison to the Accel. +{ + // Note: Y and Z are swapped in comparison to the Accel. // This accounts for DK1 sensor firmware axis swap, which should be undone in future releases. if (!convertHMDToSensor) { return Vector3f( (float)update.MagX, (float)update.MagZ, (float)update.MagY) * 0.0001f; - } + } return Vector3f( (float)update.MagX, (float)update.MagY, @@ -826,10 +827,10 @@ void SensorDeviceImpl::onTrackerMessage(TrackerMessage* message) { if (message->Type != TrackerMessage_Sensors) return; - + const float timeUnit = (1.0f / 1000.f); TrackerSensors& s = message->Sensors; - + // Call OnMessage() within a lock to avoid conflicts with handlers. Lock::Locker scopeLock(HandlerRef.GetLock()); @@ -876,7 +877,7 @@ void SensorDeviceImpl::onTrackerMessage(TrackerMessage* message) if (HandlerRef.GetHandler()) { - MessageBodyFrame sensors(this); + MessageBodyFrame sensors(this); UByte iterations = s.SampleCount; if (s.SampleCount > 3) @@ -890,7 +891,7 @@ void SensorDeviceImpl::onTrackerMessage(TrackerMessage* message) } for (UByte i = 0; i < iterations; i++) - { + { sensors.Acceleration = AccelFromBodyFrameUpdate(s, i, convertHMDToSensor); sensors.RotationRate = EulerFromBodyFrameUpdate(s, i, convertHMDToSensor); sensors.MagneticField= MagFromBodyFrameUpdate(s, convertHMDToSensor); diff --git a/LibOVR/Src/OVR_SensorImpl.h b/LibOVR/Src/OVR_SensorImpl.h index 8b9eefb..dd17486 100644 --- a/LibOVR/Src/OVR_SensorImpl.h +++ b/LibOVR/Src/OVR_SensorImpl.h @@ -30,7 +30,7 @@ limitations under the License. #include "OVR_HIDDeviceImpl.h" namespace OVR { - + struct TrackerMessage; class ExternalVisitor; @@ -47,7 +47,7 @@ public: virtual bool MatchVendorProduct(UInt16 vendorId, UInt16 productId) const; virtual bool DetectHIDDevice(DeviceManager* pdevMgr, const HIDDeviceDesc& desc); protected: - DeviceManager* getManager() const { return (DeviceManager*) pManager; } + DeviceManager* getManager() const { return (DeviceManager*) pManager; } }; @@ -57,7 +57,7 @@ class SensorDeviceCreateDesc : public HIDDeviceCreateDesc public: SensorDeviceCreateDesc(DeviceFactory* factory, const HIDDeviceDesc& hidDesc) : HIDDeviceCreateDesc(factory, Device_Sensor, hidDesc) { } - + virtual DeviceCreateDesc* Clone() const { return new SensorDeviceCreateDesc(*this); @@ -156,7 +156,7 @@ struct SensorDisplayInfoImpl }; UInt16 CommandId; - UByte DistortionType; + UByte DistortionType; UInt16 HResolution, VResolution; float HScreenSize, VScreenSize; float VCenter; @@ -185,24 +185,24 @@ public: // DeviceCommaon interface virtual bool Initialize(DeviceBase* parent); virtual void Shutdown(); - + virtual void SetMessageHandler(MessageHandler* handler); // HIDDevice::Notifier interface. - virtual void OnInputReport(UByte* pData, UInt32 length); + virtual void OnInputReport(const UByte* pData, UInt32 length); virtual UInt64 OnTicks(UInt64 ticksMks); // HMD-Mounted sensor has a different coordinate frame. - virtual void SetCoordinateFrame(CoordinateFrame coordframe); - virtual CoordinateFrame GetCoordinateFrame() const; + virtual void SetCoordinateFrame(CoordinateFrame coordframe); + virtual CoordinateFrame GetCoordinateFrame() const; // SensorDevice interface virtual bool SetRange(const SensorRange& range, bool waitFlag); virtual void GetRange(SensorRange* range) const; - // Sets report rate (in Hz) of MessageBodyFrame messages (delivered through MessageHandler::OnMessage call). - // Currently supported maximum rate is 1000Hz. If the rate is set to 500 or 333 Hz then OnMessage will be - // called twice or thrice at the same 'tick'. + // Sets report rate (in Hz) of MessageBodyFrame messages (delivered through MessageHandler::OnMessage call). + // Currently supported maximum rate is 1000Hz. If the rate is set to 500 or 333 Hz then OnMessage will be + // called twice or thrice at the same 'tick'. // If the rate is < 333 then the OnMessage / MessageBodyFrame will be called three // times for each 'tick': the first call will contain averaged values, the second // and third calls will provide with most recent two recorded samples. @@ -213,7 +213,7 @@ public: virtual unsigned GetReportRate() const; // Hack to create HMD device from sensor display info. - static void EnumerateHMDFromSensorDisplayInfo(const SensorDisplayInfoImpl& displayInfo, + static void EnumerateHMDFromSensorDisplayInfo(const SensorDisplayInfoImpl& displayInfo, DeviceFactory::EnumerateVisitor& visitor); protected: @@ -234,7 +234,7 @@ protected: { return (SensorDeviceCreateDesc*)pCreateDesc.GetPtr(); } HIDDeviceDesc* getHIDDesc() const - { return &getCreateDesc()->HIDDesc; } + { return &getCreateDesc()->HIDDesc; } */ // Set if the sensor is located on the HMD. @@ -252,10 +252,10 @@ protected: Vector3f LastRotationRate; Vector3f LastMagneticField; - // Current sensor range obtained from device. + // Current sensor range obtained from device. SensorRange MaxValidRange; SensorRange CurrentRange; - + UInt16 OldCommandId; }; diff --git a/LibOVR/Src/OVR_Win32_HIDDevice.cpp b/LibOVR/Src/OVR_Win32_HIDDevice.cpp index 8643041..81a6c8a 100644 --- a/LibOVR/Src/OVR_Win32_HIDDevice.cpp +++ b/LibOVR/Src/OVR_Win32_HIDDevice.cpp @@ -24,6 +24,8 @@ limitations under the License. *************************************************************************************/ +#pragma comment(lib, "setupapi.lib") + #include "OVR_Win32_HIDDevice.h" #include "OVR_Win32_DeviceManager.h" @@ -32,6 +34,7 @@ limitations under the License. namespace OVR { namespace Win32 { + //------------------------------------------------------------------------------------- // HIDDevicePathWrapper is a simple class used to extract HID device file path // through SetupDiGetDeviceInterfaceDetail. We use a class since this is a bit messy. diff --git a/LibOVR/Src/Util/Util_MagCalibration.cpp b/LibOVR/Src/Util/Util_MagCalibration.cpp deleted file mode 100644 index 58b8c45..0000000 --- a/LibOVR/Src/Util/Util_MagCalibration.cpp +++ /dev/null @@ -1,227 +0,0 @@ -/************************************************************************************ - -Filename : Util_MagCalibration.cpp -Content : Procedures for calibrating the magnetometer -Created : April 16, 2013 -Authors : Steve LaValle, Andrew Reisse - -Copyright : Copyright 2013 Oculus VR, Inc. All Rights reserved. - -Use of this software is subject to the terms of the Oculus license -agreement provided at the time of installation or download, or which -otherwise accompanies this software in either electronic or hard copy form. - -*************************************************************************************/ - -#include "Util_MagCalibration.h" - -namespace OVR { namespace Util { - -void MagCalibration::BeginAutoCalibration(SensorFusion& sf) -{ - Stat = Mag_AutoCalibrating; - // This is a "hard" reset of the mag, so need to clear stored values - sf.ClearMagCalibration(); - SampleCount = 0; - - // reset the statistics - MinMagValues = Vector3f(10000.0f,10000.0f,10000.0f); - MaxMagValues = Vector3f(-10000.0f,-10000.0f,-10000.0f); - MinQuatValues = Quatf(1.0f,1.0f,1.0f,1.0f); - MaxQuatValues = Quatf(0.0f,0.0f,0.0f,0.0f); -} - -unsigned MagCalibration::UpdateAutoCalibration(SensorFusion& sf) -{ - if (Stat != Mag_AutoCalibrating) - return Stat; - - Quatf q = sf.GetOrientation(); - Vector3f m = sf.GetMagnetometer(); - - InsertIfAcceptable(q, m); - - if ((SampleCount == 4) && (Stat == Mag_AutoCalibrating)) - { - //LogText("Magnetometer Output Spread: %f %f %f\n",MagSpread.x,MagSpread.y,MagSpread.z); - //LogText("Quaternion Spread: %f %f %f %f\n",QuatSpread.x,QuatSpread.y,QuatSpread.z,QuatSpread.w); - SetCalibration(sf); - } - - return Stat; - -} - -void MagCalibration::BeginManualCalibration(SensorFusion& sf) -{ - Stat = Mag_ManuallyCalibrating; - sf.ClearMagCalibration(); - SampleCount = 0; -} - -bool MagCalibration::IsAcceptableSample(const Quatf& q, const Vector3f& m) -{ - switch (SampleCount) - { - // Initial sample is always acceptable - case 0: - return true; - break; - case 1: - return (q.DistanceSq(QuatSamples[0]) > MinQuatDistanceSq)&& - ((m - MagSamples[0]).LengthSq() > MinMagDistanceSq); - break; - case 2: - return (q.DistanceSq(QuatSamples[0]) > MinQuatDistanceSq)&& - (q.DistanceSq(QuatSamples[1]) > MinQuatDistanceSq)&& - ((m - MagSamples[0]).LengthSq() > MinMagDistanceSq)&& - ((m - MagSamples[1]).LengthSq() > MinMagDistanceSq); - break; - case 3: - return (q.DistanceSq(QuatSamples[0]) > MinQuatDistanceSq)&& - (q.DistanceSq(QuatSamples[1]) > MinQuatDistanceSq)&& - (q.DistanceSq(QuatSamples[2]) > MinQuatDistanceSq)&& - ((PointToPlaneDistance(MagSamples[0],MagSamples[1],MagSamples[2],m) > MinMagDistance)|| - (PointToPlaneDistance(MagSamples[1],MagSamples[2],m,MagSamples[0]) > MinMagDistance)|| - (PointToPlaneDistance(MagSamples[2],m,MagSamples[0],MagSamples[1]) > MinMagDistance)|| - (PointToPlaneDistance(m,MagSamples[0],MagSamples[1],MagSamples[2]) > MinMagDistance)); - } - - return false; -} - - -bool MagCalibration::InsertIfAcceptable(const Quatf& q, const Vector3f& m) -{ - // Update some statistics - if (m.x < MinMagValues.x) - MinMagValues.x = m.x; - if (m.y < MinMagValues.y) - MinMagValues.y = m.y; - if (m.z < MinMagValues.z) - MinMagValues.z = m.z; - if (m.x > MaxMagValues.x) - MaxMagValues.x = m.x; - if (m.y > MaxMagValues.y) - MaxMagValues.y = m.y; - if (m.z > MaxMagValues.z) - MaxMagValues.z = m.z; - if (q.x < MinQuatValues.x) - MinQuatValues.x = q.x; - if (q.y < MinQuatValues.y) - MinQuatValues.y = q.y; - if (q.z < MinQuatValues.z) - MinQuatValues.z = q.z; - if (q.w < MinQuatValues.w) - MinQuatValues.w = q.w; - if (q.x > MaxQuatValues.x) - MaxQuatValues.x = q.x; - if (q.y > MaxQuatValues.y) - MaxQuatValues.y = q.y; - if (q.z > MaxQuatValues.z) - MaxQuatValues.z = q.z; - if (q.w > MaxQuatValues.w) - MaxQuatValues.w = q.w; - MagSpread = MaxMagValues - MinMagValues; - QuatSpread = MaxQuatValues - MinQuatValues; - - if (IsAcceptableSample(q, m)) - { - MagSamples[SampleCount] = m; - QuatSamples[SampleCount] = q; - SampleCount++; - return true; - } - - return false; -} - -Matrix4f MagCalibration::GetMagCalibration() const -{ - Matrix4f calMat = Matrix4f(); - calMat.M[0][3] = -MagCenter.x; - calMat.M[1][3] = -MagCenter.y; - calMat.M[2][3] = -MagCenter.z; - return calMat; -} - -bool MagCalibration::SetCalibration(SensorFusion& sf) -{ - if (SampleCount < 4) - return false; - - MagCenter = CalculateSphereCenter(MagSamples[0],MagSamples[1],MagSamples[2],MagSamples[3]); - Matrix4f calMat = GetMagCalibration(); - sf.SetMagCalibration(calMat); - Stat = Mag_Calibrated; - //LogText("MagCenter: %f %f %f\n",MagCenter.x,MagCenter.y,MagCenter.z); - - return true; -} - - -// Calculate the center of a sphere that passes through p1, p2, p3, p4 -Vector3f MagCalibration::CalculateSphereCenter(const Vector3f& p1, const Vector3f& p2, - const Vector3f& p3, const Vector3f& p4) -{ - Matrix4f A; - int i; - Vector3f p[4]; - p[0] = p1; - p[1] = p2; - p[2] = p3; - p[3] = p4; - - for (i = 0; i < 4; i++) - { - A.M[i][0] = p[i].x; - A.M[i][1] = p[i].y; - A.M[i][2] = p[i].z; - A.M[i][3] = 1.0f; - } - float m11 = A.Determinant(); - OVR_ASSERT(m11 != 0.0f); - - for (i = 0; i < 4; i++) - { - A.M[i][0] = p[i].x*p[i].x + p[i].y*p[i].y + p[i].z*p[i].z; - A.M[i][1] = p[i].y; - A.M[i][2] = p[i].z; - A.M[i][3] = 1.0f; - } - float m12 = A.Determinant(); - - for (i = 0; i < 4; i++) - { - A.M[i][0] = p[i].x*p[i].x + p[i].y*p[i].y + p[i].z*p[i].z; - A.M[i][1] = p[i].x; - A.M[i][2] = p[i].z; - A.M[i][3] = 1.0f; - } - float m13 = A.Determinant(); - - for (i = 0; i < 4; i++) - { - A.M[i][0] = p[i].x*p[i].x + p[i].y*p[i].y + p[i].z*p[i].z; - A.M[i][1] = p[i].x; - A.M[i][2] = p[i].y; - A.M[i][3] = 1.0f; - } - float m14 = A.Determinant(); - - float c = 0.5f / m11; - return Vector3f(c*m12, -c*m13, c*m14); -} - -// Distance from p4 to the nearest point on a plane through p1, p2, p3 -float MagCalibration::PointToPlaneDistance(const Vector3f& p1, const Vector3f& p2, - const Vector3f& p3, const Vector3f& p4) -{ - Vector3f v1 = p1 - p2; - Vector3f v2 = p1 - p3; - Vector3f planeNormal = v1.Cross(v2); - planeNormal.Normalize(); - return (fabs((planeNormal * p4) - planeNormal * p1)); -} - -}} diff --git a/LibOVR/Src/Util/Util_MagCalibration.h b/LibOVR/Src/Util/Util_MagCalibration.h deleted file mode 100644 index 1f8e8cb..0000000 --- a/LibOVR/Src/Util/Util_MagCalibration.h +++ /dev/null @@ -1,138 +0,0 @@ -/************************************************************************************ - -PublicHeader: OVR.h -Filename : Util_MagCalibration.h -Content : Procedures for calibrating the magnetometer -Created : April 16, 2013 -Authors : Steve LaValle, Andrew Reisse - -Copyright : Copyright 2013 Oculus VR, Inc. All Rights reserved. - -Use of this software is subject to the terms of the Oculus license -agreement provided at the time of installation or download, or which -otherwise accompanies this software in either electronic or hard copy form. - -*************************************************************************************/ - -#ifndef OVR_Util_MagCalibration_h -#define OVR_Util_MagCalibration_h - -#include "../OVR_SensorFusion.h" -#include "../Kernel/OVR_String.h" -#include "../Kernel/OVR_Log.h" - -namespace OVR { namespace Util { - -class MagCalibration -{ -public: - enum MagStatus - { - Mag_Uninitialized = 0, - Mag_AutoCalibrating = 1, - Mag_ManuallyCalibrating = 2, - Mag_Calibrated = 3 - }; - - MagCalibration() : - Stat(Mag_Uninitialized), - MinMagDistance(0.2f), MinQuatDistance(0.5f), - SampleCount(0) - { - MinMagDistanceSq = MinMagDistance * MinMagDistance; - MinQuatDistanceSq = MinQuatDistance * MinQuatDistance; - MinMagValues = Vector3f(10000.0f,10000.0f,10000.0f); - MaxMagValues = Vector3f(-10000.0f,-10000.0f,-10000.0f); - MinQuatValues = Quatf(1.0f,1.0f,1.0f,1.0f); - MaxQuatValues = Quatf(0.0f,0.0f,0.0f,0.0f); - } - - // Methods that are useful for either auto or manual calibration - bool IsUnitialized() const { return Stat == Mag_Uninitialized; } - bool IsCalibrated() const { return Stat == Mag_Calibrated; } - int NumberOfSamples() const { return SampleCount; } - int RequiredSampleCount() const { return 4; } - void AbortCalibration() - { - Stat = Mag_Uninitialized; - SampleCount = 0; - } - - void ClearCalibration(SensorFusion& sf) - { - Stat = Mag_Uninitialized; - SampleCount = 0; - sf.ClearMagCalibration(); - }; - - // Methods for automatic magnetometer calibration - void BeginAutoCalibration(SensorFusion& sf); - unsigned UpdateAutoCalibration(SensorFusion& sf); - bool IsAutoCalibrating() const { return Stat == Mag_AutoCalibrating; } - - // Methods for building a manual (user-guided) calibraton procedure - void BeginManualCalibration(SensorFusion& sf); - bool IsAcceptableSample(const Quatf& q, const Vector3f& m); - bool InsertIfAcceptable(const Quatf& q, const Vector3f& m); - // Returns true if successful, requiring that SampleCount = 4 - bool SetCalibration(SensorFusion& sf); - bool IsManuallyCalibrating() const { return Stat == Mag_ManuallyCalibrating; } - - // This is the minimum acceptable distance (Euclidean) between raw - // magnetometer values to be acceptable for usage in calibration. - void SetMinMagDistance(float dist) - { - MinMagDistance = dist; - MinMagDistanceSq = MinMagDistance * MinMagDistance; - } - - // The minimum acceptable distance (4D Euclidean) between orientations - // to be acceptable for calibration usage. - void SetMinQuatDistance(float dist) - { - MinQuatDistance = dist; - MinQuatDistanceSq = MinQuatDistance * MinQuatDistance; - } - - // A result of the calibration, which is the center of a sphere that - // roughly approximates the magnetometer data. - Vector3f GetMagCenter() const { return MagCenter; } - // Retrieves the full magnetometer calibration matrix - Matrix4f GetMagCalibration() const; - // Retrieves the range of each quaternion term during calibration - Quatf GetCalibrationQuatSpread() const { return QuatSpread; } - // Retrieves the range of each magnetometer term during calibration - Vector3f GetCalibrationMagSpread() const { return MagSpread; } - -private: - // Determine the unique sphere through 4 non-coplanar points - Vector3f CalculateSphereCenter(const Vector3f& p1, const Vector3f& p2, - const Vector3f& p3, const Vector3f& p4); - - // Distance from p4 to the nearest point on a plane through p1, p2, p3 - float PointToPlaneDistance(const Vector3f& p1, const Vector3f& p2, - const Vector3f& p3, const Vector3f& p4); - - Vector3f MagCenter; - unsigned Stat; - float MinMagDistance; - float MinQuatDistance; - float MinMagDistanceSq; - float MinQuatDistanceSq; - // For gathering statistics during calibration - Vector3f MinMagValues; - Vector3f MaxMagValues; - Vector3f MagSpread; - Quatf MinQuatValues; - Quatf MaxQuatValues; - Quatf QuatSpread; - - unsigned SampleCount; - Vector3f MagSamples[4]; - Quatf QuatSamples[4]; - -}; - -}} - -#endif |