1#![forbid(unsafe_code)]
2
3use byteorder::{BigEndian, ByteOrder, ReadBytesExt};
4use serialport::{self, SerialPort};
5use std::io::{self, Read, Write};
6use std::vec::Vec;
7
8const STARTCODE: u16 = 0xEF01;
9const COMMANDPACKET: u8 = 0x1;
10const ACKPACKET: u8 = 0x7;
11
12const VERIFYPASSWORD: u8 = 0x13;
13const TEMPLATECOUNT: u8 = 0x1D;
14const READSYSPARAM: u8 = 0x0F;
15
16const GETIMAGE: u8 = 0x01;
17const IMAGE2TZ: u8 = 0x02;
18const FINGERPRINTSEARCH: u8 = 0x04;
19const REGMODEL: u8 = 0x05;
20const STORE: u8 = 0x06;
21const DELETE: u8 = 0x0C;
22const DELETEALL: u8 = 0x0D;
23
24pub const OK: u8 = 0x0;
25pub const NOFINGER: u8 = 0x02;
26pub const IMAGEFAIL: u8 = 0x03;
27pub const IMAGEMESS: u8 = 0x06;
28pub const FEATUREFAIL: u8 = 0x07;
29pub const INVALIDIMAGE: u8 = 0x15;
30pub const HISPEEDSEARCH: u8 = 0x1B;
31pub const ENROLLMISMATCH: u8 = 0x0A;
32pub const BADLOCATION: u8 = 0x0B;
33pub const FLASHERR: u8 = 0x18;
34
35pub struct Device {
36 debug: bool,
37 uart: Box<dyn SerialPort>,
38 status_register: Option<u16>,
39 system_id: Option<u16>,
40 pub library_size: Option<u16>,
41 security_level: Option<u16>,
42 address: Vec<u8>,
43 data_packet_size: Option<u16>,
44 baudrate: Option<u16>,
45 password: Vec<u8>,
46 pub template_count: u16,
47 pub finger_id: u16,
48 pub confidence: u16,
49}
50
51impl Device {
52 fn new(address: Vec<u8>, password: Vec<u8>, uart: Box<dyn SerialPort>, debug: bool) -> Result<Device, std::io::Error> {
53 let mut device = Self {
54 debug,
55 uart,
56 address,
57 password,
58 status_register: None,
59 system_id: None,
60 library_size: None,
61 security_level: None,
62 data_packet_size: None,
63 baudrate: None,
64 template_count: 0,
65 finger_id: 0,
66 confidence: 0,
67 };
68
69 if !device.verify_password() {
70 return Err(io::Error::new(
71 io::ErrorKind::ConnectionRefused,
72 "Failed to find sensor, check wiring",
73 ));
74 }
75
76 device.read_sysparam()?;
77
78 Ok(device)
79 }
80
81 pub fn verify_password(&mut self) -> bool {
82 let packet: Vec<u8> = std::iter::once(VERIFYPASSWORD)
83 .chain(self.password.iter().cloned())
84 .collect();
85
86 if let Err(e) = self.send_packet(&packet) {
87 eprintln!("Failed to send the packet: {}", e);
88 return false;
89 }
90
91 let r = self.get_packet(12).unwrap_or_else(|_| vec![0; 12]);
92
93 r[0] == OK
94 }
95
96 pub fn send_packet(&mut self, data: &[u8]) -> io::Result<()> {
97 let mut packet = vec![(STARTCODE >> 8) as u8, (STARTCODE & 0xFF) as u8];
98
99 packet.extend_from_slice(&self.address);
100 packet.push(COMMANDPACKET);
101
102 let length = data.len() + 2;
103 packet.push((length >> 8) as u8);
104 packet.push((length & 0xFF) as u8);
105
106 packet.extend_from_slice(data);
107
108 let checksum: u16 = packet[6..].iter().map(|&byte| byte as u16).sum();
109 packet.push((checksum >> 8) as u8);
110 packet.push((checksum & 0xFF) as u8);
111
112 self.print_debug("send_packet length:", packet.len(), "bytes");
113 self.print_debug("send_packet data:", &packet, "hex");
114
115 self.uart.write_all(&packet)?;
116
117 Ok(())
118 }
119
120 pub fn get_packet(&mut self, expected: usize) -> io::Result<Vec<u8>> {
121 let mut res = vec![0; expected];
122
123 self.uart.read_exact(&mut res)?;
124
125 let start = (&res[0..2]).read_u16::<BigEndian>().unwrap();
126 if start != STARTCODE {
127 return Err(io::Error::new(
128 io::ErrorKind::InvalidData,
129 "Incorrect packet data",
130 ));
131 }
132
133 let addr = res[2..6].to_vec();
134 if addr != self.address {
135 return Err(io::Error::new(
136 io::ErrorKind::InvalidData,
137 "Incorrect address",
138 ));
139 }
140
141 let packet_type = res[6];
142 let length = (&res[7..9]).read_u16::<BigEndian>().unwrap() as usize;
143
144 if packet_type != ACKPACKET {
145 return Err(io::Error::new(
146 io::ErrorKind::InvalidData,
147 "Incorrect packet data",
148 ));
149 }
150
151 let reply = res[9..9 + (length - 2)].to_vec();
152
153 self.print_debug("_get_packet reply:", &reply, "hex");
154
155 Ok(reply)
156 }
157
158 pub fn read_sysparam(&mut self) -> io::Result<u8> {
159 self.send_packet(&[READSYSPARAM])?;
160
161 let r = self.get_packet(28)?;
162
163 if r[0] != OK {
164 return Err(io::Error::new(io::ErrorKind::Other, "Command failed."));
165 }
166
167 self.status_register = Some((&r[1..3]).read_u16::<BigEndian>()?);
168 self.system_id = Some((&r[3..5]).read_u16::<BigEndian>()?);
169 self.library_size = Some((&r[5..7]).read_u16::<BigEndian>()?);
170 self.security_level = Some((&r[7..9]).read_u16::<BigEndian>()?);
171 self.address = r[9..13].to_vec();
172 self.data_packet_size = Some((&r[13..15]).read_u16::<BigEndian>()?);
173 self.baudrate = Some((&r[15..17]).read_u16::<BigEndian>()?);
174
175 Ok(r[0])
176 }
177
178 pub fn count_templates(&mut self) -> io::Result<u8> {
179 let _ = self.send_packet(&[TEMPLATECOUNT]);
180 let r = self.get_packet(14)?;
181
182 if r.len() >= 3 {
183 self.template_count = BigEndian::read_u16(&r[1..3]);
184 } else {
185 self.template_count = 0;
186 }
187
188 if r[0] == OK {
189 Ok(r[0])
190 } else {
191 Err(io::Error::new(io::ErrorKind::Other, "Command failed."))
192 }
193 }
194
195 pub fn get_image(&mut self) -> io::Result<u8> {
196 let _ = self.send_packet(&[GETIMAGE]);
197 let r = self.get_packet(12)?;
198 Ok(r[0])
199 }
200
201 pub fn image_2_tz(&mut self, slot: u8) -> io::Result<u8> {
202 let _ = self.send_packet(&[IMAGE2TZ, slot]);
203 let r = self.get_packet(12)?;
204 Ok(r[0])
205 }
206
207 pub fn finger_search(&mut self) -> io::Result<u8> {
208 if self.library_size.is_none() {
209 return Err(io::Error::new(io::ErrorKind::Other, "Library size not set"));
210 }
211 let capacity = match self.library_size {
212 Some(capacity) => capacity,
213 None => return Err(io::Error::new(io::ErrorKind::Other, "Library size not set")),
214 };
215 let _ = self.send_packet(&[
216 FINGERPRINTSEARCH,
217 0x01,
218 0x00,
219 0x00,
220 (capacity >> 8) as u8,
221 (capacity & 0xFF) as u8,
222 ]);
223 let r = self.get_packet(16)?;
224 self.finger_id = BigEndian::read_u16(&r[1..3]);
225 self.confidence = BigEndian::read_u16(&r[3..5]);
226 self.print_debug("finger_search packet:", &r, "hex");
227 Ok(r[0])
228 }
229
230 pub fn finger_fast_search(&mut self) -> io::Result<u8> {
231 let _ = self.read_sysparam();
232 let capacity = match self.library_size {
233 Some(capacity) => capacity,
234 None => return Err(io::Error::new(io::ErrorKind::Other, "Library size not set")),
235 };
236
237 let packet = vec![
238 HISPEEDSEARCH,
239 0x01,
240 0x00,
241 0x00,
242 (capacity >> 8) as u8,
243 (capacity & 0xFF) as u8,
244 ];
245
246 let _ = self.send_packet(&packet);
247
248 let r = self.get_packet(16)?;
249
250 let finger_data = &r[1..5];
251 self.finger_id = u16::from_be_bytes([finger_data[0], finger_data[1]]);
252 self.confidence = u16::from_be_bytes([finger_data[2], finger_data[3]]);
253
254 self.print_debug("finger_fast_search packet:", &r, "hex");
255
256 Ok(r[0])
257 }
258
259 pub fn create_model(&mut self) -> io::Result<u8> {
260 let _ = self.send_packet(&[REGMODEL]);
261 let r = self.get_packet(12)?;
262 Ok(r[0])
263 }
264
265 pub fn store_model(&mut self, location: u16, slot: u8) -> io::Result<u8> {
266 self.send_packet(&[STORE, slot, (location >> 8) as u8, (location & 0xFF) as u8])?;
267
268 let r = self.get_packet(12)?;
269 Ok(r[0])
270 }
271
272 pub fn delete_model(&mut self, location: u16) -> io::Result<u8> {
273 let high_byte = (location >> 8) as u8;
274 let low_byte = (location & 0xFF) as u8;
275
276 self.send_packet(&[DELETE, high_byte, low_byte, 0x00, 0x01])?;
277
278 let r = self.get_packet(12)?;
279 Ok(r[0])
280 }
281
282 pub fn delete_all(&mut self) -> io::Result<u8> {
283 self.send_packet(&[DELETEALL])?;
284
285 let r = self.get_packet(12)?;
286 Ok(r[0])
287 }
288
289 fn print_debug(&self, message: &str, data: impl std::fmt::Debug, data_type: &str) {
290 if self.debug {
291 if data_type == "hex" {
292 println!("{}: {:X?}", message, data);
293 } else {
294 println!("{}: {:?}", message, data);
295 }
296 }
297 }
298}
299
300pub struct DeviceBuilder {
301 address: Vec<u8>,
302 password: Vec<u8>,
303 uart: Option<Box<dyn SerialPort>>,
304 debug: bool,
305}
306
307impl DeviceBuilder {
308 pub fn new(address: Vec<u8>, password: Vec<u8>) -> Self {
309 Self {
310 address,
311 password,
312 uart: None,
313 debug: false,
314 }
315 }
316
317 pub fn enable_debug(mut self) -> Self {
318 self.debug = true;
319 self
320 }
321
322 pub fn uart_from_port(
323 mut self,
324 port: &str,
325 baud_rate: u32,
326 ) -> io::Result<Self> {
327 let uart = serialport::new(port, baud_rate)
328 .timeout(std::time::Duration::from_millis(1000))
329 .open()?;
330
331 self.uart = Some(uart);
332 Ok(self)
333 }
334
335 pub fn build(self) -> io::Result<Device> {
336 let uart = self.uart.ok_or_else(|| io::Error::new(io::ErrorKind::InvalidInput, "UART not set"))?;
337 Device::new(self.address, self.password, uart, self.debug)
338 }
339}
340
341impl Drop for Device {
342 fn drop(&mut self) {
343 self.uart.flush().unwrap();
344 }
345}