use std::io::{Read, Write};
use crate::{
constants::{self, MAX_RESPONSE_SIZE},
error::{EtpError, EtpResult},
};
use super::common::TransportLayer;
pub type UartDevice = String;
pub type UartBaudRate = u32;
pub struct SerialPortTransport {
pub serial_port: Box<dyn serialport::SerialPort>,
}
impl SerialPortTransport {
pub fn new(port: UartDevice, baud: UartBaudRate) -> EtpResult<SerialPortTransport> {
let serial_port = serialport::new(port.clone(), baud)
.timeout(std::time::Duration::from_millis(
constants::SERIAL_PORT_TIMEOUT_MS,
))
.open()
.map_err(|e| EtpError::SerialPort(format!("{:?}", e)))?;
Ok(SerialPortTransport { serial_port })
}
}
impl TransportLayer for SerialPortTransport {
fn send(&mut self, command: Vec<u8>) -> EtpResult<()> {
self.serial_port
.write_all(&command)
.map_err(|e| EtpError::SerialPort(format!("{:?}", e)))?;
Ok(())
}
fn receive(&mut self, expected_bytes: usize) -> EtpResult<Vec<u8>> {
let mut buffer: Vec<u8> = Vec::new();
while buffer.len() < expected_bytes as usize {
let mut temp_buffer = vec![0; MAX_RESPONSE_SIZE];
let bytes_read = self
.serial_port
.read(&mut temp_buffer)
.or_else(|e| {
if e.kind() == std::io::ErrorKind::TimedOut {
Ok(0)
} else {
Err(e)
}
})
.map_err(|e| EtpError::SerialPort(format!("{:?}", e)))?;
if bytes_read == 0 {
break;
}
buffer.extend_from_slice(&temp_buffer[..bytes_read]);
}
Ok(buffer)
}
}