fpi-core.c 21.3 KB
Newer Older
Daniel Drake's avatar
Daniel Drake committed
1 2
/*
 * Core 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 20
 *
 * 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
 */

#include <config.h>
21 22
#include <errno.h>
#include <stdio.h>
Daniel Drake's avatar
Daniel Drake committed
23
#include <stdlib.h>
Daniel Drake's avatar
Daniel Drake committed
24

25
#include <glib.h>
26
#include <libusb.h>
27 28 29

#include "fp_internal.h"

Daniel Drake's avatar
Daniel Drake committed
30
libusb_context *fpi_usb_ctx = NULL;
Daniel Drake's avatar
Daniel Drake committed
31 32
GSList *opened_devices = NULL;

Daniel Drake's avatar
Daniel Drake committed
33
/**
34 35 36 37 38 39 40 41 42 43 44
 * SECTION:discovery
 * @title: Device discovery
 *
 * These functions allow you to scan the system for supported fingerprint
 * scanning hardware. This is your starting point when integrating libfprint
 * into your software.
 *
 * When you've identified a discovered device that you would like to control,
 * you can open it with fp_dev_open(). Note that discovered devices may no
 * longer be available at the time when you want to open them, for example
 * the user may have unplugged the device.
Daniel Drake's avatar
Daniel Drake committed
45 46
 */

47 48 49 50 51 52 53 54 55 56 57 58 59
/**
 * SECTION:drv
 * @title: Driver operations
 *
 * Internally, libfprint is abstracted into various drivers to communicate
 * with the different types of supported fingerprint readers. libfprint works
 * hard so that you don't have to care about these internal abstractions,
 * however there are some situations where you may be interested in a little
 * behind-the-scenes driver info.
 *
 * You can obtain the driver for a device using fp_dev_get_driver(), which
 * you can pass to the functions documented on this page.
 */
Daniel Drake's avatar
Daniel Drake committed
60 61

/**
62 63 64
 * SECTION:dev
 * @title: Devices operations
 *
Daniel Drake's avatar
Daniel Drake committed
65 66 67 68
 * In order to interact with fingerprint scanners, your software will
 * interface primarily with libfprint's representation of devices, detailed
 * on this page.
 *
69 70
 * # Enrolling # {#enrolling}
 *
Daniel Drake's avatar
Daniel Drake committed
71 72 73 74 75 76
 * Enrolling is represented within libfprint as a multi-stage process. This
 * slightly complicates things for application developers, but is required
 * for a smooth process.
 *
 * Some devices require the user to scan their finger multiple times in
 * order to complete the enrollment process. libfprint must return control
77
 * to your application in-between each scan in order for your application to
Daniel Drake's avatar
Daniel Drake committed
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
 * instruct the user to swipe their finger again. Each scan is referred to
 * as a stage, so a device that requires 3 scans for enrollment corresponds
 * to you running 3 enrollment stages using libfprint.
 *
 * The fp_dev_get_nr_enroll_stages() function can be used to find out how
 * many enroll stages are needed.
 *
 * In order to complete an enroll stage, you call an enroll function such
 * as fp_enroll_finger(). The return of this function does not necessarily
 * indicate that a stage has completed though, as the user may not have
 * produced a good enough scan. Each stage may have to be retried several
 * times.
 *
 * The exact semantics of the enroll functions are described in the
 * fp_enroll_finger() documentation. You should pay careful attention to the
 * details.
 *
95 96
 * # Imaging # {#imaging}
 *
Daniel Drake's avatar
Daniel Drake committed
97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113
 * libfprint provides you with some ways to retrieve images of scanned
 * fingers, such as the fp_dev_img_capture() function, or some enroll/verify
 * function variants which provide images. You may wish to do something with
 * such images in your application.
 *
 * However, you must be aware that not all hardware supported by libfprint
 * operates like this. Most hardware does operate simply by sending
 * fingerprint images to the host computer for further processing, but some
 * devices do all fingerprint processing in hardware and do not present images
 * to the host computer.
 *
 * You can use fp_dev_supports_imaging() to see if image capture is possible
 * on a particular device. Your application must be able to cope with the
 * fact that libfprint does support regular operations (e.g. enrolling and
 * verification) on some devices which do not provide images.
 */

