Add support for Corsair Lighting Pro
[temp2RGB.git] / src / corsair_lighting_pro.rs
1 use crate::rgb::RGB;
2
3 const CORSAIR_VID: u16 = 0x1B1C;
4 const CORSAIR_LIGHTING_NODE_PRO_PID: u16 = 0x0C0B;
5
6 const CORSAIR_LIGHTING_NODE_PACKET_ID_FIRMWARE: u8 = 0x02; // Get firmware version
7 const CORSAIR_LIGHTING_NODE_PACKET_ID_DIRECT: u8 = 0x32; // Direct mode LED update packet
8 const CORSAIR_LIGHTING_NODE_PACKET_ID_COMMIT: u8 = 0x33; // Commit changes packet
9 const CORSAIR_LIGHTING_NODE_PACKET_ID_BEGIN: u8 = 0x34; // Begin effect packet
10 const CORSAIR_LIGHTING_NODE_PACKET_ID_EFFECT_CONFIG: u8 = 0x35; // Effect mode configuration packet
11 const CORSAIR_LIGHTING_NODE_PACKET_ID_TEMPERATURE: u8 = 0x36; // Update temperature value packet
12 const CORSAIR_LIGHTING_NODE_PACKET_ID_RESET: u8 = 0x37; // Reset channel packet
13 const CORSAIR_LIGHTING_NODE_PACKET_ID_PORT_STATE: u8 = 0x38; // Set port state packet
14 const CORSAIR_LIGHTING_NODE_PACKET_ID_BRIGHTNESS: u8 = 0x39; // Set brightness packet
15 const CORSAIR_LIGHTING_NODE_PACKET_ID_LED_COUNT: u8 = 0x3A; // Set LED count packet
16 const CORSAIR_LIGHTING_NODE_PACKET_ID_PROTOCOL: u8 = 0x3B; // Set protocol packet
17
18 const CORSAIR_LIGHTING_NODE_PORT_STATE_HARDWARE: u8 = 0x01; // Effect hardware control of channel
19 const CORSAIR_LIGHTING_NODE_PORT_STATE_SOFTWARE: u8 = 0x02; // Direct software control of channel
20
21 const CORSAIR_LIGHTING_NODE_MODE_STATIC: u8 = 0x04; // Static mode
22
23 const CHANNEL_COUNT: u8 = 2;
24
25 pub struct Device {
26 device: hidapi::HidDevice,
27 }
28
29 impl Device {
30 pub fn new(api: &hidapi::HidApi) -> Self {
31 let device = Device {
32 device: api
33 .open(CORSAIR_VID, CORSAIR_LIGHTING_NODE_PRO_PID)
34 .unwrap(),
35 };
36
37 for channel_id in 0..CHANNEL_COUNT {
38 device.send_reset(channel_id);
39 device.send_begin(channel_id);
40 device.send_port_state(channel_id, CORSAIR_LIGHTING_NODE_PORT_STATE_HARDWARE);
41 device.send_effect_config(
42 channel_id,
43 &RGB {
44 red: 0x00,
45 green: 0x00,
46 blue: 0x00,
47 },
48 );
49 device.send_commit(channel_id);
50 }
51
52 device
53 }
54
55 pub fn set_color(&self, color: &RGB) {
56 for channel_id in 0..CHANNEL_COUNT {
57 self.send_effect_config(channel_id, color);
58 }
59 }
60
61 fn send_reset(&self, channel_id: u8) {
62 let mut buffer = [0u8; 65];
63 buffer[0x01] = CORSAIR_LIGHTING_NODE_PACKET_ID_RESET;
64 buffer[0x02] = channel_id;
65
66 let n_write = self.device.write(&buffer).unwrap();
67 assert_eq!(n_write, 65);
68
69 let n_read = self.device.read(&mut buffer[0..16]).unwrap();
70 assert_eq!(n_read, 16);
71 }
72
73 fn send_begin(&self, channel_id: u8) {
74 let mut buffer = [0u8; 65];
75 buffer[0x01] = CORSAIR_LIGHTING_NODE_PACKET_ID_BEGIN;
76 buffer[0x02] = channel_id;
77
78 let n_write = self.device.write(&buffer).unwrap();
79 assert_eq!(n_write, 65);
80
81 let n_read = self.device.read(&mut buffer[0..16]).unwrap();
82 assert_eq!(n_read, 16);
83 }
84
85 fn send_port_state(&self, channel_id: u8, state: u8) {
86 let mut buffer = [0u8; 65];
87 buffer[0x01] = CORSAIR_LIGHTING_NODE_PACKET_ID_PORT_STATE;
88 buffer[0x02] = channel_id;
89 buffer[0x03] = state;
90
91 let n_write = self.device.write(&buffer).unwrap();
92 assert_eq!(n_write, 65);
93
94 let n_read = self.device.read(&mut buffer[0..16]).unwrap();
95 assert_eq!(n_read, 16);
96 }
97
98 fn send_effect_config(&self, channel_id: u8, color: &RGB) {
99 let mut buffer = [0u8; 65];
100 buffer[0x01] = CORSAIR_LIGHTING_NODE_PACKET_ID_EFFECT_CONFIG;
101 buffer[0x02] = channel_id;
102 buffer[0x03] = 0x00; // count.
103 buffer[0x04] = 0x1E; // led type.
104 buffer[0x05] = CORSAIR_LIGHTING_NODE_MODE_STATIC; // mode: static.
105 buffer[0x06] = 0x00; // speed.
106 buffer[0x07] = 0x00; // direction.
107 buffer[0x08] = 0x00; // change style (random).
108 buffer[0x09] = 0x00;
109
110 let offset_color = 0x0A;
111 for i in 0..3 {
112 buffer[offset_color + 3 * i] = color.red;
113 buffer[offset_color + 3 * i + 1] = color.green;
114 buffer[offset_color + 3 * i + 2] = color.blue;
115 }
116
117 let n_write = self.device.write(&buffer).unwrap();
118 assert_eq!(n_write, 65);
119
120 let n_read = self.device.read(&mut buffer[0..16]).unwrap();
121 assert_eq!(n_read, 16);
122 }
123
124 fn send_commit(&self, channel_id: u8) {
125 let mut buffer = [0u8; 65];
126 buffer[0x01] = CORSAIR_LIGHTING_NODE_PACKET_ID_COMMIT;
127 buffer[0x02] = 0xFF;
128
129 let n_write = self.device.write(&buffer).unwrap();
130 assert_eq!(n_write, 65);
131
132 let n_read = self.device.read(&mut buffer[0..16]).unwrap();
133 assert_eq!(n_read, 16);
134 }
135 }