Compare commits

..

94 Commits

Author SHA1 Message Date
Benjamin Berg
a68fce0f2c Release 1.92.1 2021-07-19 12:50:13 +02:00
Benjamin Berg
1f5e0821e0 tests: Bump required version for pcap replay
Some tests require control transfer replay. This was added shortly after
the actual pcap replay, so simply require a new enough umockdev.
2021-07-12 17:13:43 +02:00
Benjamin Berg
d6b4adec73 tests: Add upektc_img test 2021-07-12 17:06:43 +02:00
Benjamin Berg
9e7bfa05b3 synaptics: Immediately succeed for empty identify
Such an empty identify can be run by fprintd intentionally for duplicate
checking at the start of an enroll operation, which currently runs into
an error from the driver.

Avoid this by simply returning success immediately. This is fine, as
synaptics is only checking the explicitly passed list of prints rather
than using all available prints from the storage.
2021-07-12 11:43:46 +00:00
Liran Piade
9ecd6236ee Added ELAN 0c6e (from ROG Flow X13) 2021-07-08 21:36:38 +02:00
Saeed/Ali Rk
a07011bac2 tests: Add test for egistec0570 2021-07-08 13:42:22 +02:00
Saeed/Ali Rk
f7290255e0 egistec: Add new driver
This supports 1c7a:0570

Co-Authored-By: Maxim Kolesnikov <kolesnikov@svyazcom.ru>
2021-07-08 13:42:22 +02:00
Benjamin Berg
29048c51db tests: Add elanmoc CI test 2021-07-07 13:35:59 +02:00
hermanlin
42676dd300 elanmoc: Add elanmoc driver
Signed-off-by: hermanlin <herman.lin@emc.com.tw>
2021-07-07 13:35:59 +02:00
Benjamin Berg
45c5d17f3b elanspi: Fix format string 2021-07-06 20:56:16 +00:00
Benjamin Berg
fc76db562e aesx660: Fix format strings 2021-07-06 20:56:16 +00:00
Benjamin Berg
9f93f5ded7 virtual-device: Fix format strings 2021-07-06 20:56:16 +00:00
Benjamin Berg
74c4125827 upekts: Fix format strings 2021-07-06 20:56:16 +00:00
Benjamin Berg
4f6d908390 upeksonly: Fix format string warning by using unsigned
There is no need to use size_t for num_rows as it is capped to NUM_ROWS
which is defined to 2048.
2021-07-06 20:56:16 +00:00
Benjamin Berg
575bd369d5 upektc: Fix format string on architectures where 64bit is not long 2021-07-06 20:56:16 +00:00
Benjamin Berg
304219b65c upektc_img: Fix warnings in debug format strings 2021-07-06 20:56:16 +00:00
Benjamin Berg
23bca2a8ac spi: Fix pointer cast on 32bit architectures 2021-07-06 20:56:16 +00:00
Benjamin Berg
4bf064d873 meson: Shuffle around driver/helper definition
This should make it clearer what supporting features each driver needs.
2021-07-01 13:19:42 +02:00
Benjamin Berg
d2c2410a6f meson: Move source generation into libfprint meson file 2021-07-01 13:19:03 +02:00
Benjamin Berg
e8f9cc1fce scripts: Speed up uncrustify by running 4 jobs in parallel
There are some large files, and in most setups (including CI runners) we
have multiple cores available. Use xargs to run multiple parallel
uncrustify jobs rather than one large one. Just hardcode 4 jobs and 4
files at the same time for now.
2021-07-01 13:19:03 +02:00
Benjamin Berg
0ee274946d print: Fix pspec of print type to match real default
The default is actually FPI_PRINT_UNDEFINED and not FPI_PRINT_RAW.
2021-07-01 13:19:03 +02:00
Benjamin Berg
0c26205a1e Release 1.92.0 2021-06-30 15:58:12 +02:00
Benjamin Berg
d957bbd0f4 synaptics: Fix warning about missing initialization
The compiler seems to (incorrectly) think that cleanup might happen
before the variable has been initialized.
2021-06-30 15:58:12 +02:00
Benjamin Berg
ec9e6f1947 meson: Fix udev rules directory detection
There was a copy/paste error and we postfixed it with hwdb.d rather than
rules.d.
2021-06-30 11:14:58 +02:00
Benjamin Berg
24658fb351 meson: Add elanspi to list of default drivers
Pretty much all downstream distributions just enable all drivers anyway.
Also, it should work well enough, so it seems right to simply add
elanspi into the list of drivers that are enabled by default.
2021-06-29 17:29:53 +00:00
Benjamin Berg
d5fda36bc0 tests: Detect tests by checking any matching file prefix
We were testing only for .ioctl files, but we may now have .pcap file
and ended up simply not running the synaptics test unless there was
still a .ioctl file present.
2021-06-28 16:17:56 +02:00
Benjamin Berg
cdaa3497d7 virtual-storage: Add variant without list support
Simply remove the feature flag for the NO_LIST environment variable.

This also removes the IDENT variant for now as it has never been
implemented as described.
2021-06-25 17:38:28 +02:00
Benjamin Berg
8a5bec6619 device: Add API to update features during probe
This allows updating the supported feature bitfield during probe.
2021-06-25 17:38:28 +02:00
Benjamin Berg
145f7287fa fprint-list: Add SPI devices to supported list
This will make them show up on the website.
2021-06-25 12:31:52 +02:00
Benjamin Berg
dbd89929b9 tests: Increase timeout of umockdev tests
The new elanspi driver in particular needs a lot of ioctl's during the
test. On a normal machine, this would run quite quickly (less than 5s),
however, in busy CI environments this can take longer than 30s, causing
timeouts currently.

Increase the timeout from 10s to 15s. For CI this means the timeout now
is 45s which is hopefully enough.
2021-06-25 08:39:17 +00:00
Bastien Nocera
01663c1fb5 tests: Allow multiple tests per driver
Allow multiple tests per driver by using the first section of the
directory name, before the separating '-', as the driver name.
2021-06-25 10:23:42 +02:00
Bastien Nocera
4ef13d971d uru4000: Use GLib's random functions
So we can set a static seed when running tests.
2021-06-25 10:23:42 +02:00
Bastien Nocera
a267e30fc6 uru4000: Don't throw warnings during "power on"
During startup, we'd always get:
(fprintd:151125): libfprint-uru4000-WARNING **: 12:16:56.724: ignoring unexpected interrupt 56aa

But we actually know what this interrupt is, and it's not unexpected, as
it tells us that the reader is now powered on.
2021-06-25 10:23:42 +02:00
Benjamin Berg
2ba60d0a52 tests: Improved umockdev version check
The new features will be added in 0.16, so match against that. Also,
match against CI_PROJECT_NAME to detect our CI environment (and assume
that umockdev has been patched to the point of supporting all tests).
2021-06-25 08:05:13 +00:00
Benjamin Berg
947420d2ce demo: Do not build udev_rules inside flatpak
This fixes flatpak generation after the new SPI related rule generation
has landet.
2021-06-25 09:54:00 +02:00
Benjamin Berg
793cad57f3 demo: Add libgudev into flatpak manifest
It is needed for SPI support.
2021-06-25 09:54:00 +02:00
Benjamin Berg
f37e20b8a0 meson: Permit disabling (and forcing) installation of udev rules
In some cases (e.g. inside the flatpak), it does not make sense to
generate and install udev rules.
2021-06-25 09:54:00 +02:00
Benjamin Berg
e2f199bb6a vfs301: Fix leak of USB transfer
vfs301_proto_peek_event would leak the returned transfer. Use a
g_autoptr to fix this.
2021-06-23 22:49:59 +02:00
Matthew Mirvish
059ab65081 tests: Add capture test for elanspi 2021-06-23 20:42:52 +00:00
Benjamin Berg
7893278cc6 tests: Add handling for SPI ioctl replay
This will only be supported with umockdev version 0.15.6.
2021-06-23 20:42:52 +00:00
Matthew Mirvish
0697191387 tests: Allow multiple mock devices per driver
Instead of only loading `DRIVER/device`, now we also load all files
matching device-*[!~] in the DRIVER folder..
2021-06-23 20:42:52 +00:00
Matthew Mirvish
8be666bb05 elanspi: Permit running in emulated environment
This removes the HID reset, which we cannot emulate currently and also
disabes the line timeout to as simulation might run too slowly at times.
2021-06-23 20:42:52 +00:00
Matthew Mirvish
019a294ec4 elanspi: Add driver supporting various ELAN SPI sensors
Closes: #339
2021-06-23 20:42:52 +00:00
Matthew Mirvish
f6e80456d9 ci: Add gudev to dependencies 2021-06-23 20:42:52 +00:00
Benjamin Berg
51cab75b1e assembling: Fix copying only partial tile on overhang
If the tile in question was hanging over the left edge we would not be
copying the full available width. Fix this and change the test to catch
the error condition (by forcing a too small image and overlap both
ways).

Simplify the code by only selecting the starting point inside the
image/frame and then just checking the both image and frame boundary in
the loop. Not quite as efficient, but it really shouldn't matter too
much here.
2021-06-23 22:33:07 +02:00
boger
1ed2b23902 goodixmoc: add PID 609C/6584/658C/6592/659C
add some new PID support,
609C: Framework fingerprint sensor
65xx: Thinkpad series fingerprint sensor
2021-06-23 15:30:28 +08:00
Benjamin Berg
9dd72611bf list-udev-rules: Add udev rule generation for SPI 2021-06-22 19:13:48 +00:00
Benjamin Berg
4bcb55e412 meson: Fix indentation
Change tab indented areas to 4 spaces.
2021-06-22 19:13:48 +00:00
Benjamin Berg
5bda7aef38 ci: Use --status-bugs option for scan-build
This removes the need to check the output directory for files.
2021-06-22 19:54:42 +02:00
Benjamin Berg
b4f564cafc spi-transfer: Keep CS asserted during long transfers
Long transfers need to be split into multiple chunks because of
limitations by the spidev kernel driver. If this happens, we need to
make sure that the CS line remains high between the different chunks.

Add code to split the transfer into chunks and ask the driver to not
deassert CS after the transfer. Technically, this is only an
optimization as concurrent access to another device might still cause
deselection. However, this should mean that devices work without having
to change the spidev module parameter.

Use the feature in the hope that it will work. However, print a message
(not a warning), to help with debugging in case someone does run into
issues because of this.
2021-06-21 22:24:58 +00:00
Matthew Mirvish
a3f568db3d fp-context: Check hidraw VID/PID with udev instead of an ioctl
Previously, we checked hidraw devices against drivers by using the
HIDIOCGRAWINFO ioctl. While this works, it's not ideal for doing unit
tests since umockdev would have to implement hidraw ioctls.

The new approach uses the HID_ID property on the parent hid device,
which contains the VID/PID pair.
2021-06-21 13:39:24 -04:00
Benjamin Berg
ba920aa41b goodixmoc: Remove internal cancellable
The driver has an internal cancellable that simply forwards the external
cancellation in the cancel callback. This is not really needed, we can
instead just use the external cancellable directly by fetching it using
fpi_device_get_cancellable().
2021-06-21 15:11:18 +00:00
Benjamin Berg
db1e88138b meson: Add dependency to gobject-introspection
We seem to need this to build the introspection bindings.

Closes: #385
2021-06-21 17:07:16 +02:00
Benjamin Berg
7ff95dc39a tests: Add clear_storage related tests
Closes: #382
2021-06-21 16:50:18 +02:00
Benjamin Berg
098ff97edd drivers: Fix upekts/upek_proto license
The (trivial) CRC code was copied from gstreamer. However, the license
stated here was LGPLv2 rather than LGPLv2.1+. Identical code can currently
be found upstream in gstreamer licensed under LGPLv2+. As such, update
the license, making it more compatible with the rest of libfprint.

Also add the "or any later version" to upekts.c. The library was already
LGPL2.1+ at the time and libthinkfinger authors approved a license
change.
2021-06-17 13:08:19 +00:00
Benjamin Berg
90cbcd7fb5 tests: Update README to describe pcapng replay 2021-06-17 14:35:47 +02:00
Benjamin Berg
182367a079 tests: Use pcap recording for synaptics and test clear_storage 2021-06-17 14:35:47 +02:00
Benjamin Berg
daaafc80c3 tests: Detect pcap vs. ioctl recording and run correct one 2021-06-17 14:21:08 +02:00
Benjamin Berg
c989cc4b95 ci: Build umockdev from git for pcap replay support 2021-06-17 14:21:08 +02:00
Vincent Huang
0edae7b641 synaptics: Remove PID 0xE9 2021-06-17 08:00:47 +00:00
Vincent Huang
49e3963783 synaptics: Return success when deleting a print that doesn't exist in
the database or database empty
2021-06-16 15:53:46 +00:00
Aris Lin
040d0d34fd synaptics: Send a cancel to sensor if it returns busy
fix #380
2021-06-16 15:40:02 +00:00
Nelson Jeppesen
82c406dace goodixmoc: Add PID 6A94 2021-06-07 10:40:45 +00:00
Benjamin Berg
046607add6 device: Add void return type tag to fp_device_delete_print_sync
This way it matches the other _sync functions that return a boolean just
to show that an error was set.
2021-05-14 15:28:54 +00:00
Benjamin Berg
9c0cd3fb23 device: Move fp_device_clear_storage_sync into _sync block
Just so that all the _sync functions are together.
2021-05-14 15:28:54 +00:00
Benjamin Berg
439223cac3 virtual-device-storage: Actually clear storage when requested 2021-05-14 15:28:54 +00:00
Benjamin Berg
992a207ede virtual-device: Refactor command handling and add CONT command
This command is useful to immediately continue rather than waiting for
input. It is only useful for non-scanning device actions and can be
important when steps need to be explicitly skipped (e.g. to inject an
error in the second command without a way to wait in between).
2021-05-14 15:28:54 +00:00
Benjamin Berg
ae6be6837b doc: Use includes from the source diretory
Before we try to use installed system includes, which is obviously not
the best idea.
2021-05-14 15:28:54 +00:00
Benjamin Berg
261ba3a4a4 meson: Add -Wswitch-enum
This would have caught the issue where we forgot to add
FPI_DEVICE_ACTION_CLEAR_STORAGE to fpi_device_action_error.
2021-05-14 15:28:54 +00:00
Benjamin Berg
e9dddcc87a virtual-image: Fix compilation with -Wswitch-enum 2021-05-14 15:28:54 +00:00
Benjamin Berg
7e02f3faf9 virtual-device: Avoid/Fix -Wswitch-enum warnings 2021-05-14 15:28:54 +00:00
Benjamin Berg
b61303500e utilities: Explicitly list default enum value 2021-05-14 15:28:54 +00:00
Benjamin Berg
668b3517a9 upeksonly: Explicit list default enum value 2021-05-14 15:28:54 +00:00
Benjamin Berg
657fe85c25 device: Add missing CLEAR_STORAGE to fpi_device_action_error
This was missed in the previous commit that added the support.
2021-05-14 15:28:54 +00:00
Aris Lin
4d5e2775b2 synaptics: add new PID 0xF0 and 0x103 2021-05-05 15:24:25 +08:00
Vincent Huang
8a04578847 synaptics: Add clear_storage() and remove list() 2021-04-29 11:49:27 +00:00
Vincent Huang
77e95aa545 fp-device: Add fp_device_clear_storage and clear_storage vfunc 2021-04-29 11:49:27 +00:00
Benjamin Berg
b9df7a4e70 device: Attach sources to correct main context
We were attaching the sources to the default main context. Instead, we
should be attaching them to the current tasks main context (or, failing
that, the current thread local main context).
2021-04-28 22:16:37 +02:00
Benjamin Berg
1ca56adff5 usb-transfer: Use fpi_device_add_timeout instead of g_idle_add
g_idle_add attaches to the default main context, but the rest of
libfprint is using the thread local main context. Switch to use the
internal fpi_device_add_timeout API for the workaround in order to
not rely on the default main context.
2021-04-28 22:16:37 +02:00
Benjamin Berg
d683b271d4 ssm: Remove delayed action GCancellable integration
Unfortunately, the implementation was not thread safe and was not
sticking to the thread local main context.

In addition to this, it is not entirely clear to me how this API should
behave. The current approach is to simply cancel the transition with the
state machine halting in its current state. Instead, it could also make
sense for cancellation to cause the state machine to return a
G_IO_ERROR_CANCELLED.

As such, simply remove the feature for now. If anyone actually has a
good use-case then we can add it again.
2021-04-28 22:16:37 +02:00
Benjamin Berg
94e86875ae context: Remove idle sources and use thread local context
libfprint uses the thread local context in almost all cases. Update
FpContext to also use it and make sure that any sources are removed when
the FpContext object is finalized. Otherwise we may run into
use-after-free issues.
2021-04-28 22:16:37 +02:00
Benjamin Berg
511d456006 context: Use g_signal_connect_object for removal handling
Technically the API user might not keep the FpContext around after getting
the device object. Really bad idea, but we shouldn't rely on that.
2021-04-28 22:16:34 +02:00
Benjamin Berg
11e379050f goodixmoc: Ensure power button shield is always turned off
Use the new cleanup feature of the SSM to ensure that the power button
shield is turned off again even if the operation is cancelled.
2021-04-28 20:10:20 +00:00
Benjamin Berg
9416f91c75 ssm: Add cleanup state feature
In some situations one may want to guarantee that the last steps of an
SSM are run even when the SSM is completed early or failed.

This can easily be done by making fpi_ssm_mark_completed jump to the
next cleanup stage when called (this also includes mark_failed). Due to
the mechanism, it is still possible to explicitly jump cleanup states by
using fpi_ssm_jump_to_state, including a jump to the final state in
order to skip all cleanup states.
2021-04-28 20:10:20 +00:00
Benjamin Berg
c4ae89575a ssm: Fix up the SSM documentation a bit 2021-04-28 20:10:20 +00:00
Benjamin Berg
04f6cac7ec elan: Add PID 0c63
Users are reporting that the sensor works fine.

Closes: #357
2021-04-28 22:04:16 +02:00
Benjamin Berg
d2981fc6a4 elan: Add PID 0c4f
Users are reporting that the sensor works fine.
2021-04-28 22:04:16 +02:00
Benjamin Berg
8c9167d836 elan: Add PID 0c3d
Users are reporting that the sensor works fine.

Closes: #214
2021-04-28 15:26:05 +02:00
Marco Trevisan (Treviño)
9aa3060d32 ci: Expose valgrind test logs 2021-04-13 19:39:50 +02:00
Marco Trevisan (Treviño)
9a1dcaa801 tests: Use native meson exec wrapper in test setups instead of our script
No need to provide a script that will break usage of `meson test --gdb`
when we can use a native and cleaner alternative.

We can then ignore LIBFPRINT_TEST_WRAPPER in basic tests, while it is
still needed by umockdev tests.
2021-04-13 19:38:58 +02:00
Marco Trevisan (Treviño)
683ac48e21 libfprint2-sections: Add missing FpFingerStatusFlags 2021-04-12 22:14:06 +02:00
Marco Trevisan (Treviño)
3b34fc9b5b ci: Expose coverage report and meson logs in MRs 2021-04-12 22:14:06 +02:00
Marco Trevisan (Treviño)
41f8737b48 device: Deprecate fp_device_{supports,has}_* functions for has_feature
We can avoid having multiple device feature-check functions now and
just rely on a few.

Add uncrustify config to properly handle begin/end deprecation macros.
2021-04-12 22:14:06 +02:00
Marco Trevisan (Treviño)
ef805f2341 device: Expose supported features publicly as FpDeviceFeature
It can be convenient for device users to check what it supports, without
having multiple functions to check each single feature.

So expose this and add tests.
2021-04-12 22:14:06 +02:00
98 changed files with 38300 additions and 1522 deletions

View File

@@ -52,7 +52,8 @@ build:
artifacts:
expose_as: "HTML Documentation"
paths:
- _build/doc/html/
- _build/doc/html
- _build/doc/html/index.html
expire_in: 1 week
test:
@@ -67,8 +68,10 @@ test:
- ninja -C _build coverage
- cat _build/meson-logs/coverage.txt
artifacts:
expose_as: 'Coverage Report'
paths:
- _build/meson-logs
- _build/meson-logs/coveragereport/index.html
expire_in: 1 week
coverage: '/^TOTAL.*\s+(\d+\%)$/'
@@ -81,6 +84,13 @@ test_valgrind:
- meson -Ddrivers=all . _build
- ninja -C _build
- meson test -C _build --print-errorlogs --no-stdsplit --setup=valgrind
artifacts:
expose_as: 'Valgrind test logs'
paths:
- _build/meson-logs
- _build/meson-logs/testlog-valgrind.txt
expire_in: 1 week
test_scan_build:
stage: test
@@ -90,10 +100,8 @@ test_scan_build:
allow_failure: true
script:
- meson -Ddrivers=all . _build
# This is ugly, the wrapper disables the malloc checker
# Wrapper to add --status-bugs and disable malloc checker
- SCANBUILD=$CI_PROJECT_DIR/.gitlab-ci/scan-build ninja -C _build scan-build
# Check that the directory is empty
- "! ls -A _build/meson-logs/scanbuild | grep -q ."
artifacts:
paths:
- _build/meson-logs
@@ -150,4 +158,13 @@ container_fedora_build:
variables:
GIT_STRATEGY: none # no need to pull the whole tree for rebuilding the image
# a list of packages to install
FDO_DISTRIBUTION_PACKAGES: $LIBFPRINT_DEPENDENCIES
FDO_DISTRIBUTION_PACKAGES:
$LIBFPRINT_DEPENDENCIES
vala
libpcap-devel
libudev-devel
FDO_DISTRIBUTION_EXEC: |
git clone https://github.com/martinpitt/umockdev.git && \
cd umockdev && \
meson _build --prefix=/usr && \
ninja -C _build && ninja -C _build install

View File

@@ -13,6 +13,7 @@
gtk3-devel
libabigail
libgusb-devel
libgudev-devel
libX11-devel
libXv-devel
meson

View File

@@ -1,4 +1,4 @@
#!/bin/sh
# This wrapper just disables the malloc checker
exec /usr/bin/scan-build -disable-checker unix.Malloc "$@"
exec /usr/bin/scan-build --status-bugs -disable-checker unix.Malloc "$@"

53
NEWS
View File

@@ -1,6 +1,59 @@
This file lists notable changes in each release. For the full history of all
changes, see ChangeLog.
2021-06-30: v1.92.1 release
Highlights:
* elanmoc: New driver for ELAN match-on-chip devices
* egis0570: New driver for some Egis Technology devices
* synaptics: Fix empty identify causing enroll issues
* elan: Support more PIDs
* misc: Architecture related bugfixes
2021-06-30: v1.92.0 release
Highlights:
* Support for SPI devices was added together with the elanspi driver
* Generate hwdb for autosuspend (which is now pulled by systemd)
* An API was added to clear the device storage.
Note: Devices may not implement the "list" API anymore.
* Device features can now be queried using a common API
New drivers:
* vfs7552
* nb1010
* elanspi
Driver changes:
* uru4000: Fix deactivation when unplugged unexpectedly
* goodixmoc: Correctly complete verify/identify after retry condition
* goodixmoc: Support power shield feature
* goodixmoc: Support new PIDs
* synaptics: Fix driver lockup when sequence counter overflows (#358)
* synaptics: Remove unnecessary device reset
* synaptics: Support new PIDs
* synaptics: Add clear_storage and remove list support
* synaptics: Fix initialization if the device is still busy when opening
* upeksonly: Fix double free in USB transfer callbacks
* elan: Support new PIDs
* vfs301: Fix leak of USB transfer
* uru4000: Silence warning happening during startup
Internal API changes:
* ssm: Add getter for the device
* ssm: Add cleanup state feature
* image-device: Allow overriding number of enroll stages
* context: Support udev based device discovery
* spi-transfer: Add SPI transfer helper routines
Other:
* Use pcap based USB replay for CI
* New virtual drivers for more advanced testing
* Ensure async operations are run in the thread local main context
* Disable drivers on big-endian unless they are verified to work
* Add missing gobject-introspection dependency
2020-12-01: v1.90.7 release
Highlights:

View File

@@ -64,6 +64,11 @@ usb:v08FFp5731*
usb:v5501p08FF*
ID_AUTOSUSPEND=1
# Supported by libfprint driver egis0570
usb:v1C7Ap0570*
usb:v1C7Ap0571*
ID_AUTOSUSPEND=1
# Supported by libfprint driver elan
usb:v04F3p0903*
usb:v04F3p0907*
@@ -118,8 +123,16 @@ usb:v04F3p0C30*
usb:v04F3p0C31*
usb:v04F3p0C32*
usb:v04F3p0C33*
usb:v04F3p0C3D*
usb:v04F3p0C42*
usb:v04F3p0C4D*
usb:v04F3p0C4F*
usb:v04F3p0C63*
usb:v04F3p0C6E*
ID_AUTOSUSPEND=1
# Supported by libfprint driver elanmoc
usb:v04F3p0C7E*
ID_AUTOSUSPEND=1
# Supported by libfprint driver etes603
@@ -128,11 +141,17 @@ usb:v1C7Ap0603*
# Supported by libfprint driver goodixmoc
usb:v27C6p5840*
usb:v27C6p6496*
usb:v27C6p609C*
usb:v27C6p60A2*
usb:v27C6p63AC*
usb:v27C6p639C*
usb:v27C6p63AC*
usb:v27C6p6496*
usb:v27C6p6584*
usb:v27C6p658C*
usb:v27C6p6592*
usb:v27C6p6594*
usb:v27C6p659C*
usb:v27C6p6A94*
ID_AUTOSUSPEND=1
# Supported by libfprint driver nb1010
@@ -141,13 +160,14 @@ usb:v298Dp1010*
# Supported by libfprint driver synaptics
usb:v06CBp00BD*
usb:v06CBp00E9*
usb:v06CBp00DF*
usb:v06CBp00F9*
usb:v06CBp00FC*
usb:v06CBp00C2*
usb:v06CBp00C9*
usb:v06CBp0100*
usb:v06CBp00F0*
usb:v06CBp0103*
ID_AUTOSUSPEND=1
# Supported by libfprint driver upeksonly
@@ -208,7 +228,6 @@ usb:v04F3p036B*
usb:v04F3p0C00*
usb:v04F3p0C4B*
usb:v04F3p0C4C*
usb:v04F3p0C4F*
usb:v04F3p0C57*
usb:v04F3p0C5E*
usb:v04F3p2706*
@@ -225,6 +244,7 @@ usb:v06CBp00C4*
usb:v06CBp00CB*
usb:v06CBp00D8*
usb:v06CBp00DA*
usb:v06CBp00E9*
usb:v0A5Cp5801*
usb:v0A5Cp5805*
usb:v0A5Cp5834*
@@ -250,7 +270,6 @@ usb:v147Ep1002*
usb:v1491p0088*
usb:v16D1p1027*
usb:v1C7Ap0300*
usb:v1C7Ap0570*
usb:v1C7Ap0575*
usb:v27C6p5042*
usb:v27C6p5110*

View File

@@ -526,7 +526,7 @@ libfprint_demo_window_init (LibfprintDemoWindow *window)
return;
}
if (!fp_device_supports_capture (g_ptr_array_index (devices, 0)))
if (!fp_device_has_feature (g_ptr_array_index (devices, 0), FP_DEVICE_FEATURE_CAPTURE))
{
libfprint_demo_set_mode (window, NOIMAGING_MODE);
return;

View File

@@ -47,10 +47,22 @@
}
]
},
{
"name": "gudev",
"buildsystem": "meson",
"config-opts": [ "-Dtests=disabled", "-Dintrospection=disabled" ],
"sources": [
{
"type": "archive",
"url": "https://download.gnome.org/sources/libgudev/236/libgudev-236.tar.xz",
"sha256": "e50369d06d594bae615eb7aeb787de304ebaad07a26d1043cef8e9c7ab7c9524"
}
]
},
{
"name": "libfprint",
"buildsystem": "meson",
"config-opts": [ "-Dudev_hwdb=disabled", "-Dx11-examples=false", "-Dgtk-examples=true", "-Ddrivers=all" ],
"config-opts": [ "-Dudev_hwdb=disabled", "-Dudev_rules=disabled", "-Dx11-examples=false", "-Dgtk-examples=true", "-Ddrivers=all" ],
"sources": [
{
"type": "git",

View File

@@ -20,9 +20,11 @@ FP_TYPE_DEVICE
FP_DEVICE_RETRY
FP_DEVICE_ERROR
FpDeviceType
FpDeviceFeature
FpScanType
FpDeviceRetry
FpDeviceError
FpFingerStatusFlags
fp_device_retry_quark
fp_device_error_quark
FpEnrollProgress
@@ -33,6 +35,8 @@ fp_device_get_name
fp_device_get_scan_type
fp_device_get_nr_enroll_stages
fp_device_get_finger_status
fp_device_get_features
fp_device_has_feature
fp_device_has_storage
fp_device_supports_identify
fp_device_supports_capture
@@ -45,6 +49,7 @@ fp_device_identify
fp_device_capture
fp_device_delete_print
fp_device_list_prints
fp_device_clear_storage
fp_device_open_finish
fp_device_close_finish
fp_device_enroll_finish
@@ -53,6 +58,7 @@ fp_device_identify_finish
fp_device_capture_finish
fp_device_delete_print_finish
fp_device_list_prints_finish
fp_device_clear_storage_finish
fp_device_open_sync
fp_device_close_sync
fp_device_enroll_sync
@@ -61,6 +67,7 @@ fp_device_identify_sync
fp_device_capture_sync
fp_device_delete_print_sync
fp_device_list_prints_sync
fp_device_clear_storage_sync
FpDevice
</SECTION>
@@ -131,7 +138,6 @@ fpi_get_driver_types
FpDeviceClass
FpTimeoutFunc
FpiDeviceAction
FpiDeviceFeature
FpIdEntry
FpiDeviceUdevSubtypeFlags
fpi_device_get_usb_device
@@ -153,6 +159,7 @@ fpi_device_action_is_cancelled
fpi_device_add_timeout
fpi_device_set_nr_enroll_stages
fpi_device_set_scan_type
fpi_device_update_features
fpi_device_remove
fpi_device_report_finger_status
fpi_device_report_finger_status_changes

View File

@@ -1,5 +1,5 @@
#include <libfprint-2/fprint.h>
#include <libfprint-2/fp-image-device.h>
#include <fprint.h>
#include <fp-image-device.h>
fp_context_get_type
fp_device_get_type

View File

@@ -26,6 +26,7 @@ docpath = join_paths(get_option('datadir'), 'gtk-doc', 'html')
gnome.gtkdoc(versioned_libname,
main_xml: 'libfprint-docs.xml',
src_dir: join_paths(meson.source_root(), 'libfprint'),
include_directories: include_directories('../libfprint'),
dependencies: libfprint_dep,
content_files: content_files,
expand_content_files: expand_content_files,

View File

@@ -76,7 +76,7 @@ on_enroll_completed (FpDevice *dev, GAsyncResult *res, void *user_data)
{
enroll_data->ret_value = EXIT_SUCCESS;
if (fp_device_has_storage (dev))
if (fp_device_has_feature (dev, FP_DEVICE_FEATURE_STORAGE))
g_debug ("Device has storage, saving a print reference locally");
else
g_debug ("Device has not storage, saving print only locally");

View File

@@ -212,7 +212,7 @@ on_list_completed (FpDevice *dev, GAsyncResult *res, gpointer user_data)
static void
start_identification (FpDevice *dev, IdentifyData *identify_data)
{
if (fp_device_has_storage (dev))
if (fp_device_has_feature (dev, FP_DEVICE_FEATURE_STORAGE))
{
g_print ("Creating finger template, using device storage...\n");
fp_device_list_prints (dev, NULL,
@@ -293,7 +293,7 @@ main (void)
return EXIT_FAILURE;
}
if (!fp_device_supports_identify (dev))
if (!fp_device_has_feature (dev, FP_DEVICE_FEATURE_IDENTIFY))
{
g_warning ("Device %s does not support identification.",
fp_device_get_name (dev));

View File

@@ -162,7 +162,7 @@ main (int argc, const char *argv[])
return EXIT_FAILURE;
}
if (!fp_device_supports_capture (dev))
if (!fp_device_has_feature (dev, FP_DEVICE_FEATURE_CAPTURE))
{
g_warning ("Device %s doesn't support capture",
fp_device_get_name (dev));

View File

@@ -231,7 +231,7 @@ on_device_opened (FpDevice *dev,
return;
}
if (!fp_device_has_storage (dev))
if (!fp_device_has_feature (dev, FP_DEVICE_FEATURE_STORAGE))
{
g_warning ("Device %s doesn't support storage", fp_device_get_name (dev));
g_main_loop_quit (list_data->loop);

View File

@@ -101,6 +101,7 @@ finger_to_string (FpFinger finger)
case FP_FINGER_RIGHT_LITTLE:
return "right little";
case FP_FINGER_UNKNOWN:
default:
return "unknown";
}

View File

@@ -260,7 +260,7 @@ start_verification (FpDevice *dev, VerifyData *verify_data)
return;
}
if (fp_device_has_storage (dev))
if (fp_device_has_feature (dev, FP_DEVICE_FEATURE_STORAGE))
{
g_print ("Creating finger template, using device storage...\n");
fp_device_list_prints (dev, NULL,

View File

@@ -365,7 +365,7 @@ capture_read_stripe_data_cb (FpiUsbTransfer *transfer,
return;
}
fp_dbg ("Got %lu bytes of data", actual_length);
fp_dbg ("Got %" G_GSIZE_FORMAT " bytes of data", actual_length);
while (actual_length)
{
gssize payload_length;
@@ -386,7 +386,7 @@ capture_read_stripe_data_cb (FpiUsbTransfer *transfer,
(priv->stripe_packet->data[AESX660_RESPONSE_SIZE_MSB_OFFSET] << 8);
fp_dbg ("Got frame, type %.2x payload of size %.4lx",
priv->stripe_packet->data[AESX660_RESPONSE_TYPE_OFFSET],
payload_length);
(long) payload_length);
still_needed_len = MAX (0, AESX660_HEADER_SIZE + payload_length - (gssize) priv->stripe_packet->len);
copy_len = MIN (actual_length, still_needed_len);
@@ -441,7 +441,7 @@ capture_run_state (FpiSsm *ssm, FpDevice *_dev)
break;
case CAPTURE_SET_IDLE:
fp_dbg ("Got %lu frames", priv->strips_len);
fp_dbg ("Got %" G_GSIZE_FORMAT " frames", priv->strips_len);
aesX660_send_cmd (ssm, _dev, set_idle_cmd, sizeof (set_idle_cmd),
capture_set_idle_cmd_cb);
break;

View File

@@ -0,0 +1,444 @@
/*
* Egis Technology Inc. (aka. LighTuning) 0570 driver for libfprint
* Copyright (C) 2021 Maxim Kolesnikov <kolesnikov@svyazcom.ru>
* Copyright (C) 2021 Saeed/Ali Rk <saeed.ali.rahimi@gmail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#define FP_COMPONENT "egis0570"
#include "egis0570.h"
#include "drivers_api.h"
/* Packet types */
#define PKT_TYPE_INIT 0
#define PKT_TYPE_REPEAT 1
/* Struct */
struct _FpDeviceEgis0570
{
FpImageDevice parent;
gboolean running;
gboolean stop;
GSList *strips;
guint8 *background;
gsize strips_len;
int pkt_num;
int pkt_type;
};
G_DECLARE_FINAL_TYPE (FpDeviceEgis0570, fpi_device_egis0570, FPI, DEVICE_EGIS0570, FpImageDevice);
G_DEFINE_TYPE (FpDeviceEgis0570, fpi_device_egis0570, FP_TYPE_IMAGE_DEVICE);
static unsigned char
egis_get_pixel (struct fpi_frame_asmbl_ctx *ctx, struct fpi_frame *frame, unsigned int x, unsigned int y)
{
return frame->data[x + y * ctx->frame_width];
}
static struct fpi_frame_asmbl_ctx assembling_ctx = {
.frame_width = EGIS0570_IMGWIDTH,
.frame_height = EGIS0570_RFMGHEIGHT,
.image_width = EGIS0570_IMGWIDTH * 4 / 3,
.get_pixel = egis_get_pixel,
};
/*
* Service
*/
static gboolean
is_last_pkt (FpDevice *dev)
{
FpDeviceEgis0570 *self = FPI_DEVICE_EGIS0570 (dev);
int type = self->pkt_type;
int num = self->pkt_num;
gboolean r;
r = ((type == PKT_TYPE_INIT) && (num == (EGIS0570_INIT_TOTAL - 1)));
r |= ((type == PKT_TYPE_REPEAT) && (num == (EGIS0570_REPEAT_TOTAL - 1)));
return r;
}
/*
* Returns a bit for each frame on whether or not a finger has been detected.
* e.g. 00110 means that there is a finger in frame two and three.
*/
static char
postprocess_frames (FpDeviceEgis0570 *self, guint8 * img)
{
size_t mean[EGIS0570_IMGCOUNT] = {0, 0, 0, 0, 0};
if (!self->background)
{
self->background = g_malloc (EGIS0570_IMGWIDTH * EGIS0570_RFMGHEIGHT);
memset (self->background, 255, EGIS0570_IMGWIDTH * EGIS0570_RFMGHEIGHT);
for (size_t k = 0; k < EGIS0570_IMGCOUNT; k += 1)
{
guint8 * frame = &img[(k * EGIS0570_IMGSIZE) + EGIS0570_RFMDIS * EGIS0570_IMGWIDTH];
for (size_t i = 0; i < EGIS0570_IMGWIDTH * EGIS0570_RFMGHEIGHT; i += 1)
self->background[i] = MIN (self->background[i], frame[i]);
}
return 0;
}
for (size_t k = 0; k < EGIS0570_IMGCOUNT; k += 1)
{
guint8 * frame = &img[(k * EGIS0570_IMGSIZE) + EGIS0570_RFMDIS * EGIS0570_IMGWIDTH];
for (size_t i = 0; i < EGIS0570_IMGWIDTH * EGIS0570_RFMGHEIGHT; i += 1)
{
if (frame[i] - EGIS0570_MARGIN > self->background[i])
frame[i] -= self->background[i];
else
frame[i] = 0;
mean[k] += frame[i];
}
mean[k] /= EGIS0570_IMGWIDTH * EGIS0570_RFMGHEIGHT;
}
char result = 0;
for (size_t k = 0; k < EGIS0570_IMGCOUNT; k += 1)
{
fp_dbg ("Finger status (picture number, mean) : %ld , %ld", k, mean[k]);
if (mean[k] > EGIS0570_MIN_MEAN)
result |= 1 << k;
}
return result;
}
/*
* Device communication
*/
static void
data_resp_cb (FpiUsbTransfer *transfer, FpDevice *dev, gpointer user_data, GError *error)
{
unsigned char *stripdata;
gboolean end = FALSE;
FpImageDevice *img_self = FP_IMAGE_DEVICE (dev);
FpDeviceEgis0570 *self = FPI_DEVICE_EGIS0570 (dev);
if (error)
{
fpi_ssm_mark_failed (transfer->ssm, error);
return;
}
int where_finger_is = postprocess_frames (self, transfer->buffer);
if (where_finger_is > 0)
{
FpiImageDeviceState state;
fpi_image_device_report_finger_status (img_self, TRUE);
g_object_get (dev, "fpi-image-device-state", &state, NULL);
if (state == FPI_IMAGE_DEVICE_STATE_CAPTURE)
{
for (size_t k = 0; k < EGIS0570_IMGCOUNT; k += 1)
{
if (where_finger_is & (1 << k))
{
struct fpi_frame *stripe = g_malloc (EGIS0570_IMGWIDTH * EGIS0570_RFMGHEIGHT + sizeof (struct fpi_frame));
stripe->delta_x = 0;
stripe->delta_y = 0;
stripdata = stripe->data;
memcpy (stripdata, (transfer->buffer) + (((k) * EGIS0570_IMGSIZE) + EGIS0570_IMGWIDTH * EGIS0570_RFMDIS), EGIS0570_IMGWIDTH * EGIS0570_RFMGHEIGHT);
self->strips = g_slist_prepend (self->strips, stripe);
self->strips_len += 1;
}
else
{
end = TRUE;
break;
}
}
}
}
else
{
end = TRUE;
}
if (end)
{
if (!self->stop && (self->strips_len > 0))
{
FpImage *img;
self->strips = g_slist_reverse (self->strips);
fpi_do_movement_estimation (&assembling_ctx, self->strips);
img = fpi_assemble_frames (&assembling_ctx, self->strips);
img->flags |= (FPI_IMAGE_COLORS_INVERTED | FPI_IMAGE_PARTIAL);
g_slist_free_full (self->strips, g_free);
self->strips = NULL;
self->strips_len = 0;
FpImage *resizeImage = fpi_image_resize (img, EGIS0570_RESIZE, EGIS0570_RESIZE);
fpi_image_device_image_captured (img_self, resizeImage);
}
fpi_image_device_report_finger_status (img_self, FALSE);
}
fpi_ssm_next_state (transfer->ssm);
}
static void
recv_data_resp (FpiSsm *ssm, FpDevice *dev)
{
FpiUsbTransfer *transfer = fpi_usb_transfer_new (dev);
fpi_usb_transfer_fill_bulk (transfer, EGIS0570_EPIN, EGIS0570_INPSIZE);
transfer->ssm = ssm;
transfer->short_is_error = TRUE;
fpi_usb_transfer_submit (transfer, EGIS0570_TIMEOUT, NULL, data_resp_cb, NULL);
}
static void
cmd_resp_cb (FpiUsbTransfer *transfer, FpDevice *dev, gpointer user_data, GError *error)
{
if (error)
fpi_ssm_mark_failed (transfer->ssm, error);
}
static void
recv_cmd_resp (FpiSsm *ssm, FpDevice *dev)
{
FpiUsbTransfer *transfer = fpi_usb_transfer_new (dev);
fpi_usb_transfer_fill_bulk (transfer, EGIS0570_EPIN, EGIS0570_PKTSIZE);
transfer->ssm = ssm;
fpi_usb_transfer_submit (transfer, EGIS0570_TIMEOUT, NULL, cmd_resp_cb, NULL);
}
static void
send_cmd_req (FpiSsm *ssm, FpDevice *dev, unsigned char *pkt)
{
FpiUsbTransfer *transfer = fpi_usb_transfer_new (dev);
fpi_usb_transfer_fill_bulk_full (transfer, EGIS0570_EPOUT, pkt, EGIS0570_PKTSIZE, NULL);
transfer->ssm = ssm;
transfer->short_is_error = TRUE;
fpi_usb_transfer_submit (transfer, EGIS0570_TIMEOUT, NULL, fpi_ssm_usb_transfer_cb, NULL);
}
/*
* SSM States
*/
enum sm_states {
SM_INIT,
SM_START,
SM_REQ,
SM_RESP,
SM_REC_DATA,
SM_DONE,
SM_STATES_NUM
};
static void
ssm_run_state (FpiSsm *ssm, FpDevice *dev)
{
FpDeviceEgis0570 *self = FPI_DEVICE_EGIS0570 (dev);
FpImageDevice *img_dev = FP_IMAGE_DEVICE (dev);
switch (fpi_ssm_get_cur_state (ssm))
{
case SM_INIT:
self->pkt_type = PKT_TYPE_INIT;
fpi_ssm_next_state (ssm);
break;
case SM_START:
if (self->stop)
{
fp_dbg ("deactivating, marking completed");
fpi_ssm_mark_completed (ssm);
fpi_image_device_deactivate_complete (img_dev, NULL);
}
else
{
self->pkt_num = 0;
fpi_ssm_next_state (ssm);
}
break;
case SM_REQ:
if (self->pkt_type == PKT_TYPE_INIT)
send_cmd_req (ssm, dev, init_pkts[self->pkt_num]);
else
send_cmd_req (ssm, dev, repeat_pkts[self->pkt_num]);
break;
case SM_RESP:
if (is_last_pkt (dev) == FALSE)
{
recv_cmd_resp (ssm, dev);
self->pkt_num += 1;
fpi_ssm_jump_to_state (ssm, SM_REQ);
}
else
{
if (self->pkt_type == PKT_TYPE_INIT)
self->pkt_type = PKT_TYPE_REPEAT;
fpi_ssm_next_state (ssm);
}
break;
case SM_REC_DATA:
recv_data_resp (ssm, dev);
break;
case SM_DONE:
fpi_ssm_jump_to_state (ssm, SM_START);
break;
default:
g_assert_not_reached ();
}
}
/*
* Activation
*/
static void
loop_complete (FpiSsm *ssm, FpDevice *dev, GError *error)
{
FpImageDevice *img_dev = FP_IMAGE_DEVICE (dev);
FpDeviceEgis0570 *self = FPI_DEVICE_EGIS0570 (dev);
self->running = FALSE;
g_clear_pointer (&self->background, g_free);
if (error)
fpi_image_device_session_error (img_dev, error);
}
static void
dev_activate (FpImageDevice *dev)
{
FpDeviceEgis0570 *self = FPI_DEVICE_EGIS0570 (dev);
FpiSsm *ssm = fpi_ssm_new (FP_DEVICE (dev), ssm_run_state, SM_STATES_NUM);
self->stop = FALSE;
fpi_ssm_start (ssm, loop_complete);
self->running = TRUE;
fpi_image_device_activate_complete (dev, NULL);
}
/*
* Opening
*/
static void
dev_init (FpImageDevice *dev)
{
GError *error = NULL;
g_usb_device_claim_interface (fpi_device_get_usb_device (FP_DEVICE (dev)), 0, 0, &error);
fpi_image_device_open_complete (dev, error);
}
/*
* Closing
*/
static void
dev_deinit (FpImageDevice *dev)
{
GError *error = NULL;
g_usb_device_release_interface (fpi_device_get_usb_device (FP_DEVICE (dev)), 0, 0, &error);
fpi_image_device_close_complete (dev, error);
}
/*
* Deactivation
*/
static void
dev_deactivate (FpImageDevice *dev)
{
FpDeviceEgis0570 *self = FPI_DEVICE_EGIS0570 (dev);
if (self->running)
self->stop = TRUE;
else
fpi_image_device_deactivate_complete (dev, NULL);
}
/*
* Driver data
*/
static const FpIdEntry id_table[] = {
{ .vid = 0x1c7a, .pid = 0x0570, },
{ .vid = 0x1c7a, .pid = 0x0571, },
{ .vid = 0, .pid = 0, },
};
static void
fpi_device_egis0570_init (FpDeviceEgis0570 *self)
{
}
static void
fpi_device_egis0570_class_init (FpDeviceEgis0570Class *klass)
{
FpDeviceClass *dev_class = FP_DEVICE_CLASS (klass);
FpImageDeviceClass *img_class = FP_IMAGE_DEVICE_CLASS (klass);
dev_class->id = "egis0570";
dev_class->full_name = "Egis Technology Inc. (aka. LighTuning) 0570";
dev_class->type = FP_DEVICE_TYPE_USB;
dev_class->id_table = id_table;
dev_class->scan_type = FP_SCAN_TYPE_SWIPE;
img_class->img_open = dev_init;
img_class->img_close = dev_deinit;
img_class->activate = dev_activate;
img_class->deactivate = dev_deactivate;
img_class->img_width = EGIS0570_IMGWIDTH;
img_class->img_height = -1;
img_class->bz3_threshold = EGIS0570_BZ3_THRESHOLD; /* security issue */
}

View File

@@ -0,0 +1,177 @@
/*
* Egis Technology Inc. (aka. LighTuning) 0570 driver for libfprint
* Copyright (C) 2021 Maxim Kolesnikov <kolesnikov@svyazcom.ru>
* Copyright (C) 2021 Saeed/Ali Rk <saeed.ali.rahimi@gmail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __EGIS0570_H
#define __EGIS0570_H 1
/*
* Device data
*/
#define EGIS0570_CONF 1
#define EGIS0570_INTF 0
/*
* Device endpoints
*/
#define EGIS0570_EPOUT 0x04 /* ( 4 | FPI_USB_ENDPOINT_OUT ) */
#define EGIS0570_EPIN 0x83 /* ( 3 | FPI_USB_ENDPOINT_IN ) */
/*
* Initialization packets (7 bytes each)
*
* First 4 bytes are equivalent to string "EGIS", which must be just a company identificator
* Other 3 bytes are not recognized yet and may be not important, as they are always the same
* Answers for each packet contain 7 bytes again
* First 4 bytes are reversed "EGIS", which is "SIGE", which is company ID again
* Other 3 bytes are not recognized yet
* But there is a pattern.
* Sending last packet makes sensor return image
*/
#define EGIS0570_TIMEOUT 10000
#define EGIS0570_PKTSIZE 7
#define EGIS0570_INIT_TOTAL (sizeof ((init_pkts)) / sizeof ((init_pkts[0])))
static unsigned char init_pkts[][EGIS0570_PKTSIZE] =
{
{ 0x45, 0x47, 0x49, 0x53, 0x01, 0x20, 0x3f },
{ 0x45, 0x47, 0x49, 0x53, 0x01, 0x58, 0x3f },
{ 0x45, 0x47, 0x49, 0x53, 0x01, 0x21, 0x09 },
{ 0x45, 0x47, 0x49, 0x53, 0x01, 0x57, 0x09 },
{ 0x45, 0x47, 0x49, 0x53, 0x01, 0x22, 0x03 },
{ 0x45, 0x47, 0x49, 0x53, 0x01, 0x56, 0x03 },
{ 0x45, 0x47, 0x49, 0x53, 0x01, 0x23, 0x01 },
{ 0x45, 0x47, 0x49, 0x53, 0x01, 0x55, 0x01 },
{ 0x45, 0x47, 0x49, 0x53, 0x01, 0x24, 0x01 },
{ 0x45, 0x47, 0x49, 0x53, 0x01, 0x54, 0x01 },
{ 0x45, 0x47, 0x49, 0x53, 0x01, 0x16, 0x3e },
{ 0x45, 0x47, 0x49, 0x53, 0x01, 0x09, 0x0b },
{ 0x45, 0x47, 0x49, 0x53, 0x01, 0x14, 0x03 },
{ 0x45, 0x47, 0x49, 0x53, 0x01, 0x15, 0x00 },
{ 0x45, 0x47, 0x49, 0x53, 0x01, 0x02, 0x0f },
{ 0x45, 0x47, 0x49, 0x53, 0x01, 0x10, 0x00 },
{ 0x45, 0x47, 0x49, 0x53, 0x01, 0x11, 0x38 },
{ 0x45, 0x47, 0x49, 0x53, 0x01, 0x12, 0x00 },
{ 0x45, 0x47, 0x49, 0x53, 0x01, 0x13, 0x71 },
{ 0x45, 0x47, 0x49, 0x53, 0x01, 0x03, 0x80 },
{ 0x45, 0x47, 0x49, 0x53, 0x00, 0x02, 0x80 },
{ 0x45, 0x47, 0x49, 0x53, 0x01, 0x02, 0x2f },
{ 0x45, 0x47, 0x49, 0x53, 0x06, 0x00, 0xfe } /* image returned after this packet */
};
/* There is another Packet !
* That just Work the same !!
* And the Size is different !!!
*/
/*
#define EGIS0570_INIT_TOTAL2 (sizeof((init_pkts2)) / sizeof((init_pkts2[0])))
static unsigned char init_pkts2[][EGIS0570_PKTSIZE] =
{
{0x45, 0x47, 0x49, 0x53, 0x01, 0x10, 0x00},
{0x45, 0x47, 0x49, 0x53, 0x01, 0x11, 0x38},
{0x45, 0x47, 0x49, 0x53, 0x01, 0x12, 0x00},
{0x45, 0x47, 0x49, 0x53, 0x01, 0x13, 0x71},
{0x45, 0x47, 0x49, 0x53, 0x01, 0x20, 0x3f},
{0x45, 0x47, 0x49, 0x53, 0x01, 0x58, 0x3f},
{0x45, 0x47, 0x49, 0x53, 0x01, 0x21, 0x07},
{0x45, 0x47, 0x49, 0x53, 0x01, 0x57, 0x07},
{0x45, 0x47, 0x49, 0x53, 0x01, 0x22, 0x02},
{0x45, 0x47, 0x49, 0x53, 0x01, 0x56, 0x02},
{0x45, 0x47, 0x49, 0x53, 0x01, 0x23, 0x00},
{0x45, 0x47, 0x49, 0x53, 0x01, 0x55, 0x00},
{0x45, 0x47, 0x49, 0x53, 0x01, 0x24, 0x00},
{0x45, 0x47, 0x49, 0x53, 0x01, 0x54, 0x00},
{0x45, 0x47, 0x49, 0x53, 0x01, 0x25, 0x00},
{0x45, 0x47, 0x49, 0x53, 0x01, 0x53, 0x00},
{0x45, 0x47, 0x49, 0x53, 0x01, 0x15, 0x00},
{0x45, 0x47, 0x49, 0x53, 0x01, 0x16, 0x3b},
{0x45, 0x47, 0x49, 0x53, 0x01, 0x09, 0x0a},
{0x45, 0x47, 0x49, 0x53, 0x01, 0x14, 0x00},
{0x45, 0x47, 0x49, 0x53, 0x01, 0x02, 0x0f},
{0x45, 0x47, 0x49, 0x53, 0x01, 0x03, 0x80},
{0x45, 0x47, 0x49, 0x53, 0x00, 0x02, 0x80},
{0x45, 0x47, 0x49, 0x53, 0x01, 0x02, 0x2f},
{0x45, 0x47, 0x49, 0x53, 0x06, 0x00, 0xfe}
};
*/
/*
* After sending initial packets device returns image data (32512 bytes)
* To ask device to send image data again, host needs to send four additional packets
* Further work is to repeatedly send four repeat packets and read image data
*/
#define EGIS0570_INPSIZE 32512
/* 5 image with captured in different time of size 114 * 57 = 6498
* 5 * 6498 = 32490 plus 22 extra unrecognized char size data
* Two continuous image in this 5 images may have time delay of less than 20ms
*/
#define EGIS0570_IMGSIZE 6498
#define EGIS0570_IMGWIDTH 114
#define EGIS0570_IMGHEIGHT 57
/* size of middle area that is used from each frame */
#define EGIS0570_RFMGHEIGHT 17
/* rows to ignore from top and bottom of the image*/
#define EGIS0570_RFMDIS (EGIS0570_IMGHEIGHT - EGIS0570_RFMGHEIGHT) / 2
#define EGIS0570_IMGCOUNT 5
/*
* Image repeat request
* First 4 bytes are the same as in initialization packets
* Have no idea what the other 3 bytes mean
*/
#define EGIS0570_REPEAT_TOTAL (sizeof ((repeat_pkts)) / sizeof ((repeat_pkts[0])))
static unsigned char repeat_pkts[][EGIS0570_PKTSIZE] =
{
{ 0x45, 0x47, 0x49, 0x53, 0x01, 0x02, 0x0f },
{ 0x45, 0x47, 0x49, 0x53, 0x00, 0x02, 0x0f },
{ 0x45, 0x47, 0x49, 0x53, 0x01, 0x02, 0x2f },
{ 0x45, 0x47, 0x49, 0x53, 0x06, 0x00, 0xfe } /* image returned after this packet */
};
/*
* This sensor is small so I decided to reduce bz3_threshold from
* 40 to 10 to have more success to fail ratio
* Bozorth3 Algorithm seems not fine at the end
* foreget about security :))
*/
#define EGIS0570_BZ3_THRESHOLD 25 /* and even less What a joke */
#define EGIS0570_MIN_MEAN 20
#define EGIS0570_MARGIN 3
#define EGIS0570_RESIZE 2
#endif

View File

@@ -760,7 +760,7 @@ calibrate_run_state (FpiSsm *ssm, FpDevice *dev)
if (self->calib_status == 0x00 &&
self->last_read[0] == 0x01)
self->calib_status = 0x01;
fpi_ssm_next_state_delayed (ssm, 50, NULL);
fpi_ssm_next_state_delayed (ssm, 50);
}
break;

View File

@@ -213,8 +213,12 @@ static const FpIdEntry elan_id_table[] = {
{.vid = ELAN_VEND_ID, .pid = 0x0c31, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c32, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c33, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c3d, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c42, .driver_data = ELAN_0C42},
{.vid = ELAN_VEND_ID, .pid = 0x0c4d, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c4f, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c63, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c6e, .driver_data = ELAN_ALL_DEV},
{.vid = 0, .pid = 0, .driver_data = 0},
};

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,195 @@
/*
* Copyright (C) 2021 Elan Microelectronics
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#pragma once
#include "fpi-device.h"
#include "fpi-ssm.h"
#include <libusb.h>
#include <stdio.h>
#include <stdlib.h>
G_DECLARE_FINAL_TYPE (FpiDeviceElanmoc, fpi_device_elanmoc, FPI, DEVICE_ELANMOC, FpDevice)
#define ELAN_MOC_DRIVER_FULLNAME "Elan MOC Sensors"
#define ELAN_M0C_CMD_LEN 0x3
#define ELAN_EP_CMD_OUT (0x1 | LIBUSB_ENDPOINT_OUT)
#define ELAN_EP_CMD_IN (0x3 | LIBUSB_ENDPOINT_IN)
#define ELAN_EP_MOC_CMD_IN (0x4 | LIBUSB_ENDPOINT_IN)
#define ELAN_EP_IMG_IN (0x2 | LIBUSB_ENDPOINT_IN)
#define ELAN_MOC_CMD_TIMEOUT 2000
#define ELAN_MOC_CAL_RETRY 500
#define ELAN_MOC_ENROLL_TIMES 9
#define ELAN_MAX_USER_ID_LEN 92
#define ELAN_MAX_ENROLL_NUM 9
#define ELAN_MSG_VERIFY_ERR 0xfd
#define ELAN_MSG_DIRTY 0xfb
#define ELAN_MSG_AREA_NOT_ENOUGH 0xfe
#define ELAN_MSG_TOO_HIGH 0x41
#define ELAN_MSG_TOO_LEFT 0x42
#define ELAN_MSG_TOO_LOW 0x43
#define ELAN_MSG_TOO_RIGHT 0x44
#define ELAN_MSG_OK 0x00
#define ELAN_MAX_HDR_LEN 3
#define ELAN_USERDATE_SIZE (ELAN_MAX_USER_ID_LEN + 3)
#define ELAN_MSG_DRIVER_VERSION "1004"
struct elanmoc_cmd
{
unsigned char cmd_header[ELAN_MAX_HDR_LEN];
int cmd_len;
int resp_len;
};
static const struct elanmoc_cmd fw_ver_cmd = {
.cmd_header = {0x40, 0x19},
.cmd_len = 2,
.resp_len = 2,
};
static const struct elanmoc_cmd sensor_dim_cmd = {
.cmd_header = {0x00, 0x0c},
.cmd_len = 2,
.resp_len = 4,
};
static const struct elanmoc_cmd cal_status_cmd = {
.cmd_header = {0x40, 0xff, 0x00},
.cmd_len = 3,
.resp_len = 2,
};
static const struct elanmoc_cmd enrolled_number_cmd = {
.cmd_header = {0x40, 0xff, 0x04},
.cmd_len = 3,
.resp_len = 2,
};
static const struct elanmoc_cmd elanmoc_verify_cmd = {
.cmd_header = {0x40, 0xff, 0x73},
.cmd_len = 5,
.resp_len = 2,
};
static const struct elanmoc_cmd elanmoc_above_cmd = {
.cmd_header = {0x40, 0xff, 0x02},
.cmd_len = 3,
.resp_len = 0,
};
static const struct elanmoc_cmd elanmoc_enroll_cmd = {
.cmd_header = {0x40, 0xff, 0x01},
.cmd_len = 7,
.resp_len = 2,
};
static const struct elanmoc_cmd elanmoc_delete_cmd = {
.cmd_header = {0x40, 0xff, 0x13},
.cmd_len = 128,
.resp_len = 2,
};
static const struct elanmoc_cmd elanmoc_enroll_commit_cmd = {
.cmd_header = {0x40, 0xff, 0x11},
.cmd_len = 128,
.resp_len = 2,
};
static const struct elanmoc_cmd elanmoc_remove_all_cmd = {
.cmd_header = {0x40, 0xff, 0x98},
.cmd_len = 3,
.resp_len = 2,
};
static const struct elanmoc_cmd elanmoc_get_userid_cmd = {
.cmd_header = {0x43, 0x21, 0x00},
.cmd_len = 3,
.resp_len = 97,
};
static const struct elanmoc_cmd elanmoc_set_mod_cmd = {
.cmd_header = {0x40, 0xff, 0x14},
.cmd_len = 4,
.resp_len = 2,
};
static const struct elanmoc_cmd elanmoc_check_reenroll_cmd = {
.cmd_header = {0x40, 0xff, 0x22},
.cmd_len = 5,
.resp_len = 2,
};
typedef void (*ElanCmdMsgCallback) (FpiDeviceElanmoc *self,
GError *error);
enum moc_enroll_states {
MOC_ENROLL_GET_ENROLLED_NUM,
MOC_ENROLL_REENROLL_CHECK,
MOC_ENROLL_WAIT_FINGER,
MOC_ENROLL_COMMIT_RESULT,
MOC_ENROLL_NUM_STATES,
};
enum moc_list_states {
MOC_LIST_GET_ENROLLED,
MOC_LIST_GET_FINGER,
MOC_LIST_NUM_STATES,
};
enum delete_states {
DELETE_SEND_CMD,
DELETE_NUM_STATES,
};
enum dev_init_states {
DEV_WAIT_READY,
DEV_SET_MODE,
DEV_GET_VER,
DEV_GET_DIM,
DEV_GET_ENROLLED,
DEV_INIT_STATES,
};
enum dev_exit_states {
DEV_EXIT_ABOVE,
DEV_EXIT_STATES,
};
struct _FpiDeviceElanmoc
{
FpDevice parent;
FpiSsm *task_ssm;
FpiSsm *cmd_ssm;
FpiUsbTransfer *cmd_transfer;
gboolean cmd_cancelable;
gsize cmd_len_in;
unsigned short fw_ver;
unsigned char x_trace;
unsigned char y_trace;
int num_frames;
int curr_enrolled;
int cancel_result;
int cmd_retry_cnt;
int list_index;
GPtrArray *list_result;
};

1700
libfprint/drivers/elanspi.c Normal file

File diff suppressed because it is too large Load Diff

351
libfprint/drivers/elanspi.h Normal file
View File

@@ -0,0 +1,351 @@
/*
* Elan SPI driver for libfprint
*
* Copyright (C) 2021 Matthew Mirvish <matthew@mm12.xyz>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#pragma once
#include <config.h>
#ifndef HAVE_UDEV
#error "elanspi requires udev"
#endif
#include <fp-device.h>
#include <fpi-device.h>
#define ELANSPI_TP_PID 0x04f3
/* Sensor ID information copied from the windows driver */
struct elanspi_sensor_entry
{
unsigned char sensor_id, height, width, ic_version;
gboolean is_otp_model;
const gchar * name;
};
static const struct elanspi_sensor_entry elanspi_sensor_table[] = {
{0x0, 0x78, 0x78, 0x0, 0x0, "eFSA120S"},
{0x1, 0x78, 0x78, 0x1, 0x1, "eFSA120SA"},
{0x2, 0xA0, 0xA0, 0x0, 0x0, "eFSA160S"},
{0x3, 0xd0, 0x50, 0x0, 0x0, "eFSA820R"},
{0x4, 0xC0, 0x38, 0x0, 0x0, "eFSA519R"},
{0x5, 0x60, 0x60, 0x0, 0x0, "eFSA96S"},
{0x6, 0x60, 0x60, 0x1, 0x1, "eFSA96SA"},
{0x7, 0x60, 0x60, 0x2, 0x1, "eFSA96SB"},
{0x8, 0xa0, 0x50, 0x1, 0x1, "eFSA816RA"},
{0x9, 0x90, 0x40, 0x1, 0x1, "eFSA614RA"},
{0xA, 0x90, 0x40, 0x2, 0x1, "eFSA614RB"},
{0xB, 0x40, 0x58, 0x1, 0x1, "eFSA688RA"},
{0xC, 0x50, 0x50, 0x1, 0x0, "eFSA80SA"},
{0xD, 0x47, 0x80, 0x1, 0x1, "eFSA712RA"},
{0xE, 0x50, 0x50, 0x2, 0x0, "eFSA80SC"},
{0, 0, 0, 0, 0, NULL}
};
struct elanspi_reg_entry
{
unsigned char addr, value;
/* terminates with 0xFF, 0xFF since register 0x0 is valid */
};
struct elanspi_regtable
{
const struct elanspi_reg_entry *other;
struct
{
unsigned char sid;
const struct elanspi_reg_entry *table;
} entries[];
};
static const struct elanspi_reg_entry elanspi_calibration_table_default[] = {
{0x05, 0x60},
{0x06, 0xc0},
{0x07, 0x80},
{0x08, 0x04},
{0x0a, 0x97},
{0x0b, 0x72},
{0x0c, 0x69},
{0x0f, 0x2a},
{0x11, 0x2a},
{0x13, 0x27},
{0x15, 0x67},
{0x18, 0x04},
{0x21, 0x20},
{0x22, 0x36},
{0x2a, 0x5f},
{0x2b, 0xc0},
{0x2e, 0xff},
{0xff, 0xff}
};
static const struct elanspi_reg_entry elanspi_calibration_table_id567[] = {
{0x2A, 0x07},
{0x5, 0x60},
{0x6, 0xC0},
{0x7, 0x80},
{0x8, 0x04},
{0xA, 0x97},
{0xB, 0x72},
{0xC, 0x69},
{0xF, 0x2A},
{0x11, 0x2A},
{0x13, 0x27},
{0x15, 0x67},
{0x18, 0x04},
{0x21, 0x20},
{0x22, 0x36},
{0x2A, 0x5F},
{0x2B, 0xC0},
{0x2E, 0xFF},
{0xff, 0xff}
};
static const struct elanspi_reg_entry elanspi_calibration_table_id0[] = {
{0x5, 0x60},
{0x6, 0xC0},
{0x8, 0x04},
{0xA, 0x97},
{0xB, 0x72},
{0xC, 0x69},
{0xF, 0x2B},
{0x11, 0x2B},
{0x13, 0x28},
{0x15, 0x28},
{0x18, 0x04},
{0x21, 0x20},
{0x2A, 0x4B},
{0xff, 0xff}
};
// old style sensor calibration, with only one page of registers
static const struct elanspi_regtable elanspi_calibration_table_old = {
.other = elanspi_calibration_table_default,
.entries = {
{ .sid = 0x0, .table = elanspi_calibration_table_id0 },
{ .sid = 0x5, .table = elanspi_calibration_table_id567 },
{ .sid = 0x6, .table = elanspi_calibration_table_id567 },
{ .sid = 0x7, .table = elanspi_calibration_table_id567 },
{ .sid = 0x0, .table = NULL }
}
};
// new style sensor calibration, with two pages of registers
static const struct elanspi_reg_entry elanspi_calibration_table_page0_id14[] = {
{0x00, 0x5a},
{0x01, 0x00},
{0x02, 0x4f},
{0x03, 0x00},
{0x04, 0x4f},
{0x05, 0xa0},
{0x06, 0x00},
{0x07, 0x00},
{0x08, 0x00},
{0x09, 0x04},
{0x0a, 0x74},
{0x0b, 0x05},
{0x0c, 0x08},
{0x0d, 0x00},
{0x0e, 0x00},
{0x0f, 0x14},
{0x10, 0x3c},
{0x11, 0x41},
{0x12, 0x0c},
{0x13, 0x00},
{0x14, 0x00},
{0x15, 0x04},
{0x16, 0x02},
{0x17, 0x00},
{0x18, 0x01},
{0x19, 0xf4},
{0x1a, 0x00},
{0x1b, 0x00},
{0x1c, 0x00},
{0x1d, 0x00},
{0x1e, 0x00},
{0x1f, 0x00},
{0x20, 0x00},
{0x21, 0x80},
{0x22, 0x06},
{0x23, 0x00},
{0x24, 0x00},
{0x25, 0x00},
{0x26, 0x00},
{0x27, 0x00},
{0x28, 0x00},
{0x29, 0x04},
{0x2a, 0x5f},
{0x2b, 0xe2},
{0x2c, 0xa0},
{0x2d, 0x00},
{0x2e, 0xff},
{0x2f, 0x40},
{0x30, 0x01},
{0x31, 0x38},
{0x32, 0x00},
{0x33, 0x00},
{0x34, 0x00},
{0x35, 0x1f},
{0x36, 0xff},
{0x37, 0x00},
{0x38, 0x00},
{0x39, 0x00},
{0x3a, 0x00},
{0xff, 0xff}
};
static const struct elanspi_reg_entry elanspi_calibration_table_page1_id14[] = {
{0x00, 0x7b},
{0x01, 0x7f},
{0x02, 0x77},
{0x03, 0xd4},
{0x04, 0x7d},
{0x05, 0x19},
{0x06, 0x80},
{0x07, 0x40},
{0x08, 0x11},
{0x09, 0x00},
{0x0a, 0x00},
{0x0b, 0x14},
{0x0c, 0x00},
{0x0d, 0x00},
{0x0e, 0x32},
{0x0f, 0x02},
{0x10, 0x08},
{0x11, 0x6c},
{0x12, 0x00},
{0x13, 0x00},
{0x14, 0x32},
{0x15, 0x01},
{0x16, 0x16},
{0x17, 0x01},
{0x18, 0x14},
{0x19, 0x01},
{0x1a, 0x16},
{0x1b, 0x01},
{0x1c, 0x17},
{0x1d, 0x01},
{0x1e, 0x0a},
{0x1f, 0x01},
{0x20, 0x0a},
{0x21, 0x02},
{0x22, 0x08},
{0x23, 0x29},
{0x24, 0x00},
{0x25, 0x0c},
{0x26, 0x1a},
{0x27, 0x30},
{0x28, 0x1a},
{0x29, 0x30},
{0x2a, 0x00},
{0x2b, 0x00},
{0x2c, 0x01},
{0x2d, 0x16},
{0x2e, 0x01},
{0x2f, 0x17},
{0x30, 0x03},
{0x31, 0x2d},
{0x32, 0x03},
{0x33, 0x2d},
{0x34, 0x14},
{0x35, 0x00},
{0x36, 0x00},
{0x37, 0x00},
{0x38, 0x00},
{0x39, 0x03},
{0x3a, 0xfe},
{0x3b, 0x00},
{0x3c, 0x00},
{0x3d, 0x02},
{0x3e, 0x00},
{0x3f, 0x00},
{0xff, 0xff}
};
static const struct elanspi_regtable elanspi_calibration_table_new_page0 = {
.other = NULL,
.entries = {
{ .sid = 0xe, .table = elanspi_calibration_table_page0_id14 },
{ .sid = 0x0, .table = NULL }
}
};
static const struct elanspi_regtable elanspi_calibration_table_new_page1 = {
.other = NULL,
.entries = {
{ .sid = 0xe, .table = elanspi_calibration_table_page1_id14 },
{ .sid = 0x0, .table = NULL }
}
};
#define ELANSPI_NO_ROTATE 0
#define ELANSPI_90LEFT_ROTATE 1
#define ELANSPI_180_ROTATE 2
#define ELANSPI_90RIGHT_ROTATE 3
#define ELANSPI_HV_FLIPPED 1
#define ELANSPI_UDEV_TYPES FPI_DEVICE_UDEV_SUBTYPE_SPIDEV | FPI_DEVICE_UDEV_SUBTYPE_HIDRAW
#define ELANSPI_TP_VID 0x04f3
// using checkargs ACPI:HIDPID
static const FpIdEntry elanspi_id_table[] = {
{.udev_types = ELANSPI_UDEV_TYPES, .spi_acpi_id = "ELAN7001", .hid_id = {.vid = ELANSPI_TP_VID, .pid = 0x3057}, .driver_data = ELANSPI_180_ROTATE},
{.udev_types = ELANSPI_UDEV_TYPES, .spi_acpi_id = "ELAN7001", .hid_id = {.vid = ELANSPI_TP_VID, .pid = 0x3087}, .driver_data = ELANSPI_180_ROTATE},
{.udev_types = ELANSPI_UDEV_TYPES, .spi_acpi_id = "ELAN7001", .hid_id = {.vid = ELANSPI_TP_VID, .pid = 0x30c6}, .driver_data = ELANSPI_180_ROTATE},
{.udev_types = ELANSPI_UDEV_TYPES, .spi_acpi_id = "ELAN70A1", .hid_id = {.vid = ELANSPI_TP_VID, .pid = 0x3134}, .driver_data = ELANSPI_90LEFT_ROTATE},
{.udev_types = ELANSPI_UDEV_TYPES, .spi_acpi_id = "ELAN7001", .hid_id = {.vid = ELANSPI_TP_VID, .pid = 0x3148}, .driver_data = ELANSPI_180_ROTATE},
{.udev_types = ELANSPI_UDEV_TYPES, .spi_acpi_id = "ELAN7001", .hid_id = {.vid = ELANSPI_TP_VID, .pid = 0x30b2}, .driver_data = ELANSPI_NO_ROTATE},
{.udev_types = ELANSPI_UDEV_TYPES, .spi_acpi_id = "ELAN70A1", .hid_id = {.vid = ELANSPI_TP_VID, .pid = 0x30b2}, .driver_data = ELANSPI_NO_ROTATE},
{.udev_types = ELANSPI_UDEV_TYPES, .spi_acpi_id = "ELAN7001", .hid_id = {.vid = ELANSPI_TP_VID, .pid = 0x309f}, .driver_data = ELANSPI_180_ROTATE},
{.udev_types = 0}
};
#define ELANSPI_MAX_OLD_STAGE1_CALIBRATION_MEAN 1000
#define ELANSPI_MIN_OLD_STAGE2_CALBIRATION_MEAN 3000
#define ELANSPI_MAX_OLD_STAGE2_CALBIRATION_MEAN 8000
#define ELANSPI_HV_CALIBRATION_TARGET_MEAN 3000
#define ELANSPI_MIN_EMPTY_INVALID_PERCENT 6
#define ELANSPI_MAX_REAL_INVALID_PERCENT 3
#define ELANSPI_MIN_REAL_STDDEV (592 * 592)
#define ELANSPI_MAX_EMPTY_STDDEV (350 * 350)
#define ELANSPI_MIN_FRAMES_DEBOUNCE 2
#define ELANSPI_SWIPE_FRAMES_DISCARD 1
#define ELANSPI_MIN_FRAMES_SWIPE (7 + ELANSPI_SWIPE_FRAMES_DISCARD)
#define ELANSPI_MAX_FRAMES_SWIPE (20 + ELANSPI_SWIPE_FRAMES_DISCARD)
#define ELANSPI_MAX_FRAME_HEIGHT 43
#define ELANSPI_MIN_FRAME_TO_FRAME_DIFF (250 * 250)
#define ELANSPI_HV_SENSOR_FRAME_DELAY 23
#define ELANSPI_OTP_TIMEOUT_USEC (12 * 1000)
#define ELANSPI_OLD_CAPTURE_TIMEOUT_USEC (100 * 1000)
#define ELANSPI_HV_CAPTURE_TIMEOUT_USEC (50 * 1000)

View File

@@ -54,7 +54,6 @@ struct _FpiDeviceGoodixMoc
gint enroll_stage;
gint max_enroll_stage;
gint max_stored_prints;
GCancellable *cancellable;
GPtrArray *list_result;
guint8 template_id[TEMPLATE_ID_SIZE];
gboolean is_enroll_identify;
@@ -220,7 +219,7 @@ fp_cmd_run_state (FpiSsm *ssm,
fpi_usb_transfer_fill_bulk (transfer, EP_IN, EP_IN_MAX_BUF_SIZE);
fpi_usb_transfer_submit (transfer,
self->cmd_cancelable ? 0 : DATA_TIMEOUT,
self->cmd_cancelable ? self->cancellable : NULL,
self->cmd_cancelable ? fpi_device_get_cancellable (dev) : NULL,
fp_cmd_receive_cb,
fpi_ssm_get_data (ssm));
break;
@@ -1318,6 +1317,10 @@ gx_fp_probe (FpDevice *device)
{
case 0x6496:
case 0x60A2:
case 0x609C:
case 0x639C:
case 0x63AC:
case 0x6A94:
self->max_enroll_stage = 12;
break;
@@ -1348,8 +1351,6 @@ gx_fp_init (FpDevice *device)
self->max_stored_prints = FP_MAX_FINGERNUM;
self->is_power_button_shield_on = false;
self->cancellable = g_cancellable_new ();
self->sensorcfg = g_new0 (gxfp_sensor_cfg_t, 1);
ret = gx_proto_init_sensor_config (self->sensorcfg);
@@ -1387,7 +1388,6 @@ gx_fp_release_interface (FpiDeviceGoodixMoc *self,
{
g_autoptr(GError) release_error = NULL;
g_clear_object (&self->cancellable);
g_clear_pointer (&self->sensorcfg, g_free);
/* Release usb interface */
@@ -1443,8 +1443,10 @@ gx_fp_verify_identify (FpDevice *device)
{
FpiDeviceGoodixMoc *self = FPI_DEVICE_GOODIXMOC (device);
self->task_ssm = fpi_ssm_new (device, fp_verify_sm_run_state,
FP_VERIFY_NUM_STATES);
self->task_ssm = fpi_ssm_new_full (device, fp_verify_sm_run_state,
FP_VERIFY_NUM_STATES,
FP_VERIFY_PWR_BTN_SHIELD_OFF,
"verify");
fpi_ssm_start (self->task_ssm, fp_verify_ssm_done);
@@ -1459,8 +1461,10 @@ gx_fp_enroll (FpDevice *device)
self->enroll_stage = 0;
self->is_enroll_identify = true;
self->task_ssm = fpi_ssm_new (device, fp_enroll_sm_run_state,
FP_ENROLL_NUM_STATES);
self->task_ssm = fpi_ssm_new_full (device, fp_enroll_sm_run_state,
FP_ENROLL_NUM_STATES,
FP_ENROLL_PWR_BTN_SHIELD_OFF,
"enroll");
fpi_ssm_start (self->task_ssm, fp_enroll_ssm_done);
@@ -1533,27 +1537,19 @@ fpi_device_goodixmoc_init (FpiDeviceGoodixMoc *self)
}
static void
gx_fp_cancel (FpDevice *device)
{
FpiDeviceGoodixMoc *self = FPI_DEVICE_GOODIXMOC (device);
/* Cancel any current interrupt transfer (resulting us to go into
* response reading mode again); then create a new cancellable
* for the next transfers. */
g_cancellable_cancel (self->cancellable);
g_clear_object (&self->cancellable);
self->cancellable = g_cancellable_new ();
}
static const FpIdEntry id_table[] = {
{ .vid = 0x27c6, .pid = 0x5840, },
{ .vid = 0x27c6, .pid = 0x6496, },
{ .vid = 0x27c6, .pid = 0x609C, },
{ .vid = 0x27c6, .pid = 0x60A2, },
{ .vid = 0x27c6, .pid = 0x63AC, },
{ .vid = 0x27c6, .pid = 0x639C, },
{ .vid = 0x27c6, .pid = 0x63AC, },
{ .vid = 0x27c6, .pid = 0x6496, },
{ .vid = 0x27c6, .pid = 0x6584, },
{ .vid = 0x27c6, .pid = 0x658C, },
{ .vid = 0x27c6, .pid = 0x6592, },
{ .vid = 0x27c6, .pid = 0x6594, },
{ .vid = 0x27c6, .pid = 0x659C, },
{ .vid = 0x27c6, .pid = 0x6A94, },
{ .vid = 0, .pid = 0, .driver_data = 0 }, /* terminating entry */
};
@@ -1576,10 +1572,9 @@ fpi_device_goodixmoc_class_init (FpiDeviceGoodixMocClass *klass)
dev_class->enroll = gx_fp_enroll;
dev_class->delete = gx_fp_template_delete;
dev_class->list = gx_fp_template_list;
dev_class->cancel = gx_fp_cancel;
dev_class->verify = gx_fp_verify_identify;
dev_class->identify = gx_fp_verify_identify;
fpi_device_class_auto_initialize_features (dev_class);
dev_class->features |= FPI_DEVICE_FEATURE_DUPLICATES_CHECK;
dev_class->features |= FP_DEVICE_FEATURE_DUPLICATES_CHECK;
}

View File

@@ -353,7 +353,7 @@ m_loop_state (FpiSsm *ssm, FpDevice *_dev)
{
case M_WAIT_PRINT:
/* Wait fingerprint scanning */
fpi_ssm_next_state_delayed (ssm, NB1010_TRANSITION_DELAY, NULL);
fpi_ssm_next_state_delayed (ssm, NB1010_TRANSITION_DELAY);
break;
case M_REQUEST_PRINT:

View File

@@ -468,6 +468,7 @@ typedef union
bmkt_del_all_users_resp_t del_all_users_resp;
bmkt_enroll_templates_resp_t enroll_templates_resp;
bmkt_del_user_resp_t del_user_resp;
bmkt_del_all_users_resp_t del_all_user_resp;
bmkt_enrolled_fingers_resp_t enrolled_fingers_resp;
} bmkt_response_data_t;

View File

@@ -32,13 +32,14 @@ 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 = 0x00E9, },
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x00DF, },
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x00F9, },
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x00FC, },
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x00C2, },
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x00C9, },
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0100, },
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x00F0, },
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0103, },
{ .vid = 0, .pid = 0, .driver_data = 0 }, /* terminating entry */
};
@@ -460,7 +461,7 @@ create_print (FpiDeviceSynaptics *self,
guint8 finger_id)
{
FpPrint *print;
g_autofree gchar *user_id_safe;
g_autofree gchar *user_id_safe = NULL;
GVariant *data = NULL;
GVariant *uid = NULL;
@@ -485,100 +486,6 @@ create_print (FpiDeviceSynaptics *self,
return print;
}
static void
list_msg_cb (FpiDeviceSynaptics *self,
bmkt_response_t *resp,
GError *error)
{
bmkt_enroll_templates_resp_t *get_enroll_templates_resp;
if (error)
{
g_clear_pointer (&self->list_result, g_ptr_array_unref);
fpi_device_list_complete (FP_DEVICE (self), NULL, error);
return;
}
get_enroll_templates_resp = &resp->response.enroll_templates_resp;
switch (resp->response_id)
{
case BMKT_RSP_QUERY_FAIL:
if (resp->result == BMKT_FP_DATABASE_EMPTY)
{
fp_info ("Database is empty");
fpi_device_list_complete (FP_DEVICE (self),
g_steal_pointer (&self->list_result),
NULL);
}
else
{
fp_info ("Failed to query enrolled users: %d", resp->result);
g_clear_pointer (&self->list_result, g_ptr_array_unref);
fpi_device_list_complete (FP_DEVICE (self),
NULL,
fpi_device_error_new_msg (FP_DEVICE_ERROR_GENERAL,
"Failed to query enrolled users: %d",
resp->result));
}
break;
case BMKT_RSP_QUERY_RESPONSE_COMPLETE:
fp_info ("Query complete!");
fpi_device_list_complete (FP_DEVICE (self),
g_steal_pointer (&self->list_result),
NULL);
break;
case BMKT_RSP_TEMPLATE_RECORDS_REPORT:
for (int n = 0; n < BMKT_MAX_NUM_TEMPLATES_INTERNAL_FLASH; n++)
{
FpPrint *print;
if (get_enroll_templates_resp->templates[n].user_id_len == 0)
continue;
fp_info ("![query %d of %d] template %d: status=0x%x, userId=%s, fingerId=%d",
get_enroll_templates_resp->query_sequence,
get_enroll_templates_resp->total_query_messages,
n,
get_enroll_templates_resp->templates[n].template_status,
get_enroll_templates_resp->templates[n].user_id,
get_enroll_templates_resp->templates[n].finger_id);
print = create_print (self,
get_enroll_templates_resp->templates[n].user_id,
get_enroll_templates_resp->templates[n].finger_id);
g_ptr_array_add (self->list_result, g_object_ref_sink (print));
}
synaptics_sensor_cmd (self,
self->cmd_seq_num,
BMKT_CMD_GET_NEXT_QUERY_RESPONSE,
NULL,
0,
NULL);
break;
}
}
static void
list (FpDevice *device)
{
FpiDeviceSynaptics *self = FPI_DEVICE_SYNAPTICS (device);
G_DEBUG_HERE ();
self->list_result = g_ptr_array_new_with_free_func (g_object_unref);
synaptics_sensor_cmd (self, 0, BMKT_CMD_GET_TEMPLATE_RECORDS, NULL, 0, list_msg_cb);
}
static void
verify_complete_after_finger_removal (FpiDeviceSynaptics *self)
{
@@ -810,6 +717,21 @@ identify_msg_cb (FpiDeviceSynaptics *self,
static void
identify (FpDevice *device)
{
GPtrArray *prints = NULL;
fpi_device_get_identify_data (device, &prints);
/* Identify over no prints does not work for synaptics.
* This *may* make sense for other devices though, as identify may return
* a matched print even if it is not in the list of prints.
*/
if (prints->len == 0)
{
fpi_device_identify_report (device, NULL, NULL, NULL);
fpi_device_identify_complete (device, NULL);
return;
}
init_identify_msg (device);
compose_and_send_identify_msg (device);
}
@@ -1085,13 +1007,18 @@ delete_msg_cb (FpiDeviceSynaptics *self,
break;
case BMKT_RSP_DEL_USER_FP_FAIL:
fp_info ("Failed to delete enrolled user: %d", resp->result);
if (resp->result == BMKT_FP_DATABASE_NO_RECORD_EXISTS)
fpi_device_delete_complete (device,
fpi_device_error_new (FP_DEVICE_ERROR_DATA_NOT_FOUND));
if (resp->result == BMKT_FP_DATABASE_NO_RECORD_EXISTS ||
resp->result == BMKT_FP_DATABASE_EMPTY)
{
fp_info ("Database no record");
fpi_device_delete_complete (device, NULL);
}
else
{
fp_info ("Failed to delete enrolled user: %d", resp->result);
fpi_device_delete_complete (device,
fpi_device_error_new (FP_DEVICE_ERROR_GENERAL));
}
break;
case BMKT_RSP_DEL_USER_FP_OK:
@@ -1133,6 +1060,54 @@ delete_print (FpDevice *device)
synaptics_sensor_cmd (self, 0, BMKT_CMD_DEL_USER_FP, payload, user_id_len + 1, delete_msg_cb);
}
static void
clear_storage_msg_cb (FpiDeviceSynaptics *self,
bmkt_response_t *resp,
GError *error)
{
FpDevice *device = FP_DEVICE (self);
bmkt_del_all_users_resp_t *del_all_user_resp;
if (error)
{
fpi_device_clear_storage_complete (device, error);
return;
}
del_all_user_resp = &resp->response.del_all_user_resp;
switch (resp->response_id)
{
case BMKT_RSP_DELETE_PROGRESS:
fp_info ("Deleting All Enrolled Users is %d%% complete",
del_all_user_resp->progress);
break;
case BMKT_RSP_DEL_FULL_DB_FAIL:
if (resp->result == BMKT_FP_DATABASE_EMPTY)
fpi_device_clear_storage_complete (device, NULL);
else
fpi_device_clear_storage_complete (device,
fpi_device_error_new (FP_DEVICE_ERROR_GENERAL));
break;
case BMKT_RSP_DEL_FULL_DB_OK:
fp_info ("Successfully deleted all enrolled user");
fpi_device_clear_storage_complete (device, NULL);
break;
}
}
static void
clear_storage (FpDevice *device)
{
FpiDeviceSynaptics *self = FPI_DEVICE_SYNAPTICS (device);
g_debug ("clear all prints in database");
synaptics_sensor_cmd (self, 0, BMKT_CMD_DEL_FULL_DB, NULL, 0, clear_storage_msg_cb);
return;
}
static void
prob_msg_cb (FpiDeviceSynaptics *self,
bmkt_response_t *resp,
@@ -1140,14 +1115,18 @@ prob_msg_cb (FpiDeviceSynaptics *self,
{
GUsbDevice *usb_dev = NULL;
g_autofree gchar *serial = NULL;
GError *err = NULL;
usb_dev = fpi_device_get_usb_device (FP_DEVICE (self));
if (error)
{
if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
err = fpi_device_error_new_msg (FP_DEVICE_ERROR_GENERAL, "unsupported firmware version");
g_usb_device_close (usb_dev, NULL);
fpi_device_probe_complete (FP_DEVICE (self), NULL, NULL,
fpi_device_error_new_msg (FP_DEVICE_ERROR_GENERAL, "unsupported firmware version"));
fpi_device_probe_complete (FP_DEVICE (self), NULL, NULL, err);
g_clear_error (&error);
return;
}
@@ -1156,13 +1135,17 @@ prob_msg_cb (FpiDeviceSynaptics *self,
else
serial = g_usb_device_get_string_descriptor (usb_dev,
g_usb_device_get_serial_number_index (usb_dev),
&error);
&err);
/* BMKT_OPERATION_DENIED is returned if the sensor is already initialized */
if (resp->result == BMKT_SUCCESS || resp->result == BMKT_OPERATION_DENIED)
{
g_usb_device_close (usb_dev, NULL);
fpi_device_probe_complete (FP_DEVICE (self), serial, NULL, error);
fpi_device_probe_complete (FP_DEVICE (self), serial, NULL, err);
}
else if (resp->result == BMKT_FP_SYSTEM_BUSY)
{
synaptics_sensor_cmd (self, self->cmd_seq_num, BMKT_CMD_CANCEL_OP, NULL, 0, NULL);
}
else
{
@@ -1285,6 +1268,9 @@ fps_init_msg_cb (FpiDeviceSynaptics *self,
{
if (error)
{
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
g_clear_error (&error);
fpi_device_open_complete (FP_DEVICE (self), error);
return;
}
@@ -1294,6 +1280,10 @@ fps_init_msg_cb (FpiDeviceSynaptics *self,
{
fpi_device_open_complete (FP_DEVICE (self), NULL);
}
else if (resp->result == BMKT_FP_SYSTEM_BUSY)
{
synaptics_sensor_cmd (self, self->cmd_seq_num, BMKT_CMD_CANCEL_OP, NULL, 0, NULL);
}
else
{
g_warning ("Initializing fingerprint sensor failed with %d!", resp->result);
@@ -1403,8 +1393,8 @@ fpi_device_synaptics_class_init (FpiDeviceSynapticsClass *klass)
dev_class->identify = identify;
dev_class->enroll = enroll;
dev_class->delete = delete_print;
dev_class->clear_storage = clear_storage;
dev_class->cancel = cancel;
dev_class->list = list;
fpi_device_class_auto_initialize_features (dev_class);
}

View File

@@ -1,21 +1,24 @@
/*
* LGPL CRC code copied from GStreamer-0.10.10:
* Code copied from gstreamer-plugins-bad gst/gdp/dataprotocol.c
*
* Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
* Copyright (C) 2004,2006 Thomas Vander Stichele <thomas at apestaart dot org>
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; version
* 2.1 of the License.
* Copyright (C) 2014 Tim-Philipp Müller <tim centricular com>
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* 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
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA
*/
#include "upek_proto.h"

View File

@@ -1,21 +1,24 @@
/*
* LGPL CRC code copied from GStreamer-0.10.10:
* Code copied from gstreamer-plugins-bad gst/gdp/dataprotocol.c
*
* Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
* Copyright (C) 2004,2006 Thomas Vander Stichele <thomas at apestaart dot org>
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; version
* 2.1 of the License.
* Copyright (C) 2014 Tim-Philipp Müller <tim centricular com>
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* 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
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA
*/
#include <stdint.h>

View File

@@ -79,7 +79,7 @@ struct _FpiDeviceUpeksonly
int num_flying;
GSList *rows;
size_t num_rows;
unsigned num_rows;
unsigned char *rowbuf;
int rowbuf_offset;
@@ -176,6 +176,7 @@ last_transfer_killed (FpImageDevice *dev)
fpi_image_device_session_error (dev, g_steal_pointer (&self->kill_error));
return;
case NOT_KILLING:
default:
return;
}
@@ -214,7 +215,7 @@ handoff_img (FpImageDevice *dev)
self->rows = g_slist_reverse (self->rows);
fp_dbg ("%lu rows", self->num_rows);
fp_dbg ("%u rows", self->num_rows);
img = fpi_assemble_lines (&self->assembling_ctx, self->rows, self->num_rows);
g_slist_free_full (self->rows, g_free);
@@ -294,7 +295,7 @@ row_complete (FpImageDevice *dev)
if (self->num_blank > FINGER_REMOVED_THRESHOLD)
{
self->finger_state = FINGER_REMOVED;
fp_dbg ("detected finger removal. Blank rows: %d, Full rows: %lu",
fp_dbg ("detected finger removal. Blank rows: %d, Full rows: %u",
self->num_blank, self->num_rows);
handoff_img (dev);
return;

View File

@@ -411,7 +411,7 @@ dev_init (FpImageDevice *dev)
break;
default:
fp_err ("Device variant %lu is not known", driver_data);
fp_err ("Device variant %" G_GUINT64_FORMAT " is not known", driver_data);
g_assert_not_reached ();
fpi_image_device_open_complete (dev, fpi_device_error_new (FP_DEVICE_ERROR_GENERAL));
return;

View File

@@ -221,7 +221,7 @@ capture_read_data_cb (FpiUsbTransfer *transfer, FpDevice *device,
if (response_size > transfer->actual_length)
{
fp_dbg ("response_size is %lu, actual_length is %d",
response_size, (gint) transfer->actual_length);
(gulong) response_size, (gint) transfer->actual_length);
fp_dbg ("Waiting for rest of transfer");
BUG_ON (self->response_rest);
self->response_rest = response_size - transfer->actual_length;
@@ -309,7 +309,7 @@ capture_read_data_cb (FpiUsbTransfer *transfer, FpDevice *device,
data);
BUG_ON (self->image_size != IMAGE_SIZE);
fp_dbg ("Image size is %lu",
self->image_size);
(gulong) self->image_size);
img = fp_image_new (IMAGE_WIDTH, IMAGE_HEIGHT);
img->flags |= FPI_IMAGE_PARTIAL;
memcpy (img->data, self->image_bits,

View File

@@ -10,19 +10,20 @@
* Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
* Copyright (C) 2004,2006 Thomas Vander Stichele <thomas at apestaart dot org>
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; version
* 2.1 of the License.
* This library is free software; you can redistribute it and/or modify
* 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
* 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
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA
*/
#define FP_COMPONENT "upekts"
@@ -365,7 +366,7 @@ read_msg_cb (FpiUsbTransfer *transfer, FpDevice *device,
fp_err ("async msg read too short (%d)",
(gint) transfer->actual_length);
error = fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
"Packet from device was too short (%lu)",
"Packet from device was too short (%" G_GSSIZE_FORMAT ")",
transfer->actual_length);
goto err;
}
@@ -992,7 +993,7 @@ e_handle_resp00 (FpDevice *dev, unsigned char *data,
if (data_len != 14)
{
fp_err ("received 3001 poll response of %lu bytes?", data_len);
fp_err ("received 3001 poll response of %" G_GSIZE_FORMAT " bytes?", data_len);
do_enroll_stop (dev, NULL,
fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
"received 3001 response with wrong length"));
@@ -1089,7 +1090,7 @@ e_handle_resp02 (FpDevice *dev, unsigned char *data,
if (data_len < sizeof (scan_comp))
{
fp_err ("fingerprint data too short (%lu bytes)", data_len);
fp_err ("fingerprint data too short (%" G_GSIZE_FORMAT "u bytes)", data_len);
error = fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO, "fingerprint data too short");
}
else if (memcmp (data, scan_comp, sizeof (scan_comp)) != 0)
@@ -1317,7 +1318,7 @@ v_handle_resp00 (FpDevice *dev, unsigned char *data,
if (data_len != 14)
{
fp_warn ("received 3001 poll response of %lu bytes?", data_len);
fp_warn ("received 3001 poll response of %" G_GSIZE_FORMAT "u bytes?", data_len);
error = fpi_device_error_new (FP_DEVICE_ERROR_PROTO);
goto out;
}

View File

@@ -131,6 +131,7 @@ struct _FpiDeviceUru4000
void *img_data;
int img_data_actual_length;
uint16_t img_lines_done, img_block;
GRand *rand;
uint32_t img_enc_seed;
irq_cb_fn irq_cb;
@@ -397,7 +398,7 @@ finger_presence_irq_cb (FpImageDevice *dev,
fpi_image_device_report_finger_status (dev, TRUE);
else if (type == IRQDATA_FINGER_OFF)
fpi_image_device_report_finger_status (dev, FALSE);
else
else if (type != IRQDATA_SCANPWR_ON)
fp_warn ("ignoring unexpected interrupt %04x", type);
}
@@ -722,7 +723,8 @@ imaging_run_state (FpiSsm *ssm, FpDevice *_dev)
fp_dbg ("changing encryption keys.");
img->block_info[self->img_block].flags &= ~BLOCKF_CHANGE_KEY;
img->key_number++;
self->img_enc_seed = rand ();
self->img_enc_seed = g_rand_int_range (self->rand, 0, RAND_MAX);
fp_dbg ("New image encryption seed: %d", self->img_enc_seed);
fpi_ssm_jump_to_state (ssm, IMAGING_SEND_INDEX);
return;
}
@@ -865,7 +867,7 @@ rebootpwr_run_state (FpiSsm *ssm, FpDevice *_dev)
}
else
{
fpi_ssm_jump_to_state_delayed (ssm, 10, REBOOTPWR_GET_HWSTAT, NULL);
fpi_ssm_jump_to_state_delayed (ssm, 10, REBOOTPWR_GET_HWSTAT);
}
break;
}
@@ -947,11 +949,11 @@ powerup_run_state (FpiSsm *ssm, FpDevice *_dev)
}
else if (!self->profile->auth_cr)
{
fpi_ssm_jump_to_state_delayed (ssm, POWERUP_SET_HWSTAT, 10, NULL);
fpi_ssm_jump_to_state_delayed (ssm, POWERUP_SET_HWSTAT, 10);
}
else
{
fpi_ssm_next_state_delayed (ssm, 10, NULL);
fpi_ssm_next_state_delayed (ssm, 10);
}
break;
@@ -1219,7 +1221,8 @@ execute_state_change (FpImageDevice *dev)
ssm = fpi_ssm_new (FP_DEVICE (dev), imaging_run_state,
IMAGING_NUM_STATES);
self->img_enc_seed = rand ();
self->img_enc_seed = g_rand_int_range (self->rand, 0, RAND_MAX);
fp_dbg ("Image encryption seed: %d", self->img_enc_seed);
self->img_transfer = fpi_usb_transfer_new (FP_DEVICE (dev));
self->img_transfer->ssm = ssm;
self->img_transfer->short_is_error = FALSE;
@@ -1355,6 +1358,11 @@ dev_init (FpImageDevice *dev)
self = FPI_DEVICE_URU4000 (dev);
g_clear_pointer (&self->rand, g_rand_free);
self->rand = g_rand_new ();
if (g_strcmp0 (g_getenv ("FP_DEVICE_EMULATION"), "1") == 0)
g_rand_set_seed (self->rand, 0xFACADE);
driver_data = fpi_device_get_driver_data (FP_DEVICE (dev));
self->profile = &uru4k_dev_info[driver_data];
self->interface = g_usb_interface_get_number (iface);
@@ -1407,6 +1415,7 @@ dev_deinit (FpImageDevice *dev)
PK11_FreeSlot (self->slot);
g_usb_device_release_interface (fpi_device_get_usb_device (FP_DEVICE (dev)),
self->interface, 0, &error);
g_clear_pointer (&self->rand, g_rand_free);
fpi_image_device_close_complete (dev, error);
}

View File

@@ -613,7 +613,7 @@ activate_ssm (FpiSsm *ssm, FpDevice *dev)
clear_data (self);
/* Wait for probable vdev->active changing */
fpi_ssm_next_state_delayed (ssm, VFS_SSM_TIMEOUT, NULL);
fpi_ssm_next_state_delayed (ssm, VFS_SSM_TIMEOUT);
break;
case SSM_NEXT_RECEIVE:
@@ -632,8 +632,7 @@ activate_ssm (FpiSsm *ssm, FpDevice *dev)
case SSM_WAIT_ANOTHER_SCAN:
/* Orange light is on now */
fpi_ssm_jump_to_state_delayed (ssm, SSM_TURN_ON, VFS_SSM_ORANGE_TIMEOUT,
NULL);
fpi_ssm_jump_to_state_delayed (ssm, SSM_TURN_ON, VFS_SSM_ORANGE_TIMEOUT);
break;
default:

View File

@@ -785,7 +785,7 @@ m_loop_state (FpiSsm *ssm, FpDevice *_dev)
case M_LOOP_0_SLEEP:
/* Wait fingerprint scanning */
fpi_ssm_next_state_delayed (ssm, 50, NULL);
fpi_ssm_next_state_delayed (ssm, 50);
break;
case M_LOOP_0_GET_STATE:
@@ -828,7 +828,7 @@ m_loop_state (FpiSsm *ssm, FpDevice *_dev)
img_extract (ssm, dev);
/* Wait handling image */
fpi_ssm_next_state_delayed (ssm, 10, NULL);
fpi_ssm_next_state_delayed (ssm, 10);
break;
case M_LOOP_0_CHECK_ACTION:
@@ -851,7 +851,7 @@ m_loop_state (FpiSsm *ssm, FpDevice *_dev)
if (vfs_finger_state (self) == VFS_FINGER_PRESENT)
{
fpi_image_device_report_finger_status (dev, TRUE);
fpi_ssm_next_state_delayed (ssm, 250, NULL);
fpi_ssm_next_state_delayed (ssm, 250);
}
else
{
@@ -881,7 +881,7 @@ m_loop_state (FpiSsm *ssm, FpDevice *_dev)
case M_LOOP_1_SLEEP:
/* Wait fingerprint scanning */
fpi_ssm_next_state_delayed (ssm, 10, NULL);
fpi_ssm_next_state_delayed (ssm, 10);
break;
case M_LOOP_2_ABORT_PRINT:
@@ -917,7 +917,7 @@ m_loop_state (FpiSsm *ssm, FpDevice *_dev)
{
/* Wait aborting */
self->counter++;
fpi_ssm_next_state_delayed (ssm, 100, NULL);
fpi_ssm_next_state_delayed (ssm, 100);
}
else
{
@@ -1055,7 +1055,7 @@ m_init_state (FpiSsm *ssm, FpDevice *_dev)
{
/* Wait aborting */
self->counter++;
fpi_ssm_next_state_delayed (ssm, 100, NULL);
fpi_ssm_next_state_delayed (ssm, 100);
}
else
{
@@ -1084,7 +1084,7 @@ m_init_state (FpiSsm *ssm, FpDevice *_dev)
{
/* Wait removing finger */
self->counter++;
fpi_ssm_next_state_delayed (ssm, 250, NULL);
fpi_ssm_next_state_delayed (ssm, 250);
}
else
{

View File

@@ -97,7 +97,7 @@ m_loop_state (FpiSsm *ssm, FpDevice *_dev)
case M_WAIT_PRINT:
/* Wait fingerprint scanning */
fpi_ssm_next_state_delayed (ssm, 200, NULL);
fpi_ssm_next_state_delayed (ssm, 200);
break;
case M_CHECK_PRINT:
@@ -115,7 +115,7 @@ m_loop_state (FpiSsm *ssm, FpDevice *_dev)
case M_READ_PRINT_WAIT:
/* Wait fingerprint scanning */
fpi_ssm_next_state_delayed (ssm, 200, NULL);
fpi_ssm_next_state_delayed (ssm, 200);
break;
case M_READ_PRINT_POLL:

View File

@@ -465,7 +465,7 @@ int
vfs301_proto_peek_event (FpDeviceVfs301 *dev)
{
g_autoptr(GError) error = NULL;
FpiUsbTransfer *transfer;
g_autoptr(FpiUsbTransfer) transfer = NULL;
const char no_event[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
const char got_event[] = {0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00};

View File

@@ -196,6 +196,7 @@ usb_exchange_async (FpiSsm *ssm,
FpiSsm *subsm = fpi_ssm_new_full (FP_DEVICE (data->device),
usbexchange_loop,
data->stepcount,
data->stepcount,
exchange_name);
fpi_ssm_set_data (subsm, data, NULL);
@@ -705,7 +706,7 @@ activate_loop (FpiSsm *ssm, FpDevice *_dev)
break;
case DEV_ACTIVATE_DATA_COMPLETE:
fpi_ssm_next_state_delayed (ssm, 1, NULL);
fpi_ssm_next_state_delayed (ssm, 1);
break;
case DEV_ACTIVATE_PREPARE_NEXT_CAPTURE:

View File

@@ -327,6 +327,7 @@ usb_exchange_async (FpiSsm *ssm,
FpiSsm *subsm = fpi_ssm_new_full (fpi_ssm_get_device (ssm),
usbexchange_loop,
data->stepcount,
data->stepcount,
exchange_name);
fpi_ssm_set_data (subsm, data, NULL);
@@ -486,7 +487,7 @@ deactivate_run_state (FpiSsm *ssm, FpDevice *_dev)
switch (fpi_ssm_get_cur_state (ssm))
{
case DEACTIVATE_ENTER:
fpi_ssm_next_state_delayed (ssm, 10, NULL);
fpi_ssm_next_state_delayed (ssm, 10);
break;
case DEACTIVATE_DISABLE_SENSOR:

View File

@@ -99,11 +99,13 @@ struct _FpDeviceVirtualDeviceStorage
G_DECLARE_FINAL_TYPE (FpDeviceVirtualDeviceStorage, fpi_device_virtual_device_storage, FP, DEVICE_VIRTUAL_DEVICE_STORAGE, FpDeviceVirtualDevice)
char * process_cmds (FpDeviceVirtualDevice * self, gboolean scan, GError **error);
char * start_scan_command (FpDeviceVirtualDevice *self,
gboolean process_cmds (FpDeviceVirtualDevice * self,
gboolean scan,
char **scan_id,
GError **error);
gboolean start_scan_command (FpDeviceVirtualDevice *self,
char **scan_id,
GError **error);
gboolean should_wait_for_command (FpDeviceVirtualDevice *self,
GError *error);
gboolean should_wait_to_sleep (FpDeviceVirtualDevice *self,
const char *scan_id,
GError *error);

View File

@@ -42,8 +42,7 @@ dev_identify (FpDevice *dev)
FpDeviceVirtualDevice *self = FP_DEVICE_VIRTUAL_DEVICE (dev);
g_autofree char *scan_id = NULL;
scan_id = start_scan_command (self, &error);
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_PENDING))
if (!start_scan_command (self, &scan_id, &error))
return;
if (scan_id)
@@ -147,11 +146,10 @@ dev_list (FpDevice *dev)
g_autoptr(GError) error = NULL;
FpDeviceVirtualDevice *vdev = FP_DEVICE_VIRTUAL_DEVICE (dev);
process_cmds (vdev, FALSE, &error);
if (should_wait_for_command (vdev, error))
if (!process_cmds (vdev, FALSE, NULL, &error))
return;
if (error && !g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
if (error)
{
fpi_device_list_complete (dev, NULL, g_steal_pointer (&error));
return;
@@ -160,6 +158,27 @@ dev_list (FpDevice *dev)
fpi_device_list_complete (dev, get_stored_prints (vdev), NULL);
}
static void
dev_clear_storage (FpDevice *dev)
{
g_autoptr(GPtrArray) prints_list = NULL;
g_autoptr(GError) error = NULL;
FpDeviceVirtualDevice *vdev = FP_DEVICE_VIRTUAL_DEVICE (dev);
if (!process_cmds (vdev, FALSE, NULL, &error))
return;
if (error)
{
fpi_device_clear_storage_complete (dev, g_steal_pointer (&error));
return;
}
g_hash_table_remove_all (vdev->prints_storage);
fpi_device_clear_storage_complete (dev, NULL);
}
static void
dev_delete (FpDevice *dev)
{
@@ -169,11 +188,10 @@ dev_delete (FpDevice *dev)
FpPrint *print = NULL;
const char *id = NULL;
process_cmds (vdev, FALSE, &error);
if (should_wait_for_command (vdev, error))
if (!process_cmds (vdev, FALSE, NULL, &error))
return;
if (error && !g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
if (error)
{
fpi_device_delete_complete (dev, g_steal_pointer (&error));
return;
@@ -202,6 +220,15 @@ dev_delete (FpDevice *dev)
fpi_device_error_new (FP_DEVICE_ERROR_DATA_NOT_FOUND));
}
static void
dev_probe (FpDevice *dev)
{
/* Disable features listed in driver_data */
fpi_device_update_features (dev, fpi_device_get_driver_data (dev), 0);
fpi_device_probe_complete (dev, NULL, NULL, NULL);
}
static void
fpi_device_virtual_device_storage_init (FpDeviceVirtualDeviceStorage *self)
{
@@ -224,8 +251,8 @@ fpi_device_virtual_device_storage_finalize (GObject *object)
}
static const FpIdEntry driver_ids[] = {
{ .virtual_envvar = "FP_VIRTUAL_DEVICE_STORAGE" },
{ .virtual_envvar = "FP_VIRTUAL_DEVICE_IDENT" },
{ .virtual_envvar = "FP_VIRTUAL_DEVICE_STORAGE", .driver_data = 0 },
{ .virtual_envvar = "FP_VIRTUAL_DEVICE_STORAGE_NO_LIST", .driver_data = FP_DEVICE_FEATURE_STORAGE_LIST },
{ .virtual_envvar = NULL }
};
@@ -241,10 +268,12 @@ fpi_device_virtual_device_storage_class_init (FpDeviceVirtualDeviceStorageClass
dev_class->full_name = "Virtual device with storage and identification for debugging";
dev_class->id_table = driver_ids;
dev_class->probe = dev_probe;
dev_class->identify = dev_identify;
dev_class->list = dev_list;
dev_class->delete = dev_delete;
dev_class->clear_storage = dev_clear_storage;
fpi_device_class_auto_initialize_features (dev_class);
dev_class->features |= FPI_DEVICE_FEATURE_DUPLICATES_CHECK;
dev_class->features |= FP_DEVICE_FEATURE_DUPLICATES_CHECK;
}

View File

@@ -37,6 +37,7 @@ G_DEFINE_TYPE (FpDeviceVirtualDevice, fpi_device_virtual_device, FP_TYPE_DEVICE)
#define INSERT_CMD_PREFIX "INSERT "
#define REMOVE_CMD_PREFIX "REMOVE "
#define SCAN_CMD_PREFIX "SCAN "
#define CONT_CMD_PREFIX "CONT "
#define ERROR_CMD_PREFIX "ERROR "
#define RETRY_CMD_PREFIX "RETRY "
#define FINGER_CMD_PREFIX "FINGER "
@@ -57,6 +58,8 @@ maybe_continue_current_action (FpDeviceVirtualDevice *self)
if (self->sleep_timeout_id)
return;
g_assert (self->wait_command_id == 0);
switch (fpi_device_get_current_action (dev))
{
case FPI_DEVICE_ACTION_ENROLL:
@@ -87,6 +90,14 @@ maybe_continue_current_action (FpDeviceVirtualDevice *self)
FP_DEVICE_GET_CLASS (self)->close (dev);
break;
case FPI_DEVICE_ACTION_CLEAR_STORAGE:
FP_DEVICE_GET_CLASS (self)->clear_storage (dev);
break;
/* Not implemented/nothing to do. */
case FPI_DEVICE_ACTION_NONE:
case FPI_DEVICE_ACTION_PROBE:
case FPI_DEVICE_ACTION_CAPTURE:
default:
break;
}
@@ -108,9 +119,35 @@ sleep_timeout_cb (gpointer data)
return FALSE;
}
char *
static gboolean
wait_for_command_timeout (gpointer data)
{
FpDeviceVirtualDevice *self = FP_DEVICE_VIRTUAL_DEVICE (data);
FpiDeviceAction action;
GError *error = NULL;
self->wait_command_id = 0;
action = fpi_device_get_current_action (FP_DEVICE (self));
if (action == FPI_DEVICE_ACTION_LIST || action == FPI_DEVICE_ACTION_DELETE)
{
self->ignore_wait = TRUE;
maybe_continue_current_action (self);
self->ignore_wait = FALSE;
return FALSE;
}
error = g_error_new (G_IO_ERROR, G_IO_ERROR_TIMED_OUT, "No commands arrived in time to run!");
fpi_device_action_error (FP_DEVICE (self), error);
return FALSE;
}
gboolean
process_cmds (FpDeviceVirtualDevice * self,
gboolean scan,
char **scan_id,
GError **error)
{
if (g_cancellable_is_cancelled (self->cancellable) ||
@@ -119,12 +156,17 @@ process_cmds (FpDeviceVirtualDevice * self,
{
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_CANCELLED,
"Operation was cancelled");
return NULL;
return TRUE;
}
while (self->pending_commands->len > 0)
{
gchar *cmd = g_ptr_array_index (self->pending_commands, 0);
g_autofree gchar *cmd = NULL;
/* TODO: g_ptr_array_steal_index requires GLib 2.58, we depend on 2.56 */
cmd = g_ptr_array_index (self->pending_commands, 0);
g_ptr_array_index (self->pending_commands, 0) = NULL;
g_ptr_array_remove_index (self->pending_commands, 0);
g_debug ("Processing command %s", cmd);
@@ -135,7 +177,6 @@ process_cmds (FpDeviceVirtualDevice * self,
g_hash_table_add (self->prints_storage,
g_strdup (cmd + strlen (INSERT_CMD_PREFIX)));
g_ptr_array_remove_index (self->pending_commands, 0);
continue;
}
else if (g_str_has_prefix (cmd, REMOVE_CMD_PREFIX))
@@ -145,50 +186,49 @@ process_cmds (FpDeviceVirtualDevice * self,
cmd + strlen (REMOVE_CMD_PREFIX)))
g_warning ("ID %s was not found in storage", cmd + strlen (REMOVE_CMD_PREFIX));
g_ptr_array_remove_index (self->pending_commands, 0);
continue;
}
else if (g_str_has_prefix (cmd, SLEEP_CMD_PREFIX))
{
guint64 sleep_ms = g_ascii_strtoull (cmd + strlen (SLEEP_CMD_PREFIX), NULL, 10);
g_debug ("Sleeping %lums", sleep_ms);
g_debug ("Sleeping %" G_GUINT64_FORMAT "ms", sleep_ms);
self->sleep_timeout_id = g_timeout_add (sleep_ms, sleep_timeout_cb, self);
g_ptr_array_remove_index (self->pending_commands, 0);
return NULL;
return FALSE;
}
else if (g_str_has_prefix (cmd, ERROR_CMD_PREFIX))
{
g_propagate_error (error,
fpi_device_error_new (g_ascii_strtoull (cmd + strlen (ERROR_CMD_PREFIX), NULL, 10)));
g_ptr_array_remove_index (self->pending_commands, 0);
return NULL;
return TRUE;
}
else if (!scan && g_str_has_prefix (cmd, CONT_CMD_PREFIX))
{
return TRUE;
}
/* If we are not scanning, then we have to stop here. */
if (!scan)
{
g_warning ("Could not process command: %s", cmd);
g_ptr_array_remove_index (self->pending_commands, 0);
break;
}
if (g_str_has_prefix (cmd, SCAN_CMD_PREFIX))
{
char *res = g_strdup (cmd + strlen (SCAN_CMD_PREFIX));
if (scan_id)
*scan_id = g_strdup (cmd + strlen (SCAN_CMD_PREFIX));
g_ptr_array_remove_index (self->pending_commands, 0);
return res;
return TRUE;
}
else if (g_str_has_prefix (cmd, RETRY_CMD_PREFIX))
{
g_propagate_error (error,
fpi_device_retry_new (g_ascii_strtoull (cmd + strlen (RETRY_CMD_PREFIX), NULL, 10)));
g_ptr_array_remove_index (self->pending_commands, 0);
return NULL;
return TRUE;
}
else if (g_str_has_prefix (cmd, FINGER_CMD_PREFIX))
{
@@ -199,19 +239,20 @@ process_cmds (FpDeviceVirtualDevice * self,
finger_present ? FP_FINGER_STATUS_PRESENT : FP_FINGER_STATUS_NONE,
finger_present ? FP_FINGER_STATUS_NONE : FP_FINGER_STATUS_PRESENT);
g_ptr_array_remove_index (self->pending_commands, 0);
continue;
}
else
{
g_warning ("Could not process command: %s", cmd);
g_ptr_array_remove_index (self->pending_commands, 0);
}
}
/* No commands left, throw a timeout error. */
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND, "No commands left that can be run!");
return NULL;
if (self->ignore_wait)
return TRUE;
g_assert (self->wait_command_id == 0);
self->wait_command_id = g_timeout_add (500, wait_for_command_timeout, self);
return FALSE;
}
static void
@@ -234,7 +275,7 @@ recv_instruction_cb (GObject *source_object,
gsize bytes;
bytes = fpi_device_virtual_listener_read_finish (listener, res, &error);
fp_dbg ("Got instructions of length %ld", bytes);
fp_dbg ("Got instructions of length %" G_GSIZE_FORMAT, bytes);
if (error)
{
@@ -339,14 +380,17 @@ dev_init (FpDevice *dev)
G_DEBUG_HERE ();
process_cmds (self, FALSE, &error);
if (error && !g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
self->ignore_wait = TRUE;
if (!process_cmds (self, FALSE, NULL, &error))
{
fpi_device_open_complete (dev, g_steal_pointer (&error));
self->ignore_wait = FALSE;
return;
}
else if (self->sleep_timeout_id)
self->ignore_wait = FALSE;
if (error)
{
fpi_device_open_complete (dev, g_steal_pointer (&error));
return;
}
else if (self->listener)
@@ -375,65 +419,21 @@ dev_init (FpDevice *dev)
fpi_device_open_complete (dev, NULL);
}
static gboolean
wait_for_command_timeout (gpointer data)
{
FpDeviceVirtualDevice *self = FP_DEVICE_VIRTUAL_DEVICE (data);
GError *error = NULL;
self->wait_command_id = 0;
switch (fpi_device_get_current_action (FP_DEVICE (self)))
{
case FPI_DEVICE_ACTION_LIST:
case FPI_DEVICE_ACTION_DELETE:
self->ignore_wait = TRUE;
maybe_continue_current_action (self);
self->ignore_wait = FALSE;
return FALSE;
default:
break;
}
error = g_error_new (G_IO_ERROR, G_IO_ERROR_TIMED_OUT, "No commands arrived in time to run!");
fpi_device_action_error (FP_DEVICE (self), error);
return FALSE;
}
gboolean
should_wait_for_command (FpDeviceVirtualDevice *self,
GError *error)
{
if (!error && self->sleep_timeout_id)
return TRUE;
if (self->ignore_wait)
return FALSE;
if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
return FALSE;
if (self->wait_command_id)
return FALSE;
self->wait_command_id = g_timeout_add (500, wait_for_command_timeout, self);
return TRUE;
}
char *
start_scan_command (FpDeviceVirtualDevice *self,
char **scan_id,
GError **error)
{
g_autoptr(GError) local_error = NULL;
g_autofree char *scan_id = NULL;
gboolean cont;
if (fp_device_get_finger_status (FP_DEVICE (self)) == FP_FINGER_STATUS_NONE)
self->injected_synthetic_cmd = FALSE;
scan_id = process_cmds (self, TRUE, &local_error);
cont = process_cmds (self, TRUE, scan_id, &local_error);
/* We report finger needed if we are waiting for instructions
* (i.e. we did not get an explicit SLEEP command).
*/
if (!self->sleep_timeout_id)
{
fpi_device_report_finger_status_changes (FP_DEVICE (self),
@@ -441,14 +441,13 @@ start_scan_command (FpDeviceVirtualDevice *self,
FP_FINGER_STATUS_NONE);
}
if (should_wait_for_command (self, local_error))
{
g_assert (!scan_id);
if (!cont)
return FALSE;
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_PENDING,
"Still waiting for command");
return NULL;
}
/* Scan or error*/
fpi_device_report_finger_status_changes (FP_DEVICE (self),
FP_FINGER_STATUS_NEEDED,
FP_FINGER_STATUS_NONE);
if (local_error)
g_propagate_error (error, g_steal_pointer (&local_error));
@@ -457,7 +456,7 @@ start_scan_command (FpDeviceVirtualDevice *self,
FP_FINGER_STATUS_PRESENT,
FP_FINGER_STATUS_NONE);
return g_steal_pointer (&scan_id);
return TRUE;
}
gboolean
@@ -478,7 +477,7 @@ should_wait_to_sleep (FpDeviceVirtualDevice *self,
if (g_str_has_prefix (cmd, SLEEP_CMD_PREFIX))
{
g_autoptr(GError) local_error = NULL;
g_free (process_cmds (self, FALSE, &local_error));
process_cmds (self, FALSE, NULL, &local_error);
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
return FALSE;
@@ -516,8 +515,7 @@ dev_verify (FpDevice *dev)
FpDeviceVirtualDevice *self = FP_DEVICE_VIRTUAL_DEVICE (dev);
g_autofree char *scan_id = NULL;
scan_id = start_scan_command (self, &error);
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_PENDING))
if (!start_scan_command (self, &scan_id, &error))
return;
if (scan_id)
@@ -583,8 +581,7 @@ dev_enroll (FpDevice *dev)
FpPrint *print = NULL;
g_autofree char *id = NULL;
id = start_scan_command (self, &error);
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_PENDING))
if (!start_scan_command (self, &id, &error))
return;
fpi_device_get_enroll_data (dev, &print);
@@ -696,6 +693,7 @@ dev_cancel (FpDevice *dev)
g_debug ("Got cancellation!");
g_clear_handle_id (&self->sleep_timeout_id, g_source_remove);
g_clear_handle_id (&self->wait_command_id, g_source_remove);
maybe_continue_current_action (self);
}
@@ -714,19 +712,19 @@ dev_deinit (FpDevice *dev)
g_autoptr(GError) error = NULL;
FpDeviceVirtualDevice *self = FP_DEVICE_VIRTUAL_DEVICE (dev);
process_cmds (self, FALSE, &error);
if (error && !g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
self->ignore_wait = TRUE;
if (!process_cmds (self, FALSE, NULL, &error))
{
self->ignore_wait = FALSE;
return;
}
self->ignore_wait = FALSE;
if (error)
{
fpi_device_close_complete (dev, g_steal_pointer (&error));
return;
}
else if (self->sleep_timeout_id)
{
return;
}
g_clear_handle_id (&self->wait_command_id, g_source_remove);
g_clear_handle_id (&self->sleep_timeout_id, g_source_remove);
if (!self->keep_alive)
stop_listener (self);

View File

@@ -197,6 +197,9 @@ on_listener_connected (FpiDeviceVirtualListener *listener,
case FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_OFF:
recv_image (self);
case FPI_IMAGE_DEVICE_STATE_INACTIVE:
case FPI_IMAGE_DEVICE_STATE_ACTIVATING:
case FPI_IMAGE_DEVICE_STATE_DEACTIVATING:
default:
break;
}

View File

@@ -23,16 +23,11 @@
#include "fpi-context.h"
#include "fpi-device.h"
#include <gusb.h>
#include <stdio.h>
#include <config.h>
#ifdef HAVE_UDEV
#include <sys/ioctl.h>
#include <sys/unistd.h>
#include <sys/types.h>
#include <sys/fcntl.h>
#include <sys/stat.h>
#include <linux/hidraw.h>
#include <gudev/gudev.h>
#endif
@@ -53,6 +48,8 @@ typedef struct
GUsbContext *usb_ctx;
GCancellable *cancellable;
GSList *sources;
gint pending_devices;
gboolean enumerated;
@@ -102,6 +99,7 @@ typedef struct
{
FpContext *context;
FpDevice *device;
GSource *source;
} RemoveDeviceData;
static gboolean
@@ -115,21 +113,36 @@ remove_device_idle_cb (RemoveDeviceData *data)
g_signal_emit (data->context, signals[DEVICE_REMOVED_SIGNAL], 0, data->device);
g_ptr_array_remove_index_fast (priv->devices, idx);
g_free (data);
return G_SOURCE_REMOVE;
}
static void
remove_device_data_free (RemoveDeviceData *data)
{
FpContextPrivate *priv = fp_context_get_instance_private (data->context);
priv->sources = g_slist_remove (priv->sources, data->source);
g_free (data);
}
static void
remove_device (FpContext *context, FpDevice *device)
{
g_autoptr(GSource) source = NULL;
FpContextPrivate *priv = fp_context_get_instance_private (context);
RemoveDeviceData *data;
data = g_new (RemoveDeviceData, 1);
data->context = context;
data->device = device;
g_idle_add ((GSourceFunc) remove_device_idle_cb, data);
source = data->source = g_idle_source_new ();
g_source_set_callback (source,
G_SOURCE_FUNC (remove_device_idle_cb), data,
(GDestroyNotify) remove_device_data_free);
g_source_attach (source, g_main_context_get_thread_default ());
priv->sources = g_slist_prepend (priv->sources, source);
}
static void
@@ -147,9 +160,16 @@ device_removed_cb (FpContext *context, FpDevice *device)
/* Wait for device close if the device is currently still open. */
if (open)
g_signal_connect_swapped (device, "notify::open", (GCallback) device_remove_on_notify_open_cb, context);
{
g_signal_connect_object (device, "notify::open",
(GCallback) device_remove_on_notify_open_cb,
context,
G_CONNECT_SWAPPED);
}
else
{
remove_device (context, device);
}
}
static void
@@ -177,7 +197,10 @@ async_device_init_done_cb (GObject *source_object, GAsyncResult *res, gpointer u
g_ptr_array_add (priv->devices, device);
g_signal_connect_swapped (device, "removed", (GCallback) device_removed_cb, context);
g_signal_connect_object (device, "removed",
(GCallback) device_removed_cb,
context,
G_CONNECT_SWAPPED);
g_signal_emit (context, signals[DEVICE_ADDED_SIGNAL], 0, device);
}
@@ -274,6 +297,8 @@ fp_context_finalize (GObject *object)
g_clear_object (&priv->cancellable);
g_clear_pointer (&priv->drivers, g_array_unref);
g_slist_free_full (g_steal_pointer (&priv->sources), (GDestroyNotify) g_source_destroy);
if (priv->usb_ctx)
g_object_run_dispose (G_OBJECT (priv->usb_ctx));
g_clear_object (&priv->usb_ctx);
@@ -491,22 +516,18 @@ fp_context_enumerate (FpContext *context)
{
for (matched_hidraw = hidraw_devices; matched_hidraw; matched_hidraw = matched_hidraw->next)
{
const gchar * devnode = g_udev_device_get_device_file (matched_hidraw->data);
int temp_hid = -1, res;
struct hidraw_devinfo info;
/* Find the parent HID node, and check the vid/pid from its HID_ID property */
g_autoptr(GUdevDevice) parent = g_udev_device_get_parent_with_subsystem (matched_hidraw->data, "hid", NULL);
const gchar * hid_id = g_udev_device_get_property (parent, "HID_ID");
guint32 vendor, product;
if (!devnode)
if (!parent || !hid_id)
continue;
temp_hid = open (devnode, O_RDWR);
if (temp_hid < 0)
if (sscanf (hid_id, "%*X:%X:%X", &vendor, &product) != 2)
continue;
res = ioctl (temp_hid, HIDIOCGRAWINFO, &info);
close (temp_hid);
if (res < 0)
continue;
if (info.vendor == entry->hid_id.vid && info.product == entry->hid_id.pid)
if (vendor == entry->hid_id.vid && product == entry->hid_id.pid)
break;
}
/* If match was not found exit */

View File

@@ -40,6 +40,7 @@ typedef struct
gchar *device_id;
gchar *device_name;
FpScanType scan_type;
FpDeviceFeature features;
guint64 driver_data;

View File

@@ -113,7 +113,8 @@ fp_device_cancelled_cb (GCancellable *cancellable, FpDevice *self)
fp_device_cancel_in_idle_cb,
self,
NULL);
g_source_attach (priv->current_idle_cancel_source, NULL);
g_source_attach (priv->current_idle_cancel_source,
g_task_get_context (priv->current_task));
g_source_unref (priv->current_idle_cancel_source);
}
@@ -140,12 +141,13 @@ fp_device_constructed (GObject *object)
FpDeviceClass *cls = FP_DEVICE_GET_CLASS (self);
FpDevicePrivate *priv = fp_device_get_instance_private (self);
g_assert (cls->features != FPI_DEVICE_FEATURE_NONE);
g_assert (cls->features != FP_DEVICE_FEATURE_NONE);
priv->type = cls->type;
if (cls->nr_enroll_stages)
priv->nr_enroll_stages = cls->nr_enroll_stages;
priv->scan_type = cls->scan_type;
priv->features = cls->features;
priv->device_name = g_strdup (cls->full_name);
priv->device_id = g_strdup ("0");
@@ -621,15 +623,17 @@ fp_device_get_nr_enroll_stages (FpDevice *device)
* Check whether the device supports identification.
*
* Returns: Whether the device supports identification
* Deprecated: 1.92.0: Use fp_device_has_feature() instead.
*/
gboolean
fp_device_supports_identify (FpDevice *device)
{
FpDeviceClass *cls = FP_DEVICE_GET_CLASS (device);
FpDevicePrivate *priv = fp_device_get_instance_private (device);
g_return_val_if_fail (FP_IS_DEVICE (device), FALSE);
return cls->identify && !!(cls->features & FPI_DEVICE_FEATURE_IDENTIFY);
return cls->identify && !!(priv->features & FP_DEVICE_FEATURE_IDENTIFY);
}
/**
@@ -639,15 +643,17 @@ fp_device_supports_identify (FpDevice *device)
* Check whether the device supports capturing images.
*
* Returns: Whether the device supports image capture
* Deprecated: 1.92.0: Use fp_device_has_feature() instead.
*/
gboolean
fp_device_supports_capture (FpDevice *device)
{
FpDeviceClass *cls = FP_DEVICE_GET_CLASS (device);
FpDevicePrivate *priv = fp_device_get_instance_private (device);
g_return_val_if_fail (FP_IS_DEVICE (device), FALSE);
return cls->capture && !!(cls->features & FPI_DEVICE_FEATURE_CAPTURE);
return cls->capture && !!(priv->features & FP_DEVICE_FEATURE_CAPTURE);
}
/**
@@ -658,15 +664,16 @@ fp_device_supports_capture (FpDevice *device)
* prints stored on the with fp_device_list_prints() and you should
* always delete prints from the device again using
* fp_device_delete_print().
* Deprecated: 1.92.0: Use fp_device_has_feature() instead.
*/
gboolean
fp_device_has_storage (FpDevice *device)
{
FpDeviceClass *cls = FP_DEVICE_GET_CLASS (device);
FpDevicePrivate *priv = fp_device_get_instance_private (device);
g_return_val_if_fail (FP_IS_DEVICE (device), FALSE);
return !!(cls->features & FPI_DEVICE_FEATURE_STORAGE);
return !!(priv->features & FP_DEVICE_FEATURE_STORAGE);
}
/**
@@ -976,7 +983,7 @@ fp_device_verify (FpDevice *device,
return;
}
if (!cls->verify || !(cls->features & FPI_DEVICE_FEATURE_VERIFY))
if (!cls->verify || !(priv->features & FP_DEVICE_FEATURE_VERIFY))
{
g_task_return_error (task,
fpi_device_error_new_msg (FP_DEVICE_ERROR_NOT_SUPPORTED,
@@ -1073,6 +1080,7 @@ fp_device_identify (FpDevice *device,
{
g_autoptr(GTask) task = NULL;
FpDevicePrivate *priv = fp_device_get_instance_private (device);
FpDeviceClass *cls = FP_DEVICE_GET_CLASS (device);
FpMatchData *data;
int i;
@@ -1094,7 +1102,7 @@ fp_device_identify (FpDevice *device,
return;
}
if (!fp_device_supports_identify (device))
if (!cls->identify || !(priv->features & FP_DEVICE_FEATURE_IDENTIFY))
{
g_task_return_error (task,
fpi_device_error_new_msg (FP_DEVICE_ERROR_NOT_SUPPORTED,
@@ -1121,7 +1129,7 @@ fp_device_identify (FpDevice *device,
// Attach the match data as task data so that it is destroyed
g_task_set_task_data (priv->current_task, data, (GDestroyNotify) match_data_free);
FP_DEVICE_GET_CLASS (device)->identify (device);
cls->identify (device);
}
/**
@@ -1211,7 +1219,7 @@ fp_device_capture (FpDevice *device,
return;
}
if (!cls->capture || !(cls->features & FPI_DEVICE_FEATURE_CAPTURE))
if (!cls->capture || !(priv->features & FP_DEVICE_FEATURE_CAPTURE))
{
g_task_return_error (task,
fpi_device_error_new_msg (FP_DEVICE_ERROR_NOT_SUPPORTED,
@@ -1295,7 +1303,7 @@ fp_device_delete_print (FpDevice *device,
}
/* Succeed immediately if delete is not implemented. */
if (!cls->delete || !(cls->features & FPI_DEVICE_FEATURE_STORAGE_DELETE))
if (!cls->delete || !(priv->features & FP_DEVICE_FEATURE_STORAGE_DELETE))
{
g_task_return_boolean (task, TRUE);
return;
@@ -1352,6 +1360,7 @@ fp_device_list_prints (FpDevice *device,
{
g_autoptr(GTask) task = NULL;
FpDevicePrivate *priv = fp_device_get_instance_private (device);
FpDeviceClass *cls = FP_DEVICE_GET_CLASS (device);
task = g_task_new (device, cancellable, callback, user_data);
if (g_task_return_error_if_cancelled (task))
@@ -1371,7 +1380,7 @@ fp_device_list_prints (FpDevice *device,
return;
}
if (!fp_device_has_storage (device))
if (!cls->list || !(priv->features & FP_DEVICE_FEATURE_STORAGE))
{
g_task_return_error (task,
fpi_device_error_new_msg (FP_DEVICE_ERROR_NOT_SUPPORTED,
@@ -1383,7 +1392,7 @@ fp_device_list_prints (FpDevice *device,
priv->current_task = g_steal_pointer (&task);
maybe_cancel_on_cancelled (device, cancellable);
FP_DEVICE_GET_CLASS (device)->list (device);
cls->list (device);
}
/**
@@ -1406,6 +1415,93 @@ fp_device_list_prints_finish (FpDevice *device,
return g_task_propagate_pointer (G_TASK (result), error);
}
/**
* fp_device_clear_storage:
* @device: a #FpDevice
* @cancellable: (nullable): a #GCancellable, or %NULL
* @callback: the function to call on completion
* @user_data: the data to pass to @callback
*
* Start an asynchronous operation to delete all prints from the device.
* The callback will be called once the operation has finished. Retrieve
* the result with fp_device_clear_storage_finish().
*
* This only makes sense on devices that store prints on-chip, but is safe
* to always call.
*/
void
fp_device_clear_storage (FpDevice *device,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
g_autoptr(GTask) task = NULL;
FpDevicePrivate *priv = fp_device_get_instance_private (device);
FpDeviceClass *cls = FP_DEVICE_GET_CLASS (device);
task = g_task_new (device, cancellable, callback, user_data);
if (g_task_return_error_if_cancelled (task))
return;
if (!priv->is_open)
{
g_task_return_error (task,
fpi_device_error_new (FP_DEVICE_ERROR_NOT_OPEN));
return;
}
if (priv->current_task)
{
g_task_return_error (task,
fpi_device_error_new (FP_DEVICE_ERROR_BUSY));
return;
}
if (!(priv->features & FP_DEVICE_FEATURE_STORAGE))
{
g_task_return_error (task,
fpi_device_error_new_msg (FP_DEVICE_ERROR_NOT_SUPPORTED,
"Device has no storage."));
return;
}
if (!(priv->features & FP_DEVICE_FEATURE_STORAGE_CLEAR))
{
g_task_return_error (task,
fpi_device_error_new_msg (FP_DEVICE_ERROR_NOT_SUPPORTED,
"Device doesn't support clearing storage."));
return;
}
priv->current_action = FPI_DEVICE_ACTION_CLEAR_STORAGE;
priv->current_task = g_steal_pointer (&task);
maybe_cancel_on_cancelled (device, cancellable);
cls->clear_storage (device);
return;
}
/**
* fp_device_clear_storage_finish:
* @device: A #FpDevice
* @result: A #GAsyncResult
* @error: Return location for errors, or %NULL to ignore
*
* Finish an asynchronous operation to delete all enrolled prints.
*
* See fp_device_clear_storage().
*
* Returns: (type void): %FALSE on error, %TRUE otherwise
*/
gboolean
fp_device_clear_storage_finish (FpDevice *device,
GAsyncResult *result,
GError **error)
{
return g_task_propagate_boolean (G_TASK (result), error);
}
static void
async_result_ready (GObject *source_object, GAsyncResult *res, gpointer user_data)
{
@@ -1623,7 +1719,7 @@ fp_device_capture_sync (FpDevice *device,
*
* Delete a given print from the device.
*
* Returns: %FALSE on error, %TRUE otherwise
* Returns: (type void): %FALSE on error, %TRUE otherwise
*/
gboolean
fp_device_delete_print_sync (FpDevice *device,
@@ -1672,3 +1768,71 @@ fp_device_list_prints_sync (FpDevice *device,
return fp_device_list_prints_finish (device, task, error);
}
/**
* fp_device_clear_storage_sync:
* @device: a #FpDevice
* @cancellable: (nullable): a #GCancellable, or %NULL
* @error: Return location for errors, or %NULL to ignore
*
* Clear sensor storage.
*
* Returns: (type void): %FALSE on error, %TRUE otherwise
*/
gboolean
fp_device_clear_storage_sync (FpDevice *device,
GCancellable *cancellable,
GError **error)
{
g_autoptr(GAsyncResult) task = NULL;
g_return_val_if_fail (FP_IS_DEVICE (device), FALSE);
fp_device_clear_storage (device,
cancellable,
async_result_ready, &task);
while (!task)
g_main_context_iteration (NULL, TRUE);
return fp_device_clear_storage_finish (device, task, error);
}
/**
* fp_device_get_features:
* @device: a #FpDevice
*
* Gets the #FpDeviceFeature's supported by the @device.
*
* Returns: #FpDeviceFeature flags of supported features
*/
FpDeviceFeature
fp_device_get_features (FpDevice *device)
{
FpDevicePrivate *priv = fp_device_get_instance_private (device);
g_return_val_if_fail (FP_IS_DEVICE (device), FP_DEVICE_FEATURE_NONE);
return priv->features;
}
/**
* fp_device_has_feature:
* @device: a #FpDevice
* @feature: #FpDeviceFeature flags to check against device supported features
*
* Checks if @device supports the requested #FpDeviceFeature's.
* See fp_device_get_features()
*
* Returns: %TRUE if supported, %FALSE otherwise
*/
gboolean
fp_device_has_feature (FpDevice *device,
FpDeviceFeature feature)
{
g_return_val_if_fail (FP_IS_DEVICE (device), FALSE);
if (feature == FP_DEVICE_FEATURE_NONE)
return fp_device_get_features (device) == feature;
return (fp_device_get_features (device) & feature) == feature;
}

View File

@@ -47,6 +47,30 @@ typedef enum {
FP_DEVICE_TYPE_USB,
} FpDeviceType;
/**
* FpDeviceFeature:
* @FP_DEVICE_FEATURE_NONE: Device does not support any feature
* @FP_DEVICE_FEATURE_CAPTURE: Supports image capture
* @FP_DEVICE_FEATURE_VERIFY: Supports finger verification
* @FP_DEVICE_FEATURE_IDENTIFY: Supports finger identification
* @FP_DEVICE_FEATURE_STORAGE: Device has a persistent storage
* @FP_DEVICE_FEATURE_STORAGE_LIST: Supports listing the storage templates
* @FP_DEVICE_FEATURE_STORAGE_DELETE: Supports deleting stored templates
* @FP_DEVICE_FEATURE_STORAGE_CLEAR: Supports clearing the whole storage
* @FP_DEVICE_FEATURE_DUPLICATES_CHECK: Natively supports duplicates detection
*/
typedef enum /*< flags >*/ {
FP_DEVICE_FEATURE_NONE = 0,
FP_DEVICE_FEATURE_CAPTURE = 1 << 0,
FP_DEVICE_FEATURE_IDENTIFY = 1 << 1,
FP_DEVICE_FEATURE_VERIFY = 1 << 2,
FP_DEVICE_FEATURE_STORAGE = 1 << 3,
FP_DEVICE_FEATURE_STORAGE_LIST = 1 << 4,
FP_DEVICE_FEATURE_STORAGE_DELETE = 1 << 5,
FP_DEVICE_FEATURE_STORAGE_CLEAR = 1 << 6,
FP_DEVICE_FEATURE_DUPLICATES_CHECK = 1 << 7,
} FpDeviceFeature;
/**
* FpScanType:
* @FP_SCAN_TYPE_SWIPE: Sensor requires swiping the finger.
@@ -178,9 +202,9 @@ FpScanType fp_device_get_scan_type (FpDevice *device);
FpFingerStatusFlags fp_device_get_finger_status (FpDevice *device);
gint fp_device_get_nr_enroll_stages (FpDevice *device);
gboolean fp_device_supports_identify (FpDevice *device);
gboolean fp_device_supports_capture (FpDevice *device);
gboolean fp_device_has_storage (FpDevice *device);
FpDeviceFeature fp_device_get_features (FpDevice *device);
gboolean fp_device_has_feature (FpDevice *device,
FpDeviceFeature feature);
/* Opening the device */
void fp_device_open (FpDevice *device,
@@ -237,6 +261,11 @@ void fp_device_list_prints (FpDevice *device,
GAsyncReadyCallback callback,
gpointer user_data);
void fp_device_clear_storage (FpDevice *device,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
gboolean fp_device_open_finish (FpDevice *device,
GAsyncResult *result,
GError **error);
@@ -265,7 +294,9 @@ gboolean fp_device_delete_print_finish (FpDevice *device,
GPtrArray * fp_device_list_prints_finish (FpDevice *device,
GAsyncResult *result,
GError **error);
gboolean fp_device_clear_storage_finish (FpDevice *device,
GAsyncResult *result,
GError **error);
gboolean fp_device_open_sync (FpDevice *device,
GCancellable *cancellable,
@@ -306,6 +337,15 @@ gboolean fp_device_delete_print_sync (FpDevice *device,
GPtrArray * fp_device_list_prints_sync (FpDevice *device,
GCancellable *cancellable,
GError **error);
gboolean fp_device_clear_storage_sync (FpDevice *device,
GCancellable *cancellable,
GError **error);
/* Deprecated functions */
G_DEPRECATED_FOR (fp_device_get_features)
gboolean fp_device_supports_identify (FpDevice *device);
G_DEPRECATED_FOR (fp_device_get_features)
gboolean fp_device_supports_capture (FpDevice *device);
G_DEPRECATED_FOR (fp_device_get_features)
gboolean fp_device_has_storage (FpDevice *device);
G_END_DECLS

View File

@@ -281,7 +281,7 @@ fp_print_class_init (FpPrintClass *klass)
"Type",
"Private: The type of the print data",
FPI_TYPE_PRINT_TYPE,
FPI_PRINT_RAW,
FPI_PRINT_UNDEFINED,
G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY);
/**

View File

@@ -210,69 +210,36 @@ aes_blit_stripe (struct fpi_frame_asmbl_ctx *ctx,
struct fpi_frame *stripe,
int x, int y)
{
unsigned int ix, iy;
unsigned int fx, fy;
unsigned int width, height;
unsigned int ix1, iy1;
unsigned int fx1, fy1;
unsigned int fx, fy, ix, iy;
/* Find intersection */
/* Select starting point inside image and frame */
if (x < 0)
{
width = ctx->frame_width + x;
ix = 0;
fx = -x;
ix1 = 0;
fx1 = -x;
}
else
{
ix = x;
fx = 0;
width = ctx->frame_width;
ix1 = x;
fx1 = 0;
}
if ((ix + width) > img->width)
width = img->width - ix;
if (y < 0)
{
iy = 0;
fy = -y;
height = ctx->frame_height + y;
iy1 = 0;
fy1 = -y;
}
else
{
iy = y;
fy = 0;
height = ctx->frame_height;
iy1 = y;
fy1 = 0;
}
if (fx > ctx->frame_width)
return;
if (fy > ctx->frame_height)
return;
if (ix > img->width)
return;
if (iy > img->height)
return;
if ((iy + height) > img->height)
height = img->height - iy;
for (; fy < height; fy++, iy++)
{
if (x < 0)
{
ix = 0;
fx = -x;
}
else
{
ix = x;
fx = 0;
}
for (; fx < width; fx++, ix++)
for (fy = fy1, iy = iy1; fy < ctx->frame_height && iy < img->height; fy++, iy++)
for (fx = fx1, ix = ix1; fx < ctx->frame_width && ix < img->width; fx++, ix++)
img->data[ix + (iy * img->width)] = ctx->get_pixel (ctx, stripe, fx, fy);
}
}
/**
@@ -298,7 +265,6 @@ fpi_assemble_frames (struct fpi_frame_asmbl_ctx *ctx,
//FIXME g_return_if_fail
g_return_val_if_fail (stripes != NULL, NULL);
BUG_ON (ctx->image_width < ctx->frame_width);
/* No offset for 1st image */
fpi_frame = stripes->data;
@@ -331,7 +297,7 @@ fpi_assemble_frames (struct fpi_frame_asmbl_ctx *ctx,
/* Assemble stripes */
y = reverse ? (height - ctx->frame_height) : 0;
x = (ctx->image_width - ctx->frame_width) / 2;
x = ((int) ctx->image_width - (int) ctx->frame_width) / 2;
for (l = stripes; l != NULL; l = l->next)
{

View File

@@ -59,25 +59,25 @@ fpi_device_class_auto_initialize_features (FpDeviceClass *device_class)
g_return_if_fail (FP_IS_DEVICE_CLASS (device_class));
if (device_class->capture)
device_class->features |= FPI_DEVICE_FEATURE_CAPTURE;
device_class->features |= FP_DEVICE_FEATURE_CAPTURE;
if (device_class->verify)
device_class->features |= FPI_DEVICE_FEATURE_VERIFY;
device_class->features |= FP_DEVICE_FEATURE_VERIFY;
if (device_class->identify)
device_class->features |= FPI_DEVICE_FEATURE_IDENTIFY;
device_class->features |= FP_DEVICE_FEATURE_IDENTIFY;
if (device_class->list)
{
device_class->features |= FPI_DEVICE_FEATURE_STORAGE;
device_class->features |= FPI_DEVICE_FEATURE_STORAGE_LIST;
}
device_class->features |= FP_DEVICE_FEATURE_STORAGE_LIST;
if (device_class->delete)
{
device_class->features |= FPI_DEVICE_FEATURE_STORAGE;
device_class->features |= FPI_DEVICE_FEATURE_STORAGE_DELETE;
}
device_class->features |= FP_DEVICE_FEATURE_STORAGE_DELETE;
if (device_class->clear_storage)
device_class->features |= FP_DEVICE_FEATURE_STORAGE_CLEAR;
if (device_class->delete && (device_class->list || device_class->clear_storage))
device_class->features |= FP_DEVICE_FEATURE_STORAGE;
}
/**
@@ -277,6 +277,29 @@ fpi_device_set_scan_type (FpDevice *device,
g_object_notify (G_OBJECT (device), "scan-type");
}
/**
* fpi_device_update_features:
* @device: The #FpDevice
* @update: The feature flags to update
* @value: The value to set the flags to
*
* Updates the feature flags for the device. This can be used
* to runtime detect features that are supported by the device.
*/
void
fpi_device_update_features (FpDevice *device,
FpDeviceFeature update,
FpDeviceFeature value)
{
FpDevicePrivate *priv = fp_device_get_instance_private (device);
g_return_if_fail (FP_IS_DEVICE (device));
g_return_if_fail (priv->current_action == FPI_DEVICE_ACTION_PROBE);
g_return_if_fail ((value & update) == value);
priv->features = (priv->features & ~update) | (value & update);
}
typedef struct
{
GSource source;
@@ -334,12 +357,18 @@ fpi_device_add_timeout (FpDevice *device,
{
FpDevicePrivate *priv = fp_device_get_instance_private (device);
FpDeviceTimeoutSource *source;
GMainContext *context;
source = (FpDeviceTimeoutSource *) g_source_new (&timeout_funcs,
sizeof (FpDeviceTimeoutSource));
source->device = device;
g_source_attach (&source->source, NULL);
if (priv->current_task)
context = g_task_get_context (priv->current_task);
else
context = g_main_context_get_thread_default ();
g_source_attach (&source->source, context);
g_source_set_callback (&source->source, (GSourceFunc) func, user_data, destroy_notify);
g_source_set_ready_time (&source->source,
g_source_get_time (&source->source) + interval * (guint64) 1000);
@@ -762,6 +791,10 @@ fpi_device_action_error (FpDevice *device,
fpi_device_list_complete (device, NULL, error);
break;
case FPI_DEVICE_ACTION_CLEAR_STORAGE:
fpi_device_clear_storage_complete (device, error);
break;
default:
case FPI_DEVICE_ACTION_NONE:
g_return_if_reached ();
@@ -930,7 +963,8 @@ fpi_device_return_task_in_idle (FpDevice *device,
data,
(GDestroyNotify) fpi_device_task_return_data_free);
g_source_attach (priv->current_task_idle_return_source, NULL);
g_source_attach (priv->current_task_idle_return_source,
g_task_get_context (priv->current_task));
g_source_unref (priv->current_task_idle_return_source);
}
@@ -1371,6 +1405,35 @@ fpi_device_list_complete (FpDevice *device,
}
/**
* fpi_device_clear_storage_complete:
* @device: The #FpDevice
* @error: The #GError or %NULL on success
*
* Finish an ongoing clear_storage operation.
*/
void
fpi_device_clear_storage_complete (FpDevice *device,
GError *error)
{
FpDevicePrivate *priv = fp_device_get_instance_private (device);
g_return_if_fail (FP_IS_DEVICE (device));
g_return_if_fail (priv->current_action == FPI_DEVICE_ACTION_CLEAR_STORAGE);
g_debug ("Device reported deletion completion");
clear_device_cancel_action (device);
fpi_device_report_finger_status (device, FP_FINGER_STATUS_NONE);
if (!error)
fpi_device_return_task_in_idle (device, FP_DEVICE_TASK_RETURN_BOOL,
GUINT_TO_POINTER (TRUE));
else
fpi_device_return_task_in_idle (device, FP_DEVICE_TASK_RETURN_ERROR, error);
}
/**
* fpi_device_enroll_progress:
* @device: The #FpDevice
* @completed_stages: The number of stages that are completed at this point

View File

@@ -69,30 +69,6 @@ struct _FpIdEntry
guint64 driver_data;
};
/**
* FpiDeviceFeature:
* @FPI_DEVICE_FEATURE_NONE: Device does not support any feature
* @FPI_DEVICE_FEATURE_CAPTURE: Supports image capture
* @FPI_DEVICE_FEATURE_IDENTIFY: Supports finger identification
* @FPI_DEVICE_FEATURE_VERIFY: Supports finger verification
* @FPI_DEVICE_FEATURE_STORAGE: Device has a persistent storage
* @FPI_DEVICE_FEATURE_STORAGE_LIST: Supports listing the storage templates
* @FPI_DEVICE_FEATURE_STORAGE_DELETE: Supports deleting stored templates
* @FPI_DEVICE_FEATURE_STORAGE_CLEAR: Supports clearing the whole storage
* @FPI_DEVICE_FEATURE_DUPLICATES_CHECK: Natively supports duplicates detection
*/
typedef enum /*< flags >*/ {
FPI_DEVICE_FEATURE_NONE = 0,
FPI_DEVICE_FEATURE_CAPTURE = 1 << 0,
FPI_DEVICE_FEATURE_IDENTIFY = 1 << 1,
FPI_DEVICE_FEATURE_VERIFY = 1 << 2,
FPI_DEVICE_FEATURE_STORAGE = 1 << 3,
FPI_DEVICE_FEATURE_STORAGE_LIST = 1 << 4,
FPI_DEVICE_FEATURE_STORAGE_DELETE = 1 << 5,
FPI_DEVICE_FEATURE_STORAGE_CLEAR = 1 << 6,
FPI_DEVICE_FEATURE_DUPLICATES_CHECK = 1 << 7,
} FpiDeviceFeature;
/**
* FpDeviceClass:
* @id: ID string for the driver. Should be a valid C identifier and should
@@ -125,6 +101,7 @@ typedef enum /*< flags >*/ {
* @capture: Start a capture operation
* @list: List prints stored on the device
* @delete: Delete a print from the device
* @clear_storage: Delete all prints from the device
* @cancel: Called on cancellation, this is a convenience to not need to handle
* the #GCancellable directly by using fpi_device_get_cancellable().
*
@@ -159,7 +136,7 @@ struct _FpDeviceClass
const gchar *full_name;
FpDeviceType type;
const FpIdEntry *id_table;
FpiDeviceFeature features;
FpDeviceFeature features;
/* Defaults for device properties */
gint nr_enroll_stages;
@@ -176,6 +153,7 @@ struct _FpDeviceClass
void (*capture) (FpDevice *device);
void (*list) (FpDevice *device);
void (*delete) (FpDevice * device);
void (*clear_storage) (FpDevice * device);
void (*cancel) (FpDevice *device);
};
@@ -204,6 +182,7 @@ typedef void (*FpTimeoutFunc) (FpDevice *device,
* @FPI_DEVICE_ACTION_CAPTURE: Device is currently capturing an image.
* @FPI_DEVICE_ACTION_LIST: Device stored prints are being queried.
* @FPI_DEVICE_ACTION_DELETE: Device stored print is being deleted.
* @FPI_DEVICE_ACTION_CLEAR_STORAGE: Device stored prints are being deleted.
*
* Current active action of the device. A driver can retrieve the action.
*/
@@ -218,6 +197,7 @@ typedef enum {
FPI_DEVICE_ACTION_CAPTURE,
FPI_DEVICE_ACTION_LIST,
FPI_DEVICE_ACTION_DELETE,
FPI_DEVICE_ACTION_CLEAR_STORAGE,
} FpiDeviceAction;
GUsbDevice *fpi_device_get_usb_device (FpDevice *device);
@@ -269,6 +249,10 @@ void fpi_device_set_nr_enroll_stages (FpDevice *device,
void fpi_device_set_scan_type (FpDevice *device,
FpScanType scan_type);
void fpi_device_update_features (FpDevice *device,
FpDeviceFeature update,
FpDeviceFeature value);
void fpi_device_action_error (FpDevice *device,
GError *error);
@@ -295,6 +279,8 @@ void fpi_device_delete_complete (FpDevice *device,
void fpi_device_list_complete (FpDevice *device,
GPtrArray *prints,
GError *error);
void fpi_device_clear_storage_complete (FpDevice *device,
GError *error);
void fpi_device_enroll_progress (FpDevice *device,
gint completed_stages,

View File

@@ -22,6 +22,11 @@
#include <linux/spi/spidev.h>
#include <errno.h>
/* spidev can only handle the specified block size, which defaults to 4096. */
#define SPIDEV_BLOCK_SIZE_PARAM "/sys/module/spidev/parameters/bufsiz"
#define SPIDEV_BLOCK_SIZE_FALLBACK 4096
static gsize block_size = 0;
/**
* SECTION:fpi-spi-transfer
* @title: SPI transfer helpers
@@ -114,6 +119,28 @@ fpi_spi_transfer_new (FpDevice * device, int spidev_fd)
g_assert (FP_IS_DEVICE (device));
if (G_UNLIKELY (block_size == 0))
{
g_autoptr(GError) error = NULL;
g_autofree char *contents = NULL;
block_size = SPIDEV_BLOCK_SIZE_FALLBACK;
if (g_file_get_contents (SPIDEV_BLOCK_SIZE_PARAM, &contents, NULL, &error))
{
block_size = MIN (g_ascii_strtoull (contents, NULL, 0), G_MAXUINT16);
if (block_size == 0)
{
block_size = SPIDEV_BLOCK_SIZE_FALLBACK;
g_warning ("spidev blocksize could not be decoded, using %" G_GSIZE_FORMAT, block_size);
}
}
else
{
g_message ("Failed to read spidev block size, using %" G_GSIZE_FORMAT, block_size);
}
}
self = g_slice_new0 (FpiSpiTransfer);
self->ref_count = 1;
@@ -283,6 +310,78 @@ transfer_finish_cb (GObject *source_object, GAsyncResult *res, gpointer user_dat
callback (transfer, transfer->device, transfer->user_data, error);
}
static int
transfer_chunk (FpiSpiTransfer *transfer, gsize full_length, gsize *transferred)
{
struct spi_ioc_transfer xfer[2] = { 0 };
gsize skip = *transferred;
gsize len = 0;
int transfers = 0;
int status;
if (transfer->buffer_wr)
{
if (skip < transfer->length_wr && len < block_size)
{
xfer[transfers].tx_buf = (gsize) transfer->buffer_wr + skip;
xfer[transfers].len = MIN (block_size, transfer->length_wr - skip);
len += xfer[transfers].len;
skip += xfer[transfers].len;
transfers += 1;
}
/* How much we need to skip in the next transfer. */
skip -= transfer->length_wr;
}
if (transfer->buffer_rd)
{
if (skip < transfer->length_rd && len < block_size)
{
xfer[transfers].rx_buf = (gsize) transfer->buffer_rd + skip;
xfer[transfers].len = MIN (block_size, transfer->length_rd - skip);
len += xfer[transfers].len;
/* skip += xfer[transfers].len; */
transfers += 1;
}
/* How much we need to skip in the next transfer. */
/* skip -= transfer->length_rd; */
}
g_assert (transfers > 0);
/* We have not transferred everything; ask driver to not deselect the chip.
* Unfortunately, this is inherently racy in case there are further devices
* on the same bus. In practice, it is hopefully unlikely to be an issue,
* but print a message once to help with debugging.
*/
if (full_length < *transferred + len)
{
static gboolean warned = FALSE;
if (!warned)
{
g_message ("Split SPI transfer. In case of issues, try increasing the spidev buffer size.");
warned = TRUE;
}
xfer[transfers - 1].cs_change = TRUE;
}
/* This ioctl cannot be interrupted. */
status = ioctl (transfer->spidev_fd, SPI_IOC_MESSAGE (transfers), xfer);
if (status >= 0)
*transferred += len;
return status;
}
static void
transfer_thread_func (GTask *task,
gpointer source_object,
@@ -290,9 +389,9 @@ transfer_thread_func (GTask *task,
GCancellable *cancellable)
{
FpiSpiTransfer *transfer = (FpiSpiTransfer *) task_data;
struct spi_ioc_transfer xfer[2];
int transfers = 0;
int status;
gsize full_length;
gsize transferred = 0;
int status = 0;
if (transfer->buffer_wr == NULL && transfer->buffer_rd == NULL)
{
@@ -303,26 +402,14 @@ transfer_thread_func (GTask *task,
return;
}
memset (xfer, 0, sizeof (xfer));
full_length = 0;
if (transfer->buffer_wr)
{
xfer[transfers].tx_buf = (guint64) transfer->buffer_wr;
xfer[transfers].len = transfer->length_wr;
transfers += 1;
}
full_length += transfer->length_wr;
if (transfer->buffer_rd)
{
xfer[transfers].rx_buf = (guint64) transfer->buffer_rd;
xfer[transfers].len = transfer->length_rd;
full_length += transfer->length_rd;
transfers += 1;
}
/* This ioctl cannot be interrupted. */
status = ioctl (transfer->spidev_fd, SPI_IOC_MESSAGE (transfers), xfer);
while (transferred < full_length && status >= 0)
status = transfer_chunk (transfer, full_length, &transferred);
if (status < 0)
{

View File

@@ -31,27 +31,24 @@
* @short_description: State machine helpers
*
* Asynchronous driver design encourages some kind of state machine behind it.
* In most cases, the state machine is entirely linear - you only go to the
* next state, you never jump or go backwards. The #FpiSsm functions help you
* implement such a machine.
* #FpiSsm provides a simple mechanism to implement a state machine, which
* is often entirely linear. You can however also jump to a specific state
* or do an early return from the SSM by completing it.
*
* e.g. `S1` ↦ `S2` ↦ `S3` ↦ `S4`
* e.g. `S1` ↦ `S2` ↦ `S3` ↦ `S4` ↦ `C1` ↦ `C2` ↦ `final`
*
* `S1` is the start state
* There is also an implicit error state and an implicit accepting state
* (both with implicit edges from every state).
* Where `S1` is the start state. The `C1` and later states are cleanup states
* that may be defined. The difference is that these states will never be
* skipped when marking the SSM as completed.
*
* You can also jump to any arbitrary state (while marking completion of the
* current state) while the machine is running. In other words there are
* implicit edges linking one state to every other state.
*
* To create an #fpi_ssm, you pass a state handler function and the total number of
* states (4 in the above example) to fpi_ssm_new (). Note that the state numbers
* start at zero, making them match the first value in a C enumeration.
* Use fpi_ssm_new() to create a new state machine with a defined number of
* states. Note that the state numbers start at zero, making them match the
* first value in a C enumeration.
*
* To start a ssm, you pass in a completion callback function to fpi_ssm_start()
* which gets called when the ssm completes (both on error and on failure).
* Starting a ssm also takes ownership of it.
* which gets called when the ssm completes (both on failure and on success).
* Starting a ssm also takes ownership of it and it will be automatically
* free'ed after the callback function has been called.
*
* To iterate to the next state, call fpi_ssm_next_state(). It is legal to
* attempt to iterate beyond the final state - this is equivalent to marking
@@ -59,7 +56,6 @@
*
* To mark successful completion of a SSM, either iterate beyond the final
* state or call fpi_ssm_mark_completed() from any state.
* This will also invalidate the machine, freeing it.
*
* To mark failed completion of a SSM, call fpi_ssm_mark_failed() from any
* state. You must pass a non-zero error code.
@@ -69,13 +65,9 @@
* which operations to perform (a switch statement is appropriate).
*
* Typically, the state handling function fires off an asynchronous
* communication with the device (such as a libsub transfer), and the
* communication with the device (such as a USB transfer), and the
* callback function iterates the machine to the next state
* upon success (or fails).
*
* Your completion callback should examine the return value of
* fpi_ssm_get_error() in order to determine whether the #FpiSsm completed or
* failed. An error code of zero indicates successful completion.
*/
struct _FpiSsm
@@ -86,11 +78,10 @@ struct _FpiSsm
gpointer ssm_data;
GDestroyNotify ssm_data_destroy;
int nr_states;
int start_cleanup;
int cur_state;
gboolean completed;
GSource *timeout;
GCancellable *cancellable;
gulong cancellable_id;
GError *error;
FpiSsmCompletedCallback callback;
FpiSsmHandlerCallback handler;
@@ -104,8 +95,9 @@ struct _FpiSsm
*
* Allocate a new ssm, with @nr_states states. The @handler callback
* will be called after each state transition.
* This is a macro that calls fpi_ssm_new_full() using the stringified
* version of @nr_states, so will work better with named parameters.
* This is a macro that calls fpi_ssm_new_full() using @nr_states as the
* cleanup states and using the stringified version of @nr_states. It should
* be used with an enum value.
*
* Returns: a new #FpiSsm state machine
*/
@@ -115,6 +107,7 @@ struct _FpiSsm
* @dev: a #fp_dev fingerprint device
* @handler: the callback function
* @nr_states: the number of states
* @start_cleanup: the first cleanup state
* @machine_name: the name of the state machine (for debug purposes)
*
* Allocate a new ssm, with @nr_states states. The @handler callback
@@ -126,17 +119,21 @@ FpiSsm *
fpi_ssm_new_full (FpDevice *dev,
FpiSsmHandlerCallback handler,
int nr_states,
int start_cleanup,
const char *machine_name)
{
FpiSsm *machine;
BUG_ON (dev == NULL);
BUG_ON (nr_states < 1);
BUG_ON (start_cleanup < 1);
BUG_ON (start_cleanup > nr_states);
BUG_ON (handler == NULL);
machine = g_new0 (FpiSsm, 1);
machine->handler = handler;
machine->nr_states = nr_states;
machine->start_cleanup = start_cleanup;
machine->dev = dev;
machine->name = g_strdup (machine_name);
machine->completed = TRUE;
@@ -202,59 +199,13 @@ fpi_ssm_clear_delayed_action (FpiSsm *machine)
{
g_return_if_fail (machine);
if (machine->cancellable_id)
{
g_cancellable_disconnect (machine->cancellable, machine->cancellable_id);
machine->cancellable_id = 0;
}
g_clear_object (&machine->cancellable);
g_clear_pointer (&machine->timeout, g_source_destroy);
}
typedef struct _CancelledActionIdleData
{
gulong cancellable_id;
GCancellable *cancellable;
} CancelledActionIdleData;
static gboolean
on_delayed_action_cancelled_idle (gpointer user_data)
{
CancelledActionIdleData *data = user_data;
g_cancellable_disconnect (data->cancellable, data->cancellable_id);
g_object_unref (data->cancellable);
g_free (data);
return G_SOURCE_REMOVE;
}
static void
on_delayed_action_cancelled (GCancellable *cancellable,
FpiSsm *machine)
{
CancelledActionIdleData *data;
fp_dbg ("[%s] %s cancelled delayed state change",
fp_device_get_driver (machine->dev), machine->name);
g_clear_pointer (&machine->timeout, g_source_destroy);
data = g_new0 (CancelledActionIdleData, 1);
data->cancellable = g_steal_pointer (&machine->cancellable);
data->cancellable_id = machine->cancellable_id;
machine->cancellable_id = 0;
g_idle_add_full (G_PRIORITY_HIGH_IDLE, on_delayed_action_cancelled_idle,
data, NULL);
}
static void
fpi_ssm_set_delayed_action_timeout (FpiSsm *machine,
int delay,
FpTimeoutFunc callback,
GCancellable *cancellable,
gpointer user_data,
GDestroyNotify destroy_func)
{
@@ -265,16 +216,6 @@ fpi_ssm_set_delayed_action_timeout (FpiSsm *machine,
fpi_ssm_clear_delayed_action (machine);
if (cancellable != NULL)
{
g_set_object (&machine->cancellable, cancellable);
machine->cancellable_id =
g_cancellable_connect (machine->cancellable,
G_CALLBACK (on_delayed_action_cancelled),
machine, NULL);
}
machine->timeout = fpi_device_add_timeout (machine->dev, delay, callback,
user_data, destroy_func);
}
@@ -380,11 +321,15 @@ fpi_ssm_start_subsm (FpiSsm *parent, FpiSsm *child)
* @machine: an #FpiSsm state machine
*
* Mark a ssm as completed successfully. The callback set when creating
* the state machine with fpi_ssm_new () will be called synchronously.
* the state machine with fpi_ssm_new() will be called synchronously.
*
* Note that any later cleanup state will still be executed.
*/
void
fpi_ssm_mark_completed (FpiSsm *machine)
{
int next_state;
g_return_if_fail (machine != NULL);
BUG_ON (machine->completed);
@@ -392,6 +337,19 @@ fpi_ssm_mark_completed (FpiSsm *machine)
fpi_ssm_clear_delayed_action (machine);
/* complete in a cleanup state just moves forward one step */
if (machine->cur_state < machine->start_cleanup)
next_state = machine->start_cleanup;
else
next_state = machine->cur_state + 1;
if (next_state < machine->nr_states)
{
machine->cur_state = next_state;
__ssm_call_handler (machine);
return;
}
machine->completed = TRUE;
if (machine->error)
@@ -423,24 +381,21 @@ on_device_timeout_complete (FpDevice *dev,
* fpi_ssm_mark_completed_delayed:
* @machine: an #FpiSsm state machine
* @delay: the milliseconds to wait before switching to the next state
* @cancellable: (nullable): a #GCancellable to cancel the delayed operation
*
* Mark a ssm as completed successfully with a delay of @delay ms.
* The callback set when creating the state machine with fpi_ssm_new () will be
* called when the timeout is over.
* The request can be cancelled passing a #GCancellable as @cancellable.
*/
void
fpi_ssm_mark_completed_delayed (FpiSsm *machine,
int delay,
GCancellable *cancellable)
int delay)
{
g_autofree char *source_name = NULL;
g_return_if_fail (machine != NULL);
fpi_ssm_set_delayed_action_timeout (machine, delay,
on_device_timeout_complete, cancellable,
on_device_timeout_complete,
machine, NULL);
source_name = g_strdup_printf ("[%s] ssm %s complete %d",
@@ -461,7 +416,9 @@ fpi_ssm_mark_failed (FpiSsm *machine, GError *error)
{
g_return_if_fail (machine != NULL);
g_assert (error);
if (machine->error)
/* During cleanup it is OK to call fpi_ssm_mark_failed a second time */
if (machine->error && machine->cur_state < machine->start_cleanup)
{
fp_warn ("[%s] SSM %s already has an error set, ignoring new error %s",
fp_device_get_driver (machine->dev), machine->name, error->message);
@@ -469,10 +426,15 @@ fpi_ssm_mark_failed (FpiSsm *machine, GError *error)
return;
}
fp_dbg ("[%s] SSM %s failed in state %d with error: %s",
fp_dbg ("[%s] SSM %s failed in state %d%s with error: %s",
fp_device_get_driver (machine->dev), machine->name,
machine->cur_state, error->message);
machine->cur_state,
machine->cur_state >= machine->start_cleanup ? " (cleanup)" : "",
error->message);
if (!machine->error)
machine->error = g_steal_pointer (&error);
else
g_error_free (error);
fpi_ssm_mark_completed (machine);
}
@@ -528,25 +490,21 @@ on_device_timeout_next_state (FpDevice *dev,
* fpi_ssm_next_state_delayed:
* @machine: an #FpiSsm state machine
* @delay: the milliseconds to wait before switching to the next state
* @cancellable: (nullable): a #GCancellable to cancel the delayed operation
*
* Iterate to next state of a state machine with a delay of @delay ms. If the
* current state is the last state, then the state machine will be marked as
* completed, as if calling fpi_ssm_mark_completed().
* Passing a valid #GCancellable will cause the action to be cancelled when
* @cancellable is.
*/
void
fpi_ssm_next_state_delayed (FpiSsm *machine,
int delay,
GCancellable *cancellable)
int delay)
{
g_autofree char *source_name = NULL;
g_return_if_fail (machine != NULL);
fpi_ssm_set_delayed_action_timeout (machine, delay,
on_device_timeout_next_state, cancellable,
on_device_timeout_next_state,
machine, NULL);
source_name = g_strdup_printf ("[%s] ssm %s jump to next state %d",
@@ -570,12 +528,15 @@ fpi_ssm_jump_to_state (FpiSsm *machine, int state)
g_return_if_fail (machine != NULL);
BUG_ON (machine->completed);
BUG_ON (state < 0 || state >= machine->nr_states);
BUG_ON (state < 0 || state > machine->nr_states);
BUG_ON (machine->timeout != NULL);
fpi_ssm_clear_delayed_action (machine);
machine->cur_state = state;
if (machine->cur_state == machine->nr_states)
fpi_ssm_mark_completed (machine);
else
__ssm_call_handler (machine);
}
@@ -600,24 +561,20 @@ on_device_timeout_jump_to_state (FpDevice *dev,
* @machine: an #FpiSsm state machine
* @state: the state to jump to
* @delay: the milliseconds to wait before switching to @state state
* @cancellable: (nullable): a #GCancellable to cancel the delayed operation
*
* Jump to the @state state with a delay of @delay milliseconds, bypassing
* intermediary states.
* Passing a valid #GCancellable will cause the action to be cancelled when
* @cancellable is.
*/
void
fpi_ssm_jump_to_state_delayed (FpiSsm *machine,
int state,
int delay,
GCancellable *cancellable)
int delay)
{
FpiSsmJumpToStateDelayedData *data;
g_autofree char *source_name = NULL;
g_return_if_fail (machine != NULL);
BUG_ON (state < 0 || state >= machine->nr_states);
BUG_ON (state < 0 || state > machine->nr_states);
data = g_new0 (FpiSsmJumpToStateDelayedData, 1);
data->machine = machine;
@@ -625,7 +582,7 @@ fpi_ssm_jump_to_state_delayed (FpiSsm *machine,
fpi_ssm_set_delayed_action_timeout (machine, delay,
on_device_timeout_jump_to_state,
cancellable, data, g_free);
data, g_free);
source_name = g_strdup_printf ("[%s] ssm %s jump to state %d",
fp_device_get_device_id (machine->dev),

View File

@@ -60,10 +60,11 @@ 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)
fpi_ssm_new_full (dev, handler, nr_states, nr_states, #nr_states)
FpiSsm *fpi_ssm_new_full (FpDevice *dev,
FpiSsmHandlerCallback handler,
int nr_states,
int start_cleanup,
const char *machine_name);
void fpi_ssm_free (FpiSsm *machine);
void fpi_ssm_start (FpiSsm *ssm,
@@ -76,17 +77,14 @@ void fpi_ssm_next_state (FpiSsm *machine);
void fpi_ssm_jump_to_state (FpiSsm *machine,
int state);
void fpi_ssm_next_state_delayed (FpiSsm *machine,
int delay,
GCancellable *cancellable);
int delay);
void fpi_ssm_jump_to_state_delayed (FpiSsm *machine,
int state,
int delay,
GCancellable *cancellable);
int delay);
void fpi_ssm_cancel_delayed_state_change (FpiSsm *machine);
void fpi_ssm_mark_completed (FpiSsm *machine);
void fpi_ssm_mark_completed_delayed (FpiSsm *machine,
int delay,
GCancellable *cancellable);
int delay);
void fpi_ssm_mark_failed (FpiSsm *machine,
GError *error);
void fpi_ssm_set_data (FpiSsm *machine,

View File

@@ -354,9 +354,10 @@ transfer_finish_cb (GObject *source_object, GAsyncResult *res, gpointer user_dat
fpi_usb_transfer_unref (transfer);
}
static gboolean
transfer_cancel_cb (FpiUsbTransfer *transfer)
static void
transfer_cancel_cb (FpDevice *device, gpointer user_data)
{
FpiUsbTransfer *transfer = user_data;
GError *error;
FpiUsbTransferCallback callback;
@@ -369,8 +370,6 @@ transfer_cancel_cb (FpiUsbTransfer *transfer)
callback (transfer, transfer->device, transfer->user_data, error);
fpi_usb_transfer_unref (transfer);
return G_SOURCE_REMOVE;
}
/**
@@ -413,7 +412,8 @@ fpi_usb_transfer_submit (FpiUsbTransfer *transfer,
*/
if (cancellable && g_cancellable_is_cancelled (cancellable))
{
g_idle_add ((GSourceFunc) transfer_cancel_cb, transfer);
fpi_device_add_timeout (transfer->device, 0,
transfer_cancel_cb, transfer, NULL);
return;
}

View File

@@ -28,8 +28,8 @@
GHashTable *printed = NULL;
static GList *
insert_drivers (GList *list)
static void
insert_drivers (GList **usb_list, GList **spi_list)
{
g_autoptr(GArray) drivers = fpi_get_driver_types ();
gint i;
@@ -41,8 +41,9 @@ insert_drivers (GList *list)
g_autoptr(FpDeviceClass) cls = g_type_class_ref (driver);
const FpIdEntry *entry;
if (cls->type != FP_DEVICE_TYPE_USB)
continue;
switch (cls->type)
{
case FP_DEVICE_TYPE_USB:
for (entry = cls->id_table; entry->vid; entry++)
{
@@ -58,17 +59,52 @@ insert_drivers (GList *list)
g_hash_table_insert (printed, key, GINT_TO_POINTER (1));
list = g_list_prepend (list, g_strdup_printf ("%s | %s\n", key, cls->full_name));
*usb_list = g_list_prepend (*usb_list,
g_strdup_printf ("%s | %s\n", key, cls->full_name));
}
break;
case FP_DEVICE_TYPE_UDEV:
for (entry = cls->id_table; entry->udev_types; entry++)
{
char *key;
/* Need SPI device */
if ((entry->udev_types & FPI_DEVICE_UDEV_SUBTYPE_SPIDEV) == 0)
continue;
key = g_strdup_printf ("SPI:%s:%04x:%04x", entry->spi_acpi_id, entry->hid_id.vid, entry->hid_id.pid);
if (g_hash_table_lookup (printed, key) != NULL)
{
g_free (key);
continue;
}
return list;
g_hash_table_insert (printed, key, GINT_TO_POINTER (1));
if (entry->udev_types & FPI_DEVICE_UDEV_SUBTYPE_HIDRAW)
*spi_list = g_list_prepend (*spi_list,
g_strdup_printf ("%s | %04x:%04x | %s\n", entry->spi_acpi_id, entry->hid_id.vid, entry->hid_id.pid, cls->full_name));
else
*spi_list = g_list_prepend (*spi_list,
g_strdup_printf ("%s | - | %s\n", entry->spi_acpi_id, cls->full_name));
}
break;
case FP_DEVICE_TYPE_VIRTUAL:
default:
break;
}
}
}
int
main (int argc, char **argv)
{
GList *list, *l;
GList *usb_list = NULL;
GList *spi_list = NULL;
GList *l;
setlocale (LC_ALL, "");
@@ -83,19 +119,36 @@ main (int argc, char **argv)
g_print ("\n");
g_print ("This is a list of supported devices in libfprint's development version. Those drivers might not all be available in the stable, released version. If in doubt, contact your distribution or systems integrator for details.\n");
g_print ("\n");
insert_drivers (&usb_list, &spi_list);
g_print ("## USB devices\n");
g_print ("\n");
g_print ("USB ID | Driver\n");
g_print ("------------ | ------------\n");
list = NULL;
list = insert_drivers (list);
list = g_list_sort (list, (GCompareFunc) g_strcmp0);
for (l = list; l != NULL; l = l->next)
usb_list = g_list_sort (usb_list, (GCompareFunc) g_strcmp0);
for (l = usb_list; l != NULL; l = l->next)
g_print ("%s", (char *) l->data);
g_print ("\n");
g_list_free_full (usb_list, g_free);
g_print ("## SPI devices\n");
g_print ("\n");
g_print ("The ACPI ID represents the SPI interface. Some sensors are also connected to a HID device (Human Input Device) for side-channel requests such as resets.\n");
g_print ("\n");
g_print ("ACPI ID | HID ID | Driver\n");
g_print ("------------ | ------------ | ------------\n");
spi_list = g_list_sort (spi_list, (GCompareFunc) g_strcmp0);
for (l = spi_list; l != NULL; l = l->next)
g_print ("%s", (char *) l->data);
g_print ("\n");
g_list_free_full (usb_list, g_free);
g_list_free_full (list, g_free);
g_hash_table_destroy (printed);
return 0;

View File

@@ -33,7 +33,6 @@ static const FpIdEntry whitelist_id_table[] = {
{ .vid = 0x04f3, .pid = 0x0c00 },
{ .vid = 0x04f3, .pid = 0x0c4b },
{ .vid = 0x04f3, .pid = 0x0c4c },
{ .vid = 0x04f3, .pid = 0x0c4f },
{ .vid = 0x04f3, .pid = 0x0c57 },
{ .vid = 0x04f3, .pid = 0x0c5e },
{ .vid = 0x04f3, .pid = 0x2706 },
@@ -50,6 +49,7 @@ static const FpIdEntry whitelist_id_table[] = {
{ .vid = 0x06cb, .pid = 0x00cb },
{ .vid = 0x06cb, .pid = 0x00d8 },
{ .vid = 0x06cb, .pid = 0x00da },
{ .vid = 0x06cb, .pid = 0x00e9 },
{ .vid = 0x0a5c, .pid = 0x5801 },
{ .vid = 0x0a5c, .pid = 0x5805 },
{ .vid = 0x0a5c, .pid = 0x5834 },
@@ -75,7 +75,6 @@ static const FpIdEntry whitelist_id_table[] = {
{ .vid = 0x1491, .pid = 0x0088 },
{ .vid = 0x16d1, .pid = 0x1027 },
{ .vid = 0x1c7a, .pid = 0x0300 },
{ .vid = 0x1c7a, .pid = 0x0570 },
{ .vid = 0x1c7a, .pid = 0x0575 },
{ .vid = 0x27c6, .pid = 0x5042 },
{ .vid = 0x27c6, .pid = 0x5110 },

View File

@@ -0,0 +1,93 @@
/*
* Copyright (C) 2009 Red Hat <mjg@redhat.com>
* Copyright (C) 2008 Bastien Nocera <hadess@hadess.net>
* Copyright (C) 2008 Timo Hoenig <thoenig@suse.de>, <thoenig@nouse.net>
* Coypright (C) 2019 Benjamin Berg <bberg@redhat.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <config.h>
#include "fpi-context.h"
#include "fpi-device.h"
GHashTable *printed = NULL;
static void
print_driver (const FpDeviceClass *cls)
{
const FpIdEntry *entry;
gint num_printed = 0;
if (cls->type != FP_DEVICE_TYPE_UDEV)
return;
for (entry = cls->id_table; entry->udev_types != 0; entry++)
{
/* We only add rules for spidev right now. */
if ((entry->udev_types & FPI_DEVICE_UDEV_SUBTYPE_SPIDEV) == 0)
continue;
if (g_hash_table_lookup (printed, entry->spi_acpi_id) != NULL)
continue;
g_hash_table_insert (printed, g_strdup (entry->spi_acpi_id), GINT_TO_POINTER (1));
if (num_printed == 0)
g_print ("# %s\n", cls->full_name);
g_print ("ACTION==\"add|change\", SUBSYSTEM==\"spi\", ENV{MODALIAS}==\"acpi:%s:\", RUN{builtin}+=\"kmod load spi:spidev\", RUN+=\"/bin/sh -c 'echo spidev > %%S%%p/driver_override && echo %%k > %%S%%p/subsystem/drivers/spidev/bind'\"\n",
entry->spi_acpi_id);
num_printed++;
}
if (num_printed > 0)
g_print ("\n");
}
int
main (int argc, char **argv)
{
g_autoptr(GArray) drivers = fpi_get_driver_types ();
guint i;
printed = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
g_print ("# This file is part of libfprint\n");
g_print ("# Do not modify this file, it will get overwritten on updates.\n");
g_print ("# To override or extend the rules place a file in /etc/udev/rules.d\n");
g_print ("\n");
for (i = 0; i < drivers->len; i++)
{
GType driver = g_array_index (drivers, GType, i);
FpDeviceClass *cls = FP_DEVICE_CLASS (g_type_class_ref (driver));
if (cls->type != FP_DEVICE_TYPE_UDEV)
{
g_type_class_unref (cls);
continue;
}
print_driver (cls);
g_type_class_unref (cls);
}
g_hash_table_destroy (printed);
return 0;
}

View File

@@ -80,125 +80,91 @@ nbis_sources = [
'nbis/mindtct/xytreps.c',
]
aeslib = false
aesx660 = false
aes3k = false
driver_sources = {
'upekts' :
[ 'drivers/upekts.c', 'drivers/upek_proto.c' ],
'upektc' :
[ 'drivers/upektc.c' ],
'upeksonly' :
[ 'drivers/upeksonly.c' ],
'uru4000' :
[ 'drivers/uru4000.c' ],
'aes1610' :
[ 'drivers/aes1610.c' ],
'aes1660' :
[ 'drivers/aes1660.c' ],
'aes2501' :
[ 'drivers/aes2501.c' ],
'aes2550' :
[ 'drivers/aes2550.c' ],
'aes2660' :
[ 'drivers/aes2660.c' ],
'aes3500' :
[ 'drivers/aes3500.c' ],
'aes4000' :
[ 'drivers/aes4000.c' ],
'vcom5s' :
[ 'drivers/vcom5s.c' ],
'vfs101' :
[ 'drivers/vfs101.c' ],
'vfs301' :
[ 'drivers/vfs301.c', 'drivers/vfs301_proto.c' ],
'vfs5011' :
[ 'drivers/vfs5011.c' ],
'vfs7552' :
[ 'drivers/vfs7552.c' ],
'upektc_img' :
[ 'drivers/upektc_img.c', 'drivers/upek_proto.c' ],
'etes603' :
[ 'drivers/etes603.c' ],
'egis0570' :
[ 'drivers/egis0570.c' ],
'vfs0050' :
[ 'drivers/vfs0050.c' ],
'elan' :
[ 'drivers/elan.c' ],
'elanmoc' :
[ 'drivers/elanmoc/elanmoc.c' ],
'elanspi' :
[ 'drivers/elanspi.c' ],
'nb1010' :
[ 'drivers/nb1010.c' ],
'virtual_image' :
[ 'drivers/virtual-image.c' ],
'virtual_device' :
[ 'drivers/virtual-device.c' ],
'virtual_device_storage' :
[ 'drivers/virtual-device-storage.c' ],
'synaptics' :
[ 'drivers/synaptics/synaptics.c', 'drivers/synaptics/bmkt_message.c' ],
'goodixmoc' :
[ 'drivers/goodixmoc/goodix.c', 'drivers/goodixmoc/goodix_proto.c' ],
}
helper_sources = {
'aeslib' :
[ 'drivers/aeslib.c' ],
'aesx660' :
[ 'drivers/aesx660.c' ],
'aes3k' :
[ 'drivers/aes3k.c' ],
'nss' :
[ ],
'udev' :
[ ],
'virtual' :
[ 'drivers/virtual-device-listener.c' ],
}
drivers_sources = []
drivers_cflags = []
foreach driver: drivers
if driver == 'upekts'
drivers_sources += [ 'drivers/upekts.c', 'drivers/upek_proto.c' ]
endif
if driver == 'upektc'
drivers_sources += [ 'drivers/upektc.c' ]
endif
if driver == 'upeksonly'
drivers_sources += [ 'drivers/upeksonly.c' ]
endif
if driver == 'uru4000'
drivers_sources += [ 'drivers/uru4000.c' ]
endif
if driver == 'aes1610'
drivers_sources += [ 'drivers/aes1610.c' ]
aeslib = true
endif
if driver == 'aes1660'
drivers_sources += [ 'drivers/aes1660.c' ]
aeslib = true
aesx660 = true
endif
if driver == 'aes2501'
drivers_sources += [ 'drivers/aes2501.c' ]
aeslib = true
endif
if driver == 'aes2550'
drivers_sources += [ 'drivers/aes2550.c' ]
aeslib = true
endif
if driver == 'aes2660'
drivers_sources += [ 'drivers/aes2660.c' ]
aeslib = true
aesx660 = true
endif
if driver == 'aes3500'
drivers_sources += [ 'drivers/aes3500.c' ]
aeslib = true
aes3k = true
endif
if driver == 'aes4000'
drivers_sources += [ 'drivers/aes4000.c' ]
aeslib = true
aes3k = true
endif
if driver == 'vcom5s'
drivers_sources += [ 'drivers/vcom5s.c' ]
endif
if driver == 'vfs101'
drivers_sources += [ 'drivers/vfs101.c' ]
endif
if driver == 'vfs301'
drivers_sources += [ 'drivers/vfs301.c', 'drivers/vfs301_proto.c' ]
endif
if driver == 'vfs5011'
drivers_sources += [ 'drivers/vfs5011.c' ]
endif
if driver == 'vfs7552'
drivers_sources += [ 'drivers/vfs7552.c' ]
endif
if driver == 'upektc_img'
drivers_sources += [ 'drivers/upektc_img.c', 'drivers/upek_proto.c' ]
endif
if driver == 'etes603'
drivers_sources += [ 'drivers/etes603.c' ]
endif
if driver == 'vfs0050'
drivers_sources += [ 'drivers/vfs0050.c' ]
endif
if driver == 'elan'
drivers_sources += [ 'drivers/elan.c' ]
endif
if driver == 'virtual_image'
drivers_sources += [ 'drivers/virtual-image.c' ]
endif
if driver == 'virtual_device'
drivers_sources += [ 'drivers/virtual-device.c' ]
endif
if driver == 'virtual_device_storage'
drivers_sources += [ 'drivers/virtual-device-storage.c' ]
endif
if driver.startswith('virtual_')
drivers_sources += [ 'drivers/virtual-device-listener.c' ]
endif
if driver == 'synaptics'
drivers_sources += [
'drivers/synaptics/synaptics.c',
'drivers/synaptics/bmkt_message.c',
]
endif
if driver == 'goodixmoc'
drivers_sources += [
'drivers/goodixmoc/goodix.c',
'drivers/goodixmoc/goodix_proto.c',
]
endif
if driver == 'nb1010'
drivers_sources += [
'drivers/nb1010.c',
]
endif
drivers_sources += driver_sources[driver]
endforeach
foreach helper : driver_helpers
drivers_sources += helper_sources[helper]
endforeach
if aeslib
drivers_sources += [ 'drivers/aeslib.c' ]
endif
if aesx660
drivers_sources += ['drivers/aesx660.c' ]
endif
if aes3k
drivers_sources += ['drivers/aes3k.c' ]
endif
other_sources = []
fp_enums = gnome.mkenums_simple('fp-enums',
sources: libfprint_public_headers,
@@ -217,6 +183,28 @@ enums_dep = declare_dependency(
sources: [ fp_enums_h, fpi_enums_h ]
)
# Export the drivers' types to the core code
drivers_type_list = []
drivers_type_func = []
drivers_type_list += '#include <glib-object.h>'
drivers_type_list += '#include "fpi-context.h"'
drivers_type_list += ''
drivers_type_func += 'GArray *'
drivers_type_func += 'fpi_get_driver_types (void)'
drivers_type_func += '{'
drivers_type_func += ' GArray *drivers = g_array_new (TRUE, FALSE, sizeof (GType));'
drivers_type_func += ' GType t;'
drivers_type_func += ''
foreach driver: supported_drivers
drivers_type_list += 'extern GType (fpi_device_' + driver + '_get_type) (void);'
drivers_type_func += ' t = fpi_device_' + driver + '_get_type ();'
drivers_type_func += ' g_array_append_val (drivers, t);'
drivers_type_func += ''
endforeach
drivers_type_list += ''
drivers_type_func += ' return drivers;'
drivers_type_func += '}'
drivers_sources += configure_file(input: 'empty_file',
output: 'fpi-drivers.c',
capture: true,
@@ -231,11 +219,8 @@ deps = [
glib_dep,
gobject_dep,
gusb_dep,
gudev_dep,
imaging_dep,
mathlib_dep,
nss_dep,
]
] + optional_deps
# These are empty and only exist so that the include directories are created
# in the build tree. This silences a build time warning.
@@ -282,7 +267,6 @@ libfprint = shared_library(versioned_libname.split('lib')[1],
sources: [
fp_enums,
libfprint_sources,
other_sources,
],
soversion: soversion,
version: libversion,
@@ -329,6 +313,23 @@ udev_hwdb_generator = custom_target('udev-hwdb',
install: false,
)
if install_udev_rules
udev_rules = executable('fprint-list-udev-rules',
'fprint-list-udev-rules.c',
dependencies: libfprint_private_dep,
link_with: libfprint_drivers,
install: false)
custom_target('udev-rules',
output: '70-@0@.rules'.format(versioned_libname),
depend_files: drivers_sources,
capture: true,
command: [ udev_rules ],
install: true,
install_dir: udev_rules_dir,
)
endif
custom_target('sync-udev-hwdb',
depends: udev_hwdb_generator,
output: 'sync-udev-hwdb',

View File

@@ -1,5 +1,5 @@
project('libfprint', [ 'c', 'cpp' ],
version: '1.90.7',
version: '1.92.1',
license: 'LGPLv2.1+',
default_options: [
'buildtype=debugoptimized',
@@ -33,6 +33,7 @@ common_cflags = cc.get_supported_arguments([
'-Wmissing-noreturn',
'-Wpointer-arith',
'-Wshadow',
'-Wswitch-enum',
'-Wtype-limits',
'-Wundef',
'-Wunused',
@@ -86,6 +87,9 @@ mathlib_dep = cc.find_library('m', required: false)
# The following dependencies are only used for tests
cairo_dep = dependency('cairo', required: false)
# introspection scanning and Gio-2.0.gir
gobject_introspection = dependency('gobject-introspection-1.0', required: get_option('introspection'))
# Drivers
drivers = get_option('drivers').split(',')
virtual_drivers = [
@@ -94,9 +98,6 @@ virtual_drivers = [
'virtual_device_storage',
]
udev_drivers = [
]
default_drivers = [
'upektc_img',
'vfs5011',
@@ -112,15 +113,20 @@ default_drivers = [
'vfs301',
'vfs0050',
'etes603',
'egis0570',
'vcom5s',
'synaptics',
'elan',
'elanmoc',
'uru4000',
'upektc',
'upeksonly',
'upekts',
'goodixmoc',
'nb1010'
'nb1010',
# SPI
'elanspi',
]
# FIXME: All the drivers should be fixed by adjusting the byte order.
@@ -130,7 +136,7 @@ endian_independent_drivers = virtual_drivers + [
'synaptics',
]
all_drivers = default_drivers + virtual_drivers + udev_drivers
all_drivers = default_drivers + virtual_drivers
if drivers == [ 'all' ]
drivers = all_drivers
@@ -140,6 +146,33 @@ if drivers == [ 'default' ]
drivers = default_drivers
endif
driver_helper_mapping = {
'aes1610' : [ 'aeslib' ],
'aes1660' : [ 'aeslib', 'aesx660' ],
'aes2501' : [ 'aeslib' ],
'aes2550' : [ 'aeslib' ],
'aes2660' : [ 'aeslib', 'aesx660' ],
'aes3500' : [ 'aeslib', 'aes3k' ],
'aes4000' : [ 'aeslib', 'aes3k' ],
'uru4000' : [ 'nss' ],
'elanspi' : [ 'udev' ],
'virtual_image' : [ 'virtual' ],
'virtual_device' : [ 'virtual' ],
'virtual_device_storage' : [ 'virtual' ],
}
driver_helpers = []
foreach driver : drivers
if driver in driver_helper_mapping
foreach helper : driver_helper_mapping[driver]
if helper not in driver_helpers
driver_helpers += helper
endif
endforeach
endif
endforeach
if drivers.length() == 0 or drivers[0] == ''
error('Cannot build libfprint without drivers, please specify a valid value for the drivers option')
endif
@@ -156,38 +189,61 @@ else
endforeach
endif
nss_dep = dependency('', required: false)
imaging_dep = dependency('', required: false)
gudev_dep = dependency('', required: false)
libfprint_conf.set10('HAVE_PIXMAN', false)
foreach driver: drivers
if driver == 'uru4000'
nss_dep = dependency('nss', required: false)
if not nss_dep.found()
error('NSS is required for the URU4000/URU4500 driver')
udev_rules = get_option('udev_rules')
install_udev_rules = udev_rules.enabled()
optional_deps = []
# Resolve extra dependencies
foreach i : driver_helpers
foreach d, helpers : driver_helper_mapping
if i in helpers
driver = d
break
endif
endif
if driver == 'aes3500' or driver == 'aes4000'
endforeach
if i == 'aes3k'
imaging_dep = dependency('pixman-1', required: false)
if not imaging_dep.found()
error('pixman is required for imaging support')
error('pixman is required for @0@ and possibly others'.format(driver))
endif
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))
endif
if udev_drivers.contains(driver)
optional_deps += nss_dep
elif i == 'udev'
install_udev_rules = true
gudev_dep = dependency('gudev-1.0', required: false)
if not gudev_dep.found()
error('udev is required for SPI support')
endif
libfprint_conf.set10('HAVE_UDEV', true)
endif
if not all_drivers.contains(driver)
error('Invalid driver \'' + driver + '\'')
optional_deps += gudev_dep
endif
endforeach
if udev_rules.disabled()
install_udev_rules = false
endif
if install_udev_rules
udev_rules_dir = get_option('udev_rules_dir')
if udev_rules_dir == 'auto'
udev_dep = dependency('udev')
udev_rules_dir = udev_dep.get_pkgconfig_variable('udevdir') + '/rules.d'
endif
endif
supported_drivers = []
foreach driver: drivers
if build_machine.endian() == 'little' or driver in endian_independent_drivers
@@ -202,28 +258,6 @@ if default_drivers_are_enabled and supported_drivers != drivers
default_drivers_are_enabled = false
endif
# Export the drivers' types to the core code
drivers_type_list = []
drivers_type_func = []
drivers_type_list += '#include <glib-object.h>'
drivers_type_list += '#include "fpi-context.h"'
drivers_type_list += ''
drivers_type_func += 'GArray *'
drivers_type_func += 'fpi_get_driver_types (void)'
drivers_type_func += '{'
drivers_type_func += ' GArray *drivers = g_array_new (TRUE, FALSE, sizeof (GType));'
drivers_type_func += ' GType t;'
drivers_type_func += ''
foreach driver: supported_drivers
drivers_type_list += 'extern GType (fpi_device_' + driver + '_get_type) (void);'
drivers_type_func += ' t = fpi_device_' + driver + '_get_type ();'
drivers_type_func += ' g_array_append_val (drivers, t);'
drivers_type_func += ''
endforeach
drivers_type_list += ''
drivers_type_func += ' return drivers;'
drivers_type_func += '}'
root_inc = include_directories('.')
udev_hwdb = get_option('udev_hwdb')
@@ -258,9 +292,11 @@ if get_option('gtk-examples')
endif
endif
# Some dependency resolving happens inside here
subdir('libfprint')
configure_file(output: 'config.h', configuration: libfprint_conf)
subdir('libfprint')
subdir('examples')
if get_option('doc')
gnome = import('gnome')

View File

@@ -6,8 +6,16 @@ option('introspection',
description: 'Build GObject Introspection repository',
type: 'boolean',
value: true)
option('udev_rules',
description: 'Whether to create and install udev rules (auto: turn on when needed by a driver)',
type: 'feature',
value: 'auto')
option('udev_rules_dir',
description: 'Installation path for udev rules',
type: 'string',
value: 'auto')
option('udev_hwdb',
description: 'Whether to create a udev hwdb',
description: 'Whether to create a udev hwdb for autosuspend (included in systemd v248 and later)',
type: 'feature',
value: 'auto')
option('udev_hwdb_dir',

View File

@@ -137,3 +137,7 @@ pos_conditional Trail
# custom keywords
set FOR udev_list_entry_foreach
# macros
macro-open G_GNUC_BEGIN_IGNORE_DEPRECATIONS
macro-close G_GNUC_END_IGNORE_DEPRECATIONS

View File

@@ -12,8 +12,11 @@ case "$1" in
;;
esac
ARGS=4
JOBS=4
pushd "$SRCROOT"
uncrustify -c "$CFG" $OPTS `git ls-tree --name-only -r HEAD | grep -E '.*\.[ch]$' | grep -v nbis | grep -v fpi-byte | grep -v build/`
git ls-tree --name-only -r HEAD | grep -E '.*\.[ch]$' | grep -v nbis | grep -v fpi-byte | grep -v build/ | xargs -n$ARGS -P $JOBS uncrustify -c "$CFG" $OPTS
RES=$?
popd
exit $RES

View File

@@ -7,8 +7,9 @@ This document describes how to create a 'capture' test: a test that
captures a picture of a fingerprint from the device (mocked by
`umockdev`) and compares it with the standard one.
Other kinds of `umockdev` tests could be created in a similar manner.
Other kinds of `umockdev` tests can be created in a similar manner. For
match-on-chip devices you would instead create a test specific `custom.py`
script, capture it and store the capture to `custom.pcapng`.
'Capture' Test Creation
-----------------------
@@ -19,6 +20,10 @@ A new 'capture' test is created by means of `capture.py` script:
`mkdir DRIVER`
Note that the name must be the exact name of the libfprint driver,
or the exact name of the driver followed by a `-` and a unique identifier
of your choosing.
2. Prepare your execution environment.
In the next step a working and up to date libfprint is needed. This can be
@@ -50,12 +55,14 @@ A new 'capture' test is created by means of `capture.py` script:
`umockdev-record /dev/bus/usb/001/005 > DRIVER/device`
5. Record interaction of `capture.py` (or other test) with the device:
5. Record interaction of `capture.py` (or other test) with the device. To do
so, start wireshark and record `usbmonX` (where X is the bus number). Then
run the test script:
`umockdev-record -i /dev/bus/usb/001/005=DRIVER/capture.ioctl -- python3 ./capture.py DRIVER/capture.png`
`python3 ./capture.py DRIVER/capture.png`
Files `capture.ioctl` and `capture.png` will be created as the
result of this command.
Save the wireshark recording as `capture.pcapng`. The command will create
`capture.png`.
6. Add driver's name to `drivers_tests` in the `meson.build`.
7. Check whether everything works as expected.
@@ -66,28 +73,6 @@ arm, or anything else producing an image with the device can be used.
Possible Issues
---------------
`umockdev-record` aggressively groups URBs. In most cases, manual
intervention is unfortunately required. Often, drivers do a chain of
commands like: A then B each with a different reply. However,
`umockdev-record` could create a file like this:
A
reply 1
reply 2
B
reply 1
reply 2
In that case, records must be re-ordered:
A
reply 1
B
reply 1
A
reply 2
B
reply 2
Other changes may be needed to get everything working. For example the
`elan` driver relies on a timeout that is not reported correctly. In

View File

@@ -17,6 +17,14 @@ c.enumerate()
devices = c.get_devices()
d = devices[0]
assert 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 not d.has_feature(FPrint.DeviceFeature.STORAGE)
assert not d.has_feature(FPrint.DeviceFeature.STORAGE_LIST)
assert not d.has_feature(FPrint.DeviceFeature.STORAGE_DELETE)
assert not d.has_feature(FPrint.DeviceFeature.STORAGE_CLEAR)
del devices
d.open_sync()

BIN
tests/egis0570/capture.pcapng Executable file

Binary file not shown.

BIN
tests/egis0570/capture.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 100 KiB

228
tests/egis0570/device Normal file
View File

@@ -0,0 +1,228 @@
P: /devices/pci0000:00/0000:00:14.0/usb1/1-9
N: bus/usb/001/005=12011001000000087A1C700541100102030109022000010100A0320904000002FF0000000705830240000007050402400003
E: DEVNAME=/dev/bus/usb/001/005
E: DEVTYPE=usb_device
E: DRIVER=usb
E: PRODUCT=1c7a/570/1041
E: TYPE=0/0/0
E: BUSNUM=001
E: DEVNUM=005
E: MAJOR=189
E: MINOR=4
E: SUBSYSTEM=usb
E: ID_VENDOR=EgisTec
E: ID_VENDOR_ENC=EgisTec
E: ID_VENDOR_ID=1c7a
E: ID_MODEL=EgisTec_Touch_Fingerprint_Sensor
E: ID_MODEL_ENC=EgisTec\x20Touch\x20Fingerprint\x20Sensor
E: ID_MODEL_ID=0570
E: ID_REVISION=1041
E: ID_SERIAL=EgisTec_EgisTec_Touch_Fingerprint_Sensor_W700B41B
E: ID_SERIAL_SHORT=W700B41B
E: ID_BUS=usb
E: ID_USB_INTERFACES=:ff0000:
E: ID_VENDOR_FROM_DATABASE=LighTuning Technology Inc.
E: ID_PATH=pci-0000:00:14.0-usb-0:9
E: ID_PATH_TAG=pci-0000_00_14_0-usb-0_9
E: LIBFPRINT_DRIVER=Hardcoded whitelist
A: authorized=1
A: avoid_reset_quirk=0
A: bConfigurationValue=1
A: bDeviceClass=00
A: bDeviceProtocol=00
A: bDeviceSubClass=00
A: bMaxPacketSize0=8
A: bMaxPower=100mA
A: bNumConfigurations=1
A: bNumInterfaces= 1
A: bcdDevice=1041
A: bmAttributes=a0
A: busnum=1
A: configuration=
H: descriptors=12011001000000087A1C700541100102030109022000010100A0320904000002FF0000000705830240000007050402400003
A: dev=189:4
A: devnum=5
A: devpath=9
L: driver=../../../../../bus/usb/drivers/usb
A: idProduct=0570
A: idVendor=1c7a
A: ltm_capable=no
A: manufacturer=EgisTec
A: maxchild=0
L: port=../1-0:1.0/usb1-port9
A: power/active_duration=362352
A: power/async=enabled
A: power/autosuspend=2
A: power/autosuspend_delay_ms=2000
A: power/connected_duration=5526124
A: power/control=auto
A: power/level=auto
A: power/persist=1
A: power/runtime_active_kids=0
A: power/runtime_active_time=365097
A: power/runtime_enabled=enabled
A: power/runtime_status=active
A: power/runtime_suspended_time=5160752
A: power/runtime_usage=0
A: power/wakeup=disabled
A: power/wakeup_abort_count=
A: power/wakeup_active=
A: power/wakeup_active_count=
A: power/wakeup_count=
A: power/wakeup_expire_count=
A: power/wakeup_last_time_ms=
A: power/wakeup_max_time_ms=
A: power/wakeup_total_time_ms=
A: product=EgisTec Touch Fingerprint Sensor
A: quirks=0x0
A: removable=fixed
A: rx_lanes=1
A: serial=W700B41B
A: speed=12
A: tx_lanes=1
A: urbnum=8040
A: version= 1.10
P: /devices/pci0000:00/0000:00:14.0/usb1
N: bus/usb/001/001=12010002090001406B1D020008050302010109021900010100E0000904000001090000000705810304000C
E: DEVNAME=/dev/bus/usb/001/001
E: DEVTYPE=usb_device
E: DRIVER=usb
E: PRODUCT=1d6b/2/508
E: TYPE=9/0/1
E: BUSNUM=001
E: DEVNUM=001
E: MAJOR=189
E: MINOR=0
E: SUBSYSTEM=usb
E: ID_VENDOR=Linux_5.8.0-59-generic_xhci-hcd
E: ID_VENDOR_ENC=Linux\x205.8.0-59-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=0508
E: ID_SERIAL=Linux_5.8.0-59-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_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:
A: authorized=1
A: authorized_default=1
A: avoid_reset_quirk=0
A: bConfigurationValue=1
A: bDeviceClass=09
A: bDeviceProtocol=01
A: bDeviceSubClass=00
A: bMaxPacketSize0=64
A: bMaxPower=0mA
A: bNumConfigurations=1
A: bNumInterfaces= 1
A: bcdDevice=0508
A: bmAttributes=e0
A: busnum=1
A: configuration=
H: descriptors=12010002090001406B1D020008050302010109021900010100E0000904000001090000000705810304000C
A: dev=189:0
A: devnum=1
A: devpath=0
L: driver=../../../../bus/usb/drivers/usb
A: idProduct=0002
A: idVendor=1d6b
A: interface_authorized_default=1
A: ltm_capable=no
A: manufacturer=Linux 5.8.0-59-generic xhci-hcd
A: maxchild=12
A: power/active_duration=378024
A: power/async=enabled
A: power/autosuspend=0
A: power/autosuspend_delay_ms=0
A: power/connected_duration=5527220
A: power/control=auto
A: power/level=auto
A: power/runtime_active_kids=1
A: power/runtime_active_time=377962
A: power/runtime_enabled=enabled
A: power/runtime_status=active
A: power/runtime_suspended_time=5149253
A: power/runtime_usage=0
A: power/wakeup=disabled
A: power/wakeup_abort_count=
A: power/wakeup_active=
A: power/wakeup_active_count=
A: power/wakeup_count=
A: power/wakeup_expire_count=
A: power/wakeup_last_time_ms=
A: power/wakeup_max_time_ms=
A: power/wakeup_total_time_ms=
A: product=xHCI Host Controller
A: quirks=0x0
A: removable=unknown
A: rx_lanes=1
A: serial=0000:00:14.0
A: speed=480
A: tx_lanes=1
A: urbnum=956
A: version= 2.00
P: /devices/pci0000:00/0000:00:14.0
E: DRIVER=xhci_hcd
E: PCI_CLASS=C0330
E: PCI_ID=8086:9D2F
E: PCI_SUBSYS_ID=1025:118E
E: PCI_SLOT_NAME=0000:00:14.0
E: MODALIAS=pci:v00008086d00009D2Fsv00001025sd0000118Ebc0Csc03i30
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=Sunrise Point-LP USB 3.0 xHCI Controller
A: ari_enabled=0
A: broken_parity_status=0
A: class=0x0c0330
H: config=86802F9D060490022130030C00008000040021A400000000000000000000000000000000000000000000000025108E11000000007000000000000000FF010000
A: consistent_dma_mask_bits=64
A: d3cold_allowed=1
A: dbc=disabled
A: device=0x9d2f
A: dma_mask_bits=64
L: driver=../../../bus/pci/drivers/xhci_hcd
A: driver_override=(null)
A: enable=1
A: irq=127
A: local_cpulist=0-7
A: local_cpus=ff
A: modalias=pci:v00008086d00009D2Fsv00001025sd0000118Ebc0Csc03i30
A: msi_bus=1
A: msi_irqs/127=msi
A: numa_node=-1
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 9 10 2112 10\nxHCI ring segments 32 36 4096 36\nbuffer-2048 1 2 2048 1\nbuffer-512 0 0 512 0\nbuffer-128 0 0 128 0\nbuffer-32 0 0 32 0
A: power/async=enabled
A: power/control=on
A: power/runtime_active_kids=1
A: power/runtime_active_time=5524703
A: power/runtime_enabled=forbidden
A: power/runtime_status=active
A: power/runtime_suspended_time=3373
A: power/runtime_usage=1
A: power/wakeup=enabled
A: power/wakeup_abort_count=0
A: power/wakeup_active=0
A: power/wakeup_active_count=0
A: power/wakeup_count=0
A: power/wakeup_expire_count=0
A: power/wakeup_last_time_ms=0
A: power/wakeup_max_time_ms=0
A: power/wakeup_total_time_ms=0
A: resource=0x00000000a4210000 0x00000000a421ffff 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
A: revision=0x21
A: subsystem_device=0x118e
A: subsystem_vendor=0x1025
A: vendor=0x8086

BIN
tests/elanmoc/custom.pcapng Normal file

Binary file not shown.

83
tests/elanmoc/custom.py Executable file
View File

@@ -0,0 +1,83 @@
#!/usr/bin/python3
import gi
gi.require_version('FPrint', '2.0')
from gi.repository import FPrint, GLib
ctx = GLib.main_context_default()
c = FPrint.Context()
c.enumerate()
devices = c.get_devices()
d = devices[0]
del devices
assert d.get_driver() == "elanmoc"
assert not d.has_feature(FPrint.DeviceFeature.CAPTURE)
assert d.has_feature(FPrint.DeviceFeature.IDENTIFY)
assert d.has_feature(FPrint.DeviceFeature.VERIFY)
assert not d.has_feature(FPrint.DeviceFeature.DUPLICATES_CHECK)
assert d.has_feature(FPrint.DeviceFeature.STORAGE)
assert d.has_feature(FPrint.DeviceFeature.STORAGE_LIST)
assert d.has_feature(FPrint.DeviceFeature.STORAGE_DELETE)
assert not d.has_feature(FPrint.DeviceFeature.STORAGE_CLEAR)
d.open_sync()
template = FPrint.Print.new(d)
def enroll_progress(*args):
#assert d.get_finger_status() == FPrint.FingerStatusFlags.NEEDED
print("finger status: ", d.get_finger_status())
print('enroll progress: ' + str(args))
def identify_done(dev, res):
global identified
identified = True
identify_match, identify_print = dev.identify_finish(res)
print('indentification_done: ', identify_match, identify_print)
assert identify_match.equal(identify_print)
# List, enroll, list, verify, identify, delete
print("enrolling")
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
p = d.enroll_sync(template, None, enroll_progress, None)
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
print("enroll done")
print("listing")
stored = d.list_prints_sync()
print("listing done")
assert len(stored) == 1
assert stored[0].equal(p)
print("verifying")
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
verify_res, verify_print = d.verify_sync(p)
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
print("verify done")
del p
assert verify_res == True
identified = False
deserialized_prints = []
for p in stored:
deserialized_prints.append(FPrint.Print.deserialize(p.serialize()))
assert deserialized_prints[-1].equal(p)
del stored
print('async identifying')
d.identify(deserialized_prints, callback=identify_done)
del deserialized_prints
while not identified:
ctx.iteration(True)
print("deleting")
d.delete_print_sync(p)
print("delete done")
d.close_sync()
del d
del c

223
tests/elanmoc/device Normal file
View File

@@ -0,0 +1,223 @@
P: /devices/pci0000:00/0000:00:14.0/usb1/1-3
N: bus/usb/001/017=1201000200000040F3047E0C06030102000109025300010100A0320904000008FF0000000921100100012215000705810240000107050102400001070582024000010705020240000107058302400001070503024000010705840240000107050402400001
E: DEVNAME=/dev/bus/usb/001/017
E: DEVTYPE=usb_device
E: DRIVER=usb
E: PRODUCT=4f3/c7e/306
E: TYPE=0/0/0
E: BUSNUM=001
E: DEVNUM=017
E: MAJOR=189
E: MINOR=16
E: SUBSYSTEM=usb
E: ID_VENDOR=ELAN
E: ID_VENDOR_ENC=ELAN
E: ID_VENDOR_ID=04f3
E: ID_MODEL=ELAN:ARM-M4
E: ID_MODEL_ENC=ELAN:ARM-M4
E: ID_MODEL_ID=0c7e
E: ID_REVISION=0306
E: ID_SERIAL=ELAN_ELAN:ARM-M4
E: ID_BUS=usb
E: ID_USB_INTERFACES=:ff0000:
E: ID_VENDOR_FROM_DATABASE=Elan Microelectronics Corp.
E: ID_PATH=pci-0000:00:14.0-usb-0:3
E: ID_PATH_TAG=pci-0000_00_14_0-usb-0_3
E: ID_FOR_SEAT=usb-pci-0000_00_14_0-usb-0_3
E: TAGS=:seat:
E: CURRENT_TAGS=:seat:
A: authorized=1\n
A: avoid_reset_quirk=0\n
A: bConfigurationValue=1\n
A: bDeviceClass=00\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=0306\n
A: bmAttributes=a0\n
A: busnum=1\n
A: configuration=
H: descriptors=1201000200000040F3047E0C06030102000109025300010100A0320904000008FF0000000921100100012215000705810240000107050102400001070582024000010705020240000107058302400001070503024000010705840240000107050402400001
A: dev=189:16\n
A: devnum=17\n
A: devpath=3\n
L: driver=../../../../../bus/usb/drivers/usb
L: firmware_node=../../../../LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:1c/device:1d/device:20
A: idProduct=0c7e\n
A: idVendor=04f3\n
A: ltm_capable=no\n
A: manufacturer=ELAN\n
A: maxchild=0\n
L: port=../1-0:1.0/usb1-port3
A: power/active_duration=2748\n
A: power/autosuspend=2\n
A: power/autosuspend_delay_ms=2000\n
A: power/connected_duration=18266\n
A: power/control=auto\n
A: power/level=auto\n
A: power/persist=1\n
A: power/runtime_active_time=2603\n
A: power/runtime_status=active\n
A: power/runtime_suspended_time=15422\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=ELAN:ARM-M4\n
A: quirks=0x0\n
A: removable=removable\n
A: rx_lanes=1\n
A: speed=12\n
A: tx_lanes=1\n
A: urbnum=12\n
A: version= 2.00\n
P: /devices/pci0000:00/0000:00:14.0/usb1
N: bus/usb/001/001=12010002090001406B1D020012050302010109021900010100E0000904000001090000000705810304000C
E: DEVNAME=/dev/bus/usb/001/001
E: DEVTYPE=usb_device
E: DRIVER=usb
E: PRODUCT=1d6b/2/512
E: TYPE=9/0/1
E: BUSNUM=001
E: DEVNUM=001
E: MAJOR=189
E: MINOR=0
E: SUBSYSTEM=usb
E: ID_VENDOR=Linux_5.12.12-300.fc34.x86_64_xhci-hcd
E: ID_VENDOR_ENC=Linux\x205.12.12-300.fc34.x86_64\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=0512
E: ID_SERIAL=Linux_5.12.12-300.fc34.x86_64_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=0512\n
A: bmAttributes=e0\n
A: busnum=1\n
A: configuration=
H: descriptors=12010002090001406B1D020012050302010109021900010100E0000904000001090000000705810304000C
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:1c/device:1d
A: idProduct=0002\n
A: idVendor=1d6b\n
A: interface_authorized_default=1\n
A: ltm_capable=no\n
A: manufacturer=Linux 5.12.12-300.fc34.x86_64 xhci-hcd\n
A: maxchild=12\n
A: power/active_duration=187216979\n
A: power/autosuspend=0\n
A: power/autosuspend_delay_ms=0\n
A: power/connected_duration=187239996\n
A: power/control=auto\n
A: power/level=auto\n
A: power/runtime_active_time=187220224\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=3372\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:9DED
E: PCI_SUBSYS_ID=17AA:2292
E: PCI_SLOT_NAME=0000:00:14.0
E: MODALIAS=pci:v00008086d00009DEDsv000017AAsd00002292bc0Csc03i30
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_AUTOSUSPEND=1
E: ID_MODEL_FROM_DATABASE=Cannon Point-LP USB 3.1 xHCI Controller
A: ari_enabled=0\n
A: broken_parity_status=0\n
A: class=0x0c0330\n
H: config=8680ED9D060490021130030C00008000040022EA000000000000000000000000000000000000000000000000AA179222000000007000000000000000FF010000
A: consistent_dma_mask_bits=64\n
A: d3cold_allowed=1\n
A: dbc=disabled\n
A: device=0x9ded\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:1c
A: irq=128\n
A: local_cpulist=0-7\n
A: local_cpus=ff\n
A: modalias=pci:v00008086d00009DEDsv000017AAsd00002292bc0Csc03i30\n
A: msi_bus=1\n
A: msi_irqs/128=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 11 12 2112 12\nxHCI ring segments 58 62 4096 62\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/control=on\n
A: power/runtime_active_time=187221117\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=0x00000000ea220000 0x00000000ea22ffff 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=0x11\n
A: subsystem_device=0x2292\n
A: subsystem_vendor=0x17aa\n
A: vendor=0x8086\n

30889
tests/elanspi/capture.ioctl Normal file

File diff suppressed because it is too large Load Diff

BIN
tests/elanspi/capture.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 94 KiB

136
tests/elanspi/device-hidraw Normal file
View File

@@ -0,0 +1,136 @@
P: /devices/pci0000:00/0000:00:15.1/i2c_designware.1/i2c-1/i2c-ELAN1300:00/0018:04F3:3057.0001/hidraw/hidraw0
N: hidraw0
E: DEVNAME=/dev/hidraw0
E: MAJOR=241
E: MINOR=0
E: SUBSYSTEM=hidraw
A: dev=241:0\n
L: device=../../../0018:04F3:3057.0001
A: power/async=disabled\n
A: power/control=auto\n
A: power/runtime_active_kids=0\n
A: power/runtime_active_time=0\n
A: power/runtime_enabled=disabled\n
A: power/runtime_status=unsupported\n
A: power/runtime_suspended_time=0\n
A: power/runtime_usage=0\n
P: /devices/pci0000:00/0000:00:15.1/i2c_designware.1/i2c-1/i2c-ELAN1300:00/0018:04F3:3057.0001
E: DRIVER=hid-multitouch
E: HID_ID=0018:000004F3:00003057
E: HID_NAME=ELAN1300:00 04F3:3057
E: HID_PHYS=i2c-ELAN1300:00
E: HID_UNIQ=
E: MODALIAS=hid:b0018g0004v000004F3p00003057
E: SUBSYSTEM=hid
A: country=00\n
L: driver=../../../../../../../bus/hid/drivers/hid-multitouch
A: modalias=hid:b0018g0004v000004F3p00003057\n
A: power/async=enabled\n
A: power/control=auto\n
A: power/runtime_active_kids=0\n
A: power/runtime_active_time=0\n
A: power/runtime_enabled=disabled\n
A: power/runtime_status=unsupported\n
A: power/runtime_suspended_time=0\n
A: power/runtime_usage=0\n
A: quirks=334864\n
H: report_descriptor=05010902A10185010901A100050919012902150025017501950281029506810305010930093109381581257F750895038106050C0A380295018106750895038103C0C0050D0905A10185040922A102150025010947094295027501810275019502810395017504250F095181020501150026880C7510550E6513093035004691019501810246140126A20826A20809318102050D150025649503C0550C66011047FFFF000027FFFF000075109501095681020954257F9501750881020509090125017501950181029507810309C5750895048103050D85020955095975049502250FB102850709607501950115002501B102950FB1030600FF0600FF850609C5150026FF007508960001B102850D09C4150026FF0075089504B102850C09C696E0027508B102850B09C795427508B102C0050D090EA10185030922A10009521500250A75089502B102C00922A1008505095709581500750195022503B102950EB103C0C00600FF0901A101850E09C5150026FF0026FF0075089504B102C0
P: /devices/pci0000:00/0000:00:15.1/i2c_designware.1/i2c-1/i2c-ELAN1300:00
E: DRIVER=i2c_hid
E: MODALIAS=acpi:ELAN1300:PNP0C50:
E: SUBSYSTEM=i2c
E: ID_VENDOR_FROM_DATABASE=ELAD srl
L: driver=../../../../../../bus/i2c/drivers/i2c_hid
L: firmware_node=../../../../../LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:72/ELAN1300:00
A: modalias=acpi:ELAN1300:PNP0C50:\n
A: name=ELAN1300:00\n
A: power/async=enabled\n
A: power/control=auto\n
A: power/runtime_active_kids=0\n
A: power/runtime_active_time=0\n
A: power/runtime_enabled=disabled\n
A: power/runtime_status=unsupported\n
A: power/runtime_suspended_time=0\n
A: power/runtime_usage=0\n
P: /devices/pci0000:00/0000:00:15.1/i2c_designware.1/i2c-1
E: SUBSYSTEM=i2c
L: device=../../i2c_designware.1
L: firmware_node=../../../../LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:72
A: name=Synopsys DesignWare I2C adapter\n
A: power/async=disabled\n
A: power/runtime_active_kids=0\n
A: power/runtime_enabled=enabled\n
A: power/runtime_status=suspended\n
A: power/runtime_usage=0\n
L: software_node=../../../../../kernel/software_nodes/node1
P: /devices/pci0000:00/0000:00:15.1/i2c_designware.1
E: DEVTYPE=mfd_device
E: DRIVER=i2c_designware
E: MODALIAS=platform:i2c_designware
E: SUBSYSTEM=platform
E: ID_PATH=pci-0000:00:15.1-platform-i2c_designware.1
E: ID_PATH_TAG=pci-0000_00_15_1-platform-i2c_designware_1
L: driver=../../../../bus/platform/drivers/i2c_designware
A: driver_override=(null)\n
L: firmware_node=../../../LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:72
A: modalias=platform:i2c_designware\n
A: power/async=disabled\n
A: power/autosuspend_delay_ms=1000\n
A: power/control=auto\n
A: power/runtime_active_kids=0\n
A: power/runtime_active_time=1507234\n
A: power/runtime_enabled=enabled\n
A: power/runtime_status=active\n
A: power/runtime_suspended_time=12722220\n
A: power/runtime_usage=0\n
L: software_node=../../../../kernel/software_nodes/node1
P: /devices/pci0000:00/0000:00:15.1
E: DRIVER=intel-lpss
E: PCI_CLASS=118000
E: PCI_ID=8086:9D61
E: PCI_SUBSYS_ID=1043:1D30
E: PCI_SLOT_NAME=0000:00:15.1
E: MODALIAS=pci:v00008086d00009D61sv00001043sd00001D30bc11sc80i00
E: SUBSYSTEM=pci
E: ID_PCI_CLASS_FROM_DATABASE=Signal processing controller
E: ID_PCI_SUBCLASS_FROM_DATABASE=Signal processing controller
E: ID_VENDOR_FROM_DATABASE=Intel Corporation
E: ID_MODEL_FROM_DATABASE=Sunrise Point-LP Serial IO I2C Controller
A: ari_enabled=0\n
A: broken_parity_status=0\n
A: class=0x118000\n
H: config=8680619D060010002100801110008000048013EF0000000000000000000000000000000000000000000000004310301D000000008000000000000000FF020000
A: consistent_dma_mask_bits=64\n
A: d3cold_allowed=1\n
A: device=0x9d61\n
A: dma_mask_bits=32\n
L: driver=../../../bus/pci/drivers/intel-lpss
A: driver_override=(null)\n
A: enable=1\n
L: firmware_node=../../LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:72
A: irq=17\n
A: local_cpulist=0-7\n
A: local_cpus=ff\n
A: modalias=pci:v00008086d00009D61sv00001043sd00001D30bc11sc80i00\n
A: msi_bus=1\n
A: numa_node=-1\n
A: power/async=enabled\n
A: power/control=on\n
A: power/pm_qos_latency_tolerance_us=auto\n
A: power/runtime_active_kids=1\n
A: power/runtime_active_time=9614317\n
A: power/runtime_enabled=forbidden\n
A: power/runtime_status=active\n
A: power/runtime_suspended_time=4616038\n
A: power/runtime_usage=1\n
A: resource=0x00000000ef138000 0x00000000ef138fff 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=0x21\n
A: subsystem_device=0x1d30\n
A: subsystem_vendor=0x1043\n
A: vendor=0x8086\n

170
tests/elanspi/device-spi Normal file
View File

@@ -0,0 +1,170 @@
P: /devices/pci0000:00/0000:00:1e.2/pxa2xx-spi.3/spi_master/spi0/spi-ELAN7001:00/spidev/spidev0.0
N: spidev0.0
E: DEVNAME=/dev/spidev0.0
E: MAJOR=153
E: MINOR=0
E: SUBSYSTEM=spidev
A: dev=153:0\n
L: device=../../../spi-ELAN7001:00
A: power/async=disabled\n
A: power/control=auto\n
A: power/runtime_active_kids=0\n
A: power/runtime_active_time=0\n
A: power/runtime_enabled=disabled\n
A: power/runtime_status=unsupported\n
A: power/runtime_suspended_time=0\n
A: power/runtime_usage=0\n
P: /devices/pci0000:00/0000:00:1e.2/pxa2xx-spi.3/spi_master/spi0/spi-ELAN7001:00
E: DRIVER=spidev
E: MODALIAS=acpi:ELAN7001:
E: SUBSYSTEM=spi
E: ID_VENDOR_FROM_DATABASE=ELAD srl
L: driver=../../../../../../../bus/spi/drivers/spidev
A: driver_override=spidev\n
L: firmware_node=../../../../../../LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:73/ELAN7001:00
A: modalias=acpi:ELAN7001:\n
A: power/async=disabled\n
A: power/control=auto\n
A: power/runtime_active_kids=0\n
A: power/runtime_active_time=0\n
A: power/runtime_enabled=disabled\n
A: power/runtime_status=unsupported\n
A: power/runtime_suspended_time=0\n
A: power/runtime_usage=0\n
A: statistics/bytes=23208391
A: statistics/bytes_rx=22185696
A: statistics/bytes_tx=1191980
A: statistics/errors=0
A: statistics/messages=519673
A: statistics/spi_async=0
A: statistics/spi_sync=519673
A: statistics/spi_sync_immediate=519673
A: statistics/timedout=0
A: statistics/transfer_bytes_histo_0-1=398920
A: statistics/transfer_bytes_histo_1024-2047=0
A: statistics/transfer_bytes_histo_128-255=113366
A: statistics/transfer_bytes_histo_16-31=0
A: statistics/transfer_bytes_histo_16384-32767=0
A: statistics/transfer_bytes_histo_2-3=517580
A: statistics/transfer_bytes_histo_2048-4095=0
A: statistics/transfer_bytes_histo_256-511=0
A: statistics/transfer_bytes_histo_32-63=0
A: statistics/transfer_bytes_histo_32768-65535=0
A: statistics/transfer_bytes_histo_4-7=0
A: statistics/transfer_bytes_histo_4096-8191=0
A: statistics/transfer_bytes_histo_512-1023=0
A: statistics/transfer_bytes_histo_64-127=0
A: statistics/transfer_bytes_histo_65536+=0
A: statistics/transfer_bytes_histo_8-15=0
A: statistics/transfer_bytes_histo_8192-16383=0
A: statistics/transfers=1029866
A: statistics/transfers_split_maxsize=0
P: /devices/pci0000:00/0000:00:1e.2/pxa2xx-spi.3/spi_master/spi0
E: SUBSYSTEM=spi_master
L: device=../../../pxa2xx-spi.3
A: power/async=disabled\n
A: power/control=auto\n
A: power/runtime_active_kids=0\n
A: power/runtime_active_time=0\n
A: power/runtime_enabled=disabled\n
A: power/runtime_status=unsupported\n
A: power/runtime_suspended_time=0\n
A: power/runtime_usage=0\n
A: statistics/bytes=23208391
A: statistics/bytes_rx=22185696
A: statistics/bytes_tx=1191980
A: statistics/errors=0
A: statistics/messages=519673
A: statistics/spi_async=0
A: statistics/spi_sync=519673
A: statistics/spi_sync_immediate=519673
A: statistics/timedout=0
A: statistics/transfer_bytes_histo_0-1=398920
A: statistics/transfer_bytes_histo_1024-2047=0
A: statistics/transfer_bytes_histo_128-255=113366
A: statistics/transfer_bytes_histo_16-31=0
A: statistics/transfer_bytes_histo_16384-32767=0
A: statistics/transfer_bytes_histo_2-3=517580
A: statistics/transfer_bytes_histo_2048-4095=0
A: statistics/transfer_bytes_histo_256-511=0
A: statistics/transfer_bytes_histo_32-63=0
A: statistics/transfer_bytes_histo_32768-65535=0
A: statistics/transfer_bytes_histo_4-7=0
A: statistics/transfer_bytes_histo_4096-8191=0
A: statistics/transfer_bytes_histo_512-1023=0
A: statistics/transfer_bytes_histo_64-127=0
A: statistics/transfer_bytes_histo_65536+=0
A: statistics/transfer_bytes_histo_8-15=0
A: statistics/transfer_bytes_histo_8192-16383=0
A: statistics/transfers=1029866
A: statistics/transfers_split_maxsize=0
P: /devices/pci0000:00/0000:00:1e.2/pxa2xx-spi.3
E: DEVTYPE=mfd_device
E: DRIVER=pxa2xx-spi
E: MODALIAS=platform:pxa2xx-spi
E: SUBSYSTEM=platform
E: ID_PATH=pci-0000:00:1e.2-platform-pxa2xx-spi.3
E: ID_PATH_TAG=pci-0000_00_1e_2-platform-pxa2xx-spi_3
L: driver=../../../../bus/platform/drivers/pxa2xx-spi
A: driver_override=(null)\n
L: firmware_node=../../../LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:73
A: modalias=platform:pxa2xx-spi\n
A: power/async=disabled\n
A: power/autosuspend_delay_ms=50\n
A: power/control=auto\n
A: power/runtime_active_kids=0\n
A: power/runtime_active_time=65446\n
A: power/runtime_enabled=enabled\n
A: power/runtime_status=suspended\n
A: power/runtime_suspended_time=14155204\n
A: power/runtime_usage=0\n
P: /devices/pci0000:00/0000:00:1e.2
E: DRIVER=intel-lpss
E: PCI_CLASS=118000
E: PCI_ID=8086:9D29
E: PCI_SUBSYS_ID=1043:1D2D
E: PCI_SLOT_NAME=0000:00:1e.2
E: MODALIAS=pci:v00008086d00009D29sv00001043sd00001D2Dbc11sc80i00
E: SUBSYSTEM=pci
E: ID_PCI_CLASS_FROM_DATABASE=Signal processing controller
E: ID_PCI_SUBCLASS_FROM_DATABASE=Signal processing controller
E: ID_VENDOR_FROM_DATABASE=Intel Corporation
E: ID_MODEL_FROM_DATABASE=Sunrise Point-LP Serial IO SPI Controller
A: ari_enabled=0\n
A: broken_parity_status=0\n
A: class=0x118000\n
H: config=8680299D060010002100801110008000043013EF00000000000000000000000000000000000000000000000043102D1D000000008000000000000000FF030000
A: consistent_dma_mask_bits=64\n
A: d3cold_allowed=1\n
A: device=0x9d29\n
A: dma_mask_bits=32\n
L: driver=../../../bus/pci/drivers/intel-lpss
A: driver_override=(null)\n
A: enable=1\n
L: firmware_node=../../LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:73
A: irq=22\n
A: local_cpulist=0-7\n
A: local_cpus=ff\n
A: modalias=pci:v00008086d00009D29sv00001043sd00001D2Dbc11sc80i00\n
A: msi_bus=1\n
A: numa_node=-1\n
A: pools=poolinfo - 0.1\ndma3chan1 0 102 40 1\ndma3chan0 0 102 40 1\n
A: power/async=enabled\n
A: power/control=on\n
A: power/pm_qos_latency_tolerance_us=auto\n
A: power/runtime_active_kids=0\n
A: power/runtime_active_time=9330720\n
A: power/runtime_enabled=forbidden\n
A: power/runtime_status=active\n
A: power/runtime_suspended_time=4891014\n
A: power/runtime_usage=1\n
A: resource=0x00000000ef133000 0x00000000ef133fff 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=0x21\n
A: subsystem_device=0x1d2d\n
A: subsystem_vendor=0x1043\n
A: vendor=0x8086\n

View File

@@ -14,6 +14,14 @@ d = devices[0]
del devices
assert d.get_driver() == "goodixmoc"
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 not d.has_feature(FPrint.DeviceFeature.STORAGE_CLEAR)
d.open_sync()

View File

@@ -24,13 +24,17 @@ envs.set('NO_AT_BRIDGE', '1')
drivers_tests = [
'aes3500',
'elan',
'elanmoc',
'elanspi',
'synaptics',
'upektc_img',
'vfs0050',
'vfs301',
'vfs5011',
'vfs7552',
'goodixmoc',
'nb1010',
'egis0570',
]
if get_option('introspection')
@@ -82,17 +86,22 @@ if get_option('introspection')
endforeach
foreach driver_test: drivers_tests
if driver_test.contains('-')
driver_name = driver_test.split('-')[0]
else
driver_name = driver_test
endif
driver_envs = envs
driver_envs.set('FP_DRIVERS_WHITELIST', driver_test)
driver_envs.set('FP_DRIVERS_WHITELIST', driver_name)
if (driver_test in supported_drivers and
if (driver_name in supported_drivers and
gusb_dep.version().version_compare('>= 0.3.0'))
test(driver_test,
find_program('umockdev-test.py'),
args: join_paths(meson.current_source_dir(), driver_test),
env: driver_envs,
suite: ['drivers'],
timeout: 10,
timeout: 15,
depends: libfprint_typelib,
)
else
@@ -177,9 +186,8 @@ foreach test_name: unit_tests
link_with: test_utils,
)
test(test_name,
find_program('test-runner.sh'),
test_exe,
suite: ['unit-tests'],
args: [test_exe],
env: envs,
)
endforeach
@@ -193,11 +201,17 @@ test('udev-hwdb',
gdb = find_program('gdb', required: false)
if gdb.found()
libfprint_wrapper = [
gdb.path(),
'-batch',
'-ex', 'run',
'--args',
]
add_test_setup('gdb',
timeout_multiplier: 1000,
exe_wrapper: libfprint_wrapper,
env: [
'LIBFPRINT_TEST_WRAPPER=@0@ --args'.format(
gdb.path())
'LIBFPRINT_TEST_WRAPPER=' + ' '.join(libfprint_wrapper),
])
endif
@@ -207,13 +221,19 @@ if valgrind.found()
glib_suppressions = glib_share + '/valgrind/glib.supp'
python_suppressions = '@0@/@1@'.format(meson.source_root(),
files('valgrind-python.supp')[0])
libfprint_wrapper = [
valgrind.path(),
'--tool=memcheck',
'--leak-check=full',
'--suppressions=' + glib_suppressions,
'--suppressions=' + python_suppressions,
]
add_test_setup('valgrind',
timeout_multiplier: 10,
exe_wrapper: libfprint_wrapper,
env: [
'G_SLICE=always-malloc',
'UNDER_VALGRIND=1',
('LIBFPRINT_TEST_WRAPPER=@0@ --tool=memcheck --leak-check=full ' +
'--suppressions=@1@ --suppressions=@2@').format(
valgrind.path(), glib_suppressions, python_suppressions)
'LIBFPRINT_TEST_WRAPPER=' + ' '.join(libfprint_wrapper),
])
endif

View File

@@ -1,129 +0,0 @@
@DEV /dev/bus/usb/001/070
USBDEVFS_GET_CAPABILITIES 0 7D000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 01
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 40 38 0 00009C37FE5C669C2D000A01014101C10000D11BB7134A090FA1000000000100000000000003
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 5 5 0 A7FE011100
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE01130100
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 37 37 0 A7FE02512000014650312D30303030303030302D302D30303030303030302D6E6F626F6479
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE025400
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE026000
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 05000000000100
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910100
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 05000000000000
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE0255010C
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000000
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE026000
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 05000000000100
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910100
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 05000000000000
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE02550119
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000000
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE026000
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000000
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE02550125
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 05000000000000
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910100
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000000
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE026000
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000000
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE02550125
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 05000000000000
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910100
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000000
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE026000
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000000
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE02550132
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 05000000000000
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910100
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000000
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE026000
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000000
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE0255013E
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 05000000000000
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910100
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000000
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE026000
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000000
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE0255013E
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 05000000000000
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910100
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000000
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE026000
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000000
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE0255014B
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 05000000000000
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910100
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000000
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE026000
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 05000000000100
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910100
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 05000000000000
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE02550157
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000000
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE026000
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 05000000000100
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910100
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 05000000000100
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE02550164
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 05000000000100
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 37 0 0000FE02591F014650312D30303030303030302D302D30303030303030302D6E6F626F6479
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE046000
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 05000000000100
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910100
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 05000000000100
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 39 0 0000FE0468214F2B014650312D30303030303030302D302D30303030303030302D6E6F626F6479
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 5 5 0 A7FE037100
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 41 0 0000FE03752301012007014650312D30303030303030302D302D30303030303030302D6E6F626F6479
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 5 5 0 A7FE037200
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE037600
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 35 35 0 A7FE04651E4650312D30303030303030302D302D30303030303030302D6E6F626F6479
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE046600
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 36 36 0 A7FE05811F014650312D30303030303030302D302D30303030303030302D6E6F626F6479
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 37 0 0000FE05831F014650312D30303030303030302D302D30303030303030302D6E6F626F6479

View File

@@ -1,188 +0,0 @@
@DEV /dev/bus/usb/001/070
USBDEVFS_GET_CAPABILITIES 0 7D000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 01
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 40 38 0 00009C37FE5C669C2D000A01014101C10000D11BB7134A090FA1000000000100000000000003
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 5 5 0 A7FE011100
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE01130100
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 5 5 0 A7FE021100
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE02130100
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 37 37 0 A7FE03512000014650312D30303030303030302D302D30303030303030302D6E6F626F6479
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE035400
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE036000
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 05000000000100
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910100
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 05000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE0355010C
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE036000
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 05000000000100
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910100
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 05000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE03550119
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE036000
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE03550125
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 05000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910100
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE036000
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE03550125
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 05000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910100
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE036000
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE03550132
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 05000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910100
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE036000
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE0355013E
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 05000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910100
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE036000
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE0355013E
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 05000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910100
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE036000
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE0355014B
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 05000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910100
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE036000
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 05000000000100
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910100
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 05000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE03550157
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE036000
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 05000000000100
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910100
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 05000000000100
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE03550164
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 05000000000100
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 37 0 0000FE03591F014650312D30303030303030302D302D30303030303030302D6E6F626F6479
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 5 5 0 A7FE047100
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 41 0 0000FE04752301012007014650312D30303030303030302D302D30303030303030302D6E6F626F6479
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 5 5 0 A7FE047200
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE047600
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 35 35 0 A7FE05651E4650312D30303030303030302D302D30303030303030302D6E6F626F6479
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE056600
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000000
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE056000
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 05000000000100
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910100
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 05000000000100
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 39 0 0000FE0568214F2B014650312D30303030303030302D302D30303030303030302D6E6F626F6479
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 36 36 0 A7FE06811F014650312D30303030303030302D302D30303030303030302D6E6F626F6479
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 37 0 0000FE06831F014650312D30303030303030302D302D30303030303030302D6E6F626F6479
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 5 5 0 A7FE07A100
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE07A200

Binary file not shown.

View File

@@ -14,9 +14,18 @@ d = devices[0]
del devices
assert d.get_driver() == "synaptics"
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_DELETE)
assert d.has_feature(FPrint.DeviceFeature.STORAGE_CLEAR)
d.open_sync()
d.clear_storage_sync()
template = FPrint.Print.new(d)
def enroll_progress(*args):
@@ -30,11 +39,6 @@ p = d.enroll_sync(template, None, enroll_progress, None)
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
print("enroll done")
print("listing")
stored = d.list_prints_sync()
print("listing done")
assert len(stored) == 1
assert stored[0].equal(p)
print("verifying")
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
verify_res, verify_print = d.verify_sync(p)

View File

@@ -1,14 +1,14 @@
P: /devices/pci0000:00/0000:00:14.0/usb1/1-1
N: bus/usb/001/070=12010002FF10FF08CB06BD0000000000010109022700010100A0320904000003FF000000070501024000000705810240000007058303080004
E: DEVNAME=/dev/bus/usb/001/070
P: /devices/pci0000:00/0000:00:14.0/usb1/1-9
N: bus/usb/001/005
E: DEVNAME=/dev/bus/usb/001/005
E: DEVTYPE=usb_device
E: DRIVER=usb
E: PRODUCT=6cb/bd/0
E: TYPE=255/16/255
E: BUSNUM=001
E: DEVNUM=070
E: DEVNUM=005
E: MAJOR=189
E: MINOR=69
E: MINOR=4
E: SUBSYSTEM=usb
E: ID_VENDOR=06cb
E: ID_VENDOR_ENC=06cb
@@ -17,59 +17,207 @@ E: ID_MODEL=00bd
E: ID_MODEL_ENC=00bd
E: ID_MODEL_ID=00bd
E: ID_REVISION=0000
E: ID_SERIAL=06cb_00bd_317bb11d90a4
E: ID_SERIAL_SHORT=317bb11d90a4
E: ID_SERIAL=06cb_00bd_c087f7d72126
E: ID_SERIAL_SHORT=c087f7d72126
E: ID_BUS=usb
E: ID_USB_INTERFACES=:ff0000:
E: ID_VENDOR_FROM_DATABASE=Synaptics, Inc.
A: authorized=1
A: avoid_reset_quirk=0
A: bConfigurationValue=1
A: bDeviceClass=ff
A: bDeviceProtocol=ff
A: bDeviceSubClass=10
A: bMaxPacketSize0=8
A: bMaxPower=100mA
A: bNumConfigurations=1
A: bNumInterfaces= 1
A: bcdDevice=0000
A: bmAttributes=a0
E: ID_AUTOSUSPEND=1
E: ID_MODEL_FROM_DATABASE=Prometheus MIS Touch Fingerprint Reader
E: ID_PATH=pci-0000:00:14.0-usb-0:9
E: ID_PATH_TAG=pci-0000_00_14_0-usb-0_9
E: LIBFPRINT_DRIVER=Synaptics Sensors
A: authorized=1\n
A: avoid_reset_quirk=0\n
A: bConfigurationValue=1\n
A: bDeviceClass=ff\n
A: bDeviceProtocol=ff\n
A: bDeviceSubClass=10\n
A: bMaxPacketSize0=8\n
A: bMaxPower=100mA\n
A: bNumConfigurations=1\n
A: bNumInterfaces= 1\n
A: bcdDevice=0000\n
A: bmAttributes=a0\n
A: busnum=1\n
A: configuration=
H: descriptors=12010002FF10FF08CB06BD0000000000010109022700010100A0320904000003FF000000070501024000000705810240000007058303080004
A: dev=189:69
A: devnum=70\n
A: devpath=1
A: dev=189:4\n
A: devnum=5\n
A: devpath=9\n
L: driver=../../../../../bus/usb/drivers/usb
A: idProduct=00bd
A: idVendor=06cb
A: ltm_capable=no
A: maxchild=0
L: port=../1-0:1.0/usb1-port1
A: power/active_duration=33942
A: power/autosuspend=2
A: power/autosuspend_delay_ms=2000
A: power/connected_duration=33942
A: power/control=on
A: power/level=on
A: power/persist=1
A: power/runtime_active_time=33702
A: power/runtime_status=active
A: power/runtime_suspended_time=0
A: power/wakeup=disabled
A: power/wakeup_abort_count=
A: power/wakeup_active=
A: power/wakeup_active_count=
A: power/wakeup_count=
A: power/wakeup_expire_count=
A: power/wakeup_last_time_ms=
A: power/wakeup_max_time_ms=
A: power/wakeup_total_time_ms=
A: quirks=0x0
A: removable=removable
A: rx_lanes=1
A: serial=317bb11d90a4
A: speed=12
A: tx_lanes=1
A: urbnum=12
A: version= 2.00
L: firmware_node=../../../../LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:1c/device:1d/device:28
A: idProduct=00bd\n
A: idVendor=06cb\n
A: ltm_capable=no\n
A: maxchild=0\n
L: port=../1-0:1.0/usb1-port9
A: power/active_duration=82065\n
A: power/autosuspend=2\n
A: power/autosuspend_delay_ms=2000\n
A: power/connected_duration=4271349\n
A: power/control=auto\n
A: power/level=auto\n
A: power/persist=1\n
A: power/runtime_active_time=82975\n
A: power/runtime_status=suspended\n
A: power/runtime_suspended_time=4186597\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: quirks=0x0\n
A: removable=fixed\n
A: rx_lanes=1\n
A: serial=c087f7d72126\n
A: speed=12\n
A: tx_lanes=1\n
A: urbnum=618\n
A: version= 2.00\n
P: /devices/pci0000:00/0000:00:14.0/usb1
N: bus/usb/001/001=12010002090001406B1D020012050302010109021900010100E0000904000001090000000705810304000C
E: DEVNAME=/dev/bus/usb/001/001
E: DEVTYPE=usb_device
E: DRIVER=usb
E: PRODUCT=1d6b/2/512
E: TYPE=9/0/1
E: BUSNUM=001
E: DEVNUM=001
E: MAJOR=189
E: MINOR=0
E: SUBSYSTEM=usb
E: ID_VENDOR=Linux_5.12.9-300.fc34.x86_64_xhci-hcd
E: ID_VENDOR_ENC=Linux\x205.12.9-300.fc34.x86_64\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=0512
E: ID_SERIAL=Linux_5.12.9-300.fc34.x86_64_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=0512\n
A: bmAttributes=e0\n
A: busnum=1\n
A: configuration=
H: descriptors=12010002090001406B1D020012050302010109021900010100E0000904000001090000000705810304000C
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:1c/device:1d
A: idProduct=0002\n
A: idVendor=1d6b\n
A: interface_authorized_default=1\n
A: ltm_capable=no\n
A: manufacturer=Linux 5.12.9-300.fc34.x86_64 xhci-hcd\n
A: maxchild=12\n
A: power/active_duration=4270585\n
A: power/autosuspend=0\n
A: power/autosuspend_delay_ms=0\n
A: power/connected_duration=4272308\n
A: power/control=auto\n
A: power/level=auto\n
A: power/runtime_active_time=4270770\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=463\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:9DED
E: PCI_SUBSYS_ID=17AA:2292
E: PCI_SLOT_NAME=0000:00:14.0
E: MODALIAS=pci:v00008086d00009DEDsv000017AAsd00002292bc0Csc03i30
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_AUTOSUSPEND=1
E: ID_MODEL_FROM_DATABASE=Cannon Point-LP USB 3.1 xHCI Controller
A: ari_enabled=0\n
A: broken_parity_status=0\n
A: class=0x0c0330\n
H: config=8680ED9D060490021130030C00008000040022EA000000000000000000000000000000000000000000000000AA179222000000007000000000000000FF010000
A: consistent_dma_mask_bits=64\n
A: d3cold_allowed=1\n
A: dbc=disabled\n
A: device=0x9ded\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:1c
A: irq=128\n
A: local_cpulist=0-7\n
A: local_cpus=ff\n
A: modalias=pci:v00008086d00009DEDsv000017AAsd00002292bc0Csc03i30\n
A: msi_bus=1\n
A: msi_irqs/128=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 9 12 2112 12\nxHCI ring segments 40 50 4096 50\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/control=auto\n
A: power/runtime_active_time=4271635\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=0x00000000ea220000 0x00000000ea22ffff 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=0x11\n
A: subsystem_device=0x2292\n
A: subsystem_vendor=0x17aa\n
A: vendor=0x8086\n

View File

@@ -38,6 +38,8 @@ fpi_device_fake_probe (FpDevice *device)
fake_dev->last_called_function = fpi_device_fake_probe;
g_assert_cmpuint (fpi_device_get_current_action (device), ==, FPI_DEVICE_ACTION_PROBE);
fpi_device_update_features (device, fake_dev->probe_features_update, fake_dev->probe_features_value);
if (fake_dev->return_action_error)
{
fpi_device_action_error (device, fake_dev->ret_error);
@@ -243,6 +245,23 @@ fpi_device_fake_delete (FpDevice *device)
fpi_device_delete_complete (device, fake_dev->ret_error);
}
static void
fpi_device_fake_clear_storage (FpDevice *device)
{
FpiDeviceFake *fake_dev = FPI_DEVICE_FAKE (device);
fake_dev->last_called_function = fpi_device_fake_clear_storage;
g_assert_cmpuint (fpi_device_get_current_action (device), ==, FPI_DEVICE_ACTION_CLEAR_STORAGE);
if (fake_dev->return_action_error)
{
fpi_device_action_error (device, fake_dev->ret_error);
return;
}
fpi_device_clear_storage_complete (device, fake_dev->ret_error);
}
static void
fpi_device_fake_cancel (FpDevice *device)
{
@@ -279,6 +298,7 @@ fpi_device_fake_class_init (FpiDeviceFakeClass *klass)
dev_class->list = fpi_device_fake_list;
dev_class->delete = fpi_device_fake_delete;
dev_class->cancel = fpi_device_fake_cancel;
dev_class->clear_storage = fpi_device_fake_clear_storage;
fpi_device_class_auto_initialize_features (dev_class);
}

View File

@@ -41,4 +41,7 @@ struct _FpiDeviceFake
gpointer action_data;
gpointer user_data;
FpDeviceFeature probe_features_update;
FpDeviceFeature probe_features_value;
};

View File

@@ -202,7 +202,10 @@ test_device_supports_identify (void)
g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_device (FPT_VIRTUAL_DEVICE_IMAGE);
fp_device_open_sync (tctx->device, NULL, NULL);
g_assert_true (fp_device_has_feature (tctx->device, FP_DEVICE_FEATURE_IDENTIFY));
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
g_assert_true (fp_device_supports_identify (tctx->device));
G_GNUC_END_IGNORE_DEPRECATIONS
}
static void
@@ -211,7 +214,10 @@ test_device_supports_capture (void)
g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_device (FPT_VIRTUAL_DEVICE_IMAGE);
fp_device_open_sync (tctx->device, NULL, NULL);
g_assert_true (fp_device_has_feature (tctx->device, FP_DEVICE_FEATURE_CAPTURE));
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
g_assert_true (fp_device_supports_capture (tctx->device));
G_GNUC_END_IGNORE_DEPRECATIONS
}
static void
@@ -220,7 +226,10 @@ test_device_has_storage (void)
g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_device (FPT_VIRTUAL_DEVICE_IMAGE);
fp_device_open_sync (tctx->device, NULL, NULL);
g_assert_false (fp_device_has_feature (tctx->device, FP_DEVICE_FEATURE_STORAGE));
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
g_assert_false (fp_device_has_storage (tctx->device));
G_GNUC_END_IGNORE_DEPRECATIONS
}
int

View File

@@ -62,6 +62,7 @@ test_frame_assembling (void)
int test_height;
guchar *data;
struct fpi_frame_asmbl_ctx ctx = { 0, };
gint xborder = 5;
g_autoptr(FpImage) fp_img = NULL;
GSList *frames = NULL;
@@ -79,7 +80,7 @@ test_frame_assembling (void)
ctx.get_pixel = cairo_get_pixel;
ctx.frame_width = width;
ctx.frame_height = 20;
ctx.image_width = width;
ctx.image_width = width - 2 * xborder;
g_assert (height > ctx.frame_height);
@@ -118,8 +119,8 @@ test_frame_assembling (void)
/* The FpImage and cairo surface need to be identical in the test area */
for (int y = 0; y < test_height; y++)
for (int x = 0; x < width; x++)
g_assert_cmpint (data[x * 4 + y * stride + 1], ==, fp_img->data[x + y * width]);
for (int x = 0; x < ctx.image_width; x++)
g_assert_cmpint (data[(x + xborder) * 4 + y * stride + 1], ==, fp_img->data[x + y * ctx.image_width]);
g_slist_free_full (frames, g_free);
cairo_surface_destroy (img);

View File

@@ -17,6 +17,8 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "fp-device.h"
#include "fp-enums.h"
#include <libfprint/fprint.h>
#define FP_COMPONENT "device"
@@ -506,21 +508,91 @@ test_driver_get_driver_data (void)
g_assert_cmpuint (fpi_device_get_driver_data (device), ==, driver_data);
}
static void
test_driver_features_probe_updates (void)
{
g_autoptr(FpDevice) device = g_object_new (FPI_TYPE_DEVICE_FAKE, NULL);
FpDeviceClass *dev_class = FP_DEVICE_GET_CLASS (device);
FpiDeviceFake *fake_dev;
g_assert_cmpuint (dev_class->features, !=, FP_DEVICE_FEATURE_NONE);
g_assert_true (dev_class->features & FP_DEVICE_FEATURE_CAPTURE);
g_assert_true (dev_class->features & FP_DEVICE_FEATURE_IDENTIFY);
g_assert_true (dev_class->features & FP_DEVICE_FEATURE_VERIFY);
g_assert_false (dev_class->features & FP_DEVICE_FEATURE_DUPLICATES_CHECK);
g_assert_true (dev_class->features & FP_DEVICE_FEATURE_STORAGE);
g_assert_true (dev_class->features & FP_DEVICE_FEATURE_STORAGE_LIST);
g_assert_true (dev_class->features & FP_DEVICE_FEATURE_STORAGE_DELETE);
g_assert_true (dev_class->features & FP_DEVICE_FEATURE_STORAGE_CLEAR);
/* Effectively clears FP_DEVICE_FEATURE_STORAGE_DELETE */
fake_dev = FPI_DEVICE_FAKE (device);
fake_dev->probe_features_update = FP_DEVICE_FEATURE_STORAGE_LIST | FP_DEVICE_FEATURE_STORAGE_DELETE;
fake_dev->probe_features_value = FP_DEVICE_FEATURE_STORAGE_LIST;
g_async_initable_init_async (G_ASYNC_INITABLE (device),
G_PRIORITY_DEFAULT, NULL, NULL, NULL);
while (g_main_context_iteration (NULL, FALSE))
continue;
g_assert_true (fp_device_has_feature (device, FP_DEVICE_FEATURE_CAPTURE));
g_assert_true (fp_device_has_feature (device, FP_DEVICE_FEATURE_IDENTIFY));
g_assert_true (fp_device_has_feature (device, FP_DEVICE_FEATURE_VERIFY));
g_assert_false (fp_device_has_feature (device, FP_DEVICE_FEATURE_DUPLICATES_CHECK));
g_assert_true (fp_device_has_feature (device, FP_DEVICE_FEATURE_STORAGE));
g_assert_true (fp_device_has_feature (device, FP_DEVICE_FEATURE_STORAGE_LIST));
g_assert_false (fp_device_has_feature (device, FP_DEVICE_FEATURE_STORAGE_DELETE));
g_assert_true (fp_device_has_feature (device, FP_DEVICE_FEATURE_STORAGE_CLEAR));
g_assert_cmpuint (fp_device_get_features (device),
==,
FP_DEVICE_FEATURE_CAPTURE |
FP_DEVICE_FEATURE_IDENTIFY |
FP_DEVICE_FEATURE_VERIFY |
FP_DEVICE_FEATURE_STORAGE |
FP_DEVICE_FEATURE_STORAGE_LIST |
FP_DEVICE_FEATURE_STORAGE_CLEAR);
}
static void
test_driver_initial_features (void)
{
g_autoptr(FpDevice) device = g_object_new (FPI_TYPE_DEVICE_FAKE, NULL);
FpDeviceClass *dev_class = FP_DEVICE_GET_CLASS (device);
g_assert_cmpuint (dev_class->features, !=, FPI_DEVICE_FEATURE_NONE);
g_assert_true (dev_class->features & FPI_DEVICE_FEATURE_CAPTURE);
g_assert_true (dev_class->features & FPI_DEVICE_FEATURE_IDENTIFY);
g_assert_true (dev_class->features & FPI_DEVICE_FEATURE_VERIFY);
g_assert_false (dev_class->features & FPI_DEVICE_FEATURE_DUPLICATES_CHECK);
g_assert_true (dev_class->features & FPI_DEVICE_FEATURE_STORAGE);
g_assert_true (dev_class->features & FPI_DEVICE_FEATURE_STORAGE_LIST);
g_assert_true (dev_class->features & FPI_DEVICE_FEATURE_STORAGE_DELETE);
g_assert_false (dev_class->features & FPI_DEVICE_FEATURE_STORAGE_CLEAR);
g_assert_cmpuint (dev_class->features, !=, FP_DEVICE_FEATURE_NONE);
g_assert_true (dev_class->features & FP_DEVICE_FEATURE_CAPTURE);
g_assert_true (dev_class->features & FP_DEVICE_FEATURE_IDENTIFY);
g_assert_true (dev_class->features & FP_DEVICE_FEATURE_VERIFY);
g_assert_false (dev_class->features & FP_DEVICE_FEATURE_DUPLICATES_CHECK);
g_assert_true (dev_class->features & FP_DEVICE_FEATURE_STORAGE);
g_assert_true (dev_class->features & FP_DEVICE_FEATURE_STORAGE_LIST);
g_assert_true (dev_class->features & FP_DEVICE_FEATURE_STORAGE_DELETE);
g_assert_true (dev_class->features & FP_DEVICE_FEATURE_STORAGE_CLEAR);
g_async_initable_init_async (G_ASYNC_INITABLE (device),
G_PRIORITY_DEFAULT, NULL, NULL, NULL);
while (g_main_context_iteration (NULL, FALSE))
continue;
g_assert_true (fp_device_has_feature (device, FP_DEVICE_FEATURE_CAPTURE));
g_assert_true (fp_device_has_feature (device, FP_DEVICE_FEATURE_IDENTIFY));
g_assert_true (fp_device_has_feature (device, FP_DEVICE_FEATURE_VERIFY));
g_assert_false (fp_device_has_feature (device, FP_DEVICE_FEATURE_DUPLICATES_CHECK));
g_assert_true (fp_device_has_feature (device, FP_DEVICE_FEATURE_STORAGE));
g_assert_true (fp_device_has_feature (device, FP_DEVICE_FEATURE_STORAGE_LIST));
g_assert_true (fp_device_has_feature (device, FP_DEVICE_FEATURE_STORAGE_DELETE));
g_assert_true (fp_device_has_feature (device, FP_DEVICE_FEATURE_STORAGE_CLEAR));
g_assert_cmpuint (fp_device_get_features (device),
==,
FP_DEVICE_FEATURE_CAPTURE |
FP_DEVICE_FEATURE_IDENTIFY |
FP_DEVICE_FEATURE_VERIFY |
FP_DEVICE_FEATURE_STORAGE |
FP_DEVICE_FEATURE_STORAGE_LIST |
FP_DEVICE_FEATURE_STORAGE_DELETE |
FP_DEVICE_FEATURE_STORAGE_CLEAR);
}
static void
@@ -533,19 +605,20 @@ test_driver_initial_features_none (void)
dev_class->verify = NULL;
dev_class->identify = NULL;
dev_class->delete = NULL;
dev_class->features = FPI_DEVICE_FEATURE_NONE;
dev_class->clear_storage = NULL;
dev_class->features = FP_DEVICE_FEATURE_NONE;
fpi_device_class_auto_initialize_features (dev_class);
g_assert_cmpuint (dev_class->features, ==, FPI_DEVICE_FEATURE_NONE);
g_assert_false (dev_class->features & FPI_DEVICE_FEATURE_CAPTURE);
g_assert_false (dev_class->features & FPI_DEVICE_FEATURE_IDENTIFY);
g_assert_false (dev_class->features & FPI_DEVICE_FEATURE_VERIFY);
g_assert_false (dev_class->features & FPI_DEVICE_FEATURE_DUPLICATES_CHECK);
g_assert_false (dev_class->features & FPI_DEVICE_FEATURE_STORAGE);
g_assert_false (dev_class->features & FPI_DEVICE_FEATURE_STORAGE_LIST);
g_assert_false (dev_class->features & FPI_DEVICE_FEATURE_STORAGE_DELETE);
g_assert_false (dev_class->features & FPI_DEVICE_FEATURE_STORAGE_CLEAR);
g_assert_cmpuint (dev_class->features, ==, FP_DEVICE_FEATURE_NONE);
g_assert_false (dev_class->features & FP_DEVICE_FEATURE_CAPTURE);
g_assert_false (dev_class->features & FP_DEVICE_FEATURE_IDENTIFY);
g_assert_false (dev_class->features & FP_DEVICE_FEATURE_VERIFY);
g_assert_false (dev_class->features & FP_DEVICE_FEATURE_DUPLICATES_CHECK);
g_assert_false (dev_class->features & FP_DEVICE_FEATURE_STORAGE);
g_assert_false (dev_class->features & FP_DEVICE_FEATURE_STORAGE_LIST);
g_assert_false (dev_class->features & FP_DEVICE_FEATURE_STORAGE_DELETE);
g_assert_false (dev_class->features & FP_DEVICE_FEATURE_STORAGE_CLEAR);
}
static void
@@ -554,19 +627,19 @@ test_driver_initial_features_no_capture (void)
g_autoptr(FpAutoResetClass) dev_class = auto_reset_device_class ();
dev_class->capture = NULL;
dev_class->features = FPI_DEVICE_FEATURE_NONE;
dev_class->features = FP_DEVICE_FEATURE_NONE;
fpi_device_class_auto_initialize_features (dev_class);
g_assert_cmpuint (dev_class->features, !=, FPI_DEVICE_FEATURE_NONE);
g_assert_false (dev_class->features & FPI_DEVICE_FEATURE_CAPTURE);
g_assert_true (dev_class->features & FPI_DEVICE_FEATURE_IDENTIFY);
g_assert_true (dev_class->features & FPI_DEVICE_FEATURE_VERIFY);
g_assert_false (dev_class->features & FPI_DEVICE_FEATURE_DUPLICATES_CHECK);
g_assert_true (dev_class->features & FPI_DEVICE_FEATURE_STORAGE);
g_assert_true (dev_class->features & FPI_DEVICE_FEATURE_STORAGE_LIST);
g_assert_true (dev_class->features & FPI_DEVICE_FEATURE_STORAGE_DELETE);
g_assert_false (dev_class->features & FPI_DEVICE_FEATURE_STORAGE_CLEAR);
g_assert_cmpuint (dev_class->features, !=, FP_DEVICE_FEATURE_NONE);
g_assert_false (dev_class->features & FP_DEVICE_FEATURE_CAPTURE);
g_assert_true (dev_class->features & FP_DEVICE_FEATURE_IDENTIFY);
g_assert_true (dev_class->features & FP_DEVICE_FEATURE_VERIFY);
g_assert_false (dev_class->features & FP_DEVICE_FEATURE_DUPLICATES_CHECK);
g_assert_true (dev_class->features & FP_DEVICE_FEATURE_STORAGE);
g_assert_true (dev_class->features & FP_DEVICE_FEATURE_STORAGE_LIST);
g_assert_true (dev_class->features & FP_DEVICE_FEATURE_STORAGE_DELETE);
g_assert_true (dev_class->features & FP_DEVICE_FEATURE_STORAGE_CLEAR);
}
static void
@@ -575,19 +648,19 @@ test_driver_initial_features_no_verify (void)
g_autoptr(FpAutoResetClass) dev_class = auto_reset_device_class ();
dev_class->verify = NULL;
dev_class->features = FPI_DEVICE_FEATURE_NONE;
dev_class->features = FP_DEVICE_FEATURE_NONE;
fpi_device_class_auto_initialize_features (dev_class);
g_assert_cmpuint (dev_class->features, !=, FPI_DEVICE_FEATURE_NONE);
g_assert_true (dev_class->features & FPI_DEVICE_FEATURE_CAPTURE);
g_assert_true (dev_class->features & FPI_DEVICE_FEATURE_IDENTIFY);
g_assert_false (dev_class->features & FPI_DEVICE_FEATURE_VERIFY);
g_assert_false (dev_class->features & FPI_DEVICE_FEATURE_DUPLICATES_CHECK);
g_assert_true (dev_class->features & FPI_DEVICE_FEATURE_STORAGE);
g_assert_true (dev_class->features & FPI_DEVICE_FEATURE_STORAGE_LIST);
g_assert_true (dev_class->features & FPI_DEVICE_FEATURE_STORAGE_DELETE);
g_assert_false (dev_class->features & FPI_DEVICE_FEATURE_STORAGE_CLEAR);
g_assert_cmpuint (dev_class->features, !=, FP_DEVICE_FEATURE_NONE);
g_assert_true (dev_class->features & FP_DEVICE_FEATURE_CAPTURE);
g_assert_true (dev_class->features & FP_DEVICE_FEATURE_IDENTIFY);
g_assert_false (dev_class->features & FP_DEVICE_FEATURE_VERIFY);
g_assert_false (dev_class->features & FP_DEVICE_FEATURE_DUPLICATES_CHECK);
g_assert_true (dev_class->features & FP_DEVICE_FEATURE_STORAGE);
g_assert_true (dev_class->features & FP_DEVICE_FEATURE_STORAGE_LIST);
g_assert_true (dev_class->features & FP_DEVICE_FEATURE_STORAGE_DELETE);
g_assert_true (dev_class->features & FP_DEVICE_FEATURE_STORAGE_CLEAR);
}
static void
@@ -596,19 +669,19 @@ test_driver_initial_features_no_identify (void)
g_autoptr(FpAutoResetClass) dev_class = auto_reset_device_class ();
dev_class->identify = NULL;
dev_class->features = FPI_DEVICE_FEATURE_NONE;
dev_class->features = FP_DEVICE_FEATURE_NONE;
fpi_device_class_auto_initialize_features (dev_class);
g_assert_cmpuint (dev_class->features, !=, FPI_DEVICE_FEATURE_NONE);
g_assert_true (dev_class->features & FPI_DEVICE_FEATURE_CAPTURE);
g_assert_false (dev_class->features & FPI_DEVICE_FEATURE_IDENTIFY);
g_assert_true (dev_class->features & FPI_DEVICE_FEATURE_VERIFY);
g_assert_false (dev_class->features & FPI_DEVICE_FEATURE_DUPLICATES_CHECK);
g_assert_true (dev_class->features & FPI_DEVICE_FEATURE_STORAGE);
g_assert_true (dev_class->features & FPI_DEVICE_FEATURE_STORAGE_LIST);
g_assert_true (dev_class->features & FPI_DEVICE_FEATURE_STORAGE_DELETE);
g_assert_false (dev_class->features & FPI_DEVICE_FEATURE_STORAGE_CLEAR);
g_assert_cmpuint (dev_class->features, !=, FP_DEVICE_FEATURE_NONE);
g_assert_true (dev_class->features & FP_DEVICE_FEATURE_CAPTURE);
g_assert_false (dev_class->features & FP_DEVICE_FEATURE_IDENTIFY);
g_assert_true (dev_class->features & FP_DEVICE_FEATURE_VERIFY);
g_assert_false (dev_class->features & FP_DEVICE_FEATURE_DUPLICATES_CHECK);
g_assert_true (dev_class->features & FP_DEVICE_FEATURE_STORAGE);
g_assert_true (dev_class->features & FP_DEVICE_FEATURE_STORAGE_LIST);
g_assert_true (dev_class->features & FP_DEVICE_FEATURE_STORAGE_DELETE);
g_assert_true (dev_class->features & FP_DEVICE_FEATURE_STORAGE_CLEAR);
}
static void
@@ -616,21 +689,20 @@ test_driver_initial_features_no_storage (void)
{
g_autoptr(FpAutoResetClass) dev_class = auto_reset_device_class ();
dev_class->list = NULL;
dev_class->delete = NULL;
dev_class->features = FPI_DEVICE_FEATURE_NONE;
dev_class->features = FP_DEVICE_FEATURE_NONE;
fpi_device_class_auto_initialize_features (dev_class);
g_assert_cmpuint (dev_class->features, !=, FPI_DEVICE_FEATURE_NONE);
g_assert_true (dev_class->features & FPI_DEVICE_FEATURE_CAPTURE);
g_assert_true (dev_class->features & FPI_DEVICE_FEATURE_IDENTIFY);
g_assert_true (dev_class->features & FPI_DEVICE_FEATURE_VERIFY);
g_assert_false (dev_class->features & FPI_DEVICE_FEATURE_DUPLICATES_CHECK);
g_assert_false (dev_class->features & FPI_DEVICE_FEATURE_STORAGE);
g_assert_false (dev_class->features & FPI_DEVICE_FEATURE_STORAGE_LIST);
g_assert_false (dev_class->features & FPI_DEVICE_FEATURE_STORAGE_DELETE);
g_assert_false (dev_class->features & FPI_DEVICE_FEATURE_STORAGE_CLEAR);
g_assert_cmpuint (dev_class->features, !=, FP_DEVICE_FEATURE_NONE);
g_assert_true (dev_class->features & FP_DEVICE_FEATURE_CAPTURE);
g_assert_true (dev_class->features & FP_DEVICE_FEATURE_IDENTIFY);
g_assert_true (dev_class->features & FP_DEVICE_FEATURE_VERIFY);
g_assert_false (dev_class->features & FP_DEVICE_FEATURE_DUPLICATES_CHECK);
g_assert_false (dev_class->features & FP_DEVICE_FEATURE_STORAGE);
g_assert_true (dev_class->features & FP_DEVICE_FEATURE_STORAGE_LIST);
g_assert_false (dev_class->features & FP_DEVICE_FEATURE_STORAGE_DELETE);
g_assert_true (dev_class->features & FP_DEVICE_FEATURE_STORAGE_CLEAR);
}
static void
@@ -639,19 +711,19 @@ test_driver_initial_features_no_list (void)
g_autoptr(FpAutoResetClass) dev_class = auto_reset_device_class ();
dev_class->list = NULL;
dev_class->features = FPI_DEVICE_FEATURE_NONE;
dev_class->features = FP_DEVICE_FEATURE_NONE;
fpi_device_class_auto_initialize_features (dev_class);
g_assert_cmpuint (dev_class->features, !=, FPI_DEVICE_FEATURE_NONE);
g_assert_true (dev_class->features & FPI_DEVICE_FEATURE_CAPTURE);
g_assert_true (dev_class->features & FPI_DEVICE_FEATURE_IDENTIFY);
g_assert_true (dev_class->features & FPI_DEVICE_FEATURE_VERIFY);
g_assert_false (dev_class->features & FPI_DEVICE_FEATURE_DUPLICATES_CHECK);
g_assert_true (dev_class->features & FPI_DEVICE_FEATURE_STORAGE);
g_assert_false (dev_class->features & FPI_DEVICE_FEATURE_STORAGE_LIST);
g_assert_true (dev_class->features & FPI_DEVICE_FEATURE_STORAGE_DELETE);
g_assert_false (dev_class->features & FPI_DEVICE_FEATURE_STORAGE_CLEAR);
g_assert_cmpuint (dev_class->features, !=, FP_DEVICE_FEATURE_NONE);
g_assert_true (dev_class->features & FP_DEVICE_FEATURE_CAPTURE);
g_assert_true (dev_class->features & FP_DEVICE_FEATURE_IDENTIFY);
g_assert_true (dev_class->features & FP_DEVICE_FEATURE_VERIFY);
g_assert_false (dev_class->features & FP_DEVICE_FEATURE_DUPLICATES_CHECK);
g_assert_true (dev_class->features & FP_DEVICE_FEATURE_STORAGE);
g_assert_false (dev_class->features & FP_DEVICE_FEATURE_STORAGE_LIST);
g_assert_true (dev_class->features & FP_DEVICE_FEATURE_STORAGE_DELETE);
g_assert_true (dev_class->features & FP_DEVICE_FEATURE_STORAGE_CLEAR);
}
static void
@@ -659,20 +731,41 @@ test_driver_initial_features_no_delete (void)
{
g_autoptr(FpAutoResetClass) dev_class = auto_reset_device_class ();
dev_class->list = NULL;
dev_class->features = FPI_DEVICE_FEATURE_NONE;
dev_class->delete = NULL;
dev_class->features = FP_DEVICE_FEATURE_NONE;
fpi_device_class_auto_initialize_features (dev_class);
g_assert_cmpuint (dev_class->features, !=, FPI_DEVICE_FEATURE_NONE);
g_assert_true (dev_class->features & FPI_DEVICE_FEATURE_CAPTURE);
g_assert_true (dev_class->features & FPI_DEVICE_FEATURE_IDENTIFY);
g_assert_true (dev_class->features & FPI_DEVICE_FEATURE_VERIFY);
g_assert_false (dev_class->features & FPI_DEVICE_FEATURE_DUPLICATES_CHECK);
g_assert_true (dev_class->features & FPI_DEVICE_FEATURE_STORAGE);
g_assert_false (dev_class->features & FPI_DEVICE_FEATURE_STORAGE_LIST);
g_assert_true (dev_class->features & FPI_DEVICE_FEATURE_STORAGE_DELETE);
g_assert_false (dev_class->features & FPI_DEVICE_FEATURE_STORAGE_CLEAR);
g_assert_cmpuint (dev_class->features, !=, FP_DEVICE_FEATURE_NONE);
g_assert_true (dev_class->features & FP_DEVICE_FEATURE_CAPTURE);
g_assert_true (dev_class->features & FP_DEVICE_FEATURE_IDENTIFY);
g_assert_true (dev_class->features & FP_DEVICE_FEATURE_VERIFY);
g_assert_false (dev_class->features & FP_DEVICE_FEATURE_DUPLICATES_CHECK);
g_assert_false (dev_class->features & FP_DEVICE_FEATURE_STORAGE);
g_assert_true (dev_class->features & FP_DEVICE_FEATURE_STORAGE_LIST);
g_assert_false (dev_class->features & FP_DEVICE_FEATURE_STORAGE_DELETE);
g_assert_true (dev_class->features & FP_DEVICE_FEATURE_STORAGE_CLEAR);
}
static void
test_driver_initial_features_no_clear (void)
{
g_autoptr(FpAutoResetClass) dev_class = auto_reset_device_class ();
dev_class->clear_storage = NULL;
dev_class->features = FP_DEVICE_FEATURE_NONE;
fpi_device_class_auto_initialize_features (dev_class);
g_assert_cmpuint (dev_class->features, !=, FP_DEVICE_FEATURE_NONE);
g_assert_true (dev_class->features & FP_DEVICE_FEATURE_CAPTURE);
g_assert_true (dev_class->features & FP_DEVICE_FEATURE_IDENTIFY);
g_assert_true (dev_class->features & FP_DEVICE_FEATURE_VERIFY);
g_assert_false (dev_class->features & FP_DEVICE_FEATURE_DUPLICATES_CHECK);
g_assert_true (dev_class->features & FP_DEVICE_FEATURE_STORAGE);
g_assert_true (dev_class->features & FP_DEVICE_FEATURE_STORAGE_LIST);
g_assert_true (dev_class->features & FP_DEVICE_FEATURE_STORAGE_DELETE);
g_assert_false (dev_class->features & FP_DEVICE_FEATURE_STORAGE_CLEAR);
}
static void
@@ -1173,7 +1266,7 @@ test_driver_verify_not_supported (void)
FpiDeviceFake *fake_dev;
gboolean match;
dev_class->features &= ~FPI_DEVICE_FEATURE_VERIFY;
dev_class->features &= ~FP_DEVICE_FEATURE_VERIFY;
device = auto_close_fake_device_new ();
fake_dev = FPI_DEVICE_FAKE (device);
@@ -1504,7 +1597,10 @@ test_driver_supports_identify (void)
dev_class->identify = fake_device_stub_identify;
device = g_object_new (FPI_TYPE_DEVICE_FAKE, NULL);
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
g_assert_true (fp_device_supports_identify (device));
G_GNUC_END_IGNORE_DEPRECATIONS
g_assert_true (fp_device_has_feature (device, FP_DEVICE_FEATURE_IDENTIFY));
}
static void
@@ -1513,10 +1609,13 @@ test_driver_do_not_support_identify (void)
g_autoptr(FpAutoResetClass) dev_class = auto_reset_device_class ();
g_autoptr(FpDevice) device = NULL;
dev_class->features &= ~FPI_DEVICE_FEATURE_IDENTIFY;
dev_class->features &= ~FP_DEVICE_FEATURE_IDENTIFY;
device = g_object_new (FPI_TYPE_DEVICE_FAKE, NULL);
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
g_assert_false (fp_device_supports_identify (device));
G_GNUC_END_IGNORE_DEPRECATIONS
g_assert_false (fp_device_has_feature (device, FP_DEVICE_FEATURE_IDENTIFY));
}
static void
@@ -1535,7 +1634,10 @@ test_driver_identify (void)
expected_matched = g_ptr_array_index (prints, g_random_int_range (0, 499));
fp_print_set_description (expected_matched, "fake-verified");
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
g_assert_true (fp_device_supports_identify (device));
G_GNUC_END_IGNORE_DEPRECATIONS
g_assert_true (fp_device_has_feature (device, FP_DEVICE_FEATURE_IDENTIFY));
match_data->gallery = prints;
@@ -1568,7 +1670,10 @@ test_driver_identify_fail (void)
FpDeviceClass *dev_class = FP_DEVICE_GET_CLASS (device);
FpiDeviceFake *fake_dev = FPI_DEVICE_FAKE (device);
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
g_assert_true (fp_device_supports_identify (device));
G_GNUC_END_IGNORE_DEPRECATIONS
g_assert_true (fp_device_has_feature (device, FP_DEVICE_FEATURE_IDENTIFY));
fake_dev->ret_print = make_fake_print (device, NULL);
g_assert_true (fp_device_identify_sync (device, prints, NULL,
@@ -1604,7 +1709,10 @@ test_driver_identify_retry (void)
expected_matched = g_ptr_array_index (prints, g_random_int_range (0, 499));
fp_print_set_description (expected_matched, "fake-verified");
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
g_assert_true (fp_device_supports_identify (device));
G_GNUC_END_IGNORE_DEPRECATIONS
g_assert_true (fp_device_has_feature (device, FP_DEVICE_FEATURE_IDENTIFY));
fake_dev->ret_error = fpi_device_retry_new (FP_DEVICE_RETRY_GENERAL);
g_assert_false (fp_device_identify_sync (device, prints, NULL,
@@ -1638,7 +1746,10 @@ test_driver_identify_error (void)
expected_matched = g_ptr_array_index (prints, g_random_int_range (0, 499));
fp_print_set_description (expected_matched, "fake-verified");
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
g_assert_true (fp_device_supports_identify (device));
G_GNUC_END_IGNORE_DEPRECATIONS
g_assert_true (fp_device_has_feature (device, FP_DEVICE_FEATURE_IDENTIFY));
fake_dev->ret_error = fpi_device_error_new (FP_DEVICE_ERROR_GENERAL);
g_assert_false (fp_device_identify_sync (device, prints, NULL,
@@ -1841,11 +1952,14 @@ test_driver_supports_capture (void)
g_autoptr(FpAutoResetClass) dev_class = auto_reset_device_class ();
g_autoptr(FpDevice) device = NULL;
dev_class->features |= FPI_DEVICE_FEATURE_CAPTURE;
dev_class->features |= FP_DEVICE_FEATURE_CAPTURE;
dev_class->capture = fake_device_stub_capture;
device = g_object_new (FPI_TYPE_DEVICE_FAKE, NULL);
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
g_assert_true (fp_device_supports_capture (device));
G_GNUC_END_IGNORE_DEPRECATIONS
g_assert_true (fp_device_has_feature (device, FP_DEVICE_FEATURE_CAPTURE));
}
static void
@@ -1854,11 +1968,14 @@ test_driver_do_not_support_capture (void)
g_autoptr(FpAutoResetClass) dev_class = auto_reset_device_class ();
g_autoptr(FpDevice) device = NULL;
dev_class->features &= ~FPI_DEVICE_FEATURE_CAPTURE;
dev_class->features &= ~FP_DEVICE_FEATURE_CAPTURE;
dev_class->capture = NULL;
device = g_object_new (FPI_TYPE_DEVICE_FAKE, NULL);
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
g_assert_false (fp_device_supports_capture (device));
G_GNUC_END_IGNORE_DEPRECATIONS
g_assert_false (fp_device_has_feature (device, FP_DEVICE_FEATURE_CAPTURE));
}
static void
@@ -1890,7 +2007,7 @@ test_driver_capture_not_supported (void)
gboolean wait_for_finger = TRUE;
FpiDeviceFake *fake_dev;
dev_class->features &= ~FPI_DEVICE_FEATURE_CAPTURE;
dev_class->features &= ~FP_DEVICE_FEATURE_CAPTURE;
device = auto_close_fake_device_new ();
fake_dev = FPI_DEVICE_FAKE (device);
@@ -1928,10 +2045,13 @@ test_driver_has_storage (void)
g_autoptr(FpAutoResetClass) dev_class = auto_reset_device_class ();
g_autoptr(FpDevice) device = NULL;
dev_class->features |= FPI_DEVICE_FEATURE_STORAGE;
dev_class->features |= FP_DEVICE_FEATURE_STORAGE;
device = g_object_new (FPI_TYPE_DEVICE_FAKE, NULL);
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
g_assert_true (fp_device_has_storage (device));
G_GNUC_END_IGNORE_DEPRECATIONS
g_assert_true (fp_device_has_feature (device, FP_DEVICE_FEATURE_STORAGE));
}
static void
@@ -1940,10 +2060,13 @@ test_driver_has_not_storage (void)
g_autoptr(FpAutoResetClass) dev_class = auto_reset_device_class ();
g_autoptr(FpDevice) device = NULL;
dev_class->features &= ~FPI_DEVICE_FEATURE_STORAGE;
dev_class->features &= ~FP_DEVICE_FEATURE_STORAGE;
device = g_object_new (FPI_TYPE_DEVICE_FAKE, NULL);
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
g_assert_false (fp_device_has_storage (device));
G_GNUC_END_IGNORE_DEPRECATIONS
g_assert_false (fp_device_has_feature (device, FP_DEVICE_FEATURE_STORAGE));
}
static void
@@ -1992,10 +2115,13 @@ test_driver_list_no_storage (void)
g_autoptr(GPtrArray) prints = NULL;
g_autoptr(GError) error = NULL;
dev_class->features &= ~FPI_DEVICE_FEATURE_STORAGE;
dev_class->features &= ~FP_DEVICE_FEATURE_STORAGE;
device = auto_close_fake_device_new ();
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
g_assert_false (fp_device_has_storage (device));
G_GNUC_END_IGNORE_DEPRECATIONS
g_assert_false (fp_device_has_feature (device, FP_DEVICE_FEATURE_STORAGE));
prints = fp_device_list_prints_sync (device, NULL, &error);
g_assert_null (prints);
@@ -2038,6 +2164,39 @@ test_driver_delete_error (void)
g_assert_false (ret);
}
static void
test_driver_clear_storage (void)
{
g_autoptr(GError) error = NULL;
g_autoptr(FpAutoCloseDevice) device = auto_close_fake_device_new ();
FpDeviceClass *dev_class = FP_DEVICE_GET_CLASS (device);
FpiDeviceFake *fake_dev = FPI_DEVICE_FAKE (device);
gboolean ret;
ret = fp_device_clear_storage_sync (device, NULL, &error);
g_assert (fake_dev->last_called_function == dev_class->clear_storage);
g_assert_no_error (error);
g_assert_true (ret);
}
static void
test_driver_clear_storage_error (void)
{
g_autoptr(GError) error = NULL;
g_autoptr(FpAutoCloseDevice) device = auto_close_fake_device_new ();
FpDeviceClass *dev_class = FP_DEVICE_GET_CLASS (device);
FpiDeviceFake *fake_dev = FPI_DEVICE_FAKE (device);
gboolean ret;
fake_dev->ret_error = fpi_device_error_new (FP_DEVICE_ERROR_GENERAL);
ret = fp_device_clear_storage_sync (device, NULL, &error);
g_assert (fake_dev->last_called_function == dev_class->clear_storage);
g_assert_error (error, FP_DEVICE_ERROR, FP_DEVICE_ERROR_GENERAL);
g_assert (error == g_steal_pointer (&fake_dev->ret_error));
g_assert_false (ret);
}
static gboolean
fake_device_delete_wait_for_cancel_timeout (gpointer data)
{
@@ -2404,6 +2563,12 @@ test_driver_action_error_all (void)
g_assert_error (error, FP_DEVICE_ERROR, FP_DEVICE_ERROR_DATA_INVALID);
g_clear_error (&error);
fake_dev->ret_error = fpi_device_error_new (FP_DEVICE_ERROR_DATA_INVALID);
g_assert_false (fp_device_clear_storage_sync (device, NULL, &error));
g_assert_true (fake_dev->last_called_function == dev_class->clear_storage);
g_assert_error (error, FP_DEVICE_ERROR, FP_DEVICE_ERROR_DATA_INVALID);
g_clear_error (&error);
/* Test close last, as we can't operate on a closed device. */
fake_dev->ret_error = fpi_device_error_new (FP_DEVICE_ERROR_DATA_INVALID);
g_assert_false (fp_device_close_sync (device, NULL, &error));
@@ -2503,6 +2668,16 @@ test_driver_action_error_fallback_all (void)
g_assert_error (error, FP_DEVICE_ERROR, FP_DEVICE_ERROR_GENERAL);
g_clear_error (&error);
g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_WARNING,
"*Device failed to pass an error to generic action "
"error function*");
g_assert_false (fp_device_clear_storage_sync (device, NULL, &error));
g_test_assert_expected_messages ();
g_assert_true (fake_dev->last_called_function == dev_class->clear_storage);
g_assert_error (error, FP_DEVICE_ERROR, FP_DEVICE_ERROR_GENERAL);
g_clear_error (&error);
/* Test close last, as we can't operate on a closed device. */
g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_WARNING,
"*Device failed to pass an error to generic action "
@@ -2661,6 +2836,7 @@ main (int argc, char *argv[])
g_test_add_func ("/driver/get_usb_device", test_driver_get_usb_device);
g_test_add_func ("/driver/get_virtual_env", test_driver_get_virtual_env);
g_test_add_func ("/driver/get_driver_data", test_driver_get_driver_data);
g_test_add_func ("/driver/features/probe_updates", test_driver_features_probe_updates);
g_test_add_func ("/driver/initial_features", test_driver_initial_features);
g_test_add_func ("/driver/initial_features/none", test_driver_initial_features_none);
g_test_add_func ("/driver/initial_features/no_capture", test_driver_initial_features_no_capture);
@@ -2669,6 +2845,8 @@ main (int argc, char *argv[])
g_test_add_func ("/driver/initial_features/no_storage", test_driver_initial_features_no_storage);
g_test_add_func ("/driver/initial_features/no_list", test_driver_initial_features_no_list);
g_test_add_func ("/driver/initial_features/no_delete", test_driver_initial_features_no_delete);
g_test_add_func ("/driver/initial_features/no_clear", test_driver_initial_features_no_clear);
g_test_add_func ("/driver/probe", test_driver_probe);
g_test_add_func ("/driver/probe/error", test_driver_probe_error);
@@ -2704,6 +2882,8 @@ main (int argc, char *argv[])
g_test_add_func ("/driver/list/no_storage", test_driver_list_no_storage);
g_test_add_func ("/driver/delete", test_driver_delete);
g_test_add_func ("/driver/delete/error", test_driver_delete_error);
g_test_add_func ("/driver/clear_storage", test_driver_clear_storage);
g_test_add_func ("/driver/clear_storage/error", test_driver_clear_storage_error);
g_test_add_func ("/driver/cancel", test_driver_cancel);
g_test_add_func ("/driver/cancel/fail", test_driver_cancel_fail);

View File

@@ -129,12 +129,12 @@ test_ssm_completed_callback (FpiSsm *ssm,
}
static FpiSsm *
ssm_test_new_full (int nr_states, const char *name)
ssm_test_new_full (int nr_states, int cleanup_state, const char *name)
{
FpiSsm *ssm;
FpiSsmTestData *data;
ssm = fpi_ssm_new_full (fake_device, test_ssm_handler, nr_states, name);
ssm = fpi_ssm_new_full (fake_device, test_ssm_handler, nr_states, cleanup_state, name);
data = fpi_ssm_test_data_new ();
data->expected_last_state = nr_states;
fpi_ssm_set_data (ssm, data, (GDestroyNotify) fpi_ssm_test_data_unref_by_ssm);
@@ -145,7 +145,7 @@ ssm_test_new_full (int nr_states, const char *name)
static FpiSsm *
ssm_test_new (void)
{
return ssm_test_new_full (FPI_TEST_SSM_STATE_NUM, "FPI_TEST_SSM");
return ssm_test_new_full (FPI_TEST_SSM_STATE_NUM, FPI_TEST_SSM_STATE_NUM, "FPI_TEST_SSM");
}
static gboolean
@@ -158,14 +158,6 @@ test_ssm_cancel_delayed_action_delayed (gpointer data)
return G_SOURCE_REMOVE;
}
static gboolean
test_ssm_cancel_cancellable_delayed (gpointer data)
{
g_cancellable_cancel (G_CANCELLABLE (data));
return G_SOURCE_REMOVE;
}
/* Tests */
static void
@@ -188,7 +180,8 @@ test_ssm_new_full (void)
FpiSsm *ssm;
ssm = fpi_ssm_new_full (fake_device, test_ssm_handler,
FPI_TEST_SSM_STATE_NUM, "Test SSM Name");
FPI_TEST_SSM_STATE_NUM, FPI_TEST_SSM_STATE_NUM,
"Test SSM Name");
g_assert_null (fpi_ssm_get_data (ssm));
g_assert_no_error (fpi_ssm_get_error (ssm));
@@ -215,6 +208,8 @@ test_ssm_new_wrong_states (void)
g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
"*BUG:*nr_states*");
g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
"*BUG:*start_cleanup*");
ssm = fpi_ssm_new (fake_device, test_ssm_handler, -1);
g_test_assert_expected_messages ();
}
@@ -271,7 +266,7 @@ test_ssm_start_single (void)
g_autoptr(FpiSsmTestData) data = NULL;
FpiSsm *ssm;
ssm = ssm_test_new_full (1, "FPI_TEST_SSM_SINGLE_STATE");
ssm = ssm_test_new_full (1, 1, "FPI_TEST_SSM_SINGLE_STATE");
data = fpi_ssm_test_data_ref (fpi_ssm_get_data (ssm));
fpi_ssm_start (ssm, test_ssm_completed_callback);
@@ -336,7 +331,7 @@ test_ssm_next_with_delayed (void)
g_assert_cmpint (fpi_ssm_get_cur_state (ssm), ==, FPI_TEST_SSM_STATE_0);
g_assert_cmpuint (g_slist_length (data->handlers_chain), ==, 1);
fpi_ssm_next_state_delayed (ssm, 10, NULL);
fpi_ssm_next_state_delayed (ssm, 10);
g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL, "*BUG:*timeout*");
fpi_ssm_next_state (ssm);
@@ -444,7 +439,7 @@ test_ssm_jump_to_state_with_delayed (void)
g_assert_cmpint (fpi_ssm_get_cur_state (ssm), ==, FPI_TEST_SSM_STATE_0);
g_assert_cmpuint (g_slist_length (data->handlers_chain), ==, 1);
fpi_ssm_jump_to_state_delayed (ssm, FPI_TEST_SSM_STATE_2, 10, NULL);
fpi_ssm_jump_to_state_delayed (ssm, FPI_TEST_SSM_STATE_2, 10);
g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL, "*BUG:*timeout*");
fpi_ssm_jump_to_state (ssm, FPI_TEST_SSM_STATE_2);
@@ -561,7 +556,7 @@ test_ssm_mark_completed_with_delayed (void)
g_assert_cmpuint (g_slist_length (data->handlers_chain), ==, 1);
data->expected_last_state = FPI_TEST_SSM_STATE_0;
fpi_ssm_mark_completed_delayed (ssm, 10, NULL);
fpi_ssm_mark_completed_delayed (ssm, 10);
g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL, "*BUG:*timeout*");
fpi_ssm_mark_completed (g_steal_pointer (&ssm));
@@ -623,7 +618,7 @@ test_ssm_mark_failed_with_delayed (void)
fpi_ssm_start (ssm, test_ssm_completed_callback);
g_assert_cmpuint (g_slist_length (data->handlers_chain), ==, 1);
fpi_ssm_mark_completed_delayed (ssm, 10, NULL);
fpi_ssm_mark_completed_delayed (ssm, 10);
g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL, "*BUG:*timeout*");
data->expected_last_state = FPI_TEST_SSM_STATE_0;
@@ -654,7 +649,7 @@ test_ssm_delayed_next (void)
g_assert_cmpint (fpi_ssm_get_cur_state (ssm), ==, FPI_TEST_SSM_STATE_0);
g_assert_cmpuint (g_slist_length (data->handlers_chain), ==, 1);
fpi_ssm_next_state_delayed (ssm, 10, NULL);
fpi_ssm_next_state_delayed (ssm, 10);
g_assert_cmpint (data->handler_state, ==, FPI_TEST_SSM_STATE_0);
g_assert_cmpint (fpi_ssm_get_cur_state (ssm), ==, FPI_TEST_SSM_STATE_0);
g_assert_cmpuint (g_slist_length (data->handlers_chain), ==, 1);
@@ -682,7 +677,7 @@ test_ssm_delayed_next_cancel (void)
g_assert_cmpint (fpi_ssm_get_cur_state (ssm), ==, FPI_TEST_SSM_STATE_0);
g_assert_cmpuint (g_slist_length (data->handlers_chain), ==, 1);
fpi_ssm_next_state_delayed (ssm, 10, NULL);
fpi_ssm_next_state_delayed (ssm, 10);
g_assert_cmpint (data->handler_state, ==, FPI_TEST_SSM_STATE_0);
g_assert_cmpint (fpi_ssm_get_cur_state (ssm), ==, FPI_TEST_SSM_STATE_0);
g_assert_cmpuint (g_slist_length (data->handlers_chain), ==, 1);
@@ -701,40 +696,6 @@ test_ssm_delayed_next_cancel (void)
g_assert_no_error (data->error);
}
static void
test_ssm_delayed_next_cancellable (void)
{
g_autoptr(FpiSsm) ssm = ssm_test_new ();
g_autoptr(GCancellable) cancellable = g_cancellable_new ();
FpiSsmTestData *data = fpi_ssm_get_data (ssm);
fpi_ssm_start (ssm, test_ssm_completed_callback);
g_assert_cmpint (data->handler_state, ==, FPI_TEST_SSM_STATE_0);
g_assert_cmpint (fpi_ssm_get_cur_state (ssm), ==, FPI_TEST_SSM_STATE_0);
g_assert_cmpuint (g_slist_length (data->handlers_chain), ==, 1);
fpi_ssm_next_state_delayed (ssm, 10, cancellable);
g_assert_cmpint (data->handler_state, ==, FPI_TEST_SSM_STATE_0);
g_assert_cmpint (fpi_ssm_get_cur_state (ssm), ==, FPI_TEST_SSM_STATE_0);
g_assert_cmpuint (g_slist_length (data->handlers_chain), ==, 1);
g_idle_add_full (G_PRIORITY_HIGH, test_ssm_cancel_cancellable_delayed, cancellable, NULL);
while (!g_cancellable_is_cancelled (cancellable))
g_main_context_iteration (NULL, TRUE);
g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL, "*BUG:*timeout*");
fpi_ssm_cancel_delayed_state_change (ssm);
g_test_assert_expected_messages ();
g_assert_cmpint (data->handler_state, ==, FPI_TEST_SSM_STATE_0);
g_assert_cmpint (fpi_ssm_get_cur_state (ssm), ==, FPI_TEST_SSM_STATE_0);
g_assert_cmpuint (g_slist_length (data->handlers_chain), ==, 1);
g_assert_false (data->completed);
g_assert_no_error (data->error);
}
static void
test_ssm_delayed_next_not_started (void)
{
@@ -742,7 +703,7 @@ test_ssm_delayed_next_not_started (void)
FpiSsmTestData *data = fpi_ssm_get_data (ssm);
g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL, "*BUG:*completed*");
fpi_ssm_next_state_delayed (ssm, 10, NULL);
fpi_ssm_next_state_delayed (ssm, 10);
g_test_assert_expected_messages ();
g_assert_cmpint (data->handler_state, ==, -1);
@@ -773,7 +734,7 @@ test_ssm_delayed_next_complete (void)
g_assert_cmpint (fpi_ssm_get_cur_state (ssm), ==, FPI_TEST_SSM_STATE_0);
g_assert_cmpuint (g_slist_length (data->handlers_chain), ==, 1);
fpi_ssm_next_state_delayed (ssm, 10, NULL);
fpi_ssm_next_state_delayed (ssm, 10);
g_assert_cmpint (data->handler_state, ==, FPI_TEST_SSM_STATE_0);
g_assert_cmpint (fpi_ssm_get_cur_state (ssm), ==, FPI_TEST_SSM_STATE_0);
g_assert_cmpuint (g_slist_length (data->handlers_chain), ==, 1);
@@ -785,7 +746,7 @@ test_ssm_delayed_next_complete (void)
g_assert_cmpint (fpi_ssm_get_cur_state (ssm), ==, FPI_TEST_SSM_STATE_1);
g_assert_cmpuint (g_slist_length (data->handlers_chain), ==, 2);
fpi_ssm_next_state_delayed (ssm, 10, NULL);
fpi_ssm_next_state_delayed (ssm, 10);
g_assert_cmpint (data->handler_state, ==, FPI_TEST_SSM_STATE_1);
g_assert_cmpint (fpi_ssm_get_cur_state (ssm), ==, FPI_TEST_SSM_STATE_1);
g_assert_cmpuint (g_slist_length (data->handlers_chain), ==, 2);
@@ -797,7 +758,7 @@ test_ssm_delayed_next_complete (void)
g_assert_cmpint (fpi_ssm_get_cur_state (ssm), ==, FPI_TEST_SSM_STATE_2);
g_assert_cmpuint (g_slist_length (data->handlers_chain), ==, 3);
fpi_ssm_next_state_delayed (ssm, 10, NULL);
fpi_ssm_next_state_delayed (ssm, 10);
g_assert_cmpint (data->handler_state, ==, FPI_TEST_SSM_STATE_2);
g_assert_cmpint (fpi_ssm_get_cur_state (ssm), ==, FPI_TEST_SSM_STATE_2);
g_assert_cmpuint (g_slist_length (data->handlers_chain), ==, 3);
@@ -809,7 +770,7 @@ test_ssm_delayed_next_complete (void)
g_assert_cmpint (fpi_ssm_get_cur_state (ssm), ==, FPI_TEST_SSM_STATE_3);
g_assert_cmpuint (g_slist_length (data->handlers_chain), ==, 4);
fpi_ssm_next_state_delayed (ssm, 10, NULL);
fpi_ssm_next_state_delayed (ssm, 10);
g_assert_cmpint (data->handler_state, ==, FPI_TEST_SSM_STATE_3);
g_assert_cmpint (fpi_ssm_get_cur_state (ssm), ==, FPI_TEST_SSM_STATE_3);
g_assert_cmpuint (g_slist_length (data->handlers_chain), ==, 4);
@@ -835,7 +796,7 @@ test_ssm_delayed_jump_to_state (void)
g_assert_cmpint (fpi_ssm_get_cur_state (ssm), ==, FPI_TEST_SSM_STATE_0);
g_assert_cmpuint (g_slist_length (data->handlers_chain), ==, 1);
fpi_ssm_jump_to_state_delayed (ssm, FPI_TEST_SSM_STATE_2, 10, NULL);
fpi_ssm_jump_to_state_delayed (ssm, FPI_TEST_SSM_STATE_2, 10);
g_assert_cmpint (data->handler_state, ==, FPI_TEST_SSM_STATE_0);
g_assert_cmpint (fpi_ssm_get_cur_state (ssm), ==, FPI_TEST_SSM_STATE_0);
@@ -848,7 +809,7 @@ test_ssm_delayed_jump_to_state (void)
g_assert_cmpint (fpi_ssm_get_cur_state (ssm), ==, FPI_TEST_SSM_STATE_2);
g_assert_cmpuint (g_slist_length (data->handlers_chain), ==, 2);
fpi_ssm_jump_to_state_delayed (ssm, FPI_TEST_SSM_STATE_1, 10, NULL);
fpi_ssm_jump_to_state_delayed (ssm, FPI_TEST_SSM_STATE_1, 10);
g_assert_cmpint (data->handler_state, ==, FPI_TEST_SSM_STATE_2);
g_assert_cmpint (fpi_ssm_get_cur_state (ssm), ==, FPI_TEST_SSM_STATE_2);
@@ -877,7 +838,7 @@ test_ssm_delayed_jump_to_state_cancel (void)
g_assert_cmpint (fpi_ssm_get_cur_state (ssm), ==, FPI_TEST_SSM_STATE_0);
g_assert_cmpuint (g_slist_length (data->handlers_chain), ==, 1);
fpi_ssm_jump_to_state_delayed (ssm, FPI_TEST_SSM_STATE_2, 10, NULL);
fpi_ssm_jump_to_state_delayed (ssm, FPI_TEST_SSM_STATE_2, 10);
g_assert_cmpint (data->handler_state, ==, FPI_TEST_SSM_STATE_0);
g_assert_cmpint (fpi_ssm_get_cur_state (ssm), ==, FPI_TEST_SSM_STATE_0);
g_assert_cmpuint (g_slist_length (data->handlers_chain), ==, 1);
@@ -896,40 +857,6 @@ test_ssm_delayed_jump_to_state_cancel (void)
g_assert_no_error (data->error);
}
static void
test_ssm_delayed_jump_to_state_cancellable (void)
{
g_autoptr(FpiSsm) ssm = ssm_test_new ();
g_autoptr(GCancellable) cancellable = g_cancellable_new ();
FpiSsmTestData *data = fpi_ssm_get_data (ssm);
fpi_ssm_start (ssm, test_ssm_completed_callback);
g_assert_cmpint (data->handler_state, ==, FPI_TEST_SSM_STATE_0);
g_assert_cmpint (fpi_ssm_get_cur_state (ssm), ==, FPI_TEST_SSM_STATE_0);
g_assert_cmpuint (g_slist_length (data->handlers_chain), ==, 1);
fpi_ssm_jump_to_state_delayed (ssm, FPI_TEST_SSM_STATE_2, 10, cancellable);
g_assert_cmpint (data->handler_state, ==, FPI_TEST_SSM_STATE_0);
g_assert_cmpint (fpi_ssm_get_cur_state (ssm), ==, FPI_TEST_SSM_STATE_0);
g_assert_cmpuint (g_slist_length (data->handlers_chain), ==, 1);
g_idle_add_full (G_PRIORITY_HIGH, test_ssm_cancel_cancellable_delayed, cancellable, NULL);
while (!g_cancellable_is_cancelled (cancellable))
g_main_context_iteration (NULL, TRUE);
g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL, "*BUG:*timeout*");
fpi_ssm_cancel_delayed_state_change (ssm);
g_test_assert_expected_messages ();
g_assert_cmpint (data->handler_state, ==, FPI_TEST_SSM_STATE_0);
g_assert_cmpint (fpi_ssm_get_cur_state (ssm), ==, FPI_TEST_SSM_STATE_0);
g_assert_cmpuint (g_slist_length (data->handlers_chain), ==, 1);
g_assert_false (data->completed);
g_assert_no_error (data->error);
}
static void
test_ssm_delayed_jump_to_state_not_started (void)
{
@@ -937,7 +864,7 @@ test_ssm_delayed_jump_to_state_not_started (void)
FpiSsmTestData *data = fpi_ssm_get_data (ssm);
g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL, "*BUG:*completed*");
fpi_ssm_jump_to_state_delayed (ssm, FPI_TEST_SSM_STATE_2, 10, NULL);
fpi_ssm_jump_to_state_delayed (ssm, FPI_TEST_SSM_STATE_2, 10);
g_test_assert_expected_messages ();
g_assert_cmpint (data->handler_state, ==, -1);
@@ -967,7 +894,7 @@ test_ssm_delayed_jump_to_state_last (void)
g_assert_cmpint (fpi_ssm_get_cur_state (ssm), ==, FPI_TEST_SSM_STATE_0);
g_assert_cmpuint (g_slist_length (data->handlers_chain), ==, 1);
fpi_ssm_jump_to_state_delayed (ssm, FPI_TEST_SSM_STATE_3, 10, NULL);
fpi_ssm_jump_to_state_delayed (ssm, FPI_TEST_SSM_STATE_3, 10);
g_assert_cmpint (data->handler_state, ==, FPI_TEST_SSM_STATE_0);
g_assert_cmpint (fpi_ssm_get_cur_state (ssm), ==, FPI_TEST_SSM_STATE_0);
@@ -996,7 +923,7 @@ test_ssm_delayed_jump_to_state_wrong (void)
g_assert_cmpuint (g_slist_length (data->handlers_chain), ==, 1);
g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL, "*BUG:*nr_states*");
fpi_ssm_jump_to_state_delayed (ssm, FPI_TEST_SSM_STATE_NUM + 10, 10, NULL);
fpi_ssm_jump_to_state_delayed (ssm, FPI_TEST_SSM_STATE_NUM + 10, 10);
g_test_assert_expected_messages ();
g_assert_cmpint (data->handler_state, ==, FPI_TEST_SSM_STATE_0);
@@ -1013,7 +940,7 @@ test_ssm_delayed_jump_to_state_wrong (void)
g_assert_cmpuint (g_slist_length (data->handlers_chain), ==, 2);
g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL, "*BUG:*state*");
fpi_ssm_jump_to_state_delayed (ssm, FPI_TEST_SSM_STATE_0 - 10, 10, NULL);
fpi_ssm_jump_to_state_delayed (ssm, FPI_TEST_SSM_STATE_0 - 10, 10);
g_test_assert_expected_messages ();
g_assert_cmpint (data->handler_state, ==, FPI_TEST_SSM_STATE_NUM + 10);
@@ -1043,7 +970,7 @@ test_ssm_delayed_mark_completed (void)
g_assert_cmpuint (g_slist_length (data->handlers_chain), ==, 1);
data->expected_last_state = FPI_TEST_SSM_STATE_0;
fpi_ssm_mark_completed_delayed (g_steal_pointer (&ssm), 10, NULL);
fpi_ssm_mark_completed_delayed (g_steal_pointer (&ssm), 10);
g_assert_cmpuint (g_slist_length (data->handlers_chain), ==, 1);
while (g_slist_length (data->handlers_chain) == 1)
@@ -1063,7 +990,7 @@ test_ssm_delayed_mark_completed_not_started (void)
g_autoptr(FpiSsmTestData) data = fpi_ssm_test_data_ref (fpi_ssm_get_data (ssm));
g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL, "*BUG:*completed*");
fpi_ssm_mark_completed_delayed (ssm, 10, NULL);
fpi_ssm_mark_completed_delayed (ssm, 10);
g_test_assert_expected_messages ();
g_timeout_add (100, G_SOURCE_FUNC (fpi_ssm_test_nullify_pointer), &ssm);
@@ -1090,7 +1017,7 @@ test_ssm_delayed_mark_completed_cancel (void)
g_assert_cmpint (fpi_ssm_get_cur_state (ssm), ==, FPI_TEST_SSM_STATE_0);
g_assert_cmpuint (g_slist_length (data->handlers_chain), ==, 1);
fpi_ssm_mark_completed_delayed (ssm, 10, NULL);
fpi_ssm_mark_completed_delayed (ssm, 10);
g_assert_cmpint (data->handler_state, ==, FPI_TEST_SSM_STATE_0);
g_assert_cmpint (fpi_ssm_get_cur_state (ssm), ==, FPI_TEST_SSM_STATE_0);
g_assert_cmpuint (g_slist_length (data->handlers_chain), ==, 1);
@@ -1110,40 +1037,6 @@ test_ssm_delayed_mark_completed_cancel (void)
g_assert_false (data->ssm_destroyed);
}
static void
test_ssm_delayed_mark_completed_cancellable (void)
{
g_autoptr(FpiSsm) ssm = ssm_test_new ();
g_autoptr(GCancellable) cancellable = g_cancellable_new ();
FpiSsmTestData *data = fpi_ssm_get_data (ssm);
fpi_ssm_start (ssm, test_ssm_completed_callback);
g_assert_cmpint (data->handler_state, ==, FPI_TEST_SSM_STATE_0);
g_assert_cmpint (fpi_ssm_get_cur_state (ssm), ==, FPI_TEST_SSM_STATE_0);
g_assert_cmpuint (g_slist_length (data->handlers_chain), ==, 1);
fpi_ssm_mark_completed_delayed (ssm, 10, cancellable);
g_assert_cmpint (data->handler_state, ==, FPI_TEST_SSM_STATE_0);
g_assert_cmpint (fpi_ssm_get_cur_state (ssm), ==, FPI_TEST_SSM_STATE_0);
g_assert_cmpuint (g_slist_length (data->handlers_chain), ==, 1);
g_idle_add_full (G_PRIORITY_HIGH, test_ssm_cancel_cancellable_delayed, cancellable, NULL);
while (!g_cancellable_is_cancelled (cancellable))
g_main_context_iteration (NULL, TRUE);
g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL, "*BUG:*timeout*");
fpi_ssm_cancel_delayed_state_change (ssm);
g_test_assert_expected_messages ();
g_assert_cmpint (data->handler_state, ==, FPI_TEST_SSM_STATE_0);
g_assert_cmpint (fpi_ssm_get_cur_state (ssm), ==, FPI_TEST_SSM_STATE_0);
g_assert_cmpuint (g_slist_length (data->handlers_chain), ==, 1);
g_assert_false (data->completed);
g_assert_no_error (data->error);
}
static void
test_ssm_delayed_cancel_error (void)
{
@@ -1170,7 +1063,7 @@ test_ssm_subssm_start (void)
{
g_autoptr(FpiSsm) ssm = ssm_test_new ();
g_autoptr(FpiSsm) subssm =
ssm_test_new_full (FPI_TEST_SSM_STATE_NUM, "FPI_TEST_SUB_SSM");
ssm_test_new_full (FPI_TEST_SSM_STATE_NUM, FPI_TEST_SSM_STATE_NUM, "FPI_TEST_SUB_SSM");
FpiSsmTestData *data = fpi_ssm_get_data (ssm);
g_autoptr(FpiSsmTestData) subdata =
@@ -1222,7 +1115,7 @@ test_ssm_subssm_mark_failed (void)
{
g_autoptr(FpiSsm) ssm = ssm_test_new ();
g_autoptr(FpiSsm) subssm =
ssm_test_new_full (FPI_TEST_SSM_STATE_NUM, "FPI_TEST_SUB_SSM");
ssm_test_new_full (FPI_TEST_SSM_STATE_NUM, FPI_TEST_SSM_STATE_NUM, "FPI_TEST_SUB_SSM");
g_autoptr(FpiSsmTestData) data =
fpi_ssm_test_data_ref (fpi_ssm_get_data (ssm));
g_autoptr(FpiSsmTestData) subdata =
@@ -1261,7 +1154,7 @@ test_ssm_subssm_start_with_started (void)
{
g_autoptr(FpiSsm) ssm = ssm_test_new ();
g_autoptr(FpiSsm) subssm =
ssm_test_new_full (FPI_TEST_SSM_STATE_NUM, "FPI_TEST_SUB_SSM");
ssm_test_new_full (FPI_TEST_SSM_STATE_NUM, FPI_TEST_SSM_STATE_NUM, "FPI_TEST_SUB_SSM");
FpiSsmTestData *data = fpi_ssm_get_data (ssm);
g_autoptr(FpiSsmTestData) subdata =
@@ -1305,7 +1198,7 @@ test_ssm_subssm_start_with_delayed (void)
{
g_autoptr(FpiSsm) ssm = ssm_test_new ();
g_autoptr(FpiSsm) subssm =
ssm_test_new_full (FPI_TEST_SSM_STATE_NUM, "FPI_TEST_SUB_SSM");
ssm_test_new_full (FPI_TEST_SSM_STATE_NUM, FPI_TEST_SSM_STATE_NUM, "FPI_TEST_SUB_SSM");
FpiSsmTestData *data = fpi_ssm_get_data (ssm);
g_autoptr(FpiSsmTestData) subdata =
@@ -1317,7 +1210,7 @@ test_ssm_subssm_start_with_delayed (void)
g_assert_cmpint (fpi_ssm_get_cur_state (ssm), ==, FPI_TEST_SSM_STATE_0);
g_assert_cmpuint (g_slist_length (data->handlers_chain), ==, 1);
fpi_ssm_next_state_delayed (ssm, 10, NULL);
fpi_ssm_next_state_delayed (ssm, 10);
g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL, "*BUG:*timeout*");
fpi_ssm_start_subsm (ssm, subssm);
@@ -1348,6 +1241,76 @@ test_ssm_subssm_start_with_delayed (void)
g_assert_no_error (data->error);
}
static void
test_ssm_cleanup_complete (void)
{
FpiSsm *ssm = ssm_test_new_full (4, FPI_TEST_SSM_STATE_2, "FPI_TEST_SSM");
g_autoptr(FpiSsmTestData) data = fpi_ssm_test_data_ref (fpi_ssm_get_data (ssm));
fpi_ssm_start (ssm, test_ssm_completed_callback);
g_assert_cmpuint (g_slist_length (data->handlers_chain), ==, 1);
data->expected_last_state = FPI_TEST_SSM_STATE_3;
/* Completing jumps to the cleanup state */
fpi_ssm_mark_completed (ssm);
g_assert_cmpint (data->handler_state, ==, FPI_TEST_SSM_STATE_2);
g_assert_cmpuint (g_slist_length (data->handlers_chain), ==, 2);
g_assert_false (data->completed);
g_assert_false (data->ssm_destroyed);
/* Completing again jumps to the next cleanup state */
fpi_ssm_mark_completed (ssm);
g_assert_cmpint (data->handler_state, ==, FPI_TEST_SSM_STATE_3);
g_assert_cmpuint (g_slist_length (data->handlers_chain), ==, 3);
g_assert_false (data->completed);
g_assert_false (data->ssm_destroyed);
/* Completing again finalizes everything */
fpi_ssm_mark_completed (ssm);
g_assert_cmpint (data->handler_state, ==, FPI_TEST_SSM_STATE_3);
g_assert_cmpuint (g_slist_length (data->handlers_chain), ==, 4);
g_assert_true (data->completed);
g_assert_no_error (data->error);
g_assert_true (data->ssm_destroyed);
}
static void
test_ssm_cleanup_fail (void)
{
FpiSsm *ssm = ssm_test_new_full (4, FPI_TEST_SSM_STATE_2, "FPI_TEST_SSM");
g_autoptr(FpiSsmTestData) data = fpi_ssm_test_data_ref (fpi_ssm_get_data (ssm));
fpi_ssm_start (ssm, test_ssm_completed_callback);
g_assert_cmpuint (g_slist_length (data->handlers_chain), ==, 1);
data->expected_last_state = FPI_TEST_SSM_STATE_3;
/* Failing jumps to the cleanup state */
fpi_ssm_mark_failed (ssm, g_error_new (G_IO_ERROR, G_IO_ERROR_CANCELLED, "non-cleanup"));
g_assert_cmpint (data->handler_state, ==, FPI_TEST_SSM_STATE_2);
g_assert_cmpuint (g_slist_length (data->handlers_chain), ==, 2);
g_assert_false (data->completed);
g_assert_false (data->ssm_destroyed);
/* Failing again jumps to the next cleanup state */
fpi_ssm_mark_failed (ssm, g_error_new (G_IO_ERROR, G_IO_ERROR_FAILED, "cleanup 1"));
g_assert_cmpint (data->handler_state, ==, FPI_TEST_SSM_STATE_3);
g_assert_cmpuint (g_slist_length (data->handlers_chain), ==, 3);
g_assert_false (data->completed);
g_assert_false (data->ssm_destroyed);
/* Failing again finalizes everything */
fpi_ssm_mark_failed (ssm, g_error_new (G_IO_ERROR, G_IO_ERROR_FAILED, "cleanup 2"));
g_assert_cmpint (data->handler_state, ==, FPI_TEST_SSM_STATE_3);
g_assert_cmpuint (g_slist_length (data->handlers_chain), ==, 4);
g_assert_true (data->completed);
g_assert_error (data->error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
g_assert_true (data->ssm_destroyed);
}
int
main (int argc, char *argv[])
{
@@ -1384,24 +1347,23 @@ main (int argc, char *argv[])
g_test_add_func ("/ssm/mark_failed/with_delayed", test_ssm_mark_failed_with_delayed);
g_test_add_func ("/ssm/delayed/next", test_ssm_delayed_next);
g_test_add_func ("/ssm/delayed/next/cancel", test_ssm_delayed_next_cancel);
g_test_add_func ("/ssm/delayed/next/cancellable", test_ssm_delayed_next_cancellable);
g_test_add_func ("/ssm/delayed/next/not_started", test_ssm_delayed_next_not_started);
g_test_add_func ("/ssm/delayed/next/complete", test_ssm_delayed_next_complete);
g_test_add_func ("/ssm/delayed/jump_to_state", test_ssm_delayed_jump_to_state);
g_test_add_func ("/ssm/delayed/jump_to_state/cancel", test_ssm_delayed_jump_to_state_cancel);
g_test_add_func ("/ssm/delayed/jump_to_state/cancellable", test_ssm_delayed_jump_to_state_cancellable);
g_test_add_func ("/ssm/delayed/jump_to_state/not_started", test_ssm_delayed_jump_to_state_not_started);
g_test_add_func ("/ssm/delayed/jump_to_state/last", test_ssm_delayed_jump_to_state_last);
g_test_add_func ("/ssm/delayed/jump_to_state/wrong", test_ssm_delayed_jump_to_state_wrong);
g_test_add_func ("/ssm/delayed/mark_completed", test_ssm_delayed_mark_completed);
g_test_add_func ("/ssm/delayed/mark_completed/cancel", test_ssm_delayed_mark_completed_cancel);
g_test_add_func ("/ssm/delayed/mark_completed/cancellable", test_ssm_delayed_mark_completed_cancellable);
g_test_add_func ("/ssm/delayed/mark_completed/not_started", test_ssm_delayed_mark_completed_not_started);
g_test_add_func ("/ssm/delayed/cancel/error", test_ssm_delayed_cancel_error);
g_test_add_func ("/ssm/subssm/start", test_ssm_subssm_start);
g_test_add_func ("/ssm/subssm/start/with_started", test_ssm_subssm_start_with_started);
g_test_add_func ("/ssm/subssm/start/with_delayed", test_ssm_subssm_start_with_delayed);
g_test_add_func ("/ssm/subssm/mark_failed", test_ssm_subssm_mark_failed);
g_test_add_func ("/ssm/cleanup/complete", test_ssm_cleanup_complete);
g_test_add_func ("/ssm/cleanup/fail", test_ssm_cleanup_fail);
return g_test_run ();
}

View File

@@ -1,3 +0,0 @@
#!/bin/bash
exec $LIBFPRINT_TEST_WRAPPER $@

View File

@@ -3,6 +3,7 @@
import sys
import os
import os.path
import glob
import shutil
import tempfile
import subprocess
@@ -17,6 +18,9 @@ try:
if version < (0, 13, 2):
print('umockdev is too old for test to be reliable, expect random failures!')
print('Please update umockdev to at least 0.13.2.')
pcap_supported = version >= (0, 16, 2) or os.getenv('CI_PROJECT_NAME') == "libfprint"
spi_supported = version >= (0, 16) or os.getenv('CI_PROJECT_NAME') == "libfprint"
except FileNotFoundError:
print('umockdev-run not found, skipping test!')
print('Please install umockdev.')
@@ -28,7 +32,6 @@ ddir = sys.argv[1]
tmpdir = tempfile.mkdtemp(prefix='libfprint-umockdev-test-')
assert os.path.isdir(ddir)
assert os.path.isfile(os.path.join(ddir, "device"))
def cmp_pngs(png_a, png_b):
print("Comparing PNGs %s and %s" % (png_a, png_b))
@@ -55,14 +58,41 @@ def cmp_pngs(png_a, png_b):
def get_umockdev_runner(ioctl_basename):
ioctl = os.path.join(ddir, "{}.ioctl".format(ioctl_basename))
device = os.path.join(ddir, "device")
pcap = os.path.join(ddir, "{}.pcapng".format(ioctl_basename))
devices = glob.glob(os.path.join(ddir, "device")) + glob.glob(os.path.join(ddir, "device-*[!~]"))
device_args = []
for device in devices:
p = open(device).readline().strip()
assert p.startswith('P: ')
device_args.extend(("-d", device))
if os.path.exists(pcap):
syspath = '/sys' + p[3:]
umockdev = ['umockdev-run', *device_args,
'-p', "%s=%s" % (syspath, pcap),
'--']
# Skip test if we detect too old umockdev for pcap replay
if not pcap_supported:
sys.exit(77)
else:
dev = open(ioctl).readline().strip()
assert dev.startswith('@DEV ')
dev = dev[5:]
if dev.endswith(" (SPI)"):
dev = dev[:dev.rindex(" ")]
umockdev = ['umockdev-run', '-d', device,
# Skip test if we detect too old umockdev for spi replay
if not spi_supported:
sys.exit(77)
umockdev = ['umockdev-run', *device_args,
'-i', "%s=%s" % (dev, ioctl),
'--']
wrapper = os.getenv('LIBFPRINT_TEST_WRAPPER')
return umockdev + (wrapper.split(' ') if wrapper else []) + [sys.executable]
@@ -81,10 +111,10 @@ def custom():
['%s' % os.path.join(ddir, "custom.py")])
try:
if os.path.exists(os.path.join(ddir, "capture.ioctl")):
if glob.glob(os.path.join(ddir, "capture.*")):
capture()
if os.path.exists(os.path.join(ddir, "custom.ioctl")):
if glob.glob(os.path.join(ddir, "custom.*")):
custom()
except Exception as e:

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

319
tests/upektc_img/device Normal file
View File

@@ -0,0 +1,319 @@
P: /devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.3
N: bus/usb/001/003=12010101000000087E14162002000102000109022700010100A0320904000003FF000000070581024000000705020240000007058303040014
E: DEVNAME=/dev/bus/usb/001/003
E: DEVTYPE=usb_device
E: DRIVER=usb
E: PRODUCT=147e/2016/2
E: TYPE=0/0/0
E: BUSNUM=001
E: DEVNUM=003
E: MAJOR=189
E: MINOR=2
E: SUBSYSTEM=usb
E: ID_VENDOR=UPEK
E: ID_VENDOR_ENC=UPEK
E: ID_VENDOR_ID=147e
E: ID_MODEL=Biometric_Coprocessor
E: ID_MODEL_ENC=Biometric\x20Coprocessor
E: ID_MODEL_ID=2016
E: ID_REVISION=0002
E: ID_SERIAL=UPEK_Biometric_Coprocessor
E: ID_BUS=usb
E: ID_USB_INTERFACES=:ff0000:
E: ID_VENDOR_FROM_DATABASE=Upek
E: ID_MODEL_FROM_DATABASE=Biometric Touchchip/Touchstrip Fingerprint Sensor
E: ID_PATH=pci-0000:00:1a.0-usb-0:1.3
E: ID_PATH_TAG=pci-0000_00_1a_0-usb-0_1_3
E: LIBFPRINT_DRIVER=Upek TouchChip Fingerprint Coprocessor
E: ID_FOR_SEAT=usb-pci-0000_00_1a_0-usb-0_1_3
E: TAGS=:seat:
E: CURRENT_TAGS=:seat:
A: authorized=1\n
A: avoid_reset_quirk=0\n
A: bConfigurationValue=1\n
A: bDeviceClass=00\n
A: bDeviceProtocol=00\n
A: bDeviceSubClass=00\n
A: bMaxPacketSize0=8\n
A: bMaxPower=100mA\n
A: bNumConfigurations=1\n
A: bNumInterfaces= 1\n
A: bcdDevice=0002\n
A: bmAttributes=a0\n
A: busnum=1\n
A: configuration=
H: descriptors=12010101000000087E14162002000102000109022700010100A0320904000003FF000000070581024000000705020240000007058303040014
A: dev=189:2\n
A: devnum=3\n
A: devpath=1.3\n
L: driver=../../../../../../bus/usb/drivers/usb
L: firmware_node=../../../../../LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:2d/device:2e/device:2f/device:32
A: idProduct=2016\n
A: idVendor=147e\n
A: ltm_capable=no\n
A: manufacturer=UPEK\n
A: maxchild=0\n
L: port=../1-1:1.0/1-1-port3
A: power/active_duration=757220\n
A: power/async=enabled\n
A: power/autosuspend=2\n
A: power/autosuspend_delay_ms=2000\n
A: power/connected_duration=857556\n
A: power/control=auto\n
A: power/level=auto\n
A: power/persist=1\n
A: power/runtime_active_kids=0\n
A: power/runtime_active_time=762579\n
A: power/runtime_enabled=enabled\n
A: power/runtime_status=active\n
A: power/runtime_suspended_time=94791\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=Biometric Coprocessor\n
A: quirks=0x0\n
A: removable=fixed\n
A: rx_lanes=1\n
A: speed=12\n
A: tx_lanes=1\n
A: urbnum=620\n
A: version= 1.01\n
P: /devices/pci0000:00/0000:00:1a.0/usb1/1-1
N: bus/usb/001/002=12010002090001408780200000000000000109021900010100E0000904000001090000000705810301000C
E: DEVNAME=/dev/bus/usb/001/002
E: DEVTYPE=usb_device
E: DRIVER=usb
E: PRODUCT=8087/20/0
E: TYPE=9/0/1
E: BUSNUM=001
E: DEVNUM=002
E: MAJOR=189
E: MINOR=1
E: SUBSYSTEM=usb
E: ID_VENDOR=8087
E: ID_VENDOR_ENC=8087
E: ID_VENDOR_ID=8087
E: ID_MODEL=0020
E: ID_MODEL_ENC=0020
E: ID_MODEL_ID=0020
E: ID_REVISION=0000
E: ID_SERIAL=8087_0020
E: ID_BUS=usb
E: ID_USB_INTERFACES=:090000:
E: ID_VENDOR_FROM_DATABASE=Intel Corp.
E: ID_MODEL_FROM_DATABASE=Integrated Rate Matching Hub
E: ID_PATH=pci-0000:00:1a.0-usb-0:1
E: ID_PATH_TAG=pci-0000_00_1a_0-usb-0_1
E: ID_FOR_SEAT=usb-pci-0000_00_1a_0-usb-0_1
E: TAGS=:seat:
E: CURRENT_TAGS=:seat:
A: authorized=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=0000\n
A: bmAttributes=e0\n
A: busnum=1\n
A: configuration=
H: descriptors=12010002090001408780200000000000000109021900010100E0000904000001090000000705810301000C
A: dev=189:1\n
A: devnum=2\n
A: devpath=1\n
L: driver=../../../../../bus/usb/drivers/usb
L: firmware_node=../../../../LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:2d/device:2e/device:2f
A: idProduct=0020\n
A: idVendor=8087\n
A: ltm_capable=no\n
A: maxchild=6\n
L: port=../1-0:1.0/usb1-port1
A: power/active_duration=776368\n
A: power/async=enabled\n
A: power/autosuspend=0\n
A: power/autosuspend_delay_ms=0\n
A: power/connected_duration=858060\n
A: power/control=auto\n
A: power/level=auto\n
A: power/runtime_active_kids=3\n
A: power/runtime_active_time=779955\n
A: power/runtime_enabled=enabled\n
A: power/runtime_status=active\n
A: power/runtime_suspended_time=77820\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: quirks=0x0\n
A: removable=fixed\n
A: rx_lanes=1\n
A: speed=480\n
A: tx_lanes=1\n
A: urbnum=2620\n
A: version= 2.00\n
P: /devices/pci0000:00/0000:00:1a.0/usb1
N: bus/usb/001/001=12010002090000406B1D020010050302010109021900010100E0000904000001090000000705810304000C
E: DEVNAME=/dev/bus/usb/001/001
E: DEVTYPE=usb_device
E: DRIVER=usb
E: PRODUCT=1d6b/2/510
E: TYPE=9/0/0
E: BUSNUM=001
E: DEVNUM=001
E: MAJOR=189
E: MINOR=0
E: SUBSYSTEM=usb
E: ID_VENDOR=Linux_5.10.0-8-amd64_ehci_hcd
E: ID_VENDOR_ENC=Linux\x205.10.0-8-amd64\x20ehci_hcd
E: ID_VENDOR_ID=1d6b
E: ID_MODEL=EHCI_Host_Controller
E: ID_MODEL_ENC=EHCI\x20Host\x20Controller
E: ID_MODEL_ID=0002
E: ID_REVISION=0510
E: ID_SERIAL=Linux_5.10.0-8-amd64_ehci_hcd_EHCI_Host_Controller_0000:00:1a.0
E: ID_SERIAL_SHORT=0000:00:1a.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:1a.0
E: ID_PATH_TAG=pci-0000_00_1a_0
E: ID_FOR_SEAT=usb-pci-0000_00_1a_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=00\n
A: bDeviceSubClass=00\n
A: bMaxPacketSize0=64\n
A: bMaxPower=0mA\n
A: bNumConfigurations=1\n
A: bNumInterfaces= 1\n
A: bcdDevice=0510\n
A: bmAttributes=e0\n
A: busnum=1\n
A: configuration=
H: descriptors=12010002090000406B1D020010050302010109021900010100E0000904000001090000000705810304000C
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:2d/device:2e
A: idProduct=0002\n
A: idVendor=1d6b\n
A: interface_authorized_default=1\n
A: ltm_capable=no\n
A: manufacturer=Linux 5.10.0-8-amd64 ehci_hcd\n
A: maxchild=3\n
A: power/active_duration=780512\n
A: power/async=enabled\n
A: power/autosuspend=0\n
A: power/autosuspend_delay_ms=0\n
A: power/connected_duration=858228\n
A: power/control=auto\n
A: power/level=auto\n
A: power/runtime_active_kids=1\n
A: power/runtime_active_time=780500\n
A: power/runtime_enabled=enabled\n
A: power/runtime_status=active\n
A: power/runtime_suspended_time=77697\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=EHCI Host Controller\n
A: quirks=0x0\n
A: removable=unknown\n
A: rx_lanes=1\n
A: serial=0000:00:1a.0\n
A: speed=480\n
A: tx_lanes=1\n
A: urbnum=1071\n
A: version= 2.00\n
P: /devices/pci0000:00/0000:00:1a.0
E: DRIVER=ehci-pci
E: PCI_CLASS=C0320
E: PCI_ID=8086:3B3C
E: PCI_SUBSYS_ID=17AA:2163
E: PCI_SLOT_NAME=0000:00:1a.0
E: MODALIAS=pci:v00008086d00003B3Csv000017AAsd00002163bc0Csc03i20
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=EHCI
E: ID_VENDOR_FROM_DATABASE=Intel Corporation
E: ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset USB2 Enhanced Host Controller
A: ari_enabled=0\n
A: broken_parity_status=0\n
A: class=0x0c0320\n
A: companion=
H: config=86803C3B060190020620030C00000000008072F2000000000000000000000000000000000000000000000000AA1763210000000050000000000000000B040000000000000000000000000000000000000158C2C9000000000A98A020000000002020A7070000000001000001000008C00000DF3F0000000000000000000000000000800011890C13A000000000000000000000000000000013000603000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000AAFF00000000000000000000000000000000000000000004F340BB0000000088858000870F060828171B30
A: consistent_dma_mask_bits=32\n
A: d3cold_allowed=1\n
A: device=0x3b3c\n
A: dma_mask_bits=32\n
L: driver=../../../bus/pci/drivers/ehci-pci
A: driver_override=(null)\n
A: enable=1\n
L: firmware_node=../../LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:2d
A: irq=23\n
A: local_cpulist=0-3\n
A: local_cpus=f\n
A: modalias=pci:v00008086d00003B3Csv000017AAsd00002163bc0Csc03i20\n
A: msi_bus=1\n
A: numa_node=-1\n
A: pools=poolinfo - 0.1\nehci_sitd 0 0 96 0\nehci_itd 0 0 192 0\nehci_qh 9 42 96 1\nehci_qtd 13 42 96 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\n
A: power/async=enabled\n
A: power/control=on\n
A: power/runtime_active_kids=1\n
A: power/runtime_active_time=859876\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: resource=0x00000000f2728000 0x00000000f27283ff 0x0000000000040200\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=0x06\n
A: subsystem_device=0x2163\n
A: subsystem_vendor=0x17aa\n
A: uframe_periodic_max=100\n
A: vendor=0x8086\n

View File

@@ -22,14 +22,6 @@ except Exception as e:
FPrint = None
# Re-run the test with the passed wrapper if set
wrapper = os.getenv('LIBFPRINT_TEST_WRAPPER')
if wrapper:
wrap_cmd = wrapper.split(' ') + [sys.executable, os.path.abspath(__file__)] + \
sys.argv[1:]
os.unsetenv('LIBFPRINT_TEST_WRAPPER')
sys.exit(subprocess.check_call(wrap_cmd))
ctx = GLib.main_context_default()
@@ -123,7 +115,8 @@ class VirtualDeviceBase(unittest.TestCase):
def send_command(self, command, *args):
self.assertIn(command, ['INSERT', 'REMOVE', 'SCAN', 'ERROR', 'RETRY',
'FINGER', 'UNPLUG', 'SLEEP', 'SET_ENROLL_STAGES', 'SET_SCAN_TYPE',
'SET_CANCELLATION_ENABLED', 'SET_KEEP_ALIVE', 'IGNORED_COMMAND'])
'SET_CANCELLATION_ENABLED', 'SET_KEEP_ALIVE', 'IGNORED_COMMAND',
'CONT'])
with Connection(self.sockaddr) as con:
params = ' '.join(str(p) for p in args)
@@ -352,6 +345,16 @@ class VirtualDevice(VirtualDeviceBase):
self.assertEqual(self.dev.props.nr_enroll_stages, self.dev.get_nr_enroll_stages())
self.assertEqual(self.dev.props.open, self.dev.is_open())
def test_device_features(self):
self.assertFalse(self.dev.has_feature(FPrint.DeviceFeature.CAPTURE))
self.assertFalse(self.dev.has_feature(FPrint.DeviceFeature.IDENTIFY))
self.assertTrue(self.dev.has_feature(FPrint.DeviceFeature.VERIFY))
self.assertFalse(self.dev.has_feature(FPrint.DeviceFeature.DUPLICATES_CHECK))
self.assertFalse(self.dev.has_feature(FPrint.DeviceFeature.STORAGE))
self.assertFalse(self.dev.has_feature(FPrint.DeviceFeature.STORAGE_LIST))
self.assertFalse(self.dev.has_feature(FPrint.DeviceFeature.STORAGE_DELETE))
self.assertFalse(self.dev.has_feature(FPrint.DeviceFeature.STORAGE_CLEAR))
def test_open_error(self):
self._close_on_teardown = False
self.send_command('IGNORED_COMMAND') # This will be consumed by close
@@ -1004,8 +1007,8 @@ class VirtualDeviceStorage(VirtualDevice):
def cleanup_device_storage(self):
if self.dev.is_open() and not self.dev.props.removed:
for print in self.dev.list_prints_sync():
self.assertTrue(self.dev.delete_print_sync(print, None))
self.send_command('CONT')
self.dev.clear_storage_sync()
def test_device_properties(self):
self.assertEqual(self.dev.get_driver(), 'virtual_device_storage')
@@ -1019,6 +1022,16 @@ class VirtualDeviceStorage(VirtualDevice):
self.assertFalse(self.dev.supports_capture())
self.assertTrue(self.dev.has_storage())
def test_device_features(self):
self.assertFalse(self.dev.has_feature(FPrint.DeviceFeature.CAPTURE))
self.assertTrue(self.dev.has_feature(FPrint.DeviceFeature.IDENTIFY))
self.assertTrue(self.dev.has_feature(FPrint.DeviceFeature.VERIFY))
self.assertTrue(self.dev.has_feature(FPrint.DeviceFeature.DUPLICATES_CHECK))
self.assertTrue(self.dev.has_feature(FPrint.DeviceFeature.STORAGE))
self.assertTrue(self.dev.has_feature(FPrint.DeviceFeature.STORAGE_LIST))
self.assertTrue(self.dev.has_feature(FPrint.DeviceFeature.STORAGE_DELETE))
self.assertTrue(self.dev.has_feature(FPrint.DeviceFeature.STORAGE_CLEAR))
def test_duplicate_enroll(self):
self.enroll_print('testprint', FPrint.Finger.LEFT_LITTLE)
with self.assertRaises(GLib.Error) as error:
@@ -1094,6 +1107,27 @@ class VirtualDeviceStorage(VirtualDevice):
self.assertTrue(error.exception.matches(FPrint.DeviceError.quark(),
FPrint.DeviceError.DATA_NOT_FOUND))
def test_clear_storage(self):
self.send_command('INSERT', 'p1')
l = self.dev.list_prints_sync()
print(l[0])
self.assertEqual(len(l), 1)
self.send_command('CONT')
self.dev.clear_storage_sync()
self.assertFalse(self.dev.list_prints_sync())
def test_clear_storage_error(self):
self.send_command('INSERT', 'p1')
l = self.dev.list_prints_sync()
print(l[0])
self.assertEqual(len(l), 1)
self.send_error(FPrint.DeviceError.PROTO)
with self.assertRaises(GLib.Error) as error:
self.dev.clear_storage_sync()
self.assertTrue(error.exception.matches(FPrint.DeviceError.quark(),
FPrint.DeviceError.PROTO))
def test_identify_match(self):
rt = self.enroll_print('right-thumb', FPrint.Finger.RIGHT_THUMB)
lt = self.enroll_print('left-thumb', FPrint.Finger.LEFT_THUMB)

View File

@@ -21,14 +21,6 @@ except Exception as e:
FPrint = None
# Re-run the test with the passed wrapper if set
wrapper = os.getenv('LIBFPRINT_TEST_WRAPPER')
if wrapper:
wrap_cmd = wrapper.split(' ') + [sys.executable, os.path.abspath(__file__)] + \
sys.argv[1:]
os.unsetenv('LIBFPRINT_TEST_WRAPPER')
sys.exit(subprocess.check_call(wrap_cmd))
def load_image(img):
png = cairo.ImageSurface.create_from_png(img)
@@ -140,6 +132,20 @@ class VirtualImage(unittest.TestCase):
while iterate and ctx.pending():
ctx.iteration(False)
def test_features(self):
self.assertTrue(self.dev.has_feature(FPrint.DeviceFeature.CAPTURE))
self.assertTrue(self.dev.has_feature(FPrint.DeviceFeature.IDENTIFY))
self.assertTrue(self.dev.has_feature(FPrint.DeviceFeature.VERIFY))
self.assertFalse(self.dev.has_feature(FPrint.DeviceFeature.DUPLICATES_CHECK))
self.assertFalse(self.dev.has_feature(FPrint.DeviceFeature.STORAGE))
self.assertFalse(self.dev.has_feature(FPrint.DeviceFeature.STORAGE_LIST))
self.assertFalse(self.dev.has_feature(FPrint.DeviceFeature.STORAGE_DELETE))
self.assertFalse(self.dev.has_feature(FPrint.DeviceFeature.STORAGE_CLEAR))
self.assertEqual(self.dev.get_features(),
FPrint.DeviceFeature.CAPTURE |
FPrint.DeviceFeature.IDENTIFY |
FPrint.DeviceFeature.VERIFY)
def test_capture_prevents_close(self):
cancel = Gio.Cancellable()
def cancelled_cb(dev, res, obj):