~ubuntu-branches/ubuntu/utopic/libfprint/utopic

« back to all changes in this revision

Viewing changes to .pc/u0b2d33c-imgdev-fix-cancelling-of-enrollment-from-stage_completed-callback.patch/libfprint/imgdev.c

  • Committer: Package Import Robot
  • Author(s): Didier Raboud
  • Date: 2013-05-18 16:35:39 UTC
  • mfrom: (4.1.4 experimental)
  • Revision ID: package-import@ubuntu.com-20130518163539-qvwsan4edkdtry6f
Tags: 1:0.5.0-5
* Upload to unstable with two more backports from upstream:
  - imgdev: fix cancelling of enrollment from stage_completed callback
  - upeke2: Add support for 147e:2020 ID

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Core imaging device functions for libfprint
 
3
 * Copyright (C) 2007-2008 Daniel Drake <dsd@gentoo.org>
 
4
 *
 
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.
 
9
 *
 
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.
 
14
 *
 
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
 
18
 */
 
19
 
 
20
#include <errno.h>
 
21
 
 
22
#include <glib.h>
 
23
 
 
24
#include "fp_internal.h"
 
25
 
 
26
#define MIN_ACCEPTABLE_MINUTIAE 10
 
27
#define BOZORTH3_DEFAULT_THRESHOLD 40
 
28
 
 
29
static int img_dev_open(struct fp_dev *dev, unsigned long driver_data)
 
30
{
 
31
        struct fp_img_dev *imgdev = g_malloc0(sizeof(*imgdev));
 
32
        struct fp_img_driver *imgdrv = fpi_driver_to_img_driver(dev->drv);
 
33
        int r = 0;
 
34
 
 
35
        imgdev->dev = dev;
 
36
        dev->priv = imgdev;
 
37
        dev->nr_enroll_stages = 1;
 
38
 
 
39
        /* for consistency in driver code, allow udev access through imgdev */
 
40
        imgdev->udev = dev->udev;
 
41
 
 
42
        if (imgdrv->open) {
 
43
                r = imgdrv->open(imgdev, driver_data);
 
44
                if (r)
 
45
                        goto err;
 
46
        } else {
 
47
                fpi_drvcb_open_complete(dev, 0);
 
48
        }
 
49
 
 
50
        return 0;
 
51
err:
 
52
        g_free(imgdev);
 
53
        return r;
 
54
}
 
55
 
 
56
void fpi_imgdev_open_complete(struct fp_img_dev *imgdev, int status)
 
57
{
 
58
        fpi_drvcb_open_complete(imgdev->dev, status);
 
59
}
 
60
 
 
61
static void img_dev_close(struct fp_dev *dev)
 
62
{
 
63
        struct fp_img_dev *imgdev = dev->priv;
 
64
        struct fp_img_driver *imgdrv = fpi_driver_to_img_driver(dev->drv);
 
65
 
 
66
        if (imgdrv->close)
 
67
                imgdrv->close(imgdev);
 
68
        else
 
69
                fpi_drvcb_close_complete(dev);
 
70
}
 
71
 
 
72
void fpi_imgdev_close_complete(struct fp_img_dev *imgdev)
 
73
{
 
74
        fpi_drvcb_close_complete(imgdev->dev);
 
75
        g_free(imgdev);
 
76
}
 
77
 
 
78
static int dev_change_state(struct fp_img_dev *imgdev,
 
79
        enum fp_imgdev_state state)
 
80
{
 
81
        struct fp_driver *drv = imgdev->dev->drv;
 
82
        struct fp_img_driver *imgdrv = fpi_driver_to_img_driver(drv);
 
83
 
 
84
        if (!imgdrv->change_state)
 
85
                return 0;
 
86
        return imgdrv->change_state(imgdev, state);
 
87
}
 
88
 
 
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)
 
92
{
 
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;
 
96
 
 
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");
 
101
                return -EINVAL;
 
102
        }
 
103
 
 
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");
 
108
                return -EINVAL;
 
109
        }
 
