first commit

This commit is contained in:
BotoX 2023-06-06 19:34:45 +02:00
commit 356d7de2cf
29 changed files with 2629 additions and 0 deletions

9
Makefile Normal file
View File

@ -0,0 +1,9 @@
#####################################################################
#### Please don't change this file. Use component.mk instead ####
#####################################################################
ifndef SMING_HOME
$(error SMING_HOME is not set: please configure it as an environment variable)
endif
include $(SMING_HOME)/project.mk

598
app/FingerLogic.cpp Normal file
View File

@ -0,0 +1,598 @@
#include <SmingCore.h>
#include <Crypto/Sha2.h>
#include "utils.h"
#include "main.h"
#include "FingerPrint.h"
#include "FingerLogic.h"
CFingerLogic::CFingerLogic(CMain *pMain)
{
m_pFingerPrint = NULL;
m_State = STATE_INITIAL;
m_Finger = false;
m_Power = false;
m_pMain = pMain;
memset(&m_FingerParams, 0, sizeof(m_FingerParams));
memset(m_aFingerSlots, 0, sizeof(m_aFingerSlots));
m_FingerSlotsAdded = 0;
m_PowerOffTimer.initializeMs(1000, TimerDelegate(&CFingerLogic::PowerOff, this));
}
void CFingerLogic::Init(CFingerPrint *pFingerPrint)
{
m_pFingerPrint = pFingerPrint;
InitFinger();
}
void CFingerLogic::SetState(FingerLogicState state)
{
m_State = state;
if(m_State == STATE_READY || m_State == STATE_ERROR)
m_PowerOffTimer.start(false);
else
{
m_PowerOffTimer.stop();
PowerOn();
}
}
void CFingerLogic::PowerOff()
{
if(!m_Power)
return;
debugf("PowerOff()");
m_Power = false;
Main().FingerEnable(false);
wifi_set_sleep_type(LIGHT_SLEEP_T);
system_soft_wdt_feed();
}
void CFingerLogic::PowerOn()
{
if(m_Power)
return;
debugf("PowerOn()");
m_Power = true;
Main().FingerEnable(true);
wifi_set_sleep_type(MODEM_SLEEP_T);
delayMilliseconds(100);
}
void CFingerLogic::OnFingerInterrupt(bool finger)
{
debugf("OnFingerInterrupt: %s", finger ? "DOWN" : "UP");
m_Finger = finger;
if(finger)
{
if(m_State == STATE_READY)
VerifyFinger();
else if(m_State == STATE_ENROLL_WAITFINGER1 || m_State == STATE_ENROLL_WAITFINGER2)
EnrollFinger_OnFinger();
}
}
bool CFingerLogic::FingerSlot(uint16_t index)
{
if(index > m_FingerSlotsAdded)
return false;
return m_aFingerSlots[index / 8] & (1 << (index % 8));
}
bool CFingerLogic::FingerSlot(uint16_t index, bool value)
{
if(index > m_FingerSlotsAdded)
return false;
if(value)
m_aFingerSlots[index / 8] |= (1 << (index % 8));
else
m_aFingerSlots[index / 8] &= ~(1 << (index % 8));
return true;
}
int CFingerLogic::FirstFreeFingerSlot()
{
for(int i = 0; i < m_FingerSlotsAdded / 8; i++)
{
if(m_aFingerSlots[i] != 0xFF)
{
uint8_t val = m_aFingerSlots[i];
for(int j = 0; j < 8; j++)
{
if(!(val & (1 << j)))
return (i * 8) + j;
}
}
}
return -1;
}
void CFingerLogic::InitFinger()
{
if(m_State > STATE_INIT_VERIFYPASSWORD)
return;
SetState(STATE_INIT_VERIFYPASSWORD);
FingerPrint().AsyncVerifyPassword((VerifyPasswordCallback)InitFinger_OnVerifyPassword, this);
m_Timer.initializeMs(100, TimerDelegate(&CFingerLogic::InitFinger, this)).start();
}
void CFingerLogic::InitFinger_OnVerifyPassword(CFingerLogic *pThis, FingerPrintError error, const char *errorStr)
{
pThis->m_Timer.stop();
debugf("InitFinger_OnVerifyPassword: (%d) %s", error, errorStr);
if(error == ERROR_OK)
{
pThis->SetState(STATE_INIT_READSYSTEMPARAMETERS);
pThis->FingerPrint().AsyncReadSystemParameters((ReadSystemParametersCallback)InitFinger_OnReadSystemParameters, pThis);
}
else
pThis->SetState(STATE_ERROR);
}
void CFingerLogic::InitFinger_OnReadSystemParameters(CFingerLogic *pThis, FingerPrintError error, const char *errorStr, CFingerSystemParameters *param)
{
debugf("InitFinger_OnReadSystemParameters: (%d) %s", error, errorStr);
if(error == ERROR_OK)
{
memcpy(&pThis->m_FingerParams, param, sizeof(CFingerSystemParameters));
debugf("statusRegister: %d", param->statusRegister);
debugf("systemID: %d", param->systemID);
debugf("storageCapacity: %d", param->storageCapacity);
debugf("securityLevel: %d", param->securityLevel);
debugf("deviceAddress: %X", param->deviceAddress);
debugf("packetLength: %d", param->packetLength);
debugf("baudRate: %d", param->baudRate);
pThis->SetState(STATE_INIT_READTEMPLATEMAP);
pThis->FingerPrint().AsyncReadTemplateMap((ReadTemplateMapCallback)InitFinger_OnReadTemplateMap, pThis, 0);
}
else
pThis->SetState(STATE_ERROR);
}
void CFingerLogic::InitFinger_OnReadTemplateMap(CFingerLogic *pThis, FingerPrintError error, const char *errorStr, uint8_t *pData, uint16_t dataLen)
{
debugf("InitFinger_OnReadTemplateMap: (%d) %s (%p, %d)", error, errorStr, pData, dataLen);
if(error == ERROR_OK)
{
memcpy(&pThis->m_aFingerSlots[pThis->m_FingerSlotsAdded/8], pData, dataLen);
pThis->m_FingerSlotsAdded += dataLen * 8;
if(pThis->m_FingerSlotsAdded < pThis->m_FingerParams.storageCapacity)
{
uint8_t page = pThis->m_FingerSlotsAdded / 8 / dataLen;
pThis->FingerPrint().AsyncReadTemplateMap((ReadTemplateMapCallback)InitFinger_OnReadTemplateMap, pThis, page);
}
else
{
pThis->InitFinger_VerifyTemplates();
}
}
}
void CFingerLogic::InitFinger_VerifyTemplates()
{
SetState(STATE_INIT_VERIFYTEMPLATES);
HashMap<uint16_t, CSettings::CFingerPrint> &fingerMap = Main().Settings().m_FingerPrints;
uint16_t fingerCount = fingerMap.count();
// Check consistency (1)
for(uint16_t i = 0; i < fingerCount; i++)
{
uint16_t id = fingerMap.keyAt(i);
if(!FingerSlot(id))
{
SetState(STATE_ERROR);
FingerPrint().EmptyDatabase();
fingerMap.clear();
Main().Settings().Save();
debugf("InitFinger_VerifyTemplates: INCONSITENCY(1) AT SLOT %d !!!", id);
return;
}
}
// Check consistency (2)
for(uint16_t id = 0; id < m_FingerSlotsAdded; id++)
{
if(FingerSlot(id) && !fingerMap.contains(id))
{
SetState(STATE_ERROR);
FingerPrint().EmptyDatabase();
fingerMap.clear();
Main().Settings().Save();
debugf("InitFinger_VerifyTemplates: INCONSITENCY(2) AT SLOT %d !!!", id);
return;
}
}
if(!fingerCount)
{
SetState(STATE_READY);
return;
}
m_iBuffer = 0;
uint16_t position = fingerMap.keyAt(m_iBuffer);
FingerPrint().AsyncLoadTemplate((LoadTemplateCallback)InitFinger_OnLoadTemplate, this, position, 0x01);
}
void CFingerLogic::InitFinger_OnLoadTemplate(CFingerLogic *pThis, FingerPrintError error, const char *errorStr)
{
debugf("InitFinger_OnLoadTemplate: (%d) %s", error, errorStr);
if(error == ERROR_OK)
{
pThis->FingerPrint().AsyncDownloadCharacteristics((DownloadCharacteristicsCallback)InitFinger_OnDownloadCharacteristics, pThis, 0x01);
}
else
pThis->SetState(STATE_ERROR);
}
void CFingerLogic::InitFinger_OnDownloadCharacteristics(CFingerLogic *pThis, FingerPrintError error, const char *errorStr, int8_t *pChar, uint16_t charLen)
{
debugf("InitFinger_OnDownloadCharacteristics: (%d) %s (%p, %d)", error, errorStr, pChar, charLen);
if(error == ERROR_OK)
{
Crypto::Sha256 ctx;
ctx.update(pChar, charLen);
uint8_t *digest = ctx.getHash().data();
const CSettings::CFingerPrint &finger = pThis->Main().Settings().m_FingerPrints.valueAt(pThis->m_iBuffer);
char aHexDigest1[SHA256_SIZE*2+1];
char aHexDigest2[SHA256_SIZE*2+1];
bytes2hex(digest, sizeof(digest), aHexDigest1, sizeof(aHexDigest1));
bytes2hex(finger.m_aDigest, sizeof(finger.m_aDigest), aHexDigest2, sizeof(aHexDigest2));
debugf("Index: %d -> Num: %d \"%s\" (%s ?= %s)", pThis->m_iBuffer, finger.m_FingerNum, finger.m_aLabel, aHexDigest1, aHexDigest2);
if(memcmp(digest, finger.m_aDigest, SHA256_SIZE) != 0)
{
pThis->SetState(STATE_ERROR);
debugf("InitFinger_VerifyTemplates: DIVERGENT DIGEST AT SLOT %d !!!", pThis->m_iBuffer);
return;
}
pThis->m_iBuffer++;
if(pThis->m_iBuffer >= pThis->Main().Settings().m_FingerPrints.count())
{
debugf("InitFinger_VerifyTemplates: DONE! Verified %d templates.", pThis->m_iBuffer);
pThis->SetState(STATE_READY);
return;
}
uint16_t position = pThis->Main().Settings().m_FingerPrints.keyAt(pThis->m_iBuffer);
pThis->FingerPrint().AsyncLoadTemplate((LoadTemplateCallback)InitFinger_OnLoadTemplate, pThis, position, 0x01);
}
else
pThis->SetState(STATE_ERROR);
}
void CFingerLogic::VerifyFinger()
{
if(m_State != STATE_READY)
return;
SetState(STATE_VERIFY_READIMAGE);
FingerPrint().AsyncReadImage((ReadImageCallback)VerifyFinger_OnReadImage, this);
}
void CFingerLogic::VerifyFinger_OnReadImage(CFingerLogic *pThis, FingerPrintError error, const char *errorStr)
{
debugf("VerifyFinger_OnReadImage: (%d) %s", error, errorStr);
if(error == ERROR_OK)
{
pThis->SetState(STATE_VERIFY_CONVERTIMAGE);
pThis->FingerPrint().AsyncConvertImage((ConvertImageCallback)VerifyFinger_OnConvertImage, pThis, 0x01);
}
else
{
pThis->SetState(STATE_READY);
if(pThis->m_Finger)
pThis->VerifyFinger();
}
}
void CFingerLogic::VerifyFinger_OnConvertImage(CFingerLogic *pThis, FingerPrintError error, const char *errorStr)
{
debugf("VerifyFinger_OnConvertImage: (%d) %s", error, errorStr);
if(error == ERROR_OK)
{
pThis->SetState(STATE_VERIFY_SEARCHTEMPLATE);
pThis->FingerPrint().AsyncSearchTemplate((SearchTemplateCallback)VerifyFinger_OnSearchTemplate, pThis, 0x01, 0, pThis->m_FingerParams.storageCapacity);
}
else
{
pThis->SetState(STATE_READY);
if(pThis->m_Finger)
pThis->VerifyFinger();
}
}
void CFingerLogic::VerifyFinger_OnSearchTemplate(CFingerLogic *pThis, FingerPrintError error, const char *errorStr, int16_t position, int16_t score)
{
debugf("VerifyFinger_OnSearchTemplate: (%d) %s (%d, %d)", error, errorStr, position, score);
if(error == ERROR_OK)
{
pThis->m_iBuffer = position;
pThis->SetState(STATE_VERIFY_LOADTEMPLATE);
pThis->FingerPrint().AsyncLoadTemplate((LoadTemplateCallback)VerifyFinger_OnLoadTemplate, pThis, position, 0x01);
}
else
pThis->SetState(STATE_READY);
}
void CFingerLogic::VerifyFinger_OnLoadTemplate(CFingerLogic *pThis, FingerPrintError error, const char *errorStr)
{
debugf("VerifyFinger_OnLoadTemplate: (%d) %s", error, errorStr);
if(error == ERROR_OK)
{
pThis->SetState(STATE_VERIFY_DOWNLOADCHARACTERISTICS);
pThis->FingerPrint().AsyncDownloadCharacteristics((DownloadCharacteristicsCallback)VerifyFinger_OnDownloadCharacteristics, pThis, 0x01);
}
else
pThis->SetState(STATE_READY);
}
void CFingerLogic::VerifyFinger_OnDownloadCharacteristics(CFingerLogic *pThis, FingerPrintError error, const char *errorStr, int8_t *pChar, uint16_t charLen)
{
debugf("VerifyFinger_OnDownloadCharacteristics: (%d) %s (%p, %d)", error, errorStr, pChar, charLen);
if(error == ERROR_OK)
{
Crypto::Sha256 ctx;
ctx.update(pChar, charLen);
uint8_t *digest = ctx.getHash().data();
char aHexDigest[SHA256_SIZE*2+1];
bytes2hex(digest, sizeof(digest), aHexDigest, sizeof(aHexDigest));
debugf("Finger hexdigest: %s", aHexDigest);
pThis->Main().OnFingerVerified(pThis->m_iBuffer, digest);
}
pThis->SetState(STATE_READY);
}
bool CFingerLogic::EnrollFinger(bool cancel)
{
if(cancel)
{
if(m_State < STATE_ENROLL_WAITFINGER1 || m_State > STATE_ENROLL_DOWNLOADCHARACTERISTICS)
return false;
SetState(STATE_READY);
return true;
}
if(m_State != STATE_READY)
return false;
SetState(STATE_ENROLL_WAITFINGER1);
if(m_Finger)
EnrollFinger_OnFinger();
return true;
}
void CFingerLogic::EnrollFinger_OnFinger()
{
if(m_State == STATE_ENROLL_WAITFINGER1)
{
SetState(STATE_ENROLL_READIMAGE1);
FingerPrint().AsyncReadImage((ReadImageCallback)EnrollFinger_OnReadImage1, this);
}
else if(m_State == STATE_ENROLL_WAITFINGER2)
{
SetState(STATE_ENROLL_READIMAGE2);
FingerPrint().AsyncReadImage((ReadImageCallback)EnrollFinger_OnReadImage2, this);
}
}
void CFingerLogic::EnrollFinger_OnReadImage1(CFingerLogic *pThis, FingerPrintError error, const char *errorStr)
{
debugf("EnrollFinger_OnReadImage1: (%d) %s", error, errorStr);
if(pThis->m_State != STATE_ENROLL_READIMAGE1) return;
if(error == ERROR_OK)
{
pThis->SetState(STATE_ENROLL_CONVERTIMAGE1);
pThis->FingerPrint().AsyncConvertImage((ConvertImageCallback)EnrollFinger_OnConvertImage1, pThis, 0x01);
}
else
{
pThis->SetState(STATE_ENROLL_WAITFINGER1);
char aBuf[512];
m_snprintf(aBuf, sizeof(aBuf), "Error while scanning finger: %s<br>Lift your finger and try again.", errorStr);
pThis->Main().EnrollMessage(aBuf);
}
}
void CFingerLogic::EnrollFinger_OnConvertImage1(CFingerLogic *pThis, FingerPrintError error, const char *errorStr)
{
debugf("EnrollFinger_OnConvertImage1: (%d) %s", error, errorStr);
if(pThis->m_State != STATE_ENROLL_CONVERTIMAGE1) return;
if(error == ERROR_OK)
{
pThis->SetState(STATE_ENROLL_SEARCHTEMPLATE);
pThis->FingerPrint().AsyncSearchTemplate((SearchTemplateCallback)EnrollFinger_OnSearchTemplate, pThis, 0x01, 0, pThis->m_FingerParams.storageCapacity);
}
else
{
pThis->SetState(STATE_ENROLL_WAITFINGER1);
char aBuf[512];
m_snprintf(aBuf, sizeof(aBuf), "Error while analyzing finger: %s<br>Lift your finger and try again.", errorStr);
pThis->Main().EnrollMessage(aBuf);
}
}
void CFingerLogic::EnrollFinger_OnSearchTemplate(CFingerLogic *pThis, FingerPrintError error, const char *errorStr, int16_t position, int16_t score)
{
debugf("EnrollFinger_OnSearchTemplate: (%d) %s (%d, %d)", error, errorStr, position, score);
if(pThis->m_State != STATE_ENROLL_SEARCHTEMPLATE) return;
if(error == ERROR_OK)
{
pThis->SetState(STATE_READY);
pThis->Main().EnrollMessage("Aborting: This finger is already enrolled!", true);
}
else
{
pThis->SetState(STATE_ENROLL_WAITFINGER2);
pThis->Main().EnrollMessage("Finger scanned. Lift finger and place it on the sensor again to enroll.");
}
}
void CFingerLogic::EnrollFinger_OnReadImage2(CFingerLogic *pThis, FingerPrintError error, const char *errorStr)
{
debugf("EnrollFinger_OnReadImage2: (%d) %s", error, errorStr);
if(pThis->m_State != STATE_ENROLL_READIMAGE2) return;
if(error == ERROR_OK)
{
pThis->SetState(STATE_ENROLL_CONVERTIMAGE2);
pThis->FingerPrint().AsyncConvertImage((ConvertImageCallback)EnrollFinger_OnConvertImage2, pThis, 0x02);
}
else
{
pThis->SetState(STATE_ENROLL_WAITFINGER2);
char aBuf[512];
m_snprintf(aBuf, sizeof(aBuf), "Error while scanning finger: %s<br>Lift your finger and try again.", errorStr);
pThis->Main().EnrollMessage(aBuf);
}
}
void CFingerLogic::EnrollFinger_OnConvertImage2(CFingerLogic *pThis, FingerPrintError error, const char *errorStr)
{
debugf("EnrollFinger_OnConvertImage2: (%d) %s", error, errorStr);
if(pThis->m_State != STATE_ENROLL_CONVERTIMAGE2) return;
if(error == ERROR_OK)
{
pThis->SetState(STATE_ENROLL_COMPARE);
pThis->FingerPrint().AsyncCompareCharacteristics((CompareCharacteristicsCallback)EnrollFinger_OnCompareCharacteristics, pThis);
}
else
{
pThis->SetState(STATE_ENROLL_WAITFINGER2);
char aBuf[512];
m_snprintf(aBuf, sizeof(aBuf), "Error while analyzing finger: %s<br>Lift your finger and try again.", errorStr);
pThis->Main().EnrollMessage(aBuf);
}
}
void CFingerLogic::EnrollFinger_OnCompareCharacteristics(CFingerLogic *pThis, FingerPrintError error, const char *errorStr, int16_t score)
{
debugf("EnrollFinger_OnCompareCharacteristics: (%d) %s (%d)", error, errorStr, score);
if(pThis->m_State != STATE_ENROLL_COMPARE) return;
if(error == ERROR_OK)
{
pThis->SetState(STATE_ENROLL_CREATETEMPLATE);
pThis->FingerPrint().AsyncCreateTemplate((CreateTemplateCallback)EnrollFinger_OnCreateTemplate, pThis);
}
else
{
pThis->SetState(STATE_ENROLL_WAITFINGER1);
char aBuf[512];
m_snprintf(aBuf, sizeof(aBuf), "Error while comparing fingers: %s<br>Lift your finger and try again.", errorStr);
pThis->Main().EnrollMessage(aBuf);
}
}
void CFingerLogic::EnrollFinger_OnCreateTemplate(CFingerLogic *pThis, FingerPrintError error, const char *errorStr)
{
debugf("EnrollFinger_OnCreateTemplate: (%d) %s", error, errorStr);
if(pThis->m_State != STATE_ENROLL_CREATETEMPLATE) return;
if(error == ERROR_OK)
{
pThis->SetState(STATE_ENROLL_STORETEMPLATE);
pThis->m_iBuffer = pThis->FirstFreeFingerSlot();
pThis->FingerPrint().AsyncStoreTemplate((StoreTemplateCallback)EnrollFinger_OnStoreTemplate, pThis, pThis->m_iBuffer, 0x01);
}
else
{
pThis->SetState(STATE_READY);
}
}
void CFingerLogic::EnrollFinger_OnStoreTemplate(CFingerLogic *pThis, FingerPrintError error, const char *errorStr, uint16_t positionNumber)
{
debugf("EnrollFinger_OnStoreTemplate: (%d) %s (%d)", error, errorStr, positionNumber);
if(pThis->m_State != STATE_ENROLL_STORETEMPLATE) return;
if(error == ERROR_OK)
{
pThis->FingerSlot(positionNumber, true);
pThis->SetState(STATE_ENROLL_LOADTEMPLATE);
pThis->FingerPrint().AsyncLoadTemplate((LoadTemplateCallback)EnrollFinger_OnLoadTemplate, pThis, positionNumber, 0x01);
}
else
{
pThis->SetState(STATE_READY);
}
}
void CFingerLogic::EnrollFinger_OnLoadTemplate(CFingerLogic *pThis, FingerPrintError error, const char *errorStr)
{
debugf("EnrollFinger_OnLoadTemplate: (%d) %s", error, errorStr);
if(pThis->m_State != STATE_ENROLL_LOADTEMPLATE) return;
if(error == ERROR_OK)
{
pThis->SetState(STATE_ENROLL_DOWNLOADCHARACTERISTICS);
pThis->FingerPrint().AsyncDownloadCharacteristics((DownloadCharacteristicsCallback)EnrollFinger_OnDownloadCharacteristics, pThis, 0x01);
}
else
{
pThis->SetState(STATE_READY);
}
}
void CFingerLogic::EnrollFinger_OnDownloadCharacteristics(CFingerLogic *pThis, FingerPrintError error, const char *errorStr, int8_t *pChar, uint16_t charLen)
{
debugf("EnrollFinger_OnDownloadCharacteristics: (%d) %s (%p, %d)", error, errorStr, pChar, charLen);
if(pThis->m_State != STATE_ENROLL_DOWNLOADCHARACTERISTICS) return;
if(error == ERROR_OK)
{
Crypto::Sha256 ctx;
ctx.update(pChar, charLen);
uint8_t *digest = ctx.getHash().data();
Serial1.printf("NEW Finger %d hexdigest: ", pThis->m_iBuffer);
for(uint8_t i = 0; i < sizeof(digest); i++)
Serial1.printf("%x", digest[i]);
Serial1.printf("\n");
pThis->Main().OnFingerEnrolled(pThis->m_iBuffer, digest);
}
pThis->SetState(STATE_READY);
}

