Compare commits

...

18 Commits

Author SHA1 Message Date
Bastien Nocera
f8aa82a554 0.4.0 2011-04-18 18:02:37 +01:00
Bastien Nocera
1451a2dde2 build: Quiet by default 2011-04-08 15:38:33 +01:00
Sergio Cerlesi
d2e957683f Added support for Validity VFS101
USB ID 138a:0001
2011-04-08 15:37:03 +01:00
Sergio Cerlesi
a3ae96c214 Fix function fpi_im_resize on create new image
The function fpi_im_resize copy the new resized image into old fp_img
instead of newimg so, new image is empty and often it generated a
segmentation fault error.
2011-02-22 19:14:02 +00:00
Sergio Cerlesi
3dd905d4e9 Fix return timeout of fp_get_next_timeout
On function fp_get_next_timeout if exist fprint timeout or libusb
timeout the function return the smaller of they.

But if one of that not exist and have a smaller value the function
return a timeout that not exist.
2011-02-18 13:59:28 +00:00
Bastien Nocera
aab031ce37 0.3.0 2010-09-08 11:11:31 +01:00
Bastien Nocera
6bfc516553 Add test program for C++ support
So that we don't regress
2010-09-08 11:03:58 +01:00
Kunal Gangakhedkar
ff842125c5 Add C++ guards to take care of C++ name-mangling.
The libfprint library is generally built with C calling conventions.
Which makes it difficult to link to C++ programs as it is.

This patch adds the support for linking with C++ code - by telling the C++
compiler to use C calling conventions for libfprint functions.

Reported-by: Guus Ellenkamp <guus@activediscovery.net>
Signed-off-by: Kunal Gangakhedkar <kunal.gangakhedkar@gmail.com>
2010-09-08 11:02:25 +01:00
Hugo Grostabussiat
712ebb6d44 Namespace functions and structs for 147e:2016
Inserted "_2016" in structures, enums and functions names
that are related with device 147e:2016.
2010-08-31 17:51:21 +01:00
Hugo Grostabussiat
a18f318446 Added support for UPEK TCS4C (USB ID 147e:1000)
https://bugs.freedesktop.org/show_bug.cgi?id=29719
2010-08-31 17:49:45 +01:00
Bastien Nocera
15b8e8f376 Remove HAL fdi generation
HAL is deprecated, and the rules are broken when multiple
drivers use the same USB IDs.
2010-08-25 11:20:55 +01:00
Bastien Nocera
9f8dd29a55 Make sure all sources are dist'ed
So that you can compile against ImageMagick even if the
distter doesn't.
2010-08-25 11:17:42 +01:00
Bastien Nocera
f28c579779 Print out summary of build options
At the end of the configure run.
2010-08-25 11:17:19 +01:00
Bastien Nocera
375575b701 Port OpenSSL using code to NSS
As OpenSSL cannot really be used in an LGPLv2+ piece of software
without an exception.

Adapted from the example code at:
http://www.mozilla.org/projects/security/pki/nss/sample-code/sample2.html
and:
http://github.com/bagder/curl/commit/f3b77e5
2010-08-25 10:34:30 +01:00
Alexia Death
25161286f5 Only complete scan with MIN_ROWS in print
Don't consider the scan complete unless theres at least
MIN_ROWS recorded or very long blank read occurred.

Typical problem spot: one brief touch before starting the
actual scan. Happens most commonly if scan is started from
before the first joint resulting in a gap after the inital touch.

http://lists.reactivated.net/pipermail/fprint/2009-December/001406.html
2010-08-19 20:36:16 +01:00
Alexia Death
c575afba9a Make the +2 right shift happen on image handoff.
Rather than when reading the rows. Doing it there seems a lot
more sensible and does not get in the way of minimizing the
impact of lost USB packets.

http://lists.reactivated.net/pipermail/fprint/2009-December/001404.html
2010-08-19 20:29:45 +01:00
Alexia Death
8cd31f6ad8 Try to correct missing packets in image stream
If a packet goes missing, use the data from previous row
to minimize distortion, or use some neutral dummy data.

http://lists.reactivated.net/pipermail/fprint/2009-December/001404.html
2010-08-19 20:27:09 +01:00
Alexia Death
4b518bd230 Fix a segfault if a scan was shorter than 8 lines.
This segfault was caused by proceeding to free the conversion result
without checking for an error condition in image to print
data conversion.

http://lists.reactivated.net/pipermail/fprint/2009-December/001405.html
2010-08-19 20:21:51 +01:00
16 changed files with 2175 additions and 240 deletions

View File

@@ -7,3 +7,4 @@ Copyright (C) 2007 Cyrille Bagard
Copyright (C) 2007 Vasily Khoruzhick
Copyright (C) 2007 Jan-Michael Brummer <buzz2@gmx.de>
Copyright (C) 2007 Anthony Bretaudeau <wxcover@users.sourceforge.net>
Copyright (C) 2010 Hugo Grostabussiat <dw23.devel@gmail.com>

13
NEWS
View File

@@ -1,6 +1,19 @@
This file lists notable changes in each release. For the full history of all
changes, see ChangeLog.
2011-04-18: v0.4.0 release
* Add support for Validity VFS101 (USB ID 138a:0001)
* Fix crasher when resizing a fingerprint image
* Fix wrong timeout being returned when either of
libusb or libfprint doesn't have a timeout
2010-09-08: v0.3.0 release
* Add support for UPEK TCS4C (USB ID 147e:1000)
* Use NSS instead of OpenSSL for GPL compliance
* upeksonly driver bug fixes
* Fix a crash if a scan was shorter than 8 lines
* Fix compilation with C++ compiler
2010-08-19: v0.2.0 release (since 0.1.0-pre2)
* Add gdk-pixbuf support for image manipulation
* Add udev rules to allow devices to autosuspend

View File

