etp 0.0.1-alpha

Embedded Tester Library (ETP). Control embedded devices from host!
Documentation
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;

/// Serial port transport layer
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();

        // Block and keep reading until we have the expected number of bytes
        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)
                // Timeout error is fine, just continue
                .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)
    }
}