1use crate::traits::app::BootClient;
7use tinyboot_protocol::frame::{Frame, InfoData};
8use tinyboot_protocol::{Cmd, Status};
9
10pub struct AppConfig {
12 pub capacity: u32,
14 pub erase_size: u16,
16 pub boot_version: u16,
18 pub app_version: u16,
20}
21
22pub struct App<B: BootClient> {
24 frame: Frame,
25 config: AppConfig,
26 client: B,
27}
28
29impl<B: BootClient> App<B> {
30 pub fn new(config: AppConfig, client: B) -> Self {
32 Self {
33 frame: Frame::default(),
34 config,
35 client,
36 }
37 }
38
39 pub fn confirm(&mut self) {
42 self.client.confirm();
43 }
44
45 pub fn poll<R: embedded_io::Read, W: embedded_io::Write>(&mut self, rx: &mut R, tx: &mut W) {
47 let status = match self.frame.read(rx) {
48 Ok(s) => s,
49 Err(_) => return,
50 };
51 if status == Status::Ok {
52 self.handle_cmd();
53 } else {
54 self.frame.len = 0;
55 self.frame.status = status;
56 }
57 if self.frame.cmd != Cmd::Reset {
58 let _ = self.frame.send(tx);
59 let _ = tx.flush();
60 }
61 }
62
63 pub async fn poll_async<R: embedded_io_async::Read, W: embedded_io_async::Write>(
65 &mut self,
66 rx: &mut R,
67 tx: &mut W,
68 ) {
69 let status = match self.frame.read_async(rx).await {
70 Ok(s) => s,
71 Err(_) => return,
72 };
73 if status == Status::Ok {
74 self.handle_cmd();
75 } else {
76 self.frame.len = 0;
77 self.frame.status = status;
78 }
79 if self.frame.cmd != Cmd::Reset {
80 let _ = self.frame.send_async(tx).await;
81 let _ = tx.flush().await;
82 }
83 }
84
85 fn handle_cmd(&mut self) {
86 self.frame.status = Status::Ok;
87 match self.frame.cmd {
88 Cmd::Info => {
89 self.frame.len = 12;
90 self.frame.data.info = InfoData {
91 capacity: self.config.capacity,
92 erase_size: self.config.erase_size,
93 boot_version: self.config.boot_version,
94 app_version: self.config.app_version,
95 mode: 1, };
97 }
98 Cmd::Reset => {
99 if self.frame.addr == 1 {
100 self.client.request_update();
101 }
102 self.client.system_reset();
103 }
104 _ => {
105 self.frame.len = 0;
106 self.frame.status = Status::Unsupported;
107 }
108 }
109 }
110}