sync.c 19.2 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
/*
 * 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"

#include <config.h>
#include <errno.h>

#include "fp_internal.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;
}

40 41 42 43
/**
 * fp_dev_open:
 * @ddev: the discovered device to open
 *
44
 * Opens and initialises a device. This is the function you call in order
45
 * to convert a #fp_dscv_dev discovered device into an actual device handle
46
 * that you can perform operations with.
47
 *
48
 * Returns: the opened device handle, or %NULL on error
49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
 */
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;

	fp_dbg("");
	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)
{
	fp_dbg("");
	gboolean *closed = user_data;
	*closed = TRUE;
}

82 83 84 85
/**
 * fp_dev_close:
 * @dev: the device to close. If %NULL, function simply returns.
 *
86 87 88 89 90 91 92 93 94 95 96 97 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 125 126 127
 * Close a device. You must call this function when you are finished using
 * a fingerprint device.
 */
API_EXPORTED void fp_dev_close(struct fp_dev *dev)
{
	gboolean closed = FALSE;

	if (!dev)
		return;

	fp_dbg("");
	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;
	fp_dbg("");
	*stopped = TRUE;
}

128 129 130
/**
 * fp_enroll_finger_img:
 * @dev: the device
131
 * @print_data: a location to return the resultant enrollment data from
132 133 134 135 136 137 138
 * the final stage. Must be freed with fp_print_data_free() after use.
 * @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
 * use.
 *
 * Performs an enroll stage. See [Enrolling](libfprint-Devices-operations.html#enrolling)
 * for an explanation of enroll stages.
139 140 141 142 143 144 145 146 147 148 149 150 151 152
 *
 * 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
153
 * is returned, the enrollment stage is <emphasis role="strong">not</emphasis> advanced, so the next call
154 155 156
 * into this function will retry the current stage again. The current stage may
 * need to be retried several times.
 *
157
 * The %FP_ENROLL_FAIL code may be returned from any enroll
158 159 160 161 162 163
 * 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.
 *
164
 * The %FP_ENROLL_PASS code will only ever be returned for
165 166 167 168
 * 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.
 *
169
 * The %FP_ENROLL_COMPLETE code will only ever be returned
170 171 172 173 174
 * 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.
175
 *
176 177 178 179 180
 * 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.
 *
181
 * Returns: negative code on error, otherwise a code from #fp_enroll_result
182 183 184 185 186 187 188 189
 */
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;
190
	struct sync_enroll_data *edata = NULL;
191 192 193 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
	int r;
	fp_dbg("");

	/* 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;
	}

273 274 275
	if (!final)
		return r;

276 277 278 279 280 281 282 283 284 285 286 287 288 289
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;
}

290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308
/**
 * fp_enroll_finger:
 * @dev: the device
 * @print_data: a location to return the resultant enrollment data from
 * the final stage. Must be freed with fp_print_data_free() after use.
 *
 * 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);
}

309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330
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;
	fp_dbg("");
	*stopped = TRUE;
}

331 332 333 334 335 336 337 338 339
/**
 * fp_verify_finger_img:
 * @dev: the device to perform the scan.
 * @enrolled_print: the print to verify against. Must have been previously
 * enrolled with a device compatible to the device selected to perform the scan.
 * @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
 * use.

340 341 342 343 344 345
 * Performs a new scan and verify it against a previously enrolled print.
 * 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.
 *
346
 * Returns: negative code on error, otherwise a code from #fp_verify_result
347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364
 */
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;
	}

365
	fp_dbg("to be handled by %s", dev->drv->name);
366 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
	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;
}

423 424 425 426 427 428 429 430 431 432
/**
 * fp_verify_finger:
 * @dev: the device to perform the scan.
 * @enrolled_print: the print to verify against. Must have been previously
 * enrolled with a device compatible to the device selected to perform the scan.
 *
 * 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.
 *
433 434
 * See also fp_verify_finger_img().
 *
435 436 437 438 439 440 441 442
 * 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);
}

443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466
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;
	fp_dbg("");
	*stopped = TRUE;
}

467 468 469 470 471 472 473 474 475 476 477 478 479
/**
 * fp_identify_finger_img:
 * @dev: the device to perform the scan.
 * @print_gallery: NULL-terminated array of pointers to the prints to
 * identify against. Each one must have been previously enrolled with a device
 * compatible to the device selected to perform the scan.
 * @match_offset: output location to store the array index of the matched
 * gallery print (if any was found). Only valid if FP_VERIFY_MATCH was
 * returned.
 * @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
 * use.

480 481 482 483 484 485 486 487
 * 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
488
 * %FP_VERIFY_MATCH indicates that the scanned fingerprint
489 490 491 492 493 494 495 496 497
 * 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.
 *
498
 * Returns: negative code on error, otherwise a code from #fp_verify_result
499 500 501 502 503 504 505 506 507 508
 */
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;

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

	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);

528
	r = idata->result;
529 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
	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;
}

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

 * 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.
 *
580 581
 * See also fp_identify_finger_img().
 *
582 583 584 585 586 587 588 589
 * 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);
}

590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610
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;
	fp_dbg("");
	*stopped = TRUE;
}
611 612 613 614 615 616 617
/**
 * fp_dev_img_capture:
 * @dev: the device
 * @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
 * fp_img_free() after use.
 *
618
 * Captures a #fp_img from a device. The returned image is the raw
619
 * image provided by the device, you may wish to [standardize](libfprint-Image-operations.html#img_std) it.
620
 *
621
 * If set, the @unconditional flag indicates that the device should
622 623 624 625
 * 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.
 *
626 627 628 629
 * 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
630 631 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
 * device does not support imaging.
 */
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;
}