114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132
/**
 * SECTION:fpi-core
 * @title: Driver structures
 *
 * Driver structures need to be defined inside each driver in
 * order for the core library to know what function to call, and the capabilities
 * of the driver and the devices it supports.
 */

/**
 * SECTION:fpi-core-img
 * @title: Image driver structures
 *
 * Image driver structures need to be defined inside each image driver in
 * order for the core library to know what function to call, and the capabilities
 * of the driver and the devices it supports. Its structure is based off the
 * #fp_driver struct.
 */

133
static GSList *registered_drivers = NULL;
134

Daniel Drake's avatar
Daniel Drake committed
135
static void register_driver(struct fp_driver *drv)
136
{
137
	if (drv->id == 0) {
138
		fp_err("not registering driver %s: driver ID is 0", drv->name);
139 140
		return;
	}
141
	registered_drivers = g_slist_prepend(registered_drivers, (gpointer) drv);
Daniel Drake's avatar
Daniel Drake committed
142
	fp_dbg("registered driver %s", drv->name);
143 144
}

145
#include "drivers_arrays.h"
Daniel Drake's avatar
Daniel Drake committed
146

147 148
static void register_drivers(void)
{
Daniel Drake's avatar
Daniel Drake committed
149
	unsigned int i;
150

Daniel Drake's avatar
Daniel Drake committed
151
	for (i = 0; i < G_N_ELEMENTS(primitive_drivers); i++)
Daniel Drake's avatar
Daniel Drake committed
152 153
		register_driver(primitive_drivers[i]);

Daniel Drake's avatar
Daniel Drake committed
154
	for (i = 0; i < G_N_ELEMENTS(img_drivers); i++) {
Daniel Drake's avatar
Daniel Drake committed
155 156 157 158
		struct fp_img_driver *imgdriver = img_drivers[i];
		fpi_img_driver_setup(imgdriver);
		register_driver(&imgdriver->driver);
	}
159 160
}

161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178
API_EXPORTED struct fp_driver **fprint_get_drivers (void)
{
	GPtrArray *array;
	unsigned int i;

	array = g_ptr_array_new ();
	for (i = 0; i < G_N_ELEMENTS(primitive_drivers); i++)
		g_ptr_array_add (array, primitive_drivers[i]);

	for (i = 0; i < G_N_ELEMENTS(img_drivers); i++)
		g_ptr_array_add (array, &(img_drivers[i]->driver));

	/* Add a null item terminating the array */
	g_ptr_array_add (array, NULL);

	return (struct fp_driver **) g_ptr_array_free (array, FALSE);
}

Daniel Drake's avatar
Daniel Drake committed
179
static struct fp_driver *find_supporting_driver(libusb_device *udev,
180
	const struct usb_id **usb_id, uint32_t *devtype)
181
{
182
	int ret;
183
	GSList *elem = registered_drivers;
184 185
	struct libusb_device_descriptor dsc;

186 187 188 189 190
	const struct usb_id *best_usb_id;
	struct fp_driver *best_drv;
	uint32_t best_devtype;
	int drv_score = 0;

191 192 193 194 195
	ret = libusb_get_device_descriptor(udev, &dsc);
	if (ret < 0) {
		fp_err("Failed to get device descriptor");
		return NULL;
	}
196 197 198 199

	best_drv = NULL;
	best_devtype = 0;

200
	do {
Daniel Drake's avatar
Daniel Drake committed
201
		struct fp_driver *drv = elem->data;
202
		uint32_t type = 0;
203 204
		const struct usb_id *id;

205
		for (id = drv->id_table; id->vendor; id++) {
206
			if (dsc.idVendor == id->vendor && dsc.idProduct == id->product) {
207 208 209 210 211 212 213 214 215 216 217 218 219 220
				if (drv->discover) {
					int r = drv->discover(&dsc, &type);
					if (r < 0)
						fp_err("%s discover failed, code %d", drv->name, r);
					if (r <= 0)
						continue;
					/* Has a discover function, and matched our device */
					drv_score = 100;
				} else {
					/* Already got a driver as good */
					if (drv_score >= 50)
						continue;
					drv_score = 50;
				}
Daniel Drake's avatar
Daniel Drake committed
221 222
				fp_dbg("driver %s supports USB device %04x:%04x",
					drv->name, id->vendor, id->product);
223 224 225 226 227 228 229
				best_usb_id = id;
				best_drv = drv;
				best_devtype = type;

				/* We found the best possible driver */
				if (drv_score == 100)
					break;
Daniel Drake's avatar
Daniel Drake committed
230
			}
231
		}
Daniel Drake's avatar
Daniel Drake committed
232
	} while ((elem = g_slist_next(elem)));
233

234 235 236 237 238 239
	if (best_drv != NULL) {
		fp_dbg("selected driver %s supports USB device %04x:%04x",
		       best_drv->name, dsc.idVendor, dsc.idProduct);
		*devtype = best_devtype;
		*usb_id = best_usb_id;
	}
240 241

	return best_drv;
242 243
}

