fpi-dev-img.c 17.1 KB
Newer Older
Daniel Drake's avatar
Daniel Drake committed
1
/*
2
 * Core imaging device functions for libfprint
3
 * Copyright (C) 2007-2008 Daniel Drake <dsd@gentoo.org>
Daniel Drake's avatar
Daniel Drake committed
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */

20
#include <errno.h>
21

Daniel Drake's avatar
Daniel Drake committed
22 23
#include <glib.h>

24
#include "fpi-dev-img.h"
25
#include "fpi-async.h"
26
#include "fp_internal.h"
Daniel Drake's avatar
Daniel Drake committed
27

28 29 30
/**
 * SECTION:fpi-dev-img
 * @title: Image device operations
31
 * @short_description: Image device operation functions
32 33 34 35 36 37
 *
 * As drivers work through different operations, they need to report back
 * to the core as to their internal state, so errors and successes can be
 * reported back to front-ends.
 */

38 39
#define MIN_ACCEPTABLE_MINUTIAE 10
#define BOZORTH3_DEFAULT_THRESHOLD 40
40
#define IMG_ENROLL_STAGES 5
41

42 43 44 45 46 47 48 49
/**
 * fpi_imgdev_get_action_state:
 * @imgdev: a #fp_img_dev imaging fingerprint device
 *
 * Returns the state of an imaging device while enrolling a fingerprint.
 *
 * Returns: a enum #fp_imgdev_enroll_state
 */
50 51 52 53 54 55
enum fp_imgdev_enroll_state
fpi_imgdev_get_action_state(struct fp_img_dev *imgdev)
{
	return imgdev->action_state;
}

56 57 58 59 60 61 62 63
/**
 * fpi_imgdev_get_action:
 * @imgdev: a #fp_img_dev imaging fingerprint device
 *
 * Returns the current action being performed by an imaging device.
 *
 * Returns: a enum #fp_imgdev_action
 */
64 65 66 67 68 69
enum fp_imgdev_action
fpi_imgdev_get_action(struct fp_img_dev *imgdev)
{
	return imgdev->action;
}

70 71 72 73 74 75 76 77
/**
 * fpi_imgdev_get_action_result:
 * @imgdev: a #fp_img_dev imaging fingerprint device
 *
 * Returns an integer representing the result of an action. Which enum
 * the result code is taken from depends on the current action being performed.
 * See #fp_capture_result, #fp_enroll_result and #fp_verify_result.
 */
78 79 80 81 82 83
int
fpi_imgdev_get_action_result(struct fp_img_dev *imgdev)
{
	return imgdev->action_result;
}

84 85 86 87 88 89 90 91
/**
 * fpi_imgdev_set_action_result:
 * @imgdev: a #fp_img_dev imaging fingerprint device
 * @action_result: an action result
 *
 * Drivers should use fpi_imgdev_image_captured() instead. This function
 * should not be used, and will be removed soon.
 */
92 93 94 95 96 97 98
void
fpi_imgdev_set_action_result(struct fp_img_dev *imgdev,
	int action_result)
{
	imgdev->action_result = action_result;
}

Daniel Drake's avatar
Daniel Drake committed
99
static int img_dev_open(struct fp_dev *dev, unsigned long driver_data)
100 101
{
	struct fp_img_dev *imgdev = g_malloc0(sizeof(*imgdev));
102
	struct fp_img_driver *imgdrv = fpi_driver_to_img_driver(dev->drv);
103 104
	int r = 0;

105 106 107 108
	/* Set up back pointers */
	dev->img_dev = imgdev;
	imgdev->parent = dev;

109 110
	imgdev->enroll_stage = 0;
	dev->nr_enroll_stages = IMG_ENROLL_STAGES;
111

Daniel Drake's avatar
Daniel Drake committed
112 113
	if (imgdrv->open) {
		r = imgdrv->open(imgdev, driver_data);
114 115
		if (r)
			goto err;
116
	} else {
Daniel Drake's avatar
Daniel Drake committed
117
		fpi_drvcb_open_complete(dev, 0);
118 119 120 121 122 123 124 125
	}

	return 0;
err:
	g_free(imgdev);
	return r;
}

126 127 128 129 130 131 132 133
/**
 * fpi_imgdev_open_complete:
 * @imgdev: a #fp_img_dev imaging fingerprint device
 * @status: an error code
 *
 * Function to call when the device has been opened, whether
 * successfully of not.
 */
