crazyflie_lib/subsystems/memory/
ow.rs1use std::collections::HashMap;
2
3use crate::{subsystems::memory::{memory_types, MemoryBackend}, Error, Result};
4use memory_types::{FromMemoryBackend, MemoryType};
5
6#[derive(Debug)]
8pub struct OwMemory {
9 memory: MemoryBackend,
10 used_pins: u32,
12 vid: u8,
14 pid: u8,
16 elements: HashMap<String, String>
18 }
19
20 impl OwMemory {
21 pub fn used_pins(&self) -> u32 {
23 self.used_pins
24 }
25
26 pub fn set_used_pins(&mut self, used_pins: u32) {
28 self.used_pins = used_pins;
29 }
30
31 pub fn vid(&self) -> u8 {
33 self.vid
34 }
35
36 pub fn set_vid(&mut self, vid: u8) {
38 self.vid = vid;
39 }
40
41 pub fn pid(&self) -> u8 {
43 self.pid
44 }
45
46 pub fn set_pid(&mut self, pid: u8) {
48 self.pid = pid;
49 }
50
51 pub fn elements(&self) -> &HashMap<String, String> {
53 &self.elements
54 }
55
56 pub fn elements_mut(&mut self) -> &mut HashMap<String, String> {
58 &mut self.elements
59 }
60
61 pub fn set_elements(&mut self, elements: HashMap<String, String>) {
63 self.elements = elements;
64 }
65}
66
67impl FromMemoryBackend for OwMemory {
68 async fn from_memory_backend(memory: MemoryBackend) -> Result<Self> {
69 if memory.memory_type == MemoryType::OneWire {
70 Ok(OwMemory::new(memory).await?)
71 } else {
72 Err(Error::MemoryError("Wrong type of memory!".to_owned()))
73 }
74 }
75
76 async fn initialize_memory_backend(memory: MemoryBackend) -> Result<Self> {
77 if memory.memory_type == MemoryType::OneWire {
78 Ok(OwMemory::initialize(memory).await?)
79 } else {
80 Err(Error::MemoryError("Wrong type of memory!".to_owned()))
81 }
82 }
83
84 fn close_memory(self) -> MemoryBackend {
85 self.memory
86 }
87}
88
89impl OwMemory {
90 pub(crate) async fn new(memory: MemoryBackend) -> Result<Self> {
91 let header = memory.read::<fn(usize, usize)>(0, 8, None).await?;
92
93 if header[0] != 0xEB {
95 return Err(Error::MemoryError("Invalid OneWire header".to_owned()));
96 }
97
98 let used_pins = u32::from_le_bytes([header[1], header[2], header[3], header[4]]);
100 let vid = header[5];
101 let pid = header[6];
102 let crc_byte = header[7];
103
104 let crc_data = &header[0..7];
106 let calculated_crc = crc32fast::hash(crc_data);
107 let expected_crc_lsb = (calculated_crc & 0xFF) as u8;
108
109 if crc_byte != expected_crc_lsb {
110 return Err(Error::MemoryError("OneWire CRC validation failed".to_owned()));
111 }
112
113 let element_header = memory.read::<fn(usize, usize)>(8, 2, None).await?;
114 let version = element_header[0];
115 let element_length = element_header[1];
116
117 if version != 0 {
118 return Err(Error::MemoryError("Unsupported OneWire version".to_owned()));
119 }
120
121 let elements = memory.read::<fn(usize, usize)>(10, element_length as usize, None).await?;
122 let elements_crc = memory.read::<fn(usize, usize)>(10 + element_length as usize, 1, None).await?[0];
123
124 let mut data = element_header;
125 data.extend_from_slice(&elements);
126
127 let calculated_crc = crc32fast::hash(&data);
128 let expected_crc_lsb = (calculated_crc & 0xFF) as u8;
129
130 if elements_crc != expected_crc_lsb {
131 return Err(Error::MemoryError("OneWire data CRC validation failed".to_owned()));
132 }
133
134 let elements_map = Self::parse_elements(&elements);
135
136 Ok(OwMemory {
137 memory,
138 used_pins,
139 vid,
140 pid,
141 elements: elements_map
142 })
143 }
144
145 pub(crate) async fn initialize(memory: MemoryBackend) -> Result<Self> {
146 Ok(OwMemory {
147 memory,
148 used_pins: 0,
149 vid: 0,
150 pid: 0,
151 elements: HashMap::new()
152 })
153 }
154
155 fn parse_elements(data: &[u8]) -> HashMap<String, String> {
156 let mut elements = HashMap::new();
157 let mut offset = 0;
158
159 while offset < data.len() {
160 if offset + 1 >= data.len() {
161 break;
162 }
163
164 let element_id = data[offset];
165 let element_length = data[offset + 1];
166 offset += 2;
167
168 if offset + element_length as usize > data.len() {
169 break;
170 }
171
172 let element_data = &data[offset..offset + element_length as usize];
173 offset += element_length as usize;
174
175 match element_id {
176 1 => { if let Ok(board_name) = String::from_utf8(element_data.to_vec()) {
178 elements.insert("boardName".to_string(), board_name);
179 }
180 },
181 2 => { if let Ok(revision) = String::from_utf8(element_data.to_vec()) {
183 elements.insert("revision".to_string(), revision);
184 }
185 },
186 3 => { let custom_data = hex::encode(element_data);
188 elements.insert("customData".to_string(), custom_data);
189 },
190 _ => {
191 }
193 }
194 }
195
196 elements
197 }
198
199}