105
app/FingerLogic.h Normal file
View File

@ -0,0 +1,105 @@
#ifndef FINGERLOGIC_H
#define FINGERLOGIC_H
#include <bitset>
#include "FingerPrint.h"
enum FingerLogicState
{
STATE_ERROR = -1,
STATE_INITIAL = 0,
STATE_INIT_VERIFYPASSWORD,
STATE_INIT_READSYSTEMPARAMETERS,
STATE_INIT_READTEMPLATEMAP,
STATE_INIT_VERIFYTEMPLATES,
STATE_READY,
STATE_VERIFY_READIMAGE,
STATE_VERIFY_CONVERTIMAGE,
STATE_VERIFY_SEARCHTEMPLATE,
STATE_VERIFY_LOADTEMPLATE,
STATE_VERIFY_DOWNLOADCHARACTERISTICS,
STATE_ENROLL_WAITFINGER1,
STATE_ENROLL_READIMAGE1,
STATE_ENROLL_CONVERTIMAGE1,
STATE_ENROLL_SEARCHTEMPLATE,
STATE_ENROLL_WAITFINGER2,
STATE_ENROLL_READIMAGE2,
STATE_ENROLL_CONVERTIMAGE2,
STATE_ENROLL_COMPARE,
STATE_ENROLL_CREATETEMPLATE,
STATE_ENROLL_STORETEMPLATE,
STATE_ENROLL_LOADTEMPLATE,
STATE_ENROLL_DOWNLOADCHARACTERISTICS
};
class CFingerLogic
{
public:
CFingerLogic(class CMain *pMain);
void Init(CFingerPrint *pFingerPrint);
void OnFingerInterrupt(bool finger);
bool FingerSlot(uint16_t index);
bool FingerSlot(uint16_t index, bool value);
int FirstFreeFingerSlot();
void InitFinger();
static void InitFinger_OnVerifyPassword(CFingerLogic *pThis, FingerPrintError error, const char *errorStr);
static void InitFinger_OnReadSystemParameters(CFingerLogic *pThis, FingerPrintError error, const char *errorStr, CFingerSystemParameters *param);
static void InitFinger_OnGetTemplates(CFingerLogic *pThis, FingerPrintError error, const char *errorStr);
static void InitFinger_OnReadTemplateMap(CFingerLogic *pThis, FingerPrintError error, const char *errorStr, uint8_t *pData, uint16_t dataLen);
void InitFinger_VerifyTemplates();
static void InitFinger_OnLoadTemplate(CFingerLogic *pThis, FingerPrintError error, const char *errorStr);
static void InitFinger_OnDownloadCharacteristics(CFingerLogic *pThis, FingerPrintError error, const char *errorStr, int8_t *pChar, uint16_t charLen);
void VerifyFinger();
static void VerifyFinger_OnReadImage(CFingerLogic *pThis, FingerPrintError error, const char *errorStr);
static void VerifyFinger_OnConvertImage(CFingerLogic *pThis, FingerPrintError error, const char *errorStr);
static void VerifyFinger_OnSearchTemplate(CFingerLogic *pThis, FingerPrintError error, const char *errorStr, int16_t position, int16_t score);
static void VerifyFinger_OnLoadTemplate(CFingerLogic *pThis, FingerPrintError error, const char *errorStr);
static void VerifyFinger_OnDownloadCharacteristics(CFingerLogic *pThis, FingerPrintError error, const char *errorStr, int8_t *pChar, uint16_t charLen);
bool EnrollFinger(bool cancel=false);
static void EnrollFinger_OnReadImage1(CFingerLogic *pThis, FingerPrintError error, const char *errorStr);
static void EnrollFinger_OnConvertImage1(CFingerLogic *pThis, FingerPrintError error, const char *errorStr);
static void EnrollFinger_OnSearchTemplate(CFingerLogic *pThis, FingerPrintError error, const char *errorStr, int16_t position, int16_t score);
void EnrollFinger_OnFinger();
static void EnrollFinger_OnReadImage2(CFingerLogic *pThis, FingerPrintError error, const char *errorStr);
static void EnrollFinger_OnConvertImage2(CFingerLogic *pThis, FingerPrintError error, const char *errorStr);
static void EnrollFinger_OnCompareCharacteristics(CFingerLogic *pThis, FingerPrintError error, const char *errorStr, int16_t score);
static void EnrollFinger_OnCreateTemplate(CFingerLogic *pThis, FingerPrintError error, const char *errorStr);
static void EnrollFinger_OnStoreTemplate(CFingerLogic *pThis, FingerPrintError error, const char *errorStr, uint16_t positionNumber);
static void EnrollFinger_OnLoadTemplate(CFingerLogic *pThis, FingerPrintError error, const char *errorStr);
static void EnrollFinger_OnDownloadCharacteristics(CFingerLogic *pThis, FingerPrintError error, const char *errorStr, int8_t *pChar, uint16_t charLen);
CMain &Main() { return *m_pMain; }
CFingerPrint &FingerPrint() { return *m_pFingerPrint; }
private:
bool m_Power;
void PowerOff();
void PowerOn();
void SetState(FingerLogicState state);
Timer m_PowerOffTimer;
CMain *m_pMain;
CFingerPrint *m_pFingerPrint;
FingerLogicState m_State;
bool m_Finger;
CFingerSystemParameters m_FingerParams;
uint8_t m_aFingerSlots[1792/8];
uint16_t m_FingerSlotsAdded;
int32_t m_iBuffer;
Timer m_Timer;
void *m_fnUserCallback;
void *m_pUserData;
};
#endif

