use crate::traits::app::BootClient;
use tinyboot_protocol::frame::{Frame, InfoData};
use tinyboot_protocol::{Cmd, Status};
pub struct AppConfig {
pub capacity: u32,
pub erase_size: u16,
pub boot_version: u16,
pub app_version: u16,
}
pub struct App<B: BootClient> {
frame: Frame,
config: AppConfig,
client: B,
}
impl<B: BootClient> App<B> {
pub fn new(config: AppConfig, client: B) -> Self {
Self {
frame: Frame::default(),
config,
client,
}
}
pub fn confirm(&mut self) {
self.client.confirm();
}
pub fn poll<R: embedded_io::Read, W: embedded_io::Write>(&mut self, rx: &mut R, tx: &mut W) {
let status = match self.frame.read(rx) {
Ok(s) => s,
Err(_) => return,
};
if status == Status::Ok {
self.handle_cmd();
} else {
self.frame.len = 0;
self.frame.status = status;
}
if self.frame.cmd != Cmd::Reset {
let _ = self.frame.send(tx);
let _ = tx.flush();
}
}
pub async fn poll_async<R: embedded_io_async::Read, W: embedded_io_async::Write>(
&mut self,
rx: &mut R,
tx: &mut W,
) {
let status = match self.frame.read_async(rx).await {
Ok(s) => s,
Err(_) => return,
};
if status == Status::Ok {
self.handle_cmd();
} else {
self.frame.len = 0;
self.frame.status = status;
}
if self.frame.cmd != Cmd::Reset {
let _ = self.frame.send_async(tx).await;
let _ = tx.flush().await;
}
}
fn handle_cmd(&mut self) {
self.frame.status = Status::Ok;
match self.frame.cmd {
Cmd::Info => {
self.frame.len = 12;
self.frame.data.info = InfoData {
capacity: self.config.capacity,
erase_size: self.config.erase_size,
boot_version: self.config.boot_version,
app_version: self.config.app_version,
mode: 1, };
}
Cmd::Reset => {
if self.frame.addr == 1 {
self.client.request_update();
}
self.client.system_reset();
}
_ => {
self.frame.len = 0;
self.frame.status = Status::Unsupported;
}
}
}
}