Skip to content

Commit

Permalink
Add mgos_fingerprint_svc_init() with event handler callback
Browse files Browse the repository at this point in the history
  • Loading branch information
pimvanpelt committed Dec 24, 2019
1 parent 9501afd commit 51e87d1
Show file tree
Hide file tree
Showing 4 changed files with 269 additions and 8 deletions.
30 changes: 29 additions & 1 deletion include/mgos_fingerprint.h
Original file line number Diff line number Diff line change
Expand Up @@ -125,15 +125,37 @@ struct __attribute__((packed)) mgos_fingerprint_info {
uint16_t model_capacity;
};

struct mgos_fingerprint;
typedef void (*mgos_fingerprint_ev_handler)(struct mgos_fingerprint *finger,
int ev, void *ev_data,
void *user_data);

#define MGOS_FINGERPRINT_MODE_MATCH 0x01 // Search/DB mode
#define MGOS_FINGERPRINT_MODE_ENROLL 0x02 // Enroll mode

#define MGOS_FINGERPRINT_EV_NONE 0x0000
#define MGOS_FINGERPRINT_EV_INITIALIZED 0x0001
#define MGOS_FINGERPRINT_EV_IMAGE 0x0002
#define MGOS_FINGERPRINT_EV_MATCH_OK 0x0003
#define MGOS_FINGERPRINT_EV_MATCH_ERROR 0x0004
#define MGOS_FINGERPRINT_EV_STATE_MATCH 0x0005
#define MGOS_FINGERPRINT_EV_STATE_ENROLL1 0x0006
#define MGOS_FINGERPRINT_EV_STATE_ENROLL2 0x0007
#define MGOS_FINGERPRINT_EV_ENROLL_OK 0x0008
#define MGOS_FINGERPRINT_EV_ENROLL_ERROR 0x0009

struct mgos_fingerprint_cfg {
uint32_t password;
uint32_t address;
uint8_t uart_no;
uint32_t uart_baud_rate;

// User callback event handler
mgos_fingerprint_ev_handler handler;
void *handler_user_data;
};

// Structural
struct mgos_fingerprint;
void mgos_fingerprint_config_set_defaults(struct mgos_fingerprint_cfg *cfg);
struct mgos_fingerprint *mgos_fingerprint_create(
struct mgos_fingerprint_cfg *cfg);
Expand Down Expand Up @@ -199,7 +221,13 @@ int16_t mgos_fingerprint_verify_password(struct mgos_fingerprint *dev);
int16_t mgos_fingerprint_set_password(struct mgos_fingerprint *dev,
uint32_t pwd);

// Library service
bool mgos_fingerprint_init(void);
bool mgos_fingerprint_svc_init(struct mgos_fingerprint *finger,
uint16_t period_ms);
bool mgos_fingerprint_svc_mode_set(struct mgos_fingerprint *finger, int mode);
bool mgos_fingerprint_svc_mode_get(struct mgos_fingerprint *finger, int *mode);

#ifdef __cplusplus
}
#endif
15 changes: 15 additions & 0 deletions src/mgos_fingerprint.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,21 @@
#include "mgos.h"
#include "mgos_fingerprint_internal.h"

static void write_packet(struct mgos_fingerprint *dev, uint8_t packettype,
uint16_t datalen);
static int16_t read_packet(struct mgos_fingerprint *dev);
static int16_t mgos_fingerprint_txn(struct mgos_fingerprint *dev);
static int16_t mgos_fingerprint_get_free_page_id(struct mgos_fingerprint *dev,
uint8_t page, int16_t *id);

void mgos_fingerprint_config_set_defaults(struct mgos_fingerprint_cfg *cfg) {
if (!cfg) return;
cfg->address = MGOS_FINGERPRINT_DEFAULT_ADDRESS;
cfg->password = MGOS_FINGERPRINT_DEFAULT_PASSWORD;
cfg->uart_no = 2;
cfg->uart_baud_rate = 57600;
cfg->handler = NULL;
cfg->handler_user_data = NULL;
}

