Replace some unwrap by Result
[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) -> anyhow::Result<Self> {
31 let device = Device {
32 device: api.open(
33 VID,
34 match motherboard {
35 Motherboard::Asus650e => PID_650_E,
36 Motherboard::AsusCrosshairVIIIHero => PID_CROSSHAIR,
37 },
38 )?,
39 motherboard,
40 };
41
42 device.set_fixed_mode()?;
43 Ok(device)
44 }
45
46 pub fn get_firmware_string(&self) -> anyhow::Result<String> {
47 let mut buffer = [0u8; 65];
48 buffer[0] = 0xEC;
49 buffer[1] = AURA_REQUEST_FIRMWARE_VERSION;
50 let n_write = self.device.write(&buffer)?;
51 assert_eq!(n_write, 65);
52
53 buffer.fill(0);
54 let n_read = self.device.read(&mut buffer)?;
55 assert_eq!(n_read, 65);
56 assert_eq!(buffer[0], 0xEC);
57 assert_eq!(buffer[1], 0x02);
58
59 Ok(String::from(str::from_utf8(&buffer[2..17])?))
60 }
61
62 /*
63 Example of configuration table:
64 - Positions 0 and 1 always 1E and 9F.
65 - Value 02 is the number of adressable channels.
66 1E 9F 02 01 00 00
67 78 3C 00 01 00 00
68 78 3C 00 00 00 00
69 00 00 00 00 00 00
70 00 00 00 08 0A 02
71 01 F4 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 00 00 00 00 00 00
76 */
77 pub fn get_configuration_table(&self) -> anyhow::Result<[u8; 60]> {
78 let mut buffer = [0u8; 65];
79 buffer[0] = 0xEC;
80 buffer[1] = AURA_REQUEST_CONFIG_TABLE;
81 let n_write = self.device.write(&buffer)?;
82 assert_eq!(n_write, 65);
83
84 buffer.fill(0);
85 let n_read = self.device.read(&mut buffer)?;
86 assert_eq!(n_read, 65);
87 assert_eq!(buffer[0], 0xEC);
88 assert_eq!(buffer[1], 0x30);
89
90 Ok(buffer[4..64].try_into()?)
91 }
92
93 fn set_fixed_mode(&self) -> anyhow::Result<()> {
94 let mut buffer = [0u8; 65];
95 buffer[0] = 0xEC;
96 buffer[1] = 0x35; // Control mode.
97 buffer[4] = 0x00; // Shutdown effect.
98 buffer[5] = 0x01; // Mode id: static.
99
100 for channel_effect_id in 0..2 {
101 buffer[2] = channel_effect_id; // Channel effect id: Fixed.
102 let n_write = self.device.write(&buffer)?;
103 assert_eq!(n_write, 65);
104 }
105 Ok(())
106 }
107
108 pub fn set_color(&self, color: &RGB) -> anyhow::Result<()> {
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)?;
127 assert_eq!(n_write, 65);
128 Ok(())
129 }
130
131 pub fn save_current_color(&self) -> anyhow::Result<()> {
132 let mut buffer = [0u8; 65];
133 buffer[0] = 0xEC;
134 buffer[1] = 0x3F;
135 buffer[2] = 0x55;
136
137 let n_write = self.device.write(&buffer)?;
138 assert_eq!(n_write, 65);
139 Ok(())
140 }
141 }