Daniel Drake's avatar
Daniel Drake committed
134
void fpi_imgdev_open_complete(struct fp_img_dev *imgdev, int status)
135
{
136
	fpi_drvcb_open_complete(FP_DEV(imgdev), status);
137 138
}

Daniel Drake's avatar
Daniel Drake committed
139
static void img_dev_close(struct fp_dev *dev)
140
{
141
	struct fp_img_driver *imgdrv = fpi_driver_to_img_driver(dev->drv);
142

Daniel Drake's avatar
Daniel Drake committed
143
	if (imgdrv->close)
144
		imgdrv->close(dev->img_dev);
145
	else
Daniel Drake's avatar
Daniel Drake committed
146
		fpi_drvcb_close_complete(dev);
147 148
}

149 150 151 152 153 154
/**
 * fpi_imgdev_close_complete:
 * @imgdev: a #fp_img_dev imaging fingerprint device
 *
 * Function to call when the device has been closed.
 */
Daniel Drake's avatar
Daniel Drake committed
155
void fpi_imgdev_close_complete(struct fp_img_dev *imgdev)
156
{
157
	fpi_drvcb_close_complete(FP_DEV(imgdev));
158
	g_free(imgdev);
159 160
}

161 162
static int dev_change_state(struct fp_img_dev *imgdev,
	enum fp_imgdev_state state)
163
{
164
	struct fp_driver *drv = FP_DEV(imgdev)->drv;
165
	struct fp_img_driver *imgdrv = fpi_driver_to_img_driver(drv);
166

167 168 169
	if (!imgdrv->change_state)
		return 0;
	return imgdrv->change_state(imgdev, state);
170 171
}

172 173 174
/* check image properties and resize it if necessary. potentially returns a new
 * image after freeing the old one. */
static int sanitize_image(struct fp_img_dev *imgdev, struct fp_img **_img)
175
{
176
	struct fp_driver *drv = FP_DEV(imgdev)->drv;
177
	struct fp_img_driver *imgdrv = fpi_driver_to_img_driver(drv);
178
	struct fp_img *img = *_img;
179

180
	if (imgdrv->img_width > 0) {
181
		img->width = imgdrv->img_width;
182 183
	} else if (img->width <= 0) {
		fp_err("no image width assigned");
184
		return -EINVAL;
185 186 187
	}

	if (imgdrv->img_height > 0) {
188
		img->height = imgdrv->img_height;
189 190
	} else if (img->height <= 0) {
		fp_err("no image height assigned");
191
		return -EINVAL;
192 193
	}

194 195
	if (!fpi_img_is_sane(img)) {
		fp_err("image is not sane!");
196
		return -EINVAL;
197 198 199
	}

	return 0;
200 201
}

202 203 204 205 206 207 208 209
/**
 * fpi_imgdev_report_finger_status:
 * @imgdev: a #fp_img_dev imaging fingerprint device
 * @present: whether the finger is present on the sensor
 *
 * Reports from the driver whether the user's finger is on
 * the sensor.
 */
