mirror of
https://gitlab.freedesktop.org/libfprint/libfprint.git
synced 2025-11-15 07:38:12 +00:00
Compare commits
249 Commits
v1.94.5
...
feature/sd
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d878136546 | ||
|
|
31f9a250be | ||
|
|
df004970f1 | ||
|
|
21960019fc | ||
|
|
6086c9fb27 | ||
|
|
036ebd607a | ||
|
|
99ed5d139b | ||
|
|
74e15c793b | ||
|
|
e96f9c3618 | ||
|
|
05d0b13c28 | ||
|
|
7460e0dec4 | ||
|
|
596b5f8032 | ||
|
|
7f5304d6ee | ||
|
|
bde868f05e | ||
|
|
a7448fbb4a | ||
|
|
f84ab3d104 | ||
|
|
da42268911 | ||
|
|
d83a785260 | ||
|
|
2b100a912b | ||
|
|
c74a0d4592 | ||
|
|
3c1c9acd71 | ||
|
|
6974e1bad4 | ||
|
|
89fae86e8c | ||
|
|
a925b83456 | ||
|
|
4e811f7b63 | ||
|
|
e3fab01e38 | ||
|
|
f063e3787e | ||
|
|
ca89ead07d | ||
|
|
4582b3b825 | ||
|
|
dc8b05f0a3 | ||
|
|
c37da8568f | ||
|
|
e401fc10e8 | ||
|
|
db48d1a4e4 | ||
|
|
d1504a30b7 | ||
|
|
7208b29756 | ||
|
|
e9dbfbec39 | ||
|
|
c6ca915067 | ||
|
|
385bc5e384 | ||
|
|
ee73d67765 | ||
|
|
4dd51f38c7 | ||
|
|
5b300edbe5 | ||
|
|
817281f6fd | ||
|
|
aa18595ec7 | ||
|
|
fa5828f8c0 | ||
|
|
fc3effd73b | ||
|
|
63b5908f38 | ||
|
|
7b97bed91f | ||
|
|
41949db6ce | ||
|
|
d8e0791554 | ||
|
|
c7059dc61c | ||
|
|
0c315b4f0a | ||
|
|
b04553cac9 | ||
|
|
c1dcaa805d | ||
|
|
7b2895271d | ||
|
|
3e653fe85b | ||
|
|
830a9977c0 | ||
|
|
6b914a2070 | ||
|
|
22e6670aa0 | ||
|
|
6723b74f86 | ||
|
|
7d9638bc43 | ||
|
|
559c18785b | ||
|
|
9e8dda5f17 | ||
|
|
f906afb757 | ||
|
|
1c4ed2e225 | ||
|
|
cdc22b4553 | ||
|
|
57c535d0cb | ||
|
|
a94a55b8df | ||
|
|
133eaab061 | ||
|
|
7a60912b61 | ||
|
|
6702c32b2b | ||
|
|
b8ed4b5d63 | ||
|
|
8433563602 | ||
|
|
026c09d0b4 | ||
|
|
3abdda4391 | ||
|
|
981f8e0a42 | ||
|
|
f18e11b435 | ||
|
|
42d10118a3 | ||
|
|
51d827fc74 | ||
|
|
1859a1e5d1 | ||
|
|
7292dd642c | ||
|
|
8e22b2e22e | ||
|
|
28b9ab7e37 | ||
|
|
9141014456 | ||
|
|
6f3ab36b2e | ||
|
|
d3035d5703 | ||
|
|
042365dbec | ||
|
|
0c7211329e | ||
|
|
e1b6d8a461 | ||
|
|
09ec6e66e3 | ||
|
|
8ce356fccc | ||
|
|
98f5ad1f80 | ||
|
|
29f919b4eb | ||
|
|
e57bab2f1e | ||
|
|
a88582761f | ||
|
|
75adfd37d1 | ||
|
|
990bd40cbf | ||
|
|
c7e95bb41f | ||
|
|
4611cc4a1b | ||
|
|
78c78432b9 | ||
|
|
10e1cd76aa | ||
|
|
c84d3774cf | ||
|
|
04a167b09b | ||
|
|
538a18cf17 | ||
|
|
2e766904f0 | ||
|
|
9f55ef690d | ||
|
|
b6061c0af8 | ||
|
|
3f70bde21c | ||
|
|
dd6f020378 | ||
| 2a4c05662a | |||
|
|
eaec2339cc | ||
|
|
83035be830 | ||
|
|
4709efc678 | ||
|
|
37ded921fd | ||
|
|
b7f3544e98 | ||
|
|
093f2fc0a6 | ||
|
|
c5def9a528 | ||
|
|
e71f3de786 | ||
|
|
420fd7416d | ||
|
|
f505158c04 | ||
|
|
fb13722629 | ||
|
|
666cd0c08d | ||
|
|
e055781006 | ||
|
|
48c8c539c7 | ||
|
|
40c7599fb1 | ||
|
|
28c26c7d7e | ||
|
|
dd5a71695f | ||
|
|
977d324970 | ||
|
|
4992110829 | ||
|
|
53f2539b6a | ||
|
|
18e2906d62 | ||
|
|
19806546a2 | ||
|
|
75559415fe | ||
|
|
7dbb21e77a | ||
|
|
4b72f27de6 | ||
|
|
5ada931ede | ||
|
|
bebe8565cd | ||
|
|
5501dc7b47 | ||
|
|
3e5ab6fdad | ||
|
|
5462db9901 | ||
|
|
59dc585ccd | ||
|
|
6768bd0ff4 | ||
|
|
ed1815c3d9 | ||
|
|
057c209beb | ||
|
|
90c4afded4 | ||
|
|
f8f28a066b | ||
|
|
adc66edd8d | ||
|
|
9af211cc89 | ||
|
|
904bddd988 | ||
|
|
8badfa84e9 | ||
|
|
b97efa6fed | ||
|
|
591f9ad3cf | ||
|
|
6767cd1a4f | ||
|
|
226b6abfab | ||
|
|
9e2c14d64e | ||
|
|
92aeb53ee8 | ||
|
|
87f68e3ac1 | ||
|
|
8073a5dc34 | ||
|
|
eb09156244 | ||
|
|
b8cfb95b49 | ||
|
|
a7843add0f | ||
|
|
b0f0322726 | ||
|
|
7476faba68 | ||
|
|
89ab54794e | ||
|
|
85da0e104b | ||
|
|
47fe3668e4 | ||
|
|
7aae2181e2 | ||
|
|
a9269980eb | ||
|
|
0b9a64331f | ||
|
|
54ff730f0c | ||
|
|
e05fbaa8ab | ||
|
|
61f9346aaf | ||
|
|
d878148b5e | ||
|
|
ee509c7ee6 | ||
|
|
2fa0975dec | ||
|
|
f3ab1f996f | ||
|
|
92c5fc4643 | ||
|
|
c64fa9c81b | ||
|
|
85ec9ec5b2 | ||
|
|
b8933d8f81 | ||
|
|
631da4654f | ||
|
|
1701d72ff9 | ||
|
|
d3ec9a80d3 | ||
|
|
5a1253e37c | ||
|
|
2b008b52d7 | ||
|
|
83939abe10 | ||
|
|
16d02b3ed5 | ||
|
|
79be91831c | ||
|
|
427139f347 | ||
|
|
3ebd2c3f97 | ||
|
|
2414dbdbd4 | ||
|
|
0eae0e8cc0 | ||
|
|
efba965b0c | ||
|
|
26d2c77c3d | ||
|
|
eb01d7c97d | ||
|
|
5bff5bfea6 | ||
|
|
206e92218c | ||
|
|
af3dca9003 | ||
|
|
b924d715c9 | ||
|
|
1372d6f081 | ||
|
|
135a015b6a | ||
|
|
96645eaa7a | ||
|
|
d37b255a11 | ||
|
|
903ee43b2d | ||
|
|
8562f8a964 | ||
|
|
5ff794c105 | ||
|
|
f68e0972c2 | ||
|
|
ba3cc04e84 | ||
|
|
3d4cf44f9b | ||
|
|
8e702012fd | ||
|
|
f49879b522 | ||
|
|
5e0bf2446b | ||
|
|
4d96a3efaa | ||
|
|
c27d72e3a1 | ||
|
|
0819df6988 | ||
|
|
28579239a6 | ||
|
|
e48d2b467a | ||
|
|
1c589336a2 | ||
|
|
9546659c15 | ||
|
|
c782298ae4 | ||
|
|
682fce6a5b | ||
|
|
6ed1b707d5 | ||
|
|
9fd2ccff29 | ||
|
|
b6223a9d0a | ||
|
|
5e98f10011 | ||
|
|
e7ca05e1bf | ||
|
|
677c50fc51 | ||
|
|
bb5feeca77 | ||
|
|
22683ec490 | ||
|
|
0bf7d58c5e | ||
|
|
86566e8d0b | ||
|
|
7080a5ff8b | ||
|
|
5e52ad2ad1 | ||
|
|
bfaa9a9241 | ||
|
|
9c900789de | ||
|
|
29a24ba67f | ||
|
|
987f23698e | ||
|
|
cda4e6136c | ||
|
|
522b481297 | ||
|
|
fafe70f985 | ||
|
|
62818b9407 | ||
|
|
db2fa81358 | ||
|
|
d492901c3e | ||
|
|
a5d52eb853 | ||
|
|
89509c76f4 | ||
|
|
6395dda012 | ||
|
|
54bb0c12e6 | ||
|
|
1f1ed80dbf | ||
|
|
36bcb24b3a | ||
|
|
ddacf07e3b |
213
.gitlab-ci.yml
213
.gitlab-ci.yml
@@ -4,49 +4,71 @@ include:
|
|||||||
- 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:
|
||||||
|
# Auto-retry jobs in case of infra failures
|
||||||
|
retry:
|
||||||
|
max: 1
|
||||||
|
when:
|
||||||
|
- 'runner_system_failure'
|
||||||
|
- 'stuck_or_timeout_failure'
|
||||||
|
- 'scheduler_failure'
|
||||||
|
- 'api_failure'
|
||||||
|
|
||||||
variables:
|
variables:
|
||||||
extends: .libfprint_common_variables
|
extends: .libfprint_common_variables
|
||||||
FDO_DISTRIBUTION_TAG: $LIBFPRINT_IMAGE_TAG
|
FDO_DISTRIBUTION_TAG: $LIBFPRINT_IMAGE_TAG
|
||||||
FDO_DISTRIBUTION_VERSION: rawhide
|
FDO_DISTRIBUTION_VERSION: 41
|
||||||
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: "$CI_REGISTRY/libfprint/$CI_PROJECT_NAME/fedora/$FDO_DISTRIBUTION_VERSION:$FDO_DISTRIBUTION_TAG"
|
||||||
BUNDLE: "org.freedesktop.libfprint.Demo.flatpak"
|
|
||||||
LAST_ABI_BREAK: "056ea541ddc97f5806cffbd99a12dc87e4da3546"
|
LAST_ABI_BREAK: "056ea541ddc97f5806cffbd99a12dc87e4da3546"
|
||||||
|
|
||||||
|
workflow:
|
||||||
|
rules:
|
||||||
|
- if: $CI_PIPELINE_SOURCE == 'merge_request_event'
|
||||||
|
- if: $CI_PIPELINE_SOURCE == 'push'
|
||||||
|
- if: $CI_PIPELINE_SOURCE == 'schedule'
|
||||||
|
- if: $CI_PROJECT_NAMESPACE == 'libfprint' && $LIBFPRINT_CI_ACTION != ''
|
||||||
|
|
||||||
stages:
|
stages:
|
||||||
- image-build
|
- 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
|
||||||
@@ -61,15 +83,13 @@ 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
|
||||||
- ninja -C _build coverage
|
- ninja -C _build coverage || true
|
||||||
- cat _build/meson-logs/coverage.txt
|
- cat _build/meson-logs/coverage.txt || true
|
||||||
artifacts:
|
artifacts:
|
||||||
reports:
|
reports:
|
||||||
junit: "_build/meson-logs/testlog.junit.xml"
|
junit: "_build/meson-logs/testlog.junit.xml"
|
||||||
@@ -86,16 +106,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:
|
reports:
|
||||||
junit: "_build/meson-logs/testlog.junit.xml"
|
junit: "_build/meson-logs/testlog-valgrind.junit.xml"
|
||||||
expose_as: 'Valgrind test logs'
|
expose_as: 'Valgrind test logs'
|
||||||
when: always
|
when: always
|
||||||
paths:
|
paths:
|
||||||
@@ -103,75 +122,123 @@ 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 diff-index --name-only --exit-code HEAD
|
- 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
|
||||||
script:
|
script:
|
||||||
- tests/hwdb-check-unsupported.py
|
- tests/hwdb-check-unsupported.py
|
||||||
|
|
||||||
flatpak:
|
flatpak:
|
||||||
stage: flatpak
|
stage: flatpak
|
||||||
extends: .flatpak
|
extends: .flatpak@x86_64
|
||||||
# From https://gitlab.gnome.org/GNOME/gnome-runtime-images/container_registry
|
|
||||||
image: registry.gitlab.gnome.org/gnome/gnome-runtime-images/gnome:42
|
|
||||||
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_base:
|
.container_fedora_build_base:
|
||||||
extends: .fdo.container-build@fedora
|
extends: .fdo.container-build@fedora
|
||||||
stage: image-build
|
stage: image-build
|
||||||
only:
|
|
||||||
variables:
|
|
||||||
- $CI_PIPELINE_SOURCE == "never"
|
|
||||||
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
|
||||||
@@ -180,26 +247,50 @@ flatpak:
|
|||||||
libudev-devel
|
libudev-devel
|
||||||
FDO_DISTRIBUTION_EXEC: |
|
FDO_DISTRIBUTION_EXEC: |
|
||||||
$LIBFPRINT_EXEC
|
$LIBFPRINT_EXEC
|
||||||
|
rules:
|
||||||
|
- when: never
|
||||||
|
|
||||||
|
.container_fedora_build_forced:
|
||||||
|
variables:
|
||||||
|
FDO_FORCE_REBUILD: 1
|
||||||
|
|
||||||
container_fedora_build_schedule:
|
container_fedora_build_schedule:
|
||||||
extends: .container_fedora_build_base
|
extends:
|
||||||
only:
|
- .container_fedora_build_base
|
||||||
variables:
|
- .container_fedora_build_forced
|
||||||
- $CI_PIPELINE_SOURCE == "schedule" && $CRON_TASK == "BUILD_CI_IMAGES"
|
rules:
|
||||||
|
- if: $CI_PIPELINE_SOURCE == "schedule" && $CRON_TASK == "BUILD_CI_IMAGES"
|
||||||
|
when: always
|
||||||
|
|
||||||
container_fedora_build_manual:
|
container_fedora_build_manual:
|
||||||
extends: .container_fedora_build_base
|
extends:
|
||||||
only:
|
- .container_fedora_build_base
|
||||||
variables:
|
- .container_fedora_build_forced
|
||||||
- $LIBFPRINT_CI_ACTION == "build-image"
|
rules:
|
||||||
|
- if: $LIBFPRINT_CI_ACTION == "build-image"
|
||||||
|
when: always
|
||||||
|
|
||||||
container_fedora_build_on_deps_changed:
|
container_fedora_build_on_deps_changed:
|
||||||
extends: .container_fedora_build_base
|
extends: .container_fedora_build_base
|
||||||
only:
|
rules:
|
||||||
variables:
|
- if: $CI_PROJECT_NAMESPACE == "libfprint" && $CI_PIPELINE_SOURCE != "schedule"
|
||||||
- $CI_PROJECT_NAMESPACE == "libfprint" && $CI_PIPELINE_SOURCE != "schedule"
|
changes:
|
||||||
refs:
|
compare_to: 'refs/heads/master'
|
||||||
- branches
|
paths:
|
||||||
- merge_requests
|
- '.gitlab-ci/libfprint-image-variables.yaml'
|
||||||
changes:
|
- '.gitlab-ci/libfprint-templates.yaml'
|
||||||
- .gitlab-ci/libfprint-image-variables.yaml
|
|
||||||
|
pages:
|
||||||
|
image: alpine:latest
|
||||||
|
stage: deploy
|
||||||
|
needs:
|
||||||
|
- job: test
|
||||||
|
artifacts: true
|
||||||
|
script:
|
||||||
|
- mkdir public
|
||||||
|
- mv _build/meson-logs/coveragereport public/coverage
|
||||||
|
artifacts:
|
||||||
|
paths:
|
||||||
|
- public
|
||||||
|
rules:
|
||||||
|
- if: $CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH && $CI_PIPELINE_SOURCE == "push"
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
variables:
|
variables:
|
||||||
LIBFPRINT_IMAGE_TAG: v2
|
LIBFPRINT_IMAGE_TAG: v6
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
.libfprint_common_variables:
|
.libfprint_common_variables:
|
||||||
LIBFPRINT_DEPENDENCIES:
|
LIBFPRINT_DEPENDENCIES:
|
||||||
|
appstream
|
||||||
doxygen
|
doxygen
|
||||||
dnf-plugins-core
|
dnf-plugins-core
|
||||||
flatpak-builder
|
flatpak-builder
|
||||||
@@ -13,15 +14,18 @@
|
|||||||
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
|
||||||
python3-cairo
|
python3-cairo
|
||||||
python3-gobject
|
python3-gobject
|
||||||
@@ -33,15 +37,11 @@
|
|||||||
diffutils
|
diffutils
|
||||||
|
|
||||||
LIBFPRINT_EXEC: |
|
LIBFPRINT_EXEC: |
|
||||||
dnf debuginfo-install -y \
|
dnf -y install dnf-utils
|
||||||
|
debuginfo-install -y \
|
||||||
glib2 \
|
glib2 \
|
||||||
glibc \
|
glibc \
|
||||||
libgusb \
|
libgusb \
|
||||||
libusb \
|
libusb \
|
||||||
nss \
|
openssl \
|
||||||
pixman
|
pixman
|
||||||
|
|
||||||
git clone https://github.com/martinpitt/umockdev.git && \
|
|
||||||
cd umockdev && \
|
|
||||||
meson _build --prefix=/usr && \
|
|
||||||
ninja -C _build && ninja -C _build install
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
# This wrapper just disables the malloc checker
|
# This wrapper just disables the malloc checker
|
||||||
exec /usr/bin/scan-build --status-bugs -disable-checker unix.Malloc "$@"
|
exec /usr/bin/scan-build --status-bugs -disable-checker unix.Malloc --exclude "_build/meson-private" "$@"
|
||||||
|
|||||||
63
NEWS
63
NEWS
@@ -1,6 +1,65 @@
|
|||||||
This file lists notable changes in each release. For the full history of all
|
This file lists notable changes in each release. For the full history of all
|
||||||
changes, see ChangeLog.
|
changes, see ChangeLog.
|
||||||
|
|
||||||
|
2025-02-20: v1.94.9 release
|
||||||
|
|
||||||
|
Highlights:
|
||||||
|
* uru4000: Use OpenSSL to perform AES-ECB encryption, as per this libfprint
|
||||||
|
does not support on NSS, but on openssl (>= 3.0).
|
||||||
|
* goodixmoc: New PIDs 0x60C2, 0x689A
|
||||||
|
* synaptics: New PIDs 0x016C, 0x0174, 0x0107, 0x0108, 0x00C2, 0x00F0
|
||||||
|
* fpcmoc: New PID 0xC844
|
||||||
|
* focaltech_moc: New PIDs 0xA99A, 0xA57A, 0xA78A
|
||||||
|
* elanmoc: New PIDs 0x0C98, 0x0C9D, 0x0CA3
|
||||||
|
* elanspi: New PIDs 0x3128, 0x2766
|
||||||
|
* fp-device: Add FP_DEVICE_RETRY_TOO_FAST retry error
|
||||||
|
* data: AppStream meta info listing supported USB devices.
|
||||||
|
* fixed various memory issues in multiple devices
|
||||||
|
|
||||||
|
2024-09-03: v1.94.8 release
|
||||||
|
|
||||||
|
Highlights:
|
||||||
|
* build: Support building in non-linux unix environments (tested in FreeBSD)
|
||||||
|
* egismoc: New PIDs 0x0583, 0x0586, 0x0587.
|
||||||
|
* elanmoc: New PID 0x0C9F.
|
||||||
|
* fpcmoc: New PIDs 0x9524, 0x9544.
|
||||||
|
* goodixmoc: New PIDs 0x609A, 0x650A, 0x650C, 0x6512.
|
||||||
|
* realtek: New PID 0x5816.
|
||||||
|
* synaptics: New PIDs 0x00C4, 0x019D, 0x00C6.
|
||||||
|
* fpcmoc: fix incorrect immobile handling during enrollment.
|
||||||
|
* fpcmoc: fixed jumping to wrong state at end of custom enroll.
|
||||||
|
* egismoc: various code cleanups.
|
||||||
|
|
||||||
|
2024-02-20: v1.94.7 release
|
||||||
|
|
||||||
|
Highlights:
|
||||||
|
* synaptics: fix enroll identify problem after user reset database.
|
||||||
|
* synaptics: New PIDs 0x0173, 0x0106, 0x0124.
|
||||||
|
* goodixmoc: New PID 0x6582.
|
||||||
|
* build: Do not require bash to build, only posix sh.
|
||||||
|
* fp-image: Simplify minutiae detection tasks.
|
||||||
|
* GLib 2.68 is now required to build libfprint.
|
||||||
|
|
||||||
|
New drivers:
|
||||||
|
* realtek (PID 0x5813).
|
||||||
|
* focaltech_moc (PIDs 0x9E48, 0xD979, 0xA959).
|
||||||
|
* egismoc (PIDs 0x0582, 0x05a1).
|
||||||
|
|
||||||
|
2023-08-17: v1.94.6 release
|
||||||
|
|
||||||
|
Highlights:
|
||||||
|
* goodixmoc: New PIDs 0x60A4, 0x60BC, 0x6092, 0x633C and 0x6304.
|
||||||
|
* goodixmoc: Fix missing "enroll create" state.
|
||||||
|
* elanmoc: New PID 0x0C99.
|
||||||
|
* upektc: Improve compatibility with sensors 147e:2016.
|
||||||
|
* aes4000: Actually support 08FF:5501 devices.
|
||||||
|
* virtual-device-listener: Fix failing tests with GLib 2.76
|
||||||
|
* tests: Add installed tests
|
||||||
|
|
||||||
|
Bugs fixed:
|
||||||
|
* #526 libfprint: fpcmoc: use after free if enrollment or identification is
|
||||||
|
cancelled (Vasily Khoruzhick)
|
||||||
|
|
||||||
2022-10-13: v1.94.5 release
|
2022-10-13: v1.94.5 release
|
||||||
|
|
||||||
Highlights:
|
Highlights:
|
||||||
@@ -342,7 +401,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:
|
||||||
@@ -392,7 +451,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
|
||||||
|
|
||||||
|
|||||||
@@ -46,6 +46,12 @@ We include **Bozorth3** from the **[US Export Controlled]**
|
|||||||
distribution, which we have determined to be fine
|
distribution, which we have determined to be fine
|
||||||
being shipped in an open source project.
|
being shipped in an open source project.
|
||||||
|
|
||||||
|
## Get in *touch*
|
||||||
|
|
||||||
|
- [IRC] - `#fprint` @ `irc.oftc.net`
|
||||||
|
- [Matrix] - `#fprint:matrix.org` bridged to the IRC channel
|
||||||
|
- [MailingList] - low traffic, not much used these days
|
||||||
|
|
||||||
<br/>
|
<br/>
|
||||||
|
|
||||||
<div align="right">
|
<div align="right">
|
||||||
@@ -62,6 +68,9 @@ being shipped in an open source project.
|
|||||||
[Unsupported]: https://gitlab.freedesktop.org/libfprint/wiki/-/wikis/Unsupported-Devices
|
[Unsupported]: https://gitlab.freedesktop.org/libfprint/wiki/-/wikis/Unsupported-Devices
|
||||||
[Supported]: https://fprint.freedesktop.org/supported-devices.html
|
[Supported]: https://fprint.freedesktop.org/supported-devices.html
|
||||||
[Website]: https://fprint.freedesktop.org/
|
[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
|
[Contribute]: ./HACKING.md
|
||||||
[License]: ./COPYING
|
[License]: ./COPYING
|
||||||
|
|||||||
@@ -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,17 @@ usb:v1C7Ap0571*
|
|||||||
ID_AUTOSUSPEND=1
|
ID_AUTOSUSPEND=1
|
||||||
ID_PERSIST=0
|
ID_PERSIST=0
|
||||||
|
|
||||||
|
# Supported by libfprint driver egismoc
|
||||||
|
usb:v1C7Ap0582*
|
||||||
|
usb:v1C7Ap0583*
|
||||||
|
usb:v1C7Ap0584*
|
||||||
|
usb:v1C7Ap0586*
|
||||||
|
usb:v1C7Ap0587*
|
||||||
|
usb:v1C7Ap05A1*
|
||||||
|
usb:v1C7Ap05A5*
|
||||||
|
ID_AUTOSUSPEND=1
|
||||||
|
ID_PERSIST=0
|
||||||
|
|
||||||
# Supported by libfprint driver elan
|
# Supported by libfprint driver elan
|
||||||
usb:v04F3p0903*
|
usb:v04F3p0903*
|
||||||
usb:v04F3p0907*
|
usb:v04F3p0907*
|
||||||
@@ -149,6 +160,11 @@ usb:v04F3p0C82*
|
|||||||
usb:v04F3p0C88*
|
usb:v04F3p0C88*
|
||||||
usb:v04F3p0C8C*
|
usb:v04F3p0C8C*
|
||||||
usb:v04F3p0C8D*
|
usb:v04F3p0C8D*
|
||||||
|
usb:v04F3p0C98*
|
||||||
|
usb:v04F3p0C99*
|
||||||
|
usb:v04F3p0C9D*
|
||||||
|
usb:v04F3p0C9F*
|
||||||
|
usb:v04F3p0CA3*
|
||||||
ID_AUTOSUSPEND=1
|
ID_AUTOSUSPEND=1
|
||||||
ID_PERSIST=0
|
ID_PERSIST=0
|
||||||
|
|
||||||
@@ -157,22 +173,43 @@ 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:v2808pA959*
|
||||||
|
usb:v2808pA99A*
|
||||||
|
usb:v2808pA57A*
|
||||||
|
usb:v2808pA78A*
|
||||||
|
ID_AUTOSUSPEND=1
|
||||||
|
ID_PERSIST=0
|
||||||
|
|
||||||
# Supported by libfprint driver fpcmoc
|
# Supported by libfprint driver fpcmoc
|
||||||
usb:v10A5pFFE0*
|
usb:v10A5pFFE0*
|
||||||
usb:v10A5pA305*
|
usb:v10A5pA305*
|
||||||
|
usb:v10A5pA306*
|
||||||
usb:v10A5pDA04*
|
usb:v10A5pDA04*
|
||||||
usb:v10A5pD805*
|
usb:v10A5pD805*
|
||||||
usb:v10A5pD205*
|
usb:v10A5pD205*
|
||||||
|
usb:v10A5p9524*
|
||||||
|
usb:v10A5p9544*
|
||||||
|
usb:v10A5pC844*
|
||||||
ID_AUTOSUSPEND=1
|
ID_AUTOSUSPEND=1
|
||||||
ID_PERSIST=0
|
ID_PERSIST=0
|
||||||
|
|
||||||
# Supported by libfprint driver goodixmoc
|
# Supported by libfprint driver goodixmoc
|
||||||
usb:v27C6p5840*
|
usb:v27C6p5840*
|
||||||
usb:v27C6p6014*
|
usb:v27C6p6014*
|
||||||
|
usb:v27C6p6092*
|
||||||
usb:v27C6p6094*
|
usb:v27C6p6094*
|
||||||
|
usb:v27C6p609A*
|
||||||
usb:v27C6p609C*
|
usb:v27C6p609C*
|
||||||
usb:v27C6p60A2*
|
usb:v27C6p60A2*
|
||||||
|
usb:v27C6p60A4*
|
||||||
|
usb:v27C6p60BC*
|
||||||
|
usb:v27C6p60C2*
|
||||||
|
usb:v27C6p6304*
|
||||||
usb:v27C6p631C*
|
usb:v27C6p631C*
|
||||||
|
usb:v27C6p633C*
|
||||||
usb:v27C6p634C*
|
usb:v27C6p634C*
|
||||||
usb:v27C6p6384*
|
usb:v27C6p6384*
|
||||||
usb:v27C6p639C*
|
usb:v27C6p639C*
|
||||||
@@ -180,6 +217,9 @@ 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*
|
||||||
@@ -187,6 +227,8 @@ usb:v27C6p6594*
|
|||||||
usb:v27C6p659A*
|
usb:v27C6p659A*
|
||||||
usb:v27C6p659C*
|
usb:v27C6p659C*
|
||||||
usb:v27C6p6A94*
|
usb:v27C6p6A94*
|
||||||
|
usb:v27C6p6512*
|
||||||
|
usb:v27C6p689A*
|
||||||
ID_AUTOSUSPEND=1
|
ID_AUTOSUSPEND=1
|
||||||
ID_PERSIST=0
|
ID_PERSIST=0
|
||||||
|
|
||||||
@@ -195,21 +237,40 @@ usb:v298Dp1010*
|
|||||||
ID_AUTOSUSPEND=1
|
ID_AUTOSUSPEND=1
|
||||||
ID_PERSIST=0
|
ID_PERSIST=0
|
||||||
|
|
||||||
|
# Supported by libfprint driver realtek
|
||||||
|
usb:v0BDAp5813*
|
||||||
|
usb:v0BDAp5816*
|
||||||
|
ID_AUTOSUSPEND=1
|
||||||
|
ID_PERSIST=0
|
||||||
|
|
||||||
# Supported by libfprint driver synaptics
|
# Supported by libfprint driver synaptics
|
||||||
usb:v06CBp00BD*
|
usb:v06CBp00BD*
|
||||||
|
usb:v06CBp00C2*
|
||||||
|
usb:v06CBp00C4*
|
||||||
|
usb:v06CBp00C6*
|
||||||
usb:v06CBp00DF*
|
usb:v06CBp00DF*
|
||||||
|
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:v06CBp0123*
|
usb:v06CBp0123*
|
||||||
|
usb:v06CBp0124*
|
||||||
usb:v06CBp0126*
|
usb:v06CBp0126*
|
||||||
usb:v06CBp0129*
|
usb:v06CBp0129*
|
||||||
usb:v06CBp0168*
|
|
||||||
usb:v06CBp015F*
|
usb:v06CBp015F*
|
||||||
usb:v06CBp0104*
|
usb:v06CBp0168*
|
||||||
|
usb:v06CBp016C*
|
||||||
|
usb:v06CBp0173*
|
||||||
|
usb:v06CBp0174*
|
||||||
|
usb:v06CBp019D*
|
||||||
|
usb:v06CBp019F*
|
||||||
ID_AUTOSUSPEND=1
|
ID_AUTOSUSPEND=1
|
||||||
ID_PERSIST=0
|
ID_PERSIST=0
|
||||||
|
|
||||||
@@ -278,6 +339,10 @@ usb:v138Ap0091*
|
|||||||
ID_PERSIST=0
|
ID_PERSIST=0
|
||||||
|
|
||||||
# Known unsupported devices
|
# Known unsupported devices
|
||||||
|
usb:v0A5Cp5802*
|
||||||
|
usb:v047Dp00F2*
|
||||||
|
usb:v047Dp8054*
|
||||||
|
usb:v047Dp8055*
|
||||||
usb:v04E8p730B*
|
usb:v04E8p730B*
|
||||||
usb:v04F3p036B*
|
usb:v04F3p036B*
|
||||||
usb:v04F3p0C00*
|
usb:v04F3p0C00*
|
||||||
@@ -285,12 +350,25 @@ usb:v04F3p0C4C*
|
|||||||
usb:v04F3p0C57*
|
usb:v04F3p0C57*
|
||||||
usb:v04F3p0C5E*
|
usb:v04F3p0C5E*
|
||||||
usb:v04F3p0C5A*
|
usb:v04F3p0C5A*
|
||||||
|
usb:v04F3p0C60*
|
||||||
|
usb:v04F3p0C6C*
|
||||||
usb:v04F3p0C70*
|
usb:v04F3p0C70*
|
||||||
usb:v04F3p0C72*
|
usb:v04F3p0C72*
|
||||||
|
usb:v04F3p0C77*
|
||||||
|
usb:v04F3p0C7C*
|
||||||
|
usb:v04F3p0C7F*
|
||||||
|
usb:v04F3p0C80*
|
||||||
|
usb:v04F3p0C85*
|
||||||
|
usb:v04F3p0C90*
|
||||||
usb:v04F3p2706*
|
usb:v04F3p2706*
|
||||||
|
usb:v04F3p3032*
|
||||||
usb:v04F3p3057*
|
usb:v04F3p3057*
|
||||||
usb:v04F3p3104*
|
usb:v04F3p3104*
|
||||||
usb:v04F3p310D*
|
usb:v04F3p310D*
|
||||||
|
usb:v04F3p3128*
|
||||||
|
usb:v04F3p0C8A*
|
||||||
|
usb:v05BAp000E*
|
||||||
|
usb:v06CBp0051*
|
||||||
usb:v06CBp0081*
|
usb:v06CBp0081*
|
||||||
usb:v06CBp0088*
|
usb:v06CBp0088*
|
||||||
usb:v06CBp008A*
|
usb:v06CBp008A*
|
||||||
@@ -301,7 +379,6 @@ usb:v06CBp00A8*
|
|||||||
usb:v06CBp00B7*
|
usb:v06CBp00B7*
|
||||||
usb:v06CBp00BB*
|
usb:v06CBp00BB*
|
||||||
usb:v06CBp00BE*
|
usb:v06CBp00BE*
|
||||||
usb:v06CBp00C4*
|
|
||||||
usb:v06CBp00CB*
|
usb:v06CBp00CB*
|
||||||
usb:v06CBp00C9*
|
usb:v06CBp00C9*
|
||||||
usb:v06CBp00D8*
|
usb:v06CBp00D8*
|
||||||
@@ -311,6 +388,7 @@ usb:v06CBp00E4*
|
|||||||
usb:v06CBp00E7*
|
usb:v06CBp00E7*
|
||||||
usb:v06CBp00E9*
|
usb:v06CBp00E9*
|
||||||
usb:v06CBp00FD*
|
usb:v06CBp00FD*
|
||||||
|
usb:v06CBp00FF*
|
||||||
usb:v0A5Cp5801*
|
usb:v0A5Cp5801*
|
||||||
usb:v0A5Cp5805*
|
usb:v0A5Cp5805*
|
||||||
usb:v0A5Cp5834*
|
usb:v0A5Cp5834*
|
||||||
@@ -320,10 +398,19 @@ 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:v0BDAp5812*
|
usb:v0BDAp5812*
|
||||||
usb:v10A5p0007*
|
usb:v10A5p0007*
|
||||||
usb:v10A5p9200*
|
usb:v10A5p9200*
|
||||||
usb:v10A5p9800*
|
usb:v10A5p9800*
|
||||||
|
usb:v10A5pA120*
|
||||||
|
usb:v10A5pA900*
|
||||||
|
usb:v10A5pE340*
|
||||||
usb:v1188p9545*
|
usb:v1188p9545*
|
||||||
usb:v138Ap0007*
|
usb:v138Ap0007*
|
||||||
usb:v138Ap003A*
|
usb:v138Ap003A*
|
||||||
@@ -336,12 +423,17 @@ usb:v138Ap0094*
|
|||||||
usb:v138Ap0097*
|
usb:v138Ap0097*
|
||||||
usb:v138Ap009D*
|
usb:v138Ap009D*
|
||||||
usb:v138Ap00AB*
|
usb:v138Ap00AB*
|
||||||
|
usb:v138Ap00A6*
|
||||||
usb:v147Ep1002*
|
usb:v147Ep1002*
|
||||||
usb:v1491p0088*
|
usb:v1491p0088*
|
||||||
usb:v16D1p1027*
|
usb:v16D1p1027*
|
||||||
usb:v1C7Ap0300*
|
usb:v1C7Ap0300*
|
||||||
usb:v1C7Ap0575*
|
usb:v1C7Ap0575*
|
||||||
usb:v1C7Ap0576*
|
usb:v1C7Ap0576*
|
||||||
|
usb:v1C7Ap0577*
|
||||||
|
usb:v1C7Ap057E*
|
||||||
|
usb:v2541p0236*
|
||||||
|
usb:v2541p9711*
|
||||||
usb:v27C6p5042*
|
usb:v27C6p5042*
|
||||||
usb:v27C6p5110*
|
usb:v27C6p5110*
|
||||||
usb:v27C6p5117*
|
usb:v27C6p5117*
|
||||||
@@ -369,10 +461,18 @@ usb:v27C6p55B4*
|
|||||||
usb:v27C6p5740*
|
usb:v27C6p5740*
|
||||||
usb:v27C6p5E0A*
|
usb:v27C6p5E0A*
|
||||||
usb:v27C6p581A*
|
usb:v27C6p581A*
|
||||||
|
usb:v27C6p589A*
|
||||||
|
usb:v27C6p5F10*
|
||||||
|
usb:v27C6p6382*
|
||||||
usb:v2808p9338*
|
usb:v2808p9338*
|
||||||
|
usb:v2808p9348*
|
||||||
usb:v2808p93A9*
|
usb:v2808p93A9*
|
||||||
|
usb:v2808pA658*
|
||||||
|
usb:v2808pC652*
|
||||||
usb:v298Dp2020*
|
usb:v298Dp2020*
|
||||||
usb:v298Dp2033*
|
usb:v298Dp2033*
|
||||||
|
usb:v2DF0p0003*
|
||||||
|
usb:v3274p8012*
|
||||||
usb:v3538p0930*
|
usb:v3538p0930*
|
||||||
ID_AUTOSUSPEND=1
|
ID_AUTOSUSPEND=1
|
||||||
ID_PERSIST=0
|
ID_PERSIST=0
|
||||||
|
|||||||
@@ -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,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"app-id": "org.freedesktop.libfprint.Demo",
|
"app-id": "org.freedesktop.libfprint.Demo",
|
||||||
"runtime": "org.gnome.Platform",
|
"runtime": "org.gnome.Platform",
|
||||||
"runtime-version": "42",
|
"runtime-version": "master",
|
||||||
"sdk": "org.gnome.Sdk",
|
"sdk": "org.gnome.Sdk",
|
||||||
"command": "gtk-libfprint-test",
|
"command": "gtk-libfprint-test",
|
||||||
"finish-args": [
|
"finish-args": [
|
||||||
@@ -38,24 +38,24 @@
|
|||||||
{
|
{
|
||||||
"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"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -100,6 +100,12 @@ FP_TYPE_IMAGE_DEVICE
|
|||||||
FpImageDevice
|
FpImageDevice
|
||||||
</SECTION>
|
</SECTION>
|
||||||
|
|
||||||
|
<SECTION>
|
||||||
|
<FILE>fp-sdcp-device</FILE>
|
||||||
|
FP_TYPE_SDCP_DEVICE
|
||||||
|
FpSdcpDevice
|
||||||
|
</SECTION>
|
||||||
|
|
||||||
<SECTION>
|
<SECTION>
|
||||||
<FILE>fp-print</FILE>
|
<FILE>fp-print</FILE>
|
||||||
FP_TYPE_PRINT
|
FP_TYPE_PRINT
|
||||||
@@ -215,6 +221,31 @@ fpi_image_device_retry_scan
|
|||||||
fpi_image_device_set_bz3_threshold
|
fpi_image_device_set_bz3_threshold
|
||||||
</SECTION>
|
</SECTION>
|
||||||
|
|
||||||
|
<SECTION>
|
||||||
|
<FILE>fpi-sdcp-device</FILE>
|
||||||
|
<TITLE>Internal FpSdcpDevice</TITLE>
|
||||||
|
FpiSdcpClaim
|
||||||
|
FpSdcpDeviceClass
|
||||||
|
fpi_sdcp_claim_get_type
|
||||||
|
fpi_sdcp_claim_new
|
||||||
|
fpi_sdcp_claim_copy
|
||||||
|
fpi_sdcp_claim_free
|
||||||
|
fpi_sdcp_device_open_complete
|
||||||
|
fpi_sdcp_device_get_connect_data
|
||||||
|
fpi_sdcp_device_connect_complete
|
||||||
|
fpi_sdcp_device_get_reconnect_data
|
||||||
|
fpi_sdcp_device_reconnect_complete
|
||||||
|
fpi_sdcp_device_list_complete
|
||||||
|
fpi_sdcp_device_enroll_commit
|
||||||
|
fpi_sdcp_device_enroll_commit_complete
|
||||||
|
fpi_sdcp_device_get_identify_data
|
||||||
|
fpi_sdcp_device_set_identify_data
|
||||||
|
fpi_sdcp_device_identify_retry
|
||||||
|
fpi_sdcp_device_identify_complete
|
||||||
|
fpi_sdcp_device_get_print_id
|
||||||
|
fpi_sdcp_device_set_print_id
|
||||||
|
</SECTION>
|
||||||
|
|
||||||
<SECTION>
|
<SECTION>
|
||||||
<FILE>fpi-log</FILE>
|
<FILE>fpi-log</FILE>
|
||||||
fp_dbg
|
fp_dbg
|
||||||
@@ -223,6 +254,8 @@ fp_warn
|
|||||||
fp_err
|
fp_err
|
||||||
BUG_ON
|
BUG_ON
|
||||||
BUG
|
BUG
|
||||||
|
fp_dbg_hex_dump_bytes
|
||||||
|
fp_dbg_hex_dump_gbytes
|
||||||
</SECTION>
|
</SECTION>
|
||||||
|
|
||||||
<SECTION>
|
<SECTION>
|
||||||
|
|||||||
@@ -28,6 +28,7 @@
|
|||||||
<xi:include href="xml/fp-context.xml"/>
|
<xi:include href="xml/fp-context.xml"/>
|
||||||
<xi:include href="xml/fp-device.xml"/>
|
<xi:include href="xml/fp-device.xml"/>
|
||||||
<xi:include href="xml/fp-image-device.xml"/>
|
<xi:include href="xml/fp-image-device.xml"/>
|
||||||
|
<xi:include href="xml/fp-sdcp-device.xml"/>
|
||||||
<xi:include href="xml/fp-print.xml"/>
|
<xi:include href="xml/fp-print.xml"/>
|
||||||
<xi:include href="xml/fp-image.xml"/>
|
<xi:include href="xml/fp-image.xml"/>
|
||||||
</part>
|
</part>
|
||||||
@@ -38,6 +39,7 @@
|
|||||||
<title>Device methods for drivers</title>
|
<title>Device methods for drivers</title>
|
||||||
<xi:include href="xml/fpi-device.xml"/>
|
<xi:include href="xml/fpi-device.xml"/>
|
||||||
<xi:include href="xml/fpi-image-device.xml"/>
|
<xi:include href="xml/fpi-image-device.xml"/>
|
||||||
|
<xi:include href="xml/fpi-sdcp-device.xml"/>
|
||||||
</chapter>
|
</chapter>
|
||||||
|
|
||||||
<chapter id="driver-helpers">
|
<chapter id="driver-helpers">
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
208
examples/clear-storage.c
Normal file
208
examples/clear-storage.c
Normal file
@@ -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
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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 },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
1919
libfprint/drivers/egismoc/egismoc.c
Normal file
1919
libfprint/drivers/egismoc/egismoc.c
Normal file
File diff suppressed because it is too large
Load Diff
244
libfprint/drivers/egismoc/egismoc.h
Normal file
244
libfprint/drivers/egismoc/egismoc.h
Normal file
@@ -0,0 +1,244 @@
|
|||||||
|
/*
|
||||||
|
* Driver for Egis Technology (LighTuning) Match-On-Chip sensors
|
||||||
|
* Copyright (C) 2023-2025 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)
|
||||||
|
*
|
||||||
|
* 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-ssm.h"
|
||||||
|
|
||||||
|
#include "fpi-sdcp-device.h"
|
||||||
|
|
||||||
|
G_DECLARE_FINAL_TYPE (FpiDeviceEgisMoc, fpi_device_egismoc, FPI, DEVICE_EGISMOC, FpSdcpDevice)
|
||||||
|
|
||||||
|
#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_DRIVER_MAX_ENROLL_STAGES_15 (1 << 3)
|
||||||
|
|
||||||
|
#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_FINGER_ON_SENSOR_TIMEOUT_USEC (10 * G_USEC_PER_SEC)
|
||||||
|
|
||||||
|
#define EGISMOC_CONNECT_RESPONSE_PREFIX_SIZE 15
|
||||||
|
#define EGISMOC_IDENTIFY_RESPONSE_PREFIX_SIZE 14
|
||||||
|
#define EGISMOC_ENROLL_STARTING_RESPONSE_PREFIX_SIZE 14
|
||||||
|
#define EGISMOC_LIST_RESPONSE_PREFIX_SIZE 14
|
||||||
|
#define EGISMOC_LIST_RESPONSE_SUFFIX_SIZE 2
|
||||||
|
|
||||||
|
/* standard prefixes for all read/writes */
|
||||||
|
|
||||||
|
static guchar egismoc_write_prefix[] = {'E', 'G', 'I', 'S', 0x00, 0x00, 0x00, 0x01};
|
||||||
|
static gsize egismoc_write_prefix_len = sizeof (egismoc_write_prefix) / sizeof (egismoc_write_prefix[0]);
|
||||||
|
|
||||||
|
static guchar egismoc_read_prefix[] = {'S', 'I', 'G', 'E', 0x00, 0x00, 0x00, 0x01};
|
||||||
|
static gsize egismoc_read_prefix_len = sizeof (egismoc_read_prefix) / sizeof (egismoc_read_prefix[0]);
|
||||||
|
|
||||||
|
|
||||||
|
/* hard-coded command payloads */
|
||||||
|
|
||||||
|
static guchar cmd_fw_version[] = {0x00, 0x00, 0x00, 0x07, 0x50, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x0c};
|
||||||
|
static gsize cmd_fw_version_len = sizeof (cmd_fw_version) / sizeof (cmd_fw_version[0]);
|
||||||
|
static guchar rsp_fw_version_suffix[] = {0x90, 0x00};
|
||||||
|
static gsize rsp_fw_version_suffix_len = sizeof (rsp_fw_version_suffix) / sizeof (rsp_fw_version_suffix[0]);
|
||||||
|
|
||||||
|
static guchar rsp_sensor_has_finger_suffix[] = {0x90, 0x00, 0x90, 0x00};
|
||||||
|
static gsize rsp_sensor_has_finger_suffix_len = sizeof (rsp_sensor_has_finger_suffix) / sizeof (rsp_sensor_has_finger_suffix[0]);
|
||||||
|
|
||||||
|
static guchar cmd_list[] = {0x00, 0x00, 0x00, 0x07, 0x50, 0x19, 0x04, 0x00, 0x00, 0x01, 0x40};
|
||||||
|
static gsize cmd_list_len = sizeof (cmd_list) / sizeof (cmd_list[0]);
|
||||||
|
|
||||||
|
static guchar cmd_sensor_reset[] = {0x00, 0x00, 0x00, 0x04, 0x50, 0x1a, 0x00, 0x00};
|
||||||
|
static gsize cmd_sensor_reset_len = sizeof (cmd_sensor_reset) / sizeof (cmd_sensor_reset[0]);
|
||||||
|
|
||||||
|
static guchar cmd_sensor_check[] = {0x00, 0x00, 0x00, 0x04, 0x50, 0x17, 0x02, 0x00};
|
||||||
|
static gsize cmd_sensor_check_len = sizeof (cmd_sensor_check) / sizeof (cmd_sensor_check[0]);
|
||||||
|
|
||||||
|
static guchar cmd_sensor_identify[] = {0x00, 0x00, 0x00, 0x04, 0x50, 0x17, 0x01, 0x01};
|
||||||
|
static gsize cmd_sensor_identify_len = sizeof (cmd_sensor_identify) / sizeof (cmd_sensor_identify[0]);
|
||||||
|
static guchar rsp_identify_match_suffix[] = {0x90, 0x00};
|
||||||
|
static gsize rsp_identify_match_suffix_len = sizeof (rsp_identify_match_suffix) / sizeof (rsp_identify_match_suffix[0]);
|
||||||
|
static guchar rsp_identify_notmatch_suffix[] = {0x90, 0x04};
|
||||||
|
static gsize rsp_identify_notmatch_suffix_len = sizeof (rsp_identify_notmatch_suffix) / sizeof (rsp_identify_notmatch_suffix[0]);
|
||||||
|
|
||||||
|
static guchar cmd_sensor_enroll[] = {0x00, 0x00, 0x00, 0x04, 0x50, 0x17, 0x01, 0x00};
|
||||||
|
static gsize cmd_sensor_enroll_len = sizeof (cmd_sensor_enroll) / sizeof (cmd_sensor_enroll[0]);
|
||||||
|
|
||||||
|
static guchar cmd_enroll_starting[] = {0x00, 0x00, 0x00, 0x07, 0x50, 0x16, 0x01, 0x00, 0x00, 0x00, 0x20};
|
||||||
|
static gsize cmd_enroll_starting_len = sizeof (cmd_enroll_starting) / sizeof (cmd_enroll_starting[0]);
|
||||||
|
static guchar rsp_enroll_starting_suffix[] = {0x90, 0x00};
|
||||||
|
static gsize rsp_enroll_starting_suffix_len = sizeof (rsp_enroll_starting_suffix) / sizeof (rsp_enroll_starting_suffix[0]);
|
||||||
|
|
||||||
|
static guchar cmd_sensor_start_capture[] = {0x00, 0x00, 0x00, 0x04, 0x50, 0x16, 0x02, 0x01};
|
||||||
|
static gsize cmd_sensor_start_capture_len = sizeof (cmd_sensor_start_capture) / sizeof (cmd_sensor_start_capture[0]);
|
||||||
|
|
||||||
|
static guchar cmd_capture_post_wait_finger[] = {0x00, 0x00, 0x00, 0x07, 0x50, 0x7a, 0x00, 0x00, 0x00, 0x00, 0x80};
|
||||||
|
static gsize cmd_capture_post_wait_finger_len = sizeof (cmd_capture_post_wait_finger) / sizeof (cmd_capture_post_wait_finger[0]);
|
||||||
|
|
||||||
|
static guchar cmd_read_capture[] = {0x00, 0x00, 0x00, 0x07, 0x50, 0x16, 0x02, 0x02, 0x00, 0x00, 0x02};
|
||||||
|
static gsize cmd_read_capture_len = sizeof (cmd_read_capture) / sizeof (cmd_read_capture[0]);
|
||||||
|
static guchar rsp_read_success_suffix[] = {0x90, 0x00};
|
||||||
|
static gsize rsp_read_success_suffix_len = sizeof (rsp_read_success_suffix) / sizeof (rsp_read_success_suffix[0]);
|
||||||
|
static guchar rsp_read_offcenter_suffix[] = {0x64, 0x91};
|
||||||
|
static gsize rsp_read_offcenter_suffix_len = sizeof (rsp_read_offcenter_suffix) / sizeof (rsp_read_offcenter_suffix[0]);
|
||||||
|
static guchar rsp_read_dirty_prefix[] = {0x00, 0x00, 0x00, 0x02, 0x64};
|
||||||
|
static gsize rsp_read_dirty_prefix_len = sizeof (rsp_read_dirty_prefix) / sizeof (rsp_read_dirty_prefix[0]);
|
||||||
|
|
||||||
|
static guchar cmd_commit_starting[] = {0x00, 0x00, 0x00, 0x07, 0x50, 0x16, 0x05, 0x00, 0x00, 0x00, 0x20};
|
||||||
|
static gsize cmd_commit_starting_len = sizeof (cmd_commit_starting) / sizeof (cmd_commit_starting[0]);
|
||||||
|
static guchar rsp_commit_success_suffix[] = {0x90, 0x00};
|
||||||
|
static gsize rsp_commit_success_suffix_len = sizeof (rsp_commit_success_suffix) / sizeof (rsp_commit_success_suffix[0]);
|
||||||
|
|
||||||
|
|
||||||
|
/* commands which exist on the device but are currently not used */
|
||||||
|
/*
|
||||||
|
static guchar cmd_sensor_cancel[] = {0x00, 0x00, 0x00, 0x04, 0x50, 0x16, 0x04, 0x00};
|
||||||
|
static gsize cmd_sensor_cancel_len = sizeof(cmd_sensor_cancel) / sizeof(cmd_sensor_cancel[0]);
|
||||||
|
|
||||||
|
static guchar cmd_sensor_verify[] = {0x00, 0x00, 0x00, 0x04, 0x50, 0x04, 0x01, 0x00};
|
||||||
|
static gsize cmd_sensor_verify_len = sizeof(cmd_sensor_verify) / sizeof(cmd_sensor_verify[0]);
|
||||||
|
|
||||||
|
static guchar cmd_read_verify[] = {0x00, 0x00, 0x00, 0x04, 0x50, 0x04, 0x02, 0x00};
|
||||||
|
static gsize cmd_read_verify_len = sizeof(cmd_read_verify) / sizeof(cmd_read_verify[0]);
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/* prefixes/suffixes and other things for dynamically created command payloads */
|
||||||
|
|
||||||
|
#define EGISMOC_CHECK_BYTES_LENGTH 2
|
||||||
|
|
||||||
|
static guchar cmd_sdcp_connect_prefix[] = {0x00, 0x00, 0x00, 0x6b, 0x50, 0x57, 0x01, 0x00, 0x00, 0x00, 0x62, 0x20};
|
||||||
|
static gsize cmd_sdcp_connect_prefix_len = sizeof (cmd_sdcp_connect_prefix) / sizeof (cmd_sdcp_connect_prefix[0]);
|
||||||
|
static guchar cmd_sdcp_connect_suffix[] = {0x00, 0x00};
|
||||||
|
static gsize cmd_sdcp_connect_suffix_len = sizeof (cmd_sdcp_connect_suffix) / sizeof (cmd_sdcp_connect_suffix[0]);
|
||||||
|
static guchar rsp_sdcp_connect_success_suffix[] = {0x90, 0x00};
|
||||||
|
static gsize rsp_sdcp_connect_success_suffix_len = sizeof (rsp_sdcp_connect_success_suffix) / sizeof (rsp_sdcp_connect_success_suffix[0]);
|
||||||
|
|
||||||
|
static guchar cmd_new_print_prefix[] = {0x00, 0x00, 0x00, 0x27, 0x50, 0x16, 0x03, 0x00, 0x00, 0x00, 0x20};
|
||||||
|
static gsize cmd_new_print_prefix_len = sizeof (cmd_new_print_prefix) / sizeof (cmd_new_print_prefix[0]);
|
||||||
|
|
||||||
|
static guchar cmd_delete_prefix[] = {0x50, 0x18, 0x04, 0x00, 0x00};
|
||||||
|
static gsize cmd_delete_prefix_len = sizeof (cmd_delete_prefix) / sizeof (cmd_delete_prefix[0]);
|
||||||
|
static guchar rsp_delete_success_prefix[] = {0x00, 0x00, 0x00, 0x02, 0x90, 0x00};
|
||||||
|
static gsize rsp_delete_success_prefix_len = sizeof (rsp_delete_success_prefix) / sizeof (rsp_delete_success_prefix[0]);
|
||||||
|
|
||||||
|
static guchar cmd_check_prefix_type1[] = {0x50, 0x17, 0x03, 0x00, 0x00};
|
||||||
|
static gsize cmd_check_prefix_type1_len = sizeof (cmd_check_prefix_type1) / sizeof (cmd_check_prefix_type1[0]);
|
||||||
|
static guchar cmd_check_prefix_type2[] = {0x50, 0x17, 0x03, 0x80, 0x00};
|
||||||
|
static gsize cmd_check_prefix_type2_len = sizeof (cmd_check_prefix_type2) / sizeof (cmd_check_prefix_type2[0]);
|
||||||
|
static guchar cmd_check_suffix[] = {0x00, 0x40};
|
||||||
|
static gsize cmd_check_suffix_len = sizeof (cmd_check_suffix) / sizeof (cmd_check_suffix[0]);
|
||||||
|
static guchar rsp_check_not_yet_enrolled_suffix[] = {0x90, 0x04};
|
||||||
|
static gsize rsp_check_not_yet_enrolled_suffix_len = sizeof (rsp_check_not_yet_enrolled_suffix) / sizeof (rsp_check_not_yet_enrolled_suffix[0]);
|
||||||
|
|
||||||
|
|
||||||
|
/* SSM task states and various status enums */
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
CMD_SEND,
|
||||||
|
CMD_GET,
|
||||||
|
CMD_STATES,
|
||||||
|
} CommandStates;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
DEV_INIT_CONTROL1,
|
||||||
|
DEV_INIT_CONTROL2,
|
||||||
|
DEV_INIT_CONTROL3,
|
||||||
|
DEV_INIT_CONTROL4,
|
||||||
|
DEV_INIT_CONTROL5,
|
||||||
|
DEV_GET_FW_VERSION,
|
||||||
|
DEV_INIT_STATES,
|
||||||
|
} DeviceInitStates;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
CONNECT,
|
||||||
|
CONNECT_RESPONSE,
|
||||||
|
CONNECT_STATES,
|
||||||
|
} ConnectStates;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
WAIT_FINGER_NOT_ON_SENSOR,
|
||||||
|
WAIT_FINGER_ON_SENSOR,
|
||||||
|
WAIT_FINGER_STATES,
|
||||||
|
} WaitFingerStates;
|
||||||
|
|
||||||
|
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_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_POST_WAIT_FINGER,
|
||||||
|
ENROLL_CAPTURE_READ_RESPONSE,
|
||||||
|
ENROLL_COMMIT_START,
|
||||||
|
ENROLL_COMMIT,
|
||||||
|
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;
|
||||||
@@ -31,6 +31,11 @@ static const FpIdEntry id_table[] = {
|
|||||||
{ .vid = 0x04f3, .pid = 0x0c88, },
|
{ .vid = 0x04f3, .pid = 0x0c88, },
|
||||||
{ .vid = 0x04f3, .pid = 0x0c8c, },
|
{ .vid = 0x04f3, .pid = 0x0c8c, },
|
||||||
{ .vid = 0x04f3, .pid = 0x0c8d, },
|
{ .vid = 0x04f3, .pid = 0x0c8d, },
|
||||||
|
{ .vid = 0x04f3, .pid = 0x0c98, },
|
||||||
|
{ .vid = 0x04f3, .pid = 0x0c99, },
|
||||||
|
{ .vid = 0x04f3, .pid = 0x0c9d, },
|
||||||
|
{ .vid = 0x04f3, .pid = 0x0c9f, },
|
||||||
|
{ .vid = 0x04f3, .pid = 0x0ca3, },
|
||||||
{ .vid = 0, .pid = 0, .driver_data = 0 }, /* terminating entry */
|
{ .vid = 0, .pid = 0, .driver_data = 0 }, /* terminating entry */
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -49,9 +54,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
|
||||||
@@ -1086,6 +1091,10 @@ elanmoc_open (FpDevice *device)
|
|||||||
self->max_moc_enroll_time = 11;
|
self->max_moc_enroll_time = 11;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 0x0c99:
|
||||||
|
self->max_moc_enroll_time = 14;
|
||||||
|
break;
|
||||||
|
|
||||||
case 0x0c8d:
|
case 0x0c8d:
|
||||||
self->max_moc_enroll_time = 17;
|
self->max_moc_enroll_time = 17;
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -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},
|
||||||
|
|||||||
1878
libfprint/drivers/focaltech_moc/focaltech_moc.c
Normal file
1878
libfprint/drivers/focaltech_moc/focaltech_moc.c
Normal file
File diff suppressed because it is too large
Load Diff
52
libfprint/drivers/focaltech_moc/focaltech_moc.h
Normal file
52
libfprint/drivers/focaltech_moc/focaltech_moc.h
Normal file
@@ -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;
|
||||||
|
};
|
||||||
@@ -21,7 +21,7 @@
|
|||||||
|
|
||||||
#define FP_COMPONENT "fpcmoc"
|
#define FP_COMPONENT "fpcmoc"
|
||||||
#define MAX_ENROLL_SAMPLES (25)
|
#define MAX_ENROLL_SAMPLES (25)
|
||||||
#define CTRL_TIMEOUT (1000)
|
#define CTRL_TIMEOUT (2000)
|
||||||
#define DATA_TIMEOUT (5000)
|
#define DATA_TIMEOUT (5000)
|
||||||
|
|
||||||
/* Usb port setting */
|
/* Usb port setting */
|
||||||
@@ -65,9 +65,13 @@ typedef struct
|
|||||||
static const FpIdEntry id_table[] = {
|
static const FpIdEntry id_table[] = {
|
||||||
{ .vid = 0x10A5, .pid = 0xFFE0, },
|
{ .vid = 0x10A5, .pid = 0xFFE0, },
|
||||||
{ .vid = 0x10A5, .pid = 0xA305, },
|
{ .vid = 0x10A5, .pid = 0xA305, },
|
||||||
|
{ .vid = 0x10A5, .pid = 0xA306, },
|
||||||
{ .vid = 0x10A5, .pid = 0xDA04, },
|
{ .vid = 0x10A5, .pid = 0xDA04, },
|
||||||
{ .vid = 0x10A5, .pid = 0xD805, },
|
{ .vid = 0x10A5, .pid = 0xD805, },
|
||||||
{ .vid = 0x10A5, .pid = 0xD205, },
|
{ .vid = 0x10A5, .pid = 0xD205, },
|
||||||
|
{ .vid = 0x10A5, .pid = 0x9524, },
|
||||||
|
{ .vid = 0x10A5, .pid = 0x9544, },
|
||||||
|
{ .vid = 0x10A5, .pid = 0xC844, },
|
||||||
/* terminating entry */
|
/* terminating entry */
|
||||||
{ .vid = 0, .pid = 0, .driver_data = 0 },
|
{ .vid = 0, .pid = 0, .driver_data = 0 },
|
||||||
};
|
};
|
||||||
@@ -132,7 +136,11 @@ fpc_cmd_receive_cb (FpiUsbTransfer *transfer,
|
|||||||
}
|
}
|
||||||
|
|
||||||
ssm_state = fpi_ssm_get_cur_state (transfer->ssm);
|
ssm_state = fpi_ssm_get_cur_state (transfer->ssm);
|
||||||
fp_dbg ("%s current ssm state: %d", G_STRFUNC, ssm_state);
|
fp_dbg ("%s current ssm request: %d state: %d", G_STRFUNC, data->request, ssm_state);
|
||||||
|
|
||||||
|
/* clean cmd_ssm except capture command for suspend/resume case */
|
||||||
|
if (ssm_state != FP_CMD_SEND || data->request != FPC_CMD_ARM)
|
||||||
|
self->cmd_ssm = NULL;
|
||||||
|
|
||||||
if (data->cmdtype == FPC_CMDTYPE_TO_DEVICE)
|
if (data->cmdtype == FPC_CMDTYPE_TO_DEVICE)
|
||||||
{
|
{
|
||||||
@@ -265,6 +273,7 @@ fpc_cmd_ssm_done (FpiSsm *ssm, FpDevice *dev, GError *error)
|
|||||||
FpiDeviceFpcMoc *self = FPI_DEVICE_FPCMOC (dev);
|
FpiDeviceFpcMoc *self = FPI_DEVICE_FPCMOC (dev);
|
||||||
CommandData *data = fpi_ssm_get_data (ssm);
|
CommandData *data = fpi_ssm_get_data (ssm);
|
||||||
|
|
||||||
|
self->cmd_ssm = NULL;
|
||||||
/* Notify about the SSM failure from here instead. */
|
/* Notify about the SSM failure from here instead. */
|
||||||
if (error)
|
if (error)
|
||||||
{
|
{
|
||||||
@@ -272,8 +281,6 @@ fpc_cmd_ssm_done (FpiSsm *ssm, FpDevice *dev, GError *error)
|
|||||||
if (data->callback)
|
if (data->callback)
|
||||||
data->callback (self, NULL, error);
|
data->callback (self, NULL, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
self->cmd_ssm = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -358,6 +365,7 @@ fpc_sensor_cmd (FpiDeviceFpcMoc *self,
|
|||||||
g_clear_object (&self->interrupt_cancellable);
|
g_clear_object (&self->interrupt_cancellable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
g_assert (self->cmd_ssm == NULL);
|
||||||
self->cmd_ssm = fpi_ssm_new (FP_DEVICE (self),
|
self->cmd_ssm = fpi_ssm_new (FP_DEVICE (self),
|
||||||
fpc_cmd_run_state,
|
fpc_cmd_run_state,
|
||||||
FP_CMD_NUM_STATES);
|
FP_CMD_NUM_STATES);
|
||||||
@@ -383,7 +391,7 @@ fpc_dev_release_interface (FpiDeviceFpcMoc *self,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Notify close complete */
|
/* Notify close complete */
|
||||||
fpi_device_close_complete (FP_DEVICE (self), release_error);
|
fpi_device_close_complete (FP_DEVICE (self), g_steal_pointer (&release_error));
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
@@ -441,10 +449,16 @@ fpc_evt_cb (FpiDeviceFpcMoc *self,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case FPC_EVT_FINGER_DWN:
|
case FPC_EVT_FINGER_DWN:
|
||||||
fp_dbg ("%s Got finger down event", G_STRFUNC);
|
fp_dbg ("%s Got finger down event (%d)", G_STRFUNC, presp->evt_hdr.status);
|
||||||
fpi_device_report_finger_status_changes (FP_DEVICE (self),
|
fpi_device_report_finger_status_changes (FP_DEVICE (self),
|
||||||
FP_FINGER_STATUS_PRESENT,
|
FP_FINGER_STATUS_PRESENT,
|
||||||
FP_FINGER_STATUS_NONE);
|
FP_FINGER_STATUS_NONE);
|
||||||
|
if (presp->evt_hdr.status != 0)
|
||||||
|
{
|
||||||
|
/* Redo the current task state if capture failed */
|
||||||
|
fpi_ssm_jump_to_state (self->task_ssm, fpi_ssm_get_cur_state (self->task_ssm));
|
||||||
|
return;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FPC_EVT_IMG:
|
case FPC_EVT_IMG:
|
||||||
@@ -737,15 +751,22 @@ fpc_enroll_update_cb (FpiDeviceFpcMoc *self,
|
|||||||
/* here should tips remove finger and try again */
|
/* here should tips remove finger and try again */
|
||||||
if (self->max_immobile_stage)
|
if (self->max_immobile_stage)
|
||||||
{
|
{
|
||||||
if (self->immobile_stage >= self->max_immobile_stage)
|
self->immobile_stage++;
|
||||||
|
if (self->immobile_stage > self->max_immobile_stage)
|
||||||
{
|
{
|
||||||
fp_dbg ("Skip similar handle due to customer enrollment %d(%d)",
|
fp_dbg ("Skip similar handle due to customer enrollment %d(%d)",
|
||||||
self->immobile_stage, self->max_immobile_stage);
|
self->immobile_stage, self->max_immobile_stage);
|
||||||
/* Skip too similar handle, treat as normal enroll progress. */
|
/* Skip too similar handle, treat as normal enroll progress. */
|
||||||
fpi_ssm_jump_to_state (self->task_ssm, FPC_ENROL_STATUS_PROGRESS);
|
self->enroll_stage++;
|
||||||
|
fpi_device_enroll_progress (FP_DEVICE (self), self->enroll_stage, NULL, NULL);
|
||||||
|
/* Used for customer enrollment scheme */
|
||||||
|
if (self->enroll_stage >= (self->max_enroll_stage - self->max_immobile_stage))
|
||||||
|
{
|
||||||
|
fpi_ssm_jump_to_state (self->task_ssm, FP_ENROLL_COMPLETE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
self->immobile_stage++;
|
|
||||||
}
|
}
|
||||||
fpi_device_enroll_progress (FP_DEVICE (self),
|
fpi_device_enroll_progress (FP_DEVICE (self),
|
||||||
self->enroll_stage,
|
self->enroll_stage,
|
||||||
@@ -758,7 +779,10 @@ fpc_enroll_update_cb (FpiDeviceFpcMoc *self,
|
|||||||
fpi_device_enroll_progress (FP_DEVICE (self), self->enroll_stage, NULL, NULL);
|
fpi_device_enroll_progress (FP_DEVICE (self), self->enroll_stage, NULL, NULL);
|
||||||
/* Used for customer enrollment scheme */
|
/* Used for customer enrollment scheme */
|
||||||
if (self->enroll_stage >= (self->max_enroll_stage - self->max_immobile_stage))
|
if (self->enroll_stage >= (self->max_enroll_stage - self->max_immobile_stage))
|
||||||
fpi_ssm_jump_to_state (self->task_ssm, FP_ENROLL_COMPLETE);
|
{
|
||||||
|
fpi_ssm_jump_to_state (self->task_ssm, FP_ENROLL_COMPLETE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FPC_ENROL_STATUS_IMAGE_LOW_COVERAGE:
|
case FPC_ENROL_STATUS_IMAGE_LOW_COVERAGE:
|
||||||
@@ -1149,12 +1173,9 @@ fpc_enroll_ssm_done (FpiSsm *ssm, FpDevice *dev, GError *error)
|
|||||||
|
|
||||||
fp_info ("Enrollment complete!");
|
fp_info ("Enrollment complete!");
|
||||||
|
|
||||||
if (fpi_ssm_get_error (ssm))
|
|
||||||
error = fpi_ssm_get_error (ssm);
|
|
||||||
|
|
||||||
if (error)
|
if (error)
|
||||||
{
|
{
|
||||||
fpi_device_enroll_complete (dev, NULL, error);
|
fpi_device_enroll_complete (dev, NULL, g_steal_pointer (&error));
|
||||||
self->task_ssm = NULL;
|
self->task_ssm = NULL;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1336,9 +1357,6 @@ fpc_verify_ssm_done (FpiSsm *ssm, FpDevice *dev, GError *error)
|
|||||||
|
|
||||||
fp_info ("Verify_identify complete!");
|
fp_info ("Verify_identify complete!");
|
||||||
|
|
||||||
if (fpi_ssm_get_error (ssm))
|
|
||||||
error = fpi_ssm_get_error (ssm);
|
|
||||||
|
|
||||||
if (error && error->domain == FP_DEVICE_RETRY)
|
if (error && error->domain == FP_DEVICE_RETRY)
|
||||||
{
|
{
|
||||||
if (fpi_device_get_current_action (dev) == FPI_DEVICE_ACTION_VERIFY)
|
if (fpi_device_get_current_action (dev) == FPI_DEVICE_ACTION_VERIFY)
|
||||||
@@ -1348,9 +1366,9 @@ fpc_verify_ssm_done (FpiSsm *ssm, FpDevice *dev, GError *error)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (fpi_device_get_current_action (dev) == FPI_DEVICE_ACTION_VERIFY)
|
if (fpi_device_get_current_action (dev) == FPI_DEVICE_ACTION_VERIFY)
|
||||||
fpi_device_verify_complete (dev, error);
|
fpi_device_verify_complete (dev, g_steal_pointer (&error));
|
||||||
else
|
else
|
||||||
fpi_device_identify_complete (dev, error);
|
fpi_device_identify_complete (dev, g_steal_pointer (&error));
|
||||||
|
|
||||||
self->task_ssm = NULL;
|
self->task_ssm = NULL;
|
||||||
}
|
}
|
||||||
@@ -1448,10 +1466,7 @@ fpc_clear_ssm_done (FpiSsm *ssm, FpDevice *dev, GError *error)
|
|||||||
|
|
||||||
fp_info ("Clear Storage complete!");
|
fp_info ("Clear Storage complete!");
|
||||||
|
|
||||||
if (fpi_ssm_get_error (ssm))
|
fpi_device_clear_storage_complete (dev, g_steal_pointer (&error));
|
||||||
error = fpi_ssm_get_error (ssm);
|
|
||||||
|
|
||||||
fpi_device_clear_storage_complete (dev, error);
|
|
||||||
self->task_ssm = NULL;
|
self->task_ssm = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1555,10 +1570,7 @@ fpc_init_ssm_done (FpiSsm *ssm, FpDevice *dev, GError *error)
|
|||||||
{
|
{
|
||||||
FpiDeviceFpcMoc *self = FPI_DEVICE_FPCMOC (dev);
|
FpiDeviceFpcMoc *self = FPI_DEVICE_FPCMOC (dev);
|
||||||
|
|
||||||
if (fpi_ssm_get_error (ssm))
|
fpi_device_open_complete (dev, g_steal_pointer (&error));
|
||||||
error = fpi_ssm_get_error (ssm);
|
|
||||||
|
|
||||||
fpi_device_open_complete (dev, error);
|
|
||||||
self->task_ssm = NULL;
|
self->task_ssm = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1627,9 +1639,13 @@ fpc_dev_probe (FpDevice *device)
|
|||||||
{
|
{
|
||||||
case 0xFFE0:
|
case 0xFFE0:
|
||||||
case 0xA305:
|
case 0xA305:
|
||||||
|
case 0xA306:
|
||||||
case 0xD805:
|
case 0xD805:
|
||||||
case 0xDA04:
|
case 0xDA04:
|
||||||
case 0xD205:
|
case 0xD205:
|
||||||
|
case 0x9524:
|
||||||
|
case 0x9544:
|
||||||
|
case 0xC844:
|
||||||
self->max_enroll_stage = MAX_ENROLL_SAMPLES;
|
self->max_enroll_stage = MAX_ENROLL_SAMPLES;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|||||||
@@ -128,11 +128,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 +156,10 @@ fp_cmd_receive_cb (FpiUsbTransfer *transfer,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = gx_proto_parse_header (transfer->buffer, transfer->actual_length, &header);
|
reader.data = transfer->buffer;
|
||||||
if (ret != 0)
|
reader.size = transfer->actual_length;
|
||||||
|
|
||||||
|
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,17 @@ fp_cmd_receive_cb (FpiUsbTransfer *transfer,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!fpi_byte_reader_set_pos (&reader, PACKAGE_HEADER_SIZE + header.len))
|
||||||
|
{
|
||||||
|
fpi_ssm_mark_failed (transfer->ssm,
|
||||||
|
fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
|
||||||
|
"Package crc read failed"));
|
||||||
|
}
|
||||||
|
|
||||||
gx_proto_crc32_calc (transfer->buffer, PACKAGE_HEADER_SIZE + header.len, (uint8_t *) &crc32_calc);
|
gx_proto_crc32_calc (transfer->buffer, PACKAGE_HEADER_SIZE + header.len, (uint8_t *) &crc32_calc);
|
||||||
if(crc32_calc != GUINT32_FROM_LE (*(uint32_t *) (transfer->buffer + PACKAGE_HEADER_SIZE + header.len)))
|
|
||||||
|
if (!fpi_byte_reader_get_uint32_le (&reader, &crc32) ||
|
||||||
|
crc32_calc != crc32)
|
||||||
{
|
{
|
||||||
fpi_ssm_mark_failed (transfer->ssm,
|
fpi_ssm_mark_failed (transfer->ssm,
|
||||||
fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
|
fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
|
||||||
@@ -174,8 +187,11 @@ 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_set_pos (&reader, 0);
|
||||||
if (ret != 0)
|
reader.data = &transfer->buffer[PACKAGE_HEADER_SIZE];
|
||||||
|
reader.size = header.len;
|
||||||
|
|
||||||
|
if (gx_proto_parse_body (cmd, &reader, &cmd_reponse) != 0)
|
||||||
{
|
{
|
||||||
fpi_ssm_mark_failed (transfer->ssm,
|
fpi_ssm_mark_failed (transfer->ssm,
|
||||||
fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
|
fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
|
||||||
@@ -631,20 +647,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);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -837,16 +853,6 @@ fp_enroll_sm_run_state (FpiSsm *ssm, FpDevice *device)
|
|||||||
|
|
||||||
switch (fpi_ssm_get_cur_state (ssm))
|
switch (fpi_ssm_get_cur_state (ssm))
|
||||||
{
|
{
|
||||||
case FP_ENROLL_ENUM:
|
|
||||||
{
|
|
||||||
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:
|
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,
|
||||||
@@ -857,13 +863,23 @@ fp_enroll_sm_run_state (FpiSsm *ssm, FpDevice *device)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case FP_ENROLL_ENUM:
|
||||||
|
{
|
||||||
|
goodix_sensor_cmd (self, MOC_CMD0_GETFINGERLIST, MOC_CMD1_DEFAULT,
|
||||||
|
false,
|
||||||
|
(const guint8 *) &dummy,
|
||||||
|
1,
|
||||||
|
fp_enroll_enum_cb);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case FP_ENROLL_CREATE:
|
case FP_ENROLL_CREATE:
|
||||||
{
|
{
|
||||||
goodix_sensor_cmd (self, MOC_CMD0_ENROLL_INIT, MOC_CMD1_DEFAULT,
|
goodix_sensor_cmd (self, MOC_CMD0_ENROLL_INIT, MOC_CMD1_DEFAULT,
|
||||||
false,
|
false,
|
||||||
(const guint8 *) &dummy,
|
(const guint8 *) &dummy,
|
||||||
1,
|
1,
|
||||||
fp_enroll_init_cb);
|
fp_enroll_create_cb);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -1359,16 +1375,26 @@ gx_fp_probe (FpDevice *device)
|
|||||||
{
|
{
|
||||||
case 0x6496:
|
case 0x6496:
|
||||||
case 0x60A2:
|
case 0x60A2:
|
||||||
|
case 0x60A4:
|
||||||
case 0x6014:
|
case 0x6014:
|
||||||
|
case 0x6092:
|
||||||
case 0x6094:
|
case 0x6094:
|
||||||
|
case 0x609A:
|
||||||
case 0x609C:
|
case 0x609C:
|
||||||
|
case 0x60BC:
|
||||||
|
case 0x60C2:
|
||||||
|
case 0x6304:
|
||||||
case 0x631C:
|
case 0x631C:
|
||||||
|
case 0x633C:
|
||||||
case 0x634C:
|
case 0x634C:
|
||||||
case 0x6384:
|
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 0x659A:
|
||||||
self->max_enroll_stage = 12;
|
self->max_enroll_stage = 12;
|
||||||
@@ -1457,9 +1483,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);
|
||||||
@@ -1602,10 +1626,17 @@ 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 = 0x6014, },
|
||||||
|
{ .vid = 0x27c6, .pid = 0x6092, },
|
||||||
{ .vid = 0x27c6, .pid = 0x6094, },
|
{ .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 = 0x631C, },
|
||||||
|
{ .vid = 0x27c6, .pid = 0x633C, },
|
||||||
{ .vid = 0x27c6, .pid = 0x634C, },
|
{ .vid = 0x27c6, .pid = 0x634C, },
|
||||||
{ .vid = 0x27c6, .pid = 0x6384, },
|
{ .vid = 0x27c6, .pid = 0x6384, },
|
||||||
{ .vid = 0x27c6, .pid = 0x639C, },
|
{ .vid = 0x27c6, .pid = 0x639C, },
|
||||||
@@ -1613,6 +1644,9 @@ static const FpIdEntry id_table[] = {
|
|||||||
{ .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, },
|
||||||
@@ -1620,6 +1654,8 @@ static const FpIdEntry id_table[] = {
|
|||||||
{ .vid = 0x27c6, .pid = 0x659A, },
|
{ .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 = 0x689A, },
|
||||||
{ .vid = 0, .pid = 0, .driver_data = 0 }, /* terminating entry */
|
{ .vid = 0, .pid = 0, .driver_data = 0 }, /* terminating entry */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -44,7 +44,6 @@ typedef enum {
|
|||||||
typedef enum {
|
typedef enum {
|
||||||
FP_ENROLL_PWR_BTN_SHIELD_ON = 0,
|
FP_ENROLL_PWR_BTN_SHIELD_ON = 0,
|
||||||
FP_ENROLL_ENUM,
|
FP_ENROLL_ENUM,
|
||||||
FP_ENROLL_IDENTIFY,
|
|
||||||
FP_ENROLL_CREATE,
|
FP_ENROLL_CREATE,
|
||||||
FP_ENROLL_CAPTURE,
|
FP_ENROLL_CAPTURE,
|
||||||
FP_ENROLL_UPDATE,
|
FP_ENROLL_UPDATE,
|
||||||
|
|||||||
@@ -18,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,108 @@ 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))
|
||||||
|
g_return_val_if_reached (-1);
|
||||||
|
|
||||||
|
if (!fpi_byte_reader_get_uint8 (reader, &pheader->packagenum))
|
||||||
|
g_return_val_if_reached (-1);
|
||||||
|
|
||||||
|
if (!fpi_byte_reader_get_uint8 (reader, &pheader->reserved))
|
||||||
|
g_return_val_if_reached (-1);
|
||||||
|
|
||||||
|
if (!fpi_byte_reader_get_uint16_le (reader, &pheader->len))
|
||||||
|
g_return_val_if_reached (-1);
|
||||||
|
|
||||||
|
if (!fpi_byte_reader_get_uint8 (reader, &pheader->crc8))
|
||||||
|
g_return_val_if_reached (-1);
|
||||||
|
|
||||||
|
if (!fpi_byte_reader_get_uint8 (reader, &pheader->rev_crc8))
|
||||||
|
g_return_val_if_reached (-1);
|
||||||
|
|
||||||
pheader->len -= PACKAGE_CRC_SIZE;
|
pheader->len -= PACKAGE_CRC_SIZE;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
gx_proto_parse_fingerid (
|
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;
|
const uint8_t *buffer;
|
||||||
|
|
||||||
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);
|
||||||
|
|
||||||
template->type = buffer[Offset++];
|
if (!fpi_byte_reader_skip (reader, 1))
|
||||||
template->finger_index = buffer[Offset++];
|
g_return_val_if_reached (-1);
|
||||||
Offset++;
|
|
||||||
memcpy (template->accountid, &buffer[Offset], sizeof (template->accountid));
|
if (!fpi_byte_reader_get_data (reader, sizeof (template->accountid), &buffer))
|
||||||
Offset += sizeof (template->accountid);
|
g_return_val_if_reached (-1);
|
||||||
memcpy (template->tid, &buffer[Offset], sizeof (template->tid));
|
|
||||||
Offset += sizeof (template->tid); // Offset == 68
|
memcpy (template->accountid, buffer, sizeof (template->accountid));
|
||||||
template->payload.size = buffer[Offset++];
|
|
||||||
if (template->payload.size > sizeof (template->payload.data))
|
if (!fpi_byte_reader_get_data (reader, sizeof (template->tid), &buffer))
|
||||||
return -1;
|
g_return_val_if_reached (-1);
|
||||||
if (template->payload.size + Offset > fid_buffer_size)
|
|
||||||
return -1;
|
memcpy (template->tid, buffer, sizeof (template->tid));
|
||||||
memset (template->payload.data, 0, template->payload.size);
|
|
||||||
memcpy (template->payload.data, &buffer[Offset], template->payload.size);
|
if (!fpi_byte_reader_get_uint8 (reader, &template->payload.size))
|
||||||
|
g_return_val_if_reached (-1);
|
||||||
|
|
||||||
|
if (!fpi_byte_reader_get_data (reader, template->payload.size, &buffer))
|
||||||
|
g_return_val_if_reached (-1);
|
||||||
|
|
||||||
|
memcpy (template->payload.data, buffer, template->payload.size);
|
||||||
|
|
||||||
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 +338,99 @@ 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);
|
||||||
|
|
||||||
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 +439,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 +475,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:
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
1384
libfprint/drivers/realtek/realtek.c
Normal file
1384
libfprint/drivers/realtek/realtek.c
Normal file
File diff suppressed because it is too large
Load Diff
246
libfprint/drivers/realtek/realtek.h
Normal file
246
libfprint/drivers/realtek/realtek.h
Normal file
@@ -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},
|
||||||
|
};
|
||||||
@@ -256,7 +256,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;
|
||||||
|
|
||||||
|
|||||||
@@ -32,19 +32,32 @@ 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 = 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 = 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 = 0x0104, },
|
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0168, },
|
||||||
|
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x016C, },
|
||||||
|
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0173, },
|
||||||
|
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0174, },
|
||||||
|
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x019D, },
|
||||||
|
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x019F, },
|
||||||
{ .vid = 0, .pid = 0, .driver_data = 0 }, /* terminating entry */
|
{ .vid = 0, .pid = 0, .driver_data = 0 }, /* terminating entry */
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -106,7 +119,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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -641,18 +658,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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -702,19 +722,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
|
||||||
{
|
{
|
||||||
@@ -750,7 +769,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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1238,6 +1257,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;
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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,
|
||||||
@@ -180,6 +178,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 +246,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 +282,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 +306,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;
|
||||||
@@ -307,13 +331,13 @@ capture_read_data_cb (FpiUsbTransfer *transfer, FpDevice *device,
|
|||||||
self->image_size +=
|
self->image_size +=
|
||||||
upektc_img_process_image_frame (self->image_bits + self->image_size,
|
upektc_img_process_image_frame (self->image_bits + self->image_size,
|
||||||
data);
|
data);
|
||||||
BUG_ON (self->image_size != IMAGE_SIZE);
|
BUG_ON (self->image_size != self->expected_image_size);
|
||||||
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 +370,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;
|
||||||
|
|
||||||
@@ -513,15 +541,81 @@ 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;
|
||||||
|
self->image_bits = g_malloc0 (self->expected_image_size * 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
fpi_ssm_next_state (transfer->ssm);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -616,7 +710,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 +720,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 +779,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,
|
||||||
@@ -1243,7 +1244,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 +1296,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 +1342,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 +1351,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 +1447,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
@@ -703,9 +738,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);
|
||||||
@@ -1270,8 +1305,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);
|
||||||
@@ -1343,20 +1376,6 @@ 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);
|
||||||
@@ -1369,35 +1388,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);
|
||||||
}
|
}
|
||||||
@@ -1408,14 +1409,7 @@ 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);
|
|
||||||
|
|
||||||
NSS_Shutdown ();
|
|
||||||
|
|
||||||
g_usb_device_release_interface (fpi_device_get_usb_device (FP_DEVICE (dev)),
|
g_usb_device_release_interface (fpi_device_get_usb_device (FP_DEVICE (dev)),
|
||||||
self->interface, 0, &error);
|
self->interface, 0, &error);
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -733,7 +733,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 +772,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 +788,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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
331
libfprint/drivers/virtual-sdcp.c
Normal file
331
libfprint/drivers/virtual-sdcp.c
Normal file
@@ -0,0 +1,331 @@
|
|||||||
|
/*
|
||||||
|
* Virtual driver for SDCP device debugging
|
||||||
|
*
|
||||||
|
* Copyright (C) 2025 Joshua Grisham <josh@joshuagrisham.com>
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is a virtual driver to debug the SDCP-based drivers.
|
||||||
|
* This virtual driver does not use a socket listener but instead
|
||||||
|
* embeds the simulated logic of the fake "device" directly within
|
||||||
|
* the logic of each function. This driver also allows prints to be
|
||||||
|
* registered programmatically, making it possible to test libfprint
|
||||||
|
* and fprintd.
|
||||||
|
*
|
||||||
|
* This virtual driver will override FpSdcpDevice's dynamically
|
||||||
|
* generated cryptography values and instead replace them with
|
||||||
|
* pre-generated values taken from from Microsoft's sample client
|
||||||
|
* implementation. See:
|
||||||
|
* https://github.com/Microsoft/SecureDeviceConnectionProtocol
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define FP_COMPONENT "virtual_sdcp"
|
||||||
|
#include "fpi-log.h"
|
||||||
|
|
||||||
|
#include "../fpi-sdcp.h"
|
||||||
|
#include "virtual-sdcp.h"
|
||||||
|
|
||||||
|
struct _FpDeviceVirtualSdcp
|
||||||
|
{
|
||||||
|
FpSdcpDevice parent;
|
||||||
|
|
||||||
|
GPtrArray *print_ids;
|
||||||
|
};
|
||||||
|
|
||||||
|
G_DECLARE_FINAL_TYPE (FpDeviceVirtualSdcp, fpi_device_virtual_sdcp, FPI, DEVICE_VIRTUAL_SDCP, FpSdcpDevice)
|
||||||
|
G_DEFINE_TYPE (FpDeviceVirtualSdcp, fpi_device_virtual_sdcp, FP_TYPE_SDCP_DEVICE)
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
static const guint8 from_hex_map[] = {
|
||||||
|
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, // 01234567
|
||||||
|
0x08, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 89:;<=>?
|
||||||
|
0x00, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, // @abcdef
|
||||||
|
};
|
||||||
|
|
||||||
|
static GBytes *
|
||||||
|
g_bytes_from_hex (const gchar *hex)
|
||||||
|
{
|
||||||
|
g_autoptr(GBytes) res = NULL;
|
||||||
|
guint8 b0, b1;
|
||||||
|
gsize bytes_len = strlen (hex) / 2;
|
||||||
|
guint8 *bytes = g_malloc0 (bytes_len);
|
||||||
|
|
||||||
|
for (int i = 0; i < strlen (hex) - 1; i += 2)
|
||||||
|
{
|
||||||
|
b0 = ((guint8) hex[i + 0] & 0x1F) ^ 0x10;
|
||||||
|
b1 = ((guint8) hex[i + 1] & 0x1F) ^ 0x10;
|
||||||
|
bytes[i / 2] = (guint8) (from_hex_map[b0] << 4) | from_hex_map[b1];
|
||||||
|
}
|
||||||
|
|
||||||
|
res = g_bytes_new_take (bytes, bytes_len);
|
||||||
|
|
||||||
|
return g_steal_pointer (&res);
|
||||||
|
}
|
||||||
|
|
||||||
|
static FpiSdcpClaim *
|
||||||
|
get_fake_sdcp_claim (void)
|
||||||
|
{
|
||||||
|
FpiSdcpClaim *claim = g_new0 (FpiSdcpClaim, 1);
|
||||||
|
|
||||||
|
claim->model_certificate = g_bytes_from_hex (model_certificate_hex);
|
||||||
|
claim->device_public_key = g_bytes_from_hex (device_public_key_hex);
|
||||||
|
claim->firmware_public_key = g_bytes_from_hex (firmware_public_key_hex);
|
||||||
|
claim->firmware_hash = g_bytes_from_hex (firmware_hash_hex);
|
||||||
|
claim->model_signature = g_bytes_from_hex (model_signature_hex);
|
||||||
|
claim->device_signature = g_bytes_from_hex (device_signature_hex);
|
||||||
|
return g_steal_pointer (&claim);
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
static void
|
||||||
|
dev_identify (FpSdcpDevice *sdcp_device)
|
||||||
|
{
|
||||||
|
fp_dbg ("Virtual SDCP device: %s()", G_STRFUNC);
|
||||||
|
FpDeviceVirtualSdcp *self = FPI_DEVICE_VIRTUAL_SDCP (sdcp_device);
|
||||||
|
g_autoptr(GBytes) enrollment_id = NULL;
|
||||||
|
g_autoptr(GBytes) identify_mac = NULL;
|
||||||
|
GBytes *identify_nonce = NULL;
|
||||||
|
|
||||||
|
if (self->print_ids->len > 0)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Pretend that the virtual device identified the first print.
|
||||||
|
* Since we used a pre-generated enrollment_id for it, we can also use the
|
||||||
|
* matching pre-generated test identify data for its identification.
|
||||||
|
*/
|
||||||
|
identify_nonce = g_bytes_from_hex (identify_nonce_hex);
|
||||||
|
enrollment_id = g_bytes_from_hex (enrollment_id_hex);
|
||||||
|
fpi_sdcp_device_set_identify_data (sdcp_device, identify_nonce);
|
||||||
|
identify_mac = g_bytes_from_hex (identify_mac_hex);
|
||||||
|
|
||||||
|
fpi_sdcp_device_identify_complete (sdcp_device, enrollment_id, identify_mac, NULL);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fpi_sdcp_device_identify_complete (sdcp_device, NULL, NULL,
|
||||||
|
fpi_device_error_new (FP_DEVICE_ERROR_DATA_NOT_FOUND));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
dev_enroll_commit (FpSdcpDevice *sdcp_device, GBytes *id)
|
||||||
|
{
|
||||||
|
fp_dbg ("Virtual SDCP device: %s()", G_STRFUNC);
|
||||||
|
FpDeviceVirtualSdcp *self = FPI_DEVICE_VIRTUAL_SDCP (sdcp_device);
|
||||||
|
g_autoptr(GBytes) expected_first_print_id = NULL;
|
||||||
|
GBytes *print_id;
|
||||||
|
|
||||||
|
print_id = g_bytes_new (g_bytes_get_data (id, NULL), g_bytes_get_size (id));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If this is the first print, it is probably good if we make sure the
|
||||||
|
* internal API assigned it the expected pre-known ID
|
||||||
|
*/
|
||||||
|
if (self->print_ids->len == 0)
|
||||||
|
{
|
||||||
|
expected_first_print_id = g_bytes_from_hex (enrollment_id_hex);
|
||||||
|
if (!g_bytes_equal (print_id, expected_first_print_id))
|
||||||
|
{
|
||||||
|
fpi_sdcp_device_enroll_commit_complete (sdcp_device,
|
||||||
|
fpi_device_error_new_msg (FP_DEVICE_ERROR_UNTRUSTED,
|
||||||
|
"First enrolled print ID does not match expected value"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
g_ptr_array_add (self->print_ids, g_steal_pointer (&print_id));
|
||||||
|
|
||||||
|
fpi_sdcp_device_enroll_commit_complete (sdcp_device, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
dev_enroll (FpSdcpDevice *sdcp_device)
|
||||||
|
{
|
||||||
|
fp_dbg ("Virtual SDCP device: %s()", G_STRFUNC);
|
||||||
|
FpDeviceVirtualSdcp *self = FPI_DEVICE_VIRTUAL_SDCP (sdcp_device);
|
||||||
|
FpDevice *device = FP_DEVICE (sdcp_device);
|
||||||
|
g_autoptr(GError) error = NULL;
|
||||||
|
g_autoptr(GBytes) nonce = NULL;
|
||||||
|
FpPrint *print;
|
||||||
|
|
||||||
|
fpi_device_get_enroll_data (device, &print);
|
||||||
|
|
||||||
|
if (self->print_ids->len == 0)
|
||||||
|
{
|
||||||
|
/* Use the hard-coded nonce for the first enrollment */
|
||||||
|
nonce = g_bytes_from_hex (enrollment_nonce_hex);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Generate a new nonce for all other enrollments */
|
||||||
|
nonce = fpi_sdcp_generate_random (&error);
|
||||||
|
if (error)
|
||||||
|
fpi_device_enroll_progress (device, 0, print, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
fpi_device_enroll_progress (device, 1, print, NULL);
|
||||||
|
fpi_sdcp_device_enroll_commit (sdcp_device, nonce, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
dev_list (FpSdcpDevice *sdcp_device)
|
||||||
|
{
|
||||||
|
fp_dbg ("Virtual SDCP device: %s()", G_STRFUNC);
|
||||||
|
FpDeviceVirtualSdcp *self = FPI_DEVICE_VIRTUAL_SDCP (sdcp_device);
|
||||||
|
GPtrArray *print_ids = g_ptr_array_new_with_free_func ((GDestroyNotify) g_bytes_unref);
|
||||||
|
|
||||||
|
for (gint i = 0; i < self->print_ids->len; i++)
|
||||||
|
{
|
||||||
|
GBytes *print_id = g_ptr_array_index (self->print_ids, i);
|
||||||
|
fp_dbg ("print %d:", i);
|
||||||
|
fp_dbg_hex_dump_gbytes (print_id);
|
||||||
|
g_ptr_array_add (print_ids, g_bytes_new (g_bytes_get_data (print_id, NULL),
|
||||||
|
g_bytes_get_size (print_id)));
|
||||||
|
}
|
||||||
|
|
||||||
|
fpi_sdcp_device_list_complete (sdcp_device, g_steal_pointer (&print_ids), NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
dev_reconnect (FpSdcpDevice *sdcp_device)
|
||||||
|
{
|
||||||
|
fp_dbg ("Virtual SDCP device: %s()", G_STRFUNC);
|
||||||
|
g_autoptr(GError) error = NULL;
|
||||||
|
g_autoptr(GBytes) random = NULL;
|
||||||
|
g_autoptr(GBytes) reconnect_mac = g_bytes_from_hex (reconnect_mac_hex);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Normally, a driver would fetch the reconnect data and then send it to the
|
||||||
|
* device's Reconnect command. In this fake device, we will just fetch and
|
||||||
|
* verify the random was generated but do nothing with it
|
||||||
|
*/
|
||||||
|
|
||||||
|
fpi_sdcp_device_get_reconnect_data (sdcp_device, &random);
|
||||||
|
|
||||||
|
g_assert (random);
|
||||||
|
g_assert (g_bytes_get_size (random) == SDCP_RANDOM_SIZE);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* In emulation mode (FP_DEVICE_EMULATION=1), a different hard-coded random is
|
||||||
|
* set in fpi-sdcp-device, which was the same random used to generate the
|
||||||
|
* reconnect_mac value provided here
|
||||||
|
*/
|
||||||
|
|
||||||
|
fpi_sdcp_device_reconnect_complete (sdcp_device, reconnect_mac, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
dev_connect (FpSdcpDevice *sdcp_device)
|
||||||
|
{
|
||||||
|
fp_dbg ("Virtual SDCP device: %s()", G_STRFUNC);
|
||||||
|
g_autoptr(GError) error = NULL;
|
||||||
|
g_autoptr(GBytes) host_random = NULL;
|
||||||
|
g_autoptr(GBytes) host_public_key = NULL;
|
||||||
|
g_autoptr(GBytes) device_random = g_bytes_from_hex (device_random_hex);
|
||||||
|
g_autoptr(GBytes) connect_mac = g_bytes_from_hex (connect_mac_hex);
|
||||||
|
g_autoptr(FpiSdcpClaim) claim = get_fake_sdcp_claim ();
|
||||||
|
|
||||||
|
fpi_sdcp_device_get_connect_data (sdcp_device, &host_random, &host_public_key);
|
||||||
|
|
||||||
|
g_assert (host_random);
|
||||||
|
g_assert (g_bytes_get_size (host_random) == SDCP_RANDOM_SIZE);
|
||||||
|
|
||||||
|
g_assert (host_public_key);
|
||||||
|
g_assert (g_bytes_get_size (host_public_key) == SDCP_PUBLIC_KEY_SIZE);
|
||||||
|
|
||||||
|
fpi_sdcp_device_connect_complete (sdcp_device, device_random, claim, connect_mac, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
dev_close (FpDevice *device)
|
||||||
|
{
|
||||||
|
fp_dbg ("Virtual SDCP device: %s()", G_STRFUNC);
|
||||||
|
fpi_device_close_complete (device, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
dev_open (FpSdcpDevice *sdcp_device)
|
||||||
|
{
|
||||||
|
fp_dbg ("Virtual SDCP device: %s()", G_STRFUNC);
|
||||||
|
fpi_sdcp_device_open_complete (sdcp_device, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
fpi_device_virtual_sdcp_finalize (GObject *object)
|
||||||
|
{
|
||||||
|
fp_dbg ("Virtual SDCP device: %s()", G_STRFUNC);
|
||||||
|
FpDeviceVirtualSdcp *self = FPI_DEVICE_VIRTUAL_SDCP (object);
|
||||||
|
|
||||||
|
g_clear_pointer (&self->print_ids, g_ptr_array_unref);
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (fpi_device_virtual_sdcp_parent_class)->finalize (object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
fpi_device_virtual_sdcp_init (FpDeviceVirtualSdcp *self)
|
||||||
|
{
|
||||||
|
fp_dbg ("Virtual SDCP device: %s()", G_STRFUNC);
|
||||||
|
|
||||||
|
/* Force FP_DEVICE_EMULATION=1 when using FpDeviceVirtualSdcp */
|
||||||
|
g_setenv ("FP_DEVICE_EMULATION", "1", TRUE);
|
||||||
|
|
||||||
|
self->print_ids = g_ptr_array_new_with_free_func ((GDestroyNotify) g_bytes_unref);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const FpIdEntry driver_ids[] = {
|
||||||
|
{ .virtual_envvar = "FP_VIRTUAL_SDCP" },
|
||||||
|
{ .virtual_envvar = NULL }
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
fpi_device_virtual_sdcp_class_init (FpDeviceVirtualSdcpClass *klass)
|
||||||
|
{
|
||||||
|
fp_dbg ("Virtual SDCP device: %s()", G_STRFUNC);
|
||||||
|
FpDeviceClass *dev_class = FP_DEVICE_CLASS (klass);
|
||||||
|
FpSdcpDeviceClass *sdcp_dev_class = FP_SDCP_DEVICE_CLASS (klass);
|
||||||
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||||
|
|
||||||
|
object_class->finalize = fpi_device_virtual_sdcp_finalize;
|
||||||
|
|
||||||
|
dev_class->id = FP_COMPONENT;
|
||||||
|
dev_class->full_name = "Virtual SDCP device for debugging";
|
||||||
|
dev_class->type = FP_DEVICE_TYPE_VIRTUAL;
|
||||||
|
dev_class->id_table = driver_ids;
|
||||||
|
dev_class->nr_enroll_stages = 1;
|
||||||
|
dev_class->scan_type = FP_SCAN_TYPE_PRESS;
|
||||||
|
|
||||||
|
sdcp_dev_class->ignore_device_certificate = FALSE;
|
||||||
|
sdcp_dev_class->ignore_device_signatures = FALSE;
|
||||||
|
|
||||||
|
sdcp_dev_class->open = dev_open;
|
||||||
|
sdcp_dev_class->connect = dev_connect;
|
||||||
|
|
||||||
|
if (!g_getenv ("FP_VIRTUAL_SDCP_NO_RECONNECT"))
|
||||||
|
sdcp_dev_class->reconnect = dev_reconnect;
|
||||||
|
|
||||||
|
sdcp_dev_class->list = dev_list;
|
||||||
|
sdcp_dev_class->enroll = dev_enroll;
|
||||||
|
sdcp_dev_class->enroll_commit = dev_enroll_commit;
|
||||||
|
sdcp_dev_class->identify = dev_identify;
|
||||||
|
|
||||||
|
dev_class->close = dev_close;
|
||||||
|
|
||||||
|
fpi_device_class_auto_initialize_features (dev_class);
|
||||||
|
dev_class->features |= FP_DEVICE_FEATURE_STORAGE;
|
||||||
|
}
|
||||||
92
libfprint/drivers/virtual-sdcp.h
Normal file
92
libfprint/drivers/virtual-sdcp.h
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
/*
|
||||||
|
* Virtual driver test payloads for SDCP device debugging
|
||||||
|
*
|
||||||
|
* Copyright (C) 2025 Joshua Grisham <josh@joshuagrisham.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-compat.h"
|
||||||
|
|
||||||
|
/* host keys */
|
||||||
|
|
||||||
|
static const gchar host_private_key_hex[] = "8400ed14579cdf11586477e836e8cb52708441c1c2a447c218c5bbc2d118fbc7";
|
||||||
|
static const gchar host_public_key_hex[] = "0452f056ffb9c6728654771a3629b770767b19a2106a4916fb81ba06ef6797c4"
|
||||||
|
"a3df672ade0e9116d1abe278a8223abde4958d62d4ff6882159f0617c6f8ce10"
|
||||||
|
"bf";
|
||||||
|
static const gchar host_random_hex[] = "d877403abe82f4d97e1448c5052d83a532a45e56ef049cbbf981137520e713bf";
|
||||||
|
|
||||||
|
/* device keys */
|
||||||
|
|
||||||
|
static const gchar device_random_hex[] = "6e2f6c1abef2a1973fb1315a17e209fdb0c78520f1fd6a85d294d7aeb40a04a7";
|
||||||
|
static const gchar model_certificate_hex[] = "30820323308202caa00302010202133300000004c45d661d6eed040d00000000"
|
||||||
|
"0004300a06082a8648ce3d0403023056310b3009060355040613025553311e30"
|
||||||
|
"1c060355040a13154d6963726f736f667420436f72706f726174696f6e312730"
|
||||||
|
"250603550403131e57696e646f77732048656c6c6f2032303936414443432043"
|
||||||
|
"412032303231301e170d3232303130343231303033355a170d32333034303432"
|
||||||
|
"31303033355a301c311a3018060355040313115365637572652042494f205365"
|
||||||
|
"6e736f723059301306072a8648ce3d020106082a8648ce3d0301070342000414"
|
||||||
|
"cfc287f872a2b7d3339e0b31390e3ca688e61165eaa6687c959270e07666b1fa"
|
||||||
|
"19e3efaf1750d134a886d494424fe471970c4b06838408a18d1f5d57735dd7a3"
|
||||||
|
"8201af308201ab30750603551d11046e306ca46a30683132303006082b060104"
|
||||||
|
"82376402132436423045413344382d383339372d343444332d383043392d3930"
|
||||||
|
"324130414346344343303132303006082b060104823764011324413944423730"
|
||||||
|
"32362d433646462d344341462d423134382d393133454641333730423933301d"
|
||||||
|
"0603551d0e04160414db6d66d642b7236d5e6bb2ec2186decda98067b6301f06"
|
||||||
|
"03551d23041830168014bf3748e34a632de953a3ba890298c069472a99b9305f"
|
||||||
|
"0603551d1f045830563054a052a050864e687474703a2f2f7777772e6d696372"
|
||||||
|
"6f736f66742e636f6d2f706b696f70732f63726c2f57696e646f777325323048"
|
||||||
|
"656c6c6f25323032303936414443432532304341253230323032312e63726c30"
|
||||||
|
"6c06082b060105050701010460305e305c06082b060105050730028650687474"
|
||||||
|
"703a2f2f7777772e6d6963726f736f66742e636f6d2f706b696f70732f636572"
|
||||||
|
"74732f57696e646f777325323048656c6c6f2532303230393641444343253230"
|
||||||
|
"4341253230323032312e637274300c0603551d130101ff040230003015060355"
|
||||||
|
"1d25040e300c060a2b0601040182374c2b01300a06082a8648ce3d0403020347"
|
||||||
|
"003044022077553ef520f732e03cd740c8cf807e6366e12918bc581f75bfe0f1"
|
||||||
|
"95b7b1fd4f0220324e25b93b9da7538b797a624272b21b7cc0e96ea487924250"
|
||||||
|
"4677600450f283";
|
||||||
|
static const gchar device_public_key_hex[] = "04e2787890a684f95b96b9a2316ca8d3d33d4d79ff4c89dc6f9e888e973990d1"
|
||||||
|
"d3154133dcc8bd33b99af9dbf0673390d404d092498a3f214cd93f9b9f28fb5f"
|
||||||
|
"66";
|
||||||
|
static const gchar firmware_public_key_hex[] = "04f06a84ab51a3a6e8ff46868f91dd720e4cdad21f2e090d11e8f9bfc2ea19ee"
|
||||||
|
"1b5eac850b4532968a9399f76cd779e7723e8c2ca73b597c0df5f73b94a36f2b"
|
||||||
|
"6c";
|
||||||
|
static const gchar firmware_hash_hex[] = "c3bf47ea1f4a4a605470313cacb3a44f4a461f68c6faeab07e737610cb5ac835";
|
||||||
|
static const gchar model_signature_hex[] = "febe6ba3107813e185f05189e69ae79d9f7a40802582d94324459844c8b97ec6"
|
||||||
|
"c5daed5462276cb8a193c33e350424b0305d63d79a93a9188dcfc0cb5595f6c1";
|
||||||
|
static const gchar device_signature_hex[] = "10cc57dd8dafb463510a7327a5fca49b698e999b36448e2023eaf0dff0b0d4a3"
|
||||||
|
"4f1caf4e872b77364a0a00d7476554d0324c4cc931937e232a0315837d696c06";
|
||||||
|
static const gchar connect_mac_hex[] = "422bc475a78f972bae842a28e5ad721207457fcbd9a1a3aaf71587c07b84d247";
|
||||||
|
|
||||||
|
/* expected application_secret based on above */
|
||||||
|
|
||||||
|
static const gchar application_secret_hex[] = "13330ba3135ecf5dc71cede01a886540771efab35c8ba053902b2c1ee7de6efe";
|
||||||
|
|
||||||
|
/* test verify_reconnect values */
|
||||||
|
|
||||||
|
static const gchar reconnect_random_hex[] = "8a7451c1d3a8dca1c1330ca50d73454b351a49f46c8e9dcee15c964d295c31c9";
|
||||||
|
static const gchar reconnect_mac_hex[] = "bf3f3bb3bd6ecb2784c160f526f7bc3b3ca8faf5557194c48e0024a0493903c7";
|
||||||
|
|
||||||
|
/* test enrollment_id values */
|
||||||
|
|
||||||
|
static const gchar enrollment_nonce_hex[] = "c2101c44c9a667bba397e81f48b143398603e2c9335a68b409e1dbe71e005ca2";
|
||||||
|
static const gchar enrollment_id_hex[] = "67109dc70a216331f1580ddac601915929c1ff6c9bcba6544ba572c660c3d91e";
|
||||||
|
|
||||||
|
/* test verify_identify values */
|
||||||
|
|
||||||
|
static const gchar identify_nonce_hex[] = "3a1b506f5bec089059acefb9b44dfbdea7a599ee9aa267e5252664d60b798053";
|
||||||
|
static const gchar identify_mac_hex[] = "53a723eef40713094a90c5ef9996cbd6ba268e30676cd7107705a6c3e3e1eff9";
|
||||||
@@ -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
|
||||||
@@ -364,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);
|
||||||
|
|||||||
@@ -292,14 +292,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;
|
||||||
@@ -1088,14 +1088,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
|
||||||
@@ -1217,13 +1226,30 @@ 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);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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
|
||||||
@@ -1348,8 +1374,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
|
||||||
@@ -1917,8 +1943,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
|
||||||
@@ -1957,8 +1983,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;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -140,6 +143,7 @@ typedef enum {
|
|||||||
* @FP_DEVICE_ERROR_DATA_DUPLICATE: Enrolling template duplicates storaged templates
|
* @FP_DEVICE_ERROR_DATA_DUPLICATE: Enrolling template duplicates storaged templates
|
||||||
* @FP_DEVICE_ERROR_REMOVED: The device has been removed.
|
* @FP_DEVICE_ERROR_REMOVED: The device has been removed.
|
||||||
* @FP_DEVICE_ERROR_TOO_HOT: The device might be getting too hot
|
* @FP_DEVICE_ERROR_TOO_HOT: The device might be getting too hot
|
||||||
|
* @FP_DEVICE_ERROR_UNTRUSTED: Device cannot be trusted
|
||||||
*
|
*
|
||||||
* Error codes for device operations. More specific errors from other domains
|
* Error codes for device operations. More specific errors from other domains
|
||||||
* such as #G_IO_ERROR or #G_USB_DEVICE_ERROR may also be reported.
|
* such as #G_IO_ERROR or #G_USB_DEVICE_ERROR may also be reported.
|
||||||
@@ -158,6 +162,7 @@ typedef enum {
|
|||||||
/* Leave some room to add more DATA related errors */
|
/* Leave some room to add more DATA related errors */
|
||||||
FP_DEVICE_ERROR_REMOVED = 0x100,
|
FP_DEVICE_ERROR_REMOVED = 0x100,
|
||||||
FP_DEVICE_ERROR_TOO_HOT,
|
FP_DEVICE_ERROR_TOO_HOT,
|
||||||
|
FP_DEVICE_ERROR_UNTRUSTED,
|
||||||
} FpDeviceError;
|
} FpDeviceError;
|
||||||
|
|
||||||
GQuark fp_device_retry_quark (void);
|
GQuark fp_device_retry_quark (void);
|
||||||
|
|||||||
@@ -24,6 +24,7 @@
|
|||||||
#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>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -159,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
|
||||||
@@ -265,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 = g_memdup2 (&g_lfsparms_V2, sizeof (LFSPARMS));
|
||||||
lfsparms->remove_perimeter_pts = data->flags & FPI_IMAGE_PARTIAL ? TRUE : FALSE;
|
lfsparms->remove_perimeter_pts = minutiae_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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -444,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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -476,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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -605,7 +605,7 @@ fp_print_equal (FpPrint *self, FpPrint *other)
|
|||||||
if (g_strcmp0 (self->device_id, other->device_id))
|
if (g_strcmp0 (self->device_id, other->device_id))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
if (self->type == FPI_PRINT_RAW)
|
if (self->type == FPI_PRINT_RAW || self->type == FPI_PRINT_SDCP)
|
||||||
{
|
{
|
||||||
return g_variant_equal (self->data, other->data);
|
return g_variant_equal (self->data, other->data);
|
||||||
}
|
}
|
||||||
@@ -721,13 +721,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 */
|
||||||
@@ -800,10 +799,11 @@ fp_print_deserialize (const guchar *data,
|
|||||||
if (!raw_value)
|
if (!raw_value)
|
||||||
goto invalid_format;
|
goto invalid_format;
|
||||||
|
|
||||||
if (G_BYTE_ORDER == G_BIG_ENDIAN)
|
#if (G_BYTE_ORDER == G_BIG_ENDIAN)
|
||||||
value = g_variant_byteswap (raw_value);
|
value = g_variant_byteswap (raw_value);
|
||||||
else
|
#else
|
||||||
value = g_variant_get_normal_form (raw_value);
|
value = g_variant_get_normal_form (raw_value);
|
||||||
|
#endif
|
||||||
|
|
||||||
g_variant_get (value,
|
g_variant_get (value,
|
||||||
"(i&s&sbymsmsi@a{sv}v)",
|
"(i&s&sbymsmsi@a{sv}v)",
|
||||||
@@ -870,7 +870,7 @@ fp_print_deserialize (const guchar *data,
|
|||||||
g_ptr_array_add (result->prints, g_steal_pointer (&xyt));
|
g_ptr_array_add (result->prints, g_steal_pointer (&xyt));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (type == FPI_PRINT_RAW)
|
else if (type == FPI_PRINT_RAW || type == FPI_PRINT_SDCP)
|
||||||
{
|
{
|
||||||
g_autoptr(GVariant) fp_data = g_variant_get_child_value (print_data, 0);
|
g_autoptr(GVariant) fp_data = g_variant_get_child_value (print_data, 0);
|
||||||
|
|
||||||
|
|||||||
46
libfprint/fp-sdcp-device-private.h
Normal file
46
libfprint/fp-sdcp-device-private.h
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
* FpSdcpDevice - A base class for SDCP enabled devices
|
||||||
|
* Copyright (C) 2020 Benjamin Berg <bberg@redhat.com>
|
||||||
|
* Copyright (C) 2025 Joshua Grisham <josh@joshuagrisham.com>
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "fpi-sdcp-device.h"
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
GBytes *host_private_key;
|
||||||
|
GBytes *host_public_key;
|
||||||
|
GBytes *host_random;
|
||||||
|
GBytes *reconnect_random;
|
||||||
|
GBytes *identify_nonce;
|
||||||
|
GBytes *data;
|
||||||
|
} FpSdcpDevicePrivate;
|
||||||
|
|
||||||
|
void fpi_sdcp_device_get_application_secret (FpSdcpDevice *self,
|
||||||
|
GBytes **application_secret);
|
||||||
|
void fpi_sdcp_device_set_application_secret (FpSdcpDevice *self,
|
||||||
|
GBytes *application_secret);
|
||||||
|
|
||||||
|
void fpi_sdcp_device_open (FpSdcpDevice *self);
|
||||||
|
void fpi_sdcp_device_connect (FpSdcpDevice *self);
|
||||||
|
void fpi_sdcp_device_reconnect (FpSdcpDevice *self);
|
||||||
|
|
||||||
|
void fpi_sdcp_device_list (FpSdcpDevice *self);
|
||||||
|
void fpi_sdcp_device_enroll (FpSdcpDevice *self);
|
||||||
|
void fpi_sdcp_device_identify (FpSdcpDevice *self);
|
||||||
177
libfprint/fp-sdcp-device.c
Normal file
177
libfprint/fp-sdcp-device.c
Normal file
@@ -0,0 +1,177 @@
|
|||||||
|
/*
|
||||||
|
* FpSdcpDevice - A base class for SDCP enabled devices
|
||||||
|
* Copyright (C) 2020 Benjamin Berg <bberg@redhat.com>
|
||||||
|
* Copyright (C) 2025 Joshua Grisham <josh@joshuagrisham.com>
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define FP_COMPONENT "sdcp_device"
|
||||||
|
#include "fpi-log.h"
|
||||||
|
|
||||||
|
#include "fp-sdcp-device-private.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SECTION: fp-sdcp-device
|
||||||
|
* @title: FpSdcpDevice
|
||||||
|
* @short_description: SDCP device subclass
|
||||||
|
*
|
||||||
|
* This is a base class for devices implementing the SDCP security protocol.
|
||||||
|
*/
|
||||||
|
|
||||||
|
G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (FpSdcpDevice, fp_sdcp_device, FP_TYPE_DEVICE)
|
||||||
|
|
||||||
|
enum {
|
||||||
|
PROP_0,
|
||||||
|
PROP_SDCP_DATA,
|
||||||
|
N_PROPS
|
||||||
|
};
|
||||||
|
|
||||||
|
static GParamSpec *properties[N_PROPS];
|
||||||
|
|
||||||
|
/*******************************************************/
|
||||||
|
|
||||||
|
/* Callbacks/vfuncs */
|
||||||
|
static void
|
||||||
|
fp_sdcp_device_open (FpDevice *device)
|
||||||
|
{
|
||||||
|
FpSdcpDevice *self = FP_SDCP_DEVICE (device);
|
||||||
|
|
||||||
|
fpi_sdcp_device_open (self);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
fp_sdcp_device_list (FpDevice *device)
|
||||||
|
{
|
||||||
|
FpSdcpDevice *self = FP_SDCP_DEVICE (device);
|
||||||
|
|
||||||
|
fpi_sdcp_device_list (self);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
fp_sdcp_device_enroll (FpDevice *device)
|
||||||
|
{
|
||||||
|
FpSdcpDevice *self = FP_SDCP_DEVICE (device);
|
||||||
|
|
||||||
|
fpi_sdcp_device_enroll (self);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
fp_sdcp_device_identify (FpDevice *device)
|
||||||
|
{
|
||||||
|
FpSdcpDevice *self = FP_SDCP_DEVICE (device);
|
||||||
|
|
||||||
|
fpi_sdcp_device_identify (self);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************************/
|
||||||
|
|
||||||
|
static void
|
||||||
|
fp_sdcp_device_finalize (GObject *object)
|
||||||
|
{
|
||||||
|
FpSdcpDevice *self = (FpSdcpDevice *) object;
|
||||||
|
FpSdcpDevicePrivate *priv = fp_sdcp_device_get_instance_private (self);
|
||||||
|
|
||||||
|
g_clear_pointer (&priv->host_private_key, g_bytes_unref);
|
||||||
|
g_clear_pointer (&priv->host_public_key, g_bytes_unref);
|
||||||
|
g_clear_pointer (&priv->host_random, g_bytes_unref);
|
||||||
|
g_clear_pointer (&priv->reconnect_random, g_bytes_unref);
|
||||||
|
g_clear_pointer (&priv->identify_nonce, g_bytes_unref);
|
||||||
|
g_clear_pointer (&priv->data, g_bytes_unref);
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (fp_sdcp_device_parent_class)->finalize (object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
fp_sdcp_device_get_property (GObject *object,
|
||||||
|
guint prop_id,
|
||||||
|
GValue *value,
|
||||||
|
GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
FpSdcpDevice *self = (FpSdcpDevice *) object;
|
||||||
|
FpSdcpDevicePrivate *priv = fp_sdcp_device_get_instance_private (self);
|
||||||
|
|
||||||
|
switch (prop_id)
|
||||||
|
{
|
||||||
|
case PROP_SDCP_DATA:
|
||||||
|
g_value_set_boxed (value, priv->data);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
fp_sdcp_device_set_property (GObject *object,
|
||||||
|
guint prop_id,
|
||||||
|
const GValue *value,
|
||||||
|
GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
FpSdcpDevice *self = FP_SDCP_DEVICE (object);
|
||||||
|
FpSdcpDevicePrivate *priv = fp_sdcp_device_get_instance_private (self);
|
||||||
|
|
||||||
|
switch (prop_id)
|
||||||
|
{
|
||||||
|
case PROP_SDCP_DATA:
|
||||||
|
g_clear_pointer (&priv->data, g_bytes_unref);
|
||||||
|
priv->data = g_value_dup_boxed (value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
fp_sdcp_device_constructed (GObject *obj)
|
||||||
|
{
|
||||||
|
G_OBJECT_CLASS (fp_sdcp_device_parent_class)->constructed (obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
fp_sdcp_device_class_init (FpSdcpDeviceClass *klass)
|
||||||
|
{
|
||||||
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||||
|
FpDeviceClass *fp_device_class = FP_DEVICE_CLASS (klass);
|
||||||
|
|
||||||
|
object_class->finalize = fp_sdcp_device_finalize;
|
||||||
|
object_class->get_property = fp_sdcp_device_get_property;
|
||||||
|
object_class->set_property = fp_sdcp_device_set_property;
|
||||||
|
object_class->constructed = fp_sdcp_device_constructed;
|
||||||
|
|
||||||
|
fp_device_class->open = fp_sdcp_device_open;
|
||||||
|
fp_device_class->list = fp_sdcp_device_list;
|
||||||
|
fp_device_class->enroll = fp_sdcp_device_enroll;
|
||||||
|
fp_device_class->verify = fp_sdcp_device_identify;
|
||||||
|
fp_device_class->identify = fp_sdcp_device_identify;
|
||||||
|
|
||||||
|
properties[PROP_SDCP_DATA] =
|
||||||
|
g_param_spec_boxed ("sdcp-data",
|
||||||
|
"SDCP Data",
|
||||||
|
"SDCP-related device data that should be persisted and used with the "
|
||||||
|
"device during the current system boot",
|
||||||
|
G_TYPE_BYTES,
|
||||||
|
G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE);
|
||||||
|
|
||||||
|
g_object_class_install_properties (object_class, N_PROPS, properties);
|
||||||
|
|
||||||
|
fpi_device_class_auto_initialize_features (fp_device_class);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
fp_sdcp_device_init (FpSdcpDevice *self)
|
||||||
|
{
|
||||||
|
}
|
||||||
29
libfprint/fp-sdcp-device.h
Normal file
29
libfprint/fp-sdcp-device.h
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
/*
|
||||||
|
* FpSdcpDevice - A base class for SDCP enabled devices
|
||||||
|
* Copyright (C) 2020 Benjamin Berg <bberg@redhat.com>
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <fp-device.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define FP_TYPE_SDCP_DEVICE (fp_sdcp_device_get_type ())
|
||||||
|
G_DECLARE_DERIVABLE_TYPE (FpSdcpDevice, fp_sdcp_device, FP, SDCP_DEVICE, FpDevice)
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
@@ -675,4 +675,6 @@ fpi_byte_reader_skip_inline (FpiByteReader * reader, guint nbytes)
|
|||||||
|
|
||||||
#endif /* FPI_BYTE_READER_DISABLE_INLINES */
|
#endif /* FPI_BYTE_READER_DISABLE_INLINES */
|
||||||
|
|
||||||
|
G_DEFINE_AUTOPTR_CLEANUP_FUNC (FpiByteReader, fpi_byte_reader_free);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|||||||
@@ -75,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,10 +211,9 @@ 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_memdup2 (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;
|
||||||
|
|||||||
@@ -111,6 +111,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)
|
||||||
{
|
{
|
||||||
@@ -407,4 +418,7 @@ fpi_byte_writer_fill_inline (FpiByteWriter * writer, guint8 value, guint size)
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
G_DEFINE_AUTOPTR_CLEANUP_FUNC (FpiByteWriter, fpi_byte_writer_free);
|
||||||
|
G_DEFINE_AUTO_CLEANUP_CLEAR_FUNC (FpiByteWriter, fpi_byte_writer_reset);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|||||||
@@ -20,36 +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 !GLIB_CHECK_VERSION (2, 68, 0)
|
|
||||||
#define g_memdup2(data, size) g_memdup ((data), (size))
|
|
||||||
#else
|
|
||||||
#define g_memdup2(data, size) \
|
|
||||||
(G_GNUC_EXTENSION ({ \
|
|
||||||
G_GNUC_BEGIN_IGNORE_DEPRECATIONS \
|
|
||||||
g_memdup2 ((data), (size)); \
|
|
||||||
G_GNUC_END_IGNORE_DEPRECATIONS \
|
|
||||||
}))
|
|
||||||
#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
|
||||||
|
|||||||
@@ -117,6 +117,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;
|
||||||
@@ -186,6 +190,9 @@ fpi_device_error_new (FpDeviceError error)
|
|||||||
|
|
||||||
case FP_DEVICE_ERROR_TOO_HOT:
|
case FP_DEVICE_ERROR_TOO_HOT:
|
||||||
msg = "Device disabled to prevent overheating.";
|
msg = "Device disabled to prevent overheating.";
|
||||||
|
|
||||||
|
case FP_DEVICE_ERROR_UNTRUSTED:
|
||||||
|
msg = "Could not verify integrity of the device, it cannot be trusted!";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@@ -522,33 +529,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
|
||||||
@@ -1069,34 +1049,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,
|
||||||
@@ -1128,7 +1115,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.
|
||||||
*/
|
*/
|
||||||
@@ -1174,7 +1161,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.
|
||||||
*/
|
*/
|
||||||
@@ -1201,7 +1188,7 @@ 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.
|
||||||
*/
|
*/
|
||||||
@@ -1253,7 +1240,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.
|
||||||
@@ -1382,7 +1369,7 @@ 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.
|
* Finish an ongoing identify operation.
|
||||||
*
|
*
|
||||||
@@ -1448,7 +1435,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.
|
||||||
*/
|
*/
|
||||||
@@ -1495,7 +1482,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.
|
||||||
*/
|
*/
|
||||||
@@ -1524,7 +1511,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.
|
||||||
*
|
*
|
||||||
@@ -1802,7 +1789,7 @@ fpi_device_suspend_completed (FpDevice *device)
|
|||||||
/**
|
/**
|
||||||
* 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
|
||||||
@@ -1853,7 +1840,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.
|
||||||
*/
|
*/
|
||||||
@@ -1881,7 +1868,7 @@ fpi_device_resume_complete (FpDevice *device,
|
|||||||
/**
|
/**
|
||||||
* 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.
|
||||||
*/
|
*/
|
||||||
@@ -1912,7 +1899,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().
|
||||||
|
|||||||
@@ -565,7 +565,7 @@ fpi_image_device_retry_scan (FpImageDevice *self, FpDeviceRetry retry)
|
|||||||
/**
|
/**
|
||||||
* fpi_image_device_session_error:
|
* fpi_image_device_session_error:
|
||||||
* @self: a #FpImageDevice imaging fingerprint device
|
* @self: a #FpImageDevice imaging fingerprint device
|
||||||
* @error: 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 +624,7 @@ fpi_image_device_session_error (FpImageDevice *self, GError *error)
|
|||||||
/**
|
/**
|
||||||
* fpi_image_device_activate_complete:
|
* fpi_image_device_activate_complete:
|
||||||
* @self: a #FpImageDevice imaging fingerprint device
|
* @self: a #FpImageDevice imaging fingerprint device
|
||||||
* @error: 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.
|
||||||
*/
|
*/
|
||||||
@@ -663,7 +663,7 @@ fpi_image_device_activate_complete (FpImageDevice *self, GError *error)
|
|||||||
/**
|
/**
|
||||||
* fpi_image_device_deactivate_complete:
|
* fpi_image_device_deactivate_complete:
|
||||||
* @self: a #FpImageDevice imaging fingerprint device
|
* @self: a #FpImageDevice imaging fingerprint device
|
||||||
* @error: 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 +690,7 @@ fpi_image_device_deactivate_complete (FpImageDevice *self, GError *error)
|
|||||||
/**
|
/**
|
||||||
* fpi_image_device_open_complete:
|
* fpi_image_device_open_complete:
|
||||||
* @self: a #FpImageDevice imaging fingerprint device
|
* @self: a #FpImageDevice imaging fingerprint device
|
||||||
* @error: 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 +718,7 @@ fpi_image_device_open_complete (FpImageDevice *self, GError *error)
|
|||||||
/**
|
/**
|
||||||
* fpi_image_device_close_complete:
|
* fpi_image_device_close_complete:
|
||||||
* @self: a #FpImageDevice imaging fingerprint device
|
* @self: a #FpImageDevice imaging fingerprint device
|
||||||
* @error: 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"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -34,6 +33,7 @@
|
|||||||
* 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 +68,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 +78,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
|
|
||||||
|
|||||||
57
libfprint/fpi-log.c
Normal file
57
libfprint/fpi-log.c
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
/*
|
||||||
|
* FpiLog - Internal logging functions
|
||||||
|
* Copyright (C) 2020 Benjamin Berg <bberg@redhat.com>
|
||||||
|
* Copyright (C) 2025 Joshua Grisham <josh@joshuagrisham.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 "fpi-log.h"
|
||||||
|
|
||||||
|
#undef fp_dbg_hex_dump_bytes
|
||||||
|
#undef fp_dbg_hex_dump_gbytes
|
||||||
|
|
||||||
|
void
|
||||||
|
fp_dbg_hex_dump_bytes (const gchar *log_domain,
|
||||||
|
const guint8 *buf,
|
||||||
|
gsize len)
|
||||||
|
{
|
||||||
|
g_autoptr(GString) line = NULL;
|
||||||
|
|
||||||
|
line = g_string_new ("");
|
||||||
|
|
||||||
|
for (gint i = 0; i < len; i++)
|
||||||
|
{
|
||||||
|
g_string_append_printf (line, "%02x ", buf[i]);
|
||||||
|
if ((i + 1) % 16 == 0)
|
||||||
|
{
|
||||||
|
g_log (log_domain, G_LOG_LEVEL_DEBUG, "%s", line->str);
|
||||||
|
g_string_set_size (line, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (line->len)
|
||||||
|
g_log (log_domain, G_LOG_LEVEL_DEBUG, "%s", line->str);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
fp_dbg_hex_dump_gbytes (const gchar *log_domain,
|
||||||
|
GBytes *gbytes)
|
||||||
|
{
|
||||||
|
gsize len = 0;
|
||||||
|
const guint8 *buf = g_bytes_get_data (gbytes, &len);
|
||||||
|
|
||||||
|
fp_dbg_hex_dump_bytes (log_domain, buf, len);
|
||||||
|
}
|
||||||
@@ -79,13 +79,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 +96,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)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Custom-defined logging functions are wrapped in macros for convenience so
|
||||||
|
* that the caller does not have to pass G_LOG_DOMAIN every time.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void fp_dbg_hex_dump_bytes (const gchar *log_domain,
|
||||||
|
const guint8 *buf,
|
||||||
|
gsize len);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fp_dbg_hex_dump_bytes:
|
||||||
|
* @buf: Bytes buffer to dump
|
||||||
|
* @len: Length of @buf to dump
|
||||||
|
*
|
||||||
|
* Prints hex dump of @buf to fp_dbg()
|
||||||
|
*/
|
||||||
|
#define fp_dbg_hex_dump_bytes(buf, len) fp_dbg_hex_dump_bytes (G_LOG_DOMAIN, buf, len)
|
||||||
|
|
||||||
|
void fp_dbg_hex_dump_gbytes (const gchar *log_domain,
|
||||||
|
GBytes *gbytes);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fp_dbg_hex_dump_gbytes:
|
||||||
|
* @gbytes: #GBytes to dump
|
||||||
|
*
|
||||||
|
* Prints hex dump of @gbytes to fp_dbg()
|
||||||
|
*/
|
||||||
|
#define fp_dbg_hex_dump_gbytes(gbytes) fp_dbg_hex_dump_gbytes (G_LOG_DOMAIN, gbytes)
|
||||||
|
|||||||
@@ -11,11 +11,13 @@ G_BEGIN_DECLS
|
|||||||
* @FPI_PRINT_UNDEFINED: Undefined type, this happens prior to enrollment
|
* @FPI_PRINT_UNDEFINED: Undefined type, this happens prior to enrollment
|
||||||
* @FPI_PRINT_RAW: A raw print where the data is directly compared
|
* @FPI_PRINT_RAW: A raw print where the data is directly compared
|
||||||
* @FPI_PRINT_NBIS: NBIS minutiae comparison
|
* @FPI_PRINT_NBIS: NBIS minutiae comparison
|
||||||
|
* @FPI_PRINT_SDCP: Print from an SDCP conforming device
|
||||||
*/
|
*/
|
||||||
typedef enum {
|
typedef enum {
|
||||||
FPI_PRINT_UNDEFINED = 0,
|
FPI_PRINT_UNDEFINED = 0,
|
||||||
FPI_PRINT_RAW,
|
FPI_PRINT_RAW,
|
||||||
FPI_PRINT_NBIS,
|
FPI_PRINT_NBIS,
|
||||||
|
FPI_PRINT_SDCP,
|
||||||
} FpiPrintType;
|
} FpiPrintType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
980
libfprint/fpi-sdcp-device.c
Normal file
980
libfprint/fpi-sdcp-device.c
Normal file
@@ -0,0 +1,980 @@
|
|||||||
|
/*
|
||||||
|
* FpSdcpDevice - A base class for SDCP enabled devices
|
||||||
|
* Copyright (C) 2020 Benjamin Berg <bberg@redhat.com>
|
||||||
|
* Copyright (C) 2025 Joshua Grisham <josh@joshuagrisham.com>
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define FP_COMPONENT "sdcp_device"
|
||||||
|
#include "fpi-log.h"
|
||||||
|
|
||||||
|
#include "fpi-compat.h"
|
||||||
|
#include "fpi-print.h"
|
||||||
|
|
||||||
|
#include "fp-sdcp-device-private.h"
|
||||||
|
#include "fpi-sdcp.h"
|
||||||
|
#include "fpi-sdcp-device.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SECTION: fpi-sdcp-device
|
||||||
|
* @title: Internal FpSdcpDevice
|
||||||
|
* @short_description: Internal SDCP device routines
|
||||||
|
*
|
||||||
|
* Internal SDCP handling routines. See #FpSdcpDevice for public routines.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
G_DEFINE_BOXED_TYPE (FpiSdcpClaim, fpi_sdcp_claim, fpi_sdcp_claim_copy, fpi_sdcp_claim_free)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fpi_sdcp_claim_new:
|
||||||
|
*
|
||||||
|
* Create an empty #FpiSdcpClaim to provide to the base class.
|
||||||
|
*
|
||||||
|
* Returns: (transfer full): A newly created #FpiSdcpClaim
|
||||||
|
*/
|
||||||
|
FpiSdcpClaim *
|
||||||
|
fpi_sdcp_claim_new (void)
|
||||||
|
{
|
||||||
|
FpiSdcpClaim *res = NULL;
|
||||||
|
|
||||||
|
res = g_new0 (FpiSdcpClaim, 1);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fpi_sdcp_claim_free:
|
||||||
|
* @claim: a #FpiSdcpClaim
|
||||||
|
*
|
||||||
|
* Release the memory used by an #FpiSdcpClaim.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
fpi_sdcp_claim_free (FpiSdcpClaim *claim)
|
||||||
|
{
|
||||||
|
g_return_if_fail (claim);
|
||||||
|
|
||||||
|
g_clear_pointer (&claim->model_certificate, g_bytes_unref);
|
||||||
|
g_clear_pointer (&claim->device_public_key, g_bytes_unref);
|
||||||
|
g_clear_pointer (&claim->firmware_public_key, g_bytes_unref);
|
||||||
|
g_clear_pointer (&claim->firmware_hash, g_bytes_unref);
|
||||||
|
g_clear_pointer (&claim->model_signature, g_bytes_unref);
|
||||||
|
g_clear_pointer (&claim->device_signature, g_bytes_unref);
|
||||||
|
|
||||||
|
g_free (claim);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fpi_sdcp_claim_copy:
|
||||||
|
* @other: The #FpiSdcpClaim to copy
|
||||||
|
*
|
||||||
|
* Create a (shallow) copy of a #FpiSdcpClaim.
|
||||||
|
*
|
||||||
|
* Returns: (transfer full): A newly created #FpiSdcpClaim
|
||||||
|
*/
|
||||||
|
FpiSdcpClaim *
|
||||||
|
fpi_sdcp_claim_copy (FpiSdcpClaim *other)
|
||||||
|
{
|
||||||
|
FpiSdcpClaim *res = NULL;
|
||||||
|
|
||||||
|
res = fpi_sdcp_claim_new ();
|
||||||
|
|
||||||
|
if (other->model_certificate)
|
||||||
|
res->model_certificate = g_bytes_ref (other->model_certificate);
|
||||||
|
if (other->device_public_key)
|
||||||
|
res->device_public_key = g_bytes_ref (other->device_public_key);
|
||||||
|
if (other->firmware_public_key)
|
||||||
|
res->firmware_public_key = g_bytes_ref (other->firmware_public_key);
|
||||||
|
if (other->firmware_hash)
|
||||||
|
res->firmware_hash = g_bytes_ref (other->firmware_hash);
|
||||||
|
if (other->model_signature)
|
||||||
|
res->model_signature = g_bytes_ref (other->model_signature);
|
||||||
|
if (other->device_signature)
|
||||||
|
res->device_signature = g_bytes_ref (other->device_signature);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Manually redefine what G_DEFINE_* macro does */
|
||||||
|
static inline gpointer
|
||||||
|
fp_sdcp_device_get_instance_private (FpSdcpDevice *self)
|
||||||
|
{
|
||||||
|
FpSdcpDeviceClass *sdcp_class = g_type_class_peek_static (FP_TYPE_SDCP_DEVICE);
|
||||||
|
|
||||||
|
return G_STRUCT_MEMBER_P (self,
|
||||||
|
g_type_class_get_instance_private_offset (sdcp_class));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Example values from Microsoft's SDCP documentation to use when testing (FP_DEVICE_EMULATION=1) */
|
||||||
|
static const guchar test_host_private_key[] = {
|
||||||
|
0x84, 0x00, 0xed, 0x14, 0x57, 0x9c, 0xdf, 0x11, 0x58, 0x64, 0x77, 0xe8, 0x36, 0xe8, 0xcb, 0x52,
|
||||||
|
0x70, 0x84, 0x41, 0xc1, 0xc2, 0xa4, 0x47, 0xc2, 0x18, 0xc5, 0xbb, 0xc2, 0xd1, 0x18, 0xfb, 0xc7
|
||||||
|
};
|
||||||
|
static const guchar test_host_public_key[] = {
|
||||||
|
0x04, 0x52, 0xf0, 0x56, 0xff, 0xb9, 0xc6, 0x72, 0x86, 0x54, 0x77, 0x1a, 0x36, 0x29, 0xb7, 0x70,
|
||||||
|
0x76, 0x7b, 0x19, 0xa2, 0x10, 0x6a, 0x49, 0x16, 0xfb, 0x81, 0xba, 0x06, 0xef, 0x67, 0x97, 0xc4,
|
||||||
|
0xa3, 0xdf, 0x67, 0x2a, 0xde, 0x0e, 0x91, 0x16, 0xd1, 0xab, 0xe2, 0x78, 0xa8, 0x22, 0x3a, 0xbd,
|
||||||
|
0xe4, 0x95, 0x8d, 0x62, 0xd4, 0xff, 0x68, 0x82, 0x15, 0x9f, 0x06, 0x17, 0xc6, 0xf8, 0xce, 0x10,
|
||||||
|
0xbf
|
||||||
|
};
|
||||||
|
static const gchar test_host_random[] = {
|
||||||
|
0xd8, 0x77, 0x40, 0x3a, 0xbe, 0x82, 0xf4, 0xd9, 0x7e, 0x14, 0x48, 0xc5, 0x05, 0x2d, 0x83, 0xa5,
|
||||||
|
0x32, 0xa4, 0x5e, 0x56, 0xef, 0x04, 0x9c, 0xbb, 0xf9, 0x81, 0x13, 0x75, 0x20, 0xe7, 0x13, 0xbf
|
||||||
|
};
|
||||||
|
static const gchar test_reconnect_random[] = {
|
||||||
|
0x8a, 0x74, 0x51, 0xc1, 0xd3, 0xa8, 0xdc, 0xa1, 0xc1, 0x33, 0x0c, 0xa5, 0x0d, 0x73, 0x45, 0x4b,
|
||||||
|
0x35, 0x1a, 0x49, 0xf4, 0x6c, 0x8e, 0x9d, 0xce, 0xe1, 0x5c, 0x96, 0x4d, 0x29, 0x5c, 0x31, 0xc9
|
||||||
|
};
|
||||||
|
static const gchar test_identify_nonce[] = {
|
||||||
|
0x3a, 0x1b, 0x50, 0x6f, 0x5b, 0xec, 0x08, 0x90, 0x59, 0xac, 0xef, 0xb9, 0xb4, 0x4d, 0xfb, 0xde,
|
||||||
|
0xa7, 0xa5, 0x99, 0xee, 0x9a, 0xa2, 0x67, 0xe5, 0x25, 0x26, 0x64, 0xd6, 0x0b, 0x79, 0x80, 0x53
|
||||||
|
};
|
||||||
|
|
||||||
|
/* FpiSdcpDevice */
|
||||||
|
|
||||||
|
/* Internal functions of FpSdcpDevice */
|
||||||
|
|
||||||
|
void
|
||||||
|
fpi_sdcp_device_get_application_secret (FpSdcpDevice *self,
|
||||||
|
GBytes **application_secret)
|
||||||
|
{
|
||||||
|
GBytes *data = NULL;
|
||||||
|
|
||||||
|
g_return_if_fail (*application_secret == NULL);
|
||||||
|
|
||||||
|
g_object_get (G_OBJECT (self), "sdcp-data", &data, NULL);
|
||||||
|
|
||||||
|
if (!data)
|
||||||
|
return;
|
||||||
|
|
||||||
|
*application_secret = g_steal_pointer (&data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
fpi_sdcp_device_set_application_secret (FpSdcpDevice *self,
|
||||||
|
GBytes *application_secret)
|
||||||
|
{
|
||||||
|
g_return_if_fail (application_secret);
|
||||||
|
|
||||||
|
g_object_set (G_OBJECT (self), "sdcp-data", application_secret, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
fpi_sdcp_device_open (FpSdcpDevice *self)
|
||||||
|
{
|
||||||
|
FpSdcpDeviceClass *cls = FP_SDCP_DEVICE_GET_CLASS (self);
|
||||||
|
|
||||||
|
g_return_if_fail (FP_IS_SDCP_DEVICE (self));
|
||||||
|
g_return_if_fail (fpi_device_get_current_action (FP_DEVICE (self)) == FPI_DEVICE_ACTION_OPEN);
|
||||||
|
|
||||||
|
cls->open (self);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
fpi_sdcp_device_connect (FpSdcpDevice *self)
|
||||||
|
{
|
||||||
|
FpSdcpDeviceClass *cls = FP_SDCP_DEVICE_GET_CLASS (self);
|
||||||
|
FpSdcpDevicePrivate *priv = fp_sdcp_device_get_instance_private (self);
|
||||||
|
GError *error = NULL;
|
||||||
|
|
||||||
|
g_clear_pointer (&priv->host_private_key, g_bytes_unref);
|
||||||
|
g_clear_pointer (&priv->host_public_key, g_bytes_unref);
|
||||||
|
g_clear_pointer (&priv->host_random, g_bytes_unref);
|
||||||
|
|
||||||
|
if (g_strcmp0 (g_getenv ("FP_DEVICE_EMULATION"), "1") != 0)
|
||||||
|
{
|
||||||
|
/* SDCP Connect: 3.i. Generate host ephemeral ECDH key pair */
|
||||||
|
fpi_sdcp_generate_host_key (&priv->host_private_key, &priv->host_public_key, &error);
|
||||||
|
if (error)
|
||||||
|
{
|
||||||
|
fpi_sdcp_device_connect_complete (self,
|
||||||
|
NULL, NULL, NULL,
|
||||||
|
error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* SDCP Connect: 3.ii. Generate host random */
|
||||||
|
priv->host_random = fpi_sdcp_generate_random (&error);
|
||||||
|
if (error)
|
||||||
|
{
|
||||||
|
fpi_sdcp_device_connect_complete (self,
|
||||||
|
NULL, NULL, NULL,
|
||||||
|
error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Use Microsoft's SDCP documentation example values in emulation mode */
|
||||||
|
priv->host_private_key = g_bytes_new (test_host_private_key, sizeof (test_host_private_key));
|
||||||
|
priv->host_public_key = g_bytes_new (test_host_public_key, sizeof (test_host_public_key));
|
||||||
|
priv->host_random = g_bytes_new (test_host_random, sizeof (test_host_random));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* SDCP Connect: 3.iii. Send the Connect message */
|
||||||
|
cls->connect (self);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
fpi_sdcp_device_reconnect (FpSdcpDevice *self)
|
||||||
|
{
|
||||||
|
FpSdcpDeviceClass *cls = FP_SDCP_DEVICE_GET_CLASS (self);
|
||||||
|
FpSdcpDevicePrivate *priv = fp_sdcp_device_get_instance_private (self);
|
||||||
|
GError *error = NULL;
|
||||||
|
|
||||||
|
g_clear_pointer (&priv->reconnect_random, g_bytes_unref);
|
||||||
|
|
||||||
|
if (g_strcmp0 (g_getenv ("FP_DEVICE_EMULATION"), "1") != 0)
|
||||||
|
{
|
||||||
|
/* SDCP Reconnect: 2.i. Generate host random */
|
||||||
|
priv->reconnect_random = fpi_sdcp_generate_random (&error);
|
||||||
|
if (error)
|
||||||
|
{
|
||||||
|
fpi_sdcp_device_reconnect_complete (self, NULL, error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Use Microsoft's SDCP documentation example value in emulation mode */
|
||||||
|
priv->reconnect_random = g_bytes_new (test_reconnect_random, sizeof (test_reconnect_random));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* SDCP Reconnect: 2.ii. Send the Reconnect message */
|
||||||
|
if (cls->reconnect)
|
||||||
|
cls->reconnect (self);
|
||||||
|
else
|
||||||
|
fpi_sdcp_device_connect (self);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
fpi_sdcp_device_list (FpSdcpDevice *self)
|
||||||
|
{
|
||||||
|
FpSdcpDeviceClass *cls = FP_SDCP_DEVICE_GET_CLASS (self);
|
||||||
|
|
||||||
|
g_return_if_fail (FP_IS_SDCP_DEVICE (self));
|
||||||
|
g_return_if_fail (fpi_device_get_current_action (FP_DEVICE (self)) == FPI_DEVICE_ACTION_LIST);
|
||||||
|
|
||||||
|
cls->list (self);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
fpi_sdcp_device_enroll (FpSdcpDevice *self)
|
||||||
|
{
|
||||||
|
FpSdcpDeviceClass *cls = FP_SDCP_DEVICE_GET_CLASS (self);
|
||||||
|
|
||||||
|
g_autoptr(GBytes) application_secret = NULL;
|
||||||
|
FpPrint *print;
|
||||||
|
|
||||||
|
g_return_if_fail (FP_IS_SDCP_DEVICE (self));
|
||||||
|
g_return_if_fail (fpi_device_get_current_action (FP_DEVICE (self)) == FPI_DEVICE_ACTION_ENROLL);
|
||||||
|
fpi_sdcp_device_get_application_secret (self, &application_secret);
|
||||||
|
g_return_if_fail (application_secret != NULL);
|
||||||
|
|
||||||
|
fpi_device_get_enroll_data (FP_DEVICE (self), &print);
|
||||||
|
|
||||||
|
fpi_print_set_device_stored (print, FALSE);
|
||||||
|
g_object_set (print, "fpi-data", NULL, NULL);
|
||||||
|
|
||||||
|
cls->enroll (self);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
fpi_sdcp_device_identify (FpSdcpDevice *self)
|
||||||
|
{
|
||||||
|
FpSdcpDevicePrivate *priv = fp_sdcp_device_get_instance_private (self);
|
||||||
|
FpSdcpDeviceClass *cls = FP_SDCP_DEVICE_GET_CLASS (self);
|
||||||
|
|
||||||
|
g_autoptr(GBytes) application_secret = NULL;
|
||||||
|
FpiDeviceAction action;
|
||||||
|
GError *error = NULL;
|
||||||
|
|
||||||
|
g_return_if_fail (FP_IS_SDCP_DEVICE (self));
|
||||||
|
action = fpi_device_get_current_action (FP_DEVICE (self));
|
||||||
|
g_return_if_fail (action == FPI_DEVICE_ACTION_IDENTIFY || action == FPI_DEVICE_ACTION_VERIFY);
|
||||||
|
fpi_sdcp_device_get_application_secret (self, &application_secret);
|
||||||
|
g_return_if_fail (application_secret != NULL);
|
||||||
|
|
||||||
|
g_clear_pointer (&priv->identify_nonce, g_bytes_unref);
|
||||||
|
|
||||||
|
if (g_strcmp0 (g_getenv ("FP_DEVICE_EMULATION"), "1") != 0)
|
||||||
|
{
|
||||||
|
/* Generate a new nonce. */
|
||||||
|
priv->identify_nonce = fpi_sdcp_generate_random (&error);
|
||||||
|
if (error)
|
||||||
|
{
|
||||||
|
fpi_device_action_error (FP_DEVICE (self), error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Use Microsoft's SDCP documentation example value in emulation mode */
|
||||||
|
priv->identify_nonce = g_bytes_new (test_identify_nonce, sizeof (test_identify_nonce));
|
||||||
|
}
|
||||||
|
|
||||||
|
cls->identify (self);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************************/
|
||||||
|
/* Private API */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fpi_sdcp_device_open_complete:
|
||||||
|
* @self: a #FpSdcpDevice fingerprint device
|
||||||
|
* @error: A #GError or %NULL on success
|
||||||
|
*
|
||||||
|
* Reports completion of open operation. Responsible for triggering SDCP connect
|
||||||
|
* or reconnect as necessary.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
fpi_sdcp_device_open_complete (FpSdcpDevice *self,
|
||||||
|
GError *error)
|
||||||
|
{
|
||||||
|
FpSdcpDeviceClass *cls = FP_SDCP_DEVICE_GET_CLASS (self);
|
||||||
|
|
||||||
|
g_autoptr(GBytes) application_secret = NULL;
|
||||||
|
|
||||||
|
if (!error)
|
||||||
|
{
|
||||||
|
fpi_sdcp_device_get_application_secret (self, &application_secret);
|
||||||
|
|
||||||
|
/* Try a reconnect if implemented and we already have an application_secret */
|
||||||
|
if (cls->reconnect && application_secret)
|
||||||
|
fpi_sdcp_device_reconnect (self);
|
||||||
|
|
||||||
|
/* Connect if we don't already have an application_secret */
|
||||||
|
else if (!application_secret)
|
||||||
|
fpi_sdcp_device_connect (self);
|
||||||
|
|
||||||
|
/* Complete open if we are already connected */
|
||||||
|
else
|
||||||
|
fpi_device_open_complete (FP_DEVICE (self), NULL);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fpi_device_open_complete (FP_DEVICE (self), error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fp_sdcp_device_get_connect_data:
|
||||||
|
* @self: a #FpSdcpDevice fingerprint device
|
||||||
|
* @host_random: (out) (transfer full): The host-generated random
|
||||||
|
* @host_public_key: (out) (transfer full): The host public key
|
||||||
|
*
|
||||||
|
* Get data required to connect to (i.e. open) the device securely.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
fpi_sdcp_device_get_connect_data (FpSdcpDevice *self,
|
||||||
|
GBytes **host_random,
|
||||||
|
GBytes **host_public_key)
|
||||||
|
{
|
||||||
|
FpSdcpDevicePrivate *priv = fp_sdcp_device_get_instance_private (self);
|
||||||
|
|
||||||
|
g_return_if_fail (host_random != NULL);
|
||||||
|
g_return_if_fail (host_public_key != NULL);
|
||||||
|
g_return_if_fail (priv->host_random);
|
||||||
|
g_return_if_fail (priv->host_public_key);
|
||||||
|
|
||||||
|
*host_random = g_bytes_new_from_bytes (priv->host_random, 0,
|
||||||
|
g_bytes_get_size (priv->host_random));
|
||||||
|
*host_public_key = g_bytes_new_from_bytes (priv->host_public_key, 0,
|
||||||
|
g_bytes_get_size (priv->host_public_key));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fp_sdcp_device_get_reconnect_data:
|
||||||
|
* @self: a #FpSdcpDevice fingerprint device
|
||||||
|
* @reconnect_random: (out) (transfer full): The host-generated random
|
||||||
|
*
|
||||||
|
* Get data required to reconnect to (i.e. open) to the device securely.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
fpi_sdcp_device_get_reconnect_data (FpSdcpDevice *self,
|
||||||
|
GBytes **reconnect_random)
|
||||||
|
{
|
||||||
|
FpSdcpDevicePrivate *priv = fp_sdcp_device_get_instance_private (self);
|
||||||
|
|
||||||
|
g_return_if_fail (reconnect_random != NULL);
|
||||||
|
g_return_if_fail (priv->reconnect_random);
|
||||||
|
|
||||||
|
*reconnect_random = g_bytes_new_from_bytes (priv->reconnect_random, 0,
|
||||||
|
g_bytes_get_size (priv->reconnect_random));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fp_sdcp_device_get_identify_data:
|
||||||
|
* @self: a #FpSdcpDevice fingerprint device
|
||||||
|
* @nonce: (out) (transfer full): A new host-generated nonce
|
||||||
|
*
|
||||||
|
* Get data required to identify a new print.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
fpi_sdcp_device_get_identify_data (FpSdcpDevice *self,
|
||||||
|
GBytes **nonce)
|
||||||
|
{
|
||||||
|
FpSdcpDevicePrivate *priv = fp_sdcp_device_get_instance_private (self);
|
||||||
|
|
||||||
|
g_return_if_fail (nonce != NULL);
|
||||||
|
g_return_if_fail (priv->identify_nonce);
|
||||||
|
|
||||||
|
*nonce = g_bytes_new_from_bytes (priv->identify_nonce, 0,
|
||||||
|
g_bytes_get_size (priv->identify_nonce));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fp_sdcp_device_set_identify_data:
|
||||||
|
* @self: a #FpSdcpDevice fingerprint device
|
||||||
|
* @nonce: A driver-specified nonce
|
||||||
|
*
|
||||||
|
* Sets data required to identify a new print.
|
||||||
|
*
|
||||||
|
* Most drivers should not use this function, but instead use the automatically
|
||||||
|
* generated values retrieved from fpi_sdcp_device_get_identify_data() when
|
||||||
|
* executing the device-specific Identify command.
|
||||||
|
*
|
||||||
|
* In cases where a device's Identify command does not accept a randomly
|
||||||
|
* generated nonce, this function can be used to override the randomly generated
|
||||||
|
* nonce to the nonce that was actually sent to the device.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
fpi_sdcp_device_set_identify_data (FpSdcpDevice *self,
|
||||||
|
GBytes *nonce)
|
||||||
|
{
|
||||||
|
FpSdcpDevicePrivate *priv = fp_sdcp_device_get_instance_private (self);
|
||||||
|
|
||||||
|
g_return_if_fail (nonce != NULL);
|
||||||
|
|
||||||
|
g_clear_pointer (&priv->identify_nonce, g_bytes_unref);
|
||||||
|
|
||||||
|
priv->identify_nonce = g_steal_pointer (&nonce);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fpi_sdcp_device_connect_complete:
|
||||||
|
* @self: a #FpSdcpDevice fingerprint device
|
||||||
|
* @device_random: The device random
|
||||||
|
* @claim: The device #FpiSdcpClaim
|
||||||
|
* @mac: The MAC authenticating @claim
|
||||||
|
* @error: A #GError or %NULL on success
|
||||||
|
*
|
||||||
|
* Reports completion of connect operation. Responsible for performing SDCP key
|
||||||
|
* agreement, deriving secrets necessary for processing all other SDCP-related
|
||||||
|
* payloads, and verifying the device connection is trusted.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
fpi_sdcp_device_connect_complete (FpSdcpDevice *self,
|
||||||
|
GBytes *device_random,
|
||||||
|
FpiSdcpClaim *claim,
|
||||||
|
GBytes *mac,
|
||||||
|
GError *error)
|
||||||
|
{
|
||||||
|
FpSdcpDevicePrivate *priv = fp_sdcp_device_get_instance_private (self);
|
||||||
|
FpSdcpDeviceClass *cls = FP_SDCP_DEVICE_GET_CLASS (self);
|
||||||
|
|
||||||
|
g_autoptr(GBytes) application_secret = NULL;
|
||||||
|
FpiDeviceAction action;
|
||||||
|
|
||||||
|
action = fpi_device_get_current_action (FP_DEVICE (self));
|
||||||
|
|
||||||
|
g_return_if_fail (action == FPI_DEVICE_ACTION_OPEN);
|
||||||
|
g_return_if_fail (priv->host_private_key);
|
||||||
|
g_return_if_fail (priv->host_random);
|
||||||
|
|
||||||
|
if (error)
|
||||||
|
{
|
||||||
|
if (device_random || claim || mac)
|
||||||
|
{
|
||||||
|
g_clear_pointer (&device_random, g_bytes_unref);
|
||||||
|
g_clear_pointer (&claim, fpi_sdcp_claim_free);
|
||||||
|
g_clear_pointer (&mac, g_bytes_unref);
|
||||||
|
fp_warn ("Driver provided SDCP Connect information but also reported error.");
|
||||||
|
}
|
||||||
|
|
||||||
|
fpi_device_open_complete (FP_DEVICE (self), error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!device_random || !claim || !mac ||
|
||||||
|
(!claim->model_certificate || !claim->device_public_key || !claim->firmware_public_key ||
|
||||||
|
!claim->firmware_hash || !claim->model_signature || !claim->device_signature))
|
||||||
|
{
|
||||||
|
fp_dbg ("Driver did not provide all required information to callback; returning error instead.");
|
||||||
|
g_clear_pointer (&device_random, g_bytes_unref);
|
||||||
|
g_clear_pointer (&claim, fpi_sdcp_claim_free);
|
||||||
|
g_clear_pointer (&mac, g_bytes_unref);
|
||||||
|
|
||||||
|
fpi_device_open_complete (FP_DEVICE (self),
|
||||||
|
fpi_device_error_new_msg (FP_DEVICE_ERROR_GENERAL,
|
||||||
|
"Driver called connect complete with "
|
||||||
|
"incomplete arguments"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Verify connect and store the application_secret */
|
||||||
|
if (!fpi_sdcp_verify_connect (priv->host_private_key,
|
||||||
|
priv->host_random,
|
||||||
|
device_random,
|
||||||
|
claim,
|
||||||
|
mac,
|
||||||
|
!cls->ignore_device_certificate,
|
||||||
|
!cls->ignore_device_signatures,
|
||||||
|
&application_secret,
|
||||||
|
&error))
|
||||||
|
{
|
||||||
|
fpi_device_open_complete (FP_DEVICE (self),
|
||||||
|
fpi_device_error_new_msg (FP_DEVICE_ERROR_UNTRUSTED,
|
||||||
|
"SDCP Connect verification failed: %s",
|
||||||
|
error->message));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
fpi_sdcp_device_set_application_secret (self, application_secret);
|
||||||
|
|
||||||
|
/* Clear no longer needed private data */
|
||||||
|
g_clear_pointer (&priv->host_private_key, g_bytes_unref);
|
||||||
|
g_clear_pointer (&priv->host_public_key, g_bytes_unref);
|
||||||
|
g_clear_pointer (&priv->host_random, g_bytes_unref);
|
||||||
|
|
||||||
|
fpi_device_open_complete (FP_DEVICE (self), NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fpi_sdcp_device_reconnect_complete:
|
||||||
|
* @self: a #FpSdcpDevice fingerprint device
|
||||||
|
* @mac: The MAC authenticating @claim
|
||||||
|
* @error: A #GError or %NULL on success
|
||||||
|
*
|
||||||
|
* Reports completion of a reconnect (i.e. open) operation.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
fpi_sdcp_device_reconnect_complete (FpSdcpDevice *self,
|
||||||
|
GBytes *mac,
|
||||||
|
GError *error)
|
||||||
|
{
|
||||||
|
FpSdcpDevicePrivate *priv = fp_sdcp_device_get_instance_private (self);
|
||||||
|
|
||||||
|
g_autoptr(GBytes) application_secret = NULL;
|
||||||
|
FpiDeviceAction action;
|
||||||
|
|
||||||
|
action = fpi_device_get_current_action (FP_DEVICE (self));
|
||||||
|
|
||||||
|
g_return_if_fail (action == FPI_DEVICE_ACTION_OPEN);
|
||||||
|
g_return_if_fail (priv->reconnect_random);
|
||||||
|
|
||||||
|
if (error)
|
||||||
|
{
|
||||||
|
if (mac)
|
||||||
|
{
|
||||||
|
fp_warn ("Driver provided a reconnect MAC but also reported an error.");
|
||||||
|
g_clear_pointer (&mac, g_bytes_unref);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Silently try a normal connect instead. */
|
||||||
|
fpi_sdcp_device_connect (self);
|
||||||
|
}
|
||||||
|
else if (mac)
|
||||||
|
{
|
||||||
|
fpi_sdcp_device_get_application_secret (self, &application_secret);
|
||||||
|
|
||||||
|
if (fpi_sdcp_verify_reconnect (application_secret, priv->reconnect_random, mac, &error))
|
||||||
|
{
|
||||||
|
fp_dbg ("SDCP Reconnect succeeded");
|
||||||
|
fpi_device_open_complete (FP_DEVICE (self), NULL);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fp_dbg ("SDCP Reconnect failed; doing a full connect.");
|
||||||
|
fpi_sdcp_device_connect (self);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fpi_device_open_complete (FP_DEVICE (self),
|
||||||
|
fpi_device_error_new_msg (FP_DEVICE_ERROR_GENERAL,
|
||||||
|
"Driver called reconnect complete with wrong arguments"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Clear no longer needed private data */
|
||||||
|
g_clear_pointer (&priv->reconnect_random, g_bytes_unref);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fpi_sdcp_device_list_complete:
|
||||||
|
* @self: a #FpSdcpDevice fingerprint device
|
||||||
|
* @ids: A #GPtrArray of #GBytes of each SDCP enrollment ID stored on the device
|
||||||
|
* @error: A #GError or %NULL on success
|
||||||
|
*
|
||||||
|
* Convenience function to create the minimally required #FpPrint list for
|
||||||
|
* #FpSdcpDevice prints using the provided @ids, then uses that #FpPrint list to
|
||||||
|
* report completion of the list operation.
|
||||||
|
*
|
||||||
|
* If the device provides additional attributes that should be stored on each
|
||||||
|
* #FpPrint as part of the list operation, a #GPtrArray of #FpPrint can instead
|
||||||
|
* be created with the additional attributes and fpi_device_list_complete() can
|
||||||
|
* be used instead of this function.
|
||||||
|
*
|
||||||
|
* Please note that the @ids array will be freed using g_ptr_array_unref() and
|
||||||
|
* the elements are destroyed automatically. As such, you must use
|
||||||
|
* g_ptr_array_new_with_free_func() with `(GDestroyNotify) g_bytes_unref` as the
|
||||||
|
* free func when creating the #GPtrArray.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
fpi_sdcp_device_list_complete (FpSdcpDevice *self,
|
||||||
|
GPtrArray *ids,
|
||||||
|
GError *error)
|
||||||
|
{
|
||||||
|
g_autoptr(GPtrArray) prints = NULL;
|
||||||
|
gint prints_len = 0;
|
||||||
|
FpiDeviceAction action;
|
||||||
|
|
||||||
|
action = fpi_device_get_current_action (FP_DEVICE (self));
|
||||||
|
|
||||||
|
g_return_if_fail (action == FPI_DEVICE_ACTION_LIST);
|
||||||
|
|
||||||
|
if (error)
|
||||||
|
{
|
||||||
|
fpi_device_list_complete (FP_DEVICE (self), NULL, error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
prints = g_ptr_array_new_with_free_func (g_object_unref);
|
||||||
|
|
||||||
|
/* Allow an empty array (prints_len=0) but if ids has been passed, use it */
|
||||||
|
if (ids)
|
||||||
|
prints_len = ids->len;
|
||||||
|
|
||||||
|
for (gint i = 0; i < prints_len; i++)
|
||||||
|
{
|
||||||
|
FpPrint *print = fp_print_new (FP_DEVICE (self));
|
||||||
|
fpi_print_set_type (print, FPI_PRINT_SDCP);
|
||||||
|
fpi_print_set_device_stored (print, FALSE);
|
||||||
|
fpi_sdcp_device_set_print_id (print, g_ptr_array_index (ids, i));
|
||||||
|
g_ptr_array_add (prints, g_object_ref_sink (print));
|
||||||
|
}
|
||||||
|
|
||||||
|
fpi_device_list_complete (FP_DEVICE (self), g_steal_pointer (&prints), NULL);
|
||||||
|
|
||||||
|
g_clear_pointer (&ids, g_ptr_array_unref);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fpi_sdcp_device_enroll_commit:
|
||||||
|
* @self: a #FpSdcpDevice fingerprint device
|
||||||
|
* @nonce: The device generated nonce
|
||||||
|
* @error: a #GError or %NULL on success
|
||||||
|
*
|
||||||
|
* Called when the print is ready to be committed to device memory.
|
||||||
|
* During enrollment, fpi_device_enroll_progress() must be called for each
|
||||||
|
* successful stage before the print can be committed.
|
||||||
|
* The @nonce generated by the device-specific EnrollmentNonce response must be
|
||||||
|
* provided in order for the enrollment ID to be generated.
|
||||||
|
* The driver's enroll_commit() vfunc will be triggered upon successfully
|
||||||
|
* generating the enrollment ID.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
fpi_sdcp_device_enroll_commit (FpSdcpDevice *self,
|
||||||
|
GBytes *nonce,
|
||||||
|
GError *error)
|
||||||
|
{
|
||||||
|
FpSdcpDeviceClass *cls = FP_SDCP_DEVICE_GET_CLASS (self);
|
||||||
|
|
||||||
|
g_autoptr(GBytes) application_secret = NULL;
|
||||||
|
GBytes *id = NULL;
|
||||||
|
FpPrint *print;
|
||||||
|
|
||||||
|
g_return_if_fail (FP_IS_SDCP_DEVICE (self));
|
||||||
|
g_return_if_fail (fpi_device_get_current_action (FP_DEVICE (self)) == FPI_DEVICE_ACTION_ENROLL);
|
||||||
|
g_return_if_fail (nonce != NULL);
|
||||||
|
|
||||||
|
fpi_device_get_enroll_data (FP_DEVICE (self), &print);
|
||||||
|
fpi_sdcp_device_get_application_secret (self, &application_secret);
|
||||||
|
|
||||||
|
id = fpi_sdcp_generate_enrollment_id (application_secret, nonce, &error);
|
||||||
|
if (!id || error)
|
||||||
|
{
|
||||||
|
fp_warn ("Could not generate SDCP enrollment ID");
|
||||||
|
fpi_device_enroll_complete (FP_DEVICE (self), NULL, error);
|
||||||
|
g_object_set (print, "fpi-data", NULL, NULL);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set to true once committed */
|
||||||
|
fpi_print_set_device_stored (print, FALSE);
|
||||||
|
|
||||||
|
/* Attach the ID to the print */
|
||||||
|
fpi_sdcp_device_set_print_id (print, id);
|
||||||
|
|
||||||
|
cls->enroll_commit (self, id);
|
||||||
|
|
||||||
|
g_clear_pointer (&id, g_bytes_unref);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fpi_sdcp_device_enroll_commit_complete:
|
||||||
|
* @self: a #FpSdcpDevice fingerprint device
|
||||||
|
* @error: a #GError or %NULL on success
|
||||||
|
*
|
||||||
|
* Called when device has committed the given print to memory.
|
||||||
|
* This finalizes the enroll operation.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
fpi_sdcp_device_enroll_commit_complete (FpSdcpDevice *self,
|
||||||
|
GError *error)
|
||||||
|
{
|
||||||
|
g_autoptr(GBytes) id = NULL;
|
||||||
|
FpPrint *print;
|
||||||
|
|
||||||
|
g_return_if_fail (FP_IS_SDCP_DEVICE (self));
|
||||||
|
g_return_if_fail (fpi_device_get_current_action (FP_DEVICE (self)) == FPI_DEVICE_ACTION_ENROLL);
|
||||||
|
|
||||||
|
if (error)
|
||||||
|
{
|
||||||
|
fpi_device_enroll_complete (FP_DEVICE (self), NULL, error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
fpi_device_get_enroll_data (FP_DEVICE (self), &print);
|
||||||
|
|
||||||
|
fpi_sdcp_device_get_print_id (print, &id);
|
||||||
|
if (!id)
|
||||||
|
{
|
||||||
|
g_error ("Inconsistent state; the print must have the enrolled ID attached at this point");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
fpi_print_set_type (print, FPI_PRINT_SDCP);
|
||||||
|
fpi_print_set_device_stored (print, TRUE);
|
||||||
|
|
||||||
|
fpi_device_enroll_complete (FP_DEVICE (self), g_object_ref (print), NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fpi_sdcp_device_identify_retry:
|
||||||
|
* @self: a #FpSdcpDevice fingerprint device
|
||||||
|
* @error: a #GError containing the retry condition
|
||||||
|
*
|
||||||
|
* Called when the device requires the finger to be presented again.
|
||||||
|
* This should not be called for a verified no-match, it should only
|
||||||
|
* be called if e.g. the finger was not centered properly or similar.
|
||||||
|
*
|
||||||
|
* Effectively this simply raises the error up. This function exists
|
||||||
|
* to bridge the difference in semantics that SDPC has from how
|
||||||
|
* libfprint works internally.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
fpi_sdcp_device_identify_retry (FpSdcpDevice *self,
|
||||||
|
GError *error)
|
||||||
|
{
|
||||||
|
FpiDeviceAction action;
|
||||||
|
|
||||||
|
g_return_if_fail (FP_IS_SDCP_DEVICE (self));
|
||||||
|
action = fpi_device_get_current_action (FP_DEVICE (self));
|
||||||
|
|
||||||
|
g_return_if_fail (action == FPI_DEVICE_ACTION_IDENTIFY || action == FPI_DEVICE_ACTION_VERIFY);
|
||||||
|
|
||||||
|
if (action == FPI_DEVICE_ACTION_VERIFY)
|
||||||
|
fpi_device_verify_report (FP_DEVICE (self), FPI_MATCH_ERROR, NULL, error);
|
||||||
|
else if (action == FPI_DEVICE_ACTION_IDENTIFY)
|
||||||
|
fpi_device_identify_report (FP_DEVICE (self), NULL, NULL, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fpi_sdcp_device_identify_complete:
|
||||||
|
* @self: a #FpSdcpDevice fingerprint device
|
||||||
|
* @id: (transfer none): the ID as reported by the device
|
||||||
|
* @mac: (transfer none): MAC authenticating the message
|
||||||
|
* @error: (transfer full): #GError if an error occured
|
||||||
|
*
|
||||||
|
* Called when device is done with the identification routine. The
|
||||||
|
* returned ID may be %NULL if none of the in-device templates matched.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
fpi_sdcp_device_identify_complete (FpSdcpDevice *self,
|
||||||
|
GBytes *id,
|
||||||
|
GBytes *mac,
|
||||||
|
GError *error)
|
||||||
|
{
|
||||||
|
FpSdcpDevicePrivate *priv = fp_sdcp_device_get_instance_private (self);
|
||||||
|
|
||||||
|
g_autoptr(GBytes) application_secret = NULL;
|
||||||
|
FpPrint *identified_print;
|
||||||
|
FpiDeviceAction action;
|
||||||
|
|
||||||
|
g_return_if_fail (FP_IS_SDCP_DEVICE (self));
|
||||||
|
action = fpi_device_get_current_action (FP_DEVICE (self));
|
||||||
|
|
||||||
|
g_return_if_fail (action == FPI_DEVICE_ACTION_IDENTIFY || action == FPI_DEVICE_ACTION_VERIFY);
|
||||||
|
g_return_if_fail (priv->identify_nonce);
|
||||||
|
|
||||||
|
if (error)
|
||||||
|
{
|
||||||
|
g_clear_pointer (&priv->identify_nonce, g_bytes_unref);
|
||||||
|
fpi_device_action_error (FP_DEVICE (self), error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* No error and no valid id/mac provided means that there was no match from the device */
|
||||||
|
if (!id || !mac || g_bytes_get_size (id) != SDCP_ENROLLMENT_ID_SIZE ||
|
||||||
|
g_bytes_get_size (mac) != SDCP_MAC_SIZE)
|
||||||
|
{
|
||||||
|
g_clear_pointer (&priv->identify_nonce, g_bytes_unref);
|
||||||
|
if (action == FPI_DEVICE_ACTION_VERIFY)
|
||||||
|
{
|
||||||
|
fpi_device_verify_report (FP_DEVICE (self), FPI_MATCH_FAIL, NULL, NULL);
|
||||||
|
fpi_device_verify_complete (FP_DEVICE (self), NULL);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fpi_device_identify_report (FP_DEVICE (self), NULL, NULL, NULL);
|
||||||
|
fpi_device_identify_complete (FP_DEVICE (self), NULL);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
fpi_sdcp_device_get_application_secret (self, &application_secret);
|
||||||
|
|
||||||
|
if (!fpi_sdcp_verify_identify (application_secret, priv->identify_nonce, id, mac, &error))
|
||||||
|
{
|
||||||
|
g_clear_pointer (&priv->identify_nonce, g_bytes_unref);
|
||||||
|
fpi_device_action_error (FP_DEVICE (self), error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Clear no longer needed private data */
|
||||||
|
g_clear_pointer (&priv->identify_nonce, g_bytes_unref);
|
||||||
|
|
||||||
|
/* Create a new print */
|
||||||
|
identified_print = fp_print_new (FP_DEVICE (self));
|
||||||
|
|
||||||
|
fpi_print_set_type (identified_print, FPI_PRINT_SDCP);
|
||||||
|
|
||||||
|
/* Set to true once committed */
|
||||||
|
fpi_print_set_device_stored (identified_print, FALSE);
|
||||||
|
|
||||||
|
/* Attach the ID to the print */
|
||||||
|
fpi_sdcp_device_set_print_id (identified_print, id);
|
||||||
|
|
||||||
|
|
||||||
|
/* The surrounding API expects a match/no-match against a given set. */
|
||||||
|
if (action == FPI_DEVICE_ACTION_VERIFY)
|
||||||
|
{
|
||||||
|
FpPrint *print;
|
||||||
|
|
||||||
|
fpi_device_get_verify_data (FP_DEVICE (self), &print);
|
||||||
|
|
||||||
|
if (fp_print_equal (print, identified_print))
|
||||||
|
fpi_device_verify_report (FP_DEVICE (self), FPI_MATCH_SUCCESS, identified_print, NULL);
|
||||||
|
else
|
||||||
|
fpi_device_verify_report (FP_DEVICE (self), FPI_MATCH_FAIL, identified_print, NULL);
|
||||||
|
|
||||||
|
fpi_device_verify_complete (FP_DEVICE (self), NULL);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GPtrArray *prints;
|
||||||
|
gint i;
|
||||||
|
|
||||||
|
fpi_device_get_identify_data (FP_DEVICE (self), &prints);
|
||||||
|
|
||||||
|
for (i = 0; i < prints->len; i++)
|
||||||
|
{
|
||||||
|
FpPrint *print = g_ptr_array_index (prints, i);
|
||||||
|
|
||||||
|
if (fp_print_equal (print, identified_print))
|
||||||
|
{
|
||||||
|
fpi_device_identify_report (FP_DEVICE (self), print, identified_print, NULL);
|
||||||
|
fpi_device_identify_complete (FP_DEVICE (self), NULL);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Print wasn't in database. */
|
||||||
|
fpi_device_identify_report (FP_DEVICE (self), NULL, identified_print, NULL);
|
||||||
|
fpi_device_identify_complete (FP_DEVICE (self), NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fpi_sdcp_device_get_print_id:
|
||||||
|
* @print: an SDCP device #FpPrint
|
||||||
|
* @id: (out) (transfer full): the ID gotten from the @print data
|
||||||
|
*
|
||||||
|
* Gets the SDCP enrollment ID from the @print data.
|
||||||
|
*
|
||||||
|
* The returned @id may be %NULL if the data was not set or in the wrong format.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
fpi_sdcp_device_get_print_id (FpPrint *print,
|
||||||
|
GBytes **id)
|
||||||
|
{
|
||||||
|
g_autoptr(GVariant) id_var = NULL;
|
||||||
|
g_autoptr(GVariant) data = NULL;
|
||||||
|
const guint8 *id_data;
|
||||||
|
gsize id_len;
|
||||||
|
|
||||||
|
g_return_if_fail (print);
|
||||||
|
g_return_if_fail (*id == NULL);
|
||||||
|
|
||||||
|
g_object_get (G_OBJECT (print), "fpi-data", &data, NULL);
|
||||||
|
|
||||||
|
if (!data)
|
||||||
|
{
|
||||||
|
fp_warn ("SDCP print data has not been set.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!g_variant_check_format_string (data, "(@ay)", FALSE))
|
||||||
|
{
|
||||||
|
fp_warn ("SDCP print data is not in expected format.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_variant_get (data, "(@ay)", &id_var);
|
||||||
|
|
||||||
|
id_data = g_variant_get_fixed_array (id_var, &id_len, sizeof (guint8));
|
||||||
|
|
||||||
|
*id = g_bytes_new (id_data, id_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fpi_sdcp_device_set_print_id:
|
||||||
|
* @print: an SDCP device #FpPrint
|
||||||
|
* @id: the ID to set in the @print data
|
||||||
|
*
|
||||||
|
* Sets the SDCP enrollment ID in the @print data.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
fpi_sdcp_device_set_print_id (FpPrint *print,
|
||||||
|
GBytes *id)
|
||||||
|
{
|
||||||
|
GVariant *id_var;
|
||||||
|
GVariant *data;
|
||||||
|
|
||||||
|
g_return_if_fail (print);
|
||||||
|
g_return_if_fail (id);
|
||||||
|
|
||||||
|
id_var = g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE,
|
||||||
|
g_bytes_get_data (id, NULL),
|
||||||
|
g_bytes_get_size (id),
|
||||||
|
1);
|
||||||
|
data = g_variant_new ("(@ay)", id_var);
|
||||||
|
|
||||||
|
g_object_set (G_OBJECT (print), "fpi-data", data, NULL);
|
||||||
|
}
|
||||||
185
libfprint/fpi-sdcp-device.h
Normal file
185
libfprint/fpi-sdcp-device.h
Normal file
@@ -0,0 +1,185 @@
|
|||||||
|
/*
|
||||||
|
* FpSdcpDevice - A base class for SDCP enabled devices
|
||||||
|
* Copyright (C) 2020 Benjamin Berg <bberg@redhat.com>
|
||||||
|
* Copyright (C) 2025 Joshua Grisham <josh@joshuagrisham.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 "fp-sdcp-device.h"
|
||||||
|
|
||||||
|
#define SDCP_PUBLIC_KEY_SIZE 65
|
||||||
|
#define SDCP_APPLICATION_SECRET_SIZE 32
|
||||||
|
#define SDCP_RANDOM_SIZE 32
|
||||||
|
#define SDCP_MAC_SIZE 32
|
||||||
|
#define SDCP_NONCE_SIZE 32
|
||||||
|
#define SDCP_ENROLLMENT_ID_SIZE 32
|
||||||
|
#define SDCP_SIGNATURE_SIZE 64
|
||||||
|
|
||||||
|
/**
|
||||||
|
* FpiSdcpClaim:
|
||||||
|
* @model_certificate: Microsoft-issued per-model certificate encoded in x509
|
||||||
|
* ASN.1 DER format (`cert_m`)
|
||||||
|
* @device_public_key: The per-device ECDSA public key (`pk_d`)
|
||||||
|
* @firmware_public_key: The ephemeral public key generated by the device
|
||||||
|
* firmware (`pk_f`)
|
||||||
|
* @firmware_hash: Hash of the firmware and firmware public key (`h_f`)
|
||||||
|
* @model_signature: Device public key signed by the model key (`s_m`)
|
||||||
|
* @device_signature: Firmware hash and public key signed by the device private
|
||||||
|
* key (`s_d`)
|
||||||
|
*
|
||||||
|
* Structure to hold the claim as produced by the device during a secure
|
||||||
|
* connect. See the SDCP specification for more details.
|
||||||
|
*
|
||||||
|
* Note all of these may simply be memory views into a larger #GBytes created
|
||||||
|
* using g_bytes_new_from_bytes().
|
||||||
|
*/
|
||||||
|
struct _FpiSdcpClaim
|
||||||
|
{
|
||||||
|
/*< public >*/
|
||||||
|
GBytes *model_certificate; /* cert_m */
|
||||||
|
GBytes *device_public_key; /* pk_d */
|
||||||
|
GBytes *firmware_public_key; /* pk_f */
|
||||||
|
GBytes *firmware_hash; /* h_f */
|
||||||
|
GBytes *model_signature; /* s_m */
|
||||||
|
GBytes *device_signature; /* s_d */
|
||||||
|
};
|
||||||
|
typedef struct _FpiSdcpClaim FpiSdcpClaim;
|
||||||
|
|
||||||
|
GType fpi_sdcp_claim_get_type (void) G_GNUC_CONST;
|
||||||
|
FpiSdcpClaim *fpi_sdcp_claim_new (void);
|
||||||
|
FpiSdcpClaim *fpi_sdcp_claim_copy (FpiSdcpClaim *other);
|
||||||
|
void fpi_sdcp_claim_free (FpiSdcpClaim *claim);
|
||||||
|
|
||||||
|
G_DEFINE_AUTOPTR_CLEANUP_FUNC (FpiSdcpClaim, fpi_sdcp_claim_free)
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* FpSdcpDeviceClass:
|
||||||
|
* @ignore_device_certificate: Set to %TRUE to skip validating the device's
|
||||||
|
* #FpiSdcpClaim.model_certificate against the SDCP truststore.
|
||||||
|
* @ignore_device_signatures: Set to %TRUE to skip verifying the device's
|
||||||
|
* #FpiSdcpClaim.model_signature and #FpiSdcpClaim.device_signature.
|
||||||
|
* @open: Open the device. Similar to #FpDeviceClass.open except that
|
||||||
|
* completion with fpi_sdcp_device_open_complete() will also take care of
|
||||||
|
* executing @connect and @reconnect as necessary.
|
||||||
|
* @connect: Establish SDCP connection.
|
||||||
|
* @reconnect: Perform a faster reconnect. Drivers do not need to provide this
|
||||||
|
* function. If reconnect fails, then a normal connect will be tried.
|
||||||
|
* @list: List prints stored on the device. The driver must create a #GPtrArray
|
||||||
|
* of #GBytes with each enrollment ID stored on the device and use it to call
|
||||||
|
* fpi_sdcp_device_list_complete() in order to complete the operation.
|
||||||
|
* @enroll: Start the enrollment procedure and capture all samples. The driver
|
||||||
|
* must report enrollment progress using fpi_device_enroll_progress(). It
|
||||||
|
* should also store available metadata about the print in device memory. The
|
||||||
|
* driver must call fpi_sdcp_device_enroll_commit() when all enrollment stages
|
||||||
|
* are complete and the print is ready to be commited to the device.
|
||||||
|
* @enroll_commit: Commit the newly-enrolled print to the device memory using
|
||||||
|
* the passed id. id may be %NULL, in which case the driver must abort the
|
||||||
|
* enrollment process. id is owned by the base class and remains valid
|
||||||
|
* throughout the operation. On completion, the driver must call
|
||||||
|
* fpi_sdcp_device_enroll_commit_complete().
|
||||||
|
* @identify: Start identification process. On completion, the driver must call
|
||||||
|
* fpi_sdcp_device_identify_complete(). To request the user to retry the
|
||||||
|
* fpi_sdcp_device_identify_retry() function is used.
|
||||||
|
*
|
||||||
|
* These are the main entry points for drivers implementing SDCP.
|
||||||
|
*
|
||||||
|
* Drivers *must* eventually call the corresponding function to finish the
|
||||||
|
* operation.
|
||||||
|
*
|
||||||
|
* The following #FpDeviceClass entry points are also compatible and can be set
|
||||||
|
* on the #FpDeviceClass if supported for a given device:
|
||||||
|
* - #FpDeviceClass.probe
|
||||||
|
* - #FpDeviceClass.close
|
||||||
|
* - #FpDeviceClass.delete
|
||||||
|
* - #FpDeviceClass.clear_storage
|
||||||
|
* - #FpDeviceClass.cancel
|
||||||
|
* - #FpDeviceClass.suspend
|
||||||
|
* - #FpDeviceClass.resume
|
||||||
|
*
|
||||||
|
* XXX: Is the use of fpi_device_action_error() acceptable?
|
||||||
|
*
|
||||||
|
* Drivers *must* also handle cancellation properly for any long running
|
||||||
|
* operation (i.e. any operation that requires capturing). It is entirely fine
|
||||||
|
* to ignore cancellation requests for short operations (e.g. open/close).
|
||||||
|
*
|
||||||
|
* This API is solely intended for drivers. It is purely internal and neither
|
||||||
|
* API nor ABI stable.
|
||||||
|
*/
|
||||||
|
struct _FpSdcpDeviceClass
|
||||||
|
{
|
||||||
|
FpDeviceClass parent_class;
|
||||||
|
|
||||||
|
gboolean ignore_device_certificate;
|
||||||
|
gboolean ignore_device_signatures;
|
||||||
|
|
||||||
|
void (*open) (FpSdcpDevice *sdcp_device);
|
||||||
|
void (*connect) (FpSdcpDevice *sdcp_device);
|
||||||
|
void (*reconnect) (FpSdcpDevice *sdcp_device);
|
||||||
|
void (*list) (FpSdcpDevice *sdcp_device);
|
||||||
|
void (*enroll) (FpSdcpDevice *sdcp_device);
|
||||||
|
void (*enroll_commit) (FpSdcpDevice *sdcp_device,
|
||||||
|
GBytes *id);
|
||||||
|
void (*identify) (FpSdcpDevice *sdcp_device);
|
||||||
|
};
|
||||||
|
|
||||||
|
void fpi_sdcp_device_open_complete (FpSdcpDevice *self,
|
||||||
|
GError *error);
|
||||||
|
|
||||||
|
void fpi_sdcp_device_get_connect_data (FpSdcpDevice *self,
|
||||||
|
GBytes **host_random,
|
||||||
|
GBytes **host_public_key);
|
||||||
|
void fpi_sdcp_device_connect_complete (FpSdcpDevice *self,
|
||||||
|
GBytes *device_random,
|
||||||
|
FpiSdcpClaim *claim,
|
||||||
|
GBytes *mac,
|
||||||
|
GError *error);
|
||||||
|
|
||||||
|
void fpi_sdcp_device_get_reconnect_data (FpSdcpDevice *self,
|
||||||
|
GBytes **reconnect_random);
|
||||||
|
void fpi_sdcp_device_reconnect_complete (FpSdcpDevice *self,
|
||||||
|
GBytes *mac,
|
||||||
|
GError *error);
|
||||||
|
|
||||||
|
void fpi_sdcp_device_list_complete (FpSdcpDevice *self,
|
||||||
|
GPtrArray *ids,
|
||||||
|
GError *error);
|
||||||
|
|
||||||
|
void fpi_sdcp_device_enroll_commit (FpSdcpDevice *self,
|
||||||
|
GBytes *nonce,
|
||||||
|
GError *error);
|
||||||
|
void fpi_sdcp_device_enroll_commit_complete (FpSdcpDevice *self,
|
||||||
|
GError *error);
|
||||||
|
|
||||||
|
void fpi_sdcp_device_get_identify_data (FpSdcpDevice *self,
|
||||||
|
GBytes **nonce);
|
||||||
|
void fpi_sdcp_device_set_identify_data (FpSdcpDevice *self,
|
||||||
|
GBytes *nonce);
|
||||||
|
void fpi_sdcp_device_identify_retry (FpSdcpDevice *self,
|
||||||
|
GError *error);
|
||||||
|
void fpi_sdcp_device_identify_complete (FpSdcpDevice *self,
|
||||||
|
GBytes *id,
|
||||||
|
GBytes *mac,
|
||||||
|
GError *error);
|
||||||
|
|
||||||
|
void fpi_sdcp_device_get_print_id (FpPrint *print,
|
||||||
|
GBytes **id);
|
||||||
|
void fpi_sdcp_device_set_print_id (FpPrint *print,
|
||||||
|
GBytes *id);
|
||||||
1079
libfprint/fpi-sdcp.c
Normal file
1079
libfprint/fpi-sdcp.c
Normal file
File diff suppressed because it is too large
Load Diff
132
libfprint/fpi-sdcp.h
Normal file
132
libfprint/fpi-sdcp.h
Normal file
@@ -0,0 +1,132 @@
|
|||||||
|
/*
|
||||||
|
* Secure Device Connection Protocol (SDCP) support implementation
|
||||||
|
* Copyright (C) 2025 Joshua Grisham <josh@joshuagrisham.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-compat.h"
|
||||||
|
|
||||||
|
#include "fpi-sdcp-device.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fpi_sdcp_generate_host_key:
|
||||||
|
* @private_key: (out) (transfer full): The host private key (sk_h)
|
||||||
|
* @public_key: (out) (transfer full): The host public key (pk_h)
|
||||||
|
* @error: (out): #GError in case the out values are %NULL
|
||||||
|
*
|
||||||
|
* Function to generate a new ephemeral ECDH key pair for use with SDCP.
|
||||||
|
**/
|
||||||
|
void fpi_sdcp_generate_host_key (GBytes **private_key,
|
||||||
|
GBytes **public_key,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fpi_sdcp_generate_random:
|
||||||
|
* @error: (out): #GError in case the return value is %NULL
|
||||||
|
*
|
||||||
|
* Returns: A new #GBytes with a secure random of length %SDCP_RANDOM_SIZE
|
||||||
|
**/
|
||||||
|
GBytes *fpi_sdcp_generate_random (GError **error);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fpi_sdcp_verify_connect:
|
||||||
|
* @host_private_key: Private key generated using fpi_sdcp_generate_host_key() (sk_h)
|
||||||
|
* @host_random: Random generated using fpi_sdcp_generate_random() (r_h)
|
||||||
|
* @device_random: The random provided in the device's ConnectResponse (r_d)
|
||||||
|
* @claim: #FpiSdcpClaim provided in the device's ConnectResponse (c)
|
||||||
|
* @mac: The MAC provided in the device's ConnectResponse (m)
|
||||||
|
* @validate_certificate: If the model certificate (cert_m) should be parsed and
|
||||||
|
* its trust chain validated as issued from Microsoft's well-known issuers
|
||||||
|
* @verify_signatures: If the model signature (s_m) and device signature (s_d)
|
||||||
|
* should be validated against the certificate and keys provided in the claim
|
||||||
|
* @application_secret: (out) (transfer full): A new #GBytes with the derived
|
||||||
|
* application secret (s) of length %SDCP_APPLICATION_SECRET_SIZE
|
||||||
|
* @error: (out): #GError in case the return value is %NULL
|
||||||
|
*
|
||||||
|
* High level function which internally handles the derivation of all necessary
|
||||||
|
* SDCP-related keys and secrets from the device's ConnectResponse and derives
|
||||||
|
* the application secret for use with all other SDCP-related functions.
|
||||||
|
*
|
||||||
|
* This function will also perform a validation of the ConnectResponse MAC and
|
||||||
|
* optionally perform additional verifications based on the provided
|
||||||
|
* @validate_certificate and @verify_signatures booleans. If any of these these
|
||||||
|
* validations fail then %NULL will be returned, indicating that the SDCP secure
|
||||||
|
* connection channel could not be established.
|
||||||
|
*
|
||||||
|
* Returns: %TRUE if the @application_secret was successfully derived and the
|
||||||
|
* ConnectResponse has been successfully verified
|
||||||
|
**/
|
||||||
|
gboolean fpi_sdcp_verify_connect (GBytes *host_private_key,
|
||||||
|
GBytes *host_random,
|
||||||
|
GBytes *device_random,
|
||||||
|
FpiSdcpClaim *claim,
|
||||||
|
GBytes *mac,
|
||||||
|
gboolean validate_certificate,
|
||||||
|
gboolean verify_signatures,
|
||||||
|
GBytes **application_secret,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fpi_sdcp_verify_reconnect:
|
||||||
|
* @application_secret: The host's derived application secret (s)
|
||||||
|
* @random: The host-generated random sent to the device's Reconnect command (r)
|
||||||
|
* @mac: The MAC provided in the device's ReconnectResponse (m)
|
||||||
|
* @error: (out): #GError in case the return value is %FALSE
|
||||||
|
*
|
||||||
|
* Verifies the SDCP ReconnectResponse.
|
||||||
|
*
|
||||||
|
* Returns: %TRUE if the ReconnectResponse is verified successfully
|
||||||
|
**/
|
||||||
|
gboolean fpi_sdcp_verify_reconnect (GBytes *application_secret,
|
||||||
|
GBytes *random,
|
||||||
|
GBytes *mac,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fpi_sdcp_verify_identify:
|
||||||
|
* @application_secret: The host's derived application secret (s)
|
||||||
|
* @nonce: The host-generated nonce sent to the device's Identify command (n)
|
||||||
|
* @id: The ID provided in the device's AuthorizedIdentity (id)
|
||||||
|
* @mac: The MAC provided in the device's AuthorizedIdentity (m)
|
||||||
|
* @error: (out): #GError in case the return value is %FALSE
|
||||||
|
*
|
||||||
|
* Verifies the SDCP ReconnectResponse.
|
||||||
|
*
|
||||||
|
* Returns: %TRUE if the ReconnectResponse is verified successfully
|
||||||
|
**/
|
||||||
|
gboolean fpi_sdcp_verify_identify (GBytes *application_secret,
|
||||||
|
GBytes *nonce,
|
||||||
|
GBytes *id,
|
||||||
|
GBytes *mac,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fpi_sdcp_generate_enrollment_id:
|
||||||
|
* @application_secret: The host's derived application secret (s)
|
||||||
|
* @nonce: The nonce received from the device in response to the EnrollBegin
|
||||||
|
* command (n)
|
||||||
|
* @error: (out): #GError in case the return value is %NULL
|
||||||
|
*
|
||||||
|
* Generates a new id for use with the device's EnrollCommit command.
|
||||||
|
*
|
||||||
|
* Returns: A new #GBytes with the generated enrollment id of length
|
||||||
|
* %SDCP_ENROLLMENT_ID_SIZE
|
||||||
|
**/
|
||||||
|
GBytes *fpi_sdcp_generate_enrollment_id (GBytes *application_secret,
|
||||||
|
GBytes *nonce,
|
||||||
|
GError **error);
|
||||||
@@ -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;
|
||||||
|
|||||||
107
libfprint/fprint-list-metainfo.c
Normal file
107
libfprint/fprint-list-metainfo.c
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
/*
|
||||||
|
* 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/-/issues</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_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,11 +24,15 @@
|
|||||||
#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 generate this list from the wiki page using e.g.:
|
||||||
* gio cat https://gitlab.freedesktop.org/libfprint/wiki/-/wikis/Unsupported-Devices.md | sed -n 's!|.*\([0-9a-fA-F]\{4\}\):\([0-9a-fA-F]\{4\}\).*|.*! { .vid = 0x\1, .pid = 0x\2 },!p'
|
* 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'
|
||||||
*/
|
*/
|
||||||
|
{ .vid = 0x0a5c, .pid = 0x5802 },
|
||||||
|
{ .vid = 0x047d, .pid = 0x00f2 },
|
||||||
|
{ .vid = 0x047d, .pid = 0x8054 },
|
||||||
|
{ .vid = 0x047d, .pid = 0x8055 },
|
||||||
{ .vid = 0x04e8, .pid = 0x730b },
|
{ .vid = 0x04e8, .pid = 0x730b },
|
||||||
{ .vid = 0x04f3, .pid = 0x036b },
|
{ .vid = 0x04f3, .pid = 0x036b },
|
||||||
{ .vid = 0x04f3, .pid = 0x0c00 },
|
{ .vid = 0x04f3, .pid = 0x0c00 },
|
||||||
@@ -36,12 +40,25 @@ static const FpIdEntry whitelist_id_table[] = {
|
|||||||
{ .vid = 0x04f3, .pid = 0x0c57 },
|
{ .vid = 0x04f3, .pid = 0x0c57 },
|
||||||
{ .vid = 0x04f3, .pid = 0x0c5e },
|
{ .vid = 0x04f3, .pid = 0x0c5e },
|
||||||
{ .vid = 0x04f3, .pid = 0x0c5a },
|
{ .vid = 0x04f3, .pid = 0x0c5a },
|
||||||
|
{ .vid = 0x04f3, .pid = 0x0c60 },
|
||||||
|
{ .vid = 0x04f3, .pid = 0x0c6c },
|
||||||
{ .vid = 0x04f3, .pid = 0x0c70 },
|
{ .vid = 0x04f3, .pid = 0x0c70 },
|
||||||
{ .vid = 0x04f3, .pid = 0x0c72 },
|
{ .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 = 0x0c90 },
|
||||||
{ .vid = 0x04f3, .pid = 0x2706 },
|
{ .vid = 0x04f3, .pid = 0x2706 },
|
||||||
|
{ .vid = 0x04f3, .pid = 0x3032 },
|
||||||
{ .vid = 0x04f3, .pid = 0x3057 },
|
{ .vid = 0x04f3, .pid = 0x3057 },
|
||||||
{ .vid = 0x04f3, .pid = 0x3104 },
|
{ .vid = 0x04f3, .pid = 0x3104 },
|
||||||
{ .vid = 0x04f3, .pid = 0x310d },
|
{ .vid = 0x04f3, .pid = 0x310d },
|
||||||
|
{ .vid = 0x04f3, .pid = 0x3128 },
|
||||||
|
{ .vid = 0x04f3, .pid = 0x0c8a },
|
||||||
|
{ .vid = 0x05ba, .pid = 0x000e },
|
||||||
|
{ .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 },
|
||||||
@@ -52,7 +69,6 @@ static const FpIdEntry whitelist_id_table[] = {
|
|||||||
{ .vid = 0x06cb, .pid = 0x00b7 },
|
{ .vid = 0x06cb, .pid = 0x00b7 },
|
||||||
{ .vid = 0x06cb, .pid = 0x00bb },
|
{ .vid = 0x06cb, .pid = 0x00bb },
|
||||||
{ .vid = 0x06cb, .pid = 0x00be },
|
{ .vid = 0x06cb, .pid = 0x00be },
|
||||||
{ .vid = 0x06cb, .pid = 0x00c4 },
|
|
||||||
{ .vid = 0x06cb, .pid = 0x00cb },
|
{ .vid = 0x06cb, .pid = 0x00cb },
|
||||||
{ .vid = 0x06cb, .pid = 0x00c9 },
|
{ .vid = 0x06cb, .pid = 0x00c9 },
|
||||||
{ .vid = 0x06cb, .pid = 0x00d8 },
|
{ .vid = 0x06cb, .pid = 0x00d8 },
|
||||||
@@ -62,6 +78,7 @@ static const FpIdEntry whitelist_id_table[] = {
|
|||||||
{ .vid = 0x06cb, .pid = 0x00e7 },
|
{ .vid = 0x06cb, .pid = 0x00e7 },
|
||||||
{ .vid = 0x06cb, .pid = 0x00e9 },
|
{ .vid = 0x06cb, .pid = 0x00e9 },
|
||||||
{ .vid = 0x06cb, .pid = 0x00fd },
|
{ .vid = 0x06cb, .pid = 0x00fd },
|
||||||
|
{ .vid = 0x06cb, .pid = 0x00ff },
|
||||||
{ .vid = 0x0a5c, .pid = 0x5801 },
|
{ .vid = 0x0a5c, .pid = 0x5801 },
|
||||||
{ .vid = 0x0a5c, .pid = 0x5805 },
|
{ .vid = 0x0a5c, .pid = 0x5805 },
|
||||||
{ .vid = 0x0a5c, .pid = 0x5834 },
|
{ .vid = 0x0a5c, .pid = 0x5834 },
|
||||||
@@ -71,10 +88,19 @@ 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 = 0x5812 },
|
{ .vid = 0x0bda, .pid = 0x5812 },
|
||||||
{ .vid = 0x10a5, .pid = 0x0007 },
|
{ .vid = 0x10a5, .pid = 0x0007 },
|
||||||
{ .vid = 0x10a5, .pid = 0x9200 },
|
{ .vid = 0x10a5, .pid = 0x9200 },
|
||||||
{ .vid = 0x10a5, .pid = 0x9800 },
|
{ .vid = 0x10a5, .pid = 0x9800 },
|
||||||
|
{ .vid = 0x10a5, .pid = 0xa120 },
|
||||||
|
{ .vid = 0x10a5, .pid = 0xa900 },
|
||||||
|
{ .vid = 0x10a5, .pid = 0xe340 },
|
||||||
{ .vid = 0x1188, .pid = 0x9545 },
|
{ .vid = 0x1188, .pid = 0x9545 },
|
||||||
{ .vid = 0x138a, .pid = 0x0007 },
|
{ .vid = 0x138a, .pid = 0x0007 },
|
||||||
{ .vid = 0x138a, .pid = 0x003a },
|
{ .vid = 0x138a, .pid = 0x003a },
|
||||||
@@ -87,12 +113,18 @@ static const FpIdEntry whitelist_id_table[] = {
|
|||||||
{ .vid = 0x138a, .pid = 0x0097 },
|
{ .vid = 0x138a, .pid = 0x0097 },
|
||||||
{ .vid = 0x138a, .pid = 0x009d },
|
{ .vid = 0x138a, .pid = 0x009d },
|
||||||
{ .vid = 0x138a, .pid = 0x00ab },
|
{ .vid = 0x138a, .pid = 0x00ab },
|
||||||
|
{ .vid = 0x138a, .pid = 0x00a6 },
|
||||||
{ .vid = 0x147e, .pid = 0x1002 },
|
{ .vid = 0x147e, .pid = 0x1002 },
|
||||||
{ .vid = 0x1491, .pid = 0x0088 },
|
{ .vid = 0x1491, .pid = 0x0088 },
|
||||||
{ .vid = 0x16d1, .pid = 0x1027 },
|
{ .vid = 0x16d1, .pid = 0x1027 },
|
||||||
{ .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 = 0x0584 },
|
||||||
|
{ .vid = 0x1c7a, .pid = 0x0577 },
|
||||||
|
{ .vid = 0x1c7a, .pid = 0x057e },
|
||||||
|
{ .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 },
|
||||||
@@ -120,26 +152,34 @@ static const FpIdEntry whitelist_id_table[] = {
|
|||||||
{ .vid = 0x27c6, .pid = 0x5740 },
|
{ .vid = 0x27c6, .pid = 0x5740 },
|
||||||
{ .vid = 0x27c6, .pid = 0x5e0a },
|
{ .vid = 0x27c6, .pid = 0x5e0a },
|
||||||
{ .vid = 0x27c6, .pid = 0x581a },
|
{ .vid = 0x27c6, .pid = 0x581a },
|
||||||
|
{ .vid = 0x27c6, .pid = 0x589a },
|
||||||
|
{ .vid = 0x27c6, .pid = 0x5f10 },
|
||||||
|
{ .vid = 0x27c6, .pid = 0x6382 },
|
||||||
{ .vid = 0x2808, .pid = 0x9338 },
|
{ .vid = 0x2808, .pid = 0x9338 },
|
||||||
|
{ .vid = 0x2808, .pid = 0x9348 },
|
||||||
{ .vid = 0x2808, .pid = 0x93a9 },
|
{ .vid = 0x2808, .pid = 0x93a9 },
|
||||||
|
{ .vid = 0x2808, .pid = 0xa658 },
|
||||||
|
{ .vid = 0x2808, .pid = 0xc652 },
|
||||||
{ .vid = 0x298d, .pid = 0x2020 },
|
{ .vid = 0x298d, .pid = 0x2020 },
|
||||||
{ .vid = 0x298d, .pid = 0x2033 },
|
{ .vid = 0x298d, .pid = 0x2033 },
|
||||||
|
{ .vid = 0x2df0, .pid = 0x0003 },
|
||||||
|
{ .vid = 0x3274, .pid = 0x8012 },
|
||||||
{ .vid = 0x3538, .pid = 0x0930 },
|
{ .vid = 0x3538, .pid = 0x0930 },
|
||||||
{ .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;
|
||||||
@@ -158,7 +198,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;
|
||||||
|
|
||||||
@@ -169,7 +209,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);
|
||||||
@@ -180,7 +220,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");
|
||||||
@@ -234,7 +274,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);
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,11 @@
|
|||||||
|
spi_sources = []
|
||||||
|
spi_headers = []
|
||||||
|
|
||||||
|
if enabled_spi_drivers.length() > 0
|
||||||
|
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',
|
||||||
@@ -40,10 +48,9 @@ libfprint_private_headers = [
|
|||||||
'fpi-log.h',
|
'fpi-log.h',
|
||||||
'fpi-minutiae.h',
|
'fpi-minutiae.h',
|
||||||
'fpi-print.h',
|
'fpi-print.h',
|
||||||
'fpi-usb-transfer.h',
|
|
||||||
'fpi-spi-transfer.h',
|
|
||||||
'fpi-ssm.h',
|
'fpi-ssm.h',
|
||||||
]
|
'fpi-usb-transfer.h',
|
||||||
|
] + spi_headers
|
||||||
|
|
||||||
nbis_sources = [
|
nbis_sources = [
|
||||||
'nbis/bozorth3/bozorth3.c',
|
'nbis/bozorth3/bozorth3.c',
|
||||||
@@ -119,6 +126,8 @@ driver_sources = {
|
|||||||
[ 'drivers/etes603.c' ],
|
[ 'drivers/etes603.c' ],
|
||||||
'egis0570' :
|
'egis0570' :
|
||||||
[ 'drivers/egis0570.c' ],
|
[ 'drivers/egis0570.c' ],
|
||||||
|
'egismoc' :
|
||||||
|
[ 'drivers/egismoc/egismoc.c' ],
|
||||||
'vfs0050' :
|
'vfs0050' :
|
||||||
[ 'drivers/vfs0050.c' ],
|
[ 'drivers/vfs0050.c' ],
|
||||||
'elan' :
|
'elan' :
|
||||||
@@ -135,12 +144,18 @@ driver_sources = {
|
|||||||
[ 'drivers/virtual-device.c' ],
|
[ 'drivers/virtual-device.c' ],
|
||||||
'virtual_device_storage' :
|
'virtual_device_storage' :
|
||||||
[ 'drivers/virtual-device-storage.c' ],
|
[ 'drivers/virtual-device-storage.c' ],
|
||||||
|
'virtual_sdcp' :
|
||||||
|
[ 'drivers/virtual-sdcp.c' ],
|
||||||
'synaptics' :
|
'synaptics' :
|
||||||
[ 'drivers/synaptics/synaptics.c', 'drivers/synaptics/bmkt_message.c' ],
|
[ 'drivers/synaptics/synaptics.c', 'drivers/synaptics/bmkt_message.c' ],
|
||||||
'goodixmoc' :
|
'goodixmoc' :
|
||||||
[ 'drivers/goodixmoc/goodix.c', 'drivers/goodixmoc/goodix_proto.c' ],
|
[ 'drivers/goodixmoc/goodix.c', 'drivers/goodixmoc/goodix_proto.c' ],
|
||||||
'fpcmoc' :
|
'fpcmoc' :
|
||||||
[ 'drivers/fpcmoc/fpc.c' ],
|
[ 'drivers/fpcmoc/fpc.c' ],
|
||||||
|
'realtek' :
|
||||||
|
[ 'drivers/realtek/realtek.c' ],
|
||||||
|
'focaltech_moc' :
|
||||||
|
[ 'drivers/focaltech_moc/focaltech_moc.c' ],
|
||||||
}
|
}
|
||||||
|
|
||||||
helper_sources = {
|
helper_sources = {
|
||||||
@@ -150,7 +165,9 @@ helper_sources = {
|
|||||||
[ 'drivers/aesx660.c' ],
|
[ 'drivers/aesx660.c' ],
|
||||||
'aes3k' :
|
'aes3k' :
|
||||||
[ 'drivers/aes3k.c' ],
|
[ 'drivers/aes3k.c' ],
|
||||||
'nss' :
|
'openssl' :
|
||||||
|
[ ],
|
||||||
|
'sdcp' :
|
||||||
[ ],
|
[ ],
|
||||||
'udev' :
|
'udev' :
|
||||||
[ ],
|
[ ],
|
||||||
@@ -167,6 +184,24 @@ foreach helper : driver_helpers
|
|||||||
drivers_sources += helper_sources[helper]
|
drivers_sources += helper_sources[helper]
|
||||||
endforeach
|
endforeach
|
||||||
|
|
||||||
|
subdir('sdcp')
|
||||||
|
if 'sdcp' in driver_helpers
|
||||||
|
libfprint_sources += [
|
||||||
|
'fp-sdcp-device.c',
|
||||||
|
]
|
||||||
|
libfprint_private_sources += [
|
||||||
|
'fpi-sdcp.c',
|
||||||
|
'fpi-sdcp-device.c',
|
||||||
|
sdcp_truststore_resource_c,
|
||||||
|
]
|
||||||
|
libfprint_public_headers += [
|
||||||
|
'fp-sdcp-device.h',
|
||||||
|
]
|
||||||
|
libfprint_private_headers += [
|
||||||
|
'fpi-sdcp.h',
|
||||||
|
'fpi-sdcp-device.h',
|
||||||
|
]
|
||||||
|
endif
|
||||||
|
|
||||||
fp_enums = gnome.mkenums_simple('fp-enums',
|
fp_enums = gnome.mkenums_simple('fp-enums',
|
||||||
sources: libfprint_public_headers,
|
sources: libfprint_public_headers,
|
||||||
@@ -262,8 +297,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: [
|
||||||
@@ -315,6 +355,21 @@ 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)
|
||||||
|
|
||||||
|
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',
|
||||||
@@ -339,7 +394,7 @@ sync_udev_udb = custom_target('sync-udev-hwdb',
|
|||||||
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'
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
25
libfprint/sdcp/generate-gresource.py
Normal file
25
libfprint/sdcp/generate-gresource.py
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
#!/usr/bin/python3
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
|
if len(sys.argv) != 3:
|
||||||
|
print("generate-gresource.py: Generates SDCP Truststore GResource XML file from certificates in ./truststore/*.pem")
|
||||||
|
print("Usage: generate-gresource.py <libfprint_sdcp_source_dir> <output_xml_file>")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
gresource_prefix = "/org/freedesktop/fprint/sdcp"
|
||||||
|
relative_folder = "truststore"
|
||||||
|
full_folder = os.path.join(sys.argv[1], relative_folder)
|
||||||
|
output = sys.argv[2]
|
||||||
|
|
||||||
|
files = [f for f in os.listdir(full_folder) if os.path.isfile(os.path.join(full_folder, f)) and f.endswith('.pem')]
|
||||||
|
|
||||||
|
with open(output, 'w') as f:
|
||||||
|
f.write('<?xml version="1.0" encoding="UTF-8"?>\n')
|
||||||
|
f.write('<gresources>\n')
|
||||||
|
f.write(f' <gresource prefix="{gresource_prefix}">\n')
|
||||||
|
for file in files:
|
||||||
|
f.write(f' <file compressed="true">{relative_folder}/{file}</file>\n')
|
||||||
|
f.write(' </gresource>\n')
|
||||||
|
f.write('</gresources>\n')
|
||||||
32
libfprint/sdcp/meson.build
Normal file
32
libfprint/sdcp/meson.build
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
sdcp_truststore_gresource_xml = custom_target('sdcp-truststore.gresource',
|
||||||
|
input : 'generate-gresource.py',
|
||||||
|
output : 'sdcp-truststore.gresource.xml',
|
||||||
|
command : [find_program('python3'), '@INPUT@', meson.current_source_dir(), '@OUTPUT@'],
|
||||||
|
)
|
||||||
|
|
||||||
|
sdcp_truststore_resource_h = custom_target('fpi-sdcp-truststore-resource.h',
|
||||||
|
input : sdcp_truststore_gresource_xml,
|
||||||
|
output : 'fpi-sdcp-truststore-resource.h',
|
||||||
|
command : ['glib-compile-resources',
|
||||||
|
'--target=@OUTPUT@',
|
||||||
|
'--sourcedir=' + meson.current_source_dir(),
|
||||||
|
'--internal',
|
||||||
|
'--generate',
|
||||||
|
'--c-name', 'fpi_sdcp_truststore',
|
||||||
|
'--manual-register',
|
||||||
|
'@INPUT@']
|
||||||
|
)
|
||||||
|
|
||||||
|
sdcp_truststore_resource_c = custom_target('fpi-sdcp-truststore-resource.c',
|
||||||
|
depends : [sdcp_truststore_resource_h],
|
||||||
|
input : sdcp_truststore_gresource_xml,
|
||||||
|
output : 'fpi-sdcp-truststore-resource.c',
|
||||||
|
command : ['glib-compile-resources',
|
||||||
|
'--target=@OUTPUT@',
|
||||||
|
'--sourcedir=' + meson.current_source_dir(),
|
||||||
|
'--internal',
|
||||||
|
'--generate',
|
||||||
|
'--c-name', 'fpi_sdcp_truststore',
|
||||||
|
'--manual-register',
|
||||||
|
'@INPUT@']
|
||||||
|
)
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIDIDCCAqWgAwIBAgIQKs9yK9kUXqlMVB+fSF1UMjAKBggqhkjOPQQDAzCBlDEL
|
||||||
|
MAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1v
|
||||||
|
bmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjE+MDwGA1UEAxM1TWlj
|
||||||
|
cm9zb2Z0IEVDQyBEZXZpY2VzIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIw
|
||||||
|
MTcwHhcNMTcxMTA5MTk0MDQ4WhcNNDIxMTA5MTk0ODE5WjCBlDELMAkGA1UEBhMC
|
||||||
|
VVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNV
|
||||||
|
BAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjE+MDwGA1UEAxM1TWljcm9zb2Z0IEVD
|
||||||
|
QyBEZXZpY2VzIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTcwdjAQBgcq
|
||||||
|
hkjOPQIBBgUrgQQAIgNiAARiivDX0DS0EXoGlfbd2PwxSC87Cszr6/aAjSx6pMwU
|
||||||
|
4kzXcId0dhrjSkPSIO5UCz50ggQGQiTwqRzyhM44FlEyzbzl6OHGDwR1vAg3wdmm
|
||||||
|
WEXWySzyAZKsfkwg0G7bPkijgbkwgbYwCwYDVR0PBAQDAgGGMA8GA1UdEwEB/wQF
|
||||||
|
MAMBAf8wHQYDVR0OBBYEFBTaW/EOZkfRXRNfW3rr618BCLVJMBAGCSsGAQQBgjcV
|
||||||
|
AQQDAgEAMGUGA1UdIAReMFwwBgYEVR0gADBSBgwrBgEEAYI3TIN9AQEwQjBABggr
|
||||||
|
BgEFBQcCARY0aHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9Eb2NzL1Jl
|
||||||
|
cG9zaXRvcnkuaHRtADAKBggqhkjOPQQDAwNpADBmAjEAxxAFFL8juLXiulXvZgBQ
|
||||||
|
pGGPCcV2Tr3CorZ4p/uO2/rtBemqhL3CjKAm40VlhEz8AjEArE5fhA54SEDjoTwZ
|
||||||
|
VUosaqXa8ych31qjZI+e1ttbOPebAZTt9ac7+lTzJcLTEQch
|
||||||
|
-----END CERTIFICATE-----
|
||||||
23
libfprint/sdcp/truststore/Windows Hello 2096ADCC CA 2021.pem
Normal file
23
libfprint/sdcp/truststore/Windows Hello 2096ADCC CA 2021.pem
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIDwzCCA0qgAwIBAgITMwAAAAuNaMBkOddK4wAAAAAACzAKBggqhkjOPQQDAjCB
|
||||||
|
hDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1Jl
|
||||||
|
ZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEuMCwGA1UEAxMl
|
||||||
|
V2luZG93cyBIZWxsbyBTZWN1cmUgRGV2aWNlcyBQQ0EgMjAxODAeFw0yMTEyMDky
|
||||||
|
MzI1MDFaFw0zMDEyMDkyMzM1MDFaMFYxCzAJBgNVBAYTAlVTMR4wHAYDVQQKExVN
|
||||||
|
aWNyb3NvZnQgQ29ycG9yYXRpb24xJzAlBgNVBAMTHldpbmRvd3MgSGVsbG8gMjA5
|
||||||
|
NkFEQ0MgQ0EgMjAyMTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABJWgPvl44Gei
|
||||||
|
RrTuA3f1eT60pAlBWM7ym7WSchqz3hge1WS8RUxPVedu0f7MCe/R6O6RVjV7HWq4
|
||||||
|
c6jo9FwoiAGjggHGMIIBwjAQBgkrBgEEAYI3FQEEAwIBADAdBgNVHQ4EFgQUvzdI
|
||||||
|
40pjLelTo7qJApjAaUcqmbkwVAYDVR0gBE0wSzBJBgRVHSAAMEEwPwYIKwYBBQUH
|
||||||
|
AgEWM2h0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMvRG9jcy9SZXBvc2l0
|
||||||
|
b3J5Lmh0bTAZBgkrBgEEAYI3FAIEDB4KAFMAdQBiAEMAQTALBgNVHQ8EBAMCAYYw
|
||||||
|
DwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBTaykvQTFYDJ1+X63WjAsO/RZz4
|
||||||
|
sTBoBgNVHR8EYTBfMF2gW6BZhldodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtp
|
||||||
|
b3BzL2NybC9XaW5kb3dzJTIwSGVsbG8lMjBTZWN1cmUlMjBEZXZpY2VzJTIwUENB
|
||||||
|
JTIwMjAxOC5jcmwwdQYIKwYBBQUHAQEEaTBnMGUGCCsGAQUFBzAChllodHRwOi8v
|
||||||
|
d3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NlcnRzL1dpbmRvd3MlMjBIZWxsbyUy
|
||||||
|
MFNlY3VyZSUyMERldmljZXMlMjBQQ0ElMjAyMDE4LmNydDAKBggqhkjOPQQDAgNn
|
||||||
|
ADBkAjAeGyYlzf+uBQXI/EW84I5CGFbo/U6dL4k1Y83f2p94d0wrNwjUb/yprb4+
|
||||||
|
L9+OKfQCME8PgRyJQxsvsne+WI6gr0ZzJilotoiRdvDzlMK4+hx5TGJWTV17AsAo
|
||||||
|
z2330epHQQ==
|
||||||
|
-----END CERTIFICATE-----
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIEVjCCA9ygAwIBAgITMwAAAANsz+3iRHAZvwAAAAAAAzAKBggqhkjOPQQDAzCB
|
||||||
|
lDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1Jl
|
||||||
|
ZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjE+MDwGA1UEAxM1
|
||||||
|
TWljcm9zb2Z0IEVDQyBEZXZpY2VzIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5
|
||||||
|
IDIwMTcwHhcNMTgwMTI1MTk0OTM4WhcNMzMwMTI1MTk1OTM4WjCBhDELMAkGA1UE
|
||||||
|
BhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAc
|
||||||
|
BgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEuMCwGA1UEAxMlV2luZG93cyBI
|
||||||
|
ZWxsbyBTZWN1cmUgRGV2aWNlcyBQQ0EgMjAxODB2MBAGByqGSM49AgEGBSuBBAAi
|
||||||
|
A2IABB3dCAIDJXUg4nGLrSgJgukG7oPFOmxLcZJQTiDpcrT8UyrvXcyatM12uJSX
|
||||||
|
RLJxDsmxFgOhZSu56F1f8jAu3bErIPy+AIjqH6d/mYSYfHE+TTSDaZsIy3iyS73X
|
||||||
|
Pr5noKOCAfwwggH4MBAGCSsGAQQBgjcVAQQDAgEAMB0GA1UdDgQWBBTaykvQTFYD
|
||||||
|
J1+X63WjAsO/RZz4sTBlBgNVHSAEXjBcMAYGBFUdIAAwUgYMKwYBBAGCN0yDfQEB
|
||||||
|
MEIwQAYIKwYBBQUHAgEWNGh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMv
|
||||||
|
RG9jcy9SZXBvc2l0b3J5Lmh0bQAwGQYJKwYBBAGCNxQCBAweCgBTAHUAYgBDAEEw
|
||||||
|
CwYDVR0PBAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUFNpb8Q5m
|
||||||
|
R9FdE19beuvrXwEItUkwegYDVR0fBHMwcTBvoG2ga4ZpaHR0cDovL3d3dy5taWNy
|
||||||
|
b3NvZnQuY29tL3BraW9wcy9jcmwvTWljcm9zb2Z0JTIwRUNDJTIwRGV2aWNlcyUy
|
||||||
|
MFJvb3QlMjBDZXJ0aWZpY2F0ZSUyMEF1dGhvcml0eSUyMDIwMTcuY3JsMIGHBggr
|
||||||
|
BgEFBQcBAQR7MHkwdwYIKwYBBQUHMAKGa2h0dHA6Ly93d3cubWljcm9zb2Z0LmNv
|
||||||
|
bS9wa2lvcHMvY2VydHMvTWljcm9zb2Z0JTIwRUNDJTIwRGV2aWNlcyUyMFJvb3Ql
|
||||||
|
MjBDZXJ0aWZpY2F0ZSUyMEF1dGhvcml0eSUyMDIwMTcuY3J0MAoGCCqGSM49BAMD
|
||||||
|
A2gAMGUCMFYqrXJMuYyzI4D1X/ghlGYPdnfiewPdMF7LkMp45gstEuX3ZzFYcebz
|
||||||
|
ZMEEs4vp4gIxALkgYbnQXjqkoor+HfwnYQuYFowCnCB/7vPLHwo3YrGOztmanqzm
|
||||||
|
GtS48agrsbRAmw==
|
||||||
|
-----END CERTIFICATE-----
|
||||||
102
meson.build
102
meson.build
@@ -1,27 +1,38 @@
|
|||||||
project('libfprint', [ 'c', 'cpp' ],
|
project('libfprint', [ 'c', 'cpp' ],
|
||||||
version: '1.94.4',
|
version: '1.94.9',
|
||||||
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.59.0')
|
||||||
|
|
||||||
|
fs = import('fs')
|
||||||
gnome = import('gnome')
|
gnome = import('gnome')
|
||||||
|
|
||||||
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',
|
||||||
@@ -86,19 +97,23 @@ 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)
|
||||||
|
|
||||||
# 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_drivers = [
|
||||||
'virtual_image',
|
'virtual_image',
|
||||||
'virtual_device',
|
'virtual_device',
|
||||||
'virtual_device_storage',
|
'virtual_device_storage',
|
||||||
|
'virtual_sdcp',
|
||||||
]
|
]
|
||||||
|
|
||||||
default_drivers = [
|
default_drivers = [
|
||||||
'upektc_img',
|
'upektc_img',
|
||||||
'vfs5011',
|
'vfs5011',
|
||||||
@@ -115,6 +130,7 @@ default_drivers = [
|
|||||||
'vfs0050',
|
'vfs0050',
|
||||||
'etes603',
|
'etes603',
|
||||||
'egis0570',
|
'egis0570',
|
||||||
|
'egismoc',
|
||||||
'vcom5s',
|
'vcom5s',
|
||||||
'synaptics',
|
'synaptics',
|
||||||
'elan',
|
'elan',
|
||||||
@@ -126,16 +142,42 @@ default_drivers = [
|
|||||||
'goodixmoc',
|
'goodixmoc',
|
||||||
'nb1010',
|
'nb1010',
|
||||||
'fpcmoc',
|
'fpcmoc',
|
||||||
|
'realtek',
|
||||||
# SPI
|
'focaltech_moc',
|
||||||
'elanspi',
|
|
||||||
]
|
]
|
||||||
|
|
||||||
|
spi_drivers = [
|
||||||
|
'elanspi'
|
||||||
|
]
|
||||||
|
|
||||||
|
if have_spi
|
||||||
|
default_drivers += spi_drivers
|
||||||
|
endif
|
||||||
|
|
||||||
# FIXME: All the drivers should be fixed by adjusting the byte order.
|
# FIXME: All the drivers should be fixed by adjusting the byte order.
|
||||||
# See https://gitlab.freedesktop.org/libfprint/libfprint/-/issues/236
|
# See https://gitlab.freedesktop.org/libfprint/libfprint/-/issues/236
|
||||||
endian_independent_drivers = virtual_drivers + [
|
endian_independent_drivers = virtual_drivers + [
|
||||||
|
'aes1610',
|
||||||
|
'aes1660',
|
||||||
|
'aes2550',
|
||||||
|
'aes2660',
|
||||||
'aes3500',
|
'aes3500',
|
||||||
|
'aes4000',
|
||||||
|
'egis0570',
|
||||||
|
'egismoc',
|
||||||
|
'elanmoc',
|
||||||
|
'etes603',
|
||||||
|
'focaltech_moc',
|
||||||
|
'nb1010',
|
||||||
|
'realtek',
|
||||||
'synaptics',
|
'synaptics',
|
||||||
|
'upeksonly',
|
||||||
|
'upektc',
|
||||||
|
'upektc_img',
|
||||||
|
'upekts',
|
||||||
|
'vcom5s',
|
||||||
|
'vfs101',
|
||||||
|
'vfs7552',
|
||||||
]
|
]
|
||||||
|
|
||||||
all_drivers = default_drivers + virtual_drivers
|
all_drivers = default_drivers + virtual_drivers
|
||||||
@@ -148,6 +190,17 @@ if drivers == [ 'default' ]
|
|||||||
drivers = default_drivers
|
drivers = default_drivers
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
enabled_spi_drivers = []
|
||||||
|
foreach driver : spi_drivers
|
||||||
|
if driver in drivers
|
||||||
|
enabled_spi_drivers += driver
|
||||||
|
endif
|
||||||
|
endforeach
|
||||||
|
|
||||||
|
if enabled_spi_drivers.length() > 0 and not have_spi
|
||||||
|
error('SPI drivers @0@ are not supported'.format(enabled_spi_drivers))
|
||||||
|
endif
|
||||||
|
|
||||||
driver_helper_mapping = {
|
driver_helper_mapping = {
|
||||||
'aes1610' : [ 'aeslib' ],
|
'aes1610' : [ 'aeslib' ],
|
||||||
'aes1660' : [ 'aeslib', 'aesx660' ],
|
'aes1660' : [ 'aeslib', 'aesx660' ],
|
||||||
@@ -156,11 +209,13 @@ driver_helper_mapping = {
|
|||||||
'aes2660' : [ 'aeslib', 'aesx660' ],
|
'aes2660' : [ 'aeslib', 'aesx660' ],
|
||||||
'aes3500' : [ 'aeslib', 'aes3k' ],
|
'aes3500' : [ 'aeslib', 'aes3k' ],
|
||||||
'aes4000' : [ 'aeslib', 'aes3k' ],
|
'aes4000' : [ 'aeslib', 'aes3k' ],
|
||||||
'uru4000' : [ 'nss' ],
|
'egismoc' : [ 'sdcp' ],
|
||||||
'elanspi' : [ 'udev' ],
|
'elanspi' : [ 'udev' ],
|
||||||
|
'uru4000' : [ 'openssl' ],
|
||||||
'virtual_image' : [ 'virtual' ],
|
'virtual_image' : [ 'virtual' ],
|
||||||
'virtual_device' : [ 'virtual' ],
|
'virtual_device' : [ 'virtual' ],
|
||||||
'virtual_device_storage' : [ 'virtual' ],
|
'virtual_device_storage' : [ 'virtual' ],
|
||||||
|
'virtual_sdcp' : [ 'virtual', 'sdcp' ],
|
||||||
}
|
}
|
||||||
|
|
||||||
driver_helpers = []
|
driver_helpers = []
|
||||||
@@ -213,13 +268,20 @@ 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 == 'sdcp'
|
||||||
|
openssl_dep = dependency('openssl', version: '>= 3.0.8', required: false)
|
||||||
|
if not openssl_dep.found()
|
||||||
|
error('OpenSSL >= 3.0.8 is required for SDCP support (@0@ and possibly others)'.format(driver))
|
||||||
|
endif
|
||||||
|
|
||||||
|
optional_deps += openssl_dep
|
||||||
elif i == 'udev'
|
elif i == 'udev'
|
||||||
install_udev_rules = true
|
install_udev_rules = true
|
||||||
|
|
||||||
@@ -242,7 +304,7 @@ 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
|
||||||
|
|
||||||
@@ -279,15 +341,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')
|
||||||
@@ -299,9 +359,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')
|
||||||
@@ -311,6 +369,8 @@ endif
|
|||||||
subdir('data')
|
subdir('data')
|
||||||
subdir('tests')
|
subdir('tests')
|
||||||
|
|
||||||
|
subdir('examples')
|
||||||
|
|
||||||
pkgconfig = import('pkgconfig')
|
pkgconfig = import('pkgconfig')
|
||||||
pkgconfig.generate(
|
pkgconfig.generate(
|
||||||
name: versioned_libname,
|
name: versioned_libname,
|
||||||
@@ -321,3 +381,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)
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ indent_func_proto_param false
|
|||||||
indent_switch_case 0
|
indent_switch_case 0
|
||||||
indent_case_brace 2
|
indent_case_brace 2
|
||||||
indent_paren_close 1
|
indent_paren_close 1
|
||||||
|
pp_multiline_define_body_indent 2
|
||||||
|
|
||||||
# spacing
|
# spacing
|
||||||
sp_arith Add
|
sp_arith Add
|
||||||
@@ -114,6 +115,7 @@ nl_create_for_one_liner False
|
|||||||
nl_create_while_one_liner False
|
nl_create_while_one_liner False
|
||||||
nl_after_semicolon True
|
nl_after_semicolon True
|
||||||
nl_multi_line_cond true
|
nl_multi_line_cond true
|
||||||
|
nl_multi_line_define true
|
||||||
|
|
||||||
# mod
|
# mod
|
||||||
# I'd like these to be remove, but that removes brackets in if { if { foo } }, which i dislike
|
# I'd like these to be remove, but that removes brackets in if { if { foo } }, which i dislike
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ if len(sys.argv) > 3:
|
|||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
driver_name = sys.argv[1]
|
driver_name = sys.argv[1]
|
||||||
os.environ['FP_DRIVERS_WHITELIST'] = driver_name
|
os.environ['FP_DRIVERS_ALLOWLIST'] = driver_name
|
||||||
|
|
||||||
test_variant = None
|
test_variant = None
|
||||||
if len(sys.argv) == 3:
|
if len(sys.argv) == 3:
|
||||||
|
|||||||
5
tests/driver.test.in
Normal file
5
tests/driver.test.in
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
[Test]
|
||||||
|
Type=session
|
||||||
|
# We can't use TestEnvironment as per
|
||||||
|
# https://gitlab.gnome.org/GNOME/gnome-desktop-testing/-/issues/1
|
||||||
|
Exec=env @driver_env@ @installed_tests_execdir@/@umockdev_test_name@ @installed_tests_testdir@/@driver_test@
|
||||||
0
tests/egis0570/capture.pcapng
Executable file → Normal file
0
tests/egis0570/capture.pcapng
Executable file → Normal file
@@ -24,7 +24,7 @@ E: ID_USB_INTERFACES=:ff0000:
|
|||||||
E: ID_VENDOR_FROM_DATABASE=LighTuning Technology Inc.
|
E: ID_VENDOR_FROM_DATABASE=LighTuning Technology Inc.
|
||||||
E: ID_PATH=pci-0000:00:14.0-usb-0:9
|
E: ID_PATH=pci-0000:00:14.0-usb-0:9
|
||||||
E: ID_PATH_TAG=pci-0000_00_14_0-usb-0_9
|
E: ID_PATH_TAG=pci-0000_00_14_0-usb-0_9
|
||||||
E: LIBFPRINT_DRIVER=Hardcoded whitelist
|
E: LIBFPRINT_DRIVER=Hardcoded allowlist
|
||||||
A: authorized=1\n
|
A: authorized=1\n
|
||||||
A: avoid_reset_quirk=0\n
|
A: avoid_reset_quirk=0\n
|
||||||
A: bConfigurationValue=1\n
|
A: bConfigurationValue=1\n
|
||||||
|
|||||||
BIN
tests/egismoc-0586/custom.pcapng
Normal file
BIN
tests/egismoc-0586/custom.pcapng
Normal file
Binary file not shown.
156
tests/egismoc-0586/custom.py
Executable file
156
tests/egismoc-0586/custom.py
Executable file
@@ -0,0 +1,156 @@
|
|||||||
|
#!/usr/bin/python3
|
||||||
|
|
||||||
|
import traceback
|
||||||
|
import sys
|
||||||
|
import time
|
||||||
|
import gi
|
||||||
|
|
||||||
|
gi.require_version('FPrint', '2.0')
|
||||||
|
from gi.repository import FPrint, GLib
|
||||||
|
|
||||||
|
# Exit with error on any exception, included those happening in async callbacks
|
||||||
|
sys.excepthook = lambda *args: (traceback.print_exception(*args), sys.exit(1))
|
||||||
|
|
||||||
|
ctx = GLib.main_context_default()
|
||||||
|
|
||||||
|
c = FPrint.Context()
|
||||||
|
c.enumerate()
|
||||||
|
devices = c.get_devices()
|
||||||
|
|
||||||
|
d = devices[0]
|
||||||
|
del devices
|
||||||
|
|
||||||
|
d.open_sync()
|
||||||
|
|
||||||
|
assert d.get_driver() == "egismoc"
|
||||||
|
assert not d.has_feature(FPrint.DeviceFeature.CAPTURE)
|
||||||
|
assert d.has_feature(FPrint.DeviceFeature.IDENTIFY)
|
||||||
|
assert d.has_feature(FPrint.DeviceFeature.VERIFY)
|
||||||
|
assert d.has_feature(FPrint.DeviceFeature.DUPLICATES_CHECK)
|
||||||
|
assert d.has_feature(FPrint.DeviceFeature.STORAGE)
|
||||||
|
assert d.has_feature(FPrint.DeviceFeature.STORAGE_LIST)
|
||||||
|
assert d.has_feature(FPrint.DeviceFeature.STORAGE_DELETE)
|
||||||
|
assert d.has_feature(FPrint.DeviceFeature.STORAGE_CLEAR)
|
||||||
|
|
||||||
|
def enroll_progress(*args):
|
||||||
|
print("finger status: ", d.get_finger_status())
|
||||||
|
print('enroll progress: ' + str(args))
|
||||||
|
|
||||||
|
def identify_done(dev, res):
|
||||||
|
global identified
|
||||||
|
identified = True
|
||||||
|
identify_match, identify_print = dev.identify_finish(res)
|
||||||
|
print('indentification_done: ', identify_match, identify_print)
|
||||||
|
assert identify_match.equal(identify_print)
|
||||||
|
|
||||||
|
# Beginning with list and clear assumes you begin with >0 prints enrolled before capturing
|
||||||
|
|
||||||
|
print("listing - device should have prints")
|
||||||
|
stored = d.list_prints_sync()
|
||||||
|
assert len(stored) > 0
|
||||||
|
del stored
|
||||||
|
|
||||||
|
print("clear device storage")
|
||||||
|
d.clear_storage_sync()
|
||||||
|
print("clear done")
|
||||||
|
|
||||||
|
print("listing - device should be empty")
|
||||||
|
stored = d.list_prints_sync()
|
||||||
|
assert len(stored) == 0
|
||||||
|
del stored
|
||||||
|
|
||||||
|
print("enrolling")
|
||||||
|
template = FPrint.Print.new(d)
|
||||||
|
template.set_finger(FPrint.Finger.LEFT_INDEX)
|
||||||
|
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
|
||||||
|
p1 = d.enroll_sync(template, None, enroll_progress, None)
|
||||||
|
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
|
||||||
|
print("enroll done")
|
||||||
|
del template
|
||||||
|
|
||||||
|
print("listing - device should have 1 print")
|
||||||
|
stored = d.list_prints_sync()
|
||||||
|
assert len(stored) == 1
|
||||||
|
assert stored[0].equal(p1)
|
||||||
|
|
||||||
|
print("verifying")
|
||||||
|
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
|
||||||
|
verify_res, verify_print = d.verify_sync(p1)
|
||||||
|
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
|
||||||
|
print("verify done")
|
||||||
|
assert verify_res == True
|
||||||
|
|
||||||
|
identified = False
|
||||||
|
deserialized_prints = []
|
||||||
|
for p in stored:
|
||||||
|
deserialized_prints.append(FPrint.Print.deserialize(p.serialize()))
|
||||||
|
assert deserialized_prints[-1].equal(p)
|
||||||
|
del stored
|
||||||
|
|
||||||
|
print('async identifying')
|
||||||
|
d.identify(deserialized_prints, callback=identify_done)
|
||||||
|
del deserialized_prints
|
||||||
|
|
||||||
|
while not identified:
|
||||||
|
ctx.iteration(True)
|
||||||
|
|
||||||
|
print("try to enroll duplicate")
|
||||||
|
template = FPrint.Print.new(d)
|
||||||
|
template.set_finger(FPrint.Finger.RIGHT_INDEX)
|
||||||
|
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
|
||||||
|
try:
|
||||||
|
d.enroll_sync(template, None, enroll_progress, None)
|
||||||
|
except GLib.Error as error:
|
||||||
|
assert error.matches(FPrint.DeviceError.quark(),
|
||||||
|
FPrint.DeviceError.DATA_DUPLICATE)
|
||||||
|
except Exception as exc:
|
||||||
|
raise
|
||||||
|
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
|
||||||
|
print("duplicate enroll attempt done")
|
||||||
|
|
||||||
|
print("listing - device should still only have 1 print")
|
||||||
|
stored = d.list_prints_sync()
|
||||||
|
assert len(stored) == 1
|
||||||
|
assert stored[0].equal(p1)
|
||||||
|
del stored
|
||||||
|
|
||||||
|
print("enroll new finger")
|
||||||
|
template = FPrint.Print.new(d)
|
||||||
|
template.set_finger(FPrint.Finger.RIGHT_INDEX)
|
||||||
|
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
|
||||||
|
p2 = d.enroll_sync(template, None, enroll_progress, None)
|
||||||
|
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
|
||||||
|
print("enroll new finger done")
|
||||||
|
del template
|
||||||
|
|
||||||
|
print("listing - device should have 2 prints")
|
||||||
|
stored = d.list_prints_sync()
|
||||||
|
assert len(stored) == 2
|
||||||
|
assert (stored[0].equal(p1) and stored[1].equal(p2)) or (stored[0].equal(p2) and stored[1].equal(p1))
|
||||||
|
del stored
|
||||||
|
|
||||||
|
print("deleting first print")
|
||||||
|
d.delete_print_sync(p1)
|
||||||
|
print("delete done")
|
||||||
|
del p1
|
||||||
|
|
||||||
|
print("listing - device should only have second print")
|
||||||
|
stored = d.list_prints_sync()
|
||||||
|
assert len(stored) == 1
|
||||||
|
assert stored[0].equal(p2)
|
||||||
|
del stored
|
||||||
|
del p2
|
||||||
|
|
||||||
|
print("clear device storage")
|
||||||
|
d.clear_storage_sync()
|
||||||
|
print("clear done")
|
||||||
|
|
||||||
|
print("listing - device should be empty")
|
||||||
|
stored = d.list_prints_sync()
|
||||||
|
assert len(stored) == 0
|
||||||
|
del stored
|
||||||
|
|
||||||
|
d.close_sync()
|
||||||
|
|
||||||
|
del d
|
||||||
|
del c
|
||||||
255
tests/egismoc-0586/device
Normal file
255
tests/egismoc-0586/device
Normal file
@@ -0,0 +1,255 @@
|
|||||||
|
P: /devices/pci0000:00/0000:00:14.0/usb1/1-7
|
||||||
|
N: bus/usb/001/021=12010002FF0000407A1C860556620102030109022700010100A0320904000003FF000000070581020002000705020200020007058303400005
|
||||||
|
E: BUSNUM=001
|
||||||
|
E: DEVNAME=/dev/bus/usb/001/021
|
||||||
|
E: DEVNUM=021
|
||||||
|
E: DEVTYPE=usb_device
|
||||||
|
E: DRIVER=usb
|
||||||
|
E: ID_AUTOSUSPEND=1
|
||||||
|
E: ID_BUS=usb
|
||||||
|
E: ID_MODEL=ETU905A88-E
|
||||||
|
E: ID_MODEL_ENC=ETU905A88-E
|
||||||
|
E: ID_MODEL_ID=0586
|
||||||
|
E: ID_PATH=pci-0000:00:14.0-usb-0:7
|
||||||
|
E: ID_PATH_TAG=pci-0000_00_14_0-usb-0_7
|
||||||
|
E: ID_PATH_WITH_USB_REVISION=pci-0000:00:14.0-usbv2-0:7
|
||||||
|
E: ID_PERSIST=0
|
||||||
|
E: ID_REVISION=6256
|
||||||
|
E: ID_SERIAL=EGIS_ETU905A88-E_0A5743PCU834
|
||||||
|
E: ID_SERIAL_SHORT=0A5743PCU834
|
||||||
|
E: ID_USB_INTERFACES=:ff0000:
|
||||||
|
E: ID_USB_MODEL=ETU905A88-E
|
||||||
|
E: ID_USB_MODEL_ENC=ETU905A88-E
|
||||||
|
E: ID_USB_MODEL_ID=0586
|
||||||
|
E: ID_USB_REVISION=6256
|
||||||
|
E: ID_USB_SERIAL=EGIS_ETU905A88-E_0A5743PCU834
|
||||||
|
E: ID_USB_SERIAL_SHORT=0A5743PCU834
|
||||||
|
E: ID_USB_VENDOR=EGIS
|
||||||
|
E: ID_USB_VENDOR_ENC=EGIS
|
||||||
|
E: ID_USB_VENDOR_ID=1c7a
|
||||||
|
E: ID_VENDOR=EGIS
|
||||||
|
E: ID_VENDOR_ENC=EGIS
|
||||||
|
E: ID_VENDOR_FROM_DATABASE=LighTuning Technology Inc.
|
||||||
|
E: ID_VENDOR_ID=1c7a
|
||||||
|
E: MAJOR=189
|
||||||
|
E: MINOR=20
|
||||||
|
E: PRODUCT=1c7a/586/6256
|
||||||
|
E: SUBSYSTEM=usb
|
||||||
|
E: TYPE=255/0/0
|
||||||
|
A: authorized=1\n
|
||||||
|
A: avoid_reset_quirk=0\n
|
||||||
|
A: bConfigurationValue=1\n
|
||||||
|
A: bDeviceClass=ff\n
|
||||||
|
A: bDeviceProtocol=00\n
|
||||||
|
A: bDeviceSubClass=00\n
|
||||||
|
A: bMaxPacketSize0=64\n
|
||||||
|
A: bMaxPower=100mA\n
|
||||||
|
A: bNumConfigurations=1\n
|
||||||
|
A: bNumInterfaces= 1\n
|
||||||
|
A: bcdDevice=6256\n
|
||||||
|
A: bmAttributes=a0\n
|
||||||
|
A: busnum=1\n
|
||||||
|
A: configuration=
|
||||||
|
H: descriptors=12010002FF0000407A1C860556620102030109022700010100A0320904000003FF000000070581020002000705020200020007058303400005
|
||||||
|
A: dev=189:20\n
|
||||||
|
A: devnum=21\n
|
||||||
|
A: devpath=7\n
|
||||||
|
L: driver=../../../../../bus/usb/drivers/usb
|
||||||
|
L: firmware_node=../../../../LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:4e/device:4f/device:56
|
||||||
|
A: idProduct=0586\n
|
||||||
|
A: idVendor=1c7a\n
|
||||||
|
A: ltm_capable=no\n
|
||||||
|
A: manufacturer=EGIS\n
|
||||||
|
A: maxchild=0\n
|
||||||
|
A: physical_location/dock=no\n
|
||||||
|
A: physical_location/horizontal_position=center\n
|
||||||
|
A: physical_location/lid=no\n
|
||||||
|
A: physical_location/panel=front\n
|
||||||
|
A: physical_location/vertical_position=center\n
|
||||||
|
L: port=../1-0:1.0/usb1-port7
|
||||||
|
A: power/active_duration=12644\n
|
||||||
|
A: power/autosuspend=2\n
|
||||||
|
A: power/autosuspend_delay_ms=2000\n
|
||||||
|
A: power/connected_duration=230907\n
|
||||||
|
A: power/control=auto\n
|
||||||
|
A: power/level=auto\n
|
||||||
|
A: power/persist=0\n
|
||||||
|
A: power/runtime_active_time=12929\n
|
||||||
|
A: power/runtime_status=active\n
|
||||||
|
A: power/runtime_suspended_time=217715\n
|
||||||
|
A: power/wakeup=disabled\n
|
||||||
|
A: power/wakeup_abort_count=\n
|
||||||
|
A: power/wakeup_active=\n
|
||||||
|
A: power/wakeup_active_count=\n
|
||||||
|
A: power/wakeup_count=\n
|
||||||
|
A: power/wakeup_expire_count=\n
|
||||||
|
A: power/wakeup_last_time_ms=\n
|
||||||
|
A: power/wakeup_max_time_ms=\n
|
||||||
|
A: power/wakeup_total_time_ms=\n
|
||||||
|
A: product=ETU905A88-E\n
|
||||||
|
A: quirks=0x0\n
|
||||||
|
A: removable=fixed\n
|
||||||
|
A: rx_lanes=1\n
|
||||||
|
A: serial=0A5743PCU834\n
|
||||||
|
A: speed=480\n
|
||||||
|
A: tx_lanes=1\n
|
||||||
|
A: urbnum=18\n
|
||||||
|
A: version= 2.00\n
|
||||||
|
|
||||||
|
P: /devices/pci0000:00/0000:00:14.0/usb1
|
||||||
|
N: bus/usb/001/001=12010002090001406B1D020008060302010109021900010100E0000904000001090000000705810304000C
|
||||||
|
E: BUSNUM=001
|
||||||
|
E: CURRENT_TAGS=:seat:
|
||||||
|
E: DEVNAME=/dev/bus/usb/001/001
|
||||||
|
E: DEVNUM=001
|
||||||
|
E: DEVTYPE=usb_device
|
||||||
|
E: DRIVER=usb
|
||||||
|
E: ID_AUTOSUSPEND=1
|
||||||
|
E: ID_BUS=usb
|
||||||
|
E: ID_FOR_SEAT=usb-pci-0000_00_14_0
|
||||||
|
E: ID_MODEL=xHCI_Host_Controller
|
||||||
|
E: ID_MODEL_ENC=xHCI\x20Host\x20Controller
|
||||||
|
E: ID_MODEL_FROM_DATABASE=2.0 root hub
|
||||||
|
E: ID_MODEL_ID=0002
|
||||||
|
E: ID_PATH=pci-0000:00:14.0
|
||||||
|
E: ID_PATH_TAG=pci-0000_00_14_0
|
||||||
|
E: ID_REVISION=0608
|
||||||
|
E: ID_SERIAL=Linux_6.8.5-arch1-1_xhci-hcd_xHCI_Host_Controller_0000:00:14.0
|
||||||
|
E: ID_SERIAL_SHORT=0000:00:14.0
|
||||||
|
E: ID_USB_INTERFACES=:090000:
|
||||||
|
E: ID_USB_MODEL=xHCI_Host_Controller
|
||||||
|
E: ID_USB_MODEL_ENC=xHCI\x20Host\x20Controller
|
||||||
|
E: ID_USB_MODEL_ID=0002
|
||||||
|
E: ID_USB_REVISION=0608
|
||||||
|
E: ID_USB_SERIAL=Linux_6.8.5-arch1-1_xhci-hcd_xHCI_Host_Controller_0000:00:14.0
|
||||||
|
E: ID_USB_SERIAL_SHORT=0000:00:14.0
|
||||||
|
E: ID_USB_VENDOR=Linux_6.8.5-arch1-1_xhci-hcd
|
||||||
|
E: ID_USB_VENDOR_ENC=Linux\x206.8.5-arch1-1\x20xhci-hcd
|
||||||
|
E: ID_USB_VENDOR_ID=1d6b
|
||||||
|
E: ID_VENDOR=Linux_6.8.5-arch1-1_xhci-hcd
|
||||||
|
E: ID_VENDOR_ENC=Linux\x206.8.5-arch1-1\x20xhci-hcd
|
||||||
|
E: ID_VENDOR_FROM_DATABASE=Linux Foundation
|
||||||
|
E: ID_VENDOR_ID=1d6b
|
||||||
|
E: MAJOR=189
|
||||||
|
E: MINOR=0
|
||||||
|
E: PRODUCT=1d6b/2/608
|
||||||
|
E: SUBSYSTEM=usb
|
||||||
|
E: TAGS=:seat:
|
||||||
|
E: TYPE=9/0/1
|
||||||
|
A: authorized=1\n
|
||||||
|
A: authorized_default=1\n
|
||||||
|
A: avoid_reset_quirk=0\n
|
||||||
|
A: bConfigurationValue=1\n
|
||||||
|
A: bDeviceClass=09\n
|
||||||
|
A: bDeviceProtocol=01\n
|
||||||
|
A: bDeviceSubClass=00\n
|
||||||
|
A: bMaxPacketSize0=64\n
|
||||||
|
A: bMaxPower=0mA\n
|
||||||
|
A: bNumConfigurations=1\n
|
||||||
|
A: bNumInterfaces= 1\n
|
||||||
|
A: bcdDevice=0608\n
|
||||||
|
A: bmAttributes=e0\n
|
||||||
|
A: busnum=1\n
|
||||||
|
A: configuration=
|
||||||
|
H: descriptors=12010002090001406B1D020008060302010109021900010100E0000904000001090000000705810304000C
|
||||||
|
A: dev=189:0\n
|
||||||
|
A: devnum=1\n
|
||||||
|
A: devpath=0\n
|
||||||
|
L: driver=../../../../bus/usb/drivers/usb
|
||||||
|
L: firmware_node=../../../LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:4e/device:4f
|
||||||
|
A: idProduct=0002\n
|
||||||
|
A: idVendor=1d6b\n
|
||||||
|
A: interface_authorized_default=1\n
|
||||||
|
A: ltm_capable=no\n
|
||||||
|
A: manufacturer=Linux 6.8.5-arch1-1 xhci-hcd\n
|
||||||
|
A: maxchild=12\n
|
||||||
|
A: power/active_duration=73066477\n
|
||||||
|
A: power/autosuspend=0\n
|
||||||
|
A: power/autosuspend_delay_ms=0\n
|
||||||
|
A: power/connected_duration=73071614\n
|
||||||
|
A: power/control=auto\n
|
||||||
|
A: power/level=auto\n
|
||||||
|
A: power/runtime_active_time=73070027\n
|
||||||
|
A: power/runtime_status=active\n
|
||||||
|
A: power/runtime_suspended_time=0\n
|
||||||
|
A: power/wakeup=disabled\n
|
||||||
|
A: power/wakeup_abort_count=\n
|
||||||
|
A: power/wakeup_active=\n
|
||||||
|
A: power/wakeup_active_count=\n
|
||||||
|
A: power/wakeup_count=\n
|
||||||
|
A: power/wakeup_expire_count=\n
|
||||||
|
A: power/wakeup_last_time_ms=\n
|
||||||
|
A: power/wakeup_max_time_ms=\n
|
||||||
|
A: power/wakeup_total_time_ms=\n
|
||||||
|
A: product=xHCI Host Controller\n
|
||||||
|
A: quirks=0x0\n
|
||||||
|
A: removable=unknown\n
|
||||||
|
A: rx_lanes=1\n
|
||||||
|
A: serial=0000:00:14.0\n
|
||||||
|
A: speed=480\n
|
||||||
|
A: tx_lanes=1\n
|
||||||
|
A: urbnum=1111\n
|
||||||
|
A: version= 2.00\n
|
||||||
|
|
||||||
|
P: /devices/pci0000:00/0000:00:14.0
|
||||||
|
E: DRIVER=xhci_hcd
|
||||||
|
E: ID_AUTOSUSPEND=1
|
||||||
|
E: ID_MODEL_FROM_DATABASE=Alder Lake PCH USB 3.2 xHCI Host Controller
|
||||||
|
E: ID_PATH=pci-0000:00:14.0
|
||||||
|
E: ID_PATH_TAG=pci-0000_00_14_0
|
||||||
|
E: ID_PCI_CLASS_FROM_DATABASE=Serial bus controller
|
||||||
|
E: ID_PCI_INTERFACE_FROM_DATABASE=XHCI
|
||||||
|
E: ID_PCI_SUBCLASS_FROM_DATABASE=USB controller
|
||||||
|
E: ID_VENDOR_FROM_DATABASE=Intel Corporation
|
||||||
|
E: MODALIAS=pci:v00008086d000051EDsv00001043sd0000201Fbc0Csc03i30
|
||||||
|
E: PCI_CLASS=C0330
|
||||||
|
E: PCI_ID=8086:51ED
|
||||||
|
E: PCI_SLOT_NAME=0000:00:14.0
|
||||||
|
E: PCI_SUBSYS_ID=1043:201F
|
||||||
|
E: SUBSYSTEM=pci
|
||||||
|
A: ari_enabled=0\n
|
||||||
|
A: broken_parity_status=0\n
|
||||||
|
A: class=0x0c0330\n
|
||||||
|
H: config=8680ED51060490020130030C000080000400220560000000000000000000000000000000000000000000000043101F20000000007000000000000000FF010000FD0134A089C27F8000000000000000003F6DD80F000000000000000000000000316000000000000000000000000000000180C2C10800000000000000000000000590B7001805E0FE000000000000000009B014F01000400100000000C10A080000080E00001800008F50020000010000090000018680C00009001014000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000B50F110112000000
|
||||||
|
A: consistent_dma_mask_bits=64\n
|
||||||
|
A: d3cold_allowed=1\n
|
||||||
|
A: device=0x51ed\n
|
||||||
|
A: dma_mask_bits=64\n
|
||||||
|
L: driver=../../../bus/pci/drivers/xhci_hcd
|
||||||
|
A: driver_override=(null)\n
|
||||||
|
A: enable=1\n
|
||||||
|
L: firmware_node=../../LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:4e
|
||||||
|
A: irq=143\n
|
||||||
|
A: local_cpulist=0-15\n
|
||||||
|
A: local_cpus=ffff\n
|
||||||
|
A: modalias=pci:v00008086d000051EDsv00001043sd0000201Fbc0Csc03i30\n
|
||||||
|
A: msi_bus=1\n
|
||||||
|
A: msi_irqs/143=msi\n
|
||||||
|
A: msi_irqs/144=msi\n
|
||||||
|
A: msi_irqs/145=msi\n
|
||||||
|
A: msi_irqs/146=msi\n
|
||||||
|
A: msi_irqs/147=msi\n
|
||||||
|
A: msi_irqs/148=msi\n
|
||||||
|
A: msi_irqs/149=msi\n
|
||||||
|
A: msi_irqs/150=msi\n
|
||||||
|
A: numa_node=-1\n
|
||||||
|
A: pools=poolinfo - 0.1\nbuffer-2048 0 0 2048 0\nbuffer-512 0 0 512 0\nbuffer-128 0 0 128 0\nbuffer-32 0 0 32 0\nxHCI 1KB stream ctx arrays 0 0 1024 0\nxHCI 256 byte stream ctx arrays 0 0 256 0\nxHCI input/output contexts 8 9 2112 9\nxHCI ring segments 43 53 4096 53\nbuffer-2048 0 16 2048 8\nbuffer-512 0 0 512 0\nbuffer-128 0 0 128 0\nbuffer-32 0 128 32 1\n
|
||||||
|
A: power/control=auto\n
|
||||||
|
A: power/runtime_active_time=73070690\n
|
||||||
|
A: power/runtime_status=active\n
|
||||||
|
A: power/runtime_suspended_time=0\n
|
||||||
|
A: power/wakeup=enabled\n
|
||||||
|
A: power/wakeup_abort_count=0\n
|
||||||
|
A: power/wakeup_active=0\n
|
||||||
|
A: power/wakeup_active_count=0\n
|
||||||
|
A: power/wakeup_count=0\n
|
||||||
|
A: power/wakeup_expire_count=0\n
|
||||||
|
A: power/wakeup_last_time_ms=0\n
|
||||||
|
A: power/wakeup_max_time_ms=0\n
|
||||||
|
A: power/wakeup_total_time_ms=0\n
|
||||||
|
A: power_state=D0\n
|
||||||
|
A: resource=0x0000006005220000 0x000000600522ffff 0x0000000000140204\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n
|
||||||
|
A: revision=0x01\n
|
||||||
|
A: subsystem_device=0x201f\n
|
||||||
|
A: subsystem_vendor=0x1043\n
|
||||||
|
A: vendor=0x8086\n
|
||||||
BIN
tests/egismoc-0587/custom.pcapng
Normal file
BIN
tests/egismoc-0587/custom.pcapng
Normal file
Binary file not shown.
156
tests/egismoc-0587/custom.py
Executable file
156
tests/egismoc-0587/custom.py
Executable file
@@ -0,0 +1,156 @@
|
|||||||
|
#!/usr/bin/python3
|
||||||
|
|
||||||
|
import traceback
|
||||||
|
import sys
|
||||||
|
import time
|
||||||
|
import gi
|
||||||
|
|
||||||
|
gi.require_version('FPrint', '2.0')
|
||||||
|
from gi.repository import FPrint, GLib
|
||||||
|
|
||||||
|
# Exit with error on any exception, included those happening in async callbacks
|
||||||
|
sys.excepthook = lambda *args: (traceback.print_exception(*args), sys.exit(1))
|
||||||
|
|
||||||
|
ctx = GLib.main_context_default()
|
||||||
|
|
||||||
|
c = FPrint.Context()
|
||||||
|
c.enumerate()
|
||||||
|
devices = c.get_devices()
|
||||||
|
|
||||||
|
d = devices[0]
|
||||||
|
del devices
|
||||||
|
|
||||||
|
d.open_sync()
|
||||||
|
|
||||||
|
assert d.get_driver() == "egismoc"
|
||||||
|
assert not d.has_feature(FPrint.DeviceFeature.CAPTURE)
|
||||||
|
assert d.has_feature(FPrint.DeviceFeature.IDENTIFY)
|
||||||
|
assert d.has_feature(FPrint.DeviceFeature.VERIFY)
|
||||||
|
assert d.has_feature(FPrint.DeviceFeature.DUPLICATES_CHECK)
|
||||||
|
assert d.has_feature(FPrint.DeviceFeature.STORAGE)
|
||||||
|
assert d.has_feature(FPrint.DeviceFeature.STORAGE_LIST)
|
||||||
|
assert d.has_feature(FPrint.DeviceFeature.STORAGE_DELETE)
|
||||||
|
assert d.has_feature(FPrint.DeviceFeature.STORAGE_CLEAR)
|
||||||
|
|
||||||
|
def enroll_progress(*args):
|
||||||
|
print("finger status: ", d.get_finger_status())
|
||||||
|
print('enroll progress: ' + str(args))
|
||||||
|
|
||||||
|
def identify_done(dev, res):
|
||||||
|
global identified
|
||||||
|
identified = True
|
||||||
|
identify_match, identify_print = dev.identify_finish(res)
|
||||||
|
print('indentification_done: ', identify_match, identify_print)
|
||||||
|
assert identify_match.equal(identify_print)
|
||||||
|
|
||||||
|
# Beginning with list and clear assumes you begin with >0 prints enrolled before capturing
|
||||||
|
|
||||||
|
print("listing - device should have prints")
|
||||||
|
stored = d.list_prints_sync()
|
||||||
|
assert len(stored) > 0
|
||||||
|
del stored
|
||||||
|
|
||||||
|
print("clear device storage")
|
||||||
|
d.clear_storage_sync()
|
||||||
|
print("clear done")
|
||||||
|
|
||||||
|
print("listing - device should be empty")
|
||||||
|
stored = d.list_prints_sync()
|
||||||
|
assert len(stored) == 0
|
||||||
|
del stored
|
||||||
|
|
||||||
|
print("enrolling")
|
||||||
|
template = FPrint.Print.new(d)
|
||||||
|
template.set_finger(FPrint.Finger.LEFT_INDEX)
|
||||||
|
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
|
||||||
|
p1 = d.enroll_sync(template, None, enroll_progress, None)
|
||||||
|
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
|
||||||
|
print("enroll done")
|
||||||
|
del template
|
||||||
|
|
||||||
|
print("listing - device should have 1 print")
|
||||||
|
stored = d.list_prints_sync()
|
||||||
|
assert len(stored) == 1
|
||||||
|
assert stored[0].equal(p1)
|
||||||
|
|
||||||
|
print("verifying")
|
||||||
|
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
|
||||||
|
verify_res, verify_print = d.verify_sync(p1)
|
||||||
|
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
|
||||||
|
print("verify done")
|
||||||
|
assert verify_res == True
|
||||||
|
|
||||||
|
identified = False
|
||||||
|
deserialized_prints = []
|
||||||
|
for p in stored:
|
||||||
|
deserialized_prints.append(FPrint.Print.deserialize(p.serialize()))
|
||||||
|
assert deserialized_prints[-1].equal(p)
|
||||||
|
del stored
|
||||||
|
|
||||||
|
print('async identifying')
|
||||||
|
d.identify(deserialized_prints, callback=identify_done)
|
||||||
|
del deserialized_prints
|
||||||
|
|
||||||
|
while not identified:
|
||||||
|
ctx.iteration(True)
|
||||||
|
|
||||||
|
print("try to enroll duplicate")
|
||||||
|
template = FPrint.Print.new(d)
|
||||||
|
template.set_finger(FPrint.Finger.RIGHT_INDEX)
|
||||||
|
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
|
||||||
|
try:
|
||||||
|
d.enroll_sync(template, None, enroll_progress, None)
|
||||||
|
except GLib.Error as error:
|
||||||
|
assert error.matches(FPrint.DeviceError.quark(),
|
||||||
|
FPrint.DeviceError.DATA_DUPLICATE)
|
||||||
|
except Exception as exc:
|
||||||
|
raise
|
||||||
|
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
|
||||||
|
print("duplicate enroll attempt done")
|
||||||
|
|
||||||
|
print("listing - device should still only have 1 print")
|
||||||
|
stored = d.list_prints_sync()
|
||||||
|
assert len(stored) == 1
|
||||||
|
assert stored[0].equal(p1)
|
||||||
|
del stored
|
||||||
|
|
||||||
|
print("enroll new finger")
|
||||||
|
template = FPrint.Print.new(d)
|
||||||
|
template.set_finger(FPrint.Finger.RIGHT_INDEX)
|
||||||
|
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
|
||||||
|
p2 = d.enroll_sync(template, None, enroll_progress, None)
|
||||||
|
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
|
||||||
|
print("enroll new finger done")
|
||||||
|
del template
|
||||||
|
|
||||||
|
print("listing - device should have 2 prints")
|
||||||
|
stored = d.list_prints_sync()
|
||||||
|
assert len(stored) == 2
|
||||||
|
assert (stored[0].equal(p1) and stored[1].equal(p2)) or (stored[0].equal(p2) and stored[1].equal(p1))
|
||||||
|
del stored
|
||||||
|
|
||||||
|
print("deleting first print")
|
||||||
|
d.delete_print_sync(p1)
|
||||||
|
print("delete done")
|
||||||
|
del p1
|
||||||
|
|
||||||
|
print("listing - device should only have second print")
|
||||||
|
stored = d.list_prints_sync()
|
||||||
|
assert len(stored) == 1
|
||||||
|
assert stored[0].equal(p2)
|
||||||
|
del stored
|
||||||
|
del p2
|
||||||
|
|
||||||
|
print("clear device storage")
|
||||||
|
d.clear_storage_sync()
|
||||||
|
print("clear done")
|
||||||
|
|
||||||
|
print("listing - device should be empty")
|
||||||
|
stored = d.list_prints_sync()
|
||||||
|
assert len(stored) == 0
|
||||||
|
del stored
|
||||||
|
|
||||||
|
d.close_sync()
|
||||||
|
|
||||||
|
del d
|
||||||
|
del c
|
||||||
270
tests/egismoc-0587/device
Normal file
270
tests/egismoc-0587/device
Normal file
@@ -0,0 +1,270 @@
|
|||||||
|
P: /devices/pci0000:00/0000:00:14.0/usb3/3-5
|
||||||
|
N: bus/usb/003/009=12010002FF0000407A1C870567640102030109022700010100A0320904000003FF000000070581020002000705020200020007058303400005
|
||||||
|
E: BUSNUM=003
|
||||||
|
E: DEVNAME=/dev/bus/usb/003/009
|
||||||
|
E: DEVNUM=009
|
||||||
|
E: DEVTYPE=usb_device
|
||||||
|
E: DRIVER=usb
|
||||||
|
E: ID_AUTOSUSPEND=1
|
||||||
|
E: ID_BUS=usb
|
||||||
|
E: ID_MODEL=ETU905A88-E
|
||||||
|
E: ID_MODEL_ENC=ETU905A88-E
|
||||||
|
E: ID_MODEL_ID=0587
|
||||||
|
E: ID_PATH=pci-0000:00:14.0-usb-0:5
|
||||||
|
E: ID_PATH_TAG=pci-0000_00_14_0-usb-0_5
|
||||||
|
E: ID_PATH_WITH_USB_REVISION=pci-0000:00:14.0-usbv2-0:5
|
||||||
|
E: ID_PERSIST=0
|
||||||
|
E: ID_REVISION=6467
|
||||||
|
E: ID_SERIAL=EGIS_ETU905A88-E_198427PCU834
|
||||||
|
E: ID_SERIAL_SHORT=198427PCU834
|
||||||
|
E: ID_USB_INTERFACES=:ff0000:
|
||||||
|
E: ID_USB_MODEL=ETU905A88-E
|
||||||
|
E: ID_USB_MODEL_ENC=ETU905A88-E
|
||||||
|
E: ID_USB_MODEL_ID=0587
|
||||||
|
E: ID_USB_REVISION=6467
|
||||||
|
E: ID_USB_SERIAL=EGIS_ETU905A88-E_198427PCU834
|
||||||
|
E: ID_USB_SERIAL_SHORT=198427PCU834
|
||||||
|
E: ID_USB_VENDOR=EGIS
|
||||||
|
E: ID_USB_VENDOR_ENC=EGIS
|
||||||
|
E: ID_USB_VENDOR_ID=1c7a
|
||||||
|
E: ID_VENDOR=EGIS
|
||||||
|
E: ID_VENDOR_ENC=EGIS
|
||||||
|
E: ID_VENDOR_FROM_DATABASE=LighTuning Technology Inc.
|
||||||
|
E: ID_VENDOR_ID=1c7a
|
||||||
|
E: MAJOR=189
|
||||||
|
E: MINOR=264
|
||||||
|
E: PRODUCT=1c7a/587/6467
|
||||||
|
E: SUBSYSTEM=usb
|
||||||
|
E: TYPE=255/0/0
|
||||||
|
A: authorized=1\n
|
||||||
|
A: avoid_reset_quirk=0\n
|
||||||
|
A: bConfigurationValue=1\n
|
||||||
|
A: bDeviceClass=ff\n
|
||||||
|
A: bDeviceProtocol=00\n
|
||||||
|
A: bDeviceSubClass=00\n
|
||||||
|
A: bMaxPacketSize0=64\n
|
||||||
|
A: bMaxPower=100mA\n
|
||||||
|
A: bNumConfigurations=1\n
|
||||||
|
A: bNumInterfaces= 1\n
|
||||||
|
A: bcdDevice=6467\n
|
||||||
|
A: bmAttributes=a0\n
|
||||||
|
A: busnum=3\n
|
||||||
|
A: configuration=
|
||||||
|
H: descriptors=12010002FF0000407A1C870567640102030109022700010100A0320904000003FF000000070581020002000705020200020007058303400005
|
||||||
|
A: dev=189:264\n
|
||||||
|
A: devnum=9\n
|
||||||
|
A: devpath=5\n
|
||||||
|
L: driver=../../../../../bus/usb/drivers/usb
|
||||||
|
L: firmware_node=../../../../LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:4e/device:4f/device:54
|
||||||
|
A: idProduct=0587\n
|
||||||
|
A: idVendor=1c7a\n
|
||||||
|
A: ltm_capable=no\n
|
||||||
|
A: manufacturer=EGIS\n
|
||||||
|
A: maxchild=0\n
|
||||||
|
A: physical_location/dock=no\n
|
||||||
|
A: physical_location/horizontal_position=left\n
|
||||||
|
A: physical_location/lid=no\n
|
||||||
|
A: physical_location/panel=top\n
|
||||||
|
A: physical_location/vertical_position=upper\n
|
||||||
|
L: port=../3-0:1.0/usb3-port5
|
||||||
|
A: power/active_duration=58096\n
|
||||||
|
A: power/async=enabled\n
|
||||||
|
A: power/autosuspend=2\n
|
||||||
|
A: power/autosuspend_delay_ms=2000\n
|
||||||
|
A: power/connected_duration=183928\n
|
||||||
|
A: power/control=auto\n
|
||||||
|
A: power/level=auto\n
|
||||||
|
A: power/persist=0\n
|
||||||
|
A: power/runtime_active_kids=0\n
|
||||||
|
A: power/runtime_active_time=58510\n
|
||||||
|
A: power/runtime_enabled=enabled\n
|
||||||
|
A: power/runtime_status=active\n
|
||||||
|
A: power/runtime_suspended_time=125136\n
|
||||||
|
A: power/runtime_usage=0\n
|
||||||
|
A: power/wakeup=disabled\n
|
||||||
|
A: power/wakeup_abort_count=\n
|
||||||
|
A: power/wakeup_active=\n
|
||||||
|
A: power/wakeup_active_count=\n
|
||||||
|
A: power/wakeup_count=\n
|
||||||
|
A: power/wakeup_expire_count=\n
|
||||||
|
A: power/wakeup_last_time_ms=\n
|
||||||
|
A: power/wakeup_max_time_ms=\n
|
||||||
|
A: power/wakeup_total_time_ms=\n
|
||||||
|
A: product=ETU905A88-E\n
|
||||||
|
A: quirks=0x0\n
|
||||||
|
A: removable=fixed\n
|
||||||
|
A: rx_lanes=1\n
|
||||||
|
A: serial=198427PCU834\n
|
||||||
|
A: speed=480\n
|
||||||
|
A: tx_lanes=1\n
|
||||||
|
A: urbnum=547\n
|
||||||
|
A: version= 2.00\n
|
||||||
|
|
||||||
|
P: /devices/pci0000:00/0000:00:14.0/usb3
|
||||||
|
N: bus/usb/003/001=12010002090001406B1D020006060302010109021900010100E0000904000001090000000705810304000C
|
||||||
|
E: BUSNUM=003
|
||||||
|
E: CURRENT_TAGS=:seat:
|
||||||
|
E: DEVNAME=/dev/bus/usb/003/001
|
||||||
|
E: DEVNUM=001
|
||||||
|
E: DEVTYPE=usb_device
|
||||||
|
E: DRIVER=usb
|
||||||
|
E: ID_AUTOSUSPEND=1
|
||||||
|
E: ID_BUS=usb
|
||||||
|
E: ID_FOR_SEAT=usb-pci-0000_00_14_0
|
||||||
|
E: ID_MODEL=xHCI_Host_Controller
|
||||||
|
E: ID_MODEL_ENC=xHCI\x20Host\x20Controller
|
||||||
|
E: ID_MODEL_FROM_DATABASE=2.0 root hub
|
||||||
|
E: ID_MODEL_ID=0002
|
||||||
|
E: ID_PATH=pci-0000:00:14.0
|
||||||
|
E: ID_PATH_TAG=pci-0000_00_14_0
|
||||||
|
E: ID_REVISION=0606
|
||||||
|
E: ID_SERIAL=Linux_6.6.0-14-generic_xhci-hcd_xHCI_Host_Controller_0000:00:14.0
|
||||||
|
E: ID_SERIAL_SHORT=0000:00:14.0
|
||||||
|
E: ID_USB_INTERFACES=:090000:
|
||||||
|
E: ID_USB_MODEL=xHCI_Host_Controller
|
||||||
|
E: ID_USB_MODEL_ENC=xHCI\x20Host\x20Controller
|
||||||
|
E: ID_USB_MODEL_ID=0002
|
||||||
|
E: ID_USB_REVISION=0606
|
||||||
|
E: ID_USB_SERIAL=Linux_6.6.0-14-generic_xhci-hcd_xHCI_Host_Controller_0000:00:14.0
|
||||||
|
E: ID_USB_SERIAL_SHORT=0000:00:14.0
|
||||||
|
E: ID_USB_VENDOR=Linux_6.6.0-14-generic_xhci-hcd
|
||||||
|
E: ID_USB_VENDOR_ENC=Linux\x206.6.0-14-generic\x20xhci-hcd
|
||||||
|
E: ID_USB_VENDOR_ID=1d6b
|
||||||
|
E: ID_VENDOR=Linux_6.6.0-14-generic_xhci-hcd
|
||||||
|
E: ID_VENDOR_ENC=Linux\x206.6.0-14-generic\x20xhci-hcd
|
||||||
|
E: ID_VENDOR_FROM_DATABASE=Linux Foundation
|
||||||
|
E: ID_VENDOR_ID=1d6b
|
||||||
|
E: MAJOR=189
|
||||||
|
E: MINOR=256
|
||||||
|
E: PRODUCT=1d6b/2/606
|
||||||
|
E: SUBSYSTEM=usb
|
||||||
|
E: TAGS=:seat:
|
||||||
|
E: TYPE=9/0/1
|
||||||
|
A: authorized=1\n
|
||||||
|
A: authorized_default=1\n
|
||||||
|
A: avoid_reset_quirk=0\n
|
||||||
|
A: bConfigurationValue=1\n
|
||||||
|
A: bDeviceClass=09\n
|
||||||
|
A: bDeviceProtocol=01\n
|
||||||
|
A: bDeviceSubClass=00\n
|
||||||
|
A: bMaxPacketSize0=64\n
|
||||||
|
A: bMaxPower=0mA\n
|
||||||
|
A: bNumConfigurations=1\n
|
||||||
|
A: bNumInterfaces= 1\n
|
||||||
|
A: bcdDevice=0606\n
|
||||||
|
A: bmAttributes=e0\n
|
||||||
|
A: busnum=3\n
|
||||||
|
A: configuration=
|
||||||
|
H: descriptors=12010002090001406B1D020006060302010109021900010100E0000904000001090000000705810304000C
|
||||||
|
A: dev=189:256\n
|
||||||
|
A: devnum=1\n
|
||||||
|
A: devpath=0\n
|
||||||
|
L: driver=../../../../bus/usb/drivers/usb
|
||||||
|
L: firmware_node=../../../LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:4e/device:4f
|
||||||
|
A: idProduct=0002\n
|
||||||
|
A: idVendor=1d6b\n
|
||||||
|
A: interface_authorized_default=1\n
|
||||||
|
A: ltm_capable=no\n
|
||||||
|
A: manufacturer=Linux 6.6.0-14-generic xhci-hcd\n
|
||||||
|
A: maxchild=12\n
|
||||||
|
A: power/active_duration=5145268\n
|
||||||
|
A: power/async=enabled\n
|
||||||
|
A: power/autosuspend=0\n
|
||||||
|
A: power/autosuspend_delay_ms=0\n
|
||||||
|
A: power/connected_duration=5191200\n
|
||||||
|
A: power/control=auto\n
|
||||||
|
A: power/level=auto\n
|
||||||
|
A: power/runtime_active_kids=2\n
|
||||||
|
A: power/runtime_active_time=5145262\n
|
||||||
|
A: power/runtime_enabled=enabled\n
|
||||||
|
A: power/runtime_status=active\n
|
||||||
|
A: power/runtime_suspended_time=45937\n
|
||||||
|
A: power/runtime_usage=0\n
|
||||||
|
A: power/wakeup=disabled\n
|
||||||
|
A: power/wakeup_abort_count=\n
|
||||||
|
A: power/wakeup_active=\n
|
||||||
|
A: power/wakeup_active_count=\n
|
||||||
|
A: power/wakeup_count=\n
|
||||||
|
A: power/wakeup_expire_count=\n
|
||||||
|
A: power/wakeup_last_time_ms=\n
|
||||||
|
A: power/wakeup_max_time_ms=\n
|
||||||
|
A: power/wakeup_total_time_ms=\n
|
||||||
|
A: product=xHCI Host Controller\n
|
||||||
|
A: quirks=0x0\n
|
||||||
|
A: removable=unknown\n
|
||||||
|
A: rx_lanes=1\n
|
||||||
|
A: serial=0000:00:14.0\n
|
||||||
|
A: speed=480\n
|
||||||
|
A: tx_lanes=1\n
|
||||||
|
A: urbnum=637\n
|
||||||
|
A: version= 2.00\n
|
||||||
|
|
||||||
|
P: /devices/pci0000:00/0000:00:14.0
|
||||||
|
E: DRIVER=xhci_hcd
|
||||||
|
E: ID_AUTOSUSPEND=1
|
||||||
|
E: ID_MODEL_FROM_DATABASE=Alder Lake PCH USB 3.2 xHCI Host Controller
|
||||||
|
E: ID_PATH=pci-0000:00:14.0
|
||||||
|
E: ID_PATH_TAG=pci-0000_00_14_0
|
||||||
|
E: ID_PCI_CLASS_FROM_DATABASE=Serial bus controller
|
||||||
|
E: ID_PCI_INTERFACE_FROM_DATABASE=XHCI
|
||||||
|
E: ID_PCI_SUBCLASS_FROM_DATABASE=USB controller
|
||||||
|
E: ID_VENDOR_FROM_DATABASE=Intel Corporation
|
||||||
|
E: MODALIAS=pci:v00008086d000051EDsv00001043sd0000201Fbc0Csc03i30
|
||||||
|
E: PCI_CLASS=C0330
|
||||||
|
E: PCI_ID=8086:51ED
|
||||||
|
E: PCI_SLOT_NAME=0000:00:14.0
|
||||||
|
E: PCI_SUBSYS_ID=1043:201F
|
||||||
|
E: SUBSYSTEM=pci
|
||||||
|
A: ari_enabled=0\n
|
||||||
|
A: broken_parity_status=0\n
|
||||||
|
A: class=0x0c0330\n
|
||||||
|
H: config=8680ED51060490020130030C000080000400262F62000000000000000000000000000000000000000000000043101F20000000007000000000000000FF010000FD0134A089C27F8000000000000000003F6DD80F000000000000000000000000316000000000000000000000000000000180C2C1080000000000000000000000059087001805E0FE000000000000000009B014F01000400100000000C10A080000080E00001800008F50020000010000090000018680C00009001014000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000B50F110112000000
|
||||||
|
A: consistent_dma_mask_bits=64\n
|
||||||
|
A: d3cold_allowed=1\n
|
||||||
|
A: dbc=disabled\n
|
||||||
|
A: dbc_bInterfaceProtocol=01\n
|
||||||
|
A: dbc_bcdDevice=0010\n
|
||||||
|
A: dbc_idProduct=0010\n
|
||||||
|
A: dbc_idVendor=1d6b\n
|
||||||
|
A: device=0x51ed\n
|
||||||
|
A: dma_mask_bits=64\n
|
||||||
|
L: driver=../../../bus/pci/drivers/xhci_hcd
|
||||||
|
A: driver_override=(null)\n
|
||||||
|
A: enable=1\n
|
||||||
|
L: firmware_node=../../LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:4e
|
||||||
|
A: index=10\n
|
||||||
|
L: iommu=../../virtual/iommu/dmar1
|
||||||
|
L: iommu_group=../../../kernel/iommu_groups/11
|
||||||
|
A: irq=145\n
|
||||||
|
A: label=Onboard - Other\n
|
||||||
|
A: local_cpulist=0-19\n
|
||||||
|
A: local_cpus=fffff\n
|
||||||
|
A: modalias=pci:v00008086d000051EDsv00001043sd0000201Fbc0Csc03i30\n
|
||||||
|
A: msi_bus=1\n
|
||||||
|
A: msi_irqs/145=msi\n
|
||||||
|
A: numa_node=-1\n
|
||||||
|
A: pools=poolinfo - 0.1\nbuffer-2048 0 0 2048 0\nbuffer-512 0 0 512 0\nbuffer-128 1 32 128 1\nbuffer-32 0 0 32 0\nxHCI 1KB stream ctx arrays 0 0 1024 0\nxHCI 256 byte stream ctx arrays 0 0 256 0\nxHCI input/output contexts 10 11 2112 11\nxHCI ring segments 38 38 4096 38\nbuffer-2048 0 0 2048 0\nbuffer-512 0 0 512 0\nbuffer-128 6 32 128 1\nbuffer-32 0 0 32 0\n
|
||||||
|
A: power/async=enabled\n
|
||||||
|
A: power/control=auto\n
|
||||||
|
A: power/runtime_active_kids=2\n
|
||||||
|
A: power/runtime_active_time=5192072\n
|
||||||
|
A: power/runtime_enabled=enabled\n
|
||||||
|
A: power/runtime_status=active\n
|
||||||
|
A: power/runtime_suspended_time=0\n
|
||||||
|
A: power/runtime_usage=0\n
|
||||||
|
A: power/wakeup=enabled\n
|
||||||
|
A: power/wakeup_abort_count=0\n
|
||||||
|
A: power/wakeup_active=0\n
|
||||||
|
A: power/wakeup_active_count=0\n
|
||||||
|
A: power/wakeup_count=0\n
|
||||||
|
A: power/wakeup_expire_count=0\n
|
||||||
|
A: power/wakeup_last_time_ms=0\n
|
||||||
|
A: power/wakeup_max_time_ms=0\n
|
||||||
|
A: power/wakeup_total_time_ms=0\n
|
||||||
|
A: power_state=D0\n
|
||||||
|
A: resource=0x000000622f260000 0x000000622f26ffff 0x0000000000140204\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n
|
||||||
|
A: revision=0x01\n
|
||||||
|
A: subsystem_device=0x201f\n
|
||||||
|
A: subsystem_vendor=0x1043\n
|
||||||
|
A: vendor=0x8086\n
|
||||||
|
|
||||||
BIN
tests/egismoc-05a1/custom.pcapng
Normal file
BIN
tests/egismoc-05a1/custom.pcapng
Normal file
Binary file not shown.
156
tests/egismoc-05a1/custom.py
Executable file
156
tests/egismoc-05a1/custom.py
Executable file
@@ -0,0 +1,156 @@
|
|||||||
|
#!/usr/bin/python3
|
||||||
|
|
||||||
|
import traceback
|
||||||
|
import sys
|
||||||
|
import time
|
||||||
|
import gi
|
||||||
|
|
||||||
|
gi.require_version('FPrint', '2.0')
|
||||||
|
from gi.repository import FPrint, GLib
|
||||||
|
|
||||||
|
# Exit with error on any exception, included those happening in async callbacks
|
||||||
|
sys.excepthook = lambda *args: (traceback.print_exception(*args), sys.exit(1))
|
||||||
|
|
||||||
|
ctx = GLib.main_context_default()
|
||||||
|
|
||||||
|
c = FPrint.Context()
|
||||||
|
c.enumerate()
|
||||||
|
devices = c.get_devices()
|
||||||
|
|
||||||
|
d = devices[0]
|
||||||
|
del devices
|
||||||
|
|
||||||
|
d.open_sync()
|
||||||
|
|
||||||
|
assert d.get_driver() == "egismoc"
|
||||||
|
assert not d.has_feature(FPrint.DeviceFeature.CAPTURE)
|
||||||
|
assert d.has_feature(FPrint.DeviceFeature.IDENTIFY)
|
||||||
|
assert d.has_feature(FPrint.DeviceFeature.VERIFY)
|
||||||
|
assert d.has_feature(FPrint.DeviceFeature.DUPLICATES_CHECK)
|
||||||
|
assert d.has_feature(FPrint.DeviceFeature.STORAGE)
|
||||||
|
assert d.has_feature(FPrint.DeviceFeature.STORAGE_LIST)
|
||||||
|
assert d.has_feature(FPrint.DeviceFeature.STORAGE_DELETE)
|
||||||
|
assert d.has_feature(FPrint.DeviceFeature.STORAGE_CLEAR)
|
||||||
|
|
||||||
|
def enroll_progress(*args):
|
||||||
|
print("finger status: ", d.get_finger_status())
|
||||||
|
print('enroll progress: ' + str(args))
|
||||||
|
|
||||||
|
def identify_done(dev, res):
|
||||||
|
global identified
|
||||||
|
identified = True
|
||||||
|
identify_match, identify_print = dev.identify_finish(res)
|
||||||
|
print('indentification_done: ', identify_match, identify_print)
|
||||||
|
assert identify_match.equal(identify_print)
|
||||||
|
|
||||||
|
# Beginning with list and clear assumes you begin with >0 prints enrolled before capturing
|
||||||
|
|
||||||
|
print("listing - device should have prints")
|
||||||
|
stored = d.list_prints_sync()
|
||||||
|
assert len(stored) > 0
|
||||||
|
del stored
|
||||||
|
|
||||||
|
print("clear device storage")
|
||||||
|
d.clear_storage_sync()
|
||||||
|
print("clear done")
|
||||||
|
|
||||||
|
print("listing - device should be empty")
|
||||||
|
stored = d.list_prints_sync()
|
||||||
|
assert len(stored) == 0
|
||||||
|
del stored
|
||||||
|
|
||||||
|
print("enrolling")
|
||||||
|
template = FPrint.Print.new(d)
|
||||||
|
template.set_finger(FPrint.Finger.LEFT_INDEX)
|
||||||
|
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
|
||||||
|
p1 = d.enroll_sync(template, None, enroll_progress, None)
|
||||||
|
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
|
||||||
|
print("enroll done")
|
||||||
|
del template
|
||||||
|
|
||||||
|
print("listing - device should have 1 print")
|
||||||
|
stored = d.list_prints_sync()
|
||||||
|
assert len(stored) == 1
|
||||||
|
assert stored[0].equal(p1)
|
||||||
|
|
||||||
|
print("verifying")
|
||||||
|
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
|
||||||
|
verify_res, verify_print = d.verify_sync(p1)
|
||||||
|
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
|
||||||
|
print("verify done")
|
||||||
|
assert verify_res == True
|
||||||
|
|
||||||
|
identified = False
|
||||||
|
deserialized_prints = []
|
||||||
|
for p in stored:
|
||||||
|
deserialized_prints.append(FPrint.Print.deserialize(p.serialize()))
|
||||||
|
assert deserialized_prints[-1].equal(p)
|
||||||
|
del stored
|
||||||
|
|
||||||
|
print('async identifying')
|
||||||
|
d.identify(deserialized_prints, callback=identify_done)
|
||||||
|
del deserialized_prints
|
||||||
|
|
||||||
|
while not identified:
|
||||||
|
ctx.iteration(True)
|
||||||
|
|
||||||
|
print("try to enroll duplicate")
|
||||||
|
template = FPrint.Print.new(d)
|
||||||
|
template.set_finger(FPrint.Finger.RIGHT_INDEX)
|
||||||
|
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
|
||||||
|
try:
|
||||||
|
d.enroll_sync(template, None, enroll_progress, None)
|
||||||
|
except GLib.Error as error:
|
||||||
|
assert error.matches(FPrint.DeviceError.quark(),
|
||||||
|
FPrint.DeviceError.DATA_DUPLICATE)
|
||||||
|
except Exception as exc:
|
||||||
|
raise
|
||||||
|
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
|
||||||
|
print("duplicate enroll attempt done")
|
||||||
|
|
||||||
|
print("listing - device should still only have 1 print")
|
||||||
|
stored = d.list_prints_sync()
|
||||||
|
assert len(stored) == 1
|
||||||
|
assert stored[0].equal(p1)
|
||||||
|
del stored
|
||||||
|
|
||||||
|
print("enroll new finger")
|
||||||
|
template = FPrint.Print.new(d)
|
||||||
|
template.set_finger(FPrint.Finger.RIGHT_INDEX)
|
||||||
|
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
|
||||||
|
p2 = d.enroll_sync(template, None, enroll_progress, None)
|
||||||
|
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
|
||||||
|
print("enroll new finger done")
|
||||||
|
del template
|
||||||
|
|
||||||
|
print("listing - device should have 2 prints")
|
||||||
|
stored = d.list_prints_sync()
|
||||||
|
assert len(stored) == 2
|
||||||
|
assert (stored[0].equal(p1) and stored[1].equal(p2)) or (stored[0].equal(p2) and stored[1].equal(p1))
|
||||||
|
del stored
|
||||||
|
|
||||||
|
print("deleting first print")
|
||||||
|
d.delete_print_sync(p1)
|
||||||
|
print("delete done")
|
||||||
|
del p1
|
||||||
|
|
||||||
|
print("listing - device should only have second print")
|
||||||
|
stored = d.list_prints_sync()
|
||||||
|
assert len(stored) == 1
|
||||||
|
assert stored[0].equal(p2)
|
||||||
|
del stored
|
||||||
|
del p2
|
||||||
|
|
||||||
|
print("clear device storage")
|
||||||
|
d.clear_storage_sync()
|
||||||
|
print("clear done")
|
||||||
|
|
||||||
|
print("listing - device should be empty")
|
||||||
|
stored = d.list_prints_sync()
|
||||||
|
assert len(stored) == 0
|
||||||
|
del stored
|
||||||
|
|
||||||
|
d.close_sync()
|
||||||
|
|
||||||
|
del d
|
||||||
|
del c
|
||||||
262
tests/egismoc-05a1/device
Normal file
262
tests/egismoc-05a1/device
Normal file
@@ -0,0 +1,262 @@
|
|||||||
|
P: /devices/pci0000:00/0000:00:14.0/usb1/1-5
|
||||||
|
N: bus/usb/001/003=12010002FF0000407A1CA10513120102030109022700010100A0320904000003FF000000070581020002000705020200020007058303400005
|
||||||
|
E: BUSNUM=001
|
||||||
|
E: DEVNAME=/dev/bus/usb/001/003
|
||||||
|
E: DEVNUM=003
|
||||||
|
E: DEVTYPE=usb_device
|
||||||
|
E: DRIVER=usb
|
||||||
|
E: ID_BUS=usb
|
||||||
|
E: ID_MODEL=ETU905A80-E
|
||||||
|
E: ID_MODEL_ENC=ETU905A80-E
|
||||||
|
E: ID_MODEL_ID=05a1
|
||||||
|
E: ID_REVISION=1213
|
||||||
|
E: ID_SERIAL=EGIS_ETU905A80-E_0C5A44PCU833
|
||||||
|
E: ID_SERIAL_SHORT=0C5A44PCU833
|
||||||
|
E: ID_USB_INTERFACES=:ff0000:
|
||||||
|
E: ID_USB_MODEL=ETU905A80-E
|
||||||
|
E: ID_USB_MODEL_ENC=ETU905A80-E
|
||||||
|
E: ID_USB_MODEL_ID=05a1
|
||||||
|
E: ID_USB_REVISION=1213
|
||||||
|
E: ID_USB_SERIAL=EGIS_ETU905A80-E_0C5A44PCU833
|
||||||
|
E: ID_USB_SERIAL_SHORT=0C5A44PCU833
|
||||||
|
E: ID_USB_VENDOR=EGIS
|
||||||
|
E: ID_USB_VENDOR_ENC=EGIS
|
||||||
|
E: ID_USB_VENDOR_ID=1c7a
|
||||||
|
E: ID_VENDOR=EGIS
|
||||||
|
E: ID_VENDOR_ENC=EGIS
|
||||||
|
E: ID_VENDOR_FROM_DATABASE=LighTuning Technology Inc.
|
||||||
|
E: ID_VENDOR_ID=1c7a
|
||||||
|
E: MAJOR=189
|
||||||
|
E: MINOR=2
|
||||||
|
E: PRODUCT=1c7a/5a1/1213
|
||||||
|
E: SUBSYSTEM=usb
|
||||||
|
E: TYPE=255/0/0
|
||||||
|
A: authorized=1\n
|
||||||
|
A: avoid_reset_quirk=0\n
|
||||||
|
A: bConfigurationValue=1\n
|
||||||
|
A: bDeviceClass=ff\n
|
||||||
|
A: bDeviceProtocol=00\n
|
||||||
|
A: bDeviceSubClass=00\n
|
||||||
|
A: bMaxPacketSize0=64\n
|
||||||
|
A: bMaxPower=100mA\n
|
||||||
|
A: bNumConfigurations=1\n
|
||||||
|
A: bNumInterfaces= 1\n
|
||||||
|
A: bcdDevice=1213\n
|
||||||
|
A: bmAttributes=a0\n
|
||||||
|
A: busnum=1\n
|
||||||
|
A: configuration=
|
||||||
|
H: descriptors=12010002FF0000407A1CA10513120102030109022700010100A0320904000003FF000000070581020002000705020200020007058303400005
|
||||||
|
A: dev=189:2\n
|
||||||
|
A: devnum=3\n
|
||||||
|
A: devpath=5\n
|
||||||
|
L: driver=../../../../../bus/usb/drivers/usb
|
||||||
|
L: firmware_node=../../../../LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:51/device:52/device:57
|
||||||
|
A: idProduct=05a1\n
|
||||||
|
A: idVendor=1c7a\n
|
||||||
|
A: ltm_capable=no\n
|
||||||
|
A: manufacturer=EGIS\n
|
||||||
|
A: maxchild=0\n
|
||||||
|
A: physical_location/dock=no\n
|
||||||
|
A: physical_location/horizontal_position=center\n
|
||||||
|
A: physical_location/lid=no\n
|
||||||
|
A: physical_location/panel=unknown\n
|
||||||
|
A: physical_location/vertical_position=center\n
|
||||||
|
L: port=../1-0:1.0/usb1-port5
|
||||||
|
A: power/active_duration=955612\n
|
||||||
|
A: power/async=enabled\n
|
||||||
|
A: power/autosuspend=2\n
|
||||||
|
A: power/autosuspend_delay_ms=2000\n
|
||||||
|
A: power/connected_duration=955612\n
|
||||||
|
A: power/control=on\n
|
||||||
|
A: power/level=on\n
|
||||||
|
A: power/persist=0\n
|
||||||
|
A: power/runtime_active_kids=0\n
|
||||||
|
A: power/runtime_active_time=955338\n
|
||||||
|
A: power/runtime_enabled=forbidden\n
|
||||||
|
A: power/runtime_status=active\n
|
||||||
|
A: power/runtime_suspended_time=0\n
|
||||||
|
A: power/runtime_usage=1\n
|
||||||
|
A: power/wakeup=disabled\n
|
||||||
|
A: power/wakeup_abort_count=\n
|
||||||
|
A: power/wakeup_active=\n
|
||||||
|
A: power/wakeup_active_count=\n
|
||||||
|
A: power/wakeup_count=\n
|
||||||
|
A: power/wakeup_expire_count=\n
|
||||||
|
A: power/wakeup_last_time_ms=\n
|
||||||
|
A: power/wakeup_max_time_ms=\n
|
||||||
|
A: power/wakeup_total_time_ms=\n
|
||||||
|
A: product=ETU905A80-E\n
|
||||||
|
A: quirks=0x0\n
|
||||||
|
A: removable=fixed\n
|
||||||
|
A: rx_lanes=1\n
|
||||||
|
A: serial=0C5A44PCU833\n
|
||||||
|
A: speed=480\n
|
||||||
|
A: tx_lanes=1\n
|
||||||
|
A: urbnum=491\n
|
||||||
|
A: version= 2.00\n
|
||||||
|
|
||||||
|
P: /devices/pci0000:00/0000:00:14.0/usb1
|
||||||
|
N: bus/usb/001/001=12010002090001406B1D020005060302010109021900010100E0000904000001090000000705810304000C
|
||||||
|
E: BUSNUM=001
|
||||||
|
E: CURRENT_TAGS=:seat:
|
||||||
|
E: DEVNAME=/dev/bus/usb/001/001
|
||||||
|
E: DEVNUM=001
|
||||||
|
E: DEVTYPE=usb_device
|
||||||
|
E: DRIVER=usb
|
||||||
|
E: ID_AUTOSUSPEND=1
|
||||||
|
E: ID_BUS=usb
|
||||||
|
E: ID_FOR_SEAT=usb-pci-0000_00_14_0
|
||||||
|
E: ID_MODEL=xHCI_Host_Controller
|
||||||
|
E: ID_MODEL_ENC=xHCI\x20Host\x20Controller
|
||||||
|
E: ID_MODEL_FROM_DATABASE=2.0 root hub
|
||||||
|
E: ID_MODEL_ID=0002
|
||||||
|
E: ID_PATH=pci-0000:00:14.0
|
||||||
|
E: ID_PATH_TAG=pci-0000_00_14_0
|
||||||
|
E: ID_REVISION=0605
|
||||||
|
E: ID_SERIAL=Linux_6.5.0-9-generic_xhci-hcd_xHCI_Host_Controller_0000:00:14.0
|
||||||
|
E: ID_SERIAL_SHORT=0000:00:14.0
|
||||||
|
E: ID_USB_INTERFACES=:090000:
|
||||||
|
E: ID_USB_MODEL=xHCI_Host_Controller
|
||||||
|
E: ID_USB_MODEL_ENC=xHCI\x20Host\x20Controller
|
||||||
|
E: ID_USB_MODEL_ID=0002
|
||||||
|
E: ID_USB_REVISION=0605
|
||||||
|
E: ID_USB_SERIAL=Linux_6.5.0-9-generic_xhci-hcd_xHCI_Host_Controller_0000:00:14.0
|
||||||
|
E: ID_USB_SERIAL_SHORT=0000:00:14.0
|
||||||
|
E: ID_USB_VENDOR=Linux_6.5.0-9-generic_xhci-hcd
|
||||||
|
E: ID_USB_VENDOR_ENC=Linux\x206.5.0-9-generic\x20xhci-hcd
|
||||||
|
E: ID_USB_VENDOR_ID=1d6b
|
||||||
|
E: ID_VENDOR=Linux_6.5.0-9-generic_xhci-hcd
|
||||||
|
E: ID_VENDOR_ENC=Linux\x206.5.0-9-generic\x20xhci-hcd
|
||||||
|
E: ID_VENDOR_FROM_DATABASE=Linux Foundation
|
||||||
|
E: ID_VENDOR_ID=1d6b
|
||||||
|
E: MAJOR=189
|
||||||
|
E: MINOR=0
|
||||||
|
E: PRODUCT=1d6b/2/605
|
||||||
|
E: SUBSYSTEM=usb
|
||||||
|
E: TAGS=:seat:
|
||||||
|
E: TYPE=9/0/1
|
||||||
|
A: authorized=1\n
|
||||||
|
A: authorized_default=1\n
|
||||||
|
A: avoid_reset_quirk=0\n
|
||||||
|
A: bConfigurationValue=1\n
|
||||||
|
A: bDeviceClass=09\n
|
||||||
|
A: bDeviceProtocol=01\n
|
||||||
|
A: bDeviceSubClass=00\n
|
||||||
|
A: bMaxPacketSize0=64\n
|
||||||
|
A: bMaxPower=0mA\n
|
||||||
|
A: bNumConfigurations=1\n
|
||||||
|
A: bNumInterfaces= 1\n
|
||||||
|
A: bcdDevice=0605\n
|
||||||
|
A: bmAttributes=e0\n
|
||||||
|
A: busnum=1\n
|
||||||
|
A: configuration=
|
||||||
|
H: descriptors=12010002090001406B1D020005060302010109021900010100E0000904000001090000000705810304000C
|
||||||
|
A: dev=189:0\n
|
||||||
|
A: devnum=1\n
|
||||||
|
A: devpath=0\n
|
||||||
|
L: driver=../../../../bus/usb/drivers/usb
|
||||||
|
L: firmware_node=../../../LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:51/device:52
|
||||||
|
A: idProduct=0002\n
|
||||||
|
A: idVendor=1d6b\n
|
||||||
|
A: interface_authorized_default=1\n
|
||||||
|
A: ltm_capable=no\n
|
||||||
|
A: manufacturer=Linux 6.5.0-9-generic xhci-hcd\n
|
||||||
|
A: maxchild=12\n
|
||||||
|
A: power/active_duration=956044\n
|
||||||
|
A: power/async=enabled\n
|
||||||
|
A: power/autosuspend=0\n
|
||||||
|
A: power/autosuspend_delay_ms=0\n
|
||||||
|
A: power/connected_duration=956044\n
|
||||||
|
A: power/control=auto\n
|
||||||
|
A: power/level=auto\n
|
||||||
|
A: power/runtime_active_kids=2\n
|
||||||
|
A: power/runtime_active_time=956041\n
|
||||||
|
A: power/runtime_enabled=enabled\n
|
||||||
|
A: power/runtime_status=active\n
|
||||||
|
A: power/runtime_suspended_time=0\n
|
||||||
|
A: power/runtime_usage=0\n
|
||||||
|
A: power/wakeup=disabled\n
|
||||||
|
A: power/wakeup_abort_count=\n
|
||||||
|
A: power/wakeup_active=\n
|
||||||
|
A: power/wakeup_active_count=\n
|
||||||
|
A: power/wakeup_count=\n
|
||||||
|
A: power/wakeup_expire_count=\n
|
||||||
|
A: power/wakeup_last_time_ms=\n
|
||||||
|
A: power/wakeup_max_time_ms=\n
|
||||||
|
A: power/wakeup_total_time_ms=\n
|
||||||
|
A: product=xHCI Host Controller\n
|
||||||
|
A: quirks=0x0\n
|
||||||
|
A: removable=unknown\n
|
||||||
|
A: rx_lanes=1\n
|
||||||
|
A: serial=0000:00:14.0\n
|
||||||
|
A: speed=480\n
|
||||||
|
A: tx_lanes=1\n
|
||||||
|
A: urbnum=181\n
|
||||||
|
A: version= 2.00\n
|
||||||
|
|
||||||
|
P: /devices/pci0000:00/0000:00:14.0
|
||||||
|
E: DRIVER=xhci_hcd
|
||||||
|
E: ID_MODEL_FROM_DATABASE=Alder Lake PCH USB 3.2 xHCI Host Controller
|
||||||
|
E: ID_PCI_CLASS_FROM_DATABASE=Serial bus controller
|
||||||
|
E: ID_PCI_INTERFACE_FROM_DATABASE=XHCI
|
||||||
|
E: ID_PCI_SUBCLASS_FROM_DATABASE=USB controller
|
||||||
|
E: ID_VENDOR_FROM_DATABASE=Intel Corporation
|
||||||
|
E: MODALIAS=pci:v00008086d000051EDsv0000144Dsd0000C1CAbc0Csc03i30
|
||||||
|
E: PCI_CLASS=C0330
|
||||||
|
E: PCI_ID=8086:51ED
|
||||||
|
E: PCI_SLOT_NAME=0000:00:14.0
|
||||||
|
E: PCI_SUBSYS_ID=144D:C1CA
|
||||||
|
E: SUBSYSTEM=pci
|
||||||
|
A: ari_enabled=0\n
|
||||||
|
A: broken_parity_status=0\n
|
||||||
|
A: class=0x0c0330\n
|
||||||
|
H: config=8680ED51060490020130030C0000800004001A3E6000000000000000000000000000000000000000000000004D14CAC1000000007000000000000000FF010000FD0134A089C27F8000000000000000003F6DD80F000000000000000000000000316000000000000000000000000000000180C2C108000000000000000000000005908700D804E0FE000000000000000009B014F01000400100000000C10A080000080E00001800008F50020000010000090000018680C00009001014000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000B50F110112000000
|
||||||
|
A: consistent_dma_mask_bits=64\n
|
||||||
|
A: d3cold_allowed=1\n
|
||||||
|
A: dbc=disabled\n
|
||||||
|
A: dbc_bInterfaceProtocol=01\n
|
||||||
|
A: dbc_bcdDevice=0010\n
|
||||||
|
A: dbc_idProduct=0010\n
|
||||||
|
A: dbc_idVendor=1d6b\n
|
||||||
|
A: device=0x51ed\n
|
||||||
|
A: dma_mask_bits=64\n
|
||||||
|
L: driver=../../../bus/pci/drivers/xhci_hcd
|
||||||
|
A: driver_override=(null)\n
|
||||||
|
A: enable=1\n
|
||||||
|
L: firmware_node=../../LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:51
|
||||||
|
A: index=9\n
|
||||||
|
L: iommu=../../virtual/iommu/dmar2
|
||||||
|
L: iommu_group=../../../kernel/iommu_groups/11
|
||||||
|
A: irq=142\n
|
||||||
|
A: label=Onboard - Other\n
|
||||||
|
A: local_cpulist=0-15\n
|
||||||
|
A: local_cpus=ffff\n
|
||||||
|
A: modalias=pci:v00008086d000051EDsv0000144Dsd0000C1CAbc0Csc03i30\n
|
||||||
|
A: msi_bus=1\n
|
||||||
|
A: msi_irqs/142=msi\n
|
||||||
|
A: numa_node=-1\n
|
||||||
|
A: pools=poolinfo - 0.1\nbuffer-2048 0 0 2048 0\nbuffer-512 0 0 512 0\nbuffer-128 0 0 128 0\nbuffer-32 0 0 32 0\nxHCI 1KB stream ctx arrays 0 0 1024 0\nxHCI 256 byte stream ctx arrays 0 0 256 0\nxHCI input/output contexts 6 7 2112 7\nxHCI ring segments 28 28 4096 28\nbuffer-2048 0 0 2048 0\nbuffer-512 0 0 512 0\nbuffer-128 1 32 128 1\nbuffer-32 0 0 32 0\n
|
||||||
|
A: power/async=enabled\n
|
||||||
|
A: power/control=auto\n
|
||||||
|
A: power/runtime_active_kids=1\n
|
||||||
|
A: power/runtime_active_time=957198\n
|
||||||
|
A: power/runtime_enabled=enabled\n
|
||||||
|
A: power/runtime_status=active\n
|
||||||
|
A: power/runtime_suspended_time=0\n
|
||||||
|
A: power/runtime_usage=0\n
|
||||||
|
A: power/wakeup=enabled\n
|
||||||
|
A: power/wakeup_abort_count=0\n
|
||||||
|
A: power/wakeup_active=0\n
|
||||||
|
A: power/wakeup_active_count=0\n
|
||||||
|
A: power/wakeup_count=0\n
|
||||||
|
A: power/wakeup_expire_count=0\n
|
||||||
|
A: power/wakeup_last_time_ms=0\n
|
||||||
|
A: power/wakeup_max_time_ms=0\n
|
||||||
|
A: power/wakeup_total_time_ms=0\n
|
||||||
|
A: power_state=D0\n
|
||||||
|
A: resource=0x000000603e1a0000 0x000000603e1affff 0x0000000000140204\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n
|
||||||
|
A: revision=0x01\n
|
||||||
|
A: subsystem_device=0xc1ca\n
|
||||||
|
A: subsystem_vendor=0x144d\n
|
||||||
|
A: vendor=0x8086\n
|
||||||
|
|
||||||
BIN
tests/egismoc/custom.pcapng
Normal file
BIN
tests/egismoc/custom.pcapng
Normal file
Binary file not shown.
156
tests/egismoc/custom.py
Executable file
156
tests/egismoc/custom.py
Executable file
@@ -0,0 +1,156 @@
|
|||||||
|
#!/usr/bin/python3
|
||||||
|
|
||||||
|
import traceback
|
||||||
|
import sys
|
||||||
|
import time
|
||||||
|
import gi
|
||||||
|
|
||||||
|
gi.require_version('FPrint', '2.0')
|
||||||
|
from gi.repository import FPrint, GLib
|
||||||
|
|
||||||
|
# Exit with error on any exception, included those happening in async callbacks
|
||||||
|
sys.excepthook = lambda *args: (traceback.print_exception(*args), sys.exit(1))
|
||||||
|
|
||||||
|
ctx = GLib.main_context_default()
|
||||||
|
|
||||||
|
c = FPrint.Context()
|
||||||
|
c.enumerate()
|
||||||
|
devices = c.get_devices()
|
||||||
|
|
||||||
|
d = devices[0]
|
||||||
|
del devices
|
||||||
|
|
||||||
|
d.open_sync()
|
||||||
|
|
||||||
|
assert d.get_driver() == "egismoc"
|
||||||
|
assert not d.has_feature(FPrint.DeviceFeature.CAPTURE)
|
||||||
|
assert d.has_feature(FPrint.DeviceFeature.IDENTIFY)
|
||||||
|
assert d.has_feature(FPrint.DeviceFeature.VERIFY)
|
||||||
|
assert d.has_feature(FPrint.DeviceFeature.DUPLICATES_CHECK)
|
||||||
|
assert d.has_feature(FPrint.DeviceFeature.STORAGE)
|
||||||
|
assert d.has_feature(FPrint.DeviceFeature.STORAGE_LIST)
|
||||||
|
assert d.has_feature(FPrint.DeviceFeature.STORAGE_DELETE)
|
||||||
|
assert d.has_feature(FPrint.DeviceFeature.STORAGE_CLEAR)
|
||||||
|
|
||||||
|
def enroll_progress(*args):
|
||||||
|
print("finger status: ", d.get_finger_status())
|
||||||
|
print('enroll progress: ' + str(args))
|
||||||
|
|
||||||
|
def identify_done(dev, res):
|
||||||
|
global identified
|
||||||
|
identified = True
|
||||||
|
identify_match, identify_print = dev.identify_finish(res)
|
||||||
|
print('indentification_done: ', identify_match, identify_print)
|
||||||
|
assert identify_match.equal(identify_print)
|
||||||
|
|
||||||
|
# Beginning with list and clear assumes you begin with >0 prints enrolled before capturing
|
||||||
|
|
||||||
|
print("listing - device should have prints")
|
||||||
|
stored = d.list_prints_sync()
|
||||||
|
assert len(stored) > 0
|
||||||
|
del stored
|
||||||
|
|
||||||
|
print("clear device storage")
|
||||||
|
d.clear_storage_sync()
|
||||||
|
print("clear done")
|
||||||
|
|
||||||
|
print("listing - device should be empty")
|
||||||
|
stored = d.list_prints_sync()
|
||||||
|
assert len(stored) == 0
|
||||||
|
del stored
|
||||||
|
|
||||||
|
print("enrolling")
|
||||||
|
template = FPrint.Print.new(d)
|
||||||
|
template.set_finger(FPrint.Finger.LEFT_INDEX)
|
||||||
|
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
|
||||||
|
p1 = d.enroll_sync(template, None, enroll_progress, None)
|
||||||
|
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
|
||||||
|
print("enroll done")
|
||||||
|
del template
|
||||||
|
|
||||||
|
print("listing - device should have 1 print")
|
||||||
|
stored = d.list_prints_sync()
|
||||||
|
assert len(stored) == 1
|
||||||
|
assert stored[0].equal(p1)
|
||||||
|
|
||||||
|
print("verifying")
|
||||||
|
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
|
||||||
|
verify_res, verify_print = d.verify_sync(p1)
|
||||||
|
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
|
||||||
|
print("verify done")
|
||||||
|
assert verify_res == True
|
||||||
|
|
||||||
|
identified = False
|
||||||
|
deserialized_prints = []
|
||||||
|
for p in stored:
|
||||||
|
deserialized_prints.append(FPrint.Print.deserialize(p.serialize()))
|
||||||
|
assert deserialized_prints[-1].equal(p)
|
||||||
|
del stored
|
||||||
|
|
||||||
|
print('async identifying')
|
||||||
|
d.identify(deserialized_prints, callback=identify_done)
|
||||||
|
del deserialized_prints
|
||||||
|
|
||||||
|
while not identified:
|
||||||
|
ctx.iteration(True)
|
||||||
|
|
||||||
|
print("try to enroll duplicate")
|
||||||
|
template = FPrint.Print.new(d)
|
||||||
|
template.set_finger(FPrint.Finger.RIGHT_INDEX)
|
||||||
|
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
|
||||||
|
try:
|
||||||
|
d.enroll_sync(template, None, enroll_progress, None)
|
||||||
|
except GLib.Error as error:
|
||||||
|
assert error.matches(FPrint.DeviceError.quark(),
|
||||||
|
FPrint.DeviceError.DATA_DUPLICATE)
|
||||||
|
except Exception as exc:
|
||||||
|
raise
|
||||||
|
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
|
||||||
|
print("duplicate enroll attempt done")
|
||||||
|
|
||||||
|
print("listing - device should still only have 1 print")
|
||||||
|
stored = d.list_prints_sync()
|
||||||
|
assert len(stored) == 1
|
||||||
|
assert stored[0].equal(p1)
|
||||||
|
del stored
|
||||||
|
|
||||||
|
print("enroll new finger")
|
||||||
|
template = FPrint.Print.new(d)
|
||||||
|
template.set_finger(FPrint.Finger.RIGHT_INDEX)
|
||||||
|
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
|
||||||
|
p2 = d.enroll_sync(template, None, enroll_progress, None)
|
||||||
|
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
|
||||||
|
print("enroll new finger done")
|
||||||
|
del template
|
||||||
|
|
||||||
|
print("listing - device should have 2 prints")
|
||||||
|
stored = d.list_prints_sync()
|
||||||
|
assert len(stored) == 2
|
||||||
|
assert (stored[0].equal(p1) and stored[1].equal(p2)) or (stored[0].equal(p2) and stored[1].equal(p1))
|
||||||
|
del stored
|
||||||
|
|
||||||
|
print("deleting first print")
|
||||||
|
d.delete_print_sync(p1)
|
||||||
|
print("delete done")
|
||||||
|
del p1
|
||||||
|
|
||||||
|
print("listing - device should only have second print")
|
||||||
|
stored = d.list_prints_sync()
|
||||||
|
assert len(stored) == 1
|
||||||
|
assert stored[0].equal(p2)
|
||||||
|
del stored
|
||||||
|
del p2
|
||||||
|
|
||||||
|
print("clear device storage")
|
||||||
|
d.clear_storage_sync()
|
||||||
|
print("clear done")
|
||||||
|
|
||||||
|
print("listing - device should be empty")
|
||||||
|
stored = d.list_prints_sync()
|
||||||
|
assert len(stored) == 0
|
||||||
|
del stored
|
||||||
|
|
||||||
|
d.close_sync()
|
||||||
|
|
||||||
|
del d
|
||||||
|
del c
|
||||||
281
tests/egismoc/device
Normal file
281
tests/egismoc/device
Normal file
@@ -0,0 +1,281 @@
|
|||||||
|
P: /devices/pci0000:00/0000:00:14.0/usb3/3-5
|
||||||
|
N: bus/usb/003/002=12010002FF0000407A1C820581110102030109022700010100A0320904000003FF000000070581020002000705020200020007058303400005
|
||||||
|
E: BUSNUM=003
|
||||||
|
E: CURRENT_TAGS=:snap_cups_ippeveprinter:snap_android-platform-tools_fastboot:snap_android-platform-tools_adb:snap_cups_cupsd:
|
||||||
|
E: DEVNAME=/dev/bus/usb/003/002
|
||||||
|
E: DEVNUM=002
|
||||||
|
E: DEVTYPE=usb_device
|
||||||
|
E: DRIVER=usb
|
||||||
|
E: ID_AUTOSUSPEND=1
|
||||||
|
E: ID_BUS=usb
|
||||||
|
E: ID_MODEL=ETU905A80-E
|
||||||
|
E: ID_MODEL_ENC=ETU905A80-E
|
||||||
|
E: ID_MODEL_ID=0582
|
||||||
|
E: ID_PATH=pci-0000:00:14.0-usb-0:5
|
||||||
|
E: ID_PATH_TAG=pci-0000_00_14_0-usb-0_5
|
||||||
|
E: ID_PATH_WITH_USB_REVISION=pci-0000:00:14.0-usbv2-0:5
|
||||||
|
E: ID_PERSIST=0
|
||||||
|
E: ID_PROCESSING=1
|
||||||
|
E: ID_REVISION=1181
|
||||||
|
E: ID_SERIAL=EGIS_ETU905A80-E_0E7828PBS393
|
||||||
|
E: ID_SERIAL_SHORT=0E7828PBS393
|
||||||
|
E: ID_USB_INTERFACES=:ff0000:
|
||||||
|
E: ID_USB_MODEL=ETU905A80-E
|
||||||
|
E: ID_USB_MODEL_ENC=ETU905A80-E
|
||||||
|
E: ID_USB_MODEL_ID=0582
|
||||||
|
E: ID_USB_REVISION=1181
|
||||||
|
E: ID_USB_SERIAL=EGIS_ETU905A80-E_0E7828PBS393
|
||||||
|
E: ID_USB_SERIAL_SHORT=0E7828PBS393
|
||||||
|
E: ID_USB_VENDOR=EGIS
|
||||||
|
E: ID_USB_VENDOR_ENC=EGIS
|
||||||
|
E: ID_USB_VENDOR_ID=1c7a
|
||||||
|
E: ID_VENDOR=EGIS
|
||||||
|
E: ID_VENDOR_ENC=EGIS
|
||||||
|
E: ID_VENDOR_FROM_DATABASE=LighTuning Technology Inc.
|
||||||
|
E: ID_VENDOR_ID=1c7a
|
||||||
|
E: MAJOR=189
|
||||||
|
E: MINOR=257
|
||||||
|
E: PRODUCT=1c7a/582/1181
|
||||||
|
E: SUBSYSTEM=usb
|
||||||
|
E: TAGS=:snap_cups_ippeveprinter:snap_android-platform-tools_fastboot:snap_cups_cupsd:snap_android-platform-tools_adb:
|
||||||
|
E: TYPE=255/0/0
|
||||||
|
A: authorized=1\n
|
||||||
|
A: avoid_reset_quirk=0\n
|
||||||
|
A: bConfigurationValue=1\n
|
||||||
|
A: bDeviceClass=ff\n
|
||||||
|
A: bDeviceProtocol=00\n
|
||||||
|
A: bDeviceSubClass=00\n
|
||||||
|
A: bMaxPacketSize0=64\n
|
||||||
|
A: bMaxPower=100mA\n
|
||||||
|
A: bNumConfigurations=1\n
|
||||||
|
A: bNumInterfaces= 1\n
|
||||||
|
A: bcdDevice=1181\n
|
||||||
|
A: bmAttributes=a0\n
|
||||||
|
A: busnum=3\n
|
||||||
|
A: configuration=
|
||||||
|
H: descriptors=12010002FF0000407A1C820581110102030109022700010100A0320904000003FF000000070581020002000705020200020007058303400005
|
||||||
|
A: dev=189:257\n
|
||||||
|
A: devnum=2\n
|
||||||
|
A: devpath=5\n
|
||||||
|
L: driver=../../../../../bus/usb/drivers/usb
|
||||||
|
L: firmware_node=../../../../LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:51/device:52/device:57
|
||||||
|
A: idProduct=0582\n
|
||||||
|
A: idVendor=1c7a\n
|
||||||
|
A: ltm_capable=no\n
|
||||||
|
A: manufacturer=EGIS\n
|
||||||
|
A: maxchild=0\n
|
||||||
|
A: physical_location/dock=no\n
|
||||||
|
A: physical_location/horizontal_position=center\n
|
||||||
|
A: physical_location/lid=no\n
|
||||||
|
A: physical_location/panel=unknown\n
|
||||||
|
A: physical_location/vertical_position=center\n
|
||||||
|
L: port=../3-0:1.0/usb3-port5
|
||||||
|
A: power/active_duration=2329204\n
|
||||||
|
A: power/async=enabled\n
|
||||||
|
A: power/autosuspend=2\n
|
||||||
|
A: power/autosuspend_delay_ms=2000\n
|
||||||
|
A: power/connected_duration=96447632\n
|
||||||
|
A: power/control=auto\n
|
||||||
|
A: power/level=auto\n
|
||||||
|
A: power/persist=1\n
|
||||||
|
A: power/runtime_active_kids=0\n
|
||||||
|
A: power/runtime_active_time=2345067\n
|
||||||
|
A: power/runtime_enabled=enabled\n
|
||||||
|
A: power/runtime_status=active\n
|
||||||
|
A: power/runtime_suspended_time=94056717\n
|
||||||
|
A: power/runtime_usage=0\n
|
||||||
|
A: power/wakeup=disabled\n
|
||||||
|
A: power/wakeup_abort_count=\n
|
||||||
|
A: power/wakeup_active=\n
|
||||||
|
A: power/wakeup_active_count=\n
|
||||||
|
A: power/wakeup_count=\n
|
||||||
|
A: power/wakeup_expire_count=\n
|
||||||
|
A: power/wakeup_last_time_ms=\n
|
||||||
|
A: power/wakeup_max_time_ms=\n
|
||||||
|
A: power/wakeup_total_time_ms=\n
|
||||||
|
A: product=ETU905A80-E\n
|
||||||
|
A: quirks=0x0\n
|
||||||
|
A: removable=fixed\n
|
||||||
|
A: rx_lanes=1\n
|
||||||
|
A: serial=0E7828PBS393\n
|
||||||
|
A: speed=480\n
|
||||||
|
A: tx_lanes=1\n
|
||||||
|
A: urbnum=10257\n
|
||||||
|
A: version= 2.00\n
|
||||||
|
|
||||||
|
P: /devices/pci0000:00/0000:00:14.0/usb3
|
||||||
|
N: bus/usb/003/001=12010002090001406B1D020015060302010109021900010100E0000904000001090000000705810304000C
|
||||||
|
E: BUSNUM=003
|
||||||
|
E: CURRENT_TAGS=:snap_cups_ippeveprinter:seat:snap_android-platform-tools_fastboot:snap_cups_cupsd:snap_android-platform-tools_adb:
|
||||||
|
E: DEVNAME=/dev/bus/usb/003/001
|
||||||
|
E: DEVNUM=001
|
||||||
|
E: DEVTYPE=usb_device
|
||||||
|
E: DRIVER=usb
|
||||||
|
E: ID_AUTOSUSPEND=1
|
||||||
|
E: ID_BUS=usb
|
||||||
|
E: ID_FOR_SEAT=usb-pci-0000_00_14_0
|
||||||
|
E: ID_MODEL=xHCI_Host_Controller
|
||||||
|
E: ID_MODEL_ENC=xHCI\x20Host\x20Controller
|
||||||
|
E: ID_MODEL_FROM_DATABASE=2.0 root hub
|
||||||
|
E: ID_MODEL_ID=0002
|
||||||
|
E: ID_PATH=pci-0000:00:14.0
|
||||||
|
E: ID_PATH_TAG=pci-0000_00_14_0
|
||||||
|
E: ID_REVISION=0615
|
||||||
|
E: ID_SERIAL=Linux_6.15.1_xhci-hcd_xHCI_Host_Controller_0000:00:14.0
|
||||||
|
E: ID_SERIAL_SHORT=0000:00:14.0
|
||||||
|
E: ID_USB_INTERFACES=:090000:
|
||||||
|
E: ID_USB_MODEL=xHCI_Host_Controller
|
||||||
|
E: ID_USB_MODEL_ENC=xHCI\x20Host\x20Controller
|
||||||
|
E: ID_USB_MODEL_ID=0002
|
||||||
|
E: ID_USB_REVISION=0615
|
||||||
|
E: ID_USB_SERIAL=Linux_6.15.1_xhci-hcd_xHCI_Host_Controller_0000:00:14.0
|
||||||
|
E: ID_USB_SERIAL_SHORT=0000:00:14.0
|
||||||
|
E: ID_USB_VENDOR=Linux_6.15.1_xhci-hcd
|
||||||
|
E: ID_USB_VENDOR_ENC=Linux\x206.15.1\x20xhci-hcd
|
||||||
|
E: ID_USB_VENDOR_ID=1d6b
|
||||||
|
E: ID_VENDOR=Linux_6.15.1_xhci-hcd
|
||||||
|
E: ID_VENDOR_ENC=Linux\x206.15.1\x20xhci-hcd
|
||||||
|
E: ID_VENDOR_FROM_DATABASE=Linux Foundation
|
||||||
|
E: ID_VENDOR_ID=1d6b
|
||||||
|
E: MAJOR=189
|
||||||
|
E: MINOR=256
|
||||||
|
E: PRODUCT=1d6b/2/615
|
||||||
|
E: SUBSYSTEM=usb
|
||||||
|
E: TAGS=:snap_cups_ippeveprinter:seat:snap_android-platform-tools_fastboot:snap_cups_cupsd:snap_android-platform-tools_adb:
|
||||||
|
E: TYPE=9/0/1
|
||||||
|
A: authorized=1\n
|
||||||
|
A: authorized_default=1\n
|
||||||
|
A: avoid_reset_quirk=0\n
|
||||||
|
A: bConfigurationValue=1\n
|
||||||
|
A: bDeviceClass=09\n
|
||||||
|
A: bDeviceProtocol=01\n
|
||||||
|
A: bDeviceSubClass=00\n
|
||||||
|
A: bMaxPacketSize0=64\n
|
||||||
|
A: bMaxPower=0mA\n
|
||||||
|
A: bNumConfigurations=1\n
|
||||||
|
A: bNumInterfaces= 1\n
|
||||||
|
A: bcdDevice=0615\n
|
||||||
|
A: bmAttributes=e0\n
|
||||||
|
A: busnum=3\n
|
||||||
|
A: configuration=
|
||||||
|
H: descriptors=12010002090001406B1D020015060302010109021900010100E0000904000001090000000705810304000C
|
||||||
|
A: dev=189:256\n
|
||||||
|
A: devnum=1\n
|
||||||
|
A: devpath=0\n
|
||||||
|
L: driver=../../../../bus/usb/drivers/usb
|
||||||
|
L: firmware_node=../../../LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:51/device:52
|
||||||
|
A: idProduct=0002\n
|
||||||
|
A: idVendor=1d6b\n
|
||||||
|
A: interface_authorized_default=1\n
|
||||||
|
A: ltm_capable=no\n
|
||||||
|
A: manufacturer=Linux 6.15.1 xhci-hcd\n
|
||||||
|
A: maxchild=12\n
|
||||||
|
A: power/active_duration=2362684\n
|
||||||
|
A: power/async=enabled\n
|
||||||
|
A: power/autosuspend=0\n
|
||||||
|
A: power/autosuspend_delay_ms=0\n
|
||||||
|
A: power/connected_duration=96447784\n
|
||||||
|
A: power/control=auto\n
|
||||||
|
A: power/level=auto\n
|
||||||
|
A: power/runtime_active_kids=1\n
|
||||||
|
A: power/runtime_active_time=2368910\n
|
||||||
|
A: power/runtime_enabled=enabled\n
|
||||||
|
A: power/runtime_status=active\n
|
||||||
|
A: power/runtime_suspended_time=94033284\n
|
||||||
|
A: power/runtime_usage=0\n
|
||||||
|
A: power/wakeup=disabled\n
|
||||||
|
A: power/wakeup_abort_count=\n
|
||||||
|
A: power/wakeup_active=\n
|
||||||
|
A: power/wakeup_active_count=\n
|
||||||
|
A: power/wakeup_count=\n
|
||||||
|
A: power/wakeup_expire_count=\n
|
||||||
|
A: power/wakeup_last_time_ms=\n
|
||||||
|
A: power/wakeup_max_time_ms=\n
|
||||||
|
A: power/wakeup_total_time_ms=\n
|
||||||
|
A: product=xHCI Host Controller\n
|
||||||
|
A: quirks=0x0\n
|
||||||
|
A: removable=unknown\n
|
||||||
|
A: rx_lanes=1\n
|
||||||
|
A: serial=0000:00:14.0\n
|
||||||
|
A: speed=480\n
|
||||||
|
A: tx_lanes=1\n
|
||||||
|
A: urbnum=7078\n
|
||||||
|
A: version= 2.00\n
|
||||||
|
|
||||||
|
P: /devices/pci0000:00/0000:00:14.0
|
||||||
|
E: DRIVER=xhci_hcd
|
||||||
|
E: ID_AUTOSUSPEND=1
|
||||||
|
E: ID_MODEL_FROM_DATABASE=Alder Lake PCH USB 3.2 xHCI Host Controller
|
||||||
|
E: ID_PATH=pci-0000:00:14.0
|
||||||
|
E: ID_PATH_TAG=pci-0000_00_14_0
|
||||||
|
E: ID_PCI_CLASS_FROM_DATABASE=Serial bus controller
|
||||||
|
E: ID_PCI_INTERFACE_FROM_DATABASE=XHCI
|
||||||
|
E: ID_PCI_SUBCLASS_FROM_DATABASE=USB controller
|
||||||
|
E: ID_VENDOR_FROM_DATABASE=Intel Corporation
|
||||||
|
E: MODALIAS=pci:v00008086d000051EDsv0000144Dsd0000C870bc0Csc03i30
|
||||||
|
E: PCI_CLASS=C0330
|
||||||
|
E: PCI_ID=8086:51ED
|
||||||
|
E: PCI_SLOT_NAME=0000:00:14.0
|
||||||
|
E: PCI_SUBSYS_ID=144D:C870
|
||||||
|
E: SUBSYSTEM=pci
|
||||||
|
A: ari_enabled=0\n
|
||||||
|
A: broken_parity_status=0\n
|
||||||
|
A: class=0x0c0330\n
|
||||||
|
H: config=8680ED51060490020130030C000080000400161D6000000000000000000000000000000000000000000000004D1470C8000000007000000000000000FF010000FD0134A089C27F8000000000000000003F6DD80F000000000000000000000000316000000000000000000000000000000180C2C10800000000000000000000000590B7001804E0FE000000000000000009B014F01000400100000000C10A080000080E00001800008F50020000010000090000018680C00009001014000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000B50F010112000000
|
||||||
|
A: consistent_dma_mask_bits=64\n
|
||||||
|
A: d3cold_allowed=1\n
|
||||||
|
A: dbc=disabled\n
|
||||||
|
A: dbc_bInterfaceProtocol=01\n
|
||||||
|
A: dbc_bcdDevice=0010\n
|
||||||
|
A: dbc_idProduct=0010\n
|
||||||
|
A: dbc_idVendor=1d6b\n
|
||||||
|
A: dbc_poll_interval_ms=64\n
|
||||||
|
A: device=0x51ed\n
|
||||||
|
A: dma_mask_bits=64\n
|
||||||
|
L: driver=../../../bus/pci/drivers/xhci_hcd
|
||||||
|
A: driver_override=(null)\n
|
||||||
|
A: enable=1\n
|
||||||
|
L: firmware_node=../../LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:51
|
||||||
|
A: index=7\n
|
||||||
|
L: iommu=../../virtual/iommu/dmar1
|
||||||
|
L: iommu_group=../../../kernel/iommu_groups/8
|
||||||
|
A: irq=133\n
|
||||||
|
A: label=Onboard - Other\n
|
||||||
|
A: local_cpulist=0-15\n
|
||||||
|
A: local_cpus=ffff\n
|
||||||
|
A: modalias=pci:v00008086d000051EDsv0000144Dsd0000C870bc0Csc03i30\n
|
||||||
|
A: msi_bus=1\n
|
||||||
|
A: msi_irqs/133=msi\n
|
||||||
|
A: msi_irqs/134=msi\n
|
||||||
|
A: msi_irqs/135=msi\n
|
||||||
|
A: msi_irqs/136=msi\n
|
||||||
|
A: msi_irqs/137=msi\n
|
||||||
|
A: msi_irqs/138=msi\n
|
||||||
|
A: msi_irqs/139=msi\n
|
||||||
|
A: msi_irqs/140=msi\n
|
||||||
|
A: numa_node=-1\n
|
||||||
|
A: pools=poolinfo - 0.1\nbuffer-2048 0 0 2048 0\nbuffer-512 0 0 512 0\nbuffer-128 0 0 128 0\nbuffer-32 0 0 32 0\nxHCI 1KB stream ctx arrays 0 0 1024 0\nxHCI 256 byte stream ctx arrays 0 0 256 0\nxHCI input/output contexts 6 7 2112 7\nxHCI ring segments 27 27 4096 27\nbuffer-2048 0 0 2048 0\nbuffer-512 0 0 512 0\nbuffer-128 0 0 128 0\nbuffer-32 0 0 32 0\n
|
||||||
|
A: power/async=enabled\n
|
||||||
|
A: power/control=auto\n
|
||||||
|
A: power/runtime_active_kids=1\n
|
||||||
|
A: power/runtime_active_time=2376480\n
|
||||||
|
A: power/runtime_enabled=enabled\n
|
||||||
|
A: power/runtime_status=active\n
|
||||||
|
A: power/runtime_suspended_time=94028360\n
|
||||||
|
A: power/runtime_usage=0\n
|
||||||
|
A: power/wakeup=enabled\n
|
||||||
|
A: power/wakeup_abort_count=0\n
|
||||||
|
A: power/wakeup_active=0\n
|
||||||
|
A: power/wakeup_active_count=1\n
|
||||||
|
A: power/wakeup_count=0\n
|
||||||
|
A: power/wakeup_expire_count=1\n
|
||||||
|
A: power/wakeup_last_time_ms=41666464\n
|
||||||
|
A: power/wakeup_max_time_ms=101\n
|
||||||
|
A: power/wakeup_total_time_ms=101\n
|
||||||
|
A: power_state=D0\n
|
||||||
|
A: resource=0x000000601d160000 0x000000601d16ffff 0x0000000000140204\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n
|
||||||
|
A: revision=0x01\n
|
||||||
|
A: subsystem_device=0xc870\n
|
||||||
|
A: subsystem_vendor=0x144d\n
|
||||||
|
A: vendor=0x8086\n
|
||||||
|
|
||||||
BIN
tests/focaltech_moc/custom.pcapng
Normal file
BIN
tests/focaltech_moc/custom.pcapng
Normal file
Binary file not shown.
89
tests/focaltech_moc/custom.py
Executable file
89
tests/focaltech_moc/custom.py
Executable file
@@ -0,0 +1,89 @@
|
|||||||
|
#!/usr/bin/python3
|
||||||
|
|
||||||
|
import traceback
|
||||||
|
import sys
|
||||||
|
import gi
|
||||||
|
|
||||||
|
gi.require_version('FPrint', '2.0')
|
||||||
|
from gi.repository import FPrint, GLib
|
||||||
|
|
||||||
|
# Exit with error on any exception, included those happening in async callbacks
|
||||||
|
sys.excepthook = lambda *args: (traceback.print_exception(*args), sys.exit(1))
|
||||||
|
|
||||||
|
ctx = GLib.main_context_default()
|
||||||
|
|
||||||
|
c = FPrint.Context()
|
||||||
|
c.enumerate()
|
||||||
|
devices = c.get_devices()
|
||||||
|
|
||||||
|
d = devices[0]
|
||||||
|
del devices
|
||||||
|
|
||||||
|
assert d.get_driver() == "focaltech_moc"
|
||||||
|
assert not d.has_feature(FPrint.DeviceFeature.CAPTURE)
|
||||||
|
assert d.has_feature(FPrint.DeviceFeature.IDENTIFY)
|
||||||
|
assert d.has_feature(FPrint.DeviceFeature.VERIFY)
|
||||||
|
assert not d.has_feature(FPrint.DeviceFeature.DUPLICATES_CHECK)
|
||||||
|
assert d.has_feature(FPrint.DeviceFeature.STORAGE)
|
||||||
|
assert d.has_feature(FPrint.DeviceFeature.STORAGE_LIST)
|
||||||
|
assert d.has_feature(FPrint.DeviceFeature.STORAGE_DELETE)
|
||||||
|
assert not d.has_feature(FPrint.DeviceFeature.STORAGE_CLEAR)
|
||||||
|
|
||||||
|
d.open_sync()
|
||||||
|
|
||||||
|
template = FPrint.Print.new(d)
|
||||||
|
|
||||||
|
def enroll_progress(*args):
|
||||||
|
#assert d.get_finger_status() == FPrint.FingerStatusFlags.NEEDED
|
||||||
|
print("finger status: ", d.get_finger_status())
|
||||||
|
print('enroll progress: ' + str(args))
|
||||||
|
|
||||||
|
def identify_done(dev, res):
|
||||||
|
global identified
|
||||||
|
identified = True
|
||||||
|
identify_match, identify_print = dev.identify_finish(res)
|
||||||
|
print('indentification_done: ', identify_match, identify_print)
|
||||||
|
assert identify_match.equal(identify_print)
|
||||||
|
|
||||||
|
# List, enroll, list, verify, identify, delete
|
||||||
|
print("enrolling")
|
||||||
|
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
|
||||||
|
p = d.enroll_sync(template, None, enroll_progress, None)
|
||||||
|
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
|
||||||
|
print("enroll done")
|
||||||
|
|
||||||
|
print("listing")
|
||||||
|
stored = d.list_prints_sync()
|
||||||
|
print("listing done")
|
||||||
|
assert len(stored) == 1
|
||||||
|
assert stored[0].equal(p)
|
||||||
|
print("verifying")
|
||||||
|
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
|
||||||
|
verify_res, verify_print = d.verify_sync(p)
|
||||||
|
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
|
||||||
|
print("verify done")
|
||||||
|
del p
|
||||||
|
assert verify_res == True
|
||||||
|
|
||||||
|
identified = False
|
||||||
|
deserialized_prints = []
|
||||||
|
for p in stored:
|
||||||
|
deserialized_prints.append(FPrint.Print.deserialize(p.serialize()))
|
||||||
|
assert deserialized_prints[-1].equal(p)
|
||||||
|
del stored
|
||||||
|
|
||||||
|
print('async identifying')
|
||||||
|
d.identify(deserialized_prints, callback=identify_done)
|
||||||
|
del deserialized_prints
|
||||||
|
|
||||||
|
while not identified:
|
||||||
|
ctx.iteration(True)
|
||||||
|
|
||||||
|
print("deleting")
|
||||||
|
d.delete_print_sync(p)
|
||||||
|
print("delete done")
|
||||||
|
|
||||||
|
d.close_sync()
|
||||||
|
|
||||||
|
del d
|
||||||
|
del c
|
||||||
385
tests/focaltech_moc/device
Normal file
385
tests/focaltech_moc/device
Normal file
File diff suppressed because one or more lines are too long
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user