1 /* 2 * Author: Jon Trulson <jtrulson@ics.com> 3 * Copyright (c) 2015 Intel Corporation. 4 * 5 * Thanks to Adafruit for supplying a google translated version of the 6 * Chinese datasheet and some clues in their code. 7 * 8 * Permission is hereby granted, free of charge, to any person obtaining 9 * a copy of this software and associated documentation files (the 10 * "Software"), to deal in the Software without restriction, including 11 * without limitation the rights to use, copy, modify, merge, publish, 12 * distribute, sublicense, and/or sell copies of the Software, and to 13 * permit persons to whom the Software is furnished to do so, subject to 14 * the following conditions: 15 * 16 * The above copyright notice and this permission notice shall be 17 * included in all copies or substantial portions of the Software. 18 * 19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 23 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 24 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 25 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 */ 27 #pragma once 28 29 #include <string> 30 #include <iostream> 31 32 #include <stdint.h> 33 #include <stdlib.h> 34 #include <unistd.h> 35 #include <string.h> 36 #include <fcntl.h> 37 #include <errno.h> 38 #include <termios.h> 39 #include <sys/time.h> 40 #include <sys/select.h> 41 #include <sys/types.h> 42 #include <sys/stat.h> 43 44 #include <mraa/uart.h> 45 46 #define ZFM20_DEFAULT_UART 0 47 48 // protocol start codes 49 #define ZFM20_START1 0xef 50 #define ZFM20_START2 0x01 51 52 #define ZFM20_MAX_PKT_LEN 256 53 54 #define ZFM20_TIMEOUT 5000 // in ms 55 56 #define ZFM20_DEFAULT_PASSWORD 0x00000000 57 #define ZFM20_DEFAULT_ADDRESS 0xffffffff 58 59 60 namespace upm { 61 /** 62 * @brief ZFM-20 Fingerprint Sensor Module library 63 * @defgroup zfm20 libupm-zfm20 64 * @ingroup seeed uart touch 65 */ 66 67 /** 68 * @library zfm20 69 * @sensor zfm20 70 * @comname ZFM-20 Fingerprint Sensor 71 * @altname Grove Fingerprint Sensor 72 * @type touch 73 * @man seeed 74 * @con uart 75 * 76 * @brief API for the ZFM-20 Fingerprint Sensor Module 77 * 78 * This class was tested on the Grove Fingerprint Sensor 79 * Module. It can store up to 163 fingerprints. 80 * 81 * It is connected via a UART at 57,600 baud. 82 * 83 * @image html zfm20.jpg 84 * This example demonstrates how to register and store a new fingerprint 85 * @snippet zfm20-register.cxx Interesting 86 * This example demonstrates reading a fingerprint and locating it in the DB 87 * @snippet zfm20.cxx Interesting 88 */ 89 class ZFM20 { 90 public: 91 92 // commands 93 typedef enum { 94 CMD_GEN_IMAGE = 0x01, 95 CMD_IMG2TZ = 0x02, 96 CMD_MATCH = 0x03, 97 CMD_SEARCH = 0x04, 98 CMD_REGMODEL = 0x05, 99 CMD_STORE = 0x06, 100 CMD_LOAD_TMPL = 0x07, 101 CMD_UPLOAD_TMPL = 0x08, 102 CMD_DOWNLOAD_TMPL = 0x09, 103 CMD_UPLOAD_IMAGE = 0x0a, 104 CMD_DOWNLOAD_IMAGE = 0x0b, 105 CMD_DELETE_TMPL = 0x0c, 106 CMD_EMPTYDB = 0x0d, 107 CMD_SET_SYSPARAMS = 0x0e, 108 CMD_GET_SYSPARAMS = 0x0f, 109 CMD_SET_PASSWORD = 0x12, 110 CMD_VERIFY_PASSWORD = 0x13, 111 CMD_GET_RANDOM_NUMBER = 0x14, 112 CMD_SET_ADDRESS = 0x15, 113 CMD_GET_TMPL_COUNT = 0x1d, 114 CMD_GET_INDEX_TABLE = 0x1f 115 } ZFM20_COMMAND_T; 116 117 // Error response codes 118 typedef enum { 119 ERR_OK = 0x00, 120 ERR_PACKET_RX_ERROR = 0x01, 121 ERR_NO_FINGER = 0x02, 122 ERR_FP_IMAGE_FAILED = 0x03, 123 ERR_FP_TOO_MESSY = 0x06, 124 ERR_FP_IMAGE_FEW_FEATURES = 0x07, 125 ERR_FP_NOMATCH = 0x08, 126 ERR_FP_NOTFOUND = 0x09, 127 ERR_FP_ENROLLMISMATCH = 0x0a, 128 ERR_BAD_LOCATION = 0x0b, 129 ERR_DB_ERROR = 0x0c, 130 ERR_UPLOAD_FEAT_FAILED = 0x0d, 131 ERR_NO_MORE_PACKETS = 0x0e, 132 ERR_UPLOAD_IMG_FAILED = 0x0f, 133 ERR_RM_TMPL_FAILED = 0x10, 134 ERR_EMPTY_DB_FAILED = 0x11, 135 ERR_INVALID_PWD = 0x13, 136 ERR_INVALID_IMAGE = 0x15, 137 ERR_RW_FLASH_ERROR = 0x18, 138 ERR_INVALID_REG = 0x1a, 139 ERR_INVALID_ADDR = 0x20, 140 ERR_NEEDS_PWD = 0x21, 141 // end of module-specific errors 142 ERR_INTERNAL_ERR = 0xff // API internal error 143 } ZFM20_ERRORS_T; 144 145 typedef enum { 146 PKT_COMMAND = 0x01, 147 PKT_DATA = 0x02, 148 PKT_ACK = 0x07, 149 PKT_END_DATA = 0x08 150 } ZFM20_PKTCODES_T; 151 152 /** 153 * ZFM20 constructor 154 * 155 * @param uart Default UART to use (0 or 1) 156 */ 157 ZFM20(int uart); 158 159 /** 160 * ZFM20 destructor 161 */ 162 ~ZFM20(); 163 164 /** 165 * Checks to see if there is data available for reading 166 * 167 * @param millis Number of milliseconds to wait; 0 means no waiting 168 * @return true if there is data available for reading 169 */ 170 bool dataAvailable(unsigned int millis); 171 172 /** 173 * Reads any available data in a user-supplied buffer. Note: the 174 * call blocks until data is available to be read. Use 175 * dataAvailable() to determine whether there is data available 176 * beforehand, to avoid blocking. 177 * 178 * @param buffer Buffer to hold the data read 179 * @param len Length of the buffer 180 * @return Number of bytes read 181 */ 182 int readData(char *buffer, int len); 183 184 /** 185 * Writes the data in the buffer to the device 186 * 187 * @param buffer Buffer to hold the data read 188 * @param len Length of the buffer 189 * @return Number of bytes written 190 */ 191 int writeData(char *buffer, int len); 192 193 /** 194 * Sets up proper tty I/O modes and the baud rate. For this device, 195 * the default baud rate is 57,600 (B57600). 196 * 197 * @param baud Desired baud rate. 198 * @return True if successful 199 */ 200 bool setupTty(speed_t baud=B57600); 201 202 /** 203 * Composes and writes a command packet 204 * 205 * @param pkt Packet 206 * @param len Length of packet 207 * @return Number of bytes written 208 */ 209 int writeCmdPacket(uint8_t *pkt, int len); 210 211 /** 212 * Verifies the packet header and indicates its validity 213 * 214 * @param pkt Packet to check 215 * @param len Length of packet 216 * @return True if the packet is valid, false otherwise 217 */ 218 bool verifyPacket(uint8_t *pkt, int len); 219 220 /** 221 * Returns the number of milliseconds elapsed since initClock() 222 * was last called 223 * 224 * @return Elapsed milliseconds 225 */ 226 uint32_t getMillis(); 227 228 /** 229 * Resets the clock 230 * 231 */ 232 void initClock(); 233 234 /** 235 * Sets the address that should be used to access the module 236 * 237 * @param addr Address to use 238 */ setAddress(uint32_t addr)239 void setAddress(uint32_t addr) { m_address = addr; }; 240 241 /** 242 * Sets the password that should be used to access the module 243 * 244 * @param pw Password to use 245 */ setPassword(uint32_t pw)246 void setPassword(uint32_t pw) { m_password = pw; }; 247 248 /** 249 * Gets the returned data from a request 250 * 251 * @param pkt Buffer to store the returned data 252 * @param len Expected response length; pkt should be at least this 253 * large 254 * @return True if successful 255 */ 256 bool getResponse(uint8_t *pkt, int len); 257 258 /** 259 * Verifies and authenticates to the module. The password used is 260 * the last one set by setPassword(). 261 * 262 * @return True if successful 263 */ 264 bool verifyPassword(); 265 266 /** 267 * Queries the module for the number of stored templates 268 * (fingerprints). 269 * 270 * @return Number of currently stored templates 271 */ 272 int getNumTemplates(); 273 274 /** 275 * Sets a new password for the module. This passowrd is 276 * stored in the module, and is required to access 277 * the module in the future. 278 * 279 * @param pwd New password to set on the module 280 * @return True if successful 281 */ 282 bool setNewPassword(uint32_t pwd); 283 284 /** 285 * Sets a new address for the module. This address is 286 * stored in the module, and is required to access 287 * the module in the future. 288 * 289 * @param addr New address to set on the module 290 * @return True if successful 291 */ 292 bool setNewAddress(uint32_t addr); 293 294 /** 295 * Generates a new fingerprint image (scans a fingerprint) 296 * 297 * @return One of the ZFM20_ERRORS_T values 298 */ 299 uint8_t generateImage(); 300 301 /** 302 * Converts the image in the image buffer (generated by 303 * generateImage()) and stores it in one of the two characteristics 304 * buffers, 1 or 2 305 * 306 * @param slot Characteristics buffer to use; must be 1 or 2 307 * @return One of the ZFM20_ERRORS_T values 308 */ 309 uint8_t image2Tz(int slot); 310 311 /** 312 * Based on the two characteristics buffers (1 & 2), creates a 313 * fingerprint model. Once a model is successfully created, 314 * it can be stored in the module with storeModel(). 315 * 316 * @return One of the ZFM20_ERRORS_T values 317 */ 318 uint8_t createModel(); 319 320 /** 321 * Once a fingerprint model is created, this method can be 322 * used to store it (via one of the characteristics buffers) in a 323 * given location. 324 * 325 * @param slot Characteristics buffer to store the model, 1 or 2 326 * @param id Location to store the model 327 * @return One of the ZFM20_ERRORS_T values 328 */ 329 uint8_t storeModel(int slot, uint16_t id); 330 331 /** 332 * Deletes a stored model 333 * 334 * @param id Location containing the model to delete 335 * @return One of the ZFM20_ERRORS_T values 336 */ 337 uint8_t deleteModel(uint16_t id); 338 339 /** 340 * Deletes the model database (DB) 341 * 342 * @return One of the ZFM20_ERRORS_T values 343 */ 344 uint8_t deleteDB(); 345 346 /** 347 * Searches the fingerprint DB and returns an ID and score, if found 348 * 349 * 350 * @param slot Slot containing a converted image to search for 351 * @param id ID if found, 0 otherwise 352 * @param score Score if found, 0 otherwise 353 * @return One of the ZFM20_ERRORS_T values 354 */ 355 uint8_t search(int slot, uint16_t *id, uint16_t *score); 356 357 /** 358 * Compares the features in characteristics buffers 1 and 2 and 359 * returns a score if they match 360 * 361 * @param score Score 362 * @return One of the ZFM20_ERRORS_T values 363 */ 364 uint8_t match(uint16_t *score); 365 366 367 protected: ttyFd()368 int ttyFd() { return m_ttyFd; }; 369 370 private: 371 mraa_uart_context m_uart; 372 int m_ttyFd; 373 uint32_t m_password; 374 uint32_t m_address; 375 struct timeval m_startTime; 376 }; 377 } 378 379 380