device-ls/src/main.rs
2021-06-13 17:05:06 -05:00

102 lines
2.7 KiB
Rust

fn main() -> Result<(), Box<dyn std::error::Error>> {
for port in serialport::available_ports()? {
if let Ok(mut port) = perform_handshake(port) {
println!("Handshake success");
if let Ok(ident) = get_prop(&mut port, b"ident") {
println!("ident success: {:?}", ident);
}
if let Ok(name) = get_prop(&mut port, b"name") {
println!("name success: {}", String::from_utf8_lossy(&name));
}
if let Ok(author) = get_prop(&mut port, b"author") {
println!("author success: {}", String::from_utf8_lossy(&author));
}
if let Ok(repo) = get_prop(&mut port, b"repo") {
println!("repo success: {}", String::from_utf8_lossy(&repo));
}
if send_cmd(&mut port, b"reset").is_ok() {
println!("Device reset");
continue;
}
}
}
Ok(())
}
fn send_cmd(
port: &mut Box<dyn serialport::SerialPort>,
cmd: &[u8],
) -> Result<(), Box<dyn std::error::Error>> {
port.write_all(cmd)?;
port.flush()?;
Ok(())
}
fn get_prop(
port: &mut Box<dyn serialport::SerialPort>,
prop: &[u8],
) -> Result<Vec<u8>, Box<dyn std::error::Error>> {
send_cmd(port, prop)?;
let mut len_buf = [0u8; 1];
port.read_exact(&mut len_buf)?;
let input_len = len_buf[0];
println!("LEN: {}", input_len);
let mut input = vec![0u8; input_len as usize];
port.read_exact(&mut input)?;
Ok(input)
}
#[derive(Clone, Copy, Debug)]
struct HandshakeError;
fn perform_handshake(
port: serialport::SerialPortInfo,
) -> Result<Box<dyn serialport::SerialPort>, Box<dyn std::error::Error>> {
use rand::Fill;
use std::io::{Read, Write};
std::fs::metadata(&port.port_name)?;
const INPUT_LEN: usize = 16;
let mut output = [0u8; INPUT_LEN * 2];
let mut input = [0u8; INPUT_LEN];
let mut port = serialport::new(&port.port_name, 9600)
.timeout(std::time::Duration::from_millis(500))
.open()?;
let mut rng = rand::thread_rng();
output.try_fill(&mut rng)?;
port.write_all(&output)?;
port.flush()?;
port.read_exact(&mut input)?;
for (index, byte) in input.iter().enumerate() {
if *byte != (output[index] ^ output[index + INPUT_LEN]) {
return Err(HandshakeError.into());
}
output[index] = *byte;
output[index + INPUT_LEN] = *byte;
}
port.write_all(&output)?;
port.flush()?;
Ok(port)
}
impl std::fmt::Display for HandshakeError {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "HandshakeError")
}
}
impl std::error::Error for HandshakeError {}