210 211 212 213
void fpi_imgdev_report_finger_status(struct fp_img_dev *imgdev,
	gboolean present)
{
	int r = imgdev->action_result;
Daniel Drake's avatar
Daniel Drake committed
214 215 216
	struct fp_print_data *data = imgdev->acquire_data;
	struct fp_img *img = imgdev->acquire_img;

217 218 219 220 221 222 223 224 225 226 227 228
	fp_dbg(present ? "finger on sensor" : "finger removed");

	if (present && imgdev->action_state == IMG_ACQUIRE_STATE_AWAIT_FINGER_ON) {
		dev_change_state(imgdev, IMGDEV_STATE_CAPTURE);
		imgdev->action_state = IMG_ACQUIRE_STATE_AWAIT_IMAGE;
		return;
	} else if (present
			|| imgdev->action_state != IMG_ACQUIRE_STATE_AWAIT_FINGER_OFF) {
		fp_dbg("ignoring status report");
		return;
	}

Daniel Drake's avatar
Daniel Drake committed
229 230 231 232 233 234
	/* clear these before reporting results to avoid complications with
	 * call cascading in and out of the library */
	imgdev->acquire_img = NULL;
	imgdev->acquire_data = NULL;

	/* finger removed, report results */
235 236
	switch (imgdev->action) {
	case IMG_ACTION_ENROLL:
Daniel Drake's avatar
Daniel Drake committed
237
		fp_dbg("reporting enroll result");
238 239 240 241
		data = imgdev->enroll_data;
		if (r == FP_ENROLL_COMPLETE) {
			imgdev->enroll_data = NULL;
		}
242
		fpi_drvcb_enroll_stage_completed(FP_DEV(imgdev), r,
243 244
			r == FP_ENROLL_COMPLETE ? data : NULL,
			img);
245 246 247 248
		/* the callback can cancel enrollment, so recheck current
		 * action and the status to see if retry is needed */
		if (imgdev->action == IMG_ACTION_ENROLL &&
		    r > 0 && r != FP_ENROLL_COMPLETE && r != FP_ENROLL_FAIL) {
249 250
			imgdev->action_result = 0;
			imgdev->action_state = IMG_ACQUIRE_STATE_AWAIT_FINGER_ON;
251
			dev_change_state(imgdev, IMGDEV_STATE_AWAIT_FINGER_ON);
252
		}
253 254
		break;
	case IMG_ACTION_VERIFY:
255
		fpi_drvcb_report_verify_result(FP_DEV(imgdev), r, img);
256
		imgdev->action_result = 0;
Daniel Drake's avatar
Daniel Drake committed
257
		fp_print_data_free(data);
258 259
		break;
	case IMG_ACTION_IDENTIFY:
260
		fpi_drvcb_report_identify_result(FP_DEV(imgdev), r,
Daniel Drake's avatar
Daniel Drake committed
261
			imgdev->identify_match_offset, img);
262
		imgdev->action_result = 0;
Daniel Drake's avatar
Daniel Drake committed
263
		fp_print_data_free(data);
Daniel Drake's avatar
Daniel Drake committed
264
		break;
265
	case IMG_ACTION_CAPTURE:
266
		fpi_drvcb_report_capture_result(FP_DEV(imgdev), r, img);
267
		imgdev->action_result = 0;
268
		break;
269 270 271 272 273
	default:
		fp_err("unhandled action %d", imgdev->action);
		break;
	}
}
274

275
static void verify_process_img(struct fp_img_dev *imgdev)
276
{
277
	struct fp_img_driver *imgdrv = fpi_driver_to_img_driver(FP_DEV(imgdev)->drv);
278
	int match_score = imgdrv->bz3_threshold;
279 280
	int r;

281 282
	if (match_score == 0)
		match_score = BOZORTH3_DEFAULT_THRESHOLD;
283

284
	r = fpi_img_compare_print_data(FP_DEV(imgdev)->verify_data,
285
		imgdev->acquire_data);
286

287 288 289 290
	if (r >= match_score)
		r = FP_VERIFY_MATCH;
	else if (r >= 0)
		r = FP_VERIFY_NO_MATCH;
291

292
	imgdev->action_result = r;
293 294
}

295 296
static void identify_process_img(struct fp_img_dev *imgdev)
{
297
	struct fp_img_driver *imgdrv = fpi_driver_to_img_driver(FP_DEV(imgdev)->drv);
298 299 300 301 302 303 304 305
	int match_score = imgdrv->bz3_threshold;
	size_t match_offset;
	int r;

	if (match_score == 0)
		match_score = BOZORTH3_DEFAULT_THRESHOLD;

	r = fpi_img_compare_print_data_to_gallery(imgdev->acquire_data,
306
		FP_DEV(imgdev)->identify_gallery, match_score, &match_offset);
307

308 309 310 311
	imgdev->action_result = r;
	imgdev->identify_match_offset = match_offset;
}

312 313 314 315 316 317 318 319
/**
 * fpi_imgdev_abort_scan:
 * @imgdev: a #fp_img_dev imaging fingerprint device
 * @result: the scan result
 *
 * Aborts a scan after an error, and set the action result. See
 * fpi_imgdev_get_action_result() for possible values.
 */
320 321 322 323 324 325 326
void fpi_imgdev_abort_scan(struct fp_img_dev *imgdev, int result)
{
	imgdev->action_result = result;
	imgdev->action_state = IMG_ACQUIRE_STATE_AWAIT_FINGER_OFF;
	dev_change_state(imgdev, IMGDEV_STATE_AWAIT_FINGER_OFF);
}

327 328 329 330 331 332 333
/**
 * fpi_imgdev_image_captured:
 * @imgdev: a #fp_img_dev imaging fingerprint device
 * @img: an #fp_img image
 *
 * Report to the core that the driver captured this image from the sensor.
 */
