2 * Core imaging device functions for libfprint
3 * Copyright (C) 2007 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
23 #include "fp_internal.h"
25 static int img_dev_init(struct fp_dev
*dev
, unsigned long driver_data
)
27 struct fp_img_dev
*imgdev
= g_malloc0(sizeof(*imgdev
));
28 struct fp_img_driver
*imgdrv
= fpi_driver_to_img_driver(dev
->drv
);
33 dev
->nr_enroll_stages
= 1;
35 /* for consistency in driver code, allow udev access through imgdev */
36 imgdev
->udev
= dev
->udev
;
39 r
= imgdrv
->init(imgdev
, driver_data
);
50 static void img_dev_exit(struct fp_dev
*dev
)
52 struct fp_img_dev
*imgdev
= dev
->priv
;
53 struct fp_img_driver
*imgdrv
= fpi_driver_to_img_driver(dev
->drv
);
61 int fpi_imgdev_get_img_width(struct fp_img_dev
*imgdev
)
63 struct fp_driver
*drv
= imgdev
->dev
->drv
;
64 struct fp_img_driver
*imgdrv
= fpi_driver_to_img_driver(drv
);
65 return imgdrv
->img_width
;
68 int fpi_imgdev_get_img_height(struct fp_img_dev
*imgdev
)
70 struct fp_driver
*drv
= imgdev
->dev
->drv
;
71 struct fp_img_driver
*imgdrv
= fpi_driver_to_img_driver(drv
);
72 return imgdrv
->img_height
;
75 int fpi_imgdev_capture(struct fp_img_dev
*imgdev
, int unconditional
,
78 struct fp_driver
*drv
= imgdev
->dev
->drv
;
79 struct fp_img_driver
*imgdrv
= fpi_driver_to_img_driver(drv
);
84 fp_err("no image pointer given");
88 if (!imgdrv
->capture
) {
89 fp_err("img driver %s has no capture func", drv
->name
);
94 if (!(imgdrv
->flags
& FP_IMGDRV_SUPPORTS_UNCONDITIONAL_CAPTURE
)) {
95 fp_dbg("requested unconditional capture, but driver %s does not "
96 "support it", drv
->name
);
101 fp_dbg("%s will handle capture request", drv
->name
);
103 if (!unconditional
&& imgdrv
->await_finger_on
) {
104 r
= imgdrv
->await_finger_on(imgdev
);
106 fp_err("await_finger_on failed with error %d", r
);
111 r
= imgdrv
->capture(imgdev
, unconditional
, &img
);
113 fp_err("capture failed with error %d", r
);
118 fp_err("capture succeeded but no image returned?");
122 if (!unconditional
&& imgdrv
->await_finger_off
) {
123 r
= imgdrv
->await_finger_off(imgdev
);
125 fp_err("await_finger_off failed with error %d", r
);
131 if (imgdrv
->img_width
> 0) {
132 img
->width
= imgdrv
->img_width
;
133 } else if (img
->width
<= 0) {
134 fp_err("no image width assigned");
138 if (imgdrv
->img_height
> 0) {
139 img
->height
= imgdrv
->img_height
;
140 } else if (img
->height
<= 0) {
141 fp_err("no image height assigned");
145 if (!fpi_img_is_sane(img
)) {
146 fp_err("image is not sane!");
157 #define MIN_ACCEPTABLE_MINUTIAE 10
159 int img_dev_enroll(struct fp_dev
*dev
, gboolean initial
, int stage
,
160 struct fp_print_data
**ret
, struct fp_img
**_img
)
163 struct fp_img_dev
*imgdev
= dev
->priv
;
164 struct fp_print_data
*print
;
167 /* FIXME: convert to 3-stage enroll mechanism, where we scan 3 prints,
168 * use NFIQ to pick the best one, and discard the others */
170 r
= fpi_imgdev_capture(imgdev
, 0, &img
);
172 /* If we got an image, standardize it and return it even if the scan
173 * quality was too low for processing. */
175 fp_img_standardize(img
);
181 r
= fpi_img_detect_minutiae(imgdev
, img
, &print
);
184 if (r
< MIN_ACCEPTABLE_MINUTIAE
) {
185 fp_dbg("not enough minutiae, %d/%d", r
, MIN_ACCEPTABLE_MINUTIAE
);
186 fp_print_data_free(print
);
187 return FP_ENROLL_RETRY
;
191 return FP_ENROLL_COMPLETE
;
194 #define BOZORTH3_DEFAULT_THRESHOLD 40
196 static int img_dev_verify(struct fp_dev
*dev
,
197 struct fp_print_data
*enrolled_print
, struct fp_img
**_img
)
199 struct fp_img_dev
*imgdev
= dev
->priv
;
200 struct fp_img_driver
*imgdrv
= fpi_driver_to_img_driver(dev
->drv
);
201 struct fp_img
*img
= NULL
;
202 struct fp_print_data
*print
;
203 int match_score
= imgdrv
->bz3_threshold
;
206 r
= fpi_imgdev_capture(imgdev
, 0, &img
);
208 /* If we got an image, standardize it and return it even if the scan
209 * quality was too low for processing. */
211 fp_img_standardize(img
);
217 r
= fpi_img_detect_minutiae(imgdev
, img
, &print
);
220 if (r
< MIN_ACCEPTABLE_MINUTIAE
) {
221 fp_dbg("not enough minutiae, %d/%d", r
, MIN_ACCEPTABLE_MINUTIAE
);
222 fp_print_data_free(print
);
223 return FP_VERIFY_RETRY
;
226 if (match_score
== 0)
227 match_score
= BOZORTH3_DEFAULT_THRESHOLD
;
229 r
= fpi_img_compare_print_data(enrolled_print
, print
);
230 fp_print_data_free(print
);
233 if (r
>= match_score
)
234 return FP_VERIFY_MATCH
;
236 return FP_VERIFY_NO_MATCH
;
239 void fpi_img_driver_setup(struct fp_img_driver
*idriver
)
241 idriver
->driver
.type
= DRIVER_IMAGING
;
242 idriver
->driver
.init
= img_dev_init
;
243 idriver
->driver
.exit
= img_dev_exit
;
244 idriver
->driver
.enroll
= img_dev_enroll
;
245 idriver
->driver
.verify
= img_dev_verify
;