opentitanlib/transport/
mod.rs1use anyhow::Result;
6use bitflags::bitflags;
7use serde::{Deserialize, Serialize};
8use std::any::Any;
9use std::collections::HashMap;
10use std::path::PathBuf;
11use std::rc::Rc;
12
13use crate::bootstrap::BootstrapOptions;
14use crate::io::emu::Emulator;
15use crate::io::gpio::{GpioBitbanging, GpioMonitoring, GpioPin};
16use crate::io::i2c::Bus;
17use crate::io::jtag::{JtagChain, JtagParams};
18use crate::io::spi::Target;
19use crate::io::uart::Uart;
20
21pub mod common;
22pub mod ioexpander;
23
24mod errors;
26pub use errors::{TransportError, TransportInterfaceType};
27
28bitflags! {
29    #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
31    #[serde(transparent)]
32    pub struct Capability: u32 {
33        const NONE = 0x00;
34        const UART = 0x01 << 0;
35        const SPI = 0x01 << 1;
36        const GPIO = 0x01 << 2;
37        const I2C = 0x01 << 3;
38        const PROXY = 0x01 << 4;
39        const EMULATOR = 0x01 << 5;
40        const GPIO_MONITORING = 0x01 << 6; const JTAG = 0x01 << 7;
42        const UART_NONBLOCKING = 0x01 << 8;
43        const SPI_DUAL = 0x01 << 9;
44        const SPI_QUAD = 0x01 << 10;
45        const GPIO_BITBANGING = 0x01 << 11;
46    }
47}
48
49#[derive(Serialize, Deserialize)]
51pub struct Capabilities {
52    capabilities: Capability,
53}
54
55impl Capabilities {
56    pub fn new(cap: Capability) -> Self {
59        Self { capabilities: cap }
60    }
61
62    pub fn add(&self, extra: Capability) -> Self {
63        Self {
64            capabilities: self.capabilities | extra,
65        }
66    }
67
68    pub fn request(&self, needed: Capability) -> NeededCapabilities {
70        NeededCapabilities {
71            capabilities: self.capabilities,
72            needed,
73        }
74    }
75}
76
77pub struct NeededCapabilities {
79    capabilities: Capability,
80    needed: Capability,
81}
82
83impl NeededCapabilities {
84    pub fn ok(&self) -> Result<()> {
86        if self.capabilities & self.needed != self.needed {
87            Err(TransportError::MissingCapabilities(self.needed, self.capabilities).into())
88        } else {
89            Ok(())
90        }
91    }
92}
93
94pub trait Transport {
97    fn capabilities(&self) -> Result<Capabilities>;
100
101    fn apply_default_configuration(&self) -> Result<()> {
104        Ok(())
105    }
106
107    fn jtag(&self, _opts: &JtagParams) -> Result<Box<dyn JtagChain + '_>> {
109        Err(TransportError::InvalidInterface(TransportInterfaceType::Jtag).into())
110    }
111    fn spi(&self, _instance: &str) -> Result<Rc<dyn Target>> {
113        Err(TransportError::InvalidInterface(TransportInterfaceType::Spi).into())
114    }
115    fn i2c(&self, _instance: &str) -> Result<Rc<dyn Bus>> {
117        Err(TransportError::InvalidInterface(TransportInterfaceType::I2c).into())
118    }
119    fn uart(&self, _instance: &str) -> Result<Rc<dyn Uart>> {
121        Err(TransportError::InvalidInterface(TransportInterfaceType::Uart).into())
122    }
123    fn gpio_pin(&self, _instance: &str) -> Result<Rc<dyn GpioPin>> {
125        Err(TransportError::InvalidInterface(TransportInterfaceType::Gpio).into())
126    }
127    fn gpio_monitoring(&self) -> Result<Rc<dyn GpioMonitoring>> {
129        Err(TransportError::InvalidInterface(TransportInterfaceType::GpioMonitoring).into())
130    }
131    fn gpio_bitbanging(&self) -> Result<Rc<dyn GpioBitbanging>> {
134        Err(TransportError::InvalidInterface(TransportInterfaceType::GpioBitbanging).into())
135    }
136    fn emulator(&self) -> Result<Rc<dyn Emulator>> {
138        Err(TransportError::InvalidInterface(TransportInterfaceType::Emulator).into())
139    }
140
141    fn proxy_ops(&self) -> Result<Rc<dyn ProxyOps>> {
143        Err(TransportError::InvalidInterface(TransportInterfaceType::ProxyOps).into())
144    }
145
146    fn dispatch(&self, _action: &dyn Any) -> Result<Option<Box<dyn erased_serde::Serialize>>> {
148        Err(TransportError::UnsupportedOperation.into())
149    }
150
151    fn maintain_connection(&self) -> Result<Rc<dyn MaintainConnection>> {
155        Ok(Rc::new(()))
157    }
158}
159
160pub trait MaintainConnection {}
164
165impl MaintainConnection for () {}
168
169pub trait ProxyOps {
171    fn provides_map(&self) -> Result<HashMap<String, String>>;
176
177    fn bootstrap(&self, options: &BootstrapOptions, payload: &[u8]) -> Result<()>;
178    fn apply_pin_strapping(&self, strapping_name: &str) -> Result<()>;
179    fn remove_pin_strapping(&self, strapping_name: &str) -> Result<()>;
180
181    fn apply_default_configuration_with_strap(&self, strapping_name: &str) -> Result<()>;
183}
184
185pub struct Bootstrap {
191    pub image_path: PathBuf,
192}
193
194pub struct SetJtagPins {
196    pub tclk: Option<Rc<dyn GpioPin>>,
197    pub tms: Option<Rc<dyn GpioPin>>,
198    pub tdi: Option<Rc<dyn GpioPin>>,
199    pub tdo: Option<Rc<dyn GpioPin>>,
200    pub trst: Option<Rc<dyn GpioPin>>,
201}
202
203pub trait ProgressIndicator {
204    fn new_stage(&self, name: &str, total: usize);
207    fn progress(&self, absolute: usize);
210}
211
212pub struct UpdateFirmware<'a> {
214    pub firmware: Option<Vec<u8>>,
218    pub progress: Box<dyn ProgressIndicator + 'a>,
220    pub force: bool,
223}
224
225pub struct EmptyTransport;
227
228impl Transport for EmptyTransport {
229    fn capabilities(&self) -> Result<Capabilities> {
230        Ok(Capabilities::new(Capability::NONE))
231    }
232}
233
234#[cfg(test)]
235pub mod tests {
236    use super::*;
237
238    #[test]
239    fn test_capabilities_met() -> anyhow::Result<()> {
240        let cap = Capabilities::new(Capability::UART | Capability::SPI);
241        assert!(cap.request(Capability::UART).ok().is_ok());
242        Ok(())
243    }
244
245    #[test]
246    fn test_capabilities_not_met() -> anyhow::Result<()> {
247        let cap = Capabilities::new(Capability::UART | Capability::SPI);
248        assert!(cap.request(Capability::GPIO).ok().is_err());
249        Ok(())
250    }
251}