267
app/FingerPrint.cpp Normal file
View File

@ -0,0 +1,267 @@
#include <SmingCore.h>
#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;
}

163
app/FingerPrint.h Normal file
View File

@ -0,0 +1,163 @@
#ifndef FINGERPRINT_H
#define FINGERPRINT_H
// Data package identifier
enum FingerPrintIdent
{
IDENT_COMMAND = 0x01, // Command packet
IDENT_DATA = 0x02, // Data packet;
// Data packet shall not appear alone in executing processs,
// must follow command packet or acknowledge packet.
IDENT_ACK = 0x07, // Acknowledge packet
IDENT_ENDOFDATA = 0x08, // End of Data packet
};
enum FingerPrintCommand
{
COMMAND_GENIMG = 0x01, // Collect finger image
COMMAND_IMG2TZ = 0x02, // To generate character file from image
COMMAND_MATCH = 0x03, // Carry out precise matching of two templates
COMMAND_SEARCH = 0x04, // Search library finger
COMMAND_REGMODEL = 0x05, // To combine character files and generate template
COMMAND_STORE = 0x06, // To store template;
COMMAND_LOADCHAR = 0x07, // to read/load template
COMMAND_UPCHAR = 0x08, // to upload template
COMMAND_DOWNCHR = 0x09, // to download template
COMMAND_UPIMAGE = 0x0A, // To upload image
COMMAND_DOWNIMAGE = 0x0B, // To download image
COMMAND_DELETCHAR = 0x0C, // to delete tempates
COMMAND_EMPTY = 0x0D, // to empty the library
COMMAND_SETSYSPARA = 0x0E, // To set system Parameter
COMMAND_READSYSPARA = 0x0F, // To read Parameter
COMMAND_SETPWD = 0x12, // To set password
COMMAND_VFYPWD = 0x13, // To verify password
COMMAND_GETRANDOMCODE = 0x14, // to get random code
COMMAND_SETADDER = 0x15, // To set device address
COMMAND_CONTROL = 0x17, // Port control
COMMAND_WRITENOTEPAD = 0x18, // to write note pad
COMMAND_READNOTEPAD = 0x19, // To read note pad
COMMAND_HISPEEDSEARCH = 0x1B, // Search the library fastly
COMMAND_TEMPLATENUM = 0x1D, // To read finger template numbers
COMMAND_READCONLIST = 0x1F, // To read finger template index table
};
enum FingerPrintError
{
ERROR_OK = 0x00, // command execution complete
ERROR_COMMUNICATION = 0x01, // error when receiving data package
ERROR_NOFINGER = 0x02, // no finger on the sensor
ERROR_READIMAGE = 0x03, // fail to enroll the finger
ERROR_MESSYIMAGE = 0x06, // fail to generate character file due to the over-disorderly fingerprint image
ERROR_FEWFEATUREPOINTS = 0x07, // fail to generate character file due to lackness of character point or over-smallness of fingerprint image
ERROR_NOTMATCHING = 0x08, // finger doesn't match
ERROR_NOTEMPLATEFOUND = 0x09, // fail to find the matching finger
ERROR_CHARACTERISTICSMISMATCH = 0x0A, // fail to combine the character files
ERROR_INVALIDPOSITION = 0x0B, // addressing PageID is beyond the finger library
ERROR_LOADTEMPLATE = 0x0C, // error when reading template from library or the template is invalid
ERROR_UPLOADTEMPLATE = 0x0D, // error when uploading template
ERROR_PACKETRESPONSEFAIL = 0x0E, // Module can't receive the following data packages
ERROR_UPLOADIMAGE = 0x0F, // error when uploading image
ERROR_DELETETEMPLATE = 0x10, // fail to delete the template
ERROR_CLEARDATABASE = 0x11, // fail to clear finger library
ERROR_WRONGPASSWORD = 0x13, // wrong password
ERROR_INVALIDIMAGE = 0x15, // fail to generate the image for the lackness of valid primary image
ERROR_FLASH = 0x18, // error when writing flash
ERROR_NODEF = 0x19, // No definition error
ERROR_INVALIDREGISTER = 0x1A, // invalid register number
ERROR_INCORRECTREGISTERCONF = 0x1B, // incorrect configuration of register
ERROR_INVALIDNOTEPADPAGE = 0x1C, // wrong notepad page number
ERROR_COMMUNICATIONPORT = 0x1D, // fail to operate the communication port
};
enum RecvStates
{
RECV_DONE = 0,
RECV_WAITING = 1,
RECV_DROP = 2
};
struct CFingerSystemParameters
{
uint16_t statusRegister;
uint16_t systemID;
uint16_t storageCapacity;
uint16_t securityLevel;
uint32_t deviceAddress;
uint16_t packetLength;
uint16_t baudRate;
};
class CFingerPrint;
typedef void (CFingerPrint::*RecvCallback)(FingerPrintIdent ident, uint8_t *pData, uint16_t length);
typedef void (*VerifyPasswordCallback)(void *pUser, FingerPrintError error, const char *errorStr);
typedef void (*ReadSystemParametersCallback)(void *pUser, FingerPrintError error, const char *errorStr, CFingerSystemParameters *param);
typedef void (*ReadImageCallback)(void *pUser, FingerPrintError error, const char *errorStr);
typedef void (*ConvertImageCallback)(void *pUser, FingerPrintError error, const char *errorStr);
typedef void (*SearchTemplateCallback)(void *pUser, FingerPrintError error, const char *errorStr, int16_t position, int16_t score);
typedef void (*CompareCharacteristicsCallback)(void *pUser, FingerPrintError error, const char *errorStr, int16_t score);
typedef void (*CreateTemplateCallback)(void *pUser, FingerPrintError error, const char *errorStr);
typedef void (*DownloadCharacteristicsCallback)(void *pUser, FingerPrintError error, const char *errorStr, int8_t *pChar, uint16_t charLen);
typedef void (*LoadTemplateCallback)(void *pUser, FingerPrintError error, const char *errorStr);
typedef void (*StoreTemplateCallback)(void *pUser, FingerPrintError error, const char *errorStr, uint16_t positionNumber);
typedef void (*ReadTemplateMapCallback)(void *pUser, FingerPrintError error, const char *errorStr, uint8_t *pData, uint16_t dataLen);
class CFingerPrint
{
public:
CFingerPrint();
void Init(HardwareSerial &serial, uint32_t address, uint32_t password);
static const char *ExplainFingerError(uint8_t error);
int VerifyPassword();
int ReadSystemParameters(uint8_t aResponse[17]);
int DeleteTemplate(uint16_t positionStart, uint16_t count);
int EmptyDatabase();
int AsyncVerifyPassword(VerifyPasswordCallback fnCallback, void *pUser);
int AsyncReadSystemParameters(ReadSystemParametersCallback fnCallback, void *pUser);
int AsyncReadImage(ReadImageCallback fnCallback, void *pUser);
int AsyncConvertImage(ConvertImageCallback fnCallback, void *pUser, uint8_t numCharBuffer);
int AsyncSearchTemplate(SearchTemplateCallback fnCallback, void *pUser, uint8_t numCharBuffer, uint16_t positionStart, uint16_t numTemplates);
int AsyncCompareCharacteristics(CompareCharacteristicsCallback fnCallback, void *pUser);
int AsyncCreateTemplate(CreateTemplateCallback fnCallback, void *pUser);
int AsyncDownloadCharacteristics(DownloadCharacteristicsCallback fnCallback, void *pUser, uint8_t numCharBuffer);
int AsyncLoadTemplate(LoadTemplateCallback fnCallback, void *pUser, uint16_t positionNumber, uint8_t numCharBuffer);
int AsyncStoreTemplate(StoreTemplateCallback fnCallback, void *pUser, uint16_t positionNumber, uint8_t numCharBuffer);
int AsyncReadTemplateMap(ReadTemplateMapCallback fnCallback, void *pUser, uint8_t numPage);
private:
void OnAsyncVerifyPassword(FingerPrintIdent ident, uint8_t *pData, uint16_t length);
void OnAsyncReadSystemParameters(FingerPrintIdent ident, uint8_t *pData, uint16_t length);
void OnAsyncReadImage(FingerPrintIdent ident, uint8_t *pData, uint16_t length);
void OnAsyncConvertImage(FingerPrintIdent ident, uint8_t *pData, uint16_t length);
void OnAsyncSearchTemplate(FingerPrintIdent ident, uint8_t *pData, uint16_t length);
void OnAsyncCompareCharacteristics(FingerPrintIdent ident, uint8_t *pData, uint16_t length);
void OnAsyncCreateTemplate(FingerPrintIdent ident, uint8_t *pData, uint16_t length);
void OnAsyncDownloadCharacteristics(FingerPrintIdent ident, uint8_t *pData, uint16_t length);
void OnAsyncLoadTemplate(FingerPrintIdent ident, uint8_t *pData, uint16_t length);
void OnAsyncStoreTemplate(FingerPrintIdent ident, uint8_t *pData, uint16_t length);
void OnAsyncReadTemplateMap(FingerPrintIdent ident, uint8_t *pData, uint16_t length);
void OnData(Stream &stream, char arrivedChar, unsigned short availableCharsCount);
int Write(FingerPrintIdent ident, uint8_t *pData, uint16_t length);
int Recv(FingerPrintIdent *pIdent, uint8_t *pData, uint16_t maxLength, const int maxTime=100);
uint32_t m_Address;
uint32_t m_Password;
HardwareSerial *m_pSerial;
uint8_t m_aRecvBuffer[2+4+1+2+256+2];
uint16_t m_RecvIndex;
volatile RecvStates m_RecvState;
RecvCallback m_fnRecvCallback;
void *m_fnUserCallback;
void *m_pUserData;
uint8_t m_aBuffer[1024];
int32_t m_iBuffer;
};
#endif

