nuclear@1: /************************************************************************************ nuclear@1: nuclear@1: Filename : OVR_LatencyTestImpl.cpp nuclear@1: Content : Oculus Latency Tester device implementation. nuclear@1: Created : March 7, 2013 nuclear@1: Authors : Lee Cooper nuclear@1: nuclear@1: Copyright : Copyright 2013 Oculus VR, Inc. All Rights reserved. nuclear@1: nuclear@1: Use of this software is subject to the terms of the Oculus license nuclear@1: agreement provided at the time of installation or download, or which nuclear@1: otherwise accompanies this software in either electronic or hard copy form. nuclear@1: nuclear@1: *************************************************************************************/ nuclear@1: nuclear@1: #include "OVR_LatencyTestImpl.h" nuclear@1: nuclear@1: namespace OVR { nuclear@1: nuclear@1: //------------------------------------------------------------------------------------- nuclear@1: // ***** Oculus Latency Tester specific packet data structures nuclear@1: nuclear@1: enum { nuclear@1: LatencyTester_VendorId = Oculus_VendorId, nuclear@1: LatencyTester_ProductId = 0x0101, nuclear@1: }; nuclear@1: nuclear@1: // Reported data is little-endian now nuclear@1: static UInt16 DecodeUInt16(const UByte* buffer) nuclear@1: { nuclear@1: return (UInt16(buffer[1]) << 8) | UInt16(buffer[0]); nuclear@1: } nuclear@1: nuclear@1: /* Unreferenced nuclear@1: static SInt16 DecodeSInt16(const UByte* buffer) nuclear@1: { nuclear@1: return (SInt16(buffer[1]) << 8) | SInt16(buffer[0]); nuclear@1: }*/ nuclear@1: nuclear@1: static void UnpackSamples(const UByte* buffer, UByte* r, UByte* g, UByte* b) nuclear@1: { nuclear@1: *r = buffer[0]; nuclear@1: *g = buffer[1]; nuclear@1: *b = buffer[2]; nuclear@1: } nuclear@1: nuclear@1: // Messages we handle. nuclear@1: enum LatencyTestMessageType nuclear@1: { nuclear@1: LatencyTestMessage_None = 0, nuclear@1: LatencyTestMessage_Samples = 1, nuclear@1: LatencyTestMessage_ColorDetected = 2, nuclear@1: LatencyTestMessage_TestStarted = 3, nuclear@1: LatencyTestMessage_Button = 4, nuclear@1: LatencyTestMessage_Unknown = 0x100, nuclear@1: LatencyTestMessage_SizeError = 0x101, nuclear@1: }; nuclear@1: nuclear@1: struct LatencyTestSample nuclear@1: { nuclear@1: UByte Value[3]; nuclear@1: }; nuclear@1: nuclear@1: struct LatencyTestSamples nuclear@1: { nuclear@1: UByte SampleCount; nuclear@1: UInt16 Timestamp; nuclear@1: nuclear@1: LatencyTestSample Samples[20]; nuclear@1: nuclear@1: LatencyTestMessageType Decode(const UByte* buffer, int size) nuclear@1: { nuclear@1: if (size < 64) nuclear@1: { nuclear@1: return LatencyTestMessage_SizeError; nuclear@1: } nuclear@1: nuclear@1: SampleCount = buffer[1]; nuclear@1: Timestamp = DecodeUInt16(buffer + 2); nuclear@1: nuclear@1: for (UByte i = 0; i < SampleCount; i++) nuclear@1: { nuclear@1: UnpackSamples(buffer + 4 + (3 * i), &Samples[i].Value[0], &Samples[i].Value[1], &Samples[i].Value[2]); nuclear@1: } nuclear@1: nuclear@1: return LatencyTestMessage_Samples; nuclear@1: } nuclear@1: }; nuclear@1: nuclear@1: struct LatencyTestSamplesMessage nuclear@1: { nuclear@1: LatencyTestMessageType Type; nuclear@1: LatencyTestSamples Samples; nuclear@1: }; nuclear@1: nuclear@1: bool DecodeLatencyTestSamplesMessage(LatencyTestSamplesMessage* message, UByte* buffer, int size) nuclear@1: { nuclear@1: memset(message, 0, sizeof(LatencyTestSamplesMessage)); nuclear@1: nuclear@1: if (size < 64) nuclear@1: { nuclear@1: message->Type = LatencyTestMessage_SizeError; nuclear@1: return false; nuclear@1: } nuclear@1: nuclear@1: switch (buffer[0]) nuclear@1: { nuclear@1: case LatencyTestMessage_Samples: nuclear@1: message->Type = message->Samples.Decode(buffer, size); nuclear@1: break; nuclear@1: nuclear@1: default: nuclear@1: message->Type = LatencyTestMessage_Unknown; nuclear@1: break; nuclear@1: } nuclear@1: nuclear@1: return (message->Type < LatencyTestMessage_Unknown) && (message->Type != LatencyTestMessage_None); nuclear@1: } nuclear@1: nuclear@1: struct LatencyTestColorDetected nuclear@1: { nuclear@1: UInt16 CommandID; nuclear@1: UInt16 Timestamp; nuclear@1: UInt16 Elapsed; nuclear@1: UByte TriggerValue[3]; nuclear@1: UByte TargetValue[3]; nuclear@1: nuclear@1: LatencyTestMessageType Decode(const UByte* buffer, int size) nuclear@1: { nuclear@1: if (size < 13) nuclear@1: return LatencyTestMessage_SizeError; nuclear@1: nuclear@1: CommandID = DecodeUInt16(buffer + 1); nuclear@1: Timestamp = DecodeUInt16(buffer + 3); nuclear@1: Elapsed = DecodeUInt16(buffer + 5); nuclear@1: memcpy(TriggerValue, buffer + 7, 3); nuclear@1: memcpy(TargetValue, buffer + 10, 3); nuclear@1: nuclear@1: return LatencyTestMessage_ColorDetected; nuclear@1: } nuclear@1: }; nuclear@1: nuclear@1: struct LatencyTestColorDetectedMessage nuclear@1: { nuclear@1: LatencyTestMessageType Type; nuclear@1: LatencyTestColorDetected ColorDetected; nuclear@1: }; nuclear@1: nuclear@1: bool DecodeLatencyTestColorDetectedMessage(LatencyTestColorDetectedMessage* message, UByte* buffer, int size) nuclear@1: { nuclear@1: memset(message, 0, sizeof(LatencyTestColorDetectedMessage)); nuclear@1: nuclear@1: if (size < 13) nuclear@1: { nuclear@1: message->Type = LatencyTestMessage_SizeError; nuclear@1: return false; nuclear@1: } nuclear@1: nuclear@1: switch (buffer[0]) nuclear@1: { nuclear@1: case LatencyTestMessage_ColorDetected: nuclear@1: message->Type = message->ColorDetected.Decode(buffer, size); nuclear@1: break; nuclear@1: nuclear@1: default: nuclear@1: message->Type = LatencyTestMessage_Unknown; nuclear@1: break; nuclear@1: } nuclear@1: nuclear@1: return (message->Type < LatencyTestMessage_Unknown) && (message->Type != LatencyTestMessage_None); nuclear@1: } nuclear@1: nuclear@1: struct LatencyTestStarted nuclear@1: { nuclear@1: UInt16 CommandID; nuclear@1: UInt16 Timestamp; nuclear@1: UByte TargetValue[3]; nuclear@1: nuclear@1: LatencyTestMessageType Decode(const UByte* buffer, int size) nuclear@1: { nuclear@1: if (size < 8) nuclear@1: return LatencyTestMessage_SizeError; nuclear@1: nuclear@1: CommandID = DecodeUInt16(buffer + 1); nuclear@1: Timestamp = DecodeUInt16(buffer + 3); nuclear@1: memcpy(TargetValue, buffer + 5, 3); nuclear@1: nuclear@1: return LatencyTestMessage_TestStarted; nuclear@1: } nuclear@1: }; nuclear@1: nuclear@1: struct LatencyTestStartedMessage nuclear@1: { nuclear@1: LatencyTestMessageType Type; nuclear@1: LatencyTestStarted TestStarted; nuclear@1: }; nuclear@1: nuclear@1: bool DecodeLatencyTestStartedMessage(LatencyTestStartedMessage* message, UByte* buffer, int size) nuclear@1: { nuclear@1: memset(message, 0, sizeof(LatencyTestStartedMessage)); nuclear@1: nuclear@1: if (size < 8) nuclear@1: { nuclear@1: message->Type = LatencyTestMessage_SizeError; nuclear@1: return false; nuclear@1: } nuclear@1: nuclear@1: switch (buffer[0]) nuclear@1: { nuclear@1: case LatencyTestMessage_TestStarted: nuclear@1: message->Type = message->TestStarted.Decode(buffer, size); nuclear@1: break; nuclear@1: nuclear@1: default: nuclear@1: message->Type = LatencyTestMessage_Unknown; nuclear@1: break; nuclear@1: } nuclear@1: nuclear@1: return (message->Type < LatencyTestMessage_Unknown) && (message->Type != LatencyTestMessage_None); nuclear@1: } nuclear@1: nuclear@1: struct LatencyTestButton nuclear@1: { nuclear@1: UInt16 CommandID; nuclear@1: UInt16 Timestamp; nuclear@1: nuclear@1: LatencyTestMessageType Decode(const UByte* buffer, int size) nuclear@1: { nuclear@1: if (size < 5) nuclear@1: return LatencyTestMessage_SizeError; nuclear@1: nuclear@1: CommandID = DecodeUInt16(buffer + 1); nuclear@1: Timestamp = DecodeUInt16(buffer + 3); nuclear@1: nuclear@1: return LatencyTestMessage_Button; nuclear@1: } nuclear@1: }; nuclear@1: nuclear@1: struct LatencyTestButtonMessage nuclear@1: { nuclear@1: LatencyTestMessageType Type; nuclear@1: LatencyTestButton Button; nuclear@1: }; nuclear@1: nuclear@1: bool DecodeLatencyTestButtonMessage(LatencyTestButtonMessage* message, UByte* buffer, int size) nuclear@1: { nuclear@1: memset(message, 0, sizeof(LatencyTestButtonMessage)); nuclear@1: nuclear@1: if (size < 5) nuclear@1: { nuclear@1: message->Type = LatencyTestMessage_SizeError; nuclear@1: return false; nuclear@1: } nuclear@1: nuclear@1: switch (buffer[0]) nuclear@1: { nuclear@1: case LatencyTestMessage_Button: nuclear@1: message->Type = message->Button.Decode(buffer, size); nuclear@1: break; nuclear@1: nuclear@1: default: nuclear@1: message->Type = LatencyTestMessage_Unknown; nuclear@1: break; nuclear@1: } nuclear@1: nuclear@1: return (message->Type < LatencyTestMessage_Unknown) && (message->Type != LatencyTestMessage_None); nuclear@1: } nuclear@1: nuclear@1: struct LatencyTestConfigurationImpl nuclear@1: { nuclear@1: enum { PacketSize = 5 }; nuclear@1: UByte Buffer[PacketSize]; nuclear@1: nuclear@1: OVR::LatencyTestConfiguration Configuration; nuclear@1: nuclear@1: LatencyTestConfigurationImpl(const OVR::LatencyTestConfiguration& configuration) nuclear@1: : Configuration(configuration) nuclear@1: { nuclear@1: Pack(); nuclear@1: } nuclear@1: nuclear@1: void Pack() nuclear@1: { nuclear@1: Buffer[0] = 5; nuclear@1: Buffer[1] = UByte(Configuration.SendSamples); nuclear@1: Buffer[2] = Configuration.Threshold.R; nuclear@1: Buffer[3] = Configuration.Threshold.G; nuclear@1: Buffer[4] = Configuration.Threshold.B; nuclear@1: } nuclear@1: nuclear@1: void Unpack() nuclear@1: { nuclear@1: Configuration.SendSamples = Buffer[1] != 0 ? true : false; nuclear@1: Configuration.Threshold.R = Buffer[2]; nuclear@1: Configuration.Threshold.G = Buffer[3]; nuclear@1: Configuration.Threshold.B = Buffer[4]; nuclear@1: } nuclear@1: }; nuclear@1: nuclear@1: struct LatencyTestCalibrateImpl nuclear@1: { nuclear@1: enum { PacketSize = 4 }; nuclear@1: UByte Buffer[PacketSize]; nuclear@1: nuclear@1: Color CalibrationColor; nuclear@1: nuclear@1: LatencyTestCalibrateImpl(const Color& calibrationColor) nuclear@1: : CalibrationColor(calibrationColor) nuclear@1: { nuclear@1: Pack(); nuclear@1: } nuclear@1: nuclear@1: void Pack() nuclear@1: { nuclear@1: Buffer[0] = 7; nuclear@1: Buffer[1] = CalibrationColor.R; nuclear@1: Buffer[2] = CalibrationColor.G; nuclear@1: Buffer[3] = CalibrationColor.B; nuclear@1: } nuclear@1: nuclear@1: void Unpack() nuclear@1: { nuclear@1: CalibrationColor.R = Buffer[1]; nuclear@1: CalibrationColor.G = Buffer[2]; nuclear@1: CalibrationColor.B = Buffer[3]; nuclear@1: } nuclear@1: }; nuclear@1: nuclear@1: struct LatencyTestStartTestImpl nuclear@1: { nuclear@1: enum { PacketSize = 6 }; nuclear@1: UByte Buffer[PacketSize]; nuclear@1: nuclear@1: Color TargetColor; nuclear@1: nuclear@1: LatencyTestStartTestImpl(const Color& targetColor) nuclear@1: : TargetColor(targetColor) nuclear@1: { nuclear@1: Pack(); nuclear@1: } nuclear@1: nuclear@1: void Pack() nuclear@1: { nuclear@1: UInt16 commandID = 1; nuclear@1: nuclear@1: Buffer[0] = 8; nuclear@1: Buffer[1] = UByte(commandID & 0xFF); nuclear@1: Buffer[2] = UByte(commandID >> 8); nuclear@1: Buffer[3] = TargetColor.R; nuclear@1: Buffer[4] = TargetColor.G; nuclear@1: Buffer[5] = TargetColor.B; nuclear@1: } nuclear@1: nuclear@1: void Unpack() nuclear@1: { nuclear@1: // UInt16 commandID = Buffer[1] | (UInt16(Buffer[2]) << 8); nuclear@1: TargetColor.R = Buffer[3]; nuclear@1: TargetColor.G = Buffer[4]; nuclear@1: TargetColor.B = Buffer[5]; nuclear@1: } nuclear@1: }; nuclear@1: nuclear@1: struct LatencyTestDisplayImpl nuclear@1: { nuclear@1: enum { PacketSize = 6 }; nuclear@1: UByte Buffer[PacketSize]; nuclear@1: nuclear@1: OVR::LatencyTestDisplay Display; nuclear@1: nuclear@1: LatencyTestDisplayImpl(const OVR::LatencyTestDisplay& display) nuclear@1: : Display(display) nuclear@1: { nuclear@1: Pack(); nuclear@1: } nuclear@1: nuclear@1: void Pack() nuclear@1: { nuclear@1: Buffer[0] = 9; nuclear@1: Buffer[1] = Display.Mode; nuclear@1: Buffer[2] = UByte(Display.Value & 0xFF); nuclear@1: Buffer[3] = UByte((Display.Value >> 8) & 0xFF); nuclear@1: Buffer[4] = UByte((Display.Value >> 16) & 0xFF); nuclear@1: Buffer[5] = UByte((Display.Value >> 24) & 0xFF); nuclear@1: } nuclear@1: nuclear@1: void Unpack() nuclear@1: { nuclear@1: Display.Mode = Buffer[1]; nuclear@1: Display.Value = UInt32(Buffer[2]) | nuclear@1: (UInt32(Buffer[3]) << 8) | nuclear@1: (UInt32(Buffer[4]) << 16) | nuclear@1: (UInt32(Buffer[5]) << 24); nuclear@1: } nuclear@1: }; nuclear@1: nuclear@1: //------------------------------------------------------------------------------------- nuclear@1: // ***** LatencyTestDeviceFactory nuclear@1: nuclear@1: LatencyTestDeviceFactory LatencyTestDeviceFactory::Instance; nuclear@1: nuclear@1: void LatencyTestDeviceFactory::EnumerateDevices(EnumerateVisitor& visitor) nuclear@1: { nuclear@1: nuclear@1: class LatencyTestEnumerator : public HIDEnumerateVisitor nuclear@1: { nuclear@1: // Assign not supported; suppress MSVC warning. nuclear@1: void operator = (const LatencyTestEnumerator&) { } nuclear@1: nuclear@1: DeviceFactory* pFactory; nuclear@1: EnumerateVisitor& ExternalVisitor; nuclear@1: public: nuclear@1: LatencyTestEnumerator(DeviceFactory* factory, EnumerateVisitor& externalVisitor) nuclear@1: : pFactory(factory), ExternalVisitor(externalVisitor) { } nuclear@1: nuclear@1: virtual bool MatchVendorProduct(UInt16 vendorId, UInt16 productId) nuclear@1: { nuclear@1: return pFactory->MatchVendorProduct(vendorId, productId); nuclear@1: } nuclear@1: nuclear@1: virtual void Visit(HIDDevice& device, const HIDDeviceDesc& desc) nuclear@1: { nuclear@1: OVR_UNUSED(device); nuclear@1: nuclear@1: LatencyTestDeviceCreateDesc createDesc(pFactory, desc); nuclear@1: ExternalVisitor.Visit(createDesc); nuclear@1: } nuclear@1: }; nuclear@1: nuclear@1: LatencyTestEnumerator latencyTestEnumerator(this, visitor); nuclear@1: GetManagerImpl()->GetHIDDeviceManager()->Enumerate(&latencyTestEnumerator); nuclear@1: } nuclear@1: nuclear@1: bool LatencyTestDeviceFactory::MatchVendorProduct(UInt16 vendorId, UInt16 productId) const nuclear@1: { nuclear@1: return ((vendorId == LatencyTester_VendorId) && (productId == LatencyTester_ProductId)); nuclear@1: } nuclear@1: nuclear@1: bool LatencyTestDeviceFactory::DetectHIDDevice(DeviceManager* pdevMgr, nuclear@1: const HIDDeviceDesc& desc) nuclear@1: { nuclear@1: if (MatchVendorProduct(desc.VendorId, desc.ProductId)) nuclear@1: { nuclear@1: LatencyTestDeviceCreateDesc createDesc(this, desc); nuclear@1: return pdevMgr->AddDevice_NeedsLock(createDesc).GetPtr() != NULL; nuclear@1: } nuclear@1: return false; nuclear@1: } nuclear@1: nuclear@1: //------------------------------------------------------------------------------------- nuclear@1: // ***** LatencyTestDeviceCreateDesc nuclear@1: nuclear@1: DeviceBase* LatencyTestDeviceCreateDesc::NewDeviceInstance() nuclear@1: { nuclear@1: return new LatencyTestDeviceImpl(this); nuclear@1: } nuclear@1: nuclear@1: bool LatencyTestDeviceCreateDesc::GetDeviceInfo(DeviceInfo* info) const nuclear@1: { nuclear@1: if ((info->InfoClassType != Device_LatencyTester) && nuclear@1: (info->InfoClassType != Device_None)) nuclear@1: return false; nuclear@1: nuclear@1: OVR_strcpy(info->ProductName, DeviceInfo::MaxNameLength, HIDDesc.Product.ToCStr()); nuclear@1: OVR_strcpy(info->Manufacturer, DeviceInfo::MaxNameLength, HIDDesc.Manufacturer.ToCStr()); nuclear@1: info->Type = Device_LatencyTester; nuclear@1: info->Version = 0; nuclear@1: nuclear@1: if (info->InfoClassType == Device_LatencyTester) nuclear@1: { nuclear@1: SensorInfo* sinfo = (SensorInfo*)info; nuclear@1: sinfo->VendorId = HIDDesc.VendorId; nuclear@1: sinfo->ProductId = HIDDesc.ProductId; nuclear@1: OVR_strcpy(sinfo->SerialNumber, sizeof(sinfo->SerialNumber),HIDDesc.SerialNumber.ToCStr()); nuclear@1: } nuclear@1: return true; nuclear@1: } nuclear@1: nuclear@1: //------------------------------------------------------------------------------------- nuclear@1: // ***** LatencyTestDevice nuclear@1: nuclear@1: LatencyTestDeviceImpl::LatencyTestDeviceImpl(LatencyTestDeviceCreateDesc* createDesc) nuclear@1: : OVR::HIDDeviceImpl(createDesc, 0) nuclear@1: { nuclear@1: } nuclear@1: nuclear@1: LatencyTestDeviceImpl::~LatencyTestDeviceImpl() nuclear@1: { nuclear@1: // Check that Shutdown() was called. nuclear@1: OVR_ASSERT(!pCreateDesc->pDevice); nuclear@1: } nuclear@1: nuclear@1: // Internal creation APIs. nuclear@1: bool LatencyTestDeviceImpl::Initialize(DeviceBase* parent) nuclear@1: { nuclear@1: if (HIDDeviceImpl::Initialize(parent)) nuclear@1: { nuclear@1: LogText("OVR::LatencyTestDevice initialized.\n"); nuclear@1: return true; nuclear@1: } nuclear@1: nuclear@1: return false; nuclear@1: } nuclear@1: nuclear@1: void LatencyTestDeviceImpl::Shutdown() nuclear@1: { nuclear@1: HIDDeviceImpl::Shutdown(); nuclear@1: nuclear@1: LogText("OVR::LatencyTestDevice - Closed '%s'\n", getHIDDesc()->Path.ToCStr()); nuclear@1: } nuclear@1: nuclear@1: void LatencyTestDeviceImpl::OnInputReport(UByte* pData, UInt32 length) nuclear@1: { nuclear@1: nuclear@1: bool processed = false; nuclear@1: if (!processed) nuclear@1: { nuclear@1: LatencyTestSamplesMessage message; nuclear@1: if (DecodeLatencyTestSamplesMessage(&message, pData, length)) nuclear@1: { nuclear@1: processed = true; nuclear@1: onLatencyTestSamplesMessage(&message); nuclear@1: } nuclear@1: } nuclear@1: nuclear@1: if (!processed) nuclear@1: { nuclear@1: LatencyTestColorDetectedMessage message; nuclear@1: if (DecodeLatencyTestColorDetectedMessage(&message, pData, length)) nuclear@1: { nuclear@1: processed = true; nuclear@1: onLatencyTestColorDetectedMessage(&message); nuclear@1: } nuclear@1: } nuclear@1: nuclear@1: if (!processed) nuclear@1: { nuclear@1: LatencyTestStartedMessage message; nuclear@1: if (DecodeLatencyTestStartedMessage(&message, pData, length)) nuclear@1: { nuclear@1: processed = true; nuclear@1: onLatencyTestStartedMessage(&message); nuclear@1: } nuclear@1: } nuclear@1: nuclear@1: if (!processed) nuclear@1: { nuclear@1: LatencyTestButtonMessage message; nuclear@1: if (DecodeLatencyTestButtonMessage(&message, pData, length)) nuclear@1: { nuclear@1: processed = true; nuclear@1: onLatencyTestButtonMessage(&message); nuclear@1: } nuclear@1: } nuclear@1: } nuclear@1: nuclear@1: bool LatencyTestDeviceImpl::SetConfiguration(const OVR::LatencyTestConfiguration& configuration, bool waitFlag) nuclear@1: { nuclear@1: bool result = false; nuclear@1: ThreadCommandQueue* queue = GetManagerImpl()->GetThreadQueue(); nuclear@1: nuclear@1: if (GetManagerImpl()->GetThreadId() != OVR::GetCurrentThreadId()) nuclear@1: { nuclear@1: if (!waitFlag) nuclear@1: { nuclear@1: return queue->PushCall(this, &LatencyTestDeviceImpl::setConfiguration, configuration); nuclear@1: } nuclear@1: nuclear@1: if (!queue->PushCallAndWaitResult( this, nuclear@1: &LatencyTestDeviceImpl::setConfiguration, nuclear@1: &result, nuclear@1: configuration)) nuclear@1: { nuclear@1: return false; nuclear@1: } nuclear@1: } nuclear@1: else nuclear@1: return setConfiguration(configuration); nuclear@1: nuclear@1: return result; nuclear@1: } nuclear@1: nuclear@1: bool LatencyTestDeviceImpl::setConfiguration(const OVR::LatencyTestConfiguration& configuration) nuclear@1: { nuclear@1: LatencyTestConfigurationImpl ltc(configuration); nuclear@1: return GetInternalDevice()->SetFeatureReport(ltc.Buffer, LatencyTestConfigurationImpl::PacketSize); nuclear@1: } nuclear@1: nuclear@1: bool LatencyTestDeviceImpl::GetConfiguration(OVR::LatencyTestConfiguration* configuration) nuclear@1: { nuclear@1: bool result = false; nuclear@1: nuclear@1: ThreadCommandQueue* pQueue = this->GetManagerImpl()->GetThreadQueue(); nuclear@1: if (!pQueue->PushCallAndWaitResult(this, &LatencyTestDeviceImpl::getConfiguration, &result, configuration)) nuclear@1: return false; nuclear@1: nuclear@1: return result; nuclear@1: } nuclear@1: nuclear@1: bool LatencyTestDeviceImpl::getConfiguration(OVR::LatencyTestConfiguration* configuration) nuclear@1: { nuclear@1: LatencyTestConfigurationImpl ltc(*configuration); nuclear@1: if (GetInternalDevice()->GetFeatureReport(ltc.Buffer, LatencyTestConfigurationImpl::PacketSize)) nuclear@1: { nuclear@1: ltc.Unpack(); nuclear@1: *configuration = ltc.Configuration; nuclear@1: return true; nuclear@1: } nuclear@1: nuclear@1: return false; nuclear@1: } nuclear@1: nuclear@1: bool LatencyTestDeviceImpl::SetCalibrate(const Color& calibrationColor, bool waitFlag) nuclear@1: { nuclear@1: bool result = false; nuclear@1: ThreadCommandQueue* queue = GetManagerImpl()->GetThreadQueue(); nuclear@1: nuclear@1: if (!waitFlag) nuclear@1: { nuclear@1: return queue->PushCall(this, &LatencyTestDeviceImpl::setCalibrate, calibrationColor); nuclear@1: } nuclear@1: nuclear@1: if (!queue->PushCallAndWaitResult( this, nuclear@1: &LatencyTestDeviceImpl::setCalibrate, nuclear@1: &result, nuclear@1: calibrationColor)) nuclear@1: { nuclear@1: return false; nuclear@1: } nuclear@1: nuclear@1: return result; nuclear@1: } nuclear@1: nuclear@1: bool LatencyTestDeviceImpl::setCalibrate(const Color& calibrationColor) nuclear@1: { nuclear@1: LatencyTestCalibrateImpl ltc(calibrationColor); nuclear@1: return GetInternalDevice()->SetFeatureReport(ltc.Buffer, LatencyTestCalibrateImpl::PacketSize); nuclear@1: } nuclear@1: nuclear@1: bool LatencyTestDeviceImpl::SetStartTest(const Color& targetColor, bool waitFlag) nuclear@1: { nuclear@1: bool result = false; nuclear@1: ThreadCommandQueue* queue = GetManagerImpl()->GetThreadQueue(); nuclear@1: nuclear@1: if (!waitFlag) nuclear@1: { nuclear@1: return queue->PushCall(this, &LatencyTestDeviceImpl::setStartTest, targetColor); nuclear@1: } nuclear@1: nuclear@1: if (!queue->PushCallAndWaitResult( this, nuclear@1: &LatencyTestDeviceImpl::setStartTest, nuclear@1: &result, nuclear@1: targetColor)) nuclear@1: { nuclear@1: return false; nuclear@1: } nuclear@1: nuclear@1: return result; nuclear@1: } nuclear@1: nuclear@1: bool LatencyTestDeviceImpl::setStartTest(const Color& targetColor) nuclear@1: { nuclear@1: LatencyTestStartTestImpl ltst(targetColor); nuclear@1: return GetInternalDevice()->SetFeatureReport(ltst.Buffer, LatencyTestStartTestImpl::PacketSize); nuclear@1: } nuclear@1: nuclear@1: bool LatencyTestDeviceImpl::SetDisplay(const OVR::LatencyTestDisplay& display, bool waitFlag) nuclear@1: { nuclear@1: bool result = false; nuclear@1: ThreadCommandQueue * queue = GetManagerImpl()->GetThreadQueue(); nuclear@1: nuclear@1: if (!waitFlag) nuclear@1: { nuclear@1: return queue->PushCall(this, &LatencyTestDeviceImpl::setDisplay, display); nuclear@1: } nuclear@1: nuclear@1: if (!queue->PushCallAndWaitResult( this, nuclear@1: &LatencyTestDeviceImpl::setDisplay, nuclear@1: &result, nuclear@1: display)) nuclear@1: { nuclear@1: return false; nuclear@1: } nuclear@1: nuclear@1: return result; nuclear@1: } nuclear@1: nuclear@1: bool LatencyTestDeviceImpl::setDisplay(const OVR::LatencyTestDisplay& display) nuclear@1: { nuclear@1: LatencyTestDisplayImpl ltd(display); nuclear@1: return GetInternalDevice()->SetFeatureReport(ltd.Buffer, LatencyTestDisplayImpl::PacketSize); nuclear@1: } nuclear@1: nuclear@1: void LatencyTestDeviceImpl::onLatencyTestSamplesMessage(LatencyTestSamplesMessage* message) nuclear@1: { nuclear@1: nuclear@1: if (message->Type != LatencyTestMessage_Samples) nuclear@1: return; nuclear@1: nuclear@1: LatencyTestSamples& s = message->Samples; nuclear@1: nuclear@1: // Call OnMessage() within a lock to avoid conflicts with handlers. nuclear@1: Lock::Locker scopeLock(HandlerRef.GetLock()); nuclear@1: nuclear@1: if (HandlerRef.GetHandler()) nuclear@1: { nuclear@1: MessageLatencyTestSamples samples(this); nuclear@1: for (UByte i = 0; i < s.SampleCount; i++) nuclear@1: { nuclear@1: samples.Samples.PushBack(Color(s.Samples[i].Value[0], s.Samples[i].Value[1], s.Samples[i].Value[2])); nuclear@1: } nuclear@1: nuclear@1: HandlerRef.GetHandler()->OnMessage(samples); nuclear@1: } nuclear@1: } nuclear@1: nuclear@1: void LatencyTestDeviceImpl::onLatencyTestColorDetectedMessage(LatencyTestColorDetectedMessage* message) nuclear@1: { nuclear@1: if (message->Type != LatencyTestMessage_ColorDetected) nuclear@1: return; nuclear@1: nuclear@1: LatencyTestColorDetected& s = message->ColorDetected; nuclear@1: nuclear@1: // Call OnMessage() within a lock to avoid conflicts with handlers. nuclear@1: Lock::Locker scopeLock(HandlerRef.GetLock()); nuclear@1: nuclear@1: if (HandlerRef.GetHandler()) nuclear@1: { nuclear@1: MessageLatencyTestColorDetected detected(this); nuclear@1: detected.Elapsed = s.Elapsed; nuclear@1: detected.DetectedValue = Color(s.TriggerValue[0], s.TriggerValue[1], s.TriggerValue[2]); nuclear@1: detected.TargetValue = Color(s.TargetValue[0], s.TargetValue[1], s.TargetValue[2]); nuclear@1: nuclear@1: HandlerRef.GetHandler()->OnMessage(detected); nuclear@1: } nuclear@1: } nuclear@1: nuclear@1: void LatencyTestDeviceImpl::onLatencyTestStartedMessage(LatencyTestStartedMessage* message) nuclear@1: { nuclear@1: if (message->Type != LatencyTestMessage_TestStarted) nuclear@1: return; nuclear@1: nuclear@1: LatencyTestStarted& ts = message->TestStarted; nuclear@1: nuclear@1: // Call OnMessage() within a lock to avoid conflicts with handlers. nuclear@1: Lock::Locker scopeLock(HandlerRef.GetLock()); nuclear@1: nuclear@1: if (HandlerRef.GetHandler()) nuclear@1: { nuclear@1: MessageLatencyTestStarted started(this); nuclear@1: started.TargetValue = Color(ts.TargetValue[0], ts.TargetValue[1], ts.TargetValue[2]); nuclear@1: nuclear@1: HandlerRef.GetHandler()->OnMessage(started); nuclear@1: } nuclear@1: } nuclear@1: nuclear@1: void LatencyTestDeviceImpl::onLatencyTestButtonMessage(LatencyTestButtonMessage* message) nuclear@1: { nuclear@1: if (message->Type != LatencyTestMessage_Button) nuclear@1: return; nuclear@1: nuclear@1: // LatencyTestButton& s = message->Button; nuclear@1: nuclear@1: // Call OnMessage() within a lock to avoid conflicts with handlers. nuclear@1: Lock::Locker scopeLock(HandlerRef.GetLock()); nuclear@1: nuclear@1: if (HandlerRef.GetHandler()) nuclear@1: { nuclear@1: MessageLatencyTestButton button(this); nuclear@1: nuclear@1: HandlerRef.GetHandler()->OnMessage(button); nuclear@1: } nuclear@1: } nuclear@1: nuclear@1: } // namespace OVR