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 fpi_img_to_print_data(imgdev
, img
, &print
);
232 if (img
->minutiae
->num
< MIN_ACCEPTABLE_MINUTIAE
) {
233 fp_dbg("not enough minutiae, %d/%d", img
->minutiae
->num
,
234 MIN_ACCEPTABLE_MINUTIAE
);
235 fp_print_data_free(print
);
236 /* depends on FP_ENROLL_RETRY == FP_VERIFY_RETRY */
237 imgdev
->action_result
= FP_ENROLL_RETRY
;
241 imgdev
->acquire_data
= print
;
242 switch (imgdev
->action
) {
243 case IMG_ACTION_ENROLL
:
244 imgdev
->action_result
= FP_ENROLL_COMPLETE
;
246 case IMG_ACTION_VERIFY
:
247 verify_process_img(imgdev
);
249 case IMG_ACTION_IDENTIFY
:
250 identify_process_img(imgdev
);
258 imgdev
->action_state
= IMG_ACQUIRE_STATE_AWAIT_FINGER_OFF
;
259 dev_change_state(imgdev
, IMGDEV_STATE_AWAIT_FINGER_OFF
);
262 void fpi_imgdev_session_error(struct fp_img_dev
*imgdev
, int error
)
264 fp_dbg("error %d", error
);
266 switch (imgdev
->action
) {
267 case IMG_ACTION_ENROLL
:
268 fpi_drvcb_enroll_stage_completed(imgdev
->dev
, error
, NULL
, NULL
);
270 case IMG_ACTION_VERIFY
:
271 fpi_drvcb_report_verify_result(imgdev
->dev
, error
, NULL
);
273 case IMG_ACTION_IDENTIFY
:
274 fpi_drvcb_report_identify_result(imgdev
->dev
, error
, 0, NULL
);
277 fp_err("unhandled action %d", imgdev
->action
);
282 void fpi_imgdev_activate_complete(struct fp_img_dev
*imgdev
, int status
)
284 fp_dbg("status %d", status
);
286 switch (imgdev
->action
) {
287 case IMG_ACTION_ENROLL
:
288 fpi_drvcb_enroll_started(imgdev
->dev
, status
);
290 case IMG_ACTION_VERIFY
:
291 fpi_drvcb_verify_started(imgdev
->dev
, status
);
293 case IMG_ACTION_IDENTIFY
:
294 fpi_drvcb_identify_started(imgdev
->dev
, status
);
297 fp_err("unhandled action %d", imgdev
->action
);
302 imgdev
->action_state
= IMG_ACQUIRE_STATE_AWAIT_FINGER_ON
;
303 dev_change_state(imgdev
, IMGDEV_STATE_AWAIT_FINGER_ON
);
307 void fpi_imgdev_deactivate_complete(struct fp_img_dev
*imgdev
)
311 switch (imgdev
->action
) {
312 case IMG_ACTION_ENROLL
:
313 fpi_drvcb_enroll_stopped(imgdev
->dev
);
315 case IMG_ACTION_VERIFY
:
316 fpi_drvcb_verify_stopped(imgdev
->dev
);
318 case IMG_ACTION_IDENTIFY
:
319 fpi_drvcb_identify_stopped(imgdev
->dev
);
322 fp_err("unhandled action %d", imgdev
->action
);
326 imgdev
->action
= IMG_ACTION_NONE
;
327 imgdev
->action_state
= 0;
330 int fpi_imgdev_get_img_width(struct fp_img_dev
*imgdev
)
332 struct fp_driver
*drv
= imgdev
->dev
->drv
;
333 struct fp_img_driver
*imgdrv
= fpi_driver_to_img_driver(drv
);
334 int width
= imgdrv
->img_width
;
342 int fpi_imgdev_get_img_height(struct fp_img_dev
*imgdev
)
344 struct fp_driver
*drv
= imgdev
->dev
->drv
;
345 struct fp_img_driver
*imgdrv
= fpi_driver_to_img_driver(drv
);
346 int height
= imgdrv
->img_height
;
354 static int dev_activate(struct fp_img_dev
*imgdev
, enum fp_imgdev_state state
)
356 struct fp_driver
*drv
= imgdev
->dev
->drv
;
357 struct fp_img_driver
*imgdrv
= fpi_driver_to_img_driver(drv
);
359 if (!imgdrv
->activate
)
361 return imgdrv
->activate(imgdev
, state
);
364 static void dev_deactivate(struct fp_img_dev
*imgdev
)
366 struct fp_driver
*drv
= imgdev
->dev
->drv
;
367 struct fp_img_driver
*imgdrv
= fpi_driver_to_img_driver(drv
);
369 if (!imgdrv
->activate
)
371 return imgdrv
->deactivate(imgdev
);
374 static int generic_acquire_start(struct fp_dev
*dev
, int action
)
376 struct fp_img_dev
*imgdev
= dev
->priv
;
378 fp_dbg("action %d", action
);
379 imgdev
->action
= action
;
380 imgdev
->action_state
= IMG_ACQUIRE_STATE_ACTIVATING
;
382 r
= dev_activate(imgdev
, IMGDEV_STATE_AWAIT_FINGER_ON
);
384 fp_err("activation failed with error %d", r
);
390 static void generic_acquire_stop(struct fp_img_dev
*imgdev
)
392 imgdev
->action_state
= IMG_ACQUIRE_STATE_DEACTIVATING
;
393 dev_deactivate(imgdev
);
395 fp_print_data_free(imgdev
->acquire_data
);
396 fp_img_free(imgdev
->acquire_img
);
397 imgdev
->acquire_data
= NULL
;
398 imgdev
->acquire_img
= NULL
;
399 imgdev
->action_result
= 0;
402 static int img_dev_enroll_start(struct fp_dev
*dev
)
404 return generic_acquire_start(dev
, IMG_ACTION_ENROLL
);
407 static int img_dev_verify_start(struct fp_dev
*dev
)
409 return generic_acquire_start(dev
, IMG_ACTION_VERIFY
);
412 static int img_dev_identify_start(struct fp_dev
*dev
)
414 return generic_acquire_start(dev
, IMG_ACTION_IDENTIFY
);
417 static int img_dev_enroll_stop(struct fp_dev
*dev
)
419 struct fp_img_dev
*imgdev
= dev
->priv
;
420 BUG_ON(imgdev
->action
!= IMG_ACTION_ENROLL
);
421 generic_acquire_stop(imgdev
);
425 static int img_dev_verify_stop(struct fp_dev
*dev
, gboolean iterating
)
427 struct fp_img_dev
*imgdev
= dev
->priv
;
428 BUG_ON(imgdev
->action
!= IMG_ACTION_VERIFY
);
429 generic_acquire_stop(imgdev
);
433 static int img_dev_identify_stop(struct fp_dev
*dev
, gboolean iterating
)
435 struct fp_img_dev
*imgdev
= dev
->priv
;
436 BUG_ON(imgdev
->action
!= IMG_ACTION_IDENTIFY
);
437 generic_acquire_stop(imgdev
);
438 imgdev
->identify_match_offset
= 0;
442 void fpi_img_driver_setup(struct fp_img_driver
*idriver
)
444 idriver
->driver
.type
= DRIVER_IMAGING
;
445 idriver
->driver
.open
= img_dev_open
;
446 idriver
->driver
.close
= img_dev_close
;
447 idriver
->driver
.enroll_start
= img_dev_enroll_start
;
448 idriver
->driver
.enroll_stop
= img_dev_enroll_stop
;
449 idriver
->driver
.verify_start
= img_dev_verify_start
;
450 idriver
->driver
.verify_stop
= img_dev_verify_stop
;
451 idriver
->driver
.identify_start
= img_dev_identify_start
;
452 idriver
->driver
.identify_stop
= img_dev_identify_stop
;