fpi-sync.c 19.3 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
/*
 * Synchronous I/O functionality
 * Copyright (C) 2007-2008 Daniel Drake <dsd@gentoo.org>
 *
 * 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
 */

#define FP_COMPONENT "sync"

22
#include "fp_internal.h"
23
#include "fpi-dev.h"
24

25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
#include <config.h>
#include <errno.h>

struct sync_open_data {
	struct fp_dev *dev;
	int status;
};

static void sync_open_cb(struct fp_dev *dev, int status, void *user_data)
{
	struct sync_open_data *odata = user_data;
	fp_dbg("status %d", status);
	odata->dev = dev;
	odata->status = status;
}

41 42
/**
 * fp_dev_open:
43
 * @ddev: the struct #fp_dscv_dev discovered device to open
44
 *
45
 * Opens and initialises a device. This is the function you call in order
46
 * to convert a #fp_dscv_dev discovered device into an actual device handle
47
 * that you can perform operations with.
48
 *
49
 * Returns: the opened device handle, or %NULL on error
50 51 52 53 54 55 56
 */
API_EXPORTED struct fp_dev *fp_dev_open(struct fp_dscv_dev *ddev)
{
	struct fp_dev *dev = NULL;
	struct sync_open_data *odata = g_malloc0(sizeof(*odata));
	int r;

57
	G_DEBUG_HERE();
58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
	r = fp_async_dev_open(ddev, sync_open_cb, odata);
	if (r)
		goto out;

	while (!odata->dev)
		if (fp_handle_events() < 0)
			goto out;

	if (odata->status == 0)
		dev = odata->dev;
	else
		fp_dev_close(odata->dev);

out:
	g_free(odata);
	return dev;
}

static void sync_close_cb(struct fp_dev *dev, void *user_data)
{
78
	G_DEBUG_HERE();
79 80 81 82
	gboolean *closed = user_data;
	*closed = TRUE;
}

83 84
/**
 * fp_dev_close:
85
 * @dev: the struct #fp_dev device to close. If %NULL, function simply returns
86
 *
87
 * Closes a device. You must call this function when you have finished using
88 89 90 91 92 93 94 95 96
 * a fingerprint device.
 */
API_EXPORTED void fp_dev_close(struct fp_dev *dev)
{
	gboolean closed = FALSE;

	if (!dev)
		return;

97
	G_DEBUG_HERE();
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124
	fp_async_dev_close(dev, sync_close_cb, &closed);
	while (!closed)
		if (fp_handle_events() < 0)
			break;
}

struct sync_enroll_data {
	gboolean populated;
	int result;
	struct fp_print_data *data;
	struct fp_img *img;
};

static void sync_enroll_cb(struct fp_dev *dev, int result,
	struct fp_print_data *data, struct fp_img *img, void *user_data)
{
	struct sync_enroll_data *edata = user_data;
	fp_dbg("result %d", result);
	edata->result = result;
	edata->data = data;
	edata->img = img;
	edata->populated = TRUE;
}

static void enroll_stop_cb(struct fp_dev *dev, void *user_data)
{
	gboolean *stopped = user_data;
125
	G_DEBUG_HERE();
126 127 128
	*stopped = TRUE;
}

