-
-
Save CertainLach/888c4958678bee5f1736bc2ac3a5095d to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
From f34095593b6b1928c91219cda0ad505eb6110a8d Mon Sep 17 00:00:00 2001 | |
From: Yaroslav Bolyukin <iam@lach.pw> | |
Date: Sun, 14 Aug 2022 19:47:32 +0300 | |
Subject: [PATCH] feat: vive cosmos support | |
Signed-off-by: Yaroslav Bolyukin <iam@lach.pw> | |
--- | |
bin/driver-proxy/src/driver_host.rs | 6 -- | |
bin/driver-proxy/src/hmd.rs | 31 ------ | |
crates/vive-hid/src/lib.rs | 100 ++---------------- | |
dist-proxy/install.sh | 2 +- | |
flake.nix | 1 + | |
.../0001-drm-edid-non-desktop.patch | 3 +- | |
6 files changed, 11 insertions(+), 132 deletions(-) | |
diff --git a/bin/driver-proxy/src/driver_host.rs b/bin/driver-proxy/src/driver_host.rs | |
index b9f0ae4..0415947 100644 | |
--- a/bin/driver-proxy/src/driver_host.rs | |
+++ b/bin/driver-proxy/src/driver_host.rs | |
@@ -79,17 +79,11 @@ impl IVRServerDriverHost for DriverHost { | |
vive.set_brightness(brightness as u8)?; | |
} | |
- 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, | |
mode, | |
}))); | |
diff --git a/bin/driver-proxy/src/hmd.rs b/bin/driver-proxy/src/hmd.rs | |
index d71c2f0..7e81ae0 100644 | |
--- a/bin/driver-proxy/src/hmd.rs | |
+++ b/bin/driver-proxy/src/hmd.rs | |
@@ -28,7 +28,6 @@ fn map_eye(eye: EVREye) -> Eye { | |
struct HmdDisplay { | |
// steam: Rc<SteamDevice>, | |
// vive: Rc<ViveDevice>, | |
- lens: Rc<RefCell<Client>>, | |
real: &'static VtableRef<IVRDisplayComponentVtable>, | |
mode: Mode, | |
} | |
@@ -99,40 +98,12 @@ impl IVRDisplayComponent for HmdDisplay { | |
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) | |
} | |
} | |
@@ -141,7 +112,6 @@ impl IVRDisplayComponent for HmdDisplay { | |
pub struct HmdDriver { | |
// pub steam: Rc<SteamDevice>, | |
// pub vive: Rc<ViveDevice>, | |
- pub lens: Rc<RefCell<Client>>, | |
pub real: &'static VtableRef<ITrackedDeviceServerDriverVtable>, | |
pub mode: Mode, | |
} | |
@@ -168,7 +138,6 @@ impl ITrackedDeviceServerDriver for HmdDriver { | |
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 _) }, | |
mode: self.mode, | |
}))); | |
diff --git a/crates/vive-hid/src/lib.rs b/crates/vive-hid/src/lib.rs | |
index d2d3bab..a18fc9c 100644 | |
--- a/crates/vive-hid/src/lib.rs | |
+++ b/crates/vive-hid/src/lib.rs | |
@@ -133,7 +133,7 @@ impl SteamDevice { | |
} | |
const VIVE_VID: u16 = 0x0bb4; | |
-const VIVE_PID: u16 = 0x0342; | |
+const VIVE_PID: u16 = 0x0313; | |
#[derive(Deserialize, Debug)] | |
pub struct ViveConfig { | |
@@ -165,14 +165,7 @@ impl Mode { | |
} | |
} | |
-const VIVE_PRO_2_MODES: [Mode; 6] = [ | |
- Mode::new(0, 2448, 1224, 90.0), | |
- Mode::new(1, 2448, 1224, 120.0), | |
- Mode::new(2, 3264, 1632, 90.0), | |
- Mode::new(3, 3680, 1836, 90.0), | |
- Mode::new(4, 4896, 2448, 90.0), | |
- Mode::new(5, 2896, 2448, 120.0), | |
-]; | |
+const VIVE_COSMOS_MODES: [Mode; 1] = [Mode::new(0, 2880, 1700, 90.0)]; | |
pub struct ViveDevice(HidDevice); | |
impl ViveDevice { | |
@@ -226,99 +219,20 @@ impl ViveDevice { | |
out[..size].copy_from_slice(&data[strip_prefix.len() + 2..strip_prefix.len() + 2 + size]); | |
Ok(size) | |
} | |
- pub fn read_devsn(&self) -> Result<String> { | |
- 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<String> { | |
- 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<ViveConfig> { | |
- 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::<u8>::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) | |
- } | |
/// Always returns at least one mode | |
pub fn query_modes(&self) -> Vec<Mode> { | |
- VIVE_PRO_2_MODES.into_iter().collect() | |
+ VIVE_COSMOS_MODES.into_iter().collect() | |
} | |
pub fn set_mode(&self, resolution: u8) -> Result<(), Error> { | |
- self.write_feature(0x04, 0x2970, b"wireless,0")?; | |
- self.write_feature(0x04, 0x2970, format!("dtd,{}", resolution).as_bytes())?; | |
- // TODO: wait for reconnection | |
+ // Does nothing on cosmos | |
Ok(()) | |
} | |
pub fn set_brightness(&self, brightness: u8) -> Result<(), Error> { | |
- self.write_feature( | |
- 0x04, | |
- 0x2970, | |
- format!("setbrightness,{}", brightness.min(130)).as_bytes(), | |
- ) | |
+ // Does nothing on cosmos | |
+ Ok(()) | |
} | |
pub fn toggle_noise_canceling(&self, enabled: bool) -> Result<(), Error> { | |
- const ENABLE: &[&[u8]] = &[ | |
- b"codecreg=9c9,80".as_slice(), | |
- b"codecreg=9c8,a5", | |
- b"codecreg=9d0,a4", | |
- b"codecreg=1c008f,1", | |
- b"codecreg=1c0005,9", | |
- b"codecreg=1c0005,8000", | |
- ]; | |
- const DISABLE: &[&[u8]] = &[ | |
- b"codecreg=9c9,8c".as_slice(), | |
- b"codecreg=9c8,a4", | |
- b"codecreg=9d0,0", | |
- b"codecreg=1c008f,0", | |
- b"codecreg=1c0005,9", | |
- b"codecreg=1c0005,8000", | |
- ]; | |
- // I have no idea what those values mean, this is straight | |
- // copy-pasta from what original vive console sends | |
- let lines: &'static [&'static [u8]] = if enabled { ENABLE } else { DISABLE }; | |
- for line in lines { | |
- self.write_feature(0x04, 0x2971, line)?; | |
- } | |
+ // Does nothing on cosmos | |
Ok(()) | |
} | |
} | |
diff --git a/dist-proxy/install.sh b/dist-proxy/install.sh | |
index e9f9244..cf785d0 100755 | |
--- a/dist-proxy/install.sh | |
+++ b/dist-proxy/install.sh | |
@@ -8,7 +8,7 @@ SCRIPTPATH=$(dirname $SCRIPT) | |
# Patreon release contains bundled sewer, use it here | |
PATH=$SCRIPTPATH/bin:$PATH | |
-echo "SteamVR proxy driver for Vive Pro 2" | |
+echo "SteamVR proxy driver for Vive Cosmos" | |
echo "Consider supporting developer on patreon: https://patreon.com/0lach" | |
sleep 3 | |
diff --git a/flake.nix b/flake.nix | |
index a1aa29a..2fbc60d 100644 | |
--- a/flake.nix | |
+++ b/flake.nix | |
@@ -145,6 +145,7 @@ | |
installPhase = '' | |
cp -r $src/dist-proxy/ $out/ | |
chmod u+w -R $out | |
+ cp -r $src/kernel-patches/ $out/kernel-patches/ | |
mkdir $out/bin/ | |
cp ${packages.sewer}/bin/sewer $out/bin/ | |
cp ${packages.lens-server}/bin/lens-server.exe $out/lens-server/ | |
diff --git a/kernel-patches/0001-drm-edid-non-desktop.patch b/kernel-patches/0001-drm-edid-non-desktop.patch | |
index 4840b1f..e60b405 100644 | |
--- a/kernel-patches/0001-drm-edid-non-desktop.patch | |
+++ b/kernel-patches/0001-drm-edid-non-desktop.patch | |
@@ -14,9 +14,10 @@ index 12893e7be..fdb8f0a6f 100644 | |
EDID_QUIRK('V', 'L', 'V', 0x91bf, EDID_QUIRK_NON_DESKTOP), | |
- /* HTC Vive and Vive Pro VR Headsets */ | |
-+ /* HTC Vive, Vive Pro and Vive Pro 2 VR Headsets */ | |
++ /* HTC Vive OG/Pro/Cosmos/Pro 2 VR Headsets */ | |
EDID_QUIRK('H', 'V', 'R', 0xaa01, EDID_QUIRK_NON_DESKTOP), | |
EDID_QUIRK('H', 'V', 'R', 0xaa02, EDID_QUIRK_NON_DESKTOP), | |
++ EDID_QUIRK('H', 'V', 'R', 0xaa03, EDID_QUIRK_NON_DESKTOP), | |
+ EDID_QUIRK('H', 'V', 'R', 0xaa04, EDID_QUIRK_NON_DESKTOP), | |
/* Oculus Rift DK1, DK2, CV1 and Rift S VR Headsets */ | |
-- | |
2.39.0 | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment