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;
20use crate::io::usb::UsbContext;
21
22pub mod common;
23pub mod ioexpander;
24
25mod errors;
27pub use errors::{TransportError, TransportInterfaceType};
28
29bitflags! {
30 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
32 #[serde(transparent)]
33 pub struct Capability: u32 {
34 const NONE = 0x00;
35 const UART = 0x01 << 0;
36 const SPI = 0x01 << 1;
37 const GPIO = 0x01 << 2;
38 const I2C = 0x01 << 3;
39 const PROXY = 0x01 << 4;
40 const EMULATOR = 0x01 << 5;
41 const GPIO_MONITORING = 0x01 << 6; const JTAG = 0x01 << 7;
43 const UART_NONBLOCKING = 0x01 << 8;
44 const SPI_DUAL = 0x01 << 9;
45 const SPI_QUAD = 0x01 << 10;
46 const GPIO_BITBANGING = 0x01 << 11;
47 const USB = 0x01 << 12;
48 }
49}
50
51#[derive(Serialize, Deserialize)]
53pub struct Capabilities {
54 capabilities: Capability,
55}
56
57impl Capabilities {
58 pub fn new(cap: Capability) -> Self {
61 Self { capabilities: cap }
62 }
63
64 pub fn add(&self, extra: Capability) -> Self {
65 Self {
66 capabilities: self.capabilities | extra,
67 }
68 }
69
70 pub fn request(&self, needed: Capability) -> NeededCapabilities {
72 NeededCapabilities {
73 capabilities: self.capabilities,
74 needed,
75 }
76 }
77}
78
79pub struct NeededCapabilities {
81 capabilities: Capability,
82 needed: Capability,
83}
84
85impl NeededCapabilities {
86 pub fn ok(&self) -> Result<()> {
88 if self.capabilities & self.needed != self.needed {
89 Err(TransportError::MissingCapabilities(self.needed, self.capabilities).into())
90 } else {
91 Ok(())
92 }
93 }
94}
95
96pub trait Transport {
99 fn capabilities(&self) -> Result<Capabilities>;
102
103 fn apply_default_configuration(&self) -> Result<()> {
106 Ok(())
107 }
108
109 fn jtag(&self, _opts: &JtagParams) -> Result<Box<dyn JtagChain + '_>> {
111 Err(TransportError::InvalidInterface(TransportInterfaceType::Jtag).into())
112 }
113 fn spi(&self, _instance: &str) -> Result<Rc<dyn Target>> {
115 Err(TransportError::InvalidInterface(TransportInterfaceType::Spi).into())
116 }
117 fn i2c(&self, _instance: &str) -> Result<Rc<dyn Bus>> {
119 Err(TransportError::InvalidInterface(TransportInterfaceType::I2c).into())
120 }
121 fn uart(&self, _instance: &str) -> Result<Rc<dyn Uart>> {
123 Err(TransportError::InvalidInterface(TransportInterfaceType::Uart).into())
124 }
125 fn usb(&self) -> Result<Rc<dyn UsbContext>> {
127 Err(TransportError::InvalidInterface(TransportInterfaceType::Usb).into())
128 }
129 fn gpio_pin(&self, _instance: &str) -> Result<Rc<dyn GpioPin>> {
131 Err(TransportError::InvalidInterface(TransportInterfaceType::Gpio).into())
132 }
133 fn gpio_monitoring(&self) -> Result<Rc<dyn GpioMonitoring>> {
135 Err(TransportError::InvalidInterface(TransportInterfaceType::GpioMonitoring).into())
136 }
137 fn gpio_bitbanging(&self) -> Result<Rc<dyn GpioBitbanging>> {
140 Err(TransportError::InvalidInterface(TransportInterfaceType::GpioBitbanging).into())
141 }
142 fn emulator(&self) -> Result<&dyn Emulator> {
144 Err(TransportError::InvalidInterface(TransportInterfaceType::Emulator).into())
145 }
146
147 fn fpga_ops(&self) -> Result<&dyn FpgaOps> {
149 Err(TransportError::InvalidInterface(TransportInterfaceType::FpgaOps).into())
150 }
151
152 fn proxy_ops(&self) -> Result<&dyn ProxyOps> {
154 Err(TransportError::InvalidInterface(TransportInterfaceType::ProxyOps).into())
155 }
156
157 fn dispatch(&self, _action: &dyn Any) -> Result<Option<Box<dyn erased_serde::Serialize>>> {
159 Err(TransportError::UnsupportedOperation.into())
160 }
161
162 fn relinquish_exclusive_access(&self, callback: Box<dyn FnOnce() + '_>) -> Result<()> {
171 callback();
172 Ok(())
173 }
174}
175
176pub trait FpgaOps {
178 fn load_bitstream(&self, bitstream: &[u8], progress: &dyn ProgressIndicator) -> Result<()>;
179
180 fn clear_bitstream(&self) -> Result<()>;
181}
182
183pub trait ProxyOps {
185 fn provides_map(&self) -> Result<HashMap<String, String>>;
190
191 fn bootstrap(&self, options: &BootstrapOptions, payload: &[u8]) -> Result<()>;
192 fn apply_pin_strapping(&self, strapping_name: &str) -> Result<()>;
193 fn remove_pin_strapping(&self, strapping_name: &str) -> Result<()>;
194
195 fn apply_default_configuration_with_strap(&self, strapping_name: &str) -> Result<()>;
197}
198
199pub struct Bootstrap {
205 pub image_path: PathBuf,
206}
207
208pub struct SetJtagPins {
210 pub tclk: Option<Rc<dyn GpioPin>>,
211 pub tms: Option<Rc<dyn GpioPin>>,
212 pub tdi: Option<Rc<dyn GpioPin>>,
213 pub tdo: Option<Rc<dyn GpioPin>>,
214 pub trst: Option<Rc<dyn GpioPin>>,
215}
216
217pub trait ProgressIndicator {
218 fn new_stage(&self, name: &str, total: usize);
221 fn progress(&self, absolute: usize);
224}
225
226pub struct UpdateFirmware<'a> {
228 pub firmware: Option<Vec<u8>>,
232 pub progress: Box<dyn ProgressIndicator + 'a>,
234 pub force: bool,
237}
238
239pub struct EmptyTransport;
241
242impl Transport for EmptyTransport {
243 fn capabilities(&self) -> Result<Capabilities> {
244 Ok(Capabilities::new(Capability::NONE))
245 }
246}
247
248#[cfg(test)]
249pub mod tests {
250 use super::*;
251
252 #[test]
253 fn test_capabilities_met() -> anyhow::Result<()> {
254 let cap = Capabilities::new(Capability::UART | Capability::SPI);
255 assert!(cap.request(Capability::UART).ok().is_ok());
256 Ok(())
257 }
258
259 #[test]
260 fn test_capabilities_not_met() -> anyhow::Result<()> {
261 let cap = Capabilities::new(Capability::UART | Capability::SPI);
262 assert!(cap.request(Capability::GPIO).ok().is_err());
263 Ok(())
264 }
265}