Daniel Drake's avatar
Daniel Drake committed
244
static struct fp_dscv_dev *discover_dev(libusb_device *udev)
Daniel Drake's avatar
Daniel Drake committed
245
{
Daniel Drake's avatar
Daniel Drake committed
246
	const struct usb_id *usb_id;
247
	struct fp_driver *drv;
Daniel Drake's avatar
Daniel Drake committed
248
	struct fp_dscv_dev *ddev;
249 250 251
	uint32_t devtype;

	drv = find_supporting_driver(udev, &usb_id, &devtype);
Daniel Drake's avatar
Daniel Drake committed
252 253 254 255 256 257 258 259 260 261 262 263

	if (!drv)
		return NULL;

	ddev = g_malloc0(sizeof(*ddev));
	ddev->drv = drv;
	ddev->udev = udev;
	ddev->driver_data = usb_id->driver_data;
	ddev->devtype = devtype;
	return ddev;
}

264 265 266
/**
 * fp_discover_devs:
 *
Daniel Drake's avatar
Daniel Drake committed
267 268
 * Scans the system and returns a list of discovered devices. This is your
 * entry point into finding a fingerprint reader to operate.
269
 *
Bastien Nocera's avatar
Bastien Nocera committed
270
 * Returns: a nul-terminated list of discovered devices. Must be freed with
Daniel Drake's avatar
Daniel Drake committed
271 272
 * fp_dscv_devs_free() after use.
 */
273 274
API_EXPORTED struct fp_dscv_dev **fp_discover_devs(void)
{
275
	GPtrArray *tmparray;
Daniel Drake's avatar
Daniel Drake committed
276 277 278 279
	libusb_device *udev;
	libusb_device **devs;
	int r;
	int i = 0;
280

281
	g_return_val_if_fail (registered_drivers != NULL, NULL);
282

Daniel Drake's avatar
Daniel Drake committed
283
	r = libusb_get_device_list(fpi_usb_ctx, &devs);
Daniel Drake's avatar
Daniel Drake committed
284 285 286 287
	if (r < 0) {
		fp_err("couldn't enumerate USB devices, error %d", r);
		return NULL;
	}
288

289 290
	tmparray = g_ptr_array_new ();

291
	/* Check each device against each driver, temporarily storing successfully
292
	 * discovered devices in a GPtrArray. */
Daniel Drake's avatar
Daniel Drake committed
293 294 295 296
	while ((udev = devs[i++]) != NULL) {
		struct fp_dscv_dev *ddev = discover_dev(udev);
		if (!ddev)
			continue;
297 298 299
		/* discover_dev() doesn't hold a reference to the udev,
		 * so increase the reference for ddev to hold this ref */
		libusb_ref_device(udev);
300
		g_ptr_array_add (tmparray, (gpointer) ddev);
Daniel Drake's avatar
Daniel Drake committed
301
	}
302
	libusb_free_device_list(devs, 1);
303

304
	/* Convert our temporary array into a standard NULL-terminated pointer
305
	 * array. */
306 307
	g_ptr_array_add (tmparray, NULL);
	return (struct fp_dscv_dev **) g_ptr_array_free (tmparray, FALSE);
308 309
}