110
 
 
111
        if (!fpi_img_is_sane(img)) {
 
112
                fp_err("image is not sane!");
 
113
                return -EINVAL;
 
114
        }
 
115
 
 
116
        return 0;
 
117
}
 
118
 
 
119
void fpi_imgdev_report_finger_status(struct fp_img_dev *imgdev,
 
120
        gboolean present)
 
121
{
 
122
        int r = imgdev->action_result;
 
123
        struct fp_print_data *data = imgdev->acquire_data;
 
124
        struct fp_img *img = imgdev->acquire_img;
 
125
 
 
126
        fp_dbg(present ? "finger on sensor" : "finger removed");
 
127
 
 
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;
 
131
                return;
 
132
        } else if (present
 
133
                        || imgdev->action_state != IMG_ACQUIRE_STATE_AWAIT_FINGER_OFF) {
 
134
                fp_dbg("ignoring status report");
 
135
                return;
 
136
        }
 
137
 
 
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;
 
142
 
 
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);
 
152
                }
 
153
                break;
 
154
        case IMG_ACTION_VERIFY:
 
155
                fpi_drvcb_report_verify_result(imgdev->dev, r, img);
 
156
                fp_print_data_free(data);
 
157
                break;
 
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);
 
162
                break;
 
163
        default:
 
164
                fp_err("unhandled action %d", imgdev->action);
 
165
                break;
 
166
        }
 
167
}
 
168
 
 
169
static void verify_process_img(struct fp_img_dev *imgdev)
 
170
{
 
171
        struct fp_img_driver *imgdrv = fpi_driver_to_img_driver(imgdev->dev->drv);
 
172
        int match_score = imgdrv->bz3_threshold;
 
173
        int r;
 
174
 
 
175
        if (match_score == 0)
 
176
                match_score = BOZORTH3_DEFAULT_THRESHOLD;
 
177
 
 
178
        r = fpi_img_compare_print_data(imgdev->dev->verify_data,
 
179
                imgdev->acquire_data);
 
180
 
 
181
        if (r >= match_score)
 
182
                r = FP_VERIFY_MATCH;
 
183
        else if (r >= 0)
 
184
                r = FP_VERIFY_NO_MATCH;
 
185
 
 
186
        imgdev->action_result = r;
 
187
}
 
188
 
 
189
static void identify_process_img(struct fp_img_dev *imgdev)
 
190
{
 
191
        struct fp_img_driver *imgdrv = fpi_driver_to_img_driver(imgdev->dev->drv);
 
192
        int match_score = imgdrv->bz3_threshold;
 
193
        size_t match_offset;
 
194
        int r;
 
195
 
 
196
        if (match_score == 0)
 
197
                match_score = BOZORTH3_DEFAULT_THRESHOLD;
 
198
 
 
199
        r = fpi_img_compare_print_data_to_gallery(imgdev->acquire_data,
 
200
                imgdev->dev->identify_gallery, match_score, &match_offset);
 
201
 
 
202
        imgdev->action_result = r;
 
203
        imgdev->identify_match_offset = match_offset;
 
204
}
 
205
 
 
206
void fpi_imgdev_image_captured(struct fp_img_dev *imgdev, struct fp_img *img)
 
