1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
// Copyright lowRISC contributors (OpenTitan project).
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0

use anyhow::Result;
use serde::{Deserialize, Serialize};
use std::rc::Rc;
use std::time::Duration;
use thiserror::Error;

use super::nonblocking_help::{NoNonblockingHelp, NonblockingHelp};
use crate::impl_serializable_error;

/// Errors related to the console interface.
#[derive(Error, Debug, Serialize, Deserialize)]
pub enum ConsoleError {
    #[error("Unsupported: {0}")]
    UnsupportedError(String),
    #[error("{0}")]
    GenericError(String),
}
impl_serializable_error!(ConsoleError);

pub trait ConsoleDevice {
    /// Reads data from the UART to print to the console (used when this UART is the console device).
    fn console_read(&self, _buf: &mut [u8], _timeout: Duration) -> Result<usize> {
        Err(ConsoleError::UnsupportedError("console_read() not implemented.".into()).into())
    }

    /// Writes console input data to the UART (used when this UART is the console device).
    fn console_write(&self, _buf: &[u8]) -> Result<()> {
        Err(ConsoleError::UnsupportedError("console_write() not implemented.".into()).into())
    }

    fn set_break(&self, _enable: bool) -> Result<()> {
        Err(ConsoleError::GenericError("break unsupported".into()).into())
    }

    /// Query if nonblocking mio mode is supported.
    fn supports_nonblocking_read(&self) -> Result<bool> {
        Ok(false)
    }

    /// Switch this `Uart` instance into nonblocking mio mode.  Going
    /// forward, `read()` should only be called after `mio::poll()` has
    /// indicated that the given `Token` is ready.
    fn register_nonblocking_read(
        &self,
        _registry: &mio::Registry,
        _token: mio::Token,
    ) -> Result<()> {
        unimplemented!();
    }

    /// Get the same single `NonblockingHelp` object as from top level
    /// `Transport.nonblocking_help()`.
    fn nonblocking_help(&self) -> Result<Rc<dyn NonblockingHelp>> {
        Ok(Rc::new(NoNonblockingHelp))
    }
}