core.c 21.2 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
static GSList *registered_drivers = NULL;
115

Daniel Drake's avatar
Daniel Drake committed
116
static void register_driver(struct fp_driver *drv)
117
{
118
	if (drv->id == 0) {
119
		fp_err("not registering driver %s: driver ID is 0", drv->name);
120
121
		return;
	}
122
	registered_drivers = g_slist_prepend(registered_drivers, (gpointer) drv);
Daniel Drake's avatar
Daniel Drake committed
123
	fp_dbg("registered driver %s", drv->name);
124
125
}

126
#include "drivers_arrays.h"
Daniel Drake's avatar
Daniel Drake committed
127

128
129
static void register_drivers(void)
{
Daniel Drake's avatar
Daniel Drake committed
130
	unsigned int i;
131

Daniel Drake's avatar
Daniel Drake committed
132
	for (i = 0; i < G_N_ELEMENTS(primitive_drivers); i++)
Daniel Drake's avatar
Daniel Drake committed
133
134
		register_driver(primitive_drivers[i]);

Daniel Drake's avatar
Daniel Drake committed
135
	for (i = 0; i < G_N_ELEMENTS(img_drivers); i++) {
Daniel Drake's avatar
Daniel Drake committed
136
137
138
139
		struct fp_img_driver *imgdriver = img_drivers[i];
		fpi_img_driver_setup(imgdriver);
		register_driver(&imgdriver->driver);
	}
140
141
}

142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
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
160
static struct fp_driver *find_supporting_driver(libusb_device *udev,
161
	const struct usb_id **usb_id, uint32_t *devtype)
162
{
163
	int ret;
164
	GSList *elem = registered_drivers;
165
166
	struct libusb_device_descriptor dsc;

167
168
169
170
171
	const struct usb_id *best_usb_id;
	struct fp_driver *best_drv;
	uint32_t best_devtype;
	int drv_score = 0;

172
173
174
175
176
	ret = libusb_get_device_descriptor(udev, &dsc);
	if (ret < 0) {
		fp_err("Failed to get device descriptor");
		return NULL;
	}
177
178
179
180

	best_drv = NULL;
	best_devtype = 0;

181
	do {
Daniel Drake's avatar
Daniel Drake committed
182
		struct fp_driver *drv = elem->data;
183
		uint32_t type = 0;
184
185
		const struct usb_id *id;

186
		for (id = drv->id_table; id->vendor; id++) {
187
			if (dsc.idVendor == id->vendor && dsc.idProduct == id->product) {
188
189
190
191
192
193
194
195
196
197
198
199
200
201
				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
202
203
				fp_dbg("driver %s supports USB device %04x:%04x",
					drv->name, id->vendor, id->product);
204
205
206
207
208
209
210
				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
211
			}
212
		}
Daniel Drake's avatar
Daniel Drake committed
213
	} while ((elem = g_slist_next(elem)));
214

215
216
217
218
219
220
	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;
	}
221
222

	return best_drv;
223
224
}