129 130
/**
 * fp_enroll_finger_img:
131
 * @dev: the struct #fp_dev device
132
 * @print_data: a location to return the resultant enrollment data from
133
 * the final stage. Must be freed with fp_print_data_free() after use
134 135
 * @img: location to store the scan image. accepts %NULL for no image
 * storage. If an image is returned, it must be freed with fp_img_free() after
136
 * use
137 138 139
 *
 * Performs an enroll stage. See [Enrolling](libfprint-Devices-operations.html#enrolling)
 * for an explanation of enroll stages.
140 141 142 143 144 145 146 147 148 149 150 151 152 153
 *
 * If no enrollment is in process, this kicks of the process and runs the
 * first stage. If an enrollment is already in progress, calling this
 * function runs the next stage, which may well be the last.
 *
 * A negative error code may be returned from any stage. When this occurs,
 * further calls to the enroll function will start a new enrollment process,
 * i.e. a negative error code indicates that the enrollment process has been
 * aborted. These error codes only ever indicate unexpected internal errors
 * or I/O problems.
 *
 * The RETRY codes from #fp_enroll_result may be returned from any enroll
 * stage. These codes indicate that the scan was not succesful in that the
 * user did not position their finger correctly or similar. When a RETRY code
154
 * is returned, the enrollment stage is <emphasis role="strong">not</emphasis> advanced, so the next call
155 156 157
 * into this function will retry the current stage again. The current stage may
 * need to be retried several times.
 *
158
 * The %FP_ENROLL_FAIL code may be returned from any enroll
159 160 161 162 163 164
 * stage. This code indicates that even though the scans themselves have been
 * acceptable, data processing applied to these scans produces incomprehensible
 * results. In other words, the user may have been scanning a different finger
 * for each stage or something like that. Like negative error codes, this
 * return code indicates that the enrollment process has been aborted.
 *
165
 * The %FP_ENROLL_PASS code will only ever be returned for
166 167 168 169
 * non-final stages. This return code indicates that the scan was acceptable
 * and the next call into this function will advance onto the next enroll
 * stage.
 *
170
 * The %FP_ENROLL_COMPLETE code will only ever be returned
171 172 173 174 175
 * from the final enroll stage. It indicates that enrollment completed
 * successfully, and that print_data has been assigned to point to the
 * resultant enrollment data. The print_data parameter will not be modified
 * during any other enrollment stages, hence it is actually legal to pass NULL
 * as this argument for all but the final stage.
176
 *
177 178 179 180 181
 * If the device is an imaging device, it can also return the image from
 * the scan, even when the enroll fails with a RETRY or FAIL code. It is legal
 * to call this function even on non-imaging devices, just don't expect them to
 * provide images.
 *
182
 * Returns: negative code on error, otherwise a code from #fp_enroll_result
183 184 185 186 187 188 189 190
 */
API_EXPORTED int fp_enroll_finger_img(struct fp_dev *dev,
	struct fp_print_data **print_data, struct fp_img **img)
{
	struct fp_driver *drv = dev->drv;
	int stage = dev->__enroll_stage;
	gboolean final = FALSE;
	gboolean stopped = FALSE;
191
	struct sync_enroll_data *edata = NULL;
192
	int r;
193
	G_DEBUG_HERE();
194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273

	/* FIXME __enroll_stage is ugly, can we replace it by some function that
	 * says whether we're enrolling or not, and then put __enroll_stage into
	 * edata? */

	if (stage == -1) {
		edata = g_malloc0(sizeof(struct sync_enroll_data));
		r = fp_async_enroll_start(dev, sync_enroll_cb, edata);
		if (r < 0) {
			g_free(edata);
			return r;
		}

		dev->__enroll_stage = ++stage;
	} else if (stage >= dev->nr_enroll_stages) {
		fp_err("exceeding number of enroll stages for device claimed by "
			"driver %s (%d stages)", drv->name, dev->nr_enroll_stages);
		dev->__enroll_stage = -1;
		r = -EINVAL;
		final = TRUE;
		goto out;
	}
	fp_dbg("%s will handle enroll stage %d/%d", drv->name, stage,
		dev->nr_enroll_stages - 1);

	/* FIXME this isn't very clean */
	edata = dev->enroll_stage_cb_data;

	while (!edata->populated) {
		r = fp_handle_events();
		if (r < 0) {
			g_free(edata);
			goto err;
		}
	}

	edata->populated = FALSE;

	if (img)
		*img = edata->img;
	else
		fp_img_free(edata->img);

	r = edata->result;
	switch (r) {
	case FP_ENROLL_PASS:
		fp_dbg("enroll stage passed");
		dev->__enroll_stage = stage + 1;
		break;
	case FP_ENROLL_COMPLETE:
		fp_dbg("enroll complete");
		dev->__enroll_stage = -1;
		*print_data = edata->data;
		final = TRUE;
		break;
	case FP_ENROLL_RETRY:
		fp_dbg("enroll should retry");
		break;
	case FP_ENROLL_RETRY_TOO_SHORT:
		fp_dbg("swipe was too short, enroll should retry");
		break;
	case FP_ENROLL_RETRY_CENTER_FINGER:
		fp_dbg("finger was not centered, enroll should retry");
		break;
	case FP_ENROLL_RETRY_REMOVE_FINGER:
		fp_dbg("scan failed, remove finger and retry");
		break;
	case FP_ENROLL_FAIL:
		fp_err("enroll failed");
		dev->__enroll_stage = -1;
		final = TRUE;
		break;
	default:
		fp_err("unrecognised return code %d", r);
		dev->__enroll_stage = -1;
		r = -EINVAL;
		final = TRUE;
		break;
	}

274 275 276
	if (!final)
		return r;

277 278 279 280 281 282 283 284 285 286 287 288 289 290
out:
	if (final) {
		fp_dbg("ending enrollment");
		g_free(edata);
	}

err:
	if (fp_async_enroll_stop(dev, enroll_stop_cb, &stopped) == 0)
		while (!stopped)
			if (fp_handle_events() < 0)
				break;
	return r;
}