207
{
 
208
        struct fp_print_data *print;
 
209
        int r;
 
210
        fp_dbg("");
 
211
 
 
212
        if (imgdev->action_state != IMG_ACQUIRE_STATE_AWAIT_IMAGE) {
 
213
                fp_dbg("ignoring due to current state %d", imgdev->action_state);
 
214
                return;
 
215
        }
 
216
 
 
217
        if (imgdev->action_result) {
 
218
                fp_dbg("not overwriting existing action result");
 
219
                return;
 
220
        }
 
221
 
 
222
        r = sanitize_image(imgdev, &img);
 
223
        if (r < 0) {
 
224
                imgdev->action_result = r;
 
225
                fp_img_free(img);
 
226
                goto next_state;
 
227
        }
 
228
 
 
229
        fp_img_standardize(img);
 
230
        imgdev->acquire_img = img;
 
231
        r = fpi_img_to_print_data(imgdev, img, &print);
 
232
        if (r < 0) {
 
233
                fp_dbg("image to print data conversion error: %d", r);
 
234
                imgdev->action_result = FP_ENROLL_RETRY;
 
235
                goto next_state;
 
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;
 
242
                goto next_state;
 
243
        }
 
244
 
 
245
        imgdev->acquire_data = print;
 
246
        switch (imgdev->action) {
 
247
        case IMG_ACTION_ENROLL:
 
248
                imgdev->action_result = FP_ENROLL_COMPLETE;
 
249
                break;
 
250
        case IMG_ACTION_VERIFY:
 
251
                verify_process_img(imgdev);
 
252
                break;
 
253
        case IMG_ACTION_IDENTIFY:
 
254
                identify_process_img(imgdev);
 
255
                break;
 
256
        default:
 
257
                BUG();
 
258
                break;
 
259
        }
 
260
 
 
261
next_state:
 
262
        imgdev->action_state = IMG_ACQUIRE_STATE_AWAIT_FINGER_OFF;
 
263
        dev_change_state(imgdev, IMGDEV_STATE_AWAIT_FINGER_OFF);
 
264
}
 
265
 
 
266
void fpi_imgdev_session_error(struct fp_img_dev *imgdev, int error)
 
267
{
 
268
        fp_dbg("error %d", error);
 
269
        BUG_ON(error == 0);
 
270
        switch (imgdev->action) {
 
271
        case IMG_ACTION_ENROLL:
 
272
                fpi_drvcb_enroll_stage_completed(imgdev->dev, error, NULL, NULL);
 
273
                break;
 
274
        case IMG_ACTION_VERIFY:
 
275
                fpi_drvcb_report_verify_result(imgdev->dev, error, NULL);
 
276
                break;
 
277
        case IMG_ACTION_IDENTIFY:
 
278
                fpi_drvcb_report_identify_result(imgdev->dev, error, 0, NULL);
 
279
                break;
 
280
        default:
 
281
                fp_err("unhandled action %d", imgdev->action);
 
282
                break;
 
283
        }
 
284
}
 
285
 
 
286
void fpi_imgdev_activate_complete(struct fp_img_dev *imgdev, int status)
 
287
{
 
288
        fp_dbg("status %d", status);
 
289
 
 
290
        switch (imgdev->action) {
 
291
        case IMG_ACTION_ENROLL:
 
292
                fpi_drvcb_enroll_started(imgdev->dev, status);
 
293
                break;
 
294
        case IMG_ACTION_VERIFY:
 
295
                fpi_drvcb_verify_started(imgdev->dev, status);
 
296
                break;
 
297
        case IMG_ACTION_IDENTIFY:
 
298
                fpi_drvcb_identify_started(imgdev->dev, status);
 
299
                break;
 
300
        default:
 
301
                fp_err("unhandled action %d", imgdev->action);
 
302
                return;
 
303
        }
 
304
 
 
305
        if (status == 0) {
 
306
                imgdev->action_state = IMG_ACQUIRE_STATE_AWAIT_FINGER_ON;
 
307
                dev_change_state(imgdev, IMGDEV_STATE_AWAIT_FINGER_ON);
 
308
        }
 
309
}
 
310
 
 
311
void fpi_imgdev_deactivate_complete(struct fp_img_dev *imgdev)
 
312
{
 
313
        fp_dbg("");
 
314
 
 
315
        switch (imgdev->action) {
 
316
        case IMG_ACTION_ENROLL:
 
317
                fpi_drvcb_enroll_stopped(imgdev->dev);
 
318
                break;
 
319
        case IMG_ACTION_VERIFY:
 
320
                fpi_drvcb_verify_stopped(imgdev->dev);
 
321
                break;
 
322
        case IMG_ACTION_IDENTIFY:
 
323
                fpi_drvcb_identify_stopped(imgdev->dev);
 
324
                break;
 
325
        default:
 
326
                fp_err("unhandled action %d", imgdev->action);
 
327
                break;
 
328
        }
 
329
 
 
330
        imgdev->action = IMG_ACTION_NONE;
 
331
        imgdev->action_state = 0;
 
332
}
 