Daniel Drake's avatar
Daniel Drake committed
225
static struct fp_dscv_dev *discover_dev(libusb_device *udev)
Daniel Drake's avatar
Daniel Drake committed
226
{
Daniel Drake's avatar
Daniel Drake committed
227
	const struct usb_id *usb_id;
228
	struct fp_driver *drv;
Daniel Drake's avatar
Daniel Drake committed
229
	struct fp_dscv_dev *ddev;
230
231
232
	uint32_t devtype;

	drv = find_supporting_driver(udev, &usb_id, &devtype);
Daniel Drake's avatar
Daniel Drake committed
233
234
235
236
237
238
239
240
241
242
243
244

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

245
246
247
/**
 * fp_discover_devs:
 *
Daniel Drake's avatar
Daniel Drake committed
248
249
 * Scans the system and returns a list of discovered devices. This is your
 * entry point into finding a fingerprint reader to operate.
250
251
 *
 * Returns: a %NULL-terminated list of discovered devices. Must be freed with
Daniel Drake's avatar
Daniel Drake committed
252
253
 * fp_dscv_devs_free() after use.
 */
254
255
API_EXPORTED struct fp_dscv_dev **fp_discover_devs(void)
{
256
	GSList *tmplist = NULL;
257
	struct fp_dscv_dev **list;
Daniel Drake's avatar
Daniel Drake committed
258
259
	libusb_device *udev;
	libusb_device **devs;
260
	int dscv_count = 0;
Daniel Drake's avatar
Daniel Drake committed
261
262
	int r;
	int i = 0;
263
264
265
266

	if (registered_drivers == NULL)
		return NULL;

Daniel Drake's avatar
Daniel Drake committed
267
	r = libusb_get_device_list(fpi_usb_ctx, &devs);
Daniel Drake's avatar
Daniel Drake committed
268
269
270
271
	if (r < 0) {
		fp_err("couldn't enumerate USB devices, error %d", r);
		return NULL;
	}
272
273

	/* Check each device against each driver, temporarily storing successfully
274
	 * discovered devices in a GSList.
275
276
277
	 *
	 * Quite inefficient but excusable as we'll only be dealing with small
	 * sets of drivers against small sets of USB devices */
Daniel Drake's avatar
Daniel Drake committed
278
279
280
281
	while ((udev = devs[i++]) != NULL) {
		struct fp_dscv_dev *ddev = discover_dev(udev);
		if (!ddev)
			continue;
282
283
284
		/* discover_dev() doesn't hold a reference to the udev,
		 * so increase the reference for ddev to hold this ref */
		libusb_ref_device(udev);
Daniel Drake's avatar
Daniel Drake committed
285
286
287
		tmplist = g_slist_prepend(tmplist, (gpointer) ddev);
		dscv_count++;
	}
288
	libusb_free_device_list(devs, 1);
289

290
	/* Convert our temporary GSList into a standard NULL-terminated pointer
291
292
293
	 * array. */
	list = g_malloc(sizeof(*list) * (dscv_count + 1));
	if (dscv_count > 0) {
294
		GSList *elem = tmplist;
Daniel Drake's avatar
Daniel Drake committed
295
		i = 0;
296
297
		do {
			list[i++] = elem->data;
Daniel Drake's avatar
Daniel Drake committed
298
		} while ((elem = g_slist_next(elem)));
299
300
301
	}
	list[dscv_count] = NULL; /* NULL-terminate */

302
	g_slist_free(tmplist);
303
304
305
	return list;
}

306
307
308
309
310
/**
 * fp_dscv_devs_free:
 * @devs: the list of discovered devices. If %NULL, function simply
 * returns.
 *
Daniel Drake's avatar
Daniel Drake committed
311
312
 * 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
313
 * discovered device <emphasis role="strong">before</emphasis> freeing the list.
Daniel Drake's avatar
Daniel Drake committed
314
 */
315
316
317
318
319
320
API_EXPORTED void fp_dscv_devs_free(struct fp_dscv_dev **devs)
{
	int i;
	if (!devs)
		return;

321
322
	for (i = 0; devs[i]; i++) {
		libusb_unref_device(devs[i]->udev);
323
		g_free(devs[i]);
324
	}
325
326
327
	g_free(devs);
}

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

341
342
343
344
345
346
347
348
349
350
351
/**
 * 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));
}

352
353
354
355
356
357
358
/**
 * 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
359
 */
Daniel Drake's avatar
Daniel Drake committed
360
361
362
363
364
API_EXPORTED uint32_t fp_dscv_dev_get_devtype(struct fp_dscv_dev *dev)
{
	return dev->devtype;
}

Daniel Drake's avatar
Daniel Drake committed
365
366
367
368
369
370
371
372
373
374
375
376
377
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;
	}
}

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

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

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

Daniel Drake's avatar
Daniel Drake committed
434
	for (i = 0; (ddev = devs[i]); i++)
435
		if (fp_dscv_dev_supports_print_data(ddev, print))
Daniel Drake's avatar
Daniel Drake committed
436
437
438
439
			return ddev;
	return NULL;
}

440
441
442
443
444
/**
 * fp_dscv_dev_for_dscv_print:
 * @devs: a list of discovered devices
 * @print: the print under inspection
 *
Daniel Drake's avatar
Daniel Drake committed
445
 * Searches a list of discovered devices for a device that appears to be
446
 * compatible with a #fp_dscv_print discovered print.
447
448
449
 *
 * Returns: the first discovered device that appears to support the print, or
 * %NULL if no apparently compatible devices could be found
450
451
 *
 * Deprecated: Do not use.
Daniel Drake's avatar
Daniel Drake committed
452
 */
Daniel Drake's avatar
Daniel Drake committed
453
454
455
456
457
458
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;

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

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

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

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

509
510
511
512
513
/**
 * fp_dev_supports_print_data:
 * @dev: the device
 * @data: the stored print
 *
Daniel Drake's avatar
Daniel Drake committed
514
 * Determines if a stored print is compatible with a certain device.
515
516
 *
 * Returns: 1 if the print is compatible with the device, 0 if not
Daniel Drake's avatar
Daniel Drake committed
517
 */
Daniel Drake's avatar
Daniel Drake committed
518
519
520
521
522
523
524
525
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);
}

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

545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
libusb_device_handle *
fpi_dev_get_usb_dev(struct fp_dev *dev)
{
	return dev->udev;
}

void *
fpi_dev_get_user_data (struct fp_dev *dev)
{
	return dev->priv;
}

void
fpi_dev_set_user_data (struct fp_dev *dev,
	void *user_data)
{
	dev->priv = user_data;
}

int
fpi_dev_get_nr_enroll_stages(struct fp_dev *dev)
{
	return dev->nr_enroll_stages;
}

void
fpi_dev_set_nr_enroll_stages(struct fp_dev *dev,
	int nr_enroll_stages)
{
	dev->nr_enroll_stages = nr_enroll_stages;
}

struct fp_print_data *
fpi_dev_get_verify_data(struct fp_dev *dev)
{
	return dev->verify_data;
}

enum fp_dev_state
fpi_dev_get_dev_state(struct fp_dev *dev)
{
	return dev->state;
}

589
590
591
592
/**
 * fp_driver_get_name:
 * @drv: the driver
 *
Daniel Drake's avatar
Daniel Drake committed
593
 * Retrieves the name of the driver. For example: "upekts"
594
595
 *
 * Returns: the driver name. Must not be modified or freed.
Daniel Drake's avatar
Daniel Drake committed
596
 */
Daniel Drake's avatar
Daniel Drake committed
597
API_EXPORTED const char *fp_driver_get_name(struct fp_driver *drv)
598
599
600
601
{
	return drv->name;
}

602
603
604
605
/**
 * fp_driver_get_full_name:
 * @drv: the driver
 *
Daniel Drake's avatar
Daniel Drake committed
606
 * Retrieves a descriptive name of the driver. For example: "UPEK TouchStrip"
607
608
 *
 * Returns: the descriptive name. Must not be modified or freed.
Daniel Drake's avatar
Daniel Drake committed
609
 */
Daniel Drake's avatar
Daniel Drake committed
610
API_EXPORTED const char *fp_driver_get_full_name(struct fp_driver *drv)
611
612
613
614
{
	return drv->full_name;
}

615
616
617
618
/**
 * fp_driver_get_driver_id:
 * @drv: the driver
 *
Daniel Drake's avatar
Daniel Drake committed
619
 * Retrieves the driver ID code for a driver.
620
621
 *
 * Returns: the driver ID
Daniel Drake's avatar
Daniel Drake committed
622
 */
Daniel Drake's avatar
Daniel Drake committed
623
624
625
626
627
API_EXPORTED uint16_t fp_driver_get_driver_id(struct fp_driver *drv)
{
	return drv->id;
}

628
629
630
631
/**
 * fp_driver_get_scan_type:
 * @drv: the driver
 *
632
 * Retrieves the scan type for the devices associated with the driver.
633
634
 *
 * Returns: the scan type
635
636
637
638
639
640
 */
API_EXPORTED enum fp_scan_type fp_driver_get_scan_type(struct fp_driver *drv)
{
	return drv->scan_type;
}

641
static struct fp_img_dev *dev_to_img_dev(struct fp_dev *dev)
642
643
644
645
646
647
{
	if (dev->drv->type != DRIVER_IMAGING)
		return NULL;
	return dev->priv;
}

648
649
650
651
/**
 * fp_dev_supports_imaging:
 * @dev: the fingerprint device
 *
Daniel Drake's avatar
Daniel Drake committed
652
653
654
 * 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
655
 * imaging devices – some do all processing in hardware. This function will
Daniel Drake's avatar
Daniel Drake committed
656
 * indicate which class a device in question falls into.
657
658
 *
 * Returns: 1 if the device is an imaging device, 0 if the device does not
Daniel Drake's avatar
Daniel Drake committed
659
660
 * provide images to the host computer
 */
661
662
API_EXPORTED int fp_dev_supports_imaging(struct fp_dev *dev)
{
663
	return dev->drv->capture_start != NULL;
664
665
}

666
667
668
669
670
/**
 * fp_dev_supports_identification:
 * @dev: the fingerprint device
 *
 * Determines if a device is capable of [identification](intro.html#identification)
Daniel Drake's avatar
Daniel Drake committed
671
672
 * through fp_identify_finger() and similar. Not all devices support this
 * functionality.
673
674
 *
 * Returns: 1 if the device is capable of identification, 0 otherwise.
Daniel Drake's avatar
Daniel Drake committed
675
676
677
 */
API_EXPORTED int fp_dev_supports_identification(struct fp_dev *dev)
{
678
	return dev->drv->identify_start != NULL;
Daniel Drake's avatar
Daniel Drake committed
679
680
}

681
682
683
684
/**
 * fp_dev_get_img_width:
 * @dev: the fingerprint device
 *
Daniel Drake's avatar
Daniel Drake committed
685
686
 * Gets the expected width of images that will be captured from the device.
 * This function will return -1 for devices that are not
687
 * [imaging devices](libfprint-Devices-operations.html#imaging). If the width of images from this device
Daniel Drake's avatar
Daniel Drake committed
688
 * can vary, 0 will be returned.
689
690
 *
 * Returns: the expected image width, or 0 for variable, or -1 for non-imaging
Daniel Drake's avatar
Daniel Drake committed
691
692
 * devices.
 */
693
694
695
696
697
698
699
700
701
702
703
API_EXPORTED int fp_dev_get_img_width(struct fp_dev *dev)
{
	struct fp_img_dev *imgdev = dev_to_img_dev(dev);
	if (!imgdev) {
		fp_dbg("get image width for non-imaging device");
		return -1;
	}

	return fpi_imgdev_get_img_width(imgdev);
}

704
705
706
707
/**
 * fp_dev_get_img_height:
 * @dev: the fingerprint device
 *
Daniel Drake's avatar
Daniel Drake committed
708
709
 * Gets the expected height of images that will be captured from the device.
 * This function will return -1 for devices that are not
710
 * [imaging devices](libfprint-Devices-operations.html#imaging). If the height of images from this device
Daniel Drake's avatar
Daniel Drake committed
711
 * can vary, 0 will be returned.
712
713
 *
 * Returns: the expected image height, or 0 for variable, or -1 for non-imaging
Daniel Drake's avatar
Daniel Drake committed
714
715
 * devices.
 */
716
717
718
719
720
721
722
723
724
725
726
API_EXPORTED int fp_dev_get_img_height(struct fp_dev *dev)
{
	struct fp_img_dev *imgdev = dev_to_img_dev(dev);
	if (!imgdev) {
		fp_dbg("get image height for non-imaging device");
		return -1;
	}

	return fpi_imgdev_get_img_height(imgdev);
}

727
728
729
730
/**
 * fp_set_debug:
 * @level: the verbosity level
 *
731
 * This call does nothing, see fp_init() for details.
Daniel Drake's avatar
Daniel Drake committed
732
733
734
 */
API_EXPORTED void fp_set_debug(int level)
{
735
	/* Nothing */
Daniel Drake's avatar
Daniel Drake committed
736
737
}

738
739
740
/**
 * fp_init:
 *
Daniel Drake's avatar
Daniel Drake committed
741
742
 * Initialise libfprint. This function must be called before you attempt to
 * use the library in any way.
743
 *
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
 * 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
 * ```
 *
761
 * Returns: 0 on success, non-zero on error.
Daniel Drake's avatar
Daniel Drake committed
762
 */
Daniel Drake's avatar
Daniel Drake committed
763
764
API_EXPORTED int fp_init(void)
{
765
	int r;
766
	G_DEBUG_HERE();
767

Daniel Drake's avatar
Daniel Drake committed
768
	r = libusb_init(&fpi_usb_ctx);
769
770
771
	if (r < 0)
		return r;

772
	register_drivers();
Daniel Drake's avatar
Daniel Drake committed
773
	fpi_poll_init();
Daniel Drake's avatar
Daniel Drake committed
774
775
	return 0;
}
776

777
778
779
/**
 * fp_exit:
 *
780
781
782
783
784
785
 * 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)
{
786
	G_DEBUG_HERE();
787

Daniel Drake's avatar
Daniel Drake committed
788
789
790
791
792
793
794
795
796
797
	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);
798
799
800
801
802
		g_slist_free(opened_devices);
		opened_devices = NULL;
	}

	fpi_data_exit();
803
	fpi_poll_exit();
804
805
	g_slist_free(registered_drivers);
	registered_drivers = NULL;
Daniel Drake's avatar
Daniel Drake committed
806
	libusb_exit(fpi_usb_ctx);
807
808
}