mirror of
https://gitlab.freedesktop.org/libfprint/libfprint.git
synced 2025-11-15 07:38:12 +00:00
Compare commits
136 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d82847a6b4 | ||
|
|
5a7e6e07ff | ||
|
|
2162aa9f48 | ||
|
|
a1f36c71c9 | ||
|
|
e4eedef27e | ||
|
|
5e29695969 | ||
|
|
49a46668ad | ||
|
|
76269decdd | ||
|
|
8454a25ecf | ||
|
|
a0bbbd7d32 | ||
|
|
12f6dae8cd | ||
|
|
9570c36fd4 | ||
|
|
487dae0d2f | ||
|
|
d71018bd8f | ||
|
|
61fa57b05d | ||
|
|
fc1781e317 | ||
|
|
ffef6c2bcc | ||
|
|
67d29f7936 | ||
|
|
9437c98d54 | ||
|
|
f7d00a828d | ||
|
|
0f0a4b2da6 | ||
|
|
c9cdbaf880 | ||
|
|
83f29dad9f | ||
|
|
c2a11c5918 | ||
|
|
3746b2ad5c | ||
|
|
b51fa446e3 | ||
|
|
6fc5293e83 | ||
|
|
aab3daa28b | ||
|
|
e40f7bd1f7 | ||
|
|
6664f87d8f | ||
|
|
6e8d5cd6a1 | ||
|
|
9f7e1ecf40 | ||
|
|
d9567002e4 | ||
|
|
a656a4a9f3 | ||
|
|
2944a35e74 | ||
|
|
391373fb0c | ||
|
|
985e8c4577 | ||
|
|
bd0d4258e4 | ||
|
|
9bbd9b208a | ||
|
|
59fe0fb699 | ||
|
|
f1fdd71613 | ||
|
|
bb66780cb5 | ||
|
|
45fb6d7908 | ||
|
|
9f408bf51b | ||
|
|
ee32166267 | ||
|
|
a3c90f2b24 | ||
|
|
dc537ef2c9 | ||
|
|
061a457658 | ||
|
|
82ae7c1c09 | ||
|
|
79d79c3c87 | ||
|
|
35e356f625 | ||
|
|
948ab02d1a | ||
|
|
a6101026d2 | ||
|
|
e0966cb20f | ||
|
|
e278e8321c | ||
|
|
e1728e7c25 | ||
|
|
e215b05094 | ||
|
|
fe3fdd1f50 | ||
|
|
5ff45658c0 | ||
|
|
d12b294783 | ||
|
|
2bba4fb073 | ||
|
|
aeca32fc12 | ||
|
|
12c1088777 | ||
|
|
9e2f8b5e75 | ||
|
|
c14ebd8b63 | ||
|
|
a6339a30ef | ||
|
|
f3dd55815e | ||
|
|
6d65bfcf80 | ||
|
|
1acd647b29 | ||
|
|
0e843ad6b3 | ||
|
|
7eafca7bab | ||
|
|
3b3679c900 | ||
|
|
43eca622cd | ||
|
|
02509e1073 | ||
|
|
0b2d33c712 | ||
|
|
7751fcb375 | ||
|
|
8a87ba448c | ||
|
|
7e1646c382 | ||
|
|
a5ec0b30e1 | ||
|
|
29cf86a02e | ||
|
|
7892c943e6 | ||
|
|
a7d6b7c30a | ||
|
|
258ac2d4da | ||
|
|
31cf7a9383 | ||
|
|
f335256cbe | ||
|
|
c02cb3083d | ||
|
|
2084724115 | ||
|
|
59925d2027 | ||
|
|
118c610e29 | ||
|
|
313bfede77 | ||
|
|
c1da647aed | ||
|
|
22d204cc68 | ||
|
|
bc497f1b26 | ||
|
|
8c5f2e6434 | ||
|
|
5b20892dd4 | ||
|
|
b2a53a459c | ||
|
|
45ac0eefb0 | ||
|
|
ea6d5ba6d6 | ||
|
|
ed2c75842a | ||
|
|
b307dd1a6a | ||
|
|
39902374ce | ||
|
|
9e92d4cf2c | ||
|
|
6b84c6664f | ||
|
|
f569d0bf44 | ||
|
|
1cfd14b7fe | ||
|
|
5d32102efe | ||
|
|
9e10edd422 | ||
|
|
fecf6d6fe5 | ||
|
|
e32fa8cc38 | ||
|
|
d8aae30a67 | ||
|
|
84b97ea15b | ||
|
|
8f98743857 | ||
|
|
be29f27e25 | ||
|
|
d003f08855 | ||
|
|
0f7ad00fc4 | ||
|
|
83333bce3f | ||
|
|
132b178304 | ||
|
|
c3689665db | ||
|
|
3d222ddda7 | ||
|
|
080c414ce9 | ||
|
|
ff02115b0f | ||
|
|
3b409c767c | ||
|
|
d05c69698c | ||
|
|
2d09b10a27 | ||
|
|
bc03d56186 | ||
|
|
96e7224a23 | ||
|
|
0f4a75ff61 | ||
|
|
dfff16f3e3 | ||
|
|
3d2e545264 | ||
|
|
c96fa32da4 | ||
|
|
48ec64f683 | ||
|
|
f8aa82a554 | ||
|
|
1451a2dde2 | ||
|
|
d2e957683f | ||
|
|
a3ae96c214 | ||
|
|
3dd905d4e9 |
3
AUTHORS
3
AUTHORS
@@ -4,7 +4,8 @@ Copyright (C) 2006 Pavel Machek <pavel@suse.cz>
|
||||
Copyright (C) 1999 Erik Walthinsen <omega@cse.ogi.edu>
|
||||
Copyright (C) 2004,2006 Thomas Vander Stichele <thomas at apestaart dot org>
|
||||
Copyright (C) 2007 Cyrille Bagard
|
||||
Copyright (C) 2007 Vasily Khoruzhick
|
||||
Copyright (C) 2007-2008,2012 Vasily Khoruzhick <anarsoul@gmail.com>
|
||||
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>
|
||||
Copyright (C) 2012 Timo Teräs <timo.teras@iki.fi>
|
||||
|
||||
6
HACKING
6
HACKING
@@ -85,11 +85,11 @@ be reflected by updating the appropriate doxygen comments.
|
||||
Contributing
|
||||
============
|
||||
|
||||
Patches should be sent to the fprint mailing list detailed on the website.
|
||||
A subscription is required.
|
||||
Patches should be sent to the fprint bugzilla:
|
||||
https://bugs.freedesktop.org/enter_bug.cgi?product=libfprint
|
||||
|
||||
Information about libfprint development repositories can be found here:
|
||||
http://www.reactivated.net/fprint/Libfprint_development
|
||||
http://www.freedesktop.org/wiki/Software/fprint/libfprint
|
||||
|
||||
If you're looking for ideas for things to work on, look at the TODO file or
|
||||
grep the source code for FIXMEs.
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
AUTOMAKE_OPTIONS = dist-bzip2
|
||||
ACLOCAL_AMFLAGS = -I m4
|
||||
EXTRA_DIST = THANKS TODO HACKING libfprint.pc.in
|
||||
DISTCLEANFILES = ChangeLog libfprint.pc
|
||||
@@ -9,6 +8,10 @@ if BUILD_EXAMPLES
|
||||
SUBDIRS += examples
|
||||
endif
|
||||
|
||||
DIST_SUBDIRS = libfprint doc examples
|
||||
|
||||
DISTCHECK_CONFIGURE_FLAGS = --with-drivers=all --enable-examples-build --enable-x11-examples-build --with-udev-rules-dir='$${libdir}/udev/rules.d-distcheck'
|
||||
|
||||
pkgconfigdir=$(libdir)/pkgconfig
|
||||
pkgconfig_DATA=libfprint.pc
|
||||
|
||||
|
||||
83
NEWS
83
NEWS
@@ -1,6 +1,89 @@
|
||||
This file lists notable changes in each release. For the full history of all
|
||||
changes, see ChangeLog.
|
||||
|
||||
2017-05-14: v0.7.0 release
|
||||
* Drivers:
|
||||
- Add VFS0050 driver
|
||||
- Fix possible crash in AES3500 and AES4000
|
||||
- Fix broken enrollment in VFS101
|
||||
- Better verification with small sensor scanners
|
||||
- Plenty of fixes in VFS5011
|
||||
- Fix memory corruption in AES1610
|
||||
- Improve calibration settings for AES1610
|
||||
- Improve image assembling in upeksonly driver
|
||||
- Autodetect whether image is encrypted in uru4k
|
||||
|
||||
* Library:
|
||||
- NBIS: Remove false minutia at the edge of partial image
|
||||
- Introduce routines to assemble image from lines (used in VFS5011 and upeksonly)
|
||||
- Fix a bug that can cause driver state machine to enter into endless loop.
|
||||
|
||||
* Udev rules:
|
||||
- Add driver name to the USB properties
|
||||
|
||||
* Plenty of build fixes
|
||||
|
||||
2015-02-03: v0.6.0 release
|
||||
|
||||
* Drivers:
|
||||
- Reduce duplication between AES3500 and AES4000 drivers and
|
||||
add support for AES3500 device
|
||||
- Add support for UPEK 147e:2020 and Upek Eikon 2 devices
|
||||
- Add EgisTec ES603 driver
|
||||
- Add VFS5011 driver
|
||||
- Always perform 5 scans for image enrollment
|
||||
- Better verification with AES1660 driver
|
||||
- Better verification for a number of AES drivers
|
||||
|
||||
* Library:
|
||||
- Always use Pixman for image manipulation, gdk-pixbuf and ImageMagick
|
||||
are not supported any more.
|
||||
|
||||
* Udev rules:
|
||||
- Fix warning when USB hub or system does not support power management
|
||||
|
||||
2013-08-11: v0.5.1 release
|
||||
|
||||
* Drivers
|
||||
- Add support for 147e:2020 to upeke2 driver
|
||||
- Fix possible race condition, and cancellation in uru4000 driver
|
||||
|
||||
* Udev rules:
|
||||
- Add Microsoft keyboard to the suspend blacklist
|
||||
|
||||
* Plenty of build fixes
|
||||
|
||||
2012-12-03: v0.5.0 release
|
||||
|
||||
* Drivers:
|
||||
- New VFS300/VFS301 driver
|
||||
- New AES2550/AES2810 drivers
|
||||
- New AES1660 driver
|
||||
- New AES2660 driver
|
||||
- New DigitalPersona URU4500 driver
|
||||
- Avoid empty capture and improve image contrast in the
|
||||
AES2501 and AES2550 drivers
|
||||
- Update upektc driver, add support for Eikon Touch 300
|
||||
- Fix UrU4000 image capture on ARM
|
||||
|
||||
* Library:
|
||||
- Fix global variable collisions with libusb and other system headers
|
||||
- Fix possible crash in NBIS image processing with some fingerprints
|
||||
|
||||
* Udev rules:
|
||||
- Fix power control path for newer kernels
|
||||
- Move udev rules to the correct directory
|
||||
- Don't print duplicated udev rules
|
||||
- Include udev rules in the tarball
|
||||
- Allow disabling of udev rules for cross-compiling
|
||||
- Add driver names in the generated rules
|
||||
|
||||
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
|
||||
|
||||
1
THANKS
1
THANKS
@@ -8,3 +8,4 @@ Toby Howard (University of Manchester)
|
||||
Seemant Kulleen
|
||||
Pavel Herrman
|
||||
Bastien Nocera
|
||||
Greg Kerr and Martin Konecny from AuthenTec Inc - hardware donations (AES2550 device), datasheets for AES2550 and AES2810
|
||||
|
||||
14
autogen.sh
14
autogen.sh
@@ -1,8 +1,20 @@
|
||||
#!/bin/sh
|
||||
|
||||
srcdir=`dirname $0`
|
||||
test -z "$srcdir" && srcdir=.
|
||||
|
||||
olddir="`pwd`"
|
||||
|
||||
cd "$srcdir"
|
||||
|
||||
libtoolize --copy --force || exit 1
|
||||
aclocal || exit 1
|
||||
autoheader || exit 1
|
||||
autoconf || exit 1
|
||||
automake -a -c || exit 1
|
||||
./configure --enable-maintainer-mode --enable-examples-build \
|
||||
cd "$olddir"
|
||||
|
||||
if test -z "$NOCONFIGURE"; then
|
||||
$srcdir/configure --enable-maintainer-mode --enable-examples-build \
|
||||
--enable-x11-examples-build --enable-debug-log $*
|
||||
fi
|
||||
|
||||
220
configure.ac
220
configure.ac
@@ -1,8 +1,11 @@
|
||||
AC_INIT([libfprint], [0.3.0])
|
||||
AM_INIT_AUTOMAKE([1.11 dist-bzip2 no-dist-gzip check-news])
|
||||
AC_INIT([libfprint], [0.7.0])
|
||||
AM_INIT_AUTOMAKE([1.11 no-dist-gzip dist-xz check-news subdir-objects])
|
||||
AC_CONFIG_MACRO_DIR([m4])
|
||||
AC_CONFIG_SRCDIR([libfprint/core.c])
|
||||
AM_CONFIG_HEADER([config.h])
|
||||
AC_CONFIG_HEADERS([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
|
||||
@@ -20,10 +23,12 @@ 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="upekts upektc upeksonly vcom5s uru4000 fdu2000 aes1610 aes1660 aes2501 aes2550 aes2660 aes3500 aes4000 vfs101 vfs301 vfs5011 upektc_img etes603 vfs0050"
|
||||
|
||||
require_imaging='no'
|
||||
require_aeslib='no'
|
||||
require_aesX660='no'
|
||||
require_aes3k='no'
|
||||
enable_upeke2='no'
|
||||
enable_upekts='no'
|
||||
enable_upektc='no'
|
||||
@@ -32,14 +37,28 @@ enable_vcom5s='no'
|
||||
enable_uru4000='no'
|
||||
enable_fdu2000='no'
|
||||
enable_aes1610='no'
|
||||
enable_aes1660='no'
|
||||
enable_aes2501='no'
|
||||
enable_aes2550='no'
|
||||
enable_aes2660='no'
|
||||
enable_aes3500='no'
|
||||
enable_aes4000='no'
|
||||
enable_vfs101='no'
|
||||
enable_vfs301='no'
|
||||
enable_vfs5011='no'
|
||||
enable_upektc_img='no'
|
||||
enable_etes603='no'
|
||||
enable_vfs0050='no'
|
||||
|
||||
AC_ARG_WITH([drivers],[AS_HELP_STRING([--with-drivers],
|
||||
[List of drivers to enable])],
|
||||
[drivers="$withval"],
|
||||
[drivers="$all_drivers"])
|
||||
|
||||
if test "x$drivers" = "xall" ; then
|
||||
drivers=$all_drivers
|
||||
fi
|
||||
|
||||
for driver in `echo ${drivers} | sed -e 's/,/ /g' -e 's/,$//g'`; do
|
||||
case ${driver} in
|
||||
upekts)
|
||||
@@ -52,8 +71,7 @@ for driver in `echo ${drivers} | sed -e 's/,/ /g' -e 's/,$//g'`; do
|
||||
;;
|
||||
upektc)
|
||||
AC_DEFINE([ENABLE_UPEKTC], [], [Build UPEK TouchChip driver])
|
||||
enable_upektc="no"
|
||||
# Driver not ported
|
||||
enable_upektc="yes"
|
||||
;;
|
||||
upeksonly)
|
||||
AC_DEFINE([ENABLE_UPEKSONLY], [], [Build UPEK TouchStrip sensor-only driver])
|
||||
@@ -77,31 +95,92 @@ for driver in `echo ${drivers} | sed -e 's/,/ /g' -e 's/,$//g'`; do
|
||||
require_aeslib="yes"
|
||||
enable_aes2501="yes"
|
||||
;;
|
||||
aes2550)
|
||||
AC_DEFINE([ENABLE_AES2550], [], [Build AuthenTec AES2550/AES2810 driver])
|
||||
require_aeslib="yes"
|
||||
enable_aes2550="yes"
|
||||
;;
|
||||
aes1610)
|
||||
AC_DEFINE([ENABLE_AES1610], [], [Build AuthenTec AES1610 driver])
|
||||
require_aeslib="yes"
|
||||
enable_aes1610="yes"
|
||||
;;
|
||||
aes1660)
|
||||
AC_DEFINE([ENABLE_AES1660], [], [Build AuthenTec AES1660 driver])
|
||||
require_aeslib="yes"
|
||||
require_aesX660="yes"
|
||||
enable_aes1660="yes"
|
||||
;;
|
||||
aes2660)
|
||||
AC_DEFINE([ENABLE_AES2660], [], [Build AuthenTec AES1660 driver])
|
||||
require_aeslib="yes"
|
||||
require_aesX660="yes"
|
||||
enable_aes2660="yes"
|
||||
;;
|
||||
aes3500)
|
||||
AC_DEFINE([ENABLE_AES3500], [], [Build AuthenTec AES3500 driver])
|
||||
require_aeslib="yes"
|
||||
require_imaging="yes"
|
||||
require_aes3k="yes"
|
||||
enable_aes3500="yes"
|
||||
;;
|
||||
aes4000)
|
||||
AC_DEFINE([ENABLE_AES4000], [], [Build AuthenTec AES4000 driver])
|
||||
require_aeslib="yes"
|
||||
require_imaging="yes"
|
||||
require_aes3k="yes"
|
||||
enable_aes4000="yes"
|
||||
;;
|
||||
vfs101)
|
||||
AC_DEFINE([ENABLE_VFS101], [], [Build Validity VFS101 driver])
|
||||
enable_vfs101="yes"
|
||||
;;
|
||||
vfs301)
|
||||
AC_DEFINE([ENABLE_VFS301], [], [Build Validity VFS301/VFS300 driver])
|
||||
enable_vfs301="yes"
|
||||
;;
|
||||
vfs5011)
|
||||
AC_DEFINE([ENABLE_VFS5011], [], [Build Validity VFS5011 driver])
|
||||
enable_vfs5011="yes"
|
||||
;;
|
||||
upektc_img)
|
||||
AC_DEFINE([ENABLE_UPEKTC_IMG], [], [Build Upek TouchChip Fingerprint Coprocessor driver])
|
||||
enable_upektc_img="yes"
|
||||
;;
|
||||
etes603)
|
||||
AC_DEFINE([ENABLE_ETES603], [], [Build EgisTec ES603 driver])
|
||||
enable_etes603="yes"
|
||||
;;
|
||||
vfs0050)
|
||||
AC_DEFINE([ENABLE_VFS0050], [], [Build Validity VFS0050 driver])
|
||||
enable_vfs0050="yes"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
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_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_AES1660], [test "$enable_aes1660" = "yes"])
|
||||
AM_CONDITIONAL([ENABLE_AES2501], [test "$enable_aes2501" = "yes"])
|
||||
AM_CONDITIONAL([ENABLE_AES2550], [test "$enable_aes2550" = "yes"])
|
||||
AM_CONDITIONAL([ENABLE_AES2660], [test "$enable_aes2660" = "yes"])
|
||||
AM_CONDITIONAL([ENABLE_AES3500], [test "$enable_aes3500" = "yes"])
|
||||
AM_CONDITIONAL([ENABLE_AES4000], [test "$enable_aes4000" = "yes"])
|
||||
AM_CONDITIONAL([REQUIRE_AESLIB], [test "$require_aeslib" = "yes"])
|
||||
AM_CONDITIONAL([REQUIRE_AESX660], [test "$require_aesX660" = "yes"])
|
||||
AM_CONDITIONAL([REQUIRE_AES3K], [test "$require_aes3k" = "yes"])
|
||||
AM_CONDITIONAL([ENABLE_VFS101], [test "$enable_vfs101" = "yes"])
|
||||
AM_CONDITIONAL([ENABLE_VFS301], [test "$enable_vfs301" = "yes"])
|
||||
AM_CONDITIONAL([ENABLE_VFS5011], [test "$enable_vfs5011" = "yes"])
|
||||
AM_CONDITIONAL([ENABLE_UPEKTC_IMG], [test "$enable_upektc_img" = "yes"])
|
||||
AM_CONDITIONAL([ENABLE_ETES603], [test "$enable_etes603" = "yes"])
|
||||
AM_CONDITIONAL([ENABLE_VFS0050], [test "$enable_vfs0050" = "yes"])
|
||||
|
||||
|
||||
PKG_CHECK_MODULES(LIBUSB, [libusb-1.0 >= 0.9.1])
|
||||
@@ -113,28 +192,45 @@ PKG_CHECK_MODULES(CRYPTO, nss)
|
||||
AC_SUBST(CRYPTO_CFLAGS)
|
||||
AC_SUBST(CRYPTO_LIBS)
|
||||
|
||||
PKG_CHECK_MODULES(GLIB, "glib-2.0")
|
||||
PKG_CHECK_MODULES(GLIB, [glib-2.0 >= 2.28])
|
||||
AC_SUBST(GLIB_CFLAGS)
|
||||
AC_SUBST(GLIB_LIBS)
|
||||
|
||||
imagemagick_found=no
|
||||
gdkpixbuf_found=no
|
||||
pixman_found=no
|
||||
|
||||
AC_ARG_ENABLE(udev-rules,
|
||||
AC_HELP_STRING([--enable-udev-rules],[Update the udev rules]),
|
||||
[case "${enableval}" in
|
||||
yes) ENABLE_UDEV_RULES=yes ;;
|
||||
no) ENABLE_UDEV_RULES=no ;;
|
||||
*) AC_MSG_ERROR(bad value ${enableval} for --enable-udev-rules) ;;
|
||||
esac],
|
||||
[ENABLE_UDEV_RULES=yes]) dnl Default value
|
||||
AM_CONDITIONAL(ENABLE_UDEV_RULES, test x$ENABLE_UDEV_RULES = "xyes")
|
||||
|
||||
if test $ENABLE_UDEV_RULES = no && test -d .git/ ; then
|
||||
AC_MSG_ERROR(--disable-udev-rules can only be used when building from tarballs)
|
||||
fi
|
||||
|
||||
AC_ARG_WITH(udev-rules-dir,
|
||||
AS_HELP_STRING([--with-udev-rules-dir=DIR],[Installation path for udev rules @<:@auto@:>@]),
|
||||
[ac_with_udev_rules_dir=$withval],
|
||||
[ac_with_udev_rules_dir=""])
|
||||
|
||||
if test "${ac_with_udev_rules_dir}" = ""; then
|
||||
ac_with_udev_rules_dir=`$PKG_CONFIG --variable=udevdir udev`/rules.d
|
||||
fi
|
||||
AC_MSG_NOTICE([installing udev rules in ${ac_with_udev_rules_dir}])
|
||||
AC_SUBST([udev_rulesdir],[${ac_with_udev_rules_dir}])
|
||||
|
||||
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])
|
||||
PKG_CHECK_MODULES(IMAGING, pixman-1, [pixman_found=yes], [pixman_found=no])
|
||||
if test "$pixman_found" != "yes"; then
|
||||
AC_MSG_ERROR([pixman is required for imaging support])
|
||||
fi
|
||||
fi
|
||||
|
||||
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" = "yes"])
|
||||
AM_CONDITIONAL([REQUIRE_IMAGEMAGICK], [test "$imagemagick_found" = "yes"])
|
||||
AM_CONDITIONAL([REQUIRE_PIXMAN], [test "$pixman_found" = "yes"])
|
||||
AC_SUBST(IMAGING_CFLAGS)
|
||||
AC_SUBST(IMAGING_LIBS)
|
||||
|
||||
@@ -162,17 +258,17 @@ if test "x$build_x11_examples" != "xno"; then
|
||||
AC_MSG_CHECKING(for Xv extensions)
|
||||
AC_TRY_COMPILE([
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/extensions/Xvlib.h>],[
|
||||
#include <X11/extensions/Xvlib.h>],[
|
||||
int main(void) { (void) XvGetPortAttribute(0, 0, 0, 0); return 0; }
|
||||
],xv=yes,xv=no);
|
||||
AC_MSG_RESULT($xv)
|
||||
if test x$xv = xyes; then
|
||||
XV_LIBS="-lXv -lXext"
|
||||
XV_CFLAGS=""
|
||||
if test x$xv = xyes; then
|
||||
XV_LIBS="-lXv -lXext"
|
||||
XV_CFLAGS=""
|
||||
AC_DEFINE(HAVE_XV,1,[defined if XV video overlay is available])
|
||||
else
|
||||
AC_MSG_ERROR([XV is required for X11 examples])
|
||||
fi
|
||||
fi
|
||||
])
|
||||
AC_CHECK_XV
|
||||
fi
|
||||
@@ -196,7 +292,7 @@ fi
|
||||
# Restore gnu89 inline semantics on gcc 4.3 and newer
|
||||
saved_cflags="$CFLAGS"
|
||||
CFLAGS="$CFLAGS -fgnu89-inline"
|
||||
AC_COMPILE_IFELSE(AC_LANG_PROGRAM([]), inline_cflags="-fgnu89-inline", inline_cflags="")
|
||||
AC_COMPILE_IFELSE([AC_LANG_SOURCE([[]])], inline_cflags="-fgnu89-inline", inline_cflags="")
|
||||
CFLAGS="$saved_cflags"
|
||||
|
||||
AC_DEFINE([API_EXPORTED], [__attribute__((visibility("default")))], [Default visibility])
|
||||
@@ -204,10 +300,8 @@ AM_CFLAGS="-std=gnu99 $inline_cflags -Wall -Wundef -Wunused -Wstrict-prototypes
|
||||
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])
|
||||
if test x$pixman_found != no; then
|
||||
AC_MSG_NOTICE([** Using pixman for imaging])
|
||||
fi
|
||||
else
|
||||
AC_MSG_NOTICE([ Imaging support disabled])
|
||||
@@ -221,7 +315,7 @@ fi
|
||||
if test x$enable_upeke2 != xno ; then
|
||||
AC_MSG_NOTICE([** upeke2 driver enabled])
|
||||
else
|
||||
AC_MSG_NOTICE([ upeke2 driver disabled])
|
||||
AC_MSG_NOTICE([ upeke2 driver disabled (handled by upektc_img driver)])
|
||||
fi
|
||||
if test x$enable_upektc != xno ; then
|
||||
AC_MSG_NOTICE([** upektc driver enabled])
|
||||
@@ -246,28 +340,88 @@ fi
|
||||
if test x$enable_fdu2000 != xno ; then
|
||||
AC_MSG_NOTICE([** fdu2000 driver enabled])
|
||||
else
|
||||
AC_MSG_NOTICE([ fdu2000 driver disabled])
|
||||
AC_MSG_NOTICE([ fdu2000 driver disabled (not ported)])
|
||||
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_aes1660 != xno ; then
|
||||
AC_MSG_NOTICE([** aes1660 driver enabled])
|
||||
else
|
||||
AC_MSG_NOTICE([ aes1660 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_aes2550 != xno ; then
|
||||
AC_MSG_NOTICE([** aes2550/aes2810 driver enabled])
|
||||
else
|
||||
AC_MSG_NOTICE([ aes2550/aes2810 driver disabled])
|
||||
fi
|
||||
if test x$enable_aes2660 != xno ; then
|
||||
AC_MSG_NOTICE([** aes2660 driver enabled])
|
||||
else
|
||||
AC_MSG_NOTICE([ aes2660 driver disabled])
|
||||
fi
|
||||
if test x$enable_aes3500 != xno ; then
|
||||
AC_MSG_NOTICE([** aes3500 driver enabled])
|
||||
else
|
||||
AC_MSG_NOTICE([ aes3500 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$enable_vfs301 != xno ; then
|
||||
AC_MSG_NOTICE([** vfs301 driver enabled])
|
||||
else
|
||||
AC_MSG_NOTICE([ vfs301 driver disabled])
|
||||
fi
|
||||
if test x$enable_vfs5011 != xno ; then
|
||||
AC_MSG_NOTICE([** vfs5011 driver enabled])
|
||||
else
|
||||
AC_MSG_NOTICE([ vfs5011 driver disabled])
|
||||
fi
|
||||
if test x$enable_upektc_img != xno ; then
|
||||
AC_MSG_NOTICE([** upektc_img driver enabled])
|
||||
else
|
||||
AC_MSG_NOTICE([ upektc_img driver disabled])
|
||||
fi
|
||||
if test x$enable_etes603 != xno ; then
|
||||
AC_MSG_NOTICE([** etes603 driver enabled])
|
||||
else
|
||||
AC_MSG_NOTICE([ etes603 driver disabled])
|
||||
fi
|
||||
if test x$enable_vfs0050 != xno ; then
|
||||
AC_MSG_NOTICE([** vfs0050 driver enabled])
|
||||
else
|
||||
AC_MSG_NOTICE([ vfs0050 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
|
||||
if test x$require_aesX660 != xno ; then
|
||||
AC_MSG_NOTICE([** aesX660 common routines enabled])
|
||||
else
|
||||
AC_MSG_NOTICE([ aesX660 common routines disabled])
|
||||
fi
|
||||
if test x$require_aes3k != xno ; then
|
||||
AC_MSG_NOTICE([** aes3k common routines enabled])
|
||||
else
|
||||
AC_MSG_NOTICE([ aes3k common routines disabled])
|
||||
fi
|
||||
|
||||
AC_CONFIG_FILES([libfprint.pc] [Makefile] [libfprint/Makefile] [examples/Makefile] [doc/Makefile])
|
||||
AC_OUTPUT
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
INCLUDES = -I$(top_srcdir)
|
||||
AM_CFLAGS = -I$(top_srcdir)
|
||||
noinst_PROGRAMS = verify_live enroll verify img_capture cpp-test
|
||||
|
||||
verify_live_SOURCES = verify_live.c
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
#define FORMAT 0x32595559
|
||||
|
||||
static int adaptor = -1;
|
||||
static unsigned char *framebuffer = NULL;
|
||||
static char *framebuffer = NULL;
|
||||
|
||||
static Display *display = NULL;
|
||||
static Window window=(Window)NULL;
|
||||
@@ -50,7 +50,7 @@ static int connection = -1;
|
||||
u = u > 255 ? 255 : u;\
|
||||
v = v > 255 ? 255 : v
|
||||
|
||||
static void grey2yuy2 (unsigned char *grey, unsigned char *YUV, int num) {
|
||||
static void grey2yuy2 (unsigned char *grey, char *YUV, int num) {
|
||||
int i, j;
|
||||
int y0, y1, u0, u1, v0, v1;
|
||||
int gval;
|
||||
@@ -86,7 +86,7 @@ static void display_frame(struct fp_img *img)
|
||||
|
||||
static void QueryXv()
|
||||
{
|
||||
int num_adaptors;
|
||||
unsigned int num_adaptors;
|
||||
int num_formats;
|
||||
XvImageFormatValues *formats = NULL;
|
||||
int i,j;
|
||||
|
||||
@@ -4,14 +4,24 @@ MOSTLYCLEANFILES = $(udev_rules_DATA)
|
||||
|
||||
UPEKE2_SRC = drivers/upeke2.c
|
||||
UPEKTS_SRC = drivers/upekts.c
|
||||
UPEKTC_SRC = drivers/upektc.c
|
||||
UPEKSONLY_SRC = drivers/upeksonly.c
|
||||
UPEKTC_SRC = drivers/upektc.c drivers/upektc.h
|
||||
UPEKSONLY_SRC = drivers/upeksonly.c drivers/upeksonly.h
|
||||
URU4000_SRC = drivers/uru4000.c
|
||||
AES1610_SRC = drivers/aes1610.c
|
||||
AES1660_SRC = drivers/aes1660.c drivers/aes1660.h
|
||||
AES2501_SRC = drivers/aes2501.c drivers/aes2501.h
|
||||
AES2550_SRC = drivers/aes2550.c drivers/aes2550.h
|
||||
AES2660_SRC = drivers/aes2660.c drivers/aes2660.h
|
||||
AES3500_SRC = drivers/aes3500.c
|
||||
AES4000_SRC = drivers/aes4000.c
|
||||
FDU2000_SRC = drivers/fdu2000.c
|
||||
VCOM5S_SRC = drivers/vcom5s.c
|
||||
VFS101_SRC = drivers/vfs101.c
|
||||
VFS301_SRC = drivers/vfs301.c drivers/vfs301_proto.c drivers/vfs301_proto.h drivers/vfs301_proto_fragments.h
|
||||
VFS5011_SRC = drivers/vfs5011.c drivers/vfs5011_proto.h
|
||||
UPEKTC_IMG_SRC = drivers/upektc_img.c drivers/upektc_img.h
|
||||
ETES603_SRC = drivers/etes603.c
|
||||
VFS0050_SRC = drivers/vfs0050.c drivers/vfs0050.h
|
||||
|
||||
EXTRA_DIST = \
|
||||
$(UPEKE2_SRC) \
|
||||
@@ -20,13 +30,30 @@ EXTRA_DIST = \
|
||||
$(UPEKSONLY_SRC) \
|
||||
$(URU4000_SRC) \
|
||||
$(AES1610_SRC) \
|
||||
$(AES1660_SRC) \
|
||||
$(AES2501_SRC) \
|
||||
$(AES2550_SRC) \
|
||||
$(AES2660_SRC) \
|
||||
$(AES3500_SRC) \
|
||||
$(AES4000_SRC) \
|
||||
$(FDU2000_SRC) \
|
||||
$(VCOM5S_SRC) \
|
||||
$(VFS101_SRC) \
|
||||
$(VFS301_SRC) \
|
||||
$(VFS5011_SRC) \
|
||||
$(UPEKTC_IMG_SRC) \
|
||||
$(ETES603_SRC) \
|
||||
$(VFS0050_SRC) \
|
||||
drivers/aesx660.c \
|
||||
drivers/aesx660.h \
|
||||
drivers/aes3k.c \
|
||||
drivers/aes3k.h \
|
||||
drivers/driver_ids.h \
|
||||
aeslib.c aeslib.h \
|
||||
imagemagick.c \
|
||||
gdkpixbuf.c
|
||||
assembling.c \
|
||||
assembling.h \
|
||||
pixman.c \
|
||||
60-fprint-autosuspend.rules
|
||||
|
||||
DRIVER_SRC =
|
||||
OTHER_SRC =
|
||||
@@ -73,14 +100,15 @@ libfprint_la_LDFLAGS = -version-info @lt_major@:@lt_revision@:@lt_age@
|
||||
libfprint_la_LIBADD = -lm $(LIBUSB_LIBS) $(GLIB_LIBS) $(CRYPTO_LIBS)
|
||||
|
||||
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
|
||||
fprint_list_udev_rules_CFLAGS = -fvisibility=hidden -I$(srcdir)/nbis/include $(LIBUSB_CFLAGS) $(GLIB_CFLAGS) $(CRYPTO_CFLAGS) $(AM_CFLAGS)
|
||||
fprint_list_udev_rules_LDADD = $(builddir)/libfprint.la $(GLIB_LIBS)
|
||||
|
||||
udev_rules_DATA = 60-fprint-autosuspend.rules
|
||||
udev_rulesdir = $(sysconfdir)/udev/rules.d/
|
||||
|
||||
if ENABLE_UDEV_RULES
|
||||
$(udev_rules_DATA): fprint-list-udev-rules
|
||||
$(builddir)/fprint-list-udev-rules > $@
|
||||
endif
|
||||
|
||||
if ENABLE_UPEKE2
|
||||
DRIVER_SRC += $(UPEKE2_SRC)
|
||||
@@ -94,9 +122,9 @@ if ENABLE_UPEKSONLY
|
||||
DRIVER_SRC += $(UPEKSONLY_SRC)
|
||||
endif
|
||||
|
||||
#if ENABLE_UPEKTC
|
||||
#DRIVER_SRC += $(UPEKTC_SRC)
|
||||
#endif
|
||||
if ENABLE_UPEKTC
|
||||
DRIVER_SRC += $(UPEKTC_SRC)
|
||||
endif
|
||||
|
||||
if ENABLE_URU4000
|
||||
DRIVER_SRC += $(URU4000_SRC)
|
||||
@@ -114,22 +142,56 @@ if ENABLE_AES1610
|
||||
DRIVER_SRC += $(AES1610_SRC)
|
||||
endif
|
||||
|
||||
if ENABLE_AES1660
|
||||
DRIVER_SRC += $(AES1660_SRC)
|
||||
endif
|
||||
|
||||
if ENABLE_AES2501
|
||||
DRIVER_SRC += $(AES2501_SRC)
|
||||
endif
|
||||
|
||||
if ENABLE_AES2550
|
||||
DRIVER_SRC += $(AES2550_SRC)
|
||||
endif
|
||||
|
||||
if ENABLE_AES2660
|
||||
DRIVER_SRC += $(AES2660_SRC)
|
||||
endif
|
||||
|
||||
if ENABLE_AES3500
|
||||
DRIVER_SRC += $(AES3500_SRC)
|
||||
endif
|
||||
|
||||
if ENABLE_AES4000
|
||||
DRIVER_SRC += $(AES4000_SRC)
|
||||
endif
|
||||
|
||||
if REQUIRE_IMAGEMAGICK
|
||||
OTHER_SRC += imagemagick.c
|
||||
libfprint_la_CFLAGS += $(IMAGING_CFLAGS)
|
||||
libfprint_la_LIBADD += $(IMAGING_LIBS)
|
||||
if ENABLE_VFS101
|
||||
DRIVER_SRC += $(VFS101_SRC)
|
||||
endif
|
||||
|
||||
if REQUIRE_GDKPIXBUF
|
||||
OTHER_SRC += gdkpixbuf.c
|
||||
if ENABLE_VFS301
|
||||
DRIVER_SRC += $(VFS301_SRC)
|
||||
endif
|
||||
|
||||
if ENABLE_VFS5011
|
||||
DRIVER_SRC += $(VFS5011_SRC)
|
||||
endif
|
||||
|
||||
if ENABLE_UPEKTC_IMG
|
||||
DRIVER_SRC += $(UPEKTC_IMG_SRC)
|
||||
endif
|
||||
|
||||
if ENABLE_ETES603
|
||||
DRIVER_SRC += $(ETES603_SRC)
|
||||
endif
|
||||
|
||||
if ENABLE_VFS0050
|
||||
DRIVER_SRC += $(VFS0050_SRC)
|
||||
endif
|
||||
|
||||
if REQUIRE_PIXMAN
|
||||
OTHER_SRC += pixman.c
|
||||
libfprint_la_CFLAGS += $(IMAGING_CFLAGS)
|
||||
libfprint_la_LIBADD += $(IMAGING_LIBS)
|
||||
endif
|
||||
@@ -138,6 +200,14 @@ if REQUIRE_AESLIB
|
||||
OTHER_SRC += aeslib.c aeslib.h
|
||||
endif
|
||||
|
||||
if REQUIRE_AESX660
|
||||
OTHER_SRC += drivers/aesx660.c drivers/aesx660.h
|
||||
endif
|
||||
|
||||
if REQUIRE_AES3K
|
||||
OTHER_SRC += drivers/aes3k.c drivers/aes3k.h
|
||||
endif
|
||||
|
||||
libfprint_la_SOURCES = \
|
||||
fp_internal.h \
|
||||
async.c \
|
||||
@@ -148,6 +218,8 @@ libfprint_la_SOURCES = \
|
||||
imgdev.c \
|
||||
poll.c \
|
||||
sync.c \
|
||||
assembling.c \
|
||||
assembling.h \
|
||||
$(DRIVER_SRC) \
|
||||
$(OTHER_SRC) \
|
||||
$(NBIS_SRC)
|
||||
|
||||
@@ -20,11 +20,13 @@
|
||||
#define FP_COMPONENT "aeslib"
|
||||
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <libusb.h>
|
||||
#include <glib.h>
|
||||
|
||||
#include "fp_internal.h"
|
||||
#include "assembling.h"
|
||||
#include "aeslib.h"
|
||||
|
||||
#define MAX_REGWRITES_PER_REQUEST 16
|
||||
@@ -157,17 +159,16 @@ void aes_write_regv(struct fp_img_dev *dev, const struct aes_regwrite *regs,
|
||||
continue_write_regv(wdata);
|
||||
}
|
||||
|
||||
void aes_assemble_image(unsigned char *input, size_t width, size_t height,
|
||||
unsigned char *output)
|
||||
unsigned char aes_get_pixel(struct fpi_frame_asmbl_ctx *ctx,
|
||||
struct fpi_frame *frame,
|
||||
unsigned int x,
|
||||
unsigned int y)
|
||||
{
|
||||
size_t row, column;
|
||||
unsigned char ret;
|
||||
|
||||
for (column = 0; column < width; column++) {
|
||||
for (row = 0; row < height; row += 2) {
|
||||
output[width * row + column] = (*input & 0x07) * 36;
|
||||
output[width * (row + 1) + column] = ((*input & 0x70) >> 4) * 36;
|
||||
input++;
|
||||
}
|
||||
}
|
||||
ret = frame->data[x * (ctx->frame_height >> 1) + (y >> 1)];
|
||||
ret = y % 2 ? ret >> 4 : ret & 0xf;
|
||||
ret *= 17;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -27,14 +27,19 @@ struct aes_regwrite {
|
||||
unsigned char value;
|
||||
};
|
||||
|
||||
struct fpi_frame;
|
||||
struct fpi_frame_asmbl_ctx;
|
||||
|
||||
typedef void (*aes_write_regv_cb)(struct fp_img_dev *dev, int result,
|
||||
void *user_data);
|
||||
|
||||
void aes_write_regv(struct fp_img_dev *dev, const struct aes_regwrite *regs,
|
||||
unsigned int num_regs, aes_write_regv_cb callback, void *user_data);
|
||||
|
||||
void aes_assemble_image(unsigned char *input, size_t width, size_t height,
|
||||
unsigned char *output);
|
||||
unsigned char aes_get_pixel(struct fpi_frame_asmbl_ctx *ctx,
|
||||
struct fpi_frame *frame,
|
||||
unsigned int x,
|
||||
unsigned int y);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
423
libfprint/assembling.c
Normal file
423
libfprint/assembling.c
Normal file
@@ -0,0 +1,423 @@
|
||||
/*
|
||||
* Image assembling routines
|
||||
* Copyright (C) 2007-2008 Daniel Drake <dsd@gentoo.org>
|
||||
* Copyright (C) 2013 Arseniy Lartsev <arseniy@chalmers.se>
|
||||
* Copyright (C) 2015 Vasily Khoruzhick <anarsoul@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
|
||||
* 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
|
||||
*/
|
||||
|
||||
#define FP_COMPONENT "assembling"
|
||||
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <libusb.h>
|
||||
#include <glib.h>
|
||||
|
||||
#include "fp_internal.h"
|
||||
#include "assembling.h"
|
||||
|
||||
static unsigned int calc_error(struct fpi_frame_asmbl_ctx *ctx,
|
||||
struct fpi_frame *first_frame,
|
||||
struct fpi_frame *second_frame,
|
||||
int dx,
|
||||
int dy)
|
||||
{
|
||||
unsigned int width, height;
|
||||
unsigned int x1, y1, x2, y2, err, i, j;
|
||||
|
||||
width = ctx->frame_width - (dx > 0 ? dx : -dx);
|
||||
height = ctx->frame_height - dy;
|
||||
|
||||
y1 = 0;
|
||||
y2 = dy;
|
||||
i = 0;
|
||||
err = 0;
|
||||
do {
|
||||
x1 = dx < 0 ? 0 : dx;
|
||||
x2 = dx < 0 ? -dx : 0;
|
||||
j = 0;
|
||||
|
||||
do {
|
||||
unsigned char v1, v2;
|
||||
|
||||
|
||||
v1 = ctx->get_pixel(ctx, first_frame, x1, y1);
|
||||
v2 = ctx->get_pixel(ctx, second_frame, x2, y2);
|
||||
err += v1 > v2 ? v1 - v2 : v2 - v1;
|
||||
j++;
|
||||
x1++;
|
||||
x2++;
|
||||
|
||||
} while (j < width);
|
||||
i++;
|
||||
y1++;
|
||||
y2++;
|
||||
} while (i < height);
|
||||
|
||||
/* Normalize error */
|
||||
err *= (ctx->frame_height * ctx->frame_width);
|
||||
err /= (height * width);
|
||||
|
||||
if (err == 0)
|
||||
return INT_MAX;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/* This function is rather CPU-intensive. It's better to use hardware
|
||||
* to detect movement direction when possible.
|
||||
*/
|
||||
static void find_overlap(struct fpi_frame_asmbl_ctx *ctx,
|
||||
struct fpi_frame *first_frame,
|
||||
struct fpi_frame *second_frame,
|
||||
unsigned int *min_error)
|
||||
{
|
||||
int dx, dy;
|
||||
unsigned int err;
|
||||
*min_error = 255 * ctx->frame_height * ctx->frame_width;
|
||||
|
||||
/* Seeking in horizontal and vertical dimensions,
|
||||
* for horizontal dimension we'll check only 8 pixels
|
||||
* in both directions. For vertical direction diff is
|
||||
* rarely less than 2, so start with it.
|
||||
*/
|
||||
for (dy = 2; dy < ctx->frame_height; dy++) {
|
||||
for (dx = -8; dx < 8; dx++) {
|
||||
err = calc_error(ctx, first_frame, second_frame,
|
||||
dx, dy);
|
||||
if (err < *min_error) {
|
||||
*min_error = err;
|
||||
second_frame->delta_x = -dx;
|
||||
second_frame->delta_y = dy;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned int do_movement_estimation(struct fpi_frame_asmbl_ctx *ctx,
|
||||
GSList *stripes, size_t num_stripes,
|
||||
gboolean reverse)
|
||||
{
|
||||
GSList *list_entry = stripes;
|
||||
GTimer *timer;
|
||||
int frame = 1;
|
||||
struct fpi_frame *prev_stripe = list_entry->data;
|
||||
unsigned int min_error;
|
||||
/* Max error is width * height * 255, for AES2501 which has the largest
|
||||
* sensor its 192*16*255 = 783360. So for 32bit value it's ~5482 frame before
|
||||
* we might get int overflow. Use 64bit value here to prevent integer overflow
|
||||
*/
|
||||
unsigned long long total_error = 0;
|
||||
|
||||
list_entry = g_slist_next(list_entry);
|
||||
|
||||
timer = g_timer_new();
|
||||
do {
|
||||
struct fpi_frame *cur_stripe = list_entry->data;
|
||||
|
||||
if (reverse) {
|
||||
find_overlap(ctx, prev_stripe, cur_stripe, &min_error);
|
||||
prev_stripe->delta_y = -prev_stripe->delta_y;
|
||||
prev_stripe->delta_x = -prev_stripe->delta_x;
|
||||
}
|
||||
else
|
||||
find_overlap(ctx, cur_stripe, prev_stripe, &min_error);
|
||||
total_error += min_error;
|
||||
|
||||
frame++;
|
||||
prev_stripe = cur_stripe;
|
||||
list_entry = g_slist_next(list_entry);
|
||||
|
||||
} while (frame < num_stripes);
|
||||
|
||||
g_timer_stop(timer);
|
||||
fp_dbg("calc delta completed in %f secs", g_timer_elapsed(timer, NULL));
|
||||
g_timer_destroy(timer);
|
||||
|
||||
return total_error / num_stripes;
|
||||
}
|
||||
|
||||
void fpi_do_movement_estimation(struct fpi_frame_asmbl_ctx *ctx,
|
||||
GSList *stripes, size_t num_stripes)
|
||||
{
|
||||
int err, rev_err;
|
||||
err = do_movement_estimation(ctx, stripes, num_stripes, FALSE);
|
||||
rev_err = do_movement_estimation(ctx, stripes, num_stripes, TRUE);
|
||||
fp_dbg("errors: %d rev: %d", err, rev_err);
|
||||
if (err < rev_err) {
|
||||
do_movement_estimation(ctx, stripes, num_stripes, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void aes_blit_stripe(struct fpi_frame_asmbl_ctx *ctx,
|
||||
struct fp_img *img,
|
||||
struct fpi_frame *stripe,
|
||||
int x, int y)
|
||||
{
|
||||
unsigned int ix, iy;
|
||||
unsigned int fx, fy;
|
||||
unsigned int width, height;
|
||||
|
||||
/* Find intersection */
|
||||
if (x < 0) {
|
||||
width = ctx->frame_width + x;
|
||||
ix = 0;
|
||||
fx = -x;
|
||||
} else {
|
||||
ix = x;
|
||||
fx = 0;
|
||||
width = ctx->frame_width;
|
||||
}
|
||||
if ((ix + width) > img->width)
|
||||
width = img->width - ix;
|
||||
|
||||
if (y < 0) {
|
||||
iy = 0;
|
||||
fy = -y;
|
||||
height = ctx->frame_height + y;
|
||||
} else {
|
||||
iy = y;
|
||||
fy = 0;
|
||||
height = ctx->frame_height;
|
||||
}
|
||||
|
||||
if (fx > ctx->frame_width)
|
||||
return;
|
||||
|
||||
if (fy > ctx->frame_height)
|
||||
return;
|
||||
|
||||
if (ix > img->width)
|
||||
return;
|
||||
|
||||
if (iy > img->height)
|
||||
return;
|
||||
|
||||
if ((iy + height) > img->height)
|
||||
height = img->height - iy;
|
||||
|
||||
for (; fy < height; fy++, iy++) {
|
||||
if (x < 0) {
|
||||
ix = 0;
|
||||
fx = -x;
|
||||
} else {
|
||||
ix = x;
|
||||
fx = 0;
|
||||
}
|
||||
for (; fx < width; fx++, ix++) {
|
||||
img->data[ix + (iy * img->width)] = ctx->get_pixel(ctx, stripe, fx, fy);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct fp_img *fpi_assemble_frames(struct fpi_frame_asmbl_ctx *ctx,
|
||||
GSList *stripes, size_t stripes_len)
|
||||
{
|
||||
GSList *stripe;
|
||||
struct fp_img *img;
|
||||
int height = 0;
|
||||
int i, y, x;
|
||||
gboolean reverse = FALSE;
|
||||
struct fpi_frame *fpi_frame;
|
||||
|
||||
BUG_ON(stripes_len == 0);
|
||||
BUG_ON(ctx->image_width < ctx->frame_width);
|
||||
|
||||
/* Calculate height */
|
||||
i = 0;
|
||||
stripe = stripes;
|
||||
|
||||
/* No offset for 1st image */
|
||||
fpi_frame = stripe->data;
|
||||
fpi_frame->delta_x = 0;
|
||||
fpi_frame->delta_y = 0;
|
||||
do {
|
||||
fpi_frame = stripe->data;
|
||||
|
||||
height += fpi_frame->delta_y;
|
||||
i++;
|
||||
stripe = g_slist_next(stripe);
|
||||
} while (i < stripes_len);
|
||||
|
||||
fp_dbg("height is %d", height);
|
||||
|
||||
if (height < 0) {
|
||||
reverse = TRUE;
|
||||
height = -height;
|
||||
}
|
||||
|
||||
/* For last frame */
|
||||
height += ctx->frame_height;
|
||||
|
||||
/* Create buffer big enough for max image */
|
||||
img = fpi_img_new(ctx->image_width * height);
|
||||
img->flags = FP_IMG_COLORS_INVERTED;
|
||||
img->flags |= reverse ? 0 : FP_IMG_H_FLIPPED | FP_IMG_V_FLIPPED;
|
||||
img->width = ctx->image_width;
|
||||
img->height = height;
|
||||
|
||||
/* Assemble stripes */
|
||||
i = 0;
|
||||
stripe = stripes;
|
||||
y = reverse ? (height - ctx->frame_height) : 0;
|
||||
x = (ctx->image_width - ctx->frame_width) / 2;
|
||||
|
||||
do {
|
||||
fpi_frame = stripe->data;
|
||||
|
||||
y += fpi_frame->delta_y;
|
||||
x += fpi_frame->delta_x;
|
||||
|
||||
aes_blit_stripe(ctx, img, fpi_frame, x, y);
|
||||
|
||||
stripe = g_slist_next(stripe);
|
||||
i++;
|
||||
} while (i < stripes_len);
|
||||
|
||||
return img;
|
||||
}
|
||||
|
||||
static int cmpint(const void *p1, const void *p2, gpointer data)
|
||||
{
|
||||
int a = *((int *)p1);
|
||||
int b = *((int *)p2);
|
||||
if (a < b)
|
||||
return -1;
|
||||
else if (a == b)
|
||||
return 0;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void median_filter(int *data, int size, int filtersize)
|
||||
{
|
||||
int i;
|
||||
int *result = (int *)g_malloc0(size*sizeof(int));
|
||||
int *sortbuf = (int *)g_malloc0(filtersize*sizeof(int));
|
||||
for (i = 0; i < size; i++) {
|
||||
int i1 = i - (filtersize-1)/2;
|
||||
int i2 = i + (filtersize-1)/2;
|
||||
if (i1 < 0)
|
||||
i1 = 0;
|
||||
if (i2 >= size)
|
||||
i2 = size-1;
|
||||
g_memmove(sortbuf, data+i1, (i2-i1+1)*sizeof(int));
|
||||
g_qsort_with_data(sortbuf, i2-i1+1, sizeof(int), cmpint, NULL);
|
||||
result[i] = sortbuf[(i2-i1+1)/2];
|
||||
}
|
||||
memmove(data, result, size*sizeof(int));
|
||||
g_free(result);
|
||||
g_free(sortbuf);
|
||||
}
|
||||
|
||||
static void interpolate_lines(struct fpi_line_asmbl_ctx *ctx,
|
||||
GSList *line1, float y1, GSList *line2,
|
||||
float y2, unsigned char *output, float yi, int size)
|
||||
{
|
||||
int i;
|
||||
unsigned char p1, p2;
|
||||
|
||||
if (!line1 || !line2)
|
||||
return;
|
||||
|
||||
for (i = 0; i < size; i++) {
|
||||
p1 = ctx->get_pixel(ctx, line1, i);
|
||||
p2 = ctx->get_pixel(ctx, line2, i);
|
||||
output[i] = (float)p1
|
||||
+ (yi - y1)/(y2 - y1)*(p2 - p1);
|
||||
}
|
||||
}
|
||||
|
||||
static int min(int a, int b) {return (a < b) ? a : b; }
|
||||
|
||||
/* Rescale image to account for variable swiping speed */
|
||||
struct fp_img *fpi_assemble_lines(struct fpi_line_asmbl_ctx *ctx,
|
||||
GSList *lines, size_t lines_len)
|
||||
{
|
||||
/* Number of output lines per distance between two scanners */
|
||||
int i;
|
||||
GSList *row1, *row2;
|
||||
float y = 0.0;
|
||||
int line_ind = 0;
|
||||
int *offsets = (int *)g_malloc0((lines_len / 2) * sizeof(int));
|
||||
unsigned char *output = g_malloc0(ctx->line_width * ctx->max_height);
|
||||
struct fp_img *img;
|
||||
|
||||
fp_dbg("%llu", g_get_real_time());
|
||||
|
||||
row1 = lines;
|
||||
for (i = 0; (i < lines_len - 1) && row1; i += 2) {
|
||||
int bestmatch = i;
|
||||
int bestdiff = 0;
|
||||
int j, firstrow, lastrow;
|
||||
|
||||
firstrow = i + 1;
|
||||
lastrow = min(i + ctx->max_search_offset, lines_len - 1);
|
||||
|
||||
row2 = g_slist_next(row1);
|
||||
for (j = firstrow; j <= lastrow; j++) {
|
||||
int diff = ctx->get_deviation(ctx,
|
||||
row1,
|
||||
row2);
|
||||
if ((j == firstrow) || (diff < bestdiff)) {
|
||||
bestdiff = diff;
|
||||
bestmatch = j;
|
||||
}
|
||||
row2 = g_slist_next(row2);
|
||||
}
|
||||
offsets[i / 2] = bestmatch - i;
|
||||
fp_dbg("%d", offsets[i / 2]);
|
||||
row1 = g_slist_next(row1);
|
||||
if (row1)
|
||||
row1 = g_slist_next(row1);
|
||||
}
|
||||
|
||||
median_filter(offsets, (lines_len / 2) - 1, ctx->median_filter_size);
|
||||
|
||||
fp_dbg("offsets_filtered: %llu", g_get_real_time());
|
||||
for (i = 0; i <= (lines_len / 2) - 1; i++)
|
||||
fp_dbg("%d", offsets[i]);
|
||||
row1 = lines;
|
||||
for (i = 0; i < lines_len - 1; i++, row1 = g_slist_next(row1)) {
|
||||
int offset = offsets[i/2];
|
||||
if (offset > 0) {
|
||||
float ynext = y + (float)ctx->resolution / offset;
|
||||
while (line_ind < ynext) {
|
||||
if (line_ind > ctx->max_height - 1)
|
||||
goto out;
|
||||
interpolate_lines(ctx,
|
||||
row1, y,
|
||||
g_slist_next(row1),
|
||||
ynext,
|
||||
output + line_ind * ctx->line_width,
|
||||
line_ind,
|
||||
ctx->line_width);
|
||||
line_ind++;
|
||||
}
|
||||
y = ynext;
|
||||
}
|
||||
}
|
||||
out:
|
||||
img = fpi_img_new(ctx->line_width * line_ind);
|
||||
img->height = line_ind;
|
||||
img->width = ctx->line_width;
|
||||
img->flags = FP_IMG_V_FLIPPED;
|
||||
g_memmove(img->data, output, ctx->line_width * line_ind);
|
||||
g_free(offsets);
|
||||
g_free(output);
|
||||
return img;
|
||||
}
|
||||
65
libfprint/assembling.h
Normal file
65
libfprint/assembling.h
Normal file
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Image assembling routines
|
||||
* Shared functions between libfprint Authentec drivers
|
||||
* Copyright (C) 2007 Daniel Drake <dsd@gentoo.org>
|
||||
* Copyright (C) 2015 Vasily Khoruzhick <anarsoul@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
|
||||
* 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
|
||||
*/
|
||||
|
||||
#ifndef __ASSEMBLING_H__
|
||||
#define __ASSEMBLING_H__
|
||||
|
||||
#include <fp_internal.h>
|
||||
|
||||
struct fpi_frame {
|
||||
int delta_x;
|
||||
int delta_y;
|
||||
unsigned char data[0];
|
||||
};
|
||||
|
||||
struct fpi_frame_asmbl_ctx {
|
||||
unsigned frame_width;
|
||||
unsigned frame_height;
|
||||
unsigned image_width;
|
||||
unsigned char (*get_pixel)(struct fpi_frame_asmbl_ctx *ctx,
|
||||
struct fpi_frame *frame,
|
||||
unsigned x,
|
||||
unsigned y);
|
||||
};
|
||||
|
||||
void fpi_do_movement_estimation(struct fpi_frame_asmbl_ctx *ctx,
|
||||
GSList *stripes, size_t stripes_len);
|
||||
|
||||
struct fp_img *fpi_assemble_frames(struct fpi_frame_asmbl_ctx *ctx,
|
||||
GSList *stripes, size_t stripes_len);
|
||||
|
||||
struct fpi_line_asmbl_ctx {
|
||||
unsigned line_width;
|
||||
unsigned max_height;
|
||||
unsigned resolution;
|
||||
unsigned median_filter_size;
|
||||
unsigned max_search_offset;
|
||||
int (*get_deviation)(struct fpi_line_asmbl_ctx *ctx,
|
||||
GSList *line1, GSList *line2);
|
||||
unsigned char (*get_pixel)(struct fpi_line_asmbl_ctx *ctx,
|
||||
GSList *line,
|
||||
unsigned x);
|
||||
};
|
||||
|
||||
struct fp_img *fpi_assemble_lines(struct fpi_line_asmbl_ctx *ctx,
|
||||
GSList *lines, size_t lines_len);
|
||||
|
||||
#endif
|
||||
@@ -412,3 +412,101 @@ void fpi_drvcb_identify_stopped(struct fp_dev *dev)
|
||||
dev->identify_stop_cb(dev, dev->identify_stop_cb_data);
|
||||
}
|
||||
|
||||
API_EXPORTED int fp_async_capture_start(struct fp_dev *dev, int unconditional,
|
||||
fp_capture_cb callback, void *user_data)
|
||||
{
|
||||
struct fp_driver *drv = dev->drv;
|
||||
int r;
|
||||
|
||||
fp_dbg("");
|
||||
if (!drv->capture_start)
|
||||
return -ENOTSUP;
|
||||
|
||||
dev->state = DEV_STATE_CAPTURE_STARTING;
|
||||
dev->capture_cb = callback;
|
||||
dev->capture_cb_data = user_data;
|
||||
dev->unconditional_capture = unconditional;
|
||||
|
||||
r = drv->capture_start(dev);
|
||||
if (r < 0) {
|
||||
dev->capture_cb = NULL;
|
||||
dev->state = DEV_STATE_ERROR;
|
||||
fp_err("failed to start verification, error %d", r);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Drivers call this when capture has started */
|
||||
void fpi_drvcb_capture_started(struct fp_dev *dev, int status)
|
||||
{
|
||||
fp_dbg("");
|
||||
BUG_ON(dev->state != DEV_STATE_CAPTURE_STARTING);
|
||||
if (status) {
|
||||
if (status > 0) {
|
||||
status = -status;
|
||||
fp_dbg("adjusted to %d", status);
|
||||
}
|
||||
dev->state = DEV_STATE_ERROR;
|
||||
if (dev->capture_cb)
|
||||
dev->capture_cb(dev, status, NULL, dev->capture_cb_data);
|
||||
} else {
|
||||
dev->state = DEV_STATE_CAPTURING;
|
||||
}
|
||||
}
|
||||
|
||||
/* Drivers call this to report a capture result (which might mark completion) */
|
||||
void fpi_drvcb_report_capture_result(struct fp_dev *dev, int result,
|
||||
struct fp_img *img)
|
||||
{
|
||||
fp_dbg("result %d", result);
|
||||
BUG_ON(dev->state != DEV_STATE_CAPTURING);
|
||||
if (result < 0 || result == FP_CAPTURE_COMPLETE)
|
||||
dev->state = DEV_STATE_CAPTURE_DONE;
|
||||
|
||||
if (dev->capture_cb)
|
||||
dev->capture_cb(dev, result, img, dev->capture_cb_data);
|
||||
else
|
||||
fp_dbg("ignoring capture result as no callback is subscribed");
|
||||
}
|
||||
|
||||
/* Drivers call this when capture has stopped */
|
||||
void fpi_drvcb_capture_stopped(struct fp_dev *dev)
|
||||
{
|
||||
fp_dbg("");
|
||||
BUG_ON(dev->state != DEV_STATE_CAPTURE_STOPPING);
|
||||
dev->state = DEV_STATE_INITIALIZED;
|
||||
if (dev->capture_stop_cb)
|
||||
dev->capture_stop_cb(dev, dev->capture_stop_cb_data);
|
||||
}
|
||||
|
||||
API_EXPORTED int fp_async_capture_stop(struct fp_dev *dev,
|
||||
fp_capture_stop_cb callback, void *user_data)
|
||||
{
|
||||
struct fp_driver *drv = dev->drv;
|
||||
int r;
|
||||
|
||||
fp_dbg("");
|
||||
BUG_ON(dev->state != DEV_STATE_ERROR
|
||||
&& dev->state != DEV_STATE_CAPTURING
|
||||
&& dev->state != DEV_STATE_CAPTURE_DONE);
|
||||
|
||||
dev->capture_cb = NULL;
|
||||
dev->capture_stop_cb = callback;
|
||||
dev->capture_stop_cb_data = user_data;
|
||||
dev->state = DEV_STATE_CAPTURE_STOPPING;
|
||||
|
||||
if (!drv->capture_start)
|
||||
return -ENOTSUP;
|
||||
if (!drv->capture_stop) {
|
||||
dev->state = DEV_STATE_INITIALIZED;
|
||||
fpi_drvcb_capture_stopped(dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = drv->capture_stop(dev);
|
||||
if (r < 0) {
|
||||
fp_err("failed to stop verification");
|
||||
dev->capture_stop_cb = NULL;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -291,25 +291,25 @@ void fpi_log(enum fpi_log_level level, const char *component,
|
||||
#ifndef ENABLE_DEBUG_LOGGING
|
||||
if (!log_level)
|
||||
return;
|
||||
if (level == LOG_LEVEL_WARNING && log_level < 2)
|
||||
if (level == FPRINT_LOG_LEVEL_WARNING && log_level < 2)
|
||||
return;
|
||||
if (level == LOG_LEVEL_INFO && log_level < 3)
|
||||
if (level == FPRINT_LOG_LEVEL_INFO && log_level < 3)
|
||||
return;
|
||||
#endif
|
||||
|
||||
switch (level) {
|
||||
case LOG_LEVEL_INFO:
|
||||
case FPRINT_LOG_LEVEL_INFO:
|
||||
prefix = "info";
|
||||
break;
|
||||
case LOG_LEVEL_WARNING:
|
||||
case FPRINT_LOG_LEVEL_WARNING:
|
||||
stream = stderr;
|
||||
prefix = "warning";
|
||||
break;
|
||||
case LOG_LEVEL_ERROR:
|
||||
case FPRINT_LOG_LEVEL_ERROR:
|
||||
stream = stderr;
|
||||
prefix = "error";
|
||||
break;
|
||||
case LOG_LEVEL_DEBUG:
|
||||
case FPRINT_LOG_LEVEL_DEBUG:
|
||||
stream = stderr;
|
||||
prefix = "debug";
|
||||
break;
|
||||
@@ -349,12 +349,18 @@ static struct fp_driver * const primitive_drivers[] = {
|
||||
};
|
||||
|
||||
static struct fp_img_driver * const img_drivers[] = {
|
||||
#ifdef ENABLE_AES3500
|
||||
&aes3500_driver,
|
||||
#endif
|
||||
#ifdef ENABLE_AES4000
|
||||
&aes4000_driver,
|
||||
#endif
|
||||
#ifdef ENABLE_AES2501
|
||||
&aes2501_driver,
|
||||
#endif
|
||||
#ifdef ENABLE_AES2550
|
||||
&aes2550_driver,
|
||||
#endif
|
||||
#ifdef ENABLE_URU4000
|
||||
&uru4000_driver,
|
||||
#endif
|
||||
@@ -368,10 +374,34 @@ static struct fp_img_driver * const img_drivers[] = {
|
||||
#ifdef ENABLE_AES1610
|
||||
&aes1610_driver,
|
||||
#endif
|
||||
/*#ifdef ENABLE_UPEKTC
|
||||
#ifdef ENABLE_AES1660
|
||||
&aes1660_driver,
|
||||
#endif
|
||||
#ifdef ENABLE_AES2660
|
||||
&aes2660_driver,
|
||||
#endif
|
||||
#ifdef ENABLE_VFS101
|
||||
&vfs101_driver,
|
||||
#endif
|
||||
#ifdef ENABLE_VFS301
|
||||
&vfs301_driver,
|
||||
#endif
|
||||
#ifdef ENABLE_VFS5011
|
||||
&vfs5011_driver,
|
||||
#endif
|
||||
#ifdef ENABLE_UPEKTC
|
||||
&upektc_driver,
|
||||
#endif
|
||||
#ifdef ENABLE_FDU2000
|
||||
#ifdef ENABLE_UPEKTC_IMG
|
||||
&upektc_img_driver,
|
||||
#endif
|
||||
#ifdef ENABLE_ETES603
|
||||
&etes603_driver,
|
||||
#endif
|
||||
#ifdef ENABLE_VFS0050
|
||||
&vfs0050_driver,
|
||||
#endif
|
||||
/*#ifdef ENABLE_FDU2000
|
||||
&fdu2000_driver,
|
||||
#endif
|
||||
*/
|
||||
@@ -786,7 +816,7 @@ static struct fp_img_dev *dev_to_img_dev(struct fp_dev *dev)
|
||||
*/
|
||||
API_EXPORTED int fp_dev_supports_imaging(struct fp_dev *dev)
|
||||
{
|
||||
return dev->drv->type == DRIVER_IMAGING;
|
||||
return dev->drv->capture_start != NULL;
|
||||
}
|
||||
|
||||
/** \ingroup dev
|
||||
@@ -801,38 +831,6 @@ API_EXPORTED int fp_dev_supports_identification(struct fp_dev *dev)
|
||||
return dev->drv->identify_start != NULL;
|
||||
}
|
||||
|
||||
/** \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,
|
||||
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);
|
||||
/* FIXME reimplement async */
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
/** \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
|
||||
|
||||
160
libfprint/data.c
160
libfprint/data.c
@@ -95,22 +95,33 @@ static const char *finger_num_to_str(enum fp_finger finger)
|
||||
#endif
|
||||
|
||||
static struct fp_print_data *print_data_new(uint16_t driver_id,
|
||||
uint32_t devtype, enum fp_print_data_type type, size_t length)
|
||||
uint32_t devtype, enum fp_print_data_type type)
|
||||
{
|
||||
struct fp_print_data *data = g_malloc(sizeof(*data) + length);
|
||||
fp_dbg("length=%zd driver=%02x devtype=%04x", length, driver_id, devtype);
|
||||
memset(data, 0, sizeof(*data));
|
||||
struct fp_print_data *data = g_malloc0(sizeof(*data));
|
||||
fp_dbg("driver=%02x devtype=%04x", driver_id, devtype);
|
||||
data->driver_id = driver_id;
|
||||
data->devtype = devtype;
|
||||
data->type = type;
|
||||
data->length = length;
|
||||
return data;
|
||||
}
|
||||
|
||||
struct fp_print_data *fpi_print_data_new(struct fp_dev *dev, size_t length)
|
||||
void fpi_print_data_item_free(struct fp_print_data_item *item)
|
||||
{
|
||||
g_free(item);
|
||||
}
|
||||
|
||||
struct fp_print_data_item *fpi_print_data_item_new(size_t length)
|
||||
{
|
||||
struct fp_print_data_item *item = g_malloc(sizeof(*item) + length);
|
||||
item->length = length;
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
struct fp_print_data *fpi_print_data_new(struct fp_dev *dev)
|
||||
{
|
||||
return print_data_new(dev->drv->id, dev->devtype,
|
||||
fpi_driver_get_data_type(dev->drv), length);
|
||||
fpi_driver_get_data_type(dev->drv));
|
||||
}
|
||||
|
||||
/** \ingroup print_data
|
||||
@@ -125,27 +136,115 @@ struct fp_print_data *fpi_print_data_new(struct fp_dev *dev, size_t length)
|
||||
API_EXPORTED size_t fp_print_data_get_data(struct fp_print_data *data,
|
||||
unsigned char **ret)
|
||||
{
|
||||
struct fpi_print_data_fp1 *buf;
|
||||
size_t buflen;
|
||||
struct fpi_print_data_fp2 *out_data;
|
||||
struct fpi_print_data_item_fp2 *out_item;
|
||||
struct fp_print_data_item *item;
|
||||
size_t buflen = 0;
|
||||
GSList *list_item;
|
||||
unsigned char *buf;
|
||||
|
||||
fp_dbg("");
|
||||
|
||||
buflen = sizeof(*buf) + data->length;
|
||||
buf = malloc(buflen);
|
||||
if (!buf)
|
||||
return 0;
|
||||
list_item = data->prints;
|
||||
while (list_item) {
|
||||
item = list_item->data;
|
||||
buflen += sizeof(*out_item);
|
||||
buflen += item->length;
|
||||
list_item = g_slist_next(list_item);
|
||||
}
|
||||
|
||||
buflen += sizeof(*out_data);
|
||||
out_data = g_malloc(buflen);
|
||||
|
||||
*ret = (unsigned char *) out_data;
|
||||
buf = out_data->data;
|
||||
out_data->prefix[0] = 'F';
|
||||
out_data->prefix[1] = 'P';
|
||||
out_data->prefix[2] = '2';
|
||||
out_data->driver_id = GUINT16_TO_LE(data->driver_id);
|
||||
out_data->devtype = GUINT32_TO_LE(data->devtype);
|
||||
out_data->data_type = data->type;
|
||||
|
||||
list_item = data->prints;
|
||||
while (list_item) {
|
||||
item = list_item->data;
|
||||
out_item = (struct fpi_print_data_item_fp2 *)buf;
|
||||
out_item->length = GUINT32_TO_LE(item->length);
|
||||
/* FIXME: fp_print_data_item->data content is not endianess agnostic */
|
||||
memcpy(out_item->data, item->data, item->length);
|
||||
buf += sizeof(*out_item);
|
||||
buf += item->length;
|
||||
list_item = g_slist_next(list_item);
|
||||
}
|
||||
|
||||
*ret = (unsigned char *) buf;
|
||||
buf->prefix[0] = 'F';
|
||||
buf->prefix[1] = 'P';
|
||||
buf->prefix[2] = '1';
|
||||
buf->driver_id = GUINT16_TO_LE(data->driver_id);
|
||||
buf->devtype = GUINT32_TO_LE(data->devtype);
|
||||
buf->data_type = data->type;
|
||||
memcpy(buf->data, data->data, data->length);
|
||||
return buflen;
|
||||
}
|
||||
|
||||
static struct fp_print_data *fpi_print_data_from_fp1_data(unsigned char *buf,
|
||||
size_t buflen)
|
||||
{
|
||||
size_t print_data_len;
|
||||
struct fp_print_data *data;
|
||||
struct fp_print_data_item *item;
|
||||
struct fpi_print_data_fp2 *raw = (struct fpi_print_data_fp2 *) buf;
|
||||
|
||||
print_data_len = buflen - sizeof(*raw);
|
||||
data = print_data_new(GUINT16_FROM_LE(raw->driver_id),
|
||||
GUINT32_FROM_LE(raw->devtype), raw->data_type);
|
||||
item = fpi_print_data_item_new(print_data_len);
|
||||
/* FIXME: fp_print_data->data content is not endianess agnostic */
|
||||
memcpy(item->data, raw->data, print_data_len);
|
||||
data->prints = g_slist_prepend(data->prints, item);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
static struct fp_print_data *fpi_print_data_from_fp2_data(unsigned char *buf,
|
||||
size_t buflen)
|
||||
{
|
||||
size_t total_data_len, item_len;
|
||||
struct fp_print_data *data;
|
||||
struct fp_print_data_item *item;
|
||||
struct fpi_print_data_fp2 *raw = (struct fpi_print_data_fp2 *) buf;
|
||||
unsigned char *raw_buf;
|
||||
struct fpi_print_data_item_fp2 *raw_item;
|
||||
|
||||
total_data_len = buflen - sizeof(*raw);
|
||||
data = print_data_new(GUINT16_FROM_LE(raw->driver_id),
|
||||
GUINT32_FROM_LE(raw->devtype), raw->data_type);
|
||||
raw_buf = raw->data;
|
||||
while (total_data_len) {
|
||||
if (total_data_len < sizeof(*raw_item))
|
||||
break;
|
||||
total_data_len -= sizeof(*raw_item);
|
||||
|
||||
raw_item = (struct fpi_print_data_item_fp2 *)raw_buf;
|
||||
item_len = GUINT32_FROM_LE(raw_item->length);
|
||||
fp_dbg("item len %d, total_data_len %d", item_len, total_data_len);
|
||||
if (total_data_len < item_len) {
|
||||
fp_err("corrupted fingerprint data");
|
||||
break;
|
||||
}
|
||||
total_data_len -= item_len;
|
||||
|
||||
item = fpi_print_data_item_new(item_len);
|
||||
/* FIXME: fp_print_data->data content is not endianess agnostic */
|
||||
memcpy(item->data, raw_item->data, item_len);
|
||||
data->prints = g_slist_prepend(data->prints, item);
|
||||
|
||||
raw_buf += sizeof(*raw_item);
|
||||
raw_buf += item_len;
|
||||
}
|
||||
|
||||
if (g_slist_length(data->prints) == 0) {
|
||||
fp_print_data_free(data);
|
||||
data = NULL;
|
||||
}
|
||||
|
||||
return data;
|
||||
|
||||
}
|
||||
|
||||
/** \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
|
||||
@@ -158,24 +257,21 @@ API_EXPORTED size_t fp_print_data_get_data(struct fp_print_data *data,
|
||||
API_EXPORTED struct fp_print_data *fp_print_data_from_data(unsigned char *buf,
|
||||
size_t buflen)
|
||||
{
|
||||
struct fpi_print_data_fp1 *raw = (struct fpi_print_data_fp1 *) buf;
|
||||
size_t print_data_len;
|
||||
struct fp_print_data *data;
|
||||
struct fpi_print_data_fp2 *raw = (struct fpi_print_data_fp2 *) buf;
|
||||
|
||||
fp_dbg("buffer size %zd", buflen);
|
||||
if (buflen < sizeof(*raw))
|
||||
return NULL;
|
||||
|
||||
if (strncmp(raw->prefix, "FP1", 3) != 0) {
|
||||
if (strncmp(raw->prefix, "FP1", 3) == 0) {
|
||||
return fpi_print_data_from_fp1_data(buf, buflen);
|
||||
} else if (strncmp(raw->prefix, "FP2", 3) == 0) {
|
||||
return fpi_print_data_from_fp2_data(buf, buflen);
|
||||
} else {
|
||||
fp_dbg("bad header prefix");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
print_data_len = buflen - sizeof(*raw);
|
||||
data = print_data_new(GUINT16_FROM_LE(raw->driver_id),
|
||||
GUINT32_FROM_LE(raw->devtype), raw->data_type, print_data_len);
|
||||
memcpy(data->data, raw->data, print_data_len);
|
||||
return data;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static char *get_path_to_storedir(uint16_t driver_id, uint32_t devtype)
|
||||
@@ -406,6 +502,8 @@ API_EXPORTED int fp_print_data_from_dscv_print(struct fp_dscv_print *print,
|
||||
*/
|
||||
API_EXPORTED void fp_print_data_free(struct fp_print_data *data)
|
||||
{
|
||||
if (data)
|
||||
g_slist_free_full(data->prints, (GDestroyNotify)fpi_print_data_item_free);
|
||||
g_free(data);
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
* Copyright (C) 2007 Cyrille Bagard
|
||||
* Copyright (C) 2007 Vasily Khoruzhick
|
||||
* Copyright (C) 2009 Guido Grazioli <guido.grazioli@gmail.com>
|
||||
* Copyright (C) 2012 Vasily Khoruzhick <anarsoul@gmail.com>
|
||||
*
|
||||
* Based on code from libfprint aes2501 driver.
|
||||
*
|
||||
@@ -29,9 +30,12 @@
|
||||
|
||||
#include <libusb.h>
|
||||
|
||||
#include <assembling.h>
|
||||
#include <aeslib.h>
|
||||
#include <fp_internal.h>
|
||||
|
||||
#include "driver_ids.h"
|
||||
|
||||
static void start_capture(struct fp_img_dev *dev);
|
||||
static void complete_deactivation(struct fp_img_dev *dev);
|
||||
static int adjust_gain(unsigned char *buffer, int status);
|
||||
@@ -63,6 +67,7 @@ static int adjust_gain(unsigned char *buffer, int status);
|
||||
#define FRAME_WIDTH 128
|
||||
#define FRAME_HEIGHT 8
|
||||
#define FRAME_SIZE (FRAME_WIDTH * FRAME_HEIGHT)
|
||||
#define IMAGE_WIDTH (FRAME_WIDTH + (FRAME_WIDTH / 2))
|
||||
/* maximum number of frames to read during a scan */
|
||||
/* FIXME reduce substantially */
|
||||
#define MAX_FRAMES 350
|
||||
@@ -77,6 +82,13 @@ struct aes1610_dev {
|
||||
uint8_t blanks_count;
|
||||
};
|
||||
|
||||
static struct fpi_frame_asmbl_ctx assembling_ctx = {
|
||||
.frame_width = FRAME_WIDTH,
|
||||
.frame_height = FRAME_HEIGHT,
|
||||
.image_width = IMAGE_WIDTH,
|
||||
.get_pixel = aes_get_pixel,
|
||||
};
|
||||
|
||||
typedef void (*aes1610_read_regs_cb)(struct fp_img_dev *dev, int status,
|
||||
unsigned char *regs, void *user_data);
|
||||
|
||||
@@ -110,103 +122,6 @@ static void generic_ignore_data_cb(struct libusb_transfer *transfer)
|
||||
libusb_free_transfer(transfer);
|
||||
}
|
||||
|
||||
|
||||
static void read_regs_data_cb(struct libusb_transfer *transfer)
|
||||
{
|
||||
struct aes1610_read_regs *rdata = transfer->user_data;
|
||||
unsigned char *retdata = NULL;
|
||||
int r;
|
||||
|
||||
if (transfer->status != LIBUSB_TRANSFER_COMPLETED) {
|
||||
r = -EIO;
|
||||
} else if (transfer->length != transfer->actual_length) {
|
||||
r = -EPROTO;
|
||||
} else {
|
||||
r = 0;
|
||||
retdata = transfer->buffer;
|
||||
}
|
||||
|
||||
rdata->callback(rdata->dev, r, retdata, rdata->user_data);
|
||||
g_free(rdata);
|
||||
g_free(transfer->buffer);
|
||||
libusb_free_transfer(transfer);
|
||||
}
|
||||
|
||||
static void read_regs_rq_cb(struct fp_img_dev *dev, int result, void *user_data)
|
||||
{
|
||||
struct aes1610_read_regs *rdata = user_data;
|
||||
struct libusb_transfer *transfer;
|
||||
unsigned char *data;
|
||||
int r;
|
||||
|
||||
g_free(rdata->regwrite);
|
||||
if (result != 0)
|
||||
goto err;
|
||||
|
||||
transfer = libusb_alloc_transfer(0);
|
||||
if (!transfer) {
|
||||
result = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
|
||||
data = g_malloc(126);
|
||||
libusb_fill_bulk_transfer(transfer, dev->udev, EP_IN, data, 126,
|
||||
read_regs_data_cb, rdata, BULK_TIMEOUT);
|
||||
|
||||
r = libusb_submit_transfer(transfer);
|
||||
if (r < 0) {
|
||||
g_free(data);
|
||||
libusb_free_transfer(transfer);
|
||||
result = -EIO;
|
||||
goto err;
|
||||
}
|
||||
|
||||
return;
|
||||
err:
|
||||
rdata->callback(dev, result, NULL, rdata->user_data);
|
||||
g_free(rdata);
|
||||
}
|
||||
|
||||
|
||||
// XXX: this comes from aes2501 driver but it is unused here
|
||||
static void read_regs(struct fp_img_dev *dev, aes1610_read_regs_cb callback,
|
||||
void *user_data)
|
||||
{
|
||||
/* FIXME: regwrite is dynamic because of asynchronity. is this really
|
||||
* required? */
|
||||
struct aes_regwrite *regwrite = g_malloc(sizeof(*regwrite));
|
||||
struct aes1610_read_regs *rdata = g_malloc(sizeof(*rdata));
|
||||
|
||||
fp_dbg("");
|
||||
//regwrite->reg = AES1610_REG_CTRL2;
|
||||
//regwrite->value = AES1610_CTRL2_READ_REGS;
|
||||
rdata->dev = dev;
|
||||
rdata->callback = callback;
|
||||
rdata->user_data = user_data;
|
||||
rdata->regwrite = regwrite;
|
||||
|
||||
//aes_write_regv(dev, (const struct aes_regwrite *) regwrite, 1,
|
||||
// read_regs_rq_cb, rdata);
|
||||
}
|
||||
|
||||
/* Read the value of a specific register from a register dump */
|
||||
static int regval_from_dump(unsigned char *data, uint8_t target)
|
||||
{
|
||||
if (*data != FIRST_AES1610_REG) {
|
||||
fp_err("not a register dump");
|
||||
return -EILSEQ;
|
||||
}
|
||||
|
||||
if (!(FIRST_AES1610_REG <= target && target <= LAST_AES1610_REG)) {
|
||||
fp_err("out of range");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
target -= FIRST_AES1610_REG;
|
||||
target *= 2;
|
||||
return data[target + 1];
|
||||
}
|
||||
|
||||
static void generic_write_regv_cb(struct fp_img_dev *dev, int result,
|
||||
void *user_data)
|
||||
{
|
||||
@@ -217,8 +132,6 @@ static void generic_write_regv_cb(struct fp_img_dev *dev, int result,
|
||||
fpi_ssm_mark_aborted(ssm, result);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* read the specified number of bytes from the IN endpoint but throw them
|
||||
* away, then increment the SSM */
|
||||
static void generic_read_ignore_data(struct fpi_ssm *ssm, size_t bytes)
|
||||
@@ -244,150 +157,6 @@ static void generic_read_ignore_data(struct fpi_ssm *ssm, size_t bytes)
|
||||
}
|
||||
}
|
||||
|
||||
/****** IMAGE PROCESSING ******/
|
||||
|
||||
static int sum_histogram_values(unsigned char *data, uint8_t threshold)
|
||||
{
|
||||
int r = 0;
|
||||
int i;
|
||||
uint16_t *histogram = (uint16_t *)(data + 1);
|
||||
|
||||
if (*data != 0xde)
|
||||
return -EILSEQ;
|
||||
|
||||
if (threshold > 0x0f)
|
||||
return -EINVAL;
|
||||
|
||||
/* FIXME endianness */
|
||||
for (i = threshold; i < 16; i++)
|
||||
r += histogram[i];
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/* find overlapping parts of frames */
|
||||
static unsigned int find_overlap(unsigned char *first_frame,
|
||||
unsigned char *second_frame, unsigned int *min_error)
|
||||
{
|
||||
unsigned int dy;
|
||||
unsigned int not_overlapped_height = 0;
|
||||
*min_error = 255 * FRAME_SIZE;
|
||||
for (dy = 0; dy < FRAME_HEIGHT; dy++) {
|
||||
/* Calculating difference (error) between parts of frames */
|
||||
unsigned int i;
|
||||
unsigned int error = 0;
|
||||
for (i = 0; i < FRAME_WIDTH * (FRAME_HEIGHT - dy); i++) {
|
||||
/* Using ? operator to avoid abs function */
|
||||
error += first_frame[i] > second_frame[i] ?
|
||||
(first_frame[i] - second_frame[i]) :
|
||||
(second_frame[i] - first_frame[i]);
|
||||
}
|
||||
|
||||
/* Normalize error */
|
||||
error *= 15;
|
||||
error /= i;
|
||||
if (error < *min_error) {
|
||||
*min_error = error;
|
||||
not_overlapped_height = dy;
|
||||
}
|
||||
first_frame += FRAME_WIDTH;
|
||||
}
|
||||
|
||||
return not_overlapped_height;
|
||||
}
|
||||
|
||||
/* assemble a series of frames into a single image */
|
||||
static unsigned int assemble(struct aes1610_dev *aesdev, unsigned char *output,
|
||||
gboolean reverse, unsigned int *errors_sum)
|
||||
{
|
||||
uint8_t *assembled = output;
|
||||
int frame;
|
||||
uint32_t image_height = FRAME_HEIGHT;
|
||||
unsigned int min_error;
|
||||
size_t num_strips = aesdev->strips_len;
|
||||
GSList *list_entry = aesdev->strips;
|
||||
*errors_sum = 0;
|
||||
|
||||
if (num_strips < 1)
|
||||
return 0;
|
||||
|
||||
/* Rotating given data by 90 degrees
|
||||
* Taken from document describing aes1610 image format
|
||||
* TODO: move reversing detection here */
|
||||
|
||||
if (reverse)
|
||||
output += (num_strips - 1) * FRAME_SIZE;
|
||||
for (frame = 0; frame < num_strips; frame++) {
|
||||
aes_assemble_image(list_entry->data, FRAME_WIDTH, FRAME_HEIGHT, output);
|
||||
|
||||
if (reverse)
|
||||
output -= FRAME_SIZE;
|
||||
else
|
||||
output += FRAME_SIZE;
|
||||
list_entry = g_slist_next(list_entry);
|
||||
}
|
||||
|
||||
/* Detecting where frames overlaped */
|
||||
output = assembled;
|
||||
for (frame = 1; frame < num_strips; frame++) {
|
||||
int not_overlapped;
|
||||
|
||||
output += FRAME_SIZE;
|
||||
not_overlapped = find_overlap(assembled, output, &min_error);
|
||||
*errors_sum += min_error;
|
||||
image_height += not_overlapped;
|
||||
assembled += FRAME_WIDTH * not_overlapped;
|
||||
memcpy(assembled, output, FRAME_SIZE);
|
||||
}
|
||||
return image_height;
|
||||
}
|
||||
|
||||
static void assemble_and_submit_image(struct fp_img_dev *dev)
|
||||
{
|
||||
struct aes1610_dev *aesdev = dev->priv;
|
||||
size_t final_size;
|
||||
struct fp_img *img;
|
||||
unsigned int errors_sum, r_errors_sum;
|
||||
|
||||
fp_dbg("");
|
||||
|
||||
BUG_ON(aesdev->strips_len == 0);
|
||||
|
||||
/* reverse list */
|
||||
aesdev->strips = g_slist_reverse(aesdev->strips);
|
||||
|
||||
/* create buffer big enough for max image */
|
||||
img = fpi_img_new(aesdev->strips_len * FRAME_SIZE);
|
||||
|
||||
img->flags = FP_IMG_COLORS_INVERTED;
|
||||
img->height = assemble(aesdev, img->data, FALSE, &errors_sum);
|
||||
img->height = assemble(aesdev, img->data, TRUE, &r_errors_sum);
|
||||
|
||||
if (r_errors_sum > errors_sum) {
|
||||
img->height = assemble(aesdev, img->data, FALSE, &errors_sum);
|
||||
img->flags |= FP_IMG_V_FLIPPED | FP_IMG_H_FLIPPED;
|
||||
fp_dbg("normal scan direction");
|
||||
} else {
|
||||
fp_dbg("reversed scan direction");
|
||||
}
|
||||
|
||||
/* now that overlap has been removed, resize output image buffer */
|
||||
final_size = img->height * FRAME_WIDTH;
|
||||
img = fpi_img_resize(img, final_size);
|
||||
/* FIXME: ugly workaround */
|
||||
if (img->height < 12)
|
||||
img->height = 12;
|
||||
fpi_imgdev_image_captured(dev, img);
|
||||
|
||||
/* free strips and strip list */
|
||||
g_slist_foreach(aesdev->strips, (GFunc) g_free, NULL);
|
||||
g_slist_free(aesdev->strips);
|
||||
aesdev->strips = NULL;
|
||||
aesdev->strips_len = 0;
|
||||
aesdev->blanks_count = 0;
|
||||
}
|
||||
|
||||
|
||||
/****** FINGER PRESENCE DETECTION ******/
|
||||
|
||||
|
||||
@@ -416,15 +185,6 @@ static const struct aes_regwrite finger_det_reqs[] = {
|
||||
{ 0x81, 0x04 }
|
||||
};
|
||||
|
||||
static const struct aes_regwrite finger_det_none[] = {
|
||||
{ 0x80, 0x01 },
|
||||
{ 0x82, 0x00 },
|
||||
{ 0x86, 0x00 },
|
||||
{ 0xB1, 0x28 },
|
||||
{ 0x1D, 0x00 }
|
||||
};
|
||||
|
||||
|
||||
static void start_finger_detection(struct fp_img_dev *dev);
|
||||
|
||||
static void finger_det_data_cb(struct libusb_transfer *transfer)
|
||||
@@ -461,12 +221,6 @@ out:
|
||||
libusb_free_transfer(transfer);
|
||||
}
|
||||
|
||||
|
||||
static void finger_det_none_cb(struct fp_img_dev *dev, int result, void *user_data) | ||||