mirror of
https://gitlab.freedesktop.org/libfprint/libfprint.git
synced 2026-09-10 13:00:08 +00:00
Compare commits
308
Commits
+1
-22
@@ -1,24 +1,3 @@
|
||||
ltmain.sh
|
||||
missing
|
||||
stamp-h1
|
||||
libtool
|
||||
*.la
|
||||
*.lo
|
||||
*.o
|
||||
*.swp
|
||||
Makefile
|
||||
Makefile.in
|
||||
config.h*
|
||||
aclocal.m4
|
||||
autom4te.cache
|
||||
config.guess
|
||||
config.log
|
||||
config.status
|
||||
config.sub
|
||||
configure
|
||||
depcomp
|
||||
install-sh
|
||||
.deps
|
||||
.libs
|
||||
compile
|
||||
ChangeLog
|
||||
_build
|
||||
|
||||
+101
-20
@@ -1,58 +1,111 @@
|
||||
image: fedora:rawhide
|
||||
stages:
|
||||
- build
|
||||
- test
|
||||
- flatpack
|
||||
include:
|
||||
- local: '.gitlab-ci/libfprint-templates.yaml'
|
||||
- project: 'wayland/ci-templates'
|
||||
ref: master
|
||||
file: '/templates/fedora.yml'
|
||||
|
||||
variables:
|
||||
DEPENDENCIES: libgusb-devel glib2-devel nss-devel pixman-devel systemd meson gtk-doc
|
||||
gcc gcc-c++ glibc-devel libX11-devel libXv-devel gtk3-devel flatpak-builder
|
||||
gobject-introspection-devel python3-cairo python3-gobject umockdev
|
||||
extends: .libfprint_common_variables
|
||||
FDO_DISTRIBUTION_TAG: latest
|
||||
FDO_DISTRIBUTION_VERSION: rawhide
|
||||
FEDORA_IMAGE: "$CI_REGISTRY/libfprint/$CI_PROJECT_NAME/fedora/$FDO_DISTRIBUTION_VERSION:$FDO_DISTRIBUTION_TAG"
|
||||
BUNDLE: "org.freedesktop.libfprint.Demo.flatpak"
|
||||
LAST_ABI_BREAK: "056ea541ddc97f5806cffbd99a12dc87e4da3546"
|
||||
|
||||
stages:
|
||||
- check-source
|
||||
- build
|
||||
- test
|
||||
- flatpak
|
||||
|
||||
image: "$FEDORA_IMAGE"
|
||||
|
||||
.build_one_driver_template: &build_one_driver
|
||||
script:
|
||||
- dnf update -y --nogpgcheck && dnf install -y --nogpgcheck $DEPENDENCIES
|
||||
# Build with a driver that doesn't need imaging, or nss
|
||||
- meson -Ddrivers=$driver . _build
|
||||
- meson --werror -Ddrivers=$driver . _build
|
||||
- ninja -C _build
|
||||
- rm -rf _build/
|
||||
|
||||
.build_template: &build
|
||||
script:
|
||||
- dnf update -y --nogpgcheck && dnf install -y --nogpgcheck $DEPENDENCIES
|
||||
# And build with everything
|
||||
- meson -Ddrivers=all . _build
|
||||
- meson --werror -Ddrivers=all . _build
|
||||
- ninja -C _build
|
||||
- ninja -C _build install
|
||||
|
||||
.build_template: &check_abi
|
||||
script:
|
||||
- dnf update -y --nogpgcheck && dnf install -y --nogpgcheck $DEPENDENCIES doxygen libabigail git
|
||||
- ./.ci/check-abi ${LAST_ABI_BREAK} $(git rev-parse HEAD)
|
||||
|
||||
build:
|
||||
stage: build
|
||||
except:
|
||||
variables:
|
||||
- $CI_PIPELINE_SOURCE == "schedule"
|
||||
variables:
|
||||
driver: virtual_image
|
||||
<<: *build_one_driver
|
||||
<<: *build
|
||||
# <<: *check_abi
|
||||
artifacts:
|
||||
expose_as: "HTML Documentation"
|
||||
paths:
|
||||
- _build/doc/html/
|
||||
expire_in: 1 week
|
||||
|
||||
test:
|
||||
stage: test
|
||||
except:
|
||||
variables:
|
||||
- $CI_PIPELINE_SOURCE == "schedule"
|
||||
script:
|
||||
- meson --werror -Ddrivers=all -Db_coverage=true . _build
|
||||
- ninja -C _build
|
||||
- meson test -C _build --verbose --no-stdsplit --timeout-multiplier 3
|
||||
- ninja -C _build coverage
|
||||
- cat _build/meson-logs/coverage.txt
|
||||
artifacts:
|
||||
paths:
|
||||
- _build/meson-logs
|
||||
expire_in: 1 week
|
||||
|
||||
test_valgrind:
|
||||
stage: test
|
||||
except:
|
||||
variables:
|
||||
- $CI_PIPELINE_SOURCE == "schedule"
|
||||
script:
|
||||
- dnf update -y --nogpgcheck && dnf install -y --nogpgcheck $DEPENDENCIES
|
||||
- meson -Ddrivers=all . _build
|
||||
- ninja -C _build
|
||||
- meson test -C _build --verbose --no-stdsplit
|
||||
- meson test -C _build --verbose --no-stdsplit --setup=valgrind
|
||||
|
||||
test_scan_build:
|
||||
stage: test
|
||||
except:
|
||||
variables:
|
||||
- $CI_PIPELINE_SOURCE == "schedule"
|
||||
allow_failure: true
|
||||
script:
|
||||
- meson -Ddrivers=all . _build
|
||||
# This is ugly, the wrapper disables the malloc checker
|
||||
- SCANBUILD=$CI_PROJECT_DIR/.gitlab-ci/scan-build ninja -C _build scan-build
|
||||
# Check that the directory is empty
|
||||
- "! ls -A _build/meson-logs/scanbuild | grep -q ."
|
||||
artifacts:
|
||||
paths:
|
||||
- _build/meson-logs
|
||||
expire_in: 1 week
|
||||
|
||||
test_indent:
|
||||
stage: test
|
||||
stage: check-source
|
||||
except:
|
||||
variables:
|
||||
- $CI_PIPELINE_SOURCE == "schedule"
|
||||
script:
|
||||
- dnf update -y --nogpgcheck && dnf install -y --nogpgcheck git uncrustify
|
||||
- scripts/uncrustify.sh --check
|
||||
- scripts/uncrustify.sh
|
||||
- git diff
|
||||
- "! git status -s | grep -q ."
|
||||
|
||||
.flatpak_script_template: &flatpak_script
|
||||
script:
|
||||
@@ -77,9 +130,9 @@ test_indent:
|
||||
<<: *flatpak_script
|
||||
<<: *flatpak_artifacts
|
||||
|
||||
flatpak master:
|
||||
.flatpak_master_template: &flatpak_master
|
||||
image: registry.gitlab.gnome.org/gnome/gnome-runtime-images/gnome:3.32
|
||||
stage: flatpack
|
||||
stage: flatpak
|
||||
variables:
|
||||
MANIFEST_PATH: "demo/org.freedesktop.libfprint.Demo.json"
|
||||
# From demo/org.freedesktop.libfprint.Demo.json
|
||||
@@ -87,3 +140,31 @@ flatpak master:
|
||||
FLATPAK_MODULE: "libfprint"
|
||||
DBUS_ID: "org.freedesktop.libfprint.Demo"
|
||||
<<: *flatpak
|
||||
|
||||
flatpak-auto master:
|
||||
<<: *flatpak_master
|
||||
when: always
|
||||
only:
|
||||
- tags
|
||||
- master
|
||||
|
||||
flatpak-manual master:
|
||||
<<: *flatpak_master
|
||||
when: manual
|
||||
except:
|
||||
refs:
|
||||
- tags
|
||||
- master
|
||||
variables:
|
||||
- $CI_PIPELINE_SOURCE == "schedule"
|
||||
|
||||
# CONTAINERS creation stage
|
||||
container_fedora_build:
|
||||
extends: .fdo.container-build@fedora
|
||||
only:
|
||||
variables:
|
||||
- $CI_PIPELINE_SOURCE == "schedule" && $CRON_TASK == "BUILD_CI_IMAGES"
|
||||
variables:
|
||||
GIT_STRATEGY: none # no need to pull the whole tree for rebuilding the image
|
||||
# a list of packages to install
|
||||
FDO_DISTRIBUTION_PACKAGES: $LIBFPRINT_DEPENDENCIES
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
.libfprint_common_variables:
|
||||
LIBFPRINT_DEPENDENCIES:
|
||||
doxygen
|
||||
flatpak-builder
|
||||
gcc
|
||||
gcc-c++
|
||||
gcovr
|
||||
git
|
||||
glib2-devel
|
||||
glibc-devel
|
||||
gobject-introspection-devel
|
||||
gtk-doc
|
||||
gtk3-devel
|
||||
libabigail
|
||||
libgusb-devel
|
||||
libX11-devel
|
||||
libXv-devel
|
||||
meson
|
||||
nss-devel
|
||||
pixman-devel
|
||||
python3-cairo
|
||||
python3-gobject
|
||||
systemd
|
||||
umockdev
|
||||
uncrustify
|
||||
valgrind
|
||||
clang-analyzer
|
||||
Executable
+4
@@ -0,0 +1,4 @@
|
||||
#!/bin/sh
|
||||
|
||||
# This wrapper just disables the malloc checker
|
||||
exec /usr/bin/scan-build -disable-checker unix.Malloc "$@"
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
Current maintainers of libfprint are:
|
||||
|
||||
* Benjamin Berg <bberg@redhat.com>
|
||||
* Marco Trevisan (Treviño) <mail@3v1n0.net>
|
||||
|
||||
Many drivers are not actively maintained and may not be fully functional.
|
||||
We are happy to receive contributions, but the support we can give is
|
||||
limitted unfortunately. For many drivers we may not even have test devices.
|
||||
|
||||
Maintained drivers are:
|
||||
* synaptics:
|
||||
Contributed and maintained by Synaptics Inc.
|
||||
Contact: Vincent Huang <vincent.huang@tw.synaptics.com>
|
||||
@@ -1,6 +1,41 @@
|
||||
This file lists notable changes in each release. For the full history of all
|
||||
changes, see ChangeLog.
|
||||
|
||||
2019-11-20: v1.90.1 release
|
||||
|
||||
This release fixes a lot of the regressions introduced in 1.90.0. Please note
|
||||
that both the driver and external APIs have changed, as both the verify and
|
||||
the identify functions now have early reporting mechanisms.
|
||||
The soname for the library, as well as a number of file locations have also
|
||||
changed. While this allows installation in parallel with the 1.0 version of
|
||||
libfprint, we recommend installing only one, and migrating from version 1.0 to
|
||||
version 2.0 alongside its main consumer (fprintd).
|
||||
|
||||
Only major changes are listed below. A lot of other cleanup work and small
|
||||
fixes have also been merged.
|
||||
|
||||
* Library:
|
||||
- Add support to run tests in gdb/valgrind
|
||||
- Allow testing on all architectures
|
||||
- Avoid image device AWAIT_FINGER_ON to deactivate state transitions
|
||||
- Fix verify/identify error propagation to library user
|
||||
- Correctly read image device information from class data
|
||||
- Continue enroll after an image driver reported a retry error
|
||||
- Change external API to allow reporting match results early
|
||||
- A lot of new unit tests and integration tests have been added
|
||||
|
||||
* Drivers API
|
||||
- Support variadic arguments in error functions
|
||||
- Various re-definitions of ownership handling
|
||||
- Add convenience API to change state after a timeout
|
||||
- Add unit tests for all the drivers API
|
||||
|
||||
* Drivers:
|
||||
- elan: Ensure correct deactivation of device
|
||||
- uru4000: Fix IRQ handler registration and internal state handling
|
||||
- uru4000: Fix control transfer request type
|
||||
- synaptics: Ensure errors are only reported after finger removal
|
||||
|
||||
2019-11-20: v1.90.0 release
|
||||
|
||||
This release updates the core of the library to use GLib routines and Gio
|
||||
|
||||
@@ -22,9 +22,11 @@
|
||||
#include <gtk/gtk.h>
|
||||
#include <libfprint/fprint.h>
|
||||
|
||||
typedef GtkApplication LibfprintDemo;
|
||||
typedef GtkApplicationClass LibfprintDemoClass;
|
||||
|
||||
struct _LibfprintDemo
|
||||
{
|
||||
GtkApplication parent;
|
||||
};
|
||||
G_DECLARE_FINAL_TYPE (LibfprintDemo, libfprint_demo, FP, DEMO, GtkApplication)
|
||||
G_DEFINE_TYPE (LibfprintDemo, libfprint_demo, GTK_TYPE_APPLICATION)
|
||||
|
||||
typedef enum {
|
||||
@@ -33,7 +35,7 @@ typedef enum {
|
||||
IMAGE_DISPLAY_BINARY = 1 << 1
|
||||
} ImageDisplayFlags;
|
||||
|
||||
typedef struct
|
||||
struct _LibfprintDemoWindow
|
||||
{
|
||||
GtkApplicationWindow parent_instance;
|
||||
|
||||
@@ -52,10 +54,9 @@ typedef struct
|
||||
|
||||
FpImage *img;
|
||||
ImageDisplayFlags img_flags;
|
||||
} LibfprintDemoWindow;
|
||||
|
||||
typedef GtkApplicationWindowClass LibfprintDemoWindowClass;
|
||||
};
|
||||
|
||||
G_DECLARE_FINAL_TYPE (LibfprintDemoWindow, libfprint_demo_window, FP, DEMO_WINDOW, GtkApplicationWindow)
|
||||
G_DEFINE_TYPE (LibfprintDemoWindow, libfprint_demo_window, GTK_TYPE_APPLICATION_WINDOW)
|
||||
|
||||
typedef enum {
|
||||
|
||||
+6
-6
@@ -1,4 +1,5 @@
|
||||
gtk_test_resources = gnome.compile_resources('gtk-test-resources', 'gtk-libfprint-test.gresource.xml',
|
||||
gtk_test_resources = gnome.compile_resources('gtk-test-resources',
|
||||
'gtk-libfprint-test.gresource.xml',
|
||||
source_dir : '.',
|
||||
c_name : 'gtk_test')
|
||||
|
||||
@@ -8,12 +9,11 @@ datadir = join_paths(prefix, get_option('datadir'))
|
||||
|
||||
executable('gtk-libfprint-test',
|
||||
[ 'gtk-libfprint-test.c', gtk_test_resources ],
|
||||
dependencies: [ libfprint_dep, gtk_dep ],
|
||||
include_directories: [
|
||||
root_inc,
|
||||
dependencies: [
|
||||
gtk_dep,
|
||||
libfprint_dep,
|
||||
],
|
||||
c_args: [ common_cflags,
|
||||
'-DPACKAGE_VERSION="' + meson.project_version() + '"' ],
|
||||
c_args: '-DPACKAGE_VERSION="' + meson.project_version() + '"',
|
||||
install: true,
|
||||
install_dir: bindir)
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@ FpDeviceError
|
||||
fp_device_retry_quark
|
||||
fp_device_error_quark
|
||||
FpEnrollProgress
|
||||
FpMatchCb
|
||||
fp_device_get_driver
|
||||
fp_device_get_device_id
|
||||
fp_device_get_name
|
||||
@@ -129,7 +130,7 @@ fpi_get_driver_types
|
||||
<FILE>fpi-device</FILE>
|
||||
FpDeviceClass
|
||||
FpTimeoutFunc
|
||||
FpDeviceAction
|
||||
FpiDeviceAction
|
||||
FpIdEntry
|
||||
fpi_device_get_usb_device
|
||||
fpi_device_get_virtual_env
|
||||
@@ -159,6 +160,8 @@ fpi_device_identify_complete
|
||||
fpi_device_capture_complete
|
||||
fpi_device_delete_complete
|
||||
fpi_device_enroll_progress
|
||||
fpi_device_verify_report
|
||||
fpi_device_identify_report
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
@@ -172,8 +175,8 @@ fpi_image_resize
|
||||
|
||||
<SECTION>
|
||||
<FILE>fpi-image-device</FILE>
|
||||
<TITLE>FpImageDevice</TITLE>
|
||||
FpImageDeviceState
|
||||
<TITLE>Internal FpImageDevice</TITLE>
|
||||
FpiImageDeviceState
|
||||
FpImageDeviceClass
|
||||
fpi_image_device_session_error
|
||||
fpi_image_device_open_complete
|
||||
@@ -197,13 +200,15 @@ BUG
|
||||
|
||||
<SECTION>
|
||||
<FILE>fpi-print</FILE>
|
||||
FpPrintType
|
||||
FpiPrintType
|
||||
FpiMatchResult
|
||||
fpi_print_add_print
|
||||
fpi_print_set_type
|
||||
fpi_print_set_device_stored
|
||||
fpi_print_add_from_image
|
||||
fpi_print_bz3_match
|
||||
fpi_print_generate_user_id
|
||||
fpi_print_fill_from_user_id
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
@@ -211,11 +216,15 @@ fpi_print_bz3_match
|
||||
FpiSsmCompletedCallback
|
||||
FpiSsmHandlerCallback
|
||||
fpi_ssm_new
|
||||
fpi_ssm_new_full
|
||||
fpi_ssm_free
|
||||
fpi_ssm_start
|
||||
fpi_ssm_start_subsm
|
||||
fpi_ssm_next_state
|
||||
fpi_ssm_next_state_delayed
|
||||
fpi_ssm_jump_to_state
|
||||
fpi_ssm_jump_to_state_delayed
|
||||
fpi_ssm_cancel_delayed_state_change
|
||||
fpi_ssm_mark_completed
|
||||
fpi_ssm_mark_failed
|
||||
fpi_ssm_set_data
|
||||
@@ -90,7 +90,7 @@ fp_image_get_width
|
||||
<TITLE>Base class for image devices</TITLE>
|
||||
FpImageDevice
|
||||
FpImageDeviceClass
|
||||
FpImageDeviceState
|
||||
FpiImageDeviceState
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
@@ -114,5 +114,3 @@ FpUsbTransferCallback
|
||||
FP_USB_ENDPOINT_IN
|
||||
FP_USB_ENDPOINT_OUT
|
||||
</SECTION>
|
||||
|
||||
|
||||
|
||||
+2
-7
@@ -4,7 +4,6 @@ private_headers = [
|
||||
'config.h',
|
||||
'nbis-helpers.h',
|
||||
'fprint.h',
|
||||
'fp_internal.h',
|
||||
|
||||
# Subdirectories to ignore
|
||||
'drivers',
|
||||
@@ -24,17 +23,13 @@ glib_prefix = dependency('glib-2.0').get_pkgconfig_variable('prefix')
|
||||
glib_docpath = join_paths(glib_prefix, 'share', 'gtk-doc', 'html')
|
||||
docpath = join_paths(get_option('datadir'), 'gtk-doc', 'html')
|
||||
|
||||
gnome.gtkdoc('libfprint',
|
||||
gnome.gtkdoc(versioned_libname,
|
||||
main_xml: 'libfprint-docs.xml',
|
||||
src_dir: join_paths(meson.source_root(), 'libfprint'),
|
||||
dependencies: libfprint_dep,
|
||||
content_files: content_files,
|
||||
expand_content_files: expand_content_files,
|
||||
scan_args: [
|
||||
#'--rebuild-sections',
|
||||
'--ignore-decorators=API_EXPORTED',
|
||||
'--ignore-headers=' + ' '.join(private_headers),
|
||||
],
|
||||
ignore_headers: private_headers,
|
||||
fixxref_args: [
|
||||
'--html-dir=@0@'.format(docpath),
|
||||
'--extra-dir=@0@'.format(join_paths(glib_docpath, 'glib')),
|
||||
|
||||
+6
-4
@@ -1,10 +1,12 @@
|
||||
ent_conf = configuration_data()
|
||||
ent_conf.set('PACKAGE', 'libfprint')
|
||||
ent_conf.set('PACKAGE', versioned_libname)
|
||||
ent_conf.set('PACKAGE_BUGREPORT', 'https://gitlab.freedesktop.org/libfprint/libfprint/issues')
|
||||
ent_conf.set('PACKAGE_NAME', 'libfprint')
|
||||
ent_conf.set('PACKAGE_STRING', 'libfprint')
|
||||
ent_conf.set('PACKAGE_NAME', versioned_libname)
|
||||
ent_conf.set('PACKAGE_STRING', versioned_libname)
|
||||
ent_conf.set('PACKAGE_TARNAME', 'libfprint-' + meson.project_version())
|
||||
ent_conf.set('PACKAGE_URL', 'https://fprint.freedesktop.org/')
|
||||
ent_conf.set('PACKAGE_VERSION', meson.project_version())
|
||||
ent_conf.set('PACKAGE_API_VERSION', '1.0')
|
||||
configure_file(input: 'gtkdocentities.ent.in', output: 'gtkdocentities.ent', configuration: ent_conf)
|
||||
configure_file(input: 'gtkdocentities.ent.in',
|
||||
output: 'gtkdocentities.ent',
|
||||
configuration: ent_conf)
|
||||
|
||||
+29
-4
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Example fingerprint enrollment program
|
||||
* Enrolls your choosen finger and saves the print to disk
|
||||
* Enrolls your chosen finger and saves the print to disk
|
||||
* Copyright (C) 2007 Daniel Drake <dsd@gentoo.org>
|
||||
* Copyright (C) 2019 Marco Trevisan <marco.trevisan@canonical.com>
|
||||
*
|
||||
@@ -19,8 +19,11 @@
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#define FP_COMPONENT "example-enroll"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <libfprint/fprint.h>
|
||||
#include <glib-unix.h>
|
||||
|
||||
#include "storage.h"
|
||||
#include "utilities.h"
|
||||
@@ -28,6 +31,8 @@
|
||||
typedef struct _EnrollData
|
||||
{
|
||||
GMainLoop *loop;
|
||||
GCancellable *cancellable;
|
||||
unsigned int sigint_handler;
|
||||
FpFinger finger;
|
||||
int ret_value;
|
||||
} EnrollData;
|
||||
@@ -35,6 +40,8 @@ typedef struct _EnrollData
|
||||
static void
|
||||
enroll_data_free (EnrollData *enroll_data)
|
||||
{
|
||||
g_clear_handle_id (&enroll_data->sigint_handler, g_source_remove);
|
||||
g_clear_object (&enroll_data->cancellable);
|
||||
g_main_loop_unref (enroll_data->loop);
|
||||
g_free (enroll_data);
|
||||
}
|
||||
@@ -135,11 +142,22 @@ on_device_opened (FpDevice *dev, GAsyncResult *res, void *user_data)
|
||||
printf ("Scan your finger now.\n");
|
||||
|
||||
print_template = print_create_template (dev, enroll_data->finger);
|
||||
fp_device_enroll (dev, print_template, NULL, on_enroll_progress, NULL,
|
||||
NULL, (GAsyncReadyCallback) on_enroll_completed,
|
||||
fp_device_enroll (dev, print_template, enroll_data->cancellable,
|
||||
on_enroll_progress, NULL, NULL,
|
||||
(GAsyncReadyCallback) on_enroll_completed,
|
||||
enroll_data);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
sigint_cb (void *user_data)
|
||||
{
|
||||
EnrollData *enroll_data = user_data;
|
||||
|
||||
g_cancellable_cancel (enroll_data->cancellable);
|
||||
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
@@ -186,8 +204,15 @@ main (void)
|
||||
enroll_data->finger = finger;
|
||||
enroll_data->ret_value = EXIT_FAILURE;
|
||||
enroll_data->loop = g_main_loop_new (NULL, FALSE);
|
||||
enroll_data->cancellable = g_cancellable_new ();
|
||||
enroll_data->sigint_handler = g_unix_signal_add_full (G_PRIORITY_HIGH,
|
||||
SIGINT,
|
||||
sigint_cb,
|
||||
enroll_data,
|
||||
NULL);
|
||||
|
||||
fp_device_open (dev, NULL, (GAsyncReadyCallback) on_device_opened,
|
||||
fp_device_open (dev, enroll_data->cancellable,
|
||||
(GAsyncReadyCallback) on_device_opened,
|
||||
enroll_data);
|
||||
|
||||
g_main_loop_run (enroll_data->loop);
|
||||
|
||||
@@ -18,6 +18,8 @@
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#define FP_COMPONENT "example-mange-prints"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <libfprint/fprint.h>
|
||||
@@ -153,14 +155,19 @@ on_list_completed (FpDevice *dev,
|
||||
for (i = 0; i < prints->len; ++i)
|
||||
{
|
||||
FpPrint * print = prints->pdata[i];
|
||||
const GDate *date = fp_print_get_enroll_date (print);
|
||||
|
||||
g_date_strftime (buf, G_N_ELEMENTS (buf), "%Y-%m-%d",
|
||||
fp_print_get_enroll_date (print));
|
||||
g_print ("[%d] Print of %s finger for username %s, enrolled "
|
||||
"on %s. Description: %s\n", i + 1,
|
||||
g_print ("[%d] Print of %s finger for username %s", i + 1,
|
||||
finger_to_string (fp_print_get_finger (print)),
|
||||
fp_print_get_username (print), buf,
|
||||
fp_print_get_description (print));
|
||||
fp_print_get_username (print));
|
||||
|
||||
if (date)
|
||||
{
|
||||
g_date_strftime (buf, G_N_ELEMENTS (buf), "%Y-%m-%d\0", date);
|
||||
g_print (", enrolled on %s", buf);
|
||||
}
|
||||
|
||||
g_print (". Description: %s\n", fp_print_get_description (print));
|
||||
}
|
||||
|
||||
if (prints->len)
|
||||
@@ -192,9 +199,6 @@ on_list_completed (FpDevice *dev,
|
||||
list_data->ret_value = EXIT_SUCCESS;
|
||||
else
|
||||
g_warning ("Invalid finger selected");
|
||||
|
||||
fp_device_close (dev, NULL, (GAsyncReadyCallback) on_device_closed,
|
||||
list_data);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,17 +3,14 @@ examples = [ 'enroll', 'verify', 'manage-prints' ]
|
||||
foreach example: examples
|
||||
executable(example,
|
||||
[ example + '.c', 'storage.c', 'utilities.c' ],
|
||||
dependencies: [libfprint_dep, glib_dep],
|
||||
include_directories: [
|
||||
root_inc,
|
||||
dependencies: [
|
||||
libfprint_dep,
|
||||
glib_dep,
|
||||
],
|
||||
c_args: common_cflags)
|
||||
)
|
||||
endforeach
|
||||
|
||||
executable('cpp-test',
|
||||
'cpp-test.cpp',
|
||||
dependencies: libfprint_dep,
|
||||
include_directories: [
|
||||
root_inc,
|
||||
],
|
||||
c_args: common_cflags)
|
||||
)
|
||||
|
||||
+16
-8
@@ -19,7 +19,11 @@
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#define FP_COMPONENT "example-storage"
|
||||
|
||||
#include <libfprint/fprint.h>
|
||||
#include <libfprint/fpi-compat.h>
|
||||
#include "storage.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
@@ -56,8 +60,8 @@ load_data (void)
|
||||
{
|
||||
GVariantDict *res;
|
||||
GVariant *var;
|
||||
g_autofree gchar *contents = NULL;
|
||||
gssize length = 0;
|
||||
gchar *contents = NULL;
|
||||
gsize length = 0;
|
||||
|
||||
if (!g_file_get_contents (STORAGE_FILE, &contents, &length, NULL))
|
||||
{
|
||||
@@ -65,7 +69,12 @@ load_data (void)
|
||||
return g_variant_dict_new (NULL);
|
||||
}
|
||||
|
||||
var = g_variant_new_from_data (G_VARIANT_TYPE_VARDICT, contents, length, FALSE, NULL, NULL);
|
||||
var = g_variant_new_from_data (G_VARIANT_TYPE_VARDICT,
|
||||
contents,
|
||||
length,
|
||||
FALSE,
|
||||
g_free,
|
||||
contents);
|
||||
|
||||
res = g_variant_dict_new (var);
|
||||
g_variant_unref (var);
|
||||
@@ -128,7 +137,7 @@ print_data_load (FpDevice *dev, FpFinger finger)
|
||||
|
||||
g_autoptr(GVariant) val = NULL;
|
||||
g_autoptr(GVariantDict) dict = NULL;
|
||||
g_autofree guchar *stored_data = NULL;
|
||||
const guchar *stored_data = NULL;
|
||||
gsize stored_len;
|
||||
|
||||
dict = load_data ();
|
||||
@@ -139,7 +148,7 @@ print_data_load (FpDevice *dev, FpFinger finger)
|
||||
FpPrint *print;
|
||||
g_autoptr(GError) error = NULL;
|
||||
|
||||
stored_data = (guchar *) g_variant_get_fixed_array (val, &stored_len, 1);
|
||||
stored_data = (const guchar *) g_variant_get_fixed_array (val, &stored_len, 1);
|
||||
print = fp_print_deserialize (stored_data, stored_len, &error);
|
||||
|
||||
if (error)
|
||||
@@ -155,8 +164,8 @@ FpPrint *
|
||||
print_create_template (FpDevice *dev, FpFinger finger)
|
||||
{
|
||||
g_autoptr(GDateTime) datetime = NULL;
|
||||
g_autoptr(GDate) date = NULL;
|
||||
FpPrint *template = NULL;
|
||||
GDate *date = NULL;
|
||||
gint year, month, day;
|
||||
|
||||
template = fp_print_new (dev);
|
||||
@@ -166,7 +175,6 @@ print_create_template (FpDevice *dev, FpFinger finger)
|
||||
g_date_time_get_ymd (datetime, &year, &month, &day);
|
||||
date = g_date_new_dmy (day, month, year);
|
||||
fp_print_set_enroll_date (template, date);
|
||||
g_date_free (date);
|
||||
|
||||
return template;
|
||||
}
|
||||
@@ -212,7 +220,7 @@ save_image_to_pgm (FpImage *img, const char *path)
|
||||
gboolean
|
||||
print_image_save (FpPrint *print, const char *path)
|
||||
{
|
||||
g_autoptr(FpImage) img = NULL;
|
||||
FpImage *img = NULL;
|
||||
|
||||
g_return_val_if_fail (FP_IS_PRINT (print), FALSE);
|
||||
g_return_val_if_fail (path != NULL, FALSE);
|
||||
|
||||
+1
-5
@@ -18,9 +18,7 @@
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef __STORAGE_H
|
||||
#define __STORAGE_H
|
||||
|
||||
#pragma once
|
||||
|
||||
int print_data_save (FpPrint *print,
|
||||
FpFinger finger);
|
||||
@@ -30,5 +28,3 @@ FpPrint * print_create_template (FpDevice *dev,
|
||||
FpFinger finger);
|
||||
gboolean print_image_save (FpPrint *print,
|
||||
const char *path);
|
||||
|
||||
#endif /* __STORAGE_H */
|
||||
|
||||
+9
-17
@@ -18,6 +18,8 @@
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#define FP_COMPONENT "example-utilities"
|
||||
|
||||
#include <libfprint/fprint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
@@ -107,29 +109,19 @@ finger_to_string (FpFinger finger)
|
||||
FpFinger
|
||||
finger_chooser (void)
|
||||
{
|
||||
int i;
|
||||
const FpFinger all_fingers[] = {
|
||||
FP_FINGER_LEFT_THUMB,
|
||||
FP_FINGER_LEFT_INDEX,
|
||||
FP_FINGER_LEFT_MIDDLE,
|
||||
FP_FINGER_LEFT_RING,
|
||||
FP_FINGER_LEFT_LITTLE,
|
||||
FP_FINGER_RIGHT_THUMB,
|
||||
FP_FINGER_RIGHT_INDEX,
|
||||
FP_FINGER_RIGHT_MIDDLE,
|
||||
FP_FINGER_RIGHT_RING,
|
||||
FP_FINGER_RIGHT_LITTLE,
|
||||
};
|
||||
int i = FP_FINGER_UNKNOWN;
|
||||
|
||||
for (i = all_fingers[0]; i <= G_N_ELEMENTS (all_fingers); ++i)
|
||||
g_print (" [%d] %s\n", (i - all_fingers[0]), finger_to_string (i));
|
||||
for (i = FP_FINGER_FIRST; i <= FP_FINGER_LAST; ++i)
|
||||
g_print (" [%d] %s\n", (i - FP_FINGER_FIRST), finger_to_string (i));
|
||||
|
||||
g_print ("> ");
|
||||
if (!scanf ("%d%*c", &i))
|
||||
return FP_FINGER_UNKNOWN;
|
||||
|
||||
if (i < 0 || i >= G_N_ELEMENTS (all_fingers))
|
||||
i += FP_FINGER_FIRST;
|
||||
|
||||
if (i < FP_FINGER_FIRST || i > FP_FINGER_LAST)
|
||||
return FP_FINGER_UNKNOWN;
|
||||
|
||||
return all_fingers[i];
|
||||
return i;
|
||||
}
|
||||
|
||||
@@ -18,11 +18,8 @@
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef __UTILITIES_H
|
||||
#define __UTILITIES_H
|
||||
#pragma once
|
||||
|
||||
FpDevice * discover_device (GPtrArray *devices);
|
||||
FpFinger finger_chooser (void);
|
||||
const char * finger_to_string (FpFinger finger);
|
||||
|
||||
#endif /* __UTILITIES_H */
|
||||
|
||||
+107
-31
@@ -19,8 +19,11 @@
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#define FP_COMPONENT "example-verify"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <libfprint/fprint.h>
|
||||
#include <glib-unix.h>
|
||||
|
||||
#include "storage.h"
|
||||
#include "utilities.h"
|
||||
@@ -28,6 +31,8 @@
|
||||
typedef struct _VerifyData
|
||||
{
|
||||
GMainLoop *loop;
|
||||
GCancellable *cancellable;
|
||||
unsigned int sigint_handler;
|
||||
FpFinger finger;
|
||||
int ret_value;
|
||||
} VerifyData;
|
||||
@@ -35,6 +40,8 @@ typedef struct _VerifyData
|
||||
static void
|
||||
verify_data_free (VerifyData *verify_data)
|
||||
{
|
||||
g_clear_handle_id (&verify_data->sigint_handler, g_source_remove);
|
||||
g_clear_object (&verify_data->cancellable);
|
||||
g_main_loop_unref (verify_data->loop);
|
||||
g_free (verify_data);
|
||||
}
|
||||
@@ -55,6 +62,19 @@ on_device_closed (FpDevice *dev, GAsyncResult *res, void *user_data)
|
||||
g_main_loop_quit (verify_data->loop);
|
||||
}
|
||||
|
||||
static void
|
||||
verify_quit (FpDevice *dev,
|
||||
VerifyData *verify_data)
|
||||
{
|
||||
if (!fp_device_is_open (dev))
|
||||
{
|
||||
g_main_loop_quit (verify_data->loop);
|
||||
return;
|
||||
}
|
||||
|
||||
fp_device_close (dev, NULL, (GAsyncReadyCallback) on_device_closed, verify_data);
|
||||
}
|
||||
|
||||
static void start_verification (FpDevice *dev,
|
||||
VerifyData *verify_data);
|
||||
|
||||
@@ -71,35 +91,65 @@ on_verify_completed (FpDevice *dev, GAsyncResult *res, void *user_data)
|
||||
if (!fp_device_verify_finish (dev, res, &match, &print, &error))
|
||||
{
|
||||
g_warning ("Failed to verify print: %s", error->message);
|
||||
g_main_loop_quit (verify_data->loop);
|
||||
verify_data->ret_value = EXIT_FAILURE;
|
||||
|
||||
if (error->domain != FP_DEVICE_RETRY)
|
||||
{
|
||||
verify_quit (dev, verify_data);
|
||||
return;
|
||||
}
|
||||
|
||||
if (match)
|
||||
{
|
||||
g_print ("MATCH!\n");
|
||||
if (fp_device_supports_capture (dev) &&
|
||||
print_image_save (print, "verify.pgm"))
|
||||
g_print ("Print image saved as verify.pgm");
|
||||
|
||||
verify_data->ret_value = EXIT_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_print ("NO MATCH!\n");
|
||||
verify_data->ret_value = EXIT_FAILURE;
|
||||
}
|
||||
|
||||
g_print ("Verify again? [Y/n]? ");
|
||||
if (fgets (buffer, sizeof (buffer), stdin) &&
|
||||
(buffer[0] == 'Y' || buffer[0] == 'y'))
|
||||
(buffer[0] == 'Y' || buffer[0] == 'y' || buffer[0] == '\n'))
|
||||
{
|
||||
start_verification (dev, verify_data);
|
||||
return;
|
||||
}
|
||||
|
||||
fp_device_close (dev, NULL, (GAsyncReadyCallback) on_device_closed,
|
||||
verify_data);
|
||||
verify_quit (dev, verify_data);
|
||||
}
|
||||
|
||||
static void
|
||||
on_match_cb (FpDevice *dev, FpPrint *match, FpPrint *print,
|
||||
gpointer user_data, GError *error)
|
||||
{
|
||||
VerifyData *verify_data = user_data;
|
||||
|
||||
if (error)
|
||||
{
|
||||
g_warning ("Match report: Finger not matched, retry error reported: %s",
|
||||
error->message);
|
||||
return;
|
||||
}
|
||||
|
||||
if (print && fp_device_supports_capture (dev) &&
|
||||
print_image_save (print, "verify.pgm"))
|
||||
g_print ("Print image saved as verify.pgm\n");
|
||||
|
||||
if (match)
|
||||
{
|
||||
char date_str[128];
|
||||
|
||||
verify_data->ret_value = EXIT_SUCCESS;
|
||||
|
||||
g_date_strftime (date_str, G_N_ELEMENTS (date_str), "%Y-%m-%d\0",
|
||||
fp_print_get_enroll_date (match));
|
||||
g_debug ("Match report: device %s matched finger %s successifully "
|
||||
"with print %s, enrolled on date %s by user %s",
|
||||
fp_device_get_name (dev),
|
||||
finger_to_string (fp_print_get_finger (match)),
|
||||
fp_print_get_description (match), date_str,
|
||||
fp_print_get_username (match));
|
||||
|
||||
g_print ("MATCH!\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
g_debug ("Match report: Finger not matched");
|
||||
g_print ("NO MATCH!\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -127,9 +177,14 @@ on_list_completed (FpDevice *dev, GAsyncResult *res, gpointer user_data)
|
||||
if (fp_print_get_finger (print) == verify_data->finger &&
|
||||
g_strcmp0 (fp_print_get_username (print), g_get_user_name ()) == 0)
|
||||
{
|
||||
if (!verify_print ||
|
||||
(g_date_compare (fp_print_get_enroll_date (print),
|
||||
fp_print_get_enroll_date (verify_print)) >= 0))
|
||||
const GDate *verify_print_date = NULL;
|
||||
const GDate *print_date = fp_print_get_enroll_date (print);
|
||||
|
||||
if (verify_print)
|
||||
verify_print_date = fp_print_get_enroll_date (verify_print);
|
||||
|
||||
if (!verify_print || !print_date || !verify_print_date ||
|
||||
g_date_compare (print_date, verify_print_date) >= 0)
|
||||
verify_print = print;
|
||||
}
|
||||
}
|
||||
@@ -138,7 +193,7 @@ on_list_completed (FpDevice *dev, GAsyncResult *res, gpointer user_data)
|
||||
{
|
||||
g_warning ("Did you remember to enroll your %s finger first?",
|
||||
finger_to_string (verify_data->finger));
|
||||
g_main_loop_quit (verify_data->loop);
|
||||
verify_quit (dev, verify_data);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -146,28 +201,32 @@ on_list_completed (FpDevice *dev, GAsyncResult *res, gpointer user_data)
|
||||
fp_print_get_description (verify_print));
|
||||
|
||||
g_print ("Print loaded. Time to verify!\n");
|
||||
fp_device_verify (dev, verify_print, NULL,
|
||||
fp_device_verify (dev, verify_print, verify_data->cancellable,
|
||||
on_match_cb, verify_data, NULL,
|
||||
(GAsyncReadyCallback) on_verify_completed,
|
||||
verify_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_warning ("Loading prints failed with error %s", error->message);
|
||||
g_main_loop_quit (verify_data->loop);
|
||||
verify_quit (dev, verify_data);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
start_verification (FpDevice *dev, VerifyData *verify_data)
|
||||
{
|
||||
if (verify_data->finger == FP_FINGER_UNKNOWN)
|
||||
{
|
||||
g_print ("Choose the finger to verify:\n");
|
||||
verify_data->finger = finger_chooser ();
|
||||
}
|
||||
|
||||
if (verify_data->finger == FP_FINGER_UNKNOWN)
|
||||
{
|
||||
g_warning ("Unknown finger selected");
|
||||
verify_data->ret_value = EXIT_FAILURE;
|
||||
g_main_loop_quit (verify_data->loop);
|
||||
verify_quit (dev, verify_data);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -182,7 +241,7 @@ start_verification (FpDevice *dev, VerifyData *verify_data)
|
||||
{
|
||||
g_print ("Loading previously enrolled %s finger data...\n",
|
||||
finger_to_string (verify_data->finger));
|
||||
g_autoptr(FpPrint) verify_print;
|
||||
g_autoptr(FpPrint) verify_print = NULL;
|
||||
|
||||
verify_print = print_data_load (dev, verify_data->finger);
|
||||
|
||||
@@ -191,12 +250,13 @@ start_verification (FpDevice *dev, VerifyData *verify_data)
|
||||
g_warning ("Failed to load fingerprint data");
|
||||
g_warning ("Did you remember to enroll your %s finger first?",
|
||||
finger_to_string (verify_data->finger));
|
||||
g_main_loop_quit (verify_data->loop);
|
||||
verify_quit (dev, verify_data);
|
||||
return;
|
||||
}
|
||||
|
||||
g_print ("Print loaded. Time to verify!\n");
|
||||
fp_device_verify (dev, verify_print, NULL,
|
||||
fp_device_verify (dev, verify_print, verify_data->cancellable,
|
||||
NULL, NULL, NULL,
|
||||
(GAsyncReadyCallback) on_verify_completed,
|
||||
verify_data);
|
||||
}
|
||||
@@ -212,7 +272,7 @@ on_device_opened (FpDevice *dev, GAsyncResult *res, void *user_data)
|
||||
if (!fp_device_open_finish (dev, res, &error))
|
||||
{
|
||||
g_warning ("Failed to open device: %s", error->message);
|
||||
g_main_loop_quit (verify_data->loop);
|
||||
verify_quit (dev, verify_data);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -221,6 +281,16 @@ on_device_opened (FpDevice *dev, GAsyncResult *res, void *user_data)
|
||||
start_verification (dev, verify_data);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
sigint_cb (void *user_data)
|
||||
{
|
||||
VerifyData *verify_data = user_data;
|
||||
|
||||
g_cancellable_cancel (verify_data->cancellable);
|
||||
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
@@ -251,8 +321,14 @@ main (void)
|
||||
verify_data = g_new0 (VerifyData, 1);
|
||||
verify_data->ret_value = EXIT_FAILURE;
|
||||
verify_data->loop = g_main_loop_new (NULL, FALSE);
|
||||
|
||||
fp_device_open (dev, NULL, (GAsyncReadyCallback) on_device_opened,
|
||||
verify_data->cancellable = g_cancellable_new ();
|
||||
verify_data->sigint_handler = g_unix_signal_add_full (G_PRIORITY_HIGH,
|
||||
SIGINT,
|
||||
sigint_cb,
|
||||
verify_data,
|
||||
NULL);
|
||||
fp_device_open (dev, verify_data->cancellable,
|
||||
(GAsyncReadyCallback) on_device_opened,
|
||||
verify_data);
|
||||
|
||||
g_main_loop_run (verify_data->loop);
|
||||
|
||||
@@ -116,18 +116,6 @@ stub_capture_stop_cb (FpImageDevice *dev, GError *error,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* check that read succeeded but ignore all data */
|
||||
static void
|
||||
generic_ignore_data_cb (FpiUsbTransfer *transfer, FpDevice *device,
|
||||
gpointer user_data, GError *error)
|
||||
{
|
||||
if (error)
|
||||
fpi_ssm_mark_failed (transfer->ssm, error);
|
||||
else
|
||||
fpi_ssm_next_state (transfer->ssm);
|
||||
}
|
||||
|
||||
static void
|
||||
generic_write_regv_cb (FpImageDevice *dev, GError *error,
|
||||
void *user_data)
|
||||
@@ -150,12 +138,11 @@ generic_read_ignore_data (FpiSsm *ssm, FpDevice *dev,
|
||||
unsigned char *data;
|
||||
|
||||
data = g_malloc (bytes);
|
||||
fpi_usb_transfer_fill_bulk_full (transfer, EP_IN, data, bytes, NULL);
|
||||
fpi_usb_transfer_fill_bulk_full (transfer, EP_IN, data, bytes, g_free);
|
||||
transfer->ssm = ssm;
|
||||
transfer->short_is_error = TRUE;
|
||||
fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
|
||||
generic_ignore_data_cb, NULL);
|
||||
fpi_usb_transfer_unref (transfer);
|
||||
fpi_ssm_usb_transfer_cb, NULL);
|
||||
}
|
||||
|
||||
/****** FINGER PRESENCE DETECTION ******/
|
||||
@@ -238,7 +225,6 @@ finger_det_reqs_cb (FpImageDevice *dev, GError *error,
|
||||
transfer->short_is_error = TRUE;
|
||||
fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
|
||||
finger_det_data_cb, NULL);
|
||||
fpi_usb_transfer_unref (transfer);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -628,6 +614,7 @@ capture_read_strip_cb (FpiUsbTransfer *transfer, FpDevice *device,
|
||||
self->strips = g_slist_reverse (self->strips);
|
||||
fpi_do_movement_estimation (&assembling_ctx, self->strips);
|
||||
img = fpi_assemble_frames (&assembling_ctx, self->strips);
|
||||
img->flags |= FPI_IMAGE_PARTIAL;
|
||||
|
||||
g_slist_free_full (self->strips, g_free);
|
||||
self->strips = NULL;
|
||||
@@ -683,7 +670,6 @@ capture_run_state (FpiSsm *ssm, FpDevice *_dev)
|
||||
transfer->short_is_error = TRUE;
|
||||
fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
|
||||
capture_read_strip_cb, NULL);
|
||||
fpi_usb_transfer_unref (transfer);
|
||||
break;
|
||||
}
|
||||
;
|
||||
@@ -710,7 +696,6 @@ capture_sm_complete (FpiSsm *ssm, FpDevice *_dev, GError *error)
|
||||
{
|
||||
start_finger_detection (dev);
|
||||
}
|
||||
fpi_ssm_free (ssm);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -774,7 +759,6 @@ activate_sm_complete (FpiSsm *ssm, FpDevice *_dev, GError *error)
|
||||
|
||||
if (!error)
|
||||
start_finger_detection (dev);
|
||||
fpi_ssm_free (ssm);
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
@@ -18,8 +18,7 @@
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef __AES1660_H
|
||||
#define __AES1660_H
|
||||
#pragma once
|
||||
|
||||
#define AES1660_FRAME_SIZE 0x244
|
||||
|
||||
@@ -1986,5 +1985,3 @@ static const unsigned char aes1660_start_imaging_cmd[] = {
|
||||
0x55, 0x07, 0x00, 0x80, 0x42, 0x00, 0x7f, 0x00, 0x00, 0x14,
|
||||
0x49, 0x03, 0x00, 0x20, 0x00, 0xc8
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -126,7 +126,6 @@ read_regs_rq_cb (FpImageDevice *dev, GError *error, void *user_data)
|
||||
fpi_usb_transfer_fill_bulk (transfer, EP_IN, READ_REGS_LEN);
|
||||
fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
|
||||
read_regs_data_cb, rdata);
|
||||
fpi_usb_transfer_unref (transfer);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -183,19 +182,6 @@ generic_write_regv_cb (FpImageDevice *dev, GError *error,
|
||||
fpi_ssm_mark_failed (ssm, error);
|
||||
}
|
||||
|
||||
/* check that read succeeded but ignore all data */
|
||||
static void
|
||||
generic_ignore_data_cb (FpiUsbTransfer *transfer, FpDevice *dev,
|
||||
gpointer user_data, GError *error)
|
||||
{
|
||||
FpiSsm *ssm = transfer->ssm;
|
||||
|
||||
if (error)
|
||||
fpi_ssm_mark_failed (ssm, error);
|
||||
else
|
||||
fpi_ssm_next_state (ssm);
|
||||
}
|
||||
|
||||
/* read the specified number of bytes from the IN endpoint but throw them
|
||||
* away, then increment the SSM */
|
||||
static void
|
||||
@@ -209,8 +195,7 @@ generic_read_ignore_data (FpiSsm *ssm, FpDevice *dev,
|
||||
transfer->short_is_error = TRUE;
|
||||
fpi_usb_transfer_fill_bulk (transfer, EP_IN, bytes);
|
||||
fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
|
||||
generic_ignore_data_cb, NULL);
|
||||
fpi_usb_transfer_unref (transfer);
|
||||
fpi_ssm_usb_transfer_cb, NULL);
|
||||
}
|
||||
|
||||
/****** IMAGE PROCESSING ******/
|
||||
@@ -315,7 +300,6 @@ finger_det_reqs_cb (FpImageDevice *dev, GError *error,
|
||||
fpi_usb_transfer_fill_bulk (transfer, EP_IN, FINGER_DETECTION_LEN);
|
||||
fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
|
||||
finger_det_data_cb, NULL);
|
||||
fpi_usb_transfer_unref (transfer);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -474,6 +458,7 @@ capture_read_strip_cb (FpiUsbTransfer *transfer, FpDevice *_dev,
|
||||
fpi_do_movement_estimation (&assembling_ctx, self->strips);
|
||||
img = fpi_assemble_frames (&assembling_ctx,
|
||||
self->strips);
|
||||
img->flags |= FPI_IMAGE_PARTIAL;
|
||||
g_slist_free_full (self->strips, g_free);
|
||||
self->strips = NULL;
|
||||
self->strips_len = 0;
|
||||
@@ -547,7 +532,6 @@ capture_run_state (FpiSsm *ssm, FpDevice *device)
|
||||
fpi_usb_transfer_fill_bulk (transfer, EP_IN, STRIP_CAPTURE_LEN);
|
||||
fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
|
||||
capture_read_strip_cb, NULL);
|
||||
fpi_usb_transfer_unref (transfer);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -575,7 +559,6 @@ capture_sm_complete (FpiSsm *ssm, FpDevice *_dev, GError *error)
|
||||
{
|
||||
start_finger_detection (dev);
|
||||
}
|
||||
fpi_ssm_free (ssm);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -704,7 +687,7 @@ enum activate_states {
|
||||
ACTIVATE_NUM_STATES,
|
||||
};
|
||||
|
||||
void
|
||||
static void
|
||||
activate_read_regs_cb (FpImageDevice *dev, GError *error,
|
||||
unsigned char *regs, void *user_data)
|
||||
{
|
||||
@@ -806,7 +789,6 @@ activate_sm_complete (FpiSsm *ssm, FpDevice *dev, GError *error)
|
||||
|
||||
if (!error)
|
||||
start_finger_detection (FP_IMAGE_DEVICE (dev));
|
||||
fpi_ssm_free (ssm);
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
@@ -19,8 +19,7 @@
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef __AES2501_H
|
||||
#define __AES2501_H
|
||||
#pragma once
|
||||
|
||||
enum aes2501_regs {
|
||||
AES2501_REG_CTRL1 = 0x80,
|
||||
@@ -172,5 +171,3 @@ enum aes2501_sensor_gain2 {
|
||||
|
||||
#define AES2501_SUM_HIGH_THRESH 1000
|
||||
#define AES2501_SUM_LOW_THRESH 700
|
||||
|
||||
#endif /* __AES2501_H */
|
||||
|
||||
@@ -134,7 +134,6 @@ finger_det_reqs_cb (FpiUsbTransfer *t, FpDevice *device,
|
||||
fpi_usb_transfer_fill_bulk (transfer, EP_IN, AES2550_EP_IN_BUF_SIZE);
|
||||
fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
|
||||
finger_det_data_cb, NULL);
|
||||
fpi_usb_transfer_unref (transfer);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -157,7 +156,6 @@ start_finger_detection (FpImageDevice *dev)
|
||||
sizeof (finger_det_reqs), NULL);
|
||||
fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
|
||||
finger_det_reqs_cb, NULL);
|
||||
fpi_usb_transfer_unref (transfer);
|
||||
}
|
||||
|
||||
/****** CAPTURE ******/
|
||||
@@ -218,16 +216,6 @@ process_strip_data (FpiSsm *ssm, FpImageDevice *dev,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
capture_reqs_cb (FpiUsbTransfer *transfer, FpDevice *device,
|
||||
gpointer user_data, GError *error)
|
||||
{
|
||||
if (!error)
|
||||
fpi_ssm_next_state (transfer->ssm);
|
||||
else
|
||||
fpi_ssm_mark_failed (transfer->ssm, error);
|
||||
}
|
||||
|
||||
static void
|
||||
capture_set_idle_reqs_cb (FpiUsbTransfer *transfer,
|
||||
FpDevice *device, gpointer user_data,
|
||||
@@ -242,6 +230,7 @@ capture_set_idle_reqs_cb (FpiUsbTransfer *transfer,
|
||||
|
||||
self->strips = g_slist_reverse (self->strips);
|
||||
img = fpi_assemble_frames (&assembling_ctx, self->strips);
|
||||
img->flags |= FPI_IMAGE_PARTIAL;
|
||||
g_slist_free_full (self->strips, g_free);
|
||||
self->strips = NULL;
|
||||
self->strips_len = 0;
|
||||
@@ -334,8 +323,7 @@ capture_run_state (FpiSsm *ssm, FpDevice *dev)
|
||||
transfer->ssm = ssm;
|
||||
transfer->short_is_error = TRUE;
|
||||
fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
|
||||
capture_reqs_cb, NULL);
|
||||
fpi_usb_transfer_unref (transfer);
|
||||
fpi_ssm_usb_transfer_cb, NULL);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -347,7 +335,6 @@ capture_run_state (FpiSsm *ssm, FpDevice *dev)
|
||||
transfer->ssm = ssm;
|
||||
fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
|
||||
capture_read_data_cb, NULL);
|
||||
fpi_usb_transfer_unref (transfer);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -363,7 +350,6 @@ capture_run_state (FpiSsm *ssm, FpDevice *dev)
|
||||
transfer->short_is_error = TRUE;
|
||||
fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
|
||||
capture_set_idle_reqs_cb, NULL);
|
||||
fpi_usb_transfer_unref (transfer);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -391,7 +377,6 @@ capture_sm_complete (FpiSsm *ssm, FpDevice *_dev, GError *error)
|
||||
{
|
||||
start_finger_detection (dev);
|
||||
}
|
||||
fpi_ssm_free (ssm);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -436,36 +421,13 @@ enum activate_states {
|
||||
ACTIVATE_NUM_STATES,
|
||||
};
|
||||
|
||||
static void
|
||||
init_reqs_cb (FpiUsbTransfer *transfer, FpDevice *device,
|
||||
gpointer user_data, GError *error)
|
||||
{
|
||||
if (!error)
|
||||
fpi_ssm_next_state (transfer->ssm);
|
||||
else
|
||||
fpi_ssm_mark_failed (transfer->ssm, error);
|
||||
}
|
||||
|
||||
static void
|
||||
init_read_data_cb (FpiUsbTransfer *transfer, FpDevice *device,
|
||||
gpointer user_data, GError *error)
|
||||
{
|
||||
if (!error)
|
||||
fpi_ssm_next_state (transfer->ssm);
|
||||
else
|
||||
fpi_ssm_mark_failed (transfer->ssm, error);
|
||||
}
|
||||
|
||||
/* TODO: use calibration table, datasheet is rather terse on that
|
||||
* need more info for implementation */
|
||||
static void
|
||||
calibrate_read_data_cb (FpiUsbTransfer *transfer, FpDevice *device,
|
||||
gpointer user_data, GError *error)
|
||||
{
|
||||
if (!error)
|
||||
fpi_ssm_next_state (transfer->ssm);
|
||||
else
|
||||
fpi_ssm_mark_failed (transfer->ssm, error);
|
||||
fpi_ssm_usb_transfer_cb (transfer, device, user_data, error);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -482,8 +444,7 @@ activate_run_state (FpiSsm *ssm, FpDevice *dev)
|
||||
transfer->ssm = ssm;
|
||||
transfer->short_is_error = TRUE;
|
||||
fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
|
||||
init_reqs_cb, NULL);
|
||||
fpi_usb_transfer_unref (transfer);
|
||||
fpi_ssm_usb_transfer_cb, NULL);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -494,8 +455,7 @@ activate_run_state (FpiSsm *ssm, FpDevice *dev)
|
||||
fpi_usb_transfer_fill_bulk (transfer, EP_IN, AES2550_EP_IN_BUF_SIZE);
|
||||
transfer->ssm = ssm;
|
||||
fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
|
||||
init_read_data_cb, NULL);
|
||||
fpi_usb_transfer_unref (transfer);
|
||||
fpi_ssm_usb_transfer_cb, NULL);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -509,8 +469,7 @@ activate_run_state (FpiSsm *ssm, FpDevice *dev)
|
||||
transfer->ssm = ssm;
|
||||
transfer->short_is_error = TRUE;
|
||||
fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
|
||||
init_reqs_cb, NULL);
|
||||
fpi_usb_transfer_unref (transfer);
|
||||
fpi_ssm_usb_transfer_cb, NULL);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -522,7 +481,6 @@ activate_run_state (FpiSsm *ssm, FpDevice *dev)
|
||||
transfer->ssm = ssm;
|
||||
fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
|
||||
calibrate_read_data_cb, NULL);
|
||||
fpi_usb_transfer_unref (transfer);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -537,7 +495,6 @@ activate_sm_complete (FpiSsm *ssm, FpDevice *_dev, GError *error)
|
||||
|
||||
if (!error)
|
||||
start_finger_detection (dev);
|
||||
fpi_ssm_free (ssm);
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
@@ -17,8 +17,7 @@
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef __AES2550_H
|
||||
#define __AES2550_H
|
||||
#pragma once
|
||||
|
||||
/* Registers bits */
|
||||
|
||||
@@ -110,5 +109,3 @@ enum aes2550_cmds {
|
||||
#define AES2550_HEARTBEAT_MAGIC 0xdb
|
||||
|
||||
#define AES2550_EP_IN_BUF_SIZE 8192
|
||||
|
||||
#endif
|
||||
|
||||
@@ -17,8 +17,7 @@
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef __AES2660_H
|
||||
#define __AES2660_H
|
||||
#pragma once
|
||||
|
||||
#define AES2660_FRAME_SIZE 0x354
|
||||
|
||||
@@ -1960,5 +1959,3 @@ static const unsigned char aes2660_start_imaging_cmd[] = {
|
||||
0x55, 0x07, 0x00, 0x80, 0x42, 0x00, 0xbf, 0x00, 0x00, 0x18,
|
||||
0x49, 0x03, 0x00, 0x20, 0x08, 0xc8
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -142,7 +142,6 @@ do_capture (FpImageDevice *dev)
|
||||
fpi_usb_transfer_submit (priv->img_trf, 0,
|
||||
fpi_device_get_cancellable (FP_DEVICE (dev)),
|
||||
img_cb, NULL);
|
||||
fpi_usb_transfer_unref (priv->img_trf);
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
@@ -19,13 +19,11 @@
|
||||
|
||||
#define FP_COMPONENT "aeslib"
|
||||
|
||||
#include "fp_internal.h"
|
||||
#include "drivers_api.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "fpi-usb-transfer.h"
|
||||
#include "fpi-assembling.h"
|
||||
#include "aeslib.h"
|
||||
|
||||
#define MAX_REGWRITES_PER_REQUEST 16
|
||||
@@ -88,7 +86,6 @@ do_write_regv (FpImageDevice *dev, struct write_regv_data *wdata, int upper_boun
|
||||
transfer->short_is_error = TRUE;
|
||||
fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
|
||||
write_regv_trf_complete, wdata);
|
||||
fpi_usb_transfer_unref (transfer);
|
||||
}
|
||||
|
||||
/* write the next batch of registers to be written, or if there are no more,
|
||||
|
||||
@@ -17,8 +17,7 @@
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef __AESLIB_H__
|
||||
#define __AESLIB_H__
|
||||
#pragma once
|
||||
|
||||
#include <fprint.h>
|
||||
|
||||
@@ -45,5 +44,3 @@ unsigned char aes_get_pixel (struct fpi_frame_asmbl_ctx *ctx,
|
||||
struct fpi_frame *frame,
|
||||
unsigned int x,
|
||||
unsigned int y);
|
||||
|
||||
#endif
|
||||
|
||||
+20
-28
@@ -68,7 +68,6 @@ aesX660_send_cmd_timeout (FpiSsm *ssm,
|
||||
cmd_len, NULL);
|
||||
transfer->ssm = ssm;
|
||||
fpi_usb_transfer_submit (transfer, timeout, NULL, callback, NULL);
|
||||
fpi_usb_transfer_unref (transfer);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -100,17 +99,6 @@ aesX660_read_response (FpiSsm *ssm,
|
||||
transfer->ssm = ssm;
|
||||
transfer->short_is_error = short_is_error;
|
||||
fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, cancel, callback, NULL);
|
||||
fpi_usb_transfer_unref (transfer);
|
||||
}
|
||||
|
||||
static void
|
||||
aesX660_send_cmd_cb (FpiUsbTransfer *transfer, FpDevice *device,
|
||||
gpointer user_data, GError *error)
|
||||
{
|
||||
if (!error)
|
||||
fpi_ssm_next_state (transfer->ssm);
|
||||
else
|
||||
fpi_ssm_mark_failed (transfer->ssm, error);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -131,7 +119,9 @@ aesX660_read_calibrate_data_cb (FpiUsbTransfer *transfer,
|
||||
fp_dbg ("Bogus calibrate response: %.2x\n", data[0]);
|
||||
fpi_ssm_mark_failed (transfer->ssm,
|
||||
fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
|
||||
"Bogus calibrate response"));
|
||||
"Bogus calibrate "
|
||||
"response: %.2x",
|
||||
data[0]));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -175,7 +165,8 @@ finger_det_read_fd_data_cb (FpiUsbTransfer *transfer,
|
||||
fp_dbg ("Bogus FD response: %.2x\n", data[0]);
|
||||
fpi_ssm_mark_failed (transfer->ssm,
|
||||
fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
|
||||
"Bogus FD response"));
|
||||
"Bogus FD response %.2x",
|
||||
data[0]));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -212,7 +203,6 @@ finger_det_sm_complete (FpiSsm *ssm, FpDevice *_dev, GError *error)
|
||||
|
||||
fp_dbg ("Finger detection completed");
|
||||
fpi_image_device_report_finger_status (dev, TRUE);
|
||||
fpi_ssm_free (ssm);
|
||||
|
||||
if (priv->deactivating)
|
||||
{
|
||||
@@ -238,12 +228,12 @@ finger_det_run_state (FpiSsm *ssm, FpDevice *dev)
|
||||
{
|
||||
case FINGER_DET_SEND_LED_CMD:
|
||||
aesX660_send_cmd (ssm, dev, led_blink_cmd, sizeof (led_blink_cmd),
|
||||
aesX660_send_cmd_cb);
|
||||
fpi_ssm_usb_transfer_cb);
|
||||
break;
|
||||
|
||||
case FINGER_DET_SEND_FD_CMD:
|
||||
aesX660_send_cmd_timeout (ssm, dev, wait_for_finger_cmd, sizeof (wait_for_finger_cmd),
|
||||
aesX660_send_cmd_cb, 0);
|
||||
fpi_ssm_usb_transfer_cb, 0);
|
||||
break;
|
||||
|
||||
case FINGER_DET_READ_FD_DATA:
|
||||
@@ -341,6 +331,7 @@ capture_set_idle_cmd_cb (FpiUsbTransfer *transfer, FpDevice *device,
|
||||
|
||||
priv->strips = g_slist_reverse (priv->strips);
|
||||
img = fpi_assemble_frames (cls->assembling_ctx, priv->strips);
|
||||
img->flags |= FPI_IMAGE_PARTIAL;
|
||||
g_slist_foreach (priv->strips, (GFunc) g_free, NULL);
|
||||
g_slist_free (priv->strips);
|
||||
priv->strips = NULL;
|
||||
@@ -433,14 +424,14 @@ capture_run_state (FpiSsm *ssm, FpDevice *_dev)
|
||||
{
|
||||
case CAPTURE_SEND_LED_CMD:
|
||||
aesX660_send_cmd (ssm, _dev, led_solid_cmd, sizeof (led_solid_cmd),
|
||||
aesX660_send_cmd_cb);
|
||||
fpi_ssm_usb_transfer_cb);
|
||||
break;
|
||||
|
||||
case CAPTURE_SEND_CAPTURE_CMD:
|
||||
g_byte_array_set_size (priv->stripe_packet, 0);
|
||||
aesX660_send_cmd (ssm, _dev, cls->start_imaging_cmd,
|
||||
cls->start_imaging_cmd_len,
|
||||
aesX660_send_cmd_cb);
|
||||
fpi_ssm_usb_transfer_cb);
|
||||
break;
|
||||
|
||||
case CAPTURE_READ_STRIPE_DATA:
|
||||
@@ -463,7 +454,6 @@ capture_sm_complete (FpiSsm *ssm, FpDevice *device, GError *error)
|
||||
FpiDeviceAesX660Private *priv = fpi_device_aes_x660_get_instance_private (self);
|
||||
|
||||
fp_dbg ("Capture completed");
|
||||
fpi_ssm_free (ssm);
|
||||
|
||||
if (priv->deactivating)
|
||||
{
|
||||
@@ -538,7 +528,8 @@ activate_read_id_cb (FpiUsbTransfer *transfer, FpDevice *device,
|
||||
fp_dbg ("Bogus read ID response: %.2x\n", data[AESX660_RESPONSE_TYPE_OFFSET]);
|
||||
fpi_ssm_mark_failed (transfer->ssm,
|
||||
fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
|
||||
"Bogus read ID response"));
|
||||
"Bogus read ID response %.2x",
|
||||
data[AESX660_RESPONSE_TYPE_OFFSET]));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -565,7 +556,8 @@ activate_read_id_cb (FpiUsbTransfer *transfer, FpDevice *device,
|
||||
fp_dbg ("Failed to init device! init status: %.2x\n", data[7]);
|
||||
fpi_ssm_mark_failed (transfer->ssm,
|
||||
fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
|
||||
"Failed to init device"));
|
||||
"Failed to init device %.2x",
|
||||
data[7]));
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -594,7 +586,8 @@ activate_read_init_cb (FpiUsbTransfer *transfer, FpDevice *device,
|
||||
data[3]);
|
||||
fpi_ssm_mark_failed (transfer->ssm,
|
||||
fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
|
||||
"Bogus read init response"));
|
||||
"Bogus read init response: "
|
||||
"%.2x %.2x", data[0], data[3]));
|
||||
return;
|
||||
}
|
||||
priv->init_cmd_idx++;
|
||||
@@ -623,13 +616,13 @@ activate_run_state (FpiSsm *ssm, FpDevice *_dev)
|
||||
priv->init_seq_idx = 0;
|
||||
fp_dbg ("Activate: set idle\n");
|
||||
aesX660_send_cmd (ssm, _dev, set_idle_cmd, sizeof (set_idle_cmd),
|
||||
aesX660_send_cmd_cb);
|
||||
fpi_ssm_usb_transfer_cb);
|
||||
break;
|
||||
|
||||
case ACTIVATE_SEND_READ_ID_CMD:
|
||||
fp_dbg ("Activate: read ID\n");
|
||||
aesX660_send_cmd (ssm, _dev, read_id_cmd, sizeof (read_id_cmd),
|
||||
aesX660_send_cmd_cb);
|
||||
fpi_ssm_usb_transfer_cb);
|
||||
break;
|
||||
|
||||
case ACTIVATE_READ_ID:
|
||||
@@ -643,7 +636,7 @@ activate_run_state (FpiSsm *ssm, FpDevice *_dev)
|
||||
aesX660_send_cmd (ssm, _dev,
|
||||
priv->init_seq[priv->init_cmd_idx].cmd,
|
||||
priv->init_seq[priv->init_cmd_idx].len,
|
||||
aesX660_send_cmd_cb);
|
||||
fpi_ssm_usb_transfer_cb);
|
||||
break;
|
||||
|
||||
case ACTIVATE_READ_INIT_RESPONSE:
|
||||
@@ -653,7 +646,7 @@ activate_run_state (FpiSsm *ssm, FpDevice *_dev)
|
||||
|
||||
case ACTIVATE_SEND_CALIBRATE_CMD:
|
||||
aesX660_send_cmd (ssm, _dev, calibrate_cmd, sizeof (calibrate_cmd),
|
||||
aesX660_send_cmd_cb);
|
||||
fpi_ssm_usb_transfer_cb);
|
||||
break;
|
||||
|
||||
case ACTIVATE_READ_CALIBRATE_DATA:
|
||||
@@ -666,7 +659,6 @@ static void
|
||||
activate_sm_complete (FpiSsm *ssm, FpDevice *_dev, GError *error)
|
||||
{
|
||||
fpi_image_device_activate_complete (FP_IMAGE_DEVICE (_dev), error);
|
||||
fpi_ssm_free (ssm);
|
||||
|
||||
if (!error)
|
||||
start_finger_detection (FP_IMAGE_DEVICE (_dev));
|
||||
|
||||
+44
-43
@@ -41,7 +41,7 @@
|
||||
#include "drivers_api.h"
|
||||
#include "elan.h"
|
||||
|
||||
unsigned char
|
||||
static unsigned char
|
||||
elan_get_pixel (struct fpi_frame_asmbl_ctx *ctx,
|
||||
struct fpi_frame *frame, unsigned int x,
|
||||
unsigned int y)
|
||||
@@ -74,8 +74,8 @@ struct _FpiDeviceElan
|
||||
|
||||
/* state */
|
||||
gboolean deactivating;
|
||||
FpImageDeviceState dev_state;
|
||||
FpImageDeviceState dev_state_next;
|
||||
FpiImageDeviceState dev_state;
|
||||
FpiImageDeviceState dev_state_next;
|
||||
unsigned char *last_read;
|
||||
unsigned char calib_atts_left;
|
||||
unsigned char calib_status;
|
||||
@@ -91,7 +91,7 @@ G_DECLARE_FINAL_TYPE (FpiDeviceElan, fpi_device_elan, FPI, DEVICE_ELAN,
|
||||
FpImageDevice);
|
||||
G_DEFINE_TYPE (FpiDeviceElan, fpi_device_elan, FP_TYPE_IMAGE_DEVICE);
|
||||
|
||||
int
|
||||
static int
|
||||
cmp_short (const void *a, const void *b)
|
||||
{
|
||||
return (int) (*(short *) a - *(short *) b);
|
||||
@@ -207,6 +207,7 @@ elan_save_img_frame (FpiDeviceElan *elandev)
|
||||
|
||||
unsigned int frame_size = elandev->frame_width * elandev->frame_height;
|
||||
unsigned short *frame = g_malloc (frame_size * sizeof (short));
|
||||
|
||||
elan_save_frame (elandev, frame);
|
||||
unsigned int sum = 0;
|
||||
|
||||
@@ -223,6 +224,7 @@ elan_save_img_frame (FpiDeviceElan *elandev)
|
||||
{
|
||||
fp_dbg
|
||||
("frame darker than background; finger present during calibration?");
|
||||
g_free (frame);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -243,6 +245,7 @@ elan_process_frame_linear (unsigned short *raw_frame,
|
||||
G_DEBUG_HERE ();
|
||||
|
||||
unsigned short min = 0xffff, max = 0;
|
||||
|
||||
for (int i = 0; i < frame_size; i++)
|
||||
{
|
||||
if (raw_frame[i] < min)
|
||||
@@ -254,6 +257,7 @@ elan_process_frame_linear (unsigned short *raw_frame,
|
||||
g_assert (max != min);
|
||||
|
||||
unsigned short px;
|
||||
|
||||
for (int i = 0; i < frame_size; i++)
|
||||
{
|
||||
px = raw_frame[i];
|
||||
@@ -277,6 +281,7 @@ elan_process_frame_thirds (unsigned short *raw_frame,
|
||||
|
||||
unsigned short lvl0, lvl1, lvl2, lvl3;
|
||||
unsigned short *sorted = g_malloc (frame_size * sizeof (short));
|
||||
|
||||
memcpy (sorted, raw_frame, frame_size * sizeof (short));
|
||||
qsort (sorted, frame_size, sizeof (short), cmp_short);
|
||||
lvl0 = sorted[0];
|
||||
@@ -286,6 +291,7 @@ elan_process_frame_thirds (unsigned short *raw_frame,
|
||||
g_free (sorted);
|
||||
|
||||
unsigned short px;
|
||||
|
||||
for (int i = 0; i < frame_size; i++)
|
||||
{
|
||||
px = raw_frame[i];
|
||||
@@ -319,6 +325,9 @@ elan_submit_image (FpImageDevice *dev)
|
||||
g_slist_foreach (raw_frames, (GFunc) self->process_frame, &frames);
|
||||
fpi_do_movement_estimation (&assembling_ctx, frames);
|
||||
img = fpi_assemble_frames (&assembling_ctx, frames);
|
||||
img->flags |= FPI_IMAGE_PARTIAL;
|
||||
|
||||
g_slist_free_full (frames, g_free);
|
||||
|
||||
fpi_image_device_image_captured (dev, img);
|
||||
}
|
||||
@@ -405,7 +414,6 @@ elan_cmd_read (FpiSsm *ssm, FpDevice *dev)
|
||||
cancellable = fpi_device_get_cancellable (dev);
|
||||
|
||||
fpi_usb_transfer_submit (transfer, self->cmd_timeout, cancellable, elan_cmd_cb, NULL);
|
||||
fpi_usb_transfer_unref (transfer);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -448,7 +456,6 @@ elan_run_cmd (FpiSsm *ssm,
|
||||
cancellable,
|
||||
elan_cmd_cb,
|
||||
NULL);
|
||||
fpi_usb_transfer_unref (transfer);
|
||||
}
|
||||
|
||||
enum stop_capture_states {
|
||||
@@ -478,10 +485,9 @@ stop_capture_complete (FpiSsm *ssm, FpDevice *_dev, GError *error)
|
||||
|
||||
G_DEBUG_HERE ();
|
||||
|
||||
fpi_ssm_free (ssm);
|
||||
|
||||
/* The device is inactive at this point. */
|
||||
self->dev_state = FP_IMAGE_DEVICE_STATE_INACTIVE;
|
||||
self->dev_state = FPI_IMAGE_DEVICE_STATE_INACTIVE;
|
||||
|
||||
if (self->deactivating)
|
||||
{
|
||||
@@ -509,6 +515,7 @@ elan_stop_capture (FpDevice *dev)
|
||||
|
||||
FpiSsm *ssm =
|
||||
fpi_ssm_new (dev, stop_capture_run_state, STOP_CAPTURE_NUM_STATES);
|
||||
|
||||
fpi_ssm_start (ssm, stop_capture_complete);
|
||||
}
|
||||
|
||||
@@ -538,7 +545,7 @@ capture_run_state (FpiSsm *ssm, FpDevice *dev)
|
||||
break;
|
||||
|
||||
case CAPTURE_READ_DATA:
|
||||
self->dev_state = FP_IMAGE_DEVICE_STATE_CAPTURE;
|
||||
self->dev_state = FPI_IMAGE_DEVICE_STATE_CAPTURE;
|
||||
|
||||
/* 0x55 - finger present
|
||||
* 0xff - device not calibrated (probably) */
|
||||
@@ -549,6 +556,10 @@ capture_run_state (FpiSsm *ssm, FpDevice *dev)
|
||||
}
|
||||
else
|
||||
{
|
||||
/* XXX: The timeout is emulated incorrectly, resulting in a zero byte read. */
|
||||
if (g_strcmp0 (g_getenv ("FP_DEVICE_EMULATION"), "1") == 0)
|
||||
fpi_ssm_mark_completed (ssm);
|
||||
else
|
||||
fpi_ssm_mark_failed (ssm, fpi_device_error_new (FP_DEVICE_ERROR_PROTO));
|
||||
}
|
||||
break;
|
||||
@@ -581,8 +592,6 @@ capture_complete (FpiSsm *ssm, FpDevice *_dev, GError *error)
|
||||
|
||||
G_DEBUG_HERE ();
|
||||
|
||||
/* XXX: cancellation was specially handled by doing nothing! */
|
||||
|
||||
/* either max frames captured or timed out waiting for the next frame */
|
||||
if (!error ||
|
||||
(g_error_matches (error, G_USB_DEVICE_ERROR, G_USB_DEVICE_ERROR_TIMED_OUT) &&
|
||||
@@ -605,7 +614,6 @@ capture_complete (FpiSsm *ssm, FpDevice *_dev, GError *error)
|
||||
fpi_image_device_session_error (dev, error);
|
||||
}
|
||||
|
||||
fpi_ssm_free (ssm);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -618,6 +626,7 @@ elan_capture (FpDevice *dev)
|
||||
elan_dev_reset_state (self);
|
||||
FpiSsm *ssm =
|
||||
fpi_ssm_new (dev, capture_run_state, CAPTURE_NUM_STATES);
|
||||
|
||||
fpi_ssm_start (ssm, capture_complete);
|
||||
}
|
||||
|
||||
@@ -732,7 +741,7 @@ calibrate_run_state (FpiSsm *ssm, FpDevice *dev)
|
||||
fp_dbg ("calibration failed");
|
||||
fpi_ssm_mark_failed (ssm,
|
||||
fpi_device_error_new_msg (FP_DEVICE_ERROR_GENERAL,
|
||||
"Callibration failed!"));
|
||||
"Calibration failed!"));
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -752,15 +761,10 @@ calibrate_run_state (FpiSsm *ssm, FpDevice *dev)
|
||||
}
|
||||
else
|
||||
{
|
||||
GSource *timeout;
|
||||
|
||||
if (self->calib_status == 0x00 &&
|
||||
self->last_read[0] == 0x01)
|
||||
self->calib_status = 0x01;
|
||||
timeout = fpi_device_add_timeout (dev, 50,
|
||||
fpi_ssm_next_state_timeout_cb,
|
||||
ssm);
|
||||
g_source_set_name (timeout, "calibrate_run_state");
|
||||
fpi_ssm_next_state_delayed (ssm, 50, NULL);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -779,16 +783,14 @@ calibrate_complete (FpiSsm *ssm, FpDevice *dev, GError *error)
|
||||
|
||||
if (error)
|
||||
{
|
||||
self->dev_state = FP_IMAGE_DEVICE_STATE_INACTIVE;
|
||||
self->dev_state = FPI_IMAGE_DEVICE_STATE_INACTIVE;
|
||||
fpi_image_device_session_error (FP_IMAGE_DEVICE (dev), error);
|
||||
}
|
||||
else
|
||||
{
|
||||
self->dev_state = FP_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON;
|
||||
elan_capture (dev);
|
||||
}
|
||||
|
||||
fpi_ssm_free (ssm);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -803,6 +805,7 @@ elan_calibrate (FpDevice *dev)
|
||||
|
||||
FpiSsm *ssm = fpi_ssm_new (FP_DEVICE (dev), calibrate_run_state,
|
||||
CALIBRATE_NUM_STATES);
|
||||
|
||||
fpi_ssm_start (ssm, calibrate_complete);
|
||||
}
|
||||
|
||||
@@ -885,7 +888,6 @@ activate_complete (FpiSsm *ssm, FpDevice *dev, GError *error)
|
||||
|
||||
fpi_image_device_activate_complete (idev, error);
|
||||
|
||||
fpi_ssm_free (ssm);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -899,6 +901,7 @@ elan_activate (FpImageDevice *dev)
|
||||
FpiSsm *ssm =
|
||||
fpi_ssm_new (FP_DEVICE (dev), activate_run_state,
|
||||
ACTIVATE_NUM_STATES);
|
||||
|
||||
fpi_ssm_start (ssm, activate_complete);
|
||||
}
|
||||
|
||||
@@ -960,7 +963,7 @@ elan_change_state (FpImageDevice *idev)
|
||||
{
|
||||
FpDevice *dev = FP_DEVICE (idev);
|
||||
FpiDeviceElan *self = FPI_DEVICE_ELAN (dev);
|
||||
FpImageDeviceState next_state = self->dev_state_next;
|
||||
FpiImageDeviceState next_state = self->dev_state_next;
|
||||
|
||||
if (self->dev_state == next_state)
|
||||
{
|
||||
@@ -974,22 +977,20 @@ elan_change_state (FpImageDevice *idev)
|
||||
|
||||
switch (next_state)
|
||||
{
|
||||
break;
|
||||
|
||||
case FP_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON:
|
||||
case FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON:
|
||||
/* activation completed or another enroll stage started */
|
||||
self->dev_state = FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON;
|
||||
elan_calibrate (dev);
|
||||
break;
|
||||
|
||||
case FP_IMAGE_DEVICE_STATE_CAPTURE:
|
||||
case FPI_IMAGE_DEVICE_STATE_CAPTURE:
|
||||
/* not used */
|
||||
break;
|
||||
|
||||
case FP_IMAGE_DEVICE_STATE_INACTIVE:
|
||||
case FP_IMAGE_DEVICE_STATE_AWAIT_FINGER_OFF:
|
||||
if (self->dev_state != FP_IMAGE_DEVICE_STATE_INACTIVE ||
|
||||
self->dev_state != FP_IMAGE_DEVICE_STATE_AWAIT_FINGER_OFF)
|
||||
case FPI_IMAGE_DEVICE_STATE_INACTIVE:
|
||||
case FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_OFF:
|
||||
elan_stop_capture (dev);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -997,12 +998,12 @@ static void
|
||||
elan_change_state_async (FpDevice *dev,
|
||||
void *data)
|
||||
{
|
||||
g_message ("state change dev: %p", dev);
|
||||
fp_dbg ("state change dev: %p", dev);
|
||||
elan_change_state (FP_IMAGE_DEVICE (dev));
|
||||
}
|
||||
|
||||
static void
|
||||
dev_change_state (FpImageDevice *dev, FpImageDeviceState state)
|
||||
dev_change_state (FpImageDevice *dev, FpiImageDeviceState state)
|
||||
{
|
||||
FpiDeviceElan *self = FPI_DEVICE_ELAN (dev);
|
||||
GSource *timeout;
|
||||
@@ -1010,17 +1011,17 @@ dev_change_state (FpImageDevice *dev, FpImageDeviceState state)
|
||||
G_DEBUG_HERE ();
|
||||
|
||||
/* Inactive and await finger off are equivalent for the elan driver. */
|
||||
if (state == FP_IMAGE_DEVICE_STATE_AWAIT_FINGER_OFF)
|
||||
state = FP_IMAGE_DEVICE_STATE_INACTIVE;
|
||||
if (state == FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_OFF)
|
||||
state = FPI_IMAGE_DEVICE_STATE_INACTIVE;
|
||||
|
||||
if (self->dev_state_next == state)
|
||||
fp_dbg ("change to state %d already queued", state);
|
||||
|
||||
switch (state)
|
||||
{
|
||||
case FP_IMAGE_DEVICE_STATE_INACTIVE:
|
||||
case FP_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON:
|
||||
case FP_IMAGE_DEVICE_STATE_AWAIT_FINGER_OFF: {
|
||||
case FPI_IMAGE_DEVICE_STATE_INACTIVE:
|
||||
case FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON:
|
||||
case FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_OFF: {
|
||||
char *name;
|
||||
|
||||
/* schedule state change instead of calling it directly to allow all actions
|
||||
@@ -1028,7 +1029,7 @@ dev_change_state (FpImageDevice *dev, FpImageDeviceState state)
|
||||
self->dev_state_next = state;
|
||||
timeout = fpi_device_add_timeout (FP_DEVICE (dev), 10,
|
||||
elan_change_state_async,
|
||||
NULL);
|
||||
NULL, NULL);
|
||||
|
||||
name = g_strdup_printf ("dev_change_state to %d", state);
|
||||
g_source_set_name (timeout, name);
|
||||
@@ -1037,7 +1038,7 @@ dev_change_state (FpImageDevice *dev, FpImageDeviceState state)
|
||||
break;
|
||||
}
|
||||
|
||||
case FP_IMAGE_DEVICE_STATE_CAPTURE:
|
||||
case FPI_IMAGE_DEVICE_STATE_CAPTURE:
|
||||
/* TODO MAYBE: split capture ssm into smaller ssms and use this state */
|
||||
self->dev_state = state;
|
||||
self->dev_state_next = state;
|
||||
@@ -1055,7 +1056,7 @@ dev_deactivate (FpImageDevice *dev)
|
||||
|
||||
G_DEBUG_HERE ();
|
||||
|
||||
if (self->dev_state == FP_IMAGE_DEVICE_STATE_INACTIVE)
|
||||
if (self->dev_state == FPI_IMAGE_DEVICE_STATE_INACTIVE)
|
||||
{
|
||||
/* The device is inactive already, complete the operation immediately. */
|
||||
fpi_image_device_deactivate_complete (dev, NULL);
|
||||
@@ -1066,7 +1067,7 @@ dev_deactivate (FpImageDevice *dev)
|
||||
* need to signal back deactivation) and then ensure we will change
|
||||
* to the inactive state eventually. */
|
||||
self->deactivating = TRUE;
|
||||
dev_change_state (dev, FP_IMAGE_DEVICE_STATE_INACTIVE);
|
||||
dev_change_state (dev, FPI_IMAGE_DEVICE_STATE_INACTIVE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -18,8 +18,7 @@
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef __ELAN_H
|
||||
#define __ELAN_H
|
||||
#pragma once
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
@@ -223,6 +222,4 @@ static void elan_calibrate (FpDevice *dev);
|
||||
static void elan_capture (FpDevice *dev);
|
||||
|
||||
static void dev_change_state (FpImageDevice *dev,
|
||||
FpImageDeviceState state);
|
||||
|
||||
#endif
|
||||
FpiImageDeviceState state);
|
||||
|
||||
+12
-12
@@ -36,7 +36,6 @@
|
||||
#define FP_COMPONENT "etes603"
|
||||
|
||||
#include "drivers_api.h"
|
||||
#include "driver_ids.h"
|
||||
|
||||
/* libusb defines */
|
||||
#define EP_IN 0x81
|
||||
@@ -710,7 +709,6 @@ async_tx (FpDevice *dev, unsigned int ep, void *cb,
|
||||
transfer->ssm = ssm;
|
||||
fpi_usb_transfer_fill_bulk_full (transfer, ep, buffer, length, NULL);
|
||||
fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL, cb, NULL);
|
||||
fpi_usb_transfer_unref (transfer);
|
||||
}
|
||||
|
||||
|
||||
@@ -789,7 +787,6 @@ m_exit_complete (FpiSsm *ssm, FpDevice *dev, GError *error)
|
||||
else
|
||||
fp_dbg ("The device is now in idle state");
|
||||
fpi_image_device_deactivate_complete (idev, error);
|
||||
fpi_ssm_free (ssm);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -862,13 +859,15 @@ m_capture_state (FpiSsm *ssm, FpDevice *dev)
|
||||
}
|
||||
else
|
||||
{
|
||||
FpImage *img;
|
||||
unsigned int img_size;
|
||||
/* Remove empty parts 2 times for the 2 frames */
|
||||
process_removefpi_end (self);
|
||||
process_removefpi_end (self);
|
||||
img_size = self->fp_height * FE_WIDTH;
|
||||
img = fp_image_new (FE_WIDTH, self->fp_height);
|
||||
|
||||
if (self->fp_height >= FE_WIDTH)
|
||||
{
|
||||
FpImage *img = fp_image_new (FE_WIDTH, self->fp_height);
|
||||
unsigned int img_size = self->fp_height * FE_WIDTH;
|
||||
|
||||
/* Images received are white on black, so invert it. */
|
||||
/* TODO detect sweep direction */
|
||||
img->flags = FPI_IMAGE_COLORS_INVERTED | FPI_IMAGE_V_FLIPPED;
|
||||
@@ -877,6 +876,12 @@ m_capture_state (FpiSsm *ssm, FpDevice *dev)
|
||||
fp_dbg ("Sending the raw fingerprint image (%dx%d)",
|
||||
img->width, img->height);
|
||||
fpi_image_device_image_captured (idev, img);
|
||||
}
|
||||
else
|
||||
{
|
||||
fpi_image_device_retry_scan (idev, FP_DEVICE_RETRY_TOO_SHORT);
|
||||
}
|
||||
|
||||
fpi_image_device_report_finger_status (idev, FALSE);
|
||||
fpi_ssm_mark_completed (ssm);
|
||||
}
|
||||
@@ -911,7 +916,6 @@ m_capture_complete (FpiSsm *ssm, FpDevice *dev, GError *error)
|
||||
g_error_free (error);
|
||||
}
|
||||
}
|
||||
fpi_ssm_free (ssm);
|
||||
|
||||
if (self->is_active == TRUE)
|
||||
{
|
||||
@@ -1061,7 +1065,6 @@ m_finger_complete (FpiSsm *ssm, FpDevice *dev, GError *error)
|
||||
self->is_active = FALSE;
|
||||
}
|
||||
|
||||
fpi_ssm_free (ssm);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1265,7 +1268,6 @@ m_tunevrb_complete (FpiSsm *ssm, FpDevice *dev, GError *error)
|
||||
if (!self->is_active)
|
||||
m_exit_start (idev);
|
||||
|
||||
fpi_ssm_free (ssm);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1409,7 +1411,6 @@ m_tunedc_complete (FpiSsm *ssm, FpDevice *dev, GError *error)
|
||||
if (!self->is_active)
|
||||
m_exit_start (idev);
|
||||
|
||||
fpi_ssm_free (ssm);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1543,7 +1544,6 @@ m_init_complete (FpiSsm *ssm, FpDevice *dev, GError *error)
|
||||
reset_param (FPI_DEVICE_ETES603 (dev));
|
||||
fpi_image_device_session_error (idev, error);
|
||||
}
|
||||
fpi_ssm_free (ssm);
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
@@ -17,8 +17,7 @@
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef _BMKT_H_
|
||||
#define _BMKT_H_
|
||||
#pragma once
|
||||
|
||||
/**< User ID maximum length allowed */
|
||||
#define BMKT_MAX_USER_ID_LEN 100
|
||||
@@ -228,5 +227,3 @@ typedef struct bmkt_user_id
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _BMKT_H_ */
|
||||
|
||||
@@ -206,6 +206,7 @@ parse_get_enrolled_users_report (bmkt_msg_resp_t *msg_resp, bmkt_response_t *res
|
||||
get_enroll_templates_resp->query_sequence = extract8 (msg_resp->payload, &offset);
|
||||
|
||||
int n = 0;
|
||||
|
||||
for (n = 0; n < BMKT_MAX_NUM_TEMPLATES_INTERNAL_FLASH; n++)
|
||||
{
|
||||
if (offset >= msg_resp->payload_len)
|
||||
|
||||
@@ -16,10 +16,7 @@
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
|
||||
#ifndef BMKT_MESSAGE_H_
|
||||
#define BMKT_MESSAGE_H_
|
||||
|
||||
#pragma once
|
||||
|
||||
#define BMKT_MESSAGE_HEADER_ID 0xFE
|
||||
#define BMKT_MESSAGE_HEADER_LEN (4)
|
||||
@@ -90,4 +87,3 @@ int bmkt_parse_message_header (uint8_t *resp_buf,
|
||||
bmkt_msg_resp_t *msg_resp);
|
||||
int bmkt_parse_message_payload (bmkt_msg_resp_t *msg_resp,
|
||||
bmkt_response_t *resp);
|
||||
#endif /* BMKT_MESSAGE_H_ */
|
||||
|
||||
@@ -17,9 +17,7 @@
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _BMKT_RESPONSE_H_
|
||||
#define _BMKT_RESPONSE_H_
|
||||
#pragma once
|
||||
|
||||
#include "bmkt.h"
|
||||
|
||||
@@ -318,7 +316,7 @@ typedef struct bmkt_init_resp
|
||||
*/
|
||||
typedef struct bmkt_enroll_resp
|
||||
{
|
||||
int progress; /**< Shows current progress stutus [0-100] */
|
||||
int progress; /**< Shows current progress status [0-100] */
|
||||
uint8_t finger_id; /**< User's finger id [1-10] */
|
||||
uint8_t user_id[BMKT_MAX_USER_ID_LEN]; /**< User name to be enrolled */
|
||||
} bmkt_enroll_resp_t;
|
||||
@@ -485,5 +483,3 @@ typedef struct bmkt_response
|
||||
int complete; /**< Operation completion status 1: complete / 0: not completed */
|
||||
bmkt_response_data_t response; /**< Operation specific response union */
|
||||
} bmkt_response_t;
|
||||
|
||||
#endif /* _BMKT_RESPONSE_H_ */
|
||||
|
||||
@@ -16,8 +16,7 @@
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef _SENSOR_H_
|
||||
#define _SENSOR_H_
|
||||
#pragma once
|
||||
|
||||
#include "usb_transport.h"
|
||||
#define BMKT_MAX_PENDING_SESSIONS 2
|
||||
@@ -84,4 +83,3 @@ int bmkt_sensor_handle_response (bmkt_sensor_t *sensor,
|
||||
bmkt_msg_resp_t *msg_resp);
|
||||
|
||||
int bmkt_sensor_send_async_read_command (bmkt_sensor_t *sensor);
|
||||
#endif /* _SENSOR_H_ */
|
||||
|
||||
@@ -35,7 +35,7 @@ static const FpIdEntry id_table[] = {
|
||||
|
||||
|
||||
static void
|
||||
cmd_recieve_cb (FpiUsbTransfer *transfer,
|
||||
cmd_receive_cb (FpiUsbTransfer *transfer,
|
||||
FpDevice *device,
|
||||
gpointer user_data,
|
||||
GError *error)
|
||||
@@ -137,7 +137,8 @@ cmd_recieve_cb (FpiUsbTransfer *transfer,
|
||||
fp_warn ("Received General Error %d from the sensor", (guint) err);
|
||||
fpi_ssm_mark_failed (transfer->ssm,
|
||||
fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
|
||||
"Received general error from device"));
|
||||
"Received general error %u from device",
|
||||
(guint) err));
|
||||
//fpi_ssm_jump_to_state (transfer->ssm, fpi_ssm_get_cur_state (transfer->ssm));
|
||||
return;
|
||||
}
|
||||
@@ -167,7 +168,7 @@ cmd_recieve_cb (FpiUsbTransfer *transfer,
|
||||
* depending on resp.complete. */
|
||||
if (self->cmd_pending_transfer)
|
||||
fpi_ssm_jump_to_state (transfer->ssm, SYNAPTICS_CMD_SEND_PENDING);
|
||||
else if (!resp.complete)
|
||||
else if (!resp.complete || self->cmd_complete_on_removal)
|
||||
fpi_ssm_next_state (transfer->ssm); /* SYNAPTICS_CMD_WAIT_INTERRUPT */
|
||||
else
|
||||
fpi_ssm_mark_completed (transfer->ssm);
|
||||
@@ -204,7 +205,7 @@ static void
|
||||
synaptics_cmd_run_state (FpiSsm *ssm,
|
||||
FpDevice *dev)
|
||||
{
|
||||
g_autoptr(FpiUsbTransfer) transfer = NULL;
|
||||
FpiUsbTransfer *transfer;
|
||||
FpiDeviceSynaptics *self = FPI_DEVICE_SYNAPTICS (dev);
|
||||
|
||||
switch (fpi_ssm_get_cur_state (ssm))
|
||||
@@ -218,7 +219,7 @@ synaptics_cmd_run_state (FpiSsm *ssm,
|
||||
NULL,
|
||||
fpi_ssm_usb_transfer_cb,
|
||||
NULL);
|
||||
g_clear_pointer (&self->cmd_pending_transfer, fpi_usb_transfer_unref);
|
||||
self->cmd_pending_transfer = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -233,7 +234,7 @@ synaptics_cmd_run_state (FpiSsm *ssm,
|
||||
fpi_usb_transfer_submit (transfer,
|
||||
5000,
|
||||
NULL,
|
||||
cmd_recieve_cb,
|
||||
cmd_receive_cb,
|
||||
fpi_ssm_get_data (ssm));
|
||||
|
||||
break;
|
||||
@@ -278,18 +279,10 @@ cmd_ssm_done (FpiSsm *ssm, FpDevice *dev, GError *error)
|
||||
self->cmd_ssm = NULL;
|
||||
|
||||
/* Notify about the SSM failure from here instead. */
|
||||
if (error)
|
||||
{
|
||||
if (error || self->cmd_complete_on_removal)
|
||||
callback (self, NULL, error);
|
||||
}
|
||||
else if (self->cmd_complete_on_removal)
|
||||
{
|
||||
callback (self, NULL, self->cmd_complete_error);
|
||||
self->cmd_complete_error = NULL;
|
||||
}
|
||||
|
||||
self->cmd_complete_on_removal = FALSE;
|
||||
g_clear_pointer (&self->cmd_complete_error, g_error_free);
|
||||
fpi_ssm_free (ssm);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -317,7 +310,7 @@ synaptics_sensor_cmd (FpiDeviceSynaptics *self,
|
||||
gssize payload_len,
|
||||
SynCmdMsgCallback callback)
|
||||
{
|
||||
g_autoptr(FpiUsbTransfer) transfer = NULL;
|
||||
FpiUsbTransfer *transfer;
|
||||
guint8 real_seq_num;
|
||||
gint msg_len;
|
||||
gint res;
|
||||
@@ -328,7 +321,7 @@ synaptics_sensor_cmd (FpiDeviceSynaptics *self,
|
||||
g_assert (payload || payload_len == 0);
|
||||
|
||||
/* seq_num of 0 means a normal command, -1 means the current commands
|
||||
* sequence number should not be udpated (i.e. second async command which
|
||||
* sequence number should not be updated (i.e. second async command which
|
||||
* may only be a cancellation currently). */
|
||||
if (seq_num <= 0)
|
||||
{
|
||||
@@ -407,7 +400,7 @@ static gboolean
|
||||
parse_print_data (GVariant *data,
|
||||
guint8 *finger,
|
||||
const guint8 **user_id,
|
||||
gssize *user_id_len)
|
||||
gsize *user_id_len)
|
||||
{
|
||||
g_autoptr(GVariant) user_id_var = NULL;
|
||||
|
||||
@@ -447,7 +440,7 @@ list_msg_cb (FpiDeviceSynaptics *self,
|
||||
|
||||
if (error)
|
||||
{
|
||||
g_clear_pointer (&self->list_result, g_ptr_array_free);
|
||||
g_clear_pointer (&self->list_result, g_ptr_array_unref);
|
||||
fpi_device_list_complete (FP_DEVICE (self), NULL, error);
|
||||
return;
|
||||
}
|
||||
@@ -468,11 +461,12 @@ list_msg_cb (FpiDeviceSynaptics *self,
|
||||
else
|
||||
{
|
||||
fp_info ("Failed to query enrolled users: %d", resp->result);
|
||||
g_clear_pointer (&self->list_result, g_ptr_array_free);
|
||||
g_clear_pointer (&self->list_result, g_ptr_array_unref);
|
||||
fpi_device_list_complete (FP_DEVICE (self),
|
||||
NULL,
|
||||
fpi_device_error_new_msg (FP_DEVICE_ERROR_GENERAL,
|
||||
"Failed to query enrolled users"));
|
||||
"Failed to query enrolled users: %d",
|
||||
resp->result));
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -505,7 +499,7 @@ list_msg_cb (FpiDeviceSynaptics *self,
|
||||
get_enroll_templates_resp->templates[n].user_id,
|
||||
get_enroll_templates_resp->templates[n].finger_id);
|
||||
|
||||
userid = get_enroll_templates_resp->templates[n].user_id;
|
||||
userid = (gchar *) get_enroll_templates_resp->templates[n].user_id;
|
||||
|
||||
print = fp_print_new (FP_DEVICE (self));
|
||||
uid = g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE,
|
||||
@@ -516,45 +510,12 @@ list_msg_cb (FpiDeviceSynaptics *self,
|
||||
get_enroll_templates_resp->templates[n].finger_id,
|
||||
uid);
|
||||
|
||||
fpi_print_set_type (print, FP_PRINT_RAW);
|
||||
fpi_print_set_type (print, FPI_PRINT_RAW);
|
||||
fpi_print_set_device_stored (print, TRUE);
|
||||
g_object_set (print, "fp-data", data, NULL);
|
||||
g_object_set (print, "fpi-data", data, NULL);
|
||||
g_object_set (print, "description", get_enroll_templates_resp->templates[n].user_id, NULL);
|
||||
|
||||
/* The format has 24 bytes at the start and some dashes in the right places */
|
||||
if (g_str_has_prefix (userid, "FP1-") && strlen (userid) >= 24 &&
|
||||
userid[12] == '-' && userid[14] == '-' && userid[23] == '-')
|
||||
{
|
||||
g_autofree gchar *copy = g_strdup (userid);
|
||||
gint32 date_ymd;
|
||||
GDate *date = NULL;
|
||||
gint32 finger;
|
||||
gchar *username;
|
||||
/* Try to parse information from the string. */
|
||||
|
||||
copy[12] = '\0';
|
||||
date_ymd = g_ascii_strtod (copy + 4, NULL);
|
||||
if (date_ymd > 0)
|
||||
date = g_date_new_dmy (date_ymd % 100,
|
||||
(date_ymd / 100) % 100,
|
||||
date_ymd / 10000);
|
||||
else
|
||||
date = g_date_new ();
|
||||
|
||||
fp_print_set_enroll_date (print, date);
|
||||
g_date_free (date);
|
||||
|
||||
copy[14] = '\0';
|
||||
finger = g_ascii_strtoll (copy + 13, NULL, 16);
|
||||
fp_print_set_finger (print, finger);
|
||||
|
||||
/* We ignore the next chunk, it is just random data.
|
||||
* Then comes the username; nobody is the default if the metadata
|
||||
* is unknown */
|
||||
username = copy + 24;
|
||||
if (strlen (username) > 0 && g_strcmp0 (username, "nobody") != 0)
|
||||
fp_print_set_username (print, username);
|
||||
}
|
||||
fpi_print_fill_from_user_id (print, userid);
|
||||
|
||||
g_ptr_array_add (self->list_result, g_object_ref_sink (print));
|
||||
}
|
||||
@@ -581,6 +542,22 @@ list (FpDevice *device)
|
||||
synaptics_sensor_cmd (self, 0, BMKT_CMD_GET_TEMPLATE_RECORDS, NULL, 0, list_msg_cb);
|
||||
}
|
||||
|
||||
static void
|
||||
verify_complete_after_finger_removal (FpiDeviceSynaptics *self)
|
||||
{
|
||||
FpDevice *device = FP_DEVICE (self);
|
||||
|
||||
if (self->finger_on_sensor)
|
||||
{
|
||||
fp_dbg ("delaying verify report until after finger removal!");
|
||||
self->cmd_complete_on_removal = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
fpi_device_verify_complete (device, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
verify_msg_cb (FpiDeviceSynaptics *self,
|
||||
bmkt_response_t *resp,
|
||||
@@ -591,19 +568,18 @@ verify_msg_cb (FpiDeviceSynaptics *self,
|
||||
|
||||
if (error)
|
||||
{
|
||||
fpi_device_verify_complete (device, FPI_MATCH_ERROR, NULL, error);
|
||||
fpi_device_verify_complete (device, error);
|
||||
return;
|
||||
}
|
||||
|
||||
if (resp == NULL && self->cmd_complete_on_removal)
|
||||
{
|
||||
fpi_device_verify_complete (device,
|
||||
GPOINTER_TO_INT (self->cmd_complete_data),
|
||||
NULL,
|
||||
error);
|
||||
fpi_device_verify_complete (device, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
g_assert (resp != NULL);
|
||||
|
||||
verify_resp = &resp->response.verify_resp;
|
||||
|
||||
switch (resp->response_id)
|
||||
@@ -619,37 +595,38 @@ verify_msg_cb (FpiDeviceSynaptics *self,
|
||||
case BMKT_RSP_VERIFY_FAIL:
|
||||
if (resp->result == BMKT_SENSOR_STIMULUS_ERROR)
|
||||
{
|
||||
fp_dbg ("delaying retry error until after finger removal!");
|
||||
self->cmd_complete_on_removal = TRUE;
|
||||
self->cmd_complete_data = GINT_TO_POINTER (FPI_MATCH_ERROR);
|
||||
self->cmd_complete_error = fpi_device_retry_new (FP_DEVICE_RETRY_GENERAL);
|
||||
fp_info ("Match error occurred");
|
||||
fpi_device_verify_report (device, FPI_MATCH_ERROR, NULL,
|
||||
fpi_device_retry_new (FP_DEVICE_RETRY_GENERAL));
|
||||
verify_complete_after_finger_removal (self);
|
||||
}
|
||||
else if (resp->result == BMKT_FP_NO_MATCH)
|
||||
{
|
||||
fp_dbg ("delaying match failure until after finger removal!");
|
||||
self->cmd_complete_on_removal = TRUE;
|
||||
self->cmd_complete_data = GINT_TO_POINTER (FPI_MATCH_FAIL);
|
||||
self->cmd_complete_error = NULL;
|
||||
fp_info ("Print didn't match");
|
||||
fpi_device_verify_report (device, FPI_MATCH_FAIL, NULL, NULL);
|
||||
verify_complete_after_finger_removal (self);
|
||||
}
|
||||
else if (BMKT_FP_DATABASE_NO_RECORD_EXISTS)
|
||||
else if (resp->result == BMKT_FP_DATABASE_NO_RECORD_EXISTS)
|
||||
{
|
||||
fp_info ("Print is not in database");
|
||||
fpi_device_verify_complete (device,
|
||||
FPI_MATCH_ERROR,
|
||||
NULL,
|
||||
fpi_device_error_new (FP_DEVICE_ERROR_DATA_NOT_FOUND));
|
||||
}
|
||||
else
|
||||
{
|
||||
fp_warn ("Verify has failed: %d", resp->result);
|
||||
fpi_device_verify_complete (device, FPI_MATCH_FAIL, NULL, NULL);
|
||||
fpi_device_verify_complete (device,
|
||||
fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
|
||||
"Unexpected result from device %d",
|
||||
resp->result));
|
||||
}
|
||||
break;
|
||||
|
||||
case BMKT_RSP_VERIFY_OK:
|
||||
fp_info ("Verify was successful! for user: %s finger: %d score: %f",
|
||||
verify_resp->user_id, verify_resp->finger_id, verify_resp->match_result);
|
||||
fpi_device_verify_complete (device, FPI_MATCH_SUCCESS, NULL, NULL);
|
||||
fpi_device_verify_report (device, FPI_MATCH_SUCCESS, NULL, NULL);
|
||||
fpi_device_verify_complete (device, NULL);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -667,13 +644,11 @@ verify (FpDevice *device)
|
||||
|
||||
fpi_device_get_verify_data (device, &print);
|
||||
|
||||
g_object_get (print, "fp-data", &data, NULL);
|
||||
g_object_get (print, "fpi-data", &data, NULL);
|
||||
g_debug ("data is %p", data);
|
||||
if (!parse_print_data (data, &finger, &user_id, &user_id_len))
|
||||
{
|
||||
fpi_device_verify_complete (device,
|
||||
FPI_MATCH_ERROR,
|
||||
NULL,
|
||||
fpi_device_error_new (FP_DEVICE_ERROR_DATA_INVALID));
|
||||
return;
|
||||
}
|
||||
@@ -723,7 +698,7 @@ enroll_msg_cb (FpiDeviceSynaptics *self,
|
||||
if (enroll_resp->progress < 100)
|
||||
done_stages = MIN (done_stages, ENROLL_SAMPLES - 1);
|
||||
|
||||
/* Emit a retry error if there has been no discernable
|
||||
/* Emit a retry error if there has been no discernible
|
||||
* progress. Some firmware revisions report more required
|
||||
* touches. */
|
||||
if (self->enroll_stage == done_stages)
|
||||
@@ -768,7 +743,8 @@ enroll_msg_cb (FpiDeviceSynaptics *self,
|
||||
fpi_device_enroll_complete (device,
|
||||
NULL,
|
||||
fpi_device_error_new_msg (FP_DEVICE_ERROR_GENERAL,
|
||||
"Enrollment failed"));
|
||||
"Enrollment failed (%d)",
|
||||
resp->result));
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -787,8 +763,6 @@ enroll_msg_cb (FpiDeviceSynaptics *self,
|
||||
}
|
||||
}
|
||||
|
||||
#define TEMPLATE_ID_SIZE 20
|
||||
|
||||
static void
|
||||
enroll (FpDevice *device)
|
||||
{
|
||||
@@ -796,52 +770,21 @@ enroll (FpDevice *device)
|
||||
FpPrint *print = NULL;
|
||||
GVariant *data = NULL;
|
||||
GVariant *uid = NULL;
|
||||
const gchar *username;
|
||||
guint finger;
|
||||
g_autofree gchar *user_id;
|
||||
g_autofree gchar *user_id = NULL;
|
||||
gssize user_id_len;
|
||||
g_autofree guint8 *payload = NULL;
|
||||
const GDate *date;
|
||||
gint y, m, d;
|
||||
gint32 rand_id = 0;
|
||||
|
||||
fpi_device_get_enroll_data (device, &print);
|
||||
|
||||
G_DEBUG_HERE ();
|
||||
|
||||
date = fp_print_get_enroll_date (print);
|
||||
if (date && g_date_valid (date))
|
||||
{
|
||||
y = date->year;
|
||||
m = date->month;
|
||||
d = date->day;
|
||||
}
|
||||
else
|
||||
{
|
||||
y = 0;
|
||||
m = 0;
|
||||
d = 0;
|
||||
}
|
||||
|
||||
username = fp_print_get_username (print);
|
||||
if (!username)
|
||||
username = "nobody";
|
||||
|
||||
if (g_strcmp0 (g_getenv ("FP_DEVICE_EMULATION"), "1") == 0)
|
||||
rand_id = 0;
|
||||
else
|
||||
rand_id = g_random_int ();
|
||||
|
||||
user_id = g_strdup_printf ("FP1-%04d%02d%02d-%X-%08X-%s",
|
||||
y, m, d,
|
||||
fp_print_get_finger (print),
|
||||
rand_id,
|
||||
username);
|
||||
user_id = fpi_print_generate_user_id (print);
|
||||
|
||||
user_id_len = strlen (user_id);
|
||||
user_id_len = MIN (BMKT_MAX_USER_ID_LEN, user_id_len);
|
||||
|
||||
/* We currently always use finger 1 from the devices piont of view */
|
||||
/* We currently always use finger 1 from the devices point of view */
|
||||
finger = 1;
|
||||
|
||||
uid = g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE,
|
||||
@@ -852,9 +795,9 @@ enroll (FpDevice *device)
|
||||
finger,
|
||||
uid);
|
||||
|
||||
fpi_print_set_type (print, FP_PRINT_RAW);
|
||||
fpi_print_set_type (print, FPI_PRINT_RAW);
|
||||
fpi_print_set_device_stored (print, TRUE);
|
||||
g_object_set (print, "fp-data", data, NULL);
|
||||
g_object_set (print, "fpi-data", data, NULL);
|
||||
g_object_set (print, "description", user_id, NULL);
|
||||
|
||||
g_debug ("user_id: %s, finger: %d", user_id, finger);
|
||||
@@ -923,7 +866,7 @@ delete_print (FpDevice *device)
|
||||
|
||||
fpi_device_get_delete_data (device, &print);
|
||||
|
||||
g_object_get (print, "fp-data", &data, NULL);
|
||||
g_object_get (print, "fpi-data", &data, NULL);
|
||||
g_debug ("data is %p", data);
|
||||
if (!parse_print_data (data, &finger, &user_id, &user_id_len))
|
||||
{
|
||||
@@ -946,7 +889,8 @@ dev_probe (FpDevice *device)
|
||||
{
|
||||
FpiDeviceSynaptics *self = FPI_DEVICE_SYNAPTICS (device);
|
||||
GUsbDevice *usb_dev;
|
||||
FpiUsbTransfer *transfer;
|
||||
|
||||
g_autoptr(FpiUsbTransfer) transfer = NULL;
|
||||
FpiByteReader reader;
|
||||
GError *error = NULL;
|
||||
guint16 status;
|
||||
@@ -964,13 +908,10 @@ dev_probe (FpDevice *device)
|
||||
return;
|
||||
}
|
||||
|
||||
if (!g_usb_device_reset (fpi_device_get_usb_device (device), &error))
|
||||
{
|
||||
fpi_device_probe_complete (device, NULL, NULL, error);
|
||||
return;
|
||||
}
|
||||
if (!g_usb_device_reset (usb_dev, &error))
|
||||
goto err_close;
|
||||
|
||||
if (!g_usb_device_claim_interface (fpi_device_get_usb_device (device), 0, 0, &error))
|
||||
if (!g_usb_device_claim_interface (usb_dev, 0, 0, &error))
|
||||
goto err_close;
|
||||
|
||||
/* TODO: Do not do this synchronous. */
|
||||
@@ -980,9 +921,8 @@ dev_probe (FpDevice *device)
|
||||
transfer->buffer[0] = SENSOR_CMD_GET_VERSION;
|
||||
if (!fpi_usb_transfer_submit_sync (transfer, 1000, &error))
|
||||
goto err_close;
|
||||
fpi_usb_transfer_unref (transfer);
|
||||
|
||||
|
||||
g_clear_pointer (&transfer, fpi_usb_transfer_unref);
|
||||
transfer = fpi_usb_transfer_new (device);
|
||||
fpi_usb_transfer_fill_bulk (transfer, USB_EP_REPLY, 40);
|
||||
if (!fpi_usb_transfer_submit_sync (transfer, 1000, &error))
|
||||
@@ -1024,7 +964,7 @@ dev_probe (FpDevice *device)
|
||||
|
||||
if (!read_ok)
|
||||
{
|
||||
g_warning ("Transfer in response to verison query was too short");
|
||||
g_warning ("Transfer in response to version query was too short");
|
||||
error = fpi_device_error_new (FP_DEVICE_ERROR_PROTO);
|
||||
goto err_close;
|
||||
}
|
||||
@@ -1035,7 +975,6 @@ dev_probe (FpDevice *device)
|
||||
fp_dbg ("Target: %d", self->mis_version.target);
|
||||
fp_dbg ("Product: %d", self->mis_version.product);
|
||||
|
||||
fpi_usb_transfer_unref (transfer);
|
||||
|
||||
/* We need at least firmware version 10.1, and for 10.1 build 2989158 */
|
||||
if (self->mis_version.version_major < 10 ||
|
||||
@@ -1050,7 +989,11 @@ dev_probe (FpDevice *device)
|
||||
self->mis_version.build_num);
|
||||
|
||||
error = fpi_device_error_new_msg (FP_DEVICE_ERROR_GENERAL,
|
||||
"Unsupported firmware version");
|
||||
"Unsupported firmware version "
|
||||
"(%d.%d with build number %d)",
|
||||
self->mis_version.version_major,
|
||||
self->mis_version.version_minor,
|
||||
self->mis_version.build_num);
|
||||
goto err_close;
|
||||
}
|
||||
|
||||
@@ -1118,7 +1061,7 @@ fps_deinit_cb (FpiDeviceSynaptics *self,
|
||||
case BMKT_RSP_POWER_DOWN_FAIL:
|
||||
fp_info ("Failed to go to power down mode: %d", resp->result);
|
||||
error = fpi_device_error_new_msg (FP_DEVICE_ERROR_GENERAL,
|
||||
"Power down failed");
|
||||
"Power down failed: %d", resp->result);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -16,8 +16,7 @@
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef __synaptics_h__
|
||||
#define __synaptics_h__
|
||||
#pragma once
|
||||
|
||||
#include "fpi-device.h"
|
||||
#include "fpi-ssm.h"
|
||||
@@ -111,8 +110,6 @@ struct _FpiDeviceSynaptics
|
||||
FpiSsm *cmd_ssm;
|
||||
FpiUsbTransfer *cmd_pending_transfer;
|
||||
gboolean cmd_complete_on_removal;
|
||||
GError *cmd_complete_error;
|
||||
void *cmd_complete_data;
|
||||
|
||||
bmkt_sensor_version_t mis_version;
|
||||
|
||||
@@ -126,5 +123,3 @@ struct _FpiDeviceSynaptics
|
||||
struct syna_enroll_resp_data enroll_resp_data;
|
||||
syna_state_t state;
|
||||
};
|
||||
|
||||
#endif //__synaptics_h__
|
||||
|
||||
@@ -635,7 +635,6 @@ write_regs_iterate (struct write_regs_data *wrdata)
|
||||
transfer->short_is_error = TRUE;
|
||||
transfer->ssm = wrdata->ssm;
|
||||
fpi_usb_transfer_submit (transfer, CTRL_TIMEOUT, NULL, write_regs_cb, NULL);
|
||||
fpi_usb_transfer_unref (transfer);
|
||||
|
||||
transfer->buffer[0] = regwrite->value;
|
||||
}
|
||||
@@ -657,17 +656,6 @@ sm_write_regs (FpiSsm *ssm,
|
||||
write_regs_iterate (wrdata);
|
||||
}
|
||||
|
||||
static void
|
||||
sm_write_reg_cb (FpiUsbTransfer *transfer, FpDevice *device,
|
||||
gpointer user_data, GError *error)
|
||||
{
|
||||
if (error)
|
||||
fpi_ssm_mark_failed (transfer->ssm, error);
|
||||
else
|
||||
fpi_ssm_next_state (transfer->ssm);
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
sm_write_reg (FpiSsm *ssm,
|
||||
FpImageDevice *dev,
|
||||
@@ -687,8 +675,8 @@ sm_write_reg (FpiSsm *ssm,
|
||||
1);
|
||||
transfer->short_is_error = TRUE;
|
||||
transfer->ssm = ssm;
|
||||
fpi_usb_transfer_submit (transfer, CTRL_TIMEOUT, NULL, sm_write_reg_cb, NULL);
|
||||
fpi_usb_transfer_unref (transfer);
|
||||
fpi_usb_transfer_submit (transfer, CTRL_TIMEOUT, NULL,
|
||||
fpi_ssm_usb_transfer_cb, NULL);
|
||||
|
||||
transfer->buffer[0] = value;
|
||||
}
|
||||
@@ -737,7 +725,6 @@ sm_read_reg (FpiSsm *ssm,
|
||||
NULL,
|
||||
sm_read_reg_cb,
|
||||
NULL);
|
||||
fpi_usb_transfer_unref (transfer);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -782,7 +769,6 @@ sm_await_intr (FpiSsm *ssm,
|
||||
fpi_device_get_cancellable (FP_DEVICE (dev)),
|
||||
sm_await_intr_cb,
|
||||
NULL);
|
||||
fpi_usb_transfer_unref (transfer);
|
||||
}
|
||||
|
||||
/***** AWAIT FINGER *****/
|
||||
@@ -1249,6 +1235,9 @@ loopsm_run_state (FpiSsm *ssm, FpDevice *_dev)
|
||||
awfsm_1000_run_state,
|
||||
AWFSM_1000_NUM_STATES);
|
||||
break;
|
||||
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
fpi_ssm_start_subsm (ssm, awfsm);
|
||||
}
|
||||
@@ -1290,6 +1279,9 @@ loopsm_run_state (FpiSsm *ssm, FpDevice *_dev)
|
||||
capsm_1001_run_state,
|
||||
CAPSM_1001_NUM_STATES);
|
||||
break;
|
||||
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
fpi_ssm_start_subsm (ssm, capsm);
|
||||
break;
|
||||
@@ -1318,6 +1310,9 @@ loopsm_run_state (FpiSsm *ssm, FpDevice *_dev)
|
||||
deinitsm_1001_run_state,
|
||||
DEINITSM_1001_NUM_STATES);
|
||||
break;
|
||||
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
self->capturing = FALSE;
|
||||
fpi_ssm_start_subsm (ssm, deinitsm);
|
||||
@@ -1371,7 +1366,6 @@ loopsm_complete (FpiSsm *ssm, FpDevice *_dev, GError *error)
|
||||
FpImageDevice *dev = FP_IMAGE_DEVICE (_dev);
|
||||
FpiDeviceUpeksonly *self = FPI_DEVICE_UPEKSONLY (_dev);
|
||||
|
||||
fpi_ssm_free (ssm);
|
||||
|
||||
if (self->deactivating)
|
||||
{
|
||||
@@ -1392,7 +1386,6 @@ initsm_complete (FpiSsm *ssm, FpDevice *_dev, GError *error)
|
||||
FpImageDevice *dev = FP_IMAGE_DEVICE (_dev);
|
||||
FpiDeviceUpeksonly *self = FPI_DEVICE_UPEKSONLY (_dev);
|
||||
|
||||
fpi_ssm_free (ssm);
|
||||
fpi_image_device_activate_complete (dev, error);
|
||||
if (error)
|
||||
return;
|
||||
@@ -1412,7 +1405,6 @@ dev_activate (FpImageDevice *dev)
|
||||
self->deactivating = FALSE;
|
||||
self->capturing = FALSE;
|
||||
|
||||
self->img_transfers = g_ptr_array_new_full (NUM_BULK_TRANSFERS, (GDestroyNotify) fpi_usb_transfer_unref);
|
||||
self->num_flying = 0;
|
||||
|
||||
for (i = 0; i < self->img_transfers->len; i++)
|
||||
@@ -1441,6 +1433,9 @@ dev_activate (FpImageDevice *dev)
|
||||
ssm = fpi_ssm_new (FP_DEVICE (dev), initsm_1001_run_state,
|
||||
INITSM_1001_NUM_STATES);
|
||||
break;
|
||||
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
fpi_ssm_start (ssm, initsm_complete);
|
||||
}
|
||||
|
||||
@@ -128,7 +128,6 @@ activate_run_state (FpiSsm *ssm, FpDevice *dev)
|
||||
transfer->short_is_error = TRUE;
|
||||
fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
|
||||
write_init_cb, NULL);
|
||||
fpi_usb_transfer_unref (transfer);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -142,7 +141,6 @@ activate_run_state (FpiSsm *ssm, FpDevice *dev)
|
||||
transfer->ssm = ssm;
|
||||
fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
|
||||
read_init_data_cb, NULL);
|
||||
fpi_usb_transfer_unref (transfer);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -157,7 +155,6 @@ activate_sm_complete (FpiSsm *ssm, FpDevice *_dev, GError *error)
|
||||
|
||||
if (!error)
|
||||
start_finger_detection (dev);
|
||||
fpi_ssm_free (ssm);
|
||||
}
|
||||
|
||||
|
||||
@@ -226,7 +223,6 @@ finger_det_cmd_cb (FpiUsbTransfer *t, FpDevice *device,
|
||||
IMAGE_SIZE);
|
||||
fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
|
||||
finger_det_data_cb, NULL);
|
||||
fpi_usb_transfer_unref (transfer);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -250,7 +246,6 @@ start_finger_detection (FpImageDevice *dev)
|
||||
UPEKTC_CMD_LEN, NULL);
|
||||
fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
|
||||
finger_det_cmd_cb, NULL);
|
||||
fpi_usb_transfer_unref (transfer);
|
||||
}
|
||||
|
||||
/****** CAPTURE ******/
|
||||
@@ -261,16 +256,6 @@ enum capture_states {
|
||||
CAPTURE_NUM_STATES,
|
||||
};
|
||||
|
||||
static void
|
||||
capture_cmd_cb (FpiUsbTransfer *transfer, FpDevice *device,
|
||||
gpointer user_data, GError *error)
|
||||
{
|
||||
if (!error)
|
||||
fpi_ssm_next_state (transfer->ssm);
|
||||
else
|
||||
fpi_ssm_mark_failed (transfer->ssm, error);
|
||||
}
|
||||
|
||||
static void
|
||||
capture_read_data_cb (FpiUsbTransfer *transfer, FpDevice *device,
|
||||
gpointer user_data, GError *error)
|
||||
@@ -309,8 +294,7 @@ capture_run_state (FpiSsm *ssm, FpDevice *_dev)
|
||||
transfer->ssm = ssm;
|
||||
transfer->short_is_error = TRUE;
|
||||
fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
|
||||
capture_cmd_cb, NULL);
|
||||
fpi_usb_transfer_unref (transfer);
|
||||
fpi_ssm_usb_transfer_cb, NULL);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -324,7 +308,6 @@ capture_run_state (FpiSsm *ssm, FpDevice *_dev)
|
||||
transfer->short_is_error = TRUE;
|
||||
fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
|
||||
capture_read_data_cb, NULL);
|
||||
fpi_usb_transfer_unref (transfer);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -345,7 +328,6 @@ capture_sm_complete (FpiSsm *ssm, FpDevice *_dev, GError *error)
|
||||
else
|
||||
start_finger_detection (dev);
|
||||
|
||||
fpi_ssm_free (ssm);
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
@@ -19,8 +19,7 @@
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef __UPEKTC_H
|
||||
#define __UPEKTC_H
|
||||
#pragma once
|
||||
|
||||
#define UPEKTC_CMD_LEN 0x40
|
||||
#define IMAGE_WIDTH 208
|
||||
@@ -1936,5 +1935,3 @@ static const unsigned char scan_cmd[0x40] = {
|
||||
0x05, 0x90, 0xf6, 0x77, 0x84, 0xf5, 0x2f, 0x01,
|
||||
0x05, 0x90, 0xf6, 0x00, 0xc8, 0x00, 0xec, 0x00
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -100,7 +100,6 @@ upektc_img_submit_req (FpiSsm *ssm,
|
||||
transfer->ssm = ssm;
|
||||
transfer->short_is_error = TRUE;
|
||||
fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL, cb, NULL);
|
||||
fpi_usb_transfer_unref (transfer);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -120,7 +119,6 @@ upektc_img_read_data (FpiSsm *ssm,
|
||||
NULL);
|
||||
transfer->ssm = ssm;
|
||||
fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL, cb, NULL);
|
||||
fpi_usb_transfer_unref (transfer);
|
||||
}
|
||||
|
||||
/****** CAPTURE ******/
|
||||
@@ -312,6 +310,7 @@ capture_read_data_cb (FpiUsbTransfer *transfer, FpDevice *device,
|
||||
fp_dbg ("Image size is %lu\n",
|
||||
self->image_size);
|
||||
img = fp_image_new (IMAGE_WIDTH, IMAGE_HEIGHT);
|
||||
img->flags |= FPI_IMAGE_PARTIAL;
|
||||
memcpy (img->data, self->image_bits,
|
||||
IMAGE_SIZE);
|
||||
fpi_image_device_image_captured (dev, img);
|
||||
@@ -389,7 +388,6 @@ capture_sm_complete (FpiSsm *ssm, FpDevice *_dev, GError *error_arg)
|
||||
|
||||
g_autoptr(GError) error = error_arg;
|
||||
|
||||
fpi_ssm_free (ssm);
|
||||
|
||||
/* Note: We assume that the error is a cancellation in the deactivation case */
|
||||
if (self->deactivating)
|
||||
@@ -470,7 +468,6 @@ deactivate_sm_complete (FpiSsm *ssm, FpDevice *_dev, GError *error)
|
||||
FpiDeviceUpektcImg *self = FPI_DEVICE_UPEKTC_IMG (_dev);
|
||||
|
||||
fp_dbg ("Deactivate completed");
|
||||
fpi_ssm_free (ssm);
|
||||
|
||||
self->deactivating = FALSE;
|
||||
fpi_image_device_deactivate_complete (dev, error);
|
||||
@@ -505,16 +502,6 @@ enum activate_states {
|
||||
ACTIVATE_NUM_STATES,
|
||||
};
|
||||
|
||||
static void
|
||||
init_reqs_ctrl_cb (FpiUsbTransfer *transfer, FpDevice *device,
|
||||
gpointer user_data, GError *error)
|
||||
{
|
||||
if (!error)
|
||||
fpi_ssm_next_state (transfer->ssm);
|
||||
else
|
||||
fpi_ssm_mark_failed (transfer->ssm, error);
|
||||
}
|
||||
|
||||
static void
|
||||
init_reqs_cb (FpiUsbTransfer *transfer, FpDevice *device,
|
||||
gpointer user_data, GError *error)
|
||||
@@ -558,8 +545,7 @@ activate_run_state (FpiSsm *ssm, FpDevice *dev)
|
||||
transfer->buffer[0] = '\0';
|
||||
transfer->ssm = ssm;
|
||||
fpi_usb_transfer_submit (transfer, CTRL_TIMEOUT, NULL,
|
||||
init_reqs_ctrl_cb, NULL);
|
||||
fpi_usb_transfer_unref (transfer);
|
||||
fpi_ssm_usb_transfer_cb, NULL);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -601,7 +587,6 @@ activate_sm_complete (FpiSsm *ssm, FpDevice *_dev, GError *error)
|
||||
{
|
||||
FpImageDevice *dev = FP_IMAGE_DEVICE (_dev);
|
||||
|
||||
fpi_ssm_free (ssm);
|
||||
fpi_image_device_activate_complete (dev, error);
|
||||
|
||||
if (!error)
|
||||
|
||||
@@ -17,8 +17,7 @@
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef __UPEKTC_IMG_H
|
||||
#define __UPEKTC_IMG_H
|
||||
#pragma once
|
||||
|
||||
static const unsigned char upek2020_init_1[] = {
|
||||
'C', 'i', 'a', 'o',
|
||||
@@ -140,5 +139,3 @@ static const unsigned char upek2020_ack_frame[] = {
|
||||
0x30,
|
||||
0xac, 0x5b /* CRC */
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
+53
-66
@@ -35,7 +35,6 @@
|
||||
#define TIMEOUT 5000
|
||||
|
||||
#define MSG_READ_BUF_SIZE 0x40
|
||||
#define MAX_DATA_IN_READ_BUF (MSG_READ_BUF_SIZE - 9)
|
||||
|
||||
struct _FpiDeviceUpekts
|
||||
{
|
||||
@@ -226,7 +225,6 @@ busy_ack_retry_read (FpDevice *device, struct read_msg_data *udata)
|
||||
transfer->short_is_error = TRUE;
|
||||
|
||||
fpi_usb_transfer_submit (transfer, TIMEOUT, NULL, busy_ack_sent_cb, udata);
|
||||
fpi_usb_transfer_unref (transfer);
|
||||
}
|
||||
|
||||
/* Returns 0 if message was handled, 1 if it was a device-busy message, and
|
||||
@@ -237,12 +235,18 @@ __handle_incoming_msg (FpDevice *device,
|
||||
{
|
||||
GError *error = NULL;
|
||||
guint8 *buf = udata->buffer;
|
||||
guint16 len = ((buf[5] & 0xf) << 8) | buf[6];
|
||||
guint16 computed_crc = udf_crc (buf + 4, len + 3);
|
||||
guint16 msg_crc = (buf[len + 8] << 8) | buf[len + 7];
|
||||
unsigned char *retdata = NULL;
|
||||
guint16 len;
|
||||
guint16 computed_crc;
|
||||
guint16 msg_crc;
|
||||
unsigned char code_a, code_b;
|
||||
|
||||
g_assert (udata->buflen >= 6);
|
||||
len = ((buf[5] & 0xf) << 8) | buf[6];
|
||||
|
||||
g_assert (udata->buflen >= len + 9);
|
||||
computed_crc = udf_crc (buf + 4, len + 3);
|
||||
msg_crc = (buf[len + 8] << 8) | buf[len + 7];
|
||||
|
||||
if (computed_crc != msg_crc)
|
||||
{
|
||||
fp_err ("CRC failed, got %04x expected %04x", msg_crc, computed_crc);
|
||||
@@ -268,12 +272,7 @@ __handle_incoming_msg (FpDevice *device,
|
||||
return;
|
||||
}
|
||||
|
||||
if (len > 0)
|
||||
{
|
||||
retdata = g_malloc (len);
|
||||
memcpy (retdata, buf + 7, len);
|
||||
}
|
||||
udata->callback (device, READ_MSG_CMD, code_a, 0, retdata, len,
|
||||
udata->callback (device, READ_MSG_CMD, code_a, 0, buf + 7, len,
|
||||
udata->user_data, NULL);
|
||||
goto done;
|
||||
}
|
||||
@@ -288,7 +287,7 @@ __handle_incoming_msg (FpDevice *device,
|
||||
{
|
||||
fp_warn ("cmd response too short (%d)", len);
|
||||
error = fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
|
||||
"CMD response too short");
|
||||
"CMD response too short (%d)", len);
|
||||
goto err;
|
||||
}
|
||||
if (innerbuf[0] != 0x28)
|
||||
@@ -310,14 +309,8 @@ __handle_incoming_msg (FpDevice *device,
|
||||
innerlen = innerlen - 3;
|
||||
_subcmd = innerbuf[5];
|
||||
fp_dbg ("device responds to subcmd %x with %d bytes", _subcmd, innerlen);
|
||||
if (innerlen > 0)
|
||||
{
|
||||
retdata = g_malloc (innerlen);
|
||||
memcpy (retdata, innerbuf + 6, innerlen);
|
||||
}
|
||||
udata->callback (device, READ_MSG_RESPONSE, code_b, _subcmd,
|
||||
retdata, innerlen, udata->user_data, NULL);
|
||||
g_free (retdata);
|
||||
innerbuf + 6, innerlen, udata->user_data, NULL);
|
||||
goto done;
|
||||
}
|
||||
else
|
||||
@@ -359,7 +352,8 @@ read_msg_cb (FpiUsbTransfer *transfer, FpDevice *device,
|
||||
gpointer user_data, GError *error)
|
||||
{
|
||||
struct read_msg_data *udata = user_data;
|
||||
guint16 len;
|
||||
guint16 payload_len;
|
||||
gsize packet_len;
|
||||
|
||||
if (error)
|
||||
{
|
||||
@@ -371,11 +365,12 @@ read_msg_cb (FpiUsbTransfer *transfer, FpDevice *device,
|
||||
fp_err ("async msg read too short (%d)",
|
||||
(gint) transfer->actual_length);
|
||||
error = fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
|
||||
"Packet from device was too short");
|
||||
"Packet from device was too short (%lu)",
|
||||
transfer->actual_length);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (strncmp (udata->buffer, "Ciao", 4) != 0)
|
||||
if (strncmp ((char *) udata->buffer, "Ciao", 4) != 0)
|
||||
{
|
||||
fp_err ("no Ciao for you!!");
|
||||
error = fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
|
||||
@@ -383,14 +378,15 @@ read_msg_cb (FpiUsbTransfer *transfer, FpDevice *device,
|
||||
goto err;
|
||||
}
|
||||
|
||||
len = ((udata->buffer[5] & 0xf) << 8) | udata->buffer[6];
|
||||
payload_len = ((udata->buffer[5] & 0xf) << 8) | udata->buffer[6];
|
||||
packet_len = payload_len + 9;
|
||||
if (transfer->actual_length != MSG_READ_BUF_SIZE &&
|
||||
(len + 9) > transfer->actual_length)
|
||||
packet_len > transfer->actual_length)
|
||||
{
|
||||
/* Check that the length claimed inside the message is in line with
|
||||
* the amount of data that was transferred over USB. */
|
||||
fp_err ("msg didn't include enough data, expected=%d recv=%d",
|
||||
len + 9, (gint) transfer->actual_length);
|
||||
(gint) packet_len, (gint) transfer->actual_length);
|
||||
error = fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
|
||||
"Packet from device didn't include data");
|
||||
goto err;
|
||||
@@ -399,14 +395,14 @@ read_msg_cb (FpiUsbTransfer *transfer, FpDevice *device,
|
||||
/* We use a 64 byte buffer for reading messages. However, sometimes
|
||||
* messages are longer, in which case we have to do another USB bulk read
|
||||
* to read the remainder. This is handled below. */
|
||||
if (len > MAX_DATA_IN_READ_BUF)
|
||||
if (packet_len > MSG_READ_BUF_SIZE)
|
||||
{
|
||||
int needed = len - MAX_DATA_IN_READ_BUF;
|
||||
int needed = packet_len - MSG_READ_BUF_SIZE;
|
||||
FpiUsbTransfer *etransfer = fpi_usb_transfer_new (device);
|
||||
|
||||
fp_dbg ("didn't fit in buffer, need to extend by %d bytes", needed);
|
||||
udata->buffer = g_realloc ((gpointer) udata->buffer, len);
|
||||
udata->buflen = len;
|
||||
udata->buffer = g_realloc ((gpointer) udata->buffer, packet_len);
|
||||
udata->buflen = packet_len;
|
||||
|
||||
fpi_usb_transfer_fill_bulk_full (etransfer, EP_IN,
|
||||
udata->buffer + MSG_READ_BUF_SIZE,
|
||||
@@ -415,7 +411,6 @@ read_msg_cb (FpiUsbTransfer *transfer, FpDevice *device,
|
||||
fpi_usb_transfer_submit (etransfer, TIMEOUT,
|
||||
NULL,
|
||||
read_msg_extend_cb, udata);
|
||||
fpi_usb_transfer_unref (etransfer);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -441,7 +436,6 @@ __read_msg_async (FpDevice *device, struct read_msg_data *udata)
|
||||
|
||||
fpi_usb_transfer_fill_bulk_full (transfer, EP_IN, udata->buffer, udata->buflen, NULL);
|
||||
fpi_usb_transfer_submit (transfer, TIMEOUT, NULL, read_msg_cb, udata);
|
||||
fpi_usb_transfer_unref (transfer);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -675,7 +669,6 @@ initsm_send_msg28_handler (FpiSsm *ssm,
|
||||
transfer->ssm = ssm;
|
||||
transfer->short_is_error = TRUE;
|
||||
fpi_usb_transfer_submit (transfer, TIMEOUT, NULL, fpi_ssm_usb_transfer_cb, NULL);
|
||||
fpi_usb_transfer_unref (transfer);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -696,7 +689,6 @@ initsm_run_state (FpiSsm *ssm, FpDevice *dev)
|
||||
transfer->ssm = ssm;
|
||||
transfer->short_is_error = TRUE;
|
||||
fpi_usb_transfer_submit (transfer, TIMEOUT, NULL, fpi_ssm_usb_transfer_cb, NULL);
|
||||
fpi_usb_transfer_unref (transfer);
|
||||
break;
|
||||
|
||||
case READ_MSG03:
|
||||
@@ -704,11 +696,10 @@ initsm_run_state (FpiSsm *ssm, FpDevice *dev)
|
||||
break;
|
||||
|
||||
case SEND_RESP03:;
|
||||
transfer = alloc_send_cmd28_transfer (dev, ++upekdev->seq, init_resp03, sizeof (init_resp03));
|
||||
transfer = alloc_send_cmdresponse_transfer (dev, ++upekdev->seq, init_resp03, sizeof (init_resp03));
|
||||
transfer->ssm = ssm;
|
||||
transfer->short_is_error = TRUE;
|
||||
fpi_usb_transfer_submit (transfer, TIMEOUT, NULL, fpi_ssm_usb_transfer_cb, NULL);
|
||||
fpi_usb_transfer_unref (transfer);
|
||||
break;
|
||||
|
||||
case READ_MSG05:
|
||||
@@ -798,7 +789,8 @@ read_msg01_cb (FpDevice *dev, enum read_msg_type type,
|
||||
{
|
||||
fp_err ("expected seq=1, got %x", seq);
|
||||
fpi_ssm_mark_failed (ssm, fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
|
||||
"Got wrong sequence number"));
|
||||
"Got wrong sequence number (%x)",
|
||||
seq));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -818,7 +810,6 @@ deinitsm_state_handler (FpiSsm *ssm, FpDevice *dev)
|
||||
transfer->short_is_error = TRUE;
|
||||
transfer->ssm = ssm;
|
||||
fpi_usb_transfer_submit (transfer, TIMEOUT, NULL, fpi_ssm_usb_transfer_cb, NULL);
|
||||
fpi_usb_transfer_unref (transfer);
|
||||
break;
|
||||
|
||||
case READ_MSG01:;
|
||||
@@ -861,21 +852,14 @@ dev_init (FpDevice *dev)
|
||||
fpi_ssm_start (ssm, initsm_done);
|
||||
}
|
||||
|
||||
static void
|
||||
deinitsm_done (FpiSsm *ssm, FpDevice *dev, GError *error)
|
||||
{
|
||||
g_usb_device_release_interface (fpi_device_get_usb_device (dev), 0, 0, NULL);
|
||||
|
||||
fpi_device_close_complete (dev, error);
|
||||
}
|
||||
|
||||
static void
|
||||
dev_exit (FpDevice *dev)
|
||||
{
|
||||
FpiSsm *ssm;
|
||||
GError *error = NULL;
|
||||
|
||||
ssm = fpi_ssm_new (dev, deinitsm_state_handler, DEINITSM_NUM_STATES);
|
||||
fpi_ssm_start (ssm, deinitsm_done);
|
||||
g_usb_device_release_interface (fpi_device_get_usb_device (dev), 0, 0, &error);
|
||||
|
||||
fpi_device_close_complete (dev, error);
|
||||
}
|
||||
|
||||
static const unsigned char enroll_init[] = {
|
||||
@@ -907,8 +891,10 @@ enroll_start_sm_cb_msg28 (FpDevice *dev,
|
||||
FpiSsm *ssm = user_data;
|
||||
|
||||
if (error)
|
||||
{
|
||||
fpi_ssm_mark_failed (ssm, error);
|
||||
if (type != READ_MSG_RESPONSE)
|
||||
}
|
||||
else if (type != READ_MSG_RESPONSE)
|
||||
{
|
||||
fp_err ("expected response, got %d seq=%x", type, seq);
|
||||
fpi_ssm_mark_failed (ssm, fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
|
||||
@@ -951,7 +937,6 @@ enroll_start_sm_run_state (FpiSsm *ssm, FpDevice *dev)
|
||||
transfer->ssm = ssm;
|
||||
|
||||
fpi_usb_transfer_submit (transfer, TIMEOUT, NULL, fpi_ssm_usb_transfer_cb, NULL);
|
||||
fpi_usb_transfer_unref (transfer);
|
||||
break;
|
||||
|
||||
case READ_ENROLL_MSG28:;
|
||||
@@ -987,8 +972,9 @@ enroll_stop_deinit_cb (FpiSsm *ssm, FpDevice *dev, GError *error)
|
||||
if (error)
|
||||
fp_warn ("Error deinitializing: %s", error->message);
|
||||
|
||||
fpi_device_enroll_complete (dev, data->print, data->error);
|
||||
fpi_ssm_free (ssm);
|
||||
fpi_device_enroll_complete (dev,
|
||||
g_steal_pointer (&data->print),
|
||||
g_steal_pointer (&data->error));
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -997,7 +983,7 @@ do_enroll_stop (FpDevice *dev, FpPrint *print, GError *error)
|
||||
EnrollStopData *data = g_new0 (EnrollStopData, 1);
|
||||
FpiSsm *ssm = deinitsm_new (dev, data);
|
||||
|
||||
data->print = g_object_ref (print);
|
||||
data->print = print;
|
||||
data->error = error;
|
||||
|
||||
fpi_ssm_start (ssm, enroll_stop_deinit_cb);
|
||||
@@ -1124,7 +1110,6 @@ e_handle_resp02 (FpDevice *dev, unsigned char *data,
|
||||
else
|
||||
{
|
||||
GVariant *fp_data;
|
||||
print = fp_print_new (dev);
|
||||
|
||||
fpi_device_get_enroll_data (dev, &print);
|
||||
|
||||
@@ -1133,7 +1118,8 @@ e_handle_resp02 (FpDevice *dev, unsigned char *data,
|
||||
data_len - sizeof (scan_comp),
|
||||
1);
|
||||
|
||||
g_object_set (print, "fp-data", fp_data, NULL);
|
||||
fpi_print_set_type (print, FPI_PRINT_RAW);
|
||||
g_object_set (print, "fpi-data", fp_data, NULL);
|
||||
g_object_ref (print);
|
||||
}
|
||||
|
||||
@@ -1204,7 +1190,6 @@ enroll_iterate (FpDevice *dev)
|
||||
transfer->short_is_error = TRUE;
|
||||
|
||||
fpi_usb_transfer_submit (transfer, TIMEOUT, NULL, enroll_iterate_cmd_cb, NULL);
|
||||
fpi_usb_transfer_unref (transfer);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1215,7 +1200,6 @@ enroll_started (FpiSsm *ssm, FpDevice *dev, GError *error)
|
||||
else
|
||||
enroll_iterate (dev);
|
||||
|
||||
fpi_ssm_free (ssm);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1234,7 +1218,6 @@ enroll (FpDevice *dev)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
FpiMatchResult res;
|
||||
GError *error;
|
||||
} VerifyStopData;
|
||||
|
||||
@@ -1253,8 +1236,12 @@ verify_stop_deinit_cb (FpiSsm *ssm, FpDevice *dev, GError *error)
|
||||
if (error)
|
||||
fp_warn ("Error deinitializing: %s", error->message);
|
||||
|
||||
fpi_device_verify_complete (dev, data->res, NULL, data->error);
|
||||
fpi_ssm_free (ssm);
|
||||
if (data->error)
|
||||
fpi_device_verify_complete (dev, g_steal_pointer (&data->error));
|
||||
else
|
||||
fpi_device_verify_complete (dev, g_steal_pointer (&error));
|
||||
|
||||
g_clear_error (&error);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1263,7 +1250,10 @@ do_verify_stop (FpDevice *dev, FpiMatchResult res, GError *error)
|
||||
VerifyStopData *data = g_new0 (VerifyStopData, 1);
|
||||
FpiSsm *ssm = deinitsm_new (dev, data);
|
||||
|
||||
data->res = res;
|
||||
/* Report the error immediately if possible, otherwise delay it. */
|
||||
if (error && error->domain == FP_DEVICE_RETRY)
|
||||
fpi_device_verify_report (dev, res, NULL, error);
|
||||
else
|
||||
data->error = error;
|
||||
|
||||
fpi_ssm_start (ssm, verify_stop_deinit_cb);
|
||||
@@ -1303,7 +1293,7 @@ verify_start_sm_run_state (FpiSsm *ssm, FpDevice *dev)
|
||||
|
||||
case VERIFY_INIT:
|
||||
fpi_device_get_verify_data (dev, &print);
|
||||
g_object_get (dev, "fp-data", &fp_data, NULL);
|
||||
g_object_get (print, "fpi-data", &fp_data, NULL);
|
||||
|
||||
data = g_variant_get_fixed_array (fp_data, &data_len, 1);
|
||||
|
||||
@@ -1320,7 +1310,6 @@ verify_start_sm_run_state (FpiSsm *ssm, FpDevice *dev)
|
||||
transfer->short_is_error = TRUE;
|
||||
transfer->ssm = ssm;
|
||||
fpi_usb_transfer_submit (transfer, TIMEOUT, NULL, fpi_ssm_usb_transfer_cb, NULL);
|
||||
fpi_usb_transfer_unref (transfer);
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -1520,7 +1509,6 @@ verify_iterate (FpDevice *dev)
|
||||
transfer->short_is_error = TRUE;
|
||||
|
||||
fpi_usb_transfer_submit (transfer, TIMEOUT, NULL, verify_wr2800_cb, NULL);
|
||||
fpi_usb_transfer_unref (transfer);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1538,7 +1526,6 @@ verify_started (FpiSsm *ssm, FpDevice *dev, GError *error)
|
||||
upekdev->first_verify_iteration = TRUE;
|
||||
verify_iterate (dev);
|
||||
|
||||
fpi_ssm_free (ssm);
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
+43
-67
@@ -122,7 +122,7 @@ struct _FpiDeviceUru4000
|
||||
|
||||
const struct uru4k_dev_profile *profile;
|
||||
uint8_t interface;
|
||||
FpImageDeviceState activate_state;
|
||||
FpiImageDeviceState activate_state;
|
||||
unsigned char last_reg_rd[16];
|
||||
unsigned char last_hwstat;
|
||||
|
||||
@@ -175,13 +175,12 @@ write_regs (FpImageDevice *dev, uint16_t first_reg,
|
||||
transfer->short_is_error = TRUE;
|
||||
fpi_usb_transfer_fill_control (transfer,
|
||||
G_USB_DEVICE_DIRECTION_HOST_TO_DEVICE,
|
||||
G_USB_DEVICE_REQUEST_TYPE_STANDARD,
|
||||
G_USB_DEVICE_REQUEST_TYPE_VENDOR,
|
||||
G_USB_DEVICE_RECIPIENT_DEVICE,
|
||||
USB_RQ, first_reg, 0,
|
||||
num_regs);
|
||||
memcpy (transfer->buffer, values, num_regs);
|
||||
fpi_usb_transfer_submit (transfer, CTRL_TIMEOUT, NULL, callback, user_data);
|
||||
fpi_usb_transfer_unref (transfer);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -203,11 +202,10 @@ read_regs (FpImageDevice *dev, uint16_t first_reg,
|
||||
|
||||
fpi_usb_transfer_fill_control (transfer,
|
||||
G_USB_DEVICE_DIRECTION_DEVICE_TO_HOST,
|
||||
G_USB_DEVICE_REQUEST_TYPE_STANDARD,
|
||||
G_USB_DEVICE_REQUEST_TYPE_VENDOR,
|
||||
G_USB_DEVICE_RECIPIENT_DEVICE,
|
||||
USB_RQ, first_reg, 0, num_regs);
|
||||
fpi_usb_transfer_submit (transfer, CTRL_TIMEOUT, NULL, callback, user_data);
|
||||
fpi_usb_transfer_unref (transfer);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -334,6 +332,8 @@ irq_handler (FpiUsbTransfer *transfer,
|
||||
return;
|
||||
}
|
||||
|
||||
start_irq_handler (imgdev);
|
||||
|
||||
type = GUINT16_FROM_BE (*((uint16_t *) data));
|
||||
fp_dbg ("recv irq type %04x", type);
|
||||
|
||||
@@ -346,8 +346,6 @@ irq_handler (FpiUsbTransfer *transfer,
|
||||
urudev->irq_cb (imgdev, NULL, type, urudev->irq_cb_data);
|
||||
else
|
||||
fp_dbg ("ignoring interrupt");
|
||||
|
||||
start_irq_handler (imgdev);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -365,7 +363,6 @@ start_irq_handler (FpImageDevice *dev)
|
||||
EP_INTR,
|
||||
IRQ_LENGTH);
|
||||
fpi_usb_transfer_submit (transfer, 0, self->irq_cancellable, irq_handler, NULL);
|
||||
fpi_usb_transfer_unref (transfer);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -411,16 +408,16 @@ change_state_write_reg_cb (FpiUsbTransfer *transfer,
|
||||
}
|
||||
|
||||
static void
|
||||
dev_change_state (FpImageDevice *dev, FpImageDeviceState state)
|
||||
dev_change_state (FpImageDevice *dev, FpiImageDeviceState state)
|
||||
{
|
||||
FpiDeviceUru4000 *self = FPI_DEVICE_URU4000 (dev);
|
||||
|
||||
switch (state)
|
||||
{
|
||||
case FP_IMAGE_DEVICE_STATE_INACTIVE:
|
||||
case FP_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON:
|
||||
case FP_IMAGE_DEVICE_STATE_AWAIT_FINGER_OFF:
|
||||
case FP_IMAGE_DEVICE_STATE_CAPTURE:
|
||||
case FPI_IMAGE_DEVICE_STATE_INACTIVE:
|
||||
case FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON:
|
||||
case FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_OFF:
|
||||
case FPI_IMAGE_DEVICE_STATE_CAPTURE:
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -776,7 +773,7 @@ imaging_run_state (FpiSsm *ssm, FpDevice *_dev)
|
||||
fpimg->flags |= FPI_IMAGE_V_FLIPPED | FPI_IMAGE_H_FLIPPED;
|
||||
fpi_image_device_image_captured (dev, fpimg);
|
||||
|
||||
if (self->activate_state == FP_IMAGE_DEVICE_STATE_CAPTURE)
|
||||
if (self->activate_state == FPI_IMAGE_DEVICE_STATE_CAPTURE)
|
||||
fpi_ssm_jump_to_state (ssm, IMAGING_CAPTURE);
|
||||
else
|
||||
fpi_ssm_mark_completed (ssm);
|
||||
@@ -789,7 +786,6 @@ imaging_complete (FpiSsm *ssm, FpDevice *dev, GError *error)
|
||||
{
|
||||
FpiDeviceUru4000 *self = FPI_DEVICE_URU4000 (dev);
|
||||
|
||||
fpi_ssm_free (ssm);
|
||||
|
||||
/* Report error before exiting imaging loop - the error handler
|
||||
* can request state change, which needs to be postponed to end of
|
||||
@@ -833,26 +829,6 @@ enum rebootpwr_states {
|
||||
REBOOTPWR_NUM_STATES,
|
||||
};
|
||||
|
||||
static void
|
||||
rebootpwr_pause_cb (FpDevice *dev,
|
||||
void *data)
|
||||
{
|
||||
FpiSsm *ssm = data;
|
||||
FpiDeviceUru4000 *self = FPI_DEVICE_URU4000 (dev);
|
||||
|
||||
if (!--self->rebootpwr_ctr)
|
||||
{
|
||||
fp_err ("could not reboot device power");
|
||||
fpi_ssm_mark_failed (ssm,
|
||||
fpi_device_error_new_msg (FP_DEVICE_ERROR,
|
||||
"Could not reboot device"));
|
||||
}
|
||||
else
|
||||
{
|
||||
fpi_ssm_jump_to_state (ssm, REBOOTPWR_GET_HWSTAT);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
rebootpwr_run_state (FpiSsm *ssm, FpDevice *_dev)
|
||||
{
|
||||
@@ -879,7 +855,17 @@ rebootpwr_run_state (FpiSsm *ssm, FpDevice *_dev)
|
||||
break;
|
||||
|
||||
case REBOOTPWR_PAUSE:
|
||||
fpi_device_add_timeout (_dev, 10, rebootpwr_pause_cb, ssm);
|
||||
if (!--self->rebootpwr_ctr)
|
||||
{
|
||||
fp_err ("could not reboot device power");
|
||||
fpi_ssm_mark_failed (ssm,
|
||||
fpi_device_error_new_msg (FP_DEVICE_ERROR,
|
||||
"Could not reboot device"));
|
||||
}
|
||||
else
|
||||
{
|
||||
fpi_ssm_jump_to_state_delayed (ssm, 10, REBOOTPWR_GET_HWSTAT, NULL);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -920,30 +906,6 @@ enum powerup_states {
|
||||
POWERUP_NUM_STATES,
|
||||
};
|
||||
|
||||
static void
|
||||
powerup_pause_cb (FpDevice *dev,
|
||||
void *data)
|
||||
{
|
||||
FpiSsm *ssm = data;
|
||||
FpiDeviceUru4000 *self = FPI_DEVICE_URU4000 (dev);
|
||||
|
||||
if (!--self->powerup_ctr)
|
||||
{
|
||||
fp_err ("could not power device up");
|
||||
fpi_ssm_mark_failed (ssm,
|
||||
fpi_device_error_new_msg (FP_DEVICE_ERROR_GENERAL,
|
||||
"could not power device up"));
|
||||
}
|
||||
else if (!self->profile->auth_cr)
|
||||
{
|
||||
fpi_ssm_jump_to_state (ssm, POWERUP_SET_HWSTAT);
|
||||
}
|
||||
else
|
||||
{
|
||||
fpi_ssm_next_state (ssm);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
powerup_run_state (FpiSsm *ssm, FpDevice *_dev)
|
||||
{
|
||||
@@ -975,7 +937,21 @@ powerup_run_state (FpiSsm *ssm, FpDevice *_dev)
|
||||
break;
|
||||
|
||||
case POWERUP_PAUSE:
|
||||
fpi_device_add_timeout (_dev, 10, powerup_pause_cb, ssm);
|
||||
if (!--self->powerup_ctr)
|
||||
{
|
||||
fp_err ("could not power device up");
|
||||
fpi_ssm_mark_failed (ssm,
|
||||
fpi_device_error_new_msg (FP_DEVICE_ERROR_GENERAL,
|
||||
"could not power device up"));
|
||||
}
|
||||
else if (!self->profile->auth_cr)
|
||||
{
|
||||
fpi_ssm_jump_to_state_delayed (ssm, POWERUP_SET_HWSTAT, 10, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
fpi_ssm_next_state_delayed (ssm, 10, NULL);
|
||||
}
|
||||
break;
|
||||
|
||||
case POWERUP_CHALLENGE_RESPONSE:
|
||||
@@ -1134,7 +1110,7 @@ init_run_state (FpiSsm *ssm, FpDevice *_dev)
|
||||
self->scanpwr_irq_timeout = fpi_device_add_timeout (_dev,
|
||||
300,
|
||||
init_scanpwr_timeout,
|
||||
ssm);
|
||||
ssm, NULL);
|
||||
break;
|
||||
|
||||
case INIT_DONE:
|
||||
@@ -1200,7 +1176,7 @@ deactivate_write_reg_cb (FpiUsbTransfer *transfer, FpDevice *dev,
|
||||
static void
|
||||
dev_deactivate (FpImageDevice *dev)
|
||||
{
|
||||
dev_change_state (dev, FP_IMAGE_DEVICE_STATE_INACTIVE);
|
||||
dev_change_state (dev, FPI_IMAGE_DEVICE_STATE_INACTIVE);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1211,7 +1187,7 @@ execute_state_change (FpImageDevice *dev)
|
||||
|
||||
switch (self->activate_state)
|
||||
{
|
||||
case FP_IMAGE_DEVICE_STATE_INACTIVE:
|
||||
case FPI_IMAGE_DEVICE_STATE_INACTIVE:
|
||||
fp_dbg ("deactivating");
|
||||
self->irq_cb = NULL;
|
||||
self->irq_cb_data = NULL;
|
||||
@@ -1219,7 +1195,7 @@ execute_state_change (FpImageDevice *dev)
|
||||
deactivate_write_reg_cb, NULL);
|
||||
break;
|
||||
|
||||
case FP_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON:
|
||||
case FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON:
|
||||
fp_dbg ("wait finger on");
|
||||
if (!IRQ_HANDLER_IS_RUNNING (self))
|
||||
{
|
||||
@@ -1233,7 +1209,7 @@ execute_state_change (FpImageDevice *dev)
|
||||
change_state_write_reg_cb, NULL);
|
||||
break;
|
||||
|
||||
case FP_IMAGE_DEVICE_STATE_CAPTURE:
|
||||
case FPI_IMAGE_DEVICE_STATE_CAPTURE:
|
||||
fp_dbg ("starting capture");
|
||||
self->irq_cb = NULL;
|
||||
|
||||
@@ -1253,7 +1229,7 @@ execute_state_change (FpImageDevice *dev)
|
||||
change_state_write_reg_cb, NULL);
|
||||
break;
|
||||
|
||||
case FP_IMAGE_DEVICE_STATE_AWAIT_FINGER_OFF:
|
||||
case FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_OFF:
|
||||
fp_dbg ("await finger off");
|
||||
if (!IRQ_HANDLER_IS_RUNNING (self))
|
||||
{
|
||||
|
||||
@@ -76,16 +76,6 @@ enum v5s_cmd {
|
||||
|
||||
/***** REGISTER I/O *****/
|
||||
|
||||
static void
|
||||
sm_write_reg_cb (FpiUsbTransfer *transfer, FpDevice *device,
|
||||
gpointer user_data, GError *error)
|
||||
{
|
||||
if (error)
|
||||
fpi_ssm_mark_failed (transfer->ssm, error);
|
||||
else
|
||||
fpi_ssm_next_state (transfer->ssm);
|
||||
}
|
||||
|
||||
static void
|
||||
sm_write_reg (FpiSsm *ssm,
|
||||
FpDevice *dev,
|
||||
@@ -101,19 +91,8 @@ sm_write_reg (FpiSsm *ssm,
|
||||
G_USB_DEVICE_RECIPIENT_DEVICE,
|
||||
reg, value, 0, 0);
|
||||
transfer->ssm = ssm;
|
||||
fpi_usb_transfer_submit (transfer, CTRL_TIMEOUT, NULL, sm_write_reg_cb,
|
||||
NULL);
|
||||
fpi_usb_transfer_unref (transfer);
|
||||
}
|
||||
|
||||
static void
|
||||
sm_exec_cmd_cb (FpiUsbTransfer *transfer, FpDevice *device,
|
||||
gpointer user_data, GError *error)
|
||||
{
|
||||
if (error)
|
||||
fpi_ssm_mark_failed (transfer->ssm, error);
|
||||
else
|
||||
fpi_ssm_next_state (transfer->ssm);
|
||||
fpi_usb_transfer_submit (transfer, CTRL_TIMEOUT, NULL,
|
||||
fpi_ssm_usb_transfer_cb, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -131,9 +110,8 @@ sm_exec_cmd (FpiSsm *ssm,
|
||||
G_USB_DEVICE_RECIPIENT_DEVICE,
|
||||
cmd, param, 0, 0);
|
||||
transfer->ssm = ssm;
|
||||
fpi_usb_transfer_submit (transfer, CTRL_TIMEOUT, NULL, sm_exec_cmd_cb,
|
||||
NULL);
|
||||
fpi_usb_transfer_unref (transfer);
|
||||
fpi_usb_transfer_submit (transfer, CTRL_TIMEOUT, NULL,
|
||||
fpi_ssm_usb_transfer_cb, NULL);
|
||||
}
|
||||
|
||||
/***** FINGER DETECTION *****/
|
||||
@@ -227,7 +205,6 @@ capture_iterate (FpiSsm *ssm,
|
||||
NULL);
|
||||
|
||||
fpi_usb_transfer_submit (transfer, CTRL_TIMEOUT, NULL, capture_cb, NULL);
|
||||
fpi_usb_transfer_unref (transfer);
|
||||
}
|
||||
|
||||
|
||||
@@ -301,7 +278,6 @@ loopsm_complete (FpiSsm *ssm, FpDevice *dev, GError *error)
|
||||
FpImageDevice *imgdev = FP_IMAGE_DEVICE (dev);
|
||||
FpDeviceVcom5s *self = FPI_DEVICE_VCOM5S (dev);
|
||||
|
||||
fpi_ssm_free (ssm);
|
||||
g_object_unref (self->capture_img);
|
||||
self->capture_img = NULL;
|
||||
self->loop_running = FALSE;
|
||||
|
||||
+14
-27
@@ -56,7 +56,6 @@ async_write (FpiSsm *ssm,
|
||||
transfer->short_is_error = TRUE;
|
||||
fpi_usb_transfer_submit (transfer, VFS_USB_TIMEOUT, NULL,
|
||||
async_write_callback, NULL);
|
||||
fpi_usb_transfer_unref (transfer);
|
||||
}
|
||||
|
||||
/* Callback for async_read */
|
||||
@@ -108,7 +107,6 @@ async_read (FpiSsm *ssm,
|
||||
|
||||
fpi_usb_transfer_submit (transfer, VFS_USB_TIMEOUT, NULL,
|
||||
async_read_callback, NULL);
|
||||
fpi_usb_transfer_unref (transfer);
|
||||
}
|
||||
|
||||
/* Callback for async_abort */
|
||||
@@ -121,7 +119,7 @@ async_abort_callback (FpiUsbTransfer *transfer, FpDevice *device,
|
||||
/* In normal case endpoint is empty */
|
||||
if (g_error_matches (error, G_USB_DEVICE_ERROR, G_USB_DEVICE_ERROR_TIMED_OUT))
|
||||
{
|
||||
g_free (error);
|
||||
g_error_free (error);
|
||||
fpi_ssm_next_state (transfer->ssm);
|
||||
return;
|
||||
}
|
||||
@@ -158,9 +156,10 @@ async_abort (FpDevice *dev, FpiSsm *ssm, int ep)
|
||||
else
|
||||
fpi_usb_transfer_fill_bulk (transfer, ep, VFS_USB_BUFFER_SIZE);
|
||||
|
||||
transfer->ssm = ssm;
|
||||
|
||||
fpi_usb_transfer_submit (transfer, VFS_USB_ABORT_TIMEOUT, NULL,
|
||||
async_abort_callback, NULL);
|
||||
fpi_usb_transfer_unref (transfer);
|
||||
}
|
||||
|
||||
/* Image processing functions */
|
||||
@@ -243,6 +242,7 @@ prepare_image (FpDeviceVfs0050 *vdev)
|
||||
|
||||
/* Building GSList */
|
||||
GSList *lines = NULL;
|
||||
|
||||
for (int i = height - 1; i >= 0; --i)
|
||||
lines = g_slist_prepend (lines, vdev->lines_buffer + i);
|
||||
|
||||
@@ -402,7 +402,7 @@ interrupt_callback (FpiUsbTransfer *transfer, FpDevice *device,
|
||||
gpointer user_data, GError *error)
|
||||
{
|
||||
FpDeviceVfs0050 *self = FPI_DEVICE_VFS0050 (device);
|
||||
char *interrupt = transfer->buffer;
|
||||
unsigned char *interrupt = transfer->buffer;
|
||||
|
||||
/* we expect a cancellation error when the device is deactivating
|
||||
* go into the SSM_CLEAR_EP2 state in that case. */
|
||||
@@ -467,8 +467,8 @@ receive_callback (FpiUsbTransfer *transfer, FpDevice *device,
|
||||
if (error)
|
||||
g_error_free (error);
|
||||
|
||||
/* Check if fingerprint data is over */
|
||||
if (transfer->actual_length == 0)
|
||||
/* Capture is done when there is no more data to transfer or device timed out */
|
||||
if (transfer->actual_length <= 0)
|
||||
{
|
||||
fpi_ssm_next_state (transfer->ssm);
|
||||
}
|
||||
@@ -476,22 +476,12 @@ receive_callback (FpiUsbTransfer *transfer, FpDevice *device,
|
||||
{
|
||||
self->bytes += transfer->actual_length;
|
||||
|
||||
/* We need more data */
|
||||
/* Try reading more data */
|
||||
fpi_ssm_jump_to_state (transfer->ssm,
|
||||
fpi_ssm_get_cur_state (transfer->ssm));
|
||||
}
|
||||
}
|
||||
|
||||
/* SSM stub to prepare device to another scan after orange light was on */
|
||||
static void
|
||||
another_scan (FpDevice *dev,
|
||||
void *data)
|
||||
{
|
||||
FpiSsm *ssm = data;
|
||||
|
||||
fpi_ssm_jump_to_state (ssm, SSM_TURN_ON);
|
||||
}
|
||||
|
||||
/* Main SSM loop */
|
||||
static void
|
||||
activate_ssm (FpiSsm *ssm, FpDevice *dev)
|
||||
@@ -564,7 +554,6 @@ activate_ssm (FpiSsm *ssm, FpDevice *dev)
|
||||
0,
|
||||
fpi_device_get_cancellable (dev),
|
||||
interrupt_callback, NULL);
|
||||
fpi_usb_transfer_unref (transfer);
|
||||
|
||||
/* I've put it here to be sure that data is cleared */
|
||||
clear_data (self);
|
||||
@@ -609,12 +598,11 @@ activate_ssm (FpiSsm *ssm, FpDevice *dev)
|
||||
/* Receive chunk of data */
|
||||
transfer = fpi_usb_transfer_new (dev);
|
||||
fpi_usb_transfer_fill_bulk_full (transfer, 0x82,
|
||||
(void *) self->lines_buffer + self->bytes,
|
||||
(guint8 *) self->lines_buffer + self->bytes,
|
||||
VFS_USB_BUFFER_SIZE, NULL);
|
||||
transfer->ssm = ssm;
|
||||
fpi_usb_transfer_submit (transfer, VFS_USB_TIMEOUT, NULL,
|
||||
receive_callback, NULL);
|
||||
fpi_usb_transfer_unref (transfer);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -623,8 +611,7 @@ activate_ssm (FpiSsm *ssm, FpDevice *dev)
|
||||
clear_data (self);
|
||||
|
||||
/* Wait for probable vdev->active changing */
|
||||
fpi_device_add_timeout (dev, VFS_SSM_TIMEOUT,
|
||||
fpi_ssm_next_state_timeout_cb, ssm);
|
||||
fpi_ssm_next_state_delayed (ssm, VFS_SSM_TIMEOUT, NULL);
|
||||
break;
|
||||
|
||||
case SSM_NEXT_RECEIVE:
|
||||
@@ -643,8 +630,8 @@ activate_ssm (FpiSsm *ssm, FpDevice *dev)
|
||||
|
||||
case SSM_WAIT_ANOTHER_SCAN:
|
||||
/* Orange light is on now */
|
||||
fpi_device_add_timeout (dev, VFS_SSM_ORANGE_TIMEOUT,
|
||||
another_scan, ssm);
|
||||
fpi_ssm_jump_to_state_delayed (ssm, SSM_TURN_ON, VFS_SSM_ORANGE_TIMEOUT,
|
||||
NULL);
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -669,7 +656,6 @@ dev_activate_callback (FpiSsm *ssm, FpDevice *dev, GError *error)
|
||||
g_error_free (error);
|
||||
}
|
||||
|
||||
fpi_ssm_free (ssm);
|
||||
}
|
||||
|
||||
/* Activate device */
|
||||
@@ -684,6 +670,7 @@ dev_activate (FpImageDevice *idev)
|
||||
self->ssm_active = 1;
|
||||
|
||||
FpiSsm *ssm = fpi_ssm_new (FP_DEVICE (idev), activate_ssm, SSM_STATES);
|
||||
|
||||
fpi_ssm_start (ssm, dev_activate_callback);
|
||||
}
|
||||
|
||||
@@ -710,7 +697,6 @@ dev_open_callback (FpiSsm *ssm, FpDevice *dev, GError *error)
|
||||
{
|
||||
/* Notify open complete */
|
||||
fpi_image_device_open_complete (FP_IMAGE_DEVICE (dev), error);
|
||||
fpi_ssm_free (ssm);
|
||||
}
|
||||
|
||||
/* Open device */
|
||||
@@ -728,6 +714,7 @@ dev_open (FpImageDevice *idev)
|
||||
|
||||
/* Clearing previous device state */
|
||||
FpiSsm *ssm = fpi_ssm_new (FP_DEVICE (idev), activate_ssm, SSM_STATES);
|
||||
|
||||
fpi_ssm_start (ssm, dev_open_callback);
|
||||
}
|
||||
|
||||
|
||||
@@ -219,7 +219,6 @@ async_send (FpiSsm *ssm,
|
||||
transfer->short_is_error = TRUE;
|
||||
fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
|
||||
async_send_cb, NULL);
|
||||
fpi_usb_transfer_unref (transfer);
|
||||
}
|
||||
|
||||
/* Callback of asynchronous recv */
|
||||
@@ -282,7 +281,6 @@ async_recv (FpiSsm *ssm,
|
||||
transfer->ssm = ssm;
|
||||
fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
|
||||
async_recv_cb, NULL);
|
||||
fpi_usb_transfer_unref (transfer);
|
||||
}
|
||||
|
||||
static void async_load (FpiSsm *ssm,
|
||||
@@ -369,17 +367,6 @@ async_load (FpiSsm *ssm,
|
||||
transfer->ssm = ssm;
|
||||
fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
|
||||
async_load_cb, NULL);
|
||||
fpi_usb_transfer_unref (transfer);
|
||||
}
|
||||
|
||||
/* Submit asynchronous sleep */
|
||||
static void
|
||||
async_sleep (unsigned int msec,
|
||||
FpiSsm *ssm,
|
||||
FpImageDevice *dev)
|
||||
{
|
||||
fpi_device_add_timeout (FP_DEVICE (dev), msec,
|
||||
fpi_ssm_next_state_timeout_cb, ssm);
|
||||
}
|
||||
|
||||
/* Swap ssm states */
|
||||
@@ -798,7 +785,7 @@ m_loop_state (FpiSsm *ssm, FpDevice *_dev)
|
||||
|
||||
case M_LOOP_0_SLEEP:
|
||||
/* Wait fingerprint scanning */
|
||||
async_sleep (50, ssm, dev);
|
||||
fpi_ssm_next_state_delayed (ssm, 50, NULL);
|
||||
break;
|
||||
|
||||
case M_LOOP_0_GET_STATE:
|
||||
@@ -841,7 +828,7 @@ m_loop_state (FpiSsm *ssm, FpDevice *_dev)
|
||||
img_extract (ssm, dev);
|
||||
|
||||
/* Wait handling image */
|
||||
async_sleep (10, ssm, dev);
|
||||
fpi_ssm_next_state_delayed (ssm, 10, NULL);
|
||||
break;
|
||||
|
||||
case M_LOOP_0_CHECK_ACTION:
|
||||
@@ -864,7 +851,7 @@ m_loop_state (FpiSsm *ssm, FpDevice *_dev)
|
||||
if (vfs_finger_state (self) == VFS_FINGER_PRESENT)
|
||||
{
|
||||
fpi_image_device_report_finger_status (dev, TRUE);
|
||||
async_sleep (250, ssm, dev);
|
||||
fpi_ssm_next_state_delayed (ssm, 250, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -894,7 +881,7 @@ m_loop_state (FpiSsm *ssm, FpDevice *_dev)
|
||||
|
||||
case M_LOOP_1_SLEEP:
|
||||
/* Wait fingerprint scanning */
|
||||
async_sleep (10, ssm, dev);
|
||||
fpi_ssm_next_state_delayed (ssm, 10, NULL);
|
||||
break;
|
||||
|
||||
case M_LOOP_2_ABORT_PRINT:
|
||||
@@ -930,7 +917,7 @@ m_loop_state (FpiSsm *ssm, FpDevice *_dev)
|
||||
{
|
||||
/* Wait aborting */
|
||||
self->counter++;
|
||||
async_sleep (100, ssm, dev);
|
||||
fpi_ssm_next_state_delayed (ssm, 100, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -960,7 +947,6 @@ m_loop_complete (FpiSsm *ssm, FpDevice *dev, GError *error)
|
||||
|
||||
self->active = FALSE;
|
||||
|
||||
fpi_ssm_free (ssm);
|
||||
}
|
||||
|
||||
/* Init ssm states */
|
||||
@@ -1069,7 +1055,7 @@ m_init_state (FpiSsm *ssm, FpDevice *_dev)
|
||||
{
|
||||
/* Wait aborting */
|
||||
self->counter++;
|
||||
async_sleep (100, ssm, dev);
|
||||
fpi_ssm_next_state_delayed (ssm, 100, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1098,7 +1084,7 @@ m_init_state (FpiSsm *ssm, FpDevice *_dev)
|
||||
{
|
||||
/* Wait removing finger */
|
||||
self->counter++;
|
||||
async_sleep (250, ssm, dev);
|
||||
fpi_ssm_next_state_delayed (ssm, 250, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1268,7 +1254,6 @@ m_init_complete (FpiSsm *ssm, FpDevice *_dev, GError *error)
|
||||
}
|
||||
|
||||
/* Free sequential state machine */
|
||||
fpi_ssm_free (ssm);
|
||||
}
|
||||
|
||||
/* Activate device */
|
||||
|
||||
@@ -28,17 +28,6 @@ G_DEFINE_TYPE (FpDeviceVfs301, fpi_device_vfs301, FP_TYPE_IMAGE_DEVICE)
|
||||
|
||||
/************************** GENERIC STUFF *************************************/
|
||||
|
||||
/* Submit asynchronous sleep */
|
||||
static void
|
||||
async_sleep (unsigned int msec,
|
||||
FpiSsm *ssm,
|
||||
FpImageDevice *dev)
|
||||
{
|
||||
/* Add timeout */
|
||||
fpi_device_add_timeout (FP_DEVICE (dev), msec,
|
||||
fpi_ssm_next_state_timeout_cb, ssm);
|
||||
}
|
||||
|
||||
static int
|
||||
submit_image (FpiSsm *ssm,
|
||||
FpImageDevice *dev)
|
||||
@@ -108,7 +97,7 @@ m_loop_state (FpiSsm *ssm, FpDevice *_dev)
|
||||
|
||||
case M_WAIT_PRINT:
|
||||
/* Wait fingerprint scanning */
|
||||
async_sleep (200, ssm, dev);
|
||||
fpi_ssm_next_state_delayed (ssm, 200, NULL);
|
||||
break;
|
||||
|
||||
case M_CHECK_PRINT:
|
||||
@@ -126,7 +115,7 @@ m_loop_state (FpiSsm *ssm, FpDevice *_dev)
|
||||
|
||||
case M_READ_PRINT_WAIT:
|
||||
/* Wait fingerprint scanning */
|
||||
async_sleep (200, ssm, dev);
|
||||
fpi_ssm_next_state_delayed (ssm, 200, NULL);
|
||||
break;
|
||||
|
||||
case M_READ_PRINT_POLL:
|
||||
@@ -168,7 +157,6 @@ m_loop_complete (FpiSsm *ssm, FpDevice *_dev, GError *error)
|
||||
g_error_free (error);
|
||||
}
|
||||
/* Free sequential state machine */
|
||||
fpi_ssm_free (ssm);
|
||||
}
|
||||
|
||||
/* Exec init sequential state machine */
|
||||
@@ -201,7 +189,6 @@ m_init_complete (FpiSsm *ssm, FpDevice *dev, GError *error)
|
||||
}
|
||||
|
||||
/* Free sequential state machine */
|
||||
fpi_ssm_free (ssm);
|
||||
}
|
||||
|
||||
/* Activate device */
|
||||
|
||||
@@ -79,7 +79,6 @@ usb_recv (FpDeviceVfs301 *dev, guint8 endpoint, int max_bytes, FpiUsbTransfer **
|
||||
|
||||
fpi_usb_transfer_submit_sync (transfer, VFS301_DEFAULT_WAIT_TIMEOUT, &err);
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
usb_print_packet (0, err, transfer->buffer, transfer->actual_length);
|
||||
#endif
|
||||
@@ -178,6 +177,7 @@ translate_str (const char **srcL, gssize *len)
|
||||
src_len += tmp;
|
||||
}
|
||||
|
||||
g_assert (src_len >= 2);
|
||||
*len = src_len / 2;
|
||||
res = g_malloc0 (*len);
|
||||
dst = res;
|
||||
@@ -471,7 +471,7 @@ int
|
||||
vfs301_proto_peek_event (FpDeviceVfs301 *dev)
|
||||
{
|
||||
g_autoptr(GError) error = NULL;
|
||||
g_autoptr(FpiUsbTransfer) transfer = NULL;
|
||||
FpiUsbTransfer *transfer;
|
||||
|
||||
const char no_event[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
const char got_event[] = {0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00};
|
||||
@@ -540,7 +540,6 @@ vfs301_proto_process_event_cb (FpiUsbTransfer *transfer,
|
||||
fpi_usb_transfer_fill_bulk (new, VFS301_RECEIVE_ENDPOINT_DATA, VFS301_FP_RECV_LEN_2);
|
||||
fpi_usb_transfer_submit (new, VFS301_FP_RECV_TIMEOUT, NULL,
|
||||
vfs301_proto_process_event_cb, NULL);
|
||||
fpi_usb_transfer_unref (new);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -580,7 +579,6 @@ vfs301_proto_process_event_start (FpDeviceVfs301 *dev)
|
||||
fpi_usb_transfer_fill_bulk (transfer, VFS301_RECEIVE_ENDPOINT_DATA, VFS301_FP_RECV_LEN_1);
|
||||
fpi_usb_transfer_submit (transfer, VFS301_FP_RECV_TIMEOUT, NULL,
|
||||
vfs301_proto_process_event_cb, NULL);
|
||||
fpi_usb_transfer_unref (transfer);
|
||||
}
|
||||
|
||||
int
|
||||
|
||||
+13
-20
@@ -168,7 +168,6 @@ usbexchange_loop (FpiSsm *ssm, FpDevice *_dev)
|
||||
transfer->short_is_error = TRUE;
|
||||
fpi_usb_transfer_submit (transfer, data->timeout, NULL,
|
||||
async_send_cb, NULL);
|
||||
fpi_usb_transfer_unref (transfer);
|
||||
break;
|
||||
|
||||
case ACTION_RECEIVE:
|
||||
@@ -180,7 +179,6 @@ usbexchange_loop (FpiSsm *ssm, FpDevice *_dev)
|
||||
transfer->ssm = ssm;
|
||||
fpi_usb_transfer_submit (transfer, data->timeout, NULL,
|
||||
async_recv_cb, NULL);
|
||||
fpi_usb_transfer_unref (transfer);
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -192,11 +190,13 @@ usbexchange_loop (FpiSsm *ssm, FpDevice *_dev)
|
||||
|
||||
static void
|
||||
usb_exchange_async (FpiSsm *ssm,
|
||||
struct usbexchange_data *data)
|
||||
struct usbexchange_data *data,
|
||||
const char *exchange_name)
|
||||
{
|
||||
FpiSsm *subsm = fpi_ssm_new (FP_DEVICE (data->device),
|
||||
FpiSsm *subsm = fpi_ssm_new_full (FP_DEVICE (data->device),
|
||||
usbexchange_loop,
|
||||
data->stepcount);
|
||||
data->stepcount,
|
||||
exchange_name);
|
||||
|
||||
fpi_ssm_set_data (subsm, data, NULL);
|
||||
fpi_ssm_start_subsm (ssm, subsm);
|
||||
@@ -212,8 +212,8 @@ vfs5011_get_deviation2 (struct fpi_line_asmbl_ctx *ctx, GSList *row1, GSList *ro
|
||||
int res = 0, mean = 0, i;
|
||||
const int size = 64;
|
||||
|
||||
buf1 = row1->data + 56;
|
||||
buf2 = row2->data + 168;
|
||||
buf1 = (unsigned char *) row1->data + 56;
|
||||
buf2 = (unsigned char *) row2->data + 168;
|
||||
|
||||
for (i = 0; i < size; i++)
|
||||
mean += (int) buf1[i] + (int) buf2[i];
|
||||
@@ -234,7 +234,7 @@ vfs5011_get_pixel (struct fpi_line_asmbl_ctx *ctx,
|
||||
GSList *row,
|
||||
unsigned x)
|
||||
{
|
||||
unsigned char *data = row->data + 8;
|
||||
unsigned char *data = (unsigned char *) row->data + 8;
|
||||
|
||||
return data[x];
|
||||
}
|
||||
@@ -381,9 +381,8 @@ submit_image (FpiSsm *ssm,
|
||||
{
|
||||
FpImage *img;
|
||||
|
||||
if (self->lines_recorded == 0)
|
||||
if (self->lines_recorded < VFS5011_IMAGE_WIDTH)
|
||||
{
|
||||
/* == FP_ENROLL_RETRY_TOO_SHORT */
|
||||
fpi_image_device_retry_scan (dev, FP_DEVICE_RETRY_TOO_SHORT);
|
||||
return;
|
||||
}
|
||||
@@ -466,7 +465,6 @@ capture_chunk_async (FpDeviceVfs5011 *self,
|
||||
transfer->ssm = ssm;
|
||||
fpi_usb_transfer_submit (transfer, timeout, fpi_device_get_cancellable (FP_DEVICE (self)),
|
||||
chunk_capture_callback, NULL);
|
||||
fpi_usb_transfer_unref (transfer);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -687,7 +685,7 @@ activate_loop (FpiSsm *ssm, FpDevice *_dev)
|
||||
self->init_sequence.receive_buf =
|
||||
g_malloc0 (VFS5011_RECEIVE_BUF_SIZE);
|
||||
self->init_sequence.timeout = 1000;
|
||||
usb_exchange_async (ssm, &self->init_sequence);
|
||||
usb_exchange_async (ssm, &self->init_sequence, "ACTIVATE REQUEST");
|
||||
break;
|
||||
|
||||
case DEV_ACTIVATE_INIT_COMPLETE:
|
||||
@@ -707,10 +705,7 @@ activate_loop (FpiSsm *ssm, FpDevice *_dev)
|
||||
break;
|
||||
|
||||
case DEV_ACTIVATE_DATA_COMPLETE:
|
||||
fpi_device_add_timeout (_dev, 1,
|
||||
fpi_ssm_next_state_timeout_cb,
|
||||
ssm);
|
||||
|
||||
fpi_ssm_next_state_delayed (ssm, 1, NULL);
|
||||
break;
|
||||
|
||||
case DEV_ACTIVATE_PREPARE_NEXT_CAPTURE:
|
||||
@@ -722,7 +717,7 @@ activate_loop (FpiSsm *ssm, FpDevice *_dev)
|
||||
self->init_sequence.receive_buf =
|
||||
g_malloc0 (VFS5011_RECEIVE_BUF_SIZE);
|
||||
self->init_sequence.timeout = VFS5011_DEFAULT_WAIT_TIMEOUT;
|
||||
usb_exchange_async (ssm, &self->init_sequence);
|
||||
usb_exchange_async (ssm, &self->init_sequence, "PREPARE CAPTURE");
|
||||
break;
|
||||
|
||||
}
|
||||
@@ -745,7 +740,6 @@ activate_loop_complete (FpiSsm *ssm, FpDevice *_dev, GError *error)
|
||||
submit_image (ssm, self, dev);
|
||||
fpi_image_device_report_finger_status (dev, FALSE);
|
||||
}
|
||||
fpi_ssm_free (ssm);
|
||||
|
||||
self->loop_running = FALSE;
|
||||
|
||||
@@ -776,7 +770,7 @@ open_loop (FpiSsm *ssm, FpDevice *_dev)
|
||||
self->init_sequence.receive_buf =
|
||||
g_malloc0 (VFS5011_RECEIVE_BUF_SIZE);
|
||||
self->init_sequence.timeout = VFS5011_DEFAULT_WAIT_TIMEOUT;
|
||||
usb_exchange_async (ssm, &self->init_sequence);
|
||||
usb_exchange_async (ssm, &self->init_sequence, "DEVICE OPEN");
|
||||
break;
|
||||
}
|
||||
;
|
||||
@@ -793,7 +787,6 @@ open_loop_complete (FpiSsm *ssm, FpDevice *_dev, GError *error)
|
||||
self->init_sequence.receive_buf = NULL;
|
||||
|
||||
fpi_image_device_open_complete (dev, error);
|
||||
fpi_ssm_free (ssm);
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
#ifndef __VFS5011_PROTO_H
|
||||
#define __VFS5011_PROTO_H
|
||||
#pragma once
|
||||
|
||||
#define VFS5011_LINE_SIZE 240
|
||||
#define VFS5011_IMAGE_WIDTH 160
|
||||
@@ -6182,5 +6181,3 @@ static unsigned char vfs5011_prepare_04[] = { /* 2903 B */
|
||||
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
|
||||
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
/*
|
||||
* This is a virtual driver to debug the image based drivers. A small
|
||||
* python script is provided to connect to it via a socket, allowing
|
||||
* prints to be sent to this device programatically.
|
||||
* prints to be sent to this device programmatically.
|
||||
* Using this it is possible to test libfprint and fprintd.
|
||||
*/
|
||||
|
||||
@@ -47,6 +47,7 @@ struct _FpDeviceVirtualImage
|
||||
gint socket_fd;
|
||||
gint client_fd;
|
||||
|
||||
gboolean automatic_finger;
|
||||
FpImage *recv_img;
|
||||
gint recv_img_hdr[2];
|
||||
};
|
||||
@@ -66,30 +67,33 @@ recv_image_img_recv_cb (GObject *source_object,
|
||||
g_autoptr(GError) error = NULL;
|
||||
FpDeviceVirtualImage *self;
|
||||
FpImageDevice *device;
|
||||
gssize bytes;
|
||||
gboolean success;
|
||||
gsize bytes = 0;
|
||||
|
||||
bytes = g_input_stream_read_finish (G_INPUT_STREAM (source_object), res, &error);
|
||||
success = g_input_stream_read_all_finish (G_INPUT_STREAM (source_object), res, &bytes, &error);
|
||||
|
||||
if (bytes <= 0)
|
||||
if (!success || bytes == 0)
|
||||
{
|
||||
if (bytes < 0)
|
||||
if (!success)
|
||||
{
|
||||
g_warning ("Error receiving header for image data: %s", error->message);
|
||||
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
||||
return;
|
||||
g_warning ("Error receiving header for image data: %s", error->message);
|
||||
}
|
||||
|
||||
self = FPI_DEVICE_VIRTUAL_IMAGE (user_data);
|
||||
g_io_stream_close (G_IO_STREAM (self->connection), NULL, NULL);
|
||||
self->connection = NULL;
|
||||
g_clear_object (&self->connection);
|
||||
return;
|
||||
}
|
||||
|
||||
self = FPI_DEVICE_VIRTUAL_IMAGE (user_data);
|
||||
device = FP_IMAGE_DEVICE (self);
|
||||
|
||||
if (self->automatic_finger)
|
||||
fpi_image_device_report_finger_status (device, TRUE);
|
||||
fpi_image_device_image_captured (device, g_steal_pointer (&self->recv_img));
|
||||
if (self->automatic_finger)
|
||||
fpi_image_device_report_finger_status (device, FALSE);
|
||||
|
||||
/* And, listen for more images from the same client. */
|
||||
@@ -103,22 +107,24 @@ recv_image_hdr_recv_cb (GObject *source_object,
|
||||
{
|
||||
g_autoptr(GError) error = NULL;
|
||||
FpDeviceVirtualImage *self;
|
||||
gssize bytes;
|
||||
gboolean success;
|
||||
gsize bytes;
|
||||
|
||||
bytes = g_input_stream_read_finish (G_INPUT_STREAM (source_object), res, &error);
|
||||
success = g_input_stream_read_all_finish (G_INPUT_STREAM (source_object), res, &bytes, &error);
|
||||
|
||||
if (bytes <= 0)
|
||||
if (!success || bytes == 0)
|
||||
{
|
||||
if (bytes < 0)
|
||||
if (!success)
|
||||
{
|
||||
g_warning ("Error receiving header for image data: %s", error->message);
|
||||
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
||||
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED) ||
|
||||
g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CLOSED))
|
||||
return;
|
||||
g_warning ("Error receiving header for image data: %s", error->message);
|
||||
}
|
||||
|
||||
self = FPI_DEVICE_VIRTUAL_IMAGE (user_data);
|
||||
g_io_stream_close (G_IO_STREAM (self->connection), NULL, NULL);
|
||||
self->connection = NULL;
|
||||
g_clear_object (&self->connection);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -127,7 +133,7 @@ recv_image_hdr_recv_cb (GObject *source_object,
|
||||
{
|
||||
g_warning ("Image header suggests an unrealistically large image, disconnecting client.");
|
||||
g_io_stream_close (G_IO_STREAM (self->connection), NULL, NULL);
|
||||
self->connection = NULL;
|
||||
g_clear_object (&self->connection);
|
||||
}
|
||||
|
||||
if (self->recv_img_hdr[0] < 0 || self->recv_img_hdr[1] < 0)
|
||||
@@ -145,10 +151,21 @@ recv_image_hdr_recv_cb (GObject *source_object,
|
||||
fpi_device_error_new (self->recv_img_hdr[1]));
|
||||
break;
|
||||
|
||||
case -3:
|
||||
/* -3 sets/clears automatic finger detection for images */
|
||||
self->automatic_finger = !!self->recv_img_hdr[1];
|
||||
break;
|
||||
|
||||
case -4:
|
||||
/* -4 submits a finger detection report */
|
||||
fpi_image_device_report_finger_status (FP_IMAGE_DEVICE (self),
|
||||
!!self->recv_img_hdr[1]);
|
||||
break;
|
||||
|
||||
default:
|
||||
/* disconnect client, it didn't play fair */
|
||||
g_io_stream_close (G_IO_STREAM (self->connection), NULL, NULL);
|
||||
self->connection = NULL;
|
||||
g_clear_object (&self->connection);
|
||||
}
|
||||
|
||||
/* And, listen for more images from the same client. */
|
||||
@@ -158,7 +175,7 @@ recv_image_hdr_recv_cb (GObject *source_object,
|
||||
|
||||
self->recv_img = fp_image_new (self->recv_img_hdr[0], self->recv_img_hdr[1]);
|
||||
g_debug ("image data: %p", self->recv_img->data);
|
||||
g_input_stream_read_async (G_INPUT_STREAM (source_object),
|
||||
g_input_stream_read_all_async (G_INPUT_STREAM (source_object),
|
||||
(guint8 *) self->recv_img->data,
|
||||
self->recv_img->width * self->recv_img->height,
|
||||
G_PRIORITY_DEFAULT,
|
||||
@@ -170,7 +187,7 @@ recv_image_hdr_recv_cb (GObject *source_object,
|
||||
static void
|
||||
recv_image (FpDeviceVirtualImage *dev, GInputStream *stream)
|
||||
{
|
||||
g_input_stream_read_async (stream,
|
||||
g_input_stream_read_all_async (stream,
|
||||
dev->recv_img_hdr,
|
||||
sizeof (dev->recv_img_hdr),
|
||||
G_PRIORITY_DEFAULT,
|
||||
@@ -206,10 +223,12 @@ new_connection_cb (GObject *source_object, GAsyncResult *res, gpointer user_data
|
||||
if (dev->connection)
|
||||
{
|
||||
g_io_stream_close (G_IO_STREAM (connection), NULL, NULL);
|
||||
g_object_unref (connection);
|
||||
return;
|
||||
}
|
||||
|
||||
dev->connection = connection;
|
||||
dev->automatic_finger = TRUE;
|
||||
stream = g_io_stream_get_input_stream (G_IO_STREAM (connection));
|
||||
|
||||
recv_image (dev, stream);
|
||||
@@ -233,6 +252,7 @@ dev_init (FpImageDevice *dev)
|
||||
g_autoptr(GSocketListener) listener = NULL;
|
||||
FpDeviceVirtualImage *self = FPI_DEVICE_VIRTUAL_IMAGE (dev);
|
||||
const char *env;
|
||||
|
||||
g_autoptr(GSocketAddress) addr = NULL;
|
||||
G_DEBUG_HERE ();
|
||||
|
||||
|
||||
+8
-10
@@ -2,6 +2,7 @@
|
||||
* Driver API definitions
|
||||
* Copyright (C) 2007-2008 Daniel Drake <dsd@gentoo.org>
|
||||
* Copyright (C) 2018 Bastien Nocera <hadess@hadess.net>
|
||||
* Copyright (C) 2019 Marco Trevisan <marco.trevisan@canonical.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
@@ -18,17 +19,14 @@
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef __DRIVERS_API_H__
|
||||
#define __DRIVERS_API_H__
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include "fp_internal.h"
|
||||
#pragma once
|
||||
|
||||
#include "fpi-compat.h"
|
||||
#include "fpi-assembling.h"
|
||||
#include "fpi-device.h"
|
||||
#include "fpi-image-device.h"
|
||||
#include "fpi-image.h"
|
||||
#include "fpi-log.h"
|
||||
#include "fpi-print.h"
|
||||
#include "fpi-usb-transfer.h"
|
||||
#include "fpi-ssm.h"
|
||||
#include "fpi-assembling.h"
|
||||
#include "fpi-image-device.h"
|
||||
|
||||
#endif
|
||||
|
||||
+59
-22
@@ -57,6 +57,35 @@ enum {
|
||||
};
|
||||
static guint signals[LAST_SIGNAL] = { 0 };
|
||||
|
||||
static const char *
|
||||
get_drivers_whitelist_env (void)
|
||||
{
|
||||
return g_getenv ("FP_DRIVERS_WHITELIST");
|
||||
}
|
||||
|
||||
static gboolean
|
||||
is_driver_allowed (const gchar *driver)
|
||||
{
|
||||
g_auto(GStrv) whitelisted_drivers = NULL;
|
||||
const char *fp_drivers_whitelist_env;
|
||||
int i;
|
||||
|
||||
g_return_val_if_fail (driver, TRUE);
|
||||
|
||||
fp_drivers_whitelist_env = get_drivers_whitelist_env ();
|
||||
|
||||
if (!fp_drivers_whitelist_env)
|
||||
return TRUE;
|
||||
|
||||
whitelisted_drivers = g_strsplit (fp_drivers_whitelist_env, ":", -1);
|
||||
|
||||
for (i = 0; whitelisted_drivers[i]; ++i)
|
||||
if (g_strcmp0 (driver, whitelisted_drivers[i]) == 0)
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
async_device_init_done_cb (GObject *source_object, GAsyncResult *res, gpointer user_data)
|
||||
{
|
||||
@@ -65,22 +94,21 @@ async_device_init_done_cb (GObject *source_object, GAsyncResult *res, gpointer u
|
||||
FpContext *context;
|
||||
FpContextPrivate *priv;
|
||||
|
||||
device = (FpDevice *) g_async_initable_new_finish (G_ASYNC_INITABLE (source_object), res, &error);
|
||||
if (!device)
|
||||
{
|
||||
device = FP_DEVICE (g_async_initable_new_finish (G_ASYNC_INITABLE (source_object),
|
||||
res, &error));
|
||||
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
||||
return;
|
||||
|
||||
context = FP_CONTEXT (user_data);
|
||||
priv = fp_context_get_instance_private (context);
|
||||
priv->pending_devices--;
|
||||
|
||||
if (error)
|
||||
{
|
||||
g_message ("Ignoring device due to initialization error: %s", error->message);
|
||||
return;
|
||||
}
|
||||
|
||||
context = FP_CONTEXT (user_data);
|
||||
priv = fp_context_get_instance_private (context);
|
||||
priv->pending_devices--;
|
||||
g_ptr_array_add (priv->devices, device);
|
||||
g_signal_emit (context, signals[DEVICE_ADDED_SIGNAL], 0, device);
|
||||
}
|
||||
@@ -102,14 +130,11 @@ usb_device_added_cb (FpContext *self, GUsbDevice *device, GUsbContext *usb_ctx)
|
||||
for (i = 0; i < priv->drivers->len; i++)
|
||||
{
|
||||
GType driver = g_array_index (priv->drivers, GType, i);
|
||||
FpDeviceClass *cls = FP_DEVICE_CLASS (g_type_class_ref (driver));
|
||||
g_autoptr(FpDeviceClass) cls = g_type_class_ref (driver);
|
||||
const FpIdEntry *entry;
|
||||
|
||||
if (cls->type != FP_DEVICE_TYPE_USB)
|
||||
{
|
||||
g_type_class_unref (cls);
|
||||
continue;
|
||||
}
|
||||
|
||||
for (entry = cls->id_table; entry->pid; entry++)
|
||||
{
|
||||
@@ -129,13 +154,11 @@ usb_device_added_cb (FpContext *self, GUsbDevice *device, GUsbContext *usb_ctx)
|
||||
found_driver = driver;
|
||||
found_entry = entry;
|
||||
}
|
||||
|
||||
g_type_class_unref (cls);
|
||||
}
|
||||
|
||||
if (found_driver == G_TYPE_NONE)
|
||||
{
|
||||
g_debug ("No driver found for USB device %04X:%04X", pid, vid);
|
||||
g_debug ("No driver found for USB device %04X:%04X", vid, pid);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -145,8 +168,8 @@ usb_device_added_cb (FpContext *self, GUsbDevice *device, GUsbContext *usb_ctx)
|
||||
priv->cancellable,
|
||||
async_device_init_done_cb,
|
||||
self,
|
||||
"fp-usb-device", device,
|
||||
"fp-driver-data", found_entry->driver_data,
|
||||
"fpi-usb-device", device,
|
||||
"fpi-driver-data", found_entry->driver_data,
|
||||
NULL);
|
||||
}
|
||||
|
||||
@@ -186,6 +209,8 @@ fp_context_finalize (GObject *object)
|
||||
g_cancellable_cancel (priv->cancellable);
|
||||
g_clear_object (&priv->cancellable);
|
||||
g_clear_pointer (&priv->drivers, g_array_unref);
|
||||
|
||||
g_object_run_dispose (G_OBJECT (priv->usb_ctx));
|
||||
g_clear_object (&priv->usb_ctx);
|
||||
|
||||
G_OBJECT_CLASS (fp_context_parent_class)->finalize (object);
|
||||
@@ -240,9 +265,23 @@ fp_context_init (FpContext *self)
|
||||
{
|
||||
g_autoptr(GError) error = NULL;
|
||||
FpContextPrivate *priv = fp_context_get_instance_private (self);
|
||||
guint i;
|
||||
|
||||
priv->drivers = g_array_new (TRUE, FALSE, sizeof (GType));
|
||||
fpi_get_driver_types (priv->drivers);
|
||||
priv->drivers = fpi_get_driver_types ();
|
||||
|
||||
if (get_drivers_whitelist_env ())
|
||||
{
|
||||
for (i = 0; i < priv->drivers->len;)
|
||||
{
|
||||
GType driver = g_array_index (priv->drivers, GType, i);
|
||||
g_autoptr(FpDeviceClass) cls = g_type_class_ref (driver);
|
||||
|
||||
if (!is_driver_allowed (cls->id))
|
||||
g_array_remove_index (priv->drivers, i);
|
||||
else
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
priv->devices = g_ptr_array_new_with_free_func (g_object_unref);
|
||||
|
||||
@@ -309,7 +348,7 @@ fp_context_enumerate (FpContext *context)
|
||||
for (i = 0; i < priv->drivers->len; i++)
|
||||
{
|
||||
GType driver = g_array_index (priv->drivers, GType, i);
|
||||
FpDeviceClass *cls = FP_DEVICE_CLASS (g_type_class_ref (driver));
|
||||
g_autoptr(FpDeviceClass) cls = g_type_class_ref (driver);
|
||||
const FpIdEntry *entry;
|
||||
|
||||
if (cls->type != FP_DEVICE_TYPE_VIRTUAL)
|
||||
@@ -330,13 +369,11 @@ fp_context_enumerate (FpContext *context)
|
||||
priv->cancellable,
|
||||
async_device_init_done_cb,
|
||||
context,
|
||||
"fp-environ", val,
|
||||
"fp-driver-data", entry->driver_data,
|
||||
"fpi-environ", val,
|
||||
"fpi-driver-data", entry->driver_data,
|
||||
NULL);
|
||||
g_debug ("created");
|
||||
}
|
||||
|
||||
g_type_class_unref (cls);
|
||||
}
|
||||
|
||||
while (priv->pending_devices)
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* FpDevice - A fingerprint reader device
|
||||
* Copyright (C) 2019 Benjamin Berg <bberg@redhat.com>
|
||||
* Copyright (C) 2019 Marco Trevisan <marco.trevisan@canonical.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
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "fpi-device.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
FpDeviceType type;
|
||||
|
||||
GUsbDevice *usb_device;
|
||||
const gchar *virtual_env;
|
||||
|
||||
gboolean is_open;
|
||||
|
||||
gchar *device_id;
|
||||
gchar *device_name;
|
||||
FpScanType scan_type;
|
||||
|
||||
guint64 driver_data;
|
||||
|
||||
gint nr_enroll_stages;
|
||||
GSList *sources;
|
||||
|
||||
/* We always make sure that only one task is run at a time. */
|
||||
FpiDeviceAction current_action;
|
||||
GTask *current_task;
|
||||
GAsyncReadyCallback current_user_cb;
|
||||
gulong current_cancellable_id;
|
||||
GSource *current_idle_cancel_source;
|
||||
GSource *current_task_idle_return_source;
|
||||
|
||||
/* State for tasks */
|
||||
gboolean wait_for_finger;
|
||||
} FpDevicePrivate;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
FpPrint *print;
|
||||
|
||||
FpEnrollProgress enroll_progress_cb;
|
||||
gpointer enroll_progress_data;
|
||||
GDestroyNotify enroll_progress_destroy;
|
||||
} FpEnrollData;
|
||||
|
||||
void enroll_data_free (FpEnrollData *enroll_data);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
FpPrint *enrolled_print; /* verify */
|
||||
GPtrArray *gallery; /* identify */
|
||||
|
||||
gboolean result_reported;
|
||||
FpPrint *match;
|
||||
FpPrint *print;
|
||||
GError *error;
|
||||
|
||||
FpMatchCb match_cb;
|
||||
gpointer match_data;
|
||||
GDestroyNotify match_destroy;
|
||||
} FpMatchData;
|
||||
|
||||
void match_data_free (FpMatchData *match_data);
|
||||
+135
-1209
File diff suppressed because it is too large
Load Diff
+51
-3
@@ -79,7 +79,7 @@ typedef enum {
|
||||
|
||||
/**
|
||||
* FpDeviceError:
|
||||
* @FP_DEVICE_ERROR_GENERAL: A general error occured.
|
||||
* @FP_DEVICE_ERROR_GENERAL: A general error occurred.
|
||||
* @FP_DEVICE_ERROR_NOT_SUPPORTED: The device does not support the requested
|
||||
* operation.
|
||||
* @FP_DEVICE_ERROR_NOT_OPEN: The device needs to be opened to start this
|
||||
@@ -113,8 +113,8 @@ GQuark fp_device_error_quark (void);
|
||||
* FpEnrollProgress:
|
||||
* @device: a #FpDevice
|
||||
* @completed_stages: Number of completed stages
|
||||
* @print: (nullable): The last scaned print
|
||||
* @user_data: (nullable): User provided data
|
||||
* @print: (nullable) (transfer none): The last scanned print
|
||||
* @user_data: (nullable) (transfer none): User provided data
|
||||
* @error: (nullable) (transfer none): #GError or %NULL
|
||||
*
|
||||
* The passed error is guaranteed to be of type %FP_DEVICE_RETRY if set.
|
||||
@@ -125,10 +125,48 @@ typedef void (*FpEnrollProgress) (FpDevice *device,
|
||||
gpointer user_data,
|
||||
GError *error);
|
||||
|
||||
/**
|
||||
* FpMatchCb:
|
||||
* @device: a #FpDevice
|
||||
* @match: (nullable) (transfer none): The matching print if any matched @print
|
||||
* @print: (nullable) (transfer none): The newly scanned print
|
||||
* @user_data: (nullable) (transfer none): User provided data
|
||||
* @error: (nullable) (transfer none): #GError or %NULL
|
||||
*
|
||||
* Report the result of a match (identify or verify) operation.
|
||||
*
|
||||
* If @match is non-%NULL, then it is set to the matching #FpPrint as passed
|
||||
* to the match operation. In this case @error will always be %NULL.
|
||||
*
|
||||
* If @error is not %NULL then its domain is guaranteed to be
|
||||
* %FP_DEVICE_RETRY. All other error conditions will not be reported using
|
||||
* this callback. If such an error occurs before a match/no-match decision
|
||||
* can be made, then this callback will not be called. Should an error
|
||||
* happen afterwards, then you will get a match report through this callback
|
||||
* and an error when the operation finishes.
|
||||
*
|
||||
* If @match and @error are %NULL, then a finger was presented but it did not
|
||||
* match any known print.
|
||||
*
|
||||
* @print represents the newly scanned print. The driver may or may not
|
||||
* provide this information. Image based devices will provide it and it
|
||||
* allows access to the raw data.
|
||||
*
|
||||
* This callback exists because it makes sense for drivers to wait e.g. on
|
||||
* finger removal before completing the match operation. However, the
|
||||
* success/failure can often be reported at an earlier time, and there is
|
||||
* no need to make the user wait.
|
||||
*/
|
||||
typedef void (*FpMatchCb) (FpDevice *device,
|
||||
FpPrint *match,
|
||||
FpPrint *print,
|
||||
gpointer user_data,
|
||||
GError *error);
|
||||
|
||||
const gchar *fp_device_get_driver (FpDevice *device);
|
||||
const gchar *fp_device_get_device_id (FpDevice *device);
|
||||
const gchar *fp_device_get_name (FpDevice *device);
|
||||
gboolean fp_device_is_open (FpDevice *device);
|
||||
FpScanType fp_device_get_scan_type (FpDevice *device);
|
||||
gint fp_device_get_nr_enroll_stages (FpDevice *device);
|
||||
|
||||
@@ -159,12 +197,18 @@ void fp_device_enroll (FpDevice *device,
|
||||
void fp_device_verify (FpDevice *device,
|
||||
FpPrint *enrolled_print,
|
||||
GCancellable *cancellable,
|
||||
FpMatchCb match_cb,
|
||||
gpointer match_data,
|
||||
GDestroyNotify match_destroy,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
|
||||
void fp_device_identify (FpDevice *device,
|
||||
GPtrArray *prints,
|
||||
GCancellable *cancellable,
|
||||
FpMatchCb match_cb,
|
||||
gpointer match_data,
|
||||
GDestroyNotify match_destroy,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
|
||||
@@ -230,12 +274,16 @@ FpPrint * fp_device_enroll_sync (FpDevice *device,
|
||||
gboolean fp_device_verify_sync (FpDevice *device,
|
||||
FpPrint *enrolled_print,
|
||||
GCancellable *cancellable,
|
||||
FpMatchCb match_cb,
|
||||
gpointer match_data,
|
||||
gboolean *match,
|
||||
FpPrint **print,
|
||||
GError **error);
|
||||
gboolean fp_device_identify_sync (FpDevice *device,
|
||||
GPtrArray *prints,
|
||||
GCancellable *cancellable,
|
||||
FpMatchCb match_cb,
|
||||
gpointer match_data,
|
||||
FpPrint **match,
|
||||
FpPrint **print,
|
||||
GError **error);
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* FpImageDevice - An image based fingerprint reader device
|
||||
* Copyright (C) 2019 Benjamin Berg <bberg@redhat.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
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "fpi-image-device.h"
|
||||
|
||||
#define IMG_ENROLL_STAGES 5
|
||||
|
||||
typedef struct
|
||||
{
|
||||
FpiImageDeviceState state;
|
||||
gboolean active;
|
||||
gboolean cancelling;
|
||||
|
||||
gboolean enroll_await_on_pending;
|
||||
gint enroll_stage;
|
||||
|
||||
guint pending_activation_timeout_id;
|
||||
gboolean pending_activation_timeout_waiting_finger_off;
|
||||
|
||||
gint bz3_threshold;
|
||||
} FpImageDevicePrivate;
|
||||
|
||||
|
||||
void fpi_image_device_activate (FpImageDevice *image_device);
|
||||
void fpi_image_device_deactivate (FpImageDevice *image_device);
|
||||
+110
-579
@@ -20,13 +20,9 @@
|
||||
#define FP_COMPONENT "image_device"
|
||||
#include "fpi-log.h"
|
||||
|
||||
#include "fpi-image-device.h"
|
||||
#include "fpi-print.h"
|
||||
#include "fpi-image.h"
|
||||
#include "fp-image-device-private.h"
|
||||
|
||||
#define MIN_ACCEPTABLE_MINUTIAE 10
|
||||
#define BOZORTH3_DEFAULT_THRESHOLD 40
|
||||
#define IMG_ENROLL_STAGES 5
|
||||
|
||||
/**
|
||||
* SECTION: fp-image-device
|
||||
@@ -36,30 +32,23 @@
|
||||
* This is a helper class for the commonly found image based devices.
|
||||
*/
|
||||
|
||||
/**
|
||||
* SECTION: fpi-image-device
|
||||
* @title: Internal FpImageDevice
|
||||
* @short_description: Internal image device routines
|
||||
*
|
||||
* See #FpImageDeviceClass for more details. Also see the public
|
||||
* #FpImageDevice routines.
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
FpImageDeviceState state;
|
||||
gboolean active;
|
||||
|
||||
gint enroll_stage;
|
||||
|
||||
guint pending_activation_timeout_id;
|
||||
gboolean pending_activation_timeout_waiting_finger_off;
|
||||
|
||||
gint bz3_threshold;
|
||||
} FpImageDevicePrivate;
|
||||
|
||||
G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (FpImageDevice, fp_image_device, FP_TYPE_DEVICE)
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_FPI_STATE,
|
||||
N_PROPS
|
||||
};
|
||||
|
||||
static GParamSpec *properties[N_PROPS];
|
||||
|
||||
enum {
|
||||
FPI_STATE_CHANGED,
|
||||
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
static guint signals[LAST_SIGNAL] = { 0 };
|
||||
|
||||
/*******************************************************/
|
||||
|
||||
@@ -69,77 +58,6 @@ G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (FpImageDevice, fp_image_device, FP_TYPE_DEV
|
||||
|
||||
/* Static helper functions */
|
||||
|
||||
static void
|
||||
fp_image_device_change_state (FpImageDevice *self, FpImageDeviceState state)
|
||||
{
|
||||
FpImageDevicePrivate *priv = fp_image_device_get_instance_private (self);
|
||||
FpImageDeviceClass *cls = FP_IMAGE_DEVICE_GET_CLASS (self);
|
||||
|
||||
/* Cannot change to inactive using this function. */
|
||||
g_assert (state != FP_IMAGE_DEVICE_STATE_INACTIVE);
|
||||
|
||||
/* We might have been waiting for the finger to go OFF to start the
|
||||
* next operation. */
|
||||
if (priv->pending_activation_timeout_id)
|
||||
{
|
||||
g_source_remove (priv->pending_activation_timeout_id);
|
||||
priv->pending_activation_timeout_id = 0;
|
||||
}
|
||||
|
||||
fp_dbg ("Image device internal state change from %d to %d\n", priv->state, state);
|
||||
|
||||
priv->state = state;
|
||||
|
||||
/* change_state is the only callback which is optional and does not
|
||||
* have a default implementation. */
|
||||
if (cls->change_state)
|
||||
cls->change_state (self, state);
|
||||
}
|
||||
|
||||
static void
|
||||
fp_image_device_activate (FpImageDevice *self)
|
||||
{
|
||||
FpImageDevicePrivate *priv = fp_image_device_get_instance_private (self);
|
||||
FpImageDeviceClass *cls = FP_IMAGE_DEVICE_GET_CLASS (self);
|
||||
|
||||
g_assert (!priv->active);
|
||||
|
||||
/* We don't have a neutral ACTIVE state, but we always will
|
||||
* go into WAIT_FINGER_ON afterwards. */
|
||||
priv->state = FP_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON;
|
||||
|
||||
/* We might have been waiting for deactivation to finish before
|
||||
* starting the next operation. */
|
||||
if (priv->pending_activation_timeout_id)
|
||||
{
|
||||
g_source_remove (priv->pending_activation_timeout_id);
|
||||
priv->pending_activation_timeout_id = 0;
|
||||
}
|
||||
|
||||
fp_dbg ("Activating image device\n");
|
||||
cls->activate (self);
|
||||
}
|
||||
|
||||
static void
|
||||
fp_image_device_deactivate (FpDevice *device)
|
||||
{
|
||||
FpImageDevice *self = FP_IMAGE_DEVICE (device);
|
||||
FpImageDevicePrivate *priv = fp_image_device_get_instance_private (self);
|
||||
FpImageDeviceClass *cls = FP_IMAGE_DEVICE_GET_CLASS (device);
|
||||
|
||||
if (!priv->active)
|
||||
{
|
||||
/* XXX: We currently deactivate both from minutiae scan result
|
||||
* and finger off report. */
|
||||
fp_dbg ("Already deactivated, ignoring request.");
|
||||
return;
|
||||
}
|
||||
priv->state = FP_IMAGE_DEVICE_STATE_INACTIVE;
|
||||
|
||||
fp_dbg ("Deactivating image device\n");
|
||||
cls->deactivate (self);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
pending_activation_timeout (gpointer user_data)
|
||||
{
|
||||
@@ -182,32 +100,35 @@ fp_image_device_close (FpDevice *device)
|
||||
* 1. We are inactive
|
||||
* -> immediately close
|
||||
* 2. We are waiting for finger off
|
||||
* -> imediately deactivate
|
||||
* -> immediately deactivate
|
||||
* 3. We are deactivating
|
||||
* -> handled by deactivate_complete */
|
||||
|
||||
if (!priv->active)
|
||||
cls->img_close (self);
|
||||
else if (priv->state != FP_IMAGE_DEVICE_STATE_INACTIVE)
|
||||
fp_image_device_deactivate (device);
|
||||
else if (priv->state != FPI_IMAGE_DEVICE_STATE_INACTIVE)
|
||||
fpi_image_device_deactivate (self);
|
||||
}
|
||||
|
||||
static void
|
||||
fp_image_device_cancel_action (FpDevice *device)
|
||||
{
|
||||
FpImageDevice *self = FP_IMAGE_DEVICE (device);
|
||||
FpDeviceAction action;
|
||||
FpImageDevicePrivate *priv = fp_image_device_get_instance_private (self);
|
||||
FpiDeviceAction action;
|
||||
|
||||
action = fpi_device_get_current_action (device);
|
||||
|
||||
/* We can only cancel capture operations, in that case, deactivate and return
|
||||
* an error immediately. */
|
||||
if (action == FP_DEVICE_ACTION_ENROLL ||
|
||||
action == FP_DEVICE_ACTION_VERIFY ||
|
||||
action == FP_DEVICE_ACTION_IDENTIFY ||
|
||||
action == FP_DEVICE_ACTION_CAPTURE)
|
||||
if (action == FPI_DEVICE_ACTION_ENROLL ||
|
||||
action == FPI_DEVICE_ACTION_VERIFY ||
|
||||
action == FPI_DEVICE_ACTION_IDENTIFY ||
|
||||
action == FPI_DEVICE_ACTION_CAPTURE)
|
||||
{
|
||||
fp_image_device_deactivate (FP_DEVICE (self));
|
||||
priv->cancelling = TRUE;
|
||||
fpi_image_device_deactivate (self);
|
||||
priv->cancelling = FALSE;
|
||||
|
||||
/* XXX: Some nicer way of doing this would be good. */
|
||||
fpi_device_action_error (FP_DEVICE (self),
|
||||
@@ -222,14 +143,14 @@ fp_image_device_start_capture_action (FpDevice *device)
|
||||
{
|
||||
FpImageDevice *self = FP_IMAGE_DEVICE (device);
|
||||
FpImageDevicePrivate *priv = fp_image_device_get_instance_private (self);
|
||||
FpDeviceAction action;
|
||||
FpiDeviceAction action;
|
||||
|
||||
/* There is just one action that we cannot support out
|
||||
* of the box, which is a capture without first waiting
|
||||
* for a finger to be on the device.
|
||||
*/
|
||||
action = fpi_device_get_current_action (device);
|
||||
if (action == FP_DEVICE_ACTION_CAPTURE)
|
||||
if (action == FPI_DEVICE_ACTION_CAPTURE)
|
||||
{
|
||||
gboolean wait_for_finger;
|
||||
|
||||
@@ -241,29 +162,30 @@ fp_image_device_start_capture_action (FpDevice *device)
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (action == FP_DEVICE_ACTION_ENROLL)
|
||||
else if (action == FPI_DEVICE_ACTION_ENROLL)
|
||||
{
|
||||
FpPrint *enroll_print = NULL;
|
||||
|
||||
fpi_device_get_enroll_data (device, &enroll_print);
|
||||
fpi_print_set_type (enroll_print, FP_PRINT_NBIS);
|
||||
fpi_print_set_type (enroll_print, FPI_PRINT_NBIS);
|
||||
}
|
||||
|
||||
priv->enroll_stage = 0;
|
||||
priv->enroll_await_on_pending = FALSE;
|
||||
|
||||
/* The device might still be deactivating from a previous call.
|
||||
* In that situation, try to wait for a bit before reporting back an
|
||||
* error (which will usually say that the user should remove the
|
||||
* finger).
|
||||
*/
|
||||
if (priv->state != FP_IMAGE_DEVICE_STATE_INACTIVE || priv->active)
|
||||
if (priv->state != FPI_IMAGE_DEVICE_STATE_INACTIVE || priv->active)
|
||||
{
|
||||
g_debug ("Got a new request while the device was still active");
|
||||
g_assert (priv->pending_activation_timeout_id == 0);
|
||||
priv->pending_activation_timeout_id =
|
||||
g_timeout_add (100, pending_activation_timeout, device);
|
||||
|
||||
if (priv->state == FP_IMAGE_DEVICE_STATE_AWAIT_FINGER_OFF)
|
||||
if (priv->state == FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_OFF)
|
||||
priv->pending_activation_timeout_waiting_finger_off = TRUE;
|
||||
else
|
||||
priv->pending_activation_timeout_waiting_finger_off = FALSE;
|
||||
@@ -273,7 +195,7 @@ fp_image_device_start_capture_action (FpDevice *device)
|
||||
|
||||
/* And activate the device; we rely on fpi_image_device_activate_complete()
|
||||
* to be called when done (or immediately). */
|
||||
fp_image_device_activate (self);
|
||||
fpi_image_device_activate (self);
|
||||
}
|
||||
|
||||
|
||||
@@ -286,6 +208,7 @@ fp_image_device_finalize (GObject *object)
|
||||
FpImageDevicePrivate *priv = fp_image_device_get_instance_private (self);
|
||||
|
||||
g_assert (priv->active == FALSE);
|
||||
g_clear_handle_id (&priv->pending_activation_timeout_id, g_source_remove);
|
||||
|
||||
G_OBJECT_CLASS (fp_image_device_parent_class)->finalize (object);
|
||||
}
|
||||
@@ -302,6 +225,43 @@ fp_image_device_default_deactivate (FpImageDevice *self)
|
||||
fpi_image_device_deactivate_complete (self, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
fp_image_device_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
FpImageDevice *self = FP_IMAGE_DEVICE (object);
|
||||
FpImageDevicePrivate *priv = fp_image_device_get_instance_private (self);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_FPI_STATE:
|
||||
g_value_set_enum (value, priv->state);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
fp_image_device_constructed (GObject *obj)
|
||||
{
|
||||
FpImageDevice *self = FP_IMAGE_DEVICE (obj);
|
||||
FpImageDevicePrivate *priv = fp_image_device_get_instance_private (self);
|
||||
FpImageDeviceClass *cls = FP_IMAGE_DEVICE_GET_CLASS (self);
|
||||
|
||||
/* Set default values. */
|
||||
fpi_device_set_nr_enroll_stages (FP_DEVICE (self), IMG_ENROLL_STAGES);
|
||||
|
||||
priv->bz3_threshold = BOZORTH3_DEFAULT_THRESHOLD;
|
||||
if (cls->bz3_threshold > 0)
|
||||
priv->bz3_threshold = cls->bz3_threshold;
|
||||
|
||||
G_OBJECT_CLASS (fp_image_device_parent_class)->constructed (obj);
|
||||
}
|
||||
|
||||
static void
|
||||
fp_image_device_class_init (FpImageDeviceClass *klass)
|
||||
{
|
||||
@@ -309,6 +269,8 @@ fp_image_device_class_init (FpImageDeviceClass *klass)
|
||||
FpDeviceClass *fp_device_class = FP_DEVICE_CLASS (klass);
|
||||
|
||||
object_class->finalize = fp_image_device_finalize;
|
||||
object_class->get_property = fp_image_device_get_property;
|
||||
object_class->constructed = fp_image_device_constructed;
|
||||
|
||||
fp_device_class->open = fp_image_device_open;
|
||||
fp_device_class->close = fp_image_device_close;
|
||||
@@ -322,474 +284,43 @@ fp_image_device_class_init (FpImageDeviceClass *klass)
|
||||
/* Default implementations */
|
||||
klass->activate = fp_image_device_default_activate;
|
||||
klass->deactivate = fp_image_device_default_deactivate;
|
||||
|
||||
/**
|
||||
* FpImageDevice::fpi-image-device-state: (skip)
|
||||
*
|
||||
* This property is only for internal purposes.
|
||||
*
|
||||
* Stability: private
|
||||
*/
|
||||
properties[PROP_FPI_STATE] =
|
||||
g_param_spec_enum ("fpi-image-device-state",
|
||||
"Image Device State",
|
||||
"Private: The state of the image device",
|
||||
FPI_TYPE_IMAGE_DEVICE_STATE,
|
||||
FPI_IMAGE_DEVICE_STATE_INACTIVE,
|
||||
G_PARAM_STATIC_STRINGS | G_PARAM_READABLE);
|
||||
|
||||
/**
|
||||
* FpImageDevice::fpi-image-device-state-changed: (skip)
|
||||
* @image_device: A #FpImageDevice
|
||||
* @new_state: The new state of the device
|
||||
*
|
||||
* This signal is only for internal purposes.
|
||||
*
|
||||
* Stability: private
|
||||
*/
|
||||
signals[FPI_STATE_CHANGED] =
|
||||
g_signal_new ("fpi-image-device-state-changed",
|
||||
G_TYPE_FROM_CLASS (object_class),
|
||||
G_SIGNAL_RUN_FIRST,
|
||||
G_STRUCT_OFFSET (FpImageDeviceClass, change_state),
|
||||
NULL, NULL, NULL,
|
||||
G_TYPE_NONE, 1, FPI_TYPE_IMAGE_DEVICE_STATE);
|
||||
|
||||
g_object_class_install_properties (object_class, N_PROPS, properties);
|
||||
}
|
||||
|
||||
static void
|
||||
fp_image_device_init (FpImageDevice *self)
|
||||
{
|
||||
FpImageDevicePrivate *priv = fp_image_device_get_instance_private (self);
|
||||
FpImageDeviceClass *cls = FP_IMAGE_DEVICE_GET_CLASS (self);
|
||||
|
||||
/* Set default values. */
|
||||
fpi_device_set_nr_enroll_stages (FP_DEVICE (self), IMG_ENROLL_STAGES);
|
||||
|
||||
priv->bz3_threshold = BOZORTH3_DEFAULT_THRESHOLD;
|
||||
if (cls->bz3_threshold > 0)
|
||||
priv->bz3_threshold = cls->bz3_threshold;
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
fpi_image_device_minutiae_detected (GObject *source_object, GAsyncResult *res, gpointer user_data)
|
||||
{
|
||||
g_autoptr(FpImage) image = FP_IMAGE (source_object);
|
||||
GError *error = NULL;
|
||||
FpPrint *print = NULL;
|
||||
FpDevice *device = FP_DEVICE (user_data);
|
||||
FpImageDevicePrivate *priv;
|
||||
FpDeviceAction action;
|
||||
|
||||
/* Note: We rely on the device to not disappear during an operation. */
|
||||
|
||||
if (!fp_image_detect_minutiae_finish (image, res, &error))
|
||||
{
|
||||
/* Cancel operation . */
|
||||
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
||||
{
|
||||
fpi_device_action_error (device, g_steal_pointer (&error));
|
||||
fp_image_device_deactivate (device);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Replace error with a retry condition. */
|
||||
g_warning ("Failed to detect minutiae: %s", error->message);
|
||||
g_clear_pointer (&error, g_error_free);
|
||||
|
||||
error = fpi_device_retry_new_msg (FP_DEVICE_RETRY_GENERAL, "Minutiae detection failed, please retry");
|
||||
}
|
||||
|
||||
priv = fp_image_device_get_instance_private (FP_IMAGE_DEVICE (device));
|
||||
action = fpi_device_get_current_action (device);
|
||||
|
||||
if (action == FP_DEVICE_ACTION_CAPTURE)
|
||||
{
|
||||
fpi_device_capture_complete (device, g_steal_pointer (&image), error);
|
||||
fp_image_device_deactivate (device);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!error)
|
||||
{
|
||||
print = fp_print_new (device);
|
||||
fpi_print_set_type (print, FP_PRINT_NBIS);
|
||||
if (!fpi_print_add_from_image (print, image, &error))
|
||||
g_clear_object (&print);
|
||||
}
|
||||
|
||||
if (action == FP_DEVICE_ACTION_ENROLL)
|
||||
{
|
||||
FpPrint *enroll_print;
|
||||
fpi_device_get_enroll_data (device, &enroll_print);
|
||||
|
||||
if (print)
|
||||
{
|
||||
fpi_print_add_print (enroll_print, print);
|
||||
priv->enroll_stage += 1;
|
||||
}
|
||||
|
||||
fpi_device_enroll_progress (device, priv->enroll_stage, print, error);
|
||||
|
||||
if (priv->enroll_stage == IMG_ENROLL_STAGES)
|
||||
{
|
||||
fpi_device_enroll_complete (device, g_object_ref (enroll_print), NULL);
|
||||
fp_image_device_deactivate (device);
|
||||
}
|
||||
}
|
||||
else if (action == FP_DEVICE_ACTION_VERIFY)
|
||||
{
|
||||
FpPrint *template;
|
||||
FpiMatchResult result;
|
||||
|
||||
fpi_device_get_verify_data (device, &template);
|
||||
if (print)
|
||||
result = fpi_print_bz3_match (template, print, priv->bz3_threshold, &error);
|
||||
else
|
||||
result = FPI_MATCH_ERROR;
|
||||
|
||||
fpi_device_verify_complete (device, result, print, error);
|
||||
fp_image_device_deactivate (device);
|
||||
}
|
||||
else if (action == FP_DEVICE_ACTION_IDENTIFY)
|
||||
{
|
||||
gint i;
|
||||
GPtrArray *templates;
|
||||
FpPrint *result = NULL;
|
||||
|
||||
fpi_device_get_identify_data (device, &templates);
|
||||
for (i = 0; !error && i < templates->len; i++)
|
||||
{
|
||||
FpPrint *template = g_ptr_array_index (templates, i);
|
||||
|
||||
if (fpi_print_bz3_match (template, print, priv->bz3_threshold, &error) == FPI_MATCH_SUCCESS)
|
||||
{
|
||||
result = g_object_ref (template);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
fpi_device_identify_complete (device, result, print, error);
|
||||
fp_image_device_deactivate (device);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* XXX: This can be hit currently due to a race condition in the enroll code!
|
||||
* In that case we scan a further image even though the minutiae for the previous
|
||||
* one have not yet been detected.
|
||||
* We need to keep track on the pending minutiae detection and the fact that
|
||||
* it will finish eventually (or we may need to retry on error and activate the
|
||||
* device again). */
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************/
|
||||
/* Private API */
|
||||
|
||||
/**
|
||||
* fpi_image_device_set_bz3_threshold:
|
||||
* @self: a #FpImageDevice imaging fingerprint device
|
||||
* @bz3_threshold: BZ3 threshold to use
|
||||
*
|
||||
* Dynamically adjust the bz3 threshold. This is only needed for drivers
|
||||
* that support devices with different properties. It should generally be
|
||||
* called from the probe callback, but is acceptable to call from the open
|
||||
* callback.
|
||||
*/
|
||||
void
|
||||
fpi_image_device_set_bz3_threshold (FpImageDevice *self,
|
||||
gint bz3_threshold)
|
||||
{
|
||||
FpImageDevicePrivate *priv = fp_image_device_get_instance_private (self);
|
||||
|
||||
g_return_if_fail (FP_IS_IMAGE_DEVICE (self));
|
||||
g_return_if_fail (bz3_threshold > 0);
|
||||
|
||||
priv->bz3_threshold = bz3_threshold;
|
||||
}
|
||||
|
||||
/**
|
||||
* fpi_image_device_report_finger_status:
|
||||
* @self: a #FpImageDevice imaging fingerprint device
|
||||
* @present: whether the finger is present on the sensor
|
||||
*
|
||||
* Reports from the driver whether the user's finger is on
|
||||
* the sensor.
|
||||
*/
|
||||
void
|
||||
fpi_image_device_report_finger_status (FpImageDevice *self,
|
||||
gboolean present)
|
||||
{
|
||||
FpDevice *device = FP_DEVICE (self);
|
||||
FpImageDevicePrivate *priv = fp_image_device_get_instance_private (self);
|
||||
FpDeviceAction action;
|
||||
|
||||
action = fpi_device_get_current_action (device);
|
||||
|
||||
if (priv->state == FP_IMAGE_DEVICE_STATE_INACTIVE)
|
||||
{
|
||||
/* Do we really want to always ignore such reports? We could
|
||||
* also track the state in case the user had the finger on
|
||||
* the device at initialisation time and the driver reports
|
||||
* this early.
|
||||
*/
|
||||
g_debug ("Ignoring finger presence report as the device is not active!");
|
||||
return;
|
||||
}
|
||||
|
||||
action = fpi_device_get_current_action (device);
|
||||
|
||||
g_assert (action != FP_DEVICE_ACTION_OPEN);
|
||||
g_assert (action != FP_DEVICE_ACTION_CLOSE);
|
||||
|
||||
g_debug ("Image device reported finger status: %s", present ? "on" : "off");
|
||||
|
||||
if (present && priv->state == FP_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON)
|
||||
{
|
||||
fp_image_device_change_state (self, FP_IMAGE_DEVICE_STATE_CAPTURE);
|
||||
}
|
||||
else if (!present && priv->state == FP_IMAGE_DEVICE_STATE_AWAIT_FINGER_OFF)
|
||||
{
|
||||
/* We need to deactivate or continue to await finger */
|
||||
|
||||
/* There are three possible situations:
|
||||
* 1. We are deactivating the device and the action is still in progress
|
||||
* (minutiae detection).
|
||||
* 2. We are still deactivating the device after an action completed
|
||||
* 3. We were waiting for finger removal to start the new action
|
||||
* Either way, we always end up deactivating except for the enroll case.
|
||||
* XXX: This is not quite correct though, as we assume we need another finger
|
||||
* scan even though we might be processing the last one (successfully).
|
||||
*/
|
||||
if (action != FP_DEVICE_ACTION_ENROLL)
|
||||
fp_image_device_deactivate (device);
|
||||
else
|
||||
fp_image_device_change_state (self, FP_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* fpi_image_device_image_captured:
|
||||
* @self: a #FpImageDevice imaging fingerprint device
|
||||
* @image: whether the finger is present on the sensor
|
||||
*
|
||||
* Reports an image capture. Only use this function if the image was
|
||||
* captured successfully. If there was an issue where the user should
|
||||
* retry, use fpi_image_device_retry_scan() to report the retry condition.
|
||||
*
|
||||
* In the event of a fatal error for the operation use
|
||||
* fpi_image_device_session_error(). This will abort the entire operation
|
||||
* including e.g. an enroll operation which captures multiple images during
|
||||
* one session.
|
||||
*/
|
||||
void
|
||||
fpi_image_device_image_captured (FpImageDevice *self, FpImage *image)
|
||||
{
|
||||
FpImageDevicePrivate *priv = fp_image_device_get_instance_private (self);
|
||||
FpDeviceAction action;
|
||||
|
||||
action = fpi_device_get_current_action (FP_DEVICE (self));
|
||||
|
||||
g_return_if_fail (image != NULL);
|
||||
g_return_if_fail (priv->state == FP_IMAGE_DEVICE_STATE_CAPTURE);
|
||||
g_return_if_fail (action == FP_DEVICE_ACTION_ENROLL ||
|
||||
action == FP_DEVICE_ACTION_VERIFY ||
|
||||
action == FP_DEVICE_ACTION_IDENTIFY ||
|
||||
action == FP_DEVICE_ACTION_CAPTURE);
|
||||
|
||||
fp_image_device_change_state (self, FP_IMAGE_DEVICE_STATE_AWAIT_FINGER_OFF);
|
||||
|
||||
g_debug ("Image device captured an image");
|
||||
|
||||
/* XXX: We also detect minutiae in capture mode, we solely do this
|
||||
* to normalize the image which will happen as a by-product. */
|
||||
fp_image_detect_minutiae (image,
|
||||
fpi_device_get_cancellable (FP_DEVICE (self)),
|
||||
fpi_image_device_minutiae_detected,
|
||||
self);
|
||||
}
|
||||
|
||||
/**
|
||||
* fpi_image_device_retry_scan:
|
||||
* @self: a #FpImageDevice imaging fingerprint device
|
||||
* @retry: The #FpDeviceRetry error code to report
|
||||
*
|
||||
* Reports a scan failure to the user. This may or may not abort the
|
||||
* current session. It is the equivalent of fpi_image_device_image_captured()
|
||||
* in the case of a retryable error condition (e.g. short swipe).
|
||||
*/
|
||||
void
|
||||
fpi_image_device_retry_scan (FpImageDevice *self, FpDeviceRetry retry)
|
||||
{
|
||||
FpImageDevicePrivate *priv = fp_image_device_get_instance_private (self);
|
||||
FpDeviceAction action;
|
||||
GError *error;
|
||||
|
||||
action = fpi_device_get_current_action (FP_DEVICE (self));
|
||||
|
||||
/* We might be waiting for a finger at this point, so just accept
|
||||
* all but INACTIVE */
|
||||
g_return_if_fail (priv->state != FP_IMAGE_DEVICE_STATE_INACTIVE);
|
||||
g_return_if_fail (action == FP_DEVICE_ACTION_ENROLL ||
|
||||
action == FP_DEVICE_ACTION_VERIFY ||
|
||||
action == FP_DEVICE_ACTION_IDENTIFY ||
|
||||
action == FP_DEVICE_ACTION_CAPTURE);
|
||||
|
||||
error = fpi_device_retry_new (retry);
|
||||
|
||||
if (action == FP_DEVICE_ACTION_ENROLL)
|
||||
{
|
||||
g_debug ("Reporting retry during enroll");
|
||||
fpi_device_enroll_progress (FP_DEVICE (self), priv->enroll_stage, NULL, error);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We abort the operation and let the surrounding code retry in the
|
||||
* non-enroll case (this is identical to a session error). */
|
||||
g_debug ("Abort current operation due to retry (non-enroll case)");
|
||||
fp_image_device_deactivate (FP_DEVICE (self));
|
||||
fpi_device_action_error (FP_DEVICE (self), error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* fpi_image_device_session_error:
|
||||
* @self: a #FpImageDevice imaging fingerprint device
|
||||
* @error: The #GError to report
|
||||
*
|
||||
* Report an error while interacting with the device. This effectively
|
||||
* aborts the current ongoing action.
|
||||
*/
|
||||
void
|
||||
fpi_image_device_session_error (FpImageDevice *self, GError *error)
|
||||
{
|
||||
FpImageDevicePrivate *priv = fp_image_device_get_instance_private (self);
|
||||
|
||||
g_return_if_fail (self);
|
||||
|
||||
if (!error)
|
||||
{
|
||||
g_warning ("Driver did not provide an error, generating a generic one");
|
||||
error = g_error_new (FP_DEVICE_ERROR, FP_DEVICE_ERROR_GENERAL, "Driver reported session error without an error");
|
||||
}
|
||||
|
||||
if (!priv->active)
|
||||
{
|
||||
FpDeviceAction action = fpi_device_get_current_action (FP_DEVICE (self));
|
||||
g_warning ("Driver reported session error, but device is inactive.");
|
||||
|
||||
if (action != FP_DEVICE_ACTION_NONE)
|
||||
{
|
||||
g_warning ("Translating to activation failure!");
|
||||
fpi_image_device_activate_complete (self, error);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (priv->state == FP_IMAGE_DEVICE_STATE_INACTIVE)
|
||||
{
|
||||
g_warning ("Driver reported session error; translating to deactivation failure.");
|
||||
fpi_image_device_deactivate_complete (self, error);
|
||||
return;
|
||||
}
|
||||
|
||||
if (error->domain == FP_DEVICE_RETRY)
|
||||
g_warning ("Driver should report retries using fpi_image_device_retry_scan!");
|
||||
|
||||
fp_image_device_deactivate (FP_DEVICE (self));
|
||||
fpi_device_action_error (FP_DEVICE (self), error);
|
||||
}
|
||||
|
||||
/**
|
||||
* fpi_image_device_activate_complete:
|
||||
* @self: a #FpImageDevice imaging fingerprint device
|
||||
* @error: A #GError or %NULL on success
|
||||
*
|
||||
* Reports completion of device activation.
|
||||
*/
|
||||
void
|
||||
fpi_image_device_activate_complete (FpImageDevice *self, GError *error)
|
||||
{
|
||||
FpImageDevicePrivate *priv = fp_image_device_get_instance_private (self);
|
||||
FpDeviceAction action;
|
||||
|
||||
action = fpi_device_get_current_action (FP_DEVICE (self));
|
||||
|
||||
g_return_if_fail (priv->active == FALSE);
|
||||
g_return_if_fail (action == FP_DEVICE_ACTION_ENROLL ||
|
||||
action == FP_DEVICE_ACTION_VERIFY ||
|
||||
action == FP_DEVICE_ACTION_IDENTIFY ||
|
||||
action == FP_DEVICE_ACTION_CAPTURE);
|
||||
|
||||
if (error)
|
||||
{
|
||||
g_debug ("Image device activation failed");
|
||||
fpi_device_action_error (FP_DEVICE (self), error);
|
||||
return;
|
||||
}
|
||||
|
||||
g_debug ("Image device activation completed");
|
||||
|
||||
priv->active = TRUE;
|
||||
|
||||
/* We always want to capture at this point, move to AWAIT_FINGER
|
||||
* state. */
|
||||
fp_image_device_change_state (self, FP_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON);
|
||||
}
|
||||
|
||||
/**
|
||||
* fpi_image_device_deactivate_complete:
|
||||
* @self: a #FpImageDevice imaging fingerprint device
|
||||
* @error: A #GError or %NULL on success
|
||||
*
|
||||
* Reports completion of device deactivation.
|
||||
*/
|
||||
void
|
||||
fpi_image_device_deactivate_complete (FpImageDevice *self, GError *error)
|
||||
{
|
||||
FpImageDevicePrivate *priv = fp_image_device_get_instance_private (self);
|
||||
FpImageDeviceClass *cls = FP_IMAGE_DEVICE_GET_CLASS (self);
|
||||
FpDeviceAction action;
|
||||
|
||||
g_return_if_fail (priv->active == TRUE);
|
||||
g_return_if_fail (priv->state == FP_IMAGE_DEVICE_STATE_INACTIVE);
|
||||
|
||||
g_debug ("Image device deactivation completed");
|
||||
|
||||
priv->active = FALSE;
|
||||
|
||||
/* Deactivation completed. As we deactivate in the background
|
||||
* there may already be a new task pending. Check whether we
|
||||
* need to do anything. */
|
||||
action = fpi_device_get_current_action (FP_DEVICE (self));
|
||||
|
||||
/* Special case, if we should be closing, but didn't due to a running
|
||||
* deactivation, then do so now. */
|
||||
if (action == FP_DEVICE_ACTION_CLOSE)
|
||||
{
|
||||
cls->img_close (self);
|
||||
return;
|
||||
}
|
||||
|
||||
/* We might be waiting to be able to activate again. */
|
||||
if (priv->pending_activation_timeout_id)
|
||||
fp_image_device_activate (self);
|
||||
}
|
||||
|
||||
/**
|
||||
* fpi_image_device_open_complete:
|
||||
* @self: a #FpImageDevice imaging fingerprint device
|
||||
* @error: A #GError or %NULL on success
|
||||
*
|
||||
* Reports completion of open operation.
|
||||
*/
|
||||
void
|
||||
fpi_image_device_open_complete (FpImageDevice *self, GError *error)
|
||||
{
|
||||
FpImageDevicePrivate *priv = fp_image_device_get_instance_private (self);
|
||||
FpDeviceAction action;
|
||||
|
||||
action = fpi_device_get_current_action (FP_DEVICE (self));
|
||||
|
||||
g_return_if_fail (priv->active == FALSE);
|
||||
g_return_if_fail (action == FP_DEVICE_ACTION_OPEN);
|
||||
|
||||
g_debug ("Image device open completed");
|
||||
|
||||
priv->state = FP_IMAGE_DEVICE_STATE_INACTIVE;
|
||||
|
||||
fpi_device_open_complete (FP_DEVICE (self), error);
|
||||
}
|
||||
|
||||
/**
|
||||
* fpi_image_device_close_complete:
|
||||
* @self: a #FpImageDevice imaging fingerprint device
|
||||
* @error: A #GError or %NULL on success
|
||||
*
|
||||
* Reports completion of close operation.
|
||||
*/
|
||||
void
|
||||
fpi_image_device_close_complete (FpImageDevice *self, GError *error)
|
||||
{
|
||||
FpImageDevicePrivate *priv = fp_image_device_get_instance_private (self);
|
||||
FpDeviceAction action;
|
||||
|
||||
action = fpi_device_get_current_action (FP_DEVICE (self));
|
||||
|
||||
g_debug ("Image device close completed");
|
||||
|
||||
g_return_if_fail (priv->active == FALSE);
|
||||
g_return_if_fail (action == FP_DEVICE_ACTION_CLOSE);
|
||||
|
||||
priv->state = FP_IMAGE_DEVICE_STATE_INACTIVE;
|
||||
|
||||
fpi_device_close_complete (FP_DEVICE (self), error);
|
||||
}
|
||||
|
||||
+18
-131
@@ -18,13 +18,12 @@
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#define FP_COMPONENT "image"
|
||||
|
||||
#include "fpi-image.h"
|
||||
#include "fpi-log.h"
|
||||
|
||||
#include "nbis/include/lfs.h"
|
||||
|
||||
#if HAVE_PIXMAN
|
||||
#include <pixman.h>
|
||||
#endif
|
||||
#include <nbis.h>
|
||||
|
||||
/**
|
||||
* SECTION: fp-image
|
||||
@@ -35,15 +34,6 @@
|
||||
* this object allows accessing this data.
|
||||
*/
|
||||
|
||||
/**
|
||||
* SECTION: fpi-image
|
||||
* @title: Internal FpImage
|
||||
* @short_description: Internal image handling routines
|
||||
*
|
||||
* Internal image handling routines. Also see the public <ulink
|
||||
* url="libfprint-FpImage.html">FpImage routines</ulink>.
|
||||
*/
|
||||
|
||||
G_DEFINE_TYPE (FpImage, fp_image, G_TYPE_OBJECT)
|
||||
|
||||
enum {
|
||||
@@ -194,10 +184,8 @@ fp_image_detect_minutiae_cb (GObject *source_object,
|
||||
GTask *task = G_TASK (res);
|
||||
FpImage *image;
|
||||
DetectMinutiaeData *data = g_task_get_task_data (task);
|
||||
GCancellable *cancellable;
|
||||
|
||||
cancellable = g_task_get_cancellable (task);
|
||||
if (!cancellable || !g_cancellable_is_cancelled (cancellable))
|
||||
if (!g_task_had_error (task))
|
||||
{
|
||||
gint i;
|
||||
image = FP_IMAGE (source_object);
|
||||
@@ -293,6 +281,7 @@ fp_image_detect_minutiae_thread_func (GTask *task,
|
||||
gint map_w, map_h;
|
||||
gint bw, bh, bd;
|
||||
gint r;
|
||||
g_autofree LFSPARMS *lfsparms;
|
||||
|
||||
/* Normalize the image first */
|
||||
if (data->flags & FPI_IMAGE_H_FLIPPED)
|
||||
@@ -306,12 +295,15 @@ fp_image_detect_minutiae_thread_func (GTask *task,
|
||||
|
||||
data->flags &= ~(FPI_IMAGE_H_FLIPPED | FPI_IMAGE_V_FLIPPED | FPI_IMAGE_COLORS_INVERTED);
|
||||
|
||||
lfsparms = g_memdup (&g_lfsparms_V2, sizeof (LFSPARMS));
|
||||
lfsparms->remove_perimeter_pts = data->flags & FPI_IMAGE_PARTIAL ? TRUE : FALSE;
|
||||
|
||||
timer = g_timer_new ();
|
||||
r = get_minutiae (&minutiae, &quality_map, &direction_map,
|
||||
&low_contrast_map, &low_flow_map, &high_curve_map,
|
||||
&map_w, &map_h, &bdata, &bw, &bh, &bd,
|
||||
data->image, data->width, data->height, 8,
|
||||
data->ppmm, &g_lfsparms_V2);
|
||||
data->ppmm, lfsparms);
|
||||
g_timer_stop (timer);
|
||||
fp_dbg ("Minutiae scan completed in %f secs", g_timer_elapsed (timer, NULL));
|
||||
|
||||
@@ -326,6 +318,14 @@ fp_image_detect_minutiae_thread_func (GTask *task,
|
||||
return;
|
||||
}
|
||||
|
||||
if (!data->minutiae || data->minutiae->num == 0)
|
||||
{
|
||||
g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"No minutiae found");
|
||||
g_object_unref (task);
|
||||
return;
|
||||
}
|
||||
|
||||
g_task_return_boolean (task, TRUE);
|
||||
g_object_unref (task);
|
||||
}
|
||||
@@ -478,78 +478,6 @@ fp_image_detect_minutiae_finish (FpImage *self,
|
||||
return g_task_propagate_boolean (G_TASK (result), error);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* fpi_std_sq_dev:
|
||||
* @buf: buffer (usually bitmap, one byte per pixel)
|
||||
* @size: size of @buffer
|
||||
*
|
||||
* Calculates the squared standard deviation of the individual
|
||||
* pixels in the buffer, as per the following formula:
|
||||
* |[<!-- -->
|
||||
* mean = sum (buf[0..size]) / size
|
||||
* sq_dev = sum ((buf[0.size] - mean) ^ 2)
|
||||
* ]|
|
||||
* This function is usually used to determine whether image
|
||||
* is empty.
|
||||
*
|
||||
* Returns: the squared standard deviation for @buffer
|
||||
*/
|
||||
gint
|
||||
fpi_std_sq_dev (const guint8 *buf,
|
||||
gint size)
|
||||
{
|
||||
guint64 res = 0, mean = 0;
|
||||
gint i;
|
||||
|
||||
for (i = 0; i < size; i++)
|
||||
mean += buf[i];
|
||||
|
||||
mean /= size;
|
||||
|
||||
for (i = 0; i < size; i++)
|
||||
{
|
||||
int dev = (int) buf[i] - mean;
|
||||
res += dev * dev;
|
||||
}
|
||||
|
||||
return res / size;
|
||||
}
|
||||
|
||||
/**
|
||||
* fpi_mean_sq_diff_norm:
|
||||
* @buf1: buffer (usually bitmap, one byte per pixel)
|
||||
* @buf2: buffer (usually bitmap, one byte per pixel)
|
||||
* @size: buffer size of smallest buffer
|
||||
*
|
||||
* This function calculates the normalized mean square difference of
|
||||
* two buffers, usually two lines, as per the following formula:
|
||||
* |[<!-- -->
|
||||
* sq_diff = sum ((buf1[0..size] - buf2[0..size]) ^ 2) / size
|
||||
* ]|
|
||||
*
|
||||
* This functions is usually used to get numerical difference
|
||||
* between two images.
|
||||
*
|
||||
* Returns: the normalized mean squared difference between @buf1 and @buf2
|
||||
*/
|
||||
gint
|
||||
fpi_mean_sq_diff_norm (const guint8 *buf1,
|
||||
const guint8 *buf2,
|
||||
gint size)
|
||||
{
|
||||
int res = 0, i;
|
||||
|
||||
for (i = 0; i < size; i++)
|
||||
{
|
||||
int dev = (int) buf1[i] - (int) buf2[i];
|
||||
res += dev * dev;
|
||||
}
|
||||
|
||||
return res / size;
|
||||
}
|
||||
|
||||
/**
|
||||
* fp_minutia_get_coords:
|
||||
* @min: A #FpMinutia
|
||||
@@ -567,44 +495,3 @@ fp_minutia_get_coords (FpMinutia *min, gint *x, gint *y)
|
||||
if (y)
|
||||
*y = min->y;
|
||||
}
|
||||
|
||||
#if HAVE_PIXMAN
|
||||
FpImage *
|
||||
fpi_image_resize (FpImage *orig_img,
|
||||
guint w_factor,
|
||||
guint h_factor)
|
||||
{
|
||||
int new_width = orig_img->width * w_factor;
|
||||
int new_height = orig_img->height * h_factor;
|
||||
pixman_image_t *orig, *resized;
|
||||
pixman_transform_t transform;
|
||||
FpImage *newimg;
|
||||
|
||||
orig = pixman_image_create_bits (PIXMAN_a8, orig_img->width, orig_img->height, (uint32_t *) orig_img->data, orig_img->width);
|
||||
resized = pixman_image_create_bits (PIXMAN_a8, new_width, new_height, NULL, new_width);
|
||||
|
||||
pixman_transform_init_identity (&transform);
|
||||
pixman_transform_scale (NULL, &transform, pixman_int_to_fixed (w_factor), pixman_int_to_fixed (h_factor));
|
||||
pixman_image_set_transform (orig, &transform);
|
||||
pixman_image_set_filter (orig, PIXMAN_FILTER_BILINEAR, NULL, 0);
|
||||
pixman_image_composite32 (PIXMAN_OP_SRC,
|
||||
orig, /* src */
|
||||
NULL, /* mask */
|
||||
resized, /* dst */
|
||||
0, 0, /* src x y */
|
||||
0, 0, /* mask x y */
|
||||
0, 0, /* dst x y */
|
||||
new_width, new_height /* width height */
|
||||
);
|
||||
|
||||
newimg = fp_image_new (new_width, new_height);
|
||||
newimg->flags = orig_img->flags;
|
||||
|
||||
memcpy (newimg->data, pixman_image_get_data (resized), new_width * new_height);
|
||||
|
||||
pixman_image_unref (orig);
|
||||
pixman_image_unref (resized);
|
||||
|
||||
return newimg;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/*
|
||||
* Driver IDs
|
||||
* Copyright (C) 2012 Vasily Khoruzhick <anarsoul@gmail.com>
|
||||
* FPrint Print handling
|
||||
* Copyright (C) 2007 Daniel Drake <dsd@gentoo.org>
|
||||
* Copyright (C) 2019 Benjamin Berg <bberg@redhat.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
@@ -17,31 +18,29 @@
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef __DRIVER_IDS
|
||||
#define __DRIVER_IDS
|
||||
#include "fpi-print.h"
|
||||
#include "fpi-image.h"
|
||||
|
||||
enum {
|
||||
UPEKTS_ID = 1,
|
||||
URU4000_ID = 2,
|
||||
AES4000_ID = 3,
|
||||
AES2501_ID = 4,
|
||||
UPEKTC_ID = 5,
|
||||
AES1610_ID = 6,
|
||||
/* FDU2000_ID = 7, */
|
||||
VCOM5S_ID = 8,
|
||||
UPEKSONLY_ID = 9,
|
||||
VFS101_ID = 10,
|
||||
VFS301_ID = 11,
|
||||
AES2550_ID = 12,
|
||||
/* UPEKE2_ID = 13 */
|
||||
AES1660_ID = 14,
|
||||
AES2660_ID = 15,
|
||||
AES3500_ID = 16,
|
||||
UPEKTC_IMG_ID = 17,
|
||||
ETES603_ID = 18,
|
||||
VFS5011_ID = 19,
|
||||
VFS0050_ID = 20,
|
||||
ELAN_ID = 21,
|
||||
#include <nbis.h>
|
||||
|
||||
struct _FpPrint
|
||||
{
|
||||
GInitiallyUnowned parent_instance;
|
||||
|
||||
FpiPrintType type;
|
||||
|
||||
gchar *driver;
|
||||
gchar *device_id;
|
||||
gboolean device_stored;
|
||||
|
||||
FpImage *image;
|
||||
|
||||
/* Metadata */
|
||||
FpFinger finger;
|
||||
gchar *username;
|
||||
gchar *description;
|
||||
GDate *enroll_date;
|
||||
|
||||
GVariant *data;
|
||||
GPtrArray *prints;
|
||||
};
|
||||
|
||||
#endif
|
||||
+52
-277
@@ -18,12 +18,11 @@
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "fpi-print.h"
|
||||
#include "fpi-image.h"
|
||||
#include "fpi-device.h"
|
||||
#define FP_COMPONENT "print"
|
||||
|
||||
#include "nbis/include/bozorth.h"
|
||||
#include "nbis/include/lfs.h"
|
||||
#include "fp-print-private.h"
|
||||
#include "fpi-compat.h"
|
||||
#include "fpi-log.h"
|
||||
|
||||
/**
|
||||
* SECTION: fp-print
|
||||
@@ -42,28 +41,6 @@
|
||||
* #FpPrint routines.
|
||||
*/
|
||||
|
||||
struct _FpPrint
|
||||
{
|
||||
GInitiallyUnowned parent_instance;
|
||||
|
||||
FpPrintType type;
|
||||
|
||||
gchar *driver;
|
||||
gchar *device_id;
|
||||
gboolean device_stored;
|
||||
|
||||
FpImage *image;
|
||||
|
||||
/* Metadata */
|
||||
FpFinger finger;
|
||||
gchar *username;
|
||||
gchar *description;
|
||||
GDate *enroll_date;
|
||||
|
||||
GVariant *data;
|
||||
GPtrArray *prints;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (FpPrint, fp_print, G_TYPE_INITIALLY_UNOWNED)
|
||||
|
||||
enum {
|
||||
@@ -74,7 +51,7 @@ enum {
|
||||
PROP_IMAGE,
|
||||
|
||||
/* The following is metadata that is stored by default for each print.
|
||||
* Drivers may make use of these during enrollment (e.g. to additionaly store
|
||||
* Drivers may make use of these during enrollment (e.g. to additionally store
|
||||
* the metadata on the device). */
|
||||
PROP_FINGER,
|
||||
PROP_USERNAME,
|
||||
@@ -101,6 +78,7 @@ fp_print_finalize (GObject *object)
|
||||
g_clear_pointer (&self->description, g_free);
|
||||
g_clear_pointer (&self->enroll_date, g_date_free);
|
||||
g_clear_pointer (&self->data, g_variant_unref);
|
||||
g_clear_pointer (&self->prints, g_ptr_array_unref);
|
||||
|
||||
G_OBJECT_CLASS (fp_print_parent_class)->finalize (object);
|
||||
}
|
||||
@@ -206,7 +184,7 @@ fp_print_set_property (GObject *object,
|
||||
break;
|
||||
|
||||
case PROP_FPI_DATA:
|
||||
g_clear_pointer (&self->description, g_variant_unref);
|
||||
g_clear_pointer (&self->data, g_variant_unref);
|
||||
self->data = g_value_dup_variant (value);
|
||||
break;
|
||||
|
||||
@@ -291,16 +269,30 @@ fp_print_class_init (FpPrintClass *klass)
|
||||
G_TYPE_DATE,
|
||||
G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE);
|
||||
|
||||
/**
|
||||
* FpPrint::fpi-type: (skip)
|
||||
*
|
||||
* This property is only for internal purposes.
|
||||
*
|
||||
* Stability: private
|
||||
*/
|
||||
properties[PROP_FPI_TYPE] =
|
||||
g_param_spec_enum ("fp-type",
|
||||
g_param_spec_enum ("fpi-type",
|
||||
"Type",
|
||||
"Private: The type of the print data",
|
||||
FP_TYPE_PRINT_TYPE,
|
||||
FP_PRINT_RAW,
|
||||
FPI_TYPE_PRINT_TYPE,
|
||||
FPI_PRINT_RAW,
|
||||
G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
/**
|
||||
* FpPrint::fpi-data: (skip)
|
||||
*
|
||||
* This property is only for internal purposes.
|
||||
*
|
||||
* Stability: private
|
||||
*/
|
||||
properties[PROP_FPI_DATA] =
|
||||
g_param_spec_variant ("fp-data",
|
||||
g_param_spec_variant ("fpi-data",
|
||||
"Raw Data",
|
||||
"The raw data for internal use only",
|
||||
G_VARIANT_TYPE_ANY,
|
||||
@@ -534,228 +526,11 @@ fp_print_set_enroll_date (FpPrint *print,
|
||||
|
||||
g_clear_pointer (&print->enroll_date, g_date_free);
|
||||
if (enroll_date)
|
||||
{
|
||||
/* XXX: Should use g_date_copy, but that is new in 2.56. */
|
||||
print->enroll_date = g_date_new ();
|
||||
*print->enroll_date = *enroll_date;
|
||||
}
|
||||
print->enroll_date = g_date_copy (enroll_date);
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (print), properties[PROP_ENROLL_DATE]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* fpi_print_add_print:
|
||||
* @print: A #FpPrint
|
||||
* @add: Print to append to @print
|
||||
*
|
||||
* Appends the single #FP_PRINT_NBIS print from @add to the collection of
|
||||
* prints in @print. Both print objects need to be of type #FP_PRINT_NBIS
|
||||
* for this to work.
|
||||
*/
|
||||
void
|
||||
fpi_print_add_print (FpPrint *print, FpPrint *add)
|
||||
{
|
||||
g_return_if_fail (print->type == FP_PRINT_NBIS);
|
||||
g_return_if_fail (add->type == FP_PRINT_NBIS);
|
||||
|
||||
g_assert (add->prints->len == 1);
|
||||
g_ptr_array_add (print->prints, g_memdup (add->prints->pdata[0], sizeof (struct xyt_struct)));
|
||||
}
|
||||
|
||||
/**
|
||||
* fpi_print_set_type:
|
||||
* @print: A #FpPrint
|
||||
* @type: The newly type of the print data
|
||||
*
|
||||
* This function can only be called exactly once. Drivers should
|
||||
* call it after creating a new print, or to initialize the template
|
||||
* print passed during enrollment.
|
||||
*/
|
||||
void
|
||||
fpi_print_set_type (FpPrint *print,
|
||||
FpPrintType type)
|
||||
{
|
||||
g_return_if_fail (FP_IS_PRINT (print));
|
||||
/* We only allow setting this once! */
|
||||
g_return_if_fail (print->type == FP_PRINT_UNDEFINED);
|
||||
|
||||
print->type = type;
|
||||
if (print->type == FP_PRINT_NBIS)
|
||||
print->prints = g_ptr_array_new_with_free_func (g_free);
|
||||
g_object_notify_by_pspec (G_OBJECT (print), properties[PROP_FPI_TYPE]);
|
||||
}
|
||||
|
||||
/**
|
||||
* fpi_print_set_device_stored:
|
||||
* @print: A #FpPrint
|
||||
* @device_stored: Whether the print is stored on the device or not
|
||||
*
|
||||
* Drivers must set this to %TRUE for any print that is really a handle
|
||||
* for data that is stored on the device itself.
|
||||
*/
|
||||
void
|
||||
fpi_print_set_device_stored (FpPrint *print,
|
||||
gboolean device_stored)
|
||||
{
|
||||
g_return_if_fail (FP_IS_PRINT (print));
|
||||
|
||||
print->device_stored = device_stored;
|
||||
g_object_notify_by_pspec (G_OBJECT (print), properties[PROP_DEVICE_STORED]);
|
||||
}
|
||||
|
||||
/* XXX: This is the old version, but wouldn't it be smarter to instead
|
||||
* use the highest quality mintutiae? Possibly just using bz_prune from
|
||||
* upstream? */
|
||||
static void
|
||||
minutiae_to_xyt (struct fp_minutiae *minutiae,
|
||||
int bwidth,
|
||||
int bheight,
|
||||
struct xyt_struct *xyt)
|
||||
{
|
||||
int i;
|
||||
struct fp_minutia *minutia;
|
||||
struct minutiae_struct c[MAX_FILE_MINUTIAE];
|
||||
|
||||
/* struct xyt_struct uses arrays of MAX_BOZORTH_MINUTIAE (200) */
|
||||
int nmin = min (minutiae->num, MAX_BOZORTH_MINUTIAE);
|
||||
|
||||
for (i = 0; i < nmin; i++)
|
||||
{
|
||||
minutia = minutiae->list[i];
|
||||
|
||||
lfs2nist_minutia_XYT (&c[i].col[0], &c[i].col[1], &c[i].col[2],
|
||||
minutia, bwidth, bheight);
|
||||
c[i].col[3] = sround (minutia->reliability * 100.0);
|
||||
|
||||
if (c[i].col[2] > 180)
|
||||
c[i].col[2] -= 360;
|
||||
}
|
||||
|
||||
qsort ((void *) &c, (size_t) nmin, sizeof (struct minutiae_struct),
|
||||
sort_x_y);
|
||||
|
||||
for (i = 0; i < nmin; i++)
|
||||
{
|
||||
xyt->xcol[i] = c[i].col[0];
|
||||
xyt->ycol[i] = c[i].col[1];
|
||||
xyt->thetacol[i] = c[i].col[2];
|
||||
}
|
||||
xyt->nrows = nmin;
|
||||
}
|
||||
|
||||
/**
|
||||
* fpi_print_add_from_image:
|
||||
* @print: A #FpPrint
|
||||
* @image: A #FpImage
|
||||
* @error: Return location for error
|
||||
*
|
||||
* Extracts the minutiae from the given image and adds it to @print of
|
||||
* type #FP_PRINT_NBIS.
|
||||
*
|
||||
* The @image will be kept so that API users can get retrieve it e.g.
|
||||
* for debugging purposes.
|
||||
*
|
||||
* Returns: %TRUE on success
|
||||
*/
|
||||
gboolean
|
||||
fpi_print_add_from_image (FpPrint *print,
|
||||
FpImage *image,
|
||||
GError **error)
|
||||
{
|
||||
GPtrArray *minutiae;
|
||||
struct fp_minutiae _minutiae;
|
||||
struct xyt_struct *xyt;
|
||||
|
||||
if (print->type != FP_PRINT_NBIS || !image)
|
||||
{
|
||||
g_set_error (error,
|
||||
G_IO_ERROR,
|
||||
G_IO_ERROR_INVALID_DATA,
|
||||
"Cannot add print data from image!");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
minutiae = fp_image_get_minutiae (image);
|
||||
if (!minutiae || minutiae->len == 0)
|
||||
{
|
||||
g_set_error (error,
|
||||
G_IO_ERROR,
|
||||
G_IO_ERROR_INVALID_DATA,
|
||||
"No minutiae found in image or not yet detected!");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
_minutiae.num = minutiae->len;
|
||||
_minutiae.list = (struct fp_minutia **) minutiae->pdata;
|
||||
_minutiae.alloc = minutiae->len;
|
||||
|
||||
xyt = g_new0 (struct xyt_struct, 1);
|
||||
minutiae_to_xyt (&_minutiae, image->width, image->height, xyt);
|
||||
g_ptr_array_add (print->prints, xyt);
|
||||
|
||||
g_clear_object (&print->image);
|
||||
print->image = g_object_ref (image);
|
||||
g_object_notify_by_pspec (G_OBJECT (print), properties[PROP_IMAGE]);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* fpi_print_bz3_match:
|
||||
* @template: A #FpPrint containing one or more prints
|
||||
* @print: A newly scanned #FpPrint to test
|
||||
* @bz3_threshold: The BZ3 match threshold
|
||||
* @error: Return location for error
|
||||
*
|
||||
* Match the newly scanned @print (containing exactly one print) against the
|
||||
* prints contained in @template which will have been stored during enrollment.
|
||||
*
|
||||
* Both @template and @print need to be of type #FP_PRINT_NBIS for this to
|
||||
* work.
|
||||
*
|
||||
* Returns: Whether the prints match, @error will be set if #FPI_MATCH_ERROR is returned
|
||||
*/
|
||||
FpiMatchResult
|
||||
fpi_print_bz3_match (FpPrint *template, FpPrint *print, gint bz3_threshold, GError **error)
|
||||
{
|
||||
struct xyt_struct *pstruct;
|
||||
gint probe_len;
|
||||
gint i;
|
||||
|
||||
/* XXX: Use a different error type? */
|
||||
if (template->type != FP_PRINT_NBIS || print->type != FP_PRINT_NBIS)
|
||||
{
|
||||
*error = fpi_device_error_new_msg (FP_DEVICE_ERROR_NOT_SUPPORTED,
|
||||
"It is only possible to match NBIS type print data");
|
||||
return FPI_MATCH_ERROR;
|
||||
}
|
||||
|
||||
if (print->prints->len != 1)
|
||||
{
|
||||
*error = fpi_device_error_new_msg (FP_DEVICE_ERROR_GENERAL,
|
||||
"New print contains more than one print!");
|
||||
return FPI_MATCH_ERROR;
|
||||
}
|
||||
|
||||
pstruct = g_ptr_array_index (print->prints, 0);
|
||||
probe_len = bozorth_probe_init (pstruct);
|
||||
|
||||
for (i = 0; i < template->prints->len; i++)
|
||||
{
|
||||
struct xyt_struct *gstruct;
|
||||
gint score;
|
||||
gstruct = g_ptr_array_index (template->prints, i);
|
||||
score = bozorth_to_gallery (probe_len, pstruct, gstruct);
|
||||
fp_dbg ("score %d", score);
|
||||
|
||||
if (score >= bz3_threshold)
|
||||
return FPI_MATCH_SUCCESS;
|
||||
}
|
||||
|
||||
return FPI_MATCH_FAIL;
|
||||
}
|
||||
|
||||
/**
|
||||
* fp_print_compatible:
|
||||
* @self: A #FpPrint
|
||||
@@ -795,8 +570,8 @@ fp_print_equal (FpPrint *self, FpPrint *other)
|
||||
{
|
||||
g_return_val_if_fail (FP_IS_PRINT (self), FALSE);
|
||||
g_return_val_if_fail (FP_IS_PRINT (other), FALSE);
|
||||
g_return_val_if_fail (self->type != FP_PRINT_UNDEFINED, FALSE);
|
||||
g_return_val_if_fail (other->type != FP_PRINT_UNDEFINED, FALSE);
|
||||
g_return_val_if_fail (self->type != FPI_PRINT_UNDEFINED, FALSE);
|
||||
g_return_val_if_fail (other->type != FPI_PRINT_UNDEFINED, FALSE);
|
||||
|
||||
if (self->type != other->type)
|
||||
return FALSE;
|
||||
@@ -807,13 +582,13 @@ fp_print_equal (FpPrint *self, FpPrint *other)
|
||||
if (g_strcmp0 (self->device_id, other->device_id))
|
||||
return FALSE;
|
||||
|
||||
if (self->type == FP_PRINT_RAW)
|
||||
if (self->type == FPI_PRINT_RAW)
|
||||
{
|
||||
return g_variant_equal (self->data, other->data);
|
||||
}
|
||||
else if (self->type == FP_PRINT_NBIS)
|
||||
else if (self->type == FPI_PRINT_NBIS)
|
||||
{
|
||||
gint i;
|
||||
guint i;
|
||||
|
||||
if (self->prints->len != other->prints->len)
|
||||
return FALSE;
|
||||
@@ -835,7 +610,7 @@ fp_print_equal (FpPrint *self, FpPrint *other)
|
||||
}
|
||||
}
|
||||
|
||||
#define FP_PRINT_VARIANT_TYPE G_VARIANT_TYPE ("(issbymsmsia{sv}v)")
|
||||
#define FPI_PRINT_VARIANT_TYPE G_VARIANT_TYPE ("(issbymsmsia{sv}v)")
|
||||
|
||||
G_STATIC_ASSERT (sizeof (((struct xyt_struct *) NULL)->xcol[0]) == 4);
|
||||
|
||||
@@ -858,7 +633,7 @@ fp_print_serialize (FpPrint *print,
|
||||
GError **error)
|
||||
{
|
||||
g_autoptr(GVariant) result = NULL;
|
||||
GVariantBuilder builder = G_VARIANT_BUILDER_INIT (FP_PRINT_VARIANT_TYPE);
|
||||
GVariantBuilder builder = G_VARIANT_BUILDER_INIT (FPI_PRINT_VARIANT_TYPE);
|
||||
gsize len;
|
||||
|
||||
g_assert (data);
|
||||
@@ -883,10 +658,10 @@ fp_print_serialize (FpPrint *print,
|
||||
g_variant_builder_close (&builder);
|
||||
|
||||
/* Insert NBIS print data for type NBIS, otherwise the GVariant directly */
|
||||
if (print->type == FP_PRINT_NBIS)
|
||||
if (print->type == FPI_PRINT_NBIS)
|
||||
{
|
||||
GVariantBuilder nested = G_VARIANT_BUILDER_INIT (G_VARIANT_TYPE ("(a(aiaiai))"));
|
||||
gint i;
|
||||
guint i;
|
||||
|
||||
g_variant_builder_open (&nested, G_VARIANT_TYPE ("a(aiaiai)"));
|
||||
for (i = 0; i < print->prints->len; i++)
|
||||
@@ -921,6 +696,7 @@ fp_print_serialize (FpPrint *print,
|
||||
xyt->nrows,
|
||||
sizeof (col[0])));
|
||||
g_variant_builder_close (&nested);
|
||||
g_free (col);
|
||||
}
|
||||
|
||||
g_variant_builder_close (&nested);
|
||||
@@ -976,18 +752,18 @@ fp_print_deserialize (const guchar *data,
|
||||
g_autoptr(FpPrint) result = NULL;
|
||||
g_autoptr(GVariant) raw_value = NULL;
|
||||
g_autoptr(GVariant) value = NULL;
|
||||
g_autoptr(GVariant) print_data = NULL;
|
||||
g_autoptr(GDate) date = NULL;
|
||||
guchar *aligned_data = NULL;
|
||||
GDate *date = NULL;
|
||||
guint8 finger_int8;
|
||||
FpFinger finger;
|
||||
g_autofree gchar *username = NULL;
|
||||
g_autofree gchar *description = NULL;
|
||||
gint julian_date;
|
||||
FpPrintType type;
|
||||
FpiPrintType type;
|
||||
const gchar *driver;
|
||||
const gchar *device_id;
|
||||
gboolean device_stored;
|
||||
GVariant *print_data;
|
||||
|
||||
g_assert (data);
|
||||
g_assert (length > 3);
|
||||
@@ -1005,9 +781,9 @@ fp_print_deserialize (const guchar *data,
|
||||
* longer. */
|
||||
aligned_data = g_malloc (length - 3);
|
||||
memcpy (aligned_data, data + 3, length - 3);
|
||||
raw_value = g_variant_new_from_data (FP_PRINT_VARIANT_TYPE,
|
||||
raw_value = g_variant_new_from_data (FPI_PRINT_VARIANT_TYPE,
|
||||
aligned_data, length - 3,
|
||||
FALSE, g_free, NULL);
|
||||
FALSE, g_free, aligned_data);
|
||||
|
||||
if (!raw_value)
|
||||
goto invalid_format;
|
||||
@@ -1018,7 +794,7 @@ fp_print_deserialize (const guchar *data,
|
||||
value = g_variant_get_normal_form (raw_value);
|
||||
|
||||
g_variant_get (value,
|
||||
"(issbymsmsi@a{sv}v)",
|
||||
"(i&s&sbymsmsi@a{sv}v)",
|
||||
&type,
|
||||
&driver,
|
||||
&device_id,
|
||||
@@ -1033,20 +809,20 @@ fp_print_deserialize (const guchar *data,
|
||||
finger = finger_int8;
|
||||
|
||||
/* Assume data is valid at this point if the values are somewhat sane. */
|
||||
if (type == FP_PRINT_NBIS)
|
||||
if (type == FPI_PRINT_NBIS)
|
||||
{
|
||||
g_autoptr(GVariant) prints = g_variant_get_child_value (print_data, 0);
|
||||
gint i;
|
||||
guint i;
|
||||
|
||||
result = g_object_new (FP_TYPE_PRINT,
|
||||
"driver", driver,
|
||||
"device-id", device_id,
|
||||
"device-stored", device_stored,
|
||||
NULL);
|
||||
fpi_print_set_type (result, FP_PRINT_NBIS);
|
||||
fpi_print_set_type (result, FPI_PRINT_NBIS);
|
||||
for (i = 0; i < g_variant_n_children (prints); i++)
|
||||
{
|
||||
struct xyt_struct *xyt = g_new0 (struct xyt_struct, 1);
|
||||
g_autofree struct xyt_struct *xyt = NULL;
|
||||
const gint32 *xcol, *ycol, *thetacol;
|
||||
gsize xlen, ylen, thetalen;
|
||||
g_autoptr(GVariant) xyt_data = NULL;
|
||||
@@ -1072,24 +848,25 @@ fp_print_deserialize (const guchar *data,
|
||||
if (xlen > G_N_ELEMENTS (xyt->xcol))
|
||||
goto invalid_format;
|
||||
|
||||
xyt = g_new0 (struct xyt_struct, 1);
|
||||
xyt->nrows = xlen;
|
||||
memcpy (xyt->xcol, xcol, sizeof (xcol[0]) * xlen);
|
||||
memcpy (xyt->ycol, ycol, sizeof (xcol[0]) * xlen);
|
||||
memcpy (xyt->thetacol, thetacol, sizeof (xcol[0]) * xlen);
|
||||
|
||||
g_ptr_array_add (result->prints, xyt);
|
||||
g_ptr_array_add (result->prints, g_steal_pointer (&xyt));
|
||||
}
|
||||
}
|
||||
else if (type == FP_PRINT_RAW)
|
||||
else if (type == FPI_PRINT_RAW)
|
||||
{
|
||||
g_autoptr(GVariant) fp_data = g_variant_get_child_value (print_data, 0);
|
||||
|
||||
result = g_object_new (FP_TYPE_PRINT,
|
||||
"fp-type", type,
|
||||
"fpi-type", type,
|
||||
"driver", driver,
|
||||
"device-id", device_id,
|
||||
"device-stored", device_stored,
|
||||
"fp-data", fp_data,
|
||||
"fpi-data", fp_data,
|
||||
NULL);
|
||||
}
|
||||
else
|
||||
@@ -1106,8 +883,6 @@ fp_print_deserialize (const guchar *data,
|
||||
"enroll_date", date,
|
||||
NULL);
|
||||
|
||||
g_date_free (date);
|
||||
|
||||
return g_steal_pointer (&result);
|
||||
|
||||
invalid_format:
|
||||
|
||||
@@ -28,6 +28,9 @@ G_BEGIN_DECLS
|
||||
#define FP_TYPE_PRINT (fp_print_get_type ())
|
||||
G_DECLARE_FINAL_TYPE (FpPrint, fp_print, FP, PRINT, GInitiallyUnowned)
|
||||
|
||||
#define FP_FINGER_IS_VALID(finger) \
|
||||
((finger) >= FP_FINGER_FIRST && (finger) <= FP_FINGER_LAST)
|
||||
|
||||
#include "fp-device.h"
|
||||
|
||||
/**
|
||||
@@ -43,6 +46,8 @@ G_DECLARE_FINAL_TYPE (FpPrint, fp_print, FP, PRINT, GInitiallyUnowned)
|
||||
* @FP_FINGER_RIGHT_MIDDLE: Right middle finger
|
||||
* @FP_FINGER_RIGHT_RING: Right ring finger
|
||||
* @FP_FINGER_RIGHT_LITTLE: Right little finger
|
||||
* @FP_FINGER_FIRST: The first finger in the fp-print order
|
||||
* @FP_FINGER_LAST: The last finger in the fp-print order
|
||||
*/
|
||||
typedef enum {
|
||||
FP_FINGER_UNKNOWN = 0,
|
||||
@@ -56,6 +61,9 @@ typedef enum {
|
||||
FP_FINGER_RIGHT_MIDDLE,
|
||||
FP_FINGER_RIGHT_RING,
|
||||
FP_FINGER_RIGHT_LITTLE,
|
||||
|
||||
FP_FINGER_FIRST = FP_FINGER_LEFT_THUMB,
|
||||
FP_FINGER_LAST = FP_FINGER_RIGHT_LITTLE,
|
||||
} FpFinger;
|
||||
|
||||
FpPrint *fp_print_new (FpDevice *device);
|
||||
|
||||
+41
-30
@@ -21,7 +21,8 @@
|
||||
|
||||
#define FP_COMPONENT "assembling"
|
||||
|
||||
#include "fp_internal.h"
|
||||
#include "fpi-log.h"
|
||||
#include "fpi-image.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
@@ -51,6 +52,9 @@ calc_error (struct fpi_frame_asmbl_ctx *ctx,
|
||||
width = ctx->frame_width - (dx > 0 ? dx : -dx);
|
||||
height = ctx->frame_height - dy;
|
||||
|
||||
if (height == 0 || width == 0)
|
||||
return INT_MAX;
|
||||
|
||||
y1 = 0;
|
||||
y2 = dy;
|
||||
i = 0;
|
||||
@@ -85,9 +89,6 @@ calc_error (struct fpi_frame_asmbl_ctx *ctx,
|
||||
err *= (ctx->frame_height * ctx->frame_width);
|
||||
err /= (height * width);
|
||||
|
||||
if (err == 0)
|
||||
return INT_MAX;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -98,6 +99,8 @@ static void
|
||||
find_overlap (struct fpi_frame_asmbl_ctx *ctx,
|
||||
struct fpi_frame *first_frame,
|
||||
struct fpi_frame *second_frame,
|
||||
int *dx_out,
|
||||
int *dy_out,
|
||||
unsigned int *min_error)
|
||||
{
|
||||
int dx, dy;
|
||||
@@ -119,8 +122,8 @@ find_overlap (struct fpi_frame_asmbl_ctx *ctx,
|
||||
if (err < *min_error)
|
||||
{
|
||||
*min_error = err;
|
||||
second_frame->delta_x = -dx;
|
||||
second_frame->delta_y = dy;
|
||||
*dx_out = -dx;
|
||||
*dy_out = dy;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -132,7 +135,7 @@ do_movement_estimation (struct fpi_frame_asmbl_ctx *ctx,
|
||||
{
|
||||
GSList *l;
|
||||
GTimer *timer;
|
||||
guint num_frames = 0;
|
||||
guint num_frames = 1;
|
||||
struct fpi_frame *prev_stripe;
|
||||
unsigned int min_error;
|
||||
/* Max error is width * height * 255, for AES2501 which has the largest
|
||||
@@ -142,20 +145,27 @@ do_movement_estimation (struct fpi_frame_asmbl_ctx *ctx,
|
||||
unsigned long long total_error = 0;
|
||||
|
||||
timer = g_timer_new ();
|
||||
|
||||
/* Skip the first frame */
|
||||
prev_stripe = stripes->data;
|
||||
for (l = stripes; l != NULL; l = l->next, num_frames++)
|
||||
|
||||
for (l = stripes->next; l != NULL; l = l->next, num_frames++)
|
||||
{
|
||||
struct fpi_frame *cur_stripe = l->data;
|
||||
|
||||
if (reverse)
|
||||
{
|
||||
find_overlap (ctx, prev_stripe, cur_stripe, &min_error);
|
||||
find_overlap (ctx, prev_stripe, cur_stripe,
|
||||
&cur_stripe->delta_x, &cur_stripe->delta_y,
|
||||
&min_error);
|
||||
cur_stripe->delta_y = -cur_stripe->delta_y;
|
||||
cur_stripe->delta_x = -cur_stripe->delta_x;
|
||||
}
|
||||
else
|
||||
{
|
||||
find_overlap (ctx, cur_stripe, prev_stripe, &min_error);
|
||||
find_overlap (ctx, cur_stripe, prev_stripe,
|
||||
&cur_stripe->delta_x, &cur_stripe->delta_y,
|
||||
&min_error);
|
||||
}
|
||||
total_error += min_error;
|
||||
|
||||
@@ -327,19 +337,10 @@ fpi_assemble_frames (struct fpi_frame_asmbl_ctx *ctx,
|
||||
{
|
||||
fpi_frame = l->data;
|
||||
|
||||
if(reverse)
|
||||
{
|
||||
y += fpi_frame->delta_y;
|
||||
x += fpi_frame->delta_x;
|
||||
}
|
||||
|
||||
aes_blit_stripe (ctx, img, fpi_frame, x, y);
|
||||
|
||||
if(!reverse)
|
||||
{
|
||||
y += fpi_frame->delta_y;
|
||||
x += fpi_frame->delta_x;
|
||||
}
|
||||
}
|
||||
|
||||
return img;
|
||||
@@ -385,8 +386,10 @@ median_filter (int *data, int size, int filtersize)
|
||||
|
||||
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)
|
||||
GSList *line1, gint32 y1_f,
|
||||
GSList *line2, gint32 y2_f,
|
||||
unsigned char *output, gint32 yi_f,
|
||||
int size)
|
||||
{
|
||||
int i;
|
||||
unsigned char p1, p2;
|
||||
@@ -396,10 +399,12 @@ interpolate_lines (struct fpi_line_asmbl_ctx *ctx,
|
||||
|
||||
for (i = 0; i < size; i++)
|
||||
{
|
||||
gint unscaled;
|
||||
p1 = ctx->get_pixel (ctx, line1, i);
|
||||
p2 = ctx->get_pixel (ctx, line2, i);
|
||||
output[i] = (float) p1
|
||||
+ (yi - y1) / (y2 - y1) * (p2 - p1);
|
||||
|
||||
unscaled = (yi_f - y1_f) * p2 + (y2_f - yi_f) * p1;
|
||||
output[i] = (unscaled) / (y2_f - y1_f);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -424,7 +429,13 @@ fpi_assemble_lines (struct fpi_line_asmbl_ctx *ctx,
|
||||
/* Number of output lines per distance between two scanners */
|
||||
int i;
|
||||
GSList *row1, *row2;
|
||||
float y = 0.0;
|
||||
/* The y coordinate is tracked as a 16.16 fixed point number. All
|
||||
* variables postfixed with _f follow this format here and in
|
||||
* interpolate_lines.
|
||||
* We could also use floating point here, but using fixed point means
|
||||
* we get consistent results across architectures.
|
||||
*/
|
||||
gint32 y_f = 0;
|
||||
int line_ind = 0;
|
||||
int *offsets = g_new0 (int, num_lines / 2);
|
||||
unsigned char *output = g_malloc0 (ctx->line_width * ctx->max_height);
|
||||
@@ -476,21 +487,21 @@ fpi_assemble_lines (struct fpi_line_asmbl_ctx *ctx,
|
||||
int offset = offsets[i / 2];
|
||||
if (offset > 0)
|
||||
{
|
||||
float ynext = y + (float) ctx->resolution / offset;
|
||||
while (line_ind < ynext)
|
||||
gint32 ynext_f = y_f + (ctx->resolution << 16) / offset;
|
||||
while ((line_ind << 16) < ynext_f)
|
||||
{
|
||||
if (line_ind > ctx->max_height - 1)
|
||||
goto out;
|
||||
interpolate_lines (ctx,
|
||||
row1, y,
|
||||
row1, y_f,
|
||||
g_slist_next (row1),
|
||||
ynext,
|
||||
ynext_f,
|
||||
output + line_ind * ctx->line_width,
|
||||
line_ind,
|
||||
line_ind << 16,
|
||||
ctx->line_width);
|
||||
line_ind++;
|
||||
}
|
||||
y = ynext;
|
||||
y_f = ynext_f;
|
||||
}
|
||||
}
|
||||
out:
|
||||
|
||||
@@ -17,8 +17,7 @@
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef __FPI_ASSEMBLING_H__
|
||||
#define __FPI_ASSEMBLING_H__
|
||||
#pragma once
|
||||
|
||||
#include <fprint.h>
|
||||
|
||||
@@ -116,5 +115,3 @@ struct fpi_line_asmbl_ctx
|
||||
FpImage *fpi_assemble_lines (struct fpi_line_asmbl_ctx *ctx,
|
||||
GSList *lines,
|
||||
size_t num_lines);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -19,8 +19,7 @@
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef __FPI_BYTE_READER_H__
|
||||
#define __FPI_BYTE_READER_H__
|
||||
#pragma once
|
||||
|
||||
#include <glib.h>
|
||||
#include "fpi-byte-utils.h"
|
||||
@@ -676,5 +675,3 @@ fpi_byte_reader_skip_inline (FpiByteReader * reader, guint nbytes)
|
||||
#endif /* FPI_BYTE_READER_DISABLE_INLINES */
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __FPI_BYTE_READER_H__ */
|
||||
|
||||
@@ -21,9 +21,7 @@
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __FP_UTILS_H__
|
||||
#define __FP_UTILS_H__
|
||||
#pragma once
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
@@ -485,4 +483,3 @@ FP_WRITE_DOUBLE_BE(guint8 *data, gdouble num)
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GTK_DOC_IGNORE__ */
|
||||
#endif /* __FP_UTILS_H__ */
|
||||
|
||||
@@ -18,8 +18,7 @@
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef __FPI_BYTE_WRITER_H__
|
||||
#define __FPI_BYTE_WRITER_H__
|
||||
#pragma once
|
||||
|
||||
#include "fpi-byte-reader.h"
|
||||
#include <string.h>
|
||||
@@ -409,5 +408,3 @@ fpi_byte_writer_fill_inline (FpiByteWriter * writer, guint8 value, guint size)
|
||||
#endif
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __FPI_BYTE_WRITER_H__ */
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Benjamin Berg <bberg@redhat.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
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <glib-object.h>
|
||||
|
||||
#if !GLIB_CHECK_VERSION (2, 57, 0)
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC (GTypeClass, g_type_class_unref);
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC (GEnumClass, g_type_class_unref);
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC (GParamSpec, g_param_spec_unref);
|
||||
#else
|
||||
/* Re-define G_SOURCE_FUNC as we are technically not allowed to use it with
|
||||
* the version we depend on currently. */
|
||||
#undef G_SOURCE_FUNC
|
||||
#endif
|
||||
|
||||
#define G_SOURCE_FUNC(f) ((GSourceFunc) (void (*)(void))(f))
|
||||
|
||||
#if !GLIB_CHECK_VERSION (2, 63, 3)
|
||||
typedef struct _FpDeviceClass FpDeviceClass;
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC (FpDeviceClass, g_type_class_unref);
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC (GDate, g_date_free);
|
||||
#endif
|
||||
@@ -20,14 +20,16 @@
|
||||
|
||||
#include <gusb.h>
|
||||
#include "fp-context.h"
|
||||
#include "fpi-compat.h"
|
||||
|
||||
/**
|
||||
* fpi_get_driver_types:
|
||||
* @drivers: #GArray to be filled with all driver types
|
||||
*
|
||||
* This function is purely for private used. It is solely part of the public
|
||||
* API as it is useful during build time.
|
||||
*
|
||||
* Stability: private
|
||||
* Returns: (element-type GType) (transfer container): a #GArray filled with
|
||||
* all driver types
|
||||
*/
|
||||
void fpi_get_driver_types (GArray *drivers);
|
||||
GArray *fpi_get_driver_types (void);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
+39
-33
@@ -65,10 +65,10 @@ struct _FpIdEntry
|
||||
* @probe: Called immediately for all devices. Most drivers will not need to
|
||||
* implement this. Drivers should setup the device identifier from the probe
|
||||
* callback which will be used to verify the compatibility of stored
|
||||
* #FpPrint's. It is permissable to temporarily open the USB device if this
|
||||
* #FpPrint's. It is permissible to temporarily open the USB device if this
|
||||
* is required for the operation. If an error is returned, then the device
|
||||
* will be destroyed again immediately and never reported to the API user.
|
||||
* @open: Open the device for futher operations. Any of the normal actions are
|
||||
* @open: Open the device for further operations. Any of the normal actions are
|
||||
* guaranteed to only happen when the device is open (this includes delete).
|
||||
* @close: Close the device again
|
||||
* @enroll: Start an enroll operation
|
||||
@@ -142,48 +142,50 @@ typedef void (*FpTimeoutFunc) (FpDevice *device,
|
||||
gpointer user_data);
|
||||
|
||||
/**
|
||||
* FpDeviceAction:
|
||||
* @FP_DEVICE_ACTION_NONE: No action is active.
|
||||
* @FP_DEVICE_ACTION_PROBE: Probe device for support and information.
|
||||
* @FP_DEVICE_ACTION_OPEN: Device is currently being opened.
|
||||
* @FP_DEVICE_ACTION_CLOSE: Device is currently being closed.
|
||||
* @FP_DEVICE_ACTION_ENROLL: Device is currently enrolling.
|
||||
* @FP_DEVICE_ACTION_VERIFY: Device is currently verifying.
|
||||
* @FP_DEVICE_ACTION_IDENTIFY: Device is currently identifying.
|
||||
* @FP_DEVICE_ACTION_CAPTURE: Device is currently capturing an image.
|
||||
* @FP_DEVICE_ACTION_LIST: Device stored prints are being queried.
|
||||
* @FP_DEVICE_ACTION_DELETE: Device stored print is being deleted.
|
||||
* FpiDeviceAction:
|
||||
* @FPI_DEVICE_ACTION_NONE: No action is active.
|
||||
* @FPI_DEVICE_ACTION_PROBE: Probe device for support and information.
|
||||
* @FPI_DEVICE_ACTION_OPEN: Device is currently being opened.
|
||||
* @FPI_DEVICE_ACTION_CLOSE: Device is currently being closed.
|
||||
* @FPI_DEVICE_ACTION_ENROLL: Device is currently enrolling.
|
||||
* @FPI_DEVICE_ACTION_VERIFY: Device is currently verifying.
|
||||
* @FPI_DEVICE_ACTION_IDENTIFY: Device is currently identifying.
|
||||
* @FPI_DEVICE_ACTION_CAPTURE: Device is currently capturing an image.
|
||||
* @FPI_DEVICE_ACTION_LIST: Device stored prints are being queried.
|
||||
* @FPI_DEVICE_ACTION_DELETE: Device stored print is being deleted.
|
||||
*
|
||||
* Current active action of the device. A driver can retrieve the action.
|
||||
*/
|
||||
typedef enum {
|
||||
FP_DEVICE_ACTION_NONE = 0,
|
||||
FP_DEVICE_ACTION_PROBE,
|
||||
FP_DEVICE_ACTION_OPEN,
|
||||
FP_DEVICE_ACTION_CLOSE,
|
||||
FP_DEVICE_ACTION_ENROLL,
|
||||
FP_DEVICE_ACTION_VERIFY,
|
||||
FP_DEVICE_ACTION_IDENTIFY,
|
||||
FP_DEVICE_ACTION_CAPTURE,
|
||||
FP_DEVICE_ACTION_LIST,
|
||||
FP_DEVICE_ACTION_DELETE,
|
||||
} FpDeviceAction;
|
||||
FPI_DEVICE_ACTION_NONE = 0,
|
||||
FPI_DEVICE_ACTION_PROBE,
|
||||
FPI_DEVICE_ACTION_OPEN,
|
||||
FPI_DEVICE_ACTION_CLOSE,
|
||||
FPI_DEVICE_ACTION_ENROLL,
|
||||
FPI_DEVICE_ACTION_VERIFY,
|
||||
FPI_DEVICE_ACTION_IDENTIFY,
|
||||
FPI_DEVICE_ACTION_CAPTURE,
|
||||
FPI_DEVICE_ACTION_LIST,
|
||||
FPI_DEVICE_ACTION_DELETE,
|
||||
} FpiDeviceAction;
|
||||
|
||||
GUsbDevice *fpi_device_get_usb_device (FpDevice *device);
|
||||
const gchar *fpi_device_get_virtual_env (FpDevice *device);
|
||||
//const gchar *fpi_device_get_spi_dev (FpDevice *device);
|
||||
|
||||
|
||||
FpDeviceAction fpi_device_get_current_action (FpDevice *device);
|
||||
FpiDeviceAction fpi_device_get_current_action (FpDevice *device);
|
||||
gboolean fpi_device_action_is_cancelled (FpDevice *device);
|
||||
|
||||
GError * fpi_device_retry_new (FpDeviceRetry error);
|
||||
GError * fpi_device_error_new (FpDeviceError error);
|
||||
|
||||
GError * fpi_device_retry_new_msg (FpDeviceRetry error,
|
||||
const gchar *msg);
|
||||
const gchar *msg,
|
||||
...) G_GNUC_PRINTF (2, 3);
|
||||
GError * fpi_device_error_new_msg (FpDeviceError error,
|
||||
const gchar *msg);
|
||||
const gchar *msg,
|
||||
...) G_GNUC_PRINTF (2, 3);
|
||||
|
||||
guint64 fpi_device_get_driver_data (FpDevice *device);
|
||||
|
||||
@@ -201,11 +203,11 @@ void fpi_device_get_delete_data (FpDevice *device,
|
||||
GCancellable *fpi_device_get_cancellable (FpDevice *device);
|
||||
|
||||
|
||||
|
||||
GSource * fpi_device_add_timeout (FpDevice *device,
|
||||
gint interval,
|
||||
FpTimeoutFunc func,
|
||||
gpointer user_data);
|
||||
gpointer user_data,
|
||||
GDestroyNotify destroy_notify);
|
||||
|
||||
void fpi_device_set_nr_enroll_stages (FpDevice *device,
|
||||
gint enroll_stages);
|
||||
@@ -228,12 +230,8 @@ void fpi_device_enroll_complete (FpDevice *device,
|
||||
FpPrint *print,
|
||||
GError *error);
|
||||
void fpi_device_verify_complete (FpDevice *device,
|
||||
FpiMatchResult result,
|
||||
FpPrint *print,
|
||||
GError *error);
|
||||
void fpi_device_identify_complete (FpDevice *device,
|
||||
FpPrint *match,
|
||||
FpPrint *print,
|
||||
GError *error);
|
||||
void fpi_device_capture_complete (FpDevice *device,
|
||||
FpImage *image,
|
||||
@@ -248,5 +246,13 @@ void fpi_device_enroll_progress (FpDevice *device,
|
||||
gint completed_stages,
|
||||
FpPrint *print,
|
||||
GError *error);
|
||||
void fpi_device_verify_report (FpDevice *device,
|
||||
FpiMatchResult result,
|
||||
FpPrint *print,
|
||||
GError *error);
|
||||
void fpi_device_identify_report (FpDevice *device,
|
||||
FpPrint *match,
|
||||
FpPrint *print,
|
||||
GError *error);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
@@ -0,0 +1,644 @@
|
||||
/*
|
||||
* FpImageDevice - An image based fingerprint reader device - Private APIs
|
||||
* Copyright (C) 2019 Benjamin Berg <bberg@redhat.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 "image_device"
|
||||
#include "fpi-log.h"
|
||||
|
||||
#include "fp-image-device-private.h"
|
||||
#include "fp-image-device.h"
|
||||
|
||||
/**
|
||||
* SECTION: fpi-image-device
|
||||
* @title: Internal FpImageDevice
|
||||
* @short_description: Internal image device functions
|
||||
*
|
||||
* Internal image device functions. See #FpImageDevice for public routines.
|
||||
*/
|
||||
|
||||
/* Manually redefine what G_DEFINE_* macro does */
|
||||
static inline gpointer
|
||||
fp_image_device_get_instance_private (FpImageDevice *self)
|
||||
{
|
||||
FpImageDeviceClass *img_class = g_type_class_peek_static (FP_TYPE_IMAGE_DEVICE);
|
||||
|
||||
return G_STRUCT_MEMBER_P (self,
|
||||
g_type_class_get_instance_private_offset (img_class));
|
||||
}
|
||||
|
||||
/* Private shared functions */
|
||||
|
||||
void
|
||||
fpi_image_device_activate (FpImageDevice *self)
|
||||
{
|
||||
FpImageDevicePrivate *priv = fp_image_device_get_instance_private (self);
|
||||
FpImageDeviceClass *cls = FP_IMAGE_DEVICE_GET_CLASS (self);
|
||||
|
||||
g_assert (!priv->active);
|
||||
|
||||
/* We don't have a neutral ACTIVE state, but we always will
|
||||
* go into WAIT_FINGER_ON afterwards. */
|
||||
priv->state = FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON;
|
||||
g_object_notify (G_OBJECT (self), "fpi-image-device-state");
|
||||
|
||||
/* We might have been waiting for deactivation to finish before
|
||||
* starting the next operation. */
|
||||
g_clear_handle_id (&priv->pending_activation_timeout_id, g_source_remove);
|
||||
|
||||
fp_dbg ("Activating image device\n");
|
||||
cls->activate (self);
|
||||
}
|
||||
|
||||
void
|
||||
fpi_image_device_deactivate (FpImageDevice *self)
|
||||
{
|
||||
FpDevice *device = FP_DEVICE (self);
|
||||
FpImageDevicePrivate *priv = fp_image_device_get_instance_private (self);
|
||||
FpImageDeviceClass *cls = FP_IMAGE_DEVICE_GET_CLASS (device);
|
||||
|
||||
if (!priv->active)
|
||||
{
|
||||
/* XXX: We currently deactivate both from minutiae scan result
|
||||
* and finger off report. */
|
||||
fp_dbg ("Already deactivated, ignoring request.");
|
||||
return;
|
||||
}
|
||||
if (!priv->cancelling && priv->state == FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON)
|
||||
g_warning ("Deactivating image device while waiting for finger, this should not happen.");
|
||||
|
||||
priv->state = FPI_IMAGE_DEVICE_STATE_INACTIVE;
|
||||
g_object_notify (G_OBJECT (self), "fpi-image-device-state");
|
||||
|
||||
fp_dbg ("Deactivating image device\n");
|
||||
cls->deactivate (self);
|
||||
}
|
||||
|
||||
/* Static helper functions */
|
||||
|
||||
static void
|
||||
fp_image_device_change_state (FpImageDevice *self, FpiImageDeviceState state)
|
||||
{
|
||||
FpImageDevicePrivate *priv = fp_image_device_get_instance_private (self);
|
||||
|
||||
/* Cannot change to inactive using this function. */
|
||||
g_assert (state != FPI_IMAGE_DEVICE_STATE_INACTIVE);
|
||||
|
||||
/* We might have been waiting for the finger to go OFF to start the
|
||||
* next operation. */
|
||||
g_clear_handle_id (&priv->pending_activation_timeout_id, g_source_remove);
|
||||
|
||||
fp_dbg ("Image device internal state change from %d to %d\n", priv->state, state);
|
||||
|
||||
priv->state = state;
|
||||
g_object_notify (G_OBJECT (self), "fpi-image-device-state");
|
||||
g_signal_emit_by_name (self, "fpi-image-device-state-changed", priv->state);
|
||||
}
|
||||
|
||||
static void
|
||||
fp_image_device_enroll_maybe_await_finger_on (FpImageDevice *self)
|
||||
{
|
||||
FpImageDevicePrivate *priv = fp_image_device_get_instance_private (self);
|
||||
|
||||
if (priv->enroll_await_on_pending)
|
||||
{
|
||||
priv->enroll_await_on_pending = FALSE;
|
||||
fp_image_device_change_state (self, FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON);
|
||||
}
|
||||
else
|
||||
{
|
||||
priv->enroll_await_on_pending = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
fpi_image_device_minutiae_detected (GObject *source_object, GAsyncResult *res, gpointer user_data)
|
||||
{
|
||||
g_autoptr(FpImage) image = FP_IMAGE (source_object);
|
||||
g_autoptr(FpPrint) print = NULL;
|
||||
GError *error = NULL;
|
||||
FpImageDevice *self = FP_IMAGE_DEVICE (user_data);
|
||||
FpDevice *device = FP_DEVICE (self);
|
||||
FpImageDevicePrivate *priv;
|
||||
FpiDeviceAction action;
|
||||
|
||||
/* Note: We rely on the device to not disappear during an operation. */
|
||||
|
||||
if (!fp_image_detect_minutiae_finish (image, res, &error))
|
||||
{
|
||||
/* Cancel operation . */
|
||||
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
||||
{
|
||||
fpi_device_action_error (device, g_steal_pointer (&error));
|
||||
fpi_image_device_deactivate (self);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Replace error with a retry condition. */
|
||||
g_warning ("Failed to detect minutiae: %s", error->message);
|
||||
g_clear_pointer (&error, g_error_free);
|
||||
|
||||
error = fpi_device_retry_new_msg (FP_DEVICE_RETRY_GENERAL, "Minutiae detection failed, please retry");
|
||||
}
|
||||
|
||||
priv = fp_image_device_get_instance_private (FP_IMAGE_DEVICE (device));
|
||||
action = fpi_device_get_current_action (device);
|
||||
|
||||
if (action == FPI_DEVICE_ACTION_CAPTURE)
|
||||
{
|
||||
fpi_device_capture_complete (device, g_steal_pointer (&image), error);
|
||||
fpi_image_device_deactivate (self);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!error)
|
||||
{
|
||||
print = fp_print_new (device);
|
||||
fpi_print_set_type (print, FPI_PRINT_NBIS);
|
||||
if (!fpi_print_add_from_image (print, image, &error))
|
||||
{
|
||||
g_clear_object (&print);
|
||||
|
||||
if (error->domain != FP_DEVICE_RETRY)
|
||||
{
|
||||
fpi_device_action_error (device, error);
|
||||
fpi_image_device_deactivate (self);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (action == FPI_DEVICE_ACTION_ENROLL)
|
||||
{
|
||||
FpPrint *enroll_print;
|
||||
fpi_device_get_enroll_data (device, &enroll_print);
|
||||
|
||||
if (print)
|
||||
{
|
||||
fpi_print_add_print (enroll_print, print);
|
||||
priv->enroll_stage += 1;
|
||||
}
|
||||
|
||||
fpi_device_enroll_progress (device, priv->enroll_stage,
|
||||
g_steal_pointer (&print), error);
|
||||
|
||||
/* Start another scan or deactivate. */
|
||||
if (priv->enroll_stage == IMG_ENROLL_STAGES)
|
||||
{
|
||||
fpi_device_enroll_complete (device, g_object_ref (enroll_print), NULL);
|
||||
fpi_image_device_deactivate (self);
|
||||
}
|
||||
else
|
||||
{
|
||||
fp_image_device_enroll_maybe_await_finger_on (FP_IMAGE_DEVICE (device));
|
||||
}
|
||||
}
|
||||
else if (action == FPI_DEVICE_ACTION_VERIFY)
|
||||
{
|
||||
FpPrint *template;
|
||||
FpiMatchResult result;
|
||||
|
||||
fpi_device_get_verify_data (device, &template);
|
||||
if (print)
|
||||
result = fpi_print_bz3_match (template, print, priv->bz3_threshold, &error);
|
||||
else
|
||||
result = FPI_MATCH_ERROR;
|
||||
|
||||
if (!error || error->domain == FP_DEVICE_RETRY)
|
||||
fpi_device_verify_report (device, result, g_steal_pointer (&print), g_steal_pointer (&error));
|
||||
fpi_device_verify_complete (device, error);
|
||||
fpi_image_device_deactivate (self);
|
||||
}
|
||||
else if (action == FPI_DEVICE_ACTION_IDENTIFY)
|
||||
{
|
||||
gint i;
|
||||
GPtrArray *templates;
|
||||
FpPrint *result = NULL;
|
||||
|
||||
fpi_device_get_identify_data (device, &templates);
|
||||
for (i = 0; !error && i < templates->len; i++)
|
||||
{
|
||||
FpPrint *template = g_ptr_array_index (templates, i);
|
||||
|
||||
if (fpi_print_bz3_match (template, print, priv->bz3_threshold, &error) == FPI_MATCH_SUCCESS)
|
||||
{
|
||||
result = template;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!error || error->domain == FP_DEVICE_RETRY)
|
||||
fpi_device_identify_report (device, result, g_steal_pointer (&print), g_steal_pointer (&error));
|
||||
fpi_device_identify_complete (device, error);
|
||||
fpi_image_device_deactivate (self);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* XXX: This can be hit currently due to a race condition in the enroll code!
|
||||
* In that case we scan a further image even though the minutiae for the previous
|
||||
* one have not yet been detected.
|
||||
* We need to keep track on the pending minutiae detection and the fact that
|
||||
* it will finish eventually (or we may need to retry on error and activate the
|
||||
* device again). */
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************/
|
||||
/* Private API */
|
||||
|
||||
/**
|
||||
* fpi_image_device_set_bz3_threshold:
|
||||
* @self: a #FpImageDevice imaging fingerprint device
|
||||
* @bz3_threshold: BZ3 threshold to use
|
||||
*
|
||||
* Dynamically adjust the bz3 threshold. This is only needed for drivers
|
||||
* that support devices with different properties. It should generally be
|
||||
* called from the probe callback, but is acceptable to call from the open
|
||||
* callback.
|
||||
*/
|
||||
void
|
||||
fpi_image_device_set_bz3_threshold (FpImageDevice *self,
|
||||
gint bz3_threshold)
|
||||
{
|
||||
FpImageDevicePrivate *priv = fp_image_device_get_instance_private (self);
|
||||
|
||||
g_return_if_fail (FP_IS_IMAGE_DEVICE (self));
|
||||
g_return_if_fail (bz3_threshold > 0);
|
||||
|
||||
priv->bz3_threshold = bz3_threshold;
|
||||
}
|
||||
|
||||
/**
|
||||
* fpi_image_device_report_finger_status:
|
||||
* @self: a #FpImageDevice imaging fingerprint device
|
||||
* @present: whether the finger is present on the sensor
|
||||
*
|
||||
* Reports from the driver whether the user's finger is on
|
||||
* the sensor.
|
||||
*/
|
||||
void
|
||||
fpi_image_device_report_finger_status (FpImageDevice *self,
|
||||
gboolean present)
|
||||
{
|
||||
FpDevice *device = FP_DEVICE (self);
|
||||
FpImageDevicePrivate *priv = fp_image_device_get_instance_private (self);
|
||||
FpiDeviceAction action;
|
||||
|
||||
if (priv->state == FPI_IMAGE_DEVICE_STATE_INACTIVE)
|
||||
{
|
||||
/* Do we really want to always ignore such reports? We could
|
||||
* also track the state in case the user had the finger on
|
||||
* the device at initialisation time and the driver reports
|
||||
* this early.
|
||||
*/
|
||||
g_debug ("Ignoring finger presence report as the device is not active!");
|
||||
return;
|
||||
}
|
||||
|
||||
action = fpi_device_get_current_action (device);
|
||||
|
||||
g_assert (action != FPI_DEVICE_ACTION_OPEN);
|
||||
g_assert (action != FPI_DEVICE_ACTION_CLOSE);
|
||||
|
||||
g_debug ("Image device reported finger status: %s", present ? "on" : "off");
|
||||
|
||||
if (present && priv->state == FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON)
|
||||
{
|
||||
fp_image_device_change_state (self, FPI_IMAGE_DEVICE_STATE_CAPTURE);
|
||||
}
|
||||
else if (!present && priv->state == FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_OFF)
|
||||
{
|
||||
/* We need to deactivate or continue to await finger */
|
||||
|
||||
/* There are three possible situations:
|
||||
* 1. We are deactivating the device and the action is still in progress
|
||||
* (minutiae detection).
|
||||
* 2. We are still deactivating the device after an action completed
|
||||
* 3. We were waiting for finger removal to start the new action
|
||||
* Either way, we always end up deactivating except for the enroll case.
|
||||
*
|
||||
* The enroll case is special as AWAIT_FINGER_ON should only happen after
|
||||
* minutiae detection to prevent deactivation (without cancellation)
|
||||
* from the AWAIT_FINGER_ON state.
|
||||
*/
|
||||
if (action != FPI_DEVICE_ACTION_ENROLL)
|
||||
fpi_image_device_deactivate (self);
|
||||
else
|
||||
fp_image_device_enroll_maybe_await_finger_on (self);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* fpi_image_device_image_captured:
|
||||
* @self: a #FpImageDevice imaging fingerprint device
|
||||
* @image: whether the finger is present on the sensor
|
||||
*
|
||||
* Reports an image capture. Only use this function if the image was
|
||||
* captured successfully. If there was an issue where the user should
|
||||
* retry, use fpi_image_device_retry_scan() to report the retry condition.
|
||||
*
|
||||
* In the event of a fatal error for the operation use
|
||||
* fpi_image_device_session_error(). This will abort the entire operation
|
||||
* including e.g. an enroll operation which captures multiple images during
|
||||
* one session.
|
||||
*/
|
||||
void
|
||||
fpi_image_device_image_captured (FpImageDevice *self, FpImage *image)
|
||||
{
|
||||
FpImageDevicePrivate *priv = fp_image_device_get_instance_private (self);
|
||||
FpiDeviceAction action;
|
||||
|
||||
action = fpi_device_get_current_action (FP_DEVICE (self));
|
||||
|
||||
g_return_if_fail (image != NULL);
|
||||
g_return_if_fail (priv->state == FPI_IMAGE_DEVICE_STATE_CAPTURE);
|
||||
g_return_if_fail (action == FPI_DEVICE_ACTION_ENROLL ||
|
||||
action == FPI_DEVICE_ACTION_VERIFY ||
|
||||
action == FPI_DEVICE_ACTION_IDENTIFY ||
|
||||
action == FPI_DEVICE_ACTION_CAPTURE);
|
||||
|
||||
fp_image_device_change_state (self, FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_OFF);
|
||||
|
||||
g_debug ("Image device captured an image");
|
||||
|
||||
/* XXX: We also detect minutiae in capture mode, we solely do this
|
||||
* to normalize the image which will happen as a by-product. */
|
||||
fp_image_detect_minutiae (image,
|
||||
fpi_device_get_cancellable (FP_DEVICE (self)),
|
||||
fpi_image_device_minutiae_detected,
|
||||
self);
|
||||
}
|
||||
|
||||
/**
|
||||
* fpi_image_device_retry_scan:
|
||||
* @self: a #FpImageDevice imaging fingerprint device
|
||||
* @retry: The #FpDeviceRetry error code to report
|
||||
*
|
||||
* Reports a scan failure to the user. This may or may not abort the
|
||||
* current session. It is the equivalent of fpi_image_device_image_captured()
|
||||
* in the case of a retryable error condition (e.g. short swipe).
|
||||
*/
|
||||
void
|
||||
fpi_image_device_retry_scan (FpImageDevice *self, FpDeviceRetry retry)
|
||||
{
|
||||
FpImageDevicePrivate *priv = fp_image_device_get_instance_private (self);
|
||||
FpiDeviceAction action;
|
||||
GError *error;
|
||||
|
||||
action = fpi_device_get_current_action (FP_DEVICE (self));
|
||||
|
||||
/* We might be waiting for a finger at this point, so just accept
|
||||
* all but INACTIVE */
|
||||
g_return_if_fail (priv->state != FPI_IMAGE_DEVICE_STATE_INACTIVE);
|
||||
g_return_if_fail (action == FPI_DEVICE_ACTION_ENROLL ||
|
||||
action == FPI_DEVICE_ACTION_VERIFY ||
|
||||
action == FPI_DEVICE_ACTION_IDENTIFY ||
|
||||
action == FPI_DEVICE_ACTION_CAPTURE);
|
||||
|
||||
error = fpi_device_retry_new (retry);
|
||||
|
||||
if (action == FPI_DEVICE_ACTION_ENROLL)
|
||||
{
|
||||
g_debug ("Reporting retry during enroll");
|
||||
fpi_device_enroll_progress (FP_DEVICE (self), priv->enroll_stage, NULL, error);
|
||||
|
||||
/* Wait for finger removal and re-touch.
|
||||
* TODO: Do we need to check that the finger is already off? */
|
||||
priv->enroll_await_on_pending = TRUE;
|
||||
fp_image_device_change_state (self, FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_OFF);
|
||||
}
|
||||
else if (action == FPI_DEVICE_ACTION_VERIFY)
|
||||
{
|
||||
fpi_device_verify_report (FP_DEVICE (self), FPI_MATCH_ERROR, NULL, error);
|
||||
priv->cancelling = TRUE;
|
||||
fpi_image_device_deactivate (self);
|
||||
priv->cancelling = FALSE;
|
||||
fpi_device_verify_complete (FP_DEVICE (self), NULL);
|
||||
}
|
||||
else if (action == FPI_DEVICE_ACTION_IDENTIFY)
|
||||
{
|
||||
fpi_device_identify_report (FP_DEVICE (self), NULL, NULL, error);
|
||||
priv->cancelling = TRUE;
|
||||
fpi_image_device_deactivate (self);
|
||||
priv->cancelling = FALSE;
|
||||
fpi_device_identify_complete (FP_DEVICE (self), NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We abort the operation and let the surrounding code retry in the
|
||||
* non-enroll case (this is identical to a session error). */
|
||||
g_debug ("Abort current operation due to retry (non-enroll case)");
|
||||
priv->cancelling = TRUE;
|
||||
fpi_image_device_deactivate (self);
|
||||
priv->cancelling = FALSE;
|
||||
fpi_device_action_error (FP_DEVICE (self), error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* fpi_image_device_session_error:
|
||||
* @self: a #FpImageDevice imaging fingerprint device
|
||||
* @error: The #GError to report
|
||||
*
|
||||
* Report an error while interacting with the device. This effectively
|
||||
* aborts the current ongoing action. Note that doing so will result in
|
||||
* the deactivation handler to be called and this function must not be
|
||||
* used to report an error during deactivation.
|
||||
*/
|
||||
void
|
||||
fpi_image_device_session_error (FpImageDevice *self, GError *error)
|
||||
{
|
||||
FpImageDevicePrivate *priv = fp_image_device_get_instance_private (self);
|
||||
|
||||
g_return_if_fail (self);
|
||||
|
||||
if (!error)
|
||||
{
|
||||
g_warning ("Driver did not provide an error, generating a generic one");
|
||||
error = g_error_new (FP_DEVICE_ERROR, FP_DEVICE_ERROR_GENERAL, "Driver reported session error without an error");
|
||||
}
|
||||
|
||||
if (!priv->active)
|
||||
{
|
||||
FpiDeviceAction action = fpi_device_get_current_action (FP_DEVICE (self));
|
||||
g_warning ("Driver reported session error, but device is inactive.");
|
||||
|
||||
if (action != FPI_DEVICE_ACTION_NONE)
|
||||
{
|
||||
g_warning ("Translating to activation failure!");
|
||||
fpi_image_device_activate_complete (self, error);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED) &&
|
||||
fpi_device_action_is_cancelled (FP_DEVICE (self)))
|
||||
{
|
||||
/* Ignore cancellation errors here, as we will explicitly deactivate
|
||||
* anyway (or, may already have done so at this point).
|
||||
*/
|
||||
g_debug ("Driver reported a cancellation error, this is expected but not required. Ignoring.");
|
||||
g_clear_error (&error);
|
||||
return;
|
||||
}
|
||||
else if (priv->state == FPI_IMAGE_DEVICE_STATE_INACTIVE)
|
||||
{
|
||||
g_warning ("Driver reported session error while deactivating already, ignoring. This indicates a driver bug.");
|
||||
g_clear_error (&error);
|
||||
return;
|
||||
}
|
||||
|
||||
if (error->domain == FP_DEVICE_RETRY)
|
||||
g_warning ("Driver should report retries using fpi_image_device_retry_scan!");
|
||||
|
||||
priv->cancelling = TRUE;
|
||||
fpi_image_device_deactivate (self);
|
||||
priv->cancelling = FALSE;
|
||||
fpi_device_action_error (FP_DEVICE (self), error);
|
||||
}
|
||||
|
||||
/**
|
||||
* fpi_image_device_activate_complete:
|
||||
* @self: a #FpImageDevice imaging fingerprint device
|
||||
* @error: A #GError or %NULL on success
|
||||
*
|
||||
* Reports completion of device activation.
|
||||
*/
|
||||
void
|
||||
fpi_image_device_activate_complete (FpImageDevice *self, GError *error)
|
||||
{
|
||||
FpImageDevicePrivate *priv = fp_image_device_get_instance_private (self);
|
||||
FpiDeviceAction action;
|
||||
|
||||
action = fpi_device_get_current_action (FP_DEVICE (self));
|
||||
|
||||
g_return_if_fail (priv->active == FALSE);
|
||||
g_return_if_fail (action == FPI_DEVICE_ACTION_ENROLL ||
|
||||
action == FPI_DEVICE_ACTION_VERIFY ||
|
||||
action == FPI_DEVICE_ACTION_IDENTIFY ||
|
||||
action == FPI_DEVICE_ACTION_CAPTURE);
|
||||
|
||||
if (error)
|
||||
{
|
||||
g_debug ("Image device activation failed");
|
||||
fpi_device_action_error (FP_DEVICE (self), error);
|
||||
return;
|
||||
}
|
||||
|
||||
g_debug ("Image device activation completed");
|
||||
|
||||
priv->active = TRUE;
|
||||
|
||||
/* We always want to capture at this point, move to AWAIT_FINGER
|
||||
* state. */
|
||||
fp_image_device_change_state (self, FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON);
|
||||
}
|
||||
|
||||
/**
|
||||
* fpi_image_device_deactivate_complete:
|
||||
* @self: a #FpImageDevice imaging fingerprint device
|
||||
* @error: A #GError or %NULL on success
|
||||
*
|
||||
* Reports completion of device deactivation.
|
||||
*/
|
||||
void
|
||||
fpi_image_device_deactivate_complete (FpImageDevice *self, GError *error)
|
||||
{
|
||||
FpImageDevicePrivate *priv = fp_image_device_get_instance_private (self);
|
||||
FpImageDeviceClass *cls = FP_IMAGE_DEVICE_GET_CLASS (self);
|
||||
FpiDeviceAction action;
|
||||
|
||||
g_return_if_fail (priv->active == TRUE);
|
||||
g_return_if_fail (priv->state == FPI_IMAGE_DEVICE_STATE_INACTIVE);
|
||||
|
||||
g_debug ("Image device deactivation completed");
|
||||
|
||||
priv->active = FALSE;
|
||||
|
||||
/* Deactivation completed. As we deactivate in the background
|
||||
* there may already be a new task pending. Check whether we
|
||||
* need to do anything. */
|
||||
action = fpi_device_get_current_action (FP_DEVICE (self));
|
||||
|
||||
/* Special case, if we should be closing, but didn't due to a running
|
||||
* deactivation, then do so now. */
|
||||
if (action == FPI_DEVICE_ACTION_CLOSE)
|
||||
{
|
||||
cls->img_close (self);
|
||||
return;
|
||||
}
|
||||
|
||||
/* We might be waiting to be able to activate again. */
|
||||
if (priv->pending_activation_timeout_id)
|
||||
{
|
||||
g_clear_handle_id (&priv->pending_activation_timeout_id, g_source_remove);
|
||||
priv->pending_activation_timeout_id =
|
||||
g_idle_add ((GSourceFunc) fpi_image_device_activate, self);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* fpi_image_device_open_complete:
|
||||
* @self: a #FpImageDevice imaging fingerprint device
|
||||
* @error: A #GError or %NULL on success
|
||||
*
|
||||
* Reports completion of open operation.
|
||||
*/
|
||||
void
|
||||
fpi_image_device_open_complete (FpImageDevice *self, GError *error)
|
||||
{
|
||||
FpImageDevicePrivate *priv = fp_image_device_get_instance_private (self);
|
||||
FpiDeviceAction action;
|
||||
|
||||
action = fpi_device_get_current_action (FP_DEVICE (self));
|
||||
|
||||
g_return_if_fail (priv->active == FALSE);
|
||||
g_return_if_fail (action == FPI_DEVICE_ACTION_OPEN);
|
||||
|
||||
g_debug ("Image device open completed");
|
||||
|
||||
priv->state = FPI_IMAGE_DEVICE_STATE_INACTIVE;
|
||||
g_object_notify (G_OBJECT (self), "fpi-image-device-state");
|
||||
|
||||
fpi_device_open_complete (FP_DEVICE (self), error);
|
||||
}
|
||||
|
||||
/**
|
||||
* fpi_image_device_close_complete:
|
||||
* @self: a #FpImageDevice imaging fingerprint device
|
||||
* @error: A #GError or %NULL on success
|
||||
*
|
||||
* Reports completion of close operation.
|
||||
*/
|
||||
void
|
||||
fpi_image_device_close_complete (FpImageDevice *self, GError *error)
|
||||
{
|
||||
FpImageDevicePrivate *priv = fp_image_device_get_instance_private (self);
|
||||
FpiDeviceAction action;
|
||||
|
||||
action = fpi_device_get_current_action (FP_DEVICE (self));
|
||||
|
||||
g_debug ("Image device close completed");
|
||||
|
||||
g_return_if_fail (priv->active == FALSE);
|
||||
g_return_if_fail (action == FPI_DEVICE_ACTION_CLOSE);
|
||||
|
||||
priv->state = FPI_IMAGE_DEVICE_STATE_INACTIVE;
|
||||
g_object_notify (G_OBJECT (self), "fpi-image-device-state");
|
||||
|
||||
fpi_device_close_complete (FP_DEVICE (self), error);
|
||||
}
|
||||
@@ -23,11 +23,11 @@
|
||||
#include "fp-image-device.h"
|
||||
|
||||
/**
|
||||
* FpImageDeviceState:
|
||||
* @FP_IMAGE_DEVICE_STATE_INACTIVE: inactive
|
||||
* @FP_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON: waiting for the finger to be pressed or swiped
|
||||
* @FP_IMAGE_DEVICE_STATE_CAPTURE: capturing an image
|
||||
* @FP_IMAGE_DEVICE_STATE_AWAIT_FINGER_OFF: waiting for the finger to be removed
|
||||
* FpiImageDeviceState:
|
||||
* @FPI_IMAGE_DEVICE_STATE_INACTIVE: inactive
|
||||
* @FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON: waiting for the finger to be pressed or swiped
|
||||
* @FPI_IMAGE_DEVICE_STATE_CAPTURE: capturing an image
|
||||
* @FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_OFF: waiting for the finger to be removed
|
||||
*
|
||||
* The state of an imaging device while doing a capture. The state is
|
||||
* passed through to the driver using the ::activate() or ::change_state() vfuncs.
|
||||
@@ -37,11 +37,11 @@
|
||||
* unconditionally if the device supports raw capturing.
|
||||
*/
|
||||
typedef enum {
|
||||
FP_IMAGE_DEVICE_STATE_INACTIVE,
|
||||
FP_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON,
|
||||
FP_IMAGE_DEVICE_STATE_CAPTURE,
|
||||
FP_IMAGE_DEVICE_STATE_AWAIT_FINGER_OFF,
|
||||
} FpImageDeviceState;
|
||||
FPI_IMAGE_DEVICE_STATE_INACTIVE,
|
||||
FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON,
|
||||
FPI_IMAGE_DEVICE_STATE_CAPTURE,
|
||||
FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_OFF,
|
||||
} FpiImageDeviceState;
|
||||
|
||||
/**
|
||||
* FpImageDeviceClass:
|
||||
@@ -91,7 +91,7 @@ struct _FpImageDeviceClass
|
||||
void (*img_close) (FpImageDevice *dev);
|
||||
void (*activate) (FpImageDevice *dev);
|
||||
void (*change_state) (FpImageDevice *dev,
|
||||
FpImageDeviceState state);
|
||||
FpiImageDeviceState state);
|
||||
void (*deactivate) (FpImageDevice *dev);
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,149 @@
|
||||
/*
|
||||
* FPrint Image - Private APIs
|
||||
* Copyright (C) 2007 Daniel Drake <dsd@gentoo.org>
|
||||
* Copyright (C) 2019 Benjamin Berg <bberg@redhat.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 "image"
|
||||
|
||||
#include "fpi-image.h"
|
||||
#include "fpi-log.h"
|
||||
|
||||
#include <nbis.h>
|
||||
|
||||
#if HAVE_PIXMAN
|
||||
#include <pixman.h>
|
||||
#endif
|
||||
|
||||
/**
|
||||
* SECTION: fpi-image
|
||||
* @title: Internal FpImage
|
||||
* @short_description: Internal image handling routines
|
||||
*
|
||||
* Internal image handling routines. See #FpImage for public routines.
|
||||
*/
|
||||
|
||||
/**
|
||||
* fpi_std_sq_dev:
|
||||
* @buf: buffer (usually bitmap, one byte per pixel)
|
||||
* @size: size of @buffer
|
||||
*
|
||||
* Calculates the squared standard deviation of the individual
|
||||
* pixels in the buffer, as per the following formula:
|
||||
* |[<!-- -->
|
||||
* mean = sum (buf[0..size]) / size
|
||||
* sq_dev = sum ((buf[0.size] - mean) ^ 2)
|
||||
* ]|
|
||||
* This function is usually used to determine whether image
|
||||
* is empty.
|
||||
*
|
||||
* Returns: the squared standard deviation for @buffer
|
||||
*/
|
||||
gint
|
||||
fpi_std_sq_dev (const guint8 *buf,
|
||||
gint size)
|
||||
{
|
||||
guint64 res = 0, mean = 0;
|
||||
gint i;
|
||||
|
||||
for (i = 0; i < size; i++)
|
||||
mean += buf[i];
|
||||
|
||||
mean /= size;
|
||||
|
||||
for (i = 0; i < size; i++)
|
||||
{
|
||||
int dev = (int) buf[i] - mean;
|
||||
res += dev * dev;
|
||||
}
|
||||
|
||||
return res / size;
|
||||
}
|
||||
|
||||
/**
|
||||
* fpi_mean_sq_diff_norm:
|
||||
* @buf1: buffer (usually bitmap, one byte per pixel)
|
||||
* @buf2: buffer (usually bitmap, one byte per pixel)
|
||||
* @size: buffer size of smallest buffer
|
||||
*
|
||||
* This function calculates the normalized mean square difference of
|
||||
* two buffers, usually two lines, as per the following formula:
|
||||
* |[<!-- -->
|
||||
* sq_diff = sum ((buf1[0..size] - buf2[0..size]) ^ 2) / size
|
||||
* ]|
|
||||
*
|
||||
* This functions is usually used to get numerical difference
|
||||
* between two images.
|
||||
*
|
||||
* Returns: the normalized mean squared difference between @buf1 and @buf2
|
||||
*/
|
||||
gint
|
||||
fpi_mean_sq_diff_norm (const guint8 *buf1,
|
||||
const guint8 *buf2,
|
||||
gint size)
|
||||
{
|
||||
int res = 0, i;
|
||||
|
||||
for (i = 0; i < size; i++)
|
||||
{
|
||||
int dev = (int) buf1[i] - (int) buf2[i];
|
||||
res += dev * dev;
|
||||
}
|
||||
|
||||
return res / size;
|
||||
}
|
||||
|
||||
#if HAVE_PIXMAN
|
||||
FpImage *
|
||||
fpi_image_resize (FpImage *orig_img,
|
||||
guint w_factor,
|
||||
guint h_factor)
|
||||
{
|
||||
int new_width = orig_img->width * w_factor;
|
||||
int new_height = orig_img->height * h_factor;
|
||||
pixman_image_t *orig, *resized;
|
||||
pixman_transform_t transform;
|
||||
FpImage *newimg;
|
||||
|
||||
orig = pixman_image_create_bits (PIXMAN_a8, orig_img->width, orig_img->height, (uint32_t *) orig_img->data, orig_img->width);
|
||||
resized = pixman_image_create_bits (PIXMAN_a8, new_width, new_height, NULL, new_width);
|
||||
|
||||
pixman_transform_init_identity (&transform);
|
||||
pixman_transform_scale (NULL, &transform, pixman_int_to_fixed (w_factor), pixman_int_to_fixed (h_factor));
|
||||
pixman_image_set_transform (orig, &transform);
|
||||
pixman_image_set_filter (orig, PIXMAN_FILTER_BILINEAR, NULL, 0);
|
||||
pixman_image_composite32 (PIXMAN_OP_SRC,
|
||||
orig, /* src */
|
||||
NULL, /* mask */
|
||||
resized, /* dst */
|
||||
0, 0, /* src x y */
|
||||
0, 0, /* mask x y */
|
||||
0, 0, /* dst x y */
|
||||
new_width, new_height /* width height */
|
||||
);
|
||||
|
||||
newimg = fp_image_new (new_width, new_height);
|
||||
newimg->flags = orig_img->flags;
|
||||
|
||||
memcpy (newimg->data, pixman_image_get_data (resized), new_width * new_height);
|
||||
|
||||
pixman_image_unref (orig);
|
||||
pixman_image_unref (resized);
|
||||
|
||||
return newimg;
|
||||
}
|
||||
#endif
|
||||
@@ -37,6 +37,7 @@ typedef enum {
|
||||
FPI_IMAGE_V_FLIPPED = 1 << 0,
|
||||
FPI_IMAGE_H_FLIPPED = 1 << 1,
|
||||
FPI_IMAGE_COLORS_INVERTED = 1 << 2,
|
||||
FPI_IMAGE_PARTIAL = 1 << 3,
|
||||
} FpiImageFlags;
|
||||
|
||||
/**
|
||||
|
||||
+3
-6
@@ -17,8 +17,7 @@
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef __FPI_LOG_H__
|
||||
#define __FPI_LOG_H__
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* SECTION:fpi-log
|
||||
@@ -68,11 +67,11 @@
|
||||
/**
|
||||
* fp_err:
|
||||
*
|
||||
* Same as g_warning(). In the future, this might be changed to a
|
||||
* Same as g_critical(). In the future, this might be changed to a
|
||||
* g_assert() instead, so bear this in mind when adding those calls
|
||||
* to your driver.
|
||||
*/
|
||||
#define fp_err g_warning
|
||||
#define fp_err g_critical
|
||||
|
||||
/**
|
||||
* BUG_ON:
|
||||
@@ -94,5 +93,3 @@
|
||||
* Same as BUG_ON() but is always true.
|
||||
*/
|
||||
#define BUG() BUG_ON (1)
|
||||
|
||||
#endif
|
||||
|
||||
@@ -17,13 +17,7 @@
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef __FPRINT_INTERNAL_H__
|
||||
#define __FPRINT_INTERNAL_H__
|
||||
|
||||
#include "fpi-log.h"
|
||||
#include "nbis-helpers.h"
|
||||
#include "fpi-image.h"
|
||||
#include "fpi-image-device.h"
|
||||
#pragma once
|
||||
|
||||
/* fp_minutia structure definition */
|
||||
struct fp_minutia
|
||||
@@ -49,6 +43,3 @@ struct fp_minutiae
|
||||
int num;
|
||||
struct fp_minutia **list;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,362 @@
|
||||
/*
|
||||
* FPrint Print handling - Private APIs
|
||||
* Copyright (C) 2007 Daniel Drake <dsd@gentoo.org>
|
||||
* Copyright (C) 2019 Benjamin Berg <bberg@redhat.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 "print"
|
||||
#include "fpi-log.h"
|
||||
|
||||
#include "fp-print-private.h"
|
||||
#include "fpi-device.h"
|
||||
#include "fpi-compat.h"
|
||||
|
||||
/**
|
||||
* SECTION: fpi-print
|
||||
* @title: Internal FpPrint
|
||||
* @short_description: Internal fingerprint handling routines
|
||||
*
|
||||
* Interaction with prints and their storage. See also the public
|
||||
* #FpPrint routines.
|
||||
*/
|
||||
|
||||
/**
|
||||
* fpi_print_add_print:
|
||||
* @print: A #FpPrint
|
||||
* @add: Print to append to @print
|
||||
*
|
||||
* Appends the single #FPI_PRINT_NBIS print from @add to the collection of
|
||||
* prints in @print. Both print objects need to be of type #FPI_PRINT_NBIS
|
||||
* for this to work.
|
||||
*/
|
||||
void
|
||||
fpi_print_add_print (FpPrint *print, FpPrint *add)
|
||||
{
|
||||
g_return_if_fail (print->type == FPI_PRINT_NBIS);
|
||||
g_return_if_fail (add->type == FPI_PRINT_NBIS);
|
||||
|
||||
g_assert (add->prints->len == 1);
|
||||
g_ptr_array_add (print->prints, g_memdup (add->prints->pdata[0], sizeof (struct xyt_struct)));
|
||||
}
|
||||
|
||||
/**
|
||||
* fpi_print_set_type:
|
||||
* @print: A #FpPrint
|
||||
* @type: The newly type of the print data
|
||||
*
|
||||
* This function can only be called exactly once. Drivers should
|
||||
* call it after creating a new print, or to initialize the template
|
||||
* print passed during enrollment.
|
||||
*/
|
||||
void
|
||||
fpi_print_set_type (FpPrint *print,
|
||||
FpiPrintType type)
|
||||
{
|
||||
g_return_if_fail (FP_IS_PRINT (print));
|
||||
/* We only allow setting this once! */
|
||||
g_return_if_fail (print->type == FPI_PRINT_UNDEFINED);
|
||||
|
||||
print->type = type;
|
||||
if (print->type == FPI_PRINT_NBIS)
|
||||
{
|
||||
g_assert_null (print->prints);
|
||||
print->prints = g_ptr_array_new_with_free_func (g_free);
|
||||
}
|
||||
g_object_notify (G_OBJECT (print), "fpi-type");
|
||||
}
|
||||
|
||||
/**
|
||||
* fpi_print_set_device_stored:
|
||||
* @print: A #FpPrint
|
||||
* @device_stored: Whether the print is stored on the device or not
|
||||
*
|
||||
* Drivers must set this to %TRUE for any print that is really a handle
|
||||
* for data that is stored on the device itself.
|
||||
*/
|
||||
void
|
||||
fpi_print_set_device_stored (FpPrint *print,
|
||||
gboolean device_stored)
|
||||
{
|
||||
g_return_if_fail (FP_IS_PRINT (print));
|
||||
|
||||
print->device_stored = device_stored;
|
||||
g_object_notify (G_OBJECT (print), "device-stored");
|
||||
}
|
||||
|
||||
/* XXX: This is the old version, but wouldn't it be smarter to instead
|
||||
* use the highest quality mintutiae? Possibly just using bz_prune from
|
||||
* upstream? */
|
||||
static void
|
||||
minutiae_to_xyt (struct fp_minutiae *minutiae,
|
||||
int bwidth,
|
||||
int bheight,
|
||||
struct xyt_struct *xyt)
|
||||
{
|
||||
int i;
|
||||
struct fp_minutia *minutia;
|
||||
struct minutiae_struct c[MAX_FILE_MINUTIAE];
|
||||
|
||||
/* struct xyt_struct uses arrays of MAX_BOZORTH_MINUTIAE (200) */
|
||||
int nmin = min (minutiae->num, MAX_BOZORTH_MINUTIAE);
|
||||
|
||||
for (i = 0; i < nmin; i++)
|
||||
{
|
||||
minutia = minutiae->list[i];
|
||||
|
||||
lfs2nist_minutia_XYT (&c[i].col[0], &c[i].col[1], &c[i].col[2],
|
||||
minutia, bwidth, bheight);
|
||||
c[i].col[3] = sround (minutia->reliability * 100.0);
|
||||
|
||||
if (c[i].col[2] > 180)
|
||||
c[i].col[2] -= 360;
|
||||
}
|
||||
|
||||
qsort ((void *) &c, (size_t) nmin, sizeof (struct minutiae_struct),
|
||||
sort_x_y);
|
||||
|
||||
for (i = 0; i < nmin; i++)
|
||||
{
|
||||
xyt->xcol[i] = c[i].col[0];
|
||||
xyt->ycol[i] = c[i].col[1];
|
||||
xyt->thetacol[i] = c[i].col[2];
|
||||
}
|
||||
xyt->nrows = nmin;
|
||||
}
|
||||
|
||||
/**
|
||||
* fpi_print_add_from_image:
|
||||
* @print: A #FpPrint
|
||||
* @image: A #FpImage
|
||||
* @error: Return location for error
|
||||
*
|
||||
* Extracts the minutiae from the given image and adds it to @print of
|
||||
* type #FPI_PRINT_NBIS.
|
||||
*
|
||||
* The @image will be kept so that API users can get retrieve it e.g.
|
||||
* for debugging purposes.
|
||||
*
|
||||
* Returns: %TRUE on success
|
||||
*/
|
||||
gboolean
|
||||
fpi_print_add_from_image (FpPrint *print,
|
||||
FpImage *image,
|
||||
GError **error)
|
||||
{
|
||||
GPtrArray *minutiae;
|
||||
struct fp_minutiae _minutiae;
|
||||
struct xyt_struct *xyt;
|
||||
|
||||
if (print->type != FPI_PRINT_NBIS || !image)
|
||||
{
|
||||
g_set_error (error,
|
||||
G_IO_ERROR,
|
||||
G_IO_ERROR_INVALID_DATA,
|
||||
"Cannot add print data from image!");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
minutiae = fp_image_get_minutiae (image);
|
||||
if (!minutiae || minutiae->len == 0)
|
||||
{
|
||||
g_set_error (error,
|
||||
G_IO_ERROR,
|
||||
G_IO_ERROR_INVALID_DATA,
|
||||
"No minutiae found in image or not yet detected!");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
_minutiae.num = minutiae->len;
|
||||
_minutiae.list = (struct fp_minutia **) minutiae->pdata;
|
||||
_minutiae.alloc = minutiae->len;
|
||||
|
||||
xyt = g_new0 (struct xyt_struct, 1);
|
||||
minutiae_to_xyt (&_minutiae, image->width, image->height, xyt);
|
||||
g_ptr_array_add (print->prints, xyt);
|
||||
|
||||
g_clear_object (&print->image);
|
||||
print->image = g_object_ref (image);
|
||||
g_object_notify (G_OBJECT (print), "image");
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* fpi_print_bz3_match:
|
||||
* @template: A #FpPrint containing one or more prints
|
||||
* @print: A newly scanned #FpPrint to test
|
||||
* @bz3_threshold: The BZ3 match threshold
|
||||
* @error: Return location for error
|
||||
*
|
||||
* Match the newly scanned @print (containing exactly one print) against the
|
||||
* prints contained in @template which will have been stored during enrollment.
|
||||
*
|
||||
* Both @template and @print need to be of type #FPI_PRINT_NBIS for this to
|
||||
* work.
|
||||
*
|
||||
* Returns: Whether the prints match, @error will be set if #FPI_MATCH_ERROR is returned
|
||||
*/
|
||||
FpiMatchResult
|
||||
fpi_print_bz3_match (FpPrint *template, FpPrint *print, gint bz3_threshold, GError **error)
|
||||
{
|
||||
struct xyt_struct *pstruct;
|
||||
gint probe_len;
|
||||
gint i;
|
||||
|
||||
/* XXX: Use a different error type? */
|
||||
if (template->type != FPI_PRINT_NBIS || print->type != FPI_PRINT_NBIS)
|
||||
{
|
||||
*error = fpi_device_error_new_msg (FP_DEVICE_ERROR_NOT_SUPPORTED,
|
||||
"It is only possible to match NBIS type print data");
|
||||
return FPI_MATCH_ERROR;
|
||||
}
|
||||
|
||||
if (print->prints->len != 1)
|
||||
{
|
||||
*error = fpi_device_error_new_msg (FP_DEVICE_ERROR_GENERAL,
|
||||
"New print contains more than one print!");
|
||||
return FPI_MATCH_ERROR;
|
||||
}
|
||||
|
||||
pstruct = g_ptr_array_index (print->prints, 0);
|
||||
probe_len = bozorth_probe_init (pstruct);
|
||||
|
||||
for (i = 0; i < template->prints->len; i++)
|
||||
{
|
||||
struct xyt_struct *gstruct;
|
||||
gint score;
|
||||
gstruct = g_ptr_array_index (template->prints, i);
|
||||
score = bozorth_to_gallery (probe_len, pstruct, gstruct);
|
||||
fp_dbg ("score %d", score);
|
||||
|
||||
if (score >= bz3_threshold)
|
||||
return FPI_MATCH_SUCCESS;
|
||||
}
|
||||
|
||||
return FPI_MATCH_FAIL;
|
||||
}
|
||||
|
||||
/**
|
||||
* fpi_print_generate_user_id:
|
||||
* @print: #FpPrint to generate the ID for
|
||||
*
|
||||
* Generates a string identifier for the represented print. This identifier
|
||||
* encodes some metadata about the print. It also includes a random string
|
||||
* and may be assumed to be unique.
|
||||
*
|
||||
* This is useful if devices are able to store a string identifier, but more
|
||||
* storing more metadata may be desirable. In effect, this means the driver
|
||||
* can provide somewhat more meaningful data to fp_device_list_prints().
|
||||
*
|
||||
* The generated ID may be truncated after 23 characters. However, more space
|
||||
* is required to include the username, and it is recommended to store at
|
||||
* at least 31 bytes.
|
||||
*
|
||||
* The generated format may change in the future. It is versioned though and
|
||||
* decoding should remain functional.
|
||||
*
|
||||
* Returns: A unique string of 23 + strlen(username) characters
|
||||
*/
|
||||
gchar *
|
||||
fpi_print_generate_user_id (FpPrint *print)
|
||||
{
|
||||
const gchar *username = NULL;
|
||||
gchar *user_id = NULL;
|
||||
const GDate *date;
|
||||
gint y = 0, m = 0, d = 0;
|
||||
gint32 rand_id = 0;
|
||||
|
||||
g_assert (print);
|
||||
date = fp_print_get_enroll_date (print);
|
||||
if (date && g_date_valid (date))
|
||||
{
|
||||
y = g_date_get_year (date);
|
||||
m = g_date_get_month (date);
|
||||
d = g_date_get_day (date);
|
||||
}
|
||||
|
||||
username = fp_print_get_username (print);
|
||||
if (!username)
|
||||
username = "nobody";
|
||||
|
||||
if (g_strcmp0 (g_getenv ("FP_DEVICE_EMULATION"), "1") == 0)
|
||||
rand_id = 0;
|
||||
else
|
||||
rand_id = g_random_int ();
|
||||
|
||||
user_id = g_strdup_printf ("FP1-%04d%02d%02d-%X-%08X-%s",
|
||||
y, m, d,
|
||||
fp_print_get_finger (print),
|
||||
rand_id,
|
||||
username);
|
||||
|
||||
return user_id;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* fpi_print_fill_from_user_id:
|
||||
* @print: #FpPrint to fill metadata into
|
||||
* @user_id: An ID that was likely encoded using fpi_print_generate_user_id()
|
||||
*
|
||||
* This is the reverse operation of fpi_print_generate_user_id(), allowing
|
||||
* the driver to encode some print metadata in a string.
|
||||
*
|
||||
* Returns: Whether a valid ID was found
|
||||
*/
|
||||
gboolean
|
||||
fpi_print_fill_from_user_id (FpPrint *print, const char *user_id)
|
||||
{
|
||||
g_return_val_if_fail (user_id, FALSE);
|
||||
|
||||
/* The format has 24 bytes at the start and some dashes in the right places */
|
||||
if (g_str_has_prefix (user_id, "FP1-") && strlen (user_id) >= 24 &&
|
||||
user_id[12] == '-' && user_id[14] == '-' && user_id[23] == '-')
|
||||
{
|
||||
g_autofree gchar *copy = g_strdup (user_id);
|
||||
g_autoptr(GDate) date = NULL;
|
||||
gint32 date_ymd;
|
||||
gint32 finger;
|
||||
gchar *username;
|
||||
/* Try to parse information from the string. */
|
||||
|
||||
copy[12] = '\0';
|
||||
date_ymd = g_ascii_strtod (copy + 4, NULL);
|
||||
if (date_ymd > 0)
|
||||
date = g_date_new_dmy (date_ymd % 100,
|
||||
(date_ymd / 100) % 100,
|
||||
date_ymd / 10000);
|
||||
else
|
||||
date = g_date_new ();
|
||||
|
||||
fp_print_set_enroll_date (print, date);
|
||||
|
||||
copy[14] = '\0';
|
||||
finger = g_ascii_strtoll (copy + 13, NULL, 16);
|
||||
fp_print_set_finger (print, finger);
|
||||
|
||||
/* We ignore the next chunk, it is just random data.
|
||||
* Then comes the username; nobody is the default if the metadata
|
||||
* is unknown */
|
||||
username = copy + 24;
|
||||
if (strlen (username) > 0 && g_strcmp0 (username, "nobody") != 0)
|
||||
fp_print_set_username (print, username);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
+18
-13
@@ -7,34 +7,34 @@
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/**
|
||||
* FpPrintType:
|
||||
* @FP_PRINT_UNDEFINED: Undefined type, this happens prior to enrollment
|
||||
* @FP_PRINT_RAW: A raw print where the data is directly compared
|
||||
* @FP_PRINT_NBIS: NBIS minutiae comparison
|
||||
* FpiPrintType:
|
||||
* @FPI_PRINT_UNDEFINED: Undefined type, this happens prior to enrollment
|
||||
* @FPI_PRINT_RAW: A raw print where the data is directly compared
|
||||
* @FPI_PRINT_NBIS: NBIS minutiae comparison
|
||||
*/
|
||||
typedef enum {
|
||||
FP_PRINT_UNDEFINED = 0,
|
||||
FP_PRINT_RAW,
|
||||
FP_PRINT_NBIS,
|
||||
} FpPrintType;
|
||||
FPI_PRINT_UNDEFINED = 0,
|
||||
FPI_PRINT_RAW,
|
||||
FPI_PRINT_NBIS,
|
||||
} FpiPrintType;
|
||||
|
||||
/**
|
||||
* FpiMatchResult:
|
||||
* @FPI_MATCH_ERROR: An error occured during matching
|
||||
* @FPI_MATCH_SUCCESS: The prints matched
|
||||
* @FPI_MATCH_ERROR: An error occurred during matching
|
||||
* @FPI_MATCH_FAIL: The prints did not match
|
||||
* @FPI_MATCH_SUCCESS: The prints matched
|
||||
*/
|
||||
typedef enum {
|
||||
FPI_MATCH_ERROR = 0,
|
||||
FPI_MATCH_SUCCESS,
|
||||
FPI_MATCH_ERROR = -1, /* -1 for g_task_propagate_int */
|
||||
FPI_MATCH_FAIL,
|
||||
FPI_MATCH_SUCCESS,
|
||||
} FpiMatchResult;
|
||||
|
||||
void fpi_print_add_print (FpPrint *print,
|
||||
FpPrint *add);
|
||||
|
||||
void fpi_print_set_type (FpPrint *print,
|
||||
FpPrintType type);
|
||||
FpiPrintType type);
|
||||
void fpi_print_set_device_stored (FpPrint *print,
|
||||
gboolean device_stored);
|
||||
|
||||
@@ -47,4 +47,9 @@ FpiMatchResult fpi_print_bz3_match (FpPrint * template,
|
||||
gint bz3_threshold,
|
||||
GError **error);
|
||||
|
||||
/* Helpers to encode metadata into user ID strings. */
|
||||
gchar * fpi_print_generate_user_id (FpPrint *print);
|
||||
gboolean fpi_print_fill_from_user_id (FpPrint *print,
|
||||
const char *user_id);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
+329
-38
@@ -2,6 +2,7 @@
|
||||
* Functions to assist with asynchronous driver <---> library communications
|
||||
* Copyright (C) 2007-2008 Daniel Drake <dsd@gentoo.org>
|
||||
* Copyright (C) 2019 Benjamin Berg <bberg@redhat.com>
|
||||
* Copyright (C) 2019 Marco Trevisan <marco.trevisan@canonical.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
@@ -50,6 +51,7 @@
|
||||
*
|
||||
* To start a ssm, you pass in a completion callback function to fpi_ssm_start()
|
||||
* which gets called when the ssm completes (both on error and on failure).
|
||||
* Starting a ssm also takes ownership of it.
|
||||
*
|
||||
* To iterate to the next state, call fpi_ssm_next_state(). It is legal to
|
||||
* attempt to iterate beyond the final state - this is equivalent to marking
|
||||
@@ -57,6 +59,7 @@
|
||||
*
|
||||
* To mark successful completion of a SSM, either iterate beyond the final
|
||||
* state or call fpi_ssm_mark_completed() from any state.
|
||||
* This will also invalidate the machine, freeing it.
|
||||
*
|
||||
* To mark failed completion of a SSM, call fpi_ssm_mark_failed() from any
|
||||
* state. You must pass a non-zero error code.
|
||||
@@ -78,12 +81,16 @@
|
||||
struct _FpiSsm
|
||||
{
|
||||
FpDevice *dev;
|
||||
const char *name;
|
||||
FpiSsm *parentsm;
|
||||
gpointer ssm_data;
|
||||
GDestroyNotify ssm_data_destroy;
|
||||
int nr_states;
|
||||
int cur_state;
|
||||
gboolean completed;
|
||||
GSource *timeout;
|
||||
GCancellable *cancellable;
|
||||
gulong cancellable_id;
|
||||
GError *error;
|
||||
FpiSsmCompletedCallback callback;
|
||||
FpiSsmHandlerCallback handler;
|
||||
@@ -97,22 +104,40 @@ struct _FpiSsm
|
||||
*
|
||||
* Allocate a new ssm, with @nr_states states. The @handler callback
|
||||
* will be called after each state transition.
|
||||
* This is a macro that calls fpi_ssm_new_full() using the stringified
|
||||
* version of @nr_states, so will work better with named parameters.
|
||||
*
|
||||
* Returns: a new #FpiSsm state machine
|
||||
*/
|
||||
|
||||
/**
|
||||
* fpi_ssm_new_full:
|
||||
* @dev: a #fp_dev fingerprint device
|
||||
* @handler: the callback function
|
||||
* @nr_states: the number of states
|
||||
* @machine_name: the name of the state machine (for debug purposes)
|
||||
*
|
||||
* Allocate a new ssm, with @nr_states states. The @handler callback
|
||||
* will be called after each state transition.
|
||||
*
|
||||
* Returns: a new #FpiSsm state machine
|
||||
*/
|
||||
FpiSsm *
|
||||
fpi_ssm_new (FpDevice *dev,
|
||||
fpi_ssm_new_full (FpDevice *dev,
|
||||
FpiSsmHandlerCallback handler,
|
||||
int nr_states)
|
||||
int nr_states,
|
||||
const char *machine_name)
|
||||
{
|
||||
FpiSsm *machine;
|
||||
|
||||
BUG_ON (nr_states < 1);
|
||||
BUG_ON (handler == NULL);
|
||||
|
||||
machine = g_new0 (FpiSsm, 1);
|
||||
machine->handler = handler;
|
||||
machine->nr_states = nr_states;
|
||||
machine->dev = dev;
|
||||
machine->name = g_strdup (machine_name);
|
||||
machine->completed = TRUE;
|
||||
return machine;
|
||||
}
|
||||
@@ -124,7 +149,6 @@ fpi_ssm_new (FpDevice *dev,
|
||||
* @ssm_data_destroy: (nullable): #GDestroyNotify for @ssm_data
|
||||
*
|
||||
* Sets @machine's data (freeing the existing data, if any).
|
||||
*
|
||||
*/
|
||||
void
|
||||
fpi_ssm_set_data (FpiSsm *machine,
|
||||
@@ -152,6 +176,84 @@ fpi_ssm_get_data (FpiSsm *machine)
|
||||
return machine->ssm_data;
|
||||
}
|
||||
|
||||
static void
|
||||
fpi_ssm_clear_delayed_action (FpiSsm *machine)
|
||||
{
|
||||
if (machine->cancellable_id)
|
||||
{
|
||||
g_cancellable_disconnect (machine->cancellable, machine->cancellable_id);
|
||||
machine->cancellable_id = 0;
|
||||
}
|
||||
|
||||
g_clear_object (&machine->cancellable);
|
||||
g_clear_pointer (&machine->timeout, g_source_destroy);
|
||||
}
|
||||
|
||||
typedef struct _CancelledActionIdleData
|
||||
{
|
||||
gulong cancellable_id;
|
||||
GCancellable *cancellable;
|
||||
} CancelledActionIdleData;
|
||||
|
||||
static gboolean
|
||||
on_delayed_action_cancelled_idle (gpointer user_data)
|
||||
{
|
||||
CancelledActionIdleData *data = user_data;
|
||||
|
||||
g_cancellable_disconnect (data->cancellable, data->cancellable_id);
|
||||
g_object_unref (data->cancellable);
|
||||
g_free (data);
|
||||
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static void
|
||||
on_delayed_action_cancelled (GCancellable *cancellable,
|
||||
FpiSsm *machine)
|
||||
{
|
||||
CancelledActionIdleData *data;
|
||||
|
||||
fp_dbg ("[%s] %s cancelled delayed state change",
|
||||
fp_device_get_driver (machine->dev), machine->name);
|
||||
|
||||
g_clear_pointer (&machine->timeout, g_source_destroy);
|
||||
|
||||
data = g_new0 (CancelledActionIdleData, 1);
|
||||
data->cancellable = g_steal_pointer (&machine->cancellable);
|
||||
data->cancellable_id = machine->cancellable_id;
|
||||
machine->cancellable_id = 0;
|
||||
|
||||
g_idle_add_full (G_PRIORITY_HIGH_IDLE, on_delayed_action_cancelled_idle,
|
||||
data, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
fpi_ssm_set_delayed_action_timeout (FpiSsm *machine,
|
||||
int delay,
|
||||
FpTimeoutFunc callback,
|
||||
GCancellable *cancellable,
|
||||
gpointer user_data,
|
||||
GDestroyNotify destroy_func)
|
||||
{
|
||||
BUG_ON (machine->completed);
|
||||
BUG_ON (machine->timeout != NULL);
|
||||
|
||||
fpi_ssm_clear_delayed_action (machine);
|
||||
|
||||
if (cancellable != NULL)
|
||||
{
|
||||
g_set_object (&machine->cancellable, cancellable);
|
||||
|
||||
machine->cancellable_id =
|
||||
g_cancellable_connect (machine->cancellable,
|
||||
G_CALLBACK (on_delayed_action_cancelled),
|
||||
machine, NULL);
|
||||
}
|
||||
|
||||
machine->timeout = fpi_device_add_timeout (machine->dev, delay, callback,
|
||||
user_data, destroy_func);
|
||||
}
|
||||
|
||||
/**
|
||||
* fpi_ssm_free:
|
||||
* @machine: an #FpiSsm state machine
|
||||
@@ -165,9 +267,13 @@ fpi_ssm_free (FpiSsm *machine)
|
||||
if (!machine)
|
||||
return;
|
||||
|
||||
BUG_ON (machine->timeout != NULL);
|
||||
|
||||
if (machine->ssm_data_destroy)
|
||||
g_clear_pointer (&machine->ssm_data, machine->ssm_data_destroy);
|
||||
g_clear_pointer (&machine->error, g_error_free);
|
||||
g_clear_pointer (&machine->name, g_free);
|
||||
fpi_ssm_clear_delayed_action (machine);
|
||||
g_free (machine);
|
||||
}
|
||||
|
||||
@@ -175,18 +281,23 @@ fpi_ssm_free (FpiSsm *machine)
|
||||
static void
|
||||
__ssm_call_handler (FpiSsm *machine)
|
||||
{
|
||||
fp_dbg ("%p entering state %d", machine, machine->cur_state);
|
||||
fp_dbg ("[%s] %s entering state %d", fp_device_get_driver (machine->dev),
|
||||
machine->name, machine->cur_state);
|
||||
machine->handler (machine, machine->dev);
|
||||
}
|
||||
|
||||
/**
|
||||
* fpi_ssm_start:
|
||||
* @ssm: an #FpiSsm state machine
|
||||
* @ssm: (transfer full): an #FpiSsm state machine
|
||||
* @callback: the #FpiSsmCompletedCallback callback to call on completion
|
||||
*
|
||||
* Starts a state machine. You can also use this function to restart
|
||||
* a completed or failed state machine. The @callback will be called
|
||||
* on completion.
|
||||
*
|
||||
* Note that @ssm will be stolen when this function is called.
|
||||
* So that all associated data will be free'ed automatically, after the
|
||||
* @callback is ran.
|
||||
*/
|
||||
void
|
||||
fpi_ssm_start (FpiSsm *ssm, FpiSsmCompletedCallback callback)
|
||||
@@ -209,7 +320,6 @@ __subsm_complete (FpiSsm *ssm, FpDevice *_dev, GError *error)
|
||||
fpi_ssm_mark_failed (parent, error);
|
||||
else
|
||||
fpi_ssm_next_state (parent);
|
||||
fpi_ssm_free (ssm);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -226,7 +336,12 @@ __subsm_complete (FpiSsm *ssm, FpDevice *_dev, GError *error)
|
||||
void
|
||||
fpi_ssm_start_subsm (FpiSsm *parent, FpiSsm *child)
|
||||
{
|
||||
BUG_ON (parent->timeout);
|
||||
child->parentsm = parent;
|
||||
|
||||
fpi_ssm_clear_delayed_action (parent);
|
||||
fpi_ssm_clear_delayed_action (child);
|
||||
|
||||
fpi_ssm_start (child, __subsm_complete);
|
||||
}
|
||||
|
||||
@@ -241,25 +356,73 @@ void
|
||||
fpi_ssm_mark_completed (FpiSsm *machine)
|
||||
{
|
||||
BUG_ON (machine->completed);
|
||||
BUG_ON (machine->timeout != NULL);
|
||||
|
||||
fpi_ssm_clear_delayed_action (machine);
|
||||
|
||||
machine->completed = TRUE;
|
||||
|
||||
if (machine->error)
|
||||
fp_dbg ("%p completed with error: %s", machine, machine->error->message);
|
||||
fp_dbg ("[%s] %s completed with error: %s", fp_device_get_driver (machine->dev),
|
||||
machine->name, machine->error->message);
|
||||
else
|
||||
fp_dbg ("%p completed successfully", machine);
|
||||
fp_dbg ("[%s] %s completed successfully", fp_device_get_driver (machine->dev),
|
||||
machine->name);
|
||||
if (machine->callback)
|
||||
{
|
||||
GError *error = machine->error ? g_error_copy (machine->error) : NULL;
|
||||
|
||||
machine->callback (machine, machine->dev, error);
|
||||
}
|
||||
fpi_ssm_free (machine);
|
||||
}
|
||||
|
||||
static void
|
||||
on_device_timeout_complete (FpDevice *dev,
|
||||
gpointer user_data)
|
||||
{
|
||||
FpiSsm *machine = user_data;
|
||||
|
||||
machine->timeout = NULL;
|
||||
fpi_ssm_mark_completed (machine);
|
||||
}
|
||||
|
||||
/**
|
||||
* fpi_ssm_mark_completed_delayed:
|
||||
* @machine: an #FpiSsm state machine
|
||||
* @delay: the milliseconds to wait before switching to the next state
|
||||
* @cancellable: (nullable): a #GCancellable to cancel the delayed operation
|
||||
*
|
||||
* Mark a ssm as completed successfully with a delay of @delay ms.
|
||||
* The callback set when creating the state machine with fpi_ssm_new () will be
|
||||
* called when the timeout is over.
|
||||
* The request can be cancelled passing a #GCancellable as @cancellable.
|
||||
*/
|
||||
void
|
||||
fpi_ssm_mark_completed_delayed (FpiSsm *machine,
|
||||
int delay,
|
||||
GCancellable *cancellable)
|
||||
{
|
||||
g_autofree char *source_name = NULL;
|
||||
|
||||
g_return_if_fail (machine != NULL);
|
||||
|
||||
fpi_ssm_set_delayed_action_timeout (machine, delay,
|
||||
on_device_timeout_complete, cancellable,
|
||||
machine, NULL);
|
||||
|
||||
source_name = g_strdup_printf ("[%s] ssm %s complete %d",
|
||||
fp_device_get_device_id (machine->dev),
|
||||
machine->name, machine->cur_state + 1);
|
||||
g_source_set_name (machine->timeout, source_name);
|
||||
}
|
||||
|
||||
/**
|
||||
* fpi_ssm_mark_failed:
|
||||
* @machine: an #FpiSsm state machine
|
||||
* @error: a #GError
|
||||
* @error: (transfer full): a #GError
|
||||
*
|
||||
* Mark a state machine as failed with @error as the error code.
|
||||
* Mark a state machine as failed with @error as the error code, completing it.
|
||||
*/
|
||||
void
|
||||
fpi_ssm_mark_failed (FpiSsm *machine, GError *error)
|
||||
@@ -267,13 +430,16 @@ fpi_ssm_mark_failed (FpiSsm *machine, GError *error)
|
||||
g_assert (error);
|
||||
if (machine->error)
|
||||
{
|
||||
fp_warn ("SSM already has an error set, ignoring new error %s", error->message);
|
||||
fp_warn ("[%s] SSM %s already has an error set, ignoring new error %s",
|
||||
fp_device_get_driver (machine->dev), machine->name, error->message);
|
||||
g_error_free (error);
|
||||
return;
|
||||
}
|
||||
|
||||
fp_dbg ("SSM failed in state %d with error: %s", machine->cur_state, error->message);
|
||||
machine->error = error;
|
||||
fp_dbg ("[%s] SSM %s failed in state %d with error: %s",
|
||||
fp_device_get_driver (machine->dev), machine->name,
|
||||
machine->cur_state, error->message);
|
||||
machine->error = g_steal_pointer (&error);
|
||||
fpi_ssm_mark_completed (machine);
|
||||
}
|
||||
|
||||
@@ -291,6 +457,10 @@ fpi_ssm_next_state (FpiSsm *machine)
|
||||
g_return_if_fail (machine != NULL);
|
||||
|
||||
BUG_ON (machine->completed);
|
||||
BUG_ON (machine->timeout != NULL);
|
||||
|
||||
fpi_ssm_clear_delayed_action (machine);
|
||||
|
||||
machine->cur_state++;
|
||||
if (machine->cur_state == machine->nr_states)
|
||||
fpi_ssm_mark_completed (machine);
|
||||
@@ -298,22 +468,136 @@ fpi_ssm_next_state (FpiSsm *machine)
|
||||
__ssm_call_handler (machine);
|
||||
}
|
||||
|
||||
void
|
||||
fpi_ssm_cancel_delayed_state_change (FpiSsm *machine)
|
||||
{
|
||||
g_return_if_fail (machine);
|
||||
BUG_ON (machine->completed);
|
||||
BUG_ON (machine->timeout == NULL);
|
||||
|
||||
fp_dbg ("[%s] %s cancelled delayed state change",
|
||||
fp_device_get_driver (machine->dev), machine->name);
|
||||
|
||||
fpi_ssm_clear_delayed_action (machine);
|
||||
}
|
||||
|
||||
static void
|
||||
on_device_timeout_next_state (FpDevice *dev,
|
||||
gpointer user_data)
|
||||
{
|
||||
FpiSsm *machine = user_data;
|
||||
|
||||
machine->timeout = NULL;
|
||||
fpi_ssm_next_state (machine);
|
||||
}
|
||||
|
||||
/**
|
||||
* fpi_ssm_next_state_delayed:
|
||||
* @machine: an #FpiSsm state machine
|
||||
* @delay: the milliseconds to wait before switching to the next state
|
||||
* @cancellable: (nullable): a #GCancellable to cancel the delayed operation
|
||||
*
|
||||
* Iterate to next state of a state machine with a delay of @delay ms. If the
|
||||
* current state is the last state, then the state machine will be marked as
|
||||
* completed, as if calling fpi_ssm_mark_completed().
|
||||
* Passing a valid #GCancellable will cause the action to be cancelled when
|
||||
* @cancellable is.
|
||||
*/
|
||||
void
|
||||
fpi_ssm_next_state_delayed (FpiSsm *machine,
|
||||
int delay,
|
||||
GCancellable *cancellable)
|
||||
{
|
||||
g_autofree char *source_name = NULL;
|
||||
|
||||
g_return_if_fail (machine != NULL);
|
||||
|
||||
fpi_ssm_set_delayed_action_timeout (machine, delay,
|
||||
on_device_timeout_next_state, cancellable,
|
||||
machine, NULL);
|
||||
|
||||
source_name = g_strdup_printf ("[%s] ssm %s jump to next state %d",
|
||||
fp_device_get_device_id (machine->dev),
|
||||
machine->name, machine->cur_state + 1);
|
||||
g_source_set_name (machine->timeout, source_name);
|
||||
}
|
||||
|
||||
/**
|
||||
* fpi_ssm_jump_to_state:
|
||||
* @machine: an #FpiSsm state machine
|
||||
* @state: the state to jump to
|
||||
*
|
||||
* Jump to the @state state, bypassing intermediary states.
|
||||
* If @state is the last state, the machine won't be completed unless
|
||||
* fpi_ssm_mark_completed() isn't explicitly called.
|
||||
*/
|
||||
void
|
||||
fpi_ssm_jump_to_state (FpiSsm *machine, int state)
|
||||
{
|
||||
BUG_ON (machine->completed);
|
||||
BUG_ON (state >= machine->nr_states);
|
||||
BUG_ON (state < 0 || state >= machine->nr_states);
|
||||
BUG_ON (machine->timeout != NULL);
|
||||
|
||||
fpi_ssm_clear_delayed_action (machine);
|
||||
|
||||
machine->cur_state = state;
|
||||
__ssm_call_handler (machine);
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
FpiSsm *machine;
|
||||
int next_state;
|
||||
} FpiSsmJumpToStateDelayedData;
|
||||
|
||||
static void
|
||||
on_device_timeout_jump_to_state (FpDevice *dev,
|
||||
gpointer user_data)
|
||||
{
|
||||
FpiSsmJumpToStateDelayedData *data = user_data;
|
||||
|
||||
data->machine->timeout = NULL;
|
||||
fpi_ssm_jump_to_state (data->machine, data->next_state);
|
||||
}
|
||||
|
||||
/**
|
||||
* fpi_ssm_jump_to_state_delayed:
|
||||
* @machine: an #FpiSsm state machine
|
||||
* @state: the state to jump to
|
||||
* @delay: the milliseconds to wait before switching to @state state
|
||||
* @cancellable: (nullable): a #GCancellable to cancel the delayed operation
|
||||
*
|
||||
* Jump to the @state state with a delay of @delay milliseconds, bypassing
|
||||
* intermediary states.
|
||||
* Passing a valid #GCancellable will cause the action to be cancelled when
|
||||
* @cancellable is.
|
||||
*/
|
||||
void
|
||||
fpi_ssm_jump_to_state_delayed (FpiSsm *machine,
|
||||
int state,
|
||||
int delay,
|
||||
GCancellable *cancellable)
|
||||
{
|
||||
FpiSsmJumpToStateDelayedData *data;
|
||||
g_autofree char *source_name = NULL;
|
||||
|
||||
g_return_if_fail (machine != NULL);
|
||||
BUG_ON (state < 0 || state >= machine->nr_states);
|
||||
|
||||
data = g_new0 (FpiSsmJumpToStateDelayedData, 1);
|
||||
data->machine = machine;
|
||||
data->next_state = state;
|
||||
|
||||
fpi_ssm_set_delayed_action_timeout (machine, delay,
|
||||
on_device_timeout_jump_to_state,
|
||||
cancellable, data, g_free);
|
||||
|
||||
source_name = g_strdup_printf ("[%s] ssm %s jump to state %d",
|
||||
fp_device_get_device_id (machine->dev),
|
||||
machine->name, state);
|
||||
g_source_set_name (machine->timeout, source_name);
|
||||
}
|
||||
|
||||
/**
|
||||
* fpi_ssm_get_cur_state:
|
||||
* @machine: an #FpiSsm state machine
|
||||
@@ -360,33 +644,11 @@ fpi_ssm_dup_error (FpiSsm *machine)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* fpi_ssm_next_state_timeout_cb:
|
||||
* @dev: a struct #fp_dev
|
||||
* @data: a pointer to an #FpiSsm state machine
|
||||
*
|
||||
* Same as fpi_ssm_next_state(), but to be used as a callback
|
||||
* for an fpi_timeout_add() callback, when the state change needs
|
||||
* to happen after a timeout.
|
||||
*
|
||||
* Make sure to pass the #FpiSsm as the `ssm_data` argument
|
||||
* for that fpi_timeout_add() call.
|
||||
*/
|
||||
void
|
||||
fpi_ssm_next_state_timeout_cb (FpDevice *dev,
|
||||
void *data)
|
||||
{
|
||||
g_return_if_fail (dev != NULL);
|
||||
g_return_if_fail (data != NULL);
|
||||
|
||||
fpi_ssm_next_state (data);
|
||||
}
|
||||
|
||||
/**
|
||||
* fpi_ssm_usb_transfer_cb:
|
||||
* @transfer: a #FpiUsbTransfer
|
||||
* @device: a #FpDevice
|
||||
* @ssm_data: User data (unused)
|
||||
* @unused_data: User data (unused)
|
||||
* @error: The #GError or %NULL
|
||||
*
|
||||
* Can be used in as a #FpiUsbTransfer callback handler to automatically
|
||||
@@ -396,7 +658,7 @@ fpi_ssm_next_state_timeout_cb (FpDevice *dev,
|
||||
*/
|
||||
void
|
||||
fpi_ssm_usb_transfer_cb (FpiUsbTransfer *transfer, FpDevice *device,
|
||||
gpointer ssm_data, GError *error)
|
||||
gpointer unused_data, GError *error)
|
||||
{
|
||||
g_return_if_fail (transfer->ssm);
|
||||
|
||||
@@ -405,3 +667,32 @@ fpi_ssm_usb_transfer_cb (FpiUsbTransfer *transfer, FpDevice *device,
|
||||
else
|
||||
fpi_ssm_next_state (transfer->ssm);
|
||||
}
|
||||
|
||||
/**
|
||||
* fpi_ssm_usb_transfer_with_weak_pointer_cb:
|
||||
* @transfer: a #FpiUsbTransfer
|
||||
* @device: a #FpDevice
|
||||
* @weak_ptr: A #gpointer pointer to nullify. You can pass a pointer to any
|
||||
* #gpointer to nullify when the callback is completed. I.e a
|
||||
* pointer to the current #FpiUsbTransfer.
|
||||
* @error: The #GError or %NULL
|
||||
*
|
||||
* Can be used in as a #FpiUsbTransfer callback handler to automatically
|
||||
* advance or fail a statemachine on transfer completion.
|
||||
* Passing a #gpointer* as @weak_ptr permits to nullify it once we're done
|
||||
* with the transfer.
|
||||
*
|
||||
* Make sure to set the #FpiSsm on the transfer.
|
||||
*/
|
||||
void
|
||||
fpi_ssm_usb_transfer_with_weak_pointer_cb (FpiUsbTransfer *transfer,
|
||||
FpDevice *device, gpointer weak_ptr,
|
||||
GError *error)
|
||||
{
|
||||
g_return_if_fail (transfer->ssm);
|
||||
|
||||
if (weak_ptr)
|
||||
g_nullify_pointer ((gpointer *) weak_ptr);
|
||||
|
||||
fpi_ssm_usb_transfer_cb (transfer, device, weak_ptr, error);
|
||||
}
|
||||
|
||||
+27
-7
@@ -2,6 +2,7 @@
|
||||
* Copyright (C) 2007-2008 Daniel Drake <dsd@gentoo.org>
|
||||
* Copyright (C) 2018 Bastien Nocera <hadess@hadess.net>
|
||||
* Copyright (C) 2019 Benjamin Berg <bberg@redhat.com>
|
||||
* Copyright (C) 2019 Marco Trevisan <marco.trevisan@canonical.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
@@ -21,7 +22,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "fp-device.h"
|
||||
#include "fpi-usb-transfer.h"
|
||||
|
||||
/* async drv <--> lib comms */
|
||||
|
||||
@@ -38,7 +38,7 @@ typedef struct _FpiSsm FpiSsm;
|
||||
* FpiSsmCompletedCallback:
|
||||
* @ssm: a #FpiSsm state machine
|
||||
* @dev: the #fp_dev fingerprint device
|
||||
* @error: The #GError or %NULL on successful completion
|
||||
* @error: (transfer full): The #GError or %NULL on successful completion
|
||||
*
|
||||
* The callback called when a state machine completes successfully,
|
||||
* as set when calling fpi_ssm_start().
|
||||
@@ -59,9 +59,12 @@ typedef void (*FpiSsmHandlerCallback)(FpiSsm *ssm,
|
||||
FpDevice *dev);
|
||||
|
||||
/* for library and drivers */
|
||||
FpiSsm *fpi_ssm_new (FpDevice *dev,
|
||||
#define fpi_ssm_new(dev, handler, nr_states) \
|
||||
fpi_ssm_new_full (dev, handler, nr_states, #nr_states)
|
||||
FpiSsm *fpi_ssm_new_full (FpDevice *dev,
|
||||
FpiSsmHandlerCallback handler,
|
||||
int nr_states);
|
||||
int nr_states,
|
||||
const char *machine_name);
|
||||
void fpi_ssm_free (FpiSsm *machine);
|
||||
void fpi_ssm_start (FpiSsm *ssm,
|
||||
FpiSsmCompletedCallback callback);
|
||||
@@ -72,7 +75,18 @@ void fpi_ssm_start_subsm (FpiSsm *parent,
|
||||
void fpi_ssm_next_state (FpiSsm *machine);
|
||||
void fpi_ssm_jump_to_state (FpiSsm *machine,
|
||||
int state);
|
||||
void fpi_ssm_next_state_delayed (FpiSsm *machine,
|
||||
int delay,
|
||||
GCancellable *cancellable);
|
||||
void fpi_ssm_jump_to_state_delayed (FpiSsm *machine,
|
||||
int state,
|
||||
int delay,
|
||||
GCancellable *cancellable);
|
||||
void fpi_ssm_cancel_delayed_state_change (FpiSsm *machine);
|
||||
void fpi_ssm_mark_completed (FpiSsm *machine);
|
||||
void fpi_ssm_mark_completed_delayed (FpiSsm *machine,
|
||||
int delay,
|
||||
GCancellable *cancellable);
|
||||
void fpi_ssm_mark_failed (FpiSsm *machine,
|
||||
GError *error);
|
||||
void fpi_ssm_set_data (FpiSsm *machine,
|
||||
@@ -86,9 +100,15 @@ int fpi_ssm_get_cur_state (FpiSsm *machine);
|
||||
/* Callbacks to be used by the driver instead of implementing their own
|
||||
* logic.
|
||||
*/
|
||||
void fpi_ssm_next_state_timeout_cb (FpDevice *dev,
|
||||
void *data);
|
||||
typedef struct _FpiUsbTransfer FpiUsbTransfer;
|
||||
|
||||
void fpi_ssm_usb_transfer_cb (FpiUsbTransfer *transfer,
|
||||
FpDevice *device,
|
||||
gpointer user_data,
|
||||
gpointer unused_data,
|
||||
GError *error);
|
||||
void fpi_ssm_usb_transfer_with_weak_pointer_cb (FpiUsbTransfer *transfer,
|
||||
FpDevice *device,
|
||||
gpointer weak_ptr,
|
||||
GError *error);
|
||||
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC (FpiSsm, fpi_ssm_free)
|
||||
|
||||
@@ -298,7 +298,7 @@ fpi_usb_transfer_fill_interrupt_full (FpiUsbTransfer *transfer,
|
||||
transfer->free_buffer = free_func;
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
transfer_finish_cb (GObject *source_object, GAsyncResult *res, gpointer user_data)
|
||||
{
|
||||
GError *error = NULL;
|
||||
@@ -356,7 +356,7 @@ transfer_finish_cb (GObject *source_object, GAsyncResult *res, gpointer user_dat
|
||||
|
||||
/**
|
||||
* fpi_usb_transfer_submit:
|
||||
* @transfer: The transfer to submit, must have been filled.
|
||||
* @transfer: (transfer full): The transfer to submit, must have been filled.
|
||||
* @timeout_ms: Timeout for the transfer in ms
|
||||
* @cancellable: Cancellable to use, e.g. fpi_device_get_cancellable()
|
||||
* @callback: Callback on completion or error
|
||||
@@ -364,10 +364,9 @@ transfer_finish_cb (GObject *source_object, GAsyncResult *res, gpointer user_dat
|
||||
*
|
||||
* Submit a USB transfer with a specific timeout and callback functions.
|
||||
*
|
||||
* Note that #FpiUsbTransfer is owned by the user. In most cases, you
|
||||
* should call fpi_usb_transfer_unref() just after calling this function.
|
||||
* Doing so means that all associated data will be free'ed automatically
|
||||
* after the callback ran.
|
||||
* Note that #FpiUsbTransfer will be stolen when this function is called.
|
||||
* So that all associated data will be free'ed automatically, after the
|
||||
* callback ran unless fpi_usb_transfer_ref() is explicitly called.
|
||||
*/
|
||||
void
|
||||
fpi_usb_transfer_submit (FpiUsbTransfer *transfer,
|
||||
@@ -385,11 +384,6 @@ fpi_usb_transfer_submit (FpiUsbTransfer *transfer,
|
||||
transfer->callback = callback;
|
||||
transfer->user_data = user_data;
|
||||
|
||||
/* Grab a reference, this means that one can simply unref after submit and
|
||||
* trust for the data to disappear without explicit management by the callback
|
||||
* function. */
|
||||
fpi_usb_transfer_ref (transfer);
|
||||
|
||||
log_transfer (transfer, TRUE, NULL);
|
||||
|
||||
switch (transfer->type)
|
||||
@@ -460,6 +454,7 @@ fpi_usb_transfer_submit_sync (FpiUsbTransfer *transfer,
|
||||
GError **error)
|
||||
{
|
||||
gboolean res;
|
||||
gsize actual_length;
|
||||
|
||||
g_return_val_if_fail (transfer, FALSE);
|
||||
|
||||
@@ -475,7 +470,7 @@ fpi_usb_transfer_submit_sync (FpiUsbTransfer *transfer,
|
||||
transfer->endpoint,
|
||||
transfer->buffer,
|
||||
transfer->length,
|
||||
&transfer->actual_length,
|
||||
&actual_length,
|
||||
timeout_ms,
|
||||
NULL,
|
||||
error);
|
||||
@@ -491,7 +486,7 @@ fpi_usb_transfer_submit_sync (FpiUsbTransfer *transfer,
|
||||
transfer->idx,
|
||||
transfer->buffer,
|
||||
transfer->length,
|
||||
&transfer->actual_length,
|
||||
&actual_length,
|
||||
timeout_ms,
|
||||
NULL,
|
||||
error);
|
||||
@@ -502,7 +497,7 @@ fpi_usb_transfer_submit_sync (FpiUsbTransfer *transfer,
|
||||
transfer->endpoint,
|
||||
transfer->buffer,
|
||||
transfer->length,
|
||||
&transfer->actual_length,
|
||||
&actual_length,
|
||||
timeout_ms,
|
||||
NULL,
|
||||
error);
|
||||
@@ -517,6 +512,8 @@ fpi_usb_transfer_submit_sync (FpiUsbTransfer *transfer,
|
||||
|
||||
if (!res)
|
||||
transfer->actual_length = -1;
|
||||
else
|
||||
transfer->actual_length = actual_length;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -30,8 +30,7 @@ G_BEGIN_DECLS
|
||||
#define FPI_USB_ENDPOINT_OUT 0x00
|
||||
|
||||
typedef struct _FpiUsbTransfer FpiUsbTransfer;
|
||||
|
||||
#include "fpi-ssm.h"
|
||||
typedef struct _FpiSsm FpiSsm;
|
||||
|
||||
typedef void (*FpiUsbTransferCallback)(FpiUsbTransfer *transfer,
|
||||
FpDevice *dev,
|
||||
@@ -62,7 +61,7 @@ typedef enum {
|
||||
* @length: The requested length of the transfer in bytes.
|
||||
* @actual_length: The actual length of the transfer
|
||||
* (see also fpi_usb_transfer_set_short_error())
|
||||
* @buffer: The transfered data.
|
||||
* @buffer: The transferred data.
|
||||
*
|
||||
* Helper for handling USB transfers.
|
||||
*/
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* Copyright (C) 2009 Red Hat <mjg@redhat.com>
|
||||
* Copyright (C) 2008 Bastien Nocera <hadess@hadess.net>
|
||||
* Copyright (C) 2008 Timo Hoenig <thoenig@suse.de>, <thoenig@nouse.net>
|
||||
* Coypright (C) 2019 Benjamin Berg <bberg@redhat.com>
|
||||
* Copyright (C) 2019 Benjamin Berg <bberg@redhat.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
@@ -31,23 +31,18 @@ GHashTable *printed = NULL;
|
||||
static GList *
|
||||
insert_drivers (GList *list)
|
||||
{
|
||||
g_autoptr(GArray) drivers = g_array_new (FALSE, FALSE, sizeof (GType));
|
||||
g_autoptr(GArray) drivers = fpi_get_driver_types ();
|
||||
gint i;
|
||||
|
||||
fpi_get_driver_types (drivers);
|
||||
|
||||
/* Find the best driver to handle this USB device. */
|
||||
for (i = 0; i < drivers->len; i++)
|
||||
{
|
||||
GType driver = g_array_index (drivers, GType, i);
|
||||
FpDeviceClass *cls = FP_DEVICE_CLASS (g_type_class_ref (driver));
|
||||
g_autoptr(FpDeviceClass) cls = g_type_class_ref (driver);
|
||||
const FpIdEntry *entry;
|
||||
|
||||
if (cls->type != FP_DEVICE_TYPE_USB)
|
||||
{
|
||||
g_type_class_unref (cls);
|
||||
continue;
|
||||
}
|
||||
|
||||
for (entry = cls->id_table; entry->vid; entry++)
|
||||
{
|
||||
@@ -65,8 +60,6 @@ insert_drivers (GList *list)
|
||||
|
||||
list = g_list_prepend (list, g_strdup_printf ("%s | %s\n", key, cls->full_name));
|
||||
}
|
||||
|
||||
g_type_class_unref (cls);
|
||||
}
|
||||
|
||||
return list;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* Copyright (C) 2009 Red Hat <mjg@redhat.com>
|
||||
* Copyright (C) 2008 Bastien Nocera <hadess@hadess.net>
|
||||
* Copyright (C) 2008 Timo Hoenig <thoenig@suse.de>, <thoenig@nouse.net>
|
||||
* Coypright (C) 2019 Benjamin Berg <bberg@redhat.com>
|
||||
* Copyright (C) 2019 Benjamin Berg <bberg@redhat.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
@@ -96,29 +96,20 @@ print_driver (const FpDeviceClass *cls)
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
g_autoptr(GArray) drivers = g_array_new (FALSE, FALSE, sizeof (GType));
|
||||
g_autoptr(GArray) drivers = fpi_get_driver_types ();
|
||||
guint i;
|
||||
|
||||
g_print ("%p\n", drivers);
|
||||
g_print ("%p\n", fpi_get_driver_types);
|
||||
fpi_get_driver_types (drivers);
|
||||
|
||||
printed = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
|
||||
|
||||
for (i = 0; i < drivers->len; i++)
|
||||
{
|
||||
GType driver = g_array_index (drivers, GType, i);
|
||||
FpDeviceClass *cls = FP_DEVICE_CLASS (g_type_class_ref (driver));
|
||||
g_autoptr(FpDeviceClass) cls = g_type_class_ref (driver);
|
||||
|
||||
if (cls->type != FP_DEVICE_TYPE_USB)
|
||||
{
|
||||
g_type_class_unref (cls);
|
||||
continue;
|
||||
}
|
||||
|
||||
print_driver (cls);
|
||||
|
||||
g_type_class_unref (cls);
|
||||
}
|
||||
|
||||
print_driver (&whitelist);
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
LIBFPRINT_2.0.0 {
|
||||
global:
|
||||
fp_*;
|
||||
|
||||
/* Needs to be public for the listing commands. */
|
||||
fpi_get_driver_types;
|
||||
local:
|
||||
*;
|
||||
};
|
||||
|
||||
+114
-36
@@ -4,29 +4,43 @@ libfprint_sources = [
|
||||
'fp-image.c',
|
||||
'fp-print.c',
|
||||
'fp-image-device.c',
|
||||
]
|
||||
|
||||
libfprint_private_sources = [
|
||||
'fpi-assembling.c',
|
||||
'fpi-ssm.c',
|
||||
'fpi-usb-transfer.c',
|
||||
'fpi-byte-reader.c',
|
||||
'fpi-byte-writer.c',
|
||||
'fpi-device.c',
|
||||
'fpi-image-device.c',
|
||||
'fpi-image.c',
|
||||
'fpi-print.c',
|
||||
'fpi-ssm.c',
|
||||
'fpi-usb-transfer.c',
|
||||
]
|
||||
|
||||
libfprint_public_headers = [
|
||||
'fp-context.h',
|
||||
'fp-device.h',
|
||||
'fp-image-device.h',
|
||||
'fp-image.h',
|
||||
'fp-print.h',
|
||||
]
|
||||
|
||||
libfprint_private_headers = [
|
||||
'fpi-assembling.h',
|
||||
'fpi-device.h',
|
||||
'fpi-image.h',
|
||||
'fpi-image-device.h',
|
||||
'fpi-print.h',
|
||||
'fpi-byte-reader.h',
|
||||
'fpi-byte-writer.h',
|
||||
'fpi-byte-utils.h',
|
||||
'fpi-byte-writer.h',
|
||||
'fpi-compat.h',
|
||||
'fpi-context.h',
|
||||
'fpi-device.h',
|
||||
'fpi-image-device.h',
|
||||
'fpi-image.h',
|
||||
'fpi-log.h',
|
||||
'fpi-minutiae.h',
|
||||
'fpi-print.h',
|
||||
'fpi-usb-transfer.h',
|
||||
'fpi-ssm.h',
|
||||
]
|
||||
|
||||
nbis_sources = [
|
||||
@@ -163,59 +177,125 @@ other_sources = []
|
||||
|
||||
fp_enums = gnome.mkenums_simple('fp-enums',
|
||||
sources: libfprint_public_headers,
|
||||
install_header : true)
|
||||
install_header: true,
|
||||
install_dir: get_option('includedir') / versioned_libname,
|
||||
)
|
||||
fp_enums_h = fp_enums[1]
|
||||
|
||||
fpi_enums = gnome.mkenums_simple('fpi-enums',
|
||||
sources: libfprint_private_headers,
|
||||
install_header : true)
|
||||
install_header: false,
|
||||
)
|
||||
fpi_enums_h = fpi_enums[1]
|
||||
|
||||
enums_dep = declare_dependency(
|
||||
sources: [ fp_enums_h, fpi_enums_h ]
|
||||
)
|
||||
|
||||
drivers_sources += configure_file(input: 'empty_file',
|
||||
output: 'fp-drivers.c',
|
||||
output: 'fpi-drivers.c',
|
||||
capture: true,
|
||||
command: [
|
||||
'echo',
|
||||
drivers_type_list + '\n\n' + drivers_type_func
|
||||
'\n'.join(drivers_type_list + [] + drivers_type_func)
|
||||
])
|
||||
|
||||
mapfile = 'libfprint.ver'
|
||||
vflag = '-Wl,--version-script,@0@/@1@'.format(meson.current_source_dir(), mapfile)
|
||||
deps = [
|
||||
enums_dep,
|
||||
gio_dep,
|
||||
glib_dep,
|
||||
gobject_dep,
|
||||
gusb_dep,
|
||||
imaging_dep,
|
||||
mathlib_dep,
|
||||
nss_dep,
|
||||
]
|
||||
|
||||
deps = [ mathlib_dep, glib_dep, gusb_dep, nss_dep, imaging_dep, gio_dep ]
|
||||
libfprint = library('fprint',
|
||||
libfprint_sources + fp_enums + fpi_enums +
|
||||
drivers_sources + nbis_sources + other_sources,
|
||||
soversion: soversion,
|
||||
version: libversion,
|
||||
c_args: common_cflags + drivers_cflags,
|
||||
include_directories: [
|
||||
# These are empty and only exist so that the include directories are created
|
||||
# in the build tree. This silences a build time warning.
|
||||
subdir('nbis/include')
|
||||
subdir('nbis/libfprint-include')
|
||||
deps += declare_dependency(include_directories: [
|
||||
root_inc,
|
||||
include_directories('nbis/include'),
|
||||
include_directories('nbis/libfprint-include'),
|
||||
])
|
||||
|
||||
libnbis = static_library('nbis',
|
||||
nbis_sources,
|
||||
dependencies: deps,
|
||||
c_args: cc.get_supported_arguments([
|
||||
'-Wno-error=redundant-decls',
|
||||
'-Wno-redundant-decls',
|
||||
'-Wno-discarded-qualifiers',
|
||||
]),
|
||||
install: false)
|
||||
|
||||
libfprint_private = static_library('fprint-private',
|
||||
sources: [
|
||||
fpi_enums,
|
||||
libfprint_private_sources,
|
||||
],
|
||||
dependencies: deps,
|
||||
link_with: libnbis,
|
||||
install: false)
|
||||
|
||||
libfprint_drivers = static_library('fprint-drivers',
|
||||
sources: drivers_sources,
|
||||
c_args: drivers_cflags,
|
||||
dependencies: deps,
|
||||
link_with: libfprint_private,
|
||||
install: false)
|
||||
|
||||
mapfile = files('libfprint.ver')
|
||||
vflag = '-Wl,--version-script,@0@/@1@'.format(meson.source_root(), mapfile[0])
|
||||
|
||||
libfprint = library(versioned_libname.split('lib')[1],
|
||||
sources: [
|
||||
fp_enums,
|
||||
libfprint_sources,
|
||||
other_sources,
|
||||
],
|
||||
soversion: soversion,
|
||||
version: libversion,
|
||||
link_args : vflag,
|
||||
link_depends : mapfile,
|
||||
link_with: [libfprint_drivers, libfprint_private],
|
||||
dependencies: deps,
|
||||
install: true)
|
||||
|
||||
libfprint_dep = declare_dependency(link_with: libfprint,
|
||||
sources: [ fp_enums_h ],
|
||||
include_directories: root_inc,
|
||||
dependencies: [glib_dep, gusb_dep, gio_dep])
|
||||
dependencies: [
|
||||
enums_dep,
|
||||
gio_dep,
|
||||
glib_dep,
|
||||
gobject_dep,
|
||||
gusb_dep,
|
||||
])
|
||||
|
||||
install_headers(['fprint.h'] + libfprint_public_headers, subdir: 'libfprint')
|
||||
install_headers(['fprint.h'] + libfprint_public_headers,
|
||||
subdir: versioned_libname
|
||||
)
|
||||
|
||||
libfprint_private_dep = declare_dependency(
|
||||
include_directories: include_directories('.'),
|
||||
link_with: libfprint_private,
|
||||
dependencies: [
|
||||
deps,
|
||||
libfprint_dep,
|
||||
]
|
||||
)
|
||||
|
||||
udev_rules = executable('fprint-list-udev-rules',
|
||||
'fprint-list-udev-rules.c',
|
||||
include_directories: [
|
||||
root_inc,
|
||||
],
|
||||
dependencies: [ deps, libfprint_dep ],
|
||||
dependencies: libfprint_private_dep,
|
||||
link_with: libfprint_drivers,
|
||||
install: false)
|
||||
|
||||
if get_option('udev_rules')
|
||||
custom_target('udev-rules',
|
||||
output: '60-fprint-autosuspend.rules',
|
||||
output: '60-@0@-autosuspend.rules'.format(versioned_libname),
|
||||
capture: true,
|
||||
command: [ udev_rules ],
|
||||
install: true,
|
||||
@@ -224,10 +304,8 @@ endif
|
||||
|
||||
supported_devices = executable('fprint-list-supported-devices',
|
||||
'fprint-list-supported-devices.c',
|
||||
include_directories: [
|
||||
root_inc,
|
||||
],
|
||||
dependencies: [ deps, libfprint_dep ],
|
||||
dependencies: libfprint_private_dep,
|
||||
link_with: libfprint_drivers,
|
||||
install: false)
|
||||
|
||||
|
||||
@@ -238,7 +316,7 @@ if get_option('introspection')
|
||||
libfprint_public_headers,
|
||||
libfprint_sources,
|
||||
],
|
||||
nsversion : '2.0',
|
||||
nsversion : '@0@.0'.format(soversion),
|
||||
namespace : 'FPrint',
|
||||
symbol_prefix : 'fp_',
|
||||
identifier_prefix : 'Fp',
|
||||
@@ -249,6 +327,7 @@ if get_option('introspection')
|
||||
link_with : libfprint,
|
||||
dependencies : [
|
||||
gio_dep,
|
||||
gobject_dep,
|
||||
gusb_dep,
|
||||
],
|
||||
includes : [
|
||||
@@ -256,8 +335,7 @@ if get_option('introspection')
|
||||
'GObject-2.0',
|
||||
'GUsb-1.0',
|
||||
],
|
||||
install : true
|
||||
)
|
||||
install : true)
|
||||
libfprint_gir = libfprint_girtarget[0]
|
||||
libfprint_typelib = libfprint_girtarget[1]
|
||||
endif
|
||||
|
||||
@@ -896,7 +896,7 @@ for ( k = 0; k < np - 1; k++ ) {
|
||||
for ( i = 0; i < tot; i++ ) {
|
||||
|
||||
|
||||
int colp_value = colp[ y[i]-1 ][0];
|
||||
int colp_value = colp[ bz_y[i]-1 ][0];
|
||||
if ( colp_value < 0 ) {
|
||||
kk += colp_value;
|
||||
n++;
|
||||
@@ -933,7 +933,7 @@ for ( k = 0; k < np - 1; k++ ) {
|
||||
|
||||
kk = 0;
|
||||
for ( i = 0; i < tot; i++ ) {
|
||||
int diff = colp[ y[i]-1 ][0] - jj;
|
||||
int diff = colp[ bz_y[i]-1 ][0] - jj;
|
||||
j = SQUARED( diff );
|
||||
|
||||
|
||||
@@ -942,7 +942,7 @@ for ( k = 0; k < np - 1; k++ ) {
|
||||
if ( j > TXS && j < CTXS )
|
||||
kk++;
|
||||
else
|
||||
y[i-kk] = y[i];
|
||||
bz_y[i-kk] = bz_y[i];
|
||||
} /* END FOR i */
|
||||
|
||||
tot -= kk; /* Adjust the total edge pairs TOT based on # of edge pairs skipped */
|
||||
@@ -958,7 +958,7 @@ for ( k = 0; k < np - 1; k++ ) {
|
||||
|
||||
|
||||
for ( i = tot-1 ; i >= 0; i-- ) {
|
||||
int idx = y[i] - 1;
|
||||
int idx = bz_y[i] - 1;
|
||||
if ( rk[idx] == 0 ) {
|
||||
sc[idx] = -1;
|
||||
} else {
|
||||
@@ -976,7 +976,7 @@ for ( k = 0; k < np - 1; k++ ) {
|
||||
int pd = 0;
|
||||
|
||||
for ( i = 0; i < tot; i++ ) {
|
||||
int idx = y[i] - 1;
|
||||
int idx = bz_y[i] - 1;
|
||||
for ( ii = 1; ii < 4; ii++ ) {
|
||||
|
||||
|
||||
@@ -1476,7 +1476,7 @@ return match_score;
|
||||
/* extern int rk[ RK_SIZE ]; */
|
||||
/* extern int cp[ CP_SIZE ]; */
|
||||
/* extern int rp[ RP_SIZE ]; */
|
||||
/* extern int y[ Y_SIZE ]; */
|
||||
/* extern int bz_y[ Y_SIZE ]; */
|
||||
|
||||
void bz_sift(
|
||||
int * ww, /* INPUT and OUTPUT; endpoint groups index; *ww may be bumped by one or by two */
|
||||
@@ -1507,7 +1507,7 @@ if ( n == 0 && t == 0 ) {
|
||||
|
||||
|
||||
if ( sc[kx-1] != ftt ) {
|
||||
y[ (*tot)++ ] = kx;
|
||||
bz_y[ (*tot)++ ] = kx;
|
||||
rk[kx-1] = sc[kx-1];
|
||||
sc[kx-1] = ftt;
|
||||
}
|
||||
@@ -1553,7 +1553,7 @@ if ( n == l ) {
|
||||
qq[*qh] = kz;
|
||||
zz[kz-1] = (*qh)++;
|
||||
}
|
||||
y[(*tot)++] = kx;
|
||||
bz_y[(*tot)++] = kx;
|
||||
rk[kx-1] = sc[kx-1];
|
||||
sc[kx-1] = ftt;
|
||||
}
|
||||
@@ -1697,12 +1697,12 @@ for ( ii = 0; ii < tp; ii++ ) { /* For each index up to the current value of
|
||||
}
|
||||
|
||||
t = 0;
|
||||
y[0] = lim;
|
||||
bz_y[0] = lim;
|
||||
cp[0] = 1;
|
||||
b = 0;
|
||||
n = 1;
|
||||
do { /* looping until T < 0 ... */
|
||||
if ( y[t] - cp[t] > 1 ) {
|
||||
if (bz_y[t] - cp[t] > 1 ) {
|
||||
k = sct[cp[t]][t];
|
||||
j = ctt[k] + 1;
|
||||
for ( i = 0; i < j; i++ ) {
|
||||
@@ -1715,25 +1715,25 @@ for ( ii = 0; ii < tp; ii++ ) { /* For each index up to the current value of
|
||||
do {
|
||||
while ( rp[jj] < sct[kk][t] && jj < j )
|
||||
jj++;
|
||||
while ( rp[jj] > sct[kk][t] && kk < y[t] )
|
||||
while ( rp[jj] > sct[kk][t] && kk < bz_y[t] )
|
||||
kk++;
|
||||
while ( rp[jj] == sct[kk][t] && kk < y[t] && jj < j ) {
|
||||
while ( rp[jj] == sct[kk][t] && kk < bz_y[t] && jj < j ) {
|
||||
sct[k][t+1] = sct[kk][t];
|
||||
k++;
|
||||
kk++;
|
||||
jj++;
|
||||
}
|
||||
} while ( kk < y[t] && jj < j );
|
||||
} while ( kk < bz_y[t] && jj < j );
|
||||
|
||||
t++;
|
||||
cp[t] = 1;
|
||||
y[t] = k;
|
||||
bz_y[t] = k;
|
||||
b = t;
|
||||
n = 1;
|
||||
} else {
|
||||
int tot = 0;
|
||||
|
||||
lim = y[t];
|
||||
lim = bz_y[t];
|
||||
for ( i = n-1; i < lim; i++ ) {
|
||||
tot += ct[ sct[i][t] ];
|
||||
}
|
||||
@@ -1750,7 +1750,7 @@ for ( ii = 0; ii < tp; ii++ ) { /* For each index up to the current value of
|
||||
|
||||
{
|
||||
int rk_index = b;
|
||||
lim = y[t];
|
||||
lim = bz_y[t];
|
||||
for ( i = n-1; i < lim; ) {
|
||||
rk[ rk_index++ ] = sct[ i++ ][ t ];
|
||||
}
|
||||
@@ -1760,7 +1760,7 @@ for ( ii = 0; ii < tp; ii++ ) { /* For each index up to the current value of
|
||||
t--;
|
||||
if ( t >= 0 ) {
|
||||
++cp[t];
|
||||
n = y[t];
|
||||
n = bz_y[t];
|
||||
}
|
||||
} /* END IF */
|
||||
|
||||
|
||||
@@ -102,7 +102,7 @@ int yl[ YL_SIZE_1 ][ YL_SIZE_2 ];
|
||||
int rf[RF_SIZE_1][RF_SIZE_2];
|
||||
int cf[CF_SIZE_1][CF_SIZE_2];
|
||||
|
||||
int y[20000];
|
||||
int bz_y[20000];
|
||||
#else
|
||||
int rq[ RQ_SIZE ] = {};
|
||||
int tq[ TQ_SIZE ] = {};
|
||||
@@ -122,6 +122,6 @@ int yl[ YL_SIZE_1 ][ YL_SIZE_2 ];
|
||||
int rf[RF_SIZE_1][RF_SIZE_2] = {};
|
||||
int cf[CF_SIZE_1][CF_SIZE_2] = {};
|
||||
|
||||
int y[20000] = {};
|
||||
int bz_y[20000] = {};
|
||||
#endif
|
||||
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
diff --git a/libfprint/nbis/mindtct/contour.c b/libfprint/nbis/mindtct/contour.c
|
||||
index 3e9416c..31f32d0 100644
|
||||
--- mindtct/contour.c
|
||||
+++ mindtct/contour.c
|
||||
@@ -440,6 +440,8 @@ int get_centered_contour(int **ocontour_x, int **ocontour_y,
|
||||
int *contour_x, *contour_y, *contour_ex, *contour_ey, ncontour;
|
||||
int i, j, ret;
|
||||
|
||||
+ g_assert (half_contour > 0);
|
||||
+
|
||||
/* Compute maximum length of complete contour */
|
||||
/* (2 half contours + feature point). */
|
||||
max_contour = (half_contour<<1) + 1;
|
||||
diff --git a/libfprint/nbis/mindtct/minutia.c b/libfprint/nbis/mindtct/minutia.c
|
||||
index 0b29aa0..77cf09d 100644
|
||||
--- mindtct/minutia.c
|
||||
+++ mindtct/minutia.c
|
||||
@@ -1625,7 +1625,7 @@ int process_horizontal_scan_minutia_V2(MINUTIAE *minutiae,
|
||||
dmapval, bdata, iw, ih, lfsparms);
|
||||
|
||||
/* If minuitia IGNORED and not added to the minutia list ... */
|
||||
- if(ret == IGNORE)
|
||||
+ if(ret != 0)
|
||||
/* Deallocate the minutia. */
|
||||
free_minutia(minutia);
|
||||
|
||||
@@ -1776,7 +1776,7 @@ int process_vertical_scan_minutia_V2(MINUTIAE *minutiae,
|
||||
dmapval, bdata, iw, ih, lfsparms);
|
||||
|
||||
/* If minuitia IGNORED and not added to the minutia list ... */
|
||||
- if(ret == IGNORE)
|
||||
+ if(ret != 0)
|
||||
/* Deallocate the minutia. */
|
||||
free_minutia(minutia);
|
||||
|
||||
diff --git a/libfprint/nbis/mindtct/ridges.c b/libfprint/nbis/mindtct/ridges.c
|
||||
index f0d9cd3..9902585 100644
|
||||
--- mindtct/ridges.c
|
||||
+++ mindtct/ridges.c
|
||||
@@ -147,6 +147,8 @@ int count_minutia_ridges(const int first, MINUTIAE *minutiae,
|
||||
{
|
||||
int i, ret, *nbr_list, *nbr_nridges, nnbrs;
|
||||
|
||||
+ g_assert (lfsparms->max_nbrs > 0);
|
||||
+
|
||||
/* Find up to the maximum number of qualifying neighbors. */
|
||||
nbr_list = NULL;
|
||||
if((ret = find_neighbors(&nbr_list, &nnbrs, lfsparms->max_nbrs,
|
||||
@@ -407,6 +409,8 @@ int insert_neighbor(const int pos, const int nbr_index, const double nbr_dist2,
|
||||
{
|
||||
int i;
|
||||
|
||||
+ g_assert (pos >= 0);
|
||||
+
|
||||
/* If the desired insertion position is beyond one passed the last */
|
||||
/* neighbor in the lists OR greater than equal to the maximum ... */
|
||||
/* NOTE: pos is zero-oriented while nnbrs and max_nbrs are 1-oriented. */
|
||||
@@ -245,7 +245,7 @@ extern int cp[ CP_SIZE ];
|
||||
extern int rp[ RP_SIZE ];
|
||||
extern int rf[RF_SIZE_1][RF_SIZE_2];
|
||||
extern int cf[CF_SIZE_1][CF_SIZE_2];
|
||||
extern int y[20000];
|
||||
extern int bz_y[20000];
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
@@ -66,7 +66,8 @@ of the software.
|
||||
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <fp_internal.h>
|
||||
#include <nbis-helpers.h>
|
||||
#include <fpi-minutiae.h>
|
||||
|
||||
/*************************************************************************/
|
||||
/* OUTPUT FILE EXTENSIONS */
|
||||
@@ -259,6 +260,8 @@ typedef struct g_lfsparms{
|
||||
int pores_steps_bwd;
|
||||
double pores_min_dist2;
|
||||
double pores_max_ratio;
|
||||
int remove_perimeter_pts;
|
||||
int min_pp_distance;
|
||||
|
||||
/* Ridge Counting Controls */
|
||||
int max_nbrs;
|
||||
@@ -608,6 +611,9 @@ typedef struct g_lfsparms{
|
||||
/* contour points to be considered a pore. */
|
||||
#define PORES_MAX_RATIO 2.25
|
||||
|
||||
/* Points which are closer than this distance to scan perimeter will be removed */
|
||||
#define PERIMETER_PTS_DISTANCE 10
|
||||
|
||||
|
||||
/***** RIDGE COUNTING CONSTANTS *****/
|
||||
|
||||
@@ -1122,6 +1128,9 @@ extern int remove_or_adjust_side_minutiae(MINUTIAE *, unsigned char *,
|
||||
extern int remove_or_adjust_side_minutiae_V2(MINUTIAE *,
|
||||
unsigned char *, const int, const int,
|
||||
int *, const int, const int, const LFSPARMS *);
|
||||
extern int remove_perimeter_pts(MINUTIAE *minutiae,
|
||||
unsigned char *bdata, const int iw, const int ih,
|
||||
const LFSPARMS *lfsparms);
|
||||
|
||||
/* results.c */
|
||||
extern int write_text_results(char *, const int, const int, const int,
|
||||
|
||||
@@ -1,15 +1,16 @@
|
||||
--- include/lfs.h 2018-08-24 15:31:54.535579623 +0200
|
||||
+++ include/lfs.h.orig 2018-08-24 15:31:48.781587933 +0200
|
||||
@@ -66,7 +43,7 @@ of the software.
|
||||
--- include/lfs.h
|
||||
+++ include/lfs.h
|
||||
@@ -66,7 +66,8 @@ of the software.
|
||||
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
-#include <an2k.h> /* Needed by to_type9.c */
|
||||
+#include <fp_internal.h>
|
||||
+#include <nbis-helpers.h>
|
||||
+#include <fpi-minutiae.h>
|
||||
|
||||
/*************************************************************************/
|
||||
/* OUTPUT FILE EXTENSIONS */
|
||||
@@ -154,26 +131,8 @@ typedef struct rotgrids{
|
||||
@@ -154,26 +155,8 @@ typedef struct rotgrids{
|
||||
#define DISAPPEARING 0
|
||||
#define APPEARING 1
|
||||
|
||||
@@ -38,7 +39,7 @@
|
||||
|
||||
typedef struct feature_pattern{
|
||||
int type;
|
||||
@@ -1185,17 +1185,6 @@ extern void bubble_sort_double_inc_2(double *, int *, const int);
|
||||
@@ -1203,17 +1186,6 @@ extern void bubble_sort_double_inc_2(double *, int *, const int);
|
||||
extern void bubble_sort_double_dec_2(double *, int *, const int);
|
||||
extern void bubble_sort_int_inc(int *, const int);
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user