74face19860f660f27a97bf741a072b36353d1a6
[temp2RGB.git] / src / AsusAuraUSB.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 Device {
32 device: api
33 .open(
34 VID,
35 match motherboard {
36 Motherboard::Asus650e => PID_650_E,
37 Motherboard::AsusCrosshairVIIIHero => PID_CROSSHAIR,
38 },
39 )
40 .unwrap(),
41 motherboard,
42 }
43 }
44
45 pub fn get_firmware_string(&self) -> String {
46 let mut buffer = [0u8; 65];
47 buffer[0] = 0xEC;
48 buffer[1] = AURA_REQUEST_FIRMWARE_VERSION;
49 let n_write = self.device.write(&buffer).unwrap();
50 assert_eq!(n_write, 65);
51
52 buffer.fill(0);
53 let n_read = self.device.read(&mut buffer).unwrap();
54 assert_eq!(n_read, 65);
55 assert_eq!(buffer[0], 0xEC);
56 assert_eq!(buffer[1], 0x02);
57
58 String::from(str::from_utf8(&buffer[2..17]).unwrap())
59 }
60
61 /*
62 Example of configuration table:
63 - Positions 0 and 1 always 1E and 9F.
64 - Value 02 is the number of adressable channels.
65 1E 9F 02 01 00 00
66 78 3C 00 01 00 00
67 78 3C 00 00 00 00
68 00 00 00 00 00 00
69 00 00 00 08 0A 02
70 01 F4 00 00 00 00
71 00 00 00 00 00 00
72 00 00 00 00 00 00
73 00 00 00 00 00 00
74 00 00 00 00 00 00
75 */
76 pub fn get_configuration_table(&self) -> [u8; 60] {
77 let mut buffer = [0u8; 65];
78 buffer[0] = 0xEC;
79 buffer[1] = AURA_REQUEST_CONFIG_TABLE;
80 let n_write = self.device.write(&buffer).unwrap();
81 assert_eq!(n_write, 65);
82
83 buffer.fill(0);
84 let n_read = self.device.read(&mut buffer).unwrap();
85 assert_eq!(n_read, 65);
86 assert_eq!(buffer[0], 0xEC);
87 assert_eq!(buffer[1], 0x30);
88
89 buffer[4..64]
90 .try_into()
91 .expect("slice with incorrect length")
92 }
93
94 pub fn set_fixed_mode(&self) {
95 let mut buffer = [0u8; 65];
96 buffer[0] = 0xEC;
97 buffer[1] = 0x35; // Control mode.
98 buffer[4] = 0x00; // Shutdown effect.
99 buffer[5] = 0x01; // Mode id: static.
100
101 for channel_effect_id in 0..2 {
102 buffer[2] = channel_effect_id; // Channel effect id: Fixed.
103 let n_write = self.device.write(&buffer).unwrap();
104 assert_eq!(n_write, 65);
105 }
106 }
107
108 pub fn set_color(&self, color: &RGB) {
109 let mut buffer = [0u8; 65];
110 buffer[0] = 0xEC;
111 buffer[1] = 0x36;
112
113 let start_led = 0u32;
114 let nb_of_leds = 16u32;
115 let mask = ((1u32 << nb_of_leds) - 1u32) << start_led;
116
117 buffer[2] = (mask >> 8) as u8; // 16 bits LED mask: first part.
118 buffer[3] = (mask & 0xFF) as u8; // 16 bits LED mask: second part.
119
120 for n in start_led as usize..(start_led + nb_of_leds) as usize {
121 buffer[5 + 3 * n] = color.red;
122 buffer[5 + 3 * n + 1] = color.green;
123 buffer[5 + 3 * n + 2] = color.blue;
124 }
125
126 let n_write = self.device.write(&buffer).unwrap();
127 assert_eq!(n_write, 65);
128 }
129
130 pub fn save_current_color(&self) {
131 let mut buffer = [0u8; 65];
132 buffer[0] = 0xEC;
133 buffer[1] = 0x3F;
134 buffer[2] = 0x55;
135
136 let n_write = self.device.write(&buffer).unwrap();
137 assert_eq!(n_write, 65);
138 }
139 }