101
app/FingerPrint_API.cpp Normal file
View File

@ -0,0 +1,101 @@
#include <SmingCore.h>
#include "FingerPrint.h"
int CFingerPrint::VerifyPassword()
{
uint8_t aPayload[] = {
COMMAND_VFYPWD,
(uint8_t)(m_Password >> 24 & 0xFF),
(uint8_t)(m_Password >> 16 & 0xFF),
(uint8_t)(m_Password >> 8 & 0xFF),
(uint8_t)(m_Password >> 0 & 0xFF),
};
Write(IDENT_COMMAND, aPayload, sizeof(aPayload));
FingerPrintIdent ident;
uint8_t aResponse[1];
int ret = Recv(&ident, aResponse, sizeof(aResponse));
m_RecvState = RECV_DROP;
if(ret < 0)
return ret;
if(ident != IDENT_ACK)
return ERROR_COMMUNICATION;
uint8_t error = aResponse[0];
return error;
}
int CFingerPrint::ReadSystemParameters(uint8_t aResponse[17])
{
uint8_t aPayload[] = {
COMMAND_READSYSPARA,
};
Write(IDENT_COMMAND, aPayload, sizeof(aPayload));
FingerPrintIdent ident;
int ret = Recv(&ident, aResponse, 17);
m_RecvState = RECV_DROP;
if(ret < 0)
return ret;
if(ident != IDENT_ACK)
return ERROR_COMMUNICATION;
uint8_t error = aResponse[0];
return error;
}
int CFingerPrint::DeleteTemplate(uint16_t positionStart, uint16_t count)
{
uint8_t aPayload[] = {
COMMAND_DELETCHAR,
(uint8_t)(positionStart >> 8 & 0xFF),
(uint8_t)(positionStart >> 0 & 0xFF),
(uint8_t)(count >> 8 & 0xFF),
(uint8_t)(count >> 0 & 0xFF),
};
Write(IDENT_COMMAND, aPayload, sizeof(aPayload));
FingerPrintIdent ident;
uint8_t aResponse[1];
int ret = Recv(&ident, aResponse, sizeof(aResponse));
m_RecvState = RECV_DROP;
if(ret < 0)
return ret;
if(ident != IDENT_ACK)
return ERROR_COMMUNICATION;
uint8_t error = aResponse[0];
return error;
}
int CFingerPrint::EmptyDatabase()
{
uint8_t aPayload[] = {
COMMAND_EMPTY,
};
Write(IDENT_COMMAND, aPayload, sizeof(aPayload));
FingerPrintIdent ident;
uint8_t aResponse[1];
int ret = Recv(&ident, aResponse, sizeof(aResponse));
m_RecvState = RECV_DROP;
if(ret < 0)
return ret;
if(ident != IDENT_ACK)
return ERROR_COMMUNICATION;
uint8_t error = aResponse[0];
return error;
}

