-[package]
-name = "temp_2_rgb"
-version = "0.1.0"
-edition = "2021"
-
-# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
-
-# [build]
-# target = "i686-pc-windows-msvc"
-
-[dependencies]
-serde = { version = "1.0", features = ["derive"] }
-# Rust object notation, to load configuration files.
-ron = "0.8"
-
-num = "0.4"
-
-dirs = "6.0"
-anyhow = "1.0"
-
-flexi_logger = "0.29"
-log-panics = { version = "2", features = ["with-backtrace"] }
-log = "0.4"
-
-windows-service = "0.7"
-
-# HIDAPI is a library which allows an application to interface with
-# USB and Bluetooth HID-Class devices.
-hidapi = "2.6"
-
-# Nvidia API.
-nvapi = "0.1"
-
-libc = "0.2"
-wmi = "0.15"
-crc = "3.2"
-
-# libloading = "0.8"
-# netcorehost = "0.15"
-
-[dependencies.windows]
-version = "0.59"
-features = [
- "Win32_Foundation",
- "Win32_Security",
- "Win32_Storage_FileSystem",
- "Win32_System_IO",
- "Win32_System_Services",
- "Win32_System_LibraryLoader",
- "Win32_System_Threading",
- # "Devices_I2c",
- # "Devices_Enumeration",
- # "Foundation",
- # "Foundation_Collections",
-]
-
-[build-dependencies]
-bindgen = "0.71"
-
-[profile.release]
-# strip = "debuginfo"
-codegen-units = 1
-lto = true
+[package]\r
+name = "temp_2_rgb"\r
+version = "0.1.0"\r
+edition = "2024"\r
+\r
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html\r
+\r
+# [build]\r
+# target = "i686-pc-windows-msvc"\r
+\r
+[dependencies]\r
+serde = { version = "1.0", features = ["derive"] }\r
+# Rust object notation, to load configuration files.\r
+ron = "0.8"\r
+\r
+num = "0.4"\r
+\r
+dirs = "6.0"\r
+anyhow = "1.0"\r
+\r
+clap = { version = "4", features = ["derive"] }\r
+\r
+flexi_logger = "0.29"\r
+log-panics = { version = "2", features = ["with-backtrace"] }\r
+log = "0.4"\r
+\r
+windows-service = "0.8"\r
+\r
+# HIDAPI is a library which allows an application to interface with\r
+# USB and Bluetooth HID-Class devices.\r
+hidapi = "2.6"\r
+\r
+# Nvidia API.\r
+nvapi = "0.1"\r
+\r
+libc = "0.2"\r
+wmi = "0.15"\r
+crc = "3.2"\r
+\r
+# libloading = "0.8"\r
+# netcorehost = "0.15"\r
+\r
+[dependencies.windows]\r
+version = "0.60"\r
+features = [\r
+ "Win32_Foundation",\r
+ "Win32_Security",\r
+ "Win32_Storage_FileSystem",\r
+ "Win32_System_IO",\r
+ "Win32_System_Services",\r
+ "Win32_System_LibraryLoader",\r
+ "Win32_System_Threading",\r
+ "Win32_System_SystemInformation",\r
+ # "Devices_I2c",\r
+ # "Devices_Enumeration",\r
+ # "Foundation",\r
+ # "Foundation_Collections",\r
+]\r
+\r
+[build-dependencies]\r
+bindgen = "0.71"\r
+\r
+[profile.release]\r
+# strip = "debuginfo"\r
+codegen-units = 1\r
+lto = true\r
-extern crate bindgen;
-
-use std::{env, path::PathBuf};
-
-// From: https://rust-lang.github.io/rust-bindgen/tutorial-0.html
-
-fn main() {
- // Tell cargo to look for shared libraries in the specified directory
- println!("cargo:rustc-link-search=winring0");
- println!("cargo:rustc-link-search=IntelArc");
-
- // Tell cargo to tell rustc to link the system 'WinRing0x64' shared library.
- println!("cargo:rustc-link-lib=WinRing0x64");
- println!("cargo:rustc-link-lib=IntelArc");
-
- // Tell cargo to invalidate the built crate whenever the header changes
- println!("cargo:rerun-if-changed=OlsApi.h");
- println!("cargo:rerun-if-changed=IntelArc.h");
-
- // The bindgen::Builder is the main entry point
- // to bindgen, and lets you build up options for
- // the resulting bindings.
- let bindings_winring0 = bindgen::Builder::default()
- // The input header we would like to generate bindings for.
- .header("winring0/OlsApi.h")
- // .clang_arg("-target")
- // .clang_arg("i686-pc-windows-msvc")
- .clang_arg("-x")
- .clang_arg("c++")
- .clang_arg("--std")
- .clang_arg("c++14")
- // Commented out: not needed.
- // Tell cargo to invalidate the built crate whenever any of the
- // included header files changed.
- //.parse_callbacks(Box::new(bindgen::CargoCallbacks))
- // Finish the builder and generate the bindings.
- .generate()
- // Unwrap the Result and panic on failure.
- .expect("Unable to generate bindings for winring0");
-
- // Write the bindings to the $OUT_DIR/bindings.rs file.
- let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
-
- bindings_winring0
- .write_to_file(out_path.join("ols_api.rs"))
- .expect("Couldn't write bindings for winring0!");
-
- // The bindgen::Builder is the main entry point
- // to bindgen, and lets you build up options for
- // the resulting bindings.
- let bindings_intel_arc = bindgen::Builder::default()
- // The input header we would like to generate bindings for.
- .header("IntelArc/IntelArc.h")
- // .clang_arg("-target")
- // .clang_arg("i686-pc-windows-msvc")
- .clang_arg("-x")
- .clang_arg("c++")
- .clang_arg("--std")
- .clang_arg("c++14")
- // Commented out: not needed.
- // Tell cargo to invalidate the built crate whenever any of the
- // included header files changed.
- //.parse_callbacks(Box::new(bindgen::CargoCallbacks))
- // Finish the builder and generate the bindings.
- .generate()
- // Unwrap the Result and panic on failure.
- .expect("Unable to generate bindings for IntelArc");
-
- // Write the bindings to the $OUT_DIR/bindings.rs file.
- let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
-
- bindings_intel_arc
- .write_to_file(out_path.join("intel_arc.rs"))
- .expect("Couldn't write bindings for intel arc!");
-
- // let out_dir = env::var("CARGO_TARGET_DIR").unwrap();
- // println!("out_dir: {}", out_dir);
- // TODO: How to properly get the (current) target directory?
- copy_file("winring0/WinRing0x64.sys", "target/debug/WinRing0x64.sys");
- copy_file("winring0/WinRing0x64.dll", "target/debug/WinRing0x64.dll");
- copy_file("winring0/WinRing0x64.sys", "target/release/WinRing0x64.sys");
- copy_file("winring0/WinRing0x64.dll", "target/release/WinRing0x64.dll");
-}
-
-fn copy_file(from: &str, to: &str) {
- if let Err(e) = std::fs::copy(from, to) {
- println!("cargo:warning={e:?} (copy {from} to {to})")
- };
-}
+extern crate bindgen;\r
+\r
+use std::{env, path::PathBuf};\r
+\r
+// From: https://rust-lang.github.io/rust-bindgen/tutorial-0.html\r
+\r
+fn main() {\r
+ // Tell cargo to look for shared libraries in the specified directory\r
+ println!("cargo:rustc-link-search=winring0");\r
+ // println!("cargo:rustc-link-search=IntelArc");\r
+\r
+ // Tell cargo to tell rustc to link the system 'WinRing0x64' shared library.\r
+ println!("cargo:rustc-link-lib=WinRing0x64");\r
+ // println!("cargo:rustc-link-lib=IntelArc");\r
+\r
+ // Tell cargo to invalidate the built crate whenever the header changes\r
+ println!("cargo:rerun-if-changed=OlsApi.h");\r
+ // println!("cargo:rerun-if-changed=IntelArc.h");\r
+\r
+ // The bindgen::Builder is the main entry point\r
+ // to bindgen, and lets you build up options for\r
+ // the resulting bindings.\r
+ let bindings_winring0 = bindgen::Builder::default()\r
+ // The input header we would like to generate bindings for.\r
+ .header("winring0/OlsApi.h")\r
+ // .clang_arg("-target")\r
+ // .clang_arg("i686-pc-windows-msvc")\r
+ .clang_arg("-x")\r
+ .clang_arg("c++")\r
+ .clang_arg("--std")\r
+ .clang_arg("c++14")\r
+ // Commented out: not needed.\r
+ // Tell cargo to invalidate the built crate whenever any of the\r
+ // included header files changed.\r
+ //.parse_callbacks(Box::new(bindgen::CargoCallbacks))\r
+ // Finish the builder and generate the bindings.\r
+ .generate()\r
+ .expect("Unable to generate bindings for winring0");\r
+\r
+ // Write the bindings to the $OUT_DIR/bindings.rs file.\r
+ let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());\r
+\r
+ bindings_winring0\r
+ .write_to_file(out_path.join("ols_api.rs"))\r
+ .expect("Couldn't write bindings for winring0!");\r
+\r
+ /*\r
+ // The bindgen::Builder is the main entry point\r
+ // to bindgen, and lets you build up options for\r
+ // the resulting bindings.\r
+ let bindings_intel_arc = bindgen::Builder::default()\r
+ // The input header we would like to generate bindings for.\r
+ .header("IntelArc/IntelArc.h")\r
+ // .clang_arg("-target")\r
+ // .clang_arg("i686-pc-windows-msvc")\r
+ .clang_arg("-x")\r
+ .clang_arg("c++")\r
+ .clang_arg("--std")\r
+ .clang_arg("c++14")\r
+ // Commented out: not needed.\r
+ // Tell cargo to invalidate the built crate whenever any of the\r
+ // included header files changed.\r
+ //.parse_callbacks(Box::new(bindgen::CargoCallbacks))\r
+ // Finish the builder and generate the bindings.\r
+ .generate()\r
+ // Unwrap the Result and panic on failure.\r
+ .expect("Unable to generate bindings for IntelArc");\r
+\r
+ // Write the bindings to the $OUT_DIR/bindings.rs file.\r
+ let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());\r
+\r
+ bindings_intel_arc\r
+ .write_to_file(out_path.join("intel_arc.rs"))\r
+ .expect("Couldn't write bindings for intel arc!");\r
+ */\r
+\r
+ // let out_dir = env::var("CARGO_TARGET_DIR").unwrap();\r
+ // println!("out_dir: {}", out_dir);\r
+ // TODO: How to properly get the (current) target directory?\r
+ copy_file("winring0/WinRing0x64.sys", "target/debug/WinRing0x64.sys");\r
+ copy_file("winring0/WinRing0x64.dll", "target/debug/WinRing0x64.dll");\r
+ copy_file("winring0/WinRing0x64.sys", "target/release/WinRing0x64.sys");\r
+ copy_file("winring0/WinRing0x64.dll", "target/release/WinRing0x64.dll");\r
+}\r
+\r
+fn copy_file(from: &str, to: &str) {\r
+ if let Err(e) = std::fs::copy(from, to) {\r
+ println!("cargo:warning={e:?} (copy {from} to {to})")\r
+ };\r
+}\r
-// use windows::{
-// core::w,
-// Win32::{self, Storage::FileSystem},
-// };
-// use netcorehost::{nethost, pdcstr};
-
-// pub fn set_rgb(r: u8, g: u8, b: u8) {
-// unsafe {
-// let lib = libloading::Library::new("IntelOCWrapper.dll").unwrap();
-
-// let fun: libloading::Symbol<unsafe extern fn(u8, u8, u8, u8) -> bool> = lib.get(b"SetLEDColor").unwrap();
-// let ctlInit: libloading::Symbol<unsafe extern fn(u32) -> std::ffi::c_void> = lib.get(b"ctlInit").unwrap();
-// let ctlInit: libloading::Symbol<unsafe extern "C++" fn(u32) -> std::ffi::c_void> = lib.get(b"SetLEDColor").unwrap();
-// println!("ok");
-// }
-
-// let hostfxr = nethost::load_hostfxr().unwrap();
-// let context = hostfxr.initialize_for_dotnet_command_line(pdcstr!("IntelOCWrapper.dll")).unwrap();
-// let result = context.run_app().value();
-
-// unsafe {
-// let handle = FileSystem::CreateFileW(
-// // w!("\\\\.\\Intel_NF_I2C"),
-// w!("\\\\.\\VIDEO\\INTC_I2C"),
-// // w!("\\\\.\\WinRing0_1_2_0"),
-// 3221225472,
-// FileSystem::FILE_SHARE_MODE(0),
-// None,
-// FileSystem::FILE_CREATION_DISPOSITION(3),
-// FileSystem::FILE_FLAGS_AND_ATTRIBUTES(1073741824),
-// Win32::Foundation::HANDLE::default(),
-// );
-
-// println!("handle: {:?}", handle);
-// }
-
-//"\\\\.\\Intel_NF_I2C"
-// }
-
-// internal static \u0024ArrayType\u0024\u0024\u0024BY08E \u003FA0x171ed149\u002E\u003FprevData\u0040\u003F1\u003F\u003FSetLEDBehavior\u0040CVGAAdaptor\u0040\u0040UEAA_NEEEEEEEEE\u0040Z\u00404PAEA;
-// public static __FnPtr<_ctl_result_t (_ctl_init_args_t*, _ctl_api_handle_t**)> __m2mep\u0040\u003FctlInit\u0040\u0040\u0024\u0024J0YA\u003FAW4_ctl_result_t\u0040\u0040PEAU_ctl_init_args_t\u0040\u0040PEAPEAU_ctl_api_handle_t\u0040\u0040\u0040Z;
-
-use log::error;
-
-use std::{
- io::prelude::*,
- net::TcpStream,
- process::{Child, Command},
-};
-
-pub struct A770 {
- process: Child,
- stream: TcpStream,
-}
-
-impl A770 {
- pub fn new() -> anyhow::Result<Self> {
- Ok(A770 {
- process: Command::new(r"IntelOC.exe").spawn()?,
- stream: TcpStream::connect("127.0.0.1:6577")?,
- })
- }
-
- pub fn set_color(&mut self, r: u8, g: u8, b: u8) -> anyhow::Result<()> {
- let buffer: [u8; 3] = [r, g, b];
- self.stream.write(&buffer).map(|_| ())?;
- Ok(())
- }
-}
-
-impl Drop for A770 {
- fn drop(&mut self) {
- if let Err(error) = self.process.kill().and(self.process.try_wait()) {
- error!("Unable to kill the child process: {:?}", error);
- }
- }
-}
+// use windows::{\r
+// core::w,\r
+// Win32::{self, Storage::FileSystem},\r
+// };\r
+// use netcorehost::{nethost, pdcstr};\r
+\r
+// pub fn set_rgb(r: u8, g: u8, b: u8) {\r
+// unsafe {\r
+// let lib = libloading::Library::new("IntelOCWrapper.dll").unwrap();\r
+\r
+// let fun: libloading::Symbol<unsafe extern fn(u8, u8, u8, u8) -> bool> = lib.get(b"SetLEDColor").unwrap();\r
+// let ctlInit: libloading::Symbol<unsafe extern fn(u32) -> std::ffi::c_void> = lib.get(b"ctlInit").unwrap();\r
+// let ctlInit: libloading::Symbol<unsafe extern "C++" fn(u32) -> std::ffi::c_void> = lib.get(b"SetLEDColor").unwrap();\r
+// println!("ok");\r
+// }\r
+\r
+// let hostfxr = nethost::load_hostfxr().unwrap();\r
+// let context = hostfxr.initialize_for_dotnet_command_line(pdcstr!("IntelOCWrapper.dll")).unwrap();\r
+// let result = context.run_app().value();\r
+\r
+// unsafe {\r
+// let handle = FileSystem::CreateFileW(\r
+// // w!("\\\\.\\Intel_NF_I2C"),\r
+// w!("\\\\.\\VIDEO\\INTC_I2C"),\r
+// // w!("\\\\.\\WinRing0_1_2_0"),\r
+// 3221225472,\r
+// FileSystem::FILE_SHARE_MODE(0),\r
+// None,\r
+// FileSystem::FILE_CREATION_DISPOSITION(3),\r
+// FileSystem::FILE_FLAGS_AND_ATTRIBUTES(1073741824),\r
+// Win32::Foundation::HANDLE::default(),\r
+// );\r
+\r
+// println!("handle: {:?}", handle);\r
+// }\r
+\r
+//"\\\\.\\Intel_NF_I2C"\r
+// }\r
+\r
+// internal static \u0024ArrayType\u0024\u0024\u0024BY08E \u003FA0x171ed149\u002E\u003FprevData\u0040\u003F1\u003F\u003FSetLEDBehavior\u0040CVGAAdaptor\u0040\u0040UEAA_NEEEEEEEEE\u0040Z\u00404PAEA;\r
+// public static __FnPtr<_ctl_result_t (_ctl_init_args_t*, _ctl_api_handle_t**)> __m2mep\u0040\u003FctlInit\u0040\u0040\u0024\u0024J0YA\u003FAW4_ctl_result_t\u0040\u0040PEAU_ctl_init_args_t\u0040\u0040PEAPEAU_ctl_api_handle_t\u0040\u0040\u0040Z;\r
+\r
+use log::error;\r
+\r
+use std::{\r
+ io::prelude::*,\r
+ net::TcpStream,\r
+ process::{Child, Command},\r
+};\r
+\r
+pub struct A770 {\r
+ process: Child,\r
+ stream: TcpStream,\r
+}\r
+\r
+impl A770 {\r
+ pub fn new() -> anyhow::Result<Self> {\r
+ Ok(A770 {\r
+ process: Command::new(r"IntelOC.exe").spawn()?,\r
+ stream: TcpStream::connect("127.0.0.1:6577")?,\r
+ })\r
+ }\r
+\r
+ pub fn set_color(&mut self, r: u8, g: u8, b: u8) -> anyhow::Result<()> {\r
+ let buffer: [u8; 3] = [r, g, b];\r
+ self.stream.write(&buffer).map(|_| ())?;\r
+ Ok(())\r
+ }\r
+}\r
+\r
+impl Drop for A770 {\r
+ fn drop(&mut self) {\r
+ if let Err(error) = self.process.kill().and(self.process.try_wait()) {\r
+ error!("Unable to kill the child process: {:?}", error);\r
+ }\r
+ }\r
+}\r
use std::str;
-use crate::rgb::RGB;
+use crate::rgb::Rgb;
/*
* Doc:
buffer[0] = 0xEC;
buffer[1] = AURA_REQUEST_FIRMWARE_VERSION;
let n_write = self.device.write(&buffer)?;
- assert_eq!(n_write, 65);
+ // assert_eq!(n_write, 65);
buffer.fill(0);
let n_read = self.device.read(&mut buffer)?;
- assert_eq!(n_read, 65);
- assert_eq!(buffer[0], 0xEC);
- assert_eq!(buffer[1], 0x02);
+ // assert_eq!(n_read, 65);
+ // assert_eq!(buffer[0], 0xEC);
+ // assert_eq!(buffer[1], 0x02);
Ok(String::from(str::from_utf8(&buffer[2..17])?))
}
buffer[0] = 0xEC;
buffer[1] = AURA_REQUEST_CONFIG_TABLE;
let n_write = self.device.write(&buffer)?;
- assert_eq!(n_write, 65);
+ // assert_eq!(n_write, 65);
buffer.fill(0);
let n_read = self.device.read(&mut buffer)?;
- assert_eq!(n_read, 65);
- assert_eq!(buffer[0], 0xEC);
- assert_eq!(buffer[1], 0x30);
+ // assert_eq!(n_read, 65);
+ // assert_eq!(buffer[0], 0xEC);
+ // assert_eq!(buffer[1], 0x30);
Ok(buffer[4..64].try_into()?)
}
for channel_effect_id in 0..2 {
buffer[2] = channel_effect_id; // Channel effect id: Fixed.
let n_write = self.device.write(&buffer)?;
- assert_eq!(n_write, 65);
+ // assert_eq!(n_write, 65);
}
Ok(())
}
- pub fn set_color(&self, color: &RGB) -> anyhow::Result<()> {
+ pub fn set_color(&self, color: &Rgb) -> anyhow::Result<()> {
let mut buffer = [0u8; 65];
buffer[0] = 0xEC;
buffer[1] = 0x36;
}
let n_write = self.device.write(&buffer)?;
- assert_eq!(n_write, 65);
+ // assert_eq!(n_write, 65);
Ok(())
}
buffer[2] = 0x55;
let n_write = self.device.write(&buffer)?;
- assert_eq!(n_write, 65);
+ // assert_eq!(n_write, 65);
Ok(())
}
}
-use crate::rgb::RGB;
+use crate::rgb::Rgb;
const CORSAIR_VID: u16 = 0x1B1C;
const CORSAIR_LIGHTING_NODE_PRO_PID: u16 = 0x0C0B;
}
impl Device {
- pub fn new(api: &hidapi::HidApi, initial_color: &RGB) -> Self {
+ pub fn new(api: &hidapi::HidApi, initial_color: &Rgb) -> anyhow::Result<Self> {
let device = Device {
- device: api
- .open(CORSAIR_VID, CORSAIR_LIGHTING_NODE_PRO_PID)
- .unwrap(),
+ device: api.open(CORSAIR_VID, CORSAIR_LIGHTING_NODE_PRO_PID)?,
};
for channel_id in 0..CHANNEL_COUNT {
- device.send_reset(channel_id);
- device.send_begin(channel_id);
- device.send_port_state(channel_id, CORSAIR_LIGHTING_NODE_PORT_STATE_HARDWARE);
- device.send_effect_config(channel_id, initial_color);
- device.send_commit(channel_id);
+ device.send_reset(channel_id)?;
+ device.send_begin(channel_id)?;
+ device.send_port_state(channel_id, CORSAIR_LIGHTING_NODE_PORT_STATE_HARDWARE)?;
+ device.send_effect_config(channel_id, initial_color)?;
+ device.send_commit(channel_id)?;
}
- device
+ Ok(device)
}
- fn send_reset(&self, channel_id: u8) {
+ fn send_reset(&self, channel_id: u8) -> anyhow::Result<()> {
let mut buffer = [0u8; 65];
buffer[0x01] = CORSAIR_LIGHTING_NODE_PACKET_ID_RESET;
buffer[0x02] = channel_id;
- let n_write = self.device.write(&buffer).unwrap();
- assert_eq!(n_write, 65);
+ let n_write = self.device.write(&buffer)?;
+ // assert_eq!(n_write, 65);
- let n_read = self.device.read(&mut buffer[0..16]).unwrap();
- assert_eq!(n_read, 16);
- assert_eq!(buffer[0], 0);
+ let n_read = self.device.read(&mut buffer[0..16])?;
+ // assert_eq!(n_read, 16);
+ // assert_eq!(buffer[0], 0);
+
+ Ok(())
}
- fn send_begin(&self, channel_id: u8) {
+ fn send_begin(&self, channel_id: u8) -> anyhow::Result<()> {
let mut buffer = [0u8; 65];
buffer[0x01] = CORSAIR_LIGHTING_NODE_PACKET_ID_BEGIN;
buffer[0x02] = channel_id;
- let n_write = self.device.write(&buffer).unwrap();
- assert_eq!(n_write, 65);
+ let n_write = self.device.write(&buffer)?;
+ // assert_eq!(n_write, 65);
+
+ let n_read = self.device.read(&mut buffer[0..16])?;
+ // assert_eq!(n_read, 16);
+ // assert_eq!(buffer[0], 0);
- let n_read = self.device.read(&mut buffer[0..16]).unwrap();
- assert_eq!(n_read, 16);
- assert_eq!(buffer[0], 0);
+ Ok(())
}
- fn send_port_state(&self, channel_id: u8, state: u8) {
+ fn send_port_state(&self, channel_id: u8, state: u8) -> anyhow::Result<()> {
let mut buffer = [0u8; 65];
buffer[0x01] = CORSAIR_LIGHTING_NODE_PACKET_ID_PORT_STATE;
buffer[0x02] = channel_id;
buffer[0x03] = state;
- let n_write = self.device.write(&buffer).unwrap();
- assert_eq!(n_write, 65);
+ let n_write = self.device.write(&buffer)?;
+ // assert_eq!(n_write, 65);
+
+ let n_read = self.device.read(&mut buffer[0..16])?;
+ // assert_eq!(n_read, 16);
+ // assert_eq!(buffer[0], 0);
- let n_read = self.device.read(&mut buffer[0..16]).unwrap();
- assert_eq!(n_read, 16);
- assert_eq!(buffer[0], 0);
+ Ok(())
}
- fn send_effect_config(&self, channel_id: u8, color: &RGB) {
+ fn send_effect_config(&self, channel_id: u8, color: &Rgb) -> anyhow::Result<()> {
println!("{color:?}");
let mut buffer = [0u8; 65];
buffer[offset_color + 3 * i + 2] = color.blue;
}
- let n_write = self.device.write(&buffer).unwrap();
- assert_eq!(n_write, 65);
+ let n_write = self.device.write(&buffer)?;
+ // assert_eq!(n_write, 65);
- let n_read = self.device.read(&mut buffer[0..16]).unwrap();
- assert_eq!(n_read, 16);
- assert_eq!(buffer[0], 0);
+ let n_read = self.device.read(&mut buffer[0..16])?;
+ // assert_eq!(n_read, 16);
+ // assert_eq!(buffer[0], 0);
+
+ Ok(())
}
- fn send_commit(&self, channel_id: u8) {
+ fn send_commit(&self, channel_id: u8) -> anyhow::Result<()> {
let mut buffer = [0u8; 65];
buffer[0x01] = CORSAIR_LIGHTING_NODE_PACKET_ID_COMMIT;
buffer[0x02] = 0xFF;
- let n_write = self.device.write(&buffer).unwrap();
- assert_eq!(n_write, 65);
+ let n_write = self.device.write(&buffer)?;
+ // assert_eq!(n_write, 65);
+
+ let n_read = self.device.read(&mut buffer[0..16])?;
+ // assert_eq!(n_read, 16);
+ // assert_eq!(buffer[0], 0);
- let n_read = self.device.read(&mut buffer[0..16]).unwrap();
- assert_eq!(n_read, 16);
- assert_eq!(buffer[0], 0);
+ Ok(())
}
- pub fn set_color(&self, color: &RGB) {
+ pub fn set_color(&self, color: &Rgb) -> anyhow::Result<()> {
// println!("set_color: {color:?}");
for channel_id in 0..CHANNEL_COUNT {
- self.send_port_state(channel_id, CORSAIR_LIGHTING_NODE_PORT_STATE_SOFTWARE);
+ self.send_port_state(channel_id, CORSAIR_LIGHTING_NODE_PORT_STATE_SOFTWARE)?;
let mut buffer = [0u8; 65];
buffer[0x06 + n as usize] = color_component;
}
- let n_write = self.device.write(&buffer).unwrap();
- assert_eq!(n_write, 65);
+ let n_write = self.device.write(&buffer)?;
+ // assert_eq!(n_write, 65);
- let n_read = self.device.read(&mut buffer[0..16]).unwrap();
- assert_eq!(n_read, 16);
- assert_eq!(buffer[0], 0);
+ let n_read = self.device.read(&mut buffer[0..16])?;
+ // assert_eq!(n_read, 16);
+ // assert_eq!(buffer[0], 0);
}
- self.send_commit(channel_id);
+ self.send_commit(channel_id)?;
}
+
+ Ok(())
}
}
-use std::time::Duration;
-
-use crate::{piix4_i2c, rgb::RGB, timer};
-
-// use windows::{*, Win32::{System::LibraryLoader::*, Foundation::HCS_E_CONNECTION_CLOSED, Security::InitializeAcl}, Devices::I2c::*, core::HSTRING};
-
-use crc::{Algorithm, Crc};
-
-const CRC8_ALG: Algorithm<u8> = Algorithm {
- width: 8,
- poly: 0x7,
- init: 0x0,
- refin: false,
- refout: false,
- xorout: 0x00,
- check: 0x00,
- residue: 0x00,
-};
-
-const BUS: i32 = 0;
-const BUS_ADDRESS: i32 = 0x0B00;
-
-// Called "device location" in 'CorsairDominatorPlatinumController' class.
-const ADDRESS_DDR_1: i32 = 0x19;
-const ADDRESS_DDR_2: i32 = 0x1B;
-
-const CORSAIR_LED_COUNT: usize = 12;
-
-pub struct Controller {
- bus: piix4_i2c::I2c,
- ddr_address: u8,
-}
-
-impl Controller {
- pub fn new(ddr_address: u8) -> Self {
- Controller {
- bus: piix4_i2c::I2c::new(0x0B00),
- ddr_address,
- }
- }
-
- pub fn test(&self) {
- self.bus.i2c_smbus_write_quick(self.ddr_address, 0);
- }
-
- pub fn set_color(&self, color: &RGB) {
- let mut data = [0u8; CORSAIR_LED_COUNT * 3 + 2];
- data[0] = 0xC;
-
- for i in 0..CORSAIR_LED_COUNT {
- let offset = i * 3 + 1;
- data[offset] = color.red;
- data[offset + 1] = color.green;
- data[offset + 2] = color.blue;
- }
-
- let crc = Crc::<u8>::new(&CRC8_ALG);
- let mut digest = crc.digest();
- digest.update(&data[0..data.len() - 1]); // '-1' to not take the last byte.
- data[data.len() - 1] = digest.finalize();
-
- let timer = timer::Sleep::new();
-
- self.bus
- .write_block_data(self.ddr_address, 0x31, &data[0..piix4_i2c::I2C_BLOCK_MAX]);
- timer.wait(Duration::from_micros(800));
-
- self.bus
- .write_block_data(self.ddr_address, 0x32, &data[piix4_i2c::I2C_BLOCK_MAX..]);
- timer.wait(Duration::from_micros(200));
- }
-}
-
-// TESTS WITH I2C from winapi:
-
-// let connection_settings = I2cConnectionSettings::Create(ADDRESS_DDR_1).unwrap();
-
-// // For A770: "DISPLAY\\INTC_I2C\\7&3255D98A&0&UID26040"
-// // "PCI\\VEN_1022&DEV_790B&SUBSYS_88771043&REV_71\\3&11583659&0&A0"
-
-// let selector = I2cDevice::GetDeviceSelector().unwrap();
-// println!("{:?}", selector);
-
-// let devices_async = Devices::Enumeration::DeviceInformation::FindAllAsync().unwrap(); // Devices::Enumeration::DeviceInformation::FindAllAsyncAqsFilter(&selector).unwrap();
-// let devices = devices_async.get().unwrap();
-
-// // println!("{:?}", devices.Size());
-
-// for i in 0..devices.Size().unwrap() {
-// let device = devices.GetAt(i).unwrap();
-// println!("Device Name: {:?}", device.Name().unwrap());
-// println!("Device Kind: {:?}", device.Kind().unwrap());
-// println!("Device ID: {:?}", device.Id().unwrap());
-// println!("-----------------")
-// }
-
-// // let device_id = "PCI\\VEN_1022&DEV_790B";
-
-// // let async_get_device = I2cDevice::FromIdAsync(&HSTRING::from(device_id), &connection_settings).unwrap();
-// // let device = async_get_device.get();
-
-// // println!("{:?}", device);
+use std::time::Duration;\r
+\r
+use crate::{piix4_i2c, rgb::Rgb, timer};\r
+\r
+// use windows::{*, Win32::{System::LibraryLoader::*, Foundation::HCS_E_CONNECTION_CLOSED, Security::InitializeAcl}, Devices::I2c::*, core::HSTRING};\r
+\r
+use crc::{Algorithm, Crc};\r
+\r
+const CRC8_ALG: Algorithm<u8> = Algorithm {\r
+ width: 8,\r
+ poly: 0x7,\r
+ init: 0x0,\r
+ refin: false,\r
+ refout: false,\r
+ xorout: 0x00,\r
+ check: 0x00,\r
+ residue: 0x00,\r
+};\r
+\r
+const BUS: i32 = 0;\r
+const BUS_ADDRESS: i32 = 0x0B00;\r
+\r
+// Called "device location" in 'CorsairDominatorPlatinumController' class.\r
+const ADDRESS_DDR_1: i32 = 0x19;\r
+const ADDRESS_DDR_2: i32 = 0x1B;\r
+\r
+const CORSAIR_LED_COUNT: usize = 12;\r
+\r
+pub struct Controller {\r
+ bus: piix4_i2c::I2c,\r
+ ddr_address: u8,\r
+}\r
+\r
+impl Controller {\r
+ pub fn new(ddr_address: u8) -> Self {\r
+ Controller {\r
+ bus: piix4_i2c::I2c::new(0x0B00),\r
+ ddr_address,\r
+ }\r
+ }\r
+\r
+ pub fn test(&self) {\r
+ self.bus.i2c_smbus_write_quick(self.ddr_address, 0);\r
+ }\r
+\r
+ pub fn set_color(&self, color: &Rgb) {\r
+ let mut data = [0u8; CORSAIR_LED_COUNT * 3 + 2];\r
+ data[0] = 0xC;\r
+\r
+ for i in 0..CORSAIR_LED_COUNT {\r
+ let offset = i * 3 + 1;\r
+ data[offset] = color.red;\r
+ data[offset + 1] = color.green;\r
+ data[offset + 2] = color.blue;\r
+ }\r
+\r
+ let crc = Crc::<u8>::new(&CRC8_ALG);\r
+ let mut digest = crc.digest();\r
+ digest.update(&data[0..data.len() - 1]); // '-1' to not take the last byte.\r
+ data[data.len() - 1] = digest.finalize();\r
+\r
+ let timer = timer::Sleep::new();\r
+\r
+ self.bus\r
+ .write_block_data(self.ddr_address, 0x31, &data[0..piix4_i2c::I2C_BLOCK_MAX]);\r
+ timer.wait(Duration::from_micros(800));\r
+\r
+ self.bus\r
+ .write_block_data(self.ddr_address, 0x32, &data[piix4_i2c::I2C_BLOCK_MAX..]);\r
+ timer.wait(Duration::from_micros(200));\r
+ }\r
+}\r
+\r
+// TESTS WITH I2C from winapi:\r
+\r
+// let connection_settings = I2cConnectionSettings::Create(ADDRESS_DDR_1).unwrap();\r
+\r
+// // For A770: "DISPLAY\\INTC_I2C\\7&3255D98A&0&UID26040"\r
+// // "PCI\\VEN_1022&DEV_790B&SUBSYS_88771043&REV_71\\3&11583659&0&A0"\r
+\r
+// let selector = I2cDevice::GetDeviceSelector().unwrap();\r
+// println!("{:?}", selector);\r
+\r
+// let devices_async = Devices::Enumeration::DeviceInformation::FindAllAsync().unwrap(); // Devices::Enumeration::DeviceInformation::FindAllAsyncAqsFilter(&selector).unwrap();\r
+// let devices = devices_async.get().unwrap();\r
+\r
+// // println!("{:?}", devices.Size());\r
+\r
+// for i in 0..devices.Size().unwrap() {\r
+// let device = devices.GetAt(i).unwrap();\r
+// println!("Device Name: {:?}", device.Name().unwrap());\r
+// println!("Device Kind: {:?}", device.Kind().unwrap());\r
+// println!("Device ID: {:?}", device.Id().unwrap());\r
+// println!("-----------------")\r
+// }\r
+\r
+// // let device_id = "PCI\\VEN_1022&DEV_790B";\r
+\r
+// // let async_get_device = I2cDevice::FromIdAsync(&HSTRING::from(device_id), &connection_settings).unwrap();\r
+// // let device = async_get_device.get();\r
+\r
+// // println!("{:?}", device);\r
use std::{str, time::Duration};
-use crate::rgb::RGB;
+use crate::rgb::Rgb;
const VID: u16 = 0x048D; // Vendor ID: Gigabyte.
const PID: u16 = 0x5711; // Product ID.
.device_list()
.find(|d| d.vendor_id() == VID && d.product_id() == PID && d.usage() == 204)
.unwrap()
- .open_device(api)
- .unwrap();
+ .open_device(api)?;
let device = Device { device: d };
const NB_LEDS_PER_PACKET: usize = 19;
- fn set_color_device(&self, color: &RGB, device: u8, nb_leds: usize) -> anyhow::Result<()> {
+ 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];
Ok(())
}
- fn set_color_motherboard(&self, color: &RGB) -> anyhow::Result<()> {
+ fn set_color_motherboard(&self, color: &Rgb) -> anyhow::Result<()> {
{
let mut buffer = [0u8; 64];
buffer[0] = 0xCC;
Ok(())
}
- pub fn set_color(&self, color: &RGB) {
+ pub fn set_color(&self, color: &Rgb) -> anyhow::Result<()> {
// Motherboard & GPU power cables.
- self.set_color_device(color, 0x58, 19).unwrap();
+ self.set_color_device(color, 0x58, 19)?;
// Arctic freezer 3.
- self.set_color_device(color, 0x62, 38).unwrap();
+ self.set_color_device(color, 0x62, 48)?;
- self.set_color_motherboard(color).unwrap();
+ self.set_color_motherboard(color)?;
+
+ Ok(())
}
}
-use crate::rgb::RGB;
-
-const LIANLI_VID: u16 = 0x0CF2;
-const LIANLI_UNI_HUB_SLINF_PID: u16 = 0xA102;
-
-const UNIHUB_SLINF_LED_MODE_STATIC_COLOR: u8 = 0x01;
-const UNIHUB_SLINF_LED_SPEED_000: u8 = 0x02;
-const UNIHUB_SLINF_LED_DIRECTION_LTR: u8 = 0x00;
-const UNIHUB_SLINF_LED_BRIGHTNESS_100: u8 = 0x00;
-
-const UNIHUB_SLINF_TRANSACTION_ID: u8 = 0xE0;
-
-const BUFFER_SIZE: usize = 353;
-
-const NB_LEDS_PER_FAN: u8 = 8;
-const NB_LEDS_PER_SIDE: u8 = 12;
-
-// Specific hardcoded values (should be given in the constructor).
-const CHANNEL_COUNT: u8 = 4; // 2 Channel per line of fans: one for fan itself and one for sides.
-const NB_FAN_PER_CHANNEL: u8 = 2; // 2 fans per channel.
-
-pub struct Device {
- device: hidapi::HidDevice,
-}
-
-impl Device {
- pub fn new(api: &hidapi::HidApi) -> Self {
- Self {
- device: api.open(LIANLI_VID, LIANLI_UNI_HUB_SLINF_PID).unwrap(),
- }
- }
-
- fn send_start_action(&self, channel_id: u8) {
- let mut buffer = [0u8; 5];
- buffer[0x00] = UNIHUB_SLINF_TRANSACTION_ID;
- buffer[0x01] = 0x10;
- buffer[0x02] = 0x60;
- buffer[0x03] = 1 + channel_id / 2;
- buffer[0x04] = NB_FAN_PER_CHANNEL;
-
- let n_write = self.device.write(&buffer).unwrap();
- assert_eq!(n_write, BUFFER_SIZE);
- }
-
- fn send_commit_data(&self, channel_id: u8) {
- let mut buffer = [0u8; 6];
- buffer[0x00] = UNIHUB_SLINF_TRANSACTION_ID;
- buffer[0x01] = 0x10 + channel_id;
- buffer[0x02] = UNIHUB_SLINF_LED_MODE_STATIC_COLOR;
- buffer[0x03] = UNIHUB_SLINF_LED_SPEED_000;
- buffer[0x04] = UNIHUB_SLINF_LED_DIRECTION_LTR;
- buffer[0x05] = UNIHUB_SLINF_LED_BRIGHTNESS_100;
-
- let n_write = self.device.write(&buffer).unwrap();
- assert_eq!(n_write, BUFFER_SIZE);
- }
-
- pub fn set_color(&self, color: &RGB) {
- for channel_id in 0..CHANNEL_COUNT {
- self.send_start_action(channel_id);
-
- let mut buffer = [0u8; BUFFER_SIZE];
- buffer[0x00] = UNIHUB_SLINF_TRANSACTION_ID;
- buffer[0x01] = 0x30 + channel_id;
-
- let nb_leds = if channel_id % 2 == 0 {
- NB_LEDS_PER_FAN * NB_FAN_PER_CHANNEL
- } else {
- NB_LEDS_PER_SIDE * NB_FAN_PER_CHANNEL
- };
-
- for i in 0..(26 as usize) {
- let pos = i * 3 + 2;
- buffer[pos] = color.red;
- buffer[pos + 1] = color.blue;
- buffer[pos + 2] = color.green;
- }
-
- let n_write = self.device.write(&buffer).unwrap();
- assert_eq!(n_write, buffer.len());
-
- self.send_commit_data(channel_id);
- }
- }
-}
+use crate::rgb::Rgb;\r
+\r
+const LIANLI_VID: u16 = 0x0CF2;\r
+const LIANLI_UNI_HUB_SLINF_PID: u16 = 0xA102;\r
+\r
+const UNIHUB_SLINF_LED_MODE_STATIC_COLOR: u8 = 0x01;\r
+const UNIHUB_SLINF_LED_SPEED_000: u8 = 0x02;\r
+const UNIHUB_SLINF_LED_DIRECTION_LTR: u8 = 0x00;\r
+const UNIHUB_SLINF_LED_BRIGHTNESS_100: u8 = 0x00;\r
+\r
+const UNIHUB_SLINF_TRANSACTION_ID: u8 = 0xE0;\r
+\r
+const BUFFER_SIZE: usize = 353;\r
+\r
+const NB_LEDS_PER_FAN: u8 = 8;\r
+const NB_LEDS_PER_SIDE: u8 = 12;\r
+\r
+// Specific hardcoded values (should be given in the constructor).\r
+const CHANNEL_COUNT: u8 = 4; // 2 Channel per line of fans: one for fan itself and one for sides.\r
+const NB_FAN_PER_CHANNEL: u8 = 2; // 2 fans per channel.\r
+\r
+pub struct Device {\r
+ device: hidapi::HidDevice,\r
+}\r
+\r
+impl Device {\r
+ pub fn new(api: &hidapi::HidApi) -> anyhow::Result<Self> {\r
+ Ok(Self {\r
+ device: api.open(LIANLI_VID, LIANLI_UNI_HUB_SLINF_PID)?,\r
+ })\r
+ }\r
+\r
+ fn send_start_action(&self, channel_id: u8) -> anyhow::Result<()> {\r
+ let mut buffer = [0u8; 5];\r
+ buffer[0x00] = UNIHUB_SLINF_TRANSACTION_ID;\r
+ buffer[0x01] = 0x10;\r
+ buffer[0x02] = 0x60;\r
+ buffer[0x03] = 1 + channel_id / 2;\r
+ buffer[0x04] = NB_FAN_PER_CHANNEL;\r
+\r
+ let n_write = self.device.write(&buffer)?;\r
+ // assert_eq!(n_write, BUFFER_SIZE);\r
+\r
+ Ok(())\r
+ }\r
+\r
+ fn send_commit_data(&self, channel_id: u8) -> anyhow::Result<()> {\r
+ let mut buffer = [0u8; 6];\r
+ buffer[0x00] = UNIHUB_SLINF_TRANSACTION_ID;\r
+ buffer[0x01] = 0x10 + channel_id;\r
+ buffer[0x02] = UNIHUB_SLINF_LED_MODE_STATIC_COLOR;\r
+ buffer[0x03] = UNIHUB_SLINF_LED_SPEED_000;\r
+ buffer[0x04] = UNIHUB_SLINF_LED_DIRECTION_LTR;\r
+ buffer[0x05] = UNIHUB_SLINF_LED_BRIGHTNESS_100;\r
+\r
+ let n_write = self.device.write(&buffer)?;\r
+ // assert_eq!(n_write, BUFFER_SIZE);\r
+\r
+ Ok(())\r
+ }\r
+\r
+ pub fn set_color(&self, color: &Rgb) -> anyhow::Result<()> {\r
+ for channel_id in 0..CHANNEL_COUNT {\r
+ self.send_start_action(channel_id)?;\r
+\r
+ let mut buffer = [0u8; BUFFER_SIZE];\r
+ buffer[0x00] = UNIHUB_SLINF_TRANSACTION_ID;\r
+ buffer[0x01] = 0x30 + channel_id;\r
+\r
+ let nb_leds = if channel_id % 2 == 0 {\r
+ NB_LEDS_PER_FAN * NB_FAN_PER_CHANNEL\r
+ } else {\r
+ NB_LEDS_PER_SIDE * NB_FAN_PER_CHANNEL\r
+ };\r
+\r
+ for i in 0..26 {\r
+ let pos = i * 3 + 2;\r
+ buffer[pos] = color.red;\r
+ buffer[pos + 1] = color.blue;\r
+ buffer[pos + 2] = color.green;\r
+ }\r
+\r
+ let n_write = self.device.write(&buffer)?;\r
+ // assert_eq!(n_write, buffer.len());\r
+\r
+ self.send_commit_data(channel_id)?;\r
+ }\r
+\r
+ Ok(())\r
+ }\r
+}\r
-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);
-// }
-// }
-// }
+use crate::{asus_aura_usb, corsair_vengeance, cpu_temperature, rgb};\r
+\r
+use super::Machine;\r
+\r
+pub struct MachineJiji {\r
+ ram: Vec<corsair_vengeance::Controller>,\r
+ b650e_device: asus_aura_usb::Device,\r
+ // a770: a770::A770,\r
+ // gpu_devices: intel_arc::Devices,\r
+ gpus: Vec<nvapi::PhysicalGpu>,\r
+}\r
+\r
+impl MachineJiji {\r
+ pub fn new() -> anyhow::Result<Self> {\r
+ let api = hidapi::HidApi::new().unwrap();\r
+ Ok(MachineJiji {\r
+ ram: vec![\r
+ corsair_vengeance::Controller::new(0x19),\r
+ corsair_vengeance::Controller::new(0x1B),\r
+ ],\r
+ b650e_device: asus_aura_usb::Device::new(&api, asus_aura_usb::Motherboard::Asus650e)?,\r
+ // a770: a770::A770::new()?,\r
+ // gpu_devices: unsafe { intel_arc::GetDevices() },\r
+ gpus: nvapi::PhysicalGpu::enumerate()?,\r
+ })\r
+ }\r
+}\r
+\r
+impl Machine for MachineJiji {\r
+ fn set_color_1(&mut self, color: &rgb::Rgb) -> anyhow::Result<()> {\r
+ for controller in &self.ram {\r
+ controller.set_color(color);\r
+ }\r
+ self.b650e_device.set_color(color)?;\r
+ Ok(())\r
+ }\r
+\r
+ fn set_color_2(&mut self, color: &rgb::Rgb) -> anyhow::Result<()> {\r
+ Ok(())\r
+ } // No color 2.\r
+\r
+ fn get_gpu_tmp(&self) -> f32 {\r
+ // unsafe { intel_arc::GetTemperature(self.gpu_devices, 0) as f32 }\r
+ self.gpus[0].thermal_settings(None).unwrap()[0]\r
+ .current_temperature\r
+ .0 as f32\r
+ }\r
+\r
+ fn get_cpu_tmp(&self) -> f32 {\r
+ cpu_temperature::read()\r
+ }\r
+}\r
+\r
+// impl Drop for MachineJiji {\r
+// fn drop(&mut self) {\r
+// unsafe {\r
+// intel_arc::FreeDevices(self.gpu_devices);\r
+// }\r
+// }\r
+// }\r
-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()
- }
-}
+use nvapi::sys::i2c;\r
+\r
+use crate::{asus_aura_usb, corsair_lighting_pro, cpu_temperature, lian_li_sl_infinity, rgb};\r
+\r
+use super::Machine;\r
+\r
+pub struct MachineLyssMetal {\r
+ crosshair_device: asus_aura_usb::Device,\r
+ corsair_lignting_pro: corsair_lighting_pro::Device,\r
+ lian_li_sl_infinity: lian_li_sl_infinity::Device,\r
+ gpus: Vec<nvapi::PhysicalGpu>,\r
+}\r
+\r
+impl MachineLyssMetal {\r
+ pub fn new() -> anyhow::Result<Self> {\r
+ let api = hidapi::HidApi::new()?;\r
+\r
+ nvapi::initialize().expect("Unable to initialize nvapi (Nvidia API)");\r
+\r
+ let machine = Self {\r
+ crosshair_device: asus_aura_usb::Device::new(\r
+ &api,\r
+ asus_aura_usb::Motherboard::AsusCrosshairVIIIHero,\r
+ )?,\r
+ corsair_lignting_pro: corsair_lighting_pro::Device::new(\r
+ &api,\r
+ &rgb::Rgb {\r
+ red: 0,\r
+ green: 255,\r
+ blue: 40,\r
+ },\r
+ )?,\r
+ lian_li_sl_infinity: lian_li_sl_infinity::Device::new(&api)?,\r
+ gpus: nvapi::PhysicalGpu::enumerate()?,\r
+ };\r
+\r
+ // machine.set_mode_3080ti();\r
+ Ok(machine)\r
+ }\r
+\r
+ // Doesn't work: "Error: NotSupported".\r
+ // From OpenRGB, see the following files:\r
+ // * Controllers\GigabyteRGBFusion2GPUController\GigabyteRGBFusion2GPUControllerDetect.cpp\r
+ // * Controllers\GigabyteRGBFusion2GPUController\RGBController_GigabyteRGBFusion2GPU.cpp\r
+ // * Controllers\GigabyteRGBFusion2GPUController\GigabyteRGBFusion2GPUController.cpp\r
+ // * i2c_smbus\i2c_smbus_nvapi.cpp\r
+ // Implementation of nvapi-rs: https://github.com/arcnmx/nvapi-rs/blob/master/src/gpu.rs#L645\r
+ // Reference API doc: https://docs.nvidia.com/gameworks/content/gameworkslibrary/coresdk/nvapi/structNV__I2C__INFO__V3.html\r
+ pub fn test_i2c(&self) {\r
+ // Test from 'GigabyteRGBFusion2GPUControllerDetect.cpp'\r
+ let data = [0xAB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00];\r
+ self.gpus[0]\r
+ .i2c_write(\r
+ 0,\r
+ Some(1),\r
+ false,\r
+ super::GIGABYTE_RTX3080TI_VISION_OC_ADDR,\r
+ &[],\r
+ &data,\r
+ i2c::I2cSpeed::Default,\r
+ )\r
+ .expect("Error");\r
+ }\r
+\r
+ fn set_mode_3080ti(&self) {\r
+ let data = [\r
+ super::RGB_FUSION2_GPU_REG_MODE,\r
+ 0x01, // Mode (1: static).\r
+ 0x00, // Speed.\r
+ 0x63, // Brightness max.\r
+ 0x00, // Mistery flag.\r
+ 0x01, // Zone.\r
+ 0x00,\r
+ 0x00,\r
+ ];\r
+ self.gpus[0]\r
+ .i2c_write(\r
+ 0,\r
+ Some(1),\r
+ false,\r
+ super::GIGABYTE_RTX3080TI_VISION_OC_ADDR,\r
+ &[],\r
+ &data,\r
+ i2c::I2cSpeed::Default,\r
+ )\r
+ .expect("Error");\r
+ }\r
+\r
+ fn set_color_3080ti(&self, color: &rgb::Rgb) {\r
+ // TODO.\r
+ self.test_i2c();\r
+ }\r
+}\r
+\r
+impl Machine for MachineLyssMetal {\r
+ fn set_color_1(&mut self, color: &rgb::Rgb) -> anyhow::Result<()> {\r
+ self.crosshair_device.set_color(color)?;\r
+ self.corsair_lignting_pro.set_color(color)?;\r
+ // self.set_color_3080ti(&color); // TODO.\r
+ Ok(())\r
+ }\r
+\r
+ fn set_color_2(&mut self, color: &rgb::Rgb) -> anyhow::Result<()> {\r
+ self.lian_li_sl_infinity.set_color(color)?;\r
+ Ok(())\r
+ }\r
+\r
+ fn get_gpu_tmp(&self) -> f32 {\r
+ self.gpus[0].thermal_settings(None).unwrap()[0]\r
+ .current_temperature\r
+ .0 as f32\r
+ }\r
+\r
+ fn get_cpu_tmp(&self) -> f32 {\r
+ cpu_temperature::read()\r
+ }\r
+}\r
-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()
- }
-}
+use nvapi::sys::i2c;\r
+\r
+use crate::{\r
+ corsair_lighting_pro, cpu_temperature, gigabyte_rgb_fusion_usb, lian_li_sl_infinity, rgb,\r
+};\r
+\r
+use super::Machine;\r
+\r
+pub struct MachineLyssMetal2 {\r
+ fusion_device: gigabyte_rgb_fusion_usb::Device,\r
+ corsair_lignting_pro: corsair_lighting_pro::Device,\r
+ lian_li_sl_infinity: lian_li_sl_infinity::Device,\r
+ gpus: Vec<nvapi::PhysicalGpu>,\r
+}\r
+\r
+impl MachineLyssMetal2 {\r
+ pub fn new() -> anyhow::Result<Self> {\r
+ let api = hidapi::HidApi::new()?;\r
+\r
+ nvapi::initialize().expect("Unable to initialize nvapi (Nvidia API)");\r
+\r
+ let machine = Self {\r
+ fusion_device: gigabyte_rgb_fusion_usb::Device::new(&api)?,\r
+ corsair_lignting_pro: corsair_lighting_pro::Device::new(\r
+ &api,\r
+ &rgb::Rgb {\r
+ red: 0,\r
+ green: 255,\r
+ blue: 40,\r
+ },\r
+ )?,\r
+ lian_li_sl_infinity: lian_li_sl_infinity::Device::new(&api)?,\r
+ gpus: nvapi::PhysicalGpu::enumerate()?,\r
+ };\r
+\r
+ // machine.set_mode_3080ti();\r
+ Ok(machine)\r
+ }\r
+\r
+ // Doesn't work: "Error: NotSupported".\r
+ // From OpenRGB, see the following files:\r
+ // * Controllers\GigabyteRGBFusion2GPUController\GigabyteRGBFusion2GPUControllerDetect.cpp\r
+ // * Controllers\GigabyteRGBFusion2GPUController\RGBController_GigabyteRGBFusion2GPU.cpp\r
+ // * Controllers\GigabyteRGBFusion2GPUController\GigabyteRGBFusion2GPUController.cpp\r
+ // * i2c_smbus\i2c_smbus_nvapi.cpp\r
+ // Implementation of nvapi-rs: https://github.com/arcnmx/nvapi-rs/blob/master/src/gpu.rs#L645\r
+ // Reference API doc: https://docs.nvidia.com/gameworks/content/gameworkslibrary/coresdk/nvapi/structNV__I2C__INFO__V3.html\r
+ pub fn test_i2c(&self) {\r
+ // Test from 'GigabyteRGBFusion2GPUControllerDetect.cpp'\r
+ let data = [0xAB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00];\r
+ self.gpus[0]\r
+ .i2c_write(\r
+ 0,\r
+ Some(1),\r
+ false,\r
+ super::GIGABYTE_RTX3080TI_VISION_OC_ADDR,\r
+ &[],\r
+ &data,\r
+ i2c::I2cSpeed::Default,\r
+ )\r
+ .expect("Error");\r
+ }\r
+\r
+ fn set_mode_3080ti(&self) {\r
+ let data = [\r
+ super::RGB_FUSION2_GPU_REG_MODE,\r
+ 0x01, // Mode (1: static).\r
+ 0x00, // Speed.\r
+ 0x63, // Brightness max.\r
+ 0x00, // Mistery flag.\r
+ 0x01, // Zone.\r
+ 0x00,\r
+ 0x00,\r
+ ];\r
+ self.gpus[0]\r
+ .i2c_write(\r
+ 0,\r
+ Some(1),\r
+ false,\r
+ super::GIGABYTE_RTX3080TI_VISION_OC_ADDR,\r
+ &[],\r
+ &data,\r
+ i2c::I2cSpeed::Default,\r
+ )\r
+ .expect("Error");\r
+ }\r
+\r
+ fn set_color_3080ti(&self, color: &rgb::Rgb) {\r
+ // TODO.\r
+ self.test_i2c();\r
+ }\r
+}\r
+\r
+impl Machine for MachineLyssMetal2 {\r
+ fn set_color_1(&mut self, color: &rgb::Rgb) -> anyhow::Result<()> {\r
+ self.corsair_lignting_pro.set_color(color)?;\r
+ self.fusion_device.set_color(color)?;\r
+ Ok(())\r
+ // self.set_color_3080ti(&color); // TODO.\r
+ }\r
+\r
+ fn set_color_2(&mut self, color: &rgb::Rgb) -> anyhow::Result<()> {\r
+ self.lian_li_sl_infinity.set_color(color)?;\r
+ Ok(())\r
+ }\r
+\r
+ fn get_gpu_tmp(&self) -> f32 {\r
+ match self.gpus[0].thermal_settings(None) {\r
+ Ok(thermal) => thermal[0].current_temperature.0 as f32,\r
+ Err(_) => 0.,\r
+ }\r
+ }\r
+\r
+ fn get_cpu_tmp(&self) -> f32 {\r
+ cpu_temperature::read()\r
+ }\r
+}\r
-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;
-}
+use crate::rgb;\r
+\r
+pub mod jiji;\r
+pub mod lyss_metal;\r
+pub mod lyss_metal2;\r
+\r
+const RGB_FUSION2_GPU_REG_COLOR: u8 = 0x40;\r
+const RGB_FUSION2_GPU_REG_MODE: u8 = 0x88;\r
+\r
+const GIGABYTE_RTX3080TI_VISION_OC_ADDR: u8 = 0x63;\r
+\r
+pub trait Machine {\r
+ fn set_color(&mut self, color: &rgb::Rgb) -> anyhow::Result<()> {\r
+ self.set_color_1(color)?;\r
+ self.set_color_2(color)?;\r
+ Ok(())\r
+ }\r
+ fn set_color_1(&mut self, color: &rgb::Rgb) -> anyhow::Result<()>;\r
+ fn set_color_2(&mut self, color: &rgb::Rgb) -> anyhow::Result<()>;\r
+ fn get_gpu_tmp(&self) -> f32;\r
+ fn get_cpu_tmp(&self) -> f32;\r
+}\r
-#[macro_use]
-extern crate windows_service;
-
-use std::{
- env,
- ffi::OsString,
- sync::{
- atomic::{AtomicBool, Ordering},
- Arc,
- },
- thread::sleep,
- time::{self, Duration},
-};
-
-use anyhow::Result;
-use log::{debug, error, info, trace, warn};
-use windows::Win32::Foundation::{ERROR_SERVICE_DOES_NOT_EXIST, WIN32_ERROR};
-use windows_service::{
- service::{
- ServiceAccess, ServiceControl, ServiceControlAccept, ServiceErrorControl, ServiceExitCode,
- ServiceInfo, ServiceStartType, ServiceState, ServiceStatus, ServiceType,
- },
- service_control_handler::{self, ServiceControlHandlerResult, ServiceStatusHandle},
- service_dispatcher,
- service_manager::{ServiceManager, ServiceManagerAccess},
-};
-
-define_windows_service!(ffi_service_main, service_main);
-
-mod wrapper_winring0 {
- #![allow(warnings, unused)]
- include!(concat!(env!("OUT_DIR"), "/ols_api.rs"));
-}
-mod intel_arc {
- #![allow(warnings, unused)]
- include!(concat!(env!("OUT_DIR"), "/intel_arc.rs"));
-}
-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;
-mod winring0;
-// mod common;
-mod consts;
-mod corsair_vengeance;
-mod piix4_i2c;
-mod rgb;
-// mod roccat; Disabled.
-mod cpu_temperature;
-mod settings;
-mod tests;
-mod timer;
-
-// Important: when starting as a service, the directory where the log and config files
-// are put is 'C:\Windows\System32\config\systemprofile\AppData\Roaming\Temp2RGB'.
-fn main() -> Result<()> {
- let is_debug = cfg!(debug_assertions);
-
- flexi_logger::Logger::try_with_str(if is_debug { "debug" } else { "info" })?
- .log_to_file(
- flexi_logger::FileSpec::default()
- .directory(dirs::config_dir().unwrap().join(consts::SERVICE_NAME))
- .basename(consts::SERVICE_NAME),
- )
- .duplicate_to_stdout(flexi_logger::Duplicate::All)
- .format(if is_debug {
- flexi_logger::default_format
- } else {
- flexi_logger::detailed_format
- })
- .rotate(
- flexi_logger::Criterion::Size(1024 * 1024),
- flexi_logger::Naming::Timestamps,
- flexi_logger::Cleanup::KeepLogFiles(10),
- )
- .print_message()
- .start()?;
-
- log_panics::init();
-
- let args: Vec<String> = env::args().collect();
-
- info!("Temperature to RGB");
-
- if args.contains(&"--no-service".to_string()) {
- let completed: Arc<AtomicBool> = Arc::new(AtomicBool::new(false));
- main_loop::main_loop(completed.clone());
- } else if args.contains(&"--tests".to_string()) {
- tests::tests();
- } else if args.contains(&"--install-service".to_string()) {
- println!("Installing service...");
- install_service()?;
- } else if args.contains(&"--uninstall-service".to_string()) {
- println!("Uninstalling service...");
- uninstall_service()?;
- } else {
- service_dispatcher::start(consts::SERVICE_NAME, ffi_service_main)?;
- }
-
- Ok(())
-}
-
-fn install_service() -> windows_service::Result<()> {
- let manager_access = ServiceManagerAccess::CONNECT | ServiceManagerAccess::CREATE_SERVICE;
- let service_manager = ServiceManager::local_computer(None::<&str>, manager_access)?;
-
- let service_binary_path = std::env::current_exe()
- .unwrap()
- .with_file_name("temp_2_rgb.exe");
-
- println!("Installing service: {service_binary_path:?}");
-
- let service_info = ServiceInfo {
- name: OsString::from(consts::SERVICE_NAME),
- display_name: OsString::from(consts::SERVICE_NAME),
- service_type: ServiceType::OWN_PROCESS,
- start_type: ServiceStartType::AutoStart,
- error_control: ServiceErrorControl::Normal,
- executable_path: service_binary_path,
- launch_arguments: vec![],
- dependencies: vec![],
- account_name: None, // run as System
- account_password: None,
- };
- let service = service_manager.create_service(&service_info, ServiceAccess::CHANGE_CONFIG)?;
- service.set_description(
- "A service to set the color of hardware according to the temperature of GPU and CPU",
- )?;
- Ok(())
-}
-
-fn uninstall_service() -> windows_service::Result<()> {
- let manager_access = ServiceManagerAccess::CONNECT;
- let service_manager = ServiceManager::local_computer(None::<&str>, manager_access)?;
-
- let service_access = ServiceAccess::QUERY_STATUS | ServiceAccess::STOP | ServiceAccess::DELETE;
- let service = service_manager.open_service(consts::SERVICE_NAME, service_access)?;
-
- // The service will be marked for deletion as long as this function call succeeds.
- // However, it will not be deleted from the database until it is stopped and all open handles to it are closed.
- service.delete()?;
-
- // Our handle to it is not closed yet. So we can still query it.
- if service.query_status()?.current_state != ServiceState::Stopped {
- // If the service cannot be stopped, it will be deleted when the system restarts.
- service.stop()?;
- }
-
- // Explicitly close our open handle to the service. This is automatically called when `service` goes out of scope.
- drop(service);
-
- // Win32 API does not give us a way to wait for service deletion.
- // To check if the service is deleted from the database, we have to poll it ourselves.
- let start = time::Instant::now();
- let timeout = Duration::from_secs(5);
- while start.elapsed() < timeout {
- if let Err(windows_service::Error::Winapi(e)) =
- service_manager.open_service(consts::SERVICE_NAME, ServiceAccess::QUERY_STATUS)
- {
- let WIN32_ERROR(error_num) = ERROR_SERVICE_DOES_NOT_EXIST;
- if e.raw_os_error() == Some(error_num as i32) {
- println!("{} is deleted.", consts::SERVICE_NAME);
- return Ok(());
- }
- }
- sleep(Duration::from_secs(1));
- }
- println!("{} is marked for deletion.", consts::SERVICE_NAME);
-
- Ok(())
-}
-
-fn service_main(arguments: Vec<OsString>) {
- if let Err(error) = run_service(arguments) {
- error!("{error}");
- }
-}
-
-fn run_service(_arguments: Vec<OsString>) -> Result<(), windows_service::Error> {
- let completed: Arc<AtomicBool> = Arc::new(AtomicBool::new(false));
-
- let completed_event_handler = Arc::clone(&completed);
-
- info!("Setup the event handler...");
-
- let event_handler = move |control_event| -> ServiceControlHandlerResult {
- match control_event {
- ServiceControl::Stop => {
- completed_event_handler.store(true, Ordering::Relaxed);
- // Handle stop event and return control back to the system.
- ServiceControlHandlerResult::NoError
- }
- ServiceControl::Shutdown => {
- completed_event_handler.store(true, Ordering::Relaxed);
- // Handle stop event and return control back to the system.
- ServiceControlHandlerResult::NoError
- }
- // ServiceControl::Preshutdown => {
- // completed_event_handler.store(true, Ordering::Relaxed);
- // ServiceControlHandlerResult::NoError
- // }
- // ServiceControl::PowerEvent(param) => {
- // ServiceControlHandlerResult::NotImplemented
- // }
- // All services must accept Interrogate even if it's a no-op.
- ServiceControl::Interrogate => ServiceControlHandlerResult::NoError,
- _ => ServiceControlHandlerResult::NotImplemented,
- }
- };
-
- // Register system service event handler
- let status_handle = service_control_handler::register(consts::SERVICE_NAME, event_handler)?;
-
- status_handle.set_service_status(ServiceStatus {
- service_type: ServiceType::OWN_PROCESS,
- current_state: ServiceState::Running,
- controls_accepted: ServiceControlAccept::STOP | ServiceControlAccept::SHUTDOWN,
- exit_code: ServiceExitCode::Win32(0),
- checkpoint: 0,
- wait_hint: Duration::default(),
- process_id: None, //Some(std::process::id()),
- })?;
-
- main_loop::main_loop(completed.clone());
-
- status_handle.set_service_status(ServiceStatus {
- service_type: ServiceType::OWN_PROCESS,
- current_state: ServiceState::Stopped,
- controls_accepted: ServiceControlAccept::empty(),
- exit_code: ServiceExitCode::Win32(0),
- checkpoint: 0,
- wait_hint: Duration::default(),
- process_id: None, //Some(std::process::id()),
- })?;
-
- info!("Main loop stopped: Temperature to RGB will now shut down");
-
- Ok(())
-}
+#[macro_use]\r
+extern crate windows_service;\r
+\r
+use std::{\r
+ ffi::OsString,\r
+ sync::{\r
+ Arc,\r
+ atomic::{AtomicBool, Ordering},\r
+ },\r
+ thread::sleep,\r
+ time::{self, Duration},\r
+};\r
+\r
+use anyhow::Result;\r
+use clap::Parser;\r
+use log::{error, info};\r
+use windows::Win32::Foundation::{ERROR_SERVICE_DOES_NOT_EXIST, WIN32_ERROR};\r
+use windows_service::{\r
+ service::{\r
+ ServiceAccess, ServiceControl, ServiceControlAccept, ServiceErrorControl, ServiceExitCode,\r
+ ServiceInfo, ServiceStartType, ServiceState, ServiceStatus, ServiceType,\r
+ },\r
+ service_control_handler::{self, ServiceControlHandlerResult},\r
+ service_dispatcher,\r
+ service_manager::{ServiceManager, ServiceManagerAccess},\r
+};\r
+\r
+define_windows_service!(ffi_service_main, service_main);\r
+\r
+mod wrapper_winring0 {\r
+ #![allow(warnings, unused)]\r
+ include!(concat!(env!("OUT_DIR"), "/ols_api.rs"));\r
+}\r
+// mod intel_arc {\r
+// #![allow(warnings, unused)]\r
+// include!(concat!(env!("OUT_DIR"), "/intel_arc.rs"));\r
+// }\r
+mod a770;\r
+mod asus_aura_usb;\r
+mod consts;\r
+mod corsair_lighting_pro;\r
+mod corsair_vengeance;\r
+mod gigabyte_rgb_fusion_usb;\r
+mod lian_li_sl_infinity;\r
+mod machine;\r
+mod main_loop;\r
+mod piix4_i2c;\r
+mod rgb;\r
+mod winring0;\r
+// mod roccat; Disabled.\r
+mod cpu_temperature;\r
+mod settings;\r
+mod tests;\r
+mod timer;\r
+\r
+#[derive(Parser, Debug)]\r
+#[command(\r
+ author = "Greg Burri",\r
+ version = "1.0",\r
+ about = "Set RGB according to CPU and GPU temperaturess"\r
+)]\r
+struct Args {\r
+ /// Launch without service.\r
+ #[arg(group = "main", long)]\r
+ no_service: bool,\r
+\r
+ /// Run tests.\r
+ #[arg(group = "main", long)]\r
+ tests: bool,\r
+\r
+ /// Install driver winring0.\r
+ #[arg(group = "main", long)]\r
+ install_winring0: bool,\r
+\r
+ /// Install the service.\r
+ #[arg(group = "main", long)]\r
+ install_service: bool,\r
+\r
+ /// Uninstall the service.\r
+ #[arg(group = "main", long)]\r
+ uninstall_service: bool,\r
+}\r
+\r
+// Important: when starting as a service, the directory where the log and config files\r
+// are put is 'C:\Windows\System32\config\systemprofile\AppData\Roaming\Temp2RGB'.\r
+fn main() -> Result<()> {\r
+ let is_debug = cfg!(debug_assertions);\r
+\r
+ flexi_logger::Logger::try_with_str(if is_debug { "debug" } else { "info" })?\r
+ .log_to_file(\r
+ flexi_logger::FileSpec::default()\r
+ .directory(dirs::config_dir().unwrap().join(consts::SERVICE_NAME))\r
+ .basename(consts::SERVICE_NAME),\r
+ )\r
+ .duplicate_to_stdout(flexi_logger::Duplicate::All)\r
+ .format(if is_debug {\r
+ flexi_logger::default_format\r
+ } else {\r
+ flexi_logger::detailed_format\r
+ })\r
+ .rotate(\r
+ flexi_logger::Criterion::Size(1024 * 1024),\r
+ flexi_logger::Naming::Timestamps,\r
+ flexi_logger::Cleanup::KeepLogFiles(10),\r
+ )\r
+ .print_message()\r
+ .start()?;\r
+\r
+ log_panics::init();\r
+\r
+ let args = Args::parse();\r
+\r
+ info!("Temperature to RGB");\r
+\r
+ if args.no_service {\r
+ let completed: Arc<AtomicBool> = Arc::new(AtomicBool::new(false));\r
+ main_loop::main_loop(completed.clone());\r
+ } else if args.tests {\r
+ tests::tests();\r
+ } else if args.install_winring0 {\r
+ println!("Installing winring0 service...");\r
+ install_winring0()?;\r
+ } else if args.install_service {\r
+ println!("Installing service...");\r
+ install_service()?;\r
+ } else if args.uninstall_service {\r
+ println!("Uninstalling service...");\r
+ uninstall_service()?;\r
+ } else {\r
+ service_dispatcher::start(consts::SERVICE_NAME, ffi_service_main)?;\r
+ }\r
+\r
+ Ok(())\r
+}\r
+\r
+fn install_winring0() -> windows_service::Result<()> {\r
+ let system_dir = unsafe {\r
+ let mut system_dir = [0u8; windows::Win32::Foundation::MAX_PATH as usize];\r
+ let l =\r
+ windows::Win32::System::SystemInformation::GetSystemDirectoryA(Some(&mut system_dir))\r
+ as usize;\r
+ assert_ne!(l, 0);\r
+ String::from_utf8(system_dir[0..l].into()).unwrap()\r
+ };\r
+ // TODO: to const.\r
+ let winring0_filename = "WinRing0x64.sys";\r
+ let driver_name = "WinRing0x64";\r
+\r
+ let winring0_path = std::env::current_exe()\r
+ .unwrap()\r
+ .with_file_name(winring0_filename);\r
+\r
+ let destination = std::path::Path::new(&system_dir)\r
+ .join("drivers")\r
+ .join(winring0_filename);\r
+\r
+ std::fs::copy(winring0_path, &destination).unwrap();\r
+\r
+ let manager_access = ServiceManagerAccess::CONNECT | ServiceManagerAccess::CREATE_SERVICE;\r
+ let service_manager = ServiceManager::local_computer(None::<&str>, manager_access)?;\r
+\r
+ // println!("Installing service: {service_binary_path:?}");\r
+\r
+ let service_info = ServiceInfo {\r
+ name: OsString::from(driver_name),\r
+ display_name: OsString::from(driver_name),\r
+ service_type: ServiceType::KERNEL_DRIVER,\r
+ start_type: ServiceStartType::AutoStart,\r
+ error_control: ServiceErrorControl::Normal,\r
+ executable_path: destination,\r
+ launch_arguments: vec![],\r
+ dependencies: vec![],\r
+ account_name: None, // run as System\r
+ account_password: None,\r
+ };\r
+\r
+ let service = service_manager.create_service(&service_info, ServiceAccess::CHANGE_CONFIG)?;\r
+ service.set_description("Winring0")?;\r
+\r
+ Ok(())\r
+}\r
+\r
+fn install_service() -> windows_service::Result<()> {\r
+ let manager_access = ServiceManagerAccess::CONNECT | ServiceManagerAccess::CREATE_SERVICE;\r
+ let service_manager = ServiceManager::local_computer(None::<&str>, manager_access)?;\r
+\r
+ let service_binary_path = std::env::current_exe()\r
+ .unwrap()\r
+ .with_file_name("temp_2_rgb.exe");\r
+\r
+ println!("Installing service: {service_binary_path:?}");\r
+\r
+ let service_info = ServiceInfo {\r
+ name: OsString::from(consts::SERVICE_NAME),\r
+ display_name: OsString::from(consts::SERVICE_NAME),\r
+ service_type: ServiceType::OWN_PROCESS,\r
+ start_type: ServiceStartType::AutoStart,\r
+ error_control: ServiceErrorControl::Normal,\r
+ executable_path: service_binary_path,\r
+ launch_arguments: vec![],\r
+ dependencies: vec![],\r
+ account_name: None, // run as System\r
+ account_password: None,\r
+ };\r
+\r
+ let service = service_manager.create_service(&service_info, ServiceAccess::CHANGE_CONFIG)?;\r
+ service.set_description(\r
+ "A service to set the color of hardware according to the temperature of GPU and CPU",\r
+ )?;\r
+\r
+ Ok(())\r
+}\r
+\r
+fn uninstall_service() -> windows_service::Result<()> {\r
+ let manager_access = ServiceManagerAccess::CONNECT;\r
+ let service_manager = ServiceManager::local_computer(None::<&str>, manager_access)?;\r
+\r
+ let service_access = ServiceAccess::QUERY_STATUS | ServiceAccess::STOP | ServiceAccess::DELETE;\r
+ let service = service_manager.open_service(consts::SERVICE_NAME, service_access)?;\r
+\r
+ // The service will be marked for deletion as long as this function call succeeds.\r
+ // However, it will not be deleted from the database until it is stopped and all open handles to it are closed.\r
+ service.delete()?;\r
+\r
+ // Our handle to it is not closed yet. So we can still query it.\r
+ if service.query_status()?.current_state != ServiceState::Stopped {\r
+ // If the service cannot be stopped, it will be deleted when the system restarts.\r
+ service.stop()?;\r
+ }\r
+\r
+ // Explicitly close our open handle to the service. This is automatically called when `service` goes out of scope.\r
+ drop(service);\r
+\r
+ // Win32 API does not give us a way to wait for service deletion.\r
+ // To check if the service is deleted from the database, we have to poll it ourselves.\r
+ let start = time::Instant::now();\r
+ let timeout = Duration::from_secs(5);\r
+ while start.elapsed() < timeout {\r
+ if let Err(windows_service::Error::Winapi(e)) =\r
+ service_manager.open_service(consts::SERVICE_NAME, ServiceAccess::QUERY_STATUS)\r
+ {\r
+ let WIN32_ERROR(error_num) = ERROR_SERVICE_DOES_NOT_EXIST;\r
+ if e.raw_os_error() == Some(error_num as i32) {\r
+ println!("{} is deleted.", consts::SERVICE_NAME);\r
+ return Ok(());\r
+ }\r
+ }\r
+ sleep(Duration::from_secs(1));\r
+ }\r
+ println!("{} is marked for deletion.", consts::SERVICE_NAME);\r
+\r
+ Ok(())\r
+}\r
+\r
+fn service_main(arguments: Vec<OsString>) {\r
+ if let Err(error) = run_service(arguments) {\r
+ error!("{error}");\r
+ }\r
+}\r
+\r
+fn run_service(_arguments: Vec<OsString>) -> Result<(), windows_service::Error> {\r
+ let completed: Arc<AtomicBool> = Arc::new(AtomicBool::new(false));\r
+\r
+ let completed_event_handler = Arc::clone(&completed);\r
+\r
+ info!("Setup the event handler...");\r
+\r
+ let event_handler = move |control_event| -> ServiceControlHandlerResult {\r
+ match control_event {\r
+ ServiceControl::Stop => {\r
+ completed_event_handler.store(true, Ordering::Relaxed);\r
+ // Handle stop event and return control back to the system.\r
+ ServiceControlHandlerResult::NoError\r
+ }\r
+ ServiceControl::Shutdown => {\r
+ completed_event_handler.store(true, Ordering::Relaxed);\r
+ // Handle stop event and return control back to the system.\r
+ ServiceControlHandlerResult::NoError\r
+ }\r
+ // ServiceControl::Preshutdown => {\r
+ // completed_event_handler.store(true, Ordering::Relaxed);\r
+ // ServiceControlHandlerResult::NoError\r
+ // }\r
+ // ServiceControl::PowerEvent(param) => {\r
+ // ServiceControlHandlerResult::NotImplemented\r
+ // }\r
+ // All services must accept Interrogate even if it's a no-op.\r
+ ServiceControl::Interrogate => ServiceControlHandlerResult::NoError,\r
+ _ => ServiceControlHandlerResult::NotImplemented,\r
+ }\r
+ };\r
+\r
+ // Register system service event handler\r
+ let status_handle = service_control_handler::register(consts::SERVICE_NAME, event_handler)?;\r
+\r
+ status_handle.set_service_status(ServiceStatus {\r
+ service_type: ServiceType::OWN_PROCESS,\r
+ current_state: ServiceState::Running,\r
+ controls_accepted: ServiceControlAccept::STOP | ServiceControlAccept::SHUTDOWN,\r
+ exit_code: ServiceExitCode::Win32(0),\r
+ checkpoint: 0,\r
+ wait_hint: Duration::default(),\r
+ process_id: None, //Some(std::process::id()),\r
+ })?;\r
+\r
+ main_loop::main_loop(completed.clone());\r
+\r
+ status_handle.set_service_status(ServiceStatus {\r
+ service_type: ServiceType::OWN_PROCESS,\r
+ current_state: ServiceState::Stopped,\r
+ controls_accepted: ServiceControlAccept::empty(),\r
+ exit_code: ServiceExitCode::Win32(0),\r
+ checkpoint: 0,\r
+ wait_hint: Duration::default(),\r
+ process_id: None, //Some(std::process::id()),\r
+ })?;\r
+\r
+ info!("Main loop stopped: Temperature to RGB will now shut down");\r
+\r
+ Ok(())\r
+}\r
use std::{
sync::{
- atomic::{AtomicBool, Ordering},
Arc,
+ atomic::{AtomicBool, Ordering},
},
time::{self, Duration},
};
+use log::warn;
+
use crate::{consts, machine, rgb, settings, timer, winring0};
pub fn main_loop(completed: Arc<AtomicBool>) {
if tick % (consts::FREQ_TEMP_POLLING / consts::FREQ_REFRESHING_RGB) as i64 == 0 {
println!("Update RGB: {color_1:?}/{color_2:?}, temp: {mean_temp}");
- machine.set_color_1(&color_1);
- if color_2.is_some() {
- machine.set_color_2(&color_2.unwrap());
- } else {
- machine.set_color_2(&color_1);
- }
+ if let Err(error) = machine.set_color_1(&color_1) {
+ warn!("Unable to set color 1: {}", error);
+ };
+
+ if let Err(error) =
+ machine.set_color_2(&if let Some(c) = color_2 { c } else { color_1 })
+ {
+ warn!("Unable to set color 2: {}", error);
+ };
}
let elapsed = time::Instant::now() - time_beginning_loop;
-// Partial implementation for PCI IDE ISA Xcelerator.
-// https://www.kernel.org/doc/html/latest/i2c/summary.html
-
-use std::time::Duration;
-
-use crate::{timer, wrapper_winring0};
-
-pub const I2C_BLOCK_MAX: usize = 32;
-
-#[repr(u16)]
-#[derive(Clone, Copy, Debug)]
-enum TransactionType {
- I2cSmbusQuick = 0,
- I2cSmbusByte = 1,
- I2cSmbusByteData = 2,
- I2cSmbusWordData = 3,
- I2cSmbusProcCall = 4,
- I2cSmbusBlockData = 5,
- I2cSmbusI2cBlockBroken = 6,
- I2cSmbusBlockProcCall = 7, /* SMBus 2.0 */
- I2cSmbusI2cBlockData = 8,
-}
-
-#[repr(u16)]
-#[derive(Clone, Copy, Debug)]
-enum Piix4TransactionType {
- Piix4Quick = 0x00,
- Piix4Byte = 0x04,
- Piix4ByteData = 0x08,
- Piix4WordData = 0x0C,
- Piix4BlockData = 0x14,
-}
-
-// PIIX4 SMBus address offsets
-
-#[repr(u16)]
-#[derive(Clone, Copy, Debug)]
-enum SMBusAddressOffsets {
- Smbhststs = 0,
- Smbhslvsts = 1,
- Smbhstcnt = 2,
- Smbhstcmd = 3,
- Smbhstadd = 4,
- Smbhstdat0 = 5,
- Smbhstdat1 = 6,
- Smbblkdat = 7,
- Smbslvcnt = 8,
- Smbshdwcmd = 9,
- Smbslvevt = 0xA,
- Smbslvdat = 0xC,
-}
-
-#[repr(u8)]
-#[derive(Clone, Copy)]
-enum AccessType {
- Write = 0,
- Read = 1,
-}
-
-pub struct I2c {
- base_address: u16,
-}
-
-enum XferResult {
- Ok,
- BlockData(Vec<u8>),
-}
-
-#[derive(Debug)]
-enum Error {
- Busy,
- Timeout,
- IO,
- Data,
-}
-
-impl I2c {
- pub fn new(base_address: u16) -> Self {
- I2c { base_address }
- }
-
- pub fn write_block_data(&self, addr: u8, command: u8, data: &[u8]) {
- let l = data.len();
- assert!(
- l <= I2C_BLOCK_MAX,
- "Data length must not exceed {}",
- I2C_BLOCK_MAX
- );
- let mut data_block = [0u8; I2C_BLOCK_MAX + 2];
- data_block[0] = l as u8;
- data_block[1..l + 1].copy_from_slice(data);
-
- unsafe {
- if let Err(error) = self.i2c_smbus_xfer(
- addr,
- AccessType::Write,
- command,
- TransactionType::I2cSmbusBlockData,
- Some(&data_block),
- ) {
- println!("Error when writing block (I2c): {error:?}");
- }
- }
- }
-
- pub fn i2c_smbus_write_quick(&self, addr: u8, value: u8) {
- unsafe {
- self.i2c_smbus_xfer(
- addr,
- AccessType::Write,
- value,
- TransactionType::I2cSmbusQuick,
- None,
- )
- .unwrap();
- }
- }
-
- unsafe fn i2c_smbus_xfer(
- &self,
- addr: u8,
- access_type: AccessType,
- command: u8,
- transaction_type: TransactionType, // Called 'size' in 'i2c_smbus\i2c_smbus_piix4.cpp'.
- data: Option<&[u8]>,
- ) -> Result<XferResult, Error> {
- let piix4_transaction_type = match transaction_type {
- TransactionType::I2cSmbusQuick => {
- self.write_io_port_byte(
- SMBusAddressOffsets::Smbhstadd,
- (addr << 1) | access_type as u8,
- );
- Piix4TransactionType::Piix4Quick
- }
- TransactionType::I2cSmbusByte => todo!(),
- TransactionType::I2cSmbusByteData => todo!(), // Here 'data' should be a byte, maybe using a enum?.
- TransactionType::I2cSmbusWordData => todo!(), // Here 'data' should be a u16, maybe using a enum?.
- TransactionType::I2cSmbusBlockData => {
- self.write_io_port_byte(
- SMBusAddressOffsets::Smbhstadd,
- (addr << 1) | access_type as u8,
- );
- self.write_io_port_byte(SMBusAddressOffsets::Smbhstcmd, command);
- if let AccessType::Write = access_type {
- let len = data.unwrap()[0];
- if len == 0 || len > I2C_BLOCK_MAX as u8 {
- panic!("Invalid len value: {}", len);
- }
-
- self.write_io_port_byte(SMBusAddressOffsets::Smbhstdat0, len);
- self.read_io_port_byte(SMBusAddressOffsets::Smbhstcnt); // TODO: do something of the result!?
- for i in 1..=len {
- self.write_io_port_byte(
- SMBusAddressOffsets::Smbblkdat,
- data.unwrap()[i as usize],
- );
- }
- }
- Piix4TransactionType::Piix4BlockData
- }
- _ => panic!("Not supported: {:?}", transaction_type),
- };
-
- self.write_io_port_byte(
- SMBusAddressOffsets::Smbhstcnt,
- piix4_transaction_type as u8 & 0x1C,
- );
-
- self.piix4_transaction()?;
-
- // if let (AccessType::Write, Piix4TransactionType::Piix4Quick) = (access_type, piix4_transaction_type) {
- // return Ok(())
- // }
-
- match piix4_transaction_type {
- Piix4TransactionType::Piix4Quick => Ok(XferResult::Ok),
- Piix4TransactionType::Piix4Byte => todo!(),
- Piix4TransactionType::Piix4ByteData => todo!(),
- Piix4TransactionType::Piix4WordData => todo!(),
- Piix4TransactionType::Piix4BlockData => {
- let l = self.read_io_port_byte(SMBusAddressOffsets::Smbhstdat0) as usize;
- if l == 0 || l > I2C_BLOCK_MAX {
- return Err(Error::Data);
- }
- self.read_io_port_byte(SMBusAddressOffsets::Smbhstcnt);
- let mut data = vec![0; l + 1];
- for i in 1..=l {
- data[i] = self.read_io_port_byte(SMBusAddressOffsets::Smbblkdat);
- }
- Ok(XferResult::BlockData(data))
- }
- }
- }
-
- unsafe fn piix4_transaction(&self) -> Result<(), Error> {
- let timer = timer::Sleep::new();
-
- // Make sure the SMBus is ready to start transmitting.
- let mut res = self.read_io_port_byte(SMBusAddressOffsets::Smbhststs);
- if res != 0x00 {
- self.write_io_port_byte(SMBusAddressOffsets::Smbhststs, res);
- res = self.read_io_port_byte(SMBusAddressOffsets::Smbhststs);
- if res != 0x00 {
- return Err(Error::Busy);
- }
- }
-
- // Start the transaction by setting bit 6.
- res = self.read_io_port_byte(SMBusAddressOffsets::Smbhstcnt);
- self.write_io_port_byte(SMBusAddressOffsets::Smbhstcnt, res | 0x40);
-
- // let duration: i64 = -2_500; // 250 us.
- let mut n = 0;
- loop {
- timer.wait(Duration::from_micros(250));
-
- res = self.read_io_port_byte(SMBusAddressOffsets::Smbhststs);
- // println!("Res: {}", res);
- if res > 0x01 {
- break;
- }
-
- if n >= 100 {
- return Err(Error::Timeout);
- }
- n += 1;
- }
- // println!("-----");
-
- if res & 0x10 != 0x00 || res & 0x08 != 0x0 || res & 0x04 != 0x0 {
- return Err(Error::IO);
- }
-
- res = self.read_io_port_byte(SMBusAddressOffsets::Smbhststs);
- if res != 0x00 {
- self.write_io_port_byte(SMBusAddressOffsets::Smbhststs, res);
- }
-
- Ok(())
- }
-
- unsafe fn write_io_port_byte(&self, op: SMBusAddressOffsets, value: u8) {
- wrapper_winring0::WriteIoPortByte(self.base_address + op as u16, value);
- }
-
- unsafe fn read_io_port_byte(&self, op: SMBusAddressOffsets) -> u8 {
- wrapper_winring0::ReadIoPortByte(self.base_address + op as u16)
- }
-}
-
-/*
-type ADL_MAIN_MALLOC_CALLBACK = unsafe fn(c_int) -> *mut c_void;
-type ADL_CONTEXT_HANDLE = *mut c_void;
-
-type ADL2_MAIN_CONTROL_CREATE = unsafe extern "C" fn(ADL_MAIN_MALLOC_CALLBACK, c_int, *mut ADL_CONTEXT_HANDLE) -> c_int;
-type ADL2_MAIN_CONTROL_DESTROY = unsafe extern "C" fn(ADL_CONTEXT_HANDLE) -> c_int;
-type ADL2_ADAPTER_NUMBEROFADAPTERS_GET = unsafe extern "C" fn(ADL_CONTEXT_HANDLE, *mut c_int) -> c_int;
-
-pub fn test() {
- unsafe {
- let hDLL = LoadLibraryW(w!("atiadlxx.dll")).unwrap();
- println!("{:?}", hDLL);
-
- let ADL2_Main_Control_Create: ADL2_MAIN_CONTROL_CREATE = transmute(&GetProcAddress(hDLL, s!("ADL2_Main_Control_Create")).unwrap());
- let ADL2_Main_Control_Destroy: ADL2_MAIN_CONTROL_DESTROY = transmute(&GetProcAddress(hDLL, s!("ADL2_Main_Control_Destroy")).unwrap());
- let ADL2_Adapter_NumberOfAdapters_Get: ADL2_ADAPTER_NUMBEROFADAPTERS_GET = transmute(&GetProcAddress(hDLL, s!("ADL2_Adapter_NumberOfAdapters_Get")).unwrap());
-
-
- let m: *mut c_void = libc::malloc(4);
-
-
- }
-}
-*/
+// Partial implementation for PCI IDE ISA Xcelerator.\r
+// https://www.kernel.org/doc/html/latest/i2c/summary.html\r
+\r
+use std::time::Duration;\r
+\r
+use crate::{timer, wrapper_winring0};\r
+\r
+pub const I2C_BLOCK_MAX: usize = 32;\r
+\r
+#[repr(u16)]\r
+#[derive(Clone, Copy, Debug)]\r
+enum TransactionType {\r
+ I2cSmbusQuick = 0,\r
+ I2cSmbusByte = 1,\r
+ I2cSmbusByteData = 2,\r
+ I2cSmbusWordData = 3,\r
+ I2cSmbusProcCall = 4,\r
+ I2cSmbusBlockData = 5,\r
+ I2cSmbusI2cBlockBroken = 6,\r
+ I2cSmbusBlockProcCall = 7, /* SMBus 2.0 */\r
+ I2cSmbusI2cBlockData = 8,\r
+}\r
+\r
+#[repr(u16)]\r
+#[derive(Clone, Copy, Debug)]\r
+enum Piix4TransactionType {\r
+ Piix4Quick = 0x00,\r
+ Piix4Byte = 0x04,\r
+ Piix4ByteData = 0x08,\r
+ Piix4WordData = 0x0C,\r
+ Piix4BlockData = 0x14,\r
+}\r
+\r
+// PIIX4 SMBus address offsets\r
+\r
+#[repr(u16)]\r
+#[derive(Clone, Copy, Debug)]\r
+enum SMBusAddressOffsets {\r
+ Smbhststs = 0,\r
+ Smbhslvsts = 1,\r
+ Smbhstcnt = 2,\r
+ Smbhstcmd = 3,\r
+ Smbhstadd = 4,\r
+ Smbhstdat0 = 5,\r
+ Smbhstdat1 = 6,\r
+ Smbblkdat = 7,\r
+ Smbslvcnt = 8,\r
+ Smbshdwcmd = 9,\r
+ Smbslvevt = 0xA,\r
+ Smbslvdat = 0xC,\r
+}\r
+\r
+#[repr(u8)]\r
+#[derive(Clone, Copy)]\r
+enum AccessType {\r
+ Write = 0,\r
+ Read = 1,\r
+}\r
+\r
+pub struct I2c {\r
+ base_address: u16,\r
+}\r
+\r
+enum XferResult {\r
+ Ok,\r
+ BlockData(Vec<u8>),\r
+}\r
+\r
+#[derive(Debug)]\r
+enum Error {\r
+ Busy,\r
+ Timeout,\r
+ IO,\r
+ Data,\r
+}\r
+\r
+impl I2c {\r
+ pub fn new(base_address: u16) -> Self {\r
+ I2c { base_address }\r
+ }\r
+\r
+ pub fn write_block_data(&self, addr: u8, command: u8, data: &[u8]) {\r
+ let l = data.len();\r
+ assert!(\r
+ l <= I2C_BLOCK_MAX,\r
+ "Data length must not exceed {}",\r
+ I2C_BLOCK_MAX\r
+ );\r
+ let mut data_block = [0u8; I2C_BLOCK_MAX + 2];\r
+ data_block[0] = l as u8;\r
+ data_block[1..l + 1].copy_from_slice(data);\r
+\r
+ unsafe {\r
+ if let Err(error) = self.i2c_smbus_xfer(\r
+ addr,\r
+ AccessType::Write,\r
+ command,\r
+ TransactionType::I2cSmbusBlockData,\r
+ Some(&data_block),\r
+ ) {\r
+ println!("Error when writing block (I2c): {error:?}");\r
+ }\r
+ }\r
+ }\r
+\r
+ pub fn i2c_smbus_write_quick(&self, addr: u8, value: u8) {\r
+ unsafe {\r
+ let _ = self.i2c_smbus_xfer(\r
+ addr,\r
+ AccessType::Write,\r
+ value,\r
+ TransactionType::I2cSmbusQuick,\r
+ None,\r
+ );\r
+ }\r
+ }\r
+\r
+ unsafe fn i2c_smbus_xfer(\r
+ &self,\r
+ addr: u8,\r
+ access_type: AccessType,\r
+ command: u8,\r
+ transaction_type: TransactionType, // Called 'size' in 'i2c_smbus\i2c_smbus_piix4.cpp'.\r
+ data: Option<&[u8]>,\r
+ ) -> Result<XferResult, Error> {\r
+ let piix4_transaction_type = match transaction_type {\r
+ TransactionType::I2cSmbusQuick => {\r
+ self.write_io_port_byte(\r
+ SMBusAddressOffsets::Smbhstadd,\r
+ (addr << 1) | access_type as u8,\r
+ );\r
+ Piix4TransactionType::Piix4Quick\r
+ }\r
+ TransactionType::I2cSmbusByte => todo!(),\r
+ TransactionType::I2cSmbusByteData => todo!(), // Here 'data' should be a byte, maybe using a enum?.\r
+ TransactionType::I2cSmbusWordData => todo!(), // Here 'data' should be a u16, maybe using a enum?.\r
+ TransactionType::I2cSmbusBlockData => {\r
+ self.write_io_port_byte(\r
+ SMBusAddressOffsets::Smbhstadd,\r
+ (addr << 1) | access_type as u8,\r
+ );\r
+ self.write_io_port_byte(SMBusAddressOffsets::Smbhstcmd, command);\r
+ if let AccessType::Write = access_type {\r
+ let len = data.unwrap()[0];\r
+ if len == 0 || len > I2C_BLOCK_MAX as u8 {\r
+ panic!("Invalid len value: {}", len);\r
+ }\r
+\r
+ self.write_io_port_byte(SMBusAddressOffsets::Smbhstdat0, len);\r
+ self.read_io_port_byte(SMBusAddressOffsets::Smbhstcnt); // TODO: do something of the result!?\r
+ for i in 1..=len {\r
+ self.write_io_port_byte(\r
+ SMBusAddressOffsets::Smbblkdat,\r
+ data.unwrap()[i as usize],\r
+ );\r
+ }\r
+ }\r
+ Piix4TransactionType::Piix4BlockData\r
+ }\r
+ _ => panic!("Not supported: {:?}", transaction_type),\r
+ };\r
+\r
+ self.write_io_port_byte(\r
+ SMBusAddressOffsets::Smbhstcnt,\r
+ piix4_transaction_type as u8 & 0x1C,\r
+ );\r
+\r
+ self.piix4_transaction()?;\r
+\r
+ // if let (AccessType::Write, Piix4TransactionType::Piix4Quick) = (access_type, piix4_transaction_type) {\r
+ // return Ok(())\r
+ // }\r
+\r
+ match piix4_transaction_type {\r
+ Piix4TransactionType::Piix4Quick => Ok(XferResult::Ok),\r
+ Piix4TransactionType::Piix4Byte => todo!(),\r
+ Piix4TransactionType::Piix4ByteData => todo!(),\r
+ Piix4TransactionType::Piix4WordData => todo!(),\r
+ Piix4TransactionType::Piix4BlockData => {\r
+ let l = self.read_io_port_byte(SMBusAddressOffsets::Smbhstdat0) as usize;\r
+ if l == 0 || l > I2C_BLOCK_MAX {\r
+ return Err(Error::Data);\r
+ }\r
+ self.read_io_port_byte(SMBusAddressOffsets::Smbhstcnt);\r
+ let mut data = vec![0; l + 1];\r
+ for i in 1..=l {\r
+ data[i] = self.read_io_port_byte(SMBusAddressOffsets::Smbblkdat);\r
+ }\r
+ Ok(XferResult::BlockData(data))\r
+ }\r
+ }\r
+ }\r
+\r
+ unsafe fn piix4_transaction(&self) -> Result<(), Error> {\r
+ let timer = timer::Sleep::new();\r
+\r
+ // Make sure the SMBus is ready to start transmitting.\r
+ let mut res = self.read_io_port_byte(SMBusAddressOffsets::Smbhststs);\r
+ if res != 0x00 {\r
+ self.write_io_port_byte(SMBusAddressOffsets::Smbhststs, res);\r
+ res = self.read_io_port_byte(SMBusAddressOffsets::Smbhststs);\r
+ if res != 0x00 {\r
+ return Err(Error::Busy);\r
+ }\r
+ }\r
+\r
+ // Start the transaction by setting bit 6.\r
+ res = self.read_io_port_byte(SMBusAddressOffsets::Smbhstcnt);\r
+ self.write_io_port_byte(SMBusAddressOffsets::Smbhstcnt, res | 0x40);\r
+\r
+ // let duration: i64 = -2_500; // 250 us.\r
+ let mut n = 0;\r
+ loop {\r
+ timer.wait(Duration::from_micros(250));\r
+\r
+ res = self.read_io_port_byte(SMBusAddressOffsets::Smbhststs);\r
+ // println!("Res: {}", res);\r
+ if res > 0x01 {\r
+ break;\r
+ }\r
+\r
+ if n >= 100 {\r
+ return Err(Error::Timeout);\r
+ }\r
+ n += 1;\r
+ }\r
+ // println!("-----");\r
+\r
+ if res & 0x10 != 0x00 || res & 0x08 != 0x0 || res & 0x04 != 0x0 {\r
+ return Err(Error::IO);\r
+ }\r
+\r
+ res = self.read_io_port_byte(SMBusAddressOffsets::Smbhststs);\r
+ if res != 0x00 {\r
+ self.write_io_port_byte(SMBusAddressOffsets::Smbhststs, res);\r
+ }\r
+\r
+ Ok(())\r
+ }\r
+\r
+ unsafe fn write_io_port_byte(&self, op: SMBusAddressOffsets, value: u8) {\r
+ wrapper_winring0::WriteIoPortByte(self.base_address + op as u16, value);\r
+ }\r
+\r
+ unsafe fn read_io_port_byte(&self, op: SMBusAddressOffsets) -> u8 {\r
+ wrapper_winring0::ReadIoPortByte(self.base_address + op as u16)\r
+ }\r
+}\r
+\r
+/*\r
+type ADL_MAIN_MALLOC_CALLBACK = unsafe fn(c_int) -> *mut c_void;\r
+type ADL_CONTEXT_HANDLE = *mut c_void;\r
+\r
+type ADL2_MAIN_CONTROL_CREATE = unsafe extern "C" fn(ADL_MAIN_MALLOC_CALLBACK, c_int, *mut ADL_CONTEXT_HANDLE) -> c_int;\r
+type ADL2_MAIN_CONTROL_DESTROY = unsafe extern "C" fn(ADL_CONTEXT_HANDLE) -> c_int;\r
+type ADL2_ADAPTER_NUMBEROFADAPTERS_GET = unsafe extern "C" fn(ADL_CONTEXT_HANDLE, *mut c_int) -> c_int;\r
+\r
+pub fn test() {\r
+ unsafe {\r
+ let hDLL = LoadLibraryW(w!("atiadlxx.dll")).unwrap();\r
+ println!("{:?}", hDLL);\r
+\r
+ let ADL2_Main_Control_Create: ADL2_MAIN_CONTROL_CREATE = transmute(&GetProcAddress(hDLL, s!("ADL2_Main_Control_Create")).unwrap());\r
+ let ADL2_Main_Control_Destroy: ADL2_MAIN_CONTROL_DESTROY = transmute(&GetProcAddress(hDLL, s!("ADL2_Main_Control_Destroy")).unwrap());\r
+ let ADL2_Adapter_NumberOfAdapters_Get: ADL2_ADAPTER_NUMBEROFADAPTERS_GET = transmute(&GetProcAddress(hDLL, s!("ADL2_Adapter_NumberOfAdapters_Get")).unwrap());\r
+\r
+\r
+ let m: *mut c_void = libc::malloc(4);\r
+\r
+\r
+ }\r
+}\r
+*/\r
-use serde::{Deserialize, Serialize};
-
-#[derive(Copy, Clone, Debug, Deserialize, Serialize, PartialEq)]
-pub struct RGB {
- pub red: u8,
- pub green: u8,
- pub blue: u8,
-}
-
-// 'value' is between 0 and 1.
-pub fn linear_interpolation(color1: RGB, color2: RGB, value: f32) -> RGB {
- let red = (color1.red as f32 + (color2.red as f32 - color1.red as f32) * value) as u8;
- let green = (color1.green as f32 + (color2.green as f32 - color1.green as f32) * value) as u8;
- let blue = (color1.blue as f32 + (color2.blue as f32 - color1.blue as f32) * value) as u8;
-
- RGB { red, green, blue }
-}
+use serde::{Deserialize, Serialize};\r
+\r
+#[derive(Copy, Clone, Debug, Deserialize, Serialize, PartialEq)]\r
+pub struct Rgb {\r
+ pub red: u8,\r
+ pub green: u8,\r
+ pub blue: u8,\r
+}\r
+\r
+// 'value' is between 0 and 1.\r
+pub fn linear_interpolation(color1: Rgb, color2: Rgb, value: f32) -> Rgb {\r
+ let red = (color1.red as f32 + (color2.red as f32 - color1.red as f32) * value) as u8;\r
+ let green = (color1.green as f32 + (color2.green as f32 - color1.green as f32) * value) as u8;\r
+ let blue = (color1.blue as f32 + (color2.blue as f32 - color1.blue as f32) * value) as u8;\r
+\r
+ Rgb { red, green, blue }\r
+}\r
-use std::fs::File;
-
-use ron::{
- de::from_reader,
- ser::{to_writer_pretty, PrettyConfig},
-};
-use serde::{Deserialize, Serialize};
-
-use crate::rgb::RGB;
-
-#[derive(Debug, Deserialize, Serialize)]
-pub enum MachineName {
- Jiji,
- LyssMetal,
- LyssMetal2,
-}
-
-#[derive(Debug, Deserialize, Serialize)]
-pub struct Settings {
- pub machine_name: MachineName,
- pub cold_color_1: RGB,
- pub hot_color_1: RGB,
- pub cold_color_2: Option<RGB>,
- pub hot_color_2: Option<RGB>,
- // Average temperature between CPU and GPU.
- pub cold_temperature: f32,
- pub hot_temperature: f32,
-}
-
-type Result<T> = std::result::Result<T, Box<dyn std::error::Error>>;
-
-impl Settings {
- fn default() -> Self {
- Settings {
- machine_name: MachineName::Jiji,
- cold_color_1: RGB {
- red: 0,
- green: 255,
- blue: 40,
- },
- hot_color_1: RGB {
- red: 255,
- green: 0,
- blue: 0,
- },
- cold_color_2: None,
- hot_color_2: None,
- cold_temperature: 55.,
- hot_temperature: 75.,
- }
- }
-
- pub fn read(file_path: &str) -> Result<Settings> {
- match File::open(file_path) {
- Ok(file) => from_reader(file).map_err(|e| e.into()),
- Err(_) => {
- let file = File::create(file_path)?;
- let default_config = Settings::default();
- to_writer_pretty(file, &default_config, PrettyConfig::new())?;
- Ok(default_config)
- }
- }
- }
-}
+use std::fs::File;\r
+\r
+use ron::{\r
+ de::from_reader,\r
+ ser::{PrettyConfig, to_writer_pretty},\r
+};\r
+use serde::{Deserialize, Serialize};\r
+\r
+use crate::rgb::Rgb;\r
+\r
+#[derive(Debug, Deserialize, Serialize)]\r
+pub enum MachineName {\r
+ Jiji,\r
+ LyssMetal,\r
+ LyssMetal2,\r
+}\r
+\r
+#[derive(Debug, Deserialize, Serialize)]\r
+pub struct Settings {\r
+ pub machine_name: MachineName,\r
+ pub cold_color_1: Rgb,\r
+ pub hot_color_1: Rgb,\r
+ pub cold_color_2: Option<Rgb>,\r
+ pub hot_color_2: Option<Rgb>,\r
+ // Average temperature between CPU and GPU.\r
+ pub cold_temperature: f32,\r
+ pub hot_temperature: f32,\r
+}\r
+\r
+type Result<T> = std::result::Result<T, Box<dyn std::error::Error>>;\r
+\r
+impl Settings {\r
+ fn default() -> Self {\r
+ Settings {\r
+ machine_name: MachineName::Jiji,\r
+ cold_color_1: Rgb {\r
+ red: 0,\r
+ green: 255,\r
+ blue: 40,\r
+ },\r
+ hot_color_1: Rgb {\r
+ red: 255,\r
+ green: 0,\r
+ blue: 0,\r
+ },\r
+ cold_color_2: None,\r
+ hot_color_2: None,\r
+ cold_temperature: 55.,\r
+ hot_temperature: 75.,\r
+ }\r
+ }\r
+\r
+ pub fn read(file_path: &str) -> Result<Settings> {\r
+ match File::open(file_path) {\r
+ Ok(file) => from_reader(file).map_err(|e| e.into()),\r
+ Err(_) => {\r
+ let file = File::create(file_path)?;\r
+ let default_config = Settings::default();\r
+ to_writer_pretty(file, &default_config, PrettyConfig::new())?;\r
+ Ok(default_config)\r
+ }\r
+ }\r
+ }\r
+}\r
-use std::collections::HashMap;
-
-use wmi::{COMLibrary, Variant, WMIConnection};
-
-use crate::{
- a770, asus_aura_usb, corsair_lighting_pro, corsair_vengeance, cpu_temperature,
- gigabyte_rgb_fusion_usb, lian_li_sl_infinity, machine, rgb::RGB, winring0, wrapper_winring0,
-};
-
-pub fn tests() {
- println!("Running some tests...");
-
- winring0::init();
-
- // test_asus_aura_usb(asus_aura_usb::Motherboard::Asus650e);
- // test_corsair_lighting_pro();
- // test_lianli_sl_infinity();
- // list_usb_devices();
- // test_roccat();
- // test_wmi();
- // test_corsair();
- // test_a770();
- // test_3080ti();
- // test_read_temperature_cpu();
- // test_read_temperature_a770();
- // test_read_temperature_3080();
- test_gigabyte_fusion();
-
- winring0::deinit();
-
- println!("Press any key to continue...");
- 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();
-
- //let results: Vec<HashMap<String, Variant>> = wmi_con.raw_query("SELECT * FROM Win32_PnPSignedDriver WHERE Description LIKE '%SMBUS%' OR Description LIKE '%SM BUS%'").unwrap();
- //let results: Vec<HashMap<String, Variant>> = wmi_con.raw_query("SELECT * FROM Win32_PnPSignedDriver WHERE Description LIKE 'Intel(R) NF I2C Host Controller'").unwrap();
- let results: Vec<HashMap<String, Variant>> = wmi_con
- .raw_query("SELECT * FROM Win32_PnPSignedDriver")
- .unwrap();
- //let results: Vec<HashMap<String, Variant>> = wmi_con.raw_query("SELECT * FROM Win32_PnPAllocatedResource").unwrap();
-
- for os in results {
- println!("-------------------");
- println!("{:#?}", os);
- }
-}
-
-fn list_usb_devices() {
- let api = hidapi::HidApi::new().unwrap();
- for device in api.device_list() {
- println!("{:?}", device);
- println!("name: {}", device.product_string().unwrap());
- println!("interface number: {}", device.interface_number());
- println!("page: {}", device.usage_page());
- println!("usage: {}", device.usage());
- println!("----");
- }
-}
-
-// fn test_roccat() {
-// let api = hidapi::HidApi::new().unwrap();
-// let roccat_device = roccat::get_device(&api);
-
-// let manufacturer = roccat_device.get_manufacturer_string().unwrap();
-// dbg!(manufacturer);
-
-// let product = roccat_device.get_product_string().unwrap();
-// dbg!(product);
-
-// let serial = roccat_device.get_serial_number_string().unwrap();
-// dbg!(serial);
-
-// roccat::init(&roccat_device);
-// roccat::set_color(
-// &roccat_device,
-// &RGB {
-// red: 0,
-// green: 255,
-// blue: 40,
-// },
-// );
-// }
-
-fn test_asus_aura_usb(motherboard: asus_aura_usb::Motherboard) {
- let api = hidapi::HidApi::new().unwrap();
-
- let device = asus_aura_usb::Device::new(&api, motherboard).unwrap();
-
- println!("Firmware: {}", device.get_firmware_string().unwrap());
-
- let configuration = device.get_configuration_table().unwrap();
- println!("Configuration:");
- for i in 0..60 {
- print!("{:02X} ", configuration[i]);
- if (i + 1) % 6 == 0 {
- println!("");
- }
- }
- println!("Number of addressable header: {}", configuration[0x02]);
- println!("Number of leds: {}", configuration[0x1B]);
- println!("Number of RGB headers: {}", configuration[0x1D]);
-
- device
- .set_color(&RGB {
- red: 0,
- green: 0,
- blue: 255,
- })
- .unwrap();
-
- device.save_current_color().unwrap();
-}
-
-fn test_corsair_lighting_pro() {
- let api = hidapi::HidApi::new().unwrap();
- let device = corsair_lighting_pro::Device::new(
- &api,
- &RGB {
- red: 0,
- green: 255,
- blue: 0,
- },
- );
-
- for i in 0..=255 {
- if i % 10 == 0 || i == 255 || i == 0 {
- device.set_color(&RGB {
- red: i as u8,
- green: 255u8 - i as u8,
- blue: 0,
- });
- std::thread::sleep(std::time::Duration::from_millis(200));
- }
- }
-}
-
-fn test_lianli_sl_infinity() {
- let api = hidapi::HidApi::new().unwrap();
- let device = lian_li_sl_infinity::Device::new(&api);
-
- device.set_color(&RGB {
- red: 0,
- green: 0,
- blue: 255,
- });
-}
-
-fn test_corsair() {
- let corsair_controllers = [
- corsair_vengeance::Controller::new(0x19),
- corsair_vengeance::Controller::new(0x1B),
- ];
-
- for controller in corsair_controllers {
- controller.set_color(&RGB {
- red: 0,
- green: 0,
- blue: 255,
- });
- }
-}
-
-fn test_a770() {
- // a770::set_rgb(255, 0, 0);
- let mut a770 = a770::A770::new().unwrap();
- a770.set_color(255, 0, 0).unwrap();
-}
-
-fn test_3080ti() {
- let machine: &mut dyn machine::Machine =
- &mut machine::lyss_metal::MachineLyssMetal::new().unwrap();
-
- machine.set_color(&RGB {
- red: 255,
- green: 0,
- blue: 0,
- });
-}
-
-const F17H_M01H_THM_TCON_CUR_TMP: u32 = 0x00059800;
-const F17H_TEMP_OFFSET_FLAG: u32 = 0x80000;
-const FAMILY_17H_PCI_CONTROL_REGISTER: u32 = 0x60;
-
-fn test_read_temperature_cpu() {
- println!("temp cpu: {}", cpu_temperature::read())
-}
-
-fn test_read_temperature_a770() {
- let jiji: &dyn machine::Machine = &machine::jiji::MachineJiji::new().unwrap();
- println!("temp gpu: {}", jiji.get_gpu_tmp());
-}
-
-fn test_read_temperature_3080() {
- nvapi::initialize().expect("Unable to initialize nvapi (Nvidia API)");
- // if let Ok(gpus) = {
- // for gpu in gpus {
- // let thermal = gpu.thermal_settings(None).unwrap()[0];
- // println!("{:?}", thermal.current_temperature.0)
- // }
- // }
- let gpus = nvapi::PhysicalGpu::enumerate().unwrap();
- let gpu = &gpus[0];
- let sensor = gpu.thermal_settings(None).unwrap()[0];
- println!("{:?}", sensor.current_temperature.0);
- nvapi::unload().unwrap();
-}
+use std::collections::HashMap;\r
+\r
+use wmi::{COMLibrary, Variant, WMIConnection};\r
+\r
+use crate::{\r
+ a770, asus_aura_usb, corsair_lighting_pro, corsair_vengeance, cpu_temperature,\r
+ gigabyte_rgb_fusion_usb, lian_li_sl_infinity, machine, rgb::Rgb, winring0,\r
+};\r
+\r
+pub fn tests() {\r
+ println!("Running some tests...");\r
+\r
+ winring0::init();\r
+\r
+ // test_asus_aura_usb(asus_aura_usb::Motherboard::Asus650e);\r
+ // test_corsair_lighting_pro();\r
+ // test_lianli_sl_infinity();\r
+ // list_usb_devices();\r
+ // test_roccat();\r
+ // test_wmi();\r
+ // test_corsair();\r
+ // test_a770();\r
+ // test_3080ti();\r
+ // test_read_temperature_cpu();\r
+ // test_read_temperature_a770();\r
+ // test_read_temperature_3080();\r
+ test_gigabyte_fusion();\r
+\r
+ winring0::deinit();\r
+\r
+ println!("Press any key to continue...");\r
+ std::io::stdin().read_line(&mut String::new()).unwrap();\r
+}\r
+\r
+fn test_gigabyte_fusion() {\r
+ let api = hidapi::HidApi::new().unwrap();\r
+ let device = gigabyte_rgb_fusion_usb::Device::new(&api).unwrap();\r
+ device.test_raw_data().unwrap();\r
+ // device\r
+ // .set_color(&Rgb {\r
+ // red: 0xFF,\r
+ // green: 0x00,\r
+ // blue: 0x00,\r
+ // })\r
+ // .unwrap();\r
+}\r
+\r
+fn test_wmi() {\r
+ let com_con = COMLibrary::new().unwrap();\r
+ let wmi_con = WMIConnection::new(com_con).unwrap();\r
+\r
+ //let results: Vec<HashMap<String, Variant>> = wmi_con.raw_query("SELECT * FROM Win32_PnPSignedDriver WHERE Description LIKE '%SMBUS%' OR Description LIKE '%SM BUS%'").unwrap();\r
+ //let results: Vec<HashMap<String, Variant>> = wmi_con.raw_query("SELECT * FROM Win32_PnPSignedDriver WHERE Description LIKE 'Intel(R) NF I2C Host Controller'").unwrap();\r
+ let results: Vec<HashMap<String, Variant>> = wmi_con\r
+ .raw_query("SELECT * FROM Win32_PnPSignedDriver")\r
+ .unwrap();\r
+ //let results: Vec<HashMap<String, Variant>> = wmi_con.raw_query("SELECT * FROM Win32_PnPAllocatedResource").unwrap();\r
+\r
+ for os in results {\r
+ println!("-------------------");\r
+ println!("{:#?}", os);\r
+ }\r
+}\r
+\r
+fn list_usb_devices() {\r
+ let api = hidapi::HidApi::new().unwrap();\r
+ for device in api.device_list() {\r
+ println!("{:?}", device);\r
+ println!("name: {}", device.product_string().unwrap());\r
+ println!("interface number: {}", device.interface_number());\r
+ println!("page: {}", device.usage_page());\r
+ println!("usage: {}", device.usage());\r
+ println!("----");\r
+ }\r
+}\r
+\r
+// fn test_roccat() {\r
+// let api = hidapi::HidApi::new().unwrap();\r
+// let roccat_device = roccat::get_device(&api);\r
+\r
+// let manufacturer = roccat_device.get_manufacturer_string().unwrap();\r
+// dbg!(manufacturer);\r
+\r
+// let product = roccat_device.get_product_string().unwrap();\r
+// dbg!(product);\r
+\r
+// let serial = roccat_device.get_serial_number_string().unwrap();\r
+// dbg!(serial);\r
+\r
+// roccat::init(&roccat_device);\r
+// roccat::set_color(\r
+// &roccat_device,\r
+// &RGB {\r
+// red: 0,\r
+// green: 255,\r
+// blue: 40,\r
+// },\r
+// );\r
+// }\r
+\r
+fn test_asus_aura_usb(motherboard: asus_aura_usb::Motherboard) {\r
+ let api = hidapi::HidApi::new().unwrap();\r
+\r
+ let device = asus_aura_usb::Device::new(&api, motherboard).unwrap();\r
+\r
+ println!("Firmware: {}", device.get_firmware_string().unwrap());\r
+\r
+ let configuration = device.get_configuration_table().unwrap();\r
+ println!("Configuration:");\r
+ for i in 0..60 {\r
+ print!("{:02X} ", configuration[i]);\r
+ if (i + 1) % 6 == 0 {\r
+ println!();\r
+ }\r
+ }\r
+ println!("Number of addressable header: {}", configuration[0x02]);\r
+ println!("Number of leds: {}", configuration[0x1B]);\r
+ println!("Number of RGB headers: {}", configuration[0x1D]);\r
+\r
+ device\r
+ .set_color(&Rgb {\r
+ red: 0,\r
+ green: 0,\r
+ blue: 255,\r
+ })\r
+ .unwrap();\r
+\r
+ device.save_current_color().unwrap();\r
+}\r
+\r
+fn test_corsair_lighting_pro() {\r
+ let api = hidapi::HidApi::new().unwrap();\r
+ let device = corsair_lighting_pro::Device::new(\r
+ &api,\r
+ &Rgb {\r
+ red: 0,\r
+ green: 255,\r
+ blue: 0,\r
+ },\r
+ )\r
+ .unwrap();\r
+\r
+ for i in 0..=255 {\r
+ if i % 10 == 0 || i == 255 || i == 0 {\r
+ device\r
+ .set_color(&Rgb {\r
+ red: i as u8,\r
+ green: 255u8 - i as u8,\r
+ blue: 0,\r
+ })\r
+ .unwrap();\r
+ std::thread::sleep(std::time::Duration::from_millis(200));\r
+ }\r
+ }\r
+}\r
+\r
+fn test_lianli_sl_infinity() {\r
+ let api = hidapi::HidApi::new().unwrap();\r
+ let device = lian_li_sl_infinity::Device::new(&api).unwrap();\r
+\r
+ device\r
+ .set_color(&Rgb {\r
+ red: 0,\r
+ green: 0,\r
+ blue: 255,\r
+ })\r
+ .unwrap();\r
+}\r
+\r
+fn test_corsair() {\r
+ let corsair_controllers = [\r
+ corsair_vengeance::Controller::new(0x19),\r
+ corsair_vengeance::Controller::new(0x1B),\r
+ ];\r
+\r
+ for controller in corsair_controllers {\r
+ controller.set_color(&Rgb {\r
+ red: 0,\r
+ green: 0,\r
+ blue: 255,\r
+ });\r
+ }\r
+}\r
+\r
+fn test_a770() {\r
+ // a770::set_rgb(255, 0, 0);\r
+ let mut a770 = a770::A770::new().unwrap();\r
+ a770.set_color(255, 0, 0).unwrap();\r
+}\r
+\r
+fn test_3080ti() {\r
+ let machine: &mut dyn machine::Machine =\r
+ &mut machine::lyss_metal::MachineLyssMetal::new().unwrap();\r
+\r
+ machine\r
+ .set_color(&Rgb {\r
+ red: 255,\r
+ green: 0,\r
+ blue: 0,\r
+ })\r
+ .unwrap();\r
+}\r
+\r
+const F17H_M01H_THM_TCON_CUR_TMP: u32 = 0x00059800;\r
+const F17H_TEMP_OFFSET_FLAG: u32 = 0x80000;\r
+const FAMILY_17H_PCI_CONTROL_REGISTER: u32 = 0x60;\r
+\r
+fn test_read_temperature_cpu() {\r
+ println!("temp cpu: {}", cpu_temperature::read())\r
+}\r
+\r
+fn test_read_temperature_a770() {\r
+ let jiji: &dyn machine::Machine = &machine::jiji::MachineJiji::new().unwrap();\r
+ println!("temp gpu: {}", jiji.get_gpu_tmp());\r
+}\r
+\r
+fn test_read_temperature_3080() {\r
+ nvapi::initialize().expect("Unable to initialize nvapi (Nvidia API)");\r
+ // if let Ok(gpus) = {\r
+ // for gpu in gpus {\r
+ // let thermal = gpu.thermal_settings(None).unwrap()[0];\r
+ // println!("{:?}", thermal.current_temperature.0)\r
+ // }\r
+ // }\r
+ let gpus = nvapi::PhysicalGpu::enumerate().unwrap();\r
+ let gpu = &gpus[0];\r
+ let sensor = gpu.thermal_settings(None).unwrap()[0];\r
+ println!("{:?}", sensor.current_temperature.0);\r
+ nvapi::unload().unwrap();\r
+}\r