[dependencies]
serde = { version = "1.0", features = ["derive"] }
-ron = "0.8" # Rust object notation, to load configuration files.
+# Rust object notation, to load configuration files.
+ron = "0.8"
num = "0.4"
-dirs = "5.0"
+dirs = "6.0"
anyhow = "1.0"
flexi_logger = "0.29"
nvapi = "0.1"
libc = "0.2"
-wmi = "0.13"
+wmi = "0.15"
crc = "3.2"
# libloading = "0.8"
# netcorehost = "0.15"
[dependencies.windows]
-version = "0.58"
+version = "0.59"
features = [
"Win32_Foundation",
"Win32_Security",
]
[build-dependencies]
-bindgen = "0.70"
+bindgen = "0.71"
[profile.release]
# strip = "debuginfo"
--- /dev/null
+use std::{str, time::Duration};
+
+use crate::rgb::RGB;
+
+const VID: u16 = 0x048D; // Vendor ID: Gigabyte.
+const PID: u16 = 0x5711; // Product ID.
+
+/*
+HidDeviceInfo { vendor_id: 1165, product_id: 22289 }
+name: GIGABYTE Device
+interface number: 1
+page: 65417
+usage: 204
+*/
+
+pub struct Device {
+ device: hidapi::HidDevice,
+}
+
+impl Device {
+ pub fn new(api: &hidapi::HidApi) -> anyhow::Result<Self> {
+ let d = api
+ .device_list()
+ .find(|d| d.vendor_id() == VID && d.product_id() == PID && d.usage() == 204)
+ .unwrap()
+ .open_device(api)
+ .unwrap();
+
+ let device = Device { device: d };
+
+ // Initialization?
+ let mut buffer = [0u8; 64];
+ buffer[0] = 0xCC;
+ buffer[1] = 0x60;
+ device.device.send_feature_report(&buffer)?;
+
+ Ok(device)
+ }
+
+ pub fn test_raw_data(&self) -> anyhow::Result<()> {
+ loop {
+ self.send_str(
+ "
+// cc20010000000000 000000015a00b727 610000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+// cc28ff0700000000 0000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+cc22040000000000 000000015a00b727 610000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+cc28ff0700000000 0000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+// cc23080000000000 000000015a00b727 610000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+// cc28ff0700000000 0000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+// cc24100000000000 000000015a006127 b70000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+// cc28ff0700000000 0000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+// cc25200000000000 000000015a00b727 610000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+// cc28ff0700000000 0000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+// cc26400000000000 000000015a00b727 610000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+// cc28ff0700000000 0000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+// cc27800000000000 000000015a00b727 610000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+// cc28ff0700000000 0000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+// cc91000200000000 000000015a00b727 610000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+// cc28ff0700000000 0000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+// cc92000400000000 000000015a00b727 610000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+// cc28ff0700000000 0000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+// cc34110100000000 0000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+
+cc580000392761b7 2761b72761b72761 b72761b72761b72761b72761b72761b72761b72761b72761b72761b72761b72761b72761b72761b72761b72761b70000
+// cc583900392761b7 2761b72761b72761 b72761b72761b72761b72761b72761b72761b72761b72761b72761b72761b72761b72761b72761b72761b72761b70000
+// cc587200392761b7 2761b72761b72761 b72761b72761b72761b72761b72761b72761b72761b72761b72761b72761b72761b72761b72761b72761b72761b70000
+// cc58ab00092761b7 2761b72761b70000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+
+// Arctic freezer 3
+cc620000392761b7 2761b72761b72761 b72761b72761b72761b72761b72761b72761b72761b72761b72761b72761b72761b72761b72761b72761b72761b70000
+cc623900392761b7 2761b72761b72761 b72761b72761b72761b72761b72761b72761b72761b72761b72761b72761b72761b72761b72761b72761b72761b70000
+// cc627200392761b7 2761b72761b72761 b72761b72761b72761b72761b72761b72761b72761b72761b72761b72761b72761b72761b72761b72761b72761b70000
+// cc62ab00092761b7 2761b72761b70000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")?;
+ std::thread::sleep(Duration::from_secs(1));
+ self.send_str(
+ "
+// cc20010000000000 000000015a0043ab 350000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+// cc28ff0700000000 0000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+cc22040000000000 000000015a0043ab 350000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+cc28ff0700000000 0000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+// cc23080000000000 000000015a0043ab 350000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+// cc28ff0700000000 0000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+// cc24100000000000 000000015a0035ab 430000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+// cc28ff0700000000 0000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+// cc25200000000000 000000015a0043ab 350000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+// cc28ff0700000000 0000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+// cc26400000000000 000000015a0043ab 350000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+// cc28ff0700000000 0000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+// cc27800000000000 000000015a0043ab 350000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+// cc28ff0700000000 0000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+// cc91000200000000 000000015a0043ab 350000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+// cc28ff0700000000 0000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+// cc92000400000000 000000015a0043ab 350000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+// cc28ff0700000000 0000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+// cc34110100000000 0000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+
+cc58000039ab4543 ab4543ab4543ab45 43ab4543ab4543ab4543ab4543ab4543ab4543ab4543ab4543ab4543ab4543ab4543ab4543ab4543ab4543ab45430000
+// cc58390039ab4543 ab4543ab4543ab45 43ab4543ab4543ab4543ab4543ab4543ab4543ab4543ab4543ab4543ab4543ab4543ab4543ab4543ab4543ab45430000
+// cc58720039ab4543 ab4543ab4543ab45 43ab4543ab4543ab4543ab4543ab4543ab4543ab4543ab4543ab4543ab4543ab4543ab4543ab4543ab4543ab45430000
+// cc58ab0009ab4543 ab4543ab45430000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+
+// Arctic freezer 3
+cc62000039 ab4543 ab4543 ab4543 ab4543 ab4543 ab4543 ab4543 ab4543 ab4543 ab4543 ab4543 ab4543 ab4543 ab4543 ab4543 ab4543 ab4543 ab4543 ab4543 0000
+cc62390039ab4543 ab4543ab4543ab45 43ab4543ab4543ab4543ab4543ab4543ab4543ab4543ab4543ab4543ab4543ab4543ab4543ab4543ab4543ab45430000
+// cc62720039ab4543 ab4543ab4543ab45 43ab4543ab4543ab4543ab4543ab4543ab4543ab4543ab4543ab4543ab4543ab4543ab4543ab4543ab4543ab45430000
+// cc62ab0009ab4543 ab4543ab45430000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+")?;
+ std::thread::sleep(Duration::from_secs(1));
+ }
+ }
+
+ fn line_to_bytes(line: &str) -> Vec<u8> {
+ let line = line.replace(" ", "");
+ let mut buffer = vec![0u8; line.len() / 2];
+ for i in 0..buffer.len() {
+ buffer[i] = u8::from_str_radix(&line[2 * i..2 * i + 2], 16).unwrap();
+ }
+
+ println!("buffer: {:?}", buffer);
+ buffer
+ }
+
+ fn send_str(&self, buffer: &str) -> anyhow::Result<()> {
+ println!("------");
+ for line in buffer.lines() {
+ let line = line.trim();
+ if line.is_empty() || line.starts_with("//") {
+ continue;
+ }
+
+ let buffer = Self::line_to_bytes(line);
+ self.device.send_feature_report(&buffer)?;
+ }
+ Ok(())
+ }
+
+ const NB_LEDS_PER_PACKET: usize = 19;
+
+ fn set_color_device(&self, color: &RGB, device: u8, nb_leds: usize) -> anyhow::Result<()> {
+ let nb_packets = (nb_leds - 1) / Self::NB_LEDS_PER_PACKET + 1;
+ for i in 0..nb_packets {
+ let mut buffer = [0u8; 64];
+ let nb_leds_in_packet = if i == nb_packets - 1 && nb_leds % Self::NB_LEDS_PER_PACKET > 0
+ {
+ nb_leds % Self::NB_LEDS_PER_PACKET
+ } else {
+ Self::NB_LEDS_PER_PACKET
+ };
+
+ buffer[0] = 0xCC;
+ buffer[1] = device;
+ buffer[2] = (i * Self::NB_LEDS_PER_PACKET) as u8 * 3;
+ buffer[4] = nb_leds_in_packet as u8 * 3;
+
+ for j in 0..nb_leds_in_packet {
+ buffer[5 + 3 * j] = color.green;
+ buffer[5 + 3 * j + 1] = color.red;
+ buffer[5 + 3 * j + 2] = color.blue;
+ }
+
+ // println!("BUFFER: {:?}", buffer); // Debug.
+ self.device.send_feature_report(&buffer)?;
+ }
+
+ Ok(())
+ }
+
+ fn set_color_motherboard(&self, color: &RGB) -> anyhow::Result<()> {
+ {
+ let mut buffer = [0u8; 64];
+ buffer[0] = 0xCC;
+ buffer[1] = 0x22;
+ buffer[2] = 0x04;
+
+ buffer[11] = 0x01;
+ buffer[12] = 0x5a;
+
+ buffer[14] = color.blue;
+ buffer[15] = color.green;
+ buffer[16] = color.red;
+
+ self.device.send_feature_report(&buffer)?;
+ }
+ {
+ let mut buffer = [0u8; 64];
+ buffer[0] = 0xCC;
+ buffer[1] = 0x28;
+ buffer[2] = 0xFF;
+ buffer[3] = 0x07;
+
+ self.device.send_feature_report(&buffer)?;
+ }
+
+ Ok(())
+ }
+
+ pub fn set_color(&self, color: &RGB) {
+ // Motherboard & GPU power cables.
+ self.set_color_device(color, 0x58, 19).unwrap();
+
+ // Arctic freezer 3.
+ self.set_color_device(color, 0x62, 38).unwrap();
+
+ self.set_color_motherboard(color).unwrap();
+ }
+}
impl Device {
pub fn new(api: &hidapi::HidApi) -> Self {
- let device = Device {
+ Self {
device: api.open(LIANLI_VID, LIANLI_UNI_HUB_SLINF_PID).unwrap(),
- };
-
- device
+ }
}
fn send_start_action(&self, channel_id: u8) {
+++ /dev/null
-use log::error;
-use nvapi::sys::i2c;
-
-use crate::{
- /*a770,*/ asus_aura_usb, corsair_lighting_pro, corsair_vengeance, cpu_temperature,
- intel_arc, lian_li_sl_infinity, rgb,
-};
-
-const RGB_FUSION2_GPU_REG_COLOR: u8 = 0x40;
-const RGB_FUSION2_GPU_REG_MODE: u8 = 0x88;
-
-const GIGABYTE_RTX3080TI_VISION_OC_ADDR: u8 = 0x63;
-
-pub trait Machine {
- fn set_color(&mut self, color: &rgb::RGB) {
- self.set_color_1(&color);
- self.set_color_2(&color);
- }
- fn set_color_1(&mut self, color: &rgb::RGB);
- fn set_color_2(&mut self, color: &rgb::RGB);
- fn get_gpu_tmp(&self) -> f32;
- fn get_cpu_tmp(&self) -> f32;
-}
-
-pub struct MachineJiji {
- ram: Vec<corsair_vengeance::Controller>,
- b650e_device: asus_aura_usb::Device,
- // a770: a770::A770,
- // gpu_devices: intel_arc::Devices,
- gpus: Vec<nvapi::PhysicalGpu>,
-}
-
-impl MachineJiji {
- pub fn new() -> anyhow::Result<Self> {
- let api = hidapi::HidApi::new().unwrap();
- Ok(MachineJiji {
- ram: vec![
- corsair_vengeance::Controller::new(0x19),
- corsair_vengeance::Controller::new(0x1B),
- ],
- b650e_device: asus_aura_usb::Device::new(&api, asus_aura_usb::Motherboard::Asus650e)?,
- // a770: a770::A770::new()?,
- // gpu_devices: unsafe { intel_arc::GetDevices() },
- gpus: nvapi::PhysicalGpu::enumerate()?,
- })
- }
-}
-
-impl Machine for MachineJiji {
- fn set_color_1(&mut self, color: &rgb::RGB) {
- for controller in &self.ram {
- controller.set_color(&color);
- }
- self.b650e_device.set_color(&color).unwrap();
- }
-
- fn set_color_2(&mut self, color: &rgb::RGB) {} // No color 2.
-
- fn get_gpu_tmp(&self) -> f32 {
- // unsafe { intel_arc::GetTemperature(self.gpu_devices, 0) as f32 }
- self.gpus[0].thermal_settings(None).unwrap()[0]
- .current_temperature
- .0 as f32
- }
-
- fn get_cpu_tmp(&self) -> f32 {
- cpu_temperature::read()
- }
-}
-
-// impl Drop for MachineJiji {
-// fn drop(&mut self) {
-// unsafe {
-// intel_arc::FreeDevices(self.gpu_devices);
-// }
-// }
-// }
-
-pub struct MachineLyssMetal {
- crosshair_device: asus_aura_usb::Device,
- corsair_lignting_pro: corsair_lighting_pro::Device,
- lian_li_sl_infinity: lian_li_sl_infinity::Device,
- gpus: Vec<nvapi::PhysicalGpu>,
-}
-
-impl MachineLyssMetal {
- pub fn new() -> anyhow::Result<Self> {
- let api = hidapi::HidApi::new()?;
-
- nvapi::initialize().expect("Unable to initialize nvapi (Nvidia API)");
-
- let machine = MachineLyssMetal {
- crosshair_device: asus_aura_usb::Device::new(
- &api,
- asus_aura_usb::Motherboard::AsusCrosshairVIIIHero,
- )?,
- corsair_lignting_pro: corsair_lighting_pro::Device::new(
- &api,
- &rgb::RGB {
- red: 0,
- green: 255,
- blue: 40,
- },
- ),
- lian_li_sl_infinity: lian_li_sl_infinity::Device::new(&api),
- gpus: nvapi::PhysicalGpu::enumerate()?,
- };
-
- // machine.set_mode_3080ti();
- Ok(machine)
- }
-
- // Doesn't work: "Error: NotSupported".
- // From OpenRGB, see the following files:
- // * Controllers\GigabyteRGBFusion2GPUController\GigabyteRGBFusion2GPUControllerDetect.cpp
- // * Controllers\GigabyteRGBFusion2GPUController\RGBController_GigabyteRGBFusion2GPU.cpp
- // * Controllers\GigabyteRGBFusion2GPUController\GigabyteRGBFusion2GPUController.cpp
- // * i2c_smbus\i2c_smbus_nvapi.cpp
- // Implementation of nvapi-rs: https://github.com/arcnmx/nvapi-rs/blob/master/src/gpu.rs#L645
- pub fn test_i2c(&self) {
- // Test from 'GigabyteRGBFusion2GPUControllerDetect.cpp'
- let data = [0xAB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00];
- self.gpus[0]
- .i2c_write(
- 0,
- Some(1),
- false,
- GIGABYTE_RTX3080TI_VISION_OC_ADDR,
- &[],
- &data,
- i2c::I2cSpeed::Default,
- )
- .expect("Error");
- }
-
- fn set_mode_3080ti(&self) {
- let data = [
- RGB_FUSION2_GPU_REG_MODE,
- 0x01, // Mode (1: static).
- 0x00, // Speed.
- 0x63, // Brightness max.
- 0x00, // Mistery flag.
- 0x01, // Zone.
- 0x00,
- 0x00,
- ];
- self.gpus[0]
- .i2c_write(
- 0,
- Some(1),
- false,
- GIGABYTE_RTX3080TI_VISION_OC_ADDR,
- &[],
- &data,
- i2c::I2cSpeed::Default,
- )
- .expect("Error");
- }
-
- fn set_color_3080ti(&self, color: &rgb::RGB) {
- // TODO.
- self.test_i2c();
- }
-}
-
-impl Machine for MachineLyssMetal {
- fn set_color_1(&mut self, color: &rgb::RGB) {
- self.crosshair_device.set_color(&color).unwrap();
- self.corsair_lignting_pro.set_color(&color);
- // self.set_color_3080ti(&color); // TODO.
- }
-
- fn set_color_2(&mut self, color: &rgb::RGB) {
- self.lian_li_sl_infinity.set_color(&color);
- }
-
- fn get_gpu_tmp(&self) -> f32 {
- self.gpus[0].thermal_settings(None).unwrap()[0]
- .current_temperature
- .0 as f32
- }
-
- fn get_cpu_tmp(&self) -> f32 {
- cpu_temperature::read()
- }
-}
--- /dev/null
+use crate::{asus_aura_usb, corsair_vengeance, cpu_temperature, rgb};
+
+use super::Machine;
+
+pub struct MachineJiji {
+ ram: Vec<corsair_vengeance::Controller>,
+ b650e_device: asus_aura_usb::Device,
+ // a770: a770::A770,
+ // gpu_devices: intel_arc::Devices,
+ gpus: Vec<nvapi::PhysicalGpu>,
+}
+
+impl MachineJiji {
+ pub fn new() -> anyhow::Result<Self> {
+ let api = hidapi::HidApi::new().unwrap();
+ Ok(MachineJiji {
+ ram: vec![
+ corsair_vengeance::Controller::new(0x19),
+ corsair_vengeance::Controller::new(0x1B),
+ ],
+ b650e_device: asus_aura_usb::Device::new(&api, asus_aura_usb::Motherboard::Asus650e)?,
+ // a770: a770::A770::new()?,
+ // gpu_devices: unsafe { intel_arc::GetDevices() },
+ gpus: nvapi::PhysicalGpu::enumerate()?,
+ })
+ }
+}
+
+impl Machine for MachineJiji {
+ fn set_color_1(&mut self, color: &rgb::RGB) {
+ for controller in &self.ram {
+ controller.set_color(color);
+ }
+ self.b650e_device.set_color(color).unwrap();
+ }
+
+ fn set_color_2(&mut self, color: &rgb::RGB) {} // No color 2.
+
+ fn get_gpu_tmp(&self) -> f32 {
+ // unsafe { intel_arc::GetTemperature(self.gpu_devices, 0) as f32 }
+ self.gpus[0].thermal_settings(None).unwrap()[0]
+ .current_temperature
+ .0 as f32
+ }
+
+ fn get_cpu_tmp(&self) -> f32 {
+ cpu_temperature::read()
+ }
+}
+
+// impl Drop for MachineJiji {
+// fn drop(&mut self) {
+// unsafe {
+// intel_arc::FreeDevices(self.gpu_devices);
+// }
+// }
+// }
--- /dev/null
+use nvapi::sys::i2c;
+
+use crate::{asus_aura_usb, corsair_lighting_pro, cpu_temperature, lian_li_sl_infinity, rgb};
+
+use super::Machine;
+
+pub struct MachineLyssMetal {
+ crosshair_device: asus_aura_usb::Device,
+ corsair_lignting_pro: corsair_lighting_pro::Device,
+ lian_li_sl_infinity: lian_li_sl_infinity::Device,
+ gpus: Vec<nvapi::PhysicalGpu>,
+}
+
+impl MachineLyssMetal {
+ pub fn new() -> anyhow::Result<Self> {
+ let api = hidapi::HidApi::new()?;
+
+ nvapi::initialize().expect("Unable to initialize nvapi (Nvidia API)");
+
+ let machine = Self {
+ crosshair_device: asus_aura_usb::Device::new(
+ &api,
+ asus_aura_usb::Motherboard::AsusCrosshairVIIIHero,
+ )?,
+ corsair_lignting_pro: corsair_lighting_pro::Device::new(
+ &api,
+ &rgb::RGB {
+ red: 0,
+ green: 255,
+ blue: 40,
+ },
+ ),
+ lian_li_sl_infinity: lian_li_sl_infinity::Device::new(&api),
+ gpus: nvapi::PhysicalGpu::enumerate()?,
+ };
+
+ // machine.set_mode_3080ti();
+ Ok(machine)
+ }
+
+ // Doesn't work: "Error: NotSupported".
+ // From OpenRGB, see the following files:
+ // * Controllers\GigabyteRGBFusion2GPUController\GigabyteRGBFusion2GPUControllerDetect.cpp
+ // * Controllers\GigabyteRGBFusion2GPUController\RGBController_GigabyteRGBFusion2GPU.cpp
+ // * Controllers\GigabyteRGBFusion2GPUController\GigabyteRGBFusion2GPUController.cpp
+ // * i2c_smbus\i2c_smbus_nvapi.cpp
+ // Implementation of nvapi-rs: https://github.com/arcnmx/nvapi-rs/blob/master/src/gpu.rs#L645
+ // Reference API doc: https://docs.nvidia.com/gameworks/content/gameworkslibrary/coresdk/nvapi/structNV__I2C__INFO__V3.html
+ pub fn test_i2c(&self) {
+ // Test from 'GigabyteRGBFusion2GPUControllerDetect.cpp'
+ let data = [0xAB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00];
+ self.gpus[0]
+ .i2c_write(
+ 0,
+ Some(1),
+ false,
+ super::GIGABYTE_RTX3080TI_VISION_OC_ADDR,
+ &[],
+ &data,
+ i2c::I2cSpeed::Default,
+ )
+ .expect("Error");
+ }
+
+ fn set_mode_3080ti(&self) {
+ let data = [
+ super::RGB_FUSION2_GPU_REG_MODE,
+ 0x01, // Mode (1: static).
+ 0x00, // Speed.
+ 0x63, // Brightness max.
+ 0x00, // Mistery flag.
+ 0x01, // Zone.
+ 0x00,
+ 0x00,
+ ];
+ self.gpus[0]
+ .i2c_write(
+ 0,
+ Some(1),
+ false,
+ super::GIGABYTE_RTX3080TI_VISION_OC_ADDR,
+ &[],
+ &data,
+ i2c::I2cSpeed::Default,
+ )
+ .expect("Error");
+ }
+
+ fn set_color_3080ti(&self, color: &rgb::RGB) {
+ // TODO.
+ self.test_i2c();
+ }
+}
+
+impl Machine for MachineLyssMetal {
+ fn set_color_1(&mut self, color: &rgb::RGB) {
+ self.crosshair_device.set_color(color).unwrap();
+ self.corsair_lignting_pro.set_color(color);
+ // self.set_color_3080ti(&color); // TODO.
+ }
+
+ fn set_color_2(&mut self, color: &rgb::RGB) {
+ self.lian_li_sl_infinity.set_color(color);
+ }
+
+ fn get_gpu_tmp(&self) -> f32 {
+ self.gpus[0].thermal_settings(None).unwrap()[0]
+ .current_temperature
+ .0 as f32
+ }
+
+ fn get_cpu_tmp(&self) -> f32 {
+ cpu_temperature::read()
+ }
+}
--- /dev/null
+use nvapi::sys::i2c;
+
+use crate::{
+ corsair_lighting_pro, cpu_temperature, gigabyte_rgb_fusion_usb, lian_li_sl_infinity, rgb,
+};
+
+use super::Machine;
+
+pub struct MachineLyssMetal2 {
+ fusion_device: gigabyte_rgb_fusion_usb::Device,
+ corsair_lignting_pro: corsair_lighting_pro::Device,
+ lian_li_sl_infinity: lian_li_sl_infinity::Device,
+ gpus: Vec<nvapi::PhysicalGpu>,
+}
+
+impl MachineLyssMetal2 {
+ pub fn new() -> anyhow::Result<Self> {
+ let api = hidapi::HidApi::new()?;
+
+ nvapi::initialize().expect("Unable to initialize nvapi (Nvidia API)");
+
+ let machine = Self {
+ fusion_device: gigabyte_rgb_fusion_usb::Device::new(&api)?,
+ corsair_lignting_pro: corsair_lighting_pro::Device::new(
+ &api,
+ &rgb::RGB {
+ red: 0,
+ green: 255,
+ blue: 40,
+ },
+ ),
+ lian_li_sl_infinity: lian_li_sl_infinity::Device::new(&api),
+ gpus: nvapi::PhysicalGpu::enumerate()?,
+ };
+
+ // machine.set_mode_3080ti();
+ Ok(machine)
+ }
+
+ // Doesn't work: "Error: NotSupported".
+ // From OpenRGB, see the following files:
+ // * Controllers\GigabyteRGBFusion2GPUController\GigabyteRGBFusion2GPUControllerDetect.cpp
+ // * Controllers\GigabyteRGBFusion2GPUController\RGBController_GigabyteRGBFusion2GPU.cpp
+ // * Controllers\GigabyteRGBFusion2GPUController\GigabyteRGBFusion2GPUController.cpp
+ // * i2c_smbus\i2c_smbus_nvapi.cpp
+ // Implementation of nvapi-rs: https://github.com/arcnmx/nvapi-rs/blob/master/src/gpu.rs#L645
+ // Reference API doc: https://docs.nvidia.com/gameworks/content/gameworkslibrary/coresdk/nvapi/structNV__I2C__INFO__V3.html
+ pub fn test_i2c(&self) {
+ // Test from 'GigabyteRGBFusion2GPUControllerDetect.cpp'
+ let data = [0xAB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00];
+ self.gpus[0]
+ .i2c_write(
+ 0,
+ Some(1),
+ false,
+ super::GIGABYTE_RTX3080TI_VISION_OC_ADDR,
+ &[],
+ &data,
+ i2c::I2cSpeed::Default,
+ )
+ .expect("Error");
+ }
+
+ fn set_mode_3080ti(&self) {
+ let data = [
+ super::RGB_FUSION2_GPU_REG_MODE,
+ 0x01, // Mode (1: static).
+ 0x00, // Speed.
+ 0x63, // Brightness max.
+ 0x00, // Mistery flag.
+ 0x01, // Zone.
+ 0x00,
+ 0x00,
+ ];
+ self.gpus[0]
+ .i2c_write(
+ 0,
+ Some(1),
+ false,
+ super::GIGABYTE_RTX3080TI_VISION_OC_ADDR,
+ &[],
+ &data,
+ i2c::I2cSpeed::Default,
+ )
+ .expect("Error");
+ }
+
+ fn set_color_3080ti(&self, color: &rgb::RGB) {
+ // TODO.
+ self.test_i2c();
+ }
+}
+
+impl Machine for MachineLyssMetal2 {
+ fn set_color_1(&mut self, color: &rgb::RGB) {
+ self.corsair_lignting_pro.set_color(color);
+ self.fusion_device.set_color(color);
+ // self.set_color_3080ti(&color); // TODO.
+ }
+
+ fn set_color_2(&mut self, color: &rgb::RGB) {
+ self.lian_li_sl_infinity.set_color(color);
+ }
+
+ fn get_gpu_tmp(&self) -> f32 {
+ self.gpus[0].thermal_settings(None).unwrap()[0]
+ .current_temperature
+ .0 as f32
+ }
+
+ fn get_cpu_tmp(&self) -> f32 {
+ cpu_temperature::read()
+ }
+}
--- /dev/null
+use crate::rgb;
+
+pub mod jiji;
+pub mod lyss_metal;
+pub mod lyss_metal2;
+
+const RGB_FUSION2_GPU_REG_COLOR: u8 = 0x40;
+const RGB_FUSION2_GPU_REG_MODE: u8 = 0x88;
+
+const GIGABYTE_RTX3080TI_VISION_OC_ADDR: u8 = 0x63;
+
+pub trait Machine {
+ fn set_color(&mut self, color: &rgb::RGB) {
+ self.set_color_1(color);
+ self.set_color_2(color);
+ }
+ fn set_color_1(&mut self, color: &rgb::RGB);
+ fn set_color_2(&mut self, color: &rgb::RGB);
+ fn get_gpu_tmp(&self) -> f32;
+ fn get_cpu_tmp(&self) -> f32;
+}
mod a770;
mod asus_aura_usb;
mod corsair_lighting_pro;
+mod gigabyte_rgb_fusion_usb;
mod lian_li_sl_infinity;
mod machine;
mod main_loop;
let completed_event_handler = Arc::clone(&completed);
- info!("Setuping the event handler...");
+ info!("Setup the event handler...");
let event_handler = move |control_event| -> ServiceControlHandlerResult {
match control_event {
};
let settings = settings::Settings::read(&file_conf_path).expect("Cannot load settings");
- println!("Settings: {settings:?}");
+ println!("Settings: {settings:?} from {file_conf_path}");
let mut machine: Box<dyn machine::Machine> = match settings.machine_name {
settings::MachineName::Jiji => {
- Box::new(machine::MachineJiji::new().expect("Unable to create MachineJiji"))
- }
- settings::MachineName::LyssMetal => {
- Box::new(machine::MachineLyssMetal::new().expect("Unable to create MachineLyssMetal"))
+ Box::new(machine::jiji::MachineJiji::new().expect("Unable to create MachineJiji"))
}
+ settings::MachineName::LyssMetal => Box::new(
+ machine::lyss_metal::MachineLyssMetal::new()
+ .expect("Unable to create MachineLyssMetal"),
+ ),
+ settings::MachineName::LyssMetal2 => Box::new(
+ machine::lyss_metal2::MachineLyssMetal2::new()
+ .expect("Unable to create MachineLyssMetal2"),
+ ),
};
let mut kernel = [0f32; consts::KERNEL_SIZE_SAMPLES];
);
let mut data_block = [0u8; I2C_BLOCK_MAX + 2];
data_block[0] = l as u8;
- data_block[1..l + 1].copy_from_slice(&data);
+ data_block[1..l + 1].copy_from_slice(data);
unsafe {
- match self.i2c_smbus_xfer(
+ if let Err(error) = self.i2c_smbus_xfer(
addr,
AccessType::Write,
command,
TransactionType::I2cSmbusBlockData,
Some(&data_block),
) {
- Err(error) => println!("Error when writing block (I2c): {error:?}"),
- Ok(_) => (),
+ println!("Error when writing block (I2c): {error:?}");
}
}
}
TransactionType::I2cSmbusQuick => {
self.write_io_port_byte(
SMBusAddressOffsets::Smbhstadd,
- addr << 1 | access_type as u8,
+ (addr << 1) | access_type as u8,
);
Piix4TransactionType::Piix4Quick
}
TransactionType::I2cSmbusBlockData => {
self.write_io_port_byte(
SMBusAddressOffsets::Smbhstadd,
- addr << 1 | access_type as u8,
+ (addr << 1) | access_type as u8,
);
self.write_io_port_byte(SMBusAddressOffsets::Smbhstcmd, command);
if let AccessType::Write = access_type {
for i in 1..=l {
data[i] = self.read_io_port_byte(SMBusAddressOffsets::Smbblkdat);
}
- return Ok(XferResult::BlockData(data));
+ Ok(XferResult::BlockData(data))
}
}
}
self.write_io_port_byte(SMBusAddressOffsets::Smbhststs, res);
}
- return Ok(());
+ Ok(())
}
unsafe fn write_io_port_byte(&self, op: SMBusAddressOffsets, value: u8) {
pub enum MachineName {
Jiji,
LyssMetal,
+ LyssMetal2,
}
#[derive(Debug, Deserialize, Serialize)]
use crate::{
a770, asus_aura_usb, corsair_lighting_pro, corsair_vengeance, cpu_temperature,
- lian_li_sl_infinity, machine, rgb::RGB, winring0, wrapper_winring0,
+ gigabyte_rgb_fusion_usb, lian_li_sl_infinity, machine, rgb::RGB, winring0, wrapper_winring0,
};
pub fn tests() {
// test_asus_aura_usb(asus_aura_usb::Motherboard::Asus650e);
// test_corsair_lighting_pro();
- test_lianli_sl_infinity();
+ // test_lianli_sl_infinity();
// list_usb_devices();
// test_roccat();
// test_wmi();
// test_read_temperature_cpu();
// test_read_temperature_a770();
// test_read_temperature_3080();
+ test_gigabyte_fusion();
winring0::deinit();
std::io::stdin().read_line(&mut String::new()).unwrap();
}
+fn test_gigabyte_fusion() {
+ let api = hidapi::HidApi::new().unwrap();
+ let device = gigabyte_rgb_fusion_usb::Device::new(&api).unwrap();
+ // device.test_raw_data().unwrap();
+ device.set_color(&RGB {
+ red: 0xFF,
+ green: 0x00,
+ blue: 0x00,
+ });
+}
+
fn test_wmi() {
let com_con = COMLibrary::new().unwrap();
let wmi_con = WMIConnection::new(com_con.into()).unwrap();
}
fn test_3080ti() {
- let machine: &mut dyn machine::Machine = &mut machine::MachineLyssMetal::new().unwrap();
+ let machine: &mut dyn machine::Machine =
+ &mut machine::lyss_metal::MachineLyssMetal::new().unwrap();
machine.set_color(&RGB {
red: 255,
}
fn test_read_temperature_a770() {
- let jiji: &dyn machine::Machine = &machine::MachineJiji::new().unwrap();
+ let jiji: &dyn machine::Machine = &machine::jiji::MachineJiji::new().unwrap();
println!("temp gpu: {}", jiji.get_gpu_tmp());
}