2
* Core imaging device functions for libfprint
3
* Copyright (C) 2007-2008 Daniel Drake <dsd@gentoo.org>
5
* This library is free software; you can redistribute it and/or
6
* modify it under the terms of the GNU Lesser General Public
7
* License as published by the Free Software Foundation; either
8
* version 2.1 of the License, or (at your option) any later version.
10
* This library is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
* Lesser General Public License for more details.
15
* You should have received a copy of the GNU Lesser General Public
16
* License along with this library; if not, write to the Free Software
17
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24
#include "fp_internal.h"
26
#define MIN_ACCEPTABLE_MINUTIAE 10
27
#define BOZORTH3_DEFAULT_THRESHOLD 40
29
static int img_dev_open(struct fp_dev *dev, unsigned long driver_data)
31
struct fp_img_dev *imgdev = g_malloc0(sizeof(*imgdev));
32
struct fp_img_driver *imgdrv = fpi_driver_to_img_driver(dev->drv);
37
dev->nr_enroll_stages = 1;
39
/* for consistency in driver code, allow udev access through imgdev */
40
imgdev->udev = dev->udev;
43
r = imgdrv->open(imgdev, driver_data);
47
fpi_drvcb_open_complete(dev, 0);
56
void fpi_imgdev_open_complete(struct fp_img_dev *imgdev, int status)
58
fpi_drvcb_open_complete(imgdev->dev, status);
61
static void img_dev_close(struct fp_dev *dev)
63
struct fp_img_dev *imgdev = dev->priv;
64
struct fp_img_driver *imgdrv = fpi_driver_to_img_driver(dev->drv);
67
imgdrv->close(imgdev);
69
fpi_drvcb_close_complete(dev);
72
void fpi_imgdev_close_complete(struct fp_img_dev *imgdev)
74
fpi_drvcb_close_complete(imgdev->dev);
78
static int dev_change_state(struct fp_img_dev *imgdev,
79
enum fp_imgdev_state state)
81
struct fp_driver *drv = imgdev->dev->drv;
82
struct fp_img_driver *imgdrv = fpi_driver_to_img_driver(drv);
84
if (!imgdrv->change_state)
86
return imgdrv->change_state(imgdev, state);
89
/* check image properties and resize it if necessary. potentially returns a new
90
* image after freeing the old one. */
91
static int sanitize_image(struct fp_img_dev *imgdev, struct fp_img **_img)
93
struct fp_driver *drv = imgdev->dev->drv;
94
struct fp_img_driver *imgdrv = fpi_driver_to_img_driver(drv);
95
struct fp_img *img = *_img;
97
if (imgdrv->img_width > 0) {
98
img->width = imgdrv->img_width;
99
} else if (img->width <= 0) {
100
fp_err("no image width assigned");
104
if (imgdrv->img_height > 0) {
105
img->height = imgdrv->img_height;
106
} else if (img->height <= 0) {
107
fp_err("no image height assigned");
111
if (!fpi_img_is_sane(img)) {
112
fp_err("image is not sane!");
119
void fpi_imgdev_report_finger_status(struct fp_img_dev *imgdev,
122
int r = imgdev->action_result;
123
struct fp_print_data *data = imgdev->acquire_data;
124
struct fp_img *img = imgdev->acquire_img;
126
fp_dbg(present ? "finger on sensor" : "finger removed");
128
if (present && imgdev->action_state == IMG_ACQUIRE_STATE_AWAIT_FINGER_ON) {
129
dev_change_state(imgdev, IMGDEV_STATE_CAPTURE);
130
imgdev->action_state = IMG_ACQUIRE_STATE_AWAIT_IMAGE;
133
|| imgdev->action_state != IMG_ACQUIRE_STATE_AWAIT_FINGER_OFF) {
134
fp_dbg("ignoring status report");
138
/* clear these before reporting results to avoid complications with
139
* call cascading in and out of the library */
140
imgdev->acquire_img = NULL;
141
imgdev->acquire_data = NULL;
143
/* finger removed, report results */
144
switch (imgdev->action) {
145
case IMG_ACTION_ENROLL:
146
fp_dbg("reporting enroll result");
147
fpi_drvcb_enroll_stage_completed(imgdev->dev, r, data, img);
148
if (r > 0 && r != FP_ENROLL_COMPLETE && r != FP_ENROLL_FAIL) {
149
imgdev->action_result = 0;
150
imgdev->action_state = IMG_ACQUIRE_STATE_AWAIT_FINGER_ON;
151
dev_change_state(imgdev, IMG_ACQUIRE_STATE_AWAIT_FINGER_ON);
154
case IMG_ACTION_VERIFY:
155
fpi_drvcb_report_verify_result(imgdev->dev, r, img);
156
fp_print_data_free(data);
158
case IMG_ACTION_IDENTIFY:
159
fpi_drvcb_report_identify_result(imgdev->dev, r,
160
imgdev->identify_match_offset, img);
161
fp_print_data_free(data);
164
fp_err("unhandled action %d", imgdev->action);
169
static void verify_process_img(struct fp_img_dev *imgdev)
171
struct fp_img_driver *imgdrv = fpi_driver_to_img_driver(imgdev->dev->drv);
172
int match_score = imgdrv->bz3_threshold;
175
if (match_score == 0)
176
match_score = BOZORTH3_DEFAULT_THRESHOLD;
178
r = fpi_img_compare_print_data(imgdev->dev->verify_data,
179
imgdev->acquire_data);
181
if (r >= match_score)
184
r = FP_VERIFY_NO_MATCH;
186
imgdev->action_result = r;
189
static void identify_process_img(struct fp_img_dev *imgdev)
191
struct fp_img_driver *imgdrv = fpi_driver_to_img_driver(imgdev->dev->drv);
192
int match_score = imgdrv->bz3_threshold;
196
if (match_score == 0)
197
match_score = BOZORTH3_DEFAULT_THRESHOLD;
199
r = fpi_img_compare_print_data_to_gallery(imgdev->acquire_data,
200
imgdev->dev->identify_gallery, match_score, &match_offset);
202
imgdev->action_result = r;
203
imgdev->identify_match_offset = match_offset;
206
void fpi_imgdev_image_captured(struct fp_img_dev *imgdev, struct fp_img *img)
208
struct fp_print_data *print;
212
if (imgdev->action_state != IMG_ACQUIRE_STATE_AWAIT_IMAGE) {
213
fp_dbg("ignoring due to current state %d", imgdev->action_state);
217
if (imgdev->action_result) {
218
fp_dbg("not overwriting existing action result");
222
r = sanitize_image(imgdev, &img);
224
imgdev->action_result = r;
229
fp_img_standardize(img);
230
imgdev->acquire_img = img;
231
r = fpi_img_to_print_data(imgdev, img, &print);
233
fp_dbg("image to print data conversion error: %d", r);
234
imgdev->action_result = FP_ENROLL_RETRY;
236
} else if (img->minutiae->num < MIN_ACCEPTABLE_MINUTIAE) {
237
fp_dbg("not enough minutiae, %d/%d", img->minutiae->num,
238
MIN_ACCEPTABLE_MINUTIAE);
239
fp_print_data_free(print);
240
/* depends on FP_ENROLL_RETRY == FP_VERIFY_RETRY */
241
imgdev->action_result = FP_ENROLL_RETRY;
245
imgdev->acquire_data = print;
246
switch (imgdev->action) {
247
case IMG_ACTION_ENROLL:
248
imgdev->action_result = FP_ENROLL_COMPLETE;
250
case IMG_ACTION_VERIFY:
251
verify_process_img(imgdev);
253
case IMG_ACTION_IDENTIFY:
254
identify_process_img(imgdev);
262
imgdev->action_state = IMG_ACQUIRE_STATE_AWAIT_FINGER_OFF;
263
dev_change_state(imgdev, IMGDEV_STATE_AWAIT_FINGER_OFF);
266
void fpi_imgdev_session_error(struct fp_img_dev *imgdev, int error)
268
fp_dbg("error %d", error);
270
switch (imgdev->action) {
271
case IMG_ACTION_ENROLL:
272
fpi_drvcb_enroll_stage_completed(imgdev->dev, error, NULL, NULL);
274
case IMG_ACTION_VERIFY:
275
fpi_drvcb_report_verify_result(imgdev->dev, error, NULL);
277
case IMG_ACTION_IDENTIFY:
278
fpi_drvcb_report_identify_result(imgdev->dev, error, 0, NULL);
281
fp_err("unhandled action %d", imgdev->action);
286
void fpi_imgdev_activate_complete(struct fp_img_dev *imgdev, int status)
288
fp_dbg("status %d", status);
290
switch (imgdev->action) {
291
case IMG_ACTION_ENROLL:
292
fpi_drvcb_enroll_started(imgdev->dev, status);
294
case IMG_ACTION_VERIFY:
295
fpi_drvcb_verify_started(imgdev->dev, status);
297
case IMG_ACTION_IDENTIFY:
298
fpi_drvcb_identify_started(imgdev->dev, status);
301
fp_err("unhandled action %d", imgdev->action);
306
imgdev->action_state = IMG_ACQUIRE_STATE_AWAIT_FINGER_ON;
307
dev_change_state(imgdev, IMGDEV_STATE_AWAIT_FINGER_ON);
311
void fpi_imgdev_deactivate_complete(struct fp_img_dev *imgdev)
315
switch (imgdev->action) {
316
case IMG_ACTION_ENROLL:
317
fpi_drvcb_enroll_stopped(imgdev->dev);
319
case IMG_ACTION_VERIFY:
320
fpi_drvcb_verify_stopped(imgdev->dev);
322
case IMG_ACTION_IDENTIFY:
323
fpi_drvcb_identify_stopped(imgdev->dev);
326
fp_err("unhandled action %d", imgdev->action);
330
imgdev->action = IMG_ACTION_NONE;
331
imgdev->action_state = 0;
334
int fpi_imgdev_get_img_width(struct fp_img_dev *imgdev)
336
struct fp_driver *drv = imgdev->dev->drv;
337
struct fp_img_driver *imgdrv = fpi_driver_to_img_driver(drv);
338
int width = imgdrv->img_width;
346
int fpi_imgdev_get_img_height(struct fp_img_dev *imgdev)
348
struct fp_driver *drv = imgdev->dev->drv;
349
struct fp_img_driver *imgdrv = fpi_driver_to_img_driver(drv);
350
int height = imgdrv->img_height;
358
static int dev_activate(struct fp_img_dev *imgdev, enum fp_imgdev_state state)
360
struct fp_driver *drv = imgdev->dev->drv;
361
struct fp_img_driver *imgdrv = fpi_driver_to_img_driver(drv);
363
if (!imgdrv->activate)
365
return imgdrv->activate(imgdev, state);
368
static void dev_deactivate(struct fp_img_dev *imgdev)
370
struct fp_driver *drv = imgdev->dev->drv;
371
struct fp_img_driver *imgdrv = fpi_driver_to_img_driver(drv);
373
if (!imgdrv->deactivate)
375
return imgdrv->deactivate(imgdev);
378
static int generic_acquire_start(struct fp_dev *dev, int action)
380
struct fp_img_dev *imgdev = dev->priv;
382
fp_dbg("action %d", action);
383
imgdev->action = action;
384
imgdev->action_state = IMG_ACQUIRE_STATE_ACTIVATING;
386
r = dev_activate(imgdev, IMGDEV_STATE_AWAIT_FINGER_ON);
388
fp_err("activation failed with error %d", r);
394
static void generic_acquire_stop(struct fp_img_dev *imgdev)
396
imgdev->action_state = IMG_ACQUIRE_STATE_DEACTIVATING;
397
dev_deactivate(imgdev);
399
fp_print_data_free(imgdev->acquire_data);
400
fp_img_free(imgdev->acquire_img);
401
imgdev->acquire_data = NULL;
402
imgdev->acquire_img = NULL;
403
imgdev->action_result = 0;
406
static int img_dev_enroll_start(struct fp_dev *dev)
408
return generic_acquire_start(dev, IMG_ACTION_ENROLL);
411
static int img_dev_verify_start(struct fp_dev *dev)
413
return generic_acquire_start(dev, IMG_ACTION_VERIFY);
416
static int img_dev_identify_start(struct fp_dev *dev)
418
return generic_acquire_start(dev, IMG_ACTION_IDENTIFY);
421
static int img_dev_enroll_stop(struct fp_dev *dev)
423
struct fp_img_dev *imgdev = dev->priv;
424
BUG_ON(imgdev->action != IMG_ACTION_ENROLL);
425
generic_acquire_stop(imgdev);
429
static int img_dev_verify_stop(struct fp_dev *dev, gboolean iterating)
431
struct fp_img_dev *imgdev = dev->priv;
432
BUG_ON(imgdev->action != IMG_ACTION_VERIFY);
433
generic_acquire_stop(imgdev);
437
static int img_dev_identify_stop(struct fp_dev *dev, gboolean iterating)
439
struct fp_img_dev *imgdev = dev->priv;
440
BUG_ON(imgdev->action != IMG_ACTION_IDENTIFY);
441
generic_acquire_stop(imgdev);
442
imgdev->identify_match_offset = 0;
446
void fpi_img_driver_setup(struct fp_img_driver *idriver)
448
idriver->driver.type = DRIVER_IMAGING;
449
idriver->driver.open = img_dev_open;
450
idriver->driver.close = img_dev_close;
451
idriver->driver.enroll_start = img_dev_enroll_start;
452
idriver->driver.enroll_stop = img_dev_enroll_stop;
453
idriver->driver.verify_start = img_dev_verify_start;
454
idriver->driver.verify_stop = img_dev_verify_stop;
455
idriver->driver.identify_start = img_dev_identify_start;
456
idriver->driver.identify_stop = img_dev_identify_stop;