diff --git a/.gitignore b/.gitignore index ecab4c34..dfb04e94 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,14 @@ ipch /OpenVR-SpaceCalibratorDriver/x64/ /x64/ /lib/boost* +*.o +*.a +*.srctrlprj +*.srctrldb +*.srctrlbm +*.out +OpenVR-SpaceCalibratorDriver/01spacecalibrator/bin/linux64/ +build +*.gitignore +*.py +usr/ diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 00000000..e330450c --- /dev/null +++ b/.gitmodules @@ -0,0 +1,9 @@ +[submodule "OpenVR-SpaceCalibrator/gl3w"] + path = OpenVR-SpaceCalibrator/gl3w + url = https://github.com/skaslev/gl3w.git +[submodule "modules/imgui"] + path = modules/imgui + url = https://github.com/ocornut/imgui.git +[submodule "modules/openvr"] + path = modules/openvr + url = https://github.com/ValveSoftware/openvr.git diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 00000000..7bc3b903 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,118 @@ +cmake_minimum_required(VERSION 3.10) + +project (OpenVR-SpaceCalibrator VERSION 1.0) +add_definitions(-D__linux__) + +set(CMAKE_BUILD_TYPE Debug) +set(DRIVER_LOG_FILE "/tmp/space_calibrator_driver.log" CACHE PATH "Driver Log Path" ) +set(LINUX_CONFIG_DIR ".config/OpenVR-SpaceCalibrator" CACHE PATH "Config subdirectory (from HOME)" ) + +add_library(imgui + lib/imgui/imgui.cpp + lib/imgui/imgui_demo.cpp + lib/imgui/imgui_draw.cpp + lib/imgui/imgui_impl_glfw.cpp + lib/imgui/imgui_impl_opengl3.cpp + modules/imgui/backends/imgui_impl_glfw.cpp +) + +find_library(glfw libglfw.so) +find_library(GL libGL.so) +find_library( openvr_api libopenvr_api.so PATHS ./modules/openvr/bin/linux64/libopenvr_api.so ) + +include_directories(OpenVR-SpaceCalibratorDriver) +include_directories(/usr/include/eigen3) +include_directories(lib/gl3w/include) +include_directories(lib) +include_directories(modules/openvr/headers) + +add_library( gl3w lib/gl3w/src/gl3w.c ) + +#configure_file(LinixConfig.h.in LinuxConfig.h) + +set(CMAKE_CXX_STANDARD 14) +set(CMAKE_CXX_STANDARD_REQUIRED True) + +add_executable(OpenVR-SpaceCalibrator + OpenVR-SpaceCalibrator/OpenVR-SpaceCalibrator.cpp + OpenVR-SpaceCalibrator/main_linux.cpp + OpenVR-SpaceCalibrator/Calibration.cpp + OpenVR-SpaceCalibrator/Configuration_linux.cpp + OpenVR-SpaceCalibrator/HandleCommandLine_linux.cpp + OpenVR-SpaceCalibrator/EmbeddedFiles.cpp + OpenVR-SpaceCalibrator/IPCClient_linux.cpp + OpenVR-SpaceCalibrator/OpenVR-SpaceCalibrator.cpp + OpenVR-SpaceCalibrator/UserInterface.cpp + ./OpenVR-SpaceCalibratorDriver/Logging.cpp +) +TARGET_LINK_LIBRARIES(OpenVR-SpaceCalibrator PRIVATE openvr_api imgui gl3w GL glfw) + +add_library( + driver_01spacecalibrator + SHARED + OpenVR-SpaceCalibratorDriver/OpenVR-SpaceCalibratorDriver.cpp + OpenVR-SpaceCalibratorDriver/Hooking.cpp + OpenVR-SpaceCalibratorDriver/IPCServer_linux.cpp + OpenVR-SpaceCalibratorDriver/Logging.cpp + OpenVR-SpaceCalibratorDriver/ServerTrackedDeviceProvider.cpp + OpenVR-SpaceCalibratorDriver/dllmain.cpp +) + +set_target_properties(driver_01spacecalibrator PROPERTIES + OUTPUT_NAME driver_01spacecalibrator + PREFIX "" +) + +####################################################################################### +set( APP_MANIFEST_PATH ${CMAKE_INSTALL_PREFIX}/share/openvr-spacecalibrator/manifest.vrmanifest ) +set( DRIVER_INSTALLER_PATH ${CMAKE_INSTALL_PREFIX}/share/openvr-spacecalibrator ) +set( DRIVER_MANIFEST_PATH ${CMAKE_INSTALL_PREFIX}/lib/steamvr/OpenVR-SpaceCalibrator/01spacecalibrator ) +configure_file( StaticConfig.h.in StaticConfig.h ) + +include_directories("${CMAKE_CURRENT_BINARY_DIR}") + +configure_file( ./OpenVR-SpaceCalibrator/manifest.vrmanifest ${CMAKE_CURRENT_BINARY_DIR}/manifest.vrmanifest ) +configure_file( ./OpenVR-SpaceCalibratorDriver/01spacecalibrator/driver.vrdrivermanifest ${CMAKE_CURRENT_BINARY_DIR}/driver.vrdrivermanifest ) +configure_file( ./driverInstall.py ${CMAKE_CURRENT_BINARY_DIR}/driverInstall.py ) + + +####################################################################################### +install( + FILES ${CMAKE_CURRENT_BINARY_DIR}/manifest.vrmanifest + DESTINATION ${CMAKE_INSTALL_PREFIX}/share/openvr-spacecalibrator +) + +install( + FILES ${CMAKE_CURRENT_BINARY_DIR}/driver.vrdrivermanifest + DESTINATION lib/steamvr/OpenVR-SpaceCalibrator/01spacecalibrator +) + +install( + TARGETS OpenVR-SpaceCalibrator +) +install( + TARGETS driver_01spacecalibrator + DESTINATION lib/steamvr/OpenVR-SpaceCalibrator/01spacecalibrator/bin/linux64/ +) + +install( + FILES driverInstall.py + DESTINATION "${DRIVER_INSTALLER_PATH}" +) + +find_package(Git QUIET) + +if(GIT_FOUND AND EXISTS "${PROJECT_SOURCE_DIR}/.git") + # Update submodules as needed + option(GIT_SUBMODULE "Check submodules during build" ON) + if(GIT_SUBMODULE) + message(STATUS "Submodule update") + execute_process(COMMAND ${GIT_EXECUTABLE} submodule update --init --recursive + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + RESULT_VARIABLE GIT_SUBMOD_RESULT) + if(NOT GIT_SUBMOD_RESULT EQUAL "0") + message(FATAL_ERROR "git submodule update --init --recursive failed with ${GIT_SUBMOD_RESULT}, please checkout submodules") + endif() + endif() +endif() + diff --git a/OpenVR-SpaceCalibrator/Calibration.cpp b/OpenVR-SpaceCalibrator/Calibration.cpp index cac0fbb9..2d7da975 100644 --- a/OpenVR-SpaceCalibrator/Calibration.cpp +++ b/OpenVR-SpaceCalibrator/Calibration.cpp @@ -1,4 +1,3 @@ -#include "stdafx.h" #include "Calibration.h" #include "Configuration.h" #include "IPCClient.h" diff --git a/OpenVR-SpaceCalibrator/Calibration.h b/OpenVR-SpaceCalibrator/Calibration.h index df55484c..9d73613a 100644 --- a/OpenVR-SpaceCalibrator/Calibration.h +++ b/OpenVR-SpaceCalibrator/Calibration.h @@ -3,6 +3,7 @@ #include #include #include +#include enum class CalibrationState { @@ -87,7 +88,7 @@ struct CalibrationContext Progress } type = String; - Message(Type type) : type(type) { } + Message(Type _type) : type(_type) { } std::string str; int progress, target; @@ -120,4 +121,4 @@ void InitCalibrator(); void CalibrationTick(double time); void StartCalibration(); void LoadChaperoneBounds(); -void ApplyChaperoneBounds(); \ No newline at end of file +void ApplyChaperoneBounds(); diff --git a/OpenVR-SpaceCalibrator/Configuration_linux.cpp b/OpenVR-SpaceCalibrator/Configuration_linux.cpp new file mode 100644 index 00000000..21478b5c --- /dev/null +++ b/OpenVR-SpaceCalibrator/Configuration_linux.cpp @@ -0,0 +1,279 @@ +#include "Configuration.h" + +#include + +#include +#include "stdio.h" +#include +#include +#include + +#include "Logging.h" + +#include +#include +#include +#include "StaticConfig.h" +#define LINUX_CONFIG_FILE "spacecal-config.json" + +static picojson::array FloatArray(const float *buf, int numFloats) +{ + picojson::array arr; + + for (int i = 0; i < numFloats; i++) + arr.push_back(picojson::value(double(buf[i]))); + + return arr; +} + +static void LoadFloatArray(const picojson::value &obj, float *buf, int numFloats) +{ + if (!obj.is()) + throw std::runtime_error("expected array, got " + obj.to_str()); + + auto &arr = obj.get(); + if (arr.size() != (size_t) numFloats) + throw std::runtime_error("wrong buffer size"); + + for (int i = 0; i < numFloats; i++) + buf[i] = (float) arr[i].get(); +} + +static void ParseProfile(CalibrationContext &ctx, std::istream &stream) +{ + picojson::value v; + std::string err = picojson::parse(v, stream); + if (!err.empty()) + throw std::runtime_error(err); + + auto arr = v.get(); + if (arr.size() < 1) + throw std::runtime_error("no profiles in file"); + + auto obj = arr[0].get(); + + ctx.referenceTrackingSystem = obj["reference_tracking_system"].get(); + ctx.targetTrackingSystem = obj["target_tracking_system"].get(); + ctx.calibratedRotation(0) = obj["roll"].get(); + ctx.calibratedRotation(1) = obj["yaw"].get(); + ctx.calibratedRotation(2) = obj["pitch"].get(); + ctx.calibratedTranslation(0) = obj["x"].get(); + ctx.calibratedTranslation(1) = obj["y"].get(); + ctx.calibratedTranslation(2) = obj["z"].get(); + + if (obj["scale"].is()) + ctx.calibratedScale = obj["scale"].get(); + else + ctx.calibratedScale = 1.0; + + if (obj["calibration_speed"].is()) + ctx.calibrationSpeed = (CalibrationContext::Speed)(int) obj["calibration_speed"].get(); + + if (obj["chaperone"].is()) + { + auto chaperone = obj["chaperone"].get(); + ctx.chaperone.autoApply = chaperone["auto_apply"].get(); + + LoadFloatArray(chaperone["play_space_size"], ctx.chaperone.playSpaceSize.v, 2); + + LoadFloatArray( + chaperone["standing_center"], + (float *) ctx.chaperone.standingCenter.m, + sizeof(ctx.chaperone.standingCenter.m) / sizeof(float) + ); + + if (!chaperone["geometry"].is()) + throw std::runtime_error("chaperone geometry is not an array"); + + auto &geometry = chaperone["geometry"].get(); + + if (geometry.size() > 0) + { + ctx.chaperone.geometry.resize(geometry.size() * sizeof(float) / sizeof(ctx.chaperone.geometry[0])); + LoadFloatArray(chaperone["geometry"], (float *) ctx.chaperone.geometry.data(), geometry.size()); + + ctx.chaperone.valid = true; + } + } + + ctx.validProfile = true; +} + +static void WriteProfile(CalibrationContext &ctx, std::ostream &out) +{ + if (!ctx.validProfile) + return; + + picojson::object profile; + profile["reference_tracking_system"].set(ctx.referenceTrackingSystem); + profile["target_tracking_system"].set(ctx.targetTrackingSystem); + profile["roll"].set(ctx.calibratedRotation(0)); + profile["yaw"].set(ctx.calibratedRotation(1)); + profile["pitch"].set(ctx.calibratedRotation(2)); + profile["x"].set(ctx.calibratedTranslation(0)); + profile["y"].set(ctx.calibratedTranslation(1)); + profile["z"].set(ctx.calibratedTranslation(2)); + profile["scale"].set(ctx.calibratedScale); + + double speed = (int) ctx.calibrationSpeed; + profile["calibration_speed"].set(speed); + + if (ctx.chaperone.valid) + { + picojson::object chaperone; + chaperone["auto_apply"].set(ctx.chaperone.autoApply); + chaperone["play_space_size"].set(FloatArray(ctx.chaperone.playSpaceSize.v, 2)); + + chaperone["standing_center"].set(FloatArray( + (float *) ctx.chaperone.standingCenter.m, + sizeof(ctx.chaperone.standingCenter.m) / sizeof(float) + )); + + chaperone["geometry"].set(FloatArray( + (float *) ctx.chaperone.geometry.data(), + sizeof(ctx.chaperone.geometry[0]) / sizeof(float) * ctx.chaperone.geometry.size() + )); + + profile["chaperone"].set(chaperone); + } + + picojson::value profileV; + profileV.set(profile); + + picojson::array profiles; + profiles.push_back(profileV); + + picojson::value profilesV; + profilesV.set(profiles); + + out << profilesV.serialize(true); +} + +static std::string ReadRegistryKey() +{ + char configPath[1024]; + const char * home = getenv("HOME"); + snprintf( configPath, 1024, "%s/" LINUX_CONFIG_DIR, home); + + struct stat statResult; + if(stat(LINUX_CONFIG_DIR, &statResult)){ + if(errno != 2){ // no idea why 2 is returned instead of the documented ENOTDIR + int rr = errno; + LOG("Error determining if %s is a directory: %s, %s", configPath, strerror(rr), strerror(2)); + return ""; + } else { + int rr = errno; + LOG("The directory %s is confirmed to not exist %d-%s", configPath, rr, strerror(rr)); + int retCode; + + char cmd[1500]; + snprintf(cmd, 1500, "mkdir -p %s", configPath); + LOG("Running: %s", cmd); + if( (retCode = system(cmd)) ){ + LOG("Error %d making directory " LINUX_CONFIG_DIR, retCode); + return ""; + } + } + } + + char configFilePath[2000]; + snprintf(configFilePath, 2000, "%s/" LINUX_CONFIG_FILE, configPath); + + LOG("Opening file at %s", configFilePath); + + FILE* file = fopen(configFilePath, "r"); + + if(!file) return ""; + + std::string ret; + const int buffSize = 4097; + int count = 0; + char buff[buffSize]; + buff[buffSize-1] = 0; + + do{ + count = fread((void*) buff, 1, buffSize, file); + if(count > 0){ + ret += buff; + } + }while(buffSize == count); + fclose(file); + return ret; +} + +static void WriteRegistryKey(std::string str) +{ + struct stat statResult; + + char configPath[1024]; + const char * home = getenv("HOME"); + snprintf( configPath, 1024, "%s/" LINUX_CONFIG_DIR, home); + + if(stat(LINUX_CONFIG_DIR, &statResult)){ + if(errno != 2){ // no idea why 2 is returned instead of the documented ENOTDIR + int rr = errno; + LOG("Error determining if %s is a directory: %s, %s", configPath, strerror(rr), strerror(2)); + return; + } else { + int rr = errno; + LOG("The directory %s is confirmed to not exist %d-%s", configPath, rr, strerror(rr)); + int retCode; + + char cmd[1500]; + snprintf(cmd, 1500, "mkdir -p %s", configPath); + LOG("Running: %s", cmd); + if( (retCode = system(cmd)) ){ + LOG("Error %d making directory " LINUX_CONFIG_DIR, retCode); + return; + } + } + } + + char configFilePath[2000]; + snprintf(configFilePath, 2000, "%s/" LINUX_CONFIG_FILE, configPath); + + FILE* file = fopen(configFilePath, "w"); + if(!file) { + LOG("%s - %d-%s", "Error opening config file for writing", errno, strerror(errno)); + return; + } else { + LOG("Opened file at %s to save settings", configFilePath); + } + + fprintf(file, "%s", str.c_str()); + fclose(file); +} + +void LoadProfile(CalibrationContext &ctx) +{ + ctx.validProfile = false; + + auto str = ReadRegistryKey(); + if (str == "") + { + std::cout << "Profile is empty" << std::endl; + ctx.Clear(); + return; + } + + try + { + std::stringstream io(str); + ParseProfile(ctx, io); + std::cout << "Loaded profile" << std::endl; + } + catch (const std::runtime_error &e) + { + std::cerr << "Error loading profile: " << e.what() << std::endl; + } +} + +void SaveProfile(CalibrationContext &ctx) +{ + std::cout << "Saving profile to registry" << std::endl; + + std::stringstream io; + WriteProfile(ctx, io); + WriteRegistryKey(io.str()); +} + diff --git a/OpenVR-SpaceCalibrator/HandleCommandLine.h b/OpenVR-SpaceCalibrator/HandleCommandLine.h new file mode 100644 index 00000000..af8b55d9 --- /dev/null +++ b/OpenVR-SpaceCalibrator/HandleCommandLine.h @@ -0,0 +1,119 @@ +#include +#define OPENVR_APPLICATION_KEY "pushrax.SpaceCalibrator" +#include +#include +#include + + +namespace HandleCommandLine { + +std::string ManifestPath(std::string cwd); + +static inline void OpenVRPath(char * cruntimePath, int cruntimePathLength){ + auto vrErr = vr::VRInitError_None; + vr::VR_Init(&vrErr, vr::VRApplication_Utility); + if (vrErr == vr::VRInitError_None) + { + unsigned int pathLen; + vr::VR_GetRuntimePath(cruntimePath, cruntimePathLength, &pathLen); + + printf("%s", cruntimePath); + vr::VR_Shutdown(); + exit(0); + } + fprintf(stderr, "Failed to initialize OpenVR: %s\n", vr::VR_GetVRInitErrorAsEnglishDescription(vrErr)); + vr::VR_Shutdown(); + exit(-2); +} + +static inline void InstallManifest(char const * const cwd, int max_path) { + auto vrErr = vr::VRInitError_None; + vr::VR_Init(&vrErr, vr::VRApplication_Utility); + if (vrErr == vr::VRInitError_None) + { + if (vr::VRApplications()->IsApplicationInstalled(OPENVR_APPLICATION_KEY)) + { + auto oldWd = std::make_unique(max_path); + memset((void*)oldWd.get(), 0, max_path); + + auto vrAppErr = vr::VRApplicationError_None; + vr::VRApplications()->GetApplicationPropertyString(OPENVR_APPLICATION_KEY, vr::VRApplicationProperty_WorkingDirectory_String, oldWd.get(), max_path, &vrAppErr); + if (vrAppErr != vr::VRApplicationError_None) + { + fprintf(stderr, "Failed to get old working dir, skipping removal: %s\n", vr::VRApplications()->GetApplicationsErrorNameFromEnum(vrAppErr)); + } + else + { + std::string manifestPath = oldWd.get(); + manifestPath = HandleCommandLine::ManifestPath(manifestPath); + std::cout << "Removing old manifest path: " << manifestPath << std::endl; + vr::VRApplications()->RemoveApplicationManifest(manifestPath.c_str()); + } + } + std::string manifestPath = cwd; + manifestPath = HandleCommandLine::ManifestPath(manifestPath); + + std::cout << "Adding manifest path: " << manifestPath << std::endl; + auto vrAppErr = vr::VRApplications()->AddApplicationManifest(manifestPath.c_str()); + if (vrAppErr != vr::VRApplicationError_None) + { + fprintf(stderr, "Failed to add manifest: %s\n", vr::VRApplications()->GetApplicationsErrorNameFromEnum(vrAppErr)); + } + else + { + vr::VRApplications()->SetApplicationAutoLaunch(OPENVR_APPLICATION_KEY, true); + } + vr::VR_Shutdown(); + exit(-2); + } + fprintf(stderr, "Failed to initialize OpenVR: %s\n", vr::VR_GetVRInitErrorAsEnglishDescription(vrErr)); + vr::VR_Shutdown(); + exit(-2); +} + +static inline void RemoveManifest(char const * const cwd) { + auto vrErr = vr::VRInitError_None; + vr::VR_Init(&vrErr, vr::VRApplication_Utility); + if (vrErr == vr::VRInitError_None) + { + if (vr::VRApplications()->IsApplicationInstalled(OPENVR_APPLICATION_KEY)) + { + std::string manifestPath = cwd; + manifestPath = ManifestPath(manifestPath); + + std::cout << "Removing manifest path: " << manifestPath << std::endl; + vr::VRApplications()->RemoveApplicationManifest(manifestPath.c_str()); + } + vr::VR_Shutdown(); + exit(0); + } + fprintf(stderr, "Failed to initialize OpenVR: %s\n", vr::VR_GetVRInitErrorAsEnglishDescription(vrErr)); + vr::VR_Shutdown(); + exit(-2); +} + +static inline void ActivateMultipleDrivers() { + int ret = -2; + auto vrErr = vr::VRInitError_None; + vr::VR_Init(&vrErr, vr::VRApplication_Utility); + if (vrErr == vr::VRInitError_None) + { + try + { + ActivateMultipleDrivers(); + ret = 0; + } + catch (std::runtime_error &e) + { + std::cerr << e.what() << std::endl; + } + } + else + { + fprintf(stderr, "Failed to initialize OpenVR: %s\n", vr::VR_GetVRInitErrorAsEnglishDescription(vrErr)); + } + vr::VR_Shutdown(); + exit(ret); +} + +} // namespace HandleCommandLine diff --git a/OpenVR-SpaceCalibrator/HandleCommandLine_linux.cpp b/OpenVR-SpaceCalibrator/HandleCommandLine_linux.cpp new file mode 100644 index 00000000..b7d00b39 --- /dev/null +++ b/OpenVR-SpaceCalibrator/HandleCommandLine_linux.cpp @@ -0,0 +1,7 @@ +#include "HandleCommandLine.h" + +#include "StaticConfig.h" +std::string HandleCommandLine::ManifestPath(std::string /* cwd */){ + return APP_MANIFEST_PATH; +} + diff --git a/OpenVR-SpaceCalibrator/HandleCommandLine_win.cpp b/OpenVR-SpaceCalibrator/HandleCommandLine_win.cpp new file mode 100644 index 00000000..85a246e4 --- /dev/null +++ b/OpenVR-SpaceCalibrator/HandleCommandLine_win.cpp @@ -0,0 +1,5 @@ +#include "HandleCommandLine.h" + +std::string HandleCommandLine::ManifestPath(std::string cwd){ + return cwd + "\\manifest.vrmanifest"; +} diff --git a/OpenVR-SpaceCalibrator/IPCClient.cpp b/OpenVR-SpaceCalibrator/IPCClient.cpp deleted file mode 100644 index eacafcd4..00000000 --- a/OpenVR-SpaceCalibrator/IPCClient.cpp +++ /dev/null @@ -1,93 +0,0 @@ -#include "stdafx.h" -#include "IPCClient.h" - -#include - -static std::string LastErrorString(DWORD lastError) -{ - LPSTR buffer = nullptr; - size_t size = FormatMessageA( - FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, lastError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&buffer, 0, NULL - ); - - std::string message(buffer, size); - LocalFree(buffer); - return message; -} - -IPCClient::~IPCClient() -{ - if (pipe && pipe != INVALID_HANDLE_VALUE) - CloseHandle(pipe); -} - -void IPCClient::Connect() -{ - LPTSTR pipeName = TEXT(OPENVR_SPACECALIBRATOR_PIPE_NAME); - - WaitNamedPipe(pipeName, 1000); - pipe = CreateFile(pipeName, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0); - - if (pipe == INVALID_HANDLE_VALUE) - { - throw std::runtime_error("Space Calibrator driver unavailable. Make sure SteamVR is running, and the Space Calibrator addon is enabled in SteamVR settings."); - } - - DWORD mode = PIPE_READMODE_MESSAGE; - if (!SetNamedPipeHandleState(pipe, &mode, 0, 0)) - { - throw std::runtime_error("Couldn't set pipe mode. Error: " + LastErrorString(GetLastError())); - } - - auto response = SendBlocking(protocol::Request(protocol::RequestHandshake)); - if (response.type != protocol::ResponseHandshake || response.protocol.version != protocol::Version) - { - throw std::runtime_error( - "Incorrect driver version installed, try reinstalling OpenVR-SpaceCalibrator. (Client: " + - std::to_string(protocol::Version) + - ", Driver: " + - std::to_string(response.protocol.version) + - ")" - ); - } -} - -protocol::Response IPCClient::SendBlocking(const protocol::Request &request) -{ - Send(request); - return Receive(); -} - -void IPCClient::Send(const protocol::Request &request) -{ - DWORD bytesWritten; - BOOL success = WriteFile(pipe, &request, sizeof request, &bytesWritten, 0); - if (!success) - { - throw std::runtime_error("Error writing IPC request. Error: " + LastErrorString(GetLastError())); - } -} - -protocol::Response IPCClient::Receive() -{ - protocol::Response response(protocol::ResponseInvalid); - DWORD bytesRead; - - BOOL success = ReadFile(pipe, &response, sizeof response, &bytesRead, 0); - if (!success) - { - DWORD lastError = GetLastError(); - if (lastError != ERROR_MORE_DATA) - { - throw std::runtime_error("Error reading IPC response. Error: " + LastErrorString(lastError)); - } - } - - if (bytesRead != sizeof response) - { - throw std::runtime_error("Invalid IPC response with size " + std::to_string(bytesRead)); - } - - return response; -} diff --git a/OpenVR-SpaceCalibrator/IPCClient.h b/OpenVR-SpaceCalibrator/IPCClient.h index e8e7ee86..81eebf44 100644 --- a/OpenVR-SpaceCalibrator/IPCClient.h +++ b/OpenVR-SpaceCalibrator/IPCClient.h @@ -1,11 +1,15 @@ #pragma once +#include #include "../Protocol.h" +struct IPCClientImpl; + class IPCClient { public: ~IPCClient(); + IPCClient(); void Connect(); protocol::Response SendBlocking(const protocol::Request &request); @@ -14,5 +18,5 @@ class IPCClient protocol::Response Receive(); private: - HANDLE pipe = INVALID_HANDLE_VALUE; -}; \ No newline at end of file + std::unique_ptr impl; +}; diff --git a/OpenVR-SpaceCalibrator/IPCClient_linux.cpp b/OpenVR-SpaceCalibrator/IPCClient_linux.cpp new file mode 100644 index 00000000..8ec39acf --- /dev/null +++ b/OpenVR-SpaceCalibrator/IPCClient_linux.cpp @@ -0,0 +1,61 @@ +#include "IPCClient.h" +#include "Comms.h" + +#include +#include + +struct IPCClientImpl{ + Client pipe; +}; + +IPCClient::IPCClient() +{ + impl = std::make_unique(); +} + +IPCClient::~IPCClient() +{ + //NOP +} + +void IPCClient::Connect() +{ + auto response = SendBlocking(protocol::Request(protocol::RequestHandshake)); + if (response.type != protocol::ResponseHandshake || response.protocol.version != protocol::Version) + { + throw std::runtime_error( + "Incorrect driver version installed, try reinstalling OpenVR-SpaceCalibrator. (Client: " + + std::to_string(protocol::Version) + + ", Driver: " + + std::to_string(response.protocol.version) + + ")" + ); + } +} + +protocol::Response IPCClient::SendBlocking(const protocol::Request &request) +{ + for(int i=0; i<10; i++){ + Send(request); + try{ + return Receive(); + } catch (std::runtime_error &t) { + LOG("%s: %s", "Recv timeout failed", t.what()); + } + } + throw std::runtime_error("Fell through read loop"); +} + +void IPCClient::Send(const protocol::Request &request) +{ + impl->pipe.Send(request); +} + +protocol::Response IPCClient::Receive() +{ + protocol::Response response(protocol::ResponseInvalid); + if( impl->pipe.Recv(&response) ) + return response; + else + throw std::runtime_error("No packet was received"); +} diff --git a/OpenVR-SpaceCalibrator/OpenVR-SpaceCalibrator.cpp b/OpenVR-SpaceCalibrator/OpenVR-SpaceCalibrator.cpp index 7aece1d1..9728a96e 100644 --- a/OpenVR-SpaceCalibrator/OpenVR-SpaceCalibrator.cpp +++ b/OpenVR-SpaceCalibrator/OpenVR-SpaceCalibrator.cpp @@ -1,8 +1,9 @@ -#include "stdafx.h" -#include "Calibration.h" +#include "Calibration.h" #include "Configuration.h" #include "EmbeddedFiles.h" #include "UserInterface.h" +#include "OpenVR-SpaceCalibrator.h" +#include "iostream" #include #include @@ -10,30 +11,6 @@ #include #include #include -#include - -#pragma comment(linker,"\"/manifestdependency:type='win32' \ -name='Microsoft.Windows.Common-Controls' version='6.0.0.0' \ -processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"") - -#define OPENVR_APPLICATION_KEY "pushrax.SpaceCalibrator" - -extern "C" __declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001; -extern "C" __declspec(dllexport) DWORD AmdPowerXpressRequestHighPerformance = 0x00000001; - -void CreateConsole() -{ - static bool created = false; - if (!created) - { - AllocConsole(); - FILE *file = nullptr; - freopen_s(&file, "CONIN$", "r", stdin); - freopen_s(&file, "CONOUT$", "w", stdout); - freopen_s(&file, "CONOUT$", "w", stderr); - created = true; - } -} //#define DEBUG_LOGS @@ -47,15 +24,11 @@ void openGLDebugCallback(GLenum source, GLenum type, GLuint id, GLenum severity, fprintf(stderr, "OpenGL Debug %u: %.*s\n", id, length, message); } -static void HandleCommandLine(LPWSTR lpCmdLine); - static GLFWwindow *glfwWindow = nullptr; static vr::VROverlayHandle_t overlayMainHandle = 0, overlayThumbnailHandle = 0; static GLuint fboHandle = 0, fboTextureHandle = 0; static int fboTextureWidth = 0, fboTextureHeight = 0; -static char cwd[MAX_PATH]; - void CreateGLFWWindow() { glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); @@ -116,7 +89,7 @@ void CreateGLFWWindow() } } -void TryCreateVROverlay() +void TryCreateVROverlay(char const * cwd) { if (overlayMainHandle || !vr::VROverlay()) return; @@ -202,11 +175,11 @@ void InitVR() ActivateMultipleDrivers(); } -void RunLoop() +void RunLoop(char const * cwd) { while (!glfwWindowShouldClose(glfwWindow)) { - TryCreateVROverlay(); + TryCreateVROverlay(cwd); double time = glfwGetTime(); CalibrationTick(time); @@ -339,29 +312,24 @@ void RunLoop() } } -int APIENTRY wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPWSTR lpCmdLine, _In_ int nCmdShow) -{ - _getcwd(cwd, MAX_PATH); - HandleCommandLine(lpCmdLine); - -#ifdef DEBUG_LOGS - CreateConsole(); -#endif - +int MainApplication(char const * const cwd, InitErrorCallback errCB){ if (!glfwInit()) { - MessageBox(nullptr, L"Failed to initialize GLFW", L"", 0); + errCB("Failed to initialize GLFW"); return 0; } glfwSetErrorCallback(GLFWErrorCallback); + try { InitVR(); CreateGLFWWindow(); InitCalibrator(); LoadProfile(CalCtx); - RunLoop(); + + + RunLoop(cwd); vr::VR_Shutdown(); @@ -377,10 +345,7 @@ int APIENTRY wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance } catch (std::runtime_error &e) { - std::cerr << "Runtime error: " << e.what() << std::endl; - wchar_t message[1024]; - swprintf(message, 1024, L"%hs", e.what()); - MessageBox(nullptr, message, L"Runtime Error", 0); + errCB(e.what()); } if (glfwWindow) @@ -390,110 +355,4 @@ int APIENTRY wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance return 0; } -static void HandleCommandLine(LPWSTR lpCmdLine) -{ - if (lstrcmp(lpCmdLine, L"-openvrpath") == 0) - { - auto vrErr = vr::VRInitError_None; - vr::VR_Init(&vrErr, vr::VRApplication_Utility); - if (vrErr == vr::VRInitError_None) - { - char cruntimePath[MAX_PATH] = { 0 }; - unsigned int pathLen; - vr::VR_GetRuntimePath(cruntimePath, MAX_PATH, &pathLen); - printf("%s", cruntimePath); - vr::VR_Shutdown(); - exit(0); - } - fprintf(stderr, "Failed to initialize OpenVR: %s\n", vr::VR_GetVRInitErrorAsEnglishDescription(vrErr)); - vr::VR_Shutdown(); - exit(-2); - } - else if (lstrcmp(lpCmdLine, L"-installmanifest") == 0) - { - auto vrErr = vr::VRInitError_None; - vr::VR_Init(&vrErr, vr::VRApplication_Utility); - if (vrErr == vr::VRInitError_None) - { - if (vr::VRApplications()->IsApplicationInstalled(OPENVR_APPLICATION_KEY)) - { - char oldWd[MAX_PATH] = { 0 }; - auto vrAppErr = vr::VRApplicationError_None; - vr::VRApplications()->GetApplicationPropertyString(OPENVR_APPLICATION_KEY, vr::VRApplicationProperty_WorkingDirectory_String, oldWd, MAX_PATH, &vrAppErr); - if (vrAppErr != vr::VRApplicationError_None) - { - fprintf(stderr, "Failed to get old working dir, skipping removal: %s\n", vr::VRApplications()->GetApplicationsErrorNameFromEnum(vrAppErr)); - } - else - { - std::string manifestPath = oldWd; - manifestPath += "\\manifest.vrmanifest"; - std::cout << "Removing old manifest path: " << manifestPath << std::endl; - vr::VRApplications()->RemoveApplicationManifest(manifestPath.c_str()); - } - } - std::string manifestPath = cwd; - manifestPath += "\\manifest.vrmanifest"; - std::cout << "Adding manifest path: " << manifestPath << std::endl; - auto vrAppErr = vr::VRApplications()->AddApplicationManifest(manifestPath.c_str()); - if (vrAppErr != vr::VRApplicationError_None) - { - fprintf(stderr, "Failed to add manifest: %s\n", vr::VRApplications()->GetApplicationsErrorNameFromEnum(vrAppErr)); - } - else - { - vr::VRApplications()->SetApplicationAutoLaunch(OPENVR_APPLICATION_KEY, true); - } - vr::VR_Shutdown(); - exit(-2); - } - fprintf(stderr, "Failed to initialize OpenVR: %s\n", vr::VR_GetVRInitErrorAsEnglishDescription(vrErr)); - vr::VR_Shutdown(); - exit(-2); - } - else if (lstrcmp(lpCmdLine, L"-removemanifest") == 0) - { - auto vrErr = vr::VRInitError_None; - vr::VR_Init(&vrErr, vr::VRApplication_Utility); - if (vrErr == vr::VRInitError_None) - { - if (vr::VRApplications()->IsApplicationInstalled(OPENVR_APPLICATION_KEY)) - { - std::string manifestPath = cwd; - manifestPath += "\\manifest.vrmanifest"; - std::cout << "Removing manifest path: " << manifestPath << std::endl; - vr::VRApplications()->RemoveApplicationManifest(manifestPath.c_str()); - } - vr::VR_Shutdown(); - exit(0); - } - fprintf(stderr, "Failed to initialize OpenVR: %s\n", vr::VR_GetVRInitErrorAsEnglishDescription(vrErr)); - vr::VR_Shutdown(); - exit(-2); - } - else if (lstrcmp(lpCmdLine, L"-activatemultipledrivers") == 0) - { - int ret = -2; - auto vrErr = vr::VRInitError_None; - vr::VR_Init(&vrErr, vr::VRApplication_Utility); - if (vrErr == vr::VRInitError_None) - { - try - { - ActivateMultipleDrivers(); - ret = 0; - } - catch (std::runtime_error &e) - { - std::cerr << e.what() << std::endl; - } - } - else - { - fprintf(stderr, "Failed to initialize OpenVR: %s\n", vr::VR_GetVRInitErrorAsEnglishDescription(vrErr)); - } - vr::VR_Shutdown(); - exit(ret); - } -} diff --git a/OpenVR-SpaceCalibrator/OpenVR-SpaceCalibrator.h b/OpenVR-SpaceCalibrator/OpenVR-SpaceCalibrator.h new file mode 100644 index 00000000..c66a7c5b --- /dev/null +++ b/OpenVR-SpaceCalibrator/OpenVR-SpaceCalibrator.h @@ -0,0 +1,6 @@ +#pragma once + +typedef void (*InitErrorCallback)(char const * ); + +int MainApplication(char const * const cwd, InitErrorCallback cb); + diff --git a/OpenVR-SpaceCalibrator/UserInterface.cpp b/OpenVR-SpaceCalibrator/UserInterface.cpp index fb507a9d..c83b53a3 100644 --- a/OpenVR-SpaceCalibrator/UserInterface.cpp +++ b/OpenVR-SpaceCalibrator/UserInterface.cpp @@ -1,4 +1,3 @@ -#include "stdafx.h" #include "UserInterface.h" #include "Calibration.h" #include "Configuration.h" @@ -8,7 +7,7 @@ #include #include #include -#include +#include "imgui/imgui.h" struct VRDevice { @@ -67,14 +66,14 @@ void BuildMenu(bool runningInOverlay) { auto &io = ImGui::GetIO(); ImGuiStyle &style = ImGui::GetStyle(); - ImGui::Text(""); + ImGui::Text("%s", ""); if (CalCtx.state == CalibrationState::None) { if (CalCtx.validProfile && !CalCtx.enabled) { ImGui::TextColored(ImColor(0.8f, 0.2f, 0.2f), "Reference (%s) HMD not detected, profile disabled", CalCtx.referenceTrackingSystem.c_str()); - ImGui::Text(""); + ImGui::Text("%s", ""); } float width = ImGui::GetWindowContentRegionWidth(), scale = 1.0f; @@ -114,7 +113,7 @@ void BuildMenu(bool runningInOverlay) scale = 0.5; } - ImGui::Text(""); + ImGui::Text("%s", ""); if (ImGui::Button("Copy Chaperone Bounds to profile", ImVec2(width * scale, ImGui::GetTextLineHeight() * 2))) { LoadChaperoneBounds(); @@ -135,22 +134,22 @@ void BuildMenu(bool runningInOverlay) } } - ImGui::Text(""); + ImGui::Text("%s", ""); auto speed = CalCtx.calibrationSpeed; ImGui::Columns(4, NULL, false); ImGui::Text("Calibration Speed"); ImGui::NextColumn(); - if (ImGui::RadioButton(" Fast ", speed == CalibrationContext::FAST)) + if (ImGui::RadioButton(" Fast ", speed == CalibrationContext::FAST)) CalCtx.calibrationSpeed = CalibrationContext::FAST; ImGui::NextColumn(); - if (ImGui::RadioButton(" Slow ", speed == CalibrationContext::SLOW)) + if (ImGui::RadioButton(" Slow ", speed == CalibrationContext::SLOW)) CalCtx.calibrationSpeed = CalibrationContext::SLOW; ImGui::NextColumn(); - if (ImGui::RadioButton(" Very Slow ", speed == CalibrationContext::VERY_SLOW)) + if (ImGui::RadioButton(" Very Slow ", speed == CalibrationContext::VERY_SLOW)) CalCtx.calibrationSpeed = CalibrationContext::VERY_SLOW; ImGui::Columns(1); @@ -190,11 +189,11 @@ void BuildMenu(bool runningInOverlay) switch (message.type) { case CalibrationContext::Message::String: - ImGui::TextWrapped(message.str.c_str()); + ImGui::TextWrapped("%s", message.str.c_str()); break; case CalibrationContext::Message::Progress: float fraction = (float)message.progress / (float)message.target; - ImGui::Text(""); + ImGui::Text("%s", ""); ImGui::ProgressBar(fraction, ImVec2(-1.0f, 0.0f), ""); ImGui::SetCursorPosY(ImGui::GetCursorPosY() - ImGui::GetFontSize() - style.FramePadding.y * 2); ImGui::Text(" %d%%", (int)(fraction * 100)); @@ -205,7 +204,7 @@ void BuildMenu(bool runningInOverlay) if (CalCtx.state == CalibrationState::None) { - ImGui::Text(""); + ImGui::Text("%s", ""); if (ImGui::Button("Close", ImVec2(ImGui::GetWindowContentRegionWidth(), ImGui::GetTextLineHeight() * 2))) ImGui::CloseCurrentPopup(); } @@ -279,7 +278,7 @@ void BuildSystemSelection(const VRState &state) ImGui::SameLine(); ImGui::Combo("##TargetTrackingSystem", ¤tTargetSystem, &targetSystems[0], (int) targetSystems.size()); - if (currentTargetSystem != -1 && currentTargetSystem < targetSystems.size()) + if (currentTargetSystem != -1 && currentTargetSystem < (int) targetSystems.size()) { CalCtx.targetTrackingSystem = std::string(targetSystems[currentTargetSystem]); } diff --git a/OpenVR-SpaceCalibrator/main_linux.cpp b/OpenVR-SpaceCalibrator/main_linux.cpp new file mode 100644 index 00000000..931b6eb7 --- /dev/null +++ b/OpenVR-SpaceCalibrator/main_linux.cpp @@ -0,0 +1,142 @@ +#include "Calibration.h" +#include "Configuration.h" +#include "EmbeddedFiles.h" +#include "UserInterface.h" + +#include "OpenVR-SpaceCalibrator.h" +#include +#include +#include +#include "GL/gl3w.h" + +#include + +#include "HandleCommandLine.h" + +#include +#include +#include + +#include +#include + +#include "StaticConfig.h" + +void printError(char const * err){ + std::cerr<(max_path); + unsigned int pathLen; + vr::VR_GetRuntimePath(cruntimePath.get(), max_path, &pathLen); + + const int cmdLength = 8196; + char cmd[cmdLength]; + + snprintf(cmd, cmdLength, "python " DRIVER_INSTALLER_PATH "/driverInstall.py --toInstall " DRIVER_MANIFEST_PATH " --vrpathreg %s/bin/vrpathreg.sh", cruntimePath.get()); + printf("cmd: %s\n", cmd); + system(cmd); + + vr::VR_Shutdown(); + exit(0); +} + +void UninstallDriver(int max_path){ + auto vrErr = vr::VRInitError_None; + vr::VR_Init(&vrErr, vr::VRApplication_Utility); + if (vrErr != vr::VRInitError_None) + { + fprintf(stderr, "Failed to initialize OpenVR: %s\n", vr::VR_GetVRInitErrorAsEnglishDescription(vrErr)); + vr::VR_Shutdown(); + exit(-2); + } + + auto cruntimePath = std::make_unique(max_path); + unsigned int pathLen; + vr::VR_GetRuntimePath(cruntimePath.get(), max_path, &pathLen); + + const int cmdLength = 8196; + char cmd[cmdLength]; + + snprintf(cmd, cmdLength, "\"%s/bin/vrpathreg.sh\" removedriverwithname 01spacecalibrator", cruntimePath.get()); + printf("cmd: %s\n", cmd); + + vr::VR_Shutdown(); + exit(0); +} + +static void HandleCommandLineFunction(char const * cmdLine, char * cwd) +{ + const int max_path = 2048; + if (!strcmp(cmdLine, "-help") || !strcmp(cmdLine, "-h")) + { + std::cout << "usage - OpenVR SpaceCalibrator, only pick one option" << std::endl; + std::cout << "-openvrpath print runtime path of openvr" << std::endl; + std::cout << "-installmanifest install the application vrmanifest" << std::endl; + std::cout << "-removemanifest remove the application vrmanifest" << std::endl; + std::cout << "-activatemultipledrivers enable multiple drivers in steamvr" << std::endl; + //Note that the next 2 are not on the windows build + std::cout << "-installdriver install the steam vr driver." << std::endl; + std::cout << "-uninstalldriver uninstall the steam vr driver." << std::endl; + std::cout << "-help -h print this message" << std::endl; + exit(0); + } + else if (!strcmp(cmdLine, "-openvrpath")) + { + char cruntimePath[max_path] = { 0 }; + HandleCommandLine::OpenVRPath(cruntimePath, max_path); + } + else if (!strcmp(cmdLine, "-installmanifest")) + { + HandleCommandLine::InstallManifest(cwd, max_path); + } + else if (!strcmp(cmdLine, "-removemanifest")) + { + HandleCommandLine::RemoveManifest(cwd); + } + else if (!strcmp(cmdLine, "-activatemultipledrivers")) + { + HandleCommandLine::ActivateMultipleDrivers(); + } + else if (!strcmp(cmdLine, "-installdriver")) + { + InstallDriver(max_path); + } + else if (!strcmp(cmdLine, "-uninstalldriver")) + { + UninstallDriver(max_path); + } +} + diff --git a/OpenVR-SpaceCalibrator/main_win.cpp b/OpenVR-SpaceCalibrator/main_win.cpp new file mode 100644 index 00000000..ba4e0fef --- /dev/null +++ b/OpenVR-SpaceCalibrator/main_win.cpp @@ -0,0 +1,82 @@ +#include "stdafx.h" + +#include "OpenVR-SpaceCalibrator.h" + +#include "Calibration.h" +#include "Configuration.h" +#include "EmbeddedFiles.h" +#include "UserInterface.h" + +#include +#include +#include +#include +#include +#include +#include +#include "HandleCommandLine.h" + +#pragma comment(linker,"\"/manifestdependency:type='win32' \ +name='Microsoft.Windows.Common-Controls' version='6.0.0.0' \ +processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"") + +extern "C" __declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001; +extern "C" __declspec(dllexport) DWORD AmdPowerXpressRequestHighPerformance = 0x00000001; + +static char cwd[MAX_PATH]; + +static void HandleCommandLineFunction(LPWSTR lpCmdLine) +{ + if (lstrcmp(lpCmdLine, L"-openvrpath") == 0) + { + char cruntimePath[MAX_PATH] = { 0 }; + HandleCommandLine::OpenVRPath(cruntimePath, MAX_PATH); + } + else if (lstrcmp(lpCmdLine, L"-installmanifest") == 0) + { + HandleCommandLine::InstallManifest(cwd, MAX_PATH); + } + else if (lstrcmp(lpCmdLine, L"-removemanifest") == 0) + { + HandleCommandLine::RemoveManifest(cwd); + } + else if (lstrcmp(lpCmdLine, L"-activatemultipledrivers") == 0) + { + HandleCommandLine::ActivateMultipleDrivers(); + } +} + +void CreateConsole() +{ + static bool created = false; + if (!created) + { + AllocConsole(); + FILE *file = nullptr; + freopen_s(&file, "CONIN$", "r", stdin); + freopen_s(&file, "CONOUT$", "w", stdout); + freopen_s(&file, "CONOUT$", "w", stderr); + created = true; + } +} + +void MessageBoxCallback(char * err){ + std::cerr << "Runtime error: " << err << std::endl; + wchar_t message[1024]; + swprintf(message, 1024, L"%hs", err); + MessageBox(nullptr, message, L"Runtime Error", 0); +} + +int APIENTRY wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPWSTR lpCmdLine, _In_ int nCmdShow) +{ + _getcwd(cwd, MAX_PATH); + HandleCommandLineFunction(lpCmdLine); + +#ifdef DEBUG_LOGS + CreateConsole(); +#endif + + return MainApplication(cwd, MessageBoxCallback); +} + + diff --git a/OpenVR-SpaceCalibrator/manifest.vrmanifest b/OpenVR-SpaceCalibrator/manifest.vrmanifest index 14cd0ad5..a3cfd3e7 100644 --- a/OpenVR-SpaceCalibrator/manifest.vrmanifest +++ b/OpenVR-SpaceCalibrator/manifest.vrmanifest @@ -4,6 +4,7 @@ "app_key": "pushrax.SpaceCalibrator", "launch_type": "binary", "binary_path_windows": "OpenVR-SpaceCalibrator.exe", + "binary_path_linux": "OpenVR-SpaceCalibrator", "is_dashboard_overlay": true, "strings": { @@ -13,4 +14,4 @@ } } }] -} \ No newline at end of file +} diff --git a/OpenVR-SpaceCalibrator/stdafx.h b/OpenVR-SpaceCalibrator/stdafx.h index b600ea54..e74d9c8d 100644 --- a/OpenVR-SpaceCalibrator/stdafx.h +++ b/OpenVR-SpaceCalibrator/stdafx.h @@ -1,12 +1,11 @@ #pragma once #include "targetver.h" - #define WIN32_LEAN_AND_MEAN #include +#include #include #include #include -#include #include diff --git a/OpenVR-SpaceCalibrator/targetver.h b/OpenVR-SpaceCalibrator/targetver.h index 87c0086d..adb81acb 100644 --- a/OpenVR-SpaceCalibrator/targetver.h +++ b/OpenVR-SpaceCalibrator/targetver.h @@ -4,5 +4,4 @@ // If you wish to build your application for a previous Windows platform, include WinSDKVer.h and // set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. - #include diff --git a/OpenVR-SpaceCalibratorDriver/Comms.h b/OpenVR-SpaceCalibratorDriver/Comms.h new file mode 100644 index 00000000..163da394 --- /dev/null +++ b/OpenVR-SpaceCalibratorDriver/Comms.h @@ -0,0 +1,148 @@ +#pragma once + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include "Logging.h" +#include "../Protocol.h" + +class UDPServerSocket{ + int sock; + public: + UDPServerSocket(const UDPServerSocket& other) = delete; + UDPServerSocket& operator=(const UDPServerSocket& other) = delete; + + UDPServerSocket(){} + + + bool Open(unsigned short port, int timeout=0){ + sockaddr_in my_addr = {}; + + my_addr.sin_family = AF_INET; + my_addr.sin_port = htons(port); + my_addr.sin_addr.s_addr = htonl(INADDR_ANY); + + //TODO verify that 0 is valid for UDP. + sock = socket(AF_INET, SOCK_DGRAM, 0); + + if(sock == -1){ + LOG("Failed to create socket: %s", strerror(errno)); + return false; + } + + + if(timeout > 0){ + struct timeval tv; + tv.tv_sec = timeout / 1000; + tv.tv_usec = (timeout % 1000) * 1000; + setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (const char *)&tv, sizeof(tv)); + } + + int err = bind(sock, (sockaddr*)&my_addr, sizeof(my_addr)); + if(err){ + LOG("Failed to bind socket: %s", strerror(errno)); + return false; + } + return true; + } + + template + bool Recv(RecvObj* obj, sockaddr* client, socklen_t* clientSize) { + size_t targetSize = sizeof(*obj); + size_t bytes = recvfrom(sock, (void*)obj, targetSize, 0, + client, clientSize); + if(bytes != targetSize){ + LOG("Error, recieved %d bytes when %d were expected", bytes, (int)targetSize); + return false; + } + else { + return true; + } + } + + template + bool Send(const SendObj& obj, sockaddr* sendTo, size_t sendToSize) { + ssize_t targetSize = sizeof(obj); + ssize_t bytes = sendto(sock, (void*)&obj, targetSize, 0, sendTo, sendToSize); + return targetSize == bytes; + } +}; + +template +class Comms{ + sockaddr_in lastClient; + socklen_t peer_addr_len; + + UDPServerSocket sock; + public: + Comms(const Comms& other) = delete; + Comms& operator=(const Comms& other) = delete; + + Comms(){ + if( !sock.Open(COMM_PORT_SERVER) ){ + LOG("%s", "Error opening server socket"); + } + } + + void Recv(RecvObj* obj){ + if(sock.Recv(obj, (sockaddr*) &lastClient, &peer_addr_len)){ + return; + } else { + LOG("%s", "failed to recve value"); + return; + } + } + + void Send(const SendObj& obj ) { + sock.Send(obj, (sockaddr*) &lastClient, sizeof(lastClient)); + } +}; + + +template +class Client{ + sockaddr_in serverAddr = {}; + socklen_t peer_addr_len = {}; + + UDPServerSocket sock; + public: + Client(const Client& other) = delete; + Client& operator=(const Client& other) = delete; + + Client(){ + if( !sock.Open(COMM_PORT_CLIENT, 1000) ){ + LOG("%s", "Error opening server socket"); + } + + serverAddr.sin_family = AF_INET; + serverAddr.sin_port = htons(COMM_PORT_SERVER); + serverAddr.sin_addr.s_addr = INADDR_ANY; + } + + bool Recv(RecvObj* obj){ + sockaddr_in lastClient; + lastClient.sin_family = AF_INET; + lastClient.sin_port = htons(COMM_PORT_SERVER); + lastClient.sin_addr.s_addr = INADDR_ANY; + + if(sock.Recv(obj, (sockaddr*) &lastClient, &peer_addr_len)){ + return true; + } else { + LOG("%s", "failed to recve value"); + return false; + } + } + + void Send(const SendObj& obj ) { + sock.Send(obj, (sockaddr*) &serverAddr, sizeof(serverAddr)); + } +}; + diff --git a/OpenVR-SpaceCalibratorDriver/Hooking.h b/OpenVR-SpaceCalibratorDriver/Hooking.h index 9b1f71ed..672b6e46 100644 --- a/OpenVR-SpaceCalibratorDriver/Hooking.h +++ b/OpenVR-SpaceCalibratorDriver/Hooking.h @@ -1,9 +1,19 @@ #pragma once #include "Logging.h" + +#ifdef __linux__ +#include +#include "string.h" +#include +#else #include -#include +#endif + #include +#include +#include +#include class IHook { @@ -26,13 +36,60 @@ class IHook template class Hook : public IHook { + void * obj = nullptr; + int offset = 0; public: FuncType originalFunc = nullptr; Hook(const std::string &name) : IHook(name) { } - bool CreateHookInObjectVTable(void *object, int vtableOffset, void *detourFunction) +#ifdef __linux__ + template + bool CreateHookInObjectVTable(void *object, int vtableOffset, T* detourFunction) { - // For virtual objects, VC++ adds a pointer to the vtable as the first member. + long pageSize = sysconf(_SC_PAGESIZE); + + obj = object; + offset = vtableOffset; + // For virtual objects, VC++ (and from what I can tell gcc) adds a pointer to the vtable as the first member. + // To access the vtable, we simply dereference the object. + void **vtable = *((void ***)object); + + // The vtable itself is an array of pointers to member functions, + // in the order they were declared in. + originalFunc = (FuncType) vtable[vtableOffset]; + targetFunc = (void*) vtable[vtableOffset]; + + if((uintptr_t) vtable % 8 != 0 ) + { + obj = nullptr; + originalFunc = nullptr; + throw std::runtime_error("vtable entry not aligned to 8 byte pointer"); + } + + uintptr_t otherPage = (uintptr_t) vtable & ~(uintptr_t) (pageSize - 1); + int err = mprotect((void*) otherPage, pageSize, PROT_READ | PROT_WRITE | PROT_EXEC); + if(err){ + LOG("Failed to set memory protection %d-%s", err, strerror(errno)); + } + else { + //LOG("%s", "Setting vtable value"); + vtable[vtableOffset] = (void*) detourFunction; + //LOG("%s", "Resetting permissions vtable value"); + mprotect((void*) otherPage, pageSize, PROT_READ | PROT_EXEC); + } + + LOG("Enabled Linux hook for %s", name.c_str()); + enabled = true; + return true; + } +#else + template + bool CreateHookInObjectVTable(void *object, int vtableOffset, T* detourFunction) + { + obj = object; + offset = vtableOffset; + + // For virtual objects, VC++ (and from what I can tell gcc) adds a pointer to the vtable as the first member. // To access the vtable, we simply dereference the object. void **vtable = *((void ***)object); @@ -59,6 +116,17 @@ template class Hook : public IHook enabled = true; return true; } +#endif + +#ifdef __linux__ + void Destroy() + { + //redoing it is enough if it was done the first time. + if(obj && originalFunc) CreateHookInObjectVTable(obj, offset, originalFunc); + obj = nullptr; + originalFunc = nullptr; + } +#else void Destroy() { @@ -68,8 +136,9 @@ template class Hook : public IHook enabled = false; } } +#endif private: bool enabled = false; void* targetFunc = nullptr; -}; \ No newline at end of file +}; diff --git a/OpenVR-SpaceCalibratorDriver/IPCServer.h b/OpenVR-SpaceCalibratorDriver/IPCServer.h index 8777704e..42217593 100644 --- a/OpenVR-SpaceCalibratorDriver/IPCServer.h +++ b/OpenVR-SpaceCalibratorDriver/IPCServer.h @@ -6,15 +6,12 @@ #include #include -#define WIN32_LEAN_AND_MEAN -#include - class ServerTrackedDeviceProvider; class IPCServer { public: - IPCServer(ServerTrackedDeviceProvider *driver) : driver(driver) { } + IPCServer(ServerTrackedDeviceProvider *driver); ~IPCServer(); void Run(); @@ -23,31 +20,11 @@ class IPCServer private: void HandleRequest(const protocol::Request &request, protocol::Response &response); - struct PipeInstance - { - OVERLAPPED overlap; // Used by the API - HANDLE pipe; - IPCServer *server; - - protocol::Request request; - protocol::Response response; - }; - - PipeInstance *CreatePipeInstance(HANDLE pipe); - void ClosePipeInstance(PipeInstance *pipeInst); - static void RunThread(IPCServer *_this); - static BOOL CreateAndConnectInstance(LPOVERLAPPED overlap, HANDLE &pipe); - static void WINAPI CompletedReadCallback(DWORD err, DWORD bytesRead, LPOVERLAPPED overlap); - static void WINAPI CompletedWriteCallback(DWORD err, DWORD bytesWritten, LPOVERLAPPED overlap); - std::thread mainThread; bool running = false; bool stop = false; - std::set pipes; - HANDLE connectEvent; - ServerTrackedDeviceProvider *driver; }; diff --git a/OpenVR-SpaceCalibratorDriver/IPCServer_linux.cpp b/OpenVR-SpaceCalibratorDriver/IPCServer_linux.cpp new file mode 100644 index 00000000..7dfe6826 --- /dev/null +++ b/OpenVR-SpaceCalibratorDriver/IPCServer_linux.cpp @@ -0,0 +1,60 @@ +#include "IPCServer.h" +#include "Logging.h" +#include "ServerTrackedDeviceProvider.h" +#include "Comms.h" + +void IPCServer::HandleRequest(const protocol::Request &request, protocol::Response &response) +{ + switch (request.type) + { + case protocol::RequestHandshake: + response.type = protocol::ResponseHandshake; + response.protocol.version = protocol::Version; + break; + + case protocol::RequestSetDeviceTransform: + driver->SetDeviceTransform(request.setDeviceTransform); + response.type = protocol::ResponseSuccess; + break; + + default: + LOG("Invalid IPC request: %d", request.type); + break; + } +} + +IPCServer::~IPCServer() +{ + Stop(); +} + +void IPCServer::Run() +{ + mainThread = std::thread(RunThread, this); +} + +void IPCServer::Stop() +{ + TRACE("%s", "IPCServer::Stop()"); + if (!running) + return; + + + stop = true; +} + +void IPCServer::RunThread(IPCServer *_this) +{ + Comms comms; + + protocol::Response response; + protocol::Request request; + + while(!_this->stop){ + comms.Recv(&request); + _this->HandleRequest(request, response); + comms.Send(response); + } + LOG("%s", "Stop requested"); +} + diff --git a/OpenVR-SpaceCalibratorDriver/IPCServer.cpp b/OpenVR-SpaceCalibratorDriver/IPCServer_win.cpp similarity index 79% rename from OpenVR-SpaceCalibratorDriver/IPCServer.cpp rename to OpenVR-SpaceCalibratorDriver/IPCServer_win.cpp index 5bbd0c0f..358252ac 100644 --- a/OpenVR-SpaceCalibratorDriver/IPCServer.cpp +++ b/OpenVR-SpaceCalibratorDriver/IPCServer_win.cpp @@ -2,6 +2,33 @@ #include "Logging.h" #include "ServerTrackedDeviceProvider.h" +struct IPCClientImpl{ + struct PipeInstance + { + OVERLAPPED overlap; // Used by the API + HANDLE pipe; + IPCServer *server; + + protocol::Request request; + protocol::Response response; + }; + + PipeInstance *CreatePipeInstance(HANDLE pipe); + void ClosePipeInstance(PipeInstance *pipeInst); + static void WINAPI CompletedReadCallback(DWORD err, DWORD bytesRead, LPOVERLAPPED overlap); + static void WINAPI CompletedWriteCallback(DWORD err, DWORD bytesWritten, LPOVERLAPPED overlap); + static BOOL CreateAndConnectInstance(LPOVERLAPPED overlap, HANDLE &pipe); + + std::set pipes; + HANDLE connectEvent; +}; + + +IPCServer::IPCServer(ServerTrackedDeviceProvider *driver); : driver(driver) +{ + impl = std::make_unique(); +} + void IPCServer::HandleRequest(const protocol::Request &request, protocol::Response &response) { switch (request.type) @@ -34,18 +61,17 @@ void IPCServer::Run() void IPCServer::Stop() { - TRACE("IPCServer::Stop()"); + TRACE("%s", "IPCServer::Stop()"); if (!running) return; - stop = true; + SetEvent(connectEvent); mainThread.join(); running = false; TRACE("IPCServer::Stop() finished"); } - -IPCServer::PipeInstance *IPCServer::CreatePipeInstance(HANDLE pipe) +IPCServerImpl::PipeInstance *IPCServerImpl::CreatePipeInstance(HANDLE pipe) { auto pipeInst = new PipeInstance; pipeInst->pipe = pipe; @@ -54,7 +80,7 @@ IPCServer::PipeInstance *IPCServer::CreatePipeInstance(HANDLE pipe) return pipeInst; } -void IPCServer::ClosePipeInstance(PipeInstance *pipeInst) +void IPCServerImpl::ClosePipeInstance(PipeInstance *pipeInst) { DisconnectNamedPipe(pipeInst->pipe); CloseHandle(pipeInst->pipe); @@ -122,13 +148,14 @@ void IPCServer::RunThread(IPCServer *_this) for (auto &pipeInst : _this->pipes) { - _this->ClosePipeInstance(pipeInst); + _this->impl->ClosePipeInstance(pipeInst); } _this->pipes.clear(); } -BOOL IPCServer::CreateAndConnectInstance(LPOVERLAPPED overlap, HANDLE &pipe) +BOOL IPCServerImpl::CreateAndConnectInstance(LPOVERLAPPED overlap, HANDLE &pipe) { + pipe = CreateNamedPipe( TEXT(OPENVR_SPACECALIBRATOR_PIPE_NAME), PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, @@ -165,7 +192,7 @@ BOOL IPCServer::CreateAndConnectInstance(LPOVERLAPPED overlap, HANDLE &pipe) return FALSE; } -void IPCServer::CompletedReadCallback(DWORD err, DWORD bytesRead, LPOVERLAPPED overlap) +void IPCServerImpl::CompletedReadCallback(DWORD err, DWORD bytesRead, LPOVERLAPPED overlap) { PipeInstance *pipeInst = (PipeInstance *) overlap; BOOL success = FALSE; @@ -196,7 +223,7 @@ void IPCServer::CompletedReadCallback(DWORD err, DWORD bytesRead, LPOVERLAPPED o } } -void IPCServer::CompletedWriteCallback(DWORD err, DWORD bytesWritten, LPOVERLAPPED overlap) +void IPCServerImpl::CompletedWriteCallback(DWORD err, DWORD bytesWritten, LPOVERLAPPED overlap) { PipeInstance *pipeInst = (PipeInstance *) overlap; BOOL success = FALSE; diff --git a/OpenVR-SpaceCalibratorDriver/InterfaceHookInjector.cpp b/OpenVR-SpaceCalibratorDriver/InterfaceHookInjector.cpp index 62117463..a2fe5b12 100644 --- a/OpenVR-SpaceCalibratorDriver/InterfaceHookInjector.cpp +++ b/OpenVR-SpaceCalibratorDriver/InterfaceHookInjector.cpp @@ -1,8 +1,9 @@ #include "Logging.h" -#include "Hooking.h" #include "InterfaceHookInjector.h" #include "ServerTrackedDeviceProvider.h" +#include "Hooking.h" + static ServerTrackedDeviceProvider *Driver = nullptr; static Hook @@ -62,6 +63,7 @@ static void *DetourGetGenericInterface(vr::IVRDriverContext *_this, const char * void InjectHooks(ServerTrackedDeviceProvider *driver, vr::IVRDriverContext *pDriverContext) { + LOG("%s", "Injecting hooks"); Driver = driver; auto err = MH_Initialize(); @@ -80,4 +82,4 @@ void DisableHooks() { IHook::DestroyAll(); MH_Uninitialize(); -} \ No newline at end of file +} diff --git a/OpenVR-SpaceCalibratorDriver/Logging.cpp b/OpenVR-SpaceCalibratorDriver/Logging.cpp index 67b30778..33f99538 100644 --- a/OpenVR-SpaceCalibratorDriver/Logging.cpp +++ b/OpenVR-SpaceCalibratorDriver/Logging.cpp @@ -1,12 +1,20 @@ #define _CRT_SECURE_NO_DEPRECATE #include "Logging.h" #include +#include + +#ifdef __linux__ +#include "StaticConfig.h" +#else +#define DRIVER_LOG_FILE "space_calibrator_driver.log" +#endif + FILE *LogFile; void OpenLogFile() { - LogFile = fopen("space_calibrator_driver.log", "a"); + LogFile = fopen(DRIVER_LOG_FILE, "a"); if (LogFile == nullptr) { LogFile = stderr; @@ -15,14 +23,26 @@ void OpenLogFile() tm TimeForLog() { + if(LogFile == nullptr){ + OpenLogFile(); + } + auto now = std::chrono::system_clock::now(); auto nowTime = std::chrono::system_clock::to_time_t(now); +#ifdef __linux__ + tm buf; + auto tm = localtime_r(&nowTime, &buf); + return *tm; +#else tm value; auto tm = localtime_s(&value, &nowTime); return value; +#endif } + + void LogFlush() { fflush(LogFile); -} \ No newline at end of file +} diff --git a/OpenVR-SpaceCalibratorDriver/OpenVR-SpaceCalibratorDriver.h b/OpenVR-SpaceCalibratorDriver/OpenVR-SpaceCalibratorDriver.h index 42b3263e..ef06664b 100644 --- a/OpenVR-SpaceCalibratorDriver/OpenVR-SpaceCalibratorDriver.h +++ b/OpenVR-SpaceCalibratorDriver/OpenVR-SpaceCalibratorDriver.h @@ -1,7 +1,19 @@ #pragma once #ifdef OPENVRSPACECALIBRATORDRIVER_EXPORTS + +#ifdef __linux__ +#define OPENVRSPACECALIBRATORDRIVER_API extern "C" +#else #define OPENVRSPACECALIBRATORDRIVER_API extern "C" __declspec(dllexport) +#endif + +#else + +#ifdef __linux__ +#define OPENVRSPACECALIBRATORDRIVER_API extern "C" #else #define OPENVRSPACECALIBRATORDRIVER_API extern "C" __declspec(dllimport) #endif + +#endif diff --git a/OpenVR-SpaceCalibratorDriver/ServerTrackedDeviceProvider.cpp b/OpenVR-SpaceCalibratorDriver/ServerTrackedDeviceProvider.cpp index 55b09512..ef84e56b 100644 --- a/OpenVR-SpaceCalibratorDriver/ServerTrackedDeviceProvider.cpp +++ b/OpenVR-SpaceCalibratorDriver/ServerTrackedDeviceProvider.cpp @@ -1,13 +1,19 @@ #include "ServerTrackedDeviceProvider.h" #include "Logging.h" #include "InterfaceHookInjector.h" +#include +#include vr::EVRInitError ServerTrackedDeviceProvider::Init(vr::IVRDriverContext *pDriverContext) { - TRACE("ServerTrackedDeviceProvider::Init()"); + + //LOG("%s", "Starting loop break"); + //loopBreak(); + + TRACE("%s", "ServerTrackedDeviceProvider::Init()"); VR_INIT_SERVER_DRIVER_CONTEXT(pDriverContext); - memset(transforms, 0, vr::k_unMaxTrackedDeviceCount * sizeof DeviceTransform); + memset(transforms, 0, vr::k_unMaxTrackedDeviceCount * sizeof(DeviceTransform)); InjectHooks(this, pDriverContext); server.Run(); @@ -17,7 +23,7 @@ vr::EVRInitError ServerTrackedDeviceProvider::Init(vr::IVRDriverContext *pDriver void ServerTrackedDeviceProvider::Cleanup() { - TRACE("ServerTrackedDeviceProvider::Cleanup()"); + TRACE("%s", "ServerTrackedDeviceProvider::Cleanup()"); server.Stop(); DisableHooks(); VR_CLEANUP_SERVER_DRIVER_CONTEXT(); diff --git a/OpenVR-SpaceCalibratorDriver/ServerTrackedDeviceProvider.h b/OpenVR-SpaceCalibratorDriver/ServerTrackedDeviceProvider.h index 04e2edd8..da348dc3 100644 --- a/OpenVR-SpaceCalibratorDriver/ServerTrackedDeviceProvider.h +++ b/OpenVR-SpaceCalibratorDriver/ServerTrackedDeviceProvider.h @@ -16,21 +16,21 @@ class ServerTrackedDeviceProvider : public vr::IServerTrackedDeviceProvider virtual void Cleanup() override; /** Returns the version of the ITrackedDeviceServerDriver interface used by this driver */ - virtual const char * const *GetInterfaceVersions() { return vr::k_InterfaceVersions; } + virtual const char * const *GetInterfaceVersions() override { return vr::k_InterfaceVersions; } /** Allows the driver do to some work in the main loop of the server. */ - virtual void RunFrame() { } + virtual void RunFrame() override { } /** Returns true if the driver wants to block Standby mode. */ - virtual bool ShouldBlockStandbyMode() { return false; } + virtual bool ShouldBlockStandbyMode() override { return false; } /** Called when the system is entering Standby mode. The driver should switch itself into whatever sort of low-power * state it has. */ - virtual void EnterStandby() { } + virtual void EnterStandby() override { } /** Called when the system is leaving Standby mode. The driver should switch itself back to full operation. */ - virtual void LeaveStandby() { } + virtual void LeaveStandby() override { } ////// End vr::IServerTrackedDeviceProvider functions @@ -50,4 +50,4 @@ class ServerTrackedDeviceProvider : public vr::IServerTrackedDeviceProvider }; DeviceTransform transforms[vr::k_unMaxTrackedDeviceCount]; -}; \ No newline at end of file +}; diff --git a/OpenVR-SpaceCalibratorDriver/dllmain.cpp b/OpenVR-SpaceCalibratorDriver/dllmain.cpp index 21ccf7c5..41655035 100644 --- a/OpenVR-SpaceCalibratorDriver/dllmain.cpp +++ b/OpenVR-SpaceCalibratorDriver/dllmain.cpp @@ -1,6 +1,24 @@ #include "Logging.h" #include "../Version.h" +#ifdef __linux__ +#include + +__attribute__((constructor)) +static void loaded(){ + int pid = getpid(); + LOG("OpenVR-SpaceCalibratorDriver " SPACECAL_VERSION_STRING " loaded into pid %d", pid); +} + +__attribute__((destructor)) +static void unloaded(){ + int pid = getpid(); + LOG("OpenVR-SpaceCalibratorDriver " SPACECAL_VERSION_STRING " unloaded from pid %d", pid); +} + + + +#else #define WIN32_LEAN_AND_MEAN #include #include @@ -23,3 +41,4 @@ BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserv return TRUE; } +#endif diff --git a/Protocol.h b/Protocol.h index ff0b8e7a..b565a584 100644 --- a/Protocol.h +++ b/Protocol.h @@ -8,6 +8,10 @@ #define OPENVR_SPACECALIBRATOR_PIPE_NAME "\\\\.\\pipe\\OpenVRSpaceCalibratorDriver" + +#define COMM_PORT_SERVER 5473 +#define COMM_PORT_CLIENT 5474 + namespace protocol { const uint32_t Version = 2; @@ -42,23 +46,23 @@ namespace protocol vr::HmdQuaternion_t rotation; double scale; - SetDeviceTransform(uint32_t id, bool enabled) : - openVRID(id), enabled(enabled), updateTranslation(false), updateRotation(false), updateScale(false) { } + SetDeviceTransform(uint32_t id, bool _enabled) : + openVRID(id), enabled(_enabled), updateTranslation(false), updateRotation(false), updateScale(false) { } - SetDeviceTransform(uint32_t id, bool enabled, vr::HmdVector3d_t translation) : - openVRID(id), enabled(enabled), updateTranslation(true), updateRotation(false), updateScale(false), translation(translation) { } + SetDeviceTransform(uint32_t id, bool _enabled, vr::HmdVector3d_t _translation) : + openVRID(id), enabled(_enabled), updateTranslation(true), updateRotation(false), updateScale(false), translation(_translation) { } - SetDeviceTransform(uint32_t id, bool enabled, vr::HmdQuaternion_t rotation) : - openVRID(id), enabled(enabled), updateTranslation(false), updateRotation(true), updateScale(false), rotation(rotation) { } + SetDeviceTransform(uint32_t id, bool _enabled, vr::HmdQuaternion_t _rotation) : + openVRID(id), enabled(_enabled), updateTranslation(false), updateRotation(true), updateScale(false), rotation(_rotation) { } - SetDeviceTransform(uint32_t id, bool enabled, double scale) : - openVRID(id), enabled(enabled), updateTranslation(false), updateRotation(false), updateScale(true), scale(scale) { } + SetDeviceTransform(uint32_t id, bool _enabled, double _scale) : + openVRID(id), enabled(_enabled), updateTranslation(false), updateRotation(false), updateScale(true), scale(_scale) { } - SetDeviceTransform(uint32_t id, bool enabled, vr::HmdVector3d_t translation, vr::HmdQuaternion_t rotation) : - openVRID(id), enabled(enabled), updateTranslation(true), updateRotation(true), updateScale(false), translation(translation), rotation(rotation) { } + SetDeviceTransform(uint32_t id, bool _enabled, vr::HmdVector3d_t _translation, vr::HmdQuaternion_t _rotation) : + openVRID(id), enabled(_enabled), updateTranslation(true), updateRotation(true), updateScale(false), translation(_translation), rotation(_rotation) { } - SetDeviceTransform(uint32_t id, bool enabled, vr::HmdVector3d_t translation, vr::HmdQuaternion_t rotation, double scale) : - openVRID(id), enabled(enabled), updateTranslation(true), updateRotation(true), updateScale(true), translation(translation), rotation(rotation), scale(scale) { } + SetDeviceTransform(uint32_t id, bool _enabled, vr::HmdVector3d_t _translation, vr::HmdQuaternion_t _rotation, double _scale) : + openVRID(id), enabled(_enabled), updateTranslation(true), updateRotation(true), updateScale(true), translation(_translation), rotation(_rotation), scale(_scale) { } }; struct Request @@ -70,7 +74,7 @@ namespace protocol }; Request() : type(RequestInvalid) { } - Request(RequestType type) : type(type) { } + Request(RequestType _type) : type(_type) { } }; struct Response @@ -82,6 +86,6 @@ namespace protocol }; Response() : type(ResponseInvalid) { } - Response(ResponseType type) : type(type) { } + Response(ResponseType _type) : type(_type) { } }; -} \ No newline at end of file +} diff --git a/README.md b/README.md index 5b4b1f3f..3557b3a5 100644 --- a/README.md +++ b/README.md @@ -42,10 +42,29 @@ As part of first time setup, or when you make a change to your space (e.g. move You can calibrate without using the dashboard overlay by unminimizing Space Calibrator after opening SteamVR (it starts minimized). This is required if you're calibrating for a lone HMD without any devices in its tracking system. -### Compiling your own build +### Compiling your own Windows build Open `OpenVR-SpaceCalibrator.sln` in Visual Studio 2017 and build. There are no external dependencies. +### Compiling on Linux +Dependencies: eigen, openvr, python3, libgl + +Further dependencies will be downloaded as git submodules as part of the build process. + +Run the following from the main repo directory to build and install. + +``` +mkdir build +cd build +cmake .. +make +make install +``` + +The build prefix can be modified so that it points to an interanl directory for testing without installing. + + + ### The math See [math.pdf](https://github.com/pushrax/OpenVR-SpaceCalibrator/blob/master/math.pdf) for details. diff --git a/StaticConfig.h.in b/StaticConfig.h.in new file mode 100644 index 00000000..40b27bb5 --- /dev/null +++ b/StaticConfig.h.in @@ -0,0 +1,5 @@ +#cmakedefine DRIVER_LOG_FILE "@DRIVER_LOG_FILE@" +#cmakedefine APP_MANIFEST_PATH "@APP_MANIFEST_PATH@" +#cmakedefine DRIVER_MANIFEST_PATH "@DRIVER_MANIFEST_PATH@" +#cmakedefine DRIVER_INSTALLER_PATH "@DRIVER_INSTALLER_PATH@" +#cmakedefine LINUX_CONFIG_DIR "@LINUX_CONFIG_DIR@" diff --git a/Version.h b/Version.h index 281e1715..40847b38 100644 --- a/Version.h +++ b/Version.h @@ -1,3 +1,3 @@ #pragma once -#define SPACECAL_VERSION_STRING "1.4" \ No newline at end of file +#define SPACECAL_VERSION_STRING "1.4" diff --git a/driverInstall.py b/driverInstall.py new file mode 100755 index 00000000..08fb965d --- /dev/null +++ b/driverInstall.py @@ -0,0 +1,76 @@ +#!/usr/bin/env python3 +import os, sys +import subprocess +import re +import argparse + +#vrpathreg = "/home/zack/.local/share/Steam/steamapps/common/SteamVR/bin/vrpathreg.sh" + +def GetDrivers(vrpathreg): + proc = subprocess.Popen([vrpathreg], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, encoding='utf-8') + (stdout, _) = proc.communicate() + + lineno = 0 + externalReg = re.compile('.*External Drivers:.*') + lines = stdout.split('\n') + for line in lines: + lineno += 1 + if externalReg.match(line): + break + + lines = [ x.strip().split(':')[1].strip() for x in lines[lineno:] if len(x) > 0] + return lines + +def RemoveDriver(vrpathreg, driver): + cmd = [vrpathreg, 'removedriver', driver] + print(cmd) + proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, encoding='utf-8') + (stdout, _) = proc.communicate() + +def AddDriver(vrpathreg, driver): + cmd = [vrpathreg, 'adddriver', driver] + print(cmd) + proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, encoding='utf-8') + (stdout, _) = proc.communicate() + +def main(): + parser = argparse.ArgumentParser() + + parser.add_argument('--toInstall', help="Driver to install (folder path)", required=True) + parser.add_argument('--vrpathreg', help="Path to vrpathreg.sh", required=True) + + args = parser.parse_args() + + fail = False + if not os.path.exists(args.toInstall): + print("Driver path [{args.toInstall}] does not exist") + fail = True + + if not os.path.exists(args.vrpathreg): + print("Path to vrpathreg.sh [{args.toInstall}] does not exist") + fail = True + + if fail: + return + + drivers = GetDrivers(args.vrpathreg) + + spaceCalReg = re.compile('.*01spacecalibrator.*') + + for driver in drivers: + RemoveDriver(args.vrpathreg, driver) + + AddDriver(args.vrpathreg, args.toInstall) + + for driver in drivers[::-1]: + if spaceCalReg.match(driver): + continue + + AddDriver(args.vrpathreg, driver) + + pass + + +if __name__ == "__main__": + main() + diff --git a/modules/imgui b/modules/imgui new file mode 160000 index 00000000..cdebd70e --- /dev/null +++ b/modules/imgui @@ -0,0 +1 @@ +Subproject commit cdebd70e15f57eb455485a50acb25ebc8787ab78 diff --git a/modules/openvr b/modules/openvr new file mode 160000 index 00000000..08de3821 --- /dev/null +++ b/modules/openvr @@ -0,0 +1 @@ +Subproject commit 08de3821dfd3aa46f778376680c68f33b9fdcb6c