mirror of
https://gitlab.freedesktop.org/libfprint/libfprint.git
synced 2026-09-09 12:46:50 +00:00
Compare commits
126
Commits
+2
-2
@@ -68,8 +68,8 @@ def build_install(revision):
|
||||
subprocess.check_call(['meson', build_dir,
|
||||
'--prefix=/usr', '--libdir=lib',
|
||||
'-Dx11-examples=false', '-Ddoc=false', '-Dgtk-examples=false'])
|
||||
subprocess.check_call(['ninja', '-v', '-C', build_dir])
|
||||
subprocess.check_call(['ninja', '-v', '-C', build_dir, 'install'],
|
||||
subprocess.check_call(['meson', 'compile', '-v', '-C', build_dir])
|
||||
subprocess.check_call(['meson', 'install', '-v', '-C', build_dir],
|
||||
env={'DESTDIR': dest_dir})
|
||||
|
||||
return dest_dir
|
||||
|
||||
+98
-4
@@ -23,6 +23,7 @@ variables:
|
||||
FDO_DISTRIBUTION_VERSION: rawhide
|
||||
FDO_UPSTREAM_REPO: "libfprint/$CI_PROJECT_NAME"
|
||||
FEDORA_IMAGE: "registry.freedesktop.org/libfprint/$CI_PROJECT_NAME/fedora/$FDO_DISTRIBUTION_VERSION:$FDO_DISTRIBUTION_TAG"
|
||||
FEDORA_IMAGE_S390X: "registry.freedesktop.org/libfprint/$CI_PROJECT_NAME/fedora/$FDO_DISTRIBUTION_VERSION-s390x:$LIBFPRINT_IMAGE_TAG"
|
||||
LAST_ABI_BREAK: "056ea541ddc97f5806cffbd99a12dc87e4da3546"
|
||||
|
||||
workflow:
|
||||
@@ -89,7 +90,8 @@ test:
|
||||
script:
|
||||
- meson setup _build --werror -Ddrivers=all -Db_coverage=true
|
||||
- meson test -C _build --print-errorlogs --no-stdsplit --timeout-multiplier 3
|
||||
- ninja -C _build coverage || true
|
||||
# We can't use `meson compile` https://github.com/mesonbuild/meson/issues/7895
|
||||
- ninja -C _build coverage
|
||||
- cat _build/meson-logs/coverage.txt || true
|
||||
artifacts:
|
||||
reports:
|
||||
@@ -199,8 +201,11 @@ test_unsupported_list:
|
||||
extends:
|
||||
- .standard_job
|
||||
allow_failure: true
|
||||
variables:
|
||||
FPRINT_HWDB_LIST: libfprint/fprint-list-udev-hwdb.c
|
||||
script:
|
||||
- tests/hwdb-check-unsupported.py
|
||||
- scripts/sync-unsupported-devices.py $FPRINT_HWDB_LIST
|
||||
- git diff --color=always --exit-code $FPRINT_HWDB_LIST
|
||||
|
||||
flatpak:
|
||||
stage: flatpak
|
||||
@@ -271,8 +276,7 @@ container_fedora_build_manual:
|
||||
- if: $LIBFPRINT_CI_ACTION == "build-image"
|
||||
when: always
|
||||
|
||||
container_fedora_build_on_deps_changed:
|
||||
extends: .container_fedora_build_base
|
||||
.container_fedora_build_on_deps_changed_rules:
|
||||
rules:
|
||||
- if: $CI_PROJECT_NAMESPACE == "libfprint" && $CI_PIPELINE_SOURCE != "schedule"
|
||||
changes:
|
||||
@@ -281,6 +285,96 @@ container_fedora_build_on_deps_changed:
|
||||
- '.gitlab-ci/libfprint-image-variables.yaml'
|
||||
- '.gitlab-ci/libfprint-templates.yaml'
|
||||
|
||||
container_fedora_build_on_deps_changed:
|
||||
extends:
|
||||
- .container_fedora_build_base
|
||||
- .container_fedora_build_on_deps_changed_rules
|
||||
|
||||
.container_fedora_image_build_base_s390x:
|
||||
stage: image-build
|
||||
image: quay.io/freedesktop.org/ci-templates:container-build-base-2026-05-19.0
|
||||
variables:
|
||||
GIT_STRATEGY: none
|
||||
S390X_TAG: $LIBFPRINT_IMAGE_TAG-s390x
|
||||
STORAGE_DRIVER: vfs
|
||||
script:
|
||||
- |
|
||||
if [ -z "${FDO_FORCE_REBUILD:-}" ]; then
|
||||
if skopeo inspect --no-tags --retry-times 3 "docker://$FEDORA_IMAGE_S390X" 2>/dev/null; then
|
||||
echo "Image $FEDORA_IMAGE_S390X already exists, skipping build."
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
|
||||
- buildah from --name s390x-container --platform linux/s390x
|
||||
registry.fedoraproject.org/fedora:$FDO_DISTRIBUTION_VERSION
|
||||
- ROOTFS=$(buildah mount s390x-container)
|
||||
- dnf install -y --installroot=$ROOTFS --forcearch=s390x
|
||||
--use-host-config
|
||||
--setopt=tsflags=noscripts --releasever=$FDO_DISTRIBUTION_VERSION
|
||||
--setopt=install_weak_deps=False
|
||||
$LIBFPRINT_DEPENDENCIES
|
||||
|
||||
- dnf clean all --installroot=$ROOTFS || true
|
||||
- buildah commit s390x-container "$FEDORA_IMAGE_S390X"
|
||||
- podman login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
|
||||
- buildah push "$FEDORA_IMAGE_S390X"
|
||||
|
||||
container_fedora_build_schedule_s390x:
|
||||
extends:
|
||||
- .container_fedora_image_build_base_s390x
|
||||
- .container_fedora_build_forced
|
||||
rules:
|
||||
- if: $CI_PIPELINE_SOURCE == "schedule" && $CRON_TASK == "BUILD_CI_IMAGES"
|
||||
when: always
|
||||
|
||||
container_fedora_build_manual_s390x:
|
||||
extends:
|
||||
- .container_fedora_image_build_base_s390x
|
||||
- .container_fedora_build_forced
|
||||
rules:
|
||||
- if: $LIBFPRINT_CI_ACTION == "build-image"
|
||||
when: always
|
||||
|
||||
container_fedora_build_on_deps_changed_s390x:
|
||||
extends:
|
||||
- .container_fedora_image_build_base_s390x
|
||||
- .container_fedora_build_on_deps_changed_rules
|
||||
|
||||
test_s390x:
|
||||
stage: test
|
||||
allow_failure: true
|
||||
needs:
|
||||
- job: container_fedora_build_manual_s390x
|
||||
optional: true
|
||||
variables:
|
||||
STORAGE_DRIVER: vfs
|
||||
QEMU_CPU: max
|
||||
before_script:
|
||||
# The s390x binaries are executed via the qemu-s390x-static registered in
|
||||
# the *host* kernel's binfmt_misc. Use $FEDORA_IMAGE qemu-user-static
|
||||
# (and systemd-binfmt), and run it privileged to re-register its handlers
|
||||
# and make every run use the same emulator.
|
||||
- podman run --rm --privileged
|
||||
--security-opt label=filetype:container_file_t
|
||||
--security-opt label=level:s0
|
||||
--security-opt label=type:spc_t
|
||||
-v $CI_PROJECT_DIR/.gitlab-ci/qemu-user-static/container-entrypoint:/container-entrypoint:z
|
||||
$FEDORA_IMAGE /container-entrypoint
|
||||
script:
|
||||
- podman run --rm --platform linux/s390x -e QEMU_CPU -v $CI_PROJECT_DIR:/build:z -w /build "$FEDORA_IMAGE_S390X" /bin/bash -c \
|
||||
"meson setup _build --werror -Ddrivers=all && meson test -C _build --print-errorlogs --no-stdsplit --timeout-multiplier 4 --suite=drivers --suite=virtual-driver"
|
||||
artifacts:
|
||||
when: always
|
||||
paths:
|
||||
- _build/meson-logs/
|
||||
reports:
|
||||
junit: "_build/meson-logs/testlog.junit.xml"
|
||||
rules:
|
||||
- if: $LIBFPRINT_CI_ACTION == "test-s390x"
|
||||
when: always
|
||||
- when: manual
|
||||
|
||||
pages:
|
||||
image: alpine:latest
|
||||
stage: deploy
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
variables:
|
||||
LIBFPRINT_IMAGE_TAG: v6
|
||||
LIBFPRINT_IMAGE_TAG: v8
|
||||
|
||||
@@ -27,6 +27,8 @@
|
||||
meson
|
||||
openssl-devel
|
||||
pixman-devel
|
||||
podman
|
||||
qemu-user-static
|
||||
python3-cairo
|
||||
python3-gobject
|
||||
systemd
|
||||
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Unregister any stale qemu-*-static binfmt handlers and (re-)register the ones
|
||||
# shipped by this image via systemd-binfmt, so the host always uses the recent
|
||||
# qemu-user-static built into this image (registered with the "F" fix-binary
|
||||
# flag from /usr/lib/binfmt.d).
|
||||
#
|
||||
# Based on https://www.itix.fr/blog/qemu-user-static-with-podman/
|
||||
|
||||
set -Eeuo pipefail
|
||||
|
||||
if [ ! -d /proc/sys/fs/binfmt_misc ]; then
|
||||
echo "No binfmt support in the kernel."
|
||||
echo " Try: '/sbin/modprobe binfmt_misc' from the host"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -f /proc/sys/fs/binfmt_misc/register ]; then
|
||||
echo "Mounting /proc/sys/fs/binfmt_misc..."
|
||||
mount binfmt_misc -t binfmt_misc /proc/sys/fs/binfmt_misc
|
||||
fi
|
||||
|
||||
echo "Cleaning up..."
|
||||
find /proc/sys/fs/binfmt_misc -type f -name 'qemu-*' -exec sh -c 'echo -1 > {}' \;
|
||||
|
||||
echo "Registering..."
|
||||
exec /usr/lib/systemd/systemd-binfmt
|
||||
@@ -1,6 +1,30 @@
|
||||
This file lists notable changes in each release. For the full history of all
|
||||
changes, see ChangeLog.
|
||||
|
||||
2026-07-25: v1.94.100 release
|
||||
|
||||
Highlights:
|
||||
* bump meson dependency to 0.62
|
||||
* egis_etu905: New driver supporting PIDs 0x05AE and 0x9201
|
||||
* synaptics: New PIDs 0x010D, 0x010E and 0x01A4
|
||||
* goodixmoc: Support 27c6:6382, 27c6:6984 and 27c6:6090
|
||||
* nb1010: Support the NB-2020-U fingerprint reader
|
||||
* focaltech_moc: New PID 0xA97A
|
||||
* elanmoc: New PID 0x0CB2
|
||||
* fpcmoc: New PID 0x9B24
|
||||
* aes2550: Handle tapping without swiping and fix deactivation after errors
|
||||
* fp-device: Implement verify using identification, improving driver
|
||||
consistency and reducing duplicated driver code
|
||||
* fpcmoc, egis_etu905, elan, elanspi, goodixmoc and mafpmoc: Improve
|
||||
big-endian support
|
||||
* goodixmoc: Fix malformed payload, CRC and invalid finger handling
|
||||
* synaptics, realtek, vfs101, vfs301, upekts, elan and egismoc: Fix
|
||||
memory safety, bounds checking and error handling issues
|
||||
* aes1610, aes2510, aesx660, fpcmoc and uru4000: Fix resource leaks and
|
||||
cancellation or device deactivation issues
|
||||
* Expanded USB replay coverage for aes2550 and egis_etu905, and improved
|
||||
virtual-image testing with transformed fingerprint images
|
||||
|
||||
2026-02-10: v1.94.10 release
|
||||
|
||||
Highlights:
|
||||
|
||||
+51
-9
@@ -176,6 +176,7 @@ usb:v04F3p0CA7*
|
||||
usb:v04F3p0CA8*
|
||||
usb:v04F3p0CB0*
|
||||
usb:v04F3p0CB2*
|
||||
usb:v04F3p0CB6*
|
||||
ID_AUTOSUSPEND=1
|
||||
ID_PERSIST=0
|
||||
|
||||
@@ -218,6 +219,7 @@ usb:v10A5p9B24*
|
||||
# Supported by libfprint driver goodixmoc
|
||||
usb:v27C6p5840*
|
||||
usb:v27C6p6014*
|
||||
usb:v27C6p6082*
|
||||
usb:v27C6p6090*
|
||||
usb:v27C6p6092*
|
||||
usb:v27C6p6094*
|
||||
@@ -231,6 +233,7 @@ usb:v27C6p6304*
|
||||
usb:v27C6p631C*
|
||||
usb:v27C6p633C*
|
||||
usb:v27C6p634C*
|
||||
usb:v27C6p6382*
|
||||
usb:v27C6p6384*
|
||||
usb:v27C6p639C*
|
||||
usb:v27C6p63AC*
|
||||
@@ -252,6 +255,10 @@ usb:v27C6p6890*
|
||||
usb:v27C6p689A*
|
||||
usb:v27C6p66A9*
|
||||
usb:v27C6p6984*
|
||||
usb:v27C6p65BA*
|
||||
usb:v27C6p6515*
|
||||
usb:v27C6p66AC*
|
||||
usb:v27C6p660A*
|
||||
ID_AUTOSUSPEND=1
|
||||
ID_PERSIST=0
|
||||
|
||||
@@ -262,6 +269,7 @@ usb:v3274p8012*
|
||||
|
||||
# Supported by libfprint driver nb1010
|
||||
usb:v298Dp1010*
|
||||
usb:v298Dp2020*
|
||||
ID_AUTOSUSPEND=1
|
||||
ID_PERSIST=0
|
||||
|
||||
@@ -296,6 +304,9 @@ usb:v06CBp0107*
|
||||
usb:v06CBp0108*
|
||||
usb:v06CBp0109*
|
||||
usb:v06CBp010A*
|
||||
usb:v06CBp010B*
|
||||
usb:v06CBp010D*
|
||||
usb:v06CBp010E*
|
||||
usb:v06CBp0123*
|
||||
usb:v06CBp0124*
|
||||
usb:v06CBp0126*
|
||||
@@ -378,17 +389,20 @@ usb:v138Ap0091*
|
||||
ID_PERSIST=0
|
||||
|
||||
# Known unsupported devices
|
||||
usb:v0A5Cp5802*
|
||||
usb:v006Bp00DA*
|
||||
usb:v0413p2766*
|
||||
usb:v045Ep0815*
|
||||
usb:v047Dp00F2*
|
||||
usb:v047Dp8054*
|
||||
usb:v047Dp8055*
|
||||
usb:v04E8p730B*
|
||||
usb:v04F2pB61E*
|
||||
usb:v04F3p036B*
|
||||
usb:v04F3p0C00*
|
||||
usb:v04F3p0C4C*
|
||||
usb:v04F3p0C57*
|
||||
usb:v04F3p0C5E*
|
||||
usb:v04F3p0C5A*
|
||||
usb:v04F3p0C5E*
|
||||
usb:v04F3p0C60*
|
||||
usb:v04F3p0C6C*
|
||||
usb:v04F3p0C70*
|
||||
@@ -398,15 +412,28 @@ usb:v04F3p0C7C*
|
||||
usb:v04F3p0C7F*
|
||||
usb:v04F3p0C80*
|
||||
usb:v04F3p0C85*
|
||||
usb:v04F3p0C8A*
|
||||
usb:v04F3p0C8E*
|
||||
usb:v04F3p0C90*
|
||||
usb:v04F3p0CA2*
|
||||
usb:v04F3p24CC*
|
||||
usb:v04F3p2706*
|
||||
usb:v04F3p3032*
|
||||
usb:v04F3p3057*
|
||||
usb:v04F3p3058*
|
||||
usb:v04F3p3066*
|
||||
usb:v04F3p3087*
|
||||
usb:v04F3p309F*
|
||||
usb:v04F3p30C6*
|
||||
usb:v04F3p3104*
|
||||
usb:v04F3p310D*
|
||||
usb:v04F3p3128*
|
||||
usb:v04F3p0C8A*
|
||||
usb:v04F3p3195*
|
||||
usb:v04F3p31FC*
|
||||
usb:v04F3p3201*
|
||||
usb:v04F3p3212*
|
||||
usb:v05BAp000E*
|
||||
usb:v05C8p03C0*
|
||||
usb:v06CBp0051*
|
||||
usb:v06CBp0081*
|
||||
usb:v06CBp0088*
|
||||
@@ -420,8 +447,9 @@ usb:v06CBp00B7*
|
||||
usb:v06CBp00BB*
|
||||
usb:v06CBp00BC*
|
||||
usb:v06CBp00BE*
|
||||
usb:v06CBp00CB*
|
||||
usb:v06CBp00C7*
|
||||
usb:v06CBp00C9*
|
||||
usb:v06CBp00CB*
|
||||
usb:v06CBp00D8*
|
||||
usb:v06CBp00DA*
|
||||
usb:v06CBp00DC*
|
||||
@@ -429,7 +457,12 @@ usb:v06CBp00E4*
|
||||
usb:v06CBp00E7*
|
||||
usb:v06CBp00FD*
|
||||
usb:v06CBp00FF*
|
||||
usb:v06CBp0102*
|
||||
usb:v06CBpCE67*
|
||||
usb:v06CBpCEEF*
|
||||
usb:v08FFp3400*
|
||||
usb:v0A5Cp5801*
|
||||
usb:v0A5Cp5802*
|
||||
usb:v0A5Cp5805*
|
||||
usb:v0A5Cp5834*
|
||||
usb:v0A5Cp5840*
|
||||
@@ -444,6 +477,7 @@ usb:v0A5Cp5864*
|
||||
usb:v0A5Cp5865*
|
||||
usb:v0A5Cp5866*
|
||||
usb:v0A5Cp5867*
|
||||
usb:v0BDAp0129*
|
||||
usb:v0BDAp5812*
|
||||
usb:v10A5p0007*
|
||||
usb:v10A5p9200*
|
||||
@@ -454,6 +488,7 @@ usb:v10A5pA900*
|
||||
usb:v10A5pA921*
|
||||
usb:v10A5pE340*
|
||||
usb:v1188p9545*
|
||||
usb:v138Ap0006*
|
||||
usb:v138Ap0007*
|
||||
usb:v138Ap003A*
|
||||
usb:v138Ap003C*
|
||||
@@ -464,8 +499,8 @@ usb:v138Ap0092*
|
||||
usb:v138Ap0094*
|
||||
usb:v138Ap0097*
|
||||
usb:v138Ap009D*
|
||||
usb:v138Ap00AB*
|
||||
usb:v138Ap00A6*
|
||||
usb:v138Ap00AB*
|
||||
usb:v147Ep1002*
|
||||
usb:v1491p0088*
|
||||
usb:v16D1p1027*
|
||||
@@ -474,6 +509,9 @@ usb:v1C7Ap0575*
|
||||
usb:v1C7Ap0576*
|
||||
usb:v1C7Ap0577*
|
||||
usb:v1C7Ap057E*
|
||||
usb:v1C7Ap05A5*
|
||||
usb:v1C7Ap05AA*
|
||||
usb:v1C7Ap0801*
|
||||
usb:v2541p0236*
|
||||
usb:v2541p9711*
|
||||
usb:v27C6p5042*
|
||||
@@ -501,21 +539,25 @@ usb:v27C6p55A2*
|
||||
usb:v27C6p55A4*
|
||||
usb:v27C6p55B4*
|
||||
usb:v27C6p5740*
|
||||
usb:v27C6p5E0A*
|
||||
usb:v27C6p581A*
|
||||
usb:v27C6p589A*
|
||||
usb:v27C6p5E0A*
|
||||
usb:v27C6p5F10*
|
||||
usb:v27C6p5F91*
|
||||
usb:v27C6p6382*
|
||||
usb:v2808p06FC*
|
||||
usb:v2808p6652*
|
||||
usb:v2808p9338*
|
||||
usb:v2808p9348*
|
||||
usb:v2808p93A9*
|
||||
usb:v2808pA553*
|
||||
usb:v2808pA573*
|
||||
usb:v2808pA658*
|
||||
usb:v2808pC652*
|
||||
usb:v2808pA553*
|
||||
usb:v298Dp2020*
|
||||
usb:v298Dp2033*
|
||||
usb:v2DF0p0003*
|
||||
usb:v3274p9008*
|
||||
usb:v3274pB012*
|
||||
usb:v33A7p2388*
|
||||
usb:v3538p0930*
|
||||
ID_AUTOSUSPEND=1
|
||||
ID_PERSIST=0
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
if udev_hwdb_dir != ''
|
||||
# This file has to be updated using
|
||||
# ninja -C <builddir> libfprint/sync-udev-hwdb
|
||||
# meson compile -C <builddir> sync-udev-hwdb
|
||||
# Note that the unsupported device list needs to be manually synced from
|
||||
# the wiki. See comment in libfprint/fprint-list-uev-hwdb.c
|
||||
|
||||
|
||||
@@ -791,7 +791,7 @@ complete_deactivation (FpImageDevice *dev)
|
||||
* maybe we can do this with a master reset, unconditionally? */
|
||||
|
||||
self->deactivating = FALSE;
|
||||
g_slist_free (self->strips);
|
||||
g_slist_free_full (self->strips, g_free);
|
||||
self->strips = NULL;
|
||||
self->strips_len = 0;
|
||||
self->blanks_count = 0;
|
||||
|
||||
@@ -213,9 +213,8 @@ sum_histogram_values (unsigned char *data, guint8 threshold)
|
||||
if (threshold > 0x0f)
|
||||
return -1;
|
||||
|
||||
/* FIXME endianness */
|
||||
for (i = threshold; i < 16; i++)
|
||||
r += histogram[i];
|
||||
r += GUINT16_FROM_LE (histogram[i]);
|
||||
|
||||
return r;
|
||||
}
|
||||
@@ -823,7 +822,7 @@ complete_deactivation (FpImageDevice *dev)
|
||||
* maybe we can do this with a master reset, unconditionally? */
|
||||
|
||||
self->deactivating = FALSE;
|
||||
g_slist_free (self->strips);
|
||||
g_slist_free_full (self->strips, g_free);
|
||||
self->strips = NULL;
|
||||
self->strips_len = 0;
|
||||
fpi_image_device_deactivate_complete (dev, NULL);
|
||||
|
||||
@@ -57,6 +57,7 @@ struct _FpiDeviceAes2550
|
||||
|
||||
GSList *strips;
|
||||
size_t strips_len;
|
||||
gboolean active;
|
||||
gboolean deactivating;
|
||||
int heartbeat_cnt;
|
||||
};
|
||||
@@ -91,11 +92,21 @@ finger_det_data_cb (FpiUsbTransfer *transfer, FpDevice *device,
|
||||
gpointer user_data, GError *error)
|
||||
{
|
||||
FpImageDevice *dev = FP_IMAGE_DEVICE (device);
|
||||
FpiDeviceAes2550 *self = FPI_DEVICE_AES2550 (device);
|
||||
unsigned char *data = transfer->buffer;
|
||||
|
||||
if (error)
|
||||
{
|
||||
fpi_image_device_session_error (FP_IMAGE_DEVICE (device), error);
|
||||
/* The finger-detect loop is broken; it no longer has a pending
|
||||
* operation. Clear the active flag so that the deactivation
|
||||
* triggered by the session error (or an in-flight cancellation)
|
||||
* can complete. */
|
||||
self->active = FALSE;
|
||||
|
||||
if (self->deactivating)
|
||||
complete_deactivation (dev);
|
||||
else
|
||||
fpi_image_device_session_error (dev, error);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -122,10 +133,20 @@ finger_det_reqs_cb (FpiUsbTransfer *t, FpDevice *device,
|
||||
{
|
||||
FpiUsbTransfer *transfer;
|
||||
FpImageDevice *dev = FP_IMAGE_DEVICE (device);
|
||||
FpiDeviceAes2550 *self = FPI_DEVICE_AES2550 (device);
|
||||
|
||||
if (error)
|
||||
{
|
||||
fpi_image_device_session_error (dev, error);
|
||||
/* The finger-detect loop is broken; it no longer has a pending
|
||||
* operation. Clear the active flag so that the deactivation
|
||||
* triggered by the session error (or an in-flight cancellation)
|
||||
* can complete. */
|
||||
self->active = FALSE;
|
||||
|
||||
if (self->deactivating)
|
||||
complete_deactivation (dev);
|
||||
else
|
||||
fpi_image_device_session_error (dev, error);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -239,13 +260,19 @@ capture_set_idle_reqs_cb (FpiUsbTransfer *transfer,
|
||||
/* marking machine complete will re-trigger finger detection loop */
|
||||
fpi_ssm_mark_completed (transfer->ssm);
|
||||
}
|
||||
else if (!error)
|
||||
{
|
||||
/* No image frames were captured (e.g. user tapped without swiping).
|
||||
* Such case is quite easy to happen, since Super RSR is enabled and
|
||||
* thus "Slices with 0-3 pixels of Y motion are discarded" according
|
||||
* to the design specification manual. */
|
||||
fpi_image_device_retry_scan (dev, FP_DEVICE_RETRY_TOO_SHORT);
|
||||
fpi_image_device_report_finger_status (dev, FALSE);
|
||||
fpi_ssm_mark_completed (transfer->ssm);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (error)
|
||||
fpi_ssm_mark_failed (transfer->ssm, error);
|
||||
else
|
||||
fpi_ssm_mark_failed (transfer->ssm,
|
||||
fpi_device_error_new (FP_DEVICE_ERROR_PROTO));
|
||||
fpi_ssm_mark_failed (transfer->ssm, error);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -371,6 +398,11 @@ capture_sm_complete (FpiSsm *ssm, FpDevice *_dev, GError *error)
|
||||
}
|
||||
else if (error)
|
||||
{
|
||||
/* The capture SSM has terminated, so no completion handler is left
|
||||
* to observe the deactivation that the session error triggers.
|
||||
* Clear the active flag so dev_deactivate() completes it directly.
|
||||
*/
|
||||
self->active = FALSE;
|
||||
fpi_image_device_session_error (dev, error);
|
||||
}
|
||||
else
|
||||
@@ -489,12 +521,16 @@ activate_run_state (FpiSsm *ssm, FpDevice *dev)
|
||||
static void
|
||||
activate_sm_complete (FpiSsm *ssm, FpDevice *_dev, GError *error)
|
||||
{
|
||||
FpiDeviceAes2550 *self = FPI_DEVICE_AES2550 (_dev);
|
||||
FpImageDevice *dev = FP_IMAGE_DEVICE (_dev);
|
||||
|
||||
fpi_image_device_activate_complete (dev, error);
|
||||
|
||||
if (!error)
|
||||
start_finger_detection (dev);
|
||||
{
|
||||
self->active = TRUE;
|
||||
start_finger_detection (dev);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -511,6 +547,13 @@ dev_deactivate (FpImageDevice *dev)
|
||||
{
|
||||
FpiDeviceAes2550 *self = FPI_DEVICE_AES2550 (dev);
|
||||
|
||||
if (!self->active)
|
||||
{
|
||||
/* No operation is pending, so complete it right away. */
|
||||
complete_deactivation (dev);
|
||||
return;
|
||||
}
|
||||
|
||||
self->deactivating = TRUE;
|
||||
}
|
||||
|
||||
@@ -522,6 +565,7 @@ complete_deactivation (FpImageDevice *dev)
|
||||
G_DEBUG_HERE ();
|
||||
|
||||
self->deactivating = FALSE;
|
||||
self->active = FALSE;
|
||||
g_slist_free (self->strips);
|
||||
self->strips = NULL;
|
||||
self->strips_len = 0;
|
||||
|
||||
@@ -384,6 +384,15 @@ capture_read_stripe_data_cb (FpiUsbTransfer *transfer,
|
||||
|
||||
payload_length = priv->stripe_packet->data[AESX660_RESPONSE_SIZE_LSB_OFFSET] +
|
||||
(priv->stripe_packet->data[AESX660_RESPONSE_SIZE_MSB_OFFSET] << 8);
|
||||
|
||||
if (payload_length > AESX660_BULK_TRANSFER_SIZE)
|
||||
{
|
||||
fp_dbg ("Oversized payload length %" G_GSSIZE_FORMAT ", discarding",
|
||||
payload_length);
|
||||
g_byte_array_set_size (priv->stripe_packet, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
fp_dbg ("Got frame, type %.2x payload of size %.4lx",
|
||||
priv->stripe_packet->data[AESX660_RESPONSE_TYPE_OFFSET],
|
||||
(long) payload_length);
|
||||
@@ -722,7 +731,7 @@ complete_deactivation (FpImageDevice *dev)
|
||||
G_DEBUG_HERE ();
|
||||
|
||||
priv->deactivating = FALSE;
|
||||
g_slist_free (priv->strips);
|
||||
g_slist_free_full (priv->strips, g_free);
|
||||
priv->strips = NULL;
|
||||
priv->strips_len = 0;
|
||||
fpi_image_device_deactivate_complete (dev, NULL);
|
||||
|
||||
@@ -29,12 +29,12 @@
|
||||
|
||||
struct _FpiDeviceEgisEtu905
|
||||
{
|
||||
FpDevice parent;
|
||||
FpiSsm *task_ssm;
|
||||
FpiSsm *cmd_ssm;
|
||||
FpiUsbTransfer *cmd_transfer;
|
||||
GPtrArray *enrolled_ids;
|
||||
gint max_enroll_stages;
|
||||
FpDevice parent;
|
||||
FpiSsm *task_ssm;
|
||||
FpiSsm *identify_cancel_ssm;
|
||||
GPtrArray *enrolled_ids;
|
||||
gint max_enroll_stages;
|
||||
gboolean identify_started; /* TRUE after cmd_sensor_identify is sent */
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (FpiDeviceEgisEtu905, fpi_device_egis_etu905, FP_TYPE_DEVICE);
|
||||
@@ -53,6 +53,8 @@ typedef void (*SynCmdMsgCallback) (FpDevice *device,
|
||||
typedef struct egis_etu905_command_data
|
||||
{
|
||||
SynCmdMsgCallback callback;
|
||||
FpiUsbTransfer *cmd_transfer;
|
||||
GCancellable *cancellable;
|
||||
guchar *buffer_in;
|
||||
gsize length_in;
|
||||
} CommandData;
|
||||
@@ -60,6 +62,8 @@ typedef struct egis_etu905_command_data
|
||||
static void
|
||||
egis_etu905_command_data_free (CommandData *data)
|
||||
{
|
||||
g_clear_pointer (&data->cmd_transfer, fpi_usb_transfer_unref);
|
||||
g_clear_object (&data->cancellable);
|
||||
g_free (data->buffer_in);
|
||||
g_free (data);
|
||||
}
|
||||
@@ -70,6 +74,19 @@ typedef struct egis_etu905_enroll_print
|
||||
int stage;
|
||||
} EnrollPrint;
|
||||
|
||||
static void egis_etu905_exec_cmd_full (FpDevice *device,
|
||||
const guchar *cmd,
|
||||
gsize cmd_length,
|
||||
SynCmdMsgCallback callback,
|
||||
GCancellable *cancellable);
|
||||
|
||||
static void egis_etu905_cancel (FpDevice *device);
|
||||
|
||||
static void egis_etu905_cancel_cb (FpDevice *device,
|
||||
guchar *buffer_in,
|
||||
gsize length_in,
|
||||
GError *error);
|
||||
|
||||
static void
|
||||
egis_etu905_finger_on_sensor_cb (FpiUsbTransfer *transfer,
|
||||
FpDevice *device,
|
||||
@@ -116,7 +133,7 @@ egis_etu905_validate_response_prefix (const guchar *buffer_in,
|
||||
|
||||
fpi_byte_reader_init (&reader, buffer_in, buffer_in_len);
|
||||
|
||||
if (!fpi_byte_reader_set_pos (&reader, egis_etu905_read_prefix_len +
|
||||
if (!fpi_byte_reader_set_pos (&reader, G_N_ELEMENTS (egis_etu905_read_prefix) +
|
||||
EGIS_ETU905_CHECK_BYTES_LENGTH) ||
|
||||
!fpi_byte_reader_get_data (&reader, valid_prefix_len, &data))
|
||||
{
|
||||
@@ -157,23 +174,55 @@ egis_etu905_validate_response_suffix (const guchar *buffer_in,
|
||||
return result;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
egis_etu905_maybe_cancel (FpDevice *device,
|
||||
GError *error)
|
||||
{
|
||||
FpiDeviceAction action = fpi_device_get_current_action (device);
|
||||
|
||||
if (!fpi_device_action_is_cancelled (device) &&
|
||||
!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
||||
return FALSE;
|
||||
|
||||
if (action != FPI_DEVICE_ACTION_ENROLL &&
|
||||
action != FPI_DEVICE_ACTION_IDENTIFY)
|
||||
return FALSE;
|
||||
|
||||
egis_etu905_cancel (device);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
egis_etu905_task_ssm_done (FpiSsm *ssm,
|
||||
FpDevice *device,
|
||||
GError *error)
|
||||
{
|
||||
g_autoptr(GError) task_error = g_steal_pointer (&error);
|
||||
FpiDeviceEgisEtu905 *self = FPI_DEVICE_EGIS_ETU905 (device);
|
||||
gboolean is_cancellation;
|
||||
|
||||
fp_dbg ("Task SSM done");
|
||||
|
||||
/* task_ssm is going to be freed by completion of SSM */
|
||||
g_assert (!self->task_ssm || self->task_ssm == ssm);
|
||||
self->task_ssm = NULL;
|
||||
|
||||
/* Check if this is a cancellation before clearing task_ssm, so we can
|
||||
* distinguish between "identify completed normally" and "identify was
|
||||
* cancelled". The identify_cancel_ssm_done callback needs to know this
|
||||
* to report the correct result. */
|
||||
is_cancellation = egis_etu905_maybe_cancel (device, task_error);
|
||||
|
||||
self->task_ssm = NULL;
|
||||
g_clear_pointer (&self->enrolled_ids, g_ptr_array_unref);
|
||||
|
||||
if (error)
|
||||
fpi_device_action_error (device, error);
|
||||
/* On cancellation we need to send the device-side cancel command before
|
||||
* reporting the error, as the idle ->cancel vfunc may not be called due
|
||||
* to the operation already being completed by the cancellable abort. */
|
||||
if (is_cancellation)
|
||||
return;
|
||||
|
||||
if (task_error)
|
||||
fpi_device_action_error (device, g_steal_pointer (&task_error));
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -227,7 +276,7 @@ egis_etu905_cmd_receive_cb (FpiUsbTransfer *transfer,
|
||||
return;
|
||||
}
|
||||
|
||||
if (transfer->actual_length < egis_etu905_read_prefix_len)
|
||||
if (transfer->actual_length < G_N_ELEMENTS (egis_etu905_read_prefix))
|
||||
{
|
||||
fpi_ssm_mark_failed (transfer->ssm,
|
||||
fpi_device_error_new (FP_DEVICE_ERROR_GENERAL));
|
||||
@@ -248,17 +297,18 @@ egis_etu905_cmd_run_state (FpiSsm *ssm,
|
||||
FpDevice *device)
|
||||
{
|
||||
g_autoptr(FpiUsbTransfer) transfer = NULL;
|
||||
FpiDeviceEgisEtu905 *self = FPI_DEVICE_EGIS_ETU905 (device);
|
||||
CommandData *data = fpi_ssm_get_data (ssm);
|
||||
|
||||
switch (fpi_ssm_get_cur_state (ssm))
|
||||
{
|
||||
case CMD_SEND:
|
||||
if (self->cmd_transfer)
|
||||
if (data->cmd_transfer)
|
||||
{
|
||||
self->cmd_transfer->ssm = ssm;
|
||||
fpi_usb_transfer_submit (g_steal_pointer (&self->cmd_transfer),
|
||||
transfer = g_steal_pointer (&data->cmd_transfer);
|
||||
transfer->ssm = ssm;
|
||||
fpi_usb_transfer_submit (g_steal_pointer (&transfer),
|
||||
EGIS_ETU905_USB_SEND_TIMEOUT,
|
||||
fpi_device_get_cancellable (device),
|
||||
data->cancellable,
|
||||
fpi_ssm_usb_transfer_cb,
|
||||
NULL);
|
||||
break;
|
||||
@@ -274,7 +324,7 @@ egis_etu905_cmd_run_state (FpiSsm *ssm,
|
||||
EGIS_ETU905_USB_IN_RECV_LENGTH);
|
||||
fpi_usb_transfer_submit (g_steal_pointer (&transfer),
|
||||
EGIS_ETU905_USB_RECV_TIMEOUT,
|
||||
fpi_device_get_cancellable (device),
|
||||
data->cancellable,
|
||||
egis_etu905_cmd_receive_cb,
|
||||
fpi_ssm_get_data (ssm));
|
||||
break;
|
||||
@@ -291,15 +341,8 @@ egis_etu905_cmd_ssm_done (FpiSsm *ssm,
|
||||
GError *error)
|
||||
{
|
||||
g_autoptr(GError) local_error = error;
|
||||
FpiDeviceEgisEtu905 *self = FPI_DEVICE_EGIS_ETU905 (device);
|
||||
CommandData *data = fpi_ssm_get_data (ssm);
|
||||
|
||||
g_assert (self->cmd_ssm == ssm);
|
||||
g_assert (!self->cmd_transfer || self->cmd_transfer->ssm == ssm);
|
||||
|
||||
self->cmd_ssm = NULL;
|
||||
self->cmd_transfer = NULL;
|
||||
|
||||
if (data && data->callback)
|
||||
{
|
||||
data->callback (device,
|
||||
@@ -330,15 +373,16 @@ egis_etu905_get_check_bytes (FpiByteReader *reader)
|
||||
}
|
||||
|
||||
static void
|
||||
egis_etu905_exec_cmd (FpDevice *device,
|
||||
const guchar *cmd,
|
||||
const gsize cmd_length,
|
||||
SynCmdMsgCallback callback)
|
||||
egis_etu905_exec_cmd_full (FpDevice *device,
|
||||
const guchar *cmd,
|
||||
const gsize cmd_length,
|
||||
SynCmdMsgCallback callback,
|
||||
GCancellable *cancellable)
|
||||
{
|
||||
g_auto(FpiByteWriter) writer = {0};
|
||||
g_autoptr(FpiUsbTransfer) transfer = NULL;
|
||||
FpiDeviceEgisEtu905 *self = FPI_DEVICE_EGIS_ETU905 (device);
|
||||
g_autofree CommandData *data = NULL;
|
||||
FpiSsm *ssm = NULL;
|
||||
gsize buffer_out_length = 0;
|
||||
gboolean written = TRUE;
|
||||
guint16 check_value;
|
||||
@@ -353,7 +397,7 @@ egis_etu905_exec_cmd (FpDevice *device,
|
||||
* egis_etu905_get_check_bytes() method and payload is what is passed via the cmd
|
||||
* parameter
|
||||
*/
|
||||
buffer_out_length = egis_etu905_write_prefix_len
|
||||
buffer_out_length = G_N_ELEMENTS (egis_etu905_write_prefix)
|
||||
+ EGIS_ETU905_CHECK_BYTES_LENGTH
|
||||
+ cmd_length;
|
||||
|
||||
@@ -362,7 +406,7 @@ egis_etu905_exec_cmd (FpDevice *device,
|
||||
|
||||
/* Prefix */
|
||||
written &= fpi_byte_writer_put_data (&writer, egis_etu905_write_prefix,
|
||||
egis_etu905_write_prefix_len);
|
||||
G_N_ELEMENTS (egis_etu905_write_prefix));
|
||||
|
||||
/* Check Bytes - leave them as 00 for now then later generate and copy over
|
||||
* the real ones */
|
||||
@@ -374,40 +418,49 @@ egis_etu905_exec_cmd (FpDevice *device,
|
||||
/* Now fetch and set the "real" check bytes based on the currently
|
||||
* assembled payload */
|
||||
check_value = egis_etu905_get_check_bytes (FPI_BYTE_READER (&writer));
|
||||
fpi_byte_writer_set_pos (&writer, egis_etu905_write_prefix_len);
|
||||
fpi_byte_writer_set_pos (&writer, G_N_ELEMENTS (egis_etu905_write_prefix));
|
||||
written &= fpi_byte_writer_put_uint16_be (&writer, check_value);
|
||||
|
||||
g_assert (self->cmd_ssm == NULL);
|
||||
self->cmd_ssm = fpi_ssm_new (device,
|
||||
egis_etu905_cmd_run_state,
|
||||
CMD_STATES);
|
||||
|
||||
/* The command runs on its own dedicated SSM, carrying all its state (the
|
||||
* outgoing transfer and the response buffer) via the SSM data. Nothing is
|
||||
* shared on the device instance, so commands issued from different contexts
|
||||
* (e.g. an in-progress operation and a cancellation) cannot collide. */
|
||||
data = g_new0 (CommandData, 1);
|
||||
data->callback = callback;
|
||||
fpi_ssm_set_data (self->cmd_ssm, g_steal_pointer (&data),
|
||||
(GDestroyNotify) egis_etu905_command_data_free);
|
||||
g_set_object (&data->cancellable, cancellable);
|
||||
|
||||
if (!written)
|
||||
if (written)
|
||||
{
|
||||
fpi_ssm_start (self->cmd_ssm, egis_etu905_cmd_ssm_done);
|
||||
fpi_ssm_mark_failed (self->cmd_ssm,
|
||||
fpi_device_error_new (FP_DEVICE_ERROR_PROTO));
|
||||
return;
|
||||
transfer = fpi_usb_transfer_new (device);
|
||||
fpi_usb_transfer_set_short_error (transfer, TRUE);
|
||||
|
||||
fpi_usb_transfer_fill_bulk_full (transfer,
|
||||
EGIS_ETU905_EP_CMD_OUT,
|
||||
fpi_byte_writer_reset_and_get_data (&writer),
|
||||
buffer_out_length,
|
||||
g_free);
|
||||
|
||||
data->cmd_transfer = g_steal_pointer (&transfer);
|
||||
}
|
||||
|
||||
transfer = fpi_usb_transfer_new (device);
|
||||
fpi_usb_transfer_set_short_error (transfer, TRUE);
|
||||
transfer->ssm = self->cmd_ssm;
|
||||
ssm = fpi_ssm_new (device, egis_etu905_cmd_run_state, CMD_STATES);
|
||||
fpi_ssm_set_data (ssm, g_steal_pointer (&data),
|
||||
(GDestroyNotify) egis_etu905_command_data_free);
|
||||
|
||||
fpi_usb_transfer_fill_bulk_full (transfer,
|
||||
EGIS_ETU905_EP_CMD_OUT,
|
||||
fpi_byte_writer_reset_and_get_data (&writer),
|
||||
buffer_out_length,
|
||||
g_free);
|
||||
fpi_ssm_start (ssm, egis_etu905_cmd_ssm_done);
|
||||
|
||||
g_assert (self->cmd_transfer == NULL);
|
||||
self->cmd_transfer = g_steal_pointer (&transfer);
|
||||
fpi_ssm_start (self->cmd_ssm, egis_etu905_cmd_ssm_done);
|
||||
if (!written)
|
||||
fpi_ssm_mark_failed (ssm, fpi_device_error_new (FP_DEVICE_ERROR_PROTO));
|
||||
}
|
||||
|
||||
static inline void
|
||||
egis_etu905_exec_cmd (FpDevice *device,
|
||||
const guchar *cmd,
|
||||
const gsize cmd_length,
|
||||
SynCmdMsgCallback callback)
|
||||
{
|
||||
egis_etu905_exec_cmd_full (device, cmd, cmd_length, callback,
|
||||
fpi_device_get_cancellable (device));
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -518,7 +571,7 @@ egis_etu905_list_run_state (FpiSsm *ssm,
|
||||
switch (fpi_ssm_get_cur_state (ssm))
|
||||
{
|
||||
case LIST_GET_ENROLLED_IDS:
|
||||
egis_etu905_exec_cmd (device, cmd_list, cmd_list_len,
|
||||
egis_etu905_exec_cmd (device, cmd_list, G_N_ELEMENTS (cmd_list),
|
||||
egis_etu905_list_fill_enrolled_ids_cb);
|
||||
break;
|
||||
|
||||
@@ -581,7 +634,7 @@ egis_etu905_get_delete_cmd (FpDevice *device,
|
||||
const gsize body_length = sizeof (guchar) * EGIS_ETU905_FINGERPRINT_DATA_SIZE *
|
||||
num_to_delete;
|
||||
/* total_length is the 6 various bytes plus prefix and body payload */
|
||||
const gsize total_length = (sizeof (guchar) * 6) + cmd_delete_prefix_len +
|
||||
const gsize total_length = (sizeof (guchar) * 6) + G_N_ELEMENTS (cmd_delete_prefix) +
|
||||
body_length;
|
||||
|
||||
/* pre-fill entire payload with 00s */
|
||||
@@ -609,7 +662,7 @@ egis_etu905_get_delete_cmd (FpDevice *device,
|
||||
|
||||
/* command prefix */
|
||||
written &= fpi_byte_writer_put_data (&writer, cmd_delete_prefix,
|
||||
cmd_delete_prefix_len);
|
||||
G_N_ELEMENTS (cmd_delete_prefix));
|
||||
|
||||
/* 2-bytes size logic for counter again */
|
||||
if (num_to_delete > 7)
|
||||
@@ -700,7 +753,7 @@ egis_etu905_delete_cb (FpDevice *device,
|
||||
if (egis_etu905_validate_response_prefix (buffer_in,
|
||||
length_in,
|
||||
rsp_delete_success_prefix,
|
||||
rsp_delete_success_prefix_len))
|
||||
G_N_ELEMENTS (rsp_delete_success_prefix)))
|
||||
{
|
||||
if (fpi_device_get_current_action (device) == FPI_DEVICE_ACTION_CLEAR_STORAGE)
|
||||
{
|
||||
@@ -738,7 +791,7 @@ egis_etu905_delete_run_state (FpiSsm *ssm,
|
||||
{
|
||||
case DELETE_GET_ENROLLED_IDS:
|
||||
/* get enrolled_ids from device for use building delete payload below */
|
||||
egis_etu905_exec_cmd (device, cmd_list, cmd_list_len,
|
||||
egis_etu905_exec_cmd (device, cmd_list, G_N_ELEMENTS (cmd_list),
|
||||
egis_etu905_list_fill_enrolled_ids_cb);
|
||||
break;
|
||||
|
||||
@@ -852,11 +905,11 @@ egis_etu905_read_capture_cb (FpDevice *device,
|
||||
if (egis_etu905_validate_response_prefix (buffer_in,
|
||||
length_in,
|
||||
rsp_read_success_prefix,
|
||||
rsp_read_success_prefix_len) &&
|
||||
G_N_ELEMENTS (rsp_read_success_prefix)) &&
|
||||
egis_etu905_validate_response_suffix (buffer_in,
|
||||
length_in,
|
||||
rsp_read_success_suffix,
|
||||
rsp_read_success_suffix_len))
|
||||
G_N_ELEMENTS (rsp_read_success_suffix)))
|
||||
{
|
||||
egis_etu905_enroll_status_report (device, enroll_print,
|
||||
ENROLL_STATUS_PARTIAL_OK, NULL);
|
||||
@@ -869,18 +922,18 @@ egis_etu905_read_capture_cb (FpDevice *device,
|
||||
if (egis_etu905_validate_response_prefix (buffer_in,
|
||||
length_in,
|
||||
rsp_read_offcenter_prefix,
|
||||
rsp_read_offcenter_prefix_len) &&
|
||||
G_N_ELEMENTS (rsp_read_offcenter_prefix)) &&
|
||||
egis_etu905_validate_response_suffix (buffer_in,
|
||||
length_in,
|
||||
rsp_read_offcenter_suffix,
|
||||
rsp_read_offcenter_suffix_len))
|
||||
G_N_ELEMENTS (rsp_read_offcenter_suffix)))
|
||||
error = fpi_device_retry_new (FP_DEVICE_RETRY_CENTER_FINGER);
|
||||
|
||||
/* "Sensor is dirty" */
|
||||
else if (egis_etu905_validate_response_prefix (buffer_in,
|
||||
length_in,
|
||||
rsp_read_dirty_prefix,
|
||||
rsp_read_dirty_prefix_len))
|
||||
G_N_ELEMENTS (rsp_read_dirty_prefix)))
|
||||
error = fpi_device_retry_new_msg (FP_DEVICE_RETRY_REMOVE_FINGER,
|
||||
"Your device is having trouble recognizing you. "
|
||||
"Make sure your sensor is clean.");
|
||||
@@ -918,7 +971,7 @@ egis_etu905_enroll_duplicate_check_cb (FpDevice *device,
|
||||
if (egis_etu905_validate_response_suffix (buffer_in,
|
||||
length_in,
|
||||
rsp_check_not_yet_enrolled_suffix,
|
||||
rsp_check_not_yet_enrolled_suffix_len))
|
||||
G_N_ELEMENTS (rsp_check_not_yet_enrolled_suffix)))
|
||||
fpi_ssm_jump_to_state (self->task_ssm, ENROLL_COMMIT_START);
|
||||
else
|
||||
egis_etu905_enroll_status_report (device, NULL, ENROLL_STATUS_DUPLICATE,
|
||||
@@ -946,7 +999,7 @@ egis_etu905_enroll_begin_cb (FpDevice *device,
|
||||
/*
|
||||
* Builds the full "check" payload which includes identifiers for all
|
||||
* fingerprints which currently should exist on the storage. This payload is
|
||||
* used during both enrollment and verify actions.
|
||||
* used during both enrollment and identify actions.
|
||||
*/
|
||||
static guchar *
|
||||
egis_etu905_get_check_cmd (FpDevice *device,
|
||||
@@ -980,8 +1033,8 @@ egis_etu905_get_check_cmd (FpDevice *device,
|
||||
/* prefix length can depend on the type */
|
||||
const gsize check_prefix_length = (fpi_device_get_driver_data (device) &
|
||||
EGIS_ETU905_DRIVER_CHECK_PREFIX_TYPE2) ?
|
||||
cmd_check_prefix_type2_len :
|
||||
cmd_check_prefix_type1_len;
|
||||
G_N_ELEMENTS (cmd_check_prefix_type2) :
|
||||
G_N_ELEMENTS (cmd_check_prefix_type1);
|
||||
|
||||
/* total_length is the 6 various bytes plus all other prefixes/suffixes and
|
||||
* the body payload */
|
||||
@@ -989,7 +1042,7 @@ egis_etu905_get_check_cmd (FpDevice *device,
|
||||
+ check_prefix_length
|
||||
+ EGIS_ETU905_CMD_CHECK_SEPARATOR_LENGTH
|
||||
+ body_length
|
||||
+ cmd_check_suffix_len;
|
||||
+ G_N_ELEMENTS (cmd_check_suffix);
|
||||
|
||||
/* pre-fill entire payload with 00s */
|
||||
fpi_byte_writer_init_with_size (&writer, total_length, TRUE);
|
||||
@@ -1021,10 +1074,10 @@ egis_etu905_get_check_cmd (FpDevice *device,
|
||||
/* command prefix */
|
||||
if (fpi_device_get_driver_data (device) & EGIS_ETU905_DRIVER_CHECK_PREFIX_TYPE2)
|
||||
written &= fpi_byte_writer_put_data (&writer, cmd_check_prefix_type2,
|
||||
cmd_check_prefix_type2_len);
|
||||
G_N_ELEMENTS (cmd_check_prefix_type2));
|
||||
else
|
||||
written &= fpi_byte_writer_put_data (&writer, cmd_check_prefix_type1,
|
||||
cmd_check_prefix_type1_len);
|
||||
G_N_ELEMENTS (cmd_check_prefix_type1));
|
||||
|
||||
/* 2-bytes size logic for counter again */
|
||||
if (self->enrolled_ids->len > 6)
|
||||
@@ -1054,7 +1107,7 @@ egis_etu905_get_check_cmd (FpDevice *device,
|
||||
|
||||
/* command suffix */
|
||||
written &= fpi_byte_writer_put_data (&writer, cmd_check_suffix,
|
||||
cmd_check_suffix_len);
|
||||
G_N_ELEMENTS (cmd_check_suffix));
|
||||
g_assert (written);
|
||||
|
||||
if (length_out)
|
||||
@@ -1068,7 +1121,6 @@ egis_etu905_enroll_run_state (FpiSsm *ssm,
|
||||
FpDevice *device)
|
||||
{
|
||||
g_auto(FpiByteWriter) writer = {0};
|
||||
EgismocSidData sid_data = {0};
|
||||
EnrollPrint *enroll_print = fpi_ssm_get_data (ssm);
|
||||
g_autofree guchar *payload = NULL;
|
||||
gsize payload_length = 0;
|
||||
@@ -1078,17 +1130,17 @@ egis_etu905_enroll_run_state (FpiSsm *ssm,
|
||||
switch (fpi_ssm_get_cur_state (ssm))
|
||||
{
|
||||
case ENROLL_START:
|
||||
egis_etu905_exec_cmd (device, cmd_enroll_starting, cmd_enroll_starting_len,
|
||||
egis_etu905_exec_cmd (device, cmd_enroll_starting, G_N_ELEMENTS (cmd_enroll_starting),
|
||||
egis_etu905_enroll_begin_cb);
|
||||
break;
|
||||
|
||||
case ENROLL_CAPTURE_SENSOR_RESET:
|
||||
egis_etu905_exec_cmd (device, cmd_sensor_reset, cmd_sensor_reset_len,
|
||||
egis_etu905_exec_cmd (device, cmd_sensor_reset, G_N_ELEMENTS (cmd_sensor_reset),
|
||||
egis_etu905_task_ssm_next_state_cb);
|
||||
break;
|
||||
|
||||
case ENROLL_CAPTURE_SENSOR_START_CAPTURE:
|
||||
egis_etu905_exec_cmd (device, cmd_sensor_start_capture, cmd_sensor_start_capture_len,
|
||||
egis_etu905_exec_cmd (device, cmd_sensor_start_capture, G_N_ELEMENTS (cmd_sensor_start_capture),
|
||||
egis_etu905_task_ssm_next_state_cb);
|
||||
break;
|
||||
|
||||
@@ -1097,17 +1149,17 @@ egis_etu905_enroll_run_state (FpiSsm *ssm,
|
||||
break;
|
||||
|
||||
case ENROLL_CAPTURE_READ_RESPONSE:
|
||||
egis_etu905_exec_cmd (device, cmd_read_capture, cmd_read_capture_len,
|
||||
egis_etu905_exec_cmd (device, cmd_read_capture, G_N_ELEMENTS (cmd_read_capture),
|
||||
egis_etu905_read_capture_cb);
|
||||
break;
|
||||
|
||||
case ENROLL_DUPLICATE_CHECK:
|
||||
egis_etu905_exec_cmd (device, cmd_duplicate_check, cmd_duplicate_check_len,
|
||||
egis_etu905_exec_cmd (device, cmd_duplicate_check, G_N_ELEMENTS (cmd_duplicate_check),
|
||||
egis_etu905_enroll_duplicate_check_cb);
|
||||
break;
|
||||
|
||||
case ENROLL_COMMIT_START:
|
||||
egis_etu905_exec_cmd (device, cmd_commit_starting, cmd_commit_starting_len,
|
||||
egis_etu905_exec_cmd (device, cmd_commit_starting, G_N_ELEMENTS (cmd_commit_starting),
|
||||
egis_etu905_commit_start_cb);
|
||||
break;
|
||||
|
||||
@@ -1115,20 +1167,21 @@ egis_etu905_enroll_run_state (FpiSsm *ssm,
|
||||
user_id = fpi_print_generate_user_id (enroll_print->print);
|
||||
fp_dbg ("New fingerprint ID: %s", user_id);
|
||||
|
||||
sid_data.reserve_para_1 = EGIS_ETU905_PARA_1_VALUE;
|
||||
sid_data.reserve_para_2 = EGIS_ETU905_PARA_2_VALUE;
|
||||
sid_data.reserve_para_3 = EGIS_ETU905_PARA_3_VALUE;
|
||||
memcpy (sid_data.reserve_para_4, user_id, MIN (EGIS_ETU905_FINGERPRINT_DATA_SIZE, strlen (user_id)));
|
||||
egis_etu905_set_print_data (enroll_print->print, (const gchar *) &sid_data.reserve_para_4, user_id);
|
||||
fpi_byte_writer_init (&writer);
|
||||
if (!fpi_byte_writer_put_data (&writer, cmd_new_print_prefix_type2,
|
||||
cmd_new_print_prefix_type2_len))
|
||||
{
|
||||
fpi_ssm_mark_failed (ssm, fpi_device_error_new (FP_DEVICE_ERROR_PROTO));
|
||||
break;
|
||||
}
|
||||
if (!fpi_byte_writer_put_data (&writer, (guint8 *) &sid_data,
|
||||
sizeof (EgismocSidData)))
|
||||
device_print_id = g_malloc0 (EGIS_ETU905_FINGERPRINT_DATA_SIZE);
|
||||
memcpy (device_print_id, user_id,
|
||||
MIN (EGIS_ETU905_FINGERPRINT_DATA_SIZE, strlen (user_id)));
|
||||
egis_etu905_set_print_data (enroll_print->print, device_print_id, user_id);
|
||||
|
||||
fpi_byte_writer_init_with_size (&writer,
|
||||
G_N_ELEMENTS (cmd_new_print_prefix_type2) +
|
||||
1 + 2 + 2 + EGIS_ETU905_PARA_4_SIZE,
|
||||
TRUE);
|
||||
if (!fpi_byte_writer_put_data_static (&writer, cmd_new_print_prefix_type2) ||
|
||||
!fpi_byte_writer_put_uint8 (&writer, EGIS_ETU905_PARA_1_VALUE) ||
|
||||
!fpi_byte_writer_put_uint16_le (&writer, EGIS_ETU905_PARA_2_VALUE) ||
|
||||
!fpi_byte_writer_put_uint16_le (&writer, EGIS_ETU905_PARA_3_VALUE) ||
|
||||
!fpi_byte_writer_put_data (&writer, (guint8 *) device_print_id,
|
||||
EGIS_ETU905_FINGERPRINT_DATA_SIZE))
|
||||
{
|
||||
fpi_ssm_mark_failed (ssm, fpi_device_error_new (FP_DEVICE_ERROR_PROTO));
|
||||
break;
|
||||
@@ -1141,21 +1194,13 @@ egis_etu905_enroll_run_state (FpiSsm *ssm,
|
||||
break;
|
||||
|
||||
case ENROLL_COMMIT_SENSOR_RESET:
|
||||
egis_etu905_exec_cmd (device, cmd_sensor_reset, cmd_sensor_reset_len,
|
||||
egis_etu905_exec_cmd (device, cmd_sensor_reset, G_N_ELEMENTS (cmd_sensor_reset),
|
||||
egis_etu905_task_ssm_next_state_cb);
|
||||
break;
|
||||
|
||||
case ENROLL_COMPLETE:
|
||||
egis_etu905_enroll_status_report (device, enroll_print, ENROLL_STATUS_COMPLETE, NULL);
|
||||
|
||||
/* Success, do *not* send cancel command at this point */
|
||||
fpi_ssm_jump_to_state (ssm, ENROLL_STATES);
|
||||
break;
|
||||
|
||||
/* Cleanup states follow */
|
||||
case ENROLL_CANCEL:
|
||||
egis_etu905_exec_cmd (device, cmd_enroll_discard, cmd_enroll_discard_len,
|
||||
egis_etu905_task_ssm_next_state_cb);
|
||||
fpi_ssm_next_state (ssm);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1172,9 +1217,7 @@ egis_etu905_enroll (FpDevice *device)
|
||||
enroll_print->stage = 0;
|
||||
|
||||
g_assert (self->task_ssm == NULL);
|
||||
self->task_ssm = fpi_ssm_new_full (device, egis_etu905_enroll_run_state,
|
||||
ENROLL_STATES, ENROLL_CANCEL,
|
||||
"enroll");
|
||||
self->task_ssm = fpi_ssm_new (device, egis_etu905_enroll_run_state, ENROLL_STATES);
|
||||
fpi_ssm_set_data (self->task_ssm, g_steal_pointer (&enroll_print), g_free);
|
||||
fpi_ssm_start (self->task_ssm, egis_etu905_task_ssm_done);
|
||||
}
|
||||
@@ -1188,7 +1231,6 @@ egis_etu905_identify_check_cb (FpDevice *device,
|
||||
FpiDeviceEgisEtu905 *self = FPI_DEVICE_EGIS_ETU905 (device);
|
||||
guint8 device_print_id[EGIS_ETU905_FINGERPRINT_DATA_SIZE];
|
||||
FpPrint *print = NULL;
|
||||
FpPrint *verify_print = NULL;
|
||||
GPtrArray *prints;
|
||||
gboolean found = FALSE;
|
||||
guint index;
|
||||
@@ -1205,7 +1247,7 @@ egis_etu905_identify_check_cb (FpDevice *device,
|
||||
if (egis_etu905_validate_response_suffix (buffer_in,
|
||||
length_in,
|
||||
rsp_identify_match_suffix,
|
||||
rsp_identify_match_suffix_len))
|
||||
G_N_ELEMENTS (rsp_identify_match_suffix)))
|
||||
{
|
||||
gboolean id_known = FALSE;
|
||||
FpiByteReader reader;
|
||||
@@ -1264,42 +1306,26 @@ egis_etu905_identify_check_cb (FpDevice *device,
|
||||
|
||||
fp_info ("Identify successful for: %s", fp_print_get_description (print));
|
||||
|
||||
if (fpi_device_get_current_action (device) == FPI_DEVICE_ACTION_IDENTIFY)
|
||||
{
|
||||
fpi_device_get_identify_data (device, &prints);
|
||||
found = g_ptr_array_find_with_equal_func (prints,
|
||||
print,
|
||||
(GEqualFunc) fp_print_equal,
|
||||
&index);
|
||||
fpi_device_get_identify_data (device, &prints);
|
||||
found = g_ptr_array_find_with_equal_func (prints,
|
||||
print,
|
||||
(GEqualFunc) fp_print_equal,
|
||||
&index);
|
||||
|
||||
if (found)
|
||||
fpi_device_identify_report (device, g_ptr_array_index (prints, index), print, NULL);
|
||||
else
|
||||
fpi_device_identify_report (device, NULL, print, NULL);
|
||||
}
|
||||
if (found)
|
||||
fpi_device_identify_report (device, g_ptr_array_index (prints, index), print, NULL);
|
||||
else
|
||||
{
|
||||
fpi_device_get_verify_data (device, &verify_print);
|
||||
fp_info ("Verifying against: %s", fp_print_get_description (verify_print));
|
||||
|
||||
if (fp_print_equal (verify_print, print))
|
||||
fpi_device_verify_report (device, FPI_MATCH_SUCCESS, print, NULL);
|
||||
else
|
||||
fpi_device_verify_report (device, FPI_MATCH_FAIL, print, NULL);
|
||||
}
|
||||
fpi_device_identify_report (device, NULL, print, NULL);
|
||||
}
|
||||
/* If device was successfully read but it was a "not matched" */
|
||||
else if (egis_etu905_validate_response_suffix (buffer_in,
|
||||
length_in,
|
||||
rsp_identify_notmatch_suffix,
|
||||
rsp_identify_notmatch_suffix_len))
|
||||
G_N_ELEMENTS (rsp_identify_notmatch_suffix)))
|
||||
{
|
||||
fp_info ("Print was not identified by the device");
|
||||
|
||||
if (fpi_device_get_current_action (device) == FPI_DEVICE_ACTION_VERIFY)
|
||||
fpi_device_verify_report (device, FPI_MATCH_FAIL, NULL, NULL);
|
||||
else
|
||||
fpi_device_identify_report (device, NULL, NULL, NULL);
|
||||
fpi_device_identify_report (device, NULL, NULL, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1312,6 +1338,116 @@ egis_etu905_identify_check_cb (FpDevice *device,
|
||||
fpi_ssm_next_state (self->task_ssm);
|
||||
}
|
||||
|
||||
static void egis_etu905_identify_cancel_run_state (FpiSsm *ssm,
|
||||
FpDevice *device);
|
||||
|
||||
static void
|
||||
egis_etu905_identify_cancel_ssm_done (FpiSsm *ssm,
|
||||
FpDevice *device,
|
||||
GError *error)
|
||||
{
|
||||
FpiDeviceEgisEtu905 *self = FPI_DEVICE_EGIS_ETU905 (device);
|
||||
|
||||
self->identify_cancel_ssm = NULL;
|
||||
|
||||
if (error)
|
||||
{
|
||||
g_warning ("Cancel command failed: %s", error->message);
|
||||
g_clear_error (&error);
|
||||
}
|
||||
|
||||
/* The cancel flow is triggered in two scenarios:
|
||||
* 1. Identify was cancelled before completion (task_ssm failed with
|
||||
* G_IO_ERROR_CANCELLED). We need to report the cancel error.
|
||||
* 2. Identify completed normally but was cancelled just as it finished
|
||||
* (task_ssm completed, fpi_device_identify_complete was already called
|
||||
* in IDENTIFY_COMPLETE state). We just need to clean up.
|
||||
*
|
||||
* We distinguish these by checking if the action is still cancelled.
|
||||
* If fpi_device_action_is_cancelled returns TRUE, the identify was
|
||||
* cancelled and we need to report the error. Otherwise, identify
|
||||
* completed successfully and we just complete the action. */
|
||||
if (fpi_device_action_is_cancelled (device))
|
||||
{
|
||||
fp_dbg ("Cancel completed, reporting cancel error");
|
||||
error = g_error_new_literal (G_IO_ERROR, G_IO_ERROR_CANCELLED,
|
||||
"Operation was cancelled");
|
||||
fpi_device_action_error (device, g_steal_pointer (&error));
|
||||
}
|
||||
else
|
||||
{
|
||||
fp_dbg ("Cancel completed after identify done, completing identify action");
|
||||
fpi_device_identify_complete (device, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
egis_etu905_identify_cancel_next_state_cb (FpDevice *device,
|
||||
guchar *buffer_in,
|
||||
gsize length_in,
|
||||
GError *error)
|
||||
{
|
||||
FpiDeviceEgisEtu905 *self = FPI_DEVICE_EGIS_ETU905 (device);
|
||||
|
||||
if (error)
|
||||
fpi_ssm_mark_failed (self->identify_cancel_ssm, error);
|
||||
else
|
||||
fpi_ssm_next_state (self->identify_cancel_ssm);
|
||||
}
|
||||
|
||||
static void
|
||||
egis_etu905_identify_cancel_run_state (FpiSsm *ssm,
|
||||
FpDevice *device)
|
||||
{
|
||||
FpiDeviceEgisEtu905 *self = FPI_DEVICE_EGIS_ETU905 (device);
|
||||
|
||||
switch (fpi_ssm_get_cur_state (ssm))
|
||||
{
|
||||
case CANCEL_SENSOR_RESET:
|
||||
/* Reset sensor to ensure device is in a clean state.
|
||||
* Use NULL cancellable to ensure this command reaches the device. */
|
||||
egis_etu905_exec_cmd_full (device, cmd_sensor_reset,
|
||||
G_N_ELEMENTS (cmd_sensor_reset),
|
||||
egis_etu905_identify_cancel_next_state_cb,
|
||||
NULL);
|
||||
break;
|
||||
|
||||
case CANCEL_SEND_CANCEL:
|
||||
/* Send cmd_identify_cancel to trigger firmware template update.
|
||||
* Only send if identify was actually started (cmd_sensor_identify was sent).
|
||||
* Use NULL cancellable to ensure this command reaches the device. */
|
||||
if (self->identify_started)
|
||||
{
|
||||
egis_etu905_exec_cmd_full (device, cmd_identify_cancel,
|
||||
G_N_ELEMENTS (cmd_identify_cancel),
|
||||
egis_etu905_identify_cancel_next_state_cb,
|
||||
NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
fpi_ssm_next_state (ssm);
|
||||
}
|
||||
break;
|
||||
|
||||
case CANCEL_SEND_CANCEL_RESULT:
|
||||
/* Retrieve the cancel result after template update is triggered.
|
||||
* Only send if identify was actually started.
|
||||
* Use NULL cancellable to ensure this command reaches the device. */
|
||||
if (self->identify_started)
|
||||
{
|
||||
egis_etu905_exec_cmd_full (device, cmd_identify_cancel_result,
|
||||
G_N_ELEMENTS (cmd_identify_cancel_result),
|
||||
egis_etu905_identify_cancel_next_state_cb,
|
||||
NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
fpi_ssm_next_state (ssm);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
egis_etu905_identify_run_state (FpiSsm *ssm,
|
||||
FpDevice *device)
|
||||
@@ -1324,7 +1460,7 @@ egis_etu905_identify_run_state (FpiSsm *ssm,
|
||||
{
|
||||
case IDENTIFY_GET_ENROLLED_IDS:
|
||||
/* get enrolled_ids from device for use in check stages below */
|
||||
egis_etu905_exec_cmd (device, cmd_list, cmd_list_len,
|
||||
egis_etu905_exec_cmd (device, cmd_list, G_N_ELEMENTS (cmd_list),
|
||||
egis_etu905_list_fill_enrolled_ids_cb);
|
||||
break;
|
||||
|
||||
@@ -1339,12 +1475,13 @@ egis_etu905_identify_run_state (FpiSsm *ssm,
|
||||
break;
|
||||
|
||||
case IDENTIFY_SENSOR_RESET:
|
||||
egis_etu905_exec_cmd (device, cmd_sensor_reset, cmd_sensor_reset_len,
|
||||
egis_etu905_exec_cmd (device, cmd_sensor_reset, G_N_ELEMENTS (cmd_sensor_reset),
|
||||
egis_etu905_task_ssm_next_state_cb);
|
||||
break;
|
||||
|
||||
case IDENTIFY_SENSOR_IDENTIFY:
|
||||
egis_etu905_exec_cmd (device, cmd_sensor_identify, cmd_sensor_identify_len,
|
||||
self->identify_started = TRUE;
|
||||
egis_etu905_exec_cmd (device, cmd_sensor_identify, G_N_ELEMENTS (cmd_sensor_identify),
|
||||
egis_etu905_task_ssm_next_state_cb);
|
||||
break;
|
||||
|
||||
@@ -1353,7 +1490,7 @@ egis_etu905_identify_run_state (FpiSsm *ssm,
|
||||
break;
|
||||
|
||||
case IDENTIFY_SENSOR_CHECK:
|
||||
egis_etu905_exec_cmd (device, cmd_sensor_check, cmd_sensor_check_len,
|
||||
egis_etu905_exec_cmd (device, cmd_sensor_check, G_N_ELEMENTS (cmd_sensor_check),
|
||||
egis_etu905_task_ssm_next_state_cb);
|
||||
break;
|
||||
|
||||
@@ -1363,50 +1500,43 @@ egis_etu905_identify_run_state (FpiSsm *ssm,
|
||||
egis_etu905_identify_check_cb);
|
||||
break;
|
||||
|
||||
case IDENTIFY_SEND_CANCEL_RESULT:
|
||||
egis_etu905_exec_cmd (device, cmd_identify_cancel_result, cmd_identify_cancel_result_len,
|
||||
egis_etu905_task_ssm_next_state_cb);
|
||||
break;
|
||||
|
||||
case IDENTIFY_COMPLETE_SENSOR_RESET:
|
||||
egis_etu905_exec_cmd (device, cmd_sensor_reset, cmd_sensor_reset_len,
|
||||
egis_etu905_task_ssm_next_state_cb);
|
||||
egis_etu905_exec_cmd_full (device, cmd_sensor_reset, G_N_ELEMENTS (cmd_sensor_reset),
|
||||
egis_etu905_task_ssm_next_state_cb,
|
||||
NULL);
|
||||
break;
|
||||
|
||||
/*
|
||||
* In Windows, the driver seems at this point to then immediately take
|
||||
* another read from the sensor; this is suspected to be an on-chip
|
||||
* "verify". However, because the user's finger is still on the sensor from
|
||||
* "identify". However, because the user's finger is still on the sensor from
|
||||
* the identify, then it seems to always return positive. We will consider
|
||||
* this extra step unnecessary and just skip it in this driver. This driver
|
||||
* will instead handle matching of the FpPrint from the gallery in the
|
||||
* "verify" case of the callback egis_etu905_identify_check_cb.
|
||||
* callback egis_etu905_identify_check_cb.
|
||||
*
|
||||
* If the operation was cancelled, we don't complete the identify action
|
||||
* here. Instead, we let the cancel flow (triggered by task_ssm_done)
|
||||
* complete first, and it will call fpi_device_identify_complete when done.
|
||||
* This ensures the device stays open until the cancel flow completes.
|
||||
*/
|
||||
case IDENTIFY_COMPLETE:
|
||||
if (fpi_device_get_current_action (device) == FPI_DEVICE_ACTION_IDENTIFY)
|
||||
if (!fpi_device_action_is_cancelled (device))
|
||||
fpi_device_identify_complete (device, NULL);
|
||||
else
|
||||
fpi_device_verify_complete (device, NULL);
|
||||
|
||||
/* Success, do *not* send cancel command at this point */
|
||||
fpi_ssm_jump_to_state (ssm, IDENTIFY_STATES);
|
||||
break;
|
||||
|
||||
/* Cleanup states follow */
|
||||
case IDENTIFY_CANCEL:
|
||||
egis_etu905_exec_cmd (device, cmd_identify_cancel, cmd_identify_cancel_len,
|
||||
egis_etu905_task_ssm_next_state_cb);
|
||||
fpi_ssm_mark_completed (ssm);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
egis_etu905_identify_verify (FpDevice *device)
|
||||
egis_etu905_identify (FpDevice *device)
|
||||
{
|
||||
fp_dbg ("Identify or Verify");
|
||||
fp_dbg ("Identify");
|
||||
FpiDeviceEgisEtu905 *self = FPI_DEVICE_EGIS_ETU905 (device);
|
||||
|
||||
g_assert (self->task_ssm == NULL);
|
||||
self->identify_started = FALSE;
|
||||
self->task_ssm = fpi_ssm_new (device, egis_etu905_identify_run_state, IDENTIFY_STATES);
|
||||
fpi_ssm_start (self->task_ssm, egis_etu905_task_ssm_done);
|
||||
}
|
||||
@@ -1420,7 +1550,7 @@ egis_etu905_fw_version_cb (FpDevice *device,
|
||||
FpiDeviceEgisEtu905 *self = FPI_DEVICE_EGIS_ETU905 (device);
|
||||
FpiByteReader reader;
|
||||
const guint8 *fw_version_data = NULL;
|
||||
const guint prefix_length = egis_etu905_read_prefix_len + 2 + 3 + 1;
|
||||
const guint prefix_length = G_N_ELEMENTS (egis_etu905_read_prefix) + 2 + 3 + 1;
|
||||
gsize fw_version_length;
|
||||
g_autofree gchar *fw_version = NULL;
|
||||
|
||||
@@ -1436,7 +1566,7 @@ egis_etu905_fw_version_cb (FpDevice *device,
|
||||
if (!egis_etu905_validate_response_suffix (buffer_in,
|
||||
length_in,
|
||||
rsp_fw_version_suffix,
|
||||
rsp_fw_version_suffix_len))
|
||||
G_N_ELEMENTS (rsp_fw_version_suffix)))
|
||||
{
|
||||
fpi_ssm_mark_failed (self->task_ssm,
|
||||
fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
|
||||
@@ -1462,7 +1592,7 @@ egis_etu905_fw_version_cb (FpDevice *device,
|
||||
return;
|
||||
}
|
||||
|
||||
fw_version_length = fpi_byte_reader_get_remaining (&reader) - rsp_fw_version_suffix_len;
|
||||
fw_version_length = fpi_byte_reader_get_remaining (&reader) - G_N_ELEMENTS (rsp_fw_version_suffix);
|
||||
|
||||
if (!fpi_byte_reader_get_data (&reader, fw_version_length, &fw_version_data))
|
||||
{
|
||||
@@ -1499,7 +1629,7 @@ egis_etu905_cmd_init_cb (FpDevice *device,
|
||||
if (!egis_etu905_validate_response_suffix (buffer_in,
|
||||
length_in,
|
||||
rsp_fw_version_suffix,
|
||||
rsp_fw_version_suffix_len))
|
||||
G_N_ELEMENTS (rsp_fw_version_suffix)))
|
||||
{
|
||||
fpi_ssm_mark_failed (self->task_ssm,
|
||||
fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
|
||||
@@ -1534,12 +1664,12 @@ egis_etu905_dev_init_handler (FpiSsm *ssm,
|
||||
switch (fpi_ssm_get_cur_state (ssm))
|
||||
{
|
||||
case DEV_GET_FW_VERSION:
|
||||
egis_etu905_exec_cmd (device, cmd_fw_version, cmd_fw_version_len,
|
||||
egis_etu905_exec_cmd (device, cmd_fw_version, G_N_ELEMENTS (cmd_fw_version),
|
||||
egis_etu905_fw_version_cb);
|
||||
return;
|
||||
|
||||
case DEV_INIT_CONTROL:
|
||||
egis_etu905_exec_cmd (device, cmd_init, cmd_init_len,
|
||||
egis_etu905_exec_cmd (device, cmd_init, G_N_ELEMENTS (cmd_init),
|
||||
egis_etu905_cmd_init_cb);
|
||||
return;
|
||||
|
||||
@@ -1649,6 +1779,70 @@ egis_etu905_close (FpDevice *device)
|
||||
fpi_device_close_complete (device, g_steal_pointer (&error));
|
||||
}
|
||||
|
||||
static void
|
||||
egis_etu905_cancel_cb (FpDevice *device,
|
||||
guchar *buffer_in,
|
||||
gsize length_in,
|
||||
GError *error)
|
||||
{
|
||||
if (error)
|
||||
{
|
||||
g_warning ("Cancel command failed: %s", error->message);
|
||||
g_clear_error (&error);
|
||||
}
|
||||
|
||||
/* This callback is only used for enroll cancellation.
|
||||
* Identify cancellation uses egis_etu905_identify_cancel_ssm_done instead.
|
||||
* We must always call fpi_device_action_error here to complete the enroll
|
||||
* action, even if the task_ssm has already been freed. */
|
||||
error = g_error_new_literal (G_IO_ERROR, G_IO_ERROR_CANCELLED,
|
||||
"Operation was cancelled");
|
||||
|
||||
fpi_device_action_error (device, g_steal_pointer (&error));
|
||||
}
|
||||
|
||||
static void
|
||||
egis_etu905_cancel (FpDevice *device)
|
||||
{
|
||||
FpiDeviceAction action = fpi_device_get_current_action (device);
|
||||
FpiDeviceEgisEtu905 *self = FPI_DEVICE_EGIS_ETU905 (device);
|
||||
|
||||
fp_dbg ("Cancelling action %d", action);
|
||||
|
||||
/* The cancellation commands must reach the device to abort the ongoing
|
||||
* sensor operation. By the time we get here the device cancellable is
|
||||
* already cancelled (it aborted the in-flight operation transfer), so we
|
||||
* must not bind these commands to it or they would never be sent.
|
||||
* Cancellation is effectively non-cancellable; the commands are allowed to
|
||||
* fail (no callback), the device is reset by the next operation anyway.
|
||||
*
|
||||
* Note: Even if task_ssm is NULL (operation already completed), we still
|
||||
* need to execute the cancel commands to trigger firmware template update
|
||||
* and device cleanup. The egis_etu905_cancel_cb will check task_ssm and
|
||||
* avoid calling fpi_device_action_error if the action already completed. */
|
||||
if (action == FPI_DEVICE_ACTION_ENROLL)
|
||||
{
|
||||
egis_etu905_exec_cmd_full (device,
|
||||
cmd_enroll_discard,
|
||||
G_N_ELEMENTS (cmd_enroll_discard),
|
||||
egis_etu905_cancel_cb,
|
||||
NULL);
|
||||
}
|
||||
else if (action == FPI_DEVICE_ACTION_IDENTIFY)
|
||||
{
|
||||
g_assert (self->identify_cancel_ssm == NULL);
|
||||
|
||||
self->identify_cancel_ssm = fpi_ssm_new (device,
|
||||
egis_etu905_identify_cancel_run_state,
|
||||
CANCEL_STATES);
|
||||
fpi_ssm_start (self->identify_cancel_ssm, egis_etu905_identify_cancel_ssm_done);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_warning ("Cancel called for unsupported action %d", action);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
fpi_device_egis_etu905_init (FpiDeviceEgisEtu905 *self)
|
||||
{
|
||||
@@ -1672,8 +1866,7 @@ fpi_device_egis_etu905_class_init (FpiDeviceEgisEtu905Class *klass)
|
||||
dev_class->probe = egis_etu905_probe;
|
||||
dev_class->open = egis_etu905_open;
|
||||
dev_class->close = egis_etu905_close;
|
||||
dev_class->identify = egis_etu905_identify_verify;
|
||||
dev_class->verify = egis_etu905_identify_verify;
|
||||
dev_class->identify = egis_etu905_identify;
|
||||
dev_class->enroll = egis_etu905_enroll;
|
||||
dev_class->delete = egis_etu905_delete;
|
||||
dev_class->clear_storage = egis_etu905_clear_storage;
|
||||
|
||||
@@ -53,89 +53,54 @@ G_DECLARE_FINAL_TYPE (FpiDeviceEgisEtu905, fpi_device_egis_etu905, FPI, DEVICE_E
|
||||
#define EGIS_ETU905_PARA_2_VALUE 0
|
||||
#define EGIS_ETU905_PARA_3_VALUE 32
|
||||
|
||||
#pragma pack(push, 1)
|
||||
typedef struct
|
||||
{
|
||||
guchar reserve_para_1;
|
||||
gushort reserve_para_2;
|
||||
gushort reserve_para_3;
|
||||
guchar reserve_para_4[EGIS_ETU905_PARA_4_SIZE];
|
||||
} EgismocSidData;
|
||||
#pragma pack(pop)
|
||||
|
||||
/* standard prefixes for all read/writes */
|
||||
|
||||
static const guchar egis_etu905_write_prefix[] = {'E', 'G', 'I', 'S', 0x00, 0x00, 0x00, 0x01};
|
||||
static const gsize egis_etu905_write_prefix_len = sizeof (egis_etu905_write_prefix) / sizeof (egis_etu905_write_prefix[0]);
|
||||
|
||||
static const guchar egis_etu905_read_prefix[] = {'S', 'I', 'G', 'E', 0x00, 0x00, 0x00, 0x01};
|
||||
static const gsize egis_etu905_read_prefix_len = sizeof (egis_etu905_read_prefix) / sizeof (egis_etu905_read_prefix[0]);
|
||||
|
||||
|
||||
/* hard-coded command payloads */
|
||||
|
||||
static const guchar cmd_fw_version[] = {0x00, 0x00, 0x00, 0x07, 0x50, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x0c};
|
||||
static const gsize cmd_fw_version_len = sizeof (cmd_fw_version) / sizeof (cmd_fw_version[0]);
|
||||
static const guchar rsp_fw_version_suffix[] = {0x90, 0x00};
|
||||
static const gsize rsp_fw_version_suffix_len = sizeof (rsp_fw_version_suffix) / sizeof (rsp_fw_version_suffix[0]);
|
||||
|
||||
static const guchar cmd_init[] = {0x00, 0x00, 0x00, 0x29, 0x50, 0x81, 0x80, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x12, 0x00, 0x45, 0x67, 0x69, 0x73,
|
||||
0x46, 0x50, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x00, 0x51, 0xc6, 0xbd, 0x71};
|
||||
static const gsize cmd_init_len = sizeof (cmd_init) / sizeof (cmd_init[0]);
|
||||
|
||||
static const guchar cmd_list[] = {0x00, 0x00, 0x00, 0x07, 0x50, 0x19, 0x04, 0x00, 0x00, 0x01, 0x40};
|
||||
static const gsize cmd_list_len = sizeof (cmd_list) / sizeof (cmd_list[0]);
|
||||
|
||||
static const guchar cmd_sensor_reset[] = {0x00, 0x00, 0x00, 0x04, 0x50, 0x1a, 0x00, 0x00};
|
||||
static const gsize cmd_sensor_reset_len = sizeof (cmd_sensor_reset) / sizeof (cmd_sensor_reset[0]);
|
||||
|
||||
static const guchar cmd_sensor_check[] = {0x00, 0x00, 0x00, 0x04, 0x50, 0x17, 0x02, 0x00};
|
||||
static const gsize cmd_sensor_check_len = sizeof (cmd_sensor_check) / sizeof (cmd_sensor_check[0]);
|
||||
|
||||
static const guchar cmd_sensor_identify[] = {0x00, 0x00, 0x00, 0x04, 0x50, 0x17, 0x01, 0x01};
|
||||
static const gsize cmd_sensor_identify_len = sizeof (cmd_sensor_identify) / sizeof (cmd_sensor_identify[0]);
|
||||
|
||||
static const guchar rsp_identify_match_suffix[] = {0x90, 0x00};
|
||||
static const gsize rsp_identify_match_suffix_len = sizeof (rsp_identify_match_suffix) / sizeof (rsp_identify_match_suffix[0]);
|
||||
|
||||
static const guchar rsp_identify_notmatch_suffix[] = {0x90, 0x04};
|
||||
static const gsize rsp_identify_notmatch_suffix_len = sizeof (rsp_identify_notmatch_suffix) / sizeof (rsp_identify_notmatch_suffix[0]);
|
||||
|
||||
static const guchar cmd_enroll_starting[] = {0x00, 0x00, 0x00, 0x07, 0x50, 0x16, 0x01, 0x00, 0x00, 0x00, 0x20};
|
||||
static const gsize cmd_enroll_starting_len = sizeof (cmd_enroll_starting) / sizeof (cmd_enroll_starting[0]);
|
||||
static const guchar cmd_enroll_discard[] = {0x00, 0x00, 0x00, 0x07, 0x50, 0x16, 0x04, 0x00, 0x00, 0x00, 0x20};
|
||||
|
||||
|
||||
static const guchar cmd_sensor_start_capture[] = {0x00, 0x00, 0x00, 0x04, 0x50, 0x16, 0x02, 0x01};
|
||||
static const gsize cmd_sensor_start_capture_len = sizeof (cmd_sensor_start_capture) / sizeof (cmd_sensor_start_capture[0]);
|
||||
|
||||
static const guchar cmd_read_capture[] = {0x00, 0x00, 0x00, 0x07, 0x50, 0x16, 0x02, 0x02, 0x00, 0x00, 0x02};
|
||||
static const gsize cmd_read_capture_len = sizeof (cmd_read_capture) / sizeof (cmd_read_capture[0]);
|
||||
|
||||
static const guchar cmd_duplicate_check[] = {0x00, 0x00, 0x00, 0x04, 0x50, 0x16, 0x05, 0x00};
|
||||
static const gsize cmd_duplicate_check_len = sizeof (cmd_duplicate_check) / sizeof (cmd_duplicate_check[0]);
|
||||
|
||||
static const guchar rsp_read_success_prefix[] = {0x00, 0x00, 0x00, 0x04};
|
||||
static const gsize rsp_read_success_prefix_len = sizeof (rsp_read_success_prefix) / sizeof (rsp_read_success_prefix[0]);
|
||||
static const guchar rsp_read_success_suffix[] = {0x90, 0x00};
|
||||
static const gsize rsp_read_success_suffix_len = sizeof (rsp_read_success_suffix) / sizeof (rsp_read_success_suffix[0]);
|
||||
static const guchar rsp_read_offcenter_prefix[] = {0x00, 0x00, 0x00, 0x04};
|
||||
static const gsize rsp_read_offcenter_prefix_len = sizeof (rsp_read_offcenter_prefix) / sizeof (rsp_read_offcenter_prefix[0]);
|
||||
static const guchar rsp_read_offcenter_suffix[] = {0x64, 0x91};
|
||||
static const gsize rsp_read_offcenter_suffix_len = sizeof (rsp_read_offcenter_suffix) / sizeof (rsp_read_offcenter_suffix[0]);
|
||||
static const guchar rsp_read_dirty_prefix[] = {0x00, 0x00, 0x00, 0x02, 0x64};
|
||||
static const gsize rsp_read_dirty_prefix_len = sizeof (rsp_read_dirty_prefix) / sizeof (rsp_read_dirty_prefix[0]);
|
||||
|
||||
static const guchar cmd_commit_starting[] = {0x00, 0x00, 0x00, 0x07, 0x50, 0x16, 0x05, 0x00, 0x00, 0x00, 0x20};
|
||||
static const gsize cmd_commit_starting_len = sizeof (cmd_commit_starting) / sizeof (cmd_commit_starting[0]);
|
||||
|
||||
static const guchar cmd_enroll_discard[] = {0x00, 0x00, 0x00, 0x07, 0x50, 0x16, 0x04, 0x00, 0x00, 0x00, 0x20};
|
||||
static const gsize cmd_enroll_discard_len = sizeof (cmd_enroll_discard) / sizeof (cmd_enroll_discard[0]);
|
||||
|
||||
static const guchar cmd_identify_cancel[] = {0x00, 0x00, 0x00, 0x04, 0x50, 0x04, 0x01, 0x00};
|
||||
static const gsize cmd_identify_cancel_len = sizeof (cmd_identify_cancel) / sizeof (cmd_identify_cancel[0]);
|
||||
|
||||
static const guchar cmd_identify_cancel_result[] = {0x00, 0x00, 0x00, 0x04, 0x50, 0x04, 0x02, 0x00};
|
||||
static const gsize cmd_identify_cancel_result_len = sizeof (cmd_identify_cancel_result) / sizeof (cmd_identify_cancel_result[0]);
|
||||
|
||||
/* prefixes/suffixes and other things for dynamically created command payloads */
|
||||
|
||||
@@ -144,21 +109,14 @@ static const gsize cmd_identify_cancel_result_len = sizeof (cmd_identify_cancel_
|
||||
#define EGIS_ETU905_CMD_CHECK_SEPARATOR_LENGTH 32
|
||||
|
||||
static const guchar cmd_new_print_prefix_type2[] = {0x00, 0x00, 0x00, 0x50, 0x50, 0x16, 0x03, 0x00, 0x00, 0x00, 0x49};
|
||||
static const gsize cmd_new_print_prefix_type2_len = sizeof (cmd_new_print_prefix_type2) / sizeof (cmd_new_print_prefix_type2[0]);
|
||||
|
||||
static const guchar cmd_delete_prefix[] = {0x50, 0x18, 0x04, 0x00, 0x00};
|
||||
static const gsize cmd_delete_prefix_len = sizeof (cmd_delete_prefix) / sizeof (cmd_delete_prefix[0]);
|
||||
static const guchar rsp_delete_success_prefix[] = {0x00, 0x00, 0x00, 0x02, 0x90, 0x00};
|
||||
static const gsize rsp_delete_success_prefix_len = sizeof (rsp_delete_success_prefix) / sizeof (rsp_delete_success_prefix[0]);
|
||||
|
||||
static const guchar cmd_check_prefix_type1[] = {0x50, 0x17, 0x03, 0x00, 0x00};
|
||||
static const gsize cmd_check_prefix_type1_len = sizeof (cmd_check_prefix_type1) / sizeof (cmd_check_prefix_type1[0]);
|
||||
static const guchar cmd_check_prefix_type2[] = {0x50, 0x17, 0x03, 0x80, 0x00};
|
||||
static const gsize cmd_check_prefix_type2_len = sizeof (cmd_check_prefix_type2) / sizeof (cmd_check_prefix_type2[0]);
|
||||
static const guchar cmd_check_suffix[] = {0x00, 0x40};
|
||||
static const gsize cmd_check_suffix_len = sizeof (cmd_check_suffix) / sizeof (cmd_check_suffix[0]);
|
||||
static const guchar rsp_check_not_yet_enrolled_suffix[] = {0x90, 0x04};
|
||||
static const gsize rsp_check_not_yet_enrolled_suffix_len = sizeof (rsp_check_not_yet_enrolled_suffix) / sizeof (rsp_check_not_yet_enrolled_suffix[0]);
|
||||
|
||||
|
||||
/* SSM task states and various status enums */
|
||||
@@ -183,12 +141,8 @@ typedef enum {
|
||||
IDENTIFY_WAIT_FINGER,
|
||||
IDENTIFY_SENSOR_CHECK,
|
||||
IDENTIFY_CHECK,
|
||||
IDENTIFY_SEND_CANCEL_RESULT,
|
||||
IDENTIFY_COMPLETE_SENSOR_RESET,
|
||||
IDENTIFY_COMPLETE,
|
||||
|
||||
/* Cleanup states follow */
|
||||
IDENTIFY_CANCEL,
|
||||
IDENTIFY_STATES,
|
||||
} IdentifyStates;
|
||||
|
||||
@@ -203,9 +157,6 @@ typedef enum {
|
||||
ENROLL_COMMIT,
|
||||
ENROLL_COMMIT_SENSOR_RESET,
|
||||
ENROLL_COMPLETE,
|
||||
|
||||
/* Cleanup states follow */
|
||||
ENROLL_CANCEL,
|
||||
ENROLL_STATES,
|
||||
} EnrollStates;
|
||||
|
||||
@@ -228,3 +179,10 @@ typedef enum {
|
||||
DELETE_DELETE,
|
||||
DELETE_STATES,
|
||||
} DeleteStates;
|
||||
|
||||
typedef enum {
|
||||
CANCEL_SENSOR_RESET,
|
||||
CANCEL_SEND_CANCEL,
|
||||
CANCEL_SEND_CANCEL_RESULT,
|
||||
CANCEL_STATES,
|
||||
} CancelStates;
|
||||
|
||||
@@ -122,8 +122,11 @@ egismoc_validate_response_prefix (const guchar *buffer_in,
|
||||
const guchar *valid_prefix,
|
||||
const gsize valid_prefix_len)
|
||||
{
|
||||
if (buffer_in_len < G_N_ELEMENTS (egismoc_read_prefix) + EGISMOC_CHECK_BYTES_LENGTH + valid_prefix_len)
|
||||
return FALSE;
|
||||
|
||||
const gboolean result = memcmp (buffer_in +
|
||||
(egismoc_read_prefix_len +
|
||||
(G_N_ELEMENTS (egismoc_read_prefix) +
|
||||
EGISMOC_CHECK_BYTES_LENGTH),
|
||||
valid_prefix,
|
||||
valid_prefix_len) == 0;
|
||||
@@ -138,6 +141,9 @@ egismoc_validate_response_suffix (const guchar *buffer_in,
|
||||
const guchar *valid_suffix,
|
||||
const gsize valid_suffix_len)
|
||||
{
|
||||
if (buffer_in_len < valid_suffix_len)
|
||||
return FALSE;
|
||||
|
||||
const gboolean result = memcmp (buffer_in + (buffer_in_len - valid_suffix_len),
|
||||
valid_suffix,
|
||||
valid_suffix_len) == 0;
|
||||
@@ -197,7 +203,7 @@ egismoc_cmd_receive_cb (FpiUsbTransfer *transfer,
|
||||
fpi_ssm_mark_failed (transfer->ssm, error);
|
||||
return;
|
||||
}
|
||||
if (data == NULL || transfer->actual_length < egismoc_read_prefix_len)
|
||||
if (data == NULL || transfer->actual_length < G_N_ELEMENTS (egismoc_read_prefix))
|
||||
{
|
||||
fpi_ssm_mark_failed (transfer->ssm,
|
||||
fpi_device_error_new (FP_DEVICE_ERROR_GENERAL));
|
||||
@@ -321,7 +327,7 @@ egismoc_exec_cmd (FpDevice *device,
|
||||
* egismoc_get_check_bytes() method and payload is what is passed via the cmd
|
||||
* parameter
|
||||
*/
|
||||
buffer_out_length = egismoc_write_prefix_len
|
||||
buffer_out_length = G_N_ELEMENTS (egismoc_write_prefix)
|
||||
+ EGISMOC_CHECK_BYTES_LENGTH
|
||||
+ cmd_length;
|
||||
|
||||
@@ -330,7 +336,7 @@ egismoc_exec_cmd (FpDevice *device,
|
||||
|
||||
/* Prefix */
|
||||
written &= fpi_byte_writer_put_data (&writer, egismoc_write_prefix,
|
||||
egismoc_write_prefix_len);
|
||||
G_N_ELEMENTS (egismoc_write_prefix));
|
||||
|
||||
/* Check Bytes - leave them as 00 for now then later generate and copy over
|
||||
* the real ones */
|
||||
@@ -342,7 +348,7 @@ egismoc_exec_cmd (FpDevice *device,
|
||||
/* Now fetch and set the "real" check bytes based on the currently
|
||||
* assembled payload */
|
||||
check_value = egismoc_get_check_bytes (FPI_BYTE_READER (&writer));
|
||||
fpi_byte_writer_set_pos (&writer, egismoc_write_prefix_len);
|
||||
fpi_byte_writer_set_pos (&writer, G_N_ELEMENTS (egismoc_write_prefix));
|
||||
written &= fpi_byte_writer_put_uint16_be (&writer, check_value);
|
||||
|
||||
/* destroy cmd if requested */
|
||||
@@ -492,7 +498,7 @@ egismoc_list_run_state (FpiSsm *ssm,
|
||||
switch (fpi_ssm_get_cur_state (ssm))
|
||||
{
|
||||
case LIST_GET_ENROLLED_IDS:
|
||||
egismoc_exec_cmd (device, cmd_list, cmd_list_len, NULL,
|
||||
egismoc_exec_cmd (device, cmd_list, G_N_ELEMENTS (cmd_list), NULL,
|
||||
egismoc_list_fill_enrolled_ids_cb);
|
||||
break;
|
||||
|
||||
@@ -557,7 +563,7 @@ egismoc_get_delete_cmd (FpDevice *device,
|
||||
const gsize body_length = sizeof (guchar) * EGISMOC_FINGERPRINT_DATA_SIZE *
|
||||
num_to_delete;
|
||||
/* total_length is the 6 various bytes plus prefix and body payload */
|
||||
const gsize total_length = (sizeof (guchar) * 6) + cmd_delete_prefix_len +
|
||||
const gsize total_length = (sizeof (guchar) * 6) + G_N_ELEMENTS (cmd_delete_prefix) +
|
||||
body_length;
|
||||
|
||||
/* pre-fill entire payload with 00s */
|
||||
@@ -585,7 +591,7 @@ egismoc_get_delete_cmd (FpDevice *device,
|
||||
|
||||
/* command prefix */
|
||||
written &= fpi_byte_writer_put_data (&writer, cmd_delete_prefix,
|
||||
cmd_delete_prefix_len);
|
||||
G_N_ELEMENTS (cmd_delete_prefix));
|
||||
|
||||
/* 2-bytes size logic for counter again */
|
||||
if (num_to_delete > 7)
|
||||
@@ -665,7 +671,7 @@ egismoc_delete_cb (FpDevice *device,
|
||||
if (egismoc_validate_response_prefix (buffer_in,
|
||||
length_in,
|
||||
rsp_delete_success_prefix,
|
||||
rsp_delete_success_prefix_len))
|
||||
G_N_ELEMENTS (rsp_delete_success_prefix)))
|
||||
{
|
||||
if (fpi_device_get_current_action (device) == FPI_DEVICE_ACTION_CLEAR_STORAGE)
|
||||
{
|
||||
@@ -703,7 +709,7 @@ egismoc_delete_run_state (FpiSsm *ssm,
|
||||
{
|
||||
case DELETE_GET_ENROLLED_IDS:
|
||||
/* get enrolled_ids from device for use building delete payload below */
|
||||
egismoc_exec_cmd (device, cmd_list, cmd_list_len, NULL,
|
||||
egismoc_exec_cmd (device, cmd_list, G_N_ELEMENTS (cmd_list), NULL,
|
||||
egismoc_list_fill_enrolled_ids_cb);
|
||||
break;
|
||||
|
||||
@@ -813,11 +819,11 @@ egismoc_read_capture_cb (FpDevice *device,
|
||||
if (egismoc_validate_response_prefix (buffer_in,
|
||||
length_in,
|
||||
rsp_read_success_prefix,
|
||||
rsp_read_success_prefix_len) &&
|
||||
G_N_ELEMENTS (rsp_read_success_prefix)) &&
|
||||
egismoc_validate_response_suffix (buffer_in,
|
||||
length_in,
|
||||
rsp_read_success_suffix,
|
||||
rsp_read_success_suffix_len))
|
||||
G_N_ELEMENTS (rsp_read_success_suffix)))
|
||||
{
|
||||
egismoc_enroll_status_report (device, enroll_print,
|
||||
ENROLL_STATUS_PARTIAL_OK, NULL);
|
||||
@@ -830,18 +836,18 @@ egismoc_read_capture_cb (FpDevice *device,
|
||||
if (egismoc_validate_response_prefix (buffer_in,
|
||||
length_in,
|
||||
rsp_read_offcenter_prefix,
|
||||
rsp_read_offcenter_prefix_len) &&
|
||||
G_N_ELEMENTS (rsp_read_offcenter_prefix)) &&
|
||||
egismoc_validate_response_suffix (buffer_in,
|
||||
length_in,
|
||||
rsp_read_offcenter_suffix,
|
||||
rsp_read_offcenter_suffix_len))
|
||||
G_N_ELEMENTS (rsp_read_offcenter_suffix)))
|
||||
error = fpi_device_retry_new (FP_DEVICE_RETRY_CENTER_FINGER);
|
||||
|
||||
/* "Sensor is dirty" */
|
||||
else if (egismoc_validate_response_prefix (buffer_in,
|
||||
length_in,
|
||||
rsp_read_dirty_prefix,
|
||||
rsp_read_dirty_prefix_len))
|
||||
G_N_ELEMENTS (rsp_read_dirty_prefix)))
|
||||
error = fpi_device_retry_new_msg (FP_DEVICE_RETRY_REMOVE_FINGER,
|
||||
"Your device is having trouble recognizing you. "
|
||||
"Make sure your sensor is clean.");
|
||||
@@ -879,7 +885,7 @@ egismoc_enroll_check_cb (FpDevice *device,
|
||||
if (egismoc_validate_response_suffix (buffer_in,
|
||||
length_in,
|
||||
rsp_check_not_yet_enrolled_suffix,
|
||||
rsp_check_not_yet_enrolled_suffix_len))
|
||||
G_N_ELEMENTS (rsp_check_not_yet_enrolled_suffix)))
|
||||
fpi_ssm_next_state (self->task_ssm);
|
||||
else
|
||||
egismoc_enroll_status_report (device, NULL, ENROLL_STATUS_DUPLICATE,
|
||||
@@ -889,7 +895,7 @@ egismoc_enroll_check_cb (FpDevice *device,
|
||||
/*
|
||||
* Builds the full "check" payload which includes identifiers for all
|
||||
* fingerprints which currently should exist on the storage. This payload is
|
||||
* used during both enrollment and verify actions.
|
||||
* used during both enrollment and identify actions.
|
||||
*/
|
||||
static guchar *
|
||||
egismoc_get_check_cmd (FpDevice *device,
|
||||
@@ -924,8 +930,8 @@ egismoc_get_check_cmd (FpDevice *device,
|
||||
/* prefix length can depend on the type */
|
||||
const gsize check_prefix_length = (fpi_device_get_driver_data (device) &
|
||||
EGISMOC_DRIVER_CHECK_PREFIX_TYPE2) ?
|
||||
cmd_check_prefix_type2_len :
|
||||
cmd_check_prefix_type1_len;
|
||||
G_N_ELEMENTS (cmd_check_prefix_type2) :
|
||||
G_N_ELEMENTS (cmd_check_prefix_type1);
|
||||
|
||||
/* total_length is the 6 various bytes plus all other prefixes/suffixes and
|
||||
* the body payload */
|
||||
@@ -933,7 +939,7 @@ egismoc_get_check_cmd (FpDevice *device,
|
||||
+ check_prefix_length
|
||||
+ EGISMOC_CMD_CHECK_SEPARATOR_LENGTH
|
||||
+ body_length
|
||||
+ cmd_check_suffix_len;
|
||||
+ G_N_ELEMENTS (cmd_check_suffix);
|
||||
|
||||
/* pre-fill entire payload with 00s */
|
||||
fpi_byte_writer_init_with_size (&writer, total_length, TRUE);
|
||||
@@ -965,10 +971,10 @@ egismoc_get_check_cmd (FpDevice *device,
|
||||
/* command prefix */
|
||||
if (fpi_device_get_driver_data (device) & EGISMOC_DRIVER_CHECK_PREFIX_TYPE2)
|
||||
written &= fpi_byte_writer_put_data (&writer, cmd_check_prefix_type2,
|
||||
cmd_check_prefix_type2_len);
|
||||
G_N_ELEMENTS (cmd_check_prefix_type2));
|
||||
else
|
||||
written &= fpi_byte_writer_put_data (&writer, cmd_check_prefix_type1,
|
||||
cmd_check_prefix_type1_len);
|
||||
G_N_ELEMENTS (cmd_check_prefix_type1));
|
||||
|
||||
/* 2-bytes size logic for counter again */
|
||||
if (self->enrolled_ids->len > 6)
|
||||
@@ -998,7 +1004,7 @@ egismoc_get_check_cmd (FpDevice *device,
|
||||
|
||||
/* command suffix */
|
||||
written &= fpi_byte_writer_put_data (&writer, cmd_check_suffix,
|
||||
cmd_check_suffix_len);
|
||||
G_N_ELEMENTS (cmd_check_suffix));
|
||||
g_assert (written);
|
||||
|
||||
if (length_out)
|
||||
@@ -1023,7 +1029,7 @@ egismoc_enroll_run_state (FpiSsm *ssm,
|
||||
{
|
||||
case ENROLL_GET_ENROLLED_IDS:
|
||||
/* get enrolled_ids from device for use in check stages below */
|
||||
egismoc_exec_cmd (device, cmd_list, cmd_list_len,
|
||||
egismoc_exec_cmd (device, cmd_list, G_N_ELEMENTS (cmd_list),
|
||||
NULL, egismoc_list_fill_enrolled_ids_cb);
|
||||
break;
|
||||
|
||||
@@ -1038,12 +1044,12 @@ egismoc_enroll_run_state (FpiSsm *ssm,
|
||||
break;
|
||||
|
||||
case ENROLL_SENSOR_RESET:
|
||||
egismoc_exec_cmd (device, cmd_sensor_reset, cmd_sensor_reset_len,
|
||||
egismoc_exec_cmd (device, cmd_sensor_reset, G_N_ELEMENTS (cmd_sensor_reset),
|
||||
NULL, egismoc_task_ssm_next_state_cb);
|
||||
break;
|
||||
|
||||
case ENROLL_SENSOR_ENROLL:
|
||||
egismoc_exec_cmd (device, cmd_sensor_enroll, cmd_sensor_enroll_len,
|
||||
egismoc_exec_cmd (device, cmd_sensor_enroll, G_N_ELEMENTS (cmd_sensor_enroll),
|
||||
NULL, egismoc_task_ssm_next_state_cb);
|
||||
break;
|
||||
|
||||
@@ -1052,7 +1058,7 @@ egismoc_enroll_run_state (FpiSsm *ssm,
|
||||
break;
|
||||
|
||||
case ENROLL_SENSOR_CHECK:
|
||||
egismoc_exec_cmd (device, cmd_sensor_check, cmd_sensor_check_len,
|
||||
egismoc_exec_cmd (device, cmd_sensor_check, G_N_ELEMENTS (cmd_sensor_check),
|
||||
NULL, egismoc_task_ssm_next_state_cb);
|
||||
break;
|
||||
|
||||
@@ -1063,17 +1069,17 @@ egismoc_enroll_run_state (FpiSsm *ssm,
|
||||
break;
|
||||
|
||||
case ENROLL_START:
|
||||
egismoc_exec_cmd (device, cmd_enroll_starting, cmd_enroll_starting_len,
|
||||
egismoc_exec_cmd (device, cmd_enroll_starting, G_N_ELEMENTS (cmd_enroll_starting),
|
||||
NULL, egismoc_task_ssm_next_state_cb);
|
||||
break;
|
||||
|
||||
case ENROLL_CAPTURE_SENSOR_RESET:
|
||||
egismoc_exec_cmd (device, cmd_sensor_reset, cmd_sensor_reset_len,
|
||||
egismoc_exec_cmd (device, cmd_sensor_reset, G_N_ELEMENTS (cmd_sensor_reset),
|
||||
NULL, egismoc_task_ssm_next_state_cb);
|
||||
break;
|
||||
|
||||
case ENROLL_CAPTURE_SENSOR_START_CAPTURE:
|
||||
egismoc_exec_cmd (device, cmd_sensor_start_capture, cmd_sensor_start_capture_len,
|
||||
egismoc_exec_cmd (device, cmd_sensor_start_capture, G_N_ELEMENTS (cmd_sensor_start_capture),
|
||||
NULL,
|
||||
egismoc_task_ssm_next_state_cb);
|
||||
break;
|
||||
@@ -1083,12 +1089,12 @@ egismoc_enroll_run_state (FpiSsm *ssm,
|
||||
break;
|
||||
|
||||
case ENROLL_CAPTURE_READ_RESPONSE:
|
||||
egismoc_exec_cmd (device, cmd_read_capture, cmd_read_capture_len,
|
||||
egismoc_exec_cmd (device, cmd_read_capture, G_N_ELEMENTS (cmd_read_capture),
|
||||
NULL, egismoc_read_capture_cb);
|
||||
break;
|
||||
|
||||
case ENROLL_COMMIT_START:
|
||||
egismoc_exec_cmd (device, cmd_commit_starting, cmd_commit_starting_len,
|
||||
egismoc_exec_cmd (device, cmd_commit_starting, G_N_ELEMENTS (cmd_commit_starting),
|
||||
NULL, egismoc_task_ssm_next_state_cb);
|
||||
break;
|
||||
|
||||
@@ -1101,7 +1107,7 @@ egismoc_enroll_run_state (FpiSsm *ssm,
|
||||
|
||||
fpi_byte_writer_init (&writer);
|
||||
if (!fpi_byte_writer_put_data (&writer, cmd_new_print_prefix,
|
||||
cmd_new_print_prefix_len))
|
||||
G_N_ELEMENTS (cmd_new_print_prefix)))
|
||||
{
|
||||
fpi_ssm_mark_failed (ssm, fpi_device_error_new (FP_DEVICE_ERROR_PROTO));
|
||||
break;
|
||||
@@ -1120,7 +1126,7 @@ egismoc_enroll_run_state (FpiSsm *ssm,
|
||||
break;
|
||||
|
||||
case ENROLL_COMMIT_SENSOR_RESET:
|
||||
egismoc_exec_cmd (device, cmd_sensor_reset, cmd_sensor_reset_len,
|
||||
egismoc_exec_cmd (device, cmd_sensor_reset, G_N_ELEMENTS (cmd_sensor_reset),
|
||||
NULL, egismoc_task_ssm_next_state_cb);
|
||||
break;
|
||||
|
||||
@@ -1157,7 +1163,6 @@ egismoc_identify_check_cb (FpDevice *device,
|
||||
FpiDeviceEgisMoc *self = FPI_DEVICE_EGISMOC (device);
|
||||
gchar device_print_id[EGISMOC_FINGERPRINT_DATA_SIZE];
|
||||
FpPrint *print = NULL;
|
||||
FpPrint *verify_print = NULL;
|
||||
GPtrArray *prints;
|
||||
gboolean found = FALSE;
|
||||
guint index;
|
||||
@@ -1172,12 +1177,20 @@ egismoc_identify_check_cb (FpDevice *device,
|
||||
if (egismoc_validate_response_suffix (buffer_in,
|
||||
length_in,
|
||||
rsp_identify_match_suffix,
|
||||
rsp_identify_match_suffix_len))
|
||||
G_N_ELEMENTS (rsp_identify_match_suffix)))
|
||||
{
|
||||
/*
|
||||
On success, there is a 32 byte array of "something"(?) in chars 14-45
|
||||
and then the 32 byte array ID of the matched print comes as chars 46-77
|
||||
*/
|
||||
if (length_in < EGISMOC_IDENTIFY_RESPONSE_PRINT_ID_OFFSET + EGISMOC_FINGERPRINT_DATA_SIZE)
|
||||
{
|
||||
fpi_ssm_mark_failed (self->task_ssm,
|
||||
fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
|
||||
"Identify response too short"));
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy (device_print_id,
|
||||
buffer_in + EGISMOC_IDENTIFY_RESPONSE_PRINT_ID_OFFSET,
|
||||
EGISMOC_FINGERPRINT_DATA_SIZE);
|
||||
@@ -1199,42 +1212,26 @@ egismoc_identify_check_cb (FpDevice *device,
|
||||
|
||||
fp_info ("Identify successful for: %s", fp_print_get_description (print));
|
||||
|
||||
if (fpi_device_get_current_action (device) == FPI_DEVICE_ACTION_IDENTIFY)
|
||||
{
|
||||
fpi_device_get_identify_data (device, &prints);
|
||||
found = g_ptr_array_find_with_equal_func (prints,
|
||||
print,
|
||||
(GEqualFunc) fp_print_equal,
|
||||
&index);
|
||||
fpi_device_get_identify_data (device, &prints);
|
||||
found = g_ptr_array_find_with_equal_func (prints,
|
||||
print,
|
||||
(GEqualFunc) fp_print_equal,
|
||||
&index);
|
||||
|
||||
if (found)
|
||||
fpi_device_identify_report (device, g_ptr_array_index (prints, index), print, NULL);
|
||||
else
|
||||
fpi_device_identify_report (device, NULL, print, NULL);
|
||||
}
|
||||
if (found)
|
||||
fpi_device_identify_report (device, g_ptr_array_index (prints, index), print, NULL);
|
||||
else
|
||||
{
|
||||
fpi_device_get_verify_data (device, &verify_print);
|
||||
fp_info ("Verifying against: %s", fp_print_get_description (verify_print));
|
||||
|
||||
if (fp_print_equal (verify_print, print))
|
||||
fpi_device_verify_report (device, FPI_MATCH_SUCCESS, print, NULL);
|
||||
else
|
||||
fpi_device_verify_report (device, FPI_MATCH_FAIL, print, NULL);
|
||||
}
|
||||
fpi_device_identify_report (device, NULL, print, NULL);
|
||||
}
|
||||
/* If device was successfully read but it was a "not matched" */
|
||||
else if (egismoc_validate_response_suffix (buffer_in,
|
||||
length_in,
|
||||
rsp_identify_notmatch_suffix,
|
||||
rsp_identify_notmatch_suffix_len))
|
||||
G_N_ELEMENTS (rsp_identify_notmatch_suffix)))
|
||||
{
|
||||
fp_info ("Print was not identified by the device");
|
||||
|
||||
if (fpi_device_get_current_action (device) == FPI_DEVICE_ACTION_VERIFY)
|
||||
fpi_device_verify_report (device, FPI_MATCH_FAIL, NULL, NULL);
|
||||
else
|
||||
fpi_device_identify_report (device, NULL, NULL, NULL);
|
||||
fpi_device_identify_report (device, NULL, NULL, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1259,7 +1256,7 @@ egismoc_identify_run_state (FpiSsm *ssm,
|
||||
{
|
||||
case IDENTIFY_GET_ENROLLED_IDS:
|
||||
/* get enrolled_ids from device for use in check stages below */
|
||||
egismoc_exec_cmd (device, cmd_list, cmd_list_len,
|
||||
egismoc_exec_cmd (device, cmd_list, G_N_ELEMENTS (cmd_list),
|
||||
NULL, egismoc_list_fill_enrolled_ids_cb);
|
||||
break;
|
||||
|
||||
@@ -1274,12 +1271,12 @@ egismoc_identify_run_state (FpiSsm *ssm,
|
||||
break;
|
||||
|
||||
case IDENTIFY_SENSOR_RESET:
|
||||
egismoc_exec_cmd (device, cmd_sensor_reset, cmd_sensor_reset_len,
|
||||
egismoc_exec_cmd (device, cmd_sensor_reset, G_N_ELEMENTS (cmd_sensor_reset),
|
||||
NULL, egismoc_task_ssm_next_state_cb);
|
||||
break;
|
||||
|
||||
case IDENTIFY_SENSOR_IDENTIFY:
|
||||
egismoc_exec_cmd (device, cmd_sensor_identify, cmd_sensor_identify_len,
|
||||
egismoc_exec_cmd (device, cmd_sensor_identify, G_N_ELEMENTS (cmd_sensor_identify),
|
||||
NULL, egismoc_task_ssm_next_state_cb);
|
||||
break;
|
||||
|
||||
@@ -1288,7 +1285,7 @@ egismoc_identify_run_state (FpiSsm *ssm,
|
||||
break;
|
||||
|
||||
case IDENTIFY_SENSOR_CHECK:
|
||||
egismoc_exec_cmd (device, cmd_sensor_check, cmd_sensor_check_len,
|
||||
egismoc_exec_cmd (device, cmd_sensor_check, G_N_ELEMENTS (cmd_sensor_check),
|
||||
NULL, egismoc_task_ssm_next_state_cb);
|
||||
break;
|
||||
|
||||
@@ -1299,24 +1296,21 @@ egismoc_identify_run_state (FpiSsm *ssm,
|
||||
break;
|
||||
|
||||
case IDENTIFY_COMPLETE_SENSOR_RESET:
|
||||
egismoc_exec_cmd (device, cmd_sensor_reset, cmd_sensor_reset_len,
|
||||
egismoc_exec_cmd (device, cmd_sensor_reset, G_N_ELEMENTS (cmd_sensor_reset),
|
||||
NULL, egismoc_task_ssm_next_state_cb);
|
||||
break;
|
||||
|
||||
/*
|
||||
* In Windows, the driver seems at this point to then immediately take
|
||||
* another read from the sensor; this is suspected to be an on-chip
|
||||
* "verify". However, because the user's finger is still on the sensor from
|
||||
* "identify". However, because the user's finger is still on the sensor from
|
||||
* the identify, then it seems to always return positive. We will consider
|
||||
* this extra step unnecessary and just skip it in this driver. This driver
|
||||
* will instead handle matching of the FpPrint from the gallery in the
|
||||
* "verify" case of the callback egismoc_identify_check_cb.
|
||||
* callback egismoc_identify_check_cb.
|
||||
*/
|
||||
case IDENTIFY_COMPLETE:
|
||||
if (fpi_device_get_current_action (device) == FPI_DEVICE_ACTION_IDENTIFY)
|
||||
fpi_device_identify_complete (device, NULL);
|
||||
else
|
||||
fpi_device_verify_complete (device, NULL);
|
||||
fpi_device_identify_complete (device, NULL);
|
||||
|
||||
fpi_ssm_mark_completed (ssm);
|
||||
break;
|
||||
@@ -1324,9 +1318,9 @@ egismoc_identify_run_state (FpiSsm *ssm,
|
||||
}
|
||||
|
||||
static void
|
||||
egismoc_identify_verify (FpDevice *device)
|
||||
egismoc_identify (FpDevice *device)
|
||||
{
|
||||
fp_dbg ("Identify or Verify");
|
||||
fp_dbg ("Identify");
|
||||
FpiDeviceEgisMoc *self = FPI_DEVICE_EGISMOC (device);
|
||||
|
||||
g_assert (self->task_ssm == NULL);
|
||||
@@ -1357,7 +1351,7 @@ egismoc_fw_version_cb (FpDevice *device,
|
||||
if (!egismoc_validate_response_suffix (buffer_in,
|
||||
length_in,
|
||||
rsp_fw_version_suffix,
|
||||
rsp_fw_version_suffix_len))
|
||||
G_N_ELEMENTS (rsp_fw_version_suffix)))
|
||||
{
|
||||
fpi_ssm_mark_failed (self->task_ssm,
|
||||
fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
|
||||
@@ -1372,9 +1366,18 @@ egismoc_fw_version_cb (FpDevice *device,
|
||||
* come with every payload Then we will also skip the carriage return and take
|
||||
* all but the last 2 bytes as the FW Version
|
||||
*/
|
||||
prefix_length = egismoc_read_prefix_len + 2 + 3 + 1;
|
||||
prefix_length = G_N_ELEMENTS (egismoc_read_prefix) + 2 + 3 + 1;
|
||||
|
||||
if (length_in < prefix_length + G_N_ELEMENTS (rsp_fw_version_suffix))
|
||||
{
|
||||
fpi_ssm_mark_failed (self->task_ssm,
|
||||
fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
|
||||
"Firmware version response too short"));
|
||||
return;
|
||||
}
|
||||
|
||||
fw_version_start = buffer_in + prefix_length;
|
||||
fw_version_length = length_in - prefix_length - rsp_fw_version_suffix_len;
|
||||
fw_version_length = length_in - prefix_length - G_N_ELEMENTS (rsp_fw_version_suffix);
|
||||
fw_version = g_strndup ((gchar *) fw_version_start, fw_version_length);
|
||||
|
||||
fp_info ("Device firmware version is %s", fw_version);
|
||||
@@ -1448,7 +1451,7 @@ egismoc_dev_init_handler (FpiSsm *ssm,
|
||||
break;
|
||||
|
||||
case DEV_GET_FW_VERSION:
|
||||
egismoc_exec_cmd (device, cmd_fw_version, cmd_fw_version_len,
|
||||
egismoc_exec_cmd (device, cmd_fw_version, G_N_ELEMENTS (cmd_fw_version),
|
||||
NULL, egismoc_fw_version_cb);
|
||||
return;
|
||||
|
||||
@@ -1619,8 +1622,7 @@ fpi_device_egismoc_class_init (FpiDeviceEgisMocClass *klass)
|
||||
dev_class->cancel = egismoc_cancel;
|
||||
dev_class->suspend = egismoc_suspend;
|
||||
dev_class->close = egismoc_close;
|
||||
dev_class->identify = egismoc_identify_verify;
|
||||
dev_class->verify = egismoc_identify_verify;
|
||||
dev_class->identify = egismoc_identify;
|
||||
dev_class->enroll = egismoc_enroll;
|
||||
dev_class->delete = egismoc_delete;
|
||||
dev_class->clear_storage = egismoc_clear_storage;
|
||||
|
||||
@@ -59,59 +59,39 @@ G_DECLARE_FINAL_TYPE (FpiDeviceEgisMoc, fpi_device_egismoc, FPI, DEVICE_EGISMOC,
|
||||
/* standard prefixes for all read/writes */
|
||||
|
||||
static guchar egismoc_write_prefix[] = {'E', 'G', 'I', 'S', 0x00, 0x00, 0x00, 0x01};
|
||||
static gsize egismoc_write_prefix_len = sizeof (egismoc_write_prefix) / sizeof (egismoc_write_prefix[0]);
|
||||
|
||||
static guchar egismoc_read_prefix[] = {'S', 'I', 'G', 'E', 0x00, 0x00, 0x00, 0x01};
|
||||
static gsize egismoc_read_prefix_len = sizeof (egismoc_read_prefix) / sizeof (egismoc_read_prefix[0]);
|
||||
|
||||
|
||||
/* hard-coded command payloads */
|
||||
|
||||
static guchar cmd_fw_version[] = {0x00, 0x00, 0x00, 0x07, 0x50, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x0c};
|
||||
static gsize cmd_fw_version_len = sizeof (cmd_fw_version) / sizeof (cmd_fw_version[0]);
|
||||
static guchar rsp_fw_version_suffix[] = {0x90, 0x00};
|
||||
static gsize rsp_fw_version_suffix_len = sizeof (rsp_fw_version_suffix) / sizeof (rsp_fw_version_suffix[0]);
|
||||
|
||||
static guchar cmd_list[] = {0x00, 0x00, 0x00, 0x07, 0x50, 0x19, 0x04, 0x00, 0x00, 0x01, 0x40};
|
||||
static gsize cmd_list_len = sizeof (cmd_list) / sizeof (cmd_list[0]);
|
||||
|
||||
static guchar cmd_sensor_reset[] = {0x00, 0x00, 0x00, 0x04, 0x50, 0x1a, 0x00, 0x00};
|
||||
static gsize cmd_sensor_reset_len = sizeof (cmd_sensor_reset) / sizeof (cmd_sensor_reset[0]);
|
||||
|
||||
static guchar cmd_sensor_check[] = {0x00, 0x00, 0x00, 0x04, 0x50, 0x17, 0x02, 0x00};
|
||||
static gsize cmd_sensor_check_len = sizeof (cmd_sensor_check) / sizeof (cmd_sensor_check[0]);
|
||||
|
||||
static guchar cmd_sensor_identify[] = {0x00, 0x00, 0x00, 0x04, 0x50, 0x17, 0x01, 0x01};
|
||||
static gsize cmd_sensor_identify_len = sizeof (cmd_sensor_identify) / sizeof (cmd_sensor_identify[0]);
|
||||
static guchar rsp_identify_match_suffix[] = {0x90, 0x00};
|
||||
static gsize rsp_identify_match_suffix_len = sizeof (rsp_identify_match_suffix) / sizeof (rsp_identify_match_suffix[0]);
|
||||
static guchar rsp_identify_notmatch_suffix[] = {0x90, 0x04};
|
||||
static gsize rsp_identify_notmatch_suffix_len = sizeof (rsp_identify_notmatch_suffix) / sizeof (rsp_identify_notmatch_suffix[0]);
|
||||
|
||||
static guchar cmd_sensor_enroll[] = {0x00, 0x00, 0x00, 0x04, 0x50, 0x17, 0x01, 0x00};
|
||||
static gsize cmd_sensor_enroll_len = sizeof (cmd_sensor_enroll) / sizeof (cmd_sensor_enroll[0]);
|
||||
|
||||
static guchar cmd_enroll_starting[] = {0x00, 0x00, 0x00, 0x07, 0x50, 0x16, 0x01, 0x00, 0x00, 0x00, 0x20};
|
||||
static gsize cmd_enroll_starting_len = sizeof (cmd_enroll_starting) / sizeof (cmd_enroll_starting[0]);
|
||||
|
||||
static guchar cmd_sensor_start_capture[] = {0x00, 0x00, 0x00, 0x04, 0x50, 0x16, 0x02, 0x01};
|
||||
static gsize cmd_sensor_start_capture_len = sizeof (cmd_sensor_start_capture) / sizeof (cmd_sensor_start_capture[0]);
|
||||
|
||||
static guchar cmd_read_capture[] = {0x00, 0x00, 0x00, 0x07, 0x50, 0x16, 0x02, 0x02, 0x00, 0x00, 0x02};
|
||||
static gsize cmd_read_capture_len = sizeof (cmd_read_capture) / sizeof (cmd_read_capture[0]);
|
||||
static guchar rsp_read_success_prefix[] = {0x00, 0x00, 0x00, 0x04};
|
||||
static gsize rsp_read_success_prefix_len = sizeof (rsp_read_success_prefix) / sizeof (rsp_read_success_prefix[0]);
|
||||
static guchar rsp_read_success_suffix[] = {0x90, 0x00};
|
||||
static gsize rsp_read_success_suffix_len = sizeof (rsp_read_success_suffix) / sizeof (rsp_read_success_suffix[0]);
|
||||
static guchar rsp_read_offcenter_prefix[] = {0x00, 0x00, 0x00, 0x04};
|
||||
static gsize rsp_read_offcenter_prefix_len = sizeof (rsp_read_offcenter_prefix) / sizeof (rsp_read_offcenter_prefix[0]);
|
||||
static guchar rsp_read_offcenter_suffix[] = {0x64, 0x91};
|
||||
static gsize rsp_read_offcenter_suffix_len = sizeof (rsp_read_offcenter_suffix) / sizeof (rsp_read_offcenter_suffix[0]);
|
||||
static guchar rsp_read_dirty_prefix[] = {0x00, 0x00, 0x00, 0x02, 0x64};
|
||||
static gsize rsp_read_dirty_prefix_len = sizeof (rsp_read_dirty_prefix) / sizeof (rsp_read_dirty_prefix[0]);
|
||||
|
||||
static guchar cmd_commit_starting[] = {0x00, 0x00, 0x00, 0x07, 0x50, 0x16, 0x05, 0x00, 0x00, 0x00, 0x20};
|
||||
static gsize cmd_commit_starting_len = sizeof (cmd_commit_starting) / sizeof (cmd_commit_starting[0]);
|
||||
|
||||
|
||||
/* commands which exist on the device but are currently not used */
|
||||
@@ -134,21 +114,14 @@ static gsize cmd_commit_starting_len = sizeof (cmd_commit_starting) / sizeof (cm
|
||||
#define EGISMOC_CMD_CHECK_SEPARATOR_LENGTH 32
|
||||
|
||||
static guchar cmd_new_print_prefix[] = {0x00, 0x00, 0x00, 0x27, 0x50, 0x16, 0x03, 0x00, 0x00, 0x00, 0x20};
|
||||
static gsize cmd_new_print_prefix_len = sizeof (cmd_new_print_prefix) / sizeof (cmd_new_print_prefix[0]);
|
||||
|
||||
static guchar cmd_delete_prefix[] = {0x50, 0x18, 0x04, 0x00, 0x00};
|
||||
static gsize cmd_delete_prefix_len = sizeof (cmd_delete_prefix) / sizeof (cmd_delete_prefix[0]);
|
||||
static guchar rsp_delete_success_prefix[] = {0x00, 0x00, 0x00, 0x02, 0x90, 0x00};
|
||||
static gsize rsp_delete_success_prefix_len = sizeof (rsp_delete_success_prefix) / sizeof (rsp_delete_success_prefix[0]);
|
||||
|
||||
static guchar cmd_check_prefix_type1[] = {0x50, 0x17, 0x03, 0x00, 0x00};
|
||||
static gsize cmd_check_prefix_type1_len = sizeof (cmd_check_prefix_type1) / sizeof (cmd_check_prefix_type1[0]);
|
||||
static guchar cmd_check_prefix_type2[] = {0x50, 0x17, 0x03, 0x80, 0x00};
|
||||
static gsize cmd_check_prefix_type2_len = sizeof (cmd_check_prefix_type2) / sizeof (cmd_check_prefix_type2[0]);
|
||||
static guchar cmd_check_suffix[] = {0x00, 0x40};
|
||||
static gsize cmd_check_suffix_len = sizeof (cmd_check_suffix) / sizeof (cmd_check_suffix[0]);
|
||||
static guchar rsp_check_not_yet_enrolled_suffix[] = {0x90, 0x04};
|
||||
static gsize rsp_check_not_yet_enrolled_suffix_len = sizeof (rsp_check_not_yet_enrolled_suffix) / sizeof (rsp_check_not_yet_enrolled_suffix[0]);
|
||||
|
||||
|
||||
/* SSM task states and various status enums */
|
||||
|
||||
@@ -146,7 +146,7 @@ elan_save_frame (FpiDeviceElan *self, unsigned short *frame)
|
||||
raw_idx = frame_margin + y + x * raw_height;
|
||||
frame_idx = x + y * frame_width;
|
||||
frame[frame_idx] =
|
||||
((unsigned short *) self->last_read)[raw_idx];
|
||||
GUINT16_FROM_LE (((unsigned short *) self->last_read)[raw_idx]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -251,7 +251,12 @@ elan_process_frame_linear (unsigned short *raw_frame,
|
||||
max = raw_frame[i];
|
||||
}
|
||||
|
||||
g_assert (max != min);
|
||||
if (max == min)
|
||||
{
|
||||
memset (frame->data, 0, frame_size);
|
||||
*frames = g_slist_prepend (*frames, frame);
|
||||
g_return_if_reached ();
|
||||
}
|
||||
|
||||
unsigned short px;
|
||||
|
||||
@@ -287,6 +292,11 @@ elan_process_frame_thirds (unsigned short *raw_frame,
|
||||
lvl3 = sorted[frame_size - 1];
|
||||
g_free (sorted);
|
||||
|
||||
/* Ensure levels are strictly monotonic to prevent division by zero */
|
||||
lvl1 = MAX (lvl1, lvl0 + 1);
|
||||
lvl2 = MAX (lvl2, lvl1 + 1);
|
||||
lvl3 = MAX (lvl3, lvl2 + 1);
|
||||
|
||||
unsigned short px;
|
||||
|
||||
for (int i = 0; i < frame_size; i++)
|
||||
|
||||
@@ -41,6 +41,7 @@ static const FpIdEntry id_table[] = {
|
||||
{ .vid = 0x04f3, .pid = 0x0ca8, },
|
||||
{ .vid = 0x04f3, .pid = 0x0cb0, },
|
||||
{ .vid = 0x04f3, .pid = 0x0cb2, },
|
||||
{ .vid = 0x04f3, .pid = 0x0cb6, },
|
||||
{ .vid = 0, .pid = 0, .driver_data = 0 }, /* terminating entry */
|
||||
};
|
||||
|
||||
@@ -390,11 +391,20 @@ elanmoc_enroll_cb (FpiDeviceElanmoc *self,
|
||||
}
|
||||
|
||||
if (self->num_frames == self->max_moc_enroll_time && buffer_in[1] == ELAN_MSG_OK)
|
||||
fpi_ssm_next_state (self->task_ssm);
|
||||
{
|
||||
fpi_ssm_next_state (self->task_ssm);
|
||||
}
|
||||
else if (self->num_frames < self->max_moc_enroll_time)
|
||||
fpi_ssm_jump_to_state (self->task_ssm, MOC_ENROLL_WAIT_FINGER);
|
||||
{
|
||||
fpi_ssm_jump_to_state (self->task_ssm, MOC_ENROLL_WAIT_FINGER);
|
||||
}
|
||||
else
|
||||
fpi_ssm_mark_failed (self->task_ssm, error);
|
||||
{
|
||||
fpi_ssm_mark_failed (self->task_ssm,
|
||||
fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
|
||||
"Enrollment failed (status 0x%02x)",
|
||||
buffer_in[1]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -639,7 +649,6 @@ elanmoc_match_report_cb (FpiDeviceElanmoc *self,
|
||||
{
|
||||
FpDevice *device = FP_DEVICE (self);
|
||||
FpPrint *print = NULL;
|
||||
FpPrint *verify_print = NULL;
|
||||
GPtrArray *prints;
|
||||
gboolean found = FALSE;
|
||||
guint index;
|
||||
@@ -668,31 +677,18 @@ elanmoc_match_report_cb (FpiDeviceElanmoc *self,
|
||||
|
||||
fp_info ("Verify/Identify successful for: %s", fp_print_get_description (print));
|
||||
|
||||
if (fpi_device_get_current_action (device) == FPI_DEVICE_ACTION_IDENTIFY)
|
||||
{
|
||||
fpi_device_get_identify_data (device, &prints);
|
||||
found = g_ptr_array_find_with_equal_func (prints,
|
||||
print,
|
||||
(GEqualFunc) fp_print_equal,
|
||||
&index);
|
||||
fpi_device_get_identify_data (device, &prints);
|
||||
found = g_ptr_array_find_with_equal_func (prints,
|
||||
print,
|
||||
(GEqualFunc) fp_print_equal,
|
||||
&index);
|
||||
|
||||
if (found)
|
||||
fpi_device_identify_report (device, g_ptr_array_index (prints, index), print, NULL);
|
||||
else
|
||||
fpi_device_identify_report (device, NULL, print, NULL);
|
||||
|
||||
fpi_device_identify_complete (device, NULL);
|
||||
}
|
||||
if (found)
|
||||
fpi_device_identify_report (device, g_ptr_array_index (prints, index), print, NULL);
|
||||
else
|
||||
{
|
||||
fpi_device_get_verify_data (device, &verify_print);
|
||||
fpi_device_identify_report (device, NULL, print, NULL);
|
||||
|
||||
if (fp_print_equal (verify_print, print))
|
||||
fpi_device_verify_report (device, FPI_MATCH_SUCCESS, print, NULL);
|
||||
else
|
||||
fpi_device_verify_report (device, FPI_MATCH_FAIL, print, NULL);
|
||||
fpi_device_verify_complete (device, NULL);
|
||||
}
|
||||
fpi_device_identify_complete (device, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -704,10 +700,7 @@ identify_status_report (FpiDeviceElanmoc *self, int verify_status_id,
|
||||
|
||||
if (error)
|
||||
{
|
||||
if (fpi_device_get_current_action (device) == FPI_DEVICE_ACTION_VERIFY)
|
||||
fpi_device_verify_complete (device, error);
|
||||
else
|
||||
fpi_device_identify_complete (device, error);
|
||||
fpi_device_identify_complete (device, error);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -717,16 +710,8 @@ identify_status_report (FpiDeviceElanmoc *self, int verify_status_id,
|
||||
{
|
||||
if (data == ELAN_MSG_VERIFY_ERR)
|
||||
{
|
||||
if (fpi_device_get_current_action (device) == FPI_DEVICE_ACTION_VERIFY)
|
||||
{
|
||||
fpi_device_verify_report (device, FPI_MATCH_FAIL, NULL, NULL);
|
||||
fpi_device_verify_complete (device, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
fpi_device_identify_report (device, NULL, NULL, NULL);
|
||||
fpi_device_identify_complete (device, NULL);
|
||||
}
|
||||
fpi_device_identify_report (device, NULL, NULL, NULL);
|
||||
fpi_device_identify_complete (device, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -745,23 +730,15 @@ identify_status_report (FpiDeviceElanmoc *self, int verify_status_id,
|
||||
retry_error = fpi_device_retry_new (FP_DEVICE_RETRY_GENERAL);
|
||||
}
|
||||
|
||||
if (fpi_device_get_current_action (device) == FPI_DEVICE_ACTION_VERIFY)
|
||||
{
|
||||
fpi_device_verify_report (device, FPI_MATCH_ERROR, NULL, retry_error);
|
||||
fpi_device_verify_complete (device, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
fpi_device_identify_report (device, NULL, NULL, retry_error);
|
||||
fpi_device_identify_complete (device, NULL);
|
||||
}
|
||||
fpi_device_identify_report (device, NULL, NULL, retry_error);
|
||||
fpi_device_identify_complete (device, NULL);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case RSP_VERIFY_OK:
|
||||
{
|
||||
fp_dbg ("Verify was successful! for user: %d mesg_code: %d ", data, verify_status_id);
|
||||
fp_dbg ("Identify was successful! for user: %d mesg_code: %d ", data, verify_status_id);
|
||||
cmd_buf = elanmoc_compose_cmd (&elanmoc_get_userid_cmd);
|
||||
cmd_buf[2] = data;
|
||||
elanmoc_get_cmd (device, cmd_buf, elanmoc_get_userid_cmd.cmd_len, elanmoc_get_userid_cmd.resp_len, 0, elanmoc_match_report_cb);
|
||||
@@ -815,7 +792,7 @@ elan_identify_run_state (FpiSsm *ssm, FpDevice *dev)
|
||||
break;
|
||||
|
||||
case IDENTIFY_WAIT_FINGER:
|
||||
fp_info ("elanmoc %s VERIFY_WAIT_FINGER", __func__);
|
||||
fp_info ("elanmoc %s IDENTIFY_WAIT_FINGER", __func__);
|
||||
cmd_buf = elanmoc_compose_cmd (&elanmoc_verify_cmd);
|
||||
elanmoc_get_cmd (dev, cmd_buf, elanmoc_verify_cmd.cmd_len, elanmoc_verify_cmd.resp_len, 1, elanmoc_identify_cb);
|
||||
break;
|
||||
@@ -1175,7 +1152,6 @@ fpi_device_elanmoc_class_init (FpiDeviceElanmocClass *klass)
|
||||
|
||||
dev_class->open = elanmoc_open;
|
||||
dev_class->close = elanmoc_close;
|
||||
dev_class->verify = elanmoc_identify;
|
||||
dev_class->enroll = elanmoc_enroll;
|
||||
dev_class->identify = elanmoc_identify;
|
||||
dev_class->delete = elanmoc_delete_print;
|
||||
|
||||
@@ -23,9 +23,9 @@
|
||||
#include "drivers_api.h"
|
||||
#include "elanspi.h"
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <linux/hidraw.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
@@ -338,7 +338,14 @@ msg_parse_regs (FpiDeviceEtes603 *dev)
|
||||
struct egis_msg *msg_req = dev->req;
|
||||
struct egis_msg *msg_ans = dev->ans;
|
||||
|
||||
g_return_val_if_fail (dev->ans_len >= MSG_HDR_SIZE, -1);
|
||||
|
||||
n_args = dev->ans_len - MSG_HDR_SIZE;
|
||||
if (n_args > REG_MAX)
|
||||
{
|
||||
g_warn_if_reached ();
|
||||
n_args = REG_MAX;
|
||||
}
|
||||
|
||||
if (msg_header_check (msg_ans))
|
||||
return -1;
|
||||
@@ -575,12 +582,24 @@ static void
|
||||
process_removefpi_end (FpiDeviceEtes603 *dev)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
/* Need at least the 2-line empty pattern to compare against. */
|
||||
if (dev->fp_height < 2)
|
||||
g_return_if_reached ();
|
||||
|
||||
/* 2 last lines with Fly-Estimation are the empty pattern. */
|
||||
guint8 *pattern = dev->fp + (dev->fp_height - 2) * FE_WIDTH / 2;
|
||||
|
||||
for (i = 2; i < dev->fp_height; i += 2)
|
||||
if (memcmp (pattern, pattern - (i * FE_WIDTH / 2), FE_WIDTH))
|
||||
break;
|
||||
|
||||
if (i > dev->fp_height)
|
||||
{
|
||||
g_warn_if_reached ();
|
||||
i = dev->fp_height;
|
||||
}
|
||||
|
||||
dev->fp_height -= i;
|
||||
fp_dbg ("Removing %d empty lines from image", i - 2);
|
||||
}
|
||||
|
||||
@@ -460,15 +460,16 @@ get_g_usb_device_direction_des (GUsbDeviceDirection dir)
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
usb_claim_interface_probe (FpDevice *device, int claim, GError **error)
|
||||
static gboolean
|
||||
usb_claim_interface_probe (FpDevice *device, gboolean claim, GError **error)
|
||||
{
|
||||
g_autoptr(GPtrArray) interfaces = NULL;
|
||||
FpiDeviceFocaltechMoc *self = FPI_DEVICE_FOCALTECH_MOC (device);
|
||||
int ret = -1;
|
||||
int i;
|
||||
|
||||
interfaces = g_usb_device_get_interfaces (fpi_device_get_usb_device (device), error);
|
||||
if (interfaces == NULL)
|
||||
return FALSE;
|
||||
|
||||
for (i = 0; i < interfaces->len; i++)
|
||||
{
|
||||
@@ -480,11 +481,9 @@ usb_claim_interface_probe (FpDevice *device, int claim, GError **error)
|
||||
g_usb_interface_get_subclass (cur_iface),
|
||||
g_usb_interface_get_protocol (cur_iface));
|
||||
|
||||
if (claim == 1)
|
||||
if (claim)
|
||||
{
|
||||
int j;
|
||||
|
||||
for (j = 0; j < endpoints->len; j++)
|
||||
for (int j = 0; j < endpoints->len; j++)
|
||||
{
|
||||
GUsbEndpoint *endpoint = g_ptr_array_index (endpoints, j);
|
||||
GBytes *bytes = g_usb_endpoint_get_extra (endpoint);
|
||||
@@ -511,21 +510,17 @@ usb_claim_interface_probe (FpDevice *device, int claim, GError **error)
|
||||
if (!g_usb_device_claim_interface (fpi_device_get_usb_device (device),
|
||||
g_usb_interface_get_number (cur_iface),
|
||||
0, error))
|
||||
return ret;
|
||||
return FALSE;
|
||||
}
|
||||
else if (!g_usb_device_release_interface (fpi_device_get_usb_device (device),
|
||||
g_usb_interface_get_number (cur_iface),
|
||||
0, error))
|
||||
{
|
||||
return ret;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
||||
return ret;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -534,7 +529,7 @@ task_ssm_init_done (FpiSsm *ssm, FpDevice *device, GError *error)
|
||||
FpiDeviceFocaltechMoc *self = FPI_DEVICE_FOCALTECH_MOC (device);
|
||||
|
||||
if (error)
|
||||
usb_claim_interface_probe (device, 0, &error);
|
||||
usb_claim_interface_probe (device, FALSE, NULL);
|
||||
|
||||
fpi_device_open_complete (FP_DEVICE (self), g_steal_pointer (&error));
|
||||
}
|
||||
@@ -649,8 +644,8 @@ dev_init_handler (FpiSsm *ssm, FpDevice *device)
|
||||
static void
|
||||
focaltech_moc_open (FpDevice *device)
|
||||
{
|
||||
g_autoptr(GError) error = NULL;
|
||||
FpiDeviceFocaltechMoc *self = FPI_DEVICE_FOCALTECH_MOC (device);
|
||||
GError *error = NULL;
|
||||
|
||||
if (!g_usb_device_reset (fpi_device_get_usb_device (device), &error))
|
||||
{
|
||||
@@ -658,7 +653,7 @@ focaltech_moc_open (FpDevice *device)
|
||||
return;
|
||||
}
|
||||
|
||||
if (usb_claim_interface_probe (device, 1, &error) != 0)
|
||||
if (!usb_claim_interface_probe (device, TRUE, &error))
|
||||
{
|
||||
fpi_device_open_complete (FP_DEVICE (self), g_steal_pointer (&error));
|
||||
return;
|
||||
@@ -674,12 +669,7 @@ task_ssm_exit_done (FpiSsm *ssm, FpDevice *device, GError *error)
|
||||
FpiDeviceFocaltechMoc *self = FPI_DEVICE_FOCALTECH_MOC (device);
|
||||
|
||||
if (!error)
|
||||
{
|
||||
GError *local_error = NULL;
|
||||
|
||||
if (usb_claim_interface_probe (device, 0, &local_error) < 0)
|
||||
g_propagate_error (&error, g_steal_pointer (&local_error));
|
||||
}
|
||||
usb_claim_interface_probe (device, FALSE, &error);
|
||||
|
||||
fpi_device_close_complete (FP_DEVICE (self), error);
|
||||
self->task_ssm = NULL;
|
||||
@@ -817,16 +807,8 @@ focaltech_moc_identify_capture_cb (FpiDeviceFocaltechMoc *self,
|
||||
}
|
||||
else
|
||||
{
|
||||
if (fpi_device_get_current_action (FP_DEVICE (self)) == FPI_DEVICE_ACTION_VERIFY)
|
||||
{
|
||||
fpi_device_verify_report (FP_DEVICE (self), FPI_MATCH_ERROR, NULL, error);
|
||||
fpi_device_verify_complete (FP_DEVICE (self), NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
fpi_device_identify_report (FP_DEVICE (self), NULL, NULL, error);
|
||||
fpi_device_identify_complete (FP_DEVICE (self), NULL);
|
||||
}
|
||||
fpi_device_identify_report (FP_DEVICE (self), NULL, NULL, error);
|
||||
fpi_device_identify_complete (FP_DEVICE (self), NULL);
|
||||
|
||||
fpi_ssm_mark_failed (self->task_ssm, fpi_device_retry_new (FP_DEVICE_RETRY_GENERAL));
|
||||
}
|
||||
@@ -840,50 +822,27 @@ identify_status_report (FpiDeviceFocaltechMoc *self, FpPrint *print, GError *err
|
||||
|
||||
if (print == NULL)
|
||||
{
|
||||
if (fpi_device_get_current_action (device) == FPI_DEVICE_ACTION_IDENTIFY)
|
||||
{
|
||||
fpi_device_identify_report (device, NULL, NULL, NULL);
|
||||
fpi_device_identify_complete (device, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
fpi_device_verify_report (device, FPI_MATCH_FAIL, NULL, NULL);
|
||||
fpi_device_verify_complete (device, NULL);
|
||||
}
|
||||
fpi_device_identify_report (device, NULL, NULL, NULL);
|
||||
fpi_device_identify_complete (device, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (fpi_device_get_current_action (device) == FPI_DEVICE_ACTION_IDENTIFY)
|
||||
{
|
||||
GPtrArray *prints;
|
||||
gboolean found = FALSE;
|
||||
guint index;
|
||||
GPtrArray *prints;
|
||||
gboolean found = FALSE;
|
||||
guint index;
|
||||
|
||||
fpi_device_get_identify_data (device, &prints);
|
||||
found = g_ptr_array_find_with_equal_func (prints,
|
||||
print,
|
||||
(GEqualFunc) fp_print_equal,
|
||||
&index);
|
||||
fpi_device_get_identify_data (device, &prints);
|
||||
found = g_ptr_array_find_with_equal_func (prints,
|
||||
print,
|
||||
(GEqualFunc) fp_print_equal,
|
||||
&index);
|
||||
|
||||
if (found)
|
||||
fpi_device_identify_report (device, g_ptr_array_index (prints, index), print, NULL);
|
||||
else
|
||||
fpi_device_identify_report (device, NULL, print, NULL);
|
||||
|
||||
fpi_device_identify_complete (device, NULL);
|
||||
}
|
||||
if (found)
|
||||
fpi_device_identify_report (device, g_ptr_array_index (prints, index), print, NULL);
|
||||
else
|
||||
{
|
||||
FpPrint *verify_print = NULL;
|
||||
fpi_device_get_verify_data (device, &verify_print);
|
||||
fpi_device_identify_report (device, NULL, print, NULL);
|
||||
|
||||
if (fp_print_equal (verify_print, print))
|
||||
fpi_device_verify_report (device, FPI_MATCH_SUCCESS, print, NULL);
|
||||
else
|
||||
fpi_device_verify_report (device, FPI_MATCH_FAIL, print, NULL);
|
||||
|
||||
fpi_device_verify_complete (device, NULL);
|
||||
}
|
||||
fpi_device_identify_complete (device, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2053,7 +2012,6 @@ fpi_device_focaltech_moc_class_init (FpiDeviceFocaltechMocClass *klass)
|
||||
dev_class->probe = focaltech_moc_probe;
|
||||
dev_class->open = focaltech_moc_open;
|
||||
dev_class->close = focaltech_moc_close;
|
||||
dev_class->verify = focaltech_moc_identify;
|
||||
dev_class->enroll = focaltech_moc_enroll;
|
||||
dev_class->identify = focaltech_moc_identify;
|
||||
dev_class->delete = focaltech_moc_delete_print;
|
||||
|
||||
+443
-258
File diff suppressed because it is too large
Load Diff
@@ -207,11 +207,11 @@ typedef enum {
|
||||
} FpcEnrollState;
|
||||
|
||||
typedef enum {
|
||||
FPC_VERIFY_CAPTURE = 0,
|
||||
FPC_VERIFY_GET_IMG,
|
||||
FPC_VERIFY_IDENTIFY,
|
||||
FPC_VERIFY_CANCEL,
|
||||
FPC_VERIFY_NUM_STATES,
|
||||
FPC_IDENTIFY_CAPTURE = 0,
|
||||
FPC_IDENTIFY_GET_IMG,
|
||||
FPC_IDENTIFY_IDENTIFY,
|
||||
FPC_IDENTIFY_CANCEL,
|
||||
FPC_IDENTIFY_NUM_STATES,
|
||||
} FpcVerifyState;
|
||||
|
||||
typedef enum {
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
|
||||
|
||||
|
||||
#include "glib.h"
|
||||
#define FP_COMPONENT "goodixmoc"
|
||||
|
||||
#include "drivers_api.h"
|
||||
@@ -156,8 +157,7 @@ fp_cmd_receive_cb (FpiUsbTransfer *transfer,
|
||||
return;
|
||||
}
|
||||
|
||||
reader.data = transfer->buffer;
|
||||
reader.size = transfer->actual_length;
|
||||
fpi_byte_reader_init (&reader, transfer->buffer, transfer->actual_length);
|
||||
|
||||
if (gx_proto_parse_header (&reader, &header) != 0)
|
||||
{
|
||||
@@ -167,17 +167,25 @@ fp_cmd_receive_cb (FpiUsbTransfer *transfer,
|
||||
return;
|
||||
}
|
||||
|
||||
if (!fpi_byte_reader_set_pos (&reader, PACKAGE_HEADER_SIZE + header.len))
|
||||
if (header.len < PACKAGE_CRC_SIZE ||
|
||||
!fpi_byte_reader_set_pos (&reader, PACKAGE_HEADER_SIZE + header.len - PACKAGE_CRC_SIZE))
|
||||
{
|
||||
fpi_ssm_mark_failed (transfer->ssm,
|
||||
fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
|
||||
"Package crc read failed"));
|
||||
return;
|
||||
}
|
||||
|
||||
gx_proto_crc32_calc (transfer->buffer, PACKAGE_HEADER_SIZE + header.len, (uint8_t *) &crc32_calc);
|
||||
/* Exclude the CRC from the package length */
|
||||
header.len -= PACKAGE_CRC_SIZE;
|
||||
|
||||
/* The reader is positioned right at the CRC, i.e. at the end of the data the
|
||||
* CRC is computed over, so use its position as the length. */
|
||||
gx_proto_crc32_calc (transfer->buffer, fpi_byte_reader_get_pos (&reader),
|
||||
(uint8_t *) &crc32_calc);
|
||||
|
||||
if (!fpi_byte_reader_get_uint32_le (&reader, &crc32) ||
|
||||
crc32_calc != crc32)
|
||||
GUINT32_FROM_LE (crc32_calc) != crc32)
|
||||
{
|
||||
fpi_ssm_mark_failed (transfer->ssm,
|
||||
fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
|
||||
@@ -187,9 +195,7 @@ fp_cmd_receive_cb (FpiUsbTransfer *transfer,
|
||||
|
||||
cmd = MAKE_CMD_EX (header.cmd0, header.cmd1);
|
||||
|
||||
fpi_byte_reader_set_pos (&reader, 0);
|
||||
reader.data = &transfer->buffer[PACKAGE_HEADER_SIZE];
|
||||
reader.size = header.len;
|
||||
fpi_byte_reader_init (&reader, &transfer->buffer[PACKAGE_HEADER_SIZE], header.len);
|
||||
|
||||
if (gx_proto_parse_body (cmd, &reader, &cmd_reponse) != 0)
|
||||
{
|
||||
@@ -393,13 +399,13 @@ fp_pwr_btn_shield_cb (FpiDeviceGoodixMoc *self,
|
||||
}
|
||||
/******************************************************************************
|
||||
*
|
||||
* fp_verify_xxxx Function
|
||||
* fp_identify_xxxx Function
|
||||
*
|
||||
*****************************************************************************/
|
||||
static void
|
||||
fp_verify_capture_cb (FpiDeviceGoodixMoc *self,
|
||||
gxfp_cmd_response_t *resp,
|
||||
GError *error)
|
||||
fp_identify_capture_cb (FpiDeviceGoodixMoc *self,
|
||||
gxfp_cmd_response_t *resp,
|
||||
GError *error)
|
||||
{
|
||||
if (error)
|
||||
{
|
||||
@@ -432,9 +438,9 @@ fp_verify_capture_cb (FpiDeviceGoodixMoc *self,
|
||||
}
|
||||
|
||||
static void
|
||||
fp_verify_cb (FpiDeviceGoodixMoc *self,
|
||||
gxfp_cmd_response_t *resp,
|
||||
GError *error)
|
||||
fp_identify_cb (FpiDeviceGoodixMoc *self,
|
||||
gxfp_cmd_response_t *resp,
|
||||
GError *error)
|
||||
{
|
||||
FpDevice *device = FP_DEVICE (self);
|
||||
FpPrint *new_scan = NULL;
|
||||
@@ -445,45 +451,30 @@ fp_verify_cb (FpiDeviceGoodixMoc *self,
|
||||
fpi_ssm_mark_failed (self->task_ssm, error);
|
||||
return;
|
||||
}
|
||||
|
||||
if (resp->verify.match)
|
||||
{
|
||||
GPtrArray *templates = NULL;
|
||||
guint matching_index;
|
||||
|
||||
fpi_device_get_identify_data (device, &templates);
|
||||
new_scan = fp_print_from_template (self, &resp->verify.template);
|
||||
|
||||
if (fpi_device_get_current_action (device) == FPI_DEVICE_ACTION_VERIFY)
|
||||
{
|
||||
fpi_device_get_verify_data (device, &matching);
|
||||
if (!fp_print_equal (matching, new_scan))
|
||||
matching = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
GPtrArray *templates = NULL;
|
||||
fpi_device_get_identify_data (device, &templates);
|
||||
|
||||
for (gint i = 0; i < templates->len; i++)
|
||||
{
|
||||
if (fp_print_equal (g_ptr_array_index (templates, i), new_scan))
|
||||
{
|
||||
matching = g_ptr_array_index (templates, i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (g_ptr_array_find_with_equal_func (templates, new_scan,
|
||||
(GEqualFunc) fp_print_equal,
|
||||
&matching_index))
|
||||
matching = g_ptr_array_index (templates, matching_index);
|
||||
}
|
||||
|
||||
if (fpi_device_get_current_action (device) == FPI_DEVICE_ACTION_VERIFY)
|
||||
fpi_device_verify_report (device, matching ? FPI_MATCH_SUCCESS : FPI_MATCH_FAIL, new_scan, error);
|
||||
else
|
||||
fpi_device_identify_report (device, matching, new_scan, error);
|
||||
fpi_device_identify_report (device, matching, new_scan, error);
|
||||
|
||||
fpi_ssm_next_state (self->task_ssm);
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
fp_verify_finger_mode_cb (FpiDeviceGoodixMoc *self,
|
||||
gxfp_cmd_response_t *resp,
|
||||
GError *error)
|
||||
fp_identify_finger_mode_cb (FpiDeviceGoodixMoc *self,
|
||||
gxfp_cmd_response_t *resp,
|
||||
GError *error)
|
||||
{
|
||||
if (error)
|
||||
{
|
||||
@@ -493,7 +484,7 @@ fp_verify_finger_mode_cb (FpiDeviceGoodixMoc *self,
|
||||
/* if reach max timeout(5sec) finger not up, try again */
|
||||
if (resp->finger_status.status == GX_ERROR_WAIT_FINGER_UP_TIMEOUT)
|
||||
{
|
||||
fpi_ssm_jump_to_state (self->task_ssm, GOODIX_VERIFY_WAIT_FINGER_UP);
|
||||
fpi_ssm_jump_to_state (self->task_ssm, GOODIX_IDENTIFY_WAIT_FINGER_UP);
|
||||
return;
|
||||
}
|
||||
else if (resp->finger_status.status != GX_SUCCESS)
|
||||
@@ -510,7 +501,7 @@ fp_verify_finger_mode_cb (FpiDeviceGoodixMoc *self,
|
||||
}
|
||||
|
||||
static void
|
||||
fp_verify_sm_run_state (FpiSsm *ssm, FpDevice *device)
|
||||
fp_identify_sm_run_state (FpiSsm *ssm, FpDevice *device)
|
||||
{
|
||||
FpiDeviceGoodixMoc *self = FPI_DEVICE_GOODIXMOC (device);
|
||||
guint8 param[3] = { 0 };
|
||||
@@ -522,7 +513,7 @@ fp_verify_sm_run_state (FpiSsm *ssm, FpDevice *device)
|
||||
|
||||
switch (fpi_ssm_get_cur_state (ssm))
|
||||
{
|
||||
case GOODIX_VERIFY_PWR_BTN_SHIELD_ON:
|
||||
case GOODIX_IDENTIFY_PWR_BTN_SHIELD_ON:
|
||||
goodix_sensor_cmd (self, MOC_CMD0_PWR_BTN_SHIELD, MOC_CMD1_PWR_BTN_SHIELD_ON,
|
||||
false,
|
||||
NULL,
|
||||
@@ -530,7 +521,7 @@ fp_verify_sm_run_state (FpiSsm *ssm, FpDevice *device)
|
||||
fp_pwr_btn_shield_cb);
|
||||
break;
|
||||
|
||||
case GOODIX_VERIFY_CAPTURE:
|
||||
case GOODIX_IDENTIFY_CAPTURE:
|
||||
fpi_device_report_finger_status_changes (device,
|
||||
FP_FINGER_STATUS_NEEDED,
|
||||
FP_FINGER_STATUS_NONE);
|
||||
@@ -538,29 +529,29 @@ fp_verify_sm_run_state (FpiSsm *ssm, FpDevice *device)
|
||||
true,
|
||||
(const guint8 *) ¶m,
|
||||
G_N_ELEMENTS (param),
|
||||
fp_verify_capture_cb);
|
||||
fp_identify_capture_cb);
|
||||
break;
|
||||
|
||||
case GOODIX_VERIFY_IDENTIFY:
|
||||
case GOODIX_IDENTIFY_IDENTIFY:
|
||||
goodix_sensor_cmd (self, MOC_CMD0_IDENTIFY, MOC_CMD1_DEFAULT,
|
||||
false,
|
||||
(const guint8 *) nonce,
|
||||
TEMPLATE_ID_SIZE,
|
||||
fp_verify_cb);
|
||||
fp_identify_cb);
|
||||
break;
|
||||
|
||||
case GOODIX_VERIFY_WAIT_FINGER_UP:
|
||||
case GOODIX_IDENTIFY_WAIT_FINGER_UP:
|
||||
{
|
||||
guint8 dummy = 0;
|
||||
goodix_sensor_cmd (self, MOC_CMD0_FINGER_MODE, MOC_CMD1_SET_FINGER_UP,
|
||||
true,
|
||||
&dummy,
|
||||
1,
|
||||
fp_verify_finger_mode_cb);
|
||||
fp_identify_finger_mode_cb);
|
||||
}
|
||||
break;
|
||||
|
||||
case GOODIX_VERIFY_PWR_BTN_SHIELD_OFF:
|
||||
case GOODIX_IDENTIFY_PWR_BTN_SHIELD_OFF:
|
||||
goodix_sensor_cmd (self, MOC_CMD0_PWR_BTN_SHIELD, MOC_CMD1_PWR_BTN_SHIELD_OFF,
|
||||
false,
|
||||
NULL,
|
||||
@@ -572,25 +563,16 @@ fp_verify_sm_run_state (FpiSsm *ssm, FpDevice *device)
|
||||
}
|
||||
|
||||
static void
|
||||
fp_verify_ssm_done (FpiSsm *ssm, FpDevice *dev, GError *error)
|
||||
fp_identify_ssm_done (FpiSsm *ssm, FpDevice *dev, GError *error)
|
||||
{
|
||||
FpiDeviceGoodixMoc *self = FPI_DEVICE_GOODIXMOC (dev);
|
||||
|
||||
fp_info ("Verify complete!");
|
||||
|
||||
if (error && error->domain == FP_DEVICE_RETRY)
|
||||
{
|
||||
if (fpi_device_get_current_action (dev) == FPI_DEVICE_ACTION_VERIFY)
|
||||
fpi_device_verify_report (dev, FPI_MATCH_ERROR, NULL, g_steal_pointer (&error));
|
||||
else
|
||||
fpi_device_identify_report (dev, NULL, NULL, g_steal_pointer (&error));
|
||||
}
|
||||
fpi_device_identify_report (dev, NULL, NULL, g_steal_pointer (&error));
|
||||
|
||||
if (fpi_device_get_current_action (dev) == FPI_DEVICE_ACTION_VERIFY)
|
||||
fpi_device_verify_complete (dev, error);
|
||||
|
||||
else
|
||||
fpi_device_identify_complete (dev, error);
|
||||
fpi_device_identify_complete (dev, error);
|
||||
|
||||
self->task_ssm = NULL;
|
||||
}
|
||||
@@ -1428,6 +1410,7 @@ gx_fp_probe (FpDevice *device)
|
||||
case 0x631C:
|
||||
case 0x633C:
|
||||
case 0x634C:
|
||||
case 0x6382:
|
||||
case 0x6384:
|
||||
case 0x639C:
|
||||
case 0x63AC:
|
||||
@@ -1440,9 +1423,14 @@ gx_fp_probe (FpDevice *device)
|
||||
case 0x659A:
|
||||
case 0x6890:
|
||||
case 0x6984:
|
||||
case 0x65BA:
|
||||
self->max_enroll_stage = 12;
|
||||
break;
|
||||
|
||||
case 0x6515:
|
||||
self->max_enroll_stage = 17;
|
||||
break;
|
||||
|
||||
default:
|
||||
self->max_enroll_stage = DEFAULT_ENROLL_SAMPLES;
|
||||
break;
|
||||
@@ -1556,16 +1544,16 @@ gx_fp_exit (FpDevice *device)
|
||||
|
||||
|
||||
static void
|
||||
gx_fp_verify_identify (FpDevice *device)
|
||||
gx_fp_identify (FpDevice *device)
|
||||
{
|
||||
FpiDeviceGoodixMoc *self = FPI_DEVICE_GOODIXMOC (device);
|
||||
|
||||
self->task_ssm = fpi_ssm_new_full (device, fp_verify_sm_run_state,
|
||||
GOODIX_VERIFY_NUM_STATES,
|
||||
GOODIX_VERIFY_PWR_BTN_SHIELD_OFF,
|
||||
"verify");
|
||||
self->task_ssm = fpi_ssm_new_full (device, fp_identify_sm_run_state,
|
||||
GOODIX_IDENTIFY_NUM_STATES,
|
||||
GOODIX_IDENTIFY_PWR_BTN_SHIELD_OFF,
|
||||
"identify");
|
||||
|
||||
fpi_ssm_start (self->task_ssm, fp_verify_ssm_done);
|
||||
fpi_ssm_start (self->task_ssm, fp_identify_ssm_done);
|
||||
|
||||
}
|
||||
|
||||
@@ -1618,7 +1606,7 @@ gx_fp_template_delete (FpDevice *device)
|
||||
gsize user_id_len = 0;
|
||||
const guint8 *tid;
|
||||
gsize tid_len = 0;
|
||||
gsize payload_len = 0;
|
||||
guint16 payload_len = 0;
|
||||
g_autofree guint8 *payload = NULL;
|
||||
|
||||
fpi_device_get_delete_data (device, &print);
|
||||
@@ -1631,7 +1619,8 @@ gx_fp_template_delete (FpDevice *device)
|
||||
fpi_device_error_new (FP_DEVICE_ERROR_DATA_INVALID));
|
||||
return;
|
||||
}
|
||||
if (!encode_finger_id (tid, tid_len, user_id, user_id_len, &payload, (guint16 *) &payload_len))
|
||||
|
||||
if (!encode_finger_id (tid, tid_len, user_id, user_id_len, &payload, &payload_len))
|
||||
{
|
||||
fpi_device_delete_complete (device,
|
||||
fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
|
||||
@@ -1669,6 +1658,7 @@ fpi_device_goodixmoc_init (FpiDeviceGoodixMoc *self)
|
||||
static const FpIdEntry id_table[] = {
|
||||
{ .vid = 0x27c6, .pid = 0x5840, },
|
||||
{ .vid = 0x27c6, .pid = 0x6014, },
|
||||
{ .vid = 0x27c6, .pid = 0x6082, },
|
||||
{ .vid = 0x27c6, .pid = 0x6090, },
|
||||
{ .vid = 0x27c6, .pid = 0x6092, },
|
||||
{ .vid = 0x27c6, .pid = 0x6094, },
|
||||
@@ -1682,6 +1672,7 @@ static const FpIdEntry id_table[] = {
|
||||
{ .vid = 0x27c6, .pid = 0x631C, },
|
||||
{ .vid = 0x27c6, .pid = 0x633C, },
|
||||
{ .vid = 0x27c6, .pid = 0x634C, },
|
||||
{ .vid = 0x27c6, .pid = 0x6382, },
|
||||
{ .vid = 0x27c6, .pid = 0x6384, },
|
||||
{ .vid = 0x27c6, .pid = 0x639C, },
|
||||
{ .vid = 0x27c6, .pid = 0x63AC, },
|
||||
@@ -1703,6 +1694,10 @@ static const FpIdEntry id_table[] = {
|
||||
{ .vid = 0x27c6, .pid = 0x689A, },
|
||||
{ .vid = 0x27c6, .pid = 0x66A9, },
|
||||
{ .vid = 0x27c6, .pid = 0x6984, },
|
||||
{ .vid = 0x27c6, .pid = 0x65BA, },
|
||||
{ .vid = 0x27c6, .pid = 0x6515, },
|
||||
{ .vid = 0x27c6, .pid = 0x66AC, },
|
||||
{ .vid = 0x27c6, .pid = 0x660A, },
|
||||
{ .vid = 0, .pid = 0, .driver_data = 0 }, /* terminating entry */
|
||||
};
|
||||
|
||||
@@ -1727,8 +1722,7 @@ fpi_device_goodixmoc_class_init (FpiDeviceGoodixMocClass *klass)
|
||||
dev_class->delete = gx_fp_template_delete;
|
||||
dev_class->clear_storage = gx_fp_template_delete_all;
|
||||
dev_class->list = gx_fp_template_list;
|
||||
dev_class->verify = gx_fp_verify_identify;
|
||||
dev_class->identify = gx_fp_verify_identify;
|
||||
dev_class->identify = gx_fp_identify;
|
||||
|
||||
fpi_device_class_auto_initialize_features (dev_class);
|
||||
dev_class->features |= FP_DEVICE_FEATURE_DUPLICATES_CHECK;
|
||||
|
||||
@@ -55,10 +55,10 @@ typedef enum {
|
||||
} GoodixEnrollState;
|
||||
|
||||
typedef enum {
|
||||
GOODIX_VERIFY_PWR_BTN_SHIELD_ON = 0,
|
||||
GOODIX_VERIFY_CAPTURE,
|
||||
GOODIX_VERIFY_IDENTIFY,
|
||||
GOODIX_VERIFY_WAIT_FINGER_UP,
|
||||
GOODIX_VERIFY_PWR_BTN_SHIELD_OFF,
|
||||
GOODIX_VERIFY_NUM_STATES,
|
||||
GOODIX_IDENTIFY_PWR_BTN_SHIELD_ON = 0,
|
||||
GOODIX_IDENTIFY_CAPTURE,
|
||||
GOODIX_IDENTIFY_IDENTIFY,
|
||||
GOODIX_IDENTIFY_WAIT_FINGER_UP,
|
||||
GOODIX_IDENTIFY_PWR_BTN_SHIELD_OFF,
|
||||
GOODIX_IDENTIFY_NUM_STATES,
|
||||
} GoodixVerifyState;
|
||||
|
||||
@@ -253,8 +253,6 @@ gx_proto_parse_header (FpiByteReader *reader,
|
||||
if (!fpi_byte_reader_get_uint8 (reader, &pheader->rev_crc8))
|
||||
g_return_val_if_reached (-1);
|
||||
|
||||
pheader->len -= PACKAGE_CRC_SIZE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -263,7 +261,6 @@ gx_proto_parse_fingerid (FpiByteReader *reader,
|
||||
ptemplate_format_t template)
|
||||
{
|
||||
uint8_t byte;
|
||||
const uint8_t *buffer;
|
||||
|
||||
if (!template)
|
||||
return -1;
|
||||
@@ -280,23 +277,24 @@ gx_proto_parse_fingerid (FpiByteReader *reader,
|
||||
if (!fpi_byte_reader_skip (reader, 1))
|
||||
g_return_val_if_reached (-1);
|
||||
|
||||
if (!fpi_byte_reader_get_data (reader, sizeof (template->accountid), &buffer))
|
||||
if (!fpi_byte_reader_get_data_static (reader, template->accountid))
|
||||
g_return_val_if_reached (-1);
|
||||
|
||||
memcpy (template->accountid, buffer, sizeof (template->accountid));
|
||||
|
||||
if (!fpi_byte_reader_get_data (reader, sizeof (template->tid), &buffer))
|
||||
if (!fpi_byte_reader_get_data_static (reader, template->tid))
|
||||
g_return_val_if_reached (-1);
|
||||
|
||||
memcpy (template->tid, buffer, sizeof (template->tid));
|
||||
|
||||
if (!fpi_byte_reader_get_uint8 (reader, &template->payload.size))
|
||||
g_return_val_if_reached (-1);
|
||||
|
||||
if (!fpi_byte_reader_get_data (reader, template->payload.size, &buffer))
|
||||
g_return_val_if_reached (-1);
|
||||
if (template->payload.size > sizeof (template->payload.data))
|
||||
{
|
||||
g_warning ("Device reported oversized payload (%d)", template->payload.size);
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy (template->payload.data, buffer, template->payload.size);
|
||||
if (!(fpi_byte_reader_get_data_static) (reader, template->payload.size,
|
||||
template->payload.data))
|
||||
g_return_val_if_reached (-1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -413,6 +411,13 @@ gx_proto_parse_body (uint16_t cmd, FpiByteReader *byte_reader, pgxfp_cmd_respons
|
||||
&presp->finger_list_resp.finger_num))
|
||||
g_return_val_if_reached (-1);
|
||||
|
||||
if (presp->finger_list_resp.finger_num > FP_MAX_FINGERNUM)
|
||||
{
|
||||
g_warning ("Device reported too many fingers (%d)",
|
||||
presp->finger_list_resp.finger_num);
|
||||
return -1;
|
||||
}
|
||||
|
||||
for(uint8_t num = 0; num < presp->finger_list_resp.finger_num; num++)
|
||||
{
|
||||
uint16_t fingerid_length;
|
||||
@@ -493,8 +498,6 @@ static uint8_t sensor_config[26] = {
|
||||
int
|
||||
gx_proto_init_sensor_config (pgxfp_sensor_cfg_t pconfig)
|
||||
{
|
||||
uint32_t crc32_calc = 0;
|
||||
|
||||
if (!pconfig)
|
||||
return -1;
|
||||
memset (pconfig, 0, sizeof (*pconfig));
|
||||
@@ -503,9 +506,7 @@ gx_proto_init_sensor_config (pgxfp_sensor_cfg_t pconfig)
|
||||
memcpy (&pconfig->config, sensor_config, G_N_ELEMENTS (sensor_config));
|
||||
pconfig->reserved[0] = 1;
|
||||
|
||||
gx_proto_crc32_calc ((uint8_t *) pconfig, sizeof (*pconfig) - PACKAGE_CRC_SIZE, (uint8_t *) &crc32_calc);
|
||||
|
||||
memcpy (pconfig->crc_value, &crc32_calc, PACKAGE_CRC_SIZE);
|
||||
gx_proto_crc32_calc ((uint8_t *) pconfig, sizeof (*pconfig) - PACKAGE_CRC_SIZE, pconfig->crc_value);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
+185
-211
@@ -3,6 +3,7 @@
|
||||
#include "glib.h"
|
||||
#include "drivers_api.h"
|
||||
#include "mafpmoc.h"
|
||||
#include "fpi-byte-writer.h"
|
||||
|
||||
struct _FpiDeviceMafpmoc
|
||||
{
|
||||
@@ -71,23 +72,6 @@ ma_protocol_crc16_calc ( uint8_t *data, uint32_t data_len, uint32_t start)
|
||||
return sum_s;
|
||||
}
|
||||
|
||||
static void
|
||||
init_pack_header (ppack_header pheader, uint16_t frame_len)
|
||||
{
|
||||
g_assert (pheader);
|
||||
|
||||
memset (pheader, 0, sizeof (*pheader));
|
||||
pheader->head0 = 0xEF;
|
||||
pheader->head1 = 0x01;
|
||||
pheader->addr0 = 0xFF;
|
||||
pheader->addr1 = 0xFF;
|
||||
pheader->addr2 = 0xFF;
|
||||
pheader->addr3 = 0xFF;
|
||||
pheader->flag = (uint8_t) MAPF_PACK_CMD;
|
||||
pheader->frame_len0 = (frame_len >> 8) & 0xff;
|
||||
pheader->frame_len1 = frame_len & 0xff;
|
||||
}
|
||||
|
||||
/* data tansfer:
|
||||
* while cmd_len = 0, put flag(end or not) in data[0]
|
||||
*/
|
||||
@@ -98,27 +82,48 @@ ma_protocol_build_package (uint32_t package_len,
|
||||
const uint8_t *data,
|
||||
uint32_t data_len)
|
||||
{
|
||||
g_autofree uint8_t *ppackage = g_new0 (uint8_t, package_len);
|
||||
pack_header header;
|
||||
g_autoptr(FpiByteWriter) writer = NULL;
|
||||
uint8_t flag;
|
||||
uint16_t frame_len;
|
||||
uint16_t crc;
|
||||
gboolean written;
|
||||
|
||||
writer = fpi_byte_writer_new_with_size (package_len, TRUE);
|
||||
|
||||
written = fpi_byte_writer_put_uint8 (writer, 0xEF);
|
||||
written &= fpi_byte_writer_put_uint8 (writer, 0x01);
|
||||
written &= fpi_byte_writer_put_uint8 (writer, 0xFF);
|
||||
written &= fpi_byte_writer_put_uint8 (writer, 0xFF);
|
||||
written &= fpi_byte_writer_put_uint8 (writer, 0xFF);
|
||||
written &= fpi_byte_writer_put_uint8 (writer, 0xFF);
|
||||
|
||||
flag = (uint8_t) MAPF_PACK_CMD;
|
||||
|
||||
init_pack_header (&header, package_len - PACKAGE_HEADER_SIZE);
|
||||
if (!cmd_len && data_len)
|
||||
header.flag = data[0];
|
||||
flag = data[0];
|
||||
|
||||
memcpy (ppackage, &header, PACKAGE_HEADER_SIZE);
|
||||
fpi_byte_writer_put_uint8 (writer, flag);
|
||||
|
||||
frame_len = package_len - PACKAGE_HEADER_SIZE;
|
||||
|
||||
written &= fpi_byte_writer_put_uint16_be (writer, frame_len);
|
||||
|
||||
if (cmd_len)
|
||||
memcpy (ppackage + PACKAGE_HEADER_SIZE, &cmd, 1);
|
||||
written &= fpi_byte_writer_put_uint8 (writer, cmd);
|
||||
|
||||
if (data_len)
|
||||
memcpy (ppackage + PACKAGE_HEADER_SIZE + cmd_len, data + !cmd_len, data_len);
|
||||
written &= fpi_byte_writer_put_data (writer, data + !cmd_len, data_len);
|
||||
|
||||
uint16_t crc = ma_protocol_crc16_calc (ppackage, PACKAGE_HEADER_SIZE + cmd_len + data_len, 6);
|
||||
crc = ma_protocol_crc16_calc ((uint8_t *) writer->parent.data,
|
||||
PACKAGE_HEADER_SIZE + cmd_len + data_len,
|
||||
6);
|
||||
|
||||
ppackage[package_len - 2] = (crc >> 8) & 0xFF;
|
||||
ppackage[package_len - 1] = crc & 0xFF;
|
||||
written &= fpi_byte_writer_put_uint16_be (writer, crc);
|
||||
|
||||
return g_steal_pointer (&ppackage);
|
||||
if (!written)
|
||||
g_return_val_if_reached (NULL);
|
||||
|
||||
return fpi_byte_writer_free_and_get_data (g_steal_pointer (&writer));
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -427,6 +432,8 @@ alloc_cmd_transfer (FpiDeviceMafpmoc *self,
|
||||
g_return_val_if_fail (data || data_len == 0, NULL);
|
||||
|
||||
buffer = ma_protocol_build_package (total_len, cmd, cmd_len, data, data_len);
|
||||
g_return_val_if_fail (buffer, NULL);
|
||||
|
||||
fpi_usb_transfer_fill_bulk_full (transfer, MAFP_EP_BULK_OUT, buffer, total_len, g_free);
|
||||
return g_steal_pointer (&transfer);
|
||||
}
|
||||
@@ -438,9 +445,21 @@ mafp_sensor_cmd (FpiDeviceMafpmoc *self,
|
||||
uint8_t data_len,
|
||||
SynCmdMsgCallback callback)
|
||||
{
|
||||
g_autoptr(FpiUsbTransfer) transfer = alloc_cmd_transfer (self, cmd, 1, data, data_len);
|
||||
CommandData *cmd_data = g_new0 (CommandData, 1);
|
||||
g_autoptr(FpiUsbTransfer) transfer = NULL;
|
||||
CommandData *cmd_data = NULL;
|
||||
|
||||
if (!(transfer = alloc_cmd_transfer (self, cmd, 1, data, data_len)))
|
||||
{
|
||||
g_critical ("Failed to allocate command transfer");
|
||||
|
||||
if (callback)
|
||||
callback (self, NULL, g_error_new (FP_DEVICE_ERROR, FP_DEVICE_ERROR_PROTO,
|
||||
"Failed to allocate command transfer"));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
cmd_data = g_new0 (CommandData, 1);
|
||||
cmd_data->cmd = cmd;
|
||||
cmd_data->callback = callback;
|
||||
cmd_data->cmd_transfer = g_steal_pointer (&transfer);
|
||||
@@ -1410,9 +1429,9 @@ fp_enroll_ssm_done (FpiSsm *ssm, FpDevice *dev, GError *error)
|
||||
|
||||
|
||||
static void
|
||||
fp_verify_tpl_table_cb (FpiDeviceMafpmoc *self,
|
||||
mafp_cmd_response_t *resp,
|
||||
GError *error)
|
||||
fp_identify_tpl_table_cb (FpiDeviceMafpmoc *self,
|
||||
mafp_cmd_response_t *resp,
|
||||
GError *error)
|
||||
{
|
||||
if (error)
|
||||
{
|
||||
@@ -1429,13 +1448,13 @@ fp_verify_tpl_table_cb (FpiDeviceMafpmoc *self,
|
||||
}
|
||||
|
||||
static void
|
||||
fp_verify_get_image_cb (FpiDeviceMafpmoc *self,
|
||||
mafp_cmd_response_t *resp,
|
||||
GError *error)
|
||||
fp_identify_get_image_cb (FpiDeviceMafpmoc *self,
|
||||
mafp_cmd_response_t *resp,
|
||||
GError *error)
|
||||
{
|
||||
g_autoptr(GError) local_error = NULL;
|
||||
FpDevice *dev = FP_DEVICE (self);
|
||||
MapfVerifyState nextState = MAPF_VERIFY_GET_IMAGE;
|
||||
MapfIdentifyState nextState = MAPF_IDENTIFY_GET_IMAGE;
|
||||
|
||||
if (error)
|
||||
{
|
||||
@@ -1455,16 +1474,16 @@ fp_verify_get_image_cb (FpiDeviceMafpmoc *self,
|
||||
fp_dbg ("wait finger down state %d", resp->result);
|
||||
if (resp->result == MAFP_RE_GET_IMAGE_SUCCESS)
|
||||
{
|
||||
nextState = MAPF_VERIFY_GENERATE_FEATURE;
|
||||
nextState = MAPF_IDENTIFY_GENERATE_FEATURE;
|
||||
}
|
||||
else if (resp->result == MAFP_RE_GET_IMAGE_NONE)
|
||||
{
|
||||
self->capture_cnt++;
|
||||
fp_dbg ("self->capture_cnt %d", self->capture_cnt);
|
||||
if (self->capture_cnt > MAFP_IMAGE_ERR_TRRIGER)
|
||||
nextState = MAPF_VERIFY_REFRESH_INT_PARA;
|
||||
nextState = MAPF_IDENTIFY_REFRESH_INT_PARA;
|
||||
else
|
||||
nextState = MAPF_VERIFY_DETECT_MODE;
|
||||
nextState = MAPF_IDENTIFY_DETECT_MODE;
|
||||
}
|
||||
}
|
||||
else if (self->press_state == MAFP_PRESS_WAIT_UP)
|
||||
@@ -1472,13 +1491,13 @@ fp_verify_get_image_cb (FpiDeviceMafpmoc *self,
|
||||
fp_dbg ("wait finger up state %d", resp->result);
|
||||
if (resp->result == MAFP_RE_GET_IMAGE_SUCCESS)
|
||||
{
|
||||
nextState = MAPF_VERIFY_GET_IMAGE;
|
||||
nextState = MAPF_IDENTIFY_GET_IMAGE;
|
||||
}
|
||||
else if (resp->result == MAFP_RE_GET_IMAGE_NONE)
|
||||
{
|
||||
self->press_state = MAFP_PRESS_WAIT_DOWN;
|
||||
fpi_device_report_finger_status (dev, FP_FINGER_STATUS_NONE | FP_FINGER_STATUS_NEEDED);
|
||||
nextState = MAPF_VERIFY_CHECK_INT_PARA;
|
||||
nextState = MAPF_IDENTIFY_CHECK_INT_PARA;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1486,9 +1505,9 @@ fp_verify_get_image_cb (FpiDeviceMafpmoc *self,
|
||||
}
|
||||
|
||||
static void
|
||||
fp_verify_gen_feature_cb (FpiDeviceMafpmoc *self,
|
||||
mafp_cmd_response_t *resp,
|
||||
GError *error)
|
||||
fp_identify_gen_feature_cb (FpiDeviceMafpmoc *self,
|
||||
mafp_cmd_response_t *resp,
|
||||
GError *error)
|
||||
{
|
||||
if (error)
|
||||
{
|
||||
@@ -1502,12 +1521,12 @@ fp_verify_gen_feature_cb (FpiDeviceMafpmoc *self,
|
||||
{
|
||||
self->enroll_identify_index = 0;
|
||||
self->press_state = MAFP_PRESS_WAIT_UP;
|
||||
fpi_ssm_jump_to_state (self->task_ssm, MAPF_VERIFY_SEARCH_STEP);
|
||||
fpi_ssm_jump_to_state (self->task_ssm, MAPF_IDENTIFY_SEARCH_STEP);
|
||||
}
|
||||
else
|
||||
{
|
||||
self->press_state = MAFP_PRESS_WAIT_UP;
|
||||
fpi_ssm_jump_to_state (self->task_ssm, MAPF_VERIFY_GET_IMAGE);
|
||||
fpi_ssm_jump_to_state (self->task_ssm, MAPF_IDENTIFY_GET_IMAGE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1520,13 +1539,13 @@ mafp_scl_ctl_cb (FpiUsbTransfer *transfer,
|
||||
if (error)
|
||||
fp_dbg ("control transfer out fail, %s", error->message);
|
||||
|
||||
fpi_ssm_jump_to_state (transfer->ssm, MAPF_VERIFY_EXIT);
|
||||
fpi_ssm_jump_to_state (transfer->ssm, MAPF_IDENTIFY_EXIT);
|
||||
}
|
||||
|
||||
static void
|
||||
fp_verify_get_tpl_info_cb (FpiDeviceMafpmoc *self,
|
||||
mafp_cmd_response_t *resp,
|
||||
GError *error)
|
||||
fp_identify_get_tpl_info_cb (FpiDeviceMafpmoc *self,
|
||||
mafp_cmd_response_t *resp,
|
||||
GError *error)
|
||||
{
|
||||
g_autoptr(GError) local_error = NULL;
|
||||
FpDevice *dev = FP_DEVICE (self);
|
||||
@@ -1558,27 +1577,18 @@ fp_verify_get_tpl_info_cb (FpiDeviceMafpmoc *self,
|
||||
memcpy (tpl.uid, resp->tpl_info.uid, sizeof (resp->tpl_info.uid));
|
||||
new_scan = mafp_print_from_template (self, &tpl);
|
||||
}
|
||||
|
||||
if (new_scan != NULL)
|
||||
{
|
||||
if (fpi_device_get_current_action (dev) == FPI_DEVICE_ACTION_VERIFY)
|
||||
{
|
||||
fpi_device_get_verify_data (dev, &matching);
|
||||
if (!fp_print_equal (matching, new_scan))
|
||||
matching = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
GPtrArray *templates = NULL;
|
||||
fpi_device_get_identify_data (dev, &templates);
|
||||
for (int i = 0; i < templates->len; i++)
|
||||
{
|
||||
if (fp_print_equal (g_ptr_array_index (templates, i), new_scan))
|
||||
{
|
||||
matching = g_ptr_array_index (templates, i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
GPtrArray *templates = NULL;
|
||||
guint matching_index;
|
||||
|
||||
fpi_device_get_identify_data (dev, &templates);
|
||||
|
||||
if (g_ptr_array_find_with_equal_func (templates, new_scan,
|
||||
(GEqualFunc) fp_print_equal,
|
||||
&matching_index))
|
||||
matching = g_ptr_array_index (templates, matching_index);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1590,13 +1600,13 @@ fp_verify_get_tpl_info_cb (FpiDeviceMafpmoc *self,
|
||||
mafp_sensor_control (self, 0x8C, 0x00, mafp_scl_ctl_cb, NULL, 0);
|
||||
return;
|
||||
}
|
||||
fpi_ssm_jump_to_state (self->task_ssm, MAPF_VERIFY_EXIT);
|
||||
fpi_ssm_jump_to_state (self->task_ssm, MAPF_IDENTIFY_EXIT);
|
||||
}
|
||||
|
||||
static void
|
||||
fp_verify_search_step_cb (FpiDeviceMafpmoc *self,
|
||||
mafp_cmd_response_t *resp,
|
||||
GError *error)
|
||||
fp_identify_search_step_cb (FpiDeviceMafpmoc *self,
|
||||
mafp_cmd_response_t *resp,
|
||||
GError *error)
|
||||
{
|
||||
GPtrArray *prints = NULL;
|
||||
FpDevice *dev = FP_DEVICE (self);
|
||||
@@ -1611,23 +1621,20 @@ fp_verify_search_step_cb (FpiDeviceMafpmoc *self,
|
||||
if (resp->result == MAFP_SUCCESS)
|
||||
{
|
||||
fp_dbg ("identify ok, search_id: %d", self->search_id);
|
||||
fpi_ssm_jump_to_state (self->task_ssm, MAPF_VERIFY_GET_TEMPLATE_INFO);
|
||||
fpi_ssm_jump_to_state (self->task_ssm, MAPF_IDENTIFY_GET_TEMPLATE_INFO);
|
||||
}
|
||||
else
|
||||
{
|
||||
fp_dbg ("identify fail");
|
||||
if (fpi_device_get_current_action (dev) == FPI_DEVICE_ACTION_IDENTIFY)
|
||||
fpi_device_get_identify_data (dev, &prints);
|
||||
self->enroll_identify_index++;
|
||||
if (self->enroll_identify_index < prints->len)
|
||||
{
|
||||
fpi_device_get_identify_data (dev, &prints);
|
||||
self->enroll_identify_index++;
|
||||
if (self->enroll_identify_index < prints->len)
|
||||
{
|
||||
fpi_ssm_jump_to_state (self->task_ssm, MAPF_VERIFY_SEARCH_STEP);
|
||||
return;
|
||||
}
|
||||
fpi_ssm_jump_to_state (self->task_ssm, MAPF_IDENTIFY_SEARCH_STEP);
|
||||
return;
|
||||
}
|
||||
self->search_id = G_MAXUINT16;
|
||||
fpi_ssm_jump_to_state (self->task_ssm, MAPF_VERIFY_GET_TEMPLATE_INFO);
|
||||
fpi_ssm_jump_to_state (self->task_ssm, MAPF_IDENTIFY_GET_TEMPLATE_INFO);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1654,7 +1661,7 @@ mafp_get_startup_result_cb (FpiUsbTransfer *transfer,
|
||||
{
|
||||
self->search_id = transfer->buffer[2] * 256 + transfer->buffer[1];
|
||||
usleep (1000 * 1000);
|
||||
fpi_ssm_jump_to_state (transfer->ssm, MAPF_VERIFY_GET_TEMPLATE_INFO);
|
||||
fpi_ssm_jump_to_state (transfer->ssm, MAPF_IDENTIFY_GET_TEMPLATE_INFO);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -1662,33 +1669,7 @@ mafp_get_startup_result_cb (FpiUsbTransfer *transfer,
|
||||
}
|
||||
|
||||
static void
|
||||
fp_verify_int_check_cb (FpiDeviceMafpmoc *self,
|
||||
mafp_cmd_response_t *resp,
|
||||
GError *error)
|
||||
{
|
||||
if (error)
|
||||
{
|
||||
fpi_ssm_mark_failed (self->task_ssm, g_steal_pointer (&error));
|
||||
return;
|
||||
}
|
||||
fpi_ssm_next_state (self->task_ssm);
|
||||
}
|
||||
|
||||
static void
|
||||
fp_verify_int_detect_cb (FpiDeviceMafpmoc *self,
|
||||
mafp_cmd_response_t *resp,
|
||||
GError *error)
|
||||
{
|
||||
if (error)
|
||||
{
|
||||
fpi_ssm_mark_failed (self->task_ssm, g_steal_pointer (&error));
|
||||
return;
|
||||
}
|
||||
fpi_ssm_next_state (self->task_ssm);
|
||||
}
|
||||
|
||||
static void
|
||||
fp_verify_int_refresh_cb (FpiDeviceMafpmoc *self,
|
||||
fp_identify_int_check_cb (FpiDeviceMafpmoc *self,
|
||||
mafp_cmd_response_t *resp,
|
||||
GError *error)
|
||||
{
|
||||
@@ -1697,15 +1678,41 @@ fp_verify_int_refresh_cb (FpiDeviceMafpmoc *self,
|
||||
fpi_ssm_mark_failed (self->task_ssm, g_steal_pointer (&error));
|
||||
return;
|
||||
}
|
||||
self->capture_cnt = 0;
|
||||
fpi_ssm_jump_to_state (self->task_ssm, MAPF_VERIFY_GET_IMAGE);
|
||||
fpi_ssm_next_state (self->task_ssm);
|
||||
}
|
||||
|
||||
static void
|
||||
fp_verify_enable_int_cb (FpiUsbTransfer *transfer,
|
||||
FpDevice *device,
|
||||
gpointer user_data,
|
||||
GError *error)
|
||||
fp_identify_int_detect_cb (FpiDeviceMafpmoc *self,
|
||||
mafp_cmd_response_t *resp,
|
||||
GError *error)
|
||||
{
|
||||
if (error)
|
||||
{
|
||||
fpi_ssm_mark_failed (self->task_ssm, g_steal_pointer (&error));
|
||||
return;
|
||||
}
|
||||
fpi_ssm_next_state (self->task_ssm);
|
||||
}
|
||||
|
||||
static void
|
||||
fp_identify_int_refresh_cb (FpiDeviceMafpmoc *self,
|
||||
mafp_cmd_response_t *resp,
|
||||
GError *error)
|
||||
{
|
||||
if (error)
|
||||
{
|
||||
fpi_ssm_mark_failed (self->task_ssm, g_steal_pointer (&error));
|
||||
return;
|
||||
}
|
||||
self->capture_cnt = 0;
|
||||
fpi_ssm_jump_to_state (self->task_ssm, MAPF_IDENTIFY_GET_IMAGE);
|
||||
}
|
||||
|
||||
static void
|
||||
fp_identify_enable_int_cb (FpiUsbTransfer *transfer,
|
||||
FpDevice *device,
|
||||
gpointer user_data,
|
||||
GError *error)
|
||||
{
|
||||
if (error)
|
||||
{
|
||||
@@ -1716,24 +1723,24 @@ fp_verify_enable_int_cb (FpiUsbTransfer *transfer,
|
||||
}
|
||||
|
||||
static void
|
||||
fp_verify_disable_int_cb (FpiUsbTransfer *transfer,
|
||||
FpDevice *device,
|
||||
gpointer user_data,
|
||||
GError *error)
|
||||
fp_identify_disable_int_cb (FpiUsbTransfer *transfer,
|
||||
FpDevice *device,
|
||||
gpointer user_data,
|
||||
GError *error)
|
||||
{
|
||||
if (error)
|
||||
{
|
||||
fpi_ssm_mark_failed (transfer->ssm, g_steal_pointer (&error));
|
||||
return;
|
||||
}
|
||||
fpi_ssm_jump_to_state (transfer->ssm, MAPF_VERIFY_GET_IMAGE);
|
||||
fpi_ssm_jump_to_state (transfer->ssm, MAPF_IDENTIFY_GET_IMAGE);
|
||||
}
|
||||
|
||||
static void
|
||||
fp_verify_wait_int_cb (FpiUsbTransfer *transfer,
|
||||
FpDevice *device,
|
||||
gpointer user_data,
|
||||
GError *error)
|
||||
fp_identify_wait_int_cb (FpiUsbTransfer *transfer,
|
||||
FpDevice *device,
|
||||
gpointer user_data,
|
||||
GError *error)
|
||||
{
|
||||
FpiDeviceMafpmoc *self = FPI_DEVICE_MAFPMOC (device);
|
||||
|
||||
@@ -1742,7 +1749,7 @@ fp_verify_wait_int_cb (FpiUsbTransfer *transfer,
|
||||
fp_dbg ("code %d", error->code);
|
||||
if (error->code == G_USB_DEVICE_ERROR_TIMED_OUT)
|
||||
{
|
||||
fpi_ssm_jump_to_state (self->task_ssm, MAPF_VERIFY_GET_IMAGE);
|
||||
fpi_ssm_jump_to_state (self->task_ssm, MAPF_IDENTIFY_GET_IMAGE);
|
||||
g_clear_error (&error);
|
||||
return;
|
||||
}
|
||||
@@ -1764,7 +1771,7 @@ fp_verify_wait_int_cb (FpiUsbTransfer *transfer,
|
||||
}
|
||||
|
||||
static void
|
||||
fp_verify_wait_int (FpiDeviceMafpmoc *self)
|
||||
fp_identify_wait_int (FpiDeviceMafpmoc *self)
|
||||
{
|
||||
fp_dbg ("wait interrupt");
|
||||
FpiUsbTransfer *transfer = fpi_usb_transfer_new (FP_DEVICE (self));
|
||||
@@ -1773,12 +1780,12 @@ fp_verify_wait_int (FpiDeviceMafpmoc *self)
|
||||
fpi_usb_transfer_submit (transfer,
|
||||
30 * 60 * 1000,
|
||||
fpi_device_get_cancellable (FP_DEVICE (self)),
|
||||
fp_verify_wait_int_cb,
|
||||
fp_identify_wait_int_cb,
|
||||
NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
fp_verify_sm_run_state (FpiSsm *ssm, FpDevice *device)
|
||||
fp_identify_sm_run_state (FpiSsm *ssm, FpDevice *device)
|
||||
{
|
||||
FpiDeviceMafpmoc *self = FPI_DEVICE_MAFPMOC (device);
|
||||
uint8_t para[PACKAGE_DATA_SIZE_MAX] = { 0 };
|
||||
@@ -1787,110 +1794,97 @@ fp_verify_sm_run_state (FpiSsm *ssm, FpDevice *device)
|
||||
|
||||
switch(fpi_ssm_get_cur_state (ssm))
|
||||
{
|
||||
case MAPF_VERIFY_PWR_BTN_SHIELD_ON:
|
||||
case MAPF_IDENTIFY_PWR_BTN_SHIELD_ON:
|
||||
mafp_pwr_btn_shield_on (self, 1);
|
||||
break;
|
||||
|
||||
case MAPF_VERIFY_TEMPLATE_TABLE:
|
||||
case MAPF_IDENTIFY_TEMPLATE_TABLE:
|
||||
para[0] = 0; /* page no. */
|
||||
mafp_sensor_cmd (self, MOC_CMD_GET_TEMPLATE_TABLE, (const uint8_t *) ¶, 1, fp_verify_tpl_table_cb);
|
||||
mafp_sensor_cmd (self, MOC_CMD_GET_TEMPLATE_TABLE, (const uint8_t *) ¶, 1, fp_identify_tpl_table_cb);
|
||||
break;
|
||||
|
||||
case MAPF_VERIFY_GET_STARTUP_RESULT:
|
||||
case MAPF_IDENTIFY_GET_STARTUP_RESULT:
|
||||
mafp_sensor_control (self, 0x8D, 0x00, mafp_get_startup_result_cb, NULL, 0);
|
||||
break;
|
||||
|
||||
case MAPF_VERIFY_GET_IMAGE:
|
||||
mafp_sensor_cmd (self, MOC_CMD_GET_IMAGE, NULL, 0, fp_verify_get_image_cb);
|
||||
case MAPF_IDENTIFY_GET_IMAGE:
|
||||
mafp_sensor_cmd (self, MOC_CMD_GET_IMAGE, NULL, 0, fp_identify_get_image_cb);
|
||||
break;
|
||||
|
||||
case MAPF_VERIFY_CHECK_INT_PARA:
|
||||
case MAPF_IDENTIFY_CHECK_INT_PARA:
|
||||
para[0] = MAFP_SLEEP_INT_CHECK;
|
||||
mafp_sensor_cmd (self, MOC_CMD_SLEEP, para, 1, fp_verify_int_check_cb);
|
||||
mafp_sensor_cmd (self, MOC_CMD_SLEEP, para, 1, fp_identify_int_check_cb);
|
||||
break;
|
||||
|
||||
case MAPF_VERIFY_DETECT_MODE:
|
||||
case MAPF_IDENTIFY_DETECT_MODE:
|
||||
para[0] = MAFP_SLEEP_INT_WAIT;
|
||||
mafp_sensor_cmd (self, MOC_CMD_SLEEP, para, 1, fp_verify_int_detect_cb);
|
||||
mafp_sensor_cmd (self, MOC_CMD_SLEEP, para, 1, fp_identify_int_detect_cb);
|
||||
break;
|
||||
|
||||
case MAPF_VERIFY_ENABLE_INT:
|
||||
mafp_sensor_control (self, 0x89, 1, fp_verify_enable_int_cb, NULL, 0);
|
||||
case MAPF_IDENTIFY_ENABLE_INT:
|
||||
mafp_sensor_control (self, 0x89, 1, fp_identify_enable_int_cb, NULL, 0);
|
||||
break;
|
||||
|
||||
case MAPF_VERIFY_WAIT_INT:
|
||||
fp_verify_wait_int (self);
|
||||
case MAPF_IDENTIFY_WAIT_INT:
|
||||
fp_identify_wait_int (self);
|
||||
break;
|
||||
|
||||
case MAPF_VERIFY_DISBALE_INT:
|
||||
mafp_sensor_control (self, 0x89, 0, fp_verify_disable_int_cb, NULL, 0);
|
||||
case MAPF_IDENTIFY_DISBALE_INT:
|
||||
mafp_sensor_control (self, 0x89, 0, fp_identify_disable_int_cb, NULL, 0);
|
||||
break;
|
||||
|
||||
case MAPF_VERIFY_REFRESH_INT_PARA:
|
||||
case MAPF_IDENTIFY_REFRESH_INT_PARA:
|
||||
fp_dbg ("refresh param");
|
||||
para[0] = MAFP_SLEEP_INT_REFRESH;
|
||||
mafp_sensor_cmd (self, MOC_CMD_SLEEP, para, 1, fp_verify_int_refresh_cb);
|
||||
mafp_sensor_cmd (self, MOC_CMD_SLEEP, para, 1, fp_identify_int_refresh_cb);
|
||||
break;
|
||||
|
||||
case MAPF_VERIFY_GENERATE_FEATURE:
|
||||
case MAPF_IDENTIFY_GENERATE_FEATURE:
|
||||
para[0] = 1; /* buffer id */
|
||||
mafp_sensor_cmd (self, MOC_CMD_GEN_FEATURE, (const uint8_t *) ¶, 1, fp_verify_gen_feature_cb);
|
||||
mafp_sensor_cmd (self, MOC_CMD_GEN_FEATURE, (const uint8_t *) ¶, 1, fp_identify_gen_feature_cb);
|
||||
break;
|
||||
|
||||
case MAPF_VERIFY_SEARCH_STEP:
|
||||
if (fpi_device_get_current_action (device) == FPI_DEVICE_ACTION_VERIFY)
|
||||
case MAPF_IDENTIFY_SEARCH_STEP:
|
||||
fpi_device_get_identify_data (device, &prints);
|
||||
if (!prints || prints->len == 0)
|
||||
{
|
||||
fpi_device_get_verify_data (device, &print);
|
||||
if (!print)
|
||||
{
|
||||
self->search_id = G_MAXUINT16;
|
||||
fpi_ssm_jump_to_state (self->task_ssm, MAPF_VERIFY_GET_TEMPLATE_INFO);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fpi_device_get_identify_data (device, &prints);
|
||||
if (!prints || prints->len == 0)
|
||||
{
|
||||
self->search_id = G_MAXUINT16;
|
||||
fpi_ssm_jump_to_state (self->task_ssm, MAPF_VERIFY_GET_TEMPLATE_INFO);
|
||||
break;
|
||||
}
|
||||
print = g_ptr_array_index (prints, self->enroll_identify_index);
|
||||
self->search_id = G_MAXUINT16;
|
||||
fpi_ssm_jump_to_state (self->task_ssm, MAPF_IDENTIFY_GET_TEMPLATE_INFO);
|
||||
break;
|
||||
}
|
||||
print = g_ptr_array_index (prints, self->enroll_identify_index);
|
||||
mafp_template_t tpl = mafp_template_from_print (print);
|
||||
self->search_id = tpl.id;
|
||||
para[0] = (tpl.id >> 8) & 0xff;
|
||||
para[1] = tpl.id & 0xff;
|
||||
mafp_sensor_cmd (self, MOC_CMD_MATCH_WITHFID, (const uint8_t *) ¶, 2, fp_verify_search_step_cb);
|
||||
mafp_sensor_cmd (self, MOC_CMD_MATCH_WITHFID, (const uint8_t *) ¶, 2, fp_identify_search_step_cb);
|
||||
break;
|
||||
|
||||
case MAPF_VERIFY_GET_TEMPLATE_INFO:
|
||||
case MAPF_IDENTIFY_GET_TEMPLATE_INFO:
|
||||
if (self->search_id == G_MAXUINT16)
|
||||
{
|
||||
mafp_cmd_response_t resp;
|
||||
resp.result = 1;
|
||||
fp_verify_get_tpl_info_cb (self, &resp, NULL);
|
||||
fp_identify_get_tpl_info_cb (self, &resp, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
para[0] = (self->search_id >> 8) & 0xff; /* fp id high */
|
||||
para[1] = self->search_id & 0xff; /* fp id low */
|
||||
mafp_sensor_cmd (self, MOC_CMD_GET_TEMPLATE_INFO, (const uint8_t *) ¶, 2, fp_verify_get_tpl_info_cb);
|
||||
mafp_sensor_cmd (self, MOC_CMD_GET_TEMPLATE_INFO, (const uint8_t *) ¶, 2, fp_identify_get_tpl_info_cb);
|
||||
}
|
||||
break;
|
||||
|
||||
case MAPF_VERIFY_EXIT:
|
||||
case MAPF_IDENTIFY_EXIT:
|
||||
mafp_pwr_btn_shield_on (self, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
fp_verify_ssm_done (FpiSsm *ssm, FpDevice *dev, GError *error)
|
||||
fp_identify_ssm_done (FpiSsm *ssm, FpDevice *dev, GError *error)
|
||||
{
|
||||
fp_dbg ("verify completed");
|
||||
fp_dbg ("identify completed");
|
||||
FpiDeviceMafpmoc *self = FPI_DEVICE_MAFPMOC (dev);
|
||||
g_autoptr(FpPrint) new_print = g_steal_pointer (&self->identify_new_print);
|
||||
FpPrint *match_print = g_steal_pointer (&self->identify_match_print);
|
||||
@@ -1899,10 +1893,7 @@ fp_verify_ssm_done (FpiSsm *ssm, FpDevice *dev, GError *error)
|
||||
|
||||
if (error && error->domain == FP_DEVICE_RETRY)
|
||||
{
|
||||
if (fpi_device_get_current_action (dev) == FPI_DEVICE_ACTION_VERIFY)
|
||||
fpi_device_verify_report (dev, FPI_MATCH_ERROR, NULL, g_steal_pointer (&error));
|
||||
else
|
||||
fpi_device_identify_report (dev, NULL, NULL, g_steal_pointer (&error));
|
||||
fpi_device_identify_report (dev, NULL, NULL, g_steal_pointer (&error));
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -1913,20 +1904,11 @@ fp_verify_ssm_done (FpiSsm *ssm, FpDevice *dev, GError *error)
|
||||
return;
|
||||
}
|
||||
|
||||
if (fpi_device_get_current_action (dev) == FPI_DEVICE_ACTION_VERIFY)
|
||||
{
|
||||
fpi_device_verify_report (dev, match_print ? FPI_MATCH_SUCCESS : FPI_MATCH_FAIL,
|
||||
g_steal_pointer (&new_print), NULL);
|
||||
fpi_device_verify_complete (dev, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
fpi_device_identify_report (dev, match_print,
|
||||
self->enroll_dupl_del_state ?
|
||||
g_steal_pointer (&new_print) : NULL,
|
||||
NULL);
|
||||
fpi_device_identify_complete (dev, NULL);
|
||||
}
|
||||
fpi_device_identify_report (dev, match_print,
|
||||
self->enroll_dupl_del_state ?
|
||||
g_steal_pointer (&new_print) : NULL,
|
||||
NULL);
|
||||
fpi_device_identify_complete (dev, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -2441,7 +2423,7 @@ mafp_enroll (FpDevice *device)
|
||||
}
|
||||
|
||||
static void
|
||||
mafp_verify_identify (FpDevice *device)
|
||||
mafp_identify (FpDevice *device)
|
||||
{
|
||||
FpiDeviceMafpmoc *self = FPI_DEVICE_MAFPMOC (device);
|
||||
|
||||
@@ -2452,14 +2434,14 @@ mafp_verify_identify (FpDevice *device)
|
||||
self->identify_match_print = NULL;
|
||||
g_clear_object (&self->identify_new_print);
|
||||
|
||||
self->task_ssm = fpi_ssm_new_full (device, fp_verify_sm_run_state,
|
||||
MAPF_VERIFY_STATES,
|
||||
MAPF_VERIFY_EXIT,
|
||||
"verify");
|
||||
self->task_ssm = fpi_ssm_new_full (device, fp_identify_sm_run_state,
|
||||
MAPF_IDENTIFY_STATES,
|
||||
MAPF_IDENTIFY_EXIT,
|
||||
"identify");
|
||||
|
||||
if (!PRINT_SSM_DEBUG)
|
||||
fpi_ssm_silence_debug (self->task_ssm);
|
||||
fpi_ssm_start (self->task_ssm, fp_verify_ssm_done);
|
||||
fpi_ssm_start (self->task_ssm, fp_identify_ssm_done);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -2498,12 +2480,6 @@ mafp_template_delete_all (FpDevice *device)
|
||||
fpi_ssm_start (self->task_ssm, fp_delete_all_ssm_done);
|
||||
}
|
||||
|
||||
static void
|
||||
mafp_cancel (FpDevice *device)
|
||||
{
|
||||
fp_dbg ("mafp_cancel");
|
||||
}
|
||||
|
||||
static gboolean
|
||||
mafp_release_interface (FpiDeviceMafpmoc *self,
|
||||
GError **error)
|
||||
@@ -2559,9 +2535,7 @@ fpi_device_mafpmoc_class_init (FpiDeviceMafpmocClass *klass)
|
||||
dev_class->close = mafp_exit;
|
||||
dev_class->probe = mafp_probe;
|
||||
dev_class->enroll = mafp_enroll;
|
||||
dev_class->cancel = mafp_cancel;
|
||||
dev_class->verify = mafp_verify_identify;
|
||||
dev_class->identify = mafp_verify_identify;
|
||||
dev_class->identify = mafp_identify;
|
||||
dev_class->delete = mafp_template_delete;
|
||||
dev_class->clear_storage = mafp_template_delete_all;
|
||||
dev_class->list = mafp_template_list;
|
||||
|
||||
@@ -138,22 +138,22 @@ typedef enum {
|
||||
} MapfEnrollState;
|
||||
|
||||
typedef enum {
|
||||
MAPF_VERIFY_PWR_BTN_SHIELD_ON = 0,
|
||||
MAPF_VERIFY_TEMPLATE_TABLE,
|
||||
MAPF_VERIFY_GET_STARTUP_RESULT,
|
||||
MAPF_VERIFY_GET_IMAGE,
|
||||
MAPF_VERIFY_CHECK_INT_PARA,
|
||||
MAPF_VERIFY_DETECT_MODE,
|
||||
MAPF_VERIFY_ENABLE_INT,
|
||||
MAPF_VERIFY_WAIT_INT,
|
||||
MAPF_VERIFY_DISBALE_INT,
|
||||
MAPF_VERIFY_REFRESH_INT_PARA,
|
||||
MAPF_VERIFY_GENERATE_FEATURE,
|
||||
MAPF_VERIFY_SEARCH_STEP, //match assigned id
|
||||
MAPF_VERIFY_GET_TEMPLATE_INFO,
|
||||
MAPF_VERIFY_EXIT,
|
||||
MAPF_VERIFY_STATES,
|
||||
} MapfVerifyState;
|
||||
MAPF_IDENTIFY_PWR_BTN_SHIELD_ON = 0,
|
||||
MAPF_IDENTIFY_TEMPLATE_TABLE,
|
||||
MAPF_IDENTIFY_GET_STARTUP_RESULT,
|
||||
MAPF_IDENTIFY_GET_IMAGE,
|
||||
MAPF_IDENTIFY_CHECK_INT_PARA,
|
||||
MAPF_IDENTIFY_DETECT_MODE,
|
||||
MAPF_IDENTIFY_ENABLE_INT,
|
||||
MAPF_IDENTIFY_WAIT_INT,
|
||||
MAPF_IDENTIFY_DISBALE_INT,
|
||||
MAPF_IDENTIFY_REFRESH_INT_PARA,
|
||||
MAPF_IDENTIFY_GENERATE_FEATURE,
|
||||
MAPF_IDENTIFY_SEARCH_STEP, //match assigned id
|
||||
MAPF_IDENTIFY_GET_TEMPLATE_INFO,
|
||||
MAPF_IDENTIFY_EXIT,
|
||||
MAPF_IDENTIFY_STATES,
|
||||
} MapfIdentifyState;
|
||||
|
||||
typedef enum {
|
||||
MAPF_LIST_TEMPLATE_TABLE = 0,
|
||||
|
||||
@@ -412,6 +412,7 @@ nb1010_dev_change_state (FpImageDevice *dev, FpiImageDeviceState state)
|
||||
|
||||
static const FpIdEntry id_table[] = {
|
||||
{ .vid = 0x298d, .pid = 0x1010, },
|
||||
{ .vid = 0x298d, .pid = 0x2020, },
|
||||
{ .vid = 0, .pid = 0, .driver_data = 0 },
|
||||
};
|
||||
|
||||
@@ -427,7 +428,7 @@ fpi_device_nb1010_class_init (FpiDeviceNb1010Class *klass)
|
||||
FpImageDeviceClass *img_class = FP_IMAGE_DEVICE_CLASS (klass);
|
||||
|
||||
dev_class->id = FP_COMPONENT;
|
||||
dev_class->full_name = "NextBiometrics NB-1010-U";
|
||||
dev_class->full_name = "NextBiometrics NB-1010-U/NB-2020-U";
|
||||
dev_class->type = FP_DEVICE_TYPE_USB;
|
||||
dev_class->id_table = id_table;
|
||||
dev_class->scan_type = FP_SCAN_TYPE_PRESS;
|
||||
|
||||
@@ -61,7 +61,7 @@ parse_print_data (GVariant *data,
|
||||
|
||||
*user_id = g_variant_get_fixed_array (user_id_var, user_id_len, 1);
|
||||
|
||||
if (*user_id_len <= 0 || *user_id_len > DEFAULT_UID_LEN)
|
||||
if (*user_id_len == 0 || *user_id_len > DEFAULT_UID_LEN)
|
||||
return FALSE;
|
||||
|
||||
if (*user_id[0] == '\0' || *user_id[0] == ' ')
|
||||
@@ -234,6 +234,16 @@ fp_accept_sample_cb (FpiDeviceRealtek *self,
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (in_status != FP_RTK_SUCCESS)
|
||||
{
|
||||
fpi_ssm_mark_failed (self->task_ssm,
|
||||
fpi_device_error_new_msg (FP_DEVICE_ERROR_DATA_INVALID,
|
||||
"Enrollment failed (status 0x%02x)",
|
||||
in_status));
|
||||
return;
|
||||
}
|
||||
|
||||
fpi_ssm_next_state (self->task_ssm);
|
||||
}
|
||||
}
|
||||
@@ -506,7 +516,7 @@ fp_check_duplicate_cb (FpiDeviceRealtek *self,
|
||||
if (in_status == FP_RTK_SUCCESS)
|
||||
{
|
||||
fpi_ssm_mark_failed (self->task_ssm,
|
||||
fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
|
||||
fpi_device_error_new_msg (FP_DEVICE_ERROR_DATA_DUPLICATE,
|
||||
"Current fingerprint is duplicate!"));
|
||||
}
|
||||
else if (in_status == FP_RTK_MATCH_FAIL)
|
||||
@@ -638,6 +648,14 @@ fp_cmd_receive_cb (FpiUsbTransfer *transfer,
|
||||
{
|
||||
g_autofree guchar *read_buf = NULL;
|
||||
|
||||
if ((gsize) transfer->actual_length < self->trans_data_len)
|
||||
{
|
||||
fpi_ssm_mark_failed (transfer->ssm,
|
||||
fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
|
||||
"Truncated data received"));
|
||||
return;
|
||||
}
|
||||
|
||||
read_buf = g_malloc0 (sizeof (guchar) * (self->trans_data_len));
|
||||
memcpy (read_buf, transfer->buffer, self->trans_data_len);
|
||||
self->read_data = g_steal_pointer (&read_buf);
|
||||
@@ -891,9 +909,6 @@ fp_verify_ssm_done (FpiSsm *ssm, FpDevice *dev, GError *error)
|
||||
|
||||
fp_info ("Verify complete!");
|
||||
|
||||
if (fpi_ssm_get_error (ssm))
|
||||
error = fpi_ssm_get_error (ssm);
|
||||
|
||||
if (error && error->domain == FP_DEVICE_RETRY)
|
||||
{
|
||||
if (fpi_device_get_current_action (dev) == FPI_DEVICE_ACTION_VERIFY)
|
||||
@@ -918,9 +933,6 @@ fp_enroll_ssm_done (FpiSsm *ssm, FpDevice *dev, GError *error)
|
||||
|
||||
fp_info ("Enrollment complete!");
|
||||
|
||||
if (fpi_ssm_get_error (ssm))
|
||||
error = fpi_ssm_get_error (ssm);
|
||||
|
||||
if (error)
|
||||
{
|
||||
fpi_device_enroll_complete (dev, NULL, error);
|
||||
@@ -940,9 +952,6 @@ fp_init_ssm_done (FpiSsm *ssm, FpDevice *dev, GError *error)
|
||||
|
||||
fp_info ("Init complete!");
|
||||
|
||||
if (fpi_ssm_get_error (ssm))
|
||||
error = fpi_ssm_get_error (ssm);
|
||||
|
||||
fpi_device_open_complete (dev, error);
|
||||
self->task_ssm = NULL;
|
||||
}
|
||||
@@ -954,9 +963,6 @@ fp_delete_ssm_done (FpiSsm *ssm, FpDevice *dev, GError *error)
|
||||
|
||||
fp_info ("Delete print complete!");
|
||||
|
||||
if (fpi_ssm_get_error (ssm))
|
||||
error = fpi_ssm_get_error (ssm);
|
||||
|
||||
fpi_device_delete_complete (dev, error);
|
||||
self->task_ssm = NULL;
|
||||
}
|
||||
@@ -970,7 +976,13 @@ fp_verify_sm_run_state (FpiSsm *ssm, FpDevice *device)
|
||||
switch (fpi_ssm_get_cur_state (ssm))
|
||||
{
|
||||
case FP_RTK_VERIFY_GET_TEMPLATE:
|
||||
g_assert (self->template_num > 0);
|
||||
if (self->template_num <= 0)
|
||||
{
|
||||
fpi_ssm_mark_failed (ssm,
|
||||
fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
|
||||
"No templates enrolled"));
|
||||
break;
|
||||
}
|
||||
|
||||
co_get_template.data_len[0] = GET_LEN_L (self->template_len * self->template_num);
|
||||
co_get_template.data_len[1] = GET_LEN_H (self->template_len * self->template_num);
|
||||
@@ -1032,7 +1044,13 @@ fp_enroll_sm_run_state (FpiSsm *ssm, FpDevice *device)
|
||||
switch (fpi_ssm_get_cur_state (ssm))
|
||||
{
|
||||
case FP_RTK_ENROLL_GET_TEMPLATE:
|
||||
g_assert (self->template_num > 0);
|
||||
if (self->template_num <= 0)
|
||||
{
|
||||
fpi_ssm_mark_failed (ssm,
|
||||
fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
|
||||
"No templates enrolled"));
|
||||
break;
|
||||
}
|
||||
|
||||
co_get_template.data_len[0] = GET_LEN_L (self->template_len * self->template_num);
|
||||
co_get_template.data_len[1] = GET_LEN_H (self->template_len * self->template_num);
|
||||
@@ -1152,7 +1170,13 @@ fp_delete_sm_run_state (FpiSsm *ssm, FpDevice *device)
|
||||
switch (fpi_ssm_get_cur_state (ssm))
|
||||
{
|
||||
case FP_RTK_DELETE_GET_POS:
|
||||
g_assert (self->template_num > 0);
|
||||
if (self->template_num <= 0)
|
||||
{
|
||||
fpi_ssm_mark_failed (ssm,
|
||||
fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
|
||||
"No templates enrolled"));
|
||||
break;
|
||||
}
|
||||
|
||||
co_get_template.data_len[0] = GET_LEN_L (self->template_len * self->template_num);
|
||||
co_get_template.data_len[1] = GET_LEN_H (self->template_len * self->template_num);
|
||||
@@ -1344,7 +1368,21 @@ list_print (FpDevice *device)
|
||||
guint8 *cmd_buf = NULL;
|
||||
|
||||
G_DEBUG_HERE ();
|
||||
g_assert (self->template_num > 0);
|
||||
|
||||
if (self->template_num < 0)
|
||||
{
|
||||
fpi_device_list_complete (device, NULL,
|
||||
fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
|
||||
"Get template number failed!"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (self->template_num == 0)
|
||||
{
|
||||
g_autoptr(GPtrArray) list_result = g_ptr_array_new_with_free_func (g_object_unref);
|
||||
fpi_device_list_complete (device, g_steal_pointer (&list_result), NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
co_get_template.data_len[0] = GET_LEN_L (self->template_len * self->template_num);
|
||||
co_get_template.data_len[1] = GET_LEN_H (self->template_len * self->template_num);
|
||||
|
||||
@@ -177,17 +177,25 @@ parse_get_enrolled_fingers_report (bmkt_msg_resp_t *msg_resp, bmkt_response_t *r
|
||||
|
||||
if (msg_resp->payload_len < 2)
|
||||
return BMKT_UNRECOGNIZED_MESSAGE;
|
||||
|
||||
/* 2 bytes per finger so calculate the total number of fingers to process*/
|
||||
int num_fingers = (msg_resp->payload_len) / 2;
|
||||
|
||||
bmkt_enrolled_fingers_resp_t *get_enrolled_fingers_resp = &resp->response.enrolled_fingers_resp;
|
||||
|
||||
if (num_fingers > (int) G_N_ELEMENTS (get_enrolled_fingers_resp->fingers))
|
||||
{
|
||||
g_warning ("Device reported more enrolled fingers (%d) than supported",
|
||||
num_fingers);
|
||||
num_fingers = G_N_ELEMENTS (get_enrolled_fingers_resp->fingers);
|
||||
}
|
||||
|
||||
for (i = 0; i < num_fingers; i++)
|
||||
{
|
||||
get_enrolled_fingers_resp->fingers[i].finger_id = extract8 (msg_resp->payload, &offset);
|
||||
get_enrolled_fingers_resp->fingers[i].template_status = extract8 (msg_resp->payload, &offset);
|
||||
|
||||
}
|
||||
|
||||
return BMKT_SUCCESS;
|
||||
}
|
||||
static int
|
||||
@@ -214,10 +222,18 @@ parse_get_enrolled_users_report (bmkt_msg_resp_t *msg_resp, bmkt_response_t *res
|
||||
get_enroll_templates_resp->templates[n].user_id_len = extract8 (msg_resp->payload, &offset) - 2;
|
||||
if(get_enroll_templates_resp->templates[n].user_id_len > BMKT_MAX_USER_ID_LEN)
|
||||
return BMKT_UNRECOGNIZED_MESSAGE;
|
||||
if (offset >= msg_resp->payload_len)
|
||||
return BMKT_CORRUPT_MESSAGE;
|
||||
get_enroll_templates_resp->templates[n].template_status = extract8 (msg_resp->payload, &offset);
|
||||
if (offset >= msg_resp->payload_len)
|
||||
return BMKT_CORRUPT_MESSAGE;
|
||||
get_enroll_templates_resp->templates[n].finger_id = extract8 (msg_resp->payload, &offset);
|
||||
for (i = 0; i < get_enroll_templates_resp->templates[n].user_id_len; i++)
|
||||
get_enroll_templates_resp->templates[n].user_id[i] = extract8 (msg_resp->payload, &offset);
|
||||
{
|
||||
if (offset >= msg_resp->payload_len)
|
||||
return BMKT_CORRUPT_MESSAGE;
|
||||
get_enroll_templates_resp->templates[n].user_id[i] = extract8 (msg_resp->payload, &offset);
|
||||
}
|
||||
get_enroll_templates_resp->templates[n].user_id[i] = '\0';
|
||||
}
|
||||
|
||||
@@ -267,12 +283,19 @@ bmkt_compose_message (uint8_t *cmd, int *cmd_len, uint8_t msg_id, uint8_t seq_nu
|
||||
int
|
||||
bmkt_parse_message_header (uint8_t *resp_buf, int resp_len, bmkt_msg_resp_t *msg_resp)
|
||||
{
|
||||
if (resp_len < BMKT_MESSAGE_HEADER_LEN)
|
||||
return BMKT_CORRUPT_MESSAGE;
|
||||
|
||||
if (resp_buf[BMKT_MESSAGE_HEADER_ID_FIELD] != BMKT_MESSAGE_HEADER_ID)
|
||||
return BMKT_CORRUPT_MESSAGE;
|
||||
|
||||
msg_resp->seq_num = resp_buf[BMKT_MESSAGE_SEQ_NUM_FIELD];
|
||||
msg_resp->msg_id = resp_buf[BMKT_MESSAGE_ID_FIELD];
|
||||
msg_resp->payload_len = resp_buf[BMKT_MESSAGE_PAYLOAD_LEN_FIELD];
|
||||
|
||||
if (msg_resp->payload_len > resp_len - BMKT_MESSAGE_PAYLOAD_FIELD)
|
||||
return BMKT_CORRUPT_MESSAGE;
|
||||
|
||||
if (msg_resp->payload_len > 0)
|
||||
msg_resp->payload = &resp_buf[BMKT_MESSAGE_PAYLOAD_FIELD];
|
||||
else
|
||||
|
||||
@@ -48,6 +48,9 @@ static const FpIdEntry id_table[] = {
|
||||
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0108, },
|
||||
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0109, },
|
||||
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x010A, },
|
||||
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x010B, },
|
||||
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x010D, },
|
||||
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x010E, },
|
||||
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0123, },
|
||||
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0124, },
|
||||
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0126, },
|
||||
@@ -172,6 +175,14 @@ cmd_receive_cb (FpiUsbTransfer *transfer,
|
||||
* The original code did not! */
|
||||
if (msg_resp.msg_id == BMKT_RSP_GENERAL_ERROR)
|
||||
{
|
||||
if (msg_resp.payload_len < 2 || !msg_resp.payload)
|
||||
{
|
||||
fp_warn ("Received General Error with short or empty payload");
|
||||
fpi_ssm_mark_failed (transfer->ssm,
|
||||
fpi_device_error_new (FP_DEVICE_ERROR_PROTO));
|
||||
return;
|
||||
}
|
||||
|
||||
guint16 err;
|
||||
|
||||
/* XXX: It is weird that this is big endian. */
|
||||
@@ -1479,7 +1490,7 @@ suspend (FpDevice *dev)
|
||||
self->cmd_suspended = TRUE;
|
||||
|
||||
/* Cancel the current transfer.
|
||||
* The CMD SSM will go into the suspend state and signal readyness. */
|
||||
* The CMD SSM will go into the suspend state and signal readiness. */
|
||||
g_cancellable_cancel (self->interrupt_cancellable);
|
||||
g_clear_object (&self->interrupt_cancellable);
|
||||
self->interrupt_cancellable = g_cancellable_new ();
|
||||
|
||||
@@ -155,7 +155,8 @@ capture_reqs_cb (FpiUsbTransfer *transfer, FpDevice *device,
|
||||
}
|
||||
|
||||
static int
|
||||
upektc_img_process_image_frame (unsigned char *image_buf, unsigned char *cmd_res)
|
||||
upektc_img_process_image_frame (unsigned char *image_buf, size_t image_buf_len,
|
||||
unsigned char *cmd_res, size_t cmd_res_len)
|
||||
{
|
||||
int offset = 8;
|
||||
int len = ((cmd_res[5] & 0x0f) << 8) | (cmd_res[6]);
|
||||
@@ -168,6 +169,16 @@ upektc_img_process_image_frame (unsigned char *image_buf, unsigned char *cmd_res
|
||||
}
|
||||
if (cmd_res[7] == 0x20)
|
||||
len -= 4;
|
||||
|
||||
if (len <= 0 ||
|
||||
(size_t) offset + (size_t) len > cmd_res_len ||
|
||||
(size_t) len > image_buf_len)
|
||||
{
|
||||
fp_dbg ("Invalid image frame length %d (offset %d, source %zu, dest %zu)",
|
||||
len, offset, cmd_res_len, image_buf_len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy (image_buf, cmd_res + offset, len);
|
||||
|
||||
return len;
|
||||
@@ -321,7 +332,8 @@ capture_read_data_cb (FpiUsbTransfer *transfer, FpDevice *device,
|
||||
case 0x24:
|
||||
self->image_size +=
|
||||
upektc_img_process_image_frame (self->image_bits + self->image_size,
|
||||
data);
|
||||
(self->expected_image_size * 2) - self->image_size,
|
||||
data, MAX_RESPONSE_SIZE);
|
||||
fpi_ssm_jump_to_state (transfer->ssm,
|
||||
CAPTURE_ACK_FRAME);
|
||||
break;
|
||||
@@ -330,8 +342,16 @@ capture_read_data_cb (FpiUsbTransfer *transfer, FpDevice *device,
|
||||
case 0x20:
|
||||
self->image_size +=
|
||||
upektc_img_process_image_frame (self->image_bits + self->image_size,
|
||||
data);
|
||||
BUG_ON (self->image_size != self->expected_image_size);
|
||||
(self->expected_image_size * 2) - self->image_size,
|
||||
data, MAX_RESPONSE_SIZE);
|
||||
if (self->image_size != self->expected_image_size)
|
||||
{
|
||||
fp_err ("Image size mismatch: got %zu, expected %zu",
|
||||
self->image_size, self->expected_image_size);
|
||||
fpi_ssm_mark_failed (transfer->ssm,
|
||||
fpi_device_error_new (FP_DEVICE_ERROR_PROTO));
|
||||
return;
|
||||
}
|
||||
fp_dbg ("Image size is %lu",
|
||||
(gulong) self->image_size);
|
||||
img = fp_image_new (img_class->img_width, img_class->img_height);
|
||||
@@ -412,12 +432,10 @@ capture_run_state (FpiSsm *ssm, FpDevice *_dev)
|
||||
static void
|
||||
capture_sm_complete (FpiSsm *ssm, FpDevice *_dev, GError *error_arg)
|
||||
{
|
||||
g_autoptr(GError) error = error_arg;
|
||||
FpImageDevice *dev = FP_IMAGE_DEVICE (_dev);
|
||||
FpiDeviceUpektcImg *self = FPI_DEVICE_UPEKTC_IMG (_dev);
|
||||
|
||||
g_autoptr(GError) error = error_arg;
|
||||
|
||||
|
||||
/* Note: We assume that the error is a cancellation in the deactivation case */
|
||||
if (self->deactivating)
|
||||
start_deactivation (dev);
|
||||
@@ -498,6 +516,7 @@ deactivate_sm_complete (FpiSsm *ssm, FpDevice *_dev, GError *error)
|
||||
|
||||
fp_dbg ("Deactivate completed");
|
||||
|
||||
g_clear_pointer (&self->image_bits, g_free);
|
||||
self->deactivating = FALSE;
|
||||
fpi_image_device_deactivate_complete (dev, error);
|
||||
}
|
||||
@@ -612,6 +631,7 @@ init_read_data_cb (FpiUsbTransfer *transfer, FpDevice *device,
|
||||
}
|
||||
|
||||
self->expected_image_size = img_class->img_width * img_class->img_height;
|
||||
g_clear_pointer (&self->image_bits, g_free);
|
||||
self->image_bits = g_malloc0 (self->expected_image_size * 2);
|
||||
}
|
||||
|
||||
|
||||
@@ -308,6 +308,14 @@ __handle_incoming_msg (FpDevice *device,
|
||||
fp_dbg ("non-zero bytes in cmd response");
|
||||
|
||||
innerlen = innerbuf[1] | (innerbuf[2] << 8);
|
||||
if (innerlen < 3 || innerlen > len - 3)
|
||||
{
|
||||
fp_warn ("cmd response has invalid inner length (%d)", innerlen);
|
||||
error = fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
|
||||
"CMD response has invalid inner length");
|
||||
goto err;
|
||||
}
|
||||
|
||||
innerlen = innerlen - 3;
|
||||
_subcmd = innerbuf[5];
|
||||
fp_dbg ("device responds to subcmd %x with %d bytes", _subcmd, innerlen);
|
||||
|
||||
@@ -587,7 +587,10 @@ image_transfer_cb (FpiUsbTransfer *transfer, FpDevice *dev,
|
||||
}
|
||||
else
|
||||
{
|
||||
self->img_data = g_memdup2 (transfer->buffer, sizeof (struct uru4k_image));
|
||||
struct uru4k_image *img = g_memdup2 (transfer->buffer, sizeof (struct uru4k_image));
|
||||
|
||||
img->num_lines = GUINT16_FROM_LE (img->num_lines);
|
||||
self->img_data = g_steal_pointer (&img);
|
||||
self->img_data_actual_length = transfer->actual_length;
|
||||
fpi_ssm_next_state (ssm);
|
||||
}
|
||||
@@ -678,10 +681,10 @@ calc_dev2 (struct uru4k_image *img)
|
||||
static void
|
||||
imaging_run_state (FpiSsm *ssm, FpDevice *_dev)
|
||||
{
|
||||
g_autoptr(FpImage) fpimg = NULL;
|
||||
FpImageDevice *dev = FP_IMAGE_DEVICE (_dev);
|
||||
FpiDeviceUru4000 *self = FPI_DEVICE_URU4000 (_dev);
|
||||
struct uru4k_image *img = self->img_data;
|
||||
FpImage *fpimg;
|
||||
uint32_t key;
|
||||
uint8_t flags, num_lines;
|
||||
int i, r, to, dev2;
|
||||
@@ -752,6 +755,17 @@ imaging_run_state (FpiSsm *ssm, FpDevice *_dev)
|
||||
if (num_lines == 0)
|
||||
break;
|
||||
|
||||
/* num_lines is device-supplied; make sure decoding this block stays
|
||||
* within the captured image buffer (IMAGE_HEIGHT rows). */
|
||||
if ((size_t) self->img_lines_done + num_lines > IMAGE_HEIGHT)
|
||||
{
|
||||
fp_err ("bad captured image: block %d (%d lines) overflows buffer",
|
||||
self->img_block, num_lines);
|
||||
fpi_ssm_mark_failed (ssm,
|
||||
fpi_device_error_new (FP_DEVICE_ERROR_PROTO));
|
||||
return;
|
||||
}
|
||||
|
||||
fp_dbg ("%d %02x %d", self->img_block, flags,
|
||||
num_lines);
|
||||
if (flags & BLOCKF_CHANGE_KEY)
|
||||
@@ -795,6 +809,17 @@ imaging_run_state (FpiSsm *ssm, FpDevice *_dev)
|
||||
num_lines = img->block_info[i].num_lines;
|
||||
if (num_lines == 0)
|
||||
break;
|
||||
|
||||
if ((size_t) r + num_lines > IMAGE_HEIGHT ||
|
||||
(size_t) to + (size_t) num_lines * IMAGE_WIDTH > fpimg->width * fpimg->height)
|
||||
{
|
||||
fp_err ("bad captured image: block %d (%d lines) overflows buffer",
|
||||
i, num_lines);
|
||||
fpi_ssm_mark_failed (ssm,
|
||||
fpi_device_error_new (FP_DEVICE_ERROR_PROTO));
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy (&fpimg->data[to], &img->data[r][0],
|
||||
num_lines * IMAGE_WIDTH);
|
||||
if (!(flags & BLOCKF_NOT_PRESENT))
|
||||
@@ -811,7 +836,8 @@ imaging_run_state (FpiSsm *ssm, FpDevice *_dev)
|
||||
*/
|
||||
if (self->profile->image_not_flipped)
|
||||
fpimg->flags |= FPI_IMAGE_V_FLIPPED | FPI_IMAGE_H_FLIPPED;
|
||||
fpi_image_device_image_captured (dev, fpimg);
|
||||
|
||||
fpi_image_device_image_captured (dev, g_steal_pointer (&fpimg));
|
||||
|
||||
if (self->activate_state == FPI_IMAGE_DEVICE_STATE_CAPTURE)
|
||||
fpi_ssm_jump_to_state (ssm, IMAGING_CAPTURE);
|
||||
@@ -1181,6 +1207,12 @@ init_run_state (FpiSsm *ssm, FpDevice *_dev)
|
||||
static void
|
||||
activate_initsm_complete (FpiSsm *ssm, FpDevice *dev, GError *error)
|
||||
{
|
||||
FpiDeviceUru4000 *self = FPI_DEVICE_URU4000 (dev);
|
||||
|
||||
g_clear_pointer (&self->scanpwr_irq_timeout, g_source_destroy);
|
||||
self->irq_cb_data = NULL;
|
||||
self->irq_cb = NULL;
|
||||
|
||||
fpi_image_device_activate_complete (FP_IMAGE_DEVICE (dev), error);
|
||||
}
|
||||
|
||||
|
||||
@@ -184,8 +184,8 @@ async_send_cb (FpiUsbTransfer *transfer, FpDevice *device,
|
||||
}
|
||||
else
|
||||
{
|
||||
g_error_free (error);
|
||||
fp_dbg ("Ignoring send error: %s", error->message);
|
||||
g_error_free (error);
|
||||
}
|
||||
}
|
||||
/* Reset ignore_error flag */
|
||||
@@ -708,6 +708,9 @@ vfs_check_contrast (FpDeviceVfs101 *vdev)
|
||||
int y;
|
||||
long int count = 0;
|
||||
|
||||
if (vdev->height <= 0)
|
||||
return;
|
||||
|
||||
/* Check difference from byte 4 to byte 5 for verify contrast of image */
|
||||
for (y = 0; y < vdev->height; y++)
|
||||
count = count + vdev->buffer[offset (5, y)] - vdev->buffer[offset (4, y)];
|
||||
|
||||
@@ -85,6 +85,7 @@ enum {
|
||||
static void
|
||||
m_loop_state (FpiSsm *ssm, FpDevice *_dev)
|
||||
{
|
||||
g_autoptr(GError) error = NULL;
|
||||
FpImageDevice *dev = FP_IMAGE_DEVICE (_dev);
|
||||
FpDeviceVfs301 *self = FPI_DEVICE_VFS301 (_dev);
|
||||
|
||||
@@ -101,10 +102,16 @@ m_loop_state (FpiSsm *ssm, FpDevice *_dev)
|
||||
break;
|
||||
|
||||
case M_CHECK_PRINT:
|
||||
if (!vfs301_proto_peek_event (self))
|
||||
fpi_ssm_jump_to_state (ssm, M_WAIT_PRINT);
|
||||
else
|
||||
fpi_ssm_next_state (ssm);
|
||||
{
|
||||
int rv = vfs301_proto_peek_event (self, &error);
|
||||
|
||||
if (rv == VFS301_FAILURE)
|
||||
fpi_ssm_mark_failed (ssm, error);
|
||||
else if (rv == VFS301_ONGOING)
|
||||
fpi_ssm_jump_to_state (ssm, M_WAIT_PRINT);
|
||||
else
|
||||
fpi_ssm_next_state (ssm);
|
||||
}
|
||||
break;
|
||||
|
||||
case M_READ_PRINT_START:
|
||||
@@ -121,8 +128,11 @@ m_loop_state (FpiSsm *ssm, FpDevice *_dev)
|
||||
case M_READ_PRINT_POLL:
|
||||
{
|
||||
int rv = vfs301_proto_process_event_poll (self);
|
||||
g_assert (rv != VFS301_FAILURE);
|
||||
if (rv == VFS301_ONGOING)
|
||||
|
||||
if (rv == VFS301_FAILURE)
|
||||
fpi_ssm_mark_failed (ssm,
|
||||
fpi_device_error_new (FP_DEVICE_ERROR_PROTO));
|
||||
else if (rv == VFS301_ONGOING)
|
||||
fpi_ssm_jump_to_state (ssm, M_READ_PRINT_WAIT);
|
||||
else
|
||||
fpi_ssm_next_state (ssm);
|
||||
|
||||
@@ -133,7 +133,8 @@ void vfs301_proto_deinit (FpDeviceVfs301 *dev);
|
||||
void vfs301_proto_request_fingerprint (FpDeviceVfs301 *dev);
|
||||
|
||||
/** returns 0 if no event is ready, or 1 if there is one... */
|
||||
int vfs301_proto_peek_event (FpDeviceVfs301 *dev);
|
||||
int vfs301_proto_peek_event (FpDeviceVfs301 *dev,
|
||||
GError **error);
|
||||
void vfs301_proto_process_event_start (FpDeviceVfs301 *dev);
|
||||
int vfs301_proto_process_event_poll (FpDeviceVfs301 *dev);
|
||||
|
||||
|
||||
@@ -63,7 +63,7 @@ usb_print_packet (int dir, GError *error, const guint8 *data, int length)
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
static gboolean
|
||||
usb_recv (FpDeviceVfs301 *dev, guint8 endpoint, int max_bytes, FpiUsbTransfer **out, GError **error)
|
||||
{
|
||||
GError *err = NULL;
|
||||
@@ -87,10 +87,14 @@ usb_recv (FpDeviceVfs301 *dev, guint8 endpoint, int max_bytes, FpiUsbTransfer **
|
||||
if (!error)
|
||||
g_warning ("Unhandled receive error: %s", err->message);
|
||||
g_propagate_error (error, err);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (out)
|
||||
*out = g_steal_pointer (&transfer);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
FP_GNUC_ACCESS (read_only, 2, 3)
|
||||
@@ -344,7 +348,11 @@ vfs301_extract_image (FpDeviceVfs301 *vfs, guint8 *output, int *output_height
|
||||
int last_line;
|
||||
int i;
|
||||
|
||||
g_assert (vfs->scanline_count >= 1);
|
||||
if (vfs->scanline_count < 1 || scanlines == NULL)
|
||||
{
|
||||
*output_height = 0;
|
||||
g_return_if_reached ();
|
||||
}
|
||||
|
||||
*output_height = 1;
|
||||
memcpy (output, scanlines, VFS301_FP_OUTPUT_WIDTH);
|
||||
@@ -443,7 +451,8 @@ vfs301_proto_process_data (FpDeviceVfs301 *dev, int first_block, const guint8 *b
|
||||
|
||||
if (first_block)
|
||||
{
|
||||
g_assert (len >= VFS301_FP_FRAME_SIZE);
|
||||
if (len < VFS301_FP_FRAME_SIZE)
|
||||
g_return_val_if_reached (img_process_data (first_block, dev, buf, 0));
|
||||
|
||||
/* Skip bytes until start_sequence is found */
|
||||
for (i = 0; i < VFS301_FP_FRAME_SIZE; i++, buf++, len--)
|
||||
@@ -462,26 +471,25 @@ vfs301_proto_request_fingerprint (FpDeviceVfs301 *dev)
|
||||
}
|
||||
|
||||
int
|
||||
vfs301_proto_peek_event (FpDeviceVfs301 *dev)
|
||||
vfs301_proto_peek_event (FpDeviceVfs301 *dev,
|
||||
GError **error)
|
||||
{
|
||||
g_autoptr(GError) error = NULL;
|
||||
g_autoptr(FpiUsbTransfer) transfer = NULL;
|
||||
|
||||
const char no_event[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
const char got_event[] = {0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00};
|
||||
|
||||
USB_SEND (0x17, -1);
|
||||
usb_recv (dev, VFS301_RECEIVE_ENDPOINT_CTRL, 7, &transfer, &error);
|
||||
|
||||
/* XXX: This is obviously not a sane error handling! */
|
||||
g_assert (!error);
|
||||
if (!usb_recv (dev, VFS301_RECEIVE_ENDPOINT_CTRL, 7, &transfer, error))
|
||||
return -1;
|
||||
|
||||
if (memcmp (transfer->buffer, no_event, sizeof (no_event)) == 0)
|
||||
return 0;
|
||||
else if (memcmp (transfer->buffer, got_event, sizeof (no_event)) == 0)
|
||||
return 1;
|
||||
else
|
||||
g_assert_not_reached ();
|
||||
|
||||
g_set_error (error, FP_DEVICE_ERROR_PROTO, 0, "Unexpected event response");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* XXX: We sometimes need to receive data on from two endpoints at the same
|
||||
|
||||
+51
-6
@@ -128,6 +128,9 @@ fp_device_task_cancelled_cb (GCancellable *cancellable, FpDevice *self)
|
||||
{
|
||||
FpDevicePrivate *priv = fp_device_get_instance_private (self);
|
||||
|
||||
g_debug ("Task cancellable for operation %d cancelled",
|
||||
priv->current_action);
|
||||
|
||||
g_cancellable_cancel (priv->current_cancellable);
|
||||
}
|
||||
|
||||
@@ -221,7 +224,7 @@ fp_device_finalize (GObject *object)
|
||||
|
||||
g_clear_pointer (&priv->temp_timeout, g_source_destroy);
|
||||
|
||||
g_slist_free_full (priv->sources, (GDestroyNotify) g_source_destroy);
|
||||
g_clear_slist (&priv->sources, (GDestroyNotify) g_source_destroy);
|
||||
|
||||
g_clear_pointer (&priv->current_idle_cancel_source, g_source_destroy);
|
||||
g_clear_pointer (&priv->current_task_idle_return_source, g_source_destroy);
|
||||
@@ -1246,6 +1249,33 @@ match_data_free (FpMatchData *data)
|
||||
g_free (data);
|
||||
}
|
||||
|
||||
static void
|
||||
on_verify_identification (GObject *source_object,
|
||||
GAsyncResult *result,
|
||||
gpointer user_data)
|
||||
{
|
||||
g_autoptr(FpPrint) match = NULL;
|
||||
g_autoptr(FpPrint) print = NULL;
|
||||
g_autoptr(GError) error = NULL;
|
||||
g_autoptr(GTask) verify_task = G_TASK (g_steal_pointer (&user_data));
|
||||
FpDevice *device = FP_DEVICE (source_object);
|
||||
FpMatchData *match_data;
|
||||
|
||||
if (!fp_device_identify_finish (device, result, &match, &print, &error))
|
||||
{
|
||||
g_task_return_error (verify_task, g_steal_pointer (&error));
|
||||
return;
|
||||
}
|
||||
|
||||
match_data = g_new0 (FpMatchData, 1);
|
||||
match_data->print = g_steal_pointer (&print);
|
||||
|
||||
g_task_set_task_data (verify_task, g_steal_pointer (&match_data),
|
||||
(GDestroyNotify) match_data_free);
|
||||
|
||||
g_task_return_int (verify_task, match ? FPI_MATCH_SUCCESS : FPI_MATCH_FAIL);
|
||||
}
|
||||
|
||||
/**
|
||||
* fp_device_verify:
|
||||
* @device: a #FpDevice
|
||||
@@ -1294,7 +1324,8 @@ fp_device_verify (FpDevice *device,
|
||||
return;
|
||||
}
|
||||
|
||||
if (!cls->verify || !(priv->features & FP_DEVICE_FEATURE_VERIFY))
|
||||
if ((!cls->verify && !cls->identify) ||
|
||||
!(priv->features & FP_DEVICE_FEATURE_VERIFY))
|
||||
{
|
||||
g_task_return_error (task,
|
||||
fpi_device_error_new_msg (FP_DEVICE_ERROR_NOT_SUPPORTED,
|
||||
@@ -1302,6 +1333,21 @@ fp_device_verify (FpDevice *device,
|
||||
return;
|
||||
}
|
||||
|
||||
if (!cls->verify)
|
||||
{
|
||||
g_autoptr(GPtrArray) prints = NULL;
|
||||
|
||||
g_assert (cls->identify);
|
||||
|
||||
prints = g_ptr_array_sized_new (1);
|
||||
g_ptr_array_add (prints, enrolled_print);
|
||||
|
||||
fp_device_identify (device, prints, cancellable, match_cb, match_data,
|
||||
match_destroy, on_verify_identification,
|
||||
g_steal_pointer (&task));
|
||||
return;
|
||||
}
|
||||
|
||||
fpi_device_update_temp (device, TRUE);
|
||||
if (priv->temp_current == FP_TEMPERATURE_HOT)
|
||||
{
|
||||
@@ -1401,7 +1447,6 @@ fp_device_identify (FpDevice *device,
|
||||
FpDevicePrivate *priv = fp_device_get_instance_private (device);
|
||||
FpDeviceClass *cls = FP_DEVICE_GET_CLASS (device);
|
||||
FpMatchData *data;
|
||||
int i;
|
||||
|
||||
task = g_task_new (device, cancellable, callback, user_data);
|
||||
if (g_task_return_error_if_cancelled (task))
|
||||
@@ -1454,9 +1499,9 @@ fp_device_identify (FpDevice *device,
|
||||
* a reference to each print. Also, the caller could in principle modify the
|
||||
* GPtrArray afterwards.
|
||||
*/
|
||||
data->gallery = g_ptr_array_new_full (prints->len, g_object_unref);
|
||||
for (i = 0; i < prints->len; i++)
|
||||
g_ptr_array_add (data->gallery, g_object_ref (g_ptr_array_index (prints, i)));
|
||||
data->gallery = g_ptr_array_copy (prints, (GCopyFunc) g_object_ref, NULL);
|
||||
g_ptr_array_set_free_func (data->gallery, g_object_unref);
|
||||
|
||||
data->match_cb = match_cb;
|
||||
data->match_data = match_data;
|
||||
data->match_destroy = match_destroy;
|
||||
|
||||
@@ -89,7 +89,6 @@ fp_image_device_cancel_action (FpDevice *device)
|
||||
/* We can only cancel capture operations, in that case, deactivate and return
|
||||
* an error immediately. */
|
||||
if (action == FPI_DEVICE_ACTION_ENROLL ||
|
||||
action == FPI_DEVICE_ACTION_VERIFY ||
|
||||
action == FPI_DEVICE_ACTION_IDENTIFY ||
|
||||
action == FPI_DEVICE_ACTION_CAPTURE)
|
||||
fpi_image_device_deactivate (self, TRUE);
|
||||
@@ -217,7 +216,6 @@ fp_image_device_class_init (FpImageDeviceClass *klass)
|
||||
fp_device_class->open = fp_image_device_open;
|
||||
fp_device_class->close = fp_image_device_close;
|
||||
fp_device_class->enroll = fp_image_device_start_capture_action;
|
||||
fp_device_class->verify = fp_image_device_start_capture_action;
|
||||
fp_device_class->identify = fp_image_device_start_capture_action;
|
||||
fp_device_class->capture = fp_image_device_start_capture_action;
|
||||
|
||||
|
||||
@@ -596,6 +596,9 @@ fp_print_equal (FpPrint *self, FpPrint *other)
|
||||
g_return_val_if_fail (self->type != FPI_PRINT_UNDEFINED, FALSE);
|
||||
g_return_val_if_fail (other->type != FPI_PRINT_UNDEFINED, FALSE);
|
||||
|
||||
if (self == other)
|
||||
return TRUE;
|
||||
|
||||
if (self->type != other->type)
|
||||
return FALSE;
|
||||
|
||||
|
||||
+185
-46
@@ -54,6 +54,30 @@ fp_device_get_instance_private (FpDevice *self)
|
||||
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC (GModule, g_module_close)
|
||||
|
||||
static char *
|
||||
error_to_string (GError * error)
|
||||
{
|
||||
g_autofree char *domain_str = NULL;
|
||||
|
||||
if (!error)
|
||||
return g_strdup ("none");
|
||||
|
||||
if (error->domain == FP_DEVICE_RETRY)
|
||||
domain_str = g_enum_to_string (FP_TYPE_DEVICE_RETRY, error->code);
|
||||
else if (error->domain == FP_DEVICE_ERROR)
|
||||
domain_str = g_enum_to_string (FP_TYPE_DEVICE_ERROR, error->code);
|
||||
else if (error->domain == G_IO_ERROR)
|
||||
domain_str = g_enum_to_string (g_io_error_enum_get_type (), error->code);
|
||||
else if (error->domain == G_USB_DEVICE_ERROR)
|
||||
domain_str = g_strdup_printf ("G_USB_DEVICE_ERROR_%u", error->code);
|
||||
else
|
||||
domain_str = g_strdup_printf ("%s_%u",
|
||||
g_quark_to_string (error->domain),
|
||||
error->code);
|
||||
|
||||
return g_strdup_printf ("[%s] %s", domain_str, error->message);
|
||||
}
|
||||
|
||||
/**
|
||||
* fpi_device_emulation_mode_enabled:
|
||||
* @device: The #FpDevice to check
|
||||
@@ -127,7 +151,7 @@ fpi_device_class_auto_initialize_features (FpDeviceClass *device_class)
|
||||
device_class->features |= FP_DEVICE_FEATURE_VERIFY;
|
||||
|
||||
if (device_class->identify)
|
||||
device_class->features |= FP_DEVICE_FEATURE_IDENTIFY;
|
||||
device_class->features |= FP_DEVICE_FEATURE_IDENTIFY | FP_DEVICE_FEATURE_VERIFY;
|
||||
|
||||
if (device_class->list)
|
||||
device_class->features |= FP_DEVICE_FEATURE_STORAGE_LIST;
|
||||
@@ -772,7 +796,7 @@ fpi_device_remove (FpDevice *device)
|
||||
/**
|
||||
* fpi_device_action_error:
|
||||
* @device: The #FpDevice
|
||||
* @error: The #GError to return
|
||||
* @error: (nullable) (transfer full): The #GError or %NULL on success
|
||||
*
|
||||
* Finish an ongoing action with an error. This is the same as calling
|
||||
* the corresponding complete function such as fpi_device_open_complete()
|
||||
@@ -790,11 +814,14 @@ fpi_device_action_error (FpDevice *device,
|
||||
|
||||
if (error != NULL)
|
||||
{
|
||||
g_autofree char *action_str = NULL;
|
||||
if (!g_log_writer_default_would_drop (G_LOG_LEVEL_DEBUG, G_LOG_DOMAIN))
|
||||
{
|
||||
g_autofree char *error_str = error_to_string (error);
|
||||
g_autofree char *action_str = g_enum_to_string (FPI_TYPE_DEVICE_ACTION, priv->current_action);
|
||||
|
||||
action_str = g_enum_to_string (FPI_TYPE_DEVICE_ACTION, priv->current_action);
|
||||
g_debug ("Device reported generic error (%s) during action; action was: %s",
|
||||
error->message, action_str);
|
||||
g_debug ("Device reported generic error (%s) during action; action was: %s",
|
||||
error_str, action_str);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1007,17 +1034,18 @@ typedef struct _FpDeviceTaskReturnData
|
||||
static gboolean
|
||||
fp_device_task_return_in_idle_cb (gpointer user_data)
|
||||
{
|
||||
FpDeviceTaskReturnData *data = user_data;
|
||||
FpDevicePrivate *priv = fp_device_get_instance_private (data->device);
|
||||
g_autofree char *action_str = NULL;
|
||||
FpiDeviceAction action;
|
||||
|
||||
g_autoptr(GTask) task = NULL;
|
||||
g_autoptr(GError) cancellation_reason = NULL;
|
||||
FpDeviceTaskReturnData *data = user_data;
|
||||
FpDevicePrivate *priv = fp_device_get_instance_private (data->device);
|
||||
FpiDeviceAction action;
|
||||
|
||||
if (!g_log_writer_default_would_drop (G_LOG_LEVEL_DEBUG, G_LOG_DOMAIN))
|
||||
{
|
||||
g_autofree char *action_str = g_enum_to_string (FPI_TYPE_DEVICE_ACTION, priv->current_action);
|
||||
|
||||
action_str = g_enum_to_string (FPI_TYPE_DEVICE_ACTION, priv->current_action);
|
||||
g_debug ("Completing action %s in idle!", action_str);
|
||||
g_debug ("Completing action %s in idle!", action_str);
|
||||
}
|
||||
|
||||
task = g_steal_pointer (&priv->current_task);
|
||||
action = priv->current_action;
|
||||
@@ -1185,7 +1213,13 @@ fpi_device_probe_complete (FpDevice *device,
|
||||
g_return_if_fail (FP_IS_DEVICE (device));
|
||||
g_return_if_fail (priv->current_action == FPI_DEVICE_ACTION_PROBE);
|
||||
|
||||
g_debug ("Device reported probe completion");
|
||||
if (!g_log_writer_default_would_drop (G_LOG_LEVEL_DEBUG, G_LOG_DOMAIN))
|
||||
{
|
||||
g_autofree char *error_str = error_to_string (error);
|
||||
|
||||
g_debug ("Device reported probe completion (ID: %s, name: %s, error: %s)",
|
||||
device_id, device_name, error_str);
|
||||
}
|
||||
|
||||
clear_device_cancel_action (device);
|
||||
fpi_device_report_finger_status (device, FP_FINGER_STATUS_NONE);
|
||||
@@ -1228,7 +1262,12 @@ fpi_device_open_complete (FpDevice *device, GError *error)
|
||||
g_return_if_fail (FP_IS_DEVICE (device));
|
||||
g_return_if_fail (priv->current_action == FPI_DEVICE_ACTION_OPEN);
|
||||
|
||||
g_debug ("Device reported open completion");
|
||||
if (!g_log_writer_default_would_drop (G_LOG_LEVEL_DEBUG, G_LOG_DOMAIN))
|
||||
{
|
||||
g_autofree char *error_str = error_to_string (error);
|
||||
|
||||
g_debug ("Device reported open completion (error: %s)", error_str);
|
||||
}
|
||||
|
||||
clear_device_cancel_action (device);
|
||||
fpi_device_report_finger_status (device, FP_FINGER_STATUS_NONE);
|
||||
@@ -1250,13 +1289,18 @@ fpi_device_open_complete (FpDevice *device, GError *error)
|
||||
void
|
||||
fpi_device_close_complete (FpDevice *device, GError *error)
|
||||
{
|
||||
GError *nested_error = NULL;
|
||||
g_autoptr(GError) nested_error = NULL;
|
||||
FpDevicePrivate *priv = fp_device_get_instance_private (device);
|
||||
|
||||
g_return_if_fail (FP_IS_DEVICE (device));
|
||||
g_return_if_fail (priv->current_action == FPI_DEVICE_ACTION_CLOSE);
|
||||
|
||||
g_debug ("Device reported close completion");
|
||||
if (!g_log_writer_default_would_drop (G_LOG_LEVEL_DEBUG, G_LOG_DOMAIN))
|
||||
{
|
||||
g_autofree char *error_str = error_to_string (error);
|
||||
|
||||
g_debug ("Device reported close completion (error: %s)", error_str);
|
||||
}
|
||||
|
||||
clear_device_cancel_action (device);
|
||||
fpi_device_report_finger_status (device, FP_FINGER_STATUS_NONE);
|
||||
@@ -1267,7 +1311,8 @@ fpi_device_close_complete (FpDevice *device, GError *error)
|
||||
if (!g_usb_device_close (priv->usb_device, &nested_error))
|
||||
{
|
||||
if (error == NULL)
|
||||
error = nested_error;
|
||||
error = g_steal_pointer (&nested_error);
|
||||
|
||||
fpi_device_return_task_in_idle (device, FP_DEVICE_TASK_RETURN_ERROR, error);
|
||||
return;
|
||||
}
|
||||
@@ -1308,7 +1353,13 @@ fpi_device_enroll_complete (FpDevice *device, FpPrint *print, GError *error)
|
||||
g_return_if_fail (FP_IS_DEVICE (device));
|
||||
g_return_if_fail (priv->current_action == FPI_DEVICE_ACTION_ENROLL);
|
||||
|
||||
g_debug ("Device reported enroll completion");
|
||||
if (!g_log_writer_default_would_drop (G_LOG_LEVEL_DEBUG, G_LOG_DOMAIN))
|
||||
{
|
||||
g_autofree char *error_str = error_to_string (error);
|
||||
|
||||
g_debug ("Device reported enroll completion (print: %p, error: %s)",
|
||||
print, error_str);
|
||||
}
|
||||
|
||||
clear_device_cancel_action (device);
|
||||
fpi_device_report_finger_status (device, FP_FINGER_STATUS_NONE);
|
||||
@@ -1318,7 +1369,6 @@ fpi_device_enroll_complete (FpDevice *device, FpPrint *print, GError *error)
|
||||
if (FP_IS_PRINT (print))
|
||||
{
|
||||
FpiPrintType print_type;
|
||||
g_autofree char *finger_str = NULL;
|
||||
|
||||
g_object_get (print, "fpi-type", &print_type, NULL);
|
||||
if (print_type == FPI_PRINT_UNDEFINED)
|
||||
@@ -1332,8 +1382,12 @@ fpi_device_enroll_complete (FpDevice *device, FpPrint *print, GError *error)
|
||||
return;
|
||||
}
|
||||
|
||||
finger_str = g_enum_to_string (FP_TYPE_FINGER, fp_print_get_finger (print));
|
||||
g_debug ("Print for finger %s enrolled", finger_str);
|
||||
if (!g_log_writer_default_would_drop (G_LOG_LEVEL_DEBUG, G_LOG_DOMAIN))
|
||||
{
|
||||
g_autofree char *finger_str = g_enum_to_string (FP_TYPE_FINGER, fp_print_get_finger (print));
|
||||
|
||||
g_debug ("Print for finger %s enrolled", finger_str);
|
||||
}
|
||||
|
||||
fpi_device_return_task_in_idle (device, FP_DEVICE_TASK_RETURN_OBJECT, print);
|
||||
}
|
||||
@@ -1380,7 +1434,12 @@ fpi_device_verify_complete (FpDevice *device,
|
||||
g_return_if_fail (FP_IS_DEVICE (device));
|
||||
g_return_if_fail (priv->current_action == FPI_DEVICE_ACTION_VERIFY);
|
||||
|
||||
g_debug ("Device reported verify completion");
|
||||
if (!g_log_writer_default_would_drop (G_LOG_LEVEL_DEBUG, G_LOG_DOMAIN))
|
||||
{
|
||||
g_autofree char *error_str = error_to_string (error);
|
||||
|
||||
g_debug ("Device reported verify completion (error: %s)", error_str);
|
||||
}
|
||||
|
||||
data = g_task_get_task_data (priv->current_task);
|
||||
|
||||
@@ -1445,7 +1504,12 @@ fpi_device_identify_complete (FpDevice *device,
|
||||
g_return_if_fail (FP_IS_DEVICE (device));
|
||||
g_return_if_fail (priv->current_action == FPI_DEVICE_ACTION_IDENTIFY);
|
||||
|
||||
g_debug ("Device reported identify completion");
|
||||
if (!g_log_writer_default_would_drop (G_LOG_LEVEL_DEBUG, G_LOG_DOMAIN))
|
||||
{
|
||||
g_autofree char *error_str = error_to_string (error);
|
||||
|
||||
g_debug ("Device reported identify completion (error: %s)", error_str);
|
||||
}
|
||||
|
||||
data = g_task_get_task_data (priv->current_task);
|
||||
|
||||
@@ -1504,7 +1568,13 @@ fpi_device_capture_complete (FpDevice *device,
|
||||
g_return_if_fail (FP_IS_DEVICE (device));
|
||||
g_return_if_fail (priv->current_action == FPI_DEVICE_ACTION_CAPTURE);
|
||||
|
||||
g_debug ("Device reported capture completion");
|
||||
if (!g_log_writer_default_would_drop (G_LOG_LEVEL_DEBUG, G_LOG_DOMAIN))
|
||||
{
|
||||
g_autofree char *error_str = error_to_string (error);
|
||||
|
||||
g_debug ("Device reported capture completion (image: %p, error: %s)",
|
||||
image, error_str);
|
||||
}
|
||||
|
||||
clear_device_cancel_action (device);
|
||||
fpi_device_report_finger_status (device, FP_FINGER_STATUS_NONE);
|
||||
@@ -1550,7 +1620,12 @@ fpi_device_delete_complete (FpDevice *device,
|
||||
g_return_if_fail (FP_IS_DEVICE (device));
|
||||
g_return_if_fail (priv->current_action == FPI_DEVICE_ACTION_DELETE);
|
||||
|
||||
g_debug ("Device reported deletion completion");
|
||||
if (!g_log_writer_default_would_drop (G_LOG_LEVEL_DEBUG, G_LOG_DOMAIN))
|
||||
{
|
||||
g_autofree char *error_str = error_to_string (error);
|
||||
|
||||
g_debug ("Device reported delete completion (error: %s)", error_str);
|
||||
}
|
||||
|
||||
clear_device_cancel_action (device);
|
||||
fpi_device_report_finger_status (device, FP_FINGER_STATUS_NONE);
|
||||
@@ -1585,7 +1660,13 @@ fpi_device_list_complete (FpDevice *device,
|
||||
g_return_if_fail (FP_IS_DEVICE (device));
|
||||
g_return_if_fail (priv->current_action == FPI_DEVICE_ACTION_LIST);
|
||||
|
||||
g_debug ("Device reported listing completion");
|
||||
if (!g_log_writer_default_would_drop (G_LOG_LEVEL_DEBUG, G_LOG_DOMAIN))
|
||||
{
|
||||
g_autofree char *error_str = error_to_string (error);
|
||||
|
||||
g_debug ("Device reported listing completion (prints: %ld, error: %s)",
|
||||
prints ? (long) prints->len : -1, error_str);
|
||||
}
|
||||
|
||||
clear_device_cancel_action (device);
|
||||
fpi_device_report_finger_status (device, FP_FINGER_STATUS_NONE);
|
||||
@@ -1866,6 +1947,13 @@ fpi_device_suspend_complete (FpDevice *device,
|
||||
g_return_if_fail (priv->suspend_resume_task);
|
||||
g_return_if_fail (priv->suspend_error == NULL);
|
||||
|
||||
if (!g_log_writer_default_would_drop (G_LOG_LEVEL_DEBUG, G_LOG_DOMAIN))
|
||||
{
|
||||
g_autofree char *error_str = error_to_string (error);
|
||||
|
||||
g_debug ("Device reported suspend completion (error: %s)", error_str);
|
||||
}
|
||||
|
||||
priv->suspend_error = g_steal_pointer (&error);
|
||||
priv->is_suspended = TRUE;
|
||||
|
||||
@@ -1909,6 +1997,13 @@ fpi_device_resume_complete (FpDevice *device,
|
||||
g_return_if_fail (FP_IS_DEVICE (device));
|
||||
g_return_if_fail (priv->suspend_resume_task);
|
||||
|
||||
if (!g_log_writer_default_would_drop (G_LOG_LEVEL_DEBUG, G_LOG_DOMAIN))
|
||||
{
|
||||
g_autofree char *error_str = error_to_string (error);
|
||||
|
||||
g_debug ("Device reported resume completion (error: %s)", error_str);
|
||||
}
|
||||
|
||||
priv->is_suspended = FALSE;
|
||||
fpi_device_configure_wakeup (device, FALSE);
|
||||
|
||||
@@ -1936,7 +2031,12 @@ fpi_device_clear_storage_complete (FpDevice *device,
|
||||
g_return_if_fail (FP_IS_DEVICE (device));
|
||||
g_return_if_fail (priv->current_action == FPI_DEVICE_ACTION_CLEAR_STORAGE);
|
||||
|
||||
g_debug ("Device reported deletion completion");
|
||||
if (!g_log_writer_default_would_drop (G_LOG_LEVEL_DEBUG, G_LOG_DOMAIN))
|
||||
{
|
||||
g_autofree char *error_str = error_to_string (error);
|
||||
|
||||
g_debug ("Device reported clear storage completion (error: %s)", error_str);
|
||||
}
|
||||
|
||||
clear_device_cancel_action (device);
|
||||
fpi_device_report_finger_status (device, FP_FINGER_STATUS_NONE);
|
||||
@@ -2025,7 +2125,14 @@ fpi_device_verify_report (FpDevice *device,
|
||||
|
||||
data->result_reported = TRUE;
|
||||
|
||||
g_debug ("Device reported verify result");
|
||||
if (!g_log_writer_default_would_drop (G_LOG_LEVEL_DEBUG, G_LOG_DOMAIN))
|
||||
{
|
||||
g_autofree char *result_str = g_enum_to_string (FPI_TYPE_MATCH_RESULT, result);
|
||||
g_autofree char *error_str = error_to_string (error);
|
||||
|
||||
g_debug ("Device reported verify result (result: %s, print: %p, error: %s)",
|
||||
result_str, print, error_str);
|
||||
}
|
||||
|
||||
if (print)
|
||||
print = g_object_ref_sink (print);
|
||||
@@ -2061,6 +2168,14 @@ fpi_device_verify_report (FpDevice *device,
|
||||
{
|
||||
fpi_device_get_verify_data (device, &data->match);
|
||||
g_object_ref (data->match);
|
||||
|
||||
if (print &&
|
||||
fpi_print_get_type (print) != FPI_PRINT_NBIS &&
|
||||
!fp_print_equal (print, data->match))
|
||||
{
|
||||
g_warning ("Driver reported a match providing a scanned print that is not matching it.");
|
||||
g_clear_object (&print);
|
||||
}
|
||||
}
|
||||
|
||||
data->print = g_steal_pointer (&print);
|
||||
@@ -2117,14 +2232,20 @@ fpi_device_identify_report (FpDevice *device,
|
||||
if (print)
|
||||
print = g_object_ref_sink (print);
|
||||
|
||||
if (!g_log_writer_default_would_drop (G_LOG_LEVEL_DEBUG, G_LOG_DOMAIN))
|
||||
{
|
||||
g_autofree char *error_str = error_to_string (error);
|
||||
|
||||
g_debug ("Device reported identify result (match: %p, print: %p, error: %s)",
|
||||
match, print, error_str);
|
||||
}
|
||||
|
||||
if (match && !g_ptr_array_find (data->gallery, match, NULL))
|
||||
{
|
||||
g_warning ("Driver reported a match to a print that was not in the gallery, ignoring match.");
|
||||
g_clear_object (&match);
|
||||
}
|
||||
|
||||
g_debug ("Device reported identify result");
|
||||
|
||||
if (error)
|
||||
{
|
||||
if (match != NULL)
|
||||
@@ -2149,6 +2270,14 @@ fpi_device_identify_report (FpDevice *device,
|
||||
}
|
||||
else
|
||||
{
|
||||
if (match && print && fpi_print_get_type (print) != FPI_PRINT_NBIS &&
|
||||
!g_ptr_array_find_with_equal_func (data->gallery, print,
|
||||
(GEqualFunc) fp_print_equal, NULL))
|
||||
{
|
||||
g_warning ("Driver reported a match providing a scanned print that is not matching any in the gallery.");
|
||||
g_clear_object (&print);
|
||||
}
|
||||
|
||||
if (match)
|
||||
data->match = g_steal_pointer (&match);
|
||||
|
||||
@@ -2175,13 +2304,21 @@ fpi_device_report_finger_status (FpDevice *device,
|
||||
FpFingerStatusFlags finger_status)
|
||||
{
|
||||
FpDevicePrivate *priv = fp_device_get_instance_private (device);
|
||||
g_autofree char *status_string = NULL;
|
||||
|
||||
if (priv->finger_status == finger_status)
|
||||
return FALSE;
|
||||
|
||||
status_string = g_flags_to_string (FP_TYPE_FINGER_STATUS_FLAGS, finger_status);
|
||||
fp_dbg ("Device reported finger status change: %s", status_string);
|
||||
if (!g_log_writer_default_would_drop (G_LOG_LEVEL_DEBUG, G_LOG_DOMAIN))
|
||||
{
|
||||
g_autofree char *status_string = NULL;
|
||||
g_autofree char *old_status_string = NULL;
|
||||
|
||||
old_status_string = g_flags_to_string (FP_TYPE_FINGER_STATUS_FLAGS, priv->finger_status);
|
||||
status_string = g_flags_to_string (FP_TYPE_FINGER_STATUS_FLAGS, finger_status);
|
||||
|
||||
g_debug ("Device reported finger status change: %s -> %s",
|
||||
old_status_string, status_string);
|
||||
}
|
||||
|
||||
priv->finger_status = finger_status;
|
||||
g_object_notify (G_OBJECT (device), "finger-status");
|
||||
@@ -2242,8 +2379,6 @@ fpi_device_update_temp (FpDevice *device, gboolean is_active)
|
||||
gdouble next_threshold;
|
||||
gdouble old_ratio;
|
||||
FpTemperature old_temp;
|
||||
g_autofree char *old_temp_str = NULL;
|
||||
g_autofree char *new_temp_str = NULL;
|
||||
|
||||
if (priv->temp_hot_seconds < 0)
|
||||
{
|
||||
@@ -2293,16 +2428,20 @@ fpi_device_update_temp (FpDevice *device, gboolean is_active)
|
||||
next_threshold = is_active ? -1.0 : TEMP_HOT_WARM_THRESH;
|
||||
}
|
||||
|
||||
old_temp_str = g_enum_to_string (FP_TYPE_TEMPERATURE, old_temp);
|
||||
new_temp_str = g_enum_to_string (FP_TYPE_TEMPERATURE, priv->temp_current);
|
||||
g_debug ("Updated temperature model after %0.2f seconds, ratio %0.2f -> %0.2f, active %d -> %d, %s -> %s",
|
||||
passed_seconds,
|
||||
old_ratio,
|
||||
priv->temp_current_ratio,
|
||||
priv->temp_last_active,
|
||||
is_active,
|
||||
old_temp_str,
|
||||
new_temp_str);
|
||||
if (!g_log_writer_default_would_drop (G_LOG_LEVEL_DEBUG, G_LOG_DOMAIN))
|
||||
{
|
||||
g_autofree char *old_temp_str = g_enum_to_string (FP_TYPE_TEMPERATURE, old_temp);
|
||||
g_autofree char *new_temp_str = g_enum_to_string (FP_TYPE_TEMPERATURE, priv->temp_current);
|
||||
|
||||
g_debug ("Updated temperature model after %0.2f seconds, ratio %0.2f -> %0.2f, active %d -> %d, %s -> %s",
|
||||
passed_seconds,
|
||||
old_ratio,
|
||||
priv->temp_current_ratio,
|
||||
priv->temp_last_active,
|
||||
is_active,
|
||||
old_temp_str,
|
||||
new_temp_str);
|
||||
}
|
||||
|
||||
if (priv->temp_current != old_temp)
|
||||
g_object_notify (G_OBJECT (device), "temperature");
|
||||
|
||||
@@ -107,7 +107,8 @@ struct _FpIdEntry
|
||||
* guaranteed to only happen when the device is open (this includes delete).
|
||||
* @close: Close the device again
|
||||
* @enroll: Start an enroll operation
|
||||
* @verify: Start a verify operation
|
||||
* @verify: Start a verify operation (it will be implemented via @identify
|
||||
* if not overriden).
|
||||
* @identify: Start an identify operation
|
||||
* @capture: Start a capture operation
|
||||
* @list: List prints stored on the device
|
||||
@@ -228,7 +229,6 @@ GUsbDevice *fpi_device_get_usb_device (FpDevice *device);
|
||||
const gchar *fpi_device_get_virtual_env (FpDevice *device);
|
||||
gpointer fpi_device_get_udev_data (FpDevice *device,
|
||||
FpiDeviceUdevSubtypeFlags subtype);
|
||||
//const gchar *fpi_device_get_spi_dev (FpDevice *device);
|
||||
|
||||
|
||||
FpiDeviceAction fpi_device_get_current_action (FpDevice *device);
|
||||
|
||||
@@ -120,10 +120,13 @@ fp_image_device_change_state (FpImageDevice *self, FpiImageDeviceState state)
|
||||
{ FPI_IMAGE_DEVICE_STATE_DEACTIVATING, FPI_IMAGE_DEVICE_STATE_INACTIVE },
|
||||
};
|
||||
|
||||
prev_state_str = g_enum_to_string (FPI_TYPE_IMAGE_DEVICE_STATE, priv->state);
|
||||
state_str = g_enum_to_string (FPI_TYPE_IMAGE_DEVICE_STATE, state);
|
||||
fp_dbg ("Image device internal state change from %s to %s",
|
||||
prev_state_str, state_str);
|
||||
if (!g_log_writer_default_would_drop (G_LOG_LEVEL_DEBUG, G_LOG_DOMAIN))
|
||||
{
|
||||
prev_state_str = g_enum_to_string (FPI_TYPE_IMAGE_DEVICE_STATE, priv->state);
|
||||
state_str = g_enum_to_string (FPI_TYPE_IMAGE_DEVICE_STATE, state);
|
||||
fp_dbg ("Image device internal state change from %s to %s",
|
||||
prev_state_str, state_str);
|
||||
}
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (valid_transitions); i++)
|
||||
{
|
||||
@@ -134,8 +137,15 @@ fp_image_device_change_state (FpImageDevice *self, FpiImageDeviceState state)
|
||||
}
|
||||
}
|
||||
if (!transition_is_valid)
|
||||
g_warning ("Internal state machine issue: transition from %s to %s should not happen!",
|
||||
prev_state_str, state_str);
|
||||
{
|
||||
if (!prev_state_str)
|
||||
prev_state_str = g_enum_to_string (FPI_TYPE_IMAGE_DEVICE_STATE, priv->state);
|
||||
if (!state_str)
|
||||
state_str = g_enum_to_string (FPI_TYPE_IMAGE_DEVICE_STATE, state);
|
||||
|
||||
g_warning ("Internal state machine issue: transition from %s to %s should not happen!",
|
||||
prev_state_str, state_str);
|
||||
}
|
||||
|
||||
priv->state = state;
|
||||
g_object_notify (G_OBJECT (self), "fpi-image-device-state");
|
||||
@@ -214,10 +224,6 @@ fp_image_device_maybe_complete_action (FpImageDevice *self, GError *error)
|
||||
|
||||
fpi_device_enroll_complete (device, g_object_ref (enroll_print), NULL);
|
||||
}
|
||||
else if (action == FPI_DEVICE_ACTION_VERIFY)
|
||||
{
|
||||
fpi_device_verify_complete (device, NULL);
|
||||
}
|
||||
else if (action == FPI_DEVICE_ACTION_IDENTIFY)
|
||||
{
|
||||
fpi_device_identify_complete (device, NULL);
|
||||
@@ -316,22 +322,6 @@ fpi_image_device_minutiae_detected (GObject *source_object, GAsyncResult *res, g
|
||||
fp_image_device_enroll_maybe_await_finger_on (FP_IMAGE_DEVICE (device));
|
||||
}
|
||||
}
|
||||
else if (action == FPI_DEVICE_ACTION_VERIFY)
|
||||
{
|
||||
FpPrint *template;
|
||||
FpiMatchResult result;
|
||||
|
||||
fpi_device_get_verify_data (device, &template);
|
||||
if (print)
|
||||
result = fpi_print_bz3_match (template, print, priv->bz3_threshold, &error);
|
||||
else
|
||||
result = FPI_MATCH_ERROR;
|
||||
|
||||
if (!error || error->domain == FP_DEVICE_RETRY)
|
||||
fpi_device_verify_report (device, result, g_steal_pointer (&print), g_steal_pointer (&error));
|
||||
|
||||
fp_image_device_maybe_complete_action (self, g_steal_pointer (&error));
|
||||
}
|
||||
else if (action == FPI_DEVICE_ACTION_IDENTIFY)
|
||||
{
|
||||
gint i;
|
||||
@@ -486,7 +476,6 @@ fpi_image_device_image_captured (FpImageDevice *self, FpImage *image)
|
||||
g_return_if_fail (image != NULL);
|
||||
g_return_if_fail (priv->state == FPI_IMAGE_DEVICE_STATE_CAPTURE);
|
||||
g_return_if_fail (action == FPI_DEVICE_ACTION_ENROLL ||
|
||||
action == FPI_DEVICE_ACTION_VERIFY ||
|
||||
action == FPI_DEVICE_ACTION_IDENTIFY ||
|
||||
action == FPI_DEVICE_ACTION_CAPTURE);
|
||||
|
||||
@@ -527,7 +516,6 @@ fpi_image_device_retry_scan (FpImageDevice *self, FpDeviceRetry retry)
|
||||
* all but INACTIVE */
|
||||
g_return_if_fail (priv->state != FPI_IMAGE_DEVICE_STATE_INACTIVE);
|
||||
g_return_if_fail (action == FPI_DEVICE_ACTION_ENROLL ||
|
||||
action == FPI_DEVICE_ACTION_VERIFY ||
|
||||
action == FPI_DEVICE_ACTION_IDENTIFY ||
|
||||
action == FPI_DEVICE_ACTION_CAPTURE);
|
||||
|
||||
@@ -540,13 +528,6 @@ fpi_image_device_retry_scan (FpImageDevice *self, FpDeviceRetry retry)
|
||||
|
||||
fp_image_device_change_state (self, FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_OFF);
|
||||
}
|
||||
else if (action == FPI_DEVICE_ACTION_VERIFY)
|
||||
{
|
||||
fpi_device_verify_report (FP_DEVICE (self), FPI_MATCH_ERROR, NULL, error);
|
||||
fp_image_device_maybe_complete_action (self, NULL);
|
||||
fpi_image_device_deactivate (self, TRUE);
|
||||
|
||||
}
|
||||
else if (action == FPI_DEVICE_ACTION_IDENTIFY)
|
||||
{
|
||||
fpi_device_identify_report (FP_DEVICE (self), NULL, NULL, error);
|
||||
@@ -639,7 +620,6 @@ fpi_image_device_activate_complete (FpImageDevice *self, GError *error)
|
||||
g_return_if_fail (priv->active == FALSE);
|
||||
g_return_if_fail (priv->state == FPI_IMAGE_DEVICE_STATE_ACTIVATING);
|
||||
g_return_if_fail (action == FPI_DEVICE_ACTION_ENROLL ||
|
||||
action == FPI_DEVICE_ACTION_VERIFY ||
|
||||
action == FPI_DEVICE_ACTION_IDENTIFY ||
|
||||
action == FPI_DEVICE_ACTION_CAPTURE);
|
||||
|
||||
|
||||
@@ -79,6 +79,22 @@ fpi_print_set_type (FpPrint *print,
|
||||
g_object_notify (G_OBJECT (print), "fpi-type");
|
||||
}
|
||||
|
||||
/**
|
||||
* fpi_print_get_type:
|
||||
* @print: A #FpPrint
|
||||
*
|
||||
* Retrieves the type of the print data.
|
||||
*
|
||||
* Returns: The #FpiPrintType of the print.
|
||||
*/
|
||||
FpiPrintType
|
||||
fpi_print_get_type (FpPrint *print)
|
||||
{
|
||||
g_return_val_if_fail (FP_IS_PRINT (print), FPI_PRINT_UNDEFINED);
|
||||
|
||||
return print->type;
|
||||
}
|
||||
|
||||
/**
|
||||
* fpi_print_set_device_stored:
|
||||
* @print: A #FpPrint
|
||||
|
||||
@@ -35,6 +35,9 @@ void fpi_print_add_print (FpPrint *print,
|
||||
|
||||
void fpi_print_set_type (FpPrint *print,
|
||||
FpiPrintType type);
|
||||
|
||||
FpiPrintType fpi_print_get_type (FpPrint *print);
|
||||
|
||||
void fpi_print_set_device_stored (FpPrint *print,
|
||||
gboolean device_stored);
|
||||
|
||||
|
||||
@@ -44,6 +44,8 @@ log_transfer (FpiUsbTransfer *transfer, gboolean submit, GError *error)
|
||||
{
|
||||
if (fpi_log_is_debug_transfer_enabled ())
|
||||
{
|
||||
gboolean is_incoming = !!(transfer->endpoint & FPI_USB_ENDPOINT_IN);
|
||||
|
||||
if (!submit)
|
||||
{
|
||||
g_autofree gchar *error_str = NULL;
|
||||
@@ -67,11 +69,13 @@ log_transfer (FpiUsbTransfer *transfer, gboolean submit, GError *error)
|
||||
transfer->endpoint);
|
||||
}
|
||||
|
||||
if (!submit == !!(transfer->endpoint & FPI_USB_ENDPOINT_IN))
|
||||
if (submit != is_incoming)
|
||||
{
|
||||
fp_dbg_hex_dump_data (transfer->buffer,
|
||||
(transfer->endpoint & FPI_USB_ENDPOINT_IN) ?
|
||||
transfer->actual_length : transfer->length);
|
||||
gsize dump_length = is_incoming ? transfer->actual_length : transfer->length;
|
||||
|
||||
/* Skip hex dump if actual_length is invalid (e.g., -1 on cancelled IN transfers) */
|
||||
if (dump_length <= transfer->length)
|
||||
fp_dbg_hex_dump_data (transfer->buffer, dump_length);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,20 +26,25 @@
|
||||
|
||||
static const FpIdEntry allowlist_id_table[] = {
|
||||
/* Currently known and unsupported devices.
|
||||
* You can generate this list from the wiki page using e.g.:
|
||||
* gio cat https://gitlab.freedesktop.org/libfprint/wiki/-/wikis/Unsupported-Devices.md | sed -n 's!|.*\([0-9a-fA-F]\{4\}\):\([0-9a-fA-F]\{4\}\).*|.*! { .vid = 0x\1, .pid = 0x\2 },!p'
|
||||
* You can regenerate this list from the wiki page with:
|
||||
* meson compile -C <build-dir> sync-unsupported-devices
|
||||
*/
|
||||
{ .vid = 0x0a5c, .pid = 0x5802 },
|
||||
/* --- BEGIN GENERATED IDS --- */
|
||||
{ .vid = 0x006b, .pid = 0x00da },
|
||||
{ .vid = 0x0413, .pid = 0x2766 },
|
||||
{ .vid = 0x045e, .pid = 0x0815 },
|
||||
{ .vid = 0x047d, .pid = 0x00f2 },
|
||||
{ .vid = 0x047d, .pid = 0x8054 },
|
||||
{ .vid = 0x047d, .pid = 0x8055 },
|
||||
{ .vid = 0x0483, .pid = 0x2016 },
|
||||
{ .vid = 0x04e8, .pid = 0x730b },
|
||||
{ .vid = 0x04f2, .pid = 0xb61e },
|
||||
{ .vid = 0x04f3, .pid = 0x036b },
|
||||
{ .vid = 0x04f3, .pid = 0x0c00 },
|
||||
{ .vid = 0x04f3, .pid = 0x0c4c },
|
||||
{ .vid = 0x04f3, .pid = 0x0c57 },
|
||||
{ .vid = 0x04f3, .pid = 0x0c5e },
|
||||
{ .vid = 0x04f3, .pid = 0x0c5a },
|
||||
{ .vid = 0x04f3, .pid = 0x0c5e },
|
||||
{ .vid = 0x04f3, .pid = 0x0c60 },
|
||||
{ .vid = 0x04f3, .pid = 0x0c6c },
|
||||
{ .vid = 0x04f3, .pid = 0x0c70 },
|
||||
@@ -49,15 +54,28 @@ static const FpIdEntry allowlist_id_table[] = {
|
||||
{ .vid = 0x04f3, .pid = 0x0c7f },
|
||||
{ .vid = 0x04f3, .pid = 0x0c80 },
|
||||
{ .vid = 0x04f3, .pid = 0x0c85 },
|
||||
{ .vid = 0x04f3, .pid = 0x0c8a },
|
||||
{ .vid = 0x04f3, .pid = 0x0c8e },
|
||||
{ .vid = 0x04f3, .pid = 0x0c90 },
|
||||
{ .vid = 0x04f3, .pid = 0x0ca2 },
|
||||
{ .vid = 0x04f3, .pid = 0x24cc },
|
||||
{ .vid = 0x04f3, .pid = 0x2706 },
|
||||
{ .vid = 0x04f3, .pid = 0x3032 },
|
||||
{ .vid = 0x04f3, .pid = 0x3057 },
|
||||
{ .vid = 0x04f3, .pid = 0x3058 },
|
||||
{ .vid = 0x04f3, .pid = 0x3066 },
|
||||
{ .vid = 0x04f3, .pid = 0x3087 },
|
||||
{ .vid = 0x04f3, .pid = 0x309f },
|
||||
{ .vid = 0x04f3, .pid = 0x30c6 },
|
||||
{ .vid = 0x04f3, .pid = 0x3104 },
|
||||
{ .vid = 0x04f3, .pid = 0x310d },
|
||||
{ .vid = 0x04f3, .pid = 0x3128 },
|
||||
{ .vid = 0x04f3, .pid = 0x0c8a },
|
||||
{ .vid = 0x04f3, .pid = 0x3195 },
|
||||
{ .vid = 0x04f3, .pid = 0x31fc },
|
||||
{ .vid = 0x04f3, .pid = 0x3201 },
|
||||
{ .vid = 0x04f3, .pid = 0x3212 },
|
||||
{ .vid = 0x05ba, .pid = 0x000e },
|
||||
{ .vid = 0x05c8, .pid = 0x03c0 },
|
||||
{ .vid = 0x06cb, .pid = 0x0051 },
|
||||
{ .vid = 0x06cb, .pid = 0x0081 },
|
||||
{ .vid = 0x06cb, .pid = 0x0088 },
|
||||
@@ -71,8 +89,9 @@ static const FpIdEntry allowlist_id_table[] = {
|
||||
{ .vid = 0x06cb, .pid = 0x00bb },
|
||||
{ .vid = 0x06cb, .pid = 0x00bc },
|
||||
{ .vid = 0x06cb, .pid = 0x00be },
|
||||
{ .vid = 0x06cb, .pid = 0x00cb },
|
||||
{ .vid = 0x06cb, .pid = 0x00c7 },
|
||||
{ .vid = 0x06cb, .pid = 0x00c9 },
|
||||
{ .vid = 0x06cb, .pid = 0x00cb },
|
||||
{ .vid = 0x06cb, .pid = 0x00d8 },
|
||||
{ .vid = 0x06cb, .pid = 0x00da },
|
||||
{ .vid = 0x06cb, .pid = 0x00dc },
|
||||
@@ -80,7 +99,12 @@ static const FpIdEntry allowlist_id_table[] = {
|
||||
{ .vid = 0x06cb, .pid = 0x00e7 },
|
||||
{ .vid = 0x06cb, .pid = 0x00fd },
|
||||
{ .vid = 0x06cb, .pid = 0x00ff },
|
||||
{ .vid = 0x06cb, .pid = 0x0102 },
|
||||
{ .vid = 0x06cb, .pid = 0xce67 },
|
||||
{ .vid = 0x06cb, .pid = 0xceef },
|
||||
{ .vid = 0x08ff, .pid = 0x3400 },
|
||||
{ .vid = 0x0a5c, .pid = 0x5801 },
|
||||
{ .vid = 0x0a5c, .pid = 0x5802 },
|
||||
{ .vid = 0x0a5c, .pid = 0x5805 },
|
||||
{ .vid = 0x0a5c, .pid = 0x5834 },
|
||||
{ .vid = 0x0a5c, .pid = 0x5840 },
|
||||
@@ -95,6 +119,7 @@ static const FpIdEntry allowlist_id_table[] = {
|
||||
{ .vid = 0x0a5c, .pid = 0x5865 },
|
||||
{ .vid = 0x0a5c, .pid = 0x5866 },
|
||||
{ .vid = 0x0a5c, .pid = 0x5867 },
|
||||
{ .vid = 0x0bda, .pid = 0x0129 },
|
||||
{ .vid = 0x0bda, .pid = 0x5812 },
|
||||
{ .vid = 0x10a5, .pid = 0x0007 },
|
||||
{ .vid = 0x10a5, .pid = 0x9200 },
|
||||
@@ -105,6 +130,7 @@ static const FpIdEntry allowlist_id_table[] = {
|
||||
{ .vid = 0x10a5, .pid = 0xa921 },
|
||||
{ .vid = 0x10a5, .pid = 0xe340 },
|
||||
{ .vid = 0x1188, .pid = 0x9545 },
|
||||
{ .vid = 0x138a, .pid = 0x0006 },
|
||||
{ .vid = 0x138a, .pid = 0x0007 },
|
||||
{ .vid = 0x138a, .pid = 0x003a },
|
||||
{ .vid = 0x138a, .pid = 0x003c },
|
||||
@@ -115,8 +141,8 @@ static const FpIdEntry allowlist_id_table[] = {
|
||||
{ .vid = 0x138a, .pid = 0x0094 },
|
||||
{ .vid = 0x138a, .pid = 0x0097 },
|
||||
{ .vid = 0x138a, .pid = 0x009d },
|
||||
{ .vid = 0x138a, .pid = 0x00ab },
|
||||
{ .vid = 0x138a, .pid = 0x00a6 },
|
||||
{ .vid = 0x138a, .pid = 0x00ab },
|
||||
{ .vid = 0x147e, .pid = 0x1002 },
|
||||
{ .vid = 0x1491, .pid = 0x0088 },
|
||||
{ .vid = 0x16d1, .pid = 0x1027 },
|
||||
@@ -125,6 +151,9 @@ static const FpIdEntry allowlist_id_table[] = {
|
||||
{ .vid = 0x1c7a, .pid = 0x0576 },
|
||||
{ .vid = 0x1c7a, .pid = 0x0577 },
|
||||
{ .vid = 0x1c7a, .pid = 0x057e },
|
||||
{ .vid = 0x1c7a, .pid = 0x05a5 },
|
||||
{ .vid = 0x1c7a, .pid = 0x05aa },
|
||||
{ .vid = 0x1c7a, .pid = 0x0801 },
|
||||
{ .vid = 0x2541, .pid = 0x0236 },
|
||||
{ .vid = 0x2541, .pid = 0x9711 },
|
||||
{ .vid = 0x27c6, .pid = 0x5042 },
|
||||
@@ -152,22 +181,27 @@ static const FpIdEntry allowlist_id_table[] = {
|
||||
{ .vid = 0x27c6, .pid = 0x55a4 },
|
||||
{ .vid = 0x27c6, .pid = 0x55b4 },
|
||||
{ .vid = 0x27c6, .pid = 0x5740 },
|
||||
{ .vid = 0x27c6, .pid = 0x5e0a },
|
||||
{ .vid = 0x27c6, .pid = 0x581a },
|
||||
{ .vid = 0x27c6, .pid = 0x589a },
|
||||
{ .vid = 0x27c6, .pid = 0x5e0a },
|
||||
{ .vid = 0x27c6, .pid = 0x5f10 },
|
||||
{ .vid = 0x27c6, .pid = 0x5f91 },
|
||||
{ .vid = 0x27c6, .pid = 0x6382 },
|
||||
{ .vid = 0x2808, .pid = 0x06fc },
|
||||
{ .vid = 0x2808, .pid = 0x6652 },
|
||||
{ .vid = 0x2808, .pid = 0x9338 },
|
||||
{ .vid = 0x2808, .pid = 0x9348 },
|
||||
{ .vid = 0x2808, .pid = 0x93a9 },
|
||||
{ .vid = 0x2808, .pid = 0xa553 },
|
||||
{ .vid = 0x2808, .pid = 0xa573 },
|
||||
{ .vid = 0x2808, .pid = 0xa658 },
|
||||
{ .vid = 0x2808, .pid = 0xc652 },
|
||||
{ .vid = 0x2808, .pid = 0xa553 },
|
||||
{ .vid = 0x298d, .pid = 0x2020 },
|
||||
{ .vid = 0x298d, .pid = 0x2033 },
|
||||
{ .vid = 0x2df0, .pid = 0x0003 },
|
||||
{ .vid = 0x3274, .pid = 0x9008 },
|
||||
{ .vid = 0x3274, .pid = 0xb012 },
|
||||
{ .vid = 0x33a7, .pid = 0x2388 },
|
||||
{ .vid = 0x3538, .pid = 0x0930 },
|
||||
/* --- END GENERATED IDS --- */
|
||||
{ .vid = 0 },
|
||||
};
|
||||
|
||||
|
||||
+13
-7
@@ -1,7 +1,7 @@
|
||||
spi_sources = []
|
||||
spi_headers = []
|
||||
|
||||
if enabled_spi_drivers.length() > 0
|
||||
if have_spi
|
||||
spi_headers = ['fpi-spi-transfer.h']
|
||||
spi_sources = ['fpi-spi-transfer.c']
|
||||
endif
|
||||
@@ -146,6 +146,7 @@ helper_sources = {
|
||||
'aesx660': files('drivers/aesx660.c'),
|
||||
'aes3k': files('drivers/aes3k.c'),
|
||||
'openssl': files(),
|
||||
'pixman': files(),
|
||||
'udev': files(),
|
||||
'virtual': files('drivers/virtual-device-listener.c'),
|
||||
}
|
||||
@@ -300,8 +301,10 @@ libfprint_private_dep = declare_dependency(
|
||||
]
|
||||
)
|
||||
|
||||
udev_hwdb_list = 'fprint-list-udev-hwdb.c'
|
||||
udev_hwdb_list_file = files(udev_hwdb_list)
|
||||
udev_hwdb = executable('fprint-list-udev-hwdb',
|
||||
'fprint-list-udev-hwdb.c',
|
||||
udev_hwdb_list_file,
|
||||
dependencies: libfprint_private_dep,
|
||||
link_with: libfprint_drivers,
|
||||
install: false,
|
||||
@@ -352,10 +355,13 @@ if install_udev_rules
|
||||
)
|
||||
endif
|
||||
|
||||
sync_udev_udb = custom_target('sync-udev-hwdb',
|
||||
depends: udev_hwdb_generator,
|
||||
output: 'sync-udev-hwdb',
|
||||
install: false,
|
||||
udev_hwdb_list_updater = custom_target('udev-hwdb-list-updater',
|
||||
output: udev_hwdb_list,
|
||||
command: [ sync_unsupported_files, udev_hwdb_list_file ],
|
||||
)
|
||||
|
||||
run_target('sync-udev-hwdb',
|
||||
depends: udev_hwdb_list_updater,
|
||||
command: [
|
||||
'cp', '-v',
|
||||
udev_hwdb_generator.full_path(),
|
||||
@@ -363,7 +369,7 @@ sync_udev_udb = custom_target('sync-udev-hwdb',
|
||||
]
|
||||
)
|
||||
|
||||
alias_target('sync-udev-hwdb', sync_udev_udb)
|
||||
alias_target('sync-unsupported-devices', udev_hwdb_list_updater)
|
||||
|
||||
supported_devices = executable('fprint-list-supported-devices',
|
||||
'fprint-list-supported-devices.c',
|
||||
|
||||
+73
-104
@@ -1,16 +1,18 @@
|
||||
project('libfprint', [ 'c', 'cpp' ],
|
||||
version: '1.94.10',
|
||||
version: '1.94.100',
|
||||
license: 'LGPLv2.1+',
|
||||
default_options: [
|
||||
'buildtype=debugoptimized',
|
||||
'warning_level=1',
|
||||
'c_std=gnu99',
|
||||
],
|
||||
meson_version: '>= 0.59.0')
|
||||
meson_version: '>= 0.62.0')
|
||||
|
||||
fs = import('fs')
|
||||
gnome = import('gnome')
|
||||
|
||||
python3 = find_program('python3')
|
||||
|
||||
libfprint_conf = configuration_data()
|
||||
libfprint_conf.set_quoted('LIBFPRINT_VERSION', meson.project_version())
|
||||
|
||||
@@ -101,6 +103,8 @@ mathlib_dep = cc.find_library('m', required: false)
|
||||
sh = find_program('sh', required: true)
|
||||
cairo_dep = dependency('cairo', required: false)
|
||||
|
||||
sync_unsupported_files = files('scripts' / 'sync-unsupported-devices.py')
|
||||
|
||||
# introspection scanning and Gio-2.0.gir
|
||||
gobject_introspection = dependency('gobject-introspection-1.0', required: get_option('introspection'))
|
||||
|
||||
@@ -109,81 +113,60 @@ have_spi = host_machine.system() == 'linux'
|
||||
|
||||
# Drivers
|
||||
drivers = get_option('drivers').split(',')
|
||||
virtual_drivers = [
|
||||
'virtual_image',
|
||||
'virtual_device',
|
||||
'virtual_device_storage',
|
||||
]
|
||||
|
||||
default_drivers = [
|
||||
'upektc_img',
|
||||
'vfs5011',
|
||||
'vfs7552',
|
||||
'aes3500',
|
||||
'aes4000',
|
||||
'aes1610',
|
||||
'aes1660',
|
||||
'aes2660',
|
||||
'aes2501',
|
||||
'aes2550',
|
||||
'vfs101',
|
||||
'vfs301',
|
||||
'vfs0050',
|
||||
'etes603',
|
||||
'egis0570',
|
||||
'egismoc',
|
||||
'egis_etu905',
|
||||
'vcom5s',
|
||||
'synaptics',
|
||||
'elan',
|
||||
'elanmoc',
|
||||
'uru4000',
|
||||
'upektc',
|
||||
'upeksonly',
|
||||
'upekts',
|
||||
'goodixmoc',
|
||||
'nb1010',
|
||||
'fpcmoc',
|
||||
'realtek',
|
||||
'focaltech_moc',
|
||||
'mafpmoc',
|
||||
'secugen',
|
||||
]
|
||||
drivers_info = {
|
||||
'upektc_img': {},
|
||||
'vfs5011': { 'endian_dependent': true },
|
||||
'vfs7552': {},
|
||||
'aes3500': { 'helper': ['aeslib', 'aes3k', 'pixman'] },
|
||||
'aes4000': { 'helper': ['aeslib', 'aes3k', 'pixman'] },
|
||||
'aes1610': { 'helper': ['aeslib'] },
|
||||
'aes1660': { 'helper': ['aeslib', 'aesx660'] },
|
||||
'aes2660': { 'helper': ['aeslib', 'aesx660'] },
|
||||
'aes2501': { 'helper': ['aeslib'] },
|
||||
'aes2550': { 'helper': ['aeslib'] },
|
||||
'vfs101': {},
|
||||
'vfs301': { 'endian_dependent': true },
|
||||
'vfs0050': { 'endian_dependent': true },
|
||||
'etes603': {},
|
||||
'egis0570': {},
|
||||
'egismoc': {},
|
||||
'egis_etu905': {},
|
||||
'vcom5s': {},
|
||||
'synaptics': {},
|
||||
'elan': { 'endian_dependent': true },
|
||||
'elanmoc': {},
|
||||
'uru4000': { 'helper': ['openssl'] },
|
||||
'upektc': {},
|
||||
'upeksonly': {},
|
||||
'upekts': {},
|
||||
'goodixmoc': {},
|
||||
'nb1010': {},
|
||||
'fpcmoc': {},
|
||||
'realtek': {},
|
||||
'focaltech_moc': {},
|
||||
'mafpmoc': {},
|
||||
'secugen': {},
|
||||
|
||||
spi_drivers = [
|
||||
'elanspi'
|
||||
]
|
||||
# SPI driver (non-optional if SPI is available)
|
||||
'elanspi': { 'spi': true, 'helper': ['udev'], 'optional': not have_spi },
|
||||
|
||||
if have_spi
|
||||
default_drivers += spi_drivers
|
||||
endif
|
||||
# Virtual drivers (test-only, optional)
|
||||
'virtual_image': { 'virtual': true, 'helper': ['virtual'], 'optional': true },
|
||||
'virtual_device': { 'virtual': true, 'helper': ['virtual'], 'optional': true },
|
||||
'virtual_device_storage': { 'virtual': true, 'helper': ['virtual'], 'optional': true },
|
||||
}
|
||||
|
||||
# FIXME: All the drivers should be fixed by adjusting the byte order.
|
||||
# See https://gitlab.freedesktop.org/libfprint/libfprint/-/issues/236
|
||||
endian_independent_drivers = virtual_drivers + [
|
||||
'aes1610',
|
||||
'aes1660',
|
||||
'aes2550',
|
||||
'aes2660',
|
||||
'aes3500',
|
||||
'aes4000',
|
||||
'egis0570',
|
||||
'egismoc',
|
||||
'egis_etu905',
|
||||
'elanmoc',
|
||||
'etes603',
|
||||
'focaltech_moc',
|
||||
'nb1010',
|
||||
'realtek',
|
||||
'synaptics',
|
||||
'upeksonly',
|
||||
'upektc',
|
||||
'upektc_img',
|
||||
'upekts',
|
||||
'vcom5s',
|
||||
'vfs101',
|
||||
'vfs7552',
|
||||
]
|
||||
default_drivers = []
|
||||
virtual_drivers = []
|
||||
foreach name, info : drivers_info
|
||||
if not info.get('optional', false)
|
||||
default_drivers += name
|
||||
endif
|
||||
if info.get('virtual', false)
|
||||
virtual_drivers += name
|
||||
endif
|
||||
endforeach
|
||||
|
||||
all_drivers = default_drivers + virtual_drivers
|
||||
|
||||
@@ -195,36 +178,18 @@ if drivers == [ 'default' ]
|
||||
drivers = default_drivers
|
||||
endif
|
||||
|
||||
enabled_spi_drivers = []
|
||||
foreach driver : spi_drivers
|
||||
if driver in drivers
|
||||
enabled_spi_drivers += driver
|
||||
endif
|
||||
endforeach
|
||||
|
||||
if enabled_spi_drivers.length() > 0 and not have_spi
|
||||
error('SPI drivers @0@ are not supported'.format(enabled_spi_drivers))
|
||||
if not have_spi
|
||||
foreach driver: drivers
|
||||
if drivers_info[driver].get('spi', false)
|
||||
error('SPI driver @0@ is not supported'.format(driver))
|
||||
endif
|
||||
endforeach
|
||||
endif
|
||||
|
||||
driver_helper_mapping = {
|
||||
'aes1610' : [ 'aeslib' ],
|
||||
'aes1660' : [ 'aeslib', 'aesx660' ],
|
||||
'aes2501' : [ 'aeslib' ],
|
||||
'aes2550' : [ 'aeslib' ],
|
||||
'aes2660' : [ 'aeslib', 'aesx660' ],
|
||||
'aes3500' : [ 'aeslib', 'aes3k' ],
|
||||
'aes4000' : [ 'aeslib', 'aes3k' ],
|
||||
'uru4000' : [ 'openssl' ],
|
||||
'elanspi' : [ 'udev' ],
|
||||
'virtual_image' : [ 'virtual' ],
|
||||
'virtual_device' : [ 'virtual' ],
|
||||
'virtual_device_storage' : [ 'virtual' ],
|
||||
}
|
||||
|
||||
driver_helpers = []
|
||||
foreach driver : drivers
|
||||
if driver in driver_helper_mapping
|
||||
foreach helper : driver_helper_mapping[driver]
|
||||
if driver in drivers_info
|
||||
foreach helper : drivers_info[driver].get('helper', [])
|
||||
if helper not in driver_helpers
|
||||
driver_helpers += helper
|
||||
endif
|
||||
@@ -256,14 +221,14 @@ optional_deps = []
|
||||
|
||||
# Resolve extra dependencies
|
||||
foreach i : driver_helpers
|
||||
foreach d, helpers : driver_helper_mapping
|
||||
if i in helpers
|
||||
driver = d
|
||||
foreach name, info : drivers_info
|
||||
if i in info.get('helper', [])
|
||||
driver = name
|
||||
break
|
||||
endif
|
||||
endforeach
|
||||
|
||||
if i == 'aes3k'
|
||||
if i == 'pixman'
|
||||
imaging_dep = dependency('pixman-1', required: false)
|
||||
if not imaging_dep.found()
|
||||
error('pixman is required for @0@ and possibly others'.format(driver))
|
||||
@@ -304,9 +269,11 @@ if install_udev_rules
|
||||
endif
|
||||
endif
|
||||
|
||||
# FIXME: All the drivers should be fixed by adjusting the byte order.
|
||||
# See https://gitlab.freedesktop.org/libfprint/libfprint/-/issues/236
|
||||
supported_drivers = []
|
||||
foreach driver: drivers
|
||||
if build_machine.endian() == 'little' or driver in endian_independent_drivers
|
||||
if build_machine.endian() == 'little' or not drivers_info[driver].get('endian_dependent', false)
|
||||
supported_drivers += driver
|
||||
else
|
||||
warning('Driver @0@ is not supported by big endian cpu @1@. Please, fix it!'.format(
|
||||
@@ -367,6 +334,8 @@ subdir('tests')
|
||||
|
||||
subdir('examples')
|
||||
|
||||
meson.add_dist_script(sync_unsupported_files, '--check', udev_hwdb_list_file)
|
||||
|
||||
pkgconfig = import('pkgconfig')
|
||||
pkgconfig.generate(
|
||||
name: versioned_libname,
|
||||
|
||||
Executable
+81
@@ -0,0 +1,81 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Update the hardcoded allowlist of currently unsupported devices in
|
||||
# fprint-list-udev-hwdb.c from the libfprint wiki page.
|
||||
|
||||
import argparse
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
from urllib.request import urlopen
|
||||
|
||||
DEFAULT_URL = (
|
||||
"https://gitlab.freedesktop.org/libfprint/wiki/-/wikis/Unsupported-Devices.md"
|
||||
)
|
||||
|
||||
ID_RE = re.compile(r"\|.*([0-9a-fA-F]{4}):([0-9a-fA-F]{4}).*\|.*")
|
||||
|
||||
BEGIN_MARKER = " /* --- BEGIN GENERATED IDS --- */\n"
|
||||
END_MARKER = " /* --- END GENERATED IDS --- */\n"
|
||||
|
||||
|
||||
def fetch(url):
|
||||
try:
|
||||
with urlopen(url) as response:
|
||||
return response.read().decode("utf-8")
|
||||
except OSError as exc:
|
||||
print(f"Could not download {url}: {exc}", file=sys.stderr)
|
||||
sys.exit(77)
|
||||
|
||||
|
||||
def parse_entries(text):
|
||||
devices = set()
|
||||
for line in text.splitlines():
|
||||
match = ID_RE.match(line)
|
||||
if match:
|
||||
devices.add((match.group(1).lower(), match.group(2).lower()))
|
||||
return [f" {{ .vid = 0x{vid}, .pid = 0x{pid} }}," for vid, pid in sorted(devices)]
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument("source_file", help="Path to hwdb file")
|
||||
parser.add_argument("--url", default=DEFAULT_URL, help="Wiki page URL")
|
||||
parser.add_argument(
|
||||
"--check",
|
||||
action="store_true",
|
||||
help="Do not modify files, fail if an update is needed",
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
||||
entries = parse_entries(fetch(args.url))
|
||||
if not entries:
|
||||
sys.exit("No device ids found on the wiki page")
|
||||
|
||||
with open(args.source_file, "r", encoding="utf-8") as f:
|
||||
content = f.read()
|
||||
|
||||
before, begin, rest = content.partition(BEGIN_MARKER)
|
||||
_, end, after = rest.partition(END_MARKER)
|
||||
if not begin or not end:
|
||||
sys.exit("Could not locate generated id markers in " + args.source_file)
|
||||
|
||||
block = BEGIN_MARKER + "\n".join(entries) + "\n" + END_MARKER
|
||||
new_content = before + block + after
|
||||
|
||||
if new_content == content:
|
||||
print("allowlist_id_table is already up to date")
|
||||
return
|
||||
|
||||
if args.check:
|
||||
print("allowlist_id_table is out of date", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
with open(args.source_file, "w", encoding="utf-8") as f:
|
||||
f.write(new_content)
|
||||
|
||||
print(f"Updated allowlist_id_table with {len(entries)} entries")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -54,7 +54,7 @@ sp_attribute_paren remove
|
||||
sp_macro Force
|
||||
sp_func_call_paren Force
|
||||
sp_func_call_user_paren Remove
|
||||
set func_call_user _ N_ C_ g_autoptr g_auto
|
||||
set func_call_user _ N_ C_ g_autoptr g_auto g_autolist g_autoslist
|
||||
sp_brace_typedef add
|
||||
sp_cond_colon add
|
||||
sp_cond_question add
|
||||
|
||||
+7
-4
@@ -14,9 +14,9 @@ script, capture it and store the capture to `custom.pcapng`.
|
||||
'capture' and 'custom' Test Creation
|
||||
------------------------------------
|
||||
|
||||
For image devices the `capture.py` script will be used to capture one reference
|
||||
image. If the driver is a non-image driver, then a `custom.py` script should be
|
||||
created in advance, which will be run instead.
|
||||
For image devices, use the `capture` test to capture one reference image. For
|
||||
non-image drivers, create a `custom.py` script in advance and select the
|
||||
`custom` test instead.
|
||||
|
||||
1. Make sure that libfprint is built with support for the device driver
|
||||
that you want to create a test case for.
|
||||
@@ -26,9 +26,12 @@ created in advance, which will be run instead.
|
||||
but the hardware is slightly different, you might want to pass a variant
|
||||
name as a command-line options, for example:
|
||||
```sh
|
||||
$ sudo tests/create-driver-test.py driver [variant]
|
||||
$ sudo tests/create-driver-test.py [--test capture|custom] driver [variant]
|
||||
```
|
||||
|
||||
By default, the tool runs `capture.py` and, when present, the test directory's
|
||||
`custom.py`. Use `--test capture` or `--test custom` to record only that test.
|
||||
|
||||
3. If the capture is not successful, run the tool again to start another capture.
|
||||
|
||||
4. Add driver test name to `drivers_tests` in the `meson.build`, as instructed,
|
||||
|
||||
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 74 KiB |
Binary file not shown.
@@ -0,0 +1,41 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import sys
|
||||
import traceback
|
||||
import gi
|
||||
|
||||
gi.require_version('FPrint', '2.0')
|
||||
from gi.repository import FPrint, GLib
|
||||
|
||||
# Exit with error on any exception, included those happening in async callbacks
|
||||
sys.excepthook = lambda *args: (traceback.print_exception(*args), sys.exit(1))
|
||||
|
||||
if len(sys.argv) != 1:
|
||||
print("This test does not accept arguments")
|
||||
sys.exit(1)
|
||||
|
||||
ctx = GLib.main_context_default()
|
||||
|
||||
c = FPrint.Context()
|
||||
c.enumerate()
|
||||
devices = c.get_devices()
|
||||
|
||||
d = devices[0]
|
||||
del devices
|
||||
|
||||
d.open_sync()
|
||||
|
||||
# We're testing that the device returns an error when only tapping the it.
|
||||
print("Please tap the fingerprint reader, but do not swipe your finger across it.")
|
||||
try:
|
||||
d.capture_sync(True)
|
||||
except GLib.Error as error:
|
||||
assert error.matches(FPrint.device_retry_quark(),
|
||||
FPrint.DeviceRetry.TOO_SHORT)
|
||||
else:
|
||||
raise AssertionError("Capture did not raise FP_DEVICE_RETRY_TOO_SHORT")
|
||||
finally:
|
||||
d.close_sync()
|
||||
|
||||
del d
|
||||
del c
|
||||
File diff suppressed because one or more lines are too long
@@ -3,9 +3,10 @@
|
||||
BUILDDIR='@BUILDDIR@'
|
||||
SRCDIR='@SRCDIR@'
|
||||
|
||||
import signal
|
||||
import argparse
|
||||
import os
|
||||
import sys
|
||||
import signal
|
||||
library_path = BUILDDIR + '/libfprint/'
|
||||
|
||||
# Relaunch ourselves with a changed environment so
|
||||
@@ -27,35 +28,31 @@ from gi.repository import FPrint
|
||||
gi.require_version('GUsb', '1.0')
|
||||
from gi.repository import GUsb
|
||||
|
||||
import re
|
||||
import shutil
|
||||
import subprocess
|
||||
import tempfile
|
||||
import time
|
||||
|
||||
def print_usage():
|
||||
print(f'Usage: {sys.argv[0]} driver [test-variant-name]')
|
||||
print('A test variant name is optional, and must be all lower case letters, or dashes, with no spaces')
|
||||
print(f'The captured data will be stored in {SRCDIR}/tests/[driver name]-[test variant name]')
|
||||
print(f'Create custom.py prior to execution for non image device tests.')
|
||||
def test_variant(value):
|
||||
if (not value or any(not (char.islower() or char == '-') for char in value) or
|
||||
value.startswith('-') or value.endswith('-')):
|
||||
raise argparse.ArgumentTypeError(
|
||||
'must contain only lowercase letters and dashes')
|
||||
return value
|
||||
|
||||
if len(sys.argv) > 3:
|
||||
print_usage()
|
||||
sys.exit(1)
|
||||
parser = argparse.ArgumentParser(
|
||||
description='Capture USB traffic for a libfprint driver test.')
|
||||
parser.add_argument('driver')
|
||||
parser.add_argument('variant', nargs='?', type=test_variant,
|
||||
help='Optional, lowercase test variant name')
|
||||
parser.add_argument('--test', choices=('capture', 'custom'),
|
||||
help='Run only the selected test (default: run both)')
|
||||
options = parser.parse_args()
|
||||
|
||||
driver_name = sys.argv[1]
|
||||
driver_name = options.driver
|
||||
os.environ['FP_DRIVERS_ALLOWLIST'] = driver_name
|
||||
|
||||
test_variant = None
|
||||
if len(sys.argv) == 3:
|
||||
valid_re = re.compile('[a-z-]*')
|
||||
test_variant = sys.argv[2]
|
||||
if (not valid_re.match(test_variant) or
|
||||
test_variant.startswith('-') or
|
||||
test_variant.endswith('-')):
|
||||
print(f'Invalid variant name {test_variant}\n')
|
||||
print_usage()
|
||||
sys.exit(1)
|
||||
test_variant = options.variant
|
||||
|
||||
# Check that running as root
|
||||
|
||||
@@ -94,6 +91,9 @@ print(f'### Detected USB device /dev/bus/usb/{bus_num:03d}/{device_num:03d}')
|
||||
|
||||
test_dir = SRCDIR + '/tests/' + test_name
|
||||
os.makedirs(test_dir, mode=0o775, exist_ok=True)
|
||||
custom_script = os.path.join(test_dir, 'custom.py')
|
||||
if options.test == 'custom' and not os.path.exists(custom_script):
|
||||
parser.error(f'custom test script does not exist: {custom_script}')
|
||||
|
||||
# Capture device info
|
||||
|
||||
@@ -110,32 +110,54 @@ usb_device.open()
|
||||
usb_device.reset()
|
||||
usb_device.close()
|
||||
|
||||
print(f'### Starting USB capture on usbmon{bus_num}')
|
||||
capture_pid = os.fork()
|
||||
assert(capture_pid >= 0)
|
||||
def capture_test(cmd, capture_file, prompt):
|
||||
print(f'### Starting USB capture on usbmon{bus_num}')
|
||||
capture_pid = os.fork()
|
||||
assert(capture_pid >= 0)
|
||||
|
||||
unfiltered_cap_path = os.path.join(tempfile.gettempdir(), 'capture-unfiltered.pcapng')
|
||||
if capture_pid == 0:
|
||||
os.setpgrp()
|
||||
args = ['tshark', '-q', '-i', f'usbmon{bus_num}', '-w', unfiltered_cap_path]
|
||||
os.execv(tshark, args)
|
||||
unfiltered_cap_path = os.path.join(tempfile.gettempdir(),
|
||||
f'{capture_file}-unfiltered.pcapng')
|
||||
if capture_pid == 0:
|
||||
os.setpgrp()
|
||||
args = ['tshark', '-q', '-i', f'usbmon{bus_num}', '-w', unfiltered_cap_path]
|
||||
os.execv(tshark, args)
|
||||
|
||||
# Wait 1 sec to settle (we can assume setpgrp happened)
|
||||
time.sleep(1)
|
||||
# Wait 1 sec to settle (we can assume setpgrp happened)
|
||||
time.sleep(1)
|
||||
|
||||
print('### Capturing fingerprint, please swipe or press your finger on the reader')
|
||||
cmd = ['python3', SRCDIR + '/tests/capture.py', test_dir + '/capture.png']
|
||||
capture_file = 'capture.pcapng' # capture for "capture" test
|
||||
if os.path.exists(os.path.join(test_dir, "custom.py")):
|
||||
cmd = ['python3', os.path.join(test_dir, "custom.py")]
|
||||
capture_file = "custom.pcapng"
|
||||
print(prompt)
|
||||
with subprocess.Popen([sys.executable] + cmd) as capture_process:
|
||||
capture_process.wait()
|
||||
if capture_process.returncode != 0:
|
||||
print('Failed to capture fingerprint')
|
||||
os.killpg(capture_pid, signal.SIGKILL)
|
||||
sys.exit(1)
|
||||
|
||||
with subprocess.Popen(cmd) as capture_process:
|
||||
capture_process.wait()
|
||||
if capture_process.returncode != 0:
|
||||
print('Failed to capture fingerprint')
|
||||
os.killpg(capture_pid, signal.SIGKILL)
|
||||
sys.exit(1)
|
||||
os.kill(capture_pid, signal.SIGTERM)
|
||||
try:
|
||||
r = t_waitpid(capture_pid, 2)
|
||||
# Kill if nothing died
|
||||
if r[0] == 0:
|
||||
os.kill(capture_pid, signal.SIGKILL)
|
||||
except ChildProcessError:
|
||||
pass
|
||||
|
||||
try:
|
||||
while True:
|
||||
r = t_waitpid(-capture_pid, timeout=2)
|
||||
# Kill the process group, if nothing died (and there are children)
|
||||
if r[0] == 0:
|
||||
os.killpg(capture_pid, signal.SIGKILL)
|
||||
except ChildProcessError:
|
||||
pass
|
||||
|
||||
# Filter the capture
|
||||
print(f'\n### Saving USB capture as test case {test_name}')
|
||||
args = ['tshark', '-r', unfiltered_cap_path,
|
||||
'-Y', f'usb.bus_id == {bus_num} and usb.device_address == {device_num}',
|
||||
'-w', os.path.join(test_dir, capture_file)]
|
||||
with subprocess.Popen(args, stderr=subprocess.DEVNULL) as filter_process:
|
||||
filter_process.wait()
|
||||
|
||||
def t_waitpid(pid, timeout):
|
||||
timeout = time.time() + timeout
|
||||
@@ -146,29 +168,13 @@ def t_waitpid(pid, timeout):
|
||||
|
||||
return r
|
||||
|
||||
os.kill(capture_pid, signal.SIGTERM)
|
||||
try:
|
||||
r = t_waitpid(capture_pid, 2)
|
||||
# Kill if nothing died
|
||||
if r[0] == 0:
|
||||
os.kill(capture_pid, signal.SIGKILL)
|
||||
except ChildProcessError:
|
||||
pass
|
||||
if options.test in (None, 'capture'):
|
||||
capture_test([SRCDIR + '/tests/capture.py', test_dir + '/capture.png'],
|
||||
'capture.pcapng',
|
||||
'### Capturing fingerprint, please swipe or press your finger on the reader')
|
||||
|
||||
try:
|
||||
while True:
|
||||
r = t_waitpid(-capture_pid, timeout=2)
|
||||
# Kill the process group, if nothing died (and there are children)
|
||||
if r[0] == 0:
|
||||
os.killpg(capture_pid, signal.SIGKILL)
|
||||
except ChildProcessError:
|
||||
pass
|
||||
|
||||
# Filter the capture
|
||||
print(f'\n### Saving USB capture as test case {test_name}')
|
||||
args = ['tshark', '-r', unfiltered_cap_path, '-Y', f'usb.bus_id == {bus_num} and usb.device_address == {device_num}',
|
||||
'-w', os.path.join(test_dir, capture_file)]
|
||||
with subprocess.Popen(args, stderr=subprocess.DEVNULL) as filter_process:
|
||||
filter_process.wait()
|
||||
if options.test in (None, 'custom') and os.path.exists(custom_script):
|
||||
capture_test([custom_script], 'custom.pcapng',
|
||||
'### Running the custom fingerprint capture')
|
||||
|
||||
print(f"\nDone! Don't forget to add {test_name} to tests/meson.build")
|
||||
|
||||
Binary file not shown.
+56
-22
@@ -39,7 +39,8 @@ def identify_done(dev, res):
|
||||
identified = True
|
||||
identify_match, identify_print = dev.identify_finish(res)
|
||||
print("MATCH FOUND!" if identify_match else "NO MATCH FOUND")
|
||||
assert identify_match.equal(identify_print)
|
||||
if identify_match:
|
||||
assert identify_match.equal(identify_print)
|
||||
|
||||
# List
|
||||
print("--- LISTING ---")
|
||||
@@ -64,6 +65,29 @@ prints2 = len(stored)
|
||||
print(f"--- LIST DONE: Found {prints2} prints after enroll---")
|
||||
assert (prints2 - prints1) == 1
|
||||
|
||||
# Verify
|
||||
print("--- VERIFYING ---")
|
||||
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
|
||||
verify_res, verify_print = d.verify_sync(p)
|
||||
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
|
||||
print(f"--- VERIFY DONE: Result {verify_res} ---")
|
||||
|
||||
# Identify
|
||||
print("--- ASYNC IDENTIFYING ---")
|
||||
identified = False
|
||||
deserialized_prints = []
|
||||
for sp in stored:
|
||||
deserialized_prints.append(FPrint.Print.deserialize(sp.serialize()))
|
||||
# The last stored print should be the newly enrolled one
|
||||
assert deserialized_prints[-1].equal(p)
|
||||
|
||||
d.identify(deserialized_prints, callback=identify_done)
|
||||
del deserialized_prints
|
||||
|
||||
while not identified:
|
||||
ctx.iteration(True)
|
||||
print("--- IDENTIFY DONE ---")
|
||||
|
||||
# Cancel test - start async identify and cancel it
|
||||
print("--- TESTING CANCELLATION ---")
|
||||
deserialized_prints = []
|
||||
@@ -84,7 +108,32 @@ def identify_cancelled_cb(dev, res):
|
||||
cancel_result = e
|
||||
print(f"Identify cancelled with error: {e}")
|
||||
|
||||
# Test 1: Cancel immediately after starting identify
|
||||
d.identify(deserialized_prints, cancellable=cancellable, callback=identify_cancelled_cb)
|
||||
|
||||
print("--- IDENTIFY STARTED, CANCELLING IMMEDIATELY ---")
|
||||
cancellable.cancel()
|
||||
|
||||
while not identify_cancelled:
|
||||
ctx.iteration(True)
|
||||
print(f"--- CANCELLATION TEST DONE, result: {cancel_result} ---")
|
||||
|
||||
# Reopen device to ensure clean state for next cancel test
|
||||
print("--- REOPENING DEVICE BEFORE NEXT CANCEL TEST ---")
|
||||
d.close_sync()
|
||||
d.open_sync()
|
||||
print("--- DEVICE REOPENED ---")
|
||||
|
||||
# Test 2: Cancel after device reaches wait-for-finger stage
|
||||
cancellable = Gio.Cancellable()
|
||||
identify_cancelled = False
|
||||
cancel_result = None
|
||||
d.identify(deserialized_prints, cancellable=cancellable, callback=identify_cancelled_cb)
|
||||
|
||||
# Wait until the device is actually waiting for a finger before cancelling.
|
||||
print("Waiting for device to reach wait-for-finger stage before cancelling...")
|
||||
while not (d.get_finger_status() & FPrint.FingerStatusFlags.NEEDED):
|
||||
ctx.iteration(True)
|
||||
cancellable.cancel()
|
||||
|
||||
while not identify_cancelled:
|
||||
@@ -92,27 +141,11 @@ while not identify_cancelled:
|
||||
print(f"--- CANCELLATION TEST DONE, result: {cancel_result} ---")
|
||||
del deserialized_prints
|
||||
|
||||
# Verify
|
||||
print("--- VERIFYING ---")
|
||||
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
|
||||
verify_res, verify_print = d.verify_sync(p)
|
||||
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
|
||||
print(f"--- VERIFY DONE: Result {verify_res} ---")
|
||||
|
||||
# Identify
|
||||
print("--- ASYNC IDENTIFYING ---")
|
||||
identified = False
|
||||
deserialized_prints = []
|
||||
for p in stored:
|
||||
deserialized_prints.append(FPrint.Print.deserialize(p.serialize()))
|
||||
assert deserialized_prints[-1].equal(p)
|
||||
|
||||
d.identify(deserialized_prints, callback=identify_done)
|
||||
del deserialized_prints
|
||||
|
||||
while not identified:
|
||||
ctx.iteration(True)
|
||||
print("--- IDENTIFY DONE ---")
|
||||
# Close and reopen device to ensure clean state after cancellation
|
||||
print("--- REOPENING DEVICE ---")
|
||||
d.close_sync()
|
||||
d.open_sync()
|
||||
print("--- DEVICE REOPENED ---")
|
||||
|
||||
# Delete
|
||||
print("--- DELETING ---")
|
||||
@@ -135,3 +168,4 @@ d.close_sync()
|
||||
|
||||
del d
|
||||
del c
|
||||
|
||||
|
||||
+97
-170
File diff suppressed because one or more lines are too long
@@ -1,54 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import os
|
||||
import sys
|
||||
import urllib
|
||||
import urllib.request
|
||||
import re
|
||||
|
||||
error = False
|
||||
|
||||
try:
|
||||
response = urllib.request.urlopen('https://gitlab.freedesktop.org/libfprint/wiki/-/wikis/Unsupported-Devices.md')
|
||||
except:
|
||||
print("Could not download current list of unsupported devices, skipping test.")
|
||||
sys.exit(77)
|
||||
data = response.read().decode('utf-8')
|
||||
|
||||
devices = []
|
||||
devices_re = re.compile(r'^.*([0-9a-fA-F]{4}):([0-9a-fA-F]{4}).*$', re.MULTILINE)
|
||||
for m in devices_re.finditer(data):
|
||||
vid = m.group(1)
|
||||
pid = m.group(2)
|
||||
devices.append((vid, pid))
|
||||
|
||||
generator = open(os.path.join(os.path.dirname(__file__), '..', 'libfprint', 'fprint-list-udev-hwdb.c')).read()
|
||||
|
||||
id_re = re.compile(' { .vid = 0x([a-fA-F0-9]*), .pid = 0x([a-fA-F0-9]*) }')
|
||||
# Check everything is the same
|
||||
started = False
|
||||
for l in generator.split('\n'):
|
||||
m = id_re.match(l)
|
||||
if m is None:
|
||||
# Stop on the first line that does not match anymore
|
||||
if started:
|
||||
break
|
||||
continue
|
||||
else:
|
||||
started = True
|
||||
|
||||
vid_pid = (m.group(1), m.group(2))
|
||||
try:
|
||||
devices.remove(vid_pid)
|
||||
except ValueError:
|
||||
print("Generator has entry that is not on wiki: {}:{}".format(*vid_pid))
|
||||
error = True
|
||||
|
||||
for vid_pid in devices:
|
||||
print("New entry from wiki is missing: {}:{}".format(*vid_pid))
|
||||
error = True
|
||||
|
||||
if error:
|
||||
sys.exit(1)
|
||||
else:
|
||||
sys.exit(0)
|
||||
+47
-20
@@ -26,20 +26,19 @@ envs.set('FP_PRINTS_PATH', meson.project_source_root() / 'examples' / 'prints')
|
||||
|
||||
envs.set('NO_AT_BRIDGE', '1')
|
||||
|
||||
python3 = find_program('python3')
|
||||
|
||||
installed_tests = get_option('installed-tests')
|
||||
installed_tests_execdir = libexecdir / 'installed-tests' / versioned_libname
|
||||
installed_tests_testdir = datadir / 'installed-tests' / versioned_libname
|
||||
installed_tests_libdir = libdir
|
||||
|
||||
drivers_tests = {
|
||||
'aes2501': {},
|
||||
'aes2501': { 'timeout': 20 },
|
||||
'aes2550': {},
|
||||
'aes3500': {},
|
||||
'elan': {},
|
||||
'elan-cobo': {},
|
||||
'elanmoc': {},
|
||||
'elanspi': {},
|
||||
'elanspi': { 'timeout': 30 },
|
||||
'synaptics': {},
|
||||
'upektc_img': {},
|
||||
'upektc_img-tcs1s': {},
|
||||
@@ -60,6 +59,7 @@ drivers_tests = {
|
||||
'fpcmoc': {},
|
||||
'realtek': {},
|
||||
'realtek-5816': {},
|
||||
'realtek-storage-errors': {},
|
||||
'focaltech_moc': { 'timeout': 30 },
|
||||
'focaltech_moc-6553': {},
|
||||
'mafpmoc': {},
|
||||
@@ -200,21 +200,48 @@ if get_option('introspection')
|
||||
|
||||
if (driver_name in supported_drivers and
|
||||
gusb_dep.version().version_compare('>= 0.3.0'))
|
||||
driver_tests_enabled = true
|
||||
test(driver_test,
|
||||
python3,
|
||||
args: [
|
||||
umockdev_test.full_path(),
|
||||
meson.current_source_dir() / driver_test,
|
||||
],
|
||||
env: driver_envs,
|
||||
suite: ['drivers'],
|
||||
timeout: args.get('timeout', 15),
|
||||
depends: [
|
||||
libfprint_typelib,
|
||||
test_emulation_lib,
|
||||
],
|
||||
)
|
||||
|
||||
test_types = []
|
||||
foreach test_type: args.get('test_types', ['custom', 'capture'])
|
||||
test_file_prefix = meson.current_source_dir() / driver_test / test_type
|
||||
if fs.exists(test_file_prefix + '.py')
|
||||
test_types += [test_type]
|
||||
elif fs.exists(test_file_prefix + '.png')
|
||||
test_types += [test_type]
|
||||
elif fs.exists(test_file_prefix + '.ioctl')
|
||||
test_types += [test_type]
|
||||
elif fs.exists(test_file_prefix + '.pcapng')
|
||||
test_types += [test_type]
|
||||
endif
|
||||
endforeach
|
||||
|
||||
assert(test_types.length() > 0,
|
||||
'No test types found for driver ' + driver_test)
|
||||
|
||||
foreach test_type: test_types
|
||||
driver_tests_enabled = true
|
||||
test_name = driver_test + (test_types.length() > 1 ? '-' + test_type : '')
|
||||
test(test_name,
|
||||
python3,
|
||||
args: [
|
||||
umockdev_test.full_path(),
|
||||
meson.current_source_dir() / driver_test,
|
||||
'--test', test_type,
|
||||
],
|
||||
env: driver_envs,
|
||||
is_parallel: args.get('is_parallel', true),
|
||||
priority: args.get('priority', 0),
|
||||
protocol: args.get('protocol', 'exitcode'),
|
||||
should_fail: args.get('should_fail', false),
|
||||
suite: ['drivers', test_type] + args.get('suite', []),
|
||||
timeout: args.get('timeout', 15),
|
||||
verbose: args.get('verbose', false),
|
||||
depends: [
|
||||
libfprint_typelib,
|
||||
test_emulation_lib,
|
||||
],
|
||||
)
|
||||
endforeach
|
||||
|
||||
if installed_tests
|
||||
driver_envs_str = run_command(python3, '-c', env_parser_cmd,
|
||||
@@ -266,7 +293,7 @@ else
|
||||
args: ['-c', 'exit 77']
|
||||
)
|
||||
|
||||
foreach driver_test: drivers_tests
|
||||
foreach driver_test, _args : drivers_tests
|
||||
test(driver_test,
|
||||
sh,
|
||||
args: ['-c', 'exit 77']
|
||||
|
||||
Binary file not shown.
@@ -0,0 +1,98 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# Deleting a print that is not in the sensor's storage makes the realtek driver
|
||||
# fail its task SSM, which is the path that used to hand an already-freed GError
|
||||
# to fpi_device_delete_complete(). Reading the reported error is therefore the
|
||||
# point of this test: before the fix it read freed memory, and the GError was
|
||||
# freed a second time when the GTask finalized.
|
||||
#
|
||||
# The print below is a stored realtek print, serialized, whose template is
|
||||
# deliberately not on the device.
|
||||
#
|
||||
# The same session then enrolls a finger and enrolls it again, checking that the
|
||||
# duplicate is reported as FP_DEVICE_ERROR_DATA_DUPLICATE rather than PROTO.
|
||||
|
||||
import base64
|
||||
import traceback
|
||||
import sys
|
||||
import gi
|
||||
|
||||
gi.require_version('FPrint', '2.0')
|
||||
from gi.repository import FPrint, GLib
|
||||
|
||||
# Exit with error on any exception, included those happening in async callbacks
|
||||
sys.excepthook = lambda *args: (traceback.print_exception(*args), sys.exit(1))
|
||||
|
||||
# A stored print for user 'testuser', right index finger, user id
|
||||
# 'FP1-20260101-7-DEADBEEF-test'.
|
||||
STORED_PRINT = base64.b64decode(
|
||||
'RlAzAQAAAHJlYWx0ZWsAMAABB3Rlc3R1c2VyAABGUDEtMjAyNjAxMDEtNy1ERUFEQkVFRi10ZXN0AAAhSQsAAAAAAP9GUDEtMjAyNjAxMDEtNy1ERUFEQkVFRi10ZXN0ACh5YXkpAHZAOBoODA==')
|
||||
|
||||
ctx = GLib.main_context_default()
|
||||
|
||||
c = FPrint.Context()
|
||||
c.enumerate()
|
||||
devices = c.get_devices()
|
||||
|
||||
d = devices[0]
|
||||
del devices
|
||||
|
||||
assert d.get_driver() == "realtek"
|
||||
assert d.has_feature(FPrint.DeviceFeature.STORAGE)
|
||||
assert d.has_feature(FPrint.DeviceFeature.STORAGE_DELETE)
|
||||
assert d.has_feature(FPrint.DeviceFeature.STORAGE_CLEAR)
|
||||
|
||||
d.open_sync()
|
||||
|
||||
# Make sure the device holds no templates, so the print below cannot match.
|
||||
d.clear_storage_sync()
|
||||
|
||||
p = FPrint.Print.deserialize(STORED_PRINT)
|
||||
assert p.get_driver() == "realtek"
|
||||
assert p.get_device_stored()
|
||||
assert p.get_finger() == FPrint.Finger.RIGHT_INDEX
|
||||
|
||||
print("deleting a print that is not in the device storage")
|
||||
try:
|
||||
d.delete_print_sync(p)
|
||||
except GLib.Error as error:
|
||||
print("delete reported: {}".format(error.message))
|
||||
assert error.matches(FPrint.DeviceError.quark(), FPrint.DeviceError.PROTO)
|
||||
assert error.message
|
||||
else:
|
||||
assert False, "deleting a template that is not stored should fail"
|
||||
del p
|
||||
print("delete attempt done")
|
||||
|
||||
# Storage is still empty, so enrolling the same finger twice must report the
|
||||
# error class expected by fprintd.
|
||||
|
||||
def enroll_progress(*args):
|
||||
print('enroll progress: ' + str(args))
|
||||
|
||||
template = FPrint.Print.new(d)
|
||||
|
||||
print("enrolling")
|
||||
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
|
||||
p = d.enroll_sync(template, None, enroll_progress, None)
|
||||
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
|
||||
print("enroll done")
|
||||
|
||||
print("enrolling duplicate")
|
||||
template = FPrint.Print.new(d)
|
||||
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
|
||||
try:
|
||||
d.enroll_sync(template, None, enroll_progress, None)
|
||||
except GLib.Error as error:
|
||||
assert error.matches(FPrint.DeviceError.quark(),
|
||||
FPrint.DeviceError.DATA_DUPLICATE)
|
||||
else:
|
||||
raise AssertionError("Duplicate enrollment unexpectedly succeeded")
|
||||
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
|
||||
print("duplicate enrollment rejected")
|
||||
|
||||
d.delete_print_sync(p)
|
||||
d.close_sync()
|
||||
|
||||
del d
|
||||
del c
|
||||
File diff suppressed because one or more lines are too long
+716
-15
@@ -19,6 +19,7 @@
|
||||
|
||||
#include "fp-device.h"
|
||||
#include "fp-enums.h"
|
||||
#include "fpi-print.h"
|
||||
#include <libfprint/fprint.h>
|
||||
|
||||
#define FP_COMPONENT "device"
|
||||
@@ -163,6 +164,34 @@ make_fake_nbis_print (FpDevice *device)
|
||||
return enrolled_print;
|
||||
}
|
||||
|
||||
static FpPrint *
|
||||
make_fake_nbis_print_filled (FpDevice *device,
|
||||
gint *xvals,
|
||||
gint *yvals,
|
||||
gint *tvals,
|
||||
gint nminutiae,
|
||||
gint nentries)
|
||||
{
|
||||
FpPrint *print = make_fake_nbis_print (device);
|
||||
|
||||
for (gint e = 0; e < nentries; e++)
|
||||
{
|
||||
struct xyt_struct *xyt = g_new0 (struct xyt_struct, 1);
|
||||
|
||||
xyt->nrows = nminutiae;
|
||||
for (gint m = 0; m < nminutiae; m++)
|
||||
{
|
||||
xyt->xcol[m] = xvals[m];
|
||||
xyt->ycol[m] = yvals[m];
|
||||
xyt->thetacol[m] = tvals[m];
|
||||
}
|
||||
|
||||
g_ptr_array_add (print->prints, xyt);
|
||||
}
|
||||
|
||||
return print;
|
||||
}
|
||||
|
||||
static FpPrint *
|
||||
make_fake_print_reffed (FpDevice *device,
|
||||
GVariant *print_data)
|
||||
@@ -672,6 +701,7 @@ test_driver_initial_features_no_verify (void)
|
||||
{
|
||||
g_autoptr(FpAutoResetClass) dev_class = auto_reset_device_class ();
|
||||
|
||||
dev_class->identify = NULL;
|
||||
dev_class->verify = NULL;
|
||||
dev_class->features = FP_DEVICE_FEATURE_NONE;
|
||||
|
||||
@@ -679,7 +709,7 @@ test_driver_initial_features_no_verify (void)
|
||||
|
||||
g_assert_cmpuint (dev_class->features, !=, FP_DEVICE_FEATURE_NONE);
|
||||
g_assert_true (dev_class->features & FP_DEVICE_FEATURE_CAPTURE);
|
||||
g_assert_true (dev_class->features & FP_DEVICE_FEATURE_IDENTIFY);
|
||||
g_assert_false (dev_class->features & FP_DEVICE_FEATURE_IDENTIFY);
|
||||
g_assert_false (dev_class->features & FP_DEVICE_FEATURE_VERIFY);
|
||||
g_assert_false (dev_class->features & FP_DEVICE_FEATURE_DUPLICATES_CHECK);
|
||||
g_assert_true (dev_class->features & FP_DEVICE_FEATURE_STORAGE);
|
||||
@@ -1346,7 +1376,7 @@ test_driver_match_cb (FpDevice *device,
|
||||
if (match)
|
||||
g_assert_no_error (error);
|
||||
|
||||
/* Compar gallery if this is an identify operation */
|
||||
/* Compare gallery if this is an identify operation */
|
||||
if (data->gallery)
|
||||
{
|
||||
FpiDeviceFake *fake_dev = FPI_DEVICE_FAKE (device);
|
||||
@@ -1509,6 +1539,43 @@ test_driver_verify_error (void)
|
||||
g_assert_false (match);
|
||||
}
|
||||
|
||||
static void
|
||||
test_driver_verify_mismatched_scanned_print (void)
|
||||
{
|
||||
g_autoptr(GError) error = NULL;
|
||||
g_autoptr(FpAutoCloseDevice) device = auto_close_fake_device_new ();
|
||||
g_autoptr(FpPrint) enrolled_print = NULL;
|
||||
g_autoptr(FpPrint) out_print = NULL;
|
||||
g_autoptr(MatchCbData) match_data = g_new0 (MatchCbData, 1);
|
||||
FpDeviceClass *dev_class = FP_DEVICE_GET_CLASS (device);
|
||||
FpiDeviceFake *fake_dev = FPI_DEVICE_FAKE (device);
|
||||
gboolean match;
|
||||
|
||||
enrolled_print = make_fake_print_reffed (device, g_variant_new_uint64 (3));
|
||||
fake_dev->ret_print = make_fake_print (device, g_variant_new_uint64 (7));
|
||||
g_object_add_weak_pointer (G_OBJECT (fake_dev->ret_print),
|
||||
(gpointer) (&fake_dev->ret_print));
|
||||
fake_dev->ret_result = FPI_MATCH_SUCCESS;
|
||||
|
||||
g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_WARNING,
|
||||
"*Driver reported a match providing a scanned print*");
|
||||
|
||||
g_assert_true (fp_device_verify_sync (device, enrolled_print, NULL,
|
||||
test_driver_match_cb, match_data,
|
||||
&match, &out_print, &error));
|
||||
|
||||
g_test_assert_expected_messages ();
|
||||
|
||||
g_assert (fake_dev->last_called_function == dev_class->verify);
|
||||
g_assert_no_error (error);
|
||||
|
||||
g_assert_true (match_data->called);
|
||||
g_assert_nonnull (match_data->match);
|
||||
g_assert_null (out_print);
|
||||
g_assert_true (match);
|
||||
g_assert_null (fake_dev->ret_print);
|
||||
}
|
||||
|
||||
static void
|
||||
fake_device_verify_immediate_complete (FpDevice *device)
|
||||
{
|
||||
@@ -1719,6 +1786,372 @@ test_driver_verify_complete_retry (void)
|
||||
g_clear_error (&error);
|
||||
}
|
||||
|
||||
static void
|
||||
test_driver_verify_via_identify (void)
|
||||
{
|
||||
g_autoptr(GError) error = NULL;
|
||||
g_autoptr(FpAutoResetClass) dev_class = auto_reset_device_class ();
|
||||
g_autoptr(FpAutoCloseDevice) device = NULL;
|
||||
g_autoptr(FpPrint) enrolled_print = NULL;
|
||||
g_autoptr(FpPrint) out_print = NULL;
|
||||
g_autoptr(MatchCbData) match_data = g_new0 (MatchCbData, 1);
|
||||
FpiDeviceFake *fake_dev;
|
||||
gboolean match;
|
||||
|
||||
dev_class->verify = NULL;
|
||||
|
||||
device = auto_close_fake_device_new ();
|
||||
fake_dev = FPI_DEVICE_FAKE (device);
|
||||
enrolled_print = make_fake_print_reffed (device, NULL);
|
||||
fake_dev->ret_match = enrolled_print;
|
||||
fake_dev->ret_print = enrolled_print;
|
||||
|
||||
g_assert_true (fp_device_verify_sync (device, enrolled_print, NULL,
|
||||
test_driver_match_cb, match_data,
|
||||
&match, &out_print, &error));
|
||||
|
||||
g_assert (fake_dev->last_called_function == dev_class->identify);
|
||||
g_assert_no_error (error);
|
||||
|
||||
g_assert_true (match_data->called);
|
||||
g_assert_nonnull (match_data->match);
|
||||
g_assert_true (match_data->print == out_print);
|
||||
g_assert_true (match_data->match == enrolled_print);
|
||||
|
||||
g_assert (out_print == enrolled_print);
|
||||
g_assert_true (match);
|
||||
}
|
||||
|
||||
static void
|
||||
test_driver_verify_via_identify_fail (void)
|
||||
{
|
||||
g_autoptr(GError) error = NULL;
|
||||
g_autoptr(FpAutoResetClass) dev_class = auto_reset_device_class ();
|
||||
g_autoptr(FpAutoCloseDevice) device = NULL;
|
||||
g_autoptr(FpPrint) enrolled_print = NULL;
|
||||
g_autoptr(FpPrint) out_print = NULL;
|
||||
g_autoptr(MatchCbData) match_data = g_new0 (MatchCbData, 1);
|
||||
FpiDeviceFake *fake_dev;
|
||||
gboolean match;
|
||||
|
||||
dev_class->verify = NULL;
|
||||
|
||||
device = auto_close_fake_device_new ();
|
||||
fake_dev = FPI_DEVICE_FAKE (device);
|
||||
|
||||
enrolled_print = make_fake_print_reffed (device, g_variant_new_uint64 (3));
|
||||
fake_dev->ret_match = NULL;
|
||||
fake_dev->ret_print = enrolled_print;
|
||||
g_assert_true (fp_device_verify_sync (device, enrolled_print, NULL,
|
||||
test_driver_match_cb, match_data,
|
||||
&match, &out_print, &error));
|
||||
|
||||
g_assert (fake_dev->last_called_function == dev_class->identify);
|
||||
g_assert_no_error (error);
|
||||
|
||||
g_assert_true (match_data->called);
|
||||
g_assert_no_error (match_data->error);
|
||||
g_assert_true (match_data->print == out_print);
|
||||
g_assert_null (match_data->match);
|
||||
|
||||
g_assert (out_print == enrolled_print);
|
||||
g_assert_false (match);
|
||||
}
|
||||
|
||||
static void
|
||||
test_driver_verify_via_identify_retry (void)
|
||||
{
|
||||
g_autoptr(GError) error = NULL;
|
||||
g_autoptr(FpAutoResetClass) dev_class = auto_reset_device_class ();
|
||||
g_autoptr(FpAutoCloseDevice) device = NULL;
|
||||
g_autoptr(FpPrint) enrolled_print = NULL;
|
||||
g_autoptr(FpPrint) out_print = NULL;
|
||||
g_autoptr(MatchCbData) match_data = g_new0 (MatchCbData, 1);
|
||||
FpiDeviceFake *fake_dev;
|
||||
gboolean match;
|
||||
|
||||
dev_class->verify = NULL;
|
||||
|
||||
device = auto_close_fake_device_new ();
|
||||
fake_dev = FPI_DEVICE_FAKE (device);
|
||||
enrolled_print = make_fake_print_reffed (device, NULL);
|
||||
|
||||
fake_dev->ret_error = fpi_device_retry_new (FP_DEVICE_RETRY_GENERAL);
|
||||
g_assert_false (fp_device_verify_sync (device, enrolled_print, NULL,
|
||||
test_driver_match_cb, match_data,
|
||||
&match, &out_print, &error));
|
||||
|
||||
g_assert_true (match_data->called);
|
||||
g_assert_null (match_data->match);
|
||||
g_assert_error (match_data->error, FP_DEVICE_RETRY, FP_DEVICE_RETRY_GENERAL);
|
||||
|
||||
g_assert (fake_dev->last_called_function == dev_class->identify);
|
||||
g_assert_error (error, FP_DEVICE_RETRY, FP_DEVICE_RETRY_GENERAL);
|
||||
g_assert (error == g_steal_pointer (&fake_dev->ret_error));
|
||||
g_assert_false (match);
|
||||
}
|
||||
|
||||
static void
|
||||
test_driver_verify_via_identify_error (void)
|
||||
{
|
||||
g_autoptr(GError) error = NULL;
|
||||
g_autoptr(FpAutoResetClass) dev_class = auto_reset_device_class ();
|
||||
g_autoptr(FpAutoCloseDevice) device = NULL;
|
||||
g_autoptr(FpPrint) enrolled_print = NULL;
|
||||
g_autoptr(FpPrint) out_print = NULL;
|
||||
g_autoptr(MatchCbData) match_data = g_new0 (MatchCbData, 1);
|
||||
FpiDeviceFake *fake_dev;
|
||||
gboolean match;
|
||||
|
||||
dev_class->verify = NULL;
|
||||
|
||||
device = auto_close_fake_device_new ();
|
||||
fake_dev = FPI_DEVICE_FAKE (device);
|
||||
enrolled_print = make_fake_print_reffed (device, NULL);
|
||||
|
||||
fake_dev->ret_error = fpi_device_error_new (FP_DEVICE_ERROR_GENERAL);
|
||||
g_assert_false (fp_device_verify_sync (device, enrolled_print, NULL,
|
||||
test_driver_match_cb, match_data,
|
||||
&match, &out_print, &error));
|
||||
|
||||
g_assert_false (match_data->called);
|
||||
g_assert_null (match_data->match);
|
||||
g_assert_no_error (match_data->error);
|
||||
|
||||
g_assert (fake_dev->last_called_function == dev_class->identify);
|
||||
g_assert_error (error, FP_DEVICE_ERROR, FP_DEVICE_ERROR_GENERAL);
|
||||
g_assert (error == g_steal_pointer (&fake_dev->ret_error));
|
||||
g_assert_false (match);
|
||||
}
|
||||
|
||||
static void
|
||||
test_driver_verify_via_identify_not_supported (void)
|
||||
{
|
||||
g_autoptr(GError) error = NULL;
|
||||
g_autoptr(FpPrint) enrolled_print = NULL;
|
||||
g_autoptr(FpPrint) out_print = NULL;
|
||||
g_autoptr(MatchCbData) match_data = g_new0 (MatchCbData, 1);
|
||||
g_autoptr(FpAutoResetClass) dev_class = auto_reset_device_class ();
|
||||
g_autoptr(FpAutoCloseDevice) device = NULL;
|
||||
FpiDeviceFake *fake_dev;
|
||||
gboolean match;
|
||||
|
||||
dev_class->verify = NULL;
|
||||
dev_class->features &= ~FP_DEVICE_FEATURE_VERIFY;
|
||||
|
||||
device = auto_close_fake_device_new ();
|
||||
fake_dev = FPI_DEVICE_FAKE (device);
|
||||
fake_dev->last_called_function = NULL;
|
||||
|
||||
enrolled_print = make_fake_print_reffed (device, g_variant_new_uint64 (3));
|
||||
g_assert_false (fp_device_verify_sync (device, enrolled_print, NULL,
|
||||
test_driver_match_cb, match_data,
|
||||
&match, &out_print, &error));
|
||||
|
||||
g_assert_null (fake_dev->last_called_function);
|
||||
g_assert_error (error, FP_DEVICE_ERROR, FP_DEVICE_ERROR_NOT_SUPPORTED);
|
||||
|
||||
g_assert_false (match_data->called);
|
||||
g_assert_no_error (match_data->error);
|
||||
|
||||
g_assert_null (out_print);
|
||||
g_assert_false (match);
|
||||
}
|
||||
|
||||
static void fake_device_identify_complete_error (FpDevice *device);
|
||||
|
||||
static void
|
||||
test_driver_verify_via_identify_report_no_callback (void)
|
||||
{
|
||||
g_autoptr(FpAutoResetClass) dev_class = auto_reset_device_class ();
|
||||
g_autoptr(MatchCbData) match_data = g_new0 (MatchCbData, 1);
|
||||
g_autoptr(FpAutoCloseDevice) device = NULL;
|
||||
g_autoptr(FpPrint) enrolled_print = NULL;
|
||||
g_autoptr(FpPrint) print = NULL;
|
||||
g_autoptr(GError) error = NULL;
|
||||
FpiDeviceFake *fake_dev;
|
||||
gboolean match;
|
||||
|
||||
dev_class->verify = NULL;
|
||||
|
||||
dev_class->identify = fake_device_identify_complete_error;
|
||||
device = g_object_new (FPI_TYPE_DEVICE_FAKE, NULL);
|
||||
fake_dev = FPI_DEVICE_FAKE (device);
|
||||
enrolled_print = make_fake_print_reffed (device, NULL);
|
||||
|
||||
g_assert_true (fp_device_open_sync (device, NULL, NULL));
|
||||
|
||||
g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_WARNING,
|
||||
"*Driver reported a verify error that was not in the retry domain*");
|
||||
|
||||
fake_dev->ret_error = fpi_device_error_new (FP_DEVICE_ERROR_NOT_SUPPORTED);
|
||||
g_assert_false (fp_device_verify_sync (device, enrolled_print, NULL,
|
||||
test_driver_match_cb, match_data,
|
||||
&match, &print, &error));
|
||||
|
||||
g_test_assert_expected_messages ();
|
||||
|
||||
g_assert_false (match_data->called);
|
||||
g_assert_null (match_data->match);
|
||||
g_assert_no_error (match_data->error);
|
||||
|
||||
g_assert (fake_dev->last_called_function == dev_class->identify);
|
||||
g_assert_error (error, FP_DEVICE_ERROR, FP_DEVICE_ERROR_NOT_SUPPORTED);
|
||||
g_assert (error == g_steal_pointer (&fake_dev->ret_error));
|
||||
g_assert_false (match);
|
||||
}
|
||||
|
||||
static void fake_device_identify_immediate_complete (FpDevice *device);
|
||||
|
||||
static void
|
||||
test_driver_verify_via_identify_not_reported (void)
|
||||
{
|
||||
g_autoptr(FpAutoResetClass) dev_class = auto_reset_device_class ();
|
||||
g_autoptr(FpAutoCloseDevice) device = NULL;
|
||||
g_autoptr(FpPrint) enrolled_print = NULL;
|
||||
g_autoptr(GError) error = NULL;
|
||||
|
||||
dev_class->verify = NULL;
|
||||
dev_class->identify = fake_device_identify_immediate_complete;
|
||||
device = g_object_new (FPI_TYPE_DEVICE_FAKE, NULL);
|
||||
enrolled_print = make_fake_print_reffed (device, NULL);
|
||||
|
||||
g_assert_true (fp_device_open_sync (device, NULL, NULL));
|
||||
|
||||
g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_WARNING,
|
||||
"*reported successful identify complete*not report*result*");
|
||||
|
||||
g_assert_false (fp_device_verify_sync (device, enrolled_print, NULL,
|
||||
NULL, NULL,
|
||||
NULL, NULL, &error));
|
||||
|
||||
g_assert_error (error, FP_DEVICE_ERROR, FP_DEVICE_ERROR_GENERAL);
|
||||
|
||||
g_test_assert_expected_messages ();
|
||||
}
|
||||
|
||||
static void
|
||||
test_driver_verify_via_identify_complete_retry (void)
|
||||
{
|
||||
g_autoptr(FpAutoResetClass) dev_class = auto_reset_device_class ();
|
||||
g_autoptr(MatchCbData) match_data = g_new0 (MatchCbData, 1);
|
||||
g_autoptr(FpAutoCloseDevice) device = NULL;
|
||||
g_autoptr(FpPrint) enrolled_print = NULL;
|
||||
g_autoptr(FpPrint) print = NULL;
|
||||
g_autoptr(GError) error = NULL;
|
||||
FpiDeviceFake *fake_dev;
|
||||
gboolean match;
|
||||
|
||||
dev_class->verify = NULL;
|
||||
dev_class->identify = fake_device_identify_complete_error;
|
||||
device = g_object_new (FPI_TYPE_DEVICE_FAKE, NULL);
|
||||
fake_dev = FPI_DEVICE_FAKE (device);
|
||||
enrolled_print = make_fake_print_reffed (device, NULL);
|
||||
|
||||
g_assert_true (fp_device_open_sync (device, NULL, NULL));
|
||||
|
||||
test_driver_match_data_clear (match_data);
|
||||
fake_dev->ret_error = fpi_device_retry_new (FP_DEVICE_RETRY_TOO_SHORT);
|
||||
g_assert_false (fp_device_verify_sync (device, enrolled_print, NULL, test_driver_match_cb,
|
||||
match_data, &match, &print, &error));
|
||||
|
||||
g_assert_true (error == g_steal_pointer (&fake_dev->ret_error));
|
||||
g_assert_error (error, FP_DEVICE_RETRY, FP_DEVICE_RETRY_TOO_SHORT);
|
||||
g_assert_false (match);
|
||||
g_assert_true (match_data->called);
|
||||
g_assert_error (match_data->error, FP_DEVICE_RETRY, FP_DEVICE_RETRY_TOO_SHORT);
|
||||
g_assert_null (print);
|
||||
g_clear_error (&error);
|
||||
|
||||
g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_WARNING,
|
||||
"*Driver reported a retry error to fpi_device_identify_complete"
|
||||
"*reporting general identification failure*");
|
||||
|
||||
test_driver_match_data_clear (match_data);
|
||||
fake_dev->ret_error = fpi_device_retry_new (FP_DEVICE_RETRY_TOO_SHORT);
|
||||
fake_dev->user_data = g_error_copy (fake_dev->ret_error);
|
||||
g_assert_false (fp_device_verify_sync (device, enrolled_print, NULL, test_driver_match_cb,
|
||||
match_data, &match, &print, &error));
|
||||
|
||||
g_test_assert_expected_messages ();
|
||||
g_assert_true (error != g_steal_pointer (&fake_dev->ret_error));
|
||||
g_steal_pointer (&fake_dev->user_data);
|
||||
g_assert_error (error, FP_DEVICE_ERROR, FP_DEVICE_ERROR_GENERAL);
|
||||
g_assert_true (match_data->called);
|
||||
g_assert_error (match_data->error, FP_DEVICE_RETRY, FP_DEVICE_RETRY_TOO_SHORT);
|
||||
g_assert_false (match);
|
||||
g_assert_null (print);
|
||||
g_clear_error (&error);
|
||||
|
||||
g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_WARNING,
|
||||
"*Driver reported a retry error to fpi_device_identify_complete"
|
||||
"*reporting general identification failure*");
|
||||
|
||||
test_driver_match_data_clear (match_data);
|
||||
fake_dev->ret_error = fpi_device_retry_new (FP_DEVICE_RETRY_TOO_SHORT);
|
||||
fake_dev->user_data = g_error_copy (fake_dev->ret_error);
|
||||
|
||||
g_assert_false (fp_device_verify_sync (device, enrolled_print, NULL, test_driver_match_cb,
|
||||
match_data, &match, &print, &error));
|
||||
g_test_assert_expected_messages ();
|
||||
|
||||
g_assert_true (error != g_steal_pointer (&fake_dev->ret_error));
|
||||
g_steal_pointer (&fake_dev->user_data);
|
||||
g_assert_error (error, FP_DEVICE_ERROR, FP_DEVICE_ERROR_GENERAL);
|
||||
g_assert_true (match_data->called);
|
||||
g_assert_error (match_data->error, FP_DEVICE_RETRY, FP_DEVICE_RETRY_TOO_SHORT);
|
||||
g_assert_false (match);
|
||||
g_assert_null (print);
|
||||
g_clear_error (&error);
|
||||
|
||||
g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_WARNING,
|
||||
"*Driver reported a match to a print that was not in the gallery*");
|
||||
|
||||
test_driver_match_data_clear (match_data);
|
||||
fake_dev->ret_error = fpi_device_retry_new (FP_DEVICE_RETRY_GENERAL);
|
||||
fake_dev->user_data = fpi_device_error_new (FP_DEVICE_ERROR_PROTO);
|
||||
fake_dev->ret_match = make_fake_print (device, NULL);
|
||||
g_object_add_weak_pointer (G_OBJECT (fake_dev->ret_match),
|
||||
(gpointer) (&fake_dev->ret_match));
|
||||
|
||||
g_assert_false (fp_device_verify_sync (device, enrolled_print, NULL, test_driver_match_cb,
|
||||
match_data, &match, &print, &error));
|
||||
g_test_assert_expected_messages ();
|
||||
|
||||
g_assert_true (error != g_steal_pointer (&fake_dev->ret_error));
|
||||
g_steal_pointer (&fake_dev->user_data);
|
||||
g_object_unref (fake_dev->ret_match);
|
||||
g_assert_null (fake_dev->ret_match);
|
||||
g_assert_error (error, FP_DEVICE_ERROR, FP_DEVICE_ERROR_PROTO);
|
||||
g_assert_true (match_data->called);
|
||||
g_assert_error (match_data->error, FP_DEVICE_RETRY, FP_DEVICE_RETRY_GENERAL);
|
||||
g_assert_false (match);
|
||||
g_assert_null (print);
|
||||
g_clear_error (&error);
|
||||
|
||||
g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_WARNING,
|
||||
"*Driver reported a print together with an error*");
|
||||
|
||||
test_driver_match_data_clear (match_data);
|
||||
fake_dev->ret_error = fpi_device_retry_new (FP_DEVICE_RETRY_TOO_SHORT);
|
||||
fake_dev->ret_print = make_fake_print (device, NULL);
|
||||
g_object_add_weak_pointer (G_OBJECT (fake_dev->ret_print),
|
||||
(gpointer) (&fake_dev->ret_print));
|
||||
|
||||
g_assert_false (fp_device_verify_sync (device, enrolled_print, NULL, test_driver_match_cb,
|
||||
match_data, &match, &print, &error));
|
||||
g_test_assert_expected_messages ();
|
||||
|
||||
g_assert_error (error, FP_DEVICE_RETRY, FP_DEVICE_RETRY_TOO_SHORT);
|
||||
g_assert_true (error == g_steal_pointer (&fake_dev->ret_error));
|
||||
g_assert_true (match_data->called);
|
||||
g_assert_error (match_data->error, FP_DEVICE_RETRY, FP_DEVICE_RETRY_TOO_SHORT);
|
||||
g_assert_null (fake_dev->ret_print);
|
||||
g_assert_false (match);
|
||||
g_assert_null (print);
|
||||
g_clear_error (&error);
|
||||
}
|
||||
|
||||
static void
|
||||
fake_device_stub_identify (FpDevice *device)
|
||||
{
|
||||
@@ -1789,7 +2222,7 @@ test_driver_identify (void)
|
||||
FpiDeviceFake *fake_dev = FPI_DEVICE_FAKE (device);
|
||||
FpPrint *expected_matched;
|
||||
|
||||
expected_matched = g_ptr_array_index (prints, g_random_int_range (0, 499));
|
||||
expected_matched = g_ptr_array_index (prints, g_random_int_range (0, prints->len));
|
||||
fp_print_set_description (expected_matched, "fake-verified");
|
||||
|
||||
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
|
||||
@@ -1799,7 +2232,9 @@ test_driver_identify (void)
|
||||
|
||||
match_data->gallery = prints;
|
||||
|
||||
fake_dev->ret_print = make_fake_print (device, NULL);
|
||||
fake_dev->ret_print = make_fake_print (device,
|
||||
g_variant_new_uint64 (
|
||||
g_random_int_range (0, prints->len)));
|
||||
g_assert_true (fp_device_identify_sync (device, prints, NULL,
|
||||
test_driver_match_cb, match_data,
|
||||
&matched_print, &print, &error));
|
||||
@@ -1816,6 +2251,72 @@ test_driver_identify (void)
|
||||
g_assert (expected_matched == matched_print);
|
||||
}
|
||||
|
||||
static void
|
||||
test_driver_identify_empty_gallery (void)
|
||||
{
|
||||
g_autoptr(GError) error = NULL;
|
||||
g_autoptr(FpPrint) print = NULL;
|
||||
g_autoptr(FpPrint) matched_print = NULL;
|
||||
g_autoptr(FpAutoCloseDevice) device = auto_close_fake_device_new ();
|
||||
g_autoptr(GPtrArray) prints = make_fake_prints_gallery (device, 0);
|
||||
g_autoptr(MatchCbData) match_data = g_new0 (MatchCbData, 1);
|
||||
FpDeviceClass *dev_class = FP_DEVICE_GET_CLASS (device);
|
||||
FpiDeviceFake *fake_dev = FPI_DEVICE_FAKE (device);
|
||||
|
||||
g_assert_true (fp_device_has_feature (device, FP_DEVICE_FEATURE_IDENTIFY));
|
||||
|
||||
match_data->gallery = prints;
|
||||
|
||||
g_assert_true (fp_device_identify_sync (device, prints, NULL,
|
||||
test_driver_match_cb, match_data,
|
||||
&matched_print, &print, &error));
|
||||
|
||||
g_assert_true (match_data->called);
|
||||
g_assert_null (match_data->match);
|
||||
g_assert_true (match_data->match == matched_print);
|
||||
g_assert_true (match_data->print == print);
|
||||
|
||||
g_assert_true (fake_dev->last_called_function == dev_class->identify);
|
||||
g_assert_no_error (error);
|
||||
|
||||
g_assert_null (print);
|
||||
g_assert_null (matched_print);
|
||||
}
|
||||
|
||||
static void
|
||||
test_driver_identify_empty_gallery_with_scanned_print (void)
|
||||
{
|
||||
g_autoptr(GError) error = NULL;
|
||||
g_autoptr(FpPrint) print = NULL;
|
||||
g_autoptr(FpPrint) matched_print = NULL;
|
||||
g_autoptr(FpAutoCloseDevice) device = auto_close_fake_device_new ();
|
||||
g_autoptr(GPtrArray) prints = make_fake_prints_gallery (device, 0);
|
||||
g_autoptr(MatchCbData) match_data = g_new0 (MatchCbData, 1);
|
||||
FpDeviceClass *dev_class = FP_DEVICE_GET_CLASS (device);
|
||||
FpiDeviceFake *fake_dev = FPI_DEVICE_FAKE (device);
|
||||
|
||||
g_assert_true (fp_device_has_feature (device, FP_DEVICE_FEATURE_IDENTIFY));
|
||||
|
||||
match_data->gallery = prints;
|
||||
fake_dev->ret_print = make_fake_print (device, NULL);
|
||||
match_data->print = fake_dev->ret_print;
|
||||
|
||||
g_assert_true (fp_device_identify_sync (device, prints, NULL,
|
||||
test_driver_match_cb, match_data,
|
||||
&matched_print, &print, &error));
|
||||
|
||||
g_assert_true (match_data->called);
|
||||
g_assert_null (match_data->match);
|
||||
g_assert_true (match_data->match == matched_print);
|
||||
g_assert_true (match_data->print == print);
|
||||
|
||||
g_assert_true (fake_dev->last_called_function == dev_class->identify);
|
||||
g_assert_no_error (error);
|
||||
|
||||
g_assert_true (print == fake_dev->ret_print);
|
||||
g_assert_null (matched_print);
|
||||
}
|
||||
|
||||
static void
|
||||
test_driver_identify_fail (void)
|
||||
{
|
||||
@@ -1864,7 +2365,7 @@ test_driver_identify_retry (void)
|
||||
FpiDeviceFake *fake_dev = FPI_DEVICE_FAKE (device);
|
||||
FpPrint *expected_matched;
|
||||
|
||||
expected_matched = g_ptr_array_index (prints, g_random_int_range (0, 499));
|
||||
expected_matched = g_ptr_array_index (prints, g_random_int_range (0, prints->len));
|
||||
fp_print_set_description (expected_matched, "fake-verified");
|
||||
|
||||
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
|
||||
@@ -1901,7 +2402,7 @@ test_driver_identify_error (void)
|
||||
FpiDeviceFake *fake_dev = FPI_DEVICE_FAKE (device);
|
||||
FpPrint *expected_matched;
|
||||
|
||||
expected_matched = g_ptr_array_index (prints, g_random_int_range (0, 499));
|
||||
expected_matched = g_ptr_array_index (prints, g_random_int_range (0, prints->len));
|
||||
fp_print_set_description (expected_matched, "fake-verified");
|
||||
|
||||
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
|
||||
@@ -2118,12 +2619,14 @@ test_driver_identify_suspend_continues (void)
|
||||
dev_class->identify = fake_device_stub_identify;
|
||||
|
||||
prints = make_fake_prints_gallery (device, 500);
|
||||
expected_matched = g_ptr_array_index (prints, g_random_int_range (0, 499));
|
||||
expected_matched = g_ptr_array_index (prints, g_random_int_range (0, prints->len));
|
||||
fp_print_set_description (expected_matched, "fake-verified");
|
||||
|
||||
match_data->gallery = prints;
|
||||
|
||||
fake_dev->ret_print = make_fake_print (device, NULL);
|
||||
fake_dev->ret_print = make_fake_print (device,
|
||||
g_variant_new_uint64 (
|
||||
g_random_int_range (0, prints->len)));
|
||||
|
||||
g_assert_true (fp_device_open_sync (device, NULL, NULL));
|
||||
|
||||
@@ -2184,14 +2687,16 @@ test_driver_identify_suspend_succeeds (void)
|
||||
dev_class->identify = fake_device_stub_identify;
|
||||
|
||||
prints = make_fake_prints_gallery (device, 500);
|
||||
expected_matched = g_ptr_array_index (prints, g_random_int_range (0, 499));
|
||||
expected_matched = g_ptr_array_index (prints, g_random_int_range (0, prints->len));
|
||||
fp_print_set_description (expected_matched, "fake-verified");
|
||||
|
||||
match_data->gallery = prints;
|
||||
|
||||
g_assert_true (fp_device_open_sync (device, NULL, NULL));
|
||||
|
||||
fake_dev->ret_print = make_fake_print (device, NULL);
|
||||
fake_dev->ret_print = make_fake_print (device,
|
||||
g_variant_new_uint64 (
|
||||
g_random_int_range (0, prints->len)));
|
||||
fp_device_identify (device, prints, NULL,
|
||||
test_driver_match_cb, match_data, NULL,
|
||||
(GAsyncReadyCallback) test_driver_identify_cb, identify_data);
|
||||
@@ -2246,7 +2751,7 @@ test_driver_identify_suspend_busy_error (void)
|
||||
dev_class->identify = fake_device_stub_identify;
|
||||
|
||||
prints = make_fake_prints_gallery (device, 500);
|
||||
expected_matched = g_ptr_array_index (prints, g_random_int_range (0, 499));
|
||||
expected_matched = g_ptr_array_index (prints, g_random_int_range (0, prints->len));
|
||||
fp_print_set_description (expected_matched, "fake-verified");
|
||||
|
||||
match_data->gallery = prints;
|
||||
@@ -2370,14 +2875,14 @@ test_driver_identify_warmup_cooldown (void)
|
||||
g_main_context_iteration (NULL, TRUE);
|
||||
g_assert_cmpint (fp_device_get_temperature (device), ==, FP_TEMPERATURE_WARM);
|
||||
g_assert_false (g_cancellable_is_cancelled (fpi_device_get_cancellable (device)));
|
||||
g_assert_cmpint (g_get_monotonic_time () - start_time, <, 0 + 250000);
|
||||
g_assert_cmpint (g_get_monotonic_time () - start_time, <, 0 + 500000);
|
||||
|
||||
/* we reach hot 2 seconds later */
|
||||
while (fp_device_get_temperature (device) == FP_TEMPERATURE_WARM)
|
||||
g_main_context_iteration (NULL, TRUE);
|
||||
g_assert_cmpint (fp_device_get_temperature (device), ==, FP_TEMPERATURE_HOT);
|
||||
g_assert_true (g_cancellable_is_cancelled (fpi_device_get_cancellable (device)));
|
||||
g_assert_cmpint (g_get_monotonic_time () - start_time, <, 2000000 + 250000);
|
||||
g_assert_cmpint (g_get_monotonic_time () - start_time, <, 2000000 + 500000);
|
||||
|
||||
/* cancel vfunc will be called now */
|
||||
g_assert (fake_dev->last_called_function == NULL);
|
||||
@@ -2404,12 +2909,58 @@ test_driver_identify_warmup_cooldown (void)
|
||||
while (fp_device_get_temperature (device) == FP_TEMPERATURE_HOT)
|
||||
g_main_context_iteration (NULL, TRUE);
|
||||
g_assert_cmpint (fp_device_get_temperature (device), ==, FP_TEMPERATURE_WARM);
|
||||
g_assert_cmpint (g_get_monotonic_time () - start_time, <, 2000000 + 250000);
|
||||
g_assert_cmpint (g_get_monotonic_time () - start_time, <, 2000000 + 500000);
|
||||
|
||||
while (fp_device_get_temperature (device) == FP_TEMPERATURE_WARM)
|
||||
g_main_context_iteration (NULL, TRUE);
|
||||
g_assert_cmpint (fp_device_get_temperature (device), ==, FP_TEMPERATURE_COLD);
|
||||
g_assert_cmpint (g_get_monotonic_time () - start_time, <, 5000000 + 500000);
|
||||
g_assert_cmpint (g_get_monotonic_time () - start_time, <, 5000000 + 1000000);
|
||||
}
|
||||
|
||||
static void
|
||||
test_driver_identify_mismatched_scanned_print (void)
|
||||
{
|
||||
g_autoptr(GError) error = NULL;
|
||||
g_autoptr(FpPrint) print = NULL;
|
||||
g_autoptr(FpPrint) matched_print = NULL;
|
||||
g_autoptr(FpAutoCloseDevice) device = auto_close_fake_device_new ();
|
||||
g_autoptr(GPtrArray) prints = make_fake_prints_gallery (device, 500);
|
||||
g_autoptr(MatchCbData) match_data = g_new0 (MatchCbData, 1);
|
||||
FpDeviceClass *dev_class = FP_DEVICE_GET_CLASS (device);
|
||||
FpiDeviceFake *fake_dev = FPI_DEVICE_FAKE (device);
|
||||
FpPrint *expected_matched;
|
||||
|
||||
expected_matched = g_ptr_array_index (prints, 0);
|
||||
fp_print_set_description (expected_matched, "fake-verified");
|
||||
|
||||
match_data->gallery = prints;
|
||||
|
||||
fake_dev->ret_match = expected_matched;
|
||||
fake_dev->ret_print = make_fake_print (device, g_variant_new_string ("no-match"));
|
||||
g_object_add_weak_pointer (G_OBJECT (fake_dev->ret_print),
|
||||
(gpointer) (&fake_dev->ret_print));
|
||||
|
||||
g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_WARNING,
|
||||
"*Driver reported a match providing a scanned print "
|
||||
"that is not matching any in the gallery.*");
|
||||
|
||||
g_assert_true (fp_device_identify_sync (device, prints, NULL,
|
||||
test_driver_match_cb, match_data,
|
||||
&matched_print, &print, &error));
|
||||
|
||||
g_test_assert_expected_messages ();
|
||||
|
||||
g_assert_true (match_data->called);
|
||||
g_assert_nonnull (match_data->match);
|
||||
g_assert_true (match_data->match == matched_print);
|
||||
g_assert_null (match_data->print);
|
||||
|
||||
g_assert (fake_dev->last_called_function == dev_class->identify);
|
||||
g_assert_no_error (error);
|
||||
|
||||
g_assert_null (print);
|
||||
g_assert (expected_matched == matched_print);
|
||||
g_assert_null (fake_dev->ret_print);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -3387,6 +3938,130 @@ test_driver_retry_error_types (void)
|
||||
g_test_assert_expected_messages ();
|
||||
}
|
||||
|
||||
static void
|
||||
test_fp_print_equal_same (void)
|
||||
{
|
||||
g_autoptr(FpDevice) device = g_object_new (FPI_TYPE_DEVICE_FAKE, NULL);
|
||||
g_autoptr(FpPrint) print_a = NULL;
|
||||
g_autoptr(FpPrint) print_b = NULL;
|
||||
|
||||
print_a = make_fake_print (device, g_variant_new_string ("test"));
|
||||
print_b = make_fake_print (device, g_variant_new_string ("test"));
|
||||
|
||||
g_assert_true (fp_print_equal (print_a, print_a));
|
||||
g_assert_true (fp_print_equal (print_b, print_b));
|
||||
g_assert_true (fp_print_equal (print_a, print_b));
|
||||
}
|
||||
|
||||
static void
|
||||
test_fp_print_equal_different (void)
|
||||
{
|
||||
g_autoptr(FpDevice) device = g_object_new (FPI_TYPE_DEVICE_FAKE, NULL);
|
||||
g_autoptr(FpPrint) print_a = NULL;
|
||||
g_autoptr(FpPrint) print_b = NULL;
|
||||
|
||||
print_a = make_fake_print (device, g_variant_new_string ("test"));
|
||||
print_b = make_fake_print (device, g_variant_new_string ("other"));
|
||||
|
||||
g_assert_false (fp_print_equal (print_a, print_b));
|
||||
}
|
||||
|
||||
static void
|
||||
test_fp_print_equal_nbis_empty (void)
|
||||
{
|
||||
g_autoptr(FpDevice) device = g_object_new (FPI_TYPE_DEVICE_FAKE, NULL);
|
||||
g_autoptr(FpPrint) print_a = NULL;
|
||||
g_autoptr(FpPrint) print_b = NULL;
|
||||
|
||||
print_a = make_fake_nbis_print (device);
|
||||
print_b = make_fake_nbis_print (device);
|
||||
|
||||
g_assert_true (fp_print_equal (print_a, print_b));
|
||||
}
|
||||
|
||||
static void
|
||||
test_fp_print_equal_nbis_one_empty (void)
|
||||
{
|
||||
g_autoptr(FpDevice) device = g_object_new (FPI_TYPE_DEVICE_FAKE, NULL);
|
||||
g_autoptr(FpPrint) print_a = NULL;
|
||||
g_autoptr(FpPrint) print_b = NULL;
|
||||
gint xvals[] = { 10, 20 };
|
||||
gint yvals[] = { 30, 40 };
|
||||
gint tvals[] = { 50, 60 };
|
||||
|
||||
print_a = make_fake_nbis_print_filled (device, xvals, yvals, tvals, 2, 1);
|
||||
print_b = make_fake_nbis_print (device);
|
||||
|
||||
g_assert_false (fp_print_equal (print_a, print_b));
|
||||
g_assert_false (fp_print_equal (print_b, print_a));
|
||||
}
|
||||
|
||||
static void
|
||||
test_fp_print_equal_nbis_equal (void)
|
||||
{
|
||||
g_autoptr(FpDevice) device = g_object_new (FPI_TYPE_DEVICE_FAKE, NULL);
|
||||
g_autoptr(FpPrint) print_a = NULL;
|
||||
g_autoptr(FpPrint) print_b = NULL;
|
||||
gint xvals[] = { 10, 20 };
|
||||
gint yvals[] = { 30, 40 };
|
||||
gint tvals[] = { 50, 60 };
|
||||
|
||||
print_a = make_fake_nbis_print_filled (device, xvals, yvals, tvals, 2, 1);
|
||||
print_b = make_fake_nbis_print_filled (device, xvals, yvals, tvals, 2, 1);
|
||||
|
||||
g_assert_true (fp_print_equal (print_a, print_b));
|
||||
}
|
||||
|
||||
static void
|
||||
test_fp_print_equal_nbis_different (void)
|
||||
{
|
||||
g_autoptr(FpDevice) device = g_object_new (FPI_TYPE_DEVICE_FAKE, NULL);
|
||||
g_autoptr(FpPrint) print_a = NULL;
|
||||
g_autoptr(FpPrint) print_b = NULL;
|
||||
gint xvals_a[] = { 10, 20 };
|
||||
gint yvals_a[] = { 30, 40 };
|
||||
gint tvals_a[] = { 50, 60 };
|
||||
gint xvals_b[] = { 99, 88 };
|
||||
gint yvals_b[] = { 77, 66 };
|
||||
gint tvals_b[] = { 55, 44 };
|
||||
|
||||
print_a = make_fake_nbis_print_filled (device, xvals_a, yvals_a, tvals_a, 2, 1);
|
||||
print_b = make_fake_nbis_print_filled (device, xvals_b, yvals_b, tvals_b, 2, 1);
|
||||
|
||||
g_assert_false (fp_print_equal (print_a, print_b));
|
||||
}
|
||||
|
||||
static void
|
||||
test_fp_print_equal_nbis_different_lengths (void)
|
||||
{
|
||||
g_autoptr(FpDevice) device = g_object_new (FPI_TYPE_DEVICE_FAKE, NULL);
|
||||
g_autoptr(FpPrint) print_a = NULL;
|
||||
g_autoptr(FpPrint) print_b = NULL;
|
||||
gint xvals[] = { 10, 20 };
|
||||
gint yvals[] = { 30, 40 };
|
||||
gint tvals[] = { 50, 60 };
|
||||
|
||||
print_a = make_fake_nbis_print_filled (device, xvals, yvals, tvals, 2, 5);
|
||||
print_b = make_fake_nbis_print_filled (device, xvals, yvals, tvals, 2, 1);
|
||||
|
||||
g_assert_false (fp_print_equal (print_a, print_b));
|
||||
g_assert_false (fp_print_equal (print_b, print_a));
|
||||
}
|
||||
|
||||
static void
|
||||
test_fp_print_equal_different_types (void)
|
||||
{
|
||||
g_autoptr(FpDevice) device = g_object_new (FPI_TYPE_DEVICE_FAKE, NULL);
|
||||
g_autoptr(FpPrint) print_a = NULL;
|
||||
g_autoptr(FpPrint) print_b = NULL;
|
||||
|
||||
print_a = make_fake_print (device, g_variant_new_string ("test"));
|
||||
print_b = make_fake_nbis_print (device);
|
||||
|
||||
g_assert_false (fp_print_equal (print_a, print_b));
|
||||
g_assert_false (fp_print_equal (print_b, print_a));
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
@@ -3453,6 +4128,16 @@ main (int argc, char *argv[])
|
||||
g_test_add_func ("/driver/verify/report_no_cb", test_driver_verify_report_no_callback);
|
||||
g_test_add_func ("/driver/verify/not_reported", test_driver_verify_not_reported);
|
||||
g_test_add_func ("/driver/verify/complete_retry", test_driver_verify_complete_retry);
|
||||
g_test_add_func ("/driver/verify/mismatched_scanned_print",
|
||||
test_driver_verify_mismatched_scanned_print);
|
||||
g_test_add_func ("/driver/verify/via-identify", test_driver_verify_via_identify);
|
||||
g_test_add_func ("/driver/verify/via-identify/fail", test_driver_verify_via_identify_fail);
|
||||
g_test_add_func ("/driver/verify/via-identify/retry", test_driver_verify_via_identify_retry);
|
||||
g_test_add_func ("/driver/verify/via-identify/error", test_driver_verify_via_identify_error);
|
||||
g_test_add_func ("/driver/verify/via-identify/not_supported", test_driver_verify_via_identify_not_supported);
|
||||
g_test_add_func ("/driver/verify/via-identify/report_no_cb", test_driver_verify_via_identify_report_no_callback);
|
||||
g_test_add_func ("/driver/verify/via-identify/not_reported", test_driver_verify_via_identify_not_reported);
|
||||
g_test_add_func ("/driver/verify/via-identify/complete_retry", test_driver_verify_via_identify_complete_retry);
|
||||
g_test_add_func ("/driver/identify", test_driver_identify);
|
||||
g_test_add_func ("/driver/identify/fail", test_driver_identify_fail);
|
||||
g_test_add_func ("/driver/identify/retry", test_driver_identify_retry);
|
||||
@@ -3460,6 +4145,11 @@ main (int argc, char *argv[])
|
||||
g_test_add_func ("/driver/identify/not_reported", test_driver_identify_not_reported);
|
||||
g_test_add_func ("/driver/identify/complete_retry", test_driver_identify_complete_retry);
|
||||
g_test_add_func ("/driver/identify/report_no_cb", test_driver_identify_report_no_callback);
|
||||
g_test_add_func ("/driver/identify/mismatched_scanned_print",
|
||||
test_driver_identify_mismatched_scanned_print);
|
||||
g_test_add_func ("/driver/identify/empty-gallery", test_driver_identify_empty_gallery);
|
||||
g_test_add_func ("/driver/identify/empty-gallery-with-scanned-print",
|
||||
test_driver_identify_empty_gallery_with_scanned_print);
|
||||
|
||||
g_test_add_func ("/driver/identify/suspend_continues", test_driver_identify_suspend_continues);
|
||||
g_test_add_func ("/driver/identify/suspend_succeeds", test_driver_identify_suspend_succeeds);
|
||||
@@ -3502,5 +4192,16 @@ main (int argc, char *argv[])
|
||||
g_test_add_func ("/driver/error_types", test_driver_error_types);
|
||||
g_test_add_func ("/driver/retry_error_types", test_driver_retry_error_types);
|
||||
|
||||
g_test_add_func ("/print/equal/same", test_fp_print_equal_same);
|
||||
g_test_add_func ("/print/equal/different", test_fp_print_equal_different);
|
||||
g_test_add_func ("/print/equal/nbis_empty", test_fp_print_equal_nbis_empty);
|
||||
g_test_add_func ("/print/equal/nbis_one_empty", test_fp_print_equal_nbis_one_empty);
|
||||
g_test_add_func ("/print/equal/nbis_equal", test_fp_print_equal_nbis_equal);
|
||||
g_test_add_func ("/print/equal/nbis_different", test_fp_print_equal_nbis_different);
|
||||
g_test_add_func ("/print/equal/nbis_different_lengths",
|
||||
test_fp_print_equal_nbis_different_lengths);
|
||||
g_test_add_func ("/print/equal/different_types",
|
||||
test_fp_print_equal_different_types);
|
||||
|
||||
return g_test_run ();
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ fi
|
||||
|
||||
if ! diff -u "$MESON_SOURCE_ROOT/data/autosuspend.hwdb" "$generated_rules"; then
|
||||
echo "E: Autosuspend file needs to be re-generated!"
|
||||
echo " ninja -C $MESON_BUILD_ROOT sync-udev-hwdb"
|
||||
echo " meson compile -C $MESON_BUILD_ROOT sync-udev-hwdb"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
+19
-8
@@ -1,15 +1,20 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import sys
|
||||
import argparse
|
||||
import os
|
||||
import os.path
|
||||
import glob
|
||||
import shutil
|
||||
import sys
|
||||
import tempfile
|
||||
import subprocess
|
||||
|
||||
if len(sys.argv) != 2:
|
||||
print("You need to specify exactly one argument, the directory with test data")
|
||||
parser = argparse.ArgumentParser(
|
||||
description='Run libfprint tests using umockdev data.')
|
||||
parser.add_argument('test_dir', help='Directory containing test data')
|
||||
parser.add_argument('--test', choices=('capture', 'custom'),
|
||||
help='Run only the selected test (default: run both)')
|
||||
options = parser.parse_args()
|
||||
|
||||
# Check that umockdev is available
|
||||
try:
|
||||
@@ -27,12 +32,18 @@ except FileNotFoundError:
|
||||
sys.exit(77)
|
||||
|
||||
edir = os.path.dirname(sys.argv[0])
|
||||
ddir = sys.argv[1]
|
||||
ddir = options.test_dir
|
||||
assert os.path.isdir(ddir)
|
||||
|
||||
capture_available = bool(glob.glob(os.path.join(ddir, 'capture.*')))
|
||||
custom_available = bool(glob.glob(os.path.join(ddir, 'custom.*')))
|
||||
if options.test == 'capture' and not capture_available:
|
||||
parser.error(f'capture test data does not exist in {ddir}')
|
||||
if options.test == 'custom' and not custom_available:
|
||||
parser.error(f'custom test data does not exist in {ddir}')
|
||||
|
||||
tmpdir = tempfile.mkdtemp(prefix='libfprint-umockdev-test-')
|
||||
|
||||
assert os.path.isdir(ddir)
|
||||
|
||||
def cmp_pngs(png_a, png_b):
|
||||
print("Comparing PNGs %s and %s" % (png_a, png_b))
|
||||
import cairo
|
||||
@@ -111,10 +122,10 @@ def custom():
|
||||
['%s' % os.path.join(ddir, "custom.py")])
|
||||
|
||||
try:
|
||||
if glob.glob(os.path.join(ddir, "capture.*")):
|
||||
if options.test in (None, 'capture') and capture_available:
|
||||
capture()
|
||||
|
||||
if glob.glob(os.path.join(ddir, "custom.*")):
|
||||
if options.test in (None, 'custom') and custom_available:
|
||||
custom()
|
||||
|
||||
except Exception as e:
|
||||
|
||||
+34
-10
@@ -46,6 +46,27 @@ def load_image(img):
|
||||
|
||||
return img
|
||||
|
||||
|
||||
def transform_image(surface, dx=0, dy=0, dw=0, dh=0, angle=0):
|
||||
assert dw >= 0 and dh >= 0, "dw/dh must be non-negative"
|
||||
|
||||
w = surface.get_width()
|
||||
h = surface.get_height()
|
||||
result = cairo.ImageSurface(cairo.Format.A8, w, h)
|
||||
cr = cairo.Context(result)
|
||||
|
||||
# Transform around center: translate to center, scale, rotate, then
|
||||
# offset the source so its center aligns with the origin.
|
||||
cr.translate(w / 2 + dx, h / 2 + dy)
|
||||
cr.rotate(angle)
|
||||
cr.scale((w - dw) / w, (h - dh) / h)
|
||||
cr.translate(-w / 2, -h / 2)
|
||||
|
||||
cr.set_source_surface(surface)
|
||||
cr.paint()
|
||||
return result
|
||||
|
||||
|
||||
if 'FP_PRINTS_PATH' in os.environ:
|
||||
prints_path = os.environ['FP_PRINTS_PATH']
|
||||
else:
|
||||
@@ -126,9 +147,12 @@ class VirtualImage(unittest.TestCase):
|
||||
while iterate and ctx.pending():
|
||||
ctx.iteration(False)
|
||||
|
||||
def send_image(self, image, iterate=True):
|
||||
def send_image(self, image, iterate=True, dx=0, dy=0, dw=0, dh=0, angle=0):
|
||||
img = self.prints[image]
|
||||
|
||||
if dx or dy or dw or dh or angle:
|
||||
img = transform_image(img, dx, dy, dw, dh, angle)
|
||||
|
||||
mem = img.get_data()
|
||||
mem = mem.tobytes()
|
||||
assert len(mem) == img.get_width() * img.get_height()
|
||||
@@ -223,7 +247,7 @@ class VirtualImage(unittest.TestCase):
|
||||
|
||||
# Note: Assumes 5 enroll steps for this device!
|
||||
self.wait_for_finger_status(FPrint.FingerStatusFlags.NEEDED)
|
||||
self.send_image(image)
|
||||
self.send_image(image, dx=0, dy=0, dw=0, dh=0, angle=0)
|
||||
while self._step < 1:
|
||||
ctx.iteration(True)
|
||||
|
||||
@@ -233,8 +257,8 @@ class VirtualImage(unittest.TestCase):
|
||||
self.assertEqual(self.dev.get_finger_status(), FPrint.FingerStatusFlags.NEEDED)
|
||||
self.send_finger_report(True)
|
||||
self.assertEqual(self.dev.get_finger_status(),
|
||||
FPrint.FingerStatusFlags.NEEDED | FPrint.FingerStatusFlags.PRESENT)
|
||||
self.send_image(image)
|
||||
FPrint.FingerStatusFlags.NEEDED | FPrint.FingerStatusFlags.PRESENT)
|
||||
self.send_image(image, dx=1, dy=0, dw=0, dh=0, angle=0.017)
|
||||
while self._step < 2:
|
||||
ctx.iteration(True)
|
||||
self.send_finger_report(False)
|
||||
@@ -242,19 +266,19 @@ class VirtualImage(unittest.TestCase):
|
||||
self.assertEqual(self.dev.get_finger_status(), FPrint.FingerStatusFlags.NEEDED)
|
||||
|
||||
self.send_finger_automatic(True)
|
||||
self.send_image(image)
|
||||
self.send_image(image, dx=-1, dy=1, dw=2, dh=0, angle=-0.035)
|
||||
while self._step < 3:
|
||||
ctx.iteration(True)
|
||||
|
||||
self.assertEqual(self.dev.get_finger_status(), FPrint.FingerStatusFlags.NEEDED)
|
||||
|
||||
self.send_image(image)
|
||||
self.send_image(image, dx=0, dy=-1, dw=0, dh=2, angle=0.035)
|
||||
while self._step < 4:
|
||||
ctx.iteration(True)
|
||||
|
||||
self.assertEqual(self.dev.get_finger_status(), FPrint.FingerStatusFlags.NEEDED)
|
||||
|
||||
self.send_image(image)
|
||||
self.send_image(image, dx=2, dy=0, dw=1, dh=1, angle=-0.017)
|
||||
while self._enrolled is None:
|
||||
ctx.iteration(True)
|
||||
|
||||
@@ -282,7 +306,7 @@ class VirtualImage(unittest.TestCase):
|
||||
self._verify_fp = None
|
||||
self.dev.verify(fp_whorl, callback=verify_cb)
|
||||
self.wait_for_finger_status(FPrint.FingerStatusFlags.NEEDED)
|
||||
self.send_image('whorl')
|
||||
self.send_image('whorl', dx=-2, dy=-1, dw=0, dh=0, angle=0.052)
|
||||
while self._verify_match is None:
|
||||
ctx.iteration(True)
|
||||
assert(self._verify_match)
|
||||
@@ -306,7 +330,7 @@ class VirtualImage(unittest.TestCase):
|
||||
self._verify_fp = None
|
||||
self.dev.verify(fp_whorl_tended_arch, callback=verify_cb)
|
||||
self.wait_for_finger_status(FPrint.FingerStatusFlags.NEEDED)
|
||||
self.send_image('whorl')
|
||||
self.send_image('whorl', dx=3, dy=0, dw=4, dh=2, angle=-0.052)
|
||||
while self._verify_match is None:
|
||||
ctx.iteration(True)
|
||||
assert(self._verify_match)
|
||||
@@ -422,7 +446,7 @@ class VirtualImage(unittest.TestCase):
|
||||
self._verify_fp = None
|
||||
self.dev.verify(fp_whorl_new, callback=verify_cb)
|
||||
self.wait_for_finger_status(FPrint.FingerStatusFlags.NEEDED)
|
||||
self.send_image('whorl')
|
||||
self.send_image('whorl', dx=-1, dy=2, dw=0, dh=3, angle=0.017)
|
||||
while self._verify_match is None:
|
||||
ctx.iteration(True)
|
||||
assert(self._verify_match)
|
||||
|
||||
Reference in New Issue
Block a user