#include #include "FingerPrint.h" static struct CFingerErrorsExplain { uint8_t error; const char *str; } gs_FingerErrors[] = { {ERROR_OK, "ERROR_OK: command execution complete"}, {ERROR_COMMUNICATION, "ERROR_COMMUNICATION: error when receiving data package"}, {ERROR_NOFINGER, "ERROR_NOFINGER: no finger on the sensor"}, {ERROR_READIMAGE, "ERROR_READIMAGE: fail to enroll the finger"}, {ERROR_MESSYIMAGE, "ERROR_MESSYIMAGE: fail to generate character file due to the over-disorderly fingerprint image"}, {ERROR_FEWFEATUREPOINTS, "ERROR_FEWFEATUREPOINTS: fail to generate character file due to lackness of character point or over-smallness of fingerprint image"}, {ERROR_NOTMATCHING, "ERROR_NOTMATCHING: finger doesn't match"}, {ERROR_NOTEMPLATEFOUND, "ERROR_NOTEMPLATEFOUND: fail to find the matching finger"}, {ERROR_CHARACTERISTICSMISMATCH, "ERROR_CHARACTERISTICSMISMATCH: fail to combine the character files"}, {ERROR_INVALIDPOSITION, "ERROR_INVALIDPOSITION: addressing PageID is beyond the finger library"}, {ERROR_LOADTEMPLATE, "ERROR_LOADTEMPLATE: error when reading template from library or the template is invalid"}, {ERROR_UPLOADTEMPLATE, "ERROR_UPLOADTEMPLATE: error when uploading template"}, {ERROR_PACKETRESPONSEFAIL, "ERROR_PACKETRESPONSEFAIL: Module can't receive the following data packages"}, {ERROR_UPLOADIMAGE, "ERROR_UPLOADIMAGE: error when uploading image"}, {ERROR_DELETETEMPLATE, "ERROR_DELETETEMPLATE: fail to delete the template"}, {ERROR_CLEARDATABASE, "ERROR_CLEARDATABASE: fail to clear finger library"}, {ERROR_WRONGPASSWORD, "ERROR_WRONGPASSWORD: wrong password"}, {ERROR_INVALIDIMAGE, "ERROR_INVALIDIMAGE: fail to generate the image for the lackness of valid primary image"}, {ERROR_FLASH, "ERROR_FLASH: error when writing flash"}, {ERROR_NODEF, "ERROR_NODEF: No definition error"}, {ERROR_INVALIDREGISTER, "ERROR_INVALIDREGISTER: invalid register number"}, {ERROR_INCORRECTREGISTERCONF, "ERROR_INCORRECTREGISTERCONF: incorrect configuration of register"}, {ERROR_INVALIDNOTEPADPAGE, "ERROR_INVALIDNOTEPADPAGE: wrong notepad page number"}, {ERROR_COMMUNICATIONPORT, "ERROR_COMMUNICATIONPORT: fail to operate the communication port"} }; const char *CFingerPrint::ExplainFingerError(uint8_t error) { CFingerErrorsExplain *pFound = NULL; for(int i = 0; i < sizeof(gs_FingerErrors) / sizeof(*gs_FingerErrors); i++) { if(error == gs_FingerErrors[i].error) { pFound = &gs_FingerErrors[i]; break; } } if(pFound) return pFound->str; return "Unknown error."; } CFingerPrint::CFingerPrint() { m_RecvState = RECV_DROP; } void CFingerPrint::Init(HardwareSerial &serial, uint32_t address, uint32_t password) { if(m_pSerial) return; m_pSerial = &serial; m_Address = address; m_Password = password; m_pSerial->onDataReceived(StreamDataReceivedDelegate(&CFingerPrint::OnData, this)); } void CFingerPrint::OnData(Stream &stream, char arrivedChar, unsigned short availableCharsCount) { if(m_RecvState == RECV_DONE) return; if(m_RecvState == RECV_DROP) { while(stream.available()) stream.read(); return; } // RECV_WAITING while(stream.available()) { uint8_t cur = stream.read(); if(m_RecvIndex == 0 && cur != 0xEF || m_RecvIndex == 1 && cur != 0x01) { debugf("skip garbage header at %d: %X", m_RecvIndex, cur); m_RecvIndex = 0; continue; } m_aRecvBuffer[m_RecvIndex++] = cur; // Packet could be complete (the minimal packet size is 12 bytes) if(m_RecvIndex >= 12) { // Check the packet header (redundant) uint16_t header = m_aRecvBuffer[0] << 8 | m_aRecvBuffer[1]; if(header != 0xEF01) { debugf("wrong header: %X", header); m_RecvIndex = 0; continue; } // Calculate packet payload length uint16_t length = m_aRecvBuffer[7] << 8 | m_aRecvBuffer[8]; // Check if the packet is still fully received // Condition: index counter < packet payload length + packet frame if(m_RecvIndex < length + 9) continue; // At this point the packet should be fully received uint8_t ident = m_aRecvBuffer[6]; // Calculate checksum: // Checksum = packet type (1 byte) + packet length RAW!! (2 bytes) + packet payload (n bytes) uint16_t calcChecksum = ident; const uint16_t tmp = 7 + length; for(uint16_t i = 7; i < tmp; i++) calcChecksum += m_aRecvBuffer[i]; // Checksum in received data package uint16_t recvChecksum = m_aRecvBuffer[m_RecvIndex - 2] << 8 | m_aRecvBuffer[m_RecvIndex - 1]; if(calcChecksum != recvChecksum) { debugf("checksum!!: %X != %X", calcChecksum, recvChecksum); m_RecvIndex = 0; continue; } m_RecvIndex = 0; m_RecvState = RECV_DONE; (this->*m_fnRecvCallback)((FingerPrintIdent)ident, &m_aRecvBuffer[9], length - 2); } } } int CFingerPrint::Recv(FingerPrintIdent *pIdent, uint8_t *pData, uint16_t maxLength, const int maxTime) { m_RecvState = RECV_DONE; m_RecvIndex = 0; debugf("Start manual recv:"); int Ret = -9999; int timeout = maxTime; while(true) { while(!m_pSerial->available()) { if(--timeout == 0) return Ret; delay(1); } uint8_t cur = m_pSerial->read(); m_aRecvBuffer[m_RecvIndex++] = cur; // Packet could be complete (the minimal packet size is 12 bytes) if(m_RecvIndex >= 12) { // Check the packet header uint16_t header = m_aRecvBuffer[0] << 8 | m_aRecvBuffer[1]; if(header != 0xEF01) { debugf("wrong header: %X", header); m_RecvIndex = 0; return Ret; } // Calculate packet payload length uint16_t length = m_aRecvBuffer[7] << 8 | m_aRecvBuffer[8]; // Check if the packet is still fully received // Condition: index counter < packet payload length + packet frame if(m_RecvIndex < length + 9) continue; // At this point the packet should be fully received uint8_t ident = m_aRecvBuffer[6]; // Calculate checksum: // Checksum = packet type (1 byte) + packet length RAW! (2 bytes) + packet payload (n bytes) uint16_t calcChecksum = ident + length; uint16_t tmp = 9 + length - 2; for(uint16_t i = 9; i < tmp; i++) calcChecksum += m_aRecvBuffer[i]; // Checksum in received data package uint16_t recvChecksum = m_aRecvBuffer[m_RecvIndex - 2] << 8 | m_aRecvBuffer[m_RecvIndex - 1]; if(calcChecksum != recvChecksum) { debugf("checksum!!: %X != %X", calcChecksum, recvChecksum); m_RecvIndex = 0; return Ret; } length -= 2; Ret = 0; if(pIdent) *(uint8_t *)pIdent = ident; if(pData) { memcpy(pData, &m_aRecvBuffer[9], min(length, maxLength)); Ret = (int)maxLength - length; // >= 0 = OK } break; } } debugf("End recv. (%dms)", maxTime - timeout); m_RecvIndex = 0; return Ret; } int CFingerPrint::Write(FingerPrintIdent ident, uint8_t *pData, uint16_t length) { m_RecvState = RECV_WAITING; // Header const uint16_t Header = 0xEF01; m_pSerial->write(Header >> 8 & 0xFF); m_pSerial->write(Header >> 0 & 0xFF); // Address m_pSerial->write(m_Address >> 24 & 0xFF); m_pSerial->write(m_Address >> 16 & 0xFF); m_pSerial->write(m_Address >> 8 & 0xFF); m_pSerial->write(m_Address >> 0 & 0xFF); // Package identifier m_pSerial->write(ident); // Package length length += 2; // Checksum m_pSerial->write(length >> 8 & 0xFF); m_pSerial->write(length >> 0 & 0xFF); // Checksum uint16_t Checksum = ident + length; // Data length -= 2; for(uint16_t i = 0; i < length; i++) { m_pSerial->write(pData[i]); Checksum += pData[i]; } // Checksum m_pSerial->write(Checksum >> 8 & 0xFF); m_pSerial->write(Checksum >> 0 & 0xFF); return length; }