Compare commits

..
Author SHA1 Message Date
Benjamin Berg f2dfa2ae0a sdcp-device: Use a key DB for testing 2022-02-14 17:20:00 +01:00
Benjamin Berg 67723675d2 sdcp-device: Use predictable keys and random numbers for testing
If FP_DEVICE_EMULATION is set, then switch to using predictable EC
ephemeral key and random numbers. This should allow recording and
replaying real device interactions using umockdev.
2022-02-14 17:20:00 +01:00
Benjamin Berg 39e060a71b port to low level EC key functions
This will allow creating a fixed key for testing
2022-02-14 17:20:00 +01:00
Benjamin Berg 2a99fb0aca saner public key param 2022-02-14 17:20:00 +01:00
Benjamin Berg 197d60cdb1 fixups: use static OID data 2022-02-14 17:20:00 +01:00
Benjamin Berg 2677ccc0c2 ci: Enable SDCP helper for tests 2022-02-14 17:20:00 +01:00
Benjamin Berg f921aaf0a8 tests: Add SDCP virtual device test 2022-02-14 17:20:00 +01:00
Benjamin Berg 8ecd78e982 virtual-sdcp: Add a virtual SDCP device
This device is designed to talk to an external executable. This
executable can be provided/created using the test implementation from
Microsoft.
2022-02-14 17:20:00 +01:00
Benjamin Berg 991e6e2343 sdcp: Add SDCP base class
This adds a base class for SDCP devices. Not all functionality has been
fully tested, in particular the code to verify the model certificate is
most likely broken or incomplete. One problem there is that there is no
code to find the root CA to trust.

See: #257
2022-02-14 17:20:00 +01:00
Benjamin Berg 24b02b943f device: Add new FP_DEVICE_ERROR_UNTRUSTED error code
Throw a specific error when we are unable to verify the integrety of the
device.
2022-02-14 17:19:59 +01:00
Benjamin Berg 8240bf54e6 print: Add an SDCP print type
For now it is identical to a RAW print. However, this is likely to
change in the future.
2022-02-14 17:19:05 +01:00
Benjamin Berg 6539cde70d ci: Include SDCP test binary in image 2022-02-14 17:19:05 +01:00
187 changed files with 4865 additions and 27253 deletions
+2 -2
View File
@@ -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(['meson', 'compile', '-v', '-C', build_dir])
subprocess.check_call(['meson', 'install', '-v', '-C', build_dir],
subprocess.check_call(['ninja', '-v', '-C', build_dir])
subprocess.check_call(['ninja', '-v', '-C', build_dir, 'install'],
env={'DESTDIR': dest_dir})
return dest_dir
+62 -271
View File
@@ -1,76 +1,50 @@
include:
- local: '.gitlab-ci/libfprint-image-variables.yaml'
- local: '.gitlab-ci/libfprint-templates.yaml'
- project: 'freedesktop/ci-templates'
ref: master
file: '/templates/fedora.yml'
- remote: 'https://gitlab.gnome.org/GNOME/citemplates/-/raw/71e636e012ae0ab04c5e0fe40ca73ada91ae6bde/flatpak/flatpak_ci_initiative.yml'
default:
interruptible: true
# Auto-retry jobs in case of infra failures
retry:
max: 1
when:
- 'runner_system_failure'
- 'stuck_or_timeout_failure'
- 'scheduler_failure'
- 'api_failure'
- remote: 'https://gitlab.gnome.org/GNOME/citemplates/-/raw/master/flatpak/flatpak_ci_initiative.yml'
variables:
extends: .libfprint_common_variables
FDO_DISTRIBUTION_TAG: $LIBFPRINT_IMAGE_TAG
FDO_DISTRIBUTION_TAG: latest
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"
FEDORA_IMAGE: "$CI_REGISTRY/libfprint/$CI_PROJECT_NAME/fedora/$FDO_DISTRIBUTION_VERSION:$FDO_DISTRIBUTION_TAG"
BUNDLE: "org.freedesktop.libfprint.Demo.flatpak"
LAST_ABI_BREAK: "056ea541ddc97f5806cffbd99a12dc87e4da3546"
workflow:
rules:
- if: $CI_PIPELINE_SOURCE == 'merge_request_event'
- if: $CI_PIPELINE_SOURCE == 'push'
- if: $CI_PIPELINE_SOURCE == 'schedule'
- if: $CI_PROJECT_NAMESPACE == 'libfprint' && $LIBFPRINT_CI_ACTION != ''
stages:
- image-build
- check-source
- build
- test
- flatpak
- deploy
image: $FEDORA_IMAGE
.build_one_driver_template: &build_one_driver
script:
# Build with a driver that doesn't need imaging, or openssl
- meson setup _build --werror -Ddrivers=$driver
- meson compile -C _build
# Build with a driver that doesn't need imaging, or nss
- meson --werror -Ddrivers=$driver . _build
- ninja -C _build
- rm -rf _build/
.build_template: &build
script:
# And build with everything
- meson setup _build --werror -Ddrivers=all
- meson compile -C _build
- meson install -C _build
- meson --werror -Ddrivers=all . _build
- ninja -C _build
- ninja -C _build install
.build_template: &check_abi
script:
- ./.ci/check-abi ${LAST_ABI_BREAK} $(git rev-parse HEAD)
.standard_job:
rules:
- when: on_success
- if: $CI_PIPELINE_SOURCE == "schedule"
when: never
build:
stage: build
extends:
- .standard_job
except:
variables:
- $CI_PIPELINE_SOURCE == "schedule"
variables:
driver: virtual_image
<<: *build_one_driver
@@ -85,20 +59,16 @@ build:
test:
stage: test
extends:
- .standard_job
except:
variables:
- $CI_PIPELINE_SOURCE == "schedule"
script:
- meson setup _build --werror -Ddrivers=all -Db_coverage=true
- meson --werror -Ddrivers=all -Db_coverage=true -Dsdcp_virt_binary=/usr/local/bin/sdcp_virt_device . _build
- ninja -C _build
- meson test -C _build --print-errorlogs --no-stdsplit --timeout-multiplier 3
# We can't use `meson compile` https://github.com/mesonbuild/meson/issues/7895
- ninja -C _build coverage
- cat _build/meson-logs/coverage.txt || true
- cat _build/meson-logs/coverage.txt
artifacts:
reports:
junit: "_build/meson-logs/testlog.junit.xml"
coverage_report:
coverage_format: cobertura
path: _build/meson-logs/coverage.xml
expose_as: 'Coverage Report'
when: always
paths:
@@ -109,15 +79,14 @@ test:
test_valgrind:
stage: test
extends:
- .standard_job
except:
variables:
- $CI_PIPELINE_SOURCE == "schedule"
script:
- meson setup _build -Ddrivers=all
- meson compile -C _build
- meson -Ddrivers=all -Dsdcp_virt_binary=/usr/local/bin/sdcp_virt_device . _build
- ninja -C _build
- meson test -C _build --print-errorlogs --no-stdsplit --setup=valgrind
artifacts:
reports:
junit: "_build/meson-logs/testlog-valgrind.junit.xml"
expose_as: 'Valgrind test logs'
when: always
paths:
@@ -125,271 +94,93 @@ test_valgrind:
- _build/meson-logs/testlog-valgrind.txt
expire_in: 1 week
test_asan:
stage: test
extends:
- .standard_job
script:
- meson setup _build -Ddrivers=all -Db_sanitize=address,undefined
- meson test -C _build --print-errorlogs --no-stdsplit
artifacts:
reports:
junit: "_build/meson-logs/testlog.junit.xml"
expose_as: 'Sanitizers test logs'
when: always
paths:
- _build/meson-logs
- _build/meson-logs/testlog.txt
expire_in: 1 week
test_installed:
stage: test
extends:
- .standard_job
script:
- meson setup _build --prefix=/usr -Ddrivers=all
- meson install -C _build
- mv _build _build_dir
- rm -rf tests
- gnome-desktop-testing-runner --list libfprint-2
- gnome-desktop-testing-runner libfprint-2
--report-directory=_installed-tests-report/failed/
--log-directory=_installed-tests-report/logs/
--parallel=0
artifacts:
expose_as: 'GNOME Tests Runner logs'
when: always
paths:
- _build_dir/meson-logs
- _installed-tests-report
expire_in: 1 week
test_scan_build:
stage: test
extends:
- .standard_job
except:
variables:
- $CI_PIPELINE_SOURCE == "schedule"
allow_failure: true
script:
- meson setup _build -Ddrivers=all
- meson -Ddrivers=all . _build
# Wrapper to add --status-bugs and disable malloc checker
- SCANBUILD=$CI_PROJECT_DIR/.gitlab-ci/scan-build
ninja -C _build scan-build
- SCANBUILD=$CI_PROJECT_DIR/.gitlab-ci/scan-build ninja -C _build scan-build
artifacts:
when: on_failure
paths:
- _build/meson-logs
expire_in: 1 week
test_indent:
stage: check-source
extends:
- .standard_job
except:
variables:
- $CI_PIPELINE_SOURCE == "schedule"
script:
- scripts/uncrustify.sh
- git diff
- git diff-index --name-only --exit-code HEAD
rules:
- changes:
compare_to: 'refs/heads/master'
paths:
- '**/*.c'
- '**/*.h'
- "! git status -s | grep -q ."
test_unsupported_list:
stage: check-source
extends:
- .standard_job
except:
variables:
- $CI_PIPELINE_SOURCE == "schedule"
allow_failure: true
variables:
FPRINT_HWDB_LIST: libfprint/fprint-list-udev-hwdb.c
script:
- scripts/sync-unsupported-devices.py $FPRINT_HWDB_LIST
- git diff --color=always --exit-code $FPRINT_HWDB_LIST
- tests/hwdb-check-unsupported.py
flatpak:
stage: flatpak
extends: .flatpak@x86_64
extends: .flatpak
image: registry.gitlab.gnome.org/gnome/gnome-runtime-images/gnome:3.36
variables:
MANIFEST_PATH: "demo/org.freedesktop.libfprint.Demo.json"
FLATPAK_MODULE: "libfprint"
APP_ID: "org.freedesktop.libfprint.Demo"
BUNDLE: "org.freedesktop.libfprint.Demo.flatpak"
RUNTIME_REPO: "https://nightly.gnome.org/gnome-nightly.flatpakrepo"
# Build with any builder
tags: []
rules:
- if: '$CI_PROJECT_PATH != "libfprint/libfprint"'
when: manual
allow_failure: true
- if: $CI_PIPELINE_SOURCE == "schedule"
when: never
- if: '$CI_PIPELINE_SOURCE == "schedule"'
when: never
- if: '$CI_COMMIT_BRANCH == "master"'
allow_failure: true
when: always
- if: '$CI_COMMIT_TAG'
allow_failure: true
when: always
# For any other (commit), allow manual run.
# This excludes MRs which would create a duplicate pipeline
- if: '$CI_COMMIT_BRANCH'
when: manual
allow_failure: true
- if: '$CI_MERGE_REQUEST_ID'
when: manual
allow_failure: true
# CONTAINERS creation stage
.container_fedora_build_base:
container_fedora_build:
extends: .fdo.container-build@fedora
stage: image-build
only:
variables:
- $CI_PIPELINE_SOURCE == "schedule" && $CRON_TASK == "BUILD_CI_IMAGES"
variables:
GIT_STRATEGY: none # no need to pull the whole tree for rebuilding the image
FDO_FORCE_REBUILD: 1
# a list of packages to install
FDO_DISTRIBUTION_PACKAGES:
$LIBFPRINT_DEPENDENCIES
vala
libpcap-devel
libudev-devel
mbedtls-devel
FDO_DISTRIBUTION_EXEC: |
$LIBFPRINT_EXEC
rules:
- when: never
.container_fedora_build_forced:
variables:
FDO_FORCE_REBUILD: 1
container_fedora_build_schedule:
extends:
- .container_fedora_build_base
- .container_fedora_build_forced
rules:
- if: $CI_PIPELINE_SOURCE == "schedule" && $CRON_TASK == "BUILD_CI_IMAGES"
when: always
container_fedora_build_manual:
extends:
- .container_fedora_build_base
- .container_fedora_build_forced
rules:
- if: $LIBFPRINT_CI_ACTION == "build-image"
when: always
.container_fedora_build_on_deps_changed_rules:
rules:
- if: $CI_PROJECT_NAMESPACE == "libfprint" && $CI_PIPELINE_SOURCE != "schedule"
changes:
compare_to: 'refs/heads/master'
paths:
- '.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
needs:
- job: test
artifacts: true
- job: build
artifacts: true
script:
- mkdir public
- mv _build/meson-logs/coveragereport public/coverage || true
- mv _build/doc/html public/doc
artifacts:
paths:
- public
rules:
- if: $CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH && $CI_PIPELINE_SOURCE == "push"
- if: $CI_COMMIT_TAG
git clone https://github.com/martinpitt/umockdev.git && \
cd umockdev && \
meson _build --prefix=/usr && \
ninja -C _build && ninja -C _build install
cd /tmp
mkdir -p /usr/local/bin
git clone https://github.com/benzea/SecureDeviceConnectionProtocol.git
# Don't bother with cmake
gcc -l mbedcrypto -I SecureDeviceConnectionProtocol/src/include \
SecureDeviceConnectionProtocol/src/test/virt_device.c \
SecureDeviceConnectionProtocol/src/client/client.c \
SecureDeviceConnectionProtocol/src/test/helpers.c \
SecureDeviceConnectionProtocol/src/test/testkeys.c \
-o /usr/local/bin/sdcp_virt_device
rm -rf SecureDeviceConnectionProtocol
@@ -1,2 +0,0 @@
variables:
LIBFPRINT_IMAGE_TAG: v8
+1 -23
View File
@@ -1,11 +1,6 @@
# Bump image version on .gitlab-ci/libfprint-image-variables.yaml to trigger
# a rebuild on changes to this file
.libfprint_common_variables:
LIBFPRINT_DEPENDENCIES:
appstream
doxygen
dnf-plugins-core
flatpak-builder
gcc
gcc-c++
@@ -14,21 +9,16 @@
glib2-devel
glibc-devel
gobject-introspection-devel
gnome-desktop-testing
gtk-doc
gtk3-devel
libabigail
libasan
libgusb-devel
libgudev-devel
libubsan
libX11-devel
libXv-devel
meson
openssl-devel
nss-devel
pixman-devel
podman
qemu-user-static
python3-cairo
python3-gobject
systemd
@@ -37,15 +27,3 @@
valgrind
clang-analyzer
diffutils
LIBFPRINT_EXEC: |
dnf -y install dnf-utils
debuginfo-install -y \
glib2 \
glibc \
libgusb \
libusb \
openssl \
pixman \
python3-gobject \
python3-gobject-base
@@ -1,27 +0,0 @@
#!/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
+2 -5
View File
@@ -1,7 +1,4 @@
#!/bin/sh -x
#!/bin/sh
# This wrapper just disables the malloc checker
exec /usr/bin/scan-build --status-bugs -disable-checker unix.Malloc \
--exclude "$PWD/_build/meson-private" \
--exclude "$PWD/meson-private" \
"$@"
exec /usr/bin/scan-build --status-bugs -disable-checker unix.Malloc "$@"
+2 -124
View File
@@ -1,128 +1,6 @@
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:
* synaptics: Add USB reset in probe to recover stall condition
* synaptics: New PIDs 0x0169, 0x019F, 0x00E9, 0x01A0, 0x0109, 0x010A
* goodixmoc: New PID 0x66A9
* goodixmoc: Fix crash in exit callback handler
* fpcmoc: New PID 0xA306
* fpcmoc: Fix interrupt cancellable leak
* elanmoc: New PIDs 0x0CA7, 0x0CA8, 0x0CB0
* egismoc: New PIDs 0x0584, 0x0588
* focaltech_moc: New PIDs 0xA27A, 0x1579
* realtek: New PID 0xFA03
* fp-device: Clarify getter for open property
* libfprint: Use fatal-warnings on g-i-scanner
2025-02-20: v1.94.9 release
Highlights:
* uru4000: Use OpenSSL to perform AES-ECB encryption, as per this libfprint
does not support on NSS, but on openssl (>= 3.0).
* goodixmoc: New PIDs 0x60C2, 0x689A
* synaptics: New PIDs 0x016C, 0x0174, 0x0107, 0x0108, 0x00C2, 0x00F0
* fpcmoc: New PID 0xC844
* focaltech_moc: New PIDs 0xA99A, 0xA57A, 0xA78A
* elanmoc: New PIDs 0x0C98, 0x0C9D, 0x0CA3
* elanspi: New PIDs 0x3128, 0x2766
* fp-device: Add FP_DEVICE_RETRY_TOO_FAST retry error
* data: AppStream meta info listing supported USB devices.
* fixed various memory issues in multiple devices
2024-09-03: v1.94.8 release
Highlights:
* build: Support building in non-linux unix environments (tested in FreeBSD)
* egismoc: New PIDs 0x0583, 0x0586, 0x0587.
* elanmoc: New PID 0x0C9F.
* fpcmoc: New PIDs 0x9524, 0x9544.
* goodixmoc: New PIDs 0x609A, 0x650A, 0x650C, 0x6512.
* realtek: New PID 0x5816.
* synaptics: New PIDs 0x00C4, 0x019D, 0x00C6.
* fpcmoc: fix incorrect immobile handling during enrollment.
* fpcmoc: fixed jumping to wrong state at end of custom enroll.
* egismoc: various code cleanups.
2024-02-20: v1.94.7 release
Highlights:
* synaptics: fix enroll identify problem after user reset database.
* synaptics: New PIDs 0x0173, 0x0106, 0x0124.
* goodixmoc: New PID 0x6582.
* build: Do not require bash to build, only posix sh.
* fp-image: Simplify minutiae detection tasks.
* GLib 2.68 is now required to build libfprint.
New drivers:
* realtek (PID 0x5813).
* focaltech_moc (PIDs 0x9E48, 0xD979, 0xA959).
* egismoc (PIDs 0x0582, 0x05a1).
2023-08-17: v1.94.6 release
Highlights:
* goodixmoc: New PIDs 0x60A4, 0x60BC, 0x6092, 0x633C and 0x6304.
* goodixmoc: Fix missing "enroll create" state.
* elanmoc: New PID 0x0C99.
* upektc: Improve compatibility with sensors 147e:2016.
* aes4000: Actually support 08FF:5501 devices.
* virtual-device-listener: Fix failing tests with GLib 2.76
* tests: Add installed tests
Bugs fixed:
* #526 libfprint: fpcmoc: use after free if enrollment or identification is
cancelled (Vasily Khoruzhick)
2022-10-13: v1.94.5 release
Highlights:
* New driver: fpcmoc, supporting various FPC MOC Fingerprint Sensors
* goodixmoc: New PIDs 0x6014, 0x6094, 0x631C, 0x634C, 0x6384, 0x659A.
* goodixmoc: Support resetting device on firmware failure due to corrupted DB.
* elanmoc: New PIDs 0x0c88, 0x0c8c, 0x0c8d.
* synaptics: New PID 0x0104.
* upektc: New PID 0x2017.
* Fixed various memory leaks
* More tests
2022-05-24: v1.94.4 release
Highlights:
* synaptics: New PIDs 0x0168, 0x015f
* elan: New PID 0x0c4b
* elanspi: New PID 0x241f
* synaptics: Minor fix to interrupt transfer resubmission
* Avoid sysfs writes if value is already expected
* Improvements to the testing setup
* Fixes to the internal critical section API
2021-11-02: v1.94.3 release
Highlights:
@@ -441,7 +319,7 @@ tests of the drivers using umockdev.
- Mark fp_dscv_print functions as deprecated
* Udev rules:
- Add some unsupported devices to the allowlist
- Add some unsupported devices to the whitelist
2017-05-14: v0.7.0 release
* Drivers:
@@ -491,7 +369,7 @@ tests of the drivers using umockdev.
- Fix possible race condition, and cancellation in uru4000 driver
* Udev rules:
- Add Microsoft keyboard to the suspend denylist
- Add Microsoft keyboard to the suspend blacklist
* Plenty of build fixes
+38 -79
View File
@@ -1,95 +1,54 @@
# libfprint
<div align="center">
# LibFPrint
*LibFPrint is part of the **[FPrint][Website]** project.*
<br/>
[![Button Website]][Website]
[![Button Documentation]][Documentation]
[![Button Supported]][Supported]
[![Button Unsupported]][Unsupported]
[![Button Contribute]][Contribute]
[![Button Contributors]][Contributors]
</div>
libfprint is part of the fprint project:
https://fprint.freedesktop.org/
## History
**LibFPrint** was originally developed as part of an
academic project at the **[University Of Manchester]**.
libfprint was originally developed as part of an academic project at the
University of Manchester with the aim of hiding differences between different
consumer fingerprint scanners and providing a single uniform API to application
developers. The ultimate goal of the fprint project is to make fingerprint
scanners widely and easily usable under common Linux environments.
It aimed to hide the differences between consumer
fingerprint scanners and provide a single uniform
API to application developers.
## Goal
The ultimate goal of the **FPrint** project is to make
fingerprint scanners widely and easily usable under
common Linux environments.
The academic university project runs off a codebase maintained separately
from this one, although I try to keep them as similar as possible (I'm not
hiding anything in the academic branch, it's just the open source release
contains some commits excluded from the academic project).
## License
`Section 6` of the license states that for compiled works that use
this library, such works must include **LibFPrint** copyright notices
alongside the copyright notices for the other parts of the work.
THE UNIVERSITY OF MANCHESTER DOES NOT ENDORSE THIS THIS SOFTWARE RELEASE AND
IS IN NO WAY RESPONSIBLE FOR THE CODE CONTAINED WITHIN, OR ANY DAMAGES CAUSED
BY USING OR DISTRIBUTING THE SOFTWARE. Development does not happen on
university computers and the project is not hosted at the university either.
**LibFPrint** includes code from **NIST's** **[NBIS]** software distribution.
For more information on libfprint, supported devices, API documentation, etc.,
see the homepage:
https://fprint.freedesktop.org/
We include **Bozorth3** from the **[US Export Controlled]**
distribution, which we have determined to be fine
being shipped in an open source project.
libfprint is licensed under the GNU LGPL version 2.1. See the COPYING file
for the license text.
## Get in *touch*
Section 6 of the license states that for compiled works that use this
library, such works must include libfprint copyright notices alongside the
copyright notices for the other parts of the work. We have attempted to
make this process slightly easier for you by grouping these all in one place:
the AUTHORS file.
- [IRC] - `#fprint` @ `irc.oftc.net`
- [Matrix] - `#fprint:matrix.org` bridged to the IRC channel
- [MailingList] - low traffic, not much used these days
libfprint includes code from NIST's NBIS software distribution:
http://fingerprint.nist.gov/NBIS/index.html
We include bozorth3 from the US export controlled distribution. We have
determined that it is fine to ship bozorth3 in an open source project,
see https://fprint.freedesktop.org/us-export-control.html
<br/>
## Historical links
<div align="right">
Older versions of libfprint are available at:
https://sourceforge.net/projects/fprint/files/
[![Badge License]][License]
Historical mailing-list archives:
http://www.reactivated.net/fprint_list_archives/
</div>
<!----------------------------------------------------------------------------->
[Documentation]: https://fprint.freedesktop.org/libfprint-dev/
[Contributors]: https://gitlab.freedesktop.org/libfprint/libfprint/-/graphs/master
[Unsupported]: https://gitlab.freedesktop.org/libfprint/wiki/-/wikis/Unsupported-Devices
[Supported]: https://fprint.freedesktop.org/supported-devices.html
[Website]: https://fprint.freedesktop.org/
[MailingList]: https://lists.freedesktop.org/mailman/listinfo/fprint
[IRC]: ircs://irc.oftc.net:6697/#fprint
[Matrix]: https://matrix.to/#/#fprint:matrix.org
[Contribute]: ./HACKING.md
[License]: ./COPYING
[University Of Manchester]: https://www.manchester.ac.uk/
[US Export Controlled]: https://fprint.freedesktop.org/us-export-control.html
[NBIS]: http://fingerprint.nist.gov/NBIS/index.html
<!---------------------------------[ Badges ]---------------------------------->
[Badge License]: https://img.shields.io/badge/License-LGPL2.1-015d93.svg?style=for-the-badge&labelColor=blue
<!---------------------------------[ Buttons ]--------------------------------->
[Button Documentation]: https://img.shields.io/badge/Documentation-04ACE6?style=for-the-badge&logoColor=white&logo=BookStack
[Button Contributors]: https://img.shields.io/badge/Contributors-FF4F8B?style=for-the-badge&logoColor=white&logo=ActiGraph
[Button Unsupported]: https://img.shields.io/badge/Unsupported_Devices-EF2D5E?style=for-the-badge&logoColor=white&logo=AdBlock
[Button Contribute]: https://img.shields.io/badge/Contribute-66459B?style=for-the-badge&logoColor=white&logo=Git
[Button Supported]: https://img.shields.io/badge/Supported_Devices-428813?style=for-the-badge&logoColor=white&logo=AdGuard
[Button Website]: https://img.shields.io/badge/Homepage-3B80AE?style=for-the-badge&logoColor=white&logo=freedesktopDotOrg
Historical website:
http://web.archive.org/web/*/https://www.freedesktop.org/wiki/Software/fprint/
+8 -226
View File
@@ -67,7 +67,7 @@ usb:v08FFp5731*
ID_PERSIST=0
# Supported by libfprint driver aes4000
usb:v08FFp5501*
usb:v5501p08FF*
ID_AUTOSUSPEND=1
ID_PERSIST=0
@@ -77,23 +77,6 @@ usb:v1C7Ap0571*
ID_AUTOSUSPEND=1
ID_PERSIST=0
# Supported by libfprint driver egis_etu905
usb:v1C7Ap05AE*
usb:v1C7Ap9201*
ID_AUTOSUSPEND=1
ID_PERSIST=0
# Supported by libfprint driver egismoc
usb:v1C7Ap0582*
usb:v1C7Ap0583*
usb:v1C7Ap0584*
usb:v1C7Ap0586*
usb:v1C7Ap0587*
usb:v1C7Ap0588*
usb:v1C7Ap05A1*
ID_AUTOSUSPEND=1
ID_PERSIST=0
# Supported by libfprint driver elan
usb:v04F3p0903*
usb:v04F3p0907*
@@ -150,7 +133,6 @@ usb:v04F3p0C32*
usb:v04F3p0C33*
usb:v04F3p0C3D*
usb:v04F3p0C42*
usb:v04F3p0C4B*
usb:v04F3p0C4D*
usb:v04F3p0C4F*
usb:v04F3p0C63*
@@ -162,20 +144,6 @@ usb:v04F3p0C58*
# Supported by libfprint driver elanmoc
usb:v04F3p0C7D*
usb:v04F3p0C7E*
usb:v04F3p0C82*
usb:v04F3p0C88*
usb:v04F3p0C8C*
usb:v04F3p0C8D*
usb:v04F3p0C98*
usb:v04F3p0C99*
usb:v04F3p0C9C*
usb:v04F3p0C9D*
usb:v04F3p0C9F*
usb:v04F3p0CA3*
usb:v04F3p0CA7*
usb:v04F3p0CA8*
usb:v04F3p0CB0*
usb:v04F3p0CB2*
ID_AUTOSUSPEND=1
ID_PERSIST=0
@@ -184,136 +152,41 @@ usb:v1C7Ap0603*
ID_AUTOSUSPEND=1
ID_PERSIST=0
# Supported by libfprint driver focaltech_moc
usb:v2808p9E48*
usb:v2808pD979*
usb:v2808pA27A*
usb:v2808pA959*
usb:v2808pA99A*
usb:v2808pA57A*
usb:v2808pA78A*
usb:v2808pA97A*
usb:v2808p1579*
usb:v2808p077A*
usb:v2808p079A*
usb:v2808p5158*
usb:v2808p6553*
ID_AUTOSUSPEND=1
ID_PERSIST=0
# Supported by libfprint driver fpcmoc
usb:v10A5pFFE0*
usb:v10A5pA305*
usb:v10A5pA306*
usb:v10A5pDA04*
usb:v10A5pD805*
usb:v10A5pD205*
usb:v10A5p9524*
usb:v10A5p9544*
usb:v10A5pC844*
usb:v10A5p9B24*
ID_AUTOSUSPEND=1
ID_PERSIST=0
# Supported by libfprint driver goodixmoc
usb:v27C6p5840*
usb:v27C6p6014*
usb:v27C6p6090*
usb:v27C6p6092*
usb:v27C6p6094*
usb:v27C6p609A*
usb:v27C6p609C*
usb:v27C6p60A2*
usb:v27C6p60A4*
usb:v27C6p60BC*
usb:v27C6p60C2*
usb:v27C6p6304*
usb:v27C6p631C*
usb:v27C6p633C*
usb:v27C6p634C*
usb:v27C6p6382*
usb:v27C6p6384*
usb:v27C6p639C*
usb:v27C6p63AC*
usb:v27C6p63BC*
usb:v27C6p63CC*
usb:v27C6p6496*
usb:v27C6p650A*
usb:v27C6p650C*
usb:v27C6p6582*
usb:v27C6p6584*
usb:v27C6p658C*
usb:v27C6p6592*
usb:v27C6p6594*
usb:v27C6p659A*
usb:v27C6p659C*
usb:v27C6p6A94*
usb:v27C6p6512*
usb:v27C6p6890*
usb:v27C6p689A*
usb:v27C6p66A9*
usb:v27C6p6984*
ID_AUTOSUSPEND=1
ID_PERSIST=0
# Supported by libfprint driver mafpmoc
usb:v3274p8012*
ID_AUTOSUSPEND=1
ID_PERSIST=0
# Supported by libfprint driver nb1010
usb:v298Dp1010*
usb:v298Dp2020*
ID_AUTOSUSPEND=1
ID_PERSIST=0
# Supported by libfprint driver realtek
usb:v0BDAp5813*
usb:v0BDAp5816*
usb:v2541pFA03*
usb:v3274p9003*
ID_AUTOSUSPEND=1
ID_PERSIST=0
# Supported by libfprint driver secugen
usb:v1162p2200*
ID_AUTOSUSPEND=1
ID_PERSIST=0
# Supported by libfprint driver synaptics
usb:v06CBp00BD*
usb:v06CBp00C2*
usb:v06CBp00C4*
usb:v06CBp00C6*
usb:v06CBp00DF*
usb:v06CBp00E9*
usb:v06CBp00F0*
usb:v06CBp00F9*
usb:v06CBp00FC*
usb:v06CBp00C2*
usb:v06CBp0100*
usb:v06CBp00F0*
usb:v06CBp0103*
usb:v06CBp0104*
usb:v06CBp0106*
usb:v06CBp0107*
usb:v06CBp0108*
usb:v06CBp0109*
usb:v06CBp010A*
usb:v06CBp010D*
usb:v06CBp010E*
usb:v06CBp0123*
usb:v06CBp0124*
usb:v06CBp0126*
usb:v06CBp0129*
usb:v06CBp015F*
usb:v06CBp0168*
usb:v06CBp0169*
usb:v06CBp016C*
usb:v06CBp0173*
usb:v06CBp0174*
usb:v06CBp019D*
usb:v06CBp019F*
usb:v06CBp01A0*
usb:v06CBp01A4*
ID_AUTOSUSPEND=1
ID_PERSIST=0
@@ -326,7 +199,6 @@ usb:v147Ep1001*
# Supported by libfprint driver upektc
usb:v0483p2015*
usb:v0483p2017*
usb:v147Ep3001*
ID_AUTOSUSPEND=1
ID_PERSIST=0
@@ -382,80 +254,33 @@ usb:v138Ap0091*
ID_PERSIST=0
# Known unsupported devices
usb:v006Bp00DA*
usb:v0413p2766*
usb:v045Ep0815*
usb:v047Dp00F2*
usb:v047Dp8054*
usb:v047Dp8055*
usb:v04E8p730B*
usb:v04F2pB61E*
usb:v04F3p036B*
usb:v04F3p0C00*
usb:v04F3p0C4B*
usb:v04F3p0C4C*
usb:v04F3p0C57*
usb:v04F3p0C5A*
usb:v04F3p0C5E*
usb:v04F3p0C60*
usb:v04F3p0C6C*
usb:v04F3p0C70*
usb:v04F3p0C72*
usb:v04F3p0C77*
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:v04F3p3195*
usb:v04F3p31FC*
usb:v04F3p3201*
usb:v04F3p3212*
usb:v05BAp000E*
usb:v05C8p03C0*
usb:v06CBp0051*
usb:v06CBp0081*
usb:v06CBp0088*
usb:v06CBp008A*
usb:v06CBp009A*
usb:v06CBp009B*
usb:v06CBp00A1*
usb:v06CBp00A2*
usb:v06CBp00A8*
usb:v06CBp00B7*
usb:v06CBp00BB*
usb:v06CBp00BC*
usb:v06CBp00BE*
usb:v06CBp00C7*
usb:v06CBp00C9*
usb:v06CBp00C4*
usb:v06CBp00CB*
usb:v06CBp00C9*
usb:v06CBp00D8*
usb:v06CBp00DA*
usb:v06CBp00DC*
usb:v06CBp00E4*
usb:v06CBp00E7*
usb:v06CBp00E9*
usb:v06CBp00FD*
usb:v06CBp00FF*
usb:v06CBp0102*
usb:v06CBpCE67*
usb:v06CBpCEEF*
usb:v08FFp3400*
usb:v0A5Cp5801*
usb:v0A5Cp5802*
usb:v0A5Cp5805*
usb:v0A5Cp5834*
usb:v0A5Cp5840*
@@ -464,24 +289,10 @@ usb:v0A5Cp5842*
usb:v0A5Cp5843*
usb:v0A5Cp5844*
usb:v0A5Cp5845*
usb:v0A5Cp5860*
usb:v0A5Cp5863*
usb:v0A5Cp5864*
usb:v0A5Cp5865*
usb:v0A5Cp5866*
usb:v0A5Cp5867*
usb:v0BDAp0129*
usb:v0BDAp5812*
usb:v10A5p0007*
usb:v10A5p9200*
usb:v10A5p9201*
usb:v10A5p9800*
usb:v10A5pA120*
usb:v10A5pA900*
usb:v10A5pA921*
usb:v10A5pE340*
usb:v1188p9545*
usb:v138Ap0006*
usb:v138Ap0007*
usb:v138Ap003A*
usb:v138Ap003C*
@@ -492,7 +303,6 @@ usb:v138Ap0092*
usb:v138Ap0094*
usb:v138Ap0097*
usb:v138Ap009D*
usb:v138Ap00A6*
usb:v138Ap00AB*
usb:v147Ep1002*
usb:v1491p0088*
@@ -500,57 +310,29 @@ usb:v16D1p1027*
usb:v1C7Ap0300*
usb:v1C7Ap0575*
usb:v1C7Ap0576*
usb:v1C7Ap0577*
usb:v1C7Ap057E*
usb:v1C7Ap05A5*
usb:v1C7Ap05AA*
usb:v1C7Ap0801*
usb:v2541p0236*
usb:v2541p9711*
usb:v27C6p5042*
usb:v27C6p5110*
usb:v27C6p5117*
usb:v27C6p5120*
usb:v27C6p5125*
usb:v27C6p5201*
usb:v27C6p521D*
usb:v27C6p5301*
usb:v27C6p530C*
usb:v27C6p532D*
usb:v27C6p5335*
usb:v27C6p533C*
usb:v27C6p5381*
usb:v27C6p5385*
usb:v27C6p538C*
usb:v27C6p538D*
usb:v27C6p5395*
usb:v27C6p5503*
usb:v27C6p550A*
usb:v27C6p550C*
usb:v27C6p5584*
usb:v27C6p55A2*
usb:v27C6p55A4*
usb:v27C6p55B4*
usb:v27C6p5740*
usb:v27C6p581A*
usb:v27C6p589A*
usb:v27C6p5E0A*
usb:v27C6p5F10*
usb:v27C6p5F91*
usb:v2808p06FC*
usb:v2808p6652*
usb:v2808p9338*
usb:v2808p9348*
usb:v2808p93A9*
usb:v2808pA553*
usb:v2808pA573*
usb:v2808pA658*
usb:v2808pC652*
usb:v298Dp2020*
usb:v298Dp2033*
usb:v2DF0p0003*
usb:v3274p9008*
usb:v3274pB012*
usb:v33A7p2388*
usb:v3538p0930*
ID_AUTOSUSPEND=1
ID_PERSIST=0
+1 -1
View File
@@ -1,6 +1,6 @@
if udev_hwdb_dir != ''
# This file has to be updated using
# meson compile -C <builddir> sync-udev-hwdb
# ninja -C <builddir> libfprint/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
+5 -8
View File
@@ -101,14 +101,11 @@ plot_minutiae (unsigned char *rgbdata,
{
int i;
#define write_pixel(num) \
do \
{ \
rgbdata[((num) * 3)] = 0xff; \
rgbdata[((num) * 3) + 1] = 0; \
rgbdata[((num) * 3) + 2] = 0; \
} \
while(0)
#define write_pixel(num) do { \
rgbdata[((num) * 3)] = 0xff; \
rgbdata[((num) * 3) + 1] = 0; \
rgbdata[((num) * 3) + 2] = 0; \
} while(0)
for (i = 0; i < minutiae->len; i++)
{
+16 -15
View File
@@ -1,12 +1,12 @@
{
"app-id": "org.freedesktop.libfprint.Demo",
"runtime": "org.gnome.Platform",
"runtime-version": "master",
"runtime-version": "3.36",
"sdk": "org.gnome.Sdk",
"command": "gtk-libfprint-test",
"finish-args": [
/* X11 + XShm access */
"--share=ipc", "--socket=fallback-x11",
"--share=ipc", "--socket=x11",
/* Wayland access */
"--socket=wayland",
/* OpenGL access */
@@ -18,7 +18,7 @@
"modules": [
{
"name": "libusb",
"config-opts": [ "--disable-static" ],
"config-opts": [ "--disable-static", "--disable-udev" ],
"cleanup": [
"/lib/*.la",
"/lib/pkgconfig",
@@ -26,47 +26,48 @@
],
"sources": [
{
"type": "archive",
"url": "https://github.com/libusb/libusb/releases/download/v1.0.26/libusb-1.0.26.tar.bz2",
"sha256": "12ce7a61fc9854d1d2a1ffe095f7b5fac19ddba095c259e6067a46500381b5a5"
"type": "archive",
"url": "https://github.com/libusb/libusb/archive/v1.0.22.tar.gz",
"sha256": "3500f7b182750cd9ccf9be8b1df998f83df56a39ab264976bdb3307773e16f48"
}
],
"post-install": [
"install -Dm644 COPYING /app/share/licenses/libusb/COPYING"
"install -Dm644 COPYING /app/share/licenses/libgusb/COPYING"
]
},
{
"name": "libgusb",
"buildsystem": "meson",
"config-opts": [ "-Dtests=false", "-Dvapi=false", "-Ddocs=false" ],
"config-opts": [ "-Dtests=false", "-Dvapi=false", "-Ddocs=false", "-Dintrospection=false" ],
"sources": [
{
"type": "archive",
"url": "https://github.com/hughsie/libgusb/releases/download/0.4.6/libgusb-0.4.6.tar.xz",
"sha256": "1b0422bdcd72183272ac42eec9398c5a0bc48a02f618fa3242c468cbbd003049"
"url": "https://github.com/hughsie/libgusb/archive/0.3.0.tar.gz",
"sha256": "b36310f8405d5fd68f6caf4a829f7ab4c627b38fd3d02a139d411fce0f3a49f1"
}
]
},
{
"name": "gudev",
"buildsystem": "meson",
"config-opts": [ "-Dtests=disabled", "-Dintrospection=disabled", "-Dvapi=disabled" ],
"config-opts": [ "-Dtests=disabled", "-Dintrospection=disabled" ],
"sources": [
{
"type": "archive",
"url": "https://download.gnome.org/sources/libgudev/238/libgudev-238.tar.xz",
"sha256": "61266ab1afc9d73dbc60a8b2af73e99d2fdff47d99544d085760e4fa667b5dd1"
"url": "https://download.gnome.org/sources/libgudev/236/libgudev-236.tar.xz",
"sha256": "e50369d06d594bae615eb7aeb787de304ebaad07a26d1043cef8e9c7ab7c9524"
}
]
},
{
"name": "libfprint",
"buildsystem": "meson",
"config-opts": [ "-Dudev_hwdb=disabled", "-Dudev_rules=disabled", "-Dgtk-examples=true", "-Ddrivers=all" ],
"config-opts": [ "-Dudev_hwdb=disabled", "-Dudev_rules=disabled", "-Dx11-examples=false", "-Dgtk-examples=true", "-Ddrivers=all" ],
"sources": [
{
"type": "git",
"url": "https://gitlab.freedesktop.org/libfprint/libfprint.git"
"url": "https://gitlab.freedesktop.org/libfprint/libfprint.git",
"branch": "wip/benzea/v2"
}
]
}
+26 -133
View File
@@ -75,7 +75,6 @@ fp_device_clear_storage_sync
fp_device_suspend_sync
fp_device_resume_sync
FpDevice
FpTemperature
</SECTION>
<SECTION>
@@ -101,6 +100,12 @@ FP_TYPE_IMAGE_DEVICE
FpImageDevice
</SECTION>
<SECTION>
<FILE>fp-sdcp-device</FILE>
FP_TYPE_SDCP_DEVICE
FpSdcpDevice
</SECTION>
<SECTION>
<FILE>fp-print</FILE>
FP_TYPE_PRINT
@@ -135,134 +140,6 @@ fpi_line_asmbl_ctx
fpi_assemble_lines
</SECTION>
<SECTION>
<FILE>fpi-byte-reader</FILE>
<TITLE>FpiByteReader</TITLE>
FpiByteReader
fpi_byte_reader_new
fpi_byte_reader_new_bytes
fpi_byte_reader_free
fpi_byte_reader_init
fpi_byte_reader_init_bytes
fpi_byte_reader_peek_sub_reader
fpi_byte_reader_get_sub_reader
fpi_byte_reader_set_pos
fpi_byte_reader_get_pos
fpi_byte_reader_get_remaining
fpi_byte_reader_get_size
fpi_byte_reader_skip
fpi_byte_reader_get_bytes
fpi_byte_reader_peek_bytes
fpi_byte_reader_get_uint8
fpi_byte_reader_get_int8
fpi_byte_reader_peek_uint8
fpi_byte_reader_peek_int8
fpi_byte_reader_get_uint16_le
fpi_byte_reader_get_int16_le
fpi_byte_reader_peek_uint16_le
fpi_byte_reader_peek_int16_le
fpi_byte_reader_get_uint16_be
fpi_byte_reader_get_int16_be
fpi_byte_reader_peek_uint16_be
fpi_byte_reader_peek_int16_be
fpi_byte_reader_get_uint24_le
fpi_byte_reader_get_int24_le
fpi_byte_reader_peek_uint24_le
fpi_byte_reader_peek_int24_le
fpi_byte_reader_get_uint24_be
fpi_byte_reader_get_int24_be
fpi_byte_reader_peek_uint24_be
fpi_byte_reader_peek_int24_be
fpi_byte_reader_get_uint32_le
fpi_byte_reader_get_int32_le
fpi_byte_reader_peek_uint32_le
fpi_byte_reader_peek_int32_le
fpi_byte_reader_get_uint32_be
fpi_byte_reader_get_int32_be
fpi_byte_reader_peek_uint32_be
fpi_byte_reader_peek_int32_be
fpi_byte_reader_get_uint64_le
fpi_byte_reader_get_int64_le
fpi_byte_reader_peek_uint64_le
fpi_byte_reader_peek_int64_le
fpi_byte_reader_get_uint64_be
fpi_byte_reader_get_int64_be
fpi_byte_reader_peek_uint64_be
fpi_byte_reader_peek_int64_be
fpi_byte_reader_get_float32_le
fpi_byte_reader_peek_float32_le
fpi_byte_reader_get_float32_be
fpi_byte_reader_peek_float32_be
fpi_byte_reader_get_float64_le
fpi_byte_reader_peek_float64_le
fpi_byte_reader_get_float64_be
fpi_byte_reader_peek_float64_be
fpi_byte_reader_get_data
fpi_byte_reader_peek_data
fpi_byte_reader_get_data_static
fpi_byte_reader_peek_data_static
fpi_byte_reader_dup_data
fpi_byte_reader_masked_scan_uint32
fpi_byte_reader_masked_scan_uint32_peek
fpi_byte_reader_skip_string
fpi_byte_reader_skip_string_utf8
fpi_byte_reader_skip_string_utf16
fpi_byte_reader_skip_string_utf32
fpi_byte_reader_peek_string
fpi_byte_reader_peek_string_utf8
fpi_byte_reader_get_string_utf8
fpi_byte_reader_dup_string_utf8
fpi_byte_reader_dup_string_utf16
fpi_byte_reader_dup_string_utf32
</SECTION>
<SECTION>
<FILE>fpi-byte-writer</FILE>
<TITLE>FpiByteWriter</TITLE>
FpiByteWriter
fpi_byte_writer_new
fpi_byte_writer_new_with_size
fpi_byte_writer_new_with_data
fpi_byte_writer_init
fpi_byte_writer_init_with_size
fpi_byte_writer_init_with_data
fpi_byte_writer_reset
fpi_byte_writer_reset_and_get_bytes
fpi_byte_writer_reset_and_get_data
fpi_byte_writer_free
fpi_byte_writer_free_and_get_data
fpi_byte_writer_get_remaining
fpi_byte_writer_ensure_free_space
fpi_byte_writer_put_bytes
fpi_byte_writer_put_uint8
fpi_byte_writer_put_uint16_be
fpi_byte_writer_put_uint24_be
fpi_byte_writer_put_uint32_be
fpi_byte_writer_put_uint64_be
fpi_byte_writer_put_uint16_le
fpi_byte_writer_put_uint24_le
fpi_byte_writer_put_uint32_le
fpi_byte_writer_put_uint64_le
fpi_byte_writer_put_int8
fpi_byte_writer_put_int16_be
fpi_byte_writer_put_int24_be
fpi_byte_writer_put_int32_be
fpi_byte_writer_put_int64_be
fpi_byte_writer_put_int16_le
fpi_byte_writer_put_int24_le
fpi_byte_writer_put_int32_le
fpi_byte_writer_put_int64_le
fpi_byte_writer_put_float32_be
fpi_byte_writer_put_float64_be
fpi_byte_writer_put_float32_le
fpi_byte_writer_put_float64_le
fpi_byte_writer_put_string_utf8
fpi_byte_writer_put_string_utf16
fpi_byte_writer_put_string_utf32
fpi_byte_writer_put_data
fpi_byte_writer_fill
</SECTION>
<SECTION>
<FILE>fpi-context</FILE>
fpi_get_driver_types
@@ -282,7 +159,6 @@ fpi_device_get_current_action
fpi_device_retry_new
fpi_device_error_new
fpi_device_retry_new_msg
fpi_device_emulation_mode_enabled
fpi_device_error_new_msg
fpi_device_get_driver_data
fpi_device_get_enroll_data
@@ -345,15 +221,32 @@ fpi_image_device_retry_scan
fpi_image_device_set_bz3_threshold
</SECTION>
<SECTION>
<FILE>fpi-sdcp-device</FILE>
<TITLE>Internal FpSdcpDevice</TITLE>
FpiSdcpClaim
FpSdcpDeviceClass
fpi_sdcp_claim_copy
fpi_sdcp_claim_free
fpi_sdcp_claim_get_type
fpi_sdcp_claim_new
fpi_sdcp_device_connect_complete
fpi_sdcp_device_get_connect_data
fpi_sdcp_device_get_reconnect_data
fpi_sdcp_device_reconnect_complete
fpi_sdcp_device_enroll_commit_complete
fpi_sdcp_device_enroll_ready
fpi_sdcp_device_enroll_set_nonce
fpi_sdcp_device_identify_retry
fpi_sdcp_device_identify_complete
</SECTION>
<SECTION>
<FILE>fpi-log</FILE>
fp_dbg
fp_dbg_hex_dump_bytes
fp_dbg_hex_dump_data
fp_info
fp_warn
fp_err
fpi_log_is_debug_transfer_enabled
BUG_ON
BUG
</SECTION>
+2 -6
View File
@@ -28,6 +28,7 @@
<xi:include href="xml/fp-context.xml"/>
<xi:include href="xml/fp-device.xml"/>
<xi:include href="xml/fp-image-device.xml"/>
<xi:include href="xml/fp-sdcp-device.xml"/>
<xi:include href="xml/fp-print.xml"/>
<xi:include href="xml/fp-image.xml"/>
</part>
@@ -38,6 +39,7 @@
<title>Device methods for drivers</title>
<xi:include href="xml/fpi-device.xml"/>
<xi:include href="xml/fpi-image-device.xml"/>
<xi:include href="xml/fpi-sdcp-device.xml"/>
</chapter>
<chapter id="driver-helpers">
@@ -48,12 +50,6 @@
<xi:include href="xml/fpi-log.xml"/>
</chapter>
<chapter id="driver-data">
<title>Binary buffer I/O</title>
<xi:include href="xml/fpi-byte-reader.xml"/>
<xi:include href="xml/fpi-byte-writer.xml"/>
</chapter>
<chapter id="driver-img">
<title>Image manipulation</title>
<xi:include href="xml/fpi-image.xml"/>
+2 -2
View File
@@ -19,13 +19,13 @@ content_files = [
expand_content_files = content_files
glib_prefix = dependency('glib-2.0').get_variable(pkgconfig: 'prefix')
glib_prefix = dependency('glib-2.0').get_pkgconfig_variable('prefix')
glib_docpath = join_paths(glib_prefix, 'share', 'gtk-doc', 'html')
docpath = join_paths(get_option('datadir'), 'gtk-doc', 'html')
gnome.gtkdoc(versioned_libname,
main_xml: 'libfprint-docs.xml',
src_dir: join_paths(meson.project_source_root(), 'libfprint'),
src_dir: join_paths(meson.source_root(), 'libfprint'),
include_directories: include_directories('../libfprint'),
dependencies: libfprint_dep,
content_files: content_files,
-208
View File
@@ -1,208 +0,0 @@
/*
* Example storage clearing program, which deletes all the
* fingers which have been previously enrolled to disk.
* Copyright (C) 2020 Marco Trevisan <marco.trevisan@canonical.com>
* Copyright (C) 2024 Abhinav Baid <abhinavbaid@gmail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#define FP_COMPONENT "example-clear-storage"
#include <stdlib.h>
#include <stdio.h>
#include <libfprint/fprint.h>
#include <glib-unix.h>
#include "storage.h"
#include "utilities.h"
typedef struct _ClearStorageData
{
GMainLoop *loop;
GCancellable *cancellable;
unsigned int sigint_handler;
int ret_value;
} ClearStorageData;
static void
clear_storage_data_free (ClearStorageData *clear_storage_data)
{
g_clear_handle_id (&clear_storage_data->sigint_handler, g_source_remove);
g_clear_object (&clear_storage_data->cancellable);
g_main_loop_unref (clear_storage_data->loop);
g_free (clear_storage_data);
}
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClearStorageData, clear_storage_data_free)
static void
on_device_closed (FpDevice *dev, GAsyncResult *res, void *user_data)
{
g_autoptr(GError) error = NULL;
ClearStorageData *clear_storage_data = user_data;
fp_device_close_finish (dev, res, &error);
if (error)
g_warning ("Failed closing device %s", error->message);
g_main_loop_quit (clear_storage_data->loop);
}
static void
clear_storage_quit (FpDevice *dev,
ClearStorageData *clear_storage_data)
{
if (!fp_device_is_open (dev))
{
g_main_loop_quit (clear_storage_data->loop);
return;
}
fp_device_close (dev, NULL, (GAsyncReadyCallback) on_device_closed,
clear_storage_data);
}
static void
on_clear_storage_completed (FpDevice *dev, GAsyncResult *res, void *user_data)
{
g_autoptr(GError) error = NULL;
ClearStorageData *clear_storage_data = user_data;
if (fp_device_clear_storage_finish (dev, res, &error))
{
if (!clear_saved_prints (dev, &error))
{
g_warning ("Clear saved prints from local storage failed: %s",
error->message);
clear_storage_data->ret_value = EXIT_FAILURE;
}
else
{
g_print ("Clear storage successful!\n");
clear_storage_data->ret_value = EXIT_SUCCESS;
}
clear_storage_quit (dev, clear_storage_data);
return;
}
g_warning ("Failed to clear storage: %s", error->message);
clear_storage_data->ret_value = EXIT_FAILURE;
if (g_error_matches (error, FP_DEVICE_ERROR, FP_DEVICE_ERROR_NOT_SUPPORTED))
{
g_autoptr(GError) clear_error = NULL;
if (clear_saved_prints (dev, &clear_error))
clear_storage_data->ret_value = EXIT_SUCCESS;
else
g_warning ("Clear saved prints from local storage failed: %s",
clear_error->message);
}
clear_storage_quit (dev, clear_storage_data);
}
static void
start_clear_storage (FpDevice *dev, ClearStorageData *clear_storage_data)
{
char buffer[20];
g_print ("Clear device storage? [y/N]? ");
if (fgets (buffer, sizeof (buffer), stdin) &&
(buffer[0] == 'Y' || buffer[0] == 'y'))
{
fp_device_clear_storage (dev, clear_storage_data->cancellable,
(GAsyncReadyCallback) on_clear_storage_completed,
clear_storage_data);
return;
}
clear_storage_quit (dev, clear_storage_data);
}
static void
on_device_opened (FpDevice *dev, GAsyncResult *res, void *user_data)
{
g_autoptr(GError) error = NULL;
ClearStorageData *clear_storage_data = user_data;
if (!fp_device_open_finish (dev, res, &error))
{
g_warning ("Failed to open device: %s", error->message);
clear_storage_quit (dev, clear_storage_data);
return;
}
g_print ("Opened device. ");
start_clear_storage (dev, clear_storage_data);
}
static gboolean
sigint_cb (void *user_data)
{
ClearStorageData *clear_storage_data = user_data;
g_cancellable_cancel (clear_storage_data->cancellable);
return G_SOURCE_CONTINUE;
}
int
main (void)
{
g_autoptr(FpContext) ctx = NULL;
g_autoptr(ClearStorageData) clear_storage_data = NULL;
GPtrArray *devices;
FpDevice *dev;
setenv ("G_MESSAGES_DEBUG", "all", 0);
setenv ("LIBUSB_DEBUG", "3", 0);
ctx = fp_context_new ();
devices = fp_context_get_devices (ctx);
if (!devices)
{
g_warning ("Impossible to get devices");
return EXIT_FAILURE;
}
dev = discover_device (devices);
if (!dev)
{
g_warning ("No devices detected.");
return EXIT_FAILURE;
}
clear_storage_data = g_new0 (ClearStorageData, 1);
clear_storage_data->ret_value = EXIT_FAILURE;
clear_storage_data->loop = g_main_loop_new (NULL, FALSE);
clear_storage_data->cancellable = g_cancellable_new ();
clear_storage_data->sigint_handler = g_unix_signal_add_full (G_PRIORITY_HIGH,
SIGINT,
sigint_cb,
clear_storage_data,
NULL);
fp_device_open (dev, clear_storage_data->cancellable,
(GAsyncReadyCallback) on_device_opened,
clear_storage_data);
g_main_loop_run (clear_storage_data->loop);
return clear_storage_data->ret_value;
}
-6
View File
@@ -5,7 +5,6 @@ examples = [
'img-capture',
'manage-prints',
'verify',
'clear-storage',
]
foreach example: examples
@@ -22,8 +21,3 @@ executable('cpp-test',
'cpp-test.cpp',
dependencies: libfprint_dep,
)
if installed_tests
install_subdir('prints',
install_dir: installed_tests_testdir)
endif
+5 -63
View File
@@ -26,7 +26,6 @@
#include "storage.h"
#include <errno.h>
#include <glib/gstdio.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
@@ -56,18 +55,6 @@ get_print_data_descriptor (FpPrint *print, FpDevice *dev, FpFinger finger)
finger);
}
static char *
get_print_prefix_for_device (FpDevice *dev)
{
const char *driver;
const char *dev_id;
driver = fp_device_get_driver (dev);
dev_id = fp_device_get_device_id (dev);
return g_strdup_printf ("%s/%s/", driver, dev_id);
}
static GVariantDict *
load_data (void)
{
@@ -182,6 +169,8 @@ gallery_data_load (FpDevice *dev)
g_autoptr(GVariant) dict_variant = NULL;
g_autofree char *dev_prefix = NULL;
GPtrArray *gallery;
const char *driver;
const char *dev_id;
GVariantIter iter;
GVariant *value;
gchar *key;
@@ -189,7 +178,9 @@ gallery_data_load (FpDevice *dev)
gallery = g_ptr_array_new_with_free_func (g_object_unref);
dict = load_data ();
dict_variant = g_variant_dict_end (dict);
dev_prefix = get_print_prefix_for_device (dev);
driver = fp_device_get_driver (dev);
dev_id = fp_device_get_device_id (dev);
dev_prefix = g_strdup_printf ("%s/%s/", driver, dev_id);
g_variant_iter_init (&iter, dict_variant);
while (g_variant_iter_loop (&iter, "{sv}", &key, &value))
@@ -217,55 +208,6 @@ gallery_data_load (FpDevice *dev)
return gallery;
}
gboolean
clear_saved_prints (FpDevice *dev,
GError **error)
{
g_autoptr(GVariantDict) dict = NULL;
g_autoptr(GVariantDict) updated_dict = NULL;
g_autoptr(GVariant) dict_variant = NULL;
g_autofree char *dev_prefix = NULL;
GPtrArray *print_keys;
GVariantIter iter;
GVariant *value;
gchar *key;
print_keys = g_ptr_array_new_with_free_func (g_free);
dict = load_data ();
dict_variant = g_variant_dict_end (dict);
dev_prefix = get_print_prefix_for_device (dev);
g_variant_iter_init (&iter, dict_variant);
while (g_variant_iter_loop (&iter, "{sv}", &key, &value))
{
if (!g_str_has_prefix (key, dev_prefix))
continue;
g_ptr_array_add (print_keys, g_strdup (key));
}
if (!print_keys->len)
return TRUE;
updated_dict = load_data ();
for (guint i = 0; i < print_keys->len; ++i)
{
key = g_ptr_array_index (print_keys, i);
if (!g_variant_dict_remove (updated_dict, key))
{
g_warning ("Print '%s' key not found!", key);
continue;
}
g_debug ("Dropping print '%s' from gallery", key);
}
save_data (g_variant_dict_end (updated_dict));
return TRUE;
}
FpPrint *
print_create_template (FpDevice *dev, FpFinger finger, gboolean load_existing)
{
-5
View File
@@ -20,17 +20,12 @@
#pragma once
#include <glib.h>
#include <libfprint/fprint.h>
int print_data_save (FpPrint *print,
FpFinger finger,
gboolean update_fingerprint);
FpPrint * print_data_load (FpDevice *dev,
FpFinger finger);
GPtrArray * gallery_data_load (FpDevice *dev);
gboolean clear_saved_prints (FpDevice *dev,
GError **error);
FpPrint * print_create_template (FpDevice *dev,
FpFinger finger,
const gboolean load_existing);
-1
View File
@@ -1 +0,0 @@
gcov-ignore-parse-errors = suspicious_hits.warn
+1 -1
View File
@@ -791,7 +791,7 @@ complete_deactivation (FpImageDevice *dev)
* maybe we can do this with a master reset, unconditionally? */
self->deactivating = FALSE;
g_slist_free_full (self->strips, g_free);
g_slist_free (self->strips);
self->strips = NULL;
self->strips_len = 0;
self->blanks_count = 0;
+3 -2
View File
@@ -213,8 +213,9 @@ sum_histogram_values (unsigned char *data, guint8 threshold)
if (threshold > 0x0f)
return -1;
/* FIXME endianness */
for (i = threshold; i < 16; i++)
r += GUINT16_FROM_LE (histogram[i]);
r += histogram[i];
return r;
}
@@ -822,7 +823,7 @@ complete_deactivation (FpImageDevice *dev)
* maybe we can do this with a master reset, unconditionally? */
self->deactivating = FALSE;
g_slist_free_full (self->strips, g_free);
g_slist_free (self->strips);
self->strips = NULL;
self->strips_len = 0;
fpi_image_device_deactivate_complete (dev, NULL);
+8 -52
View File
@@ -57,7 +57,6 @@ struct _FpiDeviceAes2550
GSList *strips;
size_t strips_len;
gboolean active;
gboolean deactivating;
int heartbeat_cnt;
};
@@ -92,21 +91,11 @@ 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)
{
/* 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);
fpi_image_device_session_error (FP_IMAGE_DEVICE (device), error);
return;
}
@@ -133,20 +122,10 @@ finger_det_reqs_cb (FpiUsbTransfer *t, FpDevice *device,
{
FpiUsbTransfer *transfer;
FpImageDevice *dev = FP_IMAGE_DEVICE (device);
FpiDeviceAes2550 *self = FPI_DEVICE_AES2550 (device);
if (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);
fpi_image_device_session_error (dev, error);
return;
}
@@ -260,19 +239,13 @@ 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
{
fpi_ssm_mark_failed (transfer->ssm, error);
if (error)
fpi_ssm_mark_failed (transfer->ssm, error);
else
fpi_ssm_mark_failed (transfer->ssm,
fpi_device_error_new (FP_DEVICE_ERROR_PROTO));
}
}
@@ -398,11 +371,6 @@ 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
@@ -521,16 +489,12 @@ 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)
{
self->active = TRUE;
start_finger_detection (dev);
}
start_finger_detection (dev);
}
static void
@@ -547,13 +511,6 @@ 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;
}
@@ -565,7 +522,6 @@ 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;
+1 -1
View File
@@ -124,7 +124,7 @@ G_DEFINE_TYPE (FpiDeviceAes4000, fpi_device_aes4000, FPI_TYPE_DEVICE_AES3K);
static const FpIdEntry id_table[] = {
{ .vid = 0x08ff, .pid = 0x5501 },
{ .pid = 0x08ff, .vid = 0x5501 },
{ .vid = 0, .pid = 0, .driver_data = 0 },
};
+1 -10
View File
@@ -384,15 +384,6 @@ 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);
@@ -731,7 +722,7 @@ complete_deactivation (FpImageDevice *dev)
G_DEBUG_HERE ();
priv->deactivating = FALSE;
g_slist_free_full (priv->strips, g_free);
g_slist_free (priv->strips);
priv->strips = NULL;
priv->strips_len = 0;
fpi_image_device_deactivate_complete (dev, NULL);
+2 -2
View File
@@ -190,7 +190,7 @@ data_resp_cb (FpiUsbTransfer *transfer, FpDevice *dev, gpointer user_data, GErro
{
if (!self->stop && (self->strips_len > 0))
{
g_autoptr(FpImage) img = NULL;
FpImage *img;
self->strips = g_slist_reverse (self->strips);
fpi_do_movement_estimation (&assembling_ctx, self->strips);
img = fpi_assemble_frames (&assembling_ctx, self->strips);
@@ -199,7 +199,7 @@ data_resp_cb (FpiUsbTransfer *transfer, FpDevice *dev, gpointer user_data, GErro
self->strips = NULL;
self->strips_len = 0;
FpImage *resizeImage = fpi_image_resize (img, EGIS0570_RESIZE, EGIS0570_RESIZE);
fpi_image_device_image_captured (img_self, g_steal_pointer (&resizeImage));
fpi_image_device_image_captured (img_self, resizeImage);
}
fpi_image_device_report_finger_status (img_self, FALSE);
File diff suppressed because it is too large Load Diff
-188
View File
@@ -1,188 +0,0 @@
/*
* Driver for Egis Technology (LighTuning) Match-On-Chip sensors
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#pragma once
#include "fpi-device.h"
#include "fpi-ssm.h"
G_DECLARE_FINAL_TYPE (FpiDeviceEgisEtu905, fpi_device_egis_etu905, FPI, DEVICE_EGIS_ETU905, FpDevice)
#define EGIS_ETU905_DRIVER_FULLNAME "Egis Technology (LighTuning) Match-on-Chip"
#define EGIS_ETU905_DRIVER_CHECK_PREFIX_TYPE1 (1 << 0)
#define EGIS_ETU905_DRIVER_CHECK_PREFIX_TYPE2 (1 << 1)
#define EGIS_ETU905_DRIVER_MAX_ENROLL_STAGES_20 (1 << 2)
#define EGIS_ETU905_EP_CMD_OUT (0x02 | FPI_USB_ENDPOINT_OUT)
#define EGIS_ETU905_EP_CMD_IN (0x81 | FPI_USB_ENDPOINT_IN)
#define EGIS_ETU905_EP_CMD_INTERRUPT_IN 0x83
#define EGIS_ETU905_USB_CONTROL_TIMEOUT 5000
#define EGIS_ETU905_USB_SEND_TIMEOUT 5000
#define EGIS_ETU905_USB_RECV_TIMEOUT 5000
#define EGIS_ETU905_USB_INTERRUPT_TIMEOUT 0 /* No timeout for waiting for finger down */
#define EGIS_ETU905_USB_IN_RECV_LENGTH 4096
#define EGIS_ETU905_USB_INTERRUPT_IN_RECV_LENGTH 64
#define EGIS_ETU905_MAX_ENROLL_STAGES_DEFAULT 12
#define EGIS_ETU905_MAX_ENROLL_NUM 12
#define EGIS_ETU905_FINGERPRINT_DATA_SIZE 32
#define EGIS_ETU905_LIST_RESPONSE_PREFIX_SIZE 14
#define EGIS_ETU905_LIST_RESPONSE_SUFFIX_SIZE 2
#define EGIS_ETU905_PARA_4_SIZE 68
#define EGIS_ETU905_PARA_1_VALUE 0
#define EGIS_ETU905_PARA_2_VALUE 0
#define EGIS_ETU905_PARA_3_VALUE 32
/* standard prefixes for all read/writes */
static const guchar egis_etu905_write_prefix[] = {'E', 'G', 'I', 'S', 0x00, 0x00, 0x00, 0x01};
static const guchar egis_etu905_read_prefix[] = {'S', 'I', 'G', 'E', 0x00, 0x00, 0x00, 0x01};
/* hard-coded command payloads */
static const guchar cmd_fw_version[] = {0x00, 0x00, 0x00, 0x07, 0x50, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x0c};
static const guchar rsp_fw_version_suffix[] = {0x90, 0x00};
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 guchar cmd_list[] = {0x00, 0x00, 0x00, 0x07, 0x50, 0x19, 0x04, 0x00, 0x00, 0x01, 0x40};
static const guchar cmd_sensor_reset[] = {0x00, 0x00, 0x00, 0x04, 0x50, 0x1a, 0x00, 0x00};
static const guchar cmd_sensor_check[] = {0x00, 0x00, 0x00, 0x04, 0x50, 0x17, 0x02, 0x00};
static const guchar cmd_sensor_identify[] = {0x00, 0x00, 0x00, 0x04, 0x50, 0x17, 0x01, 0x01};
static const guchar rsp_identify_match_suffix[] = {0x90, 0x00};
static const guchar rsp_identify_notmatch_suffix[] = {0x90, 0x04};
static const guchar cmd_enroll_starting[] = {0x00, 0x00, 0x00, 0x07, 0x50, 0x16, 0x01, 0x00, 0x00, 0x00, 0x20};
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 guchar cmd_read_capture[] = {0x00, 0x00, 0x00, 0x07, 0x50, 0x16, 0x02, 0x02, 0x00, 0x00, 0x02};
static const guchar cmd_duplicate_check[] = {0x00, 0x00, 0x00, 0x04, 0x50, 0x16, 0x05, 0x00};
static const guchar rsp_read_success_prefix[] = {0x00, 0x00, 0x00, 0x04};
static const guchar rsp_read_success_suffix[] = {0x90, 0x00};
static const guchar rsp_read_offcenter_prefix[] = {0x00, 0x00, 0x00, 0x04};
static const guchar rsp_read_offcenter_suffix[] = {0x64, 0x91};
static const guchar rsp_read_dirty_prefix[] = {0x00, 0x00, 0x00, 0x02, 0x64};
static const guchar cmd_commit_starting[] = {0x00, 0x00, 0x00, 0x07, 0x50, 0x16, 0x05, 0x00, 0x00, 0x00, 0x20};
static const guchar cmd_identify_cancel[] = {0x00, 0x00, 0x00, 0x04, 0x50, 0x04, 0x01, 0x00};
static const guchar cmd_identify_cancel_result[] = {0x00, 0x00, 0x00, 0x04, 0x50, 0x04, 0x02, 0x00};
/* prefixes/suffixes and other things for dynamically created command payloads */
#define EGIS_ETU905_CHECK_BYTES_LENGTH 2
#define EGIS_ETU905_IDENTIFY_RESPONSE_PRINT_ID_OFFSET 46
#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 guchar cmd_delete_prefix[] = {0x50, 0x18, 0x04, 0x00, 0x00};
static const guchar rsp_delete_success_prefix[] = {0x00, 0x00, 0x00, 0x02, 0x90, 0x00};
static const guchar cmd_check_prefix_type1[] = {0x50, 0x17, 0x03, 0x00, 0x00};
static const guchar cmd_check_prefix_type2[] = {0x50, 0x17, 0x03, 0x80, 0x00};
static const guchar cmd_check_suffix[] = {0x00, 0x40};
static const guchar rsp_check_not_yet_enrolled_suffix[] = {0x90, 0x04};
/* SSM task states and various status enums */
typedef enum {
CMD_SEND,
CMD_GET,
CMD_STATES,
} CommandStates;
typedef enum {
DEV_GET_FW_VERSION,
DEV_INIT_CONTROL,
DEV_INIT_STATES,
} DeviceInitStates;
typedef enum {
IDENTIFY_GET_ENROLLED_IDS,
IDENTIFY_CHECK_ENROLLED_NUM,
IDENTIFY_SENSOR_RESET,
IDENTIFY_SENSOR_IDENTIFY,
IDENTIFY_WAIT_FINGER,
IDENTIFY_SENSOR_CHECK,
IDENTIFY_CHECK,
IDENTIFY_COMPLETE_SENSOR_RESET,
IDENTIFY_COMPLETE,
IDENTIFY_STATES,
} IdentifyStates;
typedef enum {
ENROLL_START,
ENROLL_CAPTURE_SENSOR_RESET,
ENROLL_CAPTURE_SENSOR_START_CAPTURE,
ENROLL_CAPTURE_WAIT_FINGER,
ENROLL_CAPTURE_READ_RESPONSE,
ENROLL_DUPLICATE_CHECK,
ENROLL_COMMIT_START,
ENROLL_COMMIT,
ENROLL_COMMIT_SENSOR_RESET,
ENROLL_COMPLETE,
ENROLL_STATES,
} EnrollStates;
typedef enum {
ENROLL_STATUS_DEVICE_FULL,
ENROLL_STATUS_DUPLICATE,
ENROLL_STATUS_PARTIAL_OK,
ENROLL_STATUS_RETRY,
ENROLL_STATUS_COMPLETE,
} EnrollStatus;
typedef enum {
LIST_GET_ENROLLED_IDS,
LIST_RETURN_ENROLLED_PRINTS,
LIST_STATES,
} ListStates;
typedef enum {
DELETE_GET_ENROLLED_IDS,
DELETE_DELETE,
DELETE_STATES,
} DeleteStates;
typedef enum {
CANCEL_SENSOR_RESET,
CANCEL_SEND_CANCEL,
CANCEL_SEND_CANCEL_RESULT,
CANCEL_STATES,
} CancelStates;
File diff suppressed because it is too large Load Diff
-196
View File
@@ -1,196 +0,0 @@
/*
* Driver for Egis Technology (LighTuning) Match-On-Chip sensors
* Originally authored 2023 by Joshua Grisham <josh@joshuagrisham.com>
*
* Portions of code and logic inspired from the elanmoc libfprint driver
* which is copyright (C) 2021 Elan Microelectronics Inc (see elanmoc.c)
*
* Based on original reverse-engineering work by Joshua Grisham. The protocol has
* been reverse-engineered from captures of the official Windows driver, and by
* testing commands on the sensor with a multiplatform Python prototype driver:
* https://github.com/joshuagrisham/galaxy-book2-pro-linux/tree/main/fingerprint/
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#pragma once
#include "fpi-device.h"
#include "fpi-ssm.h"
G_DECLARE_FINAL_TYPE (FpiDeviceEgisMoc, fpi_device_egismoc, FPI, DEVICE_EGISMOC, FpDevice)
#define EGISMOC_DRIVER_FULLNAME "Egis Technology (LighTuning) Match-on-Chip"
#define EGISMOC_DRIVER_CHECK_PREFIX_TYPE1 (1 << 0)
#define EGISMOC_DRIVER_CHECK_PREFIX_TYPE2 (1 << 1)
#define EGISMOC_DRIVER_MAX_ENROLL_STAGES_20 (1 << 2)
#define EGISMOC_EP_CMD_OUT (0x02 | FPI_USB_ENDPOINT_OUT)
#define EGISMOC_EP_CMD_IN (0x81 | FPI_USB_ENDPOINT_IN)
#define EGISMOC_EP_CMD_INTERRUPT_IN 0x83
#define EGISMOC_USB_CONTROL_TIMEOUT 5000
#define EGISMOC_USB_SEND_TIMEOUT 5000
#define EGISMOC_USB_RECV_TIMEOUT 5000
#define EGISMOC_USB_INTERRUPT_TIMEOUT 60000
#define EGISMOC_USB_IN_RECV_LENGTH 4096
#define EGISMOC_USB_INTERRUPT_IN_RECV_LENGTH 64
#define EGISMOC_MAX_ENROLL_STAGES_DEFAULT 10
#define EGISMOC_MAX_ENROLL_NUM 10
#define EGISMOC_FINGERPRINT_DATA_SIZE 32
#define EGISMOC_LIST_RESPONSE_PREFIX_SIZE 14
#define EGISMOC_LIST_RESPONSE_SUFFIX_SIZE 2
/* standard prefixes for all read/writes */
static guchar egismoc_write_prefix[] = {'E', 'G', 'I', 'S', 0x00, 0x00, 0x00, 0x01};
static guchar egismoc_read_prefix[] = {'S', 'I', 'G', 'E', 0x00, 0x00, 0x00, 0x01};
/* hard-coded command payloads */
static guchar cmd_fw_version[] = {0x00, 0x00, 0x00, 0x07, 0x50, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x0c};
static guchar rsp_fw_version_suffix[] = {0x90, 0x00};
static guchar cmd_list[] = {0x00, 0x00, 0x00, 0x07, 0x50, 0x19, 0x04, 0x00, 0x00, 0x01, 0x40};
static guchar cmd_sensor_reset[] = {0x00, 0x00, 0x00, 0x04, 0x50, 0x1a, 0x00, 0x00};
static guchar cmd_sensor_check[] = {0x00, 0x00, 0x00, 0x04, 0x50, 0x17, 0x02, 0x00};
static guchar cmd_sensor_identify[] = {0x00, 0x00, 0x00, 0x04, 0x50, 0x17, 0x01, 0x01};
static guchar rsp_identify_match_suffix[] = {0x90, 0x00};
static guchar rsp_identify_notmatch_suffix[] = {0x90, 0x04};
static guchar cmd_sensor_enroll[] = {0x00, 0x00, 0x00, 0x04, 0x50, 0x17, 0x01, 0x00};
static guchar cmd_enroll_starting[] = {0x00, 0x00, 0x00, 0x07, 0x50, 0x16, 0x01, 0x00, 0x00, 0x00, 0x20};
static guchar cmd_sensor_start_capture[] = {0x00, 0x00, 0x00, 0x04, 0x50, 0x16, 0x02, 0x01};
static guchar cmd_read_capture[] = {0x00, 0x00, 0x00, 0x07, 0x50, 0x16, 0x02, 0x02, 0x00, 0x00, 0x02};
static guchar rsp_read_success_prefix[] = {0x00, 0x00, 0x00, 0x04};
static guchar rsp_read_success_suffix[] = {0x90, 0x00};
static guchar rsp_read_offcenter_prefix[] = {0x00, 0x00, 0x00, 0x04};
static guchar rsp_read_offcenter_suffix[] = {0x64, 0x91};
static guchar rsp_read_dirty_prefix[] = {0x00, 0x00, 0x00, 0x02, 0x64};
static guchar cmd_commit_starting[] = {0x00, 0x00, 0x00, 0x07, 0x50, 0x16, 0x05, 0x00, 0x00, 0x00, 0x20};
/* commands which exist on the device but are currently not used */
/*
static guchar cmd_sensor_cancel[] = {0x00, 0x00, 0x00, 0x04, 0x50, 0x16, 0x04, 0x00};
static gsize cmd_sensor_cancel_len = sizeof(cmd_sensor_cancel) / sizeof(cmd_sensor_cancel[0]);
static guchar cmd_sensor_verify[] = {0x00, 0x00, 0x00, 0x04, 0x50, 0x04, 0x01, 0x00};
static gsize cmd_sensor_verify_len = sizeof(cmd_sensor_verify) / sizeof(cmd_sensor_verify[0]);
static guchar cmd_read_verify[] = {0x00, 0x00, 0x00, 0x04, 0x50, 0x04, 0x02, 0x00};
static gsize cmd_read_verify_len = sizeof(cmd_read_verify) / sizeof(cmd_read_verify[0]);
*/
/* prefixes/suffixes and other things for dynamically created command payloads */
#define EGISMOC_CHECK_BYTES_LENGTH 2
#define EGISMOC_IDENTIFY_RESPONSE_PRINT_ID_OFFSET 46
#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 guchar cmd_delete_prefix[] = {0x50, 0x18, 0x04, 0x00, 0x00};
static guchar rsp_delete_success_prefix[] = {0x00, 0x00, 0x00, 0x02, 0x90, 0x00};
static guchar cmd_check_prefix_type1[] = {0x50, 0x17, 0x03, 0x00, 0x00};
static guchar cmd_check_prefix_type2[] = {0x50, 0x17, 0x03, 0x80, 0x00};
static guchar cmd_check_suffix[] = {0x00, 0x40};
static guchar rsp_check_not_yet_enrolled_suffix[] = {0x90, 0x04};
/* SSM task states and various status enums */
typedef enum {
CMD_SEND,
CMD_GET,
CMD_STATES,
} CommandStates;
typedef enum {
DEV_INIT_CONTROL1,
DEV_INIT_CONTROL2,
DEV_INIT_CONTROL3,
DEV_INIT_CONTROL4,
DEV_INIT_CONTROL5,
DEV_GET_FW_VERSION,
DEV_INIT_STATES,
} DeviceInitStates;
typedef enum {
IDENTIFY_GET_ENROLLED_IDS,
IDENTIFY_CHECK_ENROLLED_NUM,
IDENTIFY_SENSOR_RESET,
IDENTIFY_SENSOR_IDENTIFY,
IDENTIFY_WAIT_FINGER,
IDENTIFY_SENSOR_CHECK,
IDENTIFY_CHECK,
IDENTIFY_COMPLETE_SENSOR_RESET,
IDENTIFY_COMPLETE,
IDENTIFY_STATES,
} IdentifyStates;
typedef enum {
ENROLL_GET_ENROLLED_IDS,
ENROLL_CHECK_ENROLLED_NUM,
ENROLL_SENSOR_RESET,
ENROLL_SENSOR_ENROLL,
ENROLL_WAIT_FINGER,
ENROLL_SENSOR_CHECK,
ENROLL_CHECK,
ENROLL_START,
ENROLL_CAPTURE_SENSOR_RESET,
ENROLL_CAPTURE_SENSOR_START_CAPTURE,
ENROLL_CAPTURE_WAIT_FINGER,
ENROLL_CAPTURE_READ_RESPONSE,
ENROLL_COMMIT_START,
ENROLL_COMMIT,
ENROLL_COMMIT_SENSOR_RESET,
ENROLL_COMPLETE,
ENROLL_STATES,
} EnrollStates;
typedef enum {
ENROLL_STATUS_DEVICE_FULL,
ENROLL_STATUS_DUPLICATE,
ENROLL_STATUS_PARTIAL_OK,
ENROLL_STATUS_RETRY,
ENROLL_STATUS_COMPLETE,
} EnrollStatus;
typedef enum {
LIST_GET_ENROLLED_IDS,
LIST_RETURN_ENROLLED_PRINTS,
LIST_STATES,
} ListStates;
typedef enum {
DELETE_GET_ENROLLED_IDS,
DELETE_DELETE,
DELETE_STATES,
} DeleteStates;
+5 -22
View File
@@ -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] =
GUINT16_FROM_LE (((unsigned short *) self->last_read)[raw_idx]);
((unsigned short *) self->last_read)[raw_idx];
}
}
@@ -251,12 +251,7 @@ elan_process_frame_linear (unsigned short *raw_frame,
max = raw_frame[i];
}
if (max == min)
{
memset (frame->data, 0, frame_size);
*frames = g_slist_prepend (*frames, frame);
g_return_if_reached ();
}
g_assert (max != min);
unsigned short px;
@@ -292,11 +287,6 @@ 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++)
@@ -367,7 +357,7 @@ elan_cmd_cb (FpiUsbTransfer *transfer, FpDevice *dev,
if (transfer->endpoint & FPI_USB_ENDPOINT_IN)
{
/* just finished receiving */
self->last_read = g_memdup2 (transfer->buffer, transfer->actual_length);
self->last_read = g_memdup (transfer->buffer, transfer->actual_length);
elan_cmd_done (ssm);
}
else
@@ -557,17 +547,10 @@ capture_run_state (FpiSsm *ssm, FpDevice *dev)
fpi_image_device_report_finger_status (idev, TRUE);
elan_run_cmd (ssm, dev, &get_image_cmd, ELAN_CMD_TIMEOUT);
}
else if (self->dev_type == ELAN_0C58 && self->last_read &&
(self->last_read[0] == 0x00 || self->last_read[0] == 0xaf))
{
/* 0x00 - not ready
* 0xaf - finger removed or sensor busy (seen on 0x0c58) */
fpi_ssm_jump_to_state_delayed (ssm, CAPTURE_WAIT_FINGER, 10);
}
else
{
/* XXX: The timeout is emulated incorrectly, resulting in a zero byte read. */
if (fpi_device_emulation_mode_enabled (FP_DEVICE (self)))
if (g_strcmp0 (g_getenv ("FP_DEVICE_EMULATION"), "1") == 0)
fpi_ssm_mark_completed (ssm);
else
fpi_ssm_mark_failed (ssm, fpi_device_error_new (FP_DEVICE_ERROR_PROTO));
@@ -812,7 +795,7 @@ elan_calibrate (FpiDeviceElan *self)
g_return_if_fail (!self->active);
self->active = TRUE;
self->calib_atts_left = ELAN_CALIBRATION_ATTEMPTS (self->dev_type);
self->calib_atts_left = ELAN_CALIBRATION_ATTEMPTS;
FpiSsm *ssm = fpi_ssm_new (FP_DEVICE (self), calibrate_run_state,
CALIBRATE_NUM_STATES);
+2 -6
View File
@@ -31,7 +31,6 @@
#define ELAN_0907 (1 << 0)
#define ELAN_0C03 (1 << 1)
#define ELAN_0C42 (1 << 2)
#define ELAN_0C58 (1 << 3)
/* devices which don't require frame rotation before assembling */
#define ELAN_NOT_ROTATED ELAN_0C03
@@ -45,9 +44,7 @@
/* times to retry reading calibration status during one session
* generally prevents calibration from looping indefinitely */
#define ELAN_DEFAULT_CALIBRATION_ATTEMPTS 10
#define ELAN_CALIBRATION_ATTEMPTS(dev_type) \
((dev_type) == ELAN_0C58 ? 30 : ELAN_DEFAULT_CALIBRATION_ATTEMPTS)
#define ELAN_CALIBRATION_ATTEMPTS 10
/* min and max frames in a capture */
#define ELAN_MIN_FRAMES 7
@@ -218,12 +215,11 @@ static const FpIdEntry elan_id_table[] = {
{.vid = ELAN_VEND_ID, .pid = 0x0c33, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c3d, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c42, .driver_data = ELAN_0C42},
{.vid = ELAN_VEND_ID, .pid = 0x0c4b, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c4d, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c4f, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c63, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c6e, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c58, .driver_data = ELAN_0C58},
{.vid = ELAN_VEND_ID, .pid = 0x0c58, .driver_data = ELAN_ALL_DEV},
{.vid = 0, .pid = 0, .driver_data = 0},
};
+72 -92
View File
@@ -27,20 +27,6 @@ G_DEFINE_TYPE (FpiDeviceElanmoc, fpi_device_elanmoc, FP_TYPE_DEVICE)
static const FpIdEntry id_table[] = {
{ .vid = 0x04f3, .pid = 0x0c7d, },
{ .vid = 0x04f3, .pid = 0x0c7e, },
{ .vid = 0x04f3, .pid = 0x0c82, },
{ .vid = 0x04f3, .pid = 0x0c88, },
{ .vid = 0x04f3, .pid = 0x0c8c, },
{ .vid = 0x04f3, .pid = 0x0c8d, },
{ .vid = 0x04f3, .pid = 0x0c98, },
{ .vid = 0x04f3, .pid = 0x0c99, },
{ .vid = 0x04f3, .pid = 0x0c9c, },
{ .vid = 0x04f3, .pid = 0x0c9d, },
{ .vid = 0x04f3, .pid = 0x0c9f, },
{ .vid = 0x04f3, .pid = 0x0ca3, },
{ .vid = 0x04f3, .pid = 0x0ca7, },
{ .vid = 0x04f3, .pid = 0x0ca8, },
{ .vid = 0x04f3, .pid = 0x0cb0, },
{ .vid = 0x04f3, .pid = 0x0cb2, },
{ .vid = 0, .pid = 0, .driver_data = 0 }, /* terminating entry */
};
@@ -59,9 +45,9 @@ elanmoc_compose_cmd (
const struct elanmoc_cmd *cmd_info
)
{
g_autofree uint8_t *cmd_buf = NULL;
g_autofree char *cmd_buf = NULL;
cmd_buf = g_new0 (uint8_t, cmd_info->cmd_len);
cmd_buf = g_malloc0 (cmd_info->cmd_len);
if(cmd_info->cmd_len < ELAN_MAX_HDR_LEN)
memcpy (cmd_buf, &cmd_info->cmd_header, cmd_info->cmd_len);
else
@@ -137,10 +123,10 @@ fp_cmd_receive_cb (FpiUsbTransfer *transfer,
}
typedef enum {
ELAN_MOC_CMD_SEND = 0,
ELAN_MOC_CMD_GET,
ELAN_MOC_CMD_NUM_STATES,
} ElanMocCmdState;
FP_CMD_SEND = 0,
FP_CMD_GET,
FP_CMD_NUM_STATES,
} FpCmdState;
static void
fp_cmd_run_state (FpiSsm *ssm,
@@ -151,7 +137,7 @@ fp_cmd_run_state (FpiSsm *ssm,
switch (fpi_ssm_get_cur_state (ssm))
{
case ELAN_MOC_CMD_SEND:
case FP_CMD_SEND:
if (self->cmd_transfer)
{
self->cmd_transfer->ssm = ssm;
@@ -167,7 +153,7 @@ fp_cmd_run_state (FpiSsm *ssm,
}
break;
case ELAN_MOC_CMD_GET:
case FP_CMD_GET:
if (self->cmd_len_in == 0)
{
CommandData *data = fpi_ssm_get_data (ssm);
@@ -234,7 +220,7 @@ elanmoc_get_cmd (FpDevice *device, guint8 *buffer_out,
self->cmd_ssm = fpi_ssm_new (FP_DEVICE (self),
fp_cmd_run_state,
ELAN_MOC_CMD_NUM_STATES);
FP_CMD_NUM_STATES);
fpi_ssm_set_data (self->cmd_ssm, data, (GDestroyNotify) fp_cmd_ssm_done_data_free);
@@ -389,21 +375,12 @@ elanmoc_enroll_cb (FpiDeviceElanmoc *self,
enroll_status_report (self, ENROLL_RSP_RETRY, self->num_frames, NULL);
}
if (self->num_frames == self->max_moc_enroll_time && buffer_in[1] == ELAN_MSG_OK)
{
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);
}
if (self->num_frames == ELAN_MOC_ENROLL_TIMES && buffer_in[1] == ELAN_MSG_OK)
fpi_ssm_next_state (self->task_ssm);
else if (self->num_frames < ELAN_MOC_ENROLL_TIMES)
fpi_ssm_jump_to_state (self->task_ssm, MOC_ENROLL_WAIT_FINGER);
else
{
fpi_ssm_mark_failed (self->task_ssm,
fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
"Enrollment failed (status 0x%02x)",
buffer_in[1]));
}
fpi_ssm_mark_failed (self->task_ssm, error);
}
}
@@ -463,7 +440,7 @@ elan_enroll_run_state (FpiSsm *ssm, FpDevice *dev)
case MOC_ENROLL_WAIT_FINGER:
cmd_buf = elanmoc_compose_cmd (&elanmoc_enroll_cmd);
cmd_buf[3] = self->curr_enrolled;
cmd_buf[4] = self->max_moc_enroll_time;
cmd_buf[4] = ELAN_MOC_ENROLL_TIMES;
cmd_buf[5] = self->num_frames;
elanmoc_get_cmd (dev, cmd_buf, elanmoc_enroll_cmd.cmd_len, elanmoc_enroll_cmd.resp_len, 1, elanmoc_enroll_cb);
break;
@@ -528,7 +505,7 @@ create_print_from_response (FpiDeviceElanmoc *self,
return NULL;
}
userid = g_memdup2 (&buffer_in[5], userid_len);
userid = g_memdup (&buffer_in[5], userid_len);
userid_safe = g_strndup ((const char *) &buffer_in[5], userid_len);
print = fp_print_new (FP_DEVICE (self));
uid = g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE, userid, userid_len, 1);
@@ -648,6 +625,7 @@ 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;
@@ -676,18 +654,31 @@ elanmoc_match_report_cb (FpiDeviceElanmoc *self,
fp_info ("Verify/Identify successful for: %s", fp_print_get_description (print));
fpi_device_get_identify_data (device, &prints);
found = g_ptr_array_find_with_equal_func (prints,
print,
(GEqualFunc) fp_print_equal,
&index);
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);
if (found)
fpi_device_identify_report (device, g_ptr_array_index (prints, index), print, NULL);
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);
}
else
fpi_device_identify_report (device, NULL, print, NULL);
{
fpi_device_get_verify_data (device, &verify_print);
fpi_device_identify_complete (device, 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);
}
}
static void
@@ -699,7 +690,10 @@ identify_status_report (FpiDeviceElanmoc *self, int verify_status_id,
if (error)
{
fpi_device_identify_complete (device, 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);
return;
}
@@ -709,8 +703,16 @@ identify_status_report (FpiDeviceElanmoc *self, int verify_status_id,
{
if (data == ELAN_MSG_VERIFY_ERR)
{
fpi_device_identify_report (device, NULL, NULL, NULL);
fpi_device_identify_complete (device, NULL);
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);
}
}
else
{
@@ -729,15 +731,23 @@ identify_status_report (FpiDeviceElanmoc *self, int verify_status_id,
retry_error = fpi_device_retry_new (FP_DEVICE_RETRY_GENERAL);
}
fpi_device_identify_report (device, NULL, NULL, retry_error);
fpi_device_identify_complete (device, NULL);
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);
}
}
break;
}
case RSP_VERIFY_OK:
{
fp_dbg ("Identify was successful! for user: %d mesg_code: %d ", data, verify_status_id);
fp_dbg ("Verify 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);
@@ -747,7 +757,6 @@ identify_status_report (FpiDeviceElanmoc *self, int verify_status_id,
}
enum identify_states {
IDENTIFY_SET_MODE,
IDENTIFY_WAIT_FINGER,
IDENTIFY_NUM_STATES,
};
@@ -783,15 +792,8 @@ elan_identify_run_state (FpiSsm *ssm, FpDevice *dev)
fp_info ("elanmoc %s ", __func__);
switch (fpi_ssm_get_cur_state (ssm))
{
case IDENTIFY_SET_MODE:
fp_info ("elanmoc %s IDENTIFY_SET_MODE", __func__);
cmd_buf = elanmoc_compose_cmd (&elanmoc_set_mod_cmd);
cmd_buf[3] = 0x03;
elanmoc_get_cmd (dev, cmd_buf, elanmoc_set_mod_cmd.cmd_len, elanmoc_set_mod_cmd.resp_len, 0, elanmoc_cmd_ack_cb);
break;
case IDENTIFY_WAIT_FINGER:
fp_info ("elanmoc %s IDENTIFY_WAIT_FINGER", __func__);
fp_info ("elanmoc %s VERIFY_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;
@@ -996,12 +998,6 @@ elanmoc_get_status_cb (FpiDeviceElanmoc *self,
}
if (buffer_in[1] != 0x03 && self->cmd_retry_cnt != 0)
{
self->cmd_retry_cnt--;
cmd_buf = elanmoc_compose_cmd (&cal_status_cmd);
elanmoc_get_cmd (FP_DEVICE (self), cmd_buf, cal_status_cmd.cmd_len, cal_status_cmd.resp_len, 0, elanmoc_get_status_cb);
}
else
{
if(self->cmd_retry_cnt == 0)
{
@@ -1010,6 +1006,12 @@ elanmoc_get_status_cb (FpiDeviceElanmoc *self,
"Sensor not ready"));
return;
}
self->cmd_retry_cnt--;
cmd_buf = elanmoc_compose_cmd (&cal_status_cmd);
elanmoc_get_cmd (FP_DEVICE (self), cmd_buf, cal_status_cmd.cmd_len, cal_status_cmd.resp_len, 0, elanmoc_get_status_cb);
}
else
{
fpi_ssm_next_state (self->task_ssm);
}
}
@@ -1057,7 +1059,6 @@ elanmoc_open (FpDevice *device)
{
FpiDeviceElanmoc *self = FPI_DEVICE_ELANMOC (device);
GError *error = NULL;
gint productid = 0;
if (!g_usb_device_reset (fpi_device_get_usb_device (device), &error))
goto error;
@@ -1065,28 +1066,6 @@ elanmoc_open (FpDevice *device)
if (!g_usb_device_claim_interface (fpi_device_get_usb_device (device), 0, 0, &error))
goto error;
productid = g_usb_device_get_pid (fpi_device_get_usb_device (device));
switch (productid)
{
case 0x0c8c:
self->max_moc_enroll_time = 11;
break;
case 0x0c99:
self->max_moc_enroll_time = 14;
break;
case 0x0c8d:
self->max_moc_enroll_time = 17;
break;
default:
self->max_moc_enroll_time = ELAN_MOC_ENROLL_TIMES;
break;
}
fpi_device_set_nr_enroll_stages (device, self->max_moc_enroll_time);
self->task_ssm = fpi_ssm_new (FP_DEVICE (self), dev_init_handler, DEV_INIT_STATES);
fpi_ssm_start (self->task_ssm, task_ssm_init_done);
return;
@@ -1151,6 +1130,7 @@ 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;
-1
View File
@@ -188,7 +188,6 @@ struct _FpiDeviceElanmoc
unsigned char y_trace;
int num_frames;
int curr_enrolled;
int max_moc_enroll_time;
int cancel_result;
int cmd_retry_cnt;
int list_index;
+3 -4
View File
@@ -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>
@@ -94,7 +94,7 @@ static void
elanspi_do_hwreset (FpiDeviceElanSpi *self, GError **err)
{
/* Skip in emulation mode, since we don't mock hid devices */
if (fpi_device_emulation_mode_enabled (FP_DEVICE (self)))
if (g_strcmp0 (g_getenv ("FP_DEVICE_EMULATION"), "1") == 0)
return;
/*
@@ -485,8 +485,7 @@ elanspi_capture_old_handler (FpiSsm *ssm, FpDevice *dev)
if (!(self->sensor_status & 4))
{
/* has the timeout expired? -- disabled in testing since valgrind is very slow */
if (g_get_monotonic_time () > self->capture_timeout &&
!fpi_device_emulation_mode_enabled (FP_DEVICE (self)))
if (g_get_monotonic_time () > self->capture_timeout && g_strcmp0 (g_getenv ("FP_DEVICE_EMULATION"), "1") != 0)
{
/* end with a timeout */
fpi_ssm_mark_failed (ssm, g_error_new (G_IO_ERROR, G_IO_ERROR_TIMED_OUT, "timed out waiting for new line"));
-3
View File
@@ -340,17 +340,14 @@ static const struct elanspi_regtable elanspi_calibration_table_new_page1 = {
// using checkargs ACPI:HIDPID
static const FpIdEntry elanspi_id_table[] = {
{.udev_types = ELANSPI_UDEV_TYPES, .spi_acpi_id = "ELAN7001", .hid_id = {.vid = ELANSPI_TP_VID, .pid = 0x2766}, .driver_data = ELANSPI_NO_ROTATE},
{.udev_types = ELANSPI_UDEV_TYPES, .spi_acpi_id = "ELAN7001", .hid_id = {.vid = ELANSPI_TP_VID, .pid = 0x3057}, .driver_data = ELANSPI_180_ROTATE},
{.udev_types = ELANSPI_UDEV_TYPES, .spi_acpi_id = "ELAN7001", .hid_id = {.vid = ELANSPI_TP_VID, .pid = 0x3087}, .driver_data = ELANSPI_180_ROTATE},
{.udev_types = ELANSPI_UDEV_TYPES, .spi_acpi_id = "ELAN7001", .hid_id = {.vid = ELANSPI_TP_VID, .pid = 0x30c6}, .driver_data = ELANSPI_180_ROTATE},
{.udev_types = ELANSPI_UDEV_TYPES, .spi_acpi_id = "ELAN7001", .hid_id = {.vid = ELANSPI_TP_VID, .pid = 0x3128}, .driver_data = ELANSPI_90LEFT_ROTATE},
{.udev_types = ELANSPI_UDEV_TYPES, .spi_acpi_id = "ELAN70A1", .hid_id = {.vid = ELANSPI_TP_VID, .pid = 0x3134}, .driver_data = ELANSPI_90LEFT_ROTATE},
{.udev_types = ELANSPI_UDEV_TYPES, .spi_acpi_id = "ELAN7001", .hid_id = {.vid = ELANSPI_TP_VID, .pid = 0x3148}, .driver_data = ELANSPI_180_ROTATE},
{.udev_types = ELANSPI_UDEV_TYPES, .spi_acpi_id = "ELAN7001", .hid_id = {.vid = ELANSPI_TP_VID, .pid = 0x30b2}, .driver_data = ELANSPI_NO_ROTATE},
{.udev_types = ELANSPI_UDEV_TYPES, .spi_acpi_id = "ELAN70A1", .hid_id = {.vid = ELANSPI_TP_VID, .pid = 0x30b2}, .driver_data = ELANSPI_NO_ROTATE},
{.udev_types = ELANSPI_UDEV_TYPES, .spi_acpi_id = "ELAN7001", .hid_id = {.vid = ELANSPI_TP_VID, .pid = 0x309f}, .driver_data = ELANSPI_180_ROTATE},
{.udev_types = ELANSPI_UDEV_TYPES, .spi_acpi_id = "ELAN7001", .hid_id = {.vid = ELANSPI_TP_VID, .pid = 0x241f}, .driver_data = ELANSPI_NO_ROTATE},
{.udev_types = 0}
};
-19
View File
@@ -338,14 +338,7 @@ 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;
@@ -582,24 +575,12 @@ 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);
}
File diff suppressed because it is too large Load Diff
@@ -1,52 +0,0 @@
/*
* Copyright (C) 2021 Focaltech Microelectronics
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#pragma once
#include "fpi-device.h"
#include "fpi-ssm.h"
#include <libusb.h>
#include <stdio.h>
#include <stdlib.h>
G_DECLARE_FINAL_TYPE (FpiDeviceFocaltechMoc, fpi_device_focaltech_moc, FPI, DEVICE_FOCALTECH_MOC, FpDevice)
#define FOCALTECH_MOC_DRIVER_FULLNAME "Focaltech MOC Sensors"
#define FOCALTECH_MOC_CMD_TIMEOUT 1000
#define FOCALTECH_MOC_MAX_FINGERS 10
#define FOCALTECH_MOC_UID_PREFIX_LENGTH 8
#define FOCALTECH_MOC_USER_ID_LENGTH 64
typedef void (*FocaltechCmdMsgCallback) (FpiDeviceFocaltechMoc *self,
GError *error);
struct _FpiDeviceFocaltechMoc
{
FpDevice parent;
FpiSsm *task_ssm;
FpiSsm *cmd_ssm;
FpiUsbTransfer *cmd_transfer;
gboolean cmd_cancelable;
gsize cmd_len_in;
int num_frames;
int delete_slot;
guint8 bulk_in_ep;
guint8 bulk_out_ep;
};
File diff suppressed because it is too large Load Diff
-221
View File
@@ -1,221 +0,0 @@
/*
* Copyright (c) 2022 Fingerprint Cards AB <tech@fingerprints.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#pragma once
#include "fpi-device.h"
#include "fpi-ssm.h"
#include <stdio.h>
#include <stdlib.h>
#define TEMPLATE_ID_SIZE (32)
#define MAX_FW_VERSION_STR_LEN (16)
#define FPC_CMD_INIT (0x01)
#define FPC_CMD_ARM (0x02)
#define FPC_CMD_ABORT (0x03)
#define FPC_CMD_INDICATE_S_STATE (0x08)
#define FPC_CMD_GET_IMG (0x09)
#define FPC_CMD_GET_KPI (0x0C)
#define FPC_CMD_LOAD_DB (0x60)
#define FPC_CMD_STORE_DB (0x61)
#define FPC_CMD_DELETE_DB (0x62)
#define FPC_CMD_DELETE_TEMPLATE (0x63)
#define FPC_CMD_BEGIN_ENROL (0x67)
#define FPC_CMD_ENROL (0x68)
#define FPC_CMD_END_ENROL (0x69)
#define FPC_CMD_BIND_IDENTITY (0x6A)
#define FPC_CMD_IDENTIFY (0x6B)
#define FPC_CMD_ENUM (0x70)
#define FPC_EVT_INIT_RESULT (0x02)
#define FPC_EVT_FINGER_DWN (0x06)
#define FPC_EVT_IMG (0x08)
#define FPC_EVT_FID_DATA (0x31)
#define FPC_DB_ID_LEN (16)
#define FPC_IDENTITY_TYPE_WILDCARD (0x1)
#define FPC_IDENTITY_TYPE_RESERVED (0x3)
#define FPC_IDENTITY_WILDCARD (0x25066282)
#define FPC_SUBTYPE_ANY (0xFF)
#define FPC_SUBTYPE_RESERVED (0xF5)
#define FPC_SUBTYPE_NOINFORMATION (0x00)
#define FPC_CAPTUREID_RESERVED (0x701100F)
#define FPC_SESSIONID_RESERVED (0x0077FF12)
#define FPC_TEMPLATES_MAX (10)
#define SECURITY_MAX_SID_SIZE (68)
#define FPC_HOST_MS_S0 (0x10)
#define FPC_HOST_MS_SX (0x11)
G_DECLARE_FINAL_TYPE (FpiDeviceFpcMoc, fpi_device_fpcmoc, FPI,
DEVICE_FPCMOC, FpDevice);
typedef struct _FPC_FID_DATA
{
guint32 identity_type;
guint32 reserved;
guint32 identity_size;
guint32 subfactor;
guint8 data[SECURITY_MAX_SID_SIZE];
} FPC_FID_DATA, *PFPC_FID_DATA;
typedef struct _FPC_LOAD_DB
{
gint32 status;
guint32 reserved;
guint32 database_id_size;
guint8 data[FPC_DB_ID_LEN];
} FPC_LOAD_DB, *PFPC_LOAD_DB;
typedef union _FPC_DELETE_DB
{
guint32 reserved;
guint32 database_id_size;
guint8 data[FPC_DB_ID_LEN];
} FPC_DB_OP, *PFPC_DB_OP;
typedef struct _FPC_BEGIN_ENROL
{
gint32 status;
guint32 reserved1;
guint32 reserved2;
} FPC_BEGIN_ENROL, *PFPC_BEGIN_ENROL;
typedef struct _FPC_ENROL
{
gint32 status;
guint32 remaining;
} FPC_ENROL, *PFPC_ENROL;
typedef struct _FPC_END_ENROL
{
gint32 status;
guint32 fid;
} FPC_END_ENROL, *PFPC_END_ENROL;
typedef struct _FPC_IDENTIFY
{
gint32 status;
guint32 identity_type;
guint32 identity_offset;
guint32 identity_size;
guint32 subfactor;
guint8 data[SECURITY_MAX_SID_SIZE];
} FPC_IDENTIFY, *PFPC_IDENTIFY;
typedef struct
{
guint32 cmdid;
guint32 length;
guint32 status;
} evt_hdr_t;
typedef struct
{
evt_hdr_t hdr;
guint16 sensor;
guint16 hw_id;
guint16 img_w;
guint16 img_h;
guint8 fw_version[MAX_FW_VERSION_STR_LEN];
guint16 fw_capabilities;
} evt_initiated_t;
typedef struct
{
guint8 subfactor;
guint32 identity_type;
guint32 identity_size;
guint8 identity[SECURITY_MAX_SID_SIZE];
} __attribute__((packed)) fpc_fid_data_t;
typedef struct
{
evt_hdr_t hdr;
gint status;
guint32 num_ids;
fpc_fid_data_t fid_data[FPC_TEMPLATES_MAX];
} __attribute__((packed)) evt_enum_fids_t;
typedef struct _fp_cmd_response
{
union
{
evt_hdr_t evt_hdr;
evt_initiated_t evt_inited;
evt_enum_fids_t evt_enum_fids;
};
} fpc_cmd_response_t, *pfpc_cmd_response_t;
enum {
FPC_ENROL_STATUS_COMPLETED = 0,
FPC_ENROL_STATUS_PROGRESS = 1,
FPC_ENROL_STATUS_FAILED_COULD_NOT_COMPLETE = 2,
FPC_ENROL_STATUS_FAILED_ALREADY_ENROLED = 3,
FPC_ENROL_STATUS_IMAGE_LOW_COVERAGE = 4,
FPC_ENROL_STATUS_IMAGE_TOO_SIMILAR = 5,
FPC_ENROL_STATUS_IMAGE_LOW_QUALITY = 6,
};
typedef enum {
FPC_CMDTYPE_UNKNOWN = 0,
FPC_CMDTYPE_TO_DEVICE,
FPC_CMDTYPE_TO_DEVICE_EVTDATA,
FPC_CMDTYPE_FROM_DEVICE,
} FpcCmdType;
typedef enum {
FPC_CMD_SEND = 0,
FPC_CMD_GET_DATA,
FPC_CMD_SUSPENDED,
FPC_CMD_RESUME,
FPC_CMD_NUM_STATES,
} FpcCmdState;
typedef enum {
FPC_INIT = 0,
FPC_INIT_LOAD_DB,
FPC_INIT_NUM_STATES,
} FpcInitState;
typedef enum {
FPC_ENROLL_ENUM = 0,
FPC_ENROLL_CREATE,
FPC_ENROLL_CAPTURE,
FPC_ENROLL_GET_IMG,
FPC_ENROLL_UPDATE,
FPC_ENROLL_COMPLETE,
FPC_ENROLL_CHECK_DUPLICATE,
FPC_ENROLL_BINDID,
FPC_ENROLL_COMMIT,
FPC_ENROLL_DICARD,
FPC_ENROLL_CLEANUP,
FPC_ENROLL_NUM_STATES,
} FpcEnrollState;
typedef enum {
FPC_IDENTIFY_CAPTURE = 0,
FPC_IDENTIFY_GET_IMG,
FPC_IDENTIFY_IDENTIFY,
FPC_IDENTIFY_CANCEL,
FPC_IDENTIFY_NUM_STATES,
} FpcVerifyState;
typedef enum {
FPC_CLEAR_DELETE_DB = 0,
FPC_CLEAR_CREATE_DB,
FPC_CLEAR_NUM_STATES,
} FpClearState;
+114 -258
View File
@@ -19,7 +19,6 @@
#include "glib.h"
#define FP_COMPONENT "goodixmoc"
#include "drivers_api.h"
@@ -129,13 +128,11 @@ fp_cmd_receive_cb (FpiUsbTransfer *transfer,
GError *error)
{
FpiDeviceGoodixMoc *self = FPI_DEVICE_GOODIXMOC (device);
FpiByteReader reader = {0};
CommandData *data = user_data;
int ssm_state = 0;
int ret = -1, ssm_state = 0;
gxfp_cmd_response_t cmd_reponse = {0, };
pack_header header;
guint32 crc32_calc = 0;
guint32 crc32 = 0;
guint16 cmd = 0;
if (error)
@@ -157,9 +154,8 @@ fp_cmd_receive_cb (FpiUsbTransfer *transfer,
return;
}
fpi_byte_reader_init (&reader, transfer->buffer, transfer->actual_length);
if (gx_proto_parse_header (&reader, &header) != 0)
ret = gx_proto_parse_header (transfer->buffer, transfer->actual_length, &header);
if (ret != 0)
{
fpi_ssm_mark_failed (transfer->ssm,
fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
@@ -167,25 +163,8 @@ fp_cmd_receive_cb (FpiUsbTransfer *transfer,
return;
}
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;
}
/* 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) ||
GUINT32_FROM_LE (crc32_calc) != crc32)
gx_proto_crc32_calc (transfer->buffer, PACKAGE_HEADER_SIZE + header.len, (uint8_t *) &crc32_calc);
if(crc32_calc != GUINT32_FROM_LE (*(uint32_t *) (transfer->buffer + PACKAGE_HEADER_SIZE + header.len)))
{
fpi_ssm_mark_failed (transfer->ssm,
fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
@@ -195,9 +174,8 @@ fp_cmd_receive_cb (FpiUsbTransfer *transfer,
cmd = MAKE_CMD_EX (header.cmd0, header.cmd1);
fpi_byte_reader_init (&reader, &transfer->buffer[PACKAGE_HEADER_SIZE], header.len);
if (gx_proto_parse_body (cmd, &reader, &cmd_reponse) != 0)
ret = gx_proto_parse_body (cmd, &transfer->buffer[PACKAGE_HEADER_SIZE], header.len, &cmd_reponse);
if (ret != 0)
{
fpi_ssm_mark_failed (transfer->ssm,
fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
@@ -244,7 +222,7 @@ fp_cmd_run_state (FpiSsm *ssm,
switch (fpi_ssm_get_cur_state (ssm))
{
case GOODIX_CMD_SEND:
case FP_CMD_SEND:
if (self->cmd_transfer)
{
self->cmd_transfer->ssm = ssm;
@@ -260,7 +238,7 @@ fp_cmd_run_state (FpiSsm *ssm,
}
break;
case GOODIX_CMD_GET_ACK:
case FP_CMD_GET_ACK:
transfer = fpi_usb_transfer_new (dev);
transfer->ssm = ssm;
fpi_usb_transfer_fill_bulk (transfer, EP_IN, EP_IN_MAX_BUF_SIZE);
@@ -272,7 +250,7 @@ fp_cmd_run_state (FpiSsm *ssm,
break;
case GOODIX_CMD_GET_DATA:
case FP_CMD_GET_DATA:
transfer = fpi_usb_transfer_new (dev);
transfer->ssm = ssm;
fpi_usb_transfer_fill_bulk (transfer, EP_IN, EP_IN_MAX_BUF_SIZE);
@@ -360,7 +338,7 @@ goodix_sensor_cmd (FpiDeviceGoodixMoc *self,
self->cmd_ssm = fpi_ssm_new (FP_DEVICE (self),
fp_cmd_run_state,
GOODIX_CMD_NUM_STATES);
FP_CMD_NUM_STATES);
fpi_ssm_set_data (self->cmd_ssm, data, (GDestroyNotify) fp_cmd_ssm_done_data_free);
@@ -399,13 +377,13 @@ fp_pwr_btn_shield_cb (FpiDeviceGoodixMoc *self,
}
/******************************************************************************
*
* fp_identify_xxxx Function
* fp_verify_xxxx Function
*
*****************************************************************************/
static void
fp_identify_capture_cb (FpiDeviceGoodixMoc *self,
gxfp_cmd_response_t *resp,
GError *error)
fp_verify_capture_cb (FpiDeviceGoodixMoc *self,
gxfp_cmd_response_t *resp,
GError *error)
{
if (error)
{
@@ -438,9 +416,9 @@ fp_identify_capture_cb (FpiDeviceGoodixMoc *self,
}
static void
fp_identify_cb (FpiDeviceGoodixMoc *self,
gxfp_cmd_response_t *resp,
GError *error)
fp_verify_cb (FpiDeviceGoodixMoc *self,
gxfp_cmd_response_t *resp,
GError *error)
{
FpDevice *device = FP_DEVICE (self);
FpPrint *new_scan = NULL;
@@ -451,57 +429,43 @@ fp_identify_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 (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_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;
}
}
}
}
fpi_device_identify_report (device, matching, new_scan, error);
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_ssm_next_state (self->task_ssm);
}
static void
fp_identify_finger_mode_cb (FpiDeviceGoodixMoc *self,
gxfp_cmd_response_t *resp,
GError *error)
{
if (error)
{
fpi_ssm_mark_failed (self->task_ssm, error);
return;
}
/* 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_IDENTIFY_WAIT_FINGER_UP);
return;
}
else if (resp->finger_status.status != GX_SUCCESS)
{
fpi_ssm_mark_failed (self->task_ssm,
fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
"Switch finger mode failed"));
return;
}
fpi_device_report_finger_status_changes (FP_DEVICE (self),
FP_FINGER_STATUS_NONE,
FP_FINGER_STATUS_PRESENT);
fpi_ssm_next_state (self->task_ssm);
}
static void
fp_identify_sm_run_state (FpiSsm *ssm, FpDevice *device)
fp_verify_sm_run_state (FpiSsm *ssm, FpDevice *device)
{
FpiDeviceGoodixMoc *self = FPI_DEVICE_GOODIXMOC (device);
guint8 param[3] = { 0 };
@@ -513,7 +477,7 @@ fp_identify_sm_run_state (FpiSsm *ssm, FpDevice *device)
switch (fpi_ssm_get_cur_state (ssm))
{
case GOODIX_IDENTIFY_PWR_BTN_SHIELD_ON:
case FP_VERIFY_PWR_BTN_SHIELD_ON:
goodix_sensor_cmd (self, MOC_CMD0_PWR_BTN_SHIELD, MOC_CMD1_PWR_BTN_SHIELD_ON,
false,
NULL,
@@ -521,7 +485,7 @@ fp_identify_sm_run_state (FpiSsm *ssm, FpDevice *device)
fp_pwr_btn_shield_cb);
break;
case GOODIX_IDENTIFY_CAPTURE:
case FP_VERIFY_CAPTURE:
fpi_device_report_finger_status_changes (device,
FP_FINGER_STATUS_NEEDED,
FP_FINGER_STATUS_NONE);
@@ -529,29 +493,18 @@ fp_identify_sm_run_state (FpiSsm *ssm, FpDevice *device)
true,
(const guint8 *) &param,
G_N_ELEMENTS (param),
fp_identify_capture_cb);
fp_verify_capture_cb);
break;
case GOODIX_IDENTIFY_IDENTIFY:
case FP_VERIFY_IDENTIFY:
goodix_sensor_cmd (self, MOC_CMD0_IDENTIFY, MOC_CMD1_DEFAULT,
false,
(const guint8 *) nonce,
TEMPLATE_ID_SIZE,
fp_identify_cb);
fp_verify_cb);
break;
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_identify_finger_mode_cb);
}
break;
case GOODIX_IDENTIFY_PWR_BTN_SHIELD_OFF:
case FP_VERIFY_PWR_BTN_SHIELD_OFF:
goodix_sensor_cmd (self, MOC_CMD0_PWR_BTN_SHIELD, MOC_CMD1_PWR_BTN_SHIELD_OFF,
false,
NULL,
@@ -563,16 +516,25 @@ fp_identify_sm_run_state (FpiSsm *ssm, FpDevice *device)
}
static void
fp_identify_ssm_done (FpiSsm *ssm, FpDevice *dev, GError *error)
fp_verify_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)
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_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_complete (dev, 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);
self->task_ssm = NULL;
}
@@ -669,20 +631,20 @@ fp_enroll_enum_cb (FpiDeviceGoodixMoc *self,
return;
}
fpi_ssm_next_state (self->task_ssm);
fpi_ssm_jump_to_state (self->task_ssm, FP_ENROLL_CAPTURE);
}
static void
fp_enroll_create_cb (FpiDeviceGoodixMoc *self,
gxfp_cmd_response_t *resp,
GError *error)
fp_enroll_init_cb (FpiDeviceGoodixMoc *self,
gxfp_cmd_response_t *resp,
GError *error)
{
if (error)
{
fpi_ssm_mark_failed (self->task_ssm, error);
return;
}
memcpy (self->template_id, resp->enroll_create.tid, TEMPLATE_ID_SIZE);
memcpy (self->template_id, resp->enroll_init.tid, TEMPLATE_ID_SIZE);
fpi_ssm_next_state (self->task_ssm);
}
@@ -699,12 +661,12 @@ fp_enroll_capture_cb (FpiDeviceGoodixMoc *self,
/* */
if (resp->result >= GX_FAILED)
{
fp_info ("Capture sample failed, result: 0x%x", resp->result);
fp_warn ("Capture sample failed, result: 0x%x", resp->result);
fpi_device_enroll_progress (FP_DEVICE (self),
self->enroll_stage,
NULL,
fpi_device_retry_new (FP_DEVICE_RETRY_GENERAL));
fpi_ssm_jump_to_state (self->task_ssm, GOODIX_ENROLL_CAPTURE);
fpi_ssm_jump_to_state (self->task_ssm, FP_ENROLL_CAPTURE);
return;
}
fpi_device_report_finger_status_changes (FP_DEVICE (self),
@@ -713,7 +675,7 @@ fp_enroll_capture_cb (FpiDeviceGoodixMoc *self,
if ((resp->capture_data_resp.img_quality < self->sensorcfg->config[4]) ||
(resp->capture_data_resp.img_coverage < self->sensorcfg->config[5]))
{
fp_info ("Capture sample poor quality(%d): %d or coverage(%d): %d",
fp_warn ("Capture sample poor quality(%d): %d or coverage(%d): %d",
self->sensorcfg->config[4],
resp->capture_data_resp.img_quality,
self->sensorcfg->config[5],
@@ -722,7 +684,7 @@ fp_enroll_capture_cb (FpiDeviceGoodixMoc *self,
self->enroll_stage,
NULL,
fpi_device_retry_new (FP_DEVICE_RETRY_CENTER_FINGER));
fpi_ssm_jump_to_state (self->task_ssm, GOODIX_ENROLL_CAPTURE);
fpi_ssm_jump_to_state (self->task_ssm, FP_ENROLL_CAPTURE);
return;
}
else
@@ -753,7 +715,7 @@ fp_enroll_update_cb (FpiDeviceGoodixMoc *self,
NULL,
fpi_device_retry_new (FP_DEVICE_RETRY_REMOVE_FINGER));
}
else if (resp->enroll_update.rollback || resp->result == 0x73)
else if (resp->enroll_update.rollback)
{
fpi_device_enroll_progress (FP_DEVICE (self),
self->enroll_stage,
@@ -768,7 +730,7 @@ fp_enroll_update_cb (FpiDeviceGoodixMoc *self,
/* if enroll complete, no need to wait finger up */
if (self->enroll_stage >= self->max_enroll_stage)
{
fpi_ssm_jump_to_state (self->task_ssm, GOODIX_ENROLL_CHECK_DUPLICATE);
fpi_ssm_jump_to_state (self->task_ssm, FP_ENROLL_CHECK_DUPLICATE);
return;
}
@@ -834,7 +796,7 @@ fp_finger_mode_cb (FpiDeviceGoodixMoc *self,
/* if reach max timeout(5sec) finger not up, switch to finger up again */
if (resp->finger_status.status == GX_ERROR_WAIT_FINGER_UP_TIMEOUT)
{
fpi_ssm_jump_to_state (self->task_ssm, GOODIX_ENROLL_WAIT_FINGER_UP);
fpi_ssm_jump_to_state (self->task_ssm, FP_ENROLL_WAIT_FINGER_UP);
return;
}
else if (resp->finger_status.status != GX_SUCCESS)
@@ -849,7 +811,7 @@ fp_finger_mode_cb (FpiDeviceGoodixMoc *self,
FP_FINGER_STATUS_PRESENT);
if (self->enroll_stage < self->max_enroll_stage)
{
fpi_ssm_jump_to_state (self->task_ssm, GOODIX_ENROLL_CAPTURE);
fpi_ssm_jump_to_state (self->task_ssm, FP_ENROLL_CAPTURE);
return;
}
fpi_ssm_next_state (self->task_ssm);
@@ -875,17 +837,7 @@ fp_enroll_sm_run_state (FpiSsm *ssm, FpDevice *device)
switch (fpi_ssm_get_cur_state (ssm))
{
case GOODIX_ENROLL_PWR_BTN_SHIELD_ON:
{
goodix_sensor_cmd (self, MOC_CMD0_PWR_BTN_SHIELD, MOC_CMD1_PWR_BTN_SHIELD_ON,
false,
NULL,
0,
fp_pwr_btn_shield_cb);
}
break;
case GOODIX_ENROLL_ENUM:
case FP_ENROLL_ENUM:
{
goodix_sensor_cmd (self, MOC_CMD0_GETFINGERLIST, MOC_CMD1_DEFAULT,
false,
@@ -895,17 +847,27 @@ fp_enroll_sm_run_state (FpiSsm *ssm, FpDevice *device)
}
break;
case GOODIX_ENROLL_CREATE:
case FP_ENROLL_PWR_BTN_SHIELD_ON:
{
goodix_sensor_cmd (self, MOC_CMD0_PWR_BTN_SHIELD, MOC_CMD1_PWR_BTN_SHIELD_ON,
false,
NULL,
0,
fp_pwr_btn_shield_cb);
}
break;
case FP_ENROLL_CREATE:
{
goodix_sensor_cmd (self, MOC_CMD0_ENROLL_INIT, MOC_CMD1_DEFAULT,
false,
(const guint8 *) &dummy,
1,
fp_enroll_create_cb);
fp_enroll_init_cb);
}
break;
case GOODIX_ENROLL_CAPTURE:
case FP_ENROLL_CAPTURE:
fpi_device_report_finger_status_changes (device,
FP_FINGER_STATUS_NEEDED,
FP_FINGER_STATUS_NONE);
@@ -916,7 +878,7 @@ fp_enroll_sm_run_state (FpiSsm *ssm, FpDevice *device)
fp_enroll_capture_cb);
break;
case GOODIX_ENROLL_UPDATE:
case FP_ENROLL_UPDATE:
dummy[0] = 1;
dummy[1] = self->sensorcfg->config[2];
dummy[2] = self->sensorcfg->config[3];
@@ -927,7 +889,7 @@ fp_enroll_sm_run_state (FpiSsm *ssm, FpDevice *device)
fp_enroll_update_cb);
break;
case GOODIX_ENROLL_WAIT_FINGER_UP:
case FP_ENROLL_WAIT_FINGER_UP:
dummy[0] = 0;
goodix_sensor_cmd (self, MOC_CMD0_FINGER_MODE, MOC_CMD1_SET_FINGER_UP,
true,
@@ -936,7 +898,7 @@ fp_enroll_sm_run_state (FpiSsm *ssm, FpDevice *device)
fp_finger_mode_cb);
break;
case GOODIX_ENROLL_CHECK_DUPLICATE:
case FP_ENROLL_CHECK_DUPLICATE:
goodix_sensor_cmd (self, MOC_CMD0_CHECK4DUPLICATE, MOC_CMD1_DEFAULT,
false,
(const guint8 *) &dummy,
@@ -944,7 +906,7 @@ fp_enroll_sm_run_state (FpiSsm *ssm, FpDevice *device)
fp_enroll_check_duplicate_cb);
break;
case GOODIX_ENROLL_COMMIT:
case FP_ENROLL_COMMIT:
{
fpi_device_get_enroll_data (device, &print);
user_id = fpi_print_generate_user_id (print);
@@ -952,7 +914,7 @@ fp_enroll_sm_run_state (FpiSsm *ssm, FpDevice *device)
user_id_len = MIN (100, user_id_len);
finger = 1;
if (fpi_device_emulation_mode_enabled (FP_DEVICE (self)))
if (g_strcmp0 (g_getenv ("FP_DEVICE_EMULATION"), "1") == 0)
memset (self->template_id, 0, TEMPLATE_ID_SIZE);
uid = g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE,
user_id,
@@ -997,7 +959,7 @@ fp_enroll_sm_run_state (FpiSsm *ssm, FpDevice *device)
}
break;
case GOODIX_ENROLL_PWR_BTN_SHIELD_OFF:
case FP_ENROLL_PWR_BTN_SHIELD_OFF:
{
goodix_sensor_cmd (self, MOC_CMD0_PWR_BTN_SHIELD, MOC_CMD1_PWR_BTN_SHIELD_OFF,
false,
@@ -1079,47 +1041,6 @@ fp_init_config_cb (FpiDeviceGoodixMoc *self,
fpi_ssm_next_state (self->task_ssm);
}
static void
fp_init_cb_reset_or_complete (FpiDeviceGoodixMoc *self,
gxfp_cmd_response_t *resp,
GError *error)
{
if (error)
{
fp_warn ("Template storage appears to have been corrupted! Error was: %s", error->message);
fp_warn ("A known reason for this to happen is a firmware bug triggered by another storage area being initialized.");
fpi_ssm_jump_to_state (self->task_ssm, GOODIX_INIT_RESET_DEVICE);
}
else
{
fpi_ssm_mark_completed (self->task_ssm);
}
}
static void
fp_init_reset_device_cb (FpiDeviceGoodixMoc *self,
gxfp_cmd_response_t *resp,
GError *error)
{
if (error)
{
fp_warn ("Reset failed: %s", error->message);
fpi_ssm_mark_failed (self->task_ssm, error);
return;
}
if ((resp->result >= GX_FAILED) && (resp->result != GX_ERROR_FINGER_ID_NOEXIST))
{
fp_warn ("Reset failed, device reported: 0x%x", resp->result);
fpi_ssm_mark_failed (self->task_ssm,
fpi_device_error_new_msg (FP_DEVICE_ERROR_GENERAL,
"Failed clear storage, result: 0x%x",
resp->result));
return;
}
fp_warn ("Reset completed");
fpi_ssm_mark_completed (self->task_ssm);
}
static void
fp_init_sm_run_state (FpiSsm *ssm, FpDevice *device)
@@ -1129,7 +1050,7 @@ fp_init_sm_run_state (FpiSsm *ssm, FpDevice *device)
switch (fpi_ssm_get_cur_state (ssm))
{
case GOODIX_INIT_VERSION:
case FP_INIT_VERSION:
goodix_sensor_cmd (self, MOC_CMD0_GET_VERSION, MOC_CMD1_DEFAULT,
false,
&dummy,
@@ -1137,37 +1058,13 @@ fp_init_sm_run_state (FpiSsm *ssm, FpDevice *device)
fp_init_version_cb);
break;
case GOODIX_INIT_CONFIG:
case FP_INIT_CONFIG:
goodix_sensor_cmd (self, MOC_CMD0_UPDATE_CONFIG, MOC_CMD1_WRITE_CFG_TO_FLASH,
false,
(guint8 *) self->sensorcfg,
sizeof (gxfp_sensor_cfg_t),
fp_init_config_cb);
break;
case GOODIX_INIT_TEMPLATE_LIST:
/* List prints to check whether the template DB was corrupted.
* As of 2022-06-13 there is a known firmware issue that can cause the
* stored templates for Linux to be corrupted when the Windows storage
* area is initialized.
* In that case, we'll get a protocol failure trying to retrieve the
* list of prints.
*/
goodix_sensor_cmd (self, MOC_CMD0_GETFINGERLIST, MOC_CMD1_DEFAULT,
FALSE,
(const guint8 *) &dummy,
1,
fp_init_cb_reset_or_complete);
break;
case GOODIX_INIT_RESET_DEVICE:
fp_warn ("Resetting device storage, you will need to enroll all prints again!");
goodix_sensor_cmd (self, MOC_CMD0_DELETETEMPLATE, MOC_CMD1_DELETE_ALL,
FALSE,
NULL,
0,
fp_init_reset_device_cb);
break;
}
@@ -1372,7 +1269,7 @@ gx_fp_probe (FpDevice *device)
if (!g_usb_device_claim_interface (usb_dev, 0, 0, &error))
goto err_close;
if (fpi_device_emulation_mode_enabled (FP_DEVICE (self)))
if (g_strcmp0 (g_getenv ("FP_DEVICE_EMULATION"), "1") == 0)
{
serial = g_strdup ("emulated-device");
@@ -1397,32 +1294,12 @@ gx_fp_probe (FpDevice *device)
{
case 0x6496:
case 0x60A2:
case 0x60A4:
case 0x6014:
case 0x6090:
case 0x6092:
case 0x6094:
case 0x609A:
case 0x609C:
case 0x60BC:
case 0x60C2:
case 0x6304:
case 0x631C:
case 0x633C:
case 0x634C:
case 0x6382:
case 0x6384:
case 0x639C:
case 0x63AC:
case 0x63BC:
case 0x63CC:
case 0x650A:
case 0x650C:
case 0x6582:
case 0x6A94:
case 0x659A:
case 0x6890:
case 0x6984:
self->max_enroll_stage = 12;
break;
@@ -1478,7 +1355,7 @@ gx_fp_init (FpDevice *device)
}
self->task_ssm = fpi_ssm_new (device, fp_init_sm_run_state,
GOODIX_INIT_NUM_STATES);
FP_INIT_NUM_STATES);
fpi_ssm_start (self->task_ssm, fp_init_ssm_done);
@@ -1509,7 +1386,9 @@ gx_fp_exit_cb (FpiDeviceGoodixMoc *self,
gxfp_cmd_response_t *resp,
GError *error)
{
if (resp && resp->result >= GX_FAILED)
if (resp->result >= GX_FAILED)
fp_dbg ("Setting power button shield failed, result: 0x%x", resp->result);
self->is_power_button_shield_on = false;
gx_fp_release_interface (self, error);
@@ -1539,16 +1418,16 @@ gx_fp_exit (FpDevice *device)
static void
gx_fp_identify (FpDevice *device)
gx_fp_verify_identify (FpDevice *device)
{
FpiDeviceGoodixMoc *self = FPI_DEVICE_GOODIXMOC (device);
self->task_ssm = fpi_ssm_new_full (device, fp_identify_sm_run_state,
GOODIX_IDENTIFY_NUM_STATES,
GOODIX_IDENTIFY_PWR_BTN_SHIELD_OFF,
"identify");
self->task_ssm = fpi_ssm_new_full (device, fp_verify_sm_run_state,
FP_VERIFY_NUM_STATES,
FP_VERIFY_PWR_BTN_SHIELD_OFF,
"verify");
fpi_ssm_start (self->task_ssm, fp_identify_ssm_done);
fpi_ssm_start (self->task_ssm, fp_verify_ssm_done);
}
@@ -1561,8 +1440,8 @@ gx_fp_enroll (FpDevice *device)
self->enroll_stage = 0;
self->task_ssm = fpi_ssm_new_full (device, fp_enroll_sm_run_state,
GOODIX_ENROLL_NUM_STATES,
GOODIX_ENROLL_PWR_BTN_SHIELD_OFF,
FP_ENROLL_NUM_STATES,
FP_ENROLL_PWR_BTN_SHIELD_OFF,
"enroll");
fpi_ssm_start (self->task_ssm, fp_enroll_ssm_done);
@@ -1601,7 +1480,7 @@ gx_fp_template_delete (FpDevice *device)
gsize user_id_len = 0;
const guint8 *tid;
gsize tid_len = 0;
guint16 payload_len = 0;
gsize payload_len = 0;
g_autofree guint8 *payload = NULL;
fpi_device_get_delete_data (device, &print);
@@ -1614,8 +1493,7 @@ 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, &payload_len))
if (!encode_finger_id (tid, tid_len, user_id, user_id_len, &payload, (guint16 *) &payload_len))
{
fpi_device_delete_complete (device,
fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
@@ -1652,42 +1530,19 @@ fpi_device_goodixmoc_init (FpiDeviceGoodixMoc *self)
static const FpIdEntry id_table[] = {
{ .vid = 0x27c6, .pid = 0x5840, },
{ .vid = 0x27c6, .pid = 0x6014, },
{ .vid = 0x27c6, .pid = 0x6090, },
{ .vid = 0x27c6, .pid = 0x6092, },
{ .vid = 0x27c6, .pid = 0x6094, },
{ .vid = 0x27c6, .pid = 0x609A, },
{ .vid = 0x27c6, .pid = 0x609C, },
{ .vid = 0x27c6, .pid = 0x60A2, },
{ .vid = 0x27c6, .pid = 0x60A4, },
{ .vid = 0x27c6, .pid = 0x60BC, },
{ .vid = 0x27c6, .pid = 0x60C2, },
{ .vid = 0x27c6, .pid = 0x6304, },
{ .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, },
{ .vid = 0x27c6, .pid = 0x63BC, },
{ .vid = 0x27c6, .pid = 0x63CC, },
{ .vid = 0x27c6, .pid = 0x6496, },
{ .vid = 0x27c6, .pid = 0x650A, },
{ .vid = 0x27c6, .pid = 0x650C, },
{ .vid = 0x27c6, .pid = 0x6582, },
{ .vid = 0x27c6, .pid = 0x6584, },
{ .vid = 0x27c6, .pid = 0x658C, },
{ .vid = 0x27c6, .pid = 0x6592, },
{ .vid = 0x27c6, .pid = 0x6594, },
{ .vid = 0x27c6, .pid = 0x659A, },
{ .vid = 0x27c6, .pid = 0x659C, },
{ .vid = 0x27c6, .pid = 0x6A94, },
{ .vid = 0x27c6, .pid = 0x6512, },
{ .vid = 0x27c6, .pid = 0x6890, },
{ .vid = 0x27c6, .pid = 0x689A, },
{ .vid = 0x27c6, .pid = 0x66A9, },
{ .vid = 0x27c6, .pid = 0x6984, },
{ .vid = 0, .pid = 0, .driver_data = 0 }, /* terminating entry */
};
@@ -1712,7 +1567,8 @@ 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->identify = gx_fp_identify;
dev_class->verify = gx_fp_verify_identify;
dev_class->identify = gx_fp_verify_identify;
fpi_device_class_auto_initialize_features (dev_class);
dev_class->features |= FP_DEVICE_FEATURE_DUPLICATES_CHECK;
+27 -29
View File
@@ -25,40 +25,38 @@
G_DECLARE_FINAL_TYPE (FpiDeviceGoodixMoc, fpi_device_goodixmoc, FPI, DEVICE_GOODIXMOC, FpDevice)
typedef enum {
GOODIX_CMD_SEND = 0,
GOODIX_CMD_GET_ACK,
GOODIX_CMD_GET_DATA,
GOODIX_CMD_NUM_STATES,
} GoodixCmdState;
FP_CMD_SEND = 0,
FP_CMD_GET_ACK,
FP_CMD_GET_DATA,
FP_CMD_NUM_STATES,
} FpCmdState;
typedef enum {
GOODIX_INIT_VERSION = 0,
GOODIX_INIT_CONFIG,
GOODIX_INIT_TEMPLATE_LIST,
GOODIX_INIT_RESET_DEVICE,
GOODIX_INIT_NUM_STATES,
} GoodixInitState;
FP_INIT_VERSION = 0,
FP_INIT_CONFIG,
FP_INIT_NUM_STATES,
} FpInitState;
typedef enum {
GOODIX_ENROLL_PWR_BTN_SHIELD_ON = 0,
GOODIX_ENROLL_ENUM,
GOODIX_ENROLL_CREATE,
GOODIX_ENROLL_CAPTURE,
GOODIX_ENROLL_UPDATE,
GOODIX_ENROLL_WAIT_FINGER_UP,
GOODIX_ENROLL_CHECK_DUPLICATE,
GOODIX_ENROLL_COMMIT,
GOODIX_ENROLL_PWR_BTN_SHIELD_OFF,
GOODIX_ENROLL_NUM_STATES,
} GoodixEnrollState;
FP_ENROLL_PWR_BTN_SHIELD_ON = 0,
FP_ENROLL_ENUM,
FP_ENROLL_IDENTIFY,
FP_ENROLL_CREATE,
FP_ENROLL_CAPTURE,
FP_ENROLL_UPDATE,
FP_ENROLL_WAIT_FINGER_UP,
FP_ENROLL_CHECK_DUPLICATE,
FP_ENROLL_COMMIT,
FP_ENROLL_PWR_BTN_SHIELD_OFF,
FP_ENROLL_NUM_STATES,
} FpEnrollState;
typedef enum {
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;
FP_VERIFY_PWR_BTN_SHIELD_ON = 0,
FP_VERIFY_CAPTURE,
FP_VERIFY_IDENTIFY,
FP_VERIFY_PWR_BTN_SHIELD_OFF,
FP_VERIFY_NUM_STATES,
} FpVerifyState;
+127 -169
View File
@@ -18,8 +18,6 @@
*/
#include <glib.h>
#include <stdint.h>
#include "goodix_proto.h"
/*
@@ -109,7 +107,7 @@ reflect (uint32_t data, uint8_t n_bits)
* If the LSB bit is set, set the reflection of it.
*/
if (data & 0x01)
reflection |= (1LU << ((n_bits - 1) - bit));
reflection |= (1 << ((n_bits - 1) - bit));
data = (data >> 1);
}
@@ -213,11 +211,7 @@ gx_proto_build_package (uint8_t *ppackage,
init_pack_header (&header, payload_size, cmd, 0);
memcpy (ppackage, &header, PACKAGE_HEADER_SIZE);
if (payload)
memcpy (ppackage + PACKAGE_HEADER_SIZE, payload, payload_size);
else
ppackage[PACKAGE_HEADER_SIZE] = 0;
memcpy (ppackage + PACKAGE_HEADER_SIZE, payload, payload_size);
gx_proto_crc32_calc (ppackage, PACKAGE_HEADER_SIZE + payload_size, ppackage + PACKAGE_HEADER_SIZE + payload_size);
@@ -226,106 +220,94 @@ gx_proto_build_package (uint8_t *ppackage,
int
gx_proto_parse_header (FpiByteReader *reader,
pack_header *pheader)
gx_proto_parse_header (
uint8_t *buffer,
uint32_t buffer_len,
pack_header *pheader)
{
if (!pheader)
if (!buffer || !pheader)
return -1;
if (buffer_len < PACKAGE_HEADER_SIZE + PACKAGE_CRC_SIZE)
return -1;
if (!fpi_byte_reader_get_uint8 (reader, &pheader->cmd0))
g_return_val_if_reached (-1);
if (!fpi_byte_reader_get_uint8 (reader, &pheader->cmd1))
g_return_val_if_reached (-1);
if (!fpi_byte_reader_get_uint8 (reader, &pheader->packagenum))
g_return_val_if_reached (-1);
if (!fpi_byte_reader_get_uint8 (reader, &pheader->reserved))
g_return_val_if_reached (-1);
if (!fpi_byte_reader_get_uint16_le (reader, &pheader->len))
g_return_val_if_reached (-1);
if (!fpi_byte_reader_get_uint8 (reader, &pheader->crc8))
g_return_val_if_reached (-1);
if (!fpi_byte_reader_get_uint8 (reader, &pheader->rev_crc8))
g_return_val_if_reached (-1);
memcpy (pheader, buffer, sizeof (pack_header));
pheader->len = GUINT16_FROM_LE (pheader->len);
if (buffer_len < pheader->len + PACKAGE_HEADER_SIZE)
return -1;
pheader->len -= PACKAGE_CRC_SIZE;
return 0;
}
static int
gx_proto_parse_fingerid (FpiByteReader *reader,
ptemplate_format_t template)
gx_proto_parse_fingerid (
uint8_t * fid_buffer,
uint16_t fid_buffer_size,
ptemplate_format_t template
)
{
uint8_t byte;
uint8_t * buffer = NULL;
uint16_t Offset = 0;
if (!template)
if (!template || !fid_buffer)
return -1;
if (!fpi_byte_reader_get_uint8 (reader, &byte) || byte != 67)
g_return_val_if_reached (-1);
if (fid_buffer_size < G_STRUCT_OFFSET (template_format_t, payload) + sizeof (uint32_t))
return -1;
if (!fpi_byte_reader_get_uint8 (reader, &template->type))
g_return_val_if_reached (-1);
buffer = fid_buffer;
Offset = 0;
if (!fpi_byte_reader_get_uint8 (reader, &template->finger_index))
g_return_val_if_reached (-1);
if (!fpi_byte_reader_skip (reader, 1))
g_return_val_if_reached (-1);
if (!fpi_byte_reader_get_data_static (reader, template->accountid))
g_return_val_if_reached (-1);
if (!fpi_byte_reader_get_data_static (reader, template->tid))
g_return_val_if_reached (-1);
if (!fpi_byte_reader_get_uint8 (reader, &template->payload.size))
g_return_val_if_reached (-1);
if (buffer[Offset++] != 67)
return -1;
template->type = buffer[Offset++];
template->finger_index = buffer[Offset++];
Offset++;
memcpy (template->accountid, &buffer[Offset], sizeof (template->accountid));
Offset += sizeof (template->accountid);
memcpy (template->tid, &buffer[Offset], sizeof (template->tid));
Offset += sizeof (template->tid); // Offset == 68
template->payload.size = buffer[Offset++];
if (template->payload.size > sizeof (template->payload.data))
{
g_warning ("Device reported oversized payload (%d)", template->payload.size);
return -1;
}
if (!(fpi_byte_reader_get_data_static) (reader, template->payload.size,
template->payload.data))
g_return_val_if_reached (-1);
return -1;
if (template->payload.size + Offset > fid_buffer_size)
return -1;
memset (template->payload.data, 0, template->payload.size);
memcpy (template->payload.data, &buffer[Offset], template->payload.size);
return 0;
}
int
gx_proto_parse_body (uint16_t cmd, FpiByteReader *byte_reader, pgxfp_cmd_response_t presp)
gx_proto_parse_body (uint16_t cmd, uint8_t *buffer, uint16_t buffer_len, pgxfp_cmd_response_t presp)
{
if (!presp)
uint16_t offset = 0;
uint8_t *fingerlist = NULL;
if (!buffer || !presp)
return -1;
if (!fpi_byte_reader_get_uint8 (byte_reader, &presp->result))
g_return_val_if_reached (-1);
if (buffer_len < 1)
return -1;
presp->result = buffer[0];
switch (HIBYTE (cmd))
{
case RESPONSE_PACKAGE_CMD:
{
if (!fpi_byte_reader_get_uint8 (byte_reader, &presp->parse_msg.ack_cmd))
g_return_val_if_reached (-1);
if (buffer_len < sizeof (gxfp_parse_msg_t) + 1)
return -1;
presp->parse_msg.ack_cmd = buffer[1];
}
break;
case MOC_CMD0_UPDATE_CONFIG:
{
presp->finger_config.status = presp->result;
/* to compatiable old version firmware */
presp->finger_config.max_stored_prints = FP_MAX_FINGERNUM;
presp->finger_config.status = buffer[0];
if (buffer_len >= 3)
presp->finger_config.max_stored_prints = buffer[2];
else
/* to compatiable old version firmware */
presp->finger_config.max_stored_prints = FP_MAX_FINGERNUM;
if (fpi_byte_reader_skip (byte_reader, 1))
fpi_byte_reader_get_uint8 (byte_reader,
&presp->finger_config.max_stored_prints);
}
break;
@@ -336,106 +318,87 @@ gx_proto_parse_body (uint16_t cmd, FpiByteReader *byte_reader, pgxfp_cmd_respons
case MOC_CMD0_PWR_BTN_SHIELD:
presp->power_button_shield_resp.resp_cmd1 = LOBYTE (cmd);
uint8_t support_pwr_shield;
if (fpi_byte_reader_get_uint8 (byte_reader, &support_pwr_shield) &&
support_pwr_shield == 0xFF)
g_debug ("Power button shield feature not supported!\n");
if (buffer_len >= 2)
{
uint8_t support_pwr_shield = buffer[1];
if (support_pwr_shield == 0xFF)
g_debug ("Power button shield feature not supported!\n");
}
break;
case MOC_CMD0_GET_VERSION:
const uint8_t *version_info;
if (!fpi_byte_reader_get_data (byte_reader, sizeof (gxfp_version_info_t), &version_info))
g_return_val_if_reached (-1);
memcpy (&presp->version_info, version_info, sizeof (gxfp_version_info_t));
if (buffer_len < sizeof (gxfp_version_info_t) + 1)
return -1;
memcpy (&presp->version_info, buffer + 1, sizeof (gxfp_version_info_t));
break;
case MOC_CMD0_CAPTURE_DATA:
if (LOBYTE (cmd) == MOC_CMD1_DEFAULT)
{
if (!fpi_byte_reader_get_uint8 (byte_reader,
&presp->capture_data_resp.img_quality))
g_return_val_if_reached (-1);
if (!fpi_byte_reader_get_uint8 (byte_reader,
&presp->capture_data_resp.img_coverage))
g_return_val_if_reached (-1);
if (buffer_len < sizeof (gxfp_capturedata_t) + 1)
return -1;
presp->capture_data_resp.img_quality = buffer[1];
presp->capture_data_resp.img_coverage = buffer[2];
}
break;
case MOC_CMD0_ENROLL_INIT:
if (presp->result != GX_SUCCESS)
break;
const uint8_t *tid;
if (!fpi_byte_reader_get_data (byte_reader, TEMPLATE_ID_SIZE, &tid))
g_return_val_if_reached (-1);
memcpy (presp->enroll_create.tid, tid, TEMPLATE_ID_SIZE);
if (buffer_len < sizeof (gxfp_enroll_init_t) + 1)
return -1;
if (presp->result == GX_SUCCESS)
memcpy (&presp->enroll_init.tid, &buffer[1], TEMPLATE_ID_SIZE);
break;
case MOC_CMD0_ENROLL:
presp->enroll_update.rollback = (presp->result < 0x80) ? false : true;
if (!fpi_byte_reader_get_uint8 (byte_reader,
&presp->enroll_update.img_overlay))
g_return_val_if_reached (-1);
if (!fpi_byte_reader_get_uint8 (byte_reader,
&presp->enroll_update.img_preoverlay))
g_return_val_if_reached (-1);
if (buffer_len < sizeof (gxfp_enroll_update_t))
return -1;
presp->enroll_update.rollback = (buffer[0] < 0x80) ? false : true;
presp->enroll_update.img_overlay = buffer[1];
presp->enroll_update.img_preoverlay = buffer[2];
break;
case MOC_CMD0_CHECK4DUPLICATE:
presp->check_duplicate_resp.duplicate = (presp->result == 0) ? false : true;
if (presp->check_duplicate_resp.duplicate)
{
uint16_t tid_size;
FpiByteReader tid_reader;
if (buffer_len < 3)
return -1;
uint16_t tid_size = GUINT16_FROM_LE (*(uint16_t *) (buffer + 1));
offset += 3;
if (!fpi_byte_reader_get_uint16_le (byte_reader, &tid_size))
g_return_val_if_reached (-1);
if (!fpi_byte_reader_get_sub_reader (byte_reader, &tid_reader, tid_size))
g_return_val_if_reached (-1);
if (gx_proto_parse_fingerid (&tid_reader, &presp->check_duplicate_resp.template) != 0)
g_return_val_if_reached (-1);
if (buffer_len < tid_size + offset)
return -1;
if (gx_proto_parse_fingerid (buffer + offset, tid_size, &presp->check_duplicate_resp.template) != 0)
return -1;
}
break;
case MOC_CMD0_GETFINGERLIST:
if (presp->result != GX_SUCCESS)
break;
if (!fpi_byte_reader_get_uint8 (byte_reader,
&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;
}
if (buffer_len < 2)
return -1;
presp->finger_list_resp.finger_num = buffer[1];
fingerlist = buffer + 2;
for(uint8_t num = 0; num < presp->finger_list_resp.finger_num; num++)
{
uint16_t fingerid_length;
FpiByteReader fingerid_reader;
if (!fpi_byte_reader_get_uint16_le (byte_reader, &fingerid_length))
g_return_val_if_reached (-1);
if (!fpi_byte_reader_get_sub_reader (byte_reader, &fingerid_reader,
fingerid_length))
g_return_val_if_reached (-1);
if (gx_proto_parse_fingerid (&fingerid_reader,
if (buffer_len < offset + 2)
return -1;
fingerid_length = GUINT16_FROM_LE (*(uint16_t *) (fingerlist + offset));
offset += 2;
if (buffer_len < fingerid_length + offset)
return -1;
if (gx_proto_parse_fingerid (fingerlist + offset,
fingerid_length,
&presp->finger_list_resp.finger_list[num]) != 0)
{
g_warning ("Failed to parse finger list");
g_return_val_if_reached (-1);
g_error ("parse fingerlist error");
presp->finger_list_resp.finger_num = 0;
presp->result = GX_FAILED;
break;
}
offset += fingerid_length;
}
break;
@@ -444,32 +407,23 @@ gx_proto_parse_body (uint16_t cmd, FpiByteReader *byte_reader, pgxfp_cmd_respons
uint32_t score = 0;
uint8_t study = 0;
uint16_t fingerid_size = 0;
presp->verify.match = (presp->result == 0) ? true : false;
presp->verify.match = (buffer[0] == 0) ? true : false;
if (presp->verify.match)
{
FpiByteReader finger_reader;
if (!fpi_byte_reader_get_uint16_le (byte_reader,
&presp->verify.rejectdetail))
g_return_val_if_reached (-1);
if (!fpi_byte_reader_get_uint32_le (byte_reader, &score))
g_return_val_if_reached (-1);
if (!fpi_byte_reader_get_uint8 (byte_reader, &study))
g_return_val_if_reached (-1);
if (!fpi_byte_reader_get_uint16_le (byte_reader, &fingerid_size))
g_return_val_if_reached (-1);
if (!fpi_byte_reader_get_sub_reader (byte_reader, &finger_reader,
fingerid_size))
g_return_val_if_reached (-1);
if (gx_proto_parse_fingerid (&finger_reader,
&presp->verify.template) != 0)
if (buffer_len < 10)
return -1;
offset += 1;
presp->verify.rejectdetail = GUINT16_FROM_LE (*(uint16_t *) (buffer + offset));
offset += 2;
score = GUINT32_FROM_LE (*(uint32_t *) (buffer + offset));
offset += 4;
study = buffer[offset];
offset += 1;
fingerid_size = GUINT16_FROM_LE (*(uint16_t *) (buffer + offset));
offset += 2;
if (buffer_len < fingerid_size + offset)
return -1;
if (gx_proto_parse_fingerid (buffer + offset, fingerid_size, &presp->verify.template) != 0)
{
presp->result = GX_FAILED;
break;
@@ -480,7 +434,7 @@ gx_proto_parse_body (uint16_t cmd, FpiByteReader *byte_reader, pgxfp_cmd_respons
break;
case MOC_CMD0_FINGER_MODE:
presp->finger_status.status = presp->result;
presp->finger_status.status = buffer[0];
break;
default:
@@ -498,6 +452,8 @@ 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));
@@ -506,7 +462,9 @@ 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, pconfig->crc_value);
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);
return 0;
}
}
+9 -9
View File
@@ -22,8 +22,6 @@
#include <stdbool.h>
#include <string.h>
#include "fpi-byte-reader.h"
#define PACKAGE_CRC_SIZE (4)
#define PACKAGE_HEADER_SIZE (8)
@@ -107,10 +105,10 @@ typedef struct _gxfp_parse_msg
} gxfp_parse_msg_t, *pgxfp_parse_msg_t;
typedef struct _gxfp_enroll_create
typedef struct _gxfp_enroll_init
{
uint8_t tid[TEMPLATE_ID_SIZE];
} gxfp_enroll_create_t, *pgxfp_enroll_create_t;
} gxfp_enroll_init_t, *pgxfp_enroll_init_t;
#pragma pack(push, 1)
typedef struct _template_format
@@ -135,7 +133,7 @@ typedef struct _template_format
typedef struct _gxfp_verify
{
bool match;
uint16_t rejectdetail;
uint32_t rejectdetail;
template_format_t template;
} gxfp_verify_t, *pgxfp_verify_t;
@@ -194,7 +192,7 @@ typedef struct _fp_cmd_response
{
gxfp_parse_msg_t parse_msg;
gxfp_verify_t verify;
gxfp_enroll_create_t enroll_create;
gxfp_enroll_init_t enroll_init;
gxfp_capturedata_t capture_data_resp;
gxfp_check_duplicate_t check_duplicate_resp;
gxfp_enroll_commit_t enroll_commit;
@@ -234,11 +232,13 @@ int gx_proto_build_package (uint8_t *ppackage,
const uint8_t *payload,
uint32_t payload_size);
int gx_proto_parse_header (FpiByteReader *reader,
pack_header *pheader);
int gx_proto_parse_header (uint8_t *buffer,
uint32_t buffer_len,
pack_header *pheader);
int gx_proto_parse_body (uint16_t cmd,
FpiByteReader *byte_reader,
uint8_t *buffer,
uint16_t buffer_len,
pgxfp_cmd_response_t presponse);
int gx_proto_init_sensor_config (pgxfp_sensor_cfg_t pconfig);
File diff suppressed because it is too large Load Diff
-261
View File
@@ -1,261 +0,0 @@
#pragma once
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <stdio.h>
#include <glib.h>
#include <math.h>
#include "fpi-device.h"
#include "fpi-ssm.h"
#include "pwd.h"
#include <sys/utsname.h>
G_DECLARE_FINAL_TYPE (FpiDeviceMafpmoc, fpi_device_mafpmoc, FPI, DEVICE_MAFPMOC, FpDevice)
#define PRINT_CMD 0
#define PRINT_SSM_DEBUG 0
#define MAFP_INTERFACE_CLASS G_USB_DEVICE_CLASS_VENDOR_SPECIFIC
#define MAFP_INTERFACE_SUB_CLASS 0x01
#define MAFP_INTERFACE_PROTOCOL 0x01
/* Usb port setting */
#define MAFP_EP_BULK_OUT 0x03
#define MAFP_EP_BULK_IN 0x83
#define MAFP_EP_INT_IN 0x82
/* Command transfer timeout: ms */
#define CMD_TIMEOUT 5000
#define DATA_TIMEOUT 5000
#define CTRL_TIMEOUT 200
#define MAFP_USB_BUFFER_SIZE 512
#define PACKAGE_CRC_SIZE 2
#define PACKAGE_HEADER_SIZE 9
#define PACKAGE_DATA_SIZE_MAX (MAFP_USB_BUFFER_SIZE - PACKAGE_HEADER_SIZE - PACKAGE_CRC_SIZE)
#define TEMPLATE_ID_SIZE 2
#define TEMPLATE_UID_SIZE 128
#define DEVICE_SN_SIZE 32
#define MAX_FINGER_NUM 10
#define MAX_USER_NUM 3
#define MAX_NOTEPAD_PAGE 16
#define MOC_CMD_GET_IMAGE 0x01
#define MOC_CMD_GEN_FEATURE 0x02
#define MOC_CMD_SEARCH 0x04
#define MOC_CMD_GEN_TEMPLATE 0x05
#define MOC_CMD_SAVE_TEMPLATE 0x06
#define MOC_CMD_READ_TEMPLATE 0x07
#define MOC_CMD_DELETE_TEMPLATE 0x0C
#define MOC_CMD_EMPTY 0x0D
#define MOC_CMD_WRITE_NOTEPAD 0x18
#define MOC_CMD_READ_NOTEPAD 0x19
#define MOC_CMD_GET_TEMPLATE_NUM 0x1D
#define MOC_CMD_GET_TEMPLATE_TABLE 0x1F
#define MOC_CMD_CANCEL 0x30
#define MOC_CMD_SLEEP 0x33
#define MOC_CMD_HANDSHAKE 0x35
#define MOC_CMD_CALIBRATE 0x36
#define MOC_CMD_FACTORY_RESET 0x3B
#define MOC_CMD_FACTORY_TEST 0x56
#define MOC_CMD_MATCH_WITHFID 0x66
#define MOC_CMD_GET_MAX_ID 0x6d
#define MOC_CMD_DUPAREA_TEST 0x6f
#define MOC_CMD_SAVE_TEMPLATE_INFO 0x86
#define MOC_CMD_GET_TEMPLATE_INFO 0x87
#define MOC_CMD_GET_INIT_STATUS 0x88
#define MAFP_SUCCESS 0
#define MAFP_RE_TPL_NUM_OVERSIZE 0x0B
#define MAFP_RE_GET_IMAGE_SUCCESS 0x00
#define MAFP_RE_GET_IMAGE_NONE 0x02
/* calibrate error (un-calibrate or calibrate failed) */
#define MAFP_RE_CALIBRATE_ERROR 0x02
#define MAFP_HANDSHAKE_CODE1 'M'
#define MAFP_HANDSHAKE_CODE2 'A'
/* Default enroll stages number */
#define DEFAULT_ENROLL_SAMPLES 12
#define MAFP_ENV_ENROLL_SAMPLES "MAFP_ENROLL_SAMPLES"
#define MAFP_ENROLL_IDENTIFY_DISABLED 0
#define MAFP_ENROLL_IDENTIFY_ENABLED 1
#define MAFP_ENROLL_IDENTIFY_ONCE 2
#define MAFP_ENROLL_DUPLICATE_DELETE_DISABLED 0
#define MAFP_ENROLL_DUPLICATE_DELETE_ENABLED 1
#define MAFP_ENROLL_DUPLICATE_AREA_DENY 0
#define MAFP_ENROLL_DUPLICATE_AREA_ALLOW 1
#define MAFP_SLEEP_INT_WAIT 0
#define MAFP_SLEEP_INT_CHECK 1
#define MAFP_SLEEP_INT_REFRESH 2
#define MAFP_PRESS_WAIT_UP 0
#define MAFP_PRESS_WAIT_DOWN 1
#define MAFP_IMAGE_ERR_TRRIGER 30
typedef enum {
MAPF_CMD_SEND = 0,
MAPF_CMD_RECEIVE,
MAPF_CMD_DATA_RECEIVE,
MAPF_CMD_TRANSFER_STATES,
} MapfCmdState;
typedef enum {
MAPF_INIT_CLEAN_EPIN = 0,
MAPF_INIT_CLEAN_EPOUT,
MAPF_INIT_CLEAN_EPIN2,
MAPF_INIT_HANDSHAKE,
MAPF_INIT_MODULE_STATUS,
MAPF_INIT_STATES,
} MapfInitState;
typedef enum {
MAFP_ENROLL_PWR_BTN_SHIELD_ON = 0,
MAFP_ENROLL_CHECK_EMPTY,
MAFP_ENROLL_TEMPLATE_TABLE,
MAFP_ENROLL_READ_TEMPLATE,
MAFP_ENROLL_VERIFY_GET_IMAGE,
MAFP_ENROLL_CHECK_INT_PARA,
MAFP_ENROLL_DETECT_MODE,
MAFP_ENROLL_ENABLE_INT,
MAFP_ENROLL_WAIT_INT,
MAFP_ENROLL_DISBALE_INT,
MAFP_ENROLL_REFRESH_INT_PARA,
MAFP_ENROLL_VERIFY_GENERATE_FEATURE,
MAFP_ENROLL_VERIFY_DUPLICATE_AREA,
MAFP_ENROLL_VERIFY_SEARCH,
MAFP_ENROLL_VERIFY_SEARCH_STEP, //match assigned id
MAFP_ENROLL_GET_TEMPLATE_INFO,
MAFP_ENROLL_SAVE_TEMPLATE_INFO,
MAFP_ENROLL_SAVE_TEMPLATE,
MAFP_ENROLL_DELETE_TEMPLATE_INFO_IF_FAILED,
MAFP_ENROLL_EXIT,
MAFP_ENROLL_STATES,
} MapfEnrollState;
typedef enum {
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,
MAPF_LIST_GET_TEMPLATE_INFO,
MAPF_LIST_STATES,
} MapfListState;
typedef enum {
MAPF_DELETE_TEMPLATE_TABLE = 0,
MAPF_DELETE_GET_TEMPLATE_INFO,
MAPF_DELETE_CLEAR_TEMPLATE_INFO,
MAPF_DELETE_TEMPLATE,
MAPF_DELETE_STATES,
} MapfDeleteState;
typedef enum {
MAPF_EMPTY_TEMPLATE = 0,
MAPF_EMPTY_STATES,
} MapfDeleteAllState;
typedef enum {
MAPF_PACK_CMD = 0x01, //cmd packet
MAPF_PACK_DATA = 0x02, //data packet, with more data packets later, must follow cmd or answer packet
MAPF_PACK_ANSWER = 0x07, //answer packet for cmd packet
MAPF_PACK_END = 0x08, //last data packet
MAPF_PACK_DATA_ANDSWER = 0x09, //answer packet for data packet
} MapfPackMark;
#pragma pack(push, 1)
typedef struct _mafp_handshake
{
uint8_t code[2];
/*uint8_t state;
uint8_t desc[16];
uint8_t ver[4];*/
} mafp_handshake_t, *pmafp_handshake_t;
typedef struct _mafp_search
{
uint8_t id[2];
uint8_t score[2];
} mafp_search_t, *pmafp_search_t;
typedef struct _mafp_tpl_table
{
uint8_t used_num;
uint8_t list[256];
} mafp_tpl_table_t, *pmafp_tpl_table_t;
typedef struct _mafp_tpl_info
{
char uid[128];
} mafp_tpl_info_t, *pmafp_tpl_info_t;
typedef struct _mafp_boot_handshake
{
char code[2];
uint8_t state;
char descrip[16];
uint32_t version;
} mafp_boot_handshake_t, *pmafp_boot_handshake_t;
typedef struct _mafp_template
{
char sn[32];
uint16_t id;
char uid[128];
} mafp_template_t, *pmafp_template_t;
#pragma pack(pop)
typedef struct _mafp_templates
{
uint16_t index;
uint16_t total_num;
uint16_t priv_num;
mafp_template_t total_list[256];
mafp_template_t priv_list[MAX_FINGER_NUM];
GPtrArray *list;
} mafp_templates_t, *pmafp_templates_t;
typedef struct _fp_cmd_response
{
uint8_t result;
union
{
mafp_handshake_t handshake;
mafp_search_t search;
mafp_tpl_table_t tpl_table;
mafp_tpl_info_t tpl_info;
mafp_boot_handshake_t boot_handshake;
};
} mafp_cmd_response_t, *pmafp_cmd_response_t;
typedef struct _pack_header
{
uint8_t head0;
uint8_t head1;
uint8_t addr0;
uint8_t addr1;
uint8_t addr2;
uint8_t addr3;
uint8_t flag;
uint8_t frame_len0;
uint8_t frame_len1;
} pack_header, *ppack_header;
+1 -2
View File
@@ -412,7 +412,6 @@ 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 },
};
@@ -428,7 +427,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/NB-2020-U";
dev_class->full_name = "NextBiometrics NB-1010-U";
dev_class->type = FP_DEVICE_TYPE_USB;
dev_class->id_table = id_table;
dev_class->scan_type = FP_SCAN_TYPE_PRESS;
File diff suppressed because it is too large Load Diff
-246
View File
@@ -1,246 +0,0 @@
/*
* Copyright (C) 2022-2023 Realtek Corp.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#pragma once
#include "fpi-device.h"
#include "fpi-ssm.h"
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#define EP_IN (2 | FPI_USB_ENDPOINT_IN)
#define EP_OUT (1 | FPI_USB_ENDPOINT_OUT)
#define EP_IN_MAX_BUF_SIZE 2048
#define FP_RTK_CMD_BULK_TOTAL_LEN 12
#define FP_RTK_CMD_BULK_LEN 2
#define FP_RTK_CMD_BULK_PARAM_LEN 4
#define FP_RTK_CMD_BULK_ADDR_LEN 4
#define FP_RTK_CMD_BULK_DATA_LEN 2
#define TEMPLATE_LEN_COMMON 35
#define SUBFACTOR_OFFSET 2
#define UID_OFFSET 3
#define UID_PAYLOAD_LEN_DEFAULT 32
/* Command transfer timeout :ms*/
#define CMD_TIMEOUT 1000
#define DATA_TIMEOUT 5000
#define STATUS_TIMEOUT 2000
#define MAX_ENROLL_SAMPLES 8
#define DEFAULT_UID_LEN 28
#define SUB_FINGER_01 0xFF
#define GET_BULK_CMD_TYPE(val) ((val & 0xC0) >> 6)
#define GET_TRANS_DATA_LEN(len_h, len_l) ((len_h << 8) | len_l)
#define GET_LEN_L(total_data_len) ((total_data_len) & 0xff)
#define GET_LEN_H(total_data_len) ((total_data_len) >> 8)
G_DECLARE_FINAL_TYPE (FpiDeviceRealtek, fpi_device_realtek, FPI, DEVICE_REALTEK, FpDevice)
typedef void (*SynCmdMsgCallback) (FpiDeviceRealtek *self,
uint8_t *buffer_in,
GError *error);
typedef struct
{
SynCmdMsgCallback callback;
} CommandData;
typedef enum {
FP_RTK_CMD_BULK_ONLY = 0,
FP_RTK_CMD_BULK_READ,
FP_RTK_CMD_BULK_WRITE,
} FpRtkCmdType;
typedef enum {
FP_RTK_MSG_DEFAULT = 0,
FP_RTK_MSG_NO_STATUS,
} FpRtkMsgType;
typedef enum {
FP_RTK_PURPOSE_VERIFY = 0x01,
FP_RTK_PURPOSE_IDENTIFY = 0x02,
FP_RTK_PURPOSE_ENROLL = 0x04,
} FpRtkPurpose;
typedef enum {
FP_RTK_SUCCESS = 0x0,
FP_RTK_TOO_HIGH,
FP_RTK_TOO_LOW,
FP_RTK_TOO_LEFT,
FP_RTK_TOO_RIGHT,
FP_RTK_TOO_FAST,
FP_RTK_TOO_SLOW,
FP_RTK_POOR_QUALITY,
FP_RTK_TOO_SKEWED,
FP_RTK_TOO_SHORT,
FP_RTK_MERGE_FAILURE,
FP_RTK_MATCH_FAIL,
FP_RTK_CMD_ERR,
} FpRtkInStatus;
typedef enum {
FP_RTK_ENROLL_GET_TEMPLATE = 0,
FP_RTK_ENROLL_BEGIN_POS,
FP_RTK_ENROLL_CAPTURE,
FP_RTK_ENROLL_FINISH_CAPTURE,
FP_RTK_ENROLL_ACCEPT_SAMPLE,
FP_RTK_ENROLL_CHECK_DUPLICATE,
FP_RTK_ENROLL_COMMIT,
FP_RTK_ENROLL_CANCEL_CAPTURE,
FP_RTK_ENROLL_NUM_STATES,
} FpRtkEnrollState;
typedef enum {
FP_RTK_VERIFY_GET_TEMPLATE = 0,
FP_RTK_VERIFY_CAPTURE,
FP_RTK_VERIFY_FINISH_CAPTURE,
FP_RTK_VERIFY_ACCEPT_SAMPLE,
FP_RTK_VERIFY_INDENTIFY_FEATURE,
FP_RTK_VERIFY_UPDATE_TEMPLATE,
FP_RTK_VERIFY_CANCEL_CAPTURE,
FP_RTK_VERIFY_NUM_STATES,
} FpRtkVerifyState;
typedef enum {
FP_RTK_DELETE_GET_POS = 0,
FP_RTK_DELETE_PRINT,
FP_RTK_DELETE_NUM_STATES,
} FpRtkDeleteState;
typedef enum {
FP_RTK_INIT_GET_DEVICE_INFO = 0,
FP_RTK_INIT_SELECT_OS,
FP_RTK_INIT_GET_ENROLL_NUM,
FP_RTK_INIT_NUM_STATES,
} FpRtkInitState;
typedef enum {
FP_RTK_CMD_SEND = 0,
FP_RTK_CMD_TRANS_DATA,
FP_RTK_CMD_GET_STATUS,
FP_RTK_CMD_NUM_STATES,
} FpRtkCmdState;
struct _FpiDeviceRealtek
{
FpDevice parent;
FpiSsm *task_ssm;
FpiSsm *cmd_ssm;
FpiUsbTransfer *cmd_transfer;
FpiUsbTransfer *data_transfer;
gint cmd_type;
FpRtkMsgType message_type;
gboolean cmd_cancellable;
gint enroll_stage;
gint max_enroll_stage;
guchar *read_data;
gsize trans_data_len;
FpRtkPurpose fp_purpose;
gint pos_index;
gint template_num;
gint template_len;
};
struct rtk_cmd_bulk
{
uint8_t cmd[FP_RTK_CMD_BULK_LEN];
uint8_t param[FP_RTK_CMD_BULK_PARAM_LEN];
uint8_t addr[FP_RTK_CMD_BULK_ADDR_LEN];
uint8_t data_len[FP_RTK_CMD_BULK_DATA_LEN];
};
struct rtk_cmd_ctrl
{
int direction;
uint8_t request;
uint16_t value;
uint16_t index;
uint16_t len;
};
static struct rtk_cmd_ctrl get_device_info = {
.direction = G_USB_DEVICE_DIRECTION_DEVICE_TO_HOST,
.request = 0x07,
.value = 0x000D,
.index = 0x0000,
.len = 0x0008,
};
static struct rtk_cmd_bulk co_start_capture = {
.cmd = {0x05, 0x05},
};
static struct rtk_cmd_bulk co_finish_capture = {
.cmd = {0x45, 0x06},
.data_len = {0x05},
};
static struct rtk_cmd_bulk co_accept_sample = {
.cmd = {0x45, 0x08},
.data_len = {0x09},
};
static struct rtk_cmd_bulk nor_identify_feature = {
.cmd = {0x45, 0x22},
.data_len = {0x2A},
};
static struct rtk_cmd_bulk co_get_enroll_num = {
.cmd = {0x45, 0x0d},
.data_len = {0x02},
};
static struct rtk_cmd_bulk co_get_template = {
.cmd = {0x45, 0x0E},
};
static struct rtk_cmd_bulk nor_enroll_begin = {
.cmd = {0x05, 0x20},
};
static struct rtk_cmd_bulk co_check_duplicate = {
.cmd = {0x45, 0x10},
.data_len = {0x22},
};
static struct rtk_cmd_bulk nor_enroll_commit = {
.cmd = {0x85, 0x21},
};
static struct rtk_cmd_bulk co_update_template = {
.cmd = {0x05, 0x11},
};
static struct rtk_cmd_bulk co_delete_record = {
.cmd = {0x05, 0x0F},
};
static struct rtk_cmd_bulk co_select_system = {
.cmd = {0x05, 0x13},
};
static struct rtk_cmd_bulk co_cancel_capture = {
.cmd = {0x05, 0x07},
};
File diff suppressed because it is too large Load Diff
+3 -27
View File
@@ -177,25 +177,17 @@ 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
@@ -222,18 +214,10 @@ 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++)
{
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] = extract8 (msg_resp->payload, &offset);
get_enroll_templates_resp->templates[n].user_id[i] = '\0';
}
@@ -272,8 +256,7 @@ bmkt_compose_message (uint8_t *cmd, int *cmd_len, uint8_t msg_id, uint8_t seq_nu
cmd[BMKT_MESSAGE_SEQ_NUM_FIELD] = seq_num;
cmd[BMKT_MESSAGE_ID_FIELD] = msg_id;
cmd[BMKT_MESSAGE_PAYLOAD_LEN_FIELD] = payload_size;
if (payload_size > 0)
memcpy (&cmd[BMKT_MESSAGE_PAYLOAD_FIELD], payload, payload_size);
memcpy (&cmd[BMKT_MESSAGE_PAYLOAD_FIELD], payload, payload_size);
*cmd_len = message_len;
@@ -283,19 +266,12 @@ 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
+13 -56
View File
@@ -32,38 +32,16 @@ static void compose_and_send_identify_msg (FpDevice *device);
static const FpIdEntry id_table[] = {
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x00BD, },
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x00C2, },
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x00C4, },
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x00C6, },
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x00DF, },
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x00E9, },
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x00F0, },
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x00F9, },
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x00FC, },
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x00C2, },
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0100, },
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x00F0, },
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0103, },
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0104, },
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0106, },
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0107, },
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0108, },
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0109, },
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x010A, },
{ .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, },
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0129, },
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x015F, },
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0168, },
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0169, },
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x016C, },
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0173, },
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0174, },
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x019D, },
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x019F, },
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x01A0, },
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x01A4, },
{ .vid = 0, .pid = 0, .driver_data = 0 }, /* terminating entry */
};
@@ -125,11 +103,7 @@ cmd_receive_cb (FpiUsbTransfer *transfer,
if (self->cmd_complete_on_removal)
{
if (self->delay_error)
fpi_ssm_mark_failed (transfer->ssm,
g_steal_pointer (&self->delay_error));
else
fpi_ssm_mark_completed (transfer->ssm);
fpi_ssm_mark_completed (transfer->ssm);
return;
}
}
@@ -174,14 +148,6 @@ 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. */
@@ -258,7 +224,6 @@ cmd_interrupt_cb (FpiUsbTransfer *transfer,
}
else
{
fpi_device_critical_leave (device);
fpi_usb_transfer_submit (fpi_usb_transfer_ref (transfer),
0,
NULL,
@@ -672,21 +637,18 @@ verify (FpDevice *device)
}
static void
identify_complete_after_finger_removal (FpiDeviceSynaptics *self, GError *error)
identify_complete_after_finger_removal (FpiDeviceSynaptics *self)
{
FpDevice *device = FP_DEVICE (self);
if (self->finger_on_sensor)
{
fp_dbg ("delaying identify report until after finger removal!");
if (error)
g_propagate_error (&self->delay_error, error);
self->cmd_complete_on_removal = TRUE;
}
else
{
fpi_device_identify_complete (device, error);
fpi_device_identify_complete (device, NULL);
}
}
@@ -736,18 +698,19 @@ identify_msg_cb (FpiDeviceSynaptics *self,
fp_info ("Match error occurred");
fpi_device_identify_report (device, NULL, NULL,
fpi_device_retry_new (FP_DEVICE_RETRY_GENERAL));
identify_complete_after_finger_removal (self, NULL);
identify_complete_after_finger_removal (self);
}
else if (resp->result == BMKT_FP_NO_MATCH)
{
fp_info ("Print didn't match");
fpi_device_identify_report (device, NULL, NULL, NULL);
identify_complete_after_finger_removal (self, NULL);
identify_complete_after_finger_removal (self);
}
else if (resp->result == BMKT_FP_DATABASE_NO_RECORD_EXISTS || resp->result == BMKT_FP_DATABASE_EMPTY)
else if (resp->result == BMKT_FP_DATABASE_NO_RECORD_EXISTS)
{
fp_info ("Print is not in database");
identify_complete_after_finger_removal (self, fpi_device_error_new (FP_DEVICE_ERROR_DATA_NOT_FOUND));
fpi_device_identify_complete (device,
fpi_device_error_new (FP_DEVICE_ERROR_DATA_NOT_FOUND));
}
else
{
@@ -783,7 +746,7 @@ identify_msg_cb (FpiDeviceSynaptics *self,
else
fpi_device_identify_report (device, NULL, print, NULL);
identify_complete_after_finger_removal (self, NULL);
identify_complete_after_finger_removal (self);
}
}
}
@@ -1221,7 +1184,7 @@ prob_msg_cb (FpiDeviceSynaptics *self,
return;
}
if (fpi_device_emulation_mode_enabled (FP_DEVICE (self)))
if (g_strcmp0 (g_getenv ("FP_DEVICE_EMULATION"), "1") == 0)
serial = g_strdup ("emulated-device");
else
serial = g_usb_device_get_string_descriptor (usb_dev,
@@ -1271,12 +1234,6 @@ dev_probe (FpDevice *device)
return;
}
if (!g_usb_device_reset (usb_dev, &error))
{
fp_dbg ("%s g_usb_device_reset failed %s", G_STRFUNC, error->message);
goto err_close;
}
if (!g_usb_device_claim_interface (usb_dev, 0, 0, &error))
goto err_close;
@@ -1489,7 +1446,7 @@ suspend (FpDevice *dev)
self->cmd_suspended = TRUE;
/* Cancel the current transfer.
* The CMD SSM will go into the suspend state and signal readiness. */
* The CMD SSM will go into the suspend state and signal readyness. */
g_cancellable_cancel (self->interrupt_cancellable);
g_clear_object (&self->interrupt_cancellable);
self->interrupt_cancellable = g_cancellable_new ();
-1
View File
@@ -127,5 +127,4 @@ struct _FpiDeviceSynaptics
struct syna_enroll_resp_data enroll_resp_data;
syna_state_t state;
GError *delay_error;
};
+15 -15
View File
@@ -74,26 +74,26 @@ struct _FpiDeviceUpeksonly
FpiSsm *loopsm;
/* Do we really need multiple concurrent transfers? */
GCancellable *img_cancellable;
GPtrArray *img_transfers;
int num_flying;
GCancellable *img_cancellable;
GPtrArray *img_transfers;
int num_flying;
GSList *rows;
unsigned num_rows;
unsigned char *rowbuf;
int rowbuf_offset;
GSList *rows;
unsigned num_rows;
unsigned char *rowbuf;
int rowbuf_offset;
int wraparounds;
int num_blank;
int num_nonblank;
enum sonly_fs finger_state;
int last_seqnum;
int wraparounds;
int num_blank;
int num_nonblank;
enum sonly_fs finger_state;
int last_seqnum;
enum sonly_kill_transfers_action killing_transfers;
GError *kill_error;
FpiSsm *kill_ssm;
GError *kill_error;
FpiSsm *kill_ssm;
struct fpi_line_asmbl_ctx assembling_ctx;
struct fpi_line_asmbl_ctx assembling_ctx;
};
G_DECLARE_FINAL_TYPE (FpiDeviceUpeksonly, fpi_device_upeksonly, FPI,
DEVICE_UPEKSONLY, FpImageDevice);
-1
View File
@@ -431,7 +431,6 @@ dev_deinit (FpImageDevice *dev)
static const FpIdEntry id_table[] = {
{ .vid = 0x0483, .pid = 0x2015, .driver_data = UPEKTC_2015 },
{ .vid = 0x0483, .pid = 0x2017, .driver_data = UPEKTC_2015 },
{ .vid = 0x147e, .pid = 0x3001, .driver_data = UPEKTC_3001 },
{ .vid = 0, .pid = 0, .driver_data = 0 },
};
+29 -141
View File
@@ -31,6 +31,10 @@ static void start_deactivation (FpImageDevice *dev);
#define CTRL_TIMEOUT 4000
#define BULK_TIMEOUT 4000
#define IMAGE_WIDTH 144
#define IMAGE_HEIGHT 384
#define IMAGE_SIZE (IMAGE_WIDTH * IMAGE_HEIGHT)
#define MAX_CMD_SIZE 64
#define MAX_RESPONSE_SIZE 2052
#define SHORT_RESPONSE_SIZE 64
@@ -43,10 +47,8 @@ struct _FpiDeviceUpektcImg
unsigned char response[MAX_RESPONSE_SIZE];
unsigned char *image_bits;
unsigned char seq;
size_t expected_image_size;
size_t image_size;
size_t response_rest;
gboolean area_sensor;
gboolean deactivating;
};
G_DECLARE_FINAL_TYPE (FpiDeviceUpektcImg, fpi_device_upektc_img, FPI,
@@ -155,8 +157,7 @@ capture_reqs_cb (FpiUsbTransfer *transfer, FpDevice *device,
}
static int
upektc_img_process_image_frame (unsigned char *image_buf, size_t image_buf_len,
unsigned char *cmd_res, size_t cmd_res_len)
upektc_img_process_image_frame (unsigned char *image_buf, unsigned char *cmd_res)
{
int offset = 8;
int len = ((cmd_res[5] & 0x0f) << 8) | (cmd_res[6]);
@@ -169,16 +170,6 @@ upektc_img_process_image_frame (unsigned char *image_buf, size_t image_buf_len,
}
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;
@@ -189,7 +180,6 @@ capture_read_data_cb (FpiUsbTransfer *transfer, FpDevice *device,
gpointer user_data, GError *error)
{
FpImageDevice *dev = FP_IMAGE_DEVICE (device);
FpImageDeviceClass *img_class = FP_IMAGE_DEVICE_GET_CLASS (dev);
FpiDeviceUpektcImg *self = FPI_DEVICE_UPEKTC_IMG (dev);
unsigned char *data = self->response;
FpImage *img;
@@ -257,30 +247,8 @@ capture_read_data_cb (FpiUsbTransfer *transfer, FpDevice *device,
CAPTURE_ACK_00_28);
break;
case 0x13:
/* finger is present keep your finger on reader */
fpi_device_report_finger_status_changes (device,
FP_FINGER_STATUS_NEEDED,
FP_FINGER_STATUS_NONE);
fpi_ssm_jump_to_state (transfer->ssm,
self->area_sensor ?
CAPTURE_ACK_00_28 : CAPTURE_ACK_00_28_TERM);
break;
case 0x00:
/* finger is present! */
fpi_device_report_finger_status_changes (device,
FP_FINGER_STATUS_PRESENT,
FP_FINGER_STATUS_NONE);
fpi_ssm_jump_to_state (transfer->ssm,
CAPTURE_ACK_00_28);
break;
case 0x01:
/* no finger! */
fpi_device_report_finger_status_changes (device,
FP_FINGER_STATUS_NONE,
FP_FINGER_STATUS_PRESENT);
fpi_ssm_jump_to_state (transfer->ssm,
CAPTURE_ACK_00_28);
break;
@@ -293,20 +261,18 @@ capture_read_data_cb (FpiUsbTransfer *transfer, FpDevice *device,
fpi_image_device_report_finger_status (dev,
FALSE);
fpi_ssm_jump_to_state (transfer->ssm,
self->area_sensor ?
CAPTURE_ACK_00_28 : CAPTURE_ACK_00_28_TERM);
CAPTURE_ACK_00_28_TERM);
break;
case 0x1d:
/* too much horizontal movement */
fp_err ("too much horizontal movement, aborting");
/* too much horisontal movement */
fp_err ("too much horisontal movement, aborting");
fpi_image_device_retry_scan (dev,
FP_DEVICE_RETRY_CENTER_FINGER);
fpi_image_device_report_finger_status (dev,
FALSE);
fpi_ssm_jump_to_state (transfer->ssm,
self->area_sensor ?
CAPTURE_ACK_00_28 : CAPTURE_ACK_00_28_TERM);
CAPTURE_ACK_00_28_TERM);
break;
default:
@@ -317,8 +283,7 @@ capture_read_data_cb (FpiUsbTransfer *transfer, FpDevice *device,
fpi_image_device_report_finger_status (dev,
FALSE);
fpi_ssm_jump_to_state (transfer->ssm,
self->area_sensor ?
CAPTURE_ACK_00_28 : CAPTURE_ACK_00_28_TERM);
CAPTURE_ACK_00_28_TERM);
break;
}
break;
@@ -332,8 +297,7 @@ capture_read_data_cb (FpiUsbTransfer *transfer, FpDevice *device,
case 0x24:
self->image_size +=
upektc_img_process_image_frame (self->image_bits + self->image_size,
(self->expected_image_size * 2) - self->image_size,
data, MAX_RESPONSE_SIZE);
data);
fpi_ssm_jump_to_state (transfer->ssm,
CAPTURE_ACK_FRAME);
break;
@@ -342,22 +306,14 @@ capture_read_data_cb (FpiUsbTransfer *transfer, FpDevice *device,
case 0x20:
self->image_size +=
upektc_img_process_image_frame (self->image_bits + self->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;
}
data);
BUG_ON (self->image_size != IMAGE_SIZE);
fp_dbg ("Image size is %lu",
(gulong) self->image_size);
img = fp_image_new (img_class->img_width, img_class->img_height);
img = fp_image_new (IMAGE_WIDTH, IMAGE_HEIGHT);
img->flags |= FPI_IMAGE_PARTIAL;
memcpy (img->data, self->image_bits,
self->image_size);
IMAGE_SIZE);
fpi_image_device_image_captured (dev, img);
fpi_image_device_report_finger_status (dev,
FALSE);
@@ -390,12 +346,8 @@ capture_run_state (FpiSsm *ssm, FpDevice *_dev)
switch (fpi_ssm_get_cur_state (ssm))
{
case CAPTURE_INIT_CAPTURE:
if (self->area_sensor)
upektc_img_submit_req (ssm, dev, upek2020_init_capture_press, sizeof (upek2020_init_capture_press),
self->seq, capture_reqs_cb);
else
upektc_img_submit_req (ssm, dev, upek2020_init_capture, sizeof (upek2020_init_capture),
self->seq, capture_reqs_cb);
upektc_img_submit_req (ssm, dev, upek2020_init_capture, sizeof (upek2020_init_capture),
self->seq, capture_reqs_cb);
self->seq++;
break;
@@ -432,10 +384,12 @@ 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);
@@ -516,7 +470,6 @@ 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);
}
@@ -560,82 +513,15 @@ init_reqs_cb (FpiUsbTransfer *transfer, FpDevice *device,
fpi_ssm_mark_failed (transfer->ssm, error);
}
/* TODO: process response properly */
static void
init_read_data_cb (FpiUsbTransfer *transfer, FpDevice *device,
gpointer user_data, GError *error)
{
FpImageDevice *dev = FP_IMAGE_DEVICE (device);
FpiDeviceUpektcImg *self = FPI_DEVICE_UPEKTC_IMG (dev);
unsigned char *data = self->response;
if (error)
{
fpi_ssm_mark_failed (transfer->ssm, error);
return;
}
if (data[12] == 0x06 && data[13] == 0x14) /* if get_info */
{
FpImageDeviceClass *img_class = FP_IMAGE_DEVICE_GET_CLASS (dev);
uint16_t width = (data[51] << 8) | data[50];
uint16_t height = (data[53] << 8) | data[52];
self->area_sensor = !(data[49] & 0x80);
switch (width)
{
case 256:
fp_dbg ("Sensor type : TCS1x, width x height: %hu x %hu", width, height); /* 360x256 --- 270x192 must be set */
BUG_ON (height != 360);
img_class->img_width = 192;
img_class->img_height = 270;
break;
case 208:
fp_dbg ("Sensor type : TCS2, width x height: %hu x %hu", width, height); /* 288x208 --- 216x156 must be set */
BUG_ON (height != 288);
img_class->img_width = 156;
img_class->img_height = 216;
break;
case 248:
fp_dbg ("Sensor type : TCS3, width x height: %hu x %hu", width, height); /* 360x248 --- 270x186 must be set */
BUG_ON (height != 360);
img_class->img_width = 186;
img_class->img_height = 270;
break;
case 192:
fp_dbg ("Sensor type : TCS4x, width x height: %hu x %hu", width, height); /* 512x192 --- 384x144 must be set */
BUG_ON (height != 512);
img_class->img_width = 144;
img_class->img_height = 384;
break;
case 144:
fp_dbg ("Sensor type : TCS5x, width x height: %hu x %hu", width, height); /* 512x144 --- 384x108 must be set */
BUG_ON (height != 512);
img_class->img_width = 108;
img_class->img_height = 384;
break;
default:
fp_dbg ("Sensor type : Unknown");
fpi_ssm_mark_failed (transfer->ssm,
fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
"Unknown sensor type (reported size %dx%d)",
width, height));
return;
}
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);
}
fpi_ssm_next_state (transfer->ssm);
if (!error)
fpi_ssm_next_state (transfer->ssm);
else
fpi_ssm_mark_failed (transfer->ssm, error);
}
static void
@@ -730,6 +616,7 @@ dev_deactivate (FpImageDevice *dev)
static void
dev_init (FpImageDevice *dev)
{
FpiDeviceUpektcImg *self = FPI_DEVICE_UPEKTC_IMG (dev);
GError *error = NULL;
/* TODO check that device has endpoints we're using */
@@ -740,6 +627,7 @@ dev_init (FpImageDevice *dev)
return;
}
self->image_bits = g_malloc0 (IMAGE_SIZE * 2);
fpi_image_device_open_complete (dev, NULL);
}
@@ -799,6 +687,6 @@ fpi_device_upektc_img_class_init (FpiDeviceUpektcImgClass *klass)
img_class->bz3_threshold = 20;
img_class->img_width = -1;
img_class->img_height = -1;
img_class->img_width = IMAGE_WIDTH;
img_class->img_height = IMAGE_HEIGHT;
}
-16
View File
@@ -75,22 +75,6 @@ static const unsigned char upek2020_init_capture[] = {
0x02,
0x00, /* Wait for acceptable finger */
0x02,
0x25, 0xa9 /* CRC */
};
static const unsigned char upek2020_init_capture_press[] = {
'C', 'i', 'a', 'o',
0x00,
0x00, 0x0e, /* Seq = 7, len = 0x00e */
0x28, /* CMD = 0x28 */
0x0b, 0x00, /* Inner len = 0x000b */
0x00, 0x00,
0x0e, /* SUBCMD = 0x0e */
0x02,
0xfe, 0xff, 0xff, 0xff, /* timeout = -2 = 0xfffffffe = infinite time */
0x02,
0x01, /* Wait for finger */
0x02,
0x14, 0x9a /* CRC */
};
+6 -22
View File
@@ -196,9 +196,8 @@ struct read_msg_data
static void __read_msg_async (FpDevice *dev,
struct read_msg_data *udata);
#define READ_MSG_DATA_CB_ERR(dev, udata, error) \
(udata)->callback (dev, \
READ_MSG_CMD, 0, 0, NULL, 0, (udata)->user_data, error)
#define READ_MSG_DATA_CB_ERR(dev, udata, error) (udata)->callback (dev, \
READ_MSG_CMD, 0, 0, NULL, 0, (udata)->user_data, error)
static void
busy_ack_sent_cb (FpiUsbTransfer *transfer, FpDevice *device,
@@ -308,14 +307,6 @@ __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);
@@ -1252,7 +1243,7 @@ do_verify_stop (FpDevice *dev, FpiMatchResult res, GError *error)
FpiSsm *ssm = deinitsm_new (dev, data);
/* Report the error immediately if possible, otherwise delay it. */
if (!error || error->domain == FP_DEVICE_RETRY)
if (error && error->domain == FP_DEVICE_RETRY)
fpi_device_verify_report (dev, res, NULL, error);
else
data->error = error;
@@ -1304,7 +1295,7 @@ verify_start_sm_run_state (FpiSsm *ssm, FpDevice *dev)
memcpy (msg, verify_hdr, sizeof (verify_hdr));
memcpy (msg + sizeof (verify_hdr), data, data_len);
transfer = alloc_send_cmd28_transfer (dev, 0x03, msg, msg_len);
transfer = alloc_send_cmd28_transfer (dev, 0x03, data, data_len);
g_free (msg);
@@ -1350,6 +1341,7 @@ v_handle_resp00 (FpDevice *dev, unsigned char *data,
fp_dbg ("good image");
break;
case 0x1c: /* FIXME what does this one mean? */
case 0x0b: /* FIXME what does this one mean? */
case 0x23: /* FIXME what does this one mean? */
error = fpi_device_retry_new (FP_DEVICE_RETRY_GENERAL);
@@ -1359,14 +1351,6 @@ v_handle_resp00 (FpDevice *dev, unsigned char *data,
error = fpi_device_retry_new (FP_DEVICE_RETRY_REMOVE_FINGER);
break;
case 0x1c: /* swipe too fast */
error = fpi_device_retry_new (FP_DEVICE_RETRY_TOO_FAST);
break;
case 0x1d: /* too much horizontal movement */
error = fpi_device_retry_new (FP_DEVICE_RETRY_CENTER_FINGER);
break;
case 0x1e: /* swipe too short */
error = fpi_device_retry_new (FP_DEVICE_RETRY_TOO_SHORT);
break;
@@ -1455,7 +1439,7 @@ verify_rd2800_cb (FpDevice *dev, enum read_msg_type msgtype,
do_verify_stop (dev,
FPI_MATCH_ERROR,
fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
"Response had wrong command sequence"));
"Response hat wrong command sequence"));
return;
}
+67 -97
View File
@@ -20,8 +20,8 @@
#define FP_COMPONENT "uru4000"
#include <openssl/evp.h>
#include <openssl/err.h>
#include <nss.h>
#include <pk11pub.h>
#include "drivers_api.h"
@@ -148,7 +148,10 @@ struct _FpiDeviceUru4000
int fwfixer_offset;
unsigned char fwfixer_value;
EVP_CIPHER_CTX *cipher_ctx;
CK_MECHANISM_TYPE cipher;
PK11SlotInfo *slot;
PK11SymKey *symkey;
SECItem *param;
};
G_DECLARE_FINAL_TYPE (FpiDeviceUru4000, fpi_device_uru4000, FPI, DEVICE_URU4000,
FpImageDevice);
@@ -243,29 +246,13 @@ response_cb (FpiUsbTransfer *transfer, FpDevice *dev, void *user_data, GError *e
fpi_ssm_mark_failed (ssm, error);
}
static GError *
openssl_device_error (void)
{
char buf[256];
unsigned long e;
e = ERR_get_error ();
if (e == 0)
return fpi_device_error_new_msg (FP_DEVICE_ERROR_GENERAL,
"unexpected OpenSSL error");
ERR_error_string_n (e, buf, G_N_ELEMENTS (buf));
return fpi_device_error_new_msg (FP_DEVICE_ERROR_GENERAL, "OpenSSL error: %s",
buf);
}
static void
challenge_cb (FpiUsbTransfer *transfer, FpDevice *dev, void *user_data, GError *error)
{
FpiSsm *ssm = user_data;
FpiDeviceUru4000 *self = FPI_DEVICE_URU4000 (dev);
unsigned char respdata[CR_LENGTH * 2];
unsigned char respdata[CR_LENGTH];
PK11Context *ctx;
int outlen;
if (error)
@@ -274,39 +261,17 @@ challenge_cb (FpiUsbTransfer *transfer, FpDevice *dev, void *user_data, GError *
return;
}
if (transfer->actual_length != CR_LENGTH)
{
error = fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
"Unexpected buffer length (%" G_GSIZE_FORMAT
"instead of %d)",
transfer->actual_length, CR_LENGTH);
fpi_ssm_mark_failed (ssm, g_steal_pointer (&error));
return;
}
/* submit response */
/* produce response from challenge */
if (!EVP_EncryptUpdate (self->cipher_ctx, respdata, &outlen, transfer->buffer, CR_LENGTH))
ctx = PK11_CreateContextBySymKey (self->cipher, CKA_ENCRYPT,
self->symkey, self->param);
if (PK11_CipherOp (ctx, respdata, &outlen, CR_LENGTH, transfer->buffer, CR_LENGTH) != SECSuccess ||
PK11_Finalize (ctx) != SECSuccess)
{
fpi_ssm_mark_failed (ssm, openssl_device_error ());
return;
}
if (outlen != CR_LENGTH)
{
error = fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
"Unexpected encrypted buffer length (%d"
"instead of %d)",
outlen, CR_LENGTH);
fpi_ssm_mark_failed (ssm, g_steal_pointer (&error));
return;
}
if (!EVP_EncryptFinal_ex (self->cipher_ctx, respdata + outlen, &outlen))
{
fpi_ssm_mark_failed (ssm, openssl_device_error ());
return;
fp_err ("Failed to encrypt challenge data");
error = fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO, "Failed to encrypt challenge data");
}
PK11_DestroyContext (ctx, PR_TRUE);
if (!error)
write_regs (FP_IMAGE_DEVICE (dev), REG_RESPONSE, CR_LENGTH, respdata, response_cb, ssm);
@@ -352,7 +317,6 @@ irq_handler (FpiUsbTransfer *transfer,
if (urudev->irqs_stopped_cb)
urudev->irqs_stopped_cb (imgdev);
urudev->irqs_stopped_cb = NULL;
g_clear_error (&error);
return;
}
else if (error)
@@ -587,10 +551,7 @@ image_transfer_cb (FpiUsbTransfer *transfer, FpDevice *dev,
}
else
{
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 = g_memdup (transfer->buffer, sizeof (struct uru4k_image));
self->img_data_actual_length = transfer->actual_length;
fpi_ssm_next_state (ssm);
}
@@ -681,10 +642,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;
@@ -741,9 +702,9 @@ imaging_run_state (FpiSsm *ssm, FpDevice *_dev)
case IMAGING_DECODE:
key = self->last_reg_rd[0];
key |= (uint32_t) self->last_reg_rd[1] << 8;
key |= (uint32_t) self->last_reg_rd[2] << 16;
key |= (uint32_t) self->last_reg_rd[3] << 24;
key |= self->last_reg_rd[1] << 8;
key |= self->last_reg_rd[2] << 16;
key |= self->last_reg_rd[3] << 24;
key ^= self->img_enc_seed;
fp_dbg ("encryption id %02x -> key %08x", img->key_number, key);
@@ -755,17 +716,6 @@ 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)
@@ -809,17 +759,6 @@ 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))
@@ -836,8 +775,7 @@ 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, g_steal_pointer (&fpimg));
fpi_image_device_image_captured (dev, fpimg);
if (self->activate_state == FPI_IMAGE_DEVICE_STATE_CAPTURE)
fpi_ssm_jump_to_state (ssm, IMAGING_CAPTURE);
@@ -1207,12 +1145,6 @@ 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);
}
@@ -1337,6 +1269,8 @@ dev_init (FpImageDevice *dev)
g_autoptr(GPtrArray) interfaces = NULL;
GUsbInterface *iface = NULL;
guint64 driver_data;
SECStatus rv;
SECItem item;
int i;
interfaces = g_usb_device_get_interfaces (fpi_device_get_usb_device (FP_DEVICE (dev)), &error);
@@ -1408,11 +1342,25 @@ dev_init (FpImageDevice *dev)
return;
}
/* Disable loading p11-kit's user configuration */
g_setenv ("P11_KIT_NO_USER_CONFIG", "1", TRUE);
/* Initialise NSS early */
rv = NSS_NoDB_Init (".");
if (rv != SECSuccess)
{
fp_err ("could not initialise NSS");
fpi_image_device_open_complete (dev,
fpi_device_error_new_msg (FP_DEVICE_ERROR_GENERAL,
"Could not initialise NSS"));
return;
}
self = FPI_DEVICE_URU4000 (dev);
g_clear_pointer (&self->rand, g_rand_free);
self->rand = g_rand_new ();
if (fpi_device_emulation_mode_enabled (FP_DEVICE (dev)))
if (g_strcmp0 (g_getenv ("FP_DEVICE_EMULATION"), "1") == 0)
g_rand_set_seed (self->rand, 0xFACADE);
driver_data = fpi_device_get_driver_data (FP_DEVICE (dev));
@@ -1420,17 +1368,35 @@ dev_init (FpImageDevice *dev)
self->interface = g_usb_interface_get_number (iface);
/* Set up encryption */
if (!(self->cipher_ctx = EVP_CIPHER_CTX_new ()))
self->cipher = CKM_AES_ECB;
self->slot = PK11_GetBestSlot (self->cipher, NULL);
if (self->slot == NULL)
{
fpi_image_device_open_complete (dev, openssl_device_error ());
fp_err ("could not get encryption slot");
fpi_image_device_open_complete (dev,
fpi_device_error_new_msg (FP_DEVICE_ERROR_GENERAL,
"Could not get encryption slot"));
return;
}
if (!EVP_EncryptInit_ex (self->cipher_ctx, EVP_aes_128_ecb (), NULL, crkey, NULL))
item.type = siBuffer;
item.data = (unsigned char *) crkey;
item.len = sizeof (crkey);
self->symkey = PK11_ImportSymKey (self->slot,
self->cipher,
PK11_OriginUnwrap,
CKA_ENCRYPT,
&item, NULL);
if (self->symkey == NULL)
{
fpi_image_device_open_complete (dev, openssl_device_error ());
fp_err ("failed to import key into NSS");
PK11_FreeSlot (self->slot);
self->slot = NULL;
fpi_image_device_open_complete (dev,
fpi_device_error_new_msg (FP_DEVICE_ERROR_GENERAL,
"Failed to import key into NSS"));
return;
}
self->param = PK11_ParamFromIV (self->cipher, NULL);
fpi_image_device_open_complete (dev, NULL);
}
@@ -1441,8 +1407,12 @@ dev_deinit (FpImageDevice *dev)
GError *error = NULL;
FpiDeviceUru4000 *self = FPI_DEVICE_URU4000 (dev);
g_clear_pointer (&self->cipher_ctx, EVP_CIPHER_CTX_free);
if (self->symkey)
PK11_FreeSymKey (self->symkey);
if (self->param)
SECITEM_FreeItem (self->param, PR_TRUE);
if (self->slot)
PK11_FreeSlot (self->slot);
g_usb_device_release_interface (fpi_device_get_usb_device (FP_DEVICE (dev)),
self->interface, 0, &error);
g_clear_pointer (&self->rand, g_rand_free);
+4 -7
View File
@@ -119,7 +119,7 @@ async_abort_callback (FpiUsbTransfer *transfer, FpDevice *device,
/* In normal case endpoint is empty */
if (g_error_matches (error, G_USB_DEVICE_ERROR, G_USB_DEVICE_ERROR_TIMED_OUT) ||
(fpi_device_emulation_mode_enabled (device) && transfer->actual_length == 0))
(g_strcmp0 (g_getenv ("FP_DEVICE_EMULATION"), "1") == 0 && transfer->actual_length == 0))
{
g_clear_error (&error);
fpi_ssm_next_state (transfer->ssm);
@@ -581,7 +581,7 @@ activate_ssm (FpiSsm *ssm, FpDevice *dev)
/* Initialize fingerprint buffer */
g_free (self->lines_buffer);
self->memory = VFS_USB_BUFFER_SIZE;
self->lines_buffer = g_malloc0 (self->memory);
self->lines_buffer = g_malloc (self->memory);
self->bytes = 0;
/* Finger is on the scanner */
@@ -589,15 +589,12 @@ activate_ssm (FpiSsm *ssm, FpDevice *dev)
}
/* Increase buffer size while it's insufficient */
while (self->memory < self->bytes + VFS_USB_BUFFER_SIZE)
while (self->bytes + VFS_USB_BUFFER_SIZE > self->memory)
{
int pre_memory = self->memory;
self->memory += VFS_USB_BUFFER_SIZE;
self->memory <<= 1;
self->lines_buffer =
(struct vfs_line *) g_realloc (self->lines_buffer,
self->memory);
memset ((guint8 *) self->lines_buffer + pre_memory, 0,
VFS_USB_BUFFER_SIZE);
}
/* Receive chunk of data */
+1 -4
View File
@@ -184,8 +184,8 @@ async_send_cb (FpiUsbTransfer *transfer, FpDevice *device,
}
else
{
fp_dbg ("Ignoring send error: %s", error->message);
g_error_free (error);
fp_dbg ("Ignoring send error: %s", error->message);
}
}
/* Reset ignore_error flag */
@@ -708,9 +708,6 @@ 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)];
+6 -16
View File
@@ -85,7 +85,6 @@ 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);
@@ -102,16 +101,10 @@ m_loop_state (FpiSsm *ssm, FpDevice *_dev)
break;
case M_CHECK_PRINT:
{
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);
}
if (!vfs301_proto_peek_event (self))
fpi_ssm_jump_to_state (ssm, M_WAIT_PRINT);
else
fpi_ssm_next_state (ssm);
break;
case M_READ_PRINT_START:
@@ -128,11 +121,8 @@ m_loop_state (FpiSsm *ssm, FpDevice *_dev)
case M_READ_PRINT_POLL:
{
int rv = vfs301_proto_process_event_poll (self);
if (rv == VFS301_FAILURE)
fpi_ssm_mark_failed (ssm,
fpi_device_error_new (FP_DEVICE_ERROR_PROTO));
else if (rv == VFS301_ONGOING)
g_assert (rv != VFS301_FAILURE);
if (rv == VFS301_ONGOING)
fpi_ssm_jump_to_state (ssm, M_READ_PRINT_WAIT);
else
fpi_ssm_next_state (ssm);
+1 -2
View File
@@ -133,8 +133,7 @@ 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,
GError **error);
int vfs301_proto_peek_event (FpDeviceVfs301 *dev);
void vfs301_proto_process_event_start (FpDeviceVfs301 *dev);
int vfs301_proto_process_event_poll (FpDeviceVfs301 *dev);
+12 -20
View File
@@ -63,7 +63,7 @@ usb_print_packet (int dir, GError *error, const guint8 *data, int length)
}
#endif
static gboolean
static void
usb_recv (FpDeviceVfs301 *dev, guint8 endpoint, int max_bytes, FpiUsbTransfer **out, GError **error)
{
GError *err = NULL;
@@ -87,14 +87,10 @@ 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)
@@ -348,11 +344,7 @@ vfs301_extract_image (FpDeviceVfs301 *vfs, guint8 *output, int *output_height
int last_line;
int i;
if (vfs->scanline_count < 1 || scanlines == NULL)
{
*output_height = 0;
g_return_if_reached ();
}
g_assert (vfs->scanline_count >= 1);
*output_height = 1;
memcpy (output, scanlines, VFS301_FP_OUTPUT_WIDTH);
@@ -440,7 +432,7 @@ img_process_data (int first_block, FpDeviceVfs301 *dev, const guint8 *buf, int l
usb_send (dev, data, len, NULL); \
}
#define RAW_DATA(x) g_memdup2 (x, sizeof (x)), sizeof (x)
#define RAW_DATA(x) g_memdup (x, sizeof (x)), sizeof (x)
#define IS_VFS301_FP_SEQ_START(b) ((b[0] == 0x01) && (b[1] == 0xfe))
@@ -451,8 +443,7 @@ vfs301_proto_process_data (FpDeviceVfs301 *dev, int first_block, const guint8 *b
if (first_block)
{
if (len < VFS301_FP_FRAME_SIZE)
g_return_val_if_reached (img_process_data (first_block, dev, buf, 0));
g_assert (len >= VFS301_FP_FRAME_SIZE);
/* Skip bytes until start_sequence is found */
for (i = 0; i < VFS301_FP_FRAME_SIZE; i++, buf++, len--)
@@ -471,25 +462,26 @@ vfs301_proto_request_fingerprint (FpDeviceVfs301 *dev)
}
int
vfs301_proto_peek_event (FpDeviceVfs301 *dev,
GError **error)
vfs301_proto_peek_event (FpDeviceVfs301 *dev)
{
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);
if (!usb_recv (dev, VFS301_RECEIVE_ENDPOINT_CTRL, 7, &transfer, error))
return -1;
usb_recv (dev, VFS301_RECEIVE_ENDPOINT_CTRL, 7, &transfer, &error);
/* XXX: This is obviously not a sane error handling! */
g_assert (!error);
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;
g_set_error (error, FP_DEVICE_ERROR_PROTO, 0, "Unexpected event response");
return -1;
else
g_assert_not_reached ();
}
/* XXX: We sometimes need to receive data on from two endpoints at the same
+1 -2
View File
@@ -273,8 +273,7 @@ on_stream_read_cb (GObject *source_object,
}
else
{
g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_INVALID_DATA,
"Got empty data");
// g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_INVALID_DATA, "Got empty data");
return;
}
}
@@ -77,7 +77,6 @@ dev_identify (FpDevice *dev)
&idx))
{
match = g_ptr_array_index (prints, idx);
fp_print_set_finger (new_scan, fp_print_get_finger (match));
}
if (!self->match_reported)
+8 -27
View File
@@ -165,7 +165,11 @@ process_cmds (FpDeviceVirtualDevice * self,
{
g_autofree gchar *cmd = NULL;
cmd = g_ptr_array_steal_index (self->pending_commands, 0);
/* TODO: g_ptr_array_steal_index requires GLib 2.58, we depend on 2.56 */
cmd = g_ptr_array_index (self->pending_commands, 0);
g_ptr_array_index (self->pending_commands, 0) = NULL;
g_ptr_array_remove_index (self->pending_commands, 0);
g_debug ("Processing command %s", cmd);
/* These are always processed. */
@@ -522,8 +526,8 @@ dev_verify (FpDevice *dev)
if (scan_id)
{
g_autoptr(FpPrint) new_scan = NULL;
GVariant *data = NULL;
FpPrint *new_scan;
FpPrint *print;
gboolean success;
@@ -545,9 +549,6 @@ dev_verify (FpDevice *dev)
else
{
success = fp_print_equal (print, new_scan);
if (success)
fp_print_set_finger (new_scan, fp_print_get_finger (print));
}
if (!self->match_reported)
@@ -555,7 +556,7 @@ dev_verify (FpDevice *dev)
self->match_reported = TRUE;
fpi_device_verify_report (dev,
success ? FPI_MATCH_SUCCESS : FPI_MATCH_FAIL,
g_steal_pointer (&new_scan),
new_scan,
NULL);
}
}
@@ -732,13 +733,7 @@ dev_deinit (FpDevice *dev)
}
if (!self->keep_alive)
{
stop_listener (self);
self->supports_cancellation = TRUE;
}
self->enroll_stages_passed = 0;
self->match_reported = FALSE;
stop_listener (self);
fpi_device_close_complete (dev, NULL);
}
@@ -771,7 +766,6 @@ fpi_device_virtual_device_class_init (FpDeviceVirtualDeviceClass *klass)
{
FpDeviceClass *dev_class = FP_DEVICE_CLASS (klass);
GObjectClass *object_class = G_OBJECT_CLASS (klass);
const char *hot_seconds;
object_class->finalize = fpi_device_virtual_device_finalize;
@@ -787,18 +781,5 @@ fpi_device_virtual_device_class_init (FpDeviceVirtualDeviceClass *klass)
dev_class->enroll = dev_enroll;
dev_class->cancel = dev_cancel;
if ((hot_seconds = g_getenv ("FP_VIRTUAL_DEVICE_HOT_SECONDS")) &&
*hot_seconds != '\0')
{
gint64 hot_seconds_value;
hot_seconds_value = g_ascii_strtoll (hot_seconds, NULL, 10);
if (hot_seconds_value >= G_MAXINT32 || hot_seconds_value < 0)
hot_seconds_value = -1;
dev_class->temp_hot_seconds = hot_seconds_value;
g_debug ("device hot seconds set to %d", dev_class->temp_hot_seconds);
}
fpi_device_class_auto_initialize_features (dev_class);
}
+2 -16
View File
@@ -191,12 +191,12 @@ on_listener_connected (FpiDeviceVirtualListener *listener,
switch (state)
{
case FPI_IMAGE_DEVICE_STATE_IDLE:
case FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON:
case FPI_IMAGE_DEVICE_STATE_CAPTURE:
case FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_OFF:
recv_image (self);
case FPI_IMAGE_DEVICE_STATE_IDLE:
case FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_OFF:
case FPI_IMAGE_DEVICE_STATE_INACTIVE:
case FPI_IMAGE_DEVICE_STATE_ACTIVATING:
case FPI_IMAGE_DEVICE_STATE_DEACTIVATING:
@@ -310,7 +310,6 @@ fpi_device_virtual_image_class_init (FpDeviceVirtualImageClass *klass)
{
FpDeviceClass *dev_class = FP_DEVICE_CLASS (klass);
FpImageDeviceClass *img_class = FP_IMAGE_DEVICE_CLASS (klass);
const char *hot_seconds;
dev_class->id = FP_COMPONENT;
dev_class->full_name = "Virtual image device for debugging";
@@ -322,17 +321,4 @@ fpi_device_virtual_image_class_init (FpDeviceVirtualImageClass *klass)
img_class->activate = dev_activate;
img_class->deactivate = dev_deactivate;
if ((hot_seconds = g_getenv ("FP_VIRTUAL_IMAGE_HOT_SECONDS")) &&
*hot_seconds != '\0')
{
gint64 hot_seconds_value;
hot_seconds_value = g_ascii_strtoll (hot_seconds, NULL, 10);
if (hot_seconds_value >= G_MAXINT32 || hot_seconds_value < 0)
hot_seconds_value = -1;
dev_class->temp_hot_seconds = hot_seconds_value;
g_debug ("device hot seconds set to %d", dev_class->temp_hot_seconds);
}
}
+676
View File
@@ -0,0 +1,676 @@
/*
* Virtual driver for SDCP device debugging
*
* Copyright (C) 2020 Benjamin Berg <bberg@redhat.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/*
* This is a virtual test driver to test the basic SDCP functionality.
* It uses the test binaries from Microsoft, which were extended to allow
* a simple chat with the device.
* The environment variable contains the to be executed binary including
* arguments. This binary should be compiled from the code in
* https://github.com/Microsoft/SecureDeviceConnectionProtocol
* or, until it is merged upstream
* https://github.com/benzea/SecureDeviceConnectionProtocol
*
* Note that using this as an external executable has the advantage that we
* do not need to link against mbedtls or any other crypto library.
*/
#define FP_COMPONENT "virtual_sdcp"
#include "fpi-log.h"
#include "fpi-ssm.h"
#include "../fpi-sdcp-device.h"
#include <glib/gstdio.h>
#include <gio/gio.h>
struct _FpDeviceVirtualSdcp
{
FpSdcpDevice parent;
GSubprocess *proc;
GOutputStream *proc_stdin;
GInputStream *proc_stdout;
/* Only valid while a read/write is pending */
GByteArray *msg_out;
GByteArray *msg_in;
GByteArray *connect_msg;
};
G_DECLARE_FINAL_TYPE (FpDeviceVirtualSdcp, fpi_device_virtual_sdcp, FPI, DEVICE_VIRTUAL_SDCP, FpSdcpDevice)
G_DEFINE_TYPE (FpDeviceVirtualSdcp, fpi_device_virtual_sdcp, FP_TYPE_SDCP_DEVICE)
guint8 ca_1[] = {
0x30, 0x82, 0x03, 0xFD, 0x30, 0x82, 0x03, 0x82, 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x13, 0x33,
0x00, 0x00, 0x00, 0x07, 0xE8, 0x9D, 0x61, 0x62, 0x4D, 0x46, 0x0F, 0x95, 0x00, 0x00, 0x00, 0x00,
0x00, 0x07, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x30, 0x81,
0x84, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13,
0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0A, 0x57, 0x61, 0x73, 0x68, 0x69, 0x6E, 0x67,
0x74, 0x6F, 0x6E, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x52, 0x65,
0x64, 0x6D, 0x6F, 0x6E, 0x64, 0x31, 0x1E, 0x30, 0x1C, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x15,
0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72,
0x61, 0x74, 0x69, 0x6F, 0x6E, 0x31, 0x2E, 0x30, 0x2C, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x25,
0x57, 0x69, 0x6E, 0x64, 0x6F, 0x77, 0x73, 0x20, 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x53, 0x65,
0x63, 0x75, 0x72, 0x65, 0x20, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x20, 0x50, 0x43, 0x41,
0x20, 0x32, 0x30, 0x31, 0x38, 0x30, 0x1E, 0x17, 0x0D, 0x31, 0x38, 0x30, 0x31, 0x33, 0x31, 0x31,
0x39, 0x35, 0x34, 0x35, 0x33, 0x5A, 0x17, 0x0D, 0x32, 0x38, 0x30, 0x31, 0x33, 0x31, 0x32, 0x30,
0x30, 0x34, 0x35, 0x33, 0x5A, 0x30, 0x7D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0A, 0x57,
0x61, 0x73, 0x68, 0x69, 0x6E, 0x67, 0x74, 0x6F, 0x6E, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55,
0x04, 0x07, 0x13, 0x07, 0x52, 0x65, 0x64, 0x6D, 0x6F, 0x6E, 0x64, 0x31, 0x1E, 0x30, 0x1C, 0x06,
0x03, 0x55, 0x04, 0x0A, 0x13, 0x15, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20,
0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x31, 0x27, 0x30, 0x25, 0x06,
0x03, 0x55, 0x04, 0x03, 0x13, 0x1E, 0x57, 0x69, 0x6E, 0x64, 0x6F, 0x77, 0x73, 0x20, 0x48, 0x65,
0x6C, 0x6C, 0x6F, 0x20, 0x31, 0x39, 0x42, 0x39, 0x32, 0x39, 0x36, 0x35, 0x20, 0x43, 0x41, 0x20,
0x32, 0x30, 0x31, 0x38, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02,
0x01, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0xBE,
0x4B, 0x90, 0x6E, 0x24, 0xFC, 0xA1, 0x53, 0xC8, 0xA7, 0x3C, 0x70, 0xE8, 0x97, 0xCD, 0x1B, 0x31,
0xE4, 0x95, 0x91, 0x7A, 0x58, 0xA2, 0x86, 0xA8, 0x70, 0xF6, 0x09, 0x30, 0x77, 0x99, 0x3D, 0x10,
0xDF, 0xF7, 0x95, 0x0F, 0x68, 0x83, 0xE6, 0xA4, 0x11, 0x7C, 0xDA, 0x82, 0xE7, 0x0B, 0x8B, 0xF2,
0x9D, 0x6B, 0x5B, 0xF5, 0x3E, 0x77, 0xB4, 0xC1, 0x0E, 0x49, 0x00, 0x83, 0xBA, 0x94, 0xF8, 0xA3,
0x82, 0x01, 0xD7, 0x30, 0x82, 0x01, 0xD3, 0x30, 0x10, 0x06, 0x09, 0x2B, 0x06, 0x01, 0x04, 0x01,
0x82, 0x37, 0x15, 0x01, 0x04, 0x03, 0x02, 0x01, 0x00, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E,
0x04, 0x16, 0x04, 0x14, 0x13, 0x93, 0xC8, 0xCD, 0xF2, 0x23, 0x9A, 0x2D, 0xC6, 0x9B, 0x2A, 0xEB,
0x9A, 0xAB, 0x99, 0x0B, 0x56, 0x04, 0x5E, 0x7C, 0x30, 0x65, 0x06, 0x03, 0x55, 0x1D, 0x20, 0x04,
0x5E, 0x30, 0x5C, 0x30, 0x06, 0x06, 0x04, 0x55, 0x1D, 0x20, 0x00, 0x30, 0x52, 0x06, 0x0C, 0x2B,
0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x4C, 0x83, 0x7D, 0x01, 0x01, 0x30, 0x42, 0x30, 0x40, 0x06,
0x08, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x02, 0x01, 0x16, 0x34, 0x68, 0x74, 0x74, 0x70, 0x3A,
0x2F, 0x2F, 0x77, 0x77, 0x77, 0x2E, 0x6D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x2E,
0x63, 0x6F, 0x6D, 0x2F, 0x70, 0x6B, 0x69, 0x6F, 0x70, 0x73, 0x2F, 0x44, 0x6F, 0x63, 0x73, 0x2F,
0x52, 0x65, 0x70, 0x6F, 0x73, 0x69, 0x74, 0x6F, 0x72, 0x79, 0x2E, 0x68, 0x74, 0x6D, 0x00, 0x30,
0x19, 0x06, 0x09, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x14, 0x02, 0x04, 0x0C, 0x1E, 0x0A,
0x00, 0x53, 0x00, 0x75, 0x00, 0x62, 0x00, 0x43, 0x00, 0x41, 0x30, 0x0B, 0x06, 0x03, 0x55, 0x1D,
0x0F, 0x04, 0x04, 0x03, 0x02, 0x01, 0x86, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x1D, 0x13, 0x01, 0x01,
0xFF, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xFF, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x1D, 0x23, 0x04,
0x18, 0x30, 0x16, 0x80, 0x14, 0xDA, 0xCA, 0x4B, 0xD0, 0x4C, 0x56, 0x03, 0x27, 0x5F, 0x97, 0xEB,
0x75, 0xA3, 0x02, 0xC3, 0xBF, 0x45, 0x9C, 0xF8, 0xB1, 0x30, 0x68, 0x06, 0x03, 0x55, 0x1D, 0x1F,
0x04, 0x61, 0x30, 0x5F, 0x30, 0x5D, 0xA0, 0x5B, 0xA0, 0x59, 0x86, 0x57, 0x68, 0x74, 0x74, 0x70,
0x3A, 0x2F, 0x2F, 0x77, 0x77, 0x77, 0x2E, 0x6D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74,
0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x70, 0x6B, 0x69, 0x6F, 0x70, 0x73, 0x2F, 0x63, 0x72, 0x6C, 0x2F,
0x57, 0x69, 0x6E, 0x64, 0x6F, 0x77, 0x73, 0x25, 0x32, 0x30, 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x25,
0x32, 0x30, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x25, 0x32, 0x30, 0x44, 0x65, 0x76, 0x69, 0x63,
0x65, 0x73, 0x25, 0x32, 0x30, 0x50, 0x43, 0x41, 0x25, 0x32, 0x30, 0x32, 0x30, 0x31, 0x38, 0x2E,
0x63, 0x72, 0x6C, 0x30, 0x75, 0x06, 0x08, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x01, 0x01, 0x04,
0x69, 0x30, 0x67, 0x30, 0x65, 0x06, 0x08, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x02, 0x86,
0x59, 0x68, 0x74, 0x74, 0x70, 0x3A, 0x2F, 0x2F, 0x77, 0x77, 0x77, 0x2E, 0x6D, 0x69, 0x63, 0x72,
0x6F, 0x73, 0x6F, 0x66, 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x70, 0x6B, 0x69, 0x6F, 0x70, 0x73,
0x2F, 0x63, 0x65, 0x72, 0x74, 0x73, 0x2F, 0x57, 0x69, 0x6E, 0x64, 0x6F, 0x77, 0x73, 0x25, 0x32,
0x30, 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x25, 0x32, 0x30, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x25,
0x32, 0x30, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x25, 0x32, 0x30, 0x50, 0x43, 0x41, 0x25,
0x32, 0x30, 0x32, 0x30, 0x31, 0x38, 0x2E, 0x63, 0x72, 0x74, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86,
0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x03, 0x69, 0x00, 0x30, 0x66, 0x02, 0x31, 0x00, 0x87, 0xB6,
0x82, 0xF3, 0xDA, 0xBE, 0xB1, 0x7B, 0x98, 0x7D, 0x3D, 0x0A, 0x90, 0xA8, 0xF5, 0xBF, 0x15, 0xC3,
0xEE, 0x8A, 0x4E, 0xC0, 0x7B, 0x10, 0x1D, 0xA9, 0xE3, 0x0B, 0xEC, 0x2C, 0x53, 0x4E, 0xA7, 0xBD,
0xF1, 0x6C, 0xAD, 0x18, 0x55, 0xBA, 0x25, 0x73, 0x55, 0xB7, 0x5B, 0x12, 0x24, 0xF4, 0x02, 0x31,
0x00, 0xAF, 0x02, 0x9C, 0x4B, 0x92, 0xD0, 0x72, 0xA5, 0x80, 0xCA, 0x69, 0x2B, 0x38, 0x50, 0x64,
0xD8, 0x58, 0x9E, 0xEA, 0xD6, 0x35, 0xCF, 0x68, 0x98, 0x92, 0x81, 0x09, 0x61, 0xC2, 0xBD, 0xB1,
0x4C, 0x7F, 0xAE, 0x55, 0x7B, 0xFC, 0x22, 0xDD, 0xD6, 0xB7, 0x7C, 0xB5, 0xA8, 0x18, 0x5D, 0x33,
0x04
};
guint8 ca_2[] = {
0x30, 0x82, 0x04, 0x56, 0x30, 0x82, 0x03, 0xDC, 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x13, 0x33,
0x00, 0x00, 0x00, 0x03, 0x6C, 0xCF, 0xED, 0xE2, 0x44, 0x70, 0x19, 0xBF, 0x00, 0x00, 0x00, 0x00,
0x00, 0x03, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x03, 0x30, 0x81,
0x94, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13,
0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0A, 0x57, 0x61, 0x73, 0x68, 0x69, 0x6E, 0x67,
0x74, 0x6F, 0x6E, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x52, 0x65,
0x64, 0x6D, 0x6F, 0x6E, 0x64, 0x31, 0x1E, 0x30, 0x1C, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x15,
0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72,
0x61, 0x74, 0x69, 0x6F, 0x6E, 0x31, 0x3E, 0x30, 0x3C, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x35,
0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x45, 0x43, 0x43, 0x20, 0x44, 0x65,
0x76, 0x69, 0x63, 0x65, 0x73, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69,
0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79,
0x20, 0x32, 0x30, 0x31, 0x37, 0x30, 0x1E, 0x17, 0x0D, 0x31, 0x38, 0x30, 0x31, 0x32, 0x35, 0x31,
0x39, 0x34, 0x39, 0x33, 0x38, 0x5A, 0x17, 0x0D, 0x33, 0x33, 0x30, 0x31, 0x32, 0x35, 0x31, 0x39,
0x35, 0x39, 0x33, 0x38, 0x5A, 0x30, 0x81, 0x84, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04,
0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0A,
0x57, 0x61, 0x73, 0x68, 0x69, 0x6E, 0x67, 0x74, 0x6F, 0x6E, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03,
0x55, 0x04, 0x07, 0x13, 0x07, 0x52, 0x65, 0x64, 0x6D, 0x6F, 0x6E, 0x64, 0x31, 0x1E, 0x30, 0x1C,
0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x15, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74,
0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x31, 0x2E, 0x30, 0x2C,
0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x25, 0x57, 0x69, 0x6E, 0x64, 0x6F, 0x77, 0x73, 0x20, 0x48,
0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x20, 0x44, 0x65, 0x76, 0x69,
0x63, 0x65, 0x73, 0x20, 0x50, 0x43, 0x41, 0x20, 0x32, 0x30, 0x31, 0x38, 0x30, 0x76, 0x30, 0x10,
0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06, 0x05, 0x2B, 0x81, 0x04, 0x00, 0x22,
0x03, 0x62, 0x00, 0x04, 0x1D, 0xDD, 0x08, 0x02, 0x03, 0x25, 0x75, 0x20, 0xE2, 0x71, 0x8B, 0xAD,
0x28, 0x09, 0x82, 0xE9, 0x06, 0xEE, 0x83, 0xC5, 0x3A, 0x6C, 0x4B, 0x71, 0x92, 0x50, 0x4E, 0x20,
0xE9, 0x72, 0xB4, 0xFC, 0x53, 0x2A, 0xEF, 0x5D, 0xCC, 0x9A, 0xB4, 0xCD, 0x76, 0xB8, 0x94, 0x97,
0x44, 0xB2, 0x71, 0x0E, 0xC9, 0xB1, 0x16, 0x03, 0xA1, 0x65, 0x2B, 0xB9, 0xE8, 0x5D, 0x5F, 0xF2,
0x30, 0x2E, 0xDD, 0xB1, 0x2B, 0x20, 0xFC, 0xBE, 0x00, 0x88, 0xEA, 0x1F, 0xA7, 0x7F, 0x99, 0x84,
0x98, 0x7C, 0x71, 0x3E, 0x4D, 0x34, 0x83, 0x69, 0x9B, 0x08, 0xCB, 0x78, 0xB2, 0x4B, 0xBD, 0xD7,
0x3E, 0xBE, 0x67, 0xA0, 0xA3, 0x82, 0x01, 0xFC, 0x30, 0x82, 0x01, 0xF8, 0x30, 0x10, 0x06, 0x09,
0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x15, 0x01, 0x04, 0x03, 0x02, 0x01, 0x00, 0x30, 0x1D,
0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04, 0x16, 0x04, 0x14, 0xDA, 0xCA, 0x4B, 0xD0, 0x4C, 0x56, 0x03,
0x27, 0x5F, 0x97, 0xEB, 0x75, 0xA3, 0x02, 0xC3, 0xBF, 0x45, 0x9C, 0xF8, 0xB1, 0x30, 0x65, 0x06,
0x03, 0x55, 0x1D, 0x20, 0x04, 0x5E, 0x30, 0x5C, 0x30, 0x06, 0x06, 0x04, 0x55, 0x1D, 0x20, 0x00,
0x30, 0x52, 0x06, 0x0C, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x4C, 0x83, 0x7D, 0x01, 0x01,
0x30, 0x42, 0x30, 0x40, 0x06, 0x08, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x02, 0x01, 0x16, 0x34,
0x68, 0x74, 0x74, 0x70, 0x3A, 0x2F, 0x2F, 0x77, 0x77, 0x77, 0x2E, 0x6D, 0x69, 0x63, 0x72, 0x6F,
0x73, 0x6F, 0x66, 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x70, 0x6B, 0x69, 0x6F, 0x70, 0x73, 0x2F,
0x44, 0x6F, 0x63, 0x73, 0x2F, 0x52, 0x65, 0x70, 0x6F, 0x73, 0x69, 0x74, 0x6F, 0x72, 0x79, 0x2E,
0x68, 0x74, 0x6D, 0x00, 0x30, 0x19, 0x06, 0x09, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x14,
0x02, 0x04, 0x0C, 0x1E, 0x0A, 0x00, 0x53, 0x00, 0x75, 0x00, 0x62, 0x00, 0x43, 0x00, 0x41, 0x30,
0x0B, 0x06, 0x03, 0x55, 0x1D, 0x0F, 0x04, 0x04, 0x03, 0x02, 0x01, 0x86, 0x30, 0x0F, 0x06, 0x03,
0x55, 0x1D, 0x13, 0x01, 0x01, 0xFF, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xFF, 0x30, 0x1F, 0x06,
0x03, 0x55, 0x1D, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x14, 0xDA, 0x5B, 0xF1, 0x0E, 0x66,
0x47, 0xD1, 0x5D, 0x13, 0x5F, 0x5B, 0x7A, 0xEB, 0xEB, 0x5F, 0x01, 0x08, 0xB5, 0x49, 0x30, 0x7A,
0x06, 0x03, 0x55, 0x1D, 0x1F, 0x04, 0x73, 0x30, 0x71, 0x30, 0x6F, 0xA0, 0x6D, 0xA0, 0x6B, 0x86,
0x69, 0x68, 0x74, 0x74, 0x70, 0x3A, 0x2F, 0x2F, 0x77, 0x77, 0x77, 0x2E, 0x6D, 0x69, 0x63, 0x72,
0x6F, 0x73, 0x6F, 0x66, 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x70, 0x6B, 0x69, 0x6F, 0x70, 0x73,
0x2F, 0x63, 0x72, 0x6C, 0x2F, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x25, 0x32,
0x30, 0x45, 0x43, 0x43, 0x25, 0x32, 0x30, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x25, 0x32,
0x30, 0x52, 0x6F, 0x6F, 0x74, 0x25, 0x32, 0x30, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63,
0x61, 0x74, 0x65, 0x25, 0x32, 0x30, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x25,
0x32, 0x30, 0x32, 0x30, 0x31, 0x37, 0x2E, 0x63, 0x72, 0x6C, 0x30, 0x81, 0x87, 0x06, 0x08, 0x2B,
0x06, 0x01, 0x05, 0x05, 0x07, 0x01, 0x01, 0x04, 0x7B, 0x30, 0x79, 0x30, 0x77, 0x06, 0x08, 0x2B,
0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x02, 0x86, 0x6B, 0x68, 0x74, 0x74, 0x70, 0x3A, 0x2F, 0x2F,
0x77, 0x77, 0x77, 0x2E, 0x6D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x2E, 0x63, 0x6F,
0x6D, 0x2F, 0x70, 0x6B, 0x69, 0x6F, 0x70, 0x73, 0x2F, 0x63, 0x65, 0x72, 0x74, 0x73, 0x2F, 0x4D,
0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x25, 0x32, 0x30, 0x45, 0x43, 0x43, 0x25, 0x32,
0x30, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x25, 0x32, 0x30, 0x52, 0x6F, 0x6F, 0x74, 0x25,
0x32, 0x30, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x25, 0x32, 0x30,
0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x25, 0x32, 0x30, 0x32, 0x30, 0x31, 0x37,
0x2E, 0x63, 0x72, 0x74, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x03,
0x03, 0x68, 0x00, 0x30, 0x65, 0x02, 0x30, 0x56, 0x2A, 0xAD, 0x72, 0x4C, 0xB9, 0x8C, 0xB3, 0x23,
0x80, 0xF5, 0x5F, 0xF8, 0x21, 0x94, 0x66, 0x0F, 0x76, 0x77, 0xE2, 0x7B, 0x03, 0xDD, 0x30, 0x5E,
0xCB, 0x90, 0xCA, 0x78, 0xE6, 0x0B, 0x2D, 0x12, 0xE5, 0xF7, 0x67, 0x31, 0x58, 0x71, 0xE6, 0xF3,
0x64, 0xC1, 0x04, 0xB3, 0x8B, 0xE9, 0xE2, 0x02, 0x31, 0x00, 0xB9, 0x20, 0x61, 0xB9, 0xD0, 0x5E,
0x3A, 0xA4, 0xA2, 0x8A, 0xFE, 0x1D, 0xFC, 0x27, 0x61, 0x0B, 0x98, 0x16, 0x8C, 0x02, 0x9C, 0x20,
0x7F, 0xEE, 0xF3, 0xCB, 0x1F, 0x0A, 0x37, 0x62, 0xB1, 0x8E, 0xCE, 0xD9, 0x9A, 0x9E, 0xAC, 0xE6,
0x1A, 0xD4, 0xB8, 0xF1, 0xA8, 0x2B, 0xB1, 0xB4, 0x40, 0x9B
};
static void
msg_written_cb (GObject *source_object,
GAsyncResult *res,
gpointer user_data)
{
GError *error = NULL;
GOutputStream *stream = G_OUTPUT_STREAM (source_object);
FpiSsm *ssm = user_data;
FpDeviceVirtualSdcp *self = FPI_DEVICE_VIRTUAL_SDCP (fpi_ssm_get_device (ssm));
g_clear_pointer (&self->msg_out, g_byte_array_unref);
g_assert (self->msg_out == NULL);
if (!g_output_stream_write_all_finish (stream, res, NULL, &error))
{
fpi_ssm_mark_failed (ssm, error);
return;
}
fpi_ssm_next_state (ssm);
}
static void
msg_received_cb (GObject *source_object,
GAsyncResult *res,
gpointer user_data)
{
GError *error = NULL;
GInputStream *stream = G_INPUT_STREAM (source_object);
FpiSsm *ssm = user_data;
FpDeviceVirtualSdcp *self = FPI_DEVICE_VIRTUAL_SDCP (fpi_ssm_get_device (ssm));
gsize read;
g_assert (self->msg_out == NULL);
if (!g_input_stream_read_all_finish (stream, res, &read, &error) ||
read != self->msg_in->len)
{
g_clear_pointer (&self->msg_in, g_byte_array_unref);
if (!error)
error = fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
"Received EOF while reading from test binary.");
fpi_ssm_mark_failed (ssm, error);
return;
}
fpi_ssm_next_state (ssm);
}
enum {
SEND_MESSAGE,
RECV_MESSAGE,
SEND_RECV_STATES
};
static void
send_recv_ssm (FpiSsm *ssm, FpDevice *dev)
{
FpDeviceVirtualSdcp *self = FPI_DEVICE_VIRTUAL_SDCP (dev);
switch (fpi_ssm_get_cur_state (ssm))
{
case SEND_MESSAGE:
g_output_stream_write_all_async (self->proc_stdin,
self->msg_out->data,
self->msg_out->len,
G_PRIORITY_DEFAULT,
fpi_device_get_cancellable (FP_DEVICE (dev)),
msg_written_cb,
ssm);
break;
case RECV_MESSAGE:
g_input_stream_read_all_async (self->proc_stdout,
self->msg_in->data,
self->msg_in->len,
G_PRIORITY_DEFAULT,
fpi_device_get_cancellable (FP_DEVICE (dev)),
msg_received_cb,
ssm);
break;
}
}
static void
connect_2_cb (FpiSsm *ssm, FpDevice *dev, GError *error)
{
g_autoptr(GBytes) recv_data = NULL;
g_autoptr(GBytes) r_d = NULL;
g_autoptr(FpiSdcpClaim) claim = NULL;
g_autoptr(GBytes) mac = NULL;
g_autoptr(GBytes) ca_1_bytes = NULL, ca_2_bytes = NULL;
FpDeviceVirtualSdcp *self = FPI_DEVICE_VIRTUAL_SDCP (dev);
guint16 cert_size;
if (error)
{
fpi_sdcp_device_connect_complete (FP_SDCP_DEVICE (dev), NULL, NULL, NULL, error);
g_clear_pointer (&self->connect_msg, g_byte_array_unref);
return;
}
memcpy (&cert_size, self->connect_msg->data + 32, 2);
g_byte_array_append (self->connect_msg, self->msg_in->data, self->msg_in->len);
g_clear_pointer (&self->msg_in, g_byte_array_unref);
/* Double check that the size is correct. */
g_assert (self->connect_msg->len == 32 + (2 + cert_size + 65 + 65 + 32 + 64 + 64) + 32);
recv_data = g_byte_array_free_to_bytes (g_steal_pointer (&self->connect_msg));
claim = fpi_sdcp_claim_new ();
r_d = g_bytes_new_from_bytes (recv_data, 0, 32);
claim->cert_m = g_bytes_new_from_bytes (recv_data, 34, cert_size);
claim->pk_d = g_bytes_new_from_bytes (recv_data, 34 + cert_size, 65);
claim->pk_f = g_bytes_new_from_bytes (recv_data, 34 + cert_size + 65, 65);
claim->h_f = g_bytes_new_from_bytes (recv_data, 34 + cert_size + 65 + 65, 32);
claim->s_m = g_bytes_new_from_bytes (recv_data, 34 + cert_size + 65 + 65 + 32, 64);
claim->s_d = g_bytes_new_from_bytes (recv_data, 34 + cert_size + 65 + 65 + 32 + 64, 64);
mac = g_bytes_new_from_bytes (recv_data, 34 + cert_size + 65 + 65 + 32 + 64 + 64, 32);
ca_1_bytes = g_bytes_new_static (ca_1, G_N_ELEMENTS (ca_1));
ca_2_bytes = g_bytes_new_static (ca_2, G_N_ELEMENTS (ca_2));
fpi_sdcp_device_set_intermediat_cas (FP_SDCP_DEVICE (dev),
ca_1_bytes,
ca_2_bytes);
fpi_sdcp_device_connect_complete (FP_SDCP_DEVICE (dev), r_d, claim, mac, NULL);
}
static void
connect_1_cb (FpiSsm *ssm, FpDevice *dev, GError *error)
{
FpDeviceVirtualSdcp *self = FPI_DEVICE_VIRTUAL_SDCP (dev);
guint16 cert_size;
if (error)
{
fpi_sdcp_device_connect_complete (FP_SDCP_DEVICE (dev), NULL, NULL, NULL, error);
return;
}
g_clear_pointer (&self->connect_msg, g_byte_array_unref);
self->connect_msg = g_steal_pointer (&self->msg_in);
memcpy (&cert_size, self->connect_msg->data + 32, 2);
/* Nothing to send and the rest to receive. */
self->msg_out = g_byte_array_new ();
self->msg_in = g_byte_array_new ();
g_byte_array_set_size (self->msg_in, 32 + (2 + cert_size + 65 + 65 + 32 + 64 + 64) + 32 - self->connect_msg->len);
/* New SSM */
ssm = fpi_ssm_new_full (FP_DEVICE (dev), send_recv_ssm, SEND_RECV_STATES, SEND_RECV_STATES, "connect 2");
fpi_ssm_start (ssm, connect_2_cb);
}
static void
connect (FpSdcpDevice *dev)
{
g_autoptr(GBytes) r_h = NULL;
g_autoptr(GBytes) pk_h = NULL;
FpDeviceVirtualSdcp *self = FPI_DEVICE_VIRTUAL_SDCP (dev);
FpiSsm *ssm;
G_DEBUG_HERE ();
g_assert (self->proc);
g_assert (self->connect_msg == NULL);
fpi_sdcp_device_get_connect_data (dev, &r_h, &pk_h);
self->msg_out = g_byte_array_new ();
g_byte_array_append (self->msg_out, (const guint8 *) "C", 1);
g_byte_array_append (self->msg_out,
g_bytes_get_data (r_h, NULL),
g_bytes_get_size (r_h));
g_byte_array_append (self->msg_out,
g_bytes_get_data (pk_h, NULL),
g_bytes_get_size (pk_h));
self->msg_in = g_byte_array_new ();
g_byte_array_set_size (self->msg_in, 34);
ssm = fpi_ssm_new_full (FP_DEVICE (dev), send_recv_ssm, SEND_RECV_STATES, SEND_RECV_STATES, "connect");
fpi_ssm_start (ssm, connect_1_cb);
}
static void
reconnect_cb (FpiSsm *ssm, FpDevice *dev, GError *error)
{
g_autoptr(GBytes) mac = NULL;
FpDeviceVirtualSdcp *self = FPI_DEVICE_VIRTUAL_SDCP (dev);
if (error)
{
fpi_sdcp_device_reconnect_complete (FP_SDCP_DEVICE (dev), mac, error);
return;
}
mac = g_byte_array_free_to_bytes (g_steal_pointer (&self->msg_in));
fpi_sdcp_device_reconnect_complete (FP_SDCP_DEVICE (dev), mac, NULL);
}
static void
reconnect (FpSdcpDevice *dev)
{
g_autoptr(GBytes) r_h = NULL;
FpDeviceVirtualSdcp *self = FPI_DEVICE_VIRTUAL_SDCP (dev);
FpiSsm *ssm;
G_DEBUG_HERE ();
g_assert (self->proc);
fpi_sdcp_device_get_reconnect_data (dev, &r_h);
self->msg_out = g_byte_array_new ();
g_byte_array_append (self->msg_out, (const guint8 *) "R", 1);
g_byte_array_append (self->msg_out,
g_bytes_get_data (r_h, NULL),
g_bytes_get_size (r_h));
self->msg_in = g_byte_array_new ();
g_byte_array_set_size (self->msg_in, 32);
ssm = fpi_ssm_new_full (FP_DEVICE (dev), send_recv_ssm, SEND_RECV_STATES, SEND_RECV_STATES, "connect 2");
fpi_ssm_start (ssm, reconnect_cb);
}
static void
enroll_begin_cb (FpiSsm *ssm, FpDevice *dev, GError *error)
{
g_autoptr(GBytes) nonce = NULL;
FpDeviceVirtualSdcp *self = FPI_DEVICE_VIRTUAL_SDCP (dev);
if (error)
{
fpi_sdcp_device_enroll_ready (FP_SDCP_DEVICE (dev), error);
return;
}
nonce = g_byte_array_free_to_bytes (g_steal_pointer (&self->msg_in));
fpi_sdcp_device_enroll_set_nonce (FP_SDCP_DEVICE (dev), nonce);
/* Claim that we completed one enroll step. */
fpi_device_enroll_progress (dev, 1, NULL, NULL);
/* And signal that we are ready to commit. */
fpi_sdcp_device_enroll_ready (FP_SDCP_DEVICE (dev), NULL);
}
static void
enroll_begin (FpSdcpDevice *dev)
{
g_autoptr(GBytes) r_h = NULL;
FpDeviceVirtualSdcp *self = FPI_DEVICE_VIRTUAL_SDCP (dev);
FpiSsm *ssm;
G_DEBUG_HERE ();
g_assert (self->proc);
fpi_sdcp_device_get_reconnect_data (dev, &r_h);
self->msg_out = g_byte_array_new ();
g_byte_array_append (self->msg_out, (const guint8 *) "E", 1);
/* Expect 32 byte nonce */
self->msg_in = g_byte_array_new ();
g_byte_array_set_size (self->msg_in, 32);
ssm = fpi_ssm_new_full (FP_DEVICE (dev), send_recv_ssm, SEND_RECV_STATES, SEND_RECV_STATES, "enroll_begin");
fpi_ssm_start (ssm, enroll_begin_cb);
}
static void
enroll_commit_cb (FpiSsm *ssm, FpDevice *dev, GError *error)
{
FpDeviceVirtualSdcp *self = FPI_DEVICE_VIRTUAL_SDCP (dev);
g_clear_pointer (&self->msg_in, g_byte_array_unref);
if (error)
{
fpi_sdcp_device_enroll_ready (FP_SDCP_DEVICE (dev), error);
return;
}
/* Signal that we have committed. We don't expect a response
* from the virtual device (even though that is kind of broken).
*/
fpi_sdcp_device_enroll_commit_complete (FP_SDCP_DEVICE (dev), NULL);
}
static void
enroll_commit (FpSdcpDevice *dev, GBytes *id_in)
{
g_autoptr(GBytes) r_h = NULL;
g_autoptr(GBytes) id = id_in;
FpDeviceVirtualSdcp *self = FPI_DEVICE_VIRTUAL_SDCP (dev);
FpiSsm *ssm;
G_DEBUG_HERE ();
g_assert (self->proc);
fpi_sdcp_device_get_reconnect_data (dev, &r_h);
self->msg_out = g_byte_array_new ();
self->msg_in = g_byte_array_new ();
if (id)
{
g_byte_array_append (self->msg_out, (const guint8 *) "F", 1);
g_byte_array_append (self->msg_out,
g_bytes_get_data (id, NULL),
g_bytes_get_size (id));
/* NOTE: No response from device, assume commit works. */
}
else
{
/* Cancel enroll (does not receive a reply) */
g_byte_array_append (self->msg_out, (const guint8 *) "G", 1);
/* NOTE: No response from device, assume cancellation works. */
}
ssm = fpi_ssm_new_full (FP_DEVICE (dev), send_recv_ssm, SEND_RECV_STATES, SEND_RECV_STATES, "enroll_commit");
fpi_ssm_start (ssm, enroll_commit_cb);
}
static void
identify_cb (FpiSsm *ssm, FpDevice *dev, GError *error)
{
g_autoptr(GBytes) reply = NULL;
g_autoptr(GBytes) id = NULL;
g_autoptr(GBytes) mac = NULL;
FpDeviceVirtualSdcp *self = FPI_DEVICE_VIRTUAL_SDCP (dev);
if (error)
{
fpi_sdcp_device_identify_complete (FP_SDCP_DEVICE (dev), NULL, NULL, error);
return;
}
reply = g_byte_array_free_to_bytes (g_steal_pointer (&self->msg_in));
id = g_bytes_new_from_bytes (reply, 0, 32);
mac = g_bytes_new_from_bytes (reply, 32, 32);
fpi_sdcp_device_identify_complete (FP_SDCP_DEVICE (self), id, mac, NULL);
}
static void
identify (FpSdcpDevice *dev)
{
g_autoptr(GBytes) nonce = NULL;
FpDeviceVirtualSdcp *self = FPI_DEVICE_VIRTUAL_SDCP (dev);
FpiSsm *ssm;
G_DEBUG_HERE ();
g_assert (self->proc);
fpi_sdcp_device_get_identify_data (dev, &nonce);
self->msg_out = g_byte_array_new ();
g_byte_array_append (self->msg_out, (const guint8 *) "I", 1);
g_byte_array_append (self->msg_out, g_bytes_get_data (nonce, NULL), g_bytes_get_size (nonce));
/* Expect 64 byte nonce */
self->msg_in = g_byte_array_new ();
g_byte_array_set_size (self->msg_in, 64);
ssm = fpi_ssm_new_full (FP_DEVICE (dev), send_recv_ssm, SEND_RECV_STATES, SEND_RECV_STATES, "identify");
fpi_ssm_start (ssm, identify_cb);
}
static void
probe (FpDevice *dev)
{
g_auto(GStrv) argv = NULL;
FpDeviceVirtualSdcp *self = FPI_DEVICE_VIRTUAL_SDCP (dev);
GError *error = NULL;
const char *env;
/* We launch the test binary alread at probe time and quit only when
* the object is finalized. This allows testing reconnect properly.
*
* Also, we'll fail probe if something goes wrong executing it.
*/
env = fpi_device_get_virtual_env (FP_DEVICE (self));
if (!g_shell_parse_argv (env, NULL, &argv, &error))
goto out;
self->proc = g_subprocess_newv ((const char * const *) argv,
G_SUBPROCESS_FLAGS_STDIN_PIPE | G_SUBPROCESS_FLAGS_STDOUT_PIPE,
&error);
if (!self->proc)
goto out;
self->proc_stdin = g_object_ref (g_subprocess_get_stdin_pipe (self->proc));
self->proc_stdout = g_object_ref (g_subprocess_get_stdout_pipe (self->proc));
out:
fpi_device_probe_complete (dev, "virtual-sdcp", NULL, error);
}
static void
dev_close (FpDevice *dev)
{
/* No-op, needs to be defined. */
fpi_device_close_complete (dev, NULL);
}
static void
fpi_device_virtual_sdcp_init (FpDeviceVirtualSdcp *self)
{
}
static void
fpi_device_virtual_sdcp_finalize (GObject *obj)
{
FpDeviceVirtualSdcp *self = FPI_DEVICE_VIRTUAL_SDCP (obj);
/* Just kill the subprocess, no need to be graceful here. */
if (self->proc)
g_subprocess_force_exit (self->proc);
g_clear_object (&self->proc);
g_clear_object (&self->proc_stdin);
g_clear_object (&self->proc_stdout);
G_OBJECT_CLASS (fpi_device_virtual_sdcp_parent_class)->finalize (obj);
}
static const FpIdEntry driver_ids[] = {
{ .virtual_envvar = "FP_VIRTUAL_SDCP" },
{ .virtual_envvar = NULL }
};
static void
fpi_device_virtual_sdcp_class_init (FpDeviceVirtualSdcpClass *klass)
{
GObjectClass *obj_class = G_OBJECT_CLASS (klass);
FpDeviceClass *dev_class = FP_DEVICE_CLASS (klass);
FpSdcpDeviceClass *sdcp_class = FP_SDCP_DEVICE_CLASS (klass);
obj_class->finalize = fpi_device_virtual_sdcp_finalize;
dev_class->id = FP_COMPONENT;
dev_class->full_name = "Virtual SDCP device talking to MS test code";
dev_class->type = FP_DEVICE_TYPE_VIRTUAL;
dev_class->id_table = driver_ids;
dev_class->nr_enroll_stages = 1;
/* The SDCP base class may need to override this in the long run */
dev_class->probe = probe;
dev_class->close = dev_close;
sdcp_class->connect = connect;
sdcp_class->reconnect = reconnect;
sdcp_class->enroll_begin = enroll_begin;
sdcp_class->enroll_commit = enroll_commit;
sdcp_class->identify = identify;
}
-1
View File
@@ -22,7 +22,6 @@
#pragma once
#include "fpi-compat.h"
#include "fpi-enums.h"
#include "fpi-assembling.h"
#include "fpi-device.h"
#include "fpi-image-device.h"
+17 -12
View File
@@ -67,26 +67,32 @@ enum {
static guint signals[LAST_SIGNAL] = { 0 };
static const char *
get_drivers_allowlist_env (void)
get_drivers_whitelist_env (void)
{
return g_getenv ("FP_DRIVERS_ALLOWLIST");
return g_getenv ("FP_DRIVERS_WHITELIST");
}
static gboolean
is_driver_allowed (const gchar *driver)
{
g_auto(GStrv) allowlisted_drivers = NULL;
const char *fp_drivers_allowlist_env;
g_auto(GStrv) whitelisted_drivers = NULL;
const char *fp_drivers_whitelist_env;
int i;
g_return_val_if_fail (driver, TRUE);
fp_drivers_allowlist_env = get_drivers_allowlist_env ();
fp_drivers_whitelist_env = get_drivers_whitelist_env ();
if (!fp_drivers_allowlist_env)
if (!fp_drivers_whitelist_env)
return TRUE;
allowlisted_drivers = g_strsplit (fp_drivers_allowlist_env, ":", -1);
return g_strv_contains ((const gchar * const *) allowlisted_drivers, driver);
whitelisted_drivers = g_strsplit (fp_drivers_whitelist_env, ":", -1);
for (i = 0; whitelisted_drivers[i]; ++i)
if (g_strcmp0 (driver, whitelisted_drivers[i]) == 0)
return TRUE;
return FALSE;
}
typedef struct
@@ -285,10 +291,11 @@ fp_context_finalize (GObject *object)
FpContext *self = (FpContext *) object;
FpContextPrivate *priv = fp_context_get_instance_private (self);
g_clear_pointer (&priv->devices, g_ptr_array_unref);
g_cancellable_cancel (priv->cancellable);
g_clear_object (&priv->cancellable);
g_clear_pointer (&priv->drivers, g_array_unref);
g_clear_pointer (&priv->devices, g_ptr_array_unref);
g_slist_free_full (g_steal_pointer (&priv->sources), (GDestroyNotify) g_source_destroy);
@@ -354,11 +361,9 @@ fp_context_init (FpContext *self)
FpContextPrivate *priv = fp_context_get_instance_private (self);
guint i;
g_debug ("Initializing FpContext (libfprint version " LIBFPRINT_VERSION ")");
priv->drivers = fpi_get_driver_types ();
if (get_drivers_allowlist_env ())
if (get_drivers_whitelist_env ())
{
for (i = 0; i < priv->drivers->len;)
{
+4 -4
View File
@@ -44,7 +44,7 @@ typedef struct
FpDeviceType type;
GUsbDevice *usb_device;
gchar *virtual_env;
const gchar *virtual_env;
struct
{
gchar *spidev_path;
@@ -111,6 +111,8 @@ typedef struct
GDestroyNotify enroll_progress_destroy;
} FpEnrollData;
void enroll_data_free (FpEnrollData *enroll_data);
typedef struct
{
FpPrint *enrolled_print; /* verify */
@@ -126,9 +128,7 @@ typedef struct
GDestroyNotify match_destroy;
} FpMatchData;
void fpi_device_suspend (FpDevice *device);
void fpi_device_resume (FpDevice *device);
void match_data_free (FpMatchData *match_data);
void fpi_device_configure_wakeup (FpDevice *device,
gboolean enabled);
+119 -117
View File
@@ -128,9 +128,6 @@ 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);
}
@@ -224,11 +221,10 @@ fp_device_finalize (GObject *object)
g_clear_pointer (&priv->temp_timeout, g_source_destroy);
g_clear_slist (&priv->sources, (GDestroyNotify) g_source_destroy);
g_slist_free_full (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);
g_clear_pointer (&priv->critical_section_flush_source, g_source_destroy);
g_clear_pointer (&priv->device_id, g_free);
g_clear_pointer (&priv->device_name, g_free);
@@ -295,14 +291,14 @@ fp_device_get_property (GObject *object,
case PROP_FPI_UDEV_DATA_SPIDEV:
if (cls->type == FP_DEVICE_TYPE_UDEV)
g_value_set_string (value, priv->udev_data.spidev_path);
g_value_set_string (value, g_strdup (priv->udev_data.spidev_path));
else
g_value_set_string (value, NULL);
break;
case PROP_FPI_UDEV_DATA_HIDRAW:
if (cls->type == FP_DEVICE_TYPE_UDEV)
g_value_set_string (value, priv->udev_data.hidraw_path);
g_value_set_string (value, g_strdup (priv->udev_data.hidraw_path));
else
g_value_set_string (value, NULL);
break;
@@ -486,9 +482,6 @@ fp_device_class_init (FpDeviceClass *klass)
NULL,
G_PARAM_STATIC_STRINGS | G_PARAM_READABLE);
/**
* FpDevice:open: (getter is_open):
*/
properties[PROP_OPEN] =
g_param_spec_boolean ("open",
"Opened",
@@ -955,6 +948,16 @@ fp_device_close_finish (FpDevice *device,
return g_task_propagate_boolean (G_TASK (result), error);
}
static void
complete_suspend_resume_task (FpDevice *device)
{
FpDevicePrivate *priv = fp_device_get_instance_private (device);
g_assert (priv->suspend_resume_task);
g_task_return_boolean (g_steal_pointer (&priv->suspend_resume_task), TRUE);
}
/**
* fp_device_suspend:
* @device: a #FpDevice
@@ -1005,7 +1008,48 @@ fp_device_suspend (FpDevice *device,
priv->suspend_resume_task = g_steal_pointer (&task);
fpi_device_suspend (device);
/* If the device is currently idle, just complete immediately.
* For long running tasks, call the driver handler right away, for short
* tasks, wait for completion and then return the task.
*/
switch (priv->current_action)
{
case FPI_DEVICE_ACTION_NONE:
fpi_device_suspend_complete (device, NULL);
break;
case FPI_DEVICE_ACTION_ENROLL:
case FPI_DEVICE_ACTION_VERIFY:
case FPI_DEVICE_ACTION_IDENTIFY:
case FPI_DEVICE_ACTION_CAPTURE:
if (FP_DEVICE_GET_CLASS (device)->suspend)
{
if (priv->critical_section)
priv->suspend_queued = TRUE;
else
FP_DEVICE_GET_CLASS (device)->suspend (device);
}
else
{
fpi_device_suspend_complete (device, fpi_device_error_new (FP_DEVICE_ERROR_NOT_SUPPORTED));
}
break;
default:
case FPI_DEVICE_ACTION_PROBE:
case FPI_DEVICE_ACTION_OPEN:
case FPI_DEVICE_ACTION_CLOSE:
case FPI_DEVICE_ACTION_DELETE:
case FPI_DEVICE_ACTION_LIST:
case FPI_DEVICE_ACTION_CLEAR_STORAGE:
g_signal_connect_object (priv->current_task,
"notify::completed",
G_CALLBACK (complete_suspend_resume_task),
device,
G_CONNECT_SWAPPED);
break;
}
}
/**
@@ -1070,7 +1114,41 @@ fp_device_resume (FpDevice *device,
priv->suspend_resume_task = g_steal_pointer (&task);
fpi_device_resume (device);
switch (priv->current_action)
{
case FPI_DEVICE_ACTION_NONE:
fpi_device_resume_complete (device, NULL);
break;
case FPI_DEVICE_ACTION_ENROLL:
case FPI_DEVICE_ACTION_VERIFY:
case FPI_DEVICE_ACTION_IDENTIFY:
case FPI_DEVICE_ACTION_CAPTURE:
if (FP_DEVICE_GET_CLASS (device)->resume)
{
if (priv->critical_section)
priv->resume_queued = TRUE;
else
FP_DEVICE_GET_CLASS (device)->resume (device);
}
else
{
fpi_device_resume_complete (device, fpi_device_error_new (FP_DEVICE_ERROR_NOT_SUPPORTED));
}
break;
default:
case FPI_DEVICE_ACTION_PROBE:
case FPI_DEVICE_ACTION_OPEN:
case FPI_DEVICE_ACTION_CLOSE:
case FPI_DEVICE_ACTION_DELETE:
case FPI_DEVICE_ACTION_LIST:
case FPI_DEVICE_ACTION_CLEAR_STORAGE:
/* cannot happen as we make sure these tasks complete before suspend */
g_assert_not_reached ();
complete_suspend_resume_task (device);
break;
}
}
/**
@@ -1094,23 +1172,14 @@ fp_device_resume_finish (FpDevice *device,
return g_task_propagate_boolean (G_TASK (result), error);
}
static void
enroll_data_free (FpEnrollData *data)
{
if (data->enroll_progress_destroy)
data->enroll_progress_destroy (data->enroll_progress_data);
data->enroll_progress_data = NULL;
g_clear_object (&data->print);
g_free (data);
}
/**
* fp_device_enroll:
* @device: a #FpDevice
* @template_print: (transfer floating): a #FpPrint
* @cancellable: (nullable): a #GCancellable, or %NULL
* @progress_cb: (nullable) (closure progress_data) (scope notified): progress reporting callback
* @progress_data: user data for @progress_cb
* @progress_cb: (nullable) (scope notified): progress reporting callback
* @progress_data: (closure progress_cb): user data for @progress_cb
* @progress_destroy: (destroy progress_data): Destroy notify for @progress_data
* @callback: (scope async): the function to call on completion
* @user_data: the data to pass to @callback
@@ -1187,6 +1256,10 @@ fp_device_enroll (FpDevice *device,
}
}
priv->current_action = FPI_DEVICE_ACTION_ENROLL;
priv->current_task = g_steal_pointer (&task);
setup_task_cancellable (device);
fpi_device_update_temp (device, TRUE);
if (priv->temp_current == FP_TEMPERATURE_HOT)
{
@@ -1195,10 +1268,6 @@ fp_device_enroll (FpDevice *device,
return;
}
priv->current_action = FPI_DEVICE_ACTION_ENROLL;
priv->current_task = g_steal_pointer (&task);
setup_task_cancellable (device);
data = g_new0 (FpEnrollData, 1);
data->print = g_object_ref_sink (template_print);
data->enroll_progress_cb = progress_cb;
@@ -1232,57 +1301,13 @@ fp_device_enroll_finish (FpDevice *device,
return g_task_propagate_pointer (G_TASK (result), error);
}
static void
match_data_free (FpMatchData *data)
{
g_clear_object (&data->print);
g_clear_object (&data->match);
g_clear_error (&data->error);
if (data->match_destroy)
data->match_destroy (data->match_data);
data->match_data = NULL;
g_clear_object (&data->enrolled_print);
g_clear_pointer (&data->gallery, g_ptr_array_unref);
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
* @enrolled_print: a #FpPrint to verify
* @cancellable: (nullable): a #GCancellable, or %NULL
* @match_cb: (nullable) (scope notified) (closure match_data): match reporting callback
* @match_data: user data for @match_cb
* @match_cb: (nullable) (scope notified): match reporting callback
* @match_data: (closure match_cb): user data for @match_cb
* @match_destroy: (destroy match_data): Destroy notify for @match_data
* @callback: the function to call on completion
* @user_data: the data to pass to @callback
@@ -1324,8 +1349,7 @@ fp_device_verify (FpDevice *device,
return;
}
if ((!cls->verify && !cls->identify) ||
!(priv->features & FP_DEVICE_FEATURE_VERIFY))
if (!cls->verify || !(priv->features & FP_DEVICE_FEATURE_VERIFY))
{
g_task_return_error (task,
fpi_device_error_new_msg (FP_DEVICE_ERROR_NOT_SUPPORTED,
@@ -1333,20 +1357,9 @@ 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;
}
priv->current_action = FPI_DEVICE_ACTION_VERIFY;
priv->current_task = g_steal_pointer (&task);
setup_task_cancellable (device);
fpi_device_update_temp (device, TRUE);
if (priv->temp_current == FP_TEMPERATURE_HOT)
@@ -1356,10 +1369,6 @@ fp_device_verify (FpDevice *device,
return;
}
priv->current_action = FPI_DEVICE_ACTION_VERIFY;
priv->current_task = g_steal_pointer (&task);
setup_task_cancellable (device);
data = g_new0 (FpMatchData, 1);
data->enrolled_print = g_object_ref (enrolled_print);
data->match_cb = match_cb;
@@ -1423,8 +1432,8 @@ fp_device_verify_finish (FpDevice *device,
* @device: a #FpDevice
* @prints: (element-type FpPrint) (transfer none): #GPtrArray of #FpPrint
* @cancellable: (nullable): a #GCancellable, or %NULL
* @match_cb: (nullable) (scope notified) (closure match_data): match reporting callback
* @match_data: user data for @match_cb
* @match_cb: (nullable) (scope notified): match reporting callback
* @match_data: (closure match_cb): user data for @match_cb
* @match_destroy: (destroy match_data): Destroy notify for @match_data
* @callback: the function to call on completion
* @user_data: the data to pass to @callback
@@ -1447,6 +1456,7 @@ 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))
@@ -1474,13 +1484,9 @@ fp_device_identify (FpDevice *device,
return;
}
if (prints == NULL)
{
g_task_return_error (task,
fpi_device_error_new_msg (FP_DEVICE_ERROR_DATA_INVALID,
"Invalid gallery array"));
return;
}
priv->current_action = FPI_DEVICE_ACTION_IDENTIFY;
priv->current_task = g_steal_pointer (&task);
setup_task_cancellable (device);
fpi_device_update_temp (device, TRUE);
if (priv->temp_current == FP_TEMPERATURE_HOT)
@@ -1490,18 +1496,14 @@ fp_device_identify (FpDevice *device,
return;
}
priv->current_action = FPI_DEVICE_ACTION_IDENTIFY;
priv->current_task = g_steal_pointer (&task);
setup_task_cancellable (device);
data = g_new0 (FpMatchData, 1);
/* We cannot store the gallery directly, because the ptr array may not own
* a reference to each print. Also, the caller could in principle modify the
* GPtrArray afterwards.
*/
data->gallery = g_ptr_array_copy (prints, (GCopyFunc) g_object_ref, NULL);
g_ptr_array_set_free_func (data->gallery, g_object_unref);
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->match_cb = match_cb;
data->match_data = match_data;
data->match_destroy = match_destroy;
@@ -1607,6 +1609,10 @@ fp_device_capture (FpDevice *device,
return;
}
priv->current_action = FPI_DEVICE_ACTION_CAPTURE;
priv->current_task = g_steal_pointer (&task);
setup_task_cancellable (device);
fpi_device_update_temp (device, TRUE);
if (priv->temp_current == FP_TEMPERATURE_HOT)
{
@@ -1615,10 +1621,6 @@ fp_device_capture (FpDevice *device,
return;
}
priv->current_action = FPI_DEVICE_ACTION_CAPTURE;
priv->current_task = g_steal_pointer (&task);
setup_task_cancellable (device);
priv->wait_for_finger = wait_for_finger;
cls->capture (device);
@@ -1991,8 +1993,8 @@ fp_device_enroll_sync (FpDevice *device,
* @device: a #FpDevice
* @enrolled_print: a #FpPrint to verify
* @cancellable: (nullable): a #GCancellable, or %NULL
* @match_cb: (nullable) (scope call) (closure match_data): match reporting callback
* @match_data: user data for @match_cb
* @match_cb: (nullable) (scope call): match reporting callback
* @match_data: (closure match_cb): user data for @match_cb
* @match: (out): Whether the user presented the correct finger
* @print: (out) (transfer full) (nullable): Location to store the scanned print, or %NULL to ignore
* @error: Return location for errors, or %NULL to ignore
@@ -2031,8 +2033,8 @@ fp_device_verify_sync (FpDevice *device,
* @device: a #FpDevice
* @prints: (element-type FpPrint) (transfer none): #GPtrArray of #FpPrint
* @cancellable: (nullable): a #GCancellable, or %NULL
* @match_cb: (nullable) (scope call) (closure match_data): match reporting callback
* @match_data: user data for @match_cb
* @match_cb: (nullable) (scope call): match reporting callback
* @match_data: (closure match_cb): user data for @match_cb
* @match: (out) (transfer full) (nullable): Location for the matched #FpPrint, or %NULL
* @print: (out) (transfer full) (nullable): Location for the new #FpPrint, or %NULL
* @error: Return location for errors, or %NULL to ignore
+2 -3
View File
@@ -113,8 +113,6 @@ typedef enum {
* @FP_DEVICE_RETRY_REMOVE_FINGER: The scan did not succeed due to quality or
* pressure problems; the user should remove their finger from the scanner
* before retrying.
* @FP_DEVICE_RETRY_TOO_FAST: The scan did not succeed because the finger
* swipe or touch was too fast.
*
* Error codes representing scan failures resulting in the user needing to
* retry.
@@ -124,7 +122,6 @@ typedef enum {
FP_DEVICE_RETRY_TOO_SHORT,
FP_DEVICE_RETRY_CENTER_FINGER,
FP_DEVICE_RETRY_REMOVE_FINGER,
FP_DEVICE_RETRY_TOO_FAST,
} FpDeviceRetry;
/**
@@ -143,6 +140,7 @@ typedef enum {
* @FP_DEVICE_ERROR_DATA_DUPLICATE: Enrolling template duplicates storaged templates
* @FP_DEVICE_ERROR_REMOVED: The device has been removed.
* @FP_DEVICE_ERROR_TOO_HOT: The device might be getting too hot
* @FP_DEVICE_ERROR_UNTRUSTED: Device cannot be trusted
*
* Error codes for device operations. More specific errors from other domains
* such as #G_IO_ERROR or #G_USB_DEVICE_ERROR may also be reported.
@@ -161,6 +159,7 @@ typedef enum {
/* Leave some room to add more DATA related errors */
FP_DEVICE_ERROR_REMOVED = 0x100,
FP_DEVICE_ERROR_TOO_HOT,
FP_DEVICE_ERROR_UNTRUSTED,
} FpDeviceError;
GQuark fp_device_retry_quark (void);
+2
View File
@@ -89,6 +89,7 @@ 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);
@@ -216,6 +217,7 @@ 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;
+76 -120
View File
@@ -20,11 +20,9 @@
#define FP_COMPONENT "image"
#include "fpi-compat.h"
#include "fpi-image.h"
#include "fpi-log.h"
#include <config.h>
#include <nbis.h>
/**
@@ -160,65 +158,60 @@ fp_image_init (FpImage *self)
typedef struct
{
GAsyncReadyCallback user_cb;
struct fp_minutiae *minutiae;
guchar *binarized;
gint width, height;
gdouble ppmm;
FpiImageFlags flags;
unsigned char *image;
gboolean image_changed;
} DetectMinutiaeNbisData;
guchar *image;
guchar *binarized;
} DetectMinutiaeData;
static void
fp_image_detect_minutiae_free (DetectMinutiaeNbisData *data)
fp_image_detect_minutiae_free (DetectMinutiaeData *data)
{
g_clear_pointer (&data->image, g_free);
g_clear_pointer (&data->minutiae, free_minutiae);
g_clear_pointer (&data->binarized, g_free);
if (data->image_changed)
g_clear_pointer (&data->image, g_free);
g_free (data);
}
G_DEFINE_AUTOPTR_CLEANUP_FUNC (DetectMinutiaeNbisData, fp_image_detect_minutiae_free)
static gboolean
fp_image_detect_minutiae_nbis_finish (FpImage *self,
GTask *task,
GError **error)
static void
fp_image_detect_minutiae_cb (GObject *source_object,
GAsyncResult *res,
gpointer user_data)
{
g_autoptr(DetectMinutiaeNbisData) data = NULL;
GTask *task = G_TASK (res);
FpImage *image;
DetectMinutiaeData *data = g_task_get_task_data (task);
data = g_task_propagate_pointer (task, error);
if (data != NULL)
if (!g_task_had_error (task))
{
self->flags = data->flags;
gint i;
image = FP_IMAGE (source_object);
if (data->image_changed)
{
g_clear_pointer (&self->data, g_free);
self->data = g_steal_pointer (&data->image);
}
image->flags = data->flags;
g_clear_pointer (&self->binarized, g_free);
self->binarized = g_steal_pointer (&data->binarized);
g_clear_pointer (&image->data, g_free);
image->data = g_steal_pointer (&data->image);
g_clear_pointer (&self->minutiae, g_ptr_array_unref);
self->minutiae = g_ptr_array_new_full (data->minutiae->num,
(GDestroyNotify) free_minutia);
g_clear_pointer (&image->binarized, g_free);
image->binarized = g_steal_pointer (&data->binarized);
for (int i = 0; i < data->minutiae->num; i++)
g_ptr_array_add (self->minutiae,
g_clear_pointer (&image->minutiae, g_ptr_array_unref);
image->minutiae = g_ptr_array_new_full (data->minutiae->num,
(GDestroyNotify) free_minutia);
for (i = 0; i < data->minutiae->num; i++)
g_ptr_array_add (image->minutiae,
g_steal_pointer (&data->minutiae->list[i]));
/* Don't let free_minutiae delete the minutiae that we now own. */
/* Don't let it delete anything. */
data->minutiae->num = 0;
return TRUE;
}
return FALSE;
if (data->user_cb)
data->user_cb (source_object, res, user_data);
}
static void
@@ -271,83 +264,70 @@ invert_colors (guint8 *data, gint width, gint height)
}
static void
fp_image_detect_minutiae_nbis_thread_func (GTask *task,
gpointer source_object,
gpointer task_data,
GCancellable *cancellable)
fp_image_detect_minutiae_thread_func (GTask *task,
gpointer source_object,
gpointer task_data,
GCancellable *cancellable)
{
g_autoptr(GTimer) timer = NULL;
g_autoptr(DetectMinutiaeNbisData) ret_data = NULL;
g_autoptr(GTask) thread_task = g_steal_pointer (&task);
DetectMinutiaeData *data = task_data;
struct fp_minutiae *minutiae = NULL;
g_autofree gint *direction_map = NULL;
g_autofree gint *low_contrast_map = NULL;
g_autofree gint *low_flow_map = NULL;
g_autofree gint *high_curve_map = NULL;
g_autofree gint *quality_map = NULL;
g_autofree LFSPARMS *lfsparms = NULL;
FpImage *self = source_object;
FpiImageFlags minutiae_flags;
unsigned char *image;
g_autofree guchar *bdata = NULL;
gint map_w, map_h;
gint bw, bh, bd;
gint r;
image = self->data;
minutiae_flags = self->flags & ~(FPI_IMAGE_H_FLIPPED |
FPI_IMAGE_V_FLIPPED |
FPI_IMAGE_COLORS_INVERTED);
if (minutiae_flags != FPI_IMAGE_NONE)
image = g_memdup2 (self->data, self->width * self->height);
ret_data = g_new0 (DetectMinutiaeNbisData, 1);
ret_data->flags = minutiae_flags;
ret_data->image = image;
ret_data->image_changed = image != self->data;
g_autofree LFSPARMS *lfsparms = NULL;
/* Normalize the image first */
if (self->flags & FPI_IMAGE_H_FLIPPED)
hflip (image, self->width, self->height);
if (data->flags & FPI_IMAGE_H_FLIPPED)
hflip (data->image, data->width, data->height);
if (self->flags & FPI_IMAGE_V_FLIPPED)
vflip (image, self->width, self->height);
if (data->flags & FPI_IMAGE_V_FLIPPED)
vflip (data->image, data->width, data->height);
if (self->flags & FPI_IMAGE_COLORS_INVERTED)
invert_colors (image, self->width, self->height);
if (data->flags & FPI_IMAGE_COLORS_INVERTED)
invert_colors (data->image, data->width, data->height);
lfsparms = g_memdup2 (&g_lfsparms_V2, sizeof (LFSPARMS));
lfsparms->remove_perimeter_pts = minutiae_flags & FPI_IMAGE_PARTIAL ? TRUE : FALSE;
data->flags &= ~(FPI_IMAGE_H_FLIPPED | FPI_IMAGE_V_FLIPPED | FPI_IMAGE_COLORS_INVERTED);
lfsparms = g_memdup (&g_lfsparms_V2, sizeof (LFSPARMS));
lfsparms->remove_perimeter_pts = data->flags & FPI_IMAGE_PARTIAL ? TRUE : FALSE;
timer = g_timer_new ();
r = get_minutiae (&ret_data->minutiae, &quality_map, &direction_map,
r = get_minutiae (&minutiae, &quality_map, &direction_map,
&low_contrast_map, &low_flow_map, &high_curve_map,
&map_w, &map_h, &ret_data->binarized, &bw, &bh, &bd,
image, self->width, self->height, 8,
self->ppmm, lfsparms);
&map_w, &map_h, &bdata, &bw, &bh, &bd,
data->image, data->width, data->height, 8,
data->ppmm, lfsparms);
g_timer_stop (timer);
fp_dbg ("Minutiae scan completed in %f secs", g_timer_elapsed (timer, NULL));
if (g_task_had_error (thread_task))
return;
data->binarized = g_steal_pointer (&bdata);
data->minutiae = minutiae;
if (r)
{
fp_err ("get minutiae failed, code %d", r);
g_task_return_new_error (thread_task, G_IO_ERROR,
G_IO_ERROR_FAILED,
"Minutiae scan failed with code %d", r);
g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_FAILED, "Minutiae scan failed with code %d", r);
g_object_unref (task);
return;
}
if (!ret_data->minutiae || ret_data->minutiae->num == 0)
if (!data->minutiae || data->minutiae->num == 0)
{
g_task_return_new_error (thread_task, G_IO_ERROR, G_IO_ERROR_FAILED,
g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_FAILED,
"No minutiae found");
g_object_unref (task);
return;
}
g_task_return_pointer (thread_task, g_steal_pointer (&ret_data),
(GDestroyNotify) fp_image_detect_minutiae_free);
g_task_return_boolean (task, TRUE);
g_object_unref (task);
}
/**
@@ -463,25 +443,21 @@ fp_image_detect_minutiae (FpImage *self,
GAsyncReadyCallback callback,
gpointer user_data)
{
g_autoptr(GTask) task = NULL;
GTask *task;
DetectMinutiaeData *data = g_new0 (DetectMinutiaeData, 1);
g_return_if_fail (FP_IS_IMAGE (self));
g_return_if_fail (callback != NULL);
task = g_task_new (self, cancellable, fp_image_detect_minutiae_cb, user_data);
task = g_task_new (self, cancellable, callback, user_data);
g_task_set_source_tag (task, fp_image_detect_minutiae);
g_task_set_check_cancellable (task, TRUE);
data->image = g_malloc (self->width * self->height);
memcpy (data->image, self->data, self->width * self->height);
data->flags = self->flags;
data->width = self->width;
data->height = self->height;
data->ppmm = self->ppmm;
data->user_cb = callback;
if (!g_atomic_int_compare_and_exchange (&self->detection_in_progress,
FALSE, TRUE))
{
g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_ADDRESS_IN_USE,
"Minutiae detection is already in progress");
return;
}
g_task_run_in_thread (g_steal_pointer (&task),
fp_image_detect_minutiae_nbis_thread_func);
g_task_set_task_data (task, data, (GDestroyNotify) fp_image_detect_minutiae_free);
g_task_run_in_thread (task, fp_image_detect_minutiae_thread_func);
}
/**
@@ -499,27 +475,7 @@ fp_image_detect_minutiae_finish (FpImage *self,
GAsyncResult *result,
GError **error)
{
GTask *task;
gboolean changed;
g_return_val_if_fail (FP_IS_IMAGE (self), FALSE);
g_return_val_if_fail (g_task_is_valid (result, self), FALSE);
g_return_val_if_fail (g_task_get_source_tag (G_TASK (result)) ==
fp_image_detect_minutiae, FALSE);
task = G_TASK (result);
changed = g_atomic_int_compare_and_exchange (&self->detection_in_progress,
TRUE, FALSE);
g_assert (changed);
if (g_task_had_error (task))
{
gpointer data = g_task_propagate_pointer (task, error);
g_assert (data == NULL);
return FALSE;
}
return fp_image_detect_minutiae_nbis_finish (self, task, error);
return g_task_propagate_boolean (G_TASK (result), error);
}
/**
+85 -92
View File
@@ -339,7 +339,7 @@ fp_print_init (FpPrint *self)
* create a new print, fill in the relevant metadata, and then start
* enrollment.
*
* Returns: (transfer floating): A newly created #FpPrint
* Returns: (transfer floating): A newyl created #FpPrint
*/
FpPrint *
fp_print_new (FpDevice *device)
@@ -596,9 +596,6 @@ 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;
@@ -608,16 +605,18 @@ fp_print_equal (FpPrint *self, FpPrint *other)
if (g_strcmp0 (self->device_id, other->device_id))
return FALSE;
switch (self->type)
if (self->type == FPI_PRINT_RAW || self->type == FPI_PRINT_SDCP)
{
case FPI_PRINT_RAW:
return g_variant_equal (self->data, other->data);
}
else if (self->type == FPI_PRINT_NBIS)
{
guint i;
case FPI_PRINT_NBIS:
if (self->prints->len != other->prints->len)
return FALSE;
for (guint i = 0; i < self->prints->len; i++)
for (i = 0; i < self->prints->len; i++)
{
struct xyt_struct *a = g_ptr_array_index (self->prints, i);
struct xyt_struct *b = g_ptr_array_index (other->prints, i);
@@ -627,12 +626,11 @@ fp_print_equal (FpPrint *self, FpPrint *other)
}
return TRUE;
case FPI_PRINT_UNDEFINED:
}
else
{
g_assert_not_reached ();
}
g_return_val_if_reached (FALSE);
}
#define FPI_PRINT_VARIANT_TYPE G_VARIANT_TYPE ("(issbymsmsia{sv}v)")
@@ -723,12 +721,13 @@ fp_print_serialize (FpPrint *print,
result = g_variant_builder_end (&builder);
#if (G_BYTE_ORDER == G_BIG_ENDIAN)
GVariant *tmp;
tmp = g_variant_byteswap (result);
g_variant_unref (result);
result = tmp;
#endif
if (G_BYTE_ORDER == G_BIG_ENDIAN)
{
GVariant *tmp;
tmp = g_variant_byteswap (result);
g_variant_unref (result);
result = tmp;
}
len = g_variant_get_size (result);
/* Add 3 bytes of header */
@@ -767,7 +766,7 @@ fp_print_deserialize (const guchar *data,
g_autoptr(GVariant) value = NULL;
g_autoptr(GVariant) print_data = NULL;
g_autoptr(GDate) date = NULL;
g_autoptr(GBytes) bytes = NULL;
guchar *aligned_data = NULL;
guint8 finger_int8;
FpFinger finger;
g_autofree gchar *username = NULL;
@@ -789,19 +788,22 @@ fp_print_deserialize (const guchar *data,
* of this function (meaning we don't need to keep the data around.
*/
/* We need to copy the backing store for the raw data that we may keep for
* longer. Using a GBytes also ensures the data is correctly aligned. */
bytes = g_bytes_new (data + 3, length - 3);
raw_value = g_variant_new_from_bytes (FPI_PRINT_VARIANT_TYPE, bytes, FALSE);
/* To support GLIB < 2.60 we need to make sure that the memory is aligned correctly.
* We also need to copy the backing store for the raw data that we may keep for
* longer. */
aligned_data = g_malloc (length - 3);
memcpy (aligned_data, data + 3, length - 3);
raw_value = g_variant_new_from_data (FPI_PRINT_VARIANT_TYPE,
aligned_data, length - 3,
FALSE, g_free, aligned_data);
if (!raw_value)
goto invalid_format;
#if (G_BYTE_ORDER == G_BIG_ENDIAN)
value = g_variant_byteswap (raw_value);
#else
value = g_variant_get_normal_form (raw_value);
#endif
if (G_BYTE_ORDER == G_BIG_ENDIAN)
value = g_variant_byteswap (raw_value);
else
value = g_variant_get_normal_form (raw_value);
g_variant_get (value,
"(i&s&sbymsmsi@a{sv}v)",
@@ -819,81 +821,72 @@ fp_print_deserialize (const guchar *data,
finger = finger_int8;
/* Assume data is valid at this point if the values are somewhat sane. */
switch (type)
if (type == FPI_PRINT_NBIS)
{
case FPI_PRINT_NBIS:
{
g_autoptr(GVariant) prints = g_variant_get_child_value (print_data, 0);
guint i;
g_autoptr(GVariant) prints = g_variant_get_child_value (print_data, 0);
guint i;
result = g_object_new (FP_TYPE_PRINT,
"driver", driver,
"device-id", device_id,
"device-stored", device_stored,
NULL);
g_object_ref_sink (result);
fpi_print_set_type (result, FPI_PRINT_NBIS);
for (i = 0; i < g_variant_n_children (prints); i++)
{
g_autofree struct xyt_struct *xyt = NULL;
const gint32 *xcol, *ycol, *thetacol;
gsize xlen, ylen, thetalen;
g_autoptr(GVariant) xyt_data = NULL;
GVariant *child;
result = g_object_new (FP_TYPE_PRINT,
"driver", driver,
"device-id", device_id,
"device-stored", device_stored,
NULL);
g_object_ref_sink (result);
fpi_print_set_type (result, FPI_PRINT_NBIS);
for (i = 0; i < g_variant_n_children (prints); i++)
{
g_autofree struct xyt_struct *xyt = NULL;
const gint32 *xcol, *ycol, *thetacol;
gsize xlen, ylen, thetalen;
g_autoptr(GVariant) xyt_data = NULL;
GVariant *child;
xyt_data = g_variant_get_child_value (prints, i);
xyt_data = g_variant_get_child_value (prints, i);
child = g_variant_get_child_value (xyt_data, 0);
xcol = g_variant_get_fixed_array (child, &xlen, sizeof (gint32));
g_variant_unref (child);
child = g_variant_get_child_value (xyt_data, 0);
xcol = g_variant_get_fixed_array (child, &xlen, sizeof (gint32));
g_variant_unref (child);
child = g_variant_get_child_value (xyt_data, 1);
ycol = g_variant_get_fixed_array (child, &ylen, sizeof (gint32));
g_variant_unref (child);
child = g_variant_get_child_value (xyt_data, 1);
ycol = g_variant_get_fixed_array (child, &ylen, sizeof (gint32));
g_variant_unref (child);
child = g_variant_get_child_value (xyt_data, 2);
thetacol = g_variant_get_fixed_array (child, &thetalen, sizeof (gint32));
g_variant_unref (child);
child = g_variant_get_child_value (xyt_data, 2);
thetacol = g_variant_get_fixed_array (child, &thetalen, sizeof (gint32));
g_variant_unref (child);
if (xlen != ylen || xlen != thetalen)
goto invalid_format;
if (xlen != ylen || xlen != thetalen)
goto invalid_format;
if (xlen > G_N_ELEMENTS (xyt->xcol))
goto invalid_format;
if (xlen > G_N_ELEMENTS (xyt->xcol))
goto invalid_format;
xyt = g_new0 (struct xyt_struct, 1);
xyt->nrows = xlen;
memcpy (xyt->xcol, xcol, sizeof (xcol[0]) * xlen);
memcpy (xyt->ycol, ycol, sizeof (xcol[0]) * xlen);
memcpy (xyt->thetacol, thetacol, sizeof (xcol[0]) * xlen);
xyt = g_new0 (struct xyt_struct, 1);
xyt->nrows = xlen;
memcpy (xyt->xcol, xcol, sizeof (xcol[0]) * xlen);
memcpy (xyt->ycol, ycol, sizeof (xcol[0]) * xlen);
memcpy (xyt->thetacol, thetacol, sizeof (xcol[0]) * xlen);
g_ptr_array_add (result->prints, g_steal_pointer (&xyt));
}
}
break;
g_ptr_array_add (result->prints, g_steal_pointer (&xyt));
}
}
else if (type == FPI_PRINT_RAW || type == FPI_PRINT_SDCP)
{
g_autoptr(GVariant) fp_data = g_variant_get_child_value (print_data, 0);
case FPI_PRINT_RAW:
{
g_autoptr(GVariant) fp_data = g_variant_get_child_value (print_data, 0);
result = g_object_new (FP_TYPE_PRINT,
"fpi-type", type,
"driver", driver,
"device-id", device_id,
"device-stored", device_stored,
"fpi-data", fp_data,
NULL);
g_object_ref_sink (result);
}
break;
case FPI_PRINT_UNDEFINED:
{
g_autofree char *type_str = g_enum_to_string (fpi_print_type_get_type (), type);
g_warning ("Invalid print type: 0x%X (%s)", type, type_str);
goto invalid_format;
}
result = g_object_new (FP_TYPE_PRINT,
"fpi-type", type,
"driver", driver,
"device-id", device_id,
"device-stored", device_stored,
"fpi-data", fp_data,
NULL);
g_object_ref_sink (result);
}
else
{
g_warning ("Invalid print type: 0x%X", type);
goto invalid_format;
}
date = g_date_new_julian (julian_date);
+58
View File
@@ -0,0 +1,58 @@
/*
* FpSdcpDevice - A base class for SDCP enabled devices
* Copyright (C) 2020 Benjamin Berg <bberg@redhat.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#pragma once
#include "fpi-sdcp-device.h"
#include <nss.h>
#include <keyhi.h>
#include <keythi.h>
#include <pk11pub.h>
typedef struct
{
GError *enroll_pre_commit_error;
/* XXX: Do we want a separate SDCP session object?
*/
GPtrArray *intermediate_cas;
/* Host random for the connection */
guint8 host_random[32];
NSSInitContext *nss_init_context;
PK11SlotInfo *slot;
SECKEYPrivateKey *host_key_private;
SECKEYPublicKey *host_key_public;
/* Master secret is required for reconnects.
* TODO: We probably want to serialize this to disk so it can survive
* fprintd idle shutdown. */
PK11SymKey *master_secret;
PK11SymKey *mac_secret;
} FpSdcpDevicePrivate;
void fpi_sdcp_device_connect (FpSdcpDevice *self);
void fpi_sdcp_device_reconnect (FpSdcpDevice *self);
void fpi_sdcp_device_enroll (FpSdcpDevice *self);
void fpi_sdcp_device_identify (FpSdcpDevice *self);
+141
View File
@@ -0,0 +1,141 @@
/*
* FpSdcpDevice - A base class for SDCP enabled devices
* Copyright (C) 2020 Benjamin Berg <bberg@redhat.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#define FP_COMPONENT "sdcp_device"
#include "fpi-log.h"
#include "fp-sdcp-device-private.h"
/**
* SECTION: fp-sdcp-device
* @title: FpSdcpDevice
* @short_description: SDCP device subclass
*
* This is a base class for devices implementing the SDCP security protocol.
*/
G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (FpSdcpDevice, fp_sdcp_device, FP_TYPE_DEVICE)
#if 0
/* XXX: We'll very likely want/need some properties on this class. */
enum {
PROP_0,
N_PROPS
};
static GParamSpec *properties[N_PROPS];
#endif
/*******************************************************/
/* Callbacks/vfuncs */
static void
fp_sdcp_device_open (FpDevice *device)
{
FpSdcpDevice *self = FP_SDCP_DEVICE (device);
FpSdcpDevicePrivate *priv = fp_sdcp_device_get_instance_private (self);
/* Try a reconnect if we still have the mac secret. */
if (priv->mac_secret)
fpi_sdcp_device_reconnect (self);
else
fpi_sdcp_device_connect (self);
}
static void
fp_sdcp_device_enroll (FpDevice *device)
{
FpSdcpDevice *self = FP_SDCP_DEVICE (device);
fpi_sdcp_device_enroll (self);
}
static void
fp_sdcp_device_identify (FpDevice *device)
{
FpSdcpDevice *self = FP_SDCP_DEVICE (device);
fpi_sdcp_device_identify (self);
}
/*********************************************************/
static void
fp_sdcp_device_finalize (GObject *object)
{
FpSdcpDevice *self = (FpSdcpDevice *) object;
FpSdcpDevicePrivate *priv = fp_sdcp_device_get_instance_private (self);
g_clear_pointer (&priv->intermediate_cas, g_ptr_array_unref);
g_clear_pointer (&priv->slot, PK11_FreeSlot);
g_clear_pointer (&priv->host_key_private, SECKEY_DestroyPrivateKey);
g_clear_pointer (&priv->host_key_public, SECKEY_DestroyPublicKey);
g_clear_pointer (&priv->master_secret, PK11_FreeSymKey);
g_clear_pointer (&priv->mac_secret, PK11_FreeSymKey);
g_clear_pointer (&priv->nss_init_context, NSS_ShutdownContext);
G_OBJECT_CLASS (fp_sdcp_device_parent_class)->finalize (object);
}
static void
fp_sdcp_device_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
switch (prop_id)
{
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
static void
fp_sdcp_device_constructed (GObject *obj)
{
G_OBJECT_CLASS (fp_sdcp_device_parent_class)->constructed (obj);
}
static void
fp_sdcp_device_class_init (FpSdcpDeviceClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
FpDeviceClass *fp_device_class = FP_DEVICE_CLASS (klass);
object_class->finalize = fp_sdcp_device_finalize;
object_class->get_property = fp_sdcp_device_get_property;
object_class->constructed = fp_sdcp_device_constructed;
fp_device_class->open = fp_sdcp_device_open;
fp_device_class->enroll = fp_sdcp_device_enroll;
fp_device_class->verify = fp_sdcp_device_identify;
fp_device_class->identify = fp_sdcp_device_identify;
#if 0
g_object_class_install_properties (object_class, N_PROPS, properties);
#endif
}
static void
fp_sdcp_device_init (FpSdcpDevice *self)
{
FpSdcpDevicePrivate *priv = fp_sdcp_device_get_instance_private (self);
priv->intermediate_cas = g_ptr_array_new_with_free_func ((GDestroyNotify) g_bytes_unref);
}
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2026 Canonical, Ltd.
* FpSdcpDevice - A base class for SDCP enabled devices
* Copyright (C) 2020 Benjamin Berg <bberg@redhat.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -16,18 +17,13 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "fpi-device.h"
#include "fpi-test-emulation.h"
#pragma once
gboolean
(fpi_device_emulation_mode_enabled) (FpDevice *device)
{
static gsize emulation_mode = 0;
#include <fp-device.h>
if (g_once_init_enter (&emulation_mode))
g_once_init_leave (&emulation_mode,
g_strcmp0 (g_getenv (FPI_EMULATION_ENV_VAR), "1") == 0 ?
TRUE : G_MAXSIZE);
G_BEGIN_DECLS
return emulation_mode == TRUE;
}
#define FP_TYPE_SDCP_DEVICE (fp_sdcp_device_get_type ())
G_DECLARE_DERIVABLE_TYPE (FpSdcpDevice, fp_sdcp_device, FP, SDCP_DEVICE, FpDevice)
G_END_DECLS
+1 -85
View File
@@ -65,31 +65,6 @@ fpi_byte_reader_new (const guint8 * data, guint size)
return ret;
}
/**
* fpi_byte_reader_new_bytes: (skip)
* @bytes: (in) (transfer none): a #GBytes instance from which the
* #FpiByteReader should read
*
* Create a new #FpiByteReader instance, which will read from @bytes.
*
* Free-function: fpi_byte_reader_free
*
* Returns: (transfer full): a new #FpiByteReader instance
*/
FpiByteReader *
fpi_byte_reader_new_bytes (GBytes * bytes)
{
const guint8 *data;
gsize size = 0;
g_return_val_if_fail (bytes != NULL, NULL);
data = g_bytes_get_data (bytes, &size);
g_return_val_if_fail (size <= G_MAXUINT, NULL);
return fpi_byte_reader_new (data, (guint) size);
}
/**
* fpi_byte_reader_free:
* @reader: (in) (transfer full): a #FpiByteReader instance
@@ -125,30 +100,6 @@ fpi_byte_reader_init (FpiByteReader * reader, const guint8 * data, guint size)
reader->byte = 0;
}
/**
* fpi_byte_reader_init_bytes:
* @reader: a #FpiByteReader instance
* @bytes: (in) (transfer none): a #GBytes instance from which
* the #FpiByteReader should read
*
* Initializes a #FpiByteReader instance to read from @bytes. This function
* can be called on already initialized instances.
*/
FpiByteReader *
fpi_byte_reader_init_bytes (FpiByteReader * reader, GBytes * bytes)
{
g_return_val_if_fail (reader != NULL, NULL);
g_return_val_if_fail (bytes != NULL, NULL);
gsize size = 0;
const guint8 *data = g_bytes_get_data (bytes, &size);
g_return_val_if_fail (size <= G_MAXUINT, NULL);
fpi_byte_reader_init (reader, data, (guint) size);
return reader;
}
/**
* fpi_byte_reader_peek_sub_reader: (skip)
* @reader: an existing and initialized #FpiByteReader instance
@@ -848,41 +799,6 @@ fpi_byte_reader_peek_data (const FpiByteReader * reader, guint size,
return fpi_byte_reader_peek_data_inline (reader, size, val);
}
/**
* fpi_byte_reader_get_data_fixed:
* @reader: a #FpiByteReader instance
* @size: Size in bytes
* @val: (out) (array length=size): address of a buffer to copy data into
*
* Copies @size bytes from the current data position into @val if at
* least @size bytes are left, and updates the current position.
*
* Returns: %TRUE if successful, %FALSE otherwise.
*/
gboolean
(fpi_byte_reader_get_data_static) (FpiByteReader * reader, guint size,
const guint8 * val)
{
return (fpi_byte_reader_get_data_inline_static) (reader, size, val);
}
/**
* fpi_byte_reader_peek_data_fixed:
* @reader: a #FpiByteReader instance
* @size: Size in bytes
* @val: (out) (array length=size): address of a buffer to copy data into
*
* Like fpi_byte_reader_get_data_fixed() but does not advance the position.
*
* Returns: %TRUE if successful, %FALSE otherwise.
*/
gboolean
(fpi_byte_reader_peek_data_static) (const FpiByteReader * reader, guint size,
guint8 * val)
{
return (fpi_byte_reader_peek_data_inline_static) (reader, size, val);
}
/**
* fpi_byte_reader_dup_data:
* @reader: a #FpiByteReader instance
@@ -1265,7 +1181,7 @@ fpi_byte_reader_dup_string_utf##bits (FpiByteReader * reader, type ** str) \
*str = NULL; \
return FALSE; \
} \
*str = g_memdup2 (reader->data + reader->byte, size); \
*str = g_memdup (reader->data + reader->byte, size); \
reader->byte += size; \
return TRUE; \
}
+1 -104
View File
@@ -22,7 +22,6 @@
#pragma once
#include <glib.h>
#include "fpi-compat.h"
#include "fpi-byte-utils.h"
G_BEGIN_DECLS
@@ -50,7 +49,6 @@ typedef struct {
FpiByteReader * fpi_byte_reader_new (const guint8 *data, guint size) G_GNUC_MALLOC;
FpiByteReader * fpi_byte_reader_new_bytes (GBytes *bytes) G_GNUC_MALLOC;
void fpi_byte_reader_free (FpiByteReader *reader);
@@ -58,9 +56,6 @@ void fpi_byte_reader_free (FpiByteReader *reader);
void fpi_byte_reader_init (FpiByteReader *reader, const guint8 *data, guint size);
FpiByteReader * fpi_byte_reader_init_bytes (FpiByteReader *reader, GBytes *bytes);
gboolean fpi_byte_reader_peek_sub_reader (FpiByteReader * reader,
FpiByteReader * sub_reader,
guint size);
@@ -222,21 +217,8 @@ gboolean fpi_byte_reader_dup_data (FpiByteReader * reader, guint s
gboolean fpi_byte_reader_get_data (FpiByteReader * reader, guint size, const guint8 ** val);
gboolean fpi_byte_reader_get_data_static (FpiByteReader * reader, guint size, const guint8 * val);
gboolean fpi_byte_reader_peek_data (const FpiByteReader * reader, guint size, const guint8 ** val);
gboolean fpi_byte_reader_peek_data_static (const FpiByteReader * reader, guint size, guint8 * val);
GBytes * fpi_byte_reader_get_bytes (FpiByteReader *reader, guint size);
GBytes * fpi_byte_reader_peek_bytes (const FpiByteReader *reader, guint size);
#define fpi_byte_reader_dup_string(reader,str) \
fpi_byte_reader_dup_string_utf8(reader,str)
@@ -378,7 +360,7 @@ static inline guint8 *
fpi_byte_reader_dup_data_unchecked (FpiByteReader * reader, guint size)
{
gconstpointer data = fpi_byte_reader_get_data_unchecked (reader, size);
return (guint8 *) g_memdup2 (data, size);
return (guint8 *) g_memdup (data, size);
}
/* Unchecked variants that should not be used */
@@ -659,60 +641,6 @@ fpi_byte_reader_peek_data_inline (const FpiByteReader * reader, guint size, cons
return TRUE;
}
static inline GBytes *
fpi_byte_reader_peek_bytes_inline (const FpiByteReader *reader, guint size)
{
const guint8 *data;
g_return_val_if_fail (reader != NULL, NULL);
if (G_UNLIKELY (size > reader->size || fpi_byte_reader_get_remaining_unchecked (reader) < size))
return NULL;
data = fpi_byte_reader_peek_data_unchecked (reader);
return g_bytes_new_static (data, size);
}
static inline GBytes *
fpi_byte_reader_get_bytes_inline (FpiByteReader *reader, guint size)
{
const guint8 *data;
g_return_val_if_fail (reader != NULL, NULL);
if (G_UNLIKELY (size > reader->size || fpi_byte_reader_get_remaining_unchecked (reader) < size))
return NULL;
data = fpi_byte_reader_get_data_unchecked (reader, size);
return g_bytes_new_static (data, size);
}
static inline gboolean
(fpi_byte_reader_get_data_inline_static) (FpiByteReader * reader, guint size, const guint8 * val)
{
g_return_val_if_fail (reader != NULL, FALSE);
g_return_val_if_fail (val != NULL, FALSE);
if (G_UNLIKELY (size > reader->size || fpi_byte_reader_get_remaining_unchecked (reader) < size))
return FALSE;
memcpy ((void *) val, fpi_byte_reader_get_data_unchecked (reader, size), size);
return TRUE;
}
static inline gboolean
(fpi_byte_reader_peek_data_inline_static) (const FpiByteReader * reader, guint size, guint8 * val)
{
g_return_val_if_fail (reader != NULL, FALSE);
g_return_val_if_fail (val != NULL, FALSE);
if (G_UNLIKELY (size > reader->size || fpi_byte_reader_get_remaining_unchecked (reader) < size))
return FALSE;
memcpy (val, fpi_byte_reader_peek_data_unchecked (reader), size);
return TRUE;
}
static inline guint
fpi_byte_reader_get_pos_inline (const FpiByteReader * reader)
{
@@ -743,38 +671,7 @@ fpi_byte_reader_skip_inline (FpiByteReader * reader, guint nbytes)
G_LIKELY(fpi_byte_reader_peek_data_inline(reader,size,val))
#define fpi_byte_reader_skip(reader,nbytes) \
G_LIKELY(fpi_byte_reader_skip_inline(reader,nbytes))
#define fpi_byte_reader_get_bytes(reader,size) \
fpi_byte_reader_get_bytes_inline(reader,size)
#define fpi_byte_reader_peek_bytes(reader,size) \
fpi_byte_reader_peek_bytes_inline(reader,size)
/**
* fpi_byte_reader_get_data_static:
* @reader: a #FpiByteReader
* @val: fixed-size array (e.g. `uint8_t buf[32]`)
*
* Reads @size bytes from @reader directly into @val, where @size is
* deduced via `sizeof()` - only safe with true C arrays.
*
* Returns: %TRUE on success, %FALSE otherwise.
*/
#define fpi_byte_reader_get_data_static(reader,val) \
(fpi_byte_reader_get_data_static) (reader,sizeof(val),val)
/**
* fpi_byte_reader_peek_data_static:
* @reader: a #FpiByteReader
* @val: fixed-size array (e.g. `uint8_t buf[32]`)
*
* Like fpi_byte_reader_get_data_static() but does not advance the position.
*
* Returns: %TRUE on success, %FALSE otherwise.
*/
#define fpi_byte_reader_peek_data_static(reader,val) \
(fpi_byte_reader_peek_data_static) (reader,sizeof(val),val)
#endif /* FPI_BYTE_READER_DISABLE_INLINES */
G_DEFINE_AUTOPTR_CLEANUP_FUNC (FpiByteReader, fpi_byte_reader_free);
G_END_DECLS
+5 -45
View File
@@ -75,8 +75,7 @@ fpi_byte_writer_new_with_size (guint size, gboolean fixed)
FpiByteWriter *ret = fpi_byte_writer_new ();
ret->alloc_size = size;
ret->parent.data = g_malloc0 (ret->alloc_size);
ret->parent.size = size;
ret->parent.data = g_malloc (ret->alloc_size);
ret->fixed = fixed;
ret->owned = TRUE;
@@ -143,8 +142,7 @@ fpi_byte_writer_init_with_size (FpiByteWriter * writer, guint size,
fpi_byte_writer_init (writer);
writer->parent.data = g_malloc0 (size);
writer->parent.size = size;
writer->parent.data = g_malloc (size);
writer->alloc_size = size;
writer->fixed = fixed;
writer->owned = TRUE;
@@ -211,44 +209,15 @@ fpi_byte_writer_reset_and_get_data (FpiByteWriter * writer)
g_return_val_if_fail (writer != NULL, NULL);
data = (guint8 *) g_steal_pointer (&writer->parent.data);
data = (guint8 *) writer->parent.data;
if (!writer->owned)
data = g_memdup2 (data, writer->parent.size);
data = g_memdup (data, writer->parent.size);
writer->parent.data = NULL;
fpi_byte_writer_reset (writer);
return data;
}
/**
* fpi_byte_writer_reset_and_get_bytes:
* @writer: #FpiByteWriter instance
*
* Resets @writer and returns the current data as a #GBytes.
*
* Returns: (transfer full): the current data as a #GBytes.
*/
GBytes *
fpi_byte_writer_reset_and_get_bytes (FpiByteWriter * writer)
{
GBytes *bytes;
g_return_val_if_fail (writer != NULL, NULL);
if (!writer->owned)
{
bytes = g_bytes_new (g_steal_pointer (&writer->parent.data),
writer->parent.size);
}
else
{
bytes = g_bytes_new_take ((gpointer) g_steal_pointer (&writer->parent.data),
writer->parent.size);
}
fpi_byte_writer_reset (writer);
return g_steal_pointer (&bytes);
}
/**
* fpi_byte_writer_free:
* @writer: (in) (transfer full): #FpiByteWriter instance
@@ -632,15 +601,6 @@ CREATE_WRITE_STRING_FUNC (32, guint32);
*
* Returns: %TRUE if the value could be written
*/
/**
* fpi_byte_writer_put_bytes:
* @writer: #FpiByteWriter instance
* @bytes: (transfer none): Data to write
*
* Writes the contents of @bytes to @writer.
*
* Returns: %TRUE if the value could be written
*/
/**
* fpi_byte_writer_fill:
* @writer: #FpiByteWriter instance
-36
View File
@@ -77,9 +77,6 @@ void fpi_byte_writer_reset (FpiByteWriter *writer);
guint8 * fpi_byte_writer_reset_and_get_data (FpiByteWriter *writer);
GBytes * fpi_byte_writer_reset_and_get_bytes (FpiByteWriter *writer);
/**
* fpi_byte_writer_get_pos:
* @writer: #FpiByteWriter instance
@@ -114,17 +111,6 @@ fpi_byte_writer_set_pos (FpiByteWriter *writer, guint pos)
return fpi_byte_reader_set_pos (FPI_BYTE_READER (writer), pos);
}
static inline gboolean
fpi_byte_writer_change_pos (FpiByteWriter *writer, gint pos)
{
pos = fpi_byte_writer_get_pos (writer) + pos;
if (pos < 0)
return FALSE;
return fpi_byte_reader_set_pos (FPI_BYTE_READER (writer), pos);
}
static inline guint
fpi_byte_writer_get_size (const FpiByteWriter *writer)
{
@@ -207,9 +193,6 @@ gboolean fpi_byte_writer_put_float64_le (FpiByteWriter *writer, gdoubl
gboolean fpi_byte_writer_put_data (FpiByteWriter *writer, const guint8 *data, guint size);
gboolean fpi_byte_writer_put_bytes (FpiByteWriter *writer, const GBytes *bytes);
gboolean fpi_byte_writer_fill (FpiByteWriter *writer, guint8 value, guint size);
@@ -344,18 +327,6 @@ fpi_byte_writer_put_data_inline (FpiByteWriter * writer, const guint8 * data,
return TRUE;
}
static inline gboolean
fpi_byte_writer_put_bytes_inline (FpiByteWriter * writer, const GBytes * bytes)
{
g_return_val_if_fail (writer != NULL, FALSE);
g_return_val_if_fail (bytes != NULL, FALSE);
const guint8 *data;
gsize size;
data = g_bytes_get_data ((GBytes *) bytes, &size);
return fpi_byte_writer_put_data_inline (writer, data, size);
}
static inline void
fpi_byte_writer_fill_unchecked (FpiByteWriter * writer, guint8 value, guint size)
{
@@ -431,16 +402,9 @@ fpi_byte_writer_fill_inline (FpiByteWriter * writer, guint8 value, guint size)
#define fpi_byte_writer_put_data(writer, data, size) \
G_LIKELY (fpi_byte_writer_put_data_inline (writer, data, size))
#define fpi_byte_writer_put_data_static(writer, data) \
G_LIKELY (fpi_byte_writer_put_data_inline (writer, data, sizeof (data)))
#define fpi_byte_writer_put_bytes(writer, bytes) \
G_LIKELY (fpi_byte_writer_put_bytes_inline (writer, bytes))
#define fpi_byte_writer_fill(writer, val, size) \
G_LIKELY (fpi_byte_writer_fill_inline (writer, val, size))
#endif
G_DEFINE_AUTOPTR_CLEANUP_FUNC (FpiByteWriter, fpi_byte_writer_free);
G_DEFINE_AUTO_CLEANUP_CLEAR_FUNC (FpiByteWriter, fpi_byte_writer_reset);
G_END_DECLS
+19
View File
@@ -20,6 +20,25 @@
#include <glib-object.h>
#if !GLIB_CHECK_VERSION (2, 57, 0)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (GTypeClass, g_type_class_unref);
G_DEFINE_AUTOPTR_CLEANUP_FUNC (GEnumClass, g_type_class_unref);
G_DEFINE_AUTOPTR_CLEANUP_FUNC (GFlagsClass, g_type_class_unref);
G_DEFINE_AUTOPTR_CLEANUP_FUNC (GParamSpec, g_param_spec_unref);
#else
/* Re-define G_SOURCE_FUNC as we are technically not allowed to use it with
* the version we depend on currently. */
#undef G_SOURCE_FUNC
#endif
#define G_SOURCE_FUNC(f) ((GSourceFunc) (void (*)(void))(f))
#if !GLIB_CHECK_VERSION (2, 63, 3)
typedef struct _FpDeviceClass FpDeviceClass;
G_DEFINE_AUTOPTR_CLEANUP_FUNC (FpDeviceClass, g_type_class_unref);
G_DEFINE_AUTOPTR_CLEANUP_FUNC (GDate, g_date_free);
#endif
#if __GNUC__ > 10 || (__GNUC__ == 10 && __GNUC_MINOR__ >= 1)
#define FP_GNUC_ACCESS(m, p, s) __attribute__((access (m, p, s)))
#else
+162 -505
View File
File diff suppressed because it is too large Load Diff
+2 -16
View File
@@ -38,13 +38,6 @@ typedef enum {
/**
* FpIdEntry:
* @pid: The USB product ID (for USB devices)
* @vid: The USB vendor ID (for USB devices)
* @virtual_envvar: Environment variable name (for virtual devices)
* @driver_data: Optional driver-specific data, defaults to 0
* @udev_types: Subtypes for udev-based devices
* @spi_acpi_id: ACPI ID (for SPI devices)
* @hid_id: HID device identifier (for HID devices)
*
* An entry in the table of supported hardware. For USB devices, the product ID
* and vendor ID should be provided. The optional @driver_data field defaults
@@ -107,8 +100,7 @@ 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 (it will be implemented via @identify
* if not overriden).
* @verify: Start a verify operation
* @identify: Start an identify operation
* @capture: Start a capture operation
* @list: List prints stored on the device
@@ -229,6 +221,7 @@ 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);
@@ -332,11 +325,4 @@ gboolean fpi_device_report_finger_status_changes (FpDevice *device,
FpFingerStatusFlags added_status,
FpFingerStatusFlags removed_status);
/* Debugging utilities */
#define fpi_device_emulation_mode_enabled(dev) \
G_UNLIKELY ((fpi_device_emulation_mode_enabled) ((dev)))
gboolean (fpi_device_emulation_mode_enabled) (FpDevice *device);
G_END_DECLS
+41 -21
View File
@@ -120,13 +120,10 @@ fp_image_device_change_state (FpImageDevice *self, FpiImageDeviceState state)
{ FPI_IMAGE_DEVICE_STATE_DEACTIVATING, FPI_IMAGE_DEVICE_STATE_INACTIVE },
};
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);
}
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++)
{
@@ -137,15 +134,8 @@ fp_image_device_change_state (FpImageDevice *self, FpiImageDeviceState state)
}
}
if (!transition_is_valid)
{
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);
}
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");
@@ -224,6 +214,10 @@ 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);
@@ -322,6 +316,22 @@ 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;
@@ -476,6 +486,7 @@ 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);
@@ -516,6 +527,7 @@ 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);
@@ -528,6 +540,13 @@ 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);
@@ -546,7 +565,7 @@ fpi_image_device_retry_scan (FpImageDevice *self, FpDeviceRetry retry)
/**
* fpi_image_device_session_error:
* @self: a #FpImageDevice imaging fingerprint device
* @error: (nullable) (transfer full): The #GError to report.
* @error: The #GError to report
*
* Report an error while interacting with the device. This effectively
* aborts the current ongoing action. Note that doing so will result in
@@ -605,7 +624,7 @@ fpi_image_device_session_error (FpImageDevice *self, GError *error)
/**
* fpi_image_device_activate_complete:
* @self: a #FpImageDevice imaging fingerprint device
* @error: (nullable) (transfer full): The #GError or %NULL on success
* @error: A #GError or %NULL on success
*
* Reports completion of device activation.
*/
@@ -620,6 +639,7 @@ 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);
@@ -643,7 +663,7 @@ fpi_image_device_activate_complete (FpImageDevice *self, GError *error)
/**
* fpi_image_device_deactivate_complete:
* @self: a #FpImageDevice imaging fingerprint device
* @error: (nullable) (transfer full): The #GError or %NULL on success
* @error: A #GError or %NULL on success
*
* Reports completion of device deactivation.
*/
@@ -670,7 +690,7 @@ fpi_image_device_deactivate_complete (FpImageDevice *self, GError *error)
/**
* fpi_image_device_open_complete:
* @self: a #FpImageDevice imaging fingerprint device
* @error: (nullable) (transfer full): The #GError or %NULL on success
* @error: A #GError or %NULL on success
*
* Reports completion of open operation.
*/
@@ -698,7 +718,7 @@ fpi_image_device_open_complete (FpImageDevice *self, GError *error)
/**
* fpi_image_device_close_complete:
* @self: a #FpImageDevice imaging fingerprint device
* @error: (nullable) (transfer full): The #GError or %NULL on success
* @error: A #GError or %NULL on success
*
* Reports completion of close operation.
*/
+3 -8
View File
@@ -24,9 +24,8 @@
#include "fpi-log.h"
#include <nbis.h>
#include <config.h>
#ifdef HAVE_PIXMAN
#if HAVE_PIXMAN
#include <pixman.h>
#endif
@@ -108,12 +107,12 @@ fpi_mean_sq_diff_norm (const guint8 *buf1,
return res / size;
}
#if HAVE_PIXMAN
FpImage *
fpi_image_resize (FpImage *orig_img,
guint w_factor,
guint h_factor)
{
#ifdef HAVE_PIXMAN
int new_width = orig_img->width * w_factor;
int new_height = orig_img->height * h_factor;
pixman_image_t *orig, *resized;
@@ -146,9 +145,5 @@ fpi_image_resize (FpImage *orig_img,
pixman_image_unref (resized);
return newimg;
#else
fp_err ("Libfprint compiled without pixman support, impossible to resize");
return g_object_ref (orig_img);
#endif
}
#endif
+4 -4
View File
@@ -20,6 +20,7 @@
#pragma once
#include <config.h>
#include "fp-image.h"
/**
@@ -27,14 +28,12 @@
* @FPI_IMAGE_V_FLIPPED: the image is vertically flipped
* @FPI_IMAGE_H_FLIPPED: the image is horizontally flipped
* @FPI_IMAGE_COLORS_INVERTED: the colours are inverted
* @FPI_IMAGE_PARTIAL: the image is a partial scan
*
* Flags used in an #FpImage structure to describe the contained image.
* This is useful for image drivers as they can simply set these flags and
* rely on the image to be normalized by libfprint before further processing.
*/
typedef enum {
FPI_IMAGE_NONE = 0,
FPI_IMAGE_V_FLIPPED = 1 << 0,
FPI_IMAGE_H_FLIPPED = 1 << 1,
FPI_IMAGE_COLORS_INVERTED = 1 << 2,
@@ -69,8 +68,7 @@ struct _FpImage
guint8 *binarized;
GPtrArray *minutiae;
gboolean detection_in_progress;
guint ref_count;
};
gint fpi_std_sq_dev (const guint8 *buf,
@@ -79,6 +77,8 @@ gint fpi_mean_sq_diff_norm (const guint8 *buf1,
const guint8 *buf2,
gint size);
#if HAVE_PIXMAN
FpImage *fpi_image_resize (FpImage *orig,
guint w_factor,
guint h_factor);
#endif
-88
View File
@@ -1,88 +0,0 @@
/*
* FpiLog - Internal logging functions
* Copyright (C) 2020 Benjamin Berg <bberg@redhat.com>
* Copyright (C) 2025 Joshua Grisham <josh@joshuagrisham.com>
* Copyright (C) 2026 Marco Trevisan (Treviño) <mail@3v1n0.net>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "fpi-log.h"
/**
* fpi_log_is_debug_transfer_enabled:
*
* Checks if the %FP_DEBUG_TRANSFER environment variable is set.
*
* Returns: %TRUE if %FP_DEBUG_TRANSFER is set, %FALSE otherwise
*/
gboolean
fpi_log_is_debug_transfer_enabled (void)
{
static gsize debug_transfer_enabled = 0;
if (g_once_init_enter (&debug_transfer_enabled))
{
gsize enabled = g_getenv ("FP_DEBUG_TRANSFER") != NULL ? TRUE : G_MAXSIZE;
g_once_init_leave (&debug_transfer_enabled, enabled);
}
return debug_transfer_enabled == TRUE;
}
/**
* fpi_dbg_hex_dump_data:
* @buf: Bytes buffer to dump
* @len: Length of @buf to dump
*
* Prints hex dump of @buf to fp_dbg()
*/
void
(fpi_dbg_hex_dump_data) (const gchar *log_domain,
const guint8 *buf,
gsize len)
{
g_autoptr(GString) line = NULL;
if (g_log_writer_default_would_drop (G_LOG_LEVEL_DEBUG, log_domain))
return;
if (G_UNLIKELY (len == 0 || !buf))
return;
line = g_string_new ("");
for (gint i = 0; i < len; i++)
g_string_append_printf (line, "%02x", buf[i]);
if (line->len)
g_log (log_domain, G_LOG_LEVEL_DEBUG, "%s", line->str);
}
/**
* fpi_dbg_hex_dump_bytes:
* @bytes: #GBytes to dump
*
* Prints hex dump of @bytes to fp_dbg()
*/
void
(fpi_dbg_hex_dump_bytes) (const gchar *log_domain,
GBytes *bytes)
{
gsize length = 0;
const guint8 *data = g_bytes_get_data (bytes, &length);
(fpi_dbg_hex_dump_data) (log_domain, data, length);
}
+3 -36
View File
@@ -1,7 +1,6 @@
/*
* Copyright (C) 2007-2008 Daniel Drake <dsd@gentoo.org>
* Copyright (C) 2018 Bastien Nocera <hadess@hadess.net>
* Copyright (C) 2026 Marco Trevisan (Treviño) <mail@3v1n0.net>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -80,16 +79,13 @@
*
* Uses fp_err() to print an error if the @condition is true.
*/
#define BUG_ON(condition) \
G_STMT_START \
if (condition) \
{ \
#define BUG_ON(condition) G_STMT_START \
if (condition) { \
char *s; \
s = g_strconcat ("BUG: (", #condition, ")", NULL); \
fp_err ("%s: %s() %s:%d", s, G_STRFUNC, __FILE__, __LINE__); \
g_free (s); \
} \
G_STMT_END
} G_STMT_END
/**
* BUG:
@@ -97,32 +93,3 @@
* Same as BUG_ON() but is always true.
*/
#define BUG() BUG_ON (1)
void (fpi_dbg_hex_dump_data) (const gchar *log_domain,
const guint8 *buf,
gsize len);
/**
* fp_dbg_hex_dump_data:
* @buf: Bytes buffer to dump
* @len: Length of @buf to dump
*
* Prints hex dump of @buf to fp_dbg()
*/
#define fp_dbg_hex_dump_data(buf, len) \
(fpi_dbg_hex_dump_data) (G_LOG_DOMAIN, (buf), (len))
void (fpi_dbg_hex_dump_bytes) (const gchar *log_domain,
GBytes *bytes);
/**
* fp_dbg_hex_dump_bytes:
* @bytes: #GBytes to dump
*
* Prints hex dump of @bytes to fp_dbg()
*/
#define fp_dbg_hex_dump_bytes(bytes) \
(fpi_dbg_hex_dump_bytes) \
(G_LOG_DOMAIN, (bytes))
gboolean fpi_log_is_debug_transfer_enabled (void);
+7 -26
View File
@@ -50,7 +50,7 @@ fpi_print_add_print (FpPrint *print, FpPrint *add)
g_return_if_fail (add->type == FPI_PRINT_NBIS);
g_assert (add->prints->len == 1);
g_ptr_array_add (print->prints, g_memdup2 (add->prints->pdata[0], sizeof (struct xyt_struct)));
g_ptr_array_add (print->prints, g_memdup (add->prints->pdata[0], sizeof (struct xyt_struct)));
}
/**
@@ -79,22 +79,6 @@ 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
@@ -212,7 +196,7 @@ fpi_print_add_from_image (FpPrint *print,
/**
* fpi_print_bz3_match:
* @print_template: A #FpPrint containing one or more prints
* @template: A #FpPrint containing one or more prints
* @print: A newly scanned #FpPrint to test
* @bz3_threshold: The BZ3 match threshold
* @error: Return location for error
@@ -226,17 +210,14 @@ fpi_print_add_from_image (FpPrint *print,
* Returns: Whether the prints match, @error will be set if #FPI_MATCH_ERROR is returned
*/
FpiMatchResult
fpi_print_bz3_match (FpPrint *print_template,
FpPrint *print,
gint bz3_threshold,
GError **error)
fpi_print_bz3_match (FpPrint *template, FpPrint *print, gint bz3_threshold, GError **error)
{
struct xyt_struct *pstruct;
gint probe_len;
gint i;
/* XXX: Use a different error type? */
if (print_template->type != FPI_PRINT_NBIS || print->type != FPI_PRINT_NBIS)
if (template->type != FPI_PRINT_NBIS || print->type != FPI_PRINT_NBIS)
{
*error = fpi_device_error_new_msg (FP_DEVICE_ERROR_NOT_SUPPORTED,
"It is only possible to match NBIS type print data");
@@ -253,11 +234,11 @@ fpi_print_bz3_match (FpPrint *print_template,
pstruct = g_ptr_array_index (print->prints, 0);
probe_len = bozorth_probe_init (pstruct);
for (i = 0; i < print_template->prints->len; i++)
for (i = 0; i < template->prints->len; i++)
{
struct xyt_struct *gstruct;
gint score;
gstruct = g_ptr_array_index (print_template->prints, i);
gstruct = g_ptr_array_index (template->prints, i);
score = bozorth_to_gallery (probe_len, pstruct, gstruct);
fp_dbg ("score %d/%d", score, bz3_threshold);
@@ -311,7 +292,7 @@ fpi_print_generate_user_id (FpPrint *print)
if (!username)
username = "nobody";
if (fpi_device_emulation_mode_enabled (NULL))
if (g_strcmp0 (g_getenv ("FP_DEVICE_EMULATION"), "1") == 0)
rand_id = 0;
else
rand_id = g_random_int ();
+5 -6
View File
@@ -11,11 +11,13 @@ G_BEGIN_DECLS
* @FPI_PRINT_UNDEFINED: Undefined type, this happens prior to enrollment
* @FPI_PRINT_RAW: A raw print where the data is directly compared
* @FPI_PRINT_NBIS: NBIS minutiae comparison
* @FPI_PRINT_SDCP: Print from an SDCP conforming device
*/
typedef enum {
FPI_PRINT_UNDEFINED = 0,
FPI_PRINT_RAW,
FPI_PRINT_NBIS,
FPI_PRINT_SDCP,
} FpiPrintType;
/**
@@ -35,9 +37,6 @@ 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);
@@ -45,9 +44,9 @@ gboolean fpi_print_add_from_image (FpPrint *print,
FpImage *image,
GError **error);
FpiMatchResult fpi_print_bz3_match (FpPrint *print_template,
FpPrint *print,
gint bz3_threshold,
FpiMatchResult fpi_print_bz3_match (FpPrint * template,
FpPrint * print,
gint bz3_threshold,
GError **error);
/* Helpers to encode metadata into user ID strings. */
File diff suppressed because it is too large Load Diff
+142
View File
@@ -0,0 +1,142 @@
/*
* FpSdcpDevice - A base class for SDCP enabled devices
* Copyright (C) 2020 Benjamin Berg <bberg@redhat.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#pragma once
#include <glib-2.0/glib.h>
#include "fpi-device.h"
#include "fp-sdcp-device.h"
/**
* FpiSdcpClaim:
* @cert_m: The per-model ECDSA certificate (x509 ASN.1 DER encoded)
* @pk_d: The device public key (65 bytes)
* @pk_f: The firmware public key (65 bytes)
* @h_f: The firmware hash
* @s_m: Signature over @pk_d using the per-model private key (64 bytes)
* @s_d: Signature over h_f and pk_f using the device private key (64 bytes)
*
* Structure to hold the claim as produced by the device during a secure
* connect. See the SDCP specification for more details.
*
* Note all of these may simply be memory views into a larger #GBytes created
* using g_bytes_new_from_bytes().
*/
struct _FpiSdcpClaim
{
/*< public >*/
GBytes *cert_m;
GBytes *pk_d;
GBytes *pk_f;
GBytes *h_f;
GBytes *s_m;
GBytes *s_d;
};
typedef struct _FpiSdcpClaim FpiSdcpClaim;
GType fpi_sdcp_claim_get_type (void) G_GNUC_CONST;
FpiSdcpClaim *fpi_sdcp_claim_new (void);
FpiSdcpClaim *fpi_sdcp_claim_copy (FpiSdcpClaim *other);
void fpi_sdcp_claim_free (FpiSdcpClaim *claim);
G_DEFINE_AUTOPTR_CLEANUP_FUNC (FpiSdcpClaim, fpi_sdcp_claim_free)
/**
* FpSdcpDeviceClass:
* @connect: Establish SDCP connection. Similar to open in #FpDeviceClass
* but called connect to mirror the SDCP specification.
* @reconnect: Perform a faster reconnect. Drivers do not need to provide this
* function. If reconnect fails, then a normal connect will be tried.
* @enroll_begin: Start the enrollment procedure. In the absence of an error,
* the driver must call fpi_sdcp_device_enroll_set_nonce() at any point. It
* also must report enrollment progress using fpi_device_enroll_progress().
* It should also store available metadata about the print in device memory.
* The operation is completed with fpi_sdcp_device_enroll_ready().
* @enroll_commit: Complete the enrollment procedure. This commits the newly
* enrolled print to the device memory. Will only be called if enroll_begin
* succeeded. The passed id may be %NULL, in that case the driver must
* abort the enrollment process. id is owned by the base class and remains
* valid throughout the operation.
* @identify: Start identification process. On completion, the driver must call
* fpi_sdcp_device_identify_complete(). To request the user to retry the
* fpi_sdcp_device_identify_retry() function is used.
*
*
* These are the main entry points for drivers implementing SDCP.
*
* Drivers *must* eventually call the corresponding function to finish the
* operation.
*
* XXX: Is the use of fpi_device_action_error() acceptable?
*
* Drivers *must* also handle cancellation properly for any long running
* operation (i.e. any operation that requires capturing). It is entirely fine
* to ignore cancellation requests for short operations (e.g. open/close).
*
* This API is solely intended for drivers. It is purely internal and neither
* API nor ABI stable.
*/
struct _FpSdcpDeviceClass
{
FpDeviceClass parent_class;
void (*connect) (FpSdcpDevice *dev);
void (*reconnect) (FpSdcpDevice *dev);
void (*close) (FpSdcpDevice *dev);
void (*enroll_begin) (FpSdcpDevice *dev);
void (*enroll_commit) (FpSdcpDevice *dev,
GBytes *id);
void (*identify) (FpSdcpDevice *dev);
};
void fpi_sdcp_device_set_intermediat_cas (FpSdcpDevice *self,
GBytes *ca_1,
GBytes *ca_2);
void fpi_sdcp_device_get_connect_data (FpSdcpDevice *self,
GBytes **r_h,
GBytes **pk_h);
void fpi_sdcp_device_connect_complete (FpSdcpDevice *self,
GBytes *r_d,
FpiSdcpClaim *claim,
GBytes *mac,
GError *error);
void fpi_sdcp_device_get_reconnect_data (FpSdcpDevice *self,
GBytes **r_h);
void fpi_sdcp_device_reconnect_complete (FpSdcpDevice *self,
GBytes *mac,
GError *error);
void fpi_sdcp_device_enroll_set_nonce (FpSdcpDevice *self,
GBytes *nonce);
void fpi_sdcp_device_enroll_ready (FpSdcpDevice *self,
GError *error);
void fpi_sdcp_device_enroll_commit_complete (FpSdcpDevice *self,
GError *error);
void fpi_sdcp_device_get_identify_data (FpSdcpDevice *self,
GBytes **nonce);
void fpi_sdcp_device_identify_retry (FpSdcpDevice *self,
GError *error);
void fpi_sdcp_device_identify_complete (FpSdcpDevice *self,
GBytes *id,
GBytes *mac,
GError *error);
+25 -5
View File
@@ -18,7 +18,6 @@
*/
#include "fpi-spi-transfer.h"
#include "fpi-log.h"
#include <sys/ioctl.h>
#include <linux/spi/spidev.h>
#include <errno.h>
@@ -42,17 +41,38 @@ static gsize block_size = 0;
* Drivers should always use this API rather than calling read/write/ioctl on
* the spidev device.
*
* Setting %G_MESSAGES_DEBUG and %FP_DEBUG_TRANSFER will result in the message
* Setting G_MESSAGES_DEBUG and FP_DEBUG_TRANSFER will result in the message
* content to be dumped.
*/
G_DEFINE_BOXED_TYPE (FpiSpiTransfer, fpi_spi_transfer, fpi_spi_transfer_ref, fpi_spi_transfer_unref)
static void
dump_buffer (guchar *buf, gssize dump_len)
{
g_autoptr(GString) line = NULL;
line = g_string_new ("");
/* Dump the buffer. */
for (gssize i = 0; i < dump_len; i++)
{
g_string_append_printf (line, "%02x ", buf[i]);
if ((i + 1) % 16 == 0)
{
g_debug ("%s", line->str);
g_string_set_size (line, 0);
}
}
if (line->len)
g_debug ("%s", line->str);
}
static void
log_transfer (FpiSpiTransfer *transfer, gboolean submit, GError *error)
{
if (fpi_log_is_debug_transfer_enabled ())
if (g_getenv ("FP_DEBUG_TRANSFER"))
{
if (submit)
{
@@ -62,7 +82,7 @@ log_transfer (FpiSpiTransfer *transfer, gboolean submit, GError *error)
transfer->length_rd);
if (transfer->buffer_wr)
fp_dbg_hex_dump_data (transfer->buffer_wr, transfer->length_wr);
dump_buffer (transfer->buffer_wr, transfer->length_wr);
}
else
{
@@ -78,7 +98,7 @@ log_transfer (FpiSpiTransfer *transfer, gboolean submit, GError *error)
transfer->length_wr,
transfer->length_rd);
if (transfer->buffer_rd)
fp_dbg_hex_dump_data (transfer->buffer_rd, transfer->length_rd);
dump_buffer (transfer->buffer_rd, transfer->length_rd);
}
}
}
+15 -21
View File
@@ -73,7 +73,7 @@
struct _FpiSsm
{
FpDevice *dev;
char *name;
const char *name;
FpiSsm *parentsm;
gpointer ssm_data;
GDestroyNotify ssm_data_destroy;
@@ -615,7 +615,7 @@ fpi_ssm_get_cur_state (FpiSsm *machine)
*
* Returns the error code set by fpi_ssm_mark_failed().
*
* Returns: (transfer none): a #GError or %NULL if not set.
* Returns: (transfer none): a error code
*/
GError *
fpi_ssm_get_error (FpiSsm *machine)
@@ -631,7 +631,7 @@ fpi_ssm_get_error (FpiSsm *machine)
*
* Returns the error code set by fpi_ssm_mark_failed().
*
* Returns: (transfer full): a #GError or %NULL if not set.
* Returns: (transfer full): a error code
*/
GError *
fpi_ssm_dup_error (FpiSsm *machine)
@@ -657,8 +657,6 @@ fpi_ssm_dup_error (FpiSsm *machine)
void
fpi_ssm_silence_debug (FpiSsm *machine)
{
g_return_if_fail (machine != NULL);
machine->silence = TRUE;
}
@@ -667,10 +665,10 @@ fpi_ssm_silence_debug (FpiSsm *machine)
* @transfer: a #FpiUsbTransfer
* @device: a #FpDevice
* @unused_data: User data (unused)
* @error: (transfer full): a #GError or %NULL.
* @error: The #GError or %NULL
*
* Can be used in as a #FpiUsbTransfer callback handler to automatically
* advance or fail a state machine on transfer completion.
* advance or fail a statemachine on transfer completion.
*
* Make sure to set the #FpiSsm on the transfer.
*/
@@ -678,11 +676,10 @@ void
fpi_ssm_usb_transfer_cb (FpiUsbTransfer *transfer, FpDevice *device,
gpointer unused_data, GError *error)
{
g_return_if_fail (transfer != NULL);
g_return_if_fail (transfer->ssm);
if (error)
fpi_ssm_mark_failed (transfer->ssm, g_steal_pointer (&error));
fpi_ssm_mark_failed (transfer->ssm, error);
else
fpi_ssm_next_state (transfer->ssm);
}
@@ -694,10 +691,10 @@ fpi_ssm_usb_transfer_cb (FpiUsbTransfer *transfer, FpDevice *device,
* @weak_ptr: A #gpointer pointer to nullify. You can pass a pointer to any
* #gpointer to nullify when the callback is completed. I.e a
* pointer to the current #FpiUsbTransfer.
* @error: (transfer full): a #GError or %NULL.
* @error: The #GError or %NULL
*
* Can be used in as a #FpiUsbTransfer callback handler to automatically
* advance or fail a state machine on transfer completion.
* advance or fail a statemachine on transfer completion.
* Passing a #gpointer* as @weak_ptr permits to nullify it once we're done
* with the transfer.
*
@@ -708,13 +705,12 @@ fpi_ssm_usb_transfer_with_weak_pointer_cb (FpiUsbTransfer *transfer,
FpDevice *device, gpointer weak_ptr,
GError *error)
{
g_return_if_fail (transfer != NULL);
g_return_if_fail (transfer->ssm);
if (weak_ptr)
g_nullify_pointer ((gpointer *) weak_ptr);
fpi_ssm_usb_transfer_cb (transfer, device, weak_ptr, g_steal_pointer (&error));
fpi_ssm_usb_transfer_cb (transfer, device, weak_ptr, error);
}
/**
@@ -722,10 +718,10 @@ fpi_ssm_usb_transfer_with_weak_pointer_cb (FpiUsbTransfer *transfer,
* @transfer: a #FpiSpiTransfer
* @device: a #FpDevice
* @unused_data: User data (unused)
* @error: (transfer full): a #GError or %NULL.
* @error: The #GError or %NULL
*
* Can be used in as a #FpiSpiTransfer callback handler to automatically
* advance or fail a state machine on transfer completion.
* advance or fail a statemachine on transfer completion.
*
* Make sure to set the #FpiSsm on the transfer.
*/
@@ -733,11 +729,10 @@ void
fpi_ssm_spi_transfer_cb (FpiSpiTransfer *transfer, FpDevice *device,
gpointer unused_data, GError *error)
{
g_return_if_fail (transfer != NULL);
g_return_if_fail (transfer->ssm);
if (error)
fpi_ssm_mark_failed (transfer->ssm, g_steal_pointer (&error));
fpi_ssm_mark_failed (transfer->ssm, error);
else
fpi_ssm_next_state (transfer->ssm);
}
@@ -749,10 +744,10 @@ fpi_ssm_spi_transfer_cb (FpiSpiTransfer *transfer, FpDevice *device,
* @weak_ptr: A #gpointer pointer to nullify. You can pass a pointer to any
* #gpointer to nullify when the callback is completed. I.e a
* pointer to the current #FpiSpiTransfer.
* @error: (transfer full): a #GError or %NULL.
* @error: The #GError or %NULL
*
* Can be used in as a #FpiSpiTransfer callback handler to automatically
* advance or fail a state machine on transfer completion.
* advance or fail a statemachine on transfer completion.
* Passing a #gpointer* as @weak_ptr permits to nullify it once we're done
* with the transfer.
*
@@ -763,11 +758,10 @@ fpi_ssm_spi_transfer_with_weak_pointer_cb (FpiSpiTransfer *transfer,
FpDevice *device, gpointer weak_ptr,
GError *error)
{
g_return_if_fail (transfer != NULL);
g_return_if_fail (transfer->ssm);
if (weak_ptr)
g_nullify_pointer ((gpointer *) weak_ptr);
fpi_ssm_spi_transfer_cb (transfer, device, weak_ptr, g_steal_pointer (&error));
fpi_ssm_spi_transfer_cb (transfer, device, weak_ptr, error);
}
+21 -34
View File
@@ -18,7 +18,6 @@
*/
#include "fpi-usb-transfer.h"
#include "fpi-log.h"
/**
* SECTION:fpi-usb-transfer
@@ -31,9 +30,6 @@
*
* Drivers should use this API only rather than accessing the GUsbDevice
* directly in most cases.
*
* Setting %G_MESSAGES_DEBUG and %FP_DEBUG_TRANSFER will result in the message
* content to be dumped.
*/
@@ -42,10 +38,8 @@ G_DEFINE_BOXED_TYPE (FpiUsbTransfer, fpi_usb_transfer, fpi_usb_transfer_ref, fpi
static void
log_transfer (FpiUsbTransfer *transfer, gboolean submit, GError *error)
{
if (fpi_log_is_debug_transfer_enabled ())
if (g_getenv ("FP_DEBUG_TRANSFER"))
{
gboolean is_incoming = !!(transfer->endpoint & FPI_USB_ENDPOINT_IN);
if (!submit)
{
g_autofree gchar *error_str = NULL;
@@ -69,13 +63,27 @@ log_transfer (FpiUsbTransfer *transfer, gboolean submit, GError *error)
transfer->endpoint);
}
if (submit != is_incoming)
if (!submit == !!(transfer->endpoint & FPI_USB_ENDPOINT_IN))
{
gsize dump_length = is_incoming ? transfer->actual_length : transfer->length;
g_autoptr(GString) line = NULL;
gssize dump_len;
/* 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);
dump_len = (transfer->endpoint & FPI_USB_ENDPOINT_IN) ? transfer->actual_length : transfer->length;
line = g_string_new ("");
/* Dump the buffer. */
for (gint i = 0; i < dump_len; i++)
{
g_string_append_printf (line, "%02x ", transfer->buffer[i]);
if ((i + 1) % 16 == 0)
{
g_debug ("%s", line->str);
g_string_set_size (line, 0);
}
}
if (line->len)
g_debug ("%s", line->str);
}
}
}
@@ -336,8 +344,7 @@ transfer_finish_cb (GObject *source_object, GAsyncResult *res, gpointer user_dat
{
error = g_error_new (G_USB_DEVICE_ERROR,
G_USB_DEVICE_ERROR_IO,
"Unexpected short error of %zd size (expected %zd)",
transfer->actual_length, transfer->length);
"Unexpected short error of %zd size (expected %zd)", transfer->actual_length, transfer->length);
}
callback = transfer->callback;
@@ -541,23 +548,3 @@ fpi_usb_transfer_submit_sync (FpiUsbTransfer *transfer,
return res;
}
/**
* fpi_usb_transfer_set_short_error:
* @transfer: The transfer to submit, must have been filled.
* @short_is_error: Whether a short transfer should be considered an error
*
* Sets whether a short transfer (a transfer in which the transferred length
* does not match the expected length) should be considered an error
*
* By default, short transfers are not considered an error, but
* drivers can enforce a further check by setting this flag.
*/
void
fpi_usb_transfer_set_short_error (FpiUsbTransfer *transfer,
gboolean short_is_error)
{
g_return_if_fail (transfer);
transfer->short_is_error = short_is_error;
}

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