310 311 312 313 314
/**
 * fp_dscv_devs_free:
 * @devs: the list of discovered devices. If %NULL, function simply
 * returns.
 *
Daniel Drake's avatar
Daniel Drake committed
315 316
 * Free a list of discovered devices. This function destroys the list and all
 * discovered devices that it included, so make sure you have opened your
317
 * discovered device <emphasis role="strong">before</emphasis> freeing the list.
Daniel Drake's avatar
Daniel Drake committed
318
 */
319 320 321 322 323 324
API_EXPORTED void fp_dscv_devs_free(struct fp_dscv_dev **devs)
{
	int i;
	if (!devs)
		return;

325 326
	for (i = 0; devs[i]; i++) {
		libusb_unref_device(devs[i]->udev);
327
		g_free(devs[i]);
328
	}
329 330 331
	g_free(devs);
}

332 333 334 335
/**
 * fp_dscv_dev_get_driver:
 * @dev: the discovered device
 *
336
 * Gets the #fp_driver for a discovered device.
337 338
 *
 * Returns: the driver backing the device
Daniel Drake's avatar
Daniel Drake committed
339
 */
Daniel Drake's avatar
Daniel Drake committed
340
API_EXPORTED struct fp_driver *fp_dscv_dev_get_driver(struct fp_dscv_dev *dev)
341 342 343 344
{
	return dev->drv;
}

345 346 347 348 349 350 351 352 353 354 355
/**
 * fp_dscv_dev_get_driver_id:
 * @dev: a discovered fingerprint device
 *
 * Returns: the ID for the underlying driver for that device
 */
API_EXPORTED uint16_t fp_dscv_dev_get_driver_id(struct fp_dscv_dev *dev)
{
	return fp_driver_get_driver_id(fp_dscv_dev_get_driver(dev));
}

356 357 358 359 360 361 362
/**
 * fp_dscv_dev_get_devtype:
 * @dev: the discovered device
 *
 * Gets the [devtype](advanced-topics.html#device-types) for a discovered device.
 *
 * Returns: the devtype of the device
Daniel Drake's avatar
Daniel Drake committed
363
 */
Daniel Drake's avatar
Daniel Drake committed
364 365 366 367 368
API_EXPORTED uint32_t fp_dscv_dev_get_devtype(struct fp_dscv_dev *dev)
{
	return dev->devtype;
}

Daniel Drake's avatar
Daniel Drake committed
369 370 371 372 373 374 375 376 377 378 379 380 381
enum fp_print_data_type fpi_driver_get_data_type(struct fp_driver *drv)
{
	switch (drv->type) {
	case DRIVER_PRIMITIVE:
		return PRINT_DATA_RAW;
	case DRIVER_IMAGING:
		return PRINT_DATA_NBIS_MINUTIAE;
	default:
		fp_err("unrecognised drv type %d", drv->type);
		return PRINT_DATA_RAW;
	}
}

382 383 384 385 386
/**
 * fp_dscv_dev_supports_print_data:
 * @dev: the discovered device
 * @print: the print for compatibility checking
 *
387
 * Determines if a specific #fp_print_data stored print appears to be
Daniel Drake's avatar
Daniel Drake committed
388
 * compatible with a discovered device.
389 390
 *
 * Returns: 1 if the print is compatible with the device, 0 otherwise
Daniel Drake's avatar
Daniel Drake committed
391
 */
Daniel Drake's avatar
Daniel Drake committed
392
API_EXPORTED int fp_dscv_dev_supports_print_data(struct fp_dscv_dev *dev,
393
	struct fp_print_data *print)
Daniel Drake's avatar
Daniel Drake committed
394 395
{
	return fpi_print_data_compatible(dev->drv->id, dev->devtype,
396 397
		fpi_driver_get_data_type(dev->drv), print->driver_id, print->devtype,
		print->type);
Daniel Drake's avatar
Daniel Drake committed
398 399
}