334
void fpi_imgdev_image_captured(struct fp_img_dev *imgdev, struct fp_img *img)
335
{
336
	struct fp_print_data *print = NULL;
337
	int r;
338
	G_DEBUG_HERE();
339

340 341 342 343
	if (imgdev->action_state != IMG_ACQUIRE_STATE_AWAIT_IMAGE) {
		fp_dbg("ignoring due to current state %d", imgdev->action_state);
		return;
	}
344

345 346 347 348
	if (imgdev->action_result) {
		fp_dbg("not overwriting existing action result");
		return;
	}
349

350 351 352 353 354 355 356 357 358
	r = sanitize_image(imgdev, &img);
	if (r < 0) {
		imgdev->action_result = r;
		fp_img_free(img);
		goto next_state;
	}

	fp_img_standardize(img);
	imgdev->acquire_img = img;
359 360 361 362 363 364 365 366 367 368 369 370 371 372
	if (imgdev->action != IMG_ACTION_CAPTURE) {
		r = fpi_img_to_print_data(imgdev, img, &print);
		if (r < 0) {
			fp_dbg("image to print data conversion error: %d", r);
			imgdev->action_result = FP_ENROLL_RETRY;
			goto next_state;
		} else if (img->minutiae->num < MIN_ACCEPTABLE_MINUTIAE) {
			fp_dbg("not enough minutiae, %d/%d", img->minutiae->num,
				MIN_ACCEPTABLE_MINUTIAE);
			fp_print_data_free(print);
			/* depends on FP_ENROLL_RETRY == FP_VERIFY_RETRY */
			imgdev->action_result = FP_ENROLL_RETRY;
			goto next_state;
		}
373 374
	}

375 376 377
	imgdev->acquire_data = print;
	switch (imgdev->action) {
	case IMG_ACTION_ENROLL:
378
		if (!imgdev->enroll_data) {
379
			imgdev->enroll_data = fpi_print_data_new(FP_DEV(imgdev));
380 381 382 383 384 385 386 387 388 389
		}
		BUG_ON(g_slist_length(print->prints) != 1);
		/* Move print data from acquire data into enroll_data */
		imgdev->enroll_data->prints =
			g_slist_prepend(imgdev->enroll_data->prints, print->prints->data);
		print->prints = g_slist_remove(print->prints, print->prints->data);

		fp_print_data_free(imgdev->acquire_data);
		imgdev->acquire_data = NULL;
		imgdev->enroll_stage++;
390
		if (imgdev->enroll_stage == FP_DEV(imgdev)->nr_enroll_stages)
391 392 393
			imgdev->action_result = FP_ENROLL_COMPLETE;
		else
			imgdev->action_result = FP_ENROLL_PASS;
394 395 396 397 398 399 400
		break;
	case IMG_ACTION_VERIFY:
		verify_process_img(imgdev);
		break;
	case IMG_ACTION_IDENTIFY:
		identify_process_img(imgdev);
		break;
401 402 403
	case IMG_ACTION_CAPTURE:
		imgdev->action_result = FP_CAPTURE_COMPLETE;
		break;
404 405 406 407
	default:
		BUG();
		break;
	}
408

409 410 411
next_state:
	imgdev->action_state = IMG_ACQUIRE_STATE_AWAIT_FINGER_OFF;
	dev_change_state(imgdev, IMGDEV_STATE_AWAIT_FINGER_OFF);
412 413
}

414 415 416 417 418 419 420
/**
 * fpi_imgdev_session_error:
 * @imgdev: a #fp_img_dev imaging fingerprint device
 * @error: an error code
 *
 * Report an error that occurred in the driver.
 */
421
void fpi_imgdev_session_error(struct fp_img_dev *imgdev, int error)
422
{
423 424 425 426
	fp_dbg("error %d", error);
	BUG_ON(error == 0);
	switch (imgdev->action) {
	case IMG_ACTION_ENROLL:
427
		fpi_drvcb_enroll_stage_completed(FP_DEV(imgdev), error, NULL, NULL);
428 429
		break;
	case IMG_ACTION_VERIFY:
430
		fpi_drvcb_report_verify_result(FP_DEV(imgdev), error, NULL);
431 432
		break;
	case IMG_ACTION_IDENTIFY:
433
		fpi_drvcb_report_identify_result(FP_DEV(imgdev), error, 0, NULL);
434
		break;
435
	case IMG_ACTION_CAPTURE:
436
		fpi_drvcb_report_capture_result(FP_DEV(imgdev), error, NULL);
437
		break;
438 439 440 441 442
	default:
		fp_err("unhandled action %d", imgdev->action);
		break;
	}
}
443