@@ -1,14 +1,18 @@
AC_INIT([libfprint], [0.2.0])
AC_INIT([libfprint], [0.4.0])
AM_INIT_AUTOMAKE([1.11 dist-bzip2 no-dist-gzip check-news])
AC_CONFIG_MACRO_DIR([m4])
AC_CONFIG_SRCDIR([libfprint/core.c])
AM_CONFIG_HEADER([config.h])
# Enable silent build when available (Automake 1.11)
m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])])
AC_PREREQ([2.50])
AC_PROG_CC
AC_PROG_LIBTOOL
AC_C_INLINE
AM_PROG_CC_C_O
AC_PROG_CXX
AC_DEFINE([_GNU_SOURCE], [], [Use GNU extensions])
# Library versioning
@@ -19,7 +23,7 @@ AC_SUBST(lt_major)
AC_SUBST(lt_revision)
AC_SUBST(lt_age)
all_drivers="upeke2 upekts upektc upeksonly vcom5s uru4000 fdu2000 aes1610 aes2501 aes4000"
all_drivers="upeke2 upekts upektc upeksonly vcom5s uru4000 fdu2000 aes1610 aes2501 aes4000 vfs101"
require_imaging='no'
require_aeslib='no'
@@ -33,6 +37,7 @@ enable_fdu2000='no'
enable_aes1610='no'
enable_aes2501='no'
enable_aes4000='no'
enable_vfs101='no'
AC_ARG_WITH([drivers],[AS_HELP_STRING([--with-drivers],
[List of drivers to enable])],
@@ -51,7 +56,8 @@ for driver in `echo ${drivers} | sed -e 's/,/ /g' -e 's/,$//g'`; do
;;
upektc)
AC_DEFINE([ENABLE_UPEKTC], [], [Build UPEK TouchChip driver])
enable_upektc="yes"
enable_upektc="no"
# Driver not ported
;;
upeksonly)
AC_DEFINE([ENABLE_UPEKSONLY], [], [Build UPEK TouchStrip sensor-only driver])
@@ -63,7 +69,8 @@ for driver in `echo ${drivers} | sed -e 's/,/ /g' -e 's/,$//g'`; do
;;
fdu2000)
AC_DEFINE([ENABLE_FDU2000], [], [Build Secugen FDU 2000 driver])
enable_fdu2000="yes"
enable_fdu2000="no"
# Driver not ported
;;
vcom5s)
AC_DEFINE([ENABLE_VCOM5S], [], [Build Veridicom 5thSense driver])
@@ -85,20 +92,25 @@ for driver in `echo ${drivers} | sed -e 's/,/ /g' -e 's/,$//g'`; do
require_imaging="yes"
enable_aes4000="yes"
;;
vfs101)
AC_DEFINE([ENABLE_VFS101], [], [Build Validity VFS101 driver])
enable_vfs101="yes"
;;
esac
done
AM_CONDITIONAL([ENABLE_UPEKTS], [test "$enable_upekts" != "no"])
AM_CONDITIONAL([ENABLE_UPEKE2], [test "$enable_upeke2" != "no"])
#AM_CONDITIONAL([ENABLE_UPEKTC], [test "$enable_upektc" != "no"])
AM_CONDITIONAL([ENABLE_UPEKSONLY], [test "$enable_upeksonly" != "no"])
AM_CONDITIONAL([ENABLE_VCOM5S], [test "$enable_vcom5s" != "no"])
AM_CONDITIONAL([ENABLE_URU4000], [test "$enable_uru4000" != "no"])
#AM_CONDITIONAL([ENABLE_FDU2000], [test "$enable_fdu2000" != "no"])
AM_CONDITIONAL([ENABLE_AES1610], [test "$enable_aes1610" != "no"])
AM_CONDITIONAL([ENABLE_AES2501], [test "$enable_aes2501" != "no"])
AM_CONDITIONAL([ENABLE_AES4000], [test "$enable_aes4000" != "no"])
AM_CONDITIONAL([REQUIRE_AESLIB], [test "$require_aeslib" != "no"])
AM_CONDITIONAL([ENABLE_UPEKTS], [test "$enable_upekts" = "yes"])
AM_CONDITIONAL([ENABLE_UPEKE2], [test "$enable_upeke2" = "yes"])
#AM_CONDITIONAL([ENABLE_UPEKTC], [test "$enable_upektc" = "yes"])
AM_CONDITIONAL([ENABLE_UPEKSONLY], [test "$enable_upeksonly" = "yes"])
AM_CONDITIONAL([ENABLE_VCOM5S], [test "$enable_vcom5s" = "yes"])
AM_CONDITIONAL([ENABLE_URU4000], [test "$enable_uru4000" = "yes"])
AM_CONDITIONAL([ENABLE_FDU2000], [test "$enable_fdu2000" = "yes"])
AM_CONDITIONAL([ENABLE_AES1610], [test "$enable_aes1610" = "yes"])
AM_CONDITIONAL([ENABLE_AES2501], [test "$enable_aes2501" = "yes"])
AM_CONDITIONAL([ENABLE_AES4000], [test "$enable_aes4000" = "yes"])
AM_CONDITIONAL([REQUIRE_AESLIB], [test "$require_aeslib" = "yes"])
AM_CONDITIONAL([ENABLE_VFS101], [test "$enable_vfs101" = "yes"])
PKG_CHECK_MODULES(LIBUSB, [libusb-1.0 >= 0.9.1])
@@ -106,7 +118,7 @@ AC_SUBST(LIBUSB_CFLAGS)
AC_SUBST(LIBUSB_LIBS)
# check for OpenSSL's libcrypto
PKG_CHECK_MODULES(CRYPTO, "libcrypto")
PKG_CHECK_MODULES(CRYPTO, nss)
AC_SUBST(CRYPTO_CFLAGS)
AC_SUBST(CRYPTO_LIBS)
@@ -117,21 +129,21 @@ AC_SUBST(GLIB_LIBS)
imagemagick_found=no
gdkpixbuf_found=no
if test "$require_imaging" != "no"; then
if test "$require_imaging" = "yes"; then
PKG_CHECK_MODULES(IMAGING, gthread-2.0 gdk-pixbuf-2.0, [gdkpixbuf_found=yes], [gdkpixbuf_found=no])
if test "$gdkpixbuf_found" != "yes"; then
PKG_CHECK_MODULES(IMAGING, ImageMagick, [imagemagick_found=yes], [imagemagick_found=no])
fi
fi
if test "$require_imaging" != "no"; then
if test "$require_imaging" = "yes"; then
if test "$gdkpixbuf_found" != "yes" && test "$imagemagick_found" != "yes"; then
AC_MSG_ERROR([gdk-pixbuf or ImageMagick is required for imaging support])
fi
fi
AM_CONDITIONAL([REQUIRE_GDKPIXBUF], [test "$gdkpixbuf_found" != "no"])
AM_CONDITIONAL([REQUIRE_IMAGEMAGICK], [test "$imagemagick_found" != "no"])
AM_CONDITIONAL([REQUIRE_GDKPIXBUF], [test "$gdkpixbuf_found" = "yes"])
AM_CONDITIONAL([REQUIRE_IMAGEMAGICK], [test "$imagemagick_found" = "yes"])
AC_SUBST(IMAGING_CFLAGS)
AC_SUBST(IMAGING_LIBS)
@@ -200,6 +212,77 @@ AC_DEFINE([API_EXPORTED], [__attribute__((visibility("default")))], [Default vis
AM_CFLAGS="-std=gnu99 $inline_cflags -Wall -Wundef -Wunused -Wstrict-prototypes -Werror-implicit-function-declaration -Wno-pointer-sign -Wshadow"
AC_SUBST(AM_CFLAGS)
if test "$require_imaging" = "yes"; then
if test x$gdkpixbuf_found != no; then
AC_MSG_NOTICE([** Using gdk-pixbuf for imaging])
else
AC_MSG_NOTICE([** Using ImageMagick for imaging])
fi
else
AC_MSG_NOTICE([ Imaging support disabled])
fi
if test x$enable_upekts != xno ; then
AC_MSG_NOTICE([** upekts driver enabled])
else
AC_MSG_NOTICE([ upekts driver disabled])
fi
if test x$enable_upeke2 != xno ; then
AC_MSG_NOTICE([** upeke2 driver enabled])
else
AC_MSG_NOTICE([ upeke2 driver disabled])
fi
if test x$enable_upektc != xno ; then
AC_MSG_NOTICE([** upektc driver enabled])
else
AC_MSG_NOTICE([ upektc driver disabled])
fi
if test x$enable_upeksonly != xno ; then
AC_MSG_NOTICE([** upeksonly driver enabled])
else
AC_MSG_NOTICE([ upeksonly driver disabled])
fi
if test x$enable_vcom5s != xno ; then
AC_MSG_NOTICE([** vcom5s driver enabled])
else
AC_MSG_NOTICE([ vcom5s driver disabled])
fi
if test x$enable_uru4000 != xno ; then
AC_MSG_NOTICE([** uru4000 driver enabled])
else
AC_MSG_NOTICE([ uru4000 driver disabled])
fi
if test x$enable_fdu2000 != xno ; then
AC_MSG_NOTICE([** fdu2000 driver enabled])
else
AC_MSG_NOTICE([ fdu2000 driver disabled])
fi
if test x$enable_aes1610 != xno ; then
AC_MSG_NOTICE([** aes1610 driver enabled])
else
AC_MSG_NOTICE([ aes1610 driver disabled])
fi
if test x$enable_aes2501 != xno ; then
AC_MSG_NOTICE([** aes2501 driver enabled])
else
AC_MSG_NOTICE([ aes2501 driver disabled])
fi
if test x$enable_aes4000 != xno ; then
AC_MSG_NOTICE([** aes4000 driver enabled])
else
AC_MSG_NOTICE([ aes4000 driver disabled])
fi
if test x$enable_vfs101 != xno ; then
AC_MSG_NOTICE([** vfs101 driver enabled])
else
AC_MSG_NOTICE([ vfs101 driver disabled])
fi
if test x$require_aeslib != xno ; then
AC_MSG_NOTICE([** aeslib helper functions enabled])
else
AC_MSG_NOTICE([ aeslib helper functions disabled])
fi
AC_CONFIG_FILES([libfprint.pc] [Makefile] [libfprint/Makefile] [examples/Makefile] [doc/Makefile])
AC_OUTPUT

View File

@@ -1,5 +1,5 @@
INCLUDES = -I$(top_srcdir)
noinst_PROGRAMS = verify_live enroll verify img_capture
noinst_PROGRAMS = verify_live enroll verify img_capture cpp-test
verify_live_SOURCES = verify_live.c
verify_live_LDADD = ../libfprint/libfprint.la
@@ -13,6 +13,9 @@ verify_LDADD = ../libfprint/libfprint.la
img_capture_SOURCES = img_capture.c
img_capture_LDADD = ../libfprint/libfprint.la
cpp_test_SOURCES = cpp-test.cpp
cpp_test_LDADD = ../libfprint/libfprint.la
if BUILD_X11_EXAMPLES
noinst_PROGRAMS += img_capture_continuous

11
examples/cpp-test.cpp Normal file
View File

@@ -0,0 +1,11 @@
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <libfprint/fprint.h>
int main (int argc, char **argv)
{
fp_init ();
return 0;
}

View File

@@ -1,6 +1,6 @@
lib_LTLIBRARIES = libfprint.la
noinst_PROGRAMS = fprint-list-hal-info fprint-list-udev-rules
MOSTLYCLEANFILES = $(hal_fdi_DATA) $(udev_rules_DATA)
noinst_PROGRAMS = fprint-list-udev-rules
MOSTLYCLEANFILES = $(udev_rules_DATA)
UPEKE2_SRC = drivers/upeke2.c
UPEKTS_SRC = drivers/upekts.c
@@ -12,6 +12,23 @@ AES2501_SRC = drivers/aes2501.c drivers/aes2501.h
AES4000_SRC = drivers/aes4000.c
FDU2000_SRC = drivers/fdu2000.c
VCOM5S_SRC = drivers/vcom5s.c
VFS101_SRC = drivers/vfs101.c
EXTRA_DIST = \
$(UPEKE2_SRC) \
$(UPEKTS_SRC) \
$(UPEKTC_SRC) \
$(UPEKSONLY_SRC) \
$(URU4000_SRC) \
$(AES1610_SRC) \
$(AES2501_SRC) \
$(AES4000_SRC) \
$(FDU2000_SRC) \
$(VCOM5S_SRC) \
$(VFS101_SRC) \
aeslib.c aeslib.h \
imagemagick.c \
gdkpixbuf.c
DRIVER_SRC =
OTHER_SRC =
@@ -57,16 +74,6 @@ libfprint_la_CFLAGS = -fvisibility=hidden -I$(srcdir)/nbis/include $(LIBUSB_CFLA
libfprint_la_LDFLAGS = -version-info @lt_major@:@lt_revision@:@lt_age@
libfprint_la_LIBADD = -lm $(LIBUSB_LIBS) $(GLIB_LIBS) $(CRYPTO_LIBS)
fprint_list_hal_info_SOURCES = fprint-list-hal-info.c
fprint_list_hal_info_CFLAGS = -fvisibility=hidden -I$(srcdir)/nbis/include $(LIBUSB_CFLAGS) $(GLIB_CFLAGS) $(IMAGEMAGICK_CFLAGS) $(CRYPTO_CFLAGS) $(AM_CFLAGS)
fprint_list_hal_info_LDADD = $(builddir)/libfprint.la
hal_fdi_DATA = 10-fingerprint-reader-fprint.fdi
hal_fdidir = $(datadir)/hal/fdi/information/20thirdparty/
$(hal_fdi_DATA): fprint-list-hal-info
$(builddir)/fprint-list-hal-info > $@
fprint_list_udev_rules_SOURCES = fprint-list-udev-rules.c
fprint_list_udev_rules_CFLAGS = -fvisibility=hidden -I$(srcdir)/nbis/include $(LIBUSB_CFLAGS) $(GLIB_CFLAGS) $(IMAGEMAGICK_CFLAGS) $(CRYPTO_CFLAGS) $(AM_CFLAGS)
fprint_list_udev_rules_LDADD = $(builddir)/libfprint.la
@@ -117,6 +124,10 @@ if ENABLE_AES4000
DRIVER_SRC += $(AES4000_SRC)
endif
if ENABLE_VFS101
DRIVER_SRC += $(VFS101_SRC)
endif
if REQUIRE_IMAGEMAGICK
OTHER_SRC += imagemagick.c
libfprint_la_CFLAGS += $(IMAGING_CFLAGS)

View File

@@ -368,6 +368,9 @@ static struct fp_img_driver * const img_drivers[] = {
#ifdef ENABLE_AES1610
&aes1610_driver,
#endif
#ifdef ENABLE_VFS101
&vfs101_driver,
#endif
/*#ifdef ENABLE_UPEKTC
&upektc_driver,
#endif

View File

@@ -2,6 +2,9 @@
* UPEK TouchStrip Sensor-Only driver for libfprint
* Copyright (C) 2008 Daniel Drake <dsd@gentoo.org>
*
* TCS4C (USB ID 147e:1000) support:
* Copyright (C) 2010 Hugo Grostabussiat <dw23.devel@gmail.com>
*
* 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
@@ -31,6 +34,12 @@
#define IMG_WIDTH 288
#define NUM_BULK_TRANSFERS 24
#define MAX_ROWS 700
#define MIN_ROWS 64
enum {
UPEKSONLY_2016,
UPEKSONLY_1000,
};
struct img_transfer_data {
int idx;
@@ -60,6 +69,8 @@ struct sonly_dev {
gboolean deactivating;
uint8_t read_reg_result;
int dev_model;
struct fpi_ssm *loopsm;
struct libusb_transfer *img_transfer[NUM_BULK_TRANSFERS];
struct img_transfer_data *img_transfer_data;
@@ -168,8 +179,12 @@ static void handoff_img(struct fp_img_dev *dev)
fp_dbg("%d rows", sdev->num_rows);
img->height = sdev->num_rows;
/* The scans from this device are rolled right by two colums
* It feels a lot smarter to correct here than mess with it at
* read time*/
do {
memcpy(img->data + offset, elem->data, IMG_WIDTH);
memcpy(img->data + offset, elem->data + 2, IMG_WIDTH - 2);
memcpy(img->data + offset + IMG_WIDTH - 2, elem->data, 2);
g_free(elem->data);
offset += IMG_WIDTH;
} while ((elem = g_slist_next(elem)) != NULL);
@@ -214,13 +229,22 @@ static void row_complete(struct fp_img_dev *dev)
int total;
compute_rows(lastrow, sdev->rowbuf, &diff, &total);
if (total < 52000) {
sdev->num_blank = 0;
} else {
sdev->num_blank++;
if (sdev->num_blank > 500) {
/* Don't consider the scan complete unless theres at least
* MIN_ROWS recorded or very long blank read occurred.
*
* Typical problem spot: one brief touch before starting the
* actual scan. Happens most commonly if scan is started
* from before the first joint resulting in a gap after the inital touch.
*/
if ((sdev->num_blank > 500)
&& ((sdev->num_rows > MIN_ROWS) || (sdev->num_blank > 5000))) {
sdev->finger_removed = 1;
fp_dbg("detected finger removal");
fp_dbg("detected finger removal. Blank rows: %d, Full rows: %d", sdev->num_blank, sdev->num_rows);
handoff_img(dev);
return;
}
@@ -248,14 +272,14 @@ static void add_to_rowbuf(struct fp_img_dev *dev, unsigned char *data, int size)
sdev->rowbuf_offset += size;
if (sdev->rowbuf_offset >= IMG_WIDTH)
row_complete(dev);
}
static void start_new_row(struct sonly_dev *sdev, unsigned char *data, int size)
{
if (!sdev->rowbuf)
sdev->rowbuf = g_malloc(IMG_WIDTH);
memcpy(sdev->rowbuf + IMG_WIDTH - 2, data, 2);
memcpy(sdev->rowbuf, data + 2, size - 2);
memcpy(sdev->rowbuf, data, size);
sdev->rowbuf_offset = size;
}
@@ -282,11 +306,56 @@ static void handle_packet(struct fp_img_dev *dev, unsigned char *data)
int for_rowbuf;
int next_row_addr;
int diff;
unsigned char dummy_data[62];
/* Init dummy data to something neutral */
memset (dummy_data, 204, 62);
data += 2; /* skip sequence number */
if (seqnum != sdev->last_seqnum + 1) {
if (seqnum != 0 && sdev->last_seqnum != 16383)
fp_warn("lost some data");
if (seqnum != 0 && sdev->last_seqnum != 16383) {
int missing_data = seqnum - sdev->last_seqnum;
int i;
fp_warn("lost %d packets of data between %d and %d", missing_data, sdev->last_seqnum, seqnum );
/* Minimize distortions for readers that lose a lot of packets */
for (i =1; i < missing_data; i++) {
abs_base_addr = (sdev->last_seqnum + 1) * 62;
/* If possible take the replacement data from last row */
if (sdev->num_rows > 1) {
int row_left = IMG_WIDTH - sdev->rowbuf_offset;
unsigned char *last_row = g_slist_nth_data (sdev->rows, 0);
if (row_left >= 62) {
memcpy(dummy_data, last_row + sdev->rowbuf_offset, 62);
} else {
memcpy(dummy_data, last_row + sdev->rowbuf_offset, row_left);
memcpy(dummy_data + row_left, last_row , 62 - row_left);
}
}
fp_warn("adding dummy input for %d, i=%d", sdev->last_seqnum + i, i);
for_rowbuf = rowbuf_remaining(sdev);
if (for_rowbuf != -1) {
add_to_rowbuf(dev, dummy_data, for_rowbuf);
/* row boundary */
if (for_rowbuf < 62) {
start_new_row(sdev, dummy_data + for_rowbuf, 62 - for_rowbuf);
}
} else if (abs_base_addr % IMG_WIDTH == 0) {
start_new_row(sdev, dummy_data, 62);
} else {
/* does the data in the packet reside on a row boundary?
* if so capture it */
next_row_addr = ((abs_base_addr / IMG_WIDTH) + 1) * IMG_WIDTH;
diff = next_row_addr - abs_base_addr;
if (diff < 62)
start_new_row(sdev, dummy_data + diff, 62 - diff);
}
sdev->last_seqnum = sdev->last_seqnum + 1;
}
}
}
if (seqnum <= sdev->last_seqnum) {
fp_dbg("detected wraparound");
@@ -302,7 +371,10 @@ static void handle_packet(struct fp_img_dev *dev, unsigned char *data)
for_rowbuf = rowbuf_remaining(sdev);
if (for_rowbuf != -1) {
add_to_rowbuf(dev, data, for_rowbuf);
/* FIXME: we drop a row here */
/*row boundary*/
if (for_rowbuf < 62) {
start_new_row(sdev, data + for_rowbuf, 62 - for_rowbuf);
}
return;
}
@@ -591,22 +663,42 @@ static void sm_await_intr(struct fpi_ssm *ssm)
/***** AWAIT FINGER *****/
static const struct sonly_regwrite awfsm_writev_1[] = {
static const struct sonly_regwrite awfsm_2016_writev_1[] = {
{ 0x0a, 0x00 }, { 0x0a, 0x00 }, { 0x09, 0x20 }, { 0x03, 0x3b },
{ 0x00, 0x67 }, { 0x00, 0x67 },
};
static const struct sonly_regwrite awfsm_writev_2[] = {
static const struct sonly_regwrite awfsm_1000_writev_1[] = {
/* Initialize sensor settings */
{ 0x0a, 0x00 }, { 0x09, 0x20 }, { 0x03, 0x37 }, { 0x00, 0x5f },
{ 0x01, 0x6e }, { 0x01, 0xee }, { 0x0c, 0x13 }, { 0x0d, 0x0d },
{ 0x0e, 0x0e }, { 0x0f, 0x0d },
{ 0x13, 0x05 }, { 0x13, 0x45 },
/* Initialize finger detection registers (not enabling yet) */
{ 0x30, 0xe0 }, { 0x15, 0x26 },
{ 0x12, 0x01 }, { 0x20, 0x01 }, { 0x07, 0x10 },
{ 0x10, 0x00 }, { 0x11, 0xbf },
};
static const struct sonly_regwrite awfsm_2016_writev_2[] = {
{ 0x01, 0xc6 }, { 0x0c, 0x13 }, { 0x0d, 0x0d }, { 0x0e, 0x0e },
{ 0x0f, 0x0d }, { 0x0b, 0x00 },
};
static const struct sonly_regwrite awfsm_writev_3[] = {
static const struct sonly_regwrite awfsm_1000_writev_2[] = {
/* Enable finger detection */
{ 0x30, 0xe1 }, { 0x15, 0x06 }, { 0x15, 0x86 },
};
static const struct sonly_regwrite awfsm_2016_writev_3[] = {
{ 0x13, 0x45 }, { 0x30, 0xe0 }, { 0x12, 0x01 }, { 0x20, 0x01 },
{ 0x09, 0x20 }, { 0x0a, 0x00 }, { 0x30, 0xe0 }, { 0x20, 0x01 },
};
static const struct sonly_regwrite awfsm_writev_4[] = {
static const struct sonly_regwrite awfsm_2016_writev_4[] = {
{ 0x08, 0x00 }, { 0x10, 0x00 }, { 0x12, 0x01 }, { 0x11, 0xbf },
{ 0x12, 0x01 }, { 0x07, 0x10 }, { 0x07, 0x10 }, { 0x04, 0x00 },\
{ 0x05, 0x00 }, { 0x0b, 0x00 },
@@ -616,91 +708,150 @@ static const struct sonly_regwrite awfsm_writev_4[] = {
{ 0x15, 0x84 },
};
enum awfsm_states {
AWFSM_WRITEV_1,
AWFSM_READ_01,
AWFSM_WRITE_01,
AWFSM_WRITEV_2,
AWFSM_READ_13,
AWFSM_WRITE_13,
AWFSM_WRITEV_3,
AWFSM_READ_07,
AWFSM_WRITE_07,
AWFSM_WRITEV_4,
AWFSM_NUM_STATES,
enum awfsm_2016_states {
AWFSM_2016_WRITEV_1,
AWFSM_2016_READ_01,
AWFSM_2016_WRITE_01,
AWFSM_2016_WRITEV_2,
AWFSM_2016_READ_13,
AWFSM_2016_WRITE_13,
AWFSM_2016_WRITEV_3,
AWFSM_2016_READ_07,
AWFSM_2016_WRITE_07,
AWFSM_2016_WRITEV_4,
AWFSM_2016_NUM_STATES,
};
static void awfsm_run_state(struct fpi_ssm *ssm)
enum awfsm_1000_states {
AWFSM_1000_WRITEV_1,
AWFSM_1000_WRITEV_2,
AWFSM_1000_NUM_STATES,
};
static void awfsm_2016_run_state(struct fpi_ssm *ssm)
{
struct fp_img_dev *dev = ssm->priv;
struct sonly_dev *sdev = dev->priv;
switch (ssm->cur_state) {
case AWFSM_WRITEV_1:
sm_write_regs(ssm, awfsm_writev_1, G_N_ELEMENTS(awfsm_writev_1));
case AWFSM_2016_WRITEV_1:
sm_write_regs(ssm, awfsm_2016_writev_1, G_N_ELEMENTS(awfsm_2016_writev_1));
break;
case AWFSM_READ_01:
case AWFSM_2016_READ_01:
sm_read_reg(ssm, 0x01);
break;
case AWFSM_WRITE_01:
case AWFSM_2016_WRITE_01:
if (sdev->read_reg_result != 0xc6)
sm_write_reg(ssm, 0x01, 0x46);
else
sm_write_reg(ssm, 0x01, 0xc6);
break;
case AWFSM_WRITEV_2:
sm_write_regs(ssm, awfsm_writev_2, G_N_ELEMENTS(awfsm_writev_2));
case AWFSM_2016_WRITEV_2:
sm_write_regs(ssm, awfsm_2016_writev_2, G_N_ELEMENTS(awfsm_2016_writev_2));
break;
case AWFSM_READ_13:
case AWFSM_2016_READ_13:
sm_read_reg(ssm, 0x13);
break;
case AWFSM_WRITE_13:
case AWFSM_2016_WRITE_13:
if (sdev->read_reg_result != 0x45)
sm_write_reg(ssm, 0x13, 0x05);
else
sm_write_reg(ssm, 0x13, 0x45);
break;
case AWFSM_WRITEV_3:
sm_write_regs(ssm, awfsm_writev_3, G_N_ELEMENTS(awfsm_writev_3));
case AWFSM_2016_WRITEV_3:
sm_write_regs(ssm, awfsm_2016_writev_3, G_N_ELEMENTS(awfsm_2016_writev_3));
break;
case AWFSM_READ_07:
case AWFSM_2016_READ_07:
sm_read_reg(ssm, 0x07);
break;
case AWFSM_WRITE_07:
case AWFSM_2016_WRITE_07:
if (sdev->read_reg_result != 0x10 && sdev->read_reg_result != 0x90)
fp_warn("odd reg7 value %x", sdev->read_reg_result);
sm_write_reg(ssm, 0x07, sdev->read_reg_result);
break;
case AWFSM_WRITEV_4:
sm_write_regs(ssm, awfsm_writev_4, G_N_ELEMENTS(awfsm_writev_4));
case AWFSM_2016_WRITEV_4:
sm_write_regs(ssm, awfsm_2016_writev_4, G_N_ELEMENTS(awfsm_2016_writev_4));
break;
}
}
static void awfsm_1000_run_state(struct fpi_ssm *ssm)
{
switch (ssm->cur_state) {
case AWFSM_1000_WRITEV_1:
sm_write_regs(ssm, awfsm_1000_writev_1, G_N_ELEMENTS(awfsm_1000_writev_1));
break;
case AWFSM_1000_WRITEV_2:
sm_write_regs(ssm, awfsm_1000_writev_2, G_N_ELEMENTS(awfsm_1000_writev_2));
break;
}
}
/***** CAPTURE MODE *****/
static const struct sonly_regwrite capsm_writev[] = {
static const struct sonly_regwrite capsm_2016_writev[] = {
/* enter capture mode */
{ 0x09, 0x28 }, { 0x13, 0x55 }, { 0x0b, 0x80 }, { 0x04, 0x00 },
{ 0x05, 0x00 },
};
enum capsm_states {
CAPSM_INIT,
CAPSM_WRITE_15,
CAPSM_WRITE_30,
CAPSM_FIRE_BULK,
CAPSM_WRITEV,
CAPSM_NUM_STATES,
static const struct sonly_regwrite capsm_1000_writev[] = {
{ 0x08, 0x80 }, { 0x13, 0x55 }, { 0x0b, 0x80 }, /* Enter capture mode */
};
static void capsm_run_state(struct fpi_ssm *ssm)
enum capsm_2016_states {
CAPSM_2016_INIT,
CAPSM_2016_WRITE_15,
CAPSM_2016_WRITE_30,
CAPSM_2016_FIRE_BULK,
CAPSM_2016_WRITEV,
CAPSM_2016_NUM_STATES,
};
enum capsm_1000_states {
CAPSM_1000_INIT,
CAPSM_1000_FIRE_BULK,
CAPSM_1000_WRITEV,
CAPSM_1000_NUM_STATES,
};
static void capsm_fire_bulk(struct fpi_ssm *ssm)
{
struct fp_img_dev *dev = ssm->priv;
struct sonly_dev *sdev = dev->priv;
int i;
for (i = 0; i < NUM_BULK_TRANSFERS; i++) {
int r = libusb_submit_transfer(sdev->img_transfer[i]);
if (r < 0) {
if (i == 0) {
/* first one failed: easy peasy */
fpi_ssm_mark_aborted(ssm, r);
return;
}
/* cancel all flying transfers, and request that the SSM
* gets aborted when the last transfer has dropped out of
* the sky */
sdev->killing_transfers = ABORT_SSM;
sdev->kill_ssm = ssm;
sdev->kill_status_code = r;
cancel_img_transfers(dev);
return;
}
sdev->img_transfer_data[i].flying = TRUE;
sdev->num_flying++;
}
sdev->capturing = TRUE;
fpi_ssm_next_state(ssm);
}
static void capsm_2016_run_state(struct fpi_ssm *ssm)
{
struct fp_img_dev *dev = ssm->priv;
struct sonly_dev *sdev = dev->priv;
switch (ssm->cur_state) {
case CAPSM_INIT:
case CAPSM_2016_INIT:
sdev->rowbuf_offset = -1;
sdev->num_rows = 0;
sdev->wraparounds = -1;
@@ -710,68 +861,91 @@ static void capsm_run_state(struct fpi_ssm *ssm)
sdev->killing_transfers = 0;
fpi_ssm_next_state(ssm);
break;
case CAPSM_WRITE_15:
case CAPSM_2016_WRITE_15:
sm_write_reg(ssm, 0x15, 0x20);
break;
case CAPSM_WRITE_30:
case CAPSM_2016_WRITE_30:
sm_write_reg(ssm, 0x30, 0xe0);
break;
case CAPSM_FIRE_BULK: ;
int i;
for (i = 0; i < NUM_BULK_TRANSFERS; i++) {
int r = libusb_submit_transfer(sdev->img_transfer[i]);
if (r < 0) {
if (i == 0) {
/* first one failed: easy peasy */
fpi_ssm_mark_aborted(ssm, r);
return;
}
case CAPSM_2016_FIRE_BULK: ;
capsm_fire_bulk (ssm);
break;
case CAPSM_2016_WRITEV:
sm_write_regs(ssm, capsm_2016_writev, G_N_ELEMENTS(capsm_2016_writev));
break;
}
}
/* cancel all flying transfers, and request that the SSM
* gets aborted when the last transfer has dropped out of
* the sky */
sdev->killing_transfers = ABORT_SSM;
sdev->kill_ssm = ssm;
sdev->kill_status_code = r;
cancel_img_transfers(dev);
return;
}
sdev->img_transfer_data[i].flying = TRUE;
sdev->num_flying++;
}
sdev->capturing = TRUE;
static void capsm_1000_run_state(struct fpi_ssm *ssm)
{
struct fp_img_dev *dev = ssm->priv;
struct sonly_dev *sdev = dev->priv;
switch (ssm->cur_state) {
case CAPSM_1000_INIT:
sdev->rowbuf_offset = -1;
sdev->num_rows = 0;
sdev->wraparounds = -1;
sdev->num_blank = 0;
sdev->finger_removed = 0;
sdev->last_seqnum = 16383;
sdev->killing_transfers = 0;
fpi_ssm_next_state(ssm);
break;
case CAPSM_WRITEV:
sm_write_regs(ssm, capsm_writev, G_N_ELEMENTS(capsm_writev));
case CAPSM_1000_FIRE_BULK: ;
capsm_fire_bulk (ssm);
break;
case CAPSM_1000_WRITEV:
sm_write_regs(ssm, capsm_1000_writev, G_N_ELEMENTS(capsm_1000_writev));
break;
}
}
/***** DEINITIALIZATION *****/
static const struct sonly_regwrite deinitsm_writev[] = {
static const struct sonly_regwrite deinitsm_2016_writev[] = {
/* reset + enter low power mode */
{ 0x0b, 0x00 }, { 0x09, 0x20 }, { 0x13, 0x45 }, { 0x13, 0x45 },
};
enum deinitsm_states {
DEINITSM_WRITEV,
DEINITSM_NUM_STATES,
static const struct sonly_regwrite deinitsm_1000_writev[] = {
{ 0x15, 0x26 }, { 0x30, 0xe0 }, /* Disable finger detection */
{ 0x0b, 0x00 }, { 0x13, 0x45 }, { 0x08, 0x00 }, /* Disable capture mode */
};
static void deinitsm_run_state(struct fpi_ssm *ssm)
enum deinitsm_2016_states {
DEINITSM_2016_WRITEV,
DEINITSM_2016_NUM_STATES,
};
enum deinitsm_1000_states {
DEINITSM_1000_WRITEV,
DEINITSM_1000_NUM_STATES,
};
static void deinitsm_2016_run_state(struct fpi_ssm *ssm)
{
switch (ssm->cur_state) {
case DEINITSM_WRITEV:
sm_write_regs(ssm, deinitsm_writev, G_N_ELEMENTS(deinitsm_writev));
case DEINITSM_2016_WRITEV:
sm_write_regs(ssm, deinitsm_2016_writev, G_N_ELEMENTS(deinitsm_2016_writev));
break;
}
}
static void deinitsm_1000_run_state(struct fpi_ssm *ssm)
{
switch (ssm->cur_state) {
case DEINITSM_1000_WRITEV:
sm_write_regs(ssm, deinitsm_1000_writev, G_N_ELEMENTS(deinitsm_1000_writev));
break;
}
}
/***** INITIALIZATION *****/
static const struct sonly_regwrite initsm_writev_1[] = {
static const struct sonly_regwrite initsm_2016_writev_1[] = {
{ 0x49, 0x00 },
/* BSAPI writes different values to register 0x3e each time. I initially
@@ -784,47 +958,77 @@ static const struct sonly_regwrite initsm_writev_1[] = {
{ 0x44, 0x00 }, { 0x0b, 0x00 },
};
enum initsm_states {
INITSM_WRITEV_1,
INITSM_READ_09,
INITSM_WRITE_09,
INITSM_READ_13,
INITSM_WRITE_13,
INITSM_WRITE_04,
INITSM_WRITE_05,
INITSM_NUM_STATES,
static const struct sonly_regwrite initsm_1000_writev_1[] = {
{ 0x49, 0x00 }, /* Encryption disabled */
/* Setting encryption key. Doesn't need to be random since we don't use any
* encryption. */
{ 0x3e, 0x7f }, { 0x3e, 0x7f }, { 0x3e, 0x7f }, { 0x3e, 0x7f },
{ 0x3e, 0x7f }, { 0x3e, 0x7f }, { 0x3e, 0x7f }, { 0x3e, 0x7f },
{ 0x04, 0x00 }, { 0x05, 0x00 },
{ 0x0b, 0x00 }, { 0x08, 0x00 }, /* Initialize capture control registers */
};
static void initsm_run_state(struct fpi_ssm *ssm)
enum initsm_2016_states {
INITSM_2016_WRITEV_1,
INITSM_2016_READ_09,
INITSM_2016_WRITE_09,
INITSM_2016_READ_13,
INITSM_2016_WRITE_13,
INITSM_2016_WRITE_04,
INITSM_2016_WRITE_05,
INITSM_2016_NUM_STATES,
};
enum initsm_1000_states {
INITSM_1000_WRITEV_1,
INITSM_1000_NUM_STATES,
};
static void initsm_2016_run_state(struct fpi_ssm *ssm)
{
struct fp_img_dev *dev = ssm->priv;
struct sonly_dev *sdev = dev->priv;
switch (ssm->cur_state) {
case INITSM_WRITEV_1:
sm_write_regs(ssm, initsm_writev_1, G_N_ELEMENTS(initsm_writev_1));
case INITSM_2016_WRITEV_1:
sm_write_regs(ssm, initsm_2016_writev_1, G_N_ELEMENTS(initsm_2016_writev_1));
break;
case INITSM_READ_09:
case INITSM_2016_READ_09:
sm_read_reg(ssm, 0x09);
break;
case INITSM_WRITE_09:
case INITSM_2016_WRITE_09:
sm_write_reg(ssm, 0x09, sdev->read_reg_result & ~0x08);
break;
case INITSM_READ_13:
case INITSM_2016_READ_13:
sm_read_reg(ssm, 0x13);
break;
case INITSM_WRITE_13:
case INITSM_2016_WRITE_13:
sm_write_reg(ssm, 0x13, sdev->read_reg_result & ~0x10);
break;
case INITSM_WRITE_04:
case INITSM_2016_WRITE_04:
sm_write_reg(ssm, 0x04, 0x00);
break;
case INITSM_WRITE_05:
case INITSM_2016_WRITE_05:
sm_write_reg(ssm, 0x05, 0x00);
break;
}
}
static void initsm_1000_run_state(struct fpi_ssm *ssm)
{
struct fp_img_dev *dev = ssm->priv;
struct sonly_dev *sdev = dev->priv;
switch (ssm->cur_state) {
case INITSM_1000_WRITEV_1:
sm_write_regs(ssm, initsm_1000_writev_1, G_N_ELEMENTS(initsm_1000_writev_1));
break;
}
}
/***** CAPTURE LOOP *****/
enum loopsm_states {
@@ -847,8 +1051,17 @@ static void loopsm_run_state(struct fpi_ssm *ssm)
if (sdev->deactivating) {
fpi_ssm_mark_completed(ssm);
} else {
struct fpi_ssm *awfsm = fpi_ssm_new(dev->dev, awfsm_run_state,
AWFSM_NUM_STATES);
struct fpi_ssm *awfsm = NULL;
switch (sdev->dev_model) {
case UPEKSONLY_2016:
awfsm = fpi_ssm_new(dev->dev, awfsm_2016_run_state,
AWFSM_2016_NUM_STATES);
break;
case UPEKSONLY_1000:
awfsm = fpi_ssm_new(dev->dev, awfsm_1000_run_state,
AWFSM_1000_NUM_STATES);
break;
}
awfsm->priv = dev;
fpi_ssm_start_subsm(ssm, awfsm);
}
@@ -857,8 +1070,17 @@ static void loopsm_run_state(struct fpi_ssm *ssm)
sm_await_intr(ssm);
break;
case LOOPSM_RUN_CAPSM: ;
struct fpi_ssm *capsm = fpi_ssm_new(dev->dev, capsm_run_state,
CAPSM_NUM_STATES);
struct fpi_ssm *capsm = NULL;
switch (sdev->dev_model) {
case UPEKSONLY_2016:
capsm = fpi_ssm_new(dev->dev, capsm_2016_run_state,
CAPSM_2016_NUM_STATES);
break;
case UPEKSONLY_1000:
capsm = fpi_ssm_new(dev->dev, capsm_1000_run_state,
CAPSM_1000_NUM_STATES);
break;
}
capsm->priv = dev;
fpi_ssm_start_subsm(ssm, capsm);
break;
@@ -867,8 +1089,17 @@ static void loopsm_run_state(struct fpi_ssm *ssm)
* to push us into next state */
break;
case LOOPSM_RUN_DEINITSM: ;
struct fpi_ssm *deinitsm = fpi_ssm_new(dev->dev, deinitsm_run_state,
DEINITSM_NUM_STATES);
struct fpi_ssm *deinitsm = NULL;
switch (sdev->dev_model) {
case UPEKSONLY_2016:
deinitsm = fpi_ssm_new(dev->dev, deinitsm_2016_run_state,
DEINITSM_2016_NUM_STATES);
break;
case UPEKSONLY_1000:
deinitsm = fpi_ssm_new(dev->dev, deinitsm_1000_run_state,
DEINITSM_1000_NUM_STATES);
break;
}
sdev->capturing = FALSE;
deinitsm->priv = dev;
fpi_ssm_start_subsm(ssm, deinitsm);
@@ -977,7 +1208,14 @@ static int dev_activate(struct fp_img_dev *dev, enum fp_imgdev_state state)
4096, img_data_cb, &sdev->img_transfer_data[i], 0);
}
ssm = fpi_ssm_new(dev->dev, initsm_run_state, INITSM_NUM_STATES);
switch (sdev->dev_model) {
case UPEKSONLY_2016:
ssm = fpi_ssm_new(dev->dev, initsm_2016_run_state, INITSM_2016_NUM_STATES);
break;
case UPEKSONLY_1000:
ssm = fpi_ssm_new(dev->dev, initsm_1000_run_state, INITSM_1000_NUM_STATES);
break;
}
ssm->priv = dev;
fpi_ssm_start(ssm, initsm_complete);
return 0;
@@ -1000,6 +1238,7 @@ static int dev_init(struct fp_img_dev *dev, unsigned long driver_data)
}
dev->priv = g_malloc0(sizeof(struct sonly_dev));
((struct sonly_dev*)dev->priv)->dev_model = (int)driver_data;
fpi_imgdev_open_complete(dev, 0);
return 0;
}
@@ -1013,15 +1252,21 @@ static void dev_deinit(struct fp_img_dev *dev)
static int dev_discover(struct libusb_device_descriptor *dsc, uint32_t *devtype)
{
/* Revision 1 is what we're interested in */
if (dsc->bcdDevice == 1)
return 1;
if (dsc->idProduct == 0x2016) {
if (dsc->bcdDevice == 1) /* Revision 1 is what we're interested in */
return 1;
}
if (dsc->idProduct == 0x1000) {
if (dsc->bcdDevice == 0x0033) /* Looking for revision 0.33 */
return 1;
}
return 0;
}
static const struct usb_id id_table[] = {
{ .vendor = 0x147e, .product = 0x2016 },
{ .vendor = 0x147e, .product = 0x2016, .driver_data = UPEKSONLY_2016 },
{ .vendor = 0x147e, .product = 0x1000, .driver_data = UPEKSONLY_1000 },
{ 0, 0, 0, },
};

View File

@@ -23,7 +23,8 @@
#include <string.h>
#include <unistd.h>
#include <openssl/aes.h>
#include <nss.h>
#include <pk11pub.h>
#include <libusb.h>
#include <fp_internal.h>
@@ -92,7 +93,7 @@ static const struct uru4k_dev_profile {
},
[MS_STANDALONE_V2] = {
.name = "Microsoft Fingerprint Reader v2",
.auth_cr = TRUE,
.auth_cr = TRUE,
},
[DP_URU4000] = {
.name = "Digital Persona U.are.U 4000",
@@ -144,7 +145,10 @@ struct uru4k_dev {
int fwfixer_offset;
unsigned char fwfixer_value;
AES_KEY aeskey;
CK_MECHANISM_TYPE cipher;
PK11SlotInfo *slot;
PK11SymKey *symkey;
SECItem *param;
};
/* For 2nd generation MS devices */
@@ -326,8 +330,10 @@ static void challenge_cb(struct fp_img_dev *dev, int status,
struct fpi_ssm *ssm = user_data;
struct uru4k_dev *urudev = dev->priv;
unsigned char *respdata;
int r;
PK11Context *ctx;
int r, outlen;
r = status;
if (status != 0) {
fpi_ssm_mark_aborted(ssm, status);
return;
@@ -335,12 +341,21 @@ static void challenge_cb(struct fp_img_dev *dev, int status,
/* submit response */
/* produce response from challenge */
/* FIXME would this work in-place? */
respdata = g_malloc(CR_LENGTH);
AES_encrypt(data, respdata, &urudev->aeskey);
r = write_regs(dev, REG_RESPONSE, CR_LENGTH, respdata, response_cb, ssm);
g_free(respdata);
ctx = PK11_CreateContextBySymKey(urudev->cipher, CKA_ENCRYPT,
urudev->symkey, urudev->param);
if (PK11_CipherOp(ctx, respdata, &outlen, CR_LENGTH, data, CR_LENGTH) != SECSuccess
|| PK11_Finalize(ctx) != SECSuccess) {
fp_err("Failed to encrypt challenge data");
r = -ECONNABORTED;
g_free(respdata);
}
PK11_DestroyContext(ctx, PR_TRUE);
if (r >= 0) {
r = write_regs(dev, REG_RESPONSE, CR_LENGTH, respdata, response_cb, ssm);
g_free(respdata);
}
if (r < 0)
fpi_ssm_mark_aborted(ssm, r);
}
@@ -1111,6 +1126,8 @@ static int dev_init(struct fp_img_dev *dev, unsigned long driver_data)
const struct libusb_interface_descriptor *iface_desc;
const struct libusb_endpoint_descriptor *ep;
struct uru4k_dev *urudev;
SECStatus rv;
SECItem item;
int i;
int r;
@@ -1175,10 +1192,40 @@ static int dev_init(struct fp_img_dev *dev, unsigned long driver_data)
goto out;
}
/* Initialise NSS early */
rv = NSS_NoDB_Init(".");
if (rv != SECSuccess) {
fp_err("could not initialise NSS");
goto out;
}
urudev = g_malloc0(sizeof(*urudev));
urudev->profile = &uru4k_dev_info[driver_data];
urudev->interface = iface_desc->bInterfaceNumber;
AES_set_encrypt_key(crkey, 128, &urudev->aeskey);
/* Set up encryption */
urudev->cipher = CKM_AES_ECB;
urudev->slot = PK11_GetBestSlot(urudev->cipher, NULL);
if (urudev->slot == NULL) {
fp_err("could not get encryption slot");
goto out;
}
item.type = siBuffer;
item.data = (unsigned char*) crkey;
item.len = sizeof(crkey);
urudev->symkey = PK11_ImportSymKey(urudev->slot,
urudev->cipher,
PK11_OriginUnwrap,
CKA_ENCRYPT,
&item, NULL);
if (urudev->symkey == NULL) {
fp_err("failed to import key into NSS");
PK11_FreeSlot(urudev->slot);
urudev->slot = NULL;
goto out;
}
urudev->param = PK11_ParamFromIV(urudev->cipher, NULL);
dev->priv = urudev;
fpi_imgdev_open_complete(dev, 0);
@@ -1190,6 +1237,12 @@ out:
static void dev_deinit(struct fp_img_dev *dev)
{
struct uru4k_dev *urudev = dev->priv;
if (urudev->symkey)
PK11_FreeSymKey (urudev->symkey);
if (urudev->param)
SECITEM_FreeItem(urudev->param, PR_TRUE);
if (urudev->slot)
PK11_FreeSlot(urudev->slot);
libusb_release_interface(dev->udev, urudev->interface);
g_free(urudev);
fpi_imgdev_close_complete(dev);

1570
libfprint/drivers/vfs101.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -265,6 +265,9 @@ extern struct fp_img_driver fdu2000_driver;
#ifdef ENABLE_VCOM5S
extern struct fp_img_driver vcom5s_driver;
#endif
#ifdef ENABLE_VFS101
extern struct fp_img_driver vfs101_driver;
#endif
extern libusb_context *fpi_usb_ctx;
extern GSList *opened_devices;

View File

@@ -1,81 +0,0 @@
/*
* Helper binary for creating a HAL FDI file for supported devices
* Copyright (C) 2008 Bastien Nocera <hadess@hadess.net>
* Copyright (C) 2008 Timo Hoenig <thoenig@suse.de>, <thoenig@nouse.net>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <config.h>
#include <stdio.h>
#include "fp_internal.h"
/* FDI entry example:
*
* <!-- AuthenTec AES2501 -->
* <match key="usb.vendor_id" int="0x08ff">
* <match key="usb.product_id" int="0x2580">
* <merge key="info.category" type="string">biometric.fingerprint_reader</merge>
* <append key="biometric.fingerprint_reader.access_method" type="strlist">libfprint</append>
* <append key="info.capabilities" type="strlist">biometric</append>
* <append key="info.capabilities" type="strlist">biometric.fingerprint_reader</append>
* <merge key="biometric.fingerprint_reader.libfprint.driver" type="string">aes2501</merge>
* <merge key="biometric.fingerprint_reader.libfprint.support" type="bool">true</merge>
* </match>
* </match>
*
*/
static void print_driver (struct fp_driver *driver)
{
int i;
for (i = 0; driver->id_table[i].vendor != 0; i++) {
printf (" <!-- %s -->\n", fp_driver_get_full_name (driver));
printf (" <match key=\"usb.vendor_id\" int=\"0x%04x\">\n", driver->id_table[i].vendor);
printf (" <match key=\"usb.product_id\" int=\"0x%04x\">\n", driver->id_table[i].product);
printf (" <merge key=\"info.category\" type=\"string\">biometric.fingerprint_reader</merge>\n");
printf (" <append key=\"biometric.fingerprint_reader.access_method\" type=\"strlist\">libfprint</append>\n");
printf (" <append key=\"info.capabilities\" type=\"strlist\">biometric</append>\n");
printf (" <append key=\"info.capabilities\" type=\"strlist\">biometric.fingerprint_reader</append>\n");
printf (" <merge key=\"biometric.fingerprint_reader.libfprint.driver\" type=\"string\">%s</merge>\n", driver->name);
printf (" <merge key=\"biometric.fingerprint_reader.libfprint.support\" type=\"bool\">true</merge>\n");
printf (" <append key=\"biometric.fingerprint_reader.scan_type\" type=\"string\">%s</append>\n",
fp_driver_get_scan_type (driver) == FP_SCAN_TYPE_PRESS ? "press" : "swipe");
printf (" </match>\n");
printf (" </match>\n");
}
}
int main (int argc, char **argv)
{
struct fp_driver **list;
guint i;
list = fprint_get_drivers ();
printf ("<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n");
printf ("<!-- Created from libfprint %s -->\n", VERSION);
printf ("<deviceinfo version=\"0.2\">\n");
for (i = 0; list[i] != NULL; i++) {
print_driver (list[i]);
}
printf ("</deviceinfo>\n");
return 0;
}

View File

@@ -20,6 +20,10 @@
#ifndef __FPRINT_H__
#define __FPRINT_H__
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#include <sys/time.h>
@@ -336,5 +340,9 @@ typedef void (*fp_identify_stop_cb)(struct fp_dev *dev, void *user_data);
int fp_async_identify_stop(struct fp_dev *dev, fp_identify_stop_cb callback,
void *user_data);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -75,7 +75,7 @@ struct fp_img *fpi_im_resize(struct fp_img *img, unsigned int factor)
for (x = 0; x < newimg->width; x++) {
guchar *p, *r;
r = img->data + y * img->width + x;
r = newimg->data + y * newimg->width + x;
p = pixels + y * rowstride + x * 3;
r[0] = p[0];
}

View File

@@ -228,8 +228,12 @@ void fpi_imgdev_image_captured(struct fp_img_dev *imgdev, struct fp_img *img)
fp_img_standardize(img);
imgdev->acquire_img = img;
fpi_img_to_print_data(imgdev, img, &print);
if (img->minutiae->num < MIN_ACCEPTABLE_MINUTIAE) {
r = fpi_img_to_print_data(imgdev, img, &print);
if (r < 0) {
fp_dbg("image to print data conversion error: %d", r);
imgdev->action_result = FP_ENROLL_RETRY;
goto next_state;
} else if (img->minutiae->num < MIN_ACCEPTABLE_MINUTIAE) {
fp_dbg("not enough minutiae, %d/%d", img->minutiae->num,
MIN_ACCEPTABLE_MINUTIAE);
fp_print_data_free(print);

View File

@@ -270,6 +270,14 @@ API_EXPORTED int fp_get_next_timeout(struct timeval *tv)
if (r_fprint == 0 && r_libusb == 0)
return 0;
/* if fprint have no pending timeouts return libusb timeout */
else if (r_fprint == 0)
*tv = libusb_timeout;
/* if libusb have no pending timeouts return fprint timeout */
else if (r_libusb == 0)
*tv = fprint_timeout;
/* otherwise return the smaller of the 2 timeouts */
else if (timercmp(&fprint_timeout, &libusb_timeout, <))
*tv = fprint_timeout;