wasefire_board_api/
lib.rs1#![no_std]
21#![feature(doc_auto_cfg)]
22#![feature(never_type)]
23
24extern crate alloc;
25
26use core::marker::PhantomData;
27use core::ops::Deref;
28
29use derive_where::derive_where;
30use wasefire_error::Code;
31pub use wasefire_error::Error;
32
33pub mod applet;
34#[cfg(feature = "api-button")]
35pub mod button;
36#[cfg(feature = "api-clock")]
37pub mod clock;
38#[cfg(feature = "internal-api-crypto")]
39pub mod crypto;
40pub mod debug;
41#[cfg(feature = "internal-api-fingerprint")]
42pub mod fingerprint;
43#[cfg(feature = "api-gpio")]
44pub mod gpio;
45#[cfg(feature = "api-led")]
46pub mod led;
47pub mod platform;
48#[cfg(feature = "api-rng")]
49pub mod rng;
50#[cfg(feature = "api-timer")]
51pub mod timer;
52pub mod transfer;
53#[cfg(feature = "api-uart")]
54pub mod uart;
55#[cfg(feature = "internal-api-usb")]
56pub mod usb;
57#[cfg(feature = "api-vendor")]
58pub mod vendor;
59
60pub trait Api: Send + 'static {
66 fn try_event() -> Option<Event<Self>>;
70
71 fn wait_event() -> Event<Self>;
76
77 type Applet: applet::Api;
79
80 #[cfg(feature = "api-button")]
82 type Button: button::Api;
83
84 #[cfg(feature = "api-clock")]
86 type Clock: clock::Api;
87
88 #[cfg(feature = "internal-api-crypto")]
90 type Crypto: crypto::Api;
91
92 type Debug: debug::Api;
94
95 #[cfg(feature = "internal-api-fingerprint")]
97 type Fingerprint: fingerprint::Api;
98
99 #[cfg(feature = "api-gpio")]
101 type Gpio: gpio::Api;
102
103 #[cfg(feature = "api-led")]
105 type Led: led::Api;
106
107 type Platform: platform::Api;
109
110 #[cfg(feature = "api-rng")]
112 type Rng: rng::Api;
113
114 #[cfg(feature = "api-storage")]
116 type Storage: Singleton + wasefire_store::Storage + Send;
117
118 #[cfg(feature = "api-timer")]
120 type Timer: timer::Api;
121
122 #[cfg(feature = "api-uart")]
124 type Uart: uart::Api;
125
126 #[cfg(feature = "internal-api-usb")]
128 type Usb: usb::Api;
129
130 #[cfg(feature = "api-vendor")]
132 type Vendor: vendor::Api;
133}
134
135pub trait Support<Value> {
140 const SUPPORT: Value;
142}
143
144pub trait Supported {}
146
147pub trait Singleton: Sized {
149 fn take() -> Option<Self>;
153}
154
155#[cfg_attr(feature = "defmt", derive(defmt::Format))]
160#[derive_where(Debug, PartialEq, Eq)]
161pub enum Event<B: Api + ?Sized> {
162 #[cfg(feature = "api-button")]
164 Button(button::Event<B>),
165
166 #[cfg(feature = "internal-api-fingerprint")]
168 Fingerprint(fingerprint::Event),
169
170 #[cfg(feature = "api-gpio")]
172 Gpio(gpio::Event<B>),
173
174 Platform(platform::Event),
176
177 #[cfg(feature = "api-timer")]
179 Timer(timer::Event<B>),
180
181 #[cfg(feature = "api-uart")]
183 Uart(uart::Event<B>),
184
185 #[cfg(feature = "internal-api-usb")]
187 Usb(usb::Event),
188
189 #[cfg(feature = "api-vendor")]
191 Vendor(vendor::Event<B>),
192
193 Impossible(Impossible<B>),
195}
196
197#[derive_where(Debug, Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
202pub struct Impossible<B: Api + ?Sized>(!, PhantomData<B>);
203
204#[cfg(feature = "defmt")]
205impl<B: Api + ?Sized> defmt::Format for Impossible<B> {
206 fn format(&self, fmt: defmt::Formatter) {
207 defmt::write!(fmt, "Impossible");
208 }
209}
210
211impl<B: Api + ?Sized> Impossible<B> {
212 pub fn unreachable(&self) -> ! {
214 match self.0 {}
215 }
216}
217
218pub type Applet<B> = <B as Api>::Applet;
220
221#[cfg(feature = "api-button")]
223pub type Button<B> = <B as Api>::Button;
224
225#[cfg(feature = "api-clock")]
227pub type Clock<B> = <B as Api>::Clock;
228
229#[cfg(feature = "internal-api-crypto")]
231pub type Crypto<B> = <B as Api>::Crypto;
232
233pub type Debug<B> = <B as Api>::Debug;
235
236#[cfg(feature = "internal-api-fingerprint")]
238pub type Fingerprint<B> = <B as Api>::Fingerprint;
239
240#[cfg(feature = "api-gpio")]
242pub type Gpio<B> = <B as Api>::Gpio;
243
244#[cfg(feature = "api-led")]
246pub type Led<B> = <B as Api>::Led;
247
248pub type Platform<B> = <B as Api>::Platform;
250
251#[cfg(feature = "api-rng")]
253pub type Rng<B> = <B as Api>::Rng;
254
255#[cfg(feature = "api-storage")]
257pub type Storage<B> = <B as Api>::Storage;
258
259#[cfg(feature = "api-timer")]
261pub type Timer<B> = <B as Api>::Timer;
262
263#[cfg(feature = "api-uart")]
265pub type Uart<B> = <B as Api>::Uart;
266
267#[cfg(feature = "internal-api-usb")]
269pub type Usb<B> = <B as Api>::Usb;
270
271#[cfg(feature = "api-vendor")]
273pub type Vendor<B> = <B as Api>::Vendor;
274
275#[derive_where(Debug, Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
277pub struct Id<T: Support<usize> + ?Sized> {
278 value: usize,
280 count: PhantomData<T>,
281}
282
283#[cfg(feature = "defmt")]
284impl<T: Support<usize> + ?Sized> defmt::Format for Id<T> {
285 fn format(&self, fmt: defmt::Formatter) {
286 self.value.format(fmt)
287 }
288}
289
290impl<T: Support<usize>> Id<T> {
291 pub fn new(value: usize) -> Result<Self, Error> {
293 match value < T::SUPPORT {
294 true => Ok(Self { value, count: PhantomData }),
295 false => Err(Error::user(Code::OutOfBounds)),
296 }
297 }
298}
299
300impl<T: Support<usize>> Deref for Id<T> {
301 type Target = usize;
302
303 fn deref(&self) -> &Self::Target {
304 &self.value
305 }
306}
307
308impl<T: Supported> Support<bool> for T {
309 const SUPPORT: bool = true;
310}
311
312pub struct Trap;
314
315#[derive(Default, Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
317#[repr(transparent)]
318pub struct Failure(u32);
319
320impl Failure {
321 pub const TRAP: Self = Failure(0x100_0000);
323
324 pub fn split(self) -> Option<Error> {
326 if self == Self::TRAP {
327 return None;
328 }
329 Some(unsafe { core::mem::transmute::<u32, Error>(self.0) })
331 }
332}
333
334impl From<Trap> for Failure {
335 fn from(Trap: Trap) -> Self {
336 Failure::TRAP
337 }
338}
339
340impl From<Error> for Failure {
341 fn from(value: Error) -> Self {
342 Failure(unsafe { core::mem::transmute::<Error, u32>(value) })
344 }
345}