85 lines
2.3 KiB
Rust
85 lines
2.3 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));
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
Ok(())
|
||
|
}
|
||
|
|
||
|
fn get_prop(
|
||
|
port: &mut Box<dyn serialport::SerialPort>,
|
||
|
prop: &[u8],
|
||
|
) -> Result<Vec<u8>, Box<dyn std::error::Error>> {
|
||
|
port.write_all(prop)?;
|
||
|
port.flush()?;
|
||
|
|
||
|
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 {}
|