291 292
/**
 * fp_enroll_finger:
293
 * @dev: the struct #fp_dev device
294
 * @print_data: a location to return the resultant enrollment data from
295
 * the final stage. Must be freed with fp_print_data_free() after use
296 297 298 299 300 301 302 303 304 305 306 307 308 309
 *
 * Performs an enroll stage. See [Enrolling](libfprint-Devices-operations.html#enrolling)
 * for an explanation of enroll stages. This function is just a shortcut to
 * calling fp_enroll_finger_img() with a %NULL image parameter. Be sure to read
 * the description of fp_enroll_finger_img() in order to understand its behaviour.
 *
 * Returns: negative code on error, otherwise a code from #fp_enroll_result
 */
API_EXPORTED int fp_enroll_finger(struct fp_dev *dev,
	struct fp_print_data **print_data)
{
	return fp_enroll_finger_img(dev, print_data, NULL);
}

310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327
struct sync_verify_data {
	gboolean populated;
	int result;
	struct fp_img *img;
};

static void sync_verify_cb(struct fp_dev *dev, int result, struct fp_img *img,
	void *user_data)
{
	struct sync_verify_data *vdata = user_data;
	vdata->result = result;
	vdata->img = img;
	vdata->populated = TRUE;
}

static void verify_stop_cb(struct fp_dev *dev, void *user_data)
{
	gboolean *stopped = user_data;
328
	G_DEBUG_HERE();
329 330 331
	*stopped = TRUE;
}

332 333
/**
 * fp_verify_finger_img:
334
 * @dev: the struct #fp_dev device to perform the scan on
335
 * @enrolled_print: the print to verify against. Must have been previously
336
 * enrolled with a device compatible to the device selected to perform the scan
337 338
 * @img: location to store the scan image. accepts %NULL for no image
 * storage. If an image is returned, it must be freed with fp_img_free() after
339
 * use
340

341
 * Performs a new scan and verifies it against a previously enrolled print.
342 343 344 345 346
 * If the device is an imaging device, it can also return the image from
 * the scan, even when the verify fails with a RETRY code. It is legal to
 * call this function even on non-imaging devices, just don't expect them to
 * provide images.
 *
347
 * Returns: negative code on error, otherwise a code from #fp_verify_result
348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365
 */
API_EXPORTED int fp_verify_finger_img(struct fp_dev *dev,
	struct fp_print_data *enrolled_print, struct fp_img **img)
{
	struct sync_verify_data *vdata;
	gboolean stopped = FALSE;
	int r;

	if (!enrolled_print) {
		fp_err("no print given");
		return -EINVAL;
	}

	if (!fp_dev_supports_print_data(dev, enrolled_print)) {
		fp_err("print is not compatible with device");
		return -EINVAL;
	}

366
	fp_dbg("to be handled by %s", dev->drv->name);
367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423
	vdata = g_malloc0(sizeof(struct sync_verify_data));
	r = fp_async_verify_start(dev, enrolled_print, sync_verify_cb, vdata);
	if (r < 0) {
		fp_dbg("verify_start error %d", r);
		g_free(vdata);
		return r;
	}

	while (!vdata->populated) {
		r = fp_handle_events();
		if (r < 0) {
			g_free(vdata);
			goto err;
		}
	}

	if (img)
		*img = vdata->img;
	else
		fp_img_free(vdata->img);

	r = vdata->result;
	g_free(vdata);
	switch (r) {
	case FP_VERIFY_NO_MATCH:
		fp_dbg("result: no match");
		break;
	case FP_VERIFY_MATCH:
		fp_dbg("result: match");
		break;
	case FP_VERIFY_RETRY:
		fp_dbg("verify should retry");
		break;
	case FP_VERIFY_RETRY_TOO_SHORT:
		fp_dbg("swipe was too short, verify should retry");
		break;
	case FP_VERIFY_RETRY_CENTER_FINGER:
		fp_dbg("finger was not centered, verify should retry");
		break;
	case FP_VERIFY_RETRY_REMOVE_FINGER:
		fp_dbg("scan failed, remove finger and retry");
		break;
	default:
		fp_err("unrecognised return code %d", r);
		r = -EINVAL;
	}

err:
	fp_dbg("ending verification");
	if (fp_async_verify_stop(dev, verify_stop_cb, &stopped) == 0)
		while (!stopped)
			if (fp_handle_events() < 0)
				break;

	return r;
}