400 401 402 403 404
/**
 * fp_dscv_dev_supports_dscv_print:
 * @dev: the discovered device
 * @print: the discovered print for compatibility checking
 *
405
 * Determines if a specific #fp_dscv_print discovered print appears to be
Daniel Drake's avatar
Daniel Drake committed
406
 * compatible with a discovered device.
407 408
 *
 * Returns: 1 if the print is compatible with the device, 0 otherwise
409 410
 *
 * Deprecated: Do not use.
Daniel Drake's avatar
Daniel Drake committed
411
 */
Daniel Drake's avatar
Daniel Drake committed
412
API_EXPORTED int fp_dscv_dev_supports_dscv_print(struct fp_dscv_dev *dev,
413
	struct fp_dscv_print *print)
Daniel Drake's avatar
Daniel Drake committed
414 415
{
	return fpi_print_data_compatible(dev->drv->id, dev->devtype, 0,
416
		print->driver_id, print->devtype, 0);
Daniel Drake's avatar
Daniel Drake committed
417 418
}

419 420 421 422 423
/**
 * fp_dscv_dev_for_print_data:
 * @devs: a list of discovered devices
 * @print: the print under inspection
 *
Daniel Drake's avatar
Daniel Drake committed
424
 * Searches a list of discovered devices for a device that appears to be
425
 * compatible with a #fp_print_data stored print.
426 427 428
 *
 * Returns: the first discovered device that appears to support the print, or
 * %NULL if no apparently compatible devices could be found
429 430
 *
 * Deprecated: Do not use.
Daniel Drake's avatar
Daniel Drake committed
431
 */
Daniel Drake's avatar
Daniel Drake committed
432
API_EXPORTED struct fp_dscv_dev *fp_dscv_dev_for_print_data(struct fp_dscv_dev **devs,
433
	struct fp_print_data *print)
Daniel Drake's avatar
Daniel Drake committed
434 435 436 437
{
	struct fp_dscv_dev *ddev;
	int i;

Daniel Drake's avatar
Daniel Drake committed
438
	for (i = 0; (ddev = devs[i]); i++)
439
		if (fp_dscv_dev_supports_print_data(ddev, print))
Daniel Drake's avatar
Daniel Drake committed
440 441 442 443
			return ddev;
	return NULL;
}

444 445 446 447 448
/**
 * fp_dscv_dev_for_dscv_print:
 * @devs: a list of discovered devices
 * @print: the print under inspection
 *
Daniel Drake's avatar
Daniel Drake committed
449
 * Searches a list of discovered devices for a device that appears to be
450
 * compatible with a #fp_dscv_print discovered print.
451 452 453
 *
 * Returns: the first discovered device that appears to support the print, or
 * %NULL if no apparently compatible devices could be found
454 455
 *
 * Deprecated: Do not use.
Daniel Drake's avatar
Daniel Drake committed
456
 */
Daniel Drake's avatar
Daniel Drake committed
457 458 459 460 461 462
API_EXPORTED struct fp_dscv_dev *fp_dscv_dev_for_dscv_print(struct fp_dscv_dev **devs,
	struct fp_dscv_print *print)
{
	struct fp_dscv_dev *ddev;
	int i;

463 464 465
	for (i = 0; (ddev = devs[i]); i++) {
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
Daniel Drake's avatar
Daniel Drake committed
466 467
		if (fp_dscv_dev_supports_dscv_print(ddev, print))
			return ddev;
468 469
#pragma GCC diagnostic pop
	}
Daniel Drake's avatar
Daniel Drake committed
470 471 472
	return NULL;
}

473 474
/**
 * fp_dev_get_driver:
475
 * @dev: the struct #fp_dev device
476
 *
477
 * Get the #fp_driver for a fingerprint device.
478 479
 *
 * Returns: the driver controlling the device
Daniel Drake's avatar
Daniel Drake committed
480
 */
Daniel Drake's avatar
Daniel Drake committed
481
API_EXPORTED struct fp_driver *fp_dev_get_driver(struct fp_dev *dev)
482 483 484 485
{
	return dev->drv;
}

