mirror of
https://gitlab.freedesktop.org/libfprint/libfprint.git
synced 2025-11-15 07:38:12 +00:00
Compare commits
18 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f8aa82a554 | ||
|
|
1451a2dde2 | ||
|
|
d2e957683f | ||
|
|
a3ae96c214 | ||
|
|
3dd905d4e9 | ||
|
|
aab031ce37 | ||
|
|
6bfc516553 | ||
|
|
ff842125c5 | ||
|
|
712ebb6d44 | ||
|
|
a18f318446 | ||
|
|
15b8e8f376 | ||
|
|
9f8dd29a55 | ||
|
|
f28c579779 | ||
|
|
375575b701 | ||
|
|
25161286f5 | ||
|
|
c575afba9a | ||
|
|
8cd31f6ad8 | ||
|
|
4b518bd230 |
1
AUTHORS
1
AUTHORS
@@ -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
13
NEWS
@@ -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
|
||||
|
||||
123
configure.ac
123
configure.ac
@@ -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
|
||||
|
||||
|
||||
@@ -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
11
examples/cpp-test.cpp
Normal 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;
|
||||
}
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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, },
|
||||
};
|
||||
|
||||
|
||||
@@ -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
1570
libfprint/drivers/vfs101.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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];
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user