diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..07d7399
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,3 @@
+*.o
+*.swp
+_build
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 71f5582..4f9afac 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -19,7 +19,7 @@ default:
variables:
extends: .libfprint_common_variables
FDO_DISTRIBUTION_TAG: $LIBFPRINT_IMAGE_TAG
- FDO_DISTRIBUTION_VERSION: rawhide
+ FDO_DISTRIBUTION_VERSION: 41
FDO_UPSTREAM_REPO: "libfprint/$CI_PROJECT_NAME"
FEDORA_IMAGE: "$CI_REGISTRY/libfprint/$CI_PROJECT_NAME/fedora/$FDO_DISTRIBUTION_VERSION:$FDO_DISTRIBUTION_TAG"
LAST_ABI_BREAK: "056ea541ddc97f5806cffbd99a12dc87e4da3546"
@@ -28,6 +28,8 @@ workflow:
rules:
- if: $CI_PIPELINE_SOURCE == 'merge_request_event'
- if: $CI_PIPELINE_SOURCE == 'push'
+ - if: $CI_PIPELINE_SOURCE == 'schedule'
+ - if: $CI_PROJECT_NAMESPACE == 'libfprint' && $LIBFPRINT_CI_ACTION != ''
stages:
- image-build
@@ -35,12 +37,13 @@ stages:
- build
- test
- flatpak
+ - deploy
image: $FEDORA_IMAGE
.build_one_driver_template: &build_one_driver
script:
- # Build with a driver that doesn't need imaging, or nss
+ # Build with a driver that doesn't need imaging, or openssl
- meson setup _build --werror -Ddrivers=$driver
- meson compile -C _build
- rm -rf _build/
@@ -56,11 +59,16 @@ image: $FEDORA_IMAGE
script:
- ./.ci/check-abi ${LAST_ABI_BREAK} $(git rev-parse HEAD)
+.standard_job:
+ rules:
+ - when: on_success
+ - if: $CI_PIPELINE_SOURCE == "schedule"
+ when: never
+
build:
stage: build
- except:
- variables:
- - $CI_PIPELINE_SOURCE == "schedule"
+ extends:
+ - .standard_job
variables:
driver: virtual_image
<<: *build_one_driver
@@ -75,9 +83,8 @@ build:
test:
stage: test
- except:
- variables:
- - $CI_PIPELINE_SOURCE == "schedule"
+ extends:
+ - .standard_job
script:
- meson setup _build --werror -Ddrivers=all -Db_coverage=true
- meson test -C _build --print-errorlogs --no-stdsplit --timeout-multiplier 3
@@ -99,9 +106,8 @@ test:
test_valgrind:
stage: test
- except:
- variables:
- - $CI_PIPELINE_SOURCE == "schedule"
+ extends:
+ - .standard_job
script:
- meson setup _build -Ddrivers=all
- meson compile -C _build
@@ -116,11 +122,27 @@ test_valgrind:
- _build/meson-logs/testlog-valgrind.txt
expire_in: 1 week
+test_asan:
+ stage: test
+ extends:
+ - .standard_job
+ script:
+ - meson setup _build -Ddrivers=all -Db_sanitize=address,undefined
+ - meson test -C _build --print-errorlogs --no-stdsplit
+ artifacts:
+ reports:
+ junit: "_build/meson-logs/testlog.junit.xml"
+ expose_as: 'Sanitizers test logs'
+ when: always
+ paths:
+ - _build/meson-logs
+ - _build/meson-logs/testlog.txt
+ expire_in: 1 week
+
test_installed:
stage: test
- except:
- variables:
- - $CI_PIPELINE_SOURCE == "schedule"
+ extends:
+ - .standard_job
script:
- meson setup _build --prefix=/usr -Ddrivers=all
- meson install -C _build
@@ -142,9 +164,8 @@ test_installed:
test_scan_build:
stage: test
- except:
- variables:
- - $CI_PIPELINE_SOURCE == "schedule"
+ extends:
+ - .standard_job
allow_failure: true
script:
- meson setup _build -Ddrivers=all
@@ -159,19 +180,23 @@ test_scan_build:
test_indent:
stage: check-source
- except:
- variables:
- - $CI_PIPELINE_SOURCE == "schedule"
+ extends:
+ - .standard_job
script:
- scripts/uncrustify.sh
- git diff
- git diff-index --name-only --exit-code HEAD
+ rules:
+ - changes:
+ compare_to: 'refs/heads/master'
+ paths:
+ - '**/*.c'
+ - '**/*.h'
test_unsupported_list:
stage: check-source
- except:
- variables:
- - $CI_PIPELINE_SOURCE == "schedule"
+ extends:
+ - .standard_job
allow_failure: true
script:
- tests/hwdb-check-unsupported.py
@@ -191,7 +216,7 @@ flatpak:
- if: '$CI_PROJECT_PATH != "libfprint/libfprint"'
when: manual
allow_failure: true
- - if: '$CI_PIPELINE_SOURCE == "schedule"'
+ - if: $CI_PIPELINE_SOURCE == "schedule"
when: never
- if: '$CI_COMMIT_BRANCH == "master"'
allow_failure: true
@@ -212,9 +237,6 @@ flatpak:
.container_fedora_build_base:
extends: .fdo.container-build@fedora
stage: image-build
- only:
- variables:
- - $CI_PIPELINE_SOURCE == "never"
variables:
GIT_STRATEGY: none # no need to pull the whole tree for rebuilding the image
# a list of packages to install
@@ -225,6 +247,8 @@ flatpak:
libudev-devel
FDO_DISTRIBUTION_EXEC: |
$LIBFPRINT_EXEC
+ rules:
+ - when: never
.container_fedora_build_forced:
variables:
@@ -234,25 +258,39 @@ container_fedora_build_schedule:
extends:
- .container_fedora_build_base
- .container_fedora_build_forced
- only:
- variables:
- - $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:
extends:
- .container_fedora_build_base
- .container_fedora_build_forced
- only:
- variables:
- - $LIBFPRINT_CI_ACTION == "build-image"
+ rules:
+ - if: $LIBFPRINT_CI_ACTION == "build-image"
+ when: always
container_fedora_build_on_deps_changed:
extends: .container_fedora_build_base
- only:
- variables:
- - $CI_PROJECT_NAMESPACE == "libfprint" && $CI_PIPELINE_SOURCE != "schedule"
- refs:
- - branches
- - merge_requests
- changes:
- - .gitlab-ci/libfprint-image-variables.yaml
+ rules:
+ - if: $CI_PROJECT_NAMESPACE == "libfprint" && $CI_PIPELINE_SOURCE != "schedule"
+ changes:
+ compare_to: 'refs/heads/master'
+ paths:
+ - '.gitlab-ci/libfprint-image-variables.yaml'
+ - '.gitlab-ci/libfprint-templates.yaml'
+
+pages:
+ image: alpine:latest
+ stage: deploy
+ needs:
+ - job: test
+ artifacts: true
+ script:
+ - mkdir public
+ - mv _build/meson-logs/coveragereport public/coverage
+ artifacts:
+ paths:
+ - public
+ rules:
+ - if: $CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH
diff --git a/.gitlab-ci/libfprint-image-variables.yaml b/.gitlab-ci/libfprint-image-variables.yaml
index e568839..03525b4 100644
--- a/.gitlab-ci/libfprint-image-variables.yaml
+++ b/.gitlab-ci/libfprint-image-variables.yaml
@@ -1,2 +1,2 @@
variables:
- LIBFPRINT_IMAGE_TAG: v3
+ LIBFPRINT_IMAGE_TAG: v6
diff --git a/.gitlab-ci/libfprint-templates.yaml b/.gitlab-ci/libfprint-templates.yaml
index 9c8de1c..6401cfa 100644
--- a/.gitlab-ci/libfprint-templates.yaml
+++ b/.gitlab-ci/libfprint-templates.yaml
@@ -3,6 +3,7 @@
.libfprint_common_variables:
LIBFPRINT_DEPENDENCIES:
+ appstream
doxygen
dnf-plugins-core
flatpak-builder
@@ -17,12 +18,14 @@
gtk-doc
gtk3-devel
libabigail
+ libasan
libgusb-devel
libgudev-devel
+ libubsan
libX11-devel
libXv-devel
meson
- nss-devel
+ openssl-devel
pixman-devel
python3-cairo
python3-gobject
@@ -40,10 +43,5 @@
glibc \
libgusb \
libusb \
- nss \
+ openssl \
pixman
-
- git clone https://github.com/martinpitt/umockdev.git && \
- cd umockdev && \
- meson _build --prefix=/usr && \
- ninja -C _build && ninja -C _build install
diff --git a/.gitlab-ci/scan-build b/.gitlab-ci/scan-build
index 0aa8c99..da24849 100755
--- a/.gitlab-ci/scan-build
+++ b/.gitlab-ci/scan-build
@@ -1,4 +1,4 @@
#!/bin/sh
# This wrapper just disables the malloc checker
-exec /usr/bin/scan-build --status-bugs -disable-checker unix.Malloc "$@"
\ No newline at end of file
+exec /usr/bin/scan-build --status-bugs -disable-checker unix.Malloc --exclude "_build/meson-private" "$@"
diff --git a/NEWS b/NEWS
index 44a048f..b945e9f 100644
--- a/NEWS
+++ b/NEWS
@@ -1,6 +1,35 @@
This file lists notable changes in each release. For the full history of all
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:
diff --git a/README.md b/README.md
index 2e52403..34ad811 100644
--- a/README.md
+++ b/README.md
@@ -46,6 +46,12 @@ We include **Bozorth3** from the **[US Export Controlled]**
distribution, which we have determined to be fine
being shipped in an open source project.
+## Get in *touch*
+
+ - [IRC] - `#fprint` @ `irc.oftc.net`
+ - [Matrix] - `#fprint:matrix.org` bridged to the IRC channel
+ - [MailingList] - low traffic, not much used these days
+
@@ -62,6 +68,9 @@ being shipped in an open source project.
[Unsupported]: https://gitlab.freedesktop.org/libfprint/wiki/-/wikis/Unsupported-Devices
[Supported]: https://fprint.freedesktop.org/supported-devices.html
[Website]: https://fprint.freedesktop.org/
+[MailingList]: https://lists.freedesktop.org/mailman/listinfo/fprint
+[IRC]: ircs://irc.oftc.net:6697/#fprint
+[Matrix]: https://matrix.to/#/#fprint:matrix.org
[Contribute]: ./HACKING.md
[License]: ./COPYING
diff --git a/data/autosuspend.hwdb b/data/autosuspend.hwdb
index 74ac65b..9115fb0 100644
--- a/data/autosuspend.hwdb
+++ b/data/autosuspend.hwdb
@@ -79,6 +79,9 @@ usb:v1C7Ap0571*
# Supported by libfprint driver egismoc
usb:v1C7Ap0582*
+usb:v1C7Ap0583*
+usb:v1C7Ap0586*
+usb:v1C7Ap0587*
usb:v1C7Ap05A1*
ID_AUTOSUSPEND=1
ID_PERSIST=0
@@ -155,7 +158,11 @@ usb:v04F3p0C82*
usb:v04F3p0C88*
usb:v04F3p0C8C*
usb:v04F3p0C8D*
+usb:v04F3p0C98*
usb:v04F3p0C99*
+usb:v04F3p0C9D*
+usb:v04F3p0C9F*
+usb:v04F3p0CA3*
ID_AUTOSUSPEND=1
ID_PERSIST=0
@@ -168,6 +175,9 @@ usb:v1C7Ap0603*
usb:v2808p9E48*
usb:v2808pD979*
usb:v2808pA959*
+usb:v2808pA99A*
+usb:v2808pA57A*
+usb:v2808pA78A*
ID_AUTOSUSPEND=1
ID_PERSIST=0
@@ -177,6 +187,9 @@ usb:v10A5pA305*
usb:v10A5pDA04*
usb:v10A5pD805*
usb:v10A5pD205*
+usb:v10A5p9524*
+usb:v10A5p9544*
+usb:v10A5pC844*
ID_AUTOSUSPEND=1
ID_PERSIST=0
@@ -185,10 +198,12 @@ usb:v27C6p5840*
usb:v27C6p6014*
usb:v27C6p6092*
usb:v27C6p6094*
+usb:v27C6p609A*
usb:v27C6p609C*
usb:v27C6p60A2*
usb:v27C6p60A4*
usb:v27C6p60BC*
+usb:v27C6p60C2*
usb:v27C6p6304*
usb:v27C6p631C*
usb:v27C6p633C*
@@ -199,6 +214,8 @@ usb:v27C6p63AC*
usb:v27C6p63BC*
usb:v27C6p63CC*
usb:v27C6p6496*
+usb:v27C6p650A*
+usb:v27C6p650C*
usb:v27C6p6582*
usb:v27C6p6584*
usb:v27C6p658C*
@@ -207,6 +224,8 @@ usb:v27C6p6594*
usb:v27C6p659A*
usb:v27C6p659C*
usb:v27C6p6A94*
+usb:v27C6p6512*
+usb:v27C6p689A*
ID_AUTOSUSPEND=1
ID_PERSIST=0
@@ -217,27 +236,35 @@ usb:v298Dp1010*
# Supported by libfprint driver realtek
usb:v0BDAp5813*
+usb:v0BDAp5816*
ID_AUTOSUSPEND=1
ID_PERSIST=0
# Supported by libfprint driver synaptics
usb:v06CBp00BD*
+usb:v06CBp00C2*
+usb:v06CBp00C4*
+usb:v06CBp00C6*
usb:v06CBp00DF*
+usb:v06CBp00F0*
usb:v06CBp00F9*
usb:v06CBp00FC*
-usb:v06CBp00C2*
usb:v06CBp0100*
-usb:v06CBp00F0*
usb:v06CBp0103*
+usb:v06CBp0104*
+usb:v06CBp0106*
+usb:v06CBp0107*
+usb:v06CBp0108*
usb:v06CBp0123*
usb:v06CBp0124*
usb:v06CBp0126*
usb:v06CBp0129*
-usb:v06CBp0168*
usb:v06CBp015F*
-usb:v06CBp0104*
+usb:v06CBp0168*
+usb:v06CBp016C*
usb:v06CBp0173*
-usb:v06CBp0106*
+usb:v06CBp0174*
+usb:v06CBp019D*
ID_AUTOSUSPEND=1
ID_PERSIST=0
@@ -306,7 +333,10 @@ usb:v138Ap0091*
ID_PERSIST=0
# Known unsupported devices
+usb:v0A5Cp5802*
usb:v047Dp00F2*
+usb:v047Dp8054*
+usb:v047Dp8055*
usb:v04E8p730B*
usb:v04F3p036B*
usb:v04F3p0C00*
@@ -314,16 +344,25 @@ usb:v04F3p0C4C*
usb:v04F3p0C57*
usb:v04F3p0C5E*
usb:v04F3p0C5A*
+usb:v04F3p0C60*
usb:v04F3p0C6C*
usb:v04F3p0C70*
usb:v04F3p0C72*
usb:v04F3p0C77*
+usb:v04F3p0C7C*
+usb:v04F3p0C7F*
+usb:v04F3p0C80*
+usb:v04F3p0C85*
+usb:v04F3p0C90*
usb:v04F3p2706*
usb:v04F3p3032*
usb:v04F3p3057*
usb:v04F3p3104*
usb:v04F3p310D*
usb:v04F3p3128*
+usb:v04F3p0C8A*
+usb:v05BAp000E*
+usb:v06CBp0051*
usb:v06CBp0081*
usb:v06CBp0088*
usb:v06CBp008A*
@@ -334,7 +373,6 @@ usb:v06CBp00A8*
usb:v06CBp00B7*
usb:v06CBp00BB*
usb:v06CBp00BE*
-usb:v06CBp00C4*
usb:v06CBp00CB*
usb:v06CBp00C9*
usb:v06CBp00D8*
@@ -344,6 +382,7 @@ usb:v06CBp00E4*
usb:v06CBp00E7*
usb:v06CBp00E9*
usb:v06CBp00FD*
+usb:v06CBp00FF*
usb:v0A5Cp5801*
usb:v0A5Cp5805*
usb:v0A5Cp5834*
@@ -353,10 +392,18 @@ usb:v0A5Cp5842*
usb:v0A5Cp5843*
usb:v0A5Cp5844*
usb:v0A5Cp5845*
+usb:v0A5Cp5860*
+usb:v0A5Cp5863*
+usb:v0A5Cp5864*
+usb:v0A5Cp5865*
+usb:v0A5Cp5866*
+usb:v0A5Cp5867*
usb:v0BDAp5812*
usb:v10A5p0007*
usb:v10A5p9200*
usb:v10A5p9800*
+usb:v10A5pA120*
+usb:v10A5pA900*
usb:v10A5pE340*
usb:v1188p9545*
usb:v138Ap0007*
@@ -377,7 +424,11 @@ usb:v16D1p1027*
usb:v1C7Ap0300*
usb:v1C7Ap0575*
usb:v1C7Ap0576*
+usb:v1C7Ap0584*
usb:v1C7Ap0577*
+usb:v1C7Ap057E*
+usb:v2541p0236*
+usb:v2541p9711*
usb:v27C6p5042*
usb:v27C6p5110*
usb:v27C6p5117*
@@ -406,11 +457,17 @@ usb:v27C6p5740*
usb:v27C6p5E0A*
usb:v27C6p581A*
usb:v27C6p589A*
+usb:v27C6p5F10*
usb:v27C6p6382*
usb:v2808p9338*
+usb:v2808p9348*
usb:v2808p93A9*
+usb:v2808pA658*
+usb:v2808pC652*
usb:v298Dp2020*
usb:v298Dp2033*
+usb:v2DF0p0003*
+usb:v3274p8012*
usb:v3538p0930*
ID_AUTOSUSPEND=1
ID_PERSIST=0
diff --git a/debian/changelog b/debian/changelog
index fd019b2..9425bd0 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,14 +1,44 @@
-libfprint (1:1.94.7-2deepin2) unstable; urgency=medium
+libfprint (1:1.94.9-1deepin2) unstable; urgency=medium
- * add uru4000 suspend/resume.
+ * Add riscv64 timeout multiplier support in debian/rules
- -- lichenggang
Thu, 27 Nov 2025 13:46:41 +0800
+ -- lichenggang Wed, 11 Mar 2026 14:30:00 +0800
-libfprint (1:1.94.7-2deepin1) unstable; urgency=medium
+libfprint (1:1.94.9-1deepin1) unstable; urgency=medium
- * Disable ut synaptice and focaltech_moc
+ * Apply deepin patches:
+ - Disable synaptics and focaltech_moc tests
+ - Add uru4000 suspend/resume support
+ - Add error handling for fpi_device_suspend_complete
+ - Skip fpi-device tests
- -- xiangzelong Thu, 30 May 2024 15:15:32 +0800
+ -- lichenggang Wed, 11 Mar 2026 14:10:00 +0800
+
+libfprint (1:1.94.9-1) unstable; urgency=medium
+
+ * New upstream release
+ * debian/libfprint-2-2.postinst: Devices triggers updated
+ * debian/libfprint-2-2.install: Install metainfo data
+ * debian/control: Replace NSS build dependency with OpenSSL
+ * debian/control: Add b-d on GLib and Gio gir dev packages
+
+ -- Marco Trevisan (Treviño) Thu, 20 Feb 2025 19:01:13 +0100
+
+libfprint (1:1.94.8-2) unstable; urgency=medium
+
+ * debian/control: Build-Depend on dh-sequence-gir
+
+ -- Marco Trevisan (Treviño) Tue, 03 Sep 2024 06:02:52 +0200
+
+libfprint (1:1.94.8-1) unstable; urgency=medium
+
+ * New upstream release
+ * debian/watch: Update
+ * debian/libfprint-2-2.postinst: Devices triggers updated
+ * debian/patches: Drop, applied upstream
+ * debian/control: Update Standards Version (no change required)
+
+ -- Marco Trevisan (Treviño) Tue, 03 Sep 2024 05:41:34 +0200
libfprint (1:1.94.7-2) unstable; urgency=medium
diff --git a/debian/control b/debian/control
index 77ee6a3..7102656 100644
--- a/debian/control
+++ b/debian/control
@@ -5,17 +5,17 @@ Maintainer: FingerForce Team
Uploaders: Ulises Vitulli ,
Marco Trevisan
Build-Depends: debhelper-compat (= 13),
- gir1.2-gobject-2.0-dev ,
- gir1.2-gio-2.0-dev ,
- gobject-introspection,
+ dh-sequence-gir,
+ gir1.2-gobject-2.0-dev,
+ gir1.2-gio-2.0-dev,
gtk-doc-tools,
libcairo-dev ,
libgirepository1.0-dev,
libglib2.0-dev,
libgudev-1.0-dev,
libgusb-dev,
- libnss3-dev,
libpixman-1-dev,
+ libssl-dev,
meson,
python3 ,
python3-cairo ,
@@ -23,7 +23,7 @@ Build-Depends: debhelper-compat (= 13),
systemd-dev,
umockdev
Build-Depends-Indep: libglib2.0-doc , libgusb-doc
-Standards-Version: 4.6.2
+Standards-Version: 4.7.0
Homepage: https://www.freedesktop.org/wiki/Software/fprint/libfprint
Vcs-Browser: https://salsa.debian.org/debian/libfprint
Vcs-Git: https://salsa.debian.org/debian/libfprint.git
diff --git a/debian/libfprint-2-2.install b/debian/libfprint-2-2.install
index 8dd1e0a..1f88c0e 100644
--- a/debian/libfprint-2-2.install
+++ b/debian/libfprint-2-2.install
@@ -1,3 +1,4 @@
usr/lib/udev/hwdb.d/
usr/lib/udev/rules.d/
usr/lib/${DEB_HOST_MULTIARCH}/libfprint-[0-9].so.*
+usr/share/metainfo/org.freedesktop.libfprint.metainfo.xml
diff --git a/debian/libfprint-2-2.postinst b/debian/libfprint-2-2.postinst
index d77fb5d..36e4e28 100644
--- a/debian/libfprint-2-2.postinst
+++ b/debian/libfprint-2-2.postinst
@@ -56,6 +56,9 @@ if [ "$1" = "configure" -o "$1" = "upgrade" ] && command -V udevadm >/dev/null 2
udevadm trigger --action=add --attr-match=idVendor=1c7a --attr-match=idProduct=0570 || true
udevadm trigger --action=add --attr-match=idVendor=1c7a --attr-match=idProduct=0571 || true
udevadm trigger --action=add --attr-match=idVendor=1c7a --attr-match=idProduct=0582 || true
+ udevadm trigger --action=add --attr-match=idVendor=1c7a --attr-match=idProduct=0583 || true
+ udevadm trigger --action=add --attr-match=idVendor=1c7a --attr-match=idProduct=0586 || true
+ udevadm trigger --action=add --attr-match=idVendor=1c7a --attr-match=idProduct=0587 || true
udevadm trigger --action=add --attr-match=idVendor=1c7a --attr-match=idProduct=05a1 || true
udevadm trigger --action=add --attr-match=idVendor=04f3 --attr-match=idProduct=0903 || true
udevadm trigger --action=add --attr-match=idVendor=04f3 --attr-match=idProduct=0907 || true
@@ -124,24 +127,36 @@ if [ "$1" = "configure" -o "$1" = "upgrade" ] && command -V udevadm >/dev/null 2
udevadm trigger --action=add --attr-match=idVendor=04f3 --attr-match=idProduct=0c88 || true
udevadm trigger --action=add --attr-match=idVendor=04f3 --attr-match=idProduct=0c8c || true
udevadm trigger --action=add --attr-match=idVendor=04f3 --attr-match=idProduct=0c8d || true
+ udevadm trigger --action=add --attr-match=idVendor=04f3 --attr-match=idProduct=0c98 || true
udevadm trigger --action=add --attr-match=idVendor=04f3 --attr-match=idProduct=0c99 || true
+ udevadm trigger --action=add --attr-match=idVendor=04f3 --attr-match=idProduct=0c9d || true
+ udevadm trigger --action=add --attr-match=idVendor=04f3 --attr-match=idProduct=0c9f || true
+ udevadm trigger --action=add --attr-match=idVendor=04f3 --attr-match=idProduct=0ca3 || true
udevadm trigger --action=add --attr-match=idVendor=1c7a --attr-match=idProduct=0603 || true
udevadm trigger --action=add --attr-match=idVendor=2808 --attr-match=idProduct=9e48 || true
udevadm trigger --action=add --attr-match=idVendor=2808 --attr-match=idProduct=d979 || true
udevadm trigger --action=add --attr-match=idVendor=2808 --attr-match=idProduct=a959 || true
+ udevadm trigger --action=add --attr-match=idVendor=2808 --attr-match=idProduct=a99a || true
+ udevadm trigger --action=add --attr-match=idVendor=2808 --attr-match=idProduct=a57a || true
+ udevadm trigger --action=add --attr-match=idVendor=2808 --attr-match=idProduct=a78a || true
udevadm trigger --action=add --attr-match=idVendor=10a5 --attr-match=idProduct=ffe0 || true
udevadm trigger --action=add --attr-match=idVendor=10a5 --attr-match=idProduct=a305 || true
udevadm trigger --action=add --attr-match=idVendor=10a5 --attr-match=idProduct=da04 || true
udevadm trigger --action=add --attr-match=idVendor=10a5 --attr-match=idProduct=d805 || true
udevadm trigger --action=add --attr-match=idVendor=10a5 --attr-match=idProduct=d205 || true
+ udevadm trigger --action=add --attr-match=idVendor=10a5 --attr-match=idProduct=9524 || true
+ udevadm trigger --action=add --attr-match=idVendor=10a5 --attr-match=idProduct=9544 || true
+ udevadm trigger --action=add --attr-match=idVendor=10a5 --attr-match=idProduct=c844 || true
udevadm trigger --action=add --attr-match=idVendor=27c6 --attr-match=idProduct=5840 || true
udevadm trigger --action=add --attr-match=idVendor=27c6 --attr-match=idProduct=6014 || true
udevadm trigger --action=add --attr-match=idVendor=27c6 --attr-match=idProduct=6092 || true
udevadm trigger --action=add --attr-match=idVendor=27c6 --attr-match=idProduct=6094 || true
+ udevadm trigger --action=add --attr-match=idVendor=27c6 --attr-match=idProduct=609a || true
udevadm trigger --action=add --attr-match=idVendor=27c6 --attr-match=idProduct=609c || true
udevadm trigger --action=add --attr-match=idVendor=27c6 --attr-match=idProduct=60a2 || true
udevadm trigger --action=add --attr-match=idVendor=27c6 --attr-match=idProduct=60a4 || true
udevadm trigger --action=add --attr-match=idVendor=27c6 --attr-match=idProduct=60bc || true
+ udevadm trigger --action=add --attr-match=idVendor=27c6 --attr-match=idProduct=60c2 || true
udevadm trigger --action=add --attr-match=idVendor=27c6 --attr-match=idProduct=6304 || true
udevadm trigger --action=add --attr-match=idVendor=27c6 --attr-match=idProduct=631c || true
udevadm trigger --action=add --attr-match=idVendor=27c6 --attr-match=idProduct=633c || true
@@ -152,6 +167,8 @@ if [ "$1" = "configure" -o "$1" = "upgrade" ] && command -V udevadm >/dev/null 2
udevadm trigger --action=add --attr-match=idVendor=27c6 --attr-match=idProduct=63bc || true
udevadm trigger --action=add --attr-match=idVendor=27c6 --attr-match=idProduct=63cc || true
udevadm trigger --action=add --attr-match=idVendor=27c6 --attr-match=idProduct=6496 || true
+ udevadm trigger --action=add --attr-match=idVendor=27c6 --attr-match=idProduct=650a || true
+ udevadm trigger --action=add --attr-match=idVendor=27c6 --attr-match=idProduct=650c || true
udevadm trigger --action=add --attr-match=idVendor=27c6 --attr-match=idProduct=6582 || true
udevadm trigger --action=add --attr-match=idVendor=27c6 --attr-match=idProduct=6584 || true
udevadm trigger --action=add --attr-match=idVendor=27c6 --attr-match=idProduct=658c || true
@@ -160,25 +177,35 @@ if [ "$1" = "configure" -o "$1" = "upgrade" ] && command -V udevadm >/dev/null 2
udevadm trigger --action=add --attr-match=idVendor=27c6 --attr-match=idProduct=659a || true
udevadm trigger --action=add --attr-match=idVendor=27c6 --attr-match=idProduct=659c || true
udevadm trigger --action=add --attr-match=idVendor=27c6 --attr-match=idProduct=6a94 || true
+ udevadm trigger --action=add --attr-match=idVendor=27c6 --attr-match=idProduct=6512 || true
+ udevadm trigger --action=add --attr-match=idVendor=27c6 --attr-match=idProduct=689a || true
udevadm trigger --action=add --attr-match=idVendor=298d --attr-match=idProduct=1010 || true
udevadm trigger --action=add --attr-match=idVendor=0bda --attr-match=idProduct=5813 || true
+ udevadm trigger --action=add --attr-match=idVendor=0bda --attr-match=idProduct=5816 || true
udevadm trigger --action=add --attr-match=idVendor=06cb --attr-match=idProduct=00bd || true
+ udevadm trigger --action=add --attr-match=idVendor=06cb --attr-match=idProduct=00c2 || true
+ udevadm trigger --action=add --attr-match=idVendor=06cb --attr-match=idProduct=00c4 || true
+ udevadm trigger --action=add --attr-match=idVendor=06cb --attr-match=idProduct=00c6 || true
udevadm trigger --action=add --attr-match=idVendor=06cb --attr-match=idProduct=00df || true
+ udevadm trigger --action=add --attr-match=idVendor=06cb --attr-match=idProduct=00f0 || true
udevadm trigger --action=add --attr-match=idVendor=06cb --attr-match=idProduct=00f9 || true
udevadm trigger --action=add --attr-match=idVendor=06cb --attr-match=idProduct=00fc || true
- udevadm trigger --action=add --attr-match=idVendor=06cb --attr-match=idProduct=00c2 || true
udevadm trigger --action=add --attr-match=idVendor=06cb --attr-match=idProduct=0100 || true
- udevadm trigger --action=add --attr-match=idVendor=06cb --attr-match=idProduct=00f0 || true
udevadm trigger --action=add --attr-match=idVendor=06cb --attr-match=idProduct=0103 || true
+ udevadm trigger --action=add --attr-match=idVendor=06cb --attr-match=idProduct=0104 || true
+ udevadm trigger --action=add --attr-match=idVendor=06cb --attr-match=idProduct=0106 || true
+ udevadm trigger --action=add --attr-match=idVendor=06cb --attr-match=idProduct=0107 || true
+ udevadm trigger --action=add --attr-match=idVendor=06cb --attr-match=idProduct=0108 || true
udevadm trigger --action=add --attr-match=idVendor=06cb --attr-match=idProduct=0123 || true
udevadm trigger --action=add --attr-match=idVendor=06cb --attr-match=idProduct=0124 || true
udevadm trigger --action=add --attr-match=idVendor=06cb --attr-match=idProduct=0126 || true
udevadm trigger --action=add --attr-match=idVendor=06cb --attr-match=idProduct=0129 || true
- udevadm trigger --action=add --attr-match=idVendor=06cb --attr-match=idProduct=0168 || true
udevadm trigger --action=add --attr-match=idVendor=06cb --attr-match=idProduct=015f || true
- udevadm trigger --action=add --attr-match=idVendor=06cb --attr-match=idProduct=0104 || true
+ udevadm trigger --action=add --attr-match=idVendor=06cb --attr-match=idProduct=0168 || true
+ udevadm trigger --action=add --attr-match=idVendor=06cb --attr-match=idProduct=016c || true
udevadm trigger --action=add --attr-match=idVendor=06cb --attr-match=idProduct=0173 || true
- udevadm trigger --action=add --attr-match=idVendor=06cb --attr-match=idProduct=0106 || true
+ udevadm trigger --action=add --attr-match=idVendor=06cb --attr-match=idProduct=0174 || true
+ udevadm trigger --action=add --attr-match=idVendor=06cb --attr-match=idProduct=019d || true
udevadm trigger --action=add --attr-match=idVendor=147e --attr-match=idProduct=2016 || true
udevadm trigger --action=add --attr-match=idVendor=147e --attr-match=idProduct=1000 || true
udevadm trigger --action=add --attr-match=idVendor=147e --attr-match=idProduct=1001 || true
@@ -203,7 +230,10 @@ if [ "$1" = "configure" -o "$1" = "upgrade" ] && command -V udevadm >/dev/null 2
udevadm trigger --action=add --attr-match=idVendor=138a --attr-match=idProduct=0017 || true
udevadm trigger --action=add --attr-match=idVendor=138a --attr-match=idProduct=0018 || true
udevadm trigger --action=add --attr-match=idVendor=138a --attr-match=idProduct=0091 || true
+ udevadm trigger --action=add --attr-match=idVendor=0a5c --attr-match=idProduct=5802 || true
udevadm trigger --action=add --attr-match=idVendor=047d --attr-match=idProduct=00f2 || true
+ udevadm trigger --action=add --attr-match=idVendor=047d --attr-match=idProduct=8054 || true
+ udevadm trigger --action=add --attr-match=idVendor=047d --attr-match=idProduct=8055 || true
udevadm trigger --action=add --attr-match=idVendor=04e8 --attr-match=idProduct=730b || true
udevadm trigger --action=add --attr-match=idVendor=04f3 --attr-match=idProduct=036b || true
udevadm trigger --action=add --attr-match=idVendor=04f3 --attr-match=idProduct=0c00 || true
@@ -211,16 +241,25 @@ if [ "$1" = "configure" -o "$1" = "upgrade" ] && command -V udevadm >/dev/null 2
udevadm trigger --action=add --attr-match=idVendor=04f3 --attr-match=idProduct=0c57 || true
udevadm trigger --action=add --attr-match=idVendor=04f3 --attr-match=idProduct=0c5e || true
udevadm trigger --action=add --attr-match=idVendor=04f3 --attr-match=idProduct=0c5a || true
+ udevadm trigger --action=add --attr-match=idVendor=04f3 --attr-match=idProduct=0c60 || true
udevadm trigger --action=add --attr-match=idVendor=04f3 --attr-match=idProduct=0c6c || true
udevadm trigger --action=add --attr-match=idVendor=04f3 --attr-match=idProduct=0c70 || true
udevadm trigger --action=add --attr-match=idVendor=04f3 --attr-match=idProduct=0c72 || true
udevadm trigger --action=add --attr-match=idVendor=04f3 --attr-match=idProduct=0c77 || true
+ udevadm trigger --action=add --attr-match=idVendor=04f3 --attr-match=idProduct=0c7c || true
+ udevadm trigger --action=add --attr-match=idVendor=04f3 --attr-match=idProduct=0c7f || true
+ udevadm trigger --action=add --attr-match=idVendor=04f3 --attr-match=idProduct=0c80 || true
+ udevadm trigger --action=add --attr-match=idVendor=04f3 --attr-match=idProduct=0c85 || true
+ udevadm trigger --action=add --attr-match=idVendor=04f3 --attr-match=idProduct=0c90 || true
udevadm trigger --action=add --attr-match=idVendor=04f3 --attr-match=idProduct=2706 || true
udevadm trigger --action=add --attr-match=idVendor=04f3 --attr-match=idProduct=3032 || true
udevadm trigger --action=add --attr-match=idVendor=04f3 --attr-match=idProduct=3057 || true
udevadm trigger --action=add --attr-match=idVendor=04f3 --attr-match=idProduct=3104 || true
udevadm trigger --action=add --attr-match=idVendor=04f3 --attr-match=idProduct=310d || true
udevadm trigger --action=add --attr-match=idVendor=04f3 --attr-match=idProduct=3128 || true
+ udevadm trigger --action=add --attr-match=idVendor=04f3 --attr-match=idProduct=0c8a || true
+ udevadm trigger --action=add --attr-match=idVendor=05ba --attr-match=idProduct=000e || true
+ udevadm trigger --action=add --attr-match=idVendor=06cb --attr-match=idProduct=0051 || true
udevadm trigger --action=add --attr-match=idVendor=06cb --attr-match=idProduct=0081 || true
udevadm trigger --action=add --attr-match=idVendor=06cb --attr-match=idProduct=0088 || true
udevadm trigger --action=add --attr-match=idVendor=06cb --attr-match=idProduct=008a || true
@@ -231,7 +270,6 @@ if [ "$1" = "configure" -o "$1" = "upgrade" ] && command -V udevadm >/dev/null 2
udevadm trigger --action=add --attr-match=idVendor=06cb --attr-match=idProduct=00b7 || true
udevadm trigger --action=add --attr-match=idVendor=06cb --attr-match=idProduct=00bb || true
udevadm trigger --action=add --attr-match=idVendor=06cb --attr-match=idProduct=00be || true
- udevadm trigger --action=add --attr-match=idVendor=06cb --attr-match=idProduct=00c4 || true
udevadm trigger --action=add --attr-match=idVendor=06cb --attr-match=idProduct=00cb || true
udevadm trigger --action=add --attr-match=idVendor=06cb --attr-match=idProduct=00c9 || true
udevadm trigger --action=add --attr-match=idVendor=06cb --attr-match=idProduct=00d8 || true
@@ -241,6 +279,7 @@ if [ "$1" = "configure" -o "$1" = "upgrade" ] && command -V udevadm >/dev/null 2
udevadm trigger --action=add --attr-match=idVendor=06cb --attr-match=idProduct=00e7 || true
udevadm trigger --action=add --attr-match=idVendor=06cb --attr-match=idProduct=00e9 || true
udevadm trigger --action=add --attr-match=idVendor=06cb --attr-match=idProduct=00fd || true
+ udevadm trigger --action=add --attr-match=idVendor=06cb --attr-match=idProduct=00ff || true
udevadm trigger --action=add --attr-match=idVendor=0a5c --attr-match=idProduct=5801 || true
udevadm trigger --action=add --attr-match=idVendor=0a5c --attr-match=idProduct=5805 || true
udevadm trigger --action=add --attr-match=idVendor=0a5c --attr-match=idProduct=5834 || true
@@ -250,10 +289,18 @@ if [ "$1" = "configure" -o "$1" = "upgrade" ] && command -V udevadm >/dev/null 2
udevadm trigger --action=add --attr-match=idVendor=0a5c --attr-match=idProduct=5843 || true
udevadm trigger --action=add --attr-match=idVendor=0a5c --attr-match=idProduct=5844 || true
udevadm trigger --action=add --attr-match=idVendor=0a5c --attr-match=idProduct=5845 || true
+ udevadm trigger --action=add --attr-match=idVendor=0a5c --attr-match=idProduct=5860 || true
+ udevadm trigger --action=add --attr-match=idVendor=0a5c --attr-match=idProduct=5863 || true
+ udevadm trigger --action=add --attr-match=idVendor=0a5c --attr-match=idProduct=5864 || true
+ udevadm trigger --action=add --attr-match=idVendor=0a5c --attr-match=idProduct=5865 || true
+ udevadm trigger --action=add --attr-match=idVendor=0a5c --attr-match=idProduct=5866 || true
+ udevadm trigger --action=add --attr-match=idVendor=0a5c --attr-match=idProduct=5867 || true
udevadm trigger --action=add --attr-match=idVendor=0bda --attr-match=idProduct=5812 || true
udevadm trigger --action=add --attr-match=idVendor=10a5 --attr-match=idProduct=0007 || true
udevadm trigger --action=add --attr-match=idVendor=10a5 --attr-match=idProduct=9200 || true
udevadm trigger --action=add --attr-match=idVendor=10a5 --attr-match=idProduct=9800 || true
+ udevadm trigger --action=add --attr-match=idVendor=10a5 --attr-match=idProduct=a120 || true
+ udevadm trigger --action=add --attr-match=idVendor=10a5 --attr-match=idProduct=a900 || true
udevadm trigger --action=add --attr-match=idVendor=10a5 --attr-match=idProduct=e340 || true
udevadm trigger --action=add --attr-match=idVendor=1188 --attr-match=idProduct=9545 || true
udevadm trigger --action=add --attr-match=idVendor=138a --attr-match=idProduct=0007 || true
@@ -274,7 +321,11 @@ if [ "$1" = "configure" -o "$1" = "upgrade" ] && command -V udevadm >/dev/null 2
udevadm trigger --action=add --attr-match=idVendor=1c7a --attr-match=idProduct=0300 || true
udevadm trigger --action=add --attr-match=idVendor=1c7a --attr-match=idProduct=0575 || true
udevadm trigger --action=add --attr-match=idVendor=1c7a --attr-match=idProduct=0576 || true
+ udevadm trigger --action=add --attr-match=idVendor=1c7a --attr-match=idProduct=0584 || true
udevadm trigger --action=add --attr-match=idVendor=1c7a --attr-match=idProduct=0577 || true
+ udevadm trigger --action=add --attr-match=idVendor=1c7a --attr-match=idProduct=057e || true
+ udevadm trigger --action=add --attr-match=idVendor=2541 --attr-match=idProduct=0236 || true
+ udevadm trigger --action=add --attr-match=idVendor=2541 --attr-match=idProduct=9711 || true
udevadm trigger --action=add --attr-match=idVendor=27c6 --attr-match=idProduct=5042 || true
udevadm trigger --action=add --attr-match=idVendor=27c6 --attr-match=idProduct=5110 || true
udevadm trigger --action=add --attr-match=idVendor=27c6 --attr-match=idProduct=5117 || true
@@ -303,11 +354,17 @@ if [ "$1" = "configure" -o "$1" = "upgrade" ] && command -V udevadm >/dev/null 2
udevadm trigger --action=add --attr-match=idVendor=27c6 --attr-match=idProduct=5e0a || true
udevadm trigger --action=add --attr-match=idVendor=27c6 --attr-match=idProduct=581a || true
udevadm trigger --action=add --attr-match=idVendor=27c6 --attr-match=idProduct=589a || true
+ udevadm trigger --action=add --attr-match=idVendor=27c6 --attr-match=idProduct=5f10 || true
udevadm trigger --action=add --attr-match=idVendor=27c6 --attr-match=idProduct=6382 || true
udevadm trigger --action=add --attr-match=idVendor=2808 --attr-match=idProduct=9338 || true
+ udevadm trigger --action=add --attr-match=idVendor=2808 --attr-match=idProduct=9348 || true
udevadm trigger --action=add --attr-match=idVendor=2808 --attr-match=idProduct=93a9 || true
+ udevadm trigger --action=add --attr-match=idVendor=2808 --attr-match=idProduct=a658 || true
+ udevadm trigger --action=add --attr-match=idVendor=2808 --attr-match=idProduct=c652 || true
udevadm trigger --action=add --attr-match=idVendor=298d --attr-match=idProduct=2020 || true
udevadm trigger --action=add --attr-match=idVendor=298d --attr-match=idProduct=2033 || true
+ udevadm trigger --action=add --attr-match=idVendor=2df0 --attr-match=idProduct=0003 || true
+ udevadm trigger --action=add --attr-match=idVendor=3274 --attr-match=idProduct=8012 || true
udevadm trigger --action=add --attr-match=idVendor=3538 --attr-match=idProduct=0930 || true
fi
diff --git a/debian/patches/0001-Add-error-handling-for-fpi_device_suspend_complete.patch b/debian/patches/0001-Add-error-handling-for-fpi_device_suspend_complete.patch
index 98dcc4c..8cf4541 100644
--- a/debian/patches/0001-Add-error-handling-for-fpi_device_suspend_complete.patch
+++ b/debian/patches/0001-Add-error-handling-for-fpi_device_suspend_complete.patch
@@ -34,4 +34,3 @@ index 1b9fa8f..d383998 100644
--
2.47.2
-
diff --git a/debian/patches/0001-Disable-synaptics-and-focaltech_moc.patch b/debian/patches/0001-Disable-synaptics-and-focaltech_moc.patch
index bc45600..5118854 100644
--- a/debian/patches/0001-Disable-synaptics-and-focaltech_moc.patch
+++ b/debian/patches/0001-Disable-synaptics-and-focaltech_moc.patch
@@ -1,16 +1,5 @@
-From b8fd038b6fa2fbf95e31ef1474e33335a4827eee Mon Sep 17 00:00:00 2001
-From: xzl
-Date: Thu, 30 May 2024 15:13:02 +0800
-Subject: [PATCH 1/1] Disable synaptics and focaltech_moc
-
----
- tests/meson.build | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/tests/meson.build b/tests/meson.build
-index dc3b70e..44e3bb8 100644
---- a/tests/meson.build
-+++ b/tests/meson.build
+--- libfprint-1.94.9.orig/tests/meson.build
++++ libfprint-1.94.9/tests/meson.build
@@ -39,7 +39,7 @@ drivers_tests = [
'elan-cobo',
'elanmoc',
@@ -20,15 +9,12 @@ index dc3b70e..44e3bb8 100644
'upektc_img',
'upektc_img-tcs1s',
'uru4000-msv2',
-@@ -55,7 +55,7 @@ drivers_tests = [
- 'egismoc-05a1',
+@@ -58,7 +58,7 @@ drivers_tests = [
'fpcmoc',
- 'realtek',
+ 'realtek',
+ 'realtek-5816',
- 'focaltech_moc',
+# 'focaltech_moc',
]
if get_option('introspection')
---
-2.43.4
-
diff --git a/debian/patches/0001-skip-tests-fpi-device.patch b/debian/patches/0001-skip-tests-fpi-device.patch
index f7a630e..afbbe9a 100644
--- a/debian/patches/0001-skip-tests-fpi-device.patch
+++ b/debian/patches/0001-skip-tests-fpi-device.patch
@@ -21,4 +21,3 @@ index f68ed40..19691ce 100644
]
--
2.47.2
-
diff --git a/debian/patches/build-Look-for-sh-just-once.patch b/debian/patches/build-Look-for-sh-just-once.patch
deleted file mode 100644
index 2dadcd6..0000000
--- a/debian/patches/build-Look-for-sh-just-once.patch
+++ /dev/null
@@ -1,70 +0,0 @@
-From: =?utf-8?b?Ik1hcmNvIFRyZXZpc2FuIChUcmV2acOxbyki?=
-Date: Tue, 20 Feb 2024 08:22:42 +0100
-Subject: build: Look for sh just once
-
-Origin: https://gitlab.freedesktop.org/libfprint/libfprint/commit/4b72f27d
-Forwarded: yes
----
- meson.build | 1 +
- tests/meson.build | 10 +++++-----
- 2 files changed, 6 insertions(+), 5 deletions(-)
-
-diff --git a/meson.build b/meson.build
-index 435827c..28ee27a 100644
---- a/meson.build
-+++ b/meson.build
-@@ -91,6 +91,7 @@ gusb_dep = dependency('gusb', version: '>= 0.2.0')
- mathlib_dep = cc.find_library('m', required: false)
-
- # The following dependencies are only used for tests
-+sh = find_program('sh', required: true)
- cairo_dep = dependency('cairo', required: false)
-
- # introspection scanning and Gio-2.0.gir
-diff --git a/tests/meson.build b/tests/meson.build
-index f68ed40..8c8f5d0 100644
---- a/tests/meson.build
-+++ b/tests/meson.build
-@@ -151,7 +151,7 @@ if get_option('introspection')
- endif
- else
- test(vdtest,
-- find_program('sh'),
-+ sh,
- args: ['-c', 'exit 77']
- )
- endif
-@@ -205,7 +205,7 @@ if get_option('introspection')
- endif
- else
- test(driver_test,
-- find_program('sh'),
-+ sh,
- args: ['-c', 'exit 77']
- )
- endif
-@@ -224,13 +224,13 @@ if get_option('introspection')
- else
- warning('Skipping all driver tests as introspection bindings are missing')
- test('virtual-image',
-- find_program('sh'),
-+ sh,
- args: ['-c', 'exit 77']
- )
-
- foreach driver_test: drivers_tests
- test(driver_test,
-- find_program('sh'),
-+ sh,
- args: ['-c', 'exit 77']
- )
- endforeach
-@@ -273,7 +273,7 @@ foreach test_name: unit_tests
- # Create a dummy test that always skips instead
- warning('Test @0@ cannot be compiled due to missing dependencies'.format(test_name))
- test(test_name,
-- find_program('sh'),
-+ sh,
- suite: ['unit-tests'],
- args: ['-c', 'exit 77'],
- )
diff --git a/debian/patches/build-tests-Skip-a-test-if-the-test-requires-it-during-in.patch b/debian/patches/build-tests-Skip-a-test-if-the-test-requires-it-during-in.patch
deleted file mode 100644
index ad36306..0000000
--- a/debian/patches/build-tests-Skip-a-test-if-the-test-requires-it-during-in.patch
+++ /dev/null
@@ -1,36 +0,0 @@
-From: =?utf-8?b?Ik1hcmNvIFRyZXZpc2FuIChUcmV2acOxbyki?=
-Date: Tue, 20 Feb 2024 08:24:12 +0100
-Subject: build/tests: Skip a test if the test requires it during inspection
-
-In case we don't have dependencies, we should skip the test, otherwise
-we can just fail at test time
-
-Origin: https://gitlab.freedesktop.org/libfprint/libfprint/commit/7dbb21e7
-Forwarded: yes
----
- tests/meson.build | 8 +++++++-
- 1 file changed, 7 insertions(+), 1 deletion(-)
-
-diff --git a/tests/meson.build b/tests/meson.build
-index 8c8f5d0..dc3b70e 100644
---- a/tests/meson.build
-+++ b/tests/meson.build
-@@ -100,11 +100,17 @@ if get_option('introspection')
- base_args = files(vdtest + '.py')
- suite = ['virtual-driver']
-
-- r = run_command(unittest_inspector, files(vdtest + '.py'), check: true)
-+ r = run_command(unittest_inspector, files(vdtest + '.py'), check: false)
- unit_tests = r.stdout().strip().split('\n')
-
- if r.returncode() == 0 and unit_tests.length() > 0
- suite += vdtest
-+ elif r.returncode() == 77
-+ test(vdtest,
-+ sh,
-+ args: ['-c', 'exit 77']
-+ )
-+ continue
- else
- unit_tests = [vdtest]
- endif
diff --git a/debian/patches/series b/debian/patches/series
index 52caa3d..b5caf0d 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -1,5 +1,3 @@
-build-Look-for-sh-just-once.patch
-build-tests-Skip-a-test-if-the-test-requires-it-during-in.patch
0001-Disable-synaptics-and-focaltech_moc.patch
add-uru4000-suspend-resume.patch
0001-Add-error-handling-for-fpi_device_suspend_complete.patch
diff --git a/debian/rules b/debian/rules
index f32921a..5340736 100755
--- a/debian/rules
+++ b/debian/rules
@@ -2,6 +2,7 @@
include /usr/share/dpkg/default.mk
DEB_HOST_ARCH ?= $(shell dpkg-architecture -qDEB_HOST_ARCH)
+
export DPKG_GENSYMBOLS_CHECK_LEVEL = 2
TIMEOUT_MULTIPLIER = 5
@@ -19,7 +20,7 @@ CONFIG_ARGS = \
-Dgtk-examples=false
%:
- dh $@ --with gir
+ dh $@
override_dh_auto_configure:
dh_auto_configure -- $(CONFIG_ARGS)
diff --git a/debian/watch b/debian/watch
index 46a0137..907dd99 100644
--- a/debian/watch
+++ b/debian/watch
@@ -1,4 +1,6 @@
version=4
+opts="searchmode=plain" \
https://gitlab.freedesktop.org/libfprint/@PACKAGE@/tags?sort=updated_desc \
- archive/v(?:[^/]*)/@PACKAGE@-v(\d\S*)@ARCHIVE_EXT@
+ -/archive/v?\d[\d.]+/@PACKAGE@-@ANY_VERSION@@ARCHIVE_EXT@
+
diff --git a/demo/gtk-libfprint-test.c b/demo/gtk-libfprint-test.c
index 30e91ef..d914c12 100644
--- a/demo/gtk-libfprint-test.c
+++ b/demo/gtk-libfprint-test.c
@@ -101,11 +101,14 @@ plot_minutiae (unsigned char *rgbdata,
{
int i;
-#define write_pixel(num) do { \
- rgbdata[((num) * 3)] = 0xff; \
- rgbdata[((num) * 3) + 1] = 0; \
- rgbdata[((num) * 3) + 2] = 0; \
- } while(0)
+ #define write_pixel(num) \
+ do \
+ { \
+ rgbdata[((num) * 3)] = 0xff; \
+ rgbdata[((num) * 3) + 1] = 0; \
+ rgbdata[((num) * 3) + 2] = 0; \
+ } \
+ while(0)
for (i = 0; i < minutiae->len; i++)
{
diff --git a/examples/clear-storage.c b/examples/clear-storage.c
new file mode 100644
index 0000000..4886348
--- /dev/null
+++ b/examples/clear-storage.c
@@ -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
+ * Copyright (C) 2024 Abhinav Baid
+ *
+ * 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
+#include
+#include
+#include
+
+#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;
+}
diff --git a/examples/meson.build b/examples/meson.build
index f28a2d4..250c055 100644
--- a/examples/meson.build
+++ b/examples/meson.build
@@ -5,6 +5,7 @@ examples = [
'img-capture',
'manage-prints',
'verify',
+ 'clear-storage',
]
foreach example: examples
diff --git a/examples/storage.c b/examples/storage.c
index b84c72d..cc513bc 100644
--- a/examples/storage.c
+++ b/examples/storage.c
@@ -26,6 +26,7 @@
#include "storage.h"
#include
+#include
#include
#include
#include
@@ -55,6 +56,18 @@ get_print_data_descriptor (FpPrint *print, FpDevice *dev, FpFinger finger)
finger);
}
+static char *
+get_print_prefix_for_device (FpDevice *dev)
+{
+ const char *driver;
+ const char *dev_id;
+
+ driver = fp_device_get_driver (dev);
+ dev_id = fp_device_get_device_id (dev);
+
+ return g_strdup_printf ("%s/%s/", driver, dev_id);
+}
+
static GVariantDict *
load_data (void)
{
@@ -169,8 +182,6 @@ gallery_data_load (FpDevice *dev)
g_autoptr(GVariant) dict_variant = NULL;
g_autofree char *dev_prefix = NULL;
GPtrArray *gallery;
- const char *driver;
- const char *dev_id;
GVariantIter iter;
GVariant *value;
gchar *key;
@@ -178,9 +189,7 @@ gallery_data_load (FpDevice *dev)
gallery = g_ptr_array_new_with_free_func (g_object_unref);
dict = load_data ();
dict_variant = g_variant_dict_end (dict);
- driver = fp_device_get_driver (dev);
- dev_id = fp_device_get_device_id (dev);
- dev_prefix = g_strdup_printf ("%s/%s/", driver, dev_id);
+ dev_prefix = get_print_prefix_for_device (dev);
g_variant_iter_init (&iter, dict_variant);
while (g_variant_iter_loop (&iter, "{sv}", &key, &value))
@@ -208,6 +217,55 @@ gallery_data_load (FpDevice *dev)
return gallery;
}
+gboolean
+clear_saved_prints (FpDevice *dev,
+ GError **error)
+{
+ g_autoptr(GVariantDict) dict = NULL;
+ g_autoptr(GVariantDict) updated_dict = NULL;
+ g_autoptr(GVariant) dict_variant = NULL;
+ g_autofree char *dev_prefix = NULL;
+ GPtrArray *print_keys;
+ GVariantIter iter;
+ GVariant *value;
+ gchar *key;
+
+ print_keys = g_ptr_array_new_with_free_func (g_free);
+ dict = load_data ();
+ dict_variant = g_variant_dict_end (dict);
+ dev_prefix = get_print_prefix_for_device (dev);
+
+ g_variant_iter_init (&iter, dict_variant);
+ while (g_variant_iter_loop (&iter, "{sv}", &key, &value))
+ {
+ if (!g_str_has_prefix (key, dev_prefix))
+ continue;
+
+ g_ptr_array_add (print_keys, g_strdup (key));
+ }
+
+ if (!print_keys->len)
+ return TRUE;
+
+ updated_dict = load_data ();
+
+ for (guint i = 0; i < print_keys->len; ++i)
+ {
+ key = g_ptr_array_index (print_keys, i);
+ if (!g_variant_dict_remove (updated_dict, key))
+ {
+ g_warning ("Print '%s' key not found!", key);
+ continue;
+ }
+
+ g_debug ("Dropping print '%s' from gallery", key);
+ }
+
+ save_data (g_variant_dict_end (updated_dict));
+
+ return TRUE;
+}
+
FpPrint *
print_create_template (FpDevice *dev, FpFinger finger, gboolean load_existing)
{
diff --git a/examples/storage.h b/examples/storage.h
index 0922b90..fc3bf8a 100644
--- a/examples/storage.h
+++ b/examples/storage.h
@@ -20,12 +20,17 @@
#pragma once
+#include
+#include
+
int print_data_save (FpPrint *print,
FpFinger finger,
gboolean update_fingerprint);
FpPrint * print_data_load (FpDevice *dev,
FpFinger finger);
GPtrArray * gallery_data_load (FpDevice *dev);
+gboolean clear_saved_prints (FpDevice *dev,
+ GError **error);
FpPrint * print_create_template (FpDevice *dev,
FpFinger finger,
const gboolean load_existing);
diff --git a/libfprint/drivers/egismoc/egismoc.c b/libfprint/drivers/egismoc/egismoc.c
index 0b5e8d2..8f35a67 100644
--- a/libfprint/drivers/egismoc/egismoc.c
+++ b/libfprint/drivers/egismoc/egismoc.c
@@ -32,6 +32,7 @@
#include
#include "drivers_api.h"
+#include "fpi-byte-writer.h"
#include "egismoc.h"
@@ -42,15 +43,17 @@ struct _FpiDeviceEgisMoc
FpiSsm *cmd_ssm;
FpiUsbTransfer *cmd_transfer;
GCancellable *interrupt_cancellable;
-
- int enrolled_num;
GPtrArray *enrolled_ids;
+ gint max_enroll_stages;
};
G_DEFINE_TYPE (FpiDeviceEgisMoc, fpi_device_egismoc, FP_TYPE_DEVICE);
static const FpIdEntry egismoc_id_table[] = {
{ .vid = 0x1c7a, .pid = 0x0582, .driver_data = EGISMOC_DRIVER_CHECK_PREFIX_TYPE1 },
+ { .vid = 0x1c7a, .pid = 0x0583, .driver_data = EGISMOC_DRIVER_CHECK_PREFIX_TYPE1 },
+ { .vid = 0x1c7a, .pid = 0x0586, .driver_data = EGISMOC_DRIVER_CHECK_PREFIX_TYPE1 | EGISMOC_DRIVER_MAX_ENROLL_STAGES_20 },
+ { .vid = 0x1c7a, .pid = 0x0587, .driver_data = EGISMOC_DRIVER_CHECK_PREFIX_TYPE1 | EGISMOC_DRIVER_MAX_ENROLL_STAGES_20 },
{ .vid = 0x1c7a, .pid = 0x05a1, .driver_data = EGISMOC_DRIVER_CHECK_PREFIX_TYPE2 },
{ .vid = 0, .pid = 0, .driver_data = 0 }
};
@@ -154,8 +157,6 @@ egismoc_task_ssm_done (FpiSsm *ssm,
self->task_ssm = NULL;
g_clear_pointer (&self->enrolled_ids, g_ptr_array_unref);
- self->enrolled_ids = NULL;
- self->enrolled_num = -1;
if (error)
fpi_device_action_error (device, error);
@@ -273,43 +274,24 @@ egismoc_cmd_ssm_done (FpiSsm *ssm,
data->callback (device, NULL, 0, g_steal_pointer (&local_error));
}
-typedef union
-{
- guint16 check_value;
- guchar check_bytes[EGISMOC_CHECK_BYTES_LENGTH];
-} EgisMocCheckBytes;
-
-G_STATIC_ASSERT (G_SIZEOF_MEMBER (EgisMocCheckBytes, check_value) ==
- sizeof (guint8) * EGISMOC_CHECK_BYTES_LENGTH);
-
/*
* Derive the 2 "check bytes" for write payloads
* 32-bit big-endian sum of all 16-bit words (including check bytes) MOD 0xFFFF
* should be 0, otherwise the device will reject the payload
*/
-static EgisMocCheckBytes
-egismoc_get_check_bytes (const guchar *value,
- const gsize value_length)
+static guint16
+egismoc_get_check_bytes (FpiByteReader *reader)
{
fp_dbg ("Get check bytes");
- EgisMocCheckBytes check_bytes;
- const size_t steps = (value_length + 1) / 2;
- guint16 values[steps];
size_t sum_values = 0;
+ guint16 val;
- for (int i = 0, j = 0; i < value_length; i += 2, j++)
- {
- values[j] = (value[i] << 8 & 0xff00);
-
- if (i < value_length - 1)
- values[j] |= value[i + 1] & 0x00ff;
- }
+ fpi_byte_reader_set_pos (reader, 0);
- for (int i = 0; i < steps; i++)
- sum_values += values[i];
+ while (fpi_byte_reader_get_uint16_be (reader, &val))
+ sum_values += val;
- check_bytes.check_value = GUINT16_TO_BE (0xffff - (sum_values % 0xffff));
- return check_bytes;
+ return G_MAXUINT16 - (sum_values % G_MAXUINT16);
}
static void
@@ -319,22 +301,15 @@ egismoc_exec_cmd (FpDevice *device,
GDestroyNotify cmd_destroy,
SynCmdMsgCallback callback)
{
- fp_dbg ("Execute command and get response");
+ g_auto(FpiByteWriter) writer = {0};
+ g_autoptr(FpiUsbTransfer) transfer = NULL;
FpiDeviceEgisMoc *self = FPI_DEVICE_EGISMOC (device);
- EgisMocCheckBytes check_bytes;
- g_autofree guchar *buffer_out = NULL;
+ g_autofree CommandData *data = NULL;
gsize buffer_out_length = 0;
+ gboolean written = TRUE;
+ guint16 check_value;
- g_autoptr(FpiUsbTransfer) transfer = NULL;
- CommandData *data = g_new0 (CommandData, 1);
-
- g_assert (self->cmd_ssm == NULL);
- self->cmd_ssm = fpi_ssm_new (device,
- egismoc_cmd_run_state,
- CMD_STATES);
-
- transfer = fpi_usb_transfer_new (device);
- transfer->short_is_error = TRUE;
+ fp_dbg ("Execute command and get response");
/*
* buffer_out should be a fully composed command (with prefix, check bytes, etc)
@@ -347,40 +322,60 @@ egismoc_exec_cmd (FpDevice *device,
buffer_out_length = egismoc_write_prefix_len
+ EGISMOC_CHECK_BYTES_LENGTH
+ cmd_length;
- buffer_out = g_new0 (guchar, buffer_out_length);
+
+ fpi_byte_writer_init_with_size (&writer, buffer_out_length +
+ (buffer_out_length % 2 ? 1 : 0), TRUE);
/* Prefix */
- memcpy (buffer_out, egismoc_write_prefix, egismoc_write_prefix_len);
+ written &= fpi_byte_writer_put_data (&writer, egismoc_write_prefix,
+ egismoc_write_prefix_len);
/* Check Bytes - leave them as 00 for now then later generate and copy over
* the real ones */
+ written &= fpi_byte_writer_change_pos (&writer, EGISMOC_CHECK_BYTES_LENGTH);
/* Command Payload */
- memcpy (buffer_out + egismoc_write_prefix_len + EGISMOC_CHECK_BYTES_LENGTH,
- cmd, cmd_length);
+ written &= fpi_byte_writer_put_data (&writer, cmd, cmd_length);
+
+ /* Now fetch and set the "real" check bytes based on the currently
+ * assembled payload */
+ check_value = egismoc_get_check_bytes (FPI_BYTE_READER (&writer));
+ fpi_byte_writer_set_pos (&writer, egismoc_write_prefix_len);
+ written &= fpi_byte_writer_put_uint16_be (&writer, check_value);
/* destroy cmd if requested */
if (cmd_destroy)
- cmd_destroy (cmd);
+ g_clear_pointer (&cmd, cmd_destroy);
- /* Now fetch and set the "real" check bytes based on the currently
- * assembled payload */
- check_bytes = egismoc_get_check_bytes (buffer_out, buffer_out_length);
- memcpy (buffer_out + egismoc_write_prefix_len, check_bytes.check_bytes,
- EGISMOC_CHECK_BYTES_LENGTH);
+ g_assert (self->cmd_ssm == NULL);
+ self->cmd_ssm = fpi_ssm_new (device,
+ egismoc_cmd_run_state,
+ CMD_STATES);
+
+ data = g_new0 (CommandData, 1);
+ data->callback = callback;
+ fpi_ssm_set_data (self->cmd_ssm, g_steal_pointer (&data), g_free);
+
+ if (!written)
+ {
+ fpi_ssm_start (self->cmd_ssm, egismoc_cmd_ssm_done);
+ fpi_ssm_mark_failed (self->cmd_ssm,
+ fpi_device_error_new (FP_DEVICE_ERROR_PROTO));
+ return;
+ }
+
+ transfer = fpi_usb_transfer_new (device);
+ transfer->short_is_error = TRUE;
+ transfer->ssm = self->cmd_ssm;
fpi_usb_transfer_fill_bulk_full (transfer,
EGISMOC_EP_CMD_OUT,
- g_steal_pointer (&buffer_out),
+ fpi_byte_writer_reset_and_get_data (&writer),
buffer_out_length,
g_free);
- transfer->ssm = self->cmd_ssm;
g_assert (self->cmd_transfer == NULL);
self->cmd_transfer = g_steal_pointer (&transfer);
- data->callback = callback;
-
- fpi_ssm_set_data (self->cmd_ssm, data, g_free);
fpi_ssm_start (self->cmd_ssm, egismoc_cmd_ssm_done);
}
@@ -419,11 +414,13 @@ egismoc_get_enrolled_prints (FpDevice *device)
FpiDeviceEgisMoc *self = FPI_DEVICE_EGISMOC (device);
g_autoptr(GPtrArray) result = g_ptr_array_new_with_free_func (g_object_unref);
- FpPrint *print = NULL;
- for (int i = 0; i < self->enrolled_num; i++)
+ if (!self->enrolled_ids)
+ return g_steal_pointer (&result);
+
+ for (guint i = 0; i < self->enrolled_ids->len; i++)
{
- print = fp_print_new (device);
+ FpPrint *print = fp_print_new (device);
egismoc_set_print_data (print, g_ptr_array_index (self->enrolled_ids, i), NULL);
g_ptr_array_add (result, g_object_ref_sink (print));
}
@@ -448,26 +445,37 @@ egismoc_list_fill_enrolled_ids_cb (FpDevice *device,
g_clear_pointer (&self->enrolled_ids, g_ptr_array_unref);
self->enrolled_ids = g_ptr_array_new_with_free_func (g_free);
- self->enrolled_num = 0;
+
+ FpiByteReader reader;
+ gboolean read = TRUE;
+
+ fpi_byte_reader_init (&reader, buffer_in, length_in);
+
+ read &= fpi_byte_reader_set_pos (&reader, EGISMOC_LIST_RESPONSE_PREFIX_SIZE);
/*
* Each fingerprint ID will be returned in this response as a 32 byte array
* The other stuff in the payload is 16 bytes long, so if there is at least 1
* print then the length should be at least 16+32=48 bytes long
*/
- for (int pos = EGISMOC_LIST_RESPONSE_PREFIX_SIZE;
- pos < length_in - EGISMOC_LIST_RESPONSE_SUFFIX_SIZE;
- pos += EGISMOC_FINGERPRINT_DATA_SIZE, self->enrolled_num++)
+ while (read)
{
- g_autofree gchar *print_id = g_strndup ((gchar *) buffer_in + pos,
- EGISMOC_FINGERPRINT_DATA_SIZE);
- fp_dbg ("Device fingerprint %0d: %.*s", self->enrolled_num,
+ const guint8 *data;
+ g_autofree gchar *print_id = NULL;
+
+ read &= fpi_byte_reader_get_data (&reader, EGISMOC_FINGERPRINT_DATA_SIZE,
+ &data);
+ if (!read)
+ break;
+
+ print_id = g_strndup ((gchar *) data, EGISMOC_FINGERPRINT_DATA_SIZE);
+ fp_dbg ("Device fingerprint %0d: %.*s", self->enrolled_ids->len + 1,
EGISMOC_FINGERPRINT_DATA_SIZE, print_id);
g_ptr_array_add (self->enrolled_ids, g_steal_pointer (&print_id));
}
fp_info ("Number of currently enrolled fingerprints on the device is %d",
- self->enrolled_num);
+ self->enrolled_ids->len);
if (self->task_ssm)
fpi_ssm_next_state (self->task_ssm);
@@ -514,6 +522,7 @@ egismoc_get_delete_cmd (FpDevice *device,
{
fp_dbg ("Get delete command");
FpiDeviceEgisMoc *self = FPI_DEVICE_EGISMOC (device);
+ g_auto(FpiByteWriter) writer = {0};
g_autoptr(GVariant) print_data = NULL;
g_autoptr(GVariant) print_data_id_var = NULL;
const guchar *print_data_id = NULL;
@@ -521,7 +530,7 @@ egismoc_get_delete_cmd (FpDevice *device,
g_autofree gchar *print_description = NULL;
g_autofree guchar *enrolled_print_id = NULL;
g_autofree guchar *result = NULL;
- gsize pos = 0;
+ gboolean written = TRUE;
/*
* The final command body should contain:
@@ -537,7 +546,12 @@ egismoc_get_delete_cmd (FpDevice *device,
* identifiers (enrolled_list)
*/
- const int num_to_delete = (!delete_print) ? self->enrolled_num : 1;
+ int num_to_delete = 0;
+ if (delete_print)
+ num_to_delete = 1;
+ else if (self->enrolled_ids)
+ num_to_delete = self->enrolled_ids->len;
+
const gsize body_length = sizeof (guchar) * EGISMOC_FINGERPRINT_DATA_SIZE *
num_to_delete;
/* total_length is the 6 various bytes plus prefix and body payload */
@@ -545,10 +559,10 @@ egismoc_get_delete_cmd (FpDevice *device,
body_length;
/* pre-fill entire payload with 00s */
- result = g_new0 (guchar, total_length);
+ fpi_byte_writer_init_with_size (&writer, total_length, TRUE);
/* start with 00 00 (just move starting offset up by 2) */
- pos = 2;
+ written &= fpi_byte_writer_set_pos (&writer, 2);
/* Size Counter bytes */
/* "easiest" way to handle 2-bytes size for counter is to hard-code logic for
@@ -557,37 +571,31 @@ egismoc_get_delete_cmd (FpDevice *device,
* (assumed max is 10) */
if (num_to_delete > 7)
{
- memset (result + pos, 0x01, sizeof (guchar));
- pos += sizeof (guchar);
- memset (result + pos, ((num_to_delete - 8) * 0x20) + 0x07, sizeof (guchar));
- pos += sizeof (guchar);
+ written &= fpi_byte_writer_put_uint8 (&writer, 0x01);
+ written &= fpi_byte_writer_put_uint8 (&writer, ((num_to_delete - 8) * 0x20) + 0x07);
}
else
{
/* first byte is 0x00, just skip it */
- pos += sizeof (guchar);
- memset (result + pos, (num_to_delete * 0x20) + 0x07, sizeof (guchar));
- pos += sizeof (guchar);
+ written &= fpi_byte_writer_change_pos (&writer, 1);
+ written &= fpi_byte_writer_put_uint8 (&writer, (num_to_delete * 0x20) + 0x07);
}
/* command prefix */
- memcpy (result + pos, cmd_delete_prefix, cmd_delete_prefix_len);
- pos += cmd_delete_prefix_len;
+ written &= fpi_byte_writer_put_data (&writer, cmd_delete_prefix,
+ cmd_delete_prefix_len);
/* 2-bytes size logic for counter again */
if (num_to_delete > 7)
{
- memset (result + pos, 0x01, sizeof (guchar));
- pos += sizeof (guchar);
- memset (result + pos, ((num_to_delete - 8) * 0x20), sizeof (guchar));
- pos += sizeof (guchar);
+ written &= fpi_byte_writer_put_uint8 (&writer, 0x01);
+ written &= fpi_byte_writer_put_uint8 (&writer, (num_to_delete - 8) * 0x20);
}
else
{
/* first byte is 0x00, just skip it */
- pos += sizeof (guchar);
- memset (result + pos, (num_to_delete * 0x20), sizeof (guchar));
- pos += sizeof (guchar);
+ written &= fpi_byte_writer_change_pos (&writer, 1);
+ written &= fpi_byte_writer_put_uint8 (&writer, num_to_delete * 0x20);
}
/* append desired 32-byte fingerprint IDs */
@@ -614,21 +622,26 @@ egismoc_get_delete_cmd (FpDevice *device,
fp_info ("Delete fingerprint %s (%s)", print_description, print_data_id);
- memcpy (result + pos, print_data_id, EGISMOC_FINGERPRINT_DATA_SIZE);
+ written &= fpi_byte_writer_put_data (&writer, print_data_id,
+ EGISMOC_FINGERPRINT_DATA_SIZE);
}
/* Otherwise assume this is a "clear" - just loop through and append all enrolled IDs */
- else
+ else if (self->enrolled_ids)
{
- for (int i = 0; i < self->enrolled_ids->len; i++)
- memcpy (result + pos + (EGISMOC_FINGERPRINT_DATA_SIZE * i),
- g_ptr_array_index (self->enrolled_ids, i),
- EGISMOC_FINGERPRINT_DATA_SIZE);
+ for (guint i = 0; i < self->enrolled_ids->len && written; i++)
+ {
+ written &= fpi_byte_writer_put_data (&writer,
+ g_ptr_array_index (self->enrolled_ids, i),
+ EGISMOC_FINGERPRINT_DATA_SIZE);
+ }
}
+ g_assert (written);
+
if (length_out)
*length_out = total_length;
- return g_steal_pointer (&result);
+ return fpi_byte_writer_reset_and_get_data (&writer);
}
static void
@@ -687,9 +700,7 @@ egismoc_delete_run_state (FpiSsm *ssm,
switch (fpi_ssm_get_cur_state (ssm))
{
case DELETE_GET_ENROLLED_IDS:
- /* get enrolled_ids and enrolled_num from device for use building
- * delete payload below
- */
+ /* get enrolled_ids from device for use building delete payload below */
egismoc_exec_cmd (device, cmd_list, cmd_list_len, NULL,
egismoc_list_fill_enrolled_ids_cb);
break;
@@ -761,7 +772,7 @@ egismoc_enroll_status_report (FpDevice *device,
enroll_print->stage++;
fp_info ("Partial capture successful. Please touch the sensor again (%d/%d)",
enroll_print->stage,
- EGISMOC_MAX_ENROLL_NUM);
+ self->max_enroll_stages);
fpi_device_enroll_progress (device, enroll_print->stage, enroll_print->print, NULL);
break;
@@ -841,7 +852,7 @@ egismoc_read_capture_cb (FpDevice *device,
egismoc_enroll_status_report (device, enroll_print, ENROLL_STATUS_RETRY, error);
}
- if (enroll_print->stage == EGISMOC_ENROLL_TIMES)
+ if (enroll_print->stage == self->max_enroll_stages)
fpi_ssm_next_state (self->task_ssm);
else
fpi_ssm_jump_to_state (self->task_ssm, ENROLL_CAPTURE_SENSOR_RESET);
@@ -884,26 +895,28 @@ egismoc_get_check_cmd (FpDevice *device,
{
fp_dbg ("Get check command");
FpiDeviceEgisMoc *self = FPI_DEVICE_EGISMOC (device);
+ g_auto(FpiByteWriter) writer = {0};
g_autofree guchar *result = NULL;
- gsize pos = 0;
+ gboolean written = TRUE;
/*
* The final command body should contain:
* 1) hard-coded 00 00
* 2) 2-byte size indiciator, 20*Number enrolled identifiers plus 9 in form of:
- * (enrolled_num + 1) * 0x20 + 0x09
+ * (enrolled_ids->len + 1) * 0x20 + 0x09
* Since max prints can be higher than 7 then this goes up to 2 bytes
* (e9 + 9 = 109)
* 3) Hard-coded prefix (cmd_check_prefix)
* 4) 2-byte size indiciator, 20*Number of enrolled identifiers without plus 9
- * ((enrolled_num + 1) * 0x20)
+ * ((enrolled_ids->len + 1) * 0x20)
* 5) Hard-coded 32 * 0x00 bytes
* 6) All of the currently registered prints in their 32-byte device identifiers
* (enrolled_list)
* 7) Hard-coded suffix (cmd_check_suffix)
*/
- const gsize body_length = sizeof (guchar) * self->enrolled_num *
+ g_assert (self->enrolled_ids);
+ const gsize body_length = sizeof (guchar) * self->enrolled_ids->len *
EGISMOC_FINGERPRINT_DATA_SIZE;
/* prefix length can depend on the type */
@@ -921,87 +934,82 @@ egismoc_get_check_cmd (FpDevice *device,
+ cmd_check_suffix_len;
/* pre-fill entire payload with 00s */
- result = g_new0 (guchar, total_length);
+ fpi_byte_writer_init_with_size (&writer, total_length, TRUE);
/* start with 00 00 (just move starting offset up by 2) */
- pos = 2;
+ written &= fpi_byte_writer_set_pos (&writer, 2);
/* Size Counter bytes */
/* "easiest" way to handle 2-bytes size for counter is to hard-code logic for
* when we go to the 2nd byte
* note this will not work in case any model ever supports more than 14 prints
* (assumed max is 10) */
- if (self->enrolled_num > 6)
+ if (self->enrolled_ids->len > 6)
{
- memset (result + pos, 0x01, sizeof (guchar));
- pos += sizeof (guchar);
- memset (result + pos, ((self->enrolled_num - 7) * 0x20) + 0x09,
- sizeof (guchar));
- pos += sizeof (guchar);
+ written &= fpi_byte_writer_put_uint8 (&writer, 0x01);
+ written &= fpi_byte_writer_put_uint8 (&writer,
+ ((self->enrolled_ids->len - 7) * 0x20)
+ + 0x09);
}
else
{
/* first byte is 0x00, just skip it */
- pos += sizeof (guchar);
- memset (result + pos, ((self->enrolled_num + 1) * 0x20) + 0x09,
- sizeof (guchar));
- pos += sizeof (guchar);
+ written &= fpi_byte_writer_change_pos (&writer, 1);
+ written &= fpi_byte_writer_put_uint8 (&writer,
+ ((self->enrolled_ids->len + 1) * 0x20) +
+ 0x09);
}
/* command prefix */
if (fpi_device_get_driver_data (device) & EGISMOC_DRIVER_CHECK_PREFIX_TYPE2)
- {
- memcpy (result + pos, cmd_check_prefix_type2, cmd_check_prefix_type2_len);
- pos += cmd_check_prefix_type2_len;
- }
+ written &= fpi_byte_writer_put_data (&writer, cmd_check_prefix_type2,
+ cmd_check_prefix_type2_len);
else
- {
- memcpy (result + pos, cmd_check_prefix_type1, cmd_check_prefix_type1_len);
- pos += cmd_check_prefix_type1_len;
- }
+ written &= fpi_byte_writer_put_data (&writer, cmd_check_prefix_type1,
+ cmd_check_prefix_type1_len);
/* 2-bytes size logic for counter again */
- if (self->enrolled_num > 6)
+ if (self->enrolled_ids->len > 6)
{
- memset (result + pos, 0x01, sizeof (guchar));
- pos += sizeof (guchar);
- memset (result + pos, (self->enrolled_num - 7) * 0x20, sizeof (guchar));
- pos += sizeof (guchar);
+ written &= fpi_byte_writer_put_uint8 (&writer, 0x01);
+ written &= fpi_byte_writer_put_uint8 (&writer,
+ (self->enrolled_ids->len - 7) * 0x20);
}
else
{
/* first byte is 0x00, just skip it */
- pos += sizeof (guchar);
- memset (result + pos, (self->enrolled_num + 1) * 0x20, sizeof (guchar));
- pos += sizeof (guchar);
+ written &= fpi_byte_writer_change_pos (&writer, 1);
+ written &= fpi_byte_writer_put_uint8 (&writer,
+ (self->enrolled_ids->len + 1) * 0x20);
}
/* add 00s "separator" to offset position */
- pos += EGISMOC_CMD_CHECK_SEPARATOR_LENGTH;
-
- /* append all currently registered 32-byte fingerprint IDs */
- const gsize print_id_length = sizeof (guchar) * EGISMOC_FINGERPRINT_DATA_SIZE;
+ written &= fpi_byte_writer_change_pos (&writer,
+ EGISMOC_CMD_CHECK_SEPARATOR_LENGTH);
- for (int i = 0; i < self->enrolled_num; i++)
+ for (guint i = 0; i < self->enrolled_ids->len && written; i++)
{
- gchar *device_print_id = g_ptr_array_index (self->enrolled_ids, i);
- memcpy (result + pos + (print_id_length * i), device_print_id, print_id_length);
+ written &= fpi_byte_writer_put_data (&writer,
+ g_ptr_array_index (self->enrolled_ids, i),
+ EGISMOC_FINGERPRINT_DATA_SIZE);
}
- pos += body_length;
/* command suffix */
- memcpy (result + pos, cmd_check_suffix, cmd_check_suffix_len);
+ written &= fpi_byte_writer_put_data (&writer, cmd_check_suffix,
+ cmd_check_suffix_len);
+ g_assert (written);
if (length_out)
*length_out = total_length;
- return g_steal_pointer (&result);
+ return fpi_byte_writer_reset_and_get_data (&writer);
}
static void
egismoc_enroll_run_state (FpiSsm *ssm,
FpDevice *device)
{
+ g_auto(FpiByteWriter) writer = {0};
FpiDeviceEgisMoc *self = FPI_DEVICE_EGISMOC (device);
EnrollPrint *enroll_print = fpi_ssm_get_data (ssm);
g_autofree guchar *payload = NULL;
@@ -1012,13 +1020,13 @@ egismoc_enroll_run_state (FpiSsm *ssm,
switch (fpi_ssm_get_cur_state (ssm))
{
case ENROLL_GET_ENROLLED_IDS:
- /* get enrolled_ids and enrolled_num from device for use in check stages below */
+ /* get enrolled_ids from device for use in check stages below */
egismoc_exec_cmd (device, cmd_list, cmd_list_len,
NULL, egismoc_list_fill_enrolled_ids_cb);
break;
case ENROLL_CHECK_ENROLLED_NUM:
- if (self->enrolled_num >= EGISMOC_MAX_ENROLL_NUM)
+ if (self->enrolled_ids->len >= EGISMOC_MAX_ENROLL_NUM)
{
egismoc_enroll_status_report (device, enroll_print, ENROLL_STATUS_DEVICE_FULL,
fpi_device_error_new (FP_DEVICE_ERROR_DATA_FULL));
@@ -1089,14 +1097,23 @@ egismoc_enroll_run_state (FpiSsm *ssm,
device_print_id = g_strndup (user_id, EGISMOC_FINGERPRINT_DATA_SIZE);
egismoc_set_print_data (enroll_print->print, device_print_id, user_id);
- /* create new dynamic payload of cmd_new_print_prefix + device_print_id */
- payload_length = cmd_new_print_prefix_len + EGISMOC_FINGERPRINT_DATA_SIZE;
- payload = g_new0 (guchar, payload_length);
- memcpy (payload, cmd_new_print_prefix, cmd_new_print_prefix_len);
- memcpy (payload + cmd_new_print_prefix_len, device_print_id,
- EGISMOC_FINGERPRINT_DATA_SIZE);
+ fpi_byte_writer_init (&writer);
+ if (!fpi_byte_writer_put_data (&writer, cmd_new_print_prefix,
+ cmd_new_print_prefix_len))
+ {
+ fpi_ssm_mark_failed (ssm, fpi_device_error_new (FP_DEVICE_ERROR_PROTO));
+ break;
+ }
+ if (!fpi_byte_writer_put_data (&writer, (guint8 *) device_print_id,
+ EGISMOC_FINGERPRINT_DATA_SIZE))
+ {
+ fpi_ssm_mark_failed (ssm, fpi_device_error_new (FP_DEVICE_ERROR_PROTO));
+ break;
+ }
- egismoc_exec_cmd (device, g_steal_pointer (&payload), payload_length,
+ payload_length = fpi_byte_writer_get_size (&writer);
+ egismoc_exec_cmd (device, fpi_byte_writer_reset_and_get_data (&writer),
+ payload_length,
g_free, egismoc_task_ssm_next_state_cb);
break;
@@ -1239,13 +1256,13 @@ egismoc_identify_run_state (FpiSsm *ssm,
switch (fpi_ssm_get_cur_state (ssm))
{
case IDENTIFY_GET_ENROLLED_IDS:
- /* get enrolled_ids and enrolled_num from device for use in check stages below */
+ /* get enrolled_ids from device for use in check stages below */
egismoc_exec_cmd (device, cmd_list, cmd_list_len,
NULL, egismoc_list_fill_enrolled_ids_cb);
break;
case IDENTIFY_CHECK_ENROLLED_NUM:
- if (self->enrolled_num == 0)
+ if (self->enrolled_ids->len == 0)
{
fpi_ssm_mark_failed (g_steal_pointer (&self->task_ssm),
fpi_device_error_new (FP_DEVICE_ERROR_DATA_NOT_FOUND));
@@ -1446,6 +1463,71 @@ egismoc_dev_init_handler (FpiSsm *ssm,
NULL);
}
+static void
+egismoc_probe (FpDevice *device)
+{
+ GUsbDevice *usb_dev;
+ GError *error = NULL;
+ g_autofree gchar *serial = NULL;
+ FpiDeviceEgisMoc *self = FPI_DEVICE_EGISMOC (device);
+
+ fp_dbg ("%s enter --> ", G_STRFUNC);
+
+ /* Claim usb interface */
+ usb_dev = fpi_device_get_usb_device (device);
+ if (!g_usb_device_open (usb_dev, &error))
+ {
+ fp_dbg ("%s g_usb_device_open failed %s", G_STRFUNC, error->message);
+ fpi_device_probe_complete (device, NULL, NULL, error);
+ return;
+ }
+
+ if (!g_usb_device_reset (usb_dev, &error))
+ {
+ fp_dbg ("%s g_usb_device_reset failed %s", G_STRFUNC, error->message);
+ g_usb_device_close (usb_dev, NULL);
+ fpi_device_probe_complete (device, NULL, NULL, error);
+ return;
+ }
+
+ if (!g_usb_device_claim_interface (usb_dev, 0, 0, &error))
+ {
+ fp_dbg ("%s g_usb_device_claim_interface failed %s", G_STRFUNC, error->message);
+ g_usb_device_close (usb_dev, NULL);
+ fpi_device_probe_complete (device, NULL, NULL, error);
+ return;
+ }
+
+ if (g_strcmp0 (g_getenv ("FP_DEVICE_EMULATION"), "1") == 0)
+ serial = g_strdup ("emulated-device");
+ else
+ serial = g_usb_device_get_string_descriptor (usb_dev,
+ g_usb_device_get_serial_number_index (usb_dev),
+ &error);
+
+ if (error)
+ {
+ fp_dbg ("%s g_usb_device_get_string_descriptor failed %s", G_STRFUNC, error->message);
+ g_usb_device_release_interface (fpi_device_get_usb_device (FP_DEVICE (device)),
+ 0, 0, NULL);
+ g_usb_device_close (usb_dev, NULL);
+ fpi_device_probe_complete (device, NULL, NULL, error);
+ return;
+ }
+
+ if (fpi_device_get_driver_data (device) & EGISMOC_DRIVER_MAX_ENROLL_STAGES_20)
+ self->max_enroll_stages = 20;
+ else
+ self->max_enroll_stages = EGISMOC_MAX_ENROLL_STAGES_DEFAULT;
+
+ fpi_device_set_nr_enroll_stages (device, self->max_enroll_stages);
+
+ g_usb_device_release_interface (fpi_device_get_usb_device (FP_DEVICE (device)), 0, 0, NULL);
+ g_usb_device_close (usb_dev, NULL);
+
+ fpi_device_probe_complete (device, serial, NULL, error);
+}
+
static void
egismoc_open (FpDevice *device)
{
@@ -1526,10 +1608,11 @@ fpi_device_egismoc_class_init (FpiDeviceEgisMocClass *klass)
dev_class->type = FP_DEVICE_TYPE_USB;
dev_class->scan_type = FP_SCAN_TYPE_PRESS;
dev_class->id_table = egismoc_id_table;
- dev_class->nr_enroll_stages = EGISMOC_ENROLL_TIMES;
+ dev_class->nr_enroll_stages = EGISMOC_MAX_ENROLL_STAGES_DEFAULT;
/* device should be "always off" unless being used */
dev_class->temp_hot_seconds = 0;
+ dev_class->probe = egismoc_probe;
dev_class->open = egismoc_open;
dev_class->cancel = egismoc_cancel;
dev_class->suspend = egismoc_suspend;
diff --git a/libfprint/drivers/egismoc/egismoc.h b/libfprint/drivers/egismoc/egismoc.h
index f027ea2..ef31d2c 100644
--- a/libfprint/drivers/egismoc/egismoc.h
+++ b/libfprint/drivers/egismoc/egismoc.h
@@ -36,6 +36,7 @@ G_DECLARE_FINAL_TYPE (FpiDeviceEgisMoc, fpi_device_egismoc, FPI, DEVICE_EGISMOC,
#define EGISMOC_DRIVER_CHECK_PREFIX_TYPE1 (1 << 0)
#define EGISMOC_DRIVER_CHECK_PREFIX_TYPE2 (1 << 1)
+#define EGISMOC_DRIVER_MAX_ENROLL_STAGES_20 (1 << 2)
#define EGISMOC_EP_CMD_OUT (0x02 | FPI_USB_ENDPOINT_OUT)
#define EGISMOC_EP_CMD_IN (0x81 | FPI_USB_ENDPOINT_IN)
@@ -49,7 +50,7 @@ G_DECLARE_FINAL_TYPE (FpiDeviceEgisMoc, fpi_device_egismoc, FPI, DEVICE_EGISMOC,
#define EGISMOC_USB_IN_RECV_LENGTH 4096
#define EGISMOC_USB_INTERRUPT_IN_RECV_LENGTH 64
-#define EGISMOC_ENROLL_TIMES 10
+#define EGISMOC_MAX_ENROLL_STAGES_DEFAULT 10
#define EGISMOC_MAX_ENROLL_NUM 10
#define EGISMOC_FINGERPRINT_DATA_SIZE 32
#define EGISMOC_LIST_RESPONSE_PREFIX_SIZE 14
@@ -100,11 +101,11 @@ static guchar cmd_read_capture[] = {0x00, 0x00, 0x00, 0x07, 0x50, 0x16, 0x02, 0x
static gsize cmd_read_capture_len = sizeof (cmd_read_capture) / sizeof (cmd_read_capture[0]);
static guchar rsp_read_success_prefix[] = {0x00, 0x00, 0x00, 0x04};
static gsize rsp_read_success_prefix_len = sizeof (rsp_read_success_prefix) / sizeof (rsp_read_success_prefix[0]);
-static guchar rsp_read_success_suffix[] = {0x0a, 0x90, 0x00};
+static guchar rsp_read_success_suffix[] = {0x90, 0x00};
static gsize rsp_read_success_suffix_len = sizeof (rsp_read_success_suffix) / sizeof (rsp_read_success_suffix[0]);
static guchar rsp_read_offcenter_prefix[] = {0x00, 0x00, 0x00, 0x04};
static gsize rsp_read_offcenter_prefix_len = sizeof (rsp_read_offcenter_prefix) / sizeof (rsp_read_offcenter_prefix[0]);
-static guchar rsp_read_offcenter_suffix[] = {0x0a, 0x64, 0x91};
+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]);
diff --git a/libfprint/drivers/elanmoc/elanmoc.c b/libfprint/drivers/elanmoc/elanmoc.c
index e86b79a..f5ccc11 100644
--- a/libfprint/drivers/elanmoc/elanmoc.c
+++ b/libfprint/drivers/elanmoc/elanmoc.c
@@ -31,7 +31,11 @@ static const FpIdEntry id_table[] = {
{ .vid = 0x04f3, .pid = 0x0c88, },
{ .vid = 0x04f3, .pid = 0x0c8c, },
{ .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 */
};
diff --git a/libfprint/drivers/elanspi.h b/libfprint/drivers/elanspi.h
index a8d7319..688f477 100644
--- a/libfprint/drivers/elanspi.h
+++ b/libfprint/drivers/elanspi.h
@@ -340,9 +340,11 @@ static const struct elanspi_regtable elanspi_calibration_table_new_page1 = {
// using checkargs ACPI:HIDPID
static const FpIdEntry elanspi_id_table[] = {
+ {.udev_types = ELANSPI_UDEV_TYPES, .spi_acpi_id = "ELAN7001", .hid_id = {.vid = ELANSPI_TP_VID, .pid = 0x2766}, .driver_data = ELANSPI_NO_ROTATE},
{.udev_types = ELANSPI_UDEV_TYPES, .spi_acpi_id = "ELAN7001", .hid_id = {.vid = ELANSPI_TP_VID, .pid = 0x3057}, .driver_data = ELANSPI_180_ROTATE},
{.udev_types = ELANSPI_UDEV_TYPES, .spi_acpi_id = "ELAN7001", .hid_id = {.vid = ELANSPI_TP_VID, .pid = 0x3087}, .driver_data = ELANSPI_180_ROTATE},
{.udev_types = ELANSPI_UDEV_TYPES, .spi_acpi_id = "ELAN7001", .hid_id = {.vid = ELANSPI_TP_VID, .pid = 0x30c6}, .driver_data = ELANSPI_180_ROTATE},
+ {.udev_types = ELANSPI_UDEV_TYPES, .spi_acpi_id = "ELAN7001", .hid_id = {.vid = ELANSPI_TP_VID, .pid = 0x3128}, .driver_data = ELANSPI_90LEFT_ROTATE},
{.udev_types = ELANSPI_UDEV_TYPES, .spi_acpi_id = "ELAN70A1", .hid_id = {.vid = ELANSPI_TP_VID, .pid = 0x3134}, .driver_data = ELANSPI_90LEFT_ROTATE},
{.udev_types = ELANSPI_UDEV_TYPES, .spi_acpi_id = "ELAN7001", .hid_id = {.vid = ELANSPI_TP_VID, .pid = 0x3148}, .driver_data = ELANSPI_180_ROTATE},
{.udev_types = ELANSPI_UDEV_TYPES, .spi_acpi_id = "ELAN7001", .hid_id = {.vid = ELANSPI_TP_VID, .pid = 0x30b2}, .driver_data = ELANSPI_NO_ROTATE},
diff --git a/libfprint/drivers/focaltech_moc/focaltech_moc.c b/libfprint/drivers/focaltech_moc/focaltech_moc.c
index 9872c7c..17f5363 100644
--- a/libfprint/drivers/focaltech_moc/focaltech_moc.c
+++ b/libfprint/drivers/focaltech_moc/focaltech_moc.c
@@ -30,6 +30,9 @@ static const FpIdEntry id_table[] = {
{ .vid = 0x2808, .pid = 0x9e48, },
{ .vid = 0x2808, .pid = 0xd979, },
{ .vid = 0x2808, .pid = 0xa959, },
+ { .vid = 0x2808, .pid = 0xa99a, },
+ { .vid = 0x2808, .pid = 0xa57a, },
+ { .vid = 0x2808, .pid = 0xa78a, },
{ .vid = 0, .pid = 0, .driver_data = 0 }, /* terminating entry */
};
diff --git a/libfprint/drivers/fpcmoc/fpc.c b/libfprint/drivers/fpcmoc/fpc.c
index dd6bf09..e2e89e3 100644
--- a/libfprint/drivers/fpcmoc/fpc.c
+++ b/libfprint/drivers/fpcmoc/fpc.c
@@ -21,7 +21,7 @@
#define FP_COMPONENT "fpcmoc"
#define MAX_ENROLL_SAMPLES (25)
-#define CTRL_TIMEOUT (1000)
+#define CTRL_TIMEOUT (2000)
#define DATA_TIMEOUT (5000)
/* Usb port setting */
@@ -68,6 +68,9 @@ static const FpIdEntry id_table[] = {
{ .vid = 0x10A5, .pid = 0xDA04, },
{ .vid = 0x10A5, .pid = 0xD805, },
{ .vid = 0x10A5, .pid = 0xD205, },
+ { .vid = 0x10A5, .pid = 0x9524, },
+ { .vid = 0x10A5, .pid = 0x9544, },
+ { .vid = 0x10A5, .pid = 0xC844, },
/* terminating entry */
{ .vid = 0, .pid = 0, .driver_data = 0 },
};
@@ -269,6 +272,7 @@ fpc_cmd_ssm_done (FpiSsm *ssm, FpDevice *dev, GError *error)
FpiDeviceFpcMoc *self = FPI_DEVICE_FPCMOC (dev);
CommandData *data = fpi_ssm_get_data (ssm);
+ self->cmd_ssm = NULL;
/* Notify about the SSM failure from here instead. */
if (error)
{
@@ -276,8 +280,6 @@ fpc_cmd_ssm_done (FpiSsm *ssm, FpDevice *dev, GError *error)
if (data->callback)
data->callback (self, NULL, error);
}
-
- self->cmd_ssm = NULL;
}
static void
@@ -388,7 +390,7 @@ fpc_dev_release_interface (FpiDeviceFpcMoc *self,
}
/* 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
@@ -446,10 +448,16 @@ fpc_evt_cb (FpiDeviceFpcMoc *self,
break;
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),
FP_FINGER_STATUS_PRESENT,
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;
case FPC_EVT_IMG:
@@ -742,15 +750,22 @@ fpc_enroll_update_cb (FpiDeviceFpcMoc *self,
/* here should tips remove finger and try again */
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)",
self->immobile_stage, self->max_immobile_stage);
/* 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;
}
- self->immobile_stage++;
}
fpi_device_enroll_progress (FP_DEVICE (self),
self->enroll_stage,
@@ -763,7 +778,10 @@ fpc_enroll_update_cb (FpiDeviceFpcMoc *self,
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);
+ {
+ fpi_ssm_jump_to_state (self->task_ssm, FP_ENROLL_COMPLETE);
+ return;
+ }
break;
case FPC_ENROL_STATUS_IMAGE_LOW_COVERAGE:
@@ -1623,6 +1641,9 @@ fpc_dev_probe (FpDevice *device)
case 0xD805:
case 0xDA04:
case 0xD205:
+ case 0x9524:
+ case 0x9544:
+ case 0xC844:
self->max_enroll_stage = MAX_ENROLL_SAMPLES;
break;
diff --git a/libfprint/drivers/goodixmoc/goodix.c b/libfprint/drivers/goodixmoc/goodix.c
index 5a3ffac..33e137f 100644
--- a/libfprint/drivers/goodixmoc/goodix.c
+++ b/libfprint/drivers/goodixmoc/goodix.c
@@ -128,11 +128,13 @@ fp_cmd_receive_cb (FpiUsbTransfer *transfer,
GError *error)
{
FpiDeviceGoodixMoc *self = FPI_DEVICE_GOODIXMOC (device);
+ FpiByteReader reader = {0};
CommandData *data = user_data;
- int ret = -1, ssm_state = 0;
+ int ssm_state = 0;
gxfp_cmd_response_t cmd_reponse = {0, };
pack_header header;
guint32 crc32_calc = 0;
+ guint32 crc32 = 0;
guint16 cmd = 0;
if (error)
@@ -154,8 +156,10 @@ fp_cmd_receive_cb (FpiUsbTransfer *transfer,
return;
}
- ret = gx_proto_parse_header (transfer->buffer, transfer->actual_length, &header);
- if (ret != 0)
+ reader.data = transfer->buffer;
+ reader.size = transfer->actual_length;
+
+ if (gx_proto_parse_header (&reader, &header) != 0)
{
fpi_ssm_mark_failed (transfer->ssm,
fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
@@ -163,8 +167,17 @@ fp_cmd_receive_cb (FpiUsbTransfer *transfer,
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);
- 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_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);
- ret = gx_proto_parse_body (cmd, &transfer->buffer[PACKAGE_HEADER_SIZE], header.len, &cmd_reponse);
- if (ret != 0)
+ fpi_byte_reader_set_pos (&reader, 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_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
@@ -1363,8 +1379,10 @@ gx_fp_probe (FpDevice *device)
case 0x6014:
case 0x6092:
case 0x6094:
+ case 0x609A:
case 0x609C:
case 0x60BC:
+ case 0x60C2:
case 0x6304:
case 0x631C:
case 0x633C:
@@ -1374,6 +1392,8 @@ gx_fp_probe (FpDevice *device)
case 0x63AC:
case 0x63BC:
case 0x63CC:
+ case 0x650A:
+ case 0x650C:
case 0x6582:
case 0x6A94:
case 0x659A:
@@ -1610,10 +1630,12 @@ static const FpIdEntry id_table[] = {
{ .vid = 0x27c6, .pid = 0x6014, },
{ .vid = 0x27c6, .pid = 0x6092, },
{ .vid = 0x27c6, .pid = 0x6094, },
+ { .vid = 0x27c6, .pid = 0x609A, },
{ .vid = 0x27c6, .pid = 0x609C, },
{ .vid = 0x27c6, .pid = 0x60A2, },
{ .vid = 0x27c6, .pid = 0x60A4, },
{ .vid = 0x27c6, .pid = 0x60BC, },
+ { .vid = 0x27c6, .pid = 0x60C2, },
{ .vid = 0x27c6, .pid = 0x6304, },
{ .vid = 0x27c6, .pid = 0x631C, },
{ .vid = 0x27c6, .pid = 0x633C, },
@@ -1624,6 +1646,8 @@ static const FpIdEntry id_table[] = {
{ .vid = 0x27c6, .pid = 0x63BC, },
{ .vid = 0x27c6, .pid = 0x63CC, },
{ .vid = 0x27c6, .pid = 0x6496, },
+ { .vid = 0x27c6, .pid = 0x650A, },
+ { .vid = 0x27c6, .pid = 0x650C, },
{ .vid = 0x27c6, .pid = 0x6582, },
{ .vid = 0x27c6, .pid = 0x6584, },
{ .vid = 0x27c6, .pid = 0x658C, },
@@ -1632,6 +1656,8 @@ static const FpIdEntry id_table[] = {
{ .vid = 0x27c6, .pid = 0x659A, },
{ .vid = 0x27c6, .pid = 0x659C, },
{ .vid = 0x27c6, .pid = 0x6A94, },
+ { .vid = 0x27c6, .pid = 0x6512, },
+ { .vid = 0x27c6, .pid = 0x689A, },
{ .vid = 0, .pid = 0, .driver_data = 0 }, /* terminating entry */
};
diff --git a/libfprint/drivers/goodixmoc/goodix_proto.c b/libfprint/drivers/goodixmoc/goodix_proto.c
index d7713f0..5125d72 100644
--- a/libfprint/drivers/goodixmoc/goodix_proto.c
+++ b/libfprint/drivers/goodixmoc/goodix_proto.c
@@ -18,6 +18,8 @@
*/
#include
+#include
+
#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 (data & 0x01)
- reflection |= (1 << ((n_bits - 1) - bit));
+ reflection |= (1LU << ((n_bits - 1) - bit));
data = (data >> 1);
}
@@ -211,7 +213,11 @@ gx_proto_build_package (uint8_t *ppackage,
init_pack_header (&header, payload_size, cmd, 0);
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);
@@ -220,94 +226,108 @@ gx_proto_build_package (uint8_t *ppackage,
int
-gx_proto_parse_header (
- uint8_t *buffer,
- uint32_t buffer_len,
- pack_header *pheader)
+gx_proto_parse_header (FpiByteReader *reader,
+ pack_header *pheader)
{
- if (!buffer || !pheader)
- return -1;
- if (buffer_len < PACKAGE_HEADER_SIZE + PACKAGE_CRC_SIZE)
+ if (!pheader)
return -1;
- memcpy (pheader, buffer, sizeof (pack_header));
- pheader->len = GUINT16_FROM_LE (pheader->len);
- if (buffer_len < pheader->len + PACKAGE_HEADER_SIZE)
- return -1;
+ if (!fpi_byte_reader_get_uint8 (reader, &pheader->cmd0))
+ g_return_val_if_reached (-1);
+
+ if (!fpi_byte_reader_get_uint8 (reader, &pheader->cmd1))
+ g_return_val_if_reached (-1);
+
+ if (!fpi_byte_reader_get_uint8 (reader, &pheader->packagenum))
+ g_return_val_if_reached (-1);
+
+ if (!fpi_byte_reader_get_uint8 (reader, &pheader->reserved))
+ g_return_val_if_reached (-1);
+
+ if (!fpi_byte_reader_get_uint16_le (reader, &pheader->len))
+ g_return_val_if_reached (-1);
+
+ if (!fpi_byte_reader_get_uint8 (reader, &pheader->crc8))
+ g_return_val_if_reached (-1);
+
+ if (!fpi_byte_reader_get_uint8 (reader, &pheader->rev_crc8))
+ g_return_val_if_reached (-1);
+
pheader->len -= PACKAGE_CRC_SIZE;
+
return 0;
}
static int
-gx_proto_parse_fingerid (
- uint8_t * fid_buffer,
- uint16_t fid_buffer_size,
- ptemplate_format_t template
- )
+gx_proto_parse_fingerid (FpiByteReader *reader,
+ ptemplate_format_t template)
{
- uint8_t * buffer = NULL;
- uint16_t Offset = 0;
+ uint8_t byte;
+ const uint8_t *buffer;
- if (!template || !fid_buffer)
+ if (!template)
return -1;
- if (fid_buffer_size < G_STRUCT_OFFSET (template_format_t, payload) + sizeof (uint32_t))
- return -1;
+ if (!fpi_byte_reader_get_uint8 (reader, &byte) || byte != 67)
+ g_return_val_if_reached (-1);
- buffer = fid_buffer;
- Offset = 0;
+ if (!fpi_byte_reader_get_uint8 (reader, &template->type))
+ g_return_val_if_reached (-1);
- if (buffer[Offset++] != 67)
- return -1;
+ if (!fpi_byte_reader_get_uint8 (reader, &template->finger_index))
+ g_return_val_if_reached (-1);
- template->type = buffer[Offset++];
- template->finger_index = buffer[Offset++];
- Offset++;
- memcpy (template->accountid, &buffer[Offset], sizeof (template->accountid));
- Offset += sizeof (template->accountid);
- memcpy (template->tid, &buffer[Offset], sizeof (template->tid));
- Offset += sizeof (template->tid); // Offset == 68
- template->payload.size = buffer[Offset++];
- if (template->payload.size > sizeof (template->payload.data))
- return -1;
- if (template->payload.size + Offset > fid_buffer_size)
- return -1;
- memset (template->payload.data, 0, template->payload.size);
- memcpy (template->payload.data, &buffer[Offset], template->payload.size);
+ if (!fpi_byte_reader_skip (reader, 1))
+ g_return_val_if_reached (-1);
+
+ if (!fpi_byte_reader_get_data (reader, sizeof (template->accountid), &buffer))
+ g_return_val_if_reached (-1);
+
+ memcpy (template->accountid, buffer, sizeof (template->accountid));
+
+ if (!fpi_byte_reader_get_data (reader, sizeof (template->tid), &buffer))
+ g_return_val_if_reached (-1);
+
+ memcpy (template->tid, buffer, sizeof (template->tid));
+
+ 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;
}
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;
- uint8_t *fingerlist = NULL;
-
- if (!buffer || !presp)
- return -1;
- if (buffer_len < 1)
+ if (!presp)
return -1;
- presp->result = buffer[0];
+
+ if (!fpi_byte_reader_get_uint8 (byte_reader, &presp->result))
+ g_return_val_if_reached (-1);
+
switch (HIBYTE (cmd))
{
case RESPONSE_PACKAGE_CMD:
{
- if (buffer_len < sizeof (gxfp_parse_msg_t) + 1)
- return -1;
- presp->parse_msg.ack_cmd = buffer[1];
+ if (!fpi_byte_reader_get_uint8 (byte_reader, &presp->parse_msg.ack_cmd))
+ g_return_val_if_reached (-1);
}
break;
case MOC_CMD0_UPDATE_CONFIG:
{
- presp->finger_config.status = buffer[0];
- if (buffer_len >= 3)
- presp->finger_config.max_stored_prints = buffer[2];
- else
- /* to compatiable old version firmware */
- presp->finger_config.max_stored_prints = FP_MAX_FINGERNUM;
+ presp->finger_config.status = presp->result;
+ /* 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;
@@ -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:
presp->power_button_shield_resp.resp_cmd1 = LOBYTE (cmd);
- if (buffer_len >= 2)
- {
- uint8_t support_pwr_shield = buffer[1];
- if (support_pwr_shield == 0xFF)
- g_debug ("Power button shield feature not supported!\n");
- }
+ uint8_t support_pwr_shield;
+
+ if (fpi_byte_reader_get_uint8 (byte_reader, &support_pwr_shield) &&
+ support_pwr_shield == 0xFF)
+ g_debug ("Power button shield feature not supported!\n");
break;
case MOC_CMD0_GET_VERSION:
- if (buffer_len < sizeof (gxfp_version_info_t) + 1)
- return -1;
- memcpy (&presp->version_info, buffer + 1, sizeof (gxfp_version_info_t));
+ const uint8_t *version_info;
+
+ if (!fpi_byte_reader_get_data (byte_reader, sizeof (gxfp_version_info_t), &version_info))
+ g_return_val_if_reached (-1);
+
+ memcpy (&presp->version_info, version_info, sizeof (gxfp_version_info_t));
break;
case MOC_CMD0_CAPTURE_DATA:
if (LOBYTE (cmd) == MOC_CMD1_DEFAULT)
{
- if (buffer_len < sizeof (gxfp_capturedata_t) + 1)
- return -1;
- presp->capture_data_resp.img_quality = buffer[1];
- presp->capture_data_resp.img_coverage = buffer[2];
+ if (!fpi_byte_reader_get_uint8 (byte_reader,
+ &presp->capture_data_resp.img_quality))
+ g_return_val_if_reached (-1);
+
+ if (!fpi_byte_reader_get_uint8 (byte_reader,
+ &presp->capture_data_resp.img_coverage))
+ g_return_val_if_reached (-1);
}
break;
case MOC_CMD0_ENROLL_INIT:
- if (buffer_len < sizeof (gxfp_enroll_create_t) + 1)
- return -1;
- if (presp->result == GX_SUCCESS)
- memcpy (&presp->enroll_create.tid, &buffer[1], TEMPLATE_ID_SIZE);
+ if (presp->result != GX_SUCCESS)
+ break;
+ const uint8_t *tid;
+ if (!fpi_byte_reader_get_data (byte_reader, TEMPLATE_ID_SIZE, &tid))
+ g_return_val_if_reached (-1);
+ memcpy (presp->enroll_create.tid, tid, TEMPLATE_ID_SIZE);
break;
case MOC_CMD0_ENROLL:
- if (buffer_len < sizeof (gxfp_enroll_update_t))
- return -1;
- presp->enroll_update.rollback = (buffer[0] < 0x80) ? false : true;
- presp->enroll_update.img_overlay = buffer[1];
- presp->enroll_update.img_preoverlay = buffer[2];
+ presp->enroll_update.rollback = (presp->result < 0x80) ? false : true;
+ if (!fpi_byte_reader_get_uint8 (byte_reader,
+ &presp->enroll_update.img_overlay))
+ g_return_val_if_reached (-1);
+
+ if (!fpi_byte_reader_get_uint8 (byte_reader,
+ &presp->enroll_update.img_preoverlay))
+ g_return_val_if_reached (-1);
break;
case MOC_CMD0_CHECK4DUPLICATE:
presp->check_duplicate_resp.duplicate = (presp->result == 0) ? false : true;
if (presp->check_duplicate_resp.duplicate)
{
- if (buffer_len < 3)
- return -1;
- uint16_t tid_size = GUINT16_FROM_LE (*(uint16_t *) (buffer + 1));
- offset += 3;
-
- if (buffer_len < tid_size + offset)
- return -1;
- if (gx_proto_parse_fingerid (buffer + offset, tid_size, &presp->check_duplicate_resp.template) != 0)
- return -1;
+ uint16_t tid_size;
+ FpiByteReader tid_reader;
+
+ if (!fpi_byte_reader_get_uint16_le (byte_reader, &tid_size))
+ g_return_val_if_reached (-1);
+
+ if (!fpi_byte_reader_get_sub_reader (byte_reader, &tid_reader, tid_size))
+ g_return_val_if_reached (-1);
+
+ if (gx_proto_parse_fingerid (&tid_reader, &presp->check_duplicate_resp.template) != 0)
+ g_return_val_if_reached (-1);
}
break;
case MOC_CMD0_GETFINGERLIST:
if (presp->result != GX_SUCCESS)
break;
- if (buffer_len < 2)
- return -1;
- presp->finger_list_resp.finger_num = buffer[1];
- fingerlist = buffer + 2;
+
+ if (!fpi_byte_reader_get_uint8 (byte_reader,
+ &presp->finger_list_resp.finger_num))
+ g_return_val_if_reached (-1);
+
for(uint8_t num = 0; num < presp->finger_list_resp.finger_num; num++)
{
uint16_t fingerid_length;
- if (buffer_len < offset + 2)
- return -1;
- fingerid_length = GUINT16_FROM_LE (*(uint16_t *) (fingerlist + offset));
- offset += 2;
- if (buffer_len < fingerid_length + offset)
- return -1;
- if (gx_proto_parse_fingerid (fingerlist + offset,
- fingerid_length,
+ FpiByteReader fingerid_reader;
+
+ if (!fpi_byte_reader_get_uint16_le (byte_reader, &fingerid_length))
+ g_return_val_if_reached (-1);
+
+ if (!fpi_byte_reader_get_sub_reader (byte_reader, &fingerid_reader,
+ fingerid_length))
+ g_return_val_if_reached (-1);
+
+ if (gx_proto_parse_fingerid (&fingerid_reader,
&presp->finger_list_resp.finger_list[num]) != 0)
{
g_warning ("Failed to parse finger list");
- return -1;
+ g_return_val_if_reached (-1);
}
- offset += fingerid_length;
}
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;
uint8_t study = 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 (buffer_len < 10)
- return -1;
- offset += 1;
- presp->verify.rejectdetail = GUINT16_FROM_LE (*(uint16_t *) (buffer + offset));
- offset += 2;
- score = GUINT32_FROM_LE (*(uint32_t *) (buffer + offset));
- offset += 4;
- study = buffer[offset];
- offset += 1;
- fingerid_size = GUINT16_FROM_LE (*(uint16_t *) (buffer + offset));
- offset += 2;
- if (buffer_len < fingerid_size + offset)
- return -1;
- if (gx_proto_parse_fingerid (buffer + offset, fingerid_size, &presp->verify.template) != 0)
+ FpiByteReader finger_reader;
+
+ if (!fpi_byte_reader_get_uint16_le (byte_reader,
+ &presp->verify.rejectdetail))
+ g_return_val_if_reached (-1);
+
+ if (!fpi_byte_reader_get_uint32_le (byte_reader, &score))
+ g_return_val_if_reached (-1);
+
+ if (!fpi_byte_reader_get_uint8 (byte_reader, &study))
+ g_return_val_if_reached (-1);
+
+ if (!fpi_byte_reader_get_uint16_le (byte_reader, &fingerid_size))
+ g_return_val_if_reached (-1);
+
+ if (!fpi_byte_reader_get_sub_reader (byte_reader, &finger_reader,
+ fingerid_size))
+ g_return_val_if_reached (-1);
+
+ if (gx_proto_parse_fingerid (&finger_reader,
+ &presp->verify.template) != 0)
{
presp->result = GX_FAILED;
break;
@@ -432,7 +475,7 @@ gx_proto_parse_body (uint16_t cmd, uint8_t *buffer, uint16_t buffer_len, pgxfp_c
break;
case MOC_CMD0_FINGER_MODE:
- presp->finger_status.status = buffer[0];
+ presp->finger_status.status = presp->result;
break;
default:
diff --git a/libfprint/drivers/goodixmoc/goodix_proto.h b/libfprint/drivers/goodixmoc/goodix_proto.h
index b8ccdca..6302450 100644
--- a/libfprint/drivers/goodixmoc/goodix_proto.h
+++ b/libfprint/drivers/goodixmoc/goodix_proto.h
@@ -22,6 +22,8 @@
#include
#include
+#include "fpi-byte-reader.h"
+
#define PACKAGE_CRC_SIZE (4)
#define PACKAGE_HEADER_SIZE (8)
@@ -133,7 +135,7 @@ typedef struct _template_format
typedef struct _gxfp_verify
{
bool match;
- uint32_t rejectdetail;
+ uint16_t rejectdetail;
template_format_t template;
} gxfp_verify_t, *pgxfp_verify_t;
@@ -232,13 +234,11 @@ int gx_proto_build_package (uint8_t *ppackage,
const uint8_t *payload,
uint32_t payload_size);
-int gx_proto_parse_header (uint8_t *buffer,
- uint32_t buffer_len,
- pack_header *pheader);
+int gx_proto_parse_header (FpiByteReader *reader,
+ pack_header *pheader);
int gx_proto_parse_body (uint16_t cmd,
- uint8_t *buffer,
- uint16_t buffer_len,
+ FpiByteReader *byte_reader,
pgxfp_cmd_response_t presponse);
int gx_proto_init_sensor_config (pgxfp_sensor_cfg_t pconfig);
diff --git a/libfprint/drivers/realtek/realtek.c b/libfprint/drivers/realtek/realtek.c
index 4532290..425aadf 100644
--- a/libfprint/drivers/realtek/realtek.c
+++ b/libfprint/drivers/realtek/realtek.c
@@ -28,6 +28,7 @@ G_DEFINE_TYPE (FpiDeviceRealtek, fpi_device_realtek, FP_TYPE_DEVICE)
static const FpIdEntry id_table[] = {
{ .vid = 0x0bda, .pid = 0x5813, },
+ { .vid = 0x0bda, .pid = 0x5816, },
{ .vid = 0, .pid = 0, .driver_data = 0 }, /* terminating entry */
};
@@ -92,6 +93,50 @@ fp_task_ssm_generic_cb (FpiDeviceRealtek *self,
fpi_ssm_next_state (self->task_ssm);
}
+static void
+fp_get_device_info_cb (FpiDeviceRealtek *self,
+ uint8_t *buffer_in,
+ GError *error)
+{
+ if (error)
+ {
+ fpi_ssm_mark_failed (self->task_ssm, error);
+ return;
+ }
+
+ self->template_len = TEMPLATE_LEN_COMMON;
+
+ fpi_ssm_next_state (self->task_ssm);
+}
+
+static void
+fp_update_template_cb (FpiDeviceRealtek *self,
+ uint8_t *buffer_in,
+ GError *error)
+{
+ if (error)
+ {
+ fpi_ssm_mark_failed (self->task_ssm, error);
+ return;
+ }
+
+ fpi_ssm_jump_to_state (self->task_ssm, FP_RTK_VERIFY_NUM_STATES);
+}
+
+static void
+fp_enroll_commit_cb (FpiDeviceRealtek *self,
+ uint8_t *buffer_in,
+ GError *error)
+{
+ if (error)
+ {
+ fpi_ssm_mark_failed (self->task_ssm, error);
+ return;
+ }
+
+ fpi_ssm_jump_to_state (self->task_ssm, FP_RTK_ENROLL_NUM_STATES);
+}
+
static void
fp_finish_capture_cb (FpiDeviceRealtek *self,
uint8_t *buffer_in,
@@ -103,8 +148,17 @@ fp_finish_capture_cb (FpiDeviceRealtek *self,
return;
}
- gint capture_status = buffer_in[0];
+ /* We hope this polling CMD can be completed before the action is cancelled */
+ GCancellable *cancellable = fpi_device_get_cancellable (FP_DEVICE (self));
+ if (g_cancellable_is_cancelled (cancellable))
+ {
+ fpi_ssm_mark_failed (self->task_ssm,
+ fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
+ "Action is cancelled!"));
+ return;
+ }
+ gint capture_status = buffer_in[0];
if (capture_status == 0)
{
fpi_device_report_finger_status_changes (FP_DEVICE (self),
@@ -238,7 +292,6 @@ fp_identify_feature_cb (FpiDeviceRealtek *self,
}
gint in_status = buffer_in[0];
-
if (in_status == FP_RTK_CMD_ERR)
{
fpi_ssm_mark_failed (self->task_ssm,
@@ -291,7 +344,7 @@ fp_identify_feature_cb (FpiDeviceRealtek *self,
else
{
fpi_device_identify_report (device, print, match, error);
- fpi_ssm_mark_completed (self->task_ssm);
+ fpi_ssm_jump_to_state (self->task_ssm, FP_RTK_VERIFY_NUM_STATES);
}
return;
}
@@ -340,9 +393,9 @@ fp_get_delete_pos_cb (FpiDeviceRealtek *self,
for (gint i = 0; i < self->template_num; i++)
{
- if (buffer_in[i * TEMPLATE_LEN] != 0)
+ if (buffer_in[i * self->template_len] != 0)
{
- memcpy (temp_userid, buffer_in + i * TEMPLATE_LEN + UID_OFFSET, DEFAULT_UID_LEN);
+ memcpy (temp_userid, buffer_in + i * self->template_len + UID_OFFSET, DEFAULT_UID_LEN);
if (g_strcmp0 (fp_print_get_description (print), (const char *) temp_userid) == 0)
{
self->pos_index = i;
@@ -380,10 +433,25 @@ fp_get_enroll_num_cb (FpiDeviceRealtek *self,
}
static void
-fp_get_template_cb (FpiDeviceRealtek *self,
- uint8_t *buffer_in,
- GError *error)
+fp_verify_get_template_cb (FpiDeviceRealtek *self,
+ uint8_t *buffer_in,
+ GError *error)
+{
+ if (error)
+ {
+ fpi_ssm_mark_failed (self->task_ssm, error);
+ return;
+ }
+
+ fpi_ssm_next_state (self->task_ssm);
+}
+
+static void
+fp_enroll_get_template_cb (FpiDeviceRealtek *self,
+ uint8_t *buffer_in,
+ GError *error)
{
+ g_autofree guchar *seq_list = NULL;
gboolean found = FALSE;
if (error)
@@ -394,7 +462,7 @@ fp_get_template_cb (FpiDeviceRealtek *self,
for (gint i = 0; i < self->template_num; i++)
{
- if (buffer_in[i * TEMPLATE_LEN] == 0)
+ if (buffer_in[i * self->template_len] == 0)
{
self->pos_index = i;
found = TRUE;
@@ -425,7 +493,6 @@ fp_check_duplicate_cb (FpiDeviceRealtek *self,
}
gint in_status = buffer_in[0];
-
if (in_status == FP_RTK_CMD_ERR)
{
fpi_ssm_mark_failed (self->task_ssm,
@@ -471,10 +538,10 @@ fp_list_cb (FpiDeviceRealtek *self,
for (gint i = 0; i < self->template_num; i++)
{
- if (buffer_in[i * TEMPLATE_LEN] != 0)
+ if (buffer_in[i * self->template_len] != 0)
{
FpPrint *print = NULL;
- print = fp_print_from_data (self, buffer_in + i * TEMPLATE_LEN + SUBFACTOR_OFFSET);
+ print = fp_print_from_data (self, buffer_in + i * self->template_len + SUBFACTOR_OFFSET);
g_ptr_array_add (list_result, g_object_ref_sink (print));
found = TRUE;
}
@@ -518,11 +585,11 @@ parse_status (guint8 *buffer, gint status_type)
{
switch (status_type)
{
- case FP_RTK_MSG_PLAINTEXT_NO_STATUS:
+ case FP_RTK_MSG_NO_STATUS:
return 0;
break;
- case FP_RTK_MSG_PLAINTEXT:
+ case FP_RTK_MSG_DEFAULT:
return buffer[0];
break;
@@ -621,13 +688,13 @@ fp_cmd_run_state (FpiSsm *ssm, FpDevice *dev)
break;
case FP_RTK_CMD_TRANS_DATA:
- if (self->cmd_type == FP_RTK_CMD_ONLY)
+ if (self->cmd_type == FP_RTK_CMD_BULK_ONLY)
{
fpi_ssm_jump_to_state (ssm, FP_RTK_CMD_GET_STATUS);
break;
}
- if (self->cmd_type == FP_RTK_CMD_WRITE)
+ if (self->cmd_type == FP_RTK_CMD_BULK_WRITE)
{
if (self->data_transfer)
{
@@ -688,10 +755,10 @@ fp_cmd_ssm_done (FpiSsm *ssm, FpDevice *dev, GError *error)
}
static FpiUsbTransfer *
-prepare_transfer (FpDevice *dev,
- guint8 *data,
- gsize data_len,
- GDestroyNotify free_func)
+prepare_bulk_transfer (FpDevice *dev,
+ guint8 *data,
+ gsize data_len,
+ GDestroyNotify free_func)
{
g_autoptr(FpiUsbTransfer) transfer = NULL;
@@ -708,29 +775,100 @@ prepare_transfer (FpDevice *dev,
return g_steal_pointer (&transfer);
}
+
+static void
+fp_ctrl_cmd_cb (FpiUsbTransfer *transfer,
+ FpDevice *device,
+ gpointer user_data,
+ GError *error)
+{
+ FpiDeviceRealtek *self = FPI_DEVICE_REALTEK (device);
+ g_autofree CommandData *data = g_steal_pointer (&user_data);
+
+ g_return_if_fail (data != NULL);
+
+ if (error)
+ {
+ fpi_ssm_mark_failed (transfer->ssm, error);
+ return;
+ }
+
+ if (transfer->direction == G_USB_DEVICE_DIRECTION_HOST_TO_DEVICE)
+ {
+ if (data->callback)
+ data->callback (self, NULL, NULL);
+ }
+ else
+ {
+ if (transfer->actual_length == 0)
+ {
+ fp_info ("Control transfer receive data failed!");
+ fpi_ssm_mark_failed (transfer->ssm,
+ fpi_device_error_new (FP_DEVICE_ERROR_DATA_INVALID));
+ return;
+ }
+
+ if (data->callback)
+ data->callback (self, transfer->buffer, NULL);
+ }
+}
+
+static void
+rtk_send_ctrl_cmd (FpiDeviceRealtek *self,
+ struct rtk_cmd_ctrl *ctrl_cmd,
+ guint8 *cmd_data,
+ SynCmdMsgCallback callback)
+{
+ FpiUsbTransfer *transfer = NULL;
+ g_autofree CommandData *data = g_new0 (CommandData, 1);
+
+ data->callback = callback;
+
+ transfer = fpi_usb_transfer_new (FP_DEVICE (self));
+ fpi_usb_transfer_fill_control (transfer,
+ ctrl_cmd->direction,
+ G_USB_DEVICE_REQUEST_TYPE_VENDOR,
+ G_USB_DEVICE_RECIPIENT_DEVICE,
+ ctrl_cmd->request,
+ ctrl_cmd->value,
+ ctrl_cmd->index,
+ ctrl_cmd->len);
+
+ transfer->ssm = self->task_ssm;
+ if (ctrl_cmd->direction == G_USB_DEVICE_DIRECTION_DEVICE_TO_HOST &&
+ cmd_data != NULL && ctrl_cmd->len != 0)
+ memcpy (transfer->buffer, cmd_data, ctrl_cmd->len);
+
+ fpi_usb_transfer_submit (transfer,
+ CMD_TIMEOUT,
+ NULL,
+ fp_ctrl_cmd_cb,
+ g_steal_pointer (&data));
+}
+
static void
-realtek_sensor_cmd (FpiDeviceRealtek *self,
- guint8 *cmd,
- guint8 *trans_data,
- FpRtkMsgType message_type,
- gboolean bwait_data_delay,
- SynCmdMsgCallback callback)
+rtk_sensor_bulk_cmd (FpiDeviceRealtek *self,
+ guint8 *cmd,
+ guint8 *trans_data,
+ FpRtkMsgType message_type,
+ gboolean bwait_data_delay,
+ SynCmdMsgCallback callback)
{
g_autoptr(FpiUsbTransfer) cmd_transfer = NULL;
g_autoptr(FpiUsbTransfer) data_transfer = NULL;
CommandData *data = g_new0 (CommandData, 1);
- self->cmd_type = GET_CMD_TYPE (cmd[0]);
+ self->cmd_type = GET_BULK_CMD_TYPE (cmd[0]);
self->message_type = message_type;
self->trans_data_len = GET_TRANS_DATA_LEN (cmd[11], cmd[10]);
self->cmd_cancellable = bwait_data_delay;
- cmd_transfer = prepare_transfer (FP_DEVICE (self), cmd, FP_RTK_CMD_TOTAL_LEN, NULL);
+ cmd_transfer = prepare_bulk_transfer (FP_DEVICE (self), cmd, FP_RTK_CMD_BULK_TOTAL_LEN, NULL);
self->cmd_transfer = g_steal_pointer (&cmd_transfer);
- if ((self->cmd_type == FP_RTK_CMD_WRITE) && trans_data)
+ if ((self->cmd_type == FP_RTK_CMD_BULK_WRITE) && trans_data)
{
- data_transfer = prepare_transfer (FP_DEVICE (self), trans_data, self->trans_data_len, g_free);
+ data_transfer = prepare_bulk_transfer (FP_DEVICE (self), trans_data, self->trans_data_len, g_free);
self->data_transfer = g_steal_pointer (&data_transfer);
}
@@ -829,34 +967,49 @@ fp_verify_sm_run_state (FpiSsm *ssm, FpDevice *device)
switch (fpi_ssm_get_cur_state (ssm))
{
+ case FP_RTK_VERIFY_GET_TEMPLATE:
+ g_assert (self->template_num > 0);
+
+ co_get_template.data_len[0] = GET_LEN_L (self->template_len * self->template_num);
+ co_get_template.data_len[1] = GET_LEN_H (self->template_len * self->template_num);
+ cmd_buf = (guint8 *) &co_get_template;
+ rtk_sensor_bulk_cmd (self, cmd_buf, NULL, FP_RTK_MSG_DEFAULT, 0, fp_verify_get_template_cb);
+ break;
+
case FP_RTK_VERIFY_CAPTURE:
fpi_device_report_finger_status_changes (device,
FP_FINGER_STATUS_NEEDED,
FP_FINGER_STATUS_NONE);
cmd_buf = (guint8 *) &co_start_capture;
- realtek_sensor_cmd (self, cmd_buf, NULL, FP_RTK_MSG_PLAINTEXT, 1, fp_task_ssm_generic_cb);
+ rtk_sensor_bulk_cmd (self, cmd_buf, NULL, FP_RTK_MSG_DEFAULT, 0, fp_task_ssm_generic_cb);
break;
case FP_RTK_VERIFY_FINISH_CAPTURE:
cmd_buf = (guint8 *) &co_finish_capture;
- realtek_sensor_cmd (self, cmd_buf, NULL, FP_RTK_MSG_PLAINTEXT, 1, fp_finish_capture_cb);
+ rtk_sensor_bulk_cmd (self, cmd_buf, NULL, FP_RTK_MSG_DEFAULT, 0, fp_finish_capture_cb);
break;
case FP_RTK_VERIFY_ACCEPT_SAMPLE:
co_accept_sample.param[0] = self->fp_purpose;
cmd_buf = (guint8 *) &co_accept_sample;
- realtek_sensor_cmd (self, cmd_buf, NULL, FP_RTK_MSG_PLAINTEXT_NO_STATUS, 1, fp_accept_sample_cb);
+ rtk_sensor_bulk_cmd (self, cmd_buf, NULL, FP_RTK_MSG_NO_STATUS, 0, fp_accept_sample_cb);
break;
case FP_RTK_VERIFY_INDENTIFY_FEATURE:
- cmd_buf = (guint8 *) &tls_identify_feature;
- realtek_sensor_cmd (self, cmd_buf, NULL, FP_RTK_MSG_PLAINTEXT_NO_STATUS, 0, fp_identify_feature_cb);
+ cmd_buf = (guint8 *) &nor_identify_feature;
+ rtk_sensor_bulk_cmd (self, cmd_buf, NULL, FP_RTK_MSG_NO_STATUS, 0, fp_identify_feature_cb);
break;
case FP_RTK_VERIFY_UPDATE_TEMPLATE:
cmd_buf = (guint8 *) &co_update_template;
- realtek_sensor_cmd (self, cmd_buf, NULL, FP_RTK_MSG_PLAINTEXT, 0, fp_task_ssm_generic_cb);
+ rtk_sensor_bulk_cmd (self, cmd_buf, NULL, FP_RTK_MSG_DEFAULT, 0, fp_update_template_cb);
+ break;
+
+ case FP_RTK_VERIFY_CANCEL_CAPTURE:
+ co_cancel_capture.param[0] = self->fp_purpose;
+ cmd_buf = (guint8 *) &co_cancel_capture;
+ rtk_sensor_bulk_cmd (self, cmd_buf, NULL, FP_RTK_MSG_DEFAULT, 0, fp_task_ssm_generic_cb);
break;
}
}
@@ -869,7 +1022,6 @@ fp_enroll_sm_run_state (FpiSsm *ssm, FpDevice *device)
FpiDeviceRealtek *self = FPI_DEVICE_REALTEK (device);
FpPrint *print = NULL;
guint8 *cmd_buf = NULL;
- guint8 *trans_id = NULL;
GVariant *uid = NULL;
GVariant *data = NULL;
gsize user_id_len;
@@ -880,17 +1032,17 @@ fp_enroll_sm_run_state (FpiSsm *ssm, FpDevice *device)
case FP_RTK_ENROLL_GET_TEMPLATE:
g_assert (self->template_num > 0);
- co_get_template.data_len[0] = GET_LEN_L (TEMPLATE_LEN * self->template_num);
- co_get_template.data_len[1] = GET_LEN_H (TEMPLATE_LEN * self->template_num);
+ co_get_template.data_len[0] = GET_LEN_L (self->template_len * self->template_num);
+ co_get_template.data_len[1] = GET_LEN_H (self->template_len * self->template_num);
cmd_buf = (guint8 *) &co_get_template;
- realtek_sensor_cmd (self, cmd_buf, NULL, FP_RTK_MSG_PLAINTEXT, 0, fp_get_template_cb);
+ rtk_sensor_bulk_cmd (self, cmd_buf, NULL, FP_RTK_MSG_DEFAULT, 0, fp_enroll_get_template_cb);
break;
case FP_RTK_ENROLL_BEGIN_POS:
- tls_enroll_begin.param[0] = self->pos_index;
- cmd_buf = (guint8 *) &tls_enroll_begin;
- realtek_sensor_cmd (self, cmd_buf, NULL, FP_RTK_MSG_PLAINTEXT, 0, fp_task_ssm_generic_cb);
+ nor_enroll_begin.param[0] = self->pos_index;
+ cmd_buf = (guint8 *) &nor_enroll_begin;
+ rtk_sensor_bulk_cmd (self, cmd_buf, NULL, FP_RTK_MSG_DEFAULT, 0, fp_task_ssm_generic_cb);
break;
case FP_RTK_ENROLL_CAPTURE:
@@ -899,39 +1051,42 @@ fp_enroll_sm_run_state (FpiSsm *ssm, FpDevice *device)
FP_FINGER_STATUS_NONE);
cmd_buf = (guint8 *) &co_start_capture;
- realtek_sensor_cmd (self, cmd_buf, NULL, FP_RTK_MSG_PLAINTEXT, 1, fp_task_ssm_generic_cb);
+ rtk_sensor_bulk_cmd (self, cmd_buf, NULL, FP_RTK_MSG_DEFAULT, 0, fp_task_ssm_generic_cb);
break;
case FP_RTK_ENROLL_FINISH_CAPTURE:
cmd_buf = (guint8 *) &co_finish_capture;
- realtek_sensor_cmd (self, cmd_buf, NULL, FP_RTK_MSG_PLAINTEXT, 1, fp_finish_capture_cb);
+ rtk_sensor_bulk_cmd (self, cmd_buf, NULL, FP_RTK_MSG_DEFAULT, 0, fp_finish_capture_cb);
break;
case FP_RTK_ENROLL_ACCEPT_SAMPLE:
co_accept_sample.param[0] = self->fp_purpose;
cmd_buf = (guint8 *) &co_accept_sample;
- realtek_sensor_cmd (self, cmd_buf, NULL, FP_RTK_MSG_PLAINTEXT_NO_STATUS, 1, fp_accept_sample_cb);
+ rtk_sensor_bulk_cmd (self, cmd_buf, NULL, FP_RTK_MSG_NO_STATUS, 0, fp_accept_sample_cb);
break;
case FP_RTK_ENROLL_CHECK_DUPLICATE:
cmd_buf = (guint8 *) &co_check_duplicate;
- realtek_sensor_cmd (self, cmd_buf, NULL, FP_RTK_MSG_PLAINTEXT_NO_STATUS, 1, fp_check_duplicate_cb);
+ rtk_sensor_bulk_cmd (self, cmd_buf, NULL, FP_RTK_MSG_NO_STATUS, 0, fp_check_duplicate_cb);
break;
case FP_RTK_ENROLL_COMMIT:
+ gchar *valid_uid = NULL;
+ gint payload_len;
+
+ payload_len = UID_PAYLOAD_LEN_DEFAULT;
+
fpi_device_get_enroll_data (device, &print);
user_id = fpi_print_generate_user_id (print);
- user_id_len = strlen (user_id);
- user_id_len = MIN (DEFAULT_UID_LEN, user_id_len);
+ user_id_len = MIN (DEFAULT_UID_LEN, strlen (user_id));
- payload = g_malloc0 (UID_PAYLOAD_LEN);
+ payload = g_malloc0 (payload_len);
memcpy (payload, user_id, user_id_len);
-
- trans_id = g_steal_pointer (&payload);
+ valid_uid = (gchar *) payload;
finger = SUB_FINGER_01;
uid = g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE,
- user_id,
+ valid_uid,
user_id_len,
1);
data = g_variant_new ("(y@ay)",
@@ -941,14 +1096,23 @@ fp_enroll_sm_run_state (FpiSsm *ssm, FpDevice *device)
fpi_print_set_type (print, FPI_PRINT_RAW);
fpi_print_set_device_stored (print, TRUE);
g_object_set (print, "fpi-data", data, NULL);
- g_object_set (print, "description", user_id, NULL);
+ g_object_set (print, "description", valid_uid, NULL);
g_debug ("user_id: %s, finger: 0x%x", user_id, finger);
- tls_enroll_commit.param[0] = SUB_FINGER_01;
- cmd_buf = (guint8 *) &tls_enroll_commit;
- realtek_sensor_cmd (self, cmd_buf, trans_id, FP_RTK_MSG_PLAINTEXT, 0, fp_task_ssm_generic_cb);
+ nor_enroll_commit.param[0] = SUB_FINGER_01;
+ nor_enroll_commit.data_len[0] = GET_LEN_L (payload_len);
+ nor_enroll_commit.data_len[1] = GET_LEN_H (payload_len);
+
+ cmd_buf = (guint8 *) &nor_enroll_commit;
+ rtk_sensor_bulk_cmd (self, cmd_buf, g_steal_pointer (&payload),
+ FP_RTK_MSG_DEFAULT, 1, fp_enroll_commit_cb);
break;
+
+ case FP_RTK_ENROLL_CANCEL_CAPTURE:
+ co_cancel_capture.param[0] = self->fp_purpose;
+ cmd_buf = (guint8 *) &co_cancel_capture;
+ rtk_sensor_bulk_cmd (self, cmd_buf, NULL, FP_RTK_MSG_DEFAULT, 0, fp_task_ssm_generic_cb);
}
}
@@ -960,15 +1124,19 @@ fp_init_sm_run_state (FpiSsm *ssm, FpDevice *device)
switch (fpi_ssm_get_cur_state (ssm))
{
+ case FP_RTK_INIT_GET_DEVICE_INFO:
+ rtk_send_ctrl_cmd (self, &get_device_info, NULL, fp_get_device_info_cb);
+ break;
+
case FP_RTK_INIT_SELECT_OS:
co_select_system.param[0] = 0x01;
cmd_buf = (guint8 *) &co_select_system;
- realtek_sensor_cmd (self, cmd_buf, NULL, FP_RTK_MSG_PLAINTEXT, 0, fp_task_ssm_generic_cb);
+ rtk_sensor_bulk_cmd (self, cmd_buf, NULL, FP_RTK_MSG_DEFAULT, 0, fp_task_ssm_generic_cb);
break;
case FP_RTK_INIT_GET_ENROLL_NUM:
cmd_buf = (guint8 *) &co_get_enroll_num;
- realtek_sensor_cmd (self, cmd_buf, NULL, FP_RTK_MSG_PLAINTEXT, 0, fp_get_enroll_num_cb);
+ rtk_sensor_bulk_cmd (self, cmd_buf, NULL, FP_RTK_MSG_DEFAULT, 0, fp_get_enroll_num_cb);
break;
}
}
@@ -984,17 +1152,17 @@ fp_delete_sm_run_state (FpiSsm *ssm, FpDevice *device)
case FP_RTK_DELETE_GET_POS:
g_assert (self->template_num > 0);
- co_get_template.data_len[0] = GET_LEN_L (TEMPLATE_LEN * self->template_num);
- co_get_template.data_len[1] = GET_LEN_H (TEMPLATE_LEN * self->template_num);
+ co_get_template.data_len[0] = GET_LEN_L (self->template_len * self->template_num);
+ co_get_template.data_len[1] = GET_LEN_H (self->template_len * self->template_num);
cmd_buf = (guint8 *) &co_get_template;
- realtek_sensor_cmd (self, cmd_buf, NULL, FP_RTK_MSG_PLAINTEXT, 0, fp_get_delete_pos_cb);
+ rtk_sensor_bulk_cmd (self, cmd_buf, NULL, FP_RTK_MSG_DEFAULT, 0, fp_get_delete_pos_cb);
break;
case FP_RTK_DELETE_PRINT:
co_delete_record.param[0] = self->pos_index;
cmd_buf = (guint8 *) &co_delete_record;
- realtek_sensor_cmd (self, cmd_buf, NULL, FP_RTK_MSG_PLAINTEXT, 0, fp_task_ssm_generic_cb);
+ rtk_sensor_bulk_cmd (self, cmd_buf, NULL, FP_RTK_MSG_DEFAULT, 0, fp_task_ssm_generic_cb);
break;
}
}
@@ -1012,17 +1180,14 @@ identify_verify (FpDevice *device)
g_assert (current_action == FPI_DEVICE_ACTION_VERIFY ||
current_action == FPI_DEVICE_ACTION_IDENTIFY);
- if (current_action == FPI_DEVICE_ACTION_IDENTIFY)
- self->fp_purpose = FP_RTK_PURPOSE_IDENTIFY;
- else
- self->fp_purpose = FP_RTK_PURPOSE_VERIFY;
+ self->fp_purpose = FP_RTK_PURPOSE_IDENTIFY;
g_assert (!self->task_ssm);
self->task_ssm = fpi_ssm_new_full (device,
fp_verify_sm_run_state,
FP_RTK_VERIFY_NUM_STATES,
- FP_RTK_VERIFY_NUM_STATES,
+ FP_RTK_VERIFY_CANCEL_CAPTURE,
"Verify & Identify");
fpi_ssm_start (self->task_ssm, fp_verify_ssm_done);
@@ -1042,7 +1207,7 @@ enroll (FpDevice *device)
self->task_ssm = fpi_ssm_new_full (device,
fp_enroll_sm_run_state,
FP_RTK_ENROLL_NUM_STATES,
- FP_RTK_ENROLL_NUM_STATES,
+ FP_RTK_ENROLL_CANCEL_CAPTURE,
"Enroll");
fpi_ssm_start (self->task_ssm, fp_enroll_ssm_done);
@@ -1167,7 +1332,7 @@ clear_storage (FpDevice *device)
G_DEBUG_HERE ();
co_delete_record.param[0] = 0xff;
cmd_buf = (guint8 *) &co_delete_record;
- realtek_sensor_cmd (self, cmd_buf, NULL, FP_RTK_MSG_PLAINTEXT, 0, fp_clear_storage_cb);
+ rtk_sensor_bulk_cmd (self, cmd_buf, NULL, FP_RTK_MSG_DEFAULT, 0, fp_clear_storage_cb);
}
static void
@@ -1179,11 +1344,11 @@ list_print (FpDevice *device)
G_DEBUG_HERE ();
g_assert (self->template_num > 0);
- co_get_template.data_len[0] = GET_LEN_L (TEMPLATE_LEN * self->template_num);
- co_get_template.data_len[1] = GET_LEN_H (TEMPLATE_LEN * self->template_num);
+ co_get_template.data_len[0] = GET_LEN_L (self->template_len * self->template_num);
+ co_get_template.data_len[1] = GET_LEN_H (self->template_len * self->template_num);
cmd_buf = (guint8 *) &co_get_template;
- realtek_sensor_cmd (self, cmd_buf, NULL, FP_RTK_MSG_PLAINTEXT, 1, fp_list_cb);
+ rtk_sensor_bulk_cmd (self, cmd_buf, NULL, FP_RTK_MSG_DEFAULT, 1, fp_list_cb);
}
static void
diff --git a/libfprint/drivers/realtek/realtek.h b/libfprint/drivers/realtek/realtek.h
index 803922f..5658e05 100644
--- a/libfprint/drivers/realtek/realtek.h
+++ b/libfprint/drivers/realtek/realtek.h
@@ -30,16 +30,17 @@
#define EP_IN_MAX_BUF_SIZE 2048
-#define FP_RTK_CMD_TOTAL_LEN 12
-#define FP_RTK_CMD_LEN 2
-#define FP_RTK_CMD_PARAM_LEN 4
-#define FP_RTK_CMD_ADDR_LEN 4
-#define FP_RTK_CMD_DATA_LEN 2
+#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 TEMPLATE_LEN 35
#define SUBFACTOR_OFFSET 2
#define UID_OFFSET 3
-#define UID_PAYLOAD_LEN 32
+#define UID_PAYLOAD_LEN_DEFAULT 32
/* Command transfer timeout :ms*/
#define CMD_TIMEOUT 1000
@@ -50,7 +51,7 @@
#define DEFAULT_UID_LEN 28
#define SUB_FINGER_01 0xFF
-#define GET_CMD_TYPE(val) ((val & 0xC0) >> 6)
+#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)
@@ -67,19 +68,19 @@ typedef struct
} CommandData;
typedef enum {
- FP_RTK_CMD_ONLY = 0,
- FP_RTK_CMD_READ,
- FP_RTK_CMD_WRITE,
+ FP_RTK_CMD_BULK_ONLY = 0,
+ FP_RTK_CMD_BULK_READ,
+ FP_RTK_CMD_BULK_WRITE,
} FpRtkCmdType;
typedef enum {
- FP_RTK_MSG_PLAINTEXT = 0,
- FP_RTK_MSG_PLAINTEXT_NO_STATUS,
+ FP_RTK_MSG_DEFAULT = 0,
+ FP_RTK_MSG_NO_STATUS,
} FpRtkMsgType;
typedef enum {
- FP_RTK_PURPOSE_IDENTIFY = 0x01, /* identify before enroll */
- FP_RTK_PURPOSE_VERIFY = 0x02,
+ FP_RTK_PURPOSE_VERIFY = 0x01,
+ FP_RTK_PURPOSE_IDENTIFY = 0x02,
FP_RTK_PURPOSE_ENROLL = 0x04,
} FpRtkPurpose;
@@ -107,15 +108,18 @@ typedef enum {
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_CAPTURE = 0,
+ 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;
@@ -126,7 +130,8 @@ typedef enum {
} FpRtkDeleteState;
typedef enum {
- FP_RTK_INIT_SELECT_OS = 0,
+ FP_RTK_INIT_GET_DEVICE_INFO = 0,
+ FP_RTK_INIT_SELECT_OS,
FP_RTK_INIT_GET_ENROLL_NUM,
FP_RTK_INIT_NUM_STATES,
} FpRtkInitState;
@@ -155,66 +160,87 @@ struct _FpiDeviceRealtek
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 realtek_fp_cmd
+struct rtk_cmd_ctrl
{
- uint8_t cmd[FP_RTK_CMD_LEN];
- uint8_t param[FP_RTK_CMD_PARAM_LEN];
- uint8_t addr[FP_RTK_CMD_ADDR_LEN];
- uint8_t data_len[FP_RTK_CMD_DATA_LEN];
+ int direction;
+ uint8_t request;
+ uint16_t value;
+ uint16_t index;
+ uint16_t len;
};
-static struct realtek_fp_cmd co_start_capture = {
+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 realtek_fp_cmd co_finish_capture = {
+static struct rtk_cmd_bulk co_finish_capture = {
.cmd = {0x45, 0x06},
.data_len = {0x05},
};
-static struct realtek_fp_cmd co_accept_sample = {
+static struct rtk_cmd_bulk co_accept_sample = {
.cmd = {0x45, 0x08},
.data_len = {0x09},
};
-static struct realtek_fp_cmd tls_identify_feature = {
+static struct rtk_cmd_bulk nor_identify_feature = {
.cmd = {0x45, 0x22},
.data_len = {0x2A},
};
-static struct realtek_fp_cmd co_get_enroll_num = {
+static struct rtk_cmd_bulk co_get_enroll_num = {
.cmd = {0x45, 0x0d},
.data_len = {0x02},
};
-static struct realtek_fp_cmd co_get_template = {
+static struct rtk_cmd_bulk co_get_template = {
.cmd = {0x45, 0x0E},
};
-static struct realtek_fp_cmd tls_enroll_begin = {
+static struct rtk_cmd_bulk nor_enroll_begin = {
.cmd = {0x05, 0x20},
};
-static struct realtek_fp_cmd co_check_duplicate = {
+static struct rtk_cmd_bulk co_check_duplicate = {
.cmd = {0x45, 0x10},
.data_len = {0x22},
};
-static struct realtek_fp_cmd tls_enroll_commit = {
+static struct rtk_cmd_bulk nor_enroll_commit = {
.cmd = {0x85, 0x21},
- .data_len = {0x20},
};
-static struct realtek_fp_cmd co_update_template = {
+static struct rtk_cmd_bulk co_update_template = {
.cmd = {0x05, 0x11},
};
-static struct realtek_fp_cmd co_delete_record = {
+static struct rtk_cmd_bulk co_delete_record = {
.cmd = {0x05, 0x0F},
};
-static struct realtek_fp_cmd co_select_system = {
+static struct rtk_cmd_bulk co_select_system = {
.cmd = {0x05, 0x13},
+};
+
+static struct rtk_cmd_bulk co_cancel_capture = {
+ .cmd = {0x05, 0x07},
};
\ No newline at end of file
diff --git a/libfprint/drivers/synaptics/bmkt_message.c b/libfprint/drivers/synaptics/bmkt_message.c
index bace95c..d297156 100644
--- a/libfprint/drivers/synaptics/bmkt_message.c
+++ b/libfprint/drivers/synaptics/bmkt_message.c
@@ -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_ID_FIELD] = msg_id;
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;
diff --git a/libfprint/drivers/synaptics/synaptics.c b/libfprint/drivers/synaptics/synaptics.c
index 138e734..c0228fb 100644
--- a/libfprint/drivers/synaptics/synaptics.c
+++ b/libfprint/drivers/synaptics/synaptics.c
@@ -32,22 +32,29 @@ static void compose_and_send_identify_msg (FpDevice *device);
static const FpIdEntry id_table[] = {
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x00BD, },
+ { .vid = SYNAPTICS_VENDOR_ID, .pid = 0x00C2, },
+ { .vid = SYNAPTICS_VENDOR_ID, .pid = 0x00C4, },
+ { .vid = SYNAPTICS_VENDOR_ID, .pid = 0x00C6, },
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x00DF, },
+ { .vid = SYNAPTICS_VENDOR_ID, .pid = 0x00F0, },
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x00F9, },
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x00FC, },
- { .vid = SYNAPTICS_VENDOR_ID, .pid = 0x00C2, },
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0100, },
- { .vid = SYNAPTICS_VENDOR_ID, .pid = 0x00F0, },
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0103, },
+ { .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0104, },
+ { .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0106, },
+ { .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0107, },
+ { .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0108, },
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0123, },
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0124, },
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0126, },
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0129, },
- { .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0168, },
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x015F, },
- { .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0104, },
+ { .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0168, },
+ { .vid = SYNAPTICS_VENDOR_ID, .pid = 0x016C, },
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0173, },
- { .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0106, },
+ { .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0174, },
+ { .vid = SYNAPTICS_VENDOR_ID, .pid = 0x019D, },
{ .vid = 0, .pid = 0, .driver_data = 0 }, /* terminating entry */
};
diff --git a/libfprint/drivers/upekts.c b/libfprint/drivers/upekts.c
index 3d82cb3..828306b 100644
--- a/libfprint/drivers/upekts.c
+++ b/libfprint/drivers/upekts.c
@@ -196,8 +196,9 @@ struct read_msg_data
static void __read_msg_async (FpDevice *dev,
struct read_msg_data *udata);
-#define READ_MSG_DATA_CB_ERR(dev, udata, error) (udata)->callback (dev, \
- READ_MSG_CMD, 0, 0, NULL, 0, (udata)->user_data, error)
+#define READ_MSG_DATA_CB_ERR(dev, udata, error) \
+ (udata)->callback (dev, \
+ READ_MSG_CMD, 0, 0, NULL, 0, (udata)->user_data, error)
static void
busy_ack_sent_cb (FpiUsbTransfer *transfer, FpDevice *device,
@@ -1243,7 +1244,7 @@ do_verify_stop (FpDevice *dev, FpiMatchResult res, GError *error)
FpiSsm *ssm = deinitsm_new (dev, data);
/* Report the error immediately if possible, otherwise delay it. */
- if (error && error->domain == FP_DEVICE_RETRY)
+ if (!error || error->domain == FP_DEVICE_RETRY)
fpi_device_verify_report (dev, res, NULL, error);
else
data->error = error;
@@ -1295,7 +1296,7 @@ verify_start_sm_run_state (FpiSsm *ssm, FpDevice *dev)
memcpy (msg, verify_hdr, sizeof (verify_hdr));
memcpy (msg + sizeof (verify_hdr), data, data_len);
- transfer = alloc_send_cmd28_transfer (dev, 0x03, data, data_len);
+ transfer = alloc_send_cmd28_transfer (dev, 0x03, msg, msg_len);
g_free (msg);
@@ -1341,7 +1342,6 @@ v_handle_resp00 (FpDevice *dev, unsigned char *data,
fp_dbg ("good image");
break;
- case 0x1c: /* FIXME what does this one mean? */
case 0x0b: /* FIXME what does this one mean? */
case 0x23: /* FIXME what does this one mean? */
error = fpi_device_retry_new (FP_DEVICE_RETRY_GENERAL);
@@ -1351,6 +1351,14 @@ v_handle_resp00 (FpDevice *dev, unsigned char *data,
error = fpi_device_retry_new (FP_DEVICE_RETRY_REMOVE_FINGER);
break;
+ case 0x1c: /* swipe too fast */
+ error = fpi_device_retry_new (FP_DEVICE_RETRY_TOO_FAST);
+ break;
+
+ case 0x1d: /* too much horizontal movement */
+ error = fpi_device_retry_new (FP_DEVICE_RETRY_CENTER_FINGER);
+ break;
+
case 0x1e: /* swipe too short */
error = fpi_device_retry_new (FP_DEVICE_RETRY_TOO_SHORT);
break;
@@ -1439,7 +1447,7 @@ verify_rd2800_cb (FpDevice *dev, enum read_msg_type msgtype,
do_verify_stop (dev,
FPI_MATCH_ERROR,
fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
- "Response hat wrong command sequence"));
+ "Response had wrong command sequence"));
return;
}
diff --git a/libfprint/drivers/uru4000.c b/libfprint/drivers/uru4000.c
index 047e64c..f8d7b6e 100644
--- a/libfprint/drivers/uru4000.c
+++ b/libfprint/drivers/uru4000.c
@@ -20,8 +20,8 @@
#define FP_COMPONENT "uru4000"
-#include
-#include
+#include
+#include
#include "drivers_api.h"
@@ -148,10 +148,7 @@ struct _FpiDeviceUru4000
int fwfixer_offset;
unsigned char fwfixer_value;
- CK_MECHANISM_TYPE cipher;
- PK11SlotInfo *slot;
- PK11SymKey *symkey;
- SECItem *param;
+ EVP_CIPHER_CTX *cipher_ctx;
};
G_DECLARE_FINAL_TYPE (FpiDeviceUru4000, fpi_device_uru4000, FPI, DEVICE_URU4000,
FpImageDevice);
@@ -246,13 +243,29 @@ response_cb (FpiUsbTransfer *transfer, FpDevice *dev, void *user_data, GError *e
fpi_ssm_mark_failed (ssm, error);
}
+static GError *
+openssl_device_error (void)
+{
+ char buf[256];
+ unsigned long e;
+
+ e = ERR_get_error ();
+ if (e == 0)
+ return fpi_device_error_new_msg (FP_DEVICE_ERROR_GENERAL,
+ "unexpected OpenSSL error");
+
+ ERR_error_string_n (e, buf, G_N_ELEMENTS (buf));
+
+ return fpi_device_error_new_msg (FP_DEVICE_ERROR_GENERAL, "OpenSSL error: %s",
+ buf);
+}
+
static void
challenge_cb (FpiUsbTransfer *transfer, FpDevice *dev, void *user_data, GError *error)
{
FpiSsm *ssm = user_data;
FpiDeviceUru4000 *self = FPI_DEVICE_URU4000 (dev);
- unsigned char respdata[CR_LENGTH];
- PK11Context *ctx;
+ unsigned char respdata[CR_LENGTH * 2];
int outlen;
if (error)
@@ -261,17 +274,39 @@ challenge_cb (FpiUsbTransfer *transfer, FpDevice *dev, void *user_data, GError *
return;
}
+ if (transfer->actual_length != CR_LENGTH)
+ {
+ error = fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
+ "Unexpected buffer length (%" G_GSIZE_FORMAT
+ "instead of %d)",
+ transfer->actual_length, CR_LENGTH);
+ fpi_ssm_mark_failed (ssm, g_steal_pointer (&error));
+ return;
+ }
+
/* submit response */
/* produce response from challenge */
- ctx = PK11_CreateContextBySymKey (self->cipher, CKA_ENCRYPT,
- self->symkey, self->param);
- if (PK11_CipherOp (ctx, respdata, &outlen, CR_LENGTH, transfer->buffer, CR_LENGTH) != SECSuccess ||
- PK11_Finalize (ctx) != SECSuccess)
+ if (!EVP_EncryptUpdate (self->cipher_ctx, respdata, &outlen, transfer->buffer, CR_LENGTH))
+ {
+ fpi_ssm_mark_failed (ssm, openssl_device_error ());
+ return;
+ }
+
+ if (outlen != CR_LENGTH)
+ {
+ error = fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
+ "Unexpected encrypted buffer length (%d"
+ "instead of %d)",
+ outlen, CR_LENGTH);
+ fpi_ssm_mark_failed (ssm, g_steal_pointer (&error));
+ return;
+ }
+
+ if (!EVP_EncryptFinal_ex (self->cipher_ctx, respdata + outlen, &outlen))
{
- fp_err ("Failed to encrypt challenge data");
- error = fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO, "Failed to encrypt challenge data");
+ fpi_ssm_mark_failed (ssm, openssl_device_error ());
+ return;
}
- PK11_DestroyContext (ctx, PR_TRUE);
if (!error)
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:
key = self->last_reg_rd[0];
- key |= self->last_reg_rd[1] << 8;
- key |= self->last_reg_rd[2] << 16;
- key |= self->last_reg_rd[3] << 24;
+ key |= (uint32_t) self->last_reg_rd[1] << 8;
+ key |= (uint32_t) self->last_reg_rd[2] << 16;
+ key |= (uint32_t) self->last_reg_rd[3] << 24;
key ^= self->img_enc_seed;
fp_dbg ("encryption id %02x -> key %08x", img->key_number, key);
@@ -1270,8 +1305,6 @@ dev_init (FpImageDevice *dev)
g_autoptr(GPtrArray) interfaces = NULL;
GUsbInterface *iface = NULL;
guint64 driver_data;
- SECStatus rv;
- SECItem item;
int i;
interfaces = g_usb_device_get_interfaces (fpi_device_get_usb_device (FP_DEVICE (dev)), &error);
@@ -1343,20 +1376,6 @@ dev_init (FpImageDevice *dev)
return;
}
- /* Disable loading p11-kit's user configuration */
- g_setenv ("P11_KIT_NO_USER_CONFIG", "1", TRUE);
-
- /* Initialise NSS early */
- rv = NSS_NoDB_Init (".");
- if (rv != SECSuccess)
- {
- fp_err ("could not initialise NSS");
- fpi_image_device_open_complete (dev,
- fpi_device_error_new_msg (FP_DEVICE_ERROR_GENERAL,
- "Could not initialise NSS"));
- return;
- }
-
self = FPI_DEVICE_URU4000 (dev);
g_clear_pointer (&self->rand, g_rand_free);
@@ -1369,35 +1388,17 @@ dev_init (FpImageDevice *dev)
self->interface = g_usb_interface_get_number (iface);
/* Set up encryption */
- self->cipher = CKM_AES_ECB;
- self->slot = PK11_GetBestSlot (self->cipher, NULL);
- if (self->slot == NULL)
+ if (!(self->cipher_ctx = EVP_CIPHER_CTX_new ()))
{
- fp_err ("could not get encryption slot");
- fpi_image_device_open_complete (dev,
- fpi_device_error_new_msg (FP_DEVICE_ERROR_GENERAL,
- "Could not get encryption slot"));
+ fpi_image_device_open_complete (dev, openssl_device_error ());
return;
}
- item.type = siBuffer;
- item.data = (unsigned char *) crkey;
- item.len = sizeof (crkey);
- self->symkey = PK11_ImportSymKey (self->slot,
- self->cipher,
- PK11_OriginUnwrap,
- CKA_ENCRYPT,
- &item, NULL);
- if (self->symkey == NULL)
+
+ if (!EVP_EncryptInit_ex (self->cipher_ctx, EVP_aes_128_ecb (), NULL, crkey, NULL))
{
- fp_err ("failed to import key into NSS");
- PK11_FreeSlot (self->slot);
- self->slot = NULL;
- fpi_image_device_open_complete (dev,
- fpi_device_error_new_msg (FP_DEVICE_ERROR_GENERAL,
- "Failed to import key into NSS"));
+ fpi_image_device_open_complete (dev, openssl_device_error ());
return;
}
- self->param = PK11_ParamFromIV (self->cipher, NULL);
fpi_image_device_open_complete (dev, NULL);
}
@@ -1408,14 +1409,7 @@ dev_deinit (FpImageDevice *dev)
GError *error = NULL;
FpiDeviceUru4000 *self = FPI_DEVICE_URU4000 (dev);
- if (self->symkey)
- PK11_FreeSymKey (self->symkey);
- if (self->param)
- SECITEM_FreeItem (self->param, PR_TRUE);
- if (self->slot)
- PK11_FreeSlot (self->slot);
-
- NSS_Shutdown ();
+ g_clear_pointer (&self->cipher_ctx, EVP_CIPHER_CTX_free);
g_usb_device_release_interface (fpi_device_get_usb_device (FP_DEVICE (dev)),
self->interface, 0, &error);
diff --git a/libfprint/drivers/vfs101.c b/libfprint/drivers/vfs101.c
index 6963c59..7020726 100644
--- a/libfprint/drivers/vfs101.c
+++ b/libfprint/drivers/vfs101.c
@@ -162,9 +162,9 @@ enum {
/* Dump buffer for debug */
#define dump_buffer(buf) \
- fp_dbg ("%02x %02x %02x %02x %02x %02x %02x %02x", \
- buf[6], buf[7], buf[8], buf[9], buf[10], buf[11], buf[12], buf[13] \
- )
+ fp_dbg ("%02x %02x %02x %02x %02x %02x %02x %02x", \
+ buf[6], buf[7], buf[8], buf[9], buf[10], buf[11], buf[12], buf[13] \
+ )
/* Callback of asynchronous send */
static void
diff --git a/libfprint/drivers/vfs301_proto.c b/libfprint/drivers/vfs301_proto.c
index 6bbb3c7..122a889 100644
--- a/libfprint/drivers/vfs301_proto.c
+++ b/libfprint/drivers/vfs301_proto.c
@@ -157,7 +157,7 @@ vfs301_proto_generate_0B (int subtype, gssize *len)
}
#define HEX_TO_INT(c) \
- (((c) >= '0' && (c) <= '9') ? ((c) - '0') : ((c) - 'A' + 10))
+ (((c) >= '0' && (c) <= '9') ? ((c) - '0') : ((c) - 'A' + 10))
static guint8 *
translate_str (const char **srcL, gssize *len)
@@ -422,15 +422,15 @@ img_process_data (int first_block, FpDeviceVfs301 *dev, const guint8 *buf, int l
/************************** PROTOCOL STUFF ************************************/
#define USB_RECV(from, len) \
- usb_recv (dev, from, len, NULL, NULL)
+ usb_recv (dev, from, len, NULL, NULL)
#define USB_SEND(type, subtype) \
- { \
- const guint8 *data; \
- gssize len; \
- data = vfs301_proto_generate (type, subtype, &len); \
- usb_send (dev, data, len, NULL); \
- }
+ { \
+ const guint8 *data; \
+ gssize len; \
+ data = vfs301_proto_generate (type, subtype, &len); \
+ usb_send (dev, data, len, NULL); \
+ }
#define RAW_DATA(x) g_memdup2 (x, sizeof (x)), sizeof (x)
@@ -489,13 +489,13 @@ vfs301_proto_peek_event (FpDeviceVfs301 *dev)
* we will run into timeouts randomly and need to then try again.
*/
#define PARALLEL_RECEIVE(e1, l1, e2, l2) \
- { \
- g_autoptr(GError) error = NULL; \
- usb_recv (dev, e1, l1, NULL, &error); \
- usb_recv (dev, e2, l2, NULL, NULL); \
- if (g_error_matches (error, G_USB_DEVICE_ERROR, G_USB_DEVICE_ERROR_TIMED_OUT)) \
- usb_recv (dev, e1, l1, NULL, NULL); \
- }
+ { \
+ g_autoptr(GError) error = NULL; \
+ usb_recv (dev, e1, l1, NULL, &error); \
+ usb_recv (dev, e2, l2, NULL, NULL); \
+ if (g_error_matches (error, G_USB_DEVICE_ERROR, G_USB_DEVICE_ERROR_TIMED_OUT)) \
+ usb_recv (dev, e1, l1, NULL, NULL); \
+ }
static void
vfs301_proto_process_event_cb (FpiUsbTransfer *transfer,
diff --git a/libfprint/drivers/vfs5011.c b/libfprint/drivers/vfs5011.c
index 65c98c9..b9e0587 100644
--- a/libfprint/drivers/vfs5011.c
+++ b/libfprint/drivers/vfs5011.c
@@ -41,30 +41,30 @@ struct usb_action
};
#define SEND(ENDPOINT, COMMAND) \
- { \
- .type = ACTION_SEND, \
- .endpoint = ENDPOINT, \
- .name = #COMMAND, \
- .size = sizeof (COMMAND), \
- .data = COMMAND \
- },
+ { \
+ .type = ACTION_SEND, \
+ .endpoint = ENDPOINT, \
+ .name = #COMMAND, \
+ .size = sizeof (COMMAND), \
+ .data = COMMAND \
+ },
#define RECV(ENDPOINT, SIZE) \
- { \
- .type = ACTION_RECEIVE, \
- .endpoint = ENDPOINT, \
- .size = SIZE, \
- .data = NULL \
- },
+ { \
+ .type = ACTION_RECEIVE, \
+ .endpoint = ENDPOINT, \
+ .size = SIZE, \
+ .data = NULL \
+ },
#define RECV_CHECK(ENDPOINT, SIZE, EXPECTED) \
- { \
- .type = ACTION_RECEIVE, \
- .endpoint = ENDPOINT, \
- .size = SIZE, \
- .data = EXPECTED, \
- .correct_reply_size = sizeof (EXPECTED) \
- },
+ { \
+ .type = ACTION_RECEIVE, \
+ .endpoint = ENDPOINT, \
+ .size = SIZE, \
+ .data = EXPECTED, \
+ .correct_reply_size = sizeof (EXPECTED) \
+ },
struct usbexchange_data
{
diff --git a/libfprint/drivers/vfs7552.c b/libfprint/drivers/vfs7552.c
index 852e35b..53b4d3f 100644
--- a/libfprint/drivers/vfs7552.c
+++ b/libfprint/drivers/vfs7552.c
@@ -51,39 +51,39 @@ struct usb_action
};
#define SEND(ENDPOINT, COMMAND) \
- { \
- .type = ACTION_SEND, \
- .endpoint = ENDPOINT, \
- .name = #COMMAND, \
- .size = sizeof (COMMAND), \
- .data = COMMAND \
- },
+ { \
+ .type = ACTION_SEND, \
+ .endpoint = ENDPOINT, \
+ .name = #COMMAND, \
+ .size = sizeof (COMMAND), \
+ .data = COMMAND \
+ },
#define RECV(ENDPOINT, SIZE) \
- { \
- .type = ACTION_RECEIVE, \
- .endpoint = ENDPOINT, \
- .size = SIZE, \
- .data = NULL \
- },
+ { \
+ .type = ACTION_RECEIVE, \
+ .endpoint = ENDPOINT, \
+ .size = SIZE, \
+ .data = NULL \
+ },
#define RECV_CHECK(ENDPOINT, SIZE, EXPECTED) \
- { \
- .type = ACTION_RECEIVE, \
- .endpoint = ENDPOINT, \
- .size = SIZE, \
- .data = EXPECTED, \
- .correct_reply_size = sizeof (EXPECTED) \
- },
+ { \
+ .type = ACTION_RECEIVE, \
+ .endpoint = ENDPOINT, \
+ .size = SIZE, \
+ .data = EXPECTED, \
+ .correct_reply_size = sizeof (EXPECTED) \
+ },
#define RECV_CHECK_SIZE(ENDPOINT, SIZE, EXPECTED) \
- { \
- .type = ACTION_RECEIVE, \
- .endpoint = ENDPOINT, \
- .size = SIZE, \
- .data = NULL, \
- .correct_reply_size = sizeof (EXPECTED) \
- },
+ { \
+ .type = ACTION_RECEIVE, \
+ .endpoint = ENDPOINT, \
+ .size = SIZE, \
+ .data = NULL, \
+ .correct_reply_size = sizeof (EXPECTED) \
+ },
struct usbexchange_data
{
diff --git a/libfprint/drivers/virtual-device.c b/libfprint/drivers/virtual-device.c
index 17a7ad0..aed4424 100644
--- a/libfprint/drivers/virtual-device.c
+++ b/libfprint/drivers/virtual-device.c
@@ -772,6 +772,7 @@ fpi_device_virtual_device_class_init (FpDeviceVirtualDeviceClass *klass)
{
FpDeviceClass *dev_class = FP_DEVICE_CLASS (klass);
GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ const char *hot_seconds;
object_class->finalize = fpi_device_virtual_device_finalize;
@@ -787,5 +788,18 @@ fpi_device_virtual_device_class_init (FpDeviceVirtualDeviceClass *klass)
dev_class->enroll = dev_enroll;
dev_class->cancel = dev_cancel;
+ if ((hot_seconds = g_getenv ("FP_VIRTUAL_DEVICE_HOT_SECONDS")) &&
+ *hot_seconds != '\0')
+ {
+ gint64 hot_seconds_value;
+
+ hot_seconds_value = g_ascii_strtoll (hot_seconds, NULL, 10);
+ if (hot_seconds_value >= G_MAXINT32 || hot_seconds_value < 0)
+ hot_seconds_value = -1;
+
+ dev_class->temp_hot_seconds = hot_seconds_value;
+ g_debug ("device hot seconds set to %d", dev_class->temp_hot_seconds);
+ }
+
fpi_device_class_auto_initialize_features (dev_class);
}
diff --git a/libfprint/drivers/virtual-image.c b/libfprint/drivers/virtual-image.c
index 18657c4..97eebc9 100644
--- a/libfprint/drivers/virtual-image.c
+++ b/libfprint/drivers/virtual-image.c
@@ -191,12 +191,12 @@ on_listener_connected (FpiDeviceVirtualListener *listener,
switch (state)
{
- case FPI_IMAGE_DEVICE_STATE_IDLE:
case FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON:
case FPI_IMAGE_DEVICE_STATE_CAPTURE:
- case FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_OFF:
recv_image (self);
+ case FPI_IMAGE_DEVICE_STATE_IDLE:
+ case FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_OFF:
case FPI_IMAGE_DEVICE_STATE_INACTIVE:
case FPI_IMAGE_DEVICE_STATE_ACTIVATING:
case FPI_IMAGE_DEVICE_STATE_DEACTIVATING:
@@ -310,6 +310,7 @@ fpi_device_virtual_image_class_init (FpDeviceVirtualImageClass *klass)
{
FpDeviceClass *dev_class = FP_DEVICE_CLASS (klass);
FpImageDeviceClass *img_class = FP_IMAGE_DEVICE_CLASS (klass);
+ const char *hot_seconds;
dev_class->id = FP_COMPONENT;
dev_class->full_name = "Virtual image device for debugging";
@@ -321,4 +322,17 @@ fpi_device_virtual_image_class_init (FpDeviceVirtualImageClass *klass)
img_class->activate = dev_activate;
img_class->deactivate = dev_deactivate;
+
+ if ((hot_seconds = g_getenv ("FP_VIRTUAL_IMAGE_HOT_SECONDS")) &&
+ *hot_seconds != '\0')
+ {
+ gint64 hot_seconds_value;
+
+ hot_seconds_value = g_ascii_strtoll (hot_seconds, NULL, 10);
+ if (hot_seconds_value >= G_MAXINT32 || hot_seconds_value < 0)
+ hot_seconds_value = -1;
+
+ dev_class->temp_hot_seconds = hot_seconds_value;
+ g_debug ("device hot seconds set to %d", dev_class->temp_hot_seconds);
+ }
}
diff --git a/libfprint/fp-device.c b/libfprint/fp-device.c
index c143644..ab06e7f 100644
--- a/libfprint/fp-device.c
+++ b/libfprint/fp-device.c
@@ -292,14 +292,14 @@ fp_device_get_property (GObject *object,
case PROP_FPI_UDEV_DATA_SPIDEV:
if (cls->type == FP_DEVICE_TYPE_UDEV)
- g_value_set_string (value, g_strdup (priv->udev_data.spidev_path));
+ g_value_set_string (value, priv->udev_data.spidev_path);
else
g_value_set_string (value, NULL);
break;
case PROP_FPI_UDEV_DATA_HIDRAW:
if (cls->type == FP_DEVICE_TYPE_UDEV)
- g_value_set_string (value, g_strdup (priv->udev_data.hidraw_path));
+ g_value_set_string (value, priv->udev_data.hidraw_path);
else
g_value_set_string (value, NULL);
break;
@@ -1103,8 +1103,8 @@ enroll_data_free (FpEnrollData *data)
* @device: a #FpDevice
* @template_print: (transfer floating): a #FpPrint
* @cancellable: (nullable): a #GCancellable, or %NULL
- * @progress_cb: (nullable) (scope notified): progress reporting callback
- * @progress_data: (closure progress_cb): user data for @progress_cb
+ * @progress_cb: (nullable) (closure progress_data) (scope notified): progress reporting callback
+ * @progress_data: user data for @progress_cb
* @progress_destroy: (destroy progress_data): Destroy notify for @progress_data
* @callback: (scope async): the function to call on completion
* @user_data: the data to pass to @callback
@@ -1248,8 +1248,8 @@ match_data_free (FpMatchData *data)
* @device: a #FpDevice
* @enrolled_print: a #FpPrint to verify
* @cancellable: (nullable): a #GCancellable, or %NULL
- * @match_cb: (nullable) (scope notified): match reporting callback
- * @match_data: (closure match_cb): user data for @match_cb
+ * @match_cb: (nullable) (scope notified) (closure match_data): match reporting callback
+ * @match_data: user data for @match_cb
* @match_destroy: (destroy match_data): Destroy notify for @match_data
* @callback: the function to call on completion
* @user_data: the data to pass to @callback
@@ -1374,8 +1374,8 @@ fp_device_verify_finish (FpDevice *device,
* @device: a #FpDevice
* @prints: (element-type FpPrint) (transfer none): #GPtrArray of #FpPrint
* @cancellable: (nullable): a #GCancellable, or %NULL
- * @match_cb: (nullable) (scope notified): match reporting callback
- * @match_data: (closure match_cb): user data for @match_cb
+ * @match_cb: (nullable) (scope notified) (closure match_data): match reporting callback
+ * @match_data: user data for @match_cb
* @match_destroy: (destroy match_data): Destroy notify for @match_data
* @callback: the function to call on completion
* @user_data: the data to pass to @callback
@@ -1943,8 +1943,8 @@ fp_device_enroll_sync (FpDevice *device,
* @device: a #FpDevice
* @enrolled_print: a #FpPrint to verify
* @cancellable: (nullable): a #GCancellable, or %NULL
- * @match_cb: (nullable) (scope call): match reporting callback
- * @match_data: (closure match_cb): user data for @match_cb
+ * @match_cb: (nullable) (scope call) (closure match_data): match reporting callback
+ * @match_data: user data for @match_cb
* @match: (out): Whether the user presented the correct finger
* @print: (out) (transfer full) (nullable): Location to store the scanned print, or %NULL to ignore
* @error: Return location for errors, or %NULL to ignore
@@ -1983,8 +1983,8 @@ fp_device_verify_sync (FpDevice *device,
* @device: a #FpDevice
* @prints: (element-type FpPrint) (transfer none): #GPtrArray of #FpPrint
* @cancellable: (nullable): a #GCancellable, or %NULL
- * @match_cb: (nullable) (scope call): match reporting callback
- * @match_data: (closure match_cb): user data for @match_cb
+ * @match_cb: (nullable) (scope call) (closure match_data): match reporting callback
+ * @match_data: user data for @match_cb
* @match: (out) (transfer full) (nullable): Location for the matched #FpPrint, or %NULL
* @print: (out) (transfer full) (nullable): Location for the new #FpPrint, or %NULL
* @error: Return location for errors, or %NULL to ignore
diff --git a/libfprint/fp-device.h b/libfprint/fp-device.h
index 9dda747..e82cb53 100644
--- a/libfprint/fp-device.h
+++ b/libfprint/fp-device.h
@@ -113,6 +113,8 @@ typedef enum {
* @FP_DEVICE_RETRY_REMOVE_FINGER: The scan did not succeed due to quality or
* pressure problems; the user should remove their finger from the scanner
* before retrying.
+ * @FP_DEVICE_RETRY_TOO_FAST: The scan did not succeed because the finger
+ * swipe or touch was too fast.
*
* Error codes representing scan failures resulting in the user needing to
* retry.
@@ -122,6 +124,7 @@ typedef enum {
FP_DEVICE_RETRY_TOO_SHORT,
FP_DEVICE_RETRY_CENTER_FINGER,
FP_DEVICE_RETRY_REMOVE_FINGER,
+ FP_DEVICE_RETRY_TOO_FAST,
} FpDeviceRetry;
/**
diff --git a/libfprint/fp-print.h b/libfprint/fp-print.h
index 7a2abee..ac6820d 100644
--- a/libfprint/fp-print.h
+++ b/libfprint/fp-print.h
@@ -29,7 +29,7 @@ G_BEGIN_DECLS
G_DECLARE_FINAL_TYPE (FpPrint, fp_print, FP, PRINT, GInitiallyUnowned)
#define FP_FINGER_IS_VALID(finger) \
- ((finger) >= FP_FINGER_FIRST && (finger) <= FP_FINGER_LAST)
+ ((finger) >= FP_FINGER_FIRST && (finger) <= FP_FINGER_LAST)
#include "fp-device.h"
diff --git a/libfprint/fpi-byte-reader.h b/libfprint/fpi-byte-reader.h
index 7a89a28..c4e64d2 100644
--- a/libfprint/fpi-byte-reader.h
+++ b/libfprint/fpi-byte-reader.h
@@ -675,4 +675,6 @@ fpi_byte_reader_skip_inline (FpiByteReader * reader, guint nbytes)
#endif /* FPI_BYTE_READER_DISABLE_INLINES */
+G_DEFINE_AUTOPTR_CLEANUP_FUNC (FpiByteReader, fpi_byte_reader_free);
+
G_END_DECLS
diff --git a/libfprint/fpi-byte-writer.c b/libfprint/fpi-byte-writer.c
index 73e42cb..cb3514a 100644
--- a/libfprint/fpi-byte-writer.c
+++ b/libfprint/fpi-byte-writer.c
@@ -75,7 +75,8 @@ fpi_byte_writer_new_with_size (guint size, gboolean fixed)
FpiByteWriter *ret = fpi_byte_writer_new ();
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->owned = TRUE;
@@ -142,7 +143,8 @@ fpi_byte_writer_init_with_size (FpiByteWriter * writer, guint size,
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->fixed = fixed;
writer->owned = TRUE;
@@ -209,10 +211,9 @@ fpi_byte_writer_reset_and_get_data (FpiByteWriter * writer)
g_return_val_if_fail (writer != NULL, NULL);
- data = (guint8 *) writer->parent.data;
+ data = (guint8 *) g_steal_pointer (&writer->parent.data);
if (!writer->owned)
data = g_memdup2 (data, writer->parent.size);
- writer->parent.data = NULL;
fpi_byte_writer_reset (writer);
return data;
diff --git a/libfprint/fpi-byte-writer.h b/libfprint/fpi-byte-writer.h
index ccdaf0b..9b21b5f 100644
--- a/libfprint/fpi-byte-writer.h
+++ b/libfprint/fpi-byte-writer.h
@@ -111,6 +111,17 @@ fpi_byte_writer_set_pos (FpiByteWriter *writer, guint pos)
return fpi_byte_reader_set_pos (FPI_BYTE_READER (writer), pos);
}
+static inline gboolean
+fpi_byte_writer_change_pos (FpiByteWriter *writer, gint pos)
+{
+ pos = fpi_byte_writer_get_pos (writer) + pos;
+
+ if (pos < 0)
+ return FALSE;
+
+ return fpi_byte_reader_set_pos (FPI_BYTE_READER (writer), pos);
+}
+
static inline guint
fpi_byte_writer_get_size (const FpiByteWriter *writer)
{
@@ -407,4 +418,7 @@ fpi_byte_writer_fill_inline (FpiByteWriter * writer, guint8 value, guint size)
#endif
+G_DEFINE_AUTOPTR_CLEANUP_FUNC (FpiByteWriter, fpi_byte_writer_free);
+G_DEFINE_AUTO_CLEANUP_CLEAR_FUNC (FpiByteWriter, fpi_byte_writer_reset);
+
G_END_DECLS
diff --git a/libfprint/fpi-device.c b/libfprint/fpi-device.c
index 1b9fa8f..a1be30c 100644
--- a/libfprint/fpi-device.c
+++ b/libfprint/fpi-device.c
@@ -117,6 +117,10 @@ fpi_device_retry_new (FpDeviceRetry error)
msg = "Please try again after removing the finger first.";
break;
+ case FP_DEVICE_RETRY_TOO_FAST:
+ msg = "The swipe was too fast, please try again.";
+ break;
+
default:
g_warning ("Unsupported error, returning general error instead!");
error = FP_DEVICE_RETRY_GENERAL;
@@ -1042,34 +1046,41 @@ fp_device_task_return_in_idle_cb (gpointer user_data)
static void
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:
- break;
+ case FP_DEVICE_TASK_RETURN_INT:
+ case FP_DEVICE_TASK_RETURN_BOOL:
+ break;
- case FP_DEVICE_TASK_RETURN_OBJECT:
- g_clear_object ((GObject **) &data->result);
- break;
+ case FP_DEVICE_TASK_RETURN_OBJECT:
+ g_clear_object ((GObject **) &data->result);
+ break;
- case FP_DEVICE_TASK_RETURN_PTR_ARRAY:
- g_clear_pointer ((GPtrArray **) &data->result, g_ptr_array_unref);
- break;
+ case FP_DEVICE_TASK_RETURN_PTR_ARRAY:
+ g_clear_pointer ((GPtrArray **) &data->result, g_ptr_array_unref);
+ break;
- case FP_DEVICE_TASK_RETURN_ERROR:
- g_clear_error ((GError **) &data->result);
- break;
+ case FP_DEVICE_TASK_RETURN_ERROR:
+ g_clear_error ((GError **) &data->result);
+ break;
- default:
- g_assert_not_reached ();
- }
+ default:
+ g_assert_not_reached ();
}
+
g_object_unref (data->device);
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
fpi_device_return_task_in_idle (FpDevice *device,
FpDeviceTaskReturnType return_type,
@@ -1101,7 +1112,7 @@ fpi_device_return_task_in_idle (FpDevice *device,
* @device: The #FpDevice
* @device_id: Unique ID for the device or %NULL
* @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.
*/
@@ -1147,7 +1158,7 @@ fpi_device_probe_complete (FpDevice *device,
/**
* fpi_device_open_complete:
* @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.
*/
@@ -1174,7 +1185,7 @@ fpi_device_open_complete (FpDevice *device, GError *error)
/**
* fpi_device_close_complete:
* @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.
*/
@@ -1226,7 +1237,7 @@ fpi_device_close_complete (FpDevice *device, GError *error)
* fpi_device_enroll_complete:
* @device: The #FpDevice
* @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
* caller for later verification.
@@ -1355,7 +1366,7 @@ fpi_device_verify_complete (FpDevice *device,
/**
* fpi_device_identify_complete:
* @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.
*
@@ -1421,7 +1432,7 @@ fpi_device_identify_complete (FpDevice *device,
* fpi_device_capture_complete:
* @device: The #FpDevice
* @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.
*/
@@ -1468,7 +1479,7 @@ fpi_device_capture_complete (FpDevice *device,
/**
* fpi_device_delete_complete:
* @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.
*/
@@ -1497,7 +1508,7 @@ fpi_device_delete_complete (FpDevice *device,
* fpi_device_list_complete:
* @device: The #FpDevice
* @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.
*
@@ -1775,7 +1786,7 @@ fpi_device_suspend_completed (FpDevice *device)
/**
* fpi_device_suspend_complete:
* @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
* correctly configured and the current action as returned by
@@ -1826,7 +1837,7 @@ fpi_device_suspend_complete (FpDevice *device,
/**
* fpi_device_resume_complete:
* @device: The #FpDevice
- * @error: The #GError or %NULL on success
+ * @error: (nullable) (transfer full): The #GError or %NULL on success
*
* Finish a resume request.
*/
@@ -1854,7 +1865,7 @@ fpi_device_resume_complete (FpDevice *device,
/**
* fpi_device_clear_storage_complete:
* @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.
*/
@@ -1885,7 +1896,7 @@ fpi_device_clear_storage_complete (FpDevice *device,
* @device: The #FpDevice
* @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
- * @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.
* The passed error may be used if a scan needs to be retried, use fpi_device_retry_new().
diff --git a/libfprint/fpi-image-device.c b/libfprint/fpi-image-device.c
index 64ea340..8184d3a 100644
--- a/libfprint/fpi-image-device.c
+++ b/libfprint/fpi-image-device.c
@@ -565,7 +565,7 @@ fpi_image_device_retry_scan (FpImageDevice *self, FpDeviceRetry retry)
/**
* fpi_image_device_session_error:
* @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
* 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:
* @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.
*/
@@ -663,7 +663,7 @@ fpi_image_device_activate_complete (FpImageDevice *self, GError *error)
/**
* fpi_image_device_deactivate_complete:
* @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.
*/
@@ -690,7 +690,7 @@ fpi_image_device_deactivate_complete (FpImageDevice *self, GError *error)
/**
* fpi_image_device_open_complete:
* @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.
*/
@@ -718,7 +718,7 @@ fpi_image_device_open_complete (FpImageDevice *self, GError *error)
/**
* fpi_image_device_close_complete:
* @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.
*/
diff --git a/libfprint/fpi-log.h b/libfprint/fpi-log.h
index 3231cf5..cd8f1bd 100644
--- a/libfprint/fpi-log.h
+++ b/libfprint/fpi-log.h
@@ -79,13 +79,16 @@
*
* Uses fp_err() to print an error if the @condition is true.
*/
-#define BUG_ON(condition) G_STMT_START \
- if (condition) { \
- char *s; \
- s = g_strconcat ("BUG: (", #condition, ")", NULL); \
- fp_err ("%s: %s() %s:%d", s, G_STRFUNC, __FILE__, __LINE__); \
- g_free (s); \
- } G_STMT_END
+#define BUG_ON(condition) \
+ G_STMT_START \
+ if (condition) \
+ { \
+ char *s; \
+ s = g_strconcat ("BUG: (", #condition, ")", NULL); \
+ fp_err ("%s: %s() %s:%d", s, G_STRFUNC, __FILE__, __LINE__); \
+ g_free (s); \
+ } \
+ G_STMT_END
/**
* BUG:
diff --git a/libfprint/fpi-ssm.h b/libfprint/fpi-ssm.h
index ab80a26..d2601c8 100644
--- a/libfprint/fpi-ssm.h
+++ b/libfprint/fpi-ssm.h
@@ -60,7 +60,7 @@ typedef void (*FpiSsmHandlerCallback)(FpiSsm *ssm,
/* for library and drivers */
#define fpi_ssm_new(dev, handler, nr_states) \
- fpi_ssm_new_full (dev, handler, nr_states, nr_states, #nr_states)
+ fpi_ssm_new_full (dev, handler, nr_states, nr_states, #nr_states)
FpiSsm *fpi_ssm_new_full (FpDevice *dev,
FpiSsmHandlerCallback handler,
int nr_states,
diff --git a/libfprint/fprint-list-metainfo.c b/libfprint/fprint-list-metainfo.c
new file mode 100644
index 0000000..4faf7bd
--- /dev/null
+++ b/libfprint/fprint-list-metainfo.c
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2025 Marco Trevisan
+ *
+ * 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 \
+ "\n" \
+ "\n" \
+ " org.freedesktop.libfprint\n" \
+ " libfprint\n" \
+ " CC0-1.0\n" \
+ " LGPL-2.1-or-later\n" \
+ " https://fprint.freedesktop.org\n" \
+ " https://gitlab.freedesktop.org/libfprint/libfprint\n" \
+ " https://fprint.freedesktop.org/libfprint-dev\n" \
+ " https://gitlab.freedesktop.org/libfprint/libfprint/-/issues\n" \
+ " Async fingerprint readers library\n" \
+ " \n" \
+ " \n" \
+ " The fprint project aims to support for consumer fingerprint reader devices.\n" \
+ "
\n" \
+ " \n" \
+ " \n" \
+ "%s\n" \
+ " \n" \
+ "\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, "usb:%s*",
+ device_id);
+
+ if (i < devices_list->len - 1)
+ g_string_append_c (provided_modules, '\n');
+ }
+
+ g_print (METAINFO_BASE, provided_modules->str);
+}
diff --git a/libfprint/fprint-list-udev-hwdb.c b/libfprint/fprint-list-udev-hwdb.c
index bace9f9..5cb8d68 100644
--- a/libfprint/fprint-list-udev-hwdb.c
+++ b/libfprint/fprint-list-udev-hwdb.c
@@ -29,7 +29,10 @@ static const FpIdEntry allowlist_id_table[] = {
* 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'
*/
+ { .vid = 0x0a5c, .pid = 0x5802 },
{ .vid = 0x047d, .pid = 0x00f2 },
+ { .vid = 0x047d, .pid = 0x8054 },
+ { .vid = 0x047d, .pid = 0x8055 },
{ .vid = 0x04e8, .pid = 0x730b },
{ .vid = 0x04f3, .pid = 0x036b },
{ .vid = 0x04f3, .pid = 0x0c00 },
@@ -37,16 +40,25 @@ static const FpIdEntry allowlist_id_table[] = {
{ .vid = 0x04f3, .pid = 0x0c57 },
{ .vid = 0x04f3, .pid = 0x0c5e },
{ .vid = 0x04f3, .pid = 0x0c5a },
+ { .vid = 0x04f3, .pid = 0x0c60 },
{ .vid = 0x04f3, .pid = 0x0c6c },
{ .vid = 0x04f3, .pid = 0x0c70 },
{ .vid = 0x04f3, .pid = 0x0c72 },
{ .vid = 0x04f3, .pid = 0x0c77 },
+ { .vid = 0x04f3, .pid = 0x0c7c },
+ { .vid = 0x04f3, .pid = 0x0c7f },
+ { .vid = 0x04f3, .pid = 0x0c80 },
+ { .vid = 0x04f3, .pid = 0x0c85 },
+ { .vid = 0x04f3, .pid = 0x0c90 },
{ .vid = 0x04f3, .pid = 0x2706 },
{ .vid = 0x04f3, .pid = 0x3032 },
{ .vid = 0x04f3, .pid = 0x3057 },
{ .vid = 0x04f3, .pid = 0x3104 },
{ .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 = 0x0088 },
{ .vid = 0x06cb, .pid = 0x008a },
@@ -57,7 +69,6 @@ static const FpIdEntry allowlist_id_table[] = {
{ .vid = 0x06cb, .pid = 0x00b7 },
{ .vid = 0x06cb, .pid = 0x00bb },
{ .vid = 0x06cb, .pid = 0x00be },
- { .vid = 0x06cb, .pid = 0x00c4 },
{ .vid = 0x06cb, .pid = 0x00cb },
{ .vid = 0x06cb, .pid = 0x00c9 },
{ .vid = 0x06cb, .pid = 0x00d8 },
@@ -67,6 +78,7 @@ static const FpIdEntry allowlist_id_table[] = {
{ .vid = 0x06cb, .pid = 0x00e7 },
{ .vid = 0x06cb, .pid = 0x00e9 },
{ .vid = 0x06cb, .pid = 0x00fd },
+ { .vid = 0x06cb, .pid = 0x00ff },
{ .vid = 0x0a5c, .pid = 0x5801 },
{ .vid = 0x0a5c, .pid = 0x5805 },
{ .vid = 0x0a5c, .pid = 0x5834 },
@@ -76,10 +88,18 @@ static const FpIdEntry allowlist_id_table[] = {
{ .vid = 0x0a5c, .pid = 0x5843 },
{ .vid = 0x0a5c, .pid = 0x5844 },
{ .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 = 0x10a5, .pid = 0x0007 },
{ .vid = 0x10a5, .pid = 0x9200 },
{ .vid = 0x10a5, .pid = 0x9800 },
+ { .vid = 0x10a5, .pid = 0xa120 },
+ { .vid = 0x10a5, .pid = 0xa900 },
{ .vid = 0x10a5, .pid = 0xe340 },
{ .vid = 0x1188, .pid = 0x9545 },
{ .vid = 0x138a, .pid = 0x0007 },
@@ -100,7 +120,11 @@ static const FpIdEntry allowlist_id_table[] = {
{ .vid = 0x1c7a, .pid = 0x0300 },
{ .vid = 0x1c7a, .pid = 0x0575 },
{ .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 = 0x5110 },
{ .vid = 0x27c6, .pid = 0x5117 },
@@ -129,11 +153,17 @@ static const FpIdEntry allowlist_id_table[] = {
{ .vid = 0x27c6, .pid = 0x5e0a },
{ .vid = 0x27c6, .pid = 0x581a },
{ .vid = 0x27c6, .pid = 0x589a },
+ { .vid = 0x27c6, .pid = 0x5f10 },
{ .vid = 0x27c6, .pid = 0x6382 },
{ .vid = 0x2808, .pid = 0x9338 },
+ { .vid = 0x2808, .pid = 0x9348 },
{ .vid = 0x2808, .pid = 0x93a9 },
+ { .vid = 0x2808, .pid = 0xa658 },
+ { .vid = 0x2808, .pid = 0xc652 },
{ .vid = 0x298d, .pid = 0x2020 },
{ .vid = 0x298d, .pid = 0x2033 },
+ { .vid = 0x2df0, .pid = 0x0003 },
+ { .vid = 0x3274, .pid = 0x8012 },
{ .vid = 0x3538, .pid = 0x0930 },
{ .vid = 0 },
};
diff --git a/libfprint/meson.build b/libfprint/meson.build
index 8eed4dd..0ca1767 100644
--- a/libfprint/meson.build
+++ b/libfprint/meson.build
@@ -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 = [
'fp-context.c',
'fp-device.c',
@@ -16,8 +24,7 @@ libfprint_private_sources = [
'fpi-print.c',
'fpi-ssm.c',
'fpi-usb-transfer.c',
- 'fpi-spi-transfer.c',
-]
+] + spi_sources
libfprint_public_headers = [
'fp-context.h',
@@ -41,9 +48,8 @@ libfprint_private_headers = [
'fpi-minutiae.h',
'fpi-print.h',
'fpi-usb-transfer.h',
- 'fpi-spi-transfer.h',
'fpi-ssm.h',
-]
+] + spi_headers
nbis_sources = [
'nbis/bozorth3/bozorth3.c',
@@ -156,7 +162,7 @@ helper_sources = {
[ 'drivers/aesx660.c' ],
'aes3k' :
[ 'drivers/aes3k.c' ],
- 'nss' :
+ 'openssl' :
[ ],
'udev' :
[ ],
@@ -268,8 +274,13 @@ libfprint_drivers = static_library('fprint-drivers',
link_with: libfprint_private,
install: false)
-mapfile = files('libfprint.ver')
-vflag = '-Wl,--version-script,@0@/@1@'.format(meson.project_source_root(), mapfile[0])
+mapfile = files('libfprint.ver')[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],
sources: [
@@ -321,6 +332,21 @@ udev_hwdb_generator = custom_target('udev-hwdb',
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
udev_rules = executable('fprint-list-udev-rules',
'fprint-list-udev-rules.c',
diff --git a/meson.build b/meson.build
index 435827c..baafa19 100644
--- a/meson.build
+++ b/meson.build
@@ -1,13 +1,14 @@
project('libfprint', [ 'c', 'cpp' ],
- version: '1.94.7',
+ version: '1.94.9',
license: 'LGPLv2.1+',
default_options: [
'buildtype=debugoptimized',
'warning_level=1',
'c_std=gnu99',
],
- meson_version: '>= 0.56.0')
+ meson_version: '>= 0.59.0')
+fs = import('fs')
gnome = import('gnome')
libfprint_conf = configuration_data()
@@ -21,12 +22,17 @@ datadir = prefix / get_option('datadir')
cc = meson.get_compiler('c')
cpp = meson.get_compiler('cpp')
host_system = host_machine.system()
+
+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_min_version.split('.')[0], glib_min_version.split('.')[1])
common_cflags = cc.get_supported_arguments([
- '-Wall',
'-Wcast-align',
'-Wformat-nonliteral',
'-Wformat-security',
@@ -91,11 +97,15 @@ gusb_dep = dependency('gusb', version: '>= 0.2.0')
mathlib_dep = cc.find_library('m', required: false)
# The following dependencies are only used for tests
+sh = find_program('sh', required: true)
cairo_dep = dependency('cairo', required: false)
# introspection scanning and Gio-2.0.gir
gobject_introspection = dependency('gobject-introspection-1.0', required: get_option('introspection'))
+# SPI
+have_spi = host_machine.system() == 'linux'
+
# Drivers
drivers = get_option('drivers').split(',')
virtual_drivers = [
@@ -134,11 +144,16 @@ default_drivers = [
'fpcmoc',
'realtek',
'focaltech_moc',
+]
- # SPI
- 'elanspi',
+spi_drivers = [
+ 'elanspi'
]
+if have_spi
+ default_drivers += spi_drivers
+endif
+
# FIXME: All the drivers should be fixed by adjusting the byte order.
# See https://gitlab.freedesktop.org/libfprint/libfprint/-/issues/236
endian_independent_drivers = virtual_drivers + [
@@ -175,6 +190,17 @@ if drivers == [ 'default' ]
drivers = default_drivers
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 = {
'aes1610' : [ 'aeslib' ],
'aes1660' : [ 'aeslib', 'aesx660' ],
@@ -183,7 +209,7 @@ driver_helper_mapping = {
'aes2660' : [ 'aeslib', 'aesx660' ],
'aes3500' : [ 'aeslib', 'aes3k' ],
'aes4000' : [ 'aeslib', 'aes3k' ],
- 'uru4000' : [ 'nss' ],
+ 'uru4000' : [ 'openssl' ],
'elanspi' : [ 'udev' ],
'virtual_image' : [ 'virtual' ],
'virtual_device' : [ 'virtual' ],
@@ -240,13 +266,13 @@ foreach i : driver_helpers
libfprint_conf.set10('HAVE_PIXMAN', true)
optional_deps += imaging_dep
- elif i == 'nss'
- nss_dep = dependency('nss', required: false)
- if not nss_dep.found()
- error('nss is required for @0@ and possibly others'.format(driver))
+ elif i == 'openssl'
+ openssl_dep = dependency('openssl', version: '>= 3.0', required: false)
+ if not openssl_dep.found()
+ error('OpenSSL is required for @0@ and possibly others'.format(driver))
endif
- optional_deps += nss_dep
+ optional_deps += openssl_dep
elif i == 'udev'
install_udev_rules = true
diff --git a/scripts/uncrustify.cfg b/scripts/uncrustify.cfg
index 34b9a35..705a097 100644
--- a/scripts/uncrustify.cfg
+++ b/scripts/uncrustify.cfg
@@ -19,6 +19,7 @@ indent_func_proto_param false
indent_switch_case 0
indent_case_brace 2
indent_paren_close 1
+pp_multiline_define_body_indent 2
# spacing
sp_arith Add
@@ -114,6 +115,7 @@ nl_create_for_one_liner False
nl_create_while_one_liner False
nl_after_semicolon True
nl_multi_line_cond true
+nl_multi_line_define true
# mod
# I'd like these to be remove, but that removes brackets in if { if { foo } }, which i dislike
diff --git a/tests/egismoc-0586/custom.pcapng b/tests/egismoc-0586/custom.pcapng
new file mode 100644
index 0000000..f43dc6f
Binary files /dev/null and b/tests/egismoc-0586/custom.pcapng differ
diff --git a/tests/egismoc-0586/custom.py b/tests/egismoc-0586/custom.py
new file mode 100755
index 0000000..3a66238
--- /dev/null
+++ b/tests/egismoc-0586/custom.py
@@ -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
diff --git a/tests/egismoc-0586/device b/tests/egismoc-0586/device
new file mode 100644
index 0000000..fb41aee
--- /dev/null
+++ b/tests/egismoc-0586/device
@@ -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
diff --git a/tests/egismoc-0587/custom.pcapng b/tests/egismoc-0587/custom.pcapng
new file mode 100644
index 0000000..c721929
Binary files /dev/null and b/tests/egismoc-0587/custom.pcapng differ
diff --git a/tests/egismoc-0587/custom.py b/tests/egismoc-0587/custom.py
new file mode 100755
index 0000000..3a66238
--- /dev/null
+++ b/tests/egismoc-0587/custom.py
@@ -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
diff --git a/tests/egismoc-0587/device b/tests/egismoc-0587/device
new file mode 100644
index 0000000..91744df
--- /dev/null
+++ b/tests/egismoc-0587/device
@@ -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
+
diff --git a/tests/goodixmoc/custom.py b/tests/goodixmoc/custom.py
index aee4391..91922f1 100755
--- a/tests/goodixmoc/custom.py
+++ b/tests/goodixmoc/custom.py
@@ -53,17 +53,20 @@ def identify_done(dev, res):
p = d.enroll_sync(template, None, enroll_progress, None)
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
print("enroll done")
+assert p.get_description() == 'FP1-00000000-0-00000000-nobody'
print("listing")
stored = d.list_prints_sync()
print("listing done")
assert len(stored) == 1
assert stored[0].equal(p)
+assert stored[0].get_description() == 'FP1-00000000-0-00000000-nobody'
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")
+assert verify_print.get_description() == 'FP1-00000000-0-00000000-nobody'
del p
assert verify_res == True
diff --git a/tests/libfprint.supp b/tests/libfprint.supp
index f2acc71..274d740 100644
--- a/tests/libfprint.supp
+++ b/tests/libfprint.supp
@@ -24,3 +24,12 @@
...
fun:g_thread_new
}
+
+{
+
+ Memcheck:Leak
+ match-leak-kinds: possible
+ fun:calloc
+ ...
+ fun:libusb_init_context
+}
diff --git a/tests/meson.build b/tests/meson.build
index f68ed40..07c924b 100644
--- a/tests/meson.build
+++ b/tests/meson.build
@@ -53,8 +53,11 @@ drivers_tests = [
'egis0570',
'egismoc',
'egismoc-05a1',
+ 'egismoc-0586',
+ 'egismoc-0587',
'fpcmoc',
- 'realtek',
+ 'realtek',
+ 'realtek-5816',
'focaltech_moc',
]
@@ -100,11 +103,17 @@ if get_option('introspection')
base_args = files(vdtest + '.py')
suite = ['virtual-driver']
- r = run_command(unittest_inspector, files(vdtest + '.py'), check: true)
+ r = run_command(unittest_inspector, files(vdtest + '.py'), check: false)
unit_tests = r.stdout().strip().split('\n')
if r.returncode() == 0 and unit_tests.length() > 0
suite += vdtest
+ elif r.returncode() == 77
+ test(vdtest,
+ sh,
+ args: ['-c', 'exit 77']
+ )
+ continue
else
unit_tests = [vdtest]
endif
@@ -136,8 +145,7 @@ if get_option('introspection')
output: vdtest + '.test',
install_dir: installed_tests_testdir,
configuration: {
- # FIXME: use fs.name() on meson 0.58
- 'exec': installed_tests_execdir / '@0@'.format(base_args[0]).split('/')[-1],
+ 'exec': installed_tests_execdir / fs.name(base_args[0]),
'env': ' '.join([
envs_str,
'LD_LIBRARY_PATH=' + installed_tests_libdir,
@@ -151,7 +159,7 @@ if get_option('introspection')
endif
else
test(vdtest,
- find_program('sh'),
+ sh,
args: ['-c', 'exit 77']
)
endif
@@ -205,7 +213,7 @@ if get_option('introspection')
endif
else
test(driver_test,
- find_program('sh'),
+ sh,
args: ['-c', 'exit 77']
)
endif
@@ -224,13 +232,13 @@ if get_option('introspection')
else
warning('Skipping all driver tests as introspection bindings are missing')
test('virtual-image',
- find_program('sh'),
+ sh,
args: ['-c', 'exit 77']
)
foreach driver_test: drivers_tests
test(driver_test,
- find_program('sh'),
+ sh,
args: ['-c', 'exit 77']
)
endforeach
@@ -273,7 +281,7 @@ foreach test_name: unit_tests
# Create a dummy test that always skips instead
warning('Test @0@ cannot be compiled due to missing dependencies'.format(test_name))
test(test_name,
- find_program('sh'),
+ sh,
suite: ['unit-tests'],
args: ['-c', 'exit 77'],
)
@@ -316,13 +324,25 @@ endforeach
# Run udev rule generator with fatal warnings
envs.set('UDEV_HWDB', udev_hwdb.full_path())
envs.set('UDEV_HWDB_CHECK_CONTENTS', default_drivers_are_enabled ? '1' : '0')
+envs.set('G_MESSAGES_DEBUG', '')
test('udev-hwdb',
find_program('test-generated-hwdb.sh'),
depends: udev_hwdb,
+ suite: ['data', 'no-valgrind'],
env: envs)
+appstreamcli = find_program('appstreamcli', required: false)
+if appstreamcli.found()
+ test('metainfo-validate',
+ appstreamcli,
+ args: ['validate', metainfo_generator],
+ depends: metainfo_generator,
+ suite: ['data', 'no-valgrind'],
+ )
+endif
+
gdb = find_program('gdb', required: false)
-if gdb.found()
+if gdb.found() and libfprint_sanitizers.length() == 0
libfprint_wrapper = [
gdb.full_path(),
'-batch',
@@ -337,14 +357,32 @@ if gdb.found()
])
endif
+if ('address' in libfprint_sanitizers or
+ 'undefined' in libfprint_sanitizers or
+ 'leak' in libfprint_sanitizers)
+ add_test_setup('sanitizers',
+ is_default: true,
+ timeout_multiplier: 3,
+ env: [
+ 'ASAN_OPTIONS=verify_asan_link_order=0',
+ ])
+endif
+
valgrind = find_program('valgrind', required: false)
-if valgrind.found()
+if valgrind.found() and libfprint_sanitizers.length() == 0
glib_share = glib_dep.get_variable(pkgconfig: 'prefix') / 'share' / glib_dep.name()
glib_suppressions = glib_share + '/valgrind/glib.supp'
- libfprint_suppressions = '@0@/@1@'.format(meson.project_source_root(),
- files('libfprint.supp')[0])
- python_suppressions = '@0@/@1@'.format(meson.project_source_root(),
- files('valgrind-python.supp')[0])
+ libfprint_suppressions = files('libfprint.supp')[0]
+ python_suppressions = files('valgrind-python.supp')[0]
+
+ if meson.version().version_compare('>=1.4')
+ libfprint_suppressions = libfprint_suppressions.full_path()
+ python_suppressions = python_suppressions.full_path()
+ else
+ libfprint_suppressions = meson.project_source_root() / '@0@'.format(libfprint_suppressions)
+ python_suppressions = meson.project_source_root() / '@0@'.format(python_suppressions)
+ endif
+
libfprint_wrapper = [
valgrind.full_path(),
'--tool=memcheck',
@@ -361,11 +399,14 @@ if valgrind.found()
'--suppressions=' + python_suppressions,
]
add_test_setup('valgrind',
- timeout_multiplier: 15,
+ timeout_multiplier: 20,
exe_wrapper: libfprint_wrapper,
+ exclude_suites: ['no-valgrind'],
env: [
'G_SLICE=always-malloc',
'UNDER_VALGRIND=1',
+ 'FP_VIRTUAL_IMAGE_HOT_SECONDS=-1',
+ 'FP_VIRTUAL_DEVICE_HOT_SECONDS=-1',
'LIBFPRINT_TEST_WRAPPER=' + ' '.join(libfprint_wrapper),
])
endif
diff --git a/tests/realtek-5816/custom.pcapng b/tests/realtek-5816/custom.pcapng
new file mode 100644
index 0000000..579bac6
Binary files /dev/null and b/tests/realtek-5816/custom.pcapng differ
diff --git a/tests/realtek-5816/custom.py b/tests/realtek-5816/custom.py
new file mode 100755
index 0000000..15a71e2
--- /dev/null
+++ b/tests/realtek-5816/custom.py
@@ -0,0 +1,110 @@
+#!/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() == "realtek"
+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 d.has_feature(FPrint.DeviceFeature.STORAGE_CLEAR)
+
+d.open_sync()
+
+# 1. verify clear storage command, 2. make sure later asserts are good
+d.clear_storage_sync()
+
+template = FPrint.Print.new(d)
+
+def enroll_progress(*args):
+ # assert d.get_finger_status() & FPrint.FingerStatusFlags.NEEDED
+ print('enroll progress: ' + str(args))
+
+def identify_done(dev, res):
+ global identified
+ identified = True
+ try:
+ identify_match, identify_print = dev.identify_finish(res)
+ except gi.repository.GLib.GError as e:
+ print("Please try again")
+ else:
+ print('indentification_done: ', identify_match, identify_print)
+ assert identify_match.equal(identify_print)
+
+def start_identify_async(prints):
+ global identified
+ print('async identifying')
+ d.identify(prints, callback=identify_done)
+ del prints
+
+ while not identified:
+ ctx.iteration(True)
+
+ identified = False
+
+# 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")
+try:
+ assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
+ verify_res, verify_print = d.verify_sync(p)
+ assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
+except gi.repository.GLib.GError as e:
+ print("Please try again")
+else:
+ 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
diff --git a/tests/realtek-5816/device b/tests/realtek-5816/device
new file mode 100644
index 0000000..55f6f98
--- /dev/null
+++ b/tests/realtek-5816/device
@@ -0,0 +1,250 @@
+P: /devices/pci0000:00/0000:00:14.0/usb1/1-6
+N: bus/usb/001/006=12010102EF020140DA0B165800000301020109022E00010104A0FA0904000004FF02000507050102000200070583034000080705840340000807058202000200
+E: DEVNAME=/dev/bus/usb/001/006
+E: DEVTYPE=usb_device
+E: DRIVER=usb
+E: PRODUCT=bda/5816/0
+E: TYPE=239/2/1
+E: BUSNUM=001
+E: DEVNUM=006
+E: MAJOR=189
+E: MINOR=5
+E: SUBSYSTEM=usb
+E: ID_VENDOR=Generic
+E: ID_VENDOR_ENC=Generic
+E: ID_VENDOR_ID=0bda
+E: ID_MODEL=Realtek_USB2.0_Finger_Print_Bridge
+E: ID_MODEL_ENC=Realtek\x20USB2.0\x20Finger\x20Print\x20Bridge
+E: ID_MODEL_ID=5816
+E: ID_REVISION=0000
+E: ID_SERIAL=Generic_Realtek_USB2.0_Finger_Print_Bridge_201801010001
+E: ID_SERIAL_SHORT=201801010001
+E: ID_BUS=usb
+E: ID_USB_INTERFACES=:ff0200:
+E: ID_VENDOR_FROM_DATABASE=Realtek Semiconductor Corp.
+E: ID_PATH=pci-0000:00:14.0-usb-0:6
+E: ID_PATH_TAG=pci-0000_00_14_0-usb-0_6
+A: authorized=1\n
+A: avoid_reset_quirk=0\n
+A: bConfigurationValue=1\n
+A: bDeviceClass=ef\n
+A: bDeviceProtocol=01\n
+A: bDeviceSubClass=02\n
+A: bMaxPacketSize0=64\n
+A: bMaxPower=500mA\n
+A: bNumConfigurations=1\n
+A: bNumInterfaces= 1\n
+A: bcdDevice=0000\n
+A: bmAttributes=a0\n
+A: busnum=1\n
+A: configuration=Realtek USB2.0 Finger Print Bridge\n
+H: descriptors=12010102EF020140DA0B165800000301020109022E00010104A0FA0904000004FF02000507050102000200070583034000080705840340000807058202000200
+A: dev=189:5\n
+A: devnum=6\n
+A: devpath=6\n
+L: driver=../../../../../bus/usb/drivers/usb
+L: firmware_node=../../../../LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:4b/device:4c/device:52
+A: idProduct=5816\n
+A: idVendor=0bda\n
+A: ltm_capable=no\n
+A: manufacturer=Generic\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=../1-0:1.0/usb1-port6
+A: power/active_duration=37699\n
+A: power/async=enabled\n
+A: power/autosuspend=2\n
+A: power/autosuspend_delay_ms=2000\n
+A: power/connected_duration=37699\n
+A: power/control=on\n
+A: power/level=on\n
+A: power/persist=1\n
+A: power/runtime_active_kids=0\n
+A: power/runtime_active_time=37457\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=Realtek USB2.0 Finger Print Bridge\n
+A: quirks=0x0\n
+A: removable=removable\n
+A: rx_lanes=1\n
+A: serial=201801010001\n
+A: speed=480\n
+A: tx_lanes=1\n
+A: urbnum=22\n
+A: version= 2.01\n
+
+P: /devices/pci0000:00/0000:00:14.0/usb1
+N: bus/usb/001/001=12010002090001406B1D020008060302010109021900010100E0000904000001090000000705810304000C
+E: DEVNAME=/dev/bus/usb/001/001
+E: DEVTYPE=usb_device
+E: DRIVER=usb
+E: PRODUCT=1d6b/2/608
+E: TYPE=9/0/1
+E: BUSNUM=001
+E: DEVNUM=001
+E: MAJOR=189
+E: MINOR=0
+E: SUBSYSTEM=usb
+E: ID_VENDOR=Linux_6.8.0-40-generic_xhci-hcd
+E: ID_VENDOR_ENC=Linux\x206.8.0-40-generic\x20xhci-hcd
+E: ID_VENDOR_ID=1d6b
+E: ID_MODEL=xHCI_Host_Controller
+E: ID_MODEL_ENC=xHCI\x20Host\x20Controller
+E: ID_MODEL_ID=0002
+E: ID_REVISION=0608
+E: ID_SERIAL=Linux_6.8.0-40-generic_xhci-hcd_xHCI_Host_Controller_0000:00:14.0
+E: ID_SERIAL_SHORT=0000:00:14.0
+E: ID_BUS=usb
+E: ID_USB_INTERFACES=:090000:
+E: ID_VENDOR_FROM_DATABASE=Linux Foundation
+E: ID_AUTOSUSPEND=1
+E: ID_MODEL_FROM_DATABASE=2.0 root hub
+E: ID_PATH=pci-0000:00:14.0
+E: ID_PATH_TAG=pci-0000_00_14_0
+E: ID_FOR_SEAT=usb-pci-0000_00_14_0
+E: TAGS=:seat:
+E: CURRENT_TAGS=:seat:
+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:4b/device:4c
+A: idProduct=0002\n
+A: idVendor=1d6b\n
+A: interface_authorized_default=1\n
+A: ltm_capable=no\n
+A: manufacturer=Linux 6.8.0-40-generic xhci-hcd\n
+A: maxchild=16\n
+A: power/active_duration=1096259\n
+A: power/async=enabled\n
+A: power/autosuspend=0\n
+A: power/autosuspend_delay_ms=0\n
+A: power/connected_duration=1096259\n
+A: power/control=auto\n
+A: power/level=auto\n
+A: power/runtime_active_kids=3\n
+A: power/runtime_active_time=1096256\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=229\n
+A: version= 2.00\n
+
+P: /devices/pci0000:00/0000:00:14.0
+E: DRIVER=xhci_hcd
+E: PCI_CLASS=C0330
+E: PCI_ID=8086:A36D
+E: PCI_SUBSYS_ID=1028:085C
+E: PCI_SLOT_NAME=0000:00:14.0
+E: MODALIAS=pci:v00008086d0000A36Dsv00001028sd0000085Cbc0Csc03i30
+E: SUBSYSTEM=pci
+E: ID_PCI_CLASS_FROM_DATABASE=Serial bus controller
+E: ID_PCI_SUBCLASS_FROM_DATABASE=USB controller
+E: ID_PCI_INTERFACE_FROM_DATABASE=XHCI
+E: ID_VENDOR_FROM_DATABASE=Intel Corporation
+E: ID_MODEL_FROM_DATABASE=Cannon Lake PCH USB 3.1 xHCI Host Controller
+A: ari_enabled=0\n
+A: broken_parity_status=0\n
+A: class=0x0c0330\n
+H: config=86806DA3060590021030030C00008000040030D200000000000000000000000000000000000000000000000028105C08000000007000000000000000FF010000FD0134808FC6FF8300000000000000007F6DDC0F000000005B17C10300000000316000000000000000000000000000000180C2C10800000000000000000000000590B7001803E0FE0000000000000000090014F01000400100000000C10A080000080E00001800008F40020000010000030000000C00000000000000C000000000000000000100003000000000000000030000000C0000000000000000000000000000000000000000000000000000000000000000000000B50F120112000000
+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=0xa36d\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:4b
+A: index=4\n
+L: iommu=../../virtual/iommu/dmar1
+L: iommu_group=../../../kernel/iommu_groups/4
+A: irq=125\n
+A: label=Onboard - Other\n
+A: local_cpulist=0-3\n
+A: local_cpus=f\n
+A: modalias=pci:v00008086d0000A36Dsv00001028sd0000085Cbc0Csc03i30\n
+A: msi_bus=1\n
+A: msi_irqs/125=msi\n
+A: msi_irqs/126=msi\n
+A: msi_irqs/127=msi\n
+A: msi_irqs/128=msi\n
+A: msi_irqs/129=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 25 25 4096 25\nbuffer-2048 0 0 2048 0\nbuffer-512 0 0 512 0\nbuffer-128 12 32 128 1\nbuffer-32 0 0 32 0\n
+A: power/async=enabled\n
+A: power/control=on\n
+A: power/runtime_active_kids=1\n
+A: power/runtime_active_time=1096935\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=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=0x00000000d2300000 0x00000000d230ffff 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=0x10\n
+A: subsystem_device=0x085c\n
+A: subsystem_vendor=0x1028\n
+A: vendor=0x8086\n
+
diff --git a/tests/realtek/custom.pcapng b/tests/realtek/custom.pcapng
index 0fe6dc7..84b1599 100644
Binary files a/tests/realtek/custom.pcapng and b/tests/realtek/custom.pcapng differ
diff --git a/tests/realtek/device b/tests/realtek/device
index c4f1c85..500f62d 100644
--- a/tests/realtek/device
+++ b/tests/realtek/device
@@ -1,14 +1,14 @@
-P: /devices/pci0000:00/0000:00:14.0/usb1/1-4
-N: bus/usb/001/005=12010102EF020140DA0B135801210301020109022E00010104A0FA0904000004FF02000507050102000200070583031000080705840310000807058202000200
-E: DEVNAME=/dev/bus/usb/001/005
+P: /devices/pci0000:00/0000:00:14.0/usb1/1-8
+N: bus/usb/001/025=12010102EF020140DA0B135801210301020109022E00010104A0FA0904000004FF02000507050102000200070583031000080705840310000807058202000200
+E: DEVNAME=/dev/bus/usb/001/025
E: DEVTYPE=usb_device
E: DRIVER=usb
E: PRODUCT=bda/5813/2101
E: TYPE=239/2/1
E: BUSNUM=001
-E: DEVNUM=005
+E: DEVNUM=025
E: MAJOR=189
-E: MINOR=4
+E: MINOR=24
E: SUBSYSTEM=usb
E: ID_VENDOR=Generic
E: ID_VENDOR_ENC=Generic
@@ -22,8 +22,8 @@ E: ID_SERIAL_SHORT=201801010001
E: ID_BUS=usb
E: ID_USB_INTERFACES=:ff0200:
E: ID_VENDOR_FROM_DATABASE=Realtek Semiconductor Corp.
-E: ID_PATH=pci-0000:00:14.0-usb-0:4
-E: ID_PATH_TAG=pci-0000_00_14_0-usb-0_4
+E: ID_PATH=pci-0000:00:14.0-usb-0:8
+E: ID_PATH_TAG=pci-0000_00_14_0-usb-0_8
A: authorized=1\n
A: avoid_reset_quirk=0\n
A: bConfigurationValue=1\n
@@ -39,11 +39,11 @@ A: bmAttributes=a0\n
A: busnum=1\n
A: configuration=Realtek USB2.0 Finger Print Bridge\n
H: descriptors=12010102EF020140DA0B135801210301020109022E00010104A0FA0904000004FF02000507050102000200070583031000080705840310000807058202000200
-A: dev=189:4\n
-A: devnum=5\n
-A: devpath=4\n
+A: dev=189:24\n
+A: devnum=25\n
+A: devpath=8\n
L: driver=../../../../../bus/usb/drivers/usb
-L: firmware_node=../../../../LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:4b/device:4c/device:50
+L: firmware_node=../../../../LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:4b/device:4c/device:54
A: idProduct=5813\n
A: idVendor=0bda\n
A: ltm_capable=no\n
@@ -54,21 +54,21 @@ 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=../1-0:1.0/usb1-port4
-A: power/active_duration=91232868\n
+L: port=../1-0:1.0/usb1-port8
+A: power/active_duration=271844\n
A: power/async=enabled\n
A: power/autosuspend=2\n
A: power/autosuspend_delay_ms=2000\n
-A: power/connected_duration=91232868\n
+A: power/connected_duration=271844\n
A: power/control=on\n
A: power/level=on\n
A: power/persist=1\n
A: power/runtime_active_kids=0\n
-A: power/runtime_active_time=91232594\n
+A: power/runtime_active_time=271564\n
A: power/runtime_enabled=forbidden\n
A: power/runtime_status=active\n
A: power/runtime_suspended_time=0\n
-A: power/runtime_usage=7\n
+A: power/runtime_usage=1\n
A: power/wakeup=disabled\n
A: power/wakeup_abort_count=\n
A: power/wakeup_active=\n
@@ -85,29 +85,29 @@ A: rx_lanes=1\n
A: serial=201801010001\n
A: speed=480\n
A: tx_lanes=1\n
-A: urbnum=15076313\n
+A: urbnum=297176\n
A: version= 2.01\n
P: /devices/pci0000:00/0000:00:14.0/usb1
-N: bus/usb/001/001=12010002090001406B1D020002060302010109021900010100E0000904000001090000000705810304000C
+N: bus/usb/001/001=12010002090001406B1D020005060302010109021900010100E0000904000001090000000705810304000C
E: DEVNAME=/dev/bus/usb/001/001
E: DEVTYPE=usb_device
E: DRIVER=usb
-E: PRODUCT=1d6b/2/602
+E: PRODUCT=1d6b/2/605
E: TYPE=9/0/1
E: BUSNUM=001
E: DEVNUM=001
E: MAJOR=189
E: MINOR=0
E: SUBSYSTEM=usb
-E: ID_VENDOR=Linux_6.2.0-35-generic_xhci-hcd
-E: ID_VENDOR_ENC=Linux\x206.2.0-35-generic\x20xhci-hcd
+E: ID_VENDOR=Linux_6.5.0-18-generic_xhci-hcd
+E: ID_VENDOR_ENC=Linux\x206.5.0-18-generic\x20xhci-hcd
E: ID_VENDOR_ID=1d6b
E: ID_MODEL=xHCI_Host_Controller
E: ID_MODEL_ENC=xHCI\x20Host\x20Controller
E: ID_MODEL_ID=0002
-E: ID_REVISION=0602
-E: ID_SERIAL=Linux_6.2.0-35-generic_xhci-hcd_xHCI_Host_Controller_0000:00:14.0
+E: ID_REVISION=0605
+E: ID_SERIAL=Linux_6.5.0-18-generic_xhci-hcd_xHCI_Host_Controller_0000:00:14.0
E: ID_SERIAL_SHORT=0000:00:14.0
E: ID_BUS=usb
E: ID_USB_INTERFACES=:090000:
@@ -130,11 +130,11 @@ A: bMaxPacketSize0=64\n
A: bMaxPower=0mA\n
A: bNumConfigurations=1\n
A: bNumInterfaces= 1\n
-A: bcdDevice=0602\n
+A: bcdDevice=0605\n
A: bmAttributes=e0\n
A: busnum=1\n
A: configuration=
-H: descriptors=12010002090001406B1D020002060302010109021900010100E0000904000001090000000705810304000C
+H: descriptors=12010002090001406B1D020005060302010109021900010100E0000904000001090000000705810304000C
A: dev=189:0\n
A: devnum=1\n
A: devpath=0\n
@@ -144,17 +144,17 @@ A: idProduct=0002\n
A: idVendor=1d6b\n
A: interface_authorized_default=1\n
A: ltm_capable=no\n
-A: manufacturer=Linux 6.2.0-35-generic xhci-hcd\n
+A: manufacturer=Linux 6.5.0-18-generic xhci-hcd\n
A: maxchild=16\n
-A: power/active_duration=264747968\n
+A: power/active_duration=351477916\n
A: power/async=enabled\n
A: power/autosuspend=0\n
A: power/autosuspend_delay_ms=0\n
-A: power/connected_duration=264747968\n
+A: power/connected_duration=351477916\n
A: power/control=auto\n
A: power/level=auto\n
A: power/runtime_active_kids=3\n
-A: power/runtime_active_time=264747968\n
+A: power/runtime_active_time=351477912\n
A: power/runtime_enabled=enabled\n
A: power/runtime_status=active\n
A: power/runtime_suspended_time=0\n
@@ -175,7 +175,7 @@ A: rx_lanes=1\n
A: serial=0000:00:14.0\n
A: speed=480\n
A: tx_lanes=1\n
-A: urbnum=3177\n
+A: urbnum=2135\n
A: version= 2.00\n
P: /devices/pci0000:00/0000:00:14.0
@@ -194,10 +194,14 @@ E: ID_MODEL_FROM_DATABASE=Cannon Lake PCH USB 3.1 xHCI Host Controller
A: ari_enabled=0\n
A: broken_parity_status=0\n
A: class=0x0c0330\n
-H: config=86806DA3060590021030030C00008000040030D200000000000000000000000000000000000000000000000028105C08000000007000000000000000FF010000FD0134808FC6FF8300000000000000007F6DDC0F000000005919041B00000000316000000000000000000000000000000180C2C108000000000000000000000005908700D802E0FE0000000000000000090014F01000400100000000C10A080000080E00001800008F40020000010000030000000C00000000000000C000000000000000000100003000000000000000030000000C0000000000000000000000000000000000000000000000000000000000000000000000B50F120112000000
+H: config=86806DA3060590021030030C00008000040030D200000000000000000000000000000000000000000000000028105C08000000007000000000000000FF010000FD0134808FC6FF8300000000000000007F6DDC0F000000004505531F00000000316000000000000000000000000000000180C2C108000000000000000000000005908700D802E0FE0000000000000000090014F01000400100000000C10A080000080E00001800008F40020000010000030000000C00000000000000C000000000000000000100003000000000000000030000000C0000000000000000000000000000000000000000000000000000000000000000000000B50F120112000000
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=0xa36d\n
A: dma_mask_bits=64\n
L: driver=../../../bus/pci/drivers/xhci_hcd
@@ -205,19 +209,19 @@ A: driver_override=(null)\n
A: enable=1\n
L: firmware_node=../../LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:4b
A: index=4\n
-A: irq=125\n
+A: irq=126\n
A: label=Onboard - Other\n
A: local_cpulist=0-3\n
A: local_cpus=f\n
A: modalias=pci:v00008086d0000A36Dsv00001028sd0000085Cbc0Csc03i30\n
A: msi_bus=1\n
-A: msi_irqs/125=msi\n
+A: msi_irqs/126=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 24 24 4096 24\nbuffer-2048 0 0 2048 0\nbuffer-512 0 0 512 0\nbuffer-128 12 32 128 1\nbuffer-32 0 0 32 0\n
A: power/async=enabled\n
A: power/control=on\n
A: power/runtime_active_kids=1\n
-A: power/runtime_active_time=264748677\n
+A: power/runtime_active_time=351478612\n
A: power/runtime_enabled=forbidden\n
A: power/runtime_status=active\n
A: power/runtime_suspended_time=0\n
diff --git a/tests/valgrind-python.supp b/tests/valgrind-python.supp
index 59e2185..ff7d779 100644
--- a/tests/valgrind-python.supp
+++ b/tests/valgrind-python.supp
@@ -67,3 +67,31 @@
...
fun:_Py*
}
+
+{
+ ignore__libpython_leaks
+ Memcheck:Leak
+ fun:malloc
+ obj:/usr/lib*/libpython3*.so.*
+}
+
+{
+ ignore__libpython_leaks
+ Memcheck:Leak
+ fun:malloc
+ obj:/usr/lib/*/libpython3*.so.*
+}
+
+{
+ ignore__libpython_leaks
+ Memcheck:Leak
+ fun:realloc
+ obj:/usr/lib*/libpython3*.so.*
+}
+
+{
+ ignore__libpython_leaks
+ Memcheck:Leak
+ fun:realloc
+ obj:/usr/lib/*/libpython3*.so.*
+}
diff --git a/tests/virtual-image.py b/tests/virtual-image.py
index b3dc746..b30d519 100755
--- a/tests/virtual-image.py
+++ b/tests/virtual-image.py
@@ -140,6 +140,24 @@ def send_image(self, image, iterate=True):
while iterate and ctx.pending():
ctx.iteration(False)
+ def wait_for_finger_status(self, finger_status, timeout=5000):
+ done = False
+ def on_timeout_reached():
+ nonlocal done
+ done = True
+
+ if 'UNDER_VALGRIND' in os.environ:
+ timeout = timeout * 3
+
+ source = GLib.timeout_add(timeout, on_timeout_reached)
+ while not done:
+ if self.dev.get_finger_status() & finger_status:
+ GLib.source_remove(source)
+ return
+ ctx.iteration(True)
+
+ self.assertFalse(done)
+
def test_features(self):
self.assertTrue(self.dev.has_feature(FPrint.DeviceFeature.CAPTURE))
self.assertTrue(self.dev.has_feature(FPrint.DeviceFeature.IDENTIFY))
@@ -204,6 +222,7 @@ def done_cb(dev, res):
self.dev.enroll(template, None, progress_cb, tuple(), done_cb)
# Note: Assumes 5 enroll steps for this device!
+ self.wait_for_finger_status(FPrint.FingerStatusFlags.NEEDED)
self.send_image(image)
while self._step < 1:
ctx.iteration(True)
@@ -262,6 +281,7 @@ def verify_cb(dev, res):
self._verify_match = None
self._verify_fp = None
self.dev.verify(fp_whorl, callback=verify_cb)
+ self.wait_for_finger_status(FPrint.FingerStatusFlags.NEEDED)
self.send_image('whorl')
while self._verify_match is None:
ctx.iteration(True)
@@ -271,6 +291,7 @@ def verify_cb(dev, res):
self._verify_match = None
self._verify_fp = None
self.dev.verify(fp_whorl, callback=verify_cb)
+ self.wait_for_finger_status(FPrint.FingerStatusFlags.NEEDED)
self.send_image('tented_arch')
while self._verify_match is None:
ctx.iteration(True)
@@ -284,6 +305,7 @@ def verify_cb(dev, res):
self._verify_match = None
self._verify_fp = None
self.dev.verify(fp_whorl_tended_arch, callback=verify_cb)
+ self.wait_for_finger_status(FPrint.FingerStatusFlags.NEEDED)
self.send_image('whorl')
while self._verify_match is None:
ctx.iteration(True)
@@ -293,6 +315,7 @@ def verify_cb(dev, res):
self._verify_match = None
self._verify_fp = None
self.dev.verify(fp_whorl_tended_arch, callback=verify_cb)
+ self.wait_for_finger_status(FPrint.FingerStatusFlags.NEEDED)
self.send_image('tented_arch')
while self._verify_match is None:
ctx.iteration(True)
@@ -302,6 +325,7 @@ def verify_cb(dev, res):
self._verify_fp = None
self._verify_error = None
self.dev.verify(fp_whorl, callback=verify_cb)
+ self.wait_for_finger_status(FPrint.FingerStatusFlags.NEEDED)
self.send_retry()
while self._verify_fp is None and self._verify_error is None:
ctx.iteration(True)
@@ -311,6 +335,7 @@ def verify_cb(dev, res):
self._verify_fp = None
self._verify_error = None
self.dev.verify(fp_whorl, callback=verify_cb)
+ self.wait_for_finger_status(FPrint.FingerStatusFlags.NEEDED)
self.send_error()
while self._verify_fp is None and self._verify_error is None:
ctx.iteration(True)
@@ -334,6 +359,7 @@ def identify_cb(dev, res):
self._identify_fp = None
self.dev.identify([fp_whorl, fp_tented_arch], callback=identify_cb)
+ self.wait_for_finger_status(FPrint.FingerStatusFlags.NEEDED)
self.send_image('tented_arch')
while self._identify_fp is None:
ctx.iteration(True)
@@ -341,6 +367,7 @@ def identify_cb(dev, res):
self._identify_fp = None
self.dev.identify([fp_whorl, fp_tented_arch], callback=identify_cb)
+ self.wait_for_finger_status(FPrint.FingerStatusFlags.NEEDED)
self.send_image('whorl')
while self._identify_fp is None:
ctx.iteration(True)
@@ -350,6 +377,7 @@ def identify_cb(dev, res):
self._identify_fp = None
self._identify_error = None
self.dev.identify([fp_whorl, fp_tented_arch], callback=identify_cb)
+ self.wait_for_finger_status(FPrint.FingerStatusFlags.NEEDED)
self.send_retry()
while self._identify_fp is None and self._identify_error is None:
ctx.iteration(True)
@@ -393,6 +421,7 @@ def verify_cb(dev, res):
self._verify_match = None
self._verify_fp = None
self.dev.verify(fp_whorl_new, callback=verify_cb)
+ self.wait_for_finger_status(FPrint.FingerStatusFlags.NEEDED)
self.send_image('whorl')
while self._verify_match is None:
ctx.iteration(True)
@@ -401,6 +430,7 @@ def verify_cb(dev, res):
self._verify_match = None
self._verify_fp = None
self.dev.verify(fp_whorl_new, callback=verify_cb)
+ self.wait_for_finger_status(FPrint.FingerStatusFlags.NEEDED)
self.send_image('tented_arch')
while self._verify_match is None:
ctx.iteration(True)