trinket-streamdeck/src/handshake.rs

80 lines
2 KiB
Rust

use crate::hal::usb::UsbBus;
use cortex_m::peripheral::SYST;
use usbd_serial::SerialPort;
pub(crate) struct Handshake {
step_1_complete: bool,
step_2_complete: bool,
buffer: [u8; 16],
timestamp: u32,
}
impl Handshake {
pub(crate) const fn new() -> Self {
Handshake {
step_1_complete: false,
step_2_complete: false,
buffer: [0; 16],
timestamp: 0,
}
}
pub(crate) fn is_complete(&self) -> bool {
self.step_1_complete && self.step_2_complete
}
pub(crate) fn perform(
&mut self,
input: &[u8; 32],
serial: &mut SerialPort<UsbBus>,
) -> Option<bool> {
if self.is_complete() {
self.step_1_complete = false;
self.step_2_complete = false;
}
if !self.step_1_complete {
self.timestamp = SYST::get_current();
self.step_1(input, serial)?;
self.step_1_complete = true;
return Some(true);
} else if !self.step_2_complete {
self.step_2_complete = self.step_2(input);
if !self.step_2_complete {
self.step_1_complete = false;
}
return Some(true);
}
if self.step_1_complete
&& !self.step_2_complete
&& self.timestamp > SYST::get_current() + 100
{
self.step_1_complete = false;
}
Some(false)
}
fn step_1(&mut self, input: &[u8; 32], serial: &mut SerialPort<UsbBus>) -> Option<()> {
for ((c1, c2), out) in input[..16].iter().zip(&input[16..]).zip(&mut self.buffer) {
*out = c1 ^ c2;
}
serial.write(&self.buffer).ok()?;
serial.flush().ok()?;
Some(())
}
fn step_2(&self, input: &[u8; 32]) -> bool {
let mut succeeded = true;
for ((c1, c2), c3) in input[..16].iter().zip(&input[16..]).zip(&self.buffer) {
succeeded = succeeded || c1 == c2 && c1 == c3;
}
succeeded
}
}