486 487
/**
 * fp_dev_get_nr_enroll_stages:
488
 * @dev: the struct #fp_dev device
489 490
 *
 * Gets the number of [enroll stages](intro.html#enrollment) required to enroll a
Daniel Drake's avatar
Daniel Drake committed
491
 * fingerprint with the device.
492 493
 *
 * Returns: the number of enroll stages
Daniel Drake's avatar
Daniel Drake committed
494
 */
Daniel Drake's avatar
Daniel Drake committed
495 496 497 498 499
API_EXPORTED int fp_dev_get_nr_enroll_stages(struct fp_dev *dev)
{
	return dev->nr_enroll_stages;
}

500 501
/**
 * fp_dev_get_devtype:
502
 * @dev: the struct #fp_dev device
503 504 505 506
 *
 * Gets the [devtype](advanced-topics.html#device-types) for a device.
 *
 * Returns: the devtype
Daniel Drake's avatar
Daniel Drake committed
507
 */
Daniel Drake's avatar
Daniel Drake committed
508 509 510 511 512
API_EXPORTED uint32_t fp_dev_get_devtype(struct fp_dev *dev)
{
	return dev->devtype;
}

513 514
/**
 * fp_dev_supports_print_data:
515
 * @dev: the struct #fp_dev device
516 517
 * @data: the stored print
 *
Daniel Drake's avatar
Daniel Drake committed
518
 * Determines if a stored print is compatible with a certain device.
519 520
 *
 * Returns: 1 if the print is compatible with the device, 0 if not
Daniel Drake's avatar
Daniel Drake committed
521
 */
Daniel Drake's avatar
Daniel Drake committed
522 523 524 525 526 527 528 529
API_EXPORTED int fp_dev_supports_print_data(struct fp_dev *dev,
	struct fp_print_data *data)
{
	return fpi_print_data_compatible(dev->drv->id, dev->devtype,
		fpi_driver_get_data_type(dev->drv), data->driver_id, data->devtype,
		data->type);
}

530 531
/**
 * fp_dev_supports_dscv_print:
532
 * @dev: the struct #fp_dev device
533 534
 * @print: the discovered print
 *
535
 * Determines if a #fp_dscv_print discovered print appears to be compatible
Daniel Drake's avatar
Daniel Drake committed
536
 * with a certain device.
537 538
 *
 * Returns: 1 if the print is compatible with the device, 0 if not
539 540
 *
 * Deprecated: Do not use.
Daniel Drake's avatar
Daniel Drake committed
541
 */
Daniel Drake's avatar
Daniel Drake committed
542
API_EXPORTED int fp_dev_supports_dscv_print(struct fp_dev *dev,
543
	struct fp_dscv_print *print)
Daniel Drake's avatar
Daniel Drake committed
544 545
{
	return fpi_print_data_compatible(dev->drv->id, dev->devtype,
546
		0, print->driver_id, print->devtype, 0);
Daniel Drake's avatar
Daniel Drake committed
547 548
}

549 550 551 552
/**
 * fp_driver_get_name:
 * @drv: the driver
 *
Daniel Drake's avatar
Daniel Drake committed
553
 * Retrieves the name of the driver. For example: "upekts"
554 555
 *
 * Returns: the driver name. Must not be modified or freed.
Daniel Drake's avatar
Daniel Drake committed
556
 */
Daniel Drake's avatar
Daniel Drake committed
557
API_EXPORTED const char *fp_driver_get_name(struct fp_driver *drv)
558 559 560 561
{
	return drv->name;
}

562 563 564 565
/**
 * fp_driver_get_full_name:
 * @drv: the driver
 *
Daniel Drake's avatar
Daniel Drake committed
566
 * Retrieves a descriptive name of the driver. For example: "UPEK TouchStrip"
567 568
 *
 * Returns: the descriptive name. Must not be modified or freed.
Daniel Drake's avatar
Daniel Drake committed
569
 */
Daniel Drake's avatar
Daniel Drake committed
570
API_EXPORTED const char *fp_driver_get_full_name(struct fp_driver *drv)
571 572 573 574
{
	return drv->full_name;
}

575 576 577 578
/**
 * fp_driver_get_driver_id:
 * @drv: the driver
 *
Daniel Drake's avatar
Daniel Drake committed
579
 * Retrieves the driver ID code for a driver.
580 581
 *
 * Returns: the driver ID
Daniel Drake's avatar
Daniel Drake committed
582
 */
