mirror of
https://gitlab.freedesktop.org/libfprint/libfprint.git
synced 2026-09-11 05:10:05 +00:00
Compare commits
18
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3f13ddc40d | ||
|
|
e0f081c6e3 | ||
|
|
ae1fb4094b | ||
|
|
13350e05a2 | ||
|
|
3ea9cc90fe | ||
|
|
e862e8e881 | ||
|
|
60f5cd650a | ||
|
|
7ff36888b7 | ||
|
|
e3043123f5 | ||
|
|
77400b7a60 | ||
|
|
8d83e5eb38 | ||
|
|
e59d5451cc | ||
|
|
798bc4ee1e | ||
|
|
0e732dbafa | ||
|
|
84112abc71 | ||
|
|
c221c6b63e | ||
|
|
6e28b9a8c4 | ||
|
|
e5589a0ec2 |
+43
-152
@@ -1,57 +1,39 @@
|
|||||||
include:
|
include:
|
||||||
- local: '.gitlab-ci/libfprint-image-variables.yaml'
|
|
||||||
- local: '.gitlab-ci/libfprint-templates.yaml'
|
- local: '.gitlab-ci/libfprint-templates.yaml'
|
||||||
- project: 'freedesktop/ci-templates'
|
- project: 'wayland/ci-templates'
|
||||||
ref: master
|
ref: master
|
||||||
file: '/templates/fedora.yml'
|
file: '/templates/fedora.yml'
|
||||||
- remote: 'https://gitlab.gnome.org/GNOME/citemplates/-/raw/master/flatpak/flatpak_ci_initiative.yml'
|
- remote: 'https://gitlab.gnome.org/GNOME/citemplates/-/raw/master/flatpak/flatpak_ci_initiative.yml'
|
||||||
|
|
||||||
default:
|
|
||||||
# Auto-retry jobs in case of infra failures
|
|
||||||
retry:
|
|
||||||
max: 1
|
|
||||||
when:
|
|
||||||
- 'runner_system_failure'
|
|
||||||
- 'stuck_or_timeout_failure'
|
|
||||||
- 'scheduler_failure'
|
|
||||||
- 'api_failure'
|
|
||||||
|
|
||||||
variables:
|
variables:
|
||||||
extends: .libfprint_common_variables
|
extends: .libfprint_common_variables
|
||||||
FDO_DISTRIBUTION_TAG: $LIBFPRINT_IMAGE_TAG
|
FDO_DISTRIBUTION_TAG: latest
|
||||||
FDO_DISTRIBUTION_VERSION: rawhide
|
FDO_DISTRIBUTION_VERSION: rawhide
|
||||||
FDO_UPSTREAM_REPO: "libfprint/$CI_PROJECT_NAME"
|
|
||||||
FEDORA_IMAGE: "$CI_REGISTRY/libfprint/$CI_PROJECT_NAME/fedora/$FDO_DISTRIBUTION_VERSION:$FDO_DISTRIBUTION_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"
|
LAST_ABI_BREAK: "056ea541ddc97f5806cffbd99a12dc87e4da3546"
|
||||||
|
|
||||||
workflow:
|
|
||||||
rules:
|
|
||||||
- if: $CI_PIPELINE_SOURCE == 'merge_request_event'
|
|
||||||
- if: $CI_PIPELINE_SOURCE == 'push'
|
|
||||||
|
|
||||||
stages:
|
stages:
|
||||||
- image-build
|
|
||||||
- check-source
|
- check-source
|
||||||
- build
|
- build
|
||||||
- test
|
- test
|
||||||
- flatpak
|
- flatpak
|
||||||
- deploy
|
|
||||||
|
|
||||||
image: $FEDORA_IMAGE
|
image: "$FEDORA_IMAGE"
|
||||||
|
|
||||||
.build_one_driver_template: &build_one_driver
|
.build_one_driver_template: &build_one_driver
|
||||||
script:
|
script:
|
||||||
# Build with a driver that doesn't need imaging, or nss
|
# Build with a driver that doesn't need imaging, or nss
|
||||||
- meson setup _build --werror -Ddrivers=$driver
|
- meson --werror -Ddrivers=$driver . _build
|
||||||
- meson compile -C _build
|
- ninja -C _build
|
||||||
- rm -rf _build/
|
- rm -rf _build/
|
||||||
|
|
||||||
.build_template: &build
|
.build_template: &build
|
||||||
script:
|
script:
|
||||||
# And build with everything
|
# And build with everything
|
||||||
- meson setup _build --werror -Ddrivers=all
|
- meson --werror -Ddrivers=all . _build
|
||||||
- meson compile -C _build
|
- ninja -C _build
|
||||||
- meson install -C _build
|
- ninja -C _build install
|
||||||
|
|
||||||
.build_template: &check_abi
|
.build_template: &check_abi
|
||||||
script:
|
script:
|
||||||
@@ -70,8 +52,7 @@ build:
|
|||||||
artifacts:
|
artifacts:
|
||||||
expose_as: "HTML Documentation"
|
expose_as: "HTML Documentation"
|
||||||
paths:
|
paths:
|
||||||
- _build/doc/html
|
- _build/doc/html/
|
||||||
- _build/doc/html/index.html
|
|
||||||
expire_in: 1 week
|
expire_in: 1 week
|
||||||
|
|
||||||
test:
|
test:
|
||||||
@@ -80,21 +61,14 @@ test:
|
|||||||
variables:
|
variables:
|
||||||
- $CI_PIPELINE_SOURCE == "schedule"
|
- $CI_PIPELINE_SOURCE == "schedule"
|
||||||
script:
|
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
|
||||||
- meson test -C _build --print-errorlogs --no-stdsplit --timeout-multiplier 3
|
- ninja -C _build
|
||||||
|
- meson test -C _build --verbose --no-stdsplit --timeout-multiplier 3
|
||||||
- ninja -C _build coverage
|
- ninja -C _build coverage
|
||||||
- cat _build/meson-logs/coverage.txt || true
|
- cat _build/meson-logs/coverage.txt
|
||||||
artifacts:
|
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:
|
paths:
|
||||||
- _build/meson-logs
|
- _build/meson-logs
|
||||||
- _build/meson-logs/coveragereport/index.html
|
|
||||||
expire_in: 1 week
|
expire_in: 1 week
|
||||||
coverage: '/^TOTAL.*\s+(\d+\%)$/'
|
coverage: '/^TOTAL.*\s+(\d+\%)$/'
|
||||||
|
|
||||||
@@ -104,42 +78,9 @@ test_valgrind:
|
|||||||
variables:
|
variables:
|
||||||
- $CI_PIPELINE_SOURCE == "schedule"
|
- $CI_PIPELINE_SOURCE == "schedule"
|
||||||
script:
|
script:
|
||||||
- meson setup _build -Ddrivers=all
|
- meson -Ddrivers=all -Dsdcp_virt_binary=/usr/local/bin/sdcp_virt_device . _build
|
||||||
- meson compile -C _build
|
- ninja -C _build
|
||||||
- meson test -C _build --print-errorlogs --no-stdsplit --setup=valgrind
|
- meson test -C _build --verbose --no-stdsplit --setup=valgrind
|
||||||
artifacts:
|
|
||||||
reports:
|
|
||||||
junit: "_build/meson-logs/testlog-valgrind.junit.xml"
|
|
||||||
expose_as: 'Valgrind test logs'
|
|
||||||
when: always
|
|
||||||
paths:
|
|
||||||
- _build/meson-logs
|
|
||||||
- _build/meson-logs/testlog-valgrind.txt
|
|
||||||
expire_in: 1 week
|
|
||||||
|
|
||||||
test_installed:
|
|
||||||
stage: test
|
|
||||||
except:
|
|
||||||
variables:
|
|
||||||
- $CI_PIPELINE_SOURCE == "schedule"
|
|
||||||
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:
|
test_scan_build:
|
||||||
stage: test
|
stage: test
|
||||||
@@ -148,12 +89,12 @@ test_scan_build:
|
|||||||
- $CI_PIPELINE_SOURCE == "schedule"
|
- $CI_PIPELINE_SOURCE == "schedule"
|
||||||
allow_failure: true
|
allow_failure: true
|
||||||
script:
|
script:
|
||||||
- meson setup _build -Ddrivers=all
|
- meson -Ddrivers=all . _build
|
||||||
# Wrapper to add --status-bugs and disable malloc checker
|
# This is ugly, the wrapper disables the malloc checker
|
||||||
- SCANBUILD=$CI_PROJECT_DIR/.gitlab-ci/scan-build
|
- SCANBUILD=$CI_PROJECT_DIR/.gitlab-ci/scan-build ninja -C _build scan-build
|
||||||
ninja -C _build scan-build
|
# Check that the directory is empty
|
||||||
|
- "! ls -A _build/meson-logs/scanbuild | grep -q ."
|
||||||
artifacts:
|
artifacts:
|
||||||
when: on_failure
|
|
||||||
paths:
|
paths:
|
||||||
- _build/meson-logs
|
- _build/meson-logs
|
||||||
expire_in: 1 week
|
expire_in: 1 week
|
||||||
@@ -166,7 +107,7 @@ test_indent:
|
|||||||
script:
|
script:
|
||||||
- scripts/uncrustify.sh
|
- scripts/uncrustify.sh
|
||||||
- git diff
|
- git diff
|
||||||
- git diff-index --name-only --exit-code HEAD
|
- "! git status -s | grep -q ."
|
||||||
|
|
||||||
test_unsupported_list:
|
test_unsupported_list:
|
||||||
stage: check-source
|
stage: check-source
|
||||||
@@ -179,96 +120,46 @@ test_unsupported_list:
|
|||||||
|
|
||||||
flatpak:
|
flatpak:
|
||||||
stage: flatpak
|
stage: flatpak
|
||||||
extends: .flatpak@x86_64
|
extends: .flatpak
|
||||||
|
image: registry.gitlab.gnome.org/gnome/gnome-runtime-images/gnome:3.36
|
||||||
variables:
|
variables:
|
||||||
MANIFEST_PATH: "demo/org.freedesktop.libfprint.Demo.json"
|
MANIFEST_PATH: "demo/org.freedesktop.libfprint.Demo.json"
|
||||||
FLATPAK_MODULE: "libfprint"
|
FLATPAK_MODULE: "libfprint"
|
||||||
APP_ID: "org.freedesktop.libfprint.Demo"
|
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:
|
rules:
|
||||||
- if: '$CI_PROJECT_PATH != "libfprint/libfprint"'
|
- if: '$CI_PROJECT_PATH != "libfprint/libfprint"'
|
||||||
when: manual
|
when: never
|
||||||
allow_failure: true
|
|
||||||
- if: '$CI_PIPELINE_SOURCE == "schedule"'
|
- if: '$CI_PIPELINE_SOURCE == "schedule"'
|
||||||
when: never
|
when: never
|
||||||
- if: '$CI_COMMIT_BRANCH == "master"'
|
- if: '$CI_COMMIT_BRANCH == "master"'
|
||||||
allow_failure: true
|
|
||||||
when: always
|
when: always
|
||||||
- if: '$CI_COMMIT_TAG'
|
- if: '$CI_COMMIT_TAG'
|
||||||
allow_failure: true
|
|
||||||
when: always
|
when: always
|
||||||
# For any other (commit), allow manual run.
|
# For any other (commit), allow manual run.
|
||||||
# This excludes MRs which would create a duplicate pipeline
|
# This excludes MRs which would create a duplicate pipeline
|
||||||
- if: '$CI_COMMIT_BRANCH'
|
- if: '$CI_COMMIT_BRANCH'
|
||||||
when: manual
|
when: manual
|
||||||
allow_failure: true
|
allow_failure: true
|
||||||
- if: '$CI_MERGE_REQUEST_ID'
|
|
||||||
when: manual
|
|
||||||
allow_failure: true
|
|
||||||
|
|
||||||
# CONTAINERS creation stage
|
# CONTAINERS creation stage
|
||||||
.container_fedora_build_base:
|
container_fedora_build:
|
||||||
extends: .fdo.container-build@fedora
|
extends: .fdo.container-build@fedora
|
||||||
stage: image-build
|
|
||||||
only:
|
|
||||||
variables:
|
|
||||||
- $CI_PIPELINE_SOURCE == "never"
|
|
||||||
variables:
|
|
||||||
GIT_STRATEGY: none # no need to pull the whole tree for rebuilding the image
|
|
||||||
# a list of packages to install
|
|
||||||
FDO_DISTRIBUTION_PACKAGES:
|
|
||||||
$LIBFPRINT_DEPENDENCIES
|
|
||||||
vala
|
|
||||||
libpcap-devel
|
|
||||||
libudev-devel
|
|
||||||
FDO_DISTRIBUTION_EXEC: |
|
|
||||||
$LIBFPRINT_EXEC
|
|
||||||
|
|
||||||
.container_fedora_build_forced:
|
|
||||||
variables:
|
|
||||||
FDO_FORCE_REBUILD: 1
|
|
||||||
|
|
||||||
container_fedora_build_schedule:
|
|
||||||
extends:
|
|
||||||
- .container_fedora_build_base
|
|
||||||
- .container_fedora_build_forced
|
|
||||||
only:
|
only:
|
||||||
variables:
|
variables:
|
||||||
- $CI_PIPELINE_SOURCE == "schedule" && $CRON_TASK == "BUILD_CI_IMAGES"
|
- $CI_PIPELINE_SOURCE == "schedule" && $CRON_TASK == "BUILD_CI_IMAGES"
|
||||||
|
variables:
|
||||||
container_fedora_build_manual:
|
GIT_STRATEGY: none # no need to pull the whole tree for rebuilding the image
|
||||||
extends:
|
# a list of packages to install; we only include mbedtls here
|
||||||
- .container_fedora_build_base
|
FDO_DISTRIBUTION_PACKAGES: $LIBFPRINT_DEPENDENCIES mbedtls-devel
|
||||||
- .container_fedora_build_forced
|
FDO_DISTRIBUTION_EXEC: |
|
||||||
only:
|
cd /tmp
|
||||||
variables:
|
mkdir -p /usr/local/bin
|
||||||
- $LIBFPRINT_CI_ACTION == "build-image"
|
git clone https://github.com/benzea/SecureDeviceConnectionProtocol.git
|
||||||
|
# Don't bother with cmake
|
||||||
container_fedora_build_on_deps_changed:
|
gcc -l mbedcrypto -I SecureDeviceConnectionProtocol/src/include \
|
||||||
extends: .container_fedora_build_base
|
SecureDeviceConnectionProtocol/src/test/virt_device.c \
|
||||||
only:
|
SecureDeviceConnectionProtocol/src/client/client.c \
|
||||||
variables:
|
SecureDeviceConnectionProtocol/src/test/helpers.c \
|
||||||
- $CI_PROJECT_NAMESPACE == "libfprint" && $CI_PIPELINE_SOURCE != "schedule"
|
SecureDeviceConnectionProtocol/src/test/testkeys.c \
|
||||||
refs:
|
-o /usr/local/bin/sdcp_virt_device
|
||||||
- branches
|
rm -rf SecureDeviceConnectionProtocol
|
||||||
- merge_requests
|
|
||||||
changes:
|
|
||||||
- .gitlab-ci/libfprint-image-variables.yaml
|
|
||||||
|
|
||||||
pages:
|
|
||||||
image: alpine:latest
|
|
||||||
stage: deploy
|
|
||||||
needs:
|
|
||||||
- job: test
|
|
||||||
artifacts: true
|
|
||||||
script:
|
|
||||||
- mkdir public
|
|
||||||
- mv _build/meson-logs/coveragereport public/coverage
|
|
||||||
artifacts:
|
|
||||||
paths:
|
|
||||||
- public
|
|
||||||
rules:
|
|
||||||
- if: $CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH
|
|
||||||
|
|||||||
@@ -1,2 +0,0 @@
|
|||||||
variables:
|
|
||||||
LIBFPRINT_IMAGE_TAG: v3
|
|
||||||
@@ -1,10 +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_common_variables:
|
||||||
LIBFPRINT_DEPENDENCIES:
|
LIBFPRINT_DEPENDENCIES:
|
||||||
doxygen
|
doxygen
|
||||||
dnf-plugins-core
|
|
||||||
flatpak-builder
|
flatpak-builder
|
||||||
gcc
|
gcc
|
||||||
gcc-c++
|
gcc-c++
|
||||||
@@ -13,12 +9,10 @@
|
|||||||
glib2-devel
|
glib2-devel
|
||||||
glibc-devel
|
glibc-devel
|
||||||
gobject-introspection-devel
|
gobject-introspection-devel
|
||||||
gnome-desktop-testing
|
|
||||||
gtk-doc
|
gtk-doc
|
||||||
gtk3-devel
|
gtk3-devel
|
||||||
libabigail
|
libabigail
|
||||||
libgusb-devel
|
libgusb-devel
|
||||||
libgudev-devel
|
|
||||||
libX11-devel
|
libX11-devel
|
||||||
libXv-devel
|
libXv-devel
|
||||||
meson
|
meson
|
||||||
@@ -31,19 +25,3 @@
|
|||||||
uncrustify
|
uncrustify
|
||||||
valgrind
|
valgrind
|
||||||
clang-analyzer
|
clang-analyzer
|
||||||
diffutils
|
|
||||||
|
|
||||||
LIBFPRINT_EXEC: |
|
|
||||||
dnf -y install dnf-utils
|
|
||||||
debuginfo-install -y \
|
|
||||||
glib2 \
|
|
||||||
glibc \
|
|
||||||
libgusb \
|
|
||||||
libusb \
|
|
||||||
nss \
|
|
||||||
pixman
|
|
||||||
|
|
||||||
git clone https://github.com/martinpitt/umockdev.git && \
|
|
||||||
cd umockdev && \
|
|
||||||
meson _build --prefix=/usr && \
|
|
||||||
ninja -C _build && ninja -C _build install
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
# This wrapper just disables the malloc checker
|
# This wrapper just disables the malloc checker
|
||||||
exec /usr/bin/scan-build --status-bugs -disable-checker unix.Malloc "$@"
|
exec /usr/bin/scan-build -disable-checker unix.Malloc "$@"
|
||||||
@@ -1,165 +1,6 @@
|
|||||||
This file lists notable changes in each release. For the full history of all
|
This file lists notable changes in each release. For the full history of all
|
||||||
changes, see ChangeLog.
|
changes, see ChangeLog.
|
||||||
|
|
||||||
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:
|
|
||||||
* Ensure idle mainloop before completing enumeration (fprintd#119)
|
|
||||||
* It is now possible to extend already enrolled prints
|
|
||||||
* elanspi: Fix timeout error with some hardware (#438)
|
|
||||||
* elanspi: Fix cancellation issues
|
|
||||||
* goodixmoc: Return matching device print; fixes duplicate checking (#444)
|
|
||||||
* goodixmoc: Support clearing the storage (usually unused)
|
|
||||||
|
|
||||||
2021-11-02: v1.94.2 release
|
|
||||||
|
|
||||||
Highlights:
|
|
||||||
* goodixmoc: Fix protocol error with certain username lengths
|
|
||||||
* elanmoc: New PID 0x0c7d
|
|
||||||
* goodixmoc: New PID 0x63cc
|
|
||||||
|
|
||||||
2021-09-24: v1.94.1 release
|
|
||||||
|
|
||||||
Highlights:
|
|
||||||
* Ship a simple script to create new CI tests using tshark
|
|
||||||
* Added CI tests for elan, uru4000, aes2501
|
|
||||||
* goodixmoc: Remove duplicate checking during enroll and let fprintd handle it
|
|
||||||
* uru4000: Fix USB transfer type
|
|
||||||
* synaptics: Support for new PIDs
|
|
||||||
* goodixmoc: Support for new PIDs
|
|
||||||
|
|
||||||
2021-08-20: v1.94.0 release
|
|
||||||
|
|
||||||
Highlights:
|
|
||||||
* Implement suspend/resume handling including USB wakeup configuration.
|
|
||||||
This requires writing the "persist" and "wakeup" sysfs attributes.
|
|
||||||
* Add simple temperature module to prevent devices from becoming too hot
|
|
||||||
* Add feature for continuous scanning
|
|
||||||
* New internal "critical section" API to simplify driver development
|
|
||||||
* elan: new PID 0x0c58
|
|
||||||
* elanmoc: Fixes for multi-user handling and FW changes
|
|
||||||
* virtual-device: Do not time out for SCAN command
|
|
||||||
|
|
||||||
2021-06-30: v1.92.1 release
|
|
||||||
|
|
||||||
Highlights:
|
|
||||||
* elanmoc: New driver for ELAN match-on-chip devices
|
|
||||||
* egis0570: New driver for some Egis Technology devices
|
|
||||||
* synaptics: Fix empty identify causing enroll issues
|
|
||||||
* elan: Support more PIDs
|
|
||||||
* misc: Architecture related bugfixes
|
|
||||||
|
|
||||||
2021-06-30: v1.92.0 release
|
|
||||||
|
|
||||||
Highlights:
|
|
||||||
* Support for SPI devices was added together with the elanspi driver
|
|
||||||
* Generate hwdb for autosuspend (which is now pulled by systemd)
|
|
||||||
* An API was added to clear the device storage.
|
|
||||||
Note: Devices may not implement the "list" API anymore.
|
|
||||||
* Device features can now be queried using a common API
|
|
||||||
|
|
||||||
New drivers:
|
|
||||||
* vfs7552
|
|
||||||
* nb1010
|
|
||||||
* elanspi
|
|
||||||
|
|
||||||
Driver changes:
|
|
||||||
* uru4000: Fix deactivation when unplugged unexpectedly
|
|
||||||
* goodixmoc: Correctly complete verify/identify after retry condition
|
|
||||||
* goodixmoc: Support power shield feature
|
|
||||||
* goodixmoc: Support new PIDs
|
|
||||||
* synaptics: Fix driver lockup when sequence counter overflows (#358)
|
|
||||||
* synaptics: Remove unnecessary device reset
|
|
||||||
* synaptics: Support new PIDs
|
|
||||||
* synaptics: Add clear_storage and remove list support
|
|
||||||
* synaptics: Fix initialization if the device is still busy when opening
|
|
||||||
* upeksonly: Fix double free in USB transfer callbacks
|
|
||||||
* elan: Support new PIDs
|
|
||||||
* vfs301: Fix leak of USB transfer
|
|
||||||
* uru4000: Silence warning happening during startup
|
|
||||||
|
|
||||||
Internal API changes:
|
|
||||||
* ssm: Add getter for the device
|
|
||||||
* ssm: Add cleanup state feature
|
|
||||||
* image-device: Allow overriding number of enroll stages
|
|
||||||
* context: Support udev based device discovery
|
|
||||||
* spi-transfer: Add SPI transfer helper routines
|
|
||||||
|
|
||||||
Other:
|
|
||||||
* Use pcap based USB replay for CI
|
|
||||||
* New virtual drivers for more advanced testing
|
|
||||||
* Ensure async operations are run in the thread local main context
|
|
||||||
* Disable drivers on big-endian unless they are verified to work
|
|
||||||
* Add missing gobject-introspection dependency
|
|
||||||
|
|
||||||
|
|
||||||
2020-12-01: v1.90.7 release
|
2020-12-01: v1.90.7 release
|
||||||
|
|
||||||
Highlights:
|
Highlights:
|
||||||
@@ -386,7 +227,7 @@ tests of the drivers using umockdev.
|
|||||||
- Mark fp_dscv_print functions as deprecated
|
- Mark fp_dscv_print functions as deprecated
|
||||||
|
|
||||||
* Udev rules:
|
* Udev rules:
|
||||||
- Add some unsupported devices to the allowlist
|
- Add some unsupported devices to the whitelist
|
||||||
|
|
||||||
2017-05-14: v0.7.0 release
|
2017-05-14: v0.7.0 release
|
||||||
* Drivers:
|
* Drivers:
|
||||||
@@ -436,7 +277,7 @@ tests of the drivers using umockdev.
|
|||||||
- Fix possible race condition, and cancellation in uru4000 driver
|
- Fix possible race condition, and cancellation in uru4000 driver
|
||||||
|
|
||||||
* Udev rules:
|
* Udev rules:
|
||||||
- Add Microsoft keyboard to the suspend denylist
|
- Add Microsoft keyboard to the suspend blacklist
|
||||||
|
|
||||||
* Plenty of build fixes
|
* Plenty of build fixes
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,51 @@
|
|||||||
|
libfprint
|
||||||
|
=========
|
||||||
|
|
||||||
|
libfprint is part of the fprint project:
|
||||||
|
https://fprint.freedesktop.org/
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
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).
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
For more information on libfprint, supported devices, API documentation, etc.,
|
||||||
|
see the homepage:
|
||||||
|
https://fprint.freedesktop.org/
|
||||||
|
|
||||||
|
libfprint is licensed under the GNU LGPL version 2.1. See the COPYING file
|
||||||
|
for the license text.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
## Historical links
|
||||||
|
|
||||||
|
Older versions of libfprint are available at:
|
||||||
|
https://sourceforge.net/projects/fprint/files/
|
||||||
|
|
||||||
|
Historical mailing-list archives:
|
||||||
|
http://www.reactivated.net/fprint_list_archives/
|
||||||
|
|
||||||
|
Historical website:
|
||||||
|
http://web.archive.org/web/*/https://www.freedesktop.org/wiki/Software/fprint/
|
||||||
@@ -1,95 +0,0 @@
|
|||||||
|
|
||||||
|
|
||||||
<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>
|
|
||||||
|
|
||||||
## History
|
|
||||||
|
|
||||||
**LibFPrint** was originally developed as part of an
|
|
||||||
academic project at the **[University Of Manchester]**.
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
## 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.
|
|
||||||
|
|
||||||
**LibFPrint** includes code from **NIST's** **[NBIS]** software distribution.
|
|
||||||
|
|
||||||
We include **Bozorth3** from the **[US Export Controlled]**
|
|
||||||
distribution, which we have determined to be fine
|
|
||||||
being shipped in an open source project.
|
|
||||||
|
|
||||||
## Get in *touch*
|
|
||||||
|
|
||||||
- [IRC] - `#fprint` @ `irc.oftc.net`
|
|
||||||
- [Matrix] - `#fprint:matrix.org` bridged to the IRC channel
|
|
||||||
- [MailingList] - low traffic, not much used these days
|
|
||||||
|
|
||||||
<br/>
|
|
||||||
|
|
||||||
<div align="right">
|
|
||||||
|
|
||||||
[![Badge License]][License]
|
|
||||||
|
|
||||||
</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
|
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
LIBRARY
|
||||||
|
=======
|
||||||
|
test suite against NFIQ compliance set
|
||||||
|
make library optionally asynchronous and maybe thread-safe
|
||||||
|
nbis cleanups
|
||||||
|
API function to determine if img device supports uncond. capture
|
||||||
|
race-free way of saying "save this print but don't overwrite"
|
||||||
|
|
||||||
|
NEW DRIVERS
|
||||||
|
===========
|
||||||
|
Sunplus 895 driver
|
||||||
|
AES3400/3500 driver
|
||||||
|
ID Mouse driver
|
||||||
|
Support for 2nd generation MS devices
|
||||||
|
Support for 2nd generation UPEK devices
|
||||||
|
|
||||||
|
IMAGING
|
||||||
|
=======
|
||||||
|
ignore first frame or two with aes2501
|
||||||
|
aes2501: increase threshold "sum" for end-of-image detection
|
||||||
|
aes2501 gain calibration
|
||||||
|
aes4000 gain calibration
|
||||||
|
aes4000 resampling
|
||||||
|
PPMM parameter to get_minutiae seems to have no effect
|
||||||
|
nbis minutiae should be stored in endian-independent format
|
||||||
|
|
||||||
|
PORTABILITY
|
||||||
|
===========
|
||||||
|
OpenBSD can't do -Wshadow or visibility
|
||||||
|
OpenBSD: add compat codes for ENOTSUP ENODATA and EPROTO
|
||||||
+11
-182
@@ -4,7 +4,6 @@
|
|||||||
# Supported by libfprint driver aes1610
|
# Supported by libfprint driver aes1610
|
||||||
usb:v08FFp1600*
|
usb:v08FFp1600*
|
||||||
ID_AUTOSUSPEND=1
|
ID_AUTOSUSPEND=1
|
||||||
ID_PERSIST=0
|
|
||||||
|
|
||||||
# Supported by libfprint driver aes1660
|
# Supported by libfprint driver aes1660
|
||||||
usb:v08FFp1660*
|
usb:v08FFp1660*
|
||||||
@@ -25,19 +24,16 @@ usb:v08FFp168D*
|
|||||||
usb:v08FFp168E*
|
usb:v08FFp168E*
|
||||||
usb:v08FFp168F*
|
usb:v08FFp168F*
|
||||||
ID_AUTOSUSPEND=1
|
ID_AUTOSUSPEND=1
|
||||||
ID_PERSIST=0
|
|
||||||
|
|
||||||
# Supported by libfprint driver aes2501
|
# Supported by libfprint driver aes2501
|
||||||
usb:v08FFp2500*
|
usb:v08FFp2500*
|
||||||
usb:v08FFp2580*
|
usb:v08FFp2580*
|
||||||
ID_AUTOSUSPEND=1
|
ID_AUTOSUSPEND=1
|
||||||
ID_PERSIST=0
|
|
||||||
|
|
||||||
# Supported by libfprint driver aes2550
|
# Supported by libfprint driver aes2550
|
||||||
usb:v08FFp2550*
|
usb:v08FFp2550*
|
||||||
usb:v08FFp2810*
|
usb:v08FFp2810*
|
||||||
ID_AUTOSUSPEND=1
|
ID_AUTOSUSPEND=1
|
||||||
ID_PERSIST=0
|
|
||||||
|
|
||||||
# Supported by libfprint driver aes2660
|
# Supported by libfprint driver aes2660
|
||||||
usb:v08FFp2660*
|
usb:v08FFp2660*
|
||||||
@@ -59,32 +55,14 @@ usb:v08FFp268E*
|
|||||||
usb:v08FFp268F*
|
usb:v08FFp268F*
|
||||||
usb:v08FFp2691*
|
usb:v08FFp2691*
|
||||||
ID_AUTOSUSPEND=1
|
ID_AUTOSUSPEND=1
|
||||||
ID_PERSIST=0
|
|
||||||
|
|
||||||
# Supported by libfprint driver aes3500
|
# Supported by libfprint driver aes3500
|
||||||
usb:v08FFp5731*
|
usb:v08FFp5731*
|
||||||
ID_AUTOSUSPEND=1
|
ID_AUTOSUSPEND=1
|
||||||
ID_PERSIST=0
|
|
||||||
|
|
||||||
# Supported by libfprint driver aes4000
|
# Supported by libfprint driver aes4000
|
||||||
usb:v08FFp5501*
|
usb:v5501p08FF*
|
||||||
ID_AUTOSUSPEND=1
|
ID_AUTOSUSPEND=1
|
||||||
ID_PERSIST=0
|
|
||||||
|
|
||||||
# Supported by libfprint driver egis0570
|
|
||||||
usb:v1C7Ap0570*
|
|
||||||
usb:v1C7Ap0571*
|
|
||||||
ID_AUTOSUSPEND=1
|
|
||||||
ID_PERSIST=0
|
|
||||||
|
|
||||||
# Supported by libfprint driver egismoc
|
|
||||||
usb:v1C7Ap0582*
|
|
||||||
usb:v1C7Ap0583*
|
|
||||||
usb:v1C7Ap0586*
|
|
||||||
usb:v1C7Ap0587*
|
|
||||||
usb:v1C7Ap05A1*
|
|
||||||
ID_AUTOSUSPEND=1
|
|
||||||
ID_PERSIST=0
|
|
||||||
|
|
||||||
# Supported by libfprint driver elan
|
# Supported by libfprint driver elan
|
||||||
usb:v04F3p0903*
|
usb:v04F3p0903*
|
||||||
@@ -140,139 +118,48 @@ usb:v04F3p0C30*
|
|||||||
usb:v04F3p0C31*
|
usb:v04F3p0C31*
|
||||||
usb:v04F3p0C32*
|
usb:v04F3p0C32*
|
||||||
usb:v04F3p0C33*
|
usb:v04F3p0C33*
|
||||||
usb:v04F3p0C3D*
|
|
||||||
usb:v04F3p0C42*
|
usb:v04F3p0C42*
|
||||||
usb:v04F3p0C4B*
|
|
||||||
usb:v04F3p0C4D*
|
usb:v04F3p0C4D*
|
||||||
usb:v04F3p0C4F*
|
|
||||||
usb:v04F3p0C63*
|
|
||||||
usb:v04F3p0C6E*
|
|
||||||
usb:v04F3p0C58*
|
|
||||||
ID_AUTOSUSPEND=1
|
ID_AUTOSUSPEND=1
|
||||||
ID_PERSIST=0
|
|
||||||
|
|
||||||
# Supported by libfprint driver elanmoc
|
|
||||||
usb:v04F3p0C7D*
|
|
||||||
usb:v04F3p0C7E*
|
|
||||||
usb:v04F3p0C82*
|
|
||||||
usb:v04F3p0C88*
|
|
||||||
usb:v04F3p0C8C*
|
|
||||||
usb:v04F3p0C8D*
|
|
||||||
usb:v04F3p0C99*
|
|
||||||
usb:v04F3p0C9F*
|
|
||||||
ID_AUTOSUSPEND=1
|
|
||||||
ID_PERSIST=0
|
|
||||||
|
|
||||||
# Supported by libfprint driver etes603
|
# Supported by libfprint driver etes603
|
||||||
usb:v1C7Ap0603*
|
usb:v1C7Ap0603*
|
||||||
ID_AUTOSUSPEND=1
|
ID_AUTOSUSPEND=1
|
||||||
ID_PERSIST=0
|
|
||||||
|
|
||||||
# Supported by libfprint driver focaltech_moc
|
|
||||||
usb:v2808p9E48*
|
|
||||||
usb:v2808pD979*
|
|
||||||
usb:v2808pA959*
|
|
||||||
ID_AUTOSUSPEND=1
|
|
||||||
ID_PERSIST=0
|
|
||||||
|
|
||||||
# Supported by libfprint driver fpcmoc
|
|
||||||
usb:v10A5pFFE0*
|
|
||||||
usb:v10A5pA305*
|
|
||||||
usb:v10A5pDA04*
|
|
||||||
usb:v10A5pD805*
|
|
||||||
usb:v10A5pD205*
|
|
||||||
usb:v10A5p9524*
|
|
||||||
usb:v10A5p9544*
|
|
||||||
ID_AUTOSUSPEND=1
|
|
||||||
ID_PERSIST=0
|
|
||||||
|
|
||||||
# Supported by libfprint driver goodixmoc
|
# Supported by libfprint driver goodixmoc
|
||||||
usb:v27C6p5840*
|
usb:v27C6p5840*
|
||||||
usb:v27C6p6014*
|
|
||||||
usb:v27C6p6092*
|
|
||||||
usb:v27C6p6094*
|
|
||||||
usb:v27C6p609A*
|
|
||||||
usb:v27C6p609C*
|
|
||||||
usb:v27C6p60A2*
|
|
||||||
usb:v27C6p60A4*
|
|
||||||
usb:v27C6p60BC*
|
|
||||||
usb:v27C6p6304*
|
|
||||||
usb:v27C6p631C*
|
|
||||||
usb:v27C6p633C*
|
|
||||||
usb:v27C6p634C*
|
|
||||||
usb:v27C6p6384*
|
|
||||||
usb:v27C6p639C*
|
|
||||||
usb:v27C6p63AC*
|
|
||||||
usb:v27C6p63BC*
|
|
||||||
usb:v27C6p63CC*
|
|
||||||
usb:v27C6p6496*
|
usb:v27C6p6496*
|
||||||
usb:v27C6p650A*
|
usb:v27C6p60A2*
|
||||||
usb:v27C6p650C*
|
usb:v27C6p63AC*
|
||||||
usb:v27C6p6582*
|
usb:v27C6p639C*
|
||||||
usb:v27C6p6584*
|
|
||||||
usb:v27C6p658C*
|
|
||||||
usb:v27C6p6592*
|
|
||||||
usb:v27C6p6594*
|
usb:v27C6p6594*
|
||||||
usb:v27C6p659A*
|
|
||||||
usb:v27C6p659C*
|
|
||||||
usb:v27C6p6A94*
|
|
||||||
usb:v27C6p6512*
|
|
||||||
ID_AUTOSUSPEND=1
|
ID_AUTOSUSPEND=1
|
||||||
ID_PERSIST=0
|
|
||||||
|
|
||||||
# Supported by libfprint driver nb1010
|
|
||||||
usb:v298Dp1010*
|
|
||||||
ID_AUTOSUSPEND=1
|
|
||||||
ID_PERSIST=0
|
|
||||||
|
|
||||||
# Supported by libfprint driver realtek
|
|
||||||
usb:v0BDAp5813*
|
|
||||||
usb:v0BDAp5816*
|
|
||||||
ID_AUTOSUSPEND=1
|
|
||||||
ID_PERSIST=0
|
|
||||||
|
|
||||||
# Supported by libfprint driver synaptics
|
# Supported by libfprint driver synaptics
|
||||||
usb:v06CBp00BD*
|
usb:v06CBp00BD*
|
||||||
|
usb:v06CBp00E9*
|
||||||
usb:v06CBp00DF*
|
usb:v06CBp00DF*
|
||||||
usb:v06CBp00F9*
|
usb:v06CBp00F9*
|
||||||
usb:v06CBp00FC*
|
usb:v06CBp00FC*
|
||||||
usb:v06CBp00C2*
|
usb:v06CBp00C2*
|
||||||
usb:v06CBp00C4*
|
usb:v06CBp00C9*
|
||||||
usb:v06CBp0100*
|
usb:v06CBp00E7*
|
||||||
usb:v06CBp00F0*
|
|
||||||
usb:v06CBp0103*
|
|
||||||
usb:v06CBp0123*
|
|
||||||
usb:v06CBp0124*
|
|
||||||
usb:v06CBp0126*
|
|
||||||
usb:v06CBp0129*
|
|
||||||
usb:v06CBp0168*
|
|
||||||
usb:v06CBp015F*
|
|
||||||
usb:v06CBp0104*
|
|
||||||
usb:v06CBp0173*
|
|
||||||
usb:v06CBp0106*
|
|
||||||
usb:v06CBp019D*
|
|
||||||
usb:v06CBp00C6*
|
|
||||||
ID_AUTOSUSPEND=1
|
ID_AUTOSUSPEND=1
|
||||||
ID_PERSIST=0
|
|
||||||
|
|
||||||
# Supported by libfprint driver upeksonly
|
# Supported by libfprint driver upeksonly
|
||||||
usb:v147Ep2016*
|
usb:v147Ep2016*
|
||||||
usb:v147Ep1000*
|
usb:v147Ep1000*
|
||||||
usb:v147Ep1001*
|
usb:v147Ep1001*
|
||||||
ID_AUTOSUSPEND=1
|
ID_AUTOSUSPEND=1
|
||||||
ID_PERSIST=0
|
|
||||||
|
|
||||||
# Supported by libfprint driver upektc
|
# Supported by libfprint driver upektc
|
||||||
usb:v0483p2015*
|
usb:v0483p2015*
|
||||||
usb:v0483p2017*
|
|
||||||
usb:v147Ep3001*
|
usb:v147Ep3001*
|
||||||
ID_AUTOSUSPEND=1
|
ID_AUTOSUSPEND=1
|
||||||
ID_PERSIST=0
|
|
||||||
|
|
||||||
# Supported by libfprint driver upektc_img
|
# Supported by libfprint driver upektc_img
|
||||||
usb:v147Ep2020*
|
usb:v147Ep2020*
|
||||||
ID_AUTOSUSPEND=1
|
ID_AUTOSUSPEND=1
|
||||||
ID_PERSIST=0
|
|
||||||
|
|
||||||
# Supported by libfprint driver uru4000
|
# Supported by libfprint driver uru4000
|
||||||
usb:v045Ep00BC*
|
usb:v045Ep00BC*
|
||||||
@@ -282,28 +169,23 @@ usb:v05BAp0007*
|
|||||||
usb:v05BAp0008*
|
usb:v05BAp0008*
|
||||||
usb:v05BAp000A*
|
usb:v05BAp000A*
|
||||||
ID_AUTOSUSPEND=1
|
ID_AUTOSUSPEND=1
|
||||||
ID_PERSIST=0
|
|
||||||
|
|
||||||
# Supported by libfprint driver vcom5s
|
# Supported by libfprint driver vcom5s
|
||||||
usb:v061Ap0110*
|
usb:v061Ap0110*
|
||||||
ID_AUTOSUSPEND=1
|
ID_AUTOSUSPEND=1
|
||||||
ID_PERSIST=0
|
|
||||||
|
|
||||||
# Supported by libfprint driver vfs0050
|
# Supported by libfprint driver vfs0050
|
||||||
usb:v138Ap0050*
|
usb:v138Ap0050*
|
||||||
ID_AUTOSUSPEND=1
|
ID_AUTOSUSPEND=1
|
||||||
ID_PERSIST=0
|
|
||||||
|
|
||||||
# Supported by libfprint driver vfs101
|
# Supported by libfprint driver vfs101
|
||||||
usb:v138Ap0001*
|
usb:v138Ap0001*
|
||||||
ID_AUTOSUSPEND=1
|
ID_AUTOSUSPEND=1
|
||||||
ID_PERSIST=0
|
|
||||||
|
|
||||||
# Supported by libfprint driver vfs301
|
# Supported by libfprint driver vfs301
|
||||||
usb:v138Ap0005*
|
usb:v138Ap0005*
|
||||||
usb:v138Ap0008*
|
usb:v138Ap0008*
|
||||||
ID_AUTOSUSPEND=1
|
ID_AUTOSUSPEND=1
|
||||||
ID_PERSIST=0
|
|
||||||
|
|
||||||
# Supported by libfprint driver vfs5011
|
# Supported by libfprint driver vfs5011
|
||||||
usb:v138Ap0010*
|
usb:v138Ap0010*
|
||||||
@@ -312,71 +194,32 @@ usb:v138Ap0015*
|
|||||||
usb:v138Ap0017*
|
usb:v138Ap0017*
|
||||||
usb:v138Ap0018*
|
usb:v138Ap0018*
|
||||||
ID_AUTOSUSPEND=1
|
ID_AUTOSUSPEND=1
|
||||||
ID_PERSIST=0
|
|
||||||
|
|
||||||
# Supported by libfprint driver vfs7552
|
|
||||||
usb:v138Ap0091*
|
|
||||||
ID_AUTOSUSPEND=1
|
|
||||||
ID_PERSIST=0
|
|
||||||
|
|
||||||
# Known unsupported devices
|
# Known unsupported devices
|
||||||
usb:v047Dp00F2*
|
|
||||||
usb:v04E8p730B*
|
|
||||||
usb:v04F3p036B*
|
usb:v04F3p036B*
|
||||||
usb:v04F3p0C00*
|
usb:v04F3p0C00*
|
||||||
|
usb:v04F3p0C4B*
|
||||||
usb:v04F3p0C4C*
|
usb:v04F3p0C4C*
|
||||||
|
usb:v04F3p0C4F*
|
||||||
usb:v04F3p0C57*
|
usb:v04F3p0C57*
|
||||||
usb:v04F3p0C5E*
|
|
||||||
usb:v04F3p0C5A*
|
|
||||||
usb:v04F3p0C6C*
|
|
||||||
usb:v04F3p0C70*
|
|
||||||
usb:v04F3p0C72*
|
|
||||||
usb:v04F3p0C77*
|
|
||||||
usb:v04F3p2706*
|
usb:v04F3p2706*
|
||||||
usb:v04F3p3032*
|
|
||||||
usb:v04F3p3057*
|
|
||||||
usb:v04F3p3104*
|
|
||||||
usb:v04F3p310D*
|
|
||||||
usb:v04F3p3128*
|
|
||||||
usb:v06CBp0081*
|
usb:v06CBp0081*
|
||||||
usb:v06CBp0088*
|
usb:v06CBp0088*
|
||||||
usb:v06CBp008A*
|
usb:v06CBp008A*
|
||||||
usb:v06CBp009A*
|
usb:v06CBp009A*
|
||||||
usb:v06CBp009B*
|
usb:v06CBp009B*
|
||||||
usb:v06CBp00A2*
|
usb:v06CBp00A2*
|
||||||
usb:v06CBp00A8*
|
|
||||||
usb:v06CBp00B7*
|
usb:v06CBp00B7*
|
||||||
usb:v06CBp00BB*
|
usb:v06CBp00BB*
|
||||||
usb:v06CBp00BE*
|
usb:v06CBp00BE*
|
||||||
usb:v06CBp00CB*
|
usb:v06CBp00CB*
|
||||||
usb:v06CBp00C9*
|
|
||||||
usb:v06CBp00D8*
|
usb:v06CBp00D8*
|
||||||
usb:v06CBp00DA*
|
usb:v06CBp00DA*
|
||||||
usb:v06CBp00DC*
|
|
||||||
usb:v06CBp00E4*
|
|
||||||
usb:v06CBp00E7*
|
|
||||||
usb:v06CBp00E9*
|
|
||||||
usb:v06CBp00FD*
|
|
||||||
usb:v0A5Cp5801*
|
usb:v0A5Cp5801*
|
||||||
usb:v0A5Cp5805*
|
usb:v0A5Cp5805*
|
||||||
usb:v0A5Cp5834*
|
usb:v0A5Cp5834*
|
||||||
usb:v0A5Cp5840*
|
|
||||||
usb:v0A5Cp5841*
|
|
||||||
usb:v0A5Cp5842*
|
|
||||||
usb:v0A5Cp5843*
|
usb:v0A5Cp5843*
|
||||||
usb:v0A5Cp5844*
|
|
||||||
usb:v0A5Cp5845*
|
|
||||||
usb:v0A5Cp5860*
|
|
||||||
usb:v0A5Cp5863*
|
|
||||||
usb:v0A5Cp5864*
|
|
||||||
usb:v0A5Cp5865*
|
|
||||||
usb:v0A5Cp5866*
|
|
||||||
usb:v0A5Cp5867*
|
|
||||||
usb:v0BDAp5812*
|
|
||||||
usb:v10A5p0007*
|
usb:v10A5p0007*
|
||||||
usb:v10A5p9200*
|
|
||||||
usb:v10A5p9800*
|
|
||||||
usb:v10A5pE340*
|
|
||||||
usb:v1188p9545*
|
usb:v1188p9545*
|
||||||
usb:v138Ap0007*
|
usb:v138Ap0007*
|
||||||
usb:v138Ap003A*
|
usb:v138Ap003A*
|
||||||
@@ -384,52 +227,38 @@ usb:v138Ap003C*
|
|||||||
usb:v138Ap003D*
|
usb:v138Ap003D*
|
||||||
usb:v138Ap003F*
|
usb:v138Ap003F*
|
||||||
usb:v138Ap0090*
|
usb:v138Ap0090*
|
||||||
|
usb:v138Ap0091*
|
||||||
usb:v138Ap0092*
|
usb:v138Ap0092*
|
||||||
usb:v138Ap0094*
|
usb:v138Ap0094*
|
||||||
usb:v138Ap0097*
|
usb:v138Ap0097*
|
||||||
usb:v138Ap009D*
|
usb:v138Ap009D*
|
||||||
usb:v138Ap00AB*
|
usb:v138Ap00AB*
|
||||||
usb:v138Ap00A6*
|
|
||||||
usb:v147Ep1002*
|
usb:v147Ep1002*
|
||||||
usb:v1491p0088*
|
usb:v1491p0088*
|
||||||
usb:v16D1p1027*
|
usb:v16D1p1027*
|
||||||
usb:v1C7Ap0300*
|
usb:v1C7Ap0300*
|
||||||
|
usb:v1C7Ap0570*
|
||||||
usb:v1C7Ap0575*
|
usb:v1C7Ap0575*
|
||||||
usb:v1C7Ap0576*
|
|
||||||
usb:v1C7Ap0577*
|
|
||||||
usb:v27C6p5042*
|
usb:v27C6p5042*
|
||||||
usb:v27C6p5110*
|
usb:v27C6p5110*
|
||||||
usb:v27C6p5117*
|
usb:v27C6p5117*
|
||||||
usb:v27C6p5120*
|
|
||||||
usb:v27C6p5125*
|
|
||||||
usb:v27C6p5201*
|
usb:v27C6p5201*
|
||||||
usb:v27C6p521D*
|
usb:v27C6p521D*
|
||||||
usb:v27C6p5301*
|
usb:v27C6p5301*
|
||||||
usb:v27C6p530C*
|
usb:v27C6p530C*
|
||||||
usb:v27C6p532D*
|
usb:v27C6p532D*
|
||||||
usb:v27C6p5335*
|
|
||||||
usb:v27C6p533C*
|
usb:v27C6p533C*
|
||||||
usb:v27C6p5381*
|
usb:v27C6p5381*
|
||||||
usb:v27C6p5385*
|
usb:v27C6p5385*
|
||||||
usb:v27C6p538C*
|
usb:v27C6p538C*
|
||||||
usb:v27C6p538D*
|
usb:v27C6p538D*
|
||||||
usb:v27C6p5395*
|
usb:v27C6p5395*
|
||||||
usb:v27C6p5503*
|
|
||||||
usb:v27C6p550A*
|
|
||||||
usb:v27C6p550C*
|
|
||||||
usb:v27C6p5584*
|
usb:v27C6p5584*
|
||||||
usb:v27C6p55A2*
|
usb:v27C6p55A2*
|
||||||
usb:v27C6p55A4*
|
usb:v27C6p55A4*
|
||||||
usb:v27C6p55B4*
|
usb:v27C6p55B4*
|
||||||
usb:v27C6p5740*
|
usb:v27C6p5740*
|
||||||
usb:v27C6p5E0A*
|
|
||||||
usb:v27C6p581A*
|
|
||||||
usb:v27C6p589A*
|
|
||||||
usb:v27C6p6382*
|
|
||||||
usb:v2808p9338*
|
usb:v2808p9338*
|
||||||
usb:v2808p93A9*
|
|
||||||
usb:v298Dp2020*
|
|
||||||
usb:v298Dp2033*
|
usb:v298Dp2033*
|
||||||
usb:v3538p0930*
|
usb:v3538p0930*
|
||||||
ID_AUTOSUSPEND=1
|
ID_AUTOSUSPEND=1
|
||||||
ID_PERSIST=0
|
|
||||||
|
|||||||
+1
-3
@@ -1,8 +1,6 @@
|
|||||||
if udev_hwdb_dir != ''
|
if get_option('udev_rules')
|
||||||
# This file has to be updated using
|
# This file has to be updated using
|
||||||
# ninja -C <builddir> libfprint/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
|
|
||||||
|
|
||||||
install_data('autosuspend.hwdb',
|
install_data('autosuspend.hwdb',
|
||||||
rename: '60-autosuspend-@0@.hwdb'.format(versioned_libname),
|
rename: '60-autosuspend-@0@.hwdb'.format(versioned_libname),
|
||||||
|
|||||||
@@ -102,9 +102,9 @@ plot_minutiae (unsigned char *rgbdata,
|
|||||||
int i;
|
int i;
|
||||||
|
|
||||||
#define write_pixel(num) do { \
|
#define write_pixel(num) do { \
|
||||||
rgbdata[((num) * 3)] = 0xff; \
|
rgbdata[((num) * 3)] = 0xff; \
|
||||||
rgbdata[((num) * 3) + 1] = 0; \
|
rgbdata[((num) * 3) + 1] = 0; \
|
||||||
rgbdata[((num) * 3) + 2] = 0; \
|
rgbdata[((num) * 3) + 2] = 0; \
|
||||||
} while(0)
|
} while(0)
|
||||||
|
|
||||||
for (i = 0; i < minutiae->len; i++)
|
for (i = 0; i < minutiae->len; i++)
|
||||||
@@ -526,7 +526,7 @@ libfprint_demo_window_init (LibfprintDemoWindow *window)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!fp_device_has_feature (g_ptr_array_index (devices, 0), FP_DEVICE_FEATURE_CAPTURE))
|
if (!fp_device_supports_capture (g_ptr_array_index (devices, 0)))
|
||||||
{
|
{
|
||||||
libfprint_demo_set_mode (window, NOIMAGING_MODE);
|
libfprint_demo_set_mode (window, NOIMAGING_MODE);
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"app-id": "org.freedesktop.libfprint.Demo",
|
"app-id": "org.freedesktop.libfprint.Demo",
|
||||||
"runtime": "org.gnome.Platform",
|
"runtime": "org.gnome.Platform",
|
||||||
"runtime-version": "master",
|
"runtime-version": "3.36",
|
||||||
"sdk": "org.gnome.Sdk",
|
"sdk": "org.gnome.Sdk",
|
||||||
"command": "gtk-libfprint-test",
|
"command": "gtk-libfprint-test",
|
||||||
"finish-args": [
|
"finish-args": [
|
||||||
/* X11 + XShm access */
|
/* X11 + XShm access */
|
||||||
"--share=ipc", "--socket=fallback-x11",
|
"--share=ipc", "--socket=x11",
|
||||||
/* Wayland access */
|
/* Wayland access */
|
||||||
"--socket=wayland",
|
"--socket=wayland",
|
||||||
/* OpenGL access */
|
/* OpenGL access */
|
||||||
@@ -18,7 +18,7 @@
|
|||||||
"modules": [
|
"modules": [
|
||||||
{
|
{
|
||||||
"name": "libusb",
|
"name": "libusb",
|
||||||
"config-opts": [ "--disable-static" ],
|
"config-opts": [ "--disable-static", "--disable-udev" ],
|
||||||
"cleanup": [
|
"cleanup": [
|
||||||
"/lib/*.la",
|
"/lib/*.la",
|
||||||
"/lib/pkgconfig",
|
"/lib/pkgconfig",
|
||||||
@@ -26,47 +26,36 @@
|
|||||||
],
|
],
|
||||||
"sources": [
|
"sources": [
|
||||||
{
|
{
|
||||||
"type": "archive",
|
"type": "archive",
|
||||||
"url": "https://github.com/libusb/libusb/releases/download/v1.0.26/libusb-1.0.26.tar.bz2",
|
"url": "https://github.com/libusb/libusb/archive/v1.0.22.tar.gz",
|
||||||
"sha256": "12ce7a61fc9854d1d2a1ffe095f7b5fac19ddba095c259e6067a46500381b5a5"
|
"sha256": "3500f7b182750cd9ccf9be8b1df998f83df56a39ab264976bdb3307773e16f48"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"post-install": [
|
"post-install": [
|
||||||
"install -Dm644 COPYING /app/share/licenses/libusb/COPYING"
|
"install -Dm644 COPYING /app/share/licenses/libgusb/COPYING"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "libgusb",
|
"name": "libgusb",
|
||||||
"buildsystem": "meson",
|
"buildsystem": "meson",
|
||||||
"config-opts": [ "-Dtests=false", "-Dvapi=false", "-Ddocs=false" ],
|
"config-opts": [ "-Dtests=false", "-Dvapi=false", "-Ddocs=false", "-Dintrospection=false" ],
|
||||||
"sources": [
|
"sources": [
|
||||||
{
|
{
|
||||||
"type": "archive",
|
"type": "archive",
|
||||||
"url": "https://github.com/hughsie/libgusb/releases/download/0.4.6/libgusb-0.4.6.tar.xz",
|
"url": "https://github.com/hughsie/libgusb/archive/0.3.0.tar.gz",
|
||||||
"sha256": "1b0422bdcd72183272ac42eec9398c5a0bc48a02f618fa3242c468cbbd003049"
|
"sha256": "b36310f8405d5fd68f6caf4a829f7ab4c627b38fd3d02a139d411fce0f3a49f1"
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "gudev",
|
|
||||||
"buildsystem": "meson",
|
|
||||||
"config-opts": [ "-Dtests=disabled", "-Dintrospection=disabled", "-Dvapi=disabled" ],
|
|
||||||
"sources": [
|
|
||||||
{
|
|
||||||
"type": "archive",
|
|
||||||
"url": "https://download.gnome.org/sources/libgudev/238/libgudev-238.tar.xz",
|
|
||||||
"sha256": "61266ab1afc9d73dbc60a8b2af73e99d2fdff47d99544d085760e4fa667b5dd1"
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "libfprint",
|
"name": "libfprint",
|
||||||
"buildsystem": "meson",
|
"buildsystem": "meson",
|
||||||
"config-opts": [ "-Dudev_hwdb=disabled", "-Dudev_rules=disabled", "-Dgtk-examples=true", "-Ddrivers=all" ],
|
"config-opts": [ "-Dudev_rules=false", "-Dx11-examples=false", "-Dgtk-examples=true", "-Ddrivers=all" ],
|
||||||
"sources": [
|
"sources": [
|
||||||
{
|
{
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://gitlab.freedesktop.org/libfprint/libfprint.git"
|
"url": "https://gitlab.freedesktop.org/libfprint/libfprint.git",
|
||||||
|
"branch": "wip/benzea/v2"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,11 +20,9 @@ FP_TYPE_DEVICE
|
|||||||
FP_DEVICE_RETRY
|
FP_DEVICE_RETRY
|
||||||
FP_DEVICE_ERROR
|
FP_DEVICE_ERROR
|
||||||
FpDeviceType
|
FpDeviceType
|
||||||
FpDeviceFeature
|
|
||||||
FpScanType
|
FpScanType
|
||||||
FpDeviceRetry
|
FpDeviceRetry
|
||||||
FpDeviceError
|
FpDeviceError
|
||||||
FpFingerStatusFlags
|
|
||||||
fp_device_retry_quark
|
fp_device_retry_quark
|
||||||
fp_device_error_quark
|
fp_device_error_quark
|
||||||
FpEnrollProgress
|
FpEnrollProgress
|
||||||
@@ -34,13 +32,9 @@ fp_device_get_device_id
|
|||||||
fp_device_get_name
|
fp_device_get_name
|
||||||
fp_device_get_scan_type
|
fp_device_get_scan_type
|
||||||
fp_device_get_nr_enroll_stages
|
fp_device_get_nr_enroll_stages
|
||||||
fp_device_get_finger_status
|
|
||||||
fp_device_get_features
|
|
||||||
fp_device_has_feature
|
|
||||||
fp_device_has_storage
|
fp_device_has_storage
|
||||||
fp_device_supports_identify
|
fp_device_supports_identify
|
||||||
fp_device_supports_capture
|
fp_device_supports_capture
|
||||||
fp_device_is_open
|
|
||||||
fp_device_open
|
fp_device_open
|
||||||
fp_device_close
|
fp_device_close
|
||||||
fp_device_enroll
|
fp_device_enroll
|
||||||
@@ -49,9 +43,6 @@ fp_device_identify
|
|||||||
fp_device_capture
|
fp_device_capture
|
||||||
fp_device_delete_print
|
fp_device_delete_print
|
||||||
fp_device_list_prints
|
fp_device_list_prints
|
||||||
fp_device_clear_storage
|
|
||||||
fp_device_suspend
|
|
||||||
fp_device_resume
|
|
||||||
fp_device_open_finish
|
fp_device_open_finish
|
||||||
fp_device_close_finish
|
fp_device_close_finish
|
||||||
fp_device_enroll_finish
|
fp_device_enroll_finish
|
||||||
@@ -60,9 +51,6 @@ fp_device_identify_finish
|
|||||||
fp_device_capture_finish
|
fp_device_capture_finish
|
||||||
fp_device_delete_print_finish
|
fp_device_delete_print_finish
|
||||||
fp_device_list_prints_finish
|
fp_device_list_prints_finish
|
||||||
fp_device_clear_storage_finish
|
|
||||||
fp_device_suspend_finish
|
|
||||||
fp_device_resume_finish
|
|
||||||
fp_device_open_sync
|
fp_device_open_sync
|
||||||
fp_device_close_sync
|
fp_device_close_sync
|
||||||
fp_device_enroll_sync
|
fp_device_enroll_sync
|
||||||
@@ -71,9 +59,6 @@ fp_device_identify_sync
|
|||||||
fp_device_capture_sync
|
fp_device_capture_sync
|
||||||
fp_device_delete_print_sync
|
fp_device_delete_print_sync
|
||||||
fp_device_list_prints_sync
|
fp_device_list_prints_sync
|
||||||
fp_device_clear_storage_sync
|
|
||||||
fp_device_suspend_sync
|
|
||||||
fp_device_resume_sync
|
|
||||||
FpDevice
|
FpDevice
|
||||||
</SECTION>
|
</SECTION>
|
||||||
|
|
||||||
@@ -100,6 +85,12 @@ FP_TYPE_IMAGE_DEVICE
|
|||||||
FpImageDevice
|
FpImageDevice
|
||||||
</SECTION>
|
</SECTION>
|
||||||
|
|
||||||
|
<SECTION>
|
||||||
|
<FILE>fp-sdcp-device</FILE>
|
||||||
|
FP_TYPE_SDCP_DEVICE
|
||||||
|
FpSdcpDevice
|
||||||
|
</SECTION>
|
||||||
|
|
||||||
<SECTION>
|
<SECTION>
|
||||||
<FILE>fp-print</FILE>
|
<FILE>fp-print</FILE>
|
||||||
FP_TYPE_PRINT
|
FP_TYPE_PRINT
|
||||||
@@ -145,9 +136,7 @@ FpDeviceClass
|
|||||||
FpTimeoutFunc
|
FpTimeoutFunc
|
||||||
FpiDeviceAction
|
FpiDeviceAction
|
||||||
FpIdEntry
|
FpIdEntry
|
||||||
FpiDeviceUdevSubtypeFlags
|
|
||||||
fpi_device_get_usb_device
|
fpi_device_get_usb_device
|
||||||
fpi_device_get_udev_data
|
|
||||||
fpi_device_get_virtual_env
|
fpi_device_get_virtual_env
|
||||||
fpi_device_get_current_action
|
fpi_device_get_current_action
|
||||||
fpi_device_retry_new
|
fpi_device_retry_new
|
||||||
@@ -165,12 +154,6 @@ fpi_device_action_is_cancelled
|
|||||||
fpi_device_add_timeout
|
fpi_device_add_timeout
|
||||||
fpi_device_set_nr_enroll_stages
|
fpi_device_set_nr_enroll_stages
|
||||||
fpi_device_set_scan_type
|
fpi_device_set_scan_type
|
||||||
fpi_device_update_features
|
|
||||||
fpi_device_critical_enter
|
|
||||||
fpi_device_critical_leave
|
|
||||||
fpi_device_remove
|
|
||||||
fpi_device_report_finger_status
|
|
||||||
fpi_device_report_finger_status_changes
|
|
||||||
fpi_device_action_error
|
fpi_device_action_error
|
||||||
fpi_device_probe_complete
|
fpi_device_probe_complete
|
||||||
fpi_device_open_complete
|
fpi_device_open_complete
|
||||||
@@ -179,15 +162,10 @@ fpi_device_enroll_complete
|
|||||||
fpi_device_verify_complete
|
fpi_device_verify_complete
|
||||||
fpi_device_identify_complete
|
fpi_device_identify_complete
|
||||||
fpi_device_capture_complete
|
fpi_device_capture_complete
|
||||||
fpi_device_clear_storage_complete
|
|
||||||
fpi_device_delete_complete
|
fpi_device_delete_complete
|
||||||
fpi_device_list_complete
|
|
||||||
fpi_device_suspend_complete
|
|
||||||
fpi_device_resume_complete
|
|
||||||
fpi_device_enroll_progress
|
fpi_device_enroll_progress
|
||||||
fpi_device_verify_report
|
fpi_device_verify_report
|
||||||
fpi_device_identify_report
|
fpi_device_identify_report
|
||||||
fpi_device_class_auto_initialize_features
|
|
||||||
</SECTION>
|
</SECTION>
|
||||||
|
|
||||||
<SECTION>
|
<SECTION>
|
||||||
@@ -212,7 +190,26 @@ fpi_image_device_deactivate_complete
|
|||||||
fpi_image_device_report_finger_status
|
fpi_image_device_report_finger_status
|
||||||
fpi_image_device_image_captured
|
fpi_image_device_image_captured
|
||||||
fpi_image_device_retry_scan
|
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>
|
||||||
|
|
||||||
<SECTION>
|
<SECTION>
|
||||||
@@ -256,15 +253,11 @@ fpi_ssm_mark_completed
|
|||||||
fpi_ssm_mark_failed
|
fpi_ssm_mark_failed
|
||||||
fpi_ssm_set_data
|
fpi_ssm_set_data
|
||||||
fpi_ssm_get_data
|
fpi_ssm_get_data
|
||||||
fpi_ssm_get_device
|
|
||||||
fpi_ssm_get_error
|
fpi_ssm_get_error
|
||||||
fpi_ssm_dup_error
|
fpi_ssm_dup_error
|
||||||
fpi_ssm_get_cur_state
|
fpi_ssm_get_cur_state
|
||||||
fpi_ssm_silence_debug
|
fpi_ssm_next_state_timeout_cb
|
||||||
fpi_ssm_spi_transfer_cb
|
|
||||||
fpi_ssm_spi_transfer_with_weak_pointer_cb
|
|
||||||
fpi_ssm_usb_transfer_cb
|
fpi_ssm_usb_transfer_cb
|
||||||
fpi_ssm_usb_transfer_with_weak_pointer_cb
|
|
||||||
FpiSsm
|
FpiSsm
|
||||||
</SECTION>
|
</SECTION>
|
||||||
|
|
||||||
@@ -291,20 +284,3 @@ FPI_TYPE_USB_TRANSFER
|
|||||||
fpi_usb_transfer_get_type
|
fpi_usb_transfer_get_type
|
||||||
</SECTION>
|
</SECTION>
|
||||||
|
|
||||||
<SECTION>
|
|
||||||
<FILE>fpi-spi-transfer</FILE>
|
|
||||||
FpiSpiTransferCallback
|
|
||||||
FpiSpiTransfer
|
|
||||||
fpi_spi_transfer_new
|
|
||||||
fpi_spi_transfer_ref
|
|
||||||
fpi_spi_transfer_unref
|
|
||||||
fpi_spi_transfer_write
|
|
||||||
fpi_spi_transfer_write_full
|
|
||||||
fpi_spi_transfer_read
|
|
||||||
fpi_spi_transfer_read_full
|
|
||||||
fpi_spi_transfer_submit
|
|
||||||
fpi_spi_transfer_submit_sync
|
|
||||||
<SUBSECTION Standard>
|
|
||||||
FPI_TYPE_SPI_TRANSFER
|
|
||||||
fpi_spi_transfer_get_type
|
|
||||||
</SECTION>
|
|
||||||
|
|||||||
@@ -1,8 +0,0 @@
|
|||||||
#include <fprint.h>
|
|
||||||
#include <fp-image-device.h>
|
|
||||||
|
|
||||||
fp_context_get_type
|
|
||||||
fp_device_get_type
|
|
||||||
fp_image_device_get_type
|
|
||||||
fp_image_get_type
|
|
||||||
fp_print_get_type
|
|
||||||
@@ -28,6 +28,7 @@
|
|||||||
<xi:include href="xml/fp-context.xml"/>
|
<xi:include href="xml/fp-context.xml"/>
|
||||||
<xi:include href="xml/fp-device.xml"/>
|
<xi:include href="xml/fp-device.xml"/>
|
||||||
<xi:include href="xml/fp-image-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-print.xml"/>
|
||||||
<xi:include href="xml/fp-image.xml"/>
|
<xi:include href="xml/fp-image.xml"/>
|
||||||
</part>
|
</part>
|
||||||
@@ -38,11 +39,11 @@
|
|||||||
<title>Device methods for drivers</title>
|
<title>Device methods for drivers</title>
|
||||||
<xi:include href="xml/fpi-device.xml"/>
|
<xi:include href="xml/fpi-device.xml"/>
|
||||||
<xi:include href="xml/fpi-image-device.xml"/>
|
<xi:include href="xml/fpi-image-device.xml"/>
|
||||||
|
<xi:include href="xml/fpi-sdcp-device.xml"/>
|
||||||
</chapter>
|
</chapter>
|
||||||
|
|
||||||
<chapter id="driver-helpers">
|
<chapter id="driver-helpers">
|
||||||
<title>USB, SPI and State Machine helpers</title>
|
<title>USB and State Machine helpers</title>
|
||||||
<xi:include href="xml/fpi-spi-transfer.xml"/>
|
|
||||||
<xi:include href="xml/fpi-usb-transfer.xml"/>
|
<xi:include href="xml/fpi-usb-transfer.xml"/>
|
||||||
<xi:include href="xml/fpi-ssm.xml"/>
|
<xi:include href="xml/fpi-ssm.xml"/>
|
||||||
<xi:include href="xml/fpi-log.xml"/>
|
<xi:include href="xml/fpi-log.xml"/>
|
||||||
|
|||||||
+2
-4
@@ -19,19 +19,17 @@ content_files = [
|
|||||||
|
|
||||||
expand_content_files = 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')
|
glib_docpath = join_paths(glib_prefix, 'share', 'gtk-doc', 'html')
|
||||||
docpath = join_paths(get_option('datadir'), 'gtk-doc', 'html')
|
docpath = join_paths(get_option('datadir'), 'gtk-doc', 'html')
|
||||||
|
|
||||||
gnome.gtkdoc(versioned_libname,
|
gnome.gtkdoc(versioned_libname,
|
||||||
main_xml: 'libfprint-docs.xml',
|
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,
|
dependencies: libfprint_dep,
|
||||||
content_files: content_files,
|
content_files: content_files,
|
||||||
expand_content_files: expand_content_files,
|
expand_content_files: expand_content_files,
|
||||||
ignore_headers: private_headers,
|
ignore_headers: private_headers,
|
||||||
gobject_typesfile: 'libfprint-2.types',
|
|
||||||
fixxref_args: [
|
fixxref_args: [
|
||||||
'--html-dir=@0@'.format(docpath),
|
'--html-dir=@0@'.format(docpath),
|
||||||
'--extra-dir=@0@'.format(join_paths(glib_docpath, 'glib')),
|
'--extra-dir=@0@'.format(join_paths(glib_docpath, 'glib')),
|
||||||
|
|||||||
+9
-56
@@ -35,7 +35,6 @@ typedef struct _EnrollData
|
|||||||
unsigned int sigint_handler;
|
unsigned int sigint_handler;
|
||||||
FpFinger finger;
|
FpFinger finger;
|
||||||
int ret_value;
|
int ret_value;
|
||||||
gboolean update_fingerprint;
|
|
||||||
} EnrollData;
|
} EnrollData;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -77,7 +76,7 @@ on_enroll_completed (FpDevice *dev, GAsyncResult *res, void *user_data)
|
|||||||
{
|
{
|
||||||
enroll_data->ret_value = EXIT_SUCCESS;
|
enroll_data->ret_value = EXIT_SUCCESS;
|
||||||
|
|
||||||
if (fp_device_has_feature (dev, FP_DEVICE_FEATURE_STORAGE))
|
if (fp_device_has_storage (dev))
|
||||||
g_debug ("Device has storage, saving a print reference locally");
|
g_debug ("Device has storage, saving a print reference locally");
|
||||||
else
|
else
|
||||||
g_debug ("Device has not storage, saving print only locally");
|
g_debug ("Device has not storage, saving print only locally");
|
||||||
@@ -85,8 +84,7 @@ on_enroll_completed (FpDevice *dev, GAsyncResult *res, void *user_data)
|
|||||||
/* Even if the device has storage, it may not be able to save all the
|
/* Even if the device has storage, it may not be able to save all the
|
||||||
* metadata that the print contains, so we can always save a local copy
|
* metadata that the print contains, so we can always save a local copy
|
||||||
* containing the handle to the device print */
|
* containing the handle to the device print */
|
||||||
int r = print_data_save (print, enroll_data->finger,
|
int r = print_data_save (print, enroll_data->finger);
|
||||||
enroll_data->update_fingerprint);
|
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
{
|
{
|
||||||
g_warning ("Data save failed, code %d", r);
|
g_warning ("Data save failed, code %d", r);
|
||||||
@@ -126,40 +124,6 @@ on_enroll_progress (FpDevice *device,
|
|||||||
fp_device_get_nr_enroll_stages (device));
|
fp_device_get_nr_enroll_stages (device));
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
|
||||||
should_update_fingerprint (void)
|
|
||||||
{
|
|
||||||
int update_choice;
|
|
||||||
gboolean update_fingerprint = FALSE;
|
|
||||||
|
|
||||||
printf ("Should an existing fingerprint be updated instead of being replaced (if present)? "
|
|
||||||
"Enter Y/y or N/n to make a choice.\n");
|
|
||||||
update_choice = getchar ();
|
|
||||||
if (update_choice == EOF)
|
|
||||||
{
|
|
||||||
g_warning ("EOF encountered while reading a character");
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (update_choice)
|
|
||||||
{
|
|
||||||
case 'y':
|
|
||||||
case 'Y':
|
|
||||||
update_fingerprint = TRUE;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'n':
|
|
||||||
case 'N':
|
|
||||||
update_fingerprint = FALSE;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
g_warning ("Invalid choice %c, should be Y/y or N/n.", update_choice);
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
return update_fingerprint;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
on_device_opened (FpDevice *dev, GAsyncResult *res, void *user_data)
|
on_device_opened (FpDevice *dev, GAsyncResult *res, void *user_data)
|
||||||
{
|
{
|
||||||
@@ -175,26 +139,13 @@ on_device_opened (FpDevice *dev, GAsyncResult *res, void *user_data)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf ("Opened device.\n");
|
printf ("Opened device. It's now time to enroll your finger.\n\n");
|
||||||
|
|
||||||
if (fp_device_has_feature (dev, FP_DEVICE_FEATURE_UPDATE_PRINT))
|
|
||||||
{
|
|
||||||
printf ("The device supports fingerprint updates.\n");
|
|
||||||
enroll_data->update_fingerprint = should_update_fingerprint ();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
printf ("The device doesn't support fingerprint updates. Old prints will be erased.\n");
|
|
||||||
enroll_data->update_fingerprint = FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
printf ("It's now time to enroll your finger.\n\n");
|
|
||||||
printf ("You will need to successfully scan your %s finger %d times to "
|
printf ("You will need to successfully scan your %s finger %d times to "
|
||||||
"complete the process.\n\n", finger_to_string (enroll_data->finger),
|
"complete the process.\n\n", finger_to_string (enroll_data->finger),
|
||||||
fp_device_get_nr_enroll_stages (dev));
|
fp_device_get_nr_enroll_stages (dev));
|
||||||
printf ("Scan your finger now.\n");
|
printf ("Scan your finger now.\n");
|
||||||
|
|
||||||
print_template = print_create_template (dev, enroll_data->finger, enroll_data->update_fingerprint);
|
print_template = print_create_template (dev, enroll_data->finger);
|
||||||
fp_device_enroll (dev, print_template, enroll_data->cancellable,
|
fp_device_enroll (dev, print_template, enroll_data->cancellable,
|
||||||
on_enroll_progress, NULL, NULL,
|
on_enroll_progress, NULL, NULL,
|
||||||
(GAsyncReadyCallback) on_enroll_completed,
|
(GAsyncReadyCallback) on_enroll_completed,
|
||||||
@@ -220,9 +171,11 @@ main (void)
|
|||||||
FpDevice *dev;
|
FpDevice *dev;
|
||||||
FpFinger finger;
|
FpFinger finger;
|
||||||
|
|
||||||
g_print ("This program will enroll the selected finger overwriting any print for the same"
|
g_print ("This program will enroll the selected finger, unconditionally "
|
||||||
" finger that was enrolled previously. Fingerprint updates without erasing old data"
|
"overwriting any print for the same finger that was enrolled "
|
||||||
" are possible on devices supporting that. Ctrl+C interrupts program execution.\n");
|
"previously. If you want to continue, press enter, otherwise hit "
|
||||||
|
"Ctrl+C\n");
|
||||||
|
getchar ();
|
||||||
|
|
||||||
g_print ("Choose the finger to enroll:\n");
|
g_print ("Choose the finger to enroll:\n");
|
||||||
finger = finger_chooser ();
|
finger = finger_chooser ();
|
||||||
|
|||||||
+3
-5
@@ -143,7 +143,6 @@ on_identify_cb (FpDevice *dev, FpPrint *match, FpPrint *print,
|
|||||||
if (match)
|
if (match)
|
||||||
{
|
{
|
||||||
g_autoptr(FpPrint) matched_print = g_object_ref (match);
|
g_autoptr(FpPrint) matched_print = g_object_ref (match);
|
||||||
const GDate *date;
|
|
||||||
char date_str[128] = {};
|
char date_str[128] = {};
|
||||||
|
|
||||||
identify_data->ret_value = EXIT_SUCCESS;
|
identify_data->ret_value = EXIT_SUCCESS;
|
||||||
@@ -156,8 +155,7 @@ on_identify_cb (FpDevice *dev, FpPrint *match, FpPrint *print,
|
|||||||
matched_print = g_steal_pointer (&stored_print);
|
matched_print = g_steal_pointer (&stored_print);
|
||||||
}
|
}
|
||||||
|
|
||||||
date = fp_print_get_enroll_date (matched_print);
|
if (fp_print_get_enroll_date (matched_print))
|
||||||
if (date && g_date_valid (date))
|
|
||||||
g_date_strftime (date_str, G_N_ELEMENTS (date_str), "%Y-%m-%d\0",
|
g_date_strftime (date_str, G_N_ELEMENTS (date_str), "%Y-%m-%d\0",
|
||||||
fp_print_get_enroll_date (matched_print));
|
fp_print_get_enroll_date (matched_print));
|
||||||
else
|
else
|
||||||
@@ -214,7 +212,7 @@ on_list_completed (FpDevice *dev, GAsyncResult *res, gpointer user_data)
|
|||||||
static void
|
static void
|
||||||
start_identification (FpDevice *dev, IdentifyData *identify_data)
|
start_identification (FpDevice *dev, IdentifyData *identify_data)
|
||||||
{
|
{
|
||||||
if (fp_device_has_feature (dev, FP_DEVICE_FEATURE_STORAGE))
|
if (fp_device_has_storage (dev))
|
||||||
{
|
{
|
||||||
g_print ("Creating finger template, using device storage...\n");
|
g_print ("Creating finger template, using device storage...\n");
|
||||||
fp_device_list_prints (dev, NULL,
|
fp_device_list_prints (dev, NULL,
|
||||||
@@ -295,7 +293,7 @@ main (void)
|
|||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!fp_device_has_feature (dev, FP_DEVICE_FEATURE_IDENTIFY))
|
if (!fp_device_supports_identify (dev))
|
||||||
{
|
{
|
||||||
g_warning ("Device %s does not support identification.",
|
g_warning ("Device %s does not support identification.",
|
||||||
fp_device_get_name (dev));
|
fp_device_get_name (dev));
|
||||||
|
|||||||
@@ -162,7 +162,7 @@ main (int argc, const char *argv[])
|
|||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!fp_device_has_feature (dev, FP_DEVICE_FEATURE_CAPTURE))
|
if (!fp_device_supports_capture (dev))
|
||||||
{
|
{
|
||||||
g_warning ("Device %s doesn't support capture",
|
g_warning ("Device %s doesn't support capture",
|
||||||
fp_device_get_name (dev));
|
fp_device_get_name (dev));
|
||||||
|
|||||||
@@ -161,7 +161,7 @@ on_list_completed (FpDevice *dev,
|
|||||||
finger_to_string (fp_print_get_finger (print)),
|
finger_to_string (fp_print_get_finger (print)),
|
||||||
fp_print_get_username (print));
|
fp_print_get_username (print));
|
||||||
|
|
||||||
if (date && g_date_valid (date))
|
if (date)
|
||||||
{
|
{
|
||||||
g_date_strftime (buf, G_N_ELEMENTS (buf), "%Y-%m-%d\0", date);
|
g_date_strftime (buf, G_N_ELEMENTS (buf), "%Y-%m-%d\0", date);
|
||||||
g_print (", enrolled on %s", buf);
|
g_print (", enrolled on %s", buf);
|
||||||
@@ -231,7 +231,7 @@ on_device_opened (FpDevice *dev,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!fp_device_has_feature (dev, FP_DEVICE_FEATURE_STORAGE))
|
if (!fp_device_has_storage (dev))
|
||||||
{
|
{
|
||||||
g_warning ("Device %s doesn't support storage", fp_device_get_name (dev));
|
g_warning ("Device %s doesn't support storage", fp_device_get_name (dev));
|
||||||
g_main_loop_quit (list_data->loop);
|
g_main_loop_quit (list_data->loop);
|
||||||
|
|||||||
@@ -21,8 +21,3 @@ executable('cpp-test',
|
|||||||
'cpp-test.cpp',
|
'cpp-test.cpp',
|
||||||
dependencies: libfprint_dep,
|
dependencies: libfprint_dep,
|
||||||
)
|
)
|
||||||
|
|
||||||
if installed_tests
|
|
||||||
install_subdir('prints',
|
|
||||||
install_dir: installed_tests_testdir)
|
|
||||||
endif
|
|
||||||
|
|||||||
+19
-35
@@ -102,23 +102,8 @@ save_data (GVariant *data)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static FpPrint *
|
|
||||||
load_print_from_data (GVariant *data)
|
|
||||||
{
|
|
||||||
const guchar *stored_data = NULL;
|
|
||||||
gsize stored_len;
|
|
||||||
FpPrint *print;
|
|
||||||
|
|
||||||
g_autoptr(GError) error = NULL;
|
|
||||||
stored_data = (const guchar *) g_variant_get_fixed_array (data, &stored_len, 1);
|
|
||||||
print = fp_print_deserialize (stored_data, stored_len, &error);
|
|
||||||
if (error)
|
|
||||||
g_warning ("Error deserializing data: %s", error->message);
|
|
||||||
return print;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
int
|
||||||
print_data_save (FpPrint *print, FpFinger finger, gboolean update_fingerprint)
|
print_data_save (FpPrint *print, FpFinger finger)
|
||||||
{
|
{
|
||||||
g_autofree gchar *descr = get_print_data_descriptor (print, NULL, finger);
|
g_autofree gchar *descr = get_print_data_descriptor (print, NULL, finger);
|
||||||
|
|
||||||
@@ -152,12 +137,25 @@ print_data_load (FpDevice *dev, FpFinger finger)
|
|||||||
|
|
||||||
g_autoptr(GVariant) val = NULL;
|
g_autoptr(GVariant) val = NULL;
|
||||||
g_autoptr(GVariantDict) dict = NULL;
|
g_autoptr(GVariantDict) dict = NULL;
|
||||||
|
const guchar *stored_data = NULL;
|
||||||
|
gsize stored_len;
|
||||||
|
|
||||||
dict = load_data ();
|
dict = load_data ();
|
||||||
val = g_variant_dict_lookup_value (dict, descr, G_VARIANT_TYPE ("ay"));
|
val = g_variant_dict_lookup_value (dict, descr, G_VARIANT_TYPE ("ay"));
|
||||||
|
|
||||||
if (val)
|
if (val)
|
||||||
return load_print_from_data (val);
|
{
|
||||||
|
FpPrint *print;
|
||||||
|
g_autoptr(GError) error = NULL;
|
||||||
|
|
||||||
|
stored_data = (const guchar *) g_variant_get_fixed_array (val, &stored_len, 1);
|
||||||
|
print = fp_print_deserialize (stored_data, stored_len, &error);
|
||||||
|
|
||||||
|
if (error)
|
||||||
|
g_warning ("Error deserializing data: %s", error->message);
|
||||||
|
|
||||||
|
return print;
|
||||||
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -209,30 +207,16 @@ gallery_data_load (FpDevice *dev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
FpPrint *
|
FpPrint *
|
||||||
print_create_template (FpDevice *dev, FpFinger finger, gboolean load_existing)
|
print_create_template (FpDevice *dev, FpFinger finger)
|
||||||
{
|
{
|
||||||
g_autoptr(GVariantDict) dict = NULL;
|
|
||||||
g_autoptr(GDateTime) datetime = NULL;
|
g_autoptr(GDateTime) datetime = NULL;
|
||||||
g_autoptr(GDate) date = NULL;
|
g_autoptr(GDate) date = NULL;
|
||||||
g_autoptr(GVariant) existing_val = NULL;
|
|
||||||
g_autofree gchar *descr = get_print_data_descriptor (NULL, dev, finger);
|
|
||||||
FpPrint *template = NULL;
|
FpPrint *template = NULL;
|
||||||
gint year, month, day;
|
gint year, month, day;
|
||||||
|
|
||||||
if (load_existing)
|
template = fp_print_new (dev);
|
||||||
{
|
fp_print_set_finger (template, finger);
|
||||||
dict = load_data ();
|
fp_print_set_username (template, g_get_user_name ());
|
||||||
existing_val = g_variant_dict_lookup_value (dict, descr, G_VARIANT_TYPE ("ay"));
|
|
||||||
if (existing_val != NULL)
|
|
||||||
template = load_print_from_data (existing_val);
|
|
||||||
}
|
|
||||||
if (template == NULL)
|
|
||||||
{
|
|
||||||
template = fp_print_new (dev);
|
|
||||||
fp_print_set_finger (template, finger);
|
|
||||||
fp_print_set_username (template, g_get_user_name ());
|
|
||||||
}
|
|
||||||
|
|
||||||
datetime = g_date_time_new_now_local ();
|
datetime = g_date_time_new_now_local ();
|
||||||
g_date_time_get_ymd (datetime, &year, &month, &day);
|
g_date_time_get_ymd (datetime, &year, &month, &day);
|
||||||
date = g_date_new_dmy (day, month, year);
|
date = g_date_new_dmy (day, month, year);
|
||||||
|
|||||||
+3
-5
@@ -21,14 +21,12 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
int print_data_save (FpPrint *print,
|
int print_data_save (FpPrint *print,
|
||||||
FpFinger finger,
|
FpFinger finger);
|
||||||
gboolean update_fingerprint);
|
|
||||||
FpPrint * print_data_load (FpDevice *dev,
|
FpPrint * print_data_load (FpDevice *dev,
|
||||||
FpFinger finger);
|
FpFinger finger);
|
||||||
GPtrArray * gallery_data_load (FpDevice *dev);
|
GPtrArray * gallery_data_load (FpDevice *dev);
|
||||||
FpPrint * print_create_template (FpDevice *dev,
|
FpPrint * print_create_template (FpDevice *dev,
|
||||||
FpFinger finger,
|
FpFinger finger);
|
||||||
const gboolean load_existing);
|
|
||||||
gboolean print_image_save (FpPrint *print,
|
gboolean print_image_save (FpPrint *print,
|
||||||
const char *path);
|
const char *path);
|
||||||
gboolean save_image_to_pgm (FpImage *img,
|
gboolean save_image_to_pgm (FpImage *img,
|
||||||
|
|||||||
@@ -101,7 +101,6 @@ finger_to_string (FpFinger finger)
|
|||||||
case FP_FINGER_RIGHT_LITTLE:
|
case FP_FINGER_RIGHT_LITTLE:
|
||||||
return "right little";
|
return "right little";
|
||||||
|
|
||||||
case FP_FINGER_UNKNOWN:
|
|
||||||
default:
|
default:
|
||||||
return "unknown";
|
return "unknown";
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-6
@@ -130,14 +130,12 @@ on_match_cb (FpDevice *dev, FpPrint *match, FpPrint *print,
|
|||||||
|
|
||||||
if (match)
|
if (match)
|
||||||
{
|
{
|
||||||
const GDate *date = fp_print_get_enroll_date (match);
|
char date_str[128];
|
||||||
char date_str[128] = "<unknown>";
|
|
||||||
|
|
||||||
verify_data->ret_value = EXIT_SUCCESS;
|
verify_data->ret_value = EXIT_SUCCESS;
|
||||||
|
|
||||||
if (date && g_date_valid (date))
|
g_date_strftime (date_str, G_N_ELEMENTS (date_str), "%Y-%m-%d\0",
|
||||||
g_date_strftime (date_str, G_N_ELEMENTS (date_str), "%Y-%m-%d\0",
|
fp_print_get_enroll_date (match));
|
||||||
fp_print_get_enroll_date (match));
|
|
||||||
g_debug ("Match report: device %s matched finger %s successifully "
|
g_debug ("Match report: device %s matched finger %s successifully "
|
||||||
"with print %s, enrolled on date %s by user %s",
|
"with print %s, enrolled on date %s by user %s",
|
||||||
fp_device_get_name (dev),
|
fp_device_get_name (dev),
|
||||||
@@ -262,7 +260,7 @@ start_verification (FpDevice *dev, VerifyData *verify_data)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fp_device_has_feature (dev, FP_DEVICE_FEATURE_STORAGE))
|
if (fp_device_has_storage (dev))
|
||||||
{
|
{
|
||||||
g_print ("Creating finger template, using device storage...\n");
|
g_print ("Creating finger template, using device storage...\n");
|
||||||
fp_device_list_prints (dev, NULL,
|
fp_device_list_prints (dev, NULL,
|
||||||
|
|||||||
@@ -124,7 +124,7 @@ G_DEFINE_TYPE (FpiDeviceAes4000, fpi_device_aes4000, FPI_TYPE_DEVICE_AES3K);
|
|||||||
|
|
||||||
|
|
||||||
static const FpIdEntry id_table[] = {
|
static const FpIdEntry id_table[] = {
|
||||||
{ .vid = 0x08ff, .pid = 0x5501 },
|
{ .pid = 0x08ff, .vid = 0x5501 },
|
||||||
{ .vid = 0, .pid = 0, .driver_data = 0 },
|
{ .vid = 0, .pid = 0, .driver_data = 0 },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -365,7 +365,7 @@ capture_read_stripe_data_cb (FpiUsbTransfer *transfer,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
fp_dbg ("Got %" G_GSIZE_FORMAT " bytes of data", actual_length);
|
fp_dbg ("Got %lu bytes of data", actual_length);
|
||||||
while (actual_length)
|
while (actual_length)
|
||||||
{
|
{
|
||||||
gssize payload_length;
|
gssize payload_length;
|
||||||
@@ -386,7 +386,7 @@ capture_read_stripe_data_cb (FpiUsbTransfer *transfer,
|
|||||||
(priv->stripe_packet->data[AESX660_RESPONSE_SIZE_MSB_OFFSET] << 8);
|
(priv->stripe_packet->data[AESX660_RESPONSE_SIZE_MSB_OFFSET] << 8);
|
||||||
fp_dbg ("Got frame, type %.2x payload of size %.4lx",
|
fp_dbg ("Got frame, type %.2x payload of size %.4lx",
|
||||||
priv->stripe_packet->data[AESX660_RESPONSE_TYPE_OFFSET],
|
priv->stripe_packet->data[AESX660_RESPONSE_TYPE_OFFSET],
|
||||||
(long) payload_length);
|
payload_length);
|
||||||
|
|
||||||
still_needed_len = MAX (0, AESX660_HEADER_SIZE + payload_length - (gssize) priv->stripe_packet->len);
|
still_needed_len = MAX (0, AESX660_HEADER_SIZE + payload_length - (gssize) priv->stripe_packet->len);
|
||||||
copy_len = MIN (actual_length, still_needed_len);
|
copy_len = MIN (actual_length, still_needed_len);
|
||||||
@@ -441,7 +441,7 @@ capture_run_state (FpiSsm *ssm, FpDevice *_dev)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case CAPTURE_SET_IDLE:
|
case CAPTURE_SET_IDLE:
|
||||||
fp_dbg ("Got %" G_GSIZE_FORMAT " frames", priv->strips_len);
|
fp_dbg ("Got %lu frames", priv->strips_len);
|
||||||
aesX660_send_cmd (ssm, _dev, set_idle_cmd, sizeof (set_idle_cmd),
|
aesX660_send_cmd (ssm, _dev, set_idle_cmd, sizeof (set_idle_cmd),
|
||||||
capture_set_idle_cmd_cb);
|
capture_set_idle_cmd_cb);
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -1,444 +0,0 @@
|
|||||||
/*
|
|
||||||
* Egis Technology Inc. (aka. LighTuning) 0570 driver for libfprint
|
|
||||||
* Copyright (C) 2021 Maxim Kolesnikov <kolesnikov@svyazcom.ru>
|
|
||||||
* Copyright (C) 2021 Saeed/Ali Rk <saeed.ali.rahimi@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 "egis0570"
|
|
||||||
|
|
||||||
#include "egis0570.h"
|
|
||||||
#include "drivers_api.h"
|
|
||||||
|
|
||||||
/* Packet types */
|
|
||||||
#define PKT_TYPE_INIT 0
|
|
||||||
#define PKT_TYPE_REPEAT 1
|
|
||||||
|
|
||||||
/* Struct */
|
|
||||||
struct _FpDeviceEgis0570
|
|
||||||
{
|
|
||||||
FpImageDevice parent;
|
|
||||||
|
|
||||||
gboolean running;
|
|
||||||
gboolean stop;
|
|
||||||
|
|
||||||
GSList *strips;
|
|
||||||
guint8 *background;
|
|
||||||
gsize strips_len;
|
|
||||||
|
|
||||||
int pkt_num;
|
|
||||||
int pkt_type;
|
|
||||||
};
|
|
||||||
G_DECLARE_FINAL_TYPE (FpDeviceEgis0570, fpi_device_egis0570, FPI, DEVICE_EGIS0570, FpImageDevice);
|
|
||||||
G_DEFINE_TYPE (FpDeviceEgis0570, fpi_device_egis0570, FP_TYPE_IMAGE_DEVICE);
|
|
||||||
|
|
||||||
static unsigned char
|
|
||||||
egis_get_pixel (struct fpi_frame_asmbl_ctx *ctx, struct fpi_frame *frame, unsigned int x, unsigned int y)
|
|
||||||
{
|
|
||||||
return frame->data[x + y * ctx->frame_width];
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct fpi_frame_asmbl_ctx assembling_ctx = {
|
|
||||||
.frame_width = EGIS0570_IMGWIDTH,
|
|
||||||
.frame_height = EGIS0570_RFMGHEIGHT,
|
|
||||||
.image_width = EGIS0570_IMGWIDTH * 4 / 3,
|
|
||||||
.get_pixel = egis_get_pixel,
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Service
|
|
||||||
*/
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
is_last_pkt (FpDevice *dev)
|
|
||||||
{
|
|
||||||
FpDeviceEgis0570 *self = FPI_DEVICE_EGIS0570 (dev);
|
|
||||||
|
|
||||||
int type = self->pkt_type;
|
|
||||||
int num = self->pkt_num;
|
|
||||||
|
|
||||||
gboolean r;
|
|
||||||
|
|
||||||
r = ((type == PKT_TYPE_INIT) && (num == (EGIS0570_INIT_TOTAL - 1)));
|
|
||||||
r |= ((type == PKT_TYPE_REPEAT) && (num == (EGIS0570_REPEAT_TOTAL - 1)));
|
|
||||||
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Returns a bit for each frame on whether or not a finger has been detected.
|
|
||||||
* e.g. 00110 means that there is a finger in frame two and three.
|
|
||||||
*/
|
|
||||||
static char
|
|
||||||
postprocess_frames (FpDeviceEgis0570 *self, guint8 * img)
|
|
||||||
{
|
|
||||||
size_t mean[EGIS0570_IMGCOUNT] = {0, 0, 0, 0, 0};
|
|
||||||
|
|
||||||
if (!self->background)
|
|
||||||
{
|
|
||||||
self->background = g_malloc (EGIS0570_IMGWIDTH * EGIS0570_RFMGHEIGHT);
|
|
||||||
memset (self->background, 255, EGIS0570_IMGWIDTH * EGIS0570_RFMGHEIGHT);
|
|
||||||
|
|
||||||
for (size_t k = 0; k < EGIS0570_IMGCOUNT; k += 1)
|
|
||||||
{
|
|
||||||
guint8 * frame = &img[(k * EGIS0570_IMGSIZE) + EGIS0570_RFMDIS * EGIS0570_IMGWIDTH];
|
|
||||||
|
|
||||||
for (size_t i = 0; i < EGIS0570_IMGWIDTH * EGIS0570_RFMGHEIGHT; i += 1)
|
|
||||||
self->background[i] = MIN (self->background[i], frame[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t k = 0; k < EGIS0570_IMGCOUNT; k += 1)
|
|
||||||
{
|
|
||||||
guint8 * frame = &img[(k * EGIS0570_IMGSIZE) + EGIS0570_RFMDIS * EGIS0570_IMGWIDTH];
|
|
||||||
|
|
||||||
for (size_t i = 0; i < EGIS0570_IMGWIDTH * EGIS0570_RFMGHEIGHT; i += 1)
|
|
||||||
{
|
|
||||||
if (frame[i] - EGIS0570_MARGIN > self->background[i])
|
|
||||||
frame[i] -= self->background[i];
|
|
||||||
else
|
|
||||||
frame[i] = 0;
|
|
||||||
|
|
||||||
mean[k] += frame[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
mean[k] /= EGIS0570_IMGWIDTH * EGIS0570_RFMGHEIGHT;
|
|
||||||
}
|
|
||||||
|
|
||||||
char result = 0;
|
|
||||||
|
|
||||||
for (size_t k = 0; k < EGIS0570_IMGCOUNT; k += 1)
|
|
||||||
{
|
|
||||||
fp_dbg ("Finger status (picture number, mean) : %ld , %ld", k, mean[k]);
|
|
||||||
if (mean[k] > EGIS0570_MIN_MEAN)
|
|
||||||
result |= 1 << k;
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Device communication
|
|
||||||
*/
|
|
||||||
|
|
||||||
static void
|
|
||||||
data_resp_cb (FpiUsbTransfer *transfer, FpDevice *dev, gpointer user_data, GError *error)
|
|
||||||
{
|
|
||||||
unsigned char *stripdata;
|
|
||||||
gboolean end = FALSE;
|
|
||||||
FpImageDevice *img_self = FP_IMAGE_DEVICE (dev);
|
|
||||||
FpDeviceEgis0570 *self = FPI_DEVICE_EGIS0570 (dev);
|
|
||||||
|
|
||||||
if (error)
|
|
||||||
{
|
|
||||||
fpi_ssm_mark_failed (transfer->ssm, error);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int where_finger_is = postprocess_frames (self, transfer->buffer);
|
|
||||||
|
|
||||||
if (where_finger_is > 0)
|
|
||||||
{
|
|
||||||
FpiImageDeviceState state;
|
|
||||||
|
|
||||||
fpi_image_device_report_finger_status (img_self, TRUE);
|
|
||||||
|
|
||||||
g_object_get (dev, "fpi-image-device-state", &state, NULL);
|
|
||||||
if (state == FPI_IMAGE_DEVICE_STATE_CAPTURE)
|
|
||||||
{
|
|
||||||
for (size_t k = 0; k < EGIS0570_IMGCOUNT; k += 1)
|
|
||||||
{
|
|
||||||
if (where_finger_is & (1 << k))
|
|
||||||
{
|
|
||||||
struct fpi_frame *stripe = g_malloc (EGIS0570_IMGWIDTH * EGIS0570_RFMGHEIGHT + sizeof (struct fpi_frame));
|
|
||||||
stripe->delta_x = 0;
|
|
||||||
stripe->delta_y = 0;
|
|
||||||
stripdata = stripe->data;
|
|
||||||
memcpy (stripdata, (transfer->buffer) + (((k) * EGIS0570_IMGSIZE) + EGIS0570_IMGWIDTH * EGIS0570_RFMDIS), EGIS0570_IMGWIDTH * EGIS0570_RFMGHEIGHT);
|
|
||||||
self->strips = g_slist_prepend (self->strips, stripe);
|
|
||||||
self->strips_len += 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
end = TRUE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
end = TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (end)
|
|
||||||
{
|
|
||||||
if (!self->stop && (self->strips_len > 0))
|
|
||||||
{
|
|
||||||
g_autoptr(FpImage) img = NULL;
|
|
||||||
self->strips = g_slist_reverse (self->strips);
|
|
||||||
fpi_do_movement_estimation (&assembling_ctx, self->strips);
|
|
||||||
img = fpi_assemble_frames (&assembling_ctx, self->strips);
|
|
||||||
img->flags |= (FPI_IMAGE_COLORS_INVERTED | FPI_IMAGE_PARTIAL);
|
|
||||||
g_slist_free_full (self->strips, g_free);
|
|
||||||
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_report_finger_status (img_self, FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
fpi_ssm_next_state (transfer->ssm);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
recv_data_resp (FpiSsm *ssm, FpDevice *dev)
|
|
||||||
{
|
|
||||||
FpiUsbTransfer *transfer = fpi_usb_transfer_new (dev);
|
|
||||||
|
|
||||||
fpi_usb_transfer_fill_bulk (transfer, EGIS0570_EPIN, EGIS0570_INPSIZE);
|
|
||||||
|
|
||||||
transfer->ssm = ssm;
|
|
||||||
transfer->short_is_error = TRUE;
|
|
||||||
|
|
||||||
fpi_usb_transfer_submit (transfer, EGIS0570_TIMEOUT, NULL, data_resp_cb, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
cmd_resp_cb (FpiUsbTransfer *transfer, FpDevice *dev, gpointer user_data, GError *error)
|
|
||||||
{
|
|
||||||
if (error)
|
|
||||||
fpi_ssm_mark_failed (transfer->ssm, error);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
recv_cmd_resp (FpiSsm *ssm, FpDevice *dev)
|
|
||||||
{
|
|
||||||
FpiUsbTransfer *transfer = fpi_usb_transfer_new (dev);
|
|
||||||
|
|
||||||
fpi_usb_transfer_fill_bulk (transfer, EGIS0570_EPIN, EGIS0570_PKTSIZE);
|
|
||||||
|
|
||||||
transfer->ssm = ssm;
|
|
||||||
|
|
||||||
fpi_usb_transfer_submit (transfer, EGIS0570_TIMEOUT, NULL, cmd_resp_cb, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
send_cmd_req (FpiSsm *ssm, FpDevice *dev, unsigned char *pkt)
|
|
||||||
{
|
|
||||||
FpiUsbTransfer *transfer = fpi_usb_transfer_new (dev);
|
|
||||||
|
|
||||||
fpi_usb_transfer_fill_bulk_full (transfer, EGIS0570_EPOUT, pkt, EGIS0570_PKTSIZE, NULL);
|
|
||||||
|
|
||||||
transfer->ssm = ssm;
|
|
||||||
transfer->short_is_error = TRUE;
|
|
||||||
|
|
||||||
fpi_usb_transfer_submit (transfer, EGIS0570_TIMEOUT, NULL, fpi_ssm_usb_transfer_cb, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* SSM States
|
|
||||||
*/
|
|
||||||
|
|
||||||
enum sm_states {
|
|
||||||
SM_INIT,
|
|
||||||
SM_START,
|
|
||||||
SM_REQ,
|
|
||||||
SM_RESP,
|
|
||||||
SM_REC_DATA,
|
|
||||||
SM_DONE,
|
|
||||||
SM_STATES_NUM
|
|
||||||
};
|
|
||||||
|
|
||||||
static void
|
|
||||||
ssm_run_state (FpiSsm *ssm, FpDevice *dev)
|
|
||||||
{
|
|
||||||
FpDeviceEgis0570 *self = FPI_DEVICE_EGIS0570 (dev);
|
|
||||||
FpImageDevice *img_dev = FP_IMAGE_DEVICE (dev);
|
|
||||||
|
|
||||||
switch (fpi_ssm_get_cur_state (ssm))
|
|
||||||
{
|
|
||||||
case SM_INIT:
|
|
||||||
self->pkt_type = PKT_TYPE_INIT;
|
|
||||||
fpi_ssm_next_state (ssm);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SM_START:
|
|
||||||
if (self->stop)
|
|
||||||
{
|
|
||||||
fp_dbg ("deactivating, marking completed");
|
|
||||||
fpi_ssm_mark_completed (ssm);
|
|
||||||
fpi_image_device_deactivate_complete (img_dev, NULL);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
self->pkt_num = 0;
|
|
||||||
fpi_ssm_next_state (ssm);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SM_REQ:
|
|
||||||
if (self->pkt_type == PKT_TYPE_INIT)
|
|
||||||
send_cmd_req (ssm, dev, init_pkts[self->pkt_num]);
|
|
||||||
else
|
|
||||||
send_cmd_req (ssm, dev, repeat_pkts[self->pkt_num]);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SM_RESP:
|
|
||||||
if (is_last_pkt (dev) == FALSE)
|
|
||||||
{
|
|
||||||
recv_cmd_resp (ssm, dev);
|
|
||||||
self->pkt_num += 1;
|
|
||||||
fpi_ssm_jump_to_state (ssm, SM_REQ);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (self->pkt_type == PKT_TYPE_INIT)
|
|
||||||
self->pkt_type = PKT_TYPE_REPEAT;
|
|
||||||
|
|
||||||
fpi_ssm_next_state (ssm);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SM_REC_DATA:
|
|
||||||
recv_data_resp (ssm, dev);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SM_DONE:
|
|
||||||
fpi_ssm_jump_to_state (ssm, SM_START);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
g_assert_not_reached ();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Activation
|
|
||||||
*/
|
|
||||||
|
|
||||||
static void
|
|
||||||
loop_complete (FpiSsm *ssm, FpDevice *dev, GError *error)
|
|
||||||
{
|
|
||||||
FpImageDevice *img_dev = FP_IMAGE_DEVICE (dev);
|
|
||||||
FpDeviceEgis0570 *self = FPI_DEVICE_EGIS0570 (dev);
|
|
||||||
|
|
||||||
self->running = FALSE;
|
|
||||||
g_clear_pointer (&self->background, g_free);
|
|
||||||
|
|
||||||
if (error)
|
|
||||||
fpi_image_device_session_error (img_dev, error);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
dev_activate (FpImageDevice *dev)
|
|
||||||
{
|
|
||||||
FpDeviceEgis0570 *self = FPI_DEVICE_EGIS0570 (dev);
|
|
||||||
FpiSsm *ssm = fpi_ssm_new (FP_DEVICE (dev), ssm_run_state, SM_STATES_NUM);
|
|
||||||
|
|
||||||
self->stop = FALSE;
|
|
||||||
|
|
||||||
fpi_ssm_start (ssm, loop_complete);
|
|
||||||
|
|
||||||
self->running = TRUE;
|
|
||||||
|
|
||||||
fpi_image_device_activate_complete (dev, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Opening
|
|
||||||
*/
|
|
||||||
|
|
||||||
static void
|
|
||||||
dev_init (FpImageDevice *dev)
|
|
||||||
{
|
|
||||||
GError *error = NULL;
|
|
||||||
|
|
||||||
g_usb_device_claim_interface (fpi_device_get_usb_device (FP_DEVICE (dev)), 0, 0, &error);
|
|
||||||
|
|
||||||
fpi_image_device_open_complete (dev, error);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Closing
|
|
||||||
*/
|
|
||||||
|
|
||||||
static void
|
|
||||||
dev_deinit (FpImageDevice *dev)
|
|
||||||
{
|
|
||||||
GError *error = NULL;
|
|
||||||
|
|
||||||
g_usb_device_release_interface (fpi_device_get_usb_device (FP_DEVICE (dev)), 0, 0, &error);
|
|
||||||
|
|
||||||
fpi_image_device_close_complete (dev, error);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Deactivation
|
|
||||||
*/
|
|
||||||
|
|
||||||
static void
|
|
||||||
dev_deactivate (FpImageDevice *dev)
|
|
||||||
{
|
|
||||||
FpDeviceEgis0570 *self = FPI_DEVICE_EGIS0570 (dev);
|
|
||||||
|
|
||||||
if (self->running)
|
|
||||||
self->stop = TRUE;
|
|
||||||
else
|
|
||||||
fpi_image_device_deactivate_complete (dev, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Driver data
|
|
||||||
*/
|
|
||||||
|
|
||||||
static const FpIdEntry id_table[] = {
|
|
||||||
{ .vid = 0x1c7a, .pid = 0x0570, },
|
|
||||||
{ .vid = 0x1c7a, .pid = 0x0571, },
|
|
||||||
{ .vid = 0, .pid = 0, },
|
|
||||||
};
|
|
||||||
|
|
||||||
static void
|
|
||||||
fpi_device_egis0570_init (FpDeviceEgis0570 *self)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
fpi_device_egis0570_class_init (FpDeviceEgis0570Class *klass)
|
|
||||||
{
|
|
||||||
FpDeviceClass *dev_class = FP_DEVICE_CLASS (klass);
|
|
||||||
FpImageDeviceClass *img_class = FP_IMAGE_DEVICE_CLASS (klass);
|
|
||||||
|
|
||||||
dev_class->id = "egis0570";
|
|
||||||
dev_class->full_name = "Egis Technology Inc. (aka. LighTuning) 0570";
|
|
||||||
dev_class->type = FP_DEVICE_TYPE_USB;
|
|
||||||
dev_class->id_table = id_table;
|
|
||||||
dev_class->scan_type = FP_SCAN_TYPE_SWIPE;
|
|
||||||
|
|
||||||
img_class->img_open = dev_init;
|
|
||||||
img_class->img_close = dev_deinit;
|
|
||||||
img_class->activate = dev_activate;
|
|
||||||
img_class->deactivate = dev_deactivate;
|
|
||||||
|
|
||||||
img_class->img_width = EGIS0570_IMGWIDTH;
|
|
||||||
img_class->img_height = -1;
|
|
||||||
|
|
||||||
img_class->bz3_threshold = EGIS0570_BZ3_THRESHOLD; /* security issue */
|
|
||||||
}
|
|
||||||
@@ -1,177 +0,0 @@
|
|||||||
/*
|
|
||||||
* Egis Technology Inc. (aka. LighTuning) 0570 driver for libfprint
|
|
||||||
* Copyright (C) 2021 Maxim Kolesnikov <kolesnikov@svyazcom.ru>
|
|
||||||
* Copyright (C) 2021 Saeed/Ali Rk <saeed.ali.rahimi@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
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef __EGIS0570_H
|
|
||||||
|
|
||||||
#define __EGIS0570_H 1
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Device data
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define EGIS0570_CONF 1
|
|
||||||
#define EGIS0570_INTF 0
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Device endpoints
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define EGIS0570_EPOUT 0x04 /* ( 4 | FPI_USB_ENDPOINT_OUT ) */
|
|
||||||
#define EGIS0570_EPIN 0x83 /* ( 3 | FPI_USB_ENDPOINT_IN ) */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Initialization packets (7 bytes each)
|
|
||||||
*
|
|
||||||
* First 4 bytes are equivalent to string "EGIS", which must be just a company identificator
|
|
||||||
* Other 3 bytes are not recognized yet and may be not important, as they are always the same
|
|
||||||
|
|
||||||
* Answers for each packet contain 7 bytes again
|
|
||||||
* First 4 bytes are reversed "EGIS", which is "SIGE", which is company ID again
|
|
||||||
* Other 3 bytes are not recognized yet
|
|
||||||
* But there is a pattern.
|
|
||||||
* Sending last packet makes sensor return image
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define EGIS0570_TIMEOUT 10000
|
|
||||||
#define EGIS0570_PKTSIZE 7
|
|
||||||
|
|
||||||
#define EGIS0570_INIT_TOTAL (sizeof ((init_pkts)) / sizeof ((init_pkts[0])))
|
|
||||||
|
|
||||||
static unsigned char init_pkts[][EGIS0570_PKTSIZE] =
|
|
||||||
{
|
|
||||||
{ 0x45, 0x47, 0x49, 0x53, 0x01, 0x20, 0x3f },
|
|
||||||
{ 0x45, 0x47, 0x49, 0x53, 0x01, 0x58, 0x3f },
|
|
||||||
{ 0x45, 0x47, 0x49, 0x53, 0x01, 0x21, 0x09 },
|
|
||||||
{ 0x45, 0x47, 0x49, 0x53, 0x01, 0x57, 0x09 },
|
|
||||||
{ 0x45, 0x47, 0x49, 0x53, 0x01, 0x22, 0x03 },
|
|
||||||
{ 0x45, 0x47, 0x49, 0x53, 0x01, 0x56, 0x03 },
|
|
||||||
{ 0x45, 0x47, 0x49, 0x53, 0x01, 0x23, 0x01 },
|
|
||||||
{ 0x45, 0x47, 0x49, 0x53, 0x01, 0x55, 0x01 },
|
|
||||||
{ 0x45, 0x47, 0x49, 0x53, 0x01, 0x24, 0x01 },
|
|
||||||
{ 0x45, 0x47, 0x49, 0x53, 0x01, 0x54, 0x01 },
|
|
||||||
{ 0x45, 0x47, 0x49, 0x53, 0x01, 0x16, 0x3e },
|
|
||||||
{ 0x45, 0x47, 0x49, 0x53, 0x01, 0x09, 0x0b },
|
|
||||||
{ 0x45, 0x47, 0x49, 0x53, 0x01, 0x14, 0x03 },
|
|
||||||
{ 0x45, 0x47, 0x49, 0x53, 0x01, 0x15, 0x00 },
|
|
||||||
{ 0x45, 0x47, 0x49, 0x53, 0x01, 0x02, 0x0f },
|
|
||||||
{ 0x45, 0x47, 0x49, 0x53, 0x01, 0x10, 0x00 },
|
|
||||||
{ 0x45, 0x47, 0x49, 0x53, 0x01, 0x11, 0x38 },
|
|
||||||
{ 0x45, 0x47, 0x49, 0x53, 0x01, 0x12, 0x00 },
|
|
||||||
{ 0x45, 0x47, 0x49, 0x53, 0x01, 0x13, 0x71 },
|
|
||||||
{ 0x45, 0x47, 0x49, 0x53, 0x01, 0x03, 0x80 },
|
|
||||||
{ 0x45, 0x47, 0x49, 0x53, 0x00, 0x02, 0x80 },
|
|
||||||
{ 0x45, 0x47, 0x49, 0x53, 0x01, 0x02, 0x2f },
|
|
||||||
{ 0x45, 0x47, 0x49, 0x53, 0x06, 0x00, 0xfe } /* image returned after this packet */
|
|
||||||
};
|
|
||||||
|
|
||||||
/* There is another Packet !
|
|
||||||
* That just Work the same !!
|
|
||||||
* And the Size is different !!!
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
#define EGIS0570_INIT_TOTAL2 (sizeof((init_pkts2)) / sizeof((init_pkts2[0])))
|
|
||||||
|
|
||||||
static unsigned char init_pkts2[][EGIS0570_PKTSIZE] =
|
|
||||||
{
|
|
||||||
{0x45, 0x47, 0x49, 0x53, 0x01, 0x10, 0x00},
|
|
||||||
{0x45, 0x47, 0x49, 0x53, 0x01, 0x11, 0x38},
|
|
||||||
{0x45, 0x47, 0x49, 0x53, 0x01, 0x12, 0x00},
|
|
||||||
{0x45, 0x47, 0x49, 0x53, 0x01, 0x13, 0x71},
|
|
||||||
{0x45, 0x47, 0x49, 0x53, 0x01, 0x20, 0x3f},
|
|
||||||
{0x45, 0x47, 0x49, 0x53, 0x01, 0x58, 0x3f},
|
|
||||||
{0x45, 0x47, 0x49, 0x53, 0x01, 0x21, 0x07},
|
|
||||||
{0x45, 0x47, 0x49, 0x53, 0x01, 0x57, 0x07},
|
|
||||||
{0x45, 0x47, 0x49, 0x53, 0x01, 0x22, 0x02},
|
|
||||||
{0x45, 0x47, 0x49, 0x53, 0x01, 0x56, 0x02},
|
|
||||||
{0x45, 0x47, 0x49, 0x53, 0x01, 0x23, 0x00},
|
|
||||||
{0x45, 0x47, 0x49, 0x53, 0x01, 0x55, 0x00},
|
|
||||||
{0x45, 0x47, 0x49, 0x53, 0x01, 0x24, 0x00},
|
|
||||||
{0x45, 0x47, 0x49, 0x53, 0x01, 0x54, 0x00},
|
|
||||||
{0x45, 0x47, 0x49, 0x53, 0x01, 0x25, 0x00},
|
|
||||||
{0x45, 0x47, 0x49, 0x53, 0x01, 0x53, 0x00},
|
|
||||||
{0x45, 0x47, 0x49, 0x53, 0x01, 0x15, 0x00},
|
|
||||||
{0x45, 0x47, 0x49, 0x53, 0x01, 0x16, 0x3b},
|
|
||||||
{0x45, 0x47, 0x49, 0x53, 0x01, 0x09, 0x0a},
|
|
||||||
{0x45, 0x47, 0x49, 0x53, 0x01, 0x14, 0x00},
|
|
||||||
{0x45, 0x47, 0x49, 0x53, 0x01, 0x02, 0x0f},
|
|
||||||
{0x45, 0x47, 0x49, 0x53, 0x01, 0x03, 0x80},
|
|
||||||
{0x45, 0x47, 0x49, 0x53, 0x00, 0x02, 0x80},
|
|
||||||
{0x45, 0x47, 0x49, 0x53, 0x01, 0x02, 0x2f},
|
|
||||||
{0x45, 0x47, 0x49, 0x53, 0x06, 0x00, 0xfe}
|
|
||||||
};
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* After sending initial packets device returns image data (32512 bytes)
|
|
||||||
* To ask device to send image data again, host needs to send four additional packets
|
|
||||||
* Further work is to repeatedly send four repeat packets and read image data
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define EGIS0570_INPSIZE 32512
|
|
||||||
|
|
||||||
/* 5 image with captured in different time of size 114 * 57 = 6498
|
|
||||||
* 5 * 6498 = 32490 plus 22 extra unrecognized char size data
|
|
||||||
* Two continuous image in this 5 images may have time delay of less than 20ms
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define EGIS0570_IMGSIZE 6498
|
|
||||||
#define EGIS0570_IMGWIDTH 114
|
|
||||||
#define EGIS0570_IMGHEIGHT 57
|
|
||||||
|
|
||||||
/* size of middle area that is used from each frame */
|
|
||||||
#define EGIS0570_RFMGHEIGHT 17
|
|
||||||
/* rows to ignore from top and bottom of the image*/
|
|
||||||
#define EGIS0570_RFMDIS (EGIS0570_IMGHEIGHT - EGIS0570_RFMGHEIGHT) / 2
|
|
||||||
#define EGIS0570_IMGCOUNT 5
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Image repeat request
|
|
||||||
* First 4 bytes are the same as in initialization packets
|
|
||||||
* Have no idea what the other 3 bytes mean
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define EGIS0570_REPEAT_TOTAL (sizeof ((repeat_pkts)) / sizeof ((repeat_pkts[0])))
|
|
||||||
|
|
||||||
static unsigned char repeat_pkts[][EGIS0570_PKTSIZE] =
|
|
||||||
{
|
|
||||||
{ 0x45, 0x47, 0x49, 0x53, 0x01, 0x02, 0x0f },
|
|
||||||
{ 0x45, 0x47, 0x49, 0x53, 0x00, 0x02, 0x0f },
|
|
||||||
{ 0x45, 0x47, 0x49, 0x53, 0x01, 0x02, 0x2f },
|
|
||||||
{ 0x45, 0x47, 0x49, 0x53, 0x06, 0x00, 0xfe } /* image returned after this packet */
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This sensor is small so I decided to reduce bz3_threshold from
|
|
||||||
* 40 to 10 to have more success to fail ratio
|
|
||||||
* Bozorth3 Algorithm seems not fine at the end
|
|
||||||
* foreget about security :))
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define EGIS0570_BZ3_THRESHOLD 25 /* and even less What a joke */
|
|
||||||
|
|
||||||
#define EGIS0570_MIN_MEAN 20
|
|
||||||
#define EGIS0570_MARGIN 3
|
|
||||||
|
|
||||||
#define EGIS0570_RESIZE 2
|
|
||||||
|
|
||||||
#endif
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,223 +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 gsize egismoc_write_prefix_len = sizeof (egismoc_write_prefix) / sizeof (egismoc_write_prefix[0]);
|
|
||||||
|
|
||||||
static guchar egismoc_read_prefix[] = {'S', 'I', 'G', 'E', 0x00, 0x00, 0x00, 0x01};
|
|
||||||
static gsize egismoc_read_prefix_len = sizeof (egismoc_read_prefix) / sizeof (egismoc_read_prefix[0]);
|
|
||||||
|
|
||||||
|
|
||||||
/* hard-coded command payloads */
|
|
||||||
|
|
||||||
static guchar cmd_fw_version[] = {0x00, 0x00, 0x00, 0x07, 0x50, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x0c};
|
|
||||||
static gsize cmd_fw_version_len = sizeof (cmd_fw_version) / sizeof (cmd_fw_version[0]);
|
|
||||||
static guchar rsp_fw_version_suffix[] = {0x90, 0x00};
|
|
||||||
static gsize rsp_fw_version_suffix_len = sizeof (rsp_fw_version_suffix) / sizeof (rsp_fw_version_suffix[0]);
|
|
||||||
|
|
||||||
static guchar cmd_list[] = {0x00, 0x00, 0x00, 0x07, 0x50, 0x19, 0x04, 0x00, 0x00, 0x01, 0x40};
|
|
||||||
static gsize cmd_list_len = sizeof (cmd_list) / sizeof (cmd_list[0]);
|
|
||||||
|
|
||||||
static guchar cmd_sensor_reset[] = {0x00, 0x00, 0x00, 0x04, 0x50, 0x1a, 0x00, 0x00};
|
|
||||||
static gsize cmd_sensor_reset_len = sizeof (cmd_sensor_reset) / sizeof (cmd_sensor_reset[0]);
|
|
||||||
|
|
||||||
static guchar cmd_sensor_check[] = {0x00, 0x00, 0x00, 0x04, 0x50, 0x17, 0x02, 0x00};
|
|
||||||
static gsize cmd_sensor_check_len = sizeof (cmd_sensor_check) / sizeof (cmd_sensor_check[0]);
|
|
||||||
|
|
||||||
static guchar cmd_sensor_identify[] = {0x00, 0x00, 0x00, 0x04, 0x50, 0x17, 0x01, 0x01};
|
|
||||||
static gsize cmd_sensor_identify_len = sizeof (cmd_sensor_identify) / sizeof (cmd_sensor_identify[0]);
|
|
||||||
static guchar rsp_identify_match_suffix[] = {0x90, 0x00};
|
|
||||||
static gsize rsp_identify_match_suffix_len = sizeof (rsp_identify_match_suffix) / sizeof (rsp_identify_match_suffix[0]);
|
|
||||||
static guchar rsp_identify_notmatch_suffix[] = {0x90, 0x04};
|
|
||||||
static gsize rsp_identify_notmatch_suffix_len = sizeof (rsp_identify_notmatch_suffix) / sizeof (rsp_identify_notmatch_suffix[0]);
|
|
||||||
|
|
||||||
static guchar cmd_sensor_enroll[] = {0x00, 0x00, 0x00, 0x04, 0x50, 0x17, 0x01, 0x00};
|
|
||||||
static gsize cmd_sensor_enroll_len = sizeof (cmd_sensor_enroll) / sizeof (cmd_sensor_enroll[0]);
|
|
||||||
|
|
||||||
static guchar cmd_enroll_starting[] = {0x00, 0x00, 0x00, 0x07, 0x50, 0x16, 0x01, 0x00, 0x00, 0x00, 0x20};
|
|
||||||
static gsize cmd_enroll_starting_len = sizeof (cmd_enroll_starting) / sizeof (cmd_enroll_starting[0]);
|
|
||||||
|
|
||||||
static guchar cmd_sensor_start_capture[] = {0x00, 0x00, 0x00, 0x04, 0x50, 0x16, 0x02, 0x01};
|
|
||||||
static gsize cmd_sensor_start_capture_len = sizeof (cmd_sensor_start_capture) / sizeof (cmd_sensor_start_capture[0]);
|
|
||||||
|
|
||||||
static guchar cmd_read_capture[] = {0x00, 0x00, 0x00, 0x07, 0x50, 0x16, 0x02, 0x02, 0x00, 0x00, 0x02};
|
|
||||||
static gsize cmd_read_capture_len = sizeof (cmd_read_capture) / sizeof (cmd_read_capture[0]);
|
|
||||||
static guchar rsp_read_success_prefix[] = {0x00, 0x00, 0x00, 0x04};
|
|
||||||
static gsize rsp_read_success_prefix_len = sizeof (rsp_read_success_prefix) / sizeof (rsp_read_success_prefix[0]);
|
|
||||||
static guchar rsp_read_success_suffix[] = {0x90, 0x00};
|
|
||||||
static gsize rsp_read_success_suffix_len = sizeof (rsp_read_success_suffix) / sizeof (rsp_read_success_suffix[0]);
|
|
||||||
static guchar rsp_read_offcenter_prefix[] = {0x00, 0x00, 0x00, 0x04};
|
|
||||||
static gsize rsp_read_offcenter_prefix_len = sizeof (rsp_read_offcenter_prefix) / sizeof (rsp_read_offcenter_prefix[0]);
|
|
||||||
static guchar rsp_read_offcenter_suffix[] = {0x64, 0x91};
|
|
||||||
static gsize rsp_read_offcenter_suffix_len = sizeof (rsp_read_offcenter_suffix) / sizeof (rsp_read_offcenter_suffix[0]);
|
|
||||||
static guchar rsp_read_dirty_prefix[] = {0x00, 0x00, 0x00, 0x02, 0x64};
|
|
||||||
static gsize rsp_read_dirty_prefix_len = sizeof (rsp_read_dirty_prefix) / sizeof (rsp_read_dirty_prefix[0]);
|
|
||||||
|
|
||||||
static guchar cmd_commit_starting[] = {0x00, 0x00, 0x00, 0x07, 0x50, 0x16, 0x05, 0x00, 0x00, 0x00, 0x20};
|
|
||||||
static gsize cmd_commit_starting_len = sizeof (cmd_commit_starting) / sizeof (cmd_commit_starting[0]);
|
|
||||||
|
|
||||||
|
|
||||||
/* commands which exist on the device but are currently not used */
|
|
||||||
/*
|
|
||||||
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 gsize cmd_new_print_prefix_len = sizeof (cmd_new_print_prefix) / sizeof (cmd_new_print_prefix[0]);
|
|
||||||
|
|
||||||
static guchar cmd_delete_prefix[] = {0x50, 0x18, 0x04, 0x00, 0x00};
|
|
||||||
static gsize cmd_delete_prefix_len = sizeof (cmd_delete_prefix) / sizeof (cmd_delete_prefix[0]);
|
|
||||||
static guchar rsp_delete_success_prefix[] = {0x00, 0x00, 0x00, 0x02, 0x90, 0x00};
|
|
||||||
static gsize rsp_delete_success_prefix_len = sizeof (rsp_delete_success_prefix) / sizeof (rsp_delete_success_prefix[0]);
|
|
||||||
|
|
||||||
static guchar cmd_check_prefix_type1[] = {0x50, 0x17, 0x03, 0x00, 0x00};
|
|
||||||
static gsize cmd_check_prefix_type1_len = sizeof (cmd_check_prefix_type1) / sizeof (cmd_check_prefix_type1[0]);
|
|
||||||
static guchar cmd_check_prefix_type2[] = {0x50, 0x17, 0x03, 0x80, 0x00};
|
|
||||||
static gsize cmd_check_prefix_type2_len = sizeof (cmd_check_prefix_type2) / sizeof (cmd_check_prefix_type2[0]);
|
|
||||||
static guchar cmd_check_suffix[] = {0x00, 0x40};
|
|
||||||
static gsize cmd_check_suffix_len = sizeof (cmd_check_suffix) / sizeof (cmd_check_suffix[0]);
|
|
||||||
static guchar rsp_check_not_yet_enrolled_suffix[] = {0x90, 0x04};
|
|
||||||
static gsize rsp_check_not_yet_enrolled_suffix_len = sizeof (rsp_check_not_yet_enrolled_suffix) / sizeof (rsp_check_not_yet_enrolled_suffix[0]);
|
|
||||||
|
|
||||||
|
|
||||||
/* SSM task states and various status enums */
|
|
||||||
|
|
||||||
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;
|
|
||||||
@@ -357,7 +357,7 @@ elan_cmd_cb (FpiUsbTransfer *transfer, FpDevice *dev,
|
|||||||
if (transfer->endpoint & FPI_USB_ENDPOINT_IN)
|
if (transfer->endpoint & FPI_USB_ENDPOINT_IN)
|
||||||
{
|
{
|
||||||
/* just finished receiving */
|
/* 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);
|
elan_cmd_done (ssm);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -760,7 +760,7 @@ calibrate_run_state (FpiSsm *ssm, FpDevice *dev)
|
|||||||
if (self->calib_status == 0x00 &&
|
if (self->calib_status == 0x00 &&
|
||||||
self->last_read[0] == 0x01)
|
self->last_read[0] == 0x01)
|
||||||
self->calib_status = 0x01;
|
self->calib_status = 0x01;
|
||||||
fpi_ssm_next_state_delayed (ssm, 50);
|
fpi_ssm_next_state_delayed (ssm, 50, NULL);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|||||||
@@ -213,14 +213,8 @@ static const FpIdEntry elan_id_table[] = {
|
|||||||
{.vid = ELAN_VEND_ID, .pid = 0x0c31, .driver_data = ELAN_ALL_DEV},
|
{.vid = ELAN_VEND_ID, .pid = 0x0c31, .driver_data = ELAN_ALL_DEV},
|
||||||
{.vid = ELAN_VEND_ID, .pid = 0x0c32, .driver_data = ELAN_ALL_DEV},
|
{.vid = ELAN_VEND_ID, .pid = 0x0c32, .driver_data = ELAN_ALL_DEV},
|
||||||
{.vid = ELAN_VEND_ID, .pid = 0x0c33, .driver_data = ELAN_ALL_DEV},
|
{.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 = 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 = 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_ALL_DEV},
|
|
||||||
{.vid = 0, .pid = 0, .driver_data = 0},
|
{.vid = 0, .pid = 0, .driver_data = 0},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,196 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2021 Elan 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 (FpiDeviceElanmoc, fpi_device_elanmoc, FPI, DEVICE_ELANMOC, FpDevice)
|
|
||||||
|
|
||||||
#define ELAN_MOC_DRIVER_FULLNAME "Elan MOC Sensors"
|
|
||||||
#define ELAN_M0C_CMD_LEN 0x3
|
|
||||||
#define ELAN_EP_CMD_OUT (0x1 | LIBUSB_ENDPOINT_OUT)
|
|
||||||
#define ELAN_EP_CMD_IN (0x3 | LIBUSB_ENDPOINT_IN)
|
|
||||||
#define ELAN_EP_MOC_CMD_IN (0x4 | LIBUSB_ENDPOINT_IN)
|
|
||||||
#define ELAN_EP_IMG_IN (0x2 | LIBUSB_ENDPOINT_IN)
|
|
||||||
|
|
||||||
#define ELAN_MOC_CMD_TIMEOUT 5000
|
|
||||||
#define ELAN_MOC_CAL_RETRY 500
|
|
||||||
#define ELAN_MOC_ENROLL_TIMES 9
|
|
||||||
#define ELAN_MAX_USER_ID_LEN 92
|
|
||||||
#define ELAN_MAX_ENROLL_NUM 9
|
|
||||||
|
|
||||||
#define ELAN_MSG_VERIFY_ERR 0xfd
|
|
||||||
#define ELAN_MSG_DIRTY 0xfb
|
|
||||||
#define ELAN_MSG_AREA_NOT_ENOUGH 0xfe
|
|
||||||
#define ELAN_MSG_TOO_HIGH 0x41
|
|
||||||
#define ELAN_MSG_TOO_LEFT 0x42
|
|
||||||
#define ELAN_MSG_TOO_LOW 0x43
|
|
||||||
#define ELAN_MSG_TOO_RIGHT 0x44
|
|
||||||
#define ELAN_MSG_OK 0x00
|
|
||||||
|
|
||||||
#define ELAN_MAX_HDR_LEN 3
|
|
||||||
#define ELAN_USERDATE_SIZE (ELAN_MAX_USER_ID_LEN + 3)
|
|
||||||
|
|
||||||
#define ELAN_MSG_DRIVER_VERSION "1004"
|
|
||||||
|
|
||||||
struct elanmoc_cmd
|
|
||||||
{
|
|
||||||
unsigned char cmd_header[ELAN_MAX_HDR_LEN];
|
|
||||||
int cmd_len;
|
|
||||||
int resp_len;
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct elanmoc_cmd fw_ver_cmd = {
|
|
||||||
.cmd_header = {0x40, 0x19},
|
|
||||||
.cmd_len = 2,
|
|
||||||
.resp_len = 2,
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct elanmoc_cmd sensor_dim_cmd = {
|
|
||||||
.cmd_header = {0x00, 0x0c},
|
|
||||||
.cmd_len = 2,
|
|
||||||
.resp_len = 4,
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct elanmoc_cmd cal_status_cmd = {
|
|
||||||
.cmd_header = {0x40, 0xff, 0x00},
|
|
||||||
.cmd_len = 3,
|
|
||||||
.resp_len = 2,
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct elanmoc_cmd enrolled_number_cmd = {
|
|
||||||
.cmd_header = {0x40, 0xff, 0x04},
|
|
||||||
.cmd_len = 3,
|
|
||||||
.resp_len = 2,
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct elanmoc_cmd elanmoc_verify_cmd = {
|
|
||||||
.cmd_header = {0x40, 0xff, 0x73},
|
|
||||||
.cmd_len = 5,
|
|
||||||
.resp_len = 2,
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct elanmoc_cmd elanmoc_above_cmd = {
|
|
||||||
.cmd_header = {0x40, 0xff, 0x02},
|
|
||||||
.cmd_len = 3,
|
|
||||||
.resp_len = 0,
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct elanmoc_cmd elanmoc_enroll_cmd = {
|
|
||||||
.cmd_header = {0x40, 0xff, 0x01},
|
|
||||||
.cmd_len = 7,
|
|
||||||
.resp_len = 2,
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct elanmoc_cmd elanmoc_delete_cmd = {
|
|
||||||
.cmd_header = {0x40, 0xff, 0x13},
|
|
||||||
.cmd_len = 128,
|
|
||||||
.resp_len = 2,
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct elanmoc_cmd elanmoc_enroll_commit_cmd = {
|
|
||||||
.cmd_header = {0x40, 0xff, 0x11},
|
|
||||||
.cmd_len = 128,
|
|
||||||
.resp_len = 2,
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct elanmoc_cmd elanmoc_remove_all_cmd = {
|
|
||||||
.cmd_header = {0x40, 0xff, 0x98},
|
|
||||||
.cmd_len = 3,
|
|
||||||
.resp_len = 2,
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct elanmoc_cmd elanmoc_get_userid_cmd = {
|
|
||||||
.cmd_header = {0x43, 0x21, 0x00},
|
|
||||||
.cmd_len = 3,
|
|
||||||
.resp_len = 97,
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct elanmoc_cmd elanmoc_set_mod_cmd = {
|
|
||||||
.cmd_header = {0x40, 0xff, 0x14},
|
|
||||||
.cmd_len = 4,
|
|
||||||
.resp_len = 2,
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct elanmoc_cmd elanmoc_check_reenroll_cmd = {
|
|
||||||
.cmd_header = {0x40, 0xff, 0x22},
|
|
||||||
.cmd_len = 3 + ELAN_USERDATE_SIZE,
|
|
||||||
.resp_len = 2,
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef void (*ElanCmdMsgCallback) (FpiDeviceElanmoc *self,
|
|
||||||
GError *error);
|
|
||||||
|
|
||||||
enum moc_enroll_states {
|
|
||||||
MOC_ENROLL_GET_ENROLLED_NUM,
|
|
||||||
MOC_ENROLL_REENROLL_CHECK,
|
|
||||||
MOC_ENROLL_WAIT_FINGER,
|
|
||||||
MOC_ENROLL_COMMIT_RESULT,
|
|
||||||
MOC_ENROLL_NUM_STATES,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum moc_list_states {
|
|
||||||
MOC_LIST_GET_ENROLLED,
|
|
||||||
MOC_LIST_GET_FINGER,
|
|
||||||
MOC_LIST_NUM_STATES,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum delete_states {
|
|
||||||
DELETE_SEND_CMD,
|
|
||||||
DELETE_NUM_STATES,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum dev_init_states {
|
|
||||||
DEV_WAIT_READY,
|
|
||||||
DEV_SET_MODE,
|
|
||||||
DEV_GET_VER,
|
|
||||||
DEV_GET_DIM,
|
|
||||||
DEV_GET_ENROLLED,
|
|
||||||
DEV_INIT_STATES,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum dev_exit_states {
|
|
||||||
DEV_EXIT_ABOVE,
|
|
||||||
DEV_EXIT_STATES,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct _FpiDeviceElanmoc
|
|
||||||
{
|
|
||||||
FpDevice parent;
|
|
||||||
FpiSsm *task_ssm;
|
|
||||||
FpiSsm *cmd_ssm;
|
|
||||||
FpiUsbTransfer *cmd_transfer;
|
|
||||||
gboolean cmd_cancelable;
|
|
||||||
gsize cmd_len_in;
|
|
||||||
unsigned short fw_ver;
|
|
||||||
unsigned char x_trace;
|
|
||||||
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;
|
|
||||||
GPtrArray *list_result;
|
|
||||||
};
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,382 +0,0 @@
|
|||||||
/*
|
|
||||||
* Elan SPI driver for libfprint
|
|
||||||
*
|
|
||||||
* Copyright (C) 2021 Matthew Mirvish <matthew@mm12.xyz>
|
|
||||||
*
|
|
||||||
* 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 <config.h>
|
|
||||||
|
|
||||||
#ifndef HAVE_UDEV
|
|
||||||
#error "elanspi requires udev"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <fp-device.h>
|
|
||||||
#include <fpi-device.h>
|
|
||||||
|
|
||||||
#define ELANSPI_TP_PID 0x04f3
|
|
||||||
|
|
||||||
/* Sensor ID information copied from the windows driver */
|
|
||||||
|
|
||||||
struct elanspi_sensor_entry
|
|
||||||
{
|
|
||||||
unsigned char sensor_id, height, width, ic_version;
|
|
||||||
gboolean is_otp_model;
|
|
||||||
const gchar * name;
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct elanspi_sensor_entry elanspi_sensor_table[] = {
|
|
||||||
{0x0, 0x78, 0x78, 0x0, 0x0, "eFSA120S"},
|
|
||||||
{0x1, 0x78, 0x78, 0x1, 0x1, "eFSA120SA"},
|
|
||||||
{0x2, 0xA0, 0xA0, 0x0, 0x0, "eFSA160S"},
|
|
||||||
{0x3, 0xd0, 0x50, 0x0, 0x0, "eFSA820R"},
|
|
||||||
{0x4, 0xC0, 0x38, 0x0, 0x0, "eFSA519R"},
|
|
||||||
{0x5, 0x60, 0x60, 0x0, 0x0, "eFSA96S"},
|
|
||||||
{0x6, 0x60, 0x60, 0x1, 0x1, "eFSA96SA"},
|
|
||||||
{0x7, 0x60, 0x60, 0x2, 0x1, "eFSA96SB"},
|
|
||||||
{0x8, 0xa0, 0x50, 0x1, 0x1, "eFSA816RA"},
|
|
||||||
{0x9, 0x90, 0x40, 0x1, 0x1, "eFSA614RA"},
|
|
||||||
{0xA, 0x90, 0x40, 0x2, 0x1, "eFSA614RB"},
|
|
||||||
{0xB, 0x40, 0x58, 0x1, 0x1, "eFSA688RA"},
|
|
||||||
{0xC, 0x50, 0x50, 0x1, 0x0, "eFSA80SA"},
|
|
||||||
{0xD, 0x47, 0x80, 0x1, 0x1, "eFSA712RA"},
|
|
||||||
{0xE, 0x50, 0x50, 0x2, 0x0, "eFSA80SC"},
|
|
||||||
{0, 0, 0, 0, 0, NULL}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct elanspi_reg_entry
|
|
||||||
{
|
|
||||||
unsigned char addr, value;
|
|
||||||
/* terminates with 0xFF, 0xFF since register 0x0 is valid */
|
|
||||||
};
|
|
||||||
|
|
||||||
struct elanspi_regtable
|
|
||||||
{
|
|
||||||
const struct elanspi_reg_entry *other;
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
unsigned char sid;
|
|
||||||
const struct elanspi_reg_entry *table;
|
|
||||||
} entries[];
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct elanspi_reg_entry elanspi_calibration_table_default[] = {
|
|
||||||
{0x05, 0x60},
|
|
||||||
{0x06, 0xc0},
|
|
||||||
{0x07, 0x80},
|
|
||||||
{0x08, 0x04},
|
|
||||||
{0x0a, 0x97},
|
|
||||||
{0x0b, 0x72},
|
|
||||||
{0x0c, 0x69},
|
|
||||||
{0x0f, 0x2a},
|
|
||||||
{0x11, 0x2a},
|
|
||||||
{0x13, 0x27},
|
|
||||||
{0x15, 0x67},
|
|
||||||
{0x18, 0x04},
|
|
||||||
{0x21, 0x20},
|
|
||||||
{0x22, 0x36},
|
|
||||||
{0x2a, 0x5f},
|
|
||||||
{0x2b, 0xc0},
|
|
||||||
{0x2e, 0xff},
|
|
||||||
|
|
||||||
{0xff, 0xff}
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct elanspi_reg_entry elanspi_calibration_table_id6[] = {
|
|
||||||
{0x2A, 0x07},
|
|
||||||
{0x1, 0x00},
|
|
||||||
{0x2, 0x5f},
|
|
||||||
{0x3, 0x00},
|
|
||||||
{0x4, 0x5f},
|
|
||||||
{0x5, 0x60},
|
|
||||||
{0x6, 0xC0},
|
|
||||||
{0x7, 0x80},
|
|
||||||
{0x8, 0x04},
|
|
||||||
{0xA, 0x97},
|
|
||||||
{0xB, 0x72},
|
|
||||||
{0xC, 0x69},
|
|
||||||
{0xF, 0x2A},
|
|
||||||
{0x11, 0x2A},
|
|
||||||
{0x13, 0x27},
|
|
||||||
{0x15, 0x67},
|
|
||||||
{0x18, 0x04},
|
|
||||||
{0x21, 0x20},
|
|
||||||
{0x22, 0x36},
|
|
||||||
{0x29, 0x02},
|
|
||||||
{0x2A, 0x03},
|
|
||||||
{0x2A, 0x5F},
|
|
||||||
{0x2B, 0xC0},
|
|
||||||
{0x2C, 0x10},
|
|
||||||
{0x2E, 0xFF},
|
|
||||||
|
|
||||||
{0xff, 0xff}
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct elanspi_reg_entry elanspi_calibration_table_id57[] = {
|
|
||||||
{0x2A, 0x07},
|
|
||||||
{0x5, 0x60},
|
|
||||||
{0x6, 0xC0},
|
|
||||||
{0x7, 0x80},
|
|
||||||
{0x8, 0x04},
|
|
||||||
{0xA, 0x97},
|
|
||||||
{0xB, 0x72},
|
|
||||||
{0xC, 0x69},
|
|
||||||
{0xF, 0x2A},
|
|
||||||
{0x11, 0x2A},
|
|
||||||
{0x13, 0x27},
|
|
||||||
{0x15, 0x67},
|
|
||||||
{0x18, 0x04},
|
|
||||||
{0x21, 0x20},
|
|
||||||
{0x22, 0x36},
|
|
||||||
{0x2A, 0x5F},
|
|
||||||
{0x2B, 0xC0},
|
|
||||||
{0x2E, 0xFF},
|
|
||||||
|
|
||||||
{0xff, 0xff}
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct elanspi_reg_entry elanspi_calibration_table_id0[] = {
|
|
||||||
{0x5, 0x60},
|
|
||||||
{0x6, 0xC0},
|
|
||||||
{0x8, 0x04},
|
|
||||||
{0xA, 0x97},
|
|
||||||
{0xB, 0x72},
|
|
||||||
{0xC, 0x69},
|
|
||||||
{0xF, 0x2B},
|
|
||||||
{0x11, 0x2B},
|
|
||||||
{0x13, 0x28},
|
|
||||||
{0x15, 0x28},
|
|
||||||
{0x18, 0x04},
|
|
||||||
{0x21, 0x20},
|
|
||||||
{0x2A, 0x4B},
|
|
||||||
|
|
||||||
{0xff, 0xff}
|
|
||||||
};
|
|
||||||
|
|
||||||
// old style sensor calibration, with only one page of registers
|
|
||||||
static const struct elanspi_regtable elanspi_calibration_table_old = {
|
|
||||||
.other = elanspi_calibration_table_default,
|
|
||||||
.entries = {
|
|
||||||
{ .sid = 0x0, .table = elanspi_calibration_table_id0 },
|
|
||||||
{ .sid = 0x5, .table = elanspi_calibration_table_id57 },
|
|
||||||
{ .sid = 0x6, .table = elanspi_calibration_table_id6 },
|
|
||||||
{ .sid = 0x7, .table = elanspi_calibration_table_id57 },
|
|
||||||
{ .sid = 0x0, .table = NULL }
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// new style sensor calibration, with two pages of registers
|
|
||||||
static const struct elanspi_reg_entry elanspi_calibration_table_page0_id14[] = {
|
|
||||||
{0x00, 0x5a},
|
|
||||||
{0x01, 0x00},
|
|
||||||
{0x02, 0x4f},
|
|
||||||
{0x03, 0x00},
|
|
||||||
{0x04, 0x4f},
|
|
||||||
{0x05, 0xa0},
|
|
||||||
{0x06, 0x00},
|
|
||||||
{0x07, 0x00},
|
|
||||||
{0x08, 0x00},
|
|
||||||
{0x09, 0x04},
|
|
||||||
{0x0a, 0x74},
|
|
||||||
{0x0b, 0x05},
|
|
||||||
{0x0c, 0x08},
|
|
||||||
{0x0d, 0x00},
|
|
||||||
{0x0e, 0x00},
|
|
||||||
{0x0f, 0x14},
|
|
||||||
{0x10, 0x3c},
|
|
||||||
{0x11, 0x41},
|
|
||||||
{0x12, 0x0c},
|
|
||||||
{0x13, 0x00},
|
|
||||||
{0x14, 0x00},
|
|
||||||
{0x15, 0x04},
|
|
||||||
{0x16, 0x02},
|
|
||||||
{0x17, 0x00},
|
|
||||||
{0x18, 0x01},
|
|
||||||
{0x19, 0xf4},
|
|
||||||
{0x1a, 0x00},
|
|
||||||
{0x1b, 0x00},
|
|
||||||
{0x1c, 0x00},
|
|
||||||
{0x1d, 0x00},
|
|
||||||
{0x1e, 0x00},
|
|
||||||
{0x1f, 0x00},
|
|
||||||
{0x20, 0x00},
|
|
||||||
{0x21, 0x80},
|
|
||||||
{0x22, 0x06},
|
|
||||||
{0x23, 0x00},
|
|
||||||
{0x24, 0x00},
|
|
||||||
{0x25, 0x00},
|
|
||||||
{0x26, 0x00},
|
|
||||||
{0x27, 0x00},
|
|
||||||
{0x28, 0x00},
|
|
||||||
{0x29, 0x04},
|
|
||||||
{0x2a, 0x5f},
|
|
||||||
{0x2b, 0xe2},
|
|
||||||
{0x2c, 0xa0},
|
|
||||||
{0x2d, 0x00},
|
|
||||||
{0x2e, 0xff},
|
|
||||||
{0x2f, 0x40},
|
|
||||||
{0x30, 0x01},
|
|
||||||
{0x31, 0x38},
|
|
||||||
{0x32, 0x00},
|
|
||||||
{0x33, 0x00},
|
|
||||||
{0x34, 0x00},
|
|
||||||
{0x35, 0x1f},
|
|
||||||
{0x36, 0xff},
|
|
||||||
{0x37, 0x00},
|
|
||||||
{0x38, 0x00},
|
|
||||||
{0x39, 0x00},
|
|
||||||
{0x3a, 0x00},
|
|
||||||
{0xff, 0xff}
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct elanspi_reg_entry elanspi_calibration_table_page1_id14[] = {
|
|
||||||
{0x00, 0x7b},
|
|
||||||
{0x01, 0x7f},
|
|
||||||
{0x02, 0x77},
|
|
||||||
{0x03, 0xd4},
|
|
||||||
{0x04, 0x7d},
|
|
||||||
{0x05, 0x19},
|
|
||||||
{0x06, 0x80},
|
|
||||||
{0x07, 0x40},
|
|
||||||
{0x08, 0x11},
|
|
||||||
{0x09, 0x00},
|
|
||||||
{0x0a, 0x00},
|
|
||||||
{0x0b, 0x14},
|
|
||||||
{0x0c, 0x00},
|
|
||||||
{0x0d, 0x00},
|
|
||||||
{0x0e, 0x32},
|
|
||||||
{0x0f, 0x02},
|
|
||||||
{0x10, 0x08},
|
|
||||||
{0x11, 0x6c},
|
|
||||||
{0x12, 0x00},
|
|
||||||
{0x13, 0x00},
|
|
||||||
{0x14, 0x32},
|
|
||||||
{0x15, 0x01},
|
|
||||||
{0x16, 0x16},
|
|
||||||
{0x17, 0x01},
|
|
||||||
{0x18, 0x14},
|
|
||||||
{0x19, 0x01},
|
|
||||||
{0x1a, 0x16},
|
|
||||||
{0x1b, 0x01},
|
|
||||||
{0x1c, 0x17},
|
|
||||||
{0x1d, 0x01},
|
|
||||||
{0x1e, 0x0a},
|
|
||||||
{0x1f, 0x01},
|
|
||||||
{0x20, 0x0a},
|
|
||||||
{0x21, 0x02},
|
|
||||||
{0x22, 0x08},
|
|
||||||
{0x23, 0x29},
|
|
||||||
{0x24, 0x00},
|
|
||||||
{0x25, 0x0c},
|
|
||||||
{0x26, 0x1a},
|
|
||||||
{0x27, 0x30},
|
|
||||||
{0x28, 0x1a},
|
|
||||||
{0x29, 0x30},
|
|
||||||
{0x2a, 0x00},
|
|
||||||
{0x2b, 0x00},
|
|
||||||
{0x2c, 0x01},
|
|
||||||
{0x2d, 0x16},
|
|
||||||
{0x2e, 0x01},
|
|
||||||
{0x2f, 0x17},
|
|
||||||
{0x30, 0x03},
|
|
||||||
{0x31, 0x2d},
|
|
||||||
{0x32, 0x03},
|
|
||||||
{0x33, 0x2d},
|
|
||||||
{0x34, 0x14},
|
|
||||||
{0x35, 0x00},
|
|
||||||
{0x36, 0x00},
|
|
||||||
{0x37, 0x00},
|
|
||||||
{0x38, 0x00},
|
|
||||||
{0x39, 0x03},
|
|
||||||
{0x3a, 0xfe},
|
|
||||||
{0x3b, 0x00},
|
|
||||||
{0x3c, 0x00},
|
|
||||||
{0x3d, 0x02},
|
|
||||||
{0x3e, 0x00},
|
|
||||||
{0x3f, 0x00},
|
|
||||||
{0xff, 0xff}
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct elanspi_regtable elanspi_calibration_table_new_page0 = {
|
|
||||||
.other = NULL,
|
|
||||||
.entries = {
|
|
||||||
{ .sid = 0xe, .table = elanspi_calibration_table_page0_id14 },
|
|
||||||
{ .sid = 0x0, .table = NULL }
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct elanspi_regtable elanspi_calibration_table_new_page1 = {
|
|
||||||
.other = NULL,
|
|
||||||
.entries = {
|
|
||||||
{ .sid = 0xe, .table = elanspi_calibration_table_page1_id14 },
|
|
||||||
{ .sid = 0x0, .table = NULL }
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
#define ELANSPI_NO_ROTATE 0
|
|
||||||
#define ELANSPI_90LEFT_ROTATE 1
|
|
||||||
#define ELANSPI_180_ROTATE 2
|
|
||||||
#define ELANSPI_90RIGHT_ROTATE 3
|
|
||||||
|
|
||||||
#define ELANSPI_HV_FLIPPED 1
|
|
||||||
|
|
||||||
#define ELANSPI_UDEV_TYPES FPI_DEVICE_UDEV_SUBTYPE_SPIDEV | FPI_DEVICE_UDEV_SUBTYPE_HIDRAW
|
|
||||||
#define ELANSPI_TP_VID 0x04f3
|
|
||||||
|
|
||||||
// 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 = 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 = "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}
|
|
||||||
};
|
|
||||||
|
|
||||||
#define ELANSPI_MAX_OLD_STAGE1_CALIBRATION_MEAN 1000
|
|
||||||
|
|
||||||
#define ELANSPI_MIN_OLD_STAGE2_CALBIRATION_MEAN 3000
|
|
||||||
#define ELANSPI_MAX_OLD_STAGE2_CALBIRATION_MEAN 8000
|
|
||||||
|
|
||||||
#define ELANSPI_HV_CALIBRATION_TARGET_MEAN 3000
|
|
||||||
|
|
||||||
#define ELANSPI_MIN_EMPTY_INVALID_PERCENT 6
|
|
||||||
#define ELANSPI_MAX_REAL_INVALID_PERCENT 3
|
|
||||||
|
|
||||||
#define ELANSPI_MIN_REAL_STDDEV (592 * 592)
|
|
||||||
#define ELANSPI_MAX_EMPTY_STDDEV (350 * 350)
|
|
||||||
|
|
||||||
#define ELANSPI_MIN_FRAMES_DEBOUNCE 2
|
|
||||||
|
|
||||||
#define ELANSPI_SWIPE_FRAMES_DISCARD 1
|
|
||||||
#define ELANSPI_MIN_FRAMES_SWIPE (7 + ELANSPI_SWIPE_FRAMES_DISCARD)
|
|
||||||
#define ELANSPI_MAX_FRAMES_SWIPE (20 + ELANSPI_SWIPE_FRAMES_DISCARD)
|
|
||||||
|
|
||||||
#define ELANSPI_MAX_FRAME_HEIGHT 43
|
|
||||||
#define ELANSPI_MIN_FRAME_TO_FRAME_DIFF (250 * 250)
|
|
||||||
|
|
||||||
#define ELANSPI_HV_SENSOR_FRAME_DELAY 23
|
|
||||||
|
|
||||||
#define ELANSPI_OTP_TIMEOUT_USEC (12 * 1000)
|
|
||||||
|
|
||||||
#define ELANSPI_OLD_CAPTURE_TIMEOUT_USEC (100 * 1000)
|
|
||||||
#define ELANSPI_HV_CAPTURE_TIMEOUT_USEC (50 * 1000)
|
|
||||||
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
@@ -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 {
|
|
||||||
FP_CMD_SEND = 0,
|
|
||||||
FP_CMD_GET_DATA,
|
|
||||||
FP_CMD_SUSPENDED,
|
|
||||||
FP_CMD_RESUME,
|
|
||||||
FP_CMD_NUM_STATES,
|
|
||||||
} FpCmdState;
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
FP_INIT = 0,
|
|
||||||
FP_LOAD_DB,
|
|
||||||
FP_INIT_NUM_STATES,
|
|
||||||
} FpInitState;
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
FP_ENROLL_ENUM = 0,
|
|
||||||
FP_ENROLL_CREATE,
|
|
||||||
FP_ENROLL_CAPTURE,
|
|
||||||
FP_ENROLL_GET_IMG,
|
|
||||||
FP_ENROLL_UPDATE,
|
|
||||||
FP_ENROLL_COMPLETE,
|
|
||||||
FP_ENROLL_CHECK_DUPLICATE,
|
|
||||||
FP_ENROLL_BINDID,
|
|
||||||
FP_ENROLL_COMMIT,
|
|
||||||
FP_ENROLL_DICARD,
|
|
||||||
FP_ENROLL_CLEANUP,
|
|
||||||
FP_ENROLL_NUM_STATES,
|
|
||||||
} FpEnrollState;
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
FP_VERIFY_CAPTURE = 0,
|
|
||||||
FP_VERIFY_GET_IMG,
|
|
||||||
FP_VERIFY_IDENTIFY,
|
|
||||||
FP_VERIFY_CANCEL,
|
|
||||||
FP_VERIFY_NUM_STATES,
|
|
||||||
} FpVerifyState;
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
FP_CLEAR_DELETE_DB = 0,
|
|
||||||
FP_CLEAR_CREATE_DB,
|
|
||||||
FP_CLEAR_NUM_STATES,
|
|
||||||
} FpClearState;
|
|
||||||
@@ -54,8 +54,10 @@ struct _FpiDeviceGoodixMoc
|
|||||||
gint enroll_stage;
|
gint enroll_stage;
|
||||||
gint max_enroll_stage;
|
gint max_enroll_stage;
|
||||||
gint max_stored_prints;
|
gint max_stored_prints;
|
||||||
|
GCancellable *cancellable;
|
||||||
GPtrArray *list_result;
|
GPtrArray *list_result;
|
||||||
guint8 template_id[TEMPLATE_ID_SIZE];
|
guint8 template_id[TEMPLATE_ID_SIZE];
|
||||||
|
gboolean is_enroll_identify;
|
||||||
gboolean is_power_button_shield_on;
|
gboolean is_power_button_shield_on;
|
||||||
|
|
||||||
};
|
};
|
||||||
@@ -78,44 +80,6 @@ static gboolean parse_print_data (GVariant *data,
|
|||||||
gsize *tid_len,
|
gsize *tid_len,
|
||||||
const guint8 **user_id,
|
const guint8 **user_id,
|
||||||
gsize *user_id_len);
|
gsize *user_id_len);
|
||||||
|
|
||||||
static FpPrint *
|
|
||||||
fp_print_from_template (FpiDeviceGoodixMoc *self, template_format_t *template)
|
|
||||||
{
|
|
||||||
FpPrint *print;
|
|
||||||
GVariant *data;
|
|
||||||
GVariant *tid;
|
|
||||||
GVariant *uid;
|
|
||||||
g_autofree gchar *userid = NULL;
|
|
||||||
|
|
||||||
userid = g_strndup ((gchar *) template->payload.data, template->payload.size);
|
|
||||||
|
|
||||||
print = fp_print_new (FP_DEVICE (self));
|
|
||||||
|
|
||||||
tid = g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE,
|
|
||||||
template->tid,
|
|
||||||
TEMPLATE_ID_SIZE,
|
|
||||||
1);
|
|
||||||
|
|
||||||
uid = g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE,
|
|
||||||
template->payload.data,
|
|
||||||
template->payload.size,
|
|
||||||
1);
|
|
||||||
|
|
||||||
data = g_variant_new ("(y@ay@ay)",
|
|
||||||
template->finger_index,
|
|
||||||
tid,
|
|
||||||
uid);
|
|
||||||
|
|
||||||
fpi_print_set_type (print, FPI_PRINT_RAW);
|
|
||||||
fpi_print_set_device_stored (print, TRUE);
|
|
||||||
g_object_set (print, "fpi-data", data, NULL);
|
|
||||||
g_object_set (print, "description", userid, NULL);
|
|
||||||
fpi_print_fill_from_user_id (print, userid);
|
|
||||||
|
|
||||||
return print;
|
|
||||||
}
|
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
*
|
*
|
||||||
* fp_cmd_xxx Function
|
* fp_cmd_xxx Function
|
||||||
@@ -159,7 +123,7 @@ fp_cmd_receive_cb (FpiUsbTransfer *transfer,
|
|||||||
{
|
{
|
||||||
fpi_ssm_mark_failed (transfer->ssm,
|
fpi_ssm_mark_failed (transfer->ssm,
|
||||||
fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
|
fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
|
||||||
"Corrupted message header received"));
|
"Corrupted message received"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -256,7 +220,7 @@ fp_cmd_run_state (FpiSsm *ssm,
|
|||||||
fpi_usb_transfer_fill_bulk (transfer, EP_IN, EP_IN_MAX_BUF_SIZE);
|
fpi_usb_transfer_fill_bulk (transfer, EP_IN, EP_IN_MAX_BUF_SIZE);
|
||||||
fpi_usb_transfer_submit (transfer,
|
fpi_usb_transfer_submit (transfer,
|
||||||
self->cmd_cancelable ? 0 : DATA_TIMEOUT,
|
self->cmd_cancelable ? 0 : DATA_TIMEOUT,
|
||||||
self->cmd_cancelable ? fpi_device_get_cancellable (dev) : NULL,
|
self->cmd_cancelable ? self->cancellable : NULL,
|
||||||
fp_cmd_receive_cb,
|
fp_cmd_receive_cb,
|
||||||
fpi_ssm_get_data (ssm));
|
fpi_ssm_get_data (ssm));
|
||||||
break;
|
break;
|
||||||
@@ -420,9 +384,11 @@ fp_verify_cb (FpiDeviceGoodixMoc *self,
|
|||||||
gxfp_cmd_response_t *resp,
|
gxfp_cmd_response_t *resp,
|
||||||
GError *error)
|
GError *error)
|
||||||
{
|
{
|
||||||
|
g_autoptr(GPtrArray) templates = NULL;
|
||||||
FpDevice *device = FP_DEVICE (self);
|
FpDevice *device = FP_DEVICE (self);
|
||||||
FpPrint *new_scan = NULL;
|
FpPrint *print = NULL;
|
||||||
FpPrint *matching = NULL;
|
gint cnt = 0;
|
||||||
|
gboolean find = false;
|
||||||
|
|
||||||
if (error)
|
if (error)
|
||||||
{
|
{
|
||||||
@@ -431,34 +397,57 @@ fp_verify_cb (FpiDeviceGoodixMoc *self,
|
|||||||
}
|
}
|
||||||
if (resp->verify.match)
|
if (resp->verify.match)
|
||||||
{
|
{
|
||||||
new_scan = fp_print_from_template (self, &resp->verify.template);
|
|
||||||
|
|
||||||
if (fpi_device_get_current_action (device) == FPI_DEVICE_ACTION_VERIFY)
|
if (fpi_device_get_current_action (device) == FPI_DEVICE_ACTION_VERIFY)
|
||||||
{
|
{
|
||||||
fpi_device_get_verify_data (device, &matching);
|
templates = g_ptr_array_sized_new (1);
|
||||||
if (!fp_print_equal (matching, new_scan))
|
fpi_device_get_verify_data (device, &print);
|
||||||
matching = NULL;
|
g_ptr_array_add (templates, print);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
GPtrArray *templates = NULL;
|
|
||||||
fpi_device_get_identify_data (device, &templates);
|
fpi_device_get_identify_data (device, &templates);
|
||||||
|
g_ptr_array_ref (templates);
|
||||||
for (gint i = 0; i < templates->len; i++)
|
}
|
||||||
|
for (cnt = 0; cnt < templates->len; cnt++)
|
||||||
|
{
|
||||||
|
g_autoptr(GVariant) data = NULL;
|
||||||
|
guint8 finger;
|
||||||
|
const guint8 *user_id;
|
||||||
|
gsize user_id_len = 0;
|
||||||
|
const guint8 *tid;
|
||||||
|
gsize tid_len = 0;
|
||||||
|
print = g_ptr_array_index (templates, cnt);
|
||||||
|
g_object_get (print, "fpi-data", &data, NULL);
|
||||||
|
if (!parse_print_data (data, &finger, &tid, &tid_len, &user_id, &user_id_len))
|
||||||
{
|
{
|
||||||
if (fp_print_equal (g_ptr_array_index (templates, i), new_scan))
|
fpi_ssm_mark_failed (self->task_ssm,
|
||||||
{
|
fpi_device_error_new_msg (FP_DEVICE_ERROR_DATA_INVALID,
|
||||||
matching = g_ptr_array_index (templates, i);
|
"Parse print error"));
|
||||||
break;
|
return;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
if (memcmp (&resp->verify.template.tid, tid, TEMPLATE_ID_SIZE) == 0)
|
||||||
|
{
|
||||||
|
find = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
if (find)
|
||||||
|
{
|
||||||
|
if (fpi_device_get_current_action (device) == FPI_DEVICE_ACTION_VERIFY)
|
||||||
|
fpi_device_verify_report (device, FPI_MATCH_SUCCESS, NULL, error);
|
||||||
|
else
|
||||||
|
fpi_device_identify_report (device, print, print, error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fpi_device_get_current_action (device) == FPI_DEVICE_ACTION_VERIFY)
|
if (!find)
|
||||||
fpi_device_verify_report (device, matching ? FPI_MATCH_SUCCESS : FPI_MATCH_FAIL, new_scan, error);
|
{
|
||||||
else
|
if (fpi_device_get_current_action (device) == FPI_DEVICE_ACTION_VERIFY)
|
||||||
fpi_device_identify_report (device, matching, new_scan, error);
|
fpi_device_verify_report (device, FPI_MATCH_FAIL, NULL, error);
|
||||||
|
else
|
||||||
|
fpi_device_identify_report (device, NULL, NULL, error);
|
||||||
|
}
|
||||||
|
|
||||||
fpi_ssm_next_state (self->task_ssm);
|
fpi_ssm_next_state (self->task_ssm);
|
||||||
|
|
||||||
@@ -631,20 +620,42 @@ fp_enroll_enum_cb (FpiDeviceGoodixMoc *self,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
fpi_ssm_next_state (self->task_ssm);
|
fpi_ssm_jump_to_state (self->task_ssm, FP_ENROLL_CAPTURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
fp_enroll_create_cb (FpiDeviceGoodixMoc *self,
|
fp_enroll_identify_cb (FpiDeviceGoodixMoc *self,
|
||||||
gxfp_cmd_response_t *resp,
|
gxfp_cmd_response_t *resp,
|
||||||
GError *error)
|
GError *error)
|
||||||
{
|
{
|
||||||
if (error)
|
if (error)
|
||||||
{
|
{
|
||||||
fpi_ssm_mark_failed (self->task_ssm, error);
|
fpi_ssm_mark_failed (self->task_ssm, error);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
memcpy (self->template_id, resp->enroll_create.tid, TEMPLATE_ID_SIZE);
|
if (resp->verify.match)
|
||||||
|
{
|
||||||
|
fpi_ssm_mark_failed (self->task_ssm,
|
||||||
|
fpi_device_error_new_msg (FP_DEVICE_ERROR_DATA_DUPLICATE,
|
||||||
|
"Finger is too similar to another, try use a different finger"));
|
||||||
|
// maybe need fpi_device_enroll_report_message ...
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
fpi_ssm_next_state (self->task_ssm);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
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_init.tid, TEMPLATE_ID_SIZE);
|
||||||
fpi_ssm_next_state (self->task_ssm);
|
fpi_ssm_next_state (self->task_ssm);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -661,7 +672,7 @@ fp_enroll_capture_cb (FpiDeviceGoodixMoc *self,
|
|||||||
/* */
|
/* */
|
||||||
if (resp->result >= GX_FAILED)
|
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),
|
fpi_device_enroll_progress (FP_DEVICE (self),
|
||||||
self->enroll_stage,
|
self->enroll_stage,
|
||||||
NULL,
|
NULL,
|
||||||
@@ -675,7 +686,7 @@ fp_enroll_capture_cb (FpiDeviceGoodixMoc *self,
|
|||||||
if ((resp->capture_data_resp.img_quality < self->sensorcfg->config[4]) ||
|
if ((resp->capture_data_resp.img_quality < self->sensorcfg->config[4]) ||
|
||||||
(resp->capture_data_resp.img_coverage < self->sensorcfg->config[5]))
|
(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],
|
self->sensorcfg->config[4],
|
||||||
resp->capture_data_resp.img_quality,
|
resp->capture_data_resp.img_quality,
|
||||||
self->sensorcfg->config[5],
|
self->sensorcfg->config[5],
|
||||||
@@ -687,6 +698,11 @@ fp_enroll_capture_cb (FpiDeviceGoodixMoc *self,
|
|||||||
fpi_ssm_jump_to_state (self->task_ssm, FP_ENROLL_CAPTURE);
|
fpi_ssm_jump_to_state (self->task_ssm, FP_ENROLL_CAPTURE);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (self->is_enroll_identify)
|
||||||
|
{
|
||||||
|
self->is_enroll_identify = false;
|
||||||
|
fpi_ssm_jump_to_state (self->task_ssm, FP_ENROLL_IDENTIFY);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
fpi_ssm_next_state (self->task_ssm);
|
fpi_ssm_next_state (self->task_ssm);
|
||||||
@@ -749,14 +765,9 @@ fp_enroll_check_duplicate_cb (FpiDeviceGoodixMoc *self,
|
|||||||
}
|
}
|
||||||
if (resp->check_duplicate_resp.duplicate)
|
if (resp->check_duplicate_resp.duplicate)
|
||||||
{
|
{
|
||||||
g_autoptr(FpPrint) print = NULL;
|
|
||||||
|
|
||||||
print = g_object_ref_sink (fp_print_from_template (self, &resp->check_duplicate_resp.template));
|
|
||||||
|
|
||||||
fpi_ssm_mark_failed (self->task_ssm,
|
fpi_ssm_mark_failed (self->task_ssm,
|
||||||
fpi_device_error_new_msg (FP_DEVICE_ERROR_DATA_DUPLICATE,
|
fpi_device_error_new_msg (FP_DEVICE_ERROR_DATA_DUPLICATE,
|
||||||
"Finger was already enrolled as '%s'",
|
"Finger has already enrolled"));
|
||||||
fp_print_get_description (print)));
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -837,16 +848,6 @@ fp_enroll_sm_run_state (FpiSsm *ssm, FpDevice *device)
|
|||||||
|
|
||||||
switch (fpi_ssm_get_cur_state (ssm))
|
switch (fpi_ssm_get_cur_state (ssm))
|
||||||
{
|
{
|
||||||
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_ENUM:
|
case FP_ENROLL_ENUM:
|
||||||
{
|
{
|
||||||
goodix_sensor_cmd (self, MOC_CMD0_GETFINGERLIST, MOC_CMD1_DEFAULT,
|
goodix_sensor_cmd (self, MOC_CMD0_GETFINGERLIST, MOC_CMD1_DEFAULT,
|
||||||
@@ -857,13 +858,36 @@ fp_enroll_sm_run_state (FpiSsm *ssm, FpDevice *device)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
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_IDENTIFY:
|
||||||
|
{
|
||||||
|
dummy[0] = 0x01;
|
||||||
|
dummy[1] = self->sensorcfg->config[10];
|
||||||
|
dummy[2] = self->sensorcfg->config[11];
|
||||||
|
goodix_sensor_cmd (self, MOC_CMD0_IDENTIFY, MOC_CMD1_DEFAULT,
|
||||||
|
false,
|
||||||
|
(const guint8 *) &self->template_id,
|
||||||
|
TEMPLATE_ID_SIZE,
|
||||||
|
fp_enroll_identify_cb);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case FP_ENROLL_CREATE:
|
case FP_ENROLL_CREATE:
|
||||||
{
|
{
|
||||||
goodix_sensor_cmd (self, MOC_CMD0_ENROLL_INIT, MOC_CMD1_DEFAULT,
|
goodix_sensor_cmd (self, MOC_CMD0_ENROLL_INIT, MOC_CMD1_DEFAULT,
|
||||||
false,
|
false,
|
||||||
(const guint8 *) &dummy,
|
(const guint8 *) &dummy,
|
||||||
1,
|
1,
|
||||||
fp_enroll_create_cb);
|
fp_enroll_init_cb);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -1041,47 +1065,6 @@ fp_init_config_cb (FpiDeviceGoodixMoc *self,
|
|||||||
fpi_ssm_next_state (self->task_ssm);
|
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, FP_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
|
static void
|
||||||
fp_init_sm_run_state (FpiSsm *ssm, FpDevice *device)
|
fp_init_sm_run_state (FpiSsm *ssm, FpDevice *device)
|
||||||
@@ -1106,30 +1089,6 @@ fp_init_sm_run_state (FpiSsm *ssm, FpDevice *device)
|
|||||||
sizeof (gxfp_sensor_cfg_t),
|
sizeof (gxfp_sensor_cfg_t),
|
||||||
fp_init_config_cb);
|
fp_init_config_cb);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FP_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 FP_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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1225,32 +1184,6 @@ fp_template_delete_cb (FpiDeviceGoodixMoc *self,
|
|||||||
fp_info ("Successfully deleted enrolled user");
|
fp_info ("Successfully deleted enrolled user");
|
||||||
fpi_device_delete_complete (device, NULL);
|
fpi_device_delete_complete (device, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
fp_template_delete_all_cb (FpiDeviceGoodixMoc *self,
|
|
||||||
gxfp_cmd_response_t *resp,
|
|
||||||
GError *error)
|
|
||||||
{
|
|
||||||
FpDevice *device = FP_DEVICE (self);
|
|
||||||
|
|
||||||
if (error)
|
|
||||||
{
|
|
||||||
fpi_device_clear_storage_complete (device, error);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if ((resp->result >= GX_FAILED) && (resp->result != GX_ERROR_FINGER_ID_NOEXIST))
|
|
||||||
{
|
|
||||||
fpi_device_clear_storage_complete (FP_DEVICE (self),
|
|
||||||
fpi_device_error_new_msg (FP_DEVICE_ERROR_GENERAL,
|
|
||||||
"Failed clear storage, result: 0x%x",
|
|
||||||
resp->result));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
fp_info ("Successfully cleared storage");
|
|
||||||
fpi_device_clear_storage_complete (device, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
*
|
*
|
||||||
* fp_template_list Function
|
* fp_template_list Function
|
||||||
@@ -1292,10 +1225,36 @@ fp_template_list_cb (FpiDeviceGoodixMoc *self,
|
|||||||
|
|
||||||
for (int n = 0; n < resp->finger_list_resp.finger_num; n++)
|
for (int n = 0; n < resp->finger_list_resp.finger_num; n++)
|
||||||
{
|
{
|
||||||
|
GVariant *data = NULL;
|
||||||
|
GVariant *tid = NULL;
|
||||||
|
GVariant *uid = NULL;
|
||||||
FpPrint *print;
|
FpPrint *print;
|
||||||
|
gchar *userid;
|
||||||
|
|
||||||
print = fp_print_from_template (self, &resp->finger_list_resp.finger_list[n]);
|
userid = (gchar *) resp->finger_list_resp.finger_list[n].payload.data;
|
||||||
|
|
||||||
|
print = fp_print_new (FP_DEVICE (self));
|
||||||
|
|
||||||
|
tid = g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE,
|
||||||
|
resp->finger_list_resp.finger_list[n].tid,
|
||||||
|
TEMPLATE_ID_SIZE,
|
||||||
|
1);
|
||||||
|
|
||||||
|
uid = g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE,
|
||||||
|
resp->finger_list_resp.finger_list[n].payload.data,
|
||||||
|
resp->finger_list_resp.finger_list[n].payload.size,
|
||||||
|
1);
|
||||||
|
|
||||||
|
data = g_variant_new ("(y@ay@ay)",
|
||||||
|
resp->finger_list_resp.finger_list[n].finger_index,
|
||||||
|
tid,
|
||||||
|
uid);
|
||||||
|
|
||||||
|
fpi_print_set_type (print, FPI_PRINT_RAW);
|
||||||
|
fpi_print_set_device_stored (print, TRUE);
|
||||||
|
g_object_set (print, "fpi-data", data, NULL);
|
||||||
|
g_object_set (print, "description", userid, NULL);
|
||||||
|
fpi_print_fill_from_user_id (print, userid);
|
||||||
g_ptr_array_add (self->list_result, g_object_ref_sink (print));
|
g_ptr_array_add (self->list_result, g_object_ref_sink (print));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1359,27 +1318,6 @@ gx_fp_probe (FpDevice *device)
|
|||||||
{
|
{
|
||||||
case 0x6496:
|
case 0x6496:
|
||||||
case 0x60A2:
|
case 0x60A2:
|
||||||
case 0x60A4:
|
|
||||||
case 0x6014:
|
|
||||||
case 0x6092:
|
|
||||||
case 0x6094:
|
|
||||||
case 0x609A:
|
|
||||||
case 0x609C:
|
|
||||||
case 0x60BC:
|
|
||||||
case 0x6304:
|
|
||||||
case 0x631C:
|
|
||||||
case 0x633C:
|
|
||||||
case 0x634C:
|
|
||||||
case 0x6384:
|
|
||||||
case 0x639C:
|
|
||||||
case 0x63AC:
|
|
||||||
case 0x63BC:
|
|
||||||
case 0x63CC:
|
|
||||||
case 0x650A:
|
|
||||||
case 0x650C:
|
|
||||||
case 0x6582:
|
|
||||||
case 0x6A94:
|
|
||||||
case 0x659A:
|
|
||||||
self->max_enroll_stage = 12;
|
self->max_enroll_stage = 12;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -1410,6 +1348,8 @@ gx_fp_init (FpDevice *device)
|
|||||||
self->max_stored_prints = FP_MAX_FINGERNUM;
|
self->max_stored_prints = FP_MAX_FINGERNUM;
|
||||||
self->is_power_button_shield_on = false;
|
self->is_power_button_shield_on = false;
|
||||||
|
|
||||||
|
self->cancellable = g_cancellable_new ();
|
||||||
|
|
||||||
self->sensorcfg = g_new0 (gxfp_sensor_cfg_t, 1);
|
self->sensorcfg = g_new0 (gxfp_sensor_cfg_t, 1);
|
||||||
|
|
||||||
ret = gx_proto_init_sensor_config (self->sensorcfg);
|
ret = gx_proto_init_sensor_config (self->sensorcfg);
|
||||||
@@ -1447,6 +1387,7 @@ gx_fp_release_interface (FpiDeviceGoodixMoc *self,
|
|||||||
{
|
{
|
||||||
g_autoptr(GError) release_error = NULL;
|
g_autoptr(GError) release_error = NULL;
|
||||||
|
|
||||||
|
g_clear_object (&self->cancellable);
|
||||||
g_clear_pointer (&self->sensorcfg, g_free);
|
g_clear_pointer (&self->sensorcfg, g_free);
|
||||||
|
|
||||||
/* Release usb interface */
|
/* Release usb interface */
|
||||||
@@ -1502,10 +1443,8 @@ gx_fp_verify_identify (FpDevice *device)
|
|||||||
{
|
{
|
||||||
FpiDeviceGoodixMoc *self = FPI_DEVICE_GOODIXMOC (device);
|
FpiDeviceGoodixMoc *self = FPI_DEVICE_GOODIXMOC (device);
|
||||||
|
|
||||||
self->task_ssm = fpi_ssm_new_full (device, fp_verify_sm_run_state,
|
self->task_ssm = fpi_ssm_new (device, fp_verify_sm_run_state,
|
||||||
FP_VERIFY_NUM_STATES,
|
FP_VERIFY_NUM_STATES);
|
||||||
FP_VERIFY_PWR_BTN_SHIELD_OFF,
|
|
||||||
"verify");
|
|
||||||
|
|
||||||
fpi_ssm_start (self->task_ssm, fp_verify_ssm_done);
|
fpi_ssm_start (self->task_ssm, fp_verify_ssm_done);
|
||||||
|
|
||||||
@@ -1518,11 +1457,10 @@ gx_fp_enroll (FpDevice *device)
|
|||||||
FpiDeviceGoodixMoc *self = FPI_DEVICE_GOODIXMOC (device);
|
FpiDeviceGoodixMoc *self = FPI_DEVICE_GOODIXMOC (device);
|
||||||
|
|
||||||
self->enroll_stage = 0;
|
self->enroll_stage = 0;
|
||||||
|
self->is_enroll_identify = true;
|
||||||
|
|
||||||
self->task_ssm = fpi_ssm_new_full (device, fp_enroll_sm_run_state,
|
self->task_ssm = fpi_ssm_new (device, fp_enroll_sm_run_state,
|
||||||
FP_ENROLL_NUM_STATES,
|
FP_ENROLL_NUM_STATES);
|
||||||
FP_ENROLL_PWR_BTN_SHIELD_OFF,
|
|
||||||
"enroll");
|
|
||||||
|
|
||||||
fpi_ssm_start (self->task_ssm, fp_enroll_ssm_done);
|
fpi_ssm_start (self->task_ssm, fp_enroll_ssm_done);
|
||||||
|
|
||||||
@@ -1589,56 +1527,33 @@ gx_fp_template_delete (FpDevice *device)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
gx_fp_template_delete_all (FpDevice *device)
|
|
||||||
{
|
|
||||||
FpiDeviceGoodixMoc *self = FPI_DEVICE_GOODIXMOC (device);
|
|
||||||
|
|
||||||
goodix_sensor_cmd (self, MOC_CMD0_DELETETEMPLATE, MOC_CMD1_DELETE_ALL,
|
|
||||||
false,
|
|
||||||
NULL,
|
|
||||||
0,
|
|
||||||
fp_template_delete_all_cb);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
fpi_device_goodixmoc_init (FpiDeviceGoodixMoc *self)
|
fpi_device_goodixmoc_init (FpiDeviceGoodixMoc *self)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gx_fp_cancel (FpDevice *device)
|
||||||
|
{
|
||||||
|
FpiDeviceGoodixMoc *self = FPI_DEVICE_GOODIXMOC (device);
|
||||||
|
|
||||||
|
/* Cancel any current interrupt transfer (resulting us to go into
|
||||||
|
* response reading mode again); then create a new cancellable
|
||||||
|
* for the next transfers. */
|
||||||
|
g_cancellable_cancel (self->cancellable);
|
||||||
|
g_clear_object (&self->cancellable);
|
||||||
|
self->cancellable = g_cancellable_new ();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
static const FpIdEntry id_table[] = {
|
static const FpIdEntry id_table[] = {
|
||||||
{ .vid = 0x27c6, .pid = 0x5840, },
|
{ .vid = 0x27c6, .pid = 0x5840, },
|
||||||
{ .vid = 0x27c6, .pid = 0x6014, },
|
|
||||||
{ .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 = 0x6304, },
|
|
||||||
{ .vid = 0x27c6, .pid = 0x631C, },
|
|
||||||
{ .vid = 0x27c6, .pid = 0x633C, },
|
|
||||||
{ .vid = 0x27c6, .pid = 0x634C, },
|
|
||||||
{ .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 = 0x6496, },
|
||||||
{ .vid = 0x27c6, .pid = 0x650A, },
|
{ .vid = 0x27c6, .pid = 0x60A2, },
|
||||||
{ .vid = 0x27c6, .pid = 0x650C, },
|
{ .vid = 0x27c6, .pid = 0x63AC, },
|
||||||
{ .vid = 0x27c6, .pid = 0x6582, },
|
{ .vid = 0x27c6, .pid = 0x639C, },
|
||||||
{ .vid = 0x27c6, .pid = 0x6584, },
|
|
||||||
{ .vid = 0x27c6, .pid = 0x658C, },
|
|
||||||
{ .vid = 0x27c6, .pid = 0x6592, },
|
|
||||||
{ .vid = 0x27c6, .pid = 0x6594, },
|
{ .vid = 0x27c6, .pid = 0x6594, },
|
||||||
{ .vid = 0x27c6, .pid = 0x659A, },
|
|
||||||
{ .vid = 0x27c6, .pid = 0x659C, },
|
|
||||||
{ .vid = 0x27c6, .pid = 0x6A94, },
|
|
||||||
{ .vid = 0x27c6, .pid = 0x6512, },
|
|
||||||
{ .vid = 0, .pid = 0, .driver_data = 0 }, /* terminating entry */
|
{ .vid = 0, .pid = 0, .driver_data = 0 }, /* terminating entry */
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1654,18 +1569,14 @@ fpi_device_goodixmoc_class_init (FpiDeviceGoodixMocClass *klass)
|
|||||||
dev_class->scan_type = FP_SCAN_TYPE_PRESS;
|
dev_class->scan_type = FP_SCAN_TYPE_PRESS;
|
||||||
dev_class->id_table = id_table;
|
dev_class->id_table = id_table;
|
||||||
dev_class->nr_enroll_stages = DEFAULT_ENROLL_SAMPLES;
|
dev_class->nr_enroll_stages = DEFAULT_ENROLL_SAMPLES;
|
||||||
dev_class->temp_hot_seconds = -1;
|
|
||||||
|
|
||||||
dev_class->open = gx_fp_init;
|
dev_class->open = gx_fp_init;
|
||||||
dev_class->close = gx_fp_exit;
|
dev_class->close = gx_fp_exit;
|
||||||
dev_class->probe = gx_fp_probe;
|
dev_class->probe = gx_fp_probe;
|
||||||
dev_class->enroll = gx_fp_enroll;
|
dev_class->enroll = gx_fp_enroll;
|
||||||
dev_class->delete = gx_fp_template_delete;
|
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->list = gx_fp_template_list;
|
||||||
|
dev_class->cancel = gx_fp_cancel;
|
||||||
dev_class->verify = gx_fp_verify_identify;
|
dev_class->verify = gx_fp_verify_identify;
|
||||||
dev_class->identify = 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;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,8 +35,6 @@ typedef enum {
|
|||||||
typedef enum {
|
typedef enum {
|
||||||
FP_INIT_VERSION = 0,
|
FP_INIT_VERSION = 0,
|
||||||
FP_INIT_CONFIG,
|
FP_INIT_CONFIG,
|
||||||
FP_INIT_TEMPLATE_LIST,
|
|
||||||
FP_INIT_RESET_DEVICE,
|
|
||||||
FP_INIT_NUM_STATES,
|
FP_INIT_NUM_STATES,
|
||||||
} FpInitState;
|
} FpInitState;
|
||||||
|
|
||||||
@@ -44,6 +42,7 @@ typedef enum {
|
|||||||
typedef enum {
|
typedef enum {
|
||||||
FP_ENROLL_PWR_BTN_SHIELD_ON = 0,
|
FP_ENROLL_PWR_BTN_SHIELD_ON = 0,
|
||||||
FP_ENROLL_ENUM,
|
FP_ENROLL_ENUM,
|
||||||
|
FP_ENROLL_IDENTIFY,
|
||||||
FP_ENROLL_CREATE,
|
FP_ENROLL_CREATE,
|
||||||
FP_ENROLL_CAPTURE,
|
FP_ENROLL_CAPTURE,
|
||||||
FP_ENROLL_UPDATE,
|
FP_ENROLL_UPDATE,
|
||||||
|
|||||||
@@ -259,9 +259,12 @@ gx_proto_parse_fingerid (
|
|||||||
|
|
||||||
if (buffer[Offset++] != 67)
|
if (buffer[Offset++] != 67)
|
||||||
return -1;
|
return -1;
|
||||||
|
fid_buffer_size--;
|
||||||
|
|
||||||
template->type = buffer[Offset++];
|
template->type = buffer[Offset++];
|
||||||
|
fid_buffer_size--;
|
||||||
template->finger_index = buffer[Offset++];
|
template->finger_index = buffer[Offset++];
|
||||||
|
fid_buffer_size--;
|
||||||
Offset++;
|
Offset++;
|
||||||
memcpy (template->accountid, &buffer[Offset], sizeof (template->accountid));
|
memcpy (template->accountid, &buffer[Offset], sizeof (template->accountid));
|
||||||
Offset += sizeof (template->accountid);
|
Offset += sizeof (template->accountid);
|
||||||
@@ -270,8 +273,6 @@ gx_proto_parse_fingerid (
|
|||||||
template->payload.size = buffer[Offset++];
|
template->payload.size = buffer[Offset++];
|
||||||
if (template->payload.size > sizeof (template->payload.data))
|
if (template->payload.size > sizeof (template->payload.data))
|
||||||
return -1;
|
return -1;
|
||||||
if (template->payload.size + Offset > fid_buffer_size)
|
|
||||||
return -1;
|
|
||||||
memset (template->payload.data, 0, template->payload.size);
|
memset (template->payload.data, 0, template->payload.size);
|
||||||
memcpy (template->payload.data, &buffer[Offset], template->payload.size);
|
memcpy (template->payload.data, &buffer[Offset], template->payload.size);
|
||||||
|
|
||||||
@@ -343,10 +344,10 @@ gx_proto_parse_body (uint16_t cmd, uint8_t *buffer, uint16_t buffer_len, pgxfp_c
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case MOC_CMD0_ENROLL_INIT:
|
case MOC_CMD0_ENROLL_INIT:
|
||||||
if (buffer_len < sizeof (gxfp_enroll_create_t) + 1)
|
if (buffer_len < sizeof (gxfp_enroll_init_t) + 1)
|
||||||
return -1;
|
return -1;
|
||||||
if (presp->result == GX_SUCCESS)
|
if (presp->result == GX_SUCCESS)
|
||||||
memcpy (&presp->enroll_create.tid, &buffer[1], TEMPLATE_ID_SIZE);
|
memcpy (&presp->enroll_init.tid, &buffer[1], TEMPLATE_ID_SIZE);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MOC_CMD0_ENROLL:
|
case MOC_CMD0_ENROLL:
|
||||||
@@ -364,12 +365,9 @@ gx_proto_parse_body (uint16_t cmd, uint8_t *buffer, uint16_t buffer_len, pgxfp_c
|
|||||||
if (buffer_len < 3)
|
if (buffer_len < 3)
|
||||||
return -1;
|
return -1;
|
||||||
uint16_t tid_size = GUINT16_FROM_LE (*(uint16_t *) (buffer + 1));
|
uint16_t tid_size = GUINT16_FROM_LE (*(uint16_t *) (buffer + 1));
|
||||||
offset += 3;
|
if ((buffer_len < tid_size + 3) || (buffer_len > sizeof (template_format_t)) + 3)
|
||||||
|
|
||||||
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;
|
return -1;
|
||||||
|
memcpy (&presp->check_duplicate_resp.template, buffer + 3, tid_size);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -382,19 +380,18 @@ gx_proto_parse_body (uint16_t cmd, uint8_t *buffer, uint16_t buffer_len, pgxfp_c
|
|||||||
fingerlist = buffer + 2;
|
fingerlist = buffer + 2;
|
||||||
for(uint8_t num = 0; num < presp->finger_list_resp.finger_num; num++)
|
for(uint8_t num = 0; num < presp->finger_list_resp.finger_num; num++)
|
||||||
{
|
{
|
||||||
uint16_t fingerid_length;
|
uint16_t fingerid_length = GUINT16_FROM_LE (*(uint16_t *) (fingerlist + offset));
|
||||||
if (buffer_len < offset + 2)
|
|
||||||
return -1;
|
|
||||||
fingerid_length = GUINT16_FROM_LE (*(uint16_t *) (fingerlist + offset));
|
|
||||||
offset += 2;
|
offset += 2;
|
||||||
if (buffer_len < fingerid_length + offset)
|
if (buffer_len < fingerid_length + offset + 2)
|
||||||
return -1;
|
return -1;
|
||||||
if (gx_proto_parse_fingerid (fingerlist + offset,
|
if (gx_proto_parse_fingerid (fingerlist + offset,
|
||||||
fingerid_length,
|
fingerid_length,
|
||||||
&presp->finger_list_resp.finger_list[num]) != 0)
|
&presp->finger_list_resp.finger_list[num]) != 0)
|
||||||
{
|
{
|
||||||
g_warning ("Failed to parse finger list");
|
g_error ("parse fingerlist error");
|
||||||
return -1;
|
presp->finger_list_resp.finger_num = 0;
|
||||||
|
presp->result = GX_FAILED;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
offset += fingerid_length;
|
offset += fingerid_length;
|
||||||
}
|
}
|
||||||
@@ -408,7 +405,7 @@ gx_proto_parse_body (uint16_t cmd, uint8_t *buffer, uint16_t buffer_len, pgxfp_c
|
|||||||
presp->verify.match = (buffer[0] == 0) ? true : false;
|
presp->verify.match = (buffer[0] == 0) ? true : false;
|
||||||
if (presp->verify.match)
|
if (presp->verify.match)
|
||||||
{
|
{
|
||||||
if (buffer_len < 10)
|
if (buffer_len < sizeof (template_format_t) + 10)
|
||||||
return -1;
|
return -1;
|
||||||
offset += 1;
|
offset += 1;
|
||||||
presp->verify.rejectdetail = GUINT16_FROM_LE (*(uint16_t *) (buffer + offset));
|
presp->verify.rejectdetail = GUINT16_FROM_LE (*(uint16_t *) (buffer + offset));
|
||||||
@@ -419,8 +416,6 @@ gx_proto_parse_body (uint16_t cmd, uint8_t *buffer, uint16_t buffer_len, pgxfp_c
|
|||||||
offset += 1;
|
offset += 1;
|
||||||
fingerid_size = GUINT16_FROM_LE (*(uint16_t *) (buffer + offset));
|
fingerid_size = GUINT16_FROM_LE (*(uint16_t *) (buffer + offset));
|
||||||
offset += 2;
|
offset += 2;
|
||||||
if (buffer_len < fingerid_size + offset)
|
|
||||||
return -1;
|
|
||||||
if (gx_proto_parse_fingerid (buffer + offset, fingerid_size, &presp->verify.template) != 0)
|
if (gx_proto_parse_fingerid (buffer + offset, fingerid_size, &presp->verify.template) != 0)
|
||||||
{
|
{
|
||||||
presp->result = GX_FAILED;
|
presp->result = GX_FAILED;
|
||||||
@@ -465,4 +460,4 @@ gx_proto_init_sensor_config (pgxfp_sensor_cfg_t pconfig)
|
|||||||
memcpy (pconfig->crc_value, &crc32_calc, PACKAGE_CRC_SIZE);
|
memcpy (pconfig->crc_value, &crc32_calc, PACKAGE_CRC_SIZE);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -105,24 +105,22 @@ typedef struct _gxfp_parse_msg
|
|||||||
} gxfp_parse_msg_t, *pgxfp_parse_msg_t;
|
} gxfp_parse_msg_t, *pgxfp_parse_msg_t;
|
||||||
|
|
||||||
|
|
||||||
typedef struct _gxfp_enroll_create
|
typedef struct _gxfp_enroll_init
|
||||||
{
|
{
|
||||||
uint8_t tid[TEMPLATE_ID_SIZE];
|
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)
|
#pragma pack(push, 1)
|
||||||
typedef struct _template_format
|
typedef struct _template_format
|
||||||
{
|
{
|
||||||
uint8_t _0x43_byte;
|
|
||||||
uint8_t type;
|
uint8_t type;
|
||||||
uint8_t finger_index;
|
uint8_t finger_index;
|
||||||
uint8_t pad0;
|
|
||||||
uint8_t accountid[32];
|
uint8_t accountid[32];
|
||||||
uint8_t tid[32];
|
uint8_t tid[32];
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
uint8_t size;
|
uint32_t size;
|
||||||
uint8_t data[56];
|
uint8_t data[56];
|
||||||
} payload;
|
} payload;
|
||||||
uint8_t reserve[2];
|
uint8_t reserve[2];
|
||||||
} template_format_t, *ptemplate_format_t;
|
} template_format_t, *ptemplate_format_t;
|
||||||
@@ -192,7 +190,7 @@ typedef struct _fp_cmd_response
|
|||||||
{
|
{
|
||||||
gxfp_parse_msg_t parse_msg;
|
gxfp_parse_msg_t parse_msg;
|
||||||
gxfp_verify_t verify;
|
gxfp_verify_t verify;
|
||||||
gxfp_enroll_create_t enroll_create;
|
gxfp_enroll_init_t enroll_init;
|
||||||
gxfp_capturedata_t capture_data_resp;
|
gxfp_capturedata_t capture_data_resp;
|
||||||
gxfp_check_duplicate_t check_duplicate_resp;
|
gxfp_check_duplicate_t check_duplicate_resp;
|
||||||
gxfp_enroll_commit_t enroll_commit;
|
gxfp_enroll_commit_t enroll_commit;
|
||||||
|
|||||||
@@ -1,445 +0,0 @@
|
|||||||
/*
|
|
||||||
* Next Biometrics driver for libfprint
|
|
||||||
*
|
|
||||||
* Copyright (C) 2021 Huan Wang <fredwanghuan@gmail.com>
|
|
||||||
* Copyright (C) 2011-2012 Andrej Krutak <dev@andree.sk>
|
|
||||||
*
|
|
||||||
* 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 "nb1010"
|
|
||||||
#include "fpi-log.h"
|
|
||||||
|
|
||||||
#include "drivers_api.h"
|
|
||||||
|
|
||||||
#define FRAME_HEIGHT 180
|
|
||||||
#define FRAME_WIDTH 256
|
|
||||||
|
|
||||||
#define NB1010_EP_OUT 0x02 | FPI_USB_ENDPOINT_OUT
|
|
||||||
#define NB1010_EP_IN 0x03 | FPI_USB_ENDPOINT_IN
|
|
||||||
|
|
||||||
#define NB1010_SENSITIVITY_BIT 12
|
|
||||||
|
|
||||||
#define NB1010_CMD_RECV_LEN 16
|
|
||||||
#define NB1010_CAPTURE_RECV_LEN 540
|
|
||||||
#define NB1010_CAPTURE_HEADER_LEN 25
|
|
||||||
|
|
||||||
#define NB1010_LINE_PER_PARTIAL 2
|
|
||||||
#define NB1010_N_PARTIAL (FRAME_HEIGHT / NB1010_LINE_PER_PARTIAL)
|
|
||||||
|
|
||||||
#define NB1010_DEFAULT_TIMEOUT 500
|
|
||||||
#define NB1010_TRANSITION_DELAY 50
|
|
||||||
|
|
||||||
/* Loop ssm states */
|
|
||||||
enum {
|
|
||||||
M_WAIT_PRINT,
|
|
||||||
M_REQUEST_PRINT,
|
|
||||||
M_CHECK_PRINT,
|
|
||||||
M_READ_PRINT_PRESTART,
|
|
||||||
M_READ_PRINT_START,
|
|
||||||
M_READ_PRINT_POLL,
|
|
||||||
M_SUBMIT_PRINT,
|
|
||||||
|
|
||||||
/* Number of states */
|
|
||||||
M_LOOP_NUM_STATES,
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The Follow Commands are obtained by decoding the usbcap, so it does not expose all the command available to the device.
|
|
||||||
* Known:
|
|
||||||
* 1. every command starts with 0x80
|
|
||||||
* 2. second byte is the comand, third byte is the seqence nubmer, init with rand, gets incremented
|
|
||||||
* everytime a new instruction is sent to the device. However device does not care or check the sequence, just echo back
|
|
||||||
* whatever chosen by the host.
|
|
||||||
* 3. cmd: 0x07 check, expect [0x80, 0x29...] as response
|
|
||||||
* 4. cmd: 0x16 ???, expect [0x80, 0x20...] as response. Happens during device init.
|
|
||||||
* 5. cmd: 0x13 print device, expect [0x80, 0x23...] as response. Response contains the device string
|
|
||||||
* 6. cmd: 0x38 check finger, expect [0x80, 0x37...] as response. The 14th byte indicate whether finger present [0-255]
|
|
||||||
* 7. cmd: 0x0d ???, expect [0x80, 0x20...] as response. Happens before capture.
|
|
||||||
* 8. cmd: 0x12 capture, expect [0x80, 0x20...] as response. After capture read 90 times in sequence to get all the frame.
|
|
||||||
*/
|
|
||||||
|
|
||||||
static guint8 nb1010_cmd_check_finger[] = {
|
|
||||||
0x80, 0x38, 0x01, 0x00, 0x08, 0x00, 0x00, 0x00,
|
|
||||||
};
|
|
||||||
|
|
||||||
/* pre capture, dont know what does it do, but appears everytime a capture begins */
|
|
||||||
static guint8 nb1010_cmd_precapture[] = {
|
|
||||||
0x80, 0x0d, 0x03, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
|
|
||||||
};
|
|
||||||
|
|
||||||
static guint8 nb1010_cmd_capture[] = {
|
|
||||||
0x80, 0x12, 0x04, 0x00, 0x20, 0x00, 0x00, 0x00,
|
|
||||||
0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct _FpiDeviceNb1010
|
|
||||||
{
|
|
||||||
FpImageDevice parent;
|
|
||||||
FpiSsm *ssm;
|
|
||||||
guint8 *scanline_buf;
|
|
||||||
gboolean deactivating;
|
|
||||||
int partial_received;
|
|
||||||
};
|
|
||||||
G_DECLARE_FINAL_TYPE (FpiDeviceNb1010, fpi_device_nb1010, FPI, DEVICE_NB1010, FpImageDevice);
|
|
||||||
G_DEFINE_TYPE (FpiDeviceNb1010, fpi_device_nb1010, FP_TYPE_IMAGE_DEVICE);
|
|
||||||
|
|
||||||
static void
|
|
||||||
nb1010_dev_init (FpImageDevice *dev)
|
|
||||||
{
|
|
||||||
FpiDeviceNb1010 *self = FPI_DEVICE_NB1010 (dev);
|
|
||||||
GError *error = NULL;
|
|
||||||
|
|
||||||
g_usb_device_claim_interface (fpi_device_get_usb_device (FP_DEVICE (dev)), 0, 0, &error);
|
|
||||||
|
|
||||||
self->scanline_buf = g_malloc0 (FRAME_WIDTH * FRAME_HEIGHT);
|
|
||||||
|
|
||||||
fpi_image_device_open_complete (dev, error);
|
|
||||||
fp_dbg ("nb1010 Initialized");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
nb1010_dev_deinit (FpImageDevice *dev)
|
|
||||||
{
|
|
||||||
FpiDeviceNb1010 *self = FPI_DEVICE_NB1010 (dev);
|
|
||||||
GError *error = NULL;
|
|
||||||
|
|
||||||
g_clear_pointer (&self->scanline_buf, g_free);
|
|
||||||
|
|
||||||
g_usb_device_release_interface (fpi_device_get_usb_device (FP_DEVICE (dev)), 0, 0, &error);
|
|
||||||
fpi_image_device_close_complete (dev, error);
|
|
||||||
fp_dbg ("nb1010 Deinitialized");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
nb1010_dev_activate (FpImageDevice *dev)
|
|
||||||
{
|
|
||||||
FpiDeviceNb1010 *self = FPI_DEVICE_NB1010 (dev);
|
|
||||||
|
|
||||||
self->deactivating = FALSE;
|
|
||||||
|
|
||||||
fpi_image_device_activate_complete (dev, NULL);
|
|
||||||
fp_dbg ("nb1010 Activated");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
nb1010_dev_deactivated (FpImageDevice *dev, GError * err)
|
|
||||||
{
|
|
||||||
fpi_image_device_deactivate_complete (dev, err);
|
|
||||||
fp_dbg ("nb1010 Deactivated");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
nb1010_dev_deactivate (FpImageDevice *dev)
|
|
||||||
{
|
|
||||||
FpiDeviceNb1010 *self = FPI_DEVICE_NB1010 (dev);
|
|
||||||
|
|
||||||
self->deactivating = TRUE;
|
|
||||||
if (self->ssm == NULL)
|
|
||||||
nb1010_dev_deactivated (dev, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
nb1010_request_fingerprint (FpiDeviceNb1010 *dev)
|
|
||||||
{
|
|
||||||
FpiUsbTransfer *transfer = NULL;
|
|
||||||
|
|
||||||
transfer = fpi_usb_transfer_new (FP_DEVICE ( dev));
|
|
||||||
transfer->short_is_error = TRUE;
|
|
||||||
transfer->ssm = dev->ssm;
|
|
||||||
|
|
||||||
fpi_usb_transfer_fill_bulk_full (transfer, NB1010_EP_OUT,
|
|
||||||
nb1010_cmd_check_finger, G_N_ELEMENTS (nb1010_cmd_check_finger),
|
|
||||||
NULL);
|
|
||||||
fpi_usb_transfer_submit (transfer, NB1010_DEFAULT_TIMEOUT,
|
|
||||||
fpi_device_get_cancellable (FP_DEVICE (dev)),
|
|
||||||
fpi_ssm_usb_transfer_cb, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
nb1010_check_fingerprint_cb (FpiUsbTransfer *transfer, FpDevice *dev,
|
|
||||||
gpointer unused_data, GError *error)
|
|
||||||
{
|
|
||||||
FpiDeviceNb1010 *self = FPI_DEVICE_NB1010 (dev);
|
|
||||||
|
|
||||||
if (error)
|
|
||||||
{
|
|
||||||
fpi_ssm_mark_failed (transfer->ssm, error);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (self->deactivating)
|
|
||||||
{
|
|
||||||
fpi_ssm_mark_completed (transfer->ssm);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (transfer->buffer[NB1010_SENSITIVITY_BIT] > 0x30)
|
|
||||||
fpi_ssm_next_state (transfer->ssm);
|
|
||||||
else
|
|
||||||
fpi_ssm_jump_to_state (transfer->ssm, M_WAIT_PRINT);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
nb1010_cmd_check_fingerprint (FpiDeviceNb1010 *dev)
|
|
||||||
{
|
|
||||||
FpiUsbTransfer *transfer = NULL;
|
|
||||||
|
|
||||||
transfer = fpi_usb_transfer_new (FP_DEVICE ( dev));
|
|
||||||
transfer->short_is_error = TRUE;
|
|
||||||
transfer->ssm = dev->ssm;
|
|
||||||
|
|
||||||
fpi_usb_transfer_fill_bulk (transfer, NB1010_EP_IN, NB1010_CMD_RECV_LEN);
|
|
||||||
fpi_usb_transfer_submit (transfer, NB1010_DEFAULT_TIMEOUT,
|
|
||||||
fpi_device_get_cancellable (FP_DEVICE (dev)),
|
|
||||||
nb1010_check_fingerprint_cb, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
nb1010_read_ignore_data_cb (FpiUsbTransfer *transfer, FpDevice *dev,
|
|
||||||
gpointer unused_data, GError *error)
|
|
||||||
{
|
|
||||||
FpiDeviceNb1010 *self = FPI_DEVICE_NB1010 (dev);
|
|
||||||
FpiUsbTransfer *new_transfer = NULL;
|
|
||||||
|
|
||||||
if (error)
|
|
||||||
{
|
|
||||||
fpi_ssm_mark_failed (transfer->ssm, error);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (self->deactivating)
|
|
||||||
{
|
|
||||||
fpi_ssm_mark_completed (transfer->ssm);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
new_transfer = fpi_usb_transfer_new ( dev );
|
|
||||||
new_transfer->short_is_error = TRUE;
|
|
||||||
new_transfer->ssm = transfer->ssm;
|
|
||||||
|
|
||||||
fpi_usb_transfer_fill_bulk (new_transfer, NB1010_EP_IN, NB1010_CMD_RECV_LEN);
|
|
||||||
fpi_usb_transfer_submit (new_transfer, NB1010_DEFAULT_TIMEOUT,
|
|
||||||
fpi_device_get_cancellable (FP_DEVICE (dev)),
|
|
||||||
fpi_ssm_usb_transfer_cb, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
nb1010_write_ignore_read (FpiDeviceNb1010 *dev, guint8 *buf, gsize len)
|
|
||||||
{
|
|
||||||
FpiUsbTransfer *transfer = NULL;
|
|
||||||
|
|
||||||
transfer = fpi_usb_transfer_new (FP_DEVICE ( dev));
|
|
||||||
transfer->short_is_error = TRUE;
|
|
||||||
transfer->ssm = dev->ssm;
|
|
||||||
|
|
||||||
fpi_usb_transfer_fill_bulk_full (transfer, NB1010_EP_OUT, buf, len, NULL);
|
|
||||||
fpi_usb_transfer_submit (transfer, NB1010_DEFAULT_TIMEOUT,
|
|
||||||
fpi_device_get_cancellable (FP_DEVICE (dev)),
|
|
||||||
nb1010_read_ignore_data_cb, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
nb1010_read_capture_cb (FpiUsbTransfer *transfer, FpDevice *dev,
|
|
||||||
gpointer unused_data, GError *error)
|
|
||||||
{
|
|
||||||
FpiDeviceNb1010 *self = FPI_DEVICE_NB1010 (dev);
|
|
||||||
|
|
||||||
if (error)
|
|
||||||
{
|
|
||||||
fpi_ssm_mark_failed (transfer->ssm, error);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (self->deactivating)
|
|
||||||
{
|
|
||||||
fpi_ssm_mark_completed (transfer->ssm);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
g_assert (transfer->actual_length == NB1010_CAPTURE_RECV_LEN);
|
|
||||||
|
|
||||||
size_t offset = self->partial_received * NB1010_LINE_PER_PARTIAL * FRAME_WIDTH;
|
|
||||||
|
|
||||||
memcpy (self->scanline_buf + offset,
|
|
||||||
transfer->buffer + NB1010_CAPTURE_HEADER_LEN, NB1010_LINE_PER_PARTIAL * FRAME_WIDTH);
|
|
||||||
|
|
||||||
self->partial_received++;
|
|
||||||
if (self->partial_received == NB1010_N_PARTIAL)
|
|
||||||
{
|
|
||||||
fpi_ssm_next_state (transfer->ssm);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
fpi_usb_transfer_submit (fpi_usb_transfer_ref (transfer), NB1010_DEFAULT_TIMEOUT,
|
|
||||||
fpi_device_get_cancellable (FP_DEVICE (dev)),
|
|
||||||
nb1010_read_capture_cb, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
nb1010_read_capture (FpiDeviceNb1010 *dev)
|
|
||||||
{
|
|
||||||
FpiUsbTransfer *transfer = NULL;
|
|
||||||
|
|
||||||
transfer = fpi_usb_transfer_new ( FP_DEVICE ( dev));
|
|
||||||
transfer->short_is_error = TRUE;
|
|
||||||
transfer->ssm = dev->ssm;
|
|
||||||
|
|
||||||
fpi_usb_transfer_fill_bulk (transfer, NB1010_EP_IN, NB1010_CAPTURE_RECV_LEN);
|
|
||||||
fpi_usb_transfer_submit (transfer, NB1010_DEFAULT_TIMEOUT,
|
|
||||||
fpi_device_get_cancellable (FP_DEVICE (dev)),
|
|
||||||
nb1010_read_capture_cb, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
submit_image (FpiSsm *ssm,
|
|
||||||
FpImageDevice *dev)
|
|
||||||
{
|
|
||||||
FpiDeviceNb1010 *self = FPI_DEVICE_NB1010 (dev);
|
|
||||||
FpImage *img;
|
|
||||||
|
|
||||||
img = fp_image_new (FRAME_WIDTH, FRAME_HEIGHT);
|
|
||||||
if (img == NULL)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
memcpy (img->data, self->scanline_buf, FRAME_WIDTH * FRAME_HEIGHT);
|
|
||||||
fpi_image_device_image_captured (dev, img);
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
m_loop_complete (FpiSsm *ssm, FpDevice *_dev, GError *error)
|
|
||||||
{
|
|
||||||
fp_dbg ("nb1010 ssm complete cb");
|
|
||||||
|
|
||||||
FpImageDevice *dev = FP_IMAGE_DEVICE (_dev);
|
|
||||||
FpiDeviceNb1010 *self = FPI_DEVICE_NB1010 (_dev);
|
|
||||||
|
|
||||||
self->ssm = NULL;
|
|
||||||
|
|
||||||
if (self->deactivating)
|
|
||||||
nb1010_dev_deactivated (dev, error);
|
|
||||||
else if (error != NULL)
|
|
||||||
fpi_image_device_session_error (dev, error);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
m_loop_state (FpiSsm *ssm, FpDevice *_dev)
|
|
||||||
{
|
|
||||||
FpImageDevice *dev = FP_IMAGE_DEVICE (_dev);
|
|
||||||
FpiDeviceNb1010 *self = FPI_DEVICE_NB1010 (_dev);
|
|
||||||
|
|
||||||
if (self->deactivating)
|
|
||||||
{
|
|
||||||
fp_dbg ("deactivating, marking completed");
|
|
||||||
fpi_ssm_mark_completed (ssm);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (fpi_ssm_get_cur_state (ssm))
|
|
||||||
{
|
|
||||||
case M_WAIT_PRINT:
|
|
||||||
/* Wait fingerprint scanning */
|
|
||||||
fpi_ssm_next_state_delayed (ssm, NB1010_TRANSITION_DELAY);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case M_REQUEST_PRINT:
|
|
||||||
nb1010_request_fingerprint (self);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case M_CHECK_PRINT:
|
|
||||||
nb1010_cmd_check_fingerprint (self);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case M_READ_PRINT_PRESTART:
|
|
||||||
fpi_image_device_report_finger_status (dev, TRUE);
|
|
||||||
nb1010_write_ignore_read (self, nb1010_cmd_precapture, G_N_ELEMENTS (nb1010_cmd_precapture));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case M_READ_PRINT_START:
|
|
||||||
self->partial_received = 0;
|
|
||||||
nb1010_write_ignore_read (self, nb1010_cmd_capture, G_N_ELEMENTS (nb1010_cmd_capture));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case M_READ_PRINT_POLL:
|
|
||||||
nb1010_read_capture (self);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case M_SUBMIT_PRINT:
|
|
||||||
if (submit_image (ssm, dev))
|
|
||||||
{
|
|
||||||
fpi_ssm_mark_completed (ssm);
|
|
||||||
fpi_image_device_report_finger_status (dev, FALSE);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
fpi_ssm_jump_to_state (ssm, M_WAIT_PRINT);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
g_assert_not_reached ();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
nb1010_dev_change_state (FpImageDevice *dev, FpiImageDeviceState state)
|
|
||||||
{
|
|
||||||
FpiDeviceNb1010 *self = FPI_DEVICE_NB1010 (dev);
|
|
||||||
FpiSsm *ssm_loop;
|
|
||||||
|
|
||||||
if (state == FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON)
|
|
||||||
{
|
|
||||||
ssm_loop = fpi_ssm_new (FP_DEVICE (dev), m_loop_state, M_LOOP_NUM_STATES);
|
|
||||||
self->ssm = ssm_loop;
|
|
||||||
fpi_ssm_start (ssm_loop, m_loop_complete);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static const FpIdEntry id_table[] = {
|
|
||||||
{ .vid = 0x298d, .pid = 0x1010, },
|
|
||||||
{ .vid = 0, .pid = 0, .driver_data = 0 },
|
|
||||||
};
|
|
||||||
|
|
||||||
static void
|
|
||||||
fpi_device_nb1010_init (FpiDeviceNb1010 *self)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
fpi_device_nb1010_class_init (FpiDeviceNb1010Class *klass)
|
|
||||||
{
|
|
||||||
FpDeviceClass *dev_class = FP_DEVICE_CLASS (klass);
|
|
||||||
FpImageDeviceClass *img_class = FP_IMAGE_DEVICE_CLASS (klass);
|
|
||||||
|
|
||||||
dev_class->id = FP_COMPONENT;
|
|
||||||
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;
|
|
||||||
|
|
||||||
img_class->img_height = FRAME_HEIGHT;
|
|
||||||
img_class->img_width = FRAME_WIDTH;
|
|
||||||
|
|
||||||
img_class->bz3_threshold = 24;
|
|
||||||
|
|
||||||
img_class->img_open = nb1010_dev_init;
|
|
||||||
img_class->img_close = nb1010_dev_deinit;
|
|
||||||
img_class->activate = nb1010_dev_activate;
|
|
||||||
img_class->deactivate = nb1010_dev_deactivate;
|
|
||||||
img_class->change_state = nb1010_dev_change_state;
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -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},
|
|
||||||
};
|
|
||||||
@@ -468,7 +468,6 @@ typedef union
|
|||||||
bmkt_del_all_users_resp_t del_all_users_resp;
|
bmkt_del_all_users_resp_t del_all_users_resp;
|
||||||
bmkt_enroll_templates_resp_t enroll_templates_resp;
|
bmkt_enroll_templates_resp_t enroll_templates_resp;
|
||||||
bmkt_del_user_resp_t del_user_resp;
|
bmkt_del_user_resp_t del_user_resp;
|
||||||
bmkt_del_all_users_resp_t del_all_user_resp;
|
|
||||||
bmkt_enrolled_fingers_resp_t enrolled_fingers_resp;
|
bmkt_enrolled_fingers_resp_t enrolled_fingers_resp;
|
||||||
} bmkt_response_data_t;
|
} bmkt_response_data_t;
|
||||||
|
|
||||||
|
|||||||
@@ -31,26 +31,14 @@ static void init_identify_msg (FpDevice *device);
|
|||||||
static void compose_and_send_identify_msg (FpDevice *device);
|
static void compose_and_send_identify_msg (FpDevice *device);
|
||||||
|
|
||||||
static const FpIdEntry id_table[] = {
|
static const FpIdEntry id_table[] = {
|
||||||
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x00BD, },
|
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0xBD, },
|
||||||
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x00DF, },
|
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0xE9, },
|
||||||
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x00F9, },
|
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0xDF, },
|
||||||
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x00FC, },
|
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0xF9, },
|
||||||
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x00C2, },
|
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0xFC, },
|
||||||
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x00C4, },
|
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0xC2, },
|
||||||
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0100, },
|
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0xC9, },
|
||||||
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x00F0, },
|
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0xE7, },
|
||||||
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0103, },
|
|
||||||
{ .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 = 0x0168, },
|
|
||||||
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x015F, },
|
|
||||||
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0104, },
|
|
||||||
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0173, },
|
|
||||||
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0106, },
|
|
||||||
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x019D, },
|
|
||||||
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x00C6, },
|
|
||||||
{ .vid = 0, .pid = 0, .driver_data = 0 }, /* terminating entry */
|
{ .vid = 0, .pid = 0, .driver_data = 0 }, /* terminating entry */
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -112,11 +100,7 @@ cmd_receive_cb (FpiUsbTransfer *transfer,
|
|||||||
|
|
||||||
if (self->cmd_complete_on_removal)
|
if (self->cmd_complete_on_removal)
|
||||||
{
|
{
|
||||||
if (self->delay_error)
|
fpi_ssm_mark_completed (transfer->ssm);
|
||||||
fpi_ssm_mark_failed (transfer->ssm,
|
|
||||||
g_steal_pointer (&self->delay_error));
|
|
||||||
else
|
|
||||||
fpi_ssm_mark_completed (transfer->ssm);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -213,17 +197,12 @@ cmd_interrupt_cb (FpiUsbTransfer *transfer,
|
|||||||
GError *error)
|
GError *error)
|
||||||
{
|
{
|
||||||
g_debug ("interrupt transfer done");
|
g_debug ("interrupt transfer done");
|
||||||
fpi_device_critical_enter (device);
|
|
||||||
|
|
||||||
if (error)
|
if (error)
|
||||||
{
|
{
|
||||||
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
||||||
{
|
{
|
||||||
g_error_free (error);
|
g_error_free (error);
|
||||||
if (FPI_DEVICE_SYNAPTICS (device)->cmd_suspended)
|
fpi_ssm_jump_to_state (transfer->ssm, SYNAPTICS_CMD_GET_RESP);
|
||||||
fpi_ssm_jump_to_state (transfer->ssm, SYNAPTICS_CMD_SUSPENDED);
|
|
||||||
else
|
|
||||||
fpi_ssm_jump_to_state (transfer->ssm, SYNAPTICS_CMD_GET_RESP);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -237,7 +216,6 @@ cmd_interrupt_cb (FpiUsbTransfer *transfer,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
fpi_device_critical_leave (device);
|
|
||||||
fpi_usb_transfer_submit (fpi_usb_transfer_ref (transfer),
|
fpi_usb_transfer_submit (fpi_usb_transfer_ref (transfer),
|
||||||
0,
|
0,
|
||||||
NULL,
|
NULL,
|
||||||
@@ -285,9 +263,6 @@ synaptics_cmd_run_state (FpiSsm *ssm,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case SYNAPTICS_CMD_WAIT_INTERRUPT:
|
case SYNAPTICS_CMD_WAIT_INTERRUPT:
|
||||||
/* Interruptions are permitted only during an interrupt transfer */
|
|
||||||
fpi_device_critical_leave (dev);
|
|
||||||
|
|
||||||
transfer = fpi_usb_transfer_new (dev);
|
transfer = fpi_usb_transfer_new (dev);
|
||||||
transfer->ssm = ssm;
|
transfer->ssm = ssm;
|
||||||
fpi_usb_transfer_fill_interrupt (transfer, USB_EP_INTERRUPT, USB_INTERRUPT_DATA_SIZE);
|
fpi_usb_transfer_fill_interrupt (transfer, USB_EP_INTERRUPT, USB_INTERRUPT_DATA_SIZE);
|
||||||
@@ -315,17 +290,6 @@ synaptics_cmd_run_state (FpiSsm *ssm,
|
|||||||
case SYNAPTICS_CMD_RESTART:
|
case SYNAPTICS_CMD_RESTART:
|
||||||
fpi_ssm_jump_to_state (ssm, SYNAPTICS_CMD_SEND_PENDING);
|
fpi_ssm_jump_to_state (ssm, SYNAPTICS_CMD_SEND_PENDING);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SYNAPTICS_CMD_SUSPENDED:
|
|
||||||
/* The resume handler continues to the next state! */
|
|
||||||
fpi_device_critical_leave (dev);
|
|
||||||
fpi_device_suspend_complete (dev, NULL);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SYNAPTICS_CMD_RESUME:
|
|
||||||
fpi_device_critical_enter (dev);
|
|
||||||
fpi_ssm_jump_to_state (ssm, SYNAPTICS_CMD_WAIT_INTERRUPT);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -341,7 +305,6 @@ cmd_ssm_done (FpiSsm *ssm, FpDevice *dev, GError *error)
|
|||||||
if (error || self->cmd_complete_on_removal)
|
if (error || self->cmd_complete_on_removal)
|
||||||
callback (self, NULL, error);
|
callback (self, NULL, error);
|
||||||
|
|
||||||
fpi_device_critical_leave (dev);
|
|
||||||
self->cmd_complete_on_removal = FALSE;
|
self->cmd_complete_on_removal = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -451,7 +414,6 @@ synaptics_sensor_cmd (FpiDeviceSynaptics *self,
|
|||||||
SYNAPTICS_CMD_NUM_STATES);
|
SYNAPTICS_CMD_NUM_STATES);
|
||||||
fpi_ssm_set_data (self->cmd_ssm, callback, NULL);
|
fpi_ssm_set_data (self->cmd_ssm, callback, NULL);
|
||||||
|
|
||||||
fpi_device_critical_enter (FP_DEVICE (self));
|
|
||||||
fpi_ssm_start (self->cmd_ssm, cmd_ssm_done);
|
fpi_ssm_start (self->cmd_ssm, cmd_ssm_done);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -498,7 +460,7 @@ create_print (FpiDeviceSynaptics *self,
|
|||||||
guint8 finger_id)
|
guint8 finger_id)
|
||||||
{
|
{
|
||||||
FpPrint *print;
|
FpPrint *print;
|
||||||
g_autofree gchar *user_id_safe = NULL;
|
g_autofree gchar *user_id_safe;
|
||||||
GVariant *data = NULL;
|
GVariant *data = NULL;
|
||||||
GVariant *uid = NULL;
|
GVariant *uid = NULL;
|
||||||
|
|
||||||
@@ -523,6 +485,100 @@ create_print (FpiDeviceSynaptics *self,
|
|||||||
return print;
|
return print;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
list_msg_cb (FpiDeviceSynaptics *self,
|
||||||
|
bmkt_response_t *resp,
|
||||||
|
GError *error)
|
||||||
|
{
|
||||||
|
bmkt_enroll_templates_resp_t *get_enroll_templates_resp;
|
||||||
|
|
||||||
|
if (error)
|
||||||
|
{
|
||||||
|
g_clear_pointer (&self->list_result, g_ptr_array_unref);
|
||||||
|
fpi_device_list_complete (FP_DEVICE (self), NULL, error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
get_enroll_templates_resp = &resp->response.enroll_templates_resp;
|
||||||
|
|
||||||
|
switch (resp->response_id)
|
||||||
|
{
|
||||||
|
case BMKT_RSP_QUERY_FAIL:
|
||||||
|
if (resp->result == BMKT_FP_DATABASE_EMPTY)
|
||||||
|
{
|
||||||
|
fp_info ("Database is empty");
|
||||||
|
|
||||||
|
fpi_device_list_complete (FP_DEVICE (self),
|
||||||
|
g_steal_pointer (&self->list_result),
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fp_info ("Failed to query enrolled users: %d", resp->result);
|
||||||
|
g_clear_pointer (&self->list_result, g_ptr_array_unref);
|
||||||
|
fpi_device_list_complete (FP_DEVICE (self),
|
||||||
|
NULL,
|
||||||
|
fpi_device_error_new_msg (FP_DEVICE_ERROR_GENERAL,
|
||||||
|
"Failed to query enrolled users: %d",
|
||||||
|
resp->result));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BMKT_RSP_QUERY_RESPONSE_COMPLETE:
|
||||||
|
fp_info ("Query complete!");
|
||||||
|
|
||||||
|
fpi_device_list_complete (FP_DEVICE (self),
|
||||||
|
g_steal_pointer (&self->list_result),
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BMKT_RSP_TEMPLATE_RECORDS_REPORT:
|
||||||
|
|
||||||
|
for (int n = 0; n < BMKT_MAX_NUM_TEMPLATES_INTERNAL_FLASH; n++)
|
||||||
|
{
|
||||||
|
FpPrint *print;
|
||||||
|
|
||||||
|
if (get_enroll_templates_resp->templates[n].user_id_len == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
fp_info ("![query %d of %d] template %d: status=0x%x, userId=%s, fingerId=%d",
|
||||||
|
get_enroll_templates_resp->query_sequence,
|
||||||
|
get_enroll_templates_resp->total_query_messages,
|
||||||
|
n,
|
||||||
|
get_enroll_templates_resp->templates[n].template_status,
|
||||||
|
get_enroll_templates_resp->templates[n].user_id,
|
||||||
|
get_enroll_templates_resp->templates[n].finger_id);
|
||||||
|
|
||||||
|
print = create_print (self,
|
||||||
|
get_enroll_templates_resp->templates[n].user_id,
|
||||||
|
get_enroll_templates_resp->templates[n].finger_id);
|
||||||
|
|
||||||
|
g_ptr_array_add (self->list_result, g_object_ref_sink (print));
|
||||||
|
}
|
||||||
|
|
||||||
|
synaptics_sensor_cmd (self,
|
||||||
|
self->cmd_seq_num,
|
||||||
|
BMKT_CMD_GET_NEXT_QUERY_RESPONSE,
|
||||||
|
NULL,
|
||||||
|
0,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
list (FpDevice *device)
|
||||||
|
{
|
||||||
|
FpiDeviceSynaptics *self = FPI_DEVICE_SYNAPTICS (device);
|
||||||
|
|
||||||
|
G_DEBUG_HERE ();
|
||||||
|
|
||||||
|
self->list_result = g_ptr_array_new_with_free_func (g_object_unref);
|
||||||
|
synaptics_sensor_cmd (self, 0, BMKT_CMD_GET_TEMPLATE_RECORDS, NULL, 0, list_msg_cb);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
verify_complete_after_finger_removal (FpiDeviceSynaptics *self)
|
verify_complete_after_finger_removal (FpiDeviceSynaptics *self)
|
||||||
{
|
{
|
||||||
@@ -547,12 +603,6 @@ verify_msg_cb (FpiDeviceSynaptics *self,
|
|||||||
FpDevice *device = FP_DEVICE (self);
|
FpDevice *device = FP_DEVICE (self);
|
||||||
bmkt_verify_resp_t *verify_resp;
|
bmkt_verify_resp_t *verify_resp;
|
||||||
|
|
||||||
if (self->action_starting)
|
|
||||||
{
|
|
||||||
fpi_device_critical_leave (device);
|
|
||||||
self->action_starting = FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (error)
|
if (error)
|
||||||
{
|
{
|
||||||
fpi_device_verify_complete (device, error);
|
fpi_device_verify_complete (device, error);
|
||||||
@@ -645,27 +695,22 @@ verify (FpDevice *device)
|
|||||||
|
|
||||||
G_DEBUG_HERE ();
|
G_DEBUG_HERE ();
|
||||||
|
|
||||||
self->action_starting = TRUE;
|
|
||||||
fpi_device_critical_enter (device);
|
|
||||||
synaptics_sensor_cmd (self, 0, BMKT_CMD_VERIFY_USER, user_id, user_id_len, verify_msg_cb);
|
synaptics_sensor_cmd (self, 0, BMKT_CMD_VERIFY_USER, user_id, user_id_len, verify_msg_cb);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
identify_complete_after_finger_removal (FpiDeviceSynaptics *self, GError *error)
|
identify_complete_after_finger_removal (FpiDeviceSynaptics *self)
|
||||||
{
|
{
|
||||||
FpDevice *device = FP_DEVICE (self);
|
FpDevice *device = FP_DEVICE (self);
|
||||||
|
|
||||||
if (self->finger_on_sensor)
|
if (self->finger_on_sensor)
|
||||||
{
|
{
|
||||||
fp_dbg ("delaying identify report until after finger removal!");
|
fp_dbg ("delaying identify report until after finger removal!");
|
||||||
if (error)
|
|
||||||
g_propagate_error (&self->delay_error, error);
|
|
||||||
|
|
||||||
self->cmd_complete_on_removal = TRUE;
|
self->cmd_complete_on_removal = TRUE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
fpi_device_identify_complete (device, error);
|
fpi_device_identify_complete (device, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -677,12 +722,6 @@ identify_msg_cb (FpiDeviceSynaptics *self,
|
|||||||
{
|
{
|
||||||
FpDevice *device = FP_DEVICE (self);
|
FpDevice *device = FP_DEVICE (self);
|
||||||
|
|
||||||
if (self->action_starting)
|
|
||||||
{
|
|
||||||
fpi_device_critical_leave (device);
|
|
||||||
self->action_starting = FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (error)
|
if (error)
|
||||||
{
|
{
|
||||||
fpi_device_identify_complete (device, error);
|
fpi_device_identify_complete (device, error);
|
||||||
@@ -715,18 +754,19 @@ identify_msg_cb (FpiDeviceSynaptics *self,
|
|||||||
fp_info ("Match error occurred");
|
fp_info ("Match error occurred");
|
||||||
fpi_device_identify_report (device, NULL, NULL,
|
fpi_device_identify_report (device, NULL, NULL,
|
||||||
fpi_device_retry_new (FP_DEVICE_RETRY_GENERAL));
|
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)
|
else if (resp->result == BMKT_FP_NO_MATCH)
|
||||||
{
|
{
|
||||||
fp_info ("Print didn't match");
|
fp_info ("Print didn't match");
|
||||||
fpi_device_identify_report (device, NULL, NULL, NULL);
|
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");
|
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
|
else
|
||||||
{
|
{
|
||||||
@@ -762,7 +802,7 @@ identify_msg_cb (FpiDeviceSynaptics *self,
|
|||||||
else
|
else
|
||||||
fpi_device_identify_report (device, NULL, print, NULL);
|
fpi_device_identify_report (device, NULL, print, NULL);
|
||||||
|
|
||||||
identify_complete_after_finger_removal (self, NULL);
|
identify_complete_after_finger_removal (self);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -770,25 +810,6 @@ identify_msg_cb (FpiDeviceSynaptics *self,
|
|||||||
static void
|
static void
|
||||||
identify (FpDevice *device)
|
identify (FpDevice *device)
|
||||||
{
|
{
|
||||||
GPtrArray *prints = NULL;
|
|
||||||
FpiDeviceSynaptics *self = FPI_DEVICE_SYNAPTICS (device);
|
|
||||||
|
|
||||||
fpi_device_get_identify_data (device, &prints);
|
|
||||||
|
|
||||||
/* Identify over no prints does not work for synaptics.
|
|
||||||
* This *may* make sense for other devices though, as identify may return
|
|
||||||
* a matched print even if it is not in the list of prints.
|
|
||||||
*/
|
|
||||||
if (prints->len == 0)
|
|
||||||
{
|
|
||||||
fpi_device_identify_report (device, NULL, NULL, NULL);
|
|
||||||
fpi_device_identify_complete (device, NULL);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
self->action_starting = TRUE;
|
|
||||||
fpi_device_critical_enter (device);
|
|
||||||
|
|
||||||
init_identify_msg (device);
|
init_identify_msg (device);
|
||||||
compose_and_send_identify_msg (device);
|
compose_and_send_identify_msg (device);
|
||||||
}
|
}
|
||||||
@@ -891,12 +912,6 @@ enroll_msg_cb (FpiDeviceSynaptics *self,
|
|||||||
FpDevice *device = FP_DEVICE (self);
|
FpDevice *device = FP_DEVICE (self);
|
||||||
bmkt_enroll_resp_t *enroll_resp;
|
bmkt_enroll_resp_t *enroll_resp;
|
||||||
|
|
||||||
if (self->action_starting)
|
|
||||||
{
|
|
||||||
fpi_device_critical_leave (device);
|
|
||||||
self->action_starting = FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (error)
|
if (error)
|
||||||
{
|
{
|
||||||
fpi_device_enroll_complete (device, NULL, error);
|
fpi_device_enroll_complete (device, NULL, error);
|
||||||
@@ -1043,9 +1058,6 @@ enroll (FpDevice *device)
|
|||||||
payload[1] = finger;
|
payload[1] = finger;
|
||||||
memcpy (payload + 2, user_id, user_id_len);
|
memcpy (payload + 2, user_id, user_id_len);
|
||||||
|
|
||||||
self->action_starting = TRUE;
|
|
||||||
fpi_device_critical_enter (device);
|
|
||||||
|
|
||||||
synaptics_sensor_cmd (self, 0, BMKT_CMD_ENROLL_USER, payload, user_id_len + 2, enroll_msg_cb);
|
synaptics_sensor_cmd (self, 0, BMKT_CMD_ENROLL_USER, payload, user_id_len + 2, enroll_msg_cb);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1059,7 +1071,6 @@ delete_msg_cb (FpiDeviceSynaptics *self,
|
|||||||
|
|
||||||
if (error)
|
if (error)
|
||||||
{
|
{
|
||||||
fpi_device_critical_leave (device);
|
|
||||||
fpi_device_delete_complete (device, error);
|
fpi_device_delete_complete (device, error);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1074,24 +1085,17 @@ delete_msg_cb (FpiDeviceSynaptics *self,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case BMKT_RSP_DEL_USER_FP_FAIL:
|
case BMKT_RSP_DEL_USER_FP_FAIL:
|
||||||
fpi_device_critical_leave (device);
|
fp_info ("Failed to delete enrolled user: %d", resp->result);
|
||||||
if (resp->result == BMKT_FP_DATABASE_NO_RECORD_EXISTS ||
|
if (resp->result == BMKT_FP_DATABASE_NO_RECORD_EXISTS)
|
||||||
resp->result == BMKT_FP_DATABASE_EMPTY)
|
fpi_device_delete_complete (device,
|
||||||
{
|
fpi_device_error_new (FP_DEVICE_ERROR_DATA_NOT_FOUND));
|
||||||
fp_info ("Database no record");
|
|
||||||
fpi_device_delete_complete (device, NULL);
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
fpi_device_delete_complete (device,
|
||||||
fp_info ("Failed to delete enrolled user: %d", resp->result);
|
fpi_device_error_new (FP_DEVICE_ERROR_GENERAL));
|
||||||
fpi_device_delete_complete (device,
|
|
||||||
fpi_device_error_new (FP_DEVICE_ERROR_GENERAL));
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case BMKT_RSP_DEL_USER_FP_OK:
|
case BMKT_RSP_DEL_USER_FP_OK:
|
||||||
fp_info ("Successfully deleted enrolled user");
|
fp_info ("Successfully deleted enrolled user");
|
||||||
fpi_device_critical_leave (device);
|
|
||||||
fpi_device_delete_complete (device, NULL);
|
fpi_device_delete_complete (device, NULL);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1126,58 +1130,9 @@ delete_print (FpDevice *device)
|
|||||||
payload[0] = finger;
|
payload[0] = finger;
|
||||||
memcpy (payload + 1, user_id, user_id_len);
|
memcpy (payload + 1, user_id, user_id_len);
|
||||||
|
|
||||||
fpi_device_critical_enter (device);
|
|
||||||
synaptics_sensor_cmd (self, 0, BMKT_CMD_DEL_USER_FP, payload, user_id_len + 1, delete_msg_cb);
|
synaptics_sensor_cmd (self, 0, BMKT_CMD_DEL_USER_FP, payload, user_id_len + 1, delete_msg_cb);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
clear_storage_msg_cb (FpiDeviceSynaptics *self,
|
|
||||||
bmkt_response_t *resp,
|
|
||||||
GError *error)
|
|
||||||
{
|
|
||||||
FpDevice *device = FP_DEVICE (self);
|
|
||||||
bmkt_del_all_users_resp_t *del_all_user_resp;
|
|
||||||
|
|
||||||
if (error)
|
|
||||||
{
|
|
||||||
fpi_device_clear_storage_complete (device, error);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
del_all_user_resp = &resp->response.del_all_user_resp;
|
|
||||||
|
|
||||||
switch (resp->response_id)
|
|
||||||
{
|
|
||||||
case BMKT_RSP_DELETE_PROGRESS:
|
|
||||||
fp_info ("Deleting All Enrolled Users is %d%% complete",
|
|
||||||
del_all_user_resp->progress);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BMKT_RSP_DEL_FULL_DB_FAIL:
|
|
||||||
if (resp->result == BMKT_FP_DATABASE_EMPTY)
|
|
||||||
fpi_device_clear_storage_complete (device, NULL);
|
|
||||||
else
|
|
||||||
fpi_device_clear_storage_complete (device,
|
|
||||||
fpi_device_error_new (FP_DEVICE_ERROR_GENERAL));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BMKT_RSP_DEL_FULL_DB_OK:
|
|
||||||
fp_info ("Successfully deleted all enrolled user");
|
|
||||||
fpi_device_clear_storage_complete (device, NULL);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
clear_storage (FpDevice *device)
|
|
||||||
{
|
|
||||||
FpiDeviceSynaptics *self = FPI_DEVICE_SYNAPTICS (device);
|
|
||||||
|
|
||||||
g_debug ("clear all prints in database");
|
|
||||||
synaptics_sensor_cmd (self, 0, BMKT_CMD_DEL_FULL_DB, NULL, 0, clear_storage_msg_cb);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
prob_msg_cb (FpiDeviceSynaptics *self,
|
prob_msg_cb (FpiDeviceSynaptics *self,
|
||||||
bmkt_response_t *resp,
|
bmkt_response_t *resp,
|
||||||
@@ -1185,18 +1140,14 @@ prob_msg_cb (FpiDeviceSynaptics *self,
|
|||||||
{
|
{
|
||||||
GUsbDevice *usb_dev = NULL;
|
GUsbDevice *usb_dev = NULL;
|
||||||
g_autofree gchar *serial = NULL;
|
g_autofree gchar *serial = NULL;
|
||||||
GError *err = NULL;
|
|
||||||
|
|
||||||
usb_dev = fpi_device_get_usb_device (FP_DEVICE (self));
|
usb_dev = fpi_device_get_usb_device (FP_DEVICE (self));
|
||||||
|
|
||||||
if (error)
|
if (error)
|
||||||
{
|
{
|
||||||
if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
|
||||||
err = fpi_device_error_new_msg (FP_DEVICE_ERROR_GENERAL, "unsupported firmware version");
|
|
||||||
|
|
||||||
g_usb_device_close (usb_dev, NULL);
|
g_usb_device_close (usb_dev, NULL);
|
||||||
fpi_device_probe_complete (FP_DEVICE (self), NULL, NULL, err);
|
fpi_device_probe_complete (FP_DEVICE (self), NULL, NULL,
|
||||||
g_clear_error (&error);
|
fpi_device_error_new_msg (FP_DEVICE_ERROR_GENERAL, "unsupported firmware version"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1205,17 +1156,12 @@ prob_msg_cb (FpiDeviceSynaptics *self,
|
|||||||
else
|
else
|
||||||
serial = g_usb_device_get_string_descriptor (usb_dev,
|
serial = g_usb_device_get_string_descriptor (usb_dev,
|
||||||
g_usb_device_get_serial_number_index (usb_dev),
|
g_usb_device_get_serial_number_index (usb_dev),
|
||||||
&err);
|
&error);
|
||||||
|
|
||||||
/* BMKT_OPERATION_DENIED is returned if the sensor is already initialized */
|
if (resp->result == BMKT_SUCCESS)
|
||||||
if (resp->result == BMKT_SUCCESS || resp->result == BMKT_OPERATION_DENIED)
|
|
||||||
{
|
{
|
||||||
g_usb_device_close (usb_dev, NULL);
|
g_usb_device_close (usb_dev, NULL);
|
||||||
fpi_device_probe_complete (FP_DEVICE (self), serial, NULL, err);
|
fpi_device_probe_complete (FP_DEVICE (self), serial, NULL, error);
|
||||||
}
|
|
||||||
else if (resp->result == BMKT_FP_SYSTEM_BUSY)
|
|
||||||
{
|
|
||||||
synaptics_sensor_cmd (self, self->cmd_seq_num, BMKT_CMD_CANCEL_OP, NULL, 0, NULL);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -1250,6 +1196,9 @@ dev_probe (FpDevice *device)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!g_usb_device_reset (usb_dev, &error))
|
||||||
|
goto err_close;
|
||||||
|
|
||||||
if (!g_usb_device_claim_interface (usb_dev, 0, 0, &error))
|
if (!g_usb_device_claim_interface (usb_dev, 0, 0, &error))
|
||||||
goto err_close;
|
goto err_close;
|
||||||
|
|
||||||
@@ -1338,9 +1287,6 @@ fps_init_msg_cb (FpiDeviceSynaptics *self,
|
|||||||
{
|
{
|
||||||
if (error)
|
if (error)
|
||||||
{
|
{
|
||||||
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
|
||||||
g_clear_error (&error);
|
|
||||||
|
|
||||||
fpi_device_open_complete (FP_DEVICE (self), error);
|
fpi_device_open_complete (FP_DEVICE (self), error);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1350,10 +1296,6 @@ fps_init_msg_cb (FpiDeviceSynaptics *self,
|
|||||||
{
|
{
|
||||||
fpi_device_open_complete (FP_DEVICE (self), NULL);
|
fpi_device_open_complete (FP_DEVICE (self), NULL);
|
||||||
}
|
}
|
||||||
else if (resp->result == BMKT_FP_SYSTEM_BUSY)
|
|
||||||
{
|
|
||||||
synaptics_sensor_cmd (self, self->cmd_seq_num, BMKT_CMD_CANCEL_OP, NULL, 0, NULL);
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
g_warning ("Initializing fingerprint sensor failed with %d!", resp->result);
|
g_warning ("Initializing fingerprint sensor failed with %d!", resp->result);
|
||||||
@@ -1366,12 +1308,8 @@ fps_deinit_cb (FpiDeviceSynaptics *self,
|
|||||||
bmkt_response_t *resp,
|
bmkt_response_t *resp,
|
||||||
GError *error)
|
GError *error)
|
||||||
{
|
{
|
||||||
g_autoptr(GError) err = NULL;
|
|
||||||
|
|
||||||
/* Release usb interface */
|
/* Release usb interface */
|
||||||
g_usb_device_release_interface (fpi_device_get_usb_device (FP_DEVICE (self)), 0, 0, &err);
|
g_usb_device_release_interface (fpi_device_get_usb_device (FP_DEVICE (self)), 0, 0, &error);
|
||||||
if (!error)
|
|
||||||
error = g_steal_pointer (&err);
|
|
||||||
|
|
||||||
g_clear_object (&self->interrupt_cancellable);
|
g_clear_object (&self->interrupt_cancellable);
|
||||||
|
|
||||||
@@ -1404,6 +1342,9 @@ dev_init (FpDevice *device)
|
|||||||
|
|
||||||
self->interrupt_cancellable = g_cancellable_new ();
|
self->interrupt_cancellable = g_cancellable_new ();
|
||||||
|
|
||||||
|
if (!g_usb_device_reset (fpi_device_get_usb_device (device), &error))
|
||||||
|
goto error;
|
||||||
|
|
||||||
/* Claim usb interface */
|
/* Claim usb interface */
|
||||||
if (!g_usb_device_claim_interface (fpi_device_get_usb_device (device), 0, 0, &error))
|
if (!g_usb_device_claim_interface (fpi_device_get_usb_device (device), 0, 0, &error))
|
||||||
goto error;
|
goto error;
|
||||||
@@ -1442,59 +1383,6 @@ cancel (FpDevice *dev)
|
|||||||
self->interrupt_cancellable = g_cancellable_new ();
|
self->interrupt_cancellable = g_cancellable_new ();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
suspend (FpDevice *dev)
|
|
||||||
{
|
|
||||||
FpiDeviceSynaptics *self = FPI_DEVICE_SYNAPTICS (dev);
|
|
||||||
FpiDeviceAction action = fpi_device_get_current_action (dev);
|
|
||||||
|
|
||||||
g_debug ("got suspend request");
|
|
||||||
|
|
||||||
if (action != FPI_DEVICE_ACTION_VERIFY && action != FPI_DEVICE_ACTION_IDENTIFY)
|
|
||||||
{
|
|
||||||
fpi_device_suspend_complete (dev, fpi_device_error_new (FP_DEVICE_ERROR_NOT_SUPPORTED));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* We are guaranteed to have a cmd_ssm running at this time. */
|
|
||||||
g_assert (self->cmd_ssm);
|
|
||||||
g_assert (fpi_ssm_get_cur_state (self->cmd_ssm) == SYNAPTICS_CMD_WAIT_INTERRUPT);
|
|
||||||
self->cmd_suspended = TRUE;
|
|
||||||
|
|
||||||
/* Cancel the current transfer.
|
|
||||||
* 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 ();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
resume (FpDevice *dev)
|
|
||||||
{
|
|
||||||
FpiDeviceSynaptics *self = FPI_DEVICE_SYNAPTICS (dev);
|
|
||||||
FpiDeviceAction action = fpi_device_get_current_action (dev);
|
|
||||||
|
|
||||||
g_debug ("got resume request");
|
|
||||||
|
|
||||||
if (action != FPI_DEVICE_ACTION_VERIFY && action != FPI_DEVICE_ACTION_IDENTIFY)
|
|
||||||
{
|
|
||||||
g_assert_not_reached ();
|
|
||||||
fpi_device_resume_complete (dev, fpi_device_error_new (FP_DEVICE_ERROR_NOT_SUPPORTED));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* We must have a suspended cmd_ssm at this point */
|
|
||||||
g_assert (self->cmd_ssm);
|
|
||||||
g_assert (self->cmd_suspended);
|
|
||||||
g_assert (fpi_ssm_get_cur_state (self->cmd_ssm) == SYNAPTICS_CMD_SUSPENDED);
|
|
||||||
self->cmd_suspended = FALSE;
|
|
||||||
|
|
||||||
/* Restart interrupt transfer. */
|
|
||||||
fpi_ssm_jump_to_state (self->cmd_ssm, SYNAPTICS_CMD_RESUME);
|
|
||||||
|
|
||||||
fpi_device_resume_complete (dev, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
fpi_device_synaptics_init (FpiDeviceSynaptics *self)
|
fpi_device_synaptics_init (FpiDeviceSynaptics *self)
|
||||||
{
|
{
|
||||||
@@ -1512,7 +1400,6 @@ fpi_device_synaptics_class_init (FpiDeviceSynapticsClass *klass)
|
|||||||
dev_class->scan_type = FP_SCAN_TYPE_PRESS;
|
dev_class->scan_type = FP_SCAN_TYPE_PRESS;
|
||||||
dev_class->id_table = id_table;
|
dev_class->id_table = id_table;
|
||||||
dev_class->nr_enroll_stages = ENROLL_SAMPLES;
|
dev_class->nr_enroll_stages = ENROLL_SAMPLES;
|
||||||
dev_class->temp_hot_seconds = -1;
|
|
||||||
|
|
||||||
dev_class->open = dev_init;
|
dev_class->open = dev_init;
|
||||||
dev_class->close = dev_exit;
|
dev_class->close = dev_exit;
|
||||||
@@ -1521,10 +1408,6 @@ fpi_device_synaptics_class_init (FpiDeviceSynapticsClass *klass)
|
|||||||
dev_class->identify = identify;
|
dev_class->identify = identify;
|
||||||
dev_class->enroll = enroll;
|
dev_class->enroll = enroll;
|
||||||
dev_class->delete = delete_print;
|
dev_class->delete = delete_print;
|
||||||
dev_class->clear_storage = clear_storage;
|
|
||||||
dev_class->cancel = cancel;
|
dev_class->cancel = cancel;
|
||||||
dev_class->suspend = suspend;
|
dev_class->list = list;
|
||||||
dev_class->resume = resume;
|
|
||||||
|
|
||||||
fpi_device_class_auto_initialize_features (dev_class);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -93,8 +93,6 @@ typedef enum {
|
|||||||
SYNAPTICS_CMD_WAIT_INTERRUPT,
|
SYNAPTICS_CMD_WAIT_INTERRUPT,
|
||||||
SYNAPTICS_CMD_SEND_ASYNC,
|
SYNAPTICS_CMD_SEND_ASYNC,
|
||||||
SYNAPTICS_CMD_RESTART,
|
SYNAPTICS_CMD_RESTART,
|
||||||
SYNAPTICS_CMD_SUSPENDED,
|
|
||||||
SYNAPTICS_CMD_RESUME,
|
|
||||||
SYNAPTICS_CMD_NUM_STATES,
|
SYNAPTICS_CMD_NUM_STATES,
|
||||||
} SynapticsCmdState;
|
} SynapticsCmdState;
|
||||||
|
|
||||||
@@ -112,12 +110,10 @@ struct _FpiDeviceSynaptics
|
|||||||
FpiSsm *cmd_ssm;
|
FpiSsm *cmd_ssm;
|
||||||
FpiUsbTransfer *cmd_pending_transfer;
|
FpiUsbTransfer *cmd_pending_transfer;
|
||||||
gboolean cmd_complete_on_removal;
|
gboolean cmd_complete_on_removal;
|
||||||
gboolean cmd_suspended;
|
|
||||||
guint8 id_idx;
|
guint8 id_idx;
|
||||||
|
|
||||||
bmkt_sensor_version_t mis_version;
|
bmkt_sensor_version_t mis_version;
|
||||||
|
|
||||||
gboolean action_starting;
|
|
||||||
GCancellable *interrupt_cancellable;
|
GCancellable *interrupt_cancellable;
|
||||||
|
|
||||||
gint enroll_stage;
|
gint enroll_stage;
|
||||||
@@ -127,5 +123,4 @@ struct _FpiDeviceSynaptics
|
|||||||
|
|
||||||
struct syna_enroll_resp_data enroll_resp_data;
|
struct syna_enroll_resp_data enroll_resp_data;
|
||||||
syna_state_t state;
|
syna_state_t state;
|
||||||
GError *delay_error;
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,24 +1,21 @@
|
|||||||
/*
|
/*
|
||||||
* Code copied from gstreamer-plugins-bad gst/gdp/dataprotocol.c
|
* LGPL CRC code copied from GStreamer-0.10.10:
|
||||||
*
|
|
||||||
* Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
|
* Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
|
||||||
* Copyright (C) 2004,2006 Thomas Vander Stichele <thomas at apestaart dot org>
|
* Copyright (C) 2004,2006 Thomas Vander Stichele <thomas at apestaart dot org>
|
||||||
* Copyright (C) 2014 Tim-Philipp Müller <tim centricular 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; version
|
||||||
|
* 2.1 of the License.
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or modify
|
* This library is distributed in the hope that it will be useful,
|
||||||
* it under the terms of the GNU Lesser General Public License as
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* 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
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
* Lesser General Public License for more details.
|
* Lesser General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
* License along with this library; if not, write to the Free Software
|
* License along with this library; if not, write to the Free Software
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
* 02110-1301 USA
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "upek_proto.h"
|
#include "upek_proto.h"
|
||||||
|
|||||||
@@ -1,24 +1,21 @@
|
|||||||
/*
|
/*
|
||||||
* Code copied from gstreamer-plugins-bad gst/gdp/dataprotocol.c
|
* LGPL CRC code copied from GStreamer-0.10.10:
|
||||||
*
|
|
||||||
* Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
|
* Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
|
||||||
* Copyright (C) 2004,2006 Thomas Vander Stichele <thomas at apestaart dot org>
|
* Copyright (C) 2004,2006 Thomas Vander Stichele <thomas at apestaart dot org>
|
||||||
* Copyright (C) 2014 Tim-Philipp Müller <tim centricular 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; version
|
||||||
|
* 2.1 of the License.
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or modify
|
* This library is distributed in the hope that it will be useful,
|
||||||
* it under the terms of the GNU Lesser General Public License as
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* 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
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
* Lesser General Public License for more details.
|
* Lesser General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
* License along with this library; if not, write to the Free Software
|
* License along with this library; if not, write to the Free Software
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
* 02110-1301 USA
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|||||||
@@ -74,26 +74,26 @@ struct _FpiDeviceUpeksonly
|
|||||||
FpiSsm *loopsm;
|
FpiSsm *loopsm;
|
||||||
|
|
||||||
/* Do we really need multiple concurrent transfers? */
|
/* Do we really need multiple concurrent transfers? */
|
||||||
GCancellable *img_cancellable;
|
GCancellable *img_cancellable;
|
||||||
GPtrArray *img_transfers;
|
GPtrArray *img_transfers;
|
||||||
int num_flying;
|
int num_flying;
|
||||||
|
|
||||||
GSList *rows;
|
GSList *rows;
|
||||||
unsigned num_rows;
|
size_t num_rows;
|
||||||
unsigned char *rowbuf;
|
unsigned char *rowbuf;
|
||||||
int rowbuf_offset;
|
int rowbuf_offset;
|
||||||
|
|
||||||
int wraparounds;
|
int wraparounds;
|
||||||
int num_blank;
|
int num_blank;
|
||||||
int num_nonblank;
|
int num_nonblank;
|
||||||
enum sonly_fs finger_state;
|
enum sonly_fs finger_state;
|
||||||
int last_seqnum;
|
int last_seqnum;
|
||||||
|
|
||||||
enum sonly_kill_transfers_action killing_transfers;
|
enum sonly_kill_transfers_action killing_transfers;
|
||||||
GError *kill_error;
|
GError *kill_error;
|
||||||
FpiSsm *kill_ssm;
|
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,
|
G_DECLARE_FINAL_TYPE (FpiDeviceUpeksonly, fpi_device_upeksonly, FPI,
|
||||||
DEVICE_UPEKSONLY, FpImageDevice);
|
DEVICE_UPEKSONLY, FpImageDevice);
|
||||||
@@ -176,7 +176,6 @@ last_transfer_killed (FpImageDevice *dev)
|
|||||||
fpi_image_device_session_error (dev, g_steal_pointer (&self->kill_error));
|
fpi_image_device_session_error (dev, g_steal_pointer (&self->kill_error));
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case NOT_KILLING:
|
|
||||||
default:
|
default:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -215,7 +214,7 @@ handoff_img (FpImageDevice *dev)
|
|||||||
|
|
||||||
self->rows = g_slist_reverse (self->rows);
|
self->rows = g_slist_reverse (self->rows);
|
||||||
|
|
||||||
fp_dbg ("%u rows", self->num_rows);
|
fp_dbg ("%lu rows", self->num_rows);
|
||||||
img = fpi_assemble_lines (&self->assembling_ctx, self->rows, self->num_rows);
|
img = fpi_assemble_lines (&self->assembling_ctx, self->rows, self->num_rows);
|
||||||
|
|
||||||
g_slist_free_full (self->rows, g_free);
|
g_slist_free_full (self->rows, g_free);
|
||||||
@@ -295,7 +294,7 @@ row_complete (FpImageDevice *dev)
|
|||||||
if (self->num_blank > FINGER_REMOVED_THRESHOLD)
|
if (self->num_blank > FINGER_REMOVED_THRESHOLD)
|
||||||
{
|
{
|
||||||
self->finger_state = FINGER_REMOVED;
|
self->finger_state = FINGER_REMOVED;
|
||||||
fp_dbg ("detected finger removal. Blank rows: %d, Full rows: %u",
|
fp_dbg ("detected finger removal. Blank rows: %d, Full rows: %lu",
|
||||||
self->num_blank, self->num_rows);
|
self->num_blank, self->num_rows);
|
||||||
handoff_img (dev);
|
handoff_img (dev);
|
||||||
return;
|
return;
|
||||||
@@ -694,6 +693,8 @@ sm_read_reg_cb (FpiUsbTransfer *transfer, FpDevice *device,
|
|||||||
fp_dbg ("read reg result = %02x", self->read_reg_result);
|
fp_dbg ("read reg result = %02x", self->read_reg_result);
|
||||||
fpi_ssm_next_state (transfer->ssm);
|
fpi_ssm_next_state (transfer->ssm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
g_free (transfer->buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -730,6 +731,7 @@ sm_await_intr_cb (FpiUsbTransfer *transfer, FpDevice *device,
|
|||||||
|
|
||||||
if (error)
|
if (error)
|
||||||
{
|
{
|
||||||
|
g_free (transfer->buffer);
|
||||||
fpi_ssm_mark_failed (transfer->ssm, error);
|
fpi_ssm_mark_failed (transfer->ssm, error);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -737,6 +739,7 @@ sm_await_intr_cb (FpiUsbTransfer *transfer, FpDevice *device,
|
|||||||
fp_dbg ("interrupt received: %02x %02x %02x %02x",
|
fp_dbg ("interrupt received: %02x %02x %02x %02x",
|
||||||
transfer->buffer[0], transfer->buffer[1],
|
transfer->buffer[0], transfer->buffer[1],
|
||||||
transfer->buffer[2], transfer->buffer[3]);
|
transfer->buffer[2], transfer->buffer[3]);
|
||||||
|
g_free (transfer->buffer);
|
||||||
|
|
||||||
self->finger_state = FINGER_DETECTED;
|
self->finger_state = FINGER_DETECTED;
|
||||||
fpi_image_device_report_finger_status (dev, TRUE);
|
fpi_image_device_report_finger_status (dev, TRUE);
|
||||||
|
|||||||
@@ -411,7 +411,7 @@ dev_init (FpImageDevice *dev)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
fp_err ("Device variant %" G_GUINT64_FORMAT " is not known", driver_data);
|
fp_err ("Device variant %lu is not known", driver_data);
|
||||||
g_assert_not_reached ();
|
g_assert_not_reached ();
|
||||||
fpi_image_device_open_complete (dev, fpi_device_error_new (FP_DEVICE_ERROR_GENERAL));
|
fpi_image_device_open_complete (dev, fpi_device_error_new (FP_DEVICE_ERROR_GENERAL));
|
||||||
return;
|
return;
|
||||||
@@ -431,7 +431,6 @@ dev_deinit (FpImageDevice *dev)
|
|||||||
|
|
||||||
static const FpIdEntry id_table[] = {
|
static const FpIdEntry id_table[] = {
|
||||||
{ .vid = 0x0483, .pid = 0x2015, .driver_data = UPEKTC_2015 },
|
{ .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 = 0x147e, .pid = 0x3001, .driver_data = UPEKTC_3001 },
|
||||||
{ .vid = 0, .pid = 0, .driver_data = 0 },
|
{ .vid = 0, .pid = 0, .driver_data = 0 },
|
||||||
};
|
};
|
||||||
|
|||||||
+25
-117
@@ -31,6 +31,10 @@ static void start_deactivation (FpImageDevice *dev);
|
|||||||
#define CTRL_TIMEOUT 4000
|
#define CTRL_TIMEOUT 4000
|
||||||
#define BULK_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_CMD_SIZE 64
|
||||||
#define MAX_RESPONSE_SIZE 2052
|
#define MAX_RESPONSE_SIZE 2052
|
||||||
#define SHORT_RESPONSE_SIZE 64
|
#define SHORT_RESPONSE_SIZE 64
|
||||||
@@ -43,10 +47,8 @@ struct _FpiDeviceUpektcImg
|
|||||||
unsigned char response[MAX_RESPONSE_SIZE];
|
unsigned char response[MAX_RESPONSE_SIZE];
|
||||||
unsigned char *image_bits;
|
unsigned char *image_bits;
|
||||||
unsigned char seq;
|
unsigned char seq;
|
||||||
size_t expected_image_size;
|
|
||||||
size_t image_size;
|
size_t image_size;
|
||||||
size_t response_rest;
|
size_t response_rest;
|
||||||
gboolean area_sensor;
|
|
||||||
gboolean deactivating;
|
gboolean deactivating;
|
||||||
};
|
};
|
||||||
G_DECLARE_FINAL_TYPE (FpiDeviceUpektcImg, fpi_device_upektc_img, FPI,
|
G_DECLARE_FINAL_TYPE (FpiDeviceUpektcImg, fpi_device_upektc_img, FPI,
|
||||||
@@ -178,7 +180,6 @@ capture_read_data_cb (FpiUsbTransfer *transfer, FpDevice *device,
|
|||||||
gpointer user_data, GError *error)
|
gpointer user_data, GError *error)
|
||||||
{
|
{
|
||||||
FpImageDevice *dev = FP_IMAGE_DEVICE (device);
|
FpImageDevice *dev = FP_IMAGE_DEVICE (device);
|
||||||
FpImageDeviceClass *img_class = FP_IMAGE_DEVICE_GET_CLASS (dev);
|
|
||||||
FpiDeviceUpektcImg *self = FPI_DEVICE_UPEKTC_IMG (dev);
|
FpiDeviceUpektcImg *self = FPI_DEVICE_UPEKTC_IMG (dev);
|
||||||
unsigned char *data = self->response;
|
unsigned char *data = self->response;
|
||||||
FpImage *img;
|
FpImage *img;
|
||||||
@@ -220,7 +221,7 @@ capture_read_data_cb (FpiUsbTransfer *transfer, FpDevice *device,
|
|||||||
if (response_size > transfer->actual_length)
|
if (response_size > transfer->actual_length)
|
||||||
{
|
{
|
||||||
fp_dbg ("response_size is %lu, actual_length is %d",
|
fp_dbg ("response_size is %lu, actual_length is %d",
|
||||||
(gulong) response_size, (gint) transfer->actual_length);
|
response_size, (gint) transfer->actual_length);
|
||||||
fp_dbg ("Waiting for rest of transfer");
|
fp_dbg ("Waiting for rest of transfer");
|
||||||
BUG_ON (self->response_rest);
|
BUG_ON (self->response_rest);
|
||||||
self->response_rest = response_size - transfer->actual_length;
|
self->response_rest = response_size - transfer->actual_length;
|
||||||
@@ -246,30 +247,8 @@ capture_read_data_cb (FpiUsbTransfer *transfer, FpDevice *device,
|
|||||||
CAPTURE_ACK_00_28);
|
CAPTURE_ACK_00_28);
|
||||||
break;
|
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:
|
case 0x00:
|
||||||
/* finger is present! */
|
/* 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,
|
fpi_ssm_jump_to_state (transfer->ssm,
|
||||||
CAPTURE_ACK_00_28);
|
CAPTURE_ACK_00_28);
|
||||||
break;
|
break;
|
||||||
@@ -282,20 +261,18 @@ capture_read_data_cb (FpiUsbTransfer *transfer, FpDevice *device,
|
|||||||
fpi_image_device_report_finger_status (dev,
|
fpi_image_device_report_finger_status (dev,
|
||||||
FALSE);
|
FALSE);
|
||||||
fpi_ssm_jump_to_state (transfer->ssm,
|
fpi_ssm_jump_to_state (transfer->ssm,
|
||||||
self->area_sensor ?
|
CAPTURE_ACK_00_28_TERM);
|
||||||
CAPTURE_ACK_00_28 : CAPTURE_ACK_00_28_TERM);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x1d:
|
case 0x1d:
|
||||||
/* too much horizontal movement */
|
/* too much horisontal movement */
|
||||||
fp_err ("too much horizontal movement, aborting");
|
fp_err ("too much horisontal movement, aborting");
|
||||||
fpi_image_device_retry_scan (dev,
|
fpi_image_device_retry_scan (dev,
|
||||||
FP_DEVICE_RETRY_CENTER_FINGER);
|
FP_DEVICE_RETRY_CENTER_FINGER);
|
||||||
fpi_image_device_report_finger_status (dev,
|
fpi_image_device_report_finger_status (dev,
|
||||||
FALSE);
|
FALSE);
|
||||||
fpi_ssm_jump_to_state (transfer->ssm,
|
fpi_ssm_jump_to_state (transfer->ssm,
|
||||||
self->area_sensor ?
|
CAPTURE_ACK_00_28_TERM);
|
||||||
CAPTURE_ACK_00_28 : CAPTURE_ACK_00_28_TERM);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@@ -306,8 +283,7 @@ capture_read_data_cb (FpiUsbTransfer *transfer, FpDevice *device,
|
|||||||
fpi_image_device_report_finger_status (dev,
|
fpi_image_device_report_finger_status (dev,
|
||||||
FALSE);
|
FALSE);
|
||||||
fpi_ssm_jump_to_state (transfer->ssm,
|
fpi_ssm_jump_to_state (transfer->ssm,
|
||||||
self->area_sensor ?
|
CAPTURE_ACK_00_28_TERM);
|
||||||
CAPTURE_ACK_00_28 : CAPTURE_ACK_00_28_TERM);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -331,13 +307,13 @@ capture_read_data_cb (FpiUsbTransfer *transfer, FpDevice *device,
|
|||||||
self->image_size +=
|
self->image_size +=
|
||||||
upektc_img_process_image_frame (self->image_bits + self->image_size,
|
upektc_img_process_image_frame (self->image_bits + self->image_size,
|
||||||
data);
|
data);
|
||||||
BUG_ON (self->image_size != self->expected_image_size);
|
BUG_ON (self->image_size != IMAGE_SIZE);
|
||||||
fp_dbg ("Image size is %lu",
|
fp_dbg ("Image size is %lu",
|
||||||
(gulong) self->image_size);
|
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;
|
img->flags |= FPI_IMAGE_PARTIAL;
|
||||||
memcpy (img->data, self->image_bits,
|
memcpy (img->data, self->image_bits,
|
||||||
self->image_size);
|
IMAGE_SIZE);
|
||||||
fpi_image_device_image_captured (dev, img);
|
fpi_image_device_image_captured (dev, img);
|
||||||
fpi_image_device_report_finger_status (dev,
|
fpi_image_device_report_finger_status (dev,
|
||||||
FALSE);
|
FALSE);
|
||||||
@@ -370,12 +346,8 @@ capture_run_state (FpiSsm *ssm, FpDevice *_dev)
|
|||||||
switch (fpi_ssm_get_cur_state (ssm))
|
switch (fpi_ssm_get_cur_state (ssm))
|
||||||
{
|
{
|
||||||
case CAPTURE_INIT_CAPTURE:
|
case CAPTURE_INIT_CAPTURE:
|
||||||
if (self->area_sensor)
|
upektc_img_submit_req (ssm, dev, upek2020_init_capture, sizeof (upek2020_init_capture),
|
||||||
upektc_img_submit_req (ssm, dev, upek2020_init_capture_press, sizeof (upek2020_init_capture_press),
|
self->seq, capture_reqs_cb);
|
||||||
self->seq, capture_reqs_cb);
|
|
||||||
else
|
|
||||||
upektc_img_submit_req (ssm, dev, upek2020_init_capture, sizeof (upek2020_init_capture),
|
|
||||||
self->seq, capture_reqs_cb);
|
|
||||||
self->seq++;
|
self->seq++;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -541,81 +513,15 @@ init_reqs_cb (FpiUsbTransfer *transfer, FpDevice *device,
|
|||||||
fpi_ssm_mark_failed (transfer->ssm, error);
|
fpi_ssm_mark_failed (transfer->ssm, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* TODO: process response properly */
|
||||||
static void
|
static void
|
||||||
init_read_data_cb (FpiUsbTransfer *transfer, FpDevice *device,
|
init_read_data_cb (FpiUsbTransfer *transfer, FpDevice *device,
|
||||||
gpointer user_data, GError *error)
|
gpointer user_data, GError *error)
|
||||||
{
|
{
|
||||||
FpImageDevice *dev = FP_IMAGE_DEVICE (device);
|
if (!error)
|
||||||
FpiDeviceUpektcImg *self = FPI_DEVICE_UPEKTC_IMG (dev);
|
fpi_ssm_next_state (transfer->ssm);
|
||||||
unsigned char *data = self->response;
|
else
|
||||||
|
fpi_ssm_mark_failed (transfer->ssm, error);
|
||||||
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;
|
|
||||||
self->image_bits = g_malloc0 (self->expected_image_size * 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
fpi_ssm_next_state (transfer->ssm);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -710,6 +616,7 @@ dev_deactivate (FpImageDevice *dev)
|
|||||||
static void
|
static void
|
||||||
dev_init (FpImageDevice *dev)
|
dev_init (FpImageDevice *dev)
|
||||||
{
|
{
|
||||||
|
FpiDeviceUpektcImg *self = FPI_DEVICE_UPEKTC_IMG (dev);
|
||||||
GError *error = NULL;
|
GError *error = NULL;
|
||||||
|
|
||||||
/* TODO check that device has endpoints we're using */
|
/* TODO check that device has endpoints we're using */
|
||||||
@@ -720,6 +627,7 @@ dev_init (FpImageDevice *dev)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self->image_bits = g_malloc0 (IMAGE_SIZE * 2);
|
||||||
fpi_image_device_open_complete (dev, NULL);
|
fpi_image_device_open_complete (dev, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -779,6 +687,6 @@ fpi_device_upektc_img_class_init (FpiDeviceUpektcImgClass *klass)
|
|||||||
|
|
||||||
img_class->bz3_threshold = 20;
|
img_class->bz3_threshold = 20;
|
||||||
|
|
||||||
img_class->img_width = -1;
|
img_class->img_width = IMAGE_WIDTH;
|
||||||
img_class->img_height = -1;
|
img_class->img_height = IMAGE_HEIGHT;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -75,22 +75,6 @@ static const unsigned char upek2020_init_capture[] = {
|
|||||||
0x02,
|
0x02,
|
||||||
0x00, /* Wait for acceptable finger */
|
0x00, /* Wait for acceptable finger */
|
||||||
0x02,
|
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 */
|
0x14, 0x9a /* CRC */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
+11
-14
@@ -10,20 +10,19 @@
|
|||||||
* Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
|
* Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
|
||||||
* Copyright (C) 2004,2006 Thomas Vander Stichele <thomas at apestaart dot org>
|
* Copyright (C) 2004,2006 Thomas Vander Stichele <thomas at apestaart dot org>
|
||||||
|
|
||||||
* This library is free software; you can redistribute it and/or modify
|
* This library is free software; you can redistribute it and/or
|
||||||
* it under the terms of the GNU Lesser General Public License as
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
* published by the Free Software Foundation; either version 2.1 of the
|
* License as published by the Free Software Foundation; version
|
||||||
* License, or (at your option) any later version.
|
* 2.1 of the License.
|
||||||
*
|
*
|
||||||
* This library is distributed in the hope that it will be useful, but
|
* This library is distributed in the hope that it will be useful,
|
||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
* Lesser General Public License for more details.
|
* Lesser General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
* License along with this library; if not, write to the Free Software
|
* License along with this library; if not, write to the Free Software
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
* 02110-1301 USA
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define FP_COMPONENT "upekts"
|
#define FP_COMPONENT "upekts"
|
||||||
@@ -366,7 +365,7 @@ read_msg_cb (FpiUsbTransfer *transfer, FpDevice *device,
|
|||||||
fp_err ("async msg read too short (%d)",
|
fp_err ("async msg read too short (%d)",
|
||||||
(gint) transfer->actual_length);
|
(gint) transfer->actual_length);
|
||||||
error = fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
|
error = fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
|
||||||
"Packet from device was too short (%" G_GSSIZE_FORMAT ")",
|
"Packet from device was too short (%lu)",
|
||||||
transfer->actual_length);
|
transfer->actual_length);
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
@@ -993,7 +992,7 @@ e_handle_resp00 (FpDevice *dev, unsigned char *data,
|
|||||||
|
|
||||||
if (data_len != 14)
|
if (data_len != 14)
|
||||||
{
|
{
|
||||||
fp_err ("received 3001 poll response of %" G_GSIZE_FORMAT " bytes?", data_len);
|
fp_err ("received 3001 poll response of %lu bytes?", data_len);
|
||||||
do_enroll_stop (dev, NULL,
|
do_enroll_stop (dev, NULL,
|
||||||
fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
|
fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
|
||||||
"received 3001 response with wrong length"));
|
"received 3001 response with wrong length"));
|
||||||
@@ -1090,7 +1089,7 @@ e_handle_resp02 (FpDevice *dev, unsigned char *data,
|
|||||||
|
|
||||||
if (data_len < sizeof (scan_comp))
|
if (data_len < sizeof (scan_comp))
|
||||||
{
|
{
|
||||||
fp_err ("fingerprint data too short (%" G_GSIZE_FORMAT "u bytes)", data_len);
|
fp_err ("fingerprint data too short (%lu bytes)", data_len);
|
||||||
error = fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO, "fingerprint data too short");
|
error = fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO, "fingerprint data too short");
|
||||||
}
|
}
|
||||||
else if (memcmp (data, scan_comp, sizeof (scan_comp)) != 0)
|
else if (memcmp (data, scan_comp, sizeof (scan_comp)) != 0)
|
||||||
@@ -1318,7 +1317,7 @@ v_handle_resp00 (FpDevice *dev, unsigned char *data,
|
|||||||
|
|
||||||
if (data_len != 14)
|
if (data_len != 14)
|
||||||
{
|
{
|
||||||
fp_warn ("received 3001 poll response of %" G_GSIZE_FORMAT "u bytes?", data_len);
|
fp_warn ("received 3001 poll response of %lu bytes?", data_len);
|
||||||
error = fpi_device_error_new (FP_DEVICE_ERROR_PROTO);
|
error = fpi_device_error_new (FP_DEVICE_ERROR_PROTO);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@@ -1556,6 +1555,4 @@ fpi_device_upekts_class_init (FpiDeviceUpektsClass *klass)
|
|||||||
dev_class->verify = verify;
|
dev_class->verify = verify;
|
||||||
dev_class->enroll = enroll;
|
dev_class->enroll = enroll;
|
||||||
/* dev_class->cancel = cancel; */
|
/* dev_class->cancel = cancel; */
|
||||||
|
|
||||||
fpi_device_class_auto_initialize_features (dev_class);
|
|
||||||
}
|
}
|
||||||
|
|||||||
+10
-23
@@ -131,7 +131,6 @@ struct _FpiDeviceUru4000
|
|||||||
void *img_data;
|
void *img_data;
|
||||||
int img_data_actual_length;
|
int img_data_actual_length;
|
||||||
uint16_t img_lines_done, img_block;
|
uint16_t img_lines_done, img_block;
|
||||||
GRand *rand;
|
|
||||||
uint32_t img_enc_seed;
|
uint32_t img_enc_seed;
|
||||||
|
|
||||||
irq_cb_fn irq_cb;
|
irq_cb_fn irq_cb;
|
||||||
@@ -317,7 +316,6 @@ irq_handler (FpiUsbTransfer *transfer,
|
|||||||
if (urudev->irqs_stopped_cb)
|
if (urudev->irqs_stopped_cb)
|
||||||
urudev->irqs_stopped_cb (imgdev);
|
urudev->irqs_stopped_cb (imgdev);
|
||||||
urudev->irqs_stopped_cb = NULL;
|
urudev->irqs_stopped_cb = NULL;
|
||||||
g_clear_error (&error);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (error)
|
else if (error)
|
||||||
@@ -361,9 +359,9 @@ start_irq_handler (FpImageDevice *dev)
|
|||||||
transfer = fpi_usb_transfer_new (FP_DEVICE (dev));
|
transfer = fpi_usb_transfer_new (FP_DEVICE (dev));
|
||||||
transfer->ssm = NULL;
|
transfer->ssm = NULL;
|
||||||
transfer->short_is_error = TRUE;
|
transfer->short_is_error = TRUE;
|
||||||
fpi_usb_transfer_fill_interrupt (transfer,
|
fpi_usb_transfer_fill_bulk (transfer,
|
||||||
EP_INTR,
|
EP_INTR,
|
||||||
IRQ_LENGTH);
|
IRQ_LENGTH);
|
||||||
fpi_usb_transfer_submit (transfer, 0, self->irq_cancellable, irq_handler, NULL);
|
fpi_usb_transfer_submit (transfer, 0, self->irq_cancellable, irq_handler, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -399,7 +397,7 @@ finger_presence_irq_cb (FpImageDevice *dev,
|
|||||||
fpi_image_device_report_finger_status (dev, TRUE);
|
fpi_image_device_report_finger_status (dev, TRUE);
|
||||||
else if (type == IRQDATA_FINGER_OFF)
|
else if (type == IRQDATA_FINGER_OFF)
|
||||||
fpi_image_device_report_finger_status (dev, FALSE);
|
fpi_image_device_report_finger_status (dev, FALSE);
|
||||||
else if (type != IRQDATA_SCANPWR_ON)
|
else
|
||||||
fp_warn ("ignoring unexpected interrupt %04x", type);
|
fp_warn ("ignoring unexpected interrupt %04x", type);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -552,7 +550,7 @@ image_transfer_cb (FpiUsbTransfer *transfer, FpDevice *dev,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
self->img_data = g_memdup2 (transfer->buffer, sizeof (struct uru4k_image));
|
self->img_data = g_memdup (transfer->buffer, sizeof (struct uru4k_image));
|
||||||
self->img_data_actual_length = transfer->actual_length;
|
self->img_data_actual_length = transfer->actual_length;
|
||||||
fpi_ssm_next_state (ssm);
|
fpi_ssm_next_state (ssm);
|
||||||
}
|
}
|
||||||
@@ -724,8 +722,7 @@ imaging_run_state (FpiSsm *ssm, FpDevice *_dev)
|
|||||||
fp_dbg ("changing encryption keys.");
|
fp_dbg ("changing encryption keys.");
|
||||||
img->block_info[self->img_block].flags &= ~BLOCKF_CHANGE_KEY;
|
img->block_info[self->img_block].flags &= ~BLOCKF_CHANGE_KEY;
|
||||||
img->key_number++;
|
img->key_number++;
|
||||||
self->img_enc_seed = g_rand_int_range (self->rand, 0, RAND_MAX);
|
self->img_enc_seed = rand ();
|
||||||
fp_dbg ("New image encryption seed: %d", self->img_enc_seed);
|
|
||||||
fpi_ssm_jump_to_state (ssm, IMAGING_SEND_INDEX);
|
fpi_ssm_jump_to_state (ssm, IMAGING_SEND_INDEX);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -868,7 +865,7 @@ rebootpwr_run_state (FpiSsm *ssm, FpDevice *_dev)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
fpi_ssm_jump_to_state_delayed (ssm, 10, REBOOTPWR_GET_HWSTAT);
|
fpi_ssm_jump_to_state_delayed (ssm, 10, REBOOTPWR_GET_HWSTAT, NULL);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -950,11 +947,11 @@ powerup_run_state (FpiSsm *ssm, FpDevice *_dev)
|
|||||||
}
|
}
|
||||||
else if (!self->profile->auth_cr)
|
else if (!self->profile->auth_cr)
|
||||||
{
|
{
|
||||||
fpi_ssm_jump_to_state_delayed (ssm, POWERUP_SET_HWSTAT, 10);
|
fpi_ssm_jump_to_state_delayed (ssm, POWERUP_SET_HWSTAT, 10, NULL);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
fpi_ssm_next_state_delayed (ssm, 10);
|
fpi_ssm_next_state_delayed (ssm, 10, NULL);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -1222,8 +1219,7 @@ execute_state_change (FpImageDevice *dev)
|
|||||||
|
|
||||||
ssm = fpi_ssm_new (FP_DEVICE (dev), imaging_run_state,
|
ssm = fpi_ssm_new (FP_DEVICE (dev), imaging_run_state,
|
||||||
IMAGING_NUM_STATES);
|
IMAGING_NUM_STATES);
|
||||||
self->img_enc_seed = g_rand_int_range (self->rand, 0, RAND_MAX);
|
self->img_enc_seed = rand ();
|
||||||
fp_dbg ("Image encryption seed: %d", self->img_enc_seed);
|
|
||||||
self->img_transfer = fpi_usb_transfer_new (FP_DEVICE (dev));
|
self->img_transfer = fpi_usb_transfer_new (FP_DEVICE (dev));
|
||||||
self->img_transfer->ssm = ssm;
|
self->img_transfer->ssm = ssm;
|
||||||
self->img_transfer->short_is_error = FALSE;
|
self->img_transfer->short_is_error = FALSE;
|
||||||
@@ -1359,11 +1355,6 @@ dev_init (FpImageDevice *dev)
|
|||||||
|
|
||||||
self = FPI_DEVICE_URU4000 (dev);
|
self = FPI_DEVICE_URU4000 (dev);
|
||||||
|
|
||||||
g_clear_pointer (&self->rand, g_rand_free);
|
|
||||||
self->rand = g_rand_new ();
|
|
||||||
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));
|
driver_data = fpi_device_get_driver_data (FP_DEVICE (dev));
|
||||||
self->profile = &uru4k_dev_info[driver_data];
|
self->profile = &uru4k_dev_info[driver_data];
|
||||||
self->interface = g_usb_interface_get_number (iface);
|
self->interface = g_usb_interface_get_number (iface);
|
||||||
@@ -1414,12 +1405,8 @@ dev_deinit (FpImageDevice *dev)
|
|||||||
SECITEM_FreeItem (self->param, PR_TRUE);
|
SECITEM_FreeItem (self->param, PR_TRUE);
|
||||||
if (self->slot)
|
if (self->slot)
|
||||||
PK11_FreeSlot (self->slot);
|
PK11_FreeSlot (self->slot);
|
||||||
|
|
||||||
NSS_Shutdown ();
|
|
||||||
|
|
||||||
g_usb_device_release_interface (fpi_device_get_usb_device (FP_DEVICE (dev)),
|
g_usb_device_release_interface (fpi_device_get_usb_device (FP_DEVICE (dev)),
|
||||||
self->interface, 0, &error);
|
self->interface, 0, &error);
|
||||||
g_clear_pointer (&self->rand, g_rand_free);
|
|
||||||
fpi_image_device_close_complete (dev, error);
|
fpi_image_device_close_complete (dev, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -581,7 +581,7 @@ activate_ssm (FpiSsm *ssm, FpDevice *dev)
|
|||||||
/* Initialize fingerprint buffer */
|
/* Initialize fingerprint buffer */
|
||||||
g_free (self->lines_buffer);
|
g_free (self->lines_buffer);
|
||||||
self->memory = VFS_USB_BUFFER_SIZE;
|
self->memory = VFS_USB_BUFFER_SIZE;
|
||||||
self->lines_buffer = g_malloc0 (self->memory);
|
self->lines_buffer = g_malloc (self->memory);
|
||||||
self->bytes = 0;
|
self->bytes = 0;
|
||||||
|
|
||||||
/* Finger is on the scanner */
|
/* Finger is on the scanner */
|
||||||
@@ -589,15 +589,12 @@ activate_ssm (FpiSsm *ssm, FpDevice *dev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Increase buffer size while it's insufficient */
|
/* 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 <<= 1;
|
||||||
self->memory += VFS_USB_BUFFER_SIZE;
|
|
||||||
self->lines_buffer =
|
self->lines_buffer =
|
||||||
(struct vfs_line *) g_realloc (self->lines_buffer,
|
(struct vfs_line *) g_realloc (self->lines_buffer,
|
||||||
self->memory);
|
self->memory);
|
||||||
memset ((guint8 *) self->lines_buffer + pre_memory, 0,
|
|
||||||
VFS_USB_BUFFER_SIZE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Receive chunk of data */
|
/* Receive chunk of data */
|
||||||
@@ -616,7 +613,7 @@ activate_ssm (FpiSsm *ssm, FpDevice *dev)
|
|||||||
clear_data (self);
|
clear_data (self);
|
||||||
|
|
||||||
/* Wait for probable vdev->active changing */
|
/* Wait for probable vdev->active changing */
|
||||||
fpi_ssm_next_state_delayed (ssm, VFS_SSM_TIMEOUT);
|
fpi_ssm_next_state_delayed (ssm, VFS_SSM_TIMEOUT, NULL);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SSM_NEXT_RECEIVE:
|
case SSM_NEXT_RECEIVE:
|
||||||
@@ -635,7 +632,8 @@ activate_ssm (FpiSsm *ssm, FpDevice *dev)
|
|||||||
|
|
||||||
case SSM_WAIT_ANOTHER_SCAN:
|
case SSM_WAIT_ANOTHER_SCAN:
|
||||||
/* Orange light is on now */
|
/* Orange light is on now */
|
||||||
fpi_ssm_jump_to_state_delayed (ssm, SSM_TURN_ON, VFS_SSM_ORANGE_TIMEOUT);
|
fpi_ssm_jump_to_state_delayed (ssm, SSM_TURN_ON, VFS_SSM_ORANGE_TIMEOUT,
|
||||||
|
NULL);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|||||||
+10
-10
@@ -162,9 +162,9 @@ enum {
|
|||||||
|
|
||||||
/* Dump buffer for debug */
|
/* Dump buffer for debug */
|
||||||
#define dump_buffer(buf) \
|
#define dump_buffer(buf) \
|
||||||
fp_dbg ("%02x %02x %02x %02x %02x %02x %02x %02x", \
|
fp_dbg ("%02x %02x %02x %02x %02x %02x %02x %02x", \
|
||||||
buf[6], buf[7], buf[8], buf[9], buf[10], buf[11], buf[12], buf[13] \
|
buf[6], buf[7], buf[8], buf[9], buf[10], buf[11], buf[12], buf[13] \
|
||||||
)
|
)
|
||||||
|
|
||||||
/* Callback of asynchronous send */
|
/* Callback of asynchronous send */
|
||||||
static void
|
static void
|
||||||
@@ -785,7 +785,7 @@ m_loop_state (FpiSsm *ssm, FpDevice *_dev)
|
|||||||
|
|
||||||
case M_LOOP_0_SLEEP:
|
case M_LOOP_0_SLEEP:
|
||||||
/* Wait fingerprint scanning */
|
/* Wait fingerprint scanning */
|
||||||
fpi_ssm_next_state_delayed (ssm, 50);
|
fpi_ssm_next_state_delayed (ssm, 50, NULL);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case M_LOOP_0_GET_STATE:
|
case M_LOOP_0_GET_STATE:
|
||||||
@@ -828,7 +828,7 @@ m_loop_state (FpiSsm *ssm, FpDevice *_dev)
|
|||||||
img_extract (ssm, dev);
|
img_extract (ssm, dev);
|
||||||
|
|
||||||
/* Wait handling image */
|
/* Wait handling image */
|
||||||
fpi_ssm_next_state_delayed (ssm, 10);
|
fpi_ssm_next_state_delayed (ssm, 10, NULL);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case M_LOOP_0_CHECK_ACTION:
|
case M_LOOP_0_CHECK_ACTION:
|
||||||
@@ -851,7 +851,7 @@ m_loop_state (FpiSsm *ssm, FpDevice *_dev)
|
|||||||
if (vfs_finger_state (self) == VFS_FINGER_PRESENT)
|
if (vfs_finger_state (self) == VFS_FINGER_PRESENT)
|
||||||
{
|
{
|
||||||
fpi_image_device_report_finger_status (dev, TRUE);
|
fpi_image_device_report_finger_status (dev, TRUE);
|
||||||
fpi_ssm_next_state_delayed (ssm, 250);
|
fpi_ssm_next_state_delayed (ssm, 250, NULL);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -881,7 +881,7 @@ m_loop_state (FpiSsm *ssm, FpDevice *_dev)
|
|||||||
|
|
||||||
case M_LOOP_1_SLEEP:
|
case M_LOOP_1_SLEEP:
|
||||||
/* Wait fingerprint scanning */
|
/* Wait fingerprint scanning */
|
||||||
fpi_ssm_next_state_delayed (ssm, 10);
|
fpi_ssm_next_state_delayed (ssm, 10, NULL);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case M_LOOP_2_ABORT_PRINT:
|
case M_LOOP_2_ABORT_PRINT:
|
||||||
@@ -917,7 +917,7 @@ m_loop_state (FpiSsm *ssm, FpDevice *_dev)
|
|||||||
{
|
{
|
||||||
/* Wait aborting */
|
/* Wait aborting */
|
||||||
self->counter++;
|
self->counter++;
|
||||||
fpi_ssm_next_state_delayed (ssm, 100);
|
fpi_ssm_next_state_delayed (ssm, 100, NULL);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -1055,7 +1055,7 @@ m_init_state (FpiSsm *ssm, FpDevice *_dev)
|
|||||||
{
|
{
|
||||||
/* Wait aborting */
|
/* Wait aborting */
|
||||||
self->counter++;
|
self->counter++;
|
||||||
fpi_ssm_next_state_delayed (ssm, 100);
|
fpi_ssm_next_state_delayed (ssm, 100, NULL);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -1084,7 +1084,7 @@ m_init_state (FpiSsm *ssm, FpDevice *_dev)
|
|||||||
{
|
{
|
||||||
/* Wait removing finger */
|
/* Wait removing finger */
|
||||||
self->counter++;
|
self->counter++;
|
||||||
fpi_ssm_next_state_delayed (ssm, 250);
|
fpi_ssm_next_state_delayed (ssm, 250, NULL);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -97,7 +97,7 @@ m_loop_state (FpiSsm *ssm, FpDevice *_dev)
|
|||||||
|
|
||||||
case M_WAIT_PRINT:
|
case M_WAIT_PRINT:
|
||||||
/* Wait fingerprint scanning */
|
/* Wait fingerprint scanning */
|
||||||
fpi_ssm_next_state_delayed (ssm, 200);
|
fpi_ssm_next_state_delayed (ssm, 200, NULL);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case M_CHECK_PRINT:
|
case M_CHECK_PRINT:
|
||||||
@@ -115,7 +115,7 @@ m_loop_state (FpiSsm *ssm, FpDevice *_dev)
|
|||||||
|
|
||||||
case M_READ_PRINT_WAIT:
|
case M_READ_PRINT_WAIT:
|
||||||
/* Wait fingerprint scanning */
|
/* Wait fingerprint scanning */
|
||||||
fpi_ssm_next_state_delayed (ssm, 200);
|
fpi_ssm_next_state_delayed (ssm, 200, NULL);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case M_READ_PRINT_POLL:
|
case M_READ_PRINT_POLL:
|
||||||
|
|||||||
@@ -157,7 +157,7 @@ vfs301_proto_generate_0B (int subtype, gssize *len)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#define HEX_TO_INT(c) \
|
#define HEX_TO_INT(c) \
|
||||||
(((c) >= '0' && (c) <= '9') ? ((c) - '0') : ((c) - 'A' + 10))
|
(((c) >= '0' && (c) <= '9') ? ((c) - '0') : ((c) - 'A' + 10))
|
||||||
|
|
||||||
static guint8 *
|
static guint8 *
|
||||||
translate_str (const char **srcL, gssize *len)
|
translate_str (const char **srcL, gssize *len)
|
||||||
@@ -422,17 +422,17 @@ img_process_data (int first_block, FpDeviceVfs301 *dev, const guint8 *buf, int l
|
|||||||
/************************** PROTOCOL STUFF ************************************/
|
/************************** PROTOCOL STUFF ************************************/
|
||||||
|
|
||||||
#define USB_RECV(from, len) \
|
#define USB_RECV(from, len) \
|
||||||
usb_recv (dev, from, len, NULL, NULL)
|
usb_recv (dev, from, len, NULL, NULL)
|
||||||
|
|
||||||
#define USB_SEND(type, subtype) \
|
#define USB_SEND(type, subtype) \
|
||||||
{ \
|
{ \
|
||||||
const guint8 *data; \
|
const guint8 *data; \
|
||||||
gssize len; \
|
gssize len; \
|
||||||
data = vfs301_proto_generate (type, subtype, &len); \
|
data = vfs301_proto_generate (type, subtype, &len); \
|
||||||
usb_send (dev, data, len, NULL); \
|
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))
|
#define IS_VFS301_FP_SEQ_START(b) ((b[0] == 0x01) && (b[1] == 0xfe))
|
||||||
|
|
||||||
@@ -465,7 +465,7 @@ int
|
|||||||
vfs301_proto_peek_event (FpDeviceVfs301 *dev)
|
vfs301_proto_peek_event (FpDeviceVfs301 *dev)
|
||||||
{
|
{
|
||||||
g_autoptr(GError) error = NULL;
|
g_autoptr(GError) error = NULL;
|
||||||
g_autoptr(FpiUsbTransfer) transfer = NULL;
|
FpiUsbTransfer *transfer;
|
||||||
|
|
||||||
const char no_event[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
const char no_event[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||||
const char got_event[] = {0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00};
|
const char got_event[] = {0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00};
|
||||||
@@ -489,13 +489,13 @@ vfs301_proto_peek_event (FpDeviceVfs301 *dev)
|
|||||||
* we will run into timeouts randomly and need to then try again.
|
* we will run into timeouts randomly and need to then try again.
|
||||||
*/
|
*/
|
||||||
#define PARALLEL_RECEIVE(e1, l1, e2, l2) \
|
#define PARALLEL_RECEIVE(e1, l1, e2, l2) \
|
||||||
{ \
|
{ \
|
||||||
g_autoptr(GError) error = NULL; \
|
g_autoptr(GError) error = NULL; \
|
||||||
usb_recv (dev, e1, l1, NULL, &error); \
|
usb_recv (dev, e1, l1, NULL, &error); \
|
||||||
usb_recv (dev, e2, l2, NULL, NULL); \
|
usb_recv (dev, e2, l2, NULL, NULL); \
|
||||||
if (g_error_matches (error, G_USB_DEVICE_ERROR, G_USB_DEVICE_ERROR_TIMED_OUT)) \
|
if (g_error_matches (error, G_USB_DEVICE_ERROR, G_USB_DEVICE_ERROR_TIMED_OUT)) \
|
||||||
usb_recv (dev, e1, l1, NULL, NULL); \
|
usb_recv (dev, e1, l1, NULL, NULL); \
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
vfs301_proto_process_event_cb (FpiUsbTransfer *transfer,
|
vfs301_proto_process_event_cb (FpiUsbTransfer *transfer,
|
||||||
|
|||||||
+21
-22
@@ -41,30 +41,30 @@ struct usb_action
|
|||||||
};
|
};
|
||||||
|
|
||||||
#define SEND(ENDPOINT, COMMAND) \
|
#define SEND(ENDPOINT, COMMAND) \
|
||||||
{ \
|
{ \
|
||||||
.type = ACTION_SEND, \
|
.type = ACTION_SEND, \
|
||||||
.endpoint = ENDPOINT, \
|
.endpoint = ENDPOINT, \
|
||||||
.name = #COMMAND, \
|
.name = #COMMAND, \
|
||||||
.size = sizeof (COMMAND), \
|
.size = sizeof (COMMAND), \
|
||||||
.data = COMMAND \
|
.data = COMMAND \
|
||||||
},
|
},
|
||||||
|
|
||||||
#define RECV(ENDPOINT, SIZE) \
|
#define RECV(ENDPOINT, SIZE) \
|
||||||
{ \
|
{ \
|
||||||
.type = ACTION_RECEIVE, \
|
.type = ACTION_RECEIVE, \
|
||||||
.endpoint = ENDPOINT, \
|
.endpoint = ENDPOINT, \
|
||||||
.size = SIZE, \
|
.size = SIZE, \
|
||||||
.data = NULL \
|
.data = NULL \
|
||||||
},
|
},
|
||||||
|
|
||||||
#define RECV_CHECK(ENDPOINT, SIZE, EXPECTED) \
|
#define RECV_CHECK(ENDPOINT, SIZE, EXPECTED) \
|
||||||
{ \
|
{ \
|
||||||
.type = ACTION_RECEIVE, \
|
.type = ACTION_RECEIVE, \
|
||||||
.endpoint = ENDPOINT, \
|
.endpoint = ENDPOINT, \
|
||||||
.size = SIZE, \
|
.size = SIZE, \
|
||||||
.data = EXPECTED, \
|
.data = EXPECTED, \
|
||||||
.correct_reply_size = sizeof (EXPECTED) \
|
.correct_reply_size = sizeof (EXPECTED) \
|
||||||
},
|
},
|
||||||
|
|
||||||
struct usbexchange_data
|
struct usbexchange_data
|
||||||
{
|
{
|
||||||
@@ -196,7 +196,6 @@ usb_exchange_async (FpiSsm *ssm,
|
|||||||
FpiSsm *subsm = fpi_ssm_new_full (FP_DEVICE (data->device),
|
FpiSsm *subsm = fpi_ssm_new_full (FP_DEVICE (data->device),
|
||||||
usbexchange_loop,
|
usbexchange_loop,
|
||||||
data->stepcount,
|
data->stepcount,
|
||||||
data->stepcount,
|
|
||||||
exchange_name);
|
exchange_name);
|
||||||
|
|
||||||
fpi_ssm_set_data (subsm, data, NULL);
|
fpi_ssm_set_data (subsm, data, NULL);
|
||||||
@@ -706,7 +705,7 @@ activate_loop (FpiSsm *ssm, FpDevice *_dev)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case DEV_ACTIVATE_DATA_COMPLETE:
|
case DEV_ACTIVATE_DATA_COMPLETE:
|
||||||
fpi_ssm_next_state_delayed (ssm, 1);
|
fpi_ssm_next_state_delayed (ssm, 1, NULL);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DEV_ACTIVATE_PREPARE_NEXT_CAPTURE:
|
case DEV_ACTIVATE_PREPARE_NEXT_CAPTURE:
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -28,35 +28,35 @@
|
|||||||
|
|
||||||
#include "virtual-device-private.h"
|
#include "virtual-device-private.h"
|
||||||
|
|
||||||
struct _FpiDeviceVirtualListener
|
struct _FpDeviceVirtualListener
|
||||||
{
|
{
|
||||||
GSocketListener parent_instance;
|
GSocketListener parent_instance;
|
||||||
|
|
||||||
GSocketConnection *connection;
|
GSocketConnection *connection;
|
||||||
GCancellable *cancellable;
|
GCancellable *cancellable;
|
||||||
guint cancellable_id;
|
guint cancellable_id;
|
||||||
|
|
||||||
FpiDeviceVirtualListenerConnectionCb ready_cb;
|
FpDeviceVirtualListenerConnectionCb ready_cb;
|
||||||
gpointer ready_cb_data;
|
gpointer ready_cb_data;
|
||||||
|
|
||||||
gint socket_fd;
|
gint socket_fd;
|
||||||
gint client_fd;
|
gint client_fd;
|
||||||
};
|
};
|
||||||
|
|
||||||
G_DEFINE_TYPE (FpiDeviceVirtualListener, fpi_device_virtual_listener, G_TYPE_SOCKET_LISTENER)
|
G_DEFINE_TYPE (FpDeviceVirtualListener, fp_device_virtual_listener, G_TYPE_SOCKET_LISTENER)
|
||||||
|
|
||||||
static void start_listen (FpiDeviceVirtualListener *self);
|
static void start_listen (FpDeviceVirtualListener *self);
|
||||||
|
|
||||||
FpiDeviceVirtualListener *
|
FpDeviceVirtualListener *
|
||||||
fpi_device_virtual_listener_new (void)
|
fp_device_virtual_listener_new (void)
|
||||||
{
|
{
|
||||||
return g_object_new (fpi_device_virtual_listener_get_type (), NULL);
|
return g_object_new (fp_device_virtual_listener_get_type (), NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
fpi_device_virtual_listener_dispose (GObject *object)
|
fp_device_virtual_listener_dispose (GObject *object)
|
||||||
{
|
{
|
||||||
FpiDeviceVirtualListener *self = FPI_DEVICE_VIRTUAL_LISTENER (object);
|
FpDeviceVirtualListener *self = FP_DEVICE_VIRTUAL_LISTENER (object);
|
||||||
|
|
||||||
if (self->cancellable_id)
|
if (self->cancellable_id)
|
||||||
{
|
{
|
||||||
@@ -70,19 +70,19 @@ fpi_device_virtual_listener_dispose (GObject *object)
|
|||||||
|
|
||||||
self->ready_cb = NULL;
|
self->ready_cb = NULL;
|
||||||
|
|
||||||
G_OBJECT_CLASS (fpi_device_virtual_listener_parent_class)->dispose (object);
|
G_OBJECT_CLASS (fp_device_virtual_listener_parent_class)->dispose (object);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
fpi_device_virtual_listener_class_init (FpiDeviceVirtualListenerClass *klass)
|
fp_device_virtual_listener_class_init (FpDeviceVirtualListenerClass *klass)
|
||||||
{
|
{
|
||||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||||
|
|
||||||
object_class->dispose = fpi_device_virtual_listener_dispose;
|
object_class->dispose = fp_device_virtual_listener_dispose;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
fpi_device_virtual_listener_init (FpiDeviceVirtualListener *self)
|
fp_device_virtual_listener_init (FpDeviceVirtualListener *self)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -90,7 +90,7 @@ static void
|
|||||||
new_connection_cb (GObject *source_object, GAsyncResult *res, gpointer user_data)
|
new_connection_cb (GObject *source_object, GAsyncResult *res, gpointer user_data)
|
||||||
{
|
{
|
||||||
g_autoptr(GError) error = NULL;
|
g_autoptr(GError) error = NULL;
|
||||||
FpiDeviceVirtualListener *self = user_data;
|
FpDeviceVirtualListener *self = user_data;
|
||||||
GSocketConnection *connection;
|
GSocketConnection *connection;
|
||||||
|
|
||||||
connection = g_socket_listener_accept_finish (G_SOCKET_LISTENER (source_object),
|
connection = g_socket_listener_accept_finish (G_SOCKET_LISTENER (source_object),
|
||||||
@@ -123,7 +123,7 @@ new_connection_cb (GObject *source_object, GAsyncResult *res, gpointer user_data
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
start_listen (FpiDeviceVirtualListener *self)
|
start_listen (FpDeviceVirtualListener *self)
|
||||||
{
|
{
|
||||||
g_socket_listener_accept_async (G_SOCKET_LISTENER (self),
|
g_socket_listener_accept_async (G_SOCKET_LISTENER (self),
|
||||||
self->cancellable,
|
self->cancellable,
|
||||||
@@ -132,27 +132,27 @@ start_listen (FpiDeviceVirtualListener *self)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
on_cancelled (GCancellable *cancellable,
|
on_cancelled (GCancellable *cancellable,
|
||||||
FpiDeviceVirtualListener *self)
|
FpDeviceVirtualListener *self)
|
||||||
{
|
{
|
||||||
fpi_device_virtual_listener_connection_close (self);
|
fp_device_virtual_listener_connection_close (self);
|
||||||
g_socket_listener_close (G_SOCKET_LISTENER (self));
|
g_socket_listener_close (G_SOCKET_LISTENER (self));
|
||||||
g_clear_object (&self->cancellable);
|
g_clear_object (&self->cancellable);
|
||||||
self->ready_cb = NULL;
|
self->ready_cb = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
fpi_device_virtual_listener_start (FpiDeviceVirtualListener *self,
|
fp_device_virtual_listener_start (FpDeviceVirtualListener *self,
|
||||||
const char *address,
|
const char *address,
|
||||||
GCancellable *cancellable,
|
GCancellable *cancellable,
|
||||||
FpiDeviceVirtualListenerConnectionCb cb,
|
FpDeviceVirtualListenerConnectionCb cb,
|
||||||
gpointer user_data,
|
gpointer user_data,
|
||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
g_autoptr(GSocketAddress) addr = NULL;
|
g_autoptr(GSocketAddress) addr = NULL;
|
||||||
G_DEBUG_HERE ();
|
G_DEBUG_HERE ();
|
||||||
|
|
||||||
g_return_val_if_fail (FPI_IS_DEVICE_VIRTUAL_LISTENER (self), FALSE);
|
g_return_val_if_fail (FP_IS_DEVICE_VIRTUAL_LISTENER (self), FALSE);
|
||||||
g_return_val_if_fail (cb != NULL, FALSE);
|
g_return_val_if_fail (cb != NULL, FALSE);
|
||||||
g_return_val_if_fail (self->ready_cb == NULL, FALSE);
|
g_return_val_if_fail (self->ready_cb == NULL, FALSE);
|
||||||
|
|
||||||
@@ -191,9 +191,9 @@ fpi_device_virtual_listener_start (FpiDeviceVirtualListener *self,
|
|||||||
}
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
fpi_device_virtual_listener_connection_close (FpiDeviceVirtualListener *self)
|
fp_device_virtual_listener_connection_close (FpDeviceVirtualListener *self)
|
||||||
{
|
{
|
||||||
g_return_val_if_fail (FPI_IS_DEVICE_VIRTUAL_LISTENER (self), FALSE);
|
g_return_val_if_fail (FP_IS_DEVICE_VIRTUAL_LISTENER (self), FALSE);
|
||||||
|
|
||||||
if (!self->connection)
|
if (!self->connection)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
@@ -211,7 +211,7 @@ on_stream_read_cb (GObject *source_object,
|
|||||||
{
|
{
|
||||||
g_autoptr(GError) error = NULL;
|
g_autoptr(GError) error = NULL;
|
||||||
g_autoptr(GTask) task = user_data;
|
g_autoptr(GTask) task = user_data;
|
||||||
FpiDeviceVirtualListener *self = g_task_get_source_object (task);
|
FpDeviceVirtualListener *self = g_task_get_source_object (task);
|
||||||
gboolean all;
|
gboolean all;
|
||||||
gboolean success;
|
gboolean success;
|
||||||
gsize bytes;
|
gsize bytes;
|
||||||
@@ -273,8 +273,7 @@ on_stream_read_cb (GObject *source_object,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_INVALID_DATA,
|
// g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_INVALID_DATA, "Got empty data");
|
||||||
"Got empty data");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -283,17 +282,17 @@ on_stream_read_cb (GObject *source_object,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
fpi_device_virtual_listener_read (FpiDeviceVirtualListener *self,
|
fp_device_virtual_listener_read (FpDeviceVirtualListener *self,
|
||||||
gboolean all,
|
gboolean all,
|
||||||
void *buffer,
|
void *buffer,
|
||||||
gsize count,
|
gsize count,
|
||||||
GAsyncReadyCallback callback,
|
GAsyncReadyCallback callback,
|
||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
g_autoptr(GTask) task = NULL;
|
g_autoptr(GTask) task = NULL;
|
||||||
GInputStream *stream;
|
GInputStream *stream;
|
||||||
|
|
||||||
g_return_if_fail (FPI_IS_DEVICE_VIRTUAL_LISTENER (self));
|
g_return_if_fail (FP_IS_DEVICE_VIRTUAL_LISTENER (self));
|
||||||
|
|
||||||
task = g_task_new (self, self->cancellable, callback, user_data);
|
task = g_task_new (self, self->cancellable, callback, user_data);
|
||||||
g_object_set_data (G_OBJECT (task), "all", GINT_TO_POINTER (all));
|
g_object_set_data (G_OBJECT (task), "all", GINT_TO_POINTER (all));
|
||||||
@@ -325,9 +324,9 @@ fpi_device_virtual_listener_read (FpiDeviceVirtualListener *self,
|
|||||||
}
|
}
|
||||||
|
|
||||||
gsize
|
gsize
|
||||||
fpi_device_virtual_listener_read_finish (FpiDeviceVirtualListener *self,
|
fp_device_virtual_listener_read_finish (FpDeviceVirtualListener *self,
|
||||||
GAsyncResult *result,
|
GAsyncResult *result,
|
||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
g_return_val_if_fail (g_task_is_valid (result, self), 0);
|
g_return_val_if_fail (g_task_is_valid (result, self), 0);
|
||||||
|
|
||||||
@@ -335,10 +334,10 @@ fpi_device_virtual_listener_read_finish (FpiDeviceVirtualListener *self,
|
|||||||
}
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
fpi_device_virtual_listener_write_sync (FpiDeviceVirtualListener *self,
|
fp_device_virtual_listener_write_sync (FpDeviceVirtualListener *self,
|
||||||
const char *buffer,
|
const char *buffer,
|
||||||
gsize count,
|
gsize count,
|
||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
if (!self->connection || g_io_stream_is_closed (G_IO_STREAM (self->connection)))
|
if (!self->connection || g_io_stream_is_closed (G_IO_STREAM (self->connection)))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -32,59 +32,59 @@
|
|||||||
|
|
||||||
#define MAX_LINE_LEN 1024
|
#define MAX_LINE_LEN 1024
|
||||||
|
|
||||||
G_DECLARE_FINAL_TYPE (FpiDeviceVirtualListener, fpi_device_virtual_listener, FPI, DEVICE_VIRTUAL_LISTENER, GSocketListener)
|
G_DECLARE_FINAL_TYPE (FpDeviceVirtualListener, fp_device_virtual_listener, FP, DEVICE_VIRTUAL_LISTENER, GSocketListener)
|
||||||
|
|
||||||
typedef void (*FpiDeviceVirtualListenerConnectionCb) (FpiDeviceVirtualListener *listener,
|
typedef void (*FpDeviceVirtualListenerConnectionCb) (FpDeviceVirtualListener *listener,
|
||||||
gpointer user_data);
|
gpointer user_data);
|
||||||
|
|
||||||
FpiDeviceVirtualListener * fpi_device_virtual_listener_new (void);
|
FpDeviceVirtualListener * fp_device_virtual_listener_new (void);
|
||||||
|
|
||||||
gboolean fpi_device_virtual_listener_start (FpiDeviceVirtualListener *listener,
|
gboolean fp_device_virtual_listener_start (FpDeviceVirtualListener *listener,
|
||||||
const char *address,
|
const char *address,
|
||||||
GCancellable *cancellable,
|
GCancellable *cancellable,
|
||||||
FpiDeviceVirtualListenerConnectionCb cb,
|
FpDeviceVirtualListenerConnectionCb cb,
|
||||||
gpointer user_data,
|
gpointer user_data,
|
||||||
GError **error);
|
GError **error);
|
||||||
|
|
||||||
gboolean fpi_device_virtual_listener_connection_close (FpiDeviceVirtualListener *listener);
|
gboolean fp_device_virtual_listener_connection_close (FpDeviceVirtualListener *listener);
|
||||||
|
|
||||||
void fpi_device_virtual_listener_read (FpiDeviceVirtualListener *listener,
|
void fp_device_virtual_listener_read (FpDeviceVirtualListener *listener,
|
||||||
gboolean all,
|
gboolean all,
|
||||||
void *buffer,
|
void *buffer,
|
||||||
gsize count,
|
gsize count,
|
||||||
GAsyncReadyCallback callback,
|
GAsyncReadyCallback callback,
|
||||||
gpointer user_data);
|
gpointer user_data);
|
||||||
gsize fpi_device_virtual_listener_read_finish (FpiDeviceVirtualListener *listener,
|
gsize fp_device_virtual_listener_read_finish (FpDeviceVirtualListener *listener,
|
||||||
GAsyncResult *result,
|
GAsyncResult *result,
|
||||||
GError **error);
|
GError **error);
|
||||||
|
|
||||||
gboolean fpi_device_virtual_listener_write_sync (FpiDeviceVirtualListener *self,
|
gboolean fp_device_virtual_listener_write_sync (FpDeviceVirtualListener *self,
|
||||||
const char *buffer,
|
const char *buffer,
|
||||||
gsize count,
|
gsize count,
|
||||||
GError **error);
|
GError **error);
|
||||||
|
|
||||||
|
|
||||||
struct _FpDeviceVirtualDevice
|
struct _FpDeviceVirtualDevice
|
||||||
{
|
{
|
||||||
FpDevice parent;
|
FpDevice parent;
|
||||||
|
|
||||||
FpiDeviceVirtualListener *listener;
|
FpDeviceVirtualListener *listener;
|
||||||
GCancellable *cancellable;
|
GCancellable *cancellable;
|
||||||
|
|
||||||
char recv_buf[MAX_LINE_LEN];
|
char recv_buf[MAX_LINE_LEN];
|
||||||
|
|
||||||
GPtrArray *pending_commands;
|
GPtrArray *pending_commands;
|
||||||
|
|
||||||
GHashTable *prints_storage;
|
GHashTable *prints_storage;
|
||||||
|
|
||||||
guint wait_command_id;
|
guint wait_command_id;
|
||||||
guint sleep_timeout_id;
|
guint sleep_timeout_id;
|
||||||
guint enroll_stages_passed;
|
guint enroll_stages_passed;
|
||||||
gboolean match_reported;
|
gboolean match_reported;
|
||||||
gboolean supports_cancellation;
|
gboolean supports_cancellation;
|
||||||
gboolean injected_synthetic_cmd;
|
gboolean injected_synthetic_cmd;
|
||||||
gboolean ignore_wait;
|
gboolean ignore_wait;
|
||||||
gboolean keep_alive;
|
gboolean keep_alive;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Not really final here, but we can do this to share the FpDeviceVirtualDevice
|
/* Not really final here, but we can do this to share the FpDeviceVirtualDevice
|
||||||
@@ -99,13 +99,11 @@ struct _FpDeviceVirtualDeviceStorage
|
|||||||
G_DECLARE_FINAL_TYPE (FpDeviceVirtualDeviceStorage, fpi_device_virtual_device_storage, FP, DEVICE_VIRTUAL_DEVICE_STORAGE, FpDeviceVirtualDevice)
|
G_DECLARE_FINAL_TYPE (FpDeviceVirtualDeviceStorage, fpi_device_virtual_device_storage, FP, DEVICE_VIRTUAL_DEVICE_STORAGE, FpDeviceVirtualDevice)
|
||||||
|
|
||||||
|
|
||||||
gboolean process_cmds (FpDeviceVirtualDevice * self,
|
char * process_cmds (FpDeviceVirtualDevice * self, gboolean scan, GError **error);
|
||||||
gboolean scan,
|
char * start_scan_command (FpDeviceVirtualDevice *self,
|
||||||
char **scan_id,
|
GError **error);
|
||||||
GError **error);
|
gboolean should_wait_for_command (FpDeviceVirtualDevice *self,
|
||||||
gboolean start_scan_command (FpDeviceVirtualDevice *self,
|
GError *error);
|
||||||
char **scan_id,
|
|
||||||
GError **error);
|
|
||||||
gboolean should_wait_to_sleep (FpDeviceVirtualDevice *self,
|
gboolean should_wait_to_sleep (FpDeviceVirtualDevice *self,
|
||||||
const char *scan_id,
|
const char *scan_id,
|
||||||
GError *error);
|
GError *error);
|
||||||
|
|||||||
@@ -42,7 +42,8 @@ dev_identify (FpDevice *dev)
|
|||||||
FpDeviceVirtualDevice *self = FP_DEVICE_VIRTUAL_DEVICE (dev);
|
FpDeviceVirtualDevice *self = FP_DEVICE_VIRTUAL_DEVICE (dev);
|
||||||
g_autofree char *scan_id = NULL;
|
g_autofree char *scan_id = NULL;
|
||||||
|
|
||||||
if (!start_scan_command (self, &scan_id, &error))
|
scan_id = start_scan_command (self, &error);
|
||||||
|
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_PENDING))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (scan_id)
|
if (scan_id)
|
||||||
@@ -67,17 +68,12 @@ dev_identify (FpDevice *dev)
|
|||||||
new_scan,
|
new_scan,
|
||||||
(GEqualFunc) fp_print_equal,
|
(GEqualFunc) fp_print_equal,
|
||||||
NULL))
|
NULL))
|
||||||
{
|
error = fpi_device_error_new (FP_DEVICE_ERROR_DATA_NOT_FOUND);
|
||||||
match = FALSE;
|
|
||||||
g_clear_object (&new_scan);
|
|
||||||
}
|
|
||||||
else if (g_ptr_array_find_with_equal_func (prints,
|
else if (g_ptr_array_find_with_equal_func (prints,
|
||||||
new_scan,
|
new_scan,
|
||||||
(GEqualFunc) fp_print_equal,
|
(GEqualFunc) fp_print_equal,
|
||||||
&idx))
|
&idx))
|
||||||
{
|
match = g_ptr_array_index (prints, idx);
|
||||||
match = g_ptr_array_index (prints, idx);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!self->match_reported)
|
if (!self->match_reported)
|
||||||
{
|
{
|
||||||
@@ -151,10 +147,11 @@ dev_list (FpDevice *dev)
|
|||||||
g_autoptr(GError) error = NULL;
|
g_autoptr(GError) error = NULL;
|
||||||
FpDeviceVirtualDevice *vdev = FP_DEVICE_VIRTUAL_DEVICE (dev);
|
FpDeviceVirtualDevice *vdev = FP_DEVICE_VIRTUAL_DEVICE (dev);
|
||||||
|
|
||||||
if (!process_cmds (vdev, FALSE, NULL, &error))
|
process_cmds (vdev, FALSE, &error);
|
||||||
|
if (should_wait_for_command (vdev, error))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (error)
|
if (error && !g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
|
||||||
{
|
{
|
||||||
fpi_device_list_complete (dev, NULL, g_steal_pointer (&error));
|
fpi_device_list_complete (dev, NULL, g_steal_pointer (&error));
|
||||||
return;
|
return;
|
||||||
@@ -163,27 +160,6 @@ dev_list (FpDevice *dev)
|
|||||||
fpi_device_list_complete (dev, get_stored_prints (vdev), NULL);
|
fpi_device_list_complete (dev, get_stored_prints (vdev), NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
dev_clear_storage (FpDevice *dev)
|
|
||||||
{
|
|
||||||
g_autoptr(GPtrArray) prints_list = NULL;
|
|
||||||
g_autoptr(GError) error = NULL;
|
|
||||||
FpDeviceVirtualDevice *vdev = FP_DEVICE_VIRTUAL_DEVICE (dev);
|
|
||||||
|
|
||||||
if (!process_cmds (vdev, FALSE, NULL, &error))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (error)
|
|
||||||
{
|
|
||||||
fpi_device_clear_storage_complete (dev, g_steal_pointer (&error));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
g_hash_table_remove_all (vdev->prints_storage);
|
|
||||||
|
|
||||||
fpi_device_clear_storage_complete (dev, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
dev_delete (FpDevice *dev)
|
dev_delete (FpDevice *dev)
|
||||||
{
|
{
|
||||||
@@ -193,10 +169,11 @@ dev_delete (FpDevice *dev)
|
|||||||
FpPrint *print = NULL;
|
FpPrint *print = NULL;
|
||||||
const char *id = NULL;
|
const char *id = NULL;
|
||||||
|
|
||||||
if (!process_cmds (vdev, FALSE, NULL, &error))
|
process_cmds (vdev, FALSE, &error);
|
||||||
|
if (should_wait_for_command (vdev, error))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (error)
|
if (error && !g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
|
||||||
{
|
{
|
||||||
fpi_device_delete_complete (dev, g_steal_pointer (&error));
|
fpi_device_delete_complete (dev, g_steal_pointer (&error));
|
||||||
return;
|
return;
|
||||||
@@ -225,15 +202,6 @@ dev_delete (FpDevice *dev)
|
|||||||
fpi_device_error_new (FP_DEVICE_ERROR_DATA_NOT_FOUND));
|
fpi_device_error_new (FP_DEVICE_ERROR_DATA_NOT_FOUND));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
dev_probe (FpDevice *dev)
|
|
||||||
{
|
|
||||||
/* Disable features listed in driver_data */
|
|
||||||
fpi_device_update_features (dev, fpi_device_get_driver_data (dev), 0);
|
|
||||||
|
|
||||||
fpi_device_probe_complete (dev, NULL, NULL, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
fpi_device_virtual_device_storage_init (FpDeviceVirtualDeviceStorage *self)
|
fpi_device_virtual_device_storage_init (FpDeviceVirtualDeviceStorage *self)
|
||||||
{
|
{
|
||||||
@@ -256,8 +224,8 @@ fpi_device_virtual_device_storage_finalize (GObject *object)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static const FpIdEntry driver_ids[] = {
|
static const FpIdEntry driver_ids[] = {
|
||||||
{ .virtual_envvar = "FP_VIRTUAL_DEVICE_STORAGE", .driver_data = 0 },
|
{ .virtual_envvar = "FP_VIRTUAL_DEVICE_STORAGE" },
|
||||||
{ .virtual_envvar = "FP_VIRTUAL_DEVICE_STORAGE_NO_LIST", .driver_data = FP_DEVICE_FEATURE_STORAGE_LIST },
|
{ .virtual_envvar = "FP_VIRTUAL_DEVICE_IDENT" },
|
||||||
{ .virtual_envvar = NULL }
|
{ .virtual_envvar = NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -273,12 +241,7 @@ fpi_device_virtual_device_storage_class_init (FpDeviceVirtualDeviceStorageClass
|
|||||||
dev_class->full_name = "Virtual device with storage and identification for debugging";
|
dev_class->full_name = "Virtual device with storage and identification for debugging";
|
||||||
dev_class->id_table = driver_ids;
|
dev_class->id_table = driver_ids;
|
||||||
|
|
||||||
dev_class->probe = dev_probe;
|
|
||||||
dev_class->identify = dev_identify;
|
dev_class->identify = dev_identify;
|
||||||
dev_class->list = dev_list;
|
dev_class->list = dev_list;
|
||||||
dev_class->delete = dev_delete;
|
dev_class->delete = dev_delete;
|
||||||
dev_class->clear_storage = dev_clear_storage;
|
|
||||||
|
|
||||||
fpi_device_class_auto_initialize_features (dev_class);
|
|
||||||
dev_class->features |= FP_DEVICE_FEATURE_DUPLICATES_CHECK;
|
|
||||||
}
|
}
|
||||||
|
|||||||
+125
-137
@@ -37,7 +37,6 @@ G_DEFINE_TYPE (FpDeviceVirtualDevice, fpi_device_virtual_device, FP_TYPE_DEVICE)
|
|||||||
#define INSERT_CMD_PREFIX "INSERT "
|
#define INSERT_CMD_PREFIX "INSERT "
|
||||||
#define REMOVE_CMD_PREFIX "REMOVE "
|
#define REMOVE_CMD_PREFIX "REMOVE "
|
||||||
#define SCAN_CMD_PREFIX "SCAN "
|
#define SCAN_CMD_PREFIX "SCAN "
|
||||||
#define CONT_CMD_PREFIX "CONT "
|
|
||||||
#define ERROR_CMD_PREFIX "ERROR "
|
#define ERROR_CMD_PREFIX "ERROR "
|
||||||
#define RETRY_CMD_PREFIX "RETRY "
|
#define RETRY_CMD_PREFIX "RETRY "
|
||||||
#define FINGER_CMD_PREFIX "FINGER "
|
#define FINGER_CMD_PREFIX "FINGER "
|
||||||
@@ -58,8 +57,6 @@ maybe_continue_current_action (FpDeviceVirtualDevice *self)
|
|||||||
if (self->sleep_timeout_id)
|
if (self->sleep_timeout_id)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
g_assert (self->wait_command_id == 0);
|
|
||||||
|
|
||||||
switch (fpi_device_get_current_action (dev))
|
switch (fpi_device_get_current_action (dev))
|
||||||
{
|
{
|
||||||
case FPI_DEVICE_ACTION_ENROLL:
|
case FPI_DEVICE_ACTION_ENROLL:
|
||||||
@@ -90,14 +87,6 @@ maybe_continue_current_action (FpDeviceVirtualDevice *self)
|
|||||||
FP_DEVICE_GET_CLASS (self)->close (dev);
|
FP_DEVICE_GET_CLASS (self)->close (dev);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FPI_DEVICE_ACTION_CLEAR_STORAGE:
|
|
||||||
FP_DEVICE_GET_CLASS (self)->clear_storage (dev);
|
|
||||||
break;
|
|
||||||
|
|
||||||
/* Not implemented/nothing to do. */
|
|
||||||
case FPI_DEVICE_ACTION_NONE:
|
|
||||||
case FPI_DEVICE_ACTION_PROBE:
|
|
||||||
case FPI_DEVICE_ACTION_CAPTURE:
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -119,56 +108,23 @@ sleep_timeout_cb (gpointer data)
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
char *
|
||||||
wait_for_command_timeout (gpointer data)
|
|
||||||
{
|
|
||||||
FpDeviceVirtualDevice *self = FP_DEVICE_VIRTUAL_DEVICE (data);
|
|
||||||
FpiDeviceAction action;
|
|
||||||
GError *error = NULL;
|
|
||||||
|
|
||||||
self->wait_command_id = 0;
|
|
||||||
|
|
||||||
action = fpi_device_get_current_action (FP_DEVICE (self));
|
|
||||||
if (action == FPI_DEVICE_ACTION_LIST || action == FPI_DEVICE_ACTION_DELETE)
|
|
||||||
{
|
|
||||||
self->ignore_wait = TRUE;
|
|
||||||
maybe_continue_current_action (self);
|
|
||||||
self->ignore_wait = FALSE;
|
|
||||||
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
error = g_error_new (G_IO_ERROR, G_IO_ERROR_TIMED_OUT, "No commands arrived in time to run!");
|
|
||||||
fpi_device_action_error (FP_DEVICE (self), error);
|
|
||||||
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
gboolean
|
|
||||||
process_cmds (FpDeviceVirtualDevice * self,
|
process_cmds (FpDeviceVirtualDevice * self,
|
||||||
gboolean scan,
|
gboolean scan,
|
||||||
char **scan_id,
|
|
||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
gboolean removed;
|
|
||||||
|
|
||||||
if (g_cancellable_is_cancelled (self->cancellable) ||
|
if (g_cancellable_is_cancelled (self->cancellable) ||
|
||||||
(fpi_device_get_current_action (FP_DEVICE (self)) != FPI_DEVICE_ACTION_NONE &&
|
(fpi_device_get_current_action (FP_DEVICE (self)) != FPI_DEVICE_ACTION_NONE &&
|
||||||
g_cancellable_is_cancelled (fpi_device_get_cancellable (FP_DEVICE (self)))))
|
g_cancellable_is_cancelled (fpi_device_get_cancellable (FP_DEVICE (self)))))
|
||||||
{
|
{
|
||||||
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_CANCELLED,
|
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_CANCELLED,
|
||||||
"Operation was cancelled");
|
"Operation was cancelled");
|
||||||
return TRUE;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (self->pending_commands->len > 0)
|
while (self->pending_commands->len > 0)
|
||||||
{
|
{
|
||||||
g_autofree gchar *cmd = NULL;
|
gchar *cmd = g_ptr_array_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);
|
g_debug ("Processing command %s", cmd);
|
||||||
|
|
||||||
@@ -179,6 +135,7 @@ process_cmds (FpDeviceVirtualDevice * self,
|
|||||||
g_hash_table_add (self->prints_storage,
|
g_hash_table_add (self->prints_storage,
|
||||||
g_strdup (cmd + strlen (INSERT_CMD_PREFIX)));
|
g_strdup (cmd + strlen (INSERT_CMD_PREFIX)));
|
||||||
|
|
||||||
|
g_ptr_array_remove_index (self->pending_commands, 0);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else if (g_str_has_prefix (cmd, REMOVE_CMD_PREFIX))
|
else if (g_str_has_prefix (cmd, REMOVE_CMD_PREFIX))
|
||||||
@@ -188,49 +145,50 @@ process_cmds (FpDeviceVirtualDevice * self,
|
|||||||
cmd + strlen (REMOVE_CMD_PREFIX)))
|
cmd + strlen (REMOVE_CMD_PREFIX)))
|
||||||
g_warning ("ID %s was not found in storage", cmd + strlen (REMOVE_CMD_PREFIX));
|
g_warning ("ID %s was not found in storage", cmd + strlen (REMOVE_CMD_PREFIX));
|
||||||
|
|
||||||
|
g_ptr_array_remove_index (self->pending_commands, 0);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else if (g_str_has_prefix (cmd, SLEEP_CMD_PREFIX))
|
else if (g_str_has_prefix (cmd, SLEEP_CMD_PREFIX))
|
||||||
{
|
{
|
||||||
guint64 sleep_ms = g_ascii_strtoull (cmd + strlen (SLEEP_CMD_PREFIX), NULL, 10);
|
guint64 sleep_ms = g_ascii_strtoull (cmd + strlen (SLEEP_CMD_PREFIX), NULL, 10);
|
||||||
|
|
||||||
g_debug ("Sleeping %" G_GUINT64_FORMAT "ms", sleep_ms);
|
g_debug ("Sleeping %lums", sleep_ms);
|
||||||
self->sleep_timeout_id = g_timeout_add (sleep_ms, sleep_timeout_cb, self);
|
self->sleep_timeout_id = g_timeout_add (sleep_ms, sleep_timeout_cb, self);
|
||||||
|
g_ptr_array_remove_index (self->pending_commands, 0);
|
||||||
|
|
||||||
return FALSE;
|
return NULL;
|
||||||
}
|
}
|
||||||
else if (g_str_has_prefix (cmd, ERROR_CMD_PREFIX))
|
else if (g_str_has_prefix (cmd, ERROR_CMD_PREFIX))
|
||||||
{
|
{
|
||||||
g_propagate_error (error,
|
g_propagate_error (error,
|
||||||
fpi_device_error_new (g_ascii_strtoull (cmd + strlen (ERROR_CMD_PREFIX), NULL, 10)));
|
fpi_device_error_new (g_ascii_strtoull (cmd + strlen (ERROR_CMD_PREFIX), NULL, 10)));
|
||||||
|
|
||||||
return TRUE;
|
g_ptr_array_remove_index (self->pending_commands, 0);
|
||||||
}
|
return NULL;
|
||||||
else if (!scan && g_str_has_prefix (cmd, CONT_CMD_PREFIX))
|
|
||||||
{
|
|
||||||
return TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If we are not scanning, then we have to stop here. */
|
/* If we are not scanning, then we have to stop here. */
|
||||||
if (!scan)
|
if (!scan)
|
||||||
{
|
{
|
||||||
g_warning ("Could not process command: %s", cmd);
|
g_warning ("Could not process command: %s", cmd);
|
||||||
|
g_ptr_array_remove_index (self->pending_commands, 0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (g_str_has_prefix (cmd, SCAN_CMD_PREFIX))
|
if (g_str_has_prefix (cmd, SCAN_CMD_PREFIX))
|
||||||
{
|
{
|
||||||
if (scan_id)
|
char *res = g_strdup (cmd + strlen (SCAN_CMD_PREFIX));
|
||||||
*scan_id = g_strdup (cmd + strlen (SCAN_CMD_PREFIX));
|
|
||||||
|
|
||||||
return TRUE;
|
g_ptr_array_remove_index (self->pending_commands, 0);
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
else if (g_str_has_prefix (cmd, RETRY_CMD_PREFIX))
|
else if (g_str_has_prefix (cmd, RETRY_CMD_PREFIX))
|
||||||
{
|
{
|
||||||
g_propagate_error (error,
|
g_propagate_error (error,
|
||||||
fpi_device_retry_new (g_ascii_strtoull (cmd + strlen (RETRY_CMD_PREFIX), NULL, 10)));
|
fpi_device_retry_new (g_ascii_strtoull (cmd + strlen (RETRY_CMD_PREFIX), NULL, 10)));
|
||||||
|
|
||||||
return TRUE;
|
g_ptr_array_remove_index (self->pending_commands, 0);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
else if (g_str_has_prefix (cmd, FINGER_CMD_PREFIX))
|
else if (g_str_has_prefix (cmd, FINGER_CMD_PREFIX))
|
||||||
{
|
{
|
||||||
@@ -241,32 +199,28 @@ process_cmds (FpDeviceVirtualDevice * self,
|
|||||||
finger_present ? FP_FINGER_STATUS_PRESENT : FP_FINGER_STATUS_NONE,
|
finger_present ? FP_FINGER_STATUS_PRESENT : FP_FINGER_STATUS_NONE,
|
||||||
finger_present ? FP_FINGER_STATUS_NONE : FP_FINGER_STATUS_PRESENT);
|
finger_present ? FP_FINGER_STATUS_NONE : FP_FINGER_STATUS_PRESENT);
|
||||||
|
|
||||||
|
g_ptr_array_remove_index (self->pending_commands, 0);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
g_warning ("Could not process command: %s", cmd);
|
g_warning ("Could not process command: %s", cmd);
|
||||||
|
g_ptr_array_remove_index (self->pending_commands, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (self->ignore_wait)
|
/* No commands left, throw a timeout error. */
|
||||||
return TRUE;
|
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND, "No commands left that can be run!");
|
||||||
|
return NULL;
|
||||||
g_object_get (self, "removed", &removed, NULL);
|
|
||||||
|
|
||||||
g_assert (self->wait_command_id == 0);
|
|
||||||
if (!scan || removed)
|
|
||||||
self->wait_command_id = g_timeout_add (500, wait_for_command_timeout, self);
|
|
||||||
return FALSE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
write_key_to_listener (void *key, void *val, void *user_data)
|
write_key_to_listener (void *key, void *val, void *user_data)
|
||||||
{
|
{
|
||||||
FpiDeviceVirtualListener *listener = FPI_DEVICE_VIRTUAL_LISTENER (user_data);
|
FpDeviceVirtualListener *listener = FP_DEVICE_VIRTUAL_LISTENER (user_data);
|
||||||
|
|
||||||
if (!fpi_device_virtual_listener_write_sync (listener, key, strlen (key), NULL) ||
|
if (!fp_device_virtual_listener_write_sync (listener, key, strlen (key), NULL) ||
|
||||||
!fpi_device_virtual_listener_write_sync (listener, "\n", 1, NULL))
|
!fp_device_virtual_listener_write_sync (listener, "\n", 1, NULL))
|
||||||
g_warning ("Error writing reply to LIST command");
|
g_warning ("Error writing reply to LIST command");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -276,11 +230,11 @@ recv_instruction_cb (GObject *source_object,
|
|||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
g_autoptr(GError) error = NULL;
|
g_autoptr(GError) error = NULL;
|
||||||
FpiDeviceVirtualListener *listener = FPI_DEVICE_VIRTUAL_LISTENER (source_object);
|
FpDeviceVirtualListener *listener = FP_DEVICE_VIRTUAL_LISTENER (source_object);
|
||||||
gsize bytes;
|
gsize bytes;
|
||||||
|
|
||||||
bytes = fpi_device_virtual_listener_read_finish (listener, res, &error);
|
bytes = fp_device_virtual_listener_read_finish (listener, res, &error);
|
||||||
fp_dbg ("Got instructions of length %" G_GSIZE_FORMAT, bytes);
|
fp_dbg ("Got instructions of length %ld", bytes);
|
||||||
|
|
||||||
if (error)
|
if (error)
|
||||||
{
|
{
|
||||||
@@ -309,7 +263,6 @@ recv_instruction_cb (GObject *source_object,
|
|||||||
else if (g_str_has_prefix (cmd, UNPLUG_CMD))
|
else if (g_str_has_prefix (cmd, UNPLUG_CMD))
|
||||||
{
|
{
|
||||||
fpi_device_remove (FP_DEVICE (self));
|
fpi_device_remove (FP_DEVICE (self));
|
||||||
maybe_continue_current_action (self);
|
|
||||||
}
|
}
|
||||||
else if (g_str_has_prefix (cmd, SET_ENROLL_STAGES_PREFIX))
|
else if (g_str_has_prefix (cmd, SET_ENROLL_STAGES_PREFIX))
|
||||||
{
|
{
|
||||||
@@ -353,23 +306,23 @@ recv_instruction_cb (GObject *source_object,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fpi_device_virtual_listener_connection_close (listener);
|
fp_device_virtual_listener_connection_close (listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
recv_instruction (FpDeviceVirtualDevice *self)
|
recv_instruction (FpDeviceVirtualDevice *self)
|
||||||
{
|
{
|
||||||
fpi_device_virtual_listener_read (self->listener,
|
fp_device_virtual_listener_read (self->listener,
|
||||||
FALSE,
|
FALSE,
|
||||||
self->recv_buf,
|
self->recv_buf,
|
||||||
sizeof (self->recv_buf),
|
sizeof (self->recv_buf),
|
||||||
recv_instruction_cb,
|
recv_instruction_cb,
|
||||||
self);
|
self);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
on_listener_connected (FpiDeviceVirtualListener *listener,
|
on_listener_connected (FpDeviceVirtualListener *listener,
|
||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
FpDeviceVirtualDevice *self = FP_DEVICE_VIRTUAL_DEVICE (user_data);
|
FpDeviceVirtualDevice *self = FP_DEVICE_VIRTUAL_DEVICE (user_data);
|
||||||
|
|
||||||
@@ -381,39 +334,36 @@ dev_init (FpDevice *dev)
|
|||||||
{
|
{
|
||||||
g_autoptr(GError) error = NULL;
|
g_autoptr(GError) error = NULL;
|
||||||
g_autoptr(GCancellable) cancellable = NULL;
|
g_autoptr(GCancellable) cancellable = NULL;
|
||||||
g_autoptr(FpiDeviceVirtualListener) listener = NULL;
|
g_autoptr(FpDeviceVirtualListener) listener = NULL;
|
||||||
FpDeviceVirtualDevice *self = FP_DEVICE_VIRTUAL_DEVICE (dev);
|
FpDeviceVirtualDevice *self = FP_DEVICE_VIRTUAL_DEVICE (dev);
|
||||||
|
|
||||||
G_DEBUG_HERE ();
|
G_DEBUG_HERE ();
|
||||||
|
|
||||||
self->ignore_wait = TRUE;
|
process_cmds (self, FALSE, &error);
|
||||||
if (!process_cmds (self, FALSE, NULL, &error))
|
if (error && !g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
|
||||||
{
|
|
||||||
self->ignore_wait = FALSE;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
self->ignore_wait = FALSE;
|
|
||||||
|
|
||||||
if (error)
|
|
||||||
{
|
{
|
||||||
fpi_device_open_complete (dev, g_steal_pointer (&error));
|
fpi_device_open_complete (dev, g_steal_pointer (&error));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
else if (self->sleep_timeout_id)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
else if (self->listener)
|
else if (self->listener)
|
||||||
{
|
{
|
||||||
fpi_device_open_complete (dev, NULL);
|
fpi_device_open_complete (dev, NULL);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
listener = fpi_device_virtual_listener_new ();
|
listener = fp_device_virtual_listener_new ();
|
||||||
cancellable = g_cancellable_new ();
|
cancellable = g_cancellable_new ();
|
||||||
|
|
||||||
if (!fpi_device_virtual_listener_start (listener,
|
if (!fp_device_virtual_listener_start (listener,
|
||||||
fpi_device_get_virtual_env (FP_DEVICE (self)),
|
fpi_device_get_virtual_env (FP_DEVICE (self)),
|
||||||
cancellable,
|
cancellable,
|
||||||
on_listener_connected,
|
on_listener_connected,
|
||||||
self,
|
self,
|
||||||
&error))
|
&error))
|
||||||
{
|
{
|
||||||
fpi_device_open_complete (dev, g_steal_pointer (&error));
|
fpi_device_open_complete (dev, g_steal_pointer (&error));
|
||||||
return;
|
return;
|
||||||
@@ -425,21 +375,65 @@ dev_init (FpDevice *dev)
|
|||||||
fpi_device_open_complete (dev, NULL);
|
fpi_device_open_complete (dev, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
wait_for_command_timeout (gpointer data)
|
||||||
|
{
|
||||||
|
FpDeviceVirtualDevice *self = FP_DEVICE_VIRTUAL_DEVICE (data);
|
||||||
|
GError *error = NULL;
|
||||||
|
|
||||||
|
self->wait_command_id = 0;
|
||||||
|
|
||||||
|
switch (fpi_device_get_current_action (FP_DEVICE (self)))
|
||||||
|
{
|
||||||
|
case FPI_DEVICE_ACTION_LIST:
|
||||||
|
case FPI_DEVICE_ACTION_DELETE:
|
||||||
|
self->ignore_wait = TRUE;
|
||||||
|
maybe_continue_current_action (self);
|
||||||
|
self->ignore_wait = FALSE;
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
error = g_error_new (G_IO_ERROR, G_IO_ERROR_TIMED_OUT, "No commands arrived in time to run!");
|
||||||
|
fpi_device_action_error (FP_DEVICE (self), error);
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
|
should_wait_for_command (FpDeviceVirtualDevice *self,
|
||||||
|
GError *error)
|
||||||
|
{
|
||||||
|
if (!error && self->sleep_timeout_id)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
if (self->ignore_wait)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (self->wait_command_id)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
self->wait_command_id = g_timeout_add (500, wait_for_command_timeout, self);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *
|
||||||
start_scan_command (FpDeviceVirtualDevice *self,
|
start_scan_command (FpDeviceVirtualDevice *self,
|
||||||
char **scan_id,
|
|
||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
g_autoptr(GError) local_error = NULL;
|
g_autoptr(GError) local_error = NULL;
|
||||||
gboolean cont;
|
g_autofree char *scan_id = NULL;
|
||||||
|
|
||||||
if (fp_device_get_finger_status (FP_DEVICE (self)) == FP_FINGER_STATUS_NONE)
|
if (fp_device_get_finger_status (FP_DEVICE (self)) == FP_FINGER_STATUS_NONE)
|
||||||
self->injected_synthetic_cmd = FALSE;
|
self->injected_synthetic_cmd = FALSE;
|
||||||
|
|
||||||
cont = process_cmds (self, TRUE, scan_id, &local_error);
|
scan_id = process_cmds (self, TRUE, &local_error);
|
||||||
/* We report finger needed if we are waiting for instructions
|
|
||||||
* (i.e. we did not get an explicit SLEEP command).
|
|
||||||
*/
|
|
||||||
if (!self->sleep_timeout_id)
|
if (!self->sleep_timeout_id)
|
||||||
{
|
{
|
||||||
fpi_device_report_finger_status_changes (FP_DEVICE (self),
|
fpi_device_report_finger_status_changes (FP_DEVICE (self),
|
||||||
@@ -447,13 +441,14 @@ start_scan_command (FpDeviceVirtualDevice *self,
|
|||||||
FP_FINGER_STATUS_NONE);
|
FP_FINGER_STATUS_NONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!cont)
|
if (should_wait_for_command (self, local_error))
|
||||||
return FALSE;
|
{
|
||||||
|
g_assert (!scan_id);
|
||||||
|
|
||||||
/* Scan or error*/
|
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_PENDING,
|
||||||
fpi_device_report_finger_status_changes (FP_DEVICE (self),
|
"Still waiting for command");
|
||||||
FP_FINGER_STATUS_NEEDED,
|
return NULL;
|
||||||
FP_FINGER_STATUS_NONE);
|
}
|
||||||
|
|
||||||
if (local_error)
|
if (local_error)
|
||||||
g_propagate_error (error, g_steal_pointer (&local_error));
|
g_propagate_error (error, g_steal_pointer (&local_error));
|
||||||
@@ -462,7 +457,7 @@ start_scan_command (FpDeviceVirtualDevice *self,
|
|||||||
FP_FINGER_STATUS_PRESENT,
|
FP_FINGER_STATUS_PRESENT,
|
||||||
FP_FINGER_STATUS_NONE);
|
FP_FINGER_STATUS_NONE);
|
||||||
|
|
||||||
return TRUE;
|
return g_steal_pointer (&scan_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
@@ -483,7 +478,7 @@ should_wait_to_sleep (FpDeviceVirtualDevice *self,
|
|||||||
if (g_str_has_prefix (cmd, SLEEP_CMD_PREFIX))
|
if (g_str_has_prefix (cmd, SLEEP_CMD_PREFIX))
|
||||||
{
|
{
|
||||||
g_autoptr(GError) local_error = NULL;
|
g_autoptr(GError) local_error = NULL;
|
||||||
process_cmds (self, FALSE, NULL, &local_error);
|
g_free (process_cmds (self, FALSE, &local_error));
|
||||||
|
|
||||||
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
@@ -521,13 +516,14 @@ dev_verify (FpDevice *dev)
|
|||||||
FpDeviceVirtualDevice *self = FP_DEVICE_VIRTUAL_DEVICE (dev);
|
FpDeviceVirtualDevice *self = FP_DEVICE_VIRTUAL_DEVICE (dev);
|
||||||
g_autofree char *scan_id = NULL;
|
g_autofree char *scan_id = NULL;
|
||||||
|
|
||||||
if (!start_scan_command (self, &scan_id, &error))
|
scan_id = start_scan_command (self, &error);
|
||||||
|
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_PENDING))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (scan_id)
|
if (scan_id)
|
||||||
{
|
{
|
||||||
g_autoptr(FpPrint) new_scan = NULL;
|
|
||||||
GVariant *data = NULL;
|
GVariant *data = NULL;
|
||||||
|
FpPrint *new_scan;
|
||||||
FpPrint *print;
|
FpPrint *print;
|
||||||
gboolean success;
|
gboolean success;
|
||||||
|
|
||||||
@@ -543,7 +539,7 @@ dev_verify (FpDevice *dev)
|
|||||||
|
|
||||||
if (self->prints_storage && !g_hash_table_contains (self->prints_storage, scan_id))
|
if (self->prints_storage && !g_hash_table_contains (self->prints_storage, scan_id))
|
||||||
{
|
{
|
||||||
g_clear_object (&new_scan);
|
error = fpi_device_error_new (FP_DEVICE_ERROR_DATA_NOT_FOUND);
|
||||||
success = FALSE;
|
success = FALSE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -556,7 +552,7 @@ dev_verify (FpDevice *dev)
|
|||||||
self->match_reported = TRUE;
|
self->match_reported = TRUE;
|
||||||
fpi_device_verify_report (dev,
|
fpi_device_verify_report (dev,
|
||||||
success ? FPI_MATCH_SUCCESS : FPI_MATCH_FAIL,
|
success ? FPI_MATCH_SUCCESS : FPI_MATCH_FAIL,
|
||||||
g_steal_pointer (&new_scan),
|
new_scan,
|
||||||
NULL);
|
NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -587,7 +583,8 @@ dev_enroll (FpDevice *dev)
|
|||||||
FpPrint *print = NULL;
|
FpPrint *print = NULL;
|
||||||
g_autofree char *id = NULL;
|
g_autofree char *id = NULL;
|
||||||
|
|
||||||
if (!start_scan_command (self, &id, &error))
|
id = start_scan_command (self, &error);
|
||||||
|
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_PENDING))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
fpi_device_get_enroll_data (dev, &print);
|
fpi_device_get_enroll_data (dev, &print);
|
||||||
@@ -699,7 +696,6 @@ dev_cancel (FpDevice *dev)
|
|||||||
|
|
||||||
g_debug ("Got cancellation!");
|
g_debug ("Got cancellation!");
|
||||||
g_clear_handle_id (&self->sleep_timeout_id, g_source_remove);
|
g_clear_handle_id (&self->sleep_timeout_id, g_source_remove);
|
||||||
g_clear_handle_id (&self->wait_command_id, g_source_remove);
|
|
||||||
|
|
||||||
maybe_continue_current_action (self);
|
maybe_continue_current_action (self);
|
||||||
}
|
}
|
||||||
@@ -718,28 +714,22 @@ dev_deinit (FpDevice *dev)
|
|||||||
g_autoptr(GError) error = NULL;
|
g_autoptr(GError) error = NULL;
|
||||||
FpDeviceVirtualDevice *self = FP_DEVICE_VIRTUAL_DEVICE (dev);
|
FpDeviceVirtualDevice *self = FP_DEVICE_VIRTUAL_DEVICE (dev);
|
||||||
|
|
||||||
self->ignore_wait = TRUE;
|
process_cmds (self, FALSE, &error);
|
||||||
if (!process_cmds (self, FALSE, NULL, &error))
|
if (error && !g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
|
||||||
{
|
|
||||||
self->ignore_wait = FALSE;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
self->ignore_wait = FALSE;
|
|
||||||
|
|
||||||
if (error)
|
|
||||||
{
|
{
|
||||||
fpi_device_close_complete (dev, g_steal_pointer (&error));
|
fpi_device_close_complete (dev, g_steal_pointer (&error));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
else if (self->sleep_timeout_id)
|
||||||
if (!self->keep_alive)
|
|
||||||
{
|
{
|
||||||
stop_listener (self);
|
return;
|
||||||
self->supports_cancellation = TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
self->enroll_stages_passed = 0;
|
g_clear_handle_id (&self->wait_command_id, g_source_remove);
|
||||||
self->match_reported = FALSE;
|
g_clear_handle_id (&self->sleep_timeout_id, g_source_remove);
|
||||||
|
|
||||||
|
if (!self->keep_alive)
|
||||||
|
stop_listener (self);
|
||||||
|
|
||||||
fpi_device_close_complete (dev, NULL);
|
fpi_device_close_complete (dev, NULL);
|
||||||
}
|
}
|
||||||
@@ -786,6 +776,4 @@ fpi_device_virtual_device_class_init (FpDeviceVirtualDeviceClass *klass)
|
|||||||
dev_class->verify = dev_verify;
|
dev_class->verify = dev_verify;
|
||||||
dev_class->enroll = dev_enroll;
|
dev_class->enroll = dev_enroll;
|
||||||
dev_class->cancel = dev_cancel;
|
dev_class->cancel = dev_cancel;
|
||||||
|
|
||||||
fpi_device_class_auto_initialize_features (dev_class);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,14 +36,14 @@
|
|||||||
|
|
||||||
struct _FpDeviceVirtualImage
|
struct _FpDeviceVirtualImage
|
||||||
{
|
{
|
||||||
FpImageDevice parent;
|
FpImageDevice parent;
|
||||||
|
|
||||||
FpiDeviceVirtualListener *listener;
|
FpDeviceVirtualListener *listener;
|
||||||
GCancellable *cancellable;
|
GCancellable *cancellable;
|
||||||
|
|
||||||
gboolean automatic_finger;
|
gboolean automatic_finger;
|
||||||
FpImage *recv_img;
|
FpImage *recv_img;
|
||||||
gint recv_img_hdr[2];
|
gint recv_img_hdr[2];
|
||||||
};
|
};
|
||||||
|
|
||||||
G_DECLARE_FINAL_TYPE (FpDeviceVirtualImage, fpi_device_virtual_image, FPI, DEVICE_VIRTUAL_IMAGE, FpImageDevice)
|
G_DECLARE_FINAL_TYPE (FpDeviceVirtualImage, fpi_device_virtual_image, FPI, DEVICE_VIRTUAL_IMAGE, FpImageDevice)
|
||||||
@@ -57,12 +57,12 @@ recv_image_img_recv_cb (GObject *source_object,
|
|||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
g_autoptr(GError) error = NULL;
|
g_autoptr(GError) error = NULL;
|
||||||
FpiDeviceVirtualListener *listener = FPI_DEVICE_VIRTUAL_LISTENER (source_object);
|
FpDeviceVirtualListener *listener = FP_DEVICE_VIRTUAL_LISTENER (source_object);
|
||||||
FpDeviceVirtualImage *self;
|
FpDeviceVirtualImage *self;
|
||||||
FpImageDevice *device;
|
FpImageDevice *device;
|
||||||
gsize bytes;
|
gsize bytes;
|
||||||
|
|
||||||
bytes = fpi_device_virtual_listener_read_finish (listener, res, &error);
|
bytes = fp_device_virtual_listener_read_finish (listener, res, &error);
|
||||||
|
|
||||||
if (!bytes || g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED) ||
|
if (!bytes || g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED) ||
|
||||||
g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CONNECTION_CLOSED))
|
g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CONNECTION_CLOSED))
|
||||||
@@ -88,10 +88,10 @@ recv_image_hdr_recv_cb (GObject *source_object,
|
|||||||
{
|
{
|
||||||
g_autoptr(GError) error = NULL;
|
g_autoptr(GError) error = NULL;
|
||||||
FpDeviceVirtualImage *self;
|
FpDeviceVirtualImage *self;
|
||||||
FpiDeviceVirtualListener *listener = FPI_DEVICE_VIRTUAL_LISTENER (source_object);
|
FpDeviceVirtualListener *listener = FP_DEVICE_VIRTUAL_LISTENER (source_object);
|
||||||
gsize bytes;
|
gsize bytes;
|
||||||
|
|
||||||
bytes = fpi_device_virtual_listener_read_finish (listener, res, &error);
|
bytes = fp_device_virtual_listener_read_finish (listener, res, &error);
|
||||||
|
|
||||||
if (error)
|
if (error)
|
||||||
{
|
{
|
||||||
@@ -111,7 +111,7 @@ recv_image_hdr_recv_cb (GObject *source_object,
|
|||||||
if (self->recv_img_hdr[0] > 5000 || self->recv_img_hdr[1] > 5000)
|
if (self->recv_img_hdr[0] > 5000 || self->recv_img_hdr[1] > 5000)
|
||||||
{
|
{
|
||||||
g_warning ("Image header suggests an unrealistically large image, disconnecting client.");
|
g_warning ("Image header suggests an unrealistically large image, disconnecting client.");
|
||||||
fpi_device_virtual_listener_connection_close (listener);
|
fp_device_virtual_listener_connection_close (listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (self->recv_img_hdr[0] < 0 || self->recv_img_hdr[1] < 0)
|
if (self->recv_img_hdr[0] < 0 || self->recv_img_hdr[1] < 0)
|
||||||
@@ -147,7 +147,7 @@ recv_image_hdr_recv_cb (GObject *source_object,
|
|||||||
|
|
||||||
default:
|
default:
|
||||||
/* disconnect client, it didn't play fair */
|
/* disconnect client, it didn't play fair */
|
||||||
fpi_device_virtual_listener_connection_close (listener);
|
fp_device_virtual_listener_connection_close (listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* And, listen for more images from the same client. */
|
/* And, listen for more images from the same client. */
|
||||||
@@ -157,28 +157,28 @@ recv_image_hdr_recv_cb (GObject *source_object,
|
|||||||
|
|
||||||
self->recv_img = fp_image_new (self->recv_img_hdr[0], self->recv_img_hdr[1]);
|
self->recv_img = fp_image_new (self->recv_img_hdr[0], self->recv_img_hdr[1]);
|
||||||
g_debug ("image data: %p", self->recv_img->data);
|
g_debug ("image data: %p", self->recv_img->data);
|
||||||
fpi_device_virtual_listener_read (listener,
|
fp_device_virtual_listener_read (listener,
|
||||||
TRUE,
|
TRUE,
|
||||||
(guint8 *) self->recv_img->data,
|
(guint8 *) self->recv_img->data,
|
||||||
self->recv_img->width * self->recv_img->height,
|
self->recv_img->width * self->recv_img->height,
|
||||||
recv_image_img_recv_cb,
|
recv_image_img_recv_cb,
|
||||||
self);
|
self);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
recv_image (FpDeviceVirtualImage *self)
|
recv_image (FpDeviceVirtualImage *self)
|
||||||
{
|
{
|
||||||
fpi_device_virtual_listener_read (self->listener,
|
fp_device_virtual_listener_read (self->listener,
|
||||||
TRUE,
|
TRUE,
|
||||||
self->recv_img_hdr,
|
self->recv_img_hdr,
|
||||||
sizeof (self->recv_img_hdr),
|
sizeof (self->recv_img_hdr),
|
||||||
recv_image_hdr_recv_cb,
|
recv_image_hdr_recv_cb,
|
||||||
self);
|
self);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
on_listener_connected (FpiDeviceVirtualListener *listener,
|
on_listener_connected (FpDeviceVirtualListener *listener,
|
||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
FpDeviceVirtualImage *self = FPI_DEVICE_VIRTUAL_IMAGE (user_data);
|
FpDeviceVirtualImage *self = FPI_DEVICE_VIRTUAL_IMAGE (user_data);
|
||||||
FpiImageDeviceState state;
|
FpiImageDeviceState state;
|
||||||
@@ -188,42 +188,32 @@ on_listener_connected (FpiDeviceVirtualListener *listener,
|
|||||||
g_object_get (self,
|
g_object_get (self,
|
||||||
"fpi-image-device-state", &state,
|
"fpi-image-device-state", &state,
|
||||||
NULL);
|
NULL);
|
||||||
|
/* Only read if we are in AWAIT_FINGER_* or CAPTURE states */
|
||||||
|
if (state <= FPI_IMAGE_DEVICE_STATE_DEACTIVATING)
|
||||||
|
return;
|
||||||
|
|
||||||
switch (state)
|
recv_image (self);
|
||||||
{
|
|
||||||
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_INACTIVE:
|
|
||||||
case FPI_IMAGE_DEVICE_STATE_ACTIVATING:
|
|
||||||
case FPI_IMAGE_DEVICE_STATE_DEACTIVATING:
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
dev_init (FpImageDevice *dev)
|
dev_init (FpImageDevice *dev)
|
||||||
{
|
{
|
||||||
g_autoptr(GError) error = NULL;
|
g_autoptr(GError) error = NULL;
|
||||||
g_autoptr(FpiDeviceVirtualListener) listener = NULL;
|
g_autoptr(FpDeviceVirtualListener) listener = NULL;
|
||||||
g_autoptr(GCancellable) cancellable = NULL;
|
g_autoptr(GCancellable) cancellable = NULL;
|
||||||
FpDeviceVirtualImage *self = FPI_DEVICE_VIRTUAL_IMAGE (dev);
|
FpDeviceVirtualImage *self = FPI_DEVICE_VIRTUAL_IMAGE (dev);
|
||||||
|
|
||||||
G_DEBUG_HERE ();
|
G_DEBUG_HERE ();
|
||||||
|
|
||||||
listener = fpi_device_virtual_listener_new ();
|
listener = fp_device_virtual_listener_new ();
|
||||||
cancellable = g_cancellable_new ();
|
cancellable = g_cancellable_new ();
|
||||||
|
|
||||||
if (!fpi_device_virtual_listener_start (listener,
|
if (!fp_device_virtual_listener_start (listener,
|
||||||
fpi_device_get_virtual_env (FP_DEVICE (self)),
|
fpi_device_get_virtual_env (FP_DEVICE (self)),
|
||||||
cancellable,
|
cancellable,
|
||||||
on_listener_connected,
|
on_listener_connected,
|
||||||
self,
|
self,
|
||||||
&error))
|
&error))
|
||||||
{
|
{
|
||||||
fpi_image_device_open_complete (dev, g_steal_pointer (&error));
|
fpi_image_device_open_complete (dev, g_steal_pointer (&error));
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -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, "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, "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, "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, "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, "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, "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;
|
||||||
|
}
|
||||||
@@ -29,5 +29,4 @@
|
|||||||
#include "fpi-log.h"
|
#include "fpi-log.h"
|
||||||
#include "fpi-print.h"
|
#include "fpi-print.h"
|
||||||
#include "fpi-usb-transfer.h"
|
#include "fpi-usb-transfer.h"
|
||||||
#include "fpi-spi-transfer.h"
|
|
||||||
#include "fpi-ssm.h"
|
#include "fpi-ssm.h"
|
||||||
|
|||||||
+26
-163
@@ -23,13 +23,6 @@
|
|||||||
#include "fpi-context.h"
|
#include "fpi-context.h"
|
||||||
#include "fpi-device.h"
|
#include "fpi-device.h"
|
||||||
#include <gusb.h>
|
#include <gusb.h>
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#include <config.h>
|
|
||||||
|
|
||||||
#ifdef HAVE_UDEV
|
|
||||||
#include <gudev/gudev.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SECTION: fp-context
|
* SECTION: fp-context
|
||||||
@@ -48,8 +41,6 @@ typedef struct
|
|||||||
GUsbContext *usb_ctx;
|
GUsbContext *usb_ctx;
|
||||||
GCancellable *cancellable;
|
GCancellable *cancellable;
|
||||||
|
|
||||||
GSList *sources;
|
|
||||||
|
|
||||||
gint pending_devices;
|
gint pending_devices;
|
||||||
gboolean enumerated;
|
gboolean enumerated;
|
||||||
|
|
||||||
@@ -67,33 +58,38 @@ enum {
|
|||||||
static guint signals[LAST_SIGNAL] = { 0 };
|
static guint signals[LAST_SIGNAL] = { 0 };
|
||||||
|
|
||||||
static const char *
|
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
|
static gboolean
|
||||||
is_driver_allowed (const gchar *driver)
|
is_driver_allowed (const gchar *driver)
|
||||||
{
|
{
|
||||||
g_auto(GStrv) allowlisted_drivers = NULL;
|
g_auto(GStrv) whitelisted_drivers = NULL;
|
||||||
const char *fp_drivers_allowlist_env;
|
const char *fp_drivers_whitelist_env;
|
||||||
|
int i;
|
||||||
|
|
||||||
g_return_val_if_fail (driver, TRUE);
|
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;
|
return TRUE;
|
||||||
|
|
||||||
allowlisted_drivers = g_strsplit (fp_drivers_allowlist_env, ":", -1);
|
whitelisted_drivers = g_strsplit (fp_drivers_whitelist_env, ":", -1);
|
||||||
return g_strv_contains ((const gchar * const *) allowlisted_drivers, driver);
|
|
||||||
|
for (i = 0; whitelisted_drivers[i]; ++i)
|
||||||
|
if (g_strcmp0 (driver, whitelisted_drivers[i]) == 0)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
FpContext *context;
|
FpContext *context;
|
||||||
FpDevice *device;
|
FpDevice *device;
|
||||||
GSource *source;
|
|
||||||
} RemoveDeviceData;
|
} RemoveDeviceData;
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
@@ -107,36 +103,21 @@ remove_device_idle_cb (RemoveDeviceData *data)
|
|||||||
g_signal_emit (data->context, signals[DEVICE_REMOVED_SIGNAL], 0, data->device);
|
g_signal_emit (data->context, signals[DEVICE_REMOVED_SIGNAL], 0, data->device);
|
||||||
g_ptr_array_remove_index_fast (priv->devices, idx);
|
g_ptr_array_remove_index_fast (priv->devices, idx);
|
||||||
|
|
||||||
return G_SOURCE_REMOVE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
remove_device_data_free (RemoveDeviceData *data)
|
|
||||||
{
|
|
||||||
FpContextPrivate *priv = fp_context_get_instance_private (data->context);
|
|
||||||
|
|
||||||
priv->sources = g_slist_remove (priv->sources, data->source);
|
|
||||||
g_free (data);
|
g_free (data);
|
||||||
|
|
||||||
|
return G_SOURCE_REMOVE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
remove_device (FpContext *context, FpDevice *device)
|
remove_device (FpContext *context, FpDevice *device)
|
||||||
{
|
{
|
||||||
g_autoptr(GSource) source = NULL;
|
|
||||||
FpContextPrivate *priv = fp_context_get_instance_private (context);
|
|
||||||
RemoveDeviceData *data;
|
RemoveDeviceData *data;
|
||||||
|
|
||||||
data = g_new (RemoveDeviceData, 1);
|
data = g_new (RemoveDeviceData, 1);
|
||||||
data->context = context;
|
data->context = context;
|
||||||
data->device = device;
|
data->device = device;
|
||||||
|
|
||||||
source = data->source = g_idle_source_new ();
|
g_idle_add ((GSourceFunc) remove_device_idle_cb, data);
|
||||||
g_source_set_callback (source,
|
|
||||||
G_SOURCE_FUNC (remove_device_idle_cb), data,
|
|
||||||
(GDestroyNotify) remove_device_data_free);
|
|
||||||
g_source_attach (source, g_main_context_get_thread_default ());
|
|
||||||
|
|
||||||
priv->sources = g_slist_prepend (priv->sources, source);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -154,16 +135,9 @@ device_removed_cb (FpContext *context, FpDevice *device)
|
|||||||
|
|
||||||
/* Wait for device close if the device is currently still open. */
|
/* Wait for device close if the device is currently still open. */
|
||||||
if (open)
|
if (open)
|
||||||
{
|
g_signal_connect_swapped (device, "notify::open", (GCallback) device_remove_on_notify_open_cb, context);
|
||||||
g_signal_connect_object (device, "notify::open",
|
|
||||||
(GCallback) device_remove_on_notify_open_cb,
|
|
||||||
context,
|
|
||||||
G_CONNECT_SWAPPED);
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
remove_device (context, device);
|
||||||
remove_device (context, device);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -191,10 +165,7 @@ async_device_init_done_cb (GObject *source_object, GAsyncResult *res, gpointer u
|
|||||||
|
|
||||||
g_ptr_array_add (priv->devices, device);
|
g_ptr_array_add (priv->devices, device);
|
||||||
|
|
||||||
g_signal_connect_object (device, "removed",
|
g_signal_connect_swapped (device, "removed", (GCallback) device_removed_cb, context);
|
||||||
(GCallback) device_removed_cb,
|
|
||||||
context,
|
|
||||||
G_CONNECT_SWAPPED);
|
|
||||||
|
|
||||||
g_signal_emit (context, signals[DEVICE_ADDED_SIGNAL], 0, device);
|
g_signal_emit (context, signals[DEVICE_ADDED_SIGNAL], 0, device);
|
||||||
}
|
}
|
||||||
@@ -285,12 +256,11 @@ fp_context_finalize (GObject *object)
|
|||||||
FpContext *self = (FpContext *) object;
|
FpContext *self = (FpContext *) object;
|
||||||
FpContextPrivate *priv = fp_context_get_instance_private (self);
|
FpContextPrivate *priv = fp_context_get_instance_private (self);
|
||||||
|
|
||||||
|
g_clear_pointer (&priv->devices, g_ptr_array_unref);
|
||||||
|
|
||||||
g_cancellable_cancel (priv->cancellable);
|
g_cancellable_cancel (priv->cancellable);
|
||||||
g_clear_object (&priv->cancellable);
|
g_clear_object (&priv->cancellable);
|
||||||
g_clear_pointer (&priv->drivers, g_array_unref);
|
g_clear_pointer (&priv->drivers, g_array_unref);
|
||||||
g_clear_pointer (&priv->devices, g_ptr_array_unref);
|
|
||||||
|
|
||||||
g_slist_free_full (g_steal_pointer (&priv->sources), (GDestroyNotify) g_source_destroy);
|
|
||||||
|
|
||||||
if (priv->usb_ctx)
|
if (priv->usb_ctx)
|
||||||
g_object_run_dispose (G_OBJECT (priv->usb_ctx));
|
g_object_run_dispose (G_OBJECT (priv->usb_ctx));
|
||||||
@@ -354,11 +324,9 @@ fp_context_init (FpContext *self)
|
|||||||
FpContextPrivate *priv = fp_context_get_instance_private (self);
|
FpContextPrivate *priv = fp_context_get_instance_private (self);
|
||||||
guint i;
|
guint i;
|
||||||
|
|
||||||
g_debug ("Initializing FpContext (libfprint version " LIBFPRINT_VERSION ")");
|
|
||||||
|
|
||||||
priv->drivers = fpi_get_driver_types ();
|
priv->drivers = fpi_get_driver_types ();
|
||||||
|
|
||||||
if (get_drivers_allowlist_env ())
|
if (get_drivers_whitelist_env ())
|
||||||
{
|
{
|
||||||
for (i = 0; i < priv->drivers->len;)
|
for (i = 0; i < priv->drivers->len;)
|
||||||
{
|
{
|
||||||
@@ -421,7 +389,6 @@ void
|
|||||||
fp_context_enumerate (FpContext *context)
|
fp_context_enumerate (FpContext *context)
|
||||||
{
|
{
|
||||||
FpContextPrivate *priv = fp_context_get_instance_private (context);
|
FpContextPrivate *priv = fp_context_get_instance_private (context);
|
||||||
gboolean dispatched;
|
|
||||||
gint i;
|
gint i;
|
||||||
|
|
||||||
g_return_if_fail (FP_IS_CONTEXT (context));
|
g_return_if_fail (FP_IS_CONTEXT (context));
|
||||||
@@ -467,112 +434,8 @@ fp_context_enumerate (FpContext *context)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
while (priv->pending_devices)
|
||||||
#ifdef HAVE_UDEV
|
g_main_context_iteration (NULL, TRUE);
|
||||||
{
|
|
||||||
g_autoptr(GUdevClient) udev_client = g_udev_client_new (NULL);
|
|
||||||
|
|
||||||
/* This uses a very simple algorithm to allocate devices to drivers and assumes that no two drivers will want the same device. Future improvements
|
|
||||||
* could add a usb_discover style udev_discover that returns a score, however for internal devices the potential overlap should be very low between
|
|
||||||
* separate drivers.
|
|
||||||
*/
|
|
||||||
|
|
||||||
g_autoptr(GList) spidev_devices = g_udev_client_query_by_subsystem (udev_client, "spidev");
|
|
||||||
g_autoptr(GList) hidraw_devices = g_udev_client_query_by_subsystem (udev_client, "hidraw");
|
|
||||||
|
|
||||||
/* for each potential driver, try to match all requested resources. */
|
|
||||||
for (i = 0; i < priv->drivers->len; i++)
|
|
||||||
{
|
|
||||||
GType driver = g_array_index (priv->drivers, GType, i);
|
|
||||||
g_autoptr(FpDeviceClass) cls = g_type_class_ref (driver);
|
|
||||||
const FpIdEntry *entry;
|
|
||||||
|
|
||||||
if (cls->type != FP_DEVICE_TYPE_UDEV)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
for (entry = cls->id_table; entry->udev_types; entry++)
|
|
||||||
{
|
|
||||||
GList *matched_spidev = NULL, *matched_hidraw = NULL;
|
|
||||||
|
|
||||||
if (entry->udev_types & FPI_DEVICE_UDEV_SUBTYPE_SPIDEV)
|
|
||||||
{
|
|
||||||
for (matched_spidev = spidev_devices; matched_spidev; matched_spidev = matched_spidev->next)
|
|
||||||
{
|
|
||||||
const gchar * sysfs = g_udev_device_get_sysfs_path (matched_spidev->data);
|
|
||||||
if (!sysfs)
|
|
||||||
continue;
|
|
||||||
if (strstr (sysfs, entry->spi_acpi_id))
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
/* If match was not found exit */
|
|
||||||
if (matched_spidev == NULL)
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (entry->udev_types & FPI_DEVICE_UDEV_SUBTYPE_HIDRAW)
|
|
||||||
{
|
|
||||||
for (matched_hidraw = hidraw_devices; matched_hidraw; matched_hidraw = matched_hidraw->next)
|
|
||||||
{
|
|
||||||
/* Find the parent HID node, and check the vid/pid from its HID_ID property */
|
|
||||||
g_autoptr(GUdevDevice) parent = g_udev_device_get_parent_with_subsystem (matched_hidraw->data, "hid", NULL);
|
|
||||||
const gchar * hid_id = g_udev_device_get_property (parent, "HID_ID");
|
|
||||||
guint32 vendor, product;
|
|
||||||
|
|
||||||
if (!parent || !hid_id)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (sscanf (hid_id, "%*X:%X:%X", &vendor, &product) != 2)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (vendor == entry->hid_id.vid && product == entry->hid_id.pid)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
/* If match was not found exit */
|
|
||||||
if (matched_hidraw == NULL)
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
priv->pending_devices++;
|
|
||||||
g_async_initable_new_async (driver,
|
|
||||||
G_PRIORITY_LOW,
|
|
||||||
priv->cancellable,
|
|
||||||
async_device_init_done_cb,
|
|
||||||
context,
|
|
||||||
"fpi-driver-data", entry->driver_data,
|
|
||||||
"fpi-udev-data-spidev", (matched_spidev ? g_udev_device_get_device_file (matched_spidev->data) : NULL),
|
|
||||||
"fpi-udev-data-hidraw", (matched_hidraw ? g_udev_device_get_device_file (matched_hidraw->data) : NULL),
|
|
||||||
NULL);
|
|
||||||
/* remove entries from list to avoid conflicts */
|
|
||||||
if (matched_spidev)
|
|
||||||
{
|
|
||||||
g_object_unref (matched_spidev->data);
|
|
||||||
spidev_devices = g_list_delete_link (spidev_devices, matched_spidev);
|
|
||||||
}
|
|
||||||
if (matched_hidraw)
|
|
||||||
{
|
|
||||||
g_object_unref (matched_hidraw->data);
|
|
||||||
hidraw_devices = g_list_delete_link (hidraw_devices, matched_hidraw);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* free all unused elemnts in both lists */
|
|
||||||
g_list_foreach (spidev_devices, (GFunc) g_object_unref, NULL);
|
|
||||||
g_list_foreach (hidraw_devices, (GFunc) g_object_unref, NULL);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Iterate until 1. we have no pending devices, and 2. the mainloop is idle
|
|
||||||
* This takes care of processing hotplug events that happened during
|
|
||||||
* enumeration.
|
|
||||||
* This is important due to USB `persist` being turned off. At resume time,
|
|
||||||
* devices will disappear and immediately re-appear. In this situation,
|
|
||||||
* enumerate could first see the old state with a removed device resulting
|
|
||||||
* in it to not be discovered.
|
|
||||||
* As a hotplug event is seemingly emitted by the kernel immediately, we can
|
|
||||||
* simply make sure to process all events before returning from enumerate.
|
|
||||||
*/
|
|
||||||
dispatched = TRUE;
|
|
||||||
while (priv->pending_devices || dispatched)
|
|
||||||
dispatched = g_main_context_iteration (NULL, !!priv->pending_devices);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -581,7 +444,7 @@ fp_context_enumerate (FpContext *context)
|
|||||||
*
|
*
|
||||||
* Get all devices. fp_context_enumerate() will be called as needed.
|
* Get all devices. fp_context_enumerate() will be called as needed.
|
||||||
*
|
*
|
||||||
* Returns: (transfer none) (element-type FpDevice): a new #GPtrArray of #FpDevice's.
|
* Returns: (transfer none) (element-type FpDevice): a new #GPtrArray of #GUsbDevice's.
|
||||||
*/
|
*/
|
||||||
GPtrArray *
|
GPtrArray *
|
||||||
fp_context_get_devices (FpContext *context)
|
fp_context_get_devices (FpContext *context)
|
||||||
|
|||||||
@@ -22,83 +22,36 @@
|
|||||||
|
|
||||||
#include "fpi-device.h"
|
#include "fpi-device.h"
|
||||||
|
|
||||||
/* Chosen so that if we turn on after WARM -> COLD, it takes exactly one time
|
|
||||||
* constant to go from COLD -> HOT.
|
|
||||||
* TEMP_COLD_THRESH = 1 / (e + 1)
|
|
||||||
*/
|
|
||||||
#define TEMP_COLD_THRESH (0.26894142136999512075)
|
|
||||||
#define TEMP_WARM_HOT_THRESH (1.0 - TEMP_COLD_THRESH)
|
|
||||||
#define TEMP_HOT_WARM_THRESH (0.5)
|
|
||||||
|
|
||||||
/* Delay updates by 100ms to avoid hitting the border exactly */
|
|
||||||
#define TEMP_DELAY_SECONDS 0.1
|
|
||||||
|
|
||||||
/* Hopefully 3min is long enough to not get in the way, while also not
|
|
||||||
* properly overheating any devices.
|
|
||||||
*/
|
|
||||||
#define DEFAULT_TEMP_HOT_SECONDS (3 * 60)
|
|
||||||
#define DEFAULT_TEMP_COLD_SECONDS (9 * 60)
|
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
FpDeviceType type;
|
FpDeviceType type;
|
||||||
|
|
||||||
GUsbDevice *usb_device;
|
GUsbDevice *usb_device;
|
||||||
gchar *virtual_env;
|
const gchar *virtual_env;
|
||||||
struct
|
|
||||||
{
|
|
||||||
gchar *spidev_path;
|
|
||||||
gchar *hidraw_path;
|
|
||||||
} udev_data;
|
|
||||||
|
|
||||||
gboolean is_removed;
|
gboolean is_removed;
|
||||||
gboolean is_open;
|
gboolean is_open;
|
||||||
gboolean is_suspended;
|
|
||||||
|
|
||||||
gchar *device_id;
|
gchar *device_id;
|
||||||
gchar *device_name;
|
gchar *device_name;
|
||||||
FpScanType scan_type;
|
FpScanType scan_type;
|
||||||
FpDeviceFeature features;
|
|
||||||
|
|
||||||
guint64 driver_data;
|
guint64 driver_data;
|
||||||
|
|
||||||
gint nr_enroll_stages;
|
gint nr_enroll_stages;
|
||||||
GSList *sources;
|
GSList *sources;
|
||||||
|
|
||||||
/* We always make sure that only one task is run at a time. */
|
/* We always make sure that only one task is run at a time. */
|
||||||
FpiDeviceAction current_action;
|
FpiDeviceAction current_action;
|
||||||
GTask *current_task;
|
GTask *current_task;
|
||||||
GError *current_cancellation_reason;
|
|
||||||
GAsyncReadyCallback current_user_cb;
|
GAsyncReadyCallback current_user_cb;
|
||||||
GCancellable *current_cancellable;
|
|
||||||
gulong current_cancellable_id;
|
gulong current_cancellable_id;
|
||||||
gulong current_task_cancellable_id;
|
|
||||||
GSource *current_idle_cancel_source;
|
GSource *current_idle_cancel_source;
|
||||||
GSource *current_task_idle_return_source;
|
GSource *current_task_idle_return_source;
|
||||||
|
|
||||||
/* State for tasks */
|
/* State for tasks */
|
||||||
gboolean wait_for_finger;
|
gboolean wait_for_finger;
|
||||||
FpFingerStatusFlags finger_status;
|
FpFingerStatusFlags finger_status;
|
||||||
|
|
||||||
/* Driver critical sections */
|
|
||||||
guint critical_section;
|
|
||||||
GSource *critical_section_flush_source;
|
|
||||||
gboolean cancel_queued;
|
|
||||||
gboolean suspend_queued;
|
|
||||||
gboolean resume_queued;
|
|
||||||
|
|
||||||
/* Suspend/resume tasks */
|
|
||||||
GTask *suspend_resume_task;
|
|
||||||
GError *suspend_error;
|
|
||||||
|
|
||||||
/* Device temperature model information and state */
|
|
||||||
GSource *temp_timeout;
|
|
||||||
FpTemperature temp_current;
|
|
||||||
gint32 temp_hot_seconds;
|
|
||||||
gint32 temp_cold_seconds;
|
|
||||||
gint64 temp_last_update;
|
|
||||||
gboolean temp_last_active;
|
|
||||||
gdouble temp_current_ratio;
|
|
||||||
} FpDevicePrivate;
|
} FpDevicePrivate;
|
||||||
|
|
||||||
|
|
||||||
@@ -111,6 +64,8 @@ typedef struct
|
|||||||
GDestroyNotify enroll_progress_destroy;
|
GDestroyNotify enroll_progress_destroy;
|
||||||
} FpEnrollData;
|
} FpEnrollData;
|
||||||
|
|
||||||
|
void enroll_data_free (FpEnrollData *enroll_data);
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
FpPrint *enrolled_print; /* verify */
|
FpPrint *enrolled_print; /* verify */
|
||||||
@@ -126,11 +81,4 @@ typedef struct
|
|||||||
GDestroyNotify match_destroy;
|
GDestroyNotify match_destroy;
|
||||||
} FpMatchData;
|
} FpMatchData;
|
||||||
|
|
||||||
|
void match_data_free (FpMatchData *match_data);
|
||||||
void fpi_device_suspend (FpDevice *device);
|
|
||||||
void fpi_device_resume (FpDevice *device);
|
|
||||||
|
|
||||||
void fpi_device_configure_wakeup (FpDevice *device,
|
|
||||||
gboolean enabled);
|
|
||||||
void fpi_device_update_temp (FpDevice *device,
|
|
||||||
gboolean is_active);
|
|
||||||
|
|||||||
+57
-688
File diff suppressed because it is too large
Load Diff
+6
-93
@@ -38,43 +38,13 @@ G_DECLARE_DERIVABLE_TYPE (FpDevice, fp_device, FP, DEVICE, GObject)
|
|||||||
/**
|
/**
|
||||||
* FpDeviceType:
|
* FpDeviceType:
|
||||||
* @FP_DEVICE_TYPE_VIRTUAL: The device is a virtual device
|
* @FP_DEVICE_TYPE_VIRTUAL: The device is a virtual device
|
||||||
* @FP_DEVICE_TYPE_UDEV: The device is a udev device
|
|
||||||
* @FP_DEVICE_TYPE_USB: The device is a USB device
|
* @FP_DEVICE_TYPE_USB: The device is a USB device
|
||||||
*/
|
*/
|
||||||
typedef enum {
|
typedef enum {
|
||||||
FP_DEVICE_TYPE_VIRTUAL,
|
FP_DEVICE_TYPE_VIRTUAL,
|
||||||
FP_DEVICE_TYPE_UDEV,
|
|
||||||
FP_DEVICE_TYPE_USB,
|
FP_DEVICE_TYPE_USB,
|
||||||
} FpDeviceType;
|
} FpDeviceType;
|
||||||
|
|
||||||
/**
|
|
||||||
* FpDeviceFeature:
|
|
||||||
* @FP_DEVICE_FEATURE_NONE: Device does not support any feature
|
|
||||||
* @FP_DEVICE_FEATURE_CAPTURE: Supports image capture
|
|
||||||
* @FP_DEVICE_FEATURE_VERIFY: Supports finger verification
|
|
||||||
* @FP_DEVICE_FEATURE_IDENTIFY: Supports finger identification
|
|
||||||
* @FP_DEVICE_FEATURE_STORAGE: Device has a persistent storage
|
|
||||||
* @FP_DEVICE_FEATURE_STORAGE_LIST: Supports listing the storage templates
|
|
||||||
* @FP_DEVICE_FEATURE_STORAGE_DELETE: Supports deleting stored templates
|
|
||||||
* @FP_DEVICE_FEATURE_STORAGE_CLEAR: Supports clearing the whole storage
|
|
||||||
* @FP_DEVICE_FEATURE_DUPLICATES_CHECK: Natively supports duplicates detection
|
|
||||||
* @FP_DEVICE_FEATURE_ALWAYS_ON: Whether the device can run continuously
|
|
||||||
* @FP_DEVICE_FEATURE_UPDATE_PRINT: Supports updating an existing print record using new scans
|
|
||||||
*/
|
|
||||||
typedef enum /*< flags >*/ {
|
|
||||||
FP_DEVICE_FEATURE_NONE = 0,
|
|
||||||
FP_DEVICE_FEATURE_CAPTURE = 1 << 0,
|
|
||||||
FP_DEVICE_FEATURE_IDENTIFY = 1 << 1,
|
|
||||||
FP_DEVICE_FEATURE_VERIFY = 1 << 2,
|
|
||||||
FP_DEVICE_FEATURE_STORAGE = 1 << 3,
|
|
||||||
FP_DEVICE_FEATURE_STORAGE_LIST = 1 << 4,
|
|
||||||
FP_DEVICE_FEATURE_STORAGE_DELETE = 1 << 5,
|
|
||||||
FP_DEVICE_FEATURE_STORAGE_CLEAR = 1 << 6,
|
|
||||||
FP_DEVICE_FEATURE_DUPLICATES_CHECK = 1 << 7,
|
|
||||||
FP_DEVICE_FEATURE_ALWAYS_ON = 1 << 8,
|
|
||||||
FP_DEVICE_FEATURE_UPDATE_PRINT = 1 << 9,
|
|
||||||
} FpDeviceFeature;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* FpScanType:
|
* FpScanType:
|
||||||
* @FP_SCAN_TYPE_SWIPE: Sensor requires swiping the finger.
|
* @FP_SCAN_TYPE_SWIPE: Sensor requires swiping the finger.
|
||||||
@@ -85,23 +55,6 @@ typedef enum {
|
|||||||
FP_SCAN_TYPE_PRESS,
|
FP_SCAN_TYPE_PRESS,
|
||||||
} FpScanType;
|
} FpScanType;
|
||||||
|
|
||||||
/**
|
|
||||||
* FpTemperature:
|
|
||||||
* @FP_TEMPERATURE_COLD: Sensor is considered cold.
|
|
||||||
* @FP_TEMPERATURE_WARM: Sensor is warm, usage time may be limited.
|
|
||||||
* @FP_TEMPERATURE_HOT: Sensor is hot and cannot be used.
|
|
||||||
*
|
|
||||||
* When a device is created, it is assumed to be cold. Applications such as
|
|
||||||
* fprintd may want to ensure all devices on the system are cold before
|
|
||||||
* shutting down in order to ensure that the cool-off period is not violated
|
|
||||||
* because the internal libfprint state about the device is lost.
|
|
||||||
*/
|
|
||||||
typedef enum {
|
|
||||||
FP_TEMPERATURE_COLD,
|
|
||||||
FP_TEMPERATURE_WARM,
|
|
||||||
FP_TEMPERATURE_HOT,
|
|
||||||
} FpTemperature;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* FpDeviceRetry:
|
* FpDeviceRetry:
|
||||||
* @FP_DEVICE_RETRY_GENERAL: The scan did not succeed due to poor scan quality
|
* @FP_DEVICE_RETRY_GENERAL: The scan did not succeed due to poor scan quality
|
||||||
@@ -139,7 +92,7 @@ typedef enum {
|
|||||||
* @FP_DEVICE_ERROR_DATA_FULL: No space on device available for operation
|
* @FP_DEVICE_ERROR_DATA_FULL: No space on device available for operation
|
||||||
* @FP_DEVICE_ERROR_DATA_DUPLICATE: Enrolling template duplicates storaged templates
|
* @FP_DEVICE_ERROR_DATA_DUPLICATE: Enrolling template duplicates storaged templates
|
||||||
* @FP_DEVICE_ERROR_REMOVED: The device has been removed.
|
* @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
|
* 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.
|
* such as #G_IO_ERROR or #G_USB_DEVICE_ERROR may also be reported.
|
||||||
@@ -157,7 +110,7 @@ typedef enum {
|
|||||||
FP_DEVICE_ERROR_DATA_DUPLICATE,
|
FP_DEVICE_ERROR_DATA_DUPLICATE,
|
||||||
/* Leave some room to add more DATA related errors */
|
/* Leave some room to add more DATA related errors */
|
||||||
FP_DEVICE_ERROR_REMOVED = 0x100,
|
FP_DEVICE_ERROR_REMOVED = 0x100,
|
||||||
FP_DEVICE_ERROR_TOO_HOT,
|
FP_DEVICE_ERROR_UNTRUSTED,
|
||||||
} FpDeviceError;
|
} FpDeviceError;
|
||||||
|
|
||||||
GQuark fp_device_retry_quark (void);
|
GQuark fp_device_retry_quark (void);
|
||||||
@@ -224,11 +177,10 @@ gboolean fp_device_is_open (FpDevice *device);
|
|||||||
FpScanType fp_device_get_scan_type (FpDevice *device);
|
FpScanType fp_device_get_scan_type (FpDevice *device);
|
||||||
FpFingerStatusFlags fp_device_get_finger_status (FpDevice *device);
|
FpFingerStatusFlags fp_device_get_finger_status (FpDevice *device);
|
||||||
gint fp_device_get_nr_enroll_stages (FpDevice *device);
|
gint fp_device_get_nr_enroll_stages (FpDevice *device);
|
||||||
FpTemperature fp_device_get_temperature (FpDevice *device);
|
|
||||||
|
|
||||||
FpDeviceFeature fp_device_get_features (FpDevice *device);
|
gboolean fp_device_supports_identify (FpDevice *device);
|
||||||
gboolean fp_device_has_feature (FpDevice *device,
|
gboolean fp_device_supports_capture (FpDevice *device);
|
||||||
FpDeviceFeature feature);
|
gboolean fp_device_has_storage (FpDevice *device);
|
||||||
|
|
||||||
/* Opening the device */
|
/* Opening the device */
|
||||||
void fp_device_open (FpDevice *device,
|
void fp_device_open (FpDevice *device,
|
||||||
@@ -241,16 +193,6 @@ void fp_device_close (FpDevice *device,
|
|||||||
GAsyncReadyCallback callback,
|
GAsyncReadyCallback callback,
|
||||||
gpointer user_data);
|
gpointer user_data);
|
||||||
|
|
||||||
void fp_device_suspend (FpDevice *device,
|
|
||||||
GCancellable *cancellable,
|
|
||||||
GAsyncReadyCallback callback,
|
|
||||||
gpointer user_data);
|
|
||||||
|
|
||||||
void fp_device_resume (FpDevice *device,
|
|
||||||
GCancellable *cancellable,
|
|
||||||
GAsyncReadyCallback callback,
|
|
||||||
gpointer user_data);
|
|
||||||
|
|
||||||
void fp_device_enroll (FpDevice *device,
|
void fp_device_enroll (FpDevice *device,
|
||||||
FpPrint *template_print,
|
FpPrint *template_print,
|
||||||
GCancellable *cancellable,
|
GCancellable *cancellable,
|
||||||
@@ -295,23 +237,12 @@ void fp_device_list_prints (FpDevice *device,
|
|||||||
GAsyncReadyCallback callback,
|
GAsyncReadyCallback callback,
|
||||||
gpointer user_data);
|
gpointer user_data);
|
||||||
|
|
||||||
void fp_device_clear_storage (FpDevice *device,
|
|
||||||
GCancellable *cancellable,
|
|
||||||
GAsyncReadyCallback callback,
|
|
||||||
gpointer user_data);
|
|
||||||
|
|
||||||
gboolean fp_device_open_finish (FpDevice *device,
|
gboolean fp_device_open_finish (FpDevice *device,
|
||||||
GAsyncResult *result,
|
GAsyncResult *result,
|
||||||
GError **error);
|
GError **error);
|
||||||
gboolean fp_device_close_finish (FpDevice *device,
|
gboolean fp_device_close_finish (FpDevice *device,
|
||||||
GAsyncResult *result,
|
GAsyncResult *result,
|
||||||
GError **error);
|
GError **error);
|
||||||
gboolean fp_device_suspend_finish (FpDevice *device,
|
|
||||||
GAsyncResult *result,
|
|
||||||
GError **error);
|
|
||||||
gboolean fp_device_resume_finish (FpDevice *device,
|
|
||||||
GAsyncResult *result,
|
|
||||||
GError **error);
|
|
||||||
FpPrint *fp_device_enroll_finish (FpDevice *device,
|
FpPrint *fp_device_enroll_finish (FpDevice *device,
|
||||||
GAsyncResult *result,
|
GAsyncResult *result,
|
||||||
GError **error);
|
GError **error);
|
||||||
@@ -334,9 +265,7 @@ gboolean fp_device_delete_print_finish (FpDevice *device,
|
|||||||
GPtrArray * fp_device_list_prints_finish (FpDevice *device,
|
GPtrArray * fp_device_list_prints_finish (FpDevice *device,
|
||||||
GAsyncResult *result,
|
GAsyncResult *result,
|
||||||
GError **error);
|
GError **error);
|
||||||
gboolean fp_device_clear_storage_finish (FpDevice *device,
|
|
||||||
GAsyncResult *result,
|
|
||||||
GError **error);
|
|
||||||
|
|
||||||
gboolean fp_device_open_sync (FpDevice *device,
|
gboolean fp_device_open_sync (FpDevice *device,
|
||||||
GCancellable *cancellable,
|
GCancellable *cancellable,
|
||||||
@@ -377,22 +306,6 @@ gboolean fp_device_delete_print_sync (FpDevice *device,
|
|||||||
GPtrArray * fp_device_list_prints_sync (FpDevice *device,
|
GPtrArray * fp_device_list_prints_sync (FpDevice *device,
|
||||||
GCancellable *cancellable,
|
GCancellable *cancellable,
|
||||||
GError **error);
|
GError **error);
|
||||||
gboolean fp_device_clear_storage_sync (FpDevice *device,
|
|
||||||
GCancellable *cancellable,
|
|
||||||
GError **error);
|
|
||||||
gboolean fp_device_suspend_sync (FpDevice *device,
|
|
||||||
GCancellable *cancellable,
|
|
||||||
GError **error);
|
|
||||||
gboolean fp_device_resume_sync (FpDevice *device,
|
|
||||||
GCancellable *cancellable,
|
|
||||||
GError **error);
|
|
||||||
|
|
||||||
/* Deprecated functions */
|
|
||||||
G_DEPRECATED_FOR (fp_device_get_features)
|
|
||||||
gboolean fp_device_supports_identify (FpDevice *device);
|
|
||||||
G_DEPRECATED_FOR (fp_device_get_features)
|
|
||||||
gboolean fp_device_supports_capture (FpDevice *device);
|
|
||||||
G_DEPRECATED_FOR (fp_device_get_features)
|
|
||||||
gboolean fp_device_has_storage (FpDevice *device);
|
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|||||||
@@ -101,7 +101,6 @@ fp_image_device_start_capture_action (FpDevice *device)
|
|||||||
FpImageDevice *self = FP_IMAGE_DEVICE (device);
|
FpImageDevice *self = FP_IMAGE_DEVICE (device);
|
||||||
FpImageDevicePrivate *priv = fp_image_device_get_instance_private (self);
|
FpImageDevicePrivate *priv = fp_image_device_get_instance_private (self);
|
||||||
FpiDeviceAction action;
|
FpiDeviceAction action;
|
||||||
FpiPrintType print_type;
|
|
||||||
|
|
||||||
/* There is just one action that we cannot support out
|
/* There is just one action that we cannot support out
|
||||||
* of the box, which is a capture without first waiting
|
* of the box, which is a capture without first waiting
|
||||||
@@ -125,9 +124,7 @@ fp_image_device_start_capture_action (FpDevice *device)
|
|||||||
FpPrint *enroll_print = NULL;
|
FpPrint *enroll_print = NULL;
|
||||||
|
|
||||||
fpi_device_get_enroll_data (device, &enroll_print);
|
fpi_device_get_enroll_data (device, &enroll_print);
|
||||||
g_object_get (enroll_print, "fpi-type", &print_type, NULL);
|
fpi_print_set_type (enroll_print, FPI_PRINT_NBIS);
|
||||||
if (print_type != FPI_PRINT_NBIS)
|
|
||||||
fpi_print_set_type (enroll_print, FPI_PRINT_NBIS);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
priv->enroll_stage = 0;
|
priv->enroll_stage = 0;
|
||||||
@@ -193,7 +190,9 @@ fp_image_device_constructed (GObject *obj)
|
|||||||
FpImageDevicePrivate *priv = fp_image_device_get_instance_private (self);
|
FpImageDevicePrivate *priv = fp_image_device_get_instance_private (self);
|
||||||
FpImageDeviceClass *cls = FP_IMAGE_DEVICE_GET_CLASS (self);
|
FpImageDeviceClass *cls = FP_IMAGE_DEVICE_GET_CLASS (self);
|
||||||
|
|
||||||
/* Set default threshold. */
|
/* Set default values. */
|
||||||
|
fpi_device_set_nr_enroll_stages (FP_DEVICE (self), IMG_ENROLL_STAGES);
|
||||||
|
|
||||||
priv->bz3_threshold = BOZORTH3_DEFAULT_THRESHOLD;
|
priv->bz3_threshold = BOZORTH3_DEFAULT_THRESHOLD;
|
||||||
if (cls->bz3_threshold > 0)
|
if (cls->bz3_threshold > 0)
|
||||||
priv->bz3_threshold = cls->bz3_threshold;
|
priv->bz3_threshold = cls->bz3_threshold;
|
||||||
@@ -211,9 +210,6 @@ fp_image_device_class_init (FpImageDeviceClass *klass)
|
|||||||
object_class->get_property = fp_image_device_get_property;
|
object_class->get_property = fp_image_device_get_property;
|
||||||
object_class->constructed = fp_image_device_constructed;
|
object_class->constructed = fp_image_device_constructed;
|
||||||
|
|
||||||
/* Set default enroll stage count. */
|
|
||||||
fp_device_class->nr_enroll_stages = IMG_ENROLL_STAGES;
|
|
||||||
|
|
||||||
fp_device_class->open = fp_image_device_open;
|
fp_device_class->open = fp_image_device_open;
|
||||||
fp_device_class->close = fp_image_device_close;
|
fp_device_class->close = fp_image_device_close;
|
||||||
fp_device_class->enroll = fp_image_device_start_capture_action;
|
fp_device_class->enroll = fp_image_device_start_capture_action;
|
||||||
@@ -223,9 +219,6 @@ fp_image_device_class_init (FpImageDeviceClass *klass)
|
|||||||
|
|
||||||
fp_device_class->cancel = fp_image_device_cancel_action;
|
fp_device_class->cancel = fp_image_device_cancel_action;
|
||||||
|
|
||||||
fpi_device_class_auto_initialize_features (fp_device_class);
|
|
||||||
fp_device_class->features |= FP_DEVICE_FEATURE_UPDATE_PRINT;
|
|
||||||
|
|
||||||
/* Default implementations */
|
/* Default implementations */
|
||||||
klass->activate = fp_image_device_default_activate;
|
klass->activate = fp_image_device_default_activate;
|
||||||
klass->deactivate = fp_image_device_default_deactivate;
|
klass->deactivate = fp_image_device_default_deactivate;
|
||||||
|
|||||||
+76
-120
@@ -20,11 +20,9 @@
|
|||||||
|
|
||||||
#define FP_COMPONENT "image"
|
#define FP_COMPONENT "image"
|
||||||
|
|
||||||
#include "fpi-compat.h"
|
|
||||||
#include "fpi-image.h"
|
#include "fpi-image.h"
|
||||||
#include "fpi-log.h"
|
#include "fpi-log.h"
|
||||||
|
|
||||||
#include <config.h>
|
|
||||||
#include <nbis.h>
|
#include <nbis.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -160,65 +158,60 @@ fp_image_init (FpImage *self)
|
|||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
|
GAsyncReadyCallback user_cb;
|
||||||
struct fp_minutiae *minutiae;
|
struct fp_minutiae *minutiae;
|
||||||
guchar *binarized;
|
gint width, height;
|
||||||
|
gdouble ppmm;
|
||||||
FpiImageFlags flags;
|
FpiImageFlags flags;
|
||||||
unsigned char *image;
|
guchar *image;
|
||||||
gboolean image_changed;
|
guchar *binarized;
|
||||||
} DetectMinutiaeNbisData;
|
} DetectMinutiaeData;
|
||||||
|
|
||||||
static void
|
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->minutiae, free_minutiae);
|
||||||
g_clear_pointer (&data->binarized, g_free);
|
g_clear_pointer (&data->binarized, g_free);
|
||||||
|
|
||||||
if (data->image_changed)
|
|
||||||
g_clear_pointer (&data->image, g_free);
|
|
||||||
|
|
||||||
g_free (data);
|
g_free (data);
|
||||||
}
|
}
|
||||||
|
|
||||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC (DetectMinutiaeNbisData, fp_image_detect_minutiae_free)
|
static void
|
||||||
|
fp_image_detect_minutiae_cb (GObject *source_object,
|
||||||
|
GAsyncResult *res,
|
||||||
static gboolean
|
gpointer user_data)
|
||||||
fp_image_detect_minutiae_nbis_finish (FpImage *self,
|
|
||||||
GTask *task,
|
|
||||||
GError **error)
|
|
||||||
{
|
{
|
||||||
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 (!g_task_had_error (task))
|
||||||
|
|
||||||
if (data != NULL)
|
|
||||||
{
|
{
|
||||||
self->flags = data->flags;
|
gint i;
|
||||||
|
image = FP_IMAGE (source_object);
|
||||||
|
|
||||||
if (data->image_changed)
|
image->flags = data->flags;
|
||||||
{
|
|
||||||
g_clear_pointer (&self->data, g_free);
|
|
||||||
self->data = g_steal_pointer (&data->image);
|
|
||||||
}
|
|
||||||
|
|
||||||
g_clear_pointer (&self->binarized, g_free);
|
g_clear_pointer (&image->data, g_free);
|
||||||
self->binarized = g_steal_pointer (&data->binarized);
|
image->data = g_steal_pointer (&data->image);
|
||||||
|
|
||||||
g_clear_pointer (&self->minutiae, g_ptr_array_unref);
|
g_clear_pointer (&image->binarized, g_free);
|
||||||
self->minutiae = g_ptr_array_new_full (data->minutiae->num,
|
image->binarized = g_steal_pointer (&data->binarized);
|
||||||
(GDestroyNotify) free_minutia);
|
|
||||||
|
|
||||||
for (int i = 0; i < data->minutiae->num; i++)
|
g_clear_pointer (&image->minutiae, g_ptr_array_unref);
|
||||||
g_ptr_array_add (self->minutiae,
|
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]));
|
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;
|
data->minutiae->num = 0;
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return FALSE;
|
if (data->user_cb)
|
||||||
|
data->user_cb (source_object, res, user_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -271,83 +264,70 @@ invert_colors (guint8 *data, gint width, gint height)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
fp_image_detect_minutiae_nbis_thread_func (GTask *task,
|
fp_image_detect_minutiae_thread_func (GTask *task,
|
||||||
gpointer source_object,
|
gpointer source_object,
|
||||||
gpointer task_data,
|
gpointer task_data,
|
||||||
GCancellable *cancellable)
|
GCancellable *cancellable)
|
||||||
{
|
{
|
||||||
g_autoptr(GTimer) timer = NULL;
|
g_autoptr(GTimer) timer = NULL;
|
||||||
g_autoptr(DetectMinutiaeNbisData) ret_data = NULL;
|
DetectMinutiaeData *data = task_data;
|
||||||
g_autoptr(GTask) thread_task = g_steal_pointer (&task);
|
struct fp_minutiae *minutiae = NULL;
|
||||||
g_autofree gint *direction_map = NULL;
|
g_autofree gint *direction_map = NULL;
|
||||||
g_autofree gint *low_contrast_map = NULL;
|
g_autofree gint *low_contrast_map = NULL;
|
||||||
g_autofree gint *low_flow_map = NULL;
|
g_autofree gint *low_flow_map = NULL;
|
||||||
g_autofree gint *high_curve_map = NULL;
|
g_autofree gint *high_curve_map = NULL;
|
||||||
g_autofree gint *quality_map = NULL;
|
g_autofree gint *quality_map = NULL;
|
||||||
g_autofree LFSPARMS *lfsparms = NULL;
|
g_autofree guchar *bdata = NULL;
|
||||||
FpImage *self = source_object;
|
|
||||||
FpiImageFlags minutiae_flags;
|
|
||||||
unsigned char *image;
|
|
||||||
gint map_w, map_h;
|
gint map_w, map_h;
|
||||||
gint bw, bh, bd;
|
gint bw, bh, bd;
|
||||||
gint r;
|
gint r;
|
||||||
|
g_autofree LFSPARMS *lfsparms = NULL;
|
||||||
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;
|
|
||||||
|
|
||||||
/* Normalize the image first */
|
/* Normalize the image first */
|
||||||
if (self->flags & FPI_IMAGE_H_FLIPPED)
|
if (data->flags & FPI_IMAGE_H_FLIPPED)
|
||||||
hflip (image, self->width, self->height);
|
hflip (data->image, data->width, data->height);
|
||||||
|
|
||||||
if (self->flags & FPI_IMAGE_V_FLIPPED)
|
if (data->flags & FPI_IMAGE_V_FLIPPED)
|
||||||
vflip (image, self->width, self->height);
|
vflip (data->image, data->width, data->height);
|
||||||
|
|
||||||
if (self->flags & FPI_IMAGE_COLORS_INVERTED)
|
if (data->flags & FPI_IMAGE_COLORS_INVERTED)
|
||||||
invert_colors (image, self->width, self->height);
|
invert_colors (data->image, data->width, data->height);
|
||||||
|
|
||||||
lfsparms = g_memdup2 (&g_lfsparms_V2, sizeof (LFSPARMS));
|
data->flags &= ~(FPI_IMAGE_H_FLIPPED | FPI_IMAGE_V_FLIPPED | FPI_IMAGE_COLORS_INVERTED);
|
||||||
lfsparms->remove_perimeter_pts = minutiae_flags & FPI_IMAGE_PARTIAL ? TRUE : FALSE;
|
|
||||||
|
lfsparms = g_memdup (&g_lfsparms_V2, sizeof (LFSPARMS));
|
||||||
|
lfsparms->remove_perimeter_pts = data->flags & FPI_IMAGE_PARTIAL ? TRUE : FALSE;
|
||||||
|
|
||||||
timer = g_timer_new ();
|
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,
|
&low_contrast_map, &low_flow_map, &high_curve_map,
|
||||||
&map_w, &map_h, &ret_data->binarized, &bw, &bh, &bd,
|
&map_w, &map_h, &bdata, &bw, &bh, &bd,
|
||||||
image, self->width, self->height, 8,
|
data->image, data->width, data->height, 8,
|
||||||
self->ppmm, lfsparms);
|
data->ppmm, lfsparms);
|
||||||
g_timer_stop (timer);
|
g_timer_stop (timer);
|
||||||
fp_dbg ("Minutiae scan completed in %f secs", g_timer_elapsed (timer, NULL));
|
fp_dbg ("Minutiae scan completed in %f secs", g_timer_elapsed (timer, NULL));
|
||||||
|
|
||||||
if (g_task_had_error (thread_task))
|
data->binarized = g_steal_pointer (&bdata);
|
||||||
return;
|
data->minutiae = minutiae;
|
||||||
|
|
||||||
if (r)
|
if (r)
|
||||||
{
|
{
|
||||||
fp_err ("get minutiae failed, code %d", r);
|
fp_err ("get minutiae failed, code %d", r);
|
||||||
g_task_return_new_error (thread_task, G_IO_ERROR,
|
g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_FAILED, "Minutiae scan failed with code %d", r);
|
||||||
G_IO_ERROR_FAILED,
|
g_object_unref (task);
|
||||||
"Minutiae scan failed with code %d", r);
|
|
||||||
return;
|
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");
|
"No minutiae found");
|
||||||
|
g_object_unref (task);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
g_task_return_pointer (thread_task, g_steal_pointer (&ret_data),
|
g_task_return_boolean (task, TRUE);
|
||||||
(GDestroyNotify) fp_image_detect_minutiae_free);
|
g_object_unref (task);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -463,25 +443,21 @@ fp_image_detect_minutiae (FpImage *self,
|
|||||||
GAsyncReadyCallback callback,
|
GAsyncReadyCallback callback,
|
||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
g_autoptr(GTask) task = NULL;
|
GTask *task;
|
||||||
|
DetectMinutiaeData *data = g_new0 (DetectMinutiaeData, 1);
|
||||||
|
|
||||||
g_return_if_fail (FP_IS_IMAGE (self));
|
task = g_task_new (self, cancellable, fp_image_detect_minutiae_cb, user_data);
|
||||||
g_return_if_fail (callback != NULL);
|
|
||||||
|
|
||||||
task = g_task_new (self, cancellable, callback, user_data);
|
data->image = g_malloc (self->width * self->height);
|
||||||
g_task_set_source_tag (task, fp_image_detect_minutiae);
|
memcpy (data->image, self->data, self->width * self->height);
|
||||||
g_task_set_check_cancellable (task, TRUE);
|
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,
|
g_task_set_task_data (task, data, (GDestroyNotify) fp_image_detect_minutiae_free);
|
||||||
FALSE, TRUE))
|
g_task_run_in_thread (task, fp_image_detect_minutiae_thread_func);
|
||||||
{
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -499,27 +475,7 @@ fp_image_detect_minutiae_finish (FpImage *self,
|
|||||||
GAsyncResult *result,
|
GAsyncResult *result,
|
||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
GTask *task;
|
return g_task_propagate_boolean (G_TASK (result), error);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+14
-37
@@ -61,7 +61,6 @@ enum {
|
|||||||
/* Private property*/
|
/* Private property*/
|
||||||
PROP_FPI_TYPE,
|
PROP_FPI_TYPE,
|
||||||
PROP_FPI_DATA,
|
PROP_FPI_DATA,
|
||||||
PROP_FPI_PRINTS,
|
|
||||||
N_PROPS
|
N_PROPS
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -134,10 +133,6 @@ fp_print_get_property (GObject *object,
|
|||||||
g_value_set_variant (value, self->data);
|
g_value_set_variant (value, self->data);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PROP_FPI_PRINTS:
|
|
||||||
g_value_set_pointer (value, self->prints);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
}
|
}
|
||||||
@@ -193,11 +188,6 @@ fp_print_set_property (GObject *object,
|
|||||||
self->data = g_value_dup_variant (value);
|
self->data = g_value_dup_variant (value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PROP_FPI_PRINTS:
|
|
||||||
g_clear_pointer (&self->prints, g_ptr_array_unref);
|
|
||||||
self->prints = g_value_get_pointer (value);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
}
|
}
|
||||||
@@ -309,19 +299,6 @@ fp_print_class_init (FpPrintClass *klass)
|
|||||||
NULL,
|
NULL,
|
||||||
G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE);
|
G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE);
|
||||||
|
|
||||||
/**
|
|
||||||
* FpPrint::fpi-prints: (skip)
|
|
||||||
*
|
|
||||||
* This property is only for internal purposes.
|
|
||||||
*
|
|
||||||
* Stability: private
|
|
||||||
*/
|
|
||||||
properties[PROP_FPI_PRINTS] =
|
|
||||||
g_param_spec_pointer ("fpi-prints",
|
|
||||||
"Prints",
|
|
||||||
"Prints for internal use only",
|
|
||||||
G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE);
|
|
||||||
|
|
||||||
g_object_class_install_properties (object_class, N_PROPS, properties);
|
g_object_class_install_properties (object_class, N_PROPS, properties);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -339,7 +316,7 @@ fp_print_init (FpPrint *self)
|
|||||||
* create a new print, fill in the relevant metadata, and then start
|
* create a new print, fill in the relevant metadata, and then start
|
||||||
* enrollment.
|
* enrollment.
|
||||||
*
|
*
|
||||||
* Returns: (transfer floating): A newly created #FpPrint
|
* Returns: (transfer floating): A newyl created #FpPrint
|
||||||
*/
|
*/
|
||||||
FpPrint *
|
FpPrint *
|
||||||
fp_print_new (FpDevice *device)
|
fp_print_new (FpDevice *device)
|
||||||
@@ -605,7 +582,7 @@ fp_print_equal (FpPrint *self, FpPrint *other)
|
|||||||
if (g_strcmp0 (self->device_id, other->device_id))
|
if (g_strcmp0 (self->device_id, other->device_id))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
if (self->type == FPI_PRINT_RAW)
|
if (self->type == FPI_PRINT_RAW || self->type == FPI_PRINT_SDCP)
|
||||||
{
|
{
|
||||||
return g_variant_equal (self->data, other->data);
|
return g_variant_equal (self->data, other->data);
|
||||||
}
|
}
|
||||||
@@ -721,12 +698,13 @@ fp_print_serialize (FpPrint *print,
|
|||||||
|
|
||||||
result = g_variant_builder_end (&builder);
|
result = g_variant_builder_end (&builder);
|
||||||
|
|
||||||
#if (G_BYTE_ORDER == G_BIG_ENDIAN)
|
if (G_BYTE_ORDER == G_BIG_ENDIAN)
|
||||||
GVariant *tmp;
|
{
|
||||||
tmp = g_variant_byteswap (result);
|
GVariant *tmp;
|
||||||
g_variant_unref (result);
|
tmp = g_variant_byteswap (result);
|
||||||
result = tmp;
|
g_variant_unref (result);
|
||||||
#endif
|
result = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
len = g_variant_get_size (result);
|
len = g_variant_get_size (result);
|
||||||
/* Add 3 bytes of header */
|
/* Add 3 bytes of header */
|
||||||
@@ -799,11 +777,10 @@ fp_print_deserialize (const guchar *data,
|
|||||||
if (!raw_value)
|
if (!raw_value)
|
||||||
goto invalid_format;
|
goto invalid_format;
|
||||||
|
|
||||||
#if (G_BYTE_ORDER == G_BIG_ENDIAN)
|
if (G_BYTE_ORDER == G_BIG_ENDIAN)
|
||||||
value = g_variant_byteswap (raw_value);
|
value = g_variant_byteswap (raw_value);
|
||||||
#else
|
else
|
||||||
value = g_variant_get_normal_form (raw_value);
|
value = g_variant_get_normal_form (raw_value);
|
||||||
#endif
|
|
||||||
|
|
||||||
g_variant_get (value,
|
g_variant_get (value,
|
||||||
"(i&s&sbymsmsi@a{sv}v)",
|
"(i&s&sbymsmsi@a{sv}v)",
|
||||||
@@ -870,7 +847,7 @@ fp_print_deserialize (const guchar *data,
|
|||||||
g_ptr_array_add (result->prints, g_steal_pointer (&xyt));
|
g_ptr_array_add (result->prints, g_steal_pointer (&xyt));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (type == FPI_PRINT_RAW)
|
else if (type == FPI_PRINT_RAW || type == FPI_PRINT_SDCP)
|
||||||
{
|
{
|
||||||
g_autoptr(GVariant) fp_data = g_variant_get_child_value (print_data, 0);
|
g_autoptr(GVariant) fp_data = g_variant_get_child_value (print_data, 0);
|
||||||
|
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ G_BEGIN_DECLS
|
|||||||
G_DECLARE_FINAL_TYPE (FpPrint, fp_print, FP, PRINT, GInitiallyUnowned)
|
G_DECLARE_FINAL_TYPE (FpPrint, fp_print, FP, PRINT, GInitiallyUnowned)
|
||||||
|
|
||||||
#define FP_FINGER_IS_VALID(finger) \
|
#define FP_FINGER_IS_VALID(finger) \
|
||||||
((finger) >= FP_FINGER_FIRST && (finger) <= FP_FINGER_LAST)
|
((finger) >= FP_FINGER_FIRST && (finger) <= FP_FINGER_LAST)
|
||||||
|
|
||||||
#include "fp-device.h"
|
#include "fp-device.h"
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
/*
|
||||||
|
* 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 <fp-device.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#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
|
||||||
+50
-16
@@ -210,36 +210,69 @@ aes_blit_stripe (struct fpi_frame_asmbl_ctx *ctx,
|
|||||||
struct fpi_frame *stripe,
|
struct fpi_frame *stripe,
|
||||||
int x, int y)
|
int x, int y)
|
||||||
{
|
{
|
||||||
unsigned int ix1, iy1;
|
unsigned int ix, iy;
|
||||||
unsigned int fx1, fy1;
|
unsigned int fx, fy;
|
||||||
unsigned int fx, fy, ix, iy;
|
unsigned int width, height;
|
||||||
|
|
||||||
/* Select starting point inside image and frame */
|
/* Find intersection */
|
||||||
if (x < 0)
|
if (x < 0)
|
||||||
{
|
{
|
||||||
ix1 = 0;
|
width = ctx->frame_width + x;
|
||||||
fx1 = -x;
|
ix = 0;
|
||||||
|
fx = -x;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ix1 = x;
|
ix = x;
|
||||||
fx1 = 0;
|
fx = 0;
|
||||||
|
width = ctx->frame_width;
|
||||||
}
|
}
|
||||||
|
if ((ix + width) > img->width)
|
||||||
|
width = img->width - ix;
|
||||||
|
|
||||||
if (y < 0)
|
if (y < 0)
|
||||||
{
|
{
|
||||||
iy1 = 0;
|
iy = 0;
|
||||||
fy1 = -y;
|
fy = -y;
|
||||||
|
height = ctx->frame_height + y;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
iy1 = y;
|
iy = y;
|
||||||
fy1 = 0;
|
fy = 0;
|
||||||
|
height = ctx->frame_height;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (fy = fy1, iy = iy1; fy < ctx->frame_height && iy < img->height; fy++, iy++)
|
if (fx > ctx->frame_width)
|
||||||
for (fx = fx1, ix = ix1; fx < ctx->frame_width && ix < img->width; fx++, ix++)
|
return;
|
||||||
img->data[ix + (iy * img->width)] = ctx->get_pixel (ctx, stripe, fx, fy);
|
|
||||||
|
if (fy > ctx->frame_height)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (ix > img->width)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (iy > img->height)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if ((iy + height) > img->height)
|
||||||
|
height = img->height - iy;
|
||||||
|
|
||||||
|
for (; fy < height; fy++, iy++)
|
||||||
|
{
|
||||||
|
if (x < 0)
|
||||||
|
{
|
||||||
|
ix = 0;
|
||||||
|
fx = -x;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ix = x;
|
||||||
|
fx = 0;
|
||||||
|
}
|
||||||
|
for (; fx < width; fx++, ix++)
|
||||||
|
img->data[ix + (iy * img->width)] = ctx->get_pixel (ctx, stripe, fx, fy);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -265,6 +298,7 @@ fpi_assemble_frames (struct fpi_frame_asmbl_ctx *ctx,
|
|||||||
|
|
||||||
//FIXME g_return_if_fail
|
//FIXME g_return_if_fail
|
||||||
g_return_val_if_fail (stripes != NULL, NULL);
|
g_return_val_if_fail (stripes != NULL, NULL);
|
||||||
|
BUG_ON (ctx->image_width < ctx->frame_width);
|
||||||
|
|
||||||
/* No offset for 1st image */
|
/* No offset for 1st image */
|
||||||
fpi_frame = stripes->data;
|
fpi_frame = stripes->data;
|
||||||
@@ -297,7 +331,7 @@ fpi_assemble_frames (struct fpi_frame_asmbl_ctx *ctx,
|
|||||||
|
|
||||||
/* Assemble stripes */
|
/* Assemble stripes */
|
||||||
y = reverse ? (height - ctx->frame_height) : 0;
|
y = reverse ? (height - ctx->frame_height) : 0;
|
||||||
x = ((int) ctx->image_width - (int) ctx->frame_width) / 2;
|
x = (ctx->image_width - ctx->frame_width) / 2;
|
||||||
|
|
||||||
for (l = stripes; l != NULL; l = l->next)
|
for (l = stripes; l != NULL; l = l->next)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "fp-image.h"
|
#include <fprint.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* fpi_frame:
|
* fpi_frame:
|
||||||
|
|||||||
@@ -1181,7 +1181,7 @@ fpi_byte_reader_dup_string_utf##bits (FpiByteReader * reader, type ** str) \
|
|||||||
*str = NULL; \
|
*str = NULL; \
|
||||||
return FALSE; \
|
return FALSE; \
|
||||||
} \
|
} \
|
||||||
*str = g_memdup2 (reader->data + reader->byte, size); \
|
*str = g_memdup (reader->data + reader->byte, size); \
|
||||||
reader->byte += size; \
|
reader->byte += size; \
|
||||||
return TRUE; \
|
return TRUE; \
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,7 +22,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
#include "fpi-compat.h"
|
|
||||||
#include "fpi-byte-utils.h"
|
#include "fpi-byte-utils.h"
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
@@ -361,7 +360,7 @@ static inline guint8 *
|
|||||||
fpi_byte_reader_dup_data_unchecked (FpiByteReader * reader, guint size)
|
fpi_byte_reader_dup_data_unchecked (FpiByteReader * reader, guint size)
|
||||||
{
|
{
|
||||||
gconstpointer data = fpi_byte_reader_get_data_unchecked (reader, 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 */
|
/* Unchecked variants that should not be used */
|
||||||
@@ -675,6 +674,4 @@ fpi_byte_reader_skip_inline (FpiByteReader * reader, guint nbytes)
|
|||||||
|
|
||||||
#endif /* FPI_BYTE_READER_DISABLE_INLINES */
|
#endif /* FPI_BYTE_READER_DISABLE_INLINES */
|
||||||
|
|
||||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC (FpiByteReader, fpi_byte_reader_free);
|
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|||||||
@@ -75,8 +75,7 @@ fpi_byte_writer_new_with_size (guint size, gboolean fixed)
|
|||||||
FpiByteWriter *ret = fpi_byte_writer_new ();
|
FpiByteWriter *ret = fpi_byte_writer_new ();
|
||||||
|
|
||||||
ret->alloc_size = size;
|
ret->alloc_size = size;
|
||||||
ret->parent.data = g_malloc0 (ret->alloc_size);
|
ret->parent.data = g_malloc (ret->alloc_size);
|
||||||
ret->parent.size = size;
|
|
||||||
ret->fixed = fixed;
|
ret->fixed = fixed;
|
||||||
ret->owned = TRUE;
|
ret->owned = TRUE;
|
||||||
|
|
||||||
@@ -143,8 +142,7 @@ fpi_byte_writer_init_with_size (FpiByteWriter * writer, guint size,
|
|||||||
|
|
||||||
fpi_byte_writer_init (writer);
|
fpi_byte_writer_init (writer);
|
||||||
|
|
||||||
writer->parent.data = g_malloc0 (size);
|
writer->parent.data = g_malloc (size);
|
||||||
writer->parent.size = size;
|
|
||||||
writer->alloc_size = size;
|
writer->alloc_size = size;
|
||||||
writer->fixed = fixed;
|
writer->fixed = fixed;
|
||||||
writer->owned = TRUE;
|
writer->owned = TRUE;
|
||||||
@@ -211,9 +209,10 @@ fpi_byte_writer_reset_and_get_data (FpiByteWriter * writer)
|
|||||||
|
|
||||||
g_return_val_if_fail (writer != NULL, NULL);
|
g_return_val_if_fail (writer != NULL, NULL);
|
||||||
|
|
||||||
data = (guint8 *) g_steal_pointer (&writer->parent.data);
|
data = (guint8 *) writer->parent.data;
|
||||||
if (!writer->owned)
|
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);
|
fpi_byte_writer_reset (writer);
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
|
|||||||
@@ -111,17 +111,6 @@ fpi_byte_writer_set_pos (FpiByteWriter *writer, guint pos)
|
|||||||
return fpi_byte_reader_set_pos (FPI_BYTE_READER (writer), 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
|
static inline guint
|
||||||
fpi_byte_writer_get_size (const FpiByteWriter *writer)
|
fpi_byte_writer_get_size (const FpiByteWriter *writer)
|
||||||
{
|
{
|
||||||
@@ -418,7 +407,4 @@ fpi_byte_writer_fill_inline (FpiByteWriter * writer, guint8 value, guint size)
|
|||||||
|
|
||||||
#endif
|
#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
|
G_END_DECLS
|
||||||
|
|||||||
@@ -20,6 +20,25 @@
|
|||||||
|
|
||||||
#include <glib-object.h>
|
#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)
|
#if __GNUC__ > 10 || (__GNUC__ == 10 && __GNUC_MINOR__ >= 1)
|
||||||
#define FP_GNUC_ACCESS(m, p, s) __attribute__((access (m, p, s)))
|
#define FP_GNUC_ACCESS(m, p, s) __attribute__((access (m, p, s)))
|
||||||
#else
|
#else
|
||||||
|
|||||||
+76
-795
File diff suppressed because it is too large
Load Diff
@@ -24,18 +24,6 @@
|
|||||||
#include "fp-image.h"
|
#include "fp-image.h"
|
||||||
#include "fpi-print.h"
|
#include "fpi-print.h"
|
||||||
|
|
||||||
/**
|
|
||||||
* FpiDeviceUdevSubtypeFlags:
|
|
||||||
* @FPI_DEVICE_UDEV_SUBTYPE_SPIDEV: The device requires an spidev node
|
|
||||||
* @FPI_DEVICE_UDEV_SUBTYPE_HIDRAW: The device requires a hidraw node
|
|
||||||
*
|
|
||||||
* Bitfield of required hardware resources for a udev-backed device.
|
|
||||||
*/
|
|
||||||
typedef enum {
|
|
||||||
FPI_DEVICE_UDEV_SUBTYPE_SPIDEV = 1 << 0,
|
|
||||||
FPI_DEVICE_UDEV_SUBTYPE_HIDRAW = 1 << 1,
|
|
||||||
} FpiDeviceUdevSubtypeFlags;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* FpIdEntry:
|
* FpIdEntry:
|
||||||
*
|
*
|
||||||
@@ -55,16 +43,6 @@ struct _FpIdEntry
|
|||||||
guint vid;
|
guint vid;
|
||||||
};
|
};
|
||||||
const gchar *virtual_envvar;
|
const gchar *virtual_envvar;
|
||||||
struct
|
|
||||||
{
|
|
||||||
FpiDeviceUdevSubtypeFlags udev_types;
|
|
||||||
const gchar *spi_acpi_id;
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
guint pid;
|
|
||||||
guint vid;
|
|
||||||
} hid_id;
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
guint64 driver_data;
|
guint64 driver_data;
|
||||||
};
|
};
|
||||||
@@ -76,16 +54,10 @@ struct _FpIdEntry
|
|||||||
* @full_name: Human readable description of the driver
|
* @full_name: Human readable description of the driver
|
||||||
* @type: The type of driver
|
* @type: The type of driver
|
||||||
* @id_table: The table of IDs to bind the driver to
|
* @id_table: The table of IDs to bind the driver to
|
||||||
* @features: The features the device supports, it can be initialized using
|
|
||||||
* fpi_device_class_auto_initialize_features() on @class_init.
|
|
||||||
* @nr_enroll_stages: The number of enroll stages supported devices need; use
|
* @nr_enroll_stages: The number of enroll stages supported devices need; use
|
||||||
* fpi_device_set_nr_enroll_stages() from @probe if this is dynamic.
|
* fpi_device_set_nr_enroll_stages() from @probe if this is dynamic.
|
||||||
* @scan_type: The scan type of supported devices; use
|
* @scan_type: The scan type of supported devices; use
|
||||||
* fpi_device_set_scan_type() from @probe if this is dynamic.
|
* fpi_device_set_scan_type() from @probe if this is dynamic.
|
||||||
* @temp_hot_seconds: Assumed time in seconds for the device to become too hot
|
|
||||||
* after being mostly cold. Set to -1 if the device can be always-on.
|
|
||||||
* @temp_cold_seconds: Assumed time in seconds for the device to be mostly cold
|
|
||||||
* after having been too hot to operate.
|
|
||||||
* @usb_discover: Class method to check whether a USB device is supported by
|
* @usb_discover: Class method to check whether a USB device is supported by
|
||||||
* the driver. Should return 0 if the device is unsupported and a positive
|
* the driver. Should return 0 if the device is unsupported and a positive
|
||||||
* score otherwise. The default score is 50 and the driver with the highest
|
* score otherwise. The default score is 50 and the driver with the highest
|
||||||
@@ -105,13 +77,8 @@ struct _FpIdEntry
|
|||||||
* @capture: Start a capture operation
|
* @capture: Start a capture operation
|
||||||
* @list: List prints stored on the device
|
* @list: List prints stored on the device
|
||||||
* @delete: Delete a print from the device
|
* @delete: Delete a print from the device
|
||||||
* @clear_storage: Delete all prints from the device
|
|
||||||
* @cancel: Called on cancellation, this is a convenience to not need to handle
|
* @cancel: Called on cancellation, this is a convenience to not need to handle
|
||||||
* the #GCancellable directly by using fpi_device_get_cancellable().
|
* the #GCancellable directly by using fpi_device_get_cancellable().
|
||||||
* @suspend: Called when an interactive action is running (ENROLL, VERIFY,
|
|
||||||
* IDENTIFY or CAPTURE) and the system is about to go into suspend.
|
|
||||||
* @resume: Called to resume an ongoing interactive action after the system has
|
|
||||||
* resumed from suspend.
|
|
||||||
*
|
*
|
||||||
* NOTE: If your driver is image based, then you should subclass #FpImageDevice
|
* NOTE: If your driver is image based, then you should subclass #FpImageDevice
|
||||||
* instead. #FpImageDevice based drivers use a different way of interacting
|
* instead. #FpImageDevice based drivers use a different way of interacting
|
||||||
@@ -130,9 +97,6 @@ struct _FpIdEntry
|
|||||||
* operation (i.e. any operation that requires capturing). It is entirely fine
|
* operation (i.e. any operation that requires capturing). It is entirely fine
|
||||||
* to ignore cancellation requests for short operations (e.g. open/close).
|
* to ignore cancellation requests for short operations (e.g. open/close).
|
||||||
*
|
*
|
||||||
* Note that @cancel, @suspend and @resume will not be called while the device
|
|
||||||
* is within a fpi_device_critical_enter()/fpi_device_critical_leave() block.
|
|
||||||
*
|
|
||||||
* This API is solely intended for drivers. It is purely internal and neither
|
* This API is solely intended for drivers. It is purely internal and neither
|
||||||
* API nor ABI stable.
|
* API nor ABI stable.
|
||||||
*/
|
*/
|
||||||
@@ -147,16 +111,11 @@ struct _FpDeviceClass
|
|||||||
const gchar *full_name;
|
const gchar *full_name;
|
||||||
FpDeviceType type;
|
FpDeviceType type;
|
||||||
const FpIdEntry *id_table;
|
const FpIdEntry *id_table;
|
||||||
FpDeviceFeature features;
|
|
||||||
|
|
||||||
/* Defaults for device properties */
|
/* Defaults for device properties */
|
||||||
gint nr_enroll_stages;
|
gint nr_enroll_stages;
|
||||||
FpScanType scan_type;
|
FpScanType scan_type;
|
||||||
|
|
||||||
/* Simple device temperature model constants */
|
|
||||||
gint32 temp_hot_seconds;
|
|
||||||
gint32 temp_cold_seconds;
|
|
||||||
|
|
||||||
/* Callbacks */
|
/* Callbacks */
|
||||||
gint (*usb_discover) (GUsbDevice *usb_device);
|
gint (*usb_discover) (GUsbDevice *usb_device);
|
||||||
void (*probe) (FpDevice *device);
|
void (*probe) (FpDevice *device);
|
||||||
@@ -168,15 +127,10 @@ struct _FpDeviceClass
|
|||||||
void (*capture) (FpDevice *device);
|
void (*capture) (FpDevice *device);
|
||||||
void (*list) (FpDevice *device);
|
void (*list) (FpDevice *device);
|
||||||
void (*delete) (FpDevice * device);
|
void (*delete) (FpDevice * device);
|
||||||
void (*clear_storage) (FpDevice * device);
|
|
||||||
|
|
||||||
void (*cancel) (FpDevice *device);
|
void (*cancel) (FpDevice *device);
|
||||||
void (*suspend) (FpDevice *device);
|
|
||||||
void (*resume) (FpDevice *device);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void fpi_device_class_auto_initialize_features (FpDeviceClass *device_class);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* FpTimeoutFunc:
|
* FpTimeoutFunc:
|
||||||
* @device: The #FpDevice passed to fpi_device_add_timeout()
|
* @device: The #FpDevice passed to fpi_device_add_timeout()
|
||||||
@@ -199,7 +153,6 @@ typedef void (*FpTimeoutFunc) (FpDevice *device,
|
|||||||
* @FPI_DEVICE_ACTION_CAPTURE: Device is currently capturing an image.
|
* @FPI_DEVICE_ACTION_CAPTURE: Device is currently capturing an image.
|
||||||
* @FPI_DEVICE_ACTION_LIST: Device stored prints are being queried.
|
* @FPI_DEVICE_ACTION_LIST: Device stored prints are being queried.
|
||||||
* @FPI_DEVICE_ACTION_DELETE: Device stored print is being deleted.
|
* @FPI_DEVICE_ACTION_DELETE: Device stored print is being deleted.
|
||||||
* @FPI_DEVICE_ACTION_CLEAR_STORAGE: Device stored prints are being deleted.
|
|
||||||
*
|
*
|
||||||
* Current active action of the device. A driver can retrieve the action.
|
* Current active action of the device. A driver can retrieve the action.
|
||||||
*/
|
*/
|
||||||
@@ -214,13 +167,10 @@ typedef enum {
|
|||||||
FPI_DEVICE_ACTION_CAPTURE,
|
FPI_DEVICE_ACTION_CAPTURE,
|
||||||
FPI_DEVICE_ACTION_LIST,
|
FPI_DEVICE_ACTION_LIST,
|
||||||
FPI_DEVICE_ACTION_DELETE,
|
FPI_DEVICE_ACTION_DELETE,
|
||||||
FPI_DEVICE_ACTION_CLEAR_STORAGE,
|
|
||||||
} FpiDeviceAction;
|
} FpiDeviceAction;
|
||||||
|
|
||||||
GUsbDevice *fpi_device_get_usb_device (FpDevice *device);
|
GUsbDevice *fpi_device_get_usb_device (FpDevice *device);
|
||||||
const gchar *fpi_device_get_virtual_env (FpDevice *device);
|
const gchar *fpi_device_get_virtual_env (FpDevice *device);
|
||||||
gpointer fpi_device_get_udev_data (FpDevice *device,
|
|
||||||
FpiDeviceUdevSubtypeFlags subtype);
|
|
||||||
//const gchar *fpi_device_get_spi_dev (FpDevice *device);
|
//const gchar *fpi_device_get_spi_dev (FpDevice *device);
|
||||||
|
|
||||||
|
|
||||||
@@ -266,16 +216,9 @@ void fpi_device_set_nr_enroll_stages (FpDevice *device,
|
|||||||
void fpi_device_set_scan_type (FpDevice *device,
|
void fpi_device_set_scan_type (FpDevice *device,
|
||||||
FpScanType scan_type);
|
FpScanType scan_type);
|
||||||
|
|
||||||
void fpi_device_update_features (FpDevice *device,
|
|
||||||
FpDeviceFeature update,
|
|
||||||
FpDeviceFeature value);
|
|
||||||
|
|
||||||
void fpi_device_action_error (FpDevice *device,
|
void fpi_device_action_error (FpDevice *device,
|
||||||
GError *error);
|
GError *error);
|
||||||
|
|
||||||
void fpi_device_critical_enter (FpDevice *device);
|
|
||||||
void fpi_device_critical_leave (FpDevice *device);
|
|
||||||
|
|
||||||
void fpi_device_probe_complete (FpDevice *device,
|
void fpi_device_probe_complete (FpDevice *device,
|
||||||
const gchar *device_id,
|
const gchar *device_id,
|
||||||
const gchar *device_name,
|
const gchar *device_name,
|
||||||
@@ -299,12 +242,6 @@ void fpi_device_delete_complete (FpDevice *device,
|
|||||||
void fpi_device_list_complete (FpDevice *device,
|
void fpi_device_list_complete (FpDevice *device,
|
||||||
GPtrArray *prints,
|
GPtrArray *prints,
|
||||||
GError *error);
|
GError *error);
|
||||||
void fpi_device_clear_storage_complete (FpDevice *device,
|
|
||||||
GError *error);
|
|
||||||
void fpi_device_suspend_complete (FpDevice *device,
|
|
||||||
GError *error);
|
|
||||||
void fpi_device_resume_complete (FpDevice *device,
|
|
||||||
GError *error);
|
|
||||||
|
|
||||||
void fpi_device_enroll_progress (FpDevice *device,
|
void fpi_device_enroll_progress (FpDevice *device,
|
||||||
gint completed_stages,
|
gint completed_stages,
|
||||||
|
|||||||
@@ -306,7 +306,7 @@ fpi_image_device_minutiae_detected (GObject *source_object, GAsyncResult *res, g
|
|||||||
g_steal_pointer (&print), error);
|
g_steal_pointer (&print), error);
|
||||||
|
|
||||||
/* Start another scan or deactivate. */
|
/* Start another scan or deactivate. */
|
||||||
if (priv->enroll_stage == fp_device_get_nr_enroll_stages (device))
|
if (priv->enroll_stage == IMG_ENROLL_STAGES)
|
||||||
{
|
{
|
||||||
fp_image_device_maybe_complete_action (self, g_steal_pointer (&error));
|
fp_image_device_maybe_complete_action (self, g_steal_pointer (&error));
|
||||||
fpi_image_device_deactivate (self, FALSE);
|
fpi_image_device_deactivate (self, FALSE);
|
||||||
@@ -565,7 +565,7 @@ fpi_image_device_retry_scan (FpImageDevice *self, FpDeviceRetry retry)
|
|||||||
/**
|
/**
|
||||||
* fpi_image_device_session_error:
|
* fpi_image_device_session_error:
|
||||||
* @self: a #FpImageDevice imaging fingerprint device
|
* @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
|
* Report an error while interacting with the device. This effectively
|
||||||
* aborts the current ongoing action. Note that doing so will result in
|
* aborts the current ongoing action. Note that doing so will result in
|
||||||
@@ -624,7 +624,7 @@ fpi_image_device_session_error (FpImageDevice *self, GError *error)
|
|||||||
/**
|
/**
|
||||||
* fpi_image_device_activate_complete:
|
* fpi_image_device_activate_complete:
|
||||||
* @self: a #FpImageDevice imaging fingerprint device
|
* @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.
|
* Reports completion of device activation.
|
||||||
*/
|
*/
|
||||||
@@ -663,7 +663,7 @@ fpi_image_device_activate_complete (FpImageDevice *self, GError *error)
|
|||||||
/**
|
/**
|
||||||
* fpi_image_device_deactivate_complete:
|
* fpi_image_device_deactivate_complete:
|
||||||
* @self: a #FpImageDevice imaging fingerprint device
|
* @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.
|
* Reports completion of device deactivation.
|
||||||
*/
|
*/
|
||||||
@@ -690,7 +690,7 @@ fpi_image_device_deactivate_complete (FpImageDevice *self, GError *error)
|
|||||||
/**
|
/**
|
||||||
* fpi_image_device_open_complete:
|
* fpi_image_device_open_complete:
|
||||||
* @self: a #FpImageDevice imaging fingerprint device
|
* @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.
|
* Reports completion of open operation.
|
||||||
*/
|
*/
|
||||||
@@ -718,7 +718,7 @@ fpi_image_device_open_complete (FpImageDevice *self, GError *error)
|
|||||||
/**
|
/**
|
||||||
* fpi_image_device_close_complete:
|
* fpi_image_device_close_complete:
|
||||||
* @self: a #FpImageDevice imaging fingerprint device
|
* @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.
|
* Reports completion of close operation.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -24,9 +24,8 @@
|
|||||||
#include "fpi-log.h"
|
#include "fpi-log.h"
|
||||||
|
|
||||||
#include <nbis.h>
|
#include <nbis.h>
|
||||||
#include <config.h>
|
|
||||||
|
|
||||||
#ifdef HAVE_PIXMAN
|
#if HAVE_PIXMAN
|
||||||
#include <pixman.h>
|
#include <pixman.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -108,12 +107,12 @@ fpi_mean_sq_diff_norm (const guint8 *buf1,
|
|||||||
return res / size;
|
return res / size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if HAVE_PIXMAN
|
||||||
FpImage *
|
FpImage *
|
||||||
fpi_image_resize (FpImage *orig_img,
|
fpi_image_resize (FpImage *orig_img,
|
||||||
guint w_factor,
|
guint w_factor,
|
||||||
guint h_factor)
|
guint h_factor)
|
||||||
{
|
{
|
||||||
#ifdef HAVE_PIXMAN
|
|
||||||
int new_width = orig_img->width * w_factor;
|
int new_width = orig_img->width * w_factor;
|
||||||
int new_height = orig_img->height * h_factor;
|
int new_height = orig_img->height * h_factor;
|
||||||
pixman_image_t *orig, *resized;
|
pixman_image_t *orig, *resized;
|
||||||
@@ -146,9 +145,5 @@ fpi_image_resize (FpImage *orig_img,
|
|||||||
pixman_image_unref (resized);
|
pixman_image_unref (resized);
|
||||||
|
|
||||||
return newimg;
|
return newimg;
|
||||||
#else
|
|
||||||
fp_err ("Libfprint compiled without pixman support, impossible to resize");
|
|
||||||
|
|
||||||
return g_object_ref (orig_img);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|||||||
@@ -20,6 +20,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <config.h>
|
||||||
#include "fp-image.h"
|
#include "fp-image.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -33,7 +34,6 @@
|
|||||||
* rely on the image to be normalized by libfprint before further processing.
|
* rely on the image to be normalized by libfprint before further processing.
|
||||||
*/
|
*/
|
||||||
typedef enum {
|
typedef enum {
|
||||||
FPI_IMAGE_NONE = 0,
|
|
||||||
FPI_IMAGE_V_FLIPPED = 1 << 0,
|
FPI_IMAGE_V_FLIPPED = 1 << 0,
|
||||||
FPI_IMAGE_H_FLIPPED = 1 << 1,
|
FPI_IMAGE_H_FLIPPED = 1 << 1,
|
||||||
FPI_IMAGE_COLORS_INVERTED = 1 << 2,
|
FPI_IMAGE_COLORS_INVERTED = 1 << 2,
|
||||||
@@ -68,8 +68,7 @@ struct _FpImage
|
|||||||
guint8 *binarized;
|
guint8 *binarized;
|
||||||
|
|
||||||
GPtrArray *minutiae;
|
GPtrArray *minutiae;
|
||||||
|
guint ref_count;
|
||||||
gboolean detection_in_progress;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
gint fpi_std_sq_dev (const guint8 *buf,
|
gint fpi_std_sq_dev (const guint8 *buf,
|
||||||
@@ -78,6 +77,8 @@ gint fpi_mean_sq_diff_norm (const guint8 *buf1,
|
|||||||
const guint8 *buf2,
|
const guint8 *buf2,
|
||||||
gint size);
|
gint size);
|
||||||
|
|
||||||
|
#if HAVE_PIXMAN
|
||||||
FpImage *fpi_image_resize (FpImage *orig,
|
FpImage *fpi_image_resize (FpImage *orig,
|
||||||
guint w_factor,
|
guint w_factor,
|
||||||
guint h_factor);
|
guint h_factor);
|
||||||
|
#endif
|
||||||
|
|||||||
+6
-6
@@ -80,12 +80,12 @@
|
|||||||
* Uses fp_err() to print an error if the @condition is true.
|
* Uses fp_err() to print an error if the @condition is true.
|
||||||
*/
|
*/
|
||||||
#define BUG_ON(condition) G_STMT_START \
|
#define BUG_ON(condition) G_STMT_START \
|
||||||
if (condition) { \
|
if (condition) { \
|
||||||
char *s; \
|
char *s; \
|
||||||
s = g_strconcat ("BUG: (", #condition, ")", NULL); \
|
s = g_strconcat ("BUG: (", #condition, ")", NULL); \
|
||||||
fp_err ("%s: %s() %s:%d", s, G_STRFUNC, __FILE__, __LINE__); \
|
fp_err ("%s: %s() %s:%d", s, G_STRFUNC, __FILE__, __LINE__); \
|
||||||
g_free (s); \
|
g_free (s); \
|
||||||
} G_STMT_END
|
} G_STMT_END
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* BUG:
|
* BUG:
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ fpi_print_add_print (FpPrint *print, FpPrint *add)
|
|||||||
g_return_if_fail (add->type == FPI_PRINT_NBIS);
|
g_return_if_fail (add->type == FPI_PRINT_NBIS);
|
||||||
|
|
||||||
g_assert (add->prints->len == 1);
|
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)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -11,11 +11,13 @@ G_BEGIN_DECLS
|
|||||||
* @FPI_PRINT_UNDEFINED: Undefined type, this happens prior to enrollment
|
* @FPI_PRINT_UNDEFINED: Undefined type, this happens prior to enrollment
|
||||||
* @FPI_PRINT_RAW: A raw print where the data is directly compared
|
* @FPI_PRINT_RAW: A raw print where the data is directly compared
|
||||||
* @FPI_PRINT_NBIS: NBIS minutiae comparison
|
* @FPI_PRINT_NBIS: NBIS minutiae comparison
|
||||||
|
* @FPI_PRINT_SDCP: Print from an SDCP conforming device
|
||||||
*/
|
*/
|
||||||
typedef enum {
|
typedef enum {
|
||||||
FPI_PRINT_UNDEFINED = 0,
|
FPI_PRINT_UNDEFINED = 0,
|
||||||
FPI_PRINT_RAW,
|
FPI_PRINT_RAW,
|
||||||
FPI_PRINT_NBIS,
|
FPI_PRINT_NBIS,
|
||||||
|
FPI_PRINT_SDCP,
|
||||||
} FpiPrintType;
|
} FpiPrintType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -42,9 +44,9 @@ gboolean fpi_print_add_from_image (FpPrint *print,
|
|||||||
FpImage *image,
|
FpImage *image,
|
||||||
GError **error);
|
GError **error);
|
||||||
|
|
||||||
FpiMatchResult fpi_print_bz3_match (FpPrint *temp,
|
FpiMatchResult fpi_print_bz3_match (FpPrint * template,
|
||||||
FpPrint *print,
|
FpPrint * print,
|
||||||
gint bz3_threshold,
|
gint bz3_threshold,
|
||||||
GError **error);
|
GError **error);
|
||||||
|
|
||||||
/* Helpers to encode metadata into user ID strings. */
|
/* Helpers to encode metadata into user ID strings. */
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user