fn main() -> Result<(), Box> { 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, prop: &[u8], ) -> Result, Box> { 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> { 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 {}