Daniel Drake's avatar
Daniel Drake committed
583 584 585 586 587
API_EXPORTED uint16_t fp_driver_get_driver_id(struct fp_driver *drv)
{
	return drv->id;
}

588 589 590 591
/**
 * fp_driver_get_scan_type:
 * @drv: the driver
 *
592
 * Retrieves the scan type for the devices associated with the driver.
593 594
 *
 * Returns: the scan type
595 596 597 598 599 600
 */
API_EXPORTED enum fp_scan_type fp_driver_get_scan_type(struct fp_driver *drv)
{
	return drv->scan_type;
}

601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618
/**
 * fp_driver_supports_imaging:
 * @drv: the driver
 *
 * Determines if a driver has imaging capabilities. If a driver has imaging
 * capabilities you are able to perform imaging operations such as retrieving
 * scan images using fp_dev_img_capture(). However, not all drivers support
 * imaging devices – some do all processing in hardware. This function will
 * indicate which class a device in question falls into.
 *
 * Returns: 1 if the device is an imaging device, 0 if the device does not
 * provide images to the host computer
 */
API_EXPORTED int fp_driver_supports_imaging(struct fp_driver *drv)
{
	return drv->capture_start != NULL;
}

619 620
/**
 * fp_dev_supports_imaging:
621
 * @dev: the struct #fp_dev device
622
 *
Daniel Drake's avatar
Daniel Drake committed
623 624 625
 * Determines if a device has imaging capabilities. If a device has imaging
 * capabilities you are able to perform imaging operations such as retrieving
 * scan images using fp_dev_img_capture(). However, not all devices are
626
 * imaging devices – some do all processing in hardware. This function will
Daniel Drake's avatar
Daniel Drake committed
627
 * indicate which class a device in question falls into.
628 629
 *
 * Returns: 1 if the device is an imaging device, 0 if the device does not
Daniel Drake's avatar
Daniel Drake committed
630 631
 * provide images to the host computer
 */
632 633
API_EXPORTED int fp_dev_supports_imaging(struct fp_dev *dev)
{
634
	return dev->drv->capture_start != NULL;
635 636
}

637 638
/**
 * fp_dev_supports_identification:
639
 * @dev: the struct #fp_dev device
640 641
 *
 * Determines if a device is capable of [identification](intro.html#identification)
Daniel Drake's avatar
Daniel Drake committed
642 643
 * through fp_identify_finger() and similar. Not all devices support this
 * functionality.
644 645
 *
 * Returns: 1 if the device is capable of identification, 0 otherwise.
Daniel Drake's avatar
Daniel Drake committed
646 647 648
 */
API_EXPORTED int fp_dev_supports_identification(struct fp_dev *dev)
{
649
	return dev->drv->identify_start != NULL;
Daniel Drake's avatar
Daniel Drake committed
650 651
}

652 653
/**
 * fp_dev_get_img_width:
654
 * @dev: the struct #fp_dev device
655
 *
Daniel Drake's avatar
Daniel Drake committed
656 657
 * Gets the expected width of images that will be captured from the device.
 * This function will return -1 for devices that are not
658
 * [imaging devices](libfprint-Devices-operations.html#imaging). If the width of images from this device
Daniel Drake's avatar
Daniel Drake committed
659
 * can vary, 0 will be returned.
660 661
 *
 * Returns: the expected image width, or 0 for variable, or -1 for non-imaging
Daniel Drake's avatar
Daniel Drake committed
662 663
 * devices.
 */
664 665
API_EXPORTED int fp_dev_get_img_width(struct fp_dev *dev)
{
666
	if (!dev->img_dev) {
667 668 669 670
		fp_dbg("get image width for non-imaging device");
		return -1;
	}

671
	return fpi_imgdev_get_img_width(dev->img_dev);
672 673
}