444 445 446 447 448 449 450 451
/**
 * fpi_imgdev_activate_complete:
 * @imgdev: a #fp_img_dev imaging fingerprint device
 * @status: the activation result
 *
 * Marks an activation as complete, whether successful or not.
 * See fpi_imgdev_get_action_result() for possible values.
 */
452 453 454 455 456 457
void fpi_imgdev_activate_complete(struct fp_img_dev *imgdev, int status)
{
	fp_dbg("status %d", status);

	switch (imgdev->action) {
	case IMG_ACTION_ENROLL:
458
		fpi_drvcb_enroll_started(FP_DEV(imgdev), status);
459 460
		break;
	case IMG_ACTION_VERIFY:
461
		fpi_drvcb_verify_started(FP_DEV(imgdev), status);
462 463
		break;
	case IMG_ACTION_IDENTIFY:
464
		fpi_drvcb_identify_started(FP_DEV(imgdev), status);
465
		break;
466
	case IMG_ACTION_CAPTURE:
467
		fpi_drvcb_capture_started(FP_DEV(imgdev), status);
468
		break;
469 470 471 472
	default:
		fp_err("unhandled action %d", imgdev->action);
		return;
	}
473

474 475 476 477 478
	if (status == 0) {
		imgdev->action_state = IMG_ACQUIRE_STATE_AWAIT_FINGER_ON;
		dev_change_state(imgdev, IMGDEV_STATE_AWAIT_FINGER_ON);
	}
}
479

480 481 482 483 484 485
/**
 * fpi_imgdev_deactivate_complete:
 * @imgdev: a #fp_img_dev imaging fingerprint device
 *
 * Marks a deactivation as complete.
 */
486 487
void fpi_imgdev_deactivate_complete(struct fp_img_dev *imgdev)
{
488
	G_DEBUG_HERE();
489 490 491

	switch (imgdev->action) {
	case IMG_ACTION_ENROLL:
492
		fpi_drvcb_enroll_stopped(FP_DEV(imgdev));
493 494
		break;
	case IMG_ACTION_VERIFY:
495
		fpi_drvcb_verify_stopped(FP_DEV(imgdev));
496 497
		break;
	case IMG_ACTION_IDENTIFY:
498
		fpi_drvcb_identify_stopped(FP_DEV(imgdev));
499
		break;
500
	case IMG_ACTION_CAPTURE:
501
		fpi_drvcb_capture_stopped(FP_DEV(imgdev));
502
		break;
503 504 505
	default:
		fp_err("unhandled action %d", imgdev->action);
		break;
506 507
	}

508 509 510 511 512 513
	imgdev->action = IMG_ACTION_NONE;
	imgdev->action_state = 0;
}

int fpi_imgdev_get_img_width(struct fp_img_dev *imgdev)
{
514
	struct fp_driver *drv = FP_DEV(imgdev)->drv;
515 516 517
	struct fp_img_driver *imgdrv = fpi_driver_to_img_driver(drv);
	int width = imgdrv->img_width;

518
	if (width == -1)
519 520 521 522 523 524 525
		width = 0;

	return width;
}

int fpi_imgdev_get_img_height(struct fp_img_dev *imgdev)
{
526
	struct fp_driver *drv = FP_DEV(imgdev)->drv;
527 528 529
	struct fp_img_driver *imgdrv = fpi_driver_to_img_driver(drv);
	int height = imgdrv->img_height;

530
	if (height == -1)
531 532 533 534 535 536 537
		height = 0;

	return height;
}

static int dev_activate(struct fp_img_dev *imgdev, enum fp_imgdev_state state)
{
538
	struct fp_driver *drv = FP_DEV(imgdev)->drv;
539 540 541 542 543 544 545 546 547
	struct fp_img_driver *imgdrv = fpi_driver_to_img_driver(drv);

	if (!imgdrv->activate)
		return 0;
	return imgdrv->activate(imgdev, state);
}

static void dev_deactivate(struct fp_img_dev *imgdev)
{
548
	struct fp_driver *drv = FP_DEV(imgdev)->drv;
549 550
	struct fp_img_driver *imgdrv = fpi_driver_to_img_driver(drv);

551
	if (!imgdrv->deactivate)
552 553 554 555 556 557
		return;
	return imgdrv->deactivate(imgdev);
}

