1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
use crate::command::{rx, xmit, Command, CommandResponse, CommandResponseStatus};
use crate::Error;
use core::convert::TryFrom;
use scroll::{ctx, Pread, LE};
#[derive(Debug, PartialEq)]
pub enum BinInfoMode {
Bootloader = 0x0001,
User = 0x0002,
}
impl TryFrom<u32> for BinInfoMode {
type Error = Error;
fn try_from(value: u32) -> Result<Self, Self::Error> {
match value {
1 => Ok(BinInfoMode::Bootloader),
2 => Ok(BinInfoMode::User),
_ => Err(Error::Parse),
}
}
}
pub fn bin_info(d: &hidapi::HidDevice) -> Result<BinInfoResponse, Error> {
xmit(Command::new(0x0001, 0, vec![]), d)?;
match rx(d) {
Ok(CommandResponse {
status: CommandResponseStatus::Success,
data,
..
}) => (data.as_slice()).pread_with(0, LE),
Ok(_) => Err(Error::CommandNotRecognized),
Err(e) => Err(e),
}
}
#[derive(Debug, PartialEq)]
pub struct BinInfoResponse {
pub mode: BinInfoMode,
pub flash_page_size: u32,
pub flash_num_pages: u32,
pub max_message_size: u32,
pub family_id: Option<FamilyId>,
}
#[allow(non_camel_case_types)]
#[derive(Debug, Copy, Clone, PartialEq)]
pub enum FamilyId {
ATSAMD21,
ATSAMD51,
NRF52840,
STM32F103,
STM32F401,
ATMEGA32,
CYPRESS_FX2,
UNKNOWN(u32),
}
impl From<u32> for FamilyId {
fn from(val: u32) -> Self {
match val {
0x68ed_2b88 => Self::ATSAMD21,
0x5511_4460 => Self::ATSAMD51,
0x1b57_745f => Self::NRF52840,
0x5ee2_1072 => Self::STM32F103,
0x5775_5a57 => Self::STM32F401,
0x1657_3617 => Self::ATMEGA32,
0x5a18_069b => Self::CYPRESS_FX2,
_ => Self::UNKNOWN(val),
}
}
}
impl<'a> ctx::TryFromCtx<'a, scroll::Endian> for BinInfoResponse {
type Error = Error;
fn try_from_ctx(this: &'a [u8], le: scroll::Endian) -> Result<(Self, usize), Self::Error> {
if this.len() < 16 {
return Err(Error::Parse);
}
let mut offset = 0;
let mode: u32 = this.gread_with::<u32>(&mut offset, le)?;
let mode: Result<BinInfoMode, Error> = BinInfoMode::try_from(mode);
let mode: BinInfoMode = mode?;
let flash_page_size = this.gread_with::<u32>(&mut offset, le)?;
let flash_num_pages = this.gread_with::<u32>(&mut offset, le)?;
let max_message_size = this.gread_with::<u32>(&mut offset, le)?;
let family_id = if this.len() >= 20 {
let family_id: FamilyId = this.gread_with::<u32>(&mut offset, le)?.into();
Some(family_id)
} else {
None
};
Ok((
BinInfoResponse {
mode,
flash_page_size,
flash_num_pages,
max_message_size,
family_id,
},
offset,
))
}
}