674 675
/**
 * fp_dev_get_img_height:
676
 * @dev: the struct #fp_dev device
677
 *
Daniel Drake's avatar
Daniel Drake committed
678 679
 * Gets the expected height of images that will be captured from the device.
 * This function will return -1 for devices that are not
680
 * [imaging devices](libfprint-Devices-operations.html#imaging). If the height of images from this device
Daniel Drake's avatar
Daniel Drake committed
681
 * can vary, 0 will be returned.
682 683
 *
 * Returns: the expected image height, or 0 for variable, or -1 for non-imaging
Daniel Drake's avatar
Daniel Drake committed
684 685
 * devices.
 */
686 687
API_EXPORTED int fp_dev_get_img_height(struct fp_dev *dev)
{
688
	if (!dev->img_dev) {
689 690 691 692
		fp_dbg("get image height for non-imaging device");
		return -1;
	}

693
	return fpi_imgdev_get_img_height(dev->img_dev);
694 695
}

696 697 698 699
/**
 * fp_set_debug:
 * @level: the verbosity level
 *
700
 * This call does nothing, see fp_init() for details.
Daniel Drake's avatar
Daniel Drake committed
701 702 703
 */
API_EXPORTED void fp_set_debug(int level)
{
704
	/* Nothing */
Daniel Drake's avatar
Daniel Drake committed
705 706
}

707 708 709
/**
 * fp_init:
 *
Daniel Drake's avatar
Daniel Drake committed
710 711
 * Initialise libfprint. This function must be called before you attempt to
 * use the library in any way.
712
 *
713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729
 * To enable debug output of libfprint specifically, use GLib's `G_MESSAGES_DEBUG`
 * environment variable as explained in [Running and debugging GLib Applications](https://developer.gnome.org/glib/stable/glib-running.html#G_MESSAGES_DEBUG).
 *
 * The log domains used in libfprint are either `libfprint` or `libfprint-FP_COMPONENT`
 * where `FP_COMPONENT` is defined in the source code for each driver, or component
 * of the library. Starting with `all` and trimming down is advised.
 *
 * To enable debugging of libusb, for USB-based fingerprint reader drivers, use
 * libusb's `LIBUSB_DEBUG` environment variable as explained in the
 * [libusb-1.0 API Reference](http://libusb.sourceforge.net/api-1.0/#msglog).
 *
 * Example:
 *
 * ```
 * LIBUSB_DEBUG=4 G_MESSAGES_DEBUG=all my-libfprint-application
 * ```
 *
730
 * Returns: 0 on success, non-zero on error.
Daniel Drake's avatar
Daniel Drake committed
731
 */
Daniel Drake's avatar
Daniel Drake committed
732 733
API_EXPORTED int fp_init(void)
{
734
	int r;
735
	G_DEBUG_HERE();
736

Daniel Drake's avatar
Daniel Drake committed
737
	r = libusb_init(&fpi_usb_ctx);
738 739 740
	if (r < 0)
		return r;

741
	register_drivers();
Daniel Drake's avatar
Daniel Drake committed
742
	fpi_poll_init();
Daniel Drake's avatar
Daniel Drake committed
743 744
	return 0;
}
745

746 747 748
/**
 * fp_exit:
 *
749 750 751 752 753 754
 * Deinitialise libfprint. This function should be called during your program
 * exit sequence. You must not use any libfprint functions after calling this
 * function, unless you call fp_init() again.
 */
API_EXPORTED void fp_exit(void)
{
755
	G_DEBUG_HERE();
756

Daniel Drake's avatar
Daniel Drake committed
757 758 759 760 761 762 763 764 765 766
	if (opened_devices) {
		GSList *copy = g_slist_copy(opened_devices);
		GSList *elem = copy;
		fp_dbg("naughty app left devices open on exit!");

		do
			fp_dev_close((struct fp_dev *) elem->data);
		while ((elem = g_slist_next(elem)));

		g_slist_free(copy);
767 768 769 770 771
		g_slist_free(opened_devices);
		opened_devices = NULL;
	}

	fpi_data_exit();
772
	fpi_poll_exit();
773 774
	g_slist_free(registered_drivers);
	registered_drivers = NULL;
Daniel Drake's avatar
Daniel Drake committed
775
	libusb_exit(fpi_usb_ctx);
776 777
}