mirror of
https://gitlab.freedesktop.org/libfprint/libfprint.git
synced 2025-11-15 07:38:12 +00:00
Compare commits
18 Commits
9ec4f187b8
...
benzea/add
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3f13ddc40d | ||
|
|
e0f081c6e3 | ||
|
|
ae1fb4094b | ||
|
|
13350e05a2 | ||
|
|
3ea9cc90fe | ||
|
|
e862e8e881 | ||
|
|
60f5cd650a | ||
|
|
7ff36888b7 | ||
|
|
e3043123f5 | ||
|
|
77400b7a60 | ||
|
|
8d83e5eb38 | ||
|
|
e59d5451cc | ||
|
|
798bc4ee1e | ||
|
|
0e732dbafa | ||
|
|
84112abc71 | ||
|
|
c221c6b63e | ||
|
|
6e28b9a8c4 | ||
|
|
e5589a0ec2 |
263
.gitlab-ci.yml
263
.gitlab-ci.yml
@@ -1,74 +1,49 @@
|
|||||||
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/71e636e012ae0ab04c5e0fe40ca73ada91ae6bde/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: 41
|
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'
|
|
||||||
- if: $CI_PIPELINE_SOURCE == 'schedule'
|
|
||||||
- if: $CI_PROJECT_NAMESPACE == 'libfprint' && $LIBFPRINT_CI_ACTION != ''
|
|
||||||
|
|
||||||
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 openssl
|
# 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:
|
||||||
- ./.ci/check-abi ${LAST_ABI_BREAK} $(git rev-parse HEAD)
|
- ./.ci/check-abi ${LAST_ABI_BREAK} $(git rev-parse HEAD)
|
||||||
|
|
||||||
.standard_job:
|
|
||||||
rules:
|
|
||||||
- when: on_success
|
|
||||||
- if: $CI_PIPELINE_SOURCE == "schedule"
|
|
||||||
when: never
|
|
||||||
|
|
||||||
build:
|
build:
|
||||||
stage: build
|
stage: build
|
||||||
extends:
|
except:
|
||||||
- .standard_job
|
variables:
|
||||||
|
- $CI_PIPELINE_SOURCE == "schedule"
|
||||||
variables:
|
variables:
|
||||||
driver: virtual_image
|
driver: virtual_image
|
||||||
<<: *build_one_driver
|
<<: *build_one_driver
|
||||||
@@ -77,220 +52,114 @@ 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:
|
||||||
stage: test
|
stage: test
|
||||||
extends:
|
except:
|
||||||
- .standard_job
|
variables:
|
||||||
|
- $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
|
||||||
- ninja -C _build coverage || true
|
- meson test -C _build --verbose --no-stdsplit --timeout-multiplier 3
|
||||||
- cat _build/meson-logs/coverage.txt || true
|
- ninja -C _build coverage
|
||||||
|
- 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+\%)$/'
|
||||||
|
|
||||||
test_valgrind:
|
test_valgrind:
|
||||||
stage: test
|
stage: test
|
||||||
extends:
|
except:
|
||||||
- .standard_job
|
variables:
|
||||||
|
- $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_asan:
|
|
||||||
stage: test
|
|
||||||
extends:
|
|
||||||
- .standard_job
|
|
||||||
script:
|
|
||||||
- meson setup _build -Ddrivers=all -Db_sanitize=address,undefined
|
|
||||||
- meson test -C _build --print-errorlogs --no-stdsplit
|
|
||||||
artifacts:
|
|
||||||
reports:
|
|
||||||
junit: "_build/meson-logs/testlog.junit.xml"
|
|
||||||
expose_as: 'Sanitizers test logs'
|
|
||||||
when: always
|
|
||||||
paths:
|
|
||||||
- _build/meson-logs
|
|
||||||
- _build/meson-logs/testlog.txt
|
|
||||||
expire_in: 1 week
|
|
||||||
|
|
||||||
test_installed:
|
|
||||||
stage: test
|
|
||||||
extends:
|
|
||||||
- .standard_job
|
|
||||||
script:
|
|
||||||
- meson setup _build --prefix=/usr -Ddrivers=all
|
|
||||||
- meson install -C _build
|
|
||||||
- mv _build _build_dir
|
|
||||||
- rm -rf tests
|
|
||||||
- gnome-desktop-testing-runner --list libfprint-2
|
|
||||||
- gnome-desktop-testing-runner libfprint-2
|
|
||||||
--report-directory=_installed-tests-report/failed/
|
|
||||||
--log-directory=_installed-tests-report/logs/
|
|
||||||
--parallel=0
|
|
||||||
artifacts:
|
|
||||||
expose_as: 'GNOME Tests Runner logs'
|
|
||||||
when: always
|
|
||||||
paths:
|
|
||||||
- _build_dir/meson-logs
|
|
||||||
- _installed-tests-report
|
|
||||||
expire_in: 1 week
|
|
||||||
|
|
||||||
|
|
||||||
test_scan_build:
|
test_scan_build:
|
||||||
stage: test
|
stage: test
|
||||||
extends:
|
except:
|
||||||
- .standard_job
|
variables:
|
||||||
|
- $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
|
||||||
|
|
||||||
test_indent:
|
test_indent:
|
||||||
stage: check-source
|
stage: check-source
|
||||||
extends:
|
except:
|
||||||
- .standard_job
|
variables:
|
||||||
|
- $CI_PIPELINE_SOURCE == "schedule"
|
||||||
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 ."
|
||||||
rules:
|
|
||||||
- changes:
|
|
||||||
compare_to: 'refs/heads/master'
|
|
||||||
paths:
|
|
||||||
- '**/*.c'
|
|
||||||
- '**/*.h'
|
|
||||||
|
|
||||||
test_unsupported_list:
|
test_unsupported_list:
|
||||||
stage: check-source
|
stage: check-source
|
||||||
extends:
|
except:
|
||||||
- .standard_job
|
variables:
|
||||||
|
- $CI_PIPELINE_SOURCE == "schedule"
|
||||||
allow_failure: true
|
allow_failure: true
|
||||||
script:
|
script:
|
||||||
- tests/hwdb-check-unsupported.py
|
- tests/hwdb-check-unsupported.py
|
||||||
|
|
||||||
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 == "schedule" && $CRON_TASK == "BUILD_CI_IMAGES"
|
||||||
variables:
|
variables:
|
||||||
GIT_STRATEGY: none # no need to pull the whole tree for rebuilding the image
|
GIT_STRATEGY: none # no need to pull the whole tree for rebuilding the image
|
||||||
# a list of packages to install
|
# a list of packages to install; we only include mbedtls here
|
||||||
FDO_DISTRIBUTION_PACKAGES:
|
FDO_DISTRIBUTION_PACKAGES: $LIBFPRINT_DEPENDENCIES mbedtls-devel
|
||||||
$LIBFPRINT_DEPENDENCIES
|
|
||||||
vala
|
|
||||||
libpcap-devel
|
|
||||||
libudev-devel
|
|
||||||
FDO_DISTRIBUTION_EXEC: |
|
FDO_DISTRIBUTION_EXEC: |
|
||||||
$LIBFPRINT_EXEC
|
cd /tmp
|
||||||
rules:
|
mkdir -p /usr/local/bin
|
||||||
- when: never
|
git clone https://github.com/benzea/SecureDeviceConnectionProtocol.git
|
||||||
|
# Don't bother with cmake
|
||||||
.container_fedora_build_forced:
|
gcc -l mbedcrypto -I SecureDeviceConnectionProtocol/src/include \
|
||||||
variables:
|
SecureDeviceConnectionProtocol/src/test/virt_device.c \
|
||||||
FDO_FORCE_REBUILD: 1
|
SecureDeviceConnectionProtocol/src/client/client.c \
|
||||||
|
SecureDeviceConnectionProtocol/src/test/helpers.c \
|
||||||
container_fedora_build_schedule:
|
SecureDeviceConnectionProtocol/src/test/testkeys.c \
|
||||||
extends:
|
-o /usr/local/bin/sdcp_virt_device
|
||||||
- .container_fedora_build_base
|
rm -rf SecureDeviceConnectionProtocol
|
||||||
- .container_fedora_build_forced
|
|
||||||
rules:
|
|
||||||
- if: $CI_PIPELINE_SOURCE == "schedule" && $CRON_TASK == "BUILD_CI_IMAGES"
|
|
||||||
when: always
|
|
||||||
|
|
||||||
container_fedora_build_manual:
|
|
||||||
extends:
|
|
||||||
- .container_fedora_build_base
|
|
||||||
- .container_fedora_build_forced
|
|
||||||
rules:
|
|
||||||
- if: $LIBFPRINT_CI_ACTION == "build-image"
|
|
||||||
when: always
|
|
||||||
|
|
||||||
container_fedora_build_on_deps_changed:
|
|
||||||
extends: .container_fedora_build_base
|
|
||||||
rules:
|
|
||||||
- if: $CI_PROJECT_NAMESPACE == "libfprint" && $CI_PIPELINE_SOURCE != "schedule"
|
|
||||||
changes:
|
|
||||||
compare_to: 'refs/heads/master'
|
|
||||||
paths:
|
|
||||||
- '.gitlab-ci/libfprint-image-variables.yaml'
|
|
||||||
- '.gitlab-ci/libfprint-templates.yaml'
|
|
||||||
|
|
||||||
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 && $CI_PIPELINE_SOURCE == "push"
|
|
||||||
|
|||||||
@@ -1,2 +0,0 @@
|
|||||||
variables:
|
|
||||||
LIBFPRINT_IMAGE_TAG: v6
|
|
||||||
@@ -1,11 +1,6 @@
|
|||||||
# Bump image version on .gitlab-ci/libfprint-image-variables.yaml to trigger
|
|
||||||
# a rebuild on changes to this file
|
|
||||||
|
|
||||||
.libfprint_common_variables:
|
.libfprint_common_variables:
|
||||||
LIBFPRINT_DEPENDENCIES:
|
LIBFPRINT_DEPENDENCIES:
|
||||||
appstream
|
|
||||||
doxygen
|
doxygen
|
||||||
dnf-plugins-core
|
|
||||||
flatpak-builder
|
flatpak-builder
|
||||||
gcc
|
gcc
|
||||||
gcc-c++
|
gcc-c++
|
||||||
@@ -14,18 +9,14 @@
|
|||||||
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
|
||||||
libasan
|
|
||||||
libgusb-devel
|
libgusb-devel
|
||||||
libgudev-devel
|
|
||||||
libubsan
|
|
||||||
libX11-devel
|
libX11-devel
|
||||||
libXv-devel
|
libXv-devel
|
||||||
meson
|
meson
|
||||||
openssl-devel
|
nss-devel
|
||||||
pixman-devel
|
pixman-devel
|
||||||
python3-cairo
|
python3-cairo
|
||||||
python3-gobject
|
python3-gobject
|
||||||
@@ -34,14 +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 \
|
|
||||||
openssl \
|
|
||||||
pixman
|
|
||||||
|
|||||||
@@ -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 --exclude "_build/meson-private" "$@"
|
exec /usr/bin/scan-build -disable-checker unix.Malloc "$@"
|
||||||
178
NEWS
178
NEWS
@@ -1,180 +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.
|
||||||
|
|
||||||
2025-02-20: v1.94.9 release
|
|
||||||
|
|
||||||
Highlights:
|
|
||||||
* uru4000: Use OpenSSL to perform AES-ECB encryption, as per this libfprint
|
|
||||||
does not support on NSS, but on openssl (>= 3.0).
|
|
||||||
* goodixmoc: New PIDs 0x60C2, 0x689A
|
|
||||||
* synaptics: New PIDs 0x016C, 0x0174, 0x0107, 0x0108, 0x00C2, 0x00F0
|
|
||||||
* fpcmoc: New PID 0xC844
|
|
||||||
* focaltech_moc: New PIDs 0xA99A, 0xA57A, 0xA78A
|
|
||||||
* elanmoc: New PIDs 0x0C98, 0x0C9D, 0x0CA3
|
|
||||||
* elanspi: New PIDs 0x3128, 0x2766
|
|
||||||
* fp-device: Add FP_DEVICE_RETRY_TOO_FAST retry error
|
|
||||||
* data: AppStream meta info listing supported USB devices.
|
|
||||||
* fixed various memory issues in multiple devices
|
|
||||||
|
|
||||||
2024-09-03: v1.94.8 release
|
|
||||||
|
|
||||||
Highlights:
|
|
||||||
* build: Support building in non-linux unix environments (tested in FreeBSD)
|
|
||||||
* egismoc: New PIDs 0x0583, 0x0586, 0x0587.
|
|
||||||
* elanmoc: New PID 0x0C9F.
|
|
||||||
* fpcmoc: New PIDs 0x9524, 0x9544.
|
|
||||||
* goodixmoc: New PIDs 0x609A, 0x650A, 0x650C, 0x6512.
|
|
||||||
* realtek: New PID 0x5816.
|
|
||||||
* synaptics: New PIDs 0x00C4, 0x019D, 0x00C6.
|
|
||||||
* fpcmoc: fix incorrect immobile handling during enrollment.
|
|
||||||
* fpcmoc: fixed jumping to wrong state at end of custom enroll.
|
|
||||||
* egismoc: various code cleanups.
|
|
||||||
|
|
||||||
2024-02-20: v1.94.7 release
|
|
||||||
|
|
||||||
Highlights:
|
|
||||||
* synaptics: fix enroll identify problem after user reset database.
|
|
||||||
* synaptics: New PIDs 0x0173, 0x0106, 0x0124.
|
|
||||||
* goodixmoc: New PID 0x6582.
|
|
||||||
* build: Do not require bash to build, only posix sh.
|
|
||||||
* fp-image: Simplify minutiae detection tasks.
|
|
||||||
* GLib 2.68 is now required to build libfprint.
|
|
||||||
|
|
||||||
New drivers:
|
|
||||||
* realtek (PID 0x5813).
|
|
||||||
* focaltech_moc (PIDs 0x9E48, 0xD979, 0xA959).
|
|
||||||
* egismoc (PIDs 0x0582, 0x05a1).
|
|
||||||
|
|
||||||
2023-08-17: v1.94.6 release
|
|
||||||
|
|
||||||
Highlights:
|
|
||||||
* goodixmoc: New PIDs 0x60A4, 0x60BC, 0x6092, 0x633C and 0x6304.
|
|
||||||
* goodixmoc: Fix missing "enroll create" state.
|
|
||||||
* elanmoc: New PID 0x0C99.
|
|
||||||
* upektc: Improve compatibility with sensors 147e:2016.
|
|
||||||
* aes4000: Actually support 08FF:5501 devices.
|
|
||||||
* virtual-device-listener: Fix failing tests with GLib 2.76
|
|
||||||
* tests: Add installed tests
|
|
||||||
|
|
||||||
Bugs fixed:
|
|
||||||
* #526 libfprint: fpcmoc: use after free if enrollment or identification is
|
|
||||||
cancelled (Vasily Khoruzhick)
|
|
||||||
|
|
||||||
2022-10-13: v1.94.5 release
|
|
||||||
|
|
||||||
Highlights:
|
|
||||||
* New driver: fpcmoc, supporting various FPC MOC Fingerprint Sensors
|
|
||||||
* goodixmoc: New PIDs 0x6014, 0x6094, 0x631C, 0x634C, 0x6384, 0x659A.
|
|
||||||
* goodixmoc: Support resetting device on firmware failure due to corrupted DB.
|
|
||||||
* elanmoc: New PIDs 0x0c88, 0x0c8c, 0x0c8d.
|
|
||||||
* synaptics: New PID 0x0104.
|
|
||||||
* upektc: New PID 0x2017.
|
|
||||||
* Fixed various memory leaks
|
|
||||||
* More tests
|
|
||||||
|
|
||||||
2022-05-24: v1.94.4 release
|
|
||||||
|
|
||||||
Highlights:
|
|
||||||
* synaptics: New PIDs 0x0168, 0x015f
|
|
||||||
* elan: New PID 0x0c4b
|
|
||||||
* elanspi: New PID 0x241f
|
|
||||||
* synaptics: Minor fix to interrupt transfer resubmission
|
|
||||||
* Avoid sysfs writes if value is already expected
|
|
||||||
* Improvements to the testing setup
|
|
||||||
* Fixes to the internal critical section API
|
|
||||||
|
|
||||||
2021-11-02: v1.94.3 release
|
|
||||||
|
|
||||||
Highlights:
|
|
||||||
* 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:
|
||||||
@@ -401,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:
|
||||||
@@ -451,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
|
||||||
|
|
||||||
|
|||||||
51
README
Normal file
51
README
Normal file
@@ -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/
|
||||||
95
README.md
95
README.md
@@ -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
|
|
||||||
30
TODO
Normal file
30
TODO
Normal file
@@ -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
|
||||||
@@ -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,157 +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:v04F3p0C98*
|
|
||||||
usb:v04F3p0C99*
|
|
||||||
usb:v04F3p0C9D*
|
|
||||||
usb:v04F3p0C9F*
|
|
||||||
usb:v04F3p0CA3*
|
|
||||||
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*
|
|
||||||
usb:v2808pA99A*
|
|
||||||
usb:v2808pA57A*
|
|
||||||
usb:v2808pA78A*
|
|
||||||
ID_AUTOSUSPEND=1
|
|
||||||
ID_PERSIST=0
|
|
||||||
|
|
||||||
# Supported by libfprint driver fpcmoc
|
|
||||||
usb:v10A5pFFE0*
|
|
||||||
usb:v10A5pA305*
|
|
||||||
usb:v10A5pA306*
|
|
||||||
usb:v10A5pDA04*
|
|
||||||
usb:v10A5pD805*
|
|
||||||
usb:v10A5pD205*
|
|
||||||
usb:v10A5p9524*
|
|
||||||
usb:v10A5p9544*
|
|
||||||
usb:v10A5pC844*
|
|
||||||
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:v27C6p60C2*
|
|
||||||
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*
|
|
||||||
usb:v27C6p689A*
|
|
||||||
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:v06CBp00C2*
|
usb:v06CBp00E9*
|
||||||
usb:v06CBp00C4*
|
|
||||||
usb:v06CBp00C6*
|
|
||||||
usb:v06CBp00DF*
|
usb:v06CBp00DF*
|
||||||
usb:v06CBp00F0*
|
|
||||||
usb:v06CBp00F9*
|
usb:v06CBp00F9*
|
||||||
usb:v06CBp00FC*
|
usb:v06CBp00FC*
|
||||||
usb:v06CBp0100*
|
usb:v06CBp00C2*
|
||||||
usb:v06CBp0103*
|
usb:v06CBp00C9*
|
||||||
usb:v06CBp0104*
|
usb:v06CBp00E7*
|
||||||
usb:v06CBp0106*
|
|
||||||
usb:v06CBp0107*
|
|
||||||
usb:v06CBp0108*
|
|
||||||
usb:v06CBp0109*
|
|
||||||
usb:v06CBp010A*
|
|
||||||
usb:v06CBp0123*
|
|
||||||
usb:v06CBp0124*
|
|
||||||
usb:v06CBp0126*
|
|
||||||
usb:v06CBp0129*
|
|
||||||
usb:v06CBp015F*
|
|
||||||
usb:v06CBp0168*
|
|
||||||
usb:v06CBp0169*
|
|
||||||
usb:v06CBp016C*
|
|
||||||
usb:v06CBp0173*
|
|
||||||
usb:v06CBp0174*
|
|
||||||
usb:v06CBp019D*
|
|
||||||
usb:v06CBp019F*
|
|
||||||
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*
|
||||||
@@ -300,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*
|
||||||
@@ -330,86 +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:v0A5Cp5802*
|
|
||||||
usb:v047Dp00F2*
|
|
||||||
usb:v047Dp8054*
|
|
||||||
usb:v047Dp8055*
|
|
||||||
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:v04F3p0C60*
|
|
||||||
usb:v04F3p0C6C*
|
|
||||||
usb:v04F3p0C70*
|
|
||||||
usb:v04F3p0C72*
|
|
||||||
usb:v04F3p0C77*
|
|
||||||
usb:v04F3p0C7C*
|
|
||||||
usb:v04F3p0C7F*
|
|
||||||
usb:v04F3p0C80*
|
|
||||||
usb:v04F3p0C85*
|
|
||||||
usb:v04F3p0C90*
|
|
||||||
usb:v04F3p2706*
|
usb:v04F3p2706*
|
||||||
usb:v04F3p3032*
|
|
||||||
usb:v04F3p3057*
|
|
||||||
usb:v04F3p3104*
|
|
||||||
usb:v04F3p310D*
|
|
||||||
usb:v04F3p3128*
|
|
||||||
usb:v04F3p0C8A*
|
|
||||||
usb:v05BAp000E*
|
|
||||||
usb:v06CBp0051*
|
|
||||||
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:v06CBp00FF*
|
|
||||||
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:v10A5pA120*
|
|
||||||
usb:v10A5pA900*
|
|
||||||
usb:v10A5pE340*
|
|
||||||
usb:v1188p9545*
|
usb:v1188p9545*
|
||||||
usb:v138Ap0007*
|
usb:v138Ap0007*
|
||||||
usb:v138Ap003A*
|
usb:v138Ap003A*
|
||||||
@@ -417,62 +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:v1C7Ap0584*
|
|
||||||
usb:v1C7Ap0577*
|
|
||||||
usb:v1C7Ap057E*
|
|
||||||
usb:v2541p0236*
|
|
||||||
usb:v2541p9711*
|
|
||||||
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:v27C6p5F10*
|
|
||||||
usb:v27C6p6382*
|
|
||||||
usb:v2808p9338*
|
usb:v2808p9338*
|
||||||
usb:v2808p9348*
|
|
||||||
usb:v2808p93A9*
|
|
||||||
usb:v2808pA658*
|
|
||||||
usb:v2808pC652*
|
|
||||||
usb:v298Dp2020*
|
|
||||||
usb:v298Dp2033*
|
usb:v298Dp2033*
|
||||||
usb:v2DF0p0003*
|
|
||||||
usb:v3274p8012*
|
|
||||||
usb:v3538p0930*
|
usb:v3538p0930*
|
||||||
ID_AUTOSUSPEND=1
|
ID_AUTOSUSPEND=1
|
||||||
ID_PERSIST=0
|
|
||||||
|
|||||||
@@ -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),
|
||||||
|
|||||||
@@ -101,14 +101,11 @@ plot_minutiae (unsigned char *rgbdata,
|
|||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
#define write_pixel(num) \
|
#define write_pixel(num) do { \
|
||||||
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++)
|
||||||
{
|
{
|
||||||
@@ -529,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",
|
||||||
@@ -27,46 +27,35 @@
|
|||||||
"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"/>
|
||||||
|
|||||||
@@ -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')),
|
||||||
|
|||||||
@@ -1,208 +0,0 @@
|
|||||||
/*
|
|
||||||
* Example storage clearing program, which deletes all the
|
|
||||||
* fingers which have been previously enrolled to disk.
|
|
||||||
* Copyright (C) 2020 Marco Trevisan <marco.trevisan@canonical.com>
|
|
||||||
* Copyright (C) 2024 Abhinav Baid <abhinavbaid@gmail.com>
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
|
||||||
* License as published by the Free Software Foundation; either
|
|
||||||
* version 2.1 of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define FP_COMPONENT "example-clear-storage"
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <libfprint/fprint.h>
|
|
||||||
#include <glib-unix.h>
|
|
||||||
|
|
||||||
#include "storage.h"
|
|
||||||
#include "utilities.h"
|
|
||||||
|
|
||||||
typedef struct _ClearStorageData
|
|
||||||
{
|
|
||||||
GMainLoop *loop;
|
|
||||||
GCancellable *cancellable;
|
|
||||||
unsigned int sigint_handler;
|
|
||||||
int ret_value;
|
|
||||||
} ClearStorageData;
|
|
||||||
|
|
||||||
static void
|
|
||||||
clear_storage_data_free (ClearStorageData *clear_storage_data)
|
|
||||||
{
|
|
||||||
g_clear_handle_id (&clear_storage_data->sigint_handler, g_source_remove);
|
|
||||||
g_clear_object (&clear_storage_data->cancellable);
|
|
||||||
g_main_loop_unref (clear_storage_data->loop);
|
|
||||||
g_free (clear_storage_data);
|
|
||||||
}
|
|
||||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClearStorageData, clear_storage_data_free)
|
|
||||||
|
|
||||||
static void
|
|
||||||
on_device_closed (FpDevice *dev, GAsyncResult *res, void *user_data)
|
|
||||||
{
|
|
||||||
g_autoptr(GError) error = NULL;
|
|
||||||
ClearStorageData *clear_storage_data = user_data;
|
|
||||||
|
|
||||||
fp_device_close_finish (dev, res, &error);
|
|
||||||
|
|
||||||
if (error)
|
|
||||||
g_warning ("Failed closing device %s", error->message);
|
|
||||||
|
|
||||||
g_main_loop_quit (clear_storage_data->loop);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
clear_storage_quit (FpDevice *dev,
|
|
||||||
ClearStorageData *clear_storage_data)
|
|
||||||
{
|
|
||||||
if (!fp_device_is_open (dev))
|
|
||||||
{
|
|
||||||
g_main_loop_quit (clear_storage_data->loop);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
fp_device_close (dev, NULL, (GAsyncReadyCallback) on_device_closed,
|
|
||||||
clear_storage_data);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
on_clear_storage_completed (FpDevice *dev, GAsyncResult *res, void *user_data)
|
|
||||||
{
|
|
||||||
g_autoptr(GError) error = NULL;
|
|
||||||
ClearStorageData *clear_storage_data = user_data;
|
|
||||||
|
|
||||||
if (fp_device_clear_storage_finish (dev, res, &error))
|
|
||||||
{
|
|
||||||
if (!clear_saved_prints (dev, &error))
|
|
||||||
{
|
|
||||||
g_warning ("Clear saved prints from local storage failed: %s",
|
|
||||||
error->message);
|
|
||||||
clear_storage_data->ret_value = EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
g_print ("Clear storage successful!\n");
|
|
||||||
clear_storage_data->ret_value = EXIT_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
clear_storage_quit (dev, clear_storage_data);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
g_warning ("Failed to clear storage: %s", error->message);
|
|
||||||
clear_storage_data->ret_value = EXIT_FAILURE;
|
|
||||||
|
|
||||||
if (g_error_matches (error, FP_DEVICE_ERROR, FP_DEVICE_ERROR_NOT_SUPPORTED))
|
|
||||||
{
|
|
||||||
g_autoptr(GError) clear_error = NULL;
|
|
||||||
|
|
||||||
if (clear_saved_prints (dev, &clear_error))
|
|
||||||
clear_storage_data->ret_value = EXIT_SUCCESS;
|
|
||||||
else
|
|
||||||
g_warning ("Clear saved prints from local storage failed: %s",
|
|
||||||
clear_error->message);
|
|
||||||
}
|
|
||||||
|
|
||||||
clear_storage_quit (dev, clear_storage_data);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
start_clear_storage (FpDevice *dev, ClearStorageData *clear_storage_data)
|
|
||||||
{
|
|
||||||
char buffer[20];
|
|
||||||
|
|
||||||
g_print ("Clear device storage? [Y/n]? ");
|
|
||||||
if (fgets (buffer, sizeof (buffer), stdin) &&
|
|
||||||
(buffer[0] == 'Y' || buffer[0] == 'y'))
|
|
||||||
{
|
|
||||||
fp_device_clear_storage (dev, clear_storage_data->cancellable,
|
|
||||||
(GAsyncReadyCallback) on_clear_storage_completed,
|
|
||||||
clear_storage_data);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
clear_storage_quit (dev, clear_storage_data);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
on_device_opened (FpDevice *dev, GAsyncResult *res, void *user_data)
|
|
||||||
{
|
|
||||||
g_autoptr(GError) error = NULL;
|
|
||||||
ClearStorageData *clear_storage_data = user_data;
|
|
||||||
|
|
||||||
if (!fp_device_open_finish (dev, res, &error))
|
|
||||||
{
|
|
||||||
g_warning ("Failed to open device: %s", error->message);
|
|
||||||
clear_storage_quit (dev, clear_storage_data);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
g_print ("Opened device. ");
|
|
||||||
|
|
||||||
start_clear_storage (dev, clear_storage_data);
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
sigint_cb (void *user_data)
|
|
||||||
{
|
|
||||||
ClearStorageData *clear_storage_data = user_data;
|
|
||||||
|
|
||||||
g_cancellable_cancel (clear_storage_data->cancellable);
|
|
||||||
|
|
||||||
return G_SOURCE_CONTINUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
main (void)
|
|
||||||
{
|
|
||||||
g_autoptr(FpContext) ctx = NULL;
|
|
||||||
g_autoptr(ClearStorageData) clear_storage_data = NULL;
|
|
||||||
GPtrArray *devices;
|
|
||||||
FpDevice *dev;
|
|
||||||
|
|
||||||
setenv ("G_MESSAGES_DEBUG", "all", 0);
|
|
||||||
setenv ("LIBUSB_DEBUG", "3", 0);
|
|
||||||
|
|
||||||
ctx = fp_context_new ();
|
|
||||||
|
|
||||||
devices = fp_context_get_devices (ctx);
|
|
||||||
if (!devices)
|
|
||||||
{
|
|
||||||
g_warning ("Impossible to get devices");
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
dev = discover_device (devices);
|
|
||||||
if (!dev)
|
|
||||||
{
|
|
||||||
g_warning ("No devices detected.");
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
clear_storage_data = g_new0 (ClearStorageData, 1);
|
|
||||||
clear_storage_data->ret_value = EXIT_FAILURE;
|
|
||||||
clear_storage_data->loop = g_main_loop_new (NULL, FALSE);
|
|
||||||
clear_storage_data->cancellable = g_cancellable_new ();
|
|
||||||
clear_storage_data->sigint_handler = g_unix_signal_add_full (G_PRIORITY_HIGH,
|
|
||||||
SIGINT,
|
|
||||||
sigint_cb,
|
|
||||||
clear_storage_data,
|
|
||||||
NULL);
|
|
||||||
fp_device_open (dev, clear_storage_data->cancellable,
|
|
||||||
(GAsyncReadyCallback) on_device_opened,
|
|
||||||
clear_storage_data);
|
|
||||||
|
|
||||||
g_main_loop_run (clear_storage_data->loop);
|
|
||||||
|
|
||||||
return clear_storage_data->ret_value;
|
|
||||||
}
|
|
||||||
@@ -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 ();
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ examples = [
|
|||||||
'img-capture',
|
'img-capture',
|
||||||
'manage-prints',
|
'manage-prints',
|
||||||
'verify',
|
'verify',
|
||||||
'clear-storage',
|
|
||||||
]
|
]
|
||||||
|
|
||||||
foreach example: examples
|
foreach example: examples
|
||||||
@@ -22,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
|
|
||||||
|
|||||||
@@ -26,7 +26,6 @@
|
|||||||
#include "storage.h"
|
#include "storage.h"
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <glib/gstdio.h>
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
@@ -56,18 +55,6 @@ get_print_data_descriptor (FpPrint *print, FpDevice *dev, FpFinger finger)
|
|||||||
finger);
|
finger);
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *
|
|
||||||
get_print_prefix_for_device (FpDevice *dev)
|
|
||||||
{
|
|
||||||
const char *driver;
|
|
||||||
const char *dev_id;
|
|
||||||
|
|
||||||
driver = fp_device_get_driver (dev);
|
|
||||||
dev_id = fp_device_get_device_id (dev);
|
|
||||||
|
|
||||||
return g_strdup_printf ("%s/%s/", driver, dev_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
static GVariantDict *
|
static GVariantDict *
|
||||||
load_data (void)
|
load_data (void)
|
||||||
{
|
{
|
||||||
@@ -115,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);
|
||||||
|
|
||||||
@@ -165,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;
|
||||||
}
|
}
|
||||||
@@ -182,6 +167,8 @@ gallery_data_load (FpDevice *dev)
|
|||||||
g_autoptr(GVariant) dict_variant = NULL;
|
g_autoptr(GVariant) dict_variant = NULL;
|
||||||
g_autofree char *dev_prefix = NULL;
|
g_autofree char *dev_prefix = NULL;
|
||||||
GPtrArray *gallery;
|
GPtrArray *gallery;
|
||||||
|
const char *driver;
|
||||||
|
const char *dev_id;
|
||||||
GVariantIter iter;
|
GVariantIter iter;
|
||||||
GVariant *value;
|
GVariant *value;
|
||||||
gchar *key;
|
gchar *key;
|
||||||
@@ -189,7 +176,9 @@ gallery_data_load (FpDevice *dev)
|
|||||||
gallery = g_ptr_array_new_with_free_func (g_object_unref);
|
gallery = g_ptr_array_new_with_free_func (g_object_unref);
|
||||||
dict = load_data ();
|
dict = load_data ();
|
||||||
dict_variant = g_variant_dict_end (dict);
|
dict_variant = g_variant_dict_end (dict);
|
||||||
dev_prefix = get_print_prefix_for_device (dev);
|
driver = fp_device_get_driver (dev);
|
||||||
|
dev_id = fp_device_get_device_id (dev);
|
||||||
|
dev_prefix = g_strdup_printf ("%s/%s/", driver, dev_id);
|
||||||
|
|
||||||
g_variant_iter_init (&iter, dict_variant);
|
g_variant_iter_init (&iter, dict_variant);
|
||||||
while (g_variant_iter_loop (&iter, "{sv}", &key, &value))
|
while (g_variant_iter_loop (&iter, "{sv}", &key, &value))
|
||||||
@@ -217,80 +206,17 @@ gallery_data_load (FpDevice *dev)
|
|||||||
return gallery;
|
return gallery;
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean
|
|
||||||
clear_saved_prints (FpDevice *dev,
|
|
||||||
GError **error)
|
|
||||||
{
|
|
||||||
g_autoptr(GVariantDict) dict = NULL;
|
|
||||||
g_autoptr(GVariantDict) updated_dict = NULL;
|
|
||||||
g_autoptr(GVariant) dict_variant = NULL;
|
|
||||||
g_autofree char *dev_prefix = NULL;
|
|
||||||
GPtrArray *print_keys;
|
|
||||||
GVariantIter iter;
|
|
||||||
GVariant *value;
|
|
||||||
gchar *key;
|
|
||||||
|
|
||||||
print_keys = g_ptr_array_new_with_free_func (g_free);
|
|
||||||
dict = load_data ();
|
|
||||||
dict_variant = g_variant_dict_end (dict);
|
|
||||||
dev_prefix = get_print_prefix_for_device (dev);
|
|
||||||
|
|
||||||
g_variant_iter_init (&iter, dict_variant);
|
|
||||||
while (g_variant_iter_loop (&iter, "{sv}", &key, &value))
|
|
||||||
{
|
|
||||||
if (!g_str_has_prefix (key, dev_prefix))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
g_ptr_array_add (print_keys, g_strdup (key));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!print_keys->len)
|
|
||||||
return TRUE;
|
|
||||||
|
|
||||||
updated_dict = load_data ();
|
|
||||||
|
|
||||||
for (guint i = 0; i < print_keys->len; ++i)
|
|
||||||
{
|
|
||||||
key = g_ptr_array_index (print_keys, i);
|
|
||||||
if (!g_variant_dict_remove (updated_dict, key))
|
|
||||||
{
|
|
||||||
g_warning ("Print '%s' key not found!", key);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
g_debug ("Dropping print '%s' from gallery", key);
|
|
||||||
}
|
|
||||||
|
|
||||||
save_data (g_variant_dict_end (updated_dict));
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
FpPrint *
|
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)
|
|
||||||
{
|
|
||||||
dict = load_data ();
|
|
||||||
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);
|
template = fp_print_new (dev);
|
||||||
fp_print_set_finger (template, finger);
|
fp_print_set_finger (template, finger);
|
||||||
fp_print_set_username (template, g_get_user_name ());
|
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);
|
||||||
|
|||||||
@@ -20,20 +20,13 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <glib.h>
|
|
||||||
#include <libfprint/fprint.h>
|
|
||||||
|
|
||||||
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);
|
||||||
gboolean clear_saved_prints (FpDevice *dev,
|
|
||||||
GError **error);
|
|
||||||
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";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -130,12 +130,10 @@ 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 "
|
||||||
@@ -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,384 +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 = 0x2766}, .driver_data = ELANSPI_NO_ROTATE},
|
|
||||||
{.udev_types = ELANSPI_UDEV_TYPES, .spi_acpi_id = "ELAN7001", .hid_id = {.vid = ELANSPI_TP_VID, .pid = 0x3057}, .driver_data = ELANSPI_180_ROTATE},
|
|
||||||
{.udev_types = ELANSPI_UDEV_TYPES, .spi_acpi_id = "ELAN7001", .hid_id = {.vid = ELANSPI_TP_VID, .pid = 0x3087}, .driver_data = ELANSPI_180_ROTATE},
|
|
||||||
{.udev_types = ELANSPI_UDEV_TYPES, .spi_acpi_id = "ELAN7001", .hid_id = {.vid = ELANSPI_TP_VID, .pid = 0x30c6}, .driver_data = ELANSPI_180_ROTATE},
|
|
||||||
{.udev_types = ELANSPI_UDEV_TYPES, .spi_acpi_id = "ELAN7001", .hid_id = {.vid = ELANSPI_TP_VID, .pid = 0x3128}, .driver_data = ELANSPI_90LEFT_ROTATE},
|
|
||||||
{.udev_types = ELANSPI_UDEV_TYPES, .spi_acpi_id = "ELAN70A1", .hid_id = {.vid = ELANSPI_TP_VID, .pid = 0x3134}, .driver_data = ELANSPI_90LEFT_ROTATE},
|
|
||||||
{.udev_types = ELANSPI_UDEV_TYPES, .spi_acpi_id = "ELAN7001", .hid_id = {.vid = ELANSPI_TP_VID, .pid = 0x3148}, .driver_data = ELANSPI_180_ROTATE},
|
|
||||||
{.udev_types = ELANSPI_UDEV_TYPES, .spi_acpi_id = "ELAN7001", .hid_id = {.vid = ELANSPI_TP_VID, .pid = 0x30b2}, .driver_data = ELANSPI_NO_ROTATE},
|
|
||||||
{.udev_types = ELANSPI_UDEV_TYPES, .spi_acpi_id = "ELAN70A1", .hid_id = {.vid = ELANSPI_TP_VID, .pid = 0x30b2}, .driver_data = ELANSPI_NO_ROTATE},
|
|
||||||
{.udev_types = ELANSPI_UDEV_TYPES, .spi_acpi_id = "ELAN7001", .hid_id = {.vid = ELANSPI_TP_VID, .pid = 0x309f}, .driver_data = ELANSPI_180_ROTATE},
|
|
||||||
{.udev_types = ELANSPI_UDEV_TYPES, .spi_acpi_id = "ELAN7001", .hid_id = {.vid = ELANSPI_TP_VID, .pid = 0x241f}, .driver_data = ELANSPI_NO_ROTATE},
|
|
||||||
{.udev_types = 0}
|
|
||||||
};
|
|
||||||
|
|
||||||
#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
|
||||||
@@ -128,13 +92,11 @@ fp_cmd_receive_cb (FpiUsbTransfer *transfer,
|
|||||||
GError *error)
|
GError *error)
|
||||||
{
|
{
|
||||||
FpiDeviceGoodixMoc *self = FPI_DEVICE_GOODIXMOC (device);
|
FpiDeviceGoodixMoc *self = FPI_DEVICE_GOODIXMOC (device);
|
||||||
FpiByteReader reader = {0};
|
|
||||||
CommandData *data = user_data;
|
CommandData *data = user_data;
|
||||||
int ssm_state = 0;
|
int ret = -1, ssm_state = 0;
|
||||||
gxfp_cmd_response_t cmd_reponse = {0, };
|
gxfp_cmd_response_t cmd_reponse = {0, };
|
||||||
pack_header header;
|
pack_header header;
|
||||||
guint32 crc32_calc = 0;
|
guint32 crc32_calc = 0;
|
||||||
guint32 crc32 = 0;
|
|
||||||
guint16 cmd = 0;
|
guint16 cmd = 0;
|
||||||
|
|
||||||
if (error)
|
if (error)
|
||||||
@@ -156,28 +118,17 @@ fp_cmd_receive_cb (FpiUsbTransfer *transfer,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
reader.data = transfer->buffer;
|
ret = gx_proto_parse_header (transfer->buffer, transfer->actual_length, &header);
|
||||||
reader.size = transfer->actual_length;
|
if (ret != 0)
|
||||||
|
|
||||||
if (gx_proto_parse_header (&reader, &header) != 0)
|
|
||||||
{
|
{
|
||||||
fpi_ssm_mark_failed (transfer->ssm,
|
fpi_ssm_mark_failed (transfer->ssm,
|
||||||
fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
|
fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
|
||||||
"Corrupted message header received"));
|
"Corrupted message received"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!fpi_byte_reader_set_pos (&reader, PACKAGE_HEADER_SIZE + header.len))
|
|
||||||
{
|
|
||||||
fpi_ssm_mark_failed (transfer->ssm,
|
|
||||||
fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
|
|
||||||
"Package crc read failed"));
|
|
||||||
}
|
|
||||||
|
|
||||||
gx_proto_crc32_calc (transfer->buffer, PACKAGE_HEADER_SIZE + header.len, (uint8_t *) &crc32_calc);
|
gx_proto_crc32_calc (transfer->buffer, PACKAGE_HEADER_SIZE + header.len, (uint8_t *) &crc32_calc);
|
||||||
|
if(crc32_calc != GUINT32_FROM_LE (*(uint32_t *) (transfer->buffer + PACKAGE_HEADER_SIZE + header.len)))
|
||||||
if (!fpi_byte_reader_get_uint32_le (&reader, &crc32) ||
|
|
||||||
crc32_calc != crc32)
|
|
||||||
{
|
{
|
||||||
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,
|
||||||
@@ -187,11 +138,8 @@ fp_cmd_receive_cb (FpiUsbTransfer *transfer,
|
|||||||
|
|
||||||
cmd = MAKE_CMD_EX (header.cmd0, header.cmd1);
|
cmd = MAKE_CMD_EX (header.cmd0, header.cmd1);
|
||||||
|
|
||||||
fpi_byte_reader_set_pos (&reader, 0);
|
ret = gx_proto_parse_body (cmd, &transfer->buffer[PACKAGE_HEADER_SIZE], header.len, &cmd_reponse);
|
||||||
reader.data = &transfer->buffer[PACKAGE_HEADER_SIZE];
|
if (ret != 0)
|
||||||
reader.size = header.len;
|
|
||||||
|
|
||||||
if (gx_proto_parse_body (cmd, &reader, &cmd_reponse) != 0)
|
|
||||||
{
|
{
|
||||||
fpi_ssm_mark_failed (transfer->ssm,
|
fpi_ssm_mark_failed (transfer->ssm,
|
||||||
fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
|
fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
|
||||||
@@ -272,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;
|
||||||
@@ -436,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)
|
||||||
{
|
{
|
||||||
@@ -447,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++)
|
||||||
{
|
{
|
||||||
if (fp_print_equal (g_ptr_array_index (templates, i), new_scan))
|
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))
|
||||||
{
|
{
|
||||||
matching = g_ptr_array_index (templates, i);
|
fpi_ssm_mark_failed (self->task_ssm,
|
||||||
|
fpi_device_error_new_msg (FP_DEVICE_ERROR_DATA_INVALID,
|
||||||
|
"Parse print error"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (memcmp (&resp->verify.template.tid, tid, TEMPLATE_ID_SIZE) == 0)
|
||||||
|
{
|
||||||
|
find = true;
|
||||||
break;
|
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 (!find)
|
||||||
|
{
|
||||||
if (fpi_device_get_current_action (device) == FPI_DEVICE_ACTION_VERIFY)
|
if (fpi_device_get_current_action (device) == FPI_DEVICE_ACTION_VERIFY)
|
||||||
fpi_device_verify_report (device, matching ? FPI_MATCH_SUCCESS : FPI_MATCH_FAIL, new_scan, error);
|
fpi_device_verify_report (device, FPI_MATCH_FAIL, NULL, error);
|
||||||
else
|
else
|
||||||
fpi_device_identify_report (device, matching, new_scan, error);
|
fpi_device_identify_report (device, NULL, NULL, error);
|
||||||
|
}
|
||||||
|
|
||||||
fpi_ssm_next_state (self->task_ssm);
|
fpi_ssm_next_state (self->task_ssm);
|
||||||
|
|
||||||
@@ -647,11 +620,11 @@ 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)
|
||||||
{
|
{
|
||||||
@@ -660,7 +633,29 @@ fp_enroll_create_cb (FpiDeviceGoodixMoc *self,
|
|||||||
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -677,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,
|
||||||
@@ -691,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],
|
||||||
@@ -703,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);
|
||||||
@@ -765,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -853,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,
|
||||||
@@ -873,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;
|
||||||
|
|
||||||
@@ -1057,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)
|
||||||
@@ -1122,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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1241,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
|
||||||
@@ -1308,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));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1375,28 +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 0x60C2:
|
|
||||||
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;
|
||||||
|
|
||||||
@@ -1427,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);
|
||||||
@@ -1464,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 */
|
||||||
@@ -1483,7 +1407,9 @@ gx_fp_exit_cb (FpiDeviceGoodixMoc *self,
|
|||||||
gxfp_cmd_response_t *resp,
|
gxfp_cmd_response_t *resp,
|
||||||
GError *error)
|
GError *error)
|
||||||
{
|
{
|
||||||
if (resp && resp->result >= GX_FAILED)
|
|
||||||
|
|
||||||
|
if (resp->result >= GX_FAILED)
|
||||||
fp_dbg ("Setting power button shield failed, result: 0x%x", resp->result);
|
fp_dbg ("Setting power button shield failed, result: 0x%x", resp->result);
|
||||||
self->is_power_button_shield_on = false;
|
self->is_power_button_shield_on = false;
|
||||||
gx_fp_release_interface (self, error);
|
gx_fp_release_interface (self, error);
|
||||||
@@ -1517,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);
|
||||||
|
|
||||||
@@ -1533,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);
|
||||||
|
|
||||||
@@ -1604,58 +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 = 0x60C2, },
|
|
||||||
{ .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 = 0x27c6, .pid = 0x689A, },
|
|
||||||
{ .vid = 0, .pid = 0, .driver_data = 0 }, /* terminating entry */
|
{ .vid = 0, .pid = 0, .driver_data = 0 }, /* terminating entry */
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1671,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,
|
||||||
|
|||||||
@@ -18,8 +18,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#include "goodix_proto.h"
|
#include "goodix_proto.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -109,7 +107,7 @@ reflect (uint32_t data, uint8_t n_bits)
|
|||||||
* If the LSB bit is set, set the reflection of it.
|
* If the LSB bit is set, set the reflection of it.
|
||||||
*/
|
*/
|
||||||
if (data & 0x01)
|
if (data & 0x01)
|
||||||
reflection |= (1LU << ((n_bits - 1) - bit));
|
reflection |= (1 << ((n_bits - 1) - bit));
|
||||||
|
|
||||||
data = (data >> 1);
|
data = (data >> 1);
|
||||||
}
|
}
|
||||||
@@ -213,11 +211,7 @@ gx_proto_build_package (uint8_t *ppackage,
|
|||||||
init_pack_header (&header, payload_size, cmd, 0);
|
init_pack_header (&header, payload_size, cmd, 0);
|
||||||
|
|
||||||
memcpy (ppackage, &header, PACKAGE_HEADER_SIZE);
|
memcpy (ppackage, &header, PACKAGE_HEADER_SIZE);
|
||||||
|
|
||||||
if (payload)
|
|
||||||
memcpy (ppackage + PACKAGE_HEADER_SIZE, payload, payload_size);
|
memcpy (ppackage + PACKAGE_HEADER_SIZE, payload, payload_size);
|
||||||
else
|
|
||||||
ppackage[PACKAGE_HEADER_SIZE] = 0;
|
|
||||||
|
|
||||||
gx_proto_crc32_calc (ppackage, PACKAGE_HEADER_SIZE + payload_size, ppackage + PACKAGE_HEADER_SIZE + payload_size);
|
gx_proto_crc32_calc (ppackage, PACKAGE_HEADER_SIZE + payload_size, ppackage + PACKAGE_HEADER_SIZE + payload_size);
|
||||||
|
|
||||||
@@ -226,108 +220,95 @@ gx_proto_build_package (uint8_t *ppackage,
|
|||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
gx_proto_parse_header (FpiByteReader *reader,
|
gx_proto_parse_header (
|
||||||
|
uint8_t *buffer,
|
||||||
|
uint32_t buffer_len,
|
||||||
pack_header *pheader)
|
pack_header *pheader)
|
||||||
{
|
{
|
||||||
if (!pheader)
|
if (!buffer || !pheader)
|
||||||
|
return -1;
|
||||||
|
if (buffer_len < PACKAGE_HEADER_SIZE + PACKAGE_CRC_SIZE)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (!fpi_byte_reader_get_uint8 (reader, &pheader->cmd0))
|
memcpy (pheader, buffer, sizeof (pack_header));
|
||||||
g_return_val_if_reached (-1);
|
pheader->len = GUINT16_FROM_LE (pheader->len);
|
||||||
|
if (buffer_len < pheader->len + PACKAGE_HEADER_SIZE)
|
||||||
if (!fpi_byte_reader_get_uint8 (reader, &pheader->cmd1))
|
return -1;
|
||||||
g_return_val_if_reached (-1);
|
|
||||||
|
|
||||||
if (!fpi_byte_reader_get_uint8 (reader, &pheader->packagenum))
|
|
||||||
g_return_val_if_reached (-1);
|
|
||||||
|
|
||||||
if (!fpi_byte_reader_get_uint8 (reader, &pheader->reserved))
|
|
||||||
g_return_val_if_reached (-1);
|
|
||||||
|
|
||||||
if (!fpi_byte_reader_get_uint16_le (reader, &pheader->len))
|
|
||||||
g_return_val_if_reached (-1);
|
|
||||||
|
|
||||||
if (!fpi_byte_reader_get_uint8 (reader, &pheader->crc8))
|
|
||||||
g_return_val_if_reached (-1);
|
|
||||||
|
|
||||||
if (!fpi_byte_reader_get_uint8 (reader, &pheader->rev_crc8))
|
|
||||||
g_return_val_if_reached (-1);
|
|
||||||
|
|
||||||
pheader->len -= PACKAGE_CRC_SIZE;
|
pheader->len -= PACKAGE_CRC_SIZE;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
gx_proto_parse_fingerid (FpiByteReader *reader,
|
gx_proto_parse_fingerid (
|
||||||
ptemplate_format_t template)
|
uint8_t * fid_buffer,
|
||||||
|
uint16_t fid_buffer_size,
|
||||||
|
ptemplate_format_t template
|
||||||
|
)
|
||||||
{
|
{
|
||||||
uint8_t byte;
|
uint8_t * buffer = NULL;
|
||||||
const uint8_t *buffer;
|
uint16_t Offset = 0;
|
||||||
|
|
||||||
if (!template)
|
if (!template || !fid_buffer)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (!fpi_byte_reader_get_uint8 (reader, &byte) || byte != 67)
|
if (fid_buffer_size < G_STRUCT_OFFSET (template_format_t, payload) + sizeof (uint32_t))
|
||||||
g_return_val_if_reached (-1);
|
return -1;
|
||||||
|
|
||||||
if (!fpi_byte_reader_get_uint8 (reader, &template->type))
|
buffer = fid_buffer;
|
||||||
g_return_val_if_reached (-1);
|
Offset = 0;
|
||||||
|
|
||||||
if (!fpi_byte_reader_get_uint8 (reader, &template->finger_index))
|
if (buffer[Offset++] != 67)
|
||||||
g_return_val_if_reached (-1);
|
return -1;
|
||||||
|
fid_buffer_size--;
|
||||||
|
|
||||||
if (!fpi_byte_reader_skip (reader, 1))
|
template->type = buffer[Offset++];
|
||||||
g_return_val_if_reached (-1);
|
fid_buffer_size--;
|
||||||
|
template->finger_index = buffer[Offset++];
|
||||||
if (!fpi_byte_reader_get_data (reader, sizeof (template->accountid), &buffer))
|
fid_buffer_size--;
|
||||||
g_return_val_if_reached (-1);
|
Offset++;
|
||||||
|
memcpy (template->accountid, &buffer[Offset], sizeof (template->accountid));
|
||||||
memcpy (template->accountid, buffer, sizeof (template->accountid));
|
Offset += sizeof (template->accountid);
|
||||||
|
memcpy (template->tid, &buffer[Offset], sizeof (template->tid));
|
||||||
if (!fpi_byte_reader_get_data (reader, sizeof (template->tid), &buffer))
|
Offset += sizeof (template->tid); // Offset == 68
|
||||||
g_return_val_if_reached (-1);
|
template->payload.size = buffer[Offset++];
|
||||||
|
if (template->payload.size > sizeof (template->payload.data))
|
||||||
memcpy (template->tid, buffer, sizeof (template->tid));
|
return -1;
|
||||||
|
memset (template->payload.data, 0, template->payload.size);
|
||||||
if (!fpi_byte_reader_get_uint8 (reader, &template->payload.size))
|
memcpy (template->payload.data, &buffer[Offset], template->payload.size);
|
||||||
g_return_val_if_reached (-1);
|
|
||||||
|
|
||||||
if (!fpi_byte_reader_get_data (reader, template->payload.size, &buffer))
|
|
||||||
g_return_val_if_reached (-1);
|
|
||||||
|
|
||||||
memcpy (template->payload.data, buffer, template->payload.size);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
gx_proto_parse_body (uint16_t cmd, FpiByteReader *byte_reader, pgxfp_cmd_response_t presp)
|
gx_proto_parse_body (uint16_t cmd, uint8_t *buffer, uint16_t buffer_len, pgxfp_cmd_response_t presp)
|
||||||
{
|
{
|
||||||
if (!presp)
|
uint16_t offset = 0;
|
||||||
|
uint8_t *fingerlist = NULL;
|
||||||
|
|
||||||
|
if (!buffer || !presp)
|
||||||
return -1;
|
return -1;
|
||||||
|
if (buffer_len < 1)
|
||||||
if (!fpi_byte_reader_get_uint8 (byte_reader, &presp->result))
|
return -1;
|
||||||
g_return_val_if_reached (-1);
|
presp->result = buffer[0];
|
||||||
|
|
||||||
switch (HIBYTE (cmd))
|
switch (HIBYTE (cmd))
|
||||||
{
|
{
|
||||||
case RESPONSE_PACKAGE_CMD:
|
case RESPONSE_PACKAGE_CMD:
|
||||||
{
|
{
|
||||||
if (!fpi_byte_reader_get_uint8 (byte_reader, &presp->parse_msg.ack_cmd))
|
if (buffer_len < sizeof (gxfp_parse_msg_t) + 1)
|
||||||
g_return_val_if_reached (-1);
|
return -1;
|
||||||
|
presp->parse_msg.ack_cmd = buffer[1];
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MOC_CMD0_UPDATE_CONFIG:
|
case MOC_CMD0_UPDATE_CONFIG:
|
||||||
{
|
{
|
||||||
presp->finger_config.status = presp->result;
|
presp->finger_config.status = buffer[0];
|
||||||
|
if (buffer_len >= 3)
|
||||||
|
presp->finger_config.max_stored_prints = buffer[2];
|
||||||
|
else
|
||||||
/* to compatiable old version firmware */
|
/* to compatiable old version firmware */
|
||||||
presp->finger_config.max_stored_prints = FP_MAX_FINGERNUM;
|
presp->finger_config.max_stored_prints = FP_MAX_FINGERNUM;
|
||||||
|
|
||||||
if (fpi_byte_reader_skip (byte_reader, 1))
|
|
||||||
fpi_byte_reader_get_uint8 (byte_reader,
|
|
||||||
&presp->finger_config.max_stored_prints);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -338,99 +319,81 @@ gx_proto_parse_body (uint16_t cmd, FpiByteReader *byte_reader, pgxfp_cmd_respons
|
|||||||
|
|
||||||
case MOC_CMD0_PWR_BTN_SHIELD:
|
case MOC_CMD0_PWR_BTN_SHIELD:
|
||||||
presp->power_button_shield_resp.resp_cmd1 = LOBYTE (cmd);
|
presp->power_button_shield_resp.resp_cmd1 = LOBYTE (cmd);
|
||||||
uint8_t support_pwr_shield;
|
if (buffer_len >= 2)
|
||||||
|
{
|
||||||
if (fpi_byte_reader_get_uint8 (byte_reader, &support_pwr_shield) &&
|
uint8_t support_pwr_shield = buffer[1];
|
||||||
support_pwr_shield == 0xFF)
|
if (support_pwr_shield == 0xFF)
|
||||||
g_debug ("Power button shield feature not supported!\n");
|
g_debug ("Power button shield feature not supported!\n");
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MOC_CMD0_GET_VERSION:
|
case MOC_CMD0_GET_VERSION:
|
||||||
const uint8_t *version_info;
|
if (buffer_len < sizeof (gxfp_version_info_t) + 1)
|
||||||
|
return -1;
|
||||||
if (!fpi_byte_reader_get_data (byte_reader, sizeof (gxfp_version_info_t), &version_info))
|
memcpy (&presp->version_info, buffer + 1, sizeof (gxfp_version_info_t));
|
||||||
g_return_val_if_reached (-1);
|
|
||||||
|
|
||||||
memcpy (&presp->version_info, version_info, sizeof (gxfp_version_info_t));
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MOC_CMD0_CAPTURE_DATA:
|
case MOC_CMD0_CAPTURE_DATA:
|
||||||
if (LOBYTE (cmd) == MOC_CMD1_DEFAULT)
|
if (LOBYTE (cmd) == MOC_CMD1_DEFAULT)
|
||||||
{
|
{
|
||||||
if (!fpi_byte_reader_get_uint8 (byte_reader,
|
if (buffer_len < sizeof (gxfp_capturedata_t) + 1)
|
||||||
&presp->capture_data_resp.img_quality))
|
return -1;
|
||||||
g_return_val_if_reached (-1);
|
presp->capture_data_resp.img_quality = buffer[1];
|
||||||
|
presp->capture_data_resp.img_coverage = buffer[2];
|
||||||
if (!fpi_byte_reader_get_uint8 (byte_reader,
|
|
||||||
&presp->capture_data_resp.img_coverage))
|
|
||||||
g_return_val_if_reached (-1);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MOC_CMD0_ENROLL_INIT:
|
case MOC_CMD0_ENROLL_INIT:
|
||||||
if (presp->result != GX_SUCCESS)
|
if (buffer_len < sizeof (gxfp_enroll_init_t) + 1)
|
||||||
break;
|
return -1;
|
||||||
const uint8_t *tid;
|
if (presp->result == GX_SUCCESS)
|
||||||
if (!fpi_byte_reader_get_data (byte_reader, TEMPLATE_ID_SIZE, &tid))
|
memcpy (&presp->enroll_init.tid, &buffer[1], TEMPLATE_ID_SIZE);
|
||||||
g_return_val_if_reached (-1);
|
|
||||||
memcpy (presp->enroll_create.tid, tid, TEMPLATE_ID_SIZE);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MOC_CMD0_ENROLL:
|
case MOC_CMD0_ENROLL:
|
||||||
presp->enroll_update.rollback = (presp->result < 0x80) ? false : true;
|
if (buffer_len < sizeof (gxfp_enroll_update_t))
|
||||||
if (!fpi_byte_reader_get_uint8 (byte_reader,
|
return -1;
|
||||||
&presp->enroll_update.img_overlay))
|
presp->enroll_update.rollback = (buffer[0] < 0x80) ? false : true;
|
||||||
g_return_val_if_reached (-1);
|
presp->enroll_update.img_overlay = buffer[1];
|
||||||
|
presp->enroll_update.img_preoverlay = buffer[2];
|
||||||
if (!fpi_byte_reader_get_uint8 (byte_reader,
|
|
||||||
&presp->enroll_update.img_preoverlay))
|
|
||||||
g_return_val_if_reached (-1);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MOC_CMD0_CHECK4DUPLICATE:
|
case MOC_CMD0_CHECK4DUPLICATE:
|
||||||
presp->check_duplicate_resp.duplicate = (presp->result == 0) ? false : true;
|
presp->check_duplicate_resp.duplicate = (presp->result == 0) ? false : true;
|
||||||
if (presp->check_duplicate_resp.duplicate)
|
if (presp->check_duplicate_resp.duplicate)
|
||||||
{
|
{
|
||||||
uint16_t tid_size;
|
if (buffer_len < 3)
|
||||||
FpiByteReader tid_reader;
|
return -1;
|
||||||
|
uint16_t tid_size = GUINT16_FROM_LE (*(uint16_t *) (buffer + 1));
|
||||||
if (!fpi_byte_reader_get_uint16_le (byte_reader, &tid_size))
|
if ((buffer_len < tid_size + 3) || (buffer_len > sizeof (template_format_t)) + 3)
|
||||||
g_return_val_if_reached (-1);
|
return -1;
|
||||||
|
memcpy (&presp->check_duplicate_resp.template, buffer + 3, tid_size);
|
||||||
if (!fpi_byte_reader_get_sub_reader (byte_reader, &tid_reader, tid_size))
|
|
||||||
g_return_val_if_reached (-1);
|
|
||||||
|
|
||||||
if (gx_proto_parse_fingerid (&tid_reader, &presp->check_duplicate_resp.template) != 0)
|
|
||||||
g_return_val_if_reached (-1);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MOC_CMD0_GETFINGERLIST:
|
case MOC_CMD0_GETFINGERLIST:
|
||||||
if (presp->result != GX_SUCCESS)
|
if (presp->result != GX_SUCCESS)
|
||||||
break;
|
break;
|
||||||
|
if (buffer_len < 2)
|
||||||
if (!fpi_byte_reader_get_uint8 (byte_reader,
|
return -1;
|
||||||
&presp->finger_list_resp.finger_num))
|
presp->finger_list_resp.finger_num = buffer[1];
|
||||||
g_return_val_if_reached (-1);
|
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));
|
||||||
FpiByteReader fingerid_reader;
|
offset += 2;
|
||||||
|
if (buffer_len < fingerid_length + offset + 2)
|
||||||
if (!fpi_byte_reader_get_uint16_le (byte_reader, &fingerid_length))
|
return -1;
|
||||||
g_return_val_if_reached (-1);
|
if (gx_proto_parse_fingerid (fingerlist + offset,
|
||||||
|
fingerid_length,
|
||||||
if (!fpi_byte_reader_get_sub_reader (byte_reader, &fingerid_reader,
|
|
||||||
fingerid_length))
|
|
||||||
g_return_val_if_reached (-1);
|
|
||||||
|
|
||||||
if (gx_proto_parse_fingerid (&fingerid_reader,
|
|
||||||
&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");
|
||||||
g_return_val_if_reached (-1);
|
presp->finger_list_resp.finger_num = 0;
|
||||||
|
presp->result = GX_FAILED;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
offset += fingerid_length;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -439,32 +402,21 @@ gx_proto_parse_body (uint16_t cmd, FpiByteReader *byte_reader, pgxfp_cmd_respons
|
|||||||
uint32_t score = 0;
|
uint32_t score = 0;
|
||||||
uint8_t study = 0;
|
uint8_t study = 0;
|
||||||
uint16_t fingerid_size = 0;
|
uint16_t fingerid_size = 0;
|
||||||
|
presp->verify.match = (buffer[0] == 0) ? true : false;
|
||||||
presp->verify.match = (presp->result == 0) ? true : false;
|
|
||||||
|
|
||||||
if (presp->verify.match)
|
if (presp->verify.match)
|
||||||
{
|
{
|
||||||
FpiByteReader finger_reader;
|
if (buffer_len < sizeof (template_format_t) + 10)
|
||||||
|
return -1;
|
||||||
if (!fpi_byte_reader_get_uint16_le (byte_reader,
|
offset += 1;
|
||||||
&presp->verify.rejectdetail))
|
presp->verify.rejectdetail = GUINT16_FROM_LE (*(uint16_t *) (buffer + offset));
|
||||||
g_return_val_if_reached (-1);
|
offset += 2;
|
||||||
|
score = GUINT32_FROM_LE (*(uint32_t *) (buffer + offset));
|
||||||
if (!fpi_byte_reader_get_uint32_le (byte_reader, &score))
|
offset += 4;
|
||||||
g_return_val_if_reached (-1);
|
study = buffer[offset];
|
||||||
|
offset += 1;
|
||||||
if (!fpi_byte_reader_get_uint8 (byte_reader, &study))
|
fingerid_size = GUINT16_FROM_LE (*(uint16_t *) (buffer + offset));
|
||||||
g_return_val_if_reached (-1);
|
offset += 2;
|
||||||
|
if (gx_proto_parse_fingerid (buffer + offset, fingerid_size, &presp->verify.template) != 0)
|
||||||
if (!fpi_byte_reader_get_uint16_le (byte_reader, &fingerid_size))
|
|
||||||
g_return_val_if_reached (-1);
|
|
||||||
|
|
||||||
if (!fpi_byte_reader_get_sub_reader (byte_reader, &finger_reader,
|
|
||||||
fingerid_size))
|
|
||||||
g_return_val_if_reached (-1);
|
|
||||||
|
|
||||||
if (gx_proto_parse_fingerid (&finger_reader,
|
|
||||||
&presp->verify.template) != 0)
|
|
||||||
{
|
{
|
||||||
presp->result = GX_FAILED;
|
presp->result = GX_FAILED;
|
||||||
break;
|
break;
|
||||||
@@ -475,7 +427,7 @@ gx_proto_parse_body (uint16_t cmd, FpiByteReader *byte_reader, pgxfp_cmd_respons
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case MOC_CMD0_FINGER_MODE:
|
case MOC_CMD0_FINGER_MODE:
|
||||||
presp->finger_status.status = presp->result;
|
presp->finger_status.status = buffer[0];
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -22,8 +22,6 @@
|
|||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "fpi-byte-reader.h"
|
|
||||||
|
|
||||||
#define PACKAGE_CRC_SIZE (4)
|
#define PACKAGE_CRC_SIZE (4)
|
||||||
#define PACKAGE_HEADER_SIZE (8)
|
#define PACKAGE_HEADER_SIZE (8)
|
||||||
|
|
||||||
@@ -107,23 +105,21 @@ 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];
|
||||||
@@ -135,7 +131,7 @@ typedef struct _template_format
|
|||||||
typedef struct _gxfp_verify
|
typedef struct _gxfp_verify
|
||||||
{
|
{
|
||||||
bool match;
|
bool match;
|
||||||
uint16_t rejectdetail;
|
uint32_t rejectdetail;
|
||||||
template_format_t template;
|
template_format_t template;
|
||||||
} gxfp_verify_t, *pgxfp_verify_t;
|
} gxfp_verify_t, *pgxfp_verify_t;
|
||||||
|
|
||||||
@@ -194,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;
|
||||||
@@ -234,11 +230,13 @@ int gx_proto_build_package (uint8_t *ppackage,
|
|||||||
const uint8_t *payload,
|
const uint8_t *payload,
|
||||||
uint32_t payload_size);
|
uint32_t payload_size);
|
||||||
|
|
||||||
int gx_proto_parse_header (FpiByteReader *reader,
|
int gx_proto_parse_header (uint8_t *buffer,
|
||||||
|
uint32_t buffer_len,
|
||||||
pack_header *pheader);
|
pack_header *pheader);
|
||||||
|
|
||||||
int gx_proto_parse_body (uint16_t cmd,
|
int gx_proto_parse_body (uint16_t cmd,
|
||||||
FpiByteReader *byte_reader,
|
uint8_t *buffer,
|
||||||
|
uint16_t buffer_len,
|
||||||
pgxfp_cmd_response_t presponse);
|
pgxfp_cmd_response_t presponse);
|
||||||
|
|
||||||
int gx_proto_init_sensor_config (pgxfp_sensor_cfg_t pconfig);
|
int gx_proto_init_sensor_config (pgxfp_sensor_cfg_t pconfig);
|
||||||
|
|||||||
@@ -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},
|
|
||||||
};
|
|
||||||
@@ -256,7 +256,6 @@ bmkt_compose_message (uint8_t *cmd, int *cmd_len, uint8_t msg_id, uint8_t seq_nu
|
|||||||
cmd[BMKT_MESSAGE_SEQ_NUM_FIELD] = seq_num;
|
cmd[BMKT_MESSAGE_SEQ_NUM_FIELD] = seq_num;
|
||||||
cmd[BMKT_MESSAGE_ID_FIELD] = msg_id;
|
cmd[BMKT_MESSAGE_ID_FIELD] = msg_id;
|
||||||
cmd[BMKT_MESSAGE_PAYLOAD_LEN_FIELD] = payload_size;
|
cmd[BMKT_MESSAGE_PAYLOAD_LEN_FIELD] = payload_size;
|
||||||
if (payload_size > 0)
|
|
||||||
memcpy (&cmd[BMKT_MESSAGE_PAYLOAD_FIELD], payload, payload_size);
|
memcpy (&cmd[BMKT_MESSAGE_PAYLOAD_FIELD], payload, payload_size);
|
||||||
|
|
||||||
*cmd_len = message_len;
|
*cmd_len = message_len;
|
||||||
|
|||||||
@@ -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,34 +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 = 0x00C2, },
|
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0xE9, },
|
||||||
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x00C4, },
|
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0xDF, },
|
||||||
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x00C6, },
|
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0xF9, },
|
||||||
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x00DF, },
|
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0xFC, },
|
||||||
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x00F0, },
|
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0xC2, },
|
||||||
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x00F9, },
|
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0xC9, },
|
||||||
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x00FC, },
|
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0xE7, },
|
||||||
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0100, },
|
|
||||||
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0103, },
|
|
||||||
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0104, },
|
|
||||||
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0106, },
|
|
||||||
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0107, },
|
|
||||||
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0108, },
|
|
||||||
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0109, },
|
|
||||||
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x010A, },
|
|
||||||
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0123, },
|
|
||||||
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0124, },
|
|
||||||
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0126, },
|
|
||||||
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0129, },
|
|
||||||
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x015F, },
|
|
||||||
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0168, },
|
|
||||||
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0169, },
|
|
||||||
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x016C, },
|
|
||||||
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0173, },
|
|
||||||
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0174, },
|
|
||||||
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x019D, },
|
|
||||||
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x019F, },
|
|
||||||
{ .vid = 0, .pid = 0, .driver_data = 0 }, /* terminating entry */
|
{ .vid = 0, .pid = 0, .driver_data = 0 }, /* terminating entry */
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -120,10 +100,6 @@ cmd_receive_cb (FpiUsbTransfer *transfer,
|
|||||||
|
|
||||||
if (self->cmd_complete_on_removal)
|
if (self->cmd_complete_on_removal)
|
||||||
{
|
{
|
||||||
if (self->delay_error)
|
|
||||||
fpi_ssm_mark_failed (transfer->ssm,
|
|
||||||
g_steal_pointer (&self->delay_error));
|
|
||||||
else
|
|
||||||
fpi_ssm_mark_completed (transfer->ssm);
|
fpi_ssm_mark_completed (transfer->ssm);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -221,16 +197,11 @@ 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_SUSPENDED);
|
|
||||||
else
|
|
||||||
fpi_ssm_jump_to_state (transfer->ssm, SYNAPTICS_CMD_GET_RESP);
|
fpi_ssm_jump_to_state (transfer->ssm, SYNAPTICS_CMD_GET_RESP);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -245,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,
|
||||||
@@ -293,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);
|
||||||
@@ -323,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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -349,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -459,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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -506,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;
|
||||||
|
|
||||||
@@ -531,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)
|
||||||
{
|
{
|
||||||
@@ -555,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);
|
||||||
@@ -653,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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -685,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);
|
||||||
@@ -723,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
|
||||||
{
|
{
|
||||||
@@ -770,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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -778,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);
|
||||||
}
|
}
|
||||||
@@ -899,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);
|
||||||
@@ -1051,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);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1067,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;
|
||||||
}
|
}
|
||||||
@@ -1082,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);
|
|
||||||
if (resp->result == BMKT_FP_DATABASE_NO_RECORD_EXISTS ||
|
|
||||||
resp->result == BMKT_FP_DATABASE_EMPTY)
|
|
||||||
{
|
|
||||||
fp_info ("Database no record");
|
|
||||||
fpi_device_delete_complete (device, NULL);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
fp_info ("Failed to delete enrolled user: %d", resp->result);
|
fp_info ("Failed to delete enrolled user: %d", resp->result);
|
||||||
|
if (resp->result == BMKT_FP_DATABASE_NO_RECORD_EXISTS)
|
||||||
|
fpi_device_delete_complete (device,
|
||||||
|
fpi_device_error_new (FP_DEVICE_ERROR_DATA_NOT_FOUND));
|
||||||
|
else
|
||||||
fpi_device_delete_complete (device,
|
fpi_device_delete_complete (device,
|
||||||
fpi_device_error_new (FP_DEVICE_ERROR_GENERAL));
|
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;
|
||||||
}
|
}
|
||||||
@@ -1134,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,
|
||||||
@@ -1193,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1213,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
|
||||||
{
|
{
|
||||||
@@ -1259,10 +1197,7 @@ dev_probe (FpDevice *device)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!g_usb_device_reset (usb_dev, &error))
|
if (!g_usb_device_reset (usb_dev, &error))
|
||||||
{
|
|
||||||
fp_dbg ("%s g_usb_device_reset failed %s", G_STRFUNC, error->message);
|
|
||||||
goto err_close;
|
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;
|
||||||
@@ -1352,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;
|
||||||
}
|
}
|
||||||
@@ -1364,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);
|
||||||
@@ -1380,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);
|
||||||
|
|
||||||
@@ -1418,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;
|
||||||
@@ -1456,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)
|
||||||
{
|
{
|
||||||
@@ -1526,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;
|
||||||
@@ -1535,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>
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ struct _FpiDeviceUpeksonly
|
|||||||
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;
|
||||||
|
|
||||||
@@ -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 },
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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,10 +346,6 @@ 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_press, sizeof (upek2020_init_capture_press),
|
|
||||||
self->seq, capture_reqs_cb);
|
|
||||||
else
|
|
||||||
upektc_img_submit_req (ssm, dev, upek2020_init_capture, sizeof (upek2020_init_capture),
|
upektc_img_submit_req (ssm, dev, upek2020_init_capture, sizeof (upek2020_init_capture),
|
||||||
self->seq, capture_reqs_cb);
|
self->seq, capture_reqs_cb);
|
||||||
self->seq++;
|
self->seq++;
|
||||||
@@ -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);
|
|
||||||
unsigned char *data = self->response;
|
|
||||||
|
|
||||||
if (error)
|
|
||||||
{
|
|
||||||
fpi_ssm_mark_failed (transfer->ssm, error);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data[12] == 0x06 && data[13] == 0x14) /* if get_info */
|
|
||||||
{
|
|
||||||
FpImageDeviceClass *img_class = FP_IMAGE_DEVICE_GET_CLASS (dev);
|
|
||||||
uint16_t width = (data[51] << 8) | data[50];
|
|
||||||
uint16_t height = (data[53] << 8) | data[52];
|
|
||||||
|
|
||||||
self->area_sensor = !(data[49] & 0x80);
|
|
||||||
|
|
||||||
switch (width)
|
|
||||||
{
|
|
||||||
case 256:
|
|
||||||
fp_dbg ("Sensor type : TCS1x, width x height: %hu x %hu", width, height); /* 360x256 --- 270x192 must be set */
|
|
||||||
BUG_ON (height != 360);
|
|
||||||
img_class->img_width = 192;
|
|
||||||
img_class->img_height = 270;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 208:
|
|
||||||
fp_dbg ("Sensor type : TCS2, width x height: %hu x %hu", width, height); /* 288x208 --- 216x156 must be set */
|
|
||||||
BUG_ON (height != 288);
|
|
||||||
img_class->img_width = 156;
|
|
||||||
img_class->img_height = 216;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 248:
|
|
||||||
fp_dbg ("Sensor type : TCS3, width x height: %hu x %hu", width, height); /* 360x248 --- 270x186 must be set */
|
|
||||||
BUG_ON (height != 360);
|
|
||||||
img_class->img_width = 186;
|
|
||||||
img_class->img_height = 270;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 192:
|
|
||||||
fp_dbg ("Sensor type : TCS4x, width x height: %hu x %hu", width, height); /* 512x192 --- 384x144 must be set */
|
|
||||||
BUG_ON (height != 512);
|
|
||||||
img_class->img_width = 144;
|
|
||||||
img_class->img_height = 384;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 144:
|
|
||||||
fp_dbg ("Sensor type : TCS5x, width x height: %hu x %hu", width, height); /* 512x144 --- 384x108 must be set */
|
|
||||||
BUG_ON (height != 512);
|
|
||||||
img_class->img_width = 108;
|
|
||||||
img_class->img_height = 384;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
fp_dbg ("Sensor type : Unknown");
|
|
||||||
|
|
||||||
fpi_ssm_mark_failed (transfer->ssm,
|
|
||||||
fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
|
|
||||||
"Unknown sensor type (reported size %dx%d)",
|
|
||||||
width, height));
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
self->expected_image_size = img_class->img_width * img_class->img_height;
|
|
||||||
self->image_bits = g_malloc0 (self->expected_image_size * 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
fpi_ssm_next_state (transfer->ssm);
|
fpi_ssm_next_state (transfer->ssm);
|
||||||
|
else
|
||||||
|
fpi_ssm_mark_failed (transfer->ssm, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
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 */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -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"
|
||||||
@@ -196,8 +195,7 @@ struct read_msg_data
|
|||||||
static void __read_msg_async (FpDevice *dev,
|
static void __read_msg_async (FpDevice *dev,
|
||||||
struct read_msg_data *udata);
|
struct read_msg_data *udata);
|
||||||
|
|
||||||
#define READ_MSG_DATA_CB_ERR(dev, udata, error) \
|
#define READ_MSG_DATA_CB_ERR(dev, udata, error) (udata)->callback (dev, \
|
||||||
(udata)->callback (dev, \
|
|
||||||
READ_MSG_CMD, 0, 0, NULL, 0, (udata)->user_data, error)
|
READ_MSG_CMD, 0, 0, NULL, 0, (udata)->user_data, error)
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -367,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;
|
||||||
}
|
}
|
||||||
@@ -994,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"));
|
||||||
@@ -1091,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)
|
||||||
@@ -1244,7 +1242,7 @@ do_verify_stop (FpDevice *dev, FpiMatchResult res, GError *error)
|
|||||||
FpiSsm *ssm = deinitsm_new (dev, data);
|
FpiSsm *ssm = deinitsm_new (dev, data);
|
||||||
|
|
||||||
/* Report the error immediately if possible, otherwise delay it. */
|
/* Report the error immediately if possible, otherwise delay it. */
|
||||||
if (!error || error->domain == FP_DEVICE_RETRY)
|
if (error && error->domain == FP_DEVICE_RETRY)
|
||||||
fpi_device_verify_report (dev, res, NULL, error);
|
fpi_device_verify_report (dev, res, NULL, error);
|
||||||
else
|
else
|
||||||
data->error = error;
|
data->error = error;
|
||||||
@@ -1296,7 +1294,7 @@ verify_start_sm_run_state (FpiSsm *ssm, FpDevice *dev)
|
|||||||
memcpy (msg, verify_hdr, sizeof (verify_hdr));
|
memcpy (msg, verify_hdr, sizeof (verify_hdr));
|
||||||
memcpy (msg + sizeof (verify_hdr), data, data_len);
|
memcpy (msg + sizeof (verify_hdr), data, data_len);
|
||||||
|
|
||||||
transfer = alloc_send_cmd28_transfer (dev, 0x03, msg, msg_len);
|
transfer = alloc_send_cmd28_transfer (dev, 0x03, data, data_len);
|
||||||
|
|
||||||
g_free (msg);
|
g_free (msg);
|
||||||
|
|
||||||
@@ -1319,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;
|
||||||
}
|
}
|
||||||
@@ -1342,6 +1340,7 @@ v_handle_resp00 (FpDevice *dev, unsigned char *data,
|
|||||||
fp_dbg ("good image");
|
fp_dbg ("good image");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 0x1c: /* FIXME what does this one mean? */
|
||||||
case 0x0b: /* FIXME what does this one mean? */
|
case 0x0b: /* FIXME what does this one mean? */
|
||||||
case 0x23: /* FIXME what does this one mean? */
|
case 0x23: /* FIXME what does this one mean? */
|
||||||
error = fpi_device_retry_new (FP_DEVICE_RETRY_GENERAL);
|
error = fpi_device_retry_new (FP_DEVICE_RETRY_GENERAL);
|
||||||
@@ -1351,14 +1350,6 @@ v_handle_resp00 (FpDevice *dev, unsigned char *data,
|
|||||||
error = fpi_device_retry_new (FP_DEVICE_RETRY_REMOVE_FINGER);
|
error = fpi_device_retry_new (FP_DEVICE_RETRY_REMOVE_FINGER);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x1c: /* swipe too fast */
|
|
||||||
error = fpi_device_retry_new (FP_DEVICE_RETRY_TOO_FAST);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 0x1d: /* too much horizontal movement */
|
|
||||||
error = fpi_device_retry_new (FP_DEVICE_RETRY_CENTER_FINGER);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 0x1e: /* swipe too short */
|
case 0x1e: /* swipe too short */
|
||||||
error = fpi_device_retry_new (FP_DEVICE_RETRY_TOO_SHORT);
|
error = fpi_device_retry_new (FP_DEVICE_RETRY_TOO_SHORT);
|
||||||
break;
|
break;
|
||||||
@@ -1447,7 +1438,7 @@ verify_rd2800_cb (FpDevice *dev, enum read_msg_type msgtype,
|
|||||||
do_verify_stop (dev,
|
do_verify_stop (dev,
|
||||||
FPI_MATCH_ERROR,
|
FPI_MATCH_ERROR,
|
||||||
fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
|
fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
|
||||||
"Response had wrong command sequence"));
|
"Response hat wrong command sequence"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1564,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);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,8 +20,8 @@
|
|||||||
|
|
||||||
#define FP_COMPONENT "uru4000"
|
#define FP_COMPONENT "uru4000"
|
||||||
|
|
||||||
#include <openssl/evp.h>
|
#include <nss.h>
|
||||||
#include <openssl/err.h>
|
#include <pk11pub.h>
|
||||||
|
|
||||||
#include "drivers_api.h"
|
#include "drivers_api.h"
|
||||||
|
|
||||||
@@ -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;
|
||||||
@@ -148,7 +147,10 @@ struct _FpiDeviceUru4000
|
|||||||
int fwfixer_offset;
|
int fwfixer_offset;
|
||||||
unsigned char fwfixer_value;
|
unsigned char fwfixer_value;
|
||||||
|
|
||||||
EVP_CIPHER_CTX *cipher_ctx;
|
CK_MECHANISM_TYPE cipher;
|
||||||
|
PK11SlotInfo *slot;
|
||||||
|
PK11SymKey *symkey;
|
||||||
|
SECItem *param;
|
||||||
};
|
};
|
||||||
G_DECLARE_FINAL_TYPE (FpiDeviceUru4000, fpi_device_uru4000, FPI, DEVICE_URU4000,
|
G_DECLARE_FINAL_TYPE (FpiDeviceUru4000, fpi_device_uru4000, FPI, DEVICE_URU4000,
|
||||||
FpImageDevice);
|
FpImageDevice);
|
||||||
@@ -243,29 +245,13 @@ response_cb (FpiUsbTransfer *transfer, FpDevice *dev, void *user_data, GError *e
|
|||||||
fpi_ssm_mark_failed (ssm, error);
|
fpi_ssm_mark_failed (ssm, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
static GError *
|
|
||||||
openssl_device_error (void)
|
|
||||||
{
|
|
||||||
char buf[256];
|
|
||||||
unsigned long e;
|
|
||||||
|
|
||||||
e = ERR_get_error ();
|
|
||||||
if (e == 0)
|
|
||||||
return fpi_device_error_new_msg (FP_DEVICE_ERROR_GENERAL,
|
|
||||||
"unexpected OpenSSL error");
|
|
||||||
|
|
||||||
ERR_error_string_n (e, buf, G_N_ELEMENTS (buf));
|
|
||||||
|
|
||||||
return fpi_device_error_new_msg (FP_DEVICE_ERROR_GENERAL, "OpenSSL error: %s",
|
|
||||||
buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
challenge_cb (FpiUsbTransfer *transfer, FpDevice *dev, void *user_data, GError *error)
|
challenge_cb (FpiUsbTransfer *transfer, FpDevice *dev, void *user_data, GError *error)
|
||||||
{
|
{
|
||||||
FpiSsm *ssm = user_data;
|
FpiSsm *ssm = user_data;
|
||||||
FpiDeviceUru4000 *self = FPI_DEVICE_URU4000 (dev);
|
FpiDeviceUru4000 *self = FPI_DEVICE_URU4000 (dev);
|
||||||
unsigned char respdata[CR_LENGTH * 2];
|
unsigned char respdata[CR_LENGTH];
|
||||||
|
PK11Context *ctx;
|
||||||
int outlen;
|
int outlen;
|
||||||
|
|
||||||
if (error)
|
if (error)
|
||||||
@@ -274,39 +260,17 @@ challenge_cb (FpiUsbTransfer *transfer, FpDevice *dev, void *user_data, GError *
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (transfer->actual_length != CR_LENGTH)
|
|
||||||
{
|
|
||||||
error = fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
|
|
||||||
"Unexpected buffer length (%" G_GSIZE_FORMAT
|
|
||||||
"instead of %d)",
|
|
||||||
transfer->actual_length, CR_LENGTH);
|
|
||||||
fpi_ssm_mark_failed (ssm, g_steal_pointer (&error));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* submit response */
|
/* submit response */
|
||||||
/* produce response from challenge */
|
/* produce response from challenge */
|
||||||
if (!EVP_EncryptUpdate (self->cipher_ctx, respdata, &outlen, transfer->buffer, CR_LENGTH))
|
ctx = PK11_CreateContextBySymKey (self->cipher, CKA_ENCRYPT,
|
||||||
|
self->symkey, self->param);
|
||||||
|
if (PK11_CipherOp (ctx, respdata, &outlen, CR_LENGTH, transfer->buffer, CR_LENGTH) != SECSuccess ||
|
||||||
|
PK11_Finalize (ctx) != SECSuccess)
|
||||||
{
|
{
|
||||||
fpi_ssm_mark_failed (ssm, openssl_device_error ());
|
fp_err ("Failed to encrypt challenge data");
|
||||||
return;
|
error = fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO, "Failed to encrypt challenge data");
|
||||||
}
|
|
||||||
|
|
||||||
if (outlen != CR_LENGTH)
|
|
||||||
{
|
|
||||||
error = fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
|
|
||||||
"Unexpected encrypted buffer length (%d"
|
|
||||||
"instead of %d)",
|
|
||||||
outlen, CR_LENGTH);
|
|
||||||
fpi_ssm_mark_failed (ssm, g_steal_pointer (&error));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!EVP_EncryptFinal_ex (self->cipher_ctx, respdata + outlen, &outlen))
|
|
||||||
{
|
|
||||||
fpi_ssm_mark_failed (ssm, openssl_device_error ());
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
PK11_DestroyContext (ctx, PR_TRUE);
|
||||||
|
|
||||||
if (!error)
|
if (!error)
|
||||||
write_regs (FP_IMAGE_DEVICE (dev), REG_RESPONSE, CR_LENGTH, respdata, response_cb, ssm);
|
write_regs (FP_IMAGE_DEVICE (dev), REG_RESPONSE, CR_LENGTH, respdata, response_cb, ssm);
|
||||||
@@ -352,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)
|
||||||
@@ -396,7 +359,7 @@ 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);
|
||||||
@@ -434,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);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -587,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);
|
||||||
}
|
}
|
||||||
@@ -738,9 +701,9 @@ imaging_run_state (FpiSsm *ssm, FpDevice *_dev)
|
|||||||
|
|
||||||
case IMAGING_DECODE:
|
case IMAGING_DECODE:
|
||||||
key = self->last_reg_rd[0];
|
key = self->last_reg_rd[0];
|
||||||
key |= (uint32_t) self->last_reg_rd[1] << 8;
|
key |= self->last_reg_rd[1] << 8;
|
||||||
key |= (uint32_t) self->last_reg_rd[2] << 16;
|
key |= self->last_reg_rd[2] << 16;
|
||||||
key |= (uint32_t) self->last_reg_rd[3] << 24;
|
key |= self->last_reg_rd[3] << 24;
|
||||||
key ^= self->img_enc_seed;
|
key ^= self->img_enc_seed;
|
||||||
|
|
||||||
fp_dbg ("encryption id %02x -> key %08x", img->key_number, key);
|
fp_dbg ("encryption id %02x -> key %08x", img->key_number, key);
|
||||||
@@ -759,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;
|
||||||
}
|
}
|
||||||
@@ -903,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;
|
||||||
}
|
}
|
||||||
@@ -985,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;
|
||||||
|
|
||||||
@@ -1257,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;
|
||||||
@@ -1305,6 +1266,8 @@ dev_init (FpImageDevice *dev)
|
|||||||
g_autoptr(GPtrArray) interfaces = NULL;
|
g_autoptr(GPtrArray) interfaces = NULL;
|
||||||
GUsbInterface *iface = NULL;
|
GUsbInterface *iface = NULL;
|
||||||
guint64 driver_data;
|
guint64 driver_data;
|
||||||
|
SECStatus rv;
|
||||||
|
SECItem item;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
interfaces = g_usb_device_get_interfaces (fpi_device_get_usb_device (FP_DEVICE (dev)), &error);
|
interfaces = g_usb_device_get_interfaces (fpi_device_get_usb_device (FP_DEVICE (dev)), &error);
|
||||||
@@ -1376,29 +1339,56 @@ dev_init (FpImageDevice *dev)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
self = FPI_DEVICE_URU4000 (dev);
|
/* Disable loading p11-kit's user configuration */
|
||||||
|
g_setenv ("P11_KIT_NO_USER_CONFIG", "1", TRUE);
|
||||||
|
|
||||||
g_clear_pointer (&self->rand, g_rand_free);
|
/* Initialise NSS early */
|
||||||
self->rand = g_rand_new ();
|
rv = NSS_NoDB_Init (".");
|
||||||
if (g_strcmp0 (g_getenv ("FP_DEVICE_EMULATION"), "1") == 0)
|
if (rv != SECSuccess)
|
||||||
g_rand_set_seed (self->rand, 0xFACADE);
|
{
|
||||||
|
fp_err ("could not initialise NSS");
|
||||||
|
fpi_image_device_open_complete (dev,
|
||||||
|
fpi_device_error_new_msg (FP_DEVICE_ERROR_GENERAL,
|
||||||
|
"Could not initialise NSS"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
self = FPI_DEVICE_URU4000 (dev);
|
||||||
|
|
||||||
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);
|
||||||
|
|
||||||
/* Set up encryption */
|
/* Set up encryption */
|
||||||
if (!(self->cipher_ctx = EVP_CIPHER_CTX_new ()))
|
self->cipher = CKM_AES_ECB;
|
||||||
|
self->slot = PK11_GetBestSlot (self->cipher, NULL);
|
||||||
|
if (self->slot == NULL)
|
||||||
{
|
{
|
||||||
fpi_image_device_open_complete (dev, openssl_device_error ());
|
fp_err ("could not get encryption slot");
|
||||||
|
fpi_image_device_open_complete (dev,
|
||||||
|
fpi_device_error_new_msg (FP_DEVICE_ERROR_GENERAL,
|
||||||
|
"Could not get encryption slot"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
item.type = siBuffer;
|
||||||
if (!EVP_EncryptInit_ex (self->cipher_ctx, EVP_aes_128_ecb (), NULL, crkey, NULL))
|
item.data = (unsigned char *) crkey;
|
||||||
|
item.len = sizeof (crkey);
|
||||||
|
self->symkey = PK11_ImportSymKey (self->slot,
|
||||||
|
self->cipher,
|
||||||
|
PK11_OriginUnwrap,
|
||||||
|
CKA_ENCRYPT,
|
||||||
|
&item, NULL);
|
||||||
|
if (self->symkey == NULL)
|
||||||
{
|
{
|
||||||
fpi_image_device_open_complete (dev, openssl_device_error ());
|
fp_err ("failed to import key into NSS");
|
||||||
|
PK11_FreeSlot (self->slot);
|
||||||
|
self->slot = NULL;
|
||||||
|
fpi_image_device_open_complete (dev,
|
||||||
|
fpi_device_error_new_msg (FP_DEVICE_ERROR_GENERAL,
|
||||||
|
"Failed to import key into NSS"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
self->param = PK11_ParamFromIV (self->cipher, NULL);
|
||||||
|
|
||||||
fpi_image_device_open_complete (dev, NULL);
|
fpi_image_device_open_complete (dev, NULL);
|
||||||
}
|
}
|
||||||
@@ -1409,11 +1399,14 @@ dev_deinit (FpImageDevice *dev)
|
|||||||
GError *error = NULL;
|
GError *error = NULL;
|
||||||
FpiDeviceUru4000 *self = FPI_DEVICE_URU4000 (dev);
|
FpiDeviceUru4000 *self = FPI_DEVICE_URU4000 (dev);
|
||||||
|
|
||||||
g_clear_pointer (&self->cipher_ctx, EVP_CIPHER_CTX_free);
|
if (self->symkey)
|
||||||
|
PK11_FreeSymKey (self->symkey);
|
||||||
|
if (self->param)
|
||||||
|
SECITEM_FreeItem (self->param, PR_TRUE);
|
||||||
|
if (self->slot)
|
||||||
|
PK11_FreeSlot (self->slot);
|
||||||
g_usb_device_release_interface (fpi_device_get_usb_device (FP_DEVICE (dev)),
|
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:
|
||||||
|
|||||||
@@ -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:
|
||||||
|
|||||||
@@ -432,7 +432,7 @@ img_process_data (int first_block, FpDeviceVfs301 *dev, const guint8 *buf, int l
|
|||||||
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};
|
||||||
|
|||||||
@@ -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,7 +28,7 @@
|
|||||||
|
|
||||||
#include "virtual-device-private.h"
|
#include "virtual-device-private.h"
|
||||||
|
|
||||||
struct _FpiDeviceVirtualListener
|
struct _FpDeviceVirtualListener
|
||||||
{
|
{
|
||||||
GSocketListener parent_instance;
|
GSocketListener parent_instance;
|
||||||
|
|
||||||
@@ -36,27 +36,27 @@ struct _FpiDeviceVirtualListener
|
|||||||
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,
|
||||||
@@ -133,26 +133,26 @@ 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,7 +282,7 @@ 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,
|
||||||
@@ -293,7 +292,7 @@ fpi_device_virtual_listener_read (FpiDeviceVirtualListener *self,
|
|||||||
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,7 +324,7 @@ 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)
|
||||||
{
|
{
|
||||||
@@ -335,7 +334,7 @@ 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)
|
||||||
|
|||||||
@@ -32,33 +32,33 @@
|
|||||||
|
|
||||||
#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);
|
||||||
@@ -68,7 +68,7 @@ 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];
|
||||||
@@ -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);
|
|
||||||
gboolean start_scan_command (FpDeviceVirtualDevice *self,
|
|
||||||
char **scan_id,
|
|
||||||
GError **error);
|
GError **error);
|
||||||
|
gboolean should_wait_for_command (FpDeviceVirtualDevice *self,
|
||||||
|
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;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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,13 +306,13 @@ 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),
|
||||||
@@ -368,7 +321,7 @@ recv_instruction (FpDeviceVirtualDevice *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,34 +334,31 @@ 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,
|
||||||
@@ -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);
|
||||||
}
|
}
|
||||||
@@ -772,7 +762,6 @@ fpi_device_virtual_device_class_init (FpDeviceVirtualDeviceClass *klass)
|
|||||||
{
|
{
|
||||||
FpDeviceClass *dev_class = FP_DEVICE_CLASS (klass);
|
FpDeviceClass *dev_class = FP_DEVICE_CLASS (klass);
|
||||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||||
const char *hot_seconds;
|
|
||||||
|
|
||||||
object_class->finalize = fpi_device_virtual_device_finalize;
|
object_class->finalize = fpi_device_virtual_device_finalize;
|
||||||
|
|
||||||
@@ -787,19 +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;
|
||||||
|
|
||||||
if ((hot_seconds = g_getenv ("FP_VIRTUAL_DEVICE_HOT_SECONDS")) &&
|
|
||||||
*hot_seconds != '\0')
|
|
||||||
{
|
|
||||||
gint64 hot_seconds_value;
|
|
||||||
|
|
||||||
hot_seconds_value = g_ascii_strtoll (hot_seconds, NULL, 10);
|
|
||||||
if (hot_seconds_value >= G_MAXINT32 || hot_seconds_value < 0)
|
|
||||||
hot_seconds_value = -1;
|
|
||||||
|
|
||||||
dev_class->temp_hot_seconds = hot_seconds_value;
|
|
||||||
g_debug ("device hot seconds set to %d", dev_class->temp_hot_seconds);
|
|
||||||
}
|
|
||||||
|
|
||||||
fpi_device_class_auto_initialize_features (dev_class);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ struct _FpDeviceVirtualImage
|
|||||||
{
|
{
|
||||||
FpImageDevice parent;
|
FpImageDevice parent;
|
||||||
|
|
||||||
FpiDeviceVirtualListener *listener;
|
FpDeviceVirtualListener *listener;
|
||||||
GCancellable *cancellable;
|
GCancellable *cancellable;
|
||||||
|
|
||||||
gboolean automatic_finger;
|
gboolean automatic_finger;
|
||||||
@@ -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,7 +157,7 @@ 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,
|
||||||
@@ -168,7 +168,7 @@ recv_image_hdr_recv_cb (GObject *source_object,
|
|||||||
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),
|
||||||
@@ -177,7 +177,7 @@ recv_image (FpDeviceVirtualImage *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);
|
||||||
@@ -188,37 +188,27 @@ 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)
|
|
||||||
{
|
|
||||||
case FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON:
|
|
||||||
case FPI_IMAGE_DEVICE_STATE_CAPTURE:
|
|
||||||
recv_image (self);
|
recv_image (self);
|
||||||
|
|
||||||
case FPI_IMAGE_DEVICE_STATE_IDLE:
|
|
||||||
case FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_OFF:
|
|
||||||
case FPI_IMAGE_DEVICE_STATE_INACTIVE:
|
|
||||||
case FPI_IMAGE_DEVICE_STATE_ACTIVATING:
|
|
||||||
case FPI_IMAGE_DEVICE_STATE_DEACTIVATING:
|
|
||||||
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,
|
||||||
@@ -310,7 +300,6 @@ fpi_device_virtual_image_class_init (FpDeviceVirtualImageClass *klass)
|
|||||||
{
|
{
|
||||||
FpDeviceClass *dev_class = FP_DEVICE_CLASS (klass);
|
FpDeviceClass *dev_class = FP_DEVICE_CLASS (klass);
|
||||||
FpImageDeviceClass *img_class = FP_IMAGE_DEVICE_CLASS (klass);
|
FpImageDeviceClass *img_class = FP_IMAGE_DEVICE_CLASS (klass);
|
||||||
const char *hot_seconds;
|
|
||||||
|
|
||||||
dev_class->id = FP_COMPONENT;
|
dev_class->id = FP_COMPONENT;
|
||||||
dev_class->full_name = "Virtual image device for debugging";
|
dev_class->full_name = "Virtual image device for debugging";
|
||||||
@@ -322,17 +311,4 @@ fpi_device_virtual_image_class_init (FpDeviceVirtualImageClass *klass)
|
|||||||
|
|
||||||
img_class->activate = dev_activate;
|
img_class->activate = dev_activate;
|
||||||
img_class->deactivate = dev_deactivate;
|
img_class->deactivate = dev_deactivate;
|
||||||
|
|
||||||
if ((hot_seconds = g_getenv ("FP_VIRTUAL_IMAGE_HOT_SECONDS")) &&
|
|
||||||
*hot_seconds != '\0')
|
|
||||||
{
|
|
||||||
gint64 hot_seconds_value;
|
|
||||||
|
|
||||||
hot_seconds_value = g_ascii_strtoll (hot_seconds, NULL, 10);
|
|
||||||
if (hot_seconds_value >= G_MAXINT32 || hot_seconds_value < 0)
|
|
||||||
hot_seconds_value = -1;
|
|
||||||
|
|
||||||
dev_class->temp_hot_seconds = hot_seconds_value;
|
|
||||||
g_debug ("device hot seconds set to %d", dev_class->temp_hot_seconds);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
676
libfprint/drivers/virtual-sdcp.c
Normal file
676
libfprint/drivers/virtual-sdcp.c
Normal file
@@ -0,0 +1,676 @@
|
|||||||
|
/*
|
||||||
|
* Virtual driver for SDCP device debugging
|
||||||
|
*
|
||||||
|
* Copyright (C) 2020 Benjamin Berg <bberg@redhat.com>
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is a virtual test driver to test the basic SDCP functionality.
|
||||||
|
* It uses the test binaries from Microsoft, which were extended to allow
|
||||||
|
* a simple chat with the device.
|
||||||
|
* The environment variable contains the to be executed binary including
|
||||||
|
* arguments. This binary should be compiled from the code in
|
||||||
|
* https://github.com/Microsoft/SecureDeviceConnectionProtocol
|
||||||
|
* or, until it is merged upstream
|
||||||
|
* https://github.com/benzea/SecureDeviceConnectionProtocol
|
||||||
|
*
|
||||||
|
* Note that using this as an external executable has the advantage that we
|
||||||
|
* do not need to link against mbedtls or any other crypto library.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define FP_COMPONENT "virtual_sdcp"
|
||||||
|
|
||||||
|
#include "fpi-log.h"
|
||||||
|
#include "fpi-ssm.h"
|
||||||
|
|
||||||
|
#include "../fpi-sdcp-device.h"
|
||||||
|
|
||||||
|
#include <glib/gstdio.h>
|
||||||
|
#include <gio/gio.h>
|
||||||
|
|
||||||
|
struct _FpDeviceVirtualSdcp
|
||||||
|
{
|
||||||
|
FpSdcpDevice parent;
|
||||||
|
|
||||||
|
GSubprocess *proc;
|
||||||
|
GOutputStream *proc_stdin;
|
||||||
|
GInputStream *proc_stdout;
|
||||||
|
|
||||||
|
/* Only valid while a read/write is pending */
|
||||||
|
GByteArray *msg_out;
|
||||||
|
GByteArray *msg_in;
|
||||||
|
|
||||||
|
GByteArray *connect_msg;
|
||||||
|
};
|
||||||
|
|
||||||
|
G_DECLARE_FINAL_TYPE (FpDeviceVirtualSdcp, fpi_device_virtual_sdcp, FPI, DEVICE_VIRTUAL_SDCP, FpSdcpDevice)
|
||||||
|
G_DEFINE_TYPE (FpDeviceVirtualSdcp, fpi_device_virtual_sdcp, FP_TYPE_SDCP_DEVICE)
|
||||||
|
|
||||||
|
guint8 ca_1[] = {
|
||||||
|
0x30, 0x82, 0x03, 0xFD, 0x30, 0x82, 0x03, 0x82, 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x13, 0x33,
|
||||||
|
0x00, 0x00, 0x00, 0x07, 0xE8, 0x9D, 0x61, 0x62, 0x4D, 0x46, 0x0F, 0x95, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x07, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x30, 0x81,
|
||||||
|
0x84, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13,
|
||||||
|
0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0A, 0x57, 0x61, 0x73, 0x68, 0x69, 0x6E, 0x67,
|
||||||
|
0x74, 0x6F, 0x6E, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x52, 0x65,
|
||||||
|
0x64, 0x6D, 0x6F, 0x6E, 0x64, 0x31, 0x1E, 0x30, 0x1C, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x15,
|
||||||
|
0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72,
|
||||||
|
0x61, 0x74, 0x69, 0x6F, 0x6E, 0x31, 0x2E, 0x30, 0x2C, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x25,
|
||||||
|
0x57, 0x69, 0x6E, 0x64, 0x6F, 0x77, 0x73, 0x20, 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x53, 0x65,
|
||||||
|
0x63, 0x75, 0x72, 0x65, 0x20, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x20, 0x50, 0x43, 0x41,
|
||||||
|
0x20, 0x32, 0x30, 0x31, 0x38, 0x30, 0x1E, 0x17, 0x0D, 0x31, 0x38, 0x30, 0x31, 0x33, 0x31, 0x31,
|
||||||
|
0x39, 0x35, 0x34, 0x35, 0x33, 0x5A, 0x17, 0x0D, 0x32, 0x38, 0x30, 0x31, 0x33, 0x31, 0x32, 0x30,
|
||||||
|
0x30, 0x34, 0x35, 0x33, 0x5A, 0x30, 0x7D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
|
||||||
|
0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0A, 0x57,
|
||||||
|
0x61, 0x73, 0x68, 0x69, 0x6E, 0x67, 0x74, 0x6F, 0x6E, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55,
|
||||||
|
0x04, 0x07, 0x13, 0x07, 0x52, 0x65, 0x64, 0x6D, 0x6F, 0x6E, 0x64, 0x31, 0x1E, 0x30, 0x1C, 0x06,
|
||||||
|
0x03, 0x55, 0x04, 0x0A, 0x13, 0x15, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20,
|
||||||
|
0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x31, 0x27, 0x30, 0x25, 0x06,
|
||||||
|
0x03, 0x55, 0x04, 0x03, 0x13, 0x1E, 0x57, 0x69, 0x6E, 0x64, 0x6F, 0x77, 0x73, 0x20, 0x48, 0x65,
|
||||||
|
0x6C, 0x6C, 0x6F, 0x20, 0x31, 0x39, 0x42, 0x39, 0x32, 0x39, 0x36, 0x35, 0x20, 0x43, 0x41, 0x20,
|
||||||
|
0x32, 0x30, 0x31, 0x38, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02,
|
||||||
|
0x01, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0xBE,
|
||||||
|
0x4B, 0x90, 0x6E, 0x24, 0xFC, 0xA1, 0x53, 0xC8, 0xA7, 0x3C, 0x70, 0xE8, 0x97, 0xCD, 0x1B, 0x31,
|
||||||
|
0xE4, 0x95, 0x91, 0x7A, 0x58, 0xA2, 0x86, 0xA8, 0x70, 0xF6, 0x09, 0x30, 0x77, 0x99, 0x3D, 0x10,
|
||||||
|
0xDF, 0xF7, 0x95, 0x0F, 0x68, 0x83, 0xE6, 0xA4, 0x11, 0x7C, 0xDA, 0x82, 0xE7, 0x0B, 0x8B, 0xF2,
|
||||||
|
0x9D, 0x6B, 0x5B, 0xF5, 0x3E, 0x77, 0xB4, 0xC1, 0x0E, 0x49, 0x00, 0x83, 0xBA, 0x94, 0xF8, 0xA3,
|
||||||
|
0x82, 0x01, 0xD7, 0x30, 0x82, 0x01, 0xD3, 0x30, 0x10, 0x06, 0x09, 0x2B, 0x06, 0x01, 0x04, 0x01,
|
||||||
|
0x82, 0x37, 0x15, 0x01, 0x04, 0x03, 0x02, 0x01, 0x00, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E,
|
||||||
|
0x04, 0x16, 0x04, 0x14, 0x13, 0x93, 0xC8, 0xCD, 0xF2, 0x23, 0x9A, 0x2D, 0xC6, 0x9B, 0x2A, 0xEB,
|
||||||
|
0x9A, 0xAB, 0x99, 0x0B, 0x56, 0x04, 0x5E, 0x7C, 0x30, 0x65, 0x06, 0x03, 0x55, 0x1D, 0x20, 0x04,
|
||||||
|
0x5E, 0x30, 0x5C, 0x30, 0x06, 0x06, 0x04, 0x55, 0x1D, 0x20, 0x00, 0x30, 0x52, 0x06, 0x0C, 0x2B,
|
||||||
|
0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x4C, 0x83, 0x7D, 0x01, 0x01, 0x30, 0x42, 0x30, 0x40, 0x06,
|
||||||
|
0x08, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x02, 0x01, 0x16, 0x34, 0x68, 0x74, 0x74, 0x70, 0x3A,
|
||||||
|
0x2F, 0x2F, 0x77, 0x77, 0x77, 0x2E, 0x6D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x2E,
|
||||||
|
0x63, 0x6F, 0x6D, 0x2F, 0x70, 0x6B, 0x69, 0x6F, 0x70, 0x73, 0x2F, 0x44, 0x6F, 0x63, 0x73, 0x2F,
|
||||||
|
0x52, 0x65, 0x70, 0x6F, 0x73, 0x69, 0x74, 0x6F, 0x72, 0x79, 0x2E, 0x68, 0x74, 0x6D, 0x00, 0x30,
|
||||||
|
0x19, 0x06, 0x09, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x14, 0x02, 0x04, 0x0C, 0x1E, 0x0A,
|
||||||
|
0x00, 0x53, 0x00, 0x75, 0x00, 0x62, 0x00, 0x43, 0x00, 0x41, 0x30, 0x0B, 0x06, 0x03, 0x55, 0x1D,
|
||||||
|
0x0F, 0x04, 0x04, 0x03, 0x02, 0x01, 0x86, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x1D, 0x13, 0x01, 0x01,
|
||||||
|
0xFF, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xFF, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x1D, 0x23, 0x04,
|
||||||
|
0x18, 0x30, 0x16, 0x80, 0x14, 0xDA, 0xCA, 0x4B, 0xD0, 0x4C, 0x56, 0x03, 0x27, 0x5F, 0x97, 0xEB,
|
||||||
|
0x75, 0xA3, 0x02, 0xC3, 0xBF, 0x45, 0x9C, 0xF8, 0xB1, 0x30, 0x68, 0x06, 0x03, 0x55, 0x1D, 0x1F,
|
||||||
|
0x04, 0x61, 0x30, 0x5F, 0x30, 0x5D, 0xA0, 0x5B, 0xA0, 0x59, 0x86, 0x57, 0x68, 0x74, 0x74, 0x70,
|
||||||
|
0x3A, 0x2F, 0x2F, 0x77, 0x77, 0x77, 0x2E, 0x6D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74,
|
||||||
|
0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x70, 0x6B, 0x69, 0x6F, 0x70, 0x73, 0x2F, 0x63, 0x72, 0x6C, 0x2F,
|
||||||
|
0x57, 0x69, 0x6E, 0x64, 0x6F, 0x77, 0x73, 0x25, 0x32, 0x30, 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x25,
|
||||||
|
0x32, 0x30, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x25, 0x32, 0x30, 0x44, 0x65, 0x76, 0x69, 0x63,
|
||||||
|
0x65, 0x73, 0x25, 0x32, 0x30, 0x50, 0x43, 0x41, 0x25, 0x32, 0x30, 0x32, 0x30, 0x31, 0x38, 0x2E,
|
||||||
|
0x63, 0x72, 0x6C, 0x30, 0x75, 0x06, 0x08, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x01, 0x01, 0x04,
|
||||||
|
0x69, 0x30, 0x67, 0x30, 0x65, 0x06, 0x08, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x02, 0x86,
|
||||||
|
0x59, 0x68, 0x74, 0x74, 0x70, 0x3A, 0x2F, 0x2F, 0x77, 0x77, 0x77, 0x2E, 0x6D, 0x69, 0x63, 0x72,
|
||||||
|
0x6F, 0x73, 0x6F, 0x66, 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x70, 0x6B, 0x69, 0x6F, 0x70, 0x73,
|
||||||
|
0x2F, 0x63, 0x65, 0x72, 0x74, 0x73, 0x2F, 0x57, 0x69, 0x6E, 0x64, 0x6F, 0x77, 0x73, 0x25, 0x32,
|
||||||
|
0x30, 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x25, 0x32, 0x30, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x25,
|
||||||
|
0x32, 0x30, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x25, 0x32, 0x30, 0x50, 0x43, 0x41, 0x25,
|
||||||
|
0x32, 0x30, 0x32, 0x30, 0x31, 0x38, 0x2E, 0x63, 0x72, 0x74, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86,
|
||||||
|
0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x03, 0x69, 0x00, 0x30, 0x66, 0x02, 0x31, 0x00, 0x87, 0xB6,
|
||||||
|
0x82, 0xF3, 0xDA, 0xBE, 0xB1, 0x7B, 0x98, 0x7D, 0x3D, 0x0A, 0x90, 0xA8, 0xF5, 0xBF, 0x15, 0xC3,
|
||||||
|
0xEE, 0x8A, 0x4E, 0xC0, 0x7B, 0x10, 0x1D, 0xA9, 0xE3, 0x0B, 0xEC, 0x2C, 0x53, 0x4E, 0xA7, 0xBD,
|
||||||
|
0xF1, 0x6C, 0xAD, 0x18, 0x55, 0xBA, 0x25, 0x73, 0x55, 0xB7, 0x5B, 0x12, 0x24, 0xF4, 0x02, 0x31,
|
||||||
|
0x00, 0xAF, 0x02, 0x9C, 0x4B, 0x92, 0xD0, 0x72, 0xA5, 0x80, 0xCA, 0x69, 0x2B, 0x38, 0x50, 0x64,
|
||||||
|
0xD8, 0x58, 0x9E, 0xEA, 0xD6, 0x35, 0xCF, 0x68, 0x98, 0x92, 0x81, 0x09, 0x61, 0xC2, 0xBD, 0xB1,
|
||||||
|
0x4C, 0x7F, 0xAE, 0x55, 0x7B, 0xFC, 0x22, 0xDD, 0xD6, 0xB7, 0x7C, 0xB5, 0xA8, 0x18, 0x5D, 0x33,
|
||||||
|
0x04
|
||||||
|
};
|
||||||
|
guint8 ca_2[] = {
|
||||||
|
0x30, 0x82, 0x04, 0x56, 0x30, 0x82, 0x03, 0xDC, 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x13, 0x33,
|
||||||
|
0x00, 0x00, 0x00, 0x03, 0x6C, 0xCF, 0xED, 0xE2, 0x44, 0x70, 0x19, 0xBF, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x03, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x03, 0x30, 0x81,
|
||||||
|
0x94, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13,
|
||||||
|
0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0A, 0x57, 0x61, 0x73, 0x68, 0x69, 0x6E, 0x67,
|
||||||
|
0x74, 0x6F, 0x6E, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x52, 0x65,
|
||||||
|
0x64, 0x6D, 0x6F, 0x6E, 0x64, 0x31, 0x1E, 0x30, 0x1C, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x15,
|
||||||
|
0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72,
|
||||||
|
0x61, 0x74, 0x69, 0x6F, 0x6E, 0x31, 0x3E, 0x30, 0x3C, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x35,
|
||||||
|
0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x45, 0x43, 0x43, 0x20, 0x44, 0x65,
|
||||||
|
0x76, 0x69, 0x63, 0x65, 0x73, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69,
|
||||||
|
0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79,
|
||||||
|
0x20, 0x32, 0x30, 0x31, 0x37, 0x30, 0x1E, 0x17, 0x0D, 0x31, 0x38, 0x30, 0x31, 0x32, 0x35, 0x31,
|
||||||
|
0x39, 0x34, 0x39, 0x33, 0x38, 0x5A, 0x17, 0x0D, 0x33, 0x33, 0x30, 0x31, 0x32, 0x35, 0x31, 0x39,
|
||||||
|
0x35, 0x39, 0x33, 0x38, 0x5A, 0x30, 0x81, 0x84, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04,
|
||||||
|
0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0A,
|
||||||
|
0x57, 0x61, 0x73, 0x68, 0x69, 0x6E, 0x67, 0x74, 0x6F, 0x6E, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03,
|
||||||
|
0x55, 0x04, 0x07, 0x13, 0x07, 0x52, 0x65, 0x64, 0x6D, 0x6F, 0x6E, 0x64, 0x31, 0x1E, 0x30, 0x1C,
|
||||||
|
0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x15, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74,
|
||||||
|
0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x31, 0x2E, 0x30, 0x2C,
|
||||||
|
0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x25, 0x57, 0x69, 0x6E, 0x64, 0x6F, 0x77, 0x73, 0x20, 0x48,
|
||||||
|
0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x20, 0x44, 0x65, 0x76, 0x69,
|
||||||
|
0x63, 0x65, 0x73, 0x20, 0x50, 0x43, 0x41, 0x20, 0x32, 0x30, 0x31, 0x38, 0x30, 0x76, 0x30, 0x10,
|
||||||
|
0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06, 0x05, 0x2B, 0x81, 0x04, 0x00, 0x22,
|
||||||
|
0x03, 0x62, 0x00, 0x04, 0x1D, 0xDD, 0x08, 0x02, 0x03, 0x25, 0x75, 0x20, 0xE2, 0x71, 0x8B, 0xAD,
|
||||||
|
0x28, 0x09, 0x82, 0xE9, 0x06, 0xEE, 0x83, 0xC5, 0x3A, 0x6C, 0x4B, 0x71, 0x92, 0x50, 0x4E, 0x20,
|
||||||
|
0xE9, 0x72, 0xB4, 0xFC, 0x53, 0x2A, 0xEF, 0x5D, 0xCC, 0x9A, 0xB4, 0xCD, 0x76, 0xB8, 0x94, 0x97,
|
||||||
|
0x44, 0xB2, 0x71, 0x0E, 0xC9, 0xB1, 0x16, 0x03, 0xA1, 0x65, 0x2B, 0xB9, 0xE8, 0x5D, 0x5F, 0xF2,
|
||||||
|
0x30, 0x2E, 0xDD, 0xB1, 0x2B, 0x20, 0xFC, 0xBE, 0x00, 0x88, 0xEA, 0x1F, 0xA7, 0x7F, 0x99, 0x84,
|
||||||
|
0x98, 0x7C, 0x71, 0x3E, 0x4D, 0x34, 0x83, 0x69, 0x9B, 0x08, 0xCB, 0x78, 0xB2, 0x4B, 0xBD, 0xD7,
|
||||||
|
0x3E, 0xBE, 0x67, 0xA0, 0xA3, 0x82, 0x01, 0xFC, 0x30, 0x82, 0x01, 0xF8, 0x30, 0x10, 0x06, 0x09,
|
||||||
|
0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x15, 0x01, 0x04, 0x03, 0x02, 0x01, 0x00, 0x30, 0x1D,
|
||||||
|
0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04, 0x16, 0x04, 0x14, 0xDA, 0xCA, 0x4B, 0xD0, 0x4C, 0x56, 0x03,
|
||||||
|
0x27, 0x5F, 0x97, 0xEB, 0x75, 0xA3, 0x02, 0xC3, 0xBF, 0x45, 0x9C, 0xF8, 0xB1, 0x30, 0x65, 0x06,
|
||||||
|
0x03, 0x55, 0x1D, 0x20, 0x04, 0x5E, 0x30, 0x5C, 0x30, 0x06, 0x06, 0x04, 0x55, 0x1D, 0x20, 0x00,
|
||||||
|
0x30, 0x52, 0x06, 0x0C, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x4C, 0x83, 0x7D, 0x01, 0x01,
|
||||||
|
0x30, 0x42, 0x30, 0x40, 0x06, 0x08, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x02, 0x01, 0x16, 0x34,
|
||||||
|
0x68, 0x74, 0x74, 0x70, 0x3A, 0x2F, 0x2F, 0x77, 0x77, 0x77, 0x2E, 0x6D, 0x69, 0x63, 0x72, 0x6F,
|
||||||
|
0x73, 0x6F, 0x66, 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x70, 0x6B, 0x69, 0x6F, 0x70, 0x73, 0x2F,
|
||||||
|
0x44, 0x6F, 0x63, 0x73, 0x2F, 0x52, 0x65, 0x70, 0x6F, 0x73, 0x69, 0x74, 0x6F, 0x72, 0x79, 0x2E,
|
||||||
|
0x68, 0x74, 0x6D, 0x00, 0x30, 0x19, 0x06, 0x09, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x14,
|
||||||
|
0x02, 0x04, 0x0C, 0x1E, 0x0A, 0x00, 0x53, 0x00, 0x75, 0x00, 0x62, 0x00, 0x43, 0x00, 0x41, 0x30,
|
||||||
|
0x0B, 0x06, 0x03, 0x55, 0x1D, 0x0F, 0x04, 0x04, 0x03, 0x02, 0x01, 0x86, 0x30, 0x0F, 0x06, 0x03,
|
||||||
|
0x55, 0x1D, 0x13, 0x01, 0x01, 0xFF, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xFF, 0x30, 0x1F, 0x06,
|
||||||
|
0x03, 0x55, 0x1D, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x14, 0xDA, 0x5B, 0xF1, 0x0E, 0x66,
|
||||||
|
0x47, 0xD1, 0x5D, 0x13, 0x5F, 0x5B, 0x7A, 0xEB, 0xEB, 0x5F, 0x01, 0x08, 0xB5, 0x49, 0x30, 0x7A,
|
||||||
|
0x06, 0x03, 0x55, 0x1D, 0x1F, 0x04, 0x73, 0x30, 0x71, 0x30, 0x6F, 0xA0, 0x6D, 0xA0, 0x6B, 0x86,
|
||||||
|
0x69, 0x68, 0x74, 0x74, 0x70, 0x3A, 0x2F, 0x2F, 0x77, 0x77, 0x77, 0x2E, 0x6D, 0x69, 0x63, 0x72,
|
||||||
|
0x6F, 0x73, 0x6F, 0x66, 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x70, 0x6B, 0x69, 0x6F, 0x70, 0x73,
|
||||||
|
0x2F, 0x63, 0x72, 0x6C, 0x2F, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x25, 0x32,
|
||||||
|
0x30, 0x45, 0x43, 0x43, 0x25, 0x32, 0x30, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x25, 0x32,
|
||||||
|
0x30, 0x52, 0x6F, 0x6F, 0x74, 0x25, 0x32, 0x30, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63,
|
||||||
|
0x61, 0x74, 0x65, 0x25, 0x32, 0x30, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x25,
|
||||||
|
0x32, 0x30, 0x32, 0x30, 0x31, 0x37, 0x2E, 0x63, 0x72, 0x6C, 0x30, 0x81, 0x87, 0x06, 0x08, 0x2B,
|
||||||
|
0x06, 0x01, 0x05, 0x05, 0x07, 0x01, 0x01, 0x04, 0x7B, 0x30, 0x79, 0x30, 0x77, 0x06, 0x08, 0x2B,
|
||||||
|
0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x02, 0x86, 0x6B, 0x68, 0x74, 0x74, 0x70, 0x3A, 0x2F, 0x2F,
|
||||||
|
0x77, 0x77, 0x77, 0x2E, 0x6D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x2E, 0x63, 0x6F,
|
||||||
|
0x6D, 0x2F, 0x70, 0x6B, 0x69, 0x6F, 0x70, 0x73, 0x2F, 0x63, 0x65, 0x72, 0x74, 0x73, 0x2F, 0x4D,
|
||||||
|
0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x25, 0x32, 0x30, 0x45, 0x43, 0x43, 0x25, 0x32,
|
||||||
|
0x30, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x25, 0x32, 0x30, 0x52, 0x6F, 0x6F, 0x74, 0x25,
|
||||||
|
0x32, 0x30, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x25, 0x32, 0x30,
|
||||||
|
0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x25, 0x32, 0x30, 0x32, 0x30, 0x31, 0x37,
|
||||||
|
0x2E, 0x63, 0x72, 0x74, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x03,
|
||||||
|
0x03, 0x68, 0x00, 0x30, 0x65, 0x02, 0x30, 0x56, 0x2A, 0xAD, 0x72, 0x4C, 0xB9, 0x8C, 0xB3, 0x23,
|
||||||
|
0x80, 0xF5, 0x5F, 0xF8, 0x21, 0x94, 0x66, 0x0F, 0x76, 0x77, 0xE2, 0x7B, 0x03, 0xDD, 0x30, 0x5E,
|
||||||
|
0xCB, 0x90, 0xCA, 0x78, 0xE6, 0x0B, 0x2D, 0x12, 0xE5, 0xF7, 0x67, 0x31, 0x58, 0x71, 0xE6, 0xF3,
|
||||||
|
0x64, 0xC1, 0x04, 0xB3, 0x8B, 0xE9, 0xE2, 0x02, 0x31, 0x00, 0xB9, 0x20, 0x61, 0xB9, 0xD0, 0x5E,
|
||||||
|
0x3A, 0xA4, 0xA2, 0x8A, 0xFE, 0x1D, 0xFC, 0x27, 0x61, 0x0B, 0x98, 0x16, 0x8C, 0x02, 0x9C, 0x20,
|
||||||
|
0x7F, 0xEE, 0xF3, 0xCB, 0x1F, 0x0A, 0x37, 0x62, 0xB1, 0x8E, 0xCE, 0xD9, 0x9A, 0x9E, 0xAC, 0xE6,
|
||||||
|
0x1A, 0xD4, 0xB8, 0xF1, 0xA8, 0x2B, 0xB1, 0xB4, 0x40, 0x9B
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
msg_written_cb (GObject *source_object,
|
||||||
|
GAsyncResult *res,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
GError *error = NULL;
|
||||||
|
GOutputStream *stream = G_OUTPUT_STREAM (source_object);
|
||||||
|
FpiSsm *ssm = user_data;
|
||||||
|
FpDeviceVirtualSdcp *self = FPI_DEVICE_VIRTUAL_SDCP (fpi_ssm_get_device (ssm));
|
||||||
|
|
||||||
|
g_clear_pointer (&self->msg_out, g_byte_array_unref);
|
||||||
|
g_assert (self->msg_out == NULL);
|
||||||
|
|
||||||
|
if (!g_output_stream_write_all_finish (stream, res, NULL, &error))
|
||||||
|
{
|
||||||
|
fpi_ssm_mark_failed (ssm, error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
fpi_ssm_next_state (ssm);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
msg_received_cb (GObject *source_object,
|
||||||
|
GAsyncResult *res,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
GError *error = NULL;
|
||||||
|
GInputStream *stream = G_INPUT_STREAM (source_object);
|
||||||
|
FpiSsm *ssm = user_data;
|
||||||
|
FpDeviceVirtualSdcp *self = FPI_DEVICE_VIRTUAL_SDCP (fpi_ssm_get_device (ssm));
|
||||||
|
gsize read;
|
||||||
|
|
||||||
|
g_assert (self->msg_out == NULL);
|
||||||
|
|
||||||
|
if (!g_input_stream_read_all_finish (stream, res, &read, &error) ||
|
||||||
|
read != self->msg_in->len)
|
||||||
|
{
|
||||||
|
g_clear_pointer (&self->msg_in, g_byte_array_unref);
|
||||||
|
|
||||||
|
if (!error)
|
||||||
|
error = fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
|
||||||
|
"Received EOF while reading from test binary.");
|
||||||
|
|
||||||
|
fpi_ssm_mark_failed (ssm, error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
fpi_ssm_next_state (ssm);
|
||||||
|
}
|
||||||
|
|
||||||
|
enum {
|
||||||
|
SEND_MESSAGE,
|
||||||
|
RECV_MESSAGE,
|
||||||
|
SEND_RECV_STATES
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
send_recv_ssm (FpiSsm *ssm, FpDevice *dev)
|
||||||
|
{
|
||||||
|
FpDeviceVirtualSdcp *self = FPI_DEVICE_VIRTUAL_SDCP (dev);
|
||||||
|
|
||||||
|
switch (fpi_ssm_get_cur_state (ssm))
|
||||||
|
{
|
||||||
|
case SEND_MESSAGE:
|
||||||
|
g_output_stream_write_all_async (self->proc_stdin,
|
||||||
|
self->msg_out->data,
|
||||||
|
self->msg_out->len,
|
||||||
|
G_PRIORITY_DEFAULT,
|
||||||
|
fpi_device_get_cancellable (FP_DEVICE (dev)),
|
||||||
|
msg_written_cb,
|
||||||
|
ssm);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case RECV_MESSAGE:
|
||||||
|
g_input_stream_read_all_async (self->proc_stdout,
|
||||||
|
self->msg_in->data,
|
||||||
|
self->msg_in->len,
|
||||||
|
G_PRIORITY_DEFAULT,
|
||||||
|
fpi_device_get_cancellable (FP_DEVICE (dev)),
|
||||||
|
msg_received_cb,
|
||||||
|
ssm);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
connect_2_cb (FpiSsm *ssm, FpDevice *dev, GError *error)
|
||||||
|
{
|
||||||
|
g_autoptr(GBytes) recv_data = NULL;
|
||||||
|
g_autoptr(GBytes) r_d = NULL;
|
||||||
|
g_autoptr(FpiSdcpClaim) claim = NULL;
|
||||||
|
g_autoptr(GBytes) mac = NULL;
|
||||||
|
g_autoptr(GBytes) ca_1_bytes = NULL, ca_2_bytes = NULL;
|
||||||
|
FpDeviceVirtualSdcp *self = FPI_DEVICE_VIRTUAL_SDCP (dev);
|
||||||
|
guint16 cert_size;
|
||||||
|
|
||||||
|
if (error)
|
||||||
|
{
|
||||||
|
fpi_sdcp_device_connect_complete (FP_SDCP_DEVICE (dev), NULL, NULL, NULL, error);
|
||||||
|
g_clear_pointer (&self->connect_msg, g_byte_array_unref);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy (&cert_size, self->connect_msg->data + 32, 2);
|
||||||
|
g_byte_array_append (self->connect_msg, self->msg_in->data, self->msg_in->len);
|
||||||
|
g_clear_pointer (&self->msg_in, g_byte_array_unref);
|
||||||
|
/* Double check that the size is correct. */
|
||||||
|
g_assert (self->connect_msg->len == 32 + (2 + cert_size + 65 + 65 + 32 + 64 + 64) + 32);
|
||||||
|
recv_data = g_byte_array_free_to_bytes (g_steal_pointer (&self->connect_msg));
|
||||||
|
|
||||||
|
claim = fpi_sdcp_claim_new ();
|
||||||
|
r_d = g_bytes_new_from_bytes (recv_data, 0, 32);
|
||||||
|
claim->cert_m = g_bytes_new_from_bytes (recv_data, 34, cert_size);
|
||||||
|
claim->pk_d = g_bytes_new_from_bytes (recv_data, 34 + cert_size, 65);
|
||||||
|
claim->pk_f = g_bytes_new_from_bytes (recv_data, 34 + cert_size + 65, 65);
|
||||||
|
claim->h_f = g_bytes_new_from_bytes (recv_data, 34 + cert_size + 65 + 65, 32);
|
||||||
|
claim->s_m = g_bytes_new_from_bytes (recv_data, 34 + cert_size + 65 + 65 + 32, 64);
|
||||||
|
claim->s_d = g_bytes_new_from_bytes (recv_data, 34 + cert_size + 65 + 65 + 32 + 64, 64);
|
||||||
|
mac = g_bytes_new_from_bytes (recv_data, 34 + cert_size + 65 + 65 + 32 + 64 + 64, 32);
|
||||||
|
|
||||||
|
ca_1_bytes = g_bytes_new_static (ca_1, G_N_ELEMENTS (ca_1));
|
||||||
|
ca_2_bytes = g_bytes_new_static (ca_2, G_N_ELEMENTS (ca_2));
|
||||||
|
|
||||||
|
fpi_sdcp_device_set_intermediat_cas (FP_SDCP_DEVICE (dev),
|
||||||
|
ca_1_bytes,
|
||||||
|
ca_2_bytes);
|
||||||
|
|
||||||
|
fpi_sdcp_device_connect_complete (FP_SDCP_DEVICE (dev), r_d, claim, mac, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
connect_1_cb (FpiSsm *ssm, FpDevice *dev, GError *error)
|
||||||
|
{
|
||||||
|
FpDeviceVirtualSdcp *self = FPI_DEVICE_VIRTUAL_SDCP (dev);
|
||||||
|
guint16 cert_size;
|
||||||
|
|
||||||
|
if (error)
|
||||||
|
{
|
||||||
|
fpi_sdcp_device_connect_complete (FP_SDCP_DEVICE (dev), NULL, NULL, NULL, error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_clear_pointer (&self->connect_msg, g_byte_array_unref);
|
||||||
|
self->connect_msg = g_steal_pointer (&self->msg_in);
|
||||||
|
|
||||||
|
memcpy (&cert_size, self->connect_msg->data + 32, 2);
|
||||||
|
|
||||||
|
/* Nothing to send and the rest to receive. */
|
||||||
|
self->msg_out = g_byte_array_new ();
|
||||||
|
self->msg_in = g_byte_array_new ();
|
||||||
|
g_byte_array_set_size (self->msg_in, 32 + (2 + cert_size + 65 + 65 + 32 + 64 + 64) + 32 - self->connect_msg->len);
|
||||||
|
|
||||||
|
/* New SSM */
|
||||||
|
ssm = fpi_ssm_new_full (FP_DEVICE (dev), send_recv_ssm, SEND_RECV_STATES, "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"
|
||||||
|
|||||||
@@ -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,43 +22,19 @@
|
|||||||
|
|
||||||
#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;
|
||||||
|
|
||||||
@@ -68,37 +44,14 @@ typedef struct
|
|||||||
/* 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);
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||||
@@ -113,8 +66,6 @@ typedef enum {
|
|||||||
* @FP_DEVICE_RETRY_REMOVE_FINGER: The scan did not succeed due to quality or
|
* @FP_DEVICE_RETRY_REMOVE_FINGER: The scan did not succeed due to quality or
|
||||||
* pressure problems; the user should remove their finger from the scanner
|
* pressure problems; the user should remove their finger from the scanner
|
||||||
* before retrying.
|
* before retrying.
|
||||||
* @FP_DEVICE_RETRY_TOO_FAST: The scan did not succeed because the finger
|
|
||||||
* swipe or touch was too fast.
|
|
||||||
*
|
*
|
||||||
* Error codes representing scan failures resulting in the user needing to
|
* Error codes representing scan failures resulting in the user needing to
|
||||||
* retry.
|
* retry.
|
||||||
@@ -124,7 +75,6 @@ typedef enum {
|
|||||||
FP_DEVICE_RETRY_TOO_SHORT,
|
FP_DEVICE_RETRY_TOO_SHORT,
|
||||||
FP_DEVICE_RETRY_CENTER_FINGER,
|
FP_DEVICE_RETRY_CENTER_FINGER,
|
||||||
FP_DEVICE_RETRY_REMOVE_FINGER,
|
FP_DEVICE_RETRY_REMOVE_FINGER,
|
||||||
FP_DEVICE_RETRY_TOO_FAST,
|
|
||||||
} FpDeviceRetry;
|
} FpDeviceRetry;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -142,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.
|
||||||
@@ -160,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);
|
||||||
@@ -227,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,
|
||||||
@@ -244,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,
|
||||||
@@ -298,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);
|
||||||
@@ -337,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,
|
||||||
@@ -380,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,8 +124,6 @@ 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);
|
|
||||||
if (print_type != FPI_PRINT_NBIS)
|
|
||||||
fpi_print_set_type (enroll_print, FPI_PRINT_NBIS);
|
fpi_print_set_type (enroll_print, FPI_PRINT_NBIS);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -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;
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
g_clear_pointer (&image->minutiae, g_ptr_array_unref);
|
||||||
|
image->minutiae = g_ptr_array_new_full (data->minutiae->num,
|
||||||
(GDestroyNotify) free_minutia);
|
(GDestroyNotify) free_minutia);
|
||||||
|
|
||||||
for (int i = 0; i < data->minutiae->num; i++)
|
for (i = 0; i < data->minutiae->num; i++)
|
||||||
g_ptr_array_add (self->minutiae,
|
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -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;
|
GVariant *tmp;
|
||||||
tmp = g_variant_byteswap (result);
|
tmp = g_variant_byteswap (result);
|
||||||
g_variant_unref (result);
|
g_variant_unref (result);
|
||||||
result = tmp;
|
result = tmp;
|
||||||
#endif
|
}
|
||||||
|
|
||||||
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);
|
||||||
|
|
||||||
|
|||||||
58
libfprint/fp-sdcp-device-private.h
Normal file
58
libfprint/fp-sdcp-device-private.h
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
* FpSdcpDevice - A base class for SDCP enabled devices
|
||||||
|
* Copyright (C) 2020 Benjamin Berg <bberg@redhat.com>
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "fpi-sdcp-device.h"
|
||||||
|
|
||||||
|
#include <nss.h>
|
||||||
|
#include <keyhi.h>
|
||||||
|
#include <keythi.h>
|
||||||
|
#include <pk11pub.h>
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
GError *enroll_pre_commit_error;
|
||||||
|
|
||||||
|
/* XXX: Do we want a separate SDCP session object?
|
||||||
|
*/
|
||||||
|
|
||||||
|
GPtrArray *intermediate_cas;
|
||||||
|
|
||||||
|
/* Host random for the connection */
|
||||||
|
guint8 host_random[32];
|
||||||
|
|
||||||
|
NSSInitContext *nss_init_context;
|
||||||
|
PK11SlotInfo *slot;
|
||||||
|
SECKEYPrivateKey *host_key_private;
|
||||||
|
SECKEYPublicKey *host_key_public;
|
||||||
|
|
||||||
|
/* Master secret is required for reconnects.
|
||||||
|
* TODO: We probably want to serialize this to disk so it can survive
|
||||||
|
* fprintd idle shutdown. */
|
||||||
|
PK11SymKey *master_secret;
|
||||||
|
PK11SymKey *mac_secret;
|
||||||
|
|
||||||
|
} FpSdcpDevicePrivate;
|
||||||
|
|
||||||
|
void fpi_sdcp_device_connect (FpSdcpDevice *self);
|
||||||
|
void fpi_sdcp_device_reconnect (FpSdcpDevice *self);
|
||||||
|
|
||||||
|
void fpi_sdcp_device_enroll (FpSdcpDevice *self);
|
||||||
|
void fpi_sdcp_device_identify (FpSdcpDevice *self);
|
||||||
141
libfprint/fp-sdcp-device.c
Normal file
141
libfprint/fp-sdcp-device.c
Normal file
@@ -0,0 +1,141 @@
|
|||||||
|
/*
|
||||||
|
* FpSdcpDevice - A base class for SDCP enabled devices
|
||||||
|
* Copyright (C) 2020 Benjamin Berg <bberg@redhat.com>
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define FP_COMPONENT "sdcp_device"
|
||||||
|
#include "fpi-log.h"
|
||||||
|
|
||||||
|
#include "fp-sdcp-device-private.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SECTION: fp-sdcp-device
|
||||||
|
* @title: FpSdcpDevice
|
||||||
|
* @short_description: SDCP device subclass
|
||||||
|
*
|
||||||
|
* This is a base class for devices implementing the SDCP security protocol.
|
||||||
|
*/
|
||||||
|
|
||||||
|
G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (FpSdcpDevice, fp_sdcp_device, FP_TYPE_DEVICE)
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
/* XXX: We'll very likely want/need some properties on this class. */
|
||||||
|
enum {
|
||||||
|
PROP_0,
|
||||||
|
N_PROPS
|
||||||
|
};
|
||||||
|
|
||||||
|
static GParamSpec *properties[N_PROPS];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*******************************************************/
|
||||||
|
|
||||||
|
/* Callbacks/vfuncs */
|
||||||
|
static void
|
||||||
|
fp_sdcp_device_open (FpDevice *device)
|
||||||
|
{
|
||||||
|
FpSdcpDevice *self = FP_SDCP_DEVICE (device);
|
||||||
|
FpSdcpDevicePrivate *priv = fp_sdcp_device_get_instance_private (self);
|
||||||
|
|
||||||
|
/* Try a reconnect if we still have the mac secret. */
|
||||||
|
if (priv->mac_secret)
|
||||||
|
fpi_sdcp_device_reconnect (self);
|
||||||
|
else
|
||||||
|
fpi_sdcp_device_connect (self);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
fp_sdcp_device_enroll (FpDevice *device)
|
||||||
|
{
|
||||||
|
FpSdcpDevice *self = FP_SDCP_DEVICE (device);
|
||||||
|
|
||||||
|
fpi_sdcp_device_enroll (self);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
fp_sdcp_device_identify (FpDevice *device)
|
||||||
|
{
|
||||||
|
FpSdcpDevice *self = FP_SDCP_DEVICE (device);
|
||||||
|
|
||||||
|
fpi_sdcp_device_identify (self);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************************/
|
||||||
|
|
||||||
|
static void
|
||||||
|
fp_sdcp_device_finalize (GObject *object)
|
||||||
|
{
|
||||||
|
FpSdcpDevice *self = (FpSdcpDevice *) object;
|
||||||
|
FpSdcpDevicePrivate *priv = fp_sdcp_device_get_instance_private (self);
|
||||||
|
|
||||||
|
g_clear_pointer (&priv->intermediate_cas, g_ptr_array_unref);
|
||||||
|
g_clear_pointer (&priv->slot, PK11_FreeSlot);
|
||||||
|
g_clear_pointer (&priv->host_key_private, SECKEY_DestroyPrivateKey);
|
||||||
|
g_clear_pointer (&priv->host_key_public, SECKEY_DestroyPublicKey);
|
||||||
|
g_clear_pointer (&priv->master_secret, PK11_FreeSymKey);
|
||||||
|
g_clear_pointer (&priv->mac_secret, PK11_FreeSymKey);
|
||||||
|
g_clear_pointer (&priv->nss_init_context, NSS_ShutdownContext);
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (fp_sdcp_device_parent_class)->finalize (object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
fp_sdcp_device_get_property (GObject *object,
|
||||||
|
guint prop_id,
|
||||||
|
GValue *value,
|
||||||
|
GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
switch (prop_id)
|
||||||
|
{
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
fp_sdcp_device_constructed (GObject *obj)
|
||||||
|
{
|
||||||
|
G_OBJECT_CLASS (fp_sdcp_device_parent_class)->constructed (obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
fp_sdcp_device_class_init (FpSdcpDeviceClass *klass)
|
||||||
|
{
|
||||||
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||||
|
FpDeviceClass *fp_device_class = FP_DEVICE_CLASS (klass);
|
||||||
|
|
||||||
|
object_class->finalize = fp_sdcp_device_finalize;
|
||||||
|
object_class->get_property = fp_sdcp_device_get_property;
|
||||||
|
object_class->constructed = fp_sdcp_device_constructed;
|
||||||
|
|
||||||
|
fp_device_class->open = fp_sdcp_device_open;
|
||||||
|
fp_device_class->enroll = fp_sdcp_device_enroll;
|
||||||
|
fp_device_class->verify = fp_sdcp_device_identify;
|
||||||
|
fp_device_class->identify = fp_sdcp_device_identify;
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
g_object_class_install_properties (object_class, N_PROPS, properties);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
fp_sdcp_device_init (FpSdcpDevice *self)
|
||||||
|
{
|
||||||
|
FpSdcpDevicePrivate *priv = fp_sdcp_device_get_instance_private (self);
|
||||||
|
|
||||||
|
priv->intermediate_cas = g_ptr_array_new_with_free_func ((GDestroyNotify) g_bytes_unref);
|
||||||
|
}
|
||||||
29
libfprint/fp-sdcp-device.h
Normal file
29
libfprint/fp-sdcp-device.h
Normal file
@@ -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
|
||||||
@@ -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;
|
||||||
|
|
||||||
|
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);
|
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
|
||||||
|
|||||||
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
|
||||||
|
|||||||
@@ -79,16 +79,13 @@
|
|||||||
*
|
*
|
||||||
* 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) \
|
#define BUG_ON(condition) G_STMT_START \
|
||||||
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)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user