core.c 35.6 KB
 Daniel Drake committed Oct 08, 2007 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 /* * Core functions for libfprint * Copyright (C) 2007 Daniel Drake * * 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  Daniel Drake committed Oct 14, 2007 21 22 #include #include  Daniel Drake committed Oct 08, 2007 23   Daniel Drake committed Oct 08, 2007 24 #include  Daniel Drake committed Oct 08, 2007 25 #include  Daniel Drake committed Oct 08, 2007 26 27 28  #include "fp_internal.h"  Daniel Drake committed Nov 04, 2007 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 /** * \mainpage libfprint API Reference * libfprint is an open source library to provide access to fingerprint * scanning devices. For more info, see the * libfprint project * homepage. * * 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 * mailing list. * * \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 collection 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 no other knowledge 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 * are 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 device type 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 and 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. *  Daniel Drake committed Nov 15, 2007 146  * \section sync Synchronity/asynchronity  Daniel Drake committed Nov 04, 2007 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278  * * 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 * devtype 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 * * documented on the wiki 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. */  Daniel Drake committed Nov 15, 2007 279 280 static GSList *registered_drivers = NULL; static GSList *opened_devices = NULL;  Daniel Drake committed Oct 08, 2007 281   Daniel Drake committed Oct 12, 2007 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 void fpi_log(enum fpi_log_level level, const char *component, const char *function, const char *format, ...) { va_list args; FILE *stream = stdout; const char *prefix; switch (level) { case LOG_LEVEL_INFO: prefix = "info"; break; case LOG_LEVEL_WARNING: stream = stderr; prefix = "warning"; break; case LOG_LEVEL_ERROR: stream = stderr; prefix = "error"; break; case LOG_LEVEL_DEBUG: stream = stderr; prefix = "debug"; break;  Daniel Drake committed Oct 13, 2007 305 306 307 308  default: stream = stderr; prefix = "unknown"; break;  Daniel Drake committed Oct 12, 2007 309 310 311 312 313 314 315 316 317 318 319 320  } fprintf(stream, "%s:%s [%s] ", component ? component : "fp", prefix, function); va_start (args, format); vfprintf(stream, format, args); va_end (args); fprintf(stream, "\n"); }  Daniel Drake committed Oct 23, 2007 321 static void register_driver(struct fp_driver *drv)  Daniel Drake committed Oct 08, 2007 322 {  Daniel Drake committed Oct 28, 2007 323 324 325 326  if (drv->id == 0) { fp_err("not registering driver %s: driver ID is 0"); return; }  Daniel Drake committed Nov 15, 2007 327  registered_drivers = g_slist_prepend(registered_drivers, (gpointer) drv);  Daniel Drake committed Oct 12, 2007 328  fp_dbg("registered driver %s", drv->name);  Daniel Drake committed Oct 08, 2007 329 330 }  Daniel Drake committed Oct 23, 2007 331 static struct fp_driver * const primitive_drivers[] = {  Daniel Drake committed Oct 08, 2007 332 333 334  &upekts_driver, };  Daniel Drake committed Oct 23, 2007 335 336 static struct fp_img_driver * const img_drivers[] = { &uru4000_driver,  Daniel Drake committed Nov 15, 2007 337  &aes2501_driver,  Daniel Drake committed Oct 27, 2007 338  &aes4000_driver,  Daniel Drake committed Oct 23, 2007 339 340 };  Daniel Drake committed Oct 08, 2007 341 342 static void register_drivers(void) {  Daniel Drake committed Oct 13, 2007 343  unsigned int i;  Daniel Drake committed Oct 08, 2007 344   Daniel Drake committed Oct 23, 2007 345 346 347 348 349 350 351 352  for (i = 0; i < ARRAY_SIZE(primitive_drivers); i++) register_driver(primitive_drivers[i]); for (i = 0; i < ARRAY_SIZE(img_drivers); i++) { struct fp_img_driver *imgdriver = img_drivers[i]; fpi_img_driver_setup(imgdriver); register_driver(&imgdriver->driver); }  Daniel Drake committed Oct 08, 2007 353 354 }  Daniel Drake committed Oct 25, 2007 355 static struct fp_driver *find_supporting_driver(struct usb_device *udev,  Daniel Drake committed Oct 31, 2007 356  const struct usb_id **usb_id)  Daniel Drake committed Oct 08, 2007 357 {  Daniel Drake committed Nov 15, 2007 358  GSList *elem = registered_drivers;  Daniel Drake committed Oct 08, 2007 359 360  do {  Daniel Drake committed Oct 23, 2007 361  struct fp_driver *drv = elem->data;  Daniel Drake committed Oct 08, 2007 362 363 364 365  const struct usb_id *id; for (id = drv->id_table; id->vendor; id++) if (udev->descriptor.idVendor == id->vendor &&  Daniel Drake committed Oct 12, 2007 366 367 368  udev->descriptor.idProduct == id->product) { fp_dbg("driver %s supports USB device %04x:%04x", drv->name, id->vendor, id->product);  Daniel Drake committed Oct 31, 2007 369  *usb_id = id;  Daniel Drake committed Oct 08, 2007 370  return drv;  Daniel Drake committed Oct 12, 2007 371  }  Daniel Drake committed Nov 15, 2007 372  } while (elem = g_slist_next(elem));  Daniel Drake committed Oct 08, 2007 373 374 375  return NULL; }  Daniel Drake committed Oct 30, 2007 376 377 static struct fp_dscv_dev *discover_dev(struct usb_device *udev) {  Daniel Drake committed Oct 31, 2007 378  const struct usb_id *usb_id;  Daniel Drake committed Oct 30, 2007 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401  struct fp_driver *drv = find_supporting_driver(udev, &usb_id); struct fp_dscv_dev *ddev; uint32_t devtype = 0; if (!drv) return NULL; if (drv->discover) { int r = drv->discover(usb_id, &devtype); if (r < 0) fp_err("%s discover failed, code %d", drv->name, r); if (r <= 0) 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; }  Daniel Drake committed Nov 04, 2007 402 403 404 405 406 407 /** \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. */  Daniel Drake committed Oct 08, 2007 408 409 API_EXPORTED struct fp_dscv_dev **fp_discover_devs(void) {  Daniel Drake committed Nov 15, 2007 410  GSList *tmplist = NULL;  Daniel Drake committed Oct 08, 2007 411 412 413 414 415 416 417 418 419 420 421 422  struct fp_dscv_dev **list; struct usb_device *udev; struct usb_bus *bus; int dscv_count = 0; if (registered_drivers == NULL) return NULL; usb_find_busses(); usb_find_devices(); /* Check each device against each driver, temporarily storing successfully  Daniel Drake committed Nov 15, 2007 423  * discovered devices in a GSList.  Daniel Drake committed Oct 08, 2007 424 425 426 427 428  * * Quite inefficient but excusable as we'll only be dealing with small * sets of drivers against small sets of USB devices */ for (bus = usb_get_busses(); bus; bus = bus->next) for (udev = bus->devices; udev; udev = udev->next) {  Daniel Drake committed Oct 30, 2007 429 430  struct fp_dscv_dev *ddev = discover_dev(udev); if (!ddev)  Daniel Drake committed Oct 08, 2007 431  continue;  Daniel Drake committed Nov 15, 2007 432  tmplist = g_slist_prepend(tmplist, (gpointer) ddev);  Daniel Drake committed Oct 08, 2007 433 434 435  dscv_count++; }  Daniel Drake committed Nov 15, 2007 436  /* Convert our temporary GSList into a standard NULL-terminated pointer  Daniel Drake committed Oct 08, 2007 437 438 439  * array. */ list = g_malloc(sizeof(*list) * (dscv_count + 1)); if (dscv_count > 0) {  Daniel Drake committed Nov 15, 2007 440  GSList *elem = tmplist;  Daniel Drake committed Oct 08, 2007 441 442 443  int i = 0; do { list[i++] = elem->data;  Daniel Drake committed Nov 15, 2007 444  } while (elem = g_slist_next(elem));  Daniel Drake committed Oct 08, 2007 445 446 447  } list[dscv_count] = NULL; /* NULL-terminate */  Daniel Drake committed Nov 15, 2007 448  g_slist_free(tmplist);  Daniel Drake committed Oct 08, 2007 449 450 451  return list; }  Daniel Drake committed Nov 04, 2007 452 453 454 455 /** \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 before freeing the list.  Daniel Drake committed Nov 15, 2007 456 457  * \param devs the list of discovered devices. If NULL, function simply * returns.  Daniel Drake committed Nov 04, 2007 458  */  Daniel Drake committed Oct 08, 2007 459 460 461 462 463 464 465 466 467 468 469 API_EXPORTED void fp_dscv_devs_free(struct fp_dscv_dev **devs) { int i; if (!devs) return; for (i = 0; devs[i]; i++) g_free(devs[i]); g_free(devs); }  Daniel Drake committed Nov 04, 2007 470 471 472 473 474 /** \ingroup dscv_dev * Gets the \ref drv "driver" for a discovered device. * \param dev the discovered device * \returns the driver backing the device */  Daniel Drake committed Oct 23, 2007 475 API_EXPORTED struct fp_driver *fp_dscv_dev_get_driver(struct fp_dscv_dev *dev)  Daniel Drake committed Oct 08, 2007 476 477 478 479 { return dev->drv; }  Daniel Drake committed Nov 04, 2007 480 481 482 483 484 /** \ingroup dscv_dev * Gets the \ref devtype "devtype" for a discovered device. * \param dev the discovered device * \returns the devtype of the device */  Daniel Drake committed Oct 30, 2007 485 486 487 488 489 API_EXPORTED uint32_t fp_dscv_dev_get_devtype(struct fp_dscv_dev *dev) { return dev->devtype; }  Daniel Drake committed Oct 31, 2007 490 491 492 493 494 495 496 497 498 499 500 501 502 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; } }  Daniel Drake committed Nov 04, 2007 503 504 505 506 507 508 509 /** \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 */  Daniel Drake committed Oct 31, 2007 510 511 512 513 514 515 516 517 API_EXPORTED int fp_dscv_dev_supports_print_data(struct fp_dscv_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); }  Daniel Drake committed Nov 04, 2007 518 519 520 521 522 523 524 /** \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 */  Daniel Drake committed Oct 31, 2007 525 526 527 528 529 530 531 API_EXPORTED int fp_dscv_dev_supports_dscv_print(struct fp_dscv_dev *dev, struct fp_dscv_print *data) { return fpi_print_data_compatible(dev->drv->id, dev->devtype, 0, data->driver_id, data->devtype, 0); }  Daniel Drake committed Nov 04, 2007 532 533 534 535 536 537 538 539 /** \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 */  Daniel Drake committed Oct 31, 2007 540 541 542 543 544 545 546 547 548 549 550 551 API_EXPORTED struct fp_dscv_dev *fp_dscv_dev_for_print_data(struct fp_dscv_dev **devs, struct fp_print_data *data) { struct fp_dscv_dev *ddev; int i; for (i = 0; ddev = devs[i]; i++) if (fp_dscv_dev_supports_print_data(ddev, data)) return ddev; return NULL; }  Daniel Drake committed Nov 04, 2007 552 553 554 555 556 557 558 559 /** \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 */  Daniel Drake committed Oct 31, 2007 560 561 562 563 564 565 566 567 568 569 570 571 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; for (i = 0; ddev = devs[i]; i++) if (fp_dscv_dev_supports_dscv_print(ddev, print)) return ddev; return NULL; }  Daniel Drake committed Nov 04, 2007 572 573 574 575 576 577 578 /** \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 */  Daniel Drake committed Oct 08, 2007 579 580 581 API_EXPORTED struct fp_dev *fp_dev_open(struct fp_dscv_dev *ddev) { struct fp_dev *dev;  Daniel Drake committed Oct 23, 2007 582  struct fp_driver *drv = ddev->drv;  Daniel Drake committed Oct 08, 2007 583 584 585  int r; usb_dev_handle *udevh = usb_open(ddev->udev);  Daniel Drake committed Oct 12, 2007 586 587  if (!udevh) { fp_err("usb_open failed");  Daniel Drake committed Oct 08, 2007 588  return NULL;  Daniel Drake committed Oct 12, 2007 589  }  Daniel Drake committed Oct 27, 2007 590   Daniel Drake committed Oct 08, 2007 591 592 593  dev = g_malloc0(sizeof(*dev)); dev->drv = drv; dev->udev = udevh;  Daniel Drake committed Oct 13, 2007 594  dev->__enroll_stage = -1;  Daniel Drake committed Oct 08, 2007 595 596  if (drv->init) {  Daniel Drake committed Oct 25, 2007 597  r = drv->init(dev, ddev->driver_data);  Daniel Drake committed Oct 08, 2007 598  if (r) {  Daniel Drake committed Oct 12, 2007 599  fp_err("device initialisation failed, driver=%s", drv->name);  Daniel Drake committed Oct 08, 2007 600 601 602 603 604 605  usb_close(udevh); g_free(dev); return NULL; } }  Daniel Drake committed Oct 12, 2007 606  fp_dbg("");  Daniel Drake committed Nov 15, 2007 607  opened_devices = g_slist_prepend(opened_devices, (gpointer) dev);  Daniel Drake committed Oct 08, 2007 608 609 610  return dev; }  Daniel Drake committed Nov 15, 2007 611 612 613 614 615 616 617 618 619 /* performs close operation without modifying opened_devices list */ static void do_close(struct fp_dev *dev) { if (dev->drv->exit) dev->drv->exit(dev); usb_close(dev->udev); g_free(dev); }  Daniel Drake committed Nov 04, 2007 620 621 622 /** \ingroup dev * Close a device. You must call this function when you are finished using * a fingerprint device.  Daniel Drake committed Nov 15, 2007 623  * \param dev the device to close. If NULL, function simply returns.  Daniel Drake committed Nov 04, 2007 624  */  Daniel Drake committed Oct 08, 2007 625 626 API_EXPORTED void fp_dev_close(struct fp_dev *dev) {  Daniel Drake committed Nov 15, 2007 627 628 629  if (!dev) return;  Daniel Drake committed Oct 12, 2007 630  fp_dbg("");  Daniel Drake committed Nov 15, 2007 631 632 633 634 635  if (g_slist_index(opened_devices, (gconstpointer) dev) == -1) fp_err("device %p not in opened list!", dev); opened_devices = g_slist_remove(opened_devices, (gconstpointer) dev); do_close(dev);  Daniel Drake committed Oct 08, 2007 636 637 }  Daniel Drake committed Nov 04, 2007 638 639 640 641 642 /** \ingroup dev * Get the \ref drv "driver" for a fingerprint device. * \param dev the device * \returns the driver controlling the device */  Daniel Drake committed Oct 23, 2007 643 API_EXPORTED struct fp_driver *fp_dev_get_driver(struct fp_dev *dev)  Daniel Drake committed Oct 08, 2007 644 645 646 647 { return dev->drv; }  Daniel Drake committed Nov 04, 2007 648 649 650 651 652 653 /** \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 */  Daniel Drake committed Oct 08, 2007 654 655 656 657 658 API_EXPORTED int fp_dev_get_nr_enroll_stages(struct fp_dev *dev) { return dev->nr_enroll_stages; }  Daniel Drake committed Nov 04, 2007 659 660 661 662 663 /** \ingroup dev * Gets the \ref devtype "devtype" for a device. * \param dev the device * \returns the devtype */  Daniel Drake committed Oct 30, 2007 664 665 666 667 668 API_EXPORTED uint32_t fp_dev_get_devtype(struct fp_dev *dev) { return dev->devtype; }  Daniel Drake committed Nov 04, 2007 669 670 671 672 673 674 /** \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 */  Daniel Drake committed Oct 31, 2007 675 676 677 678 679 680 681 682 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); }  Daniel Drake committed Nov 04, 2007 683 684 685 686 687 688 689 /** \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 */  Daniel Drake committed Oct 31, 2007 690 691 692 693 694 695 696 API_EXPORTED int fp_dev_supports_dscv_print(struct fp_dev *dev, struct fp_dscv_print *data) { return fpi_print_data_compatible(dev->drv->id, dev->devtype, 0, data->driver_id, data->devtype, 0); }  Daniel Drake committed Nov 04, 2007 697 698 699 700 701 /** \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. */  Daniel Drake committed Oct 23, 2007 702 API_EXPORTED const char *fp_driver_get_name(struct fp_driver *drv)  Daniel Drake committed Oct 08, 2007 703 704 705 706 { return drv->name; }  Daniel Drake committed Nov 04, 2007 707 708 709 710 711 /** \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. */  Daniel Drake committed Oct 23, 2007 712 API_EXPORTED const char *fp_driver_get_full_name(struct fp_driver *drv)  Daniel Drake committed Oct 08, 2007 713 714 715 716 { return drv->full_name; }  Daniel Drake committed Nov 04, 2007 717 718 719 720 721 /** \ingroup drv * Retrieves the driver ID code for a driver. * \param drv the driver * \returns the driver ID */  Daniel Drake committed Oct 30, 2007 722 723 724 725 726 API_EXPORTED uint16_t fp_driver_get_driver_id(struct fp_driver *drv) { return drv->id; }  Daniel Drake committed Nov 02, 2007 727 static struct fp_img_dev *dev_to_img_dev(struct fp_dev *dev)  Daniel Drake committed Oct 27, 2007 728 729 730 731 732 733 { if (dev->drv->type != DRIVER_IMAGING) return NULL; return dev->priv; }  Daniel Drake committed Nov 04, 2007 734 735 736 737 738 739 740 741 742 743 /** \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 */  Daniel Drake committed Nov 02, 2007 744 745 746 747 748 API_EXPORTED int fp_dev_supports_imaging(struct fp_dev *dev) { return dev->drv->type == DRIVER_IMAGING; }  Daniel Drake committed Nov 04, 2007 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 /** \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 unconditional 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() */  Daniel Drake committed Nov 02, 2007 767 768 769 770 771 772 773 774 775 776 777 778 API_EXPORTED int fp_dev_img_capture(struct fp_dev *dev, int unconditional, struct fp_img **image) { struct fp_img_dev *imgdev = dev_to_img_dev(dev); if (!imgdev) { fp_dbg("image capture on non-imaging device"); return -ENOTSUP; } return fpi_imgdev_capture(imgdev, unconditional, image); }  Daniel Drake committed Nov 04, 2007 779 780 781 782 783 784 785 786 787 /** \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. */  Daniel Drake committed Nov 02, 2007 788 789 790 791 792 793 794 795 796 797 798 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); }  Daniel Drake committed Nov 04, 2007 799 800 801 802 803 804 805 806 807 /** \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. */  Daniel Drake committed Nov 02, 2007 808 809 810 811 812 813 814 815 816 817 818 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); }  Daniel Drake committed Nov 04, 2007 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 /** \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 not 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.  Daniel Drake committed Nov 15, 2007 858 859 860 861 862  * * If the device is an imaging device, it can also return the image from * the scan, even when the enroll fails with a RETRY or FAIL code. It is legal * to call this function even on non-imaging devices, just don't expect them to * provide images.  Daniel Drake committed Nov 04, 2007 863 864 865 866  * * \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.  Daniel Drake committed Nov 15, 2007 867 868 869 870  * \param img location to store the scan image. accepts NULL for no image * storage. If an image is returned, it must be freed with fp_img_free() after * use. * \return negative code on error, otherwise a code from #fp_enroll_result  Daniel Drake committed Nov 04, 2007 871  */  Daniel Drake committed Nov 15, 2007 872 873 API_EXPORTED int fp_enroll_finger_img(struct fp_dev *dev, struct fp_print_data **print_data, struct fp_img **img)  Daniel Drake committed Oct 08, 2007 874 {  Daniel Drake committed Oct 23, 2007 875  struct fp_driver *drv = dev->drv;  Daniel Drake committed Nov 15, 2007 876  struct fp_img *_img = NULL;  Daniel Drake committed Oct 14, 2007 877  int ret;  Daniel Drake committed Oct 13, 2007 878 879 880  int stage = dev->__enroll_stage; gboolean initial = FALSE;  Daniel Drake committed Oct 12, 2007 881 882  if (!dev->nr_enroll_stages || !drv->enroll) { fp_err("driver %s has 0 enroll stages or no enroll func",  Daniel Drake committed Oct 14, 2007 883 884  drv->name); return -ENOTSUP;  Daniel Drake committed Oct 12, 2007 885  }  Daniel Drake committed Oct 08, 2007 886   Daniel Drake committed Oct 13, 2007 887 888 889 890 891 892 893  if (stage == -1) { initial = TRUE; dev->__enroll_stage = ++stage; } if (stage >= dev->nr_enroll_stages) { fp_err("exceeding number of enroll stages for device claimed by "  Daniel Drake committed Oct 14, 2007 894 895 896  "driver %s (%d stages)", drv->name, dev->nr_enroll_stages); dev->__enroll_stage = -1; return -EINVAL;  Daniel Drake committed Oct 13, 2007 897 898 899 900  } fp_dbg("%s will handle enroll stage %d/%d%s", drv->name, stage, dev->nr_enroll_stages - 1, initial ? " (initial)" : "");  Daniel Drake committed Nov 15, 2007 901  ret = drv->enroll(dev, initial, stage, print_data, &_img);  Daniel Drake committed Oct 14, 2007 902 903 904 905 906  if (ret < 0) { fp_err("enroll failed with code %d", ret); dev->__enroll_stage = -1; return ret; }  Daniel Drake committed Nov 15, 2007 907 908 909 910 911 912  if (img) *img = _img; else fp_img_free(_img);  Daniel Drake committed Oct 13, 2007 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930  switch (ret) { case FP_ENROLL_PASS: fp_dbg("enroll stage passed"); dev->__enroll_stage = stage + 1; break; case FP_ENROLL_COMPLETE: fp_dbg("enroll complete"); dev->__enroll_stage = -1; break; case FP_ENROLL_RETRY: fp_dbg("enroll should retry"); break; case FP_ENROLL_RETRY_TOO_SHORT: fp_dbg("swipe was too short, enroll should retry"); break; case FP_ENROLL_RETRY_CENTER_FINGER: fp_dbg("finger was not centered, enroll should retry"); break;  Daniel Drake committed Oct 14, 2007 931 932 933  case FP_ENROLL_RETRY_REMOVE_FINGER: fp_dbg("scan failed, remove finger and retry"); break;  Daniel Drake committed Oct 13, 2007 934 935 936 937 938 939 940  case FP_ENROLL_FAIL: fp_err("enroll failed"); dev->__enroll_stage = -1; break; default: fp_err("unrecognised return code %d", ret); dev->__enroll_stage = -1;  Daniel Drake committed Oct 14, 2007 941  return -EINVAL;  Daniel Drake committed Oct 13, 2007 942 943  } return ret;  Daniel Drake committed Oct 08, 2007 944 945 }  Daniel Drake committed Nov 04, 2007 946 947 /** \ingroup dev * Performs a new scan and verify it against a previously enrolled print.  Daniel Drake committed Nov 15, 2007 948 949 950 951 952  * If the device is an imaging device, it can also return the image from * the scan, even when the verify fails with a RETRY code. It is legal to * call this function even on non-imaging devices, just don't expect them to * provide images. *  Daniel Drake committed Nov 04, 2007 953 954 955  * \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.  Daniel Drake committed Nov 15, 2007 956 957 958  * \param img location to store the scan image. accepts NULL for no image * storage. If an image is returned, it must be freed with fp_img_free() after * use.  Daniel Drake committed Nov 04, 2007 959 960  * \return negative code on error, otherwise a code from #fp_verify_result */  Daniel Drake committed Nov 15, 2007 961 962 API_EXPORTED int fp_verify_finger_img(struct fp_dev *dev, struct fp_print_data *enrolled_print, struct fp_img **img)  Daniel Drake committed Oct 15, 2007 963 {  Daniel Drake committed Oct 23, 2007 964  struct fp_driver *drv = dev->drv;  Daniel Drake committed Nov 15, 2007 965  struct fp_img *_img = NULL;  Daniel Drake committed Oct 15, 2007 966 967 968 969 970 971 972 973 974 975 976 977  int r; if (!enrolled_print) { fp_err("no print given"); return -EINVAL; } if (!drv->verify) { fp_err("driver %s has no verify func", drv->name); return -EINVAL; }  Daniel Drake committed Oct 31, 2007 978  if (!fp_dev_supports_print_data(dev, enrolled_print)) {  Daniel Drake committed Oct 15, 2007 979 980 981 982 983  fp_err("print is not compatible with device"); return -EINVAL; } fp_dbg("to be handled by %s", drv->name);  Daniel Drake committed Nov 15, 2007 984  r = drv->verify(dev, enrolled_print, &_img);  Daniel Drake committed Oct 16, 2007 985  if (r < 0) {  Daniel Drake committed Oct 15, 2007 986  fp_dbg("verify error %d", r);  Daniel Drake committed Oct 16, 2007 987 988 989  return r; }  Daniel Drake committed Nov 15, 2007 990 991 992 993 994  if (img) *img = _img; else fp_img_free(_img);  Daniel Drake committed Oct 16, 2007 995 996  switch (r) { case FP_VERIFY_NO_MATCH:  Daniel Drake committed Oct 15, 2007 997  fp_dbg("result: no match");  Daniel Drake committed Oct 16, 2007 998 999  break; case FP_VERIFY_MATCH:  Daniel Drake committed Oct 15, 2007 1000  fp_dbg("result: match");  Daniel Drake committed Oct 16, 2007 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017  break; case FP_VERIFY_RETRY: fp_dbg("verify should retry"); break; case FP_VERIFY_RETRY_TOO_SHORT: fp_dbg("swipe was too short, verify should retry"); break; case FP_VERIFY_RETRY_CENTER_FINGER: fp_dbg("finger was not centered, verify should retry"); break; case FP_VERIFY_RETRY_REMOVE_FINGER: fp_dbg("scan failed, remove finger and retry"); break; default: fp_err("unrecognised return code %d", r); return -EINVAL; }  Daniel Drake committed Oct 15, 2007 1018 1019 1020 1021  return r; }  Daniel Drake committed Nov 04, 2007 1022 1023 1024 1025 1026 /** \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. */  Daniel Drake committed Oct 08, 2007 1027 1028 API_EXPORTED int fp_init(void) {  Daniel Drake committed Oct 12, 2007 1029  fp_dbg("");  Daniel Drake committed Oct 08, 2007 1030  usb_init();  Daniel Drake committed Oct 08, 2007 1031  register_drivers();  Daniel Drake committed Oct 08, 2007 1032 1033  return 0; }  Daniel Drake committed Oct 08, 2007 1034   Daniel Drake committed Nov 15, 2007 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 /** \ingroup core * 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) { GSList *elem = opened_devices; fp_dbg(""); if (elem != NULL) { do { fp_dbg("naughty app left a device open on exit!"); do_close((struct fp_dev *) elem->data); } while (elem = g_slist_next(elem)); g_slist_free(opened_devices); opened_devices = NULL; } fpi_data_exit(); g_slist_free(registered_drivers); registered_drivers = NULL; }