struct mgos_fingerprint *mgos_fingerprint_create(
Expand All @@ -40,6 +49,8 @@ struct mgos_fingerprint *mgos_fingerprint_create(
dev->address = cfg->address;
dev->password = cfg->password;
dev->uart_no = cfg->uart_no;
dev->handler = cfg->handler;
dev->handler_user_data = cfg->handler_user_data;

// Initialize UART
mgos_uart_config_set_defaults(dev->uart_no, &ucfg);
Expand Down Expand Up @@ -70,6 +81,10 @@ struct mgos_fingerprint *mgos_fingerprint_create(
dev->info.sensor_width, dev->info.sensor_height,
dev->info.model_capacity, num_models));

if (dev->handler)
dev->handler(dev, MGOS_FINGERPRINT_EV_INITIALIZED, NULL,
dev->handler_user_data);

return dev;
err:
if (dev) free(dev);
Expand Down
20 changes: 13 additions & 7 deletions src/mgos_fingerprint_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,12 @@ extern "C" {
#define MGOS_FINGERPRINT_DEFAULT_TIMEOUT 2000
#define MGOS_FINGERPRINT_TEMPLATES_PER_PAGE 256

// Service
#define MGOS_FINGERPRINT_STATE_NONE 0x00
#define MGOS_FINGERPRINT_STATE_MATCH 0x01 // Search/DB mode
#define MGOS_FINGERPRINT_STATE_ENROLL1 0x02 // Enroll mode: First fingerprint
#define MGOS_FINGERPRINT_STATE_ENROLL2 0x03 // Enroll mode: Second fingerprint

struct mgos_fingerprint_packet {
uint16_t startcode __attribute__((packed));
uint32_t address __attribute__((packed));
Expand All @@ -80,15 +86,15 @@ struct mgos_fingerprint {
struct mgos_fingerprint_system_params system_params;
struct mgos_fingerprint_info info;
struct mgos_fingerprint_packet packet;
};

static void write_packet(struct mgos_fingerprint *dev, uint8_t packettype,
uint16_t datalen);
static int16_t read_packet(struct mgos_fingerprint *dev);
static int16_t mgos_fingerprint_txn(struct mgos_fingerprint *dev);
mgos_fingerprint_ev_handler handler;
void *handler_user_data;

static int16_t mgos_fingerprint_get_free_page_id(struct mgos_fingerprint *dev,
uint8_t page, int16_t *id);
// Service
uint8_t svc_state;
int svc_timer_id;
uint16_t svc_period_ms;
};

#ifdef __cplusplus
}
Expand Down
212 changes: 212 additions & 0 deletions src/mgos_fingerprint_svc.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,212 @@
/*
* Copyright 2019 Pim van Pelt <pim@ipng.nl>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#include "mgos.h"
#include "mgos_fingerprint_internal.h"

static void mgos_fingerprint_svc_match(struct mgos_fingerprint *finger) {
int16_t p;
if (!finger) return;

p = mgos_fingerprint_image_genchar(finger, 1);
if (p != MGOS_FINGERPRINT_OK) {
LOG(LL_ERROR, ("Error image_genchar(): %d!", p));
goto out;
}

uint16_t fid = -1, score = 0;
p = mgos_fingerprint_database_search(finger, &fid, &score, 1);
switch (p) {
case MGOS_FINGERPRINT_OK:
LOG(LL_INFO, ("Fingerprint match: fid=%d score=%d", fid, score));
break;
case MGOS_FINGERPRINT_NOTFOUND:
LOG(LL_INFO, ("Fingerprint not found"));
break;
default:
LOG(LL_ERROR, ("Error database_search(): %d!", p));
}

out:
if (p == MGOS_FINGERPRINT_OK) {
if (finger->handler)
finger->handler(finger, MGOS_FINGERPRINT_EV_MATCH_OK, NULL,
finger->handler_user_data);
} else {
if (finger->handler)
finger->handler(finger, MGOS_FINGERPRINT_EV_MATCH_ERROR, NULL,
finger->handler_user_data);
}
}

static void mgos_fingerprint_svc_enroll(struct mgos_fingerprint *finger) {
if (!finger) return;
int16_t p;

switch (finger->svc_state) {
case MGOS_FINGERPRINT_STATE_ENROLL1:
if (MGOS_FINGERPRINT_OK !=
(p = mgos_fingerprint_image_genchar(finger, 1))) {
LOG(LL_ERROR, ("Could not generate first image"));
goto err;
}
LOG(LL_INFO, ("Stored first fingerprint: Remove finger"));

while (p != MGOS_FINGERPRINT_NOFINGER) {
p = mgos_fingerprint_image_get(finger);
usleep(50000);
}

finger->svc_state = MGOS_FINGERPRINT_STATE_ENROLL2;
if (finger->handler)
finger->handler(finger, MGOS_FINGERPRINT_EV_STATE_ENROLL2, NULL,
finger->handler_user_data);

return;

break;
case MGOS_FINGERPRINT_STATE_ENROLL2: {
int16_t fid;

if (MGOS_FINGERPRINT_OK != mgos_fingerprint_image_genchar(finger, 2)) {
LOG(LL_ERROR, ("Could not generate second fingerprint"));
goto err;
}
LOG(LL_INFO, ("Stored second fingerprint"));

if (MGOS_FINGERPRINT_OK != mgos_fingerprint_model_combine(finger)) {
LOG(LL_ERROR, ("Could not combine fingerprints into a model"));
goto err;
}
LOG(LL_INFO, ("Fingerprints combined successfully"));

if (MGOS_FINGERPRINT_OK != mgos_fingerprint_get_free_id(finger, &fid)) {
LOG(LL_ERROR, ("Could not get free flash slot"));
goto err;
}

if (MGOS_FINGERPRINT_OK != mgos_fingerprint_model_store(finger, fid, 1)) {
LOG(LL_ERROR, ("Could not store model in flash slot %u", fid));
goto err;
}
LOG(LL_INFO, ("Model stored in flash slot %d", fid));
if (finger->handler)
finger->handler(finger, MGOS_FINGERPRINT_EV_ENROLL_OK, NULL,
finger->handler_user_data);

finger->svc_state = MGOS_FINGERPRINT_STATE_MATCH;
if (finger->handler)
finger->handler(finger, MGOS_FINGERPRINT_EV_STATE_MATCH, NULL,
finger->handler_user_data);
return;
}
}

// Bail with error, and return to enroll mode.
err:
if (finger->handler)
finger->handler(finger, MGOS_FINGERPRINT_EV_ENROLL_ERROR, NULL,
finger->handler_user_data);

LOG(LL_ERROR, ("Error, returning to enroll mode"));
finger->svc_state = MGOS_FINGERPRINT_STATE_ENROLL1;

if (finger->handler)
finger->handler(finger, MGOS_FINGERPRINT_EV_STATE_ENROLL1, NULL,
finger->handler_user_data);
}

static void mgos_fingerprint_svc_timer(void *arg) {
struct mgos_fingerprint *finger = (struct mgos_fingerprint *) arg;

if (!finger) return;

int16_t p = mgos_fingerprint_image_get(finger);
if (p == MGOS_FINGERPRINT_NOFINGER) {
return;
}
if (p != MGOS_FINGERPRINT_OK) {
LOG(LL_ERROR, ("image_get() error: %d", p));
return;
}

LOG(LL_INFO,
("Fingerprint image taken (%s mode)",
finger->svc_state == MGOS_FINGERPRINT_STATE_MATCH ? "match" : "enroll"));

if (finger->handler)
finger->handler(finger, MGOS_FINGERPRINT_EV_IMAGE, NULL,
finger->handler_user_data);

switch (finger->svc_state) {
case MGOS_FINGERPRINT_STATE_ENROLL1:
case MGOS_FINGERPRINT_STATE_ENROLL2:
mgos_fingerprint_svc_enroll(finger);
return;
break;
default:
break;
}
mgos_fingerprint_svc_match(finger);
return;
}

bool mgos_fingerprint_svc_init(struct mgos_fingerprint *finger,
uint16_t period_ms) {
if (!finger) return false;

if (finger->svc_timer_id > 0) {
// Clean up
LOG(LL_ERROR, ("Service already initialized, bailing"));
return false;
}
finger->svc_period_ms = period_ms;
finger->svc_timer_id = mgos_set_timer(finger->svc_period_ms, true,
mgos_fingerprint_svc_timer, finger);

LOG(LL_INFO, ("Service initialized, period=%ums", finger->svc_period_ms));
return mgos_fingerprint_svc_mode_set(finger, MGOS_FINGERPRINT_MODE_MATCH);
}

bool mgos_fingerprint_svc_mode_set(struct mgos_fingerprint *finger, int mode) {
if (!finger) return false;
if (mode == MGOS_FINGERPRINT_MODE_ENROLL) {
finger->svc_state = MGOS_FINGERPRINT_STATE_ENROLL1;
if (finger->handler)
finger->handler(finger, MGOS_FINGERPRINT_EV_STATE_ENROLL1, NULL,
finger->handler_user_data);
return true;
}
finger->svc_state = MGOS_FINGERPRINT_STATE_MATCH;
if (finger->handler)
finger->handler(finger, MGOS_FINGERPRINT_EV_STATE_MATCH, NULL,
finger->handler_user_data);
return true;
}

bool mgos_fingerprint_svc_mode_get(struct mgos_fingerprint *finger, int *mode) {
if (!finger || !mode) return false;
if (finger->svc_state == MGOS_FINGERPRINT_STATE_MATCH)
*mode = MGOS_FINGERPRINT_MODE_MATCH;
else
*mode = MGOS_FINGERPRINT_MODE_ENROLL;
return true;
}

0 comments on commit 51e87d1

Please sign in to comment.