Add AES2501 driver
[libfprint.git] / libfprint / imgdev.c
blobb9da4b5a6bfd9f6f7d4ec7dc07a2e72bcdc92b22
1 /*
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
20 #include <errno.h>
21 #include <glib.h>
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);
29 int r = 0;
31 imgdev->dev = dev;
32 dev->priv = imgdev;
33 dev->nr_enroll_stages = 1;
35 /* for consistency in driver code, allow udev access through imgdev */
36 imgdev->udev = dev->udev;
38 if (imgdrv->init) {
39 r = imgdrv->init(imgdev, driver_data);
40 if (r)
41 goto err;
44 return 0;
45 err:
46 g_free(imgdev);
47 return r;
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);
55 if (imgdrv->exit)
56 imgdrv->exit(imgdev);
58 g_free(imgdev);
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,
76 struct fp_img **_img)
78 struct fp_driver *drv = imgdev->dev->drv;
79 struct fp_img_driver *imgdrv = fpi_driver_to_img_driver(drv);
80 struct fp_img *img;
81 int r;
83 if (!_img) {
84 fp_err("no image pointer given");
85 return -EINVAL;
88 if (!imgdrv->capture) {
89 fp_err("img driver %s has no capture func", drv->name);
90 return -ENOTSUP;
93 if (unconditional) {
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);
97 return -ENOTSUP;
101 fp_dbg("%s will handle capture request", drv->name);
103 if (!unconditional && imgdrv->await_finger_on) {
104 r = imgdrv->await_finger_on(imgdev);
105 if (r) {
106 fp_err("await_finger_on failed with error %d", r);
107 return r;
111 r = imgdrv->capture(imgdev, unconditional, &img);
112 if (r) {
113 fp_err("capture failed with error %d", r);
114 return r;
117 if (img == NULL) {
118 fp_err("capture succeeded but no image returned?");
119 return -ENODATA;
122 if (!unconditional && imgdrv->await_finger_off) {
123 r = imgdrv->await_finger_off(imgdev);
124 if (r) {
125 fp_err("await_finger_off failed with error %d", r);
126 fp_img_free(img);
127 return 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");
135 goto err;
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");
142 goto err;
145 if (!fpi_img_is_sane(img)) {
146 fp_err("image is not sane!");
147 goto err;
150 *_img = img;
151 return 0;
152 err:
153 fp_img_free(img);
154 return -EIO;
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)
162 struct fp_img *img;
163 struct fp_img_dev *imgdev = dev->priv;
164 struct fp_print_data *print;
165 int r;
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. */
174 if (img)
175 fp_img_standardize(img);
176 if (_img)
177 *_img = img;
178 if (r)
179 return r;
181 r = fpi_img_detect_minutiae(imgdev, img, &print);
182 if (r < 0)
183 return r;
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;
190 *ret = print;
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;
204 int r;
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. */
210 if (img)
211 fp_img_standardize(img);
212 if (_img)
213 *_img = img;
214 if (r)
215 return r;
217 r = fpi_img_detect_minutiae(imgdev, img, &print);
218 if (r < 0)
219 return r;
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);
231 if (r < 0)
232 return r;
233 if (r >= match_score)
234 return FP_VERIFY_MATCH;
235 else
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;