New upstream version 1.90.1

This commit is contained in:
Laurent Bigonville
2020-02-12 18:13:06 +01:00
122 changed files with 9905 additions and 3427 deletions
+35
View File
@@ -1,6 +1,41 @@
This file lists notable changes in each release. For the full history of all This file lists notable changes in each release. For the full history of all
changes, see ChangeLog. 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 2019-11-20: v1.90.0 release
This release updates the core of the library to use GLib routines and Gio This release updates the core of the library to use GLib routines and Gio
+8 -7
View File
@@ -22,9 +22,11 @@
#include <gtk/gtk.h> #include <gtk/gtk.h>
#include <libfprint/fprint.h> #include <libfprint/fprint.h>
typedef GtkApplication LibfprintDemo; struct _LibfprintDemo
typedef GtkApplicationClass LibfprintDemoClass; {
GtkApplication parent;
};
G_DECLARE_FINAL_TYPE (LibfprintDemo, libfprint_demo, FP, DEMO, GtkApplication)
G_DEFINE_TYPE (LibfprintDemo, libfprint_demo, GTK_TYPE_APPLICATION) G_DEFINE_TYPE (LibfprintDemo, libfprint_demo, GTK_TYPE_APPLICATION)
typedef enum { typedef enum {
@@ -33,7 +35,7 @@ typedef enum {
IMAGE_DISPLAY_BINARY = 1 << 1 IMAGE_DISPLAY_BINARY = 1 << 1
} ImageDisplayFlags; } ImageDisplayFlags;
typedef struct struct _LibfprintDemoWindow
{ {
GtkApplicationWindow parent_instance; GtkApplicationWindow parent_instance;
@@ -52,10 +54,9 @@ typedef struct
FpImage *img; FpImage *img;
ImageDisplayFlags img_flags; 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) G_DEFINE_TYPE (LibfprintDemoWindow, libfprint_demo_window, GTK_TYPE_APPLICATION_WINDOW)
typedef enum { typedef enum {
+12 -12
View File
@@ -1,21 +1,21 @@
gtk_test_resources = gnome.compile_resources('gtk-test-resources', 'gtk-libfprint-test.gresource.xml', gtk_test_resources = gnome.compile_resources('gtk-test-resources',
source_dir : '.', 'gtk-libfprint-test.gresource.xml',
c_name : 'gtk_test') source_dir : '.',
c_name : 'gtk_test')
prefix = get_option('prefix') prefix = get_option('prefix')
bindir = join_paths(prefix, get_option('bindir')) bindir = join_paths(prefix, get_option('bindir'))
datadir = join_paths(prefix, get_option('datadir')) datadir = join_paths(prefix, get_option('datadir'))
executable('gtk-libfprint-test', executable('gtk-libfprint-test',
[ 'gtk-libfprint-test.c', gtk_test_resources ], [ 'gtk-libfprint-test.c', gtk_test_resources ],
dependencies: [ libfprint_dep, gtk_dep ], dependencies: [
include_directories: [ gtk_dep,
root_inc, libfprint_dep,
], ],
c_args: [ common_cflags, c_args: '-DPACKAGE_VERSION="' + meson.project_version() + '"',
'-DPACKAGE_VERSION="' + meson.project_version() + '"' ], install: true,
install: true, install_dir: bindir)
install_dir: bindir)
appdata = 'org.freedesktop.libfprint.Demo.appdata.xml' appdata = 'org.freedesktop.libfprint.Demo.appdata.xml'
install_data(appdata, install_data(appdata,
+10 -3
View File
@@ -26,6 +26,7 @@ FpDeviceError
fp_device_retry_quark fp_device_retry_quark
fp_device_error_quark fp_device_error_quark
FpEnrollProgress FpEnrollProgress
FpMatchCb
fp_device_get_driver fp_device_get_driver
fp_device_get_device_id fp_device_get_device_id
fp_device_get_name fp_device_get_name
@@ -129,7 +130,7 @@ fpi_get_driver_types
<FILE>fpi-device</FILE> <FILE>fpi-device</FILE>
FpDeviceClass FpDeviceClass
FpTimeoutFunc FpTimeoutFunc
FpDeviceAction FpiDeviceAction
FpIdEntry FpIdEntry
fpi_device_get_usb_device fpi_device_get_usb_device
fpi_device_get_virtual_env fpi_device_get_virtual_env
@@ -159,6 +160,8 @@ fpi_device_identify_complete
fpi_device_capture_complete fpi_device_capture_complete
fpi_device_delete_complete fpi_device_delete_complete
fpi_device_enroll_progress fpi_device_enroll_progress
fpi_device_verify_report
fpi_device_identify_report
</SECTION> </SECTION>
<SECTION> <SECTION>
@@ -173,7 +176,7 @@ fpi_image_resize
<SECTION> <SECTION>
<FILE>fpi-image-device</FILE> <FILE>fpi-image-device</FILE>
<TITLE>FpImageDevice</TITLE> <TITLE>FpImageDevice</TITLE>
FpImageDeviceState FpiImageDeviceState
FpImageDeviceClass FpImageDeviceClass
fpi_image_device_session_error fpi_image_device_session_error
fpi_image_device_open_complete fpi_image_device_open_complete
@@ -197,7 +200,7 @@ BUG
<SECTION> <SECTION>
<FILE>fpi-print</FILE> <FILE>fpi-print</FILE>
FpPrintType FpiPrintType
FpiMatchResult FpiMatchResult
fpi_print_add_print fpi_print_add_print
fpi_print_set_type fpi_print_set_type
@@ -211,11 +214,15 @@ fpi_print_bz3_match
FpiSsmCompletedCallback FpiSsmCompletedCallback
FpiSsmHandlerCallback FpiSsmHandlerCallback
fpi_ssm_new fpi_ssm_new
fpi_ssm_new_full
fpi_ssm_free fpi_ssm_free
fpi_ssm_start fpi_ssm_start
fpi_ssm_start_subsm fpi_ssm_start_subsm
fpi_ssm_next_state fpi_ssm_next_state
fpi_ssm_next_state_delayed
fpi_ssm_jump_to_state fpi_ssm_jump_to_state
fpi_ssm_jump_to_state_delayed
fpi_ssm_cancel_delayed_state_change
fpi_ssm_mark_completed fpi_ssm_mark_completed
fpi_ssm_mark_failed fpi_ssm_mark_failed
fpi_ssm_set_data fpi_ssm_set_data
+1 -3
View File
@@ -90,7 +90,7 @@ fp_image_get_width
<TITLE>Base class for image devices</TITLE> <TITLE>Base class for image devices</TITLE>
FpImageDevice FpImageDevice
FpImageDeviceClass FpImageDeviceClass
FpImageDeviceState FpiImageDeviceState
</SECTION> </SECTION>
<SECTION> <SECTION>
@@ -114,5 +114,3 @@ FpUsbTransferCallback
FP_USB_ENDPOINT_IN FP_USB_ENDPOINT_IN
FP_USB_ENDPOINT_OUT FP_USB_ENDPOINT_OUT
</SECTION> </SECTION>
+20 -25
View File
@@ -1,14 +1,13 @@
subdir('xml') subdir('xml')
private_headers = [ private_headers = [
'config.h', 'config.h',
'nbis-helpers.h', 'nbis-helpers.h',
'fprint.h', 'fprint.h',
'fp_internal.h',
# Subdirectories to ignore # Subdirectories to ignore
'drivers', 'drivers',
'nbis', 'nbis',
] ]
html_images = [ html_images = [
@@ -24,21 +23,17 @@ glib_prefix = dependency('glib-2.0').get_pkgconfig_variable('prefix')
glib_docpath = join_paths(glib_prefix, 'share', 'gtk-doc', 'html') glib_docpath = join_paths(glib_prefix, 'share', 'gtk-doc', 'html')
docpath = join_paths(get_option('datadir'), 'gtk-doc', 'html') docpath = join_paths(get_option('datadir'), 'gtk-doc', 'html')
gnome.gtkdoc('libfprint', gnome.gtkdoc(versioned_libname,
main_xml: 'libfprint-docs.xml', main_xml: 'libfprint-docs.xml',
src_dir: join_paths(meson.source_root(), 'libfprint'), src_dir: join_paths(meson.source_root(), 'libfprint'),
dependencies: libfprint_dep, dependencies: libfprint_dep,
content_files: content_files, content_files: content_files,
expand_content_files: expand_content_files, expand_content_files: expand_content_files,
scan_args: [ ignore_headers: private_headers,
#'--rebuild-sections', fixxref_args: [
'--ignore-decorators=API_EXPORTED', '--html-dir=@0@'.format(docpath),
'--ignore-headers=' + ' '.join(private_headers), '--extra-dir=@0@'.format(join_paths(glib_docpath, 'glib')),
], '--extra-dir=@0@'.format(join_paths(glib_docpath, 'gobject')),
fixxref_args: [ ],
'--html-dir=@0@'.format(docpath), html_assets: html_images,
'--extra-dir=@0@'.format(join_paths(glib_docpath, 'glib')), install: true)
'--extra-dir=@0@'.format(join_paths(glib_docpath, 'gobject')),
],
html_assets: html_images,
install: true)
+6 -4
View File
@@ -1,10 +1,12 @@
ent_conf = configuration_data() 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_BUGREPORT', 'https://gitlab.freedesktop.org/libfprint/libfprint/issues')
ent_conf.set('PACKAGE_NAME', 'libfprint') ent_conf.set('PACKAGE_NAME', versioned_libname)
ent_conf.set('PACKAGE_STRING', 'libfprint') ent_conf.set('PACKAGE_STRING', versioned_libname)
ent_conf.set('PACKAGE_TARNAME', 'libfprint-' + meson.project_version()) ent_conf.set('PACKAGE_TARNAME', 'libfprint-' + meson.project_version())
ent_conf.set('PACKAGE_URL', 'https://fprint.freedesktop.org/') ent_conf.set('PACKAGE_URL', 'https://fprint.freedesktop.org/')
ent_conf.set('PACKAGE_VERSION', meson.project_version()) ent_conf.set('PACKAGE_VERSION', meson.project_version())
ent_conf.set('PACKAGE_API_VERSION', '1.0') 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)
+4 -4
View File
@@ -6,10 +6,10 @@
int main (int argc, char **argv) int main (int argc, char **argv)
{ {
FpContext *ctx; FpContext *ctx;
ctx = fp_context_new (); ctx = fp_context_new ();
g_object_unref (ctx); g_object_unref (ctx);
return 0; return 0;
} }
+2
View File
@@ -19,6 +19,8 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
#define FP_COMPONENT "example-enroll"
#include <stdio.h> #include <stdio.h>
#include <libfprint/fprint.h> #include <libfprint/fprint.h>
+13 -9
View File
@@ -18,6 +18,8 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
#define FP_COMPONENT "example-mange-prints"
#include <stdio.h> #include <stdio.h>
#include <libfprint/fprint.h> #include <libfprint/fprint.h>
@@ -153,14 +155,19 @@ on_list_completed (FpDevice *dev,
for (i = 0; i < prints->len; ++i) for (i = 0; i < prints->len; ++i)
{ {
FpPrint * print = prints->pdata[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", g_print ("[%d] Print of %s finger for username %s", i + 1,
fp_print_get_enroll_date (print));
g_print ("[%d] Print of %s finger for username %s, enrolled "
"on %s. Description: %s\n", i + 1,
finger_to_string (fp_print_get_finger (print)), finger_to_string (fp_print_get_finger (print)),
fp_print_get_username (print), buf, fp_print_get_username (print));
fp_print_get_description (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) if (prints->len)
@@ -192,9 +199,6 @@ on_list_completed (FpDevice *dev,
list_data->ret_value = EXIT_SUCCESS; list_data->ret_value = EXIT_SUCCESS;
else else
g_warning ("Invalid finger selected"); g_warning ("Invalid finger selected");
fp_device_close (dev, NULL, (GAsyncReadyCallback) on_device_closed,
list_data);
} }
} }
+9 -12
View File
@@ -2,18 +2,15 @@
examples = [ 'enroll', 'verify', 'manage-prints' ] examples = [ 'enroll', 'verify', 'manage-prints' ]
foreach example: examples foreach example: examples
executable(example, executable(example,
[example + '.c', 'storage.c', 'utilities.c'], [ example + '.c', 'storage.c', 'utilities.c' ],
dependencies: [libfprint_dep, glib_dep], dependencies: [
include_directories: [ libfprint_dep,
root_inc, glib_dep,
], ],
c_args: common_cflags) )
endforeach endforeach
executable('cpp-test', executable('cpp-test',
'cpp-test.cpp', 'cpp-test.cpp',
dependencies: libfprint_dep, dependencies: libfprint_dep,
include_directories: [ )
root_inc,
],
c_args: common_cflags)
+16 -8
View File
@@ -19,7 +19,11 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
#define FP_COMPONENT "example-storage"
#include <libfprint/fprint.h> #include <libfprint/fprint.h>
#include <libfprint/fpi-compat.h>
#include "storage.h"
#include <errno.h> #include <errno.h>
#include <stdio.h> #include <stdio.h>
@@ -56,8 +60,8 @@ load_data (void)
{ {
GVariantDict *res; GVariantDict *res;
GVariant *var; GVariant *var;
g_autofree gchar *contents = NULL; gchar *contents = NULL;
gssize length = 0; gsize length = 0;
if (!g_file_get_contents (STORAGE_FILE, &contents, &length, NULL)) if (!g_file_get_contents (STORAGE_FILE, &contents, &length, NULL))
{ {
@@ -65,7 +69,12 @@ load_data (void)
return g_variant_dict_new (NULL); 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); res = g_variant_dict_new (var);
g_variant_unref (var); g_variant_unref (var);
@@ -128,7 +137,7 @@ print_data_load (FpDevice *dev, FpFinger finger)
g_autoptr(GVariant) val = NULL; g_autoptr(GVariant) val = NULL;
g_autoptr(GVariantDict) dict = NULL; g_autoptr(GVariantDict) dict = NULL;
g_autofree guchar *stored_data = NULL; const guchar *stored_data = NULL;
gsize stored_len; gsize stored_len;
dict = load_data (); dict = load_data ();
@@ -139,7 +148,7 @@ print_data_load (FpDevice *dev, FpFinger finger)
FpPrint *print; FpPrint *print;
g_autoptr(GError) error = NULL; 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); print = fp_print_deserialize (stored_data, stored_len, &error);
if (error) if (error)
@@ -155,8 +164,8 @@ FpPrint *
print_create_template (FpDevice *dev, FpFinger finger) print_create_template (FpDevice *dev, FpFinger finger)
{ {
g_autoptr(GDateTime) datetime = NULL; g_autoptr(GDateTime) datetime = NULL;
g_autoptr(GDate) date = NULL;
FpPrint *template = NULL; FpPrint *template = NULL;
GDate *date = NULL;
gint year, month, day; gint year, month, day;
template = fp_print_new (dev); 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); g_date_time_get_ymd (datetime, &year, &month, &day);
date = g_date_new_dmy (day, month, year); date = g_date_new_dmy (day, month, year);
fp_print_set_enroll_date (template, date); fp_print_set_enroll_date (template, date);
g_date_free (date);
return template; return template;
} }
@@ -212,7 +220,7 @@ save_image_to_pgm (FpImage *img, const char *path)
gboolean gboolean
print_image_save (FpPrint *print, const char *path) 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 (FP_IS_PRINT (print), FALSE);
g_return_val_if_fail (path != NULL, FALSE); g_return_val_if_fail (path != NULL, FALSE);
+1 -5
View File
@@ -18,9 +18,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
#ifndef __STORAGE_H #pragma once
#define __STORAGE_H
int print_data_save (FpPrint *print, int print_data_save (FpPrint *print,
FpFinger finger); FpFinger finger);
@@ -30,5 +28,3 @@ FpPrint * print_create_template (FpDevice *dev,
FpFinger finger); FpFinger finger);
gboolean print_image_save (FpPrint *print, gboolean print_image_save (FpPrint *print,
const char *path); const char *path);
#endif /* __STORAGE_H */
+9 -17
View File
@@ -18,6 +18,8 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
#define FP_COMPONENT "example-utilities"
#include <libfprint/fprint.h> #include <libfprint/fprint.h>
#include <stdio.h> #include <stdio.h>
@@ -107,29 +109,19 @@ finger_to_string (FpFinger finger)
FpFinger FpFinger
finger_chooser (void) finger_chooser (void)
{ {
int i; int i = FP_FINGER_UNKNOWN;
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,
};
for (i = all_fingers[0]; i <= G_N_ELEMENTS (all_fingers); ++i) for (i = FP_FINGER_FIRST; i <= FP_FINGER_LAST; ++i)
g_print (" [%d] %s\n", (i - all_fingers[0]), finger_to_string (i)); g_print (" [%d] %s\n", (i - FP_FINGER_FIRST), finger_to_string (i));
g_print ("> "); g_print ("> ");
if (!scanf ("%d%*c", &i)) if (!scanf ("%d%*c", &i))
return FP_FINGER_UNKNOWN; 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 FP_FINGER_UNKNOWN;
return all_fingers[i]; return i;
} }
+1 -4
View File
@@ -18,11 +18,8 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
#ifndef __UTILITIES_H #pragma once
#define __UTILITIES_H
FpDevice * discover_device (GPtrArray *devices); FpDevice * discover_device (GPtrArray *devices);
FpFinger finger_chooser (void); FpFinger finger_chooser (void);
const char * finger_to_string (FpFinger finger); const char * finger_to_string (FpFinger finger);
#endif /* __UTILITIES_H */
+85 -30
View File
@@ -19,6 +19,8 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
#define FP_COMPONENT "example-verify"
#include <stdio.h> #include <stdio.h>
#include <libfprint/fprint.h> #include <libfprint/fprint.h>
@@ -55,6 +57,19 @@ on_device_closed (FpDevice *dev, GAsyncResult *res, void *user_data)
g_main_loop_quit (verify_data->loop); 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, static void start_verification (FpDevice *dev,
VerifyData *verify_data); VerifyData *verify_data);
@@ -71,35 +86,65 @@ on_verify_completed (FpDevice *dev, GAsyncResult *res, void *user_data)
if (!fp_device_verify_finish (dev, res, &match, &print, &error)) if (!fp_device_verify_finish (dev, res, &match, &print, &error))
{ {
g_warning ("Failed to verify print: %s", error->message); g_warning ("Failed to verify print: %s", error->message);
g_main_loop_quit (verify_data->loop);
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; verify_data->ret_value = EXIT_FAILURE;
if (error->domain != FP_DEVICE_RETRY)
{
verify_quit (dev, verify_data);
return;
}
} }
g_print ("Verify again? [Y/n]? "); g_print ("Verify again? [Y/n]? ");
if (fgets (buffer, sizeof (buffer), stdin) && 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); start_verification (dev, verify_data);
return; return;
} }
fp_device_close (dev, NULL, (GAsyncReadyCallback) on_device_closed, verify_quit (dev, verify_data);
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 static void
@@ -127,9 +172,14 @@ on_list_completed (FpDevice *dev, GAsyncResult *res, gpointer user_data)
if (fp_print_get_finger (print) == verify_data->finger && if (fp_print_get_finger (print) == verify_data->finger &&
g_strcmp0 (fp_print_get_username (print), g_get_user_name ()) == 0) g_strcmp0 (fp_print_get_username (print), g_get_user_name ()) == 0)
{ {
if (!verify_print || const GDate *verify_print_date = NULL;
(g_date_compare (fp_print_get_enroll_date (print), const GDate *print_date = fp_print_get_enroll_date (print);
fp_print_get_enroll_date (verify_print)) >= 0))
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; verify_print = print;
} }
} }
@@ -138,7 +188,7 @@ on_list_completed (FpDevice *dev, GAsyncResult *res, gpointer user_data)
{ {
g_warning ("Did you remember to enroll your %s finger first?", g_warning ("Did you remember to enroll your %s finger first?",
finger_to_string (verify_data->finger)); finger_to_string (verify_data->finger));
g_main_loop_quit (verify_data->loop); verify_quit (dev, verify_data);
return; return;
} }
@@ -147,27 +197,31 @@ on_list_completed (FpDevice *dev, GAsyncResult *res, gpointer user_data)
g_print ("Print loaded. Time to verify!\n"); g_print ("Print loaded. Time to verify!\n");
fp_device_verify (dev, verify_print, NULL, fp_device_verify (dev, verify_print, NULL,
on_match_cb, verify_data, NULL,
(GAsyncReadyCallback) on_verify_completed, (GAsyncReadyCallback) on_verify_completed,
verify_data); verify_data);
} }
else else
{ {
g_warning ("Loading prints failed with error %s", error->message); g_warning ("Loading prints failed with error %s", error->message);
g_main_loop_quit (verify_data->loop); verify_quit (dev, verify_data);
} }
} }
static void static void
start_verification (FpDevice *dev, VerifyData *verify_data) start_verification (FpDevice *dev, VerifyData *verify_data)
{ {
g_print ("Choose the finger to verify:\n"); if (verify_data->finger == FP_FINGER_UNKNOWN)
verify_data->finger = finger_chooser (); {
g_print ("Choose the finger to verify:\n");
verify_data->finger = finger_chooser ();
}
if (verify_data->finger == FP_FINGER_UNKNOWN) if (verify_data->finger == FP_FINGER_UNKNOWN)
{ {
g_warning ("Unknown finger selected"); g_warning ("Unknown finger selected");
verify_data->ret_value = EXIT_FAILURE; verify_data->ret_value = EXIT_FAILURE;
g_main_loop_quit (verify_data->loop); verify_quit (dev, verify_data);
return; return;
} }
@@ -182,7 +236,7 @@ start_verification (FpDevice *dev, VerifyData *verify_data)
{ {
g_print ("Loading previously enrolled %s finger data...\n", g_print ("Loading previously enrolled %s finger data...\n",
finger_to_string (verify_data->finger)); 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); verify_print = print_data_load (dev, verify_data->finger);
@@ -191,12 +245,13 @@ start_verification (FpDevice *dev, VerifyData *verify_data)
g_warning ("Failed to load fingerprint data"); g_warning ("Failed to load fingerprint data");
g_warning ("Did you remember to enroll your %s finger first?", g_warning ("Did you remember to enroll your %s finger first?",
finger_to_string (verify_data->finger)); finger_to_string (verify_data->finger));
g_main_loop_quit (verify_data->loop); verify_quit (dev, verify_data);
return; return;
} }
g_print ("Print loaded. Time to verify!\n"); g_print ("Print loaded. Time to verify!\n");
fp_device_verify (dev, verify_print, NULL, fp_device_verify (dev, verify_print, NULL,
NULL, NULL, NULL,
(GAsyncReadyCallback) on_verify_completed, (GAsyncReadyCallback) on_verify_completed,
verify_data); verify_data);
} }
@@ -212,7 +267,7 @@ on_device_opened (FpDevice *dev, GAsyncResult *res, void *user_data)
if (!fp_device_open_finish (dev, res, &error)) if (!fp_device_open_finish (dev, res, &error))
{ {
g_warning ("Failed to open device: %s", error->message); g_warning ("Failed to open device: %s", error->message);
g_main_loop_quit (verify_data->loop); verify_quit (dev, verify_data);
return; return;
} }
+1 -18
View File
@@ -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 static void
generic_write_regv_cb (FpImageDevice *dev, GError *error, generic_write_regv_cb (FpImageDevice *dev, GError *error,
void *user_data) void *user_data)
@@ -154,8 +142,7 @@ generic_read_ignore_data (FpiSsm *ssm, FpDevice *dev,
transfer->ssm = ssm; transfer->ssm = ssm;
transfer->short_is_error = TRUE; transfer->short_is_error = TRUE;
fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL, fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
generic_ignore_data_cb, NULL); fpi_ssm_usb_transfer_cb, NULL);
fpi_usb_transfer_unref (transfer);
} }
/****** FINGER PRESENCE DETECTION ******/ /****** FINGER PRESENCE DETECTION ******/
@@ -238,7 +225,6 @@ finger_det_reqs_cb (FpImageDevice *dev, GError *error,
transfer->short_is_error = TRUE; transfer->short_is_error = TRUE;
fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL, fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
finger_det_data_cb, NULL); finger_det_data_cb, NULL);
fpi_usb_transfer_unref (transfer);
} }
static void static void
@@ -683,7 +669,6 @@ capture_run_state (FpiSsm *ssm, FpDevice *_dev)
transfer->short_is_error = TRUE; transfer->short_is_error = TRUE;
fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL, fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
capture_read_strip_cb, NULL); capture_read_strip_cb, NULL);
fpi_usb_transfer_unref (transfer);
break; break;
} }
; ;
@@ -710,7 +695,6 @@ capture_sm_complete (FpiSsm *ssm, FpDevice *_dev, GError *error)
{ {
start_finger_detection (dev); start_finger_detection (dev);
} }
fpi_ssm_free (ssm);
} }
static void static void
@@ -774,7 +758,6 @@ activate_sm_complete (FpiSsm *ssm, FpDevice *_dev, GError *error)
if (!error) if (!error)
start_finger_detection (dev); start_finger_detection (dev);
fpi_ssm_free (ssm);
} }
static void static void
+1 -4
View File
@@ -18,8 +18,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
#ifndef __AES1660_H #pragma once
#define __AES1660_H
#define AES1660_FRAME_SIZE 0x244 #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, 0x55, 0x07, 0x00, 0x80, 0x42, 0x00, 0x7f, 0x00, 0x00, 0x14,
0x49, 0x03, 0x00, 0x20, 0x00, 0xc8 0x49, 0x03, 0x00, 0x20, 0x00, 0xc8
}; };
#endif
+2 -21
View File
@@ -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_fill_bulk (transfer, EP_IN, READ_REGS_LEN);
fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL, fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
read_regs_data_cb, rdata); read_regs_data_cb, rdata);
fpi_usb_transfer_unref (transfer);
} }
static void static void
@@ -183,19 +182,6 @@ generic_write_regv_cb (FpImageDevice *dev, GError *error,
fpi_ssm_mark_failed (ssm, 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 /* read the specified number of bytes from the IN endpoint but throw them
* away, then increment the SSM */ * away, then increment the SSM */
static void static void
@@ -209,8 +195,7 @@ generic_read_ignore_data (FpiSsm *ssm, FpDevice *dev,
transfer->short_is_error = TRUE; transfer->short_is_error = TRUE;
fpi_usb_transfer_fill_bulk (transfer, EP_IN, bytes); fpi_usb_transfer_fill_bulk (transfer, EP_IN, bytes);
fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL, fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
generic_ignore_data_cb, NULL); fpi_ssm_usb_transfer_cb, NULL);
fpi_usb_transfer_unref (transfer);
} }
/****** IMAGE PROCESSING ******/ /****** 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_fill_bulk (transfer, EP_IN, FINGER_DETECTION_LEN);
fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL, fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
finger_det_data_cb, NULL); finger_det_data_cb, NULL);
fpi_usb_transfer_unref (transfer);
} }
static void static void
@@ -547,7 +531,6 @@ capture_run_state (FpiSsm *ssm, FpDevice *device)
fpi_usb_transfer_fill_bulk (transfer, EP_IN, STRIP_CAPTURE_LEN); fpi_usb_transfer_fill_bulk (transfer, EP_IN, STRIP_CAPTURE_LEN);
fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL, fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
capture_read_strip_cb, NULL); capture_read_strip_cb, NULL);
fpi_usb_transfer_unref (transfer);
break; break;
} }
} }
@@ -575,7 +558,6 @@ capture_sm_complete (FpiSsm *ssm, FpDevice *_dev, GError *error)
{ {
start_finger_detection (dev); start_finger_detection (dev);
} }
fpi_ssm_free (ssm);
} }
static void static void
@@ -704,7 +686,7 @@ enum activate_states {
ACTIVATE_NUM_STATES, ACTIVATE_NUM_STATES,
}; };
void static void
activate_read_regs_cb (FpImageDevice *dev, GError *error, activate_read_regs_cb (FpImageDevice *dev, GError *error,
unsigned char *regs, void *user_data) unsigned char *regs, void *user_data)
{ {
@@ -806,7 +788,6 @@ activate_sm_complete (FpiSsm *ssm, FpDevice *dev, GError *error)
if (!error) if (!error)
start_finger_detection (FP_IMAGE_DEVICE (dev)); start_finger_detection (FP_IMAGE_DEVICE (dev));
fpi_ssm_free (ssm);
} }
static void static void
+1 -4
View File
@@ -19,8 +19,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
#ifndef __AES2501_H #pragma once
#define __AES2501_H
enum aes2501_regs { enum aes2501_regs {
AES2501_REG_CTRL1 = 0x80, AES2501_REG_CTRL1 = 0x80,
@@ -172,5 +171,3 @@ enum aes2501_sensor_gain2 {
#define AES2501_SUM_HIGH_THRESH 1000 #define AES2501_SUM_HIGH_THRESH 1000
#define AES2501_SUM_LOW_THRESH 700 #define AES2501_SUM_LOW_THRESH 700
#endif /* __AES2501_H */
+5 -49
View File
@@ -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_fill_bulk (transfer, EP_IN, AES2550_EP_IN_BUF_SIZE);
fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL, fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
finger_det_data_cb, NULL); finger_det_data_cb, NULL);
fpi_usb_transfer_unref (transfer);
} }
static void static void
@@ -157,7 +156,6 @@ start_finger_detection (FpImageDevice *dev)
sizeof (finger_det_reqs), NULL); sizeof (finger_det_reqs), NULL);
fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL, fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
finger_det_reqs_cb, NULL); finger_det_reqs_cb, NULL);
fpi_usb_transfer_unref (transfer);
} }
/****** CAPTURE ******/ /****** CAPTURE ******/
@@ -218,16 +216,6 @@ process_strip_data (FpiSsm *ssm, FpImageDevice *dev,
return TRUE; 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 static void
capture_set_idle_reqs_cb (FpiUsbTransfer *transfer, capture_set_idle_reqs_cb (FpiUsbTransfer *transfer,
FpDevice *device, gpointer user_data, FpDevice *device, gpointer user_data,
@@ -334,8 +322,7 @@ capture_run_state (FpiSsm *ssm, FpDevice *dev)
transfer->ssm = ssm; transfer->ssm = ssm;
transfer->short_is_error = TRUE; transfer->short_is_error = TRUE;
fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL, fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
capture_reqs_cb, NULL); fpi_ssm_usb_transfer_cb, NULL);
fpi_usb_transfer_unref (transfer);
} }
break; break;
@@ -347,7 +334,6 @@ capture_run_state (FpiSsm *ssm, FpDevice *dev)
transfer->ssm = ssm; transfer->ssm = ssm;
fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL, fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
capture_read_data_cb, NULL); capture_read_data_cb, NULL);
fpi_usb_transfer_unref (transfer);
} }
break; break;
@@ -363,7 +349,6 @@ capture_run_state (FpiSsm *ssm, FpDevice *dev)
transfer->short_is_error = TRUE; transfer->short_is_error = TRUE;
fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL, fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
capture_set_idle_reqs_cb, NULL); capture_set_idle_reqs_cb, NULL);
fpi_usb_transfer_unref (transfer);
} }
break; break;
} }
@@ -391,7 +376,6 @@ capture_sm_complete (FpiSsm *ssm, FpDevice *_dev, GError *error)
{ {
start_finger_detection (dev); start_finger_detection (dev);
} }
fpi_ssm_free (ssm);
} }
static void static void
@@ -436,36 +420,13 @@ enum activate_states {
ACTIVATE_NUM_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 /* TODO: use calibration table, datasheet is rather terse on that
* need more info for implementation */ * need more info for implementation */
static void static void
calibrate_read_data_cb (FpiUsbTransfer *transfer, FpDevice *device, calibrate_read_data_cb (FpiUsbTransfer *transfer, FpDevice *device,
gpointer user_data, GError *error) gpointer user_data, GError *error)
{ {
if (!error) fpi_ssm_usb_transfer_cb (transfer, device, user_data, error);
fpi_ssm_next_state (transfer->ssm);
else
fpi_ssm_mark_failed (transfer->ssm, error);
} }
static void static void
@@ -482,8 +443,7 @@ activate_run_state (FpiSsm *ssm, FpDevice *dev)
transfer->ssm = ssm; transfer->ssm = ssm;
transfer->short_is_error = TRUE; transfer->short_is_error = TRUE;
fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL, fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
init_reqs_cb, NULL); fpi_ssm_usb_transfer_cb, NULL);
fpi_usb_transfer_unref (transfer);
} }
break; break;
@@ -494,8 +454,7 @@ activate_run_state (FpiSsm *ssm, FpDevice *dev)
fpi_usb_transfer_fill_bulk (transfer, EP_IN, AES2550_EP_IN_BUF_SIZE); fpi_usb_transfer_fill_bulk (transfer, EP_IN, AES2550_EP_IN_BUF_SIZE);
transfer->ssm = ssm; transfer->ssm = ssm;
fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL, fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
init_read_data_cb, NULL); fpi_ssm_usb_transfer_cb, NULL);
fpi_usb_transfer_unref (transfer);
} }
break; break;
@@ -509,8 +468,7 @@ activate_run_state (FpiSsm *ssm, FpDevice *dev)
transfer->ssm = ssm; transfer->ssm = ssm;
transfer->short_is_error = TRUE; transfer->short_is_error = TRUE;
fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL, fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
init_reqs_cb, NULL); fpi_ssm_usb_transfer_cb, NULL);
fpi_usb_transfer_unref (transfer);
} }
break; break;
@@ -522,7 +480,6 @@ activate_run_state (FpiSsm *ssm, FpDevice *dev)
transfer->ssm = ssm; transfer->ssm = ssm;
fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL, fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
calibrate_read_data_cb, NULL); calibrate_read_data_cb, NULL);
fpi_usb_transfer_unref (transfer);
} }
break; break;
} }
@@ -537,7 +494,6 @@ activate_sm_complete (FpiSsm *ssm, FpDevice *_dev, GError *error)
if (!error) if (!error)
start_finger_detection (dev); start_finger_detection (dev);
fpi_ssm_free (ssm);
} }
static void static void
+1 -4
View File
@@ -17,8 +17,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
#ifndef __AES2550_H #pragma once
#define __AES2550_H
/* Registers bits */ /* Registers bits */
@@ -110,5 +109,3 @@ enum aes2550_cmds {
#define AES2550_HEARTBEAT_MAGIC 0xdb #define AES2550_HEARTBEAT_MAGIC 0xdb
#define AES2550_EP_IN_BUF_SIZE 8192 #define AES2550_EP_IN_BUF_SIZE 8192
#endif
+1 -4
View File
@@ -17,8 +17,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
#ifndef __AES2660_H #pragma once
#define __AES2660_H
#define AES2660_FRAME_SIZE 0x354 #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, 0x55, 0x07, 0x00, 0x80, 0x42, 0x00, 0xbf, 0x00, 0x00, 0x18,
0x49, 0x03, 0x00, 0x20, 0x08, 0xc8 0x49, 0x03, 0x00, 0x20, 0x08, 0xc8
}; };
#endif
-1
View File
@@ -142,7 +142,6 @@ do_capture (FpImageDevice *dev)
fpi_usb_transfer_submit (priv->img_trf, 0, fpi_usb_transfer_submit (priv->img_trf, 0,
fpi_device_get_cancellable (FP_DEVICE (dev)), fpi_device_get_cancellable (FP_DEVICE (dev)),
img_cb, NULL); img_cb, NULL);
fpi_usb_transfer_unref (priv->img_trf);
} }
static void static void
+1 -4
View File
@@ -19,13 +19,11 @@
#define FP_COMPONENT "aeslib" #define FP_COMPONENT "aeslib"
#include "fp_internal.h" #include "drivers_api.h"
#include <errno.h> #include <errno.h>
#include <string.h> #include <string.h>
#include "fpi-usb-transfer.h"
#include "fpi-assembling.h"
#include "aeslib.h" #include "aeslib.h"
#define MAX_REGWRITES_PER_REQUEST 16 #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; transfer->short_is_error = TRUE;
fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL, fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
write_regv_trf_complete, wdata); 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, /* write the next batch of registers to be written, or if there are no more,
+1 -4
View File
@@ -17,8 +17,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
#ifndef __AESLIB_H__ #pragma once
#define __AESLIB_H__
#include <fprint.h> #include <fprint.h>
@@ -45,5 +44,3 @@ unsigned char aes_get_pixel (struct fpi_frame_asmbl_ctx *ctx,
struct fpi_frame *frame, struct fpi_frame *frame,
unsigned int x, unsigned int x,
unsigned int y); unsigned int y);
#endif
+19 -28
View File
@@ -68,7 +68,6 @@ aesX660_send_cmd_timeout (FpiSsm *ssm,
cmd_len, NULL); cmd_len, NULL);
transfer->ssm = ssm; transfer->ssm = ssm;
fpi_usb_transfer_submit (transfer, timeout, NULL, callback, NULL); fpi_usb_transfer_submit (transfer, timeout, NULL, callback, NULL);
fpi_usb_transfer_unref (transfer);
} }
static void static void
@@ -100,17 +99,6 @@ aesX660_read_response (FpiSsm *ssm,
transfer->ssm = ssm; transfer->ssm = ssm;
transfer->short_is_error = short_is_error; transfer->short_is_error = short_is_error;
fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, cancel, callback, NULL); 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 static void
@@ -131,7 +119,9 @@ aesX660_read_calibrate_data_cb (FpiUsbTransfer *transfer,
fp_dbg ("Bogus calibrate response: %.2x\n", data[0]); fp_dbg ("Bogus calibrate response: %.2x\n", data[0]);
fpi_ssm_mark_failed (transfer->ssm, fpi_ssm_mark_failed (transfer->ssm,
fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO, fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
"Bogus calibrate response")); "Bogus calibrate "
"response: %.2x",
data[0]));
return; return;
} }
@@ -175,7 +165,8 @@ finger_det_read_fd_data_cb (FpiUsbTransfer *transfer,
fp_dbg ("Bogus FD response: %.2x\n", data[0]); fp_dbg ("Bogus FD response: %.2x\n", data[0]);
fpi_ssm_mark_failed (transfer->ssm, fpi_ssm_mark_failed (transfer->ssm,
fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO, fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
"Bogus FD response")); "Bogus FD response %.2x",
data[0]));
return; return;
} }
@@ -212,7 +203,6 @@ finger_det_sm_complete (FpiSsm *ssm, FpDevice *_dev, GError *error)
fp_dbg ("Finger detection completed"); fp_dbg ("Finger detection completed");
fpi_image_device_report_finger_status (dev, TRUE); fpi_image_device_report_finger_status (dev, TRUE);
fpi_ssm_free (ssm);
if (priv->deactivating) if (priv->deactivating)
{ {
@@ -238,12 +228,12 @@ finger_det_run_state (FpiSsm *ssm, FpDevice *dev)
{ {
case FINGER_DET_SEND_LED_CMD: case FINGER_DET_SEND_LED_CMD:
aesX660_send_cmd (ssm, dev, led_blink_cmd, sizeof (led_blink_cmd), aesX660_send_cmd (ssm, dev, led_blink_cmd, sizeof (led_blink_cmd),
aesX660_send_cmd_cb); fpi_ssm_usb_transfer_cb);
break; break;
case FINGER_DET_SEND_FD_CMD: case FINGER_DET_SEND_FD_CMD:
aesX660_send_cmd_timeout (ssm, dev, wait_for_finger_cmd, sizeof (wait_for_finger_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; break;
case FINGER_DET_READ_FD_DATA: case FINGER_DET_READ_FD_DATA:
@@ -433,14 +423,14 @@ capture_run_state (FpiSsm *ssm, FpDevice *_dev)
{ {
case CAPTURE_SEND_LED_CMD: case CAPTURE_SEND_LED_CMD:
aesX660_send_cmd (ssm, _dev, led_solid_cmd, sizeof (led_solid_cmd), aesX660_send_cmd (ssm, _dev, led_solid_cmd, sizeof (led_solid_cmd),
aesX660_send_cmd_cb); fpi_ssm_usb_transfer_cb);
break; break;
case CAPTURE_SEND_CAPTURE_CMD: case CAPTURE_SEND_CAPTURE_CMD:
g_byte_array_set_size (priv->stripe_packet, 0); g_byte_array_set_size (priv->stripe_packet, 0);
aesX660_send_cmd (ssm, _dev, cls->start_imaging_cmd, aesX660_send_cmd (ssm, _dev, cls->start_imaging_cmd,
cls->start_imaging_cmd_len, cls->start_imaging_cmd_len,
aesX660_send_cmd_cb); fpi_ssm_usb_transfer_cb);
break; break;
case CAPTURE_READ_STRIPE_DATA: case CAPTURE_READ_STRIPE_DATA:
@@ -463,7 +453,6 @@ capture_sm_complete (FpiSsm *ssm, FpDevice *device, GError *error)
FpiDeviceAesX660Private *priv = fpi_device_aes_x660_get_instance_private (self); FpiDeviceAesX660Private *priv = fpi_device_aes_x660_get_instance_private (self);
fp_dbg ("Capture completed"); fp_dbg ("Capture completed");
fpi_ssm_free (ssm);
if (priv->deactivating) if (priv->deactivating)
{ {
@@ -538,7 +527,8 @@ activate_read_id_cb (FpiUsbTransfer *transfer, FpDevice *device,
fp_dbg ("Bogus read ID response: %.2x\n", data[AESX660_RESPONSE_TYPE_OFFSET]); fp_dbg ("Bogus read ID response: %.2x\n", data[AESX660_RESPONSE_TYPE_OFFSET]);
fpi_ssm_mark_failed (transfer->ssm, fpi_ssm_mark_failed (transfer->ssm,
fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO, fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
"Bogus read ID response")); "Bogus read ID response %.2x",
data[AESX660_RESPONSE_TYPE_OFFSET]));
return; return;
} }
@@ -565,7 +555,8 @@ activate_read_id_cb (FpiUsbTransfer *transfer, FpDevice *device,
fp_dbg ("Failed to init device! init status: %.2x\n", data[7]); fp_dbg ("Failed to init device! init status: %.2x\n", data[7]);
fpi_ssm_mark_failed (transfer->ssm, fpi_ssm_mark_failed (transfer->ssm,
fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO, fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
"Failed to init device")); "Failed to init device %.2x",
data[7]));
break; break;
} }
} }
@@ -594,7 +585,8 @@ activate_read_init_cb (FpiUsbTransfer *transfer, FpDevice *device,
data[3]); data[3]);
fpi_ssm_mark_failed (transfer->ssm, fpi_ssm_mark_failed (transfer->ssm,
fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO, fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
"Bogus read init response")); "Bogus read init response: "
"%.2x %.2x", data[0], data[3]));
return; return;
} }
priv->init_cmd_idx++; priv->init_cmd_idx++;
@@ -623,13 +615,13 @@ activate_run_state (FpiSsm *ssm, FpDevice *_dev)
priv->init_seq_idx = 0; priv->init_seq_idx = 0;
fp_dbg ("Activate: set idle\n"); fp_dbg ("Activate: set idle\n");
aesX660_send_cmd (ssm, _dev, set_idle_cmd, sizeof (set_idle_cmd), aesX660_send_cmd (ssm, _dev, set_idle_cmd, sizeof (set_idle_cmd),
aesX660_send_cmd_cb); fpi_ssm_usb_transfer_cb);
break; break;
case ACTIVATE_SEND_READ_ID_CMD: case ACTIVATE_SEND_READ_ID_CMD:
fp_dbg ("Activate: read ID\n"); fp_dbg ("Activate: read ID\n");
aesX660_send_cmd (ssm, _dev, read_id_cmd, sizeof (read_id_cmd), aesX660_send_cmd (ssm, _dev, read_id_cmd, sizeof (read_id_cmd),
aesX660_send_cmd_cb); fpi_ssm_usb_transfer_cb);
break; break;
case ACTIVATE_READ_ID: case ACTIVATE_READ_ID:
@@ -643,7 +635,7 @@ activate_run_state (FpiSsm *ssm, FpDevice *_dev)
aesX660_send_cmd (ssm, _dev, aesX660_send_cmd (ssm, _dev,
priv->init_seq[priv->init_cmd_idx].cmd, priv->init_seq[priv->init_cmd_idx].cmd,
priv->init_seq[priv->init_cmd_idx].len, priv->init_seq[priv->init_cmd_idx].len,
aesX660_send_cmd_cb); fpi_ssm_usb_transfer_cb);
break; break;
case ACTIVATE_READ_INIT_RESPONSE: case ACTIVATE_READ_INIT_RESPONSE:
@@ -653,7 +645,7 @@ activate_run_state (FpiSsm *ssm, FpDevice *_dev)
case ACTIVATE_SEND_CALIBRATE_CMD: case ACTIVATE_SEND_CALIBRATE_CMD:
aesX660_send_cmd (ssm, _dev, calibrate_cmd, sizeof (calibrate_cmd), aesX660_send_cmd (ssm, _dev, calibrate_cmd, sizeof (calibrate_cmd),
aesX660_send_cmd_cb); fpi_ssm_usb_transfer_cb);
break; break;
case ACTIVATE_READ_CALIBRATE_DATA: case ACTIVATE_READ_CALIBRATE_DATA:
@@ -666,7 +658,6 @@ static void
activate_sm_complete (FpiSsm *ssm, FpDevice *_dev, GError *error) activate_sm_complete (FpiSsm *ssm, FpDevice *_dev, GError *error)
{ {
fpi_image_device_activate_complete (FP_IMAGE_DEVICE (_dev), error); fpi_image_device_activate_complete (FP_IMAGE_DEVICE (_dev), error);
fpi_ssm_free (ssm);
if (!error) if (!error)
start_finger_detection (FP_IMAGE_DEVICE (_dev)); start_finger_detection (FP_IMAGE_DEVICE (_dev));
+44 -53
View File
@@ -41,7 +41,7 @@
#include "drivers_api.h" #include "drivers_api.h"
#include "elan.h" #include "elan.h"
unsigned char static unsigned char
elan_get_pixel (struct fpi_frame_asmbl_ctx *ctx, elan_get_pixel (struct fpi_frame_asmbl_ctx *ctx,
struct fpi_frame *frame, unsigned int x, struct fpi_frame *frame, unsigned int x,
unsigned int y) unsigned int y)
@@ -73,25 +73,25 @@ struct _FpiDeviceElan
/* end commands */ /* end commands */
/* state */ /* state */
gboolean deactivating; gboolean deactivating;
FpImageDeviceState dev_state; FpiImageDeviceState dev_state;
FpImageDeviceState dev_state_next; FpiImageDeviceState dev_state_next;
unsigned char *last_read; unsigned char *last_read;
unsigned char calib_atts_left; unsigned char calib_atts_left;
unsigned char calib_status; unsigned char calib_status;
unsigned short *background; unsigned short *background;
unsigned char frame_width; unsigned char frame_width;
unsigned char frame_height; unsigned char frame_height;
unsigned char raw_frame_height; unsigned char raw_frame_height;
int num_frames; int num_frames;
GSList *frames; GSList *frames;
/* end state */ /* end state */
}; };
G_DECLARE_FINAL_TYPE (FpiDeviceElan, fpi_device_elan, FPI, DEVICE_ELAN, G_DECLARE_FINAL_TYPE (FpiDeviceElan, fpi_device_elan, FPI, DEVICE_ELAN,
FpImageDevice); FpImageDevice);
G_DEFINE_TYPE (FpiDeviceElan, fpi_device_elan, FP_TYPE_IMAGE_DEVICE); G_DEFINE_TYPE (FpiDeviceElan, fpi_device_elan, FP_TYPE_IMAGE_DEVICE);
int static int
cmp_short (const void *a, const void *b) cmp_short (const void *a, const void *b)
{ {
return (int) (*(short *) a - *(short *) b); return (int) (*(short *) a - *(short *) b);
@@ -223,6 +223,7 @@ elan_save_img_frame (FpiDeviceElan *elandev)
{ {
fp_dbg fp_dbg
("frame darker than background; finger present during calibration?"); ("frame darker than background; finger present during calibration?");
g_free (frame);
return -1; return -1;
} }
@@ -320,6 +321,8 @@ elan_submit_image (FpImageDevice *dev)
fpi_do_movement_estimation (&assembling_ctx, frames); fpi_do_movement_estimation (&assembling_ctx, frames);
img = fpi_assemble_frames (&assembling_ctx, frames); img = fpi_assemble_frames (&assembling_ctx, frames);
g_slist_free_full (frames, g_free);
fpi_image_device_image_captured (dev, img); fpi_image_device_image_captured (dev, img);
} }
@@ -405,7 +408,6 @@ elan_cmd_read (FpiSsm *ssm, FpDevice *dev)
cancellable = fpi_device_get_cancellable (dev); cancellable = fpi_device_get_cancellable (dev);
fpi_usb_transfer_submit (transfer, self->cmd_timeout, cancellable, elan_cmd_cb, NULL); fpi_usb_transfer_submit (transfer, self->cmd_timeout, cancellable, elan_cmd_cb, NULL);
fpi_usb_transfer_unref (transfer);
} }
static void static void
@@ -448,7 +450,6 @@ elan_run_cmd (FpiSsm *ssm,
cancellable, cancellable,
elan_cmd_cb, elan_cmd_cb,
NULL); NULL);
fpi_usb_transfer_unref (transfer);
} }
enum stop_capture_states { enum stop_capture_states {
@@ -478,10 +479,9 @@ stop_capture_complete (FpiSsm *ssm, FpDevice *_dev, GError *error)
G_DEBUG_HERE (); G_DEBUG_HERE ();
fpi_ssm_free (ssm);
/* The device is inactive at this point. */ /* 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) if (self->deactivating)
{ {
@@ -538,7 +538,7 @@ capture_run_state (FpiSsm *ssm, FpDevice *dev)
break; break;
case CAPTURE_READ_DATA: case CAPTURE_READ_DATA:
self->dev_state = FP_IMAGE_DEVICE_STATE_CAPTURE; self->dev_state = FPI_IMAGE_DEVICE_STATE_CAPTURE;
/* 0x55 - finger present /* 0x55 - finger present
* 0xff - device not calibrated (probably) */ * 0xff - device not calibrated (probably) */
@@ -549,7 +549,11 @@ capture_run_state (FpiSsm *ssm, FpDevice *dev)
} }
else else
{ {
fpi_ssm_mark_failed (ssm, fpi_device_error_new (FP_DEVICE_ERROR_PROTO)); /* 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; break;
@@ -581,8 +585,6 @@ capture_complete (FpiSsm *ssm, FpDevice *_dev, GError *error)
G_DEBUG_HERE (); G_DEBUG_HERE ();
/* XXX: cancellation was specially handled by doing nothing! */
/* either max frames captured or timed out waiting for the next frame */ /* either max frames captured or timed out waiting for the next frame */
if (!error || if (!error ||
(g_error_matches (error, G_USB_DEVICE_ERROR, G_USB_DEVICE_ERROR_TIMED_OUT) && (g_error_matches (error, G_USB_DEVICE_ERROR, G_USB_DEVICE_ERROR_TIMED_OUT) &&
@@ -605,7 +607,6 @@ capture_complete (FpiSsm *ssm, FpDevice *_dev, GError *error)
fpi_image_device_session_error (dev, error); fpi_image_device_session_error (dev, error);
} }
fpi_ssm_free (ssm);
} }
static void static void
@@ -752,15 +753,10 @@ calibrate_run_state (FpiSsm *ssm, FpDevice *dev)
} }
else else
{ {
GSource *timeout;
if (self->calib_status == 0x00 && if (self->calib_status == 0x00 &&
self->last_read[0] == 0x01) self->last_read[0] == 0x01)
self->calib_status = 0x01; self->calib_status = 0x01;
timeout = fpi_device_add_timeout (dev, 50, fpi_ssm_next_state_delayed (ssm, 50, NULL);
fpi_ssm_next_state_timeout_cb,
ssm);
g_source_set_name (timeout, "calibrate_run_state");
} }
break; break;
@@ -779,16 +775,14 @@ calibrate_complete (FpiSsm *ssm, FpDevice *dev, GError *error)
if (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); fpi_image_device_session_error (FP_IMAGE_DEVICE (dev), error);
} }
else else
{ {
self->dev_state = FP_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON;
elan_capture (dev); elan_capture (dev);
} }
fpi_ssm_free (ssm);
} }
static void static void
@@ -885,7 +879,6 @@ activate_complete (FpiSsm *ssm, FpDevice *dev, GError *error)
fpi_image_device_activate_complete (idev, error); fpi_image_device_activate_complete (idev, error);
fpi_ssm_free (ssm);
} }
static void static void
@@ -960,7 +953,7 @@ elan_change_state (FpImageDevice *idev)
{ {
FpDevice *dev = FP_DEVICE (idev); FpDevice *dev = FP_DEVICE (idev);
FpiDeviceElan *self = FPI_DEVICE_ELAN (dev); 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) if (self->dev_state == next_state)
{ {
@@ -974,22 +967,20 @@ elan_change_state (FpImageDevice *idev)
switch (next_state) switch (next_state)
{ {
break; case FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON:
case FP_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON:
/* activation completed or another enroll stage started */ /* activation completed or another enroll stage started */
self->dev_state = FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON;
elan_calibrate (dev); elan_calibrate (dev);
break; break;
case FP_IMAGE_DEVICE_STATE_CAPTURE: case FPI_IMAGE_DEVICE_STATE_CAPTURE:
/* not used */ /* not used */
break; break;
case FP_IMAGE_DEVICE_STATE_INACTIVE: case FPI_IMAGE_DEVICE_STATE_INACTIVE:
case FP_IMAGE_DEVICE_STATE_AWAIT_FINGER_OFF: case FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_OFF:
if (self->dev_state != FP_IMAGE_DEVICE_STATE_INACTIVE || elan_stop_capture (dev);
self->dev_state != FP_IMAGE_DEVICE_STATE_AWAIT_FINGER_OFF) break;
elan_stop_capture (dev);
} }
} }
@@ -1002,7 +993,7 @@ elan_change_state_async (FpDevice *dev,
} }
static void static void
dev_change_state (FpImageDevice *dev, FpImageDeviceState state) dev_change_state (FpImageDevice *dev, FpiImageDeviceState state)
{ {
FpiDeviceElan *self = FPI_DEVICE_ELAN (dev); FpiDeviceElan *self = FPI_DEVICE_ELAN (dev);
GSource *timeout; GSource *timeout;
@@ -1010,17 +1001,17 @@ dev_change_state (FpImageDevice *dev, FpImageDeviceState state)
G_DEBUG_HERE (); G_DEBUG_HERE ();
/* Inactive and await finger off are equivalent for the elan driver. */ /* Inactive and await finger off are equivalent for the elan driver. */
if (state == FP_IMAGE_DEVICE_STATE_AWAIT_FINGER_OFF) if (state == FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_OFF)
state = FP_IMAGE_DEVICE_STATE_INACTIVE; state = FPI_IMAGE_DEVICE_STATE_INACTIVE;
if (self->dev_state_next == state) if (self->dev_state_next == state)
fp_dbg ("change to state %d already queued", state); fp_dbg ("change to state %d already queued", state);
switch (state) switch (state)
{ {
case FP_IMAGE_DEVICE_STATE_INACTIVE: case FPI_IMAGE_DEVICE_STATE_INACTIVE:
case FP_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON: case FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON:
case FP_IMAGE_DEVICE_STATE_AWAIT_FINGER_OFF: { case FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_OFF: {
char *name; char *name;
/* schedule state change instead of calling it directly to allow all actions /* schedule state change instead of calling it directly to allow all actions
@@ -1028,7 +1019,7 @@ dev_change_state (FpImageDevice *dev, FpImageDeviceState state)
self->dev_state_next = state; self->dev_state_next = state;
timeout = fpi_device_add_timeout (FP_DEVICE (dev), 10, timeout = fpi_device_add_timeout (FP_DEVICE (dev), 10,
elan_change_state_async, elan_change_state_async,
NULL); NULL, NULL);
name = g_strdup_printf ("dev_change_state to %d", state); name = g_strdup_printf ("dev_change_state to %d", state);
g_source_set_name (timeout, name); g_source_set_name (timeout, name);
@@ -1037,7 +1028,7 @@ dev_change_state (FpImageDevice *dev, FpImageDeviceState state)
break; 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 */ /* TODO MAYBE: split capture ssm into smaller ssms and use this state */
self->dev_state = state; self->dev_state = state;
self->dev_state_next = state; self->dev_state_next = state;
@@ -1055,7 +1046,7 @@ dev_deactivate (FpImageDevice *dev)
G_DEBUG_HERE (); 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. */ /* The device is inactive already, complete the operation immediately. */
fpi_image_device_deactivate_complete (dev, NULL); fpi_image_device_deactivate_complete (dev, NULL);
@@ -1066,7 +1057,7 @@ dev_deactivate (FpImageDevice *dev)
* need to signal back deactivation) and then ensure we will change * need to signal back deactivation) and then ensure we will change
* to the inactive state eventually. */ * to the inactive state eventually. */
self->deactivating = TRUE; self->deactivating = TRUE;
dev_change_state (dev, FP_IMAGE_DEVICE_STATE_INACTIVE); dev_change_state (dev, FPI_IMAGE_DEVICE_STATE_INACTIVE);
} }
} }
+3 -6
View File
@@ -18,8 +18,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
#ifndef __ELAN_H #pragma once
#define __ELAN_H
#include <glib.h> #include <glib.h>
@@ -222,7 +221,5 @@ static void elan_cmd_read (FpiSsm *ssm,
static void elan_calibrate (FpDevice *dev); static void elan_calibrate (FpDevice *dev);
static void elan_capture (FpDevice *dev); static void elan_capture (FpDevice *dev);
static void dev_change_state (FpImageDevice *dev, static void dev_change_state (FpImageDevice *dev,
FpImageDeviceState state); FpiImageDeviceState state);
#endif
-8
View File
@@ -36,7 +36,6 @@
#define FP_COMPONENT "etes603" #define FP_COMPONENT "etes603"
#include "drivers_api.h" #include "drivers_api.h"
#include "driver_ids.h"
/* libusb defines */ /* libusb defines */
#define EP_IN 0x81 #define EP_IN 0x81
@@ -710,7 +709,6 @@ async_tx (FpDevice *dev, unsigned int ep, void *cb,
transfer->ssm = ssm; transfer->ssm = ssm;
fpi_usb_transfer_fill_bulk_full (transfer, ep, buffer, length, NULL); fpi_usb_transfer_fill_bulk_full (transfer, ep, buffer, length, NULL);
fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL, cb, 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 else
fp_dbg ("The device is now in idle state"); fp_dbg ("The device is now in idle state");
fpi_image_device_deactivate_complete (idev, error); fpi_image_device_deactivate_complete (idev, error);
fpi_ssm_free (ssm);
} }
static void static void
@@ -911,7 +908,6 @@ m_capture_complete (FpiSsm *ssm, FpDevice *dev, GError *error)
g_error_free (error); g_error_free (error);
} }
} }
fpi_ssm_free (ssm);
if (self->is_active == TRUE) if (self->is_active == TRUE)
{ {
@@ -1061,7 +1057,6 @@ m_finger_complete (FpiSsm *ssm, FpDevice *dev, GError *error)
self->is_active = FALSE; self->is_active = FALSE;
} }
fpi_ssm_free (ssm);
} }
static void static void
@@ -1265,7 +1260,6 @@ m_tunevrb_complete (FpiSsm *ssm, FpDevice *dev, GError *error)
if (!self->is_active) if (!self->is_active)
m_exit_start (idev); m_exit_start (idev);
fpi_ssm_free (ssm);
} }
/* /*
@@ -1409,7 +1403,6 @@ m_tunedc_complete (FpiSsm *ssm, FpDevice *dev, GError *error)
if (!self->is_active) if (!self->is_active)
m_exit_start (idev); m_exit_start (idev);
fpi_ssm_free (ssm);
} }
static void static void
@@ -1543,7 +1536,6 @@ m_init_complete (FpiSsm *ssm, FpDevice *dev, GError *error)
reset_param (FPI_DEVICE_ETES603 (dev)); reset_param (FPI_DEVICE_ETES603 (dev));
fpi_image_device_session_error (idev, error); fpi_image_device_session_error (idev, error);
} }
fpi_ssm_free (ssm);
} }
static void static void
+1 -4
View File
@@ -17,8 +17,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
#ifndef _BMKT_H_ #pragma once
#define _BMKT_H_
/**< User ID maximum length allowed */ /**< User ID maximum length allowed */
#define BMKT_MAX_USER_ID_LEN 100 #define BMKT_MAX_USER_ID_LEN 100
@@ -228,5 +227,3 @@ typedef struct bmkt_user_id
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif /* _BMKT_H_ */
+1 -5
View File
@@ -16,10 +16,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
#pragma once
#ifndef BMKT_MESSAGE_H_
#define BMKT_MESSAGE_H_
#define BMKT_MESSAGE_HEADER_ID 0xFE #define BMKT_MESSAGE_HEADER_ID 0xFE
#define BMKT_MESSAGE_HEADER_LEN (4) #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); bmkt_msg_resp_t *msg_resp);
int bmkt_parse_message_payload (bmkt_msg_resp_t *msg_resp, int bmkt_parse_message_payload (bmkt_msg_resp_t *msg_resp,
bmkt_response_t *resp); bmkt_response_t *resp);
#endif /* BMKT_MESSAGE_H_ */
+1 -5
View File
@@ -17,9 +17,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
#pragma once
#ifndef _BMKT_RESPONSE_H_
#define _BMKT_RESPONSE_H_
#include "bmkt.h" #include "bmkt.h"
@@ -485,5 +483,3 @@ typedef struct bmkt_response
int complete; /**< Operation completion status 1: complete / 0: not completed */ int complete; /**< Operation completion status 1: complete / 0: not completed */
bmkt_response_data_t response; /**< Operation specific response union */ bmkt_response_data_t response; /**< Operation specific response union */
} bmkt_response_t; } bmkt_response_t;
#endif /* _BMKT_RESPONSE_H_ */
+1 -3
View File
@@ -16,8 +16,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
#ifndef _SENSOR_H_ #pragma once
#define _SENSOR_H_
#include "usb_transport.h" #include "usb_transport.h"
#define BMKT_MAX_PENDING_SESSIONS 2 #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); bmkt_msg_resp_t *msg_resp);
int bmkt_sensor_send_async_read_command (bmkt_sensor_t *sensor); int bmkt_sensor_send_async_read_command (bmkt_sensor_t *sensor);
#endif /* _SENSOR_H_ */
+75 -67
View File
@@ -137,7 +137,8 @@ cmd_recieve_cb (FpiUsbTransfer *transfer,
fp_warn ("Received General Error %d from the sensor", (guint) err); fp_warn ("Received General Error %d from the sensor", (guint) err);
fpi_ssm_mark_failed (transfer->ssm, fpi_ssm_mark_failed (transfer->ssm,
fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO, 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)); //fpi_ssm_jump_to_state (transfer->ssm, fpi_ssm_get_cur_state (transfer->ssm));
return; return;
} }
@@ -167,7 +168,7 @@ cmd_recieve_cb (FpiUsbTransfer *transfer,
* depending on resp.complete. */ * depending on resp.complete. */
if (self->cmd_pending_transfer) if (self->cmd_pending_transfer)
fpi_ssm_jump_to_state (transfer->ssm, SYNAPTICS_CMD_SEND_PENDING); 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 */ fpi_ssm_next_state (transfer->ssm); /* SYNAPTICS_CMD_WAIT_INTERRUPT */
else else
fpi_ssm_mark_completed (transfer->ssm); fpi_ssm_mark_completed (transfer->ssm);
@@ -204,7 +205,7 @@ static void
synaptics_cmd_run_state (FpiSsm *ssm, synaptics_cmd_run_state (FpiSsm *ssm,
FpDevice *dev) FpDevice *dev)
{ {
g_autoptr(FpiUsbTransfer) transfer = NULL; FpiUsbTransfer *transfer;
FpiDeviceSynaptics *self = FPI_DEVICE_SYNAPTICS (dev); FpiDeviceSynaptics *self = FPI_DEVICE_SYNAPTICS (dev);
switch (fpi_ssm_get_cur_state (ssm)) switch (fpi_ssm_get_cur_state (ssm))
@@ -218,7 +219,7 @@ synaptics_cmd_run_state (FpiSsm *ssm,
NULL, NULL,
fpi_ssm_usb_transfer_cb, fpi_ssm_usb_transfer_cb,
NULL); NULL);
g_clear_pointer (&self->cmd_pending_transfer, fpi_usb_transfer_unref); self->cmd_pending_transfer = NULL;
} }
else else
{ {
@@ -278,18 +279,10 @@ cmd_ssm_done (FpiSsm *ssm, FpDevice *dev, GError *error)
self->cmd_ssm = NULL; self->cmd_ssm = NULL;
/* Notify about the SSM failure from here instead. */ /* Notify about the SSM failure from here instead. */
if (error) if (error || self->cmd_complete_on_removal)
{ callback (self, NULL, error);
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; self->cmd_complete_on_removal = FALSE;
g_clear_pointer (&self->cmd_complete_error, g_error_free);
fpi_ssm_free (ssm);
} }
static void static void
@@ -317,7 +310,7 @@ synaptics_sensor_cmd (FpiDeviceSynaptics *self,
gssize payload_len, gssize payload_len,
SynCmdMsgCallback callback) SynCmdMsgCallback callback)
{ {
g_autoptr(FpiUsbTransfer) transfer = NULL; FpiUsbTransfer *transfer;
guint8 real_seq_num; guint8 real_seq_num;
gint msg_len; gint msg_len;
gint res; gint res;
@@ -407,7 +400,7 @@ static gboolean
parse_print_data (GVariant *data, parse_print_data (GVariant *data,
guint8 *finger, guint8 *finger,
const guint8 **user_id, const guint8 **user_id,
gssize *user_id_len) gsize *user_id_len)
{ {
g_autoptr(GVariant) user_id_var = NULL; g_autoptr(GVariant) user_id_var = NULL;
@@ -447,7 +440,7 @@ list_msg_cb (FpiDeviceSynaptics *self,
if (error) 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); fpi_device_list_complete (FP_DEVICE (self), NULL, error);
return; return;
} }
@@ -468,11 +461,12 @@ list_msg_cb (FpiDeviceSynaptics *self,
else else
{ {
fp_info ("Failed to query enrolled users: %d", resp->result); 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), fpi_device_list_complete (FP_DEVICE (self),
NULL, NULL,
fpi_device_error_new_msg (FP_DEVICE_ERROR_GENERAL, fpi_device_error_new_msg (FP_DEVICE_ERROR_GENERAL,
"Failed to query enrolled users")); "Failed to query enrolled users: %d",
resp->result));
} }
break; break;
@@ -505,7 +499,7 @@ list_msg_cb (FpiDeviceSynaptics *self,
get_enroll_templates_resp->templates[n].user_id, get_enroll_templates_resp->templates[n].user_id,
get_enroll_templates_resp->templates[n].finger_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)); print = fp_print_new (FP_DEVICE (self));
uid = g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE, uid = g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE,
@@ -516,9 +510,9 @@ list_msg_cb (FpiDeviceSynaptics *self,
get_enroll_templates_resp->templates[n].finger_id, get_enroll_templates_resp->templates[n].finger_id,
uid); uid);
fpi_print_set_type (print, FP_PRINT_RAW); fpi_print_set_type (print, FPI_PRINT_RAW);
fpi_print_set_device_stored (print, TRUE); 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); 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 */ /* The format has 24 bytes at the start and some dashes in the right places */
@@ -526,8 +520,8 @@ list_msg_cb (FpiDeviceSynaptics *self,
userid[12] == '-' && userid[14] == '-' && userid[23] == '-') userid[12] == '-' && userid[14] == '-' && userid[23] == '-')
{ {
g_autofree gchar *copy = g_strdup (userid); g_autofree gchar *copy = g_strdup (userid);
g_autoptr(GDate) date = NULL;
gint32 date_ymd; gint32 date_ymd;
GDate *date = NULL;
gint32 finger; gint32 finger;
gchar *username; gchar *username;
/* Try to parse information from the string. */ /* Try to parse information from the string. */
@@ -542,7 +536,6 @@ list_msg_cb (FpiDeviceSynaptics *self,
date = g_date_new (); date = g_date_new ();
fp_print_set_enroll_date (print, date); fp_print_set_enroll_date (print, date);
g_date_free (date);
copy[14] = '\0'; copy[14] = '\0';
finger = g_ascii_strtoll (copy + 13, NULL, 16); finger = g_ascii_strtoll (copy + 13, NULL, 16);
@@ -581,6 +574,22 @@ list (FpDevice *device)
synaptics_sensor_cmd (self, 0, BMKT_CMD_GET_TEMPLATE_RECORDS, NULL, 0, list_msg_cb); 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 static void
verify_msg_cb (FpiDeviceSynaptics *self, verify_msg_cb (FpiDeviceSynaptics *self,
bmkt_response_t *resp, bmkt_response_t *resp,
@@ -591,19 +600,18 @@ verify_msg_cb (FpiDeviceSynaptics *self,
if (error) if (error)
{ {
fpi_device_verify_complete (device, FPI_MATCH_ERROR, NULL, error); fpi_device_verify_complete (device, error);
return; return;
} }
if (resp == NULL && self->cmd_complete_on_removal) if (resp == NULL && self->cmd_complete_on_removal)
{ {
fpi_device_verify_complete (device, fpi_device_verify_complete (device, NULL);
GPOINTER_TO_INT (self->cmd_complete_data),
NULL,
error);
return; return;
} }
g_assert (resp != NULL);
verify_resp = &resp->response.verify_resp; verify_resp = &resp->response.verify_resp;
switch (resp->response_id) switch (resp->response_id)
@@ -617,39 +625,40 @@ verify_msg_cb (FpiDeviceSynaptics *self,
break; break;
case BMKT_RSP_VERIFY_FAIL: case BMKT_RSP_VERIFY_FAIL:
if(resp->result == BMKT_SENSOR_STIMULUS_ERROR) if (resp->result == BMKT_SENSOR_STIMULUS_ERROR)
{ {
fp_dbg ("delaying retry error until after finger removal!"); fp_info ("Match error occurred");
self->cmd_complete_on_removal = TRUE; fpi_device_verify_report (device, FPI_MATCH_ERROR, NULL,
self->cmd_complete_data = GINT_TO_POINTER (FPI_MATCH_ERROR); fpi_device_retry_new (FP_DEVICE_RETRY_GENERAL));
self->cmd_complete_error = fpi_device_retry_new (FP_DEVICE_RETRY_GENERAL); verify_complete_after_finger_removal (self);
} }
else if (resp->result == BMKT_FP_NO_MATCH) else if (resp->result == BMKT_FP_NO_MATCH)
{ {
fp_dbg ("delaying match failure until after finger removal!"); fp_info ("Print didn't match");
self->cmd_complete_on_removal = TRUE; fpi_device_verify_report (device, FPI_MATCH_FAIL, NULL, error);
self->cmd_complete_data = GINT_TO_POINTER (FPI_MATCH_FAIL); verify_complete_after_finger_removal (self);
self->cmd_complete_error = NULL;
} }
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"); fp_info ("Print is not in database");
fpi_device_verify_complete (device, fpi_device_verify_complete (device,
FPI_MATCH_ERROR,
NULL,
fpi_device_error_new (FP_DEVICE_ERROR_DATA_NOT_FOUND)); fpi_device_error_new (FP_DEVICE_ERROR_DATA_NOT_FOUND));
} }
else else
{ {
fp_warn ("Verify has failed: %d", resp->result); 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; break;
case BMKT_RSP_VERIFY_OK: case BMKT_RSP_VERIFY_OK:
fp_info ("Verify was successful! for user: %s finger: %d score: %f", fp_info ("Verify was successful! for user: %s finger: %d score: %f",
verify_resp->user_id, verify_resp->finger_id, verify_resp->match_result); 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; break;
} }
} }
@@ -667,13 +676,11 @@ verify (FpDevice *device)
fpi_device_get_verify_data (device, &print); 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); g_debug ("data is %p", data);
if (!parse_print_data (data, &finger, &user_id, &user_id_len)) if (!parse_print_data (data, &finger, &user_id, &user_id_len))
{ {
fpi_device_verify_complete (device, fpi_device_verify_complete (device,
FPI_MATCH_ERROR,
NULL,
fpi_device_error_new (FP_DEVICE_ERROR_DATA_INVALID)); fpi_device_error_new (FP_DEVICE_ERROR_DATA_INVALID));
return; return;
} }
@@ -768,7 +775,8 @@ enroll_msg_cb (FpiDeviceSynaptics *self,
fpi_device_enroll_complete (device, fpi_device_enroll_complete (device,
NULL, NULL,
fpi_device_error_new_msg (FP_DEVICE_ERROR_GENERAL, fpi_device_error_new_msg (FP_DEVICE_ERROR_GENERAL,
"Enrollment failed")); "Enrollment failed (%d)",
resp->result));
} }
break; break;
} }
@@ -798,7 +806,7 @@ enroll (FpDevice *device)
GVariant *uid = NULL; GVariant *uid = NULL;
const gchar *username; const gchar *username;
guint finger; guint finger;
g_autofree gchar *user_id; g_autofree gchar *user_id = NULL;
gssize user_id_len; gssize user_id_len;
g_autofree guint8 *payload = NULL; g_autofree guint8 *payload = NULL;
const GDate *date; const GDate *date;
@@ -812,9 +820,9 @@ enroll (FpDevice *device)
date = fp_print_get_enroll_date (print); date = fp_print_get_enroll_date (print);
if (date && g_date_valid (date)) if (date && g_date_valid (date))
{ {
y = date->year; y = g_date_get_year (date);
m = date->month; m = g_date_get_month (date);
d = date->day; d = g_date_get_day (date);
} }
else else
{ {
@@ -852,9 +860,9 @@ enroll (FpDevice *device)
finger, finger,
uid); uid);
fpi_print_set_type (print, FP_PRINT_RAW); fpi_print_set_type (print, FPI_PRINT_RAW);
fpi_print_set_device_stored (print, TRUE); 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_object_set (print, "description", user_id, NULL);
g_debug ("user_id: %s, finger: %d", user_id, finger); g_debug ("user_id: %s, finger: %d", user_id, finger);
@@ -923,7 +931,7 @@ delete_print (FpDevice *device)
fpi_device_get_delete_data (device, &print); 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); g_debug ("data is %p", data);
if (!parse_print_data (data, &finger, &user_id, &user_id_len)) if (!parse_print_data (data, &finger, &user_id, &user_id_len))
{ {
@@ -946,7 +954,8 @@ dev_probe (FpDevice *device)
{ {
FpiDeviceSynaptics *self = FPI_DEVICE_SYNAPTICS (device); FpiDeviceSynaptics *self = FPI_DEVICE_SYNAPTICS (device);
GUsbDevice *usb_dev; GUsbDevice *usb_dev;
FpiUsbTransfer *transfer;
g_autoptr(FpiUsbTransfer) transfer = NULL;
FpiByteReader reader; FpiByteReader reader;
GError *error = NULL; GError *error = NULL;
guint16 status; guint16 status;
@@ -964,13 +973,10 @@ dev_probe (FpDevice *device)
return; return;
} }
if (!g_usb_device_reset (fpi_device_get_usb_device (device), &error)) if (!g_usb_device_reset (usb_dev, &error))
{ goto err_close;
fpi_device_probe_complete (device, NULL, NULL, error);
return;
}
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; goto err_close;
/* TODO: Do not do this synchronous. */ /* TODO: Do not do this synchronous. */
@@ -980,9 +986,8 @@ dev_probe (FpDevice *device)
transfer->buffer[0] = SENSOR_CMD_GET_VERSION; transfer->buffer[0] = SENSOR_CMD_GET_VERSION;
if (!fpi_usb_transfer_submit_sync (transfer, 1000, &error)) if (!fpi_usb_transfer_submit_sync (transfer, 1000, &error))
goto err_close; goto err_close;
fpi_usb_transfer_unref (transfer);
g_clear_pointer (&transfer, fpi_usb_transfer_unref);
transfer = fpi_usb_transfer_new (device); transfer = fpi_usb_transfer_new (device);
fpi_usb_transfer_fill_bulk (transfer, USB_EP_REPLY, 40); fpi_usb_transfer_fill_bulk (transfer, USB_EP_REPLY, 40);
if (!fpi_usb_transfer_submit_sync (transfer, 1000, &error)) if (!fpi_usb_transfer_submit_sync (transfer, 1000, &error))
@@ -1035,7 +1040,6 @@ dev_probe (FpDevice *device)
fp_dbg ("Target: %d", self->mis_version.target); fp_dbg ("Target: %d", self->mis_version.target);
fp_dbg ("Product: %d", self->mis_version.product); 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 */ /* We need at least firmware version 10.1, and for 10.1 build 2989158 */
if (self->mis_version.version_major < 10 || if (self->mis_version.version_major < 10 ||
@@ -1050,7 +1054,11 @@ dev_probe (FpDevice *device)
self->mis_version.build_num); self->mis_version.build_num);
error = fpi_device_error_new_msg (FP_DEVICE_ERROR_GENERAL, 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; goto err_close;
} }
@@ -1118,7 +1126,7 @@ fps_deinit_cb (FpiDeviceSynaptics *self,
case BMKT_RSP_POWER_DOWN_FAIL: case BMKT_RSP_POWER_DOWN_FAIL:
fp_info ("Failed to go to power down mode: %d", resp->result); fp_info ("Failed to go to power down mode: %d", resp->result);
error = fpi_device_error_new_msg (FP_DEVICE_ERROR_GENERAL, error = fpi_device_error_new_msg (FP_DEVICE_ERROR_GENERAL,
"Power down failed"); "Power down failed: %d", resp->result);
break; break;
} }
+1 -6
View File
@@ -16,8 +16,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
#ifndef __synaptics_h__ #pragma once
#define __synaptics_h__
#include "fpi-device.h" #include "fpi-device.h"
#include "fpi-ssm.h" #include "fpi-ssm.h"
@@ -111,8 +110,6 @@ struct _FpiDeviceSynaptics
FpiSsm *cmd_ssm; FpiSsm *cmd_ssm;
FpiUsbTransfer *cmd_pending_transfer; FpiUsbTransfer *cmd_pending_transfer;
gboolean cmd_complete_on_removal; gboolean cmd_complete_on_removal;
GError *cmd_complete_error;
void *cmd_complete_data;
bmkt_sensor_version_t mis_version; bmkt_sensor_version_t mis_version;
@@ -126,5 +123,3 @@ struct _FpiDeviceSynaptics
struct syna_enroll_resp_data enroll_resp_data; struct syna_enroll_resp_data enroll_resp_data;
syna_state_t state; syna_state_t state;
}; };
#endif //__synaptics_h__
+14 -19
View File
@@ -635,7 +635,6 @@ write_regs_iterate (struct write_regs_data *wrdata)
transfer->short_is_error = TRUE; transfer->short_is_error = TRUE;
transfer->ssm = wrdata->ssm; transfer->ssm = wrdata->ssm;
fpi_usb_transfer_submit (transfer, CTRL_TIMEOUT, NULL, write_regs_cb, NULL); fpi_usb_transfer_submit (transfer, CTRL_TIMEOUT, NULL, write_regs_cb, NULL);
fpi_usb_transfer_unref (transfer);
transfer->buffer[0] = regwrite->value; transfer->buffer[0] = regwrite->value;
} }
@@ -657,17 +656,6 @@ sm_write_regs (FpiSsm *ssm,
write_regs_iterate (wrdata); 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 static void
sm_write_reg (FpiSsm *ssm, sm_write_reg (FpiSsm *ssm,
FpImageDevice *dev, FpImageDevice *dev,
@@ -687,8 +675,8 @@ sm_write_reg (FpiSsm *ssm,
1); 1);
transfer->short_is_error = TRUE; transfer->short_is_error = TRUE;
transfer->ssm = ssm; transfer->ssm = ssm;
fpi_usb_transfer_submit (transfer, CTRL_TIMEOUT, NULL, sm_write_reg_cb, NULL); fpi_usb_transfer_submit (transfer, CTRL_TIMEOUT, NULL,
fpi_usb_transfer_unref (transfer); fpi_ssm_usb_transfer_cb, NULL);
transfer->buffer[0] = value; transfer->buffer[0] = value;
} }
@@ -737,7 +725,6 @@ sm_read_reg (FpiSsm *ssm,
NULL, NULL,
sm_read_reg_cb, sm_read_reg_cb,
NULL); NULL);
fpi_usb_transfer_unref (transfer);
} }
static void static void
@@ -782,7 +769,6 @@ sm_await_intr (FpiSsm *ssm,
fpi_device_get_cancellable (FP_DEVICE (dev)), fpi_device_get_cancellable (FP_DEVICE (dev)),
sm_await_intr_cb, sm_await_intr_cb,
NULL); NULL);
fpi_usb_transfer_unref (transfer);
} }
/***** AWAIT FINGER *****/ /***** AWAIT FINGER *****/
@@ -1249,6 +1235,9 @@ loopsm_run_state (FpiSsm *ssm, FpDevice *_dev)
awfsm_1000_run_state, awfsm_1000_run_state,
AWFSM_1000_NUM_STATES); AWFSM_1000_NUM_STATES);
break; break;
default:
g_assert_not_reached ();
} }
fpi_ssm_start_subsm (ssm, awfsm); fpi_ssm_start_subsm (ssm, awfsm);
} }
@@ -1290,6 +1279,9 @@ loopsm_run_state (FpiSsm *ssm, FpDevice *_dev)
capsm_1001_run_state, capsm_1001_run_state,
CAPSM_1001_NUM_STATES); CAPSM_1001_NUM_STATES);
break; break;
default:
g_assert_not_reached ();
} }
fpi_ssm_start_subsm (ssm, capsm); fpi_ssm_start_subsm (ssm, capsm);
break; break;
@@ -1318,6 +1310,9 @@ loopsm_run_state (FpiSsm *ssm, FpDevice *_dev)
deinitsm_1001_run_state, deinitsm_1001_run_state,
DEINITSM_1001_NUM_STATES); DEINITSM_1001_NUM_STATES);
break; break;
default:
g_assert_not_reached ();
} }
self->capturing = FALSE; self->capturing = FALSE;
fpi_ssm_start_subsm (ssm, deinitsm); fpi_ssm_start_subsm (ssm, deinitsm);
@@ -1371,7 +1366,6 @@ loopsm_complete (FpiSsm *ssm, FpDevice *_dev, GError *error)
FpImageDevice *dev = FP_IMAGE_DEVICE (_dev); FpImageDevice *dev = FP_IMAGE_DEVICE (_dev);
FpiDeviceUpeksonly *self = FPI_DEVICE_UPEKSONLY (_dev); FpiDeviceUpeksonly *self = FPI_DEVICE_UPEKSONLY (_dev);
fpi_ssm_free (ssm);
if (self->deactivating) if (self->deactivating)
{ {
@@ -1392,7 +1386,6 @@ initsm_complete (FpiSsm *ssm, FpDevice *_dev, GError *error)
FpImageDevice *dev = FP_IMAGE_DEVICE (_dev); FpImageDevice *dev = FP_IMAGE_DEVICE (_dev);
FpiDeviceUpeksonly *self = FPI_DEVICE_UPEKSONLY (_dev); FpiDeviceUpeksonly *self = FPI_DEVICE_UPEKSONLY (_dev);
fpi_ssm_free (ssm);
fpi_image_device_activate_complete (dev, error); fpi_image_device_activate_complete (dev, error);
if (error) if (error)
return; return;
@@ -1412,7 +1405,6 @@ dev_activate (FpImageDevice *dev)
self->deactivating = FALSE; self->deactivating = FALSE;
self->capturing = FALSE; self->capturing = FALSE;
self->img_transfers = g_ptr_array_new_full (NUM_BULK_TRANSFERS, (GDestroyNotify) fpi_usb_transfer_unref);
self->num_flying = 0; self->num_flying = 0;
for (i = 0; i < self->img_transfers->len; i++) 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, ssm = fpi_ssm_new (FP_DEVICE (dev), initsm_1001_run_state,
INITSM_1001_NUM_STATES); INITSM_1001_NUM_STATES);
break; break;
default:
g_assert_not_reached ();
} }
fpi_ssm_start (ssm, initsm_complete); fpi_ssm_start (ssm, initsm_complete);
} }
+1 -19
View File
@@ -128,7 +128,6 @@ activate_run_state (FpiSsm *ssm, FpDevice *dev)
transfer->short_is_error = TRUE; transfer->short_is_error = TRUE;
fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL, fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
write_init_cb, NULL); write_init_cb, NULL);
fpi_usb_transfer_unref (transfer);
} }
break; break;
@@ -142,7 +141,6 @@ activate_run_state (FpiSsm *ssm, FpDevice *dev)
transfer->ssm = ssm; transfer->ssm = ssm;
fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL, fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
read_init_data_cb, NULL); read_init_data_cb, NULL);
fpi_usb_transfer_unref (transfer);
} }
break; break;
} }
@@ -157,7 +155,6 @@ activate_sm_complete (FpiSsm *ssm, FpDevice *_dev, GError *error)
if (!error) if (!error)
start_finger_detection (dev); start_finger_detection (dev);
fpi_ssm_free (ssm);
} }
@@ -226,7 +223,6 @@ finger_det_cmd_cb (FpiUsbTransfer *t, FpDevice *device,
IMAGE_SIZE); IMAGE_SIZE);
fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL, fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
finger_det_data_cb, NULL); finger_det_data_cb, NULL);
fpi_usb_transfer_unref (transfer);
} }
static void static void
@@ -250,7 +246,6 @@ start_finger_detection (FpImageDevice *dev)
UPEKTC_CMD_LEN, NULL); UPEKTC_CMD_LEN, NULL);
fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL, fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
finger_det_cmd_cb, NULL); finger_det_cmd_cb, NULL);
fpi_usb_transfer_unref (transfer);
} }
/****** CAPTURE ******/ /****** CAPTURE ******/
@@ -261,16 +256,6 @@ enum capture_states {
CAPTURE_NUM_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 static void
capture_read_data_cb (FpiUsbTransfer *transfer, FpDevice *device, capture_read_data_cb (FpiUsbTransfer *transfer, FpDevice *device,
gpointer user_data, GError *error) gpointer user_data, GError *error)
@@ -309,8 +294,7 @@ capture_run_state (FpiSsm *ssm, FpDevice *_dev)
transfer->ssm = ssm; transfer->ssm = ssm;
transfer->short_is_error = TRUE; transfer->short_is_error = TRUE;
fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL, fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
capture_cmd_cb, NULL); fpi_ssm_usb_transfer_cb, NULL);
fpi_usb_transfer_unref (transfer);
} }
break; break;
@@ -324,7 +308,6 @@ capture_run_state (FpiSsm *ssm, FpDevice *_dev)
transfer->short_is_error = TRUE; transfer->short_is_error = TRUE;
fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL, fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
capture_read_data_cb, NULL); capture_read_data_cb, NULL);
fpi_usb_transfer_unref (transfer);
} }
break; break;
} }
@@ -345,7 +328,6 @@ capture_sm_complete (FpiSsm *ssm, FpDevice *_dev, GError *error)
else else
start_finger_detection (dev); start_finger_detection (dev);
fpi_ssm_free (ssm);
} }
static void static void
+1 -4
View File
@@ -19,8 +19,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
#ifndef __UPEKTC_H #pragma once
#define __UPEKTC_H
#define UPEKTC_CMD_LEN 0x40 #define UPEKTC_CMD_LEN 0x40
#define IMAGE_WIDTH 208 #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, 0x77, 0x84, 0xf5, 0x2f, 0x01,
0x05, 0x90, 0xf6, 0x00, 0xc8, 0x00, 0xec, 0x00 0x05, 0x90, 0xf6, 0x00, 0xc8, 0x00, 0xec, 0x00
}; };
#endif
+1 -17
View File
@@ -100,7 +100,6 @@ upektc_img_submit_req (FpiSsm *ssm,
transfer->ssm = ssm; transfer->ssm = ssm;
transfer->short_is_error = TRUE; transfer->short_is_error = TRUE;
fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL, cb, NULL); fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL, cb, NULL);
fpi_usb_transfer_unref (transfer);
} }
static void static void
@@ -120,7 +119,6 @@ upektc_img_read_data (FpiSsm *ssm,
NULL); NULL);
transfer->ssm = ssm; transfer->ssm = ssm;
fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL, cb, NULL); fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL, cb, NULL);
fpi_usb_transfer_unref (transfer);
} }
/****** CAPTURE ******/ /****** CAPTURE ******/
@@ -389,7 +387,6 @@ capture_sm_complete (FpiSsm *ssm, FpDevice *_dev, GError *error_arg)
g_autoptr(GError) error = 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 */ /* Note: We assume that the error is a cancellation in the deactivation case */
if (self->deactivating) if (self->deactivating)
@@ -470,7 +467,6 @@ deactivate_sm_complete (FpiSsm *ssm, FpDevice *_dev, GError *error)
FpiDeviceUpektcImg *self = FPI_DEVICE_UPEKTC_IMG (_dev); FpiDeviceUpektcImg *self = FPI_DEVICE_UPEKTC_IMG (_dev);
fp_dbg ("Deactivate completed"); fp_dbg ("Deactivate completed");
fpi_ssm_free (ssm);
self->deactivating = FALSE; self->deactivating = FALSE;
fpi_image_device_deactivate_complete (dev, error); fpi_image_device_deactivate_complete (dev, error);
@@ -505,16 +501,6 @@ enum activate_states {
ACTIVATE_NUM_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 static void
init_reqs_cb (FpiUsbTransfer *transfer, FpDevice *device, init_reqs_cb (FpiUsbTransfer *transfer, FpDevice *device,
gpointer user_data, GError *error) gpointer user_data, GError *error)
@@ -558,8 +544,7 @@ activate_run_state (FpiSsm *ssm, FpDevice *dev)
transfer->buffer[0] = '\0'; transfer->buffer[0] = '\0';
transfer->ssm = ssm; transfer->ssm = ssm;
fpi_usb_transfer_submit (transfer, CTRL_TIMEOUT, NULL, fpi_usb_transfer_submit (transfer, CTRL_TIMEOUT, NULL,
init_reqs_ctrl_cb, NULL); fpi_ssm_usb_transfer_cb, NULL);
fpi_usb_transfer_unref (transfer);
} }
break; break;
@@ -601,7 +586,6 @@ activate_sm_complete (FpiSsm *ssm, FpDevice *_dev, GError *error)
{ {
FpImageDevice *dev = FP_IMAGE_DEVICE (_dev); FpImageDevice *dev = FP_IMAGE_DEVICE (_dev);
fpi_ssm_free (ssm);
fpi_image_device_activate_complete (dev, error); fpi_image_device_activate_complete (dev, error);
if (!error) if (!error)
+1 -4
View File
@@ -17,8 +17,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
#ifndef __UPEKTC_IMG_H #pragma once
#define __UPEKTC_IMG_H
static const unsigned char upek2020_init_1[] = { static const unsigned char upek2020_init_1[] = {
'C', 'i', 'a', 'o', 'C', 'i', 'a', 'o',
@@ -140,5 +139,3 @@ static const unsigned char upek2020_ack_frame[] = {
0x30, 0x30,
0xac, 0x5b /* CRC */ 0xac, 0x5b /* CRC */
}; };
#endif
+24 -28
View File
@@ -226,7 +226,6 @@ busy_ack_retry_read (FpDevice *device, struct read_msg_data *udata)
transfer->short_is_error = TRUE; transfer->short_is_error = TRUE;
fpi_usb_transfer_submit (transfer, TIMEOUT, NULL, busy_ack_sent_cb, udata); 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 /* Returns 0 if message was handled, 1 if it was a device-busy message, and
@@ -288,7 +287,7 @@ __handle_incoming_msg (FpDevice *device,
{ {
fp_warn ("cmd response too short (%d)", len); fp_warn ("cmd response too short (%d)", len);
error = fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO, error = fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
"CMD response too short"); "CMD response too short (%d)", len);
goto err; goto err;
} }
if (innerbuf[0] != 0x28) if (innerbuf[0] != 0x28)
@@ -371,11 +370,12 @@ read_msg_cb (FpiUsbTransfer *transfer, FpDevice *device,
fp_err ("async msg read too short (%d)", fp_err ("async msg read too short (%d)",
(gint) transfer->actual_length); (gint) transfer->actual_length);
error = fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO, 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; goto err;
} }
if (strncmp (udata->buffer, "Ciao", 4) != 0) if (strncmp ((char *) udata->buffer, "Ciao", 4) != 0)
{ {
fp_err ("no Ciao for you!!"); fp_err ("no Ciao for you!!");
error = fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO, error = fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
@@ -415,7 +415,6 @@ read_msg_cb (FpiUsbTransfer *transfer, FpDevice *device,
fpi_usb_transfer_submit (etransfer, TIMEOUT, fpi_usb_transfer_submit (etransfer, TIMEOUT,
NULL, NULL,
read_msg_extend_cb, udata); read_msg_extend_cb, udata);
fpi_usb_transfer_unref (etransfer);
return; return;
} }
@@ -441,7 +440,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_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_submit (transfer, TIMEOUT, NULL, read_msg_cb, udata);
fpi_usb_transfer_unref (transfer);
} }
static void static void
@@ -675,7 +673,6 @@ initsm_send_msg28_handler (FpiSsm *ssm,
transfer->ssm = ssm; transfer->ssm = ssm;
transfer->short_is_error = TRUE; transfer->short_is_error = TRUE;
fpi_usb_transfer_submit (transfer, TIMEOUT, NULL, fpi_ssm_usb_transfer_cb, NULL); fpi_usb_transfer_submit (transfer, TIMEOUT, NULL, fpi_ssm_usb_transfer_cb, NULL);
fpi_usb_transfer_unref (transfer);
} }
static void static void
@@ -696,7 +693,6 @@ initsm_run_state (FpiSsm *ssm, FpDevice *dev)
transfer->ssm = ssm; transfer->ssm = ssm;
transfer->short_is_error = TRUE; transfer->short_is_error = TRUE;
fpi_usb_transfer_submit (transfer, TIMEOUT, NULL, fpi_ssm_usb_transfer_cb, NULL); fpi_usb_transfer_submit (transfer, TIMEOUT, NULL, fpi_ssm_usb_transfer_cb, NULL);
fpi_usb_transfer_unref (transfer);
break; break;
case READ_MSG03: case READ_MSG03:
@@ -708,7 +704,6 @@ initsm_run_state (FpiSsm *ssm, FpDevice *dev)
transfer->ssm = ssm; transfer->ssm = ssm;
transfer->short_is_error = TRUE; transfer->short_is_error = TRUE;
fpi_usb_transfer_submit (transfer, TIMEOUT, NULL, fpi_ssm_usb_transfer_cb, NULL); fpi_usb_transfer_submit (transfer, TIMEOUT, NULL, fpi_ssm_usb_transfer_cb, NULL);
fpi_usb_transfer_unref (transfer);
break; break;
case READ_MSG05: case READ_MSG05:
@@ -798,7 +793,8 @@ read_msg01_cb (FpDevice *dev, enum read_msg_type type,
{ {
fp_err ("expected seq=1, got %x", seq); fp_err ("expected seq=1, got %x", seq);
fpi_ssm_mark_failed (ssm, fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO, 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; return;
} }
@@ -818,7 +814,6 @@ deinitsm_state_handler (FpiSsm *ssm, FpDevice *dev)
transfer->short_is_error = TRUE; transfer->short_is_error = TRUE;
transfer->ssm = ssm; transfer->ssm = ssm;
fpi_usb_transfer_submit (transfer, TIMEOUT, NULL, fpi_ssm_usb_transfer_cb, NULL); fpi_usb_transfer_submit (transfer, TIMEOUT, NULL, fpi_ssm_usb_transfer_cb, NULL);
fpi_usb_transfer_unref (transfer);
break; break;
case READ_MSG01:; case READ_MSG01:;
@@ -907,8 +902,10 @@ enroll_start_sm_cb_msg28 (FpDevice *dev,
FpiSsm *ssm = user_data; FpiSsm *ssm = user_data;
if (error) if (error)
fpi_ssm_mark_failed (ssm, error); {
if (type != READ_MSG_RESPONSE) fpi_ssm_mark_failed (ssm, error);
}
else if (type != READ_MSG_RESPONSE)
{ {
fp_err ("expected response, got %d seq=%x", type, seq); fp_err ("expected response, got %d seq=%x", type, seq);
fpi_ssm_mark_failed (ssm, fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO, fpi_ssm_mark_failed (ssm, fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
@@ -951,7 +948,6 @@ enroll_start_sm_run_state (FpiSsm *ssm, FpDevice *dev)
transfer->ssm = ssm; transfer->ssm = ssm;
fpi_usb_transfer_submit (transfer, TIMEOUT, NULL, fpi_ssm_usb_transfer_cb, NULL); fpi_usb_transfer_submit (transfer, TIMEOUT, NULL, fpi_ssm_usb_transfer_cb, NULL);
fpi_usb_transfer_unref (transfer);
break; break;
case READ_ENROLL_MSG28:; case READ_ENROLL_MSG28:;
@@ -988,7 +984,6 @@ enroll_stop_deinit_cb (FpiSsm *ssm, FpDevice *dev, GError *error)
fp_warn ("Error deinitializing: %s", error->message); fp_warn ("Error deinitializing: %s", error->message);
fpi_device_enroll_complete (dev, data->print, data->error); fpi_device_enroll_complete (dev, data->print, data->error);
fpi_ssm_free (ssm);
} }
static void static void
@@ -1133,7 +1128,7 @@ e_handle_resp02 (FpDevice *dev, unsigned char *data,
data_len - sizeof (scan_comp), data_len - sizeof (scan_comp),
1); 1);
g_object_set (print, "fp-data", fp_data, NULL); g_object_set (print, "fpi-data", fp_data, NULL);
g_object_ref (print); g_object_ref (print);
} }
@@ -1204,7 +1199,6 @@ enroll_iterate (FpDevice *dev)
transfer->short_is_error = TRUE; transfer->short_is_error = TRUE;
fpi_usb_transfer_submit (transfer, TIMEOUT, NULL, enroll_iterate_cmd_cb, NULL); fpi_usb_transfer_submit (transfer, TIMEOUT, NULL, enroll_iterate_cmd_cb, NULL);
fpi_usb_transfer_unref (transfer);
} }
static void static void
@@ -1215,7 +1209,6 @@ enroll_started (FpiSsm *ssm, FpDevice *dev, GError *error)
else else
enroll_iterate (dev); enroll_iterate (dev);
fpi_ssm_free (ssm);
} }
static void static void
@@ -1234,8 +1227,7 @@ enroll (FpDevice *dev)
typedef struct typedef struct
{ {
FpiMatchResult res; GError *error;
GError *error;
} VerifyStopData; } VerifyStopData;
static void static void
@@ -1253,8 +1245,12 @@ verify_stop_deinit_cb (FpiSsm *ssm, FpDevice *dev, GError *error)
if (error) if (error)
fp_warn ("Error deinitializing: %s", error->message); fp_warn ("Error deinitializing: %s", error->message);
fpi_device_verify_complete (dev, data->res, NULL, data->error); if (data->error)
fpi_ssm_free (ssm); fpi_device_verify_complete (dev, data->error);
else
fpi_device_verify_complete (dev, g_steal_pointer (&error));
g_error_free (error);
} }
static void static void
@@ -1263,8 +1259,11 @@ do_verify_stop (FpDevice *dev, FpiMatchResult res, GError *error)
VerifyStopData *data = g_new0 (VerifyStopData, 1); VerifyStopData *data = g_new0 (VerifyStopData, 1);
FpiSsm *ssm = deinitsm_new (dev, data); FpiSsm *ssm = deinitsm_new (dev, data);
data->res = res; /* Report the error immediately if possible, otherwise delay it. */
data->error = error; 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); fpi_ssm_start (ssm, verify_stop_deinit_cb);
fpi_ssm_set_data (ssm, data, (GDestroyNotify) verify_stop_data_free); fpi_ssm_set_data (ssm, data, (GDestroyNotify) verify_stop_data_free);
@@ -1303,7 +1302,7 @@ verify_start_sm_run_state (FpiSsm *ssm, FpDevice *dev)
case VERIFY_INIT: case VERIFY_INIT:
fpi_device_get_verify_data (dev, &print); fpi_device_get_verify_data (dev, &print);
g_object_get (dev, "fp-data", &fp_data, NULL); g_object_get (dev, "fpi-data", &fp_data, NULL);
data = g_variant_get_fixed_array (fp_data, &data_len, 1); data = g_variant_get_fixed_array (fp_data, &data_len, 1);
@@ -1320,7 +1319,6 @@ verify_start_sm_run_state (FpiSsm *ssm, FpDevice *dev)
transfer->short_is_error = TRUE; transfer->short_is_error = TRUE;
transfer->ssm = ssm; transfer->ssm = ssm;
fpi_usb_transfer_submit (transfer, TIMEOUT, NULL, fpi_ssm_usb_transfer_cb, NULL); fpi_usb_transfer_submit (transfer, TIMEOUT, NULL, fpi_ssm_usb_transfer_cb, NULL);
fpi_usb_transfer_unref (transfer);
break; break;
} }
@@ -1520,7 +1518,6 @@ verify_iterate (FpDevice *dev)
transfer->short_is_error = TRUE; transfer->short_is_error = TRUE;
fpi_usb_transfer_submit (transfer, TIMEOUT, NULL, verify_wr2800_cb, NULL); fpi_usb_transfer_submit (transfer, TIMEOUT, NULL, verify_wr2800_cb, NULL);
fpi_usb_transfer_unref (transfer);
} }
} }
@@ -1538,7 +1535,6 @@ verify_started (FpiSsm *ssm, FpDevice *dev, GError *error)
upekdev->first_verify_iteration = TRUE; upekdev->first_verify_iteration = TRUE;
verify_iterate (dev); verify_iterate (dev);
fpi_ssm_free (ssm);
} }
static void static void
+43 -67
View File
@@ -122,7 +122,7 @@ struct _FpiDeviceUru4000
const struct uru4k_dev_profile *profile; const struct uru4k_dev_profile *profile;
uint8_t interface; uint8_t interface;
FpImageDeviceState activate_state; FpiImageDeviceState activate_state;
unsigned char last_reg_rd[16]; unsigned char last_reg_rd[16];
unsigned char last_hwstat; unsigned char last_hwstat;
@@ -175,13 +175,12 @@ write_regs (FpImageDevice *dev, uint16_t first_reg,
transfer->short_is_error = TRUE; transfer->short_is_error = TRUE;
fpi_usb_transfer_fill_control (transfer, fpi_usb_transfer_fill_control (transfer,
G_USB_DEVICE_DIRECTION_HOST_TO_DEVICE, G_USB_DEVICE_DIRECTION_HOST_TO_DEVICE,
G_USB_DEVICE_REQUEST_TYPE_STANDARD, G_USB_DEVICE_REQUEST_TYPE_VENDOR,
G_USB_DEVICE_RECIPIENT_DEVICE, G_USB_DEVICE_RECIPIENT_DEVICE,
USB_RQ, first_reg, 0, USB_RQ, first_reg, 0,
num_regs); num_regs);
memcpy (transfer->buffer, values, num_regs); memcpy (transfer->buffer, values, num_regs);
fpi_usb_transfer_submit (transfer, CTRL_TIMEOUT, NULL, callback, user_data); fpi_usb_transfer_submit (transfer, CTRL_TIMEOUT, NULL, callback, user_data);
fpi_usb_transfer_unref (transfer);
} }
static void static void
@@ -203,11 +202,10 @@ read_regs (FpImageDevice *dev, uint16_t first_reg,
fpi_usb_transfer_fill_control (transfer, fpi_usb_transfer_fill_control (transfer,
G_USB_DEVICE_DIRECTION_DEVICE_TO_HOST, G_USB_DEVICE_DIRECTION_DEVICE_TO_HOST,
G_USB_DEVICE_REQUEST_TYPE_STANDARD, G_USB_DEVICE_REQUEST_TYPE_VENDOR,
G_USB_DEVICE_RECIPIENT_DEVICE, G_USB_DEVICE_RECIPIENT_DEVICE,
USB_RQ, first_reg, 0, num_regs); USB_RQ, first_reg, 0, num_regs);
fpi_usb_transfer_submit (transfer, CTRL_TIMEOUT, NULL, callback, user_data); 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; return;
} }
start_irq_handler (imgdev);
type = GUINT16_FROM_BE (*((uint16_t *) data)); type = GUINT16_FROM_BE (*((uint16_t *) data));
fp_dbg ("recv irq type %04x", type); 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); urudev->irq_cb (imgdev, NULL, type, urudev->irq_cb_data);
else else
fp_dbg ("ignoring interrupt"); fp_dbg ("ignoring interrupt");
start_irq_handler (imgdev);
} }
static void static void
@@ -365,7 +363,6 @@ start_irq_handler (FpImageDevice *dev)
EP_INTR, EP_INTR,
IRQ_LENGTH); IRQ_LENGTH);
fpi_usb_transfer_submit (transfer, 0, self->irq_cancellable, irq_handler, NULL); fpi_usb_transfer_submit (transfer, 0, self->irq_cancellable, irq_handler, NULL);
fpi_usb_transfer_unref (transfer);
} }
static void static void
@@ -411,16 +408,16 @@ change_state_write_reg_cb (FpiUsbTransfer *transfer,
} }
static void static void
dev_change_state (FpImageDevice *dev, FpImageDeviceState state) dev_change_state (FpImageDevice *dev, FpiImageDeviceState state)
{ {
FpiDeviceUru4000 *self = FPI_DEVICE_URU4000 (dev); FpiDeviceUru4000 *self = FPI_DEVICE_URU4000 (dev);
switch (state) switch (state)
{ {
case FP_IMAGE_DEVICE_STATE_INACTIVE: case FPI_IMAGE_DEVICE_STATE_INACTIVE:
case FP_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON: case FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON:
case FP_IMAGE_DEVICE_STATE_AWAIT_FINGER_OFF: case FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_OFF:
case FP_IMAGE_DEVICE_STATE_CAPTURE: case FPI_IMAGE_DEVICE_STATE_CAPTURE:
break; break;
default: default:
@@ -776,7 +773,7 @@ imaging_run_state (FpiSsm *ssm, FpDevice *_dev)
fpimg->flags |= FPI_IMAGE_V_FLIPPED | FPI_IMAGE_H_FLIPPED; fpimg->flags |= FPI_IMAGE_V_FLIPPED | FPI_IMAGE_H_FLIPPED;
fpi_image_device_image_captured (dev, fpimg); 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); fpi_ssm_jump_to_state (ssm, IMAGING_CAPTURE);
else else
fpi_ssm_mark_completed (ssm); fpi_ssm_mark_completed (ssm);
@@ -789,7 +786,6 @@ imaging_complete (FpiSsm *ssm, FpDevice *dev, GError *error)
{ {
FpiDeviceUru4000 *self = FPI_DEVICE_URU4000 (dev); FpiDeviceUru4000 *self = FPI_DEVICE_URU4000 (dev);
fpi_ssm_free (ssm);
/* Report error before exiting imaging loop - the error handler /* Report error before exiting imaging loop - the error handler
* can request state change, which needs to be postponed to end of * can request state change, which needs to be postponed to end of
@@ -833,26 +829,6 @@ enum rebootpwr_states {
REBOOTPWR_NUM_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 static void
rebootpwr_run_state (FpiSsm *ssm, FpDevice *_dev) rebootpwr_run_state (FpiSsm *ssm, FpDevice *_dev)
{ {
@@ -879,7 +855,17 @@ rebootpwr_run_state (FpiSsm *ssm, FpDevice *_dev)
break; break;
case REBOOTPWR_PAUSE: 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; break;
} }
} }
@@ -920,30 +906,6 @@ enum powerup_states {
POWERUP_NUM_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 static void
powerup_run_state (FpiSsm *ssm, FpDevice *_dev) powerup_run_state (FpiSsm *ssm, FpDevice *_dev)
{ {
@@ -975,7 +937,21 @@ powerup_run_state (FpiSsm *ssm, FpDevice *_dev)
break; break;
case POWERUP_PAUSE: 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; break;
case POWERUP_CHALLENGE_RESPONSE: case POWERUP_CHALLENGE_RESPONSE:
@@ -1134,7 +1110,7 @@ init_run_state (FpiSsm *ssm, FpDevice *_dev)
self->scanpwr_irq_timeout = fpi_device_add_timeout (_dev, self->scanpwr_irq_timeout = fpi_device_add_timeout (_dev,
300, 300,
init_scanpwr_timeout, init_scanpwr_timeout,
ssm); ssm, NULL);
break; break;
case INIT_DONE: case INIT_DONE:
@@ -1200,7 +1176,7 @@ deactivate_write_reg_cb (FpiUsbTransfer *transfer, FpDevice *dev,
static void static void
dev_deactivate (FpImageDevice *dev) dev_deactivate (FpImageDevice *dev)
{ {
dev_change_state (dev, FP_IMAGE_DEVICE_STATE_INACTIVE); dev_change_state (dev, FPI_IMAGE_DEVICE_STATE_INACTIVE);
} }
static void static void
@@ -1211,7 +1187,7 @@ execute_state_change (FpImageDevice *dev)
switch (self->activate_state) switch (self->activate_state)
{ {
case FP_IMAGE_DEVICE_STATE_INACTIVE: case FPI_IMAGE_DEVICE_STATE_INACTIVE:
fp_dbg ("deactivating"); fp_dbg ("deactivating");
self->irq_cb = NULL; self->irq_cb = NULL;
self->irq_cb_data = NULL; self->irq_cb_data = NULL;
@@ -1219,7 +1195,7 @@ execute_state_change (FpImageDevice *dev)
deactivate_write_reg_cb, NULL); deactivate_write_reg_cb, NULL);
break; break;
case FP_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON: case FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON:
fp_dbg ("wait finger on"); fp_dbg ("wait finger on");
if (!IRQ_HANDLER_IS_RUNNING (self)) if (!IRQ_HANDLER_IS_RUNNING (self))
{ {
@@ -1233,7 +1209,7 @@ execute_state_change (FpImageDevice *dev)
change_state_write_reg_cb, NULL); change_state_write_reg_cb, NULL);
break; break;
case FP_IMAGE_DEVICE_STATE_CAPTURE: case FPI_IMAGE_DEVICE_STATE_CAPTURE:
fp_dbg ("starting capture"); fp_dbg ("starting capture");
self->irq_cb = NULL; self->irq_cb = NULL;
@@ -1253,7 +1229,7 @@ execute_state_change (FpImageDevice *dev)
change_state_write_reg_cb, NULL); change_state_write_reg_cb, NULL);
break; break;
case FP_IMAGE_DEVICE_STATE_AWAIT_FINGER_OFF: case FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_OFF:
fp_dbg ("await finger off"); fp_dbg ("await finger off");
if (!IRQ_HANDLER_IS_RUNNING (self)) if (!IRQ_HANDLER_IS_RUNNING (self))
{ {
+4 -28
View File
@@ -76,16 +76,6 @@ enum v5s_cmd {
/***** REGISTER I/O *****/ /***** 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 static void
sm_write_reg (FpiSsm *ssm, sm_write_reg (FpiSsm *ssm,
FpDevice *dev, FpDevice *dev,
@@ -101,19 +91,8 @@ sm_write_reg (FpiSsm *ssm,
G_USB_DEVICE_RECIPIENT_DEVICE, G_USB_DEVICE_RECIPIENT_DEVICE,
reg, value, 0, 0); reg, value, 0, 0);
transfer->ssm = ssm; transfer->ssm = ssm;
fpi_usb_transfer_submit (transfer, CTRL_TIMEOUT, NULL, sm_write_reg_cb, fpi_usb_transfer_submit (transfer, CTRL_TIMEOUT, NULL,
NULL); fpi_ssm_usb_transfer_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);
} }
static void static void
@@ -131,9 +110,8 @@ sm_exec_cmd (FpiSsm *ssm,
G_USB_DEVICE_RECIPIENT_DEVICE, G_USB_DEVICE_RECIPIENT_DEVICE,
cmd, param, 0, 0); cmd, param, 0, 0);
transfer->ssm = ssm; transfer->ssm = ssm;
fpi_usb_transfer_submit (transfer, CTRL_TIMEOUT, NULL, sm_exec_cmd_cb, fpi_usb_transfer_submit (transfer, CTRL_TIMEOUT, NULL,
NULL); fpi_ssm_usb_transfer_cb, NULL);
fpi_usb_transfer_unref (transfer);
} }
/***** FINGER DETECTION *****/ /***** FINGER DETECTION *****/
@@ -227,7 +205,6 @@ capture_iterate (FpiSsm *ssm,
NULL); NULL);
fpi_usb_transfer_submit (transfer, CTRL_TIMEOUT, NULL, capture_cb, 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); FpImageDevice *imgdev = FP_IMAGE_DEVICE (dev);
FpDeviceVcom5s *self = FPI_DEVICE_VCOM5S (dev); FpDeviceVcom5s *self = FPI_DEVICE_VCOM5S (dev);
fpi_ssm_free (ssm);
g_object_unref (self->capture_img); g_object_unref (self->capture_img);
self->capture_img = NULL; self->capture_img = NULL;
self->loop_running = FALSE; self->loop_running = FALSE;
+6 -23
View File
@@ -56,7 +56,6 @@ async_write (FpiSsm *ssm,
transfer->short_is_error = TRUE; transfer->short_is_error = TRUE;
fpi_usb_transfer_submit (transfer, VFS_USB_TIMEOUT, NULL, fpi_usb_transfer_submit (transfer, VFS_USB_TIMEOUT, NULL,
async_write_callback, NULL); async_write_callback, NULL);
fpi_usb_transfer_unref (transfer);
} }
/* Callback for async_read */ /* Callback for async_read */
@@ -108,7 +107,6 @@ async_read (FpiSsm *ssm,
fpi_usb_transfer_submit (transfer, VFS_USB_TIMEOUT, NULL, fpi_usb_transfer_submit (transfer, VFS_USB_TIMEOUT, NULL,
async_read_callback, NULL); async_read_callback, NULL);
fpi_usb_transfer_unref (transfer);
} }
/* Callback for async_abort */ /* Callback for async_abort */
@@ -160,7 +158,6 @@ async_abort (FpDevice *dev, FpiSsm *ssm, int ep)
fpi_usb_transfer_submit (transfer, VFS_USB_ABORT_TIMEOUT, NULL, fpi_usb_transfer_submit (transfer, VFS_USB_ABORT_TIMEOUT, NULL,
async_abort_callback, NULL); async_abort_callback, NULL);
fpi_usb_transfer_unref (transfer);
} }
/* Image processing functions */ /* Image processing functions */
@@ -402,7 +399,7 @@ interrupt_callback (FpiUsbTransfer *transfer, FpDevice *device,
gpointer user_data, GError *error) gpointer user_data, GError *error)
{ {
FpDeviceVfs0050 *self = FPI_DEVICE_VFS0050 (device); 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 /* we expect a cancellation error when the device is deactivating
* go into the SSM_CLEAR_EP2 state in that case. */ * go into the SSM_CLEAR_EP2 state in that case. */
@@ -482,16 +479,6 @@ receive_callback (FpiUsbTransfer *transfer, FpDevice *device,
} }
} }
/* 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 */ /* Main SSM loop */
static void static void
activate_ssm (FpiSsm *ssm, FpDevice *dev) activate_ssm (FpiSsm *ssm, FpDevice *dev)
@@ -564,7 +551,6 @@ activate_ssm (FpiSsm *ssm, FpDevice *dev)
0, 0,
fpi_device_get_cancellable (dev), fpi_device_get_cancellable (dev),
interrupt_callback, NULL); interrupt_callback, NULL);
fpi_usb_transfer_unref (transfer);
/* I've put it here to be sure that data is cleared */ /* I've put it here to be sure that data is cleared */
clear_data (self); clear_data (self);
@@ -609,12 +595,12 @@ activate_ssm (FpiSsm *ssm, FpDevice *dev)
/* Receive chunk of data */ /* Receive chunk of data */
transfer = fpi_usb_transfer_new (dev); transfer = fpi_usb_transfer_new (dev);
fpi_usb_transfer_fill_bulk_full (transfer, 0x82, 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); VFS_USB_BUFFER_SIZE, NULL);
transfer->ssm = ssm; transfer->ssm = ssm;
fpi_usb_transfer_submit (transfer, VFS_USB_TIMEOUT, NULL, fpi_usb_transfer_submit (transfer, VFS_USB_TIMEOUT, NULL,
receive_callback, NULL); receive_callback, NULL);
fpi_usb_transfer_unref (transfer);
break; break;
} }
@@ -623,8 +609,7 @@ activate_ssm (FpiSsm *ssm, FpDevice *dev)
clear_data (self); clear_data (self);
/* Wait for probable vdev->active changing */ /* Wait for probable vdev->active changing */
fpi_device_add_timeout (dev, VFS_SSM_TIMEOUT, fpi_ssm_next_state_delayed (ssm, VFS_SSM_TIMEOUT, NULL);
fpi_ssm_next_state_timeout_cb, ssm);
break; break;
case SSM_NEXT_RECEIVE: case SSM_NEXT_RECEIVE:
@@ -643,8 +628,8 @@ activate_ssm (FpiSsm *ssm, FpDevice *dev)
case SSM_WAIT_ANOTHER_SCAN: case SSM_WAIT_ANOTHER_SCAN:
/* Orange light is on now */ /* Orange light is on now */
fpi_device_add_timeout (dev, VFS_SSM_ORANGE_TIMEOUT, fpi_ssm_jump_to_state_delayed (ssm, SSM_TURN_ON, VFS_SSM_ORANGE_TIMEOUT,
another_scan, ssm); NULL);
break; break;
default: default:
@@ -669,7 +654,6 @@ dev_activate_callback (FpiSsm *ssm, FpDevice *dev, GError *error)
g_error_free (error); g_error_free (error);
} }
fpi_ssm_free (ssm);
} }
/* Activate device */ /* Activate device */
@@ -710,7 +694,6 @@ dev_open_callback (FpiSsm *ssm, FpDevice *dev, GError *error)
{ {
/* Notify open complete */ /* Notify open complete */
fpi_image_device_open_complete (FP_IMAGE_DEVICE (dev), error); fpi_image_device_open_complete (FP_IMAGE_DEVICE (dev), error);
fpi_ssm_free (ssm);
} }
/* Open device */ /* Open device */
+7 -22
View File
@@ -219,7 +219,6 @@ async_send (FpiSsm *ssm,
transfer->short_is_error = TRUE; transfer->short_is_error = TRUE;
fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL, fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
async_send_cb, NULL); async_send_cb, NULL);
fpi_usb_transfer_unref (transfer);
} }
/* Callback of asynchronous recv */ /* Callback of asynchronous recv */
@@ -282,7 +281,6 @@ async_recv (FpiSsm *ssm,
transfer->ssm = ssm; transfer->ssm = ssm;
fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL, fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
async_recv_cb, NULL); async_recv_cb, NULL);
fpi_usb_transfer_unref (transfer);
} }
static void async_load (FpiSsm *ssm, static void async_load (FpiSsm *ssm,
@@ -369,17 +367,6 @@ async_load (FpiSsm *ssm,
transfer->ssm = ssm; transfer->ssm = ssm;
fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL, fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
async_load_cb, 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 */ /* Swap ssm states */
@@ -798,7 +785,7 @@ m_loop_state (FpiSsm *ssm, FpDevice *_dev)
case M_LOOP_0_SLEEP: case M_LOOP_0_SLEEP:
/* Wait fingerprint scanning */ /* Wait fingerprint scanning */
async_sleep (50, ssm, dev); fpi_ssm_next_state_delayed (ssm, 50, NULL);
break; break;
case M_LOOP_0_GET_STATE: case M_LOOP_0_GET_STATE:
@@ -841,7 +828,7 @@ m_loop_state (FpiSsm *ssm, FpDevice *_dev)
img_extract (ssm, dev); img_extract (ssm, dev);
/* Wait handling image */ /* Wait handling image */
async_sleep (10, ssm, dev); fpi_ssm_next_state_delayed (ssm, 10, NULL);
break; break;
case M_LOOP_0_CHECK_ACTION: 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) if (vfs_finger_state (self) == VFS_FINGER_PRESENT)
{ {
fpi_image_device_report_finger_status (dev, TRUE); fpi_image_device_report_finger_status (dev, TRUE);
async_sleep (250, ssm, dev); fpi_ssm_next_state_delayed (ssm, 250, NULL);
} }
else else
{ {
@@ -894,7 +881,7 @@ m_loop_state (FpiSsm *ssm, FpDevice *_dev)
case M_LOOP_1_SLEEP: case M_LOOP_1_SLEEP:
/* Wait fingerprint scanning */ /* Wait fingerprint scanning */
async_sleep (10, ssm, dev); fpi_ssm_next_state_delayed (ssm, 10, NULL);
break; break;
case M_LOOP_2_ABORT_PRINT: case M_LOOP_2_ABORT_PRINT:
@@ -930,7 +917,7 @@ m_loop_state (FpiSsm *ssm, FpDevice *_dev)
{ {
/* Wait aborting */ /* Wait aborting */
self->counter++; self->counter++;
async_sleep (100, ssm, dev); fpi_ssm_next_state_delayed (ssm, 100, NULL);
} }
else else
{ {
@@ -960,7 +947,6 @@ m_loop_complete (FpiSsm *ssm, FpDevice *dev, GError *error)
self->active = FALSE; self->active = FALSE;
fpi_ssm_free (ssm);
} }
/* Init ssm states */ /* Init ssm states */
@@ -1069,7 +1055,7 @@ m_init_state (FpiSsm *ssm, FpDevice *_dev)
{ {
/* Wait aborting */ /* Wait aborting */
self->counter++; self->counter++;
async_sleep (100, ssm, dev); fpi_ssm_next_state_delayed (ssm, 100, NULL);
} }
else else
{ {
@@ -1098,7 +1084,7 @@ m_init_state (FpiSsm *ssm, FpDevice *_dev)
{ {
/* Wait removing finger */ /* Wait removing finger */
self->counter++; self->counter++;
async_sleep (250, ssm, dev); fpi_ssm_next_state_delayed (ssm, 250, NULL);
} }
else else
{ {
@@ -1268,7 +1254,6 @@ m_init_complete (FpiSsm *ssm, FpDevice *_dev, GError *error)
} }
/* Free sequential state machine */ /* Free sequential state machine */
fpi_ssm_free (ssm);
} }
/* Activate device */ /* Activate device */
+2 -15
View File
@@ -28,17 +28,6 @@ G_DEFINE_TYPE (FpDeviceVfs301, fpi_device_vfs301, FP_TYPE_IMAGE_DEVICE)
/************************** GENERIC STUFF *************************************/ /************************** 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 static int
submit_image (FpiSsm *ssm, submit_image (FpiSsm *ssm,
FpImageDevice *dev) FpImageDevice *dev)
@@ -108,7 +97,7 @@ m_loop_state (FpiSsm *ssm, FpDevice *_dev)
case M_WAIT_PRINT: case M_WAIT_PRINT:
/* Wait fingerprint scanning */ /* Wait fingerprint scanning */
async_sleep (200, ssm, dev); fpi_ssm_next_state_delayed (ssm, 200, NULL);
break; break;
case M_CHECK_PRINT: case M_CHECK_PRINT:
@@ -126,7 +115,7 @@ m_loop_state (FpiSsm *ssm, FpDevice *_dev)
case M_READ_PRINT_WAIT: case M_READ_PRINT_WAIT:
/* Wait fingerprint scanning */ /* Wait fingerprint scanning */
async_sleep (200, ssm, dev); fpi_ssm_next_state_delayed (ssm, 200, NULL);
break; break;
case M_READ_PRINT_POLL: case M_READ_PRINT_POLL:
@@ -168,7 +157,6 @@ m_loop_complete (FpiSsm *ssm, FpDevice *_dev, GError *error)
g_error_free (error); g_error_free (error);
} }
/* Free sequential state machine */ /* Free sequential state machine */
fpi_ssm_free (ssm);
} }
/* Exec init sequential state machine */ /* Exec init sequential state machine */
@@ -201,7 +189,6 @@ m_init_complete (FpiSsm *ssm, FpDevice *dev, GError *error)
} }
/* Free sequential state machine */ /* Free sequential state machine */
fpi_ssm_free (ssm);
} }
/* Activate device */ /* Activate device */
+2 -5
View File
@@ -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); fpi_usb_transfer_submit_sync (transfer, VFS301_DEFAULT_WAIT_TIMEOUT, &err);
#ifdef DEBUG #ifdef DEBUG
usb_print_packet (0, err, transfer->buffer, transfer->actual_length); usb_print_packet (0, err, transfer->buffer, transfer->actual_length);
#endif #endif
@@ -471,7 +470,7 @@ int
vfs301_proto_peek_event (FpDeviceVfs301 *dev) vfs301_proto_peek_event (FpDeviceVfs301 *dev)
{ {
g_autoptr(GError) error = NULL; 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 no_event[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
const char got_event[] = {0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00}; const char got_event[] = {0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00};
@@ -500,7 +499,7 @@ vfs301_proto_peek_event (FpDeviceVfs301 *dev)
usb_recv (dev, e1, l1, NULL, &error); \ usb_recv (dev, e1, l1, NULL, &error); \
usb_recv (dev, e2, l2, NULL, NULL); \ usb_recv (dev, e2, l2, NULL, NULL); \
if (g_error_matches (error, G_USB_DEVICE_ERROR, G_USB_DEVICE_ERROR_TIMED_OUT)) \ if (g_error_matches (error, G_USB_DEVICE_ERROR, G_USB_DEVICE_ERROR_TIMED_OUT)) \
usb_recv(dev, e1, l1, NULL, NULL); \ usb_recv (dev, e1, l1, NULL, NULL); \
} }
static void static void
@@ -540,7 +539,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_fill_bulk (new, VFS301_RECEIVE_ENDPOINT_DATA, VFS301_FP_RECV_LEN_2);
fpi_usb_transfer_submit (new, VFS301_FP_RECV_TIMEOUT, NULL, fpi_usb_transfer_submit (new, VFS301_FP_RECV_TIMEOUT, NULL,
vfs301_proto_process_event_cb, NULL); vfs301_proto_process_event_cb, NULL);
fpi_usb_transfer_unref (new);
return; return;
} }
} }
@@ -580,7 +578,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_fill_bulk (transfer, VFS301_RECEIVE_ENDPOINT_DATA, VFS301_FP_RECV_LEN_1);
fpi_usb_transfer_submit (transfer, VFS301_FP_RECV_TIMEOUT, NULL, fpi_usb_transfer_submit (transfer, VFS301_FP_RECV_TIMEOUT, NULL,
vfs301_proto_process_event_cb, NULL); vfs301_proto_process_event_cb, NULL);
fpi_usb_transfer_unref (transfer);
} }
int int
+13 -19
View File
@@ -168,7 +168,6 @@ usbexchange_loop (FpiSsm *ssm, FpDevice *_dev)
transfer->short_is_error = TRUE; transfer->short_is_error = TRUE;
fpi_usb_transfer_submit (transfer, data->timeout, NULL, fpi_usb_transfer_submit (transfer, data->timeout, NULL,
async_send_cb, NULL); async_send_cb, NULL);
fpi_usb_transfer_unref (transfer);
break; break;
case ACTION_RECEIVE: case ACTION_RECEIVE:
@@ -180,7 +179,6 @@ usbexchange_loop (FpiSsm *ssm, FpDevice *_dev)
transfer->ssm = ssm; transfer->ssm = ssm;
fpi_usb_transfer_submit (transfer, data->timeout, NULL, fpi_usb_transfer_submit (transfer, data->timeout, NULL,
async_recv_cb, NULL); async_recv_cb, NULL);
fpi_usb_transfer_unref (transfer);
break; break;
default: default:
@@ -192,11 +190,13 @@ usbexchange_loop (FpiSsm *ssm, FpDevice *_dev)
static void static void
usb_exchange_async (FpiSsm *ssm, 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, usbexchange_loop,
data->stepcount); data->stepcount,
exchange_name);
fpi_ssm_set_data (subsm, data, NULL); fpi_ssm_set_data (subsm, data, NULL);
fpi_ssm_start_subsm (ssm, subsm); 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; int res = 0, mean = 0, i;
const int size = 64; const int size = 64;
buf1 = row1->data + 56; buf1 = (unsigned char *) row1->data + 56;
buf2 = row2->data + 168; buf2 = (unsigned char *) row2->data + 168;
for (i = 0; i < size; i++) for (i = 0; i < size; i++)
mean += (int) buf1[i] + (int) buf2[i]; mean += (int) buf1[i] + (int) buf2[i];
@@ -234,7 +234,7 @@ vfs5011_get_pixel (struct fpi_line_asmbl_ctx *ctx,
GSList *row, GSList *row,
unsigned x) unsigned x)
{ {
unsigned char *data = row->data + 8; unsigned char *data = (unsigned char *) row->data + 8;
return data[x]; return data[x];
} }
@@ -466,7 +466,6 @@ capture_chunk_async (FpDeviceVfs5011 *self,
transfer->ssm = ssm; transfer->ssm = ssm;
fpi_usb_transfer_submit (transfer, timeout, fpi_device_get_cancellable (FP_DEVICE (self)), fpi_usb_transfer_submit (transfer, timeout, fpi_device_get_cancellable (FP_DEVICE (self)),
chunk_capture_callback, NULL); chunk_capture_callback, NULL);
fpi_usb_transfer_unref (transfer);
} }
/* /*
@@ -687,7 +686,7 @@ activate_loop (FpiSsm *ssm, FpDevice *_dev)
self->init_sequence.receive_buf = self->init_sequence.receive_buf =
g_malloc0 (VFS5011_RECEIVE_BUF_SIZE); g_malloc0 (VFS5011_RECEIVE_BUF_SIZE);
self->init_sequence.timeout = 1000; self->init_sequence.timeout = 1000;
usb_exchange_async (ssm, &self->init_sequence); usb_exchange_async (ssm, &self->init_sequence, "ACTIVATE REQUEST");
break; break;
case DEV_ACTIVATE_INIT_COMPLETE: case DEV_ACTIVATE_INIT_COMPLETE:
@@ -707,10 +706,7 @@ activate_loop (FpiSsm *ssm, FpDevice *_dev)
break; break;
case DEV_ACTIVATE_DATA_COMPLETE: case DEV_ACTIVATE_DATA_COMPLETE:
fpi_device_add_timeout (_dev, 1, fpi_ssm_next_state_delayed (ssm, 1, NULL);
fpi_ssm_next_state_timeout_cb,
ssm);
break; break;
case DEV_ACTIVATE_PREPARE_NEXT_CAPTURE: case DEV_ACTIVATE_PREPARE_NEXT_CAPTURE:
@@ -722,7 +718,7 @@ activate_loop (FpiSsm *ssm, FpDevice *_dev)
self->init_sequence.receive_buf = self->init_sequence.receive_buf =
g_malloc0 (VFS5011_RECEIVE_BUF_SIZE); g_malloc0 (VFS5011_RECEIVE_BUF_SIZE);
self->init_sequence.timeout = VFS5011_DEFAULT_WAIT_TIMEOUT; 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; break;
} }
@@ -745,7 +741,6 @@ activate_loop_complete (FpiSsm *ssm, FpDevice *_dev, GError *error)
submit_image (ssm, self, dev); submit_image (ssm, self, dev);
fpi_image_device_report_finger_status (dev, FALSE); fpi_image_device_report_finger_status (dev, FALSE);
} }
fpi_ssm_free (ssm);
self->loop_running = FALSE; self->loop_running = FALSE;
@@ -776,7 +771,7 @@ open_loop (FpiSsm *ssm, FpDevice *_dev)
self->init_sequence.receive_buf = self->init_sequence.receive_buf =
g_malloc0 (VFS5011_RECEIVE_BUF_SIZE); g_malloc0 (VFS5011_RECEIVE_BUF_SIZE);
self->init_sequence.timeout = VFS5011_DEFAULT_WAIT_TIMEOUT; 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; break;
} }
; ;
@@ -793,7 +788,6 @@ open_loop_complete (FpiSsm *ssm, FpDevice *_dev, GError *error)
self->init_sequence.receive_buf = NULL; self->init_sequence.receive_buf = NULL;
fpi_image_device_open_complete (dev, error); fpi_image_device_open_complete (dev, error);
fpi_ssm_free (ssm);
} }
static void static void
+1 -4
View File
@@ -1,5 +1,4 @@
#ifndef __VFS5011_PROTO_H #pragma once
#define __VFS5011_PROTO_H
#define VFS5011_LINE_SIZE 240 #define VFS5011_LINE_SIZE 240
#define VFS5011_IMAGE_WIDTH 160 #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, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
}; };
#endif
+50 -31
View File
@@ -47,6 +47,7 @@ struct _FpDeviceVirtualImage
gint socket_fd; gint socket_fd;
gint client_fd; gint client_fd;
gboolean automatic_finger;
FpImage *recv_img; FpImage *recv_img;
gint recv_img_hdr[2]; gint recv_img_hdr[2];
}; };
@@ -66,31 +67,34 @@ recv_image_img_recv_cb (GObject *source_object,
g_autoptr(GError) error = NULL; g_autoptr(GError) error = NULL;
FpDeviceVirtualImage *self; FpDeviceVirtualImage *self;
FpImageDevice *device; 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)) if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
return; return;
g_warning ("Error receiving header for image data: %s", error->message);
} }
self = FPI_DEVICE_VIRTUAL_IMAGE (user_data); self = FPI_DEVICE_VIRTUAL_IMAGE (user_data);
g_io_stream_close (G_IO_STREAM (self->connection), NULL, NULL); g_io_stream_close (G_IO_STREAM (self->connection), NULL, NULL);
self->connection = NULL; g_clear_object (&self->connection);
return; return;
} }
self = FPI_DEVICE_VIRTUAL_IMAGE (user_data); self = FPI_DEVICE_VIRTUAL_IMAGE (user_data);
device = FP_IMAGE_DEVICE (self); device = FP_IMAGE_DEVICE (self);
fpi_image_device_report_finger_status (device, TRUE); if (self->automatic_finger)
fpi_image_device_report_finger_status (device, TRUE);
fpi_image_device_image_captured (device, g_steal_pointer (&self->recv_img)); fpi_image_device_image_captured (device, g_steal_pointer (&self->recv_img));
fpi_image_device_report_finger_status (device, FALSE); if (self->automatic_finger)
fpi_image_device_report_finger_status (device, FALSE);
/* And, listen for more images from the same client. */ /* And, listen for more images from the same client. */
recv_image (self, G_INPUT_STREAM (source_object)); recv_image (self, G_INPUT_STREAM (source_object));
@@ -103,22 +107,24 @@ recv_image_hdr_recv_cb (GObject *source_object,
{ {
g_autoptr(GError) error = NULL; g_autoptr(GError) error = NULL;
FpDeviceVirtualImage *self; 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; return;
g_warning ("Error receiving header for image data: %s", error->message);
} }
self = FPI_DEVICE_VIRTUAL_IMAGE (user_data); self = FPI_DEVICE_VIRTUAL_IMAGE (user_data);
g_io_stream_close (G_IO_STREAM (self->connection), NULL, NULL); g_io_stream_close (G_IO_STREAM (self->connection), NULL, NULL);
self->connection = NULL; g_clear_object (&self->connection);
return; 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_warning ("Image header suggests an unrealistically large image, disconnecting client.");
g_io_stream_close (G_IO_STREAM (self->connection), NULL, NULL); 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) 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])); fpi_device_error_new (self->recv_img_hdr[1]));
break; 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: default:
/* disconnect client, it didn't play fair */ /* disconnect client, it didn't play fair */
g_io_stream_close (G_IO_STREAM (self->connection), NULL, NULL); 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. */ /* And, listen for more images from the same client. */
@@ -158,25 +175,25 @@ recv_image_hdr_recv_cb (GObject *source_object,
self->recv_img = fp_image_new (self->recv_img_hdr[0], self->recv_img_hdr[1]); 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_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, (guint8 *) self->recv_img->data,
self->recv_img->width * self->recv_img->height, self->recv_img->width * self->recv_img->height,
G_PRIORITY_DEFAULT, G_PRIORITY_DEFAULT,
self->cancellable, self->cancellable,
recv_image_img_recv_cb, recv_image_img_recv_cb,
self); self);
} }
static void static void
recv_image (FpDeviceVirtualImage *dev, GInputStream *stream) recv_image (FpDeviceVirtualImage *dev, GInputStream *stream)
{ {
g_input_stream_read_async (stream, g_input_stream_read_all_async (stream,
dev->recv_img_hdr, dev->recv_img_hdr,
sizeof (dev->recv_img_hdr), sizeof (dev->recv_img_hdr),
G_PRIORITY_DEFAULT, G_PRIORITY_DEFAULT,
dev->cancellable, dev->cancellable,
recv_image_hdr_recv_cb, recv_image_hdr_recv_cb,
dev); dev);
} }
static void static void
@@ -206,10 +223,12 @@ new_connection_cb (GObject *source_object, GAsyncResult *res, gpointer user_data
if (dev->connection) if (dev->connection)
{ {
g_io_stream_close (G_IO_STREAM (connection), NULL, NULL); g_io_stream_close (G_IO_STREAM (connection), NULL, NULL);
g_object_unref (connection);
return; return;
} }
dev->connection = connection; dev->connection = connection;
dev->automatic_finger = TRUE;
stream = g_io_stream_get_input_stream (G_IO_STREAM (connection)); stream = g_io_stream_get_input_stream (G_IO_STREAM (connection));
recv_image (dev, stream); recv_image (dev, stream);
+8 -10
View File
@@ -2,6 +2,7 @@
* Driver API definitions * Driver API definitions
* Copyright (C) 2007-2008 Daniel Drake <dsd@gentoo.org> * Copyright (C) 2007-2008 Daniel Drake <dsd@gentoo.org>
* Copyright (C) 2018 Bastien Nocera <hadess@hadess.net> * 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 * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * 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 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
#ifndef __DRIVERS_API_H__ #pragma once
#define __DRIVERS_API_H__
#include <config.h>
#include "fp_internal.h"
#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-log.h"
#include "fpi-print.h"
#include "fpi-usb-transfer.h" #include "fpi-usb-transfer.h"
#include "fpi-ssm.h" #include "fpi-ssm.h"
#include "fpi-assembling.h"
#include "fpi-image-device.h"
#endif
+54 -16
View File
@@ -57,6 +57,35 @@ enum {
}; };
static guint signals[LAST_SIGNAL] = { 0 }; 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 static void
async_device_init_done_cb (GObject *source_object, GAsyncResult *res, gpointer user_data) async_device_init_done_cb (GObject *source_object, GAsyncResult *res, gpointer user_data)
{ {
@@ -102,14 +131,11 @@ usb_device_added_cb (FpContext *self, GUsbDevice *device, GUsbContext *usb_ctx)
for (i = 0; i < priv->drivers->len; i++) for (i = 0; i < priv->drivers->len; i++)
{ {
GType driver = g_array_index (priv->drivers, GType, 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; const FpIdEntry *entry;
if (cls->type != FP_DEVICE_TYPE_USB) if (cls->type != FP_DEVICE_TYPE_USB)
{ continue;
g_type_class_unref (cls);
continue;
}
for (entry = cls->id_table; entry->pid; entry++) for (entry = cls->id_table; entry->pid; entry++)
{ {
@@ -129,8 +155,6 @@ usb_device_added_cb (FpContext *self, GUsbDevice *device, GUsbContext *usb_ctx)
found_driver = driver; found_driver = driver;
found_entry = entry; found_entry = entry;
} }
g_type_class_unref (cls);
} }
if (found_driver == G_TYPE_NONE) if (found_driver == G_TYPE_NONE)
@@ -145,8 +169,8 @@ usb_device_added_cb (FpContext *self, GUsbDevice *device, GUsbContext *usb_ctx)
priv->cancellable, priv->cancellable,
async_device_init_done_cb, async_device_init_done_cb,
self, self,
"fp-usb-device", device, "fpi-usb-device", device,
"fp-driver-data", found_entry->driver_data, "fpi-driver-data", found_entry->driver_data,
NULL); NULL);
} }
@@ -186,6 +210,8 @@ fp_context_finalize (GObject *object)
g_cancellable_cancel (priv->cancellable); g_cancellable_cancel (priv->cancellable);
g_clear_object (&priv->cancellable); g_clear_object (&priv->cancellable);
g_clear_pointer (&priv->drivers, g_array_unref); g_clear_pointer (&priv->drivers, g_array_unref);
g_object_run_dispose (G_OBJECT (priv->usb_ctx));
g_clear_object (&priv->usb_ctx); g_clear_object (&priv->usb_ctx);
G_OBJECT_CLASS (fp_context_parent_class)->finalize (object); G_OBJECT_CLASS (fp_context_parent_class)->finalize (object);
@@ -240,9 +266,23 @@ fp_context_init (FpContext *self)
{ {
g_autoptr(GError) error = NULL; g_autoptr(GError) error = NULL;
FpContextPrivate *priv = fp_context_get_instance_private (self); FpContextPrivate *priv = fp_context_get_instance_private (self);
guint i;
priv->drivers = g_array_new (TRUE, FALSE, sizeof (GType)); priv->drivers = fpi_get_driver_types ();
fpi_get_driver_types (priv->drivers);
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); priv->devices = g_ptr_array_new_with_free_func (g_object_unref);
@@ -309,7 +349,7 @@ fp_context_enumerate (FpContext *context)
for (i = 0; i < priv->drivers->len; i++) for (i = 0; i < priv->drivers->len; i++)
{ {
GType driver = g_array_index (priv->drivers, GType, 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; const FpIdEntry *entry;
if (cls->type != FP_DEVICE_TYPE_VIRTUAL) if (cls->type != FP_DEVICE_TYPE_VIRTUAL)
@@ -330,13 +370,11 @@ fp_context_enumerate (FpContext *context)
priv->cancellable, priv->cancellable,
async_device_init_done_cb, async_device_init_done_cb,
context, context,
"fp-environ", val, "fpi-environ", val,
"fp-driver-data", entry->driver_data, "fpi-driver-data", entry->driver_data,
NULL); NULL);
g_debug ("created"); g_debug ("created");
} }
g_type_class_unref (cls);
} }
while (priv->pending_devices) while (priv->pending_devices)
+82
View File
@@ -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);
+133 -1202
View File
File diff suppressed because it is too large Load Diff
+50 -2
View File
@@ -113,8 +113,8 @@ GQuark fp_device_error_quark (void);
* FpEnrollProgress: * FpEnrollProgress:
* @device: a #FpDevice * @device: a #FpDevice
* @completed_stages: Number of completed stages * @completed_stages: Number of completed stages
* @print: (nullable): The last scaned print * @print: (nullable) (transfer none): The last scaned print
* @user_data: (nullable): User provided data * @user_data: (nullable) (transfer none): User provided data
* @error: (nullable) (transfer none): #GError or %NULL * @error: (nullable) (transfer none): #GError or %NULL
* *
* The passed error is guaranteed to be of type %FP_DEVICE_RETRY if set. * 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, gpointer user_data,
GError *error); 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_driver (FpDevice *device);
const gchar *fp_device_get_device_id (FpDevice *device); const gchar *fp_device_get_device_id (FpDevice *device);
const gchar *fp_device_get_name (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); FpScanType fp_device_get_scan_type (FpDevice *device);
gint fp_device_get_nr_enroll_stages (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, void fp_device_verify (FpDevice *device,
FpPrint *enrolled_print, FpPrint *enrolled_print,
GCancellable *cancellable, GCancellable *cancellable,
FpMatchCb match_cb,
gpointer match_data,
GDestroyNotify match_destroy,
GAsyncReadyCallback callback, GAsyncReadyCallback callback,
gpointer user_data); gpointer user_data);
void fp_device_identify (FpDevice *device, void fp_device_identify (FpDevice *device,
GPtrArray *prints, GPtrArray *prints,
GCancellable *cancellable, GCancellable *cancellable,
FpMatchCb match_cb,
gpointer match_data,
GDestroyNotify match_destroy,
GAsyncReadyCallback callback, GAsyncReadyCallback callback,
gpointer user_data); gpointer user_data);
@@ -230,12 +274,16 @@ FpPrint * fp_device_enroll_sync (FpDevice *device,
gboolean fp_device_verify_sync (FpDevice *device, gboolean fp_device_verify_sync (FpDevice *device,
FpPrint *enrolled_print, FpPrint *enrolled_print,
GCancellable *cancellable, GCancellable *cancellable,
FpMatchCb match_cb,
gpointer match_data,
gboolean *match, gboolean *match,
FpPrint **print, FpPrint **print,
GError **error); GError **error);
gboolean fp_device_identify_sync (FpDevice *device, gboolean fp_device_identify_sync (FpDevice *device,
GPtrArray *prints, GPtrArray *prints,
GCancellable *cancellable, GCancellable *cancellable,
FpMatchCb match_cb,
gpointer match_data,
FpPrint **match, FpPrint **match,
FpPrint **print, FpPrint **print,
GError **error); GError **error);
+43
View File
@@ -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);
+109 -578
View File
@@ -20,13 +20,9 @@
#define FP_COMPONENT "image_device" #define FP_COMPONENT "image_device"
#include "fpi-log.h" #include "fpi-log.h"
#include "fpi-image-device.h" #include "fp-image-device-private.h"
#include "fpi-print.h"
#include "fpi-image.h"
#define MIN_ACCEPTABLE_MINUTIAE 10
#define BOZORTH3_DEFAULT_THRESHOLD 40 #define BOZORTH3_DEFAULT_THRESHOLD 40
#define IMG_ENROLL_STAGES 5
/** /**
* SECTION: fp-image-device * SECTION: fp-image-device
@@ -36,30 +32,23 @@
* This is a helper class for the commonly found image based devices. * 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) 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 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 static gboolean
pending_activation_timeout (gpointer user_data) pending_activation_timeout (gpointer user_data)
{ {
@@ -188,26 +106,29 @@ fp_image_device_close (FpDevice *device)
if (!priv->active) if (!priv->active)
cls->img_close (self); cls->img_close (self);
else if (priv->state != FP_IMAGE_DEVICE_STATE_INACTIVE) else if (priv->state != FPI_IMAGE_DEVICE_STATE_INACTIVE)
fp_image_device_deactivate (device); fpi_image_device_deactivate (self);
} }
static void static void
fp_image_device_cancel_action (FpDevice *device) fp_image_device_cancel_action (FpDevice *device)
{ {
FpImageDevice *self = FP_IMAGE_DEVICE (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); action = fpi_device_get_current_action (device);
/* We can only cancel capture operations, in that case, deactivate and return /* We can only cancel capture operations, in that case, deactivate and return
* an error immediately. */ * an error immediately. */
if (action == FP_DEVICE_ACTION_ENROLL || if (action == FPI_DEVICE_ACTION_ENROLL ||
action == FP_DEVICE_ACTION_VERIFY || action == FPI_DEVICE_ACTION_VERIFY ||
action == FP_DEVICE_ACTION_IDENTIFY || action == FPI_DEVICE_ACTION_IDENTIFY ||
action == FP_DEVICE_ACTION_CAPTURE) 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. */ /* XXX: Some nicer way of doing this would be good. */
fpi_device_action_error (FP_DEVICE (self), 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); FpImageDevice *self = FP_IMAGE_DEVICE (device);
FpImageDevicePrivate *priv = fp_image_device_get_instance_private (self); FpImageDevicePrivate *priv = fp_image_device_get_instance_private (self);
FpDeviceAction action; FpiDeviceAction action;
/* There is just one action that we cannot support out /* There is just one action that we cannot support out
* of the box, which is a capture without first waiting * of the box, which is a capture without first waiting
* for a finger to be on the device. * for a finger to be on the device.
*/ */
action = fpi_device_get_current_action (device); action = fpi_device_get_current_action (device);
if (action == FP_DEVICE_ACTION_CAPTURE) if (action == FPI_DEVICE_ACTION_CAPTURE)
{ {
gboolean wait_for_finger; gboolean wait_for_finger;
@@ -241,29 +162,30 @@ fp_image_device_start_capture_action (FpDevice *device)
return; return;
} }
} }
else if (action == FP_DEVICE_ACTION_ENROLL) else if (action == FPI_DEVICE_ACTION_ENROLL)
{ {
FpPrint *enroll_print = NULL; FpPrint *enroll_print = NULL;
fpi_device_get_enroll_data (device, &enroll_print); 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_stage = 0;
priv->enroll_await_on_pending = FALSE;
/* The device might still be deactivating from a previous call. /* The device might still be deactivating from a previous call.
* In that situation, try to wait for a bit before reporting back an * In that situation, try to wait for a bit before reporting back an
* error (which will usually say that the user should remove the * error (which will usually say that the user should remove the
* finger). * 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_debug ("Got a new request while the device was still active");
g_assert (priv->pending_activation_timeout_id == 0); g_assert (priv->pending_activation_timeout_id == 0);
priv->pending_activation_timeout_id = priv->pending_activation_timeout_id =
g_timeout_add (100, pending_activation_timeout, device); 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; priv->pending_activation_timeout_waiting_finger_off = TRUE;
else else
priv->pending_activation_timeout_waiting_finger_off = FALSE; 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() /* And activate the device; we rely on fpi_image_device_activate_complete()
* to be called when done (or immediately). */ * 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); FpImageDevicePrivate *priv = fp_image_device_get_instance_private (self);
g_assert (priv->active == FALSE); 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); 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); 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 static void
fp_image_device_class_init (FpImageDeviceClass *klass) 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); FpDeviceClass *fp_device_class = FP_DEVICE_CLASS (klass);
object_class->finalize = fp_image_device_finalize; 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->open = fp_image_device_open;
fp_device_class->close = fp_image_device_close; fp_device_class->close = fp_image_device_close;
@@ -322,474 +284,43 @@ fp_image_device_class_init (FpImageDeviceClass *klass)
/* Default implementations */ /* Default implementations */
klass->activate = fp_image_device_default_activate; klass->activate = fp_image_device_default_activate;
klass->deactivate = fp_image_device_default_deactivate; 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 static void
fp_image_device_init (FpImageDevice *self) 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);
} }
+4 -127
View File
@@ -18,13 +18,12 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
#define FP_COMPONENT "image"
#include "fpi-image.h" #include "fpi-image.h"
#include "fpi-log.h"
#include "nbis/include/lfs.h" #include <nbis.h>
#if HAVE_PIXMAN
#include <pixman.h>
#endif
/** /**
* SECTION: fp-image * SECTION: fp-image
@@ -35,15 +34,6 @@
* this object allows accessing this data. * 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) G_DEFINE_TYPE (FpImage, fp_image, G_TYPE_OBJECT)
enum { enum {
@@ -478,78 +468,6 @@ fp_image_detect_minutiae_finish (FpImage *self,
return g_task_propagate_boolean (G_TASK (result), error); 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: * fp_minutia_get_coords:
* @min: A #FpMinutia * @min: A #FpMinutia
@@ -567,44 +485,3 @@ fp_minutia_get_coords (FpMinutia *min, gint *x, gint *y)
if (y) if (y)
*y = min->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 * FPrint Print handling
* Copyright (C) 2012 Vasily Khoruzhick <anarsoul@gmail.com> * 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 * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * 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 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
#ifndef __DRIVER_IDS #include "fpi-print.h"
#define __DRIVER_IDS #include "fpi-image.h"
enum { #include <nbis.h>
UPEKTS_ID = 1,
URU4000_ID = 2, struct _FpPrint
AES4000_ID = 3, {
AES2501_ID = 4, GInitiallyUnowned parent_instance;
UPEKTC_ID = 5,
AES1610_ID = 6, FpiPrintType type;
/* FDU2000_ID = 7, */
VCOM5S_ID = 8, gchar *driver;
UPEKSONLY_ID = 9, gchar *device_id;
VFS101_ID = 10, gboolean device_stored;
VFS301_ID = 11,
AES2550_ID = 12, FpImage *image;
/* UPEKE2_ID = 13 */
AES1660_ID = 14, /* Metadata */
AES2660_ID = 15, FpFinger finger;
AES3500_ID = 16, gchar *username;
UPEKTC_IMG_ID = 17, gchar *description;
ETES603_ID = 18, GDate *enroll_date;
VFS5011_ID = 19,
VFS0050_ID = 20, GVariant *data;
ELAN_ID = 21, GPtrArray *prints;
}; };
#endif
+47 -273
View File
@@ -18,12 +18,11 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
#include "fpi-print.h" #define FP_COMPONENT "print"
#include "fpi-image.h"
#include "fpi-device.h"
#include "nbis/include/bozorth.h" #include "fp-print-private.h"
#include "nbis/include/lfs.h" #include "fpi-compat.h"
#include "fpi-log.h"
/** /**
* SECTION: fp-print * SECTION: fp-print
@@ -42,28 +41,6 @@
* #FpPrint routines. * #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) G_DEFINE_TYPE (FpPrint, fp_print, G_TYPE_INITIALLY_UNOWNED)
enum { enum {
@@ -101,6 +78,7 @@ fp_print_finalize (GObject *object)
g_clear_pointer (&self->description, g_free); g_clear_pointer (&self->description, g_free);
g_clear_pointer (&self->enroll_date, g_date_free); g_clear_pointer (&self->enroll_date, g_date_free);
g_clear_pointer (&self->data, g_variant_unref); 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); G_OBJECT_CLASS (fp_print_parent_class)->finalize (object);
} }
@@ -206,7 +184,7 @@ fp_print_set_property (GObject *object,
break; break;
case PROP_FPI_DATA: 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); self->data = g_value_dup_variant (value);
break; break;
@@ -291,16 +269,30 @@ fp_print_class_init (FpPrintClass *klass)
G_TYPE_DATE, G_TYPE_DATE,
G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE); G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE);
/**
* FpPrint::fpi-type: (skip)
*
* This property is only for internal purposes.
*
* Stability: private
*/
properties[PROP_FPI_TYPE] = properties[PROP_FPI_TYPE] =
g_param_spec_enum ("fp-type", g_param_spec_enum ("fpi-type",
"Type", "Type",
"Private: The type of the print data", "Private: The type of the print data",
FP_TYPE_PRINT_TYPE, FPI_TYPE_PRINT_TYPE,
FP_PRINT_RAW, FPI_PRINT_RAW,
G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY); 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] = properties[PROP_FPI_DATA] =
g_param_spec_variant ("fp-data", g_param_spec_variant ("fpi-data",
"Raw Data", "Raw Data",
"The raw data for internal use only", "The raw data for internal use only",
G_VARIANT_TYPE_ANY, G_VARIANT_TYPE_ANY,
@@ -534,228 +526,11 @@ fp_print_set_enroll_date (FpPrint *print,
g_clear_pointer (&print->enroll_date, g_date_free); g_clear_pointer (&print->enroll_date, g_date_free);
if (enroll_date) if (enroll_date)
{ print->enroll_date = g_date_copy (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;
}
g_object_notify_by_pspec (G_OBJECT (print), properties[PROP_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: * fp_print_compatible:
* @self: A #FpPrint * @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 (self), FALSE);
g_return_val_if_fail (FP_IS_PRINT (other), 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 (self->type != FPI_PRINT_UNDEFINED, FALSE);
g_return_val_if_fail (other->type != FP_PRINT_UNDEFINED, FALSE); g_return_val_if_fail (other->type != FPI_PRINT_UNDEFINED, FALSE);
if (self->type != other->type) if (self->type != other->type)
return FALSE; return FALSE;
@@ -807,11 +582,11 @@ fp_print_equal (FpPrint *self, FpPrint *other)
if (g_strcmp0 (self->device_id, other->device_id)) if (g_strcmp0 (self->device_id, other->device_id))
return FALSE; return FALSE;
if (self->type == FP_PRINT_RAW) if (self->type == FPI_PRINT_RAW)
{ {
return g_variant_equal (self->data, other->data); return g_variant_equal (self->data, other->data);
} }
else if (self->type == FP_PRINT_NBIS) else if (self->type == FPI_PRINT_NBIS)
{ {
gint i; gint i;
@@ -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); G_STATIC_ASSERT (sizeof (((struct xyt_struct *) NULL)->xcol[0]) == 4);
@@ -858,7 +633,7 @@ fp_print_serialize (FpPrint *print,
GError **error) GError **error)
{ {
g_autoptr(GVariant) result = NULL; 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; gsize len;
g_assert (data); g_assert (data);
@@ -883,7 +658,7 @@ fp_print_serialize (FpPrint *print,
g_variant_builder_close (&builder); g_variant_builder_close (&builder);
/* Insert NBIS print data for type NBIS, otherwise the GVariant directly */ /* 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))")); GVariantBuilder nested = G_VARIANT_BUILDER_INIT (G_VARIANT_TYPE ("(a(aiaiai))"));
gint i; gint i;
@@ -921,6 +696,7 @@ fp_print_serialize (FpPrint *print,
xyt->nrows, xyt->nrows,
sizeof (col[0]))); sizeof (col[0])));
g_variant_builder_close (&nested); g_variant_builder_close (&nested);
g_free (col);
} }
g_variant_builder_close (&nested); g_variant_builder_close (&nested);
@@ -976,18 +752,18 @@ fp_print_deserialize (const guchar *data,
g_autoptr(FpPrint) result = NULL; g_autoptr(FpPrint) result = NULL;
g_autoptr(GVariant) raw_value = NULL; g_autoptr(GVariant) raw_value = NULL;
g_autoptr(GVariant) value = NULL; g_autoptr(GVariant) value = NULL;
g_autoptr(GVariant) print_data = NULL;
g_autoptr(GDate) date = NULL;
guchar *aligned_data = NULL; guchar *aligned_data = NULL;
GDate *date = NULL;
guint8 finger_int8; guint8 finger_int8;
FpFinger finger; FpFinger finger;
g_autofree gchar *username = NULL; g_autofree gchar *username = NULL;
g_autofree gchar *description = NULL; g_autofree gchar *description = NULL;
gint julian_date; gint julian_date;
FpPrintType type; FpiPrintType type;
const gchar *driver; const gchar *driver;
const gchar *device_id; const gchar *device_id;
gboolean device_stored; gboolean device_stored;
GVariant *print_data;
g_assert (data); g_assert (data);
g_assert (length > 3); g_assert (length > 3);
@@ -1005,9 +781,9 @@ fp_print_deserialize (const guchar *data,
* longer. */ * longer. */
aligned_data = g_malloc (length - 3); aligned_data = g_malloc (length - 3);
memcpy (aligned_data, data + 3, 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, aligned_data, length - 3,
FALSE, g_free, NULL); FALSE, g_free, aligned_data);
if (!raw_value) if (!raw_value)
goto invalid_format; goto invalid_format;
@@ -1018,7 +794,7 @@ fp_print_deserialize (const guchar *data,
value = g_variant_get_normal_form (raw_value); value = g_variant_get_normal_form (raw_value);
g_variant_get (value, g_variant_get (value,
"(issbymsmsi@a{sv}v)", "(i&s&sbymsmsi@a{sv}v)",
&type, &type,
&driver, &driver,
&device_id, &device_id,
@@ -1033,7 +809,7 @@ fp_print_deserialize (const guchar *data,
finger = finger_int8; finger = finger_int8;
/* Assume data is valid at this point if the values are somewhat sane. */ /* 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); g_autoptr(GVariant) prints = g_variant_get_child_value (print_data, 0);
gint i; gint i;
@@ -1043,10 +819,10 @@ fp_print_deserialize (const guchar *data,
"device-id", device_id, "device-id", device_id,
"device-stored", device_stored, "device-stored", device_stored,
NULL); 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++) 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 = g_new0 (struct xyt_struct, 1);
const gint32 *xcol, *ycol, *thetacol; const gint32 *xcol, *ycol, *thetacol;
gsize xlen, ylen, thetalen; gsize xlen, ylen, thetalen;
g_autoptr(GVariant) xyt_data = NULL; g_autoptr(GVariant) xyt_data = NULL;
@@ -1077,19 +853,19 @@ fp_print_deserialize (const guchar *data,
memcpy (xyt->ycol, ycol, sizeof (xcol[0]) * xlen); memcpy (xyt->ycol, ycol, sizeof (xcol[0]) * xlen);
memcpy (xyt->thetacol, thetacol, 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); g_autoptr(GVariant) fp_data = g_variant_get_child_value (print_data, 0);
result = g_object_new (FP_TYPE_PRINT, result = g_object_new (FP_TYPE_PRINT,
"fp-type", type, "fpi-type", type,
"driver", driver, "driver", driver,
"device-id", device_id, "device-id", device_id,
"device-stored", device_stored, "device-stored", device_stored,
"fp-data", fp_data, "fpi-data", fp_data,
NULL); NULL);
} }
else else
@@ -1106,8 +882,6 @@ fp_print_deserialize (const guchar *data,
"enroll_date", date, "enroll_date", date,
NULL); NULL);
g_date_free (date);
return g_steal_pointer (&result); return g_steal_pointer (&result);
invalid_format: invalid_format:
+8
View File
@@ -28,6 +28,9 @@ G_BEGIN_DECLS
#define FP_TYPE_PRINT (fp_print_get_type ()) #define FP_TYPE_PRINT (fp_print_get_type ())
G_DECLARE_FINAL_TYPE (FpPrint, fp_print, FP, PRINT, GInitiallyUnowned) 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" #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_MIDDLE: Right middle finger
* @FP_FINGER_RIGHT_RING: Right ring finger * @FP_FINGER_RIGHT_RING: Right ring finger
* @FP_FINGER_RIGHT_LITTLE: Right little 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 { typedef enum {
FP_FINGER_UNKNOWN = 0, FP_FINGER_UNKNOWN = 0,
@@ -56,6 +61,9 @@ typedef enum {
FP_FINGER_RIGHT_MIDDLE, FP_FINGER_RIGHT_MIDDLE,
FP_FINGER_RIGHT_RING, FP_FINGER_RIGHT_RING,
FP_FINGER_RIGHT_LITTLE, FP_FINGER_RIGHT_LITTLE,
FP_FINGER_FIRST = FP_FINGER_LEFT_THUMB,
FP_FINGER_LAST = FP_FINGER_RIGHT_LITTLE,
} FpFinger; } FpFinger;
FpPrint *fp_print_new (FpDevice *device); FpPrint *fp_print_new (FpDevice *device);
+43 -32
View File
@@ -21,7 +21,8 @@
#define FP_COMPONENT "assembling" #define FP_COMPONENT "assembling"
#include "fp_internal.h" #include "fpi-log.h"
#include "fpi-image.h"
#include <string.h> #include <string.h>
@@ -51,6 +52,9 @@ calc_error (struct fpi_frame_asmbl_ctx *ctx,
width = ctx->frame_width - (dx > 0 ? dx : -dx); width = ctx->frame_width - (dx > 0 ? dx : -dx);
height = ctx->frame_height - dy; height = ctx->frame_height - dy;
if (height == 0 || width == 0)
return INT_MAX;
y1 = 0; y1 = 0;
y2 = dy; y2 = dy;
i = 0; i = 0;
@@ -85,9 +89,6 @@ calc_error (struct fpi_frame_asmbl_ctx *ctx,
err *= (ctx->frame_height * ctx->frame_width); err *= (ctx->frame_height * ctx->frame_width);
err /= (height * width); err /= (height * width);
if (err == 0)
return INT_MAX;
return err; return err;
} }
@@ -98,6 +99,8 @@ static void
find_overlap (struct fpi_frame_asmbl_ctx *ctx, find_overlap (struct fpi_frame_asmbl_ctx *ctx,
struct fpi_frame *first_frame, struct fpi_frame *first_frame,
struct fpi_frame *second_frame, struct fpi_frame *second_frame,
int *dx_out,
int *dy_out,
unsigned int *min_error) unsigned int *min_error)
{ {
int dx, dy; int dx, dy;
@@ -119,8 +122,8 @@ find_overlap (struct fpi_frame_asmbl_ctx *ctx,
if (err < *min_error) if (err < *min_error)
{ {
*min_error = err; *min_error = err;
second_frame->delta_x = -dx; *dx_out = -dx;
second_frame->delta_y = dy; *dy_out = dy;
} }
} }
} }
@@ -132,7 +135,7 @@ do_movement_estimation (struct fpi_frame_asmbl_ctx *ctx,
{ {
GSList *l; GSList *l;
GTimer *timer; GTimer *timer;
guint num_frames = 0; guint num_frames = 1;
struct fpi_frame *prev_stripe; struct fpi_frame *prev_stripe;
unsigned int min_error; unsigned int min_error;
/* Max error is width * height * 255, for AES2501 which has the largest /* 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; unsigned long long total_error = 0;
timer = g_timer_new (); timer = g_timer_new ();
/* Skip the first frame */
prev_stripe = stripes->data; 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; struct fpi_frame *cur_stripe = l->data;
if (reverse) 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_y = -cur_stripe->delta_y;
cur_stripe->delta_x = -cur_stripe->delta_x; cur_stripe->delta_x = -cur_stripe->delta_x;
} }
else 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; total_error += min_error;
@@ -327,19 +337,10 @@ fpi_assemble_frames (struct fpi_frame_asmbl_ctx *ctx,
{ {
fpi_frame = l->data; fpi_frame = l->data;
if(reverse) y += fpi_frame->delta_y;
{ x += fpi_frame->delta_x;
y += fpi_frame->delta_y;
x += fpi_frame->delta_x;
}
aes_blit_stripe (ctx, img, fpi_frame, x, y); aes_blit_stripe (ctx, img, fpi_frame, x, y);
if(!reverse)
{
y += fpi_frame->delta_y;
x += fpi_frame->delta_x;
}
} }
return img; return img;
@@ -385,8 +386,10 @@ median_filter (int *data, int size, int filtersize)
static void static void
interpolate_lines (struct fpi_line_asmbl_ctx *ctx, interpolate_lines (struct fpi_line_asmbl_ctx *ctx,
GSList *line1, float y1, GSList *line2, GSList *line1, gint32 y1_f,
float y2, unsigned char *output, float yi, int size) GSList *line2, gint32 y2_f,
unsigned char *output, gint32 yi_f,
int size)
{ {
int i; int i;
unsigned char p1, p2; unsigned char p1, p2;
@@ -396,10 +399,12 @@ interpolate_lines (struct fpi_line_asmbl_ctx *ctx,
for (i = 0; i < size; i++) for (i = 0; i < size; i++)
{ {
gint unscaled;
p1 = ctx->get_pixel (ctx, line1, i); p1 = ctx->get_pixel (ctx, line1, i);
p2 = ctx->get_pixel (ctx, line2, 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 */ /* Number of output lines per distance between two scanners */
int i; int i;
GSList *row1, *row2; 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 line_ind = 0;
int *offsets = g_new0 (int, num_lines / 2); int *offsets = g_new0 (int, num_lines / 2);
unsigned char *output = g_malloc0 (ctx->line_width * ctx->max_height); 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]; int offset = offsets[i / 2];
if (offset > 0) if (offset > 0)
{ {
float ynext = y + (float) ctx->resolution / offset; gint32 ynext_f = y_f + (ctx->resolution << 16) / offset;
while (line_ind < ynext) while ((line_ind << 16) < ynext_f)
{ {
if (line_ind > ctx->max_height - 1) if (line_ind > ctx->max_height - 1)
goto out; goto out;
interpolate_lines (ctx, interpolate_lines (ctx,
row1, y, row1, y_f,
g_slist_next (row1), g_slist_next (row1),
ynext, ynext_f,
output + line_ind * ctx->line_width, output + line_ind * ctx->line_width,
line_ind, line_ind << 16,
ctx->line_width); ctx->line_width);
line_ind++; line_ind++;
} }
y = ynext; y_f = ynext_f;
} }
} }
out: out:
+1 -4
View File
@@ -17,8 +17,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
#ifndef __FPI_ASSEMBLING_H__ #pragma once
#define __FPI_ASSEMBLING_H__
#include <fprint.h> #include <fprint.h>
@@ -116,5 +115,3 @@ struct fpi_line_asmbl_ctx
FpImage *fpi_assemble_lines (struct fpi_line_asmbl_ctx *ctx, FpImage *fpi_assemble_lines (struct fpi_line_asmbl_ctx *ctx,
GSList *lines, GSList *lines,
size_t num_lines); size_t num_lines);
#endif
+1 -4
View File
@@ -19,8 +19,7 @@
* Boston, MA 02110-1301, USA. * Boston, MA 02110-1301, USA.
*/ */
#ifndef __FPI_BYTE_READER_H__ #pragma once
#define __FPI_BYTE_READER_H__
#include <glib.h> #include <glib.h>
#include "fpi-byte-utils.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 */ #endif /* FPI_BYTE_READER_DISABLE_INLINES */
G_END_DECLS G_END_DECLS
#endif /* __FPI_BYTE_READER_H__ */
+1 -4
View File
@@ -21,9 +21,7 @@
* Boston, MA 02110-1301, USA. * Boston, MA 02110-1301, USA.
*/ */
#pragma once
#ifndef __FP_UTILS_H__
#define __FP_UTILS_H__
#include <glib.h> #include <glib.h>
@@ -485,4 +483,3 @@ FP_WRITE_DOUBLE_BE(guint8 *data, gdouble num)
G_END_DECLS G_END_DECLS
#endif /* __GTK_DOC_IGNORE__ */ #endif /* __GTK_DOC_IGNORE__ */
#endif /* __FP_UTILS_H__ */
+1 -4
View File
@@ -18,8 +18,7 @@
* Boston, MA 02110-1301, USA. * Boston, MA 02110-1301, USA.
*/ */
#ifndef __FPI_BYTE_WRITER_H__ #pragma once
#define __FPI_BYTE_WRITER_H__
#include "fpi-byte-reader.h" #include "fpi-byte-reader.h"
#include <string.h> #include <string.h>
@@ -409,5 +408,3 @@ fpi_byte_writer_fill_inline (FpiByteWriter * writer, guint8 value, guint size)
#endif #endif
G_END_DECLS G_END_DECLS
#endif /* __FPI_BYTE_WRITER_H__ */
+39
View File
@@ -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
+4 -2
View File
@@ -20,14 +20,16 @@
#include <gusb.h> #include <gusb.h>
#include "fp-context.h" #include "fp-context.h"
#include "fpi-compat.h"
/** /**
* fpi_get_driver_types: * 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 * This function is purely for private used. It is solely part of the public
* API as it is useful during build time. * API as it is useful during build time.
* *
* Stability: private * 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
+42 -36
View File
@@ -142,48 +142,50 @@ typedef void (*FpTimeoutFunc) (FpDevice *device,
gpointer user_data); gpointer user_data);
/** /**
* FpDeviceAction: * FpiDeviceAction:
* @FP_DEVICE_ACTION_NONE: No action is active. * @FPI_DEVICE_ACTION_NONE: No action is active.
* @FP_DEVICE_ACTION_PROBE: Probe device for support and information. * @FPI_DEVICE_ACTION_PROBE: Probe device for support and information.
* @FP_DEVICE_ACTION_OPEN: Device is currently being opened. * @FPI_DEVICE_ACTION_OPEN: Device is currently being opened.
* @FP_DEVICE_ACTION_CLOSE: Device is currently being closed. * @FPI_DEVICE_ACTION_CLOSE: Device is currently being closed.
* @FP_DEVICE_ACTION_ENROLL: Device is currently enrolling. * @FPI_DEVICE_ACTION_ENROLL: Device is currently enrolling.
* @FP_DEVICE_ACTION_VERIFY: Device is currently verifying. * @FPI_DEVICE_ACTION_VERIFY: Device is currently verifying.
* @FP_DEVICE_ACTION_IDENTIFY: Device is currently identifying. * @FPI_DEVICE_ACTION_IDENTIFY: Device is currently identifying.
* @FP_DEVICE_ACTION_CAPTURE: Device is currently capturing an image. * @FPI_DEVICE_ACTION_CAPTURE: Device is currently capturing an image.
* @FP_DEVICE_ACTION_LIST: Device stored prints are being queried. * @FPI_DEVICE_ACTION_LIST: Device stored prints are being queried.
* @FP_DEVICE_ACTION_DELETE: Device stored print is being deleted. * @FPI_DEVICE_ACTION_DELETE: Device stored print is being deleted.
* *
* Current active action of the device. A driver can retrieve the action. * Current active action of the device. A driver can retrieve the action.
*/ */
typedef enum { typedef enum {
FP_DEVICE_ACTION_NONE = 0, FPI_DEVICE_ACTION_NONE = 0,
FP_DEVICE_ACTION_PROBE, FPI_DEVICE_ACTION_PROBE,
FP_DEVICE_ACTION_OPEN, FPI_DEVICE_ACTION_OPEN,
FP_DEVICE_ACTION_CLOSE, FPI_DEVICE_ACTION_CLOSE,
FP_DEVICE_ACTION_ENROLL, FPI_DEVICE_ACTION_ENROLL,
FP_DEVICE_ACTION_VERIFY, FPI_DEVICE_ACTION_VERIFY,
FP_DEVICE_ACTION_IDENTIFY, FPI_DEVICE_ACTION_IDENTIFY,
FP_DEVICE_ACTION_CAPTURE, FPI_DEVICE_ACTION_CAPTURE,
FP_DEVICE_ACTION_LIST, FPI_DEVICE_ACTION_LIST,
FP_DEVICE_ACTION_DELETE, FPI_DEVICE_ACTION_DELETE,
} FpDeviceAction; } FpiDeviceAction;
GUsbDevice *fpi_device_get_usb_device (FpDevice *device); GUsbDevice *fpi_device_get_usb_device (FpDevice *device);
const gchar *fpi_device_get_virtual_env (FpDevice *device); const gchar *fpi_device_get_virtual_env (FpDevice *device);
//const gchar *fpi_device_get_spi_dev (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); gboolean fpi_device_action_is_cancelled (FpDevice *device);
GError * fpi_device_retry_new (FpDeviceRetry error); GError * fpi_device_retry_new (FpDeviceRetry error);
GError * fpi_device_error_new (FpDeviceError error); GError * fpi_device_error_new (FpDeviceError error);
GError * fpi_device_retry_new_msg (FpDeviceRetry 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, 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); 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); GCancellable *fpi_device_get_cancellable (FpDevice *device);
GSource * fpi_device_add_timeout (FpDevice *device,
GSource * fpi_device_add_timeout (FpDevice *device, gint interval,
gint interval, FpTimeoutFunc func,
FpTimeoutFunc func, gpointer user_data,
gpointer user_data); GDestroyNotify destroy_notify);
void fpi_device_set_nr_enroll_stages (FpDevice *device, void fpi_device_set_nr_enroll_stages (FpDevice *device,
gint enroll_stages); gint enroll_stages);
@@ -227,13 +229,9 @@ void fpi_device_close_complete (FpDevice *device,
void fpi_device_enroll_complete (FpDevice *device, void fpi_device_enroll_complete (FpDevice *device,
FpPrint *print, FpPrint *print,
GError *error); GError *error);
void fpi_device_verify_complete (FpDevice *device, void fpi_device_verify_complete (FpDevice *device,
FpiMatchResult result, GError *error);
FpPrint *print,
GError *error);
void fpi_device_identify_complete (FpDevice *device, void fpi_device_identify_complete (FpDevice *device,
FpPrint *match,
FpPrint *print,
GError *error); GError *error);
void fpi_device_capture_complete (FpDevice *device, void fpi_device_capture_complete (FpDevice *device,
FpImage *image, FpImage *image,
@@ -248,5 +246,13 @@ void fpi_device_enroll_progress (FpDevice *device,
gint completed_stages, gint completed_stages,
FpPrint *print, FpPrint *print,
GError *error); 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 G_END_DECLS
+636
View File
@@ -0,0 +1,636 @@
/*
* 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
* @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>.
*/
/* 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 (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);
}
+12 -12
View File
@@ -23,11 +23,11 @@
#include "fp-image-device.h" #include "fp-image-device.h"
/** /**
* FpImageDeviceState: * FpiImageDeviceState:
* @FP_IMAGE_DEVICE_STATE_INACTIVE: inactive * @FPI_IMAGE_DEVICE_STATE_INACTIVE: inactive
* @FP_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON: waiting for the finger to be pressed or swiped * @FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON: waiting for the finger to be pressed or swiped
* @FP_IMAGE_DEVICE_STATE_CAPTURE: capturing an image * @FPI_IMAGE_DEVICE_STATE_CAPTURE: capturing an image
* @FP_IMAGE_DEVICE_STATE_AWAIT_FINGER_OFF: waiting for the finger to be removed * @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 * 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. * passed through to the driver using the ::activate() or ::change_state() vfuncs.
@@ -37,11 +37,11 @@
* unconditionally if the device supports raw capturing. * unconditionally if the device supports raw capturing.
*/ */
typedef enum { typedef enum {
FP_IMAGE_DEVICE_STATE_INACTIVE, FPI_IMAGE_DEVICE_STATE_INACTIVE,
FP_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON, FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON,
FP_IMAGE_DEVICE_STATE_CAPTURE, FPI_IMAGE_DEVICE_STATE_CAPTURE,
FP_IMAGE_DEVICE_STATE_AWAIT_FINGER_OFF, FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_OFF,
} FpImageDeviceState; } FpiImageDeviceState;
/** /**
* FpImageDeviceClass: * FpImageDeviceClass:
@@ -90,8 +90,8 @@ struct _FpImageDeviceClass
void (*img_open) (FpImageDevice *dev); void (*img_open) (FpImageDevice *dev);
void (*img_close) (FpImageDevice *dev); void (*img_close) (FpImageDevice *dev);
void (*activate) (FpImageDevice *dev); void (*activate) (FpImageDevice *dev);
void (*change_state) (FpImageDevice *dev, void (*change_state) (FpImageDevice *dev,
FpImageDeviceState state); FpiImageDeviceState state);
void (*deactivate) (FpImageDevice *dev); void (*deactivate) (FpImageDevice *dev);
}; };
+150
View File
@@ -0,0 +1,150 @@
/*
* 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. Also see the public <ulink
* url="libfprint-FpImage.html">FpImage routines</ulink>.
*/
/**
* 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
+3 -6
View File
@@ -17,8 +17,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
#ifndef __FPI_LOG_H__ #pragma once
#define __FPI_LOG_H__
/** /**
* SECTION:fpi-log * SECTION:fpi-log
@@ -68,11 +67,11 @@
/** /**
* fp_err: * 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 * g_assert() instead, so bear this in mind when adding those calls
* to your driver. * to your driver.
*/ */
#define fp_err g_warning #define fp_err g_critical
/** /**
* BUG_ON: * BUG_ON:
@@ -94,5 +93,3 @@
* Same as BUG_ON() but is always true. * Same as BUG_ON() but is always true.
*/ */
#define BUG() BUG_ON (1) #define BUG() BUG_ON (1)
#endif
@@ -17,13 +17,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
#ifndef __FPRINT_INTERNAL_H__ #pragma once
#define __FPRINT_INTERNAL_H__
#include "fpi-log.h"
#include "nbis-helpers.h"
#include "fpi-image.h"
#include "fpi-image-device.h"
/* fp_minutia structure definition */ /* fp_minutia structure definition */
struct fp_minutia struct fp_minutia
@@ -49,6 +43,3 @@ struct fp_minutiae
int num; int num;
struct fp_minutia **list; struct fp_minutia **list;
}; };
#endif
+249
View File
@@ -0,0 +1,249 @@
/*
* 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"
/**
* 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;
}
+14 -14
View File
@@ -7,34 +7,34 @@
G_BEGIN_DECLS G_BEGIN_DECLS
/** /**
* FpPrintType: * FpiPrintType:
* @FP_PRINT_UNDEFINED: Undefined type, this happens prior to enrollment * @FPI_PRINT_UNDEFINED: Undefined type, this happens prior to enrollment
* @FP_PRINT_RAW: A raw print where the data is directly compared * @FPI_PRINT_RAW: A raw print where the data is directly compared
* @FP_PRINT_NBIS: NBIS minutiae comparison * @FPI_PRINT_NBIS: NBIS minutiae comparison
*/ */
typedef enum { typedef enum {
FP_PRINT_UNDEFINED = 0, FPI_PRINT_UNDEFINED = 0,
FP_PRINT_RAW, FPI_PRINT_RAW,
FP_PRINT_NBIS, FPI_PRINT_NBIS,
} FpPrintType; } FpiPrintType;
/** /**
* FpiMatchResult: * FpiMatchResult:
* @FPI_MATCH_ERROR: An error occured during matching * @FPI_MATCH_ERROR: An error occured during matching
* @FPI_MATCH_SUCCESS: The prints matched
* @FPI_MATCH_FAIL: The prints did not match * @FPI_MATCH_FAIL: The prints did not match
* @FPI_MATCH_SUCCESS: The prints matched
*/ */
typedef enum { typedef enum {
FPI_MATCH_ERROR = 0, FPI_MATCH_ERROR = -1, /* -1 for g_task_propagate_int */
FPI_MATCH_SUCCESS,
FPI_MATCH_FAIL, FPI_MATCH_FAIL,
FPI_MATCH_SUCCESS,
} FpiMatchResult; } FpiMatchResult;
void fpi_print_add_print (FpPrint *print, void fpi_print_add_print (FpPrint *print,
FpPrint *add); FpPrint *add);
void fpi_print_set_type (FpPrint *print, void fpi_print_set_type (FpPrint *print,
FpPrintType type); FpiPrintType type);
void fpi_print_set_device_stored (FpPrint *print, void fpi_print_set_device_stored (FpPrint *print,
gboolean device_stored); gboolean device_stored);
@@ -43,7 +43,7 @@ gboolean fpi_print_add_from_image (FpPrint *print,
GError **error); GError **error);
FpiMatchResult fpi_print_bz3_match (FpPrint * template, FpiMatchResult fpi_print_bz3_match (FpPrint * template,
FpPrint *print, FpPrint * print,
gint bz3_threshold, gint bz3_threshold,
GError **error); GError **error);
+330 -39
View File
@@ -2,6 +2,7 @@
* Functions to assist with asynchronous driver <---> library communications * Functions to assist with asynchronous driver <---> library communications
* Copyright (C) 2007-2008 Daniel Drake <dsd@gentoo.org> * Copyright (C) 2007-2008 Daniel Drake <dsd@gentoo.org>
* Copyright (C) 2019 Benjamin Berg <bberg@redhat.com> * 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 * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * 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() * 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). * 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 * 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 * 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 * To mark successful completion of a SSM, either iterate beyond the final
* state or call fpi_ssm_mark_completed() from any state. * 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 * To mark failed completion of a SSM, call fpi_ssm_mark_failed() from any
* state. You must pass a non-zero error code. * state. You must pass a non-zero error code.
@@ -78,12 +81,16 @@
struct _FpiSsm struct _FpiSsm
{ {
FpDevice *dev; FpDevice *dev;
const char *name;
FpiSsm *parentsm; FpiSsm *parentsm;
gpointer ssm_data; gpointer ssm_data;
GDestroyNotify ssm_data_destroy; GDestroyNotify ssm_data_destroy;
int nr_states; int nr_states;
int cur_state; int cur_state;
gboolean completed; gboolean completed;
GSource *timeout;
GCancellable *cancellable;
gulong cancellable_id;
GError *error; GError *error;
FpiSsmCompletedCallback callback; FpiSsmCompletedCallback callback;
FpiSsmHandlerCallback handler; FpiSsmHandlerCallback handler;
@@ -97,22 +104,40 @@ struct _FpiSsm
* *
* Allocate a new ssm, with @nr_states states. The @handler callback * Allocate a new ssm, with @nr_states states. The @handler callback
* will be called after each state transition. * 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 * Returns: a new #FpiSsm state machine
*/ */
FpiSsm * FpiSsm *
fpi_ssm_new (FpDevice *dev, fpi_ssm_new_full (FpDevice *dev,
FpiSsmHandlerCallback handler, FpiSsmHandlerCallback handler,
int nr_states) int nr_states,
const char *machine_name)
{ {
FpiSsm *machine; FpiSsm *machine;
BUG_ON (nr_states < 1); BUG_ON (nr_states < 1);
BUG_ON (handler == NULL);
machine = g_new0 (FpiSsm, 1); machine = g_new0 (FpiSsm, 1);
machine->handler = handler; machine->handler = handler;
machine->nr_states = nr_states; machine->nr_states = nr_states;
machine->dev = dev; machine->dev = dev;
machine->name = g_strdup (machine_name);
machine->completed = TRUE; machine->completed = TRUE;
return machine; return machine;
} }
@@ -124,7 +149,6 @@ fpi_ssm_new (FpDevice *dev,
* @ssm_data_destroy: (nullable): #GDestroyNotify for @ssm_data * @ssm_data_destroy: (nullable): #GDestroyNotify for @ssm_data
* *
* Sets @machine's data (freeing the existing data, if any). * Sets @machine's data (freeing the existing data, if any).
*
*/ */
void void
fpi_ssm_set_data (FpiSsm *machine, fpi_ssm_set_data (FpiSsm *machine,
@@ -152,6 +176,84 @@ fpi_ssm_get_data (FpiSsm *machine)
return machine->ssm_data; 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: * fpi_ssm_free:
* @machine: an #FpiSsm state machine * @machine: an #FpiSsm state machine
@@ -165,9 +267,13 @@ fpi_ssm_free (FpiSsm *machine)
if (!machine) if (!machine)
return; return;
BUG_ON (machine->timeout != NULL);
if (machine->ssm_data_destroy) if (machine->ssm_data_destroy)
g_clear_pointer (&machine->ssm_data, 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->error, g_error_free);
g_clear_pointer (&machine->name, g_free);
fpi_ssm_clear_delayed_action (machine);
g_free (machine); g_free (machine);
} }
@@ -175,18 +281,23 @@ fpi_ssm_free (FpiSsm *machine)
static void static void
__ssm_call_handler (FpiSsm *machine) __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); machine->handler (machine, machine->dev);
} }
/** /**
* fpi_ssm_start: * fpi_ssm_start:
* @ssm: an #FpiSsm state machine * @ssm: (transfer full): an #FpiSsm state machine
* @callback: the #FpiSsmCompletedCallback callback to call on completion * @callback: the #FpiSsmCompletedCallback callback to call on completion
* *
* Starts a state machine. You can also use this function to restart * Starts a state machine. You can also use this function to restart
* a completed or failed state machine. The @callback will be called * a completed or failed state machine. The @callback will be called
* on completion. * 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 void
fpi_ssm_start (FpiSsm *ssm, FpiSsmCompletedCallback callback) 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); fpi_ssm_mark_failed (parent, error);
else else
fpi_ssm_next_state (parent); fpi_ssm_next_state (parent);
fpi_ssm_free (ssm);
} }
/** /**
@@ -226,7 +336,12 @@ __subsm_complete (FpiSsm *ssm, FpDevice *_dev, GError *error)
void void
fpi_ssm_start_subsm (FpiSsm *parent, FpiSsm *child) fpi_ssm_start_subsm (FpiSsm *parent, FpiSsm *child)
{ {
BUG_ON (parent->timeout);
child->parentsm = parent; child->parentsm = parent;
fpi_ssm_clear_delayed_action (parent);
fpi_ssm_clear_delayed_action (child);
fpi_ssm_start (child, __subsm_complete); fpi_ssm_start (child, __subsm_complete);
} }
@@ -241,25 +356,73 @@ void
fpi_ssm_mark_completed (FpiSsm *machine) fpi_ssm_mark_completed (FpiSsm *machine)
{ {
BUG_ON (machine->completed); BUG_ON (machine->completed);
BUG_ON (machine->timeout != NULL);
fpi_ssm_clear_delayed_action (machine);
machine->completed = TRUE; machine->completed = TRUE;
if (machine->error) 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 else
fp_dbg ("%p completed successfully", machine); fp_dbg ("[%s] %s completed successfully", fp_device_get_driver (machine->dev),
machine->name);
if (machine->callback) if (machine->callback)
{ {
GError *error = machine->error ? g_error_copy (machine->error) : NULL; GError *error = machine->error ? g_error_copy (machine->error) : NULL;
machine->callback (machine, machine->dev, error); 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: * fpi_ssm_mark_failed:
* @machine: an #FpiSsm state machine * @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 void
fpi_ssm_mark_failed (FpiSsm *machine, GError *error) fpi_ssm_mark_failed (FpiSsm *machine, GError *error)
@@ -267,13 +430,16 @@ fpi_ssm_mark_failed (FpiSsm *machine, GError *error)
g_assert (error); g_assert (error);
if (machine->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); g_error_free (error);
return; return;
} }
fp_dbg ("SSM failed in state %d with error: %s", machine->cur_state, error->message); fp_dbg ("[%s] SSM %s failed in state %d with error: %s",
machine->error = error; fp_device_get_driver (machine->dev), machine->name,
machine->cur_state, error->message);
machine->error = g_steal_pointer (&error);
fpi_ssm_mark_completed (machine); fpi_ssm_mark_completed (machine);
} }
@@ -291,6 +457,10 @@ fpi_ssm_next_state (FpiSsm *machine)
g_return_if_fail (machine != NULL); g_return_if_fail (machine != NULL);
BUG_ON (machine->completed); BUG_ON (machine->completed);
BUG_ON (machine->timeout != NULL);
fpi_ssm_clear_delayed_action (machine);
machine->cur_state++; machine->cur_state++;
if (machine->cur_state == machine->nr_states) if (machine->cur_state == machine->nr_states)
fpi_ssm_mark_completed (machine); fpi_ssm_mark_completed (machine);
@@ -298,22 +468,136 @@ fpi_ssm_next_state (FpiSsm *machine)
__ssm_call_handler (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: * fpi_ssm_jump_to_state:
* @machine: an #FpiSsm state machine * @machine: an #FpiSsm state machine
* @state: the state to jump to * @state: the state to jump to
* *
* Jump to the @state state, bypassing intermediary states. * 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 void
fpi_ssm_jump_to_state (FpiSsm *machine, int state) fpi_ssm_jump_to_state (FpiSsm *machine, int state)
{ {
BUG_ON (machine->completed); 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; machine->cur_state = state;
__ssm_call_handler (machine); __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: * fpi_ssm_get_cur_state:
* @machine: an #FpiSsm state machine * @machine: an #FpiSsm state machine
@@ -360,33 +644,11 @@ fpi_ssm_dup_error (FpiSsm *machine)
return NULL; 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: * fpi_ssm_usb_transfer_cb:
* @transfer: a #FpiUsbTransfer * @transfer: a #FpiUsbTransfer
* @device: a #FpDevice * @device: a #FpDevice
* @ssm_data: User data (unused) * @unused_data: User data (unused)
* @error: The #GError or %NULL * @error: The #GError or %NULL
* *
* Can be used in as a #FpiUsbTransfer callback handler to automatically * Can be used in as a #FpiUsbTransfer callback handler to automatically
@@ -396,7 +658,7 @@ fpi_ssm_next_state_timeout_cb (FpDevice *dev,
*/ */
void void
fpi_ssm_usb_transfer_cb (FpiUsbTransfer *transfer, FpDevice *device, 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); g_return_if_fail (transfer->ssm);
@@ -405,3 +667,32 @@ fpi_ssm_usb_transfer_cb (FpiUsbTransfer *transfer, FpDevice *device,
else else
fpi_ssm_next_state (transfer->ssm); 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);
}
+28 -8
View File
@@ -2,6 +2,7 @@
* Copyright (C) 2007-2008 Daniel Drake <dsd@gentoo.org> * Copyright (C) 2007-2008 Daniel Drake <dsd@gentoo.org>
* Copyright (C) 2018 Bastien Nocera <hadess@hadess.net> * Copyright (C) 2018 Bastien Nocera <hadess@hadess.net>
* Copyright (C) 2019 Benjamin Berg <bberg@redhat.com> * 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 * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * modify it under the terms of the GNU Lesser General Public
@@ -21,7 +22,6 @@
#pragma once #pragma once
#include "fp-device.h" #include "fp-device.h"
#include "fpi-usb-transfer.h"
/* async drv <--> lib comms */ /* async drv <--> lib comms */
@@ -38,7 +38,7 @@ typedef struct _FpiSsm FpiSsm;
* FpiSsmCompletedCallback: * FpiSsmCompletedCallback:
* @ssm: a #FpiSsm state machine * @ssm: a #FpiSsm state machine
* @dev: the #fp_dev fingerprint device * @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, * The callback called when a state machine completes successfully,
* as set when calling fpi_ssm_start(). * as set when calling fpi_ssm_start().
@@ -59,9 +59,12 @@ typedef void (*FpiSsmHandlerCallback)(FpiSsm *ssm,
FpDevice *dev); FpDevice *dev);
/* for library and drivers */ /* for library and drivers */
FpiSsm *fpi_ssm_new (FpDevice *dev, #define fpi_ssm_new(dev, handler, nr_states) \
FpiSsmHandlerCallback handler, fpi_ssm_new_full (dev, handler, nr_states, #nr_states)
int nr_states); FpiSsm *fpi_ssm_new_full (FpDevice *dev,
FpiSsmHandlerCallback handler,
int nr_states,
const char *machine_name);
void fpi_ssm_free (FpiSsm *machine); void fpi_ssm_free (FpiSsm *machine);
void fpi_ssm_start (FpiSsm *ssm, void fpi_ssm_start (FpiSsm *ssm,
FpiSsmCompletedCallback callback); FpiSsmCompletedCallback callback);
@@ -72,7 +75,18 @@ void fpi_ssm_start_subsm (FpiSsm *parent,
void fpi_ssm_next_state (FpiSsm *machine); void fpi_ssm_next_state (FpiSsm *machine);
void fpi_ssm_jump_to_state (FpiSsm *machine, void fpi_ssm_jump_to_state (FpiSsm *machine,
int state); 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 (FpiSsm *machine);
void fpi_ssm_mark_completed_delayed (FpiSsm *machine,
int delay,
GCancellable *cancellable);
void fpi_ssm_mark_failed (FpiSsm *machine, void fpi_ssm_mark_failed (FpiSsm *machine,
GError *error); GError *error);
void fpi_ssm_set_data (FpiSsm *machine, 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 /* Callbacks to be used by the driver instead of implementing their own
* logic. * logic.
*/ */
void fpi_ssm_next_state_timeout_cb (FpDevice *dev, typedef struct _FpiUsbTransfer FpiUsbTransfer;
void *data);
void fpi_ssm_usb_transfer_cb (FpiUsbTransfer *transfer, void fpi_ssm_usb_transfer_cb (FpiUsbTransfer *transfer,
FpDevice *device, FpDevice *device,
gpointer user_data, gpointer unused_data,
GError *error); 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)
+11 -14
View File
@@ -298,7 +298,7 @@ fpi_usb_transfer_fill_interrupt_full (FpiUsbTransfer *transfer,
transfer->free_buffer = free_func; transfer->free_buffer = free_func;
} }
void static void
transfer_finish_cb (GObject *source_object, GAsyncResult *res, gpointer user_data) transfer_finish_cb (GObject *source_object, GAsyncResult *res, gpointer user_data)
{ {
GError *error = NULL; GError *error = NULL;
@@ -356,7 +356,7 @@ transfer_finish_cb (GObject *source_object, GAsyncResult *res, gpointer user_dat
/** /**
* fpi_usb_transfer_submit: * 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 * @timeout_ms: Timeout for the transfer in ms
* @cancellable: Cancellable to use, e.g. fpi_device_get_cancellable() * @cancellable: Cancellable to use, e.g. fpi_device_get_cancellable()
* @callback: Callback on completion or error * @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. * Submit a USB transfer with a specific timeout and callback functions.
* *
* Note that #FpiUsbTransfer is owned by the user. In most cases, you * Note that #FpiUsbTransfer will be stolen when this function is called.
* should call fpi_usb_transfer_unref() just after calling this function. * So that all associated data will be free'ed automatically, after the
* Doing so means that all associated data will be free'ed automatically * callback ran unless fpi_usb_transfer_ref() is explictly called.
* after the callback ran.
*/ */
void void
fpi_usb_transfer_submit (FpiUsbTransfer *transfer, fpi_usb_transfer_submit (FpiUsbTransfer *transfer,
@@ -385,11 +384,6 @@ fpi_usb_transfer_submit (FpiUsbTransfer *transfer,
transfer->callback = callback; transfer->callback = callback;
transfer->user_data = user_data; 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); log_transfer (transfer, TRUE, NULL);
switch (transfer->type) switch (transfer->type)
@@ -460,6 +454,7 @@ fpi_usb_transfer_submit_sync (FpiUsbTransfer *transfer,
GError **error) GError **error)
{ {
gboolean res; gboolean res;
gsize actual_length;
g_return_val_if_fail (transfer, FALSE); g_return_val_if_fail (transfer, FALSE);
@@ -475,7 +470,7 @@ fpi_usb_transfer_submit_sync (FpiUsbTransfer *transfer,
transfer->endpoint, transfer->endpoint,
transfer->buffer, transfer->buffer,
transfer->length, transfer->length,
&transfer->actual_length, &actual_length,
timeout_ms, timeout_ms,
NULL, NULL,
error); error);
@@ -491,7 +486,7 @@ fpi_usb_transfer_submit_sync (FpiUsbTransfer *transfer,
transfer->idx, transfer->idx,
transfer->buffer, transfer->buffer,
transfer->length, transfer->length,
&transfer->actual_length, &actual_length,
timeout_ms, timeout_ms,
NULL, NULL,
error); error);
@@ -502,7 +497,7 @@ fpi_usb_transfer_submit_sync (FpiUsbTransfer *transfer,
transfer->endpoint, transfer->endpoint,
transfer->buffer, transfer->buffer,
transfer->length, transfer->length,
&transfer->actual_length, &actual_length,
timeout_ms, timeout_ms,
NULL, NULL,
error); error);
@@ -517,6 +512,8 @@ fpi_usb_transfer_submit_sync (FpiUsbTransfer *transfer,
if (!res) if (!res)
transfer->actual_length = -1; transfer->actual_length = -1;
else
transfer->actual_length = actual_length;
return res; return res;
} }
+1 -2
View File
@@ -30,8 +30,7 @@ G_BEGIN_DECLS
#define FPI_USB_ENDPOINT_OUT 0x00 #define FPI_USB_ENDPOINT_OUT 0x00
typedef struct _FpiUsbTransfer FpiUsbTransfer; typedef struct _FpiUsbTransfer FpiUsbTransfer;
typedef struct _FpiSsm FpiSsm;
#include "fpi-ssm.h"
typedef void (*FpiUsbTransferCallback)(FpiUsbTransfer *transfer, typedef void (*FpiUsbTransferCallback)(FpiUsbTransfer *transfer,
FpDevice *dev, FpDevice *dev,
+3 -10
View File
@@ -31,23 +31,18 @@ GHashTable *printed = NULL;
static GList * static GList *
insert_drivers (GList *list) 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; gint i;
fpi_get_driver_types (drivers);
/* Find the best driver to handle this USB device. */ /* Find the best driver to handle this USB device. */
for (i = 0; i < drivers->len; i++) for (i = 0; i < drivers->len; i++)
{ {
GType driver = g_array_index (drivers, GType, 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; const FpIdEntry *entry;
if (cls->type != FP_DEVICE_TYPE_USB) if (cls->type != FP_DEVICE_TYPE_USB)
{ continue;
g_type_class_unref (cls);
continue;
}
for (entry = cls->id_table; entry->vid; entry++) 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)); list = g_list_prepend (list, g_strdup_printf ("%s | %s\n", key, cls->full_name));
} }
g_type_class_unref (cls);
} }
return list; return list;
+3 -12
View File
@@ -96,29 +96,20 @@ print_driver (const FpDeviceClass *cls)
int int
main (int argc, char **argv) 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; 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); printed = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
for (i = 0; i < drivers->len; i++) for (i = 0; i < drivers->len; i++)
{ {
GType driver = g_array_index (drivers, GType, 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) if (cls->type != FP_DEVICE_TYPE_USB)
{ continue;
g_type_class_unref (cls);
continue;
}
print_driver (cls); print_driver (cls);
g_type_class_unref (cls);
} }
print_driver (&whitelist); print_driver (&whitelist);
-3
View File
@@ -1,9 +1,6 @@
LIBFPRINT_2.0.0 { LIBFPRINT_2.0.0 {
global: global:
fp_*; fp_*;
/* Needs to be public for the listing commands. */
fpi_get_driver_types;
local: local:
*; *;
}; };
+132 -58
View File
@@ -4,29 +4,42 @@ libfprint_sources = [
'fp-image.c', 'fp-image.c',
'fp-print.c', 'fp-print.c',
'fp-image-device.c', 'fp-image-device.c',
]
libfprint_private_sources = [
'fpi-assembling.c', 'fpi-assembling.c',
'fpi-ssm.c',
'fpi-usb-transfer.c',
'fpi-byte-reader.c', 'fpi-byte-reader.c',
'fpi-byte-writer.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 = [ libfprint_public_headers = [
'fp-context.h', 'fp-context.h',
'fp-device.h', 'fp-device.h',
'fp-image-device.h',
'fp-image.h', 'fp-image.h',
'fp-print.h', 'fp-print.h',
] ]
libfprint_private_headers = [ libfprint_private_headers = [
'fpi-assembling.h', 'fpi-assembling.h',
'fpi-device.h',
'fpi-image.h',
'fpi-image-device.h',
'fpi-print.h',
'fpi-byte-reader.h', 'fpi-byte-reader.h',
'fpi-byte-writer.h',
'fpi-byte-utils.h', 'fpi-byte-utils.h',
'fpi-byte-writer.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 = [ nbis_sources = [
@@ -162,73 +175,135 @@ endif
other_sources = [] other_sources = []
fp_enums = gnome.mkenums_simple('fp-enums', fp_enums = gnome.mkenums_simple('fp-enums',
sources: libfprint_public_headers, sources: libfprint_public_headers,
install_header : true) install_header: true,
install_dir: get_option('includedir') / versioned_libname,
)
fp_enums_h = fp_enums[1] fp_enums_h = fp_enums[1]
fpi_enums = gnome.mkenums_simple('fpi-enums', fpi_enums = gnome.mkenums_simple('fpi-enums',
sources: libfprint_private_headers, sources: libfprint_private_headers,
install_header : true) install_header: false,
)
fpi_enums_h = fpi_enums[1] fpi_enums_h = fpi_enums[1]
enums_dep = declare_dependency(
sources: [ fp_enums_h, fpi_enums_h ]
)
drivers_sources += configure_file(input: 'empty_file', drivers_sources += configure_file(input: 'empty_file',
output: 'fp-drivers.c', output: 'fpi-drivers.c',
capture: true, capture: true,
command: [ command: [
'echo', 'echo',
drivers_type_list + '\n\n' + drivers_type_func '\n'.join(drivers_type_list + [] + drivers_type_func)
]) ])
mapfile = 'libfprint.ver' deps = [
vflag = '-Wl,--version-script,@0@/@1@'.format(meson.current_source_dir(), mapfile) enums_dep,
gio_dep,
glib_dep,
gusb_dep,
imaging_dep,
mathlib_dep,
nss_dep,
]
deps = [ mathlib_dep, glib_dep, gusb_dep, nss_dep, imaging_dep, gio_dep ] # These are empty and only exist so that the include directories are created
libfprint = library('fprint', # in the build tree. This silences a build time warning.
libfprint_sources + fp_enums + fpi_enums + subdir('nbis/include')
drivers_sources + nbis_sources + other_sources, subdir('nbis/libfprint-include')
soversion: soversion, deps += declare_dependency(include_directories: [
version: libversion, root_inc,
c_args: common_cflags + drivers_cflags, include_directories('nbis/include'),
include_directories: [ include_directories('nbis/libfprint-include'),
root_inc, ])
include_directories('nbis/include'),
], libnbis = static_library('nbis',
link_args : vflag, nbis_sources,
link_depends : mapfile, dependencies: deps,
dependencies: deps, c_args: cc.get_supported_arguments([
install: true) '-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_private, libfprint_drivers],
dependencies: deps,
install: true)
libfprint_dep = declare_dependency(link_with: libfprint, libfprint_dep = declare_dependency(link_with: libfprint,
sources: [ fp_enums_h ], include_directories: root_inc,
include_directories: root_inc, dependencies: [
dependencies: [glib_dep, gusb_dep, gio_dep]) enums_dep,
gio_dep,
glib_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', udev_rules = executable('fprint-list-udev-rules',
'fprint-list-udev-rules.c', 'fprint-list-udev-rules.c',
include_directories: [ dependencies: libfprint_private_dep,
root_inc, link_with: libfprint_drivers,
], install: false)
dependencies: [ deps, libfprint_dep ],
install: false)
if get_option('udev_rules') if get_option('udev_rules')
custom_target('udev-rules', custom_target('udev-rules',
output: '60-fprint-autosuspend.rules', output: '60-@0@-autosuspend.rules'.format(versioned_libname),
capture: true, capture: true,
command: [ udev_rules ], command: [ udev_rules ],
install: true, install: true,
install_dir: udev_rules_dir) install_dir: udev_rules_dir)
endif endif
supported_devices = executable('fprint-list-supported-devices', supported_devices = executable('fprint-list-supported-devices',
'fprint-list-supported-devices.c', 'fprint-list-supported-devices.c',
include_directories: [ dependencies: libfprint_private_dep,
root_inc, link_with: libfprint_drivers,
], install: false)
dependencies: [ deps, libfprint_dep ],
install: false)
if get_option('introspection') if get_option('introspection')
@@ -238,7 +313,7 @@ if get_option('introspection')
libfprint_public_headers, libfprint_public_headers,
libfprint_sources, libfprint_sources,
], ],
nsversion : '2.0', nsversion : '@0@.0'.format(soversion),
namespace : 'FPrint', namespace : 'FPrint',
symbol_prefix : 'fp_', symbol_prefix : 'fp_',
identifier_prefix : 'Fp', identifier_prefix : 'Fp',
@@ -256,8 +331,7 @@ if get_option('introspection')
'GObject-2.0', 'GObject-2.0',
'GUsb-1.0', 'GUsb-1.0',
], ],
install : true install : true)
)
libfprint_gir = libfprint_girtarget[0] libfprint_gir = libfprint_girtarget[0]
libfprint_typelib = libfprint_girtarget[1] libfprint_typelib = libfprint_girtarget[1]
endif endif
+17 -17
View File
@@ -896,7 +896,7 @@ for ( k = 0; k < np - 1; k++ ) {
for ( i = 0; i < tot; i++ ) { 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 ) { if ( colp_value < 0 ) {
kk += colp_value; kk += colp_value;
n++; n++;
@@ -933,7 +933,7 @@ for ( k = 0; k < np - 1; k++ ) {
kk = 0; kk = 0;
for ( i = 0; i < tot; i++ ) { 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 ); j = SQUARED( diff );
@@ -942,7 +942,7 @@ for ( k = 0; k < np - 1; k++ ) {
if ( j > TXS && j < CTXS ) if ( j > TXS && j < CTXS )
kk++; kk++;
else else
y[i-kk] = y[i]; bz_y[i-kk] = bz_y[i];
} /* END FOR i */ } /* END FOR i */
tot -= kk; /* Adjust the total edge pairs TOT based on # of edge pairs skipped */ 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-- ) { for ( i = tot-1 ; i >= 0; i-- ) {
int idx = y[i] - 1; int idx = bz_y[i] - 1;
if ( rk[idx] == 0 ) { if ( rk[idx] == 0 ) {
sc[idx] = -1; sc[idx] = -1;
} else { } else {
@@ -976,7 +976,7 @@ for ( k = 0; k < np - 1; k++ ) {
int pd = 0; int pd = 0;
for ( i = 0; i < tot; i++ ) { for ( i = 0; i < tot; i++ ) {
int idx = y[i] - 1; int idx = bz_y[i] - 1;
for ( ii = 1; ii < 4; ii++ ) { for ( ii = 1; ii < 4; ii++ ) {
@@ -1476,7 +1476,7 @@ return match_score;
/* extern int rk[ RK_SIZE ]; */ /* extern int rk[ RK_SIZE ]; */
/* extern int cp[ CP_SIZE ]; */ /* extern int cp[ CP_SIZE ]; */
/* extern int rp[ RP_SIZE ]; */ /* extern int rp[ RP_SIZE ]; */
/* extern int y[ Y_SIZE ]; */ /* extern int bz_y[ Y_SIZE ]; */
void bz_sift( void bz_sift(
int * ww, /* INPUT and OUTPUT; endpoint groups index; *ww may be bumped by one or by two */ 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 ) { if ( sc[kx-1] != ftt ) {
y[ (*tot)++ ] = kx; bz_y[ (*tot)++ ] = kx;
rk[kx-1] = sc[kx-1]; rk[kx-1] = sc[kx-1];
sc[kx-1] = ftt; sc[kx-1] = ftt;
} }
@@ -1553,7 +1553,7 @@ if ( n == l ) {
qq[*qh] = kz; qq[*qh] = kz;
zz[kz-1] = (*qh)++; zz[kz-1] = (*qh)++;
} }
y[(*tot)++] = kx; bz_y[(*tot)++] = kx;
rk[kx-1] = sc[kx-1]; rk[kx-1] = sc[kx-1];
sc[kx-1] = ftt; 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; t = 0;
y[0] = lim; bz_y[0] = lim;
cp[0] = 1; cp[0] = 1;
b = 0; b = 0;
n = 1; n = 1;
do { /* looping until T < 0 ... */ do { /* looping until T < 0 ... */
if ( y[t] - cp[t] > 1 ) { if (bz_y[t] - cp[t] > 1 ) {
k = sct[cp[t]][t]; k = sct[cp[t]][t];
j = ctt[k] + 1; j = ctt[k] + 1;
for ( i = 0; i < j; i++ ) { 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 { do {
while ( rp[jj] < sct[kk][t] && jj < j ) while ( rp[jj] < sct[kk][t] && jj < j )
jj++; jj++;
while ( rp[jj] > sct[kk][t] && kk < y[t] ) while ( rp[jj] > sct[kk][t] && kk < bz_y[t] )
kk++; 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]; sct[k][t+1] = sct[kk][t];
k++; k++;
kk++; kk++;
jj++; jj++;
} }
} while ( kk < y[t] && jj < j ); } while ( kk < bz_y[t] && jj < j );
t++; t++;
cp[t] = 1; cp[t] = 1;
y[t] = k; bz_y[t] = k;
b = t; b = t;
n = 1; n = 1;
} else { } else {
int tot = 0; int tot = 0;
lim = y[t]; lim = bz_y[t];
for ( i = n-1; i < lim; i++ ) { for ( i = n-1; i < lim; i++ ) {
tot += ct[ sct[i][t] ]; 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; int rk_index = b;
lim = y[t]; lim = bz_y[t];
for ( i = n-1; i < lim; ) { for ( i = n-1; i < lim; ) {
rk[ rk_index++ ] = sct[ i++ ][ t ]; 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--; t--;
if ( t >= 0 ) { if ( t >= 0 ) {
++cp[t]; ++cp[t];
n = y[t]; n = bz_y[t];
} }
} /* END IF */ } /* END IF */
+2 -2
View File
@@ -102,7 +102,7 @@ int yl[ YL_SIZE_1 ][ YL_SIZE_2 ];
int rf[RF_SIZE_1][RF_SIZE_2]; int rf[RF_SIZE_1][RF_SIZE_2];
int cf[CF_SIZE_1][CF_SIZE_2]; int cf[CF_SIZE_1][CF_SIZE_2];
int y[20000]; int bz_y[20000];
#else #else
int rq[ RQ_SIZE ] = {}; int rq[ RQ_SIZE ] = {};
int tq[ TQ_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 rf[RF_SIZE_1][RF_SIZE_2] = {};
int cf[CF_SIZE_1][CF_SIZE_2] = {}; int cf[CF_SIZE_1][CF_SIZE_2] = {};
int y[20000] = {}; int bz_y[20000] = {};
#endif #endif
+1 -1
View File
@@ -245,7 +245,7 @@ extern int cp[ CP_SIZE ];
extern int rp[ RP_SIZE ]; extern int rp[ RP_SIZE ];
extern int rf[RF_SIZE_1][RF_SIZE_2]; extern int rf[RF_SIZE_1][RF_SIZE_2];
extern int cf[CF_SIZE_1][CF_SIZE_2]; extern int cf[CF_SIZE_1][CF_SIZE_2];
extern int y[20000]; extern int bz_y[20000];
/**************************************************************************/ /**************************************************************************/
/**************************************************************************/ /**************************************************************************/
+2 -1
View File
@@ -66,7 +66,8 @@ of the software.
#include <math.h> #include <math.h>
#include <stdio.h> #include <stdio.h>
#include <fp_internal.h> #include <nbis-helpers.h>
#include <fpi-minutiae.h>
/*************************************************************************/ /*************************************************************************/
/* OUTPUT FILE EXTENSIONS */ /* OUTPUT FILE EXTENSIONS */
View File
+7 -6
View File
@@ -1,15 +1,16 @@
--- include/lfs.h 2018-08-24 15:31:54.535579623 +0200 --- include/lfs.h
+++ include/lfs.h.orig 2018-08-24 15:31:48.781587933 +0200 +++ include/lfs.h
@@ -66,7 +43,7 @@ of the software. @@ -66,7 +66,8 @@ of the software.
#include <math.h> #include <math.h>
#include <stdio.h> #include <stdio.h>
-#include <an2k.h> /* Needed by to_type9.c */ -#include <an2k.h> /* Needed by to_type9.c */
+#include <fp_internal.h> +#include <nbis-helpers.h>
+#include <fpi-minutiae.h>
/*************************************************************************/ /*************************************************************************/
/* OUTPUT FILE EXTENSIONS */ /* OUTPUT FILE EXTENSIONS */
@@ -154,26 +131,8 @@ typedef struct rotgrids{ @@ -154,26 +155,8 @@ typedef struct rotgrids{
#define DISAPPEARING 0 #define DISAPPEARING 0
#define APPEARING 1 #define APPEARING 1
@@ -38,7 +39,7 @@
typedef struct feature_pattern{ typedef struct feature_pattern{
int type; 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_double_dec_2(double *, int *, const int);
extern void bubble_sort_int_inc(int *, const int); extern void bubble_sort_int_inc(int *, const int);
+35
View File
@@ -0,0 +1,35 @@
/*
* Example fingerprint device prints listing and deletion
* Enrolls your right index finger and saves the print to disk
* 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
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wredundant-decls"
#include <bozorth.h>
#include <bz_array.h>
#include <defs.h>
#include <lfs.h>
#include <log.h>
#include <morph.h>
#include <mytime.h>
#include <sunrast.h>
#pragma GCC diagnostic pop
+2 -2
View File
@@ -66,7 +66,7 @@ of the software.
/***************************************************************************/ /***************************************************************************/
/***************************************************************************/ /***************************************************************************/
int open_logfile() int open_logfile(void)
{ {
#ifdef LOG_REPORT #ifdef LOG_REPORT
fprintf(stderr, "ERROR : open_logfile : fopen : %s\n", LOG_FILE); fprintf(stderr, "ERROR : open_logfile : fopen : %s\n", LOG_FILE);
@@ -91,7 +91,7 @@ void print2log(char *fmt, ...)
/***************************************************************************/ /***************************************************************************/
/***************************************************************************/ /***************************************************************************/
int close_logfile() int close_logfile(void)
{ {
#ifdef LOG_REPORT #ifdef LOG_REPORT
fprintf(stderr, "ERROR : close_logfile : fclose : %s\n", LOG_FILE); fprintf(stderr, "ERROR : close_logfile : fclose : %s\n", LOG_FILE);
+21
View File
@@ -0,0 +1,21 @@
@ global_y @
identifier y;
@@
int
- y
+ bz_y
[20000];
@@
identifier global_y.y;
@@
- y
+ bz_y
[...]
@@
@@
int
- y
+ bz_y
[20000] = {};
+8 -1
View File
@@ -179,9 +179,16 @@ sed -i 's/[ \t]*$//' `find -name "*.[ch]"`
# Remove usebsd.h # Remove usebsd.h
sed -i '/usebsd.h/d' `find -name "*.[ch]"` sed -i '/usebsd.h/d' `find -name "*.[ch]"`
# Replace functions with empty parameters using (void)
sed -i 's/^\([[:space:]]*[[:alnum:]_]\+[\*[:space:]]\+'\
'[[:alnum:]_]\+[[:space:]]*\)([[:space:]]*)/\1(void)/g' `find -name "*.[ch]"`
# Use GLib memory management # Use GLib memory management
spatch --sp-file glib-memory.cocci --dir . --in-place spatch --sp-file glib-memory.cocci --dir . --in-place
# Rename global "y" variable in "bz_y"
spatch --sp-file remove-global-y.cocci bozorth3/* include/bozorth.h --in-place
# The above leaves an unused variable around, triggering a warning # The above leaves an unused variable around, triggering a warning
# remove it. # remove it.
patch -p0 < glib-mem-warning.patch patch -p0 < glib-mem-warning.patch
+105 -39
View File
@@ -1,38 +1,71 @@
project('libfprint', [ 'c', 'cpp' ], project('libfprint', [ 'c', 'cpp' ],
version: '1.90.0', version: '1.90.1',
license: 'LGPLv2.1+', license: 'LGPLv2.1+',
default_options: [ default_options: [
'buildtype=debugoptimized', 'buildtype=debugoptimized',
'warning_level=1', 'warning_level=1',
'c_std=c99', 'c_std=gnu99',
], ],
meson_version: '>= 0.46.0') meson_version: '>= 0.49.0')
gnome = import('gnome') gnome = import('gnome')
add_project_arguments([ '-D_GNU_SOURCE' ], language: 'c')
add_project_arguments([ '-DG_LOG_DOMAIN="libfprint"' ], language: 'c')
libfprint_conf = configuration_data() libfprint_conf = configuration_data()
cc = meson.get_compiler('c') cc = meson.get_compiler('c')
cpp = meson.get_compiler('cpp') cpp = meson.get_compiler('cpp')
host_system = host_machine.system() host_system = host_machine.system()
glib_min_version = '2.56'
glib_version_def = 'GLIB_VERSION_@0@_@1@'.format(
glib_min_version.split('.')[0], glib_min_version.split('.')[1])
common_cflags = cc.get_supported_arguments([ common_cflags = cc.get_supported_arguments([
'-fgnu89-inline',
'-std=gnu99',
'-Wall', '-Wall',
'-Wcast-align',
'-Wformat-nonliteral',
'-Wformat-security',
'-Wformat=2',
'-Wignored-qualifiers',
'-Wlogical-op',
'-Wmissing-declarations',
'-Wmissing-format-attribute',
'-Wmissing-include-dirs',
'-Wmissing-noreturn',
'-Wpointer-arith',
'-Wshadow',
'-Wtype-limits', '-Wtype-limits',
'-Wundef', '-Wundef',
'-Wunused', '-Wunused',
'-Wstrict-prototypes', '-Werror=address',
'-Werror-implicit-function-declaration', '-Werror=array-bounds',
'-Wno-pointer-sign', '-Werror=empty-body',
'-Wshadow', '-Werror=init-self',
'-DGLIB_VERSION_MIN_REQUIRED=GLIB_VERSION_2_50', '-Werror=int-to-pointer-cast',
'-DGLIB_VERSION_MAX_ALLOWED=GLIB_VERSION_2_50', '-Werror=main',
'-Werror=missing-braces',
'-Werror=nonnull',
'-Werror=redundant-decls',
'-Werror=return-type',
'-Werror=sequence-point',
'-Werror=trigraphs',
'-Werror=write-strings',
'-fno-strict-aliasing',
'-DGLIB_VERSION_MIN_REQUIRED=' + glib_version_def,
'-DGLIB_VERSION_MAX_ALLOWED=' + glib_version_def,
'-D_GNU_SOURCE',
'-DG_LOG_DOMAIN="@0@"'.format(meson.project_name()),
]) ])
c_cflags = cc.get_supported_arguments([
'-Wimplicit-function-declaration',
'-Wmissing-prototypes',
'-Wnested-externs',
'-Wold-style-definition',
'-Wstrict-prototypes',
'-Werror=implicit',
'-Werror=pointer-to-int-cast',
])
add_project_arguments(common_cflags + c_cflags, language: 'c')
add_project_arguments(common_cflags, language: 'cpp')
# maintaining compatibility with the previous libtool versioning # maintaining compatibility with the previous libtool versioning
# current = binary - interface # current = binary - interface
@@ -41,17 +74,42 @@ soversion = 2
current = 0 current = 0
revision = 0 revision = 0
libversion = '@0@.@1@.@2@'.format(soversion, current, revision) libversion = '@0@.@1@.@2@'.format(soversion, current, revision)
versioned_libname = meson.project_name() + '-' + soversion.to_string()
# Dependencies # Dependencies
glib_dep = dependency('glib-2.0', version: '>= 2.50') glib_dep = dependency('glib-2.0', version: '>=' + glib_min_version)
gio_dep = dependency('gio-unix-2.0', version: '>= 2.44.0') gio_dep = dependency('gio-unix-2.0', version: '>=' + glib_min_version)
gusb_dep = dependency('gusb', version: '>= 0.3.0') gusb_dep = dependency('gusb', version: '>= 0.2.0')
mathlib_dep = cc.find_library('m', required: false) mathlib_dep = cc.find_library('m', required: false)
# The following dependencies are only used for tests
cairo_dep = dependency('cairo', required: false)
# Drivers # Drivers
drivers = get_option('drivers').split(',') drivers = get_option('drivers').split(',')
virtual_drivers = [ 'virtual_image' ] virtual_drivers = [ 'virtual_image' ]
default_drivers = [ 'upektc_img', 'vfs5011', 'aes3500', 'aes4000', 'aes1610', 'aes1660', 'aes2660', 'aes2501', 'aes2550', 'vfs101', 'vfs301', 'vfs0050', 'etes603', 'vcom5s', 'synaptics', 'elan', 'uru4000', 'upektc', 'upeksonly', 'upekts' ] default_drivers = [
'upektc_img',
'vfs5011',
'aes3500',
'aes4000',
'aes1610',
'aes1660',
'aes2660',
'aes2501',
'aes2550',
'vfs101',
'vfs301',
'vfs0050',
'etes603',
'vcom5s',
'synaptics',
'elan',
'uru4000',
'upektc',
'upeksonly',
'upekts',
]
all_drivers = default_drivers + virtual_drivers all_drivers = default_drivers + virtual_drivers
@@ -91,14 +149,26 @@ foreach driver: drivers
endforeach endforeach
# Export the drivers' types to the core code # Export the drivers' types to the core code
drivers_type_list = '#include <glib-object.h>\n' drivers_type_list = []
drivers_type_func = 'void fpi_get_driver_types(GArray *drivers)\n{\n\tGType t;\n' drivers_type_func = []
drivers_type_list += '#include <glib-object.h>'
drivers_type_list += '#include "fpi-context.h"'
drivers_type_list += ''
drivers_type_func += 'GArray *'
drivers_type_func += 'fpi_get_driver_types (void)'
drivers_type_func += '{'
drivers_type_func += ' GArray *drivers = g_array_new (TRUE, FALSE, sizeof (GType));'
drivers_type_func += ' GType t;'
drivers_type_func += ''
foreach driver: drivers foreach driver: drivers
drivers_type_list += 'extern GType (fpi_device_' + driver + '_get_type) (void);\n' drivers_type_list += 'extern GType (fpi_device_' + driver + '_get_type) (void);'
drivers_type_func += ' t = fpi_device_' + driver + '_get_type(); g_array_append_val (drivers, t);\n' drivers_type_func += ' t = fpi_device_' + driver + '_get_type ();'
drivers_type_func += ' g_array_append_val (drivers, t);'
drivers_type_func += ''
endforeach endforeach
drivers_type_list += '' drivers_type_list += ''
drivers_type_func += '};' drivers_type_func += ' return drivers;'
drivers_type_func += '}'
root_inc = include_directories('.') root_inc = include_directories('.')
@@ -132,18 +202,14 @@ if get_option('gtk-examples')
subdir('demo') subdir('demo')
endif endif
# The tests require introspeciton support to run subdir('tests')
if get_option('introspection')
subdir('tests')
endif
pkgconfig = import('pkgconfig') pkgconfig = import('pkgconfig')
pkgconfig.generate( pkgconfig.generate(
name: 'libfprint', name: versioned_libname,
description: 'Generic C API for fingerprint reader access', description: 'Generic C API for fingerprint reader access',
version: meson.project_version(), version: meson.project_version(),
libraries: libfprint, libraries: libfprint,
subdirs: 'libfprint', subdirs: versioned_libname,
filebase: 'libfprint2', filebase: versioned_libname,
install_dir: join_paths(get_option('libdir'), 'pkgconfig'),
) )
+30 -1
View File
@@ -21,4 +21,33 @@ To create a new umockdev test, you should:
Please note, there is no need to use a real finger print in this case. If Please note, there is no need to use a real finger print in this case. If
you would like to avoid submitting your own fingerprint then please just you would like to avoid submitting your own fingerprint then please just
use e.g. the side of your finger, arm, or anything else that will produce use e.g. the side of your finger, arm, or anything else that will produce
an image with the device. an image with the device.
Note that umockdev-record groups URBs aggressively. In most cases, manual
intervention is unfortunately required. In most cases, drivers do a chain
of commands like e.g. A then B each with a different reply. Umockdev will
create a file like:
A
reply 1
reply 2
B
reply 1
reply 2
which then needs to be re-ordered to be:
A
reply 1
B
reply 1
A
reply 2
B
reply 2
Other changes may be needed to get everything working. For example the elan
driver relies on a timeout that is not reported correctly. In this case the
driver works around it by interpreting the protocol error differently in
the virtual environment.

Some files were not shown because too many files have changed in this diff Show More