blob: 66a7233084af4fcc69cc6d4cc04d70a7aa10144f [file] [log] [blame]
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
use anyhow::Result;
use std::cell::RefCell;
use std::time::Duration;
use std::io::Read;
use std::io::Write;
use std::path::Path;
use crate::io::uart::Uart;
use crate::transport::hyperdebug::Error;
use crate::transport::hyperdebug::Hyperdebug;
pub struct HyperdebugUart {
port: RefCell<Box<dyn serialport::SerialPort>>,
}
impl HyperdebugUart {
pub fn open(_hyperdebug: &Hyperdebug, tty: &Path) -> Result<Self> {
let port =
serialport::new(tty.to_str().ok_or(Error::UnicodePathError)?,
115_200)
.timeout(Duration::from_millis(100))
.open().expect("Failed to open port");
Ok(HyperdebugUart {
port: RefCell::new(port),
})
}
// Not really forever, but close enough. I'd rather use Duration::MAX, but
// it seems that the serialport library can compute an invalid `timeval` struct
// to pass to `poll`, which then leads to an `Invalid argument` error when
// trying to `read` or `write` without a timeout. One hundred years should be
// longer than any invocation of this program.
const FOREVER: Duration = Duration::from_secs(100 * 365 * 86400);
}
impl Uart for HyperdebugUart {
fn read(&self, buf: &mut [u8]) -> Result<usize> {
self.port.borrow_mut().set_timeout(Self::FOREVER)?;
Ok(self.port.borrow_mut().read(buf)?)
}
fn write(&self, buf: &[u8]) -> Result<usize> {
Ok(self.port.borrow_mut().write(buf)?)
}
fn get_baudrate(&self) -> u32 {
match self.port.borrow().baud_rate() {
Ok(baud_rate) => baud_rate,
_ => panic!("SerialPort::baud_rate() returned Err")
}
}
fn set_baudrate(&self, baudrate: u32) -> Result<()> {
Ok(self.port.borrow_mut().set_baud_rate(baudrate)?)
}
fn read_timeout(&self, buf: &mut [u8], timeout: Duration) -> Result<usize> {
self.port.borrow_mut().set_timeout(timeout)?;
Ok(self.port.borrow_mut().read(buf)?)
}
}