Implement 'set_color' for corsair lighting pro
[temp2RGB.git] / src / asus_aura_usb.rs
1 use std::str;
2
3 use crate::rgb::RGB;
4
5 /*
6 * Doc:
7 * - https://blog.inlart.com/post/openrgb-asus-x570/
8 * - https://openrgb-wiki.readthedocs.io/en/latest/asus/ASUS-Aura-USB/
9 */
10
11 const AURA_REQUEST_FIRMWARE_VERSION: u8 = 0x82;
12 const AURA_REQUEST_CONFIG_TABLE: u8 = 0xB0;
13
14 const VID: u16 = 0x0B05; // Vendor ID: ASUS.
15
16 const PID_650_E: u16 = 0x19AF; // Product ID: AURA LED Controller.
17 const PID_CROSSHAIR: u16 = 0x18F3; // Product ID: AURA LED Controller.
18
19 pub enum Motherboard {
20 Asus650e,
21 AsusCrosshairVIIIHero,
22 }
23
24 pub struct Device {
25 device: hidapi::HidDevice,
26 motherboard: Motherboard,
27 }
28
29 impl Device {
30 pub fn new(api: &hidapi::HidApi, motherboard: Motherboard) -> Self {
31 let device =
32 Device {
33 device: api
34 .open(
35 VID,
36 match motherboard {
37 Motherboard::Asus650e => PID_650_E,
38 Motherboard::AsusCrosshairVIIIHero => PID_CROSSHAIR,
39 },
40 )
41 .unwrap(),
42 motherboard,
43 };
44
45 device.set_fixed_mode();
46 device
47 }
48
49 pub fn get_firmware_string(&self) -> String {
50 let mut buffer = [0u8; 65];
51 buffer[0] = 0xEC;
52 buffer[1] = AURA_REQUEST_FIRMWARE_VERSION;
53 let n_write = self.device.write(&buffer).unwrap();
54 assert_eq!(n_write, 65);
55
56 buffer.fill(0);
57 let n_read = self.device.read(&mut buffer).unwrap();
58 assert_eq!(n_read, 65);
59 assert_eq!(buffer[0], 0xEC);
60 assert_eq!(buffer[1], 0x02);
61
62 String::from(str::from_utf8(&buffer[2..17]).unwrap())
63 }
64
65 /*
66 Example of configuration table:
67 - Positions 0 and 1 always 1E and 9F.
68 - Value 02 is the number of adressable channels.
69 1E 9F 02 01 00 00
70 78 3C 00 01 00 00
71 78 3C 00 00 00 00
72 00 00 00 00 00 00
73 00 00 00 08 0A 02
74 01 F4 00 00 00 00
75 00 00 00 00 00 00
76 00 00 00 00 00 00
77 00 00 00 00 00 00
78 00 00 00 00 00 00
79 */
80 pub fn get_configuration_table(&self) -> [u8; 60] {
81 let mut buffer = [0u8; 65];
82 buffer[0] = 0xEC;
83 buffer[1] = AURA_REQUEST_CONFIG_TABLE;
84 let n_write = self.device.write(&buffer).unwrap();
85 assert_eq!(n_write, 65);
86
87 buffer.fill(0);
88 let n_read = self.device.read(&mut buffer).unwrap();
89 assert_eq!(n_read, 65);
90 assert_eq!(buffer[0], 0xEC);
91 assert_eq!(buffer[1], 0x30);
92
93 buffer[4..64]
94 .try_into()
95 .expect("slice with incorrect length")
96 }
97
98 fn set_fixed_mode(&self) {
99 let mut buffer = [0u8; 65];
100 buffer[0] = 0xEC;
101 buffer[1] = 0x35; // Control mode.
102 buffer[4] = 0x00; // Shutdown effect.
103 buffer[5] = 0x01; // Mode id: static.
104
105 for channel_effect_id in 0..2 {
106 buffer[2] = channel_effect_id; // Channel effect id: Fixed.
107 let n_write = self.device.write(&buffer).unwrap();
108 assert_eq!(n_write, 65);
109 }
110 }
111
112 pub fn set_color(&self, color: &RGB) {
113 let mut buffer = [0u8; 65];
114 buffer[0] = 0xEC;
115 buffer[1] = 0x36;
116
117 let start_led = 0u32;
118 let nb_of_leds = 16u32;
119 let mask = ((1u32 << nb_of_leds) - 1u32) << start_led;
120
121 buffer[2] = (mask >> 8) as u8; // 16 bits LED mask: first part.
122 buffer[3] = (mask & 0xFF) as u8; // 16 bits LED mask: second part.
123
124 for n in start_led as usize..(start_led + nb_of_leds) as usize {
125 buffer[5 + 3 * n] = color.red;
126 buffer[5 + 3 * n + 1] = color.green;
127 buffer[5 + 3 * n + 2] = color.blue;
128 }
129
130 let n_write = self.device.write(&buffer).unwrap();
131 assert_eq!(n_write, 65);
132 }
133
134 pub fn save_current_color(&self) {
135 let mut buffer = [0u8; 65];
136 buffer[0] = 0xEC;
137 buffer[1] = 0x3F;
138 buffer[2] = 0x55;
139
140 let n_write = self.device.write(&buffer).unwrap();
141 assert_eq!(n_write, 65);
142 }
143 }