1#[allow(unused_imports)]
2use binrw::{BinRead, BinWrite, binread, binrw, binwrite};
3use std::borrow::Cow;
4use std::ops::RangeInclusive;
5use std::ops::{Deref, DerefMut};
6
7#[cfg(feature = "serde")]
8use serde::{Deserialize, Deserializer, Serialize, Serializer};
9#[allow(unused_imports)]
10#[cfg(feature = "serde")]
11use serde::{de, de::Error as _, ser};
12
13#[derive(Debug, Clone)]
15pub enum Error {
16 Exceeded(Exceeded),
17}
18
19impl Error {
20 pub fn is_exceeded(&self) -> bool {
21 matches!(self, Self::Exceeded(..))
22 }
23
24 pub fn exceeded(&self) -> Option<&Exceeded> {
25 match &self {
26 Self::Exceeded(e) => Some(e),
27 }
28 }
29}
30
31impl From<Exceeded> for Error {
32 fn from(value: Exceeded) -> Self {
33 Self::Exceeded(value)
34 }
35}
36
37impl std::fmt::Display for Error {
38 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
39 match self {
40 Self::Exceeded(e) => write!(f, "exceeded: {}", e),
41 }
42 }
43}
44
45impl std::error::Error for Error {}
46
47#[derive(Debug, Clone)]
48pub struct Exceeded(usize, ExpectedRange);
49
50impl Exceeded {
51 pub fn unexpected(&self) -> usize {
52 self.0
53 }
54 pub fn expected_range(&self) -> &RangeInclusive<usize> {
55 &self.1.0
56 }
57
58 #[cfg(feature = "serde")]
59 pub fn to_serde<'de, D: Deserializer<'de>>(&self) -> D::Error {
60 D::Error::invalid_value(de::Unexpected::Unsigned(self.0 as u64), &self.1)
61 }
62}
63
64impl std::fmt::Display for Exceeded {
65 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
66 write!(
67 f,
68 "{} is not within valid range of size ({})",
69 self.0, self.1
70 )
71 }
72}
73
74impl std::error::Error for Exceeded {}
75
76#[derive(Debug, Clone, PartialEq, Eq)]
79struct ExpectedRange(RangeInclusive<usize>);
80
81impl From<RangeInclusive<usize>> for ExpectedRange {
82 fn from(value: RangeInclusive<usize>) -> Self {
83 Self(value)
84 }
85}
86
87impl std::fmt::Display for ExpectedRange {
88 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
89 write!(f, "{:?}", self.0)
90 }
91}
92
93#[cfg(feature = "serde")]
94impl de::Expected for ExpectedRange {
95 fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
96 write!(formatter, "a size within range {}", self)
97 }
98}
99
100mod checksum {
101 #[derive(Default, Debug, Clone)]
102 pub struct Buffer {
103 state: u8,
104 }
105
106 impl Buffer {
107 pub fn new() -> Self {
108 Self::default()
109 }
110 pub fn state(&self) -> u8 {
111 self.state
112 }
113 }
114
115 impl std::io::Write for Buffer {
116 fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
117 self.state = self.state ^ iter(buf.iter().copied());
118 Ok(buf.len())
119 }
120 fn flush(&mut self) -> std::io::Result<()> {
121 Ok(())
122 }
123 }
124
125 pub(super) fn single(data: u8) -> u8 {
126 data ^ 0xff
127 }
128
129 pub(super) fn iter(data: impl Iterator<Item = u8>) -> u8 {
130 data.fold(0u8, |acc, e| acc ^ e)
131 }
132}
133
134#[binwrite]
153#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
154#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
155#[bw(big)]
156pub struct Opcode(u8, #[bw(calc = checksum::single(self.0))] u8);
157
158impl Opcode {
159 pub const GET: Self = Self(0x00u8);
160 pub const GET_VERSION: Self = Self(0x01u8);
161 pub const GET_ID: Self = Self(0x02u8);
162 pub const READ: Self = Self(0x11u8);
163 pub const GO: Self = Self(0x21u8);
164 pub const WRITE: Self = Self(0x31u8);
165 pub const ERASE: Self = Self(0x43u8);
166 pub const EXTENDED_ERASE: Self = Self(0x44u8);
167 pub const WRITE_PROTECT: Self = Self(0x63u8);
168 pub const WRITE_UNPROTECT: Self = Self(0x73u8);
169 pub const READ_PROTECT: Self = Self(0x82u8);
170 pub const READ_UNPROTECT: Self = Self(0x92u8);
171 pub const GET_CHECKSUM: Self = Self(0xa1u8);
172 pub const SPECIAL: Self = Self(0x50u8);
173 pub const EXTENDED_SPECIAL: Self = Self(0x51u8);
174
175 pub fn as_u8(&self) -> u8 {
176 self.0
177 }
178}
179
180impl std::fmt::Display for Opcode {
181 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
182 match self {
183 &Self::GET => write!(f, "GET"),
184 &Self::GET_VERSION => write!(f, "GET_VERSION"),
185 &Self::GET_ID => write!(f, "GET_ID"),
186 &Self::READ => write!(f, "READ"),
187 &Self::GO => write!(f, "GO"),
188 &Self::WRITE => write!(f, "WRITE"),
189 &Self::ERASE => write!(f, "ERASE"),
190 &Self::EXTENDED_ERASE => write!(f, "EXTENDED_ERASE"),
191 &Self::WRITE_PROTECT => write!(f, "WRITE_PROTECT"),
192 &Self::WRITE_UNPROTECT => write!(f, "WRITE_UNPROTECT"),
193 &Self::READ_PROTECT => write!(f, "READ_PROTECT"),
194 &Self::READ_UNPROTECT => write!(f, "READ_UNPROTECT"),
195 &Self::GET_CHECKSUM => write!(f, "GET_CHECKSUM"),
196 &Self::SPECIAL => write!(f, "SPECIAL"),
197 &Self::EXTENDED_SPECIAL => write!(f, "EXTENDED_SPECIAL"),
198 opcode => write!(f, "UNKNOWN ({:02x?})", opcode.as_u8()),
199 }
200 }
201}
202
203impl From<u8> for Opcode {
204 fn from(value: u8) -> Self {
205 Self(value)
206 }
207}
208
209#[binwrite]
211#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
212#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
213#[bw(big)]
214pub struct Address(
215 u32,
216 #[bw(calc = checksum::iter(self.0.to_ne_bytes().iter().copied()))] u8,
217);
218
219impl Address {
220 pub fn as_u32(&self) -> u32 {
221 self.0
222 }
223}
224
225impl From<u32> for Address {
226 fn from(value: u32) -> Self {
227 Self(value)
228 }
229}
230
231impl Into<u32> for Address {
232 fn into(self) -> u32 {
233 self.0
234 }
235}
236
237macro_rules! define_slice_item {
238 ($vis:vis $name:ident($inner_ty:ident), $as_method:ident, $size_ty:ty, $size_range:expr) => {
239 #[derive(BinWrite, Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
240 $vis struct $name;
241
242 impl SliceItem for $name {
243 type Repr = $inner_ty;
244 type Size = $size_ty;
245 const SIZE_RANGE: RangeInclusive<usize> = $size_range;
246 }
247 }
248}
249
250pub type PageNo = u8;
251pub type ExtendedPageNo = u16;
252pub type SectorNo = u8;
253
254define_slice_item! { pub Byte(u8), as_u8, u8, 1..=256 }
255define_slice_item! { pub Page(PageNo), as_u8, u8, 1..=256 }
256define_slice_item! { pub ExtendedPage(ExtendedPageNo), as_u16, u16, 1..=0xff00 }
257define_slice_item! { pub Sector(SectorNo), as_u8, u8, 1..=256 }
258
259#[binwrite]
260#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
261#[bw(big)]
262pub struct Size(u8, #[bw(calc = checksum::single(self.0))] u8);
263
264impl Into<usize> for Size {
265 fn into(self) -> usize {
266 self.0 as usize + <Byte as SliceItem>::SIZE_RANGE.start()
267 }
268}
269
270impl TryFrom<usize> for Size {
271 type Error = Error;
272
273 fn try_from(value: usize) -> Result<Self, Self::Error> {
274 let range = <Byte as SliceItem>::SIZE_RANGE;
275 if range.contains(&value) {
276 Ok(Self(value as u8))
277 } else {
278 Err(Exceeded(value, range.into()).into())
279 }
280 }
281}
282
283#[cfg(feature = "serde")]
284impl<'de> Deserialize<'de> for Size {
285 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
286 where
287 D: Deserializer<'de>,
288 {
289 let value = usize::deserialize(deserializer)?;
290 let converted = Self::try_from(value).map_err(|e| {
291 let exceeded = e.exceeded().unwrap();
292 exceeded.to_serde::<D>()
293 })?;
294 Ok(converted)
295 }
296}
297
298#[cfg(feature = "serde")]
299impl serde::Serialize for Size {
300 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
301 where
302 S: Serializer,
303 {
304 serializer.serialize_u64(self.0 as u64)
305 }
306}
307
308pub trait SliceItem {
309 #[cfg(not(feature = "serde"))]
310 type Repr: Copy + Clone;
311 #[cfg(feature = "serde")]
312 type Repr: Copy + Clone + Serialize + for<'de> Deserialize<'de>;
313 type Size: TryFrom<usize>;
314 const SIZE_RANGE: RangeInclusive<usize> = usize::MIN..=usize::MAX;
315}
316
317#[derive(Debug, Clone)]
318#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
319pub struct Slice<'a, T: SliceItem> {
320 inner: Cow<'a, [T::Repr]>,
321}
322
323impl<'a, T: SliceItem> Deref for Slice<'a, T> {
324 type Target = Cow<'a, [T::Repr]>;
325
326 fn deref(&self) -> &Self::Target {
327 &self.inner
328 }
329}
330
331impl<'a, T: SliceItem> DerefMut for Slice<'a, T> {
332 fn deref_mut(&mut self) -> &mut Self::Target {
333 &mut self.inner
334 }
335}
336
337impl<'a, T: SliceItem> Slice<'a, T> {
338 pub fn into_inner(self) -> Cow<'a, [T::Repr]> {
340 self.inner
341 }
342
343 pub fn as_slice(&self) -> &[T::Repr] {
345 &self.inner
346 }
347}
348
349impl<'a, T: SliceItem> Into<Cow<'a, [T::Repr]>> for Slice<'a, T> {
350 fn into(self) -> Cow<'a, [T::Repr]> {
351 self.inner
352 }
353}
354
355impl<'a, T: SliceItem> TryFrom<Cow<'a, [T::Repr]>> for Slice<'a, T> {
356 type Error = Error;
357
358 fn try_from(value: Cow<'a, [T::Repr]>) -> Result<Self, Self::Error> {
359 if T::SIZE_RANGE.contains(&value.len()) {
360 Ok(Self { inner: value })
361 } else {
362 Err(Exceeded(value.len(), T::SIZE_RANGE.into()).into())
363 }
364 }
365}
366
367impl<'a, T: SliceItem> TryFrom<Vec<T::Repr>> for Slice<'a, T> {
368 type Error = Error;
369
370 fn try_from(value: Vec<T::Repr>) -> Result<Self, Self::Error> {
371 if T::SIZE_RANGE.contains(&value.len()) {
372 Ok(Self {
373 inner: value.into(),
374 })
375 } else {
376 Err(Exceeded(value.len(), T::SIZE_RANGE.into()).into())
377 }
378 }
379}
380
381impl<'a, T: SliceItem> TryFrom<&'a [T::Repr]> for Slice<'a, T> {
382 type Error = Error;
383
384 fn try_from(value: &'a [T::Repr]) -> Result<Self, Self::Error> {
385 if T::SIZE_RANGE.contains(&value.len()) {
386 Ok(Self {
387 inner: value.into(),
388 })
389 } else {
390 Err(Exceeded(value.len(), T::SIZE_RANGE.into()).into())
391 }
392 }
393}
394
395impl<'a, T: SliceItem + BinWrite<Args<'a> = ()>> BinWrite for Slice<'a, T>
396where
397 [T::Repr]: BinWrite<Args<'a> = ()>,
398 T::Size: BinWrite<Args<'a> = ()>,
399 <T::Size as TryFrom<usize>>::Error: std::fmt::Debug,
400{
401 type Args<'arg> = ();
402
403 fn write_options<W: std::io::Write + std::io::Seek>(
404 &self,
405 writer: &mut W,
406 endian: binrw::Endian,
407 args: Self::Args<'_>,
408 ) -> binrw::BinResult<()> {
409 use binrw::io::NoSeek;
410
411 let lowerbound = *<T as SliceItem>::SIZE_RANGE.start();
413 let size = <T as SliceItem>::Size::try_from(self.inner.len() - lowerbound).unwrap();
414 size.write_options(writer, endian, args)?;
415
416 self.inner.write_options(writer, endian, args)?;
418
419 let mut buffer = checksum::Buffer::new();
421 self.inner
422 .write_options(&mut NoSeek::new(&mut buffer), endian, args)?;
423 buffer.state().write_options(writer, endian, args)?;
424
425 Ok(())
426 }
427}
428
429impl<'a, T: SliceItem + BinWrite<Args<'a> = ()>> binrw::meta::WriteEndian for Slice<'a, T>
430where
431 [T::Repr]: BinWrite<Args<'a> = ()>,
432 T::Size: BinWrite<Args<'a> = ()>,
433 <T::Size as TryFrom<usize>>::Error: std::fmt::Debug,
434{
435 const ENDIAN: binrw::meta::EndianKind = binrw::meta::EndianKind::Endian(binrw::Endian::Big);
436}
437
438pub type Data<'a> = Slice<'a, Byte>;
439pub type PageNos<'a> = Slice<'a, Page>;
440pub type ExtendedPageNos<'a> = Slice<'a, ExtendedPage>;
441pub type SectorNos<'a> = Slice<'a, Sector>;
442
443#[binwrite]
445#[derive(Debug, Clone)]
446#[bw(big)]
447pub enum Command<'a> {
448 Get(#[bw(calc = Opcode::GET)] Opcode),
449 Version(#[bw(calc = Opcode::GET_VERSION)] Opcode),
450 Id(#[bw(calc = Opcode::GET_ID)] Opcode),
451 Read {
452 #[bw(calc = Opcode::READ)]
453 opcode: Opcode,
454 address: Address,
455 size: Size,
456 },
457 Go(#[bw(calc = Opcode::GO)] Opcode, Address),
458 Write {
459 #[bw(calc = Opcode::WRITE)]
460 opcode: Opcode,
461 address: Address,
462 data: Data<'a>,
463 },
464 Erase(#[bw(calc = Opcode::ERASE)] Opcode, Erase<'a>),
465 ExtendedErase(#[bw(calc = Opcode::ERASE)] Opcode, ExtendedErase<'a>),
466 WriteProtect(#[bw(calc = Opcode::WRITE_PROTECT)] Opcode),
467 WriteUnprotect(#[bw(calc = Opcode::WRITE_UNPROTECT)] Opcode),
468 ReadProtect(#[bw(calc = Opcode::READ_PROTECT)] Opcode),
469 ReadUnprotect(#[bw(calc = Opcode::READ_UNPROTECT)] Opcode),
470
471 #[bw(magic = 0x7fu8)]
473 Synchronize,
474}
475
476#[derive(BinWrite, Debug, Clone)]
478#[bw(big)]
479pub enum Erase<'a> {
480 #[bw(magic = 0xff00u16)]
481 Global,
482 Specific(Slice<'a, Page>),
483}
484
485impl<'a> Erase<'a> {
486 pub fn is_global(self) -> bool {
488 matches!(self, Self::Global)
489 }
490
491 pub fn is_specific(self) -> bool {
493 matches!(self, Self::Specific(..))
494 }
495
496 pub fn pages(&self) -> Option<&[PageNo]> {
498 match self {
499 Self::Global => None,
500 Self::Specific(slice) => Some(slice.as_slice()),
501 }
502 }
503}
504
505#[derive(BinWrite, Debug, Clone)]
507#[bw(big)]
508pub enum ExtendedErase<'a> {
509 #[bw(magic = b"\xff\xff\x00")]
510 Global,
511 #[bw(magic = b"\xff\xfe\x01")]
512 Bank1,
513 #[bw(magic = b"\xff\xfd\x02")]
514 Bank2,
515 Specific(Slice<'a, ExtendedPage>),
516}
517
518impl<'a> ExtendedErase<'a> {
519 pub fn is_global(self) -> bool {
521 matches!(self, Self::Global)
522 }
523
524 pub fn is_bank1(self) -> bool {
526 matches!(self, Self::Bank1)
527 }
528
529 pub fn is_bank2(self) -> bool {
531 matches!(self, Self::Bank2)
532 }
533
534 pub fn is_specific(self) -> bool {
536 matches!(self, Self::Specific(..))
537 }
538
539 pub fn pages(&self) -> Option<&[ExtendedPageNo]> {
541 match self {
542 Self::Global => None,
543 Self::Bank1 => None,
544 Self::Bank2 => None,
545 Self::Specific(slice) => Some(slice.as_slice()),
546 }
547 }
548}
549
550#[derive(BinRead, Debug, Clone, Copy)]
552#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
553#[br(big)]
554pub enum Reply {
555 #[brw(magic = 0x79u8)]
557 Ack,
558 #[brw(magic = 0x1fu8)]
560 NAck,
561}
562
563#[binread]
567#[derive(Debug, Clone)]
568#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
569#[br(big)]
570pub struct Bootloader {
571 #[br(temp)]
572 len: u8,
573 version: u8,
574 #[br(count = len, map = |data: Vec<u8>| {
575 data.into_iter().map(|v| v.into()).collect()
576 })]
577 opcodes: Vec<Opcode>,
578}
579
580impl Bootloader {
581 #[inline]
583 pub fn version(&self) -> u8 {
584 self.version
585 }
586
587 #[inline]
589 pub fn major(&self) -> u8 {
590 self.version >> 4
591 }
592
593 #[inline]
595 pub fn minor(&self) -> u8 {
596 self.version & 0xf
597 }
598
599 pub fn version_string(&self) -> String {
601 format!("{}.{}", self.major(), self.minor())
602 }
603
604 #[inline]
606 pub fn opcodes(&self) -> &[Opcode] {
607 &self.opcodes
608 }
609
610 #[inline]
612 pub fn supports(&self, opcode: impl Into<Opcode>) -> bool {
613 self.opcodes.contains(&opcode.into())
614 }
615}
616
617#[derive(BinRead, Debug, Clone)]
619#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
620#[br(big)]
621pub struct Version {
622 version: u8,
623 options: [u8; 2],
624}
625
626impl Version {
627 #[inline]
629 pub fn version(&self) -> u8 {
630 self.version
631 }
632
633 #[inline]
635 pub fn major(&self) -> u8 {
636 self.version >> 4
637 }
638
639 #[inline]
641 pub fn minor(&self) -> u8 {
642 self.version & 0xf
643 }
644
645 pub fn version_string(&self) -> String {
647 format!("{}.{}", self.major(), self.minor())
648 }
649
650 #[inline]
651 pub fn options(&self) -> [u8; 2] {
652 self.options
653 }
654}
655
656impl std::fmt::Display for Version {
657 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
658 write!(f, "{}.{}", self.major(), self.minor())
659 }
660}
661
662#[binread]
664#[derive(Debug, Clone)]
665#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
666#[br(big)]
667pub struct Id {
668 #[br(temp)]
669 len: u8,
670 #[br(count = len + 1)]
671 id: Vec<u8>,
672}
673
674impl Id {
675 #[inline]
677 pub fn into_id(self) -> Vec<u8> {
678 self.id
679 }
680
681 #[inline]
683 pub fn id(&self) -> &[u8] {
684 &self.id
685 }
686
687 #[inline]
689 pub fn as_slice(&self) -> &[u8] {
690 &self.id
691 }
692
693 pub fn as_array<const N: usize>(&self) -> [u8; N] {
695 let mut buf: [u8; N] = [0u8; N];
696 buf[N - self.id.len()..].copy_from_slice(&self.id);
697 buf
698 }
699
700 #[inline]
702 pub fn as_u16(&self) -> u16 {
703 u16::from_be_bytes(self.as_array())
704 }
705
706 #[inline]
708 pub fn as_u32(&self) -> u32 {
709 u32::from_be_bytes(self.as_array())
710 }
711
712 #[inline]
714 pub fn as_u64(&self) -> u64 {
715 u64::from_be_bytes(self.as_array())
716 }
717}