View File

@ -0,0 +1,510 @@
#include <SmingCore.h>
#include "FingerPrint.h"
int CFingerPrint::AsyncVerifyPassword(VerifyPasswordCallback fnCallback, void *pUser)
{
uint8_t aPayload[] = {
COMMAND_VFYPWD,
(uint8_t)(m_Password >> 24 & 0xFF),
(uint8_t)(m_Password >> 16 & 0xFF),
(uint8_t)(m_Password >> 8 & 0xFF),
(uint8_t)(m_Password >> 0 & 0xFF),
};
m_fnRecvCallback = &CFingerPrint::OnAsyncVerifyPassword;
m_fnUserCallback = (void *)fnCallback;
m_pUserData = pUser;
Write(IDENT_COMMAND, aPayload, sizeof(aPayload));
return 0;
}
void CFingerPrint::OnAsyncVerifyPassword(FingerPrintIdent ident, uint8_t *pData, uint16_t length)
{
m_RecvState = RECV_DROP;
if(ident != IDENT_ACK)
{
((VerifyPasswordCallback)m_fnUserCallback)(m_pUserData, ERROR_COMMUNICATION, "The received packet is no ack packet!");
return;
}
if(length != 1)
{
((VerifyPasswordCallback)m_fnUserCallback)(m_pUserData, ERROR_COMMUNICATION, "Incorrect data length!");
return;
}
uint8_t error = pData[0];
const char *errorStr = ExplainFingerError(error);
((VerifyPasswordCallback)m_fnUserCallback)(m_pUserData, (FingerPrintError)error, errorStr);
}
int CFingerPrint::AsyncReadSystemParameters(ReadSystemParametersCallback fnCallback, void *pUser)
{
uint8_t aPayload[] = {
COMMAND_READSYSPARA,
};
m_fnRecvCallback = &CFingerPrint::OnAsyncReadSystemParameters;
m_fnUserCallback = (void *)fnCallback;
m_pUserData = pUser;
Write(IDENT_COMMAND, aPayload, sizeof(aPayload));
return 0;
}
void CFingerPrint::OnAsyncReadSystemParameters(FingerPrintIdent ident, uint8_t *pData, uint16_t length)
{
m_RecvState = RECV_DROP;
if(ident != IDENT_ACK)
{
((ReadSystemParametersCallback)m_fnUserCallback)(m_pUserData, ERROR_COMMUNICATION, "The received packet is no ack packet!", NULL);
return;
}
if(length != 1 + sizeof(CFingerSystemParameters))
{
((ReadSystemParametersCallback)m_fnUserCallback)(m_pUserData, ERROR_COMMUNICATION, "Incorrect data length!", NULL);
return;
}
uint8_t error = pData[0];
const char *errorStr = ExplainFingerError(error);
CFingerSystemParameters *param = (CFingerSystemParameters *)m_aBuffer;
param->statusRegister = pData[1] << 8 | pData[2];
param->systemID = pData[3] << 8 | pData[4];
param->storageCapacity = pData[5] << 8 | pData[6];
param->securityLevel = pData[7] << 8 | pData[8];
param->deviceAddress = pData[9] << 24 | pData[10] << 16 | pData[11] << 8 | pData[12];
param->packetLength = pData[13] << 8 | pData[14];
param->baudRate = pData[15] << 8 | pData[16];
((ReadSystemParametersCallback)m_fnUserCallback)(m_pUserData, (FingerPrintError)error, errorStr, param);
}
int CFingerPrint::AsyncReadImage(ReadImageCallback fnCallback, void *pUser)
{
uint8_t aPayload[] = {
COMMAND_GENIMG,
};
m_fnRecvCallback = &CFingerPrint::OnAsyncReadImage;
m_fnUserCallback = (void *)fnCallback;
m_pUserData = pUser;
Write(IDENT_COMMAND, aPayload, sizeof(aPayload));
return 0;
}
void CFingerPrint::OnAsyncReadImage(FingerPrintIdent ident, uint8_t *pData, uint16_t length)
{
m_RecvState = RECV_DROP;
if(ident != IDENT_ACK)
{
((ReadImageCallback)m_fnUserCallback)(m_pUserData, ERROR_COMMUNICATION, "The received packet is no ack packet!");
return;
}
if(length != 1)
{
((ReadImageCallback)m_fnUserCallback)(m_pUserData, ERROR_COMMUNICATION, "Incorrect data length!");
return;
}
uint8_t error = pData[0];
const char *errorStr = ExplainFingerError(error);
((ReadImageCallback)m_fnUserCallback)(m_pUserData, (FingerPrintError)error, errorStr);
}
int CFingerPrint::AsyncConvertImage(ConvertImageCallback fnCallback, void *pUser, uint8_t numCharBuffer)
{
if(numCharBuffer != 0x01 && numCharBuffer != 0x02)
return -1;
uint8_t aPayload[] = {
COMMAND_IMG2TZ,
numCharBuffer,
};
m_fnRecvCallback = &CFingerPrint::OnAsyncConvertImage;
m_fnUserCallback = (void *)fnCallback;
m_pUserData = pUser;
Write(IDENT_COMMAND, aPayload, sizeof(aPayload));
return 0;
}
void CFingerPrint::OnAsyncConvertImage(FingerPrintIdent ident, uint8_t *pData, uint16_t length)
{
m_RecvState = RECV_DROP;
if(ident != IDENT_ACK)
{
((ConvertImageCallback)m_fnUserCallback)(m_pUserData, ERROR_COMMUNICATION, "The received packet is no ack packet!");
return;
}
if(length != 1)
{
((ConvertImageCallback)m_fnUserCallback)(m_pUserData, ERROR_COMMUNICATION, "Incorrect data length!");
return;
}
uint8_t error = pData[0];
const char *errorStr = ExplainFingerError(error);
((ConvertImageCallback)m_fnUserCallback)(m_pUserData, (FingerPrintError)error, errorStr);
}
int CFingerPrint::AsyncSearchTemplate(SearchTemplateCallback fnCallback, void *pUser, uint8_t numCharBuffer, uint16_t positionStart, uint16_t numTemplates)
{
if(numCharBuffer != 0x01 && numCharBuffer != 0x02)
return -1;
uint8_t aPayload[] = {
COMMAND_SEARCH,
numCharBuffer,
(uint8_t)(positionStart >> 8 & 0xFF),
(uint8_t)(positionStart >> 0 & 0xFF),
(uint8_t)(numTemplates >> 8 & 0xFF),
(uint8_t)(numTemplates >> 0 & 0xFF),
};
m_fnRecvCallback = &CFingerPrint::OnAsyncSearchTemplate;
m_fnUserCallback = (void *)fnCallback;
m_pUserData = pUser;
Write(IDENT_COMMAND, aPayload, sizeof(aPayload));
return 0;
}
void CFingerPrint::OnAsyncSearchTemplate(FingerPrintIdent ident, uint8_t *pData, uint16_t length)
{
m_RecvState = RECV_DROP;
int16_t position = -1;
int16_t score = -1;
if(ident != IDENT_ACK)
{
((SearchTemplateCallback)m_fnUserCallback)(m_pUserData, ERROR_COMMUNICATION, "The received packet is no ack packet!", position, score);
return;
}
uint8_t error = pData[0];
const char *errorStr = ExplainFingerError(error);
if(error == ERROR_OK)
{
if(length != 5)
{
((SearchTemplateCallback)m_fnUserCallback)(m_pUserData, ERROR_COMMUNICATION, "Incorrect data length!", position, score);
return;
}
position = pData[1] << 8 | pData[2];
score = pData[3] << 8 | pData[4];
}
((SearchTemplateCallback)m_fnUserCallback)(m_pUserData, (FingerPrintError)error, errorStr, position, score);
}
int CFingerPrint::AsyncCompareCharacteristics(CompareCharacteristicsCallback fnCallback, void *pUser)
{
uint8_t aPayload[] = {
COMMAND_MATCH,
};
m_fnRecvCallback = &CFingerPrint::OnAsyncCompareCharacteristics;