use sealed::sealed;
use wasefire_applet_api::uart as api;
use crate::serial::Event;
use crate::{Error, convert, convert_unit};
pub fn count() -> usize {
convert(unsafe { api::count() }).unwrap_or(0)
}
pub struct Uart(usize);
impl Uart {
pub fn new(uart: usize) -> Result<Self, Error> {
UartBuilder::new(uart).build()
}
}
pub struct UartBuilder {
uart: usize,
baudrate: Option<usize>,
}
impl UartBuilder {
pub fn new(uart: usize) -> Self {
UartBuilder { uart, baudrate: None }
}
pub fn set_baudrate(mut self, baudrate: usize) -> Self {
self.baudrate = Some(baudrate);
self
}
pub fn build(self) -> Result<Uart, Error> {
let uart = self.uart;
if let Some(baudrate) = self.baudrate {
let params = api::set_baudrate::Params { uart, baudrate };
convert_unit(unsafe { api::set_baudrate(params) })?;
}
let params = api::start::Params { uart };
convert_unit(unsafe { api::start(params) })?;
Ok(Uart(uart))
}
}
impl Drop for Uart {
fn drop(&mut self) {
let params = api::stop::Params { uart: self.0 };
convert_unit(unsafe { api::stop(params) }).unwrap();
}
}
#[sealed]
impl crate::serial::Serial for Uart {
fn read(&self, buffer: &mut [u8]) -> Result<usize, Error> {
let params =
api::read::Params { uart: self.0, ptr: buffer.as_mut_ptr(), len: buffer.len() };
convert(unsafe { api::read(params) })
}
fn write(&self, buffer: &[u8]) -> Result<usize, Error> {
let params = api::write::Params { uart: self.0, ptr: buffer.as_ptr(), len: buffer.len() };
convert(unsafe { api::write(params) })
}
fn flush(&self) -> Result<(), Error> {
Ok(())
}
unsafe fn register(
&self, event: Event, func: extern "C" fn(*const u8), data: *const u8,
) -> Result<(), Error> {
let params = api::register::Params {
uart: self.0,
event: convert_event(event) as usize,
handler_func: func,
handler_data: data,
};
convert_unit(unsafe { api::register(params) })
}
fn unregister(&self, event: Event) -> Result<(), Error> {
let params = api::unregister::Params { uart: self.0, event: convert_event(event) as usize };
convert_unit(unsafe { api::unregister(params) })
}
}
fn convert_event(event: Event) -> api::Event {
match event {
Event::Read => api::Event::Read,
Event::Write => api::Event::Write,
}
}