mirror of
https://gitlab.freedesktop.org/libfprint/libfprint.git
synced 2026-09-10 13:00:08 +00:00
Compare commits
533
Commits
+2
-2
@@ -68,8 +68,8 @@ def build_install(revision):
|
|||||||
subprocess.check_call(['meson', build_dir,
|
subprocess.check_call(['meson', build_dir,
|
||||||
'--prefix=/usr', '--libdir=lib',
|
'--prefix=/usr', '--libdir=lib',
|
||||||
'-Dx11-examples=false', '-Ddoc=false', '-Dgtk-examples=false'])
|
'-Dx11-examples=false', '-Ddoc=false', '-Dgtk-examples=false'])
|
||||||
subprocess.check_call(['ninja', '-v', '-C', build_dir])
|
subprocess.check_call(['meson', 'compile', '-v', '-C', build_dir])
|
||||||
subprocess.check_call(['ninja', '-v', '-C', build_dir, 'install'],
|
subprocess.check_call(['meson', 'install', '-v', '-C', build_dir],
|
||||||
env={'DESTDIR': dest_dir})
|
env={'DESTDIR': dest_dir})
|
||||||
|
|
||||||
return dest_dir
|
return dest_dir
|
||||||
|
|||||||
+271
-50
@@ -1,50 +1,76 @@
|
|||||||
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: 'freedesktop/ci-templates'
|
||||||
ref: master
|
ref: master
|
||||||
file: '/templates/fedora.yml'
|
file: '/templates/fedora.yml'
|
||||||
- remote: 'https://gitlab.gnome.org/GNOME/citemplates/-/raw/master/flatpak/flatpak_ci_initiative.yml'
|
- remote: 'https://gitlab.gnome.org/GNOME/citemplates/-/raw/71e636e012ae0ab04c5e0fe40ca73ada91ae6bde/flatpak/flatpak_ci_initiative.yml'
|
||||||
|
|
||||||
|
default:
|
||||||
|
interruptible: true
|
||||||
|
# Auto-retry jobs in case of infra failures
|
||||||
|
retry:
|
||||||
|
max: 1
|
||||||
|
when:
|
||||||
|
- 'runner_system_failure'
|
||||||
|
- 'stuck_or_timeout_failure'
|
||||||
|
- 'scheduler_failure'
|
||||||
|
- 'api_failure'
|
||||||
|
|
||||||
variables:
|
variables:
|
||||||
extends: .libfprint_common_variables
|
extends: .libfprint_common_variables
|
||||||
FDO_DISTRIBUTION_TAG: latest
|
FDO_DISTRIBUTION_TAG: $LIBFPRINT_IMAGE_TAG
|
||||||
FDO_DISTRIBUTION_VERSION: rawhide
|
FDO_DISTRIBUTION_VERSION: rawhide
|
||||||
FDO_UPSTREAM_REPO: "libfprint/$CI_PROJECT_NAME"
|
FDO_UPSTREAM_REPO: "libfprint/$CI_PROJECT_NAME"
|
||||||
FEDORA_IMAGE: "$CI_REGISTRY/libfprint/$CI_PROJECT_NAME/fedora/$FDO_DISTRIBUTION_VERSION:$FDO_DISTRIBUTION_TAG"
|
FEDORA_IMAGE: "registry.freedesktop.org/libfprint/$CI_PROJECT_NAME/fedora/$FDO_DISTRIBUTION_VERSION:$FDO_DISTRIBUTION_TAG"
|
||||||
BUNDLE: "org.freedesktop.libfprint.Demo.flatpak"
|
FEDORA_IMAGE_S390X: "registry.freedesktop.org/libfprint/$CI_PROJECT_NAME/fedora/$FDO_DISTRIBUTION_VERSION-s390x:$LIBFPRINT_IMAGE_TAG"
|
||||||
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 nss
|
# Build with a driver that doesn't need imaging, or openssl
|
||||||
- meson --werror -Ddrivers=$driver . _build
|
- meson setup _build --werror -Ddrivers=$driver
|
||||||
- ninja -C _build
|
- meson compile -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 --werror -Ddrivers=all . _build
|
- meson setup _build --werror -Ddrivers=all
|
||||||
- ninja -C _build
|
- meson compile -C _build
|
||||||
- ninja -C _build install
|
- meson install -C _build
|
||||||
|
|
||||||
.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
|
||||||
except:
|
extends:
|
||||||
variables:
|
- .standard_job
|
||||||
- $CI_PIPELINE_SOURCE == "schedule"
|
|
||||||
variables:
|
variables:
|
||||||
driver: virtual_image
|
driver: virtual_image
|
||||||
<<: *build_one_driver
|
<<: *build_one_driver
|
||||||
@@ -59,16 +85,20 @@ build:
|
|||||||
|
|
||||||
test:
|
test:
|
||||||
stage: test
|
stage: test
|
||||||
except:
|
extends:
|
||||||
variables:
|
- .standard_job
|
||||||
- $CI_PIPELINE_SOURCE == "schedule"
|
|
||||||
script:
|
script:
|
||||||
- meson --werror -Ddrivers=all -Db_coverage=true . _build
|
- meson setup _build --werror -Ddrivers=all -Db_coverage=true
|
||||||
- ninja -C _build
|
|
||||||
- meson test -C _build --print-errorlogs --no-stdsplit --timeout-multiplier 3
|
- meson test -C _build --print-errorlogs --no-stdsplit --timeout-multiplier 3
|
||||||
|
# We can't use `meson compile` https://github.com/mesonbuild/meson/issues/7895
|
||||||
- ninja -C _build coverage
|
- ninja -C _build coverage
|
||||||
- cat _build/meson-logs/coverage.txt
|
- cat _build/meson-logs/coverage.txt || true
|
||||||
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'
|
expose_as: 'Coverage Report'
|
||||||
when: always
|
when: always
|
||||||
paths:
|
paths:
|
||||||
@@ -79,14 +109,15 @@ test:
|
|||||||
|
|
||||||
test_valgrind:
|
test_valgrind:
|
||||||
stage: test
|
stage: test
|
||||||
except:
|
extends:
|
||||||
variables:
|
- .standard_job
|
||||||
- $CI_PIPELINE_SOURCE == "schedule"
|
|
||||||
script:
|
script:
|
||||||
- meson -Ddrivers=all . _build
|
- meson setup _build -Ddrivers=all
|
||||||
- ninja -C _build
|
- meson compile -C _build
|
||||||
- meson test -C _build --print-errorlogs --no-stdsplit --setup=valgrind
|
- meson test -C _build --print-errorlogs --no-stdsplit --setup=valgrind
|
||||||
artifacts:
|
artifacts:
|
||||||
|
reports:
|
||||||
|
junit: "_build/meson-logs/testlog-valgrind.junit.xml"
|
||||||
expose_as: 'Valgrind test logs'
|
expose_as: 'Valgrind test logs'
|
||||||
when: always
|
when: always
|
||||||
paths:
|
paths:
|
||||||
@@ -94,73 +125,126 @@ test_valgrind:
|
|||||||
- _build/meson-logs/testlog-valgrind.txt
|
- _build/meson-logs/testlog-valgrind.txt
|
||||||
expire_in: 1 week
|
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
|
||||||
except:
|
extends:
|
||||||
variables:
|
- .standard_job
|
||||||
- $CI_PIPELINE_SOURCE == "schedule"
|
|
||||||
allow_failure: true
|
allow_failure: true
|
||||||
script:
|
script:
|
||||||
- meson -Ddrivers=all . _build
|
- meson setup _build -Ddrivers=all
|
||||||
# Wrapper to add --status-bugs and disable malloc checker
|
# Wrapper to add --status-bugs and disable malloc checker
|
||||||
- SCANBUILD=$CI_PROJECT_DIR/.gitlab-ci/scan-build ninja -C _build scan-build
|
- SCANBUILD=$CI_PROJECT_DIR/.gitlab-ci/scan-build
|
||||||
|
ninja -C _build scan-build
|
||||||
artifacts:
|
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
|
||||||
except:
|
extends:
|
||||||
variables:
|
- .standard_job
|
||||||
- $CI_PIPELINE_SOURCE == "schedule"
|
|
||||||
script:
|
script:
|
||||||
- scripts/uncrustify.sh
|
- scripts/uncrustify.sh
|
||||||
- git diff
|
- git diff
|
||||||
- "! git status -s | grep -q ."
|
- git diff-index --name-only --exit-code HEAD
|
||||||
|
rules:
|
||||||
|
- changes:
|
||||||
|
compare_to: 'refs/heads/master'
|
||||||
|
paths:
|
||||||
|
- '**/*.c'
|
||||||
|
- '**/*.h'
|
||||||
|
|
||||||
test_unsupported_list:
|
test_unsupported_list:
|
||||||
stage: check-source
|
stage: check-source
|
||||||
except:
|
extends:
|
||||||
variables:
|
- .standard_job
|
||||||
- $CI_PIPELINE_SOURCE == "schedule"
|
|
||||||
allow_failure: true
|
allow_failure: true
|
||||||
|
variables:
|
||||||
|
FPRINT_HWDB_LIST: libfprint/fprint-list-udev-hwdb.c
|
||||||
script:
|
script:
|
||||||
- tests/hwdb-check-unsupported.py
|
- scripts/sync-unsupported-devices.py $FPRINT_HWDB_LIST
|
||||||
|
- git diff --color=always --exit-code $FPRINT_HWDB_LIST
|
||||||
|
|
||||||
flatpak:
|
flatpak:
|
||||||
stage: flatpak
|
stage: flatpak
|
||||||
extends: .flatpak
|
extends: .flatpak@x86_64
|
||||||
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: never
|
when: manual
|
||||||
- if: '$CI_PIPELINE_SOURCE == "schedule"'
|
allow_failure: true
|
||||||
|
- 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:
|
.container_fedora_build_base:
|
||||||
extends: .fdo.container-build@fedora
|
extends: .fdo.container-build@fedora
|
||||||
only:
|
stage: image-build
|
||||||
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
|
||||||
FDO_FORCE_REBUILD: 1
|
|
||||||
# a list of packages to install
|
# a list of packages to install
|
||||||
FDO_DISTRIBUTION_PACKAGES:
|
FDO_DISTRIBUTION_PACKAGES:
|
||||||
$LIBFPRINT_DEPENDENCIES
|
$LIBFPRINT_DEPENDENCIES
|
||||||
@@ -168,7 +252,144 @@ container_fedora_build:
|
|||||||
libpcap-devel
|
libpcap-devel
|
||||||
libudev-devel
|
libudev-devel
|
||||||
FDO_DISTRIBUTION_EXEC: |
|
FDO_DISTRIBUTION_EXEC: |
|
||||||
git clone https://github.com/martinpitt/umockdev.git && \
|
$LIBFPRINT_EXEC
|
||||||
cd umockdev && \
|
rules:
|
||||||
meson _build --prefix=/usr && \
|
- when: never
|
||||||
ninja -C _build && ninja -C _build install
|
|
||||||
|
.container_fedora_build_forced:
|
||||||
|
variables:
|
||||||
|
FDO_FORCE_REBUILD: 1
|
||||||
|
|
||||||
|
container_fedora_build_schedule:
|
||||||
|
extends:
|
||||||
|
- .container_fedora_build_base
|
||||||
|
- .container_fedora_build_forced
|
||||||
|
rules:
|
||||||
|
- if: $CI_PIPELINE_SOURCE == "schedule" && $CRON_TASK == "BUILD_CI_IMAGES"
|
||||||
|
when: always
|
||||||
|
|
||||||
|
container_fedora_build_manual:
|
||||||
|
extends:
|
||||||
|
- .container_fedora_build_base
|
||||||
|
- .container_fedora_build_forced
|
||||||
|
rules:
|
||||||
|
- if: $LIBFPRINT_CI_ACTION == "build-image"
|
||||||
|
when: always
|
||||||
|
|
||||||
|
.container_fedora_build_on_deps_changed_rules:
|
||||||
|
rules:
|
||||||
|
- if: $CI_PROJECT_NAMESPACE == "libfprint" && $CI_PIPELINE_SOURCE != "schedule"
|
||||||
|
changes:
|
||||||
|
compare_to: 'refs/heads/master'
|
||||||
|
paths:
|
||||||
|
- '.gitlab-ci/libfprint-image-variables.yaml'
|
||||||
|
- '.gitlab-ci/libfprint-templates.yaml'
|
||||||
|
|
||||||
|
container_fedora_build_on_deps_changed:
|
||||||
|
extends:
|
||||||
|
- .container_fedora_build_base
|
||||||
|
- .container_fedora_build_on_deps_changed_rules
|
||||||
|
|
||||||
|
.container_fedora_image_build_base_s390x:
|
||||||
|
stage: image-build
|
||||||
|
image: quay.io/freedesktop.org/ci-templates:container-build-base-2026-05-19.0
|
||||||
|
variables:
|
||||||
|
GIT_STRATEGY: none
|
||||||
|
S390X_TAG: $LIBFPRINT_IMAGE_TAG-s390x
|
||||||
|
STORAGE_DRIVER: vfs
|
||||||
|
script:
|
||||||
|
- |
|
||||||
|
if [ -z "${FDO_FORCE_REBUILD:-}" ]; then
|
||||||
|
if skopeo inspect --no-tags --retry-times 3 "docker://$FEDORA_IMAGE_S390X" 2>/dev/null; then
|
||||||
|
echo "Image $FEDORA_IMAGE_S390X already exists, skipping build."
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
- buildah from --name s390x-container --platform linux/s390x
|
||||||
|
registry.fedoraproject.org/fedora:$FDO_DISTRIBUTION_VERSION
|
||||||
|
- ROOTFS=$(buildah mount s390x-container)
|
||||||
|
- dnf install -y --installroot=$ROOTFS --forcearch=s390x
|
||||||
|
--use-host-config
|
||||||
|
--setopt=tsflags=noscripts --releasever=$FDO_DISTRIBUTION_VERSION
|
||||||
|
--setopt=install_weak_deps=False
|
||||||
|
$LIBFPRINT_DEPENDENCIES
|
||||||
|
|
||||||
|
- dnf clean all --installroot=$ROOTFS || true
|
||||||
|
- buildah commit s390x-container "$FEDORA_IMAGE_S390X"
|
||||||
|
- podman login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
|
||||||
|
- buildah push "$FEDORA_IMAGE_S390X"
|
||||||
|
|
||||||
|
container_fedora_build_schedule_s390x:
|
||||||
|
extends:
|
||||||
|
- .container_fedora_image_build_base_s390x
|
||||||
|
- .container_fedora_build_forced
|
||||||
|
rules:
|
||||||
|
- if: $CI_PIPELINE_SOURCE == "schedule" && $CRON_TASK == "BUILD_CI_IMAGES"
|
||||||
|
when: always
|
||||||
|
|
||||||
|
container_fedora_build_manual_s390x:
|
||||||
|
extends:
|
||||||
|
- .container_fedora_image_build_base_s390x
|
||||||
|
- .container_fedora_build_forced
|
||||||
|
rules:
|
||||||
|
- if: $LIBFPRINT_CI_ACTION == "build-image"
|
||||||
|
when: always
|
||||||
|
|
||||||
|
container_fedora_build_on_deps_changed_s390x:
|
||||||
|
extends:
|
||||||
|
- .container_fedora_image_build_base_s390x
|
||||||
|
- .container_fedora_build_on_deps_changed_rules
|
||||||
|
|
||||||
|
test_s390x:
|
||||||
|
stage: test
|
||||||
|
allow_failure: true
|
||||||
|
needs:
|
||||||
|
- job: container_fedora_build_manual_s390x
|
||||||
|
optional: true
|
||||||
|
variables:
|
||||||
|
STORAGE_DRIVER: vfs
|
||||||
|
QEMU_CPU: max
|
||||||
|
before_script:
|
||||||
|
# The s390x binaries are executed via the qemu-s390x-static registered in
|
||||||
|
# the *host* kernel's binfmt_misc. Use $FEDORA_IMAGE qemu-user-static
|
||||||
|
# (and systemd-binfmt), and run it privileged to re-register its handlers
|
||||||
|
# and make every run use the same emulator.
|
||||||
|
- podman run --rm --privileged
|
||||||
|
--security-opt label=filetype:container_file_t
|
||||||
|
--security-opt label=level:s0
|
||||||
|
--security-opt label=type:spc_t
|
||||||
|
-v $CI_PROJECT_DIR/.gitlab-ci/qemu-user-static/container-entrypoint:/container-entrypoint:z
|
||||||
|
$FEDORA_IMAGE /container-entrypoint
|
||||||
|
script:
|
||||||
|
- podman run --rm --platform linux/s390x -e QEMU_CPU -v $CI_PROJECT_DIR:/build:z -w /build "$FEDORA_IMAGE_S390X" /bin/bash -c \
|
||||||
|
"meson setup _build --werror -Ddrivers=all && meson test -C _build --print-errorlogs --no-stdsplit --timeout-multiplier 4 --suite=drivers --suite=virtual-driver"
|
||||||
|
artifacts:
|
||||||
|
when: always
|
||||||
|
paths:
|
||||||
|
- _build/meson-logs/
|
||||||
|
reports:
|
||||||
|
junit: "_build/meson-logs/testlog.junit.xml"
|
||||||
|
rules:
|
||||||
|
- if: $LIBFPRINT_CI_ACTION == "test-s390x"
|
||||||
|
when: always
|
||||||
|
- when: manual
|
||||||
|
|
||||||
|
pages:
|
||||||
|
image: alpine:latest
|
||||||
|
stage: deploy
|
||||||
|
needs:
|
||||||
|
- job: test
|
||||||
|
artifacts: true
|
||||||
|
- job: build
|
||||||
|
artifacts: true
|
||||||
|
script:
|
||||||
|
- mkdir public
|
||||||
|
- mv _build/meson-logs/coveragereport public/coverage || true
|
||||||
|
- mv _build/doc/html public/doc
|
||||||
|
artifacts:
|
||||||
|
paths:
|
||||||
|
- public
|
||||||
|
rules:
|
||||||
|
- if: $CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH && $CI_PIPELINE_SOURCE == "push"
|
||||||
|
- if: $CI_COMMIT_TAG
|
||||||
|
|||||||
@@ -0,0 +1,2 @@
|
|||||||
|
variables:
|
||||||
|
LIBFPRINT_IMAGE_TAG: v8
|
||||||
@@ -1,6 +1,11 @@
|
|||||||
|
# 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++
|
||||||
@@ -9,16 +14,21 @@
|
|||||||
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
|
libgudev-devel
|
||||||
|
libubsan
|
||||||
libX11-devel
|
libX11-devel
|
||||||
libXv-devel
|
libXv-devel
|
||||||
meson
|
meson
|
||||||
nss-devel
|
openssl-devel
|
||||||
pixman-devel
|
pixman-devel
|
||||||
|
podman
|
||||||
|
qemu-user-static
|
||||||
python3-cairo
|
python3-cairo
|
||||||
python3-gobject
|
python3-gobject
|
||||||
systemd
|
systemd
|
||||||
@@ -27,3 +37,15 @@
|
|||||||
valgrind
|
valgrind
|
||||||
clang-analyzer
|
clang-analyzer
|
||||||
diffutils
|
diffutils
|
||||||
|
|
||||||
|
LIBFPRINT_EXEC: |
|
||||||
|
dnf -y install dnf-utils
|
||||||
|
debuginfo-install -y \
|
||||||
|
glib2 \
|
||||||
|
glibc \
|
||||||
|
libgusb \
|
||||||
|
libusb \
|
||||||
|
openssl \
|
||||||
|
pixman \
|
||||||
|
python3-gobject \
|
||||||
|
python3-gobject-base
|
||||||
|
|||||||
+27
@@ -0,0 +1,27 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
#
|
||||||
|
# Unregister any stale qemu-*-static binfmt handlers and (re-)register the ones
|
||||||
|
# shipped by this image via systemd-binfmt, so the host always uses the recent
|
||||||
|
# qemu-user-static built into this image (registered with the "F" fix-binary
|
||||||
|
# flag from /usr/lib/binfmt.d).
|
||||||
|
#
|
||||||
|
# Based on https://www.itix.fr/blog/qemu-user-static-with-podman/
|
||||||
|
|
||||||
|
set -Eeuo pipefail
|
||||||
|
|
||||||
|
if [ ! -d /proc/sys/fs/binfmt_misc ]; then
|
||||||
|
echo "No binfmt support in the kernel."
|
||||||
|
echo " Try: '/sbin/modprobe binfmt_misc' from the host"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -f /proc/sys/fs/binfmt_misc/register ]; then
|
||||||
|
echo "Mounting /proc/sys/fs/binfmt_misc..."
|
||||||
|
mount binfmt_misc -t binfmt_misc /proc/sys/fs/binfmt_misc
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Cleaning up..."
|
||||||
|
find /proc/sys/fs/binfmt_misc -type f -name 'qemu-*' -exec sh -c 'echo -1 > {}' \;
|
||||||
|
|
||||||
|
echo "Registering..."
|
||||||
|
exec /usr/lib/systemd/systemd-binfmt
|
||||||
@@ -1,4 +1,7 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh -x
|
||||||
|
|
||||||
# This wrapper just disables the malloc checker
|
# This wrapper just disables the malloc checker
|
||||||
exec /usr/bin/scan-build --status-bugs -disable-checker unix.Malloc "$@"
|
exec /usr/bin/scan-build --status-bugs -disable-checker unix.Malloc \
|
||||||
|
--exclude "$PWD/_build/meson-private" \
|
||||||
|
--exclude "$PWD/meson-private" \
|
||||||
|
"$@"
|
||||||
|
|||||||
@@ -1,6 +1,117 @@
|
|||||||
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.
|
||||||
|
|
||||||
|
2026-07-25: v1.94.100 release
|
||||||
|
|
||||||
|
Highlights:
|
||||||
|
* bump meson dependency to 0.62
|
||||||
|
* egis_etu905: New driver supporting PIDs 0x05AE and 0x9201
|
||||||
|
* synaptics: New PIDs 0x010D, 0x010E and 0x01A4
|
||||||
|
* goodixmoc: Support 27c6:6382, 27c6:6984 and 27c6:6090
|
||||||
|
* nb1010: Support the NB-2020-U fingerprint reader
|
||||||
|
* focaltech_moc: New PID 0xA97A
|
||||||
|
* elanmoc: New PID 0x0CB2
|
||||||
|
* fpcmoc: New PID 0x9B24
|
||||||
|
* aes2550: Handle tapping without swiping and fix deactivation after errors
|
||||||
|
* fp-device: Implement verify using identification, improving driver
|
||||||
|
consistency and reducing duplicated driver code
|
||||||
|
* fpcmoc, egis_etu905, elan, elanspi, goodixmoc and mafpmoc: Improve
|
||||||
|
big-endian support
|
||||||
|
* goodixmoc: Fix malformed payload, CRC and invalid finger handling
|
||||||
|
* synaptics, realtek, vfs101, vfs301, upekts, elan and egismoc: Fix
|
||||||
|
memory safety, bounds checking and error handling issues
|
||||||
|
* aes1610, aes2510, aesx660, fpcmoc and uru4000: Fix resource leaks and
|
||||||
|
cancellation or device deactivation issues
|
||||||
|
* Expanded USB replay coverage for aes2550 and egis_etu905, and improved
|
||||||
|
virtual-image testing with transformed fingerprint images
|
||||||
|
|
||||||
|
2026-02-10: v1.94.10 release
|
||||||
|
|
||||||
|
Highlights:
|
||||||
|
* synaptics: Add USB reset in probe to recover stall condition
|
||||||
|
* synaptics: New PIDs 0x0169, 0x019F, 0x00E9, 0x01A0, 0x0109, 0x010A
|
||||||
|
* goodixmoc: New PID 0x66A9
|
||||||
|
* goodixmoc: Fix crash in exit callback handler
|
||||||
|
* fpcmoc: New PID 0xA306
|
||||||
|
* fpcmoc: Fix interrupt cancellable leak
|
||||||
|
* elanmoc: New PIDs 0x0CA7, 0x0CA8, 0x0CB0
|
||||||
|
* egismoc: New PIDs 0x0584, 0x0588
|
||||||
|
* focaltech_moc: New PIDs 0xA27A, 0x1579
|
||||||
|
* realtek: New PID 0xFA03
|
||||||
|
* fp-device: Clarify getter for open property
|
||||||
|
* libfprint: Use fatal-warnings on g-i-scanner
|
||||||
|
|
||||||
|
2025-02-20: v1.94.9 release
|
||||||
|
|
||||||
|
Highlights:
|
||||||
|
* uru4000: Use OpenSSL to perform AES-ECB encryption, as per this libfprint
|
||||||
|
does not support on NSS, but on openssl (>= 3.0).
|
||||||
|
* goodixmoc: New PIDs 0x60C2, 0x689A
|
||||||
|
* synaptics: New PIDs 0x016C, 0x0174, 0x0107, 0x0108, 0x00C2, 0x00F0
|
||||||
|
* fpcmoc: New PID 0xC844
|
||||||
|
* focaltech_moc: New PIDs 0xA99A, 0xA57A, 0xA78A
|
||||||
|
* elanmoc: New PIDs 0x0C98, 0x0C9D, 0x0CA3
|
||||||
|
* elanspi: New PIDs 0x3128, 0x2766
|
||||||
|
* fp-device: Add FP_DEVICE_RETRY_TOO_FAST retry error
|
||||||
|
* data: AppStream meta info listing supported USB devices.
|
||||||
|
* fixed various memory issues in multiple devices
|
||||||
|
|
||||||
|
2024-09-03: v1.94.8 release
|
||||||
|
|
||||||
|
Highlights:
|
||||||
|
* build: Support building in non-linux unix environments (tested in FreeBSD)
|
||||||
|
* egismoc: New PIDs 0x0583, 0x0586, 0x0587.
|
||||||
|
* elanmoc: New PID 0x0C9F.
|
||||||
|
* fpcmoc: New PIDs 0x9524, 0x9544.
|
||||||
|
* goodixmoc: New PIDs 0x609A, 0x650A, 0x650C, 0x6512.
|
||||||
|
* realtek: New PID 0x5816.
|
||||||
|
* synaptics: New PIDs 0x00C4, 0x019D, 0x00C6.
|
||||||
|
* fpcmoc: fix incorrect immobile handling during enrollment.
|
||||||
|
* fpcmoc: fixed jumping to wrong state at end of custom enroll.
|
||||||
|
* egismoc: various code cleanups.
|
||||||
|
|
||||||
|
2024-02-20: v1.94.7 release
|
||||||
|
|
||||||
|
Highlights:
|
||||||
|
* synaptics: fix enroll identify problem after user reset database.
|
||||||
|
* synaptics: New PIDs 0x0173, 0x0106, 0x0124.
|
||||||
|
* goodixmoc: New PID 0x6582.
|
||||||
|
* build: Do not require bash to build, only posix sh.
|
||||||
|
* fp-image: Simplify minutiae detection tasks.
|
||||||
|
* GLib 2.68 is now required to build libfprint.
|
||||||
|
|
||||||
|
New drivers:
|
||||||
|
* realtek (PID 0x5813).
|
||||||
|
* focaltech_moc (PIDs 0x9E48, 0xD979, 0xA959).
|
||||||
|
* egismoc (PIDs 0x0582, 0x05a1).
|
||||||
|
|
||||||
|
2023-08-17: v1.94.6 release
|
||||||
|
|
||||||
|
Highlights:
|
||||||
|
* goodixmoc: New PIDs 0x60A4, 0x60BC, 0x6092, 0x633C and 0x6304.
|
||||||
|
* goodixmoc: Fix missing "enroll create" state.
|
||||||
|
* elanmoc: New PID 0x0C99.
|
||||||
|
* upektc: Improve compatibility with sensors 147e:2016.
|
||||||
|
* aes4000: Actually support 08FF:5501 devices.
|
||||||
|
* virtual-device-listener: Fix failing tests with GLib 2.76
|
||||||
|
* tests: Add installed tests
|
||||||
|
|
||||||
|
Bugs fixed:
|
||||||
|
* #526 libfprint: fpcmoc: use after free if enrollment or identification is
|
||||||
|
cancelled (Vasily Khoruzhick)
|
||||||
|
|
||||||
|
2022-10-13: v1.94.5 release
|
||||||
|
|
||||||
|
Highlights:
|
||||||
|
* New driver: fpcmoc, supporting various FPC MOC Fingerprint Sensors
|
||||||
|
* goodixmoc: New PIDs 0x6014, 0x6094, 0x631C, 0x634C, 0x6384, 0x659A.
|
||||||
|
* goodixmoc: Support resetting device on firmware failure due to corrupted DB.
|
||||||
|
* elanmoc: New PIDs 0x0c88, 0x0c8c, 0x0c8d.
|
||||||
|
* synaptics: New PID 0x0104.
|
||||||
|
* upektc: New PID 0x2017.
|
||||||
|
* Fixed various memory leaks
|
||||||
|
* More tests
|
||||||
|
|
||||||
2022-05-24: v1.94.4 release
|
2022-05-24: v1.94.4 release
|
||||||
|
|
||||||
Highlights:
|
Highlights:
|
||||||
@@ -330,7 +441,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 whitelist
|
- Add some unsupported devices to the allowlist
|
||||||
|
|
||||||
2017-05-14: v0.7.0 release
|
2017-05-14: v0.7.0 release
|
||||||
* Drivers:
|
* Drivers:
|
||||||
@@ -380,7 +491,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 blacklist
|
- Add Microsoft keyboard to the suspend denylist
|
||||||
|
|
||||||
* Plenty of build fixes
|
* Plenty of build fixes
|
||||||
|
|
||||||
|
|||||||
@@ -1,54 +1,95 @@
|
|||||||
# libfprint
|
|
||||||
|
|
||||||
libfprint is part of the fprint project:
|
|
||||||
https://fprint.freedesktop.org/
|
<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
|
## History
|
||||||
|
|
||||||
libfprint was originally developed as part of an academic project at the
|
**LibFPrint** was originally developed as part of an
|
||||||
University of Manchester with the aim of hiding differences between different
|
academic project at the **[University Of Manchester]**.
|
||||||
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
|
It aimed to hide the differences between consumer
|
||||||
from this one, although I try to keep them as similar as possible (I'm not
|
fingerprint scanners and provide a single uniform
|
||||||
hiding anything in the academic branch, it's just the open source release
|
API to application developers.
|
||||||
contains some commits excluded from the academic project).
|
|
||||||
|
## Goal
|
||||||
|
|
||||||
|
The ultimate goal of the **FPrint** project is to make
|
||||||
|
fingerprint scanners widely and easily usable under
|
||||||
|
common Linux environments.
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
THE UNIVERSITY OF MANCHESTER DOES NOT ENDORSE THIS THIS SOFTWARE RELEASE AND
|
`Section 6` of the license states that for compiled works that use
|
||||||
IS IN NO WAY RESPONSIBLE FOR THE CODE CONTAINED WITHIN, OR ANY DAMAGES CAUSED
|
this library, such works must include **LibFPrint** copyright notices
|
||||||
BY USING OR DISTRIBUTING THE SOFTWARE. Development does not happen on
|
alongside the copyright notices for the other parts of the work.
|
||||||
university computers and the project is not hosted at the university either.
|
|
||||||
|
|
||||||
For more information on libfprint, supported devices, API documentation, etc.,
|
**LibFPrint** includes code from **NIST's** **[NBIS]** software distribution.
|
||||||
see the homepage:
|
|
||||||
https://fprint.freedesktop.org/
|
|
||||||
|
|
||||||
libfprint is licensed under the GNU LGPL version 2.1. See the COPYING file
|
We include **Bozorth3** from the **[US Export Controlled]**
|
||||||
for the license text.
|
distribution, which we have determined to be fine
|
||||||
|
being shipped in an open source project.
|
||||||
|
|
||||||
Section 6 of the license states that for compiled works that use this
|
## Get in *touch*
|
||||||
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:
|
- [IRC] - `#fprint` @ `irc.oftc.net`
|
||||||
http://fingerprint.nist.gov/NBIS/index.html
|
- [Matrix] - `#fprint:matrix.org` bridged to the IRC channel
|
||||||
We include bozorth3 from the US export controlled distribution. We have
|
- [MailingList] - low traffic, not much used these days
|
||||||
determined that it is fine to ship bozorth3 in an open source project,
|
|
||||||
see https://fprint.freedesktop.org/us-export-control.html
|
|
||||||
|
|
||||||
## Historical links
|
<br/>
|
||||||
|
|
||||||
Older versions of libfprint are available at:
|
<div align="right">
|
||||||
https://sourceforge.net/projects/fprint/files/
|
|
||||||
|
|
||||||
Historical mailing-list archives:
|
[![Badge License]][License]
|
||||||
http://www.reactivated.net/fprint_list_archives/
|
|
||||||
|
|
||||||
Historical website:
|
</div>
|
||||||
http://web.archive.org/web/*/https://www.freedesktop.org/wiki/Software/fprint/
|
|
||||||
|
|
||||||
|
<!----------------------------------------------------------------------------->
|
||||||
|
|
||||||
|
[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
|
||||||
|
|||||||
+217
-8
@@ -67,7 +67,7 @@ usb:v08FFp5731*
|
|||||||
ID_PERSIST=0
|
ID_PERSIST=0
|
||||||
|
|
||||||
# Supported by libfprint driver aes4000
|
# Supported by libfprint driver aes4000
|
||||||
usb:v5501p08FF*
|
usb:v08FFp5501*
|
||||||
ID_AUTOSUSPEND=1
|
ID_AUTOSUSPEND=1
|
||||||
ID_PERSIST=0
|
ID_PERSIST=0
|
||||||
|
|
||||||
@@ -77,6 +77,23 @@ usb:v1C7Ap0571*
|
|||||||
ID_AUTOSUSPEND=1
|
ID_AUTOSUSPEND=1
|
||||||
ID_PERSIST=0
|
ID_PERSIST=0
|
||||||
|
|
||||||
|
# Supported by libfprint driver egis_etu905
|
||||||
|
usb:v1C7Ap05AE*
|
||||||
|
usb:v1C7Ap9201*
|
||||||
|
ID_AUTOSUSPEND=1
|
||||||
|
ID_PERSIST=0
|
||||||
|
|
||||||
|
# Supported by libfprint driver egismoc
|
||||||
|
usb:v1C7Ap0582*
|
||||||
|
usb:v1C7Ap0583*
|
||||||
|
usb:v1C7Ap0584*
|
||||||
|
usb:v1C7Ap0586*
|
||||||
|
usb:v1C7Ap0587*
|
||||||
|
usb:v1C7Ap0588*
|
||||||
|
usb:v1C7Ap05A1*
|
||||||
|
ID_AUTOSUSPEND=1
|
||||||
|
ID_PERSIST=0
|
||||||
|
|
||||||
# Supported by libfprint driver elan
|
# Supported by libfprint driver elan
|
||||||
usb:v04F3p0903*
|
usb:v04F3p0903*
|
||||||
usb:v04F3p0907*
|
usb:v04F3p0907*
|
||||||
@@ -147,6 +164,18 @@ usb:v04F3p0C7D*
|
|||||||
usb:v04F3p0C7E*
|
usb:v04F3p0C7E*
|
||||||
usb:v04F3p0C82*
|
usb:v04F3p0C82*
|
||||||
usb:v04F3p0C88*
|
usb:v04F3p0C88*
|
||||||
|
usb:v04F3p0C8C*
|
||||||
|
usb:v04F3p0C8D*
|
||||||
|
usb:v04F3p0C98*
|
||||||
|
usb:v04F3p0C99*
|
||||||
|
usb:v04F3p0C9C*
|
||||||
|
usb:v04F3p0C9D*
|
||||||
|
usb:v04F3p0C9F*
|
||||||
|
usb:v04F3p0CA3*
|
||||||
|
usb:v04F3p0CA7*
|
||||||
|
usb:v04F3p0CA8*
|
||||||
|
usb:v04F3p0CB0*
|
||||||
|
usb:v04F3p0CB2*
|
||||||
ID_AUTOSUSPEND=1
|
ID_AUTOSUSPEND=1
|
||||||
ID_PERSIST=0
|
ID_PERSIST=0
|
||||||
|
|
||||||
@@ -155,43 +184,136 @@ usb:v1C7Ap0603*
|
|||||||
ID_AUTOSUSPEND=1
|
ID_AUTOSUSPEND=1
|
||||||
ID_PERSIST=0
|
ID_PERSIST=0
|
||||||
|
|
||||||
|
# Supported by libfprint driver focaltech_moc
|
||||||
|
usb:v2808p9E48*
|
||||||
|
usb:v2808pD979*
|
||||||
|
usb:v2808pA27A*
|
||||||
|
usb:v2808pA959*
|
||||||
|
usb:v2808pA99A*
|
||||||
|
usb:v2808pA57A*
|
||||||
|
usb:v2808pA78A*
|
||||||
|
usb:v2808pA97A*
|
||||||
|
usb:v2808p1579*
|
||||||
|
usb:v2808p077A*
|
||||||
|
usb:v2808p079A*
|
||||||
|
usb:v2808p5158*
|
||||||
|
usb:v2808p6553*
|
||||||
|
ID_AUTOSUSPEND=1
|
||||||
|
ID_PERSIST=0
|
||||||
|
|
||||||
|
# Supported by libfprint driver fpcmoc
|
||||||
|
usb:v10A5pFFE0*
|
||||||
|
usb:v10A5pA305*
|
||||||
|
usb:v10A5pA306*
|
||||||
|
usb:v10A5pDA04*
|
||||||
|
usb:v10A5pD805*
|
||||||
|
usb:v10A5pD205*
|
||||||
|
usb:v10A5p9524*
|
||||||
|
usb:v10A5p9544*
|
||||||
|
usb:v10A5pC844*
|
||||||
|
usb:v10A5p9B24*
|
||||||
|
ID_AUTOSUSPEND=1
|
||||||
|
ID_PERSIST=0
|
||||||
|
|
||||||
# Supported by libfprint driver goodixmoc
|
# Supported by libfprint driver goodixmoc
|
||||||
usb:v27C6p5840*
|
usb:v27C6p5840*
|
||||||
|
usb:v27C6p6014*
|
||||||
|
usb:v27C6p6090*
|
||||||
|
usb:v27C6p6092*
|
||||||
|
usb:v27C6p6094*
|
||||||
|
usb:v27C6p609A*
|
||||||
usb:v27C6p609C*
|
usb:v27C6p609C*
|
||||||
usb:v27C6p60A2*
|
usb:v27C6p60A2*
|
||||||
|
usb:v27C6p60A4*
|
||||||
|
usb:v27C6p60BC*
|
||||||
|
usb:v27C6p60C2*
|
||||||
|
usb:v27C6p6304*
|
||||||
|
usb:v27C6p631C*
|
||||||
|
usb:v27C6p633C*
|
||||||
|
usb:v27C6p634C*
|
||||||
|
usb:v27C6p6382*
|
||||||
|
usb:v27C6p6384*
|
||||||
usb:v27C6p639C*
|
usb:v27C6p639C*
|
||||||
usb:v27C6p63AC*
|
usb:v27C6p63AC*
|
||||||
usb:v27C6p63BC*
|
usb:v27C6p63BC*
|
||||||
usb:v27C6p63CC*
|
usb:v27C6p63CC*
|
||||||
usb:v27C6p6496*
|
usb:v27C6p6496*
|
||||||
|
usb:v27C6p650A*
|
||||||
|
usb:v27C6p650C*
|
||||||
|
usb:v27C6p6582*
|
||||||
usb:v27C6p6584*
|
usb:v27C6p6584*
|
||||||
usb:v27C6p658C*
|
usb:v27C6p658C*
|
||||||
usb:v27C6p6592*
|
usb:v27C6p6592*
|
||||||
usb:v27C6p6594*
|
usb:v27C6p6594*
|
||||||
|
usb:v27C6p659A*
|
||||||
usb:v27C6p659C*
|
usb:v27C6p659C*
|
||||||
usb:v27C6p6A94*
|
usb:v27C6p6A94*
|
||||||
|
usb:v27C6p6512*
|
||||||
|
usb:v27C6p6890*
|
||||||
|
usb:v27C6p689A*
|
||||||
|
usb:v27C6p66A9*
|
||||||
|
usb:v27C6p6984*
|
||||||
|
ID_AUTOSUSPEND=1
|
||||||
|
ID_PERSIST=0
|
||||||
|
|
||||||
|
# Supported by libfprint driver mafpmoc
|
||||||
|
usb:v3274p8012*
|
||||||
ID_AUTOSUSPEND=1
|
ID_AUTOSUSPEND=1
|
||||||
ID_PERSIST=0
|
ID_PERSIST=0
|
||||||
|
|
||||||
# Supported by libfprint driver nb1010
|
# Supported by libfprint driver nb1010
|
||||||
usb:v298Dp1010*
|
usb:v298Dp1010*
|
||||||
|
usb:v298Dp2020*
|
||||||
|
ID_AUTOSUSPEND=1
|
||||||
|
ID_PERSIST=0
|
||||||
|
|
||||||
|
# Supported by libfprint driver realtek
|
||||||
|
usb:v0BDAp5813*
|
||||||
|
usb:v0BDAp5816*
|
||||||
|
usb:v2541pFA03*
|
||||||
|
usb:v3274p9003*
|
||||||
|
ID_AUTOSUSPEND=1
|
||||||
|
ID_PERSIST=0
|
||||||
|
|
||||||
|
# Supported by libfprint driver secugen
|
||||||
|
usb:v1162p2200*
|
||||||
ID_AUTOSUSPEND=1
|
ID_AUTOSUSPEND=1
|
||||||
ID_PERSIST=0
|
ID_PERSIST=0
|
||||||
|
|
||||||
# Supported by libfprint driver synaptics
|
# Supported by libfprint driver synaptics
|
||||||
usb:v06CBp00BD*
|
usb:v06CBp00BD*
|
||||||
|
usb:v06CBp00C2*
|
||||||
|
usb:v06CBp00C4*
|
||||||
|
usb:v06CBp00C6*
|
||||||
usb:v06CBp00DF*
|
usb:v06CBp00DF*
|
||||||
|
usb:v06CBp00E9*
|
||||||
|
usb:v06CBp00F0*
|
||||||
usb:v06CBp00F9*
|
usb:v06CBp00F9*
|
||||||
usb:v06CBp00FC*
|
usb:v06CBp00FC*
|
||||||
usb:v06CBp00C2*
|
|
||||||
usb:v06CBp0100*
|
usb:v06CBp0100*
|
||||||
usb:v06CBp00F0*
|
|
||||||
usb:v06CBp0103*
|
usb:v06CBp0103*
|
||||||
|
usb:v06CBp0104*
|
||||||
|
usb:v06CBp0106*
|
||||||
|
usb:v06CBp0107*
|
||||||
|
usb:v06CBp0108*
|
||||||
|
usb:v06CBp0109*
|
||||||
|
usb:v06CBp010A*
|
||||||
|
usb:v06CBp010D*
|
||||||
|
usb:v06CBp010E*
|
||||||
usb:v06CBp0123*
|
usb:v06CBp0123*
|
||||||
|
usb:v06CBp0124*
|
||||||
usb:v06CBp0126*
|
usb:v06CBp0126*
|
||||||
usb:v06CBp0129*
|
usb:v06CBp0129*
|
||||||
usb:v06CBp0168*
|
|
||||||
usb:v06CBp015F*
|
usb:v06CBp015F*
|
||||||
|
usb:v06CBp0168*
|
||||||
|
usb:v06CBp0169*
|
||||||
|
usb:v06CBp016C*
|
||||||
|
usb:v06CBp0173*
|
||||||
|
usb:v06CBp0174*
|
||||||
|
usb:v06CBp019D*
|
||||||
|
usb:v06CBp019F*
|
||||||
|
usb:v06CBp01A0*
|
||||||
|
usb:v06CBp01A4*
|
||||||
ID_AUTOSUSPEND=1
|
ID_AUTOSUSPEND=1
|
||||||
ID_PERSIST=0
|
ID_PERSIST=0
|
||||||
|
|
||||||
@@ -204,6 +326,7 @@ usb:v147Ep1001*
|
|||||||
|
|
||||||
# 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
|
ID_PERSIST=0
|
||||||
@@ -259,34 +382,80 @@ usb:v138Ap0091*
|
|||||||
ID_PERSIST=0
|
ID_PERSIST=0
|
||||||
|
|
||||||
# Known unsupported devices
|
# Known unsupported devices
|
||||||
|
usb:v006Bp00DA*
|
||||||
|
usb:v0413p2766*
|
||||||
|
usb:v045Ep0815*
|
||||||
|
usb:v047Dp00F2*
|
||||||
|
usb:v047Dp8054*
|
||||||
|
usb:v047Dp8055*
|
||||||
usb:v04E8p730B*
|
usb:v04E8p730B*
|
||||||
|
usb:v04F2pB61E*
|
||||||
usb:v04F3p036B*
|
usb:v04F3p036B*
|
||||||
usb:v04F3p0C00*
|
usb:v04F3p0C00*
|
||||||
usb:v04F3p0C4C*
|
usb:v04F3p0C4C*
|
||||||
usb:v04F3p0C57*
|
usb:v04F3p0C57*
|
||||||
|
usb:v04F3p0C5A*
|
||||||
usb:v04F3p0C5E*
|
usb:v04F3p0C5E*
|
||||||
|
usb:v04F3p0C60*
|
||||||
|
usb:v04F3p0C6C*
|
||||||
|
usb:v04F3p0C70*
|
||||||
|
usb:v04F3p0C72*
|
||||||
|
usb:v04F3p0C77*
|
||||||
|
usb:v04F3p0C7C*
|
||||||
|
usb:v04F3p0C7F*
|
||||||
|
usb:v04F3p0C80*
|
||||||
|
usb:v04F3p0C85*
|
||||||
|
usb:v04F3p0C8A*
|
||||||
|
usb:v04F3p0C8E*
|
||||||
|
usb:v04F3p0C90*
|
||||||
|
usb:v04F3p0CA2*
|
||||||
|
usb:v04F3p24CC*
|
||||||
usb:v04F3p2706*
|
usb:v04F3p2706*
|
||||||
|
usb:v04F3p3032*
|
||||||
|
usb:v04F3p3057*
|
||||||
|
usb:v04F3p3058*
|
||||||
|
usb:v04F3p3066*
|
||||||
|
usb:v04F3p3087*
|
||||||
|
usb:v04F3p309F*
|
||||||
|
usb:v04F3p30C6*
|
||||||
|
usb:v04F3p3104*
|
||||||
|
usb:v04F3p310D*
|
||||||
|
usb:v04F3p3128*
|
||||||
|
usb:v04F3p3195*
|
||||||
|
usb:v04F3p31FC*
|
||||||
|
usb:v04F3p3201*
|
||||||
|
usb:v04F3p3212*
|
||||||
|
usb:v05BAp000E*
|
||||||
|
usb:v05C8p03C0*
|
||||||
|
usb:v06CBp0051*
|
||||||
usb:v06CBp0081*
|
usb:v06CBp0081*
|
||||||
usb:v06CBp0088*
|
usb:v06CBp0088*
|
||||||
usb:v06CBp008A*
|
usb:v06CBp008A*
|
||||||
usb:v06CBp009A*
|
usb:v06CBp009A*
|
||||||
usb:v06CBp009B*
|
usb:v06CBp009B*
|
||||||
|
usb:v06CBp00A1*
|
||||||
usb:v06CBp00A2*
|
usb:v06CBp00A2*
|
||||||
usb:v06CBp00A8*
|
usb:v06CBp00A8*
|
||||||
usb:v06CBp00B7*
|
usb:v06CBp00B7*
|
||||||
usb:v06CBp00BB*
|
usb:v06CBp00BB*
|
||||||
|
usb:v06CBp00BC*
|
||||||
usb:v06CBp00BE*
|
usb:v06CBp00BE*
|
||||||
usb:v06CBp00C4*
|
usb:v06CBp00C7*
|
||||||
usb:v06CBp00CB*
|
|
||||||
usb:v06CBp00C9*
|
usb:v06CBp00C9*
|
||||||
|
usb:v06CBp00CB*
|
||||||
usb:v06CBp00D8*
|
usb:v06CBp00D8*
|
||||||
usb:v06CBp00DA*
|
usb:v06CBp00DA*
|
||||||
usb:v06CBp00DC*
|
usb:v06CBp00DC*
|
||||||
usb:v06CBp00E4*
|
usb:v06CBp00E4*
|
||||||
usb:v06CBp00E7*
|
usb:v06CBp00E7*
|
||||||
usb:v06CBp00E9*
|
|
||||||
usb:v06CBp00FD*
|
usb:v06CBp00FD*
|
||||||
|
usb:v06CBp00FF*
|
||||||
|
usb:v06CBp0102*
|
||||||
|
usb:v06CBpCE67*
|
||||||
|
usb:v06CBpCEEF*
|
||||||
|
usb:v08FFp3400*
|
||||||
usb:v0A5Cp5801*
|
usb:v0A5Cp5801*
|
||||||
|
usb:v0A5Cp5802*
|
||||||
usb:v0A5Cp5805*
|
usb:v0A5Cp5805*
|
||||||
usb:v0A5Cp5834*
|
usb:v0A5Cp5834*
|
||||||
usb:v0A5Cp5840*
|
usb:v0A5Cp5840*
|
||||||
@@ -295,11 +464,24 @@ usb:v0A5Cp5842*
|
|||||||
usb:v0A5Cp5843*
|
usb:v0A5Cp5843*
|
||||||
usb:v0A5Cp5844*
|
usb:v0A5Cp5844*
|
||||||
usb:v0A5Cp5845*
|
usb:v0A5Cp5845*
|
||||||
|
usb:v0A5Cp5860*
|
||||||
|
usb:v0A5Cp5863*
|
||||||
|
usb:v0A5Cp5864*
|
||||||
|
usb:v0A5Cp5865*
|
||||||
|
usb:v0A5Cp5866*
|
||||||
|
usb:v0A5Cp5867*
|
||||||
|
usb:v0BDAp0129*
|
||||||
usb:v0BDAp5812*
|
usb:v0BDAp5812*
|
||||||
usb:v10A5p0007*
|
usb:v10A5p0007*
|
||||||
usb:v10A5p9200*
|
usb:v10A5p9200*
|
||||||
|
usb:v10A5p9201*
|
||||||
usb:v10A5p9800*
|
usb:v10A5p9800*
|
||||||
|
usb:v10A5pA120*
|
||||||
|
usb:v10A5pA900*
|
||||||
|
usb:v10A5pA921*
|
||||||
|
usb:v10A5pE340*
|
||||||
usb:v1188p9545*
|
usb:v1188p9545*
|
||||||
|
usb:v138Ap0006*
|
||||||
usb:v138Ap0007*
|
usb:v138Ap0007*
|
||||||
usb:v138Ap003A*
|
usb:v138Ap003A*
|
||||||
usb:v138Ap003C*
|
usb:v138Ap003C*
|
||||||
@@ -310,6 +492,7 @@ usb:v138Ap0092*
|
|||||||
usb:v138Ap0094*
|
usb:v138Ap0094*
|
||||||
usb:v138Ap0097*
|
usb:v138Ap0097*
|
||||||
usb:v138Ap009D*
|
usb:v138Ap009D*
|
||||||
|
usb:v138Ap00A6*
|
||||||
usb:v138Ap00AB*
|
usb:v138Ap00AB*
|
||||||
usb:v147Ep1002*
|
usb:v147Ep1002*
|
||||||
usb:v1491p0088*
|
usb:v1491p0088*
|
||||||
@@ -317,15 +500,24 @@ usb:v16D1p1027*
|
|||||||
usb:v1C7Ap0300*
|
usb:v1C7Ap0300*
|
||||||
usb:v1C7Ap0575*
|
usb:v1C7Ap0575*
|
||||||
usb:v1C7Ap0576*
|
usb:v1C7Ap0576*
|
||||||
|
usb:v1C7Ap0577*
|
||||||
|
usb:v1C7Ap057E*
|
||||||
|
usb:v1C7Ap05A5*
|
||||||
|
usb:v1C7Ap05AA*
|
||||||
|
usb:v1C7Ap0801*
|
||||||
|
usb:v2541p0236*
|
||||||
|
usb:v2541p9711*
|
||||||
usb:v27C6p5042*
|
usb:v27C6p5042*
|
||||||
usb:v27C6p5110*
|
usb:v27C6p5110*
|
||||||
usb:v27C6p5117*
|
usb:v27C6p5117*
|
||||||
|
usb:v27C6p5120*
|
||||||
usb:v27C6p5125*
|
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*
|
||||||
@@ -333,15 +525,32 @@ usb:v27C6p538C*
|
|||||||
usb:v27C6p538D*
|
usb:v27C6p538D*
|
||||||
usb:v27C6p5395*
|
usb:v27C6p5395*
|
||||||
usb:v27C6p5503*
|
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:v27C6p581A*
|
||||||
|
usb:v27C6p589A*
|
||||||
usb:v27C6p5E0A*
|
usb:v27C6p5E0A*
|
||||||
|
usb:v27C6p5F10*
|
||||||
|
usb:v27C6p5F91*
|
||||||
|
usb:v2808p06FC*
|
||||||
|
usb:v2808p6652*
|
||||||
usb:v2808p9338*
|
usb:v2808p9338*
|
||||||
usb:v298Dp2020*
|
usb:v2808p9348*
|
||||||
|
usb:v2808p93A9*
|
||||||
|
usb:v2808pA553*
|
||||||
|
usb:v2808pA573*
|
||||||
|
usb:v2808pA658*
|
||||||
|
usb:v2808pC652*
|
||||||
usb:v298Dp2033*
|
usb:v298Dp2033*
|
||||||
|
usb:v2DF0p0003*
|
||||||
|
usb:v3274p9008*
|
||||||
|
usb:v3274pB012*
|
||||||
|
usb:v33A7p2388*
|
||||||
usb:v3538p0930*
|
usb:v3538p0930*
|
||||||
ID_AUTOSUSPEND=1
|
ID_AUTOSUSPEND=1
|
||||||
ID_PERSIST=0
|
ID_PERSIST=0
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
if udev_hwdb_dir != ''
|
if udev_hwdb_dir != ''
|
||||||
# This file has to be updated using
|
# This file has to be updated using
|
||||||
# ninja -C <builddir> libfprint/sync-udev-hwdb
|
# meson compile -C <builddir> sync-udev-hwdb
|
||||||
# Note that the unsupported device list needs to be manually synced from
|
# Note that the unsupported device list needs to be manually synced from
|
||||||
# the wiki. See comment in libfprint/fprint-list-uev-hwdb.c
|
# the wiki. See comment in libfprint/fprint-list-uev-hwdb.c
|
||||||
|
|
||||||
|
|||||||
@@ -101,11 +101,14 @@ plot_minutiae (unsigned char *rgbdata,
|
|||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
#define write_pixel(num) do { \
|
#define write_pixel(num) \
|
||||||
rgbdata[((num) * 3)] = 0xff; \
|
do \
|
||||||
rgbdata[((num) * 3) + 1] = 0; \
|
{ \
|
||||||
rgbdata[((num) * 3) + 2] = 0; \
|
rgbdata[((num) * 3)] = 0xff; \
|
||||||
} while(0)
|
rgbdata[((num) * 3) + 1] = 0; \
|
||||||
|
rgbdata[((num) * 3) + 2] = 0; \
|
||||||
|
} \
|
||||||
|
while(0)
|
||||||
|
|
||||||
for (i = 0; i < minutiae->len; i++)
|
for (i = 0; i < minutiae->len; i++)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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": "3.36",
|
"runtime-version": "master",
|
||||||
"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=x11",
|
"--share=ipc", "--socket=fallback-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", "--disable-udev" ],
|
"config-opts": [ "--disable-static" ],
|
||||||
"cleanup": [
|
"cleanup": [
|
||||||
"/lib/*.la",
|
"/lib/*.la",
|
||||||
"/lib/pkgconfig",
|
"/lib/pkgconfig",
|
||||||
@@ -26,48 +26,47 @@
|
|||||||
],
|
],
|
||||||
"sources": [
|
"sources": [
|
||||||
{
|
{
|
||||||
"type": "archive",
|
"type": "archive",
|
||||||
"url": "https://github.com/libusb/libusb/archive/v1.0.22.tar.gz",
|
"url": "https://github.com/libusb/libusb/releases/download/v1.0.26/libusb-1.0.26.tar.bz2",
|
||||||
"sha256": "3500f7b182750cd9ccf9be8b1df998f83df56a39ab264976bdb3307773e16f48"
|
"sha256": "12ce7a61fc9854d1d2a1ffe095f7b5fac19ddba095c259e6067a46500381b5a5"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"post-install": [
|
"post-install": [
|
||||||
"install -Dm644 COPYING /app/share/licenses/libgusb/COPYING"
|
"install -Dm644 COPYING /app/share/licenses/libusb/COPYING"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "libgusb",
|
"name": "libgusb",
|
||||||
"buildsystem": "meson",
|
"buildsystem": "meson",
|
||||||
"config-opts": [ "-Dtests=false", "-Dvapi=false", "-Ddocs=false", "-Dintrospection=false" ],
|
"config-opts": [ "-Dtests=false", "-Dvapi=false", "-Ddocs=false" ],
|
||||||
"sources": [
|
"sources": [
|
||||||
{
|
{
|
||||||
"type": "archive",
|
"type": "archive",
|
||||||
"url": "https://github.com/hughsie/libgusb/archive/0.3.0.tar.gz",
|
"url": "https://github.com/hughsie/libgusb/releases/download/0.4.6/libgusb-0.4.6.tar.xz",
|
||||||
"sha256": "b36310f8405d5fd68f6caf4a829f7ab4c627b38fd3d02a139d411fce0f3a49f1"
|
"sha256": "1b0422bdcd72183272ac42eec9398c5a0bc48a02f618fa3242c468cbbd003049"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "gudev",
|
"name": "gudev",
|
||||||
"buildsystem": "meson",
|
"buildsystem": "meson",
|
||||||
"config-opts": [ "-Dtests=disabled", "-Dintrospection=disabled" ],
|
"config-opts": [ "-Dtests=disabled", "-Dintrospection=disabled", "-Dvapi=disabled" ],
|
||||||
"sources": [
|
"sources": [
|
||||||
{
|
{
|
||||||
"type": "archive",
|
"type": "archive",
|
||||||
"url": "https://download.gnome.org/sources/libgudev/236/libgudev-236.tar.xz",
|
"url": "https://download.gnome.org/sources/libgudev/238/libgudev-238.tar.xz",
|
||||||
"sha256": "e50369d06d594bae615eb7aeb787de304ebaad07a26d1043cef8e9c7ab7c9524"
|
"sha256": "61266ab1afc9d73dbc60a8b2af73e99d2fdff47d99544d085760e4fa667b5dd1"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "libfprint",
|
"name": "libfprint",
|
||||||
"buildsystem": "meson",
|
"buildsystem": "meson",
|
||||||
"config-opts": [ "-Dudev_hwdb=disabled", "-Dudev_rules=disabled", "-Dx11-examples=false", "-Dgtk-examples=true", "-Ddrivers=all" ],
|
"config-opts": [ "-Dudev_hwdb=disabled", "-Dudev_rules=disabled", "-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"
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -75,6 +75,7 @@ fp_device_clear_storage_sync
|
|||||||
fp_device_suspend_sync
|
fp_device_suspend_sync
|
||||||
fp_device_resume_sync
|
fp_device_resume_sync
|
||||||
FpDevice
|
FpDevice
|
||||||
|
FpTemperature
|
||||||
</SECTION>
|
</SECTION>
|
||||||
|
|
||||||
<SECTION>
|
<SECTION>
|
||||||
@@ -134,6 +135,134 @@ fpi_line_asmbl_ctx
|
|||||||
fpi_assemble_lines
|
fpi_assemble_lines
|
||||||
</SECTION>
|
</SECTION>
|
||||||
|
|
||||||
|
<SECTION>
|
||||||
|
<FILE>fpi-byte-reader</FILE>
|
||||||
|
<TITLE>FpiByteReader</TITLE>
|
||||||
|
FpiByteReader
|
||||||
|
fpi_byte_reader_new
|
||||||
|
fpi_byte_reader_new_bytes
|
||||||
|
fpi_byte_reader_free
|
||||||
|
fpi_byte_reader_init
|
||||||
|
fpi_byte_reader_init_bytes
|
||||||
|
fpi_byte_reader_peek_sub_reader
|
||||||
|
fpi_byte_reader_get_sub_reader
|
||||||
|
fpi_byte_reader_set_pos
|
||||||
|
fpi_byte_reader_get_pos
|
||||||
|
fpi_byte_reader_get_remaining
|
||||||
|
fpi_byte_reader_get_size
|
||||||
|
fpi_byte_reader_skip
|
||||||
|
fpi_byte_reader_get_bytes
|
||||||
|
fpi_byte_reader_peek_bytes
|
||||||
|
fpi_byte_reader_get_uint8
|
||||||
|
fpi_byte_reader_get_int8
|
||||||
|
fpi_byte_reader_peek_uint8
|
||||||
|
fpi_byte_reader_peek_int8
|
||||||
|
fpi_byte_reader_get_uint16_le
|
||||||
|
fpi_byte_reader_get_int16_le
|
||||||
|
fpi_byte_reader_peek_uint16_le
|
||||||
|
fpi_byte_reader_peek_int16_le
|
||||||
|
fpi_byte_reader_get_uint16_be
|
||||||
|
fpi_byte_reader_get_int16_be
|
||||||
|
fpi_byte_reader_peek_uint16_be
|
||||||
|
fpi_byte_reader_peek_int16_be
|
||||||
|
fpi_byte_reader_get_uint24_le
|
||||||
|
fpi_byte_reader_get_int24_le
|
||||||
|
fpi_byte_reader_peek_uint24_le
|
||||||
|
fpi_byte_reader_peek_int24_le
|
||||||
|
fpi_byte_reader_get_uint24_be
|
||||||
|
fpi_byte_reader_get_int24_be
|
||||||
|
fpi_byte_reader_peek_uint24_be
|
||||||
|
fpi_byte_reader_peek_int24_be
|
||||||
|
fpi_byte_reader_get_uint32_le
|
||||||
|
fpi_byte_reader_get_int32_le
|
||||||
|
fpi_byte_reader_peek_uint32_le
|
||||||
|
fpi_byte_reader_peek_int32_le
|
||||||
|
fpi_byte_reader_get_uint32_be
|
||||||
|
fpi_byte_reader_get_int32_be
|
||||||
|
fpi_byte_reader_peek_uint32_be
|
||||||
|
fpi_byte_reader_peek_int32_be
|
||||||
|
fpi_byte_reader_get_uint64_le
|
||||||
|
fpi_byte_reader_get_int64_le
|
||||||
|
fpi_byte_reader_peek_uint64_le
|
||||||
|
fpi_byte_reader_peek_int64_le
|
||||||
|
fpi_byte_reader_get_uint64_be
|
||||||
|
fpi_byte_reader_get_int64_be
|
||||||
|
fpi_byte_reader_peek_uint64_be
|
||||||
|
fpi_byte_reader_peek_int64_be
|
||||||
|
fpi_byte_reader_get_float32_le
|
||||||
|
fpi_byte_reader_peek_float32_le
|
||||||
|
fpi_byte_reader_get_float32_be
|
||||||
|
fpi_byte_reader_peek_float32_be
|
||||||
|
fpi_byte_reader_get_float64_le
|
||||||
|
fpi_byte_reader_peek_float64_le
|
||||||
|
fpi_byte_reader_get_float64_be
|
||||||
|
fpi_byte_reader_peek_float64_be
|
||||||
|
fpi_byte_reader_get_data
|
||||||
|
fpi_byte_reader_peek_data
|
||||||
|
fpi_byte_reader_get_data_static
|
||||||
|
fpi_byte_reader_peek_data_static
|
||||||
|
fpi_byte_reader_dup_data
|
||||||
|
fpi_byte_reader_masked_scan_uint32
|
||||||
|
fpi_byte_reader_masked_scan_uint32_peek
|
||||||
|
fpi_byte_reader_skip_string
|
||||||
|
fpi_byte_reader_skip_string_utf8
|
||||||
|
fpi_byte_reader_skip_string_utf16
|
||||||
|
fpi_byte_reader_skip_string_utf32
|
||||||
|
fpi_byte_reader_peek_string
|
||||||
|
fpi_byte_reader_peek_string_utf8
|
||||||
|
fpi_byte_reader_get_string_utf8
|
||||||
|
fpi_byte_reader_dup_string_utf8
|
||||||
|
fpi_byte_reader_dup_string_utf16
|
||||||
|
fpi_byte_reader_dup_string_utf32
|
||||||
|
</SECTION>
|
||||||
|
|
||||||
|
<SECTION>
|
||||||
|
<FILE>fpi-byte-writer</FILE>
|
||||||
|
<TITLE>FpiByteWriter</TITLE>
|
||||||
|
FpiByteWriter
|
||||||
|
fpi_byte_writer_new
|
||||||
|
fpi_byte_writer_new_with_size
|
||||||
|
fpi_byte_writer_new_with_data
|
||||||
|
fpi_byte_writer_init
|
||||||
|
fpi_byte_writer_init_with_size
|
||||||
|
fpi_byte_writer_init_with_data
|
||||||
|
fpi_byte_writer_reset
|
||||||
|
fpi_byte_writer_reset_and_get_bytes
|
||||||
|
fpi_byte_writer_reset_and_get_data
|
||||||
|
fpi_byte_writer_free
|
||||||
|
fpi_byte_writer_free_and_get_data
|
||||||
|
fpi_byte_writer_get_remaining
|
||||||
|
fpi_byte_writer_ensure_free_space
|
||||||
|
fpi_byte_writer_put_bytes
|
||||||
|
fpi_byte_writer_put_uint8
|
||||||
|
fpi_byte_writer_put_uint16_be
|
||||||
|
fpi_byte_writer_put_uint24_be
|
||||||
|
fpi_byte_writer_put_uint32_be
|
||||||
|
fpi_byte_writer_put_uint64_be
|
||||||
|
fpi_byte_writer_put_uint16_le
|
||||||
|
fpi_byte_writer_put_uint24_le
|
||||||
|
fpi_byte_writer_put_uint32_le
|
||||||
|
fpi_byte_writer_put_uint64_le
|
||||||
|
fpi_byte_writer_put_int8
|
||||||
|
fpi_byte_writer_put_int16_be
|
||||||
|
fpi_byte_writer_put_int24_be
|
||||||
|
fpi_byte_writer_put_int32_be
|
||||||
|
fpi_byte_writer_put_int64_be
|
||||||
|
fpi_byte_writer_put_int16_le
|
||||||
|
fpi_byte_writer_put_int24_le
|
||||||
|
fpi_byte_writer_put_int32_le
|
||||||
|
fpi_byte_writer_put_int64_le
|
||||||
|
fpi_byte_writer_put_float32_be
|
||||||
|
fpi_byte_writer_put_float64_be
|
||||||
|
fpi_byte_writer_put_float32_le
|
||||||
|
fpi_byte_writer_put_float64_le
|
||||||
|
fpi_byte_writer_put_string_utf8
|
||||||
|
fpi_byte_writer_put_string_utf16
|
||||||
|
fpi_byte_writer_put_string_utf32
|
||||||
|
fpi_byte_writer_put_data
|
||||||
|
fpi_byte_writer_fill
|
||||||
|
</SECTION>
|
||||||
|
|
||||||
<SECTION>
|
<SECTION>
|
||||||
<FILE>fpi-context</FILE>
|
<FILE>fpi-context</FILE>
|
||||||
fpi_get_driver_types
|
fpi_get_driver_types
|
||||||
@@ -153,6 +282,7 @@ fpi_device_get_current_action
|
|||||||
fpi_device_retry_new
|
fpi_device_retry_new
|
||||||
fpi_device_error_new
|
fpi_device_error_new
|
||||||
fpi_device_retry_new_msg
|
fpi_device_retry_new_msg
|
||||||
|
fpi_device_emulation_mode_enabled
|
||||||
fpi_device_error_new_msg
|
fpi_device_error_new_msg
|
||||||
fpi_device_get_driver_data
|
fpi_device_get_driver_data
|
||||||
fpi_device_get_enroll_data
|
fpi_device_get_enroll_data
|
||||||
@@ -218,9 +348,12 @@ fpi_image_device_set_bz3_threshold
|
|||||||
<SECTION>
|
<SECTION>
|
||||||
<FILE>fpi-log</FILE>
|
<FILE>fpi-log</FILE>
|
||||||
fp_dbg
|
fp_dbg
|
||||||
|
fp_dbg_hex_dump_bytes
|
||||||
|
fp_dbg_hex_dump_data
|
||||||
fp_info
|
fp_info
|
||||||
fp_warn
|
fp_warn
|
||||||
fp_err
|
fp_err
|
||||||
|
fpi_log_is_debug_transfer_enabled
|
||||||
BUG_ON
|
BUG_ON
|
||||||
BUG
|
BUG
|
||||||
</SECTION>
|
</SECTION>
|
||||||
|
|||||||
@@ -48,6 +48,12 @@
|
|||||||
<xi:include href="xml/fpi-log.xml"/>
|
<xi:include href="xml/fpi-log.xml"/>
|
||||||
</chapter>
|
</chapter>
|
||||||
|
|
||||||
|
<chapter id="driver-data">
|
||||||
|
<title>Binary buffer I/O</title>
|
||||||
|
<xi:include href="xml/fpi-byte-reader.xml"/>
|
||||||
|
<xi:include href="xml/fpi-byte-writer.xml"/>
|
||||||
|
</chapter>
|
||||||
|
|
||||||
<chapter id="driver-img">
|
<chapter id="driver-img">
|
||||||
<title>Image manipulation</title>
|
<title>Image manipulation</title>
|
||||||
<xi:include href="xml/fpi-image.xml"/>
|
<xi:include href="xml/fpi-image.xml"/>
|
||||||
|
|||||||
+2
-2
@@ -19,13 +19,13 @@ content_files = [
|
|||||||
|
|
||||||
expand_content_files = content_files
|
expand_content_files = content_files
|
||||||
|
|
||||||
glib_prefix = dependency('glib-2.0').get_pkgconfig_variable('prefix')
|
glib_prefix = dependency('glib-2.0').get_variable(pkgconfig: '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.source_root(), 'libfprint'),
|
src_dir: join_paths(meson.project_source_root(), 'libfprint'),
|
||||||
include_directories: include_directories('../libfprint'),
|
include_directories: include_directories('../libfprint'),
|
||||||
dependencies: libfprint_dep,
|
dependencies: libfprint_dep,
|
||||||
content_files: content_files,
|
content_files: content_files,
|
||||||
|
|||||||
@@ -0,0 +1,208 @@
|
|||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
}
|
||||||
@@ -5,6 +5,7 @@ examples = [
|
|||||||
'img-capture',
|
'img-capture',
|
||||||
'manage-prints',
|
'manage-prints',
|
||||||
'verify',
|
'verify',
|
||||||
|
'clear-storage',
|
||||||
]
|
]
|
||||||
|
|
||||||
foreach example: examples
|
foreach example: examples
|
||||||
@@ -21,3 +22,8 @@ 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
|
||||||
|
|||||||
+63
-5
@@ -26,6 +26,7 @@
|
|||||||
#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>
|
||||||
@@ -55,6 +56,18 @@ 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)
|
||||||
{
|
{
|
||||||
@@ -169,8 +182,6 @@ 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;
|
||||||
@@ -178,9 +189,7 @@ 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);
|
||||||
driver = fp_device_get_driver (dev);
|
dev_prefix = get_print_prefix_for_device (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))
|
||||||
@@ -208,6 +217,55 @@ 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, gboolean load_existing)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -20,12 +20,17 @@
|
|||||||
|
|
||||||
#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);
|
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);
|
const gboolean load_existing);
|
||||||
|
|||||||
@@ -791,7 +791,7 @@ complete_deactivation (FpImageDevice *dev)
|
|||||||
* maybe we can do this with a master reset, unconditionally? */
|
* maybe we can do this with a master reset, unconditionally? */
|
||||||
|
|
||||||
self->deactivating = FALSE;
|
self->deactivating = FALSE;
|
||||||
g_slist_free (self->strips);
|
g_slist_free_full (self->strips, g_free);
|
||||||
self->strips = NULL;
|
self->strips = NULL;
|
||||||
self->strips_len = 0;
|
self->strips_len = 0;
|
||||||
self->blanks_count = 0;
|
self->blanks_count = 0;
|
||||||
|
|||||||
@@ -213,9 +213,8 @@ sum_histogram_values (unsigned char *data, guint8 threshold)
|
|||||||
if (threshold > 0x0f)
|
if (threshold > 0x0f)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
/* FIXME endianness */
|
|
||||||
for (i = threshold; i < 16; i++)
|
for (i = threshold; i < 16; i++)
|
||||||
r += histogram[i];
|
r += GUINT16_FROM_LE (histogram[i]);
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
@@ -823,7 +822,7 @@ complete_deactivation (FpImageDevice *dev)
|
|||||||
* maybe we can do this with a master reset, unconditionally? */
|
* maybe we can do this with a master reset, unconditionally? */
|
||||||
|
|
||||||
self->deactivating = FALSE;
|
self->deactivating = FALSE;
|
||||||
g_slist_free (self->strips);
|
g_slist_free_full (self->strips, g_free);
|
||||||
self->strips = NULL;
|
self->strips = NULL;
|
||||||
self->strips_len = 0;
|
self->strips_len = 0;
|
||||||
fpi_image_device_deactivate_complete (dev, NULL);
|
fpi_image_device_deactivate_complete (dev, NULL);
|
||||||
|
|||||||
@@ -57,6 +57,7 @@ struct _FpiDeviceAes2550
|
|||||||
|
|
||||||
GSList *strips;
|
GSList *strips;
|
||||||
size_t strips_len;
|
size_t strips_len;
|
||||||
|
gboolean active;
|
||||||
gboolean deactivating;
|
gboolean deactivating;
|
||||||
int heartbeat_cnt;
|
int heartbeat_cnt;
|
||||||
};
|
};
|
||||||
@@ -91,11 +92,21 @@ finger_det_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);
|
||||||
|
FpiDeviceAes2550 *self = FPI_DEVICE_AES2550 (device);
|
||||||
unsigned char *data = transfer->buffer;
|
unsigned char *data = transfer->buffer;
|
||||||
|
|
||||||
if (error)
|
if (error)
|
||||||
{
|
{
|
||||||
fpi_image_device_session_error (FP_IMAGE_DEVICE (device), error);
|
/* The finger-detect loop is broken; it no longer has a pending
|
||||||
|
* operation. Clear the active flag so that the deactivation
|
||||||
|
* triggered by the session error (or an in-flight cancellation)
|
||||||
|
* can complete. */
|
||||||
|
self->active = FALSE;
|
||||||
|
|
||||||
|
if (self->deactivating)
|
||||||
|
complete_deactivation (dev);
|
||||||
|
else
|
||||||
|
fpi_image_device_session_error (dev, error);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -122,10 +133,20 @@ finger_det_reqs_cb (FpiUsbTransfer *t, FpDevice *device,
|
|||||||
{
|
{
|
||||||
FpiUsbTransfer *transfer;
|
FpiUsbTransfer *transfer;
|
||||||
FpImageDevice *dev = FP_IMAGE_DEVICE (device);
|
FpImageDevice *dev = FP_IMAGE_DEVICE (device);
|
||||||
|
FpiDeviceAes2550 *self = FPI_DEVICE_AES2550 (device);
|
||||||
|
|
||||||
if (error)
|
if (error)
|
||||||
{
|
{
|
||||||
fpi_image_device_session_error (dev, error);
|
/* The finger-detect loop is broken; it no longer has a pending
|
||||||
|
* operation. Clear the active flag so that the deactivation
|
||||||
|
* triggered by the session error (or an in-flight cancellation)
|
||||||
|
* can complete. */
|
||||||
|
self->active = FALSE;
|
||||||
|
|
||||||
|
if (self->deactivating)
|
||||||
|
complete_deactivation (dev);
|
||||||
|
else
|
||||||
|
fpi_image_device_session_error (dev, error);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -239,13 +260,19 @@ capture_set_idle_reqs_cb (FpiUsbTransfer *transfer,
|
|||||||
/* marking machine complete will re-trigger finger detection loop */
|
/* marking machine complete will re-trigger finger detection loop */
|
||||||
fpi_ssm_mark_completed (transfer->ssm);
|
fpi_ssm_mark_completed (transfer->ssm);
|
||||||
}
|
}
|
||||||
|
else if (!error)
|
||||||
|
{
|
||||||
|
/* No image frames were captured (e.g. user tapped without swiping).
|
||||||
|
* Such case is quite easy to happen, since Super RSR is enabled and
|
||||||
|
* thus "Slices with 0-3 pixels of Y motion are discarded" according
|
||||||
|
* to the design specification manual. */
|
||||||
|
fpi_image_device_retry_scan (dev, FP_DEVICE_RETRY_TOO_SHORT);
|
||||||
|
fpi_image_device_report_finger_status (dev, FALSE);
|
||||||
|
fpi_ssm_mark_completed (transfer->ssm);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (error)
|
fpi_ssm_mark_failed (transfer->ssm, error);
|
||||||
fpi_ssm_mark_failed (transfer->ssm, error);
|
|
||||||
else
|
|
||||||
fpi_ssm_mark_failed (transfer->ssm,
|
|
||||||
fpi_device_error_new (FP_DEVICE_ERROR_PROTO));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -371,6 +398,11 @@ capture_sm_complete (FpiSsm *ssm, FpDevice *_dev, GError *error)
|
|||||||
}
|
}
|
||||||
else if (error)
|
else if (error)
|
||||||
{
|
{
|
||||||
|
/* The capture SSM has terminated, so no completion handler is left
|
||||||
|
* to observe the deactivation that the session error triggers.
|
||||||
|
* Clear the active flag so dev_deactivate() completes it directly.
|
||||||
|
*/
|
||||||
|
self->active = FALSE;
|
||||||
fpi_image_device_session_error (dev, error);
|
fpi_image_device_session_error (dev, error);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -489,12 +521,16 @@ activate_run_state (FpiSsm *ssm, FpDevice *dev)
|
|||||||
static void
|
static void
|
||||||
activate_sm_complete (FpiSsm *ssm, FpDevice *_dev, GError *error)
|
activate_sm_complete (FpiSsm *ssm, FpDevice *_dev, GError *error)
|
||||||
{
|
{
|
||||||
|
FpiDeviceAes2550 *self = FPI_DEVICE_AES2550 (_dev);
|
||||||
FpImageDevice *dev = FP_IMAGE_DEVICE (_dev);
|
FpImageDevice *dev = FP_IMAGE_DEVICE (_dev);
|
||||||
|
|
||||||
fpi_image_device_activate_complete (dev, error);
|
fpi_image_device_activate_complete (dev, error);
|
||||||
|
|
||||||
if (!error)
|
if (!error)
|
||||||
start_finger_detection (dev);
|
{
|
||||||
|
self->active = TRUE;
|
||||||
|
start_finger_detection (dev);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -511,6 +547,13 @@ dev_deactivate (FpImageDevice *dev)
|
|||||||
{
|
{
|
||||||
FpiDeviceAes2550 *self = FPI_DEVICE_AES2550 (dev);
|
FpiDeviceAes2550 *self = FPI_DEVICE_AES2550 (dev);
|
||||||
|
|
||||||
|
if (!self->active)
|
||||||
|
{
|
||||||
|
/* No operation is pending, so complete it right away. */
|
||||||
|
complete_deactivation (dev);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
self->deactivating = TRUE;
|
self->deactivating = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -522,6 +565,7 @@ complete_deactivation (FpImageDevice *dev)
|
|||||||
G_DEBUG_HERE ();
|
G_DEBUG_HERE ();
|
||||||
|
|
||||||
self->deactivating = FALSE;
|
self->deactivating = FALSE;
|
||||||
|
self->active = FALSE;
|
||||||
g_slist_free (self->strips);
|
g_slist_free (self->strips);
|
||||||
self->strips = NULL;
|
self->strips = NULL;
|
||||||
self->strips_len = 0;
|
self->strips_len = 0;
|
||||||
|
|||||||
@@ -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[] = {
|
||||||
{ .pid = 0x08ff, .vid = 0x5501 },
|
{ .vid = 0x08ff, .pid = 0x5501 },
|
||||||
{ .vid = 0, .pid = 0, .driver_data = 0 },
|
{ .vid = 0, .pid = 0, .driver_data = 0 },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -384,6 +384,15 @@ capture_read_stripe_data_cb (FpiUsbTransfer *transfer,
|
|||||||
|
|
||||||
payload_length = priv->stripe_packet->data[AESX660_RESPONSE_SIZE_LSB_OFFSET] +
|
payload_length = priv->stripe_packet->data[AESX660_RESPONSE_SIZE_LSB_OFFSET] +
|
||||||
(priv->stripe_packet->data[AESX660_RESPONSE_SIZE_MSB_OFFSET] << 8);
|
(priv->stripe_packet->data[AESX660_RESPONSE_SIZE_MSB_OFFSET] << 8);
|
||||||
|
|
||||||
|
if (payload_length > AESX660_BULK_TRANSFER_SIZE)
|
||||||
|
{
|
||||||
|
fp_dbg ("Oversized payload length %" G_GSSIZE_FORMAT ", discarding",
|
||||||
|
payload_length);
|
||||||
|
g_byte_array_set_size (priv->stripe_packet, 0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
fp_dbg ("Got frame, type %.2x payload of size %.4lx",
|
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);
|
(long) payload_length);
|
||||||
@@ -722,7 +731,7 @@ complete_deactivation (FpImageDevice *dev)
|
|||||||
G_DEBUG_HERE ();
|
G_DEBUG_HERE ();
|
||||||
|
|
||||||
priv->deactivating = FALSE;
|
priv->deactivating = FALSE;
|
||||||
g_slist_free (priv->strips);
|
g_slist_free_full (priv->strips, g_free);
|
||||||
priv->strips = NULL;
|
priv->strips = NULL;
|
||||||
priv->strips_len = 0;
|
priv->strips_len = 0;
|
||||||
fpi_image_device_deactivate_complete (dev, NULL);
|
fpi_image_device_deactivate_complete (dev, NULL);
|
||||||
|
|||||||
@@ -190,7 +190,7 @@ data_resp_cb (FpiUsbTransfer *transfer, FpDevice *dev, gpointer user_data, GErro
|
|||||||
{
|
{
|
||||||
if (!self->stop && (self->strips_len > 0))
|
if (!self->stop && (self->strips_len > 0))
|
||||||
{
|
{
|
||||||
FpImage *img;
|
g_autoptr(FpImage) img = NULL;
|
||||||
self->strips = g_slist_reverse (self->strips);
|
self->strips = g_slist_reverse (self->strips);
|
||||||
fpi_do_movement_estimation (&assembling_ctx, self->strips);
|
fpi_do_movement_estimation (&assembling_ctx, self->strips);
|
||||||
img = fpi_assemble_frames (&assembling_ctx, self->strips);
|
img = fpi_assemble_frames (&assembling_ctx, self->strips);
|
||||||
@@ -199,7 +199,7 @@ data_resp_cb (FpiUsbTransfer *transfer, FpDevice *dev, gpointer user_data, GErro
|
|||||||
self->strips = NULL;
|
self->strips = NULL;
|
||||||
self->strips_len = 0;
|
self->strips_len = 0;
|
||||||
FpImage *resizeImage = fpi_image_resize (img, EGIS0570_RESIZE, EGIS0570_RESIZE);
|
FpImage *resizeImage = fpi_image_resize (img, EGIS0570_RESIZE, EGIS0570_RESIZE);
|
||||||
fpi_image_device_image_captured (img_self, resizeImage);
|
fpi_image_device_image_captured (img_self, g_steal_pointer (&resizeImage));
|
||||||
}
|
}
|
||||||
|
|
||||||
fpi_image_device_report_finger_status (img_self, FALSE);
|
fpi_image_device_report_finger_status (img_self, FALSE);
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,188 @@
|
|||||||
|
/*
|
||||||
|
* Driver for Egis Technology (LighTuning) Match-On-Chip sensors
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "fpi-device.h"
|
||||||
|
#include "fpi-ssm.h"
|
||||||
|
|
||||||
|
G_DECLARE_FINAL_TYPE (FpiDeviceEgisEtu905, fpi_device_egis_etu905, FPI, DEVICE_EGIS_ETU905, FpDevice)
|
||||||
|
|
||||||
|
#define EGIS_ETU905_DRIVER_FULLNAME "Egis Technology (LighTuning) Match-on-Chip"
|
||||||
|
|
||||||
|
#define EGIS_ETU905_DRIVER_CHECK_PREFIX_TYPE1 (1 << 0)
|
||||||
|
#define EGIS_ETU905_DRIVER_CHECK_PREFIX_TYPE2 (1 << 1)
|
||||||
|
#define EGIS_ETU905_DRIVER_MAX_ENROLL_STAGES_20 (1 << 2)
|
||||||
|
|
||||||
|
#define EGIS_ETU905_EP_CMD_OUT (0x02 | FPI_USB_ENDPOINT_OUT)
|
||||||
|
#define EGIS_ETU905_EP_CMD_IN (0x81 | FPI_USB_ENDPOINT_IN)
|
||||||
|
#define EGIS_ETU905_EP_CMD_INTERRUPT_IN 0x83
|
||||||
|
|
||||||
|
#define EGIS_ETU905_USB_CONTROL_TIMEOUT 5000
|
||||||
|
#define EGIS_ETU905_USB_SEND_TIMEOUT 5000
|
||||||
|
#define EGIS_ETU905_USB_RECV_TIMEOUT 5000
|
||||||
|
#define EGIS_ETU905_USB_INTERRUPT_TIMEOUT 0 /* No timeout for waiting for finger down */
|
||||||
|
|
||||||
|
#define EGIS_ETU905_USB_IN_RECV_LENGTH 4096
|
||||||
|
#define EGIS_ETU905_USB_INTERRUPT_IN_RECV_LENGTH 64
|
||||||
|
|
||||||
|
#define EGIS_ETU905_MAX_ENROLL_STAGES_DEFAULT 12
|
||||||
|
#define EGIS_ETU905_MAX_ENROLL_NUM 12
|
||||||
|
#define EGIS_ETU905_FINGERPRINT_DATA_SIZE 32
|
||||||
|
#define EGIS_ETU905_LIST_RESPONSE_PREFIX_SIZE 14
|
||||||
|
#define EGIS_ETU905_LIST_RESPONSE_SUFFIX_SIZE 2
|
||||||
|
|
||||||
|
#define EGIS_ETU905_PARA_4_SIZE 68
|
||||||
|
|
||||||
|
#define EGIS_ETU905_PARA_1_VALUE 0
|
||||||
|
#define EGIS_ETU905_PARA_2_VALUE 0
|
||||||
|
#define EGIS_ETU905_PARA_3_VALUE 32
|
||||||
|
|
||||||
|
/* standard prefixes for all read/writes */
|
||||||
|
|
||||||
|
static const guchar egis_etu905_write_prefix[] = {'E', 'G', 'I', 'S', 0x00, 0x00, 0x00, 0x01};
|
||||||
|
|
||||||
|
static const guchar egis_etu905_read_prefix[] = {'S', 'I', 'G', 'E', 0x00, 0x00, 0x00, 0x01};
|
||||||
|
|
||||||
|
|
||||||
|
/* hard-coded command payloads */
|
||||||
|
|
||||||
|
static const guchar cmd_fw_version[] = {0x00, 0x00, 0x00, 0x07, 0x50, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x0c};
|
||||||
|
static const guchar rsp_fw_version_suffix[] = {0x90, 0x00};
|
||||||
|
|
||||||
|
static const guchar cmd_init[] = {0x00, 0x00, 0x00, 0x29, 0x50, 0x81, 0x80, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x12, 0x00, 0x45, 0x67, 0x69, 0x73,
|
||||||
|
0x46, 0x50, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x00, 0x51, 0xc6, 0xbd, 0x71};
|
||||||
|
|
||||||
|
static const guchar cmd_list[] = {0x00, 0x00, 0x00, 0x07, 0x50, 0x19, 0x04, 0x00, 0x00, 0x01, 0x40};
|
||||||
|
|
||||||
|
static const guchar cmd_sensor_reset[] = {0x00, 0x00, 0x00, 0x04, 0x50, 0x1a, 0x00, 0x00};
|
||||||
|
|
||||||
|
static const guchar cmd_sensor_check[] = {0x00, 0x00, 0x00, 0x04, 0x50, 0x17, 0x02, 0x00};
|
||||||
|
|
||||||
|
static const guchar cmd_sensor_identify[] = {0x00, 0x00, 0x00, 0x04, 0x50, 0x17, 0x01, 0x01};
|
||||||
|
|
||||||
|
static const guchar rsp_identify_match_suffix[] = {0x90, 0x00};
|
||||||
|
|
||||||
|
static const guchar rsp_identify_notmatch_suffix[] = {0x90, 0x04};
|
||||||
|
|
||||||
|
static const guchar cmd_enroll_starting[] = {0x00, 0x00, 0x00, 0x07, 0x50, 0x16, 0x01, 0x00, 0x00, 0x00, 0x20};
|
||||||
|
static const guchar cmd_enroll_discard[] = {0x00, 0x00, 0x00, 0x07, 0x50, 0x16, 0x04, 0x00, 0x00, 0x00, 0x20};
|
||||||
|
|
||||||
|
|
||||||
|
static const guchar cmd_sensor_start_capture[] = {0x00, 0x00, 0x00, 0x04, 0x50, 0x16, 0x02, 0x01};
|
||||||
|
|
||||||
|
static const guchar cmd_read_capture[] = {0x00, 0x00, 0x00, 0x07, 0x50, 0x16, 0x02, 0x02, 0x00, 0x00, 0x02};
|
||||||
|
|
||||||
|
static const guchar cmd_duplicate_check[] = {0x00, 0x00, 0x00, 0x04, 0x50, 0x16, 0x05, 0x00};
|
||||||
|
|
||||||
|
static const guchar rsp_read_success_prefix[] = {0x00, 0x00, 0x00, 0x04};
|
||||||
|
static const guchar rsp_read_success_suffix[] = {0x90, 0x00};
|
||||||
|
static const guchar rsp_read_offcenter_prefix[] = {0x00, 0x00, 0x00, 0x04};
|
||||||
|
static const guchar rsp_read_offcenter_suffix[] = {0x64, 0x91};
|
||||||
|
static const guchar rsp_read_dirty_prefix[] = {0x00, 0x00, 0x00, 0x02, 0x64};
|
||||||
|
|
||||||
|
static const guchar cmd_commit_starting[] = {0x00, 0x00, 0x00, 0x07, 0x50, 0x16, 0x05, 0x00, 0x00, 0x00, 0x20};
|
||||||
|
|
||||||
|
static const guchar cmd_identify_cancel[] = {0x00, 0x00, 0x00, 0x04, 0x50, 0x04, 0x01, 0x00};
|
||||||
|
static const guchar cmd_identify_cancel_result[] = {0x00, 0x00, 0x00, 0x04, 0x50, 0x04, 0x02, 0x00};
|
||||||
|
|
||||||
|
/* prefixes/suffixes and other things for dynamically created command payloads */
|
||||||
|
|
||||||
|
#define EGIS_ETU905_CHECK_BYTES_LENGTH 2
|
||||||
|
#define EGIS_ETU905_IDENTIFY_RESPONSE_PRINT_ID_OFFSET 46
|
||||||
|
#define EGIS_ETU905_CMD_CHECK_SEPARATOR_LENGTH 32
|
||||||
|
|
||||||
|
static const guchar cmd_new_print_prefix_type2[] = {0x00, 0x00, 0x00, 0x50, 0x50, 0x16, 0x03, 0x00, 0x00, 0x00, 0x49};
|
||||||
|
|
||||||
|
static const guchar cmd_delete_prefix[] = {0x50, 0x18, 0x04, 0x00, 0x00};
|
||||||
|
static const guchar rsp_delete_success_prefix[] = {0x00, 0x00, 0x00, 0x02, 0x90, 0x00};
|
||||||
|
|
||||||
|
static const guchar cmd_check_prefix_type1[] = {0x50, 0x17, 0x03, 0x00, 0x00};
|
||||||
|
static const guchar cmd_check_prefix_type2[] = {0x50, 0x17, 0x03, 0x80, 0x00};
|
||||||
|
static const guchar cmd_check_suffix[] = {0x00, 0x40};
|
||||||
|
static const guchar rsp_check_not_yet_enrolled_suffix[] = {0x90, 0x04};
|
||||||
|
|
||||||
|
|
||||||
|
/* SSM task states and various status enums */
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
CMD_SEND,
|
||||||
|
CMD_GET,
|
||||||
|
CMD_STATES,
|
||||||
|
} CommandStates;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
DEV_GET_FW_VERSION,
|
||||||
|
DEV_INIT_CONTROL,
|
||||||
|
DEV_INIT_STATES,
|
||||||
|
} DeviceInitStates;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
IDENTIFY_GET_ENROLLED_IDS,
|
||||||
|
IDENTIFY_CHECK_ENROLLED_NUM,
|
||||||
|
IDENTIFY_SENSOR_RESET,
|
||||||
|
IDENTIFY_SENSOR_IDENTIFY,
|
||||||
|
IDENTIFY_WAIT_FINGER,
|
||||||
|
IDENTIFY_SENSOR_CHECK,
|
||||||
|
IDENTIFY_CHECK,
|
||||||
|
IDENTIFY_COMPLETE_SENSOR_RESET,
|
||||||
|
IDENTIFY_COMPLETE,
|
||||||
|
IDENTIFY_STATES,
|
||||||
|
} IdentifyStates;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
ENROLL_START,
|
||||||
|
ENROLL_CAPTURE_SENSOR_RESET,
|
||||||
|
ENROLL_CAPTURE_SENSOR_START_CAPTURE,
|
||||||
|
ENROLL_CAPTURE_WAIT_FINGER,
|
||||||
|
ENROLL_CAPTURE_READ_RESPONSE,
|
||||||
|
ENROLL_DUPLICATE_CHECK,
|
||||||
|
ENROLL_COMMIT_START,
|
||||||
|
ENROLL_COMMIT,
|
||||||
|
ENROLL_COMMIT_SENSOR_RESET,
|
||||||
|
ENROLL_COMPLETE,
|
||||||
|
ENROLL_STATES,
|
||||||
|
} EnrollStates;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
ENROLL_STATUS_DEVICE_FULL,
|
||||||
|
ENROLL_STATUS_DUPLICATE,
|
||||||
|
ENROLL_STATUS_PARTIAL_OK,
|
||||||
|
ENROLL_STATUS_RETRY,
|
||||||
|
ENROLL_STATUS_COMPLETE,
|
||||||
|
} EnrollStatus;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
LIST_GET_ENROLLED_IDS,
|
||||||
|
LIST_RETURN_ENROLLED_PRINTS,
|
||||||
|
LIST_STATES,
|
||||||
|
} ListStates;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
DELETE_GET_ENROLLED_IDS,
|
||||||
|
DELETE_DELETE,
|
||||||
|
DELETE_STATES,
|
||||||
|
} DeleteStates;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
CANCEL_SENSOR_RESET,
|
||||||
|
CANCEL_SEND_CANCEL,
|
||||||
|
CANCEL_SEND_CANCEL_RESULT,
|
||||||
|
CANCEL_STATES,
|
||||||
|
} CancelStates;
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,196 @@
|
|||||||
|
/*
|
||||||
|
* Driver for Egis Technology (LighTuning) Match-On-Chip sensors
|
||||||
|
* Originally authored 2023 by Joshua Grisham <josh@joshuagrisham.com>
|
||||||
|
*
|
||||||
|
* Portions of code and logic inspired from the elanmoc libfprint driver
|
||||||
|
* which is copyright (C) 2021 Elan Microelectronics Inc (see elanmoc.c)
|
||||||
|
*
|
||||||
|
* Based on original reverse-engineering work by Joshua Grisham. The protocol has
|
||||||
|
* been reverse-engineered from captures of the official Windows driver, and by
|
||||||
|
* testing commands on the sensor with a multiplatform Python prototype driver:
|
||||||
|
* https://github.com/joshuagrisham/galaxy-book2-pro-linux/tree/main/fingerprint/
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "fpi-device.h"
|
||||||
|
#include "fpi-ssm.h"
|
||||||
|
|
||||||
|
G_DECLARE_FINAL_TYPE (FpiDeviceEgisMoc, fpi_device_egismoc, FPI, DEVICE_EGISMOC, FpDevice)
|
||||||
|
|
||||||
|
#define EGISMOC_DRIVER_FULLNAME "Egis Technology (LighTuning) Match-on-Chip"
|
||||||
|
|
||||||
|
#define EGISMOC_DRIVER_CHECK_PREFIX_TYPE1 (1 << 0)
|
||||||
|
#define EGISMOC_DRIVER_CHECK_PREFIX_TYPE2 (1 << 1)
|
||||||
|
#define EGISMOC_DRIVER_MAX_ENROLL_STAGES_20 (1 << 2)
|
||||||
|
|
||||||
|
#define EGISMOC_EP_CMD_OUT (0x02 | FPI_USB_ENDPOINT_OUT)
|
||||||
|
#define EGISMOC_EP_CMD_IN (0x81 | FPI_USB_ENDPOINT_IN)
|
||||||
|
#define EGISMOC_EP_CMD_INTERRUPT_IN 0x83
|
||||||
|
|
||||||
|
#define EGISMOC_USB_CONTROL_TIMEOUT 5000
|
||||||
|
#define EGISMOC_USB_SEND_TIMEOUT 5000
|
||||||
|
#define EGISMOC_USB_RECV_TIMEOUT 5000
|
||||||
|
#define EGISMOC_USB_INTERRUPT_TIMEOUT 60000
|
||||||
|
|
||||||
|
#define EGISMOC_USB_IN_RECV_LENGTH 4096
|
||||||
|
#define EGISMOC_USB_INTERRUPT_IN_RECV_LENGTH 64
|
||||||
|
|
||||||
|
#define EGISMOC_MAX_ENROLL_STAGES_DEFAULT 10
|
||||||
|
#define EGISMOC_MAX_ENROLL_NUM 10
|
||||||
|
#define EGISMOC_FINGERPRINT_DATA_SIZE 32
|
||||||
|
#define EGISMOC_LIST_RESPONSE_PREFIX_SIZE 14
|
||||||
|
#define EGISMOC_LIST_RESPONSE_SUFFIX_SIZE 2
|
||||||
|
|
||||||
|
/* standard prefixes for all read/writes */
|
||||||
|
|
||||||
|
static guchar egismoc_write_prefix[] = {'E', 'G', 'I', 'S', 0x00, 0x00, 0x00, 0x01};
|
||||||
|
|
||||||
|
static guchar egismoc_read_prefix[] = {'S', 'I', 'G', 'E', 0x00, 0x00, 0x00, 0x01};
|
||||||
|
|
||||||
|
|
||||||
|
/* hard-coded command payloads */
|
||||||
|
|
||||||
|
static guchar cmd_fw_version[] = {0x00, 0x00, 0x00, 0x07, 0x50, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x0c};
|
||||||
|
static guchar rsp_fw_version_suffix[] = {0x90, 0x00};
|
||||||
|
|
||||||
|
static guchar cmd_list[] = {0x00, 0x00, 0x00, 0x07, 0x50, 0x19, 0x04, 0x00, 0x00, 0x01, 0x40};
|
||||||
|
|
||||||
|
static guchar cmd_sensor_reset[] = {0x00, 0x00, 0x00, 0x04, 0x50, 0x1a, 0x00, 0x00};
|
||||||
|
|
||||||
|
static guchar cmd_sensor_check[] = {0x00, 0x00, 0x00, 0x04, 0x50, 0x17, 0x02, 0x00};
|
||||||
|
|
||||||
|
static guchar cmd_sensor_identify[] = {0x00, 0x00, 0x00, 0x04, 0x50, 0x17, 0x01, 0x01};
|
||||||
|
static guchar rsp_identify_match_suffix[] = {0x90, 0x00};
|
||||||
|
static guchar rsp_identify_notmatch_suffix[] = {0x90, 0x04};
|
||||||
|
|
||||||
|
static guchar cmd_sensor_enroll[] = {0x00, 0x00, 0x00, 0x04, 0x50, 0x17, 0x01, 0x00};
|
||||||
|
|
||||||
|
static guchar cmd_enroll_starting[] = {0x00, 0x00, 0x00, 0x07, 0x50, 0x16, 0x01, 0x00, 0x00, 0x00, 0x20};
|
||||||
|
|
||||||
|
static guchar cmd_sensor_start_capture[] = {0x00, 0x00, 0x00, 0x04, 0x50, 0x16, 0x02, 0x01};
|
||||||
|
|
||||||
|
static guchar cmd_read_capture[] = {0x00, 0x00, 0x00, 0x07, 0x50, 0x16, 0x02, 0x02, 0x00, 0x00, 0x02};
|
||||||
|
static guchar rsp_read_success_prefix[] = {0x00, 0x00, 0x00, 0x04};
|
||||||
|
static guchar rsp_read_success_suffix[] = {0x90, 0x00};
|
||||||
|
static guchar rsp_read_offcenter_prefix[] = {0x00, 0x00, 0x00, 0x04};
|
||||||
|
static guchar rsp_read_offcenter_suffix[] = {0x64, 0x91};
|
||||||
|
static guchar rsp_read_dirty_prefix[] = {0x00, 0x00, 0x00, 0x02, 0x64};
|
||||||
|
|
||||||
|
static guchar cmd_commit_starting[] = {0x00, 0x00, 0x00, 0x07, 0x50, 0x16, 0x05, 0x00, 0x00, 0x00, 0x20};
|
||||||
|
|
||||||
|
|
||||||
|
/* commands which exist on the device but are currently not used */
|
||||||
|
/*
|
||||||
|
static guchar cmd_sensor_cancel[] = {0x00, 0x00, 0x00, 0x04, 0x50, 0x16, 0x04, 0x00};
|
||||||
|
static gsize cmd_sensor_cancel_len = sizeof(cmd_sensor_cancel) / sizeof(cmd_sensor_cancel[0]);
|
||||||
|
|
||||||
|
static guchar cmd_sensor_verify[] = {0x00, 0x00, 0x00, 0x04, 0x50, 0x04, 0x01, 0x00};
|
||||||
|
static gsize cmd_sensor_verify_len = sizeof(cmd_sensor_verify) / sizeof(cmd_sensor_verify[0]);
|
||||||
|
|
||||||
|
static guchar cmd_read_verify[] = {0x00, 0x00, 0x00, 0x04, 0x50, 0x04, 0x02, 0x00};
|
||||||
|
static gsize cmd_read_verify_len = sizeof(cmd_read_verify) / sizeof(cmd_read_verify[0]);
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/* prefixes/suffixes and other things for dynamically created command payloads */
|
||||||
|
|
||||||
|
#define EGISMOC_CHECK_BYTES_LENGTH 2
|
||||||
|
#define EGISMOC_IDENTIFY_RESPONSE_PRINT_ID_OFFSET 46
|
||||||
|
#define EGISMOC_CMD_CHECK_SEPARATOR_LENGTH 32
|
||||||
|
|
||||||
|
static guchar cmd_new_print_prefix[] = {0x00, 0x00, 0x00, 0x27, 0x50, 0x16, 0x03, 0x00, 0x00, 0x00, 0x20};
|
||||||
|
|
||||||
|
static guchar cmd_delete_prefix[] = {0x50, 0x18, 0x04, 0x00, 0x00};
|
||||||
|
static guchar rsp_delete_success_prefix[] = {0x00, 0x00, 0x00, 0x02, 0x90, 0x00};
|
||||||
|
|
||||||
|
static guchar cmd_check_prefix_type1[] = {0x50, 0x17, 0x03, 0x00, 0x00};
|
||||||
|
static guchar cmd_check_prefix_type2[] = {0x50, 0x17, 0x03, 0x80, 0x00};
|
||||||
|
static guchar cmd_check_suffix[] = {0x00, 0x40};
|
||||||
|
static guchar rsp_check_not_yet_enrolled_suffix[] = {0x90, 0x04};
|
||||||
|
|
||||||
|
|
||||||
|
/* SSM task states and various status enums */
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
CMD_SEND,
|
||||||
|
CMD_GET,
|
||||||
|
CMD_STATES,
|
||||||
|
} CommandStates;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
DEV_INIT_CONTROL1,
|
||||||
|
DEV_INIT_CONTROL2,
|
||||||
|
DEV_INIT_CONTROL3,
|
||||||
|
DEV_INIT_CONTROL4,
|
||||||
|
DEV_INIT_CONTROL5,
|
||||||
|
DEV_GET_FW_VERSION,
|
||||||
|
DEV_INIT_STATES,
|
||||||
|
} DeviceInitStates;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
IDENTIFY_GET_ENROLLED_IDS,
|
||||||
|
IDENTIFY_CHECK_ENROLLED_NUM,
|
||||||
|
IDENTIFY_SENSOR_RESET,
|
||||||
|
IDENTIFY_SENSOR_IDENTIFY,
|
||||||
|
IDENTIFY_WAIT_FINGER,
|
||||||
|
IDENTIFY_SENSOR_CHECK,
|
||||||
|
IDENTIFY_CHECK,
|
||||||
|
IDENTIFY_COMPLETE_SENSOR_RESET,
|
||||||
|
IDENTIFY_COMPLETE,
|
||||||
|
IDENTIFY_STATES,
|
||||||
|
} IdentifyStates;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
ENROLL_GET_ENROLLED_IDS,
|
||||||
|
ENROLL_CHECK_ENROLLED_NUM,
|
||||||
|
ENROLL_SENSOR_RESET,
|
||||||
|
ENROLL_SENSOR_ENROLL,
|
||||||
|
ENROLL_WAIT_FINGER,
|
||||||
|
ENROLL_SENSOR_CHECK,
|
||||||
|
ENROLL_CHECK,
|
||||||
|
ENROLL_START,
|
||||||
|
ENROLL_CAPTURE_SENSOR_RESET,
|
||||||
|
ENROLL_CAPTURE_SENSOR_START_CAPTURE,
|
||||||
|
ENROLL_CAPTURE_WAIT_FINGER,
|
||||||
|
ENROLL_CAPTURE_READ_RESPONSE,
|
||||||
|
ENROLL_COMMIT_START,
|
||||||
|
ENROLL_COMMIT,
|
||||||
|
ENROLL_COMMIT_SENSOR_RESET,
|
||||||
|
ENROLL_COMPLETE,
|
||||||
|
ENROLL_STATES,
|
||||||
|
} EnrollStates;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
ENROLL_STATUS_DEVICE_FULL,
|
||||||
|
ENROLL_STATUS_DUPLICATE,
|
||||||
|
ENROLL_STATUS_PARTIAL_OK,
|
||||||
|
ENROLL_STATUS_RETRY,
|
||||||
|
ENROLL_STATUS_COMPLETE,
|
||||||
|
} EnrollStatus;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
LIST_GET_ENROLLED_IDS,
|
||||||
|
LIST_RETURN_ENROLLED_PRINTS,
|
||||||
|
LIST_STATES,
|
||||||
|
} ListStates;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
DELETE_GET_ENROLLED_IDS,
|
||||||
|
DELETE_DELETE,
|
||||||
|
DELETE_STATES,
|
||||||
|
} DeleteStates;
|
||||||
@@ -146,7 +146,7 @@ elan_save_frame (FpiDeviceElan *self, unsigned short *frame)
|
|||||||
raw_idx = frame_margin + y + x * raw_height;
|
raw_idx = frame_margin + y + x * raw_height;
|
||||||
frame_idx = x + y * frame_width;
|
frame_idx = x + y * frame_width;
|
||||||
frame[frame_idx] =
|
frame[frame_idx] =
|
||||||
((unsigned short *) self->last_read)[raw_idx];
|
GUINT16_FROM_LE (((unsigned short *) self->last_read)[raw_idx]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -251,7 +251,12 @@ elan_process_frame_linear (unsigned short *raw_frame,
|
|||||||
max = raw_frame[i];
|
max = raw_frame[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
g_assert (max != min);
|
if (max == min)
|
||||||
|
{
|
||||||
|
memset (frame->data, 0, frame_size);
|
||||||
|
*frames = g_slist_prepend (*frames, frame);
|
||||||
|
g_return_if_reached ();
|
||||||
|
}
|
||||||
|
|
||||||
unsigned short px;
|
unsigned short px;
|
||||||
|
|
||||||
@@ -287,6 +292,11 @@ elan_process_frame_thirds (unsigned short *raw_frame,
|
|||||||
lvl3 = sorted[frame_size - 1];
|
lvl3 = sorted[frame_size - 1];
|
||||||
g_free (sorted);
|
g_free (sorted);
|
||||||
|
|
||||||
|
/* Ensure levels are strictly monotonic to prevent division by zero */
|
||||||
|
lvl1 = MAX (lvl1, lvl0 + 1);
|
||||||
|
lvl2 = MAX (lvl2, lvl1 + 1);
|
||||||
|
lvl3 = MAX (lvl3, lvl2 + 1);
|
||||||
|
|
||||||
unsigned short px;
|
unsigned short px;
|
||||||
|
|
||||||
for (int i = 0; i < frame_size; i++)
|
for (int i = 0; i < frame_size; i++)
|
||||||
@@ -357,7 +367,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_memdup (transfer->buffer, transfer->actual_length);
|
self->last_read = g_memdup2 (transfer->buffer, transfer->actual_length);
|
||||||
elan_cmd_done (ssm);
|
elan_cmd_done (ssm);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -547,10 +557,17 @@ capture_run_state (FpiSsm *ssm, FpDevice *dev)
|
|||||||
fpi_image_device_report_finger_status (idev, TRUE);
|
fpi_image_device_report_finger_status (idev, TRUE);
|
||||||
elan_run_cmd (ssm, dev, &get_image_cmd, ELAN_CMD_TIMEOUT);
|
elan_run_cmd (ssm, dev, &get_image_cmd, ELAN_CMD_TIMEOUT);
|
||||||
}
|
}
|
||||||
|
else if (self->dev_type == ELAN_0C58 && self->last_read &&
|
||||||
|
(self->last_read[0] == 0x00 || self->last_read[0] == 0xaf))
|
||||||
|
{
|
||||||
|
/* 0x00 - not ready
|
||||||
|
* 0xaf - finger removed or sensor busy (seen on 0x0c58) */
|
||||||
|
fpi_ssm_jump_to_state_delayed (ssm, CAPTURE_WAIT_FINGER, 10);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* XXX: The timeout is emulated incorrectly, resulting in a zero byte read. */
|
/* XXX: The timeout is emulated incorrectly, resulting in a zero byte read. */
|
||||||
if (g_strcmp0 (g_getenv ("FP_DEVICE_EMULATION"), "1") == 0)
|
if (fpi_device_emulation_mode_enabled (FP_DEVICE (self)))
|
||||||
fpi_ssm_mark_completed (ssm);
|
fpi_ssm_mark_completed (ssm);
|
||||||
else
|
else
|
||||||
fpi_ssm_mark_failed (ssm, fpi_device_error_new (FP_DEVICE_ERROR_PROTO));
|
fpi_ssm_mark_failed (ssm, fpi_device_error_new (FP_DEVICE_ERROR_PROTO));
|
||||||
@@ -795,7 +812,7 @@ elan_calibrate (FpiDeviceElan *self)
|
|||||||
|
|
||||||
g_return_if_fail (!self->active);
|
g_return_if_fail (!self->active);
|
||||||
self->active = TRUE;
|
self->active = TRUE;
|
||||||
self->calib_atts_left = ELAN_CALIBRATION_ATTEMPTS;
|
self->calib_atts_left = ELAN_CALIBRATION_ATTEMPTS (self->dev_type);
|
||||||
|
|
||||||
FpiSsm *ssm = fpi_ssm_new (FP_DEVICE (self), calibrate_run_state,
|
FpiSsm *ssm = fpi_ssm_new (FP_DEVICE (self), calibrate_run_state,
|
||||||
CALIBRATE_NUM_STATES);
|
CALIBRATE_NUM_STATES);
|
||||||
|
|||||||
@@ -31,6 +31,7 @@
|
|||||||
#define ELAN_0907 (1 << 0)
|
#define ELAN_0907 (1 << 0)
|
||||||
#define ELAN_0C03 (1 << 1)
|
#define ELAN_0C03 (1 << 1)
|
||||||
#define ELAN_0C42 (1 << 2)
|
#define ELAN_0C42 (1 << 2)
|
||||||
|
#define ELAN_0C58 (1 << 3)
|
||||||
|
|
||||||
/* devices which don't require frame rotation before assembling */
|
/* devices which don't require frame rotation before assembling */
|
||||||
#define ELAN_NOT_ROTATED ELAN_0C03
|
#define ELAN_NOT_ROTATED ELAN_0C03
|
||||||
@@ -44,7 +45,9 @@
|
|||||||
|
|
||||||
/* times to retry reading calibration status during one session
|
/* times to retry reading calibration status during one session
|
||||||
* generally prevents calibration from looping indefinitely */
|
* generally prevents calibration from looping indefinitely */
|
||||||
#define ELAN_CALIBRATION_ATTEMPTS 10
|
#define ELAN_DEFAULT_CALIBRATION_ATTEMPTS 10
|
||||||
|
#define ELAN_CALIBRATION_ATTEMPTS(dev_type) \
|
||||||
|
((dev_type) == ELAN_0C58 ? 30 : ELAN_DEFAULT_CALIBRATION_ATTEMPTS)
|
||||||
|
|
||||||
/* min and max frames in a capture */
|
/* min and max frames in a capture */
|
||||||
#define ELAN_MIN_FRAMES 7
|
#define ELAN_MIN_FRAMES 7
|
||||||
@@ -220,7 +223,7 @@ static const FpIdEntry elan_id_table[] = {
|
|||||||
{.vid = ELAN_VEND_ID, .pid = 0x0c4f, .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 = 0x0c63, .driver_data = ELAN_ALL_DEV},
|
||||||
{.vid = ELAN_VEND_ID, .pid = 0x0c6e, .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 = ELAN_VEND_ID, .pid = 0x0c58, .driver_data = ELAN_0C58},
|
||||||
{.vid = 0, .pid = 0, .driver_data = 0},
|
{.vid = 0, .pid = 0, .driver_data = 0},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -29,6 +29,18 @@ static const FpIdEntry id_table[] = {
|
|||||||
{ .vid = 0x04f3, .pid = 0x0c7e, },
|
{ .vid = 0x04f3, .pid = 0x0c7e, },
|
||||||
{ .vid = 0x04f3, .pid = 0x0c82, },
|
{ .vid = 0x04f3, .pid = 0x0c82, },
|
||||||
{ .vid = 0x04f3, .pid = 0x0c88, },
|
{ .vid = 0x04f3, .pid = 0x0c88, },
|
||||||
|
{ .vid = 0x04f3, .pid = 0x0c8c, },
|
||||||
|
{ .vid = 0x04f3, .pid = 0x0c8d, },
|
||||||
|
{ .vid = 0x04f3, .pid = 0x0c98, },
|
||||||
|
{ .vid = 0x04f3, .pid = 0x0c99, },
|
||||||
|
{ .vid = 0x04f3, .pid = 0x0c9c, },
|
||||||
|
{ .vid = 0x04f3, .pid = 0x0c9d, },
|
||||||
|
{ .vid = 0x04f3, .pid = 0x0c9f, },
|
||||||
|
{ .vid = 0x04f3, .pid = 0x0ca3, },
|
||||||
|
{ .vid = 0x04f3, .pid = 0x0ca7, },
|
||||||
|
{ .vid = 0x04f3, .pid = 0x0ca8, },
|
||||||
|
{ .vid = 0x04f3, .pid = 0x0cb0, },
|
||||||
|
{ .vid = 0x04f3, .pid = 0x0cb2, },
|
||||||
{ .vid = 0, .pid = 0, .driver_data = 0 }, /* terminating entry */
|
{ .vid = 0, .pid = 0, .driver_data = 0 }, /* terminating entry */
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -47,9 +59,9 @@ elanmoc_compose_cmd (
|
|||||||
const struct elanmoc_cmd *cmd_info
|
const struct elanmoc_cmd *cmd_info
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
g_autofree char *cmd_buf = NULL;
|
g_autofree uint8_t *cmd_buf = NULL;
|
||||||
|
|
||||||
cmd_buf = g_malloc0 (cmd_info->cmd_len);
|
cmd_buf = g_new0 (uint8_t, cmd_info->cmd_len);
|
||||||
if(cmd_info->cmd_len < ELAN_MAX_HDR_LEN)
|
if(cmd_info->cmd_len < ELAN_MAX_HDR_LEN)
|
||||||
memcpy (cmd_buf, &cmd_info->cmd_header, cmd_info->cmd_len);
|
memcpy (cmd_buf, &cmd_info->cmd_header, cmd_info->cmd_len);
|
||||||
else
|
else
|
||||||
@@ -125,10 +137,10 @@ fp_cmd_receive_cb (FpiUsbTransfer *transfer,
|
|||||||
}
|
}
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
FP_CMD_SEND = 0,
|
ELAN_MOC_CMD_SEND = 0,
|
||||||
FP_CMD_GET,
|
ELAN_MOC_CMD_GET,
|
||||||
FP_CMD_NUM_STATES,
|
ELAN_MOC_CMD_NUM_STATES,
|
||||||
} FpCmdState;
|
} ElanMocCmdState;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
fp_cmd_run_state (FpiSsm *ssm,
|
fp_cmd_run_state (FpiSsm *ssm,
|
||||||
@@ -139,7 +151,7 @@ fp_cmd_run_state (FpiSsm *ssm,
|
|||||||
|
|
||||||
switch (fpi_ssm_get_cur_state (ssm))
|
switch (fpi_ssm_get_cur_state (ssm))
|
||||||
{
|
{
|
||||||
case FP_CMD_SEND:
|
case ELAN_MOC_CMD_SEND:
|
||||||
if (self->cmd_transfer)
|
if (self->cmd_transfer)
|
||||||
{
|
{
|
||||||
self->cmd_transfer->ssm = ssm;
|
self->cmd_transfer->ssm = ssm;
|
||||||
@@ -155,7 +167,7 @@ fp_cmd_run_state (FpiSsm *ssm,
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FP_CMD_GET:
|
case ELAN_MOC_CMD_GET:
|
||||||
if (self->cmd_len_in == 0)
|
if (self->cmd_len_in == 0)
|
||||||
{
|
{
|
||||||
CommandData *data = fpi_ssm_get_data (ssm);
|
CommandData *data = fpi_ssm_get_data (ssm);
|
||||||
@@ -222,7 +234,7 @@ elanmoc_get_cmd (FpDevice *device, guint8 *buffer_out,
|
|||||||
|
|
||||||
self->cmd_ssm = fpi_ssm_new (FP_DEVICE (self),
|
self->cmd_ssm = fpi_ssm_new (FP_DEVICE (self),
|
||||||
fp_cmd_run_state,
|
fp_cmd_run_state,
|
||||||
FP_CMD_NUM_STATES);
|
ELAN_MOC_CMD_NUM_STATES);
|
||||||
|
|
||||||
fpi_ssm_set_data (self->cmd_ssm, data, (GDestroyNotify) fp_cmd_ssm_done_data_free);
|
fpi_ssm_set_data (self->cmd_ssm, data, (GDestroyNotify) fp_cmd_ssm_done_data_free);
|
||||||
|
|
||||||
@@ -377,12 +389,21 @@ elanmoc_enroll_cb (FpiDeviceElanmoc *self,
|
|||||||
enroll_status_report (self, ENROLL_RSP_RETRY, self->num_frames, NULL);
|
enroll_status_report (self, ENROLL_RSP_RETRY, self->num_frames, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (self->num_frames == ELAN_MOC_ENROLL_TIMES && buffer_in[1] == ELAN_MSG_OK)
|
if (self->num_frames == self->max_moc_enroll_time && buffer_in[1] == ELAN_MSG_OK)
|
||||||
fpi_ssm_next_state (self->task_ssm);
|
{
|
||||||
else if (self->num_frames < ELAN_MOC_ENROLL_TIMES)
|
fpi_ssm_next_state (self->task_ssm);
|
||||||
fpi_ssm_jump_to_state (self->task_ssm, MOC_ENROLL_WAIT_FINGER);
|
}
|
||||||
|
else if (self->num_frames < self->max_moc_enroll_time)
|
||||||
|
{
|
||||||
|
fpi_ssm_jump_to_state (self->task_ssm, MOC_ENROLL_WAIT_FINGER);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
fpi_ssm_mark_failed (self->task_ssm, error);
|
{
|
||||||
|
fpi_ssm_mark_failed (self->task_ssm,
|
||||||
|
fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
|
||||||
|
"Enrollment failed (status 0x%02x)",
|
||||||
|
buffer_in[1]));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -442,7 +463,7 @@ elan_enroll_run_state (FpiSsm *ssm, FpDevice *dev)
|
|||||||
case MOC_ENROLL_WAIT_FINGER:
|
case MOC_ENROLL_WAIT_FINGER:
|
||||||
cmd_buf = elanmoc_compose_cmd (&elanmoc_enroll_cmd);
|
cmd_buf = elanmoc_compose_cmd (&elanmoc_enroll_cmd);
|
||||||
cmd_buf[3] = self->curr_enrolled;
|
cmd_buf[3] = self->curr_enrolled;
|
||||||
cmd_buf[4] = ELAN_MOC_ENROLL_TIMES;
|
cmd_buf[4] = self->max_moc_enroll_time;
|
||||||
cmd_buf[5] = self->num_frames;
|
cmd_buf[5] = self->num_frames;
|
||||||
elanmoc_get_cmd (dev, cmd_buf, elanmoc_enroll_cmd.cmd_len, elanmoc_enroll_cmd.resp_len, 1, elanmoc_enroll_cb);
|
elanmoc_get_cmd (dev, cmd_buf, elanmoc_enroll_cmd.cmd_len, elanmoc_enroll_cmd.resp_len, 1, elanmoc_enroll_cb);
|
||||||
break;
|
break;
|
||||||
@@ -507,7 +528,7 @@ create_print_from_response (FpiDeviceElanmoc *self,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
userid = g_memdup (&buffer_in[5], userid_len);
|
userid = g_memdup2 (&buffer_in[5], userid_len);
|
||||||
userid_safe = g_strndup ((const char *) &buffer_in[5], userid_len);
|
userid_safe = g_strndup ((const char *) &buffer_in[5], userid_len);
|
||||||
print = fp_print_new (FP_DEVICE (self));
|
print = fp_print_new (FP_DEVICE (self));
|
||||||
uid = g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE, userid, userid_len, 1);
|
uid = g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE, userid, userid_len, 1);
|
||||||
@@ -627,7 +648,6 @@ elanmoc_match_report_cb (FpiDeviceElanmoc *self,
|
|||||||
{
|
{
|
||||||
FpDevice *device = FP_DEVICE (self);
|
FpDevice *device = FP_DEVICE (self);
|
||||||
FpPrint *print = NULL;
|
FpPrint *print = NULL;
|
||||||
FpPrint *verify_print = NULL;
|
|
||||||
GPtrArray *prints;
|
GPtrArray *prints;
|
||||||
gboolean found = FALSE;
|
gboolean found = FALSE;
|
||||||
guint index;
|
guint index;
|
||||||
@@ -656,31 +676,18 @@ elanmoc_match_report_cb (FpiDeviceElanmoc *self,
|
|||||||
|
|
||||||
fp_info ("Verify/Identify successful for: %s", fp_print_get_description (print));
|
fp_info ("Verify/Identify successful for: %s", fp_print_get_description (print));
|
||||||
|
|
||||||
if (fpi_device_get_current_action (device) == FPI_DEVICE_ACTION_IDENTIFY)
|
fpi_device_get_identify_data (device, &prints);
|
||||||
{
|
found = g_ptr_array_find_with_equal_func (prints,
|
||||||
fpi_device_get_identify_data (device, &prints);
|
print,
|
||||||
found = g_ptr_array_find_with_equal_func (prints,
|
(GEqualFunc) fp_print_equal,
|
||||||
print,
|
&index);
|
||||||
(GEqualFunc) fp_print_equal,
|
|
||||||
&index);
|
|
||||||
|
|
||||||
if (found)
|
if (found)
|
||||||
fpi_device_identify_report (device, g_ptr_array_index (prints, index), print, NULL);
|
fpi_device_identify_report (device, g_ptr_array_index (prints, index), print, NULL);
|
||||||
else
|
|
||||||
fpi_device_identify_report (device, NULL, print, NULL);
|
|
||||||
|
|
||||||
fpi_device_identify_complete (device, NULL);
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
fpi_device_identify_report (device, NULL, print, NULL);
|
||||||
fpi_device_get_verify_data (device, &verify_print);
|
|
||||||
|
|
||||||
if (fp_print_equal (verify_print, print))
|
fpi_device_identify_complete (device, NULL);
|
||||||
fpi_device_verify_report (device, FPI_MATCH_SUCCESS, print, NULL);
|
|
||||||
else
|
|
||||||
fpi_device_verify_report (device, FPI_MATCH_FAIL, print, NULL);
|
|
||||||
fpi_device_verify_complete (device, NULL);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -692,10 +699,7 @@ identify_status_report (FpiDeviceElanmoc *self, int verify_status_id,
|
|||||||
|
|
||||||
if (error)
|
if (error)
|
||||||
{
|
{
|
||||||
if (fpi_device_get_current_action (device) == FPI_DEVICE_ACTION_VERIFY)
|
fpi_device_identify_complete (device, error);
|
||||||
fpi_device_verify_complete (device, error);
|
|
||||||
else
|
|
||||||
fpi_device_identify_complete (device, error);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -705,16 +709,8 @@ identify_status_report (FpiDeviceElanmoc *self, int verify_status_id,
|
|||||||
{
|
{
|
||||||
if (data == ELAN_MSG_VERIFY_ERR)
|
if (data == ELAN_MSG_VERIFY_ERR)
|
||||||
{
|
{
|
||||||
if (fpi_device_get_current_action (device) == FPI_DEVICE_ACTION_VERIFY)
|
fpi_device_identify_report (device, NULL, NULL, NULL);
|
||||||
{
|
fpi_device_identify_complete (device, NULL);
|
||||||
fpi_device_verify_report (device, FPI_MATCH_FAIL, NULL, NULL);
|
|
||||||
fpi_device_verify_complete (device, NULL);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
fpi_device_identify_report (device, NULL, NULL, NULL);
|
|
||||||
fpi_device_identify_complete (device, NULL);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -733,23 +729,15 @@ identify_status_report (FpiDeviceElanmoc *self, int verify_status_id,
|
|||||||
retry_error = fpi_device_retry_new (FP_DEVICE_RETRY_GENERAL);
|
retry_error = fpi_device_retry_new (FP_DEVICE_RETRY_GENERAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fpi_device_get_current_action (device) == FPI_DEVICE_ACTION_VERIFY)
|
fpi_device_identify_report (device, NULL, NULL, retry_error);
|
||||||
{
|
fpi_device_identify_complete (device, NULL);
|
||||||
fpi_device_verify_report (device, FPI_MATCH_ERROR, NULL, retry_error);
|
|
||||||
fpi_device_verify_complete (device, NULL);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
fpi_device_identify_report (device, NULL, NULL, retry_error);
|
|
||||||
fpi_device_identify_complete (device, NULL);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case RSP_VERIFY_OK:
|
case RSP_VERIFY_OK:
|
||||||
{
|
{
|
||||||
fp_dbg ("Verify was successful! for user: %d mesg_code: %d ", data, verify_status_id);
|
fp_dbg ("Identify was successful! for user: %d mesg_code: %d ", data, verify_status_id);
|
||||||
cmd_buf = elanmoc_compose_cmd (&elanmoc_get_userid_cmd);
|
cmd_buf = elanmoc_compose_cmd (&elanmoc_get_userid_cmd);
|
||||||
cmd_buf[2] = data;
|
cmd_buf[2] = data;
|
||||||
elanmoc_get_cmd (device, cmd_buf, elanmoc_get_userid_cmd.cmd_len, elanmoc_get_userid_cmd.resp_len, 0, elanmoc_match_report_cb);
|
elanmoc_get_cmd (device, cmd_buf, elanmoc_get_userid_cmd.cmd_len, elanmoc_get_userid_cmd.resp_len, 0, elanmoc_match_report_cb);
|
||||||
@@ -803,7 +791,7 @@ elan_identify_run_state (FpiSsm *ssm, FpDevice *dev)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case IDENTIFY_WAIT_FINGER:
|
case IDENTIFY_WAIT_FINGER:
|
||||||
fp_info ("elanmoc %s VERIFY_WAIT_FINGER", __func__);
|
fp_info ("elanmoc %s IDENTIFY_WAIT_FINGER", __func__);
|
||||||
cmd_buf = elanmoc_compose_cmd (&elanmoc_verify_cmd);
|
cmd_buf = elanmoc_compose_cmd (&elanmoc_verify_cmd);
|
||||||
elanmoc_get_cmd (dev, cmd_buf, elanmoc_verify_cmd.cmd_len, elanmoc_verify_cmd.resp_len, 1, elanmoc_identify_cb);
|
elanmoc_get_cmd (dev, cmd_buf, elanmoc_verify_cmd.cmd_len, elanmoc_verify_cmd.resp_len, 1, elanmoc_identify_cb);
|
||||||
break;
|
break;
|
||||||
@@ -1008,6 +996,12 @@ elanmoc_get_status_cb (FpiDeviceElanmoc *self,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (buffer_in[1] != 0x03 && self->cmd_retry_cnt != 0)
|
if (buffer_in[1] != 0x03 && self->cmd_retry_cnt != 0)
|
||||||
|
{
|
||||||
|
self->cmd_retry_cnt--;
|
||||||
|
cmd_buf = elanmoc_compose_cmd (&cal_status_cmd);
|
||||||
|
elanmoc_get_cmd (FP_DEVICE (self), cmd_buf, cal_status_cmd.cmd_len, cal_status_cmd.resp_len, 0, elanmoc_get_status_cb);
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
if(self->cmd_retry_cnt == 0)
|
if(self->cmd_retry_cnt == 0)
|
||||||
{
|
{
|
||||||
@@ -1016,12 +1010,6 @@ elanmoc_get_status_cb (FpiDeviceElanmoc *self,
|
|||||||
"Sensor not ready"));
|
"Sensor not ready"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
self->cmd_retry_cnt--;
|
|
||||||
cmd_buf = elanmoc_compose_cmd (&cal_status_cmd);
|
|
||||||
elanmoc_get_cmd (FP_DEVICE (self), cmd_buf, cal_status_cmd.cmd_len, cal_status_cmd.resp_len, 0, elanmoc_get_status_cb);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
fpi_ssm_next_state (self->task_ssm);
|
fpi_ssm_next_state (self->task_ssm);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1069,6 +1057,7 @@ elanmoc_open (FpDevice *device)
|
|||||||
{
|
{
|
||||||
FpiDeviceElanmoc *self = FPI_DEVICE_ELANMOC (device);
|
FpiDeviceElanmoc *self = FPI_DEVICE_ELANMOC (device);
|
||||||
GError *error = NULL;
|
GError *error = NULL;
|
||||||
|
gint productid = 0;
|
||||||
|
|
||||||
if (!g_usb_device_reset (fpi_device_get_usb_device (device), &error))
|
if (!g_usb_device_reset (fpi_device_get_usb_device (device), &error))
|
||||||
goto error;
|
goto error;
|
||||||
@@ -1076,6 +1065,28 @@ elanmoc_open (FpDevice *device)
|
|||||||
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;
|
||||||
|
|
||||||
|
productid = g_usb_device_get_pid (fpi_device_get_usb_device (device));
|
||||||
|
switch (productid)
|
||||||
|
{
|
||||||
|
case 0x0c8c:
|
||||||
|
self->max_moc_enroll_time = 11;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x0c99:
|
||||||
|
self->max_moc_enroll_time = 14;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x0c8d:
|
||||||
|
self->max_moc_enroll_time = 17;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
self->max_moc_enroll_time = ELAN_MOC_ENROLL_TIMES;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
fpi_device_set_nr_enroll_stages (device, self->max_moc_enroll_time);
|
||||||
|
|
||||||
self->task_ssm = fpi_ssm_new (FP_DEVICE (self), dev_init_handler, DEV_INIT_STATES);
|
self->task_ssm = fpi_ssm_new (FP_DEVICE (self), dev_init_handler, DEV_INIT_STATES);
|
||||||
fpi_ssm_start (self->task_ssm, task_ssm_init_done);
|
fpi_ssm_start (self->task_ssm, task_ssm_init_done);
|
||||||
return;
|
return;
|
||||||
@@ -1140,7 +1151,6 @@ fpi_device_elanmoc_class_init (FpiDeviceElanmocClass *klass)
|
|||||||
|
|
||||||
dev_class->open = elanmoc_open;
|
dev_class->open = elanmoc_open;
|
||||||
dev_class->close = elanmoc_close;
|
dev_class->close = elanmoc_close;
|
||||||
dev_class->verify = elanmoc_identify;
|
|
||||||
dev_class->enroll = elanmoc_enroll;
|
dev_class->enroll = elanmoc_enroll;
|
||||||
dev_class->identify = elanmoc_identify;
|
dev_class->identify = elanmoc_identify;
|
||||||
dev_class->delete = elanmoc_delete_print;
|
dev_class->delete = elanmoc_delete_print;
|
||||||
|
|||||||
@@ -188,6 +188,7 @@ struct _FpiDeviceElanmoc
|
|||||||
unsigned char y_trace;
|
unsigned char y_trace;
|
||||||
int num_frames;
|
int num_frames;
|
||||||
int curr_enrolled;
|
int curr_enrolled;
|
||||||
|
int max_moc_enroll_time;
|
||||||
int cancel_result;
|
int cancel_result;
|
||||||
int cmd_retry_cnt;
|
int cmd_retry_cnt;
|
||||||
int list_index;
|
int list_index;
|
||||||
|
|||||||
@@ -23,9 +23,9 @@
|
|||||||
#include "drivers_api.h"
|
#include "drivers_api.h"
|
||||||
#include "elanspi.h"
|
#include "elanspi.h"
|
||||||
|
|
||||||
|
#include <fcntl.h>
|
||||||
#include <linux/hidraw.h>
|
#include <linux/hidraw.h>
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
#include <sys/fcntl.h>
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
@@ -94,7 +94,7 @@ static void
|
|||||||
elanspi_do_hwreset (FpiDeviceElanSpi *self, GError **err)
|
elanspi_do_hwreset (FpiDeviceElanSpi *self, GError **err)
|
||||||
{
|
{
|
||||||
/* Skip in emulation mode, since we don't mock hid devices */
|
/* Skip in emulation mode, since we don't mock hid devices */
|
||||||
if (g_strcmp0 (g_getenv ("FP_DEVICE_EMULATION"), "1") == 0)
|
if (fpi_device_emulation_mode_enabled (FP_DEVICE (self)))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -485,7 +485,8 @@ elanspi_capture_old_handler (FpiSsm *ssm, FpDevice *dev)
|
|||||||
if (!(self->sensor_status & 4))
|
if (!(self->sensor_status & 4))
|
||||||
{
|
{
|
||||||
/* has the timeout expired? -- disabled in testing since valgrind is very slow */
|
/* has the timeout expired? -- disabled in testing since valgrind is very slow */
|
||||||
if (g_get_monotonic_time () > self->capture_timeout && g_strcmp0 (g_getenv ("FP_DEVICE_EMULATION"), "1") != 0)
|
if (g_get_monotonic_time () > self->capture_timeout &&
|
||||||
|
!fpi_device_emulation_mode_enabled (FP_DEVICE (self)))
|
||||||
{
|
{
|
||||||
/* end with a timeout */
|
/* end with a timeout */
|
||||||
fpi_ssm_mark_failed (ssm, g_error_new (G_IO_ERROR, G_IO_ERROR_TIMED_OUT, "timed out waiting for new line"));
|
fpi_ssm_mark_failed (ssm, g_error_new (G_IO_ERROR, G_IO_ERROR_TIMED_OUT, "timed out waiting for new line"));
|
||||||
|
|||||||
@@ -340,9 +340,11 @@ static const struct elanspi_regtable elanspi_calibration_table_new_page1 = {
|
|||||||
|
|
||||||
// using checkargs ACPI:HIDPID
|
// using checkargs ACPI:HIDPID
|
||||||
static const FpIdEntry elanspi_id_table[] = {
|
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 = 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 = 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 = 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 = "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 = 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 = "ELAN7001", .hid_id = {.vid = ELANSPI_TP_VID, .pid = 0x30b2}, .driver_data = ELANSPI_NO_ROTATE},
|
||||||
|
|||||||
@@ -338,7 +338,14 @@ msg_parse_regs (FpiDeviceEtes603 *dev)
|
|||||||
struct egis_msg *msg_req = dev->req;
|
struct egis_msg *msg_req = dev->req;
|
||||||
struct egis_msg *msg_ans = dev->ans;
|
struct egis_msg *msg_ans = dev->ans;
|
||||||
|
|
||||||
|
g_return_val_if_fail (dev->ans_len >= MSG_HDR_SIZE, -1);
|
||||||
|
|
||||||
n_args = dev->ans_len - MSG_HDR_SIZE;
|
n_args = dev->ans_len - MSG_HDR_SIZE;
|
||||||
|
if (n_args > REG_MAX)
|
||||||
|
{
|
||||||
|
g_warn_if_reached ();
|
||||||
|
n_args = REG_MAX;
|
||||||
|
}
|
||||||
|
|
||||||
if (msg_header_check (msg_ans))
|
if (msg_header_check (msg_ans))
|
||||||
return -1;
|
return -1;
|
||||||
@@ -575,12 +582,24 @@ static void
|
|||||||
process_removefpi_end (FpiDeviceEtes603 *dev)
|
process_removefpi_end (FpiDeviceEtes603 *dev)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
|
/* Need at least the 2-line empty pattern to compare against. */
|
||||||
|
if (dev->fp_height < 2)
|
||||||
|
g_return_if_reached ();
|
||||||
|
|
||||||
/* 2 last lines with Fly-Estimation are the empty pattern. */
|
/* 2 last lines with Fly-Estimation are the empty pattern. */
|
||||||
guint8 *pattern = dev->fp + (dev->fp_height - 2) * FE_WIDTH / 2;
|
guint8 *pattern = dev->fp + (dev->fp_height - 2) * FE_WIDTH / 2;
|
||||||
|
|
||||||
for (i = 2; i < dev->fp_height; i += 2)
|
for (i = 2; i < dev->fp_height; i += 2)
|
||||||
if (memcmp (pattern, pattern - (i * FE_WIDTH / 2), FE_WIDTH))
|
if (memcmp (pattern, pattern - (i * FE_WIDTH / 2), FE_WIDTH))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
if (i > dev->fp_height)
|
||||||
|
{
|
||||||
|
g_warn_if_reached ();
|
||||||
|
i = dev->fp_height;
|
||||||
|
}
|
||||||
|
|
||||||
dev->fp_height -= i;
|
dev->fp_height -= i;
|
||||||
fp_dbg ("Removing %d empty lines from image", i - 2);
|
fp_dbg ("Removing %d empty lines from image", i - 2);
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,52 @@
|
|||||||
|
/*
|
||||||
|
* 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
@@ -0,0 +1,221 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2022 Fingerprint Cards AB <tech@fingerprints.com>
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "fpi-device.h"
|
||||||
|
#include "fpi-ssm.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#define TEMPLATE_ID_SIZE (32)
|
||||||
|
#define MAX_FW_VERSION_STR_LEN (16)
|
||||||
|
#define FPC_CMD_INIT (0x01)
|
||||||
|
#define FPC_CMD_ARM (0x02)
|
||||||
|
#define FPC_CMD_ABORT (0x03)
|
||||||
|
#define FPC_CMD_INDICATE_S_STATE (0x08)
|
||||||
|
#define FPC_CMD_GET_IMG (0x09)
|
||||||
|
#define FPC_CMD_GET_KPI (0x0C)
|
||||||
|
#define FPC_CMD_LOAD_DB (0x60)
|
||||||
|
#define FPC_CMD_STORE_DB (0x61)
|
||||||
|
#define FPC_CMD_DELETE_DB (0x62)
|
||||||
|
#define FPC_CMD_DELETE_TEMPLATE (0x63)
|
||||||
|
#define FPC_CMD_BEGIN_ENROL (0x67)
|
||||||
|
#define FPC_CMD_ENROL (0x68)
|
||||||
|
#define FPC_CMD_END_ENROL (0x69)
|
||||||
|
#define FPC_CMD_BIND_IDENTITY (0x6A)
|
||||||
|
#define FPC_CMD_IDENTIFY (0x6B)
|
||||||
|
#define FPC_CMD_ENUM (0x70)
|
||||||
|
#define FPC_EVT_INIT_RESULT (0x02)
|
||||||
|
#define FPC_EVT_FINGER_DWN (0x06)
|
||||||
|
#define FPC_EVT_IMG (0x08)
|
||||||
|
#define FPC_EVT_FID_DATA (0x31)
|
||||||
|
#define FPC_DB_ID_LEN (16)
|
||||||
|
#define FPC_IDENTITY_TYPE_WILDCARD (0x1)
|
||||||
|
#define FPC_IDENTITY_TYPE_RESERVED (0x3)
|
||||||
|
#define FPC_IDENTITY_WILDCARD (0x25066282)
|
||||||
|
#define FPC_SUBTYPE_ANY (0xFF)
|
||||||
|
#define FPC_SUBTYPE_RESERVED (0xF5)
|
||||||
|
#define FPC_SUBTYPE_NOINFORMATION (0x00)
|
||||||
|
#define FPC_CAPTUREID_RESERVED (0x701100F)
|
||||||
|
#define FPC_SESSIONID_RESERVED (0x0077FF12)
|
||||||
|
#define FPC_TEMPLATES_MAX (10)
|
||||||
|
#define SECURITY_MAX_SID_SIZE (68)
|
||||||
|
#define FPC_HOST_MS_S0 (0x10)
|
||||||
|
#define FPC_HOST_MS_SX (0x11)
|
||||||
|
|
||||||
|
G_DECLARE_FINAL_TYPE (FpiDeviceFpcMoc, fpi_device_fpcmoc, FPI,
|
||||||
|
DEVICE_FPCMOC, FpDevice);
|
||||||
|
|
||||||
|
typedef struct _FPC_FID_DATA
|
||||||
|
{
|
||||||
|
guint32 identity_type;
|
||||||
|
guint32 reserved;
|
||||||
|
guint32 identity_size;
|
||||||
|
guint32 subfactor;
|
||||||
|
guint8 data[SECURITY_MAX_SID_SIZE];
|
||||||
|
} FPC_FID_DATA, *PFPC_FID_DATA;
|
||||||
|
|
||||||
|
typedef struct _FPC_LOAD_DB
|
||||||
|
{
|
||||||
|
gint32 status;
|
||||||
|
guint32 reserved;
|
||||||
|
guint32 database_id_size;
|
||||||
|
guint8 data[FPC_DB_ID_LEN];
|
||||||
|
} FPC_LOAD_DB, *PFPC_LOAD_DB;
|
||||||
|
|
||||||
|
typedef union _FPC_DELETE_DB
|
||||||
|
{
|
||||||
|
guint32 reserved;
|
||||||
|
guint32 database_id_size;
|
||||||
|
guint8 data[FPC_DB_ID_LEN];
|
||||||
|
} FPC_DB_OP, *PFPC_DB_OP;
|
||||||
|
|
||||||
|
typedef struct _FPC_BEGIN_ENROL
|
||||||
|
{
|
||||||
|
gint32 status;
|
||||||
|
guint32 reserved1;
|
||||||
|
guint32 reserved2;
|
||||||
|
} FPC_BEGIN_ENROL, *PFPC_BEGIN_ENROL;
|
||||||
|
|
||||||
|
typedef struct _FPC_ENROL
|
||||||
|
{
|
||||||
|
gint32 status;
|
||||||
|
guint32 remaining;
|
||||||
|
} FPC_ENROL, *PFPC_ENROL;
|
||||||
|
|
||||||
|
typedef struct _FPC_END_ENROL
|
||||||
|
{
|
||||||
|
gint32 status;
|
||||||
|
guint32 fid;
|
||||||
|
} FPC_END_ENROL, *PFPC_END_ENROL;
|
||||||
|
|
||||||
|
typedef struct _FPC_IDENTIFY
|
||||||
|
{
|
||||||
|
gint32 status;
|
||||||
|
guint32 identity_type;
|
||||||
|
guint32 identity_offset;
|
||||||
|
guint32 identity_size;
|
||||||
|
guint32 subfactor;
|
||||||
|
guint8 data[SECURITY_MAX_SID_SIZE];
|
||||||
|
} FPC_IDENTIFY, *PFPC_IDENTIFY;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
guint32 cmdid;
|
||||||
|
guint32 length;
|
||||||
|
guint32 status;
|
||||||
|
} evt_hdr_t;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
evt_hdr_t hdr;
|
||||||
|
guint16 sensor;
|
||||||
|
guint16 hw_id;
|
||||||
|
guint16 img_w;
|
||||||
|
guint16 img_h;
|
||||||
|
guint8 fw_version[MAX_FW_VERSION_STR_LEN];
|
||||||
|
guint16 fw_capabilities;
|
||||||
|
} evt_initiated_t;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
guint8 subfactor;
|
||||||
|
guint32 identity_type;
|
||||||
|
guint32 identity_size;
|
||||||
|
guint8 identity[SECURITY_MAX_SID_SIZE];
|
||||||
|
} __attribute__((packed)) fpc_fid_data_t;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
evt_hdr_t hdr;
|
||||||
|
gint status;
|
||||||
|
guint32 num_ids;
|
||||||
|
fpc_fid_data_t fid_data[FPC_TEMPLATES_MAX];
|
||||||
|
} __attribute__((packed)) evt_enum_fids_t;
|
||||||
|
|
||||||
|
typedef struct _fp_cmd_response
|
||||||
|
{
|
||||||
|
union
|
||||||
|
{
|
||||||
|
evt_hdr_t evt_hdr;
|
||||||
|
evt_initiated_t evt_inited;
|
||||||
|
evt_enum_fids_t evt_enum_fids;
|
||||||
|
};
|
||||||
|
} fpc_cmd_response_t, *pfpc_cmd_response_t;
|
||||||
|
|
||||||
|
enum {
|
||||||
|
FPC_ENROL_STATUS_COMPLETED = 0,
|
||||||
|
FPC_ENROL_STATUS_PROGRESS = 1,
|
||||||
|
FPC_ENROL_STATUS_FAILED_COULD_NOT_COMPLETE = 2,
|
||||||
|
FPC_ENROL_STATUS_FAILED_ALREADY_ENROLED = 3,
|
||||||
|
FPC_ENROL_STATUS_IMAGE_LOW_COVERAGE = 4,
|
||||||
|
FPC_ENROL_STATUS_IMAGE_TOO_SIMILAR = 5,
|
||||||
|
FPC_ENROL_STATUS_IMAGE_LOW_QUALITY = 6,
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
FPC_CMDTYPE_UNKNOWN = 0,
|
||||||
|
FPC_CMDTYPE_TO_DEVICE,
|
||||||
|
FPC_CMDTYPE_TO_DEVICE_EVTDATA,
|
||||||
|
FPC_CMDTYPE_FROM_DEVICE,
|
||||||
|
} FpcCmdType;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
FPC_CMD_SEND = 0,
|
||||||
|
FPC_CMD_GET_DATA,
|
||||||
|
FPC_CMD_SUSPENDED,
|
||||||
|
FPC_CMD_RESUME,
|
||||||
|
FPC_CMD_NUM_STATES,
|
||||||
|
} FpcCmdState;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
FPC_INIT = 0,
|
||||||
|
FPC_INIT_LOAD_DB,
|
||||||
|
FPC_INIT_NUM_STATES,
|
||||||
|
} FpcInitState;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
FPC_ENROLL_ENUM = 0,
|
||||||
|
FPC_ENROLL_CREATE,
|
||||||
|
FPC_ENROLL_CAPTURE,
|
||||||
|
FPC_ENROLL_GET_IMG,
|
||||||
|
FPC_ENROLL_UPDATE,
|
||||||
|
FPC_ENROLL_COMPLETE,
|
||||||
|
FPC_ENROLL_CHECK_DUPLICATE,
|
||||||
|
FPC_ENROLL_BINDID,
|
||||||
|
FPC_ENROLL_COMMIT,
|
||||||
|
FPC_ENROLL_DICARD,
|
||||||
|
FPC_ENROLL_CLEANUP,
|
||||||
|
FPC_ENROLL_NUM_STATES,
|
||||||
|
} FpcEnrollState;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
FPC_IDENTIFY_CAPTURE = 0,
|
||||||
|
FPC_IDENTIFY_GET_IMG,
|
||||||
|
FPC_IDENTIFY_IDENTIFY,
|
||||||
|
FPC_IDENTIFY_CANCEL,
|
||||||
|
FPC_IDENTIFY_NUM_STATES,
|
||||||
|
} FpcVerifyState;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
FPC_CLEAR_DELETE_DB = 0,
|
||||||
|
FPC_CLEAR_CREATE_DB,
|
||||||
|
FPC_CLEAR_NUM_STATES,
|
||||||
|
} FpClearState;
|
||||||
@@ -19,6 +19,7 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#include "glib.h"
|
||||||
#define FP_COMPONENT "goodixmoc"
|
#define FP_COMPONENT "goodixmoc"
|
||||||
|
|
||||||
#include "drivers_api.h"
|
#include "drivers_api.h"
|
||||||
@@ -128,11 +129,13 @@ 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 ret = -1, ssm_state = 0;
|
int 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)
|
||||||
@@ -154,8 +157,9 @@ fp_cmd_receive_cb (FpiUsbTransfer *transfer,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = gx_proto_parse_header (transfer->buffer, transfer->actual_length, &header);
|
fpi_byte_reader_init (&reader, transfer->buffer, 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,
|
||||||
@@ -163,8 +167,25 @@ fp_cmd_receive_cb (FpiUsbTransfer *transfer,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
gx_proto_crc32_calc (transfer->buffer, PACKAGE_HEADER_SIZE + header.len, (uint8_t *) &crc32_calc);
|
if (header.len < PACKAGE_CRC_SIZE ||
|
||||||
if(crc32_calc != GUINT32_FROM_LE (*(uint32_t *) (transfer->buffer + PACKAGE_HEADER_SIZE + header.len)))
|
!fpi_byte_reader_set_pos (&reader, PACKAGE_HEADER_SIZE + header.len - PACKAGE_CRC_SIZE))
|
||||||
|
{
|
||||||
|
fpi_ssm_mark_failed (transfer->ssm,
|
||||||
|
fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
|
||||||
|
"Package crc read failed"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Exclude the CRC from the package length */
|
||||||
|
header.len -= PACKAGE_CRC_SIZE;
|
||||||
|
|
||||||
|
/* The reader is positioned right at the CRC, i.e. at the end of the data the
|
||||||
|
* CRC is computed over, so use its position as the length. */
|
||||||
|
gx_proto_crc32_calc (transfer->buffer, fpi_byte_reader_get_pos (&reader),
|
||||||
|
(uint8_t *) &crc32_calc);
|
||||||
|
|
||||||
|
if (!fpi_byte_reader_get_uint32_le (&reader, &crc32) ||
|
||||||
|
GUINT32_FROM_LE (crc32_calc) != crc32)
|
||||||
{
|
{
|
||||||
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,
|
||||||
@@ -174,8 +195,9 @@ fp_cmd_receive_cb (FpiUsbTransfer *transfer,
|
|||||||
|
|
||||||
cmd = MAKE_CMD_EX (header.cmd0, header.cmd1);
|
cmd = MAKE_CMD_EX (header.cmd0, header.cmd1);
|
||||||
|
|
||||||
ret = gx_proto_parse_body (cmd, &transfer->buffer[PACKAGE_HEADER_SIZE], header.len, &cmd_reponse);
|
fpi_byte_reader_init (&reader, &transfer->buffer[PACKAGE_HEADER_SIZE], header.len);
|
||||||
if (ret != 0)
|
|
||||||
|
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,
|
||||||
@@ -222,7 +244,7 @@ fp_cmd_run_state (FpiSsm *ssm,
|
|||||||
|
|
||||||
switch (fpi_ssm_get_cur_state (ssm))
|
switch (fpi_ssm_get_cur_state (ssm))
|
||||||
{
|
{
|
||||||
case FP_CMD_SEND:
|
case GOODIX_CMD_SEND:
|
||||||
if (self->cmd_transfer)
|
if (self->cmd_transfer)
|
||||||
{
|
{
|
||||||
self->cmd_transfer->ssm = ssm;
|
self->cmd_transfer->ssm = ssm;
|
||||||
@@ -238,7 +260,7 @@ fp_cmd_run_state (FpiSsm *ssm,
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FP_CMD_GET_ACK:
|
case GOODIX_CMD_GET_ACK:
|
||||||
transfer = fpi_usb_transfer_new (dev);
|
transfer = fpi_usb_transfer_new (dev);
|
||||||
transfer->ssm = ssm;
|
transfer->ssm = 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);
|
||||||
@@ -250,7 +272,7 @@ fp_cmd_run_state (FpiSsm *ssm,
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FP_CMD_GET_DATA:
|
case GOODIX_CMD_GET_DATA:
|
||||||
transfer = fpi_usb_transfer_new (dev);
|
transfer = fpi_usb_transfer_new (dev);
|
||||||
transfer->ssm = ssm;
|
transfer->ssm = 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);
|
||||||
@@ -338,7 +360,7 @@ goodix_sensor_cmd (FpiDeviceGoodixMoc *self,
|
|||||||
|
|
||||||
self->cmd_ssm = fpi_ssm_new (FP_DEVICE (self),
|
self->cmd_ssm = fpi_ssm_new (FP_DEVICE (self),
|
||||||
fp_cmd_run_state,
|
fp_cmd_run_state,
|
||||||
FP_CMD_NUM_STATES);
|
GOODIX_CMD_NUM_STATES);
|
||||||
|
|
||||||
fpi_ssm_set_data (self->cmd_ssm, data, (GDestroyNotify) fp_cmd_ssm_done_data_free);
|
fpi_ssm_set_data (self->cmd_ssm, data, (GDestroyNotify) fp_cmd_ssm_done_data_free);
|
||||||
|
|
||||||
@@ -377,13 +399,13 @@ fp_pwr_btn_shield_cb (FpiDeviceGoodixMoc *self,
|
|||||||
}
|
}
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
*
|
*
|
||||||
* fp_verify_xxxx Function
|
* fp_identify_xxxx Function
|
||||||
*
|
*
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
static void
|
static void
|
||||||
fp_verify_capture_cb (FpiDeviceGoodixMoc *self,
|
fp_identify_capture_cb (FpiDeviceGoodixMoc *self,
|
||||||
gxfp_cmd_response_t *resp,
|
gxfp_cmd_response_t *resp,
|
||||||
GError *error)
|
GError *error)
|
||||||
{
|
{
|
||||||
if (error)
|
if (error)
|
||||||
{
|
{
|
||||||
@@ -416,9 +438,9 @@ fp_verify_capture_cb (FpiDeviceGoodixMoc *self,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
fp_verify_cb (FpiDeviceGoodixMoc *self,
|
fp_identify_cb (FpiDeviceGoodixMoc *self,
|
||||||
gxfp_cmd_response_t *resp,
|
gxfp_cmd_response_t *resp,
|
||||||
GError *error)
|
GError *error)
|
||||||
{
|
{
|
||||||
FpDevice *device = FP_DEVICE (self);
|
FpDevice *device = FP_DEVICE (self);
|
||||||
FpPrint *new_scan = NULL;
|
FpPrint *new_scan = NULL;
|
||||||
@@ -429,43 +451,57 @@ fp_verify_cb (FpiDeviceGoodixMoc *self,
|
|||||||
fpi_ssm_mark_failed (self->task_ssm, error);
|
fpi_ssm_mark_failed (self->task_ssm, error);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (resp->verify.match)
|
if (resp->verify.match)
|
||||||
{
|
{
|
||||||
|
GPtrArray *templates = NULL;
|
||||||
|
guint matching_index;
|
||||||
|
|
||||||
|
fpi_device_get_identify_data (device, &templates);
|
||||||
new_scan = fp_print_from_template (self, &resp->verify.template);
|
new_scan = fp_print_from_template (self, &resp->verify.template);
|
||||||
|
|
||||||
if (fpi_device_get_current_action (device) == FPI_DEVICE_ACTION_VERIFY)
|
if (g_ptr_array_find_with_equal_func (templates, new_scan,
|
||||||
{
|
(GEqualFunc) fp_print_equal,
|
||||||
fpi_device_get_verify_data (device, &matching);
|
&matching_index))
|
||||||
if (!fp_print_equal (matching, new_scan))
|
matching = g_ptr_array_index (templates, matching_index);
|
||||||
matching = NULL;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
GPtrArray *templates = NULL;
|
|
||||||
fpi_device_get_identify_data (device, &templates);
|
|
||||||
|
|
||||||
for (gint i = 0; i < templates->len; i++)
|
|
||||||
{
|
|
||||||
if (fp_print_equal (g_ptr_array_index (templates, i), new_scan))
|
|
||||||
{
|
|
||||||
matching = g_ptr_array_index (templates, i);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fpi_device_get_current_action (device) == FPI_DEVICE_ACTION_VERIFY)
|
fpi_device_identify_report (device, matching, new_scan, error);
|
||||||
fpi_device_verify_report (device, matching ? FPI_MATCH_SUCCESS : FPI_MATCH_FAIL, new_scan, error);
|
|
||||||
else
|
|
||||||
fpi_device_identify_report (device, matching, new_scan, error);
|
|
||||||
|
|
||||||
fpi_ssm_next_state (self->task_ssm);
|
fpi_ssm_next_state (self->task_ssm);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
fp_verify_sm_run_state (FpiSsm *ssm, FpDevice *device)
|
fp_identify_finger_mode_cb (FpiDeviceGoodixMoc *self,
|
||||||
|
gxfp_cmd_response_t *resp,
|
||||||
|
GError *error)
|
||||||
|
{
|
||||||
|
if (error)
|
||||||
|
{
|
||||||
|
fpi_ssm_mark_failed (self->task_ssm, error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/* if reach max timeout(5sec) finger not up, try again */
|
||||||
|
if (resp->finger_status.status == GX_ERROR_WAIT_FINGER_UP_TIMEOUT)
|
||||||
|
{
|
||||||
|
fpi_ssm_jump_to_state (self->task_ssm, GOODIX_IDENTIFY_WAIT_FINGER_UP);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (resp->finger_status.status != GX_SUCCESS)
|
||||||
|
{
|
||||||
|
fpi_ssm_mark_failed (self->task_ssm,
|
||||||
|
fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
|
||||||
|
"Switch finger mode failed"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
fpi_device_report_finger_status_changes (FP_DEVICE (self),
|
||||||
|
FP_FINGER_STATUS_NONE,
|
||||||
|
FP_FINGER_STATUS_PRESENT);
|
||||||
|
fpi_ssm_next_state (self->task_ssm);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
fp_identify_sm_run_state (FpiSsm *ssm, FpDevice *device)
|
||||||
{
|
{
|
||||||
FpiDeviceGoodixMoc *self = FPI_DEVICE_GOODIXMOC (device);
|
FpiDeviceGoodixMoc *self = FPI_DEVICE_GOODIXMOC (device);
|
||||||
guint8 param[3] = { 0 };
|
guint8 param[3] = { 0 };
|
||||||
@@ -477,7 +513,7 @@ fp_verify_sm_run_state (FpiSsm *ssm, FpDevice *device)
|
|||||||
|
|
||||||
switch (fpi_ssm_get_cur_state (ssm))
|
switch (fpi_ssm_get_cur_state (ssm))
|
||||||
{
|
{
|
||||||
case FP_VERIFY_PWR_BTN_SHIELD_ON:
|
case GOODIX_IDENTIFY_PWR_BTN_SHIELD_ON:
|
||||||
goodix_sensor_cmd (self, MOC_CMD0_PWR_BTN_SHIELD, MOC_CMD1_PWR_BTN_SHIELD_ON,
|
goodix_sensor_cmd (self, MOC_CMD0_PWR_BTN_SHIELD, MOC_CMD1_PWR_BTN_SHIELD_ON,
|
||||||
false,
|
false,
|
||||||
NULL,
|
NULL,
|
||||||
@@ -485,7 +521,7 @@ fp_verify_sm_run_state (FpiSsm *ssm, FpDevice *device)
|
|||||||
fp_pwr_btn_shield_cb);
|
fp_pwr_btn_shield_cb);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FP_VERIFY_CAPTURE:
|
case GOODIX_IDENTIFY_CAPTURE:
|
||||||
fpi_device_report_finger_status_changes (device,
|
fpi_device_report_finger_status_changes (device,
|
||||||
FP_FINGER_STATUS_NEEDED,
|
FP_FINGER_STATUS_NEEDED,
|
||||||
FP_FINGER_STATUS_NONE);
|
FP_FINGER_STATUS_NONE);
|
||||||
@@ -493,18 +529,29 @@ fp_verify_sm_run_state (FpiSsm *ssm, FpDevice *device)
|
|||||||
true,
|
true,
|
||||||
(const guint8 *) ¶m,
|
(const guint8 *) ¶m,
|
||||||
G_N_ELEMENTS (param),
|
G_N_ELEMENTS (param),
|
||||||
fp_verify_capture_cb);
|
fp_identify_capture_cb);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FP_VERIFY_IDENTIFY:
|
case GOODIX_IDENTIFY_IDENTIFY:
|
||||||
goodix_sensor_cmd (self, MOC_CMD0_IDENTIFY, MOC_CMD1_DEFAULT,
|
goodix_sensor_cmd (self, MOC_CMD0_IDENTIFY, MOC_CMD1_DEFAULT,
|
||||||
false,
|
false,
|
||||||
(const guint8 *) nonce,
|
(const guint8 *) nonce,
|
||||||
TEMPLATE_ID_SIZE,
|
TEMPLATE_ID_SIZE,
|
||||||
fp_verify_cb);
|
fp_identify_cb);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FP_VERIFY_PWR_BTN_SHIELD_OFF:
|
case GOODIX_IDENTIFY_WAIT_FINGER_UP:
|
||||||
|
{
|
||||||
|
guint8 dummy = 0;
|
||||||
|
goodix_sensor_cmd (self, MOC_CMD0_FINGER_MODE, MOC_CMD1_SET_FINGER_UP,
|
||||||
|
true,
|
||||||
|
&dummy,
|
||||||
|
1,
|
||||||
|
fp_identify_finger_mode_cb);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GOODIX_IDENTIFY_PWR_BTN_SHIELD_OFF:
|
||||||
goodix_sensor_cmd (self, MOC_CMD0_PWR_BTN_SHIELD, MOC_CMD1_PWR_BTN_SHIELD_OFF,
|
goodix_sensor_cmd (self, MOC_CMD0_PWR_BTN_SHIELD, MOC_CMD1_PWR_BTN_SHIELD_OFF,
|
||||||
false,
|
false,
|
||||||
NULL,
|
NULL,
|
||||||
@@ -516,25 +563,16 @@ fp_verify_sm_run_state (FpiSsm *ssm, FpDevice *device)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
fp_verify_ssm_done (FpiSsm *ssm, FpDevice *dev, GError *error)
|
fp_identify_ssm_done (FpiSsm *ssm, FpDevice *dev, GError *error)
|
||||||
{
|
{
|
||||||
FpiDeviceGoodixMoc *self = FPI_DEVICE_GOODIXMOC (dev);
|
FpiDeviceGoodixMoc *self = FPI_DEVICE_GOODIXMOC (dev);
|
||||||
|
|
||||||
fp_info ("Verify complete!");
|
fp_info ("Verify complete!");
|
||||||
|
|
||||||
if (error && error->domain == FP_DEVICE_RETRY)
|
if (error && error->domain == FP_DEVICE_RETRY)
|
||||||
{
|
fpi_device_identify_report (dev, NULL, NULL, g_steal_pointer (&error));
|
||||||
if (fpi_device_get_current_action (dev) == FPI_DEVICE_ACTION_VERIFY)
|
|
||||||
fpi_device_verify_report (dev, FPI_MATCH_ERROR, NULL, g_steal_pointer (&error));
|
|
||||||
else
|
|
||||||
fpi_device_identify_report (dev, NULL, NULL, g_steal_pointer (&error));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fpi_device_get_current_action (dev) == FPI_DEVICE_ACTION_VERIFY)
|
fpi_device_identify_complete (dev, error);
|
||||||
fpi_device_verify_complete (dev, error);
|
|
||||||
|
|
||||||
else
|
|
||||||
fpi_device_identify_complete (dev, error);
|
|
||||||
|
|
||||||
self->task_ssm = NULL;
|
self->task_ssm = NULL;
|
||||||
}
|
}
|
||||||
@@ -631,20 +669,20 @@ fp_enroll_enum_cb (FpiDeviceGoodixMoc *self,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
fpi_ssm_jump_to_state (self->task_ssm, FP_ENROLL_CAPTURE);
|
fpi_ssm_next_state (self->task_ssm);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
fp_enroll_init_cb (FpiDeviceGoodixMoc *self,
|
fp_enroll_create_cb (FpiDeviceGoodixMoc *self,
|
||||||
gxfp_cmd_response_t *resp,
|
gxfp_cmd_response_t *resp,
|
||||||
GError *error)
|
GError *error)
|
||||||
{
|
{
|
||||||
if (error)
|
if (error)
|
||||||
{
|
{
|
||||||
fpi_ssm_mark_failed (self->task_ssm, error);
|
fpi_ssm_mark_failed (self->task_ssm, error);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
memcpy (self->template_id, resp->enroll_init.tid, TEMPLATE_ID_SIZE);
|
memcpy (self->template_id, resp->enroll_create.tid, TEMPLATE_ID_SIZE);
|
||||||
fpi_ssm_next_state (self->task_ssm);
|
fpi_ssm_next_state (self->task_ssm);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -666,7 +704,7 @@ fp_enroll_capture_cb (FpiDeviceGoodixMoc *self,
|
|||||||
self->enroll_stage,
|
self->enroll_stage,
|
||||||
NULL,
|
NULL,
|
||||||
fpi_device_retry_new (FP_DEVICE_RETRY_GENERAL));
|
fpi_device_retry_new (FP_DEVICE_RETRY_GENERAL));
|
||||||
fpi_ssm_jump_to_state (self->task_ssm, FP_ENROLL_CAPTURE);
|
fpi_ssm_jump_to_state (self->task_ssm, GOODIX_ENROLL_CAPTURE);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
fpi_device_report_finger_status_changes (FP_DEVICE (self),
|
fpi_device_report_finger_status_changes (FP_DEVICE (self),
|
||||||
@@ -684,7 +722,7 @@ fp_enroll_capture_cb (FpiDeviceGoodixMoc *self,
|
|||||||
self->enroll_stage,
|
self->enroll_stage,
|
||||||
NULL,
|
NULL,
|
||||||
fpi_device_retry_new (FP_DEVICE_RETRY_CENTER_FINGER));
|
fpi_device_retry_new (FP_DEVICE_RETRY_CENTER_FINGER));
|
||||||
fpi_ssm_jump_to_state (self->task_ssm, FP_ENROLL_CAPTURE);
|
fpi_ssm_jump_to_state (self->task_ssm, GOODIX_ENROLL_CAPTURE);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -715,7 +753,7 @@ fp_enroll_update_cb (FpiDeviceGoodixMoc *self,
|
|||||||
NULL,
|
NULL,
|
||||||
fpi_device_retry_new (FP_DEVICE_RETRY_REMOVE_FINGER));
|
fpi_device_retry_new (FP_DEVICE_RETRY_REMOVE_FINGER));
|
||||||
}
|
}
|
||||||
else if (resp->enroll_update.rollback)
|
else if (resp->enroll_update.rollback || resp->result == 0x73)
|
||||||
{
|
{
|
||||||
fpi_device_enroll_progress (FP_DEVICE (self),
|
fpi_device_enroll_progress (FP_DEVICE (self),
|
||||||
self->enroll_stage,
|
self->enroll_stage,
|
||||||
@@ -730,7 +768,7 @@ fp_enroll_update_cb (FpiDeviceGoodixMoc *self,
|
|||||||
/* if enroll complete, no need to wait finger up */
|
/* if enroll complete, no need to wait finger up */
|
||||||
if (self->enroll_stage >= self->max_enroll_stage)
|
if (self->enroll_stage >= self->max_enroll_stage)
|
||||||
{
|
{
|
||||||
fpi_ssm_jump_to_state (self->task_ssm, FP_ENROLL_CHECK_DUPLICATE);
|
fpi_ssm_jump_to_state (self->task_ssm, GOODIX_ENROLL_CHECK_DUPLICATE);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -796,7 +834,7 @@ fp_finger_mode_cb (FpiDeviceGoodixMoc *self,
|
|||||||
/* if reach max timeout(5sec) finger not up, switch to finger up again */
|
/* if reach max timeout(5sec) finger not up, switch to finger up again */
|
||||||
if (resp->finger_status.status == GX_ERROR_WAIT_FINGER_UP_TIMEOUT)
|
if (resp->finger_status.status == GX_ERROR_WAIT_FINGER_UP_TIMEOUT)
|
||||||
{
|
{
|
||||||
fpi_ssm_jump_to_state (self->task_ssm, FP_ENROLL_WAIT_FINGER_UP);
|
fpi_ssm_jump_to_state (self->task_ssm, GOODIX_ENROLL_WAIT_FINGER_UP);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (resp->finger_status.status != GX_SUCCESS)
|
else if (resp->finger_status.status != GX_SUCCESS)
|
||||||
@@ -811,7 +849,7 @@ fp_finger_mode_cb (FpiDeviceGoodixMoc *self,
|
|||||||
FP_FINGER_STATUS_PRESENT);
|
FP_FINGER_STATUS_PRESENT);
|
||||||
if (self->enroll_stage < self->max_enroll_stage)
|
if (self->enroll_stage < self->max_enroll_stage)
|
||||||
{
|
{
|
||||||
fpi_ssm_jump_to_state (self->task_ssm, FP_ENROLL_CAPTURE);
|
fpi_ssm_jump_to_state (self->task_ssm, GOODIX_ENROLL_CAPTURE);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
fpi_ssm_next_state (self->task_ssm);
|
fpi_ssm_next_state (self->task_ssm);
|
||||||
@@ -837,17 +875,7 @@ 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_ENUM:
|
case GOODIX_ENROLL_PWR_BTN_SHIELD_ON:
|
||||||
{
|
|
||||||
goodix_sensor_cmd (self, MOC_CMD0_GETFINGERLIST, MOC_CMD1_DEFAULT,
|
|
||||||
false,
|
|
||||||
(const guint8 *) &dummy,
|
|
||||||
1,
|
|
||||||
fp_enroll_enum_cb);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case FP_ENROLL_PWR_BTN_SHIELD_ON:
|
|
||||||
{
|
{
|
||||||
goodix_sensor_cmd (self, MOC_CMD0_PWR_BTN_SHIELD, MOC_CMD1_PWR_BTN_SHIELD_ON,
|
goodix_sensor_cmd (self, MOC_CMD0_PWR_BTN_SHIELD, MOC_CMD1_PWR_BTN_SHIELD_ON,
|
||||||
false,
|
false,
|
||||||
@@ -857,17 +885,27 @@ fp_enroll_sm_run_state (FpiSsm *ssm, FpDevice *device)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FP_ENROLL_CREATE:
|
case GOODIX_ENROLL_ENUM:
|
||||||
|
{
|
||||||
|
goodix_sensor_cmd (self, MOC_CMD0_GETFINGERLIST, MOC_CMD1_DEFAULT,
|
||||||
|
false,
|
||||||
|
(const guint8 *) &dummy,
|
||||||
|
1,
|
||||||
|
fp_enroll_enum_cb);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GOODIX_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_init_cb);
|
fp_enroll_create_cb);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FP_ENROLL_CAPTURE:
|
case GOODIX_ENROLL_CAPTURE:
|
||||||
fpi_device_report_finger_status_changes (device,
|
fpi_device_report_finger_status_changes (device,
|
||||||
FP_FINGER_STATUS_NEEDED,
|
FP_FINGER_STATUS_NEEDED,
|
||||||
FP_FINGER_STATUS_NONE);
|
FP_FINGER_STATUS_NONE);
|
||||||
@@ -878,7 +916,7 @@ fp_enroll_sm_run_state (FpiSsm *ssm, FpDevice *device)
|
|||||||
fp_enroll_capture_cb);
|
fp_enroll_capture_cb);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FP_ENROLL_UPDATE:
|
case GOODIX_ENROLL_UPDATE:
|
||||||
dummy[0] = 1;
|
dummy[0] = 1;
|
||||||
dummy[1] = self->sensorcfg->config[2];
|
dummy[1] = self->sensorcfg->config[2];
|
||||||
dummy[2] = self->sensorcfg->config[3];
|
dummy[2] = self->sensorcfg->config[3];
|
||||||
@@ -889,7 +927,7 @@ fp_enroll_sm_run_state (FpiSsm *ssm, FpDevice *device)
|
|||||||
fp_enroll_update_cb);
|
fp_enroll_update_cb);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FP_ENROLL_WAIT_FINGER_UP:
|
case GOODIX_ENROLL_WAIT_FINGER_UP:
|
||||||
dummy[0] = 0;
|
dummy[0] = 0;
|
||||||
goodix_sensor_cmd (self, MOC_CMD0_FINGER_MODE, MOC_CMD1_SET_FINGER_UP,
|
goodix_sensor_cmd (self, MOC_CMD0_FINGER_MODE, MOC_CMD1_SET_FINGER_UP,
|
||||||
true,
|
true,
|
||||||
@@ -898,7 +936,7 @@ fp_enroll_sm_run_state (FpiSsm *ssm, FpDevice *device)
|
|||||||
fp_finger_mode_cb);
|
fp_finger_mode_cb);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FP_ENROLL_CHECK_DUPLICATE:
|
case GOODIX_ENROLL_CHECK_DUPLICATE:
|
||||||
goodix_sensor_cmd (self, MOC_CMD0_CHECK4DUPLICATE, MOC_CMD1_DEFAULT,
|
goodix_sensor_cmd (self, MOC_CMD0_CHECK4DUPLICATE, MOC_CMD1_DEFAULT,
|
||||||
false,
|
false,
|
||||||
(const guint8 *) &dummy,
|
(const guint8 *) &dummy,
|
||||||
@@ -906,7 +944,7 @@ fp_enroll_sm_run_state (FpiSsm *ssm, FpDevice *device)
|
|||||||
fp_enroll_check_duplicate_cb);
|
fp_enroll_check_duplicate_cb);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FP_ENROLL_COMMIT:
|
case GOODIX_ENROLL_COMMIT:
|
||||||
{
|
{
|
||||||
fpi_device_get_enroll_data (device, &print);
|
fpi_device_get_enroll_data (device, &print);
|
||||||
user_id = fpi_print_generate_user_id (print);
|
user_id = fpi_print_generate_user_id (print);
|
||||||
@@ -914,7 +952,7 @@ fp_enroll_sm_run_state (FpiSsm *ssm, FpDevice *device)
|
|||||||
user_id_len = MIN (100, user_id_len);
|
user_id_len = MIN (100, user_id_len);
|
||||||
finger = 1;
|
finger = 1;
|
||||||
|
|
||||||
if (g_strcmp0 (g_getenv ("FP_DEVICE_EMULATION"), "1") == 0)
|
if (fpi_device_emulation_mode_enabled (FP_DEVICE (self)))
|
||||||
memset (self->template_id, 0, TEMPLATE_ID_SIZE);
|
memset (self->template_id, 0, TEMPLATE_ID_SIZE);
|
||||||
uid = g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE,
|
uid = g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE,
|
||||||
user_id,
|
user_id,
|
||||||
@@ -959,7 +997,7 @@ fp_enroll_sm_run_state (FpiSsm *ssm, FpDevice *device)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FP_ENROLL_PWR_BTN_SHIELD_OFF:
|
case GOODIX_ENROLL_PWR_BTN_SHIELD_OFF:
|
||||||
{
|
{
|
||||||
goodix_sensor_cmd (self, MOC_CMD0_PWR_BTN_SHIELD, MOC_CMD1_PWR_BTN_SHIELD_OFF,
|
goodix_sensor_cmd (self, MOC_CMD0_PWR_BTN_SHIELD, MOC_CMD1_PWR_BTN_SHIELD_OFF,
|
||||||
false,
|
false,
|
||||||
@@ -1050,7 +1088,7 @@ fp_init_cb_reset_or_complete (FpiDeviceGoodixMoc *self,
|
|||||||
{
|
{
|
||||||
fp_warn ("Template storage appears to have been corrupted! Error was: %s", error->message);
|
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.");
|
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);
|
fpi_ssm_jump_to_state (self->task_ssm, GOODIX_INIT_RESET_DEVICE);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -1091,7 +1129,7 @@ fp_init_sm_run_state (FpiSsm *ssm, FpDevice *device)
|
|||||||
|
|
||||||
switch (fpi_ssm_get_cur_state (ssm))
|
switch (fpi_ssm_get_cur_state (ssm))
|
||||||
{
|
{
|
||||||
case FP_INIT_VERSION:
|
case GOODIX_INIT_VERSION:
|
||||||
goodix_sensor_cmd (self, MOC_CMD0_GET_VERSION, MOC_CMD1_DEFAULT,
|
goodix_sensor_cmd (self, MOC_CMD0_GET_VERSION, MOC_CMD1_DEFAULT,
|
||||||
false,
|
false,
|
||||||
&dummy,
|
&dummy,
|
||||||
@@ -1099,7 +1137,7 @@ fp_init_sm_run_state (FpiSsm *ssm, FpDevice *device)
|
|||||||
fp_init_version_cb);
|
fp_init_version_cb);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FP_INIT_CONFIG:
|
case GOODIX_INIT_CONFIG:
|
||||||
goodix_sensor_cmd (self, MOC_CMD0_UPDATE_CONFIG, MOC_CMD1_WRITE_CFG_TO_FLASH,
|
goodix_sensor_cmd (self, MOC_CMD0_UPDATE_CONFIG, MOC_CMD1_WRITE_CFG_TO_FLASH,
|
||||||
false,
|
false,
|
||||||
(guint8 *) self->sensorcfg,
|
(guint8 *) self->sensorcfg,
|
||||||
@@ -1107,7 +1145,7 @@ fp_init_sm_run_state (FpiSsm *ssm, FpDevice *device)
|
|||||||
fp_init_config_cb);
|
fp_init_config_cb);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FP_INIT_TEMPLATE_LIST:
|
case GOODIX_INIT_TEMPLATE_LIST:
|
||||||
/* List prints to check whether the template DB was corrupted.
|
/* 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
|
* 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
|
* stored templates for Linux to be corrupted when the Windows storage
|
||||||
@@ -1122,7 +1160,7 @@ fp_init_sm_run_state (FpiSsm *ssm, FpDevice *device)
|
|||||||
fp_init_cb_reset_or_complete);
|
fp_init_cb_reset_or_complete);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FP_INIT_RESET_DEVICE:
|
case GOODIX_INIT_RESET_DEVICE:
|
||||||
fp_warn ("Resetting device storage, you will need to enroll all prints again!");
|
fp_warn ("Resetting device storage, you will need to enroll all prints again!");
|
||||||
goodix_sensor_cmd (self, MOC_CMD0_DELETETEMPLATE, MOC_CMD1_DELETE_ALL,
|
goodix_sensor_cmd (self, MOC_CMD0_DELETETEMPLATE, MOC_CMD1_DELETE_ALL,
|
||||||
FALSE,
|
FALSE,
|
||||||
@@ -1334,7 +1372,7 @@ gx_fp_probe (FpDevice *device)
|
|||||||
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;
|
||||||
|
|
||||||
if (g_strcmp0 (g_getenv ("FP_DEVICE_EMULATION"), "1") == 0)
|
if (fpi_device_emulation_mode_enabled (FP_DEVICE (self)))
|
||||||
{
|
{
|
||||||
|
|
||||||
serial = g_strdup ("emulated-device");
|
serial = g_strdup ("emulated-device");
|
||||||
@@ -1359,12 +1397,32 @@ gx_fp_probe (FpDevice *device)
|
|||||||
{
|
{
|
||||||
case 0x6496:
|
case 0x6496:
|
||||||
case 0x60A2:
|
case 0x60A2:
|
||||||
|
case 0x60A4:
|
||||||
|
case 0x6014:
|
||||||
|
case 0x6090:
|
||||||
|
case 0x6092:
|
||||||
|
case 0x6094:
|
||||||
|
case 0x609A:
|
||||||
case 0x609C:
|
case 0x609C:
|
||||||
|
case 0x60BC:
|
||||||
|
case 0x60C2:
|
||||||
|
case 0x6304:
|
||||||
|
case 0x631C:
|
||||||
|
case 0x633C:
|
||||||
|
case 0x634C:
|
||||||
|
case 0x6382:
|
||||||
|
case 0x6384:
|
||||||
case 0x639C:
|
case 0x639C:
|
||||||
case 0x63AC:
|
case 0x63AC:
|
||||||
case 0x63BC:
|
case 0x63BC:
|
||||||
case 0x63CC:
|
case 0x63CC:
|
||||||
|
case 0x650A:
|
||||||
|
case 0x650C:
|
||||||
|
case 0x6582:
|
||||||
case 0x6A94:
|
case 0x6A94:
|
||||||
|
case 0x659A:
|
||||||
|
case 0x6890:
|
||||||
|
case 0x6984:
|
||||||
self->max_enroll_stage = 12;
|
self->max_enroll_stage = 12;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -1420,7 +1478,7 @@ gx_fp_init (FpDevice *device)
|
|||||||
}
|
}
|
||||||
|
|
||||||
self->task_ssm = fpi_ssm_new (device, fp_init_sm_run_state,
|
self->task_ssm = fpi_ssm_new (device, fp_init_sm_run_state,
|
||||||
FP_INIT_NUM_STATES);
|
GOODIX_INIT_NUM_STATES);
|
||||||
|
|
||||||
fpi_ssm_start (self->task_ssm, fp_init_ssm_done);
|
fpi_ssm_start (self->task_ssm, fp_init_ssm_done);
|
||||||
|
|
||||||
@@ -1451,9 +1509,7 @@ 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);
|
||||||
@@ -1483,16 +1539,16 @@ gx_fp_exit (FpDevice *device)
|
|||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gx_fp_verify_identify (FpDevice *device)
|
gx_fp_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_full (device, fp_identify_sm_run_state,
|
||||||
FP_VERIFY_NUM_STATES,
|
GOODIX_IDENTIFY_NUM_STATES,
|
||||||
FP_VERIFY_PWR_BTN_SHIELD_OFF,
|
GOODIX_IDENTIFY_PWR_BTN_SHIELD_OFF,
|
||||||
"verify");
|
"identify");
|
||||||
|
|
||||||
fpi_ssm_start (self->task_ssm, fp_verify_ssm_done);
|
fpi_ssm_start (self->task_ssm, fp_identify_ssm_done);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1505,8 +1561,8 @@ gx_fp_enroll (FpDevice *device)
|
|||||||
self->enroll_stage = 0;
|
self->enroll_stage = 0;
|
||||||
|
|
||||||
self->task_ssm = fpi_ssm_new_full (device, fp_enroll_sm_run_state,
|
self->task_ssm = fpi_ssm_new_full (device, fp_enroll_sm_run_state,
|
||||||
FP_ENROLL_NUM_STATES,
|
GOODIX_ENROLL_NUM_STATES,
|
||||||
FP_ENROLL_PWR_BTN_SHIELD_OFF,
|
GOODIX_ENROLL_PWR_BTN_SHIELD_OFF,
|
||||||
"enroll");
|
"enroll");
|
||||||
|
|
||||||
fpi_ssm_start (self->task_ssm, fp_enroll_ssm_done);
|
fpi_ssm_start (self->task_ssm, fp_enroll_ssm_done);
|
||||||
@@ -1545,7 +1601,7 @@ gx_fp_template_delete (FpDevice *device)
|
|||||||
gsize user_id_len = 0;
|
gsize user_id_len = 0;
|
||||||
const guint8 *tid;
|
const guint8 *tid;
|
||||||
gsize tid_len = 0;
|
gsize tid_len = 0;
|
||||||
gsize payload_len = 0;
|
guint16 payload_len = 0;
|
||||||
g_autofree guint8 *payload = NULL;
|
g_autofree guint8 *payload = NULL;
|
||||||
|
|
||||||
fpi_device_get_delete_data (device, &print);
|
fpi_device_get_delete_data (device, &print);
|
||||||
@@ -1558,7 +1614,8 @@ gx_fp_template_delete (FpDevice *device)
|
|||||||
fpi_device_error_new (FP_DEVICE_ERROR_DATA_INVALID));
|
fpi_device_error_new (FP_DEVICE_ERROR_DATA_INVALID));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!encode_finger_id (tid, tid_len, user_id, user_id_len, &payload, (guint16 *) &payload_len))
|
|
||||||
|
if (!encode_finger_id (tid, tid_len, user_id, user_id_len, &payload, &payload_len))
|
||||||
{
|
{
|
||||||
fpi_device_delete_complete (device,
|
fpi_device_delete_complete (device,
|
||||||
fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
|
fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
|
||||||
@@ -1595,19 +1652,42 @@ fpi_device_goodixmoc_init (FpiDeviceGoodixMoc *self)
|
|||||||
|
|
||||||
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 = 0x6090, },
|
||||||
|
{ .vid = 0x27c6, .pid = 0x6092, },
|
||||||
|
{ .vid = 0x27c6, .pid = 0x6094, },
|
||||||
|
{ .vid = 0x27c6, .pid = 0x609A, },
|
||||||
{ .vid = 0x27c6, .pid = 0x609C, },
|
{ .vid = 0x27c6, .pid = 0x609C, },
|
||||||
{ .vid = 0x27c6, .pid = 0x60A2, },
|
{ .vid = 0x27c6, .pid = 0x60A2, },
|
||||||
|
{ .vid = 0x27c6, .pid = 0x60A4, },
|
||||||
|
{ .vid = 0x27c6, .pid = 0x60BC, },
|
||||||
|
{ .vid = 0x27c6, .pid = 0x60C2, },
|
||||||
|
{ .vid = 0x27c6, .pid = 0x6304, },
|
||||||
|
{ .vid = 0x27c6, .pid = 0x631C, },
|
||||||
|
{ .vid = 0x27c6, .pid = 0x633C, },
|
||||||
|
{ .vid = 0x27c6, .pid = 0x634C, },
|
||||||
|
{ .vid = 0x27c6, .pid = 0x6382, },
|
||||||
|
{ .vid = 0x27c6, .pid = 0x6384, },
|
||||||
{ .vid = 0x27c6, .pid = 0x639C, },
|
{ .vid = 0x27c6, .pid = 0x639C, },
|
||||||
{ .vid = 0x27c6, .pid = 0x63AC, },
|
{ .vid = 0x27c6, .pid = 0x63AC, },
|
||||||
{ .vid = 0x27c6, .pid = 0x63BC, },
|
{ .vid = 0x27c6, .pid = 0x63BC, },
|
||||||
{ .vid = 0x27c6, .pid = 0x63CC, },
|
{ .vid = 0x27c6, .pid = 0x63CC, },
|
||||||
{ .vid = 0x27c6, .pid = 0x6496, },
|
{ .vid = 0x27c6, .pid = 0x6496, },
|
||||||
|
{ .vid = 0x27c6, .pid = 0x650A, },
|
||||||
|
{ .vid = 0x27c6, .pid = 0x650C, },
|
||||||
|
{ .vid = 0x27c6, .pid = 0x6582, },
|
||||||
{ .vid = 0x27c6, .pid = 0x6584, },
|
{ .vid = 0x27c6, .pid = 0x6584, },
|
||||||
{ .vid = 0x27c6, .pid = 0x658C, },
|
{ .vid = 0x27c6, .pid = 0x658C, },
|
||||||
{ .vid = 0x27c6, .pid = 0x6592, },
|
{ .vid = 0x27c6, .pid = 0x6592, },
|
||||||
{ .vid = 0x27c6, .pid = 0x6594, },
|
{ .vid = 0x27c6, .pid = 0x6594, },
|
||||||
|
{ .vid = 0x27c6, .pid = 0x659A, },
|
||||||
{ .vid = 0x27c6, .pid = 0x659C, },
|
{ .vid = 0x27c6, .pid = 0x659C, },
|
||||||
{ .vid = 0x27c6, .pid = 0x6A94, },
|
{ .vid = 0x27c6, .pid = 0x6A94, },
|
||||||
|
{ .vid = 0x27c6, .pid = 0x6512, },
|
||||||
|
{ .vid = 0x27c6, .pid = 0x6890, },
|
||||||
|
{ .vid = 0x27c6, .pid = 0x689A, },
|
||||||
|
{ .vid = 0x27c6, .pid = 0x66A9, },
|
||||||
|
{ .vid = 0x27c6, .pid = 0x6984, },
|
||||||
{ .vid = 0, .pid = 0, .driver_data = 0 }, /* terminating entry */
|
{ .vid = 0, .pid = 0, .driver_data = 0 }, /* terminating entry */
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1632,8 +1712,7 @@ fpi_device_goodixmoc_class_init (FpiDeviceGoodixMocClass *klass)
|
|||||||
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->clear_storage = gx_fp_template_delete_all;
|
||||||
dev_class->list = gx_fp_template_list;
|
dev_class->list = gx_fp_template_list;
|
||||||
dev_class->verify = gx_fp_verify_identify;
|
dev_class->identify = gx_fp_identify;
|
||||||
dev_class->identify = gx_fp_verify_identify;
|
|
||||||
|
|
||||||
fpi_device_class_auto_initialize_features (dev_class);
|
fpi_device_class_auto_initialize_features (dev_class);
|
||||||
dev_class->features |= FP_DEVICE_FEATURE_DUPLICATES_CHECK;
|
dev_class->features |= FP_DEVICE_FEATURE_DUPLICATES_CHECK;
|
||||||
|
|||||||
@@ -25,40 +25,40 @@
|
|||||||
G_DECLARE_FINAL_TYPE (FpiDeviceGoodixMoc, fpi_device_goodixmoc, FPI, DEVICE_GOODIXMOC, FpDevice)
|
G_DECLARE_FINAL_TYPE (FpiDeviceGoodixMoc, fpi_device_goodixmoc, FPI, DEVICE_GOODIXMOC, FpDevice)
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
FP_CMD_SEND = 0,
|
GOODIX_CMD_SEND = 0,
|
||||||
FP_CMD_GET_ACK,
|
GOODIX_CMD_GET_ACK,
|
||||||
FP_CMD_GET_DATA,
|
GOODIX_CMD_GET_DATA,
|
||||||
FP_CMD_NUM_STATES,
|
GOODIX_CMD_NUM_STATES,
|
||||||
} FpCmdState;
|
} GoodixCmdState;
|
||||||
|
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
FP_INIT_VERSION = 0,
|
GOODIX_INIT_VERSION = 0,
|
||||||
FP_INIT_CONFIG,
|
GOODIX_INIT_CONFIG,
|
||||||
FP_INIT_TEMPLATE_LIST,
|
GOODIX_INIT_TEMPLATE_LIST,
|
||||||
FP_INIT_RESET_DEVICE,
|
GOODIX_INIT_RESET_DEVICE,
|
||||||
FP_INIT_NUM_STATES,
|
GOODIX_INIT_NUM_STATES,
|
||||||
} FpInitState;
|
} GoodixInitState;
|
||||||
|
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
FP_ENROLL_PWR_BTN_SHIELD_ON = 0,
|
GOODIX_ENROLL_PWR_BTN_SHIELD_ON = 0,
|
||||||
FP_ENROLL_ENUM,
|
GOODIX_ENROLL_ENUM,
|
||||||
FP_ENROLL_IDENTIFY,
|
GOODIX_ENROLL_CREATE,
|
||||||
FP_ENROLL_CREATE,
|
GOODIX_ENROLL_CAPTURE,
|
||||||
FP_ENROLL_CAPTURE,
|
GOODIX_ENROLL_UPDATE,
|
||||||
FP_ENROLL_UPDATE,
|
GOODIX_ENROLL_WAIT_FINGER_UP,
|
||||||
FP_ENROLL_WAIT_FINGER_UP,
|
GOODIX_ENROLL_CHECK_DUPLICATE,
|
||||||
FP_ENROLL_CHECK_DUPLICATE,
|
GOODIX_ENROLL_COMMIT,
|
||||||
FP_ENROLL_COMMIT,
|
GOODIX_ENROLL_PWR_BTN_SHIELD_OFF,
|
||||||
FP_ENROLL_PWR_BTN_SHIELD_OFF,
|
GOODIX_ENROLL_NUM_STATES,
|
||||||
FP_ENROLL_NUM_STATES,
|
} GoodixEnrollState;
|
||||||
} FpEnrollState;
|
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
FP_VERIFY_PWR_BTN_SHIELD_ON = 0,
|
GOODIX_IDENTIFY_PWR_BTN_SHIELD_ON = 0,
|
||||||
FP_VERIFY_CAPTURE,
|
GOODIX_IDENTIFY_CAPTURE,
|
||||||
FP_VERIFY_IDENTIFY,
|
GOODIX_IDENTIFY_IDENTIFY,
|
||||||
FP_VERIFY_PWR_BTN_SHIELD_OFF,
|
GOODIX_IDENTIFY_WAIT_FINGER_UP,
|
||||||
FP_VERIFY_NUM_STATES,
|
GOODIX_IDENTIFY_PWR_BTN_SHIELD_OFF,
|
||||||
} FpVerifyState;
|
GOODIX_IDENTIFY_NUM_STATES,
|
||||||
|
} GoodixVerifyState;
|
||||||
|
|||||||
@@ -18,6 +18,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
#include "goodix_proto.h"
|
#include "goodix_proto.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -107,7 +109,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 |= (1 << ((n_bits - 1) - bit));
|
reflection |= (1LU << ((n_bits - 1) - bit));
|
||||||
|
|
||||||
data = (data >> 1);
|
data = (data >> 1);
|
||||||
}
|
}
|
||||||
@@ -211,7 +213,11 @@ 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);
|
||||||
memcpy (ppackage + PACKAGE_HEADER_SIZE, payload, payload_size);
|
|
||||||
|
if (payload)
|
||||||
|
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);
|
||||||
|
|
||||||
@@ -220,94 +226,106 @@ gx_proto_build_package (uint8_t *ppackage,
|
|||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
gx_proto_parse_header (
|
gx_proto_parse_header (FpiByteReader *reader,
|
||||||
uint8_t *buffer,
|
pack_header *pheader)
|
||||||
uint32_t buffer_len,
|
|
||||||
pack_header *pheader)
|
|
||||||
{
|
{
|
||||||
if (!buffer || !pheader)
|
if (!pheader)
|
||||||
return -1;
|
|
||||||
if (buffer_len < PACKAGE_HEADER_SIZE + PACKAGE_CRC_SIZE)
|
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
memcpy (pheader, buffer, sizeof (pack_header));
|
if (!fpi_byte_reader_get_uint8 (reader, &pheader->cmd0))
|
||||||
pheader->len = GUINT16_FROM_LE (pheader->len);
|
g_return_val_if_reached (-1);
|
||||||
if (buffer_len < pheader->len + PACKAGE_HEADER_SIZE)
|
|
||||||
return -1;
|
if (!fpi_byte_reader_get_uint8 (reader, &pheader->cmd1))
|
||||||
pheader->len -= PACKAGE_CRC_SIZE;
|
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);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
gx_proto_parse_fingerid (
|
gx_proto_parse_fingerid (FpiByteReader *reader,
|
||||||
uint8_t * fid_buffer,
|
ptemplate_format_t template)
|
||||||
uint16_t fid_buffer_size,
|
|
||||||
ptemplate_format_t template
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
uint8_t * buffer = NULL;
|
uint8_t byte;
|
||||||
uint16_t Offset = 0;
|
|
||||||
|
|
||||||
if (!template || !fid_buffer)
|
if (!template)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (fid_buffer_size < G_STRUCT_OFFSET (template_format_t, payload) + sizeof (uint32_t))
|
if (!fpi_byte_reader_get_uint8 (reader, &byte) || byte != 67)
|
||||||
return -1;
|
g_return_val_if_reached (-1);
|
||||||
|
|
||||||
buffer = fid_buffer;
|
if (!fpi_byte_reader_get_uint8 (reader, &template->type))
|
||||||
Offset = 0;
|
g_return_val_if_reached (-1);
|
||||||
|
|
||||||
if (buffer[Offset++] != 67)
|
if (!fpi_byte_reader_get_uint8 (reader, &template->finger_index))
|
||||||
return -1;
|
g_return_val_if_reached (-1);
|
||||||
|
|
||||||
|
if (!fpi_byte_reader_skip (reader, 1))
|
||||||
|
g_return_val_if_reached (-1);
|
||||||
|
|
||||||
|
if (!fpi_byte_reader_get_data_static (reader, template->accountid))
|
||||||
|
g_return_val_if_reached (-1);
|
||||||
|
|
||||||
|
if (!fpi_byte_reader_get_data_static (reader, template->tid))
|
||||||
|
g_return_val_if_reached (-1);
|
||||||
|
|
||||||
|
if (!fpi_byte_reader_get_uint8 (reader, &template->payload.size))
|
||||||
|
g_return_val_if_reached (-1);
|
||||||
|
|
||||||
template->type = buffer[Offset++];
|
|
||||||
template->finger_index = buffer[Offset++];
|
|
||||||
Offset++;
|
|
||||||
memcpy (template->accountid, &buffer[Offset], sizeof (template->accountid));
|
|
||||||
Offset += sizeof (template->accountid);
|
|
||||||
memcpy (template->tid, &buffer[Offset], sizeof (template->tid));
|
|
||||||
Offset += sizeof (template->tid); // Offset == 68
|
|
||||||
template->payload.size = buffer[Offset++];
|
|
||||||
if (template->payload.size > sizeof (template->payload.data))
|
if (template->payload.size > sizeof (template->payload.data))
|
||||||
return -1;
|
{
|
||||||
if (template->payload.size + Offset > fid_buffer_size)
|
g_warning ("Device reported oversized payload (%d)", template->payload.size);
|
||||||
return -1;
|
return -1;
|
||||||
memset (template->payload.data, 0, template->payload.size);
|
}
|
||||||
memcpy (template->payload.data, &buffer[Offset], template->payload.size);
|
|
||||||
|
if (!(fpi_byte_reader_get_data_static) (reader, template->payload.size,
|
||||||
|
template->payload.data))
|
||||||
|
g_return_val_if_reached (-1);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
gx_proto_parse_body (uint16_t cmd, uint8_t *buffer, uint16_t buffer_len, pgxfp_cmd_response_t presp)
|
gx_proto_parse_body (uint16_t cmd, FpiByteReader *byte_reader, pgxfp_cmd_response_t presp)
|
||||||
{
|
{
|
||||||
uint16_t offset = 0;
|
if (!presp)
|
||||||
uint8_t *fingerlist = NULL;
|
return -1;
|
||||||
|
|
||||||
|
if (!fpi_byte_reader_get_uint8 (byte_reader, &presp->result))
|
||||||
|
g_return_val_if_reached (-1);
|
||||||
|
|
||||||
if (!buffer || !presp)
|
|
||||||
return -1;
|
|
||||||
if (buffer_len < 1)
|
|
||||||
return -1;
|
|
||||||
presp->result = buffer[0];
|
|
||||||
switch (HIBYTE (cmd))
|
switch (HIBYTE (cmd))
|
||||||
{
|
{
|
||||||
case RESPONSE_PACKAGE_CMD:
|
case RESPONSE_PACKAGE_CMD:
|
||||||
{
|
{
|
||||||
if (buffer_len < sizeof (gxfp_parse_msg_t) + 1)
|
if (!fpi_byte_reader_get_uint8 (byte_reader, &presp->parse_msg.ack_cmd))
|
||||||
return -1;
|
g_return_val_if_reached (-1);
|
||||||
presp->parse_msg.ack_cmd = buffer[1];
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MOC_CMD0_UPDATE_CONFIG:
|
case MOC_CMD0_UPDATE_CONFIG:
|
||||||
{
|
{
|
||||||
presp->finger_config.status = buffer[0];
|
presp->finger_config.status = presp->result;
|
||||||
if (buffer_len >= 3)
|
/* to compatiable old version firmware */
|
||||||
presp->finger_config.max_stored_prints = buffer[2];
|
presp->finger_config.max_stored_prints = FP_MAX_FINGERNUM;
|
||||||
else
|
|
||||||
/* to compatiable old version firmware */
|
|
||||||
presp->finger_config.max_stored_prints = FP_MAX_FINGERNUM;
|
|
||||||
|
|
||||||
|
if (fpi_byte_reader_skip (byte_reader, 1))
|
||||||
|
fpi_byte_reader_get_uint8 (byte_reader,
|
||||||
|
&presp->finger_config.max_stored_prints);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -318,85 +336,106 @@ gx_proto_parse_body (uint16_t cmd, uint8_t *buffer, uint16_t buffer_len, pgxfp_c
|
|||||||
|
|
||||||
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);
|
||||||
if (buffer_len >= 2)
|
uint8_t support_pwr_shield;
|
||||||
{
|
|
||||||
uint8_t support_pwr_shield = buffer[1];
|
if (fpi_byte_reader_get_uint8 (byte_reader, &support_pwr_shield) &&
|
||||||
if (support_pwr_shield == 0xFF)
|
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:
|
||||||
if (buffer_len < sizeof (gxfp_version_info_t) + 1)
|
const uint8_t *version_info;
|
||||||
return -1;
|
|
||||||
memcpy (&presp->version_info, buffer + 1, sizeof (gxfp_version_info_t));
|
if (!fpi_byte_reader_get_data (byte_reader, sizeof (gxfp_version_info_t), &version_info))
|
||||||
|
g_return_val_if_reached (-1);
|
||||||
|
|
||||||
|
memcpy (&presp->version_info, version_info, sizeof (gxfp_version_info_t));
|
||||||
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 (buffer_len < sizeof (gxfp_capturedata_t) + 1)
|
if (!fpi_byte_reader_get_uint8 (byte_reader,
|
||||||
return -1;
|
&presp->capture_data_resp.img_quality))
|
||||||
presp->capture_data_resp.img_quality = buffer[1];
|
g_return_val_if_reached (-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 (buffer_len < sizeof (gxfp_enroll_init_t) + 1)
|
if (presp->result != GX_SUCCESS)
|
||||||
return -1;
|
break;
|
||||||
if (presp->result == GX_SUCCESS)
|
const uint8_t *tid;
|
||||||
memcpy (&presp->enroll_init.tid, &buffer[1], TEMPLATE_ID_SIZE);
|
if (!fpi_byte_reader_get_data (byte_reader, TEMPLATE_ID_SIZE, &tid))
|
||||||
|
g_return_val_if_reached (-1);
|
||||||
|
memcpy (presp->enroll_create.tid, tid, TEMPLATE_ID_SIZE);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MOC_CMD0_ENROLL:
|
case MOC_CMD0_ENROLL:
|
||||||
if (buffer_len < sizeof (gxfp_enroll_update_t))
|
presp->enroll_update.rollback = (presp->result < 0x80) ? false : true;
|
||||||
return -1;
|
if (!fpi_byte_reader_get_uint8 (byte_reader,
|
||||||
presp->enroll_update.rollback = (buffer[0] < 0x80) ? false : true;
|
&presp->enroll_update.img_overlay))
|
||||||
presp->enroll_update.img_overlay = buffer[1];
|
g_return_val_if_reached (-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)
|
||||||
{
|
{
|
||||||
if (buffer_len < 3)
|
uint16_t tid_size;
|
||||||
return -1;
|
FpiByteReader tid_reader;
|
||||||
uint16_t tid_size = GUINT16_FROM_LE (*(uint16_t *) (buffer + 1));
|
|
||||||
offset += 3;
|
|
||||||
|
|
||||||
if (buffer_len < tid_size + offset)
|
if (!fpi_byte_reader_get_uint16_le (byte_reader, &tid_size))
|
||||||
return -1;
|
g_return_val_if_reached (-1);
|
||||||
if (gx_proto_parse_fingerid (buffer + offset, tid_size, &presp->check_duplicate_resp.template) != 0)
|
|
||||||
return -1;
|
if (!fpi_byte_reader_get_sub_reader (byte_reader, &tid_reader, tid_size))
|
||||||
|
g_return_val_if_reached (-1);
|
||||||
|
|
||||||
|
if (gx_proto_parse_fingerid (&tid_reader, &presp->check_duplicate_resp.template) != 0)
|
||||||
|
g_return_val_if_reached (-1);
|
||||||
}
|
}
|
||||||
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)
|
|
||||||
return -1;
|
if (!fpi_byte_reader_get_uint8 (byte_reader,
|
||||||
presp->finger_list_resp.finger_num = buffer[1];
|
&presp->finger_list_resp.finger_num))
|
||||||
fingerlist = buffer + 2;
|
g_return_val_if_reached (-1);
|
||||||
|
|
||||||
|
if (presp->finger_list_resp.finger_num > FP_MAX_FINGERNUM)
|
||||||
|
{
|
||||||
|
g_warning ("Device reported too many fingers (%d)",
|
||||||
|
presp->finger_list_resp.finger_num);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
for(uint8_t num = 0; num < presp->finger_list_resp.finger_num; num++)
|
for(uint8_t num = 0; num < presp->finger_list_resp.finger_num; num++)
|
||||||
{
|
{
|
||||||
uint16_t fingerid_length;
|
uint16_t fingerid_length;
|
||||||
if (buffer_len < offset + 2)
|
FpiByteReader fingerid_reader;
|
||||||
return -1;
|
|
||||||
fingerid_length = GUINT16_FROM_LE (*(uint16_t *) (fingerlist + offset));
|
if (!fpi_byte_reader_get_uint16_le (byte_reader, &fingerid_length))
|
||||||
offset += 2;
|
g_return_val_if_reached (-1);
|
||||||
if (buffer_len < fingerid_length + offset)
|
|
||||||
return -1;
|
if (!fpi_byte_reader_get_sub_reader (byte_reader, &fingerid_reader,
|
||||||
if (gx_proto_parse_fingerid (fingerlist + offset,
|
fingerid_length))
|
||||||
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_warning ("Failed to parse finger list");
|
||||||
return -1;
|
g_return_val_if_reached (-1);
|
||||||
}
|
}
|
||||||
offset += fingerid_length;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -405,23 +444,32 @@ gx_proto_parse_body (uint16_t cmd, uint8_t *buffer, uint16_t buffer_len, pgxfp_c
|
|||||||
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)
|
||||||
{
|
{
|
||||||
if (buffer_len < 10)
|
FpiByteReader finger_reader;
|
||||||
return -1;
|
|
||||||
offset += 1;
|
if (!fpi_byte_reader_get_uint16_le (byte_reader,
|
||||||
presp->verify.rejectdetail = GUINT16_FROM_LE (*(uint16_t *) (buffer + offset));
|
&presp->verify.rejectdetail))
|
||||||
offset += 2;
|
g_return_val_if_reached (-1);
|
||||||
score = GUINT32_FROM_LE (*(uint32_t *) (buffer + offset));
|
|
||||||
offset += 4;
|
if (!fpi_byte_reader_get_uint32_le (byte_reader, &score))
|
||||||
study = buffer[offset];
|
g_return_val_if_reached (-1);
|
||||||
offset += 1;
|
|
||||||
fingerid_size = GUINT16_FROM_LE (*(uint16_t *) (buffer + offset));
|
if (!fpi_byte_reader_get_uint8 (byte_reader, &study))
|
||||||
offset += 2;
|
g_return_val_if_reached (-1);
|
||||||
if (buffer_len < fingerid_size + offset)
|
|
||||||
return -1;
|
if (!fpi_byte_reader_get_uint16_le (byte_reader, &fingerid_size))
|
||||||
if (gx_proto_parse_fingerid (buffer + offset, fingerid_size, &presp->verify.template) != 0)
|
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;
|
||||||
@@ -432,7 +480,7 @@ gx_proto_parse_body (uint16_t cmd, uint8_t *buffer, uint16_t buffer_len, pgxfp_c
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case MOC_CMD0_FINGER_MODE:
|
case MOC_CMD0_FINGER_MODE:
|
||||||
presp->finger_status.status = buffer[0];
|
presp->finger_status.status = presp->result;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@@ -450,8 +498,6 @@ static uint8_t sensor_config[26] = {
|
|||||||
int
|
int
|
||||||
gx_proto_init_sensor_config (pgxfp_sensor_cfg_t pconfig)
|
gx_proto_init_sensor_config (pgxfp_sensor_cfg_t pconfig)
|
||||||
{
|
{
|
||||||
uint32_t crc32_calc = 0;
|
|
||||||
|
|
||||||
if (!pconfig)
|
if (!pconfig)
|
||||||
return -1;
|
return -1;
|
||||||
memset (pconfig, 0, sizeof (*pconfig));
|
memset (pconfig, 0, sizeof (*pconfig));
|
||||||
@@ -460,9 +506,7 @@ gx_proto_init_sensor_config (pgxfp_sensor_cfg_t pconfig)
|
|||||||
memcpy (&pconfig->config, sensor_config, G_N_ELEMENTS (sensor_config));
|
memcpy (&pconfig->config, sensor_config, G_N_ELEMENTS (sensor_config));
|
||||||
pconfig->reserved[0] = 1;
|
pconfig->reserved[0] = 1;
|
||||||
|
|
||||||
gx_proto_crc32_calc ((uint8_t *) pconfig, sizeof (*pconfig) - PACKAGE_CRC_SIZE, (uint8_t *) &crc32_calc);
|
gx_proto_crc32_calc ((uint8_t *) pconfig, sizeof (*pconfig) - PACKAGE_CRC_SIZE, pconfig->crc_value);
|
||||||
|
|
||||||
memcpy (pconfig->crc_value, &crc32_calc, PACKAGE_CRC_SIZE);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -22,6 +22,8 @@
|
|||||||
#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)
|
||||||
|
|
||||||
@@ -105,10 +107,10 @@ 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_init
|
typedef struct _gxfp_enroll_create
|
||||||
{
|
{
|
||||||
uint8_t tid[TEMPLATE_ID_SIZE];
|
uint8_t tid[TEMPLATE_ID_SIZE];
|
||||||
} gxfp_enroll_init_t, *pgxfp_enroll_init_t;
|
} gxfp_enroll_create_t, *pgxfp_enroll_create_t;
|
||||||
|
|
||||||
#pragma pack(push, 1)
|
#pragma pack(push, 1)
|
||||||
typedef struct _template_format
|
typedef struct _template_format
|
||||||
@@ -133,7 +135,7 @@ typedef struct _template_format
|
|||||||
typedef struct _gxfp_verify
|
typedef struct _gxfp_verify
|
||||||
{
|
{
|
||||||
bool match;
|
bool match;
|
||||||
uint32_t rejectdetail;
|
uint16_t rejectdetail;
|
||||||
template_format_t template;
|
template_format_t template;
|
||||||
} gxfp_verify_t, *pgxfp_verify_t;
|
} gxfp_verify_t, *pgxfp_verify_t;
|
||||||
|
|
||||||
@@ -192,7 +194,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_init_t enroll_init;
|
gxfp_enroll_create_t enroll_create;
|
||||||
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;
|
||||||
@@ -232,13 +234,11 @@ 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 (uint8_t *buffer,
|
int gx_proto_parse_header (FpiByteReader *reader,
|
||||||
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,
|
||||||
uint8_t *buffer,
|
FpiByteReader *byte_reader,
|
||||||
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);
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,261 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <glib.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include "fpi-device.h"
|
||||||
|
#include "fpi-ssm.h"
|
||||||
|
#include "pwd.h"
|
||||||
|
#include <sys/utsname.h>
|
||||||
|
|
||||||
|
G_DECLARE_FINAL_TYPE (FpiDeviceMafpmoc, fpi_device_mafpmoc, FPI, DEVICE_MAFPMOC, FpDevice)
|
||||||
|
|
||||||
|
#define PRINT_CMD 0
|
||||||
|
#define PRINT_SSM_DEBUG 0
|
||||||
|
|
||||||
|
#define MAFP_INTERFACE_CLASS G_USB_DEVICE_CLASS_VENDOR_SPECIFIC
|
||||||
|
#define MAFP_INTERFACE_SUB_CLASS 0x01
|
||||||
|
#define MAFP_INTERFACE_PROTOCOL 0x01
|
||||||
|
|
||||||
|
/* Usb port setting */
|
||||||
|
#define MAFP_EP_BULK_OUT 0x03
|
||||||
|
#define MAFP_EP_BULK_IN 0x83
|
||||||
|
#define MAFP_EP_INT_IN 0x82
|
||||||
|
|
||||||
|
/* Command transfer timeout: ms */
|
||||||
|
#define CMD_TIMEOUT 5000
|
||||||
|
#define DATA_TIMEOUT 5000
|
||||||
|
#define CTRL_TIMEOUT 200
|
||||||
|
|
||||||
|
#define MAFP_USB_BUFFER_SIZE 512
|
||||||
|
#define PACKAGE_CRC_SIZE 2
|
||||||
|
#define PACKAGE_HEADER_SIZE 9
|
||||||
|
#define PACKAGE_DATA_SIZE_MAX (MAFP_USB_BUFFER_SIZE - PACKAGE_HEADER_SIZE - PACKAGE_CRC_SIZE)
|
||||||
|
|
||||||
|
#define TEMPLATE_ID_SIZE 2
|
||||||
|
#define TEMPLATE_UID_SIZE 128
|
||||||
|
#define DEVICE_SN_SIZE 32
|
||||||
|
#define MAX_FINGER_NUM 10
|
||||||
|
#define MAX_USER_NUM 3
|
||||||
|
#define MAX_NOTEPAD_PAGE 16
|
||||||
|
|
||||||
|
#define MOC_CMD_GET_IMAGE 0x01
|
||||||
|
#define MOC_CMD_GEN_FEATURE 0x02
|
||||||
|
#define MOC_CMD_SEARCH 0x04
|
||||||
|
#define MOC_CMD_GEN_TEMPLATE 0x05
|
||||||
|
#define MOC_CMD_SAVE_TEMPLATE 0x06
|
||||||
|
#define MOC_CMD_READ_TEMPLATE 0x07
|
||||||
|
#define MOC_CMD_DELETE_TEMPLATE 0x0C
|
||||||
|
#define MOC_CMD_EMPTY 0x0D
|
||||||
|
#define MOC_CMD_WRITE_NOTEPAD 0x18
|
||||||
|
#define MOC_CMD_READ_NOTEPAD 0x19
|
||||||
|
#define MOC_CMD_GET_TEMPLATE_NUM 0x1D
|
||||||
|
#define MOC_CMD_GET_TEMPLATE_TABLE 0x1F
|
||||||
|
#define MOC_CMD_CANCEL 0x30
|
||||||
|
#define MOC_CMD_SLEEP 0x33
|
||||||
|
#define MOC_CMD_HANDSHAKE 0x35
|
||||||
|
#define MOC_CMD_CALIBRATE 0x36
|
||||||
|
#define MOC_CMD_FACTORY_RESET 0x3B
|
||||||
|
#define MOC_CMD_FACTORY_TEST 0x56
|
||||||
|
#define MOC_CMD_MATCH_WITHFID 0x66
|
||||||
|
#define MOC_CMD_GET_MAX_ID 0x6d
|
||||||
|
#define MOC_CMD_DUPAREA_TEST 0x6f
|
||||||
|
#define MOC_CMD_SAVE_TEMPLATE_INFO 0x86
|
||||||
|
#define MOC_CMD_GET_TEMPLATE_INFO 0x87
|
||||||
|
#define MOC_CMD_GET_INIT_STATUS 0x88
|
||||||
|
|
||||||
|
#define MAFP_SUCCESS 0
|
||||||
|
#define MAFP_RE_TPL_NUM_OVERSIZE 0x0B
|
||||||
|
#define MAFP_RE_GET_IMAGE_SUCCESS 0x00
|
||||||
|
#define MAFP_RE_GET_IMAGE_NONE 0x02
|
||||||
|
/* calibrate error (un-calibrate or calibrate failed) */
|
||||||
|
#define MAFP_RE_CALIBRATE_ERROR 0x02
|
||||||
|
|
||||||
|
#define MAFP_HANDSHAKE_CODE1 'M'
|
||||||
|
#define MAFP_HANDSHAKE_CODE2 'A'
|
||||||
|
|
||||||
|
/* Default enroll stages number */
|
||||||
|
#define DEFAULT_ENROLL_SAMPLES 12
|
||||||
|
#define MAFP_ENV_ENROLL_SAMPLES "MAFP_ENROLL_SAMPLES"
|
||||||
|
|
||||||
|
#define MAFP_ENROLL_IDENTIFY_DISABLED 0
|
||||||
|
#define MAFP_ENROLL_IDENTIFY_ENABLED 1
|
||||||
|
#define MAFP_ENROLL_IDENTIFY_ONCE 2
|
||||||
|
#define MAFP_ENROLL_DUPLICATE_DELETE_DISABLED 0
|
||||||
|
#define MAFP_ENROLL_DUPLICATE_DELETE_ENABLED 1
|
||||||
|
#define MAFP_ENROLL_DUPLICATE_AREA_DENY 0
|
||||||
|
#define MAFP_ENROLL_DUPLICATE_AREA_ALLOW 1
|
||||||
|
|
||||||
|
#define MAFP_SLEEP_INT_WAIT 0
|
||||||
|
#define MAFP_SLEEP_INT_CHECK 1
|
||||||
|
#define MAFP_SLEEP_INT_REFRESH 2
|
||||||
|
|
||||||
|
#define MAFP_PRESS_WAIT_UP 0
|
||||||
|
#define MAFP_PRESS_WAIT_DOWN 1
|
||||||
|
|
||||||
|
#define MAFP_IMAGE_ERR_TRRIGER 30
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
MAPF_CMD_SEND = 0,
|
||||||
|
MAPF_CMD_RECEIVE,
|
||||||
|
MAPF_CMD_DATA_RECEIVE,
|
||||||
|
MAPF_CMD_TRANSFER_STATES,
|
||||||
|
} MapfCmdState;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
MAPF_INIT_CLEAN_EPIN = 0,
|
||||||
|
MAPF_INIT_CLEAN_EPOUT,
|
||||||
|
MAPF_INIT_CLEAN_EPIN2,
|
||||||
|
MAPF_INIT_HANDSHAKE,
|
||||||
|
MAPF_INIT_MODULE_STATUS,
|
||||||
|
MAPF_INIT_STATES,
|
||||||
|
} MapfInitState;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
MAFP_ENROLL_PWR_BTN_SHIELD_ON = 0,
|
||||||
|
MAFP_ENROLL_CHECK_EMPTY,
|
||||||
|
MAFP_ENROLL_TEMPLATE_TABLE,
|
||||||
|
MAFP_ENROLL_READ_TEMPLATE,
|
||||||
|
MAFP_ENROLL_VERIFY_GET_IMAGE,
|
||||||
|
MAFP_ENROLL_CHECK_INT_PARA,
|
||||||
|
MAFP_ENROLL_DETECT_MODE,
|
||||||
|
MAFP_ENROLL_ENABLE_INT,
|
||||||
|
MAFP_ENROLL_WAIT_INT,
|
||||||
|
MAFP_ENROLL_DISBALE_INT,
|
||||||
|
MAFP_ENROLL_REFRESH_INT_PARA,
|
||||||
|
MAFP_ENROLL_VERIFY_GENERATE_FEATURE,
|
||||||
|
MAFP_ENROLL_VERIFY_DUPLICATE_AREA,
|
||||||
|
MAFP_ENROLL_VERIFY_SEARCH,
|
||||||
|
MAFP_ENROLL_VERIFY_SEARCH_STEP, //match assigned id
|
||||||
|
MAFP_ENROLL_GET_TEMPLATE_INFO,
|
||||||
|
MAFP_ENROLL_SAVE_TEMPLATE_INFO,
|
||||||
|
MAFP_ENROLL_SAVE_TEMPLATE,
|
||||||
|
MAFP_ENROLL_DELETE_TEMPLATE_INFO_IF_FAILED,
|
||||||
|
MAFP_ENROLL_EXIT,
|
||||||
|
MAFP_ENROLL_STATES,
|
||||||
|
} MapfEnrollState;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
MAPF_IDENTIFY_PWR_BTN_SHIELD_ON = 0,
|
||||||
|
MAPF_IDENTIFY_TEMPLATE_TABLE,
|
||||||
|
MAPF_IDENTIFY_GET_STARTUP_RESULT,
|
||||||
|
MAPF_IDENTIFY_GET_IMAGE,
|
||||||
|
MAPF_IDENTIFY_CHECK_INT_PARA,
|
||||||
|
MAPF_IDENTIFY_DETECT_MODE,
|
||||||
|
MAPF_IDENTIFY_ENABLE_INT,
|
||||||
|
MAPF_IDENTIFY_WAIT_INT,
|
||||||
|
MAPF_IDENTIFY_DISBALE_INT,
|
||||||
|
MAPF_IDENTIFY_REFRESH_INT_PARA,
|
||||||
|
MAPF_IDENTIFY_GENERATE_FEATURE,
|
||||||
|
MAPF_IDENTIFY_SEARCH_STEP, //match assigned id
|
||||||
|
MAPF_IDENTIFY_GET_TEMPLATE_INFO,
|
||||||
|
MAPF_IDENTIFY_EXIT,
|
||||||
|
MAPF_IDENTIFY_STATES,
|
||||||
|
} MapfIdentifyState;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
MAPF_LIST_TEMPLATE_TABLE = 0,
|
||||||
|
MAPF_LIST_GET_TEMPLATE_INFO,
|
||||||
|
MAPF_LIST_STATES,
|
||||||
|
} MapfListState;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
MAPF_DELETE_TEMPLATE_TABLE = 0,
|
||||||
|
MAPF_DELETE_GET_TEMPLATE_INFO,
|
||||||
|
MAPF_DELETE_CLEAR_TEMPLATE_INFO,
|
||||||
|
MAPF_DELETE_TEMPLATE,
|
||||||
|
MAPF_DELETE_STATES,
|
||||||
|
} MapfDeleteState;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
MAPF_EMPTY_TEMPLATE = 0,
|
||||||
|
MAPF_EMPTY_STATES,
|
||||||
|
} MapfDeleteAllState;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
MAPF_PACK_CMD = 0x01, //cmd packet
|
||||||
|
MAPF_PACK_DATA = 0x02, //data packet, with more data packets later, must follow cmd or answer packet
|
||||||
|
MAPF_PACK_ANSWER = 0x07, //answer packet for cmd packet
|
||||||
|
MAPF_PACK_END = 0x08, //last data packet
|
||||||
|
MAPF_PACK_DATA_ANDSWER = 0x09, //answer packet for data packet
|
||||||
|
} MapfPackMark;
|
||||||
|
|
||||||
|
#pragma pack(push, 1)
|
||||||
|
typedef struct _mafp_handshake
|
||||||
|
{
|
||||||
|
uint8_t code[2];
|
||||||
|
/*uint8_t state;
|
||||||
|
uint8_t desc[16];
|
||||||
|
uint8_t ver[4];*/
|
||||||
|
} mafp_handshake_t, *pmafp_handshake_t;
|
||||||
|
|
||||||
|
typedef struct _mafp_search
|
||||||
|
{
|
||||||
|
uint8_t id[2];
|
||||||
|
uint8_t score[2];
|
||||||
|
} mafp_search_t, *pmafp_search_t;
|
||||||
|
|
||||||
|
typedef struct _mafp_tpl_table
|
||||||
|
{
|
||||||
|
uint8_t used_num;
|
||||||
|
uint8_t list[256];
|
||||||
|
} mafp_tpl_table_t, *pmafp_tpl_table_t;
|
||||||
|
|
||||||
|
typedef struct _mafp_tpl_info
|
||||||
|
{
|
||||||
|
char uid[128];
|
||||||
|
} mafp_tpl_info_t, *pmafp_tpl_info_t;
|
||||||
|
|
||||||
|
typedef struct _mafp_boot_handshake
|
||||||
|
{
|
||||||
|
char code[2];
|
||||||
|
uint8_t state;
|
||||||
|
char descrip[16];
|
||||||
|
uint32_t version;
|
||||||
|
} mafp_boot_handshake_t, *pmafp_boot_handshake_t;
|
||||||
|
|
||||||
|
typedef struct _mafp_template
|
||||||
|
{
|
||||||
|
char sn[32];
|
||||||
|
uint16_t id;
|
||||||
|
char uid[128];
|
||||||
|
} mafp_template_t, *pmafp_template_t;
|
||||||
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
typedef struct _mafp_templates
|
||||||
|
{
|
||||||
|
uint16_t index;
|
||||||
|
uint16_t total_num;
|
||||||
|
uint16_t priv_num;
|
||||||
|
mafp_template_t total_list[256];
|
||||||
|
mafp_template_t priv_list[MAX_FINGER_NUM];
|
||||||
|
GPtrArray *list;
|
||||||
|
} mafp_templates_t, *pmafp_templates_t;
|
||||||
|
|
||||||
|
typedef struct _fp_cmd_response
|
||||||
|
{
|
||||||
|
uint8_t result;
|
||||||
|
union
|
||||||
|
{
|
||||||
|
mafp_handshake_t handshake;
|
||||||
|
mafp_search_t search;
|
||||||
|
mafp_tpl_table_t tpl_table;
|
||||||
|
mafp_tpl_info_t tpl_info;
|
||||||
|
mafp_boot_handshake_t boot_handshake;
|
||||||
|
};
|
||||||
|
} mafp_cmd_response_t, *pmafp_cmd_response_t;
|
||||||
|
|
||||||
|
typedef struct _pack_header
|
||||||
|
{
|
||||||
|
uint8_t head0;
|
||||||
|
uint8_t head1;
|
||||||
|
uint8_t addr0;
|
||||||
|
uint8_t addr1;
|
||||||
|
uint8_t addr2;
|
||||||
|
uint8_t addr3;
|
||||||
|
uint8_t flag;
|
||||||
|
uint8_t frame_len0;
|
||||||
|
uint8_t frame_len1;
|
||||||
|
} pack_header, *ppack_header;
|
||||||
@@ -412,6 +412,7 @@ nb1010_dev_change_state (FpImageDevice *dev, FpiImageDeviceState state)
|
|||||||
|
|
||||||
static const FpIdEntry id_table[] = {
|
static const FpIdEntry id_table[] = {
|
||||||
{ .vid = 0x298d, .pid = 0x1010, },
|
{ .vid = 0x298d, .pid = 0x1010, },
|
||||||
|
{ .vid = 0x298d, .pid = 0x2020, },
|
||||||
{ .vid = 0, .pid = 0, .driver_data = 0 },
|
{ .vid = 0, .pid = 0, .driver_data = 0 },
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -427,7 +428,7 @@ fpi_device_nb1010_class_init (FpiDeviceNb1010Class *klass)
|
|||||||
FpImageDeviceClass *img_class = FP_IMAGE_DEVICE_CLASS (klass);
|
FpImageDeviceClass *img_class = FP_IMAGE_DEVICE_CLASS (klass);
|
||||||
|
|
||||||
dev_class->id = FP_COMPONENT;
|
dev_class->id = FP_COMPONENT;
|
||||||
dev_class->full_name = "NextBiometrics NB-1010-U";
|
dev_class->full_name = "NextBiometrics NB-1010-U/NB-2020-U";
|
||||||
dev_class->type = FP_DEVICE_TYPE_USB;
|
dev_class->type = FP_DEVICE_TYPE_USB;
|
||||||
dev_class->id_table = id_table;
|
dev_class->id_table = id_table;
|
||||||
dev_class->scan_type = FP_SCAN_TYPE_PRESS;
|
dev_class->scan_type = FP_SCAN_TYPE_PRESS;
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,246 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2022-2023 Realtek Corp.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "fpi-device.h"
|
||||||
|
#include "fpi-ssm.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#define EP_IN (2 | FPI_USB_ENDPOINT_IN)
|
||||||
|
#define EP_OUT (1 | FPI_USB_ENDPOINT_OUT)
|
||||||
|
|
||||||
|
#define EP_IN_MAX_BUF_SIZE 2048
|
||||||
|
|
||||||
|
#define FP_RTK_CMD_BULK_TOTAL_LEN 12
|
||||||
|
#define FP_RTK_CMD_BULK_LEN 2
|
||||||
|
#define FP_RTK_CMD_BULK_PARAM_LEN 4
|
||||||
|
#define FP_RTK_CMD_BULK_ADDR_LEN 4
|
||||||
|
#define FP_RTK_CMD_BULK_DATA_LEN 2
|
||||||
|
|
||||||
|
#define TEMPLATE_LEN_COMMON 35
|
||||||
|
|
||||||
|
#define SUBFACTOR_OFFSET 2
|
||||||
|
#define UID_OFFSET 3
|
||||||
|
#define UID_PAYLOAD_LEN_DEFAULT 32
|
||||||
|
|
||||||
|
/* Command transfer timeout :ms*/
|
||||||
|
#define CMD_TIMEOUT 1000
|
||||||
|
#define DATA_TIMEOUT 5000
|
||||||
|
#define STATUS_TIMEOUT 2000
|
||||||
|
|
||||||
|
#define MAX_ENROLL_SAMPLES 8
|
||||||
|
#define DEFAULT_UID_LEN 28
|
||||||
|
#define SUB_FINGER_01 0xFF
|
||||||
|
|
||||||
|
#define GET_BULK_CMD_TYPE(val) ((val & 0xC0) >> 6)
|
||||||
|
#define GET_TRANS_DATA_LEN(len_h, len_l) ((len_h << 8) | len_l)
|
||||||
|
#define GET_LEN_L(total_data_len) ((total_data_len) & 0xff)
|
||||||
|
#define GET_LEN_H(total_data_len) ((total_data_len) >> 8)
|
||||||
|
|
||||||
|
G_DECLARE_FINAL_TYPE (FpiDeviceRealtek, fpi_device_realtek, FPI, DEVICE_REALTEK, FpDevice)
|
||||||
|
|
||||||
|
typedef void (*SynCmdMsgCallback) (FpiDeviceRealtek *self,
|
||||||
|
uint8_t *buffer_in,
|
||||||
|
GError *error);
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
SynCmdMsgCallback callback;
|
||||||
|
} CommandData;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
FP_RTK_CMD_BULK_ONLY = 0,
|
||||||
|
FP_RTK_CMD_BULK_READ,
|
||||||
|
FP_RTK_CMD_BULK_WRITE,
|
||||||
|
} FpRtkCmdType;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
FP_RTK_MSG_DEFAULT = 0,
|
||||||
|
FP_RTK_MSG_NO_STATUS,
|
||||||
|
} FpRtkMsgType;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
FP_RTK_PURPOSE_VERIFY = 0x01,
|
||||||
|
FP_RTK_PURPOSE_IDENTIFY = 0x02,
|
||||||
|
FP_RTK_PURPOSE_ENROLL = 0x04,
|
||||||
|
} FpRtkPurpose;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
FP_RTK_SUCCESS = 0x0,
|
||||||
|
FP_RTK_TOO_HIGH,
|
||||||
|
FP_RTK_TOO_LOW,
|
||||||
|
FP_RTK_TOO_LEFT,
|
||||||
|
FP_RTK_TOO_RIGHT,
|
||||||
|
FP_RTK_TOO_FAST,
|
||||||
|
FP_RTK_TOO_SLOW,
|
||||||
|
FP_RTK_POOR_QUALITY,
|
||||||
|
FP_RTK_TOO_SKEWED,
|
||||||
|
FP_RTK_TOO_SHORT,
|
||||||
|
FP_RTK_MERGE_FAILURE,
|
||||||
|
FP_RTK_MATCH_FAIL,
|
||||||
|
FP_RTK_CMD_ERR,
|
||||||
|
} FpRtkInStatus;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
FP_RTK_ENROLL_GET_TEMPLATE = 0,
|
||||||
|
FP_RTK_ENROLL_BEGIN_POS,
|
||||||
|
FP_RTK_ENROLL_CAPTURE,
|
||||||
|
FP_RTK_ENROLL_FINISH_CAPTURE,
|
||||||
|
FP_RTK_ENROLL_ACCEPT_SAMPLE,
|
||||||
|
FP_RTK_ENROLL_CHECK_DUPLICATE,
|
||||||
|
FP_RTK_ENROLL_COMMIT,
|
||||||
|
FP_RTK_ENROLL_CANCEL_CAPTURE,
|
||||||
|
FP_RTK_ENROLL_NUM_STATES,
|
||||||
|
} FpRtkEnrollState;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
FP_RTK_VERIFY_GET_TEMPLATE = 0,
|
||||||
|
FP_RTK_VERIFY_CAPTURE,
|
||||||
|
FP_RTK_VERIFY_FINISH_CAPTURE,
|
||||||
|
FP_RTK_VERIFY_ACCEPT_SAMPLE,
|
||||||
|
FP_RTK_VERIFY_INDENTIFY_FEATURE,
|
||||||
|
FP_RTK_VERIFY_UPDATE_TEMPLATE,
|
||||||
|
FP_RTK_VERIFY_CANCEL_CAPTURE,
|
||||||
|
FP_RTK_VERIFY_NUM_STATES,
|
||||||
|
} FpRtkVerifyState;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
FP_RTK_DELETE_GET_POS = 0,
|
||||||
|
FP_RTK_DELETE_PRINT,
|
||||||
|
FP_RTK_DELETE_NUM_STATES,
|
||||||
|
} FpRtkDeleteState;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
FP_RTK_INIT_GET_DEVICE_INFO = 0,
|
||||||
|
FP_RTK_INIT_SELECT_OS,
|
||||||
|
FP_RTK_INIT_GET_ENROLL_NUM,
|
||||||
|
FP_RTK_INIT_NUM_STATES,
|
||||||
|
} FpRtkInitState;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
FP_RTK_CMD_SEND = 0,
|
||||||
|
FP_RTK_CMD_TRANS_DATA,
|
||||||
|
FP_RTK_CMD_GET_STATUS,
|
||||||
|
FP_RTK_CMD_NUM_STATES,
|
||||||
|
} FpRtkCmdState;
|
||||||
|
|
||||||
|
struct _FpiDeviceRealtek
|
||||||
|
{
|
||||||
|
FpDevice parent;
|
||||||
|
FpiSsm *task_ssm;
|
||||||
|
FpiSsm *cmd_ssm;
|
||||||
|
FpiUsbTransfer *cmd_transfer;
|
||||||
|
FpiUsbTransfer *data_transfer;
|
||||||
|
gint cmd_type;
|
||||||
|
FpRtkMsgType message_type;
|
||||||
|
gboolean cmd_cancellable;
|
||||||
|
gint enroll_stage;
|
||||||
|
gint max_enroll_stage;
|
||||||
|
guchar *read_data;
|
||||||
|
gsize trans_data_len;
|
||||||
|
FpRtkPurpose fp_purpose;
|
||||||
|
gint pos_index;
|
||||||
|
gint template_num;
|
||||||
|
gint template_len;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct rtk_cmd_bulk
|
||||||
|
{
|
||||||
|
uint8_t cmd[FP_RTK_CMD_BULK_LEN];
|
||||||
|
uint8_t param[FP_RTK_CMD_BULK_PARAM_LEN];
|
||||||
|
uint8_t addr[FP_RTK_CMD_BULK_ADDR_LEN];
|
||||||
|
uint8_t data_len[FP_RTK_CMD_BULK_DATA_LEN];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct rtk_cmd_ctrl
|
||||||
|
{
|
||||||
|
int direction;
|
||||||
|
uint8_t request;
|
||||||
|
uint16_t value;
|
||||||
|
uint16_t index;
|
||||||
|
uint16_t len;
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct rtk_cmd_ctrl get_device_info = {
|
||||||
|
.direction = G_USB_DEVICE_DIRECTION_DEVICE_TO_HOST,
|
||||||
|
.request = 0x07,
|
||||||
|
.value = 0x000D,
|
||||||
|
.index = 0x0000,
|
||||||
|
.len = 0x0008,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct rtk_cmd_bulk co_start_capture = {
|
||||||
|
.cmd = {0x05, 0x05},
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct rtk_cmd_bulk co_finish_capture = {
|
||||||
|
.cmd = {0x45, 0x06},
|
||||||
|
.data_len = {0x05},
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct rtk_cmd_bulk co_accept_sample = {
|
||||||
|
.cmd = {0x45, 0x08},
|
||||||
|
.data_len = {0x09},
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct rtk_cmd_bulk nor_identify_feature = {
|
||||||
|
.cmd = {0x45, 0x22},
|
||||||
|
.data_len = {0x2A},
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct rtk_cmd_bulk co_get_enroll_num = {
|
||||||
|
.cmd = {0x45, 0x0d},
|
||||||
|
.data_len = {0x02},
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct rtk_cmd_bulk co_get_template = {
|
||||||
|
.cmd = {0x45, 0x0E},
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct rtk_cmd_bulk nor_enroll_begin = {
|
||||||
|
.cmd = {0x05, 0x20},
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct rtk_cmd_bulk co_check_duplicate = {
|
||||||
|
.cmd = {0x45, 0x10},
|
||||||
|
.data_len = {0x22},
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct rtk_cmd_bulk nor_enroll_commit = {
|
||||||
|
.cmd = {0x85, 0x21},
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct rtk_cmd_bulk co_update_template = {
|
||||||
|
.cmd = {0x05, 0x11},
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct rtk_cmd_bulk co_delete_record = {
|
||||||
|
.cmd = {0x05, 0x0F},
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct rtk_cmd_bulk co_select_system = {
|
||||||
|
.cmd = {0x05, 0x13},
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct rtk_cmd_bulk co_cancel_capture = {
|
||||||
|
.cmd = {0x05, 0x07},
|
||||||
|
};
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -177,17 +177,25 @@ parse_get_enrolled_fingers_report (bmkt_msg_resp_t *msg_resp, bmkt_response_t *r
|
|||||||
|
|
||||||
if (msg_resp->payload_len < 2)
|
if (msg_resp->payload_len < 2)
|
||||||
return BMKT_UNRECOGNIZED_MESSAGE;
|
return BMKT_UNRECOGNIZED_MESSAGE;
|
||||||
|
|
||||||
/* 2 bytes per finger so calculate the total number of fingers to process*/
|
/* 2 bytes per finger so calculate the total number of fingers to process*/
|
||||||
int num_fingers = (msg_resp->payload_len) / 2;
|
int num_fingers = (msg_resp->payload_len) / 2;
|
||||||
|
|
||||||
bmkt_enrolled_fingers_resp_t *get_enrolled_fingers_resp = &resp->response.enrolled_fingers_resp;
|
bmkt_enrolled_fingers_resp_t *get_enrolled_fingers_resp = &resp->response.enrolled_fingers_resp;
|
||||||
|
|
||||||
|
if (num_fingers > (int) G_N_ELEMENTS (get_enrolled_fingers_resp->fingers))
|
||||||
|
{
|
||||||
|
g_warning ("Device reported more enrolled fingers (%d) than supported",
|
||||||
|
num_fingers);
|
||||||
|
num_fingers = G_N_ELEMENTS (get_enrolled_fingers_resp->fingers);
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0; i < num_fingers; i++)
|
for (i = 0; i < num_fingers; i++)
|
||||||
{
|
{
|
||||||
get_enrolled_fingers_resp->fingers[i].finger_id = extract8 (msg_resp->payload, &offset);
|
get_enrolled_fingers_resp->fingers[i].finger_id = extract8 (msg_resp->payload, &offset);
|
||||||
get_enrolled_fingers_resp->fingers[i].template_status = extract8 (msg_resp->payload, &offset);
|
get_enrolled_fingers_resp->fingers[i].template_status = extract8 (msg_resp->payload, &offset);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return BMKT_SUCCESS;
|
return BMKT_SUCCESS;
|
||||||
}
|
}
|
||||||
static int
|
static int
|
||||||
@@ -214,10 +222,18 @@ parse_get_enrolled_users_report (bmkt_msg_resp_t *msg_resp, bmkt_response_t *res
|
|||||||
get_enroll_templates_resp->templates[n].user_id_len = extract8 (msg_resp->payload, &offset) - 2;
|
get_enroll_templates_resp->templates[n].user_id_len = extract8 (msg_resp->payload, &offset) - 2;
|
||||||
if(get_enroll_templates_resp->templates[n].user_id_len > BMKT_MAX_USER_ID_LEN)
|
if(get_enroll_templates_resp->templates[n].user_id_len > BMKT_MAX_USER_ID_LEN)
|
||||||
return BMKT_UNRECOGNIZED_MESSAGE;
|
return BMKT_UNRECOGNIZED_MESSAGE;
|
||||||
|
if (offset >= msg_resp->payload_len)
|
||||||
|
return BMKT_CORRUPT_MESSAGE;
|
||||||
get_enroll_templates_resp->templates[n].template_status = extract8 (msg_resp->payload, &offset);
|
get_enroll_templates_resp->templates[n].template_status = extract8 (msg_resp->payload, &offset);
|
||||||
|
if (offset >= msg_resp->payload_len)
|
||||||
|
return BMKT_CORRUPT_MESSAGE;
|
||||||
get_enroll_templates_resp->templates[n].finger_id = extract8 (msg_resp->payload, &offset);
|
get_enroll_templates_resp->templates[n].finger_id = extract8 (msg_resp->payload, &offset);
|
||||||
for (i = 0; i < get_enroll_templates_resp->templates[n].user_id_len; i++)
|
for (i = 0; i < get_enroll_templates_resp->templates[n].user_id_len; i++)
|
||||||
get_enroll_templates_resp->templates[n].user_id[i] = extract8 (msg_resp->payload, &offset);
|
{
|
||||||
|
if (offset >= msg_resp->payload_len)
|
||||||
|
return BMKT_CORRUPT_MESSAGE;
|
||||||
|
get_enroll_templates_resp->templates[n].user_id[i] = extract8 (msg_resp->payload, &offset);
|
||||||
|
}
|
||||||
get_enroll_templates_resp->templates[n].user_id[i] = '\0';
|
get_enroll_templates_resp->templates[n].user_id[i] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -256,7 +272,8 @@ 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;
|
||||||
memcpy (&cmd[BMKT_MESSAGE_PAYLOAD_FIELD], payload, payload_size);
|
if (payload_size > 0)
|
||||||
|
memcpy (&cmd[BMKT_MESSAGE_PAYLOAD_FIELD], payload, payload_size);
|
||||||
|
|
||||||
*cmd_len = message_len;
|
*cmd_len = message_len;
|
||||||
|
|
||||||
@@ -266,12 +283,19 @@ bmkt_compose_message (uint8_t *cmd, int *cmd_len, uint8_t msg_id, uint8_t seq_nu
|
|||||||
int
|
int
|
||||||
bmkt_parse_message_header (uint8_t *resp_buf, int resp_len, bmkt_msg_resp_t *msg_resp)
|
bmkt_parse_message_header (uint8_t *resp_buf, int resp_len, bmkt_msg_resp_t *msg_resp)
|
||||||
{
|
{
|
||||||
|
if (resp_len < BMKT_MESSAGE_HEADER_LEN)
|
||||||
|
return BMKT_CORRUPT_MESSAGE;
|
||||||
|
|
||||||
if (resp_buf[BMKT_MESSAGE_HEADER_ID_FIELD] != BMKT_MESSAGE_HEADER_ID)
|
if (resp_buf[BMKT_MESSAGE_HEADER_ID_FIELD] != BMKT_MESSAGE_HEADER_ID)
|
||||||
return BMKT_CORRUPT_MESSAGE;
|
return BMKT_CORRUPT_MESSAGE;
|
||||||
|
|
||||||
msg_resp->seq_num = resp_buf[BMKT_MESSAGE_SEQ_NUM_FIELD];
|
msg_resp->seq_num = resp_buf[BMKT_MESSAGE_SEQ_NUM_FIELD];
|
||||||
msg_resp->msg_id = resp_buf[BMKT_MESSAGE_ID_FIELD];
|
msg_resp->msg_id = resp_buf[BMKT_MESSAGE_ID_FIELD];
|
||||||
msg_resp->payload_len = resp_buf[BMKT_MESSAGE_PAYLOAD_LEN_FIELD];
|
msg_resp->payload_len = resp_buf[BMKT_MESSAGE_PAYLOAD_LEN_FIELD];
|
||||||
|
|
||||||
|
if (msg_resp->payload_len > resp_len - BMKT_MESSAGE_PAYLOAD_FIELD)
|
||||||
|
return BMKT_CORRUPT_MESSAGE;
|
||||||
|
|
||||||
if (msg_resp->payload_len > 0)
|
if (msg_resp->payload_len > 0)
|
||||||
msg_resp->payload = &resp_buf[BMKT_MESSAGE_PAYLOAD_FIELD];
|
msg_resp->payload = &resp_buf[BMKT_MESSAGE_PAYLOAD_FIELD];
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -32,18 +32,38 @@ 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 = 0x00BD, },
|
||||||
|
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x00C2, },
|
||||||
|
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x00C4, },
|
||||||
|
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x00C6, },
|
||||||
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x00DF, },
|
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x00DF, },
|
||||||
|
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x00E9, },
|
||||||
|
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x00F0, },
|
||||||
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x00F9, },
|
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x00F9, },
|
||||||
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x00FC, },
|
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x00FC, },
|
||||||
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x00C2, },
|
|
||||||
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0100, },
|
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0100, },
|
||||||
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x00F0, },
|
|
||||||
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0103, },
|
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0103, },
|
||||||
|
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0104, },
|
||||||
|
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0106, },
|
||||||
|
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0107, },
|
||||||
|
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0108, },
|
||||||
|
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0109, },
|
||||||
|
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x010A, },
|
||||||
|
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x010D, },
|
||||||
|
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x010E, },
|
||||||
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0123, },
|
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0123, },
|
||||||
|
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0124, },
|
||||||
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0126, },
|
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0126, },
|
||||||
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0129, },
|
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0129, },
|
||||||
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0168, },
|
|
||||||
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x015F, },
|
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x015F, },
|
||||||
|
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0168, },
|
||||||
|
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0169, },
|
||||||
|
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x016C, },
|
||||||
|
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0173, },
|
||||||
|
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0174, },
|
||||||
|
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x019D, },
|
||||||
|
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x019F, },
|
||||||
|
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x01A0, },
|
||||||
|
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x01A4, },
|
||||||
{ .vid = 0, .pid = 0, .driver_data = 0 }, /* terminating entry */
|
{ .vid = 0, .pid = 0, .driver_data = 0 }, /* terminating entry */
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -105,7 +125,11 @@ cmd_receive_cb (FpiUsbTransfer *transfer,
|
|||||||
|
|
||||||
if (self->cmd_complete_on_removal)
|
if (self->cmd_complete_on_removal)
|
||||||
{
|
{
|
||||||
fpi_ssm_mark_completed (transfer->ssm);
|
if (self->delay_error)
|
||||||
|
fpi_ssm_mark_failed (transfer->ssm,
|
||||||
|
g_steal_pointer (&self->delay_error));
|
||||||
|
else
|
||||||
|
fpi_ssm_mark_completed (transfer->ssm);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -150,6 +174,14 @@ cmd_receive_cb (FpiUsbTransfer *transfer,
|
|||||||
* The original code did not! */
|
* The original code did not! */
|
||||||
if (msg_resp.msg_id == BMKT_RSP_GENERAL_ERROR)
|
if (msg_resp.msg_id == BMKT_RSP_GENERAL_ERROR)
|
||||||
{
|
{
|
||||||
|
if (msg_resp.payload_len < 2 || !msg_resp.payload)
|
||||||
|
{
|
||||||
|
fp_warn ("Received General Error with short or empty payload");
|
||||||
|
fpi_ssm_mark_failed (transfer->ssm,
|
||||||
|
fpi_device_error_new (FP_DEVICE_ERROR_PROTO));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
guint16 err;
|
guint16 err;
|
||||||
|
|
||||||
/* XXX: It is weird that this is big endian. */
|
/* XXX: It is weird that this is big endian. */
|
||||||
@@ -640,18 +672,21 @@ verify (FpDevice *device)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
identify_complete_after_finger_removal (FpiDeviceSynaptics *self)
|
identify_complete_after_finger_removal (FpiDeviceSynaptics *self, GError *error)
|
||||||
{
|
{
|
||||||
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, NULL);
|
fpi_device_identify_complete (device, error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -701,19 +736,18 @@ 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);
|
identify_complete_after_finger_removal (self, NULL);
|
||||||
}
|
}
|
||||||
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);
|
identify_complete_after_finger_removal (self, NULL);
|
||||||
}
|
}
|
||||||
else if (resp->result == BMKT_FP_DATABASE_NO_RECORD_EXISTS)
|
else if (resp->result == BMKT_FP_DATABASE_NO_RECORD_EXISTS || resp->result == BMKT_FP_DATABASE_EMPTY)
|
||||||
{
|
{
|
||||||
fp_info ("Print is not in database");
|
fp_info ("Print is not in database");
|
||||||
fpi_device_identify_complete (device,
|
identify_complete_after_finger_removal (self, fpi_device_error_new (FP_DEVICE_ERROR_DATA_NOT_FOUND));
|
||||||
fpi_device_error_new (FP_DEVICE_ERROR_DATA_NOT_FOUND));
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -749,7 +783,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);
|
identify_complete_after_finger_removal (self, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1187,7 +1221,7 @@ prob_msg_cb (FpiDeviceSynaptics *self,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (g_strcmp0 (g_getenv ("FP_DEVICE_EMULATION"), "1") == 0)
|
if (fpi_device_emulation_mode_enabled (FP_DEVICE (self)))
|
||||||
serial = g_strdup ("emulated-device");
|
serial = g_strdup ("emulated-device");
|
||||||
else
|
else
|
||||||
serial = g_usb_device_get_string_descriptor (usb_dev,
|
serial = g_usb_device_get_string_descriptor (usb_dev,
|
||||||
@@ -1237,6 +1271,12 @@ dev_probe (FpDevice *device)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!g_usb_device_reset (usb_dev, &error))
|
||||||
|
{
|
||||||
|
fp_dbg ("%s g_usb_device_reset failed %s", G_STRFUNC, error->message);
|
||||||
|
goto err_close;
|
||||||
|
}
|
||||||
|
|
||||||
if (!g_usb_device_claim_interface (usb_dev, 0, 0, &error))
|
if (!g_usb_device_claim_interface (usb_dev, 0, 0, &error))
|
||||||
goto err_close;
|
goto err_close;
|
||||||
|
|
||||||
@@ -1449,7 +1489,7 @@ suspend (FpDevice *dev)
|
|||||||
self->cmd_suspended = TRUE;
|
self->cmd_suspended = TRUE;
|
||||||
|
|
||||||
/* Cancel the current transfer.
|
/* Cancel the current transfer.
|
||||||
* The CMD SSM will go into the suspend state and signal readyness. */
|
* The CMD SSM will go into the suspend state and signal readiness. */
|
||||||
g_cancellable_cancel (self->interrupt_cancellable);
|
g_cancellable_cancel (self->interrupt_cancellable);
|
||||||
g_clear_object (&self->interrupt_cancellable);
|
g_clear_object (&self->interrupt_cancellable);
|
||||||
self->interrupt_cancellable = g_cancellable_new ();
|
self->interrupt_cancellable = g_cancellable_new ();
|
||||||
|
|||||||
@@ -127,4 +127,5 @@ 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;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -74,26 +74,26 @@ struct _FpiDeviceUpeksonly
|
|||||||
FpiSsm *loopsm;
|
FpiSsm *loopsm;
|
||||||
|
|
||||||
/* Do we really need multiple concurrent transfers? */
|
/* Do we really need multiple concurrent transfers? */
|
||||||
GCancellable *img_cancellable;
|
GCancellable *img_cancellable;
|
||||||
GPtrArray *img_transfers;
|
GPtrArray *img_transfers;
|
||||||
int num_flying;
|
int num_flying;
|
||||||
|
|
||||||
GSList *rows;
|
GSList *rows;
|
||||||
unsigned num_rows;
|
unsigned num_rows;
|
||||||
unsigned char *rowbuf;
|
unsigned char *rowbuf;
|
||||||
int rowbuf_offset;
|
int rowbuf_offset;
|
||||||
|
|
||||||
int wraparounds;
|
int wraparounds;
|
||||||
int num_blank;
|
int num_blank;
|
||||||
int num_nonblank;
|
int num_nonblank;
|
||||||
enum sonly_fs finger_state;
|
enum sonly_fs finger_state;
|
||||||
int last_seqnum;
|
int last_seqnum;
|
||||||
|
|
||||||
enum sonly_kill_transfers_action killing_transfers;
|
enum sonly_kill_transfers_action killing_transfers;
|
||||||
GError *kill_error;
|
GError *kill_error;
|
||||||
FpiSsm *kill_ssm;
|
FpiSsm *kill_ssm;
|
||||||
|
|
||||||
struct fpi_line_asmbl_ctx assembling_ctx;
|
struct fpi_line_asmbl_ctx assembling_ctx;
|
||||||
};
|
};
|
||||||
G_DECLARE_FINAL_TYPE (FpiDeviceUpeksonly, fpi_device_upeksonly, FPI,
|
G_DECLARE_FINAL_TYPE (FpiDeviceUpeksonly, fpi_device_upeksonly, FPI,
|
||||||
DEVICE_UPEKSONLY, FpImageDevice);
|
DEVICE_UPEKSONLY, FpImageDevice);
|
||||||
|
|||||||
@@ -431,6 +431,7 @@ 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 },
|
||||||
};
|
};
|
||||||
|
|||||||
+141
-29
@@ -31,10 +31,6 @@ 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
|
||||||
@@ -47,8 +43,10 @@ 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,
|
||||||
@@ -157,7 +155,8 @@ capture_reqs_cb (FpiUsbTransfer *transfer, FpDevice *device,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
upektc_img_process_image_frame (unsigned char *image_buf, unsigned char *cmd_res)
|
upektc_img_process_image_frame (unsigned char *image_buf, size_t image_buf_len,
|
||||||
|
unsigned char *cmd_res, size_t cmd_res_len)
|
||||||
{
|
{
|
||||||
int offset = 8;
|
int offset = 8;
|
||||||
int len = ((cmd_res[5] & 0x0f) << 8) | (cmd_res[6]);
|
int len = ((cmd_res[5] & 0x0f) << 8) | (cmd_res[6]);
|
||||||
@@ -170,6 +169,16 @@ upektc_img_process_image_frame (unsigned char *image_buf, unsigned char *cmd_res
|
|||||||
}
|
}
|
||||||
if (cmd_res[7] == 0x20)
|
if (cmd_res[7] == 0x20)
|
||||||
len -= 4;
|
len -= 4;
|
||||||
|
|
||||||
|
if (len <= 0 ||
|
||||||
|
(size_t) offset + (size_t) len > cmd_res_len ||
|
||||||
|
(size_t) len > image_buf_len)
|
||||||
|
{
|
||||||
|
fp_dbg ("Invalid image frame length %d (offset %d, source %zu, dest %zu)",
|
||||||
|
len, offset, cmd_res_len, image_buf_len);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
memcpy (image_buf, cmd_res + offset, len);
|
memcpy (image_buf, cmd_res + offset, len);
|
||||||
|
|
||||||
return len;
|
return len;
|
||||||
@@ -180,6 +189,7 @@ 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;
|
||||||
@@ -247,8 +257,30 @@ 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;
|
||||||
@@ -261,18 +293,20 @@ 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,
|
||||||
CAPTURE_ACK_00_28_TERM);
|
self->area_sensor ?
|
||||||
|
CAPTURE_ACK_00_28 : CAPTURE_ACK_00_28_TERM);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x1d:
|
case 0x1d:
|
||||||
/* too much horisontal movement */
|
/* too much horizontal movement */
|
||||||
fp_err ("too much horisontal movement, aborting");
|
fp_err ("too much horizontal 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,
|
||||||
CAPTURE_ACK_00_28_TERM);
|
self->area_sensor ?
|
||||||
|
CAPTURE_ACK_00_28 : CAPTURE_ACK_00_28_TERM);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@@ -283,7 +317,8 @@ 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,
|
||||||
CAPTURE_ACK_00_28_TERM);
|
self->area_sensor ?
|
||||||
|
CAPTURE_ACK_00_28 : CAPTURE_ACK_00_28_TERM);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -297,7 +332,8 @@ capture_read_data_cb (FpiUsbTransfer *transfer, FpDevice *device,
|
|||||||
case 0x24:
|
case 0x24:
|
||||||
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);
|
(self->expected_image_size * 2) - self->image_size,
|
||||||
|
data, MAX_RESPONSE_SIZE);
|
||||||
fpi_ssm_jump_to_state (transfer->ssm,
|
fpi_ssm_jump_to_state (transfer->ssm,
|
||||||
CAPTURE_ACK_FRAME);
|
CAPTURE_ACK_FRAME);
|
||||||
break;
|
break;
|
||||||
@@ -306,14 +342,22 @@ capture_read_data_cb (FpiUsbTransfer *transfer, FpDevice *device,
|
|||||||
case 0x20:
|
case 0x20:
|
||||||
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);
|
(self->expected_image_size * 2) - self->image_size,
|
||||||
BUG_ON (self->image_size != IMAGE_SIZE);
|
data, MAX_RESPONSE_SIZE);
|
||||||
|
if (self->image_size != self->expected_image_size)
|
||||||
|
{
|
||||||
|
fp_err ("Image size mismatch: got %zu, expected %zu",
|
||||||
|
self->image_size, self->expected_image_size);
|
||||||
|
fpi_ssm_mark_failed (transfer->ssm,
|
||||||
|
fpi_device_error_new (FP_DEVICE_ERROR_PROTO));
|
||||||
|
return;
|
||||||
|
}
|
||||||
fp_dbg ("Image size is %lu",
|
fp_dbg ("Image size is %lu",
|
||||||
(gulong) self->image_size);
|
(gulong) self->image_size);
|
||||||
img = fp_image_new (IMAGE_WIDTH, IMAGE_HEIGHT);
|
img = fp_image_new (img_class->img_width, img_class->img_height);
|
||||||
img->flags |= FPI_IMAGE_PARTIAL;
|
img->flags |= FPI_IMAGE_PARTIAL;
|
||||||
memcpy (img->data, self->image_bits,
|
memcpy (img->data, self->image_bits,
|
||||||
IMAGE_SIZE);
|
self->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);
|
||||||
@@ -346,8 +390,12 @@ 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:
|
||||||
upektc_img_submit_req (ssm, dev, upek2020_init_capture, sizeof (upek2020_init_capture),
|
if (self->area_sensor)
|
||||||
self->seq, capture_reqs_cb);
|
upektc_img_submit_req (ssm, dev, upek2020_init_capture_press, sizeof (upek2020_init_capture_press),
|
||||||
|
self->seq, capture_reqs_cb);
|
||||||
|
else
|
||||||
|
upektc_img_submit_req (ssm, dev, upek2020_init_capture, sizeof (upek2020_init_capture),
|
||||||
|
self->seq, capture_reqs_cb);
|
||||||
self->seq++;
|
self->seq++;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -384,12 +432,10 @@ capture_run_state (FpiSsm *ssm, FpDevice *_dev)
|
|||||||
static void
|
static void
|
||||||
capture_sm_complete (FpiSsm *ssm, FpDevice *_dev, GError *error_arg)
|
capture_sm_complete (FpiSsm *ssm, FpDevice *_dev, GError *error_arg)
|
||||||
{
|
{
|
||||||
|
g_autoptr(GError) error = error_arg;
|
||||||
FpImageDevice *dev = FP_IMAGE_DEVICE (_dev);
|
FpImageDevice *dev = FP_IMAGE_DEVICE (_dev);
|
||||||
FpiDeviceUpektcImg *self = FPI_DEVICE_UPEKTC_IMG (_dev);
|
FpiDeviceUpektcImg *self = FPI_DEVICE_UPEKTC_IMG (_dev);
|
||||||
|
|
||||||
g_autoptr(GError) error = error_arg;
|
|
||||||
|
|
||||||
|
|
||||||
/* Note: We assume that the error is a cancellation in the deactivation case */
|
/* Note: We assume that the error is a cancellation in the deactivation case */
|
||||||
if (self->deactivating)
|
if (self->deactivating)
|
||||||
start_deactivation (dev);
|
start_deactivation (dev);
|
||||||
@@ -470,6 +516,7 @@ deactivate_sm_complete (FpiSsm *ssm, FpDevice *_dev, GError *error)
|
|||||||
|
|
||||||
fp_dbg ("Deactivate completed");
|
fp_dbg ("Deactivate completed");
|
||||||
|
|
||||||
|
g_clear_pointer (&self->image_bits, g_free);
|
||||||
self->deactivating = FALSE;
|
self->deactivating = FALSE;
|
||||||
fpi_image_device_deactivate_complete (dev, error);
|
fpi_image_device_deactivate_complete (dev, error);
|
||||||
}
|
}
|
||||||
@@ -513,15 +560,82 @@ 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)
|
||||||
{
|
{
|
||||||
if (!error)
|
FpImageDevice *dev = FP_IMAGE_DEVICE (device);
|
||||||
fpi_ssm_next_state (transfer->ssm);
|
FpiDeviceUpektcImg *self = FPI_DEVICE_UPEKTC_IMG (dev);
|
||||||
else
|
unsigned char *data = self->response;
|
||||||
fpi_ssm_mark_failed (transfer->ssm, error);
|
|
||||||
|
if (error)
|
||||||
|
{
|
||||||
|
fpi_ssm_mark_failed (transfer->ssm, error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data[12] == 0x06 && data[13] == 0x14) /* if get_info */
|
||||||
|
{
|
||||||
|
FpImageDeviceClass *img_class = FP_IMAGE_DEVICE_GET_CLASS (dev);
|
||||||
|
uint16_t width = (data[51] << 8) | data[50];
|
||||||
|
uint16_t height = (data[53] << 8) | data[52];
|
||||||
|
|
||||||
|
self->area_sensor = !(data[49] & 0x80);
|
||||||
|
|
||||||
|
switch (width)
|
||||||
|
{
|
||||||
|
case 256:
|
||||||
|
fp_dbg ("Sensor type : TCS1x, width x height: %hu x %hu", width, height); /* 360x256 --- 270x192 must be set */
|
||||||
|
BUG_ON (height != 360);
|
||||||
|
img_class->img_width = 192;
|
||||||
|
img_class->img_height = 270;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 208:
|
||||||
|
fp_dbg ("Sensor type : TCS2, width x height: %hu x %hu", width, height); /* 288x208 --- 216x156 must be set */
|
||||||
|
BUG_ON (height != 288);
|
||||||
|
img_class->img_width = 156;
|
||||||
|
img_class->img_height = 216;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 248:
|
||||||
|
fp_dbg ("Sensor type : TCS3, width x height: %hu x %hu", width, height); /* 360x248 --- 270x186 must be set */
|
||||||
|
BUG_ON (height != 360);
|
||||||
|
img_class->img_width = 186;
|
||||||
|
img_class->img_height = 270;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 192:
|
||||||
|
fp_dbg ("Sensor type : TCS4x, width x height: %hu x %hu", width, height); /* 512x192 --- 384x144 must be set */
|
||||||
|
BUG_ON (height != 512);
|
||||||
|
img_class->img_width = 144;
|
||||||
|
img_class->img_height = 384;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 144:
|
||||||
|
fp_dbg ("Sensor type : TCS5x, width x height: %hu x %hu", width, height); /* 512x144 --- 384x108 must be set */
|
||||||
|
BUG_ON (height != 512);
|
||||||
|
img_class->img_width = 108;
|
||||||
|
img_class->img_height = 384;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
fp_dbg ("Sensor type : Unknown");
|
||||||
|
|
||||||
|
fpi_ssm_mark_failed (transfer->ssm,
|
||||||
|
fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
|
||||||
|
"Unknown sensor type (reported size %dx%d)",
|
||||||
|
width, height));
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
self->expected_image_size = img_class->img_width * img_class->img_height;
|
||||||
|
g_clear_pointer (&self->image_bits, g_free);
|
||||||
|
self->image_bits = g_malloc0 (self->expected_image_size * 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
fpi_ssm_next_state (transfer->ssm);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -616,7 +730,6 @@ 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 */
|
||||||
@@ -627,7 +740,6 @@ 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -687,6 +799,6 @@ fpi_device_upektc_img_class_init (FpiDeviceUpektcImgClass *klass)
|
|||||||
|
|
||||||
img_class->bz3_threshold = 20;
|
img_class->bz3_threshold = 20;
|
||||||
|
|
||||||
img_class->img_width = IMAGE_WIDTH;
|
img_class->img_width = -1;
|
||||||
img_class->img_height = IMAGE_HEIGHT;
|
img_class->img_height = -1;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -75,6 +75,22 @@ 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 */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -196,8 +196,9 @@ 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) (udata)->callback (dev, \
|
#define READ_MSG_DATA_CB_ERR(dev, udata, error) \
|
||||||
READ_MSG_CMD, 0, 0, NULL, 0, (udata)->user_data, error)
|
(udata)->callback (dev, \
|
||||||
|
READ_MSG_CMD, 0, 0, NULL, 0, (udata)->user_data, error)
|
||||||
|
|
||||||
static void
|
static void
|
||||||
busy_ack_sent_cb (FpiUsbTransfer *transfer, FpDevice *device,
|
busy_ack_sent_cb (FpiUsbTransfer *transfer, FpDevice *device,
|
||||||
@@ -307,6 +308,14 @@ __handle_incoming_msg (FpDevice *device,
|
|||||||
fp_dbg ("non-zero bytes in cmd response");
|
fp_dbg ("non-zero bytes in cmd response");
|
||||||
|
|
||||||
innerlen = innerbuf[1] | (innerbuf[2] << 8);
|
innerlen = innerbuf[1] | (innerbuf[2] << 8);
|
||||||
|
if (innerlen < 3 || innerlen > len - 3)
|
||||||
|
{
|
||||||
|
fp_warn ("cmd response has invalid inner length (%d)", innerlen);
|
||||||
|
error = fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
|
||||||
|
"CMD response has invalid inner length");
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
innerlen = innerlen - 3;
|
innerlen = innerlen - 3;
|
||||||
_subcmd = innerbuf[5];
|
_subcmd = innerbuf[5];
|
||||||
fp_dbg ("device responds to subcmd %x with %d bytes", _subcmd, innerlen);
|
fp_dbg ("device responds to subcmd %x with %d bytes", _subcmd, innerlen);
|
||||||
@@ -1243,7 +1252,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;
|
||||||
@@ -1295,7 +1304,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, data, data_len);
|
transfer = alloc_send_cmd28_transfer (dev, 0x03, msg, msg_len);
|
||||||
|
|
||||||
g_free (msg);
|
g_free (msg);
|
||||||
|
|
||||||
@@ -1341,7 +1350,6 @@ 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,6 +1359,14 @@ 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;
|
||||||
@@ -1439,7 +1455,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 hat wrong command sequence"));
|
"Response had wrong command sequence"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+97
-67
@@ -20,8 +20,8 @@
|
|||||||
|
|
||||||
#define FP_COMPONENT "uru4000"
|
#define FP_COMPONENT "uru4000"
|
||||||
|
|
||||||
#include <nss.h>
|
#include <openssl/evp.h>
|
||||||
#include <pk11pub.h>
|
#include <openssl/err.h>
|
||||||
|
|
||||||
#include "drivers_api.h"
|
#include "drivers_api.h"
|
||||||
|
|
||||||
@@ -148,10 +148,7 @@ struct _FpiDeviceUru4000
|
|||||||
int fwfixer_offset;
|
int fwfixer_offset;
|
||||||
unsigned char fwfixer_value;
|
unsigned char fwfixer_value;
|
||||||
|
|
||||||
CK_MECHANISM_TYPE cipher;
|
EVP_CIPHER_CTX *cipher_ctx;
|
||||||
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);
|
||||||
@@ -246,13 +243,29 @@ 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];
|
unsigned char respdata[CR_LENGTH * 2];
|
||||||
PK11Context *ctx;
|
|
||||||
int outlen;
|
int outlen;
|
||||||
|
|
||||||
if (error)
|
if (error)
|
||||||
@@ -261,17 +274,39 @@ 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 */
|
||||||
ctx = PK11_CreateContextBySymKey (self->cipher, CKA_ENCRYPT,
|
if (!EVP_EncryptUpdate (self->cipher_ctx, respdata, &outlen, transfer->buffer, CR_LENGTH))
|
||||||
self->symkey, self->param);
|
|
||||||
if (PK11_CipherOp (ctx, respdata, &outlen, CR_LENGTH, transfer->buffer, CR_LENGTH) != SECSuccess ||
|
|
||||||
PK11_Finalize (ctx) != SECSuccess)
|
|
||||||
{
|
{
|
||||||
fp_err ("Failed to encrypt challenge data");
|
fpi_ssm_mark_failed (ssm, openssl_device_error ());
|
||||||
error = fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO, "Failed to encrypt challenge data");
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (outlen != CR_LENGTH)
|
||||||
|
{
|
||||||
|
error = fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
|
||||||
|
"Unexpected encrypted buffer length (%d"
|
||||||
|
"instead of %d)",
|
||||||
|
outlen, CR_LENGTH);
|
||||||
|
fpi_ssm_mark_failed (ssm, g_steal_pointer (&error));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!EVP_EncryptFinal_ex (self->cipher_ctx, respdata + outlen, &outlen))
|
||||||
|
{
|
||||||
|
fpi_ssm_mark_failed (ssm, openssl_device_error ());
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
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);
|
||||||
@@ -317,6 +352,7 @@ 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)
|
||||||
@@ -551,7 +587,10 @@ image_transfer_cb (FpiUsbTransfer *transfer, FpDevice *dev,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
self->img_data = g_memdup (transfer->buffer, sizeof (struct uru4k_image));
|
struct uru4k_image *img = g_memdup2 (transfer->buffer, sizeof (struct uru4k_image));
|
||||||
|
|
||||||
|
img->num_lines = GUINT16_FROM_LE (img->num_lines);
|
||||||
|
self->img_data = g_steal_pointer (&img);
|
||||||
self->img_data_actual_length = transfer->actual_length;
|
self->img_data_actual_length = transfer->actual_length;
|
||||||
fpi_ssm_next_state (ssm);
|
fpi_ssm_next_state (ssm);
|
||||||
}
|
}
|
||||||
@@ -642,10 +681,10 @@ calc_dev2 (struct uru4k_image *img)
|
|||||||
static void
|
static void
|
||||||
imaging_run_state (FpiSsm *ssm, FpDevice *_dev)
|
imaging_run_state (FpiSsm *ssm, FpDevice *_dev)
|
||||||
{
|
{
|
||||||
|
g_autoptr(FpImage) fpimg = NULL;
|
||||||
FpImageDevice *dev = FP_IMAGE_DEVICE (_dev);
|
FpImageDevice *dev = FP_IMAGE_DEVICE (_dev);
|
||||||
FpiDeviceUru4000 *self = FPI_DEVICE_URU4000 (_dev);
|
FpiDeviceUru4000 *self = FPI_DEVICE_URU4000 (_dev);
|
||||||
struct uru4k_image *img = self->img_data;
|
struct uru4k_image *img = self->img_data;
|
||||||
FpImage *fpimg;
|
|
||||||
uint32_t key;
|
uint32_t key;
|
||||||
uint8_t flags, num_lines;
|
uint8_t flags, num_lines;
|
||||||
int i, r, to, dev2;
|
int i, r, to, dev2;
|
||||||
@@ -702,9 +741,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 |= self->last_reg_rd[1] << 8;
|
key |= (uint32_t) self->last_reg_rd[1] << 8;
|
||||||
key |= self->last_reg_rd[2] << 16;
|
key |= (uint32_t) self->last_reg_rd[2] << 16;
|
||||||
key |= self->last_reg_rd[3] << 24;
|
key |= (uint32_t) 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);
|
||||||
@@ -716,6 +755,17 @@ imaging_run_state (FpiSsm *ssm, FpDevice *_dev)
|
|||||||
if (num_lines == 0)
|
if (num_lines == 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
/* num_lines is device-supplied; make sure decoding this block stays
|
||||||
|
* within the captured image buffer (IMAGE_HEIGHT rows). */
|
||||||
|
if ((size_t) self->img_lines_done + num_lines > IMAGE_HEIGHT)
|
||||||
|
{
|
||||||
|
fp_err ("bad captured image: block %d (%d lines) overflows buffer",
|
||||||
|
self->img_block, num_lines);
|
||||||
|
fpi_ssm_mark_failed (ssm,
|
||||||
|
fpi_device_error_new (FP_DEVICE_ERROR_PROTO));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
fp_dbg ("%d %02x %d", self->img_block, flags,
|
fp_dbg ("%d %02x %d", self->img_block, flags,
|
||||||
num_lines);
|
num_lines);
|
||||||
if (flags & BLOCKF_CHANGE_KEY)
|
if (flags & BLOCKF_CHANGE_KEY)
|
||||||
@@ -759,6 +809,17 @@ imaging_run_state (FpiSsm *ssm, FpDevice *_dev)
|
|||||||
num_lines = img->block_info[i].num_lines;
|
num_lines = img->block_info[i].num_lines;
|
||||||
if (num_lines == 0)
|
if (num_lines == 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
if ((size_t) r + num_lines > IMAGE_HEIGHT ||
|
||||||
|
(size_t) to + (size_t) num_lines * IMAGE_WIDTH > fpimg->width * fpimg->height)
|
||||||
|
{
|
||||||
|
fp_err ("bad captured image: block %d (%d lines) overflows buffer",
|
||||||
|
i, num_lines);
|
||||||
|
fpi_ssm_mark_failed (ssm,
|
||||||
|
fpi_device_error_new (FP_DEVICE_ERROR_PROTO));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
memcpy (&fpimg->data[to], &img->data[r][0],
|
memcpy (&fpimg->data[to], &img->data[r][0],
|
||||||
num_lines * IMAGE_WIDTH);
|
num_lines * IMAGE_WIDTH);
|
||||||
if (!(flags & BLOCKF_NOT_PRESENT))
|
if (!(flags & BLOCKF_NOT_PRESENT))
|
||||||
@@ -775,7 +836,8 @@ imaging_run_state (FpiSsm *ssm, FpDevice *_dev)
|
|||||||
*/
|
*/
|
||||||
if (self->profile->image_not_flipped)
|
if (self->profile->image_not_flipped)
|
||||||
fpimg->flags |= FPI_IMAGE_V_FLIPPED | FPI_IMAGE_H_FLIPPED;
|
fpimg->flags |= FPI_IMAGE_V_FLIPPED | FPI_IMAGE_H_FLIPPED;
|
||||||
fpi_image_device_image_captured (dev, fpimg);
|
|
||||||
|
fpi_image_device_image_captured (dev, g_steal_pointer (&fpimg));
|
||||||
|
|
||||||
if (self->activate_state == FPI_IMAGE_DEVICE_STATE_CAPTURE)
|
if (self->activate_state == FPI_IMAGE_DEVICE_STATE_CAPTURE)
|
||||||
fpi_ssm_jump_to_state (ssm, IMAGING_CAPTURE);
|
fpi_ssm_jump_to_state (ssm, IMAGING_CAPTURE);
|
||||||
@@ -1145,6 +1207,12 @@ init_run_state (FpiSsm *ssm, FpDevice *_dev)
|
|||||||
static void
|
static void
|
||||||
activate_initsm_complete (FpiSsm *ssm, FpDevice *dev, GError *error)
|
activate_initsm_complete (FpiSsm *ssm, FpDevice *dev, GError *error)
|
||||||
{
|
{
|
||||||
|
FpiDeviceUru4000 *self = FPI_DEVICE_URU4000 (dev);
|
||||||
|
|
||||||
|
g_clear_pointer (&self->scanpwr_irq_timeout, g_source_destroy);
|
||||||
|
self->irq_cb_data = NULL;
|
||||||
|
self->irq_cb = NULL;
|
||||||
|
|
||||||
fpi_image_device_activate_complete (FP_IMAGE_DEVICE (dev), error);
|
fpi_image_device_activate_complete (FP_IMAGE_DEVICE (dev), error);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1269,8 +1337,6 @@ 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);
|
||||||
@@ -1342,25 +1408,11 @@ dev_init (FpImageDevice *dev)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Disable loading p11-kit's user configuration */
|
|
||||||
g_setenv ("P11_KIT_NO_USER_CONFIG", "1", TRUE);
|
|
||||||
|
|
||||||
/* Initialise NSS early */
|
|
||||||
rv = NSS_NoDB_Init (".");
|
|
||||||
if (rv != SECSuccess)
|
|
||||||
{
|
|
||||||
fp_err ("could not initialise NSS");
|
|
||||||
fpi_image_device_open_complete (dev,
|
|
||||||
fpi_device_error_new_msg (FP_DEVICE_ERROR_GENERAL,
|
|
||||||
"Could not initialise NSS"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
self = FPI_DEVICE_URU4000 (dev);
|
self = FPI_DEVICE_URU4000 (dev);
|
||||||
|
|
||||||
g_clear_pointer (&self->rand, g_rand_free);
|
g_clear_pointer (&self->rand, g_rand_free);
|
||||||
self->rand = g_rand_new ();
|
self->rand = g_rand_new ();
|
||||||
if (g_strcmp0 (g_getenv ("FP_DEVICE_EMULATION"), "1") == 0)
|
if (fpi_device_emulation_mode_enabled (FP_DEVICE (dev)))
|
||||||
g_rand_set_seed (self->rand, 0xFACADE);
|
g_rand_set_seed (self->rand, 0xFACADE);
|
||||||
|
|
||||||
driver_data = fpi_device_get_driver_data (FP_DEVICE (dev));
|
driver_data = fpi_device_get_driver_data (FP_DEVICE (dev));
|
||||||
@@ -1368,35 +1420,17 @@ dev_init (FpImageDevice *dev)
|
|||||||
self->interface = g_usb_interface_get_number (iface);
|
self->interface = g_usb_interface_get_number (iface);
|
||||||
|
|
||||||
/* Set up encryption */
|
/* Set up encryption */
|
||||||
self->cipher = CKM_AES_ECB;
|
if (!(self->cipher_ctx = EVP_CIPHER_CTX_new ()))
|
||||||
self->slot = PK11_GetBestSlot (self->cipher, NULL);
|
|
||||||
if (self->slot == NULL)
|
|
||||||
{
|
{
|
||||||
fp_err ("could not get encryption slot");
|
fpi_image_device_open_complete (dev, openssl_device_error ());
|
||||||
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;
|
|
||||||
item.data = (unsigned char *) crkey;
|
if (!EVP_EncryptInit_ex (self->cipher_ctx, EVP_aes_128_ecb (), NULL, crkey, NULL))
|
||||||
item.len = sizeof (crkey);
|
|
||||||
self->symkey = PK11_ImportSymKey (self->slot,
|
|
||||||
self->cipher,
|
|
||||||
PK11_OriginUnwrap,
|
|
||||||
CKA_ENCRYPT,
|
|
||||||
&item, NULL);
|
|
||||||
if (self->symkey == NULL)
|
|
||||||
{
|
{
|
||||||
fp_err ("failed to import key into NSS");
|
fpi_image_device_open_complete (dev, openssl_device_error ());
|
||||||
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);
|
||||||
}
|
}
|
||||||
@@ -1407,12 +1441,8 @@ dev_deinit (FpImageDevice *dev)
|
|||||||
GError *error = NULL;
|
GError *error = NULL;
|
||||||
FpiDeviceUru4000 *self = FPI_DEVICE_URU4000 (dev);
|
FpiDeviceUru4000 *self = FPI_DEVICE_URU4000 (dev);
|
||||||
|
|
||||||
if (self->symkey)
|
g_clear_pointer (&self->cipher_ctx, EVP_CIPHER_CTX_free);
|
||||||
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);
|
g_clear_pointer (&self->rand, g_rand_free);
|
||||||
|
|||||||
@@ -119,7 +119,7 @@ async_abort_callback (FpiUsbTransfer *transfer, FpDevice *device,
|
|||||||
|
|
||||||
/* In normal case endpoint is empty */
|
/* In normal case endpoint is empty */
|
||||||
if (g_error_matches (error, G_USB_DEVICE_ERROR, G_USB_DEVICE_ERROR_TIMED_OUT) ||
|
if (g_error_matches (error, G_USB_DEVICE_ERROR, G_USB_DEVICE_ERROR_TIMED_OUT) ||
|
||||||
(g_strcmp0 (g_getenv ("FP_DEVICE_EMULATION"), "1") == 0 && transfer->actual_length == 0))
|
(fpi_device_emulation_mode_enabled (device) && transfer->actual_length == 0))
|
||||||
{
|
{
|
||||||
g_clear_error (&error);
|
g_clear_error (&error);
|
||||||
fpi_ssm_next_state (transfer->ssm);
|
fpi_ssm_next_state (transfer->ssm);
|
||||||
@@ -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_malloc (self->memory);
|
self->lines_buffer = g_malloc0 (self->memory);
|
||||||
self->bytes = 0;
|
self->bytes = 0;
|
||||||
|
|
||||||
/* Finger is on the scanner */
|
/* Finger is on the scanner */
|
||||||
@@ -589,12 +589,15 @@ activate_ssm (FpiSsm *ssm, FpDevice *dev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Increase buffer size while it's insufficient */
|
/* Increase buffer size while it's insufficient */
|
||||||
while (self->bytes + VFS_USB_BUFFER_SIZE > self->memory)
|
while (self->memory < self->bytes + VFS_USB_BUFFER_SIZE)
|
||||||
{
|
{
|
||||||
self->memory <<= 1;
|
int pre_memory = self->memory;
|
||||||
|
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 */
|
||||||
|
|||||||
@@ -184,8 +184,8 @@ async_send_cb (FpiUsbTransfer *transfer, FpDevice *device,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
g_error_free (error);
|
|
||||||
fp_dbg ("Ignoring send error: %s", error->message);
|
fp_dbg ("Ignoring send error: %s", error->message);
|
||||||
|
g_error_free (error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* Reset ignore_error flag */
|
/* Reset ignore_error flag */
|
||||||
@@ -708,6 +708,9 @@ vfs_check_contrast (FpDeviceVfs101 *vdev)
|
|||||||
int y;
|
int y;
|
||||||
long int count = 0;
|
long int count = 0;
|
||||||
|
|
||||||
|
if (vdev->height <= 0)
|
||||||
|
return;
|
||||||
|
|
||||||
/* Check difference from byte 4 to byte 5 for verify contrast of image */
|
/* Check difference from byte 4 to byte 5 for verify contrast of image */
|
||||||
for (y = 0; y < vdev->height; y++)
|
for (y = 0; y < vdev->height; y++)
|
||||||
count = count + vdev->buffer[offset (5, y)] - vdev->buffer[offset (4, y)];
|
count = count + vdev->buffer[offset (5, y)] - vdev->buffer[offset (4, y)];
|
||||||
|
|||||||
@@ -85,6 +85,7 @@ enum {
|
|||||||
static void
|
static void
|
||||||
m_loop_state (FpiSsm *ssm, FpDevice *_dev)
|
m_loop_state (FpiSsm *ssm, FpDevice *_dev)
|
||||||
{
|
{
|
||||||
|
g_autoptr(GError) error = NULL;
|
||||||
FpImageDevice *dev = FP_IMAGE_DEVICE (_dev);
|
FpImageDevice *dev = FP_IMAGE_DEVICE (_dev);
|
||||||
FpDeviceVfs301 *self = FPI_DEVICE_VFS301 (_dev);
|
FpDeviceVfs301 *self = FPI_DEVICE_VFS301 (_dev);
|
||||||
|
|
||||||
@@ -101,10 +102,16 @@ m_loop_state (FpiSsm *ssm, FpDevice *_dev)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case M_CHECK_PRINT:
|
case M_CHECK_PRINT:
|
||||||
if (!vfs301_proto_peek_event (self))
|
{
|
||||||
fpi_ssm_jump_to_state (ssm, M_WAIT_PRINT);
|
int rv = vfs301_proto_peek_event (self, &error);
|
||||||
else
|
|
||||||
fpi_ssm_next_state (ssm);
|
if (rv == VFS301_FAILURE)
|
||||||
|
fpi_ssm_mark_failed (ssm, error);
|
||||||
|
else if (rv == VFS301_ONGOING)
|
||||||
|
fpi_ssm_jump_to_state (ssm, M_WAIT_PRINT);
|
||||||
|
else
|
||||||
|
fpi_ssm_next_state (ssm);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case M_READ_PRINT_START:
|
case M_READ_PRINT_START:
|
||||||
@@ -121,8 +128,11 @@ m_loop_state (FpiSsm *ssm, FpDevice *_dev)
|
|||||||
case M_READ_PRINT_POLL:
|
case M_READ_PRINT_POLL:
|
||||||
{
|
{
|
||||||
int rv = vfs301_proto_process_event_poll (self);
|
int rv = vfs301_proto_process_event_poll (self);
|
||||||
g_assert (rv != VFS301_FAILURE);
|
|
||||||
if (rv == VFS301_ONGOING)
|
if (rv == VFS301_FAILURE)
|
||||||
|
fpi_ssm_mark_failed (ssm,
|
||||||
|
fpi_device_error_new (FP_DEVICE_ERROR_PROTO));
|
||||||
|
else if (rv == VFS301_ONGOING)
|
||||||
fpi_ssm_jump_to_state (ssm, M_READ_PRINT_WAIT);
|
fpi_ssm_jump_to_state (ssm, M_READ_PRINT_WAIT);
|
||||||
else
|
else
|
||||||
fpi_ssm_next_state (ssm);
|
fpi_ssm_next_state (ssm);
|
||||||
|
|||||||
@@ -133,7 +133,8 @@ void vfs301_proto_deinit (FpDeviceVfs301 *dev);
|
|||||||
void vfs301_proto_request_fingerprint (FpDeviceVfs301 *dev);
|
void vfs301_proto_request_fingerprint (FpDeviceVfs301 *dev);
|
||||||
|
|
||||||
/** returns 0 if no event is ready, or 1 if there is one... */
|
/** returns 0 if no event is ready, or 1 if there is one... */
|
||||||
int vfs301_proto_peek_event (FpDeviceVfs301 *dev);
|
int vfs301_proto_peek_event (FpDeviceVfs301 *dev,
|
||||||
|
GError **error);
|
||||||
void vfs301_proto_process_event_start (FpDeviceVfs301 *dev);
|
void vfs301_proto_process_event_start (FpDeviceVfs301 *dev);
|
||||||
int vfs301_proto_process_event_poll (FpDeviceVfs301 *dev);
|
int vfs301_proto_process_event_poll (FpDeviceVfs301 *dev);
|
||||||
|
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ usb_print_packet (int dir, GError *error, const guint8 *data, int length)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void
|
static gboolean
|
||||||
usb_recv (FpDeviceVfs301 *dev, guint8 endpoint, int max_bytes, FpiUsbTransfer **out, GError **error)
|
usb_recv (FpDeviceVfs301 *dev, guint8 endpoint, int max_bytes, FpiUsbTransfer **out, GError **error)
|
||||||
{
|
{
|
||||||
GError *err = NULL;
|
GError *err = NULL;
|
||||||
@@ -87,10 +87,14 @@ usb_recv (FpDeviceVfs301 *dev, guint8 endpoint, int max_bytes, FpiUsbTransfer **
|
|||||||
if (!error)
|
if (!error)
|
||||||
g_warning ("Unhandled receive error: %s", err->message);
|
g_warning ("Unhandled receive error: %s", err->message);
|
||||||
g_propagate_error (error, err);
|
g_propagate_error (error, err);
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (out)
|
if (out)
|
||||||
*out = g_steal_pointer (&transfer);
|
*out = g_steal_pointer (&transfer);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
FP_GNUC_ACCESS (read_only, 2, 3)
|
FP_GNUC_ACCESS (read_only, 2, 3)
|
||||||
@@ -344,7 +348,11 @@ vfs301_extract_image (FpDeviceVfs301 *vfs, guint8 *output, int *output_height
|
|||||||
int last_line;
|
int last_line;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
g_assert (vfs->scanline_count >= 1);
|
if (vfs->scanline_count < 1 || scanlines == NULL)
|
||||||
|
{
|
||||||
|
*output_height = 0;
|
||||||
|
g_return_if_reached ();
|
||||||
|
}
|
||||||
|
|
||||||
*output_height = 1;
|
*output_height = 1;
|
||||||
memcpy (output, scanlines, VFS301_FP_OUTPUT_WIDTH);
|
memcpy (output, scanlines, VFS301_FP_OUTPUT_WIDTH);
|
||||||
@@ -432,7 +440,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_memdup (x, sizeof (x)), sizeof (x)
|
#define RAW_DATA(x) g_memdup2 (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))
|
||||||
|
|
||||||
@@ -443,7 +451,8 @@ vfs301_proto_process_data (FpDeviceVfs301 *dev, int first_block, const guint8 *b
|
|||||||
|
|
||||||
if (first_block)
|
if (first_block)
|
||||||
{
|
{
|
||||||
g_assert (len >= VFS301_FP_FRAME_SIZE);
|
if (len < VFS301_FP_FRAME_SIZE)
|
||||||
|
g_return_val_if_reached (img_process_data (first_block, dev, buf, 0));
|
||||||
|
|
||||||
/* Skip bytes until start_sequence is found */
|
/* Skip bytes until start_sequence is found */
|
||||||
for (i = 0; i < VFS301_FP_FRAME_SIZE; i++, buf++, len--)
|
for (i = 0; i < VFS301_FP_FRAME_SIZE; i++, buf++, len--)
|
||||||
@@ -462,26 +471,25 @@ vfs301_proto_request_fingerprint (FpDeviceVfs301 *dev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
vfs301_proto_peek_event (FpDeviceVfs301 *dev)
|
vfs301_proto_peek_event (FpDeviceVfs301 *dev,
|
||||||
|
GError **error)
|
||||||
{
|
{
|
||||||
g_autoptr(GError) error = NULL;
|
|
||||||
g_autoptr(FpiUsbTransfer) transfer = NULL;
|
g_autoptr(FpiUsbTransfer) transfer = NULL;
|
||||||
|
|
||||||
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};
|
||||||
|
|
||||||
USB_SEND (0x17, -1);
|
USB_SEND (0x17, -1);
|
||||||
usb_recv (dev, VFS301_RECEIVE_ENDPOINT_CTRL, 7, &transfer, &error);
|
if (!usb_recv (dev, VFS301_RECEIVE_ENDPOINT_CTRL, 7, &transfer, error))
|
||||||
|
return -1;
|
||||||
/* XXX: This is obviously not a sane error handling! */
|
|
||||||
g_assert (!error);
|
|
||||||
|
|
||||||
if (memcmp (transfer->buffer, no_event, sizeof (no_event)) == 0)
|
if (memcmp (transfer->buffer, no_event, sizeof (no_event)) == 0)
|
||||||
return 0;
|
return 0;
|
||||||
else if (memcmp (transfer->buffer, got_event, sizeof (no_event)) == 0)
|
else if (memcmp (transfer->buffer, got_event, sizeof (no_event)) == 0)
|
||||||
return 1;
|
return 1;
|
||||||
else
|
|
||||||
g_assert_not_reached ();
|
g_set_error (error, FP_DEVICE_ERROR_PROTO, 0, "Unexpected event response");
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* XXX: We sometimes need to receive data on from two endpoints at the same
|
/* XXX: We sometimes need to receive data on from two endpoints at the same
|
||||||
|
|||||||
@@ -273,7 +273,8 @@ on_stream_read_cb (GObject *source_object,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_INVALID_DATA, "Got empty data");
|
g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_INVALID_DATA,
|
||||||
|
"Got empty data");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -77,6 +77,7 @@ dev_identify (FpDevice *dev)
|
|||||||
&idx))
|
&idx))
|
||||||
{
|
{
|
||||||
match = g_ptr_array_index (prints, idx);
|
match = g_ptr_array_index (prints, idx);
|
||||||
|
fp_print_set_finger (new_scan, fp_print_get_finger (match));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!self->match_reported)
|
if (!self->match_reported)
|
||||||
|
|||||||
@@ -165,11 +165,7 @@ process_cmds (FpDeviceVirtualDevice * self,
|
|||||||
{
|
{
|
||||||
g_autofree gchar *cmd = NULL;
|
g_autofree gchar *cmd = NULL;
|
||||||
|
|
||||||
/* TODO: g_ptr_array_steal_index requires GLib 2.58, we depend on 2.56 */
|
cmd = g_ptr_array_steal_index (self->pending_commands, 0);
|
||||||
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);
|
||||||
|
|
||||||
/* These are always processed. */
|
/* These are always processed. */
|
||||||
@@ -526,8 +522,8 @@ dev_verify (FpDevice *dev)
|
|||||||
|
|
||||||
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;
|
||||||
|
|
||||||
@@ -549,6 +545,9 @@ dev_verify (FpDevice *dev)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
success = fp_print_equal (print, new_scan);
|
success = fp_print_equal (print, new_scan);
|
||||||
|
|
||||||
|
if (success)
|
||||||
|
fp_print_set_finger (new_scan, fp_print_get_finger (print));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!self->match_reported)
|
if (!self->match_reported)
|
||||||
@@ -556,7 +555,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,
|
||||||
new_scan,
|
g_steal_pointer (&new_scan),
|
||||||
NULL);
|
NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -733,7 +732,13 @@ dev_deinit (FpDevice *dev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!self->keep_alive)
|
if (!self->keep_alive)
|
||||||
stop_listener (self);
|
{
|
||||||
|
stop_listener (self);
|
||||||
|
self->supports_cancellation = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
self->enroll_stages_passed = 0;
|
||||||
|
self->match_reported = FALSE;
|
||||||
|
|
||||||
fpi_device_close_complete (dev, NULL);
|
fpi_device_close_complete (dev, NULL);
|
||||||
}
|
}
|
||||||
@@ -766,6 +771,7 @@ 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;
|
||||||
|
|
||||||
@@ -781,5 +787,18 @@ fpi_device_virtual_device_class_init (FpDeviceVirtualDeviceClass *klass)
|
|||||||
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);
|
fpi_device_class_auto_initialize_features (dev_class);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -191,12 +191,12 @@ on_listener_connected (FpiDeviceVirtualListener *listener,
|
|||||||
|
|
||||||
switch (state)
|
switch (state)
|
||||||
{
|
{
|
||||||
case FPI_IMAGE_DEVICE_STATE_IDLE:
|
|
||||||
case FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON:
|
case FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON:
|
||||||
case FPI_IMAGE_DEVICE_STATE_CAPTURE:
|
case FPI_IMAGE_DEVICE_STATE_CAPTURE:
|
||||||
case FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_OFF:
|
|
||||||
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_INACTIVE:
|
||||||
case FPI_IMAGE_DEVICE_STATE_ACTIVATING:
|
case FPI_IMAGE_DEVICE_STATE_ACTIVATING:
|
||||||
case FPI_IMAGE_DEVICE_STATE_DEACTIVATING:
|
case FPI_IMAGE_DEVICE_STATE_DEACTIVATING:
|
||||||
@@ -310,6 +310,7 @@ 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";
|
||||||
@@ -321,4 +322,17 @@ 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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "fpi-compat.h"
|
#include "fpi-compat.h"
|
||||||
|
#include "fpi-enums.h"
|
||||||
#include "fpi-assembling.h"
|
#include "fpi-assembling.h"
|
||||||
#include "fpi-device.h"
|
#include "fpi-device.h"
|
||||||
#include "fpi-image-device.h"
|
#include "fpi-image-device.h"
|
||||||
|
|||||||
+10
-17
@@ -67,32 +67,26 @@ enum {
|
|||||||
static guint signals[LAST_SIGNAL] = { 0 };
|
static guint signals[LAST_SIGNAL] = { 0 };
|
||||||
|
|
||||||
static const char *
|
static const char *
|
||||||
get_drivers_whitelist_env (void)
|
get_drivers_allowlist_env (void)
|
||||||
{
|
{
|
||||||
return g_getenv ("FP_DRIVERS_WHITELIST");
|
return g_getenv ("FP_DRIVERS_ALLOWLIST");
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
is_driver_allowed (const gchar *driver)
|
is_driver_allowed (const gchar *driver)
|
||||||
{
|
{
|
||||||
g_auto(GStrv) whitelisted_drivers = NULL;
|
g_auto(GStrv) allowlisted_drivers = NULL;
|
||||||
const char *fp_drivers_whitelist_env;
|
const char *fp_drivers_allowlist_env;
|
||||||
int i;
|
|
||||||
|
|
||||||
g_return_val_if_fail (driver, TRUE);
|
g_return_val_if_fail (driver, TRUE);
|
||||||
|
|
||||||
fp_drivers_whitelist_env = get_drivers_whitelist_env ();
|
fp_drivers_allowlist_env = get_drivers_allowlist_env ();
|
||||||
|
|
||||||
if (!fp_drivers_whitelist_env)
|
if (!fp_drivers_allowlist_env)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
whitelisted_drivers = g_strsplit (fp_drivers_whitelist_env, ":", -1);
|
allowlisted_drivers = g_strsplit (fp_drivers_allowlist_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
|
||||||
@@ -291,11 +285,10 @@ 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);
|
g_slist_free_full (g_steal_pointer (&priv->sources), (GDestroyNotify) g_source_destroy);
|
||||||
|
|
||||||
@@ -365,7 +358,7 @@ fp_context_init (FpContext *self)
|
|||||||
|
|
||||||
priv->drivers = fpi_get_driver_types ();
|
priv->drivers = fpi_get_driver_types ();
|
||||||
|
|
||||||
if (get_drivers_whitelist_env ())
|
if (get_drivers_allowlist_env ())
|
||||||
{
|
{
|
||||||
for (i = 0; i < priv->drivers->len;)
|
for (i = 0; i < priv->drivers->len;)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ typedef struct
|
|||||||
FpDeviceType type;
|
FpDeviceType type;
|
||||||
|
|
||||||
GUsbDevice *usb_device;
|
GUsbDevice *usb_device;
|
||||||
const gchar *virtual_env;
|
gchar *virtual_env;
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
gchar *spidev_path;
|
gchar *spidev_path;
|
||||||
@@ -111,8 +111,6 @@ 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 */
|
||||||
@@ -128,7 +126,6 @@ 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_suspend (FpDevice *device);
|
||||||
void fpi_device_resume (FpDevice *device);
|
void fpi_device_resume (FpDevice *device);
|
||||||
|
|||||||
+114
-32
@@ -128,6 +128,9 @@ fp_device_task_cancelled_cb (GCancellable *cancellable, FpDevice *self)
|
|||||||
{
|
{
|
||||||
FpDevicePrivate *priv = fp_device_get_instance_private (self);
|
FpDevicePrivate *priv = fp_device_get_instance_private (self);
|
||||||
|
|
||||||
|
g_debug ("Task cancellable for operation %d cancelled",
|
||||||
|
priv->current_action);
|
||||||
|
|
||||||
g_cancellable_cancel (priv->current_cancellable);
|
g_cancellable_cancel (priv->current_cancellable);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -221,7 +224,7 @@ fp_device_finalize (GObject *object)
|
|||||||
|
|
||||||
g_clear_pointer (&priv->temp_timeout, g_source_destroy);
|
g_clear_pointer (&priv->temp_timeout, g_source_destroy);
|
||||||
|
|
||||||
g_slist_free_full (priv->sources, (GDestroyNotify) g_source_destroy);
|
g_clear_slist (&priv->sources, (GDestroyNotify) g_source_destroy);
|
||||||
|
|
||||||
g_clear_pointer (&priv->current_idle_cancel_source, g_source_destroy);
|
g_clear_pointer (&priv->current_idle_cancel_source, g_source_destroy);
|
||||||
g_clear_pointer (&priv->current_task_idle_return_source, g_source_destroy);
|
g_clear_pointer (&priv->current_task_idle_return_source, g_source_destroy);
|
||||||
@@ -292,14 +295,14 @@ fp_device_get_property (GObject *object,
|
|||||||
|
|
||||||
case PROP_FPI_UDEV_DATA_SPIDEV:
|
case PROP_FPI_UDEV_DATA_SPIDEV:
|
||||||
if (cls->type == FP_DEVICE_TYPE_UDEV)
|
if (cls->type == FP_DEVICE_TYPE_UDEV)
|
||||||
g_value_set_string (value, g_strdup (priv->udev_data.spidev_path));
|
g_value_set_string (value, priv->udev_data.spidev_path);
|
||||||
else
|
else
|
||||||
g_value_set_string (value, NULL);
|
g_value_set_string (value, NULL);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PROP_FPI_UDEV_DATA_HIDRAW:
|
case PROP_FPI_UDEV_DATA_HIDRAW:
|
||||||
if (cls->type == FP_DEVICE_TYPE_UDEV)
|
if (cls->type == FP_DEVICE_TYPE_UDEV)
|
||||||
g_value_set_string (value, g_strdup (priv->udev_data.hidraw_path));
|
g_value_set_string (value, priv->udev_data.hidraw_path);
|
||||||
else
|
else
|
||||||
g_value_set_string (value, NULL);
|
g_value_set_string (value, NULL);
|
||||||
break;
|
break;
|
||||||
@@ -483,6 +486,9 @@ fp_device_class_init (FpDeviceClass *klass)
|
|||||||
NULL,
|
NULL,
|
||||||
G_PARAM_STATIC_STRINGS | G_PARAM_READABLE);
|
G_PARAM_STATIC_STRINGS | G_PARAM_READABLE);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* FpDevice:open: (getter is_open):
|
||||||
|
*/
|
||||||
properties[PROP_OPEN] =
|
properties[PROP_OPEN] =
|
||||||
g_param_spec_boolean ("open",
|
g_param_spec_boolean ("open",
|
||||||
"Opened",
|
"Opened",
|
||||||
@@ -1088,14 +1094,23 @@ fp_device_resume_finish (FpDevice *device,
|
|||||||
return g_task_propagate_boolean (G_TASK (result), error);
|
return g_task_propagate_boolean (G_TASK (result), error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
enroll_data_free (FpEnrollData *data)
|
||||||
|
{
|
||||||
|
if (data->enroll_progress_destroy)
|
||||||
|
data->enroll_progress_destroy (data->enroll_progress_data);
|
||||||
|
data->enroll_progress_data = NULL;
|
||||||
|
g_clear_object (&data->print);
|
||||||
|
g_free (data);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* fp_device_enroll:
|
* fp_device_enroll:
|
||||||
* @device: a #FpDevice
|
* @device: a #FpDevice
|
||||||
* @template_print: (transfer floating): a #FpPrint
|
* @template_print: (transfer floating): a #FpPrint
|
||||||
* @cancellable: (nullable): a #GCancellable, or %NULL
|
* @cancellable: (nullable): a #GCancellable, or %NULL
|
||||||
* @progress_cb: (nullable) (scope notified): progress reporting callback
|
* @progress_cb: (nullable) (closure progress_data) (scope notified): progress reporting callback
|
||||||
* @progress_data: (closure progress_cb): user data for @progress_cb
|
* @progress_data: user data for @progress_cb
|
||||||
* @progress_destroy: (destroy progress_data): Destroy notify for @progress_data
|
* @progress_destroy: (destroy progress_data): Destroy notify for @progress_data
|
||||||
* @callback: (scope async): the function to call on completion
|
* @callback: (scope async): the function to call on completion
|
||||||
* @user_data: the data to pass to @callback
|
* @user_data: the data to pass to @callback
|
||||||
@@ -1172,10 +1187,6 @@ fp_device_enroll (FpDevice *device,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
priv->current_action = FPI_DEVICE_ACTION_ENROLL;
|
|
||||||
priv->current_task = g_steal_pointer (&task);
|
|
||||||
setup_task_cancellable (device);
|
|
||||||
|
|
||||||
fpi_device_update_temp (device, TRUE);
|
fpi_device_update_temp (device, TRUE);
|
||||||
if (priv->temp_current == FP_TEMPERATURE_HOT)
|
if (priv->temp_current == FP_TEMPERATURE_HOT)
|
||||||
{
|
{
|
||||||
@@ -1184,6 +1195,10 @@ fp_device_enroll (FpDevice *device,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
priv->current_action = FPI_DEVICE_ACTION_ENROLL;
|
||||||
|
priv->current_task = g_steal_pointer (&task);
|
||||||
|
setup_task_cancellable (device);
|
||||||
|
|
||||||
data = g_new0 (FpEnrollData, 1);
|
data = g_new0 (FpEnrollData, 1);
|
||||||
data->print = g_object_ref_sink (template_print);
|
data->print = g_object_ref_sink (template_print);
|
||||||
data->enroll_progress_cb = progress_cb;
|
data->enroll_progress_cb = progress_cb;
|
||||||
@@ -1217,13 +1232,57 @@ fp_device_enroll_finish (FpDevice *device,
|
|||||||
return g_task_propagate_pointer (G_TASK (result), error);
|
return g_task_propagate_pointer (G_TASK (result), error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
match_data_free (FpMatchData *data)
|
||||||
|
{
|
||||||
|
g_clear_object (&data->print);
|
||||||
|
g_clear_object (&data->match);
|
||||||
|
g_clear_error (&data->error);
|
||||||
|
|
||||||
|
if (data->match_destroy)
|
||||||
|
data->match_destroy (data->match_data);
|
||||||
|
data->match_data = NULL;
|
||||||
|
|
||||||
|
g_clear_object (&data->enrolled_print);
|
||||||
|
g_clear_pointer (&data->gallery, g_ptr_array_unref);
|
||||||
|
|
||||||
|
g_free (data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_verify_identification (GObject *source_object,
|
||||||
|
GAsyncResult *result,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
g_autoptr(FpPrint) match = NULL;
|
||||||
|
g_autoptr(FpPrint) print = NULL;
|
||||||
|
g_autoptr(GError) error = NULL;
|
||||||
|
g_autoptr(GTask) verify_task = G_TASK (g_steal_pointer (&user_data));
|
||||||
|
FpDevice *device = FP_DEVICE (source_object);
|
||||||
|
FpMatchData *match_data;
|
||||||
|
|
||||||
|
if (!fp_device_identify_finish (device, result, &match, &print, &error))
|
||||||
|
{
|
||||||
|
g_task_return_error (verify_task, g_steal_pointer (&error));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
match_data = g_new0 (FpMatchData, 1);
|
||||||
|
match_data->print = g_steal_pointer (&print);
|
||||||
|
|
||||||
|
g_task_set_task_data (verify_task, g_steal_pointer (&match_data),
|
||||||
|
(GDestroyNotify) match_data_free);
|
||||||
|
|
||||||
|
g_task_return_int (verify_task, match ? FPI_MATCH_SUCCESS : FPI_MATCH_FAIL);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* fp_device_verify:
|
* fp_device_verify:
|
||||||
* @device: a #FpDevice
|
* @device: a #FpDevice
|
||||||
* @enrolled_print: a #FpPrint to verify
|
* @enrolled_print: a #FpPrint to verify
|
||||||
* @cancellable: (nullable): a #GCancellable, or %NULL
|
* @cancellable: (nullable): a #GCancellable, or %NULL
|
||||||
* @match_cb: (nullable) (scope notified): match reporting callback
|
* @match_cb: (nullable) (scope notified) (closure match_data): match reporting callback
|
||||||
* @match_data: (closure match_cb): user data for @match_cb
|
* @match_data: user data for @match_cb
|
||||||
* @match_destroy: (destroy match_data): Destroy notify for @match_data
|
* @match_destroy: (destroy match_data): Destroy notify for @match_data
|
||||||
* @callback: the function to call on completion
|
* @callback: the function to call on completion
|
||||||
* @user_data: the data to pass to @callback
|
* @user_data: the data to pass to @callback
|
||||||
@@ -1265,7 +1324,8 @@ fp_device_verify (FpDevice *device,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!cls->verify || !(priv->features & FP_DEVICE_FEATURE_VERIFY))
|
if ((!cls->verify && !cls->identify) ||
|
||||||
|
!(priv->features & FP_DEVICE_FEATURE_VERIFY))
|
||||||
{
|
{
|
||||||
g_task_return_error (task,
|
g_task_return_error (task,
|
||||||
fpi_device_error_new_msg (FP_DEVICE_ERROR_NOT_SUPPORTED,
|
fpi_device_error_new_msg (FP_DEVICE_ERROR_NOT_SUPPORTED,
|
||||||
@@ -1273,9 +1333,20 @@ fp_device_verify (FpDevice *device,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
priv->current_action = FPI_DEVICE_ACTION_VERIFY;
|
if (!cls->verify)
|
||||||
priv->current_task = g_steal_pointer (&task);
|
{
|
||||||
setup_task_cancellable (device);
|
g_autoptr(GPtrArray) prints = NULL;
|
||||||
|
|
||||||
|
g_assert (cls->identify);
|
||||||
|
|
||||||
|
prints = g_ptr_array_sized_new (1);
|
||||||
|
g_ptr_array_add (prints, enrolled_print);
|
||||||
|
|
||||||
|
fp_device_identify (device, prints, cancellable, match_cb, match_data,
|
||||||
|
match_destroy, on_verify_identification,
|
||||||
|
g_steal_pointer (&task));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
fpi_device_update_temp (device, TRUE);
|
fpi_device_update_temp (device, TRUE);
|
||||||
if (priv->temp_current == FP_TEMPERATURE_HOT)
|
if (priv->temp_current == FP_TEMPERATURE_HOT)
|
||||||
@@ -1285,6 +1356,10 @@ fp_device_verify (FpDevice *device,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
priv->current_action = FPI_DEVICE_ACTION_VERIFY;
|
||||||
|
priv->current_task = g_steal_pointer (&task);
|
||||||
|
setup_task_cancellable (device);
|
||||||
|
|
||||||
data = g_new0 (FpMatchData, 1);
|
data = g_new0 (FpMatchData, 1);
|
||||||
data->enrolled_print = g_object_ref (enrolled_print);
|
data->enrolled_print = g_object_ref (enrolled_print);
|
||||||
data->match_cb = match_cb;
|
data->match_cb = match_cb;
|
||||||
@@ -1348,8 +1423,8 @@ fp_device_verify_finish (FpDevice *device,
|
|||||||
* @device: a #FpDevice
|
* @device: a #FpDevice
|
||||||
* @prints: (element-type FpPrint) (transfer none): #GPtrArray of #FpPrint
|
* @prints: (element-type FpPrint) (transfer none): #GPtrArray of #FpPrint
|
||||||
* @cancellable: (nullable): a #GCancellable, or %NULL
|
* @cancellable: (nullable): a #GCancellable, or %NULL
|
||||||
* @match_cb: (nullable) (scope notified): match reporting callback
|
* @match_cb: (nullable) (scope notified) (closure match_data): match reporting callback
|
||||||
* @match_data: (closure match_cb): user data for @match_cb
|
* @match_data: user data for @match_cb
|
||||||
* @match_destroy: (destroy match_data): Destroy notify for @match_data
|
* @match_destroy: (destroy match_data): Destroy notify for @match_data
|
||||||
* @callback: the function to call on completion
|
* @callback: the function to call on completion
|
||||||
* @user_data: the data to pass to @callback
|
* @user_data: the data to pass to @callback
|
||||||
@@ -1372,7 +1447,6 @@ fp_device_identify (FpDevice *device,
|
|||||||
FpDevicePrivate *priv = fp_device_get_instance_private (device);
|
FpDevicePrivate *priv = fp_device_get_instance_private (device);
|
||||||
FpDeviceClass *cls = FP_DEVICE_GET_CLASS (device);
|
FpDeviceClass *cls = FP_DEVICE_GET_CLASS (device);
|
||||||
FpMatchData *data;
|
FpMatchData *data;
|
||||||
int i;
|
|
||||||
|
|
||||||
task = g_task_new (device, cancellable, callback, user_data);
|
task = g_task_new (device, cancellable, callback, user_data);
|
||||||
if (g_task_return_error_if_cancelled (task))
|
if (g_task_return_error_if_cancelled (task))
|
||||||
@@ -1400,9 +1474,13 @@ fp_device_identify (FpDevice *device,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
priv->current_action = FPI_DEVICE_ACTION_IDENTIFY;
|
if (prints == NULL)
|
||||||
priv->current_task = g_steal_pointer (&task);
|
{
|
||||||
setup_task_cancellable (device);
|
g_task_return_error (task,
|
||||||
|
fpi_device_error_new_msg (FP_DEVICE_ERROR_DATA_INVALID,
|
||||||
|
"Invalid gallery array"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
fpi_device_update_temp (device, TRUE);
|
fpi_device_update_temp (device, TRUE);
|
||||||
if (priv->temp_current == FP_TEMPERATURE_HOT)
|
if (priv->temp_current == FP_TEMPERATURE_HOT)
|
||||||
@@ -1412,14 +1490,18 @@ fp_device_identify (FpDevice *device,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
priv->current_action = FPI_DEVICE_ACTION_IDENTIFY;
|
||||||
|
priv->current_task = g_steal_pointer (&task);
|
||||||
|
setup_task_cancellable (device);
|
||||||
|
|
||||||
data = g_new0 (FpMatchData, 1);
|
data = g_new0 (FpMatchData, 1);
|
||||||
/* We cannot store the gallery directly, because the ptr array may not own
|
/* We cannot store the gallery directly, because the ptr array may not own
|
||||||
* a reference to each print. Also, the caller could in principle modify the
|
* a reference to each print. Also, the caller could in principle modify the
|
||||||
* GPtrArray afterwards.
|
* GPtrArray afterwards.
|
||||||
*/
|
*/
|
||||||
data->gallery = g_ptr_array_new_full (prints->len, g_object_unref);
|
data->gallery = g_ptr_array_copy (prints, (GCopyFunc) g_object_ref, NULL);
|
||||||
for (i = 0; i < prints->len; i++)
|
g_ptr_array_set_free_func (data->gallery, g_object_unref);
|
||||||
g_ptr_array_add (data->gallery, g_object_ref (g_ptr_array_index (prints, i)));
|
|
||||||
data->match_cb = match_cb;
|
data->match_cb = match_cb;
|
||||||
data->match_data = match_data;
|
data->match_data = match_data;
|
||||||
data->match_destroy = match_destroy;
|
data->match_destroy = match_destroy;
|
||||||
@@ -1525,10 +1607,6 @@ fp_device_capture (FpDevice *device,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
priv->current_action = FPI_DEVICE_ACTION_CAPTURE;
|
|
||||||
priv->current_task = g_steal_pointer (&task);
|
|
||||||
setup_task_cancellable (device);
|
|
||||||
|
|
||||||
fpi_device_update_temp (device, TRUE);
|
fpi_device_update_temp (device, TRUE);
|
||||||
if (priv->temp_current == FP_TEMPERATURE_HOT)
|
if (priv->temp_current == FP_TEMPERATURE_HOT)
|
||||||
{
|
{
|
||||||
@@ -1537,6 +1615,10 @@ fp_device_capture (FpDevice *device,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
priv->current_action = FPI_DEVICE_ACTION_CAPTURE;
|
||||||
|
priv->current_task = g_steal_pointer (&task);
|
||||||
|
setup_task_cancellable (device);
|
||||||
|
|
||||||
priv->wait_for_finger = wait_for_finger;
|
priv->wait_for_finger = wait_for_finger;
|
||||||
|
|
||||||
cls->capture (device);
|
cls->capture (device);
|
||||||
@@ -1909,8 +1991,8 @@ fp_device_enroll_sync (FpDevice *device,
|
|||||||
* @device: a #FpDevice
|
* @device: a #FpDevice
|
||||||
* @enrolled_print: a #FpPrint to verify
|
* @enrolled_print: a #FpPrint to verify
|
||||||
* @cancellable: (nullable): a #GCancellable, or %NULL
|
* @cancellable: (nullable): a #GCancellable, or %NULL
|
||||||
* @match_cb: (nullable) (scope call): match reporting callback
|
* @match_cb: (nullable) (scope call) (closure match_data): match reporting callback
|
||||||
* @match_data: (closure match_cb): user data for @match_cb
|
* @match_data: user data for @match_cb
|
||||||
* @match: (out): Whether the user presented the correct finger
|
* @match: (out): Whether the user presented the correct finger
|
||||||
* @print: (out) (transfer full) (nullable): Location to store the scanned print, or %NULL to ignore
|
* @print: (out) (transfer full) (nullable): Location to store the scanned print, or %NULL to ignore
|
||||||
* @error: Return location for errors, or %NULL to ignore
|
* @error: Return location for errors, or %NULL to ignore
|
||||||
@@ -1949,8 +2031,8 @@ fp_device_verify_sync (FpDevice *device,
|
|||||||
* @device: a #FpDevice
|
* @device: a #FpDevice
|
||||||
* @prints: (element-type FpPrint) (transfer none): #GPtrArray of #FpPrint
|
* @prints: (element-type FpPrint) (transfer none): #GPtrArray of #FpPrint
|
||||||
* @cancellable: (nullable): a #GCancellable, or %NULL
|
* @cancellable: (nullable): a #GCancellable, or %NULL
|
||||||
* @match_cb: (nullable) (scope call): match reporting callback
|
* @match_cb: (nullable) (scope call) (closure match_data): match reporting callback
|
||||||
* @match_data: (closure match_cb): user data for @match_cb
|
* @match_data: user data for @match_cb
|
||||||
* @match: (out) (transfer full) (nullable): Location for the matched #FpPrint, or %NULL
|
* @match: (out) (transfer full) (nullable): Location for the matched #FpPrint, or %NULL
|
||||||
* @print: (out) (transfer full) (nullable): Location for the new #FpPrint, or %NULL
|
* @print: (out) (transfer full) (nullable): Location for the new #FpPrint, or %NULL
|
||||||
* @error: Return location for errors, or %NULL to ignore
|
* @error: Return location for errors, or %NULL to ignore
|
||||||
|
|||||||
@@ -113,6 +113,8 @@ 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.
|
||||||
@@ -122,6 +124,7 @@ 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;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -89,7 +89,6 @@ fp_image_device_cancel_action (FpDevice *device)
|
|||||||
/* We can only cancel capture operations, in that case, deactivate and return
|
/* We can only cancel capture operations, in that case, deactivate and return
|
||||||
* an error immediately. */
|
* an error immediately. */
|
||||||
if (action == FPI_DEVICE_ACTION_ENROLL ||
|
if (action == FPI_DEVICE_ACTION_ENROLL ||
|
||||||
action == FPI_DEVICE_ACTION_VERIFY ||
|
|
||||||
action == FPI_DEVICE_ACTION_IDENTIFY ||
|
action == FPI_DEVICE_ACTION_IDENTIFY ||
|
||||||
action == FPI_DEVICE_ACTION_CAPTURE)
|
action == FPI_DEVICE_ACTION_CAPTURE)
|
||||||
fpi_image_device_deactivate (self, TRUE);
|
fpi_image_device_deactivate (self, TRUE);
|
||||||
@@ -217,7 +216,6 @@ fp_image_device_class_init (FpImageDeviceClass *klass)
|
|||||||
fp_device_class->open = fp_image_device_open;
|
fp_device_class->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;
|
||||||
fp_device_class->verify = fp_image_device_start_capture_action;
|
|
||||||
fp_device_class->identify = fp_image_device_start_capture_action;
|
fp_device_class->identify = fp_image_device_start_capture_action;
|
||||||
fp_device_class->capture = fp_image_device_start_capture_action;
|
fp_device_class->capture = fp_image_device_start_capture_action;
|
||||||
|
|
||||||
|
|||||||
+120
-76
@@ -20,9 +20,11 @@
|
|||||||
|
|
||||||
#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>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -158,60 +160,65 @@ fp_image_init (FpImage *self)
|
|||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
GAsyncReadyCallback user_cb;
|
|
||||||
struct fp_minutiae *minutiae;
|
struct fp_minutiae *minutiae;
|
||||||
gint width, height;
|
|
||||||
gdouble ppmm;
|
|
||||||
FpiImageFlags flags;
|
|
||||||
guchar *image;
|
|
||||||
guchar *binarized;
|
guchar *binarized;
|
||||||
} DetectMinutiaeData;
|
FpiImageFlags flags;
|
||||||
|
unsigned char *image;
|
||||||
|
gboolean image_changed;
|
||||||
|
} DetectMinutiaeNbisData;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
fp_image_detect_minutiae_free (DetectMinutiaeData *data)
|
fp_image_detect_minutiae_free (DetectMinutiaeNbisData *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);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
G_DEFINE_AUTOPTR_CLEANUP_FUNC (DetectMinutiaeNbisData, fp_image_detect_minutiae_free)
|
||||||
fp_image_detect_minutiae_cb (GObject *source_object,
|
|
||||||
GAsyncResult *res,
|
|
||||||
gpointer user_data)
|
static gboolean
|
||||||
|
fp_image_detect_minutiae_nbis_finish (FpImage *self,
|
||||||
|
GTask *task,
|
||||||
|
GError **error)
|
||||||
{
|
{
|
||||||
GTask *task = G_TASK (res);
|
g_autoptr(DetectMinutiaeNbisData) data = NULL;
|
||||||
FpImage *image;
|
|
||||||
DetectMinutiaeData *data = g_task_get_task_data (task);
|
|
||||||
|
|
||||||
if (!g_task_had_error (task))
|
data = g_task_propagate_pointer (task, error);
|
||||||
|
|
||||||
|
if (data != NULL)
|
||||||
{
|
{
|
||||||
gint i;
|
self->flags = data->flags;
|
||||||
image = FP_IMAGE (source_object);
|
|
||||||
|
|
||||||
image->flags = data->flags;
|
if (data->image_changed)
|
||||||
|
{
|
||||||
|
g_clear_pointer (&self->data, g_free);
|
||||||
|
self->data = g_steal_pointer (&data->image);
|
||||||
|
}
|
||||||
|
|
||||||
g_clear_pointer (&image->data, g_free);
|
g_clear_pointer (&self->binarized, g_free);
|
||||||
image->data = g_steal_pointer (&data->image);
|
self->binarized = g_steal_pointer (&data->binarized);
|
||||||
|
|
||||||
g_clear_pointer (&image->binarized, g_free);
|
g_clear_pointer (&self->minutiae, g_ptr_array_unref);
|
||||||
image->binarized = g_steal_pointer (&data->binarized);
|
self->minutiae = g_ptr_array_new_full (data->minutiae->num,
|
||||||
|
(GDestroyNotify) free_minutia);
|
||||||
|
|
||||||
g_clear_pointer (&image->minutiae, g_ptr_array_unref);
|
for (int i = 0; i < data->minutiae->num; i++)
|
||||||
image->minutiae = g_ptr_array_new_full (data->minutiae->num,
|
g_ptr_array_add (self->minutiae,
|
||||||
(GDestroyNotify) free_minutia);
|
|
||||||
|
|
||||||
for (i = 0; i < data->minutiae->num; i++)
|
|
||||||
g_ptr_array_add (image->minutiae,
|
|
||||||
g_steal_pointer (&data->minutiae->list[i]));
|
g_steal_pointer (&data->minutiae->list[i]));
|
||||||
|
|
||||||
/* Don't let it delete anything. */
|
/* Don't let free_minutiae delete the minutiae that we now own. */
|
||||||
data->minutiae->num = 0;
|
data->minutiae->num = 0;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data->user_cb)
|
return FALSE;
|
||||||
data->user_cb (source_object, res, user_data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -264,70 +271,83 @@ invert_colors (guint8 *data, gint width, gint height)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
fp_image_detect_minutiae_thread_func (GTask *task,
|
fp_image_detect_minutiae_nbis_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;
|
||||||
DetectMinutiaeData *data = task_data;
|
g_autoptr(DetectMinutiaeNbisData) ret_data = NULL;
|
||||||
struct fp_minutiae *minutiae = NULL;
|
g_autoptr(GTask) thread_task = g_steal_pointer (&task);
|
||||||
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 guchar *bdata = NULL;
|
g_autofree LFSPARMS *lfsparms = 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 (data->flags & FPI_IMAGE_H_FLIPPED)
|
if (self->flags & FPI_IMAGE_H_FLIPPED)
|
||||||
hflip (data->image, data->width, data->height);
|
hflip (image, self->width, self->height);
|
||||||
|
|
||||||
if (data->flags & FPI_IMAGE_V_FLIPPED)
|
if (self->flags & FPI_IMAGE_V_FLIPPED)
|
||||||
vflip (data->image, data->width, data->height);
|
vflip (image, self->width, self->height);
|
||||||
|
|
||||||
if (data->flags & FPI_IMAGE_COLORS_INVERTED)
|
if (self->flags & FPI_IMAGE_COLORS_INVERTED)
|
||||||
invert_colors (data->image, data->width, data->height);
|
invert_colors (image, self->width, self->height);
|
||||||
|
|
||||||
data->flags &= ~(FPI_IMAGE_H_FLIPPED | FPI_IMAGE_V_FLIPPED | FPI_IMAGE_COLORS_INVERTED);
|
lfsparms = g_memdup2 (&g_lfsparms_V2, sizeof (LFSPARMS));
|
||||||
|
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 (&minutiae, &quality_map, &direction_map,
|
r = get_minutiae (&ret_data->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, &bdata, &bw, &bh, &bd,
|
&map_w, &map_h, &ret_data->binarized, &bw, &bh, &bd,
|
||||||
data->image, data->width, data->height, 8,
|
image, self->width, self->height, 8,
|
||||||
data->ppmm, lfsparms);
|
self->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));
|
||||||
|
|
||||||
data->binarized = g_steal_pointer (&bdata);
|
if (g_task_had_error (thread_task))
|
||||||
data->minutiae = minutiae;
|
return;
|
||||||
|
|
||||||
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 (task, G_IO_ERROR, G_IO_ERROR_FAILED, "Minutiae scan failed with code %d", r);
|
g_task_return_new_error (thread_task, G_IO_ERROR,
|
||||||
g_object_unref (task);
|
G_IO_ERROR_FAILED,
|
||||||
|
"Minutiae scan failed with code %d", r);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!data->minutiae || data->minutiae->num == 0)
|
if (!ret_data->minutiae || ret_data->minutiae->num == 0)
|
||||||
{
|
{
|
||||||
g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_FAILED,
|
g_task_return_new_error (thread_task, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||||
"No minutiae found");
|
"No minutiae found");
|
||||||
g_object_unref (task);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
g_task_return_boolean (task, TRUE);
|
g_task_return_pointer (thread_task, g_steal_pointer (&ret_data),
|
||||||
g_object_unref (task);
|
(GDestroyNotify) fp_image_detect_minutiae_free);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -443,21 +463,25 @@ fp_image_detect_minutiae (FpImage *self,
|
|||||||
GAsyncReadyCallback callback,
|
GAsyncReadyCallback callback,
|
||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
GTask *task;
|
g_autoptr(GTask) task = NULL;
|
||||||
DetectMinutiaeData *data = g_new0 (DetectMinutiaeData, 1);
|
|
||||||
|
|
||||||
task = g_task_new (self, cancellable, fp_image_detect_minutiae_cb, user_data);
|
g_return_if_fail (FP_IS_IMAGE (self));
|
||||||
|
g_return_if_fail (callback != NULL);
|
||||||
|
|
||||||
data->image = g_malloc (self->width * self->height);
|
task = g_task_new (self, cancellable, callback, user_data);
|
||||||
memcpy (data->image, self->data, self->width * self->height);
|
g_task_set_source_tag (task, fp_image_detect_minutiae);
|
||||||
data->flags = self->flags;
|
g_task_set_check_cancellable (task, TRUE);
|
||||||
data->width = self->width;
|
|
||||||
data->height = self->height;
|
|
||||||
data->ppmm = self->ppmm;
|
|
||||||
data->user_cb = callback;
|
|
||||||
|
|
||||||
g_task_set_task_data (task, data, (GDestroyNotify) fp_image_detect_minutiae_free);
|
if (!g_atomic_int_compare_and_exchange (&self->detection_in_progress,
|
||||||
g_task_run_in_thread (task, fp_image_detect_minutiae_thread_func);
|
FALSE, TRUE))
|
||||||
|
{
|
||||||
|
g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_ADDRESS_IN_USE,
|
||||||
|
"Minutiae detection is already in progress");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_task_run_in_thread (g_steal_pointer (&task),
|
||||||
|
fp_image_detect_minutiae_nbis_thread_func);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -475,7 +499,27 @@ fp_image_detect_minutiae_finish (FpImage *self,
|
|||||||
GAsyncResult *result,
|
GAsyncResult *result,
|
||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
return g_task_propagate_boolean (G_TASK (result), error);
|
GTask *task;
|
||||||
|
gboolean changed;
|
||||||
|
|
||||||
|
g_return_val_if_fail (FP_IS_IMAGE (self), FALSE);
|
||||||
|
g_return_val_if_fail (g_task_is_valid (result, self), FALSE);
|
||||||
|
g_return_val_if_fail (g_task_get_source_tag (G_TASK (result)) ==
|
||||||
|
fp_image_detect_minutiae, FALSE);
|
||||||
|
|
||||||
|
task = G_TASK (result);
|
||||||
|
changed = g_atomic_int_compare_and_exchange (&self->detection_in_progress,
|
||||||
|
TRUE, FALSE);
|
||||||
|
g_assert (changed);
|
||||||
|
|
||||||
|
if (g_task_had_error (task))
|
||||||
|
{
|
||||||
|
gpointer data = g_task_propagate_pointer (task, error);
|
||||||
|
g_assert (data == NULL);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return fp_image_detect_minutiae_nbis_finish (self, task, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+92
-85
@@ -339,7 +339,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 newyl created #FpPrint
|
* Returns: (transfer floating): A newly created #FpPrint
|
||||||
*/
|
*/
|
||||||
FpPrint *
|
FpPrint *
|
||||||
fp_print_new (FpDevice *device)
|
fp_print_new (FpDevice *device)
|
||||||
@@ -596,6 +596,9 @@ fp_print_equal (FpPrint *self, FpPrint *other)
|
|||||||
g_return_val_if_fail (self->type != FPI_PRINT_UNDEFINED, FALSE);
|
g_return_val_if_fail (self->type != FPI_PRINT_UNDEFINED, FALSE);
|
||||||
g_return_val_if_fail (other->type != FPI_PRINT_UNDEFINED, FALSE);
|
g_return_val_if_fail (other->type != FPI_PRINT_UNDEFINED, FALSE);
|
||||||
|
|
||||||
|
if (self == other)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
if (self->type != other->type)
|
if (self->type != other->type)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
@@ -605,18 +608,16 @@ 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)
|
switch (self->type)
|
||||||
{
|
{
|
||||||
|
case FPI_PRINT_RAW:
|
||||||
return g_variant_equal (self->data, other->data);
|
return g_variant_equal (self->data, other->data);
|
||||||
}
|
|
||||||
else if (self->type == FPI_PRINT_NBIS)
|
|
||||||
{
|
|
||||||
guint i;
|
|
||||||
|
|
||||||
|
case FPI_PRINT_NBIS:
|
||||||
if (self->prints->len != other->prints->len)
|
if (self->prints->len != other->prints->len)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
for (i = 0; i < self->prints->len; i++)
|
for (guint i = 0; i < self->prints->len; i++)
|
||||||
{
|
{
|
||||||
struct xyt_struct *a = g_ptr_array_index (self->prints, i);
|
struct xyt_struct *a = g_ptr_array_index (self->prints, i);
|
||||||
struct xyt_struct *b = g_ptr_array_index (other->prints, i);
|
struct xyt_struct *b = g_ptr_array_index (other->prints, i);
|
||||||
@@ -626,11 +627,12 @@ fp_print_equal (FpPrint *self, FpPrint *other)
|
|||||||
}
|
}
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
|
||||||
else
|
case FPI_PRINT_UNDEFINED:
|
||||||
{
|
|
||||||
g_assert_not_reached ();
|
g_assert_not_reached ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
g_return_val_if_reached (FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define FPI_PRINT_VARIANT_TYPE G_VARIANT_TYPE ("(issbymsmsia{sv}v)")
|
#define FPI_PRINT_VARIANT_TYPE G_VARIANT_TYPE ("(issbymsmsia{sv}v)")
|
||||||
@@ -721,13 +723,12 @@ 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 */
|
||||||
@@ -766,7 +767,7 @@ fp_print_deserialize (const guchar *data,
|
|||||||
g_autoptr(GVariant) value = NULL;
|
g_autoptr(GVariant) value = NULL;
|
||||||
g_autoptr(GVariant) print_data = NULL;
|
g_autoptr(GVariant) print_data = NULL;
|
||||||
g_autoptr(GDate) date = NULL;
|
g_autoptr(GDate) date = NULL;
|
||||||
guchar *aligned_data = NULL;
|
g_autoptr(GBytes) bytes = NULL;
|
||||||
guint8 finger_int8;
|
guint8 finger_int8;
|
||||||
FpFinger finger;
|
FpFinger finger;
|
||||||
g_autofree gchar *username = NULL;
|
g_autofree gchar *username = NULL;
|
||||||
@@ -788,22 +789,19 @@ fp_print_deserialize (const guchar *data,
|
|||||||
* of this function (meaning we don't need to keep the data around.
|
* of this function (meaning we don't need to keep the data around.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* To support GLIB < 2.60 we need to make sure that the memory is aligned correctly.
|
/* We need to copy the backing store for the raw data that we may keep for
|
||||||
* We also need to copy the backing store for the raw data that we may keep for
|
* longer. Using a GBytes also ensures the data is correctly aligned. */
|
||||||
* longer. */
|
bytes = g_bytes_new (data + 3, length - 3);
|
||||||
aligned_data = g_malloc (length - 3);
|
raw_value = g_variant_new_from_bytes (FPI_PRINT_VARIANT_TYPE, bytes, FALSE);
|
||||||
memcpy (aligned_data, data + 3, length - 3);
|
|
||||||
raw_value = g_variant_new_from_data (FPI_PRINT_VARIANT_TYPE,
|
|
||||||
aligned_data, length - 3,
|
|
||||||
FALSE, g_free, aligned_data);
|
|
||||||
|
|
||||||
if (!raw_value)
|
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)",
|
||||||
@@ -821,72 +819,81 @@ fp_print_deserialize (const guchar *data,
|
|||||||
finger = finger_int8;
|
finger = finger_int8;
|
||||||
|
|
||||||
/* Assume data is valid at this point if the values are somewhat sane. */
|
/* Assume data is valid at this point if the values are somewhat sane. */
|
||||||
if (type == FPI_PRINT_NBIS)
|
switch (type)
|
||||||
{
|
{
|
||||||
g_autoptr(GVariant) prints = g_variant_get_child_value (print_data, 0);
|
case FPI_PRINT_NBIS:
|
||||||
guint i;
|
{
|
||||||
|
g_autoptr(GVariant) prints = g_variant_get_child_value (print_data, 0);
|
||||||
|
guint i;
|
||||||
|
|
||||||
result = g_object_new (FP_TYPE_PRINT,
|
result = g_object_new (FP_TYPE_PRINT,
|
||||||
"driver", driver,
|
"driver", driver,
|
||||||
"device-id", device_id,
|
"device-id", device_id,
|
||||||
"device-stored", device_stored,
|
"device-stored", device_stored,
|
||||||
NULL);
|
NULL);
|
||||||
g_object_ref_sink (result);
|
g_object_ref_sink (result);
|
||||||
fpi_print_set_type (result, FPI_PRINT_NBIS);
|
fpi_print_set_type (result, FPI_PRINT_NBIS);
|
||||||
for (i = 0; i < g_variant_n_children (prints); i++)
|
for (i = 0; i < g_variant_n_children (prints); i++)
|
||||||
{
|
{
|
||||||
g_autofree struct xyt_struct *xyt = NULL;
|
g_autofree struct xyt_struct *xyt = NULL;
|
||||||
const gint32 *xcol, *ycol, *thetacol;
|
const gint32 *xcol, *ycol, *thetacol;
|
||||||
gsize xlen, ylen, thetalen;
|
gsize xlen, ylen, thetalen;
|
||||||
g_autoptr(GVariant) xyt_data = NULL;
|
g_autoptr(GVariant) xyt_data = NULL;
|
||||||
GVariant *child;
|
GVariant *child;
|
||||||
|
|
||||||
xyt_data = g_variant_get_child_value (prints, i);
|
xyt_data = g_variant_get_child_value (prints, i);
|
||||||
|
|
||||||
child = g_variant_get_child_value (xyt_data, 0);
|
child = g_variant_get_child_value (xyt_data, 0);
|
||||||
xcol = g_variant_get_fixed_array (child, &xlen, sizeof (gint32));
|
xcol = g_variant_get_fixed_array (child, &xlen, sizeof (gint32));
|
||||||
g_variant_unref (child);
|
g_variant_unref (child);
|
||||||
|
|
||||||
child = g_variant_get_child_value (xyt_data, 1);
|
child = g_variant_get_child_value (xyt_data, 1);
|
||||||
ycol = g_variant_get_fixed_array (child, &ylen, sizeof (gint32));
|
ycol = g_variant_get_fixed_array (child, &ylen, sizeof (gint32));
|
||||||
g_variant_unref (child);
|
g_variant_unref (child);
|
||||||
|
|
||||||
child = g_variant_get_child_value (xyt_data, 2);
|
child = g_variant_get_child_value (xyt_data, 2);
|
||||||
thetacol = g_variant_get_fixed_array (child, &thetalen, sizeof (gint32));
|
thetacol = g_variant_get_fixed_array (child, &thetalen, sizeof (gint32));
|
||||||
g_variant_unref (child);
|
g_variant_unref (child);
|
||||||
|
|
||||||
if (xlen != ylen || xlen != thetalen)
|
if (xlen != ylen || xlen != thetalen)
|
||||||
goto invalid_format;
|
goto invalid_format;
|
||||||
|
|
||||||
if (xlen > G_N_ELEMENTS (xyt->xcol))
|
if (xlen > G_N_ELEMENTS (xyt->xcol))
|
||||||
goto invalid_format;
|
goto invalid_format;
|
||||||
|
|
||||||
xyt = g_new0 (struct xyt_struct, 1);
|
xyt = g_new0 (struct xyt_struct, 1);
|
||||||
xyt->nrows = xlen;
|
xyt->nrows = xlen;
|
||||||
memcpy (xyt->xcol, xcol, sizeof (xcol[0]) * xlen);
|
memcpy (xyt->xcol, xcol, sizeof (xcol[0]) * xlen);
|
||||||
memcpy (xyt->ycol, ycol, sizeof (xcol[0]) * xlen);
|
memcpy (xyt->ycol, ycol, sizeof (xcol[0]) * xlen);
|
||||||
memcpy (xyt->thetacol, thetacol, sizeof (xcol[0]) * xlen);
|
memcpy (xyt->thetacol, thetacol, sizeof (xcol[0]) * xlen);
|
||||||
|
|
||||||
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)
|
break;
|
||||||
{
|
|
||||||
g_autoptr(GVariant) fp_data = g_variant_get_child_value (print_data, 0);
|
|
||||||
|
|
||||||
result = g_object_new (FP_TYPE_PRINT,
|
case FPI_PRINT_RAW:
|
||||||
"fpi-type", type,
|
{
|
||||||
"driver", driver,
|
g_autoptr(GVariant) fp_data = g_variant_get_child_value (print_data, 0);
|
||||||
"device-id", device_id,
|
|
||||||
"device-stored", device_stored,
|
result = g_object_new (FP_TYPE_PRINT,
|
||||||
"fpi-data", fp_data,
|
"fpi-type", type,
|
||||||
NULL);
|
"driver", driver,
|
||||||
g_object_ref_sink (result);
|
"device-id", device_id,
|
||||||
}
|
"device-stored", device_stored,
|
||||||
else
|
"fpi-data", fp_data,
|
||||||
{
|
NULL);
|
||||||
g_warning ("Invalid print type: 0x%X", type);
|
g_object_ref_sink (result);
|
||||||
goto invalid_format;
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FPI_PRINT_UNDEFINED:
|
||||||
|
{
|
||||||
|
g_autofree char *type_str = g_enum_to_string (fpi_print_type_get_type (), type);
|
||||||
|
g_warning ("Invalid print type: 0x%X (%s)", type, type_str);
|
||||||
|
|
||||||
|
goto invalid_format;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
date = g_date_new_julian (julian_date);
|
date = g_date_new_julian (julian_date);
|
||||||
|
|||||||
@@ -65,6 +65,31 @@ fpi_byte_reader_new (const guint8 * data, guint size)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fpi_byte_reader_new_bytes: (skip)
|
||||||
|
* @bytes: (in) (transfer none): a #GBytes instance from which the
|
||||||
|
* #FpiByteReader should read
|
||||||
|
*
|
||||||
|
* Create a new #FpiByteReader instance, which will read from @bytes.
|
||||||
|
*
|
||||||
|
* Free-function: fpi_byte_reader_free
|
||||||
|
*
|
||||||
|
* Returns: (transfer full): a new #FpiByteReader instance
|
||||||
|
*/
|
||||||
|
FpiByteReader *
|
||||||
|
fpi_byte_reader_new_bytes (GBytes * bytes)
|
||||||
|
{
|
||||||
|
const guint8 *data;
|
||||||
|
gsize size = 0;
|
||||||
|
|
||||||
|
g_return_val_if_fail (bytes != NULL, NULL);
|
||||||
|
|
||||||
|
data = g_bytes_get_data (bytes, &size);
|
||||||
|
g_return_val_if_fail (size <= G_MAXUINT, NULL);
|
||||||
|
|
||||||
|
return fpi_byte_reader_new (data, (guint) size);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* fpi_byte_reader_free:
|
* fpi_byte_reader_free:
|
||||||
* @reader: (in) (transfer full): a #FpiByteReader instance
|
* @reader: (in) (transfer full): a #FpiByteReader instance
|
||||||
@@ -100,6 +125,30 @@ fpi_byte_reader_init (FpiByteReader * reader, const guint8 * data, guint size)
|
|||||||
reader->byte = 0;
|
reader->byte = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fpi_byte_reader_init_bytes:
|
||||||
|
* @reader: a #FpiByteReader instance
|
||||||
|
* @bytes: (in) (transfer none): a #GBytes instance from which
|
||||||
|
* the #FpiByteReader should read
|
||||||
|
*
|
||||||
|
* Initializes a #FpiByteReader instance to read from @bytes. This function
|
||||||
|
* can be called on already initialized instances.
|
||||||
|
*/
|
||||||
|
FpiByteReader *
|
||||||
|
fpi_byte_reader_init_bytes (FpiByteReader * reader, GBytes * bytes)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (reader != NULL, NULL);
|
||||||
|
g_return_val_if_fail (bytes != NULL, NULL);
|
||||||
|
|
||||||
|
gsize size = 0;
|
||||||
|
const guint8 *data = g_bytes_get_data (bytes, &size);
|
||||||
|
|
||||||
|
g_return_val_if_fail (size <= G_MAXUINT, NULL);
|
||||||
|
fpi_byte_reader_init (reader, data, (guint) size);
|
||||||
|
|
||||||
|
return reader;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* fpi_byte_reader_peek_sub_reader: (skip)
|
* fpi_byte_reader_peek_sub_reader: (skip)
|
||||||
* @reader: an existing and initialized #FpiByteReader instance
|
* @reader: an existing and initialized #FpiByteReader instance
|
||||||
@@ -799,6 +848,41 @@ fpi_byte_reader_peek_data (const FpiByteReader * reader, guint size,
|
|||||||
return fpi_byte_reader_peek_data_inline (reader, size, val);
|
return fpi_byte_reader_peek_data_inline (reader, size, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fpi_byte_reader_get_data_fixed:
|
||||||
|
* @reader: a #FpiByteReader instance
|
||||||
|
* @size: Size in bytes
|
||||||
|
* @val: (out) (array length=size): address of a buffer to copy data into
|
||||||
|
*
|
||||||
|
* Copies @size bytes from the current data position into @val if at
|
||||||
|
* least @size bytes are left, and updates the current position.
|
||||||
|
*
|
||||||
|
* Returns: %TRUE if successful, %FALSE otherwise.
|
||||||
|
*/
|
||||||
|
gboolean
|
||||||
|
(fpi_byte_reader_get_data_static) (FpiByteReader * reader, guint size,
|
||||||
|
const guint8 * val)
|
||||||
|
{
|
||||||
|
return (fpi_byte_reader_get_data_inline_static) (reader, size, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fpi_byte_reader_peek_data_fixed:
|
||||||
|
* @reader: a #FpiByteReader instance
|
||||||
|
* @size: Size in bytes
|
||||||
|
* @val: (out) (array length=size): address of a buffer to copy data into
|
||||||
|
*
|
||||||
|
* Like fpi_byte_reader_get_data_fixed() but does not advance the position.
|
||||||
|
*
|
||||||
|
* Returns: %TRUE if successful, %FALSE otherwise.
|
||||||
|
*/
|
||||||
|
gboolean
|
||||||
|
(fpi_byte_reader_peek_data_static) (const FpiByteReader * reader, guint size,
|
||||||
|
guint8 * val)
|
||||||
|
{
|
||||||
|
return (fpi_byte_reader_peek_data_inline_static) (reader, size, val);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* fpi_byte_reader_dup_data:
|
* fpi_byte_reader_dup_data:
|
||||||
* @reader: a #FpiByteReader instance
|
* @reader: a #FpiByteReader instance
|
||||||
@@ -1181,7 +1265,7 @@ fpi_byte_reader_dup_string_utf##bits (FpiByteReader * reader, type ** str) \
|
|||||||
*str = NULL; \
|
*str = NULL; \
|
||||||
return FALSE; \
|
return FALSE; \
|
||||||
} \
|
} \
|
||||||
*str = g_memdup (reader->data + reader->byte, size); \
|
*str = g_memdup2 (reader->data + reader->byte, size); \
|
||||||
reader->byte += size; \
|
reader->byte += size; \
|
||||||
return TRUE; \
|
return TRUE; \
|
||||||
}
|
}
|
||||||
|
|||||||
+104
-1
@@ -22,6 +22,7 @@
|
|||||||
#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
|
||||||
@@ -49,6 +50,7 @@ typedef struct {
|
|||||||
|
|
||||||
FpiByteReader * fpi_byte_reader_new (const guint8 *data, guint size) G_GNUC_MALLOC;
|
FpiByteReader * fpi_byte_reader_new (const guint8 *data, guint size) G_GNUC_MALLOC;
|
||||||
|
|
||||||
|
FpiByteReader * fpi_byte_reader_new_bytes (GBytes *bytes) G_GNUC_MALLOC;
|
||||||
|
|
||||||
void fpi_byte_reader_free (FpiByteReader *reader);
|
void fpi_byte_reader_free (FpiByteReader *reader);
|
||||||
|
|
||||||
@@ -56,6 +58,9 @@ void fpi_byte_reader_free (FpiByteReader *reader);
|
|||||||
void fpi_byte_reader_init (FpiByteReader *reader, const guint8 *data, guint size);
|
void fpi_byte_reader_init (FpiByteReader *reader, const guint8 *data, guint size);
|
||||||
|
|
||||||
|
|
||||||
|
FpiByteReader * fpi_byte_reader_init_bytes (FpiByteReader *reader, GBytes *bytes);
|
||||||
|
|
||||||
|
|
||||||
gboolean fpi_byte_reader_peek_sub_reader (FpiByteReader * reader,
|
gboolean fpi_byte_reader_peek_sub_reader (FpiByteReader * reader,
|
||||||
FpiByteReader * sub_reader,
|
FpiByteReader * sub_reader,
|
||||||
guint size);
|
guint size);
|
||||||
@@ -217,8 +222,21 @@ gboolean fpi_byte_reader_dup_data (FpiByteReader * reader, guint s
|
|||||||
gboolean fpi_byte_reader_get_data (FpiByteReader * reader, guint size, const guint8 ** val);
|
gboolean fpi_byte_reader_get_data (FpiByteReader * reader, guint size, const guint8 ** val);
|
||||||
|
|
||||||
|
|
||||||
|
gboolean fpi_byte_reader_get_data_static (FpiByteReader * reader, guint size, const guint8 * val);
|
||||||
|
|
||||||
|
|
||||||
gboolean fpi_byte_reader_peek_data (const FpiByteReader * reader, guint size, const guint8 ** val);
|
gboolean fpi_byte_reader_peek_data (const FpiByteReader * reader, guint size, const guint8 ** val);
|
||||||
|
|
||||||
|
|
||||||
|
gboolean fpi_byte_reader_peek_data_static (const FpiByteReader * reader, guint size, guint8 * val);
|
||||||
|
|
||||||
|
|
||||||
|
GBytes * fpi_byte_reader_get_bytes (FpiByteReader *reader, guint size);
|
||||||
|
|
||||||
|
|
||||||
|
GBytes * fpi_byte_reader_peek_bytes (const FpiByteReader *reader, guint size);
|
||||||
|
|
||||||
|
|
||||||
#define fpi_byte_reader_dup_string(reader,str) \
|
#define fpi_byte_reader_dup_string(reader,str) \
|
||||||
fpi_byte_reader_dup_string_utf8(reader,str)
|
fpi_byte_reader_dup_string_utf8(reader,str)
|
||||||
|
|
||||||
@@ -360,7 +378,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_memdup (data, size);
|
return (guint8 *) g_memdup2 (data, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Unchecked variants that should not be used */
|
/* Unchecked variants that should not be used */
|
||||||
@@ -641,6 +659,60 @@ fpi_byte_reader_peek_data_inline (const FpiByteReader * reader, guint size, cons
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline GBytes *
|
||||||
|
fpi_byte_reader_peek_bytes_inline (const FpiByteReader *reader, guint size)
|
||||||
|
{
|
||||||
|
const guint8 *data;
|
||||||
|
|
||||||
|
g_return_val_if_fail (reader != NULL, NULL);
|
||||||
|
|
||||||
|
if (G_UNLIKELY (size > reader->size || fpi_byte_reader_get_remaining_unchecked (reader) < size))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
data = fpi_byte_reader_peek_data_unchecked (reader);
|
||||||
|
return g_bytes_new_static (data, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline GBytes *
|
||||||
|
fpi_byte_reader_get_bytes_inline (FpiByteReader *reader, guint size)
|
||||||
|
{
|
||||||
|
const guint8 *data;
|
||||||
|
|
||||||
|
g_return_val_if_fail (reader != NULL, NULL);
|
||||||
|
|
||||||
|
if (G_UNLIKELY (size > reader->size || fpi_byte_reader_get_remaining_unchecked (reader) < size))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
data = fpi_byte_reader_get_data_unchecked (reader, size);
|
||||||
|
return g_bytes_new_static (data, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline gboolean
|
||||||
|
(fpi_byte_reader_get_data_inline_static) (FpiByteReader * reader, guint size, const guint8 * val)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (reader != NULL, FALSE);
|
||||||
|
g_return_val_if_fail (val != NULL, FALSE);
|
||||||
|
|
||||||
|
if (G_UNLIKELY (size > reader->size || fpi_byte_reader_get_remaining_unchecked (reader) < size))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
memcpy ((void *) val, fpi_byte_reader_get_data_unchecked (reader, size), size);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline gboolean
|
||||||
|
(fpi_byte_reader_peek_data_inline_static) (const FpiByteReader * reader, guint size, guint8 * val)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (reader != NULL, FALSE);
|
||||||
|
g_return_val_if_fail (val != NULL, FALSE);
|
||||||
|
|
||||||
|
if (G_UNLIKELY (size > reader->size || fpi_byte_reader_get_remaining_unchecked (reader) < size))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
memcpy (val, fpi_byte_reader_peek_data_unchecked (reader), size);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
static inline guint
|
static inline guint
|
||||||
fpi_byte_reader_get_pos_inline (const FpiByteReader * reader)
|
fpi_byte_reader_get_pos_inline (const FpiByteReader * reader)
|
||||||
{
|
{
|
||||||
@@ -671,7 +743,38 @@ fpi_byte_reader_skip_inline (FpiByteReader * reader, guint nbytes)
|
|||||||
G_LIKELY(fpi_byte_reader_peek_data_inline(reader,size,val))
|
G_LIKELY(fpi_byte_reader_peek_data_inline(reader,size,val))
|
||||||
#define fpi_byte_reader_skip(reader,nbytes) \
|
#define fpi_byte_reader_skip(reader,nbytes) \
|
||||||
G_LIKELY(fpi_byte_reader_skip_inline(reader,nbytes))
|
G_LIKELY(fpi_byte_reader_skip_inline(reader,nbytes))
|
||||||
|
#define fpi_byte_reader_get_bytes(reader,size) \
|
||||||
|
fpi_byte_reader_get_bytes_inline(reader,size)
|
||||||
|
#define fpi_byte_reader_peek_bytes(reader,size) \
|
||||||
|
fpi_byte_reader_peek_bytes_inline(reader,size)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fpi_byte_reader_get_data_static:
|
||||||
|
* @reader: a #FpiByteReader
|
||||||
|
* @val: fixed-size array (e.g. `uint8_t buf[32]`)
|
||||||
|
*
|
||||||
|
* Reads @size bytes from @reader directly into @val, where @size is
|
||||||
|
* deduced via `sizeof()` - only safe with true C arrays.
|
||||||
|
*
|
||||||
|
* Returns: %TRUE on success, %FALSE otherwise.
|
||||||
|
*/
|
||||||
|
#define fpi_byte_reader_get_data_static(reader,val) \
|
||||||
|
(fpi_byte_reader_get_data_static) (reader,sizeof(val),val)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fpi_byte_reader_peek_data_static:
|
||||||
|
* @reader: a #FpiByteReader
|
||||||
|
* @val: fixed-size array (e.g. `uint8_t buf[32]`)
|
||||||
|
*
|
||||||
|
* Like fpi_byte_reader_get_data_static() but does not advance the position.
|
||||||
|
*
|
||||||
|
* Returns: %TRUE on success, %FALSE otherwise.
|
||||||
|
*/
|
||||||
|
#define fpi_byte_reader_peek_data_static(reader,val) \
|
||||||
|
(fpi_byte_reader_peek_data_static) (reader,sizeof(val),val)
|
||||||
|
|
||||||
#endif /* FPI_BYTE_READER_DISABLE_INLINES */
|
#endif /* FPI_BYTE_READER_DISABLE_INLINES */
|
||||||
|
|
||||||
|
G_DEFINE_AUTOPTR_CLEANUP_FUNC (FpiByteReader, fpi_byte_reader_free);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|||||||
@@ -75,7 +75,8 @@ 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_malloc (ret->alloc_size);
|
ret->parent.data = g_malloc0 (ret->alloc_size);
|
||||||
|
ret->parent.size = size;
|
||||||
ret->fixed = fixed;
|
ret->fixed = fixed;
|
||||||
ret->owned = TRUE;
|
ret->owned = TRUE;
|
||||||
|
|
||||||
@@ -142,7 +143,8 @@ fpi_byte_writer_init_with_size (FpiByteWriter * writer, guint size,
|
|||||||
|
|
||||||
fpi_byte_writer_init (writer);
|
fpi_byte_writer_init (writer);
|
||||||
|
|
||||||
writer->parent.data = g_malloc (size);
|
writer->parent.data = g_malloc0 (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;
|
||||||
@@ -209,15 +211,44 @@ 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 *) writer->parent.data;
|
data = (guint8 *) g_steal_pointer (&writer->parent.data);
|
||||||
if (!writer->owned)
|
if (!writer->owned)
|
||||||
data = g_memdup (data, writer->parent.size);
|
data = g_memdup2 (data, writer->parent.size);
|
||||||
writer->parent.data = NULL;
|
|
||||||
fpi_byte_writer_reset (writer);
|
fpi_byte_writer_reset (writer);
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fpi_byte_writer_reset_and_get_bytes:
|
||||||
|
* @writer: #FpiByteWriter instance
|
||||||
|
*
|
||||||
|
* Resets @writer and returns the current data as a #GBytes.
|
||||||
|
*
|
||||||
|
* Returns: (transfer full): the current data as a #GBytes.
|
||||||
|
*/
|
||||||
|
GBytes *
|
||||||
|
fpi_byte_writer_reset_and_get_bytes (FpiByteWriter * writer)
|
||||||
|
{
|
||||||
|
GBytes *bytes;
|
||||||
|
|
||||||
|
g_return_val_if_fail (writer != NULL, NULL);
|
||||||
|
|
||||||
|
if (!writer->owned)
|
||||||
|
{
|
||||||
|
bytes = g_bytes_new (g_steal_pointer (&writer->parent.data),
|
||||||
|
writer->parent.size);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bytes = g_bytes_new_take ((gpointer) g_steal_pointer (&writer->parent.data),
|
||||||
|
writer->parent.size);
|
||||||
|
}
|
||||||
|
|
||||||
|
fpi_byte_writer_reset (writer);
|
||||||
|
return g_steal_pointer (&bytes);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* fpi_byte_writer_free:
|
* fpi_byte_writer_free:
|
||||||
* @writer: (in) (transfer full): #FpiByteWriter instance
|
* @writer: (in) (transfer full): #FpiByteWriter instance
|
||||||
@@ -601,6 +632,15 @@ CREATE_WRITE_STRING_FUNC (32, guint32);
|
|||||||
*
|
*
|
||||||
* Returns: %TRUE if the value could be written
|
* Returns: %TRUE if the value could be written
|
||||||
*/
|
*/
|
||||||
|
/**
|
||||||
|
* fpi_byte_writer_put_bytes:
|
||||||
|
* @writer: #FpiByteWriter instance
|
||||||
|
* @bytes: (transfer none): Data to write
|
||||||
|
*
|
||||||
|
* Writes the contents of @bytes to @writer.
|
||||||
|
*
|
||||||
|
* Returns: %TRUE if the value could be written
|
||||||
|
*/
|
||||||
/**
|
/**
|
||||||
* fpi_byte_writer_fill:
|
* fpi_byte_writer_fill:
|
||||||
* @writer: #FpiByteWriter instance
|
* @writer: #FpiByteWriter instance
|
||||||
|
|||||||
@@ -77,6 +77,9 @@ void fpi_byte_writer_reset (FpiByteWriter *writer);
|
|||||||
|
|
||||||
guint8 * fpi_byte_writer_reset_and_get_data (FpiByteWriter *writer);
|
guint8 * fpi_byte_writer_reset_and_get_data (FpiByteWriter *writer);
|
||||||
|
|
||||||
|
|
||||||
|
GBytes * fpi_byte_writer_reset_and_get_bytes (FpiByteWriter *writer);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* fpi_byte_writer_get_pos:
|
* fpi_byte_writer_get_pos:
|
||||||
* @writer: #FpiByteWriter instance
|
* @writer: #FpiByteWriter instance
|
||||||
@@ -111,6 +114,17 @@ 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)
|
||||||
{
|
{
|
||||||
@@ -193,6 +207,9 @@ gboolean fpi_byte_writer_put_float64_le (FpiByteWriter *writer, gdoubl
|
|||||||
gboolean fpi_byte_writer_put_data (FpiByteWriter *writer, const guint8 *data, guint size);
|
gboolean fpi_byte_writer_put_data (FpiByteWriter *writer, const guint8 *data, guint size);
|
||||||
|
|
||||||
|
|
||||||
|
gboolean fpi_byte_writer_put_bytes (FpiByteWriter *writer, const GBytes *bytes);
|
||||||
|
|
||||||
|
|
||||||
gboolean fpi_byte_writer_fill (FpiByteWriter *writer, guint8 value, guint size);
|
gboolean fpi_byte_writer_fill (FpiByteWriter *writer, guint8 value, guint size);
|
||||||
|
|
||||||
|
|
||||||
@@ -327,6 +344,18 @@ fpi_byte_writer_put_data_inline (FpiByteWriter * writer, const guint8 * data,
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline gboolean
|
||||||
|
fpi_byte_writer_put_bytes_inline (FpiByteWriter * writer, const GBytes * bytes)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (writer != NULL, FALSE);
|
||||||
|
g_return_val_if_fail (bytes != NULL, FALSE);
|
||||||
|
const guint8 *data;
|
||||||
|
gsize size;
|
||||||
|
|
||||||
|
data = g_bytes_get_data ((GBytes *) bytes, &size);
|
||||||
|
return fpi_byte_writer_put_data_inline (writer, data, size);
|
||||||
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
fpi_byte_writer_fill_unchecked (FpiByteWriter * writer, guint8 value, guint size)
|
fpi_byte_writer_fill_unchecked (FpiByteWriter * writer, guint8 value, guint size)
|
||||||
{
|
{
|
||||||
@@ -402,9 +431,16 @@ fpi_byte_writer_fill_inline (FpiByteWriter * writer, guint8 value, guint size)
|
|||||||
|
|
||||||
#define fpi_byte_writer_put_data(writer, data, size) \
|
#define fpi_byte_writer_put_data(writer, data, size) \
|
||||||
G_LIKELY (fpi_byte_writer_put_data_inline (writer, data, size))
|
G_LIKELY (fpi_byte_writer_put_data_inline (writer, data, size))
|
||||||
|
#define fpi_byte_writer_put_data_static(writer, data) \
|
||||||
|
G_LIKELY (fpi_byte_writer_put_data_inline (writer, data, sizeof (data)))
|
||||||
|
#define fpi_byte_writer_put_bytes(writer, bytes) \
|
||||||
|
G_LIKELY (fpi_byte_writer_put_bytes_inline (writer, bytes))
|
||||||
#define fpi_byte_writer_fill(writer, val, size) \
|
#define fpi_byte_writer_fill(writer, val, size) \
|
||||||
G_LIKELY (fpi_byte_writer_fill_inline (writer, val, size))
|
G_LIKELY (fpi_byte_writer_fill_inline (writer, val, 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,25 +20,6 @@
|
|||||||
|
|
||||||
#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
|
||||||
|
|||||||
+354
-129
@@ -22,10 +22,12 @@
|
|||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <gmodule.h>
|
||||||
|
|
||||||
#include "fpi-log.h"
|
#include "fpi-log.h"
|
||||||
|
|
||||||
#include "fp-device-private.h"
|
#include "fp-device-private.h"
|
||||||
|
#include "tests/fpi-test-emulation.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SECTION: fpi-device
|
* SECTION: fpi-device
|
||||||
@@ -50,8 +52,88 @@ fp_device_get_instance_private (FpDevice *self)
|
|||||||
g_type_class_get_instance_private_offset (dev_class));
|
g_type_class_get_instance_private_offset (dev_class));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
G_DEFINE_AUTOPTR_CLEANUP_FUNC (GModule, g_module_close)
|
||||||
|
|
||||||
|
static char *
|
||||||
|
error_to_string (GError * error)
|
||||||
|
{
|
||||||
|
g_autofree char *domain_str = NULL;
|
||||||
|
|
||||||
|
if (!error)
|
||||||
|
return g_strdup ("none");
|
||||||
|
|
||||||
|
if (error->domain == FP_DEVICE_RETRY)
|
||||||
|
domain_str = g_enum_to_string (FP_TYPE_DEVICE_RETRY, error->code);
|
||||||
|
else if (error->domain == FP_DEVICE_ERROR)
|
||||||
|
domain_str = g_enum_to_string (FP_TYPE_DEVICE_ERROR, error->code);
|
||||||
|
else if (error->domain == G_IO_ERROR)
|
||||||
|
domain_str = g_enum_to_string (g_io_error_enum_get_type (), error->code);
|
||||||
|
else if (error->domain == G_USB_DEVICE_ERROR)
|
||||||
|
domain_str = g_strdup_printf ("G_USB_DEVICE_ERROR_%u", error->code);
|
||||||
|
else
|
||||||
|
domain_str = g_strdup_printf ("%s_%u",
|
||||||
|
g_quark_to_string (error->domain),
|
||||||
|
error->code);
|
||||||
|
|
||||||
|
return g_strdup_printf ("[%s] %s", domain_str, error->message);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fpi_device_emulation_mode_enabled:
|
||||||
|
* @device: The #FpDevice to check
|
||||||
|
*
|
||||||
|
* Checks if the device is running in emulation mode, which is enabled by
|
||||||
|
* setting the FP_DEVICE_EMULATION environment variable to a '1' value but
|
||||||
|
* only when the test emulation library is loaded.
|
||||||
|
* This is used by some drivers to enable special behavior for testing
|
||||||
|
* and development purposes.
|
||||||
|
*/
|
||||||
|
gboolean
|
||||||
|
(fpi_device_emulation_mode_enabled) (FpDevice *device)
|
||||||
|
{
|
||||||
|
static gboolean (*real_fn)(FpDevice *) = NULL;
|
||||||
|
static gsize emulation_mode = 0;
|
||||||
|
|
||||||
|
if (g_once_init_enter (&emulation_mode))
|
||||||
|
{
|
||||||
|
if (g_strcmp0 (g_getenv (FPI_EMULATION_ENV_VAR), "1") == 0)
|
||||||
|
{
|
||||||
|
const char *dirs[] = {
|
||||||
|
FPI_EMULATION_HELPER_BUILDDIR,
|
||||||
|
FPI_EMULATION_HELPER_INSTALLDIR,
|
||||||
|
};
|
||||||
|
|
||||||
|
for (size_t i = 0; i < G_N_ELEMENTS (dirs); ++i)
|
||||||
|
{
|
||||||
|
g_autofree char *path = NULL;
|
||||||
|
g_autoptr(GModule) mod = NULL;
|
||||||
|
gpointer sym;
|
||||||
|
|
||||||
|
path = g_build_filename (dirs[i], FPI_EMULATION_HELPER_MODULE, NULL);
|
||||||
|
if (!(mod = g_module_open (path, G_MODULE_BIND_LAZY | G_MODULE_BIND_LOCAL)))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!g_module_symbol (mod, "fpi_device_emulation_mode_enabled", &sym))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
real_fn = (gboolean (*)(FpDevice *)) sym;
|
||||||
|
g_steal_pointer (&mod);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
g_once_init_leave (&emulation_mode, real_fn ? TRUE : G_MAXSIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (real_fn)
|
||||||
|
return real_fn (device);
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* fpi_device_class_auto_initialize_features:
|
* fpi_device_class_auto_initialize_features:
|
||||||
|
* @device_class: An #FpDeviceClass to initialize
|
||||||
*
|
*
|
||||||
* Initializes the #FpDeviceClass @features flags checking what device vfuncs
|
* Initializes the #FpDeviceClass @features flags checking what device vfuncs
|
||||||
* are implemented.
|
* are implemented.
|
||||||
@@ -69,7 +151,7 @@ fpi_device_class_auto_initialize_features (FpDeviceClass *device_class)
|
|||||||
device_class->features |= FP_DEVICE_FEATURE_VERIFY;
|
device_class->features |= FP_DEVICE_FEATURE_VERIFY;
|
||||||
|
|
||||||
if (device_class->identify)
|
if (device_class->identify)
|
||||||
device_class->features |= FP_DEVICE_FEATURE_IDENTIFY;
|
device_class->features |= FP_DEVICE_FEATURE_IDENTIFY | FP_DEVICE_FEATURE_VERIFY;
|
||||||
|
|
||||||
if (device_class->list)
|
if (device_class->list)
|
||||||
device_class->features |= FP_DEVICE_FEATURE_STORAGE_LIST;
|
device_class->features |= FP_DEVICE_FEATURE_STORAGE_LIST;
|
||||||
@@ -117,6 +199,10 @@ fpi_device_retry_new (FpDeviceRetry error)
|
|||||||
msg = "Please try again after removing the finger first.";
|
msg = "Please try again after removing the finger first.";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case FP_DEVICE_RETRY_TOO_FAST:
|
||||||
|
msg = "The swipe was too fast, please try again.";
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
g_warning ("Unsupported error, returning general error instead!");
|
g_warning ("Unsupported error, returning general error instead!");
|
||||||
error = FP_DEVICE_RETRY_GENERAL;
|
error = FP_DEVICE_RETRY_GENERAL;
|
||||||
@@ -522,33 +608,6 @@ fpi_device_get_driver_data (FpDevice *device)
|
|||||||
return priv->driver_data;
|
return priv->driver_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
enroll_data_free (FpEnrollData *data)
|
|
||||||
{
|
|
||||||
if (data->enroll_progress_destroy)
|
|
||||||
data->enroll_progress_destroy (data->enroll_progress_data);
|
|
||||||
data->enroll_progress_data = NULL;
|
|
||||||
g_clear_object (&data->print);
|
|
||||||
g_free (data);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
match_data_free (FpMatchData *data)
|
|
||||||
{
|
|
||||||
g_clear_object (&data->print);
|
|
||||||
g_clear_object (&data->match);
|
|
||||||
g_clear_error (&data->error);
|
|
||||||
|
|
||||||
if (data->match_destroy)
|
|
||||||
data->match_destroy (data->match_data);
|
|
||||||
data->match_data = NULL;
|
|
||||||
|
|
||||||
g_clear_object (&data->enrolled_print);
|
|
||||||
g_clear_pointer (&data->gallery, g_ptr_array_unref);
|
|
||||||
|
|
||||||
g_free (data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* fpi_device_get_enroll_data:
|
* fpi_device_get_enroll_data:
|
||||||
* @device: The #FpDevice
|
* @device: The #FpDevice
|
||||||
@@ -622,7 +681,14 @@ fpi_device_get_verify_data (FpDevice *device,
|
|||||||
* @device: The #FpDevice
|
* @device: The #FpDevice
|
||||||
* @prints: (out) (transfer none) (element-type FpPrint): The gallery of prints
|
* @prints: (out) (transfer none) (element-type FpPrint): The gallery of prints
|
||||||
*
|
*
|
||||||
* Get data for identify.
|
* Get prints gallery for identification.
|
||||||
|
*
|
||||||
|
* The @prints array is always non-%NULL and may contain a list of #FpPrint's
|
||||||
|
* that the device should match against.
|
||||||
|
*
|
||||||
|
* Note that @prints can be an empty array, in such case the device is expected
|
||||||
|
* to report the scanned print matching the one in its internal storage, if any.
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
fpi_device_get_identify_data (FpDevice *device,
|
fpi_device_get_identify_data (FpDevice *device,
|
||||||
@@ -730,7 +796,7 @@ fpi_device_remove (FpDevice *device)
|
|||||||
/**
|
/**
|
||||||
* fpi_device_action_error:
|
* fpi_device_action_error:
|
||||||
* @device: The #FpDevice
|
* @device: The #FpDevice
|
||||||
* @error: The #GError to return
|
* @error: (nullable) (transfer full): The #GError or %NULL on success
|
||||||
*
|
*
|
||||||
* Finish an ongoing action with an error. This is the same as calling
|
* Finish an ongoing action with an error. This is the same as calling
|
||||||
* the corresponding complete function such as fpi_device_open_complete()
|
* the corresponding complete function such as fpi_device_open_complete()
|
||||||
@@ -748,11 +814,14 @@ fpi_device_action_error (FpDevice *device,
|
|||||||
|
|
||||||
if (error != NULL)
|
if (error != NULL)
|
||||||
{
|
{
|
||||||
g_autofree char *action_str = NULL;
|
if (!g_log_writer_default_would_drop (G_LOG_LEVEL_DEBUG, G_LOG_DOMAIN))
|
||||||
|
{
|
||||||
|
g_autofree char *error_str = error_to_string (error);
|
||||||
|
g_autofree char *action_str = g_enum_to_string (FPI_TYPE_DEVICE_ACTION, priv->current_action);
|
||||||
|
|
||||||
action_str = g_enum_to_string (FPI_TYPE_DEVICE_ACTION, priv->current_action);
|
g_debug ("Device reported generic error (%s) during action; action was: %s",
|
||||||
g_debug ("Device reported generic error (%s) during action; action was: %s",
|
error_str, action_str);
|
||||||
error->message, action_str);
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -965,17 +1034,18 @@ typedef struct _FpDeviceTaskReturnData
|
|||||||
static gboolean
|
static gboolean
|
||||||
fp_device_task_return_in_idle_cb (gpointer user_data)
|
fp_device_task_return_in_idle_cb (gpointer user_data)
|
||||||
{
|
{
|
||||||
FpDeviceTaskReturnData *data = user_data;
|
|
||||||
FpDevicePrivate *priv = fp_device_get_instance_private (data->device);
|
|
||||||
g_autofree char *action_str = NULL;
|
|
||||||
FpiDeviceAction action;
|
|
||||||
|
|
||||||
g_autoptr(GTask) task = NULL;
|
g_autoptr(GTask) task = NULL;
|
||||||
g_autoptr(GError) cancellation_reason = NULL;
|
g_autoptr(GError) cancellation_reason = NULL;
|
||||||
|
FpDeviceTaskReturnData *data = user_data;
|
||||||
|
FpDevicePrivate *priv = fp_device_get_instance_private (data->device);
|
||||||
|
FpiDeviceAction action;
|
||||||
|
|
||||||
|
if (!g_log_writer_default_would_drop (G_LOG_LEVEL_DEBUG, G_LOG_DOMAIN))
|
||||||
|
{
|
||||||
|
g_autofree char *action_str = g_enum_to_string (FPI_TYPE_DEVICE_ACTION, priv->current_action);
|
||||||
|
|
||||||
action_str = g_enum_to_string (FPI_TYPE_DEVICE_ACTION, priv->current_action);
|
g_debug ("Completing action %s in idle!", action_str);
|
||||||
g_debug ("Completing action %s in idle!", action_str);
|
}
|
||||||
|
|
||||||
task = g_steal_pointer (&priv->current_task);
|
task = g_steal_pointer (&priv->current_task);
|
||||||
action = priv->current_action;
|
action = priv->current_action;
|
||||||
@@ -1062,34 +1132,41 @@ fp_device_task_return_in_idle_cb (gpointer user_data)
|
|||||||
static void
|
static void
|
||||||
fpi_device_task_return_data_free (FpDeviceTaskReturnData *data)
|
fpi_device_task_return_data_free (FpDeviceTaskReturnData *data)
|
||||||
{
|
{
|
||||||
if (data->result)
|
switch (data->type)
|
||||||
{
|
{
|
||||||
switch (data->type)
|
case FP_DEVICE_TASK_RETURN_INT:
|
||||||
{
|
case FP_DEVICE_TASK_RETURN_BOOL:
|
||||||
case FP_DEVICE_TASK_RETURN_INT:
|
break;
|
||||||
case FP_DEVICE_TASK_RETURN_BOOL:
|
|
||||||
break;
|
|
||||||
|
|
||||||
case FP_DEVICE_TASK_RETURN_OBJECT:
|
case FP_DEVICE_TASK_RETURN_OBJECT:
|
||||||
g_clear_object ((GObject **) &data->result);
|
g_clear_object ((GObject **) &data->result);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FP_DEVICE_TASK_RETURN_PTR_ARRAY:
|
case FP_DEVICE_TASK_RETURN_PTR_ARRAY:
|
||||||
g_clear_pointer ((GPtrArray **) &data->result, g_ptr_array_unref);
|
g_clear_pointer ((GPtrArray **) &data->result, g_ptr_array_unref);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FP_DEVICE_TASK_RETURN_ERROR:
|
case FP_DEVICE_TASK_RETURN_ERROR:
|
||||||
g_clear_error ((GError **) &data->result);
|
g_clear_error ((GError **) &data->result);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
g_assert_not_reached ();
|
g_assert_not_reached ();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
g_object_unref (data->device);
|
g_object_unref (data->device);
|
||||||
g_free (data);
|
g_free (data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fpi_device_return_task_in_idle:
|
||||||
|
* @device: The #FpDevice
|
||||||
|
* @return_type: The #FpDeviceTaskReturnType of @return_data
|
||||||
|
* @return_data: (nullable) (transfer full): The data to return.
|
||||||
|
*
|
||||||
|
* Completes a #FpDevice task in an idle source, stealing the ownership of
|
||||||
|
* the passed @returned_data.
|
||||||
|
*/
|
||||||
static void
|
static void
|
||||||
fpi_device_return_task_in_idle (FpDevice *device,
|
fpi_device_return_task_in_idle (FpDevice *device,
|
||||||
FpDeviceTaskReturnType return_type,
|
FpDeviceTaskReturnType return_type,
|
||||||
@@ -1121,7 +1198,7 @@ fpi_device_return_task_in_idle (FpDevice *device,
|
|||||||
* @device: The #FpDevice
|
* @device: The #FpDevice
|
||||||
* @device_id: Unique ID for the device or %NULL
|
* @device_id: Unique ID for the device or %NULL
|
||||||
* @device_name: Human readable name or %NULL for driver name
|
* @device_name: Human readable name or %NULL for driver name
|
||||||
* @error: The #GError or %NULL on success
|
* @error: (nullable) (transfer full): The #GError or %NULL on success
|
||||||
*
|
*
|
||||||
* Finish an ongoing probe operation. If error is %NULL success is assumed.
|
* Finish an ongoing probe operation. If error is %NULL success is assumed.
|
||||||
*/
|
*/
|
||||||
@@ -1136,7 +1213,13 @@ fpi_device_probe_complete (FpDevice *device,
|
|||||||
g_return_if_fail (FP_IS_DEVICE (device));
|
g_return_if_fail (FP_IS_DEVICE (device));
|
||||||
g_return_if_fail (priv->current_action == FPI_DEVICE_ACTION_PROBE);
|
g_return_if_fail (priv->current_action == FPI_DEVICE_ACTION_PROBE);
|
||||||
|
|
||||||
g_debug ("Device reported probe completion");
|
if (!g_log_writer_default_would_drop (G_LOG_LEVEL_DEBUG, G_LOG_DOMAIN))
|
||||||
|
{
|
||||||
|
g_autofree char *error_str = error_to_string (error);
|
||||||
|
|
||||||
|
g_debug ("Device reported probe completion (ID: %s, name: %s, error: %s)",
|
||||||
|
device_id, device_name, error_str);
|
||||||
|
}
|
||||||
|
|
||||||
clear_device_cancel_action (device);
|
clear_device_cancel_action (device);
|
||||||
fpi_device_report_finger_status (device, FP_FINGER_STATUS_NONE);
|
fpi_device_report_finger_status (device, FP_FINGER_STATUS_NONE);
|
||||||
@@ -1167,7 +1250,7 @@ fpi_device_probe_complete (FpDevice *device,
|
|||||||
/**
|
/**
|
||||||
* fpi_device_open_complete:
|
* fpi_device_open_complete:
|
||||||
* @device: The #FpDevice
|
* @device: The #FpDevice
|
||||||
* @error: The #GError or %NULL on success
|
* @error: (nullable) (transfer full): The #GError or %NULL on success
|
||||||
*
|
*
|
||||||
* Finish an ongoing open operation. If error is %NULL success is assumed.
|
* Finish an ongoing open operation. If error is %NULL success is assumed.
|
||||||
*/
|
*/
|
||||||
@@ -1179,7 +1262,12 @@ fpi_device_open_complete (FpDevice *device, GError *error)
|
|||||||
g_return_if_fail (FP_IS_DEVICE (device));
|
g_return_if_fail (FP_IS_DEVICE (device));
|
||||||
g_return_if_fail (priv->current_action == FPI_DEVICE_ACTION_OPEN);
|
g_return_if_fail (priv->current_action == FPI_DEVICE_ACTION_OPEN);
|
||||||
|
|
||||||
g_debug ("Device reported open completion");
|
if (!g_log_writer_default_would_drop (G_LOG_LEVEL_DEBUG, G_LOG_DOMAIN))
|
||||||
|
{
|
||||||
|
g_autofree char *error_str = error_to_string (error);
|
||||||
|
|
||||||
|
g_debug ("Device reported open completion (error: %s)", error_str);
|
||||||
|
}
|
||||||
|
|
||||||
clear_device_cancel_action (device);
|
clear_device_cancel_action (device);
|
||||||
fpi_device_report_finger_status (device, FP_FINGER_STATUS_NONE);
|
fpi_device_report_finger_status (device, FP_FINGER_STATUS_NONE);
|
||||||
@@ -1194,20 +1282,25 @@ fpi_device_open_complete (FpDevice *device, GError *error)
|
|||||||
/**
|
/**
|
||||||
* fpi_device_close_complete:
|
* fpi_device_close_complete:
|
||||||
* @device: The #FpDevice
|
* @device: The #FpDevice
|
||||||
* @error: The #GError or %NULL on success
|
* @error: (nullable) (transfer full): The #GError or %NULL on success
|
||||||
*
|
*
|
||||||
* Finish an ongoing close operation. If error is %NULL success is assumed.
|
* Finish an ongoing close operation. If error is %NULL success is assumed.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
fpi_device_close_complete (FpDevice *device, GError *error)
|
fpi_device_close_complete (FpDevice *device, GError *error)
|
||||||
{
|
{
|
||||||
GError *nested_error = NULL;
|
g_autoptr(GError) nested_error = NULL;
|
||||||
FpDevicePrivate *priv = fp_device_get_instance_private (device);
|
FpDevicePrivate *priv = fp_device_get_instance_private (device);
|
||||||
|
|
||||||
g_return_if_fail (FP_IS_DEVICE (device));
|
g_return_if_fail (FP_IS_DEVICE (device));
|
||||||
g_return_if_fail (priv->current_action == FPI_DEVICE_ACTION_CLOSE);
|
g_return_if_fail (priv->current_action == FPI_DEVICE_ACTION_CLOSE);
|
||||||
|
|
||||||
g_debug ("Device reported close completion");
|
if (!g_log_writer_default_would_drop (G_LOG_LEVEL_DEBUG, G_LOG_DOMAIN))
|
||||||
|
{
|
||||||
|
g_autofree char *error_str = error_to_string (error);
|
||||||
|
|
||||||
|
g_debug ("Device reported close completion (error: %s)", error_str);
|
||||||
|
}
|
||||||
|
|
||||||
clear_device_cancel_action (device);
|
clear_device_cancel_action (device);
|
||||||
fpi_device_report_finger_status (device, FP_FINGER_STATUS_NONE);
|
fpi_device_report_finger_status (device, FP_FINGER_STATUS_NONE);
|
||||||
@@ -1218,7 +1311,8 @@ fpi_device_close_complete (FpDevice *device, GError *error)
|
|||||||
if (!g_usb_device_close (priv->usb_device, &nested_error))
|
if (!g_usb_device_close (priv->usb_device, &nested_error))
|
||||||
{
|
{
|
||||||
if (error == NULL)
|
if (error == NULL)
|
||||||
error = nested_error;
|
error = g_steal_pointer (&nested_error);
|
||||||
|
|
||||||
fpi_device_return_task_in_idle (device, FP_DEVICE_TASK_RETURN_ERROR, error);
|
fpi_device_return_task_in_idle (device, FP_DEVICE_TASK_RETURN_ERROR, error);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1246,7 +1340,7 @@ fpi_device_close_complete (FpDevice *device, GError *error)
|
|||||||
* fpi_device_enroll_complete:
|
* fpi_device_enroll_complete:
|
||||||
* @device: The #FpDevice
|
* @device: The #FpDevice
|
||||||
* @print: (nullable) (transfer full): The #FpPrint or %NULL on failure
|
* @print: (nullable) (transfer full): The #FpPrint or %NULL on failure
|
||||||
* @error: The #GError or %NULL on success
|
* @error: (nullable) (transfer full): The #GError or %NULL on success
|
||||||
*
|
*
|
||||||
* Finish an ongoing enroll operation. The #FpPrint can be stored by the
|
* Finish an ongoing enroll operation. The #FpPrint can be stored by the
|
||||||
* caller for later verification.
|
* caller for later verification.
|
||||||
@@ -1259,7 +1353,13 @@ fpi_device_enroll_complete (FpDevice *device, FpPrint *print, GError *error)
|
|||||||
g_return_if_fail (FP_IS_DEVICE (device));
|
g_return_if_fail (FP_IS_DEVICE (device));
|
||||||
g_return_if_fail (priv->current_action == FPI_DEVICE_ACTION_ENROLL);
|
g_return_if_fail (priv->current_action == FPI_DEVICE_ACTION_ENROLL);
|
||||||
|
|
||||||
g_debug ("Device reported enroll completion");
|
if (!g_log_writer_default_would_drop (G_LOG_LEVEL_DEBUG, G_LOG_DOMAIN))
|
||||||
|
{
|
||||||
|
g_autofree char *error_str = error_to_string (error);
|
||||||
|
|
||||||
|
g_debug ("Device reported enroll completion (print: %p, error: %s)",
|
||||||
|
print, error_str);
|
||||||
|
}
|
||||||
|
|
||||||
clear_device_cancel_action (device);
|
clear_device_cancel_action (device);
|
||||||
fpi_device_report_finger_status (device, FP_FINGER_STATUS_NONE);
|
fpi_device_report_finger_status (device, FP_FINGER_STATUS_NONE);
|
||||||
@@ -1269,7 +1369,6 @@ fpi_device_enroll_complete (FpDevice *device, FpPrint *print, GError *error)
|
|||||||
if (FP_IS_PRINT (print))
|
if (FP_IS_PRINT (print))
|
||||||
{
|
{
|
||||||
FpiPrintType print_type;
|
FpiPrintType print_type;
|
||||||
g_autofree char *finger_str = NULL;
|
|
||||||
|
|
||||||
g_object_get (print, "fpi-type", &print_type, NULL);
|
g_object_get (print, "fpi-type", &print_type, NULL);
|
||||||
if (print_type == FPI_PRINT_UNDEFINED)
|
if (print_type == FPI_PRINT_UNDEFINED)
|
||||||
@@ -1283,8 +1382,12 @@ fpi_device_enroll_complete (FpDevice *device, FpPrint *print, GError *error)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
finger_str = g_enum_to_string (FP_TYPE_FINGER, fp_print_get_finger (print));
|
if (!g_log_writer_default_would_drop (G_LOG_LEVEL_DEBUG, G_LOG_DOMAIN))
|
||||||
g_debug ("Print for finger %s enrolled", finger_str);
|
{
|
||||||
|
g_autofree char *finger_str = g_enum_to_string (FP_TYPE_FINGER, fp_print_get_finger (print));
|
||||||
|
|
||||||
|
g_debug ("Print for finger %s enrolled", finger_str);
|
||||||
|
}
|
||||||
|
|
||||||
fpi_device_return_task_in_idle (device, FP_DEVICE_TASK_RETURN_OBJECT, print);
|
fpi_device_return_task_in_idle (device, FP_DEVICE_TASK_RETURN_OBJECT, print);
|
||||||
}
|
}
|
||||||
@@ -1312,12 +1415,14 @@ fpi_device_enroll_complete (FpDevice *device, FpPrint *print, GError *error)
|
|||||||
* @device: The #FpDevice
|
* @device: The #FpDevice
|
||||||
* @error: A #GError if result is %FPI_MATCH_ERROR
|
* @error: A #GError if result is %FPI_MATCH_ERROR
|
||||||
*
|
*
|
||||||
* Finish an ongoing verify operation. The returned print should be
|
* Finish an ongoing verify operation.
|
||||||
* representing the new scan and not the one passed for verification.
|
|
||||||
*
|
*
|
||||||
* Note that @error should only be set for actual errors. In the case
|
* Note that @error should only be set for actual errors. In the case
|
||||||
* of retry errors, report these using fpi_device_verify_report()
|
* of retry errors, report these using fpi_device_verify_report()
|
||||||
* and then call this function without any error argument.
|
* and then call this function without any error argument.
|
||||||
|
*
|
||||||
|
* If @error is not set, we expect that a result (and print, in case)
|
||||||
|
* have been already reported via fpi_device_verify_report().
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
fpi_device_verify_complete (FpDevice *device,
|
fpi_device_verify_complete (FpDevice *device,
|
||||||
@@ -1329,7 +1434,12 @@ fpi_device_verify_complete (FpDevice *device,
|
|||||||
g_return_if_fail (FP_IS_DEVICE (device));
|
g_return_if_fail (FP_IS_DEVICE (device));
|
||||||
g_return_if_fail (priv->current_action == FPI_DEVICE_ACTION_VERIFY);
|
g_return_if_fail (priv->current_action == FPI_DEVICE_ACTION_VERIFY);
|
||||||
|
|
||||||
g_debug ("Device reported verify completion");
|
if (!g_log_writer_default_would_drop (G_LOG_LEVEL_DEBUG, G_LOG_DOMAIN))
|
||||||
|
{
|
||||||
|
g_autofree char *error_str = error_to_string (error);
|
||||||
|
|
||||||
|
g_debug ("Device reported verify completion (error: %s)", error_str);
|
||||||
|
}
|
||||||
|
|
||||||
data = g_task_get_task_data (priv->current_task);
|
data = g_task_get_task_data (priv->current_task);
|
||||||
|
|
||||||
@@ -1373,11 +1483,16 @@ fpi_device_verify_complete (FpDevice *device,
|
|||||||
/**
|
/**
|
||||||
* fpi_device_identify_complete:
|
* fpi_device_identify_complete:
|
||||||
* @device: The #FpDevice
|
* @device: The #FpDevice
|
||||||
* @error: The #GError or %NULL on success
|
* @error: (nullable) (transfer full): The #GError or %NULL on success
|
||||||
*
|
*
|
||||||
* Finish an ongoing identify operation. The match that was identified is
|
* Finish an ongoing identify operation.
|
||||||
* returned in @match. The @print parameter returns the newly created scan
|
*
|
||||||
* that was used for matching.
|
* Note that @error should only be set for actual errors. In the case
|
||||||
|
* of retry errors, report these using fpi_device_identify_report()
|
||||||
|
* and then call this function without any error argument.
|
||||||
|
*
|
||||||
|
* If @error is not set, we expect that a match and / or a print have been
|
||||||
|
* already reported via fpi_device_identify_report()
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
fpi_device_identify_complete (FpDevice *device,
|
fpi_device_identify_complete (FpDevice *device,
|
||||||
@@ -1389,7 +1504,12 @@ fpi_device_identify_complete (FpDevice *device,
|
|||||||
g_return_if_fail (FP_IS_DEVICE (device));
|
g_return_if_fail (FP_IS_DEVICE (device));
|
||||||
g_return_if_fail (priv->current_action == FPI_DEVICE_ACTION_IDENTIFY);
|
g_return_if_fail (priv->current_action == FPI_DEVICE_ACTION_IDENTIFY);
|
||||||
|
|
||||||
g_debug ("Device reported identify completion");
|
if (!g_log_writer_default_would_drop (G_LOG_LEVEL_DEBUG, G_LOG_DOMAIN))
|
||||||
|
{
|
||||||
|
g_autofree char *error_str = error_to_string (error);
|
||||||
|
|
||||||
|
g_debug ("Device reported identify completion (error: %s)", error_str);
|
||||||
|
}
|
||||||
|
|
||||||
data = g_task_get_task_data (priv->current_task);
|
data = g_task_get_task_data (priv->current_task);
|
||||||
|
|
||||||
@@ -1434,7 +1554,7 @@ fpi_device_identify_complete (FpDevice *device,
|
|||||||
* fpi_device_capture_complete:
|
* fpi_device_capture_complete:
|
||||||
* @device: The #FpDevice
|
* @device: The #FpDevice
|
||||||
* @image: The #FpImage, or %NULL on error
|
* @image: The #FpImage, or %NULL on error
|
||||||
* @error: The #GError or %NULL on success
|
* @error: (nullable) (transfer full): The #GError or %NULL on success
|
||||||
*
|
*
|
||||||
* Finish an ongoing capture operation.
|
* Finish an ongoing capture operation.
|
||||||
*/
|
*/
|
||||||
@@ -1448,7 +1568,13 @@ fpi_device_capture_complete (FpDevice *device,
|
|||||||
g_return_if_fail (FP_IS_DEVICE (device));
|
g_return_if_fail (FP_IS_DEVICE (device));
|
||||||
g_return_if_fail (priv->current_action == FPI_DEVICE_ACTION_CAPTURE);
|
g_return_if_fail (priv->current_action == FPI_DEVICE_ACTION_CAPTURE);
|
||||||
|
|
||||||
g_debug ("Device reported capture completion");
|
if (!g_log_writer_default_would_drop (G_LOG_LEVEL_DEBUG, G_LOG_DOMAIN))
|
||||||
|
{
|
||||||
|
g_autofree char *error_str = error_to_string (error);
|
||||||
|
|
||||||
|
g_debug ("Device reported capture completion (image: %p, error: %s)",
|
||||||
|
image, error_str);
|
||||||
|
}
|
||||||
|
|
||||||
clear_device_cancel_action (device);
|
clear_device_cancel_action (device);
|
||||||
fpi_device_report_finger_status (device, FP_FINGER_STATUS_NONE);
|
fpi_device_report_finger_status (device, FP_FINGER_STATUS_NONE);
|
||||||
@@ -1481,7 +1607,7 @@ fpi_device_capture_complete (FpDevice *device,
|
|||||||
/**
|
/**
|
||||||
* fpi_device_delete_complete:
|
* fpi_device_delete_complete:
|
||||||
* @device: The #FpDevice
|
* @device: The #FpDevice
|
||||||
* @error: The #GError or %NULL on success
|
* @error: (nullable) (transfer full): The #GError or %NULL on success
|
||||||
*
|
*
|
||||||
* Finish an ongoing delete operation.
|
* Finish an ongoing delete operation.
|
||||||
*/
|
*/
|
||||||
@@ -1494,7 +1620,12 @@ fpi_device_delete_complete (FpDevice *device,
|
|||||||
g_return_if_fail (FP_IS_DEVICE (device));
|
g_return_if_fail (FP_IS_DEVICE (device));
|
||||||
g_return_if_fail (priv->current_action == FPI_DEVICE_ACTION_DELETE);
|
g_return_if_fail (priv->current_action == FPI_DEVICE_ACTION_DELETE);
|
||||||
|
|
||||||
g_debug ("Device reported deletion completion");
|
if (!g_log_writer_default_would_drop (G_LOG_LEVEL_DEBUG, G_LOG_DOMAIN))
|
||||||
|
{
|
||||||
|
g_autofree char *error_str = error_to_string (error);
|
||||||
|
|
||||||
|
g_debug ("Device reported delete completion (error: %s)", error_str);
|
||||||
|
}
|
||||||
|
|
||||||
clear_device_cancel_action (device);
|
clear_device_cancel_action (device);
|
||||||
fpi_device_report_finger_status (device, FP_FINGER_STATUS_NONE);
|
fpi_device_report_finger_status (device, FP_FINGER_STATUS_NONE);
|
||||||
@@ -1510,7 +1641,7 @@ fpi_device_delete_complete (FpDevice *device,
|
|||||||
* fpi_device_list_complete:
|
* fpi_device_list_complete:
|
||||||
* @device: The #FpDevice
|
* @device: The #FpDevice
|
||||||
* @prints: (element-type FpPrint) (transfer container): Possibly empty array of prints or %NULL on error
|
* @prints: (element-type FpPrint) (transfer container): Possibly empty array of prints or %NULL on error
|
||||||
* @error: The #GError or %NULL on success
|
* @error: (nullable) (transfer full): The #GError or %NULL on success
|
||||||
*
|
*
|
||||||
* Finish an ongoing list operation.
|
* Finish an ongoing list operation.
|
||||||
*
|
*
|
||||||
@@ -1529,7 +1660,13 @@ fpi_device_list_complete (FpDevice *device,
|
|||||||
g_return_if_fail (FP_IS_DEVICE (device));
|
g_return_if_fail (FP_IS_DEVICE (device));
|
||||||
g_return_if_fail (priv->current_action == FPI_DEVICE_ACTION_LIST);
|
g_return_if_fail (priv->current_action == FPI_DEVICE_ACTION_LIST);
|
||||||
|
|
||||||
g_debug ("Device reported listing completion");
|
if (!g_log_writer_default_would_drop (G_LOG_LEVEL_DEBUG, G_LOG_DOMAIN))
|
||||||
|
{
|
||||||
|
g_autofree char *error_str = error_to_string (error);
|
||||||
|
|
||||||
|
g_debug ("Device reported listing completion (prints: %ld, error: %s)",
|
||||||
|
prints ? (long) prints->len : -1, error_str);
|
||||||
|
}
|
||||||
|
|
||||||
clear_device_cancel_action (device);
|
clear_device_cancel_action (device);
|
||||||
fpi_device_report_finger_status (device, FP_FINGER_STATUS_NONE);
|
fpi_device_report_finger_status (device, FP_FINGER_STATUS_NONE);
|
||||||
@@ -1596,11 +1733,13 @@ update_attr (const char *attr, const char *value)
|
|||||||
static void
|
static void
|
||||||
complete_suspend_resume_task (FpDevice *device)
|
complete_suspend_resume_task (FpDevice *device)
|
||||||
{
|
{
|
||||||
|
g_autoptr(GTask) task = NULL;
|
||||||
FpDevicePrivate *priv = fp_device_get_instance_private (device);
|
FpDevicePrivate *priv = fp_device_get_instance_private (device);
|
||||||
|
|
||||||
g_assert (priv->suspend_resume_task);
|
g_assert (priv->suspend_resume_task);
|
||||||
|
task = g_steal_pointer (&priv->suspend_resume_task);
|
||||||
|
|
||||||
g_task_return_boolean (g_steal_pointer (&priv->suspend_resume_task), TRUE);
|
g_task_return_boolean (task, TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -1704,9 +1843,9 @@ fpi_device_configure_wakeup (FpDevice *device, gboolean enabled)
|
|||||||
case FP_DEVICE_TYPE_USB:
|
case FP_DEVICE_TYPE_USB:
|
||||||
{
|
{
|
||||||
g_autoptr(GString) ports = NULL;
|
g_autoptr(GString) ports = NULL;
|
||||||
GUsbDevice *dev, *parent;
|
g_autoptr(GUsbDevice) dev = NULL;
|
||||||
const char *wakeup_command = enabled ? "enabled" : "disabled";
|
const char *wakeup_command = enabled ? "enabled" : "disabled";
|
||||||
guint8 bus, port;
|
guint8 bus;
|
||||||
g_autofree gchar *sysfs_wakeup = NULL;
|
g_autofree gchar *sysfs_wakeup = NULL;
|
||||||
g_autofree gchar *sysfs_persist = NULL;
|
g_autofree gchar *sysfs_persist = NULL;
|
||||||
int res;
|
int res;
|
||||||
@@ -1715,12 +1854,20 @@ fpi_device_configure_wakeup (FpDevice *device, gboolean enabled)
|
|||||||
bus = g_usb_device_get_bus (priv->usb_device);
|
bus = g_usb_device_get_bus (priv->usb_device);
|
||||||
|
|
||||||
/* Walk up, skipping the root hub. */
|
/* Walk up, skipping the root hub. */
|
||||||
dev = priv->usb_device;
|
g_set_object (&dev, priv->usb_device);
|
||||||
while ((parent = g_usb_device_get_parent (dev)))
|
while (TRUE)
|
||||||
{
|
{
|
||||||
|
g_autoptr(GUsbDevice) parent = g_usb_device_get_parent (dev);
|
||||||
|
g_autofree gchar *port_str = NULL;
|
||||||
|
guint8 port;
|
||||||
|
|
||||||
|
if (!parent)
|
||||||
|
break;
|
||||||
|
|
||||||
port = g_usb_device_get_port_number (dev);
|
port = g_usb_device_get_port_number (dev);
|
||||||
g_string_prepend (ports, g_strdup_printf ("%d.", port));
|
port_str = g_strdup_printf ("%d.", port);
|
||||||
dev = parent;
|
g_string_prepend (ports, port_str);
|
||||||
|
g_set_object (&dev, parent);
|
||||||
}
|
}
|
||||||
g_string_set_size (ports, ports->len - 1);
|
g_string_set_size (ports, ports->len - 1);
|
||||||
|
|
||||||
@@ -1757,6 +1904,7 @@ fpi_device_configure_wakeup (FpDevice *device, gboolean enabled)
|
|||||||
static void
|
static void
|
||||||
fpi_device_suspend_completed (FpDevice *device)
|
fpi_device_suspend_completed (FpDevice *device)
|
||||||
{
|
{
|
||||||
|
g_autoptr(GTask) task = NULL;
|
||||||
FpDevicePrivate *priv = fp_device_get_instance_private (device);
|
FpDevicePrivate *priv = fp_device_get_instance_private (device);
|
||||||
|
|
||||||
/* We have an ongoing operation, allow the device to wake up the machine. */
|
/* We have an ongoing operation, allow the device to wake up the machine. */
|
||||||
@@ -1766,17 +1914,18 @@ fpi_device_suspend_completed (FpDevice *device)
|
|||||||
if (priv->critical_section)
|
if (priv->critical_section)
|
||||||
g_warning ("Driver was in a critical section at suspend time. It likely deadlocked!");
|
g_warning ("Driver was in a critical section at suspend time. It likely deadlocked!");
|
||||||
|
|
||||||
|
task = g_steal_pointer (&priv->suspend_resume_task);
|
||||||
|
|
||||||
if (priv->suspend_error)
|
if (priv->suspend_error)
|
||||||
g_task_return_error (g_steal_pointer (&priv->suspend_resume_task),
|
g_task_return_error (task, g_steal_pointer (&priv->suspend_error));
|
||||||
g_steal_pointer (&priv->suspend_error));
|
|
||||||
else
|
else
|
||||||
g_task_return_boolean (g_steal_pointer (&priv->suspend_resume_task), TRUE);
|
g_task_return_boolean (task, TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* fpi_device_suspend_complete:
|
* fpi_device_suspend_complete:
|
||||||
* @device: The #FpDevice
|
* @device: The #FpDevice
|
||||||
* @error: The #GError or %NULL on success
|
* @error: (nullable) (transfer full): The #GError or %NULL on success
|
||||||
*
|
*
|
||||||
* Finish a suspend request. Only return a %NULL error if suspend has been
|
* Finish a suspend request. Only return a %NULL error if suspend has been
|
||||||
* correctly configured and the current action as returned by
|
* correctly configured and the current action as returned by
|
||||||
@@ -1786,7 +1935,7 @@ fpi_device_suspend_completed (FpDevice *device)
|
|||||||
* current action will be cancelled before the error is forwarded to the
|
* current action will be cancelled before the error is forwarded to the
|
||||||
* application.
|
* application.
|
||||||
*
|
*
|
||||||
* It is recommended to set @error to #FP_ERROR_NOT_IMPLEMENTED.
|
* It is recommended to set @error to #FP_DEVICE_ERROR_NOT_SUPPORTED.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
fpi_device_suspend_complete (FpDevice *device,
|
fpi_device_suspend_complete (FpDevice *device,
|
||||||
@@ -1798,11 +1947,19 @@ fpi_device_suspend_complete (FpDevice *device,
|
|||||||
g_return_if_fail (priv->suspend_resume_task);
|
g_return_if_fail (priv->suspend_resume_task);
|
||||||
g_return_if_fail (priv->suspend_error == NULL);
|
g_return_if_fail (priv->suspend_error == NULL);
|
||||||
|
|
||||||
priv->suspend_error = error;
|
if (!g_log_writer_default_would_drop (G_LOG_LEVEL_DEBUG, G_LOG_DOMAIN))
|
||||||
|
{
|
||||||
|
g_autofree char *error_str = error_to_string (error);
|
||||||
|
|
||||||
|
g_debug ("Device reported suspend completion (error: %s)", error_str);
|
||||||
|
}
|
||||||
|
|
||||||
|
priv->suspend_error = g_steal_pointer (&error);
|
||||||
priv->is_suspended = TRUE;
|
priv->is_suspended = TRUE;
|
||||||
|
|
||||||
/* If there is no error, we have no running task, return immediately. */
|
/* If there is no error, we have no running task, return immediately. */
|
||||||
if (error == NULL || !priv->current_task || g_task_get_completed (priv->current_task))
|
if (!priv->suspend_error || !priv->current_task ||
|
||||||
|
g_task_get_completed (priv->current_task))
|
||||||
{
|
{
|
||||||
fpi_device_suspend_completed (device);
|
fpi_device_suspend_completed (device);
|
||||||
return;
|
return;
|
||||||
@@ -1826,7 +1983,7 @@ fpi_device_suspend_complete (FpDevice *device,
|
|||||||
/**
|
/**
|
||||||
* fpi_device_resume_complete:
|
* fpi_device_resume_complete:
|
||||||
* @device: The #FpDevice
|
* @device: The #FpDevice
|
||||||
* @error: The #GError or %NULL on success
|
* @error: (nullable) (transfer full): The #GError or %NULL on success
|
||||||
*
|
*
|
||||||
* Finish a resume request.
|
* Finish a resume request.
|
||||||
*/
|
*/
|
||||||
@@ -1834,24 +1991,34 @@ void
|
|||||||
fpi_device_resume_complete (FpDevice *device,
|
fpi_device_resume_complete (FpDevice *device,
|
||||||
GError *error)
|
GError *error)
|
||||||
{
|
{
|
||||||
|
g_autoptr(GTask) task = NULL;
|
||||||
FpDevicePrivate *priv = fp_device_get_instance_private (device);
|
FpDevicePrivate *priv = fp_device_get_instance_private (device);
|
||||||
|
|
||||||
g_return_if_fail (FP_IS_DEVICE (device));
|
g_return_if_fail (FP_IS_DEVICE (device));
|
||||||
g_return_if_fail (priv->suspend_resume_task);
|
g_return_if_fail (priv->suspend_resume_task);
|
||||||
|
|
||||||
|
if (!g_log_writer_default_would_drop (G_LOG_LEVEL_DEBUG, G_LOG_DOMAIN))
|
||||||
|
{
|
||||||
|
g_autofree char *error_str = error_to_string (error);
|
||||||
|
|
||||||
|
g_debug ("Device reported resume completion (error: %s)", error_str);
|
||||||
|
}
|
||||||
|
|
||||||
priv->is_suspended = FALSE;
|
priv->is_suspended = FALSE;
|
||||||
fpi_device_configure_wakeup (device, FALSE);
|
fpi_device_configure_wakeup (device, FALSE);
|
||||||
|
|
||||||
|
task = g_steal_pointer (&priv->suspend_resume_task);
|
||||||
|
|
||||||
if (error)
|
if (error)
|
||||||
g_task_return_error (g_steal_pointer (&priv->suspend_resume_task), error);
|
g_task_return_error (task, error);
|
||||||
else
|
else
|
||||||
g_task_return_boolean (g_steal_pointer (&priv->suspend_resume_task), TRUE);
|
g_task_return_boolean (task, TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* fpi_device_clear_storage_complete:
|
* fpi_device_clear_storage_complete:
|
||||||
* @device: The #FpDevice
|
* @device: The #FpDevice
|
||||||
* @error: The #GError or %NULL on success
|
* @error: (nullable) (transfer full): The #GError or %NULL on success
|
||||||
*
|
*
|
||||||
* Finish an ongoing clear_storage operation.
|
* Finish an ongoing clear_storage operation.
|
||||||
*/
|
*/
|
||||||
@@ -1864,7 +2031,12 @@ fpi_device_clear_storage_complete (FpDevice *device,
|
|||||||
g_return_if_fail (FP_IS_DEVICE (device));
|
g_return_if_fail (FP_IS_DEVICE (device));
|
||||||
g_return_if_fail (priv->current_action == FPI_DEVICE_ACTION_CLEAR_STORAGE);
|
g_return_if_fail (priv->current_action == FPI_DEVICE_ACTION_CLEAR_STORAGE);
|
||||||
|
|
||||||
g_debug ("Device reported deletion completion");
|
if (!g_log_writer_default_would_drop (G_LOG_LEVEL_DEBUG, G_LOG_DOMAIN))
|
||||||
|
{
|
||||||
|
g_autofree char *error_str = error_to_string (error);
|
||||||
|
|
||||||
|
g_debug ("Device reported clear storage completion (error: %s)", error_str);
|
||||||
|
}
|
||||||
|
|
||||||
clear_device_cancel_action (device);
|
clear_device_cancel_action (device);
|
||||||
fpi_device_report_finger_status (device, FP_FINGER_STATUS_NONE);
|
fpi_device_report_finger_status (device, FP_FINGER_STATUS_NONE);
|
||||||
@@ -1882,7 +2054,7 @@ fpi_device_clear_storage_complete (FpDevice *device,
|
|||||||
* @device: The #FpDevice
|
* @device: The #FpDevice
|
||||||
* @completed_stages: The number of stages that are completed at this point
|
* @completed_stages: The number of stages that are completed at this point
|
||||||
* @print: (transfer floating): The #FpPrint for the newly completed stage or %NULL on failure
|
* @print: (transfer floating): The #FpPrint for the newly completed stage or %NULL on failure
|
||||||
* @error: (transfer full): The #GError or %NULL on success
|
* @error: (nullable) (transfer full): The #GError or %NULL on success
|
||||||
*
|
*
|
||||||
* Notify about the progress of the enroll operation. This is important for UI interaction.
|
* Notify about the progress of the enroll operation. This is important for UI interaction.
|
||||||
* The passed error may be used if a scan needs to be retried, use fpi_device_retry_new().
|
* The passed error may be used if a scan needs to be retried, use fpi_device_retry_new().
|
||||||
@@ -1953,7 +2125,14 @@ fpi_device_verify_report (FpDevice *device,
|
|||||||
|
|
||||||
data->result_reported = TRUE;
|
data->result_reported = TRUE;
|
||||||
|
|
||||||
g_debug ("Device reported verify result");
|
if (!g_log_writer_default_would_drop (G_LOG_LEVEL_DEBUG, G_LOG_DOMAIN))
|
||||||
|
{
|
||||||
|
g_autofree char *result_str = g_enum_to_string (FPI_TYPE_MATCH_RESULT, result);
|
||||||
|
g_autofree char *error_str = error_to_string (error);
|
||||||
|
|
||||||
|
g_debug ("Device reported verify result (result: %s, print: %p, error: %s)",
|
||||||
|
result_str, print, error_str);
|
||||||
|
}
|
||||||
|
|
||||||
if (print)
|
if (print)
|
||||||
print = g_object_ref_sink (print);
|
print = g_object_ref_sink (print);
|
||||||
@@ -1989,6 +2168,14 @@ fpi_device_verify_report (FpDevice *device,
|
|||||||
{
|
{
|
||||||
fpi_device_get_verify_data (device, &data->match);
|
fpi_device_get_verify_data (device, &data->match);
|
||||||
g_object_ref (data->match);
|
g_object_ref (data->match);
|
||||||
|
|
||||||
|
if (print &&
|
||||||
|
fpi_print_get_type (print) != FPI_PRINT_NBIS &&
|
||||||
|
!fp_print_equal (print, data->match))
|
||||||
|
{
|
||||||
|
g_warning ("Driver reported a match providing a scanned print that is not matching it.");
|
||||||
|
g_clear_object (&print);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
data->print = g_steal_pointer (&print);
|
data->print = g_steal_pointer (&print);
|
||||||
@@ -2002,12 +2189,26 @@ fpi_device_verify_report (FpDevice *device,
|
|||||||
* fpi_device_identify_report:
|
* fpi_device_identify_report:
|
||||||
* @device: The #FpDevice
|
* @device: The #FpDevice
|
||||||
* @match: (transfer none): The #FpPrint from the gallery that matched
|
* @match: (transfer none): The #FpPrint from the gallery that matched
|
||||||
* @print: (transfer floating): The scanned #FpPrint
|
* @print: (transfer floating): The scanned #FpPrint, set in the absence
|
||||||
* @error: A #GError if result is %FPI_MATCH_ERROR
|
* of an error.
|
||||||
|
* @error: A #GError of %FP_DEVICE_RETRY type if @match and @print are unset.
|
||||||
*
|
*
|
||||||
* Report the result of a identify operation. Note that the passed @error must be
|
* Report the results of an identify operation.
|
||||||
* a retry error with the %FP_DEVICE_RETRY domain. For all other error cases,
|
*
|
||||||
* the error should passed to fpi_device_identify_complete().
|
* In case of successful identification @match is expected to be set to a
|
||||||
|
* #FpPrint that matches one from the provided gallery, while @print
|
||||||
|
* represents the scanned print and will be different.
|
||||||
|
*
|
||||||
|
* If there are no errors, it's expected that the device always reports the
|
||||||
|
* recognized @print even if there is no @match with the provided gallery (that
|
||||||
|
* can be potentially empty). This is required for application logic further
|
||||||
|
* up in the stack, such as for enroll-duplicate checking. @print needs to be
|
||||||
|
* sufficiently filled to do a comparison.
|
||||||
|
*
|
||||||
|
* In case of error, both @match and @print are expected to be %NULL.
|
||||||
|
* Note that the passed @error must be a retry error from the %FP_DEVICE_RETRY
|
||||||
|
* domain. For all other error cases, the error should passed to
|
||||||
|
* fpi_device_identify_complete().
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
fpi_device_identify_report (FpDevice *device,
|
fpi_device_identify_report (FpDevice *device,
|
||||||
@@ -2031,14 +2232,20 @@ fpi_device_identify_report (FpDevice *device,
|
|||||||
if (print)
|
if (print)
|
||||||
print = g_object_ref_sink (print);
|
print = g_object_ref_sink (print);
|
||||||
|
|
||||||
|
if (!g_log_writer_default_would_drop (G_LOG_LEVEL_DEBUG, G_LOG_DOMAIN))
|
||||||
|
{
|
||||||
|
g_autofree char *error_str = error_to_string (error);
|
||||||
|
|
||||||
|
g_debug ("Device reported identify result (match: %p, print: %p, error: %s)",
|
||||||
|
match, print, error_str);
|
||||||
|
}
|
||||||
|
|
||||||
if (match && !g_ptr_array_find (data->gallery, match, NULL))
|
if (match && !g_ptr_array_find (data->gallery, match, NULL))
|
||||||
{
|
{
|
||||||
g_warning ("Driver reported a match to a print that was not in the gallery, ignoring match.");
|
g_warning ("Driver reported a match to a print that was not in the gallery, ignoring match.");
|
||||||
g_clear_object (&match);
|
g_clear_object (&match);
|
||||||
}
|
}
|
||||||
|
|
||||||
g_debug ("Device reported identify result");
|
|
||||||
|
|
||||||
if (error)
|
if (error)
|
||||||
{
|
{
|
||||||
if (match != NULL)
|
if (match != NULL)
|
||||||
@@ -2063,6 +2270,14 @@ fpi_device_identify_report (FpDevice *device,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
if (match && print && fpi_print_get_type (print) != FPI_PRINT_NBIS &&
|
||||||
|
!g_ptr_array_find_with_equal_func (data->gallery, print,
|
||||||
|
(GEqualFunc) fp_print_equal, NULL))
|
||||||
|
{
|
||||||
|
g_warning ("Driver reported a match providing a scanned print that is not matching any in the gallery.");
|
||||||
|
g_clear_object (&print);
|
||||||
|
}
|
||||||
|
|
||||||
if (match)
|
if (match)
|
||||||
data->match = g_steal_pointer (&match);
|
data->match = g_steal_pointer (&match);
|
||||||
|
|
||||||
@@ -2089,13 +2304,21 @@ fpi_device_report_finger_status (FpDevice *device,
|
|||||||
FpFingerStatusFlags finger_status)
|
FpFingerStatusFlags finger_status)
|
||||||
{
|
{
|
||||||
FpDevicePrivate *priv = fp_device_get_instance_private (device);
|
FpDevicePrivate *priv = fp_device_get_instance_private (device);
|
||||||
g_autofree char *status_string = NULL;
|
|
||||||
|
|
||||||
if (priv->finger_status == finger_status)
|
if (priv->finger_status == finger_status)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
status_string = g_flags_to_string (FP_TYPE_FINGER_STATUS_FLAGS, finger_status);
|
if (!g_log_writer_default_would_drop (G_LOG_LEVEL_DEBUG, G_LOG_DOMAIN))
|
||||||
fp_dbg ("Device reported finger status change: %s", status_string);
|
{
|
||||||
|
g_autofree char *status_string = NULL;
|
||||||
|
g_autofree char *old_status_string = NULL;
|
||||||
|
|
||||||
|
old_status_string = g_flags_to_string (FP_TYPE_FINGER_STATUS_FLAGS, priv->finger_status);
|
||||||
|
status_string = g_flags_to_string (FP_TYPE_FINGER_STATUS_FLAGS, finger_status);
|
||||||
|
|
||||||
|
g_debug ("Device reported finger status change: %s -> %s",
|
||||||
|
old_status_string, status_string);
|
||||||
|
}
|
||||||
|
|
||||||
priv->finger_status = finger_status;
|
priv->finger_status = finger_status;
|
||||||
g_object_notify (G_OBJECT (device), "finger-status");
|
g_object_notify (G_OBJECT (device), "finger-status");
|
||||||
@@ -2156,8 +2379,6 @@ fpi_device_update_temp (FpDevice *device, gboolean is_active)
|
|||||||
gdouble next_threshold;
|
gdouble next_threshold;
|
||||||
gdouble old_ratio;
|
gdouble old_ratio;
|
||||||
FpTemperature old_temp;
|
FpTemperature old_temp;
|
||||||
g_autofree char *old_temp_str = NULL;
|
|
||||||
g_autofree char *new_temp_str = NULL;
|
|
||||||
|
|
||||||
if (priv->temp_hot_seconds < 0)
|
if (priv->temp_hot_seconds < 0)
|
||||||
{
|
{
|
||||||
@@ -2207,16 +2428,20 @@ fpi_device_update_temp (FpDevice *device, gboolean is_active)
|
|||||||
next_threshold = is_active ? -1.0 : TEMP_HOT_WARM_THRESH;
|
next_threshold = is_active ? -1.0 : TEMP_HOT_WARM_THRESH;
|
||||||
}
|
}
|
||||||
|
|
||||||
old_temp_str = g_enum_to_string (FP_TYPE_TEMPERATURE, old_temp);
|
if (!g_log_writer_default_would_drop (G_LOG_LEVEL_DEBUG, G_LOG_DOMAIN))
|
||||||
new_temp_str = g_enum_to_string (FP_TYPE_TEMPERATURE, priv->temp_current);
|
{
|
||||||
g_debug ("Updated temperature model after %0.2f seconds, ratio %0.2f -> %0.2f, active %d -> %d, %s -> %s",
|
g_autofree char *old_temp_str = g_enum_to_string (FP_TYPE_TEMPERATURE, old_temp);
|
||||||
passed_seconds,
|
g_autofree char *new_temp_str = g_enum_to_string (FP_TYPE_TEMPERATURE, priv->temp_current);
|
||||||
old_ratio,
|
|
||||||
priv->temp_current_ratio,
|
g_debug ("Updated temperature model after %0.2f seconds, ratio %0.2f -> %0.2f, active %d -> %d, %s -> %s",
|
||||||
priv->temp_last_active,
|
passed_seconds,
|
||||||
is_active,
|
old_ratio,
|
||||||
old_temp_str,
|
priv->temp_current_ratio,
|
||||||
new_temp_str);
|
priv->temp_last_active,
|
||||||
|
is_active,
|
||||||
|
old_temp_str,
|
||||||
|
new_temp_str);
|
||||||
|
}
|
||||||
|
|
||||||
if (priv->temp_current != old_temp)
|
if (priv->temp_current != old_temp)
|
||||||
g_object_notify (G_OBJECT (device), "temperature");
|
g_object_notify (G_OBJECT (device), "temperature");
|
||||||
|
|||||||
+16
-2
@@ -38,6 +38,13 @@ typedef enum {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* FpIdEntry:
|
* FpIdEntry:
|
||||||
|
* @pid: The USB product ID (for USB devices)
|
||||||
|
* @vid: The USB vendor ID (for USB devices)
|
||||||
|
* @virtual_envvar: Environment variable name (for virtual devices)
|
||||||
|
* @driver_data: Optional driver-specific data, defaults to 0
|
||||||
|
* @udev_types: Subtypes for udev-based devices
|
||||||
|
* @spi_acpi_id: ACPI ID (for SPI devices)
|
||||||
|
* @hid_id: HID device identifier (for HID devices)
|
||||||
*
|
*
|
||||||
* An entry in the table of supported hardware. For USB devices, the product ID
|
* An entry in the table of supported hardware. For USB devices, the product ID
|
||||||
* and vendor ID should be provided. The optional @driver_data field defaults
|
* and vendor ID should be provided. The optional @driver_data field defaults
|
||||||
@@ -100,7 +107,8 @@ struct _FpIdEntry
|
|||||||
* guaranteed to only happen when the device is open (this includes delete).
|
* guaranteed to only happen when the device is open (this includes delete).
|
||||||
* @close: Close the device again
|
* @close: Close the device again
|
||||||
* @enroll: Start an enroll operation
|
* @enroll: Start an enroll operation
|
||||||
* @verify: Start a verify operation
|
* @verify: Start a verify operation (it will be implemented via @identify
|
||||||
|
* if not overriden).
|
||||||
* @identify: Start an identify operation
|
* @identify: Start an identify operation
|
||||||
* @capture: Start a capture operation
|
* @capture: Start a capture operation
|
||||||
* @list: List prints stored on the device
|
* @list: List prints stored on the device
|
||||||
@@ -221,7 +229,6 @@ 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,
|
gpointer fpi_device_get_udev_data (FpDevice *device,
|
||||||
FpiDeviceUdevSubtypeFlags subtype);
|
FpiDeviceUdevSubtypeFlags subtype);
|
||||||
//const gchar *fpi_device_get_spi_dev (FpDevice *device);
|
|
||||||
|
|
||||||
|
|
||||||
FpiDeviceAction fpi_device_get_current_action (FpDevice *device);
|
FpiDeviceAction fpi_device_get_current_action (FpDevice *device);
|
||||||
@@ -325,4 +332,11 @@ gboolean fpi_device_report_finger_status_changes (FpDevice *device,
|
|||||||
FpFingerStatusFlags added_status,
|
FpFingerStatusFlags added_status,
|
||||||
FpFingerStatusFlags removed_status);
|
FpFingerStatusFlags removed_status);
|
||||||
|
|
||||||
|
/* Debugging utilities */
|
||||||
|
|
||||||
|
#define fpi_device_emulation_mode_enabled(dev) \
|
||||||
|
G_UNLIKELY ((fpi_device_emulation_mode_enabled) ((dev)))
|
||||||
|
|
||||||
|
gboolean (fpi_device_emulation_mode_enabled) (FpDevice *device);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|||||||
@@ -120,10 +120,13 @@ fp_image_device_change_state (FpImageDevice *self, FpiImageDeviceState state)
|
|||||||
{ FPI_IMAGE_DEVICE_STATE_DEACTIVATING, FPI_IMAGE_DEVICE_STATE_INACTIVE },
|
{ FPI_IMAGE_DEVICE_STATE_DEACTIVATING, FPI_IMAGE_DEVICE_STATE_INACTIVE },
|
||||||
};
|
};
|
||||||
|
|
||||||
prev_state_str = g_enum_to_string (FPI_TYPE_IMAGE_DEVICE_STATE, priv->state);
|
if (!g_log_writer_default_would_drop (G_LOG_LEVEL_DEBUG, G_LOG_DOMAIN))
|
||||||
state_str = g_enum_to_string (FPI_TYPE_IMAGE_DEVICE_STATE, state);
|
{
|
||||||
fp_dbg ("Image device internal state change from %s to %s",
|
prev_state_str = g_enum_to_string (FPI_TYPE_IMAGE_DEVICE_STATE, priv->state);
|
||||||
prev_state_str, state_str);
|
state_str = g_enum_to_string (FPI_TYPE_IMAGE_DEVICE_STATE, state);
|
||||||
|
fp_dbg ("Image device internal state change from %s to %s",
|
||||||
|
prev_state_str, state_str);
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0; i < G_N_ELEMENTS (valid_transitions); i++)
|
for (i = 0; i < G_N_ELEMENTS (valid_transitions); i++)
|
||||||
{
|
{
|
||||||
@@ -134,8 +137,15 @@ fp_image_device_change_state (FpImageDevice *self, FpiImageDeviceState state)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!transition_is_valid)
|
if (!transition_is_valid)
|
||||||
g_warning ("Internal state machine issue: transition from %s to %s should not happen!",
|
{
|
||||||
prev_state_str, state_str);
|
if (!prev_state_str)
|
||||||
|
prev_state_str = g_enum_to_string (FPI_TYPE_IMAGE_DEVICE_STATE, priv->state);
|
||||||
|
if (!state_str)
|
||||||
|
state_str = g_enum_to_string (FPI_TYPE_IMAGE_DEVICE_STATE, state);
|
||||||
|
|
||||||
|
g_warning ("Internal state machine issue: transition from %s to %s should not happen!",
|
||||||
|
prev_state_str, state_str);
|
||||||
|
}
|
||||||
|
|
||||||
priv->state = state;
|
priv->state = state;
|
||||||
g_object_notify (G_OBJECT (self), "fpi-image-device-state");
|
g_object_notify (G_OBJECT (self), "fpi-image-device-state");
|
||||||
@@ -214,10 +224,6 @@ fp_image_device_maybe_complete_action (FpImageDevice *self, GError *error)
|
|||||||
|
|
||||||
fpi_device_enroll_complete (device, g_object_ref (enroll_print), NULL);
|
fpi_device_enroll_complete (device, g_object_ref (enroll_print), NULL);
|
||||||
}
|
}
|
||||||
else if (action == FPI_DEVICE_ACTION_VERIFY)
|
|
||||||
{
|
|
||||||
fpi_device_verify_complete (device, NULL);
|
|
||||||
}
|
|
||||||
else if (action == FPI_DEVICE_ACTION_IDENTIFY)
|
else if (action == FPI_DEVICE_ACTION_IDENTIFY)
|
||||||
{
|
{
|
||||||
fpi_device_identify_complete (device, NULL);
|
fpi_device_identify_complete (device, NULL);
|
||||||
@@ -316,22 +322,6 @@ fpi_image_device_minutiae_detected (GObject *source_object, GAsyncResult *res, g
|
|||||||
fp_image_device_enroll_maybe_await_finger_on (FP_IMAGE_DEVICE (device));
|
fp_image_device_enroll_maybe_await_finger_on (FP_IMAGE_DEVICE (device));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (action == FPI_DEVICE_ACTION_VERIFY)
|
|
||||||
{
|
|
||||||
FpPrint *template;
|
|
||||||
FpiMatchResult result;
|
|
||||||
|
|
||||||
fpi_device_get_verify_data (device, &template);
|
|
||||||
if (print)
|
|
||||||
result = fpi_print_bz3_match (template, print, priv->bz3_threshold, &error);
|
|
||||||
else
|
|
||||||
result = FPI_MATCH_ERROR;
|
|
||||||
|
|
||||||
if (!error || error->domain == FP_DEVICE_RETRY)
|
|
||||||
fpi_device_verify_report (device, result, g_steal_pointer (&print), g_steal_pointer (&error));
|
|
||||||
|
|
||||||
fp_image_device_maybe_complete_action (self, g_steal_pointer (&error));
|
|
||||||
}
|
|
||||||
else if (action == FPI_DEVICE_ACTION_IDENTIFY)
|
else if (action == FPI_DEVICE_ACTION_IDENTIFY)
|
||||||
{
|
{
|
||||||
gint i;
|
gint i;
|
||||||
@@ -486,7 +476,6 @@ fpi_image_device_image_captured (FpImageDevice *self, FpImage *image)
|
|||||||
g_return_if_fail (image != NULL);
|
g_return_if_fail (image != NULL);
|
||||||
g_return_if_fail (priv->state == FPI_IMAGE_DEVICE_STATE_CAPTURE);
|
g_return_if_fail (priv->state == FPI_IMAGE_DEVICE_STATE_CAPTURE);
|
||||||
g_return_if_fail (action == FPI_DEVICE_ACTION_ENROLL ||
|
g_return_if_fail (action == FPI_DEVICE_ACTION_ENROLL ||
|
||||||
action == FPI_DEVICE_ACTION_VERIFY ||
|
|
||||||
action == FPI_DEVICE_ACTION_IDENTIFY ||
|
action == FPI_DEVICE_ACTION_IDENTIFY ||
|
||||||
action == FPI_DEVICE_ACTION_CAPTURE);
|
action == FPI_DEVICE_ACTION_CAPTURE);
|
||||||
|
|
||||||
@@ -527,7 +516,6 @@ fpi_image_device_retry_scan (FpImageDevice *self, FpDeviceRetry retry)
|
|||||||
* all but INACTIVE */
|
* all but INACTIVE */
|
||||||
g_return_if_fail (priv->state != FPI_IMAGE_DEVICE_STATE_INACTIVE);
|
g_return_if_fail (priv->state != FPI_IMAGE_DEVICE_STATE_INACTIVE);
|
||||||
g_return_if_fail (action == FPI_DEVICE_ACTION_ENROLL ||
|
g_return_if_fail (action == FPI_DEVICE_ACTION_ENROLL ||
|
||||||
action == FPI_DEVICE_ACTION_VERIFY ||
|
|
||||||
action == FPI_DEVICE_ACTION_IDENTIFY ||
|
action == FPI_DEVICE_ACTION_IDENTIFY ||
|
||||||
action == FPI_DEVICE_ACTION_CAPTURE);
|
action == FPI_DEVICE_ACTION_CAPTURE);
|
||||||
|
|
||||||
@@ -540,13 +528,6 @@ fpi_image_device_retry_scan (FpImageDevice *self, FpDeviceRetry retry)
|
|||||||
|
|
||||||
fp_image_device_change_state (self, FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_OFF);
|
fp_image_device_change_state (self, FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_OFF);
|
||||||
}
|
}
|
||||||
else if (action == FPI_DEVICE_ACTION_VERIFY)
|
|
||||||
{
|
|
||||||
fpi_device_verify_report (FP_DEVICE (self), FPI_MATCH_ERROR, NULL, error);
|
|
||||||
fp_image_device_maybe_complete_action (self, NULL);
|
|
||||||
fpi_image_device_deactivate (self, TRUE);
|
|
||||||
|
|
||||||
}
|
|
||||||
else if (action == FPI_DEVICE_ACTION_IDENTIFY)
|
else if (action == FPI_DEVICE_ACTION_IDENTIFY)
|
||||||
{
|
{
|
||||||
fpi_device_identify_report (FP_DEVICE (self), NULL, NULL, error);
|
fpi_device_identify_report (FP_DEVICE (self), NULL, NULL, error);
|
||||||
@@ -565,7 +546,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: The #GError to report
|
* @error: (nullable) (transfer full): 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 +605,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: A #GError or %NULL on success
|
* @error: (nullable) (transfer full): The #GError or %NULL on success
|
||||||
*
|
*
|
||||||
* Reports completion of device activation.
|
* Reports completion of device activation.
|
||||||
*/
|
*/
|
||||||
@@ -639,7 +620,6 @@ fpi_image_device_activate_complete (FpImageDevice *self, GError *error)
|
|||||||
g_return_if_fail (priv->active == FALSE);
|
g_return_if_fail (priv->active == FALSE);
|
||||||
g_return_if_fail (priv->state == FPI_IMAGE_DEVICE_STATE_ACTIVATING);
|
g_return_if_fail (priv->state == FPI_IMAGE_DEVICE_STATE_ACTIVATING);
|
||||||
g_return_if_fail (action == FPI_DEVICE_ACTION_ENROLL ||
|
g_return_if_fail (action == FPI_DEVICE_ACTION_ENROLL ||
|
||||||
action == FPI_DEVICE_ACTION_VERIFY ||
|
|
||||||
action == FPI_DEVICE_ACTION_IDENTIFY ||
|
action == FPI_DEVICE_ACTION_IDENTIFY ||
|
||||||
action == FPI_DEVICE_ACTION_CAPTURE);
|
action == FPI_DEVICE_ACTION_CAPTURE);
|
||||||
|
|
||||||
@@ -663,7 +643,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: A #GError or %NULL on success
|
* @error: (nullable) (transfer full): The #GError or %NULL on success
|
||||||
*
|
*
|
||||||
* Reports completion of device deactivation.
|
* Reports completion of device deactivation.
|
||||||
*/
|
*/
|
||||||
@@ -690,7 +670,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: A #GError or %NULL on success
|
* @error: (nullable) (transfer full): The #GError or %NULL on success
|
||||||
*
|
*
|
||||||
* Reports completion of open operation.
|
* Reports completion of open operation.
|
||||||
*/
|
*/
|
||||||
@@ -718,7 +698,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: A #GError or %NULL on success
|
* @error: (nullable) (transfer full): The #GError or %NULL on success
|
||||||
*
|
*
|
||||||
* Reports completion of close operation.
|
* Reports completion of close operation.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -24,8 +24,9 @@
|
|||||||
#include "fpi-log.h"
|
#include "fpi-log.h"
|
||||||
|
|
||||||
#include <nbis.h>
|
#include <nbis.h>
|
||||||
|
#include <config.h>
|
||||||
|
|
||||||
#if HAVE_PIXMAN
|
#ifdef HAVE_PIXMAN
|
||||||
#include <pixman.h>
|
#include <pixman.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -107,12 +108,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;
|
||||||
@@ -145,5 +146,9 @@ 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,7 +20,6 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <config.h>
|
|
||||||
#include "fp-image.h"
|
#include "fp-image.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -28,12 +27,14 @@
|
|||||||
* @FPI_IMAGE_V_FLIPPED: the image is vertically flipped
|
* @FPI_IMAGE_V_FLIPPED: the image is vertically flipped
|
||||||
* @FPI_IMAGE_H_FLIPPED: the image is horizontally flipped
|
* @FPI_IMAGE_H_FLIPPED: the image is horizontally flipped
|
||||||
* @FPI_IMAGE_COLORS_INVERTED: the colours are inverted
|
* @FPI_IMAGE_COLORS_INVERTED: the colours are inverted
|
||||||
|
* @FPI_IMAGE_PARTIAL: the image is a partial scan
|
||||||
*
|
*
|
||||||
* Flags used in an #FpImage structure to describe the contained image.
|
* Flags used in an #FpImage structure to describe the contained image.
|
||||||
* This is useful for image drivers as they can simply set these flags and
|
* This is useful for image drivers as they can simply set these flags and
|
||||||
* rely on the image to be normalized by libfprint before further processing.
|
* 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,7 +69,8 @@ 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,
|
||||||
@@ -77,8 +79,6 @@ 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
|
|
||||||
|
|||||||
@@ -0,0 +1,88 @@
|
|||||||
|
/*
|
||||||
|
* FpiLog - Internal logging functions
|
||||||
|
* Copyright (C) 2020 Benjamin Berg <bberg@redhat.com>
|
||||||
|
* Copyright (C) 2025 Joshua Grisham <josh@joshuagrisham.com>
|
||||||
|
* Copyright (C) 2026 Marco Trevisan (Treviño) <mail@3v1n0.net>
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "fpi-log.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fpi_log_is_debug_transfer_enabled:
|
||||||
|
*
|
||||||
|
* Checks if the %FP_DEBUG_TRANSFER environment variable is set.
|
||||||
|
*
|
||||||
|
* Returns: %TRUE if %FP_DEBUG_TRANSFER is set, %FALSE otherwise
|
||||||
|
*/
|
||||||
|
gboolean
|
||||||
|
fpi_log_is_debug_transfer_enabled (void)
|
||||||
|
{
|
||||||
|
static gsize debug_transfer_enabled = 0;
|
||||||
|
|
||||||
|
if (g_once_init_enter (&debug_transfer_enabled))
|
||||||
|
{
|
||||||
|
gsize enabled = g_getenv ("FP_DEBUG_TRANSFER") != NULL ? TRUE : G_MAXSIZE;
|
||||||
|
g_once_init_leave (&debug_transfer_enabled, enabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
return debug_transfer_enabled == TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fpi_dbg_hex_dump_data:
|
||||||
|
* @buf: Bytes buffer to dump
|
||||||
|
* @len: Length of @buf to dump
|
||||||
|
*
|
||||||
|
* Prints hex dump of @buf to fp_dbg()
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
(fpi_dbg_hex_dump_data) (const gchar *log_domain,
|
||||||
|
const guint8 *buf,
|
||||||
|
gsize len)
|
||||||
|
{
|
||||||
|
g_autoptr(GString) line = NULL;
|
||||||
|
|
||||||
|
if (g_log_writer_default_would_drop (G_LOG_LEVEL_DEBUG, log_domain))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (G_UNLIKELY (len == 0 || !buf))
|
||||||
|
return;
|
||||||
|
|
||||||
|
line = g_string_new ("");
|
||||||
|
|
||||||
|
for (gint i = 0; i < len; i++)
|
||||||
|
g_string_append_printf (line, "%02x", buf[i]);
|
||||||
|
|
||||||
|
if (line->len)
|
||||||
|
g_log (log_domain, G_LOG_LEVEL_DEBUG, "%s", line->str);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fpi_dbg_hex_dump_bytes:
|
||||||
|
* @bytes: #GBytes to dump
|
||||||
|
*
|
||||||
|
* Prints hex dump of @bytes to fp_dbg()
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
(fpi_dbg_hex_dump_bytes) (const gchar *log_domain,
|
||||||
|
GBytes *bytes)
|
||||||
|
{
|
||||||
|
gsize length = 0;
|
||||||
|
const guint8 *data = g_bytes_get_data (bytes, &length);
|
||||||
|
|
||||||
|
(fpi_dbg_hex_dump_data) (log_domain, data, length);
|
||||||
|
}
|
||||||
+36
-3
@@ -1,6 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2007-2008 Daniel Drake <dsd@gentoo.org>
|
* Copyright (C) 2007-2008 Daniel Drake <dsd@gentoo.org>
|
||||||
* Copyright (C) 2018 Bastien Nocera <hadess@hadess.net>
|
* Copyright (C) 2018 Bastien Nocera <hadess@hadess.net>
|
||||||
|
* Copyright (C) 2026 Marco Trevisan (Treviño) <mail@3v1n0.net>
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or
|
* This library is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
@@ -79,13 +80,16 @@
|
|||||||
*
|
*
|
||||||
* Uses fp_err() to print an error if the @condition is true.
|
* Uses fp_err() to print an error if the @condition is true.
|
||||||
*/
|
*/
|
||||||
#define BUG_ON(condition) G_STMT_START \
|
#define BUG_ON(condition) \
|
||||||
if (condition) { \
|
G_STMT_START \
|
||||||
|
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:
|
||||||
@@ -93,3 +97,32 @@
|
|||||||
* Same as BUG_ON() but is always true.
|
* Same as BUG_ON() but is always true.
|
||||||
*/
|
*/
|
||||||
#define BUG() BUG_ON (1)
|
#define BUG() BUG_ON (1)
|
||||||
|
|
||||||
|
void (fpi_dbg_hex_dump_data) (const gchar *log_domain,
|
||||||
|
const guint8 *buf,
|
||||||
|
gsize len);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fp_dbg_hex_dump_data:
|
||||||
|
* @buf: Bytes buffer to dump
|
||||||
|
* @len: Length of @buf to dump
|
||||||
|
*
|
||||||
|
* Prints hex dump of @buf to fp_dbg()
|
||||||
|
*/
|
||||||
|
#define fp_dbg_hex_dump_data(buf, len) \
|
||||||
|
(fpi_dbg_hex_dump_data) (G_LOG_DOMAIN, (buf), (len))
|
||||||
|
|
||||||
|
void (fpi_dbg_hex_dump_bytes) (const gchar *log_domain,
|
||||||
|
GBytes *bytes);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fp_dbg_hex_dump_bytes:
|
||||||
|
* @bytes: #GBytes to dump
|
||||||
|
*
|
||||||
|
* Prints hex dump of @bytes to fp_dbg()
|
||||||
|
*/
|
||||||
|
#define fp_dbg_hex_dump_bytes(bytes) \
|
||||||
|
(fpi_dbg_hex_dump_bytes) \
|
||||||
|
(G_LOG_DOMAIN, (bytes))
|
||||||
|
|
||||||
|
gboolean fpi_log_is_debug_transfer_enabled (void);
|
||||||
|
|||||||
+26
-7
@@ -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_memdup (add->prints->pdata[0], sizeof (struct xyt_struct)));
|
g_ptr_array_add (print->prints, g_memdup2 (add->prints->pdata[0], sizeof (struct xyt_struct)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -79,6 +79,22 @@ fpi_print_set_type (FpPrint *print,
|
|||||||
g_object_notify (G_OBJECT (print), "fpi-type");
|
g_object_notify (G_OBJECT (print), "fpi-type");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fpi_print_get_type:
|
||||||
|
* @print: A #FpPrint
|
||||||
|
*
|
||||||
|
* Retrieves the type of the print data.
|
||||||
|
*
|
||||||
|
* Returns: The #FpiPrintType of the print.
|
||||||
|
*/
|
||||||
|
FpiPrintType
|
||||||
|
fpi_print_get_type (FpPrint *print)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (FP_IS_PRINT (print), FPI_PRINT_UNDEFINED);
|
||||||
|
|
||||||
|
return print->type;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* fpi_print_set_device_stored:
|
* fpi_print_set_device_stored:
|
||||||
* @print: A #FpPrint
|
* @print: A #FpPrint
|
||||||
@@ -196,7 +212,7 @@ fpi_print_add_from_image (FpPrint *print,
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* fpi_print_bz3_match:
|
* fpi_print_bz3_match:
|
||||||
* @template: A #FpPrint containing one or more prints
|
* @print_template: A #FpPrint containing one or more prints
|
||||||
* @print: A newly scanned #FpPrint to test
|
* @print: A newly scanned #FpPrint to test
|
||||||
* @bz3_threshold: The BZ3 match threshold
|
* @bz3_threshold: The BZ3 match threshold
|
||||||
* @error: Return location for error
|
* @error: Return location for error
|
||||||
@@ -210,14 +226,17 @@ fpi_print_add_from_image (FpPrint *print,
|
|||||||
* Returns: Whether the prints match, @error will be set if #FPI_MATCH_ERROR is returned
|
* Returns: Whether the prints match, @error will be set if #FPI_MATCH_ERROR is returned
|
||||||
*/
|
*/
|
||||||
FpiMatchResult
|
FpiMatchResult
|
||||||
fpi_print_bz3_match (FpPrint *template, FpPrint *print, gint bz3_threshold, GError **error)
|
fpi_print_bz3_match (FpPrint *print_template,
|
||||||
|
FpPrint *print,
|
||||||
|
gint bz3_threshold,
|
||||||
|
GError **error)
|
||||||
{
|
{
|
||||||
struct xyt_struct *pstruct;
|
struct xyt_struct *pstruct;
|
||||||
gint probe_len;
|
gint probe_len;
|
||||||
gint i;
|
gint i;
|
||||||
|
|
||||||
/* XXX: Use a different error type? */
|
/* XXX: Use a different error type? */
|
||||||
if (template->type != FPI_PRINT_NBIS || print->type != FPI_PRINT_NBIS)
|
if (print_template->type != FPI_PRINT_NBIS || print->type != FPI_PRINT_NBIS)
|
||||||
{
|
{
|
||||||
*error = fpi_device_error_new_msg (FP_DEVICE_ERROR_NOT_SUPPORTED,
|
*error = fpi_device_error_new_msg (FP_DEVICE_ERROR_NOT_SUPPORTED,
|
||||||
"It is only possible to match NBIS type print data");
|
"It is only possible to match NBIS type print data");
|
||||||
@@ -234,11 +253,11 @@ fpi_print_bz3_match (FpPrint *template, FpPrint *print, gint bz3_threshold, GErr
|
|||||||
pstruct = g_ptr_array_index (print->prints, 0);
|
pstruct = g_ptr_array_index (print->prints, 0);
|
||||||
probe_len = bozorth_probe_init (pstruct);
|
probe_len = bozorth_probe_init (pstruct);
|
||||||
|
|
||||||
for (i = 0; i < template->prints->len; i++)
|
for (i = 0; i < print_template->prints->len; i++)
|
||||||
{
|
{
|
||||||
struct xyt_struct *gstruct;
|
struct xyt_struct *gstruct;
|
||||||
gint score;
|
gint score;
|
||||||
gstruct = g_ptr_array_index (template->prints, i);
|
gstruct = g_ptr_array_index (print_template->prints, i);
|
||||||
score = bozorth_to_gallery (probe_len, pstruct, gstruct);
|
score = bozorth_to_gallery (probe_len, pstruct, gstruct);
|
||||||
fp_dbg ("score %d/%d", score, bz3_threshold);
|
fp_dbg ("score %d/%d", score, bz3_threshold);
|
||||||
|
|
||||||
@@ -292,7 +311,7 @@ fpi_print_generate_user_id (FpPrint *print)
|
|||||||
if (!username)
|
if (!username)
|
||||||
username = "nobody";
|
username = "nobody";
|
||||||
|
|
||||||
if (g_strcmp0 (g_getenv ("FP_DEVICE_EMULATION"), "1") == 0)
|
if (fpi_device_emulation_mode_enabled (NULL))
|
||||||
rand_id = 0;
|
rand_id = 0;
|
||||||
else
|
else
|
||||||
rand_id = g_random_int ();
|
rand_id = g_random_int ();
|
||||||
|
|||||||
@@ -35,6 +35,9 @@ void fpi_print_add_print (FpPrint *print,
|
|||||||
|
|
||||||
void fpi_print_set_type (FpPrint *print,
|
void fpi_print_set_type (FpPrint *print,
|
||||||
FpiPrintType type);
|
FpiPrintType type);
|
||||||
|
|
||||||
|
FpiPrintType fpi_print_get_type (FpPrint *print);
|
||||||
|
|
||||||
void fpi_print_set_device_stored (FpPrint *print,
|
void fpi_print_set_device_stored (FpPrint *print,
|
||||||
gboolean device_stored);
|
gboolean device_stored);
|
||||||
|
|
||||||
@@ -42,7 +45,7 @@ gboolean fpi_print_add_from_image (FpPrint *print,
|
|||||||
FpImage *image,
|
FpImage *image,
|
||||||
GError **error);
|
GError **error);
|
||||||
|
|
||||||
FpiMatchResult fpi_print_bz3_match (FpPrint *temp,
|
FpiMatchResult fpi_print_bz3_match (FpPrint *print_template,
|
||||||
FpPrint *print,
|
FpPrint *print,
|
||||||
gint bz3_threshold,
|
gint bz3_threshold,
|
||||||
GError **error);
|
GError **error);
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "fpi-spi-transfer.h"
|
#include "fpi-spi-transfer.h"
|
||||||
|
#include "fpi-log.h"
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
#include <linux/spi/spidev.h>
|
#include <linux/spi/spidev.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
@@ -41,38 +42,17 @@ static gsize block_size = 0;
|
|||||||
* Drivers should always use this API rather than calling read/write/ioctl on
|
* Drivers should always use this API rather than calling read/write/ioctl on
|
||||||
* the spidev device.
|
* the spidev device.
|
||||||
*
|
*
|
||||||
* Setting G_MESSAGES_DEBUG and FP_DEBUG_TRANSFER will result in the message
|
* Setting %G_MESSAGES_DEBUG and %FP_DEBUG_TRANSFER will result in the message
|
||||||
* content to be dumped.
|
* content to be dumped.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
G_DEFINE_BOXED_TYPE (FpiSpiTransfer, fpi_spi_transfer, fpi_spi_transfer_ref, fpi_spi_transfer_unref)
|
G_DEFINE_BOXED_TYPE (FpiSpiTransfer, fpi_spi_transfer, fpi_spi_transfer_ref, fpi_spi_transfer_unref)
|
||||||
|
|
||||||
static void
|
|
||||||
dump_buffer (guchar *buf, gssize dump_len)
|
|
||||||
{
|
|
||||||
g_autoptr(GString) line = NULL;
|
|
||||||
|
|
||||||
line = g_string_new ("");
|
|
||||||
/* Dump the buffer. */
|
|
||||||
for (gssize i = 0; i < dump_len; i++)
|
|
||||||
{
|
|
||||||
g_string_append_printf (line, "%02x ", buf[i]);
|
|
||||||
if ((i + 1) % 16 == 0)
|
|
||||||
{
|
|
||||||
g_debug ("%s", line->str);
|
|
||||||
g_string_set_size (line, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (line->len)
|
|
||||||
g_debug ("%s", line->str);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
log_transfer (FpiSpiTransfer *transfer, gboolean submit, GError *error)
|
log_transfer (FpiSpiTransfer *transfer, gboolean submit, GError *error)
|
||||||
{
|
{
|
||||||
if (g_getenv ("FP_DEBUG_TRANSFER"))
|
if (fpi_log_is_debug_transfer_enabled ())
|
||||||
{
|
{
|
||||||
if (submit)
|
if (submit)
|
||||||
{
|
{
|
||||||
@@ -82,7 +62,7 @@ log_transfer (FpiSpiTransfer *transfer, gboolean submit, GError *error)
|
|||||||
transfer->length_rd);
|
transfer->length_rd);
|
||||||
|
|
||||||
if (transfer->buffer_wr)
|
if (transfer->buffer_wr)
|
||||||
dump_buffer (transfer->buffer_wr, transfer->length_wr);
|
fp_dbg_hex_dump_data (transfer->buffer_wr, transfer->length_wr);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -98,7 +78,7 @@ log_transfer (FpiSpiTransfer *transfer, gboolean submit, GError *error)
|
|||||||
transfer->length_wr,
|
transfer->length_wr,
|
||||||
transfer->length_rd);
|
transfer->length_rd);
|
||||||
if (transfer->buffer_rd)
|
if (transfer->buffer_rd)
|
||||||
dump_buffer (transfer->buffer_rd, transfer->length_rd);
|
fp_dbg_hex_dump_data (transfer->buffer_rd, transfer->length_rd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+21
-15
@@ -73,7 +73,7 @@
|
|||||||
struct _FpiSsm
|
struct _FpiSsm
|
||||||
{
|
{
|
||||||
FpDevice *dev;
|
FpDevice *dev;
|
||||||
const char *name;
|
char *name;
|
||||||
FpiSsm *parentsm;
|
FpiSsm *parentsm;
|
||||||
gpointer ssm_data;
|
gpointer ssm_data;
|
||||||
GDestroyNotify ssm_data_destroy;
|
GDestroyNotify ssm_data_destroy;
|
||||||
@@ -615,7 +615,7 @@ fpi_ssm_get_cur_state (FpiSsm *machine)
|
|||||||
*
|
*
|
||||||
* Returns the error code set by fpi_ssm_mark_failed().
|
* Returns the error code set by fpi_ssm_mark_failed().
|
||||||
*
|
*
|
||||||
* Returns: (transfer none): a error code
|
* Returns: (transfer none): a #GError or %NULL if not set.
|
||||||
*/
|
*/
|
||||||
GError *
|
GError *
|
||||||
fpi_ssm_get_error (FpiSsm *machine)
|
fpi_ssm_get_error (FpiSsm *machine)
|
||||||
@@ -631,7 +631,7 @@ fpi_ssm_get_error (FpiSsm *machine)
|
|||||||
*
|
*
|
||||||
* Returns the error code set by fpi_ssm_mark_failed().
|
* Returns the error code set by fpi_ssm_mark_failed().
|
||||||
*
|
*
|
||||||
* Returns: (transfer full): a error code
|
* Returns: (transfer full): a #GError or %NULL if not set.
|
||||||
*/
|
*/
|
||||||
GError *
|
GError *
|
||||||
fpi_ssm_dup_error (FpiSsm *machine)
|
fpi_ssm_dup_error (FpiSsm *machine)
|
||||||
@@ -657,6 +657,8 @@ fpi_ssm_dup_error (FpiSsm *machine)
|
|||||||
void
|
void
|
||||||
fpi_ssm_silence_debug (FpiSsm *machine)
|
fpi_ssm_silence_debug (FpiSsm *machine)
|
||||||
{
|
{
|
||||||
|
g_return_if_fail (machine != NULL);
|
||||||
|
|
||||||
machine->silence = TRUE;
|
machine->silence = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -665,10 +667,10 @@ fpi_ssm_silence_debug (FpiSsm *machine)
|
|||||||
* @transfer: a #FpiUsbTransfer
|
* @transfer: a #FpiUsbTransfer
|
||||||
* @device: a #FpDevice
|
* @device: a #FpDevice
|
||||||
* @unused_data: User data (unused)
|
* @unused_data: User data (unused)
|
||||||
* @error: The #GError or %NULL
|
* @error: (transfer full): a #GError or %NULL.
|
||||||
*
|
*
|
||||||
* Can be used in as a #FpiUsbTransfer callback handler to automatically
|
* Can be used in as a #FpiUsbTransfer callback handler to automatically
|
||||||
* advance or fail a statemachine on transfer completion.
|
* advance or fail a state machine on transfer completion.
|
||||||
*
|
*
|
||||||
* Make sure to set the #FpiSsm on the transfer.
|
* Make sure to set the #FpiSsm on the transfer.
|
||||||
*/
|
*/
|
||||||
@@ -676,10 +678,11 @@ void
|
|||||||
fpi_ssm_usb_transfer_cb (FpiUsbTransfer *transfer, FpDevice *device,
|
fpi_ssm_usb_transfer_cb (FpiUsbTransfer *transfer, FpDevice *device,
|
||||||
gpointer unused_data, GError *error)
|
gpointer unused_data, GError *error)
|
||||||
{
|
{
|
||||||
|
g_return_if_fail (transfer != NULL);
|
||||||
g_return_if_fail (transfer->ssm);
|
g_return_if_fail (transfer->ssm);
|
||||||
|
|
||||||
if (error)
|
if (error)
|
||||||
fpi_ssm_mark_failed (transfer->ssm, error);
|
fpi_ssm_mark_failed (transfer->ssm, g_steal_pointer (&error));
|
||||||
else
|
else
|
||||||
fpi_ssm_next_state (transfer->ssm);
|
fpi_ssm_next_state (transfer->ssm);
|
||||||
}
|
}
|
||||||
@@ -691,10 +694,10 @@ fpi_ssm_usb_transfer_cb (FpiUsbTransfer *transfer, FpDevice *device,
|
|||||||
* @weak_ptr: A #gpointer pointer to nullify. You can pass a pointer to any
|
* @weak_ptr: A #gpointer pointer to nullify. You can pass a pointer to any
|
||||||
* #gpointer to nullify when the callback is completed. I.e a
|
* #gpointer to nullify when the callback is completed. I.e a
|
||||||
* pointer to the current #FpiUsbTransfer.
|
* pointer to the current #FpiUsbTransfer.
|
||||||
* @error: The #GError or %NULL
|
* @error: (transfer full): a #GError or %NULL.
|
||||||
*
|
*
|
||||||
* Can be used in as a #FpiUsbTransfer callback handler to automatically
|
* Can be used in as a #FpiUsbTransfer callback handler to automatically
|
||||||
* advance or fail a statemachine on transfer completion.
|
* advance or fail a state machine on transfer completion.
|
||||||
* Passing a #gpointer* as @weak_ptr permits to nullify it once we're done
|
* Passing a #gpointer* as @weak_ptr permits to nullify it once we're done
|
||||||
* with the transfer.
|
* with the transfer.
|
||||||
*
|
*
|
||||||
@@ -705,12 +708,13 @@ fpi_ssm_usb_transfer_with_weak_pointer_cb (FpiUsbTransfer *transfer,
|
|||||||
FpDevice *device, gpointer weak_ptr,
|
FpDevice *device, gpointer weak_ptr,
|
||||||
GError *error)
|
GError *error)
|
||||||
{
|
{
|
||||||
|
g_return_if_fail (transfer != NULL);
|
||||||
g_return_if_fail (transfer->ssm);
|
g_return_if_fail (transfer->ssm);
|
||||||
|
|
||||||
if (weak_ptr)
|
if (weak_ptr)
|
||||||
g_nullify_pointer ((gpointer *) weak_ptr);
|
g_nullify_pointer ((gpointer *) weak_ptr);
|
||||||
|
|
||||||
fpi_ssm_usb_transfer_cb (transfer, device, weak_ptr, error);
|
fpi_ssm_usb_transfer_cb (transfer, device, weak_ptr, g_steal_pointer (&error));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -718,10 +722,10 @@ fpi_ssm_usb_transfer_with_weak_pointer_cb (FpiUsbTransfer *transfer,
|
|||||||
* @transfer: a #FpiSpiTransfer
|
* @transfer: a #FpiSpiTransfer
|
||||||
* @device: a #FpDevice
|
* @device: a #FpDevice
|
||||||
* @unused_data: User data (unused)
|
* @unused_data: User data (unused)
|
||||||
* @error: The #GError or %NULL
|
* @error: (transfer full): a #GError or %NULL.
|
||||||
*
|
*
|
||||||
* Can be used in as a #FpiSpiTransfer callback handler to automatically
|
* Can be used in as a #FpiSpiTransfer callback handler to automatically
|
||||||
* advance or fail a statemachine on transfer completion.
|
* advance or fail a state machine on transfer completion.
|
||||||
*
|
*
|
||||||
* Make sure to set the #FpiSsm on the transfer.
|
* Make sure to set the #FpiSsm on the transfer.
|
||||||
*/
|
*/
|
||||||
@@ -729,10 +733,11 @@ void
|
|||||||
fpi_ssm_spi_transfer_cb (FpiSpiTransfer *transfer, FpDevice *device,
|
fpi_ssm_spi_transfer_cb (FpiSpiTransfer *transfer, FpDevice *device,
|
||||||
gpointer unused_data, GError *error)
|
gpointer unused_data, GError *error)
|
||||||
{
|
{
|
||||||
|
g_return_if_fail (transfer != NULL);
|
||||||
g_return_if_fail (transfer->ssm);
|
g_return_if_fail (transfer->ssm);
|
||||||
|
|
||||||
if (error)
|
if (error)
|
||||||
fpi_ssm_mark_failed (transfer->ssm, error);
|
fpi_ssm_mark_failed (transfer->ssm, g_steal_pointer (&error));
|
||||||
else
|
else
|
||||||
fpi_ssm_next_state (transfer->ssm);
|
fpi_ssm_next_state (transfer->ssm);
|
||||||
}
|
}
|
||||||
@@ -744,10 +749,10 @@ fpi_ssm_spi_transfer_cb (FpiSpiTransfer *transfer, FpDevice *device,
|
|||||||
* @weak_ptr: A #gpointer pointer to nullify. You can pass a pointer to any
|
* @weak_ptr: A #gpointer pointer to nullify. You can pass a pointer to any
|
||||||
* #gpointer to nullify when the callback is completed. I.e a
|
* #gpointer to nullify when the callback is completed. I.e a
|
||||||
* pointer to the current #FpiSpiTransfer.
|
* pointer to the current #FpiSpiTransfer.
|
||||||
* @error: The #GError or %NULL
|
* @error: (transfer full): a #GError or %NULL.
|
||||||
*
|
*
|
||||||
* Can be used in as a #FpiSpiTransfer callback handler to automatically
|
* Can be used in as a #FpiSpiTransfer callback handler to automatically
|
||||||
* advance or fail a statemachine on transfer completion.
|
* advance or fail a state machine on transfer completion.
|
||||||
* Passing a #gpointer* as @weak_ptr permits to nullify it once we're done
|
* Passing a #gpointer* as @weak_ptr permits to nullify it once we're done
|
||||||
* with the transfer.
|
* with the transfer.
|
||||||
*
|
*
|
||||||
@@ -758,10 +763,11 @@ fpi_ssm_spi_transfer_with_weak_pointer_cb (FpiSpiTransfer *transfer,
|
|||||||
FpDevice *device, gpointer weak_ptr,
|
FpDevice *device, gpointer weak_ptr,
|
||||||
GError *error)
|
GError *error)
|
||||||
{
|
{
|
||||||
|
g_return_if_fail (transfer != NULL);
|
||||||
g_return_if_fail (transfer->ssm);
|
g_return_if_fail (transfer->ssm);
|
||||||
|
|
||||||
if (weak_ptr)
|
if (weak_ptr)
|
||||||
g_nullify_pointer ((gpointer *) weak_ptr);
|
g_nullify_pointer ((gpointer *) weak_ptr);
|
||||||
|
|
||||||
fpi_ssm_spi_transfer_cb (transfer, device, weak_ptr, error);
|
fpi_ssm_spi_transfer_cb (transfer, device, weak_ptr, g_steal_pointer (&error));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "fpi-usb-transfer.h"
|
#include "fpi-usb-transfer.h"
|
||||||
|
#include "fpi-log.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SECTION:fpi-usb-transfer
|
* SECTION:fpi-usb-transfer
|
||||||
@@ -30,6 +31,9 @@
|
|||||||
*
|
*
|
||||||
* Drivers should use this API only rather than accessing the GUsbDevice
|
* Drivers should use this API only rather than accessing the GUsbDevice
|
||||||
* directly in most cases.
|
* directly in most cases.
|
||||||
|
*
|
||||||
|
* Setting %G_MESSAGES_DEBUG and %FP_DEBUG_TRANSFER will result in the message
|
||||||
|
* content to be dumped.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@@ -38,8 +42,10 @@ G_DEFINE_BOXED_TYPE (FpiUsbTransfer, fpi_usb_transfer, fpi_usb_transfer_ref, fpi
|
|||||||
static void
|
static void
|
||||||
log_transfer (FpiUsbTransfer *transfer, gboolean submit, GError *error)
|
log_transfer (FpiUsbTransfer *transfer, gboolean submit, GError *error)
|
||||||
{
|
{
|
||||||
if (g_getenv ("FP_DEBUG_TRANSFER"))
|
if (fpi_log_is_debug_transfer_enabled ())
|
||||||
{
|
{
|
||||||
|
gboolean is_incoming = !!(transfer->endpoint & FPI_USB_ENDPOINT_IN);
|
||||||
|
|
||||||
if (!submit)
|
if (!submit)
|
||||||
{
|
{
|
||||||
g_autofree gchar *error_str = NULL;
|
g_autofree gchar *error_str = NULL;
|
||||||
@@ -63,27 +69,13 @@ log_transfer (FpiUsbTransfer *transfer, gboolean submit, GError *error)
|
|||||||
transfer->endpoint);
|
transfer->endpoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!submit == !!(transfer->endpoint & FPI_USB_ENDPOINT_IN))
|
if (submit != is_incoming)
|
||||||
{
|
{
|
||||||
g_autoptr(GString) line = NULL;
|
gsize dump_length = is_incoming ? transfer->actual_length : transfer->length;
|
||||||
gssize dump_len;
|
|
||||||
|
|
||||||
dump_len = (transfer->endpoint & FPI_USB_ENDPOINT_IN) ? transfer->actual_length : transfer->length;
|
/* Skip hex dump if actual_length is invalid (e.g., -1 on cancelled IN transfers) */
|
||||||
|
if (dump_length <= transfer->length)
|
||||||
line = g_string_new ("");
|
fp_dbg_hex_dump_data (transfer->buffer, dump_length);
|
||||||
/* Dump the buffer. */
|
|
||||||
for (gint i = 0; i < dump_len; i++)
|
|
||||||
{
|
|
||||||
g_string_append_printf (line, "%02x ", transfer->buffer[i]);
|
|
||||||
if ((i + 1) % 16 == 0)
|
|
||||||
{
|
|
||||||
g_debug ("%s", line->str);
|
|
||||||
g_string_set_size (line, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (line->len)
|
|
||||||
g_debug ("%s", line->str);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -344,7 +336,8 @@ transfer_finish_cb (GObject *source_object, GAsyncResult *res, gpointer user_dat
|
|||||||
{
|
{
|
||||||
error = g_error_new (G_USB_DEVICE_ERROR,
|
error = g_error_new (G_USB_DEVICE_ERROR,
|
||||||
G_USB_DEVICE_ERROR_IO,
|
G_USB_DEVICE_ERROR_IO,
|
||||||
"Unexpected short error of %zd size (expected %zd)", transfer->actual_length, transfer->length);
|
"Unexpected short error of %zd size (expected %zd)",
|
||||||
|
transfer->actual_length, transfer->length);
|
||||||
}
|
}
|
||||||
|
|
||||||
callback = transfer->callback;
|
callback = transfer->callback;
|
||||||
@@ -548,3 +541,23 @@ fpi_usb_transfer_submit_sync (FpiUsbTransfer *transfer,
|
|||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fpi_usb_transfer_set_short_error:
|
||||||
|
* @transfer: The transfer to submit, must have been filled.
|
||||||
|
* @short_is_error: Whether a short transfer should be considered an error
|
||||||
|
*
|
||||||
|
* Sets whether a short transfer (a transfer in which the transferred length
|
||||||
|
* does not match the expected length) should be considered an error
|
||||||
|
*
|
||||||
|
* By default, short transfers are not considered an error, but
|
||||||
|
* drivers can enforce a further check by setting this flag.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
fpi_usb_transfer_set_short_error (FpiUsbTransfer *transfer,
|
||||||
|
gboolean short_is_error)
|
||||||
|
{
|
||||||
|
g_return_if_fail (transfer);
|
||||||
|
|
||||||
|
transfer->short_is_error = short_is_error;
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,109 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2025 Marco Trevisan <marco.trevisan@canonical.com>
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "glib.h"
|
||||||
|
#include "fpi-context.h"
|
||||||
|
#include "fpi-device.h"
|
||||||
|
|
||||||
|
#define METAINFO_BASE \
|
||||||
|
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" \
|
||||||
|
"<component>\n" \
|
||||||
|
" <id>org.freedesktop.libfprint</id>\n" \
|
||||||
|
" <name>libfprint</name>\n" \
|
||||||
|
" <metadata_license>CC0-1.0</metadata_license>\n" \
|
||||||
|
" <project_license>LGPL-2.1-or-later</project_license>\n" \
|
||||||
|
" <url type=\"homepage\">https://fprint.freedesktop.org</url>\n" \
|
||||||
|
" <url type=\"vcs-browser\">https://gitlab.freedesktop.org/libfprint/libfprint</url>\n" \
|
||||||
|
" <url type=\"help\">https://fprint.freedesktop.org/libfprint-dev</url>\n" \
|
||||||
|
" <url type=\"bugtracker\">https://gitlab.freedesktop.org/libfprint/libfprint/-/work_items</url>\n" \
|
||||||
|
" <summary>Async fingerprint readers library</summary>\n" \
|
||||||
|
" <description>\n" \
|
||||||
|
" <p>\n" \
|
||||||
|
" The fprint project aims to support for consumer fingerprint reader devices.\n" \
|
||||||
|
" </p>\n" \
|
||||||
|
" </description>\n" \
|
||||||
|
" <provides>\n" \
|
||||||
|
"%s\n" \
|
||||||
|
" </provides>\n" \
|
||||||
|
"</component>\n"
|
||||||
|
|
||||||
|
static int
|
||||||
|
driver_compare (gconstpointer p1, gconstpointer p2)
|
||||||
|
{
|
||||||
|
g_autoptr(FpDeviceClass) cls1 = g_type_class_ref (*(GType *) p1);
|
||||||
|
g_autoptr(FpDeviceClass) cls2 = g_type_class_ref (*(GType *) p2);
|
||||||
|
|
||||||
|
return g_strcmp0 (cls1->id, cls2->id);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
usb_driver_devices_append (GPtrArray *devices_list,
|
||||||
|
const FpDeviceClass *cls)
|
||||||
|
{
|
||||||
|
const FpIdEntry *entry;
|
||||||
|
|
||||||
|
if (cls->type != FP_DEVICE_TYPE_USB)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (entry = cls->id_table; entry->vid != 0; entry++)
|
||||||
|
{
|
||||||
|
if (entry->vid == 0 || entry->pid == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
g_ptr_array_add (devices_list,
|
||||||
|
g_strdup_printf ("v%04xp%04x", entry->vid, entry->pid));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main (void)
|
||||||
|
{
|
||||||
|
g_autoptr(GPtrArray) devices_list = g_ptr_array_new_with_free_func (g_free);
|
||||||
|
g_autoptr(GArray) drivers = fpi_get_driver_types ();
|
||||||
|
g_autoptr(GString) provided_modules = g_string_new (NULL);
|
||||||
|
g_autoptr(GError) error = NULL;
|
||||||
|
|
||||||
|
g_log_writer_default_set_use_stderr (TRUE);
|
||||||
|
|
||||||
|
g_array_sort (drivers, driver_compare);
|
||||||
|
|
||||||
|
for (guint i = 0; i < drivers->len; ++i)
|
||||||
|
{
|
||||||
|
GType driver = g_array_index (drivers, GType, i);
|
||||||
|
g_autoptr(FpDeviceClass) cls = g_type_class_ref (driver);
|
||||||
|
|
||||||
|
if (cls->type != FP_DEVICE_TYPE_USB)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
usb_driver_devices_append (devices_list, cls);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (guint i = 0; i < devices_list->len; ++i)
|
||||||
|
{
|
||||||
|
const char *device_id = g_ptr_array_index (devices_list, i);
|
||||||
|
|
||||||
|
g_string_append (provided_modules, " ");
|
||||||
|
g_string_append_printf (provided_modules, "<modalias>usb:%s*</modalias>",
|
||||||
|
device_id);
|
||||||
|
|
||||||
|
if (i < devices_list->len - 1)
|
||||||
|
g_string_append_c (provided_modules, '\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
g_print (METAINFO_BASE, provided_modules->str);
|
||||||
|
}
|
||||||
@@ -110,7 +110,7 @@ main (int argc, char **argv)
|
|||||||
|
|
||||||
printed = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
|
printed = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
|
||||||
|
|
||||||
g_print ("%% lifprint — Supported Devices\n");
|
g_print ("%% libfprint — Supported Devices\n");
|
||||||
g_print ("%% Bastien Nocera, Daniel Drake\n");
|
g_print ("%% Bastien Nocera, Daniel Drake\n");
|
||||||
g_print ("%% 2018\n");
|
g_print ("%% 2018\n");
|
||||||
g_print ("\n");
|
g_print ("\n");
|
||||||
@@ -132,7 +132,7 @@ main (int argc, char **argv)
|
|||||||
g_print ("%s", (char *) l->data);
|
g_print ("%s", (char *) l->data);
|
||||||
g_print ("\n");
|
g_print ("\n");
|
||||||
|
|
||||||
g_list_free_full (usb_list, g_free);
|
g_list_free_full (g_steal_pointer (&usb_list), g_free);
|
||||||
|
|
||||||
g_print ("## SPI devices\n");
|
g_print ("## SPI devices\n");
|
||||||
g_print ("\n");
|
g_print ("\n");
|
||||||
@@ -146,7 +146,7 @@ main (int argc, char **argv)
|
|||||||
g_print ("%s", (char *) l->data);
|
g_print ("%s", (char *) l->data);
|
||||||
g_print ("\n");
|
g_print ("\n");
|
||||||
|
|
||||||
g_list_free_full (usb_list, g_free);
|
g_list_free_full (g_steal_pointer (&spi_list), g_free);
|
||||||
|
|
||||||
|
|
||||||
g_hash_table_destroy (printed);
|
g_hash_table_destroy (printed);
|
||||||
|
|||||||
@@ -24,39 +24,87 @@
|
|||||||
#include "fpi-context.h"
|
#include "fpi-context.h"
|
||||||
#include "fpi-device.h"
|
#include "fpi-device.h"
|
||||||
|
|
||||||
static const FpIdEntry whitelist_id_table[] = {
|
static const FpIdEntry allowlist_id_table[] = {
|
||||||
/* Currently known and unsupported devices.
|
/* Currently known and unsupported devices.
|
||||||
* You can generate this list from the wiki page using e.g.:
|
* You can regenerate this list from the wiki page with:
|
||||||
* gio cat https://gitlab.freedesktop.org/libfprint/wiki/-/wikis/Unsupported-Devices.md | sed -n 's!|.*\([0-9a-fA-F]\{4\}\):\([0-9a-fA-F]\{4\}\).*|.*! { .vid = 0x\1, .pid = 0x\2 },!p'
|
* meson compile -C <build-dir> sync-unsupported-devices
|
||||||
*/
|
*/
|
||||||
|
/* --- BEGIN GENERATED IDS --- */
|
||||||
|
{ .vid = 0x006b, .pid = 0x00da },
|
||||||
|
{ .vid = 0x0413, .pid = 0x2766 },
|
||||||
|
{ .vid = 0x045e, .pid = 0x0815 },
|
||||||
|
{ .vid = 0x047d, .pid = 0x00f2 },
|
||||||
|
{ .vid = 0x047d, .pid = 0x8054 },
|
||||||
|
{ .vid = 0x047d, .pid = 0x8055 },
|
||||||
|
{ .vid = 0x0483, .pid = 0x2016 },
|
||||||
{ .vid = 0x04e8, .pid = 0x730b },
|
{ .vid = 0x04e8, .pid = 0x730b },
|
||||||
|
{ .vid = 0x04f2, .pid = 0xb61e },
|
||||||
{ .vid = 0x04f3, .pid = 0x036b },
|
{ .vid = 0x04f3, .pid = 0x036b },
|
||||||
{ .vid = 0x04f3, .pid = 0x0c00 },
|
{ .vid = 0x04f3, .pid = 0x0c00 },
|
||||||
{ .vid = 0x04f3, .pid = 0x0c4c },
|
{ .vid = 0x04f3, .pid = 0x0c4c },
|
||||||
{ .vid = 0x04f3, .pid = 0x0c57 },
|
{ .vid = 0x04f3, .pid = 0x0c57 },
|
||||||
|
{ .vid = 0x04f3, .pid = 0x0c5a },
|
||||||
{ .vid = 0x04f3, .pid = 0x0c5e },
|
{ .vid = 0x04f3, .pid = 0x0c5e },
|
||||||
|
{ .vid = 0x04f3, .pid = 0x0c60 },
|
||||||
|
{ .vid = 0x04f3, .pid = 0x0c6c },
|
||||||
|
{ .vid = 0x04f3, .pid = 0x0c70 },
|
||||||
|
{ .vid = 0x04f3, .pid = 0x0c72 },
|
||||||
|
{ .vid = 0x04f3, .pid = 0x0c77 },
|
||||||
|
{ .vid = 0x04f3, .pid = 0x0c7c },
|
||||||
|
{ .vid = 0x04f3, .pid = 0x0c7f },
|
||||||
|
{ .vid = 0x04f3, .pid = 0x0c80 },
|
||||||
|
{ .vid = 0x04f3, .pid = 0x0c85 },
|
||||||
|
{ .vid = 0x04f3, .pid = 0x0c8a },
|
||||||
|
{ .vid = 0x04f3, .pid = 0x0c8e },
|
||||||
|
{ .vid = 0x04f3, .pid = 0x0c90 },
|
||||||
|
{ .vid = 0x04f3, .pid = 0x0ca2 },
|
||||||
|
{ .vid = 0x04f3, .pid = 0x24cc },
|
||||||
{ .vid = 0x04f3, .pid = 0x2706 },
|
{ .vid = 0x04f3, .pid = 0x2706 },
|
||||||
|
{ .vid = 0x04f3, .pid = 0x3032 },
|
||||||
|
{ .vid = 0x04f3, .pid = 0x3057 },
|
||||||
|
{ .vid = 0x04f3, .pid = 0x3058 },
|
||||||
|
{ .vid = 0x04f3, .pid = 0x3066 },
|
||||||
|
{ .vid = 0x04f3, .pid = 0x3087 },
|
||||||
|
{ .vid = 0x04f3, .pid = 0x309f },
|
||||||
|
{ .vid = 0x04f3, .pid = 0x30c6 },
|
||||||
|
{ .vid = 0x04f3, .pid = 0x3104 },
|
||||||
|
{ .vid = 0x04f3, .pid = 0x310d },
|
||||||
|
{ .vid = 0x04f3, .pid = 0x3128 },
|
||||||
|
{ .vid = 0x04f3, .pid = 0x3195 },
|
||||||
|
{ .vid = 0x04f3, .pid = 0x31fc },
|
||||||
|
{ .vid = 0x04f3, .pid = 0x3201 },
|
||||||
|
{ .vid = 0x04f3, .pid = 0x3212 },
|
||||||
|
{ .vid = 0x05ba, .pid = 0x000e },
|
||||||
|
{ .vid = 0x05c8, .pid = 0x03c0 },
|
||||||
|
{ .vid = 0x06cb, .pid = 0x0051 },
|
||||||
{ .vid = 0x06cb, .pid = 0x0081 },
|
{ .vid = 0x06cb, .pid = 0x0081 },
|
||||||
{ .vid = 0x06cb, .pid = 0x0088 },
|
{ .vid = 0x06cb, .pid = 0x0088 },
|
||||||
{ .vid = 0x06cb, .pid = 0x008a },
|
{ .vid = 0x06cb, .pid = 0x008a },
|
||||||
{ .vid = 0x06cb, .pid = 0x009a },
|
{ .vid = 0x06cb, .pid = 0x009a },
|
||||||
{ .vid = 0x06cb, .pid = 0x009b },
|
{ .vid = 0x06cb, .pid = 0x009b },
|
||||||
|
{ .vid = 0x06cb, .pid = 0x00a1 },
|
||||||
{ .vid = 0x06cb, .pid = 0x00a2 },
|
{ .vid = 0x06cb, .pid = 0x00a2 },
|
||||||
{ .vid = 0x06cb, .pid = 0x00a8 },
|
{ .vid = 0x06cb, .pid = 0x00a8 },
|
||||||
{ .vid = 0x06cb, .pid = 0x00b7 },
|
{ .vid = 0x06cb, .pid = 0x00b7 },
|
||||||
{ .vid = 0x06cb, .pid = 0x00bb },
|
{ .vid = 0x06cb, .pid = 0x00bb },
|
||||||
|
{ .vid = 0x06cb, .pid = 0x00bc },
|
||||||
{ .vid = 0x06cb, .pid = 0x00be },
|
{ .vid = 0x06cb, .pid = 0x00be },
|
||||||
{ .vid = 0x06cb, .pid = 0x00c4 },
|
{ .vid = 0x06cb, .pid = 0x00c7 },
|
||||||
{ .vid = 0x06cb, .pid = 0x00cb },
|
|
||||||
{ .vid = 0x06cb, .pid = 0x00c9 },
|
{ .vid = 0x06cb, .pid = 0x00c9 },
|
||||||
|
{ .vid = 0x06cb, .pid = 0x00cb },
|
||||||
{ .vid = 0x06cb, .pid = 0x00d8 },
|
{ .vid = 0x06cb, .pid = 0x00d8 },
|
||||||
{ .vid = 0x06cb, .pid = 0x00da },
|
{ .vid = 0x06cb, .pid = 0x00da },
|
||||||
{ .vid = 0x06cb, .pid = 0x00dc },
|
{ .vid = 0x06cb, .pid = 0x00dc },
|
||||||
{ .vid = 0x06cb, .pid = 0x00e4 },
|
{ .vid = 0x06cb, .pid = 0x00e4 },
|
||||||
{ .vid = 0x06cb, .pid = 0x00e7 },
|
{ .vid = 0x06cb, .pid = 0x00e7 },
|
||||||
{ .vid = 0x06cb, .pid = 0x00e9 },
|
|
||||||
{ .vid = 0x06cb, .pid = 0x00fd },
|
{ .vid = 0x06cb, .pid = 0x00fd },
|
||||||
|
{ .vid = 0x06cb, .pid = 0x00ff },
|
||||||
|
{ .vid = 0x06cb, .pid = 0x0102 },
|
||||||
|
{ .vid = 0x06cb, .pid = 0xce67 },
|
||||||
|
{ .vid = 0x06cb, .pid = 0xceef },
|
||||||
|
{ .vid = 0x08ff, .pid = 0x3400 },
|
||||||
{ .vid = 0x0a5c, .pid = 0x5801 },
|
{ .vid = 0x0a5c, .pid = 0x5801 },
|
||||||
|
{ .vid = 0x0a5c, .pid = 0x5802 },
|
||||||
{ .vid = 0x0a5c, .pid = 0x5805 },
|
{ .vid = 0x0a5c, .pid = 0x5805 },
|
||||||
{ .vid = 0x0a5c, .pid = 0x5834 },
|
{ .vid = 0x0a5c, .pid = 0x5834 },
|
||||||
{ .vid = 0x0a5c, .pid = 0x5840 },
|
{ .vid = 0x0a5c, .pid = 0x5840 },
|
||||||
@@ -65,11 +113,24 @@ static const FpIdEntry whitelist_id_table[] = {
|
|||||||
{ .vid = 0x0a5c, .pid = 0x5843 },
|
{ .vid = 0x0a5c, .pid = 0x5843 },
|
||||||
{ .vid = 0x0a5c, .pid = 0x5844 },
|
{ .vid = 0x0a5c, .pid = 0x5844 },
|
||||||
{ .vid = 0x0a5c, .pid = 0x5845 },
|
{ .vid = 0x0a5c, .pid = 0x5845 },
|
||||||
|
{ .vid = 0x0a5c, .pid = 0x5860 },
|
||||||
|
{ .vid = 0x0a5c, .pid = 0x5863 },
|
||||||
|
{ .vid = 0x0a5c, .pid = 0x5864 },
|
||||||
|
{ .vid = 0x0a5c, .pid = 0x5865 },
|
||||||
|
{ .vid = 0x0a5c, .pid = 0x5866 },
|
||||||
|
{ .vid = 0x0a5c, .pid = 0x5867 },
|
||||||
|
{ .vid = 0x0bda, .pid = 0x0129 },
|
||||||
{ .vid = 0x0bda, .pid = 0x5812 },
|
{ .vid = 0x0bda, .pid = 0x5812 },
|
||||||
{ .vid = 0x10a5, .pid = 0x0007 },
|
{ .vid = 0x10a5, .pid = 0x0007 },
|
||||||
{ .vid = 0x10a5, .pid = 0x9200 },
|
{ .vid = 0x10a5, .pid = 0x9200 },
|
||||||
|
{ .vid = 0x10a5, .pid = 0x9201 },
|
||||||
{ .vid = 0x10a5, .pid = 0x9800 },
|
{ .vid = 0x10a5, .pid = 0x9800 },
|
||||||
|
{ .vid = 0x10a5, .pid = 0xa120 },
|
||||||
|
{ .vid = 0x10a5, .pid = 0xa900 },
|
||||||
|
{ .vid = 0x10a5, .pid = 0xa921 },
|
||||||
|
{ .vid = 0x10a5, .pid = 0xe340 },
|
||||||
{ .vid = 0x1188, .pid = 0x9545 },
|
{ .vid = 0x1188, .pid = 0x9545 },
|
||||||
|
{ .vid = 0x138a, .pid = 0x0006 },
|
||||||
{ .vid = 0x138a, .pid = 0x0007 },
|
{ .vid = 0x138a, .pid = 0x0007 },
|
||||||
{ .vid = 0x138a, .pid = 0x003a },
|
{ .vid = 0x138a, .pid = 0x003a },
|
||||||
{ .vid = 0x138a, .pid = 0x003c },
|
{ .vid = 0x138a, .pid = 0x003c },
|
||||||
@@ -80,6 +141,7 @@ static const FpIdEntry whitelist_id_table[] = {
|
|||||||
{ .vid = 0x138a, .pid = 0x0094 },
|
{ .vid = 0x138a, .pid = 0x0094 },
|
||||||
{ .vid = 0x138a, .pid = 0x0097 },
|
{ .vid = 0x138a, .pid = 0x0097 },
|
||||||
{ .vid = 0x138a, .pid = 0x009d },
|
{ .vid = 0x138a, .pid = 0x009d },
|
||||||
|
{ .vid = 0x138a, .pid = 0x00a6 },
|
||||||
{ .vid = 0x138a, .pid = 0x00ab },
|
{ .vid = 0x138a, .pid = 0x00ab },
|
||||||
{ .vid = 0x147e, .pid = 0x1002 },
|
{ .vid = 0x147e, .pid = 0x1002 },
|
||||||
{ .vid = 0x1491, .pid = 0x0088 },
|
{ .vid = 0x1491, .pid = 0x0088 },
|
||||||
@@ -87,15 +149,24 @@ static const FpIdEntry whitelist_id_table[] = {
|
|||||||
{ .vid = 0x1c7a, .pid = 0x0300 },
|
{ .vid = 0x1c7a, .pid = 0x0300 },
|
||||||
{ .vid = 0x1c7a, .pid = 0x0575 },
|
{ .vid = 0x1c7a, .pid = 0x0575 },
|
||||||
{ .vid = 0x1c7a, .pid = 0x0576 },
|
{ .vid = 0x1c7a, .pid = 0x0576 },
|
||||||
|
{ .vid = 0x1c7a, .pid = 0x0577 },
|
||||||
|
{ .vid = 0x1c7a, .pid = 0x057e },
|
||||||
|
{ .vid = 0x1c7a, .pid = 0x05a5 },
|
||||||
|
{ .vid = 0x1c7a, .pid = 0x05aa },
|
||||||
|
{ .vid = 0x1c7a, .pid = 0x0801 },
|
||||||
|
{ .vid = 0x2541, .pid = 0x0236 },
|
||||||
|
{ .vid = 0x2541, .pid = 0x9711 },
|
||||||
{ .vid = 0x27c6, .pid = 0x5042 },
|
{ .vid = 0x27c6, .pid = 0x5042 },
|
||||||
{ .vid = 0x27c6, .pid = 0x5110 },
|
{ .vid = 0x27c6, .pid = 0x5110 },
|
||||||
{ .vid = 0x27c6, .pid = 0x5117 },
|
{ .vid = 0x27c6, .pid = 0x5117 },
|
||||||
|
{ .vid = 0x27c6, .pid = 0x5120 },
|
||||||
{ .vid = 0x27c6, .pid = 0x5125 },
|
{ .vid = 0x27c6, .pid = 0x5125 },
|
||||||
{ .vid = 0x27c6, .pid = 0x5201 },
|
{ .vid = 0x27c6, .pid = 0x5201 },
|
||||||
{ .vid = 0x27c6, .pid = 0x521d },
|
{ .vid = 0x27c6, .pid = 0x521d },
|
||||||
{ .vid = 0x27c6, .pid = 0x5301 },
|
{ .vid = 0x27c6, .pid = 0x5301 },
|
||||||
{ .vid = 0x27c6, .pid = 0x530c },
|
{ .vid = 0x27c6, .pid = 0x530c },
|
||||||
{ .vid = 0x27c6, .pid = 0x532d },
|
{ .vid = 0x27c6, .pid = 0x532d },
|
||||||
|
{ .vid = 0x27c6, .pid = 0x5335 },
|
||||||
{ .vid = 0x27c6, .pid = 0x533c },
|
{ .vid = 0x27c6, .pid = 0x533c },
|
||||||
{ .vid = 0x27c6, .pid = 0x5381 },
|
{ .vid = 0x27c6, .pid = 0x5381 },
|
||||||
{ .vid = 0x27c6, .pid = 0x5385 },
|
{ .vid = 0x27c6, .pid = 0x5385 },
|
||||||
@@ -103,31 +174,49 @@ static const FpIdEntry whitelist_id_table[] = {
|
|||||||
{ .vid = 0x27c6, .pid = 0x538d },
|
{ .vid = 0x27c6, .pid = 0x538d },
|
||||||
{ .vid = 0x27c6, .pid = 0x5395 },
|
{ .vid = 0x27c6, .pid = 0x5395 },
|
||||||
{ .vid = 0x27c6, .pid = 0x5503 },
|
{ .vid = 0x27c6, .pid = 0x5503 },
|
||||||
|
{ .vid = 0x27c6, .pid = 0x550a },
|
||||||
|
{ .vid = 0x27c6, .pid = 0x550c },
|
||||||
{ .vid = 0x27c6, .pid = 0x5584 },
|
{ .vid = 0x27c6, .pid = 0x5584 },
|
||||||
{ .vid = 0x27c6, .pid = 0x55a2 },
|
{ .vid = 0x27c6, .pid = 0x55a2 },
|
||||||
{ .vid = 0x27c6, .pid = 0x55a4 },
|
{ .vid = 0x27c6, .pid = 0x55a4 },
|
||||||
{ .vid = 0x27c6, .pid = 0x55b4 },
|
{ .vid = 0x27c6, .pid = 0x55b4 },
|
||||||
{ .vid = 0x27c6, .pid = 0x5740 },
|
{ .vid = 0x27c6, .pid = 0x5740 },
|
||||||
|
{ .vid = 0x27c6, .pid = 0x581a },
|
||||||
|
{ .vid = 0x27c6, .pid = 0x589a },
|
||||||
{ .vid = 0x27c6, .pid = 0x5e0a },
|
{ .vid = 0x27c6, .pid = 0x5e0a },
|
||||||
|
{ .vid = 0x27c6, .pid = 0x5f10 },
|
||||||
|
{ .vid = 0x27c6, .pid = 0x5f91 },
|
||||||
|
{ .vid = 0x2808, .pid = 0x06fc },
|
||||||
|
{ .vid = 0x2808, .pid = 0x6652 },
|
||||||
{ .vid = 0x2808, .pid = 0x9338 },
|
{ .vid = 0x2808, .pid = 0x9338 },
|
||||||
{ .vid = 0x298d, .pid = 0x2020 },
|
{ .vid = 0x2808, .pid = 0x9348 },
|
||||||
|
{ .vid = 0x2808, .pid = 0x93a9 },
|
||||||
|
{ .vid = 0x2808, .pid = 0xa553 },
|
||||||
|
{ .vid = 0x2808, .pid = 0xa573 },
|
||||||
|
{ .vid = 0x2808, .pid = 0xa658 },
|
||||||
|
{ .vid = 0x2808, .pid = 0xc652 },
|
||||||
{ .vid = 0x298d, .pid = 0x2033 },
|
{ .vid = 0x298d, .pid = 0x2033 },
|
||||||
|
{ .vid = 0x2df0, .pid = 0x0003 },
|
||||||
|
{ .vid = 0x3274, .pid = 0x9008 },
|
||||||
|
{ .vid = 0x3274, .pid = 0xb012 },
|
||||||
|
{ .vid = 0x33a7, .pid = 0x2388 },
|
||||||
{ .vid = 0x3538, .pid = 0x0930 },
|
{ .vid = 0x3538, .pid = 0x0930 },
|
||||||
|
/* --- END GENERATED IDS --- */
|
||||||
{ .vid = 0 },
|
{ .vid = 0 },
|
||||||
};
|
};
|
||||||
|
|
||||||
static const FpIdEntry blacklist_id_table[] = {
|
static const FpIdEntry denylist_id_table[] = {
|
||||||
{ .vid = 0x0483, .pid = 0x2016 },
|
{ .vid = 0x0483, .pid = 0x2016 },
|
||||||
/* https://bugs.freedesktop.org/show_bug.cgi?id=66659 */
|
/* https://bugs.freedesktop.org/show_bug.cgi?id=66659 */
|
||||||
{ .vid = 0x045e, .pid = 0x00bb },
|
{ .vid = 0x045e, .pid = 0x00bb },
|
||||||
{ .vid = 0 },
|
{ .vid = 0 },
|
||||||
};
|
};
|
||||||
|
|
||||||
static const FpDeviceClass whitelist = {
|
static const FpDeviceClass allowlist = {
|
||||||
.type = FP_DEVICE_TYPE_USB,
|
.type = FP_DEVICE_TYPE_USB,
|
||||||
.id_table = whitelist_id_table,
|
.id_table = allowlist_id_table,
|
||||||
.id = "whitelist",
|
.id = "allowlist",
|
||||||
.full_name = "Hardcoded whitelist"
|
.full_name = "Hardcoded allowlist"
|
||||||
};
|
};
|
||||||
|
|
||||||
GHashTable *printed = NULL;
|
GHashTable *printed = NULL;
|
||||||
@@ -146,7 +235,7 @@ print_driver (const FpDeviceClass *cls)
|
|||||||
const FpIdEntry *bl_entry;
|
const FpIdEntry *bl_entry;
|
||||||
char *key;
|
char *key;
|
||||||
|
|
||||||
for (bl_entry = blacklist_id_table; bl_entry->vid != 0; bl_entry++)
|
for (bl_entry = denylist_id_table; bl_entry->vid != 0; bl_entry++)
|
||||||
if (entry->vid == bl_entry->vid && entry->pid == bl_entry->pid)
|
if (entry->vid == bl_entry->vid && entry->pid == bl_entry->pid)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -157,7 +246,7 @@ print_driver (const FpDeviceClass *cls)
|
|||||||
|
|
||||||
if (g_hash_table_lookup (printed, key) != NULL)
|
if (g_hash_table_lookup (printed, key) != NULL)
|
||||||
{
|
{
|
||||||
if (cls == &whitelist)
|
if (cls == &allowlist)
|
||||||
g_warning ("%s implemented by driver %s",
|
g_warning ("%s implemented by driver %s",
|
||||||
key, (const char *) g_hash_table_lookup (printed, key));
|
key, (const char *) g_hash_table_lookup (printed, key));
|
||||||
g_free (key);
|
g_free (key);
|
||||||
@@ -168,7 +257,7 @@ print_driver (const FpDeviceClass *cls)
|
|||||||
|
|
||||||
if (num_printed == 0)
|
if (num_printed == 0)
|
||||||
{
|
{
|
||||||
if (cls != &whitelist)
|
if (cls != &allowlist)
|
||||||
g_print ("\n# Supported by libfprint driver %s\n", cls->id);
|
g_print ("\n# Supported by libfprint driver %s\n", cls->id);
|
||||||
else
|
else
|
||||||
g_print ("\n# Known unsupported devices\n");
|
g_print ("\n# Known unsupported devices\n");
|
||||||
@@ -222,7 +311,7 @@ main (int argc, char **argv)
|
|||||||
print_driver (cls);
|
print_driver (cls);
|
||||||
}
|
}
|
||||||
|
|
||||||
print_driver (&whitelist);
|
print_driver (&allowlist);
|
||||||
|
|
||||||
g_hash_table_destroy (printed);
|
g_hash_table_destroy (printed);
|
||||||
|
|
||||||
|
|||||||
+115
-84
@@ -1,3 +1,11 @@
|
|||||||
|
spi_sources = []
|
||||||
|
spi_headers = []
|
||||||
|
|
||||||
|
if have_spi
|
||||||
|
spi_headers = ['fpi-spi-transfer.h']
|
||||||
|
spi_sources = ['fpi-spi-transfer.c']
|
||||||
|
endif
|
||||||
|
|
||||||
libfprint_sources = [
|
libfprint_sources = [
|
||||||
'fp-context.c',
|
'fp-context.c',
|
||||||
'fp-device.c',
|
'fp-device.c',
|
||||||
@@ -13,11 +21,11 @@ libfprint_private_sources = [
|
|||||||
'fpi-device.c',
|
'fpi-device.c',
|
||||||
'fpi-image-device.c',
|
'fpi-image-device.c',
|
||||||
'fpi-image.c',
|
'fpi-image.c',
|
||||||
|
'fpi-log.c',
|
||||||
'fpi-print.c',
|
'fpi-print.c',
|
||||||
'fpi-ssm.c',
|
'fpi-ssm.c',
|
||||||
'fpi-usb-transfer.c',
|
'fpi-usb-transfer.c',
|
||||||
'fpi-spi-transfer.c',
|
] + spi_sources
|
||||||
]
|
|
||||||
|
|
||||||
libfprint_public_headers = [
|
libfprint_public_headers = [
|
||||||
'fp-context.h',
|
'fp-context.h',
|
||||||
@@ -41,9 +49,8 @@ libfprint_private_headers = [
|
|||||||
'fpi-minutiae.h',
|
'fpi-minutiae.h',
|
||||||
'fpi-print.h',
|
'fpi-print.h',
|
||||||
'fpi-usb-transfer.h',
|
'fpi-usb-transfer.h',
|
||||||
'fpi-spi-transfer.h',
|
|
||||||
'fpi-ssm.h',
|
'fpi-ssm.h',
|
||||||
]
|
] + spi_headers
|
||||||
|
|
||||||
nbis_sources = [
|
nbis_sources = [
|
||||||
'nbis/bozorth3/bozorth3.c',
|
'nbis/bozorth3/bozorth3.c',
|
||||||
@@ -81,79 +88,67 @@ nbis_sources = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
driver_sources = {
|
driver_sources = {
|
||||||
'upekts' :
|
'upekts' : files(
|
||||||
[ 'drivers/upekts.c', 'drivers/upek_proto.c' ],
|
'drivers/upekts.c',
|
||||||
'upektc' :
|
'drivers/upek_proto.c',
|
||||||
[ 'drivers/upektc.c' ],
|
),
|
||||||
'upeksonly' :
|
'upektc' : files('drivers/upektc.c'),
|
||||||
[ 'drivers/upeksonly.c' ],
|
'upeksonly' : files('drivers/upeksonly.c'),
|
||||||
'uru4000' :
|
'uru4000' : files('drivers/uru4000.c'),
|
||||||
[ 'drivers/uru4000.c' ],
|
'aes1610' : files('drivers/aes1610.c'),
|
||||||
'aes1610' :
|
'aes1660' : files('drivers/aes1660.c'),
|
||||||
[ 'drivers/aes1610.c' ],
|
'aes2501' : files('drivers/aes2501.c'),
|
||||||
'aes1660' :
|
'aes2550' : files('drivers/aes2550.c'),
|
||||||
[ 'drivers/aes1660.c' ],
|
'aes2660' : files('drivers/aes2660.c'),
|
||||||
'aes2501' :
|
'aes3500' : files('drivers/aes3500.c'),
|
||||||
[ 'drivers/aes2501.c' ],
|
'aes4000' : files('drivers/aes4000.c'),
|
||||||
'aes2550' :
|
'vcom5s' : files('drivers/vcom5s.c'),
|
||||||
[ 'drivers/aes2550.c' ],
|
'vfs101' : files('drivers/vfs101.c'),
|
||||||
'aes2660' :
|
'vfs301' : files(
|
||||||
[ 'drivers/aes2660.c' ],
|
'drivers/vfs301.c',
|
||||||
'aes3500' :
|
'drivers/vfs301_proto.c',
|
||||||
[ 'drivers/aes3500.c' ],
|
),
|
||||||
'aes4000' :
|
'vfs5011' : files('drivers/vfs5011.c'),
|
||||||
[ 'drivers/aes4000.c' ],
|
'vfs7552' : files('drivers/vfs7552.c'),
|
||||||
'vcom5s' :
|
'upektc_img' : files(
|
||||||
[ 'drivers/vcom5s.c' ],
|
'drivers/upektc_img.c',
|
||||||
'vfs101' :
|
'drivers/upek_proto.c',
|
||||||
[ 'drivers/vfs101.c' ],
|
),
|
||||||
'vfs301' :
|
'etes603' : files('drivers/etes603.c'),
|
||||||
[ 'drivers/vfs301.c', 'drivers/vfs301_proto.c' ],
|
'egis0570' : files('drivers/egis0570.c'),
|
||||||
'vfs5011' :
|
'egismoc' : files('drivers/egismoc/egismoc.c'),
|
||||||
[ 'drivers/vfs5011.c' ],
|
'egis_etu905' : files('drivers/egismoc/egis_etu905.c'),
|
||||||
'vfs7552' :
|
'vfs0050' : files('drivers/vfs0050.c'),
|
||||||
[ 'drivers/vfs7552.c' ],
|
'elan' : files('drivers/elan.c'),
|
||||||
'upektc_img' :
|
'elanmoc' : files('drivers/elanmoc/elanmoc.c'),
|
||||||
[ 'drivers/upektc_img.c', 'drivers/upek_proto.c' ],
|
'elanspi' : files('drivers/elanspi.c'),
|
||||||
'etes603' :
|
'nb1010' : files('drivers/nb1010.c'),
|
||||||
[ 'drivers/etes603.c' ],
|
'virtual_image' : files('drivers/virtual-image.c'),
|
||||||
'egis0570' :
|
'virtual_device' : files('drivers/virtual-device.c'),
|
||||||
[ 'drivers/egis0570.c' ],
|
'virtual_device_storage' : files('drivers/virtual-device-storage.c'),
|
||||||
'vfs0050' :
|
'synaptics' : files(
|
||||||
[ 'drivers/vfs0050.c' ],
|
'drivers/synaptics/synaptics.c',
|
||||||
'elan' :
|
'drivers/synaptics/bmkt_message.c',
|
||||||
[ 'drivers/elan.c' ],
|
),
|
||||||
'elanmoc' :
|
'goodixmoc' : files(
|
||||||
[ 'drivers/elanmoc/elanmoc.c' ],
|
'drivers/goodixmoc/goodix.c',
|
||||||
'elanspi' :
|
'drivers/goodixmoc/goodix_proto.c',
|
||||||
[ 'drivers/elanspi.c' ],
|
),
|
||||||
'nb1010' :
|
'fpcmoc' : files('drivers/fpcmoc/fpc.c'),
|
||||||
[ 'drivers/nb1010.c' ],
|
'realtek' : files('drivers/realtek/realtek.c'),
|
||||||
'virtual_image' :
|
'focaltech_moc' : files('drivers/focaltech_moc/focaltech_moc.c'),
|
||||||
[ 'drivers/virtual-image.c' ],
|
'mafpmoc' : files('drivers/mafpmoc/mafpmoc.c'),
|
||||||
'virtual_device' :
|
'secugen' : files('drivers/secugen.c'),
|
||||||
[ 'drivers/virtual-device.c' ],
|
|
||||||
'virtual_device_storage' :
|
|
||||||
[ 'drivers/virtual-device-storage.c' ],
|
|
||||||
'synaptics' :
|
|
||||||
[ 'drivers/synaptics/synaptics.c', 'drivers/synaptics/bmkt_message.c' ],
|
|
||||||
'goodixmoc' :
|
|
||||||
[ 'drivers/goodixmoc/goodix.c', 'drivers/goodixmoc/goodix_proto.c' ],
|
|
||||||
}
|
}
|
||||||
|
|
||||||
helper_sources = {
|
helper_sources = {
|
||||||
'aeslib' :
|
'aeslib': files('drivers/aeslib.c'),
|
||||||
[ 'drivers/aeslib.c' ],
|
'aesx660': files('drivers/aesx660.c'),
|
||||||
'aesx660' :
|
'aes3k': files('drivers/aes3k.c'),
|
||||||
[ 'drivers/aesx660.c' ],
|
'openssl': files(),
|
||||||
'aes3k' :
|
'pixman': files(),
|
||||||
[ 'drivers/aes3k.c' ],
|
'udev': files(),
|
||||||
'nss' :
|
'virtual': files('drivers/virtual-device-listener.c'),
|
||||||
[ ],
|
|
||||||
'udev' :
|
|
||||||
[ ],
|
|
||||||
'virtual' :
|
|
||||||
[ 'drivers/virtual-device-listener.c' ],
|
|
||||||
}
|
}
|
||||||
|
|
||||||
drivers_sources = []
|
drivers_sources = []
|
||||||
@@ -217,6 +212,7 @@ deps = [
|
|||||||
enums_dep,
|
enums_dep,
|
||||||
gio_dep,
|
gio_dep,
|
||||||
glib_dep,
|
glib_dep,
|
||||||
|
gmodule_dep,
|
||||||
gobject_dep,
|
gobject_dep,
|
||||||
gusb_dep,
|
gusb_dep,
|
||||||
mathlib_dep,
|
mathlib_dep,
|
||||||
@@ -241,6 +237,7 @@ libnbis = static_library('nbis',
|
|||||||
'-Wno-discarded-qualifiers',
|
'-Wno-discarded-qualifiers',
|
||||||
'-Wno-array-bounds',
|
'-Wno-array-bounds',
|
||||||
'-Wno-array-parameter',
|
'-Wno-array-parameter',
|
||||||
|
'-Wno-unused-but-set-variable',
|
||||||
]),
|
]),
|
||||||
install: false)
|
install: false)
|
||||||
|
|
||||||
@@ -260,8 +257,13 @@ libfprint_drivers = static_library('fprint-drivers',
|
|||||||
link_with: libfprint_private,
|
link_with: libfprint_private,
|
||||||
install: false)
|
install: false)
|
||||||
|
|
||||||
mapfile = files('libfprint.ver')
|
mapfile = files('libfprint.ver')[0]
|
||||||
vflag = '-Wl,--version-script,@0@/@1@'.format(meson.source_root(), mapfile[0])
|
if meson.version().version_compare('>=1.4')
|
||||||
|
mapfile_path = mapfile.full_path()
|
||||||
|
else
|
||||||
|
mapfile_path = meson.project_source_root() / '@0@'.format(mapfile)
|
||||||
|
endif
|
||||||
|
vflag = '-Wl,--version-script,@0@'.format(mapfile_path)
|
||||||
|
|
||||||
libfprint = shared_library(versioned_libname.split('lib')[1],
|
libfprint = shared_library(versioned_libname.split('lib')[1],
|
||||||
sources: [
|
sources: [
|
||||||
@@ -299,11 +301,15 @@ libfprint_private_dep = declare_dependency(
|
|||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
udev_hwdb_list = 'fprint-list-udev-hwdb.c'
|
||||||
|
udev_hwdb_list_file = files(udev_hwdb_list)
|
||||||
udev_hwdb = executable('fprint-list-udev-hwdb',
|
udev_hwdb = executable('fprint-list-udev-hwdb',
|
||||||
'fprint-list-udev-hwdb.c',
|
udev_hwdb_list_file,
|
||||||
dependencies: libfprint_private_dep,
|
dependencies: libfprint_private_dep,
|
||||||
link_with: libfprint_drivers,
|
link_with: libfprint_drivers,
|
||||||
install: false)
|
install: false,
|
||||||
|
link_args: ['-Wl,--disable-new-dtags'],
|
||||||
|
)
|
||||||
|
|
||||||
udev_hwdb_generator = custom_target('udev-hwdb',
|
udev_hwdb_generator = custom_target('udev-hwdb',
|
||||||
output: 'autosuspend.hwdb',
|
output: 'autosuspend.hwdb',
|
||||||
@@ -313,12 +319,31 @@ udev_hwdb_generator = custom_target('udev-hwdb',
|
|||||||
install: false,
|
install: false,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
metainfo = executable('fprint-list-metainfo',
|
||||||
|
'fprint-list-metainfo.c',
|
||||||
|
dependencies: libfprint_private_dep,
|
||||||
|
link_with: libfprint_drivers,
|
||||||
|
install: false,
|
||||||
|
link_args: ['-Wl,--disable-new-dtags'],
|
||||||
|
)
|
||||||
|
|
||||||
|
metainfo_generator = custom_target('metainfo',
|
||||||
|
output: 'org.freedesktop.libfprint.metainfo.xml',
|
||||||
|
depend_files: drivers_sources,
|
||||||
|
capture: true,
|
||||||
|
command: [ metainfo ],
|
||||||
|
install: true,
|
||||||
|
install_dir: datadir / 'metainfo'
|
||||||
|
)
|
||||||
|
|
||||||
if install_udev_rules
|
if install_udev_rules
|
||||||
udev_rules = executable('fprint-list-udev-rules',
|
udev_rules = executable('fprint-list-udev-rules',
|
||||||
'fprint-list-udev-rules.c',
|
'fprint-list-udev-rules.c',
|
||||||
dependencies: libfprint_private_dep,
|
dependencies: libfprint_private_dep,
|
||||||
link_with: libfprint_drivers,
|
link_with: libfprint_drivers,
|
||||||
install: false)
|
install: false,
|
||||||
|
link_args: ['-Wl,--disable-new-dtags'],
|
||||||
|
)
|
||||||
|
|
||||||
custom_target('udev-rules',
|
custom_target('udev-rules',
|
||||||
output: '70-@0@.rules'.format(versioned_libname),
|
output: '70-@0@.rules'.format(versioned_libname),
|
||||||
@@ -330,17 +355,22 @@ if install_udev_rules
|
|||||||
)
|
)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
custom_target('sync-udev-hwdb',
|
udev_hwdb_list_updater = custom_target('udev-hwdb-list-updater',
|
||||||
depends: udev_hwdb_generator,
|
output: udev_hwdb_list,
|
||||||
output: 'sync-udev-hwdb',
|
command: [ sync_unsupported_files, udev_hwdb_list_file ],
|
||||||
install: false,
|
)
|
||||||
|
|
||||||
|
run_target('sync-udev-hwdb',
|
||||||
|
depends: udev_hwdb_list_updater,
|
||||||
command: [
|
command: [
|
||||||
'cp', '-v',
|
'cp', '-v',
|
||||||
udev_hwdb_generator.full_path(),
|
udev_hwdb_generator.full_path(),
|
||||||
meson.source_root() / 'data'
|
meson.project_source_root() / 'data'
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
alias_target('sync-unsupported-devices', udev_hwdb_list_updater)
|
||||||
|
|
||||||
supported_devices = executable('fprint-list-supported-devices',
|
supported_devices = executable('fprint-list-supported-devices',
|
||||||
'fprint-list-supported-devices.c',
|
'fprint-list-supported-devices.c',
|
||||||
dependencies: libfprint_private_dep,
|
dependencies: libfprint_private_dep,
|
||||||
@@ -374,6 +404,7 @@ if get_option('introspection')
|
|||||||
'GObject-2.0',
|
'GObject-2.0',
|
||||||
'GUsb-1.0',
|
'GUsb-1.0',
|
||||||
],
|
],
|
||||||
|
fatal_warnings: true,
|
||||||
install : true)
|
install : true)
|
||||||
libfprint_gir = libfprint_girtarget[0]
|
libfprint_gir = libfprint_girtarget[0]
|
||||||
libfprint_typelib = libfprint_girtarget[1]
|
libfprint_typelib = libfprint_girtarget[1]
|
||||||
|
|||||||
+104
-76
@@ -1,27 +1,40 @@
|
|||||||
project('libfprint', [ 'c', 'cpp' ],
|
project('libfprint', [ 'c', 'cpp' ],
|
||||||
version: '1.94.4',
|
version: '1.94.100',
|
||||||
license: 'LGPLv2.1+',
|
license: 'LGPLv2.1+',
|
||||||
default_options: [
|
default_options: [
|
||||||
'buildtype=debugoptimized',
|
'buildtype=debugoptimized',
|
||||||
'warning_level=1',
|
'warning_level=1',
|
||||||
'c_std=gnu99',
|
'c_std=gnu99',
|
||||||
],
|
],
|
||||||
meson_version: '>= 0.49.0')
|
meson_version: '>= 0.62.0')
|
||||||
|
|
||||||
|
fs = import('fs')
|
||||||
gnome = import('gnome')
|
gnome = import('gnome')
|
||||||
|
|
||||||
|
python3 = find_program('python3')
|
||||||
|
|
||||||
libfprint_conf = configuration_data()
|
libfprint_conf = configuration_data()
|
||||||
libfprint_conf.set_quoted('LIBFPRINT_VERSION', meson.project_version())
|
libfprint_conf.set_quoted('LIBFPRINT_VERSION', meson.project_version())
|
||||||
|
|
||||||
|
prefix = get_option('prefix')
|
||||||
|
libdir = prefix / get_option('libdir')
|
||||||
|
libexecdir = prefix / get_option('libexecdir')
|
||||||
|
datadir = prefix / get_option('datadir')
|
||||||
|
|
||||||
cc = meson.get_compiler('c')
|
cc = meson.get_compiler('c')
|
||||||
cpp = meson.get_compiler('cpp')
|
cpp = meson.get_compiler('cpp')
|
||||||
host_system = host_machine.system()
|
host_system = host_machine.system()
|
||||||
glib_min_version = '2.56'
|
|
||||||
|
libfprint_sanitizers = get_option('b_sanitize').split(',')
|
||||||
|
if libfprint_sanitizers == ['none']
|
||||||
|
libfprint_sanitizers = []
|
||||||
|
endif
|
||||||
|
|
||||||
|
glib_min_version = '2.68'
|
||||||
|
|
||||||
glib_version_def = 'GLIB_VERSION_@0@_@1@'.format(
|
glib_version_def = 'GLIB_VERSION_@0@_@1@'.format(
|
||||||
glib_min_version.split('.')[0], glib_min_version.split('.')[1])
|
glib_min_version.split('.')[0], glib_min_version.split('.')[1])
|
||||||
common_cflags = cc.get_supported_arguments([
|
common_cflags = cc.get_supported_arguments([
|
||||||
'-Wall',
|
|
||||||
'-Wcast-align',
|
'-Wcast-align',
|
||||||
'-Wformat-nonliteral',
|
'-Wformat-nonliteral',
|
||||||
'-Wformat-security',
|
'-Wformat-security',
|
||||||
@@ -82,60 +95,78 @@ versioned_libname = meson.project_name() + '-' + soversion.to_string()
|
|||||||
glib_dep = dependency('glib-2.0', version: '>=' + glib_min_version)
|
glib_dep = dependency('glib-2.0', version: '>=' + glib_min_version)
|
||||||
gio_dep = dependency('gio-unix-2.0', version: '>=' + glib_min_version)
|
gio_dep = dependency('gio-unix-2.0', version: '>=' + glib_min_version)
|
||||||
gobject_dep = dependency('gobject-2.0', version: '>=' + glib_min_version)
|
gobject_dep = dependency('gobject-2.0', version: '>=' + glib_min_version)
|
||||||
|
gmodule_dep = dependency('gmodule-2.0', version: '>=' + glib_min_version)
|
||||||
gusb_dep = dependency('gusb', version: '>= 0.2.0')
|
gusb_dep = dependency('gusb', version: '>= 0.2.0')
|
||||||
mathlib_dep = cc.find_library('m', required: false)
|
mathlib_dep = cc.find_library('m', required: false)
|
||||||
|
|
||||||
# The following dependencies are only used for tests
|
# The following dependencies are only used for tests
|
||||||
|
sh = find_program('sh', required: true)
|
||||||
cairo_dep = dependency('cairo', required: false)
|
cairo_dep = dependency('cairo', required: false)
|
||||||
|
|
||||||
|
sync_unsupported_files = files('scripts' / 'sync-unsupported-devices.py')
|
||||||
|
|
||||||
# introspection scanning and Gio-2.0.gir
|
# introspection scanning and Gio-2.0.gir
|
||||||
gobject_introspection = dependency('gobject-introspection-1.0', required: get_option('introspection'))
|
gobject_introspection = dependency('gobject-introspection-1.0', required: get_option('introspection'))
|
||||||
|
|
||||||
|
# SPI
|
||||||
|
have_spi = host_machine.system() == 'linux'
|
||||||
|
|
||||||
# Drivers
|
# Drivers
|
||||||
drivers = get_option('drivers').split(',')
|
drivers = get_option('drivers').split(',')
|
||||||
virtual_drivers = [
|
|
||||||
'virtual_image',
|
|
||||||
'virtual_device',
|
|
||||||
'virtual_device_storage',
|
|
||||||
]
|
|
||||||
|
|
||||||
default_drivers = [
|
drivers_info = {
|
||||||
'upektc_img',
|
'upektc_img': {},
|
||||||
'vfs5011',
|
'vfs5011': { 'endian_dependent': true },
|
||||||
'vfs7552',
|
'vfs7552': {},
|
||||||
'aes3500',
|
'aes3500': { 'helper': ['aeslib', 'aes3k', 'pixman'] },
|
||||||
'aes4000',
|
'aes4000': { 'helper': ['aeslib', 'aes3k', 'pixman'] },
|
||||||
'aes1610',
|
'aes1610': { 'helper': ['aeslib'] },
|
||||||
'aes1660',
|
'aes1660': { 'helper': ['aeslib', 'aesx660'] },
|
||||||
'aes2660',
|
'aes2660': { 'helper': ['aeslib', 'aesx660'] },
|
||||||
'aes2501',
|
'aes2501': { 'helper': ['aeslib'] },
|
||||||
'aes2550',
|
'aes2550': { 'helper': ['aeslib'] },
|
||||||
'vfs101',
|
'vfs101': {},
|
||||||
'vfs301',
|
'vfs301': { 'endian_dependent': true },
|
||||||
'vfs0050',
|
'vfs0050': { 'endian_dependent': true },
|
||||||
'etes603',
|
'etes603': {},
|
||||||
'egis0570',
|
'egis0570': {},
|
||||||
'vcom5s',
|
'egismoc': {},
|
||||||
'synaptics',
|
'egis_etu905': {},
|
||||||
'elan',
|
'vcom5s': {},
|
||||||
'elanmoc',
|
'synaptics': {},
|
||||||
'uru4000',
|
'elan': { 'endian_dependent': true },
|
||||||
'upektc',
|
'elanmoc': {},
|
||||||
'upeksonly',
|
'uru4000': { 'helper': ['openssl'] },
|
||||||
'upekts',
|
'upektc': {},
|
||||||
'goodixmoc',
|
'upeksonly': {},
|
||||||
'nb1010',
|
'upekts': {},
|
||||||
|
'goodixmoc': {},
|
||||||
|
'nb1010': {},
|
||||||
|
'fpcmoc': {},
|
||||||
|
'realtek': {},
|
||||||
|
'focaltech_moc': {},
|
||||||
|
'mafpmoc': {},
|
||||||
|
'secugen': {},
|
||||||
|
|
||||||
# SPI
|
# SPI driver (non-optional if SPI is available)
|
||||||
'elanspi',
|
'elanspi': { 'spi': true, 'helper': ['udev'], 'optional': not have_spi },
|
||||||
]
|
|
||||||
|
|
||||||
# FIXME: All the drivers should be fixed by adjusting the byte order.
|
# Virtual drivers (test-only, optional)
|
||||||
# See https://gitlab.freedesktop.org/libfprint/libfprint/-/issues/236
|
'virtual_image': { 'virtual': true, 'helper': ['virtual'], 'optional': true },
|
||||||
endian_independent_drivers = virtual_drivers + [
|
'virtual_device': { 'virtual': true, 'helper': ['virtual'], 'optional': true },
|
||||||
'aes3500',
|
'virtual_device_storage': { 'virtual': true, 'helper': ['virtual'], 'optional': true },
|
||||||
'synaptics',
|
}
|
||||||
]
|
|
||||||
|
default_drivers = []
|
||||||
|
virtual_drivers = []
|
||||||
|
foreach name, info : drivers_info
|
||||||
|
if not info.get('optional', false)
|
||||||
|
default_drivers += name
|
||||||
|
endif
|
||||||
|
if info.get('virtual', false)
|
||||||
|
virtual_drivers += name
|
||||||
|
endif
|
||||||
|
endforeach
|
||||||
|
|
||||||
all_drivers = default_drivers + virtual_drivers
|
all_drivers = default_drivers + virtual_drivers
|
||||||
|
|
||||||
@@ -147,25 +178,18 @@ if drivers == [ 'default' ]
|
|||||||
drivers = default_drivers
|
drivers = default_drivers
|
||||||
endif
|
endif
|
||||||
|
|
||||||
driver_helper_mapping = {
|
if not have_spi
|
||||||
'aes1610' : [ 'aeslib' ],
|
foreach driver: drivers
|
||||||
'aes1660' : [ 'aeslib', 'aesx660' ],
|
if drivers_info[driver].get('spi', false)
|
||||||
'aes2501' : [ 'aeslib' ],
|
error('SPI driver @0@ is not supported'.format(driver))
|
||||||
'aes2550' : [ 'aeslib' ],
|
endif
|
||||||
'aes2660' : [ 'aeslib', 'aesx660' ],
|
endforeach
|
||||||
'aes3500' : [ 'aeslib', 'aes3k' ],
|
endif
|
||||||
'aes4000' : [ 'aeslib', 'aes3k' ],
|
|
||||||
'uru4000' : [ 'nss' ],
|
|
||||||
'elanspi' : [ 'udev' ],
|
|
||||||
'virtual_image' : [ 'virtual' ],
|
|
||||||
'virtual_device' : [ 'virtual' ],
|
|
||||||
'virtual_device_storage' : [ 'virtual' ],
|
|
||||||
}
|
|
||||||
|
|
||||||
driver_helpers = []
|
driver_helpers = []
|
||||||
foreach driver : drivers
|
foreach driver : drivers
|
||||||
if driver in driver_helper_mapping
|
if driver in drivers_info
|
||||||
foreach helper : driver_helper_mapping[driver]
|
foreach helper : drivers_info[driver].get('helper', [])
|
||||||
if helper not in driver_helpers
|
if helper not in driver_helpers
|
||||||
driver_helpers += helper
|
driver_helpers += helper
|
||||||
endif
|
endif
|
||||||
@@ -197,14 +221,14 @@ optional_deps = []
|
|||||||
|
|
||||||
# Resolve extra dependencies
|
# Resolve extra dependencies
|
||||||
foreach i : driver_helpers
|
foreach i : driver_helpers
|
||||||
foreach d, helpers : driver_helper_mapping
|
foreach name, info : drivers_info
|
||||||
if i in helpers
|
if i in info.get('helper', [])
|
||||||
driver = d
|
driver = name
|
||||||
break
|
break
|
||||||
endif
|
endif
|
||||||
endforeach
|
endforeach
|
||||||
|
|
||||||
if i == 'aes3k'
|
if i == 'pixman'
|
||||||
imaging_dep = dependency('pixman-1', required: false)
|
imaging_dep = dependency('pixman-1', required: false)
|
||||||
if not imaging_dep.found()
|
if not imaging_dep.found()
|
||||||
error('pixman is required for @0@ and possibly others'.format(driver))
|
error('pixman is required for @0@ and possibly others'.format(driver))
|
||||||
@@ -212,13 +236,13 @@ foreach i : driver_helpers
|
|||||||
|
|
||||||
libfprint_conf.set10('HAVE_PIXMAN', true)
|
libfprint_conf.set10('HAVE_PIXMAN', true)
|
||||||
optional_deps += imaging_dep
|
optional_deps += imaging_dep
|
||||||
elif i == 'nss'
|
elif i == 'openssl'
|
||||||
nss_dep = dependency('nss', required: false)
|
openssl_dep = dependency('openssl', version: '>= 3.0', required: false)
|
||||||
if not nss_dep.found()
|
if not openssl_dep.found()
|
||||||
error('nss is required for @0@ and possibly others'.format(driver))
|
error('OpenSSL is required for @0@ and possibly others'.format(driver))
|
||||||
endif
|
endif
|
||||||
|
|
||||||
optional_deps += nss_dep
|
optional_deps += openssl_dep
|
||||||
elif i == 'udev'
|
elif i == 'udev'
|
||||||
install_udev_rules = true
|
install_udev_rules = true
|
||||||
|
|
||||||
@@ -241,13 +265,15 @@ if install_udev_rules
|
|||||||
udev_rules_dir = get_option('udev_rules_dir')
|
udev_rules_dir = get_option('udev_rules_dir')
|
||||||
if udev_rules_dir == 'auto'
|
if udev_rules_dir == 'auto'
|
||||||
udev_dep = dependency('udev')
|
udev_dep = dependency('udev')
|
||||||
udev_rules_dir = udev_dep.get_pkgconfig_variable('udevdir') + '/rules.d'
|
udev_rules_dir = udev_dep.get_variable(pkgconfig: 'udevdir') + '/rules.d'
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
# FIXME: All the drivers should be fixed by adjusting the byte order.
|
||||||
|
# See https://gitlab.freedesktop.org/libfprint/libfprint/-/issues/236
|
||||||
supported_drivers = []
|
supported_drivers = []
|
||||||
foreach driver: drivers
|
foreach driver: drivers
|
||||||
if build_machine.endian() == 'little' or driver in endian_independent_drivers
|
if build_machine.endian() == 'little' or not drivers_info[driver].get('endian_dependent', false)
|
||||||
supported_drivers += driver
|
supported_drivers += driver
|
||||||
else
|
else
|
||||||
warning('Driver @0@ is not supported by big endian cpu @1@. Please, fix it!'.format(
|
warning('Driver @0@ is not supported by big endian cpu @1@. Please, fix it!'.format(
|
||||||
@@ -278,15 +304,13 @@ if not udev_hwdb.disabled()
|
|||||||
|
|
||||||
if udev_hwdb_dir == 'auto'
|
if udev_hwdb_dir == 'auto'
|
||||||
udev_dep = dependency('udev')
|
udev_dep = dependency('udev')
|
||||||
udev_hwdb_dir = udev_dep.get_pkgconfig_variable('udevdir') + '/hwdb.d'
|
udev_hwdb_dir = udev_dep.get_variable(pkgconfig: 'udevdir') + '/hwdb.d'
|
||||||
endif
|
endif
|
||||||
else
|
else
|
||||||
udev_hwdb_dir = ''
|
udev_hwdb_dir = ''
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if get_option('gtk-examples')
|
if get_option('gtk-examples')
|
||||||
gnome = import('gnome')
|
|
||||||
|
|
||||||
gtk_dep = dependency('gtk+-3.0', required: false)
|
gtk_dep = dependency('gtk+-3.0', required: false)
|
||||||
if not gtk_dep.found()
|
if not gtk_dep.found()
|
||||||
error('GTK+ 3.x is required for GTK+ examples')
|
error('GTK+ 3.x is required for GTK+ examples')
|
||||||
@@ -298,9 +322,7 @@ subdir('libfprint')
|
|||||||
|
|
||||||
configure_file(output: 'config.h', configuration: libfprint_conf)
|
configure_file(output: 'config.h', configuration: libfprint_conf)
|
||||||
|
|
||||||
subdir('examples')
|
|
||||||
if get_option('doc')
|
if get_option('doc')
|
||||||
gnome = import('gnome')
|
|
||||||
subdir('doc')
|
subdir('doc')
|
||||||
endif
|
endif
|
||||||
if get_option('gtk-examples')
|
if get_option('gtk-examples')
|
||||||
@@ -310,6 +332,10 @@ endif
|
|||||||
subdir('data')
|
subdir('data')
|
||||||
subdir('tests')
|
subdir('tests')
|
||||||
|
|
||||||
|
subdir('examples')
|
||||||
|
|
||||||
|
meson.add_dist_script(sync_unsupported_files, '--check', udev_hwdb_list_file)
|
||||||
|
|
||||||
pkgconfig = import('pkgconfig')
|
pkgconfig = import('pkgconfig')
|
||||||
pkgconfig.generate(
|
pkgconfig.generate(
|
||||||
name: versioned_libname,
|
name: versioned_libname,
|
||||||
@@ -320,3 +346,5 @@ pkgconfig.generate(
|
|||||||
subdirs: versioned_libname,
|
subdirs: versioned_libname,
|
||||||
filebase: versioned_libname,
|
filebase: versioned_libname,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
summary({'Drivers': drivers, }, section: 'Drivers')
|
||||||
|
|||||||
@@ -30,3 +30,7 @@ option('doc',
|
|||||||
description: 'Whether to build the API documentation',
|
description: 'Whether to build the API documentation',
|
||||||
type: 'boolean',
|
type: 'boolean',
|
||||||
value: true)
|
value: true)
|
||||||
|
option('installed-tests',
|
||||||
|
description: 'Whether to install the installed tests',
|
||||||
|
type: 'boolean',
|
||||||
|
value: true)
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user