blob: 1ca5e1df5de5d454ac39f155877f7e659afcf388 [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::{anyhow, Result};
use bitflags::bitflags;
use crate::io::gpio::Gpio;
use crate::io::spi::Target;
use crate::io::uart::Uart;
bitflags! {
/// A bitmap of capabilities which may be provided by a transport.
pub struct Capability: u32 {
const NONE = 0x00000000;
const UART = 0x00000001;
const SPI = 0x00000002;
const GPIO = 0x00000004;
}
}
/// A struct which can check that needed capability requirements are met.
pub struct Capabilities {
capabilities: Capability,
needed: Capability,
}
impl Capabilities {
/// Create a new Capabilities object representing a provider of
/// capabilities specified by `cap`.
pub fn new(cap: Capability) -> Self {
Self {
capabilities: cap,
needed: Capability::NONE,
}
}
/// Request the capabilities specified by `cap`.
pub fn request(&mut self, cap: Capability) -> &mut Self {
self.needed |= cap;
self
}
/// Checks that the requested capabilities are provided.
pub fn ok(&self) -> Result<()> {
if self.capabilities & self.needed != self.needed {
Err(anyhow!(
"Requested capabilities {:?}, but capabilities {:?} are supplied",
self.needed,
self.capabilities
))
} else {
Ok(())
}
}
}
/// A transport object is a factory for the low-level interfaces provided
/// by a given communications backend.
pub trait Transport {
/// Returns a `Capabilities` object to check the capabilities of this
/// transport object.
fn capabilities(&self) -> Capabilities;
/// Returns a SPI [`Target`] implementation.
fn spi(&self) -> Result<Box<dyn Target>> {
unimplemented!();
}
/// Returns a [`Uart`] implementation.
fn uart(&self) -> Result<Box<dyn Uart>> {
unimplemented!();
}
/// Returns a [`Gpio`] implementation.
fn gpio(&self) -> Result<Box<dyn Gpio>> {
unimplemented!();
}
}
/// An `EmptyTransport` provides no communications backend.
pub struct EmptyTransport;
impl Transport for EmptyTransport {
fn capabilities(&self) -> Capabilities {
Capabilities::new(Capability::NONE)
}
}
#[cfg(test)]
pub mod tests {
use super::*;
#[test]
fn test_capabilities_met() -> Result<()> {
let mut cap = Capabilities::new(Capability::UART | Capability::SPI);
assert!(cap.request(Capability::UART).ok().is_ok());
Ok(())
}
#[test]
fn test_capabilities_not_met() -> Result<()> {
let mut cap = Capabilities::new(Capability::UART | Capability::SPI);
assert!(cap.request(Capability::GPIO).ok().is_err());
Ok(())
}
}