Remove a lot of 'unwrap'
authorGreg Burri <greg.burri@gmail.com>
Wed, 19 Mar 2025 17:16:03 +0000 (18:16 +0100)
committerGreg Burri <greg.burri@gmail.com>
Wed, 19 Mar 2025 17:16:03 +0000 (18:16 +0100)
19 files changed:
Cargo.toml
build.rs
src/a770.rs
src/asus_aura_usb.rs
src/common.rs [deleted file]
src/corsair_lighting_pro.rs
src/corsair_vengeance.rs
src/gigabyte_rgb_fusion_usb.rs
src/lian_li_sl_infinity.rs
src/machine/jiji.rs
src/machine/lyss_metal.rs
src/machine/lyss_metal2.rs
src/machine/mod.rs
src/main.rs
src/main_loop.rs
src/piix4_i2c.rs
src/rgb.rs
src/settings.rs
src/tests.rs

index ce95993..d14eea0 100644 (file)
@@ -1,63 +1,66 @@
-[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
index 6612712..59d15d9 100644 (file)
--- a/build.rs
+++ b/build.rs
@@ -1,89 +1,90 @@
-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
index ed6c18e..8edfcb6 100644 (file)
@@ -1,77 +1,77 @@
-// 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
index 31a2b27..2f8591d 100644 (file)
@@ -1,6 +1,6 @@
 use std::str;
 
-use crate::rgb::RGB;
+use crate::rgb::Rgb;
 
 /*
  * Doc:
@@ -48,13 +48,13 @@ impl Device {
         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])?))
     }
@@ -79,13 +79,13 @@ impl Device {
         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()?)
     }
@@ -100,12 +100,12 @@ impl Device {
         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;
@@ -124,7 +124,7 @@ impl Device {
         }
 
         let n_write = self.device.write(&buffer)?;
-        assert_eq!(n_write, 65);
+        // assert_eq!(n_write, 65);
         Ok(())
     }
 
@@ -135,7 +135,7 @@ impl Device {
         buffer[2] = 0x55;
 
         let n_write = self.device.write(&buffer)?;
-        assert_eq!(n_write, 65);
+        // assert_eq!(n_write, 65);
         Ok(())
     }
 }
diff --git a/src/common.rs b/src/common.rs
deleted file mode 100644 (file)
index e69de29..0000000
index 25bee13..957326b 100644 (file)
@@ -1,4 +1,4 @@
-use crate::rgb::RGB;
+use crate::rgb::Rgb;
 
 const CORSAIR_VID: u16 = 0x1B1C;
 const CORSAIR_LIGHTING_NODE_PRO_PID: u16 = 0x0C0B;
@@ -32,65 +32,69 @@ pub struct Device {
 }
 
 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];
@@ -111,31 +115,35 @@ impl Device {
             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];
 
@@ -159,15 +167,17 @@ impl Device {
                     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(())
     }
 }
index 0c574f0..f1899dc 100644 (file)
-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
index c9667be..0ecd9a7 100644 (file)
@@ -1,6 +1,6 @@
 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.
@@ -23,8 +23,7 @@ impl Device {
             .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 };
 
@@ -136,7 +135,7 @@ cc62390039ab4543 ab4543ab4543ab45 43ab4543ab4543ab4543ab4543ab4543ab4543ab4543ab
 
     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];
@@ -165,7 +164,7 @@ cc62390039ab4543 ab4543ab4543ab45 43ab4543ab4543ab4543ab4543ab4543ab4543ab4543ab
         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;
@@ -194,13 +193,15 @@ cc62390039ab4543 ab4543ab4543ab45 43ab4543ab4543ab4543ab4543ab4543ab4543ab4543ab
         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(())
     }
 }
index cd3e149..af0e640 100644 (file)
@@ -1,85 +1,91 @@
-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
index 402d9a4..d4e7841 100644 (file)
@@ -1,57 +1,60 @@
-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
index ba4cc43..adf8205 100644 (file)
-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
index f96d213..f5ec827 100644 (file)
-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
index 0ed2ff5..f6cddfe 100644 (file)
@@ -1,21 +1,22 @@
-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
index ff87264..ed4eccb 100644 (file)
-#[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
index 1d523b3..a8b7618 100644 (file)
@@ -1,11 +1,13 @@
 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>) {
@@ -98,12 +100,15 @@ 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;
index 7397459..8138e06 100644 (file)
-// 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
index a6217c7..9152459 100644 (file)
@@ -1,17 +1,17 @@
-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
index 43ae03d..54c880b 100644 (file)
@@ -1,64 +1,64 @@
-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
index c7ea81c..c0d0ad4 100644 (file)
-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