80 lines
2 KiB
Rust
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
|
|
}
|
|
}
|