333
 
 
334
int fpi_imgdev_get_img_width(struct fp_img_dev *imgdev)
 
335
{
 
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;
 
339
 
 
340
        if (width == -1)
 
341
                width = 0;
 
342
 
 
343
        return width;
 
344
}
 
345
 
 
346
int fpi_imgdev_get_img_height(struct fp_img_dev *imgdev)
 
347
{
 
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;
 
351
 
 
352
        if (height == -1)
 
353
                height = 0;
 
354
 
 
355
        return height;
 
356
}
 
357
 
 
358
static int dev_activate(struct fp_img_dev *imgdev, enum fp_imgdev_state state)
 
359
{
 
360
        struct fp_driver *drv = imgdev->dev->drv;
 
361
        struct fp_img_driver *imgdrv = fpi_driver_to_img_driver(drv);
 
362
 
 
363
        if (!imgdrv->activate)
 
364
                return 0;
 
365
        return imgdrv->activate(imgdev, state);
 
366
}
 
367
 
 
368
static void dev_deactivate(struct fp_img_dev *imgdev)
 
369
{
 
370
        struct fp_driver *drv = imgdev->dev->drv;
 
371
        struct fp_img_driver *imgdrv = fpi_driver_to_img_driver(drv);
 
372
 
 
373
        if (!imgdrv->deactivate)
 
374
                return;
 
375
        return imgdrv->deactivate(imgdev);
 
376
}
 
377
 
 
378
static int generic_acquire_start(struct fp_dev *dev, int action)
 
379
{
 
380
        struct fp_img_dev *imgdev = dev->priv;
 
381
        int r;
 
382
        fp_dbg("action %d", action);
 
383
        imgdev->action = action;
 
384
        imgdev->action_state = IMG_ACQUIRE_STATE_ACTIVATING;
 
385
 
 
386
        r = dev_activate(imgdev, IMGDEV_STATE_AWAIT_FINGER_ON);
 
387
        if (r < 0)
 
388
                fp_err("activation failed with error %d", r);
 
389
 
 
390
        return r;
 
391
 
 
392
}
 
393
 
 
394
static void generic_acquire_stop(struct fp_img_dev *imgdev)
 
395
{
 
396
        imgdev->action_state = IMG_ACQUIRE_STATE_DEACTIVATING;
 
397
        dev_deactivate(imgdev);
 
398
 
 
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;
 
404
}
 
405
 
 
406
static int img_dev_enroll_start(struct fp_dev *dev)
 
407
{
 
408
        return generic_acquire_start(dev, IMG_ACTION_ENROLL);
 
409
}
 
410
 
 
411
static int img_dev_verify_start(struct fp_dev *dev)
 
412
{
 
413
        return generic_acquire_start(dev, IMG_ACTION_VERIFY);
 
414
}
 
415
 
 
416
static int img_dev_identify_start(struct fp_dev *dev)
 
417
{
 
418
        return generic_acquire_start(dev, IMG_ACTION_IDENTIFY);
 
419
}
 
420
 
 
421
static int img_dev_enroll_stop(struct fp_dev *dev)
 
422
{
 
423
        struct fp_img_dev *imgdev = dev->priv;
 
424
        BUG_ON(imgdev->action != IMG_ACTION_ENROLL);
 
425
        generic_acquire_stop(imgdev);
 
426
        return 0;
 
427
}
 
428
 
 
429
static int img_dev_verify_stop(struct fp_dev *dev, gboolean iterating)
 
430
{
 
431
        struct fp_img_dev *imgdev = dev->priv;
 
432
        BUG_ON(imgdev->action != IMG_ACTION_VERIFY);
 
433
        generic_acquire_stop(imgdev);
 
434
        return 0;
 
435
}
 
436
 
 
437
static int img_dev_identify_stop(struct fp_dev *dev, gboolean iterating)
 
438
{
 
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;
 
443
        return 0;
 
444
}
 
445
 
 
446
void fpi_img_driver_setup(struct fp_img_driver *idriver)
 
447
{
 
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;
 
457
}
 
458