From e29060235bce50a35131abbc261e14537871ab5c Mon Sep 17 00:00:00 2001 From: Yaroslav Bolyukin Date: Sun, 6 Mar 2022 14:32:42 +0300 Subject: [PATCH] refactor: rust rewrite, dynamic reconfiguration --- .cargo/config.toml | 3 + .envrc | 4 +- .gitignore | 2 +- .rustfmt.toml | 1 + Cargo.lock | 455 +++ Cargo.toml | 24 + Makefile | 32 - bin/lens-server/.envrc | 1 + {lensServer => bin/lens-server}/Cargo.toml | 11 +- bin/lens-server/src/main.rs | 169 ++ crates/lens-client/Cargo.toml | 16 + crates/lens-client/src/lib.rs | 88 + {vivectl => crates/lens-protocol}/Cargo.toml | 11 +- crates/lens-protocol/src/lib.rs | 190 ++ crates/vive-hid/Cargo.toml | 16 + crates/vive-hid/src/lib.rs | 286 ++ dist/.gitignore | 1 + dist/install.sh | 30 + dist/lens-server/.gitignore | 1 + .../lens-server}/LibLensDistortion.dll | Bin .../lens-server}/opencv_world346.dll | Bin driver.cpp | 328 --- driver.h | 33 - flake.lock | 59 +- flake.nix | 56 +- lensServer/.cargo/config | 2 - lensServer/.envrc | 3 - lensServer/.gitignore | 1 - lensServer/Cargo.lock | 83 - lensServer/asset/config.json | 448 --- lensServer/dist/.gitignore | 0 lensServer/flake.lock | 93 - lensServer/flake.nix | 39 - lensServer/src/main.rs | 215 -- lens_server.h | 22 - src/driver_context.rs | 69 + src/driver_host.rs | 183 ++ src/error.rs | 68 + src/factory.rs | 63 + src/hmd.rs | 195 ++ src/lib.rs | 17 + src/log.rs | 37 + src/openvr/.gitignore | 2 + openvr_driver.h => src/openvr/a.hpp | 0 src/openvr/a.jsonnet | 82 + src/openvr/gen_mod_rs.sh | 8 + src/openvr/mod.rs | 2552 +++++++++++++++++ src/openvr/mod_rs.jsonnet | 151 + src/server_tracked_provider.rs | 71 + src/settings.rs | 65 + vivectl/.envrc | 3 - vivectl/.gitignore | 1 - vivectl/Cargo.lock | 297 -- vivectl/flake.lock | 93 - vivectl/flake.nix | 33 - vivectl/src/main.rs | 275 -- 56 files changed, 4960 insertions(+), 2028 deletions(-) create mode 100644 .cargo/config.toml create mode 100644 .rustfmt.toml create mode 100644 Cargo.lock create mode 100644 Cargo.toml delete mode 100644 Makefile create mode 100644 bin/lens-server/.envrc rename {lensServer => bin/lens-server}/Cargo.toml (50%) create mode 100644 bin/lens-server/src/main.rs create mode 100644 crates/lens-client/Cargo.toml create mode 100644 crates/lens-client/src/lib.rs rename {vivectl => crates/lens-protocol}/Cargo.toml (51%) create mode 100644 crates/lens-protocol/src/lib.rs create mode 100644 crates/vive-hid/Cargo.toml create mode 100644 crates/vive-hid/src/lib.rs create mode 100644 dist/.gitignore create mode 100755 dist/install.sh create mode 100644 dist/lens-server/.gitignore rename {lensServer/asset => dist/lens-server}/LibLensDistortion.dll (100%) rename {lensServer/asset => dist/lens-server}/opencv_world346.dll (100%) delete mode 100644 driver.cpp delete mode 100644 driver.h delete mode 100644 lensServer/.cargo/config delete mode 100644 lensServer/.envrc delete mode 100644 lensServer/.gitignore delete mode 100644 lensServer/Cargo.lock delete mode 100644 lensServer/asset/config.json delete mode 100644 lensServer/dist/.gitignore delete mode 100644 lensServer/flake.lock delete mode 100644 lensServer/flake.nix delete mode 100644 lensServer/src/main.rs delete mode 100644 lens_server.h create mode 100644 src/driver_context.rs create mode 100644 src/driver_host.rs create mode 100644 src/error.rs create mode 100644 src/factory.rs create mode 100644 src/hmd.rs create mode 100644 src/lib.rs create mode 100644 src/log.rs create mode 100644 src/openvr/.gitignore rename openvr_driver.h => src/openvr/a.hpp (100%) create mode 100644 src/openvr/a.jsonnet create mode 100755 src/openvr/gen_mod_rs.sh create mode 100644 src/openvr/mod.rs create mode 100644 src/openvr/mod_rs.jsonnet create mode 100644 src/server_tracked_provider.rs create mode 100644 src/settings.rs delete mode 100644 vivectl/.envrc delete mode 100644 vivectl/.gitignore delete mode 100644 vivectl/Cargo.lock delete mode 100644 vivectl/flake.lock delete mode 100644 vivectl/flake.nix delete mode 100644 vivectl/src/main.rs diff --git a/.cargo/config.toml b/.cargo/config.toml new file mode 100644 index 0000000..e2ac979 --- /dev/null +++ b/.cargo/config.toml @@ -0,0 +1,3 @@ +[target.x86_64-pc-windows-gnu] +linker = "x86_64-w64-mingw32-cc" +runner = "wine64" diff --git a/.envrc b/.envrc index feae7f4..11f188f 100644 --- a/.envrc +++ b/.envrc @@ -1,3 +1 @@ -source_url "https://raw.githubusercontent.com/nix-community/nix-direnv/1.2.3/direnvrc" "sha256-/aHqL/6nLpHcZJcB5/7/5+mO338l28uFbq88DMfWJn4=" - -use flake +use flake .#default diff --git a/.gitignore b/.gitignore index 8346342..ea8c4bf 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1 @@ -driver_lighthouse_proxy.so +/target diff --git a/.rustfmt.toml b/.rustfmt.toml new file mode 100644 index 0000000..218e203 --- /dev/null +++ b/.rustfmt.toml @@ -0,0 +1 @@ +hard_tabs = true diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..68fcc49 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,455 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "ansi_term" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" +dependencies = [ + "winapi", +] + +[[package]] +name = "anyhow" +version = "1.0.55" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "159bb86af3a200e19a068f4224eae4c8bb2d0fa054c7e5d1cacd5cef95e684cd" + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "bincode" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" +dependencies = [ + "serde", +] + +[[package]] +name = "cc" +version = "1.0.73" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "cppvtbl" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "574c8b3f359807d21c4e211e076a9084656971b5a0b7aeb4d464ba20a029c719" +dependencies = [ + "cppvtbl-macros", +] + +[[package]] +name = "cppvtbl-macros" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1ab98c91f5b37bbac5de658fdbb22dd02a475106f829c0d567de46963ed4cb9" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "crc32fast" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "driver_lighthouse" +version = "0.1.0" +dependencies = [ + "cppvtbl", + "lens-client", + "lens-protocol", + "libloading", + "once_cell", + "process_path", + "real_c_string", + "thiserror", + "tracing", + "tracing-subscriber", + "vive-hid", +] + +[[package]] +name = "flate2" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e6988e897c1c9c485f43b47a529cef42fde0547f9d8d41a7062518f1d8fc53f" +dependencies = [ + "cfg-if", + "crc32fast", + "libc", + "miniz_oxide", +] + +[[package]] +name = "hidapi" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fd21b5ac4a597bf657ed92a5b078f46a011837bda14afb7a07a5c1157c33ac2" +dependencies = [ + "cc", + "libc", + "pkg-config", +] + +[[package]] +name = "itoa" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35" + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "lens-client" +version = "0.1.0" +dependencies = [ + "lens-protocol", + "process_path", + "serde_json", + "thiserror", + "tracing", + "tracing-subscriber", +] + +[[package]] +name = "lens-protocol" +version = "0.1.0" +dependencies = [ + "bincode", + "serde", + "serde_json", + "thiserror", +] + +[[package]] +name = "lens-server" +version = "0.1.0" +dependencies = [ + "anyhow", + "lens-protocol", + "libloading", + "process_path", + "serde_json", + "tracing", + "tracing-subscriber", +] + +[[package]] +name = "libc" +version = "0.2.119" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bf2e165bb3457c8e098ea76f3e3bc9db55f87aa90d52d0e6be741470916aaa4" + +[[package]] +name = "libloading" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "efbc0f03f9a775e9f6aed295c6a1ba2253c5757a9e03d55c6caa46a681abcddd" +dependencies = [ + "cfg-if", + "winapi", +] + +[[package]] +name = "log" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "miniz_oxide" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b" +dependencies = [ + "adler", + "autocfg", +] + +[[package]] +name = "once_cell" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87f3e037eac156d1775da914196f0f37741a274155e34a0b7e427c35d2a2ecb9" + +[[package]] +name = "pin-project-lite" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e280fbe77cc62c91527259e9442153f4688736748d24660126286329742b4c6c" + +[[package]] +name = "pkg-config" +version = "0.3.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58893f751c9b0412871a09abd62ecd2a00298c6c83befa223ef98c52aef40cbe" + +[[package]] +name = "proc-macro2" +version = "1.0.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029" +dependencies = [ + "unicode-xid", +] + +[[package]] +name = "process_path" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abe7f344db15ba012152680e204d5869ec60cb0d8acfda230069484f4fa3811b" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "quote" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "864d3e96a899863136fc6e99f3d7cae289dafe43bf2c5ac19b70df7210c0a145" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "real_c_string" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a58f0db826345d4f9ce00f375c6132e90e96aba9e38b840572b5b70728ba6ddf" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "ryu" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f" + +[[package]] +name = "serde" +version = "1.0.136" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce31e24b01e1e524df96f1c2fdd054405f8d7376249a5110886fb4b658484789" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.136" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08597e7152fcd306f41838ed3e37be9eaeed2b61c42e2117266a554fab4662f9" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e8d9fa5c3b304765ce1fd9c4c8a3de2c8db365a5b91be52f186efc675681d95" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "sharded-slab" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "smallvec" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83" + +[[package]] +name = "syn" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a65b3f4ffa0092e9887669db0eae07941f023991ab58ea44da8fe8e2d511c6b" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + +[[package]] +name = "thiserror" +version = "1.0.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "thread_local" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5516c27b78311c50bf42c071425c560ac799b11c30b31f87e3081965fe5e0180" +dependencies = [ + "once_cell", +] + +[[package]] +name = "tracing" +version = "0.1.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6c650a8ef0cd2dd93736f033d21cbd1224c5a967aa0c258d00fcf7dafef9b9f" +dependencies = [ + "cfg-if", + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8276d9a4a3a558d7b7ad5303ad50b53d58264641b82914b7ada36bd762e7a716" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tracing-core" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03cfcb51380632a72d3111cb8d3447a8d908e577d31beeac006f836383d29a23" +dependencies = [ + "lazy_static", + "valuable", +] + +[[package]] +name = "tracing-log" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6923477a48e41c1951f1999ef8bb5a3023eb723ceadafe78ffb65dc366761e3" +dependencies = [ + "lazy_static", + "log", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e0ab7bdc962035a87fba73f3acca9b8a8d0034c2e6f60b84aeaaddddc155dce" +dependencies = [ + "ansi_term", + "sharded-slab", + "smallvec", + "thread_local", + "tracing-core", + "tracing-log", +] + +[[package]] +name = "unicode-xid" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" + +[[package]] +name = "valuable" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" + +[[package]] +name = "vive-hid" +version = "0.1.0" +dependencies = [ + "flate2", + "hidapi", + "once_cell", + "serde", + "serde_json", + "thiserror", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..6156901 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,24 @@ +[package] +name = "driver_lighthouse" +version = "0.1.0" +edition = "2021" + +[dependencies] +cppvtbl = "0.2.0" +libloading = "0.7.3" +once_cell = "1.9.0" +process_path = "0.1.3" +thiserror = "1.0.30" +tracing = "0.1.31" +tracing-subscriber = "0.3.9" + +vive-hid = { path = "./crates/vive-hid" } +lens-client = { path = "./crates/lens-client" } +lens-protocol = { path = "./crates/lens-protocol" } +real_c_string = "1.0.0" + +[lib] +crate-type = ["cdylib"] + +[workspace] +members = ["crates/*", "bin/*"] diff --git a/Makefile b/Makefile deleted file mode 100644 index 7d68ae3..0000000 --- a/Makefile +++ /dev/null @@ -1,32 +0,0 @@ -.PHONY: clean build install enable disable - -LIGHTHOUSE_BIN:=$(HOME)/.local/share/Steam/steamapps/common/SteamVR/drivers/lighthouse/bin/linux64 -LENS_SERVER_DIST:=$(PWD)/lensServer/dist -WINE:=`which wine` - -clean: - rm -f driver_lighthouse_proxy.so -format: - clang-format -i driver.cpp -style=llvm - clang-format -i driver.h -style=llvm - - -build: driver_lighthouse_proxy.so - -install: build - cp $(PWD)/driver_lighthouse_proxy.so $(LIGHTHOUSE_BIN)/ - test ! -f $(LIGHTHOUSE_BIN)/driver_lighthouse_real.so && cp $(LIGHTHOUSE_BIN)/driver_lighthouse.so $(LIGHTHOUSE_BIN)/driver_lighthouse_real.so || true - -enable: install - rm $(LIGHTHOUSE_BIN)/driver_lighthouse.so - ln -s $(LIGHTHOUSE_BIN)/driver_lighthouse_proxy.so $(LIGHTHOUSE_BIN)/driver_lighthouse.so - -disable: - rm $(LIGHTHOUSE_BIN)/driver_lighthouse.so - ln -s $(LIGHTHOUSE_BIN)/driver_lighthouse_real.so $(LIGHTHOUSE_BIN)/driver_lighthouse.so - -driver_lighthouse_proxy.so: driver.cpp - g++ \ - --pedantic -fpermissive -std=c++2a -Werror \ - -DLIGHTHOUSE_BIN=\"$(LIGHTHOUSE_BIN)\" -DLENS_SERVER_DIST=\"$(LENS_SERVER_DIST)\" -DWINE=\"$(WINE)\" \ - -shared -static-libgcc -static-libstdc++ -ldl -o $@ -fPIC $< diff --git a/bin/lens-server/.envrc b/bin/lens-server/.envrc new file mode 100644 index 0000000..d9c09f7 --- /dev/null +++ b/bin/lens-server/.envrc @@ -0,0 +1 @@ +use flake ../../#mingw diff --git a/lensServer/Cargo.toml b/bin/lens-server/Cargo.toml similarity index 50% rename from lensServer/Cargo.toml rename to bin/lens-server/Cargo.toml index 4c1d17f..3e688d1 100644 --- a/lensServer/Cargo.toml +++ b/bin/lens-server/Cargo.toml @@ -1,12 +1,15 @@ [package] name = "lens-server" version = "0.1.0" -authors = ["Yaroslav Bolyukin "] -edition = "2018" +edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +lens-protocol = { path = "../../crates/lens-protocol" } libloading = "0.7.3" -serde_json = "1.0.76" -byteorder = "1.4.3" +process_path = "0.1.3" +tracing-subscriber = "0.3.9" +tracing = "0.1.31" +anyhow = "1.0" +serde_json = "1.0" diff --git a/bin/lens-server/src/main.rs b/bin/lens-server/src/main.rs new file mode 100644 index 0000000..a9eb888 --- /dev/null +++ b/bin/lens-server/src/main.rs @@ -0,0 +1,169 @@ +use std::{ + ffi::OsStr, + sync::atomic::{AtomicBool, Ordering}, +}; + +use anyhow::{ensure, Context, Result}; +use lens_protocol::{DistortOutput, Eye, LeftRightTopBottom, Request, Server}; +use libloading::{Library, Symbol}; +use serde_json::Value; +use tracing::info; + +static CREATED: AtomicBool = AtomicBool::new(false); + +struct LensLibraryMethods { + init: Symbol<'static, unsafe extern "C" fn() -> u32>, + set_resolution: Symbol<'static, unsafe extern "C" fn(width: u32, height: u32) -> u32>, + load_json_str: Symbol<'static, unsafe extern "C" fn(str: *const u8, len: usize) -> u32>, + distort_uv: Symbol< + 'static, + unsafe extern "C" fn( + eye: u32, + color: u32, + u: f32, + v: f32, + c1: &mut f32, + c2: &mut f32, + ) -> u32, + >, + grow_for_undistort: Symbol<'static, unsafe extern "C" fn(eye: u32, out: &mut [f32; 4]) -> u32>, + intrinsic: Symbol<'static, unsafe extern "C" fn(eye: u32, out: &mut [f32; 8]) -> u32>, +} +impl LensLibraryMethods { + fn init(&self) -> Result<()> { + ensure!(unsafe { (self.init)() } == 0); + Ok(()) + } + fn set_resolution(&self, width: u32, height: u32) -> Result<()> { + ensure!(unsafe { (self.set_resolution)(width, height) } == 0); + Ok(()) + } + fn load_json_str(&self, str: &str) -> Result<()> { + ensure!(unsafe { (self.load_json_str)(str.as_ptr(), str.len()) } == 0); + Ok(()) + } + + fn grow_for_undistort(&self, eye: Eye) -> Result<[f32; 4]> { + let mut out = [0.0; 4]; + ensure!(unsafe { (self.grow_for_undistort)(eye as u32, &mut out) } == 0); + Ok(out) + } + fn intrinsic(&self, eye: Eye) -> Result<[f32; 8]> { + let mut out = [0.0; 8]; + ensure!(unsafe { (self.intrinsic)(eye as u32, &mut out) } == 0); + Ok(out) + } + fn distort_uv(&self, eye: Eye, color: u32, uv: [f32; 2]) -> Result<[f32; 2]> { + let mut a = 0.0; + let mut b = 0.0; + ensure!(unsafe { (self.distort_uv)(eye as u32, color, uv[0], uv[1], &mut a, &mut b) } == 0); + Ok([a, b]) + } +} +struct LensLibrary { + m: LensLibraryMethods, + _marker: *const (), +} +impl LensLibrary { + unsafe fn new(library: impl AsRef, resolution: (u32, u32)) -> Result { + ensure!( + !CREATED.swap(true, Ordering::Relaxed), + "only single LensLibrary may exist per process" + ); + let lib = Box::leak(Box::new( + #[cfg(windows)] + Library::from( + libloading::os::windows::Library::load_with_flags( + library, + libloading::os::windows::LOAD_WITH_ALTERED_SEARCH_PATH, + ) + .context("failed to load library")?, + ), + #[cfg(not(windows))] + Library::new(library).context("failed to load library")?, + )); + let m = LensLibraryMethods { + init: lib.get(b"init")?, + set_resolution: lib.get(b"setResolution")?, + load_json_str: lib.get(b"loadJsonStr")?, + distort_uv: lib.get(b"distortUV")?, + grow_for_undistort: lib.get(b"getGrowForUndistort")?, + intrinsic: lib.get(b"getIntrinsic")?, + }; + m.init()?; + m.set_resolution(resolution.0, resolution.1)?; + Ok(Self { + m, + _marker: std::ptr::null(), + }) + } + fn set_config(&self, config: Value) -> Result<()> { + let config_str = serde_json::to_string(&config)?; + self.m.load_json_str(&config_str)?; + Ok(()) + } + fn distort(&self, eye: Eye, uv: [f32; 2]) -> Result { + Ok(DistortOutput { + red: self.m.distort_uv(eye, 2, uv)?, + green: self.m.distort_uv(eye, 1, uv)?, + blue: self.m.distort_uv(eye, 0, uv)?, + }) + } + fn projection_raw(&self, eye: Eye) -> Result { + let mut g = self.m.grow_for_undistort(eye)?; + for v in g.iter_mut() { + *v += 1.0; + } + let i = self.m.intrinsic(eye)?; + Ok(LeftRightTopBottom { + left: (-1.0 - i[2]) * g[0] / i[0], + right: (1.0 - i[2]) * g[1] / i[0], + top: (1.0 - i[4 + 1]) * g[2] / i[4], + bottom: (-1.0 - i[4 + 1]) * g[3] / i[4], + }) + } +} + +#[tracing::instrument(err)] +fn main() -> Result<()> { + tracing_subscriber::fmt() + .without_time() + // stdout is occupied for protocol, and stderr is available + .with_writer(std::io::stderr) + .init(); + info!("hello from lens server"); + let mut path = process_path::get_executable_path().context("failed to find executable path")?; + path.pop(); + + let mut dll_path = path.clone(); + dll_path.push("LibLensDistortion.dll"); + info!("dll path: {dll_path:?}"); + + let mut server = Server::listen(); + + let library = unsafe { LensLibrary::new(dll_path, (2448, 2448))? }; + + loop { + let req = server.recv().context("failed to read request")?; + match req { + Request::Init(config) => { + info!("set config"); + library.set_config(config)?; + } + Request::Distort(eye, uv) => { + server.send(&library.distort(eye, uv)?)?; + } + Request::ProjectionRaw(eye) => { + server.send(&library.projection_raw(eye)?)?; + } + Request::Ping(v) => { + server.send(&v)?; + } + Request::Exit => { + info!("received exit signal"); + break; + } + } + } + Ok(()) +} diff --git a/crates/lens-client/Cargo.toml b/crates/lens-client/Cargo.toml new file mode 100644 index 0000000..856090d --- /dev/null +++ b/crates/lens-client/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "lens-client" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +lens-protocol = { path = "../lens-protocol" } +process_path = "0.1.3" +thiserror = "1.0.30" +tracing = "0.1.31" +serde_json = "1.0.79" + +[dev-dependencies] +tracing-subscriber = "0.3.9" diff --git a/crates/lens-client/src/lib.rs b/crates/lens-client/src/lib.rs new file mode 100644 index 0000000..333448e --- /dev/null +++ b/crates/lens-client/src/lib.rs @@ -0,0 +1,88 @@ +use std::{ + env, + ffi::OsStr, + io, + path::{Path, PathBuf}, + process::{Command, Stdio}, + result, +}; + +use lens_protocol::Client; +use serde_json::Value; +use tracing::info; + +#[derive(thiserror::Error, Debug)] +pub enum Error { + #[error("io error: {0}")] + Io(#[from] io::Error), + #[error("lens protocol error: {0}")] + Protocol(#[from] lens_protocol::Error), + #[error("cant find server, specify LENS_SERVER_EXE")] + CantFindServer, + #[error("expected server exe at {0}, but it is not found")] + ServerExeNotFound(PathBuf), + #[error("can't find wine in PATH")] + WineNotFound, +} + +type Result = result::Result; + +// TODO: Pass config on startup +pub fn start_lens_server(config: Value) -> Result { + let server = find_server().ok_or(Error::CantFindServer)?; + info!("using lens server at {server:?}"); + + if let Some(wine) = env::var_os("WINE") { + let res = start_lens_server_with(wine, server, config)?; + info!("server is working"); + Ok(res) + } else { + for wine in ["wine64", "wine"] { + info!("trying {wine} as wine"); + let res = start_lens_server_with(wine, &server, config.clone()); + match res { + Err(Error::Io(io)) if io.kind() == io::ErrorKind::NotFound => { + // Only possible if wine not exists + continue; + } + _ => {} + } + let res = res?; + return Ok(res); + } + Err(Error::WineNotFound) + } +} + +pub fn start_lens_server_with( + wine: impl AsRef, + server_path: impl AsRef, + config: Value, +) -> Result { + let server_path = server_path.as_ref(); + if !server_path.exists() { + return Err(Error::ServerExeNotFound(server_path.to_owned())); + } + + let child = Command::new(wine) + // fixme slows down responses + .env("WINEDEBUG", "fixme-all") + .arg(server_path) + .stdin(Stdio::piped()) + .stdout(Stdio::piped()) + .stderr(Stdio::inherit()) + .spawn()?; + + Ok(Client::open(child, config)?) +} + +pub fn find_server() -> Option { + if let Some(path) = env::var_os("LENS_SERVER_EXE") { + return Some(PathBuf::from(path)); + } + let mut path = process_path::get_dylib_path()?; + path.pop(); + path.push("lens-server"); + path.push("lens-server.exe"); + Some(path) +} diff --git a/vivectl/Cargo.toml b/crates/lens-protocol/Cargo.toml similarity index 51% rename from vivectl/Cargo.toml rename to crates/lens-protocol/Cargo.toml index 41125cb..da1f560 100644 --- a/vivectl/Cargo.toml +++ b/crates/lens-protocol/Cargo.toml @@ -1,13 +1,12 @@ [package] -name = "vivectl" +name = "lens-protocol" version = "0.1.0" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -anyhow = "1.0.53" -clap = { version = "3.0.13", features = ["derive"] } -hex-literal = "0.3.4" -hidapi = "1.3.2" -thiserror = "1.0.30" +serde = { version = "1.0", features = ["derive"] } +serde_json = "1.0" +bincode = "1.3" +thiserror = "1.0" diff --git a/crates/lens-protocol/src/lib.rs b/crates/lens-protocol/src/lib.rs new file mode 100644 index 0000000..a83ee2b --- /dev/null +++ b/crates/lens-protocol/src/lib.rs @@ -0,0 +1,190 @@ +#![feature(stdio_locked)] + +use std::{ + io::{self, StdinLock, StdoutLock, Write}, + process::{Child, ChildStdin, ChildStdout}, + result, +}; + +use serde::{de::DeserializeOwned, Deserialize, Serialize}; +use serde_json::Value; + +#[derive(thiserror::Error, Debug)] +pub enum Error { + #[error("bincode error: {0}")] + Bincode(#[from] bincode::Error), + #[error("io error: {0}")] + Io(#[from] io::Error), + #[error("pipe failed")] + MissingPipe, + #[error("failed to ping server")] + PingFailed, +} +type Result = result::Result; + +#[derive(Debug, Serialize, Deserialize)] +pub struct DistortOutput { + pub red: [f32; 2], + pub green: [f32; 2], + pub blue: [f32; 2], +} + +#[derive(Debug, Serialize, Deserialize)] +pub struct LeftRightTopBottom { + pub left: f32, + pub right: f32, + pub top: f32, + pub bottom: f32, +} + +#[derive(Debug, Clone, Copy, Serialize, Deserialize)] +#[repr(u32)] +pub enum Eye { + Left = 0, + Right = 1, +} + +mod json { + use serde::{Deserialize, Deserializer, Serialize, Serializer}; + use serde_json::Value; + + pub fn serialize(value: &Value, serializer: S) -> Result + where + S: Serializer, + { + let str = serde_json::to_string(&value).unwrap(); + str.serialize(serializer) + } + pub fn deserialize<'de, D>(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let str = String::deserialize(deserializer).unwrap(); + Ok(serde_json::from_str(&str).unwrap()) + } +} + +#[derive(Debug, Serialize, Deserialize)] +pub enum Request { + Init(#[serde(with = "json")] Value), + Ping(u32), + Distort(Eye, [f32; 2]), + ProjectionRaw(Eye), + Exit, +} + +pub struct Client { + stdin: ChildStdin, + stdout: ChildStdout, + child: Child, +} +impl Client { + pub fn open(mut child: Child, config: Value) -> Result { + let mut res = Self { + stdin: child.stdin.take().ok_or(Error::MissingPipe)?, + stdout: child.stdout.take().ok_or(Error::MissingPipe)?, + child, + }; + + if res.ping(0x12345678)? != 0x12345678 { + return Err(Error::MissingPipe); + } + res.set_config(config)?; + + Ok(res) + } + pub fn request(&mut self, request: &Request) -> Result { + self.send(request)?; + Ok(bincode::deserialize_from(&mut self.stdout)?) + } + pub fn send(&mut self, request: &Request) -> Result<()> { + bincode::serialize_into(&self.stdin, request)?; + self.stdin.flush()?; + Ok(()) + } + pub fn set_config(&mut self, config: Value) -> Result<()> { + self.send(&Request::Init(config))?; + Ok(()) + } + pub fn ping(&mut self, v: u32) -> Result { + Ok(self.request(&Request::Ping(v))?) + } + pub fn project(&mut self, eye: Eye) -> Result { + Ok(self.request(&Request::ProjectionRaw(eye))?) + } + pub fn matrix_needs_inversion(&mut self) -> Result { + let v = self.project(Eye::Left)?; + Ok(v.top > v.bottom) + } + pub fn distort(&mut self, eye: Eye, uv: [f32; 2]) -> Result { + self.request(&Request::Distort(eye, uv)) + } + pub fn exit(&mut self) { + // Flush may fail in case if exit succeeded + let _ = self.send(&Request::Exit); + self.child.wait().unwrap(); + } +} +impl Drop for Client { + fn drop(&mut self) { + self.exit() + } +} + +#[cfg(target_os = "windows")] +#[link(name = "msvcrt")] +extern "C" { + fn _setmode(fd: i32, mode: i32) -> i32; +} + +pub struct Server { + stdin: StdinLock<'static>, + stdout: StdoutLock<'static>, + #[cfg(target_os = "windows")] + modes: (i32, i32), +} +impl Server { + pub fn listen() -> Self { + #[cfg(target_os = "windows")] + let modes = { + let stdout = unsafe { _setmode(0, 0x8000) }; + let stdin = unsafe { _setmode(1, 0x8000) }; + assert!( + stdout != -1 && stdin != -1, + "binary mode should be accepted, and fds are correct" + ); + (stdout, stdin) + }; + + let stdin = io::stdin_locked(); + let stdout = io::stdout_locked(); + + Self { + stdin, + stdout, + #[cfg(target_os = "windows")] + modes, + } + } + pub fn recv(&mut self) -> Result { + Ok(bincode::deserialize_from(&mut self.stdin)?) + } + pub fn send(&mut self, v: &impl Serialize) -> Result<()> { + bincode::serialize_into(&mut self.stdout, v)?; + self.stdout.flush()?; + Ok(()) + } +} +impl Drop for Server { + fn drop(&mut self) { + #[cfg(target_os = "windows")] + { + let stdout = unsafe { _setmode(0, self.modes.0) }; + let stdin = unsafe { _setmode(1, self.modes.1) }; + assert!( + stdout != -1 && stdin != -1, + "previous mode and fds should be correct" + ); + } + } +} diff --git a/crates/vive-hid/Cargo.toml b/crates/vive-hid/Cargo.toml new file mode 100644 index 0000000..2cb8550 --- /dev/null +++ b/crates/vive-hid/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "vive-hid" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +hidapi = { version = "1.3.3", default-features = false, features = [ + "linux-static-hidraw", +] } +once_cell = "1.9.0" +thiserror = "1.0.30" +flate2 = "1.0.22" +serde = { version = "1.0.136", features = ["derive"] } +serde_json = "1.0.79" diff --git a/crates/vive-hid/src/lib.rs b/crates/vive-hid/src/lib.rs new file mode 100644 index 0000000..cf83bce --- /dev/null +++ b/crates/vive-hid/src/lib.rs @@ -0,0 +1,286 @@ +use std::{io::Read, result}; + +use flate2::read::ZlibDecoder; +use hidapi::{HidApi, HidDevice, HidError}; +use once_cell::sync::OnceCell; +use serde::Deserialize; +use serde_json::Value; + +#[derive(thiserror::Error, Debug)] +pub enum Error { + #[error("hid error: {0}")] + Hid(#[from] HidError), + #[error("device not found")] + DeviceNotFound, + #[error("device is not a vive device")] + NotAVive, + #[error("config size mismatch")] + ConfigSizeMismatch, + #[error("failed to read config")] + ConfigReadFailed, + #[error("protocol error: {0}")] + ProtocolError(&'static str), +} + +type Result = result::Result; + +static HIDAPI: OnceCell = OnceCell::new(); +pub fn get_hidapi() -> Result<&'static HidApi> { + HIDAPI.get_or_try_init(|| HidApi::new()).map_err(From::from) +} + +const STEAM_VID: u16 = 0x28de; +const STEAM_PID: u16 = 0x2300; + +#[derive(Deserialize, Debug)] +pub struct ConfigDevice { + pub eye_target_height_in_pixels: u32, + pub eye_target_width_in_pixels: u32, +} +#[derive(Deserialize, Debug)] +pub struct SteamConfig { + pub device: ConfigDevice, + pub direct_mode_edid_pid: u32, + pub direct_mode_edid_vid: u32, + pub seconds_from_photons_to_vblank: f64, + pub seconds_from_vsync_to_photons: f64, + /// SN of ViveDevice + pub mb_serial_number: String, +} + +pub struct SteamDevice(HidDevice); +impl SteamDevice { + pub fn open_first() -> Result { + let api = get_hidapi()?; + let device = api.open(STEAM_VID, STEAM_PID)?; + Ok(Self(device)) + } + pub fn open(sn: &str) -> Result { + let api = get_hidapi()?; + let device = api + .device_list() + .find(|dev| dev.serial_number() == Some(sn)) + .ok_or(Error::DeviceNotFound)?; + if device.vendor_id() != STEAM_VID || device.product_id() != STEAM_PID { + return Err(Error::NotAVive); + } + let open = api.open_serial(device.vendor_id(), device.product_id(), sn)?; + Ok(Self(open)) + } + pub fn read_config(&self) -> Result { + let mut report = [0u8; 64]; + report[0] = 16; + let mut read_retries = 0; + while self.0.get_feature_report(&mut report).is_err() { + if read_retries > 5 { + return Err(Error::ConfigReadFailed); + } + read_retries += 1; + } + read_retries = 0; + let mut out = Vec::new(); + loop { + report[0] = 17; + if self.0.get_feature_report(&mut report).is_err() { + if read_retries > 5 { + return Err(Error::ConfigReadFailed); + } + read_retries += 1; + continue; + } + read_retries = 0; + if report[1] == 0 { + break; + } + out.extend_from_slice(&report[2..2 + report[1] as usize]) + } + let mut dec = ZlibDecoder::new(out.as_slice()); + let mut out = String::new(); + dec.read_to_string(&mut out) + .map_err(|_| Error::ConfigReadFailed)?; + + serde_json::from_str(&out).map_err(|_| Error::ConfigReadFailed) + } +} + +const VIVE_VID: u16 = 0x0bb4; +const VIVE_PID: u16 = 0x0342; + +#[derive(Deserialize, Debug)] +pub struct ViveConfig { + pub device: ConfigDevice, + pub direct_mode_edid_pid: u32, + pub direct_mode_edid_vid: u32, + pub seconds_from_photons_to_vblank: f64, + pub seconds_from_vsync_to_photons: f64, + /// Lets threat it as something opaque, anyway we directly feed this to lens-client + pub inhouse_lens_correction: Value, +} + +#[derive(Clone, Copy)] +#[repr(u8)] +pub enum Resolution { + R2448x1224f90 = 0, + R2448x1224f120 = 1, + R3264x1632f90 = 2, + R3680x1836f90 = 3, + R4896x2448f90 = 4, + R4896x2448f120 = 5, +} +impl Resolution { + pub fn resolution(&self) -> (u32, u32) { + match self { + Self::R2448x1224f90 => (2448, 1224), + Self::R2448x1224f120 => (2448, 1224), + Self::R3264x1632f90 => (3264, 1632), + Self::R3680x1836f90 => (3680, 1836), + Self::R4896x2448f90 => (4896, 2448), + Self::R4896x2448f120 => (4896, 2448), + } + } + pub fn frame_rate(&self) -> f32 { + match self { + Self::R2448x1224f90 => 90.03, + Self::R2448x1224f120 => 120.05, + Self::R3264x1632f90 => 90.00, + Self::R3680x1836f90 => 90.02, + Self::R4896x2448f90 => 90.02, + Self::R4896x2448f120 => 120.02, + } + } +} +impl TryFrom for Resolution { + type Error = (); + + fn try_from(value: u8) -> Result { + Ok(match value { + 0 => Self::R2448x1224f90, + 1 => Self::R2448x1224f120, + 2 => Self::R3264x1632f90, + 3 => Self::R3680x1836f90, + 4 => Self::R4896x2448f90, + 5 => Self::R4896x2448f120, + _ => return Err(()), + }) + } +} + +pub struct ViveDevice(HidDevice); +impl ViveDevice { + pub fn open_first() -> Result { + let api = get_hidapi()?; + let device = api.open(VIVE_VID, VIVE_PID)?; + Ok(Self(device)) + } + pub fn open(sn: &str) -> Result { + let api = get_hidapi()?; + let device = api + .device_list() + .find(|dev| dev.serial_number() == Some(sn)) + .ok_or(Error::DeviceNotFound)?; + if device.vendor_id() != STEAM_VID || device.product_id() != STEAM_PID { + return Err(Error::NotAVive); + } + let open = api.open_serial(device.vendor_id(), device.product_id(), sn)?; + Ok(Self(open)) + } + fn write(&self, id: u8, data: &[u8]) -> Result<()> { + let mut report = [0u8; 64]; + report[0] = id; + report[1..1 + data.len()].copy_from_slice(data); + self.0.write(&report)?; + Ok(()) + } + fn write_feature(&self, id: u8, sub_id: u16, data: &[u8]) -> Result<()> { + let mut report = [0u8; 64]; + report[0] = id; + report[1] = (sub_id & 0xff) as u8; + report[2] = (sub_id >> 8) as u8; + report[3] = data.len() as u8; + report[4..][..data.len()].copy_from_slice(data); + self.0.send_feature_report(&report)?; + Ok(()) + } + fn read(&self, id: u8, strip_prefix: &[u8], out: &mut [u8]) -> Result { + let mut data = [0u8; 64]; + self.0.read(&mut data)?; + if data[0] != id { + return Err(Error::ProtocolError("wrong report id")); + } + if &data[1..1 + strip_prefix.len()] != strip_prefix { + return Err(Error::ProtocolError("wrong prefix")); + } + let size = data[1 + strip_prefix.len()] as usize; + if size > 62 { + return Err(Error::ProtocolError("wrong size")); + } + out[..size].copy_from_slice(&data[strip_prefix.len() + 2..strip_prefix.len() + 2 + size]); + Ok(size) + } + pub fn read_devsn(&self) -> Result { + self.write(0x02, b"mfg-r-devsn")?; + let mut out = [0u8; 62]; + let size = self.read(0x02, &[], &mut out)?; + Ok(std::str::from_utf8(&out[..size]) + .map_err(|_| Error::ProtocolError("devsn is not a string"))? + .to_string()) + } + pub fn read_ipd(&self) -> Result { + self.write(0x02, b"mfg-r-ipdadc")?; + let mut out = [0u8; 62]; + let size = self.read(0x02, &[], &mut out)?; + Ok(std::str::from_utf8(&out[..size]) + .map_err(|_| Error::ProtocolError("devsn is not a string"))? + .to_string()) + } + pub fn read_config(&self) -> Result { + let mut buf = [0u8; 62]; + // Request size + let total_len = { + self.write(0x01, &[0xea, 0xb1])?; + let size = self.read(0x01, &[0xea, 0xb1], &mut buf)?; + if size != 4 { + return Err(Error::ProtocolError("config length has 4 bytes")); + } + let mut total_len = [0u8; 4]; + total_len.copy_from_slice(&buf[0..4]); + u32::from_le_bytes(total_len) as usize + }; + let mut read = 0; + let mut out = Vec::::with_capacity(total_len); + while read < total_len { + let mut req = [0; 63]; + req[0] = 0xeb; + req[1] = 0xb1; + req[2] = 0x04; + req[3..7].copy_from_slice(&u32::to_le_bytes(read as u32)); + + self.write(0x01, &req)?; + let size = self.read(0x01, &[0xeb, 0xb1], &mut buf)?; + read += size; + out.extend_from_slice(&buf[0..size]); + } + if read != total_len { + return Err(Error::ProtocolError("config size mismatch")); + } + + // First 128 bytes - something i can't decipher + sha256 hash (why?) + let string = std::str::from_utf8(&out[128..]) + .map_err(|_| Error::ProtocolError("config is not utf-8"))?; + + serde_json::from_str(&string).map_err(|_| Error::ConfigReadFailed) + } + pub fn set_resolution(&self, resolution: Resolution) -> Result<(), Error> { + self.write_feature(0x04, 0x2970, b"wireless,0")?; + self.write_feature(0x04, 0x2970, format!("dtd,{}", resolution as u8).as_bytes())?; + // TODO: wait for reconnection + Ok(()) + } +} + +#[test] +fn test() -> Result<()> { + let dev = ViveDevice::open_first()?; + dbg!(dev.read_ipd()?); + Ok(()) +} diff --git a/dist/.gitignore b/dist/.gitignore new file mode 100644 index 0000000..a9b1676 --- /dev/null +++ b/dist/.gitignore @@ -0,0 +1 @@ +driver_lighthouse.so diff --git a/dist/install.sh b/dist/install.sh new file mode 100755 index 0000000..42f9754 --- /dev/null +++ b/dist/install.sh @@ -0,0 +1,30 @@ +#!/bin/sh + +set -euo pipefail + +SCRIPT=$(readlink -f "$0") +SCRIPTPATH=$(dirname $SCRIPT) + +STEAMVR="${STEAMVR:-$HOME/.local/share/Steam/steamapps/common/SteamVR}" +if ! test -d $STEAMVR; then + echo "SteamVR not found at $STEAMVR (Set \$STEAMVR manually?)" + exit 1 +fi +echo "SteamVR at $STEAMVR" + +LIGHTHOUSE_DRIVER=$STEAMVR/drivers/lighthouse/bin/linux64 + +if ! test -f $LIGHTHOUSE_DRIVER/driver_lighthouse.so; then + echo "Lighthouse driver not found, broken installation?" +fi +if ! test -f $LIGHTHOUSE_DRIVER/driver_lighthouse_real.so; then + echo "Creating backup (also used by proxy driver)" + cp $LIGHTHOUSE_DRIVER/driver_lighthouse.so $LIGHTHOUSE_DRIVER/driver_lighthouse_real.so +else + echo "Seems like proxy driver is already installed? Proceeding with update then" +fi + +rsync -a $SCRIPTPATH/driver_lighthouse.so $LIGHTHOUSE_DRIVER/driver_lighthouse.so +rsync -ar $SCRIPTPATH/lens-server/ $LIGHTHOUSE_DRIVER/lens-server + +echo "Installation finished, try to start SteamVR" diff --git a/dist/lens-server/.gitignore b/dist/lens-server/.gitignore new file mode 100644 index 0000000..0956f85 --- /dev/null +++ b/dist/lens-server/.gitignore @@ -0,0 +1 @@ +lens-server.exe diff --git a/lensServer/asset/LibLensDistortion.dll b/dist/lens-server/LibLensDistortion.dll similarity index 100% rename from lensServer/asset/LibLensDistortion.dll rename to dist/lens-server/LibLensDistortion.dll diff --git a/lensServer/asset/opencv_world346.dll b/dist/lens-server/opencv_world346.dll similarity index 100% rename from lensServer/asset/opencv_world346.dll rename to dist/lens-server/opencv_world346.dll diff --git a/driver.cpp b/driver.cpp deleted file mode 100644 index 114ada5..0000000 --- a/driver.cpp +++ /dev/null @@ -1,328 +0,0 @@ -#include "driver.h" - -typedef void *(*HmdDriverFactory_ty)(const char *pInterfaceName, - int *pReturnCode); -HmdDriverFactory_ty HmdDriverFactoryReal; - -static int lens_server_in; -static int lens_server_out; - -// Replace with false if textures are located on wrong sides of meshes -#define INVERT_MATRIX (true) -#define WIDTH (2448) -#define HEIGHT (1224) - -int read_exact(int fd, void *buf, size_t nbytes) { - while (nbytes > 0) { - int res = read(fd, buf, nbytes); - if (res == -1) - return -1; - else if (res == 0) - return -1; - nbytes -= res; - buf = (void *)((size_t)buf + res); - } - return 0; -} - -static pthread_mutex_t cs_mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP; - -class CVRDisplayComponent : public vr::IVRDisplayComponent { -public: - CVRDisplayComponent(vr::IVRDisplayComponent *_real) : real(_real) {} - vr::IVRDisplayComponent *real; - virtual void GetWindowBounds(int32_t *pnX, int32_t *pnY, uint32_t *pnWidth, - uint32_t *pnHeight) { - DEBUG("GetWindowBounds()\n"); - real->GetWindowBounds(pnX, pnY, pnWidth, pnHeight); - DEBUG("original driver returned %d %d %dx%d\n", *pnX, *pnY, *pnWidth, - *pnHeight); - *pnX = 0; - *pnY = 0; - *pnWidth = WIDTH; - *pnHeight = HEIGHT; - DEBUG("proxy driver returned %d %d %dx%d\n", *pnX, *pnY, *pnWidth, - *pnHeight); - } - virtual bool IsDisplayOnDesktop() { return real->IsDisplayOnDesktop(); } - virtual bool IsDisplayRealDisplay() { return real->IsDisplayRealDisplay(); } - virtual void GetRecommendedRenderTargetSize(uint32_t *pnWidth, - uint32_t *pnHeight) { - real->GetRecommendedRenderTargetSize(pnWidth, pnHeight); - } - virtual void GetEyeOutputViewport(vr::EVREye eEye, uint32_t *pnX, - uint32_t *pnY, uint32_t *pnWidth, - uint32_t *pnHeight) { - DEBUG("GetEyeOutputViewport(%d)\n", eEye); - real->GetEyeOutputViewport(eEye, pnX, pnY, pnWidth, pnHeight); - DEBUG("original driver returned %d %d %dx%d\n", *pnX, *pnY, *pnWidth, - *pnHeight); - *pnWidth = WIDTH / 2; - *pnHeight = HEIGHT; - *pnY = 0; - *pnX = eEye == vr::Eye_Left ? 0 : *pnWidth; - } - virtual void GetProjectionRaw(vr::EVREye eEye, float *pfLeft, float *pfRight, - float *pfTop, float *pfBottom) { - pthread_mutex_lock(&cs_mutex); - ServerInputProjectionRaw input = {1, eEye}; - ASSERT_FATAL( - write(lens_server_in, &input, sizeof(ServerInputProjectionRaw)) != -1, - "write"); - ServerOutputProjectionRaw output; - ASSERT_FATAL(read_exact(lens_server_out, &output, - sizeof(ServerOutputProjectionRaw)) != -1, - "read"); - pthread_mutex_unlock(&cs_mutex); - *pfLeft = output.left; - *pfRight = output.right; - if (INVERT_MATRIX) { - *pfTop = output.bottom; - *pfBottom = output.top; - } else { - *pfTop = output.top; - *pfBottom = output.bottom; - } - DEBUG("LRTB: %f %f %f %f\n", *pfLeft, *pfRight, *pfTop, *pfBottom); - } - virtual vr::DistortionCoordinates_t ComputeDistortion(vr::EVREye eEye, - float fU, float fV) { - pthread_mutex_lock(&cs_mutex); - ServerInputDistort input = {0, eEye, fU, INVERT_MATRIX ? 1.0f - fV : fV}; - ASSERT_FATAL(write(lens_server_in, &input, sizeof(ServerInputDistort)) != - -1, - "write"); - ServerOutputDistort output; - ASSERT_FATAL( - read_exact(lens_server_out, &output, sizeof(ServerOutputDistort)) != -1, - "read"); - pthread_mutex_unlock(&cs_mutex); - return {{output.red[0], output.red[1]}, - {output.green[0], output.green[1]}, - {output.blue[0], output.blue[1]}}; - } -}; - -class CVRHmdDriver final : public vr::ITrackedDeviceServerDriver { -public: - CVRHmdDriver(vr::ITrackedDeviceServerDriver *_real) : real(_real) {} - vr::ITrackedDeviceServerDriver *real; - virtual vr::EVRInitError Activate(uint32_t unObjectId) { - return real->Activate(unObjectId); - } - virtual void Deactivate() { real->Deactivate(); } - virtual void EnterStandby() { real->EnterStandby(); } - virtual void *GetComponent(const char *pchComponentNameAndVersion) { - DEBUG("GetComponent(%s)\n", pchComponentNameAndVersion); - void *result = real->GetComponent(pchComponentNameAndVersion); - if (strcmp(pchComponentNameAndVersion, vr::IVRDisplayComponent_Version) == - 0) { - result = (vr::IVRDisplayComponent *)new CVRDisplayComponent( - (vr::IVRDisplayComponent *)result); - } - return result; - } - virtual void DebugRequest(const char *pchRequest, char *pchResponseBuffer, - uint32_t unResponseBufferSize) { - real->DebugRequest(pchRequest, pchResponseBuffer, unResponseBufferSize); - } - virtual vr::DriverPose_t GetPose() { return real->GetPose(); } -}; - -class CVRServerDriverHost : public vr::IVRServerDriverHost { -public: - CVRServerDriverHost(vr::IVRServerDriverHost *_real) : real(_real) {} - vr::IVRServerDriverHost *real; - - virtual bool TrackedDeviceAdded(const char *pchDeviceSerialNumber, - vr::ETrackedDeviceClass eDeviceClass, - vr::ITrackedDeviceServerDriver *pDriver) { - DEBUG("TrackedDeviceAdded(%s, %d)\n", pchDeviceSerialNumber, eDeviceClass); - if (eDeviceClass == vr::TrackedDeviceClass_HMD) { - pDriver = new CVRHmdDriver(pDriver); - } - return real->TrackedDeviceAdded(pchDeviceSerialNumber, eDeviceClass, - pDriver); - } - virtual void TrackedDevicePoseUpdated(uint32_t unWhichDevice, - const vr::DriverPose_t &newPose, - uint32_t unPoseStructSize) { - real->TrackedDevicePoseUpdated(unWhichDevice, newPose, unPoseStructSize); - } - virtual void VsyncEvent(double vsyncTimeOffsetSeconds) { - real->VsyncEvent(vsyncTimeOffsetSeconds); - } - virtual void VendorSpecificEvent(uint32_t unWhichDevice, - vr::EVREventType eventType, - const vr::VREvent_Data_t &eventData, - double eventTimeOffset) { - real->VendorSpecificEvent(unWhichDevice, eventType, eventData, - eventTimeOffset); - } - virtual bool IsExiting() { return real->IsExiting(); } - virtual bool PollNextEvent(vr::VREvent_t *pEvent, uint32_t uncbVREvent) { - return real->PollNextEvent(pEvent, uncbVREvent); - } - virtual void - GetRawTrackedDevicePoses(float fPredictedSecondsFromNow, - vr::TrackedDevicePose_t *pTrackedDevicePoseArray, - uint32_t unTrackedDevicePoseArrayCount) { - real->GetRawTrackedDevicePoses(fPredictedSecondsFromNow, - pTrackedDevicePoseArray, - unTrackedDevicePoseArrayCount); - } - virtual void RequestRestart(const char *pchLocalizedReason, - const char *pchExecutableToStart, - const char *pchArguments, - const char *pchWorkingDirectory) { - real->RequestRestart(pchLocalizedReason, pchExecutableToStart, pchArguments, - pchWorkingDirectory); - } - virtual uint32_t GetFrameTimings(vr::Compositor_FrameTiming *pTiming, - uint32_t nFrames) { - return real->GetFrameTimings(pTiming, nFrames); - } - virtual void SetDisplayEyeToHead(uint32_t unWhichDevice, - const vr::HmdMatrix34_t &eyeToHeadLeft, - const vr::HmdMatrix34_t &eyeToHeadRight) { - real->SetDisplayEyeToHead(unWhichDevice, eyeToHeadLeft, eyeToHeadRight); - } - virtual void SetDisplayProjectionRaw(uint32_t unWhichDevice, - const vr::HmdRect2_t &eyeLeft, - const vr::HmdRect2_t &eyeRight) { - real->SetDisplayProjectionRaw(unWhichDevice, eyeLeft, eyeRight); - } - virtual void SetRecommendedRenderTargetSize(uint32_t unWhichDevice, - uint32_t nWidth, - uint32_t nHeight) { - real->SetRecommendedRenderTargetSize(unWhichDevice, nWidth, nHeight); - } -}; - -class CVRDriverContext : public vr::IVRDriverContext { -public: - CVRDriverContext(vr::IVRDriverContext *_real) : real(_real) {} - vr::IVRDriverContext *real; - - virtual void *GetGenericInterface(const char *pchInterfaceVersion, - vr::EVRInitError *peError = nullptr) { - DEBUG("GetGenericInterface(%s)\n", pchInterfaceVersion); - void *result = real->GetGenericInterface(pchInterfaceVersion, peError); - - if (strcmp(pchInterfaceVersion, vr::IVRServerDriverHost_Version) == 0) { - result = new CVRServerDriverHost((vr::IVRServerDriverHost *)result); - } - - return result; - } - virtual vr::DriverHandle_t GetDriverHandle() { - DEBUG("GetDriverHandle()\n"); - return real->GetDriverHandle(); - } -}; - -class CServerTrackedDeviceProvider : public vr::IServerTrackedDeviceProvider { -public: - CServerTrackedDeviceProvider(vr::IServerTrackedDeviceProvider *_real) - : real(_real) {} - vr::IServerTrackedDeviceProvider *real; - - virtual vr::EVRInitError Init(vr::IVRDriverContext *pDriverContext) { - DEBUG("Init()\n"); - return real->Init(new CVRDriverContext(pDriverContext)); - } - virtual void Cleanup() { - DEBUG("Cleanup()\n"); - real->Cleanup(); - } - virtual const char *const *GetInterfaceVersions() { - DEBUG("GetInterfaceVersions()\n"); - auto result = real->GetInterfaceVersions(); - auto it = result; - DEBUG("interfaces:\n"); - for (auto iface = *it; iface; iface = *++it) { - DEBUG("- %s\n", iface); - } - DEBUG("done\n"); - return result; - } - virtual void RunFrame() { real->RunFrame(); } - virtual bool ShouldBlockStandbyMode() { - DEBUG("ShouldBlockStandbyMode()\n"); - return real->ShouldBlockStandbyMode(); - } - virtual void EnterStandby() { - DEBUG("EnterStandby()\n"); - real->EnterStandby(); - } - virtual void LeaveStandby() { - DEBUG("LeaveStandby()\n"); - real->LeaveStandby(); - } -}; -static CServerTrackedDeviceProvider *server_device_provider; - -extern "C" __attribute__((visibility("default"))) void * -HmdDriverFactory(const char *pInterfaceName, int *pReturnCode) { - if (HmdDriverFactoryReal == nullptr) { - DEBUG("loading library from %s\n", LIGHTHOUSE_BIN); - void *library = - dlopen(LIGHTHOUSE_BIN "/driver_lighthouse_real.so", RTLD_NOW); - ASSERT_RET(library != nullptr, "library not found"); - HmdDriverFactoryReal = - (HmdDriverFactory_ty)dlsym(library, "HmdDriverFactory"); - ASSERT_RET(HmdDriverFactoryReal != nullptr, "symbol not found"); - DEBUG("initialized real factory"); - } - if (lens_server_out == 0) { - DEBUG("starting lens server from %s", LENS_SERVER_DIST); - int inpipefd[2]; - int outpipefd[2]; - ASSERT_RET(pipe(inpipefd) == 0, "pipe failed"); - ASSERT_RET(pipe(outpipefd) == 0, "pipe failed"); - if (fork() == 0) { - DEBUG("hello from lens process"); - dup2(inpipefd[0], STDIN_FILENO); - dup2(outpipefd[1], STDOUT_FILENO); - prctl(PR_SET_PDEATHSIG, SIGTERM); - - DEBUG("executing [%s %s]", WINE, LENS_SERVER_DIST "/lens-server.exe"); - const char *env[] = {"WINEDEBUG=-all", NULL}; - execle(WINE, "wine", LENS_SERVER_DIST "/lens-server.exe", (char *)nullptr, - env); - exit(1); - } - - DEBUG("testing lens server\n"); - ServerInputDistort input = {0, 0, 0.0, 0.0}; - ASSERT_RET(write(inpipefd[1], &input, sizeof(ServerInputDistort)) != -1, - "write failed"); - - ServerOutputDistort output; - ASSERT_RET(read_exact(outpipefd[0], &output, sizeof(ServerOutputDistort)) != - -1, - "read failed"); - DEBUG("request completed, assuming lens server is fine\n"); - lens_server_in = inpipefd[1]; - lens_server_out = outpipefd[0]; - } - - if (strcmp(pInterfaceName, vr::IServerTrackedDeviceProvider_Version) == 0) { - if (server_device_provider == nullptr) { - DEBUG("server tracked init\n"); - auto real = (vr::IServerTrackedDeviceProvider *)HmdDriverFactoryReal( - pInterfaceName, pReturnCode); - server_device_provider = new CServerTrackedDeviceProvider(real); - } - if (pReturnCode) { - *pReturnCode = vr::VRInitError_None; - } - return server_device_provider; - } - - DEBUG("requested unknown interface = %s\n", pInterfaceName); - if (pReturnCode) { - *pReturnCode = vr::VRInitError_Init_InterfaceNotFound; - } - return nullptr; -} diff --git a/driver.h b/driver.h deleted file mode 100644 index 4fecfc5..0000000 --- a/driver.h +++ /dev/null @@ -1,33 +0,0 @@ -#include "lens_server.h" -#include "openvr_driver.h" -#include -#include -#include -#include -#include - -#define DEBUG(fmt, ...) \ - do { \ - fprintf(stderr, "PROXY %s(%d): " fmt "\n", __func__, __LINE__, \ - ##__VA_ARGS__); \ - fflush(stderr); \ - } while (0) - -#define ASSERT_RET(condition, fmt, ...) \ - do { \ - if (!(condition)) { \ - DEBUG("assert failed (%s): " fmt, #condition, ##__VA_ARGS__); \ - if (pReturnCode) { \ - *pReturnCode = vr::VRInitError_Init_Internal; \ - } \ - return nullptr; \ - } \ - } while (0) - -#define ASSERT_FATAL(condition, fmt, ...) \ - do { \ - if (!(condition)) { \ - DEBUG("fatal assert failed (%s): " fmt, #condition, ##__VA_ARGS__); \ - exit(1); \ - } \ - } while (0) diff --git a/flake.lock b/flake.lock index 23ce6ab..59e4203 100644 --- a/flake.lock +++ b/flake.lock @@ -15,13 +15,28 @@ "type": "github" } }, + "flake-utils_2": { + "locked": { + "lastModified": 1637014545, + "narHash": "sha256-26IZAc5yzlD9FlDT54io1oqG/bBoyka+FJk5guaX4x4=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "bba5dcc8e0b20ab664967ad83d24d64cb64ec4f4", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, "nixpkgs": { "locked": { - "lastModified": 1642978727, - "narHash": "sha256-ihzVhZZzdspqcSbon5EhOFNRRldKDZGd273WHuAtyDM=", + "lastModified": 1643332957, + "narHash": "sha256-1Dj9EwKeAGdnyyHyttwbstvT6R2yNP8DnS6h1hwcoes=", "owner": "nixos", "repo": "nixpkgs", - "rev": "c78dba5f76837695d75b6f7903cb776b904a2653", + "rev": "ab14cf224f7f076ea92dae1519750178eb0dcecd", "type": "github" }, "original": { @@ -30,10 +45,46 @@ "type": "github" } }, + "nixpkgs_2": { + "locked": { + "lastModified": 1637453606, + "narHash": "sha256-Gy6cwUswft9xqsjWxFYEnx/63/qzaFUwatcbV5GF/GQ=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "8afc4e543663ca0a6a4f496262cd05233737e732", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, "root": { "inputs": { "flake-utils": "flake-utils", - "nixpkgs": "nixpkgs" + "nixpkgs": "nixpkgs", + "rust-overlay": "rust-overlay" + } + }, + "rust-overlay": { + "inputs": { + "flake-utils": "flake-utils_2", + "nixpkgs": "nixpkgs_2" + }, + "locked": { + "lastModified": 1642838864, + "narHash": "sha256-pHnhm3HWwtvtOK7NdNHwERih3PgNlacrfeDwachIG8E=", + "owner": "oxalica", + "repo": "rust-overlay", + "rev": "9fb49daf1bbe1d91e6c837706c481f9ebb3d8097", + "type": "github" + }, + "original": { + "owner": "oxalica", + "repo": "rust-overlay", + "type": "github" } } }, diff --git a/flake.nix b/flake.nix index 92a1f9d..45215b8 100644 --- a/flake.nix +++ b/flake.nix @@ -3,18 +3,56 @@ inputs = { nixpkgs.url = "github:nixos/nixpkgs"; flake-utils.url = "github:numtide/flake-utils"; + rust-overlay.url = "github:oxalica/rust-overlay"; }; - outputs = { self, nixpkgs, flake-utils }: + outputs = { self, nixpkgs, flake-utils, rust-overlay }: flake-utils.lib.eachDefaultSystem (system: - let pkgs = import nixpkgs { inherit system; }; in + let + pkgs = import nixpkgs { + inherit system; + overlays = [ rust-overlay.overlay ]; + }; + rust = ((pkgs.buildPackages.rustChannelOf { date = "2022-01-13"; channel = "nightly"; }).default.override { + targets = [ "x86_64-pc-windows-gnu" ]; + extensions = [ "rust-src" ]; + }); + pkgs-mingw = import nixpkgs { + inherit system; + crossSystem = { config = "x86_64-w64-mingw32"; }; + }; + in rec { - devShell = pkgs.mkShell { - nativeBuildInputs = with pkgs;[ - gcc - gnumake - clang-tools - wineWowPackages.full - ]; + devShells = { + default = pkgs.mkShell { + nativeBuildInputs = with pkgs;[ + rust + cargo-edit + hidapi + udev + libusb + pkg-config + wine64 + + # druid build + cmake + pkg-config + fontconfig + + # slint runtime + xorg.libxcb + xorg.libX11 + xorg.libXcursor + xorg.libXrandr + xorg.libXi + + cairo + ]; + }; + mingw = pkgs-mingw.mkShell { + nativeBuildInputs = [ rust ]; + depsBuildBuild = with pkgs; [ wine64 ]; + buildInputs = with pkgs-mingw; [ windows.pthreads ]; + }; }; } ); diff --git a/lensServer/.cargo/config b/lensServer/.cargo/config deleted file mode 100644 index ba54493..0000000 --- a/lensServer/.cargo/config +++ /dev/null @@ -1,2 +0,0 @@ -[build] -target = "x86_64-pc-windows-gnu" diff --git a/lensServer/.envrc b/lensServer/.envrc deleted file mode 100644 index feae7f4..0000000 --- a/lensServer/.envrc +++ /dev/null @@ -1,3 +0,0 @@ -source_url "https://raw.githubusercontent.com/nix-community/nix-direnv/1.2.3/direnvrc" "sha256-/aHqL/6nLpHcZJcB5/7/5+mO338l28uFbq88DMfWJn4=" - -use flake diff --git a/lensServer/.gitignore b/lensServer/.gitignore deleted file mode 100644 index 1de5659..0000000 --- a/lensServer/.gitignore +++ /dev/null @@ -1 +0,0 @@ -target \ No newline at end of file diff --git a/lensServer/Cargo.lock b/lensServer/Cargo.lock deleted file mode 100644 index e165d83..0000000 --- a/lensServer/Cargo.lock +++ /dev/null @@ -1,83 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -[[package]] -name = "byteorder" -version = "1.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "itoa" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35" - -[[package]] -name = "lens-server" -version = "0.1.0" -dependencies = [ - "byteorder", - "libloading", - "serde_json", -] - -[[package]] -name = "libloading" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efbc0f03f9a775e9f6aed295c6a1ba2253c5757a9e03d55c6caa46a681abcddd" -dependencies = [ - "cfg-if", - "winapi", -] - -[[package]] -name = "ryu" -version = "1.0.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f" - -[[package]] -name = "serde" -version = "1.0.134" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96b3c34c1690edf8174f5b289a336ab03f568a4460d8c6df75f2f3a692b3bc6a" - -[[package]] -name = "serde_json" -version = "1.0.77" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "651bca88044a8a5166bd0fd984a7ca558301079cf08365ca6287b2bb608cca3e" -dependencies = [ - "itoa", - "ryu", - "serde", -] - -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/lensServer/asset/config.json b/lensServer/asset/config.json deleted file mode 100644 index c7619b4..0000000 --- a/lensServer/asset/config.json +++ /dev/null @@ -1,448 +0,0 @@ -{ - "left": { - "center": { - "left": { - "x": 97, - "y": 1 - }, - "right": { - "x": 0, - "y": 0 - } - }, - "distortion_coeff": { - "left": { - "blue": { - "k0": 1, - "k1": 1.0646823644638062, - "k10": 491255776, - "k11": -716738112, - "k12": 422669216, - "k2": -86.96723937988281, - "k3": 2981.66552734375, - "k4": -51199.046875, - "k5": 498936.8125, - "k6": -2713603, - "k7": 6043729, - "k8": 17097578, - "k9": -162136560, - "p1": 0.007612932939082384, - "p2": -0.2132890522480011, - "p3": 4.699353218078613, - "p4": -0.0012157321907579899, - "p5": 0.054873138666152954, - "p6": 0.0025426489301025867, - "s1": 0.021408427506685257, - "s2": -0.38772502541542053, - "s3": -0.005474057514220476, - "s4": 0.023369837552309036 - }, - "green": { - "k0": 1, - "k1": -0.34352442622184753, - "k10": 407482208, - "k11": -607444544, - "k12": 364629760, - "k2": -24.74683952331543, - "k3": 1511.1038818359375, - "k4": -31125.5234375, - "k5": 335715.46875, - "k6": -1955696.125, - "k7": 4600685, - "k8": 13278577, - "k9": -130938128, - "p1": 0.004142312798649073, - "p2": -0.09396903216838837, - "p3": 2.4918816089630127, - "p4": -0.0022665332071483135, - "p5": 0.10812357068061829, - "p6": -0.44162964820861816, - "s1": 0.0093619329854846, - "s2": -0.14777334034442902, - "s3": -0.007819280959665775, - "s4": 0.04495905712246895 - }, - "red": { - "k0": 1, - "k1": -2.3546030521392822, - "k10": -186403008, - "k11": 188764864, - "k12": -76325736, - "k2": 105.43265533447266, - "k3": -2204.986572265625, - "k4": 25744.6015625, - "k5": -155664.125, - "k6": 224915.46875, - "k7": 3438194.75, - "k8": -27138312, - "k9": 96143232, - "p1": 0.002255076775327325, - "p2": 0.04626873880624771, - "p3": 0.5855537056922913, - "p4": -0.00238604168407619, - "p5": 0.13307441771030426, - "p6": -0.7181653380393982, - "s1": -0.007675641681998968, - "s2": 0.06325908750295639, - "s3": -0.010614600963890553, - "s4": 0.08439233154058456 - } - }, - "right": { - "blue": null, - "green": null, - "red": null - } - }, - "distortion_coeff_WVR": { - "left": { - "blue": { - "k1": -0.52751225233078, - "k2": 21.61807632446289, - "k3": -242.61370849609375, - "k4": 1472.376708984375, - "k5": -4238.3759765625, - "k6": 4892.56494140625 - }, - "green": { - "k1": -1.0224546194076538, - "k2": 27.280540466308594, - "k3": -268.6165771484375, - "k4": 1501.5048828125, - "k5": -4129.18359375, - "k6": 4632.85888671875 - }, - "red": { - "k1": -1.1281183958053589, - "k2": 27.28583335876465, - "k3": -259.07769775390625, - "k4": 1417.8099365234375, - "k5": -3838.6845703125, - "k6": 4259.6640625 - } - }, - "right": { - "blue": null, - "green": null, - "red": null - } - }, - "distortion_coeff_modify": { - "left": { - "blue": { - "k0": 1, - "k1": 0.20147620141506195, - "k10": -3472923.5, - "k2": -12.570015907287598, - "k3": 496.2109375, - "k4": -8279.626953125, - "k5": 81062.2109375, - "k6": -494675.1875, - "k7": 1915181.375, - "k8": -4567405.5, - "k9": 6103839, - "theta": 0.02045777626335621 - } - }, - "right": { - "blue": null - } - }, - "enlarge_ratio": { - "left": 1.7995648384094238, - "right": 0 - }, - "grow_for_undistort": { - "left": 0.799564778804779, - "right": null - }, - "grow_for_undistort2": { - "left": 0.22050705552101135, - "right": null - }, - "grow_for_undistort3": { - "left": 0.4016369581222534, - "right": null - }, - "grow_for_undistort4": { - "left": 0.3988267183303833, - "right": null - }, - "hmd_model_name": "C10_2.88", - "intrinsics": { - "left": [ - [ - 1.2503293752670288, - 0, - 0.15849673748016357 - ], - [ - 0, - 1.2503293752670288, - -0.0016339869471266866 - ], - [ - 0, - 0, - -1 - ] - ], - "right": null - }, - "intrinsics2": { - "left": [ - [ - 1.2421778440475464, - 0, - 0.15849673748016357 - ], - [ - 0, - 1.2421778440475464, - -0.0016339869471266866 - ], - [ - 0, - 0, - -1 - ] - ], - "right": null - }, - "model_type": "strengthen_high_order", - "normalizedRadius": 1860.4783935546875, - "resolution": { - "height": 2448, - "width": 2448 - }, - "scale": { - "left": 0.4587453305721283, - "right": 0 - }, - "scale_ratio": 2, - "version": "1.10" - }, - "right": { - "center": { - "left": { - "x": 0, - "y": 0 - }, - "right": { - "x": -97, - "y": -5 - } - }, - "distortion_coeff": { - "left": { - "blue": null, - "green": null, - "red": null - }, - "right": { - "blue": { - "k0": 1, - "k1": 0.11100059002637863, - "k10": -344108864, - "k11": 533194880, - "k12": -329702240, - "k2": 23.737092971801758, - "k3": -1139.0538330078125, - "k4": 24623.287109375, - "k5": -280001.8125, - "k6": 1740926.25, - "k7": -4790315, - "k8": -7387014.5, - "k9": 103427968, - "p1": -0.005450691562145948, - "p2": 0.5274219512939453, - "p3": -7.250232219696045, - "p4": 0.0024943137541413307, - "p5": -0.04658109322190285, - "p6": -0.3234362006187439, - "s1": -0.041014980524778366, - "s2": 0.4618517756462097, - "s3": -0.013776713982224464, - "s4": 0.1097743883728981 - }, - "green": { - "k0": 1, - "k1": -1.9853897094726562, - "k10": -97788800, - "k11": 238769408, - "k12": -170494400, - "k2": 121.99394226074219, - "k3": -3483.334716796875, - "k4": 58569.11328125, - "k5": -608190.4375, - "k6": 3996987, - "k7": -16292569, - "k8": 36816728, - "k9": -22024784, - "p1": -0.005147983785718679, - "p2": 0.4241090416908264, - "p3": -5.4583611488342285, - "p4": 0.002887109527364373, - "p5": -0.033154699951410294, - "p6": -0.6358795762062073, - "s1": -0.030129536986351013, - "s2": 0.28500503301620483, - "s3": -0.011760484427213669, - "s4": 0.1217983067035675 - }, - "red": { - "k0": 1, - "k1": -2.262211322784424, - "k10": -284243968, - "k11": 333681088, - "k12": -167608336, - "k2": 99.14322662353516, - "k3": -1967.49658203125, - "k4": 21486.826171875, - "k5": -111867.375, - "k6": -85187.3046875, - "k7": 5260033, - "k8": -36534268, - "k9": 133527448, - "p1": -0.00616124551743269, - "p2": 0.383841335773468, - "p3": -4.855395317077637, - "p4": 0.004933151416480541, - "p5": -0.10234498977661133, - "p6": 0.0001925224787555635, - "s1": -0.023164117708802223, - "s2": 0.21405749022960663, - "s3": -0.008042753674089909, - "s4": 0.08172719925642014 - } - } - }, - "distortion_coeff_WVR": { - "left": { - "blue": null, - "green": null, - "red": null - }, - "right": { - "blue": { - "k1": -0.10089507699012756, - "k2": 11.111873626708984, - "k3": -134.39077758789062, - "k4": 928.0538940429688, - "k5": -2900.510498046875, - "k6": 3611.87255859375 - }, - "green": { - "k1": -0.8295236229896545, - "k2": 23.274219512939453, - "k3": -226.37644958496094, - "k4": 1265.251708984375, - "k5": -3461.201171875, - "k6": 3898.091796875 - }, - "red": { - "k1": -0.995377242565155, - "k2": 24.5732479095459, - "k3": -229.68536376953125, - "k4": 1250.6016845703125, - "k5": -3361.6220703125, - "k6": 3731.44580078125 - } - } - }, - "distortion_coeff_modify": { - "left": { - "blue": null - }, - "right": { - "blue": { - "k0": 1, - "k1": 1.0663613080978394, - "k10": -19183604, - "k2": -63.7076416015625, - "k3": 1963.8306884765625, - "k4": -32677.841796875, - "k5": 332866.96875, - "k6": -2150781, - "k7": 8842296, - "k8": -22365840, - "k9": 31675536, - "theta": -0.017072169110178947 - } - } - }, - "enlarge_ratio": { - "left": 0, - "right": 1.771338939666748 - }, - "grow_for_undistort": { - "left": null, - "right": 0.7713388800621033 - }, - "grow_for_undistort2": { - "left": null, - "right": 0.2265591025352478 - }, - "grow_for_undistort3": { - "left": null, - "right": 0.40129444003105164 - }, - "grow_for_undistort4": { - "left": null, - "right": 0.4169063866138458 - }, - "hmd_model_name": "C10_2.88", - "intrinsics": { - "left": null, - "right": [ - [ - 1.2549976110458374, - 0, - -0.15849673748016357 - ], - [ - 0, - 1.2549976110458374, - 0.008169935084879398 - ], - [ - 0, - 0, - -1 - ] - ] - }, - "intrinsics2": { - "left": null, - "right": [ - [ - 1.2421778440475464, - 0, - -0.15849673748016357 - ], - [ - 0, - 1.2421778440475464, - 0.008169935084879398 - ], - [ - 0, - 0, - -1 - ] - ] - }, - "model_type": "strengthen_high_order", - "normalizedRadius": 1860.4783935546875, - "resolution": { - "height": 2448, - "width": 2448 - }, - "scale": { - "left": 0, - "right": 0.45825129747390747 - }, - "scale_ratio": 2, - "version": "1.10" - } -} \ No newline at end of file diff --git a/lensServer/dist/.gitignore b/lensServer/dist/.gitignore deleted file mode 100644 index e69de29..0000000 diff --git a/lensServer/flake.lock b/lensServer/flake.lock deleted file mode 100644 index a338188..0000000 --- a/lensServer/flake.lock +++ /dev/null @@ -1,93 +0,0 @@ -{ - "nodes": { - "flake-utils": { - "locked": { - "lastModified": 1642700792, - "narHash": "sha256-XqHrk7hFb+zBvRg6Ghl+AZDq03ov6OshJLiSWOoX5es=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "846b2ae0fc4cc943637d3d1def4454213e203cba", - "type": "github" - }, - "original": { - "owner": "numtide", - "repo": "flake-utils", - "type": "github" - } - }, - "flake-utils_2": { - "locked": { - "lastModified": 1637014545, - "narHash": "sha256-26IZAc5yzlD9FlDT54io1oqG/bBoyka+FJk5guaX4x4=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "bba5dcc8e0b20ab664967ad83d24d64cb64ec4f4", - "type": "github" - }, - "original": { - "owner": "numtide", - "repo": "flake-utils", - "type": "github" - } - }, - "nixpkgs": { - "locked": { - "lastModified": 1642978727, - "narHash": "sha256-ihzVhZZzdspqcSbon5EhOFNRRldKDZGd273WHuAtyDM=", - "owner": "nixos", - "repo": "nixpkgs", - "rev": "c78dba5f76837695d75b6f7903cb776b904a2653", - "type": "github" - }, - "original": { - "owner": "nixos", - "repo": "nixpkgs", - "type": "github" - } - }, - "nixpkgs_2": { - "locked": { - "lastModified": 1637453606, - "narHash": "sha256-Gy6cwUswft9xqsjWxFYEnx/63/qzaFUwatcbV5GF/GQ=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "8afc4e543663ca0a6a4f496262cd05233737e732", - "type": "github" - }, - "original": { - "owner": "NixOS", - "ref": "nixpkgs-unstable", - "repo": "nixpkgs", - "type": "github" - } - }, - "root": { - "inputs": { - "flake-utils": "flake-utils", - "nixpkgs": "nixpkgs", - "rust-overlay": "rust-overlay" - } - }, - "rust-overlay": { - "inputs": { - "flake-utils": "flake-utils_2", - "nixpkgs": "nixpkgs_2" - }, - "locked": { - "lastModified": 1642838864, - "narHash": "sha256-pHnhm3HWwtvtOK7NdNHwERih3PgNlacrfeDwachIG8E=", - "owner": "oxalica", - "repo": "rust-overlay", - "rev": "9fb49daf1bbe1d91e6c837706c481f9ebb3d8097", - "type": "github" - }, - "original": { - "owner": "oxalica", - "repo": "rust-overlay", - "type": "github" - } - } - }, - "root": "root", - "version": 7 -} diff --git a/lensServer/flake.nix b/lensServer/flake.nix deleted file mode 100644 index d95c042..0000000 --- a/lensServer/flake.nix +++ /dev/null @@ -1,39 +0,0 @@ -{ - description = "VIVE Pro 2 support for linux"; - inputs = { - nixpkgs.url = "github:nixos/nixpkgs"; - flake-utils.url = "github:numtide/flake-utils"; - rust-overlay.url = "github:oxalica/rust-overlay"; - }; - outputs = { self, nixpkgs, flake-utils, rust-overlay }: - flake-utils.lib.eachDefaultSystem (system: - let - pkgs = import nixpkgs - { - inherit system; - overlays = [ rust-overlay.overlay ]; - crossSystem = { - config = "x86_64-w64-mingw32"; - }; - }; - rust = ((pkgs.buildPackages.rustChannelOf { date = "2022-01-13"; channel = "nightly"; }).default.override { - extensions = [ "rust-src" ]; - }); - in - rec { - devShell = pkgs.callPackage - ({ mkShell, stdenv, windows, wine64 }: mkShell { - nativeBuildInputs = [ - rust - ]; - - depsBuildBuild = [ wine64 ]; - buildInputs = [ windows.pthreads ]; - - CARGO_TARGET_X86_64_PC_WINDOWS_GNU_LINKER = "${stdenv.cc.targetPrefix}cc"; - CARGO_TARGET_X86_64_PC_WINDOWS_GNU_RUNNER = "wine64"; - }) - { }; - } - ); -} diff --git a/lensServer/src/main.rs b/lensServer/src/main.rs deleted file mode 100644 index 366c390..0000000 --- a/lensServer/src/main.rs +++ /dev/null @@ -1,215 +0,0 @@ -use byteorder::{NativeEndian as NE, ReadBytesExt, WriteBytesExt}; -use libloading::os::windows::{Library, Symbol}; -use std::ffi::OsStr; -use std::io::{self, Read, Write}; -use std::sync::atomic::{AtomicBool, Ordering}; - -#[link(name = "msvcrt")] -extern "C" { - fn _setmode(fd: u32, mode: u32) -> i32; -} - -#[derive(Debug)] -struct DistortOutput { - red: [f32; 2], - green: [f32; 2], - blue: [f32; 2], -} -impl Output for DistortOutput { - fn write(self, w: &mut W) { - w.write_f32::(self.red[0]).unwrap(); - w.write_f32::(self.red[1]).unwrap(); - w.write_f32::(self.green[0]).unwrap(); - w.write_f32::(self.green[1]).unwrap(); - w.write_f32::(self.blue[0]).unwrap(); - w.write_f32::(self.blue[1]).unwrap(); - } -} -#[derive(Debug)] -struct LeftRightTopBottom { - left: f32, - right: f32, - top: f32, - bottom: f32, -} -impl Output for LeftRightTopBottom { - fn write(self, w: &mut W) { - w.write_f32::(self.left).unwrap(); - w.write_f32::(self.right).unwrap(); - w.write_f32::(self.top).unwrap(); - w.write_f32::(self.bottom).unwrap(); - } -} - -#[derive(Clone, Copy)] -#[repr(u32)] -enum Eye { - Left = 0, - Right = 1, -} -impl Eye { - fn read(r: &mut R) -> Self { - match r.read_u8().unwrap() { - 0 => Self::Left, - 1 => Self::Right, - _ => panic!(), - } - } -} - -static CREATED: AtomicBool = AtomicBool::new(false); - -struct LensLibraryMethods { - init: Symbol u32>, - set_resolution: Symbol u32>, - load_json_str: Symbol u32>, - distort_uv: Symbol< - unsafe extern "C" fn( - eye: u32, - color: u32, - u: f32, - v: f32, - c1: &mut f32, - c2: &mut f32, - ) -> u32, - >, - grow_for_undistort: Symbol u32>, - intrinsic: Symbol u32>, -} -impl LensLibraryMethods { - fn init(&self) { - assert_eq!(unsafe { (self.init)() }, 0); - } - fn set_resolution(&self, width: u32, height: u32) { - assert_eq!(unsafe { (self.set_resolution)(width, height) }, 0); - } - fn load_json_str(&self, str: &str) { - assert_eq!(unsafe { (self.load_json_str)(str.as_ptr(), str.len()) }, 0) - } - - fn grow_for_undistort(&self, eye: Eye) -> [f32; 4] { - let mut out = [0.0; 4]; - assert_eq!( - unsafe { (self.grow_for_undistort)(eye as u32, &mut out) }, - 0 - ); - out - } - fn intrinsic(&self, eye: Eye) -> [f32; 8] { - let mut out = [0.0; 8]; - assert_eq!(unsafe { (self.intrinsic)(eye as u32, &mut out) }, 0); - out - } - fn distort_uv(&self, eye: Eye, color: u32, uv: [f32; 2]) -> [f32; 2] { - let mut a = 0.0; - let mut b = 0.0; - assert_eq!( - unsafe { (self.distort_uv)(eye as u32, color, uv[0], uv[1], &mut a, &mut b) }, - 0 - ); - [a, b] - } -} -struct LensLibrary { - m: LensLibraryMethods, - _marker: *const (), -} -impl LensLibrary { - unsafe fn new(library: impl AsRef, resolution: (u32, u32), json: &str) -> Self { - assert!( - !CREATED.swap(true, Ordering::Relaxed), - "only single LensLibrary may exist per process" - ); - let lib = Box::leak(Box::new( - Library::load_with_flags(library, 0x00000008).expect("failed to load library"), - )); - let m = LensLibraryMethods { - init: lib.get(b"init").unwrap(), - set_resolution: lib.get(b"setResolution").unwrap(), - load_json_str: lib.get(b"loadJsonStr").unwrap(), - distort_uv: lib.get(b"distortUV").unwrap(), - grow_for_undistort: lib.get(b"getGrowForUndistort").unwrap(), - intrinsic: lib.get(b"getIntrinsic").unwrap(), - }; - m.init(); - m.set_resolution(resolution.0, resolution.1); - m.load_json_str(json); - Self { - m, - _marker: std::ptr::null(), - } - } - fn distort(&self, eye: Eye, uv: [f32; 2]) -> DistortOutput { - DistortOutput { - red: self.m.distort_uv(eye, 2, uv), - green: self.m.distort_uv(eye, 1, uv), - blue: self.m.distort_uv(eye, 0, uv), - } - } - fn projection_raw(&self, eye: Eye) -> LeftRightTopBottom { - let mut g = self.m.grow_for_undistort(eye); - for v in g.iter_mut() { - *v += 1.0; - } - let i = self.m.intrinsic(eye); - LeftRightTopBottom { - left: (-1.0 - i[2]) * g[0] / i[0], - right: (1.0 - i[2]) * g[1] / i[0], - top: (1.0 - i[4 + 1]) * g[2] / i[4], - bottom: (-1.0 - i[4 + 1]) * g[3] / i[4], - } - } -} - -enum Input { - Distort(Eye, [f32; 2]), - ProjectionRaw(Eye), -} -impl Input { - fn read(r: &mut R) -> Self { - match r.read_u8().unwrap() { - 0 => Self::Distort( - Eye::read(r), - [r.read_f32::().unwrap(), r.read_f32::().unwrap()], - ), - 1 => Self::ProjectionRaw(Eye::read(r)), - _ => panic!(), - } - } -} - -trait Output { - fn write(self, w: &mut W); -} - -// center pos - to int -// scale ratio - to int -fn main() { - eprintln!("hello from lens server"); - let mut exedir = std::env::current_exe().unwrap(); - exedir.pop(); - - let mut config_path = exedir.clone(); - config_path.push("config.json"); - let config = std::fs::read_to_string(config_path).expect("failed to read config"); - - let mut distortion_path = exedir.clone(); - distortion_path.push("LibLensDistortion.dll"); - let lib = unsafe { LensLibrary::new(distortion_path, (2448, 2448), &config) }; - - let stdin = io::stdin(); - let mut stdin = stdin.lock(); - let stdout = io::stdout(); - let mut stdout = stdout.lock(); - - eprintln!("server ready"); - assert_ne!(unsafe { _setmode(0, 0x8000) }, -1); - assert_ne!(unsafe { _setmode(1, 0x8000) }, -1); - loop { - match Input::read(&mut stdin) { - Input::Distort(eye, uv) => lib.distort(eye, uv).write(&mut stdout), - Input::ProjectionRaw(eye) => lib.projection_raw(eye).write(&mut stdout), - }; - stdout.flush().unwrap(); - } -} diff --git a/lens_server.h b/lens_server.h deleted file mode 100644 index 5177d26..0000000 --- a/lens_server.h +++ /dev/null @@ -1,22 +0,0 @@ -struct ServerInputDistort { - char id; - char eye; - float u; - float v; -} __attribute__((__packed__)); -struct ServerOutputDistort { - float red[2]; - float green[2]; - float blue[2]; -} __attribute__((__packed__)); - -struct ServerInputProjectionRaw { - char id; - char eye; -} __attribute__((__packed__)); -struct ServerOutputProjectionRaw { - float left; - float right; - float top; - float bottom; -} __attribute__((__packed__)); diff --git a/src/driver_context.rs b/src/driver_context.rs new file mode 100644 index 0000000..f5f8918 --- /dev/null +++ b/src/driver_context.rs @@ -0,0 +1,69 @@ +use std::{ + ffi::{c_void, CStr}, + os::raw::c_char, + ptr::null_mut, +}; + +use crate::{ + driver_host::get_driver_host, openvr::IVRServerDriverHostVtable, try_vr, vr_result, Error, + Result, +}; +use cppvtbl::{impl_vtables, HasVtable, VtableRef, WithVtables}; +use once_cell::sync::OnceCell; +use tracing::info; + +use crate::openvr::{ + DriverHandle_t, EVRInitError, IVRDriverContext, IVRDriverContextVtable, + IVRServerDriverHost_Version, +}; + +#[impl_vtables(IVRDriverContext)] +pub struct DriverContext { + pub real: &'static VtableRef, +} +impl DriverContext { + pub fn get_generic_interface(&self, name: *const c_char) -> Result<*mut c_void> { + try_vr!(self.real.GetGenericInterface(name)) + } +} + +impl IVRDriverContext for DriverContext { + fn GetGenericInterface( + &self, + pchInterfaceVersion: *const c_char, + result: *mut EVRInitError, + ) -> *mut c_void { + let name = unsafe { CStr::from_ptr(pchInterfaceVersion) }; + info!("get generic interface {name:?}"); + if name == unsafe { CStr::from_ptr(IVRServerDriverHost_Version) } { + vr_result!( + result, + get_driver_host().map(|host| { + VtableRef::into_raw(HasVtable::::get(host)) as *mut _ + }), + null_mut() + ) + } else { + self.real.GetGenericInterface(pchInterfaceVersion, result) + } + } + + fn GetDriverHandle(&self) -> DriverHandle_t { + self.real.GetDriverHandle() + } +} + +static DRIVER_CONTEXT: OnceCell> = OnceCell::new(); +pub fn try_init_driver_context(real: &'static VtableRef) -> Result<(), ()> { + if DRIVER_CONTEXT.get().is_some() { + return Ok(()); + } + let context = WithVtables::new(DriverContext { real }); + DRIVER_CONTEXT.set(context).map_err(|_| ()) +} + +pub fn get_driver_context() -> Result<&'static WithVtables> { + DRIVER_CONTEXT + .get() + .ok_or_else(|| Error::Internal("driver context is not initialized yet")) +} diff --git a/src/driver_host.rs b/src/driver_host.rs new file mode 100644 index 0000000..d56aa1f --- /dev/null +++ b/src/driver_host.rs @@ -0,0 +1,183 @@ +use cppvtbl::{impl_vtables, HasVtable, VtableRef, WithVtables}; +use lens_client::start_lens_server; +use once_cell::sync::OnceCell; +use std::cell::RefCell; +use std::ffi::CStr; +use std::os::raw::c_char; +use std::rc::Rc; +use tracing::{error, info}; +use vive_hid::{Resolution, SteamDevice, ViveDevice}; + +use crate::driver_context::get_driver_context; +use crate::hmd::HmdDriver; +use crate::openvr::{ + Compositor_FrameTiming, DriverPose_t, ETrackedDeviceClass, EVREventType, HmdMatrix34_t, + HmdRect2_t, ITrackedDeviceServerDriverVtable, IVRServerDriverHost_Version, TrackedDevicePose_t, + VREvent_t, +}; +use crate::openvr::{IVRServerDriverHost, IVRServerDriverHostVtable, VREvent_Data_t}; +use crate::settings::Setting; +use crate::{setting, Result}; + +#[impl_vtables(IVRServerDriverHost)] +pub struct DriverHost { + real: &'static VtableRef, +} + +const HMD_RESOLUTION: Setting = setting!("vivepro2", "resolution"); + +impl IVRServerDriverHost for DriverHost { + fn TrackedDeviceAdded( + &self, + pchDeviceSerialNumber: *const c_char, + eDeviceClass: ETrackedDeviceClass, + pDriver: *const VtableRef, + ) -> bool { + let sn = unsafe { CStr::from_ptr(pchDeviceSerialNumber) } + .to_string_lossy() + .to_string(); + info!("added tracked device: {sn:?} ({eDeviceClass:?})"); + if eDeviceClass == ETrackedDeviceClass::TrackedDeviceClass_HMD { + let err: Result<()> = try { + // Steam part is opened for checking if this is really a needed HMD device + let _steam = Rc::new(SteamDevice::open(&sn)?); + // We don't know for sure this device serial + let vive = Rc::new(ViveDevice::open_first()?); + + let res = HMD_RESOLUTION.get(); + let resolution = + Resolution::try_from(res as u8).unwrap_or(Resolution::R2448x1224f90); + HMD_RESOLUTION.set(resolution as u8 as i32); + + vive.set_resolution(resolution)?; + + let config = vive.read_config()?; + + let lens = Rc::new(RefCell::new(start_lens_server( + config.inhouse_lens_correction, + )?)); + let real = unsafe { VtableRef::from_raw(pDriver) }; + + let hmd = Box::leak(Box::new(WithVtables::new(HmdDriver { + // steam, + // vive, + lens, + real, + resolution, + }))); + + return self.real.TrackedDeviceAdded( + pchDeviceSerialNumber, + eDeviceClass, + HasVtable::::get(hmd), + ); + }; + error!("failed to wrap hmd: {}", err.err().unwrap()); + } + self.real + .TrackedDeviceAdded(pchDeviceSerialNumber, eDeviceClass, pDriver) + } + + fn TrackedDevicePoseUpdated( + &self, + unWhichDevice: u32, + newPose: *const DriverPose_t, + unPoseStructSize: u32, + ) { + self.real + .TrackedDevicePoseUpdated(unWhichDevice, newPose, unPoseStructSize) + } + + fn VsyncEvent(&self, vsyncTimeOffsetSeconds: f64) { + self.real.VsyncEvent(vsyncTimeOffsetSeconds) + } + + fn VendorSpecificEvent( + &self, + unWhichDevice: u32, + eventType: EVREventType, + eventData: *const VREvent_Data_t, + eventTimeOffset: f64, + ) { + self.real + .VendorSpecificEvent(unWhichDevice, eventType, eventData, eventTimeOffset) + } + + fn IsExiting(&self) -> bool { + self.real.IsExiting() + } + + fn PollNextEvent(&self, pEvent: *mut VREvent_t, uncbVREvent: u32) -> bool { + self.real.PollNextEvent(pEvent, uncbVREvent) + } + + fn GetRawTrackedDevicePoses( + &self, + fPredictedSecondsFromNow: f32, + pTrackedDevicePoseArray: *mut TrackedDevicePose_t, + unTrackedDevicePoseArrayCount: u32, + ) { + self.real.GetRawTrackedDevicePoses( + fPredictedSecondsFromNow, + pTrackedDevicePoseArray, + unTrackedDevicePoseArrayCount, + ) + } + + fn RequestRestart( + &self, + pchLocalizedReason: *const c_char, + pchExecutableToStart: *const c_char, + pchArguments: *const c_char, + pchWorkingDirectory: *const c_char, + ) { + self.real.RequestRestart( + pchLocalizedReason, + pchExecutableToStart, + pchArguments, + pchWorkingDirectory, + ) + } + + fn GetFrameTimings(&self, pTiming: *mut Compositor_FrameTiming, nFrames: u32) -> u32 { + self.real.GetFrameTimings(pTiming, nFrames) + } + + fn SetDisplayEyeToHead( + &self, + unWhichDevice: u32, + eyeToHeadLeft: *const HmdMatrix34_t, + eyeToHeadRight: *const HmdMatrix34_t, + ) { + self.real + .SetDisplayEyeToHead(unWhichDevice, eyeToHeadLeft, eyeToHeadRight) + } + + fn SetDisplayProjectionRaw( + &self, + unWhichDevice: u32, + eyeLeft: *const HmdRect2_t, + eyeRight: *const HmdRect2_t, + ) { + self.real + .SetDisplayProjectionRaw(unWhichDevice, eyeLeft, eyeRight) + } + + fn SetRecommendedRenderTargetSize(&self, unWhichDevice: u32, nWidth: u32, nHeight: u32) { + self.real + .SetRecommendedRenderTargetSize(unWhichDevice, nWidth, nHeight) + } +} + +static DRIVER_HOST: OnceCell> = OnceCell::new(); + +pub fn get_driver_host() -> Result<&'static WithVtables> { + DRIVER_HOST.get_or_try_init(|| { + let context = get_driver_context()?; + let real = unsafe { + &*(context.get_generic_interface(IVRServerDriverHost_Version)? as *const _ + as *const VtableRef) + }; + Ok(WithVtables::new(DriverHost { real })) + }) +} diff --git a/src/error.rs b/src/error.rs new file mode 100644 index 0000000..2a7ad1b --- /dev/null +++ b/src/error.rs @@ -0,0 +1,68 @@ +use std::result; + +use crate::openvr::EVRInitError; + +#[derive(thiserror::Error, Debug)] +pub enum Error { + #[error("openvr error: {0:?}")] + VR(EVRInitError), + #[error("lens error: {0}")] + Lens(#[from] lens_protocol::Error), + #[error("lens client error: {0}")] + LensClient(#[from] lens_client::Error), + #[error("libloading: {0}")] + LibLoading(#[from] libloading::Error), + #[error("hid error: {0}")] + Hid(#[from] vive_hid::Error), + #[error("internal error: {0}")] + Internal(&'static str), +} + +impl From for Error { + fn from(e: EVRInitError) -> Self { + Self::VR(e) + } +} + +pub type Result = result::Result; + +#[macro_export] +macro_rules! try_vr { + ($($call:ident).+ ($($arg:expr),*)) => {{ + let mut error = crate::openvr::EVRInitError::VRInitError_None; + let res = $($call).+($($arg,)* &mut error); + + if error != crate::openvr::EVRInitError::VRInitError_None { + Err(crate::Error::VR(error)) + } else { + Ok(res) + } + }}; +} + +#[macro_export] +macro_rules! vr_result { + ($result:ident, $res:expr, $err:expr) => { + #[allow(unreachable_patterns)] + match $res { + Ok(v) => { + if !$result.is_null() { + unsafe { *$result = crate::openvr::EVRInitError::VRInitError_None }; + } + v + } + Err(crate::Error::VR(vr)) => { + if !$result.is_null() { + unsafe { *$result = vr }; + } + $err + } + Err(_) => { + if !$result.is_null() { + unsafe { *$result = crate::openvr::EVRInitError::VRInitError_Unknown }; + } + $err + } + } + }; +} diff --git a/src/factory.rs b/src/factory.rs new file mode 100644 index 0000000..24b18c3 --- /dev/null +++ b/src/factory.rs @@ -0,0 +1,63 @@ +use std::{ + ffi::{c_void, CStr}, + os::raw::c_char, + ptr::null, +}; + +use crate::{Error, Result}; +use cppvtbl::{HasVtable, VtableRef}; +use libloading::{Library, Symbol}; +use once_cell::sync::OnceCell; +use tracing::info; + +use crate::{ + openvr::{ + EVRInitError, IServerTrackedDeviceProviderVtable, IServerTrackedDeviceProvider_Version, + }, + server_tracked_provider::get_server_tracked_provider, +}; + +pub type HmdDriverFactory = + unsafe extern "C" fn(*const c_char, result: *mut EVRInitError) -> *const c_void; +static HMD_DRIVER_FACTORY: OnceCell> = OnceCell::new(); +pub fn get_hmd_driver_factory() -> Result<&'static Symbol<'static, HmdDriverFactory>> { + HMD_DRIVER_FACTORY.get_or_try_init(|| { + let mut path = + process_path::get_dylib_path().ok_or(Error::Internal("process path failed"))?; + path.pop(); + path.push("driver_lighthouse_real.so"); + + let library: &'static mut Library = + Box::leak(Box::new(unsafe { libloading::Library::new(&path)? })); + Ok(unsafe { library.get(b"HmdDriverFactory") }.expect("can't find HmdDriverFactory")) + }) +} + +fn HmdDriverFactory_impl(iface: *const c_char) -> Result<*const c_void> { + // May be already installed + let _ = tracing_subscriber::fmt().without_time().try_init(); + + let ifacen = unsafe { CStr::from_ptr(iface) }; + info!("requested interface: {ifacen:?}"); + + if ifacen == unsafe { CStr::from_ptr(IServerTrackedDeviceProvider_Version) } { + let provider = get_server_tracked_provider()?; + Ok( + VtableRef::into_raw(HasVtable::::get( + &provider, + )) as *const _ as *const c_void, + ) + } else { + let factory = get_hmd_driver_factory()?; + unsafe { try_vr!(factory(iface)) } + } +} + +#[no_mangle] +pub extern "C" fn HmdDriverFactory( + iface: *const c_char, + result: *mut EVRInitError, +) -> *const c_void { + eprintln!("factory call"); + vr_result!(result, HmdDriverFactory_impl(iface), null()) +} diff --git a/src/hmd.rs b/src/hmd.rs new file mode 100644 index 0000000..1f2ac52 --- /dev/null +++ b/src/hmd.rs @@ -0,0 +1,195 @@ +use std::{ + cell::RefCell, + ffi::{c_void, CStr}, + os::raw::c_char, + rc::Rc, +}; + +use crate::Result; +use cppvtbl::{impl_vtables, HasVtable, VtableRef, WithVtables}; +use lens_protocol::{Client, Eye}; +use tracing::{error, instrument}; +use vive_hid::Resolution; + +use crate::openvr::{ + DistortionCoordinates_t, DriverPose_t, EVREye, EVRInitError, ITrackedDeviceServerDriver, + ITrackedDeviceServerDriverVtable, IVRDisplayComponent, IVRDisplayComponentVtable, + IVRDisplayComponent_Version, +}; + +fn map_eye(eye: EVREye) -> Eye { + match eye { + EVREye::Eye_Left => Eye::Left, + EVREye::Eye_Right => Eye::Right, + } +} + +#[impl_vtables(IVRDisplayComponent)] +struct HmdDisplay { + // steam: Rc, + // vive: Rc, + lens: Rc>, + real: &'static VtableRef, + resolution: Resolution, +} + +impl IVRDisplayComponent for HmdDisplay { + #[instrument(skip(self))] + fn GetWindowBounds(&self, pnX: *mut i32, pnY: *mut i32, pnWidth: *mut u32, pnHeight: *mut u32) { + // let err: Result<()> = try { + let (width, height) = self.resolution.resolution(); + unsafe { + *pnX = 0; + *pnY = 0; + *pnWidth = width; + *pnHeight = height; + } + // return; + // }; + // error!("failed: {}", err.err().unwrap()); + // self.real.GetWindowBounds(pnX, pnY, pnWidth, pnHeight) + } + + fn IsDisplayOnDesktop(&self) -> bool { + self.real.IsDisplayOnDesktop() + } + + fn IsDisplayRealDisplay(&self) -> bool { + self.real.IsDisplayRealDisplay() + } + + fn GetRecommendedRenderTargetSize(&self, pnWidth: *mut u32, pnHeight: *mut u32) { + self.real.GetRecommendedRenderTargetSize(pnWidth, pnHeight) + } + + #[instrument(skip(self))] + fn GetEyeOutputViewport( + &self, + eEye: EVREye, + pnX: *mut u32, + pnY: *mut u32, + pnWidth: *mut u32, + pnHeight: *mut u32, + ) { + // let err: Result<()> = try { + let (width, height) = self.resolution.resolution(); + unsafe { + *pnX = if eEye == EVREye::Eye_Left { + 0 + } else { + width / 2 + }; + *pnY = 0; + *pnWidth = width / 2; + *pnHeight = height; + } + // return; + // }; + // error!("failed: {}", err.err().unwrap()); + // self.real + // .GetEyeOutputViewport(eEye, pnX, pnY, pnWidth, pnHeight) + } + + #[instrument(skip(self))] + fn GetProjectionRaw( + &self, + eEye: EVREye, + pfLeft: *mut f32, + pfRight: *mut f32, + pfTop: *mut f32, + pfBottom: *mut f32, + ) { + let err: Result<()> = try { + let mut lens = self.lens.borrow_mut(); + let result = lens.project(map_eye(eEye))?; + unsafe { + *pfLeft = result.left; + *pfRight = result.right; + if lens.matrix_needs_inversion()? { + *pfTop = result.bottom; + *pfBottom = result.top; + } else { + *pfTop = result.top; + *pfBottom = result.bottom; + } + } + return; + }; + error!("failed: {}", err.err().unwrap()); + self.real + .GetProjectionRaw(eEye, pfLeft, pfRight, pfTop, pfBottom) + } + + #[instrument(skip(self))] + fn ComputeDistortion(&self, eEye: EVREye, fU: f32, fV: f32) -> DistortionCoordinates_t { + let err: Result<()> = try { + let mut lens = self.lens.borrow_mut(); + let inverse = lens.matrix_needs_inversion()?; + let result = lens.distort(map_eye(eEye), [fU, if inverse { 1.0 - fV } else { fV }])?; + return DistortionCoordinates_t { + rfRed: result.red, + rfGreen: result.green, + rfBlue: result.blue, + }; + }; + error!("failed: {}", err.err().unwrap()); + self.real.ComputeDistortion(eEye, fU, fV) + } +} + +#[impl_vtables(ITrackedDeviceServerDriver)] +pub struct HmdDriver { + // pub steam: Rc, + // pub vive: Rc, + pub lens: Rc>, + pub real: &'static VtableRef, + pub resolution: Resolution, +} + +impl ITrackedDeviceServerDriver for HmdDriver { + fn Activate(&self, unObjectId: u32) -> EVRInitError { + self.real.Activate(unObjectId) + } + + fn Deactivate(&self) { + self.real.Deactivate() + } + + fn EnterStandby(&self) { + self.real.EnterStandby() + } + + fn GetComponent(&self, pchComponentNameAndVersion: *const c_char) -> *mut c_void { + let name = unsafe { CStr::from_ptr(pchComponentNameAndVersion) }; + println!("getting {name:?} hmd component"); + let real = self.real.GetComponent(pchComponentNameAndVersion); + if name == unsafe { CStr::from_ptr(IVRDisplayComponent_Version) } { + println!("faking display"); + let display = Box::leak(Box::new(WithVtables::new(HmdDisplay { + // steam: self.steam.clone(), + // vive: self.vive.clone(), + lens: self.lens.clone(), + real: unsafe { VtableRef::from_raw(real as *const _) }, + resolution: self.resolution, + }))); + VtableRef::into_raw_mut(HasVtable::::get_mut(display)) + as *mut _ + } else { + real + } + } + + fn DebugRequest( + &self, + pchRequest: *const c_char, + pchResponseBuffer: *mut c_char, + unResponseBufferSize: u32, + ) { + self.real + .DebugRequest(pchRequest, pchResponseBuffer, unResponseBufferSize) + } + + fn GetPose(&self) -> DriverPose_t { + self.real.GetPose() + } +} diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..71e0d1e --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,17 @@ +#![feature(never_type, try_blocks)] +#![allow(non_snake_case)] + +#[macro_use] +mod openvr; +mod driver_context; +mod driver_host; +#[macro_use] +mod error; +mod factory; +mod hmd; +mod server_tracked_provider; +#[macro_use] +mod settings; +mod log; + +pub use error::{Error, Result}; diff --git a/src/log.rs b/src/log.rs new file mode 100644 index 0000000..d7e84fe --- /dev/null +++ b/src/log.rs @@ -0,0 +1,37 @@ +use std::{ffi::CString, io::Write}; + +use cppvtbl::VtableRef; +use once_cell::sync::OnceCell; + +use crate::openvr::{IVRDriverLog, IVRDriverLogVtable}; + +static DRIVER_LOG: OnceCell<&'static VtableRef> = OnceCell::new(); + +struct LogWriter(Vec); +impl LogWriter { + fn flush_line(&mut self) { + if let Some(driver) = DRIVER_LOG.get() { + self.0.retain(|&x| x != 0); + let v = CString::new(self.0.as_slice()).unwrap(); + driver.Log(v.as_ptr()); + } else { + eprintln!("{}", String::from_utf8_lossy(self.0.as_slice())) + } + self.0.clear(); + } +} +impl Write for LogWriter { + fn write(&mut self, mut buf: &[u8]) -> std::io::Result { + while let Some(pos) = buf.iter().position(|v| *v == b'\n') { + self.0.extend_from_slice(&buf[..pos]); + self.flush_line(); + buf = &buf[pos + 1..]; + } + self.0.extend_from_slice(&buf); + Ok(buf.len()) + } + + fn flush(&mut self) -> std::io::Result<()> { + Ok(()) + } +} diff --git a/src/openvr/.gitignore b/src/openvr/.gitignore new file mode 100644 index 0000000..3d3cf7f --- /dev/null +++ b/src/openvr/.gitignore @@ -0,0 +1,2 @@ +/a.json +/openvr.json diff --git a/openvr_driver.h b/src/openvr/a.hpp similarity index 100% rename from openvr_driver.h rename to src/openvr/a.hpp diff --git a/src/openvr/a.jsonnet b/src/openvr/a.jsonnet new file mode 100644 index 0000000..83696b5 --- /dev/null +++ b/src/openvr/a.jsonnet @@ -0,0 +1,82 @@ +// Generate file similar to openvr.json +// Initally i wrote api generator from it, but then realized driver api isn't defined in it, +// so i wrote this .cpp => openvr.json converter + +local a = import './a.json'; + +local + merge(a, b) = + if a == null then b + else if b == null then a + else if std.type(a) == 'array' && std.type(b) == 'array' then a + b + else if std.type(a) == 'object' && std.type(b) == 'object' then { + [k]: merge(std.get(a, k), std.get(b, k)) for k in std.set(std.objectFields(a) + std.objectFields(b)) + } + else error "can't merge %v and %v" % [a, b]; + +local + makeValue(v) = + if v.kind == "ImplicitCastExpr" then makeValue(v.inner[0]) + else if v.kind == "ConstantExpr" || v.kind == "IntegerLiteral" then v.value + else if v.kind == "StringLiteral" then v.value[1:std.length(v.value) - 1] + else if v.kind == "InitListExpr" then "{%s}" % std.join(", ", std.map(makeValue, v.inner)) + else if v.kind == "DeclRefExpr" then "REF" + else if v.kind == "CXXNullPtrLiteralExpr" then "NULL" + else if v.kind == "UnaryOperator" && v.opcode == "-" then "-%s" % makeValue(v.inner[0]) + else if v.kind == "BinaryOperator" && v.opcode == "*" then "%s * %s" % [makeValue(v.inner[0]), makeValue(v.inner[1])] + else error "" + v, + makeNamespace(a, ns = '') = + local + makeTypedef(def) = { + typedef: def.name, + type: def.type.qualType, + }, + makeParam(param) = { + paramname: param.name, + paramtype: param.type.qualType, + }, + makeMethod(method) = { + methodname: method.name, + returntype: std.stripChars(method.type.qualType[:std.findSubstr("(", method.type.qualType)[0]], " "), + params: std.map(makeParam, std.filter(function(p) p.kind == "ParmVarDecl", std.get(method, "inner", []))), + }, + makeClass(class) = + local methods = std.map(makeMethod, std.filter(function(v) v.kind == "CXXMethodDecl" && !std.get(v, "isImplicit", false), std.get(class, "inner", []))); + std.map(function(m) m { + classname: class.name, + }, methods), + makeField(field) = { + fieldname: field.name, + fieldtype: field.type.qualType, + }, + makeConst(const) = { + constname: const.name, + consttype: const.type.qualType, + constval: makeValue(const.inner[0]), + }, + makeStruct(struct) = { + struct: struct.name, + fields: std.map(makeField, std.filter(function(f) f.kind == "FieldDecl", struct.inner)), + }, + makeEnumValue(value) = { + name: value.name, + value: if !("inner" in value) then null else makeValue(value.inner[0]), + }, + makeEnum(enum) = { + enumname: enum.name, + values: std.map(makeEnumValue, std.filter(function(f) f.kind == "EnumConstantDecl", enum.inner)) + }, + makeUnion(union) = { + values: std.map(makeField, std.filter(function(v) v.kind == "FieldDecl", union.inner)) + }; + std.foldr(merge, std.map(makeNamespace, std.filter(function(c) c.kind == "NamespaceDecl", a.inner)), {}) + { + typedefs+: std.map(makeTypedef, std.filter(function(c) c.kind == "TypedefDecl" && !std.get(c, "isImplicit", false) && !std.startsWith(std.get(c.loc, "file", ""), "/nix/") && !("includedFrom" in c.loc), a.inner)), + methods+: std.join([], std.map(makeClass, std.filter(function(c) c.kind == "CXXRecordDecl" && c.tagUsed == "class", a.inner))), + consts+: std.map(makeConst, std.filter(function(c) c.kind == "VarDecl", a.inner)), + structs+: std.map(makeStruct, std.filter(function(c) "name" in c && c.kind == "CXXRecordDecl" && c.tagUsed == "struct" && "inner" in c, a.inner)), + enums+: std.map(makeEnum, std.filter(function(c) c.kind == "EnumDecl", a.inner)), + /// In openvr.json there is no definition for EventData_t + unions+: std.map(makeUnion, std.filter(function(c) c.kind == "CXXRecordDecl" && c.tagUsed == "union", a.inner)), + }; + +makeNamespace(a) diff --git a/src/openvr/gen_mod_rs.sh b/src/openvr/gen_mod_rs.sh new file mode 100755 index 0000000..fc3c7be --- /dev/null +++ b/src/openvr/gen_mod_rs.sh @@ -0,0 +1,8 @@ +#!/bin/sh + +# Generate AST, fails, as it also tries to compile +clang -Xclang -ast-dump=json -stdlib=libc++ a.hpp > a.json || true +jrsonnet a.jsonnet > openvr.json +jrsonnet mod_rs.jsonnet -S > mod.rs + +rustfmt mod.rs diff --git a/src/openvr/mod.rs b/src/openvr/mod.rs new file mode 100644 index 0000000..1fab50b --- /dev/null +++ b/src/openvr/mod.rs @@ -0,0 +1,2552 @@ +#![allow( + non_camel_case_types, + dead_code, + non_snake_case, + non_upper_case_globals +)] + +use cppvtbl::{vtable, VtableRef}; +use real_c_string::real_c_string; +use std::ffi::c_void; +use std::os::raw::c_char; + +// Graphic api stubs +type VkDevice_T = (); +type VkInstance_T = (); +type VkQueue_T = (); +type VkPhysicalDevice_T = (); + +#[derive(Clone, Copy)] +pub union Union0 { + reserved: VREvent_Reserved_t, + controller: VREvent_Controller_t, + mouse: VREvent_Mouse_t, + scroll: VREvent_Scroll_t, + process: VREvent_Process_t, + notification: VREvent_Notification_t, + overlay: VREvent_Overlay_t, + status: VREvent_Status_t, + keyboard: VREvent_Keyboard_t, + ipd: VREvent_Ipd_t, + chaperone: VREvent_Chaperone_t, + performanceTest: VREvent_PerformanceTest_t, + touchPadMove: VREvent_TouchPadMove_t, + seatedZeroPoseReset: VREvent_SeatedZeroPoseReset_t, + screenshot: VREvent_Screenshot_t, + screenshotProgress: VREvent_ScreenshotProgress_t, + applicationLaunch: VREvent_ApplicationLaunch_t, + cameraSurface: VREvent_EditingCameraSurface_t, + messageOverlay: VREvent_MessageOverlay_t, + property: VREvent_Property_t, + hapticVibration: VREvent_HapticVibration_t, + webConsole: VREvent_WebConsole_t, + inputBinding: VREvent_InputBindingLoad_t, + actionManifest: VREvent_InputActionManifestLoad_t, + spatialAnchor: VREvent_SpatialAnchor_t, + progressUpdate: VREvent_ProgressUpdate_t, + showUi: VREvent_ShowUI_t, + showDevTools: VREvent_ShowDevTools_t, + hdcpError: VREvent_HDCPError_t, +} +pub type SpatialAnchorHandle_t = u32; +pub type glSharedTextureHandle_t = *mut c_void; +pub type glInt_t = i32; +pub type glUInt_t = u32; +pub type SharedTextureHandle_t = u64; +pub type DriverId_t = u32; +pub type TrackedDeviceIndex_t = u32; +pub type WebConsoleHandle_t = u64; +pub type PropertyContainerHandle_t = u64; +pub type PropertyTypeTag_t = u32; +pub type DriverHandle_t = PropertyContainerHandle_t; +pub type VRActionHandle_t = u64; +pub type VRActionSetHandle_t = u64; +pub type VRInputValueHandle_t = u64; +pub type VREvent_Data_t = Union0; +pub type VRComponentProperties = u32; +pub type VRControllerState_t = VRControllerState001_t; +pub type VROverlayHandle_t = u64; +pub type BoneIndex_t = i32; +pub type TrackedCameraHandle_t = u64; +pub type ScreenshotHandle_t = u32; +pub type VRInputComponentHandle_t = u64; +pub type IOBufferHandle_t = u64; +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[repr(i32)] +pub enum EVREye { + Eye_Left = 0, + Eye_Right = 1, +} +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[repr(i32)] +pub enum ETextureType { + TextureType_Invalid = -1, + TextureType_DirectX = 0, + TextureType_OpenGL = 1, + TextureType_Vulkan = 2, + TextureType_IOSurface = 3, + TextureType_DirectX12 = 4, + TextureType_DXGISharedHandle = 5, + TextureType_Metal = 6, +} +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[repr(i32)] +pub enum EColorSpace { + ColorSpace_Auto = 0, + ColorSpace_Gamma = 1, + ColorSpace_Linear = 2, +} +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[repr(i32)] +pub enum ETrackingResult { + TrackingResult_Uninitialized = 1, + TrackingResult_Calibrating_InProgress = 100, + TrackingResult_Calibrating_OutOfRange = 101, + TrackingResult_Running_OK = 200, + TrackingResult_Running_OutOfRange = 201, + TrackingResult_Fallback_RotationOnly = 300, +} +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[repr(i32)] +pub enum ETrackedDeviceClass { + TrackedDeviceClass_Invalid = 0, + TrackedDeviceClass_HMD = 1, + TrackedDeviceClass_Controller = 2, + TrackedDeviceClass_GenericTracker = 3, + TrackedDeviceClass_TrackingReference = 4, + TrackedDeviceClass_DisplayRedirect = 5, + TrackedDeviceClass_Max, +} +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[repr(i32)] +pub enum ETrackedControllerRole { + TrackedControllerRole_Invalid = 0, + TrackedControllerRole_LeftHand = 1, + TrackedControllerRole_RightHand = 2, + TrackedControllerRole_OptOut = 3, + TrackedControllerRole_Treadmill = 4, + TrackedControllerRole_Stylus = 5, +} +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[repr(i32)] +pub enum ETrackingUniverseOrigin { + TrackingUniverseSeated = 0, + TrackingUniverseStanding = 1, + TrackingUniverseRawAndUncalibrated = 2, +} +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[repr(i32)] +pub enum EAdditionalRadioFeatures { + AdditionalRadioFeatures_None = 0, + AdditionalRadioFeatures_HTCLinkBox = 1, + AdditionalRadioFeatures_InternalDongle = 2, + AdditionalRadioFeatures_ExternalDongle = 4, +} +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[repr(i32)] +pub enum ETrackedDeviceProperty { + Prop_Invalid = 0, + Prop_TrackingSystemName_String = 1000, + Prop_ModelNumber_String = 1001, + Prop_SerialNumber_String = 1002, + Prop_RenderModelName_String = 1003, + Prop_WillDriftInYaw_Bool = 1004, + Prop_ManufacturerName_String = 1005, + Prop_TrackingFirmwareVersion_String = 1006, + Prop_HardwareRevision_String = 1007, + Prop_AllWirelessDongleDescriptions_String = 1008, + Prop_ConnectedWirelessDongle_String = 1009, + Prop_DeviceIsWireless_Bool = 1010, + Prop_DeviceIsCharging_Bool = 1011, + Prop_DeviceBatteryPercentage_Float = 1012, + Prop_StatusDisplayTransform_Matrix34 = 1013, + Prop_Firmware_UpdateAvailable_Bool = 1014, + Prop_Firmware_ManualUpdate_Bool = 1015, + Prop_Firmware_ManualUpdateURL_String = 1016, + Prop_HardwareRevision_Uint64 = 1017, + Prop_FirmwareVersion_Uint64 = 1018, + Prop_FPGAVersion_Uint64 = 1019, + Prop_VRCVersion_Uint64 = 1020, + Prop_RadioVersion_Uint64 = 1021, + Prop_DongleVersion_Uint64 = 1022, + Prop_BlockServerShutdown_Bool = 1023, + Prop_CanUnifyCoordinateSystemWithHmd_Bool = 1024, + Prop_ContainsProximitySensor_Bool = 1025, + Prop_DeviceProvidesBatteryStatus_Bool = 1026, + Prop_DeviceCanPowerOff_Bool = 1027, + Prop_Firmware_ProgrammingTarget_String = 1028, + Prop_DeviceClass_Int32 = 1029, + Prop_HasCamera_Bool = 1030, + Prop_DriverVersion_String = 1031, + Prop_Firmware_ForceUpdateRequired_Bool = 1032, + Prop_ViveSystemButtonFixRequired_Bool = 1033, + Prop_ParentDriver_Uint64 = 1034, + Prop_ResourceRoot_String = 1035, + Prop_RegisteredDeviceType_String = 1036, + Prop_InputProfilePath_String = 1037, + Prop_NeverTracked_Bool = 1038, + Prop_NumCameras_Int32 = 1039, + Prop_CameraFrameLayout_Int32 = 1040, + Prop_CameraStreamFormat_Int32 = 1041, + Prop_AdditionalDeviceSettingsPath_String = 1042, + Prop_Identifiable_Bool = 1043, + Prop_BootloaderVersion_Uint64 = 1044, + Prop_AdditionalSystemReportData_String = 1045, + Prop_CompositeFirmwareVersion_String = 1046, + Prop_Firmware_RemindUpdate_Bool = 1047, + Prop_PeripheralApplicationVersion_Uint64 = 1048, + Prop_ManufacturerSerialNumber_String = 1049, + Prop_ComputedSerialNumber_String = 1050, + Prop_EstimatedDeviceFirstUseTime_Int32 = 1051, + Prop_ReportsTimeSinceVSync_Bool = 2000, + Prop_SecondsFromVsyncToPhotons_Float = 2001, + Prop_DisplayFrequency_Float = 2002, + Prop_UserIpdMeters_Float = 2003, + Prop_CurrentUniverseId_Uint64 = 2004, + Prop_PreviousUniverseId_Uint64 = 2005, + Prop_DisplayFirmwareVersion_Uint64 = 2006, + Prop_IsOnDesktop_Bool = 2007, + Prop_DisplayMCType_Int32 = 2008, + Prop_DisplayMCOffset_Float = 2009, + Prop_DisplayMCScale_Float = 2010, + Prop_EdidVendorID_Int32 = 2011, + Prop_DisplayMCImageLeft_String = 2012, + Prop_DisplayMCImageRight_String = 2013, + Prop_DisplayGCBlackClamp_Float = 2014, + Prop_EdidProductID_Int32 = 2015, + Prop_CameraToHeadTransform_Matrix34 = 2016, + Prop_DisplayGCType_Int32 = 2017, + Prop_DisplayGCOffset_Float = 2018, + Prop_DisplayGCScale_Float = 2019, + Prop_DisplayGCPrescale_Float = 2020, + Prop_DisplayGCImage_String = 2021, + Prop_LensCenterLeftU_Float = 2022, + Prop_LensCenterLeftV_Float = 2023, + Prop_LensCenterRightU_Float = 2024, + Prop_LensCenterRightV_Float = 2025, + Prop_UserHeadToEyeDepthMeters_Float = 2026, + Prop_CameraFirmwareVersion_Uint64 = 2027, + Prop_CameraFirmwareDescription_String = 2028, + Prop_DisplayFPGAVersion_Uint64 = 2029, + Prop_DisplayBootloaderVersion_Uint64 = 2030, + Prop_DisplayHardwareVersion_Uint64 = 2031, + Prop_AudioFirmwareVersion_Uint64 = 2032, + Prop_CameraCompatibilityMode_Int32 = 2033, + Prop_ScreenshotHorizontalFieldOfViewDegrees_Float = 2034, + Prop_ScreenshotVerticalFieldOfViewDegrees_Float = 2035, + Prop_DisplaySuppressed_Bool = 2036, + Prop_DisplayAllowNightMode_Bool = 2037, + Prop_DisplayMCImageWidth_Int32 = 2038, + Prop_DisplayMCImageHeight_Int32 = 2039, + Prop_DisplayMCImageNumChannels_Int32 = 2040, + Prop_DisplayMCImageData_Binary = 2041, + Prop_SecondsFromPhotonsToVblank_Float = 2042, + Prop_DriverDirectModeSendsVsyncEvents_Bool = 2043, + Prop_DisplayDebugMode_Bool = 2044, + Prop_GraphicsAdapterLuid_Uint64 = 2045, + Prop_DriverProvidedChaperonePath_String = 2048, + Prop_ExpectedTrackingReferenceCount_Int32 = 2049, + Prop_ExpectedControllerCount_Int32 = 2050, + Prop_NamedIconPathControllerLeftDeviceOff_String = 2051, + Prop_NamedIconPathControllerRightDeviceOff_String = 2052, + Prop_NamedIconPathTrackingReferenceDeviceOff_String = 2053, + Prop_DoNotApplyPrediction_Bool = 2054, + Prop_CameraToHeadTransforms_Matrix34_Array = 2055, + Prop_DistortionMeshResolution_Int32 = 2056, + Prop_DriverIsDrawingControllers_Bool = 2057, + Prop_DriverRequestsApplicationPause_Bool = 2058, + Prop_DriverRequestsReducedRendering_Bool = 2059, + Prop_MinimumIpdStepMeters_Float = 2060, + Prop_AudioBridgeFirmwareVersion_Uint64 = 2061, + Prop_ImageBridgeFirmwareVersion_Uint64 = 2062, + Prop_ImuToHeadTransform_Matrix34 = 2063, + Prop_ImuFactoryGyroBias_Vector3 = 2064, + Prop_ImuFactoryGyroScale_Vector3 = 2065, + Prop_ImuFactoryAccelerometerBias_Vector3 = 2066, + Prop_ImuFactoryAccelerometerScale_Vector3 = 2067, + Prop_ConfigurationIncludesLighthouse20Features_Bool = 2069, + Prop_AdditionalRadioFeatures_Uint64 = 2070, + Prop_CameraWhiteBalance_Vector4_Array = 2071, + Prop_CameraDistortionFunction_Int32_Array = 2072, + Prop_CameraDistortionCoefficients_Float_Array = 2073, + Prop_ExpectedControllerType_String = 2074, + Prop_HmdTrackingStyle_Int32 = 2075, + Prop_DriverProvidedChaperoneVisibility_Bool = 2076, + Prop_HmdColumnCorrectionSettingPrefix_String = 2077, + Prop_CameraSupportsCompatibilityModes_Bool = 2078, + Prop_SupportsRoomViewDepthProjection_Bool = 2079, + Prop_DisplayAvailableFrameRates_Float_Array = 2080, + Prop_DisplaySupportsMultipleFramerates_Bool = 2081, + Prop_DisplayColorMultLeft_Vector3 = 2082, + Prop_DisplayColorMultRight_Vector3 = 2083, + Prop_DisplaySupportsRuntimeFramerateChange_Bool = 2084, + Prop_DisplaySupportsAnalogGain_Bool = 2085, + Prop_DisplayMinAnalogGain_Float = 2086, + Prop_DisplayMaxAnalogGain_Float = 2087, + Prop_CameraExposureTime_Float = 2088, + Prop_CameraGlobalGain_Float = 2089, + Prop_DashboardScale_Float = 2091, + Prop_IpdUIRangeMinMeters_Float = 2100, + Prop_IpdUIRangeMaxMeters_Float = 2101, + Prop_Hmd_SupportsHDCP14LegacyCompat_Bool = 2102, + Prop_Hmd_SupportsMicMonitoring_Bool = 2103, + Prop_DriverRequestedMuraCorrectionMode_Int32 = 2200, + Prop_DriverRequestedMuraFeather_InnerLeft_Int32 = 2201, + Prop_DriverRequestedMuraFeather_InnerRight_Int32 = 2202, + Prop_DriverRequestedMuraFeather_InnerTop_Int32 = 2203, + Prop_DriverRequestedMuraFeather_InnerBottom_Int32 = 2204, + Prop_DriverRequestedMuraFeather_OuterLeft_Int32 = 2205, + Prop_DriverRequestedMuraFeather_OuterRight_Int32 = 2206, + Prop_DriverRequestedMuraFeather_OuterTop_Int32 = 2207, + Prop_DriverRequestedMuraFeather_OuterBottom_Int32 = 2208, + Prop_Audio_DefaultPlaybackDeviceId_String = 2300, + Prop_Audio_DefaultRecordingDeviceId_String = 2301, + Prop_Audio_DefaultPlaybackDeviceVolume_Float = 2302, + Prop_Audio_SupportsDualSpeakerAndJackOutput_Bool = 2303, + Prop_AttachedDeviceId_String = 3000, + Prop_SupportedButtons_Uint64 = 3001, + Prop_Axis0Type_Int32 = 3002, + Prop_Axis1Type_Int32 = 3003, + Prop_Axis2Type_Int32 = 3004, + Prop_Axis3Type_Int32 = 3005, + Prop_Axis4Type_Int32 = 3006, + Prop_ControllerRoleHint_Int32 = 3007, + Prop_FieldOfViewLeftDegrees_Float = 4000, + Prop_FieldOfViewRightDegrees_Float = 4001, + Prop_FieldOfViewTopDegrees_Float = 4002, + Prop_FieldOfViewBottomDegrees_Float = 4003, + Prop_TrackingRangeMinimumMeters_Float = 4004, + Prop_TrackingRangeMaximumMeters_Float = 4005, + Prop_ModeLabel_String = 4006, + Prop_CanWirelessIdentify_Bool = 4007, + Prop_Nonce_Int32 = 4008, + Prop_IconPathName_String = 5000, + Prop_NamedIconPathDeviceOff_String = 5001, + Prop_NamedIconPathDeviceSearching_String = 5002, + Prop_NamedIconPathDeviceSearchingAlert_String = 5003, + Prop_NamedIconPathDeviceReady_String = 5004, + Prop_NamedIconPathDeviceReadyAlert_String = 5005, + Prop_NamedIconPathDeviceNotReady_String = 5006, + Prop_NamedIconPathDeviceStandby_String = 5007, + Prop_NamedIconPathDeviceAlertLow_String = 5008, + Prop_NamedIconPathDeviceStandbyAlert_String = 5009, + Prop_DisplayHiddenArea_Binary_Start = 5100, + Prop_DisplayHiddenArea_Binary_End = 5150, + Prop_ParentContainer = 5151, + Prop_OverrideContainer_Uint64 = 5152, + Prop_UserConfigPath_String = 6000, + Prop_InstallPath_String = 6001, + Prop_HasDisplayComponent_Bool = 6002, + Prop_HasControllerComponent_Bool = 6003, + Prop_HasCameraComponent_Bool = 6004, + Prop_HasDriverDirectModeComponent_Bool = 6005, + Prop_HasVirtualDisplayComponent_Bool = 6006, + Prop_HasSpatialAnchorsSupport_Bool = 6007, + Prop_ControllerType_String = 7000, + Prop_ControllerHandSelectionPriority_Int32 = 7002, + Prop_VendorSpecific_Reserved_Start = 10000, + Prop_VendorSpecific_Reserved_End = 10999, + Prop_TrackedDeviceProperty_Max = 1000000, +} +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[repr(i32)] +pub enum ETrackedPropertyError { + TrackedProp_Success = 0, + TrackedProp_WrongDataType = 1, + TrackedProp_WrongDeviceClass = 2, + TrackedProp_BufferTooSmall = 3, + TrackedProp_UnknownProperty = 4, + TrackedProp_InvalidDevice = 5, + TrackedProp_CouldNotContactServer = 6, + TrackedProp_ValueNotProvidedByDevice = 7, + TrackedProp_StringExceedsMaximumLength = 8, + TrackedProp_NotYetAvailable = 9, + TrackedProp_PermissionDenied = 10, + TrackedProp_InvalidOperation = 11, + TrackedProp_CannotWriteToWildcards = 12, + TrackedProp_IPCReadFailure = 13, + TrackedProp_OutOfMemory = 14, + TrackedProp_InvalidContainer = 15, +} +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[repr(i32)] +pub enum EHmdTrackingStyle { + HmdTrackingStyle_Unknown = 0, + HmdTrackingStyle_Lighthouse = 1, + HmdTrackingStyle_OutsideInCameras = 2, + HmdTrackingStyle_InsideOutCameras = 3, +} +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[repr(i32)] +pub enum EVRSubmitFlags { + Submit_Default = 0, + Submit_LensDistortionAlreadyApplied = 1, + Submit_GlRenderBuffer = 2, + Submit_Reserved = 4, + Submit_TextureWithPose = 8, + Submit_TextureWithDepth = 16, + Submit_FrameDiscontinuty = 32, + Submit_VulkanTextureWithArrayData = 64, + Submit_GlArrayTexture = 128, + Submit_Reserved2 = 32768, +} +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[repr(i32)] +pub enum EVRState { + VRState_Undefined = -1, + VRState_Off = 0, + VRState_Searching = 1, + VRState_Searching_Alert = 2, + VRState_Ready = 3, + VRState_Ready_Alert = 4, + VRState_NotReady = 5, + VRState_Standby = 6, + VRState_Ready_Alert_Low = 7, +} +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[repr(i32)] +pub enum EVREventType { + VREvent_None = 0, + VREvent_TrackedDeviceActivated = 100, + VREvent_TrackedDeviceDeactivated = 101, + VREvent_TrackedDeviceUpdated = 102, + VREvent_TrackedDeviceUserInteractionStarted = 103, + VREvent_TrackedDeviceUserInteractionEnded = 104, + VREvent_IpdChanged = 105, + VREvent_EnterStandbyMode = 106, + VREvent_LeaveStandbyMode = 107, + VREvent_TrackedDeviceRoleChanged = 108, + VREvent_WatchdogWakeUpRequested = 109, + VREvent_LensDistortionChanged = 110, + VREvent_PropertyChanged = 111, + VREvent_WirelessDisconnect = 112, + VREvent_WirelessReconnect = 113, + VREvent_ButtonPress = 200, + VREvent_ButtonUnpress = 201, + VREvent_ButtonTouch = 202, + VREvent_ButtonUntouch = 203, + VREvent_Modal_Cancel = 257, + VREvent_MouseMove = 300, + VREvent_MouseButtonDown = 301, + VREvent_MouseButtonUp = 302, + VREvent_FocusEnter = 303, + VREvent_FocusLeave = 304, + VREvent_ScrollDiscrete = 305, + VREvent_TouchPadMove = 306, + VREvent_OverlayFocusChanged = 307, + VREvent_ReloadOverlays = 308, + VREvent_ScrollSmooth = 309, + VREvent_LockMousePosition = 310, + VREvent_UnlockMousePosition = 311, + VREvent_InputFocusCaptured = 400, + VREvent_InputFocusReleased = 401, + VREvent_SceneApplicationChanged = 404, + VREvent_SceneFocusChanged = 405, + VREvent_InputFocusChanged = 406, + VREvent_SceneApplicationUsingWrongGraphicsAdapter = 408, + VREvent_ActionBindingReloaded = 409, + VREvent_HideRenderModels = 410, + VREvent_ShowRenderModels = 411, + VREvent_SceneApplicationStateChanged = 412, + VREvent_ConsoleOpened = 420, + VREvent_ConsoleClosed = 421, + VREvent_OverlayShown = 500, + VREvent_OverlayHidden = 501, + VREvent_DashboardActivated = 502, + VREvent_DashboardDeactivated = 503, + VREvent_DashboardRequested = 505, + VREvent_ResetDashboard = 506, + VREvent_ImageLoaded = 508, + VREvent_ShowKeyboard = 509, + VREvent_HideKeyboard = 510, + VREvent_OverlayGamepadFocusGained = 511, + VREvent_OverlayGamepadFocusLost = 512, + VREvent_OverlaySharedTextureChanged = 513, + VREvent_ScreenshotTriggered = 516, + VREvent_ImageFailed = 517, + VREvent_DashboardOverlayCreated = 518, + VREvent_SwitchGamepadFocus = 519, + VREvent_RequestScreenshot = 520, + VREvent_ScreenshotTaken = 521, + VREvent_ScreenshotFailed = 522, + VREvent_SubmitScreenshotToDashboard = 523, + VREvent_ScreenshotProgressToDashboard = 524, + VREvent_PrimaryDashboardDeviceChanged = 525, + VREvent_RoomViewShown = 526, + VREvent_RoomViewHidden = 527, + VREvent_ShowUI = 528, + VREvent_ShowDevTools = 529, + VREvent_DesktopViewUpdating = 530, + VREvent_DesktopViewReady = 531, + VREvent_Notification_Shown = 600, + VREvent_Notification_Hidden = 601, + VREvent_Notification_BeginInteraction = 602, + VREvent_Notification_Destroyed = 603, + VREvent_Quit = 700, + VREvent_ProcessQuit = 701, + VREvent_QuitAcknowledged = 703, + VREvent_DriverRequestedQuit = 704, + VREvent_RestartRequested = 705, + VREvent_ChaperoneDataHasChanged = 800, + VREvent_ChaperoneUniverseHasChanged = 801, + VREvent_ChaperoneTempDataHasChanged = 802, + VREvent_ChaperoneSettingsHaveChanged = 803, + VREvent_SeatedZeroPoseReset = 804, + VREvent_ChaperoneFlushCache = 805, + VREvent_ChaperoneRoomSetupStarting = 806, + VREvent_ChaperoneRoomSetupFinished = 807, + VREvent_StandingZeroPoseReset = 808, + VREvent_AudioSettingsHaveChanged = 820, + VREvent_BackgroundSettingHasChanged = 850, + VREvent_CameraSettingsHaveChanged = 851, + VREvent_ReprojectionSettingHasChanged = 852, + VREvent_ModelSkinSettingsHaveChanged = 853, + VREvent_EnvironmentSettingsHaveChanged = 854, + VREvent_PowerSettingsHaveChanged = 855, + VREvent_EnableHomeAppSettingsHaveChanged = 856, + VREvent_SteamVRSectionSettingChanged = 857, + VREvent_LighthouseSectionSettingChanged = 858, + VREvent_NullSectionSettingChanged = 859, + VREvent_UserInterfaceSectionSettingChanged = 860, + VREvent_NotificationsSectionSettingChanged = 861, + VREvent_KeyboardSectionSettingChanged = 862, + VREvent_PerfSectionSettingChanged = 863, + VREvent_DashboardSectionSettingChanged = 864, + VREvent_WebInterfaceSectionSettingChanged = 865, + VREvent_TrackersSectionSettingChanged = 866, + VREvent_LastKnownSectionSettingChanged = 867, + VREvent_DismissedWarningsSectionSettingChanged = 868, + VREvent_GpuSpeedSectionSettingChanged = 869, + VREvent_WindowsMRSectionSettingChanged = 870, + VREvent_OtherSectionSettingChanged = 871, + VREvent_StatusUpdate = 900, + VREvent_WebInterface_InstallDriverCompleted = 950, + VREvent_MCImageUpdated = 1000, + VREvent_FirmwareUpdateStarted = 1100, + VREvent_FirmwareUpdateFinished = 1101, + VREvent_KeyboardClosed = 1200, + VREvent_KeyboardCharInput = 1201, + VREvent_KeyboardDone = 1202, + VREvent_ApplicationListUpdated = 1303, + VREvent_ApplicationMimeTypeLoad = 1304, + VREvent_ProcessConnected = 1306, + VREvent_ProcessDisconnected = 1307, + VREvent_Compositor_ChaperoneBoundsShown = 1410, + VREvent_Compositor_ChaperoneBoundsHidden = 1411, + VREvent_Compositor_DisplayDisconnected = 1412, + VREvent_Compositor_DisplayReconnected = 1413, + VREvent_Compositor_HDCPError = 1414, + VREvent_Compositor_ApplicationNotResponding = 1415, + VREvent_Compositor_ApplicationResumed = 1416, + VREvent_Compositor_OutOfVideoMemory = 1417, + VREvent_Compositor_DisplayModeNotSupported = 1418, + VREvent_Compositor_StageOverrideReady = 1419, + VREvent_TrackedCamera_StartVideoStream = 1500, + VREvent_TrackedCamera_StopVideoStream = 1501, + VREvent_TrackedCamera_PauseVideoStream = 1502, + VREvent_TrackedCamera_ResumeVideoStream = 1503, + VREvent_TrackedCamera_EditingSurface = 1550, + VREvent_PerformanceTest_EnableCapture = 1600, + VREvent_PerformanceTest_DisableCapture = 1601, + VREvent_PerformanceTest_FidelityLevel = 1602, + VREvent_MessageOverlay_Closed = 1650, + VREvent_MessageOverlayCloseRequested = 1651, + VREvent_Input_HapticVibration = 1700, + VREvent_Input_BindingLoadFailed = 1701, + VREvent_Input_BindingLoadSuccessful = 1702, + VREvent_Input_ActionManifestReloaded = 1703, + VREvent_Input_ActionManifestLoadFailed = 1704, + VREvent_Input_ProgressUpdate = 1705, + VREvent_Input_TrackerActivated = 1706, + VREvent_Input_BindingsUpdated = 1707, + VREvent_Input_BindingSubscriptionChanged = 1708, + VREvent_SpatialAnchors_PoseUpdated = 1800, + VREvent_SpatialAnchors_DescriptorUpdated = 1801, + VREvent_SpatialAnchors_RequestPoseUpdate = 1802, + VREvent_SpatialAnchors_RequestDescriptorUpdate = 1803, + VREvent_SystemReport_Started = 1900, + VREvent_Monitor_ShowHeadsetView = 2000, + VREvent_Monitor_HideHeadsetView = 2001, + VREvent_VendorSpecific_Reserved_Start = 10000, + VREvent_VendorSpecific_Reserved_End = 19999, +} +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[repr(i32)] +pub enum EDeviceActivityLevel { + k_EDeviceActivityLevel_Unknown = -1, + k_EDeviceActivityLevel_Idle = 0, + k_EDeviceActivityLevel_UserInteraction = 1, + k_EDeviceActivityLevel_UserInteraction_Timeout = 2, + k_EDeviceActivityLevel_Standby = 3, + k_EDeviceActivityLevel_Idle_Timeout = 4, +} +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[repr(i32)] +pub enum EVRButtonId { + k_EButton_System = 0, + k_EButton_ApplicationMenu = 1, + k_EButton_Grip = 2, + k_EButton_DPad_Left = 3, + k_EButton_DPad_Up = 4, + k_EButton_DPad_Right = 5, + k_EButton_DPad_Down = 6, + k_EButton_A = 7, + k_EButton_ProximitySensor = 31, + k_EButton_Axis0 = 32, + k_EButton_Axis1 = 33, + k_EButton_Axis2 = 34, + k_EButton_Axis3 = 35, + k_EButton_Axis4 = 36, + k_EButton_Max = 64, +} +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[repr(i32)] +pub enum EVRMouseButton { + VRMouseButton_Left = 1, + VRMouseButton_Right = 2, + VRMouseButton_Middle = 4, +} +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[repr(i32)] +pub enum EShowUIType { + ShowUI_ControllerBinding = 0, + ShowUI_ManageTrackers = 1, + ShowUI_Pairing = 3, + ShowUI_Settings = 4, + ShowUI_DebugCommands = 5, + ShowUI_FullControllerBinding = 6, + ShowUI_ManageDrivers = 7, +} +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[repr(i32)] +pub enum EHDCPError { + HDCPError_None = 0, + HDCPError_LinkLost = 1, + HDCPError_Tampered = 2, + HDCPError_DeviceRevoked = 3, + HDCPError_Unknown = 4, +} +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[repr(i32)] +pub enum EVRComponentProperty { + VRComponentProperty_IsStatic = 1, + VRComponentProperty_IsVisible = 2, + VRComponentProperty_IsTouched = 4, + VRComponentProperty_IsPressed = 8, + VRComponentProperty_IsScrolled = 16, + VRComponentProperty_IsHighlighted = 32, +} +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[repr(i32)] +pub enum EVRInputError { + VRInputError_None = 0, + VRInputError_NameNotFound = 1, + VRInputError_WrongType = 2, + VRInputError_InvalidHandle = 3, + VRInputError_InvalidParam = 4, + VRInputError_NoSteam = 5, + VRInputError_MaxCapacityReached = 6, + VRInputError_IPCError = 7, + VRInputError_NoActiveActionSet = 8, + VRInputError_InvalidDevice = 9, + VRInputError_InvalidSkeleton = 10, + VRInputError_InvalidBoneCount = 11, + VRInputError_InvalidCompressedData = 12, + VRInputError_NoData = 13, + VRInputError_BufferTooSmall = 14, + VRInputError_MismatchedActionManifest = 15, + VRInputError_MissingSkeletonData = 16, + VRInputError_InvalidBoneIndex = 17, + VRInputError_InvalidPriority = 18, + VRInputError_PermissionDenied = 19, + VRInputError_InvalidRenderModel = 20, +} +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[repr(i32)] +pub enum EVRSpatialAnchorError { + VRSpatialAnchorError_Success = 0, + VRSpatialAnchorError_Internal = 1, + VRSpatialAnchorError_UnknownHandle = 2, + VRSpatialAnchorError_ArrayTooSmall = 3, + VRSpatialAnchorError_InvalidDescriptorChar = 4, + VRSpatialAnchorError_NotYetAvailable = 5, + VRSpatialAnchorError_NotAvailableInThisUniverse = 6, + VRSpatialAnchorError_PermanentlyUnavailable = 7, + VRSpatialAnchorError_WrongDriver = 8, + VRSpatialAnchorError_DescriptorTooLong = 9, + VRSpatialAnchorError_Unknown = 10, + VRSpatialAnchorError_NoRoomCalibration = 11, + VRSpatialAnchorError_InvalidArgument = 12, + VRSpatialAnchorError_UnknownDriver = 13, +} +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[repr(i32)] +pub enum EHiddenAreaMeshType { + k_eHiddenAreaMesh_Standard = 0, + k_eHiddenAreaMesh_Inverse = 1, + k_eHiddenAreaMesh_LineLoop = 2, + k_eHiddenAreaMesh_Max = 3, +} +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[repr(i32)] +pub enum EVRControllerAxisType { + k_eControllerAxis_None = 0, + k_eControllerAxis_TrackPad = 1, + k_eControllerAxis_Joystick = 2, + k_eControllerAxis_Trigger = 3, +} +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[repr(i32)] +pub enum EVRControllerEventOutputType { + ControllerEventOutput_OSEvents = 0, + ControllerEventOutput_VREvents = 1, +} +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[repr(i32)] +pub enum ECollisionBoundsStyle { + COLLISION_BOUNDS_STYLE_BEGINNER = 0, + COLLISION_BOUNDS_STYLE_INTERMEDIATE, + COLLISION_BOUNDS_STYLE_SQUARES, + COLLISION_BOUNDS_STYLE_ADVANCED, + COLLISION_BOUNDS_STYLE_NONE, + COLLISION_BOUNDS_STYLE_COUNT, +} +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[repr(i32)] +pub enum EVROverlayError { + VROverlayError_None = 0, + VROverlayError_UnknownOverlay = 10, + VROverlayError_InvalidHandle = 11, + VROverlayError_PermissionDenied = 12, + VROverlayError_OverlayLimitExceeded = 13, + VROverlayError_WrongVisibilityType = 14, + VROverlayError_KeyTooLong = 15, + VROverlayError_NameTooLong = 16, + VROverlayError_KeyInUse = 17, + VROverlayError_WrongTransformType = 18, + VROverlayError_InvalidTrackedDevice = 19, + VROverlayError_InvalidParameter = 20, + VROverlayError_ThumbnailCantBeDestroyed = 21, + VROverlayError_ArrayTooSmall = 22, + VROverlayError_RequestFailed = 23, + VROverlayError_InvalidTexture = 24, + VROverlayError_UnableToLoadFile = 25, + VROverlayError_KeyboardAlreadyInUse = 26, + VROverlayError_NoNeighbor = 27, + VROverlayError_TooManyMaskPrimitives = 29, + VROverlayError_BadMaskPrimitive = 30, + VROverlayError_TextureAlreadyLocked = 31, + VROverlayError_TextureLockCapacityReached = 32, + VROverlayError_TextureNotLocked = 33, +} +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[repr(i32)] +pub enum EVRApplicationType { + VRApplication_Other = 0, + VRApplication_Scene = 1, + VRApplication_Overlay = 2, + VRApplication_Background = 3, + VRApplication_Utility = 4, + VRApplication_VRMonitor = 5, + VRApplication_SteamWatchdog = 6, + VRApplication_Bootstrapper = 7, + VRApplication_WebHelper = 8, + VRApplication_OpenXRInstance = 9, + VRApplication_OpenXRScene = 10, + VRApplication_OpenXROverlay = 11, + VRApplication_Prism = 12, + VRApplication_Max, +} +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[repr(i32)] +pub enum EVRFirmwareError { + VRFirmwareError_None = 0, + VRFirmwareError_Success = 1, + VRFirmwareError_Fail = 2, +} +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[repr(i32)] +pub enum EVRNotificationError { + VRNotificationError_OK = 0, + VRNotificationError_InvalidNotificationId = 100, + VRNotificationError_NotificationQueueFull = 101, + VRNotificationError_InvalidOverlayHandle = 102, + VRNotificationError_SystemWithUserValueAlreadyExists = 103, +} +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[repr(i32)] +pub enum EVRSkeletalMotionRange { + VRSkeletalMotionRange_WithController = 0, + VRSkeletalMotionRange_WithoutController = 1, +} +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[repr(i32)] +pub enum EVRSkeletalTrackingLevel { + VRSkeletalTracking_Estimated = 0, + VRSkeletalTracking_Partial = 1, + VRSkeletalTracking_Full = 2, +} +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[repr(i32)] +pub enum EVRInitError { + VRInitError_None = 0, + VRInitError_Unknown = 1, + VRInitError_Init_InstallationNotFound = 100, + VRInitError_Init_InstallationCorrupt = 101, + VRInitError_Init_VRClientDLLNotFound = 102, + VRInitError_Init_FileNotFound = 103, + VRInitError_Init_FactoryNotFound = 104, + VRInitError_Init_InterfaceNotFound = 105, + VRInitError_Init_InvalidInterface = 106, + VRInitError_Init_UserConfigDirectoryInvalid = 107, + VRInitError_Init_HmdNotFound = 108, + VRInitError_Init_NotInitialized = 109, + VRInitError_Init_PathRegistryNotFound = 110, + VRInitError_Init_NoConfigPath = 111, + VRInitError_Init_NoLogPath = 112, + VRInitError_Init_PathRegistryNotWritable = 113, + VRInitError_Init_AppInfoInitFailed = 114, + VRInitError_Init_Retry = 115, + VRInitError_Init_InitCanceledByUser = 116, + VRInitError_Init_AnotherAppLaunching = 117, + VRInitError_Init_SettingsInitFailed = 118, + VRInitError_Init_ShuttingDown = 119, + VRInitError_Init_TooManyObjects = 120, + VRInitError_Init_NoServerForBackgroundApp = 121, + VRInitError_Init_NotSupportedWithCompositor = 122, + VRInitError_Init_NotAvailableToUtilityApps = 123, + VRInitError_Init_Internal = 124, + VRInitError_Init_HmdDriverIdIsNone = 125, + VRInitError_Init_HmdNotFoundPresenceFailed = 126, + VRInitError_Init_VRMonitorNotFound = 127, + VRInitError_Init_VRMonitorStartupFailed = 128, + VRInitError_Init_LowPowerWatchdogNotSupported = 129, + VRInitError_Init_InvalidApplicationType = 130, + VRInitError_Init_NotAvailableToWatchdogApps = 131, + VRInitError_Init_WatchdogDisabledInSettings = 132, + VRInitError_Init_VRDashboardNotFound = 133, + VRInitError_Init_VRDashboardStartupFailed = 134, + VRInitError_Init_VRHomeNotFound = 135, + VRInitError_Init_VRHomeStartupFailed = 136, + VRInitError_Init_RebootingBusy = 137, + VRInitError_Init_FirmwareUpdateBusy = 138, + VRInitError_Init_FirmwareRecoveryBusy = 139, + VRInitError_Init_USBServiceBusy = 140, + VRInitError_Init_VRWebHelperStartupFailed = 141, + VRInitError_Init_TrackerManagerInitFailed = 142, + VRInitError_Init_AlreadyRunning = 143, + VRInitError_Init_FailedForVrMonitor = 144, + VRInitError_Init_PropertyManagerInitFailed = 145, + VRInitError_Init_WebServerFailed = 146, + VRInitError_Init_IllegalTypeTransition = 147, + VRInitError_Init_MismatchedRuntimes = 148, + VRInitError_Init_InvalidProcessId = 149, + VRInitError_Init_VRServiceStartupFailed = 150, + VRInitError_Init_PrismNeedsNewDrivers = 151, + VRInitError_Init_PrismStartupTimedOut = 152, + VRInitError_Init_CouldNotStartPrism = 153, + VRInitError_Init_CreateDriverDirectDeviceFailed = 154, + VRInitError_Init_PrismExitedUnexpectedly = 155, + VRInitError_Driver_Failed = 200, + VRInitError_Driver_Unknown = 201, + VRInitError_Driver_HmdUnknown = 202, + VRInitError_Driver_NotLoaded = 203, + VRInitError_Driver_RuntimeOutOfDate = 204, + VRInitError_Driver_HmdInUse = 205, + VRInitError_Driver_NotCalibrated = 206, + VRInitError_Driver_CalibrationInvalid = 207, + VRInitError_Driver_HmdDisplayNotFound = 208, + VRInitError_Driver_TrackedDeviceInterfaceUnknown = 209, + VRInitError_Driver_HmdDriverIdOutOfBounds = 211, + VRInitError_Driver_HmdDisplayMirrored = 212, + VRInitError_Driver_HmdDisplayNotFoundLaptop = 213, + VRInitError_IPC_ServerInitFailed = 300, + VRInitError_IPC_ConnectFailed = 301, + VRInitError_IPC_SharedStateInitFailed = 302, + VRInitError_IPC_CompositorInitFailed = 303, + VRInitError_IPC_MutexInitFailed = 304, + VRInitError_IPC_Failed = 305, + VRInitError_IPC_CompositorConnectFailed = 306, + VRInitError_IPC_CompositorInvalidConnectResponse = 307, + VRInitError_IPC_ConnectFailedAfterMultipleAttempts = 308, + VRInitError_IPC_ConnectFailedAfterTargetExited = 309, + VRInitError_IPC_NamespaceUnavailable = 310, + VRInitError_Compositor_Failed = 400, + VRInitError_Compositor_D3D11HardwareRequired = 401, + VRInitError_Compositor_FirmwareRequiresUpdate = 402, + VRInitError_Compositor_OverlayInitFailed = 403, + VRInitError_Compositor_ScreenshotsInitFailed = 404, + VRInitError_Compositor_UnableToCreateDevice = 405, + VRInitError_Compositor_SharedStateIsNull = 406, + VRInitError_Compositor_NotificationManagerIsNull = 407, + VRInitError_Compositor_ResourceManagerClientIsNull = 408, + VRInitError_Compositor_MessageOverlaySharedStateInitFailure = 409, + VRInitError_Compositor_PropertiesInterfaceIsNull = 410, + VRInitError_Compositor_CreateFullscreenWindowFailed = 411, + VRInitError_Compositor_SettingsInterfaceIsNull = 412, + VRInitError_Compositor_FailedToShowWindow = 413, + VRInitError_Compositor_DistortInterfaceIsNull = 414, + VRInitError_Compositor_DisplayFrequencyFailure = 415, + VRInitError_Compositor_RendererInitializationFailed = 416, + VRInitError_Compositor_DXGIFactoryInterfaceIsNull = 417, + VRInitError_Compositor_DXGIFactoryCreateFailed = 418, + VRInitError_Compositor_DXGIFactoryQueryFailed = 419, + VRInitError_Compositor_InvalidAdapterDesktop = 420, + VRInitError_Compositor_InvalidHmdAttachment = 421, + VRInitError_Compositor_InvalidOutputDesktop = 422, + VRInitError_Compositor_InvalidDeviceProvided = 423, + VRInitError_Compositor_D3D11RendererInitializationFailed = 424, + VRInitError_Compositor_FailedToFindDisplayMode = 425, + VRInitError_Compositor_FailedToCreateSwapChain = 426, + VRInitError_Compositor_FailedToGetBackBuffer = 427, + VRInitError_Compositor_FailedToCreateRenderTarget = 428, + VRInitError_Compositor_FailedToCreateDXGI2SwapChain = 429, + VRInitError_Compositor_FailedtoGetDXGI2BackBuffer = 430, + VRInitError_Compositor_FailedToCreateDXGI2RenderTarget = 431, + VRInitError_Compositor_FailedToGetDXGIDeviceInterface = 432, + VRInitError_Compositor_SelectDisplayMode = 433, + VRInitError_Compositor_FailedToCreateNvAPIRenderTargets = 434, + VRInitError_Compositor_NvAPISetDisplayMode = 435, + VRInitError_Compositor_FailedToCreateDirectModeDisplay = 436, + VRInitError_Compositor_InvalidHmdPropertyContainer = 437, + VRInitError_Compositor_UpdateDisplayFrequency = 438, + VRInitError_Compositor_CreateRasterizerState = 439, + VRInitError_Compositor_CreateWireframeRasterizerState = 440, + VRInitError_Compositor_CreateSamplerState = 441, + VRInitError_Compositor_CreateClampToBorderSamplerState = 442, + VRInitError_Compositor_CreateAnisoSamplerState = 443, + VRInitError_Compositor_CreateOverlaySamplerState = 444, + VRInitError_Compositor_CreatePanoramaSamplerState = 445, + VRInitError_Compositor_CreateFontSamplerState = 446, + VRInitError_Compositor_CreateNoBlendState = 447, + VRInitError_Compositor_CreateBlendState = 448, + VRInitError_Compositor_CreateAlphaBlendState = 449, + VRInitError_Compositor_CreateBlendStateMaskR = 450, + VRInitError_Compositor_CreateBlendStateMaskG = 451, + VRInitError_Compositor_CreateBlendStateMaskB = 452, + VRInitError_Compositor_CreateDepthStencilState = 453, + VRInitError_Compositor_CreateDepthStencilStateNoWrite = 454, + VRInitError_Compositor_CreateDepthStencilStateNoDepth = 455, + VRInitError_Compositor_CreateFlushTexture = 456, + VRInitError_Compositor_CreateDistortionSurfaces = 457, + VRInitError_Compositor_CreateConstantBuffer = 458, + VRInitError_Compositor_CreateHmdPoseConstantBuffer = 459, + VRInitError_Compositor_CreateHmdPoseStagingConstantBuffer = 460, + VRInitError_Compositor_CreateSharedFrameInfoConstantBuffer = 461, + VRInitError_Compositor_CreateOverlayConstantBuffer = 462, + VRInitError_Compositor_CreateSceneTextureIndexConstantBuffer = 463, + VRInitError_Compositor_CreateReadableSceneTextureIndexConstantBuffer = 464, + VRInitError_Compositor_CreateLayerGraphicsTextureIndexConstantBuffer = 465, + VRInitError_Compositor_CreateLayerComputeTextureIndexConstantBuffer = 466, + VRInitError_Compositor_CreateLayerComputeSceneTextureIndexConstantBuffer = 467, + VRInitError_Compositor_CreateComputeHmdPoseConstantBuffer = 468, + VRInitError_Compositor_CreateGeomConstantBuffer = 469, + VRInitError_Compositor_CreatePanelMaskConstantBuffer = 470, + VRInitError_Compositor_CreatePixelSimUBO = 471, + VRInitError_Compositor_CreateMSAARenderTextures = 472, + VRInitError_Compositor_CreateResolveRenderTextures = 473, + VRInitError_Compositor_CreateComputeResolveRenderTextures = 474, + VRInitError_Compositor_CreateDriverDirectModeResolveTextures = 475, + VRInitError_Compositor_OpenDriverDirectModeResolveTextures = 476, + VRInitError_Compositor_CreateFallbackSyncTexture = 477, + VRInitError_Compositor_ShareFallbackSyncTexture = 478, + VRInitError_Compositor_CreateOverlayIndexBuffer = 479, + VRInitError_Compositor_CreateOverlayVertexBuffer = 480, + VRInitError_Compositor_CreateTextVertexBuffer = 481, + VRInitError_Compositor_CreateTextIndexBuffer = 482, + VRInitError_Compositor_CreateMirrorTextures = 483, + VRInitError_Compositor_CreateLastFrameRenderTexture = 484, + VRInitError_Compositor_CreateMirrorOverlay = 485, + VRInitError_Compositor_FailedToCreateVirtualDisplayBackbuffer = 486, + VRInitError_Compositor_DisplayModeNotSupported = 487, + VRInitError_Compositor_CreateOverlayInvalidCall = 488, + VRInitError_Compositor_CreateOverlayAlreadyInitialized = 489, + VRInitError_Compositor_FailedToCreateMailbox = 490, + VRInitError_Compositor_WindowInterfaceIsNull = 491, + VRInitError_Compositor_SystemLayerCreateInstance = 492, + VRInitError_Compositor_SystemLayerCreateSession = 493, + VRInitError_VendorSpecific_UnableToConnectToOculusRuntime = 1000, + VRInitError_VendorSpecific_WindowsNotInDevMode = 1001, + VRInitError_VendorSpecific_HmdFound_CantOpenDevice = 1101, + VRInitError_VendorSpecific_HmdFound_UnableToRequestConfigStart = 1102, + VRInitError_VendorSpecific_HmdFound_NoStoredConfig = 1103, + VRInitError_VendorSpecific_HmdFound_ConfigTooBig = 1104, + VRInitError_VendorSpecific_HmdFound_ConfigTooSmall = 1105, + VRInitError_VendorSpecific_HmdFound_UnableToInitZLib = 1106, + VRInitError_VendorSpecific_HmdFound_CantReadFirmwareVersion = 1107, + VRInitError_VendorSpecific_HmdFound_UnableToSendUserDataStart = 1108, + VRInitError_VendorSpecific_HmdFound_UnableToGetUserDataStart = 1109, + VRInitError_VendorSpecific_HmdFound_UnableToGetUserDataNext = 1110, + VRInitError_VendorSpecific_HmdFound_UserDataAddressRange = 1111, + VRInitError_VendorSpecific_HmdFound_UserDataError = 1112, + VRInitError_VendorSpecific_HmdFound_ConfigFailedSanityCheck = 1113, + VRInitError_VendorSpecific_OculusRuntimeBadInstall = 1114, + VRInitError_Steam_SteamInstallationNotFound = 2000, + VRInitError_LastError, +} +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[repr(i32)] +pub enum EVRScreenshotType { + VRScreenshotType_None = 0, + VRScreenshotType_Mono = 1, + VRScreenshotType_Stereo = 2, + VRScreenshotType_Cubemap = 3, + VRScreenshotType_MonoPanorama = 4, + VRScreenshotType_StereoPanorama = 5, +} +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[repr(i32)] +pub enum EVRScreenshotPropertyFilenames { + VRScreenshotPropertyFilenames_Preview = 0, + VRScreenshotPropertyFilenames_VR = 1, +} +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[repr(i32)] +pub enum EVRTrackedCameraError { + VRTrackedCameraError_None = 0, + VRTrackedCameraError_OperationFailed = 100, + VRTrackedCameraError_InvalidHandle = 101, + VRTrackedCameraError_InvalidFrameHeaderVersion = 102, + VRTrackedCameraError_OutOfHandles = 103, + VRTrackedCameraError_IPCFailure = 104, + VRTrackedCameraError_NotSupportedForThisDevice = 105, + VRTrackedCameraError_SharedMemoryFailure = 106, + VRTrackedCameraError_FrameBufferingFailure = 107, + VRTrackedCameraError_StreamSetupFailure = 108, + VRTrackedCameraError_InvalidGLTextureId = 109, + VRTrackedCameraError_InvalidSharedTextureHandle = 110, + VRTrackedCameraError_FailedToGetGLTextureId = 111, + VRTrackedCameraError_SharedTextureFailure = 112, + VRTrackedCameraError_NoFrameAvailable = 113, + VRTrackedCameraError_InvalidArgument = 114, + VRTrackedCameraError_InvalidFrameBufferSize = 115, +} +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[repr(i32)] +pub enum EVRTrackedCameraFrameLayout { + EVRTrackedCameraFrameLayout_Mono = 1, + EVRTrackedCameraFrameLayout_Stereo = 2, + EVRTrackedCameraFrameLayout_VerticalLayout = 16, + EVRTrackedCameraFrameLayout_HorizontalLayout = 32, +} +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[repr(i32)] +pub enum EVRTrackedCameraFrameType { + VRTrackedCameraFrameType_Distorted = 0, + VRTrackedCameraFrameType_Undistorted, + VRTrackedCameraFrameType_MaximumUndistorted, + MAX_CAMERA_FRAME_TYPES, +} +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[repr(i32)] +pub enum EVRDistortionFunctionType { + VRDistortionFunctionType_None, + VRDistortionFunctionType_FTheta, + VRDistortionFunctionType_Extended_FTheta, + MAX_DISTORTION_FUNCTION_TYPES, +} +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[repr(i32)] +pub enum EVSync { + VSync_None, + VSync_WaitRender, + VSync_NoWaitRender, +} +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[repr(i32)] +pub enum EVRMuraCorrectionMode { + EVRMuraCorrectionMode_Default = 0, + EVRMuraCorrectionMode_NoCorrection, +} +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[repr(i32)] +pub enum Imu_OffScaleFlags { + OffScale_AccelX = 1, + OffScale_AccelY = 2, + OffScale_AccelZ = 4, + OffScale_GyroX = 8, + OffScale_GyroY = 16, + OffScale_GyroZ = 32, +} +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[repr(i32)] +pub enum ECameraVideoStreamFormat { + CVS_FORMAT_UNKNOWN = 0, + CVS_FORMAT_RAW10 = 1, + CVS_FORMAT_NV12 = 2, + CVS_FORMAT_RGB24 = 3, + CVS_FORMAT_NV12_2 = 4, + CVS_FORMAT_YUYV16 = 5, + CVS_FORMAT_BAYER16BG = 6, + CVS_FORMAT_MJPEG = 7, + CVS_MAX_FORMATS, +} +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[repr(i32)] +pub enum ECameraCompatibilityMode { + CAMERA_COMPAT_MODE_BULK_DEFAULT = 0, + CAMERA_COMPAT_MODE_BULK_64K_DMA = 1, + CAMERA_COMPAT_MODE_BULK_16K_DMA = 2, + CAMERA_COMPAT_MODE_BULK_8K_DMA = 3, + CAMERA_COMPAT_MODE_ISO_52FPS = 4, + CAMERA_COMPAT_MODE_ISO_50FPS = 5, + CAMERA_COMPAT_MODE_ISO_48FPS = 6, + CAMERA_COMPAT_MODE_ISO_46FPS = 7, + CAMERA_COMPAT_MODE_ISO_44FPS = 8, + CAMERA_COMPAT_MODE_ISO_42FPS = 9, + CAMERA_COMPAT_MODE_ISO_40FPS = 10, + CAMERA_COMPAT_MODE_ISO_35FPS = 11, + CAMERA_COMPAT_MODE_ISO_30FPS = 12, + CAMERA_COMPAT_MODE_ISO_15FPS = 13, + MAX_CAMERA_COMPAT_MODES, +} +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[repr(i32)] +pub enum ECameraRoomViewStyle { + CAMERA_ROOMVIEW_STYLE_DEFAULT = 0, + CAMERA_ROOMVIEW_STYLE_EDGE_A = 1, + CAMERA_ROOMVIEW_STYLE_EDGE_B = 2, + CAMERA_ROOMVIEW_STYLE_VIDEO_TRANSLUSCENT = 3, + CAMERA_ROOMVIEW_STYLE_VIDEO_OPAQUE = 4, + CAMERA_ROOMVIEW_STYLE_COUNT = 5, +} +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[repr(i32)] +pub enum EVRSettingsError { + VRSettingsError_None = 0, + VRSettingsError_IPCFailed = 1, + VRSettingsError_WriteFailed = 2, + VRSettingsError_ReadFailed = 3, + VRSettingsError_JsonParseFailed = 4, + VRSettingsError_UnsetSettingHasNoDefault = 5, +} +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[repr(i32)] +pub enum VRSwapTextureFlag { + VRSwapTextureFlag_Shared_NTHandle = 1, +} +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[repr(i32)] +pub enum EPropertyWriteType { + PropertyWrite_Set = 0, + PropertyWrite_Erase = 1, + PropertyWrite_SetError = 2, +} +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[repr(i32)] +pub enum EVRScalarType { + VRScalarType_Absolute = 0, + VRScalarType_Relative = 1, +} +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[repr(i32)] +pub enum EVRScalarUnits { + VRScalarUnits_NormalizedOneSided = 0, + VRScalarUnits_NormalizedTwoSided = 1, +} +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[repr(i32)] +pub enum EIOBufferError { + IOBuffer_Success = 0, + IOBuffer_OperationFailed = 100, + IOBuffer_InvalidHandle = 101, + IOBuffer_InvalidArgument = 102, + IOBuffer_PathExists = 103, + IOBuffer_PathDoesNotExist = 104, + IOBuffer_Permission = 105, +} +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[repr(i32)] +pub enum EIOBufferMode { + IOBufferMode_Read = 1, + IOBufferMode_Write = 2, + IOBufferMode_Create = 512, +} +pub const k_nSteamVRVersionMajor: u32 = 1; +pub const k_nSteamVRVersionMinor: u32 = 16; +pub const k_nSteamVRVersionBuild: u32 = 8; +pub const k_nDriverNone: u32 = 4294967295; +pub const k_unMaxDriverDebugResponseSize: u32 = 32768; +pub const k_unTrackedDeviceIndex_Hmd: u32 = 0; +pub const k_unMaxTrackedDeviceCount: u32 = 64; +pub const k_unTrackedDeviceIndexOther: u32 = 4294967294; +pub const k_unTrackedDeviceIndexInvalid: u32 = 4294967295; +pub const k_ulInvalidPropertyContainer: PropertyContainerHandle_t = 0; +pub const k_unInvalidPropertyTag: PropertyTypeTag_t = 0; +pub const k_ulInvalidDriverHandle: PropertyContainerHandle_t = 0; +pub const k_unFloatPropertyTag: PropertyTypeTag_t = 1; +pub const k_unInt32PropertyTag: PropertyTypeTag_t = 2; +pub const k_unUint64PropertyTag: PropertyTypeTag_t = 3; +pub const k_unBoolPropertyTag: PropertyTypeTag_t = 4; +pub const k_unStringPropertyTag: PropertyTypeTag_t = 5; +pub const k_unErrorPropertyTag: PropertyTypeTag_t = 6; +pub const k_unDoublePropertyTag: PropertyTypeTag_t = 7; +pub const k_unHmdMatrix34PropertyTag: PropertyTypeTag_t = 20; +pub const k_unHmdMatrix44PropertyTag: PropertyTypeTag_t = 21; +pub const k_unHmdVector3PropertyTag: PropertyTypeTag_t = 22; +pub const k_unHmdVector4PropertyTag: PropertyTypeTag_t = 23; +pub const k_unHmdVector2PropertyTag: PropertyTypeTag_t = 24; +pub const k_unHmdQuadPropertyTag: PropertyTypeTag_t = 25; +pub const k_unHiddenAreaPropertyTag: PropertyTypeTag_t = 30; +pub const k_unPathHandleInfoTag: PropertyTypeTag_t = 31; +pub const k_unActionPropertyTag: PropertyTypeTag_t = 32; +pub const k_unInputValuePropertyTag: PropertyTypeTag_t = 33; +pub const k_unWildcardPropertyTag: PropertyTypeTag_t = 34; +pub const k_unHapticVibrationPropertyTag: PropertyTypeTag_t = 35; +pub const k_unSkeletonPropertyTag: PropertyTypeTag_t = 36; +pub const k_unSpatialAnchorPosePropertyTag: PropertyTypeTag_t = 40; +pub const k_unJsonPropertyTag: PropertyTypeTag_t = 41; +pub const k_unActiveActionSetPropertyTag: PropertyTypeTag_t = 42; +pub const k_unOpenVRInternalReserved_Start: PropertyTypeTag_t = 1000; +pub const k_unOpenVRInternalReserved_End: PropertyTypeTag_t = 10000; +pub const k_unMaxPropertyStringSize: u32 = 32 * 1024; +pub const k_ulInvalidActionHandle: VRActionHandle_t = 0; +pub const k_ulInvalidActionSetHandle: VRActionSetHandle_t = 0; +pub const k_ulInvalidInputValueHandle: VRInputValueHandle_t = 0; +pub const k_unControllerStateAxisCount: u32 = 5; +pub const k_ulOverlayHandleInvalid: VROverlayHandle_t = 0; +pub const k_unInvalidBoneIndex: BoneIndex_t = -1; +pub const k_unMaxDistortionFunctionParameters: u32 = 8; +pub const k_unScreenshotHandleInvalid: u32 = 0; +pub const VRCompositor_ReprojectionReason_Cpu: u32 = 1; +pub const VRCompositor_ReprojectionReason_Gpu: u32 = 2; +pub const VRCompositor_ReprojectionAsync: u32 = 4; +pub const VRCompositor_ReprojectionMotion: u32 = 8; +pub const VRCompositor_PredictionMask: u32 = 240; +pub const VRCompositor_ThrottleMask: u32 = 3840; +pub const VRCompositor_ReprojectionMotion_Enabled: u32 = 256; +pub const VRCompositor_ReprojectionMotion_ForcedOn: u32 = 512; +pub const VRCompositor_ReprojectionMotion_AppThrottled: u32 = 1024; +pub const k_unMaxCameras: u32 = 4; +pub const k_unMaxCameraFrameSharedHandles: u32 = 4; +pub const k_unMaxSettingsKeyLength: u32 = 128; +pub const IVRSettings_Version: *const c_char = real_c_string!("IVRSettings_003"); +pub const k_pch_SteamVR_Section: *const c_char = real_c_string!("steamvr"); +pub const k_pch_SteamVR_RequireHmd_String: *const c_char = real_c_string!("requireHmd"); +pub const k_pch_SteamVR_ForcedDriverKey_String: *const c_char = real_c_string!("forcedDriver"); +pub const k_pch_SteamVR_ForcedHmdKey_String: *const c_char = real_c_string!("forcedHmd"); +pub const k_pch_SteamVR_DisplayDebug_Bool: *const c_char = real_c_string!("displayDebug"); +pub const k_pch_SteamVR_DebugProcessPipe_String: *const c_char = real_c_string!("debugProcessPipe"); +pub const k_pch_SteamVR_DisplayDebugX_Int32: *const c_char = real_c_string!("displayDebugX"); +pub const k_pch_SteamVR_DisplayDebugY_Int32: *const c_char = real_c_string!("displayDebugY"); +pub const k_pch_SteamVR_SendSystemButtonToAllApps_Bool: *const c_char = + real_c_string!("sendSystemButtonToAllApps"); +pub const k_pch_SteamVR_LogLevel_Int32: *const c_char = real_c_string!("loglevel"); +pub const k_pch_SteamVR_IPD_Float: *const c_char = real_c_string!("ipd"); +pub const k_pch_SteamVR_Background_String: *const c_char = real_c_string!("background"); +pub const k_pch_SteamVR_BackgroundUseDomeProjection_Bool: *const c_char = + real_c_string!("backgroundUseDomeProjection"); +pub const k_pch_SteamVR_BackgroundCameraHeight_Float: *const c_char = + real_c_string!("backgroundCameraHeight"); +pub const k_pch_SteamVR_BackgroundDomeRadius_Float: *const c_char = + real_c_string!("backgroundDomeRadius"); +pub const k_pch_SteamVR_GridColor_String: *const c_char = real_c_string!("gridColor"); +pub const k_pch_SteamVR_PlayAreaColor_String: *const c_char = real_c_string!("playAreaColor"); +pub const k_pch_SteamVR_TrackingLossColor_String: *const c_char = + real_c_string!("trackingLossColor"); +pub const k_pch_SteamVR_ShowStage_Bool: *const c_char = real_c_string!("showStage"); +pub const k_pch_SteamVR_DrawTrackingReferences_Bool: *const c_char = + real_c_string!("drawTrackingReferences"); +pub const k_pch_SteamVR_ActivateMultipleDrivers_Bool: *const c_char = + real_c_string!("activateMultipleDrivers"); +pub const k_pch_SteamVR_UsingSpeakers_Bool: *const c_char = real_c_string!("usingSpeakers"); +pub const k_pch_SteamVR_SpeakersForwardYawOffsetDegrees_Float: *const c_char = + real_c_string!("speakersForwardYawOffsetDegrees"); +pub const k_pch_SteamVR_BaseStationPowerManagement_Int32: *const c_char = + real_c_string!("basestationPowerManagement"); +pub const k_pch_SteamVR_ShowBaseStationPowerManagementTip_Int32: *const c_char = + real_c_string!("ShowBaseStationPowerManagementTip"); +pub const k_pch_SteamVR_NeverKillProcesses_Bool: *const c_char = + real_c_string!("neverKillProcesses"); +pub const k_pch_SteamVR_SupersampleScale_Float: *const c_char = real_c_string!("supersampleScale"); +pub const k_pch_SteamVR_MaxRecommendedResolution_Int32: *const c_char = + real_c_string!("maxRecommendedResolution"); +pub const k_pch_SteamVR_MotionSmoothing_Bool: *const c_char = real_c_string!("motionSmoothing"); +pub const k_pch_SteamVR_MotionSmoothingOverride_Int32: *const c_char = + real_c_string!("motionSmoothingOverride"); +pub const k_pch_SteamVR_FramesToThrottle_Int32: *const c_char = real_c_string!("framesToThrottle"); +pub const k_pch_SteamVR_AdditionalFramesToPredict_Int32: *const c_char = + real_c_string!("additionalFramesToPredict"); +pub const k_pch_SteamVR_DisableAsyncReprojection_Bool: *const c_char = + real_c_string!("disableAsync"); +pub const k_pch_SteamVR_ForceFadeOnBadTracking_Bool: *const c_char = + real_c_string!("forceFadeOnBadTracking"); +pub const k_pch_SteamVR_DefaultMirrorView_Int32: *const c_char = real_c_string!("mirrorView"); +pub const k_pch_SteamVR_ShowLegacyMirrorView_Bool: *const c_char = + real_c_string!("showLegacyMirrorView"); +pub const k_pch_SteamVR_MirrorViewVisibility_Bool: *const c_char = real_c_string!("showMirrorView"); +pub const k_pch_SteamVR_MirrorViewDisplayMode_Int32: *const c_char = + real_c_string!("mirrorViewDisplayMode"); +pub const k_pch_SteamVR_MirrorViewEye_Int32: *const c_char = real_c_string!("mirrorViewEye"); +pub const k_pch_SteamVR_MirrorViewGeometry_String: *const c_char = + real_c_string!("mirrorViewGeometry"); +pub const k_pch_SteamVR_MirrorViewGeometryMaximized_String: *const c_char = + real_c_string!("mirrorViewGeometryMaximized"); +pub const k_pch_SteamVR_PerfGraphVisibility_Bool: *const c_char = real_c_string!("showPerfGraph"); +pub const k_pch_SteamVR_StartMonitorFromAppLaunch: *const c_char = + real_c_string!("startMonitorFromAppLaunch"); +pub const k_pch_SteamVR_StartCompositorFromAppLaunch_Bool: *const c_char = + real_c_string!("startCompositorFromAppLaunch"); +pub const k_pch_SteamVR_StartDashboardFromAppLaunch_Bool: *const c_char = + real_c_string!("startDashboardFromAppLaunch"); +pub const k_pch_SteamVR_StartOverlayAppsFromDashboard_Bool: *const c_char = + real_c_string!("startOverlayAppsFromDashboard"); +pub const k_pch_SteamVR_EnableHomeApp: *const c_char = real_c_string!("enableHomeApp"); +pub const k_pch_SteamVR_CycleBackgroundImageTimeSec_Int32: *const c_char = + real_c_string!("CycleBackgroundImageTimeSec"); +pub const k_pch_SteamVR_RetailDemo_Bool: *const c_char = real_c_string!("retailDemo"); +pub const k_pch_SteamVR_IpdOffset_Float: *const c_char = real_c_string!("ipdOffset"); +pub const k_pch_SteamVR_AllowSupersampleFiltering_Bool: *const c_char = + real_c_string!("allowSupersampleFiltering"); +pub const k_pch_SteamVR_SupersampleManualOverride_Bool: *const c_char = + real_c_string!("supersampleManualOverride"); +pub const k_pch_SteamVR_EnableLinuxVulkanAsync_Bool: *const c_char = + real_c_string!("enableLinuxVulkanAsync"); +pub const k_pch_SteamVR_AllowDisplayLockedMode_Bool: *const c_char = + real_c_string!("allowDisplayLockedMode"); +pub const k_pch_SteamVR_HaveStartedTutorialForNativeChaperoneDriver_Bool: *const c_char = + real_c_string!("haveStartedTutorialForNativeChaperoneDriver"); +pub const k_pch_SteamVR_ForceWindows32bitVRMonitor: *const c_char = + real_c_string!("forceWindows32BitVRMonitor"); +pub const k_pch_SteamVR_DebugInputBinding: *const c_char = real_c_string!("debugInputBinding"); +pub const k_pch_SteamVR_DoNotFadeToGrid: *const c_char = real_c_string!("doNotFadeToGrid"); +pub const k_pch_SteamVR_RenderCameraMode: *const c_char = real_c_string!("renderCameraMode"); +pub const k_pch_SteamVR_EnableSharedResourceJournaling: *const c_char = + real_c_string!("enableSharedResourceJournaling"); +pub const k_pch_SteamVR_EnableSafeMode: *const c_char = real_c_string!("enableSafeMode"); +pub const k_pch_SteamVR_PreferredRefreshRate: *const c_char = + real_c_string!("preferredRefreshRate"); +pub const k_pch_SteamVR_LastVersionNotice: *const c_char = real_c_string!("lastVersionNotice"); +pub const k_pch_SteamVR_LastVersionNoticeDate: *const c_char = + real_c_string!("lastVersionNoticeDate"); +pub const k_pch_SteamVR_HmdDisplayColorGainR_Float: *const c_char = + real_c_string!("hmdDisplayColorGainR"); +pub const k_pch_SteamVR_HmdDisplayColorGainG_Float: *const c_char = + real_c_string!("hmdDisplayColorGainG"); +pub const k_pch_SteamVR_HmdDisplayColorGainB_Float: *const c_char = + real_c_string!("hmdDisplayColorGainB"); +pub const k_pch_SteamVR_CustomIconStyle_String: *const c_char = real_c_string!("customIconStyle"); +pub const k_pch_SteamVR_CustomOffIconStyle_String: *const c_char = + real_c_string!("customOffIconStyle"); +pub const k_pch_SteamVR_CustomIconForceUpdate_String: *const c_char = + real_c_string!("customIconForceUpdate"); +pub const k_pch_SteamVR_AllowGlobalActionSetPriority: *const c_char = + real_c_string!("globalActionSetPriority"); +pub const k_pch_SteamVR_OverlayRenderQuality: *const c_char = + real_c_string!("overlayRenderQuality_2"); +pub const k_pch_SteamVR_BlockOculusSDKOnOpenVRLaunchOption_Bool: *const c_char = + real_c_string!("blockOculusSDKOnOpenVRLaunchOption"); +pub const k_pch_SteamVR_BlockOculusSDKOnAllLaunches_Bool: *const c_char = + real_c_string!("blockOculusSDKOnAllLaunches"); +pub const k_pch_SteamVR_HDCPLegacyCompatibility_Bool: *const c_char = + real_c_string!("hdcp14legacyCompatibility"); +pub const k_pch_SteamVR_UsePrism_Bool: *const c_char = real_c_string!("usePrism"); +pub const k_pch_DirectMode_Section: *const c_char = real_c_string!("direct_mode"); +pub const k_pch_DirectMode_Enable_Bool: *const c_char = real_c_string!("enable"); +pub const k_pch_DirectMode_Count_Int32: *const c_char = real_c_string!("count"); +pub const k_pch_DirectMode_EdidVid_Int32: *const c_char = real_c_string!("edidVid"); +pub const k_pch_DirectMode_EdidPid_Int32: *const c_char = real_c_string!("edidPid"); +pub const k_pch_Lighthouse_Section: *const c_char = real_c_string!("driver_lighthouse"); +pub const k_pch_Lighthouse_DisableIMU_Bool: *const c_char = real_c_string!("disableimu"); +pub const k_pch_Lighthouse_DisableIMUExceptHMD_Bool: *const c_char = + real_c_string!("disableimuexcepthmd"); +pub const k_pch_Lighthouse_UseDisambiguation_String: *const c_char = + real_c_string!("usedisambiguation"); +pub const k_pch_Lighthouse_DisambiguationDebug_Int32: *const c_char = + real_c_string!("disambiguationdebug"); +pub const k_pch_Lighthouse_PrimaryBasestation_Int32: *const c_char = + real_c_string!("primarybasestation"); +pub const k_pch_Lighthouse_DBHistory_Bool: *const c_char = real_c_string!("dbhistory"); +pub const k_pch_Lighthouse_EnableBluetooth_Bool: *const c_char = real_c_string!("enableBluetooth"); +pub const k_pch_Lighthouse_PowerManagedBaseStations_String: *const c_char = + real_c_string!("PowerManagedBaseStations"); +pub const k_pch_Lighthouse_PowerManagedBaseStations2_String: *const c_char = + real_c_string!("PowerManagedBaseStations2"); +pub const k_pch_Lighthouse_InactivityTimeoutForBaseStations_Int32: *const c_char = + real_c_string!("InactivityTimeoutForBaseStations"); +pub const k_pch_Lighthouse_EnableImuFallback_Bool: *const c_char = + real_c_string!("enableImuFallback"); +pub const k_pch_Null_Section: *const c_char = real_c_string!("driver_null"); +pub const k_pch_Null_SerialNumber_String: *const c_char = real_c_string!("serialNumber"); +pub const k_pch_Null_ModelNumber_String: *const c_char = real_c_string!("modelNumber"); +pub const k_pch_Null_WindowX_Int32: *const c_char = real_c_string!("windowX"); +pub const k_pch_Null_WindowY_Int32: *const c_char = real_c_string!("windowY"); +pub const k_pch_Null_WindowWidth_Int32: *const c_char = real_c_string!("windowWidth"); +pub const k_pch_Null_WindowHeight_Int32: *const c_char = real_c_string!("windowHeight"); +pub const k_pch_Null_RenderWidth_Int32: *const c_char = real_c_string!("renderWidth"); +pub const k_pch_Null_RenderHeight_Int32: *const c_char = real_c_string!("renderHeight"); +pub const k_pch_Null_SecondsFromVsyncToPhotons_Float: *const c_char = + real_c_string!("secondsFromVsyncToPhotons"); +pub const k_pch_Null_DisplayFrequency_Float: *const c_char = real_c_string!("displayFrequency"); +pub const k_pch_WindowsMR_Section: *const c_char = real_c_string!("driver_holographic"); +pub const k_pch_UserInterface_Section: *const c_char = real_c_string!("userinterface"); +pub const k_pch_UserInterface_StatusAlwaysOnTop_Bool: *const c_char = + real_c_string!("StatusAlwaysOnTop"); +pub const k_pch_UserInterface_MinimizeToTray_Bool: *const c_char = real_c_string!("MinimizeToTray"); +pub const k_pch_UserInterface_HidePopupsWhenStatusMinimized_Bool: *const c_char = + real_c_string!("HidePopupsWhenStatusMinimized"); +pub const k_pch_UserInterface_Screenshots_Bool: *const c_char = real_c_string!("screenshots"); +pub const k_pch_UserInterface_ScreenshotType_Int: *const c_char = real_c_string!("screenshotType"); +pub const k_pch_Notifications_Section: *const c_char = real_c_string!("notifications"); +pub const k_pch_Notifications_DoNotDisturb_Bool: *const c_char = real_c_string!("DoNotDisturb"); +pub const k_pch_Keyboard_Section: *const c_char = real_c_string!("keyboard"); +pub const k_pch_Keyboard_TutorialCompletions: *const c_char = real_c_string!("TutorialCompletions"); +pub const k_pch_Keyboard_ScaleX: *const c_char = real_c_string!("ScaleX"); +pub const k_pch_Keyboard_ScaleY: *const c_char = real_c_string!("ScaleY"); +pub const k_pch_Keyboard_OffsetLeftX: *const c_char = real_c_string!("OffsetLeftX"); +pub const k_pch_Keyboard_OffsetRightX: *const c_char = real_c_string!("OffsetRightX"); +pub const k_pch_Keyboard_OffsetY: *const c_char = real_c_string!("OffsetY"); +pub const k_pch_Keyboard_Smoothing: *const c_char = real_c_string!("Smoothing"); +pub const k_pch_Perf_Section: *const c_char = real_c_string!("perfcheck"); +pub const k_pch_Perf_PerfGraphInHMD_Bool: *const c_char = real_c_string!("perfGraphInHMD"); +pub const k_pch_Perf_AllowTimingStore_Bool: *const c_char = real_c_string!("allowTimingStore"); +pub const k_pch_Perf_SaveTimingsOnExit_Bool: *const c_char = real_c_string!("saveTimingsOnExit"); +pub const k_pch_Perf_TestData_Float: *const c_char = real_c_string!("perfTestData"); +pub const k_pch_Perf_GPUProfiling_Bool: *const c_char = real_c_string!("GPUProfiling"); +pub const k_pch_CollisionBounds_Section: *const c_char = real_c_string!("collisionBounds"); +pub const k_pch_CollisionBounds_Style_Int32: *const c_char = real_c_string!("CollisionBoundsStyle"); +pub const k_pch_CollisionBounds_GroundPerimeterOn_Bool: *const c_char = + real_c_string!("CollisionBoundsGroundPerimeterOn"); +pub const k_pch_CollisionBounds_CenterMarkerOn_Bool: *const c_char = + real_c_string!("CollisionBoundsCenterMarkerOn"); +pub const k_pch_CollisionBounds_PlaySpaceOn_Bool: *const c_char = + real_c_string!("CollisionBoundsPlaySpaceOn"); +pub const k_pch_CollisionBounds_FadeDistance_Float: *const c_char = + real_c_string!("CollisionBoundsFadeDistance"); +pub const k_pch_CollisionBounds_WallHeight_Float: *const c_char = + real_c_string!("CollisionBoundsWallHeight"); +pub const k_pch_CollisionBounds_ColorGammaR_Int32: *const c_char = + real_c_string!("CollisionBoundsColorGammaR"); +pub const k_pch_CollisionBounds_ColorGammaG_Int32: *const c_char = + real_c_string!("CollisionBoundsColorGammaG"); +pub const k_pch_CollisionBounds_ColorGammaB_Int32: *const c_char = + real_c_string!("CollisionBoundsColorGammaB"); +pub const k_pch_CollisionBounds_ColorGammaA_Int32: *const c_char = + real_c_string!("CollisionBoundsColorGammaA"); +pub const k_pch_CollisionBounds_EnableDriverImport: *const c_char = + real_c_string!("enableDriverBoundsImport"); +pub const k_pch_Camera_Section: *const c_char = real_c_string!("camera"); +pub const k_pch_Camera_EnableCamera_Bool: *const c_char = real_c_string!("enableCamera"); +pub const k_pch_Camera_ShowOnController_Bool: *const c_char = real_c_string!("showOnController"); +pub const k_pch_Camera_EnableCameraForCollisionBounds_Bool: *const c_char = + real_c_string!("enableCameraForCollisionBounds"); +pub const k_pch_Camera_RoomView_Int32: *const c_char = real_c_string!("roomView"); +pub const k_pch_Camera_BoundsColorGammaR_Int32: *const c_char = + real_c_string!("cameraBoundsColorGammaR"); +pub const k_pch_Camera_BoundsColorGammaG_Int32: *const c_char = + real_c_string!("cameraBoundsColorGammaG"); +pub const k_pch_Camera_BoundsColorGammaB_Int32: *const c_char = + real_c_string!("cameraBoundsColorGammaB"); +pub const k_pch_Camera_BoundsColorGammaA_Int32: *const c_char = + real_c_string!("cameraBoundsColorGammaA"); +pub const k_pch_Camera_BoundsStrength_Int32: *const c_char = real_c_string!("cameraBoundsStrength"); +pub const k_pch_Camera_RoomViewStyle_Int32: *const c_char = real_c_string!("roomViewStyle"); +pub const k_pch_audio_Section: *const c_char = real_c_string!("audio"); +pub const k_pch_audio_SetOsDefaultPlaybackDevice_Bool: *const c_char = + real_c_string!("setOsDefaultPlaybackDevice"); +pub const k_pch_audio_EnablePlaybackDeviceOverride_Bool: *const c_char = + real_c_string!("enablePlaybackDeviceOverride"); +pub const k_pch_audio_PlaybackDeviceOverride_String: *const c_char = + real_c_string!("playbackDeviceOverride"); +pub const k_pch_audio_PlaybackDeviceOverrideName_String: *const c_char = + real_c_string!("playbackDeviceOverrideName"); +pub const k_pch_audio_SetOsDefaultRecordingDevice_Bool: *const c_char = + real_c_string!("setOsDefaultRecordingDevice"); +pub const k_pch_audio_EnableRecordingDeviceOverride_Bool: *const c_char = + real_c_string!("enableRecordingDeviceOverride"); +pub const k_pch_audio_RecordingDeviceOverride_String: *const c_char = + real_c_string!("recordingDeviceOverride"); +pub const k_pch_audio_RecordingDeviceOverrideName_String: *const c_char = + real_c_string!("recordingDeviceOverrideName"); +pub const k_pch_audio_EnablePlaybackMirror_Bool: *const c_char = + real_c_string!("enablePlaybackMirror"); +pub const k_pch_audio_PlaybackMirrorDevice_String: *const c_char = + real_c_string!("playbackMirrorDevice"); +pub const k_pch_audio_PlaybackMirrorDeviceName_String: *const c_char = + real_c_string!("playbackMirrorDeviceName"); +pub const k_pch_audio_OldPlaybackMirrorDevice_String: *const c_char = + real_c_string!("onPlaybackMirrorDevice"); +pub const k_pch_audio_ActiveMirrorDevice_String: *const c_char = + real_c_string!("activePlaybackMirrorDevice"); +pub const k_pch_audio_EnablePlaybackMirrorIndependentVolume_Bool: *const c_char = + real_c_string!("enablePlaybackMirrorIndependentVolume"); +pub const k_pch_audio_LastHmdPlaybackDeviceId_String: *const c_char = + real_c_string!("lastHmdPlaybackDeviceId"); +pub const k_pch_audio_VIVEHDMIGain: *const c_char = real_c_string!("viveHDMIGain"); +pub const k_pch_audio_DualSpeakerAndJackOutput_Bool: *const c_char = + real_c_string!("dualSpeakerAndJackOutput"); +pub const k_pch_audio_MuteMicMonitor_Bool: *const c_char = real_c_string!("muteMicMonitor"); +pub const k_pch_Power_Section: *const c_char = real_c_string!("power"); +pub const k_pch_Power_PowerOffOnExit_Bool: *const c_char = real_c_string!("powerOffOnExit"); +pub const k_pch_Power_TurnOffScreensTimeout_Float: *const c_char = + real_c_string!("turnOffScreensTimeout"); +pub const k_pch_Power_TurnOffControllersTimeout_Float: *const c_char = + real_c_string!("turnOffControllersTimeout"); +pub const k_pch_Power_ReturnToWatchdogTimeout_Float: *const c_char = + real_c_string!("returnToWatchdogTimeout"); +pub const k_pch_Power_AutoLaunchSteamVROnButtonPress: *const c_char = + real_c_string!("autoLaunchSteamVROnButtonPress"); +pub const k_pch_Power_PauseCompositorOnStandby_Bool: *const c_char = + real_c_string!("pauseCompositorOnStandby"); +pub const k_pch_Dashboard_Section: *const c_char = real_c_string!("dashboard"); +pub const k_pch_Dashboard_EnableDashboard_Bool: *const c_char = real_c_string!("enableDashboard"); +pub const k_pch_Dashboard_ArcadeMode_Bool: *const c_char = real_c_string!("arcadeMode"); +pub const k_pch_Dashboard_Position: *const c_char = real_c_string!("position"); +pub const k_pch_Dashboard_DesktopScale: *const c_char = real_c_string!("desktopScale"); +pub const k_pch_Dashboard_DashboardScale: *const c_char = real_c_string!("dashboardScale"); +pub const k_pch_Dashboard_UseStandaloneSystemLayer: *const c_char = + real_c_string!("standaloneSystemLayer"); +pub const k_pch_modelskin_Section: *const c_char = real_c_string!("modelskins"); +pub const k_pch_Driver_Enable_Bool: *const c_char = real_c_string!("enable"); +pub const k_pch_Driver_BlockedBySafemode_Bool: *const c_char = + real_c_string!("blocked_by_safe_mode"); +pub const k_pch_Driver_LoadPriority_Int32: *const c_char = real_c_string!("loadPriority"); +pub const k_pch_WebInterface_Section: *const c_char = real_c_string!("WebInterface"); +pub const k_pch_VRWebHelper_Section: *const c_char = real_c_string!("VRWebHelper"); +pub const k_pch_VRWebHelper_DebuggerEnabled_Bool: *const c_char = real_c_string!("DebuggerEnabled"); +pub const k_pch_VRWebHelper_DebuggerPort_Int32: *const c_char = real_c_string!("DebuggerPort"); +pub const k_pch_TrackingOverride_Section: *const c_char = real_c_string!("TrackingOverrides"); +pub const k_pch_App_BindingAutosaveURLSuffix_String: *const c_char = real_c_string!("AutosaveURL"); +pub const k_pch_App_BindingLegacyAPISuffix_String: *const c_char = real_c_string!("_legacy"); +pub const k_pch_App_BindingSteamVRInputAPISuffix_String: *const c_char = + real_c_string!("_steamvrinput"); +pub const k_pch_App_BindingCurrentURLSuffix_String: *const c_char = real_c_string!("CurrentURL"); +pub const k_pch_App_BindingPreviousURLSuffix_String: *const c_char = real_c_string!("PreviousURL"); +pub const k_pch_App_NeedToUpdateAutosaveSuffix_Bool: *const c_char = + real_c_string!("NeedToUpdateAutosave"); +pub const k_pch_App_DominantHand_Int32: *const c_char = real_c_string!("DominantHand"); +pub const k_pch_App_BlockOculusSDK_Bool: *const c_char = real_c_string!("blockOculusSDK"); +pub const k_pch_Trackers_Section: *const c_char = real_c_string!("trackers"); +pub const k_pch_DesktopUI_Section: *const c_char = real_c_string!("DesktopUI"); +pub const k_pch_LastKnown_Section: *const c_char = real_c_string!("LastKnown"); +pub const k_pch_LastKnown_HMDManufacturer_String: *const c_char = real_c_string!("HMDManufacturer"); +pub const k_pch_LastKnown_HMDModel_String: *const c_char = real_c_string!("HMDModel"); +pub const k_pch_DismissedWarnings_Section: *const c_char = real_c_string!("DismissedWarnings"); +pub const k_pch_Input_Section: *const c_char = real_c_string!("input"); +pub const k_pch_Input_LeftThumbstickRotation_Float: *const c_char = + real_c_string!("leftThumbstickRotation"); +pub const k_pch_Input_RightThumbstickRotation_Float: *const c_char = + real_c_string!("rightThumbstickRotation"); +pub const k_pch_Input_ThumbstickDeadzone_Float: *const c_char = + real_c_string!("thumbstickDeadzone"); +pub const k_pch_GpuSpeed_Section: *const c_char = real_c_string!("GpuSpeed"); +pub const ITrackedDeviceServerDriver_Version: *const c_char = + real_c_string!("ITrackedDeviceServerDriver_005"); +pub const IVRDisplayComponent_Version: *const c_char = real_c_string!("IVRDisplayComponent_002"); +pub const IVRDriverDirectModeComponent_Version: *const c_char = + real_c_string!("IVRDriverDirectModeComponent_007"); +pub const IVRCameraComponent_Version: *const c_char = real_c_string!("IVRCameraComponent_003"); +pub const IServerTrackedDeviceProvider_Version: *const c_char = + real_c_string!("IServerTrackedDeviceProvider_004"); +pub const IVRWatchdogProvider_Version: *const c_char = real_c_string!("IVRWatchdogProvider_001"); +pub const IVRCompositorPluginProvider_Version: *const c_char = + real_c_string!("IVRCompositorPluginProvider_001"); +pub const k_ulDisplayRedirectContainer: PropertyContainerHandle_t = 25769803779; +pub const IVRProperties_Version: *const c_char = real_c_string!("IVRProperties_001"); +pub const k_ulInvalidInputComponentHandle: VRInputComponentHandle_t = 0; +pub const IVRDriverInput_Version: *const c_char = real_c_string!("IVRDriverInput_003"); +pub const IVRDriverLog_Version: *const c_char = real_c_string!("IVRDriverLog_001"); +pub const IVRServerDriverHost_Version: *const c_char = real_c_string!("IVRServerDriverHost_006"); +pub const IVRCompositorDriverHost_Version: *const c_char = + real_c_string!("IVRCompositorDriverHost_001"); +pub const IVRWatchdogHost_Version: *const c_char = real_c_string!("IVRWatchdogHost_002"); +pub const IVRVirtualDisplay_Version: *const c_char = real_c_string!("IVRVirtualDisplay_002"); +pub const IVRResources_Version: *const c_char = real_c_string!("IVRResources_001"); +pub const k_ulInvalidIOBufferHandle: u64 = 0; +pub const IVRIOBuffer_Version: *const c_char = real_c_string!("IVRIOBuffer_002"); +pub const IVRDriverManager_Version: *const c_char = real_c_string!("IVRDriverManager_001"); +pub const IVRDriverSpatialAnchors_Version: *const c_char = + real_c_string!("IVRDriverSpatialAnchors_001"); +// pub const k_InterfaceVersions: [*const c_char; 12] = {REF, REF, REF, REF, REF, REF, REF, REF, REF, REF, REF, NULL}; +#[derive(Clone, Copy)] +#[repr(C)] +pub struct HmdMatrix34_t { + pub m: [[f32; 3]; 4], +} +#[derive(Clone, Copy)] +#[repr(C)] +pub struct HmdMatrix33_t { + pub m: [[f32; 3]; 3], +} +#[derive(Clone, Copy)] +#[repr(C)] +pub struct HmdMatrix44_t { + pub m: [[f32; 4]; 4], +} +#[derive(Clone, Copy)] +#[repr(C)] +pub struct HmdVector3_t { + pub v: [f32; 3], +} +#[derive(Clone, Copy)] +#[repr(C)] +pub struct HmdVector4_t { + pub v: [f32; 4], +} +#[derive(Clone, Copy)] +#[repr(C)] +pub struct HmdVector3d_t { + pub v: [f64; 3], +} +#[derive(Clone, Copy)] +#[repr(C)] +pub struct HmdVector2_t { + pub v: [f32; 2], +} +#[derive(Clone, Copy)] +#[repr(C)] +pub struct HmdQuaternion_t { + pub w: f64, + pub x: f64, + pub y: f64, + pub z: f64, +} +#[derive(Clone, Copy)] +#[repr(C)] +pub struct HmdQuaternionf_t { + pub w: f32, + pub x: f32, + pub y: f32, + pub z: f32, +} +#[derive(Clone, Copy)] +#[repr(C)] +pub struct HmdColor_t { + pub r: f32, + pub g: f32, + pub b: f32, + pub a: f32, +} +#[derive(Clone, Copy)] +#[repr(C)] +pub struct HmdQuad_t { + pub vCorners: [HmdVector3_t; 4], +} +#[derive(Clone, Copy)] +#[repr(C)] +pub struct HmdRect2_t { + pub vTopLeft: HmdVector2_t, + pub vBottomRight: HmdVector2_t, +} +#[derive(Clone, Copy)] +#[repr(C)] +pub struct VRBoneTransform_t { + pub position: HmdVector4_t, + pub orientation: HmdQuaternionf_t, +} +#[derive(Clone, Copy)] +#[repr(C)] +pub struct DistortionCoordinates_t { + pub rfRed: [f32; 2], + pub rfGreen: [f32; 2], + pub rfBlue: [f32; 2], +} +#[derive(Clone, Copy)] +#[repr(C)] +pub struct Texture_t { + pub handle: *mut c_void, + pub eType: ETextureType, + pub eColorSpace: EColorSpace, +} +#[derive(Clone, Copy)] +#[repr(C)] +pub struct TrackedDevicePose_t { + pub mDeviceToAbsoluteTracking: HmdMatrix34_t, + pub vVelocity: HmdVector3_t, + pub vAngularVelocity: HmdVector3_t, + pub eTrackingResult: ETrackingResult, + pub bPoseIsValid: bool, + pub bDeviceIsConnected: bool, +} +#[derive(Clone, Copy)] +#[repr(C)] +pub struct VRTextureBounds_t { + pub uMin: f32, + pub vMin: f32, + pub uMax: f32, + pub vMax: f32, +} +#[derive(Clone, Copy)] +#[repr(C)] +pub struct VRTextureWithPose_t { + pub mDeviceToAbsoluteTracking: HmdMatrix34_t, +} +#[derive(Clone, Copy)] +#[repr(C)] +pub struct VRTextureDepthInfo_t { + pub handle: *mut c_void, + pub mProjection: HmdMatrix44_t, + pub vRange: HmdVector2_t, +} +#[derive(Clone, Copy)] +#[repr(C)] +pub struct VRTextureWithDepth_t { + pub depth: VRTextureDepthInfo_t, +} +#[derive(Clone, Copy)] +#[repr(C)] +pub struct VRTextureWithPoseAndDepth_t { + pub depth: VRTextureDepthInfo_t, +} +#[derive(Clone, Copy)] +#[repr(C)] +pub struct VRVulkanTextureData_t { + pub m_nImage: u64, + pub m_pDevice: *mut VkDevice_T, + pub m_pPhysicalDevice: *mut VkPhysicalDevice_T, + pub m_pInstance: *mut VkInstance_T, + pub m_pQueue: *mut VkQueue_T, + pub m_nQueueFamilyIndex: u32, + pub m_nWidth: u32, + pub m_nHeight: u32, + pub m_nFormat: u32, + pub m_nSampleCount: u32, +} +#[derive(Clone, Copy)] +#[repr(C)] +pub struct VRVulkanTextureArrayData_t { + pub m_unArrayIndex: u32, + pub m_unArraySize: u32, +} +#[derive(Clone, Copy)] +#[repr(C)] +pub struct D3D12TextureData_t { + pub m_pResource: *const c_void, + pub m_pCommandQueue: *const c_void, + pub m_nNodeMask: u32, +} +#[derive(Clone, Copy)] +#[repr(C)] +pub struct VREvent_Controller_t { + pub button: u32, +} +#[derive(Clone, Copy)] +#[repr(C)] +pub struct VREvent_Mouse_t { + pub x: f32, + pub y: f32, + pub button: u32, +} +#[derive(Clone, Copy)] +#[repr(C)] +pub struct VREvent_Scroll_t { + pub xdelta: f32, + pub ydelta: f32, + pub unused: u32, + pub viewportscale: f32, +} +#[derive(Clone, Copy)] +#[repr(C)] +pub struct VREvent_TouchPadMove_t { + pub bFingerDown: bool, + pub flSecondsFingerDown: f32, + pub fValueXFirst: f32, + pub fValueYFirst: f32, + pub fValueXRaw: f32, + pub fValueYRaw: f32, +} +#[derive(Clone, Copy)] +#[repr(C)] +pub struct VREvent_Notification_t { + pub ulUserValue: u64, + pub notificationId: u32, +} +#[derive(Clone, Copy)] +#[repr(C)] +pub struct VREvent_Process_t { + pub pid: u32, + pub oldPid: u32, + pub bForced: bool, + pub bConnectionLost: bool, +} +#[derive(Clone, Copy)] +#[repr(C)] +pub struct VREvent_Overlay_t { + pub overlayHandle: u64, + pub devicePath: u64, + pub memoryBlockId: u64, +} +#[derive(Clone, Copy)] +#[repr(C)] +pub struct VREvent_Status_t { + pub statusState: u32, +} +#[derive(Clone, Copy)] +#[repr(C)] +pub struct VREvent_Keyboard_t { + pub cNewInput: [c_char; 8], + pub uUserValue: u64, +} +#[derive(Clone, Copy)] +#[repr(C)] +pub struct VREvent_Ipd_t { + pub ipdMeters: f32, +} +#[derive(Clone, Copy)] +#[repr(C)] +pub struct VREvent_Chaperone_t { + pub m_nPreviousUniverse: u64, + pub m_nCurrentUniverse: u64, +} +#[derive(Clone, Copy)] +#[repr(C)] +pub struct VREvent_Reserved_t { + pub reserved0: u64, + pub reserved1: u64, + pub reserved2: u64, + pub reserved3: u64, + pub reserved4: u64, + pub reserved5: u64, +} +#[derive(Clone, Copy)] +#[repr(C)] +pub struct VREvent_PerformanceTest_t { + pub m_nFidelityLevel: u32, +} +#[derive(Clone, Copy)] +#[repr(C)] +pub struct VREvent_SeatedZeroPoseReset_t { + pub bResetBySystemMenu: bool, +} +#[derive(Clone, Copy)] +#[repr(C)] +pub struct VREvent_Screenshot_t { + pub handle: u32, + pub typ: u32, +} +#[derive(Clone, Copy)] +#[repr(C)] +pub struct VREvent_ScreenshotProgress_t { + pub progress: f32, +} +#[derive(Clone, Copy)] +#[repr(C)] +pub struct VREvent_ApplicationLaunch_t { + pub pid: u32, + pub unArgsHandle: u32, +} +#[derive(Clone, Copy)] +#[repr(C)] +pub struct VREvent_EditingCameraSurface_t { + pub overlayHandle: u64, + pub nVisualMode: u32, +} +#[derive(Clone, Copy)] +#[repr(C)] +pub struct VREvent_MessageOverlay_t { + pub unVRMessageOverlayResponse: u32, +} +#[derive(Clone, Copy)] +#[repr(C)] +pub struct VREvent_Property_t { + pub container: PropertyContainerHandle_t, + pub prop: ETrackedDeviceProperty, +} +#[derive(Clone, Copy)] +#[repr(C)] +pub struct VREvent_HapticVibration_t { + pub containerHandle: u64, + pub componentHandle: u64, + pub fDurationSeconds: f32, + pub fFrequency: f32, + pub fAmplitude: f32, +} +#[derive(Clone, Copy)] +#[repr(C)] +pub struct VREvent_WebConsole_t { + pub webConsoleHandle: WebConsoleHandle_t, +} +#[derive(Clone, Copy)] +#[repr(C)] +pub struct VREvent_InputBindingLoad_t { + pub ulAppContainer: PropertyContainerHandle_t, + pub pathMessage: u64, + pub pathUrl: u64, + pub pathControllerType: u64, +} +#[derive(Clone, Copy)] +#[repr(C)] +pub struct VREvent_InputActionManifestLoad_t { + pub pathAppKey: u64, + pub pathMessage: u64, + pub pathMessageParam: u64, + pub pathManifestPath: u64, +} +#[derive(Clone, Copy)] +#[repr(C)] +pub struct VREvent_SpatialAnchor_t { + pub unHandle: SpatialAnchorHandle_t, +} +#[derive(Clone, Copy)] +#[repr(C)] +pub struct VREvent_ProgressUpdate_t { + pub ulApplicationPropertyContainer: u64, + pub pathDevice: u64, + pub pathInputSource: u64, + pub pathProgressAction: u64, + pub pathIcon: u64, + pub fProgress: f32, +} +#[derive(Clone, Copy)] +#[repr(C)] +pub struct VREvent_ShowUI_t { + pub eType: EShowUIType, +} +#[derive(Clone, Copy)] +#[repr(C)] +pub struct VREvent_ShowDevTools_t { + pub nBrowserIdentifier: i32, +} +#[derive(Clone, Copy)] +#[repr(C)] +pub struct VREvent_HDCPError_t { + pub eCode: EHDCPError, +} +#[derive(Clone, Copy)] +#[repr(C)] +pub struct VREvent_t { + pub eventType: u32, + pub trackedDeviceIndex: TrackedDeviceIndex_t, + pub eventAgeSeconds: f32, + pub data: VREvent_Data_t, +} +#[derive(Clone, Copy)] +#[repr(C)] +pub struct RenderModel_ComponentState_t { + pub mTrackingToComponentRenderModel: HmdMatrix34_t, + pub mTrackingToComponentLocal: HmdMatrix34_t, + pub uProperties: VRComponentProperties, +} +#[derive(Clone, Copy)] +#[repr(C)] +pub struct HiddenAreaMesh_t { + pub pVertexData: *const HmdVector2_t, + pub unTriangleCount: u32, +} +#[derive(Clone, Copy)] +#[repr(C)] +pub struct VRControllerAxis_t { + pub x: f32, + pub y: f32, +} +#[derive(Clone, Copy)] +#[repr(C)] +pub struct VRControllerState001_t { + pub unPacketNum: u32, + pub ulButtonPressed: u64, + pub ulButtonTouched: u64, + pub rAxis: [VRControllerAxis_t; 5], +} +#[derive(Clone, Copy)] +#[repr(C)] +pub struct CameraVideoStreamFrameHeader_t { + pub eFrameType: EVRTrackedCameraFrameType, + pub nWidth: u32, + pub nHeight: u32, + pub nBytesPerPixel: u32, + pub nFrameSequence: u32, + pub trackedDevicePose: TrackedDevicePose_t, + pub ulFrameExposureTime: u64, +} +#[derive(Clone, Copy)] +#[repr(C)] +pub struct Compositor_FrameTiming { + pub m_nSize: u32, + pub m_nFrameIndex: u32, + pub m_nNumFramePresents: u32, + pub m_nNumMisPresented: u32, + pub m_nNumDroppedFrames: u32, + pub m_nReprojectionFlags: u32, + pub m_flSystemTimeInSeconds: f64, + pub m_flPreSubmitGpuMs: f32, + pub m_flPostSubmitGpuMs: f32, + pub m_flTotalRenderGpuMs: f32, + pub m_flCompositorRenderGpuMs: f32, + pub m_flCompositorRenderCpuMs: f32, + pub m_flCompositorIdleCpuMs: f32, + pub m_flClientFrameIntervalMs: f32, + pub m_flPresentCallCpuMs: f32, + pub m_flWaitForPresentCpuMs: f32, + pub m_flSubmitFrameMs: f32, + pub m_flWaitGetPosesCalledMs: f32, + pub m_flNewPosesReadyMs: f32, + pub m_flNewFrameReadyMs: f32, + pub m_flCompositorUpdateStartMs: f32, + pub m_flCompositorUpdateEndMs: f32, + pub m_flCompositorRenderStartMs: f32, + pub m_HmdPose: TrackedDevicePose_t, + pub m_nNumVSyncsReadyForUse: u32, + pub m_nNumVSyncsToFirstView: u32, +} +#[derive(Clone, Copy)] +#[repr(C)] +pub struct Compositor_BenchmarkResults { + pub m_flMegaPixelsPerSecond: f32, + pub m_flHmdRecommendedMegaPixelsPerSecond: f32, +} +#[derive(Clone, Copy)] +#[repr(C)] +pub struct DriverDirectMode_FrameTiming { + pub m_nSize: u32, + pub m_nNumFramePresents: u32, + pub m_nNumMisPresented: u32, + pub m_nNumDroppedFrames: u32, + pub m_nReprojectionFlags: u32, +} +#[derive(Clone, Copy)] +#[repr(C)] +pub struct ImuSample_t { + pub fSampleTime: f64, + pub vAccel: HmdVector3d_t, + pub vGyro: HmdVector3d_t, + pub unOffScaleFlags: u32, +} +#[derive(Clone, Copy)] +#[repr(C)] +pub struct CameraVideoStreamFrame_t { + pub m_nStreamFormat: ECameraVideoStreamFormat, + pub m_nWidth: u32, + pub m_nHeight: u32, + pub m_nImageDataSize: u32, + pub m_nFrameSequence: u32, + pub m_nBufferIndex: u32, + pub m_nBufferCount: u32, + pub m_nExposureTime: u32, + pub m_nISPFrameTimeStamp: u32, + pub m_nISPReferenceTimeStamp: u32, + pub m_nSyncCounter: u32, + pub m_nCamSyncEvents: u32, + pub m_nISPSyncEvents: u32, + pub m_flReferenceCamSyncTime: f64, + pub m_flFrameElapsedTime: f64, + pub m_flFrameDeliveryRate: f64, + pub m_flFrameCaptureTime_DriverAbsolute: f64, + pub m_flFrameCaptureTime_ServerRelative: f64, + pub m_nFrameCaptureTicks_ServerAbsolute: u64, + pub m_flFrameCaptureTime_ClientRelative: f64, + pub m_flSyncMarkerError: f64, + pub m_RawTrackedDevicePose: TrackedDevicePose_t, + pub m_pImageData: u64, +} +#[derive(Clone, Copy)] +#[repr(C)] +pub struct DriverPoseQuaternion_t { + pub w: f64, + pub x: f64, + pub y: f64, + pub z: f64, +} +#[derive(Clone, Copy)] +#[repr(C)] +pub struct DriverPose_t { + pub poseTimeOffset: f64, + pub qWorldFromDriverRotation: HmdQuaternion_t, + pub vecWorldFromDriverTranslation: [f64; 3], + pub qDriverFromHeadRotation: HmdQuaternion_t, + pub vecDriverFromHeadTranslation: [f64; 3], + pub vecPosition: [f64; 3], + pub vecVelocity: [f64; 3], + pub vecAcceleration: [f64; 3], + pub qRotation: HmdQuaternion_t, + pub vecAngularVelocity: [f64; 3], + pub vecAngularAcceleration: [f64; 3], + pub result: ETrackingResult, + pub poseIsValid: bool, + pub willDriftInYaw: bool, + pub shouldApplyHeadModel: bool, + pub deviceIsConnected: bool, +} +#[derive(Clone, Copy)] +#[repr(C)] +pub struct PropertyWrite_t { + pub prop: ETrackedDeviceProperty, + pub writeType: EPropertyWriteType, + pub eSetError: ETrackedPropertyError, + pub pvBuffer: *mut c_void, + pub unBufferSize: u32, + pub unTag: PropertyTypeTag_t, + pub eError: ETrackedPropertyError, +} +#[derive(Clone, Copy)] +#[repr(C)] +pub struct PropertyRead_t { + pub prop: ETrackedDeviceProperty, + pub pvBuffer: *mut c_void, + pub unBufferSize: u32, + pub unTag: PropertyTypeTag_t, + pub unRequiredBufferSize: u32, + pub eError: ETrackedPropertyError, +} +#[derive(Clone, Copy)] +#[repr(C)] +pub struct PresentInfo_t { + pub backbufferTextureHandle: SharedTextureHandle_t, + pub vsync: EVSync, + pub nFrameId: u64, + pub flVSyncTimeInSeconds: f64, +} +#[derive(Clone, Copy)] +#[repr(C)] +pub struct SpatialAnchorDriverPose_t { + pub qWorldRotation: HmdQuaternion_t, + pub vWorldTranslation: HmdVector3d_t, + pub ulRequiredUniverseId: u64, + pub fValidDuration: f64, +} +#[vtable] +pub trait ICameraVideoSinkCallback { + fn OnCameraVideoSinkCallback(&self); +} +#[vtable] +pub trait IServerTrackedDeviceProvider { + fn Init(&self, pDriverContext: *const VtableRef) -> EVRInitError; + fn Cleanup(&self); + fn GetInterfaceVersions(&self) -> *const *const c_char; + fn RunFrame(&self); + fn ShouldBlockStandbyMode(&self) -> bool; + fn EnterStandby(&self); + fn LeaveStandby(&self); +} +#[vtable] +pub trait ITrackedDeviceServerDriver { + fn Activate(&self, unObjectId: u32) -> EVRInitError; + fn Deactivate(&self); + fn EnterStandby(&self); + fn GetComponent(&self, pchComponentNameAndVersion: *const c_char) -> *mut c_void; + fn DebugRequest( + &self, + pchRequest: *const c_char, + pchResponseBuffer: *mut c_char, + unResponseBufferSize: u32, + ); + fn GetPose(&self) -> DriverPose_t; +} +#[vtable] +pub trait IVRCameraComponent { + fn GetCameraFrameDimensions( + &self, + nVideoStreamFormat: ECameraVideoStreamFormat, + pWidth: *mut u32, + pHeight: *mut u32, + ) -> bool; + fn GetCameraFrameBufferingRequirements( + &self, + pDefaultFrameQueueSize: *mut i32, + pFrameBufferDataSize: *mut u32, + ) -> bool; + fn SetCameraFrameBuffering( + &self, + nFrameBufferCount: i32, + ppFrameBuffers: *mut *mut c_void, + nFrameBufferDataSize: u32, + ) -> bool; + fn SetCameraVideoStreamFormat(&self, nVideoStreamFormat: ECameraVideoStreamFormat) -> bool; + fn GetCameraVideoStreamFormat(&self) -> ECameraVideoStreamFormat; + fn StartVideoStream(&self) -> bool; + fn StopVideoStream(&self); + fn IsVideoStreamActive(&self, pbPaused: *mut bool, pflElapsedTime: *mut f32) -> bool; + fn GetVideoStreamFrame(&self) -> *const CameraVideoStreamFrame_t; + fn ReleaseVideoStreamFrame(&self, pFrameImage: *const CameraVideoStreamFrame_t); + fn SetAutoExposure(&self, bEnable: bool) -> bool; + fn PauseVideoStream(&self) -> bool; + fn ResumeVideoStream(&self) -> bool; + fn GetCameraDistortion( + &self, + nCameraIndex: u32, + flInputU: f32, + flInputV: f32, + pflOutputU: *mut f32, + pflOutputV: *mut f32, + ) -> bool; + fn GetCameraProjection( + &self, + nCameraIndex: u32, + eFrameType: EVRTrackedCameraFrameType, + flZNear: f32, + flZFar: f32, + pProjection: *mut HmdMatrix44_t, + ) -> bool; + fn SetFrameRate(&self, nISPFrameRate: i32, nSensorFrameRate: i32) -> bool; + fn SetCameraVideoSinkCallback( + &self, + pCameraVideoSinkCallback: *const VtableRef, + ) -> bool; + fn GetCameraCompatibilityMode( + &self, + pCameraCompatibilityMode: *mut ECameraCompatibilityMode, + ) -> bool; + fn SetCameraCompatibilityMode( + &self, + nCameraCompatibilityMode: ECameraCompatibilityMode, + ) -> bool; + fn GetCameraFrameBounds( + &self, + eFrameType: EVRTrackedCameraFrameType, + pLeft: *mut u32, + pTop: *mut u32, + pWidth: *mut u32, + pHeight: *mut u32, + ) -> bool; + fn GetCameraIntrinsics( + &self, + nCameraIndex: u32, + eFrameType: EVRTrackedCameraFrameType, + pFocalLength: *mut HmdVector2_t, + pCenter: *mut HmdVector2_t, + peDistortionType: *mut EVRDistortionFunctionType, + rCoefficients: *mut f64, + ) -> bool; +} +#[vtable] +pub trait IVRCompositorDriverHost { + fn PollNextEvent(&self, pEvent: *mut VREvent_t, uncbVREvent: u32) -> bool; +} +#[vtable] +pub trait IVRCompositorPluginProvider { + fn Init(&self, pDriverContext: *const VtableRef) -> EVRInitError; + fn Cleanup(&self); + fn GetInterfaceVersions(&self) -> *const *const c_char; + fn GetComponent(&self, pchComponentNameAndVersion: *const c_char) -> *mut c_void; +} +#[vtable] +pub trait IVRDisplayComponent { + fn GetWindowBounds(&self, pnX: *mut i32, pnY: *mut i32, pnWidth: *mut u32, pnHeight: *mut u32); + fn IsDisplayOnDesktop(&self) -> bool; + fn IsDisplayRealDisplay(&self) -> bool; + fn GetRecommendedRenderTargetSize(&self, pnWidth: *mut u32, pnHeight: *mut u32); + fn GetEyeOutputViewport( + &self, + eEye: EVREye, + pnX: *mut u32, + pnY: *mut u32, + pnWidth: *mut u32, + pnHeight: *mut u32, + ); + fn GetProjectionRaw( + &self, + eEye: EVREye, + pfLeft: *mut f32, + pfRight: *mut f32, + pfTop: *mut f32, + pfBottom: *mut f32, + ); + fn ComputeDistortion(&self, eEye: EVREye, fU: f32, fV: f32) -> DistortionCoordinates_t; +} +#[vtable] +pub trait IVRDriverContext { + fn GetGenericInterface( + &self, + pchInterfaceVersion: *const c_char, + peError: *mut EVRInitError, + ) -> *mut c_void; + fn GetDriverHandle(&self) -> DriverHandle_t; +} +#[vtable] +pub trait IVRDriverDirectModeComponent { + fn CreateSwapTextureSet( + &self, + unPid: u32, + pSwapTextureSetDesc: *const c_void, + pOutSwapTextureSet: *mut c_void, + ); + fn DestroySwapTextureSet(&self, sharedTextureHandle: SharedTextureHandle_t); + fn DestroyAllSwapTextureSets(&self, unPid: u32); + fn GetNextSwapTextureSetIndex( + &self, + sharedTextureHandles: *mut SharedTextureHandle_t, + pIndices: *mut [u32; 2], + ); + fn SubmitLayer(&self, perEye: *const c_void); + fn Present(&self, syncTexture: SharedTextureHandle_t); + fn PostPresent(&self); + fn GetFrameTiming(&self, pFrameTiming: *mut DriverDirectMode_FrameTiming); +} +#[vtable] +pub trait IVRDriverInput { + fn CreateBooleanComponent( + &self, + ulContainer: PropertyContainerHandle_t, + pchName: *const c_char, + pHandle: *mut VRInputComponentHandle_t, + ) -> EVRInputError; + fn UpdateBooleanComponent( + &self, + ulComponent: VRInputComponentHandle_t, + bNewValue: bool, + fTimeOffset: f64, + ) -> EVRInputError; + fn CreateScalarComponent( + &self, + ulContainer: PropertyContainerHandle_t, + pchName: *const c_char, + pHandle: *mut VRInputComponentHandle_t, + eType: EVRScalarType, + eUnits: EVRScalarUnits, + ) -> EVRInputError; + fn UpdateScalarComponent( + &self, + ulComponent: VRInputComponentHandle_t, + fNewValue: f32, + fTimeOffset: f64, + ) -> EVRInputError; + fn CreateHapticComponent( + &self, + ulContainer: PropertyContainerHandle_t, + pchName: *const c_char, + pHandle: *mut VRInputComponentHandle_t, + ) -> EVRInputError; + fn CreateSkeletonComponent( + &self, + ulContainer: PropertyContainerHandle_t, + pchName: *const c_char, + pchSkeletonPath: *const c_char, + pchBasePosePath: *const c_char, + eSkeletalTrackingLevel: EVRSkeletalTrackingLevel, + pGripLimitTransforms: *const VRBoneTransform_t, + unGripLimitTransformCount: u32, + pHandle: *mut VRInputComponentHandle_t, + ) -> EVRInputError; + fn UpdateSkeletonComponent( + &self, + ulComponent: VRInputComponentHandle_t, + eMotionRange: EVRSkeletalMotionRange, + pTransforms: *const VRBoneTransform_t, + unTransformCount: u32, + ) -> EVRInputError; +} +#[vtable] +pub trait IVRDriverLog { + fn Log(&self, pchLogMessage: *const c_char); +} +#[vtable] +pub trait IVRDriverManager { + fn GetDriverCount(&self) -> u32; + fn GetDriverName(&self, nDriver: DriverId_t, pchValue: *mut c_char, unBufferSize: u32) -> u32; + fn GetDriverHandle(&self, pchDriverName: *const c_char) -> DriverHandle_t; + fn IsEnabled(&self, nDriver: DriverId_t) -> bool; +} +#[vtable] +pub trait IVRDriverSpatialAnchors { + fn UpdateSpatialAnchorPose( + &self, + unHandle: SpatialAnchorHandle_t, + pPose: *const SpatialAnchorDriverPose_t, + ) -> EVRSpatialAnchorError; + fn SetSpatialAnchorPoseError( + &self, + unHandle: SpatialAnchorHandle_t, + eError: EVRSpatialAnchorError, + fValidDuration: f64, + ) -> EVRSpatialAnchorError; + fn UpdateSpatialAnchorDescriptor( + &self, + unHandle: SpatialAnchorHandle_t, + pchDescriptor: *const c_char, + ) -> EVRSpatialAnchorError; + fn GetSpatialAnchorPose( + &self, + unHandle: SpatialAnchorHandle_t, + pDriverPoseOut: *mut SpatialAnchorDriverPose_t, + ) -> EVRSpatialAnchorError; + fn GetSpatialAnchorDescriptor( + &self, + unHandle: SpatialAnchorHandle_t, + pchDescriptorOut: *mut c_char, + punDescriptorBufferLenInOut: *mut u32, + bDecorated: bool, + ) -> EVRSpatialAnchorError; +} +#[vtable] +pub trait IVRIOBuffer { + fn Open( + &self, + pchPath: *const c_char, + mode: EIOBufferMode, + unElementSize: u32, + unElements: u32, + pulBuffer: *const c_void, + ) -> EIOBufferError; + fn Close(&self, ulBuffer: IOBufferHandle_t) -> EIOBufferError; + fn Read( + &self, + ulBuffer: IOBufferHandle_t, + pDst: *mut c_void, + unBytes: u32, + punRead: *mut u32, + ) -> EIOBufferError; + fn Write(&self, ulBuffer: IOBufferHandle_t, pSrc: *mut c_void, unBytes: u32) -> EIOBufferError; + fn PropertyContainer(&self, ulBuffer: IOBufferHandle_t) -> PropertyContainerHandle_t; + fn HasReaders(&self, ulBuffer: IOBufferHandle_t) -> bool; +} +#[vtable] +pub trait IVRProperties { + fn ReadPropertyBatch( + &self, + ulContainerHandle: PropertyContainerHandle_t, + pBatch: *mut PropertyRead_t, + unBatchEntryCount: u32, + ) -> ETrackedPropertyError; + fn WritePropertyBatch( + &self, + ulContainerHandle: PropertyContainerHandle_t, + pBatch: *mut PropertyWrite_t, + unBatchEntryCount: u32, + ) -> ETrackedPropertyError; + fn GetPropErrorNameFromEnum(&self, error: ETrackedPropertyError) -> *const c_char; + fn TrackedDeviceToPropertyContainer( + &self, + nDevice: TrackedDeviceIndex_t, + ) -> PropertyContainerHandle_t; +} +#[vtable] +pub trait IVRResources { + fn LoadSharedResource( + &self, + pchResourceName: *const c_char, + pchBuffer: *mut c_char, + unBufferLen: u32, + ) -> u32; + fn GetResourceFullPath( + &self, + pchResourceName: *const c_char, + pchResourceTypeDirectory: *const c_char, + pchPathBuffer: *mut c_char, + unBufferLen: u32, + ) -> u32; +} +#[vtable] +pub trait IVRServerDriverHost { + fn TrackedDeviceAdded( + &self, + pchDeviceSerialNumber: *const c_char, + eDeviceClass: ETrackedDeviceClass, + pDriver: *const VtableRef, + ) -> bool; + fn TrackedDevicePoseUpdated( + &self, + unWhichDevice: u32, + newPose: *const DriverPose_t, + unPoseStructSize: u32, + ); + fn VsyncEvent(&self, vsyncTimeOffsetSeconds: f64); + fn VendorSpecificEvent( + &self, + unWhichDevice: u32, + eventType: EVREventType, + eventData: *const VREvent_Data_t, + eventTimeOffset: f64, + ); + fn IsExiting(&self) -> bool; + fn PollNextEvent(&self, pEvent: *mut VREvent_t, uncbVREvent: u32) -> bool; + fn GetRawTrackedDevicePoses( + &self, + fPredictedSecondsFromNow: f32, + pTrackedDevicePoseArray: *mut TrackedDevicePose_t, + unTrackedDevicePoseArrayCount: u32, + ); + fn RequestRestart( + &self, + pchLocalizedReason: *const c_char, + pchExecutableToStart: *const c_char, + pchArguments: *const c_char, + pchWorkingDirectory: *const c_char, + ); + fn GetFrameTimings(&self, pTiming: *mut Compositor_FrameTiming, nFrames: u32) -> u32; + fn SetDisplayEyeToHead( + &self, + unWhichDevice: u32, + eyeToHeadLeft: *const HmdMatrix34_t, + eyeToHeadRight: *const HmdMatrix34_t, + ); + fn SetDisplayProjectionRaw( + &self, + unWhichDevice: u32, + eyeLeft: *const HmdRect2_t, + eyeRight: *const HmdRect2_t, + ); + fn SetRecommendedRenderTargetSize(&self, unWhichDevice: u32, nWidth: u32, nHeight: u32); +} +#[vtable] +pub trait IVRSettings { + fn GetSettingsErrorNameFromEnum(&self, eError: EVRSettingsError) -> *const c_char; + fn SetBool( + &self, + pchSection: *const c_char, + pchSettingsKey: *const c_char, + bValue: bool, + peError: *mut EVRSettingsError, + ); + fn SetInt32( + &self, + pchSection: *const c_char, + pchSettingsKey: *const c_char, + nValue: i32, + peError: *mut EVRSettingsError, + ); + fn SetFloat( + &self, + pchSection: *const c_char, + pchSettingsKey: *const c_char, + flValue: f32, + peError: *mut EVRSettingsError, + ); + fn SetString( + &self, + pchSection: *const c_char, + pchSettingsKey: *const c_char, + pchValue: *const c_char, + peError: *mut EVRSettingsError, + ); + fn GetBool( + &self, + pchSection: *const c_char, + pchSettingsKey: *const c_char, + peError: *mut EVRSettingsError, + ) -> bool; + fn GetInt32( + &self, + pchSection: *const c_char, + pchSettingsKey: *const c_char, + peError: *mut EVRSettingsError, + ) -> i32; + fn GetFloat( + &self, + pchSection: *const c_char, + pchSettingsKey: *const c_char, + peError: *mut EVRSettingsError, + ) -> f32; + fn GetString( + &self, + pchSection: *const c_char, + pchSettingsKey: *const c_char, + pchValue: *mut c_char, + unValueLen: u32, + peError: *mut EVRSettingsError, + ); + fn RemoveSection(&self, pchSection: *const c_char, peError: *mut EVRSettingsError); + fn RemoveKeyInSection( + &self, + pchSection: *const c_char, + pchSettingsKey: *const c_char, + peError: *mut EVRSettingsError, + ); +} +#[vtable] +pub trait IVRVirtualDisplay { + fn Present(&self, pPresentInfo: *const PresentInfo_t, unPresentInfoSize: u32); + fn WaitForPresent(&self); + fn GetTimeSinceLastVsync( + &self, + pfSecondsSinceLastVsync: *mut f32, + pulFrameCounter: *mut u64, + ) -> bool; +} +#[vtable] +pub trait IVRWatchdogHost { + fn WatchdogWakeUp(&self, eDeviceClass: ETrackedDeviceClass); +} +#[vtable] +pub trait IVRWatchdogProvider { + fn Init(&self, pDriverContext: *const VtableRef) -> EVRInitError; + fn Cleanup(&self); +} diff --git a/src/openvr/mod_rs.jsonnet b/src/openvr/mod_rs.jsonnet new file mode 100644 index 0000000..b573355 --- /dev/null +++ b/src/openvr/mod_rs.jsonnet @@ -0,0 +1,151 @@ +local api = import './openvr.json'; + +local + groupBy(field, array) = + local set = std.set(std.map(function(e) e[field], array)); + { + [key]: std.filter(function(e) e[field] == key, array) for key in set + }; + +local + blacklistConsts = {k_InterfaceVersions: null}, + blacklistFields = { + TrackedControllerRole_Max: null, + k_EButton_SteamVR_Touchpad: null, k_EButton_SteamVR_Trigger: null, + k_EButton_Dashboard_Back: null, + k_EButton_IndexController_A: null, k_EButton_IndexController_B: null, k_EButton_IndexController_JoyStick: null, + VRSkeletalTrackingLevel_Count: null, VRSkeletalTrackingLevel_Max: null, + }, + fixedTypes = { + void: "c_void", + uint64_t: "u64", + uint32_t: "u32", + uint16_t: "u16", + uint8_t: "u8", + int32_t: "i32", + int: "i32", + float: "f32", + double: "f64", + char: "c_char", + "unsigned short": "u16", + _Bool: "bool", + + 'vr::IOBufferHandle_t *': '*const c_void', + 'ID3D12Resource *': '*const c_void', + 'ID3D12CommandQueue *': '*const c_void', + + 'uint32_t (*)[2]': '*mut [u32; 2]', + 'const vr::IVRDriverDirectModeComponent::SubmitLayerPerEye_t (&)[2]': '*const c_void', + + 'const vr::IVRDriverDirectModeComponent::SwapTextureSetDesc_t *': '*const c_void', + 'vr::IVRDriverDirectModeComponent::SwapTextureSet_t *': '*mut c_void', + }, + unions = { + 'VREvent_Data_t': 'Union0', + }; + +local + cleanupDefName(name_) = + local name = std.stripChars(name_, " "); + if std.startsWith(name, "vr::") then cleanupDefName(name) + else name, + fixTypeName_(typ_) = + local typ = std.stripChars(typ_, " "); + if std.get(fixedTypes, typ) != null then fixedTypes[typ] + else if std.startsWith(typ, "vr::") then fixTypeName_(typ[4:]) + else if std.startsWith(typ, "const ") && (std.endsWith(typ, "*") || std.endsWith(typ, "&")) then "*const %s" % fixTypeName_(typ[5:std.length(typ) - 1]) + else if std.endsWith(typ, "*const") then "*const %s" % fixTypeName_(typ[:std.length(typ) - 6]) + else if std.endsWith(typ, "*") then "*mut %s" % fixTypeName_(typ[:std.length(typ) - 1]) + else if std.endsWith(typ, "&") then "*mut %s" % fixTypeName_(typ[:std.length(typ) - 1]) + else if std.endsWith(typ, "]") then local poss = std.findSubstr("[", typ), pos = poss[std.length(poss)-1]; + "[%s; %s]" % [ + fixTypeName_(typ[:pos]), + typ[pos+1:std.length(typ) - 1], + ] + else typ, + fixTypeName(typ_) = + local typ = fixTypeName_(typ_); + assert std.type(typ) == "string" : "%s => %s" % [ typ_, typ ]; + if std.startsWith(typ, "*mut I") then "*const VtableRef<%sVtable>" % typ[5:] + else typ, + + fixFieldName(field) = + if field == "type" then "typ" else field; + +local + makeTypeDef(typ) = + local type = fixTypeName(typ.type); + "pub type %s = %s;" % [ + cleanupDefName(typ.typedef), + if std.startsWith(type, "union ") then unions[type[6:]] + else if type == "&()" then "*const c_void" + else type, + ], + makeEnumValue(val) = + if val.value != null then "\t%s = %s," % [val.name, val.value] + else "\t%s," % val.name, + makeEnumDef(enum) = + ("#[derive(Clone, Copy, PartialEq, Eq, Debug)]\n#[repr(i32)]\npub enum %s {\n" % cleanupDefName(enum.enumname)) + + std.join("\n", std.map(makeEnumValue, std.filter(function(value) std.get(blacklistFields, value.name, false) == false, enum.values))) + + "\n}", + makeConst(const) = + assert const.consttype[0:6] == "const "; + (if const.constname in blacklistConsts then "// " else "") + + if const.consttype == "const char *const" || const.consttype == "const char *" then + "pub const %s: *const c_char = real_c_string!(\"%s\");" % [const.constname, const.constval] + else + "pub const %s: %s = %s;" % [const.constname, fixTypeName(const.consttype[6:]), const.constval], + makeStructField(field) = + "\tpub %s: %s," % [fixFieldName(field.fieldname), fixTypeName(field.fieldtype)], + makeStruct(struct) = + (if struct.struct == "vr::(anonymous)" then "/*" else "") + + ("#[derive(Clone, Copy)]\n#[repr(C)]\npub struct %s {\n" % cleanupDefName(struct.struct)) + + std.join("\n", std.map(makeStructField, struct.fields)) + + "\n}" + + (if struct.struct == "vr::(anonymous)" then "*/" else ""), + makeParam(param) = + "%s: %s" % [fixFieldName(param.paramname), fixTypeName(param.paramtype)], + makeMethod(method) = + local params = std.get(method, "params", []); + "\tfn %s(&self%s)%s;" % [ + method.methodname, + if std.length(params) == 0 then "" else ", " + std.join(", ", std.map(makeParam, method.params)), + local ret = fixTypeName(method.returntype); if ret == "c_void" then "" else " -> %s" % ret, + ], + makeClass(name, methods) = + ("#[vtable]\npub trait %s {\n" % cleanupDefName(name)) + + std.join("\n", std.map(makeMethod, methods)) + + "\n}", + makeUnionValue(value) = + "\t%s: %s," % [fixFieldName(value.fieldname), fixTypeName(value.fieldtype)], + makeUnion(union) = + ("#[derive(Clone, Copy)]\npub union %s {\n" % cleanupDefName(union.name)) + + std.join("\n", std.map(makeUnionValue, union.values)) + + "\n}"; + +||| + #![allow( + non_camel_case_types, + dead_code, + non_snake_case, + non_upper_case_globals + )] + + use cppvtbl::{vtable, VtableRef}; + use real_c_string::real_c_string; + use std::ffi::c_void; + use std::os::raw::c_char; + + // Graphic api stubs + type VkDevice_T = (); + type VkInstance_T = (); + type VkQueue_T = (); + type VkPhysicalDevice_T = (); + +||| + +std.join('\n', std.map(makeUnion, std.makeArray(std.length(api.unions), function(i) api.unions[i] {name: 'Union%d' % i}))) + '\n' + +std.join('\n', std.map(makeTypeDef, api.typedefs)) + '\n' + +std.join('\n', std.map(makeEnumDef, api.enums)) + '\n' + +std.join('\n', std.map(makeConst, api.consts)) + '\n' + +std.join('\n', std.map(makeStruct, api.structs)) + '\n' + +std.join('\n', std.objectValues(std.mapWithKey(makeClass, groupBy('classname', std.filter(function(m) !std.startsWith(m.classname, "C"), api.methods))))) diff --git a/src/server_tracked_provider.rs b/src/server_tracked_provider.rs new file mode 100644 index 0000000..177d410 --- /dev/null +++ b/src/server_tracked_provider.rs @@ -0,0 +1,71 @@ +use std::os::raw::c_char; + +use crate::{ + driver_context::{get_driver_context, try_init_driver_context}, + factory::get_hmd_driver_factory, + Result, +}; +use cppvtbl::{impl_vtables, HasVtable, VtableRef, WithVtables}; +use once_cell::sync::OnceCell; +use tracing::info; + +use crate::openvr::{ + EVRInitError, IServerTrackedDeviceProvider, IServerTrackedDeviceProviderVtable, + IServerTrackedDeviceProvider_Version, IVRDriverContextVtable, +}; + +#[impl_vtables(IServerTrackedDeviceProvider)] +pub struct ServerTrackedProvider { + real: &'static VtableRef, +} +impl IServerTrackedDeviceProvider for ServerTrackedProvider { + fn Init( + &self, + pDriverContext: *const cppvtbl::VtableRef, + ) -> EVRInitError { + let _ = try_init_driver_context(unsafe { &*pDriverContext }); + let context = get_driver_context().expect("context just initialized"); + self.real.Init( + VtableRef::into_raw(HasVtable::::get(context)) as *const _, + ) + } + + fn Cleanup(&self) { + self.real.Cleanup() + } + + fn GetInterfaceVersions(&self) -> *const *const c_char { + self.real.GetInterfaceVersions() + } + + fn RunFrame(&self) { + self.real.RunFrame() + } + + fn ShouldBlockStandbyMode(&self) -> bool { + self.real.ShouldBlockStandbyMode() + } + + fn EnterStandby(&self) { + self.real.EnterStandby() + } + + fn LeaveStandby(&self) { + self.real.LeaveStandby() + } +} + +static SERVER_TRACKED_DEVICE_PROVIDER: OnceCell> = + OnceCell::new(); +pub fn get_server_tracked_provider() -> Result<&'static WithVtables> { + SERVER_TRACKED_DEVICE_PROVIDER.get_or_try_init(|| { + info!("intializing server tracker provider"); + let real = unsafe { + let factory = get_hmd_driver_factory()?; + try_vr!(factory(IServerTrackedDeviceProvider_Version))? + }; + Ok(WithVtables::new(ServerTrackedProvider { + real: unsafe { VtableRef::from_raw(real as *const _) }, + })) as Result<_> + }) +} diff --git a/src/settings.rs b/src/settings.rs new file mode 100644 index 0000000..d64d2b7 --- /dev/null +++ b/src/settings.rs @@ -0,0 +1,65 @@ +use std::{marker::PhantomData, os::raw::c_char}; + +use cppvtbl::VtableRef; +use once_cell::sync::OnceCell; +use tracing::{error, instrument}; + +use crate::driver_context::get_driver_context; +use crate::openvr::{EVRSettingsError, IVRSettings, IVRSettingsVtable, IVRSettings_Version}; +use crate::Result; + +#[derive(Debug)] +pub struct Setting(*const c_char, *const c_char, PhantomData); +impl Setting { + pub const fn unsafe_new(section: *const c_char, name: *const c_char) -> Self { + Self(section, name, PhantomData) + } +} +macro_rules! impl_setting { + ($ty:ty, $get_meth:ident, $set_meth:ident, $default:expr) => { + #[allow(dead_code)] + impl Setting<$ty> { + #[instrument] + pub fn get(&self) -> $ty { + let err: Result<()> = try { + let settings = get_settings()?; + let mut err = EVRSettingsError::VRSettingsError_None; + return settings.$get_meth(self.0, self.1, &mut err); + }; + error!("failed: {}", err.err().unwrap()); + $default + } + #[instrument] + pub fn set(&self, value: $ty) { + let err: Result<()> = try { + let settings = get_settings()?; + let mut err = EVRSettingsError::VRSettingsError_None; + settings.$set_meth(self.0, self.1, value, &mut err); + return; + }; + error!("failed: {}", err.err().unwrap()); + } + } + }; +} +impl_setting!(i32, GetInt32, SetInt32, 0); +impl_setting!(bool, GetBool, SetBool, false); + +#[macro_export] +macro_rules! setting { + ($section:expr, $name:expr) => { + crate::settings::Setting::unsafe_new( + ::real_c_string::real_c_string!($section), + ::real_c_string::real_c_string!($name), + ) + }; +} + +static SETTINGS: OnceCell<&'static VtableRef> = OnceCell::new(); +pub fn get_settings() -> Result<&'static &'static VtableRef> { + SETTINGS.get_or_try_init(|| { + let ctx = get_driver_context()?; + let raw = ctx.get_generic_interface(IVRSettings_Version)?; + Ok(unsafe { VtableRef::from_raw(raw as *const VtableRef) }) + }) +} diff --git a/vivectl/.envrc b/vivectl/.envrc deleted file mode 100644 index feae7f4..0000000 --- a/vivectl/.envrc +++ /dev/null @@ -1,3 +0,0 @@ -source_url "https://raw.githubusercontent.com/nix-community/nix-direnv/1.2.3/direnvrc" "sha256-/aHqL/6nLpHcZJcB5/7/5+mO338l28uFbq88DMfWJn4=" - -use flake diff --git a/vivectl/.gitignore b/vivectl/.gitignore deleted file mode 100644 index 1de5659..0000000 --- a/vivectl/.gitignore +++ /dev/null @@ -1 +0,0 @@ -target \ No newline at end of file diff --git a/vivectl/Cargo.lock b/vivectl/Cargo.lock deleted file mode 100644 index 81f6ae5..0000000 --- a/vivectl/Cargo.lock +++ /dev/null @@ -1,297 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "anyhow" -version = "1.0.53" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94a45b455c14666b85fc40a019e8ab9eb75e3a124e05494f5397122bc9eb06e0" - -[[package]] -name = "atty" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" -dependencies = [ - "hermit-abi", - "libc", - "winapi", -] - -[[package]] -name = "autocfg" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" - -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - -[[package]] -name = "cc" -version = "1.0.72" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22a9137b95ea06864e018375b72adfb7db6e6f68cfc8df5a04d00288050485ee" - -[[package]] -name = "clap" -version = "3.0.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08799f92c961c7a1cf0cc398a9073da99e21ce388b46372c37f3191f2f3eed3e" -dependencies = [ - "atty", - "bitflags", - "clap_derive", - "indexmap", - "lazy_static", - "os_str_bytes", - "strsim", - "termcolor", - "textwrap", -] - -[[package]] -name = "clap_derive" -version = "3.0.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fd2078197a22f338bd4fbf7d6387eb6f0d6a3c69e6cbc09f5c93e97321fd92a" -dependencies = [ - "heck", - "proc-macro-error", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "hashbrown" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" - -[[package]] -name = "heck" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" - -[[package]] -name = "hermit-abi" -version = "0.1.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" -dependencies = [ - "libc", -] - -[[package]] -name = "hex-literal" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ebdb29d2ea9ed0083cd8cece49bbd968021bd99b0849edb4a9a7ee0fdf6a4e0" - -[[package]] -name = "hidapi" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c4cc7279df8353788ac551186920e44959d5948aec404be02b28544a598bce" -dependencies = [ - "cc", - "libc", - "pkg-config", -] - -[[package]] -name = "indexmap" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "282a6247722caba404c065016bbfa522806e51714c34f5dfc3e4a3a46fcb4223" -dependencies = [ - "autocfg", - "hashbrown", -] - -[[package]] -name = "lazy_static" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" - -[[package]] -name = "libc" -version = "0.2.115" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a8d982fa7a96a000f6ec4cfe966de9703eccde29750df2bb8949da91b0e818d" - -[[package]] -name = "memchr" -version = "2.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" - -[[package]] -name = "os_str_bytes" -version = "6.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e22443d1643a904602595ba1cd8f7d896afe56d26712531c5ff73a15b2fbf64" -dependencies = [ - "memchr", -] - -[[package]] -name = "pkg-config" -version = "0.3.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58893f751c9b0412871a09abd62ecd2a00298c6c83befa223ef98c52aef40cbe" - -[[package]] -name = "proc-macro-error" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" -dependencies = [ - "proc-macro-error-attr", - "proc-macro2", - "quote", - "syn", - "version_check", -] - -[[package]] -name = "proc-macro-error-attr" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" -dependencies = [ - "proc-macro2", - "quote", - "version_check", -] - -[[package]] -name = "proc-macro2" -version = "1.0.36" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029" -dependencies = [ - "unicode-xid", -] - -[[package]] -name = "quote" -version = "1.0.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "864d3e96a899863136fc6e99f3d7cae289dafe43bf2c5ac19b70df7210c0a145" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "strsim" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" - -[[package]] -name = "syn" -version = "1.0.86" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a65b3f4ffa0092e9887669db0eae07941f023991ab58ea44da8fe8e2d511c6b" -dependencies = [ - "proc-macro2", - "quote", - "unicode-xid", -] - -[[package]] -name = "termcolor" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4" -dependencies = [ - "winapi-util", -] - -[[package]] -name = "textwrap" -version = "0.14.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0066c8d12af8b5acd21e00547c3797fde4e8677254a7ee429176ccebbe93dd80" - -[[package]] -name = "thiserror" -version = "1.0.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417" -dependencies = [ - "thiserror-impl", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "unicode-xid" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" - -[[package]] -name = "version_check" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" - -[[package]] -name = "vivectl" -version = "0.1.0" -dependencies = [ - "anyhow", - "clap", - "hex-literal", - "hidapi", - "thiserror", -] - -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - -[[package]] -name = "winapi-util" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" -dependencies = [ - "winapi", -] - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/vivectl/flake.lock b/vivectl/flake.lock deleted file mode 100644 index 59e4203..0000000 --- a/vivectl/flake.lock +++ /dev/null @@ -1,93 +0,0 @@ -{ - "nodes": { - "flake-utils": { - "locked": { - "lastModified": 1642700792, - "narHash": "sha256-XqHrk7hFb+zBvRg6Ghl+AZDq03ov6OshJLiSWOoX5es=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "846b2ae0fc4cc943637d3d1def4454213e203cba", - "type": "github" - }, - "original": { - "owner": "numtide", - "repo": "flake-utils", - "type": "github" - } - }, - "flake-utils_2": { - "locked": { - "lastModified": 1637014545, - "narHash": "sha256-26IZAc5yzlD9FlDT54io1oqG/bBoyka+FJk5guaX4x4=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "bba5dcc8e0b20ab664967ad83d24d64cb64ec4f4", - "type": "github" - }, - "original": { - "owner": "numtide", - "repo": "flake-utils", - "type": "github" - } - }, - "nixpkgs": { - "locked": { - "lastModified": 1643332957, - "narHash": "sha256-1Dj9EwKeAGdnyyHyttwbstvT6R2yNP8DnS6h1hwcoes=", - "owner": "nixos", - "repo": "nixpkgs", - "rev": "ab14cf224f7f076ea92dae1519750178eb0dcecd", - "type": "github" - }, - "original": { - "owner": "nixos", - "repo": "nixpkgs", - "type": "github" - } - }, - "nixpkgs_2": { - "locked": { - "lastModified": 1637453606, - "narHash": "sha256-Gy6cwUswft9xqsjWxFYEnx/63/qzaFUwatcbV5GF/GQ=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "8afc4e543663ca0a6a4f496262cd05233737e732", - "type": "github" - }, - "original": { - "owner": "NixOS", - "ref": "nixpkgs-unstable", - "repo": "nixpkgs", - "type": "github" - } - }, - "root": { - "inputs": { - "flake-utils": "flake-utils", - "nixpkgs": "nixpkgs", - "rust-overlay": "rust-overlay" - } - }, - "rust-overlay": { - "inputs": { - "flake-utils": "flake-utils_2", - "nixpkgs": "nixpkgs_2" - }, - "locked": { - "lastModified": 1642838864, - "narHash": "sha256-pHnhm3HWwtvtOK7NdNHwERih3PgNlacrfeDwachIG8E=", - "owner": "oxalica", - "repo": "rust-overlay", - "rev": "9fb49daf1bbe1d91e6c837706c481f9ebb3d8097", - "type": "github" - }, - "original": { - "owner": "oxalica", - "repo": "rust-overlay", - "type": "github" - } - } - }, - "root": "root", - "version": 7 -} diff --git a/vivectl/flake.nix b/vivectl/flake.nix deleted file mode 100644 index b7a3382..0000000 --- a/vivectl/flake.nix +++ /dev/null @@ -1,33 +0,0 @@ -{ - description = "VIVE Pro 2 support for linux"; - inputs = { - nixpkgs.url = "github:nixos/nixpkgs"; - flake-utils.url = "github:numtide/flake-utils"; - rust-overlay.url = "github:oxalica/rust-overlay"; - }; - outputs = { self, nixpkgs, flake-utils, rust-overlay }: - flake-utils.lib.eachDefaultSystem (system: - let - pkgs = import nixpkgs - { - inherit system; - overlays = [ rust-overlay.overlay ]; - }; - rust = ((pkgs.buildPackages.rustChannelOf { date = "2022-01-13"; channel = "nightly"; }).default.override { - extensions = [ "rust-src" ]; - }); - in - rec { - devShell = pkgs.mkShell { - nativeBuildInputs = with pkgs;[ - rust - cargo-edit - hidapi - udev - libusb - pkg-config - ]; - }; - } - ); -} diff --git a/vivectl/src/main.rs b/vivectl/src/main.rs deleted file mode 100644 index b78c122..0000000 --- a/vivectl/src/main.rs +++ /dev/null @@ -1,275 +0,0 @@ -use anyhow::{bail, Context, Result}; -use clap::{ArgEnum, Parser}; -use hex_literal::hex; -use hidapi::{HidApi, HidDevice}; -use std::str::FromStr; - -fn send_str_report(handle: &HidDevice, is_alt: bool, report: &[u8]) -> Result<()> { - let mut buf = [0u8; 64]; - buf[0] = 4; - buf[1] = if is_alt { 0x71 } else { 0x70 }; - buf[2] = 0x29; - buf[3] = report.len() as u8; - buf[4..][..report.len()].copy_from_slice(report); - handle.send_feature_report(&buf)?; - Ok(()) -} -// wireless,0 - -fn send_magic_report(handle: &HidDevice, report: &[u8]) -> Result<()> { - let mut buf = [0u8; 64]; - buf[0..][..report.len()].copy_from_slice(report); - handle.send_feature_report(&buf)?; - Ok(()) -} -// Unknown magic requests: -// 0478293808000000000000000000000100000000000000000000000000000000 -// 0000000000000000000000000000000000000000000000000000000000000000 -// -// 0478293801000000000000000100000000000000000000000000000000000000 -// 0000000000000000000000000000000000000000000000000000000000000000 - -/// Unused, as there is no useful (known) information here (only edid vid/pid) -/// Often called by official software, maybe used as ping? -fn recv_report(handle: &HidDevice) -> Result<[u8; 64]> { - let mut buf = [0u8; 64]; - buf[0] = 4; - handle.get_feature_report(&mut buf)?; - Ok(buf) -} - -fn toggle_mic_noise_cancel(device: &HidDevice, enabled: bool) -> Result<()> { - if enabled { - send_str_report(&device, true, b"codecreg=9c9,80")?; - send_str_report(&device, true, b"codecreg=9c8,a5")?; - send_str_report(&device, true, b"codecreg=9d0,a4")?; - send_str_report(&device, true, b"codecreg=1c008f,1")?; - send_str_report(&device, true, b"codecreg=1c0005,9")?; - send_str_report(&device, true, b"codecreg=1c0005,8000")?; - } else { - send_str_report(&device, true, b"codecreg=9c9,8c")?; - send_str_report(&device, true, b"codecreg=9c8,a4")?; - send_str_report(&device, true, b"codecreg=9d0,0")?; - send_str_report(&device, true, b"codecreg=1c008f,0")?; - send_str_report(&device, true, b"codecreg=1c0005,9")?; - send_str_report(&device, true, b"codecreg=1c0005,8000")?; - } - Ok(()) -} - -struct Brightness(u8); -impl FromStr for Brightness { - type Err = anyhow::Error; - fn from_str(s: &str) -> Result { - let v: u8 = u8::from_str(s).context("failed to parse brightness")?; - if v > 130 { - bail!("max brightness = 130") - } - Ok(Self(v)) - } -} -fn set_brightness(device: &HidDevice, brightness: Brightness) -> Result<()> { - send_str_report( - &device, - false, - format!("setbrightness,{}", brightness.0).as_bytes(), - )?; - Ok(()) -} - -#[derive(Clone, Copy, ArgEnum)] -enum LedState { - /// Bright green - On, - /// Green - Sleep, -} -impl LedState { - fn magic(&self) -> [u8; 64] { - match self { - Self::On => hex! {" - 0478293800000000000002000000000000000000000000000000000000000000 - 000000000000000000000000007a000000000000000000000000000000000000 - "}, - Self::Sleep => hex! {" - 0478293800000000000002000000000000000000000000000000000000000000 - 000000000000000000000000007b000000000000000000000000000000000000 - // ^- vive console also sends c here, but i see no difference between b and c - // perhaps brightness, but hardware only supports 2 levels? - "}, - // Also used on bootup, i see no effect - // Self::Idk => hex!(" - // 0478293800000000000000000000000000000000000000000000000000000000 - // 0000000000000000000000000000000000000000000000000000000000000000 - // ") - } - } -} -fn set_led(device: &HidDevice, state: LedState) -> Result<()> { - send_magic_report(&device, &state.magic())?; - Ok(()) -} - -fn reset_dp(device: &HidDevice) -> Result<()> { - send_str_report(device, false, b"chipreset")?; - Ok(()) -} - -/// Hardcoded in official software too -#[derive(Clone, Copy, ArgEnum)] -#[repr(u8)] -enum Resolution { - R2448x1224f90 = 0, - R2448x1224f120 = 1, - R3264x1632f90 = 2, - R3680x1836f90 = 3, - R4896x2448f90 = 4, - R4896x2448f120 = 5, -} - -fn set_resolution(device: &HidDevice, resolution: Resolution) -> Result<()> { - // If not sent - something is wrong - send_str_report(&device, false, b"wireless,0")?; - send_str_report( - &device, - false, - &format!("dtd,{}", resolution as u8).as_bytes(), - )?; - Ok(()) -} - -fn set_mode(device: &HidDevice, mst: bool, dsc: bool, amdgpu: bool) -> Result<()> { - send_str_report( - &device, - false, - &format!( - "mode,{},{},{}", - if mst { '1' } else { '0' }, - if dsc { '1' } else { '0' }, - if amdgpu { '1' } else { '0' } - ) - .as_bytes(), - ) -} - -#[derive(Clone, Copy, ArgEnum)] -enum NoiseCancelState { - Disable, - Enable, -} - -#[derive(Parser)] -#[clap(author, version)] -enum Args { - /// Reconnect HMD - ResetDp, - /// Restart HMD with new reported resolution - Mode { - /// Multi-stream-transport - #[clap(long)] - mst: bool, - /// Display stream compression - #[clap(long)] - dsc: bool, - /// ? - #[clap(long)] - amdgpu: bool, - #[clap(arg_enum)] - resolution: Resolution, - }, - /// Change display brightness - SetBrightness { - #[clap(parse(try_from_str))] - value: Brightness, - }, - /// Enable/disable microphone noise cancellation - NoiseCancel { - #[clap(arg_enum)] - state: NoiseCancelState, - }, - Led { - #[clap(arg_enum)] - state: LedState, - }, - Payload { - #[clap(long)] - alt: bool, - value: String, - }, - /// Testing only, performs full initialization sequence (captured on windows) - Magic, -} - -fn main() -> Result<()> { - let args = Args::parse(); - let manager = HidApi::new()?; - let device = manager.open(0x0bb4, 0x0342)?; - match args { - Args::ResetDp => reset_dp(&device)?, - Args::Mode { - resolution, - mst, - dsc, - amdgpu, - } => { - set_mode(&device, mst, dsc, amdgpu)?; - set_resolution(&device, resolution)?; - // set_mode does strage things without DP reset - reset_dp(&device)?; - // TODO: Wait for device to reappear? - } - Args::SetBrightness { value } => { - set_brightness(&device, value)?; - } - Args::NoiseCancel { state } => { - toggle_mic_noise_cancel(&device, matches!(state, NoiseCancelState::Enable))?; - } - Args::Led { state } => { - set_led(&device, state)?; - } - Args::Payload { alt, value } => send_str_report(&device, alt, value.as_bytes())?, - Args::Magic => { - send_magic_report( - &device, - &hex! {" - 0478293801000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - "}, - )?; - send_magic_report( - &device, - &hex! {" - 0478293801000000000000000100000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - "}, - )?; - send_magic_report( - &device, - &hex! {" - 04782938010000000000000001725f766976655fb2551e4d6ff1cf1188cb0011 - 11000030686463fa9b020000b8dc63fa9b020000b2551e4d6ff1cf1100000000 - "}, - )?; - set_led(&device, LedState::On)?; - set_brightness(&device, Brightness(130))?; - send_magic_report( - &device, - &hex! {" - 0478293808000000000000000000000100000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - "}, - )?; - toggle_mic_noise_cancel(&device, false)?; - send_magic_report( - &device, - &hex! {" - 0478293800000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - "}, - )?; - set_resolution(&device, Resolution::R2448x1224f90)?; - reset_dp(&device)?; - } - } - Ok(()) -}