elf2flash_core/boards/
mod.rs1mod circuit_playground_bluefruit;
2mod rp2040;
3mod rp2350;
4
5pub use circuit_playground_bluefruit::CircuitPlaygroundBluefruit;
6pub use rp2040::RP2040;
7pub use rp2350::RP2350;
8use thiserror::Error;
9
10pub struct BoardIter {
12 inner: std::vec::IntoIter<Box<dyn BoardInfo>>,
13}
14
15impl BoardIter {
16 pub fn new() -> Self {
18 Self {
19 inner: vec![
20 Box::new(RP2040::default()) as Box<dyn BoardInfo>,
21 Box::new(RP2350::default()),
22 Box::new(CircuitPlaygroundBluefruit::default()),
23 ]
24 .into_iter(),
25 }
26 }
27
28 pub fn find_by_name(name: &str) -> Option<Box<dyn BoardInfo>> {
29 for board in Self::new() {
30 if board.board_name().eq_ignore_ascii_case(name) {
31 return Some(board);
32 }
33 }
34 None
35 }
36}
37
38impl Iterator for BoardIter {
39 type Item = Box<dyn BoardInfo>;
40 fn next(&mut self) -> Option<Self::Item> {
41 self.inner.next()
42 }
43}
44
45#[allow(unused)]
47#[derive(Debug, Clone)]
48pub struct UsbVersion(pub u8, pub u8, pub u8);
49
50#[allow(unused)]
53#[derive(Debug, Clone)]
54pub struct UsbDevice {
55 pub bus_number: u8,
56 pub address: u8,
57 pub vendor_id: u16,
58 pub product_id: u16,
59 pub version: UsbVersion,
60}
61
62pub trait BoardInfo {
64 fn is_device_board(&self, device: &UsbDevice) -> bool;
66
67 fn family_id(&self) -> u32;
69
70 fn page_size(&self) -> u32 {
72 256
73 }
74
75 fn flash_sector_erase_size(&self) -> u64 {
77 4096
78 }
79
80 fn board_name(&self) -> String;
82}
83
84#[derive(Debug, Clone)]
86pub struct CustomBoardBuilder {
87 vendor_id: Option<u16>,
88 product_id: Option<u16>,
89 family_id: Option<u32>,
90 board_name: Option<String>,
91 page_size: Option<u32>,
92 flash_sector_erase_size: Option<u64>,
93}
94
95impl CustomBoardBuilder {
96 pub fn new() -> Self {
97 Self {
98 vendor_id: None,
99 product_id: None,
100 family_id: None,
101 board_name: None,
102 page_size: None,
103 flash_sector_erase_size: None,
104 }
105 }
106
107 pub fn vendor_id(mut self, vendor_id: u16) -> Self {
108 self.vendor_id = Some(vendor_id);
109 self
110 }
111
112 pub fn product_id(mut self, product_id: u16) -> Self {
113 self.product_id = Some(product_id);
114 self
115 }
116
117 pub fn family_id(mut self, family_id: u32) -> Self {
118 self.family_id = Some(family_id);
119 self
120 }
121
122 pub fn board_name<S: Into<String>>(mut self, board_name: S) -> Self {
123 self.board_name = Some(board_name.into());
124 self
125 }
126
127 pub fn page_size(mut self, page_size: u32) -> Self {
128 self.page_size = Some(page_size);
129 self
130 }
131
132 pub fn flash_sector_erase_size(mut self, size: u64) -> Self {
133 self.flash_sector_erase_size = Some(size);
134 self
135 }
136
137 pub fn build(self) -> Result<CustomBoard, CustomBoardBuildError> {
138 Ok(CustomBoard {
139 vendor_id: self.vendor_id,
140 product_id: self.product_id,
141 family_id: self
142 .family_id
143 .ok_or(CustomBoardBuildError::FamilyIdRequired)?,
144 board_name: self.board_name,
145 page_size: self.page_size,
146 flash_sector_erase_size: self.flash_sector_erase_size,
147 })
148 }
149}
150
151#[derive(Error, Debug)]
152pub enum CustomBoardBuildError {
153 #[error("family_id is required")]
154 FamilyIdRequired,
155}
156
157#[derive(Debug, Clone)]
159pub struct CustomBoard {
160 vendor_id: Option<u16>,
161 product_id: Option<u16>,
162 family_id: u32,
163 board_name: Option<String>,
164 page_size: Option<u32>,
165 flash_sector_erase_size: Option<u64>,
166}
167
168impl BoardInfo for CustomBoard {
169 fn is_device_board(&self, device: &UsbDevice) -> bool {
170 if let Some(vendor_id) = self.vendor_id
171 && device.vendor_id != vendor_id
172 {
173 return false;
174 }
175
176 if let Some(vendor_id) = self.product_id
177 && device.product_id != vendor_id
178 {
179 return false;
180 }
181
182 true
183 }
184
185 fn family_id(&self) -> u32 {
186 self.family_id
187 }
188
189 fn board_name(&self) -> String {
190 self.board_name.clone().unwrap_or("custom".to_string())
191 }
192
193 fn page_size(&self) -> u32 {
194 self.page_size.unwrap_or(256)
195 }
196
197 fn flash_sector_erase_size(&self) -> u64 {
198 self.flash_sector_erase_size.unwrap_or(4096)
199 }
200}