Port imaging layer to asynchronous model
This commit is contained in:
parent
aeeec97fb2
commit
3048b37176
5 changed files with 393 additions and 198 deletions
|
@ -798,7 +798,9 @@ API_EXPORTED int fp_dev_img_capture(struct fp_dev *dev, int unconditional,
|
||||||
return -ENOTSUP;
|
return -ENOTSUP;
|
||||||
}
|
}
|
||||||
|
|
||||||
return fpi_imgdev_capture(imgdev, unconditional, image);
|
//return fpi_imgdev_capture(imgdev, unconditional, image);
|
||||||
|
/* FIXME reimplement async */
|
||||||
|
return -ENOTSUP;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** \ingroup dev
|
/** \ingroup dev
|
||||||
|
|
|
@ -67,6 +67,7 @@ int fpi_drv_enroll_start(struct fp_dev *dev, fp_enroll_stage_cb callback)
|
||||||
{
|
{
|
||||||
struct fp_driver *drv = dev->drv;
|
struct fp_driver *drv = dev->drv;
|
||||||
int r;
|
int r;
|
||||||
|
fp_dbg("");
|
||||||
if (!drv->enroll_start)
|
if (!drv->enroll_start)
|
||||||
return -ENOTSUP;
|
return -ENOTSUP;
|
||||||
dev->state = DEV_STATE_ENROLL_STARTING;
|
dev->state = DEV_STATE_ENROLL_STARTING;
|
||||||
|
@ -108,6 +109,7 @@ void fpi_drvcb_enroll_stage_completed(struct fp_dev *dev, int result,
|
||||||
int fpi_drv_enroll_stop(struct fp_dev *dev)
|
int fpi_drv_enroll_stop(struct fp_dev *dev)
|
||||||
{
|
{
|
||||||
struct fp_driver *drv = dev->drv;
|
struct fp_driver *drv = dev->drv;
|
||||||
|
fp_dbg("");
|
||||||
dev->enroll_cb = NULL;
|
dev->enroll_cb = NULL;
|
||||||
|
|
||||||
if (!drv->enroll_start)
|
if (!drv->enroll_start)
|
||||||
|
@ -328,7 +330,7 @@ struct fpi_ssm *fpi_ssm_new(struct fp_dev *dev, ssm_handler_fn handler,
|
||||||
int nr_states)
|
int nr_states)
|
||||||
{
|
{
|
||||||
struct fpi_ssm *machine;
|
struct fpi_ssm *machine;
|
||||||
BUG_ON(nr_states < 1)
|
BUG_ON(nr_states < 1);
|
||||||
|
|
||||||
machine = g_malloc0(sizeof(*machine));
|
machine = g_malloc0(sizeof(*machine));
|
||||||
machine->handler = handler;
|
machine->handler = handler;
|
||||||
|
|
|
@ -62,13 +62,15 @@ void fpi_log(enum fpi_log_level, const char *component, const char *function,
|
||||||
#define fp_warn(fmt...) _fpi_log(LOG_LEVEL_WARNING, fmt)
|
#define fp_warn(fmt...) _fpi_log(LOG_LEVEL_WARNING, fmt)
|
||||||
#define fp_err(fmt...) _fpi_log(LOG_LEVEL_ERROR, fmt)
|
#define fp_err(fmt...) _fpi_log(LOG_LEVEL_ERROR, fmt)
|
||||||
|
|
||||||
#ifdef NDEBUG
|
#ifndef NDEBUG
|
||||||
#define BUG_ON(condition) \
|
#define BUG_ON(condition) \
|
||||||
if ((condition)) fp_err("BUG at %s:%d", __FILE__, __LINE__)
|
if ((condition)) fp_err("BUG at %s:%d", __FILE__, __LINE__)
|
||||||
#else
|
#else
|
||||||
#define BUG_ON(condition)
|
#define BUG_ON(condition)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define BUG() BUG_ON(1)
|
||||||
|
|
||||||
enum fp_dev_state {
|
enum fp_dev_state {
|
||||||
DEV_STATE_INITIAL = 0,
|
DEV_STATE_INITIAL = 0,
|
||||||
DEV_STATE_ERROR,
|
DEV_STATE_ERROR,
|
||||||
|
@ -123,9 +125,48 @@ struct fp_dev {
|
||||||
fp_identify_cb identify_cb;
|
fp_identify_cb identify_cb;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum fp_imgdev_state {
|
||||||
|
IMGDEV_STATE_INACTIVE,
|
||||||
|
IMGDEV_STATE_AWAIT_FINGER_ON,
|
||||||
|
IMGDEV_STATE_CAPTURE,
|
||||||
|
IMGDEV_STATE_AWAIT_FINGER_OFF,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum fp_imgdev_action {
|
||||||
|
IMG_ACTION_NONE = 0,
|
||||||
|
IMG_ACTION_ENROLL,
|
||||||
|
IMG_ACTION_VERIFY,
|
||||||
|
IMG_ACTION_IDENTIFY,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum fp_imgdev_enroll_state {
|
||||||
|
IMG_ACQUIRE_STATE_NONE = 0,
|
||||||
|
IMG_ACQUIRE_STATE_ACTIVATING,
|
||||||
|
IMG_ACQUIRE_STATE_AWAIT_FINGER_ON,
|
||||||
|
IMG_ACQUIRE_STATE_AWAIT_IMAGE,
|
||||||
|
IMG_ACQUIRE_STATE_AWAIT_FINGER_OFF,
|
||||||
|
IMG_ACQUIRE_STATE_DONE,
|
||||||
|
IMG_ACQUIRE_STATE_DEACTIVATING,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum fp_imgdev_verify_state {
|
||||||
|
IMG_VERIFY_STATE_NONE = 0,
|
||||||
|
IMG_VERIFY_STATE_ACTIVATING
|
||||||
|
};
|
||||||
|
|
||||||
struct fp_img_dev {
|
struct fp_img_dev {
|
||||||
struct fp_dev *dev;
|
struct fp_dev *dev;
|
||||||
libusb_dev_handle *udev;
|
libusb_dev_handle *udev;
|
||||||
|
enum fp_imgdev_action action;
|
||||||
|
int action_state;
|
||||||
|
|
||||||
|
struct fp_print_data *acquire_data;
|
||||||
|
struct fp_img *acquire_img;
|
||||||
|
int action_result;
|
||||||
|
|
||||||
|
/* FIXME: better place to put this? */
|
||||||
|
size_t identify_match_offset;
|
||||||
|
|
||||||
void *priv;
|
void *priv;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -181,11 +222,10 @@ struct fp_img_driver {
|
||||||
|
|
||||||
/* Device operations */
|
/* Device operations */
|
||||||
int (*init)(struct fp_img_dev *dev, unsigned long driver_data);
|
int (*init)(struct fp_img_dev *dev, unsigned long driver_data);
|
||||||
void (*exit)(struct fp_img_dev *dev);
|
void (*deinit)(struct fp_img_dev *dev);
|
||||||
int (*await_finger_on)(struct fp_img_dev *dev);
|
int (*activate)(struct fp_img_dev *dev, enum fp_imgdev_state state);
|
||||||
int (*await_finger_off)(struct fp_img_dev *dev);
|
int (*change_state)(struct fp_img_dev *dev, enum fp_imgdev_state state);
|
||||||
int (*capture)(struct fp_img_dev *dev, gboolean unconditional,
|
void (*deactivate)(struct fp_img_dev *dev);
|
||||||
struct fp_img **image);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
extern struct fp_driver upekts_driver;
|
extern struct fp_driver upekts_driver;
|
||||||
|
@ -277,7 +317,7 @@ int fpi_img_to_print_data(struct fp_img_dev *imgdev, struct fp_img *img,
|
||||||
int fpi_img_compare_print_data(struct fp_print_data *enrolled_print,
|
int fpi_img_compare_print_data(struct fp_print_data *enrolled_print,
|
||||||
struct fp_print_data *new_print);
|
struct fp_print_data *new_print);
|
||||||
int fpi_img_compare_print_data_to_gallery(struct fp_print_data *print,
|
int fpi_img_compare_print_data_to_gallery(struct fp_print_data *print,
|
||||||
struct fp_print_data **gallery, int match_threshold, int *match_offset);
|
struct fp_print_data **gallery, int match_threshold, size_t *match_offset);
|
||||||
|
|
||||||
/* async drv <--> lib comms */
|
/* async drv <--> lib comms */
|
||||||
|
|
||||||
|
@ -340,5 +380,15 @@ void fpi_drvcb_report_identify_result(struct fp_dev *dev, int result,
|
||||||
int fpi_drv_identify_stop(struct fp_dev *dev);
|
int fpi_drv_identify_stop(struct fp_dev *dev);
|
||||||
void fpi_drvcb_identify_stopped(struct fp_dev *dev);
|
void fpi_drvcb_identify_stopped(struct fp_dev *dev);
|
||||||
|
|
||||||
|
/* for image drivers */
|
||||||
|
void fpi_imgdev_init_complete(struct fp_img_dev *imgdev, int status);
|
||||||
|
void fpi_imgdev_deinit_complete(struct fp_img_dev *imgdev);
|
||||||
|
void fpi_imgdev_activate_complete(struct fp_img_dev *imgdev, int status);
|
||||||
|
void fpi_imgdev_deactivate_complete(struct fp_img_dev *imgdev);
|
||||||
|
void fpi_imgdev_report_finger_status(struct fp_img_dev *imgdev,
|
||||||
|
gboolean present);
|
||||||
|
void fpi_imgdev_image_captured(struct fp_img_dev *imgdev, struct fp_img *img);
|
||||||
|
void fpi_imgdev_session_error(struct fp_img_dev *imgdev, int error);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -334,7 +334,7 @@ int fpi_img_to_print_data(struct fp_img_dev *imgdev, struct fp_img *img,
|
||||||
|
|
||||||
/* FIXME: the print buffer at this point is endian-specific, and will
|
/* FIXME: the print buffer at this point is endian-specific, and will
|
||||||
* only work when loaded onto machines with identical endianness. not good!
|
* only work when loaded onto machines with identical endianness. not good!
|
||||||
* data format should be platform-independant. */
|
* data format should be platform-independent. */
|
||||||
*ret = print;
|
*ret = print;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -365,7 +365,7 @@ int fpi_img_compare_print_data(struct fp_print_data *enrolled_print,
|
||||||
}
|
}
|
||||||
|
|
||||||
int fpi_img_compare_print_data_to_gallery(struct fp_print_data *print,
|
int fpi_img_compare_print_data_to_gallery(struct fp_print_data *print,
|
||||||
struct fp_print_data **gallery, int match_threshold, int *match_offset)
|
struct fp_print_data **gallery, int match_threshold, size_t *match_offset)
|
||||||
{
|
{
|
||||||
struct xyt_struct *pstruct = (struct xyt_struct *) print->data;
|
struct xyt_struct *pstruct = (struct xyt_struct *) print->data;
|
||||||
struct fp_print_data *gallery_print;
|
struct fp_print_data *gallery_print;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Core imaging device functions for libfprint
|
* Core imaging device functions for libfprint
|
||||||
* Copyright (C) 2007 Daniel Drake <dsd@gentoo.org>
|
* Copyright (C) 2007-2008 Daniel Drake <dsd@gentoo.org>
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or
|
* This library is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
@ -24,6 +24,9 @@
|
||||||
|
|
||||||
#include "fp_internal.h"
|
#include "fp_internal.h"
|
||||||
|
|
||||||
|
#define MIN_ACCEPTABLE_MINUTIAE 10
|
||||||
|
#define BOZORTH3_DEFAULT_THRESHOLD 40
|
||||||
|
|
||||||
static int img_dev_init(struct fp_dev *dev, unsigned long driver_data)
|
static int img_dev_init(struct fp_dev *dev, unsigned long driver_data)
|
||||||
{
|
{
|
||||||
struct fp_img_dev *imgdev = g_malloc0(sizeof(*imgdev));
|
struct fp_img_dev *imgdev = g_malloc0(sizeof(*imgdev));
|
||||||
|
@ -41,6 +44,8 @@ static int img_dev_init(struct fp_dev *dev, unsigned long driver_data)
|
||||||
r = imgdrv->init(imgdev, driver_data);
|
r = imgdrv->init(imgdev, driver_data);
|
||||||
if (r)
|
if (r)
|
||||||
goto err;
|
goto err;
|
||||||
|
} else {
|
||||||
|
fpi_drvcb_init_complete(dev, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -49,43 +54,37 @@ err:
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void img_dev_exit(struct fp_dev *dev)
|
void fpi_imgdev_init_complete(struct fp_img_dev *imgdev, int status)
|
||||||
|
{
|
||||||
|
fpi_drvcb_init_complete(imgdev->dev, status);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void img_dev_deinit(struct fp_dev *dev)
|
||||||
{
|
{
|
||||||
struct fp_img_dev *imgdev = dev->priv;
|
struct fp_img_dev *imgdev = dev->priv;
|
||||||
struct fp_img_driver *imgdrv = fpi_driver_to_img_driver(dev->drv);
|
struct fp_img_driver *imgdrv = fpi_driver_to_img_driver(dev->drv);
|
||||||
|
|
||||||
if (imgdrv->exit)
|
if (imgdrv->deinit)
|
||||||
imgdrv->exit(imgdev);
|
imgdrv->deinit(imgdev);
|
||||||
|
else
|
||||||
|
fpi_drvcb_deinit_complete(dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
void fpi_imgdev_deinit_complete(struct fp_img_dev *imgdev)
|
||||||
|
{
|
||||||
|
fpi_drvcb_deinit_complete(imgdev->dev);
|
||||||
g_free(imgdev);
|
g_free(imgdev);
|
||||||
}
|
}
|
||||||
|
|
||||||
int fpi_imgdev_get_img_width(struct fp_img_dev *imgdev)
|
static int dev_change_state(struct fp_img_dev *imgdev,
|
||||||
|
enum fp_imgdev_state state)
|
||||||
{
|
{
|
||||||
struct fp_driver *drv = imgdev->dev->drv;
|
struct fp_driver *drv = imgdev->dev->drv;
|
||||||
struct fp_img_driver *imgdrv = fpi_driver_to_img_driver(drv);
|
struct fp_img_driver *imgdrv = fpi_driver_to_img_driver(drv);
|
||||||
int width = imgdrv->img_width;
|
|
||||||
|
|
||||||
if (width > 0 && imgdrv->enlarge_factor > 1)
|
if (!imgdrv->change_state)
|
||||||
width *= imgdrv->enlarge_factor;
|
return 0;
|
||||||
else if (width == -1)
|
return imgdrv->change_state(imgdev, state);
|
||||||
width = 0;
|
|
||||||
|
|
||||||
return width;
|
|
||||||
}
|
|
||||||
|
|
||||||
int fpi_imgdev_get_img_height(struct fp_img_dev *imgdev)
|
|
||||||
{
|
|
||||||
struct fp_driver *drv = imgdev->dev->drv;
|
|
||||||
struct fp_img_driver *imgdrv = fpi_driver_to_img_driver(drv);
|
|
||||||
int height = imgdrv->img_height;
|
|
||||||
|
|
||||||
if (height > 0 && imgdrv->enlarge_factor > 1)
|
|
||||||
height *= imgdrv->enlarge_factor;
|
|
||||||
else if (height == -1)
|
|
||||||
height = 0;
|
|
||||||
|
|
||||||
return height;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct fp_img *im_resize(struct fp_img *img, unsigned int factor)
|
static struct fp_img *im_resize(struct fp_img *img, unsigned int factor)
|
||||||
|
@ -131,79 +130,31 @@ static struct fp_img *im_resize(struct fp_img *img, unsigned int factor)
|
||||||
return newimg;
|
return newimg;
|
||||||
}
|
}
|
||||||
|
|
||||||
int fpi_imgdev_capture(struct fp_img_dev *imgdev, int unconditional,
|
/* check image properties and resize it if necessary. potentially returns a new
|
||||||
struct fp_img **_img)
|
* image after freeing the old one. */
|
||||||
|
static int sanitize_image(struct fp_img_dev *imgdev, struct fp_img **_img)
|
||||||
{
|
{
|
||||||
struct fp_driver *drv = imgdev->dev->drv;
|
struct fp_driver *drv = imgdev->dev->drv;
|
||||||
struct fp_img_driver *imgdrv = fpi_driver_to_img_driver(drv);
|
struct fp_img_driver *imgdrv = fpi_driver_to_img_driver(drv);
|
||||||
struct fp_img *img;
|
struct fp_img *img = *_img;
|
||||||
int r;
|
|
||||||
|
|
||||||
if (!_img) {
|
|
||||||
fp_err("no image pointer given");
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!imgdrv->capture) {
|
|
||||||
fp_err("img driver %s has no capture func", drv->name);
|
|
||||||
return -ENOTSUP;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (unconditional) {
|
|
||||||
if (!(imgdrv->flags & FP_IMGDRV_SUPPORTS_UNCONDITIONAL_CAPTURE)) {
|
|
||||||
fp_dbg("requested unconditional capture, but driver %s does not "
|
|
||||||
"support it", drv->name);
|
|
||||||
return -ENOTSUP;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fp_dbg("%s will handle capture request", drv->name);
|
|
||||||
|
|
||||||
if (!unconditional && imgdrv->await_finger_on) {
|
|
||||||
r = imgdrv->await_finger_on(imgdev);
|
|
||||||
if (r) {
|
|
||||||
fp_err("await_finger_on failed with error %d", r);
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
r = imgdrv->capture(imgdev, unconditional, &img);
|
|
||||||
if (r) {
|
|
||||||
fp_err("capture failed with error %d", r);
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (img == NULL) {
|
|
||||||
fp_err("capture succeeded but no image returned?");
|
|
||||||
return -ENODATA;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!unconditional && imgdrv->await_finger_off) {
|
|
||||||
r = imgdrv->await_finger_off(imgdev);
|
|
||||||
if (r) {
|
|
||||||
fp_err("await_finger_off failed with error %d", r);
|
|
||||||
fp_img_free(img);
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (imgdrv->img_width > 0) {
|
if (imgdrv->img_width > 0) {
|
||||||
img->width = imgdrv->img_width;
|
img->width = imgdrv->img_width;
|
||||||
} else if (img->width <= 0) {
|
} else if (img->width <= 0) {
|
||||||
fp_err("no image width assigned");
|
fp_err("no image width assigned");
|
||||||
goto err;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (imgdrv->img_height > 0) {
|
if (imgdrv->img_height > 0) {
|
||||||
img->height = imgdrv->img_height;
|
img->height = imgdrv->img_height;
|
||||||
} else if (img->height <= 0) {
|
} else if (img->height <= 0) {
|
||||||
fp_err("no image height assigned");
|
fp_err("no image height assigned");
|
||||||
goto err;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!fpi_img_is_sane(img)) {
|
if (!fpi_img_is_sane(img)) {
|
||||||
fp_err("image is not sane!");
|
fp_err("image is not sane!");
|
||||||
goto err;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (imgdrv->enlarge_factor > 1) {
|
if (imgdrv->enlarge_factor > 1) {
|
||||||
|
@ -213,145 +164,335 @@ int fpi_imgdev_capture(struct fp_img_dev *imgdev, int unconditional,
|
||||||
* were bigger. */
|
* were bigger. */
|
||||||
struct fp_img *tmp = im_resize(img, imgdrv->enlarge_factor);
|
struct fp_img *tmp = im_resize(img, imgdrv->enlarge_factor);
|
||||||
fp_img_free(img);
|
fp_img_free(img);
|
||||||
img = tmp;
|
*_img = tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
*_img = img;
|
|
||||||
return 0;
|
return 0;
|
||||||
err:
|
|
||||||
fp_img_free(img);
|
|
||||||
return -EIO;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#define MIN_ACCEPTABLE_MINUTIAE 10
|
void fpi_imgdev_report_finger_status(struct fp_img_dev *imgdev,
|
||||||
|
gboolean present)
|
||||||
int img_dev_enroll(struct fp_dev *dev, gboolean initial, int stage,
|
|
||||||
struct fp_print_data **ret, struct fp_img **_img)
|
|
||||||
{
|
{
|
||||||
struct fp_img *img = NULL;
|
int r = imgdev->action_result;
|
||||||
struct fp_img_dev *imgdev = dev->priv;
|
fp_dbg(present ? "finger on sensor" : "finger removed");
|
||||||
struct fp_print_data *print;
|
|
||||||
int r;
|
|
||||||
|
|
||||||
/* FIXME: convert to 3-stage enroll mechanism, where we scan 3 prints,
|
if (present && imgdev->action_state == IMG_ACQUIRE_STATE_AWAIT_FINGER_ON) {
|
||||||
* use NFIQ to pick the best one, and discard the others */
|
dev_change_state(imgdev, IMGDEV_STATE_CAPTURE);
|
||||||
|
imgdev->action_state = IMG_ACQUIRE_STATE_AWAIT_IMAGE;
|
||||||
r = fpi_imgdev_capture(imgdev, 0, &img);
|
return;
|
||||||
|
} else if (present
|
||||||
/* If we got an image, standardize it and return it even if the scan
|
|| imgdev->action_state != IMG_ACQUIRE_STATE_AWAIT_FINGER_OFF) {
|
||||||
* quality was too low for processing. */
|
fp_dbg("ignoring status report");
|
||||||
if (img)
|
return;
|
||||||
fp_img_standardize(img);
|
|
||||||
if (_img)
|
|
||||||
*_img = img;
|
|
||||||
if (r)
|
|
||||||
return r;
|
|
||||||
|
|
||||||
r = fpi_img_to_print_data(imgdev, img, &print);
|
|
||||||
if (r < 0)
|
|
||||||
return r;
|
|
||||||
if (img->minutiae->num < MIN_ACCEPTABLE_MINUTIAE) {
|
|
||||||
fp_dbg("not enough minutiae, %d/%d", r, MIN_ACCEPTABLE_MINUTIAE);
|
|
||||||
fp_print_data_free(print);
|
|
||||||
return FP_ENROLL_RETRY;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
*ret = print;
|
switch (imgdev->action) {
|
||||||
return FP_ENROLL_COMPLETE;
|
case IMG_ACTION_ENROLL:
|
||||||
|
fpi_drvcb_enroll_stage_completed(imgdev->dev, r, imgdev->acquire_data,
|
||||||
|
imgdev->acquire_img);
|
||||||
|
break;
|
||||||
|
case IMG_ACTION_VERIFY:
|
||||||
|
fpi_drvcb_report_verify_result(imgdev->dev, r, imgdev->acquire_img);
|
||||||
|
fp_print_data_free(imgdev->acquire_data);
|
||||||
|
break;
|
||||||
|
case IMG_ACTION_IDENTIFY:
|
||||||
|
fpi_drvcb_report_identify_result(imgdev->dev, r,
|
||||||
|
imgdev->identify_match_offset, imgdev->acquire_img);
|
||||||
|
fp_print_data_free(imgdev->acquire_data);
|
||||||
|
default:
|
||||||
|
fp_err("unhandled action %d", imgdev->action);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
imgdev->acquire_img = NULL;
|
||||||
|
imgdev->acquire_data = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define BOZORTH3_DEFAULT_THRESHOLD 40
|
static void verify_process_img(struct fp_img_dev *imgdev)
|
||||||
|
|
||||||
static int img_dev_verify(struct fp_dev *dev,
|
|
||||||
struct fp_print_data *enrolled_print, struct fp_img **_img)
|
|
||||||
{
|
{
|
||||||
struct fp_img_dev *imgdev = dev->priv;
|
struct fp_img_driver *imgdrv = fpi_driver_to_img_driver(imgdev->dev->drv);
|
||||||
struct fp_img_driver *imgdrv = fpi_driver_to_img_driver(dev->drv);
|
|
||||||
struct fp_img *img = NULL;
|
|
||||||
struct fp_print_data *print;
|
|
||||||
int match_score = imgdrv->bz3_threshold;
|
int match_score = imgdrv->bz3_threshold;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
r = fpi_imgdev_capture(imgdev, 0, &img);
|
|
||||||
|
|
||||||
/* If we got an image, standardize it and return it even if the scan
|
|
||||||
* quality was too low for processing. */
|
|
||||||
if (img)
|
|
||||||
fp_img_standardize(img);
|
|
||||||
if (_img)
|
|
||||||
*_img = img;
|
|
||||||
if (r)
|
|
||||||
return r;
|
|
||||||
|
|
||||||
r = fpi_img_to_print_data(imgdev, img, &print);
|
|
||||||
if (r < 0)
|
|
||||||
return r;
|
|
||||||
if (img->minutiae->num < MIN_ACCEPTABLE_MINUTIAE) {
|
|
||||||
fp_dbg("not enough minutiae, %d/%d", r, MIN_ACCEPTABLE_MINUTIAE);
|
|
||||||
fp_print_data_free(print);
|
|
||||||
return FP_VERIFY_RETRY;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (match_score == 0)
|
if (match_score == 0)
|
||||||
match_score = BOZORTH3_DEFAULT_THRESHOLD;
|
match_score = BOZORTH3_DEFAULT_THRESHOLD;
|
||||||
|
|
||||||
r = fpi_img_compare_print_data(enrolled_print, print);
|
r = fpi_img_compare_print_data(imgdev->dev->verify_data,
|
||||||
fp_print_data_free(print);
|
imgdev->acquire_data);
|
||||||
if (r < 0)
|
|
||||||
return r;
|
|
||||||
if (r >= match_score)
|
if (r >= match_score)
|
||||||
return FP_VERIFY_MATCH;
|
r = FP_VERIFY_MATCH;
|
||||||
else
|
else if (r >= 0)
|
||||||
return FP_VERIFY_NO_MATCH;
|
r = FP_VERIFY_NO_MATCH;
|
||||||
|
|
||||||
|
imgdev->action_result = r;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int img_dev_identify(struct fp_dev *dev,
|
static void identify_process_img(struct fp_img_dev *imgdev)
|
||||||
struct fp_print_data **print_gallery, size_t *match_offset,
|
|
||||||
struct fp_img **_img)
|
|
||||||
{
|
{
|
||||||
struct fp_img_dev *imgdev = dev->priv;
|
struct fp_img_driver *imgdrv = fpi_driver_to_img_driver(imgdev->dev->drv);
|
||||||
struct fp_img_driver *imgdrv = fpi_driver_to_img_driver(dev->drv);
|
|
||||||
struct fp_img *img = NULL;
|
|
||||||
struct fp_print_data *print;
|
|
||||||
int match_score = imgdrv->bz3_threshold;
|
int match_score = imgdrv->bz3_threshold;
|
||||||
|
size_t match_offset;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
r = fpi_imgdev_capture(imgdev, 0, &img);
|
|
||||||
|
|
||||||
/* If we got an image, standardize it and return it even if the scan
|
|
||||||
* quality was too low for processing. */
|
|
||||||
if (img)
|
|
||||||
fp_img_standardize(img);
|
|
||||||
if (_img)
|
|
||||||
*_img = img;
|
|
||||||
if (r)
|
|
||||||
return r;
|
|
||||||
|
|
||||||
r = fpi_img_to_print_data(imgdev, img, &print);
|
|
||||||
if (r < 0)
|
|
||||||
return r;
|
|
||||||
if (img->minutiae->num < MIN_ACCEPTABLE_MINUTIAE) {
|
|
||||||
fp_dbg("not enough minutiae, %d/%d", r, MIN_ACCEPTABLE_MINUTIAE);
|
|
||||||
fp_print_data_free(print);
|
|
||||||
return FP_VERIFY_RETRY;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (match_score == 0)
|
if (match_score == 0)
|
||||||
match_score = BOZORTH3_DEFAULT_THRESHOLD;
|
match_score = BOZORTH3_DEFAULT_THRESHOLD;
|
||||||
|
|
||||||
r = fpi_img_compare_print_data_to_gallery(print, print_gallery,
|
r = fpi_img_compare_print_data_to_gallery(imgdev->acquire_data,
|
||||||
match_score, match_offset);
|
imgdev->dev->identify_data, match_score, &match_offset);
|
||||||
|
|
||||||
|
imgdev->action_result = r;
|
||||||
|
imgdev->identify_match_offset = match_offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
void fpi_imgdev_image_captured(struct fp_img_dev *imgdev, struct fp_img *img)
|
||||||
|
{
|
||||||
|
struct fp_print_data *print;
|
||||||
|
int r;
|
||||||
|
fp_dbg("");
|
||||||
|
|
||||||
|
if (imgdev->action_state != IMG_ACQUIRE_STATE_AWAIT_IMAGE) {
|
||||||
|
fp_dbg("ignoring due to current state %d", imgdev->action_state);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (imgdev->action_result) {
|
||||||
|
fp_dbg("not overwriting existing action result");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = sanitize_image(imgdev, &img);
|
||||||
|
if (r < 0) {
|
||||||
|
imgdev->action_result = r;
|
||||||
|
fp_img_free(img);
|
||||||
|
goto next_state;
|
||||||
|
}
|
||||||
|
|
||||||
|
fp_img_standardize(img);
|
||||||
|
imgdev->acquire_img = img;
|
||||||
|
fpi_img_to_print_data(imgdev, img, &print);
|
||||||
|
if (img->minutiae->num < MIN_ACCEPTABLE_MINUTIAE) {
|
||||||
|
fp_dbg("not enough minutiae, %d/%d", img->minutiae->num,
|
||||||
|
MIN_ACCEPTABLE_MINUTIAE);
|
||||||
fp_print_data_free(print);
|
fp_print_data_free(print);
|
||||||
|
/* depends on FP_ENROLL_RETRY == FP_VERIFY_RETRY */
|
||||||
|
imgdev->action = FP_ENROLL_RETRY;
|
||||||
|
goto next_state;
|
||||||
|
}
|
||||||
|
|
||||||
|
imgdev->acquire_data = print;
|
||||||
|
switch (imgdev->action) {
|
||||||
|
case IMG_ACTION_ENROLL:
|
||||||
|
imgdev->action_result = FP_ENROLL_COMPLETE;
|
||||||
|
break;
|
||||||
|
case IMG_ACTION_VERIFY:
|
||||||
|
verify_process_img(imgdev);
|
||||||
|
break;
|
||||||
|
case IMG_ACTION_IDENTIFY:
|
||||||
|
identify_process_img(imgdev);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
BUG();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
next_state:
|
||||||
|
imgdev->action_state = IMG_ACQUIRE_STATE_AWAIT_FINGER_OFF;
|
||||||
|
dev_change_state(imgdev, IMGDEV_STATE_AWAIT_FINGER_OFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
void fpi_imgdev_session_error(struct fp_img_dev *imgdev, int error)
|
||||||
|
{
|
||||||
|
fp_dbg("error %d", error);
|
||||||
|
BUG_ON(error == 0);
|
||||||
|
switch (imgdev->action) {
|
||||||
|
case IMG_ACTION_ENROLL:
|
||||||
|
fpi_drvcb_enroll_stage_completed(imgdev->dev, error, NULL, NULL);
|
||||||
|
break;
|
||||||
|
case IMG_ACTION_VERIFY:
|
||||||
|
fpi_drvcb_report_verify_result(imgdev->dev, error, NULL);
|
||||||
|
break;
|
||||||
|
case IMG_ACTION_IDENTIFY:
|
||||||
|
fpi_drvcb_report_identify_result(imgdev->dev, error, 0, NULL);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
fp_err("unhandled action %d", imgdev->action);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void fpi_imgdev_activate_complete(struct fp_img_dev *imgdev, int status)
|
||||||
|
{
|
||||||
|
fp_dbg("status %d", status);
|
||||||
|
|
||||||
|
switch (imgdev->action) {
|
||||||
|
case IMG_ACTION_ENROLL:
|
||||||
|
fpi_drvcb_enroll_started(imgdev->dev, status);
|
||||||
|
break;
|
||||||
|
case IMG_ACTION_VERIFY:
|
||||||
|
fpi_drvcb_verify_started(imgdev->dev, status);
|
||||||
|
break;
|
||||||
|
case IMG_ACTION_IDENTIFY:
|
||||||
|
fpi_drvcb_identify_started(imgdev->dev, status);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
fp_err("unhandled action %d", imgdev->action);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status == 0) {
|
||||||
|
imgdev->action_state = IMG_ACQUIRE_STATE_AWAIT_FINGER_ON;
|
||||||
|
dev_change_state(imgdev, IMGDEV_STATE_AWAIT_FINGER_ON);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void fpi_imgdev_deactivate_complete(struct fp_img_dev *imgdev)
|
||||||
|
{
|
||||||
|
fp_dbg("");
|
||||||
|
|
||||||
|
switch (imgdev->action) {
|
||||||
|
case IMG_ACTION_ENROLL:
|
||||||
|
fpi_drvcb_enroll_stopped(imgdev->dev);
|
||||||
|
break;
|
||||||
|
case IMG_ACTION_VERIFY:
|
||||||
|
fpi_drvcb_verify_stopped(imgdev->dev);
|
||||||
|
break;
|
||||||
|
case IMG_ACTION_IDENTIFY:
|
||||||
|
fpi_drvcb_identify_stopped(imgdev->dev);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
fp_err("unhandled action %d", imgdev->action);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
imgdev->action = IMG_ACTION_NONE;
|
||||||
|
imgdev->action_state = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int fpi_imgdev_get_img_width(struct fp_img_dev *imgdev)
|
||||||
|
{
|
||||||
|
struct fp_driver *drv = imgdev->dev->drv;
|
||||||
|
struct fp_img_driver *imgdrv = fpi_driver_to_img_driver(drv);
|
||||||
|
int width = imgdrv->img_width;
|
||||||
|
|
||||||
|
if (width > 0 && imgdrv->enlarge_factor > 1)
|
||||||
|
width *= imgdrv->enlarge_factor;
|
||||||
|
else if (width == -1)
|
||||||
|
width = 0;
|
||||||
|
|
||||||
|
return width;
|
||||||
|
}
|
||||||
|
|
||||||
|
int fpi_imgdev_get_img_height(struct fp_img_dev *imgdev)
|
||||||
|
{
|
||||||
|
struct fp_driver *drv = imgdev->dev->drv;
|
||||||
|
struct fp_img_driver *imgdrv = fpi_driver_to_img_driver(drv);
|
||||||
|
int height = imgdrv->img_height;
|
||||||
|
|
||||||
|
if (height > 0 && imgdrv->enlarge_factor > 1)
|
||||||
|
height *= imgdrv->enlarge_factor;
|
||||||
|
else if (height == -1)
|
||||||
|
height = 0;
|
||||||
|
|
||||||
|
return height;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int dev_activate(struct fp_img_dev *imgdev, enum fp_imgdev_state state)
|
||||||
|
{
|
||||||
|
struct fp_driver *drv = imgdev->dev->drv;
|
||||||
|
struct fp_img_driver *imgdrv = fpi_driver_to_img_driver(drv);
|
||||||
|
|
||||||
|
if (!imgdrv->activate)
|
||||||
|
return 0;
|
||||||
|
return imgdrv->activate(imgdev, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dev_deactivate(struct fp_img_dev *imgdev)
|
||||||
|
{
|
||||||
|
struct fp_driver *drv = imgdev->dev->drv;
|
||||||
|
struct fp_img_driver *imgdrv = fpi_driver_to_img_driver(drv);
|
||||||
|
|
||||||
|
if (!imgdrv->activate)
|
||||||
|
return;
|
||||||
|
return imgdrv->deactivate(imgdev);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int generic_acquire_start(struct fp_dev *dev, int action)
|
||||||
|
{
|
||||||
|
struct fp_img_dev *imgdev = dev->priv;
|
||||||
|
int r;
|
||||||
|
fp_dbg("action %d", action);
|
||||||
|
imgdev->action = action;
|
||||||
|
imgdev->action_state = IMG_ACQUIRE_STATE_ACTIVATING;
|
||||||
|
|
||||||
|
r = dev_activate(imgdev, IMGDEV_STATE_AWAIT_FINGER_ON);
|
||||||
|
if (r < 0)
|
||||||
|
fp_err("activation failed with error %d", r);
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static void generic_acquire_stop(struct fp_img_dev *imgdev)
|
||||||
|
{
|
||||||
|
imgdev->action_state = IMG_ACQUIRE_STATE_DEACTIVATING;
|
||||||
|
dev_deactivate(imgdev);
|
||||||
|
|
||||||
|
fp_print_data_free(imgdev->acquire_data);
|
||||||
|
fp_img_free(imgdev->acquire_img);
|
||||||
|
imgdev->acquire_data = NULL;
|
||||||
|
imgdev->acquire_img = NULL;
|
||||||
|
imgdev->action_result = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int img_dev_enroll_start(struct fp_dev *dev)
|
||||||
|
{
|
||||||
|
return generic_acquire_start(dev, IMG_ACTION_ENROLL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int img_dev_verify_start(struct fp_dev *dev)
|
||||||
|
{
|
||||||
|
return generic_acquire_start(dev, IMG_ACTION_VERIFY);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int img_dev_identify_start(struct fp_dev *dev)
|
||||||
|
{
|
||||||
|
return generic_acquire_start(dev, IMG_ACTION_IDENTIFY);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int img_dev_enroll_stop(struct fp_dev *dev)
|
||||||
|
{
|
||||||
|
struct fp_img_dev *imgdev = dev->priv;
|
||||||
|
BUG_ON(imgdev->action != IMG_ACTION_ENROLL);
|
||||||
|
generic_acquire_stop(imgdev);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int img_dev_verify_stop(struct fp_dev *dev, gboolean iterating)
|
||||||
|
{
|
||||||
|
struct fp_img_dev *imgdev = dev->priv;
|
||||||
|
BUG_ON(imgdev->action != IMG_ACTION_VERIFY);
|
||||||
|
generic_acquire_stop(imgdev);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int img_dev_identify_stop(struct fp_dev *dev, gboolean iterating)
|
||||||
|
{
|
||||||
|
struct fp_img_dev *imgdev = dev->priv;
|
||||||
|
BUG_ON(imgdev->action != IMG_ACTION_IDENTIFY);
|
||||||
|
generic_acquire_stop(imgdev);
|
||||||
|
imgdev->identify_match_offset = 0;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void fpi_img_driver_setup(struct fp_img_driver *idriver)
|
void fpi_img_driver_setup(struct fp_img_driver *idriver)
|
||||||
{
|
{
|
||||||
idriver->driver.type = DRIVER_IMAGING;
|
idriver->driver.type = DRIVER_IMAGING;
|
||||||
idriver->driver.init = img_dev_init;
|
idriver->driver.init = img_dev_init;
|
||||||
//idriver->driver.exit = img_dev_exit;
|
idriver->driver.deinit = img_dev_deinit;
|
||||||
//idriver->driver.enroll = img_dev_enroll;
|
idriver->driver.enroll_start = img_dev_enroll_start;
|
||||||
//idriver->driver.verify = img_dev_verify;
|
idriver->driver.enroll_stop = img_dev_enroll_stop;
|
||||||
//idriver->driver.identify = img_dev_identify;
|
idriver->driver.verify_start = img_dev_verify_start;
|
||||||
|
idriver->driver.verify_stop = img_dev_verify_stop;
|
||||||
|
idriver->driver.identify_start = img_dev_identify_start;
|
||||||
|
idriver->driver.identify_stop = img_dev_identify_stop;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue