API documentation
This commit is contained in:
parent
7e6f25908b
commit
2e6c3b940c
9 changed files with 2038 additions and 16 deletions
|
@ -1,6 +1,6 @@
|
||||||
EXTRA_DIST = THANKS TODO HACKING libfprint.pc.in
|
EXTRA_DIST = THANKS TODO HACKING libfprint.pc.in
|
||||||
|
|
||||||
SUBDIRS = libfprint
|
SUBDIRS = libfprint doc
|
||||||
|
|
||||||
if BUILD_EXAMPLES
|
if BUILD_EXAMPLES
|
||||||
SUBDIRS += examples
|
SUBDIRS += examples
|
||||||
|
|
2
TODO
2
TODO
|
@ -7,6 +7,8 @@ make library optionally asynchronous and maybe thread-safe
|
||||||
nbis cleanups
|
nbis cleanups
|
||||||
track open devices, so we can close them during libfprint close
|
track open devices, so we can close them during libfprint close
|
||||||
free memory during libfprint close
|
free memory during libfprint close
|
||||||
|
API function to determine if img device supports uncond. capture
|
||||||
|
race-free way of saying "save this print but don't overwrite"
|
||||||
|
|
||||||
NEW DRIVERS
|
NEW DRIVERS
|
||||||
===========
|
===========
|
||||||
|
|
|
@ -85,6 +85,6 @@ AC_DEFINE([API_EXPORTED], [__attribute__((visibility("default")))], [Default vis
|
||||||
AM_CFLAGS="-Werror-implicit-function-declaration -Wimplicit-int -Wunreachable-code -Wunused-function -Wunused-label -Wunused-value -Wunused-variable -Wnonnull -Wreturn-type -Wextra -Wshadow"
|
AM_CFLAGS="-Werror-implicit-function-declaration -Wimplicit-int -Wunreachable-code -Wunused-function -Wunused-label -Wunused-value -Wunused-variable -Wnonnull -Wreturn-type -Wextra -Wshadow"
|
||||||
AC_SUBST(AM_CFLAGS)
|
AC_SUBST(AM_CFLAGS)
|
||||||
|
|
||||||
AC_CONFIG_FILES([libfprint.pc] [Makefile] [libfprint/Makefile] [examples/Makefile])
|
AC_CONFIG_FILES([libfprint.pc] [Makefile] [libfprint/Makefile] [examples/Makefile] [doc/Makefile])
|
||||||
AC_OUTPUT
|
AC_OUTPUT
|
||||||
|
|
||||||
|
|
10
doc/Makefile.am
Normal file
10
doc/Makefile.am
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
EXTRA_DIST = doxygen.cfg
|
||||||
|
|
||||||
|
docs: doxygen.cfg
|
||||||
|
doxygen $^
|
||||||
|
|
||||||
|
docs-upload: docs
|
||||||
|
ln -s html fprint-api
|
||||||
|
ncftpput -f ~/.ncftp/reactivated -m -R httpdocs fprint-api/
|
||||||
|
rm -f fprint-api
|
||||||
|
|
1294
doc/doxygen.cfg
Normal file
1294
doc/doxygen.cfg
Normal file
File diff suppressed because it is too large
Load diff
462
libfprint/core.c
462
libfprint/core.c
|
@ -26,6 +26,256 @@
|
||||||
|
|
||||||
#include "fp_internal.h"
|
#include "fp_internal.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \mainpage libfprint API Reference
|
||||||
|
* libfprint is an open source library to provide access to fingerprint
|
||||||
|
* scanning devices. For more info, see the
|
||||||
|
* <a href="http://www.reactivated.net/fprint/Libfprint">libfprint project
|
||||||
|
* homepage</a>.
|
||||||
|
*
|
||||||
|
* This documentation is aimed at application developers who wish to integrate
|
||||||
|
* fingerprint-related functionality into their software. libfprint has been
|
||||||
|
* designed so that you only have to do this once - by integrating your
|
||||||
|
* software with libfprint, you'll be supporting all the fingerprint readers
|
||||||
|
* that we have got our hands on. As such, the API is rather general (and
|
||||||
|
* therefore hopefully easy to comprehend!), and does it's best to hide the
|
||||||
|
* technical details that required to operate the hardware.
|
||||||
|
*
|
||||||
|
* This documentation is not aimed at developers wishing to develop and
|
||||||
|
* contribute fingerprint device drivers to libfprint.
|
||||||
|
*
|
||||||
|
* Feedback on this API and it's associated documentation is appreciated. Was
|
||||||
|
* anything unclear? Does anything seem unreasonably complicated? Is anything
|
||||||
|
* missing? Let us know on the
|
||||||
|
* <a href="http://www.reactivated.net/fprint/Mailing_list">mailing list</a>.
|
||||||
|
*
|
||||||
|
* \section enrollment Enrollment
|
||||||
|
*
|
||||||
|
* Before you dive into the API, it's worth introducing a couple of concepts.
|
||||||
|
*
|
||||||
|
* The process of enrolling a finger is where you effectively scan your
|
||||||
|
* finger for the purposes of teaching the system what your finger looks like.
|
||||||
|
* This means that you scan your fingerprint, then the system processes it and
|
||||||
|
* stores some data about your fingerprint to refer to later.
|
||||||
|
*
|
||||||
|
* \section verification Verification
|
||||||
|
*
|
||||||
|
* Verification is what most people think of when they think about fingerprint
|
||||||
|
* scanning. The process of verification is effectively performing a fresh
|
||||||
|
* fingerprint scan, and then comparing that scan to a finger that was
|
||||||
|
* previously enrolled.
|
||||||
|
*
|
||||||
|
* As an example scenario, verification can be used to implement what people
|
||||||
|
* would picture as fingerprint login (i.e. fingerprint replaces password).
|
||||||
|
* For example:
|
||||||
|
* - I enroll my fingerprint through some software that trusts I am who I say
|
||||||
|
* I am. This is a prerequisite before I can perform fingerprint-based
|
||||||
|
* login for my account.
|
||||||
|
* - Some time later, I want to login to my computer. I enter my username,
|
||||||
|
* but instead of prompting me for a password, it asks me to scan my finger.
|
||||||
|
* I scan my finger.
|
||||||
|
* - The system compares the finger I just scanned to the one that was
|
||||||
|
* enrolled earlier. If the system decides that the fingerprints match,
|
||||||
|
* I am successfully logged in. Otherwise, the system informs me that I am
|
||||||
|
* not authorised to login as that user.
|
||||||
|
*
|
||||||
|
* \section identification Identification
|
||||||
|
*
|
||||||
|
* libfprint supports enrollment and verification as described above. Although
|
||||||
|
* libfprint does not yet support identification (it is planned), it is worth
|
||||||
|
* introducing the concept to give you a complete picture.
|
||||||
|
*
|
||||||
|
* Identification is the process of comparing a freshly scanned fingerprint
|
||||||
|
* to a <em>collection</em> of previously enrolled fingerprints. For example,
|
||||||
|
* imagine there are 100 people in an organisation, and they all have enrolled
|
||||||
|
* their fingerprints. One user walks up to a fingerprint scanner and scans
|
||||||
|
* their finger. With <em>no other knowledge</em> of who that user might be,
|
||||||
|
* the system examines their fingerprint, looks in the database, and determines
|
||||||
|
* that the user is user number #61.
|
||||||
|
*
|
||||||
|
* In other words, verification might be seen as a one-to-one fingerprint
|
||||||
|
* comparison where you know the identity of the user that you wish to
|
||||||
|
* authenticate, whereas identification is a one-to-many comparison where you
|
||||||
|
* do not know the identity of the user that you wish to authenticate.
|
||||||
|
*
|
||||||
|
* \section compat_general Device and print compatibility
|
||||||
|
* Moving off generic conceptual ideas and onto libfprint-specific
|
||||||
|
* implementation details, here are some introductory notes regarding how
|
||||||
|
* libfprint copes with compatibility of fingerprints.
|
||||||
|
*
|
||||||
|
* libfprint deals with a whole variety of different fingerprint readers and
|
||||||
|
* the design includes considerations of compatibility and interoperability
|
||||||
|
* between multiple devices. Your application should also be prepared to
|
||||||
|
* work with more than one type of fingerprint reader and should consider that
|
||||||
|
* enrolled fingerprint X may not be compatible with the device the user has
|
||||||
|
* plugged in today.
|
||||||
|
*
|
||||||
|
* libfprint implements the principle that fingerprints from different devices
|
||||||
|
* are not necessarily compatible. For example, different devices may see
|
||||||
|
* significantly different areas of fingerprint surface, and comparing images
|
||||||
|
* between the devices would be unreliable. Also, devices can stretch and
|
||||||
|
* distort images in different ways.
|
||||||
|
*
|
||||||
|
* libfprint also implements the principle that in some cases, fingerprints
|
||||||
|
* <em>are</em> compatible between different devices. If you go and buy two
|
||||||
|
* identical fingerprint readers, it seems logical that you should be able
|
||||||
|
* to enroll on one and verify on another without problems.
|
||||||
|
*
|
||||||
|
* libfprint takes a fairly simplistic approach to these issues. Internally,
|
||||||
|
* fingerprint hardware is driven by individual drivers. libfprint enforces
|
||||||
|
* that a fingerprint that came from a device backed by driver X is never
|
||||||
|
* compared to a fingerprint that came from a device backed by driver Y.
|
||||||
|
*
|
||||||
|
* Additionally, libfprint is designed for the situation where a single driver
|
||||||
|
* may support a range of devices which differ in imaging or scanning
|
||||||
|
* properties. For example, a driver may support two ranges of devices which
|
||||||
|
* even though are programmed over the same interface, one device sees
|
||||||
|
* substantially less of the finger flesh, therefore images from the two
|
||||||
|
* device types should be incompatible despite being from the same driver. To
|
||||||
|
* implement this, each driver assigns a <em>device type</em> to each device
|
||||||
|
* that it detects based on its imaging characteristics. libfprint ensures that
|
||||||
|
* two prints being compared have the same device type.
|
||||||
|
*
|
||||||
|
* In summary, libfprint represents fingerprints in several internal structures
|
||||||
|
* and each representation will offer you a way of determining the
|
||||||
|
* \ref driver_id "driver ID" and \ref devtype "devtype" of the print in
|
||||||
|
* question. Prints are only compatible if the driver ID <b>and</b> devtypes
|
||||||
|
* match. libfprint does offer you some "is this print compatible?" helper
|
||||||
|
* functions, so you don't have to worry about these details too much.
|
||||||
|
*
|
||||||
|
* \section Synchronity/asynchronity
|
||||||
|
*
|
||||||
|
* Currently, all data acquisition operations are synchronous and can
|
||||||
|
* potentially block for extended periods of time. For example, the enroll
|
||||||
|
* function will block for an unpredictable amount of time until the user
|
||||||
|
* scans their finger.
|
||||||
|
*
|
||||||
|
* Alternative asynchronous/non-blocking functionality will be offered in
|
||||||
|
* future but has not been implemented yet.
|
||||||
|
*
|
||||||
|
* \section getting_started Getting started
|
||||||
|
*
|
||||||
|
* libfprint includes several simple functional examples under the examples/
|
||||||
|
* directory in the libfprint source distribution. Those are good starting
|
||||||
|
* points.
|
||||||
|
*
|
||||||
|
* Usually the first thing you want to do is determine which fingerprint
|
||||||
|
* devices are present. This is done through \ref dscv_dev "device discovery".
|
||||||
|
*
|
||||||
|
* Once you have found a device you would like to operate, you should open it.
|
||||||
|
* Refer to \ref dev "device operations". This section also details enrollment,
|
||||||
|
* image capture, and verification.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* That should be enough to get you started, but do remember there are
|
||||||
|
* documentation pages on other aspects of libfprint's API (see the modules
|
||||||
|
* page).
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @defgroup core Core library operations */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @defgroup dev Device operations
|
||||||
|
* In order to interact with fingerprint scanners, your software will
|
||||||
|
* interface primarily with libfprint's representation of devices, detailed
|
||||||
|
* on this page.
|
||||||
|
*
|
||||||
|
* \section enrolling Enrolling
|
||||||
|
* 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
|
||||||
|
* to your application inbetween each scan in order for your application to
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* \section imaging Imaging
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* \section devtype Devtypes
|
||||||
|
* Internally, the \ref drv "driver" behind a device assigns a 32-bit
|
||||||
|
* <em>devtype</em> identifier to the device. This cannot be used as a unique
|
||||||
|
* ID for a specific device as many devices under the same range may share
|
||||||
|
* the same devtype. The devtype may even be 0 in all cases.
|
||||||
|
*
|
||||||
|
* The only reason you may be interested in retrieving the devtype for a
|
||||||
|
* device is for the purpose of checking if some print data is compatible
|
||||||
|
* with a device. libfprint uses the devtype as one way of checking that the
|
||||||
|
* print you are verifying is compatible with the device in question - the
|
||||||
|
* devtypes must be equal. This effectively allows drivers to support more
|
||||||
|
* than one type of device where the data from each one is not compatible with
|
||||||
|
* the other. Note that libfprint does provide you with helper functions to
|
||||||
|
* determine whether a print is compatible with a device, so under most
|
||||||
|
* circumstances, you don't have to worry about devtypes at all.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @defgroup dscv_dev 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @defgroup drv 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.
|
||||||
|
*
|
||||||
|
* \section driver_id Driver IDs
|
||||||
|
* Each driver is assigned a unique ID by the project maintainer. These
|
||||||
|
* assignments are
|
||||||
|
* <a href="http://www.reactivated.net/fprint/Driver_ID_assignments">
|
||||||
|
* documented on the wiki</a> and will never change.
|
||||||
|
*
|
||||||
|
* The only reason you may be interested in retrieving the driver ID for a
|
||||||
|
* driver is for the purpose of checking if some print data is compatible
|
||||||
|
* with a device. libfprint uses the driver ID as one way of checking that
|
||||||
|
* the print you are trying to verify is compatible with the device in
|
||||||
|
* question - it ensures that enrollment data from one driver is never fed to
|
||||||
|
* another. Note that libfprint does provide you with helper functions to
|
||||||
|
* determine whether a print is compatible with a device, so under most
|
||||||
|
* circumstances, you don't have to worry about driver IDs at all.
|
||||||
|
*/
|
||||||
|
|
||||||
static GList *registered_drivers = NULL;
|
static GList *registered_drivers = NULL;
|
||||||
|
|
||||||
void fpi_log(enum fpi_log_level level, const char *component,
|
void fpi_log(enum fpi_log_level level, const char *component,
|
||||||
|
@ -147,6 +397,12 @@ static struct fp_dscv_dev *discover_dev(struct usb_device *udev)
|
||||||
return ddev;
|
return ddev;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** \ingroup dscv_dev
|
||||||
|
* Scans the system and returns a list of discovered devices. This is your
|
||||||
|
* entry point into finding a fingerprint reader to operate.
|
||||||
|
* \returns a NULL-terminated list of discovered devices. Must be freed with
|
||||||
|
* fp_dscv_devs_free() after use.
|
||||||
|
*/
|
||||||
API_EXPORTED struct fp_dscv_dev **fp_discover_devs(void)
|
API_EXPORTED struct fp_dscv_dev **fp_discover_devs(void)
|
||||||
{
|
{
|
||||||
GList *tmplist = NULL;
|
GList *tmplist = NULL;
|
||||||
|
@ -191,6 +447,12 @@ API_EXPORTED struct fp_dscv_dev **fp_discover_devs(void)
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** \ingroup dscv_dev
|
||||||
|
* 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
|
||||||
|
* discovered device <b>before</b> freeing the list.
|
||||||
|
* \param devs the list of discovered devices
|
||||||
|
*/
|
||||||
API_EXPORTED void fp_dscv_devs_free(struct fp_dscv_dev **devs)
|
API_EXPORTED void fp_dscv_devs_free(struct fp_dscv_dev **devs)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
@ -202,11 +464,21 @@ API_EXPORTED void fp_dscv_devs_free(struct fp_dscv_dev **devs)
|
||||||
g_free(devs);
|
g_free(devs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** \ingroup dscv_dev
|
||||||
|
* Gets the \ref drv "driver" for a discovered device.
|
||||||
|
* \param dev the discovered device
|
||||||
|
* \returns the driver backing the device
|
||||||
|
*/
|
||||||
API_EXPORTED struct fp_driver *fp_dscv_dev_get_driver(struct fp_dscv_dev *dev)
|
API_EXPORTED struct fp_driver *fp_dscv_dev_get_driver(struct fp_dscv_dev *dev)
|
||||||
{
|
{
|
||||||
return dev->drv;
|
return dev->drv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** \ingroup dscv_dev
|
||||||
|
* Gets the \ref devtype "devtype" for a discovered device.
|
||||||
|
* \param dev the discovered device
|
||||||
|
* \returns the devtype of the device
|
||||||
|
*/
|
||||||
API_EXPORTED uint32_t fp_dscv_dev_get_devtype(struct fp_dscv_dev *dev)
|
API_EXPORTED uint32_t fp_dscv_dev_get_devtype(struct fp_dscv_dev *dev)
|
||||||
{
|
{
|
||||||
return dev->devtype;
|
return dev->devtype;
|
||||||
|
@ -225,6 +497,13 @@ enum fp_print_data_type fpi_driver_get_data_type(struct fp_driver *drv)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** \ingroup dscv_dev
|
||||||
|
* Determines if a specific \ref print_data "stored print" appears to be
|
||||||
|
* compatible with a discovered device.
|
||||||
|
* \param dev the discovered device
|
||||||
|
* \param data the print for compatibility checking
|
||||||
|
* \returns 1 if the print is compatible with the device, 0 otherwise
|
||||||
|
*/
|
||||||
API_EXPORTED int fp_dscv_dev_supports_print_data(struct fp_dscv_dev *dev,
|
API_EXPORTED int fp_dscv_dev_supports_print_data(struct fp_dscv_dev *dev,
|
||||||
struct fp_print_data *data)
|
struct fp_print_data *data)
|
||||||
{
|
{
|
||||||
|
@ -233,6 +512,13 @@ API_EXPORTED int fp_dscv_dev_supports_print_data(struct fp_dscv_dev *dev,
|
||||||
data->type);
|
data->type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** \ingroup dscv_dev
|
||||||
|
* Determines if a specific \ref dscv_print "discovered print" appears to be
|
||||||
|
* compatible with a discovered device.
|
||||||
|
* \param dev the discovered device
|
||||||
|
* \param data the discovered print for compatibility checking
|
||||||
|
* \returns 1 if the print is compatible with the device, 0 otherwise
|
||||||
|
*/
|
||||||
API_EXPORTED int fp_dscv_dev_supports_dscv_print(struct fp_dscv_dev *dev,
|
API_EXPORTED int fp_dscv_dev_supports_dscv_print(struct fp_dscv_dev *dev,
|
||||||
struct fp_dscv_print *data)
|
struct fp_dscv_print *data)
|
||||||
{
|
{
|
||||||
|
@ -240,6 +526,14 @@ API_EXPORTED int fp_dscv_dev_supports_dscv_print(struct fp_dscv_dev *dev,
|
||||||
data->driver_id, data->devtype, 0);
|
data->driver_id, data->devtype, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** \ingroup dscv_dev
|
||||||
|
* Searches a list of discovered devices for a device that appears to be
|
||||||
|
* compatible with a \ref print_data "stored print".
|
||||||
|
* \param devs a list of discovered devices
|
||||||
|
* \param data the print under inspection
|
||||||
|
* \returns the first discovered device that appears to support the print, or
|
||||||
|
* NULL if no apparently compatible devices could be found
|
||||||
|
*/
|
||||||
API_EXPORTED struct fp_dscv_dev *fp_dscv_dev_for_print_data(struct fp_dscv_dev **devs,
|
API_EXPORTED struct fp_dscv_dev *fp_dscv_dev_for_print_data(struct fp_dscv_dev **devs,
|
||||||
struct fp_print_data *data)
|
struct fp_print_data *data)
|
||||||
{
|
{
|
||||||
|
@ -252,6 +546,14 @@ API_EXPORTED struct fp_dscv_dev *fp_dscv_dev_for_print_data(struct fp_dscv_dev *
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** \ingroup dscv_dev
|
||||||
|
* Searches a list of discovered devices for a device that appears to be
|
||||||
|
* compatible with a \ref dscv_print "discovered print".
|
||||||
|
* \param devs a list of discovered devices
|
||||||
|
* \param print the print under inspection
|
||||||
|
* \returns the first discovered device that appears to support the print, or
|
||||||
|
* NULL if no apparently compatible devices could be found
|
||||||
|
*/
|
||||||
API_EXPORTED struct fp_dscv_dev *fp_dscv_dev_for_dscv_print(struct fp_dscv_dev **devs,
|
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_print *print)
|
||||||
{
|
{
|
||||||
|
@ -264,6 +566,13 @@ API_EXPORTED struct fp_dscv_dev *fp_dscv_dev_for_dscv_print(struct fp_dscv_dev *
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** \ingroup dev
|
||||||
|
* Opens and initialises a device. This is the function you call in order
|
||||||
|
* to convert a \ref dscv_dev "discovered device" into an actual device handle
|
||||||
|
* that you can perform operations with.
|
||||||
|
* \param ddev the discovered device to open
|
||||||
|
* \returns the opened device handle, or NULL on error
|
||||||
|
*/
|
||||||
API_EXPORTED struct fp_dev *fp_dev_open(struct fp_dscv_dev *ddev)
|
API_EXPORTED struct fp_dev *fp_dev_open(struct fp_dscv_dev *ddev)
|
||||||
{
|
{
|
||||||
struct fp_dev *dev;
|
struct fp_dev *dev;
|
||||||
|
@ -295,6 +604,11 @@ API_EXPORTED struct fp_dev *fp_dev_open(struct fp_dscv_dev *ddev)
|
||||||
return dev;
|
return dev;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** \ingroup dev
|
||||||
|
* Close a device. You must call this function when you are finished using
|
||||||
|
* a fingerprint device.
|
||||||
|
* \param dev the device to close
|
||||||
|
*/
|
||||||
API_EXPORTED void fp_dev_close(struct fp_dev *dev)
|
API_EXPORTED void fp_dev_close(struct fp_dev *dev)
|
||||||
{
|
{
|
||||||
fp_dbg("");
|
fp_dbg("");
|
||||||
|
@ -304,21 +618,43 @@ API_EXPORTED void fp_dev_close(struct fp_dev *dev)
|
||||||
g_free(dev);
|
g_free(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** \ingroup dev
|
||||||
|
* Get the \ref drv "driver" for a fingerprint device.
|
||||||
|
* \param dev the device
|
||||||
|
* \returns the driver controlling the device
|
||||||
|
*/
|
||||||
API_EXPORTED struct fp_driver *fp_dev_get_driver(struct fp_dev *dev)
|
API_EXPORTED struct fp_driver *fp_dev_get_driver(struct fp_dev *dev)
|
||||||
{
|
{
|
||||||
return dev->drv;
|
return dev->drv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** \ingroup dev
|
||||||
|
* Gets the number of \ref enrolling "enroll stages" required to enroll a
|
||||||
|
* fingerprint with the device.
|
||||||
|
* \param dev the device
|
||||||
|
* \returns the number of enroll stages
|
||||||
|
*/
|
||||||
API_EXPORTED int fp_dev_get_nr_enroll_stages(struct fp_dev *dev)
|
API_EXPORTED int fp_dev_get_nr_enroll_stages(struct fp_dev *dev)
|
||||||
{
|
{
|
||||||
return dev->nr_enroll_stages;
|
return dev->nr_enroll_stages;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** \ingroup dev
|
||||||
|
* Gets the \ref devtype "devtype" for a device.
|
||||||
|
* \param dev the device
|
||||||
|
* \returns the devtype
|
||||||
|
*/
|
||||||
API_EXPORTED uint32_t fp_dev_get_devtype(struct fp_dev *dev)
|
API_EXPORTED uint32_t fp_dev_get_devtype(struct fp_dev *dev)
|
||||||
{
|
{
|
||||||
return dev->devtype;
|
return dev->devtype;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** \ingroup dev
|
||||||
|
* Determines if a stored print is compatible with a certain device.
|
||||||
|
* \param dev the device
|
||||||
|
* \param data the stored print
|
||||||
|
* \returns 1 if the print is compatible with the device, 0 if not
|
||||||
|
*/
|
||||||
API_EXPORTED int fp_dev_supports_print_data(struct fp_dev *dev,
|
API_EXPORTED int fp_dev_supports_print_data(struct fp_dev *dev,
|
||||||
struct fp_print_data *data)
|
struct fp_print_data *data)
|
||||||
{
|
{
|
||||||
|
@ -327,6 +663,13 @@ API_EXPORTED int fp_dev_supports_print_data(struct fp_dev *dev,
|
||||||
data->type);
|
data->type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** \ingroup dev
|
||||||
|
* Determines if a \ref dscv_print "discovered print" appears to be compatible
|
||||||
|
* with a certain device.
|
||||||
|
* \param dev the device
|
||||||
|
* \param data the discovered print
|
||||||
|
* \returns 1 if the print is compatible with the device, 0 if not
|
||||||
|
*/
|
||||||
API_EXPORTED int fp_dev_supports_dscv_print(struct fp_dev *dev,
|
API_EXPORTED int fp_dev_supports_dscv_print(struct fp_dev *dev,
|
||||||
struct fp_dscv_print *data)
|
struct fp_dscv_print *data)
|
||||||
{
|
{
|
||||||
|
@ -334,16 +677,31 @@ API_EXPORTED int fp_dev_supports_dscv_print(struct fp_dev *dev,
|
||||||
0, data->driver_id, data->devtype, 0);
|
0, data->driver_id, data->devtype, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** \ingroup drv
|
||||||
|
* Retrieves the name of the driver. For example: "upekts"
|
||||||
|
* \param drv the driver
|
||||||
|
* \returns the driver name. Must not be modified or freed.
|
||||||
|
*/
|
||||||
API_EXPORTED const char *fp_driver_get_name(struct fp_driver *drv)
|
API_EXPORTED const char *fp_driver_get_name(struct fp_driver *drv)
|
||||||
{
|
{
|
||||||
return drv->name;
|
return drv->name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** \ingroup drv
|
||||||
|
* Retrieves a descriptive name of the driver. For example: "UPEK TouchStrip"
|
||||||
|
* \param drv the driver
|
||||||
|
* \returns the descriptive name. Must not be modified or freed.
|
||||||
|
*/
|
||||||
API_EXPORTED const char *fp_driver_get_full_name(struct fp_driver *drv)
|
API_EXPORTED const char *fp_driver_get_full_name(struct fp_driver *drv)
|
||||||
{
|
{
|
||||||
return drv->full_name;
|
return drv->full_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** \ingroup drv
|
||||||
|
* Retrieves the driver ID code for a driver.
|
||||||
|
* \param drv the driver
|
||||||
|
* \returns the driver ID
|
||||||
|
*/
|
||||||
API_EXPORTED uint16_t fp_driver_get_driver_id(struct fp_driver *drv)
|
API_EXPORTED uint16_t fp_driver_get_driver_id(struct fp_driver *drv)
|
||||||
{
|
{
|
||||||
return drv->id;
|
return drv->id;
|
||||||
|
@ -356,11 +714,39 @@ static struct fp_img_dev *dev_to_img_dev(struct fp_dev *dev)
|
||||||
return dev->priv;
|
return dev->priv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** \ingroup dev
|
||||||
|
* 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
|
||||||
|
* imaging devices - some do all processing in hardware. This function will
|
||||||
|
* indicate which class a device in question falls into.
|
||||||
|
* \param dev the fingerprint device
|
||||||
|
* \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_dev_supports_imaging(struct fp_dev *dev)
|
API_EXPORTED int fp_dev_supports_imaging(struct fp_dev *dev)
|
||||||
{
|
{
|
||||||
return dev->drv->type == DRIVER_IMAGING;
|
return dev->drv->type == DRIVER_IMAGING;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** \ingroup dev
|
||||||
|
* Captures an \ref img "image" from a device. The returned image is the raw
|
||||||
|
* image provided by the device, you may wish to \ref img_std "standardize" it.
|
||||||
|
*
|
||||||
|
* If set, the <tt>unconditional</tt> flag indicates that the device should
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* \param dev the device
|
||||||
|
* \param unconditional whether to unconditionally capture an image, or to only capture when a finger is detected
|
||||||
|
* \param image a location to return the captured image. Must be freed with
|
||||||
|
* fp_img_free() after use.
|
||||||
|
* \return 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
|
||||||
|
* device does not support imaging.
|
||||||
|
* \sa fp_dev_supports_imaging()
|
||||||
|
*/
|
||||||
API_EXPORTED int fp_dev_img_capture(struct fp_dev *dev, int unconditional,
|
API_EXPORTED int fp_dev_img_capture(struct fp_dev *dev, int unconditional,
|
||||||
struct fp_img **image)
|
struct fp_img **image)
|
||||||
{
|
{
|
||||||
|
@ -373,6 +759,15 @@ API_EXPORTED int fp_dev_img_capture(struct fp_dev *dev, int unconditional,
|
||||||
return fpi_imgdev_capture(imgdev, unconditional, image);
|
return fpi_imgdev_capture(imgdev, unconditional, image);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** \ingroup dev
|
||||||
|
* Gets the expected width of images that will be captured from the device.
|
||||||
|
* This function will return -1 for devices that are not
|
||||||
|
* \ref imaging "imaging devices". If the width of images from this device
|
||||||
|
* can vary, 0 will be returned.
|
||||||
|
* \param dev the device
|
||||||
|
* \returns the expected image width, or 0 for variable, or -1 for non-imaging
|
||||||
|
* devices.
|
||||||
|
*/
|
||||||
API_EXPORTED int fp_dev_get_img_width(struct fp_dev *dev)
|
API_EXPORTED int fp_dev_get_img_width(struct fp_dev *dev)
|
||||||
{
|
{
|
||||||
struct fp_img_dev *imgdev = dev_to_img_dev(dev);
|
struct fp_img_dev *imgdev = dev_to_img_dev(dev);
|
||||||
|
@ -384,6 +779,15 @@ API_EXPORTED int fp_dev_get_img_width(struct fp_dev *dev)
|
||||||
return fpi_imgdev_get_img_width(imgdev);
|
return fpi_imgdev_get_img_width(imgdev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** \ingroup dev
|
||||||
|
* Gets the expected height of images that will be captured from the device.
|
||||||
|
* This function will return -1 for devices that are not
|
||||||
|
* \ref imaging "imaging devices". If the height of images from this device
|
||||||
|
* can vary, 0 will be returned.
|
||||||
|
* \param dev the device
|
||||||
|
* \returns the expected image height, or 0 for variable, or -1 for non-imaging
|
||||||
|
* devices.
|
||||||
|
*/
|
||||||
API_EXPORTED int fp_dev_get_img_height(struct fp_dev *dev)
|
API_EXPORTED int fp_dev_get_img_height(struct fp_dev *dev)
|
||||||
{
|
{
|
||||||
struct fp_img_dev *imgdev = dev_to_img_dev(dev);
|
struct fp_img_dev *imgdev = dev_to_img_dev(dev);
|
||||||
|
@ -395,6 +799,51 @@ API_EXPORTED int fp_dev_get_img_height(struct fp_dev *dev)
|
||||||
return fpi_imgdev_get_img_height(imgdev);
|
return fpi_imgdev_get_img_height(imgdev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** \ingroup dev
|
||||||
|
* Performs an enroll stage. See \ref enrolling for an explanation of enroll
|
||||||
|
* stages.
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
* is returned, the enrollment stage is <b>not</b> advanced, so the next call
|
||||||
|
* into this function will retry the current stage again. The current stage may
|
||||||
|
* need to be retried several times.
|
||||||
|
*
|
||||||
|
* The fp_enroll_result#FP_ENROLL_FAIL code may be returned from any enroll
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* The fp_enroll_result#FP_ENROLL_PASS code will only ever be returned for
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* The fp_enroll_result#FP_ENROLL_COMPLETE code will only ever be returned
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* \param dev the device
|
||||||
|
* \param print_data a location to return the resultant enrollment data from
|
||||||
|
* the final stage. Must be freed with fp_print_data_free() after use.
|
||||||
|
* \return negative code on error, otherwise a code from #fp_verify_result
|
||||||
|
*/
|
||||||
API_EXPORTED int fp_enroll_finger(struct fp_dev *dev,
|
API_EXPORTED int fp_enroll_finger(struct fp_dev *dev,
|
||||||
struct fp_print_data **print_data)
|
struct fp_print_data **print_data)
|
||||||
{
|
{
|
||||||
|
@ -462,6 +911,13 @@ API_EXPORTED int fp_enroll_finger(struct fp_dev *dev,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** \ingroup dev
|
||||||
|
* Performs a new scan and verify it against a previously enrolled print.
|
||||||
|
* \param dev the device to perform the scan.
|
||||||
|
* \param enrolled_print the print to verify against. Must have been previously
|
||||||
|
* enrolled with a device compatible to the device selected to perform the scan.
|
||||||
|
* \return negative code on error, otherwise a code from #fp_verify_result
|
||||||
|
*/
|
||||||
API_EXPORTED int fp_verify_finger(struct fp_dev *dev,
|
API_EXPORTED int fp_verify_finger(struct fp_dev *dev,
|
||||||
struct fp_print_data *enrolled_print)
|
struct fp_print_data *enrolled_print)
|
||||||
{
|
{
|
||||||
|
@ -517,6 +973,11 @@ API_EXPORTED int fp_verify_finger(struct fp_dev *dev,
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** \ingroup core
|
||||||
|
* Initialise libfprint. This function must be called before you attempt to
|
||||||
|
* use the library in any way.
|
||||||
|
* \return 0 on success, non-zero on error.
|
||||||
|
*/
|
||||||
API_EXPORTED int fp_init(void)
|
API_EXPORTED int fp_init(void)
|
||||||
{
|
{
|
||||||
fp_dbg("");
|
fp_dbg("");
|
||||||
|
@ -525,4 +986,3 @@ API_EXPORTED int fp_init(void)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
162
libfprint/data.c
162
libfprint/data.c
|
@ -30,6 +30,21 @@
|
||||||
|
|
||||||
#define DIR_PERMS 0700
|
#define DIR_PERMS 0700
|
||||||
|
|
||||||
|
/** @defgroup print_data Stored prints
|
||||||
|
* Stored prints are represented by a structure named <tt>fp_print_data</tt>.
|
||||||
|
* Stored prints are originally obtained from an enrollment function such as
|
||||||
|
* fp_enroll_finger().
|
||||||
|
*
|
||||||
|
* This page documents the various operations you can do with a stored print.
|
||||||
|
* Note that by default, "stored prints" are not actually stored anywhere
|
||||||
|
* except in RAM. For the simple scenarios, libfprint provides a simple API
|
||||||
|
* for you to save and load the stored prints referring to a single user in
|
||||||
|
* their home directory. For more advanced users, libfprint provides APIs for
|
||||||
|
* you to convert print data to a byte string, and to reconstruct stored prints
|
||||||
|
* from such data at a later point. You are welcome to store these byte strings
|
||||||
|
* in any fashion that suits you.
|
||||||
|
*/
|
||||||
|
|
||||||
/* FIXME: should free this during library shutdown */
|
/* FIXME: should free this during library shutdown */
|
||||||
static char *base_store = NULL;
|
static char *base_store = NULL;
|
||||||
|
|
||||||
|
@ -92,6 +107,15 @@ struct fp_print_data *fpi_print_data_new(struct fp_dev *dev, size_t length)
|
||||||
fpi_driver_get_data_type(dev->drv), length);
|
fpi_driver_get_data_type(dev->drv), length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** \ingroup print_data
|
||||||
|
* Convert a stored print into a unified representation inside a data buffer.
|
||||||
|
* You can then store this data buffer in any way that suits you, and load
|
||||||
|
* it back at some later time using fp_print_data_from_data().
|
||||||
|
* \param data the stored print
|
||||||
|
* \param ret output location for the data buffer. Must be freed with free()
|
||||||
|
* after use.
|
||||||
|
* \returns the size of the freshly allocated buffer, or 0 on error.
|
||||||
|
*/
|
||||||
API_EXPORTED size_t fp_print_data_get_data(struct fp_print_data *data,
|
API_EXPORTED size_t fp_print_data_get_data(struct fp_print_data *data,
|
||||||
unsigned char **ret)
|
unsigned char **ret)
|
||||||
{
|
{
|
||||||
|
@ -116,6 +140,15 @@ API_EXPORTED size_t fp_print_data_get_data(struct fp_print_data *data,
|
||||||
return buflen;
|
return buflen;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** \ingroup print_data
|
||||||
|
* Load a stored print from a data buffer. The contents of said buffer must
|
||||||
|
* be the untouched contents of a buffer previously supplied to you by the
|
||||||
|
* fp_print_data_get_data() function.
|
||||||
|
* \param buf the data buffer
|
||||||
|
* \param buflen the length of the buffer
|
||||||
|
* \returns the stored print represented by the data, or NULL on error. Must
|
||||||
|
* be freed with fp_print_data_free() after use.
|
||||||
|
*/
|
||||||
API_EXPORTED struct fp_print_data *fp_print_data_from_data(unsigned char *buf,
|
API_EXPORTED struct fp_print_data *fp_print_data_from_data(unsigned char *buf,
|
||||||
size_t buflen)
|
size_t buflen)
|
||||||
{
|
{
|
||||||
|
@ -170,6 +203,21 @@ static char *get_path_to_print(struct fp_dev *dev, enum fp_finger finger)
|
||||||
return __get_path_to_print(dev->drv->id, dev->devtype, finger);
|
return __get_path_to_print(dev->drv->id, dev->devtype, finger);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** \ingroup print_data
|
||||||
|
* Saves a stored print to disk, assigned to a specific finger. Even though
|
||||||
|
* you are limited to storing only the 10 human fingers, this is a
|
||||||
|
* per-device-type limit. For example, you can store the users right index
|
||||||
|
* finger from a DigitalPersona scanner, and you can also save the right index
|
||||||
|
* finger from a UPEK scanner. When you later come to load the print, the right
|
||||||
|
* one will be automatically selected.
|
||||||
|
*
|
||||||
|
* This function will unconditionally overwrite a fingerprint previously
|
||||||
|
* saved for the same finger and device type. The print is saved in a hidden
|
||||||
|
* directory beneath the current user's home directory.
|
||||||
|
* \param data the stored print to save to disk
|
||||||
|
* \param finger the finger that this print corresponds to
|
||||||
|
* \returns 0 on success, non-zero on error.
|
||||||
|
*/
|
||||||
API_EXPORTED int fp_print_data_save(struct fp_print_data *data,
|
API_EXPORTED int fp_print_data_save(struct fp_print_data *data,
|
||||||
enum fp_finger finger)
|
enum fp_finger finger)
|
||||||
{
|
{
|
||||||
|
@ -242,6 +290,7 @@ static int load_from_file(char *path, struct fp_print_data **data)
|
||||||
gsize length;
|
gsize length;
|
||||||
gchar *contents;
|
gchar *contents;
|
||||||
GError *err = NULL;
|
GError *err = NULL;
|
||||||
|
struct fp_print_data *fdata;
|
||||||
|
|
||||||
fp_dbg("from %s", path);
|
fp_dbg("from %s", path);
|
||||||
g_file_get_contents(path, &contents, &length, &err);
|
g_file_get_contents(path, &contents, &length, &err);
|
||||||
|
@ -256,11 +305,28 @@ static int load_from_file(char *path, struct fp_print_data **data)
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
*data = fp_print_data_from_data(contents, length);
|
fdata = fp_print_data_from_data(contents, length);
|
||||||
g_free(contents);
|
g_free(contents);
|
||||||
|
if (!fdata)
|
||||||
|
return -EIO;
|
||||||
|
*data = fdata;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** \ingroup print_data
|
||||||
|
* Loads a previously stored print from disk. The print must have been saved
|
||||||
|
* earlier using the fp_print_data_save() function.
|
||||||
|
*
|
||||||
|
* A return code of -ENOENT indicates that the fingerprint requested could not
|
||||||
|
* be found. Other error codes (both positive and negative) are possible for
|
||||||
|
* obscure error conditions (e.g. corruption).
|
||||||
|
*
|
||||||
|
* \param dev the device you are loading the print for
|
||||||
|
* \param finger the finger of the file you are loading
|
||||||
|
* \param data output location to put the corresponding stored print. Must be
|
||||||
|
* freed with fp_print_data_free() after use.
|
||||||
|
* \returns 0 on success, non-zero on error
|
||||||
|
*/
|
||||||
API_EXPORTED int fp_print_data_load(struct fp_dev *dev,
|
API_EXPORTED int fp_print_data_load(struct fp_dev *dev,
|
||||||
enum fp_finger finger, struct fp_print_data **data)
|
enum fp_finger finger, struct fp_print_data **data)
|
||||||
{
|
{
|
||||||
|
@ -287,27 +353,89 @@ API_EXPORTED int fp_print_data_load(struct fp_dev *dev,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** \ingroup print_data
|
||||||
|
* Attempts to load a stored print based on a \ref dscv_print
|
||||||
|
* "discovered print" record.
|
||||||
|
*
|
||||||
|
* A return code of -ENOENT indicates that the file referred to by the
|
||||||
|
* discovered print could not be found. Other error codes (both positive and
|
||||||
|
* negative) are possible for obscure error conditions (e.g. corruption).
|
||||||
|
*
|
||||||
|
* \param print the discovered print
|
||||||
|
* \param data output location to point to the corresponding stored print. Must
|
||||||
|
* be freed with fp_print_data_free() after use.
|
||||||
|
* \returns 0 on success, non-zero on error.
|
||||||
|
*/
|
||||||
API_EXPORTED int fp_print_data_from_dscv_print(struct fp_dscv_print *print,
|
API_EXPORTED int fp_print_data_from_dscv_print(struct fp_dscv_print *print,
|
||||||
struct fp_print_data **data)
|
struct fp_print_data **data)
|
||||||
{
|
{
|
||||||
return load_from_file(print->path, data);
|
return load_from_file(print->path, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** \ingroup print_data
|
||||||
|
* Frees a stored print. Must be called when you are finished using the print.
|
||||||
|
* \param data the stored print to destroy
|
||||||
|
*/
|
||||||
API_EXPORTED void fp_print_data_free(struct fp_print_data *data)
|
API_EXPORTED void fp_print_data_free(struct fp_print_data *data)
|
||||||
{
|
{
|
||||||
g_free(data);
|
g_free(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** \ingroup print_data
|
||||||
|
* Gets the \ref driver_id "driver ID" for a stored print. The driver ID
|
||||||
|
* indicates which driver the print originally came from. The print is
|
||||||
|
* only usable with a device controlled by that driver.
|
||||||
|
* \param data the stored print
|
||||||
|
* \returns the driver ID of the driver compatible with the print
|
||||||
|
*/
|
||||||
API_EXPORTED uint16_t fp_print_data_get_driver_id(struct fp_print_data *data)
|
API_EXPORTED uint16_t fp_print_data_get_driver_id(struct fp_print_data *data)
|
||||||
{
|
{
|
||||||
return data->driver_id;
|
return data->driver_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** \ingroup print_data
|
||||||
|
* Gets the \ref devtype "devtype" for a stored print. The devtype represents
|
||||||
|
* which type of device under the parent driver is compatible with the print.
|
||||||
|
* \param data the stored print
|
||||||
|
* \returns the devtype of the device range compatible with the print
|
||||||
|
*/
|
||||||
API_EXPORTED uint32_t fp_print_data_get_devtype(struct fp_print_data *data)
|
API_EXPORTED uint32_t fp_print_data_get_devtype(struct fp_print_data *data)
|
||||||
{
|
{
|
||||||
return data->devtype;
|
return data->devtype;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @defgroup dscv_print Print discovery
|
||||||
|
* The \ref print_data "stored print" documentation detailed a simple API
|
||||||
|
* for storing per-device prints for a single user, namely
|
||||||
|
* fp_print_data_save(). It also detailed a load function,
|
||||||
|
* fp_print_data_load(), but usage of this function is limited to scenarios
|
||||||
|
* where you know which device you would like to use, and you know which
|
||||||
|
* finger you are looking to verify.
|
||||||
|
*
|
||||||
|
* In other cases, it would be more useful to be able to enumerate all
|
||||||
|
* previously saved prints, potentially even before device discovery. These
|
||||||
|
* functions are designed to offer this functionality to you.
|
||||||
|
*
|
||||||
|
* Discovered prints are stored in a <tt>dscv_print</tt> structure, and you
|
||||||
|
* can use functions documented below to access some information about these
|
||||||
|
* prints. You can determine if a discovered print appears to be compatible
|
||||||
|
* with a device using functions such as fp_dscv_dev_supports_dscv_print() and
|
||||||
|
* fp_dev_supports_dscv_print().
|
||||||
|
*
|
||||||
|
* When you are ready to use the print, you can load it into memory in the form
|
||||||
|
* of a stored print by using the fp_print_data_from_dscv_print() function.
|
||||||
|
*
|
||||||
|
* You may have noticed the use of the word "appears" in the above paragraphs.
|
||||||
|
* libfprint performs print discovery simply by examining the file and
|
||||||
|
* directory structure of libfprint's private data store. It does not examine
|
||||||
|
* the actual prints themselves. Just because a print has been discovered
|
||||||
|
* and appears to be compatible with a certain device does not necessarily mean
|
||||||
|
* that it is usable; when you come to load or use it, under unusual
|
||||||
|
* circumstances it may turn out that the print is corrupt or not for the
|
||||||
|
* device that it appeared to be. Also, it is possible that the print may have
|
||||||
|
* been deleted by the time you come to load it.
|
||||||
|
*/
|
||||||
|
|
||||||
static GSList *scan_dev_store_dir(char *devpath, uint16_t driver_id,
|
static GSList *scan_dev_store_dir(char *devpath, uint16_t driver_id,
|
||||||
uint32_t devtype, GSList *list)
|
uint32_t devtype, GSList *list)
|
||||||
{
|
{
|
||||||
|
@ -389,6 +517,12 @@ static GSList *scan_driver_store_dir(char *drvpath, uint16_t driver_id,
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** \ingroup dscv_print
|
||||||
|
* Scans the users home directory and returns a list of prints that were
|
||||||
|
* previously saved using fp_print_data_save().
|
||||||
|
* \returns a NULL-terminated list of discovered prints, must be freed with
|
||||||
|
* fp_dscv_prints_free() after use.
|
||||||
|
*/
|
||||||
API_EXPORTED struct fp_dscv_print **fp_discover_prints(void)
|
API_EXPORTED struct fp_dscv_print **fp_discover_prints(void)
|
||||||
{
|
{
|
||||||
GDir *dir;
|
GDir *dir;
|
||||||
|
@ -444,6 +578,12 @@ API_EXPORTED struct fp_dscv_print **fp_discover_prints(void)
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** \ingroup dscv_print
|
||||||
|
* Frees a list of discovered prints. This function also frees the discovered
|
||||||
|
* prints themselves, so make sure you do not use any discovered prints
|
||||||
|
* after calling this function.
|
||||||
|
* \param prints the list of discovered prints
|
||||||
|
*/
|
||||||
API_EXPORTED void fp_dscv_prints_free(struct fp_dscv_print **prints)
|
API_EXPORTED void fp_dscv_prints_free(struct fp_dscv_print **prints)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
@ -460,17 +600,37 @@ API_EXPORTED void fp_dscv_prints_free(struct fp_dscv_print **prints)
|
||||||
g_free(prints);
|
g_free(prints);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** \ingroup dscv_print
|
||||||
|
* Gets the \ref driver_id "driver ID" for a discovered print. The driver ID
|
||||||
|
* indicates which driver the print originally came from. The print is only
|
||||||
|
* usable with a device controlled by that driver.
|
||||||
|
* \param print the discovered print
|
||||||
|
* \returns the driver ID of the driver compatible with the print
|
||||||
|
*/
|
||||||
API_EXPORTED uint16_t fp_dscv_print_get_driver_id(struct fp_dscv_print *print)
|
API_EXPORTED uint16_t fp_dscv_print_get_driver_id(struct fp_dscv_print *print)
|
||||||
{
|
{
|
||||||
return print->driver_id;
|
return print->driver_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** \ingroup dscv_print
|
||||||
|
* Gets the \ref devtype "devtype" for a discovered print. The devtype
|
||||||
|
* represents which type of device under the parent driver is compatible
|
||||||
|
* with the print.
|
||||||
|
* \param print the discovered print
|
||||||
|
* \returns the devtype of the device range compatible with the print
|
||||||
|
*/
|
||||||
API_EXPORTED uint32_t fp_dscv_print_get_devtype(struct fp_dscv_print *print)
|
API_EXPORTED uint32_t fp_dscv_print_get_devtype(struct fp_dscv_print *print)
|
||||||
{
|
{
|
||||||
return print->devtype;
|
return print->devtype;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** \ingroup dscv_print
|
||||||
|
* Gets the finger code for a discovered print.
|
||||||
|
* \param print discovered print
|
||||||
|
* \returns a finger code from #fp_finger
|
||||||
|
*/
|
||||||
API_EXPORTED enum fp_finger fp_dscv_print_get_finger(struct fp_dscv_print *print)
|
API_EXPORTED enum fp_finger fp_dscv_print_get_finger(struct fp_dscv_print *print)
|
||||||
{
|
{
|
||||||
return print->finger;
|
return print->finger;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -31,17 +31,23 @@ struct fp_print_data;
|
||||||
struct fp_img;
|
struct fp_img;
|
||||||
|
|
||||||
/* misc/general stuff */
|
/* misc/general stuff */
|
||||||
|
|
||||||
|
/** \ingroup print_data
|
||||||
|
* Numeric codes used to refer to fingers (and thumbs) of a human. These are
|
||||||
|
* purposely not available as strings, to avoid getting the library tangled up
|
||||||
|
* in localization efforts.
|
||||||
|
*/
|
||||||
enum fp_finger {
|
enum fp_finger {
|
||||||
LEFT_THUMB = 1,
|
LEFT_THUMB = 1, /** thumb (left hand) */
|
||||||
LEFT_INDEX,
|
LEFT_INDEX, /** index finger (left hand) */
|
||||||
LEFT_MIDDLE,
|
LEFT_MIDDLE, /** middle finger (left hand) */
|
||||||
LEFT_RING,
|
LEFT_RING, /** ring finger (left hand) */
|
||||||
LEFT_LITTLE,
|
LEFT_LITTLE, /** little finger (left hand) */
|
||||||
RIGHT_THUMB,
|
RIGHT_THUMB, /** thumb (right hand) */
|
||||||
RIGHT_INDEX,
|
RIGHT_INDEX, /** index finger (right hand) */
|
||||||
RIGHT_MIDDLE,
|
RIGHT_MIDDLE, /** middle finger (right hand) */
|
||||||
RIGHT_RING,
|
RIGHT_RING, /** ring finger (right hand) */
|
||||||
RIGHT_LITTLE,
|
RIGHT_LITTLE, /** little finger (right hand) */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Drivers */
|
/* Drivers */
|
||||||
|
@ -90,26 +96,65 @@ int fp_dev_img_capture(struct fp_dev *dev, int unconditional,
|
||||||
int fp_dev_get_img_width(struct fp_dev *dev);
|
int fp_dev_get_img_width(struct fp_dev *dev);
|
||||||
int fp_dev_get_img_height(struct fp_dev *dev);
|
int fp_dev_get_img_height(struct fp_dev *dev);
|
||||||
|
|
||||||
/* Enrollment */
|
/** \ingroup dev
|
||||||
|
* Enrollment result codes returned from fp_enroll_finger().
|
||||||
|
* Result codes with RETRY in the name suggest that the scan failed due to
|
||||||
|
* user error. Applications will generally want to inform the user of the
|
||||||
|
* problem and then retry the enrollment stage. For more info on the semantics
|
||||||
|
* of interpreting these result codes and tracking enrollment process, see
|
||||||
|
* \ref enrolling.
|
||||||
|
*/
|
||||||
enum fp_enroll_result {
|
enum fp_enroll_result {
|
||||||
|
/** Enrollment completed successfully, the enrollment data has been
|
||||||
|
* returned to the caller. */
|
||||||
FP_ENROLL_COMPLETE = 1,
|
FP_ENROLL_COMPLETE = 1,
|
||||||
|
/** Enrollment failed due to incomprehensible data; this may occur when
|
||||||
|
* the user scans a different finger on each enroll stage. */
|
||||||
FP_ENROLL_FAIL,
|
FP_ENROLL_FAIL,
|
||||||
|
/** Enroll stage passed; more stages are need to complete the process. */
|
||||||
FP_ENROLL_PASS,
|
FP_ENROLL_PASS,
|
||||||
|
/** The enrollment scan did not succeed due to poor scan quality or
|
||||||
|
* other general user scanning problem. */
|
||||||
FP_ENROLL_RETRY = 100,
|
FP_ENROLL_RETRY = 100,
|
||||||
|
/** The enrollment scan did not succeed because the finger swipe was
|
||||||
|
* too short. */
|
||||||
FP_ENROLL_RETRY_TOO_SHORT,
|
FP_ENROLL_RETRY_TOO_SHORT,
|
||||||
|
/** The enrollment scan did not succeed because the finger was not
|
||||||
|
* centered on the scanner. */
|
||||||
FP_ENROLL_RETRY_CENTER_FINGER,
|
FP_ENROLL_RETRY_CENTER_FINGER,
|
||||||
|
/** The verification scan did not succeed due to quality or pressure
|
||||||
|
* problems; the user should remove their finger from the scanner before
|
||||||
|
* retrying. */
|
||||||
FP_ENROLL_RETRY_REMOVE_FINGER,
|
FP_ENROLL_RETRY_REMOVE_FINGER,
|
||||||
};
|
};
|
||||||
|
|
||||||
int fp_enroll_finger(struct fp_dev *dev, struct fp_print_data **print_data);
|
int fp_enroll_finger(struct fp_dev *dev, struct fp_print_data **print_data);
|
||||||
|
|
||||||
/* Verification */
|
/** \ingroup dev
|
||||||
|
* Verification result codes returned from fp_verify_finger().
|
||||||
|
* Result codes with RETRY in the name suggest that the scan failed due to
|
||||||
|
* user error. Applications will generally want to inform the user of the
|
||||||
|
* problem and then retry the verify operation.
|
||||||
|
*/
|
||||||
enum fp_verify_result {
|
enum fp_verify_result {
|
||||||
|
/** The verification scan completed successfully, but the newly scanned
|
||||||
|
* fingerprint does not match the fingerprint being verified against. */
|
||||||
FP_VERIFY_NO_MATCH = 0,
|
FP_VERIFY_NO_MATCH = 0,
|
||||||
|
/** The verification scan completed successfully and the newly scanned
|
||||||
|
* fingerprint does match the fingerprint being verified. */
|
||||||
FP_VERIFY_MATCH = 1,
|
FP_VERIFY_MATCH = 1,
|
||||||
|
/** The verification scan did not succeed due to poor scan quality or
|
||||||
|
* other general user scanning problem. */
|
||||||
FP_VERIFY_RETRY = FP_ENROLL_RETRY,
|
FP_VERIFY_RETRY = FP_ENROLL_RETRY,
|
||||||
|
/** The verification scan did not succeed because the finger swipe was
|
||||||
|
* too short. */
|
||||||
FP_VERIFY_RETRY_TOO_SHORT = FP_ENROLL_RETRY_TOO_SHORT,
|
FP_VERIFY_RETRY_TOO_SHORT = FP_ENROLL_RETRY_TOO_SHORT,
|
||||||
|
/** The verification scan did not succeed because the finger was not
|
||||||
|
* centered on the scanner. */
|
||||||
FP_VERIFY_RETRY_CENTER_FINGER = FP_ENROLL_RETRY_CENTER_FINGER,
|
FP_VERIFY_RETRY_CENTER_FINGER = FP_ENROLL_RETRY_CENTER_FINGER,
|
||||||
|
/** The verification scan did not succeed due to quality or pressure
|
||||||
|
* problems; the user should remove their finger from the scanner before
|
||||||
|
* retrying. */
|
||||||
FP_VERIFY_RETRY_REMOVE_FINGER = FP_ENROLL_RETRY_REMOVE_FINGER,
|
FP_VERIFY_RETRY_REMOVE_FINGER = FP_ENROLL_RETRY_REMOVE_FINGER,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,23 @@
|
||||||
#include "nbis/include/bozorth.h"
|
#include "nbis/include/bozorth.h"
|
||||||
#include "nbis/include/lfs.h"
|
#include "nbis/include/lfs.h"
|
||||||
|
|
||||||
|
/** @defgroup img Image operations
|
||||||
|
* libfprint offers several ways of retrieving images from imaging devices,
|
||||||
|
* one example being the fp_dev_img_capture() function. The functions
|
||||||
|
* documented below allow you to work with such images.
|
||||||
|
*
|
||||||
|
* \section img_fmt Image format
|
||||||
|
* All images are represented as 8-bit greyscale data.
|
||||||
|
*
|
||||||
|
* \section img_std Image standardization
|
||||||
|
* In some contexts, images you are provided through libfprint are raw images
|
||||||
|
* from the hardware. The orientation of these varies from device-to-device,
|
||||||
|
* as does the color scheme (black-on-white or white-on-black?). libfprint
|
||||||
|
* provides the fp_img_standardize function to convert images into standard
|
||||||
|
* form, which is defined to be: finger flesh as black on white surroundings,
|
||||||
|
* natural upright orientation.
|
||||||
|
*/
|
||||||
|
|
||||||
struct fp_img *fpi_img_new(size_t length)
|
struct fp_img *fpi_img_new(size_t length)
|
||||||
{
|
{
|
||||||
struct fp_img *img = g_malloc(sizeof(*img) + length);
|
struct fp_img *img = g_malloc(sizeof(*img) + length);
|
||||||
|
@ -66,26 +83,53 @@ struct fp_img *fpi_img_resize(struct fp_img *img, size_t newsize)
|
||||||
return g_realloc(img, sizeof(*img) + newsize);
|
return g_realloc(img, sizeof(*img) + newsize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** \ingroup img
|
||||||
|
* Frees an image. Must be called when you are finished working with an image.
|
||||||
|
* \param img the image to destroy
|
||||||
|
*/
|
||||||
API_EXPORTED void fp_img_free(struct fp_img *img)
|
API_EXPORTED void fp_img_free(struct fp_img *img)
|
||||||
{
|
{
|
||||||
g_free(img);
|
g_free(img);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** \ingroup img
|
||||||
|
* Gets the pixel height of an image.
|
||||||
|
* \param img an image
|
||||||
|
* \returns the height of the image
|
||||||
|
*/
|
||||||
API_EXPORTED int fp_img_get_height(struct fp_img *img)
|
API_EXPORTED int fp_img_get_height(struct fp_img *img)
|
||||||
{
|
{
|
||||||
return img->height;
|
return img->height;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** \ingroup img
|
||||||
|
* Gets the pixel width of an image.
|
||||||
|
* \param img an image
|
||||||
|
* \returns the width of the image
|
||||||
|
*/
|
||||||
API_EXPORTED int fp_img_get_width(struct fp_img *img)
|
API_EXPORTED int fp_img_get_width(struct fp_img *img)
|
||||||
{
|
{
|
||||||
return img->width;
|
return img->width;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** \ingroup img
|
||||||
|
* Gets the greyscale data for an image. This data must not be modified or
|
||||||
|
* freed, and must not be used after fp_img_free() has been called.
|
||||||
|
* \param img an image
|
||||||
|
* \returns a pointer to libfprint's internal data for the image
|
||||||
|
*/
|
||||||
API_EXPORTED unsigned char *fp_img_get_data(struct fp_img *img)
|
API_EXPORTED unsigned char *fp_img_get_data(struct fp_img *img)
|
||||||
{
|
{
|
||||||
return img->data;
|
return img->data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** \ingroup img
|
||||||
|
* A quick convenience function to save an image to a file in
|
||||||
|
* <a href="http://netpbm.sourceforge.net/doc/pgm.html">PGM format</a>.
|
||||||
|
* \param img the image to save
|
||||||
|
* \param path the path to save the image. Existing files will be overwritten.
|
||||||
|
* \returns 0 on success, non-zero on error.
|
||||||
|
*/
|
||||||
API_EXPORTED int fp_img_save_to_file(struct fp_img *img, char *path)
|
API_EXPORTED int fp_img_save_to_file(struct fp_img *img, char *path)
|
||||||
{
|
{
|
||||||
FILE *fd = fopen(path, "w");
|
FILE *fd = fopen(path, "w");
|
||||||
|
@ -159,6 +203,13 @@ static void invert_colors(struct fp_img *img)
|
||||||
img->data[i] = 0xff - img->data[i];
|
img->data[i] = 0xff - img->data[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** \ingroup img
|
||||||
|
* \ref img_std "Standardizes" an image by normalizing its orientation, colors,
|
||||||
|
* etc. It is safe to call this multiple times on an image, libfprint keeps
|
||||||
|
* track of the work it needs to do to make an image standard and will not
|
||||||
|
* perform these operations more than once for a given image.
|
||||||
|
* \param img the image to standardize
|
||||||
|
*/
|
||||||
API_EXPORTED void fp_img_standardize(struct fp_img *img)
|
API_EXPORTED void fp_img_standardize(struct fp_img *img)
|
||||||
{
|
{
|
||||||
if (img->flags & FP_IMG_V_FLIPPED) {
|
if (img->flags & FP_IMG_V_FLIPPED) {
|
||||||
|
|
Loading…
Reference in a new issue