From 10b16d2ff540bcdddbc41027b0b70764f7084119 Mon Sep 17 00:00:00 2001 From: Ryan Pavlik Date: Tue, 28 Jun 2016 11:08:56 -0500 Subject: [PATCH 01/11] Add SPDX meta tag to property traits file generator output. --- GenerateTypedPropertyEnums.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/GenerateTypedPropertyEnums.cpp b/GenerateTypedPropertyEnums.cpp index 857883e..0714db9 100644 --- a/GenerateTypedPropertyEnums.cpp +++ b/GenerateTypedPropertyEnums.cpp @@ -57,6 +57,8 @@ static const auto startOfOutput = R"(/** @file /* Copyright 2016 Razer Inc. +SPDX-License-Identifier: BSD-3-Clause + OpenVR input data: Copyright (c) 2015, Valve Corporation All rights reserved. From 2067d4f977700f4c606750287440787446368aff Mon Sep 17 00:00:00 2001 From: Ryan Pavlik Date: Tue, 28 Jun 2016 11:09:59 -0500 Subject: [PATCH 02/11] Adjust the licenses on the property traits helper files to also be bsd 3 clause --- PropertyHelper.h | 49 +++++++++++++++++++++++++++++------------ ServerPropertyHelper.h | 50 ++++++++++++++++++++++++++++++------------ 2 files changed, 71 insertions(+), 28 deletions(-) diff --git a/PropertyHelper.h b/PropertyHelper.h index 65e4740..c2d00ce 100644 --- a/PropertyHelper.h +++ b/PropertyHelper.h @@ -1,5 +1,7 @@ /** @file - @brief Header + @brief Header designed to build on the generated PropertyTraits.h header. + + BSD-3-Clause to match the "OpenVR" and thus PropertyTraits.h license. @date 2016 @@ -8,25 +10,44 @@ */ -// Copyright 2016 Razer Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* +SPDX-License-Identifier: BSD-3-Clause + +Copyright (c) 2016, Razer Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its contributors +may be used to endorse or promote products derived from this software without +specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ #ifndef INCLUDED_PropertyHelper_h_GUID_08BEA00F_2E0C_4FA5_DF5B_31BE33EF27A3 #define INCLUDED_PropertyHelper_h_GUID_08BEA00F_2E0C_4FA5_DF5B_31BE33EF27A3 #include +// Include the generated file #include "PropertyTraits.h" // Standard includes diff --git a/ServerPropertyHelper.h b/ServerPropertyHelper.h index acb4946..f3bc57a 100644 --- a/ServerPropertyHelper.h +++ b/ServerPropertyHelper.h @@ -1,5 +1,7 @@ /** @file - @brief Header + @brief Header based on PropertyHelper for users of openvr_driver.h + + BSD-3-Clause to match the "OpenVR" and thus PropertyTraits.h license. @date 2016 @@ -8,25 +10,45 @@ */ -// Copyright 2016 Sensics, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* +SPDX-License-Identifier: BSD-3-Clause + +Copyright (c) 2016, Sensics, Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its contributors +may be used to endorse or promote products derived from this software without +specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ #ifndef INCLUDED_ServerPropertyHelper_h_GUID_9835023A_E639_409F_3A68_CFB4029FBBE7 #define INCLUDED_ServerPropertyHelper_h_GUID_9835023A_E639_409F_3A68_CFB4029FBBE7 +// OpenVR header #include +// PropertyHelper (and transitively, the generated traits header) #include "PropertyHelper.h" namespace osvr { From 05af30bdf809f2b02007119869582a7263c2f519 Mon Sep 17 00:00:00 2001 From: Ryan Pavlik Date: Tue, 28 Jun 2016 16:16:09 -0500 Subject: [PATCH 03/11] Be able to signal both temporary and permanent (driver version mismatch) failure from Vive driver object --- OSVRViveTracker.cpp | 12 +++++++----- OSVRViveTracker.h | 5 +++-- com_osvr_Vive.cpp | 17 ++++++++++++----- 3 files changed, 22 insertions(+), 12 deletions(-) diff --git a/OSVRViveTracker.cpp b/OSVRViveTracker.cpp index c10a3c7..8664642 100644 --- a/OSVRViveTracker.cpp +++ b/OSVRViveTracker.cpp @@ -117,12 +117,14 @@ namespace vive { : m_universeXform(Eigen::Isometry3d::Identity()), m_universeRotation(Eigen::Quaterniond::Identity()) {} - bool ViveDriverHost::start(OSVR_PluginRegContext ctx, - osvr::vive::DriverWrapper &&inVive) { + ViveDriverHost::StartResult + ViveDriverHost::start(OSVR_PluginRegContext ctx, + osvr::vive::DriverWrapper &&inVive) { if (!inVive) { std::cerr << PREFIX << "Error: called ViveDriverHost::start() with " "an invalid vive object!" << std::endl; + return StartResult::TemporaryFailure; } /// Take ownership of the Vive. m_vive.reset(new osvr::vive::DriverWrapper(std::move(inVive))); @@ -134,7 +136,7 @@ namespace vive { "device provider in the " "Vive driver. Exiting." << std::endl; - return false; + return StartResult::TemporaryFailure; } } catch (CouldNotGetInterface &e) { std::cerr << PREFIX @@ -145,7 +147,7 @@ namespace vive { "changed, may need to be rebuilt against an updated " "header or use an older SteamVR version. Exiting." << std::endl; - return false; + return StartResult::PermanentFailure; } /// Power the system up. @@ -221,7 +223,7 @@ namespace vive { /// Register update callback m_dev.registerUpdateCallback(this); - return true; + return StartResult::Success; } inline OSVR_ReturnCode ViveDriverHost::update() { m_vive->serverDevProvider().RunFrame(); diff --git a/OSVRViveTracker.h b/OSVRViveTracker.h index f660885..657c994 100644 --- a/OSVRViveTracker.h +++ b/OSVRViveTracker.h @@ -87,9 +87,10 @@ namespace vive { EIGEN_MAKE_ALIGNED_OPERATOR_NEW ViveDriverHost(); + enum class StartResult { Success, TemporaryFailure, PermanentFailure }; /// @return false if we failed to start up for some reason. - bool start(OSVR_PluginRegContext ctx, - osvr::vive::DriverWrapper &&inVive); + StartResult start(OSVR_PluginRegContext ctx, + osvr::vive::DriverWrapper &&inVive); /// Standard OSVR device callback OSVR_ReturnCode update(); diff --git a/com_osvr_Vive.cpp b/com_osvr_Vive.cpp index c9a631e..5a2a89a 100644 --- a/com_osvr_Vive.cpp +++ b/com_osvr_Vive.cpp @@ -87,9 +87,11 @@ class HardwareDetection { return OSVR_RETURN_SUCCESS; } - std::cout << PREFIX << "Vive driver startup failed somewhere, " - "unloading to perhaps try again later." - << std::endl; + std::cout << "\n" << PREFIX << "Vive driver startup failed."; + if (m_shouldAttemptDetection) { + std::cout << " Unloading to perhaps try again later."; + } + std::cout << std::endl; unloadTemporaries(); return OSVR_RETURN_FAILURE; @@ -99,10 +101,15 @@ class HardwareDetection { auto startResult = m_inactiveDriverHost->start(ctx, std::move(*m_viveWrapper)); m_viveWrapper.reset(); - if (startResult) { + if (osvr::vive::ViveDriverHost::StartResult::Success == startResult) { m_driverHost = std::move(m_inactiveDriverHost); + return true; + } + if (osvr::vive::ViveDriverHost::StartResult::PermanentFailure == + startResult) { + stopAttemptingDetection(); } - return startResult; + return false; } /// Attempts the first part of startup, if required. From ad11c46792cd18f8096d770daaa99507dabc8055 Mon Sep 17 00:00:00 2001 From: Ryan Pavlik Date: Tue, 28 Jun 2016 15:46:12 -0500 Subject: [PATCH 04/11] Add return value header. --- CMakeLists.txt | 1 + ReturnValue.h | 110 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 111 insertions(+) create mode 100644 ReturnValue.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 465e2a9..dce551d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -95,6 +95,7 @@ add_library(ViveLoaderLib STATIC GetComponent.h GetProvider.h InterfaceTraits.h + ReturnValue.h SearchPathExtender.h ServerDriverHost.cpp ServerDriverHost.h diff --git a/ReturnValue.h b/ReturnValue.h new file mode 100644 index 0000000..c8035b0 --- /dev/null +++ b/ReturnValue.h @@ -0,0 +1,110 @@ +/** @file + @brief Header + + @date 2016 + + @author + Sensics, Inc. + +*/ + +// Copyright 2016 Sensics, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef INCLUDED_ReturnValue_h_GUID_B28A8BE9_541A_42AC_6925_C51C944B089E +#define INCLUDED_ReturnValue_h_GUID_B28A8BE9_541A_42AC_6925_C51C944B089E + +// Internal Includes +// - none + +// Library/third-party includes +// - none + +// Standard includes +// - none + +namespace osvr { +namespace vive { + struct ReturnValueBase { + ReturnValueBase() {} + ReturnValueBase(bool ok) : valid(ok) {} + + const bool valid = false; + + /// check validity by evaluating as a bool + explicit operator bool() const { return valid; } + }; + + template + struct ReturnValue : ReturnValueBase { + ReturnValue(ValueType const &val, ErrorCodeType err) + : ReturnValueBase(), value(val), errorCode(err) {} + ReturnValue(ValueType const &val, ErrorCodeType err, bool ok) + : ReturnValueBase(ok), value(val), errorCode(err) {} + + ValueType value = {}; + ErrorCodeType errorCode = {}; + + static ReturnValue makeError(ErrorCodeType err) { + return ReturnValue{{}, err}; + } + static ReturnValue makeValueFromRvalue(ValueType &&val) { + return ReturnValue{std::move(val), {}, true}; + } + static ReturnValue makeValue(ValueType val) { + return ReturnValue{val, {}, true}; + } + }; + + /// specialization for bool "error codes" + template + struct ReturnValue : ReturnValueBase { + ReturnValue(ValueType const &val) : ReturnValueBase(true), value(val) {} + ReturnValue(ValueType const &val, bool ok) + : ReturnValueBase(ok), value(val) {} + + ValueType value = {}; + + static ReturnValue makeError() { return ReturnValue{{}, false}; } + static ReturnValue makeValueFromRvalue(ValueType &&val) { + return ReturnValue{std::move(val), true}; + } + static ReturnValue makeValue(ValueType val) { + return ReturnValue{val, true}; + } + }; + + template + inline ReturnValue + makeGenericReturnValue(ValueType const &val, ErrorCodeType err, + bool valid) { + using type = ReturnValue; + return type(val, err, valid); + } + + template + inline ReturnValue makeError(ValueType const &val, + ErrorCodeType err) { + return makeGenericReturnValue(val, err, false); + } + + template + inline ReturnValue + makeReturnValue(ValueType const &val, ErrorCodeType err) { + return makeGenericReturnValue(val, err, true); + } + +} // namespace vive +} // namespace osvr +#endif // INCLUDED_ReturnValue_h_GUID_B28A8BE9_541A_42AC_6925_C51C944B089E From b1e710cf787f3bb410951abb639b132b7accc186 Mon Sep 17 00:00:00 2001 From: Ryan Pavlik Date: Tue, 28 Jun 2016 15:48:57 -0500 Subject: [PATCH 05/11] Use ReturnValue struct across the codebase. --- DeviceHolder.h | 50 ++++++++++++++++++++++++--------------------- DriverLoader.cpp | 6 +++--- DriverLoader.h | 15 +++++++------- OSVRViveTracker.cpp | 16 +++++++-------- OSVRViveTracker.h | 8 +++++--- ViveLoader.cpp | 4 ++-- 6 files changed, 53 insertions(+), 46 deletions(-) diff --git a/DeviceHolder.h b/DeviceHolder.h index d78e62a..0ab6bc9 100644 --- a/DeviceHolder.h +++ b/DeviceHolder.h @@ -26,7 +26,7 @@ #define INCLUDED_DeviceHolder_h_GUID_58F7E011_8D87_49A3_FE26_0DB159405E77 // Internal Includes -// - none +#include "ReturnValue.h" // Library/third-party includes #include @@ -77,40 +77,46 @@ namespace vive { return *this; } - std::pair + using IdReturnValue = ReturnValue; + + IdReturnValue addAndActivateDevice(vr::ITrackedDeviceServerDriver *dev) { /// check to make sure it's not null and not already in there - if (!dev || findDevice(dev).first) { - return std::make_pair(false, 0); + if (!dev) { + return IdReturnValue::makeError(); } - auto it = std::find(begin(devices_), end(devices_), dev); - if (it != end(devices_)) { + auto existing = findDevice(dev); + if (existing) { + /// @todo do we return an error or the existing location? This + /// returns the existing location after re-activating. + dev->Activate(existing.value); + return existing; } auto newId = static_cast(devices_.size()); devices_.push_back(dev); dev->Activate(newId); - return std::make_pair(true, newId); + return IdReturnValue::makeValue(newId); } /// Add and activate a device at a reserved id. - std::pair + IdReturnValue addAndActivateDeviceAt(vr::ITrackedDeviceServerDriver *dev, std::uint32_t idx) { /// check to make sure it's not null and not already in there if (!dev) { - return std::make_pair(false, 0); + return IdReturnValue::makeError(); } auto existing = findDevice(dev); - if (existing.first && !existing.second == idx) { + if (existing && existing.value != idx) { // if we already found it in there and it's not at the desired // index... - return std::make_pair(false, existing.second); + return IdReturnValue(existing.value, false); } - if (existing.first) { + if (existing) { // well, in this case, we might need to just activate it again. dev->Activate(idx); - return std::make_pair(true, idx); + return IdReturnValue::makeValue(idx); } if (!(idx < devices_.size())) { @@ -120,14 +126,14 @@ namespace vive { if (devices_[idx]) { // there's already somebody else there... - return std::make_pair(false, 0); + return IdReturnValue::makeError(); } /// Finally, if we made it through that, it's our turn. devices_[idx] = dev; dev->Activate(idx); - return std::make_pair(true, idx); + return IdReturnValue::makeValue(idx); } /// Reserve the first n ids, if not already allocated, for manual @@ -153,16 +159,14 @@ namespace vive { } /// @return a (found, index) pair for a non-null device pointer. - std::pair - findDevice(vr::ITrackedDeviceServerDriver *dev) { + IdReturnValue findDevice(vr::ITrackedDeviceServerDriver *dev) { - auto it = std::find(begin(devices_), end(devices_), dev); - if (it == end(devices_)) { - return std::make_pair(false, 0); + auto it = std::find(devices_.cbegin(), devices_.cend(), dev); + if (devices_.cend() == it) { + return IdReturnValue::makeError(); } - return std::make_pair( - true, - static_cast(std::distance(begin(devices_), it))); + return IdReturnValue::makeValue(static_cast( + std::distance(devices_.cbegin(), it))); } /// @return the number of allocated/reserved ids diff --git a/DriverLoader.cpp b/DriverLoader.cpp index 4a72a53..1986f34 100644 --- a/DriverLoader.cpp +++ b/DriverLoader.cpp @@ -129,17 +129,17 @@ namespace vive { bool DriverLoader::isHMDPresent(std::string const &userConfigDir) const { auto ret = getInterface(); - if (ret.first) { + if (ret) { // std::cout << "Successfully got the // IClientTrackedDeviceProvider!"; - auto clientProvider = ret.first; + auto clientProvider = ret.value; auto isPresent = clientProvider->BIsHmdPresent(userConfigDir.c_str()); // std::cout << " is present? " << std::boolalpha << isPresent // << std::endl; return isPresent; } - // std::cout << "Couldn't get it, error code " << ret.second << + // std::cout << "Couldn't get it, error code " << ret.errorCode << // std::endl; return false; } diff --git a/DriverLoader.h b/DriverLoader.h index bf30dfb..7d9a2e2 100644 --- a/DriverLoader.h +++ b/DriverLoader.h @@ -27,6 +27,7 @@ // Internal Includes #include "InterfaceTraits.h" +#include "ReturnValue.h" // Library/third-party includes // - none @@ -105,7 +106,7 @@ namespace vive { /// right string and do the right casting. Returns the pointer and /// the error code in a pair. template - std::pair getInterface() const { + ReturnValue getInterface() const { static_assert( InterfaceExpectedFromEntryPointTrait::value, "Can only use this function for interface types expected to be " @@ -115,14 +116,14 @@ namespace vive { int returnCode = 0; if (!(*this)) { /// We've been reset or could never load. - return std::make_pair(ret, returnCode); + return makeError(ret, returnCode); } void *product = factory_(InterfaceNameTrait::get(), &returnCode); if (product) { ret = static_cast(product); } - return std::make_pair(ret, returnCode); + return makeReturnValue(ret, returnCode); } /// Similar to the above, except that it throws in case of failure, @@ -130,15 +131,15 @@ namespace vive { /// always non-null. template InterfaceType *getInterfaceThrowing() const { - auto pairRet = getInterface(); + auto ret = getInterface(); if (!(*this)) { /// we early-out throw DriverNotLoaded(); } - if (!pairRet.first) { - throw CouldNotGetInterface(pairRet.second); + if (!ret) { + throw CouldNotGetInterface(ret.errorCode); } - return pairRet.first; + return ret.value; } std::string const &getDriverRoot() const { return driverRoot_; } diff --git a/OSVRViveTracker.cpp b/OSVRViveTracker.cpp index 8664642..49fc175 100644 --- a/OSVRViveTracker.cpp +++ b/OSVRViveTracker.cpp @@ -154,8 +154,8 @@ namespace vive { m_vive->serverDevProvider().LeaveStandby(); auto handleNewDevice = [&](const char *serialNum) { - auto dev = m_vive->serverDevProvider().FindTrackedDeviceDriver( - serialNum, vr::ITrackedDeviceServerDriver_Version); + auto dev = + m_vive->serverDevProvider().FindTrackedDeviceDriver(serialNum); if (!dev) { /// The only devices we usually can't look up by serial number /// seem to be the lighthouse base stations. @@ -172,13 +172,13 @@ namespace vive { return false; } auto ret = activateDevice(dev); - if (!ret.first) { + if (!ret) { std::cout << PREFIX << "Device with serial number " << serialNum << " couldn't be added to the devices vector." << std::endl; return false; } - NewDeviceReport out{std::string{serialNum}, ret.second}; + NewDeviceReport out{std::string{serialNum}, ret.value}; { std::lock_guard lock(m_mutex); m_newDevices.submitNew(std::move(out), lock); @@ -292,15 +292,15 @@ namespace vive { return OSVR_RETURN_SUCCESS; } - std::pair + ViveDriverHost::DevIdReturnValue ViveDriverHost::activateDevice(vr::ITrackedDeviceServerDriver *dev) { auto ret = activateDeviceImpl(dev); auto mfrProp = getProperty(dev); auto modelProp = getProperty(dev); auto serialProp = getProperty(dev); std::cout << PREFIX; - if (ret.first) { - std::cout << "Assigned sensor ID " << ret.second << " to "; + if (ret) { + std::cout << "Assigned sensor ID " << ret.value << " to "; } else { std::cout << "Could not assign a sensor ID to "; } @@ -309,7 +309,7 @@ namespace vive { return ret; } - std::pair + ViveDriverHost::DevIdReturnValue ViveDriverHost::activateDeviceImpl(vr::ITrackedDeviceServerDriver *dev) { auto &devs = m_vive->devices(); if (getComponent(dev)) { diff --git a/OSVRViveTracker.h b/OSVRViveTracker.h index 657c994..6c57f4d 100644 --- a/OSVRViveTracker.h +++ b/OSVRViveTracker.h @@ -28,6 +28,7 @@ // Internal Includes #include "QuickProcessingDeque.h" +#include "ReturnValue.h" #include "ServerDriverHost.h" #include #include @@ -87,7 +88,9 @@ namespace vive { EIGEN_MAKE_ALIGNED_OPERATOR_NEW ViveDriverHost(); + using DevIdReturnValue = ReturnValue; enum class StartResult { Success, TemporaryFailure, PermanentFailure }; + /// @return false if we failed to start up for some reason. StartResult start(OSVR_PluginRegContext ctx, osvr::vive::DriverWrapper &&inVive); @@ -98,8 +101,7 @@ namespace vive { /// Called when we get a new device from the SteamVR driver that we need /// to activate. Delegates the real work - this just displays /// information. - std::pair - activateDevice(vr::ITrackedDeviceServerDriver *dev); + DevIdReturnValue activateDevice(vr::ITrackedDeviceServerDriver *dev); /// @name ServerDriverHost overrides - called from a tracker thread (not /// the main thread) @@ -170,7 +172,7 @@ namespace vive { bool state); /// Does the real work of adding a new device. - std::pair + DevIdReturnValue activateDeviceImpl(vr::ITrackedDeviceServerDriver *dev); osvr::pluginkit::DeviceToken m_dev; diff --git a/ViveLoader.cpp b/ViveLoader.cpp index a039134..2cfc791 100644 --- a/ViveLoader.cpp +++ b/ViveLoader.cpp @@ -202,7 +202,7 @@ int main() { return false; } auto ret = vive.devices().addAndActivateDevice(dev); - if (!ret.first) { + if (!ret) { std::cout << PREFIX << "Device with serial number " << serialNum << " couldn't be added to the devices vector." << std::endl; @@ -210,7 +210,7 @@ int main() { } std::cout << "\n" << PREFIX << "Device with s/n " << serialNum - << " activated, assigned ID " << ret.second << std::endl; + << " activated, assigned ID " << ret.value << std::endl; whatIsThisDevice(dev); return true; }; From e20429e61f89320f203d329f2df3a780edd47fb5 Mon Sep 17 00:00:00 2001 From: Ryan Pavlik Date: Tue, 28 Jun 2016 11:13:12 -0500 Subject: [PATCH 06/11] Update OpenVR submodule version 1.0.1 --- vendor/openvr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/openvr b/vendor/openvr index f1ffbf4..e1507a2 160000 --- a/vendor/openvr +++ b/vendor/openvr @@ -1 +1 @@ -Subproject commit f1ffbf4e92f383bdb453d58f9583c51a5ec350d9 +Subproject commit e1507a27547d22a680153862865d40b90fad8c75 From a7a55dabde4c2be5eb1c9b367c5911c582a34af5 Mon Sep 17 00:00:00 2001 From: Ryan Pavlik Date: Tue, 28 Jun 2016 11:13:40 -0500 Subject: [PATCH 07/11] Update generated PropertyTraits --- PropertyTraits.h | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/PropertyTraits.h b/PropertyTraits.h index 40c007c..a34f442 100644 --- a/PropertyTraits.h +++ b/PropertyTraits.h @@ -11,6 +11,8 @@ /* Copyright 2016 Razer Inc. +SPDX-License-Identifier: BSD-3-Clause + OpenVR input data: Copyright (c) 2015, Valve Corporation All rights reserved. @@ -87,6 +89,9 @@ namespace vive { Firmware_ProgrammingTarget = vr::Prop_Firmware_ProgrammingTarget_String, DeviceClass = vr::Prop_DeviceClass_Int32, HasCamera = vr::Prop_HasCamera_Bool, + DriverVersion = vr::Prop_DriverVersion_String, + Firmware_ForceUpdateRequired = + vr::Prop_Firmware_ForceUpdateRequired_Bool, ReportsTimeSinceVSync = vr::Prop_ReportsTimeSinceVSync_Bool, SecondsFromVsyncToPhotons = vr::Prop_SecondsFromVsyncToPhotons_Float, DisplayFrequency = vr::Prop_DisplayFrequency_Float, @@ -121,6 +126,11 @@ namespace vive { DisplayHardwareVersion = vr::Prop_DisplayHardwareVersion_Uint64, AudioFirmwareVersion = vr::Prop_AudioFirmwareVersion_Uint64, CameraCompatibilityMode = vr::Prop_CameraCompatibilityMode_Int32, + ScreenshotHorizontalFieldOfViewDegrees = + vr::Prop_ScreenshotHorizontalFieldOfViewDegrees_Float, + ScreenshotVerticalFieldOfViewDegrees = + vr::Prop_ScreenshotVerticalFieldOfViewDegrees_Float, + DisplaySuppressed = vr::Prop_DisplaySuppressed_Bool, AttachedDeviceId = vr::Prop_AttachedDeviceId_String, SupportedButtons = vr::Prop_SupportedButtons_Uint64, Axis0Type = vr::Prop_Axis0Type_Int32, @@ -249,6 +259,13 @@ namespace vive { template <> struct PropertyTypeTrait { using type = bool; }; + template <> struct PropertyTypeTrait { + using type = std::string; + }; + template <> + struct PropertyTypeTrait { + using type = bool; + }; template <> struct PropertyTypeTrait { using type = bool; @@ -368,6 +385,19 @@ namespace vive { struct PropertyTypeTrait { using type = int32_t; }; + template <> + struct PropertyTypeTrait< + vr::Prop_ScreenshotHorizontalFieldOfViewDegrees_Float> { + using type = float; + }; + template <> + struct PropertyTypeTrait< + vr::Prop_ScreenshotVerticalFieldOfViewDegrees_Float> { + using type = float; + }; + template <> struct PropertyTypeTrait { + using type = bool; + }; template <> struct PropertyTypeTrait { using type = std::string; }; From 51588e42bf7e4c66d5bf94741621b81b576cdcbe Mon Sep 17 00:00:00 2001 From: Ryan Pavlik Date: Tue, 28 Jun 2016 15:50:04 -0500 Subject: [PATCH 08/11] Add code to look for interface versions compatibility, and port ViveLoader to new API --- DriverWrapper.h | 175 ++++++++++++++++++++++++++++++++++++++++++++++++ ViveLoader.cpp | 50 ++++++++++++-- 2 files changed, 221 insertions(+), 4 deletions(-) diff --git a/DriverWrapper.h b/DriverWrapper.h index 3564b20..d5c3c1b 100644 --- a/DriverWrapper.h +++ b/DriverWrapper.h @@ -37,6 +37,7 @@ // - none // Standard includes +#include #include #include #include @@ -45,6 +46,117 @@ namespace osvr { namespace vive { + namespace detail { + /// Given something like ITrackedDeviceServerDriver_004, returns + /// ITrackedDeviceServerDriver + inline std::string + getInterfaceName(std::string const &interfaceVersionString) { + auto pos = interfaceVersionString.find('_'); + if (std::string::npos == pos) { + /// error case: + /// passed-in string isn't an interface version string as we + /// expect it. + /// Return the whole thing. + return interfaceVersionString; + } + return interfaceVersionString.substr(0, pos); + } + + /// Helper function for dealing with the arrays of string literals used + /// in the list of interface version strings. + template + inline void for_each_const_string_array(const char *const *strings, + F &&functor) { + while (*strings != nullptr) { + std::forward(functor)(*strings); + ++strings; + } + } + + /// Helper class managing a list of supported interface version strings. + class InterfaceVersionSupport { + public: + InterfaceVersionSupport() : supportedInterfaces_(populate()) {} + InterfaceVersionSupport & + operator=(InterfaceVersionSupport const &) = delete; + + /// Given a string (or something convertible to it) that is an + /// interface version string, checks to see if it is supported. + template + bool isSupportedInterfaceVersionString(T const &ifaceVerStr) const { + return std::binary_search(supportedInterfaces_.cbegin(), + supportedInterfaces_.cend(), + ifaceVerStr); + } + + /// Given a string (or convertible) without the _\d\d\d version + /// suffix, searches the supported list for it and if found, returns + /// the full version string corresponding to it. Returns an empty + /// string if the interface wasn't found. + template + std::string + findVersionStringForInterface(T const &interfaceName) const { + auto it = + std::upper_bound(supportedInterfaces_.begin(), + supportedInterfaces_.end(), interfaceName); + std::string ret; + if (supportedInterfaces_.end() == it) { + // we didn't find it - hit the end + return ret; + } + auto ifaceName = getInterfaceName(*it); + if (ifaceName != interfaceName) { + // we didn't find it - in the middle + return ret; + } + // ok, we found it + ret = *it; + return ret; + } + + /// Like findVersionStringForInterface() except that you may also + /// pass a full interface version string, which will be trimmed to + /// just the interface name for you automatically. + std::string findSupportedVersionOfInterface( + std::string const &ifaceString) const { + return findVersionStringForInterface( + getInterfaceName(ifaceString)); + } + + private: + using Container = std::vector; + /// Function to create and populate the supported interface + /// container, so the object's data member may be const. + static Container populate() { + Container ret; + // Populate a vector with all the supported interfaces. + for_each_const_string_array( + vr::k_InterfaceVersions, + [&](const char *str) { ret.emplace_back(str); }); + + // so we can use binary_search + std::sort(ret.begin(), ret.end()); + return ret; + } + const Container supportedInterfaces_; + }; + + /// A list of just the interface names we actually use. + static const auto interfaceNamesWeCareAbout = { + "ITrackedDeviceServerDriver", "IVRDisplayComponent", + "IVRControllerComponent", //< @todo do we actually use/cast to + // this interface? + "IServerTrackedDeviceProvider", "IClientTrackedDeviceProvider"}; + + } // namespace detail + + inline bool isInterfaceNameWeCareAbout(std::string const &interfaceName) { + return std::find(detail::interfaceNamesWeCareAbout.begin(), + detail::interfaceNamesWeCareAbout.end(), + interfaceName) != + detail::interfaceNamesWeCareAbout.end(); + } + /// The do-nothing driver logger. class NullDriverLog : public vr::IDriverLog { public: @@ -169,6 +281,65 @@ namespace vive { return static_cast(serverDeviceProvider_); } + enum class InterfaceVersionStatus { + /// All mentioned interface version strings are handled/described by + /// the header we've built against. + AllInterfacesOK, + /// Not all mentioned interface version strings are + /// handled/described by the header we've built against, but the + /// interfaces that we use match. + AllUsedInterfacesOK, + /// At least one of the interfaces that we use doesn't match the + /// version we built against. + InterfaceMismatch + }; + + InterfaceVersionStatus checkServerDeviceProviderInterfaces() { + /// Now, go through the interfaces mentioned by the driver. + bool allUsedSupported = true; + unsupportedRequestedInterfaces_.clear(); + + detail::for_each_const_string_array( + serverDevProvider().GetInterfaceVersions(), + [&](const char *iface) { + auto ifaceStr = std::string{iface}; + auto found = + supportedInterfaces_.isSupportedInterfaceVersionString( + ifaceStr); + if (!found) { + // Record all interfaces we didn't find. + unsupportedRequestedInterfaces_.emplace_back(ifaceStr); + // See if not finding this interface will cause a + // problem. + bool isUsed = isInterfaceNameWeCareAbout( + detail::getInterfaceName(iface)); + if (isUsed) { + allUsedSupported = false; + } + } + }); + return allUsedSupported + ? (unsupportedRequestedInterfaces_.empty() + ? InterfaceVersionStatus::AllInterfacesOK + : InterfaceVersionStatus::AllUsedInterfacesOK) + : InterfaceVersionStatus::InterfaceMismatch; + } + + /// If checkServerDeviceProviderInterfaces is not + /// InterfaceVersionStatus::AllInterfacesOK, this will + /// return access to a non-empty list of interfaces that the device + /// driver reports that were not available in the headers we + /// compiled against. + std::vector const & + getUnsupportedRequestedInterfaces() const { + return unsupportedRequestedInterfaces_; + } + + detail::InterfaceVersionSupport const & + getSupportedInterfaceVersions() const { + return supportedInterfaces_; + } + vr::IServerTrackedDeviceProvider &serverDevProvider() const { if (!haveDriverLoaded() || !serverDeviceProvider_) { throw std::logic_error("Attempted to access server device " @@ -229,6 +400,7 @@ namespace vive { return; } } + /// This pointer manages lifetime if we created our own host but isn't /// accessed beyond that. std::unique_ptr owningServerDriverHost_; @@ -242,6 +414,9 @@ namespace vive { std::unique_ptr loader_; ProviderPtr serverDeviceProvider_; + detail::InterfaceVersionSupport supportedInterfaces_; + std::vector unsupportedRequestedInterfaces_; + DeviceHolder devices_; NullDriverLog nullDriverLog_; }; diff --git a/ViveLoader.cpp b/ViveLoader.cpp index 2cfc791..fa56425 100644 --- a/ViveLoader.cpp +++ b/ViveLoader.cpp @@ -188,13 +188,56 @@ int main() { /// but now, we can do things with vive.serverDevProvider() + /// first thing we should do is check driver compatibility. + auto interfaceStatus = vive.checkServerDeviceProviderInterfaces(); + switch (interfaceStatus) { + case osvr::vive::DriverWrapper::InterfaceVersionStatus::AllInterfacesOK: + std::cerr << PREFIX << "All interface versions mentioned by the driver " + "are available and supported." + << std::endl; + break; + case osvr::vive::DriverWrapper::InterfaceVersionStatus::AllUsedInterfacesOK: + std::cerr << PREFIX << "Not all interface versions mentioned by the " + "driver are available and supported, but the " + "ones used by this code match." + << std::endl; + break; + case osvr::vive::DriverWrapper::InterfaceVersionStatus::InterfaceMismatch: + std::cerr + << PREFIX + << "Driver requires unavailable/unsupported interface versions." + << std::endl; + break; + default: + break; + } + + switch (interfaceStatus) { + case osvr::vive::DriverWrapper::InterfaceVersionStatus::AllUsedInterfacesOK: + case osvr::vive::DriverWrapper::InterfaceVersionStatus::InterfaceMismatch: + std::cerr << PREFIX + << "Unavailable interface version strings:" << std::endl; + for (auto iface : vive.getUnsupportedRequestedInterfaces()) { + std::cerr << PREFIX << " - " << iface << std::endl; + } + break; + case osvr::vive::DriverWrapper::InterfaceVersionStatus::AllInterfacesOK: + default: + break; + } + + if (osvr::vive::DriverWrapper::InterfaceVersionStatus::InterfaceMismatch == + interfaceStatus) { + std::cerr << PREFIX << "Cannot continue." << std::endl; + return 1; + } + /// Power the system up. vive.serverDevProvider().LeaveStandby(); std::vector knownSerialNumbers; auto handleNewDevice = [&](const char *serialNum) { - auto dev = vive.serverDevProvider().FindTrackedDeviceDriver( - serialNum, vr::ITrackedDeviceServerDriver_Version); + auto dev = vive.serverDevProvider().FindTrackedDeviceDriver(serialNum); if (!dev) { std::cout << PREFIX << "Couldn't find the corresponding device driver for " @@ -222,8 +265,7 @@ int main() { std::cout << PREFIX << "Got " << numDevices << " tracked devices at startup" << std::endl; for (decltype(numDevices) i = 0; i < numDevices; ++i) { - auto dev = vive.serverDevProvider().GetTrackedDeviceDriver( - i, vr::ITrackedDeviceServerDriver_Version); + auto dev = vive.serverDevProvider().GetTrackedDeviceDriver(i); vive.devices().addAndActivateDevice(dev); std::cout << PREFIX << "Device " << i << std::endl; whatIsThisDevice(dev); From d53f2d6302ceb78dcd6075d644e34b6318db0f77 Mon Sep 17 00:00:00 2001 From: Ryan Pavlik Date: Tue, 28 Jun 2016 15:51:00 -0500 Subject: [PATCH 09/11] Check interface versions in display extractor. --- DisplayExtractor.cpp | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/DisplayExtractor.cpp b/DisplayExtractor.cpp index 6de1d71..77b6254 100644 --- a/DisplayExtractor.cpp +++ b/DisplayExtractor.cpp @@ -286,6 +286,26 @@ int main() { return 1; } + if (osvr::vive::DriverWrapper::InterfaceVersionStatus:: + InterfaceMismatch == + vive.checkServerDeviceProviderInterfaces()) { + std::cerr << PREFIX + << "SteamVR driver requires unavailable/unsupported " + "interface versions - either too old or too new for " + "this build. Cannot continue." + << std::endl; + for (auto iface : vive.getUnsupportedRequestedInterfaces()) { + if (osvr::vive::isInterfaceNameWeCareAbout(iface)) { + auto supported = + vive.getSupportedInterfaceVersions() + .findSupportedVersionOfInterface(iface); + std::cerr << PREFIX << " - Driver requested " << iface + << " but we support " << supported << std::endl; + } + } + return 1; + } + /// Power the system up. vive.serverDevProvider().LeaveStandby(); { From 0551d2c74330301c733e30c200e0672fcdf501dc Mon Sep 17 00:00:00 2001 From: Ryan Pavlik Date: Tue, 28 Jun 2016 16:16:32 -0500 Subject: [PATCH 10/11] Vive Tracker: check interface versions (permanent failure if mismatch) --- OSVRViveTracker.cpp | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/OSVRViveTracker.cpp b/OSVRViveTracker.cpp index 49fc175..9d712d0 100644 --- a/OSVRViveTracker.cpp +++ b/OSVRViveTracker.cpp @@ -150,6 +150,30 @@ namespace vive { return StartResult::PermanentFailure; } + /// Check for interface compatibility + if (DriverWrapper::InterfaceVersionStatus::InterfaceMismatch == + m_vive->checkServerDeviceProviderInterfaces()) { + std::cerr + << PREFIX + << "SteamVR lighthouse driver requires unavailable/unsupported " + "interface versions - either too old or too new for " + "this build. Specifically, the following critical " + "mismatches: " + << std::endl; + for (auto iface : m_vive->getUnsupportedRequestedInterfaces()) { + if (isInterfaceNameWeCareAbout( + detail::getInterfaceName(iface))) { + auto supported = + m_vive->getSupportedInterfaceVersions() + .findSupportedVersionOfInterface(iface); + std::cerr << PREFIX << " - SteamVR lighthouse: " << iface + << "\t\t OSVR-Vive: " << supported << std::endl; + } + } + std::cerr << PREFIX << "Cannot continue.\n" << std::endl; + return StartResult::PermanentFailure; + } + /// Power the system up. m_vive->serverDevProvider().LeaveStandby(); @@ -584,7 +608,7 @@ namespace vive { std::pair ViveDriverHost::getDriverPtr(uint32_t unWhichDevice) { - return std::pair(); + // return std::pair(); if (m_vive->devices().hasDeviceAt(unWhichDevice)) { return std::make_pair(&(m_vive->devices().getDevice(unWhichDevice)), true); From 7911c10bf645f5bedf5662957e9e958b9abdbed5 Mon Sep 17 00:00:00 2001 From: Ryan Pavlik Date: Tue, 28 Jun 2016 15:50:50 -0500 Subject: [PATCH 11/11] Port plugin and display extractor to new API --- DisplayExtractor.cpp | 2 +- OSVRViveTracker.cpp | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/DisplayExtractor.cpp b/DisplayExtractor.cpp index 77b6254..173c24a 100644 --- a/DisplayExtractor.cpp +++ b/DisplayExtractor.cpp @@ -314,7 +314,7 @@ int main() { << " tracked devices at startup" << std::endl; for (decltype(numDevices) i = 0; i < numDevices; ++i) { auto dev = vive.serverDevProvider().GetTrackedDeviceDriver( - i, vr::ITrackedDeviceServerDriver_Version); + i); vive.devices().addAndActivateDevice(dev); std::cout << PREFIX << "Device " << i << std::endl; auto disp = diff --git a/OSVRViveTracker.cpp b/OSVRViveTracker.cpp index 9d712d0..a7a5659 100644 --- a/OSVRViveTracker.cpp +++ b/OSVRViveTracker.cpp @@ -221,8 +221,8 @@ namespace vive { std::cout << PREFIX << "Got " << numDevices << " tracked devices at startup" << std::endl; for (decltype(numDevices) i = 0; i < numDevices; ++i) { - auto dev = m_vive->serverDevProvider().GetTrackedDeviceDriver( - i, vr::ITrackedDeviceServerDriver_Version); + auto dev = + m_vive->serverDevProvider().GetTrackedDeviceDriver(i); activateDevice(dev); } } @@ -455,7 +455,8 @@ namespace vive { OSVR_ChannelCount sensor, const DriverPose_t &newPose) { if (!(sensor < m_trackingResults.size())) { - m_trackingResults.resize(sensor + 1, vr::TrackingResult_Uninitialized); + m_trackingResults.resize(sensor + 1, + vr::TrackingResult_Uninitialized); } if (newPose.result != m_trackingResults[sensor]) { @@ -614,8 +615,7 @@ namespace vive { true); } return std::make_pair( - m_vive->serverDevProvider().GetTrackedDeviceDriver( - unWhichDevice, vr::ITrackedDeviceServerDriver_Version), + m_vive->serverDevProvider().GetTrackedDeviceDriver(unWhichDevice), false); }