Add support for Lian Li SL Infinity fan controller
[temp2RGB.git] / src / lian_li_sl_infinity.rs
1 use crate::rgb::RGB;
2
3 const LIANLI_VID: u16 = 0x0CF2;
4 const LIANLI_UNI_HUB_SLINF_PID: u16 = 0xA102;
5
6 const UNIHUB_SLINF_LED_MODE_STATIC_COLOR: u8 = 0x01;
7 const UNIHUB_SLINF_LED_SPEED_000: u8 = 0x02;
8 const UNIHUB_SLINF_LED_DIRECTION_LTR: u8 = 0x00;
9 const UNIHUB_SLINF_LED_BRIGHTNESS_100: u8 = 0x00;
10
11 const UNIHUB_SLINF_TRANSACTION_ID: u8 = 0xE0;
12
13 const BUFFER_SIZE: usize = 353;
14
15 const NB_LEDS_PER_FAN: u8 = 8;
16 const NB_LEDS_PER_SIDE: u8 = 12;
17
18 // Specific hardcoded values (should be given in the constructor).
19 const CHANNEL_COUNT: u8 = 4; // 2 Channel per line of fans: one for fan itself and one for sides.
20 const NB_FAN_PER_CHANNEL: u8 = 2; // 2 fans per channel.
21
22 pub struct Device {
23 device: hidapi::HidDevice,
24 }
25
26 impl Device {
27 pub fn new(api: &hidapi::HidApi) -> Self {
28 let device = Device {
29 device: api.open(LIANLI_VID, LIANLI_UNI_HUB_SLINF_PID).unwrap(),
30 };
31
32 device
33 }
34
35 fn send_start_action(&self, channel_id: u8) {
36 let mut buffer = [0u8; 5];
37 buffer[0x00] = UNIHUB_SLINF_TRANSACTION_ID;
38 buffer[0x01] = 0x10;
39 buffer[0x02] = 0x60;
40 buffer[0x03] = 1 + channel_id / 2;
41 buffer[0x04] = NB_FAN_PER_CHANNEL;
42
43 let n_write = self.device.write(&buffer).unwrap();
44 assert_eq!(n_write, BUFFER_SIZE);
45 }
46
47 fn send_commit_data(&self, channel_id: u8) {
48 let mut buffer = [0u8; 6];
49 buffer[0x00] = UNIHUB_SLINF_TRANSACTION_ID;
50 buffer[0x01] = 0x10 + channel_id;
51 buffer[0x02] = UNIHUB_SLINF_LED_MODE_STATIC_COLOR;
52 buffer[0x03] = UNIHUB_SLINF_LED_SPEED_000;
53 buffer[0x04] = UNIHUB_SLINF_LED_DIRECTION_LTR;
54 buffer[0x05] = UNIHUB_SLINF_LED_BRIGHTNESS_100;
55
56 let n_write = self.device.write(&buffer).unwrap();
57 assert_eq!(n_write, BUFFER_SIZE);
58 }
59
60 pub fn set_color(&self, color: &RGB) {
61 for channel_id in 0..CHANNEL_COUNT {
62 self.send_start_action(channel_id);
63
64 let mut buffer = [0u8; BUFFER_SIZE];
65 buffer[0x00] = UNIHUB_SLINF_TRANSACTION_ID;
66 buffer[0x01] = 0x30 + channel_id;
67
68 let nb_leds = if channel_id % 2 == 0 {
69 NB_LEDS_PER_FAN * NB_FAN_PER_CHANNEL
70 } else {
71 NB_LEDS_PER_SIDE * NB_FAN_PER_CHANNEL
72 };
73
74 for i in 0..(26 as usize) {
75 let pos = i * 3 + 2;
76 buffer[pos] = color.red;
77 buffer[pos + 1] = color.blue;
78 buffer[pos + 2] = color.green;
79 }
80
81 let n_write = self.device.write(&buffer).unwrap();
82 assert_eq!(n_write, buffer.len());
83
84 self.send_commit_data(channel_id);
85 }
86 }
87 }