1pub mod handler;
2pub mod key;
3pub mod key_led;
4
5use chrono::{DateTime, Utc};
6use hidapi::{HidDevice, HidError};
7use std::{io::Read, thread, time::Duration};
8use strum::IntoEnumIterator;
9
10use handler::{
11 ConnectedHandler, DisconnectedHandler, JogHandler, KeyDownHandler, KeyHandler, KeyUpHandler,
12 KeysHandler, UnknownHandler,
13};
14use key::Key;
15use key_led::KeyLed;
16
17pub struct SpeedEditor {
18 pub device: Option<HidDevice>,
19 pub last_authenticated_at: Option<DateTime<Utc>>,
20 pub current_keys: Vec<Key>,
21 pub current_key_leds: Vec<KeyLed>,
22 pub connected_handler: ConnectedHandler,
23 pub disconnected_handler: DisconnectedHandler,
24 pub keys_handler: KeysHandler,
25 pub key_handler: KeyHandler,
26 pub key_down_handler: KeyDownHandler,
27 pub key_up_handler: KeyUpHandler,
28 pub jog_handler: JogHandler,
29 pub unknown_handler: UnknownHandler,
30}
31
32pub type SpeedEditorResult = Result<(), SpeedEditorError>;
33
34#[derive(Debug)]
35pub enum SpeedEditorError {
36 HidApiError(hidapi::HidError),
37 StdIoError(std::io::Error),
38 AuthGetKbdChallengeError,
39 AuthGetKbdResponseError,
40 AuthGetKbdStatusError,
41 CallbackExecutionError,
42}
43
44impl From<hidapi::HidError> for SpeedEditorError {
45 fn from(e: HidError) -> Self {
46 SpeedEditorError::HidApiError(e)
47 }
48}
49
50impl From<std::io::Error> for SpeedEditorError {
51 fn from(e: std::io::Error) -> Self {
52 SpeedEditorError::StdIoError(e)
53 }
54}
55
56impl SpeedEditor {
57 const VID: u16 = 7899;
58 const PID: u16 = 55822;
59 const READ_TIMEOUT: i32 = 1000;
60 const RECONNECT_INTERVAL: u64 = 100;
61 const AUTH_INTERVAL: i64 = 30000;
62
63 const AUTH_EVEN_TBL: [u64; 8] = [
64 4242707987619187656,
65 3069963097229903046,
66 2352841328256802570,
67 12646368222702737177,
68 17018789593460232529,
69 12706253227766860309,
70 11978781369061872007,
71 8438608961089703390,
72 ];
73
74 const AUTH_ODD_TBL: [u64; 8] = [
75 4477338132788707294,
76 2622620659002747676,
77 11637077509869926595,
78 7923852755392722584,
79 8224257920127642516,
80 4049197610885016386,
81 18266591397768539273,
82 7035737829027231430,
83 ];
84
85 const MASK: u64 = 12077075256910773232;
86
87 fn rol8(&self, v: u64) -> u64 {
88 ((v << 56) | (v >> 8)) & 18446744073709551615
89 }
90
91 fn rol8n(&self, mut v: u64, n: u64) -> u64 {
92 for _ in 0..n {
93 v = self.rol8(v);
94 }
95 v
96 }
97
98 fn auth(&mut self) -> SpeedEditorResult {
105 let mut buf = [0; 8];
106 let mut bytes = vec![0; 10];
107
108 if let Some(device) = &self.device {
109 device.send_feature_report(&[0x6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0])?;
110 bytes[0] = 0x6;
111
112 let _ = device.get_feature_report(&mut bytes)?;
113 if bytes[0] != 0x6 || bytes[1] != 0x0 {
114 return Err(SpeedEditorError::AuthGetKbdChallengeError);
115 }
116
117 (&bytes[2..]).read_exact(&mut buf).unwrap();
118 let challenge = u64::from_le_bytes(buf);
119
120 device.send_feature_report(&[0x6, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0])?;
121 let _ = device.get_feature_report(&mut bytes)?;
122 if bytes[0] != 0x6 || bytes[1] != 0x2 {
123 return Err(SpeedEditorError::AuthGetKbdResponseError);
124 }
125
126 let n = challenge & 7;
127 let mut v = self.rol8n(challenge, n);
128 let k: u64;
129 if (v & 1) == ((120 >> n) & 1) {
130 k = Self::AUTH_EVEN_TBL[n as usize];
131 } else {
132 v = v ^ self.rol8(v);
133 k = Self::AUTH_ODD_TBL[n as usize];
134 }
135
136 let response = v ^ (self.rol8(v) & Self::MASK) ^ k;
137 buf = response.to_le_bytes();
138
139 bytes[1] = 0x3;
140 for i in 0..8 {
141 bytes[i + 2] = buf[i];
142 }
143
144 device.send_feature_report(bytes.as_slice())?;
145
146 let _ = device.get_feature_report(&mut bytes)?;
147 if bytes[0] != 0x6 || bytes[1] != 0x4 {
148 return Err(SpeedEditorError::AuthGetKbdStatusError);
149 }
150
151 self.last_authenticated_at = Some(Utc::now());
152 }
153
154 Ok(())
155 }
156
157 fn is_expired(&self) -> bool {
158 if let Some(at) = self.last_authenticated_at {
159 let elapsed_time = Utc::now() - at;
160 elapsed_time.num_milliseconds() >= Self::AUTH_INTERVAL
161 } else {
162 true
163 }
164 }
165
166 pub fn run(&mut self) -> SpeedEditorResult {
167 loop {
168 if self.device.is_none() {
169 self.connect()?;
170 continue;
171 }
172
173 if self.is_expired() {
174 self.auth()?;
175 continue;
176 }
177
178 if let Some(device) = &self.device {
179 let mut buf = [0; 64];
180 match device.read_timeout(&mut buf, Self::READ_TIMEOUT) {
181 Ok(len) => {
182 if len > 0 {
183 self.process_events(&buf[..len])?;
184 }
185 }
186 Err(_) => self.disconnect()?,
187 }
188 }
189 }
190 }
191
192 fn process_events(&mut self, buf: &[u8]) -> SpeedEditorResult {
193 match buf[0] {
194 3 => self.jog_event(buf[1], &buf[2..])?,
195 4 => self.key_event(&buf[1..])?,
196 _ => self.unknown_event(buf)?,
197 }
198
199 Ok(())
200 }
201
202 fn jog_event(&mut self, mode: u8, buf: &[u8]) -> SpeedEditorResult {
203 let mut data = [0; 4];
204 (&buf[..]).read_exact(&mut data)?;
205 let value = i32::from_le_bytes(data) / 360;
206 self.jog_handler.call(mode, value)?;
207 Ok(())
208 }
209
210 fn key_event(&mut self, buf: &[u8]) -> SpeedEditorResult {
211 let current_keys: Vec<Key> = buf
212 .iter()
213 .enumerate()
214 .filter(|&(i, _)| i % 2 == 0)
215 .filter(|&(_, &v)| v > 0)
216 .map(|(_, &v)| Key::try_from(v).unwrap())
217 .collect();
218
219 if current_keys == self.current_keys {
221 return Ok(());
222 }
223
224 let down_keys: Vec<Key> = current_keys
225 .iter()
226 .map(|&v| {
227 if self.current_keys.iter().find(|&k| *k == v) == None {
228 v
229 } else {
230 Key::None
231 }
232 })
233 .filter(|&v| v > Key::None)
234 .collect();
235
236 let up_keys: Vec<Key> = self
237 .current_keys
238 .iter()
239 .map(|&v| {
240 if current_keys.iter().find(|&k| *k == v) == None {
241 v
242 } else {
243 Key::None
244 }
245 })
246 .filter(|&v| v > Key::None)
247 .collect();
248
249 self.current_keys = current_keys.to_owned();
250
251 for k in down_keys {
252 self.key_handler.call(k, true)?;
253 self.key_down_handler.call(k)?;
254 }
255
256 for k in up_keys {
257 self.key_handler.call(k, false)?;
258 self.key_up_handler.call(k)?;
259 }
260
261 self.keys_handler.call(&self.current_keys)?;
262
263 Ok(())
264 }
265
266 fn unknown_event(&mut self, buf: &[u8]) -> SpeedEditorResult {
267 self.unknown_handler.call(buf)
268 }
269
270 fn disconnect(&mut self) -> SpeedEditorResult {
271 self.device = None;
272 self.last_authenticated_at = None;
273 self.disconnected_handler.call()
274 }
275
276 fn connect(&mut self) -> SpeedEditorResult {
278 let api = hidapi::HidApi::new()?;
279
280 self.device = match api.open(SpeedEditor::VID, SpeedEditor::PID) {
281 Ok(device) => {
282 self.connected_handler.call()?;
283 Some(device)
284 }
285 Err(_) => {
286 thread::sleep(Duration::from_millis(Self::RECONNECT_INTERVAL));
287 None
288 }
289 };
290
291 Ok(())
292 }
293
294 fn add_key_led(&mut self, led: KeyLed) {
295 self.current_key_leds.push(led);
296 }
297
298 fn remove_key_led(&mut self, led: KeyLed) {
299 self.current_key_leds = self
300 .current_key_leds
301 .iter()
302 .filter(|&i| *i != led)
303 .map(|i| *i)
304 .collect::<Vec<KeyLed>>();
305 }
306
307 pub fn set_all_key_leds(&mut self, on: bool) -> SpeedEditorResult {
308 for led in KeyLed::iter() {
309 if on {
310 self.add_key_led(led);
311 } else {
312 self.remove_key_led(led);
313 }
314 }
315
316 self.light_key_leds()
317 }
318
319 pub fn set_key_led(&mut self, led: KeyLed, on: bool) -> SpeedEditorResult {
320 if on {
321 self.add_key_led(led);
322 } else {
323 self.remove_key_led(led);
324 }
325
326 self.light_key_leds()
327 }
328
329 pub fn set_leds(&mut self, leds: Vec<KeyLed>, on: bool) -> SpeedEditorResult {
330 for led in leds {
331 if on {
332 self.add_key_led(led);
333 } else {
334 self.remove_key_led(led);
335 }
336 }
337
338 self.light_key_leds()
339 }
340
341 fn light_key_leds(&mut self) -> SpeedEditorResult {
342 if let Some(device) = &self.device {
343 let mut leds: i32 = 0;
344 for i in self.current_key_leds.iter() {
345 leds |= 1 << *i as i32;
346 }
347
348 let buf = leds.to_le_bytes();
349 let mut data = [0x2, 0x0, 0x0, 0x0, 0x0, 0x0];
350 data[0] = 0x2;
351 for i in 0..4 {
352 data[i + 1] = buf[i];
353 }
354
355 device.write(data.as_slice())?;
356 }
357 Ok(())
358 }
359
360 pub fn on_connected<F>(&mut self, callback: F)
361 where
362 F: FnMut() -> SpeedEditorResult + Sync + Send + 'static,
363 {
364 self.connected_handler.callbacks.push(Box::new(callback));
365 }
366
367 pub fn on_disconnected<F>(&mut self, callback: F)
368 where
369 F: FnMut() -> SpeedEditorResult + Sync + Send + 'static,
370 {
371 self.disconnected_handler.callbacks.push(Box::new(callback));
372 }
373
374 pub fn on_keys<F>(&mut self, callback: F)
375 where
376 F: FnMut(Vec<Key>) -> SpeedEditorResult + Send + Sync + 'static,
377 {
378 self.keys_handler.callbacks.push(Box::new(callback));
379 }
380
381 pub fn on_key<F>(&mut self, callback: F)
382 where
383 F: FnMut(Key, bool) -> SpeedEditorResult + Sync + Send + 'static,
384 {
385 self.key_handler.callbacks.push(Box::new(callback));
386 }
387
388 pub fn on_key_down<F>(&mut self, callback: F)
389 where
390 F: FnMut(Key) -> SpeedEditorResult + Sync + Send + 'static,
391 {
392 self.key_down_handler.callbacks.push(Box::new(callback));
393 }
394
395 pub fn on_key_up<F>(&mut self, callback: F)
396 where
397 F: FnMut(Key) -> SpeedEditorResult + Sync + Send + 'static,
398 {
399 self.key_up_handler.callbacks.push(Box::new(callback));
400 }
401
402 pub fn on_jog<F>(&mut self, callback: F)
403 where
404 F: FnMut(u8, i32) -> SpeedEditorResult + Sync + Send + 'static,
405 {
406 self.jog_handler.callbacks.push(Box::new(callback));
407 }
408
409 pub fn on_unknown<F>(&mut self, callback: F)
410 where
411 F: FnMut(&[u8]) -> SpeedEditorResult + Sync + Send + 'static,
412 {
413 self.unknown_handler.callbacks.push(Box::new(callback));
414 }
415}
416
417#[cfg(test)]
418mod tests {
419 #[test]
420 fn it_works() {
421 let result = 2 + 2;
422 assert_eq!(result, 4);
423 }
424}