Add support for Corsair Lighting Pro
[temp2RGB.git] / src / asus_aura_usb.rs
diff --git a/src/asus_aura_usb.rs b/src/asus_aura_usb.rs
new file mode 100644 (file)
index 0000000..74face1
--- /dev/null
@@ -0,0 +1,139 @@
+use std::str;
+
+use crate::rgb::RGB;
+
+/*
+ * Doc:
+ *  - https://blog.inlart.com/post/openrgb-asus-x570/
+ *  - https://openrgb-wiki.readthedocs.io/en/latest/asus/ASUS-Aura-USB/
+ */
+
+const AURA_REQUEST_FIRMWARE_VERSION: u8 = 0x82;
+const AURA_REQUEST_CONFIG_TABLE: u8 = 0xB0;
+
+const VID: u16 = 0x0B05; // Vendor ID: ASUS.
+
+const PID_650_E: u16 = 0x19AF; // Product ID: AURA LED Controller.
+const PID_CROSSHAIR: u16 = 0x18F3; // Product ID: AURA LED Controller.
+
+pub enum Motherboard {
+    Asus650e,
+    AsusCrosshairVIIIHero,
+}
+
+pub struct Device {
+    device: hidapi::HidDevice,
+    motherboard: Motherboard,
+}
+
+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,
+        }
+    }
+
+    pub fn get_firmware_string(&self) -> String {
+        let mut buffer = [0u8; 65];
+        buffer[0] = 0xEC;
+        buffer[1] = AURA_REQUEST_FIRMWARE_VERSION;
+        let n_write = self.device.write(&buffer).unwrap();
+        assert_eq!(n_write, 65);
+
+        buffer.fill(0);
+        let n_read = self.device.read(&mut buffer).unwrap();
+        assert_eq!(n_read, 65);
+        assert_eq!(buffer[0], 0xEC);
+        assert_eq!(buffer[1], 0x02);
+
+        String::from(str::from_utf8(&buffer[2..17]).unwrap())
+    }
+
+    /*
+    Example of configuration table:
+    - Positions 0 and 1 always 1E and 9F.
+    - Value 02 is the number of adressable channels.
+    1E 9F 02 01 00 00
+    78 3C 00 01 00 00
+    78 3C 00 00 00 00
+    00 00 00 00 00 00
+    00 00 00 08 0A 02
+    01 F4 00 00 00 00
+    00 00 00 00 00 00
+    00 00 00 00 00 00
+    00 00 00 00 00 00
+    00 00 00 00 00 00
+    */
+    pub fn get_configuration_table(&self) -> [u8; 60] {
+        let mut buffer = [0u8; 65];
+        buffer[0] = 0xEC;
+        buffer[1] = AURA_REQUEST_CONFIG_TABLE;
+        let n_write = self.device.write(&buffer).unwrap();
+        assert_eq!(n_write, 65);
+
+        buffer.fill(0);
+        let n_read = self.device.read(&mut buffer).unwrap();
+        assert_eq!(n_read, 65);
+        assert_eq!(buffer[0], 0xEC);
+        assert_eq!(buffer[1], 0x30);
+
+        buffer[4..64]
+            .try_into()
+            .expect("slice with incorrect length")
+    }
+
+    pub fn set_fixed_mode(&self) {
+        let mut buffer = [0u8; 65];
+        buffer[0] = 0xEC;
+        buffer[1] = 0x35; // Control mode.
+        buffer[4] = 0x00; // Shutdown effect.
+        buffer[5] = 0x01; // Mode id: static.
+
+        for channel_effect_id in 0..2 {
+            buffer[2] = channel_effect_id; // Channel effect id: Fixed.
+            let n_write = self.device.write(&buffer).unwrap();
+            assert_eq!(n_write, 65);
+        }
+    }
+
+    pub fn set_color(&self, color: &RGB) {
+        let mut buffer = [0u8; 65];
+        buffer[0] = 0xEC;
+        buffer[1] = 0x36;
+
+        let start_led = 0u32;
+        let nb_of_leds = 16u32;
+        let mask = ((1u32 << nb_of_leds) - 1u32) << start_led;
+
+        buffer[2] = (mask >> 8) as u8; // 16 bits LED mask: first part.
+        buffer[3] = (mask & 0xFF) as u8; // 16 bits LED mask: second part.
+
+        for n in start_led as usize..(start_led + nb_of_leds) as usize {
+            buffer[5 + 3 * n] = color.red;
+            buffer[5 + 3 * n + 1] = color.green;
+            buffer[5 + 3 * n + 2] = color.blue;
+        }
+
+        let n_write = self.device.write(&buffer).unwrap();
+        assert_eq!(n_write, 65);
+    }
+
+    pub fn save_current_color(&self) {
+        let mut buffer = [0u8; 65];
+        buffer[0] = 0xEC;
+        buffer[1] = 0x3F;
+        buffer[2] = 0x55;
+
+        let n_write = self.device.write(&buffer).unwrap();
+        assert_eq!(n_write, 65);
+    }
+}