log-panics = { version = "2", features = ["with-backtrace"] }
log = "0.4"
-windows-service = "0.6"
+windows-service = "0.7"
# HIDAPI is a library which allows an application to interface with
# USB and Bluetooth HID-Class devices.
# netcorehost = "0.15"
[dependencies.windows]
-version = "0.54"
+version = "0.56"
features = [
"Win32_Foundation",
"Win32_Security",
--- /dev/null
+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 {
+ let device = Device {
+ device: api.open(LIANLI_VID, LIANLI_UNI_HUB_SLINF_PID).unwrap(),
+ };
+
+ device
+ }
+
+ 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::{
/*a770,*/ asus_aura_usb, corsair_lighting_pro, corsair_vengeance, cpu_temperature,
- intel_arc, rgb,
+ intel_arc, lian_li_sl_infinity, rgb,
};
const RGB_FUSION2_GPU_REG_COLOR: u8 = 0x40;
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>,
}
blue: 40,
},
),
+ lian_li_sl_infinity: lian_li_sl_infinity::Device::new(&api),
gpus: nvapi::PhysicalGpu::enumerate()?,
};
impl Machine for MachineLyssMetal {
fn set_color(&mut self, color: &rgb::RGB) {
- self.crosshair_device.set_color(&color);
+ self.crosshair_device.set_color(&color).unwrap();
self.corsair_lignting_pro.set_color(&color);
+ self.lian_li_sl_infinity.set_color(&color);
// self.set_color_3080ti(&color); // TODO.
}
mod a770;
mod asus_aura_usb;
mod corsair_lighting_pro;
+mod lian_li_sl_infinity;
mod machine;
mod main_loop;
mod winring0;
use wmi::{COMLibrary, Variant, WMIConnection};
use crate::{
- a770, asus_aura_usb, corsair_lighting_pro, corsair_vengeance, cpu_temperature, machine,
- rgb::RGB, winring0, wrapper_winring0,
+ a770, asus_aura_usb, corsair_lighting_pro, corsair_vengeance, cpu_temperature,
+ lian_li_sl_infinity, machine, rgb::RGB, winring0, wrapper_winring0,
};
pub fn tests() {
// test_asus_aura_usb(asus_aura_usb::Motherboard::Asus650e);
// test_corsair_lighting_pro();
+ test_lianli_sl_infinity();
// list_usb_devices();
// test_roccat();
// test_wmi();
// test_3080ti();
// test_read_temperature_cpu();
// test_read_temperature_a770();
- test_read_temperature_3080();
+ // test_read_temperature_3080();
winring0::deinit();
}
}
+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),