Implement 'set_color' for corsair lighting pro
authorGreg Burri <greg.burri@gmail.com>
Thu, 21 Sep 2023 08:11:07 +0000 (10:11 +0200)
committerGreg Burri <greg.burri@gmail.com>
Thu, 21 Sep 2023 08:11:07 +0000 (10:11 +0200)
Cargo.toml
src/asus_aura_usb.rs
src/corsair_lighting_pro.rs
src/machine.rs
src/main_loop.rs
src/piix4_i2c.rs
src/tests.rs

index ee00d9c..b44964a 100644 (file)
@@ -26,6 +26,9 @@ windows-service = "0.6"
 # USB and Bluetooth HID-Class devices.
 hidapi = "2.4"
 
+# Nvidia API.
+nvapi = "0.1"
+
 libc = "0.2"
 wmi = "0.13"
 crc = "3.0"
index 74face1..01590c0 100644 (file)
@@ -28,18 +28,22 @@ pub struct Device {
 
 impl Device {
     pub fn new(api: &hidapi::HidApi, motherboard: Motherboard) -> Self {
-        Device {
-            device: api
-                .open(
-                    VID,
-                    match motherboard {
-                        Motherboard::Asus650e => PID_650_E,
-                        Motherboard::AsusCrosshairVIIIHero => PID_CROSSHAIR,
-                    },
-                )
-                .unwrap(),
-            motherboard,
-        }
+        let device =
+            Device {
+                device: api
+                    .open(
+                        VID,
+                        match motherboard {
+                            Motherboard::Asus650e => PID_650_E,
+                            Motherboard::AsusCrosshairVIIIHero => PID_CROSSHAIR,
+                        },
+                    )
+                    .unwrap(),
+                motherboard,
+            };
+
+        device.set_fixed_mode();
+        device
     }
 
     pub fn get_firmware_string(&self) -> String {
@@ -91,7 +95,7 @@ impl Device {
             .expect("slice with incorrect length")
     }
 
-    pub fn set_fixed_mode(&self) {
+    fn set_fixed_mode(&self) {
         let mut buffer = [0u8; 65];
         buffer[0] = 0xEC;
         buffer[1] = 0x35; // Control mode.
index 48bef11..7ccb373 100644 (file)
@@ -20,14 +20,19 @@ const CORSAIR_LIGHTING_NODE_PORT_STATE_SOFTWARE: u8 = 0x02; // Direct software c
 
 const CORSAIR_LIGHTING_NODE_MODE_STATIC: u8 = 0x04; // Static mode
 
+const CORSAIR_LIGHTING_NODE_DIRECT_CHANNEL_RED: u8 = 0x00;
+const CORSAIR_LIGHTING_NODE_DIRECT_CHANNEL_GREEN: u8 = 0x01;
+const CORSAIR_LIGHTING_NODE_DIRECT_CHANNEL_BLUE: u8 = 0x02;
+
 const CHANNEL_COUNT: u8 = 2;
+const NB_LEDS: u8 = 20;
 
 pub struct Device {
     device: hidapi::HidDevice,
 }
 
 impl Device {
-    pub fn new(api: &hidapi::HidApi) -> Self {
+    pub fn new(api: &hidapi::HidApi, initial_color: &RGB) -> Self {
         let device = Device {
             device: api
                 .open(CORSAIR_VID, CORSAIR_LIGHTING_NODE_PRO_PID)
@@ -38,26 +43,13 @@ impl Device {
             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,
-                &RGB {
-                    red: 0x00,
-                    green: 0x00,
-                    blue: 0x00,
-                },
-            );
+            device.send_effect_config(channel_id, initial_color);
             device.send_commit(channel_id);
         }
 
         device
     }
 
-    pub fn set_color(&self, color: &RGB) {
-        for channel_id in 0..CHANNEL_COUNT {
-            self.send_effect_config(channel_id, color);
-        }
-    }
-
     fn send_reset(&self, channel_id: u8) {
         let mut buffer = [0u8; 65];
         buffer[0x01] = CORSAIR_LIGHTING_NODE_PACKET_ID_RESET;
@@ -68,6 +60,7 @@ impl Device {
 
         let n_read = self.device.read(&mut buffer[0..16]).unwrap();
         assert_eq!(n_read, 16);
+        assert_eq!(buffer[0], 0);
     }
 
     fn send_begin(&self, channel_id: u8) {
@@ -80,6 +73,7 @@ impl Device {
 
         let n_read = self.device.read(&mut buffer[0..16]).unwrap();
         assert_eq!(n_read, 16);
+        assert_eq!(buffer[0], 0);
     }
 
     fn send_port_state(&self, channel_id: u8, state: u8) {
@@ -93,14 +87,17 @@ impl Device {
 
         let n_read = self.device.read(&mut buffer[0..16]).unwrap();
         assert_eq!(n_read, 16);
+        assert_eq!(buffer[0], 0);
     }
 
     fn send_effect_config(&self, channel_id: u8, color: &RGB) {
+        println!("{color:?}");
+
         let mut buffer = [0u8; 65];
         buffer[0x01] = CORSAIR_LIGHTING_NODE_PACKET_ID_EFFECT_CONFIG;
         buffer[0x02] = channel_id;
         buffer[0x03] = 0x00; // count.
-        buffer[0x04] = 0x1E; // led type.
+        buffer[0x04] = NB_LEDS; // led type. (number of leds!?).
         buffer[0x05] = CORSAIR_LIGHTING_NODE_MODE_STATIC; // mode: static.
         buffer[0x06] = 0x00; // speed.
         buffer[0x07] = 0x00; // direction.
@@ -119,6 +116,7 @@ impl Device {
 
         let n_read = self.device.read(&mut buffer[0..16]).unwrap();
         assert_eq!(n_read, 16);
+        assert_eq!(buffer[0], 0);
     }
 
     fn send_commit(&self, channel_id: u8) {
@@ -131,5 +129,45 @@ impl Device {
 
         let n_read = self.device.read(&mut buffer[0..16]).unwrap();
         assert_eq!(n_read, 16);
+        assert_eq!(buffer[0], 0);
+    }
+
+    pub fn set_color(&self, color: &RGB) {
+        // println!("set_color: {color:?}");
+        for channel_id in 0..CHANNEL_COUNT {
+            self.send_port_state(channel_id, CORSAIR_LIGHTING_NODE_PORT_STATE_SOFTWARE);
+
+            let mut buffer = [0u8; 65];
+
+            for color_channel in [
+                CORSAIR_LIGHTING_NODE_DIRECT_CHANNEL_RED,
+                CORSAIR_LIGHTING_NODE_DIRECT_CHANNEL_GREEN,
+                CORSAIR_LIGHTING_NODE_DIRECT_CHANNEL_BLUE,
+            ] {
+                buffer[0x01] = CORSAIR_LIGHTING_NODE_PACKET_ID_DIRECT;
+                buffer[0x02] = channel_id;
+                buffer[0x04] = NB_LEDS; // Number of color;
+                buffer[0x05] = color_channel;
+
+                let color_component =  match color_channel {
+                    0 => color.red,
+                    1 => color.green,
+                    _ => color.blue,
+                };
+
+                for n in 0..NB_LEDS {
+                    buffer[0x06 + n as usize] = color_component;
+                }
+
+                let n_write = self.device.write(&buffer).unwrap();
+                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);
+            }
+
+            self.send_commit(channel_id);
+        }
     }
 }
index 6bb3bfc..9436f49 100644 (file)
@@ -1,4 +1,6 @@
-use crate::{a770, asus_aura_usb, corsair_vengeance, cpu_temperature, intel_arc, rgb};
+use crate::{
+    a770, asus_aura_usb, corsair_lighting_pro, corsair_vengeance, cpu_temperature, intel_arc, rgb,
+};
 
 pub trait Machine {
     fn set_color(&mut self, color: &rgb::RGB);
@@ -16,7 +18,7 @@ pub struct MachineJiji {
 impl MachineJiji {
     pub fn new() -> Self {
         let api = hidapi::HidApi::new().unwrap();
-        let machine = MachineJiji {
+        MachineJiji {
             ram: vec![
                 corsair_vengeance::Controller::new(0x19),
                 corsair_vengeance::Controller::new(0x1B),
@@ -24,9 +26,7 @@ impl MachineJiji {
             b650e_device: asus_aura_usb::Device::new(&api, asus_aura_usb::Motherboard::Asus650e),
             a770: a770::A770::new(),
             gpu_devices: unsafe { intel_arc::GetDevices() },
-        };
-        machine.b650e_device.set_fixed_mode();
-        machine
+        }
     }
 }
 
@@ -56,4 +56,49 @@ impl Drop for MachineJiji {
     }
 }
 
-struct MachineLyssMetal {}
+pub struct MachineLyssMetal {
+    crosshair_device: asus_aura_usb::Device,
+    corsair_lignting_pro: corsair_lighting_pro::Device,
+    gpus: Vec<nvapi::PhysicalGpu>,
+}
+
+impl MachineLyssMetal {
+    pub fn new() -> Self {
+        let api = hidapi::HidApi::new().unwrap();
+
+        nvapi::initialize().expect("Unable to initialize nvapi (Nvidia API)");
+
+        MachineLyssMetal {
+            crosshair_device: asus_aura_usb::Device::new(
+                &api,
+                asus_aura_usb::Motherboard::AsusCrosshairVIIIHero,
+            ),
+            corsair_lignting_pro: corsair_lighting_pro::Device::new(
+                &api,
+                &rgb::RGB {
+                    red: 0,
+                    green: 255,
+                    blue: 40,
+                },
+            ),
+            gpus: nvapi::PhysicalGpu::enumerate().unwrap(),
+        }
+    }
+}
+
+impl Machine for MachineLyssMetal {
+    fn set_color(&mut self, color: &rgb::RGB) {
+        self.crosshair_device.set_color(&color);
+        self.corsair_lignting_pro.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()
+    }
+}
index ae4c221..c787250 100644 (file)
@@ -23,7 +23,10 @@ pub fn main_loop(completed: Arc<AtomicBool>) {
     let settings = settings::Settings::read(consts::FILE_CONF).expect("Cannot load settings");
     println!("Settings: {settings:?}");
 
-    let machine: &mut dyn machine::Machine = &mut machine::MachineJiji::new();
+    let mut machine: Box<dyn machine::Machine> = match settings.machine_name {
+        settings::MachineName::Jiji => Box::new(machine::MachineJiji::new()),
+        settings::MachineName::LyssMetal => Box::new(machine::MachineLyssMetal::new()),
+    };
 
     let mut kernel = [0f32; consts::KERNEL_SIZE_SAMPLES];
     let mut current_pos = 0usize;
index ae974b7..7acc572 100644 (file)
@@ -1,4 +1,5 @@
 // Partial implementation for PCI IDE ISA Xcelerator.
+// https://www.kernel.org/doc/html/latest/i2c/summary.html
 
 use std::time::Duration;
 
index 1321005..09c75e4 100644 (file)
@@ -12,15 +12,16 @@ pub fn tests() {
 
     winring0::init();
 
-    // test_asus_aura_usb(asus_aura_usb::Motherboard::AsusCrosshairVIIIHero);
+    test_asus_aura_usb(asus_aura_usb::Motherboard::AsusCrosshairVIIIHero);
     // test_corsair_lighting_pro();
     // list_usb_devices();
     // test_roccat();
     // test_wmi();
     // test_corsair();
     // test_a770();
-    test_read_temperature_cpu();
-    // test_read_temperatur_a770
+    // test_read_temperature_cpu();
+    // test_read_temperature_a770()
+    // test_read_temperature_3080();
 
     winring0::deinit();
 
@@ -100,9 +101,6 @@ fn test_asus_aura_usb(motherboard: asus_aura_usb::Motherboard) {
     println!("Number of leds: {}", configuration[0x1B]);
     println!("Number of RGB headers: {}", configuration[0x1D]);
 
-    // Only once, at start.
-    device.set_fixed_mode();
-
     device.set_color(&RGB {
         red: 0,
         green: 0,
@@ -114,13 +112,25 @@ fn test_asus_aura_usb(motherboard: asus_aura_usb::Motherboard) {
 
 fn test_corsair_lighting_pro() {
     let api = hidapi::HidApi::new().unwrap();
-    let device = corsair_lighting_pro::Device::new(&api);
-
-    device.set_color(&RGB {
-        red: 0,
-        green: 0,
-        blue: 255,
-    });
+    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_corsair() {
@@ -128,6 +138,7 @@ fn test_corsair() {
         corsair_vengeance::Controller::new(0x19),
         corsair_vengeance::Controller::new(0x1B),
     ];
+
     for controller in corsair_controllers {
         controller.set_color(&RGB {
             red: 0,
@@ -151,8 +162,22 @@ fn test_read_temperature_cpu() {
     println!("temp cpu: {}", cpu_temperature::read())
 }
 
-fn test_read_temperatur_a770() {
+fn test_read_temperature_a770() {
     let jiji: &dyn machine::Machine = &machine::MachineJiji::new();
     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();
+}