Skip to content

Instantly share code, notes, and snippets.

@CertainLach
Created January 21, 2023 21:21
Show Gist options
  • Save CertainLach/888c4958678bee5f1736bc2ac3a5095d to your computer and use it in GitHub Desktop.
Save CertainLach/888c4958678bee5f1736bc2ac3a5095d to your computer and use it in GitHub Desktop.
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