424 425
/**
 * fp_verify_finger:
426
 * @dev: the struct #fp_dev device to perform the scan on
427
 * @enrolled_print: the print to verify against. Must have been previously
428
 * enrolled with a device compatible to the device selected to perform the scan
429 430 431 432 433
 *
 * Performs a new scan and verify it against a previously enrolled print. This
 * function is just a shortcut to calling fp_verify_finger_img() with a NULL
 * image output parameter.
 *
434 435
 * See also fp_verify_finger_img().
 *
436 437 438 439 440 441 442 443
 * Returns: negative code on error, otherwise a code from #fp_verify_result
 */
API_EXPORTED int fp_verify_finger(struct fp_dev *dev,
	struct fp_print_data *enrolled_print)
{
	return fp_verify_finger_img(dev, enrolled_print, NULL);
}

444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463
struct sync_identify_data {
	gboolean populated;
	int result;
	size_t match_offset;
	struct fp_img *img;
};

static void sync_identify_cb(struct fp_dev *dev, int result,
	size_t match_offset, struct fp_img *img, void *user_data)
{
	struct sync_identify_data *idata = user_data;
	idata->result = result;
	idata->match_offset = match_offset;
	idata->img = img;
	idata->populated = TRUE;
}

static void identify_stop_cb(struct fp_dev *dev, void *user_data)
{
	gboolean *stopped = user_data;
464
	G_DEBUG_HERE();
465 466 467
	*stopped = TRUE;
}

468 469
/**
 * fp_identify_finger_img:
470
 * @dev: the struct #fp_dev device to perform the scan on
471 472
 * @print_gallery: NULL-terminated array of pointers to the prints to
 * identify against. Each one must have been previously enrolled with a device
473
 * compatible to the device selected to perform the scan
474
 * @match_offset: output location to store the array index of the matched
475
 * gallery print (if any was found). Only valid if %FP_VERIFY_MATCH was
476
 * returned
477 478
 * @img: location to store the scan image. accepts %NULL for no image
 * storage. If an image is returned, it must be freed with fp_img_free() after
479
 * use
480

481 482 483 484 485 486 487 488
 * Performs a new scan and attempts to identify the scanned finger against
 * a collection of previously enrolled fingerprints.
 * If the device is an imaging device, it can also return the image from
 * the scan, even when identification fails with a RETRY code. It is legal to
 * call this function even on non-imaging devices, just don't expect them to
 * provide images.
 *
 * This function returns codes from #fp_verify_result. The return code
489
 * %FP_VERIFY_MATCH indicates that the scanned fingerprint
490 491 492 493 494 495 496 497 498
 * does appear in the print gallery, and the match_offset output parameter
 * will indicate the index into the print gallery array of the matched print.
 *
 * This function will not necessarily examine the whole print gallery, it
 * will return as soon as it finds a matching print.
 *
 * Not all devices support identification. -ENOTSUP will be returned when
 * this is the case.
 *
499
 * Returns: negative code on error, otherwise a code from #fp_verify_result
500 501 502 503 504 505 506 507 508 509
 */
API_EXPORTED int fp_identify_finger_img(struct fp_dev *dev,
	struct fp_print_data **print_gallery, size_t *match_offset,
	struct fp_img **img)
{
	gboolean stopped = FALSE;
	struct sync_identify_data *idata
		= g_malloc0(sizeof(struct sync_identify_data));
	int r;

510
	fp_dbg("to be handled by %s", dev->drv->name);
511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528

	r = fp_async_identify_start(dev, print_gallery, sync_identify_cb, idata);
	if (r < 0) {
		fp_err("identify_start error %d", r);
		goto err;
	}

	while (!idata->populated) {
		r = fp_handle_events();
		if (r < 0)
			goto err_stop;
	}

	if (img)
		*img = idata->img;
	else
		fp_img_free(idata->img);

529
	r = idata->result;
530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565
	switch (idata->result) {
	case FP_VERIFY_NO_MATCH:
		fp_dbg("result: no match");
		break;
	case FP_VERIFY_MATCH:
		fp_dbg("result: match at offset %zd", idata->match_offset);
		*match_offset = idata->match_offset;
		break;
	case FP_VERIFY_RETRY:
		fp_dbg("verify should retry");
		break;
	case FP_VERIFY_RETRY_TOO_SHORT:
		fp_dbg("swipe was too short, verify should retry");
		break;
	case FP_VERIFY_RETRY_CENTER_FINGER:
		fp_dbg("finger was not centered, verify should retry");
		break;
	case FP_VERIFY_RETRY_REMOVE_FINGER:
		fp_dbg("scan failed, remove finger and retry");
		break;
	default:
		fp_err("unrecognised return code %d", r);
		r = -EINVAL;
	}

err_stop:
	if (fp_async_identify_stop(dev, identify_stop_cb, &stopped) == 0)
		while (!stopped)
			if (fp_handle_events() < 0)
				break;

err:
	g_free(idata);
	return r;
}

