fingerprint_sensor/
lib.rs

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}