mirror of
https://gitlab.freedesktop.org/libfprint/libfprint.git
synced 2025-11-15 07:38:12 +00:00
Compare commits
82 Commits
benzea/fix
...
benzea/mis
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
788fd9ca7a | ||
|
|
8c5eede914 | ||
|
|
07c8481bf6 | ||
|
|
d435fc7c2c | ||
|
|
dc3b5e52ac | ||
|
|
7e2db8e988 | ||
|
|
24d388f923 | ||
|
|
af42b3e468 | ||
|
|
edb09463f4 | ||
|
|
42b1deaeea | ||
|
|
fe828d0bb2 | ||
|
|
cf5473a55c | ||
|
|
0471edbf10 | ||
|
|
299a797423 | ||
|
|
c594863639 | ||
|
|
3bb1840750 | ||
|
|
f31b8483d4 | ||
|
|
324258bc8c | ||
|
|
f578ebe82d | ||
|
|
98fa6efce3 | ||
|
|
c7b7f78273 | ||
|
|
b4c3756ab0 | ||
|
|
da46f53e82 | ||
|
|
eeddd8c7bc | ||
|
|
43a8c909bf | ||
|
|
09576e5209 | ||
|
|
8184e33dd6 | ||
|
|
6f2b1f97da | ||
|
|
c3bf6fe863 | ||
|
|
5bed81025e | ||
|
|
d7100e41df | ||
|
|
ae7021e529 | ||
|
|
d9de941a47 | ||
|
|
7114d97f25 | ||
|
|
92a5278a74 | ||
|
|
d01bb41b7c | ||
|
|
ad88a5a78f | ||
|
|
ff0107fc0a | ||
|
|
107fdfde32 | ||
|
|
bb0ef04b85 | ||
|
|
0a475196e0 | ||
|
|
1dee7985b9 | ||
|
|
a1a3933191 | ||
|
|
9c8360ad67 | ||
|
|
0c7d2d8ecd | ||
|
|
6209b22e3b | ||
|
|
f404a69b73 | ||
|
|
50a837573d | ||
|
|
3e958ab7b4 | ||
|
|
a8a2a757ed | ||
|
|
702255b182 | ||
|
|
a64ac2296b | ||
|
|
a522e3fd6f | ||
|
|
65828e0e56 | ||
|
|
fe967d0ac2 | ||
|
|
10c5bdade7 | ||
|
|
8f21aa1b26 | ||
|
|
7b68344394 | ||
|
|
dccb5b3ab2 | ||
|
|
2fcc2deb43 | ||
|
|
c678b9021c | ||
|
|
b2e55308d6 | ||
|
|
a176fa1d34 | ||
|
|
cacce50ef9 | ||
|
|
5ab4d6c454 | ||
|
|
0c655be159 | ||
|
|
2b8c524928 | ||
|
|
2f2ea65d32 | ||
|
|
1d48b70f38 | ||
|
|
35e9f19c0c | ||
|
|
70a0d6f0fe | ||
|
|
7ed9b0c2f9 | ||
|
|
6a090656b6 | ||
|
|
e1d181887f | ||
|
|
e143f12e57 | ||
|
|
e64c18f8de | ||
|
|
7e70344b4a | ||
|
|
44af2173a8 | ||
|
|
e7c7f368c9 | ||
|
|
a29586f398 | ||
|
|
98cd1c2680 | ||
|
|
ae285e790d |
105
.gitlab-ci.yml
105
.gitlab-ci.yml
@@ -1,40 +1,46 @@
|
|||||||
image: fedora:rawhide
|
variables:
|
||||||
|
FEDORA_TAG: rawhide
|
||||||
|
FEDORA_VERSION: rawhide
|
||||||
|
FEDORA_IMAGE: "$CI_REGISTRY/libfprint/$CI_PROJECT_NAME/fedora/$FEDORA_VERSION:$FEDORA_TAG"
|
||||||
|
BUNDLE: "org.freedesktop.libfprint.Demo.flatpak"
|
||||||
|
LAST_ABI_BREAK: "056ea541ddc97f5806cffbd99a12dc87e4da3546"
|
||||||
|
|
||||||
|
include:
|
||||||
|
- project: 'wayland/ci-templates'
|
||||||
|
ref: master
|
||||||
|
file: '/templates/fedora.yml'
|
||||||
|
|
||||||
stages:
|
stages:
|
||||||
- check-source
|
- check-source
|
||||||
- build
|
- build
|
||||||
- test
|
- test
|
||||||
- flatpack
|
- flatpack
|
||||||
|
|
||||||
variables:
|
image: "$FEDORA_IMAGE"
|
||||||
DEPENDENCIES: libgusb-devel glib2-devel nss-devel pixman-devel systemd meson gtk-doc
|
|
||||||
gcc gcc-c++ glibc-devel libX11-devel libXv-devel gtk3-devel flatpak-builder
|
|
||||||
gobject-introspection-devel python3-cairo python3-gobject umockdev
|
|
||||||
BUNDLE: "org.freedesktop.libfprint.Demo.flatpak"
|
|
||||||
LAST_ABI_BREAK: "056ea541ddc97f5806cffbd99a12dc87e4da3546"
|
|
||||||
|
|
||||||
.build_one_driver_template: &build_one_driver
|
.build_one_driver_template: &build_one_driver
|
||||||
script:
|
script:
|
||||||
- dnf update -y --nogpgcheck && dnf install -y --nogpgcheck $DEPENDENCIES
|
|
||||||
# Build with a driver that doesn't need imaging, or nss
|
# Build with a driver that doesn't need imaging, or nss
|
||||||
- meson -Ddrivers=$driver . _build
|
- meson --werror -Ddrivers=$driver . _build
|
||||||
- ninja -C _build
|
- ninja -C _build
|
||||||
- rm -rf _build/
|
- rm -rf _build/
|
||||||
|
|
||||||
.build_template: &build
|
.build_template: &build
|
||||||
script:
|
script:
|
||||||
- dnf update -y --nogpgcheck && dnf install -y --nogpgcheck $DEPENDENCIES
|
|
||||||
# And build with everything
|
# And build with everything
|
||||||
- meson -Ddrivers=all . _build
|
- meson --werror -Ddrivers=all . _build
|
||||||
- ninja -C _build
|
- ninja -C _build
|
||||||
- ninja -C _build install
|
- ninja -C _build install
|
||||||
|
|
||||||
.build_template: &check_abi
|
.build_template: &check_abi
|
||||||
script:
|
script:
|
||||||
- dnf update -y --nogpgcheck && dnf install -y --nogpgcheck $DEPENDENCIES doxygen libabigail git
|
|
||||||
- ./.ci/check-abi ${LAST_ABI_BREAK} $(git rev-parse HEAD)
|
- ./.ci/check-abi ${LAST_ABI_BREAK} $(git rev-parse HEAD)
|
||||||
|
|
||||||
build:
|
build:
|
||||||
stage: build
|
stage: build
|
||||||
|
except:
|
||||||
|
variables:
|
||||||
|
- $CI_PIPELINE_SOURCE == "schedule"
|
||||||
variables:
|
variables:
|
||||||
driver: virtual_image
|
driver: virtual_image
|
||||||
<<: *build_one_driver
|
<<: *build_one_driver
|
||||||
@@ -43,24 +49,35 @@ build:
|
|||||||
|
|
||||||
test:
|
test:
|
||||||
stage: test
|
stage: test
|
||||||
|
except:
|
||||||
|
variables:
|
||||||
|
- $CI_PIPELINE_SOURCE == "schedule"
|
||||||
script:
|
script:
|
||||||
- dnf update -y --nogpgcheck && dnf install -y --nogpgcheck $DEPENDENCIES
|
- meson --werror -Ddrivers=all -Db_coverage=true . _build
|
||||||
- meson -Ddrivers=all . _build
|
|
||||||
- ninja -C _build
|
- ninja -C _build
|
||||||
- meson test -C _build --verbose --no-stdsplit
|
- meson test -C _build --verbose --no-stdsplit --timeout-multiplier 3
|
||||||
|
- ninja -C _build coverage
|
||||||
|
artifacts:
|
||||||
|
paths:
|
||||||
|
- _build/meson-logs
|
||||||
|
expire_in: 1 week
|
||||||
|
|
||||||
test_valgrind:
|
test_valgrind:
|
||||||
stage: test
|
stage: test
|
||||||
|
except:
|
||||||
|
variables:
|
||||||
|
- $CI_PIPELINE_SOURCE == "schedule"
|
||||||
script:
|
script:
|
||||||
- dnf update -y --nogpgcheck && dnf install -y --nogpgcheck $DEPENDENCIES valgrind
|
|
||||||
- meson -Ddrivers=all . _build
|
- meson -Ddrivers=all . _build
|
||||||
- ninja -C _build
|
- ninja -C _build
|
||||||
- meson test -C _build --verbose --no-stdsplit --setup=valgrind
|
- meson test -C _build --verbose --no-stdsplit --setup=valgrind
|
||||||
|
|
||||||
test_indent:
|
test_indent:
|
||||||
stage: check-source
|
stage: check-source
|
||||||
|
except:
|
||||||
|
variables:
|
||||||
|
- $CI_PIPELINE_SOURCE == "schedule"
|
||||||
script:
|
script:
|
||||||
- dnf update -y --nogpgcheck && dnf install -y --nogpgcheck git uncrustify
|
|
||||||
- scripts/uncrustify.sh --check
|
- scripts/uncrustify.sh --check
|
||||||
|
|
||||||
.flatpak_script_template: &flatpak_script
|
.flatpak_script_template: &flatpak_script
|
||||||
@@ -86,9 +103,12 @@ test_indent:
|
|||||||
<<: *flatpak_script
|
<<: *flatpak_script
|
||||||
<<: *flatpak_artifacts
|
<<: *flatpak_artifacts
|
||||||
|
|
||||||
flatpak master:
|
.flatpak_master_template: &flatpak_master
|
||||||
image: registry.gitlab.gnome.org/gnome/gnome-runtime-images/gnome:3.32
|
image: registry.gitlab.gnome.org/gnome/gnome-runtime-images/gnome:3.32
|
||||||
stage: flatpack
|
stage: flatpack
|
||||||
|
except:
|
||||||
|
variables:
|
||||||
|
- $CI_PIPELINE_SOURCE == "schedule"
|
||||||
variables:
|
variables:
|
||||||
MANIFEST_PATH: "demo/org.freedesktop.libfprint.Demo.json"
|
MANIFEST_PATH: "demo/org.freedesktop.libfprint.Demo.json"
|
||||||
# From demo/org.freedesktop.libfprint.Demo.json
|
# From demo/org.freedesktop.libfprint.Demo.json
|
||||||
@@ -96,3 +116,52 @@ flatpak master:
|
|||||||
FLATPAK_MODULE: "libfprint"
|
FLATPAK_MODULE: "libfprint"
|
||||||
DBUS_ID: "org.freedesktop.libfprint.Demo"
|
DBUS_ID: "org.freedesktop.libfprint.Demo"
|
||||||
<<: *flatpak
|
<<: *flatpak
|
||||||
|
|
||||||
|
flatpak-auto master:
|
||||||
|
<<: *flatpak_master
|
||||||
|
when: always
|
||||||
|
only:
|
||||||
|
- tags
|
||||||
|
- master
|
||||||
|
|
||||||
|
flatpak-manual master:
|
||||||
|
<<: *flatpak_master
|
||||||
|
when: manual
|
||||||
|
except:
|
||||||
|
- tags
|
||||||
|
- master
|
||||||
|
|
||||||
|
# CONTAINERS creation stage
|
||||||
|
container_fedora_build:
|
||||||
|
extends: .fedora@container-build
|
||||||
|
only:
|
||||||
|
variables:
|
||||||
|
- $CI_PIPELINE_SOURCE == "schedule" && $CRON_TASK == "BUILD_CI_IMAGES"
|
||||||
|
variables:
|
||||||
|
GIT_STRATEGY: none # no need to pull the whole tree for rebuilding the image
|
||||||
|
# a list of packages to install
|
||||||
|
FEDORA_RPMS:
|
||||||
|
doxygen
|
||||||
|
flatpak-builder
|
||||||
|
gcc
|
||||||
|
gcc-c++
|
||||||
|
gcovr
|
||||||
|
git
|
||||||
|
glib2-devel
|
||||||
|
glibc-devel
|
||||||
|
gobject-introspection-devel
|
||||||
|
gtk-doc
|
||||||
|
gtk3-devel
|
||||||
|
libabigail
|
||||||
|
libgusb-devel
|
||||||
|
libX11-devel
|
||||||
|
libXv-devel
|
||||||
|
meson
|
||||||
|
nss-devel
|
||||||
|
pixman-devel
|
||||||
|
python3-cairo
|
||||||
|
python3-gobject
|
||||||
|
systemd
|
||||||
|
umockdev
|
||||||
|
uncrustify
|
||||||
|
valgrind
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -9,14 +9,11 @@ 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,
|
|
||||||
'-DPACKAGE_VERSION="' + meson.project_version() + '"'
|
|
||||||
],
|
],
|
||||||
|
c_args: '-DPACKAGE_VERSION="' + meson.project_version() + '"',
|
||||||
install: true,
|
install: true,
|
||||||
install_dir: bindir)
|
install_dir: bindir)
|
||||||
|
|
||||||
|
|||||||
@@ -211,6 +211,7 @@ 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
|
||||||
|
|||||||
@@ -32,7 +32,6 @@ gnome.gtkdoc('libfprint',
|
|||||||
expand_content_files: expand_content_files,
|
expand_content_files: expand_content_files,
|
||||||
scan_args: [
|
scan_args: [
|
||||||
#'--rebuild-sections',
|
#'--rebuild-sections',
|
||||||
'--ignore-decorators=API_EXPORTED',
|
|
||||||
'--ignore-headers=' + ' '.join(private_headers),
|
'--ignore-headers=' + ' '.join(private_headers),
|
||||||
],
|
],
|
||||||
fixxref_args: [
|
fixxref_args: [
|
||||||
|
|||||||
@@ -197,9 +197,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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,17 +3,14 @@ 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)
|
|
||||||
|
|||||||
@@ -20,6 +20,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <libfprint/fprint.h>
|
#include <libfprint/fprint.h>
|
||||||
|
#include "storage.h"
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@@ -57,7 +58,7 @@ load_data (void)
|
|||||||
GVariantDict *res;
|
GVariantDict *res;
|
||||||
GVariant *var;
|
GVariant *var;
|
||||||
g_autofree gchar *contents = NULL;
|
g_autofree 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))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -686,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)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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)
|
||||||
@@ -91,7 +91,7 @@ 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);
|
||||||
@@ -321,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);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -776,7 +778,6 @@ calibrate_complete (FpiSsm *ssm, FpDevice *dev, GError *error)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
self->dev_state = FP_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON;
|
|
||||||
elan_capture (dev);
|
elan_capture (dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -966,6 +967,7 @@ elan_change_state (FpImageDevice *idev)
|
|||||||
{
|
{
|
||||||
case FP_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 = FP_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON;
|
||||||
elan_calibrate (dev);
|
elan_calibrate (dev);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -168,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);
|
||||||
@@ -407,7 +407,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;
|
||||||
|
|
||||||
@@ -506,7 +506,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,
|
||||||
@@ -969,10 +969,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;
|
goto err_close;
|
||||||
|
|
||||||
if (!g_usb_device_claim_interface (fpi_device_get_usb_device (device), 0, 0, &error))
|
if (!g_usb_device_claim_interface (usb_dev, 0, 0, &error))
|
||||||
goto err_close;
|
goto err_close;
|
||||||
|
|
||||||
/* TODO: Do not do this synchronous. */
|
/* TODO: Do not do this synchronous. */
|
||||||
|
|||||||
@@ -375,7 +375,7 @@ read_msg_cb (FpiUsbTransfer *transfer, FpDevice *device,
|
|||||||
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,
|
||||||
|
|||||||
@@ -175,7 +175,7 @@ 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);
|
||||||
@@ -202,7 +202,7 @@ 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);
|
||||||
@@ -332,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);
|
||||||
|
|
||||||
@@ -344,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
|
||||||
|
|||||||
@@ -399,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. */
|
||||||
@@ -595,7 +595,8 @@ 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,
|
||||||
|
|||||||
@@ -190,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);
|
||||||
@@ -210,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];
|
||||||
@@ -232,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];
|
||||||
}
|
}
|
||||||
@@ -684,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:
|
||||||
@@ -716,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;
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -769,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;
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|||||||
@@ -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];
|
||||||
};
|
};
|
||||||
@@ -75,9 +76,9 @@ recv_image_img_recv_cb (GObject *source_object,
|
|||||||
{
|
{
|
||||||
if (!success)
|
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);
|
||||||
@@ -89,8 +90,10 @@ recv_image_img_recv_cb (GObject *source_object,
|
|||||||
self = FPI_DEVICE_VIRTUAL_IMAGE (user_data);
|
self = FPI_DEVICE_VIRTUAL_IMAGE (user_data);
|
||||||
device = FP_IMAGE_DEVICE (self);
|
device = FP_IMAGE_DEVICE (self);
|
||||||
|
|
||||||
|
if (self->automatic_finger)
|
||||||
fpi_image_device_report_finger_status (device, TRUE);
|
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));
|
||||||
|
if (self->automatic_finger)
|
||||||
fpi_image_device_report_finger_status (device, FALSE);
|
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. */
|
||||||
@@ -113,9 +116,10 @@ recv_image_hdr_recv_cb (GObject *source_object,
|
|||||||
{
|
{
|
||||||
if (!success)
|
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);
|
||||||
@@ -147,6 +151,17 @@ 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);
|
||||||
@@ -213,6 +228,7 @@ new_connection_cb (GObject *source_object, GAsyncResult *res, gpointer user_data
|
|||||||
}
|
}
|
||||||
|
|
||||||
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);
|
||||||
|
|||||||
@@ -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,12 @@ 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(GTypeClass) type_class = g_type_class_ref (driver);
|
||||||
|
FpDeviceClass *cls = FP_DEVICE_CLASS (type_class);
|
||||||
const FpIdEntry *entry;
|
const FpIdEntry *entry;
|
||||||
|
|
||||||
if (cls->type != FP_DEVICE_TYPE_USB)
|
if (cls->type != FP_DEVICE_TYPE_USB)
|
||||||
{
|
|
||||||
g_type_class_unref (cls);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
|
|
||||||
for (entry = cls->id_table; entry->pid; entry++)
|
for (entry = cls->id_table; entry->pid; entry++)
|
||||||
{
|
{
|
||||||
@@ -129,8 +156,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)
|
||||||
@@ -242,9 +267,24 @@ 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(GTypeClass) type_class = g_type_class_ref (driver);
|
||||||
|
FpDeviceClass *cls = FP_DEVICE_CLASS (type_class);
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
@@ -311,7 +351,8 @@ 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(GTypeClass) type_class = g_type_class_ref (driver);
|
||||||
|
FpDeviceClass *cls = FP_DEVICE_CLASS (type_class);
|
||||||
const FpIdEntry *entry;
|
const FpIdEntry *entry;
|
||||||
|
|
||||||
if (cls->type != FP_DEVICE_TYPE_VIRTUAL)
|
if (cls->type != FP_DEVICE_TYPE_VIRTUAL)
|
||||||
@@ -337,8 +378,6 @@ fp_context_enumerate (FpContext *context)
|
|||||||
NULL);
|
NULL);
|
||||||
g_debug ("created");
|
g_debug ("created");
|
||||||
}
|
}
|
||||||
|
|
||||||
g_type_class_unref (cls);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
while (priv->pending_devices)
|
while (priv->pending_devices)
|
||||||
|
|||||||
65
libfprint/fp-device-private.h
Normal file
65
libfprint/fp-device-private.h
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
/*
|
||||||
|
* 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. */
|
||||||
|
FpDeviceAction 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);
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -129,6 +129,7 @@ typedef void (*FpEnrollProgress) (FpDevice *device,
|
|||||||
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);
|
||||||
|
|
||||||
|
|||||||
43
libfprint/fp-image-device-private.h
Normal file
43
libfprint/fp-image-device-private.h
Normal 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
|
||||||
|
{
|
||||||
|
FpImageDeviceState 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);
|
||||||
@@ -20,14 +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-enums.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
|
||||||
@@ -37,28 +32,6 @@
|
|||||||
* 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 {
|
enum {
|
||||||
@@ -85,67 +58,6 @@ static guint signals[LAST_SIGNAL] = { 0 };
|
|||||||
|
|
||||||
/* 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);
|
|
||||||
|
|
||||||
/* 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. */
|
|
||||||
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_by_pspec (G_OBJECT (self), properties[PROP_FPI_STATE]);
|
|
||||||
g_signal_emit (self, signals[FPI_STATE_CHANGED], 0, priv->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;
|
|
||||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_FPI_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);
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_FPI_STATE]);
|
|
||||||
|
|
||||||
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)
|
||||||
{
|
{
|
||||||
@@ -195,13 +107,14 @@ 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 != FP_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);
|
||||||
|
FpImageDevicePrivate *priv = fp_image_device_get_instance_private (self);
|
||||||
FpDeviceAction action;
|
FpDeviceAction action;
|
||||||
|
|
||||||
action = fpi_device_get_current_action (device);
|
action = fpi_device_get_current_action (device);
|
||||||
@@ -213,7 +126,9 @@ fp_image_device_cancel_action (FpDevice *device)
|
|||||||
action == FP_DEVICE_ACTION_IDENTIFY ||
|
action == FP_DEVICE_ACTION_IDENTIFY ||
|
||||||
action == FP_DEVICE_ACTION_CAPTURE)
|
action == FP_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),
|
||||||
@@ -256,6 +171,7 @@ fp_image_device_start_capture_action (FpDevice *device)
|
|||||||
}
|
}
|
||||||
|
|
||||||
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
|
||||||
@@ -279,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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -382,465 +298,4 @@ fp_image_device_init (FpImageDevice *self)
|
|||||||
priv->bz3_threshold = BOZORTH3_DEFAULT_THRESHOLD;
|
priv->bz3_threshold = BOZORTH3_DEFAULT_THRESHOLD;
|
||||||
if (cls->bz3_threshold > 0)
|
if (cls->bz3_threshold > 0)
|
||||||
priv->bz3_threshold = cls->bz3_threshold;
|
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);
|
|
||||||
g_autoptr(FpPrint) print = NULL;
|
|
||||||
GError *error = 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,
|
|
||||||
g_steal_pointer (&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, g_steal_pointer (&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, g_steal_pointer (&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;
|
|
||||||
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
g_clear_handle_id (&priv->pending_activation_timeout_id, g_source_remove);
|
|
||||||
priv->pending_activation_timeout_id =
|
|
||||||
g_idle_add ((GSourceFunc) 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;
|
|
||||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_FPI_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);
|
|
||||||
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;
|
|
||||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_FPI_STATE]);
|
|
||||||
|
|
||||||
fpi_device_close_complete (FP_DEVICE (self), error);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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,
|
FpPrintType 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
|
|
||||||
@@ -18,12 +18,10 @@
|
|||||||
* 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-log.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SECTION: fp-print
|
* SECTION: fp-print
|
||||||
@@ -42,28 +40,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 {
|
||||||
@@ -207,7 +183,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;
|
||||||
|
|
||||||
@@ -540,223 +516,6 @@ fp_print_set_enroll_date (FpPrint *print,
|
|||||||
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)
|
|
||||||
{
|
|
||||||
g_assert_null (print->prints);
|
|
||||||
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
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Internal/private definitions for libfprint
|
* Internal/private definitions for libfprint
|
||||||
* Copyright (C) 2007-2008 Daniel Drake <dsd@gentoo.org>
|
* 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
|
||||||
@@ -17,38 +17,9 @@
|
|||||||
* 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 "fpi-log.h"
|
||||||
#include "nbis-helpers.h"
|
|
||||||
#include "fpi-image.h"
|
#include "fpi-image.h"
|
||||||
#include "fpi-image-device.h"
|
#include "fpi-image-device.h"
|
||||||
|
#include "fpi-minutiae.h"
|
||||||
/* fp_minutia structure definition */
|
|
||||||
struct fp_minutia
|
|
||||||
{
|
|
||||||
int x;
|
|
||||||
int y;
|
|
||||||
int ex;
|
|
||||||
int ey;
|
|
||||||
int direction;
|
|
||||||
double reliability;
|
|
||||||
int type;
|
|
||||||
int appearing;
|
|
||||||
int feature_id;
|
|
||||||
int *nbrs;
|
|
||||||
int *ridge_counts;
|
|
||||||
int num_nbrs;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* fp_minutiae structure definition */
|
|
||||||
struct fp_minutiae
|
|
||||||
{
|
|
||||||
int alloc;
|
|
||||||
int num;
|
|
||||||
struct fp_minutia **list;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|||||||
@@ -23,11 +23,12 @@
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 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);
|
||||||
|
|||||||
1177
libfprint/fpi-device.c
Normal file
1177
libfprint/fpi-device.c
Normal file
File diff suppressed because it is too large
Load Diff
595
libfprint/fpi-image-device.c
Normal file
595
libfprint/fpi-image-device.c
Normal file
@@ -0,0 +1,595 @@
|
|||||||
|
/*
|
||||||
|
* 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 = FP_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON;
|
||||||
|
g_object_notify (G_OBJECT (self), "fp-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 == FP_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON)
|
||||||
|
g_warning ("Deactivating image device while waiting for finger, this should not happen.");
|
||||||
|
|
||||||
|
priv->state = FP_IMAGE_DEVICE_STATE_INACTIVE;
|
||||||
|
g_object_notify (G_OBJECT (self), "fp-image-device-state");
|
||||||
|
|
||||||
|
fp_dbg ("Deactivating image device\n");
|
||||||
|
cls->deactivate (self);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Static helper functions */
|
||||||
|
|
||||||
|
static void
|
||||||
|
fp_image_device_change_state (FpImageDevice *self, FpImageDeviceState state)
|
||||||
|
{
|
||||||
|
FpImageDevicePrivate *priv = fp_image_device_get_instance_private (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. */
|
||||||
|
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), "fp-image-device-state");
|
||||||
|
g_signal_emit_by_name (self, "fp-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, FP_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;
|
||||||
|
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));
|
||||||
|
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 == FP_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, 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,
|
||||||
|
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 == 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, g_steal_pointer (&print), error);
|
||||||
|
fpi_image_device_deactivate (self);
|
||||||
|
}
|
||||||
|
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, g_steal_pointer (&print), 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);
|
||||||
|
FpDeviceAction action;
|
||||||
|
|
||||||
|
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.
|
||||||
|
*
|
||||||
|
* 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 != FP_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);
|
||||||
|
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)");
|
||||||
|
fpi_image_device_deactivate (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!");
|
||||||
|
|
||||||
|
fpi_image_device_deactivate (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)
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
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;
|
||||||
|
g_object_notify (G_OBJECT (self), "fp-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);
|
||||||
|
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;
|
||||||
|
g_object_notify (G_OBJECT (self), "fp-image-device-state");
|
||||||
|
|
||||||
|
fpi_device_close_complete (FP_DEVICE (self), error);
|
||||||
|
}
|
||||||
150
libfprint/fpi-image.c
Normal file
150
libfprint/fpi-image.c
Normal 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
|
||||||
45
libfprint/fpi-minutiae.h
Normal file
45
libfprint/fpi-minutiae.h
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
/*
|
||||||
|
* Internal/private definitions for libfprint
|
||||||
|
* Copyright (C) 2007-2008 Daniel Drake <dsd@gentoo.org>
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
|
||||||
|
/* fp_minutia structure definition */
|
||||||
|
struct fp_minutia
|
||||||
|
{
|
||||||
|
int x;
|
||||||
|
int y;
|
||||||
|
int ex;
|
||||||
|
int ey;
|
||||||
|
int direction;
|
||||||
|
double reliability;
|
||||||
|
int type;
|
||||||
|
int appearing;
|
||||||
|
int feature_id;
|
||||||
|
int *nbrs;
|
||||||
|
int *ridge_counts;
|
||||||
|
int num_nbrs;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* fp_minutiae structure definition */
|
||||||
|
struct fp_minutiae
|
||||||
|
{
|
||||||
|
int alloc;
|
||||||
|
int num;
|
||||||
|
struct fp_minutia **list;
|
||||||
|
};
|
||||||
249
libfprint/fpi-print.c
Normal file
249
libfprint/fpi-print.c
Normal 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 #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)
|
||||||
|
{
|
||||||
|
g_assert_null (print->prints);
|
||||||
|
print->prints = g_ptr_array_new_with_free_func (g_free);
|
||||||
|
}
|
||||||
|
g_object_notify (G_OBJECT (print), "fp-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 #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 (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 #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;
|
||||||
|
}
|
||||||
@@ -21,13 +21,13 @@ typedef enum {
|
|||||||
/**
|
/**
|
||||||
* 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,
|
||||||
|
|||||||
@@ -81,6 +81,7 @@
|
|||||||
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;
|
||||||
@@ -103,13 +104,29 @@ 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;
|
||||||
|
|
||||||
@@ -120,6 +137,7 @@ fpi_ssm_new (FpDevice *dev,
|
|||||||
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;
|
||||||
}
|
}
|
||||||
@@ -195,6 +213,9 @@ on_delayed_action_cancelled (GCancellable *cancellable,
|
|||||||
{
|
{
|
||||||
CancelledActionIdleData *data;
|
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);
|
g_clear_pointer (&machine->timeout, g_source_destroy);
|
||||||
|
|
||||||
data = g_new0 (CancelledActionIdleData, 1);
|
data = g_new0 (CancelledActionIdleData, 1);
|
||||||
@@ -251,6 +272,7 @@ fpi_ssm_free (FpiSsm *machine)
|
|||||||
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);
|
fpi_ssm_clear_delayed_action (machine);
|
||||||
g_free (machine);
|
g_free (machine);
|
||||||
}
|
}
|
||||||
@@ -259,7 +281,8 @@ 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -315,7 +338,10 @@ fpi_ssm_start_subsm (FpiSsm *parent, FpiSsm *child)
|
|||||||
{
|
{
|
||||||
BUG_ON (parent->timeout);
|
BUG_ON (parent->timeout);
|
||||||
child->parentsm = parent;
|
child->parentsm = parent;
|
||||||
g_clear_pointer (&parent->timeout, g_source_destroy);
|
|
||||||
|
fpi_ssm_clear_delayed_action (parent);
|
||||||
|
fpi_ssm_clear_delayed_action (child);
|
||||||
|
|
||||||
fpi_ssm_start (child, __subsm_complete);
|
fpi_ssm_start (child, __subsm_complete);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -337,9 +363,11 @@ fpi_ssm_mark_completed (FpiSsm *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;
|
||||||
@@ -383,9 +411,9 @@ fpi_ssm_mark_completed_delayed (FpiSsm *machine,
|
|||||||
on_device_timeout_complete, cancellable,
|
on_device_timeout_complete, cancellable,
|
||||||
machine, NULL);
|
machine, NULL);
|
||||||
|
|
||||||
source_name = g_strdup_printf ("[%s] ssm %p complete %d",
|
source_name = g_strdup_printf ("[%s] ssm %s complete %d",
|
||||||
fp_device_get_device_id (machine->dev),
|
fp_device_get_device_id (machine->dev),
|
||||||
machine, machine->cur_state + 1);
|
machine->name, machine->cur_state + 1);
|
||||||
g_source_set_name (machine->timeout, source_name);
|
g_source_set_name (machine->timeout, source_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -402,12 +430,15 @@ 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",
|
||||||
|
fp_device_get_driver (machine->dev), machine->name,
|
||||||
|
machine->cur_state, error->message);
|
||||||
machine->error = g_steal_pointer (&error);
|
machine->error = g_steal_pointer (&error);
|
||||||
fpi_ssm_mark_completed (machine);
|
fpi_ssm_mark_completed (machine);
|
||||||
}
|
}
|
||||||
@@ -444,6 +475,9 @@ fpi_ssm_cancel_delayed_state_change (FpiSsm *machine)
|
|||||||
BUG_ON (machine->completed);
|
BUG_ON (machine->completed);
|
||||||
BUG_ON (machine->timeout == NULL);
|
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);
|
fpi_ssm_clear_delayed_action (machine);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -482,9 +516,9 @@ fpi_ssm_next_state_delayed (FpiSsm *machine,
|
|||||||
on_device_timeout_next_state, cancellable,
|
on_device_timeout_next_state, cancellable,
|
||||||
machine, NULL);
|
machine, NULL);
|
||||||
|
|
||||||
source_name = g_strdup_printf ("[%s] ssm %p jump to next state %d",
|
source_name = g_strdup_printf ("[%s] ssm %s jump to next state %d",
|
||||||
fp_device_get_device_id (machine->dev),
|
fp_device_get_device_id (machine->dev),
|
||||||
machine, machine->cur_state + 1);
|
machine->name, machine->cur_state + 1);
|
||||||
g_source_set_name (machine->timeout, source_name);
|
g_source_set_name (machine->timeout, source_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -548,8 +582,7 @@ fpi_ssm_jump_to_state_delayed (FpiSsm *machine,
|
|||||||
g_autofree char *source_name = NULL;
|
g_autofree char *source_name = NULL;
|
||||||
|
|
||||||
g_return_if_fail (machine != NULL);
|
g_return_if_fail (machine != NULL);
|
||||||
BUG_ON (machine->completed);
|
BUG_ON (state < 0 || state >= machine->nr_states);
|
||||||
BUG_ON (machine->timeout != NULL);
|
|
||||||
|
|
||||||
data = g_new0 (FpiSsmJumpToStateDelayedData, 1);
|
data = g_new0 (FpiSsmJumpToStateDelayedData, 1);
|
||||||
data->machine = machine;
|
data->machine = machine;
|
||||||
@@ -559,9 +592,9 @@ fpi_ssm_jump_to_state_delayed (FpiSsm *machine,
|
|||||||
on_device_timeout_jump_to_state,
|
on_device_timeout_jump_to_state,
|
||||||
cancellable, data, g_free);
|
cancellable, data, g_free);
|
||||||
|
|
||||||
source_name = g_strdup_printf ("[%s] ssm %p jump to state %d",
|
source_name = g_strdup_printf ("[%s] ssm %s jump to state %d",
|
||||||
fp_device_get_device_id (machine->dev),
|
fp_device_get_device_id (machine->dev),
|
||||||
machine, state);
|
machine->name, state);
|
||||||
g_source_set_name (machine->timeout, source_name);
|
g_source_set_name (machine->timeout, source_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -39,7 +39,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().
|
||||||
@@ -60,9 +60,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) \
|
||||||
|
fpi_ssm_new_full (dev, handler, nr_states, #nr_states)
|
||||||
|
FpiSsm *fpi_ssm_new_full (FpDevice *dev,
|
||||||
FpiSsmHandlerCallback handler,
|
FpiSsmHandlerCallback handler,
|
||||||
int nr_states);
|
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);
|
||||||
@@ -106,3 +109,5 @@ void fpi_ssm_usb_transfer_with_weak_pointer_cb (FpiUsbTransfer *transfer,
|
|||||||
FpDevice *device,
|
FpDevice *device,
|
||||||
gpointer weak_ptr,
|
gpointer weak_ptr,
|
||||||
GError *error);
|
GError *error);
|
||||||
|
|
||||||
|
G_DEFINE_AUTOPTR_CLEANUP_FUNC (FpiSsm, fpi_ssm_free)
|
||||||
|
|||||||
@@ -298,7 +298,7 @@ fpi_usb_transfer_fill_interrupt_full (FpiUsbTransfer *transfer,
|
|||||||
transfer->free_buffer = free_func;
|
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;
|
||||||
@@ -454,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);
|
||||||
|
|
||||||
@@ -469,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);
|
||||||
@@ -485,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);
|
||||||
@@ -496,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);
|
||||||
@@ -511,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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,23 +31,19 @@ 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(GTypeClass) type_class = g_type_class_ref (driver);
|
||||||
|
FpDeviceClass *cls = FP_DEVICE_CLASS (type_class);
|
||||||
const FpIdEntry *entry;
|
const FpIdEntry *entry;
|
||||||
|
|
||||||
if (cls->type != FP_DEVICE_TYPE_USB)
|
if (cls->type != FP_DEVICE_TYPE_USB)
|
||||||
{
|
|
||||||
g_type_class_unref (cls);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
|
|
||||||
for (entry = cls->id_table; entry->vid; entry++)
|
for (entry = cls->id_table; entry->vid; entry++)
|
||||||
{
|
{
|
||||||
@@ -65,8 +61,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;
|
||||||
|
|||||||
@@ -96,27 +96,21 @@ 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;
|
||||||
|
|
||||||
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(GTypeClass) type_class = g_type_class_ref (driver);
|
||||||
|
FpDeviceClass *cls = FP_DEVICE_CLASS (type_class);
|
||||||
|
|
||||||
if (cls->type != FP_DEVICE_TYPE_USB)
|
if (cls->type != FP_DEVICE_TYPE_USB)
|
||||||
{
|
|
||||||
g_type_class_unref (cls);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
|
|
||||||
print_driver (cls);
|
print_driver (cls);
|
||||||
|
|
||||||
g_type_class_unref (cls);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
print_driver (&whitelist);
|
print_driver (&whitelist);
|
||||||
|
|||||||
@@ -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:
|
||||||
*;
|
*;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -4,7 +4,14 @@ 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-device.c',
|
||||||
|
'fpi-image.c',
|
||||||
|
'fpi-image-device.c',
|
||||||
|
'fpi-print.c',
|
||||||
'fpi-ssm.c',
|
'fpi-ssm.c',
|
||||||
'fpi-usb-transfer.c',
|
'fpi-usb-transfer.c',
|
||||||
'fpi-byte-reader.c',
|
'fpi-byte-reader.c',
|
||||||
@@ -172,45 +179,81 @@ fpi_enums = gnome.mkenums_simple('fpi-enums',
|
|||||||
fpi_enums_h = fpi_enums[1]
|
fpi_enums_h = fpi_enums[1]
|
||||||
|
|
||||||
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'
|
|
||||||
vflag = '-Wl,--version-script,@0@/@1@'.format(meson.current_source_dir(), mapfile)
|
|
||||||
|
|
||||||
deps = [ mathlib_dep, glib_dep, gusb_dep, nss_dep, imaging_dep, gio_dep ]
|
deps = [ mathlib_dep, glib_dep, gusb_dep, nss_dep, imaging_dep, gio_dep ]
|
||||||
libfprint = library('fprint',
|
|
||||||
libfprint_sources + fp_enums + fpi_enums +
|
deps += declare_dependency(include_directories: [
|
||||||
drivers_sources + nbis_sources + other_sources,
|
|
||||||
soversion: soversion,
|
|
||||||
version: libversion,
|
|
||||||
c_args: common_cflags + drivers_cflags,
|
|
||||||
include_directories: [
|
|
||||||
root_inc,
|
root_inc,
|
||||||
include_directories('nbis/include'),
|
include_directories('nbis/include'),
|
||||||
],
|
include_directories('nbis/libfprint-include'),
|
||||||
|
])
|
||||||
|
|
||||||
|
libnbis = static_library('nbis',
|
||||||
|
nbis_sources,
|
||||||
|
dependencies: deps,
|
||||||
|
c_args: cc.get_supported_arguments([
|
||||||
|
'-Wno-error=redundant-decls',
|
||||||
|
'-Wno-redundant-decls',
|
||||||
|
'-Wno-discarded-qualifiers',
|
||||||
|
]),
|
||||||
|
install: false)
|
||||||
|
|
||||||
|
libfprint_private = static_library('fprint-private',
|
||||||
|
sources: libfprint_private_sources + fpi_enums + [ fp_enums_h ],
|
||||||
|
dependencies: deps,
|
||||||
|
link_with: libnbis,
|
||||||
|
install: false)
|
||||||
|
|
||||||
|
libfprint_drivers = static_library('fprint-drivers',
|
||||||
|
sources: drivers_sources + [ fp_enums_h ],
|
||||||
|
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('fprint',
|
||||||
|
sources: libfprint_sources + fp_enums + other_sources,
|
||||||
|
soversion: soversion,
|
||||||
|
version: libversion,
|
||||||
link_args : vflag,
|
link_args : vflag,
|
||||||
link_depends : mapfile,
|
link_depends : mapfile,
|
||||||
|
link_with: [libfprint_private, libfprint_drivers],
|
||||||
dependencies: deps,
|
dependencies: deps,
|
||||||
install: true)
|
install: true)
|
||||||
|
|
||||||
libfprint_dep = declare_dependency(link_with: libfprint,
|
libfprint_dep = declare_dependency(link_with: libfprint,
|
||||||
sources: [ fp_enums_h ],
|
sources: [ fp_enums_h ],
|
||||||
include_directories: root_inc,
|
include_directories: root_inc,
|
||||||
dependencies: [ glib_dep, gusb_dep, gio_dep ])
|
dependencies: [
|
||||||
|
gio_dep,
|
||||||
|
glib_dep,
|
||||||
|
gusb_dep,
|
||||||
|
])
|
||||||
|
|
||||||
install_headers(['fprint.h'] + libfprint_public_headers, subdir: 'libfprint')
|
install_headers(['fprint.h'] + libfprint_public_headers, subdir: 'libfprint')
|
||||||
|
|
||||||
|
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,
|
||||||
],
|
|
||||||
dependencies: [ deps, libfprint_dep ],
|
|
||||||
install: false)
|
install: false)
|
||||||
|
|
||||||
if get_option('udev_rules')
|
if get_option('udev_rules')
|
||||||
@@ -224,10 +267,8 @@ 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,
|
||||||
],
|
|
||||||
dependencies: [ deps, libfprint_dep ],
|
|
||||||
install: false)
|
install: false)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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 */
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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];
|
||||||
|
|
||||||
/**************************************************************************/
|
/**************************************************************************/
|
||||||
/**************************************************************************/
|
/**************************************************************************/
|
||||||
|
|||||||
@@ -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 */
|
||||||
|
|||||||
@@ -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
libfprint/nbis/libfprint-include/nbis.h
Normal file
35
libfprint/nbis/libfprint-include/nbis.h
Normal 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
|
||||||
@@ -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
libfprint/nbis/remove-global-y.cocci
Normal file
21
libfprint/nbis/remove-global-y.cocci
Normal 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] = {};
|
||||||
@@ -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
|
||||||
76
meson.build
76
meson.build
@@ -10,9 +10,6 @@ project('libfprint', [ 'c', 'cpp' ],
|
|||||||
|
|
||||||
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')
|
||||||
@@ -23,19 +20,53 @@ glib_min_version = '2.56'
|
|||||||
glib_version_def = 'GLIB_VERSION_@0@_@1@'.format(
|
glib_version_def = 'GLIB_VERSION_@0@_@1@'.format(
|
||||||
glib_min_version.split('.')[0], glib_min_version.split('.')[1])
|
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',
|
||||||
|
'-Werror=int-to-pointer-cast',
|
||||||
|
'-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_MIN_REQUIRED=' + glib_version_def,
|
||||||
'-DGLIB_VERSION_MAX_ALLOWED=' + glib_version_def,
|
'-DGLIB_VERSION_MAX_ALLOWED=' + glib_version_def,
|
||||||
|
'-D_GNU_SOURCE',
|
||||||
|
'-DG_LOG_DOMAIN="libfprint"',
|
||||||
])
|
])
|
||||||
|
c_cflags = cc.get_supported_arguments([
|
||||||
|
'-std=gnu99',
|
||||||
|
'-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
|
||||||
@@ -115,14 +146,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('.')
|
||||||
|
|
||||||
@@ -156,10 +199,7 @@ 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(
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ c.enumerate()
|
|||||||
devices = c.get_devices()
|
devices = c.get_devices()
|
||||||
|
|
||||||
d = devices[0]
|
d = devices[0]
|
||||||
|
del devices
|
||||||
|
|
||||||
d.open_sync()
|
d.open_sync()
|
||||||
|
|
||||||
@@ -24,6 +25,9 @@ img = d.capture_sync(True)
|
|||||||
|
|
||||||
d.close_sync()
|
d.close_sync()
|
||||||
|
|
||||||
|
del d
|
||||||
|
del c
|
||||||
|
|
||||||
width = img.get_width()
|
width = img.get_width()
|
||||||
height = img.get_height()
|
height = img.get_height()
|
||||||
|
|
||||||
@@ -36,10 +40,12 @@ c_buf = c_img.get_data()
|
|||||||
|
|
||||||
for x in range(width):
|
for x in range(width):
|
||||||
for y in range(height):
|
for y in range(height):
|
||||||
|
# The upper byte is don't care, but the location depends on endianness,
|
||||||
|
# so just set all of them.
|
||||||
c_buf[y * c_rowstride + x * 4 + 0] = buf[y * width + x]
|
c_buf[y * c_rowstride + x * 4 + 0] = buf[y * width + x]
|
||||||
c_buf[y * c_rowstride + x * 4 + 1] = buf[y * width + x]
|
c_buf[y * c_rowstride + x * 4 + 1] = buf[y * width + x]
|
||||||
c_buf[y * c_rowstride + x * 4 + 2] = buf[y * width + x]
|
c_buf[y * c_rowstride + x * 4 + 2] = buf[y * width + x]
|
||||||
# Byte 4 is don't care
|
c_buf[y * c_rowstride + x * 4 + 3] = buf[y * width + x]
|
||||||
|
|
||||||
c_img.mark_dirty()
|
c_img.mark_dirty()
|
||||||
c_img.write_to_png(sys.argv[1])
|
c_img.write_to_png(sys.argv[1])
|
||||||
|
|||||||
@@ -5,16 +5,20 @@ envs.set('G_MESSAGES_DEBUG', 'all')
|
|||||||
|
|
||||||
# Setup paths
|
# Setup paths
|
||||||
envs.set('MESON_SOURCE_ROOT', meson.build_root())
|
envs.set('MESON_SOURCE_ROOT', meson.build_root())
|
||||||
envs.prepend('GI_TYPELIB_PATH', join_paths(meson.build_root(), 'libfprint'))
|
|
||||||
envs.prepend('LD_LIBRARY_PATH', join_paths(meson.build_root(), 'libfprint'))
|
envs.prepend('LD_LIBRARY_PATH', join_paths(meson.build_root(), 'libfprint'))
|
||||||
|
|
||||||
# Set FP_DEVICE_EMULATION so that drivers can adapt (e.g. to use fixed
|
# Set FP_DEVICE_EMULATION so that drivers can adapt (e.g. to use fixed
|
||||||
# random numbers rather than proper ones)
|
# random numbers rather than proper ones)
|
||||||
envs.set('FP_DEVICE_EMULATION', '1')
|
envs.set('FP_DEVICE_EMULATION', '1')
|
||||||
|
|
||||||
|
# Set a colon-separated list of native drivers we enable in tests
|
||||||
|
envs.set('FP_DRIVERS_WHITELIST', 'virtual_image')
|
||||||
|
|
||||||
envs.set('NO_AT_BRIDGE', '1')
|
envs.set('NO_AT_BRIDGE', '1')
|
||||||
|
|
||||||
if get_option('introspection')
|
if get_option('introspection')
|
||||||
|
envs.prepend('GI_TYPELIB_PATH', join_paths(meson.build_root(), 'libfprint'))
|
||||||
|
|
||||||
if 'virtual_image' in drivers
|
if 'virtual_image' in drivers
|
||||||
test('virtual-image',
|
test('virtual-image',
|
||||||
find_program('virtual-image.py'),
|
find_program('virtual-image.py'),
|
||||||
@@ -30,10 +34,13 @@ if get_option('introspection')
|
|||||||
]
|
]
|
||||||
|
|
||||||
foreach driver_test: drivers_tests
|
foreach driver_test: drivers_tests
|
||||||
|
driver_envs = envs
|
||||||
|
driver_envs.set('FP_DRIVERS_WHITELIST', driver_test)
|
||||||
|
|
||||||
test(driver_test,
|
test(driver_test,
|
||||||
find_program('umockdev-test.py'),
|
find_program('umockdev-test.py'),
|
||||||
args: join_paths(meson.current_source_dir(), driver_test),
|
args: join_paths(meson.current_source_dir(), driver_test),
|
||||||
env: envs,
|
env: driver_envs,
|
||||||
suite: ['drivers'],
|
suite: ['drivers'],
|
||||||
timeout: 10,
|
timeout: 10,
|
||||||
depends: libfprint_typelib,
|
depends: libfprint_typelib,
|
||||||
@@ -41,6 +48,42 @@ if get_option('introspection')
|
|||||||
endforeach
|
endforeach
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
test_utils = static_library('fprint-test-utils',
|
||||||
|
sources: [
|
||||||
|
'test-utils.c',
|
||||||
|
'test-device-fake.c',
|
||||||
|
],
|
||||||
|
dependencies: libfprint_private_dep,
|
||||||
|
install: false)
|
||||||
|
|
||||||
|
unit_tests = [
|
||||||
|
'fpi-device',
|
||||||
|
'fpi-ssm',
|
||||||
|
]
|
||||||
|
|
||||||
|
if 'virtual_image' in drivers
|
||||||
|
unit_tests += [
|
||||||
|
'fp-context',
|
||||||
|
'fp-device',
|
||||||
|
]
|
||||||
|
endif
|
||||||
|
|
||||||
|
foreach test_name: unit_tests
|
||||||
|
basename = 'test-' + test_name
|
||||||
|
test_exe = executable(basename,
|
||||||
|
sources: basename + '.c',
|
||||||
|
dependencies: libfprint_private_dep,
|
||||||
|
c_args: common_cflags,
|
||||||
|
link_with: test_utils,
|
||||||
|
)
|
||||||
|
test(test_name,
|
||||||
|
find_program('test-runner.sh'),
|
||||||
|
suite: ['unit-tests'],
|
||||||
|
args: [test_exe],
|
||||||
|
env: envs,
|
||||||
|
)
|
||||||
|
endforeach
|
||||||
|
|
||||||
gdb = find_program('gdb', required: false)
|
gdb = find_program('gdb', required: false)
|
||||||
if gdb.found()
|
if gdb.found()
|
||||||
add_test_setup('gdb',
|
add_test_setup('gdb',
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ c.enumerate()
|
|||||||
devices = c.get_devices()
|
devices = c.get_devices()
|
||||||
|
|
||||||
d = devices[0]
|
d = devices[0]
|
||||||
|
del devices
|
||||||
|
|
||||||
assert d.get_driver() == "synaptics"
|
assert d.get_driver() == "synaptics"
|
||||||
|
|
||||||
@@ -40,3 +41,6 @@ print("deleting")
|
|||||||
d.delete_print_sync(p)
|
d.delete_print_sync(p)
|
||||||
print("delete done")
|
print("delete done")
|
||||||
d.close_sync()
|
d.close_sync()
|
||||||
|
|
||||||
|
del d
|
||||||
|
del c
|
||||||
|
|||||||
205
tests/test-device-fake.c
Normal file
205
tests/test-device-fake.c
Normal file
@@ -0,0 +1,205 @@
|
|||||||
|
/*
|
||||||
|
* Virtual driver for device debugging
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define FP_COMPONENT "fake_test_dev"
|
||||||
|
|
||||||
|
#include "test-device-fake.h"
|
||||||
|
|
||||||
|
G_DEFINE_TYPE (FpiDeviceFake, fpi_device_fake, FP_TYPE_DEVICE)
|
||||||
|
|
||||||
|
static const FpIdEntry driver_ids[] = {
|
||||||
|
{ .virtual_envvar = "FP_VIRTUAL_FAKE_DEVICE" },
|
||||||
|
{ .virtual_envvar = NULL }
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
fpi_device_fake_probe (FpDevice *device)
|
||||||
|
{
|
||||||
|
FpDeviceClass *dev_class = FP_DEVICE_GET_CLASS (device);
|
||||||
|
FpiDeviceFake *fake_dev = FPI_DEVICE_FAKE (device);
|
||||||
|
|
||||||
|
g_assert_cmpuint (fpi_device_get_current_action (device), ==, FP_DEVICE_ACTION_PROBE);
|
||||||
|
|
||||||
|
fake_dev->last_called_function = fpi_device_fake_probe;
|
||||||
|
fpi_device_probe_complete (device, dev_class->id, dev_class->full_name,
|
||||||
|
fake_dev->ret_error);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
fpi_device_fake_open (FpDevice *device)
|
||||||
|
{
|
||||||
|
FpiDeviceFake *fake_dev = FPI_DEVICE_FAKE (device);
|
||||||
|
|
||||||
|
g_assert_cmpuint (fpi_device_get_current_action (device), ==, FP_DEVICE_ACTION_OPEN);
|
||||||
|
|
||||||
|
fake_dev->last_called_function = fpi_device_fake_open;
|
||||||
|
fpi_device_open_complete (device, fake_dev->ret_error);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
fpi_device_fake_close (FpDevice *device)
|
||||||
|
{
|
||||||
|
FpiDeviceFake *fake_dev = FPI_DEVICE_FAKE (device);
|
||||||
|
|
||||||
|
g_assert_cmpuint (fpi_device_get_current_action (device), ==, FP_DEVICE_ACTION_CLOSE);
|
||||||
|
|
||||||
|
fake_dev->last_called_function = fpi_device_fake_close;
|
||||||
|
fpi_device_close_complete (device, fake_dev->ret_error);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
fpi_device_fake_enroll (FpDevice *device)
|
||||||
|
{
|
||||||
|
FpiDeviceFake *fake_dev = FPI_DEVICE_FAKE (device);
|
||||||
|
FpPrint *print = fake_dev->ret_print;
|
||||||
|
|
||||||
|
g_assert_cmpuint (fpi_device_get_current_action (device), ==, FP_DEVICE_ACTION_ENROLL);
|
||||||
|
fpi_device_get_enroll_data (device, (FpPrint **) &fake_dev->action_data);
|
||||||
|
|
||||||
|
if (!print && !fake_dev->ret_error)
|
||||||
|
fpi_device_get_enroll_data (device, &print);
|
||||||
|
|
||||||
|
fake_dev->last_called_function = fpi_device_fake_enroll;
|
||||||
|
fpi_device_enroll_complete (device, print, fake_dev->ret_error);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
fpi_device_fake_verify (FpDevice *device)
|
||||||
|
{
|
||||||
|
FpiDeviceFake *fake_dev = FPI_DEVICE_FAKE (device);
|
||||||
|
FpPrint *print = fake_dev->ret_print;
|
||||||
|
|
||||||
|
g_assert_cmpuint (fpi_device_get_current_action (device), ==, FP_DEVICE_ACTION_VERIFY);
|
||||||
|
fpi_device_get_verify_data (device, (FpPrint **) &fake_dev->action_data);
|
||||||
|
|
||||||
|
if (!print && !fake_dev->ret_error)
|
||||||
|
fpi_device_get_verify_data (device, &print);
|
||||||
|
|
||||||
|
fake_dev->last_called_function = fpi_device_fake_verify;
|
||||||
|
fpi_device_verify_complete (device, fake_dev->ret_result, print,
|
||||||
|
fake_dev->ret_error);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
fpi_device_fake_identify (FpDevice *device)
|
||||||
|
{
|
||||||
|
FpiDeviceFake *fake_dev = FPI_DEVICE_FAKE (device);
|
||||||
|
FpPrint *match = fake_dev->ret_match;
|
||||||
|
|
||||||
|
g_assert_cmpuint (fpi_device_get_current_action (device), ==, FP_DEVICE_ACTION_IDENTIFY);
|
||||||
|
fpi_device_get_identify_data (device, (GPtrArray **) &fake_dev->action_data);
|
||||||
|
|
||||||
|
if (!match && !fake_dev->ret_error)
|
||||||
|
{
|
||||||
|
GPtrArray *prints;
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
fpi_device_get_identify_data (device, &prints);
|
||||||
|
|
||||||
|
for (i = 0; prints && i < prints->len; ++i)
|
||||||
|
{
|
||||||
|
FpPrint *print = g_ptr_array_index (prints, i);
|
||||||
|
|
||||||
|
if (g_strcmp0 (fp_print_get_description (print), "fake-verified") == 0)
|
||||||
|
{
|
||||||
|
match = print;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fake_dev->last_called_function = fpi_device_fake_identify;
|
||||||
|
fpi_device_identify_complete (device, match, fake_dev->ret_print,
|
||||||
|
fake_dev->ret_error);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
fpi_device_fake_capture (FpDevice *device)
|
||||||
|
{
|
||||||
|
FpiDeviceFake *fake_dev = FPI_DEVICE_FAKE (device);
|
||||||
|
|
||||||
|
g_assert_cmpuint (fpi_device_get_current_action (device), ==, FP_DEVICE_ACTION_CAPTURE);
|
||||||
|
fpi_device_get_capture_data (device, (gboolean *) &fake_dev->action_data);
|
||||||
|
|
||||||
|
fake_dev->last_called_function = fpi_device_fake_capture;
|
||||||
|
fpi_device_capture_complete (device, fake_dev->ret_image, fake_dev->ret_error);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
fpi_device_fake_list (FpDevice *device)
|
||||||
|
{
|
||||||
|
FpiDeviceFake *fake_dev = FPI_DEVICE_FAKE (device);
|
||||||
|
|
||||||
|
g_assert_cmpuint (fpi_device_get_current_action (device), ==, FP_DEVICE_ACTION_LIST);
|
||||||
|
|
||||||
|
fake_dev->last_called_function = fpi_device_fake_list;
|
||||||
|
fpi_device_list_complete (device, fake_dev->ret_list, fake_dev->ret_error);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
fpi_device_fake_delete (FpDevice *device)
|
||||||
|
{
|
||||||
|
FpiDeviceFake *fake_dev = FPI_DEVICE_FAKE (device);
|
||||||
|
|
||||||
|
g_assert_cmpuint (fpi_device_get_current_action (device), ==, FP_DEVICE_ACTION_DELETE);
|
||||||
|
fpi_device_get_delete_data (device, (gpointer) & fake_dev->action_data);
|
||||||
|
|
||||||
|
fake_dev->last_called_function = fpi_device_fake_delete;
|
||||||
|
fpi_device_delete_complete (device, fake_dev->ret_error);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
fpi_device_fake_cancel (FpDevice *device)
|
||||||
|
{
|
||||||
|
FpiDeviceFake *fake_dev = FPI_DEVICE_FAKE (device);
|
||||||
|
|
||||||
|
g_assert_cmpuint (fpi_device_get_current_action (device), !=, FP_DEVICE_ACTION_NONE);
|
||||||
|
|
||||||
|
fake_dev->last_called_function = fpi_device_fake_cancel;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
fpi_device_fake_init (FpiDeviceFake *self)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
fpi_device_fake_class_init (FpiDeviceFakeClass *klass)
|
||||||
|
{
|
||||||
|
FpDeviceClass *dev_class = FP_DEVICE_CLASS (klass);
|
||||||
|
|
||||||
|
dev_class->id = FP_COMPONENT;
|
||||||
|
dev_class->full_name = "Virtual device for debugging";
|
||||||
|
dev_class->type = FP_DEVICE_TYPE_VIRTUAL;
|
||||||
|
dev_class->id_table = driver_ids;
|
||||||
|
dev_class->nr_enroll_stages = 5;
|
||||||
|
dev_class->scan_type = FP_SCAN_TYPE_PRESS;
|
||||||
|
|
||||||
|
dev_class->probe = fpi_device_fake_probe;
|
||||||
|
dev_class->open = fpi_device_fake_open;
|
||||||
|
dev_class->close = fpi_device_fake_close;
|
||||||
|
dev_class->enroll = fpi_device_fake_enroll;
|
||||||
|
dev_class->verify = fpi_device_fake_verify;
|
||||||
|
dev_class->identify = fpi_device_fake_identify;
|
||||||
|
dev_class->capture = fpi_device_fake_capture;
|
||||||
|
dev_class->list = fpi_device_fake_list;
|
||||||
|
dev_class->delete = fpi_device_fake_delete;
|
||||||
|
dev_class->cancel = fpi_device_fake_cancel;
|
||||||
|
}
|
||||||
43
tests/test-device-fake.h
Normal file
43
tests/test-device-fake.h
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
/*
|
||||||
|
* Virtual driver for device debugging
|
||||||
|
*
|
||||||
|
* 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"
|
||||||
|
|
||||||
|
#define FPI_TYPE_DEVICE_FAKE (fpi_device_fake_get_type ())
|
||||||
|
G_DECLARE_FINAL_TYPE (FpiDeviceFake, fpi_device_fake, FPI, DEVICE_FAKE, FpDevice)
|
||||||
|
|
||||||
|
struct _FpiDeviceFake
|
||||||
|
{
|
||||||
|
FpDevice parent;
|
||||||
|
|
||||||
|
gpointer last_called_function;
|
||||||
|
|
||||||
|
GError *ret_error;
|
||||||
|
FpPrint *ret_print;
|
||||||
|
FpPrint *ret_match;
|
||||||
|
FpiMatchResult ret_result;
|
||||||
|
FpImage *ret_image;
|
||||||
|
GPtrArray *ret_list;
|
||||||
|
|
||||||
|
gpointer action_data;
|
||||||
|
gpointer user_data;
|
||||||
|
};
|
||||||
106
tests/test-fp-context.c
Normal file
106
tests/test-fp-context.c
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
/*
|
||||||
|
* FpContext Unit tests
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <libfprint/fprint.h>
|
||||||
|
|
||||||
|
#include "test-utils.h"
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_context_new (void)
|
||||||
|
{
|
||||||
|
g_autoptr(FpContext) context = fp_context_new ();
|
||||||
|
g_assert_true (FP_CONTEXT (context));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_context_has_no_devices (void)
|
||||||
|
{
|
||||||
|
g_autoptr(FpContext) context = NULL;
|
||||||
|
GPtrArray *devices;
|
||||||
|
|
||||||
|
context = fp_context_new ();
|
||||||
|
devices = fp_context_get_devices (context);
|
||||||
|
|
||||||
|
g_assert_nonnull (devices);
|
||||||
|
g_assert_cmpuint (devices->len, ==, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_context_has_virtual_device (void)
|
||||||
|
{
|
||||||
|
g_autoptr(FpContext) context = NULL;
|
||||||
|
FpDevice *virtual_device = NULL;
|
||||||
|
GPtrArray *devices;
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
fpt_setup_virtual_device_environment ();
|
||||||
|
|
||||||
|
context = fp_context_new ();
|
||||||
|
devices = fp_context_get_devices (context);
|
||||||
|
|
||||||
|
g_assert_nonnull (devices);
|
||||||
|
g_assert_cmpuint (devices->len, ==, 1);
|
||||||
|
|
||||||
|
for (i = 0; i < devices->len; ++i)
|
||||||
|
{
|
||||||
|
FpDevice *device = devices->pdata[i];
|
||||||
|
|
||||||
|
if (g_strcmp0 (fp_device_get_driver (device), "virtual_image") == 0)
|
||||||
|
{
|
||||||
|
virtual_device = device;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
g_assert_true (FP_IS_DEVICE (virtual_device));
|
||||||
|
|
||||||
|
fpt_teardown_virtual_device_environment ();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_context_enumerates_new_devices (void)
|
||||||
|
{
|
||||||
|
g_autoptr(FpContext) context = NULL;
|
||||||
|
GPtrArray *devices;
|
||||||
|
|
||||||
|
context = fp_context_new ();
|
||||||
|
|
||||||
|
fpt_setup_virtual_device_environment ();
|
||||||
|
|
||||||
|
fp_context_enumerate (context);
|
||||||
|
devices = fp_context_get_devices (context);
|
||||||
|
|
||||||
|
g_assert_nonnull (devices);
|
||||||
|
g_assert_cmpuint (devices->len, ==, 1);
|
||||||
|
|
||||||
|
fpt_teardown_virtual_device_environment ();
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main (int argc, char *argv[])
|
||||||
|
{
|
||||||
|
g_test_init (&argc, &argv, NULL);
|
||||||
|
|
||||||
|
g_test_add_func ("/context/new", test_context_new);
|
||||||
|
g_test_add_func ("/context/no-devices", test_context_has_no_devices);
|
||||||
|
g_test_add_func ("/context/has-virtual-device", test_context_has_virtual_device);
|
||||||
|
g_test_add_func ("/context/enumerates-new-devices", test_context_enumerates_new_devices);
|
||||||
|
|
||||||
|
return g_test_run ();
|
||||||
|
}
|
||||||
238
tests/test-fp-device.c
Normal file
238
tests/test-fp-device.c
Normal file
@@ -0,0 +1,238 @@
|
|||||||
|
/*
|
||||||
|
* FpDevice Unit tests
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <libfprint/fprint.h>
|
||||||
|
|
||||||
|
#include "test-utils.h"
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_device_opened (FpDevice *dev, GAsyncResult *res, FptContext *tctx)
|
||||||
|
{
|
||||||
|
g_autoptr(GError) error = NULL;
|
||||||
|
|
||||||
|
g_assert_true (fp_device_open_finish (dev, res, &error));
|
||||||
|
g_assert_no_error (error);
|
||||||
|
g_assert_true (fp_device_is_open (tctx->device));
|
||||||
|
|
||||||
|
tctx->user_data = GUINT_TO_POINTER (TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_device_open_async (void)
|
||||||
|
{
|
||||||
|
g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_imgdev ();
|
||||||
|
|
||||||
|
fp_device_open (tctx->device, NULL, (GAsyncReadyCallback) on_device_opened, tctx);
|
||||||
|
|
||||||
|
while (!GPOINTER_TO_UINT (tctx->user_data))
|
||||||
|
g_main_context_iteration (NULL, TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_device_closed (FpDevice *dev, GAsyncResult *res, FptContext *tctx)
|
||||||
|
{
|
||||||
|
g_autoptr(GError) error = NULL;
|
||||||
|
|
||||||
|
g_assert_true (fp_device_close_finish (dev, res, &error));
|
||||||
|
g_assert_no_error (error);
|
||||||
|
g_assert_false (fp_device_is_open (tctx->device));
|
||||||
|
|
||||||
|
tctx->user_data = GUINT_TO_POINTER (TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_device_close_async (void)
|
||||||
|
{
|
||||||
|
g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_imgdev ();
|
||||||
|
|
||||||
|
fp_device_open (tctx->device, NULL, (GAsyncReadyCallback) on_device_opened, tctx);
|
||||||
|
while (!tctx->user_data)
|
||||||
|
g_main_context_iteration (NULL, TRUE);
|
||||||
|
|
||||||
|
tctx->user_data = GUINT_TO_POINTER (FALSE);
|
||||||
|
fp_device_close (tctx->device, NULL, (GAsyncReadyCallback) on_device_closed, tctx);
|
||||||
|
|
||||||
|
while (!GPOINTER_TO_UINT (tctx->user_data))
|
||||||
|
g_main_context_iteration (NULL, TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_device_open_sync (void)
|
||||||
|
{
|
||||||
|
g_autoptr(GError) error = NULL;
|
||||||
|
g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_imgdev ();
|
||||||
|
|
||||||
|
fp_device_open_sync (tctx->device, NULL, &error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
g_assert_true (fp_device_is_open (tctx->device));
|
||||||
|
|
||||||
|
fp_device_open_sync (tctx->device, NULL, &error);
|
||||||
|
g_assert_error (error, FP_DEVICE_ERROR, FP_DEVICE_ERROR_ALREADY_OPEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_open_notify (FpDevice *rdev, GParamSpec *spec, FptContext *tctx)
|
||||||
|
{
|
||||||
|
g_assert_cmpstr (spec->name, ==, "open");
|
||||||
|
tctx->user_data = GUINT_TO_POINTER (TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_device_open_sync_notify (void)
|
||||||
|
{
|
||||||
|
g_autoptr(GError) error = NULL;
|
||||||
|
g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_imgdev ();
|
||||||
|
|
||||||
|
g_signal_connect (tctx->device, "notify::open", G_CALLBACK (on_open_notify), tctx);
|
||||||
|
fp_device_open_sync (tctx->device, NULL, &error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
g_assert_true (GPOINTER_TO_INT (tctx->user_data));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_device_close_sync (void)
|
||||||
|
{
|
||||||
|
g_autoptr(GError) error = NULL;
|
||||||
|
g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_imgdev ();
|
||||||
|
|
||||||
|
fp_device_open_sync (tctx->device, NULL, NULL);
|
||||||
|
fp_device_close_sync (tctx->device, NULL, &error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
g_assert_false (fp_device_is_open (tctx->device));
|
||||||
|
|
||||||
|
fp_device_close_sync (tctx->device, NULL, &error);
|
||||||
|
g_assert_error (error, FP_DEVICE_ERROR, FP_DEVICE_ERROR_NOT_OPEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_close_notify (FpDevice *rdev, GParamSpec *spec, FptContext *tctx)
|
||||||
|
{
|
||||||
|
g_assert_cmpstr (spec->name, ==, "open");
|
||||||
|
tctx->user_data = GUINT_TO_POINTER (TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_device_close_sync_notify (void)
|
||||||
|
{
|
||||||
|
g_autoptr(GError) error = NULL;
|
||||||
|
g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_imgdev ();
|
||||||
|
|
||||||
|
fp_device_open_sync (tctx->device, NULL, NULL);
|
||||||
|
|
||||||
|
g_signal_connect (tctx->device, "notify::open", G_CALLBACK (on_close_notify), tctx);
|
||||||
|
fp_device_close_sync (tctx->device, NULL, &error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
g_assert_true (GPOINTER_TO_INT (tctx->user_data));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_device_get_driver (void)
|
||||||
|
{
|
||||||
|
g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_imgdev ();
|
||||||
|
|
||||||
|
fp_device_open_sync (tctx->device, NULL, NULL);
|
||||||
|
g_assert_cmpstr (fp_device_get_driver (tctx->device), ==, "virtual_image");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_device_get_device_id (void)
|
||||||
|
{
|
||||||
|
g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_imgdev ();
|
||||||
|
|
||||||
|
fp_device_open_sync (tctx->device, NULL, NULL);
|
||||||
|
g_assert_cmpstr (fp_device_get_device_id (tctx->device), ==, "0");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_device_get_name (void)
|
||||||
|
{
|
||||||
|
g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_imgdev ();
|
||||||
|
|
||||||
|
fp_device_open_sync (tctx->device, NULL, NULL);
|
||||||
|
g_assert_cmpstr (fp_device_get_name (tctx->device), ==,
|
||||||
|
"Virtual image device for debugging");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_device_get_scan_type (void)
|
||||||
|
{
|
||||||
|
g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_imgdev ();
|
||||||
|
|
||||||
|
fp_device_open_sync (tctx->device, NULL, NULL);
|
||||||
|
g_assert_cmpint (fp_device_get_scan_type (tctx->device), ==, FP_SCAN_TYPE_SWIPE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_device_get_nr_enroll_stages (void)
|
||||||
|
{
|
||||||
|
g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_imgdev ();
|
||||||
|
|
||||||
|
fp_device_open_sync (tctx->device, NULL, NULL);
|
||||||
|
g_assert_cmpuint (fp_device_get_nr_enroll_stages (tctx->device), ==, 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_device_supports_identify (void)
|
||||||
|
{
|
||||||
|
g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_imgdev ();
|
||||||
|
|
||||||
|
fp_device_open_sync (tctx->device, NULL, NULL);
|
||||||
|
g_assert_true (fp_device_supports_identify (tctx->device));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_device_supports_capture (void)
|
||||||
|
{
|
||||||
|
g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_imgdev ();
|
||||||
|
|
||||||
|
fp_device_open_sync (tctx->device, NULL, NULL);
|
||||||
|
g_assert_true (fp_device_supports_capture (tctx->device));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_device_has_storage (void)
|
||||||
|
{
|
||||||
|
g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_imgdev ();
|
||||||
|
|
||||||
|
fp_device_open_sync (tctx->device, NULL, NULL);
|
||||||
|
g_assert_false (fp_device_has_storage (tctx->device));
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main (int argc, char *argv[])
|
||||||
|
{
|
||||||
|
g_test_init (&argc, &argv, NULL);
|
||||||
|
|
||||||
|
g_test_add_func ("/device/async/open", test_device_open_async);
|
||||||
|
g_test_add_func ("/device/async/close", test_device_close_async);
|
||||||
|
g_test_add_func ("/device/sync/open", test_device_open_sync);
|
||||||
|
g_test_add_func ("/device/sync/open/notify", test_device_open_sync_notify);
|
||||||
|
g_test_add_func ("/device/sync/close", test_device_close_sync);
|
||||||
|
g_test_add_func ("/device/sync/close/notify", test_device_close_sync_notify);
|
||||||
|
g_test_add_func ("/device/sync/get_driver", test_device_get_driver);
|
||||||
|
g_test_add_func ("/device/sync/get_device_id", test_device_get_device_id);
|
||||||
|
g_test_add_func ("/device/sync/get_name", test_device_get_name);
|
||||||
|
g_test_add_func ("/device/sync/get_scan_type", test_device_get_scan_type);
|
||||||
|
g_test_add_func ("/device/sync/get_nr_enroll_stages", test_device_get_nr_enroll_stages);
|
||||||
|
g_test_add_func ("/device/sync/supports_identify", test_device_supports_identify);
|
||||||
|
g_test_add_func ("/device/sync/supports_capture", test_device_supports_capture);
|
||||||
|
g_test_add_func ("/device/sync/has_storage", test_device_has_storage);
|
||||||
|
|
||||||
|
return g_test_run ();
|
||||||
|
}
|
||||||
1411
tests/test-fpi-device.c
Normal file
1411
tests/test-fpi-device.c
Normal file
File diff suppressed because it is too large
Load Diff
1396
tests/test-fpi-ssm.c
Normal file
1396
tests/test-fpi-ssm.c
Normal file
File diff suppressed because it is too large
Load Diff
3
tests/test-runner.sh
Executable file
3
tests/test-runner.sh
Executable file
@@ -0,0 +1,3 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
exec $LIBFPRINT_TEST_WRAPPER $@
|
||||||
127
tests/test-utils.c
Normal file
127
tests/test-utils.c
Normal file
@@ -0,0 +1,127 @@
|
|||||||
|
/*
|
||||||
|
* Unit tests for libfprint
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <libfprint/fprint.h>
|
||||||
|
#include <glib/gstdio.h>
|
||||||
|
|
||||||
|
#include "test-utils.h"
|
||||||
|
|
||||||
|
void
|
||||||
|
fpt_teardown_virtual_device_environment (void)
|
||||||
|
{
|
||||||
|
const char *path = g_getenv ("FP_VIRTUAL_IMAGE");
|
||||||
|
|
||||||
|
if (path)
|
||||||
|
{
|
||||||
|
g_autofree char *temp_dir = g_path_get_dirname (path);
|
||||||
|
|
||||||
|
g_unsetenv ("FP_VIRTUAL_IMAGE");
|
||||||
|
g_unlink (path);
|
||||||
|
g_rmdir (temp_dir);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_signal_event (int sig)
|
||||||
|
{
|
||||||
|
fpt_teardown_virtual_device_environment ();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
fpt_setup_virtual_device_environment (void)
|
||||||
|
{
|
||||||
|
g_autoptr(GError) error = NULL;
|
||||||
|
g_autofree char *temp_dir = NULL;
|
||||||
|
g_autofree char *temp_path = NULL;
|
||||||
|
|
||||||
|
g_assert_null (g_getenv ("FP_VIRTUAL_IMAGE"));
|
||||||
|
|
||||||
|
temp_dir = g_dir_make_tmp ("libfprint-XXXXXX", &error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
|
||||||
|
temp_path = g_build_filename (temp_dir, "virtual-image.socket", NULL);
|
||||||
|
g_setenv ("FP_VIRTUAL_IMAGE", temp_path, TRUE);
|
||||||
|
|
||||||
|
signal (SIGKILL, on_signal_event);
|
||||||
|
signal (SIGABRT, on_signal_event);
|
||||||
|
signal (SIGSEGV, on_signal_event);
|
||||||
|
signal (SIGTERM, on_signal_event);
|
||||||
|
signal (SIGQUIT, on_signal_event);
|
||||||
|
signal (SIGPIPE, on_signal_event);
|
||||||
|
}
|
||||||
|
|
||||||
|
FptContext *
|
||||||
|
fpt_context_new (void)
|
||||||
|
{
|
||||||
|
FptContext *tctx;
|
||||||
|
|
||||||
|
tctx = g_new0 (FptContext, 1);
|
||||||
|
tctx->fp_context = fp_context_new ();
|
||||||
|
|
||||||
|
return tctx;
|
||||||
|
}
|
||||||
|
|
||||||
|
FptContext *
|
||||||
|
fpt_context_new_with_virtual_imgdev (void)
|
||||||
|
{
|
||||||
|
FptContext *tctx;
|
||||||
|
GPtrArray *devices;
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
fpt_setup_virtual_device_environment ();
|
||||||
|
|
||||||
|
tctx = fpt_context_new ();
|
||||||
|
devices = fp_context_get_devices (tctx->fp_context);
|
||||||
|
|
||||||
|
g_assert_nonnull (devices);
|
||||||
|
g_assert_cmpuint (devices->len, ==, 1);
|
||||||
|
|
||||||
|
for (i = 0; i < devices->len; ++i)
|
||||||
|
{
|
||||||
|
FpDevice *device = devices->pdata[i];
|
||||||
|
|
||||||
|
if (g_strcmp0 (fp_device_get_driver (device), "virtual_image") == 0)
|
||||||
|
{
|
||||||
|
tctx->device = device;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
g_assert_true (FP_IS_DEVICE (tctx->device));
|
||||||
|
g_object_add_weak_pointer (G_OBJECT (tctx->device), (gpointer) & tctx->device);
|
||||||
|
|
||||||
|
return tctx;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
fpt_context_free (FptContext *tctx)
|
||||||
|
{
|
||||||
|
if (tctx->device && fp_device_is_open (tctx->device))
|
||||||
|
{
|
||||||
|
g_autoptr(GError) error = NULL;
|
||||||
|
|
||||||
|
fp_device_close_sync (tctx->device, NULL, &error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_clear_object (&tctx->fp_context);
|
||||||
|
g_free (tctx);
|
||||||
|
|
||||||
|
fpt_teardown_virtual_device_environment ();
|
||||||
|
}
|
||||||
37
tests/test-utils.h
Normal file
37
tests/test-utils.h
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
* Unit tests for libfprint
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
|
||||||
|
void fpt_setup_virtual_device_environment (void);
|
||||||
|
void fpt_teardown_virtual_device_environment (void);
|
||||||
|
|
||||||
|
typedef struct _FptContext
|
||||||
|
{
|
||||||
|
FpContext *fp_context;
|
||||||
|
FpDevice *device;
|
||||||
|
gpointer user_data;
|
||||||
|
} FptContext;
|
||||||
|
|
||||||
|
FptContext * fpt_context_new (void);
|
||||||
|
FptContext * fpt_context_new_with_virtual_imgdev (void);
|
||||||
|
|
||||||
|
void fpt_context_free (FptContext *test_context);
|
||||||
|
|
||||||
|
G_DEFINE_AUTOPTR_CLEANUP_FUNC (FptContext, fpt_context_free)
|
||||||
@@ -24,20 +24,6 @@ if wrapper:
|
|||||||
os.unsetenv('LIBFPRINT_TEST_WRAPPER')
|
os.unsetenv('LIBFPRINT_TEST_WRAPPER')
|
||||||
sys.exit(subprocess.check_call(wrap_cmd))
|
sys.exit(subprocess.check_call(wrap_cmd))
|
||||||
|
|
||||||
class Connection:
|
|
||||||
|
|
||||||
def __init__(self, addr):
|
|
||||||
self.addr = addr
|
|
||||||
|
|
||||||
def __enter__(self):
|
|
||||||
self.con = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
|
|
||||||
self.con.connect(self.addr)
|
|
||||||
return self.con
|
|
||||||
|
|
||||||
def __exit__(self, exc_type, exc_val, exc_tb):
|
|
||||||
self.con.close()
|
|
||||||
del self.con
|
|
||||||
|
|
||||||
def load_image(img):
|
def load_image(img):
|
||||||
png = cairo.ImageSurface.create_from_png(img)
|
png = cairo.ImageSurface.create_from_png(img)
|
||||||
|
|
||||||
@@ -97,20 +83,47 @@ class VirtualImage(unittest.TestCase):
|
|||||||
@classmethod
|
@classmethod
|
||||||
def tearDownClass(cls):
|
def tearDownClass(cls):
|
||||||
shutil.rmtree(cls.tmpdir)
|
shutil.rmtree(cls.tmpdir)
|
||||||
|
del cls.dev
|
||||||
|
del cls.ctx
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.dev.open_sync()
|
self.dev.open_sync()
|
||||||
|
|
||||||
|
self.con = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
|
||||||
|
self.con.connect(self.sockaddr)
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
|
self.con.close()
|
||||||
|
del self.con
|
||||||
self.dev.close_sync()
|
self.dev.close_sync()
|
||||||
|
|
||||||
def report_finger(self, state):
|
def send_retry(self, retry_error=1, iterate=True):
|
||||||
with Connection(self.sockaddr) as con:
|
# The default (1) is too-short
|
||||||
con.write(struct.pack('ii', -1, 1 if state else 0))
|
self.sendall(struct.pack('ii', -1, retry_error))
|
||||||
|
while iterate and ctx.pending():
|
||||||
|
ctx.iteration(False)
|
||||||
|
|
||||||
def send_image(self, image):
|
def send_error(self, device_error=0, iterate=True):
|
||||||
|
# The default (0) is a generic error
|
||||||
|
self.sendall(struct.pack('ii', -1, retry_error))
|
||||||
|
while iterate and ctx.pending():
|
||||||
|
ctx.iteration(False)
|
||||||
|
|
||||||
|
def send_finger_automatic(self, automatic, iterate=True):
|
||||||
|
# Set whether finger on/off is reported around images
|
||||||
|
self.con.sendall(struct.pack('ii', -3, 1 if automatic else 0))
|
||||||
|
while iterate and ctx.pending():
|
||||||
|
ctx.iteration(False)
|
||||||
|
|
||||||
|
def send_finger_report(self, has_finger, iterate=True):
|
||||||
|
# Send finger on/off
|
||||||
|
self.con.sendall(struct.pack('ii', -4, 1 if has_finger else 0))
|
||||||
|
while iterate and ctx.pending():
|
||||||
|
ctx.iteration(False)
|
||||||
|
|
||||||
|
def send_image(self, image, iterate=True):
|
||||||
img = self.prints[image]
|
img = self.prints[image]
|
||||||
with Connection(self.sockaddr) as con:
|
|
||||||
mem = img.get_data()
|
mem = img.get_data()
|
||||||
mem = mem.tobytes()
|
mem = mem.tobytes()
|
||||||
assert len(mem) == img.get_width() * img.get_height()
|
assert len(mem) == img.get_width() * img.get_height()
|
||||||
@@ -118,7 +131,9 @@ class VirtualImage(unittest.TestCase):
|
|||||||
encoded_img = struct.pack('ii', img.get_width(), img.get_height())
|
encoded_img = struct.pack('ii', img.get_width(), img.get_height())
|
||||||
encoded_img += mem
|
encoded_img += mem
|
||||||
|
|
||||||
con.sendall(encoded_img)
|
self.con.sendall(encoded_img)
|
||||||
|
while iterate and ctx.pending():
|
||||||
|
ctx.iteration(False)
|
||||||
|
|
||||||
def test_capture_prevents_close(self):
|
def test_capture_prevents_close(self):
|
||||||
cancel = Gio.Cancellable()
|
cancel = Gio.Cancellable()
|
||||||
@@ -169,10 +184,16 @@ class VirtualImage(unittest.TestCase):
|
|||||||
while self._step < 1:
|
while self._step < 1:
|
||||||
ctx.iteration(True)
|
ctx.iteration(True)
|
||||||
|
|
||||||
|
# Test the image-device path where the finger is removed after
|
||||||
|
# the minutiae scan is completed.
|
||||||
|
self.send_finger_automatic(False)
|
||||||
|
self.send_finger_report(True)
|
||||||
self.send_image(image)
|
self.send_image(image)
|
||||||
while self._step < 2:
|
while self._step < 2:
|
||||||
ctx.iteration(True)
|
ctx.iteration(True)
|
||||||
|
self.send_finger_report(False)
|
||||||
|
|
||||||
|
self.send_finger_automatic(True)
|
||||||
self.send_image(image)
|
self.send_image(image)
|
||||||
while self._step < 3:
|
while self._step < 3:
|
||||||
ctx.iteration(True)
|
ctx.iteration(True)
|
||||||
|
|||||||
Reference in New Issue
Block a user