566 567
/**
 * fp_identify_finger:
568
 * @dev: the struct #fp_dev device to perform the scan on
569 570
 * @print_gallery: %NULL-terminated array of pointers to the prints to
 * identify against. Each one must have been previously enrolled with a device
571
 * compatible to the device selected to perform the scan
572
 * @match_offset: output location to store the array index of the matched
573
 * gallery print (if any was found). Only valid if %FP_VERIFY_MATCH was
574
 * returned
575 576 577 578 579 580

 * Performs a new scan and attempts to identify the scanned finger against a
 * collection of previously enrolled fingerprints. This function is just a
 * shortcut to calling fp_identify_finger_img() with a %NULL image output
 * parameter.
 *
581 582
 * See also fp_identify_finger_img().
 *
583 584 585 586 587 588 589 590
 * Returns: negative code on error, otherwise a code from #fp_verify_result
 */
API_EXPORTED int fp_identify_finger(struct fp_dev *dev,
	struct fp_print_data **print_gallery, size_t *match_offset)
{
	return fp_identify_finger_img(dev, print_gallery, match_offset, NULL);
}

591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608
struct sync_capture_data {
	gboolean populated;
	int result;
	struct fp_img *img;
};

static void sync_capture_cb(struct fp_dev *dev, int result, struct fp_img *img,
	void *user_data)
{
	struct sync_capture_data *vdata = user_data;
	vdata->result = result;
	vdata->img = img;
	vdata->populated = TRUE;
}

static void capture_stop_cb(struct fp_dev *dev, void *user_data)
{
	gboolean *stopped = user_data;
609
	G_DEBUG_HERE();
610 611
	*stopped = TRUE;
}
612 613
/**
 * fp_dev_img_capture:
614
 * @dev: the struct #fp_dev device
615 616
 * @unconditional: whether to unconditionally capture an image, or to only capture when a finger is detected
 * @img: a location to return the captured image. Must be freed with
617
 * fp_img_free() after use
618
 *
619
 * Captures a #fp_img from a device. The returned image is the raw
620
 * image provided by the device, you may wish to [standardize](libfprint-Image-operations.html#img_std) it.
621
 *
622
 * If set, the @unconditional flag indicates that the device should
623 624 625 626
 * capture an image unconditionally, regardless of whether a finger is there
 * or not. If unset, this function will block until a finger is detected on
 * the sensor.
 *
627 628 629 630
 * See fp_dev_supports_imaging().
 *
 * Returns: 0 on success, non-zero on error. -ENOTSUP indicates that either the
 * @unconditional flag was set but the device does not support this, or that the
631
 * device does not support imaging
632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690
 */
API_EXPORTED int fp_dev_img_capture(struct fp_dev *dev, int unconditional,
	struct fp_img **img)
{
	struct sync_capture_data *vdata;
	gboolean stopped = FALSE;
	int r;

	if (!dev->drv->capture_start) {
		fp_dbg("image capture is not supported on %s device", dev->drv->name);
		return -ENOTSUP;
	}

	fp_dbg("to be handled by %s", dev->drv->name);
	vdata = g_malloc0(sizeof(struct sync_capture_data));
	r = fp_async_capture_start(dev, unconditional, sync_capture_cb, vdata);
	if (r < 0) {
		fp_dbg("capture_start error %d", r);
		g_free(vdata);
		return r;
	}

	while (!vdata->populated) {
		r = fp_handle_events();
		if (r < 0) {
			g_free(vdata);
			goto err;
		}
	}

	if (img)
		*img = vdata->img;
	else
		fp_img_free(vdata->img);

	r = vdata->result;
	g_free(vdata);
	switch (r) {
	case FP_CAPTURE_COMPLETE:
		fp_dbg("result: complete");
		break;
	case FP_CAPTURE_FAIL:
		fp_dbg("result: fail");
		break;
	default:
		fp_err("unrecognised return code %d", r);
		r = -EINVAL;
	}

err:
	fp_dbg("ending capture");
	if (fp_async_capture_stop(dev, capture_stop_cb, &stopped) == 0)
		while (!stopped)
			if (fp_handle_events() < 0)
				break;

	return r;
}