oculus1

view libovr/Src/OVR_LatencyTestImpl.cpp @ 17:cfe4979ab3eb

ops, minor error in the last commit
author John Tsiombikas <nuclear@member.fsf.org>
date Sat, 21 Sep 2013 07:09:48 +0300
parents
children
line source
1 /************************************************************************************
3 Filename : OVR_LatencyTestImpl.cpp
4 Content : Oculus Latency Tester device implementation.
5 Created : March 7, 2013
6 Authors : Lee Cooper
8 Copyright : Copyright 2013 Oculus VR, Inc. All Rights reserved.
10 Use of this software is subject to the terms of the Oculus license
11 agreement provided at the time of installation or download, or which
12 otherwise accompanies this software in either electronic or hard copy form.
14 *************************************************************************************/
16 #include "OVR_LatencyTestImpl.h"
18 namespace OVR {
20 //-------------------------------------------------------------------------------------
21 // ***** Oculus Latency Tester specific packet data structures
23 enum {
24 LatencyTester_VendorId = Oculus_VendorId,
25 LatencyTester_ProductId = 0x0101,
26 };
28 // Reported data is little-endian now
29 static UInt16 DecodeUInt16(const UByte* buffer)
30 {
31 return (UInt16(buffer[1]) << 8) | UInt16(buffer[0]);
32 }
34 /* Unreferenced
35 static SInt16 DecodeSInt16(const UByte* buffer)
36 {
37 return (SInt16(buffer[1]) << 8) | SInt16(buffer[0]);
38 }*/
40 static void UnpackSamples(const UByte* buffer, UByte* r, UByte* g, UByte* b)
41 {
42 *r = buffer[0];
43 *g = buffer[1];
44 *b = buffer[2];
45 }
47 // Messages we handle.
48 enum LatencyTestMessageType
49 {
50 LatencyTestMessage_None = 0,
51 LatencyTestMessage_Samples = 1,
52 LatencyTestMessage_ColorDetected = 2,
53 LatencyTestMessage_TestStarted = 3,
54 LatencyTestMessage_Button = 4,
55 LatencyTestMessage_Unknown = 0x100,
56 LatencyTestMessage_SizeError = 0x101,
57 };
59 struct LatencyTestSample
60 {
61 UByte Value[3];
62 };
64 struct LatencyTestSamples
65 {
66 UByte SampleCount;
67 UInt16 Timestamp;
69 LatencyTestSample Samples[20];
71 LatencyTestMessageType Decode(const UByte* buffer, int size)
72 {
73 if (size < 64)
74 {
75 return LatencyTestMessage_SizeError;
76 }
78 SampleCount = buffer[1];
79 Timestamp = DecodeUInt16(buffer + 2);
81 for (UByte i = 0; i < SampleCount; i++)
82 {
83 UnpackSamples(buffer + 4 + (3 * i), &Samples[i].Value[0], &Samples[i].Value[1], &Samples[i].Value[2]);
84 }
86 return LatencyTestMessage_Samples;
87 }
88 };
90 struct LatencyTestSamplesMessage
91 {
92 LatencyTestMessageType Type;
93 LatencyTestSamples Samples;
94 };
96 bool DecodeLatencyTestSamplesMessage(LatencyTestSamplesMessage* message, UByte* buffer, int size)
97 {
98 memset(message, 0, sizeof(LatencyTestSamplesMessage));
100 if (size < 64)
101 {
102 message->Type = LatencyTestMessage_SizeError;
103 return false;
104 }
106 switch (buffer[0])
107 {
108 case LatencyTestMessage_Samples:
109 message->Type = message->Samples.Decode(buffer, size);
110 break;
112 default:
113 message->Type = LatencyTestMessage_Unknown;
114 break;
115 }
117 return (message->Type < LatencyTestMessage_Unknown) && (message->Type != LatencyTestMessage_None);
118 }
120 struct LatencyTestColorDetected
121 {
122 UInt16 CommandID;
123 UInt16 Timestamp;
124 UInt16 Elapsed;
125 UByte TriggerValue[3];
126 UByte TargetValue[3];
128 LatencyTestMessageType Decode(const UByte* buffer, int size)
129 {
130 if (size < 13)
131 return LatencyTestMessage_SizeError;
133 CommandID = DecodeUInt16(buffer + 1);
134 Timestamp = DecodeUInt16(buffer + 3);
135 Elapsed = DecodeUInt16(buffer + 5);
136 memcpy(TriggerValue, buffer + 7, 3);
137 memcpy(TargetValue, buffer + 10, 3);
139 return LatencyTestMessage_ColorDetected;
140 }
141 };
143 struct LatencyTestColorDetectedMessage
144 {
145 LatencyTestMessageType Type;
146 LatencyTestColorDetected ColorDetected;
147 };
149 bool DecodeLatencyTestColorDetectedMessage(LatencyTestColorDetectedMessage* message, UByte* buffer, int size)
150 {
151 memset(message, 0, sizeof(LatencyTestColorDetectedMessage));
153 if (size < 13)
154 {
155 message->Type = LatencyTestMessage_SizeError;
156 return false;
157 }
159 switch (buffer[0])
160 {
161 case LatencyTestMessage_ColorDetected:
162 message->Type = message->ColorDetected.Decode(buffer, size);
163 break;
165 default:
166 message->Type = LatencyTestMessage_Unknown;
167 break;
168 }
170 return (message->Type < LatencyTestMessage_Unknown) && (message->Type != LatencyTestMessage_None);
171 }
173 struct LatencyTestStarted
174 {
175 UInt16 CommandID;
176 UInt16 Timestamp;
177 UByte TargetValue[3];
179 LatencyTestMessageType Decode(const UByte* buffer, int size)
180 {
181 if (size < 8)
182 return LatencyTestMessage_SizeError;
184 CommandID = DecodeUInt16(buffer + 1);
185 Timestamp = DecodeUInt16(buffer + 3);
186 memcpy(TargetValue, buffer + 5, 3);
188 return LatencyTestMessage_TestStarted;
189 }
190 };
192 struct LatencyTestStartedMessage
193 {
194 LatencyTestMessageType Type;
195 LatencyTestStarted TestStarted;
196 };
198 bool DecodeLatencyTestStartedMessage(LatencyTestStartedMessage* message, UByte* buffer, int size)
199 {
200 memset(message, 0, sizeof(LatencyTestStartedMessage));
202 if (size < 8)
203 {
204 message->Type = LatencyTestMessage_SizeError;
205 return false;
206 }
208 switch (buffer[0])
209 {
210 case LatencyTestMessage_TestStarted:
211 message->Type = message->TestStarted.Decode(buffer, size);
212 break;
214 default:
215 message->Type = LatencyTestMessage_Unknown;
216 break;
217 }
219 return (message->Type < LatencyTestMessage_Unknown) && (message->Type != LatencyTestMessage_None);
220 }
222 struct LatencyTestButton
223 {
224 UInt16 CommandID;
225 UInt16 Timestamp;
227 LatencyTestMessageType Decode(const UByte* buffer, int size)
228 {
229 if (size < 5)
230 return LatencyTestMessage_SizeError;
232 CommandID = DecodeUInt16(buffer + 1);
233 Timestamp = DecodeUInt16(buffer + 3);
235 return LatencyTestMessage_Button;
236 }
237 };
239 struct LatencyTestButtonMessage
240 {
241 LatencyTestMessageType Type;
242 LatencyTestButton Button;
243 };
245 bool DecodeLatencyTestButtonMessage(LatencyTestButtonMessage* message, UByte* buffer, int size)
246 {
247 memset(message, 0, sizeof(LatencyTestButtonMessage));
249 if (size < 5)
250 {
251 message->Type = LatencyTestMessage_SizeError;
252 return false;
253 }
255 switch (buffer[0])
256 {
257 case LatencyTestMessage_Button:
258 message->Type = message->Button.Decode(buffer, size);
259 break;
261 default:
262 message->Type = LatencyTestMessage_Unknown;
263 break;
264 }
266 return (message->Type < LatencyTestMessage_Unknown) && (message->Type != LatencyTestMessage_None);
267 }
269 struct LatencyTestConfigurationImpl
270 {
271 enum { PacketSize = 5 };
272 UByte Buffer[PacketSize];
274 OVR::LatencyTestConfiguration Configuration;
276 LatencyTestConfigurationImpl(const OVR::LatencyTestConfiguration& configuration)
277 : Configuration(configuration)
278 {
279 Pack();
280 }
282 void Pack()
283 {
284 Buffer[0] = 5;
285 Buffer[1] = UByte(Configuration.SendSamples);
286 Buffer[2] = Configuration.Threshold.R;
287 Buffer[3] = Configuration.Threshold.G;
288 Buffer[4] = Configuration.Threshold.B;
289 }
291 void Unpack()
292 {
293 Configuration.SendSamples = Buffer[1] != 0 ? true : false;
294 Configuration.Threshold.R = Buffer[2];
295 Configuration.Threshold.G = Buffer[3];
296 Configuration.Threshold.B = Buffer[4];
297 }
298 };
300 struct LatencyTestCalibrateImpl
301 {
302 enum { PacketSize = 4 };
303 UByte Buffer[PacketSize];
305 Color CalibrationColor;
307 LatencyTestCalibrateImpl(const Color& calibrationColor)
308 : CalibrationColor(calibrationColor)
309 {
310 Pack();
311 }
313 void Pack()
314 {
315 Buffer[0] = 7;
316 Buffer[1] = CalibrationColor.R;
317 Buffer[2] = CalibrationColor.G;
318 Buffer[3] = CalibrationColor.B;
319 }
321 void Unpack()
322 {
323 CalibrationColor.R = Buffer[1];
324 CalibrationColor.G = Buffer[2];
325 CalibrationColor.B = Buffer[3];
326 }
327 };
329 struct LatencyTestStartTestImpl
330 {
331 enum { PacketSize = 6 };
332 UByte Buffer[PacketSize];
334 Color TargetColor;
336 LatencyTestStartTestImpl(const Color& targetColor)
337 : TargetColor(targetColor)
338 {
339 Pack();
340 }
342 void Pack()
343 {
344 UInt16 commandID = 1;
346 Buffer[0] = 8;
347 Buffer[1] = UByte(commandID & 0xFF);
348 Buffer[2] = UByte(commandID >> 8);
349 Buffer[3] = TargetColor.R;
350 Buffer[4] = TargetColor.G;
351 Buffer[5] = TargetColor.B;
352 }
354 void Unpack()
355 {
356 // UInt16 commandID = Buffer[1] | (UInt16(Buffer[2]) << 8);
357 TargetColor.R = Buffer[3];
358 TargetColor.G = Buffer[4];
359 TargetColor.B = Buffer[5];
360 }
361 };
363 struct LatencyTestDisplayImpl
364 {
365 enum { PacketSize = 6 };
366 UByte Buffer[PacketSize];
368 OVR::LatencyTestDisplay Display;
370 LatencyTestDisplayImpl(const OVR::LatencyTestDisplay& display)
371 : Display(display)
372 {
373 Pack();
374 }
376 void Pack()
377 {
378 Buffer[0] = 9;
379 Buffer[1] = Display.Mode;
380 Buffer[2] = UByte(Display.Value & 0xFF);
381 Buffer[3] = UByte((Display.Value >> 8) & 0xFF);
382 Buffer[4] = UByte((Display.Value >> 16) & 0xFF);
383 Buffer[5] = UByte((Display.Value >> 24) & 0xFF);
384 }
386 void Unpack()
387 {
388 Display.Mode = Buffer[1];
389 Display.Value = UInt32(Buffer[2]) |
390 (UInt32(Buffer[3]) << 8) |
391 (UInt32(Buffer[4]) << 16) |
392 (UInt32(Buffer[5]) << 24);
393 }
394 };
396 //-------------------------------------------------------------------------------------
397 // ***** LatencyTestDeviceFactory
399 LatencyTestDeviceFactory LatencyTestDeviceFactory::Instance;
401 void LatencyTestDeviceFactory::EnumerateDevices(EnumerateVisitor& visitor)
402 {
404 class LatencyTestEnumerator : public HIDEnumerateVisitor
405 {
406 // Assign not supported; suppress MSVC warning.
407 void operator = (const LatencyTestEnumerator&) { }
409 DeviceFactory* pFactory;
410 EnumerateVisitor& ExternalVisitor;
411 public:
412 LatencyTestEnumerator(DeviceFactory* factory, EnumerateVisitor& externalVisitor)
413 : pFactory(factory), ExternalVisitor(externalVisitor) { }
415 virtual bool MatchVendorProduct(UInt16 vendorId, UInt16 productId)
416 {
417 return pFactory->MatchVendorProduct(vendorId, productId);
418 }
420 virtual void Visit(HIDDevice& device, const HIDDeviceDesc& desc)
421 {
422 OVR_UNUSED(device);
424 LatencyTestDeviceCreateDesc createDesc(pFactory, desc);
425 ExternalVisitor.Visit(createDesc);
426 }
427 };
429 LatencyTestEnumerator latencyTestEnumerator(this, visitor);
430 GetManagerImpl()->GetHIDDeviceManager()->Enumerate(&latencyTestEnumerator);
431 }
433 bool LatencyTestDeviceFactory::MatchVendorProduct(UInt16 vendorId, UInt16 productId) const
434 {
435 return ((vendorId == LatencyTester_VendorId) && (productId == LatencyTester_ProductId));
436 }
438 bool LatencyTestDeviceFactory::DetectHIDDevice(DeviceManager* pdevMgr,
439 const HIDDeviceDesc& desc)
440 {
441 if (MatchVendorProduct(desc.VendorId, desc.ProductId))
442 {
443 LatencyTestDeviceCreateDesc createDesc(this, desc);
444 return pdevMgr->AddDevice_NeedsLock(createDesc).GetPtr() != NULL;
445 }
446 return false;
447 }
449 //-------------------------------------------------------------------------------------
450 // ***** LatencyTestDeviceCreateDesc
452 DeviceBase* LatencyTestDeviceCreateDesc::NewDeviceInstance()
453 {
454 return new LatencyTestDeviceImpl(this);
455 }
457 bool LatencyTestDeviceCreateDesc::GetDeviceInfo(DeviceInfo* info) const
458 {
459 if ((info->InfoClassType != Device_LatencyTester) &&
460 (info->InfoClassType != Device_None))
461 return false;
463 OVR_strcpy(info->ProductName, DeviceInfo::MaxNameLength, HIDDesc.Product.ToCStr());
464 OVR_strcpy(info->Manufacturer, DeviceInfo::MaxNameLength, HIDDesc.Manufacturer.ToCStr());
465 info->Type = Device_LatencyTester;
466 info->Version = 0;
468 if (info->InfoClassType == Device_LatencyTester)
469 {
470 SensorInfo* sinfo = (SensorInfo*)info;
471 sinfo->VendorId = HIDDesc.VendorId;
472 sinfo->ProductId = HIDDesc.ProductId;
473 OVR_strcpy(sinfo->SerialNumber, sizeof(sinfo->SerialNumber),HIDDesc.SerialNumber.ToCStr());
474 }
475 return true;
476 }
478 //-------------------------------------------------------------------------------------
479 // ***** LatencyTestDevice
481 LatencyTestDeviceImpl::LatencyTestDeviceImpl(LatencyTestDeviceCreateDesc* createDesc)
482 : OVR::HIDDeviceImpl<OVR::LatencyTestDevice>(createDesc, 0)
483 {
484 }
486 LatencyTestDeviceImpl::~LatencyTestDeviceImpl()
487 {
488 // Check that Shutdown() was called.
489 OVR_ASSERT(!pCreateDesc->pDevice);
490 }
492 // Internal creation APIs.
493 bool LatencyTestDeviceImpl::Initialize(DeviceBase* parent)
494 {
495 if (HIDDeviceImpl<OVR::LatencyTestDevice>::Initialize(parent))
496 {
497 LogText("OVR::LatencyTestDevice initialized.\n");
498 return true;
499 }
501 return false;
502 }
504 void LatencyTestDeviceImpl::Shutdown()
505 {
506 HIDDeviceImpl<OVR::LatencyTestDevice>::Shutdown();
508 LogText("OVR::LatencyTestDevice - Closed '%s'\n", getHIDDesc()->Path.ToCStr());
509 }
511 void LatencyTestDeviceImpl::OnInputReport(UByte* pData, UInt32 length)
512 {
514 bool processed = false;
515 if (!processed)
516 {
517 LatencyTestSamplesMessage message;
518 if (DecodeLatencyTestSamplesMessage(&message, pData, length))
519 {
520 processed = true;
521 onLatencyTestSamplesMessage(&message);
522 }
523 }
525 if (!processed)
526 {
527 LatencyTestColorDetectedMessage message;
528 if (DecodeLatencyTestColorDetectedMessage(&message, pData, length))
529 {
530 processed = true;
531 onLatencyTestColorDetectedMessage(&message);
532 }
533 }
535 if (!processed)
536 {
537 LatencyTestStartedMessage message;
538 if (DecodeLatencyTestStartedMessage(&message, pData, length))
539 {
540 processed = true;
541 onLatencyTestStartedMessage(&message);
542 }
543 }
545 if (!processed)
546 {
547 LatencyTestButtonMessage message;
548 if (DecodeLatencyTestButtonMessage(&message, pData, length))
549 {
550 processed = true;
551 onLatencyTestButtonMessage(&message);
552 }
553 }
554 }
556 bool LatencyTestDeviceImpl::SetConfiguration(const OVR::LatencyTestConfiguration& configuration, bool waitFlag)
557 {
558 bool result = false;
559 ThreadCommandQueue* queue = GetManagerImpl()->GetThreadQueue();
561 if (GetManagerImpl()->GetThreadId() != OVR::GetCurrentThreadId())
562 {
563 if (!waitFlag)
564 {
565 return queue->PushCall(this, &LatencyTestDeviceImpl::setConfiguration, configuration);
566 }
568 if (!queue->PushCallAndWaitResult( this,
569 &LatencyTestDeviceImpl::setConfiguration,
570 &result,
571 configuration))
572 {
573 return false;
574 }
575 }
576 else
577 return setConfiguration(configuration);
579 return result;
580 }
582 bool LatencyTestDeviceImpl::setConfiguration(const OVR::LatencyTestConfiguration& configuration)
583 {
584 LatencyTestConfigurationImpl ltc(configuration);
585 return GetInternalDevice()->SetFeatureReport(ltc.Buffer, LatencyTestConfigurationImpl::PacketSize);
586 }
588 bool LatencyTestDeviceImpl::GetConfiguration(OVR::LatencyTestConfiguration* configuration)
589 {
590 bool result = false;
592 ThreadCommandQueue* pQueue = this->GetManagerImpl()->GetThreadQueue();
593 if (!pQueue->PushCallAndWaitResult(this, &LatencyTestDeviceImpl::getConfiguration, &result, configuration))
594 return false;
596 return result;
597 }
599 bool LatencyTestDeviceImpl::getConfiguration(OVR::LatencyTestConfiguration* configuration)
600 {
601 LatencyTestConfigurationImpl ltc(*configuration);
602 if (GetInternalDevice()->GetFeatureReport(ltc.Buffer, LatencyTestConfigurationImpl::PacketSize))
603 {
604 ltc.Unpack();
605 *configuration = ltc.Configuration;
606 return true;
607 }
609 return false;
610 }
612 bool LatencyTestDeviceImpl::SetCalibrate(const Color& calibrationColor, bool waitFlag)
613 {
614 bool result = false;
615 ThreadCommandQueue* queue = GetManagerImpl()->GetThreadQueue();
617 if (!waitFlag)
618 {
619 return queue->PushCall(this, &LatencyTestDeviceImpl::setCalibrate, calibrationColor);
620 }
622 if (!queue->PushCallAndWaitResult( this,
623 &LatencyTestDeviceImpl::setCalibrate,
624 &result,
625 calibrationColor))
626 {
627 return false;
628 }
630 return result;
631 }
633 bool LatencyTestDeviceImpl::setCalibrate(const Color& calibrationColor)
634 {
635 LatencyTestCalibrateImpl ltc(calibrationColor);
636 return GetInternalDevice()->SetFeatureReport(ltc.Buffer, LatencyTestCalibrateImpl::PacketSize);
637 }
639 bool LatencyTestDeviceImpl::SetStartTest(const Color& targetColor, bool waitFlag)
640 {
641 bool result = false;
642 ThreadCommandQueue* queue = GetManagerImpl()->GetThreadQueue();
644 if (!waitFlag)
645 {
646 return queue->PushCall(this, &LatencyTestDeviceImpl::setStartTest, targetColor);
647 }
649 if (!queue->PushCallAndWaitResult( this,
650 &LatencyTestDeviceImpl::setStartTest,
651 &result,
652 targetColor))
653 {
654 return false;
655 }
657 return result;
658 }
660 bool LatencyTestDeviceImpl::setStartTest(const Color& targetColor)
661 {
662 LatencyTestStartTestImpl ltst(targetColor);
663 return GetInternalDevice()->SetFeatureReport(ltst.Buffer, LatencyTestStartTestImpl::PacketSize);
664 }
666 bool LatencyTestDeviceImpl::SetDisplay(const OVR::LatencyTestDisplay& display, bool waitFlag)
667 {
668 bool result = false;
669 ThreadCommandQueue * queue = GetManagerImpl()->GetThreadQueue();
671 if (!waitFlag)
672 {
673 return queue->PushCall(this, &LatencyTestDeviceImpl::setDisplay, display);
674 }
676 if (!queue->PushCallAndWaitResult( this,
677 &LatencyTestDeviceImpl::setDisplay,
678 &result,
679 display))
680 {
681 return false;
682 }
684 return result;
685 }
687 bool LatencyTestDeviceImpl::setDisplay(const OVR::LatencyTestDisplay& display)
688 {
689 LatencyTestDisplayImpl ltd(display);
690 return GetInternalDevice()->SetFeatureReport(ltd.Buffer, LatencyTestDisplayImpl::PacketSize);
691 }
693 void LatencyTestDeviceImpl::onLatencyTestSamplesMessage(LatencyTestSamplesMessage* message)
694 {
696 if (message->Type != LatencyTestMessage_Samples)
697 return;
699 LatencyTestSamples& s = message->Samples;
701 // Call OnMessage() within a lock to avoid conflicts with handlers.
702 Lock::Locker scopeLock(HandlerRef.GetLock());
704 if (HandlerRef.GetHandler())
705 {
706 MessageLatencyTestSamples samples(this);
707 for (UByte i = 0; i < s.SampleCount; i++)
708 {
709 samples.Samples.PushBack(Color(s.Samples[i].Value[0], s.Samples[i].Value[1], s.Samples[i].Value[2]));
710 }
712 HandlerRef.GetHandler()->OnMessage(samples);
713 }
714 }
716 void LatencyTestDeviceImpl::onLatencyTestColorDetectedMessage(LatencyTestColorDetectedMessage* message)
717 {
718 if (message->Type != LatencyTestMessage_ColorDetected)
719 return;
721 LatencyTestColorDetected& s = message->ColorDetected;
723 // Call OnMessage() within a lock to avoid conflicts with handlers.
724 Lock::Locker scopeLock(HandlerRef.GetLock());
726 if (HandlerRef.GetHandler())
727 {
728 MessageLatencyTestColorDetected detected(this);
729 detected.Elapsed = s.Elapsed;
730 detected.DetectedValue = Color(s.TriggerValue[0], s.TriggerValue[1], s.TriggerValue[2]);
731 detected.TargetValue = Color(s.TargetValue[0], s.TargetValue[1], s.TargetValue[2]);
733 HandlerRef.GetHandler()->OnMessage(detected);
734 }
735 }
737 void LatencyTestDeviceImpl::onLatencyTestStartedMessage(LatencyTestStartedMessage* message)
738 {
739 if (message->Type != LatencyTestMessage_TestStarted)
740 return;
742 LatencyTestStarted& ts = message->TestStarted;
744 // Call OnMessage() within a lock to avoid conflicts with handlers.
745 Lock::Locker scopeLock(HandlerRef.GetLock());
747 if (HandlerRef.GetHandler())
748 {
749 MessageLatencyTestStarted started(this);
750 started.TargetValue = Color(ts.TargetValue[0], ts.TargetValue[1], ts.TargetValue[2]);
752 HandlerRef.GetHandler()->OnMessage(started);
753 }
754 }
756 void LatencyTestDeviceImpl::onLatencyTestButtonMessage(LatencyTestButtonMessage* message)
757 {
758 if (message->Type != LatencyTestMessage_Button)
759 return;
761 // LatencyTestButton& s = message->Button;
763 // Call OnMessage() within a lock to avoid conflicts with handlers.
764 Lock::Locker scopeLock(HandlerRef.GetLock());
766 if (HandlerRef.GetHandler())
767 {
768 MessageLatencyTestButton button(this);
770 HandlerRef.GetHandler()->OnMessage(button);
771 }
772 }
774 } // namespace OVR