static int generic_acquire_start(struct fp_dev *dev, int action)
{
558
	struct fp_img_dev *imgdev = dev->img_dev;
559 560 561 562
	int r;
	fp_dbg("action %d", action);
	imgdev->action = action;
	imgdev->action_state = IMG_ACQUIRE_STATE_ACTIVATING;
563
	imgdev->enroll_stage = 0;
564 565 566 567

	r = dev_activate(imgdev, IMGDEV_STATE_AWAIT_FINGER_ON);
	if (r < 0)
		fp_err("activation failed with error %d", r);
568 569

	return r;
570 571 572 573 574 575 576 577 578

}

static void generic_acquire_stop(struct fp_img_dev *imgdev)
{
	imgdev->action_state = IMG_ACQUIRE_STATE_DEACTIVATING;
	dev_deactivate(imgdev);

	fp_print_data_free(imgdev->acquire_data);
579
	fp_print_data_free(imgdev->enroll_data);
580 581
	fp_img_free(imgdev->acquire_img);
	imgdev->acquire_data = NULL;
582
	imgdev->enroll_data = NULL;
583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601
	imgdev->acquire_img = NULL;
	imgdev->action_result = 0;
}

static int img_dev_enroll_start(struct fp_dev *dev)
{
	return generic_acquire_start(dev, IMG_ACTION_ENROLL);
}

static int img_dev_verify_start(struct fp_dev *dev)
{
	return generic_acquire_start(dev, IMG_ACTION_VERIFY);
}

static int img_dev_identify_start(struct fp_dev *dev)
{
	return generic_acquire_start(dev, IMG_ACTION_IDENTIFY);
}

602 603 604 605 606 607 608 609
static int img_dev_capture_start(struct fp_dev *dev)
{
	/* Unconditional capture is not supported yet */
	if (dev->unconditional_capture)
		return -ENOTSUP;
	return generic_acquire_start(dev, IMG_ACTION_CAPTURE);
}

610 611
static int img_dev_enroll_stop(struct fp_dev *dev)
{
612
	struct fp_img_dev *imgdev = dev->img_dev;
613 614 615 616 617 618 619
	BUG_ON(imgdev->action != IMG_ACTION_ENROLL);
	generic_acquire_stop(imgdev);
	return 0;
}

static int img_dev_verify_stop(struct fp_dev *dev, gboolean iterating)
{
620
	struct fp_img_dev *imgdev = dev->img_dev;
621 622 623 624 625 626 627
	BUG_ON(imgdev->action != IMG_ACTION_VERIFY);
	generic_acquire_stop(imgdev);
	return 0;
}

static int img_dev_identify_stop(struct fp_dev *dev, gboolean iterating)
{
628
	struct fp_img_dev *imgdev = dev->img_dev;
629 630 631 632
	BUG_ON(imgdev->action != IMG_ACTION_IDENTIFY);
	generic_acquire_stop(imgdev);
	imgdev->identify_match_offset = 0;
	return 0;
633 634
}

635 636
static int img_dev_capture_stop(struct fp_dev *dev)
{
637
	struct fp_img_dev *imgdev = dev->img_dev;
638 639 640 641 642
	BUG_ON(imgdev->action != IMG_ACTION_CAPTURE);
	generic_acquire_stop(imgdev);
	return 0;
}

Daniel Drake's avatar
Daniel Drake committed
643 644 645
void fpi_img_driver_setup(struct fp_img_driver *idriver)
{
	idriver->driver.type = DRIVER_IMAGING;
Daniel Drake's avatar
Daniel Drake committed
646 647
	idriver->driver.open = img_dev_open;
	idriver->driver.close = img_dev_close;
648 649 650 651 652 653
	idriver->driver.enroll_start = img_dev_enroll_start;
	idriver->driver.enroll_stop = img_dev_enroll_stop;
	idriver->driver.verify_start = img_dev_verify_start;
	idriver->driver.verify_stop = img_dev_verify_stop;
	idriver->driver.identify_start = img_dev_identify_start;
	idriver->driver.identify_stop = img_dev_identify_stop;
654 655
	idriver->driver.capture_start = img_dev_capture_start;
	idriver->driver.capture_stop = img_dev_capture_stop;
Daniel Drake's avatar
Daniel Drake committed
656 657
}