Compare commits

...

310 Commits

Author SHA1 Message Date
Himura Kazuto
b97914a454 Merge branch 'master' into 'master'
egismoc: Support ETU905A88-E device (1c7a:0584)

See merge request libfprint/libfprint!549
2025-10-29 07:31:54 +00:00
Himura Kazuto
7517793367 egismoc: support ETU905A88-E device (1c7a:0584) 2025-10-29 11:31:05 +04:00
Danny
596b5f8032 fpcmoc: add 10a5:a306 fingerprint reader 2025-08-08 21:30:32 +02:00
Aris Lin
7f5304d6ee synaptics: add new PID 0x019F, 0x109 and 0x10A 2025-07-31 23:56:39 +00:00
Aris Lin
bde868f05e synaptics: add usb reset in probe to recover stall condition 2025-07-31 23:56:39 +00:00
Marco Trevisan (Treviño)
a7448fbb4a ci: Only run pages step on push events 2025-08-01 01:47:17 +02:00
Marco Trevisan (Treviño)
f84ab3d104 gcovr: Add gcovr project configuration
And mark suspicious hits as warnings instead of failures
2025-08-01 01:42:01 +02:00
Benjamin Berg
da42268911 goodixmoc: fix crash in exit callback handler
If the button shield command cannot be executed due to an underlying
error then resp is NULL. Avoid the crash by adding the appropriate
check.

Closes: #694
2025-07-24 08:39:54 +02:00
Benjamin Berg
d83a785260 ci: permit coverage failures for now
gcovr seems to fail for unclear reasons. Permit failures to not block
merge requests.
2025-07-23 19:09:54 +02:00
Jordan Petridis
2b100a912b ci: Pin the version of the Flatpak template
In [1] the template broke due to the inclusion of
a sub-include which doesn't resolve across different
gitlab instances without the same group setup.

Pin the template for now to the previous working commit

[1] https://gitlab.gnome.org/GNOME/citemplates/-/merge_requests/104#note_2501085
2025-07-23 19:09:04 +02:00
Marco Trevisan (Treviño)
dc8b05f0a3 Release 1.94.9 2025-02-20 18:41:27 +01:00
Marco Trevisan (Treviño)
c37da8568f build: Use fs to get files basename
We can safely bump meson
2025-02-20 18:41:27 +01:00
Marco Trevisan (Treviño)
e401fc10e8 build: Do not use deprecated features in meson 2025-02-20 18:28:15 +01:00
Marco Trevisan (Treviño)
db48d1a4e4 build: Adapt meson version to requirements 2025-02-20 18:28:15 +01:00
Marco Trevisan (Treviño)
d1504a30b7 fp-device: Clarify docs about FP_DEVICE_RETRY_TOO_FAST
This is an error that is valid also for touch devices, so let's make it
more generic in description
2025-02-20 17:20:03 +01:00
Marco Trevisan (Treviño)
7208b29756 tests: Ignore testing external tools with valgrind 2025-02-20 15:50:46 +00:00
Marco Trevisan (Treviño)
e9dbfbec39 ci: Install appstream for testing metainfo 2025-02-20 15:50:46 +00:00
Marco Trevisan (Treviño)
c6ca915067 tests: Validate the generated metainfo if appstreamcli is available 2025-02-20 15:50:46 +00:00
Marco Trevisan (Treviño)
385bc5e384 libfprint/fprint-list-metainfo: Generate AppStream metainfo
UI tools can use this information to see what package provides support
for specific devices, so let's provide the data since we have it.
2025-02-20 15:50:46 +00:00
Marco Trevisan (Treviño)
ee73d67765 scripts/uncrustify: Use 2-spaces indentation for defines too 2025-02-20 15:50:46 +00:00
Marco Trevisan (Treviño)
4dd51f38c7 examples/clear-storage: Remove local storage for devices without storage 2025-02-20 16:37:11 +01:00
Marco Trevisan (Treviño)
5b300edbe5 examples/storage: Clear storage per device
We used to clear the whole storage file, but this has to be done
per-device, not globally
2025-02-20 16:35:58 +01:00
Marco Trevisan (Treviño)
817281f6fd examples/clear-storage: Cleanup code and use better error handling 2025-02-20 16:35:58 +01:00
Abhinav Baid
aa18595ec7 Add clear-storage example 2025-02-20 16:35:58 +01:00
Marco Trevisan (Treviño)
fa5828f8c0 fp-device: Fix introspection warnings in handling closure tag
It has to be defined in the callback, not on the data.
2025-02-20 14:34:13 +01:00
Marco Trevisan (Treviño)
fc3effd73b goodixmoc/proto: Use a byte-reader to parse the finger ID 2025-02-13 23:51:52 +00:00
Marco Trevisan (Treviño)
63b5908f38 goodix: Read the header using byte reader 2025-02-13 23:51:52 +00:00
Marco Trevisan (Treviño)
7b97bed91f ci: Add job testing libfprint using address and undefined sanitizers 2025-02-13 23:51:52 +00:00
Marco Trevisan (Treviño)
41949db6ce uru4000: Fix shifting using unsigned types
../libfprint/drivers/uru4000.c:743:35: runtime error: left shift of 138 by 24
places cannot be represented in type 'int'
    #0 0x7fa3e696e06d in imaging_run_state ../libfprint/drivers/uru4000.c:743
    #1 0x7fa3e6a366f6 in __ssm_call_handler ../libfprint/fpi-ssm.c:254
    #2 0x7fa3e6a38cc8 in fpi_ssm_next_state ../libfprint/fpi-ssm.c:465
    #3 0x7fa3e696bd07 in sm_read_reg_cb ../libfprint/drivers/uru4000.c:515
    #4 0x7fa3e6a3db74 in transfer_finish_cb ../libfprint/fpi-usb-transfer.c:352
    #5 0x7fa3ed9b9862 in g_task_return_now ../../glib/gio/gtask.c:1363
    #6 0x7fa3ed9b989c in complete_in_idle_cb ../../glib/gio/gtask.c:1377
    #7 0x7fa3ede4a70b in g_main_dispatch ../../glib/glib/gmain.c:3373
    #8 0x7fa3ede4c8de in g_main_context_dispatch_unlocked ../../glib/glib/gmain.c:4224
    #9 0x7fa3ede4c8de in g_main_context_iterate_unlocked ../../glib/glib/gmain.c:4289
    #10 0x7fa3ede4cfef in g_main_context_iteration ../../glib/glib/gmain.c:4354
    #11 0x7fa3e68d4a1b in fp_device_capture_sync ../libfprint/fp-device.c:2048
2025-02-13 23:51:52 +00:00
Marco Trevisan (Treviño)
d8e0791554 goodixmoc/proto: Use FpiByteReader to parse the body
We had some read issues, so let's just use the safer reader that
makes things cleaner too

../libfprint/drivers/goodixmoc/goodix_proto.c:418:42: runtime error:
load of misaligned address 0x0000115ced29 for type 'uint16_t', which
requires 2 byte alignment
0x0000115ced29: note: pointer points here
 00 c0 3f  00 21 64 1c 00 00 00 00  64 00 43 01 01 00 00 00  00 00 00 00 00 00 00 00  00 00 00 00 00
              ^
    #0 0x7f974ff9e868 in gx_proto_parse_body ../libfprint/drivers/goodixmoc/goodix_proto.c:418
    #1 0x7f974ff8ec79 in fp_cmd_receive_cb ../libfprint/drivers/goodixmoc/goodix.c:185
    #2 0x7f975003ca0c in transfer_finish_cb ../libfprint/fpi-usb-transfer.c:352
    #3 0x7f9756e57862 in g_task_return_now ../../glib/gio/gtask.c:1363
    #4 0x7f9756e5789c in complete_in_idle_cb ../../glib/gio/gtask.c:1377
    #5 0x7f97577f070b in g_main_dispatch ../../glib/glib/gmain.c:3373
    #6 0x7f97577f28de in g_main_context_dispatch_unlocked ../../glib/glib/gmain.c:4224
    #7 0x7f97577f28de in g_main_context_iterate_unlocked ../../glib/glib/gmain.c:4289
    #8 0x7f97577f2fef in g_main_context_iteration ../../glib/glib/gmain.c:4354
    #9 0x7f974fed4656 in fp_device_verify_sync ../libfprint/fp-device.c:1976
2025-02-13 23:51:52 +00:00
Marco Trevisan (Treviño)
c7059dc61c goodixmoc: Use FpiByteReader to safely read the device CRC
This is was leading to a potential error due to misaligned memory:

../libfprint/drivers/goodixmoc/goodix.c:167:20: runtime error: load of
misaligned address 0x00001165c989 for type 'uint32_t', which requires 4 byte
alignment
0x00001165c989: note: pointer points here
 00 00 00  00 0a ac b3 09 00 00 00  00 00 00 55 53 42 00 00  00 00 00 56 42 53 00 00  00 00 00 30 30
              ^
    #0 0x7ff3ba98d190 in fp_cmd_receive_cb ../libfprint/drivers/goodixmoc/goodix.c:167
    #1 0x7ff3baa3b235 in transfer_finish_cb ../libfprint/fpi-usb-transfer.c:352
    #2 0x7ff3c18ca862 in g_task_return_now ../../glib/gio/gtask.c:1363
    #3 0x7ff3c18ca89c in complete_in_idle_cb ../../glib/gio/gtask.c:1377
    #4 0x7ff3c228470b in g_main_dispatch ../../glib/glib/gmain.c:3373
    #5 0x7ff3c22868de in g_main_context_dispatch_unlocked ../../glib/glib/gmain.c:4224
    #6 0x7ff3c22868de in g_main_context_iterate_unlocked ../../glib/glib/gmain.c:4289
    #7 0x7ff3c2286fef in g_main_context_iteration ../../glib/glib/gmain.c:4354
    #8 0x7ff3ba8d2fe5 in fp_device_open_sync ../libfprint/fp-device.c:1874
2025-02-13 23:51:52 +00:00
Marco Trevisan (Treviño)
0c315b4f0a tests/goodixmoc: Add explicit test on print description
So that we can ensure that what we get from device matches
2025-02-13 23:51:52 +00:00
Marco Trevisan (Treviño)
b04553cac9 goodix-proto: Do not memcpy NULL values
../libfprint/drivers/goodixmoc/goodix_proto.c:214:5: runtime error: null pointer passed as argument 2, which is declared to never be null
    #0 0x7f378839c3e5 in gx_proto_build_package ../libfprint/drivers/goodixmoc/goodix_proto.c:214
    #1 0x7f378838fd9e in alloc_cmd_transfer ../libfprint/drivers/goodixmoc/goodix.c:309
    #2 0x7f378838ffe4 in goodix_sensor_cmd ../libfprint/drivers/goodixmoc/goodix.c:336
    #3 0x7f378839a778 in gx_fp_template_delete_all ../libfprint/drivers/goodixmoc/goodix.c:1602
    #4 0x7f37882d3d59 in fp_device_clear_storage ../libfprint/fp-device.c:1820
    #5 0x7f37882d50af in fp_device_clear_storage_sync ../libfprint/fp-device.c:2132
2025-02-13 23:51:52 +00:00
Marco Trevisan (Treviño)
c1dcaa805d goodixmoc: Fix potential invalid shift on integer type
../libfprint/drivers/goodixmoc/goodix_proto.c:111:26: runtime error: left shift of 1 by 31 places cannot be represented in type 'int'
    #0 0x7f6776799c2e in reflect ../libfprint/drivers/goodixmoc/goodix_proto.c:111
    #1 0x7f677679a0f3 in crc32_final ../libfprint/drivers/goodixmoc/goodix_proto.c:147
    #2 0x7f677679a3ee in gx_proto_crc32_calc ../libfprint/drivers/goodixmoc/goodix_proto.c:164
    #3 0x7f677679d7aa in gx_proto_init_sensor_config ../libfprint/drivers/goodixmoc/goodix_proto.c:464
    #4 0x7f6776797b40 in gx_fp_init ../libfprint/drivers/goodixmoc/goodix.c:1415
    #5 0x7f67766cc56e in fp_device_open ../libfprint/fp-device.c:866
    #6 0x7f67766d2fd4 in fp_device_open_sync ../libfprint/fp-device.c:1872
2025-02-13 23:51:52 +00:00
Marco Trevisan (Treviño)
7b2895271d synaptics: Do not call memcpy with NULL data
../libfprint/drivers/synaptics/bmkt_message.c:260:5: runtime error: null pointer passed as argument 2, which is declared to never be null
    #0 0x7fd21f154592 in bmkt_compose_message ../libfprint/drivers/synaptics/bmkt_message.c:260
    #1 0x7fd21f14596c in synaptics_sensor_cmd ../libfprint/drivers/synaptics/synaptics.c:417
    #2 0x7fd21f14d93f in dev_probe ../libfprint/drivers/synaptics/synaptics.c:1329
    #3 0x7fd21f0ca61d in device_idle_probe_cb ../libfprint/fp-device.c:375
    #4 0x7fd21f21a431 in timeout_dispatch ../libfprint/fpi-device.c:336
    #5 0x7fd2269cf70b in g_main_dispatch ../../glib/glib/gmain.c:3373
    #6 0x7fd2269d18de in g_main_context_dispatch_unlocked ../../glib/glib/gmain.c:4224
    #7 0x7fd2269d18de in g_main_context_iterate_unlocked ../../glib/glib/gmain.c:4289
    #8 0x7fd2269d1fef in g_main_context_iteration ../../glib/glib/gmain.c:4354
    #9 0x7fd21f0c5a85 in fp_context_enumerate ../libfprint/fp-context.c:575
2025-02-13 23:51:52 +00:00
Marco Trevisan (Treviño)
3e653fe85b build/tests: Increase timeout multiplier in valgrind
CI is quite slow these days, so let's give valgrind more time
2025-02-13 23:51:52 +00:00
Marco Trevisan (Treviño)
830a9977c0 build: Support running tests with memory sanitizers
When memory sanitizers are set, tests may fail because we are indirectly
LD_PRELOAD'ing (through umockdev). While we could ensure that sanitizer
libraries are loaded first, it's just something we don't care because we
don't want to test the launcher wrappers themselves.

So, let's just ignore the link order and live with it
2025-02-13 23:51:52 +00:00
Marco Trevisan (Treviño)
6b914a2070 data: Update unsupported devices list 2025-02-14 00:40:16 +01:00
Marco Trevisan (Treviño)
22e6670aa0 elanspi: Add elanspi PID 0x2766
Patch by Z. A.

Closes: #571
2025-02-14 00:29:17 +01:00
Marco Trevisan (Treviño)
6723b74f86 elanspi: Add elanspi PID 0x3128
Patch by Alexey Vishnyakov

Closes: #650
2025-02-13 23:22:46 +01:00
Marco Trevisan (Treviño)
7d9638bc43 goodix: Add support for PID 0x60C2
Patch by Sergey Kokorin

Closes: #646
2025-02-13 22:01:02 +00:00
huan_huang
559c18785b realtek: modify the way to store userid in enroll flow
Signed-off-by: huan_huang <huan_huang@realsil.com.cn>
2025-02-13 20:40:49 +00:00
MrNerdHair
9e8dda5f17 upekts: fix typo 2025-02-13 19:20:10 +00:00
MrNerdHair
f906afb757 upekts: handle more retryable verify errors 2025-02-13 19:20:10 +00:00
MrNerdHair
1c4ed2e225 fp-device: add FP_DEVICE_RETRY_TOO_FAST error code 2025-02-13 19:20:10 +00:00
MrNerdHair
cdc22b4553 upekts: fix verify 2025-02-13 19:20:10 +00:00
Marco Trevisan (Treviño)
57c535d0cb libfprint.supp: Ignore libusb context init potential leak 2025-02-13 18:52:24 +00:00
Marco Trevisan (Treviño)
a94a55b8df ci: Use distro-provided umockdev
It's new enough nowadays
2025-02-13 18:52:24 +00:00
Marco Trevisan (Treviño)
133eaab061 uru4000: Use OpenSSL to perform AES-ECB encryption
Drop usage of NSS library now that openssl >= 3.0 has not anymore any
license incompatibility.

OpenSSL will provide us a better ground for further developments and
it's also the preferred crypto library by most distros these days
2025-02-13 18:52:24 +00:00
Dadoum
7a60912b61 Empty commit to hopefully fix the pipeline. 2025-02-13 18:52:24 +00:00
Marco Trevisan (Treviño)
6702c32b2b tests/meson: Ignore debug messages when generating hwdb 2025-02-13 19:31:16 +01:00
Marco Trevisan (Treviño)
b8ed4b5d63 tests/virtual-image: Use sleep multiplier when running under valgrind 2025-02-13 18:46:15 +01:00
Marco Trevisan (Treviño)
8433563602 tests: Do not enable virtual device hot seconds under valgrind
Valgrind tests may be slow, leading the devices to be considered hot.

We don't disable this for other tests, since we may still want to be
sure that the logic is fine for normal usage
2025-02-13 18:46:15 +01:00
Marco Trevisan (Treviño)
026c09d0b4 virtual-{image, device}: Make hot seconds value to be configurable 2025-02-13 18:46:15 +01:00
Marco Trevisan (Treviño)
3abdda4391 tests/virtual-image: Do not send images or retries if driver is not waiting finger 2025-02-13 03:36:52 +01:00
Marco Trevisan (Treviño)
981f8e0a42 virtual-image: Only receive image when waiting for finger
We may send an image when not waiting it, leading to a failure:

libfprint-image_device-DEBUG: 00:55:29.669: Image device internal state change
  from FPI_IMAGE_DEVICE_STATE_DEACTIVATING to FPI_IMAGE_DEVICE_STATE_INACTIVE
libfprint-image-DEBUG: 00:55:31.861: Minutiae scan completed in 2.204906 secs
libfprint-print-DEBUG: 00:55:56.902: score 1093/40
libfprint-device-DEBUG: 00:55:56.902: Device reported verify result
libfprint-device-DEBUG: 00:55:56.902: Device reported verify completion
libfprint-device-DEBUG: 00:55:56.903: Updated temperature model after 27.26
  seconds, ratio 0.69 -> 0.73, active 1 -> 1,
  FP_TEMPERATURE_WARM -> FP_TEMPERATURE_HOT
libfprint-device-DEBUG: 00:55:56.906: Completing action
  FPI_DEVICE_ACTION_VERIFY in idle!
libfprint-device-DEBUG: 00:55:56.906: Updated temperature model after 0.00
  seconds, ratio 0.73 -> 0.73, active 0 -> 0,
  FP_TEMPERATURE_HOT -> FP_TEMPERATURE_HOT
libfprint-device-DEBUG: 00:55:56.910: Updated temperature model after 0.00
  seconds, ratio 0.73 -> 0.73, active 1 -> 1,
  FP_TEMPERATURE_HOT -> FP_TEMPERATURE_HOT
libfprint-device-DEBUG: 00:55:56.910: Updated temperature model after 0.00
  seconds, ratio 0.73 -> 0.73, active 0 -> 0,
  FP_TEMPERATURE_HOT -> FP_TEMPERATURE_HOT
libfprint-virtual_image-DEBUG: 00:55:56.912: image data: 0xc8f6c10
libfprint-device-DEBUG: 00:55:56.916: Device reported finger status change:
  FP_FINGER_STATUS_PRESENT
libfprint-image_device-DEBUG: 00:55:56.917: Ignoring finger presence report as
  the device is not active!
libfprint-image_device-CRITICAL **: 00:55:56.918:
  fpi_image_device_image_captured: assertion
  'priv->state == FPI_IMAGE_DEVICE_STATE_CAPTURE' failed
2025-02-13 02:51:41 +01:00
Dadoum
f18e11b435 Empty commit to hopefully fix the pipeline. 2025-02-12 21:03:10 +00:00
Dadoum .
42d10118a3 Synaptics: add new PID 0x016C 2025-02-12 21:03:10 +00:00
Johnathon Clark
51d827fc74 Add support for the 10a5:c844 FPC fingerprint reader as found on
recent Lenovo Yoga i9 laptops.
2025-02-12 20:55:19 +00:00
wangyong
1859a1e5d1 add new pid: 0xa99a, 0xa57a, 0xa78a 2025-02-12 20:45:15 +00:00
Marco Trevisan (Treviño)
7292dd642c ci: Only run uncrustify check if source files have been changed 2025-02-12 20:36:46 +00:00
Marco Trevisan (Treviño)
8e22b2e22e ci: scan-build, ignore meson-built files
Like .gir introspection files that are generated are currently failing
2025-02-12 20:36:46 +00:00
Marco Trevisan (Treviño)
28b9ab7e37 tests: Ignore more python leaks 2025-02-12 20:36:46 +00:00
Marco Trevisan (Treviño)
9141014456 ci: Let's stick to fedora 41 for now
Rawhide seems to be a bit broken, so let's go with the stable version
2025-02-12 20:36:46 +00:00
Marco Trevisan (Treviño)
6f3ab36b2e ci: Enable running pipelines on schedules or to force rebuild 2025-02-12 20:36:46 +00:00
Marco Trevisan (Treviño)
d3035d5703 ci: Use rules to control when to run images build 2025-02-12 20:36:46 +00:00
Egor Ignatov
042365dbec elanmoc: Add new PID 0x0C98
Tested-on: Lenovo IdeaPad 5 2-in-1 16AHP9
Signed-off-by: Egor Ignatov <egori@altlinux.org>
2025-02-11 20:54:24 +00:00
Zihan Chen
0c7211329e synaptics: add new PID 0x0174
Found and tested on HP Omnibook Ultra Flip
2025-02-11 20:02:38 +00:00
herman lin
e1b6d8a461 elanmoc: Add new PID 0x0C9D and 0x0CA3 2025-02-10 13:49:05 +08:00
Aris Lin
09ec6e66e3 synaptics: Add new PID 0x0107 and 0x108, also fine tune PID sequence 2024-11-18 11:18:29 +08:00
SirCipherz
8ce356fccc Update autosuspend.hwdb 2024-09-05 11:05:02 +02:00
SirCipherz
98f5ad1f80 Add support for goodix 689a 2024-09-04 16:31:06 +02:00
Marco Trevisan (Treviño)
29f919b4eb build: Sum arrays instead of mixing them 2024-09-03 06:29:55 +02:00
Marco Trevisan (Treviño)
e57bab2f1e Release 1.94.8 2024-09-03 05:14:11 +02:00
huan_huang
a88582761f realtek: add support for rts5816
Signed-off-by: huan_huang <huan_huang@realsil.com.cn>
2024-09-03 04:44:04 +02:00
Marco Trevisan (Treviño)
75adfd37d1 egismoc: Add PID 0x0583
As per comment:
 - https://gitlab.freedesktop.org/libfprint/libfprint/-/issues/630#note_2547528
2024-08-30 04:42:56 +02:00
Tamer Hassan
990bd40cbf egismoc: add 0586 support 2024-08-30 04:42:56 +02:00
Tamer Hassan
c7e95bb41f egismoc: add 0587 support (also supports 0586 but missing device file) 2024-08-30 04:42:56 +02:00
Nkaspers
4611cc4a1b Synaptics: add new PID 0x00C4
And drop it from the unsupported list
2024-08-30 04:34:34 +02:00
Marco Trevisan (Treviño)
78c78432b9 build: Generalize spi drivers detection
Don't be limited to elan only
2024-08-30 04:16:48 +02:00
Daniel Schaefer
10e1cd76aa Don't build SPI driver on non-Linux
Doesn't build on other operating systems.
With auto-detection we don't have to manually select all other drivers.

Signed-off-by: Daniel Schaefer <dhs@frame.work>
2024-08-30 04:06:43 +02:00
Daniel Schaefer
c84d3774cf libfprint: Don't build SPI backend if not SPI driver
The SPI backend only builds on Linux, this makes it work non non-Linux platforms, such as FreeBSD.

Signed-off-by: Daniel Schaefer <dhs@frame.work>
2024-08-30 02:00:16 +00:00
Haowei Lo
04a167b09b fpcmoc: Add PID 0x9524 and 0x9544
Change-Id: Id85116df233308297cf3d7b56146582a79f5fcdd
2024-08-30 01:33:03 +00:00
Aris Lin
538a18cf17 synaptics: Add new PID 0x00C6 2024-08-30 00:57:29 +00:00
Aris Lin
2e766904f0 synaptics: Add new PID 0x019D 2024-08-30 00:57:29 +00:00
haoweilo
9f55ef690d fpcmoc: fixed the error jumping to wrong state at end of custom enroll 2024-08-30 00:47:01 +00:00
herman lin
b6061c0af8 elanmoc: Add new PID 0x0C9F 2024-08-08 14:08:19 +08:00
Marco Trevisan (Treviño)
3f70bde21c fp-device: Do not duplicate udev paths strings
This is happening already internally when using g_value_set_string
2024-06-17 19:08:16 +00:00
Timo Schrader
dd6f020378 goodixmoc: Add PID 0x609A 2024-06-17 17:57:29 +00:00
2a4c05662a goodixmoc: Add PID 0x6512 2024-06-15 12:17:34 -05:00
Marco Trevisan (Treviño)
eaec2339cc libfprint-fprint-list-udev-hwdb: Add new broadcom device IDs 2024-05-22 17:09:38 +02:00
Marco Trevisan (Treviño)
83035be830 README: Add contact information 2024-05-03 15:35:11 +02:00
Marco Trevisan (Treviño)
4709efc678 fpi-device: Clarify transfer of errors in device complete tasks 2024-04-17 17:00:47 +00:00
Marco Trevisan (Treviño)
37ded921fd fpi-device: Simplify logic of fpi_device_task_return_data_free
The clear functions will do NULL checks already, so there's no need to
duplicate such effort
2024-04-17 17:00:47 +00:00
Haowei Lo
b7f3544e98 fpcmoc: Transfer error from autoptr before fpi_device_close_complete
Fixed coredump because of trying to free a null space

Change-Id: If5a23ba7b4f307580593712612e150d1ab893826
2024-04-18 00:38:44 +08:00
steven.chen
093f2fc0a6 fpcmoc: Modify ctrl timeout to fix identify return failed 2024-04-17 15:05:06 +00:00
Lee Jiajun
c5def9a528 goodixmoc: Add PID 0x609A 2024-04-17 09:37:25 +00:00
haoweilo
e71f3de786 fpcmoc: add error handling to evt_finger_dwn
Redo the current task state
if we got failed status from evt_finger_dwn
2024-04-17 08:33:24 +00:00
haoweilo
420fd7416d fpcmoc: fix incorrect immobile handling during enrollment
For the custom enrollment,
if the number of immobile touches have reached the maximum,
we should treat this touch as normal (valid) and increase
the enrollment progress.
2024-04-17 08:33:24 +00:00
Haowei Lo
f505158c04 fpcmoc: clean cmd_ssm before callback
fixed assertion of "cmd_ssm is not null"

Change-Id: I8f914468dc0e40c6cac33d680411a2d957cf2296
2024-04-16 21:46:19 +08:00
Jichi Zhang
fb13722629 goodixmoc: Add PID 0x650C 2024-03-13 05:16:16 -07:00
Marco Trevisan (Treviño)
666cd0c08d egismoc: Use FpiByteReader to compute the check bytes
We can read the values in the proper format without having to
deal with endianness ourself, so let's do this instead of manual
labor.
2024-02-20 18:07:18 +01:00
Marco Trevisan (Treviño)
e055781006 egismoc: Use FpiByteWriter to allocate the commit payload 2024-02-20 17:57:46 +01:00
Marco Trevisan (Treviño)
48c8c539c7 egismoc: Use FpiByteWriter to generate the get check command 2024-02-20 17:57:46 +01:00
Marco Trevisan (Treviño)
40c7599fb1 egismoc: Compute the delete command using FpiByteWriter 2024-02-20 17:57:46 +01:00
Marco Trevisan (Treviño)
28c26c7d7e egismoc: Use FpiByteReader to read the enrolled IDs 2024-02-20 17:57:46 +01:00
Marco Trevisan (Treviño)
dd5a71695f egismoc: Use FpiByteWriter to prepare the command message 2024-02-20 17:57:46 +01:00
Marco Trevisan (Treviño)
977d324970 egismoc: Do not store twice the number of enrolled IDs
We already store it in the array, so let's just use that value
2024-02-20 17:57:46 +01:00
Marco Trevisan (Treviño)
4992110829 fpi-byte-writer: Zero-init the allocated data by default
This could have been done via fill method + pos reset, but it's just
something we normally want to do for safety, so let's do it all the
times.
2024-02-20 17:57:46 +01:00
Marco Trevisan (Treviño)
53f2539b6a fpi-byte-writer: Use nicer API to unset the parent data 2024-02-20 17:57:46 +01:00
Marco Trevisan (Treviño)
18e2906d62 fpi-byte-writer: Initialize the parent size when initializing with size 2024-02-20 17:57:46 +01:00
Marco Trevisan (Treviño)
19806546a2 fpi-byte-writer: Add change pos method
It allows to move the position of the cursor with a relative position.
2024-02-20 17:57:46 +01:00
Marco Trevisan (Treviño)
75559415fe fpi-byte-writer/reader: Add autopointers definitions 2024-02-20 17:57:46 +01:00
Marco Trevisan (Treviño)
7dbb21e77a build/tests: Skip a test if the test requires it during inspection
In case we don't have dependencies, we should skip the test, otherwise
we can just fail at test time
2024-02-20 08:25:53 +01:00
Marco Trevisan (Treviño)
4b72f27de6 build: Look for sh just once 2024-02-20 08:22:42 +01:00
Marco Trevisan (Treviño)
5ada931ede ci: Export coverage to pages
So that we can link it outside
2024-02-20 01:55:11 +01:00
Marco Trevisan (Treviño)
bebe8565cd Release 1.94.7 2024-02-20 01:09:54 +01:00
Marco Trevisan (Treviño)
5501dc7b47 build: Stop using deprecated dep.get_pkgconfig_variable() method
Use generic get_variable() instead
2024-02-20 01:02:00 +01:00
Marco Trevisan (Treviño)
3e5ab6fdad egismoc: Convert value check values to big endian only when needed
Since the driver seem to require a big-endian value it's just better
to use architecture native endianness to compute the check value and
eventually just convert to big endian as the chip wants.
2024-02-19 23:38:40 +01:00
Marco Trevisan (Treviño)
5462db9901 egismoc: Convert the check value to little endian
In this way we can support the big-endian architectures too.
2024-02-19 23:38:40 +01:00
Marco Trevisan (Treviño)
59dc585ccd egismoc: Simplify check bytes computation
We use big endian values for generating the check bytes, but we can do
the same logic in a simpler way.
2024-02-19 23:38:40 +01:00
Marco Trevisan (Treviño)
6768bd0ff4 egismoc: Use strictly sized types to hold check bytes contents
So we are sure about the size we're sending at compile time too.
2024-02-19 23:38:40 +01:00
Marco Trevisan (Treviño)
ed1815c3d9 build: Allow testing more drivers in both big and little endian
I've tested them in a s390x host and many more tests work fine, so let's
enable them.
2024-02-19 23:38:40 +01:00
Marco Trevisan (Treviño)
057c209beb build: Build-depend on glib 2.68
GLib 2.68 is now more than 3 years old, so we can definitely start
using it without thinking too much.

This allows us to drop lots of compat code that we had around.

And like the previous commit tells us, it will also help us to have
more correct code around.
2024-02-19 22:23:02 +01:00
Marco Trevisan (Treviño)
90c4afded4 cleanup: Use non-const pointers for non constant cases
We had various cases in which we were using const pointers for
non constant data, and in fact we were allocating and free'ing
them.

So let's handle all these case properly, so that we won't have
newer GLib complaining at us!
2024-02-19 22:14:14 +01:00
Marco Trevisan (Treviño)
f8f28a066b egismoc: Simplify fingerprint id and firmware reading
We can do copy and duplicate in oneshot since we are handling strings
after all.
2024-02-19 17:25:21 +01:00
Marco Trevisan (Treviño)
adc66edd8d egismoc: Implement suspension properly
In case of suspension we can't just cancel the operations but
also return when completed, and this may not happen immediately
if there are ongoing operations.

This is automagically handled by libfprint internals, but in order
to make it happen, we need to cancel the ongoing operations and then
mark it completed. libfprint will then wait for the task completion
before actually marking the device as suspended.
2024-02-19 17:21:58 +01:00
Marco Trevisan (Treviño)
9af211cc89 egismoc: Use device cancellable on transfers 2024-02-19 17:12:12 +01:00
Marco Trevisan (Treviño)
904bddd988 egismoc: Use g_new0 instead of g_malloc to make the type clearer 2024-02-19 17:12:12 +01:00
Marco Trevisan (Treviño)
8badfa84e9 egismoc: Assert that current transfer is unset when setting it
We need to ensure that we are not overwriting the instance transfer, so
that we can be sure that we are only doing one transfer at time.

Also we need to ensure that the ssm unsetting it, is the owner of it.
2024-02-19 17:12:12 +01:00
Marco Trevisan (Treviño)
b97efa6fed egismoc: Assert that task ssm is unset when setting it
We need to ensure that we are not overwriting the instance SSM, so that
we can be sure that we are only doing one operation at time.

Also we need to ensure that the task unsetting it, is the owner of it.
2024-02-19 17:12:12 +01:00
Joshua Grisham
591f9ad3cf egismoc: clear task pointers also after dev_init_done 2024-02-19 17:12:12 +01:00
Marco Trevisan (Treviño)
6767cd1a4f egismoc: Ensure that the command callback is after SSM is completed
We need to make sure that we won't trigger a callback when a SSM is
already in progress or we may end up overwriting it
2024-02-19 17:12:12 +01:00
Marco Trevisan (Treviño)
226b6abfab egismoc: Use an autopointer to cleanup error on command done callback 2024-02-19 17:12:12 +01:00
Marco Trevisan (Treviño)
9e2c14d64e egismoc: Clarify delete print ownership in delete callback 2024-02-19 17:12:12 +01:00
Marco Trevisan (Treviño)
92aeb53ee8 egismoc: Simplify egismoc identification stage handling 2024-02-19 17:12:12 +01:00
Marco Trevisan (Treviño)
87f68e3ac1 egismoc: Avoid gotos in init code, just handle the errors immediately 2024-02-19 17:12:12 +01:00
Marco Trevisan (Treviño)
8073a5dc34 egismoc: Remove unused increments
This is also to please static analyzer
2024-02-19 17:12:12 +01:00
Marco Trevisan (Treviño)
eb09156244 egismoc: Clear enrolled IDs using nicer GLib api 2024-02-19 17:12:12 +01:00
Marco Trevisan (Treviño)
b8cfb95b49 egismoc: Ensure we've enough null bytes at the end of strings 2024-02-19 17:12:12 +01:00
Marco Trevisan (Treviño)
a7843add0f egismoc: Do not initialize to zero twice 2024-02-19 17:12:12 +01:00
Marco Trevisan (Treviño)
b0f0322726 egismoc: Indentation and syntax fixes 2024-02-19 17:12:12 +01:00
Marco Trevisan (Treviño)
7476faba68 data, libfprint: Update list of unsupported drivers 2024-02-19 16:16:02 +01:00
Joshua Grisham
89ab54794e egismoc: added test and capture for 05a1 variant 2024-02-19 16:16:02 +01:00
Joshua Grisham
85da0e104b egismoc: add support for 1c7a:05a1 2024-02-19 16:16:02 +01:00
Joshua Grisham
47fe3668e4 egismoc: Return truncated text instead of null for description when using list 2024-02-19 16:16:02 +01:00
Joshua Grisham
7aae2181e2 egismoc: Add support for usernames longer than 8 chars 2024-02-19 16:16:02 +01:00
Joshua Grisham
a9269980eb egismoc: Fix crash during close 2024-02-19 16:16:02 +01:00
Joshua Grisham
0b9a64331f Initial commit of egismoc driver 2024-02-19 16:16:02 +01:00
Adam Jones
54ff730f0c Fix typo of libfprint in supported devices list
This also updates the title of the website page at https://fprint.freedesktop.org/supported-devices.html
2024-02-13 16:13:10 +00:00
Marco Trevisan (Treviño)
e05fbaa8ab realtek: Do not initialize variables in switch cases
Handles scan-build warning
2024-02-13 14:54:42 +00:00
Marco Trevisan (Treviño)
61f9346aaf realtek: Do not leak an error
Found by scan-build.
2024-02-13 14:54:42 +00:00
Marco Trevisan (Treviño)
d878148b5e ci: Expose scan build artifacts on failures
That's the only case we care about
2024-02-13 14:54:42 +00:00
Marco Trevisan (Treviño)
ee509c7ee6 libfprint/fprint-list-udev-hwdb: Update unsupported list from wiki 2024-02-13 15:28:53 +01:00
Marco Trevisan (Treviño)
2fa0975dec cleanup: Address some newer uncrustify syntax cleanups 2024-02-13 15:25:15 +01:00
Marco Trevisan (Treviño)
f3ab1f996f fp-context: use g_strv_contains instead of manual labor 2024-02-13 15:25:15 +01:00
Marco Trevisan (Treviño)
92c5fc4643 cleanup: Use allow/deny lists instead of color based ones
There was nothing racist on those names here (what? Do human races even
exist?!), but let's avoid any confusion.
2024-02-13 15:19:47 +01:00
Puspendu Banerjee
c64fa9c81b synaptics: Add new PID 0x0124 2024-02-13 14:45:47 +01:00
Marco Trevisan (Treviño)
85ec9ec5b2 ci: Allow flatpak failure
It's not a critical thing, so if it fails (as it does currently) we
should not block on that.
2024-02-13 14:42:18 +01:00
Marco Trevisan (Treviño)
b8933d8f81 fp-print: Do not check compile-time macros at runtime 2024-02-13 14:36:46 +01:00
xiaofei
631da4654f focaltechmoc:Support FocalTech moc devices
Supported UID: 0x2808
    Supported PIDs: 0x9E48, 0xD979, 0xa959
2024-02-13 14:34:12 +01:00
Mohammed Anas
1701d72ff9 tests: make mktemp command call work with Chimera Linux's mktemp
On Chimera Linux, which uses FreeBSD's userland tools, the original call
fails with the following error:

mktemp: mkstemp failed on /tmp/libfprint-XXXXXX.hwdb: Invalid argument

Moving the X's to the end of the template passed to `mktemp` fixes the
error, and also works with GNU's `mktemp`.
2024-01-22 15:52:46 +00:00
Mohammed Anas
d3ec9a80d3 tests: remove Bash dependency in favor of sh
The script works just fine with `sh`.

Also replace nonstandard `test` operator `==` with the standard `=`.

The other changes are mostly cosmetic.
2024-01-22 15:27:33 +00:00
Marco Trevisan (Treviño)
5a1253e37c fp-image: Do not start thread detection task thread if already running 2023-11-24 21:02:50 +01:00
Marco Trevisan (Treviño)
2b008b52d7 fp-image: Simplify minutiae detection tasks
We can just use a GTask to handle the detection while using the
finish function to process the results to the image, so that it
is more predictable when this happens and it does not depend on
a thread returning.

Also remove data duplication when possible, this class wasn't
fully safe anyway to be used concurrently, so there's no point
to copy data when not needed. Also added the hard constraint to
not proceed with minutiae detection if something else is already
doing this.

At the same time we can mark the task to finish early on
cancellation.
2023-11-21 16:43:04 +00:00
Marco Trevisan (Treviño)
83939abe10 fp-image: Add FP_IMAGE_NONE flags definition 2023-11-21 16:43:04 +00:00
Marco Trevisan (Treviño)
16d02b3ed5 fp-image: Remove unused ref_count flag
It's an object so we already ref-count it.
2023-11-21 16:43:04 +00:00
huan_huang
79be91831c drivers: add realtek rts5813 driver 2023-10-27 13:21:06 +00:00
Aris Lin
427139f347 synaptics: Add new PID 0x0106 2023-10-24 14:56:15 +08:00
Aris Lin
3ebd2c3f97 synaptics: Add new PID 0x0173 2023-10-19 14:25:09 +08:00
Marco Trevisan (Treviño)
2414dbdbd4 libfprint/fprint-list-udev-hwdb: Update unsupported devices from wiki 2023-09-27 19:44:37 +02:00
swbgdx
0eae0e8cc0 goodixmoc: Add PID 0x6582 2023-09-27 16:10:03 +00:00
Marco Trevisan (Treviño)
efba965b0c ci: Build flatpak using gnome master
Also bump dependencies versions
2023-09-27 17:47:38 +02:00
Marco Trevisan (Treviño)
26d2c77c3d ci: Allow manual flatpak build in any fork and MR 2023-09-27 17:29:24 +02:00
Marco Trevisan (Treviño)
eb01d7c97d ci: Fix building flatpak using GNOME 42 runtime
Use versioned ci template so we are sure what we're using
2023-09-27 17:10:31 +02:00
Vincent Huang
5bff5bfea6 synaptics: Add null check to prevent g_propagate_error assertion failure 2023-09-11 16:58:33 +08:00
Vincent Huang
206e92218c synaptics: fix enroll_identify problem after user reset database 2023-09-01 09:47:12 +00:00
Marco Trevisan (Treviño)
af3dca9003 tests/egis0570/capture.pcapng: Remove execution permission 2023-08-22 23:08:55 +00:00
Marco Trevisan (Treviño)
b924d715c9 ci: Move build dir during installed tests so we check that we don't use built artifacts 2023-08-21 14:19:27 +00:00
Marco Trevisan (Treviño)
1372d6f081 tests: Use native GTest utils to generate assets names 2023-08-21 14:19:27 +00:00
Marco Trevisan (Treviño)
135a015b6a Release 1.94.6 2023-08-17 05:08:04 +02:00
swbgdx
96645eaa7a goodixmoc: Add PID 0x633C and 0x6304 2023-08-17 01:37:56 +00:00
hermanlin
d37b255a11 elanmoc: add PID 0x0C99 2023-07-10 11:17:27 +08:00
Marco Trevisan (Treviño)
903ee43b2d ci: Do not force-rebuild if an image with such tag exists 2023-06-28 16:35:16 +02:00
Marco Trevisan (Treviño)
8562f8a964 ci: Use meson commands only to setup, compile and install
Old ones are semi-deprecated, so let's adjust to what upstream suggests
2023-06-28 16:35:16 +02:00
Marco Trevisan (Treviño)
5ff794c105 ci: Run installed tests 2023-06-28 16:35:16 +02:00
Marco Trevisan (Treviño)
f68e0972c2 ci: Auto-Retry jobs on infrastructure failures 2023-06-28 16:35:16 +02:00
Marco Trevisan (Treviño)
ba3cc04e84 tests: Add support for installed tests
They allow distrubtions to check whether libfprint continues working as
expected, in different contexts.
2023-06-28 16:35:16 +02:00
Marco Trevisan (Treviño)
3d4cf44f9b ci: Add gnome-desktop-testing to the image
It can be used to run the installed tests.
2023-06-28 16:23:45 +02:00
Marco Trevisan (Treviño)
8e702012fd ci: Use debuginfo-install to install debug symbols
dnf doesn't seem to handle the plugin well in rawhide:

  bash-5.2# dnf -y debuginfo-install glib2
    Unknown argument "debuginfo-install" for command "dnf5".
    Add "--help" for more information about the arguments.
2023-06-28 15:58:48 +02:00
Marco Trevisan (Treviño)
f49879b522 tests/virtual-image: Support passing specific FP_PRINTS_PATH env variable 2023-06-24 00:28:04 +02:00
Marco Trevisan (Treviño)
5e0bf2446b meson: Bump requirements to 0.56 and adapt deprecated functions 2023-06-24 00:28:04 +02:00
Marco Trevisan (Treviño)
4d96a3efaa tests/virtual-device: Check that removed devices are not in context anymore 2023-06-23 18:20:04 +02:00
Marco Trevisan (Treviño)
c27d72e3a1 tests/virtual-device: Do not preserve context on unplug tests
The unplug tests assume that the device is removed from the context once
they run, however we may have left the device around in a removed state
causing other tests to fail.

So isolate them in a new class where we create context and device
instances every time we run a test case.
2023-06-22 06:59:00 +02:00
Marco Trevisan (Treviño)
0819df6988 virtual-device: Reset transient parameters on deinit
Tests may change some options so we need to reset these values, even
though some may need not to be reserved when not in keep-alive mode.
2023-06-22 06:55:44 +02:00
Marco Trevisan (Treviño)
28579239a6 tests/virtual-device: Reset keep alive status when test is done
We don't want this to be preserved across tests, since it's meant to be
used inside a single test case.
2023-06-22 06:55:44 +02:00
Marco Trevisan (Treviño)
e48d2b467a tests/virtual-device: Restore default enroll steps on tearDown
When running the tests as a single script we may leave the device in an
inconsistent state, so reset the enroll steps when done.
2023-06-22 06:55:44 +02:00
Marco Trevisan (Treviño)
1c589336a2 meson: Remove duplicate gnome imports 2023-06-22 06:55:44 +02:00
Egor Ignatov
9546659c15 goodixmoc: add PID 0x60A4
Signed-off-by: Egor Ignatov <egori@altlinux.org>
2023-06-21 19:28:38 +03:00
haoweilo
c782298ae4 fpcmoc: Ensure the current SSM is never overwritten 2023-06-21 15:09:00 +00:00
Elytscha Smith
682fce6a5b goodixmoc: add PID 0x60BC 2023-03-28 15:59:48 +00:00
swbgdx
6ed1b707d5 goodixmoc: Add PID 0x6092 2023-03-15 15:45:56 +00:00
Marco Trevisan (Treviño)
9fd2ccff29 virtual-device-listener: Always return task even if we got zero bytes
See: https://gitlab.gnome.org/GNOME/glib/-/issues/1346
2023-03-15 15:26:37 +00:00
Marco Trevisan (Treviño)
b6223a9d0a test-fpi-device: Only push pragma -wdanging-pointer in newer GCC versions
It may not be supported and warn otherwise
2023-03-15 15:23:17 +00:00
Marco Trevisan (Treviño)
5e98f10011 ci: Do not require coverage to always happen
meson coverage could be broken in some cases, so let's ignore the error
for now if it happens.
2023-03-15 16:18:17 +01:00
Marco Trevisan (Treviño)
e7ca05e1bf ci: Use proper name for valgrind junit file 2023-03-15 16:18:17 +01:00
Marco Trevisan (Treviño)
677c50fc51 fprint-list-supported-devices: Do not double-free usb_list
We were leaking the spi_list instead.
2023-03-15 14:50:41 +01:00
Bastien Nocera
bb5feeca77 ci: Use detached pipelines
See https://gitlab.freedesktop.org/freedesktop/freedesktop/-/issues/438#what-it-means-for-me-a-maintainer-of-a-project-part-of-gitlabfreedesktoporg
2023-03-15 13:33:52 +01:00
wagner.oliveira
22683ec490 Fix AES4000 wrong IDs (swapped pid/vid) 2023-01-27 18:23:55 -05:00
Enrik Berkhan
0bf7d58c5e goodixmoc: cleanup enroll state machine
As suggested by @benzea, the following cleanup actions have been
performed:

  - let case order match enroll states enum

  - remove FP_ENROLL_IDENTIFY that is no longer used

  - finally use fpi_ssm_next_state instead of explicitly jumping to
    FP_ENROLL_CREATE

Additionally, all types/functions/variables referring to "enroll_init"
used for FP_ENROLL_CREATE have been renamed to match "enroll_create".
All other states use similar name matching.

Signed-off-by: Enrik Berkhan <Enrik.Berkhan@inka.de>
2023-01-19 20:30:05 +01:00
Enrik Berkhan
86566e8d0b goodixmoc: Fix missing "enroll create" state
After the driver internal duplicate check had been removed in
46669e9f53, all templates were saved with
an all-zeroes template ID.

By going through FP_ENROLL_CREATE before starting to capture, the
template ID returned from the device is taken into account again.

Signed-off-by: Enrik Berkhan <Enrik.Berkhan@inka.de>
2023-01-19 20:28:33 +01:00
Zoltán Böszörményi
7080a5ff8b Abort initialization if unknown sensor dimensions are reported
Signed-off-by: Zoltán Böszörményi <zboszor@gmail.com>
2023-01-17 19:50:21 +00:00
Zoltán Böszörményi
5e52ad2ad1 upektc_img: Add new unit test for the TCS1s chip variant 2023-01-17 19:50:21 +00:00
Zoltán Böszörményi
bfaa9a9241 upektc_img: Fix asynchronous problem in init_read_data_cb() 2023-01-17 19:50:21 +00:00
Zoltán Böszörményi
9c900789de upektc_img: Add asserts for expected height reported by the device 2023-01-17 19:50:21 +00:00
Zoltán Böszörményi
29a24ba67f upektc_img: Add finger status changes 2023-01-17 19:50:21 +00:00
Zoltán Böszörményi
987f23698e upektc_img: Deduce sensor type from the information packet 2023-01-17 19:50:21 +00:00
Toni
cda4e6136c upektc_img: Fix protocol for area sensors 2023-01-17 19:50:21 +00:00
Toni
522b481297 upektc_img: Add sensor chip detection
Move setting up sensor type and image dimensions to
activation time.
2023-01-17 19:50:21 +00:00
Toni
fafe70f985 upektc_img: Fix CRC for upek2020_init_capture. 2023-01-17 19:50:21 +00:00
Vasily Khoruzhick
62818b9407 fpcmoc: fix use-after free in multiple callbacks
Drop if statement that retrieves internal ssm->error.
"error" is already a copied ssm->error, so it makes no sense to return
internal copy which will be freed when ssm is marked as done.

Fixes #526
2023-01-10 11:22:22 -08:00
Vasily Khoruzhick
db2fa81358 tests: valgrind: update python and libfprint suppressions list 2023-01-10 11:15:17 -08:00
Vasily Khoruzhick
d492901c3e tests: valgrind: generate suppressions list for new tests-suppress-new-valgrind-errors-in-python
That will help with updating suppresions lists in future
2023-01-10 11:14:51 -08:00
Vasily Khoruzhick
a5d52eb853 Fix indentation issues with uncrustify-0.76.0
Apparently older version didn't find this indentation issues
2023-01-08 23:36:18 -08:00
Bastien Nocera
89509c76f4 build: Print the list of enabled drivers
This saves us from having to figure out which drivers were enabled
during a build in some other way.
2022-11-02 12:04:34 +01:00
Marco Trevisan (Treviño)
6395dda012 fp-image: Remove config.h inclusion in fpi-header
And also avoid defining a function we expose depending on it's presency.
2022-10-13 20:35:52 +00:00
Marco Trevisan (Treviño)
54bb0c12e6 fpi-image: Check for PIXMAN presency using #ifdef
That's a defined variable that may be there or not, and currently we
warn with:
 - fpi-image.c:29:5: warning: "HAVE_PIXMAN" is not defined, evaluates to 0
2022-10-13 20:35:52 +00:00
Marco Trevisan (Treviño)
1f1ed80dbf test-device-fake: Add more logging showing the current device action 2022-10-13 20:31:28 +00:00
Marco Trevisan (Treviño)
36bcb24b3a fp-device: Move FpDevice private functions to public library
This these functions are not really needed by anything else than
FpDevice, so move them back to the cpp file, so that we don't expose
them in the private library, given that we don't need them
2022-10-13 20:31:28 +00:00
Marco Trevisan (Treviño)
ddacf07e3b meson: Actually bump the version to 1.94.5 2022-10-13 20:31:28 +00:00
Marco Trevisan (Treviño)
86961a9429 Release 1.94.5 2022-10-13 05:57:04 +02:00
Marco Trevisan (Treviño)
3ca20a8e70 ci: Do not run two image rebuild pipelines on schedules 2022-10-13 05:37:12 +02:00
Marco Trevisan (Treviño)
3100404419 ci: Install more debug symbols 2022-10-13 05:27:44 +02:00
Marco Trevisan (Treviño)
892c9767a2 tests: Be stricter on valgrind leak checks
We used to ignore leaks, and we are ending up in having various of them,
so let's make valgrind to exit with error when using the valgrind test
setup (so in CI) to catch them better.
2022-10-13 05:20:28 +02:00
Marco Trevisan (Treviño)
2718dc02e0 vfs0050: Initialize the usb transfer buffer when allocating it
Ensure that the memory that we're going to populate via USB transfer is
initialized, otherwise valgrind may complain about (even if that's not
really an issue).
2022-10-13 05:04:03 +02:00
Marco Trevisan (Treviño)
abd7c66833 fp-device: Do not setup current action before updating temperature
At every action we update the device temperature, and this can
potentially lead to a failure, if the temperature is too hot.

However in such case we were failing a task that we had just stolen,
causing an error, tasks never returning and the device was left in an
undefined state.

So, just return early in case temperature is too hot, as we don't really
need to have the current task or action set at this point because
there's no active action to cancel yet.

This was causing random errors when running tests under valgrind
2022-10-13 05:04:03 +02:00
Marco Trevisan (Treviño)
8716ddb07a fp-print: Fix a typo in documentation 2022-10-13 05:04:03 +02:00
Marco Trevisan (Treviño)
fd7d93e619 fpi-device: Do not leak suspend/resume tasks
We kept suspend/resume GTask's around but at the moment of completing
them we didn't unref them, leading to leaks.
2022-10-13 05:04:02 +02:00
Marco Trevisan (Treviño)
0592c0e5ad uru4000: Cleanup cancelled error before early return 2022-10-13 05:04:02 +02:00
Marco Trevisan (Treviño)
684e3c460a uru4000: Shutdown NSS on device close
We were allocating NSS during device opening but never closing it,
causing many leaks.
2022-10-13 05:04:02 +02:00
Marco Trevisan (Treviño)
4278668c8f egis0570: Cleanup the received image that is going to be resized
It's just temporary for us as we're providing the resized one instead.
2022-10-13 05:04:02 +02:00
Marco Trevisan (Treviño)
a86ab6c854 test-fpi-device: Cleanup the device ID / driver before overriding it
Otherwise we'd leak the one that was initially set.
2022-10-13 05:04:02 +02:00
Marco Trevisan (Treviño)
b04eed0aea test-device-fake: Consume the identify print if we're returning with error 2022-10-13 05:04:02 +02:00
Marco Trevisan (Treviño)
669e091b03 virtual-device: Use an autoptr to handle the new scan print
We may not use this print, so let's use an autoptr to handle its life
cycle to clean it up when not used.
2022-10-13 05:04:02 +02:00
Marco Trevisan (Treviño)
0b6a92150c tests/fpcmoc: Ensure python tests exit with error on every exception
We ignored assertions happening on callbacks as they only raise
exceptions that does not stop the execution.

So ensure that this is happening in all the tests as synaptics was
doing already

Same as commit: be8888431
2022-10-13 04:26:58 +02:00
Haowei Lo
cca2b6a624 fpcmoc: Support FPC moc devices
Supported PID: 0xFFE0/A305/D805/DA04/D205
2022-10-11 08:11:38 +00:00
ElectronicsArchiver
1d24037f14 README: Improved formatting 2022-10-10 23:35:24 +02:00
Lv Ying
6395228bb8 goodixmoc: add PID 0x6014
Signed-off-by: Lv Ying <lvying.system.thoughts@gmail.com>
2022-10-09 10:45:18 +08:00
Marco Trevisan (Treviño)
b718f4d567 tests/meson: Avoid searching for programs multiple times 2022-09-28 01:23:58 +02:00
Marco Trevisan (Treviño)
be88884315 tests: Ensure python tests exit with error on every exception
We ignored assertions happening on callbacks as they only raise
exceptions that does not stop the execution.

So ensure that this is happening in all the tests as synaptics was
doing already
2022-09-28 01:22:15 +02:00
Marco Trevisan (Treviño)
d2a0eda56c synaptics, goodix: Properly check for finger status during enroll progress
It may contain other values, but for sure we finger must be neeeded
2022-09-28 01:21:31 +02:00
Marco Trevisan (Treviño)
5d9fc8b3c8 fpi-device: Do not leak USB devices while iterating
To compute the device ports we walked up through the devices using
g_usb_device_get_parent(), but this is supposed to return a device with
transfer full, so we need to unref it when done with it.

To handle this nicely, use a mixture of autopointer's and g_set_object
to ensure we're doing the right thing when passing the ownership around.
2022-09-27 18:21:20 +02:00
Marco Trevisan (Treviño)
62f2f34655 fpi-device: Fix a small leak when configuring the wakeup 2022-09-27 17:38:51 +02:00
Marco Trevisan (Treviño)
171e65f73f libfprint: Use g_memdup2 everywhere
It's just safer when available.
2022-09-27 17:10:33 +02:00
Marco Trevisan (Treviño)
446cedbcfc fpi-compat: Add definition for g_memdup2 when not available or deprecated
It's suggested to use g_memdup2 everywhere, but since we've a max-glib
version set we'd get a "deprecation" warning.

Avoid it this by re-defininig it through a macro in both cases.
2022-09-27 17:10:33 +02:00
Marco Trevisan (Treviño)
4012a4fe6f fpi-device: Clarify identify prints gallery usage in drivers docs 2022-09-27 16:43:33 +02:00
Marco Trevisan (Treviño)
70dc61d647 libfprint: Add top-level sync-udev-hwdb target for updating DB 2022-09-27 16:32:09 +02:00
Marco Trevisan (Treviño)
ca481cce50 fprint-list-udev-hwdb: Update devices from wiki 2022-09-27 16:32:09 +02:00
Marco Trevisan (Treviño)
4d74838c50 ci: Generate Cobertura XML and use it to feed gitlab for MR integration
gitlab has coverage integration in MRs, but we need a cobertura
formatted XML files (each must be less than 10 MB) to show it, since
meson generates it already via gcovr, we can just inform gitlab about it

See https://docs.gitlab.com/ee/ci/testing/test_coverage_visualization.html
2022-09-27 13:05:01 +02:00
Marco Trevisan (Treviño)
c429052e5e tests: Do not use deprecated declarations in virtual device tests 2022-09-27 12:52:38 +02:00
mbv06
1e55a066dc Update autosuspend.hwdb 2022-09-27 09:01:58 +00:00
mbv06
06abc256a4 upek: add PID 0x2017 2022-09-27 09:01:58 +00:00
Marco Trevisan (Treviño)
7ea2e55793 ci: Check for uncrustify changes in a safer way 2022-09-27 01:38:26 +02:00
Marco Trevisan (Treviño)
34e8655a08 ci: Use versioned image tags 2022-09-27 01:06:35 +02:00
Marco Trevisan (Treviño)
c512a47e8a ci: Install debuginfo packages for better valgrind debugging
Related-to: https://gitlab.freedesktop.org/libfprint/libfprint/-/issues/507
2022-09-27 00:21:05 +02:00
Marco Trevisan (Treviño)
012d77ac41 libfprint-templates: Include exec commands 2022-09-27 00:15:16 +02:00
Marco Trevisan (Treviño)
2acd3ca571 ci: Rebuild the image in case deps changed 2022-09-27 00:15:16 +02:00
Paulo E. Castro
c74a1ab6d1 goodixmoc: add PID 6094 2022-09-06 07:59:57 +00:00
hermanlin
beac7f934d elanmoc: Fixed unreachable code
ISSUE=503

Signed-off-by: hermanlin <herman.lin@emc.com.tw>
2022-08-26 18:44:22 +08:00
Bastien Nocera
114097718a build: Fix run_command() warning
WARNING: You should add the boolean check kwarg to the run_command call.
         It currently defaults to false,
         but it will default to true in future releases of meson.
         See also: https://github.com/mesonbuild/meson/issues/9300
2022-08-26 11:48:32 +02:00
mahaosen
151551b52b goodixmoc: add PID 0x634C 2022-08-26 16:46:16 +08:00
Aris Lin
89a0d5f958 synaptics: Add new PID 0x0104 2022-08-16 15:45:13 +00:00
mahaosen
3a82991586 goodixmoc: add PID 0x631C 2022-08-16 15:30:47 +00:00
Bastien Nocera
08a90e911e flatpak: Remove obsolete libfprint branch 2022-08-16 17:14:07 +02:00
Bastien Nocera
3176eb8821 flatpak: Remove obsolete option
See 256c7cea07
2022-08-16 17:14:07 +02:00
Bastien Nocera
f74b3f7794 flatpak: Update libusb module 2022-08-16 17:14:07 +02:00
Bastien Nocera
fc6403899e flatpak: Only require X11 access on X11 2022-08-16 17:14:07 +02:00
Bastien Nocera
b10baf02ea flatpak: Build Flatpak using GNOME 42
So the old meson in the 3.36 runtime doesn't choke on:
tests/meson.build:46:7: ERROR: Unknown method "project_source_root" in object.
2022-08-16 17:14:07 +02:00
Bastien Nocera
96013a03c5 test-generated-hwdb: Add missing test dep
E: UDEV_HWDB (/run/build/libfprint/_flatpak_build/libfprint/fprint-list-udev-hwdb) unset or not executable.
2022-08-16 17:14:07 +02:00
Bastien Nocera
3b3fc573da test-generated-hwdb: Add more debug on error 2022-08-16 17:14:07 +02:00
Bastien Nocera
e782de3747 tests: Fix umockdev version detection
Traceback (most recent call last):
  File "/builds/libfprint/libfprint/tests/umockdev-test.py", line 17, in <module>
    version = tuple(int(_) for _ in umockdev_version.split(b'.'))
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/builds/libfprint/libfprint/tests/umockdev-test.py", line 17, in <genexpr>
    version = tuple(int(_) for _ in umockdev_version.split(b'.'))
                    ^^^^^^
ValueError: invalid literal for int() with base 10: b'g9049374\n'
2022-08-16 17:14:07 +02:00
Bastien Nocera
c3e88f6e46 context: Fix race when shutting down context
Fix possible race which would happen when freeing the devices array
before cancelling the initialisation:
(/builds/libfprint/libfprint/_build/tests/test-fp-context:1449): GLib-CRITICAL **: 14:00:19.640: g_ptr_array_add: assertion 'rarray' failed
2022-08-16 17:14:07 +02:00
Bastien Nocera
ac3b0d07ba hwdb: Add FT9201Fingerprint reader
To the unsupported list.
2022-08-16 15:58:53 +02:00
Bastien Nocera
9ca1564e2d hwdb: Add Lenovo ThinkPad E15 fingerprint reader
To the unsupported list.
2022-08-16 15:58:53 +02:00
Johnny Li
fb63c39750 elanmoc: add PID 0x0c8c & 0x0c8d 2022-07-25 14:11:37 +08:00
Marcus Pfeffer
f007161bcd goodixmoc: add PID 0x6384
Closes: #489
2022-07-21 11:37:40 +02:00
yangdi
489332c07d goodixmoc: add PID 0x659A 2022-07-19 11:37:46 +08:00
Marco Trevisan (Treviño)
15bee898b8 ci: Use junit test reports
They can be used to show test failure logs directly in the MR's
pipelines page.
2022-07-14 22:13:49 +02:00
Marco Trevisan (Treviño)
fb9e054637 test-fp-device: Add few tests to check identification init errors 2022-07-14 21:35:30 +02:00
Marco Trevisan (Treviño)
7f6ab61292 fp-device: Return an error if prints are invalid
We'd crash later otherwise, while it's better to return an error.
2022-07-14 21:14:29 +02:00
Marco Trevisan (Treviño)
f03d9361e3 fpi-device: Improve documentation for identify/verify report and complete
We still mentioned variables that are not accepted anymore since we
switched to match reporting API.
2022-07-14 21:13:35 +02:00
hermanlin
24e7e1f100 elanmoc: Make sure sensor in the right mode at identity
Signed-off-by: hermanlin <herman.lin@emc.com.tw>
2022-07-11 15:39:11 +00:00
Sam James
61f0f86904 nbis: fix build on musl
Drop re-definition of stderr. There's no need for this anywhere
(including glibc). This breaks in particular on musl because
stderr (and stdin) are both const, and macros unlike in glibc.

Bug: https://bugs.gentoo.org/853811
2022-07-03 02:36:55 +01:00
Benjamin Berg
08da0eb1e1 goodix: Make fingerlist parse error non-fatal
Otherwise we cannot recover from the error by doing a device reset.
2022-06-22 15:40:12 +00:00
Benjamin Berg
8552290bec goodix: Reset device if storage listing fails
When opening the device, query the stored prints. This should usually
always succeed (and it should be fast). If it fails, then we are very
likely dealing with a corrupted template storage on the device. In that
case, emit the command to clear the storage in order to reset the device
and get it back into a usable state.
2022-06-22 15:40:12 +00:00
Benjamin Berg
42c9003f49 goodix: Lower poor capture warnings to debug message
It is completely fine for a capture to have a low quality or fail. No
need to warn about this. Main reason to remove it though is so that
recordings that contain such a message do not trigger a failure.
2022-06-22 15:40:12 +00:00
ArronYen
7899bf4240 elanmoc: add PID 0x0c88 2022-06-20 14:03:05 +08:00
Benjamin Berg
d1fbf34fdf scripts: Update uncrustify configuration
The mod_full_brace_if_chain option needs an integer (we want method 1)
rather than a boolean.
2022-06-09 15:36:10 +02:00
Benjamin Berg
9c12b762a7 print: Fix indentation 2022-06-09 15:36:10 +02:00
Benjamin Berg
f20b8bc311 Release 1.94.4 2022-05-24 14:53:52 +02:00
Benjamin Berg
8b8dc0fec2 hwdb: Sync with wiki to add more unknown devices 2022-05-24 14:38:10 +02:00
Aris Lin
82d0f4288a synaptics: Add new PID 0x015F 2022-05-23 21:06:23 +08:00
Benjamin Berg
e86c45c988 device: Add missing errno.h include
This made the flatpak build fail.
2022-05-18 09:09:48 +02:00
Benjamin Berg
56ae75d2b2 device: Fully re-evaluate suspend/resume logic when delayed
If we delayed the suspend(/resume) call, then the circumstances may have
changed. In particular, an active action may have completed already
which means that the driver handler should not be called anymore.
2022-05-17 20:29:00 +02:00
Benjamin Berg
54a98bb286 device: Run critical section flushing with a high priority
These delayed calls are pushed into the mainloop for consistency.
However, they should run immediately and not be delayed, as such, it
makes sense to run them at a higher priority.

This actually solves an issue inside the CI where an URB reply is played
back even though it should be cancelled by the client.
2022-05-17 20:29:00 +02:00
Benjamin Berg
bfbe24b172 synaptics: Correctly handle critical section during interrupt resubmit
We re-aquire the critical section at the start of the callback, however,
it needs to be dropped again (or not taken) if the interrupt transfer is
resubmitted.
2022-05-17 20:29:00 +02:00
Benjamin Berg
1f925fef7c tests: Test suspend/resume and sysfs attributes in synaptics 2022-05-17 20:29:00 +02:00
Benjamin Berg
7b0093b4c6 tests: Reset the USB device before testing
The kernel caches URBs to get descriptor values. Doing a reset before
starting the record ensures that we will see any descriptor reads in the
usbmon trace and can therefore correctly replay them (possibly not true
if they happen multiple times).
2022-05-17 20:29:00 +02:00
Benjamin Berg
0fd5a617ab device: Do not update sysfs attributes if value is correct
This avoids spurious warnings on e.g. SELinux enabled systems.
2022-05-17 20:29:00 +02:00
Matthew Mirvish
e7d041d258 elanspi: add 04f3:241f
Reported as working with this config in
https://github.com/mincrmatt12/elan-spi-fingerprint/issues/11.
2022-05-08 18:32:29 -04:00
129 changed files with 14320 additions and 1270 deletions

View File

@@ -1,50 +1,74 @@
include:
- local: '.gitlab-ci/libfprint-image-variables.yaml'
- local: '.gitlab-ci/libfprint-templates.yaml'
- project: 'freedesktop/ci-templates'
ref: master
file: '/templates/fedora.yml'
- remote: 'https://gitlab.gnome.org/GNOME/citemplates/-/raw/master/flatpak/flatpak_ci_initiative.yml'
- remote: 'https://gitlab.gnome.org/GNOME/citemplates/-/raw/71e636e012ae0ab04c5e0fe40ca73ada91ae6bde/flatpak/flatpak_ci_initiative.yml'
default:
# Auto-retry jobs in case of infra failures
retry:
max: 1
when:
- 'runner_system_failure'
- 'stuck_or_timeout_failure'
- 'scheduler_failure'
- 'api_failure'
variables:
extends: .libfprint_common_variables
FDO_DISTRIBUTION_TAG: latest
FDO_DISTRIBUTION_VERSION: rawhide
FDO_DISTRIBUTION_TAG: $LIBFPRINT_IMAGE_TAG
FDO_DISTRIBUTION_VERSION: 41
FDO_UPSTREAM_REPO: "libfprint/$CI_PROJECT_NAME"
FEDORA_IMAGE: "$CI_REGISTRY/libfprint/$CI_PROJECT_NAME/fedora/$FDO_DISTRIBUTION_VERSION:$FDO_DISTRIBUTION_TAG"
BUNDLE: "org.freedesktop.libfprint.Demo.flatpak"
LAST_ABI_BREAK: "056ea541ddc97f5806cffbd99a12dc87e4da3546"
workflow:
rules:
- if: $CI_PIPELINE_SOURCE == 'merge_request_event'
- if: $CI_PIPELINE_SOURCE == 'push'
- if: $CI_PIPELINE_SOURCE == 'schedule'
- if: $CI_PROJECT_NAMESPACE == 'libfprint' && $LIBFPRINT_CI_ACTION != ''
stages:
- image-build
- check-source
- build
- test
- flatpak
- deploy
image: $FEDORA_IMAGE
.build_one_driver_template: &build_one_driver
script:
# Build with a driver that doesn't need imaging, or nss
- meson --werror -Ddrivers=$driver . _build
- ninja -C _build
# Build with a driver that doesn't need imaging, or openssl
- meson setup _build --werror -Ddrivers=$driver
- meson compile -C _build
- rm -rf _build/
.build_template: &build
script:
# And build with everything
- meson --werror -Ddrivers=all . _build
- ninja -C _build
- ninja -C _build install
- meson setup _build --werror -Ddrivers=all
- meson compile -C _build
- meson install -C _build
.build_template: &check_abi
script:
- ./.ci/check-abi ${LAST_ABI_BREAK} $(git rev-parse HEAD)
.standard_job:
rules:
- when: on_success
- if: $CI_PIPELINE_SOURCE == "schedule"
when: never
build:
stage: build
except:
variables:
- $CI_PIPELINE_SOURCE == "schedule"
extends:
- .standard_job
variables:
driver: virtual_image
<<: *build_one_driver
@@ -59,16 +83,19 @@ build:
test:
stage: test
except:
variables:
- $CI_PIPELINE_SOURCE == "schedule"
extends:
- .standard_job
script:
- meson --werror -Ddrivers=all -Db_coverage=true . _build
- ninja -C _build
- meson setup _build --werror -Ddrivers=all -Db_coverage=true
- meson test -C _build --print-errorlogs --no-stdsplit --timeout-multiplier 3
- ninja -C _build coverage
- cat _build/meson-logs/coverage.txt
- ninja -C _build coverage || true
- cat _build/meson-logs/coverage.txt || true
artifacts:
reports:
junit: "_build/meson-logs/testlog.junit.xml"
coverage_report:
coverage_format: cobertura
path: _build/meson-logs/coverage.xml
expose_as: 'Coverage Report'
when: always
paths:
@@ -79,14 +106,15 @@ test:
test_valgrind:
stage: test
except:
variables:
- $CI_PIPELINE_SOURCE == "schedule"
extends:
- .standard_job
script:
- meson -Ddrivers=all . _build
- ninja -C _build
- meson setup _build -Ddrivers=all
- meson compile -C _build
- meson test -C _build --print-errorlogs --no-stdsplit --setup=valgrind
artifacts:
reports:
junit: "_build/meson-logs/testlog-valgrind.junit.xml"
expose_as: 'Valgrind test logs'
when: always
paths:
@@ -94,73 +122,123 @@ test_valgrind:
- _build/meson-logs/testlog-valgrind.txt
expire_in: 1 week
test_asan:
stage: test
extends:
- .standard_job
script:
- meson setup _build -Ddrivers=all -Db_sanitize=address,undefined
- meson test -C _build --print-errorlogs --no-stdsplit
artifacts:
reports:
junit: "_build/meson-logs/testlog.junit.xml"
expose_as: 'Sanitizers test logs'
when: always
paths:
- _build/meson-logs
- _build/meson-logs/testlog.txt
expire_in: 1 week
test_installed:
stage: test
extends:
- .standard_job
script:
- meson setup _build --prefix=/usr -Ddrivers=all
- meson install -C _build
- mv _build _build_dir
- rm -rf tests
- gnome-desktop-testing-runner --list libfprint-2
- gnome-desktop-testing-runner libfprint-2
--report-directory=_installed-tests-report/failed/
--log-directory=_installed-tests-report/logs/
--parallel=0
artifacts:
expose_as: 'GNOME Tests Runner logs'
when: always
paths:
- _build_dir/meson-logs
- _installed-tests-report
expire_in: 1 week
test_scan_build:
stage: test
except:
variables:
- $CI_PIPELINE_SOURCE == "schedule"
extends:
- .standard_job
allow_failure: true
script:
- meson -Ddrivers=all . _build
- meson setup _build -Ddrivers=all
# Wrapper to add --status-bugs and disable malloc checker
- SCANBUILD=$CI_PROJECT_DIR/.gitlab-ci/scan-build ninja -C _build scan-build
- SCANBUILD=$CI_PROJECT_DIR/.gitlab-ci/scan-build
ninja -C _build scan-build
artifacts:
when: on_failure
paths:
- _build/meson-logs
expire_in: 1 week
test_indent:
stage: check-source
except:
variables:
- $CI_PIPELINE_SOURCE == "schedule"
extends:
- .standard_job
script:
- scripts/uncrustify.sh
- git diff
- "! git status -s | grep -q ."
- git diff-index --name-only --exit-code HEAD
rules:
- changes:
compare_to: 'refs/heads/master'
paths:
- '**/*.c'
- '**/*.h'
test_unsupported_list:
stage: check-source
except:
variables:
- $CI_PIPELINE_SOURCE == "schedule"
extends:
- .standard_job
allow_failure: true
script:
- tests/hwdb-check-unsupported.py
flatpak:
stage: flatpak
extends: .flatpak
image: registry.gitlab.gnome.org/gnome/gnome-runtime-images/gnome:3.36
extends: .flatpak@x86_64
variables:
MANIFEST_PATH: "demo/org.freedesktop.libfprint.Demo.json"
FLATPAK_MODULE: "libfprint"
APP_ID: "org.freedesktop.libfprint.Demo"
BUNDLE: "org.freedesktop.libfprint.Demo.flatpak"
RUNTIME_REPO: "https://nightly.gnome.org/gnome-nightly.flatpakrepo"
# Build with any builder
tags: []
rules:
- if: '$CI_PROJECT_PATH != "libfprint/libfprint"'
when: never
- if: '$CI_PIPELINE_SOURCE == "schedule"'
when: manual
allow_failure: true
- if: $CI_PIPELINE_SOURCE == "schedule"
when: never
- if: '$CI_COMMIT_BRANCH == "master"'
allow_failure: true
when: always
- if: '$CI_COMMIT_TAG'
allow_failure: true
when: always
# For any other (commit), allow manual run.
# This excludes MRs which would create a duplicate pipeline
- if: '$CI_COMMIT_BRANCH'
when: manual
allow_failure: true
- if: '$CI_MERGE_REQUEST_ID'
when: manual
allow_failure: true
# CONTAINERS creation stage
container_fedora_build:
.container_fedora_build_base:
extends: .fdo.container-build@fedora
only:
variables:
- $CI_PIPELINE_SOURCE == "schedule" && $CRON_TASK == "BUILD_CI_IMAGES"
stage: image-build
variables:
GIT_STRATEGY: none # no need to pull the whole tree for rebuilding the image
FDO_FORCE_REBUILD: 1
# a list of packages to install
FDO_DISTRIBUTION_PACKAGES:
$LIBFPRINT_DEPENDENCIES
@@ -168,7 +246,51 @@ container_fedora_build:
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
$LIBFPRINT_EXEC
rules:
- when: never
.container_fedora_build_forced:
variables:
FDO_FORCE_REBUILD: 1
container_fedora_build_schedule:
extends:
- .container_fedora_build_base
- .container_fedora_build_forced
rules:
- if: $CI_PIPELINE_SOURCE == "schedule" && $CRON_TASK == "BUILD_CI_IMAGES"
when: always
container_fedora_build_manual:
extends:
- .container_fedora_build_base
- .container_fedora_build_forced
rules:
- if: $LIBFPRINT_CI_ACTION == "build-image"
when: always
container_fedora_build_on_deps_changed:
extends: .container_fedora_build_base
rules:
- if: $CI_PROJECT_NAMESPACE == "libfprint" && $CI_PIPELINE_SOURCE != "schedule"
changes:
compare_to: 'refs/heads/master'
paths:
- '.gitlab-ci/libfprint-image-variables.yaml'
- '.gitlab-ci/libfprint-templates.yaml'
pages:
image: alpine:latest
stage: deploy
needs:
- job: test
artifacts: true
script:
- mkdir public
- mv _build/meson-logs/coveragereport public/coverage
artifacts:
paths:
- public
rules:
- if: $CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH && $CI_PIPELINE_SOURCE == "push"

View File

@@ -0,0 +1,2 @@
variables:
LIBFPRINT_IMAGE_TAG: v6

View File

@@ -1,6 +1,11 @@
# Bump image version on .gitlab-ci/libfprint-image-variables.yaml to trigger
# a rebuild on changes to this file
.libfprint_common_variables:
LIBFPRINT_DEPENDENCIES:
appstream
doxygen
dnf-plugins-core
flatpak-builder
gcc
gcc-c++
@@ -9,15 +14,18 @@
glib2-devel
glibc-devel
gobject-introspection-devel
gnome-desktop-testing
gtk-doc
gtk3-devel
libabigail
libasan
libgusb-devel
libgudev-devel
libubsan
libX11-devel
libXv-devel
meson
nss-devel
openssl-devel
pixman-devel
python3-cairo
python3-gobject
@@ -27,3 +35,13 @@
valgrind
clang-analyzer
diffutils
LIBFPRINT_EXEC: |
dnf -y install dnf-utils
debuginfo-install -y \
glib2 \
glibc \
libgusb \
libusb \
openssl \
pixman

View File

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

86
NEWS
View File

@@ -1,6 +1,88 @@
This file lists notable changes in each release. For the full history of all
changes, see ChangeLog.
2025-02-20: v1.94.9 release
Highlights:
* uru4000: Use OpenSSL to perform AES-ECB encryption, as per this libfprint
does not support on NSS, but on openssl (>= 3.0).
* goodixmoc: New PIDs 0x60C2, 0x689A
* synaptics: New PIDs 0x016C, 0x0174, 0x0107, 0x0108, 0x00C2, 0x00F0
* fpcmoc: New PID 0xC844
* focaltech_moc: New PIDs 0xA99A, 0xA57A, 0xA78A
* elanmoc: New PIDs 0x0C98, 0x0C9D, 0x0CA3
* elanspi: New PIDs 0x3128, 0x2766
* fp-device: Add FP_DEVICE_RETRY_TOO_FAST retry error
* data: AppStream meta info listing supported USB devices.
* fixed various memory issues in multiple devices
2024-09-03: v1.94.8 release
Highlights:
* build: Support building in non-linux unix environments (tested in FreeBSD)
* egismoc: New PIDs 0x0583, 0x0586, 0x0587.
* elanmoc: New PID 0x0C9F.
* fpcmoc: New PIDs 0x9524, 0x9544.
* goodixmoc: New PIDs 0x609A, 0x650A, 0x650C, 0x6512.
* realtek: New PID 0x5816.
* synaptics: New PIDs 0x00C4, 0x019D, 0x00C6.
* fpcmoc: fix incorrect immobile handling during enrollment.
* fpcmoc: fixed jumping to wrong state at end of custom enroll.
* egismoc: various code cleanups.
2024-02-20: v1.94.7 release
Highlights:
* synaptics: fix enroll identify problem after user reset database.
* synaptics: New PIDs 0x0173, 0x0106, 0x0124.
* goodixmoc: New PID 0x6582.
* build: Do not require bash to build, only posix sh.
* fp-image: Simplify minutiae detection tasks.
* GLib 2.68 is now required to build libfprint.
New drivers:
* realtek (PID 0x5813).
* focaltech_moc (PIDs 0x9E48, 0xD979, 0xA959).
* egismoc (PIDs 0x0582, 0x05a1).
2023-08-17: v1.94.6 release
Highlights:
* goodixmoc: New PIDs 0x60A4, 0x60BC, 0x6092, 0x633C and 0x6304.
* goodixmoc: Fix missing "enroll create" state.
* elanmoc: New PID 0x0C99.
* upektc: Improve compatibility with sensors 147e:2016.
* aes4000: Actually support 08FF:5501 devices.
* virtual-device-listener: Fix failing tests with GLib 2.76
* tests: Add installed tests
Bugs fixed:
* #526 libfprint: fpcmoc: use after free if enrollment or identification is
cancelled (Vasily Khoruzhick)
2022-10-13: v1.94.5 release
Highlights:
* New driver: fpcmoc, supporting various FPC MOC Fingerprint Sensors
* goodixmoc: New PIDs 0x6014, 0x6094, 0x631C, 0x634C, 0x6384, 0x659A.
* goodixmoc: Support resetting device on firmware failure due to corrupted DB.
* elanmoc: New PIDs 0x0c88, 0x0c8c, 0x0c8d.
* synaptics: New PID 0x0104.
* upektc: New PID 0x2017.
* Fixed various memory leaks
* More tests
2022-05-24: v1.94.4 release
Highlights:
* synaptics: New PIDs 0x0168, 0x015f
* elan: New PID 0x0c4b
* elanspi: New PID 0x241f
* synaptics: Minor fix to interrupt transfer resubmission
* Avoid sysfs writes if value is already expected
* Improvements to the testing setup
* Fixes to the internal critical section API
2021-11-02: v1.94.3 release
Highlights:
@@ -319,7 +401,7 @@ tests of the drivers using umockdev.
- Mark fp_dscv_print functions as deprecated
* Udev rules:
- Add some unsupported devices to the whitelist
- Add some unsupported devices to the allowlist
2017-05-14: v0.7.0 release
* Drivers:
@@ -369,7 +451,7 @@ tests of the drivers using umockdev.
- Fix possible race condition, and cancellation in uru4000 driver
* Udev rules:
- Add Microsoft keyboard to the suspend blacklist
- Add Microsoft keyboard to the suspend denylist
* Plenty of build fixes

117
README.md
View File

@@ -1,54 +1,95 @@
# libfprint
libfprint is part of the fprint project:
https://fprint.freedesktop.org/
<div align="center">
# LibFPrint
*LibFPrint is part of the **[FPrint][Website]** project.*
<br/>
[![Button Website]][Website]
[![Button Documentation]][Documentation]
[![Button Supported]][Supported]
[![Button Unsupported]][Unsupported]
[![Button Contribute]][Contribute]
[![Button Contributors]][Contributors]
</div>
## History
libfprint was originally developed as part of an academic project at the
University of Manchester with the aim of hiding differences between different
consumer fingerprint scanners and providing a single uniform API to application
developers. The ultimate goal of the fprint project is to make fingerprint
scanners widely and easily usable under common Linux environments.
**LibFPrint** was originally developed as part of an
academic project at the **[University Of Manchester]**.
The academic university project runs off a codebase maintained separately
from this one, although I try to keep them as similar as possible (I'm not
hiding anything in the academic branch, it's just the open source release
contains some commits excluded from the academic project).
It aimed to hide the differences between consumer
fingerprint scanners and provide a single uniform
API to application developers.
## Goal
The ultimate goal of the **FPrint** project is to make
fingerprint scanners widely and easily usable under
common Linux environments.
## License
THE UNIVERSITY OF MANCHESTER DOES NOT ENDORSE THIS THIS SOFTWARE RELEASE AND
IS IN NO WAY RESPONSIBLE FOR THE CODE CONTAINED WITHIN, OR ANY DAMAGES CAUSED
BY USING OR DISTRIBUTING THE SOFTWARE. Development does not happen on
university computers and the project is not hosted at the university either.
`Section 6` of the license states that for compiled works that use
this library, such works must include **LibFPrint** copyright notices
alongside the copyright notices for the other parts of the work.
For more information on libfprint, supported devices, API documentation, etc.,
see the homepage:
https://fprint.freedesktop.org/
**LibFPrint** includes code from **NIST's** **[NBIS]** software distribution.
libfprint is licensed under the GNU LGPL version 2.1. See the COPYING file
for the license text.
We include **Bozorth3** from the **[US Export Controlled]**
distribution, which we have determined to be fine
being shipped in an open source project.
Section 6 of the license states that for compiled works that use this
library, such works must include libfprint copyright notices alongside the
copyright notices for the other parts of the work. We have attempted to
make this process slightly easier for you by grouping these all in one place:
the AUTHORS file.
## Get in *touch*
libfprint includes code from NIST's NBIS software distribution:
http://fingerprint.nist.gov/NBIS/index.html
We include bozorth3 from the US export controlled distribution. We have
determined that it is fine to ship bozorth3 in an open source project,
see https://fprint.freedesktop.org/us-export-control.html
- [IRC] - `#fprint` @ `irc.oftc.net`
- [Matrix] - `#fprint:matrix.org` bridged to the IRC channel
- [MailingList] - low traffic, not much used these days
## Historical links
<br/>
Older versions of libfprint are available at:
https://sourceforge.net/projects/fprint/files/
<div align="right">
Historical mailing-list archives:
http://www.reactivated.net/fprint_list_archives/
[![Badge License]][License]
Historical website:
http://web.archive.org/web/*/https://www.freedesktop.org/wiki/Software/fprint/
</div>
<!----------------------------------------------------------------------------->
[Documentation]: https://fprint.freedesktop.org/libfprint-dev/
[Contributors]: https://gitlab.freedesktop.org/libfprint/libfprint/-/graphs/master
[Unsupported]: https://gitlab.freedesktop.org/libfprint/wiki/-/wikis/Unsupported-Devices
[Supported]: https://fprint.freedesktop.org/supported-devices.html
[Website]: https://fprint.freedesktop.org/
[MailingList]: https://lists.freedesktop.org/mailman/listinfo/fprint
[IRC]: ircs://irc.oftc.net:6697/#fprint
[Matrix]: https://matrix.to/#/#fprint:matrix.org
[Contribute]: ./HACKING.md
[License]: ./COPYING
[University Of Manchester]: https://www.manchester.ac.uk/
[US Export Controlled]: https://fprint.freedesktop.org/us-export-control.html
[NBIS]: http://fingerprint.nist.gov/NBIS/index.html
<!---------------------------------[ Badges ]---------------------------------->
[Badge License]: https://img.shields.io/badge/License-LGPL2.1-015d93.svg?style=for-the-badge&labelColor=blue
<!---------------------------------[ Buttons ]--------------------------------->
[Button Documentation]: https://img.shields.io/badge/Documentation-04ACE6?style=for-the-badge&logoColor=white&logo=BookStack
[Button Contributors]: https://img.shields.io/badge/Contributors-FF4F8B?style=for-the-badge&logoColor=white&logo=ActiGraph
[Button Unsupported]: https://img.shields.io/badge/Unsupported_Devices-EF2D5E?style=for-the-badge&logoColor=white&logo=AdBlock
[Button Contribute]: https://img.shields.io/badge/Contribute-66459B?style=for-the-badge&logoColor=white&logo=Git
[Button Supported]: https://img.shields.io/badge/Supported_Devices-428813?style=for-the-badge&logoColor=white&logo=AdGuard
[Button Website]: https://img.shields.io/badge/Homepage-3B80AE?style=for-the-badge&logoColor=white&logo=freedesktopDotOrg

View File

@@ -67,7 +67,7 @@ usb:v08FFp5731*
ID_PERSIST=0
# Supported by libfprint driver aes4000
usb:v5501p08FF*
usb:v08FFp5501*
ID_AUTOSUSPEND=1
ID_PERSIST=0
@@ -77,6 +77,16 @@ usb:v1C7Ap0571*
ID_AUTOSUSPEND=1
ID_PERSIST=0
# Supported by libfprint driver egismoc
usb:v1C7Ap0582*
usb:v1C7Ap0583*
usb:v1C7Ap0584*
usb:v1C7Ap0586*
usb:v1C7Ap0587*
usb:v1C7Ap05A1*
ID_AUTOSUSPEND=1
ID_PERSIST=0
# Supported by libfprint driver elan
usb:v04F3p0903*
usb:v04F3p0907*
@@ -146,6 +156,14 @@ usb:v04F3p0C58*
usb:v04F3p0C7D*
usb:v04F3p0C7E*
usb:v04F3p0C82*
usb:v04F3p0C88*
usb:v04F3p0C8C*
usb:v04F3p0C8D*
usb:v04F3p0C98*
usb:v04F3p0C99*
usb:v04F3p0C9D*
usb:v04F3p0C9F*
usb:v04F3p0CA3*
ID_AUTOSUSPEND=1
ID_PERSIST=0
@@ -154,21 +172,62 @@ usb:v1C7Ap0603*
ID_AUTOSUSPEND=1
ID_PERSIST=0
# Supported by libfprint driver focaltech_moc
usb:v2808p9E48*
usb:v2808pD979*
usb:v2808pA959*
usb:v2808pA99A*
usb:v2808pA57A*
usb:v2808pA78A*
ID_AUTOSUSPEND=1
ID_PERSIST=0
# Supported by libfprint driver fpcmoc
usb:v10A5pFFE0*
usb:v10A5pA305*
usb:v10A5pA306*
usb:v10A5pDA04*
usb:v10A5pD805*
usb:v10A5pD205*
usb:v10A5p9524*
usb:v10A5p9544*
usb:v10A5pC844*
ID_AUTOSUSPEND=1
ID_PERSIST=0
# Supported by libfprint driver goodixmoc
usb:v27C6p5840*
usb:v27C6p6014*
usb:v27C6p6092*
usb:v27C6p6094*
usb:v27C6p609A*
usb:v27C6p609C*
usb:v27C6p60A2*
usb:v27C6p60A4*
usb:v27C6p60BC*
usb:v27C6p60C2*
usb:v27C6p6304*
usb:v27C6p631C*
usb:v27C6p633C*
usb:v27C6p634C*
usb:v27C6p6384*
usb:v27C6p639C*
usb:v27C6p63AC*
usb:v27C6p63BC*
usb:v27C6p63CC*
usb:v27C6p6496*
usb:v27C6p650A*
usb:v27C6p650C*
usb:v27C6p6582*
usb:v27C6p6584*
usb:v27C6p658C*
usb:v27C6p6592*
usb:v27C6p6594*
usb:v27C6p659A*
usb:v27C6p659C*
usb:v27C6p6A94*
usb:v27C6p6512*
usb:v27C6p689A*
ID_AUTOSUSPEND=1
ID_PERSIST=0
@@ -177,19 +236,40 @@ usb:v298Dp1010*
ID_AUTOSUSPEND=1
ID_PERSIST=0
# Supported by libfprint driver realtek
usb:v0BDAp5813*
usb:v0BDAp5816*
ID_AUTOSUSPEND=1
ID_PERSIST=0
# Supported by libfprint driver synaptics
usb:v06CBp00BD*
usb:v06CBp00C2*
usb:v06CBp00C4*
usb:v06CBp00C6*
usb:v06CBp00DF*
usb:v06CBp00F0*
usb:v06CBp00F9*
usb:v06CBp00FC*
usb:v06CBp00C2*
usb:v06CBp0100*
usb:v06CBp00F0*
usb:v06CBp0103*
usb:v06CBp0104*
usb:v06CBp0106*
usb:v06CBp0107*
usb:v06CBp0108*
usb:v06CBp0109*
usb:v06CBp010A*
usb:v06CBp0123*
usb:v06CBp0124*
usb:v06CBp0126*
usb:v06CBp0129*
usb:v06CBp015F*
usb:v06CBp0168*
usb:v06CBp016C*
usb:v06CBp0173*
usb:v06CBp0174*
usb:v06CBp019D*
usb:v06CBp019F*
ID_AUTOSUSPEND=1
ID_PERSIST=0
@@ -202,6 +282,7 @@ usb:v147Ep1001*
# Supported by libfprint driver upektc
usb:v0483p2015*
usb:v0483p2017*
usb:v147Ep3001*
ID_AUTOSUSPEND=1
ID_PERSIST=0
@@ -257,12 +338,36 @@ usb:v138Ap0091*
ID_PERSIST=0
# Known unsupported devices
usb:v0A5Cp5802*
usb:v047Dp00F2*
usb:v047Dp8054*
usb:v047Dp8055*
usb:v04E8p730B*
usb:v04F3p036B*
usb:v04F3p0C00*
usb:v04F3p0C4C*
usb:v04F3p0C57*
usb:v04F3p0C5E*
usb:v04F3p0C5A*
usb:v04F3p0C60*
usb:v04F3p0C6C*
usb:v04F3p0C70*
usb:v04F3p0C72*
usb:v04F3p0C77*
usb:v04F3p0C7C*
usb:v04F3p0C7F*
usb:v04F3p0C80*
usb:v04F3p0C85*
usb:v04F3p0C90*
usb:v04F3p2706*
usb:v04F3p3032*
usb:v04F3p3057*
usb:v04F3p3104*
usb:v04F3p310D*
usb:v04F3p3128*
usb:v04F3p0C8A*
usb:v05BAp000E*
usb:v06CBp0051*
usb:v06CBp0081*
usb:v06CBp0088*
usb:v06CBp008A*
@@ -273,15 +378,16 @@ usb:v06CBp00A8*
usb:v06CBp00B7*
usb:v06CBp00BB*
usb:v06CBp00BE*
usb:v06CBp00C4*
usb:v06CBp00CB*
usb:v06CBp00C9*
usb:v06CBp00D8*
usb:v06CBp00DA*
usb:v06CBp00DC*
usb:v06CBp00E4*
usb:v06CBp00E7*
usb:v06CBp00E9*
usb:v06CBp00FD*
usb:v06CBp00FF*
usb:v0A5Cp5801*
usb:v0A5Cp5805*
usb:v0A5Cp5834*
@@ -291,9 +397,19 @@ usb:v0A5Cp5842*
usb:v0A5Cp5843*
usb:v0A5Cp5844*
usb:v0A5Cp5845*
usb:v0A5Cp5860*
usb:v0A5Cp5863*
usb:v0A5Cp5864*
usb:v0A5Cp5865*
usb:v0A5Cp5866*
usb:v0A5Cp5867*
usb:v0BDAp5812*
usb:v10A5p0007*
usb:v10A5p9200*
usb:v10A5p9800*
usb:v10A5pA120*
usb:v10A5pA900*
usb:v10A5pE340*
usb:v1188p9545*
usb:v138Ap0007*
usb:v138Ap003A*
@@ -306,35 +422,56 @@ usb:v138Ap0094*
usb:v138Ap0097*
usb:v138Ap009D*
usb:v138Ap00AB*
usb:v138Ap00A6*
usb:v147Ep1002*
usb:v1491p0088*
usb:v16D1p1027*
usb:v1C7Ap0300*
usb:v1C7Ap0575*
usb:v1C7Ap0576*
usb:v1C7Ap0577*
usb:v1C7Ap057E*
usb:v2541p0236*
usb:v2541p9711*
usb:v27C6p5042*
usb:v27C6p5110*
usb:v27C6p5117*
usb:v27C6p5120*
usb:v27C6p5125*
usb:v27C6p5201*
usb:v27C6p521D*
usb:v27C6p5301*
usb:v27C6p530C*
usb:v27C6p532D*
usb:v27C6p5335*
usb:v27C6p533C*
usb:v27C6p5381*
usb:v27C6p5385*
usb:v27C6p538C*
usb:v27C6p538D*
usb:v27C6p5395*
usb:v27C6p5503*
usb:v27C6p550A*
usb:v27C6p550C*
usb:v27C6p5584*
usb:v27C6p55A2*
usb:v27C6p55A4*
usb:v27C6p55B4*
usb:v27C6p5740*
usb:v27C6p5E0A*
usb:v27C6p581A*
usb:v27C6p589A*
usb:v27C6p5F10*
usb:v27C6p6382*
usb:v2808p9338*
usb:v2808p9348*
usb:v2808p93A9*
usb:v2808pA658*
usb:v2808pC652*
usb:v298Dp2020*
usb:v298Dp2033*
usb:v2DF0p0003*
usb:v3274p8012*
usb:v3538p0930*
ID_AUTOSUSPEND=1
ID_PERSIST=0

View File

@@ -101,11 +101,14 @@ plot_minutiae (unsigned char *rgbdata,
{
int i;
#define write_pixel(num) do { \
rgbdata[((num) * 3)] = 0xff; \
rgbdata[((num) * 3) + 1] = 0; \
rgbdata[((num) * 3) + 2] = 0; \
} while(0)
#define write_pixel(num) \
do \
{ \
rgbdata[((num) * 3)] = 0xff; \
rgbdata[((num) * 3) + 1] = 0; \
rgbdata[((num) * 3) + 2] = 0; \
} \
while(0)
for (i = 0; i < minutiae->len; i++)
{

View File

@@ -1,12 +1,12 @@
{
"app-id": "org.freedesktop.libfprint.Demo",
"runtime": "org.gnome.Platform",
"runtime-version": "3.36",
"runtime-version": "master",
"sdk": "org.gnome.Sdk",
"command": "gtk-libfprint-test",
"finish-args": [
/* X11 + XShm access */
"--share=ipc", "--socket=x11",
"--share=ipc", "--socket=fallback-x11",
/* Wayland access */
"--socket=wayland",
/* OpenGL access */
@@ -18,7 +18,7 @@
"modules": [
{
"name": "libusb",
"config-opts": [ "--disable-static", "--disable-udev" ],
"config-opts": [ "--disable-static" ],
"cleanup": [
"/lib/*.la",
"/lib/pkgconfig",
@@ -26,48 +26,47 @@
],
"sources": [
{
"type": "archive",
"url": "https://github.com/libusb/libusb/archive/v1.0.22.tar.gz",
"sha256": "3500f7b182750cd9ccf9be8b1df998f83df56a39ab264976bdb3307773e16f48"
"type": "archive",
"url": "https://github.com/libusb/libusb/releases/download/v1.0.26/libusb-1.0.26.tar.bz2",
"sha256": "12ce7a61fc9854d1d2a1ffe095f7b5fac19ddba095c259e6067a46500381b5a5"
}
],
"post-install": [
"install -Dm644 COPYING /app/share/licenses/libgusb/COPYING"
"install -Dm644 COPYING /app/share/licenses/libusb/COPYING"
]
},
{
"name": "libgusb",
"buildsystem": "meson",
"config-opts": [ "-Dtests=false", "-Dvapi=false", "-Ddocs=false", "-Dintrospection=false" ],
"config-opts": [ "-Dtests=false", "-Dvapi=false", "-Ddocs=false" ],
"sources": [
{
"type": "archive",
"url": "https://github.com/hughsie/libgusb/archive/0.3.0.tar.gz",
"sha256": "b36310f8405d5fd68f6caf4a829f7ab4c627b38fd3d02a139d411fce0f3a49f1"
"url": "https://github.com/hughsie/libgusb/releases/download/0.4.6/libgusb-0.4.6.tar.xz",
"sha256": "1b0422bdcd72183272ac42eec9398c5a0bc48a02f618fa3242c468cbbd003049"
}
]
},
{
"name": "gudev",
"buildsystem": "meson",
"config-opts": [ "-Dtests=disabled", "-Dintrospection=disabled" ],
"config-opts": [ "-Dtests=disabled", "-Dintrospection=disabled", "-Dvapi=disabled" ],
"sources": [
{
"type": "archive",
"url": "https://download.gnome.org/sources/libgudev/236/libgudev-236.tar.xz",
"sha256": "e50369d06d594bae615eb7aeb787de304ebaad07a26d1043cef8e9c7ab7c9524"
"url": "https://download.gnome.org/sources/libgudev/238/libgudev-238.tar.xz",
"sha256": "61266ab1afc9d73dbc60a8b2af73e99d2fdff47d99544d085760e4fa667b5dd1"
}
]
},
{
"name": "libfprint",
"buildsystem": "meson",
"config-opts": [ "-Dudev_hwdb=disabled", "-Dudev_rules=disabled", "-Dx11-examples=false", "-Dgtk-examples=true", "-Ddrivers=all" ],
"config-opts": [ "-Dudev_hwdb=disabled", "-Dudev_rules=disabled", "-Dgtk-examples=true", "-Ddrivers=all" ],
"sources": [
{
"type": "git",
"url": "https://gitlab.freedesktop.org/libfprint/libfprint.git",
"branch": "wip/benzea/v2"
"url": "https://gitlab.freedesktop.org/libfprint/libfprint.git"
}
]
}

View File

@@ -19,13 +19,13 @@ content_files = [
expand_content_files = content_files
glib_prefix = dependency('glib-2.0').get_pkgconfig_variable('prefix')
glib_prefix = dependency('glib-2.0').get_variable(pkgconfig: 'prefix')
glib_docpath = join_paths(glib_prefix, 'share', 'gtk-doc', 'html')
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'),
src_dir: join_paths(meson.project_source_root(), 'libfprint'),
include_directories: include_directories('../libfprint'),
dependencies: libfprint_dep,
content_files: content_files,

208
examples/clear-storage.c Normal file
View File

@@ -0,0 +1,208 @@
/*
* Example storage clearing program, which deletes all the
* fingers which have been previously enrolled to disk.
* Copyright (C) 2020 Marco Trevisan <marco.trevisan@canonical.com>
* Copyright (C) 2024 Abhinav Baid <abhinavbaid@gmail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#define FP_COMPONENT "example-clear-storage"
#include <stdlib.h>
#include <stdio.h>
#include <libfprint/fprint.h>
#include <glib-unix.h>
#include "storage.h"
#include "utilities.h"
typedef struct _ClearStorageData
{
GMainLoop *loop;
GCancellable *cancellable;
unsigned int sigint_handler;
int ret_value;
} ClearStorageData;
static void
clear_storage_data_free (ClearStorageData *clear_storage_data)
{
g_clear_handle_id (&clear_storage_data->sigint_handler, g_source_remove);
g_clear_object (&clear_storage_data->cancellable);
g_main_loop_unref (clear_storage_data->loop);
g_free (clear_storage_data);
}
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClearStorageData, clear_storage_data_free)
static void
on_device_closed (FpDevice *dev, GAsyncResult *res, void *user_data)
{
g_autoptr(GError) error = NULL;
ClearStorageData *clear_storage_data = user_data;
fp_device_close_finish (dev, res, &error);
if (error)
g_warning ("Failed closing device %s", error->message);
g_main_loop_quit (clear_storage_data->loop);
}
static void
clear_storage_quit (FpDevice *dev,
ClearStorageData *clear_storage_data)
{
if (!fp_device_is_open (dev))
{
g_main_loop_quit (clear_storage_data->loop);
return;
}
fp_device_close (dev, NULL, (GAsyncReadyCallback) on_device_closed,
clear_storage_data);
}
static void
on_clear_storage_completed (FpDevice *dev, GAsyncResult *res, void *user_data)
{
g_autoptr(GError) error = NULL;
ClearStorageData *clear_storage_data = user_data;
if (fp_device_clear_storage_finish (dev, res, &error))
{
if (!clear_saved_prints (dev, &error))
{
g_warning ("Clear saved prints from local storage failed: %s",
error->message);
clear_storage_data->ret_value = EXIT_FAILURE;
}
else
{
g_print ("Clear storage successful!\n");
clear_storage_data->ret_value = EXIT_SUCCESS;
}
clear_storage_quit (dev, clear_storage_data);
return;
}
g_warning ("Failed to clear storage: %s", error->message);
clear_storage_data->ret_value = EXIT_FAILURE;
if (g_error_matches (error, FP_DEVICE_ERROR, FP_DEVICE_ERROR_NOT_SUPPORTED))
{
g_autoptr(GError) clear_error = NULL;
if (clear_saved_prints (dev, &clear_error))
clear_storage_data->ret_value = EXIT_SUCCESS;
else
g_warning ("Clear saved prints from local storage failed: %s",
clear_error->message);
}
clear_storage_quit (dev, clear_storage_data);
}
static void
start_clear_storage (FpDevice *dev, ClearStorageData *clear_storage_data)
{
char buffer[20];
g_print ("Clear device storage? [Y/n]? ");
if (fgets (buffer, sizeof (buffer), stdin) &&
(buffer[0] == 'Y' || buffer[0] == 'y'))
{
fp_device_clear_storage (dev, clear_storage_data->cancellable,
(GAsyncReadyCallback) on_clear_storage_completed,
clear_storage_data);
return;
}
clear_storage_quit (dev, clear_storage_data);
}
static void
on_device_opened (FpDevice *dev, GAsyncResult *res, void *user_data)
{
g_autoptr(GError) error = NULL;
ClearStorageData *clear_storage_data = user_data;
if (!fp_device_open_finish (dev, res, &error))
{
g_warning ("Failed to open device: %s", error->message);
clear_storage_quit (dev, clear_storage_data);
return;
}
g_print ("Opened device. ");
start_clear_storage (dev, clear_storage_data);
}
static gboolean
sigint_cb (void *user_data)
{
ClearStorageData *clear_storage_data = user_data;
g_cancellable_cancel (clear_storage_data->cancellable);
return G_SOURCE_CONTINUE;
}
int
main (void)
{
g_autoptr(FpContext) ctx = NULL;
g_autoptr(ClearStorageData) clear_storage_data = NULL;
GPtrArray *devices;
FpDevice *dev;
setenv ("G_MESSAGES_DEBUG", "all", 0);
setenv ("LIBUSB_DEBUG", "3", 0);
ctx = fp_context_new ();
devices = fp_context_get_devices (ctx);
if (!devices)
{
g_warning ("Impossible to get devices");
return EXIT_FAILURE;
}
dev = discover_device (devices);
if (!dev)
{
g_warning ("No devices detected.");
return EXIT_FAILURE;
}
clear_storage_data = g_new0 (ClearStorageData, 1);
clear_storage_data->ret_value = EXIT_FAILURE;
clear_storage_data->loop = g_main_loop_new (NULL, FALSE);
clear_storage_data->cancellable = g_cancellable_new ();
clear_storage_data->sigint_handler = g_unix_signal_add_full (G_PRIORITY_HIGH,
SIGINT,
sigint_cb,
clear_storage_data,
NULL);
fp_device_open (dev, clear_storage_data->cancellable,
(GAsyncReadyCallback) on_device_opened,
clear_storage_data);
g_main_loop_run (clear_storage_data->loop);
return clear_storage_data->ret_value;
}

View File

@@ -5,6 +5,7 @@ examples = [
'img-capture',
'manage-prints',
'verify',
'clear-storage',
]
foreach example: examples
@@ -21,3 +22,8 @@ executable('cpp-test',
'cpp-test.cpp',
dependencies: libfprint_dep,
)
if installed_tests
install_subdir('prints',
install_dir: installed_tests_testdir)
endif

View File

@@ -26,6 +26,7 @@
#include "storage.h"
#include <errno.h>
#include <glib/gstdio.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
@@ -55,6 +56,18 @@ get_print_data_descriptor (FpPrint *print, FpDevice *dev, FpFinger finger)
finger);
}
static char *
get_print_prefix_for_device (FpDevice *dev)
{
const char *driver;
const char *dev_id;
driver = fp_device_get_driver (dev);
dev_id = fp_device_get_device_id (dev);
return g_strdup_printf ("%s/%s/", driver, dev_id);
}
static GVariantDict *
load_data (void)
{
@@ -169,8 +182,6 @@ gallery_data_load (FpDevice *dev)
g_autoptr(GVariant) dict_variant = NULL;
g_autofree char *dev_prefix = NULL;
GPtrArray *gallery;
const char *driver;
const char *dev_id;
GVariantIter iter;
GVariant *value;
gchar *key;
@@ -178,9 +189,7 @@ gallery_data_load (FpDevice *dev)
gallery = g_ptr_array_new_with_free_func (g_object_unref);
dict = load_data ();
dict_variant = g_variant_dict_end (dict);
driver = fp_device_get_driver (dev);
dev_id = fp_device_get_device_id (dev);
dev_prefix = g_strdup_printf ("%s/%s/", driver, dev_id);
dev_prefix = get_print_prefix_for_device (dev);
g_variant_iter_init (&iter, dict_variant);
while (g_variant_iter_loop (&iter, "{sv}", &key, &value))
@@ -208,6 +217,55 @@ gallery_data_load (FpDevice *dev)
return gallery;
}
gboolean
clear_saved_prints (FpDevice *dev,
GError **error)
{
g_autoptr(GVariantDict) dict = NULL;
g_autoptr(GVariantDict) updated_dict = NULL;
g_autoptr(GVariant) dict_variant = NULL;
g_autofree char *dev_prefix = NULL;
GPtrArray *print_keys;
GVariantIter iter;
GVariant *value;
gchar *key;
print_keys = g_ptr_array_new_with_free_func (g_free);
dict = load_data ();
dict_variant = g_variant_dict_end (dict);
dev_prefix = get_print_prefix_for_device (dev);
g_variant_iter_init (&iter, dict_variant);
while (g_variant_iter_loop (&iter, "{sv}", &key, &value))
{
if (!g_str_has_prefix (key, dev_prefix))
continue;
g_ptr_array_add (print_keys, g_strdup (key));
}
if (!print_keys->len)
return TRUE;
updated_dict = load_data ();
for (guint i = 0; i < print_keys->len; ++i)
{
key = g_ptr_array_index (print_keys, i);
if (!g_variant_dict_remove (updated_dict, key))
{
g_warning ("Print '%s' key not found!", key);
continue;
}
g_debug ("Dropping print '%s' from gallery", key);
}
save_data (g_variant_dict_end (updated_dict));
return TRUE;
}
FpPrint *
print_create_template (FpDevice *dev, FpFinger finger, gboolean load_existing)
{

View File

@@ -20,12 +20,17 @@
#pragma once
#include <glib.h>
#include <libfprint/fprint.h>
int print_data_save (FpPrint *print,
FpFinger finger,
gboolean update_fingerprint);
FpPrint * print_data_load (FpDevice *dev,
FpFinger finger);
GPtrArray * gallery_data_load (FpDevice *dev);
gboolean clear_saved_prints (FpDevice *dev,
GError **error);
FpPrint * print_create_template (FpDevice *dev,
FpFinger finger,
const gboolean load_existing);

1
gcovr.cfg Normal file
View File

@@ -0,0 +1 @@
gcov-ignore-parse-errors = suspicious_hits.warn

View File

@@ -124,7 +124,7 @@ G_DEFINE_TYPE (FpiDeviceAes4000, fpi_device_aes4000, FPI_TYPE_DEVICE_AES3K);
static const FpIdEntry id_table[] = {
{ .pid = 0x08ff, .vid = 0x5501 },
{ .vid = 0x08ff, .pid = 0x5501 },
{ .vid = 0, .pid = 0, .driver_data = 0 },
};

View File

@@ -190,7 +190,7 @@ data_resp_cb (FpiUsbTransfer *transfer, FpDevice *dev, gpointer user_data, GErro
{
if (!self->stop && (self->strips_len > 0))
{
FpImage *img;
g_autoptr(FpImage) img = NULL;
self->strips = g_slist_reverse (self->strips);
fpi_do_movement_estimation (&assembling_ctx, self->strips);
img = fpi_assemble_frames (&assembling_ctx, self->strips);
@@ -199,7 +199,7 @@ data_resp_cb (FpiUsbTransfer *transfer, FpDevice *dev, gpointer user_data, GErro
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_image_captured (img_self, g_steal_pointer (&resizeImage));
}
fpi_image_device_report_finger_status (img_self, FALSE);

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,223 @@
/*
* Driver for Egis Technology (LighTuning) Match-On-Chip sensors
* Originally authored 2023 by Joshua Grisham <josh@joshuagrisham.com>
*
* Portions of code and logic inspired from the elanmoc libfprint driver
* which is copyright (C) 2021 Elan Microelectronics Inc (see elanmoc.c)
*
* Based on original reverse-engineering work by Joshua Grisham. The protocol has
* been reverse-engineered from captures of the official Windows driver, and by
* testing commands on the sensor with a multiplatform Python prototype driver:
* https://github.com/joshuagrisham/galaxy-book2-pro-linux/tree/main/fingerprint/
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#pragma once
#include "fpi-device.h"
#include "fpi-ssm.h"
G_DECLARE_FINAL_TYPE (FpiDeviceEgisMoc, fpi_device_egismoc, FPI, DEVICE_EGISMOC, FpDevice)
#define EGISMOC_DRIVER_FULLNAME "Egis Technology (LighTuning) Match-on-Chip"
#define EGISMOC_DRIVER_CHECK_PREFIX_TYPE1 (1 << 0)
#define EGISMOC_DRIVER_CHECK_PREFIX_TYPE2 (1 << 1)
#define EGISMOC_DRIVER_MAX_ENROLL_STAGES_20 (1 << 2)
#define EGISMOC_EP_CMD_OUT (0x02 | FPI_USB_ENDPOINT_OUT)
#define EGISMOC_EP_CMD_IN (0x81 | FPI_USB_ENDPOINT_IN)
#define EGISMOC_EP_CMD_INTERRUPT_IN 0x83
#define EGISMOC_USB_CONTROL_TIMEOUT 5000
#define EGISMOC_USB_SEND_TIMEOUT 5000
#define EGISMOC_USB_RECV_TIMEOUT 5000
#define EGISMOC_USB_INTERRUPT_TIMEOUT 60000
#define EGISMOC_USB_IN_RECV_LENGTH 4096
#define EGISMOC_USB_INTERRUPT_IN_RECV_LENGTH 64
#define EGISMOC_MAX_ENROLL_STAGES_DEFAULT 10
#define EGISMOC_MAX_ENROLL_NUM 10
#define EGISMOC_FINGERPRINT_DATA_SIZE 32
#define EGISMOC_LIST_RESPONSE_PREFIX_SIZE 14
#define EGISMOC_LIST_RESPONSE_SUFFIX_SIZE 2
/* standard prefixes for all read/writes */
static guchar egismoc_write_prefix[] = {'E', 'G', 'I', 'S', 0x00, 0x00, 0x00, 0x01};
static gsize egismoc_write_prefix_len = sizeof (egismoc_write_prefix) / sizeof (egismoc_write_prefix[0]);
static guchar egismoc_read_prefix[] = {'S', 'I', 'G', 'E', 0x00, 0x00, 0x00, 0x01};
static gsize egismoc_read_prefix_len = sizeof (egismoc_read_prefix) / sizeof (egismoc_read_prefix[0]);
/* hard-coded command payloads */
static guchar cmd_fw_version[] = {0x00, 0x00, 0x00, 0x07, 0x50, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x0c};
static gsize cmd_fw_version_len = sizeof (cmd_fw_version) / sizeof (cmd_fw_version[0]);
static guchar rsp_fw_version_suffix[] = {0x90, 0x00};
static gsize rsp_fw_version_suffix_len = sizeof (rsp_fw_version_suffix) / sizeof (rsp_fw_version_suffix[0]);
static guchar cmd_list[] = {0x00, 0x00, 0x00, 0x07, 0x50, 0x19, 0x04, 0x00, 0x00, 0x01, 0x40};
static gsize cmd_list_len = sizeof (cmd_list) / sizeof (cmd_list[0]);
static guchar cmd_sensor_reset[] = {0x00, 0x00, 0x00, 0x04, 0x50, 0x1a, 0x00, 0x00};
static gsize cmd_sensor_reset_len = sizeof (cmd_sensor_reset) / sizeof (cmd_sensor_reset[0]);
static guchar cmd_sensor_check[] = {0x00, 0x00, 0x00, 0x04, 0x50, 0x17, 0x02, 0x00};
static gsize cmd_sensor_check_len = sizeof (cmd_sensor_check) / sizeof (cmd_sensor_check[0]);
static guchar cmd_sensor_identify[] = {0x00, 0x00, 0x00, 0x04, 0x50, 0x17, 0x01, 0x01};
static gsize cmd_sensor_identify_len = sizeof (cmd_sensor_identify) / sizeof (cmd_sensor_identify[0]);
static guchar rsp_identify_match_suffix[] = {0x90, 0x00};
static gsize rsp_identify_match_suffix_len = sizeof (rsp_identify_match_suffix) / sizeof (rsp_identify_match_suffix[0]);
static guchar rsp_identify_notmatch_suffix[] = {0x90, 0x04};
static gsize rsp_identify_notmatch_suffix_len = sizeof (rsp_identify_notmatch_suffix) / sizeof (rsp_identify_notmatch_suffix[0]);
static guchar cmd_sensor_enroll[] = {0x00, 0x00, 0x00, 0x04, 0x50, 0x17, 0x01, 0x00};
static gsize cmd_sensor_enroll_len = sizeof (cmd_sensor_enroll) / sizeof (cmd_sensor_enroll[0]);
static guchar cmd_enroll_starting[] = {0x00, 0x00, 0x00, 0x07, 0x50, 0x16, 0x01, 0x00, 0x00, 0x00, 0x20};
static gsize cmd_enroll_starting_len = sizeof (cmd_enroll_starting) / sizeof (cmd_enroll_starting[0]);
static guchar cmd_sensor_start_capture[] = {0x00, 0x00, 0x00, 0x04, 0x50, 0x16, 0x02, 0x01};
static gsize cmd_sensor_start_capture_len = sizeof (cmd_sensor_start_capture) / sizeof (cmd_sensor_start_capture[0]);
static guchar cmd_read_capture[] = {0x00, 0x00, 0x00, 0x07, 0x50, 0x16, 0x02, 0x02, 0x00, 0x00, 0x02};
static gsize cmd_read_capture_len = sizeof (cmd_read_capture) / sizeof (cmd_read_capture[0]);
static guchar rsp_read_success_prefix[] = {0x00, 0x00, 0x00, 0x04};
static gsize rsp_read_success_prefix_len = sizeof (rsp_read_success_prefix) / sizeof (rsp_read_success_prefix[0]);
static guchar rsp_read_success_suffix[] = {0x90, 0x00};
static gsize rsp_read_success_suffix_len = sizeof (rsp_read_success_suffix) / sizeof (rsp_read_success_suffix[0]);
static guchar rsp_read_offcenter_prefix[] = {0x00, 0x00, 0x00, 0x04};
static gsize rsp_read_offcenter_prefix_len = sizeof (rsp_read_offcenter_prefix) / sizeof (rsp_read_offcenter_prefix[0]);
static guchar rsp_read_offcenter_suffix[] = {0x64, 0x91};
static gsize rsp_read_offcenter_suffix_len = sizeof (rsp_read_offcenter_suffix) / sizeof (rsp_read_offcenter_suffix[0]);
static guchar rsp_read_dirty_prefix[] = {0x00, 0x00, 0x00, 0x02, 0x64};
static gsize rsp_read_dirty_prefix_len = sizeof (rsp_read_dirty_prefix) / sizeof (rsp_read_dirty_prefix[0]);
static guchar cmd_commit_starting[] = {0x00, 0x00, 0x00, 0x07, 0x50, 0x16, 0x05, 0x00, 0x00, 0x00, 0x20};
static gsize cmd_commit_starting_len = sizeof (cmd_commit_starting) / sizeof (cmd_commit_starting[0]);
/* commands which exist on the device but are currently not used */
/*
static guchar cmd_sensor_cancel[] = {0x00, 0x00, 0x00, 0x04, 0x50, 0x16, 0x04, 0x00};
static gsize cmd_sensor_cancel_len = sizeof(cmd_sensor_cancel) / sizeof(cmd_sensor_cancel[0]);
static guchar cmd_sensor_verify[] = {0x00, 0x00, 0x00, 0x04, 0x50, 0x04, 0x01, 0x00};
static gsize cmd_sensor_verify_len = sizeof(cmd_sensor_verify) / sizeof(cmd_sensor_verify[0]);
static guchar cmd_read_verify[] = {0x00, 0x00, 0x00, 0x04, 0x50, 0x04, 0x02, 0x00};
static gsize cmd_read_verify_len = sizeof(cmd_read_verify) / sizeof(cmd_read_verify[0]);
*/
/* prefixes/suffixes and other things for dynamically created command payloads */
#define EGISMOC_CHECK_BYTES_LENGTH 2
#define EGISMOC_IDENTIFY_RESPONSE_PRINT_ID_OFFSET 46
#define EGISMOC_CMD_CHECK_SEPARATOR_LENGTH 32
static guchar cmd_new_print_prefix[] = {0x00, 0x00, 0x00, 0x27, 0x50, 0x16, 0x03, 0x00, 0x00, 0x00, 0x20};
static gsize cmd_new_print_prefix_len = sizeof (cmd_new_print_prefix) / sizeof (cmd_new_print_prefix[0]);
static guchar cmd_delete_prefix[] = {0x50, 0x18, 0x04, 0x00, 0x00};
static gsize cmd_delete_prefix_len = sizeof (cmd_delete_prefix) / sizeof (cmd_delete_prefix[0]);
static guchar rsp_delete_success_prefix[] = {0x00, 0x00, 0x00, 0x02, 0x90, 0x00};
static gsize rsp_delete_success_prefix_len = sizeof (rsp_delete_success_prefix) / sizeof (rsp_delete_success_prefix[0]);
static guchar cmd_check_prefix_type1[] = {0x50, 0x17, 0x03, 0x00, 0x00};
static gsize cmd_check_prefix_type1_len = sizeof (cmd_check_prefix_type1) / sizeof (cmd_check_prefix_type1[0]);
static guchar cmd_check_prefix_type2[] = {0x50, 0x17, 0x03, 0x80, 0x00};
static gsize cmd_check_prefix_type2_len = sizeof (cmd_check_prefix_type2) / sizeof (cmd_check_prefix_type2[0]);
static guchar cmd_check_suffix[] = {0x00, 0x40};
static gsize cmd_check_suffix_len = sizeof (cmd_check_suffix) / sizeof (cmd_check_suffix[0]);
static guchar rsp_check_not_yet_enrolled_suffix[] = {0x90, 0x04};
static gsize rsp_check_not_yet_enrolled_suffix_len = sizeof (rsp_check_not_yet_enrolled_suffix) / sizeof (rsp_check_not_yet_enrolled_suffix[0]);
/* SSM task states and various status enums */
typedef enum {
CMD_SEND,
CMD_GET,
CMD_STATES,
} CommandStates;
typedef enum {
DEV_INIT_CONTROL1,
DEV_INIT_CONTROL2,
DEV_INIT_CONTROL3,
DEV_INIT_CONTROL4,
DEV_INIT_CONTROL5,
DEV_GET_FW_VERSION,
DEV_INIT_STATES,
} DeviceInitStates;
typedef enum {
IDENTIFY_GET_ENROLLED_IDS,
IDENTIFY_CHECK_ENROLLED_NUM,
IDENTIFY_SENSOR_RESET,
IDENTIFY_SENSOR_IDENTIFY,
IDENTIFY_WAIT_FINGER,
IDENTIFY_SENSOR_CHECK,
IDENTIFY_CHECK,
IDENTIFY_COMPLETE_SENSOR_RESET,
IDENTIFY_COMPLETE,
IDENTIFY_STATES,
} IdentifyStates;
typedef enum {
ENROLL_GET_ENROLLED_IDS,
ENROLL_CHECK_ENROLLED_NUM,
ENROLL_SENSOR_RESET,
ENROLL_SENSOR_ENROLL,
ENROLL_WAIT_FINGER,
ENROLL_SENSOR_CHECK,
ENROLL_CHECK,
ENROLL_START,
ENROLL_CAPTURE_SENSOR_RESET,
ENROLL_CAPTURE_SENSOR_START_CAPTURE,
ENROLL_CAPTURE_WAIT_FINGER,
ENROLL_CAPTURE_READ_RESPONSE,
ENROLL_COMMIT_START,
ENROLL_COMMIT,
ENROLL_COMMIT_SENSOR_RESET,
ENROLL_COMPLETE,
ENROLL_STATES,
} EnrollStates;
typedef enum {
ENROLL_STATUS_DEVICE_FULL,
ENROLL_STATUS_DUPLICATE,
ENROLL_STATUS_PARTIAL_OK,
ENROLL_STATUS_RETRY,
ENROLL_STATUS_COMPLETE,
} EnrollStatus;
typedef enum {
LIST_GET_ENROLLED_IDS,
LIST_RETURN_ENROLLED_PRINTS,
LIST_STATES,
} ListStates;
typedef enum {
DELETE_GET_ENROLLED_IDS,
DELETE_DELETE,
DELETE_STATES,
} DeleteStates;

View File

@@ -357,7 +357,7 @@ elan_cmd_cb (FpiUsbTransfer *transfer, FpDevice *dev,
if (transfer->endpoint & FPI_USB_ENDPOINT_IN)
{
/* just finished receiving */
self->last_read = g_memdup (transfer->buffer, transfer->actual_length);
self->last_read = g_memdup2 (transfer->buffer, transfer->actual_length);
elan_cmd_done (ssm);
}
else

View File

@@ -28,6 +28,14 @@ static const FpIdEntry id_table[] = {
{ .vid = 0x04f3, .pid = 0x0c7d, },
{ .vid = 0x04f3, .pid = 0x0c7e, },
{ .vid = 0x04f3, .pid = 0x0c82, },
{ .vid = 0x04f3, .pid = 0x0c88, },
{ .vid = 0x04f3, .pid = 0x0c8c, },
{ .vid = 0x04f3, .pid = 0x0c8d, },
{ .vid = 0x04f3, .pid = 0x0c98, },
{ .vid = 0x04f3, .pid = 0x0c99, },
{ .vid = 0x04f3, .pid = 0x0c9d, },
{ .vid = 0x04f3, .pid = 0x0c9f, },
{ .vid = 0x04f3, .pid = 0x0ca3, },
{ .vid = 0, .pid = 0, .driver_data = 0 }, /* terminating entry */
};
@@ -46,9 +54,9 @@ elanmoc_compose_cmd (
const struct elanmoc_cmd *cmd_info
)
{
g_autofree char *cmd_buf = NULL;
g_autofree uint8_t *cmd_buf = NULL;
cmd_buf = g_malloc0 (cmd_info->cmd_len);
cmd_buf = g_new0 (uint8_t, cmd_info->cmd_len);
if(cmd_info->cmd_len < ELAN_MAX_HDR_LEN)
memcpy (cmd_buf, &cmd_info->cmd_header, cmd_info->cmd_len);
else
@@ -376,9 +384,9 @@ elanmoc_enroll_cb (FpiDeviceElanmoc *self,
enroll_status_report (self, ENROLL_RSP_RETRY, self->num_frames, NULL);
}
if (self->num_frames == ELAN_MOC_ENROLL_TIMES && buffer_in[1] == ELAN_MSG_OK)
if (self->num_frames == self->max_moc_enroll_time && buffer_in[1] == ELAN_MSG_OK)
fpi_ssm_next_state (self->task_ssm);
else if (self->num_frames < ELAN_MOC_ENROLL_TIMES)
else if (self->num_frames < self->max_moc_enroll_time)
fpi_ssm_jump_to_state (self->task_ssm, MOC_ENROLL_WAIT_FINGER);
else
fpi_ssm_mark_failed (self->task_ssm, error);
@@ -441,7 +449,7 @@ elan_enroll_run_state (FpiSsm *ssm, FpDevice *dev)
case MOC_ENROLL_WAIT_FINGER:
cmd_buf = elanmoc_compose_cmd (&elanmoc_enroll_cmd);
cmd_buf[3] = self->curr_enrolled;
cmd_buf[4] = ELAN_MOC_ENROLL_TIMES;
cmd_buf[4] = self->max_moc_enroll_time;
cmd_buf[5] = self->num_frames;
elanmoc_get_cmd (dev, cmd_buf, elanmoc_enroll_cmd.cmd_len, elanmoc_enroll_cmd.resp_len, 1, elanmoc_enroll_cb);
break;
@@ -506,7 +514,7 @@ create_print_from_response (FpiDeviceElanmoc *self,
return NULL;
}
userid = g_memdup (&buffer_in[5], userid_len);
userid = g_memdup2 (&buffer_in[5], userid_len);
userid_safe = g_strndup ((const char *) &buffer_in[5], userid_len);
print = fp_print_new (FP_DEVICE (self));
uid = g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE, userid, userid_len, 1);
@@ -758,6 +766,7 @@ identify_status_report (FpiDeviceElanmoc *self, int verify_status_id,
}
enum identify_states {
IDENTIFY_SET_MODE,
IDENTIFY_WAIT_FINGER,
IDENTIFY_NUM_STATES,
};
@@ -793,6 +802,13 @@ elan_identify_run_state (FpiSsm *ssm, FpDevice *dev)
fp_info ("elanmoc %s ", __func__);
switch (fpi_ssm_get_cur_state (ssm))
{
case IDENTIFY_SET_MODE:
fp_info ("elanmoc %s IDENTIFY_SET_MODE", __func__);
cmd_buf = elanmoc_compose_cmd (&elanmoc_set_mod_cmd);
cmd_buf[3] = 0x03;
elanmoc_get_cmd (dev, cmd_buf, elanmoc_set_mod_cmd.cmd_len, elanmoc_set_mod_cmd.resp_len, 0, elanmoc_cmd_ack_cb);
break;
case IDENTIFY_WAIT_FINGER:
fp_info ("elanmoc %s VERIFY_WAIT_FINGER", __func__);
cmd_buf = elanmoc_compose_cmd (&elanmoc_verify_cmd);
@@ -999,6 +1015,12 @@ elanmoc_get_status_cb (FpiDeviceElanmoc *self,
}
if (buffer_in[1] != 0x03 && self->cmd_retry_cnt != 0)
{
self->cmd_retry_cnt--;
cmd_buf = elanmoc_compose_cmd (&cal_status_cmd);
elanmoc_get_cmd (FP_DEVICE (self), cmd_buf, cal_status_cmd.cmd_len, cal_status_cmd.resp_len, 0, elanmoc_get_status_cb);
}
else
{
if(self->cmd_retry_cnt == 0)
{
@@ -1007,12 +1029,6 @@ elanmoc_get_status_cb (FpiDeviceElanmoc *self,
"Sensor not ready"));
return;
}
self->cmd_retry_cnt--;
cmd_buf = elanmoc_compose_cmd (&cal_status_cmd);
elanmoc_get_cmd (FP_DEVICE (self), cmd_buf, cal_status_cmd.cmd_len, cal_status_cmd.resp_len, 0, elanmoc_get_status_cb);
}
else
{
fpi_ssm_next_state (self->task_ssm);
}
}
@@ -1060,6 +1076,7 @@ elanmoc_open (FpDevice *device)
{
FpiDeviceElanmoc *self = FPI_DEVICE_ELANMOC (device);
GError *error = NULL;
gint productid = 0;
if (!g_usb_device_reset (fpi_device_get_usb_device (device), &error))
goto error;
@@ -1067,6 +1084,28 @@ elanmoc_open (FpDevice *device)
if (!g_usb_device_claim_interface (fpi_device_get_usb_device (device), 0, 0, &error))
goto error;
productid = g_usb_device_get_pid (fpi_device_get_usb_device (device));
switch (productid)
{
case 0x0c8c:
self->max_moc_enroll_time = 11;
break;
case 0x0c99:
self->max_moc_enroll_time = 14;
break;
case 0x0c8d:
self->max_moc_enroll_time = 17;
break;
default:
self->max_moc_enroll_time = ELAN_MOC_ENROLL_TIMES;
break;
}
fpi_device_set_nr_enroll_stages (device, self->max_moc_enroll_time);
self->task_ssm = fpi_ssm_new (FP_DEVICE (self), dev_init_handler, DEV_INIT_STATES);
fpi_ssm_start (self->task_ssm, task_ssm_init_done);
return;

View File

@@ -188,6 +188,7 @@ struct _FpiDeviceElanmoc
unsigned char y_trace;
int num_frames;
int curr_enrolled;
int max_moc_enroll_time;
int cancel_result;
int cmd_retry_cnt;
int list_index;

View File

@@ -340,14 +340,17 @@ static const struct elanspi_regtable elanspi_calibration_table_new_page1 = {
// using checkargs ACPI:HIDPID
static const FpIdEntry elanspi_id_table[] = {
{.udev_types = ELANSPI_UDEV_TYPES, .spi_acpi_id = "ELAN7001", .hid_id = {.vid = ELANSPI_TP_VID, .pid = 0x2766}, .driver_data = ELANSPI_NO_ROTATE},
{.udev_types = ELANSPI_UDEV_TYPES, .spi_acpi_id = "ELAN7001", .hid_id = {.vid = ELANSPI_TP_VID, .pid = 0x3057}, .driver_data = ELANSPI_180_ROTATE},
{.udev_types = ELANSPI_UDEV_TYPES, .spi_acpi_id = "ELAN7001", .hid_id = {.vid = ELANSPI_TP_VID, .pid = 0x3087}, .driver_data = ELANSPI_180_ROTATE},
{.udev_types = ELANSPI_UDEV_TYPES, .spi_acpi_id = "ELAN7001", .hid_id = {.vid = ELANSPI_TP_VID, .pid = 0x30c6}, .driver_data = ELANSPI_180_ROTATE},
{.udev_types = ELANSPI_UDEV_TYPES, .spi_acpi_id = "ELAN7001", .hid_id = {.vid = ELANSPI_TP_VID, .pid = 0x3128}, .driver_data = ELANSPI_90LEFT_ROTATE},
{.udev_types = ELANSPI_UDEV_TYPES, .spi_acpi_id = "ELAN70A1", .hid_id = {.vid = ELANSPI_TP_VID, .pid = 0x3134}, .driver_data = ELANSPI_90LEFT_ROTATE},
{.udev_types = ELANSPI_UDEV_TYPES, .spi_acpi_id = "ELAN7001", .hid_id = {.vid = ELANSPI_TP_VID, .pid = 0x3148}, .driver_data = ELANSPI_180_ROTATE},
{.udev_types = ELANSPI_UDEV_TYPES, .spi_acpi_id = "ELAN7001", .hid_id = {.vid = ELANSPI_TP_VID, .pid = 0x30b2}, .driver_data = ELANSPI_NO_ROTATE},
{.udev_types = ELANSPI_UDEV_TYPES, .spi_acpi_id = "ELAN70A1", .hid_id = {.vid = ELANSPI_TP_VID, .pid = 0x30b2}, .driver_data = ELANSPI_NO_ROTATE},
{.udev_types = ELANSPI_UDEV_TYPES, .spi_acpi_id = "ELAN7001", .hid_id = {.vid = ELANSPI_TP_VID, .pid = 0x309f}, .driver_data = ELANSPI_180_ROTATE},
{.udev_types = ELANSPI_UDEV_TYPES, .spi_acpi_id = "ELAN7001", .hid_id = {.vid = ELANSPI_TP_VID, .pid = 0x241f}, .driver_data = ELANSPI_NO_ROTATE},
{.udev_types = 0}
};

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,52 @@
/*
* Copyright (C) 2021 Focaltech Microelectronics
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#pragma once
#include "fpi-device.h"
#include "fpi-ssm.h"
#include <libusb.h>
#include <stdio.h>
#include <stdlib.h>
G_DECLARE_FINAL_TYPE (FpiDeviceFocaltechMoc, fpi_device_focaltech_moc, FPI, DEVICE_FOCALTECH_MOC, FpDevice)
#define FOCALTECH_MOC_DRIVER_FULLNAME "Focaltech MOC Sensors"
#define FOCALTECH_MOC_CMD_TIMEOUT 1000
#define FOCALTECH_MOC_MAX_FINGERS 10
#define FOCALTECH_MOC_UID_PREFIX_LENGTH 8
#define FOCALTECH_MOC_USER_ID_LENGTH 64
typedef void (*FocaltechCmdMsgCallback) (FpiDeviceFocaltechMoc *self,
GError *error);
struct _FpiDeviceFocaltechMoc
{
FpDevice parent;
FpiSsm *task_ssm;
FpiSsm *cmd_ssm;
FpiUsbTransfer *cmd_transfer;
gboolean cmd_cancelable;
gsize cmd_len_in;
int num_frames;
int delete_slot;
guint8 bulk_in_ep;
guint8 bulk_out_ep;
};

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,221 @@
/*
* Copyright (c) 2022 Fingerprint Cards AB <tech@fingerprints.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#pragma once
#include "fpi-device.h"
#include "fpi-ssm.h"
#include <stdio.h>
#include <stdlib.h>
#define TEMPLATE_ID_SIZE (32)
#define MAX_FW_VERSION_STR_LEN (16)
#define FPC_CMD_INIT (0x01)
#define FPC_CMD_ARM (0x02)
#define FPC_CMD_ABORT (0x03)
#define FPC_CMD_INDICATE_S_STATE (0x08)
#define FPC_CMD_GET_IMG (0x09)
#define FPC_CMD_GET_KPI (0x0C)
#define FPC_CMD_LOAD_DB (0x60)
#define FPC_CMD_STORE_DB (0x61)
#define FPC_CMD_DELETE_DB (0x62)
#define FPC_CMD_DELETE_TEMPLATE (0x63)
#define FPC_CMD_BEGIN_ENROL (0x67)
#define FPC_CMD_ENROL (0x68)
#define FPC_CMD_END_ENROL (0x69)
#define FPC_CMD_BIND_IDENTITY (0x6A)
#define FPC_CMD_IDENTIFY (0x6B)
#define FPC_CMD_ENUM (0x70)
#define FPC_EVT_INIT_RESULT (0x02)
#define FPC_EVT_FINGER_DWN (0x06)
#define FPC_EVT_IMG (0x08)
#define FPC_EVT_FID_DATA (0x31)
#define FPC_DB_ID_LEN (16)
#define FPC_IDENTITY_TYPE_WILDCARD (0x1)
#define FPC_IDENTITY_TYPE_RESERVED (0x3)
#define FPC_IDENTITY_WILDCARD (0x25066282)
#define FPC_SUBTYPE_ANY (0xFF)
#define FPC_SUBTYPE_RESERVED (0xF5)
#define FPC_SUBTYPE_NOINFORMATION (0x00)
#define FPC_CAPTUREID_RESERVED (0x701100F)
#define FPC_SESSIONID_RESERVED (0x0077FF12)
#define FPC_TEMPLATES_MAX (10)
#define SECURITY_MAX_SID_SIZE (68)
#define FPC_HOST_MS_S0 (0x10)
#define FPC_HOST_MS_SX (0x11)
G_DECLARE_FINAL_TYPE (FpiDeviceFpcMoc, fpi_device_fpcmoc, FPI,
DEVICE_FPCMOC, FpDevice);
typedef struct _FPC_FID_DATA
{
guint32 identity_type;
guint32 reserved;
guint32 identity_size;
guint32 subfactor;
guint8 data[SECURITY_MAX_SID_SIZE];
} FPC_FID_DATA, *PFPC_FID_DATA;
typedef struct _FPC_LOAD_DB
{
gint32 status;
guint32 reserved;
guint32 database_id_size;
guint8 data[FPC_DB_ID_LEN];
} FPC_LOAD_DB, *PFPC_LOAD_DB;
typedef union _FPC_DELETE_DB
{
guint32 reserved;
guint32 database_id_size;
guint8 data[FPC_DB_ID_LEN];
} FPC_DB_OP, *PFPC_DB_OP;
typedef struct _FPC_BEGIN_ENROL
{
gint32 status;
guint32 reserved1;
guint32 reserved2;
} FPC_BEGIN_ENROL, *PFPC_BEGIN_ENROL;
typedef struct _FPC_ENROL
{
gint32 status;
guint32 remaining;
} FPC_ENROL, *PFPC_ENROL;
typedef struct _FPC_END_ENROL
{
gint32 status;
guint32 fid;
} FPC_END_ENROL, *PFPC_END_ENROL;
typedef struct _FPC_IDENTIFY
{
gint32 status;
guint32 identity_type;
guint32 identity_offset;
guint32 identity_size;
guint32 subfactor;
guint8 data[SECURITY_MAX_SID_SIZE];
} FPC_IDENTIFY, *PFPC_IDENTIFY;
typedef struct
{
guint32 cmdid;
guint32 length;
guint32 status;
} evt_hdr_t;
typedef struct
{
evt_hdr_t hdr;
guint16 sensor;
guint16 hw_id;
guint16 img_w;
guint16 img_h;
guint8 fw_version[MAX_FW_VERSION_STR_LEN];
guint16 fw_capabilities;
} evt_initiated_t;
typedef struct
{
guint8 subfactor;
guint32 identity_type;
guint32 identity_size;
guint8 identity[SECURITY_MAX_SID_SIZE];
} __attribute__((packed)) fpc_fid_data_t;
typedef struct
{
evt_hdr_t hdr;
gint status;
guint32 num_ids;
fpc_fid_data_t fid_data[FPC_TEMPLATES_MAX];
} __attribute__((packed)) evt_enum_fids_t;
typedef struct _fp_cmd_response
{
union
{
evt_hdr_t evt_hdr;
evt_initiated_t evt_inited;
evt_enum_fids_t evt_enum_fids;
};
} fpc_cmd_response_t, *pfpc_cmd_response_t;
enum {
FPC_ENROL_STATUS_COMPLETED = 0,
FPC_ENROL_STATUS_PROGRESS = 1,
FPC_ENROL_STATUS_FAILED_COULD_NOT_COMPLETE = 2,
FPC_ENROL_STATUS_FAILED_ALREADY_ENROLED = 3,
FPC_ENROL_STATUS_IMAGE_LOW_COVERAGE = 4,
FPC_ENROL_STATUS_IMAGE_TOO_SIMILAR = 5,
FPC_ENROL_STATUS_IMAGE_LOW_QUALITY = 6,
};
typedef enum {
FPC_CMDTYPE_UNKNOWN = 0,
FPC_CMDTYPE_TO_DEVICE,
FPC_CMDTYPE_TO_DEVICE_EVTDATA,
FPC_CMDTYPE_FROM_DEVICE,
} FpcCmdType;
typedef enum {
FP_CMD_SEND = 0,
FP_CMD_GET_DATA,
FP_CMD_SUSPENDED,
FP_CMD_RESUME,
FP_CMD_NUM_STATES,
} FpCmdState;
typedef enum {
FP_INIT = 0,
FP_LOAD_DB,
FP_INIT_NUM_STATES,
} FpInitState;
typedef enum {
FP_ENROLL_ENUM = 0,
FP_ENROLL_CREATE,
FP_ENROLL_CAPTURE,
FP_ENROLL_GET_IMG,
FP_ENROLL_UPDATE,
FP_ENROLL_COMPLETE,
FP_ENROLL_CHECK_DUPLICATE,
FP_ENROLL_BINDID,
FP_ENROLL_COMMIT,
FP_ENROLL_DICARD,
FP_ENROLL_CLEANUP,
FP_ENROLL_NUM_STATES,
} FpEnrollState;
typedef enum {
FP_VERIFY_CAPTURE = 0,
FP_VERIFY_GET_IMG,
FP_VERIFY_IDENTIFY,
FP_VERIFY_CANCEL,
FP_VERIFY_NUM_STATES,
} FpVerifyState;
typedef enum {
FP_CLEAR_DELETE_DB = 0,
FP_CLEAR_CREATE_DB,
FP_CLEAR_NUM_STATES,
} FpClearState;

View File

@@ -128,11 +128,13 @@ fp_cmd_receive_cb (FpiUsbTransfer *transfer,
GError *error)
{
FpiDeviceGoodixMoc *self = FPI_DEVICE_GOODIXMOC (device);
FpiByteReader reader = {0};
CommandData *data = user_data;
int ret = -1, ssm_state = 0;
int ssm_state = 0;
gxfp_cmd_response_t cmd_reponse = {0, };
pack_header header;
guint32 crc32_calc = 0;
guint32 crc32 = 0;
guint16 cmd = 0;
if (error)
@@ -154,8 +156,10 @@ fp_cmd_receive_cb (FpiUsbTransfer *transfer,
return;
}
ret = gx_proto_parse_header (transfer->buffer, transfer->actual_length, &header);
if (ret != 0)
reader.data = transfer->buffer;
reader.size = transfer->actual_length;
if (gx_proto_parse_header (&reader, &header) != 0)
{
fpi_ssm_mark_failed (transfer->ssm,
fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
@@ -163,8 +167,17 @@ fp_cmd_receive_cb (FpiUsbTransfer *transfer,
return;
}
if (!fpi_byte_reader_set_pos (&reader, PACKAGE_HEADER_SIZE + header.len))
{
fpi_ssm_mark_failed (transfer->ssm,
fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
"Package crc read failed"));
}
gx_proto_crc32_calc (transfer->buffer, PACKAGE_HEADER_SIZE + header.len, (uint8_t *) &crc32_calc);
if(crc32_calc != GUINT32_FROM_LE (*(uint32_t *) (transfer->buffer + PACKAGE_HEADER_SIZE + header.len)))
if (!fpi_byte_reader_get_uint32_le (&reader, &crc32) ||
crc32_calc != crc32)
{
fpi_ssm_mark_failed (transfer->ssm,
fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
@@ -174,8 +187,11 @@ fp_cmd_receive_cb (FpiUsbTransfer *transfer,
cmd = MAKE_CMD_EX (header.cmd0, header.cmd1);
ret = gx_proto_parse_body (cmd, &transfer->buffer[PACKAGE_HEADER_SIZE], header.len, &cmd_reponse);
if (ret != 0)
fpi_byte_reader_set_pos (&reader, 0);
reader.data = &transfer->buffer[PACKAGE_HEADER_SIZE];
reader.size = header.len;
if (gx_proto_parse_body (cmd, &reader, &cmd_reponse) != 0)
{
fpi_ssm_mark_failed (transfer->ssm,
fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
@@ -631,20 +647,20 @@ fp_enroll_enum_cb (FpiDeviceGoodixMoc *self,
return;
}
fpi_ssm_jump_to_state (self->task_ssm, FP_ENROLL_CAPTURE);
fpi_ssm_next_state (self->task_ssm);
}
static void
fp_enroll_init_cb (FpiDeviceGoodixMoc *self,
gxfp_cmd_response_t *resp,
GError *error)
fp_enroll_create_cb (FpiDeviceGoodixMoc *self,
gxfp_cmd_response_t *resp,
GError *error)
{
if (error)
{
fpi_ssm_mark_failed (self->task_ssm, error);
return;
}
memcpy (self->template_id, resp->enroll_init.tid, TEMPLATE_ID_SIZE);
memcpy (self->template_id, resp->enroll_create.tid, TEMPLATE_ID_SIZE);
fpi_ssm_next_state (self->task_ssm);
}
@@ -661,7 +677,7 @@ fp_enroll_capture_cb (FpiDeviceGoodixMoc *self,
/* */
if (resp->result >= GX_FAILED)
{
fp_warn ("Capture sample failed, result: 0x%x", resp->result);
fp_info ("Capture sample failed, result: 0x%x", resp->result);
fpi_device_enroll_progress (FP_DEVICE (self),
self->enroll_stage,
NULL,
@@ -675,7 +691,7 @@ fp_enroll_capture_cb (FpiDeviceGoodixMoc *self,
if ((resp->capture_data_resp.img_quality < self->sensorcfg->config[4]) ||
(resp->capture_data_resp.img_coverage < self->sensorcfg->config[5]))
{
fp_warn ("Capture sample poor quality(%d): %d or coverage(%d): %d",
fp_info ("Capture sample poor quality(%d): %d or coverage(%d): %d",
self->sensorcfg->config[4],
resp->capture_data_resp.img_quality,
self->sensorcfg->config[5],
@@ -837,16 +853,6 @@ fp_enroll_sm_run_state (FpiSsm *ssm, FpDevice *device)
switch (fpi_ssm_get_cur_state (ssm))
{
case FP_ENROLL_ENUM:
{
goodix_sensor_cmd (self, MOC_CMD0_GETFINGERLIST, MOC_CMD1_DEFAULT,
false,
(const guint8 *) &dummy,
1,
fp_enroll_enum_cb);
}
break;
case FP_ENROLL_PWR_BTN_SHIELD_ON:
{
goodix_sensor_cmd (self, MOC_CMD0_PWR_BTN_SHIELD, MOC_CMD1_PWR_BTN_SHIELD_ON,
@@ -857,13 +863,23 @@ fp_enroll_sm_run_state (FpiSsm *ssm, FpDevice *device)
}
break;
case FP_ENROLL_ENUM:
{
goodix_sensor_cmd (self, MOC_CMD0_GETFINGERLIST, MOC_CMD1_DEFAULT,
false,
(const guint8 *) &dummy,
1,
fp_enroll_enum_cb);
}
break;
case FP_ENROLL_CREATE:
{
goodix_sensor_cmd (self, MOC_CMD0_ENROLL_INIT, MOC_CMD1_DEFAULT,
false,
(const guint8 *) &dummy,
1,
fp_enroll_init_cb);
fp_enroll_create_cb);
}
break;
@@ -1041,6 +1057,47 @@ fp_init_config_cb (FpiDeviceGoodixMoc *self,
fpi_ssm_next_state (self->task_ssm);
}
static void
fp_init_cb_reset_or_complete (FpiDeviceGoodixMoc *self,
gxfp_cmd_response_t *resp,
GError *error)
{
if (error)
{
fp_warn ("Template storage appears to have been corrupted! Error was: %s", error->message);
fp_warn ("A known reason for this to happen is a firmware bug triggered by another storage area being initialized.");
fpi_ssm_jump_to_state (self->task_ssm, FP_INIT_RESET_DEVICE);
}
else
{
fpi_ssm_mark_completed (self->task_ssm);
}
}
static void
fp_init_reset_device_cb (FpiDeviceGoodixMoc *self,
gxfp_cmd_response_t *resp,
GError *error)
{
if (error)
{
fp_warn ("Reset failed: %s", error->message);
fpi_ssm_mark_failed (self->task_ssm, error);
return;
}
if ((resp->result >= GX_FAILED) && (resp->result != GX_ERROR_FINGER_ID_NOEXIST))
{
fp_warn ("Reset failed, device reported: 0x%x", resp->result);
fpi_ssm_mark_failed (self->task_ssm,
fpi_device_error_new_msg (FP_DEVICE_ERROR_GENERAL,
"Failed clear storage, result: 0x%x",
resp->result));
return;
}
fp_warn ("Reset completed");
fpi_ssm_mark_completed (self->task_ssm);
}
static void
fp_init_sm_run_state (FpiSsm *ssm, FpDevice *device)
@@ -1065,6 +1122,30 @@ fp_init_sm_run_state (FpiSsm *ssm, FpDevice *device)
sizeof (gxfp_sensor_cfg_t),
fp_init_config_cb);
break;
case FP_INIT_TEMPLATE_LIST:
/* List prints to check whether the template DB was corrupted.
* As of 2022-06-13 there is a known firmware issue that can cause the
* stored templates for Linux to be corrupted when the Windows storage
* area is initialized.
* In that case, we'll get a protocol failure trying to retrieve the
* list of prints.
*/
goodix_sensor_cmd (self, MOC_CMD0_GETFINGERLIST, MOC_CMD1_DEFAULT,
FALSE,
(const guint8 *) &dummy,
1,
fp_init_cb_reset_or_complete);
break;
case FP_INIT_RESET_DEVICE:
fp_warn ("Resetting device storage, you will need to enroll all prints again!");
goodix_sensor_cmd (self, MOC_CMD0_DELETETEMPLATE, MOC_CMD1_DELETE_ALL,
FALSE,
NULL,
0,
fp_init_reset_device_cb);
break;
}
@@ -1294,12 +1375,28 @@ gx_fp_probe (FpDevice *device)
{
case 0x6496:
case 0x60A2:
case 0x60A4:
case 0x6014:
case 0x6092:
case 0x6094:
case 0x609A:
case 0x609C:
case 0x60BC:
case 0x60C2:
case 0x6304:
case 0x631C:
case 0x633C:
case 0x634C:
case 0x6384:
case 0x639C:
case 0x63AC:
case 0x63BC:
case 0x63CC:
case 0x650A:
case 0x650C:
case 0x6582:
case 0x6A94:
case 0x659A:
self->max_enroll_stage = 12;
break;
@@ -1386,9 +1483,7 @@ gx_fp_exit_cb (FpiDeviceGoodixMoc *self,
gxfp_cmd_response_t *resp,
GError *error)
{
if (resp->result >= GX_FAILED)
if (resp && resp->result >= GX_FAILED)
fp_dbg ("Setting power button shield failed, result: 0x%x", resp->result);
self->is_power_button_shield_on = false;
gx_fp_release_interface (self, error);
@@ -1530,19 +1625,37 @@ fpi_device_goodixmoc_init (FpiDeviceGoodixMoc *self)
static const FpIdEntry id_table[] = {
{ .vid = 0x27c6, .pid = 0x5840, },
{ .vid = 0x27c6, .pid = 0x6014, },
{ .vid = 0x27c6, .pid = 0x6092, },
{ .vid = 0x27c6, .pid = 0x6094, },
{ .vid = 0x27c6, .pid = 0x609A, },
{ .vid = 0x27c6, .pid = 0x609C, },
{ .vid = 0x27c6, .pid = 0x60A2, },
{ .vid = 0x27c6, .pid = 0x60A4, },
{ .vid = 0x27c6, .pid = 0x60BC, },
{ .vid = 0x27c6, .pid = 0x60C2, },
{ .vid = 0x27c6, .pid = 0x6304, },
{ .vid = 0x27c6, .pid = 0x631C, },
{ .vid = 0x27c6, .pid = 0x633C, },
{ .vid = 0x27c6, .pid = 0x634C, },
{ .vid = 0x27c6, .pid = 0x6384, },
{ .vid = 0x27c6, .pid = 0x639C, },
{ .vid = 0x27c6, .pid = 0x63AC, },
{ .vid = 0x27c6, .pid = 0x63BC, },
{ .vid = 0x27c6, .pid = 0x63CC, },
{ .vid = 0x27c6, .pid = 0x6496, },
{ .vid = 0x27c6, .pid = 0x650A, },
{ .vid = 0x27c6, .pid = 0x650C, },
{ .vid = 0x27c6, .pid = 0x6582, },
{ .vid = 0x27c6, .pid = 0x6584, },
{ .vid = 0x27c6, .pid = 0x658C, },
{ .vid = 0x27c6, .pid = 0x6592, },
{ .vid = 0x27c6, .pid = 0x6594, },
{ .vid = 0x27c6, .pid = 0x659A, },
{ .vid = 0x27c6, .pid = 0x659C, },
{ .vid = 0x27c6, .pid = 0x6A94, },
{ .vid = 0x27c6, .pid = 0x6512, },
{ .vid = 0x27c6, .pid = 0x689A, },
{ .vid = 0, .pid = 0, .driver_data = 0 }, /* terminating entry */
};

View File

@@ -35,6 +35,8 @@ typedef enum {
typedef enum {
FP_INIT_VERSION = 0,
FP_INIT_CONFIG,
FP_INIT_TEMPLATE_LIST,
FP_INIT_RESET_DEVICE,
FP_INIT_NUM_STATES,
} FpInitState;
@@ -42,7 +44,6 @@ typedef enum {
typedef enum {
FP_ENROLL_PWR_BTN_SHIELD_ON = 0,
FP_ENROLL_ENUM,
FP_ENROLL_IDENTIFY,
FP_ENROLL_CREATE,
FP_ENROLL_CAPTURE,
FP_ENROLL_UPDATE,

View File

@@ -18,6 +18,8 @@
*/
#include <glib.h>
#include <stdint.h>
#include "goodix_proto.h"
/*
@@ -107,7 +109,7 @@ reflect (uint32_t data, uint8_t n_bits)
* If the LSB bit is set, set the reflection of it.
*/
if (data & 0x01)
reflection |= (1 << ((n_bits - 1) - bit));
reflection |= (1LU << ((n_bits - 1) - bit));
data = (data >> 1);
}
@@ -211,7 +213,11 @@ gx_proto_build_package (uint8_t *ppackage,
init_pack_header (&header, payload_size, cmd, 0);
memcpy (ppackage, &header, PACKAGE_HEADER_SIZE);
memcpy (ppackage + PACKAGE_HEADER_SIZE, payload, payload_size);
if (payload)
memcpy (ppackage + PACKAGE_HEADER_SIZE, payload, payload_size);
else
ppackage[PACKAGE_HEADER_SIZE] = 0;
gx_proto_crc32_calc (ppackage, PACKAGE_HEADER_SIZE + payload_size, ppackage + PACKAGE_HEADER_SIZE + payload_size);
@@ -220,94 +226,108 @@ gx_proto_build_package (uint8_t *ppackage,
int
gx_proto_parse_header (
uint8_t *buffer,
uint32_t buffer_len,
pack_header *pheader)
gx_proto_parse_header (FpiByteReader *reader,
pack_header *pheader)
{
if (!buffer || !pheader)
return -1;
if (buffer_len < PACKAGE_HEADER_SIZE + PACKAGE_CRC_SIZE)
if (!pheader)
return -1;
memcpy (pheader, buffer, sizeof (pack_header));
pheader->len = GUINT16_FROM_LE (pheader->len);
if (buffer_len < pheader->len + PACKAGE_HEADER_SIZE)
return -1;
if (!fpi_byte_reader_get_uint8 (reader, &pheader->cmd0))
g_return_val_if_reached (-1);
if (!fpi_byte_reader_get_uint8 (reader, &pheader->cmd1))
g_return_val_if_reached (-1);
if (!fpi_byte_reader_get_uint8 (reader, &pheader->packagenum))
g_return_val_if_reached (-1);
if (!fpi_byte_reader_get_uint8 (reader, &pheader->reserved))
g_return_val_if_reached (-1);
if (!fpi_byte_reader_get_uint16_le (reader, &pheader->len))
g_return_val_if_reached (-1);
if (!fpi_byte_reader_get_uint8 (reader, &pheader->crc8))
g_return_val_if_reached (-1);
if (!fpi_byte_reader_get_uint8 (reader, &pheader->rev_crc8))
g_return_val_if_reached (-1);
pheader->len -= PACKAGE_CRC_SIZE;
return 0;
}
static int
gx_proto_parse_fingerid (
uint8_t * fid_buffer,
uint16_t fid_buffer_size,
ptemplate_format_t template
)
gx_proto_parse_fingerid (FpiByteReader *reader,
ptemplate_format_t template)
{
uint8_t * buffer = NULL;
uint16_t Offset = 0;
uint8_t byte;
const uint8_t *buffer;
if (!template || !fid_buffer)
if (!template)
return -1;
if (fid_buffer_size < G_STRUCT_OFFSET (template_format_t, payload) + sizeof (uint32_t))
return -1;
if (!fpi_byte_reader_get_uint8 (reader, &byte) || byte != 67)
g_return_val_if_reached (-1);
buffer = fid_buffer;
Offset = 0;
if (!fpi_byte_reader_get_uint8 (reader, &template->type))
g_return_val_if_reached (-1);
if (buffer[Offset++] != 67)
return -1;
if (!fpi_byte_reader_get_uint8 (reader, &template->finger_index))
g_return_val_if_reached (-1);
template->type = buffer[Offset++];
template->finger_index = buffer[Offset++];
Offset++;
memcpy (template->accountid, &buffer[Offset], sizeof (template->accountid));
Offset += sizeof (template->accountid);
memcpy (template->tid, &buffer[Offset], sizeof (template->tid));
Offset += sizeof (template->tid); // Offset == 68
template->payload.size = buffer[Offset++];
if (template->payload.size > sizeof (template->payload.data))
return -1;
if (template->payload.size + Offset > fid_buffer_size)
return -1;
memset (template->payload.data, 0, template->payload.size);
memcpy (template->payload.data, &buffer[Offset], template->payload.size);
if (!fpi_byte_reader_skip (reader, 1))
g_return_val_if_reached (-1);
if (!fpi_byte_reader_get_data (reader, sizeof (template->accountid), &buffer))
g_return_val_if_reached (-1);
memcpy (template->accountid, buffer, sizeof (template->accountid));
if (!fpi_byte_reader_get_data (reader, sizeof (template->tid), &buffer))
g_return_val_if_reached (-1);
memcpy (template->tid, buffer, sizeof (template->tid));
if (!fpi_byte_reader_get_uint8 (reader, &template->payload.size))
g_return_val_if_reached (-1);
if (!fpi_byte_reader_get_data (reader, template->payload.size, &buffer))
g_return_val_if_reached (-1);
memcpy (template->payload.data, buffer, template->payload.size);
return 0;
}
int
gx_proto_parse_body (uint16_t cmd, uint8_t *buffer, uint16_t buffer_len, pgxfp_cmd_response_t presp)
gx_proto_parse_body (uint16_t cmd, FpiByteReader *byte_reader, pgxfp_cmd_response_t presp)
{
uint16_t offset = 0;
uint8_t *fingerlist = NULL;
if (!presp)
return -1;
if (!fpi_byte_reader_get_uint8 (byte_reader, &presp->result))
g_return_val_if_reached (-1);
if (!buffer || !presp)
return -1;
if (buffer_len < 1)
return -1;
presp->result = buffer[0];
switch (HIBYTE (cmd))
{
case RESPONSE_PACKAGE_CMD:
{
if (buffer_len < sizeof (gxfp_parse_msg_t) + 1)
return -1;
presp->parse_msg.ack_cmd = buffer[1];
if (!fpi_byte_reader_get_uint8 (byte_reader, &presp->parse_msg.ack_cmd))
g_return_val_if_reached (-1);
}
break;
case MOC_CMD0_UPDATE_CONFIG:
{
presp->finger_config.status = buffer[0];
if (buffer_len >= 3)
presp->finger_config.max_stored_prints = buffer[2];
else
/* to compatiable old version firmware */
presp->finger_config.max_stored_prints = FP_MAX_FINGERNUM;
presp->finger_config.status = presp->result;
/* to compatiable old version firmware */
presp->finger_config.max_stored_prints = FP_MAX_FINGERNUM;
if (fpi_byte_reader_skip (byte_reader, 1))
fpi_byte_reader_get_uint8 (byte_reader,
&presp->finger_config.max_stored_prints);
}
break;
@@ -318,87 +338,99 @@ gx_proto_parse_body (uint16_t cmd, uint8_t *buffer, uint16_t buffer_len, pgxfp_c
case MOC_CMD0_PWR_BTN_SHIELD:
presp->power_button_shield_resp.resp_cmd1 = LOBYTE (cmd);
if (buffer_len >= 2)
{
uint8_t support_pwr_shield = buffer[1];
if (support_pwr_shield == 0xFF)
g_debug ("Power button shield feature not supported!\n");
}
uint8_t support_pwr_shield;
if (fpi_byte_reader_get_uint8 (byte_reader, &support_pwr_shield) &&
support_pwr_shield == 0xFF)
g_debug ("Power button shield feature not supported!\n");
break;
case MOC_CMD0_GET_VERSION:
if (buffer_len < sizeof (gxfp_version_info_t) + 1)
return -1;
memcpy (&presp->version_info, buffer + 1, sizeof (gxfp_version_info_t));
const uint8_t *version_info;
if (!fpi_byte_reader_get_data (byte_reader, sizeof (gxfp_version_info_t), &version_info))
g_return_val_if_reached (-1);
memcpy (&presp->version_info, version_info, sizeof (gxfp_version_info_t));
break;
case MOC_CMD0_CAPTURE_DATA:
if (LOBYTE (cmd) == MOC_CMD1_DEFAULT)
{
if (buffer_len < sizeof (gxfp_capturedata_t) + 1)
return -1;
presp->capture_data_resp.img_quality = buffer[1];
presp->capture_data_resp.img_coverage = buffer[2];
if (!fpi_byte_reader_get_uint8 (byte_reader,
&presp->capture_data_resp.img_quality))
g_return_val_if_reached (-1);
if (!fpi_byte_reader_get_uint8 (byte_reader,
&presp->capture_data_resp.img_coverage))
g_return_val_if_reached (-1);
}
break;
case MOC_CMD0_ENROLL_INIT:
if (buffer_len < sizeof (gxfp_enroll_init_t) + 1)
return -1;
if (presp->result == GX_SUCCESS)
memcpy (&presp->enroll_init.tid, &buffer[1], TEMPLATE_ID_SIZE);
if (presp->result != GX_SUCCESS)
break;
const uint8_t *tid;
if (!fpi_byte_reader_get_data (byte_reader, TEMPLATE_ID_SIZE, &tid))
g_return_val_if_reached (-1);
memcpy (presp->enroll_create.tid, tid, TEMPLATE_ID_SIZE);
break;
case MOC_CMD0_ENROLL:
if (buffer_len < sizeof (gxfp_enroll_update_t))
return -1;
presp->enroll_update.rollback = (buffer[0] < 0x80) ? false : true;
presp->enroll_update.img_overlay = buffer[1];
presp->enroll_update.img_preoverlay = buffer[2];
presp->enroll_update.rollback = (presp->result < 0x80) ? false : true;
if (!fpi_byte_reader_get_uint8 (byte_reader,
&presp->enroll_update.img_overlay))
g_return_val_if_reached (-1);
if (!fpi_byte_reader_get_uint8 (byte_reader,
&presp->enroll_update.img_preoverlay))
g_return_val_if_reached (-1);
break;
case MOC_CMD0_CHECK4DUPLICATE:
presp->check_duplicate_resp.duplicate = (presp->result == 0) ? false : true;
if (presp->check_duplicate_resp.duplicate)
{
if (buffer_len < 3)
return -1;
uint16_t tid_size = GUINT16_FROM_LE (*(uint16_t *) (buffer + 1));
offset += 3;
uint16_t tid_size;
FpiByteReader tid_reader;
if (buffer_len < tid_size + offset)
return -1;
if (gx_proto_parse_fingerid (buffer + offset, tid_size, &presp->check_duplicate_resp.template) != 0)
return -1;
if (!fpi_byte_reader_get_uint16_le (byte_reader, &tid_size))
g_return_val_if_reached (-1);
if (!fpi_byte_reader_get_sub_reader (byte_reader, &tid_reader, tid_size))
g_return_val_if_reached (-1);
if (gx_proto_parse_fingerid (&tid_reader, &presp->check_duplicate_resp.template) != 0)
g_return_val_if_reached (-1);
}
break;
case MOC_CMD0_GETFINGERLIST:
if (presp->result != GX_SUCCESS)
break;
if (buffer_len < 2)
return -1;
presp->finger_list_resp.finger_num = buffer[1];
fingerlist = buffer + 2;
if (!fpi_byte_reader_get_uint8 (byte_reader,
&presp->finger_list_resp.finger_num))
g_return_val_if_reached (-1);
for(uint8_t num = 0; num < presp->finger_list_resp.finger_num; num++)
{
uint16_t fingerid_length;
if (buffer_len < offset + 2)
return -1;
fingerid_length = GUINT16_FROM_LE (*(uint16_t *) (fingerlist + offset));
offset += 2;
if (buffer_len < fingerid_length + offset)
return -1;
if (gx_proto_parse_fingerid (fingerlist + offset,
fingerid_length,
FpiByteReader fingerid_reader;
if (!fpi_byte_reader_get_uint16_le (byte_reader, &fingerid_length))
g_return_val_if_reached (-1);
if (!fpi_byte_reader_get_sub_reader (byte_reader, &fingerid_reader,
fingerid_length))
g_return_val_if_reached (-1);
if (gx_proto_parse_fingerid (&fingerid_reader,
&presp->finger_list_resp.finger_list[num]) != 0)
{
g_error ("parse fingerlist error");
presp->finger_list_resp.finger_num = 0;
presp->result = GX_FAILED;
break;
g_warning ("Failed to parse finger list");
g_return_val_if_reached (-1);
}
offset += fingerid_length;
}
break;
@@ -407,23 +439,32 @@ gx_proto_parse_body (uint16_t cmd, uint8_t *buffer, uint16_t buffer_len, pgxfp_c
uint32_t score = 0;
uint8_t study = 0;
uint16_t fingerid_size = 0;
presp->verify.match = (buffer[0] == 0) ? true : false;
presp->verify.match = (presp->result == 0) ? true : false;
if (presp->verify.match)
{
if (buffer_len < 10)
return -1;
offset += 1;
presp->verify.rejectdetail = GUINT16_FROM_LE (*(uint16_t *) (buffer + offset));
offset += 2;
score = GUINT32_FROM_LE (*(uint32_t *) (buffer + offset));
offset += 4;
study = buffer[offset];
offset += 1;
fingerid_size = GUINT16_FROM_LE (*(uint16_t *) (buffer + offset));
offset += 2;
if (buffer_len < fingerid_size + offset)
return -1;
if (gx_proto_parse_fingerid (buffer + offset, fingerid_size, &presp->verify.template) != 0)
FpiByteReader finger_reader;
if (!fpi_byte_reader_get_uint16_le (byte_reader,
&presp->verify.rejectdetail))
g_return_val_if_reached (-1);
if (!fpi_byte_reader_get_uint32_le (byte_reader, &score))
g_return_val_if_reached (-1);
if (!fpi_byte_reader_get_uint8 (byte_reader, &study))
g_return_val_if_reached (-1);
if (!fpi_byte_reader_get_uint16_le (byte_reader, &fingerid_size))
g_return_val_if_reached (-1);
if (!fpi_byte_reader_get_sub_reader (byte_reader, &finger_reader,
fingerid_size))
g_return_val_if_reached (-1);
if (gx_proto_parse_fingerid (&finger_reader,
&presp->verify.template) != 0)
{
presp->result = GX_FAILED;
break;
@@ -434,7 +475,7 @@ gx_proto_parse_body (uint16_t cmd, uint8_t *buffer, uint16_t buffer_len, pgxfp_c
break;
case MOC_CMD0_FINGER_MODE:
presp->finger_status.status = buffer[0];
presp->finger_status.status = presp->result;
break;
default:
@@ -467,4 +508,4 @@ gx_proto_init_sensor_config (pgxfp_sensor_cfg_t pconfig)
memcpy (pconfig->crc_value, &crc32_calc, PACKAGE_CRC_SIZE);
return 0;
}
}

View File

@@ -22,6 +22,8 @@
#include <stdbool.h>
#include <string.h>
#include "fpi-byte-reader.h"
#define PACKAGE_CRC_SIZE (4)
#define PACKAGE_HEADER_SIZE (8)
@@ -105,10 +107,10 @@ typedef struct _gxfp_parse_msg
} gxfp_parse_msg_t, *pgxfp_parse_msg_t;
typedef struct _gxfp_enroll_init
typedef struct _gxfp_enroll_create
{
uint8_t tid[TEMPLATE_ID_SIZE];
} gxfp_enroll_init_t, *pgxfp_enroll_init_t;
} gxfp_enroll_create_t, *pgxfp_enroll_create_t;
#pragma pack(push, 1)
typedef struct _template_format
@@ -133,7 +135,7 @@ typedef struct _template_format
typedef struct _gxfp_verify
{
bool match;
uint32_t rejectdetail;
uint16_t rejectdetail;
template_format_t template;
} gxfp_verify_t, *pgxfp_verify_t;
@@ -192,7 +194,7 @@ typedef struct _fp_cmd_response
{
gxfp_parse_msg_t parse_msg;
gxfp_verify_t verify;
gxfp_enroll_init_t enroll_init;
gxfp_enroll_create_t enroll_create;
gxfp_capturedata_t capture_data_resp;
gxfp_check_duplicate_t check_duplicate_resp;
gxfp_enroll_commit_t enroll_commit;
@@ -232,13 +234,11 @@ int gx_proto_build_package (uint8_t *ppackage,
const uint8_t *payload,
uint32_t payload_size);
int gx_proto_parse_header (uint8_t *buffer,
uint32_t buffer_len,
pack_header *pheader);
int gx_proto_parse_header (FpiByteReader *reader,
pack_header *pheader);
int gx_proto_parse_body (uint16_t cmd,
uint8_t *buffer,
uint16_t buffer_len,
FpiByteReader *byte_reader,
pgxfp_cmd_response_t presponse);
int gx_proto_init_sensor_config (pgxfp_sensor_cfg_t pconfig);

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,246 @@
/*
* Copyright (C) 2022-2023 Realtek Corp.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#pragma once
#include "fpi-device.h"
#include "fpi-ssm.h"
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#define EP_IN (2 | FPI_USB_ENDPOINT_IN)
#define EP_OUT (1 | FPI_USB_ENDPOINT_OUT)
#define EP_IN_MAX_BUF_SIZE 2048
#define FP_RTK_CMD_BULK_TOTAL_LEN 12
#define FP_RTK_CMD_BULK_LEN 2
#define FP_RTK_CMD_BULK_PARAM_LEN 4
#define FP_RTK_CMD_BULK_ADDR_LEN 4
#define FP_RTK_CMD_BULK_DATA_LEN 2
#define TEMPLATE_LEN_COMMON 35
#define SUBFACTOR_OFFSET 2
#define UID_OFFSET 3
#define UID_PAYLOAD_LEN_DEFAULT 32
/* Command transfer timeout :ms*/
#define CMD_TIMEOUT 1000
#define DATA_TIMEOUT 5000
#define STATUS_TIMEOUT 2000
#define MAX_ENROLL_SAMPLES 8
#define DEFAULT_UID_LEN 28
#define SUB_FINGER_01 0xFF
#define GET_BULK_CMD_TYPE(val) ((val & 0xC0) >> 6)
#define GET_TRANS_DATA_LEN(len_h, len_l) ((len_h << 8) | len_l)
#define GET_LEN_L(total_data_len) ((total_data_len) & 0xff)
#define GET_LEN_H(total_data_len) ((total_data_len) >> 8)
G_DECLARE_FINAL_TYPE (FpiDeviceRealtek, fpi_device_realtek, FPI, DEVICE_REALTEK, FpDevice)
typedef void (*SynCmdMsgCallback) (FpiDeviceRealtek *self,
uint8_t *buffer_in,
GError *error);
typedef struct
{
SynCmdMsgCallback callback;
} CommandData;
typedef enum {
FP_RTK_CMD_BULK_ONLY = 0,
FP_RTK_CMD_BULK_READ,
FP_RTK_CMD_BULK_WRITE,
} FpRtkCmdType;
typedef enum {
FP_RTK_MSG_DEFAULT = 0,
FP_RTK_MSG_NO_STATUS,
} FpRtkMsgType;
typedef enum {
FP_RTK_PURPOSE_VERIFY = 0x01,
FP_RTK_PURPOSE_IDENTIFY = 0x02,
FP_RTK_PURPOSE_ENROLL = 0x04,
} FpRtkPurpose;
typedef enum {
FP_RTK_SUCCESS = 0x0,
FP_RTK_TOO_HIGH,
FP_RTK_TOO_LOW,
FP_RTK_TOO_LEFT,
FP_RTK_TOO_RIGHT,
FP_RTK_TOO_FAST,
FP_RTK_TOO_SLOW,
FP_RTK_POOR_QUALITY,
FP_RTK_TOO_SKEWED,
FP_RTK_TOO_SHORT,
FP_RTK_MERGE_FAILURE,
FP_RTK_MATCH_FAIL,
FP_RTK_CMD_ERR,
} FpRtkInStatus;
typedef enum {
FP_RTK_ENROLL_GET_TEMPLATE = 0,
FP_RTK_ENROLL_BEGIN_POS,
FP_RTK_ENROLL_CAPTURE,
FP_RTK_ENROLL_FINISH_CAPTURE,
FP_RTK_ENROLL_ACCEPT_SAMPLE,
FP_RTK_ENROLL_CHECK_DUPLICATE,
FP_RTK_ENROLL_COMMIT,
FP_RTK_ENROLL_CANCEL_CAPTURE,
FP_RTK_ENROLL_NUM_STATES,
} FpRtkEnrollState;
typedef enum {
FP_RTK_VERIFY_GET_TEMPLATE = 0,
FP_RTK_VERIFY_CAPTURE,
FP_RTK_VERIFY_FINISH_CAPTURE,
FP_RTK_VERIFY_ACCEPT_SAMPLE,
FP_RTK_VERIFY_INDENTIFY_FEATURE,
FP_RTK_VERIFY_UPDATE_TEMPLATE,
FP_RTK_VERIFY_CANCEL_CAPTURE,
FP_RTK_VERIFY_NUM_STATES,
} FpRtkVerifyState;
typedef enum {
FP_RTK_DELETE_GET_POS = 0,
FP_RTK_DELETE_PRINT,
FP_RTK_DELETE_NUM_STATES,
} FpRtkDeleteState;
typedef enum {
FP_RTK_INIT_GET_DEVICE_INFO = 0,
FP_RTK_INIT_SELECT_OS,
FP_RTK_INIT_GET_ENROLL_NUM,
FP_RTK_INIT_NUM_STATES,
} FpRtkInitState;
typedef enum {
FP_RTK_CMD_SEND = 0,
FP_RTK_CMD_TRANS_DATA,
FP_RTK_CMD_GET_STATUS,
FP_RTK_CMD_NUM_STATES,
} FpRtkCmdState;
struct _FpiDeviceRealtek
{
FpDevice parent;
FpiSsm *task_ssm;
FpiSsm *cmd_ssm;
FpiUsbTransfer *cmd_transfer;
FpiUsbTransfer *data_transfer;
gint cmd_type;
FpRtkMsgType message_type;
gboolean cmd_cancellable;
gint enroll_stage;
gint max_enroll_stage;
guchar *read_data;
gsize trans_data_len;
FpRtkPurpose fp_purpose;
gint pos_index;
gint template_num;
gint template_len;
};
struct rtk_cmd_bulk
{
uint8_t cmd[FP_RTK_CMD_BULK_LEN];
uint8_t param[FP_RTK_CMD_BULK_PARAM_LEN];
uint8_t addr[FP_RTK_CMD_BULK_ADDR_LEN];
uint8_t data_len[FP_RTK_CMD_BULK_DATA_LEN];
};
struct rtk_cmd_ctrl
{
int direction;
uint8_t request;
uint16_t value;
uint16_t index;
uint16_t len;
};
static struct rtk_cmd_ctrl get_device_info = {
.direction = G_USB_DEVICE_DIRECTION_DEVICE_TO_HOST,
.request = 0x07,
.value = 0x000D,
.index = 0x0000,
.len = 0x0008,
};
static struct rtk_cmd_bulk co_start_capture = {
.cmd = {0x05, 0x05},
};
static struct rtk_cmd_bulk co_finish_capture = {
.cmd = {0x45, 0x06},
.data_len = {0x05},
};
static struct rtk_cmd_bulk co_accept_sample = {
.cmd = {0x45, 0x08},
.data_len = {0x09},
};
static struct rtk_cmd_bulk nor_identify_feature = {
.cmd = {0x45, 0x22},
.data_len = {0x2A},
};
static struct rtk_cmd_bulk co_get_enroll_num = {
.cmd = {0x45, 0x0d},
.data_len = {0x02},
};
static struct rtk_cmd_bulk co_get_template = {
.cmd = {0x45, 0x0E},
};
static struct rtk_cmd_bulk nor_enroll_begin = {
.cmd = {0x05, 0x20},
};
static struct rtk_cmd_bulk co_check_duplicate = {
.cmd = {0x45, 0x10},
.data_len = {0x22},
};
static struct rtk_cmd_bulk nor_enroll_commit = {
.cmd = {0x85, 0x21},
};
static struct rtk_cmd_bulk co_update_template = {
.cmd = {0x05, 0x11},
};
static struct rtk_cmd_bulk co_delete_record = {
.cmd = {0x05, 0x0F},
};
static struct rtk_cmd_bulk co_select_system = {
.cmd = {0x05, 0x13},
};
static struct rtk_cmd_bulk co_cancel_capture = {
.cmd = {0x05, 0x07},
};

View File

@@ -256,7 +256,8 @@ bmkt_compose_message (uint8_t *cmd, int *cmd_len, uint8_t msg_id, uint8_t seq_nu
cmd[BMKT_MESSAGE_SEQ_NUM_FIELD] = seq_num;
cmd[BMKT_MESSAGE_ID_FIELD] = msg_id;
cmd[BMKT_MESSAGE_PAYLOAD_LEN_FIELD] = payload_size;
memcpy (&cmd[BMKT_MESSAGE_PAYLOAD_FIELD], payload, payload_size);
if (payload_size > 0)
memcpy (&cmd[BMKT_MESSAGE_PAYLOAD_FIELD], payload, payload_size);
*cmd_len = message_len;

View File

@@ -32,17 +32,32 @@ static void compose_and_send_identify_msg (FpDevice *device);
static const FpIdEntry id_table[] = {
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x00BD, },
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x00C2, },
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x00C4, },
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x00C6, },
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x00DF, },
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x00F0, },
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x00F9, },
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x00FC, },
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x00C2, },
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0100, },
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x00F0, },
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0103, },
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0104, },
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0106, },
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0107, },
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0108, },
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0109, },
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x010A, },
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0123, },
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0124, },
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0126, },
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0129, },
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x015F, },
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0168, },
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x016C, },
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0173, },
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0174, },
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x019D, },
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0x019F, },
{ .vid = 0, .pid = 0, .driver_data = 0 }, /* terminating entry */
};
@@ -104,7 +119,11 @@ cmd_receive_cb (FpiUsbTransfer *transfer,
if (self->cmd_complete_on_removal)
{
fpi_ssm_mark_completed (transfer->ssm);
if (self->delay_error)
fpi_ssm_mark_failed (transfer->ssm,
g_steal_pointer (&self->delay_error));
else
fpi_ssm_mark_completed (transfer->ssm);
return;
}
}
@@ -225,6 +244,7 @@ cmd_interrupt_cb (FpiUsbTransfer *transfer,
}
else
{
fpi_device_critical_leave (device);
fpi_usb_transfer_submit (fpi_usb_transfer_ref (transfer),
0,
NULL,
@@ -638,18 +658,21 @@ verify (FpDevice *device)
}
static void
identify_complete_after_finger_removal (FpiDeviceSynaptics *self)
identify_complete_after_finger_removal (FpiDeviceSynaptics *self, GError *error)
{
FpDevice *device = FP_DEVICE (self);
if (self->finger_on_sensor)
{
fp_dbg ("delaying identify report until after finger removal!");
if (error)
g_propagate_error (&self->delay_error, error);
self->cmd_complete_on_removal = TRUE;
}
else
{
fpi_device_identify_complete (device, NULL);
fpi_device_identify_complete (device, error);
}
}
@@ -699,19 +722,18 @@ identify_msg_cb (FpiDeviceSynaptics *self,
fp_info ("Match error occurred");
fpi_device_identify_report (device, NULL, NULL,
fpi_device_retry_new (FP_DEVICE_RETRY_GENERAL));
identify_complete_after_finger_removal (self);
identify_complete_after_finger_removal (self, NULL);
}
else if (resp->result == BMKT_FP_NO_MATCH)
{
fp_info ("Print didn't match");
fpi_device_identify_report (device, NULL, NULL, NULL);
identify_complete_after_finger_removal (self);
identify_complete_after_finger_removal (self, NULL);
}
else if (resp->result == BMKT_FP_DATABASE_NO_RECORD_EXISTS)
else if (resp->result == BMKT_FP_DATABASE_NO_RECORD_EXISTS || resp->result == BMKT_FP_DATABASE_EMPTY)
{
fp_info ("Print is not in database");
fpi_device_identify_complete (device,
fpi_device_error_new (FP_DEVICE_ERROR_DATA_NOT_FOUND));
identify_complete_after_finger_removal (self, fpi_device_error_new (FP_DEVICE_ERROR_DATA_NOT_FOUND));
}
else
{
@@ -747,7 +769,7 @@ identify_msg_cb (FpiDeviceSynaptics *self,
else
fpi_device_identify_report (device, NULL, print, NULL);
identify_complete_after_finger_removal (self);
identify_complete_after_finger_removal (self, NULL);
}
}
}
@@ -1235,6 +1257,12 @@ dev_probe (FpDevice *device)
return;
}
if (!g_usb_device_reset (usb_dev, &error))
{
fp_dbg ("%s g_usb_device_reset failed %s", G_STRFUNC, error->message);
goto err_close;
}
if (!g_usb_device_claim_interface (usb_dev, 0, 0, &error))
goto err_close;

View File

@@ -127,4 +127,5 @@ struct _FpiDeviceSynaptics
struct syna_enroll_resp_data enroll_resp_data;
syna_state_t state;
GError *delay_error;
};

View File

@@ -74,26 +74,26 @@ struct _FpiDeviceUpeksonly
FpiSsm *loopsm;
/* Do we really need multiple concurrent transfers? */
GCancellable *img_cancellable;
GPtrArray *img_transfers;
int num_flying;
GCancellable *img_cancellable;
GPtrArray *img_transfers;
int num_flying;
GSList *rows;
unsigned num_rows;
unsigned char *rowbuf;
int rowbuf_offset;
GSList *rows;
unsigned num_rows;
unsigned char *rowbuf;
int rowbuf_offset;
int wraparounds;
int num_blank;
int num_nonblank;
enum sonly_fs finger_state;
int last_seqnum;
int wraparounds;
int num_blank;
int num_nonblank;
enum sonly_fs finger_state;
int last_seqnum;
enum sonly_kill_transfers_action killing_transfers;
GError *kill_error;
FpiSsm *kill_ssm;
GError *kill_error;
FpiSsm *kill_ssm;
struct fpi_line_asmbl_ctx assembling_ctx;
struct fpi_line_asmbl_ctx assembling_ctx;
};
G_DECLARE_FINAL_TYPE (FpiDeviceUpeksonly, fpi_device_upeksonly, FPI,
DEVICE_UPEKSONLY, FpImageDevice);

View File

@@ -431,6 +431,7 @@ dev_deinit (FpImageDevice *dev)
static const FpIdEntry id_table[] = {
{ .vid = 0x0483, .pid = 0x2015, .driver_data = UPEKTC_2015 },
{ .vid = 0x0483, .pid = 0x2017, .driver_data = UPEKTC_2015 },
{ .vid = 0x147e, .pid = 0x3001, .driver_data = UPEKTC_3001 },
{ .vid = 0, .pid = 0, .driver_data = 0 },
};

View File

@@ -31,10 +31,6 @@ static void start_deactivation (FpImageDevice *dev);
#define CTRL_TIMEOUT 4000
#define BULK_TIMEOUT 4000
#define IMAGE_WIDTH 144
#define IMAGE_HEIGHT 384
#define IMAGE_SIZE (IMAGE_WIDTH * IMAGE_HEIGHT)
#define MAX_CMD_SIZE 64
#define MAX_RESPONSE_SIZE 2052
#define SHORT_RESPONSE_SIZE 64
@@ -47,8 +43,10 @@ struct _FpiDeviceUpektcImg
unsigned char response[MAX_RESPONSE_SIZE];
unsigned char *image_bits;
unsigned char seq;
size_t expected_image_size;
size_t image_size;
size_t response_rest;
gboolean area_sensor;
gboolean deactivating;
};
G_DECLARE_FINAL_TYPE (FpiDeviceUpektcImg, fpi_device_upektc_img, FPI,
@@ -180,6 +178,7 @@ capture_read_data_cb (FpiUsbTransfer *transfer, FpDevice *device,
gpointer user_data, GError *error)
{
FpImageDevice *dev = FP_IMAGE_DEVICE (device);
FpImageDeviceClass *img_class = FP_IMAGE_DEVICE_GET_CLASS (dev);
FpiDeviceUpektcImg *self = FPI_DEVICE_UPEKTC_IMG (dev);
unsigned char *data = self->response;
FpImage *img;
@@ -247,8 +246,30 @@ capture_read_data_cb (FpiUsbTransfer *transfer, FpDevice *device,
CAPTURE_ACK_00_28);
break;
case 0x13:
/* finger is present keep your finger on reader */
fpi_device_report_finger_status_changes (device,
FP_FINGER_STATUS_NEEDED,
FP_FINGER_STATUS_NONE);
fpi_ssm_jump_to_state (transfer->ssm,
self->area_sensor ?
CAPTURE_ACK_00_28 : CAPTURE_ACK_00_28_TERM);
break;
case 0x00:
/* finger is present! */
fpi_device_report_finger_status_changes (device,
FP_FINGER_STATUS_PRESENT,
FP_FINGER_STATUS_NONE);
fpi_ssm_jump_to_state (transfer->ssm,
CAPTURE_ACK_00_28);
break;
case 0x01:
/* no finger! */
fpi_device_report_finger_status_changes (device,
FP_FINGER_STATUS_NONE,
FP_FINGER_STATUS_PRESENT);
fpi_ssm_jump_to_state (transfer->ssm,
CAPTURE_ACK_00_28);
break;
@@ -261,18 +282,20 @@ capture_read_data_cb (FpiUsbTransfer *transfer, FpDevice *device,
fpi_image_device_report_finger_status (dev,
FALSE);
fpi_ssm_jump_to_state (transfer->ssm,
CAPTURE_ACK_00_28_TERM);
self->area_sensor ?
CAPTURE_ACK_00_28 : CAPTURE_ACK_00_28_TERM);
break;
case 0x1d:
/* too much horisontal movement */
fp_err ("too much horisontal movement, aborting");
/* too much horizontal movement */
fp_err ("too much horizontal movement, aborting");
fpi_image_device_retry_scan (dev,
FP_DEVICE_RETRY_CENTER_FINGER);
fpi_image_device_report_finger_status (dev,
FALSE);
fpi_ssm_jump_to_state (transfer->ssm,
CAPTURE_ACK_00_28_TERM);
self->area_sensor ?
CAPTURE_ACK_00_28 : CAPTURE_ACK_00_28_TERM);
break;
default:
@@ -283,7 +306,8 @@ capture_read_data_cb (FpiUsbTransfer *transfer, FpDevice *device,
fpi_image_device_report_finger_status (dev,
FALSE);
fpi_ssm_jump_to_state (transfer->ssm,
CAPTURE_ACK_00_28_TERM);
self->area_sensor ?
CAPTURE_ACK_00_28 : CAPTURE_ACK_00_28_TERM);
break;
}
break;
@@ -307,13 +331,13 @@ capture_read_data_cb (FpiUsbTransfer *transfer, FpDevice *device,
self->image_size +=
upektc_img_process_image_frame (self->image_bits + self->image_size,
data);
BUG_ON (self->image_size != IMAGE_SIZE);
BUG_ON (self->image_size != self->expected_image_size);
fp_dbg ("Image size is %lu",
(gulong) self->image_size);
img = fp_image_new (IMAGE_WIDTH, IMAGE_HEIGHT);
img = fp_image_new (img_class->img_width, img_class->img_height);
img->flags |= FPI_IMAGE_PARTIAL;
memcpy (img->data, self->image_bits,
IMAGE_SIZE);
self->image_size);
fpi_image_device_image_captured (dev, img);
fpi_image_device_report_finger_status (dev,
FALSE);
@@ -346,8 +370,12 @@ capture_run_state (FpiSsm *ssm, FpDevice *_dev)
switch (fpi_ssm_get_cur_state (ssm))
{
case CAPTURE_INIT_CAPTURE:
upektc_img_submit_req (ssm, dev, upek2020_init_capture, sizeof (upek2020_init_capture),
self->seq, capture_reqs_cb);
if (self->area_sensor)
upektc_img_submit_req (ssm, dev, upek2020_init_capture_press, sizeof (upek2020_init_capture_press),
self->seq, capture_reqs_cb);
else
upektc_img_submit_req (ssm, dev, upek2020_init_capture, sizeof (upek2020_init_capture),
self->seq, capture_reqs_cb);
self->seq++;
break;
@@ -513,15 +541,81 @@ init_reqs_cb (FpiUsbTransfer *transfer, FpDevice *device,
fpi_ssm_mark_failed (transfer->ssm, error);
}
/* TODO: process response properly */
static void
init_read_data_cb (FpiUsbTransfer *transfer, FpDevice *device,
gpointer user_data, GError *error)
{
if (!error)
fpi_ssm_next_state (transfer->ssm);
else
fpi_ssm_mark_failed (transfer->ssm, error);
FpImageDevice *dev = FP_IMAGE_DEVICE (device);
FpiDeviceUpektcImg *self = FPI_DEVICE_UPEKTC_IMG (dev);
unsigned char *data = self->response;
if (error)
{
fpi_ssm_mark_failed (transfer->ssm, error);
return;
}
if (data[12] == 0x06 && data[13] == 0x14) /* if get_info */
{
FpImageDeviceClass *img_class = FP_IMAGE_DEVICE_GET_CLASS (dev);
uint16_t width = (data[51] << 8) | data[50];
uint16_t height = (data[53] << 8) | data[52];
self->area_sensor = !(data[49] & 0x80);
switch (width)
{
case 256:
fp_dbg ("Sensor type : TCS1x, width x height: %hu x %hu", width, height); /* 360x256 --- 270x192 must be set */
BUG_ON (height != 360);
img_class->img_width = 192;
img_class->img_height = 270;
break;
case 208:
fp_dbg ("Sensor type : TCS2, width x height: %hu x %hu", width, height); /* 288x208 --- 216x156 must be set */
BUG_ON (height != 288);
img_class->img_width = 156;
img_class->img_height = 216;
break;
case 248:
fp_dbg ("Sensor type : TCS3, width x height: %hu x %hu", width, height); /* 360x248 --- 270x186 must be set */
BUG_ON (height != 360);
img_class->img_width = 186;
img_class->img_height = 270;
break;
case 192:
fp_dbg ("Sensor type : TCS4x, width x height: %hu x %hu", width, height); /* 512x192 --- 384x144 must be set */
BUG_ON (height != 512);
img_class->img_width = 144;
img_class->img_height = 384;
break;
case 144:
fp_dbg ("Sensor type : TCS5x, width x height: %hu x %hu", width, height); /* 512x144 --- 384x108 must be set */
BUG_ON (height != 512);
img_class->img_width = 108;
img_class->img_height = 384;
break;
default:
fp_dbg ("Sensor type : Unknown");
fpi_ssm_mark_failed (transfer->ssm,
fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
"Unknown sensor type (reported size %dx%d)",
width, height));
return;
}
self->expected_image_size = img_class->img_width * img_class->img_height;
self->image_bits = g_malloc0 (self->expected_image_size * 2);
}
fpi_ssm_next_state (transfer->ssm);
}
static void
@@ -616,7 +710,6 @@ dev_deactivate (FpImageDevice *dev)
static void
dev_init (FpImageDevice *dev)
{
FpiDeviceUpektcImg *self = FPI_DEVICE_UPEKTC_IMG (dev);
GError *error = NULL;
/* TODO check that device has endpoints we're using */
@@ -627,7 +720,6 @@ dev_init (FpImageDevice *dev)
return;
}
self->image_bits = g_malloc0 (IMAGE_SIZE * 2);
fpi_image_device_open_complete (dev, NULL);
}
@@ -687,6 +779,6 @@ fpi_device_upektc_img_class_init (FpiDeviceUpektcImgClass *klass)
img_class->bz3_threshold = 20;
img_class->img_width = IMAGE_WIDTH;
img_class->img_height = IMAGE_HEIGHT;
img_class->img_width = -1;
img_class->img_height = -1;
}

View File

@@ -75,6 +75,22 @@ static const unsigned char upek2020_init_capture[] = {
0x02,
0x00, /* Wait for acceptable finger */
0x02,
0x25, 0xa9 /* CRC */
};
static const unsigned char upek2020_init_capture_press[] = {
'C', 'i', 'a', 'o',
0x00,
0x00, 0x0e, /* Seq = 7, len = 0x00e */
0x28, /* CMD = 0x28 */
0x0b, 0x00, /* Inner len = 0x000b */
0x00, 0x00,
0x0e, /* SUBCMD = 0x0e */
0x02,
0xfe, 0xff, 0xff, 0xff, /* timeout = -2 = 0xfffffffe = infinite time */
0x02,
0x01, /* Wait for finger */
0x02,
0x14, 0x9a /* CRC */
};

View File

@@ -196,8 +196,9 @@ struct read_msg_data
static void __read_msg_async (FpDevice *dev,
struct read_msg_data *udata);
#define READ_MSG_DATA_CB_ERR(dev, udata, error) (udata)->callback (dev, \
READ_MSG_CMD, 0, 0, NULL, 0, (udata)->user_data, error)
#define READ_MSG_DATA_CB_ERR(dev, udata, error) \
(udata)->callback (dev, \
READ_MSG_CMD, 0, 0, NULL, 0, (udata)->user_data, error)
static void
busy_ack_sent_cb (FpiUsbTransfer *transfer, FpDevice *device,
@@ -1243,7 +1244,7 @@ do_verify_stop (FpDevice *dev, FpiMatchResult res, GError *error)
FpiSsm *ssm = deinitsm_new (dev, data);
/* Report the error immediately if possible, otherwise delay it. */
if (error && error->domain == FP_DEVICE_RETRY)
if (!error || error->domain == FP_DEVICE_RETRY)
fpi_device_verify_report (dev, res, NULL, error);
else
data->error = error;
@@ -1295,7 +1296,7 @@ verify_start_sm_run_state (FpiSsm *ssm, FpDevice *dev)
memcpy (msg, verify_hdr, sizeof (verify_hdr));
memcpy (msg + sizeof (verify_hdr), data, data_len);
transfer = alloc_send_cmd28_transfer (dev, 0x03, data, data_len);
transfer = alloc_send_cmd28_transfer (dev, 0x03, msg, msg_len);
g_free (msg);
@@ -1341,7 +1342,6 @@ v_handle_resp00 (FpDevice *dev, unsigned char *data,
fp_dbg ("good image");
break;
case 0x1c: /* FIXME what does this one mean? */
case 0x0b: /* FIXME what does this one mean? */
case 0x23: /* FIXME what does this one mean? */
error = fpi_device_retry_new (FP_DEVICE_RETRY_GENERAL);
@@ -1351,6 +1351,14 @@ v_handle_resp00 (FpDevice *dev, unsigned char *data,
error = fpi_device_retry_new (FP_DEVICE_RETRY_REMOVE_FINGER);
break;
case 0x1c: /* swipe too fast */
error = fpi_device_retry_new (FP_DEVICE_RETRY_TOO_FAST);
break;
case 0x1d: /* too much horizontal movement */
error = fpi_device_retry_new (FP_DEVICE_RETRY_CENTER_FINGER);
break;
case 0x1e: /* swipe too short */
error = fpi_device_retry_new (FP_DEVICE_RETRY_TOO_SHORT);
break;
@@ -1439,7 +1447,7 @@ verify_rd2800_cb (FpDevice *dev, enum read_msg_type msgtype,
do_verify_stop (dev,
FPI_MATCH_ERROR,
fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
"Response hat wrong command sequence"));
"Response had wrong command sequence"));
return;
}

View File

@@ -20,8 +20,8 @@
#define FP_COMPONENT "uru4000"
#include <nss.h>
#include <pk11pub.h>
#include <openssl/evp.h>
#include <openssl/err.h>
#include "drivers_api.h"
@@ -148,10 +148,7 @@ struct _FpiDeviceUru4000
int fwfixer_offset;
unsigned char fwfixer_value;
CK_MECHANISM_TYPE cipher;
PK11SlotInfo *slot;
PK11SymKey *symkey;
SECItem *param;
EVP_CIPHER_CTX *cipher_ctx;
};
G_DECLARE_FINAL_TYPE (FpiDeviceUru4000, fpi_device_uru4000, FPI, DEVICE_URU4000,
FpImageDevice);
@@ -246,13 +243,29 @@ response_cb (FpiUsbTransfer *transfer, FpDevice *dev, void *user_data, GError *e
fpi_ssm_mark_failed (ssm, error);
}
static GError *
openssl_device_error (void)
{
char buf[256];
unsigned long e;
e = ERR_get_error ();
if (e == 0)
return fpi_device_error_new_msg (FP_DEVICE_ERROR_GENERAL,
"unexpected OpenSSL error");
ERR_error_string_n (e, buf, G_N_ELEMENTS (buf));
return fpi_device_error_new_msg (FP_DEVICE_ERROR_GENERAL, "OpenSSL error: %s",
buf);
}
static void
challenge_cb (FpiUsbTransfer *transfer, FpDevice *dev, void *user_data, GError *error)
{
FpiSsm *ssm = user_data;
FpiDeviceUru4000 *self = FPI_DEVICE_URU4000 (dev);
unsigned char respdata[CR_LENGTH];
PK11Context *ctx;
unsigned char respdata[CR_LENGTH * 2];
int outlen;
if (error)
@@ -261,17 +274,39 @@ challenge_cb (FpiUsbTransfer *transfer, FpDevice *dev, void *user_data, GError *
return;
}
if (transfer->actual_length != CR_LENGTH)
{
error = fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
"Unexpected buffer length (%" G_GSIZE_FORMAT
"instead of %d)",
transfer->actual_length, CR_LENGTH);
fpi_ssm_mark_failed (ssm, g_steal_pointer (&error));
return;
}
/* submit response */
/* produce response from challenge */
ctx = PK11_CreateContextBySymKey (self->cipher, CKA_ENCRYPT,
self->symkey, self->param);
if (PK11_CipherOp (ctx, respdata, &outlen, CR_LENGTH, transfer->buffer, CR_LENGTH) != SECSuccess ||
PK11_Finalize (ctx) != SECSuccess)
if (!EVP_EncryptUpdate (self->cipher_ctx, respdata, &outlen, transfer->buffer, CR_LENGTH))
{
fp_err ("Failed to encrypt challenge data");
error = fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO, "Failed to encrypt challenge data");
fpi_ssm_mark_failed (ssm, openssl_device_error ());
return;
}
if (outlen != CR_LENGTH)
{
error = fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
"Unexpected encrypted buffer length (%d"
"instead of %d)",
outlen, CR_LENGTH);
fpi_ssm_mark_failed (ssm, g_steal_pointer (&error));
return;
}
if (!EVP_EncryptFinal_ex (self->cipher_ctx, respdata + outlen, &outlen))
{
fpi_ssm_mark_failed (ssm, openssl_device_error ());
return;
}
PK11_DestroyContext (ctx, PR_TRUE);
if (!error)
write_regs (FP_IMAGE_DEVICE (dev), REG_RESPONSE, CR_LENGTH, respdata, response_cb, ssm);
@@ -317,6 +352,7 @@ irq_handler (FpiUsbTransfer *transfer,
if (urudev->irqs_stopped_cb)
urudev->irqs_stopped_cb (imgdev);
urudev->irqs_stopped_cb = NULL;
g_clear_error (&error);
return;
}
else if (error)
@@ -551,7 +587,7 @@ image_transfer_cb (FpiUsbTransfer *transfer, FpDevice *dev,
}
else
{
self->img_data = g_memdup (transfer->buffer, sizeof (struct uru4k_image));
self->img_data = g_memdup2 (transfer->buffer, sizeof (struct uru4k_image));
self->img_data_actual_length = transfer->actual_length;
fpi_ssm_next_state (ssm);
}
@@ -702,9 +738,9 @@ imaging_run_state (FpiSsm *ssm, FpDevice *_dev)
case IMAGING_DECODE:
key = self->last_reg_rd[0];
key |= self->last_reg_rd[1] << 8;
key |= self->last_reg_rd[2] << 16;
key |= self->last_reg_rd[3] << 24;
key |= (uint32_t) self->last_reg_rd[1] << 8;
key |= (uint32_t) self->last_reg_rd[2] << 16;
key |= (uint32_t) self->last_reg_rd[3] << 24;
key ^= self->img_enc_seed;
fp_dbg ("encryption id %02x -> key %08x", img->key_number, key);
@@ -1269,8 +1305,6 @@ dev_init (FpImageDevice *dev)
g_autoptr(GPtrArray) interfaces = NULL;
GUsbInterface *iface = NULL;
guint64 driver_data;
SECStatus rv;
SECItem item;
int i;
interfaces = g_usb_device_get_interfaces (fpi_device_get_usb_device (FP_DEVICE (dev)), &error);
@@ -1342,20 +1376,6 @@ dev_init (FpImageDevice *dev)
return;
}
/* Disable loading p11-kit's user configuration */
g_setenv ("P11_KIT_NO_USER_CONFIG", "1", TRUE);
/* Initialise NSS early */
rv = NSS_NoDB_Init (".");
if (rv != SECSuccess)
{
fp_err ("could not initialise NSS");
fpi_image_device_open_complete (dev,
fpi_device_error_new_msg (FP_DEVICE_ERROR_GENERAL,
"Could not initialise NSS"));
return;
}
self = FPI_DEVICE_URU4000 (dev);
g_clear_pointer (&self->rand, g_rand_free);
@@ -1368,35 +1388,17 @@ dev_init (FpImageDevice *dev)
self->interface = g_usb_interface_get_number (iface);
/* Set up encryption */
self->cipher = CKM_AES_ECB;
self->slot = PK11_GetBestSlot (self->cipher, NULL);
if (self->slot == NULL)
if (!(self->cipher_ctx = EVP_CIPHER_CTX_new ()))
{
fp_err ("could not get encryption slot");
fpi_image_device_open_complete (dev,
fpi_device_error_new_msg (FP_DEVICE_ERROR_GENERAL,
"Could not get encryption slot"));
fpi_image_device_open_complete (dev, openssl_device_error ());
return;
}
item.type = siBuffer;
item.data = (unsigned char *) crkey;
item.len = sizeof (crkey);
self->symkey = PK11_ImportSymKey (self->slot,
self->cipher,
PK11_OriginUnwrap,
CKA_ENCRYPT,
&item, NULL);
if (self->symkey == NULL)
if (!EVP_EncryptInit_ex (self->cipher_ctx, EVP_aes_128_ecb (), NULL, crkey, NULL))
{
fp_err ("failed to import key into NSS");
PK11_FreeSlot (self->slot);
self->slot = NULL;
fpi_image_device_open_complete (dev,
fpi_device_error_new_msg (FP_DEVICE_ERROR_GENERAL,
"Failed to import key into NSS"));
fpi_image_device_open_complete (dev, openssl_device_error ());
return;
}
self->param = PK11_ParamFromIV (self->cipher, NULL);
fpi_image_device_open_complete (dev, NULL);
}
@@ -1407,12 +1409,8 @@ dev_deinit (FpImageDevice *dev)
GError *error = NULL;
FpiDeviceUru4000 *self = FPI_DEVICE_URU4000 (dev);
if (self->symkey)
PK11_FreeSymKey (self->symkey);
if (self->param)
SECITEM_FreeItem (self->param, PR_TRUE);
if (self->slot)
PK11_FreeSlot (self->slot);
g_clear_pointer (&self->cipher_ctx, EVP_CIPHER_CTX_free);
g_usb_device_release_interface (fpi_device_get_usb_device (FP_DEVICE (dev)),
self->interface, 0, &error);
g_clear_pointer (&self->rand, g_rand_free);

View File

@@ -581,7 +581,7 @@ activate_ssm (FpiSsm *ssm, FpDevice *dev)
/* Initialize fingerprint buffer */
g_free (self->lines_buffer);
self->memory = VFS_USB_BUFFER_SIZE;
self->lines_buffer = g_malloc (self->memory);
self->lines_buffer = g_malloc0 (self->memory);
self->bytes = 0;
/* Finger is on the scanner */
@@ -589,12 +589,15 @@ activate_ssm (FpiSsm *ssm, FpDevice *dev)
}
/* Increase buffer size while it's insufficient */
while (self->bytes + VFS_USB_BUFFER_SIZE > self->memory)
while (self->memory < self->bytes + VFS_USB_BUFFER_SIZE)
{
self->memory <<= 1;
int pre_memory = self->memory;
self->memory += VFS_USB_BUFFER_SIZE;
self->lines_buffer =
(struct vfs_line *) g_realloc (self->lines_buffer,
self->memory);
memset ((guint8 *) self->lines_buffer + pre_memory, 0,
VFS_USB_BUFFER_SIZE);
}
/* Receive chunk of data */

View File

@@ -432,7 +432,7 @@ img_process_data (int first_block, FpDeviceVfs301 *dev, const guint8 *buf, int l
usb_send (dev, data, len, NULL); \
}
#define RAW_DATA(x) g_memdup (x, sizeof (x)), sizeof (x)
#define RAW_DATA(x) g_memdup2 (x, sizeof (x)), sizeof (x)
#define IS_VFS301_FP_SEQ_START(b) ((b[0] == 0x01) && (b[1] == 0xfe))

View File

@@ -273,7 +273,8 @@ on_stream_read_cb (GObject *source_object,
}
else
{
// g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_INVALID_DATA, "Got empty data");
g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_INVALID_DATA,
"Got empty data");
return;
}
}

View File

@@ -526,8 +526,8 @@ dev_verify (FpDevice *dev)
if (scan_id)
{
g_autoptr(FpPrint) new_scan = NULL;
GVariant *data = NULL;
FpPrint *new_scan;
FpPrint *print;
gboolean success;
@@ -556,7 +556,7 @@ dev_verify (FpDevice *dev)
self->match_reported = TRUE;
fpi_device_verify_report (dev,
success ? FPI_MATCH_SUCCESS : FPI_MATCH_FAIL,
new_scan,
g_steal_pointer (&new_scan),
NULL);
}
}
@@ -733,7 +733,13 @@ dev_deinit (FpDevice *dev)
}
if (!self->keep_alive)
stop_listener (self);
{
stop_listener (self);
self->supports_cancellation = TRUE;
}
self->enroll_stages_passed = 0;
self->match_reported = FALSE;
fpi_device_close_complete (dev, NULL);
}
@@ -766,6 +772,7 @@ fpi_device_virtual_device_class_init (FpDeviceVirtualDeviceClass *klass)
{
FpDeviceClass *dev_class = FP_DEVICE_CLASS (klass);
GObjectClass *object_class = G_OBJECT_CLASS (klass);
const char *hot_seconds;
object_class->finalize = fpi_device_virtual_device_finalize;
@@ -781,5 +788,18 @@ fpi_device_virtual_device_class_init (FpDeviceVirtualDeviceClass *klass)
dev_class->enroll = dev_enroll;
dev_class->cancel = dev_cancel;
if ((hot_seconds = g_getenv ("FP_VIRTUAL_DEVICE_HOT_SECONDS")) &&
*hot_seconds != '\0')
{
gint64 hot_seconds_value;
hot_seconds_value = g_ascii_strtoll (hot_seconds, NULL, 10);
if (hot_seconds_value >= G_MAXINT32 || hot_seconds_value < 0)
hot_seconds_value = -1;
dev_class->temp_hot_seconds = hot_seconds_value;
g_debug ("device hot seconds set to %d", dev_class->temp_hot_seconds);
}
fpi_device_class_auto_initialize_features (dev_class);
}

View File

@@ -191,12 +191,12 @@ on_listener_connected (FpiDeviceVirtualListener *listener,
switch (state)
{
case FPI_IMAGE_DEVICE_STATE_IDLE:
case FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON:
case FPI_IMAGE_DEVICE_STATE_CAPTURE:
case FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_OFF:
recv_image (self);
case FPI_IMAGE_DEVICE_STATE_IDLE:
case FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_OFF:
case FPI_IMAGE_DEVICE_STATE_INACTIVE:
case FPI_IMAGE_DEVICE_STATE_ACTIVATING:
case FPI_IMAGE_DEVICE_STATE_DEACTIVATING:
@@ -310,6 +310,7 @@ fpi_device_virtual_image_class_init (FpDeviceVirtualImageClass *klass)
{
FpDeviceClass *dev_class = FP_DEVICE_CLASS (klass);
FpImageDeviceClass *img_class = FP_IMAGE_DEVICE_CLASS (klass);
const char *hot_seconds;
dev_class->id = FP_COMPONENT;
dev_class->full_name = "Virtual image device for debugging";
@@ -321,4 +322,17 @@ fpi_device_virtual_image_class_init (FpDeviceVirtualImageClass *klass)
img_class->activate = dev_activate;
img_class->deactivate = dev_deactivate;
if ((hot_seconds = g_getenv ("FP_VIRTUAL_IMAGE_HOT_SECONDS")) &&
*hot_seconds != '\0')
{
gint64 hot_seconds_value;
hot_seconds_value = g_ascii_strtoll (hot_seconds, NULL, 10);
if (hot_seconds_value >= G_MAXINT32 || hot_seconds_value < 0)
hot_seconds_value = -1;
dev_class->temp_hot_seconds = hot_seconds_value;
g_debug ("device hot seconds set to %d", dev_class->temp_hot_seconds);
}
}

View File

@@ -67,32 +67,26 @@ enum {
static guint signals[LAST_SIGNAL] = { 0 };
static const char *
get_drivers_whitelist_env (void)
get_drivers_allowlist_env (void)
{
return g_getenv ("FP_DRIVERS_WHITELIST");
return g_getenv ("FP_DRIVERS_ALLOWLIST");
}
static gboolean
is_driver_allowed (const gchar *driver)
{
g_auto(GStrv) whitelisted_drivers = NULL;
const char *fp_drivers_whitelist_env;
int i;
g_auto(GStrv) allowlisted_drivers = NULL;
const char *fp_drivers_allowlist_env;
g_return_val_if_fail (driver, TRUE);
fp_drivers_whitelist_env = get_drivers_whitelist_env ();
fp_drivers_allowlist_env = get_drivers_allowlist_env ();
if (!fp_drivers_whitelist_env)
if (!fp_drivers_allowlist_env)
return TRUE;
whitelisted_drivers = g_strsplit (fp_drivers_whitelist_env, ":", -1);
for (i = 0; whitelisted_drivers[i]; ++i)
if (g_strcmp0 (driver, whitelisted_drivers[i]) == 0)
return TRUE;
return FALSE;
allowlisted_drivers = g_strsplit (fp_drivers_allowlist_env, ":", -1);
return g_strv_contains ((const gchar * const *) allowlisted_drivers, driver);
}
typedef struct
@@ -291,11 +285,10 @@ fp_context_finalize (GObject *object)
FpContext *self = (FpContext *) object;
FpContextPrivate *priv = fp_context_get_instance_private (self);
g_clear_pointer (&priv->devices, g_ptr_array_unref);
g_cancellable_cancel (priv->cancellable);
g_clear_object (&priv->cancellable);
g_clear_pointer (&priv->drivers, g_array_unref);
g_clear_pointer (&priv->devices, g_ptr_array_unref);
g_slist_free_full (g_steal_pointer (&priv->sources), (GDestroyNotify) g_source_destroy);
@@ -365,7 +358,7 @@ fp_context_init (FpContext *self)
priv->drivers = fpi_get_driver_types ();
if (get_drivers_whitelist_env ())
if (get_drivers_allowlist_env ())
{
for (i = 0; i < priv->drivers->len;)
{

View File

@@ -44,7 +44,7 @@ typedef struct
FpDeviceType type;
GUsbDevice *usb_device;
const gchar *virtual_env;
gchar *virtual_env;
struct
{
gchar *spidev_path;
@@ -111,8 +111,6 @@ typedef struct
GDestroyNotify enroll_progress_destroy;
} FpEnrollData;
void enroll_data_free (FpEnrollData *enroll_data);
typedef struct
{
FpPrint *enrolled_print; /* verify */
@@ -128,7 +126,9 @@ typedef struct
GDestroyNotify match_destroy;
} FpMatchData;
void match_data_free (FpMatchData *match_data);
void fpi_device_suspend (FpDevice *device);
void fpi_device_resume (FpDevice *device);
void fpi_device_configure_wakeup (FpDevice *device,
gboolean enabled);

View File

@@ -292,14 +292,14 @@ fp_device_get_property (GObject *object,
case PROP_FPI_UDEV_DATA_SPIDEV:
if (cls->type == FP_DEVICE_TYPE_UDEV)
g_value_set_string (value, g_strdup (priv->udev_data.spidev_path));
g_value_set_string (value, priv->udev_data.spidev_path);
else
g_value_set_string (value, NULL);
break;
case PROP_FPI_UDEV_DATA_HIDRAW:
if (cls->type == FP_DEVICE_TYPE_UDEV)
g_value_set_string (value, g_strdup (priv->udev_data.hidraw_path));
g_value_set_string (value, priv->udev_data.hidraw_path);
else
g_value_set_string (value, NULL);
break;
@@ -949,16 +949,6 @@ fp_device_close_finish (FpDevice *device,
return g_task_propagate_boolean (G_TASK (result), error);
}
static void
complete_suspend_resume_task (FpDevice *device)
{
FpDevicePrivate *priv = fp_device_get_instance_private (device);
g_assert (priv->suspend_resume_task);
g_task_return_boolean (g_steal_pointer (&priv->suspend_resume_task), TRUE);
}
/**
* fp_device_suspend:
* @device: a #FpDevice
@@ -1009,48 +999,7 @@ fp_device_suspend (FpDevice *device,
priv->suspend_resume_task = g_steal_pointer (&task);
/* If the device is currently idle, just complete immediately.
* For long running tasks, call the driver handler right away, for short
* tasks, wait for completion and then return the task.
*/
switch (priv->current_action)
{
case FPI_DEVICE_ACTION_NONE:
fpi_device_suspend_complete (device, NULL);
break;
case FPI_DEVICE_ACTION_ENROLL:
case FPI_DEVICE_ACTION_VERIFY:
case FPI_DEVICE_ACTION_IDENTIFY:
case FPI_DEVICE_ACTION_CAPTURE:
if (FP_DEVICE_GET_CLASS (device)->suspend)
{
if (priv->critical_section)
priv->suspend_queued = TRUE;
else
FP_DEVICE_GET_CLASS (device)->suspend (device);
}
else
{
fpi_device_suspend_complete (device, fpi_device_error_new (FP_DEVICE_ERROR_NOT_SUPPORTED));
}
break;
default:
case FPI_DEVICE_ACTION_PROBE:
case FPI_DEVICE_ACTION_OPEN:
case FPI_DEVICE_ACTION_CLOSE:
case FPI_DEVICE_ACTION_DELETE:
case FPI_DEVICE_ACTION_LIST:
case FPI_DEVICE_ACTION_CLEAR_STORAGE:
g_signal_connect_object (priv->current_task,
"notify::completed",
G_CALLBACK (complete_suspend_resume_task),
device,
G_CONNECT_SWAPPED);
break;
}
fpi_device_suspend (device);
}
/**
@@ -1115,41 +1064,7 @@ fp_device_resume (FpDevice *device,
priv->suspend_resume_task = g_steal_pointer (&task);
switch (priv->current_action)
{
case FPI_DEVICE_ACTION_NONE:
fpi_device_resume_complete (device, NULL);
break;
case FPI_DEVICE_ACTION_ENROLL:
case FPI_DEVICE_ACTION_VERIFY:
case FPI_DEVICE_ACTION_IDENTIFY:
case FPI_DEVICE_ACTION_CAPTURE:
if (FP_DEVICE_GET_CLASS (device)->resume)
{
if (priv->critical_section)
priv->resume_queued = TRUE;
else
FP_DEVICE_GET_CLASS (device)->resume (device);
}
else
{
fpi_device_resume_complete (device, fpi_device_error_new (FP_DEVICE_ERROR_NOT_SUPPORTED));
}
break;
default:
case FPI_DEVICE_ACTION_PROBE:
case FPI_DEVICE_ACTION_OPEN:
case FPI_DEVICE_ACTION_CLOSE:
case FPI_DEVICE_ACTION_DELETE:
case FPI_DEVICE_ACTION_LIST:
case FPI_DEVICE_ACTION_CLEAR_STORAGE:
/* cannot happen as we make sure these tasks complete before suspend */
g_assert_not_reached ();
complete_suspend_resume_task (device);
break;
}
fpi_device_resume (device);
}
/**
@@ -1173,14 +1088,23 @@ fp_device_resume_finish (FpDevice *device,
return g_task_propagate_boolean (G_TASK (result), error);
}
static void
enroll_data_free (FpEnrollData *data)
{
if (data->enroll_progress_destroy)
data->enroll_progress_destroy (data->enroll_progress_data);
data->enroll_progress_data = NULL;
g_clear_object (&data->print);
g_free (data);
}
/**
* fp_device_enroll:
* @device: a #FpDevice
* @template_print: (transfer floating): a #FpPrint
* @cancellable: (nullable): a #GCancellable, or %NULL
* @progress_cb: (nullable) (scope notified): progress reporting callback
* @progress_data: (closure progress_cb): user data for @progress_cb
* @progress_cb: (nullable) (closure progress_data) (scope notified): progress reporting callback
* @progress_data: user data for @progress_cb
* @progress_destroy: (destroy progress_data): Destroy notify for @progress_data
* @callback: (scope async): the function to call on completion
* @user_data: the data to pass to @callback
@@ -1257,10 +1181,6 @@ fp_device_enroll (FpDevice *device,
}
}
priv->current_action = FPI_DEVICE_ACTION_ENROLL;
priv->current_task = g_steal_pointer (&task);
setup_task_cancellable (device);
fpi_device_update_temp (device, TRUE);
if (priv->temp_current == FP_TEMPERATURE_HOT)
{
@@ -1269,6 +1189,10 @@ fp_device_enroll (FpDevice *device,
return;
}
priv->current_action = FPI_DEVICE_ACTION_ENROLL;
priv->current_task = g_steal_pointer (&task);
setup_task_cancellable (device);
data = g_new0 (FpEnrollData, 1);
data->print = g_object_ref_sink (template_print);
data->enroll_progress_cb = progress_cb;
@@ -1302,13 +1226,30 @@ fp_device_enroll_finish (FpDevice *device,
return g_task_propagate_pointer (G_TASK (result), error);
}
static void
match_data_free (FpMatchData *data)
{
g_clear_object (&data->print);
g_clear_object (&data->match);
g_clear_error (&data->error);
if (data->match_destroy)
data->match_destroy (data->match_data);
data->match_data = NULL;
g_clear_object (&data->enrolled_print);
g_clear_pointer (&data->gallery, g_ptr_array_unref);
g_free (data);
}
/**
* fp_device_verify:
* @device: a #FpDevice
* @enrolled_print: a #FpPrint to verify
* @cancellable: (nullable): a #GCancellable, or %NULL
* @match_cb: (nullable) (scope notified): match reporting callback
* @match_data: (closure match_cb): user data for @match_cb
* @match_cb: (nullable) (scope notified) (closure match_data): match reporting callback
* @match_data: user data for @match_cb
* @match_destroy: (destroy match_data): Destroy notify for @match_data
* @callback: the function to call on completion
* @user_data: the data to pass to @callback
@@ -1358,10 +1299,6 @@ fp_device_verify (FpDevice *device,
return;
}
priv->current_action = FPI_DEVICE_ACTION_VERIFY;
priv->current_task = g_steal_pointer (&task);
setup_task_cancellable (device);
fpi_device_update_temp (device, TRUE);
if (priv->temp_current == FP_TEMPERATURE_HOT)
{
@@ -1370,6 +1307,10 @@ fp_device_verify (FpDevice *device,
return;
}
priv->current_action = FPI_DEVICE_ACTION_VERIFY;
priv->current_task = g_steal_pointer (&task);
setup_task_cancellable (device);
data = g_new0 (FpMatchData, 1);
data->enrolled_print = g_object_ref (enrolled_print);
data->match_cb = match_cb;
@@ -1433,8 +1374,8 @@ fp_device_verify_finish (FpDevice *device,
* @device: a #FpDevice
* @prints: (element-type FpPrint) (transfer none): #GPtrArray of #FpPrint
* @cancellable: (nullable): a #GCancellable, or %NULL
* @match_cb: (nullable) (scope notified): match reporting callback
* @match_data: (closure match_cb): user data for @match_cb
* @match_cb: (nullable) (scope notified) (closure match_data): match reporting callback
* @match_data: user data for @match_cb
* @match_destroy: (destroy match_data): Destroy notify for @match_data
* @callback: the function to call on completion
* @user_data: the data to pass to @callback
@@ -1485,9 +1426,13 @@ fp_device_identify (FpDevice *device,
return;
}
priv->current_action = FPI_DEVICE_ACTION_IDENTIFY;
priv->current_task = g_steal_pointer (&task);
setup_task_cancellable (device);
if (prints == NULL)
{
g_task_return_error (task,
fpi_device_error_new_msg (FP_DEVICE_ERROR_DATA_INVALID,
"Invalid gallery array"));
return;
}
fpi_device_update_temp (device, TRUE);
if (priv->temp_current == FP_TEMPERATURE_HOT)
@@ -1497,6 +1442,10 @@ fp_device_identify (FpDevice *device,
return;
}
priv->current_action = FPI_DEVICE_ACTION_IDENTIFY;
priv->current_task = g_steal_pointer (&task);
setup_task_cancellable (device);
data = g_new0 (FpMatchData, 1);
/* We cannot store the gallery directly, because the ptr array may not own
* a reference to each print. Also, the caller could in principle modify the
@@ -1610,10 +1559,6 @@ fp_device_capture (FpDevice *device,
return;
}
priv->current_action = FPI_DEVICE_ACTION_CAPTURE;
priv->current_task = g_steal_pointer (&task);
setup_task_cancellable (device);
fpi_device_update_temp (device, TRUE);
if (priv->temp_current == FP_TEMPERATURE_HOT)
{
@@ -1622,6 +1567,10 @@ fp_device_capture (FpDevice *device,
return;
}
priv->current_action = FPI_DEVICE_ACTION_CAPTURE;
priv->current_task = g_steal_pointer (&task);
setup_task_cancellable (device);
priv->wait_for_finger = wait_for_finger;
cls->capture (device);
@@ -1994,8 +1943,8 @@ fp_device_enroll_sync (FpDevice *device,
* @device: a #FpDevice
* @enrolled_print: a #FpPrint to verify
* @cancellable: (nullable): a #GCancellable, or %NULL
* @match_cb: (nullable) (scope call): match reporting callback
* @match_data: (closure match_cb): user data for @match_cb
* @match_cb: (nullable) (scope call) (closure match_data): match reporting callback
* @match_data: user data for @match_cb
* @match: (out): Whether the user presented the correct finger
* @print: (out) (transfer full) (nullable): Location to store the scanned print, or %NULL to ignore
* @error: Return location for errors, or %NULL to ignore
@@ -2034,8 +1983,8 @@ fp_device_verify_sync (FpDevice *device,
* @device: a #FpDevice
* @prints: (element-type FpPrint) (transfer none): #GPtrArray of #FpPrint
* @cancellable: (nullable): a #GCancellable, or %NULL
* @match_cb: (nullable) (scope call): match reporting callback
* @match_data: (closure match_cb): user data for @match_cb
* @match_cb: (nullable) (scope call) (closure match_data): match reporting callback
* @match_data: user data for @match_cb
* @match: (out) (transfer full) (nullable): Location for the matched #FpPrint, or %NULL
* @print: (out) (transfer full) (nullable): Location for the new #FpPrint, or %NULL
* @error: Return location for errors, or %NULL to ignore

View File

@@ -113,6 +113,8 @@ typedef enum {
* @FP_DEVICE_RETRY_REMOVE_FINGER: The scan did not succeed due to quality or
* pressure problems; the user should remove their finger from the scanner
* before retrying.
* @FP_DEVICE_RETRY_TOO_FAST: The scan did not succeed because the finger
* swipe or touch was too fast.
*
* Error codes representing scan failures resulting in the user needing to
* retry.
@@ -122,6 +124,7 @@ typedef enum {
FP_DEVICE_RETRY_TOO_SHORT,
FP_DEVICE_RETRY_CENTER_FINGER,
FP_DEVICE_RETRY_REMOVE_FINGER,
FP_DEVICE_RETRY_TOO_FAST,
} FpDeviceRetry;
/**

View File

@@ -20,9 +20,11 @@
#define FP_COMPONENT "image"
#include "fpi-compat.h"
#include "fpi-image.h"
#include "fpi-log.h"
#include <config.h>
#include <nbis.h>
/**
@@ -158,60 +160,65 @@ fp_image_init (FpImage *self)
typedef struct
{
GAsyncReadyCallback user_cb;
struct fp_minutiae *minutiae;
gint width, height;
gdouble ppmm;
FpiImageFlags flags;
guchar *image;
guchar *binarized;
} DetectMinutiaeData;
FpiImageFlags flags;
unsigned char *image;
gboolean image_changed;
} DetectMinutiaeNbisData;
static void
fp_image_detect_minutiae_free (DetectMinutiaeData *data)
fp_image_detect_minutiae_free (DetectMinutiaeNbisData *data)
{
g_clear_pointer (&data->image, g_free);
g_clear_pointer (&data->minutiae, free_minutiae);
g_clear_pointer (&data->binarized, g_free);
if (data->image_changed)
g_clear_pointer (&data->image, g_free);
g_free (data);
}
static void
fp_image_detect_minutiae_cb (GObject *source_object,
GAsyncResult *res,
gpointer user_data)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (DetectMinutiaeNbisData, fp_image_detect_minutiae_free)
static gboolean
fp_image_detect_minutiae_nbis_finish (FpImage *self,
GTask *task,
GError **error)
{
GTask *task = G_TASK (res);
FpImage *image;
DetectMinutiaeData *data = g_task_get_task_data (task);
g_autoptr(DetectMinutiaeNbisData) data = NULL;
if (!g_task_had_error (task))
data = g_task_propagate_pointer (task, error);
if (data != NULL)
{
gint i;
image = FP_IMAGE (source_object);
self->flags = data->flags;
image->flags = data->flags;
if (data->image_changed)
{
g_clear_pointer (&self->data, g_free);
self->data = g_steal_pointer (&data->image);
}
g_clear_pointer (&image->data, g_free);
image->data = g_steal_pointer (&data->image);
g_clear_pointer (&self->binarized, g_free);
self->binarized = g_steal_pointer (&data->binarized);
g_clear_pointer (&image->binarized, g_free);
image->binarized = g_steal_pointer (&data->binarized);
g_clear_pointer (&self->minutiae, g_ptr_array_unref);
self->minutiae = g_ptr_array_new_full (data->minutiae->num,
(GDestroyNotify) free_minutia);
g_clear_pointer (&image->minutiae, g_ptr_array_unref);
image->minutiae = g_ptr_array_new_full (data->minutiae->num,
(GDestroyNotify) free_minutia);
for (i = 0; i < data->minutiae->num; i++)
g_ptr_array_add (image->minutiae,
for (int i = 0; i < data->minutiae->num; i++)
g_ptr_array_add (self->minutiae,
g_steal_pointer (&data->minutiae->list[i]));
/* Don't let it delete anything. */
/* Don't let free_minutiae delete the minutiae that we now own. */
data->minutiae->num = 0;
return TRUE;
}
if (data->user_cb)
data->user_cb (source_object, res, user_data);
return FALSE;
}
static void
@@ -264,70 +271,83 @@ invert_colors (guint8 *data, gint width, gint height)
}
static void
fp_image_detect_minutiae_thread_func (GTask *task,
gpointer source_object,
gpointer task_data,
GCancellable *cancellable)
fp_image_detect_minutiae_nbis_thread_func (GTask *task,
gpointer source_object,
gpointer task_data,
GCancellable *cancellable)
{
g_autoptr(GTimer) timer = NULL;
DetectMinutiaeData *data = task_data;
struct fp_minutiae *minutiae = NULL;
g_autoptr(DetectMinutiaeNbisData) ret_data = NULL;
g_autoptr(GTask) thread_task = g_steal_pointer (&task);
g_autofree gint *direction_map = NULL;
g_autofree gint *low_contrast_map = NULL;
g_autofree gint *low_flow_map = NULL;
g_autofree gint *high_curve_map = NULL;
g_autofree gint *quality_map = NULL;
g_autofree guchar *bdata = NULL;
g_autofree LFSPARMS *lfsparms = NULL;
FpImage *self = source_object;
FpiImageFlags minutiae_flags;
unsigned char *image;
gint map_w, map_h;
gint bw, bh, bd;
gint r;
g_autofree LFSPARMS *lfsparms = NULL;
image = self->data;
minutiae_flags = self->flags & ~(FPI_IMAGE_H_FLIPPED |
FPI_IMAGE_V_FLIPPED |
FPI_IMAGE_COLORS_INVERTED);
if (minutiae_flags != FPI_IMAGE_NONE)
image = g_memdup2 (self->data, self->width * self->height);
ret_data = g_new0 (DetectMinutiaeNbisData, 1);
ret_data->flags = minutiae_flags;
ret_data->image = image;
ret_data->image_changed = image != self->data;
/* Normalize the image first */
if (data->flags & FPI_IMAGE_H_FLIPPED)
hflip (data->image, data->width, data->height);
if (self->flags & FPI_IMAGE_H_FLIPPED)
hflip (image, self->width, self->height);
if (data->flags & FPI_IMAGE_V_FLIPPED)
vflip (data->image, data->width, data->height);
if (self->flags & FPI_IMAGE_V_FLIPPED)
vflip (image, self->width, self->height);
if (data->flags & FPI_IMAGE_COLORS_INVERTED)
invert_colors (data->image, data->width, data->height);
if (self->flags & FPI_IMAGE_COLORS_INVERTED)
invert_colors (image, self->width, self->height);
data->flags &= ~(FPI_IMAGE_H_FLIPPED | FPI_IMAGE_V_FLIPPED | FPI_IMAGE_COLORS_INVERTED);
lfsparms = g_memdup (&g_lfsparms_V2, sizeof (LFSPARMS));
lfsparms->remove_perimeter_pts = data->flags & FPI_IMAGE_PARTIAL ? TRUE : FALSE;
lfsparms = g_memdup2 (&g_lfsparms_V2, sizeof (LFSPARMS));
lfsparms->remove_perimeter_pts = minutiae_flags & FPI_IMAGE_PARTIAL ? TRUE : FALSE;
timer = g_timer_new ();
r = get_minutiae (&minutiae, &quality_map, &direction_map,
r = get_minutiae (&ret_data->minutiae, &quality_map, &direction_map,
&low_contrast_map, &low_flow_map, &high_curve_map,
&map_w, &map_h, &bdata, &bw, &bh, &bd,
data->image, data->width, data->height, 8,
data->ppmm, lfsparms);
&map_w, &map_h, &ret_data->binarized, &bw, &bh, &bd,
image, self->width, self->height, 8,
self->ppmm, lfsparms);
g_timer_stop (timer);
fp_dbg ("Minutiae scan completed in %f secs", g_timer_elapsed (timer, NULL));
data->binarized = g_steal_pointer (&bdata);
data->minutiae = minutiae;
if (g_task_had_error (thread_task))
return;
if (r)
{
fp_err ("get minutiae failed, code %d", r);
g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_FAILED, "Minutiae scan failed with code %d", r);
g_object_unref (task);
g_task_return_new_error (thread_task, G_IO_ERROR,
G_IO_ERROR_FAILED,
"Minutiae scan failed with code %d", r);
return;
}
if (!data->minutiae || data->minutiae->num == 0)
if (!ret_data->minutiae || ret_data->minutiae->num == 0)
{
g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_FAILED,
g_task_return_new_error (thread_task, G_IO_ERROR, G_IO_ERROR_FAILED,
"No minutiae found");
g_object_unref (task);
return;
}
g_task_return_boolean (task, TRUE);
g_object_unref (task);
g_task_return_pointer (thread_task, g_steal_pointer (&ret_data),
(GDestroyNotify) fp_image_detect_minutiae_free);
}
/**
@@ -443,21 +463,25 @@ fp_image_detect_minutiae (FpImage *self,
GAsyncReadyCallback callback,
gpointer user_data)
{
GTask *task;
DetectMinutiaeData *data = g_new0 (DetectMinutiaeData, 1);
g_autoptr(GTask) task = NULL;
task = g_task_new (self, cancellable, fp_image_detect_minutiae_cb, user_data);
g_return_if_fail (FP_IS_IMAGE (self));
g_return_if_fail (callback != NULL);
data->image = g_malloc (self->width * self->height);
memcpy (data->image, self->data, self->width * self->height);
data->flags = self->flags;
data->width = self->width;
data->height = self->height;
data->ppmm = self->ppmm;
data->user_cb = callback;
task = g_task_new (self, cancellable, callback, user_data);
g_task_set_source_tag (task, fp_image_detect_minutiae);
g_task_set_check_cancellable (task, TRUE);
g_task_set_task_data (task, data, (GDestroyNotify) fp_image_detect_minutiae_free);
g_task_run_in_thread (task, fp_image_detect_minutiae_thread_func);
if (!g_atomic_int_compare_and_exchange (&self->detection_in_progress,
FALSE, TRUE))
{
g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_ADDRESS_IN_USE,
"Minutiae detection is already in progress");
return;
}
g_task_run_in_thread (g_steal_pointer (&task),
fp_image_detect_minutiae_nbis_thread_func);
}
/**
@@ -475,7 +499,27 @@ fp_image_detect_minutiae_finish (FpImage *self,
GAsyncResult *result,
GError **error)
{
return g_task_propagate_boolean (G_TASK (result), error);
GTask *task;
gboolean changed;
g_return_val_if_fail (FP_IS_IMAGE (self), FALSE);
g_return_val_if_fail (g_task_is_valid (result, self), FALSE);
g_return_val_if_fail (g_task_get_source_tag (G_TASK (result)) ==
fp_image_detect_minutiae, FALSE);
task = G_TASK (result);
changed = g_atomic_int_compare_and_exchange (&self->detection_in_progress,
TRUE, FALSE);
g_assert (changed);
if (g_task_had_error (task))
{
gpointer data = g_task_propagate_pointer (task, error);
g_assert (data == NULL);
return FALSE;
}
return fp_image_detect_minutiae_nbis_finish (self, task, error);
}
/**

View File

@@ -339,7 +339,7 @@ fp_print_init (FpPrint *self)
* create a new print, fill in the relevant metadata, and then start
* enrollment.
*
* Returns: (transfer floating): A newyl created #FpPrint
* Returns: (transfer floating): A newly created #FpPrint
*/
FpPrint *
fp_print_new (FpDevice *device)
@@ -721,13 +721,12 @@ fp_print_serialize (FpPrint *print,
result = g_variant_builder_end (&builder);
if (G_BYTE_ORDER == G_BIG_ENDIAN)
{
GVariant *tmp;
tmp = g_variant_byteswap (result);
g_variant_unref (result);
result = tmp;
}
#if (G_BYTE_ORDER == G_BIG_ENDIAN)
GVariant *tmp;
tmp = g_variant_byteswap (result);
g_variant_unref (result);
result = tmp;
#endif
len = g_variant_get_size (result);
/* Add 3 bytes of header */
@@ -800,10 +799,11 @@ fp_print_deserialize (const guchar *data,
if (!raw_value)
goto invalid_format;
if (G_BYTE_ORDER == G_BIG_ENDIAN)
value = g_variant_byteswap (raw_value);
else
value = g_variant_get_normal_form (raw_value);
#if (G_BYTE_ORDER == G_BIG_ENDIAN)
value = g_variant_byteswap (raw_value);
#else
value = g_variant_get_normal_form (raw_value);
#endif
g_variant_get (value,
"(i&s&sbymsmsi@a{sv}v)",

View File

@@ -1181,7 +1181,7 @@ fpi_byte_reader_dup_string_utf##bits (FpiByteReader * reader, type ** str) \
*str = NULL; \
return FALSE; \
} \
*str = g_memdup (reader->data + reader->byte, size); \
*str = g_memdup2 (reader->data + reader->byte, size); \
reader->byte += size; \
return TRUE; \
}

View File

@@ -22,6 +22,7 @@
#pragma once
#include <glib.h>
#include "fpi-compat.h"
#include "fpi-byte-utils.h"
G_BEGIN_DECLS
@@ -360,7 +361,7 @@ static inline guint8 *
fpi_byte_reader_dup_data_unchecked (FpiByteReader * reader, guint size)
{
gconstpointer data = fpi_byte_reader_get_data_unchecked (reader, size);
return (guint8 *) g_memdup (data, size);
return (guint8 *) g_memdup2 (data, size);
}
/* Unchecked variants that should not be used */
@@ -674,4 +675,6 @@ fpi_byte_reader_skip_inline (FpiByteReader * reader, guint nbytes)
#endif /* FPI_BYTE_READER_DISABLE_INLINES */
G_DEFINE_AUTOPTR_CLEANUP_FUNC (FpiByteReader, fpi_byte_reader_free);
G_END_DECLS

View File

@@ -75,7 +75,8 @@ fpi_byte_writer_new_with_size (guint size, gboolean fixed)
FpiByteWriter *ret = fpi_byte_writer_new ();
ret->alloc_size = size;
ret->parent.data = g_malloc (ret->alloc_size);
ret->parent.data = g_malloc0 (ret->alloc_size);
ret->parent.size = size;
ret->fixed = fixed;
ret->owned = TRUE;
@@ -142,7 +143,8 @@ fpi_byte_writer_init_with_size (FpiByteWriter * writer, guint size,
fpi_byte_writer_init (writer);
writer->parent.data = g_malloc (size);
writer->parent.data = g_malloc0 (size);
writer->parent.size = size;
writer->alloc_size = size;
writer->fixed = fixed;
writer->owned = TRUE;
@@ -209,10 +211,9 @@ fpi_byte_writer_reset_and_get_data (FpiByteWriter * writer)
g_return_val_if_fail (writer != NULL, NULL);
data = (guint8 *) writer->parent.data;
data = (guint8 *) g_steal_pointer (&writer->parent.data);
if (!writer->owned)
data = g_memdup (data, writer->parent.size);
writer->parent.data = NULL;
data = g_memdup2 (data, writer->parent.size);
fpi_byte_writer_reset (writer);
return data;

View File

@@ -111,6 +111,17 @@ fpi_byte_writer_set_pos (FpiByteWriter *writer, guint pos)
return fpi_byte_reader_set_pos (FPI_BYTE_READER (writer), pos);
}
static inline gboolean
fpi_byte_writer_change_pos (FpiByteWriter *writer, gint pos)
{
pos = fpi_byte_writer_get_pos (writer) + pos;
if (pos < 0)
return FALSE;
return fpi_byte_reader_set_pos (FPI_BYTE_READER (writer), pos);
}
static inline guint
fpi_byte_writer_get_size (const FpiByteWriter *writer)
{
@@ -407,4 +418,7 @@ fpi_byte_writer_fill_inline (FpiByteWriter * writer, guint8 value, guint size)
#endif
G_DEFINE_AUTOPTR_CLEANUP_FUNC (FpiByteWriter, fpi_byte_writer_free);
G_DEFINE_AUTO_CLEANUP_CLEAR_FUNC (FpiByteWriter, fpi_byte_writer_reset);
G_END_DECLS

View File

@@ -20,25 +20,6 @@
#include <glib-object.h>
#if !GLIB_CHECK_VERSION (2, 57, 0)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (GTypeClass, g_type_class_unref);
G_DEFINE_AUTOPTR_CLEANUP_FUNC (GEnumClass, g_type_class_unref);
G_DEFINE_AUTOPTR_CLEANUP_FUNC (GFlagsClass, g_type_class_unref);
G_DEFINE_AUTOPTR_CLEANUP_FUNC (GParamSpec, g_param_spec_unref);
#else
/* Re-define G_SOURCE_FUNC as we are technically not allowed to use it with
* the version we depend on currently. */
#undef G_SOURCE_FUNC
#endif
#define G_SOURCE_FUNC(f) ((GSourceFunc) (void (*)(void))(f))
#if !GLIB_CHECK_VERSION (2, 63, 3)
typedef struct _FpDeviceClass FpDeviceClass;
G_DEFINE_AUTOPTR_CLEANUP_FUNC (FpDeviceClass, g_type_class_unref);
G_DEFINE_AUTOPTR_CLEANUP_FUNC (GDate, g_date_free);
#endif
#if __GNUC__ > 10 || (__GNUC__ == 10 && __GNUC_MINOR__ >= 1)
#define FP_GNUC_ACCESS(m, p, s) __attribute__((access (m, p, s)))
#else

View File

@@ -21,6 +21,7 @@
#define FP_COMPONENT "device"
#include <math.h>
#include <fcntl.h>
#include <errno.h>
#include "fpi-log.h"
@@ -116,6 +117,10 @@ fpi_device_retry_new (FpDeviceRetry error)
msg = "Please try again after removing the finger first.";
break;
case FP_DEVICE_RETRY_TOO_FAST:
msg = "The swipe was too fast, please try again.";
break;
default:
g_warning ("Unsupported error, returning general error instead!");
error = FP_DEVICE_RETRY_GENERAL;
@@ -521,33 +526,6 @@ fpi_device_get_driver_data (FpDevice *device)
return priv->driver_data;
}
void
enroll_data_free (FpEnrollData *data)
{
if (data->enroll_progress_destroy)
data->enroll_progress_destroy (data->enroll_progress_data);
data->enroll_progress_data = NULL;
g_clear_object (&data->print);
g_free (data);
}
void
match_data_free (FpMatchData *data)
{
g_clear_object (&data->print);
g_clear_object (&data->match);
g_clear_error (&data->error);
if (data->match_destroy)
data->match_destroy (data->match_data);
data->match_data = NULL;
g_clear_object (&data->enrolled_print);
g_clear_pointer (&data->gallery, g_ptr_array_unref);
g_free (data);
}
/**
* fpi_device_get_enroll_data:
* @device: The #FpDevice
@@ -621,7 +599,14 @@ fpi_device_get_verify_data (FpDevice *device,
* @device: The #FpDevice
* @prints: (out) (transfer none) (element-type FpPrint): The gallery of prints
*
* Get data for identify.
* Get prints gallery for identification.
*
* The @prints array is always non-%NULL and may contain a list of #FpPrint's
* that the device should match against.
*
* Note that @prints can be an empty array, in such case the device is expected
* to report the scanned print matching the one in its internal storage, if any.
*
*/
void
fpi_device_get_identify_data (FpDevice *device,
@@ -866,16 +851,16 @@ fpi_device_critical_section_flush_idle_cb (FpDevice *device)
if (priv->suspend_queued)
{
cls->suspend (device);
priv->suspend_queued = FALSE;
fpi_device_suspend (device);
return G_SOURCE_CONTINUE;
}
if (priv->resume_queued)
{
cls->resume (device);
priv->resume_queued = FALSE;
fpi_device_resume (device);
return G_SOURCE_CONTINUE;
}
@@ -912,6 +897,7 @@ fpi_device_critical_leave (FpDevice *device)
return;
priv->critical_section_flush_source = g_idle_source_new ();
g_source_set_priority (priv->critical_section_flush_source, G_PRIORITY_HIGH);
g_source_set_callback (priv->critical_section_flush_source,
(GSourceFunc) fpi_device_critical_section_flush_idle_cb,
device,
@@ -1060,34 +1046,41 @@ fp_device_task_return_in_idle_cb (gpointer user_data)
static void
fpi_device_task_return_data_free (FpDeviceTaskReturnData *data)
{
if (data->result)
switch (data->type)
{
switch (data->type)
{
case FP_DEVICE_TASK_RETURN_INT:
case FP_DEVICE_TASK_RETURN_BOOL:
break;
case FP_DEVICE_TASK_RETURN_INT:
case FP_DEVICE_TASK_RETURN_BOOL:
break;
case FP_DEVICE_TASK_RETURN_OBJECT:
g_clear_object ((GObject **) &data->result);
break;
case FP_DEVICE_TASK_RETURN_OBJECT:
g_clear_object ((GObject **) &data->result);
break;
case FP_DEVICE_TASK_RETURN_PTR_ARRAY:
g_clear_pointer ((GPtrArray **) &data->result, g_ptr_array_unref);
break;
case FP_DEVICE_TASK_RETURN_PTR_ARRAY:
g_clear_pointer ((GPtrArray **) &data->result, g_ptr_array_unref);
break;
case FP_DEVICE_TASK_RETURN_ERROR:
g_clear_error ((GError **) &data->result);
break;
case FP_DEVICE_TASK_RETURN_ERROR:
g_clear_error ((GError **) &data->result);
break;
default:
g_assert_not_reached ();
}
default:
g_assert_not_reached ();
}
g_object_unref (data->device);
g_free (data);
}
/**
* fpi_device_return_task_in_idle:
* @device: The #FpDevice
* @return_type: The #FpDeviceTaskReturnType of @return_data
* @return_data: (nullable) (transfer full): The data to return.
*
* Completes a #FpDevice task in an idle source, stealing the ownership of
* the passed @returned_data.
*/
static void
fpi_device_return_task_in_idle (FpDevice *device,
FpDeviceTaskReturnType return_type,
@@ -1119,7 +1112,7 @@ fpi_device_return_task_in_idle (FpDevice *device,
* @device: The #FpDevice
* @device_id: Unique ID for the device or %NULL
* @device_name: Human readable name or %NULL for driver name
* @error: The #GError or %NULL on success
* @error: (nullable) (transfer full): The #GError or %NULL on success
*
* Finish an ongoing probe operation. If error is %NULL success is assumed.
*/
@@ -1165,7 +1158,7 @@ fpi_device_probe_complete (FpDevice *device,
/**
* fpi_device_open_complete:
* @device: The #FpDevice
* @error: The #GError or %NULL on success
* @error: (nullable) (transfer full): The #GError or %NULL on success
*
* Finish an ongoing open operation. If error is %NULL success is assumed.
*/
@@ -1192,7 +1185,7 @@ fpi_device_open_complete (FpDevice *device, GError *error)
/**
* fpi_device_close_complete:
* @device: The #FpDevice
* @error: The #GError or %NULL on success
* @error: (nullable) (transfer full): The #GError or %NULL on success
*
* Finish an ongoing close operation. If error is %NULL success is assumed.
*/
@@ -1244,7 +1237,7 @@ fpi_device_close_complete (FpDevice *device, GError *error)
* fpi_device_enroll_complete:
* @device: The #FpDevice
* @print: (nullable) (transfer full): The #FpPrint or %NULL on failure
* @error: The #GError or %NULL on success
* @error: (nullable) (transfer full): The #GError or %NULL on success
*
* Finish an ongoing enroll operation. The #FpPrint can be stored by the
* caller for later verification.
@@ -1310,12 +1303,14 @@ fpi_device_enroll_complete (FpDevice *device, FpPrint *print, GError *error)
* @device: The #FpDevice
* @error: A #GError if result is %FPI_MATCH_ERROR
*
* Finish an ongoing verify operation. The returned print should be
* representing the new scan and not the one passed for verification.
* Finish an ongoing verify operation.
*
* Note that @error should only be set for actual errors. In the case
* of retry errors, report these using fpi_device_verify_report()
* and then call this function without any error argument.
*
* If @error is not set, we expect that a result (and print, in case)
* have been already reported via fpi_device_verify_report().
*/
void
fpi_device_verify_complete (FpDevice *device,
@@ -1371,11 +1366,16 @@ fpi_device_verify_complete (FpDevice *device,
/**
* fpi_device_identify_complete:
* @device: The #FpDevice
* @error: The #GError or %NULL on success
* @error: (nullable) (transfer full): The #GError or %NULL on success
*
* Finish an ongoing identify operation. The match that was identified is
* returned in @match. The @print parameter returns the newly created scan
* that was used for matching.
* Finish an ongoing identify operation.
*
* Note that @error should only be set for actual errors. In the case
* of retry errors, report these using fpi_device_identify_report()
* and then call this function without any error argument.
*
* If @error is not set, we expect that a match and / or a print have been
* already reported via fpi_device_identify_report()
*/
void
fpi_device_identify_complete (FpDevice *device,
@@ -1432,7 +1432,7 @@ fpi_device_identify_complete (FpDevice *device,
* fpi_device_capture_complete:
* @device: The #FpDevice
* @image: The #FpImage, or %NULL on error
* @error: The #GError or %NULL on success
* @error: (nullable) (transfer full): The #GError or %NULL on success
*
* Finish an ongoing capture operation.
*/
@@ -1479,7 +1479,7 @@ fpi_device_capture_complete (FpDevice *device,
/**
* fpi_device_delete_complete:
* @device: The #FpDevice
* @error: The #GError or %NULL on success
* @error: (nullable) (transfer full): The #GError or %NULL on success
*
* Finish an ongoing delete operation.
*/
@@ -1508,7 +1508,7 @@ fpi_device_delete_complete (FpDevice *device,
* fpi_device_list_complete:
* @device: The #FpDevice
* @prints: (element-type FpPrint) (transfer container): Possibly empty array of prints or %NULL on error
* @error: The #GError or %NULL on success
* @error: (nullable) (transfer full): The #GError or %NULL on success
*
* Finish an ongoing list operation.
*
@@ -1550,6 +1550,150 @@ fpi_device_list_complete (FpDevice *device,
fpi_device_return_task_in_idle (device, FP_DEVICE_TASK_RETURN_ERROR, error);
}
static int
update_attr (const char *attr, const char *value)
{
int fd, err;
gssize r;
char buf[50] = { 0 };
fd = open (attr, O_RDONLY);
err = -errno;
if (fd < 0)
return -err;
r = read (fd, buf, sizeof (buf) - 1);
err = errno;
close (fd);
if (r < 0)
return -err;
g_strchomp (buf);
if (g_strcmp0 (buf, value) == 0)
return 0;
/* O_TRUNC makes things work in the umockdev environment */
fd = open (attr, O_WRONLY | O_TRUNC);
err = errno;
if (fd < 0)
return -err;
r = write (fd, value, strlen (value));
err = -errno;
close (fd);
if (r < 0)
{
/* Write failures are weird, and are worth a warning */
g_warning ("Could not write %s to %s", value, attr);
return -err;
}
return 0;
}
static void
complete_suspend_resume_task (FpDevice *device)
{
g_autoptr(GTask) task = NULL;
FpDevicePrivate *priv = fp_device_get_instance_private (device);
g_assert (priv->suspend_resume_task);
task = g_steal_pointer (&priv->suspend_resume_task);
g_task_return_boolean (task, TRUE);
}
void
fpi_device_suspend (FpDevice *device)
{
FpDevicePrivate *priv = fp_device_get_instance_private (device);
/* If the device is currently idle, just complete immediately.
* For long running tasks, call the driver handler right away, for short
* tasks, wait for completion and then return the task.
*/
switch (priv->current_action)
{
case FPI_DEVICE_ACTION_NONE:
fpi_device_suspend_complete (device, NULL);
break;
case FPI_DEVICE_ACTION_ENROLL:
case FPI_DEVICE_ACTION_VERIFY:
case FPI_DEVICE_ACTION_IDENTIFY:
case FPI_DEVICE_ACTION_CAPTURE:
if (FP_DEVICE_GET_CLASS (device)->suspend)
{
if (priv->critical_section)
priv->suspend_queued = TRUE;
else
FP_DEVICE_GET_CLASS (device)->suspend (device);
}
else
{
fpi_device_suspend_complete (device, fpi_device_error_new (FP_DEVICE_ERROR_NOT_SUPPORTED));
}
break;
default:
case FPI_DEVICE_ACTION_PROBE:
case FPI_DEVICE_ACTION_OPEN:
case FPI_DEVICE_ACTION_CLOSE:
case FPI_DEVICE_ACTION_DELETE:
case FPI_DEVICE_ACTION_LIST:
case FPI_DEVICE_ACTION_CLEAR_STORAGE:
g_signal_connect_object (priv->current_task,
"notify::completed",
G_CALLBACK (complete_suspend_resume_task),
device,
G_CONNECT_SWAPPED);
break;
}
}
void
fpi_device_resume (FpDevice *device)
{
FpDevicePrivate *priv = fp_device_get_instance_private (device);
switch (priv->current_action)
{
case FPI_DEVICE_ACTION_NONE:
fpi_device_resume_complete (device, NULL);
break;
case FPI_DEVICE_ACTION_ENROLL:
case FPI_DEVICE_ACTION_VERIFY:
case FPI_DEVICE_ACTION_IDENTIFY:
case FPI_DEVICE_ACTION_CAPTURE:
if (FP_DEVICE_GET_CLASS (device)->resume)
{
if (priv->critical_section)
priv->resume_queued = TRUE;
else
FP_DEVICE_GET_CLASS (device)->resume (device);
}
else
{
fpi_device_resume_complete (device, fpi_device_error_new (FP_DEVICE_ERROR_NOT_SUPPORTED));
}
break;
default:
case FPI_DEVICE_ACTION_PROBE:
case FPI_DEVICE_ACTION_OPEN:
case FPI_DEVICE_ACTION_CLOSE:
case FPI_DEVICE_ACTION_DELETE:
case FPI_DEVICE_ACTION_LIST:
case FPI_DEVICE_ACTION_CLEAR_STORAGE:
/* cannot happen as we make sure these tasks complete before suspend */
g_assert_not_reached ();
complete_suspend_resume_task (device);
break;
}
}
void
fpi_device_configure_wakeup (FpDevice *device, gboolean enabled)
{
@@ -1560,42 +1704,38 @@ fpi_device_configure_wakeup (FpDevice *device, gboolean enabled)
case FP_DEVICE_TYPE_USB:
{
g_autoptr(GString) ports = NULL;
GUsbDevice *dev, *parent;
g_autoptr(GUsbDevice) dev = NULL;
const char *wakeup_command = enabled ? "enabled" : "disabled";
guint8 bus, port;
guint8 bus;
g_autofree gchar *sysfs_wakeup = NULL;
g_autofree gchar *sysfs_persist = NULL;
gssize r;
int fd;
int res;
ports = g_string_new (NULL);
bus = g_usb_device_get_bus (priv->usb_device);
/* Walk up, skipping the root hub. */
dev = priv->usb_device;
while ((parent = g_usb_device_get_parent (dev)))
g_set_object (&dev, priv->usb_device);
while (TRUE)
{
g_autoptr(GUsbDevice) parent = g_usb_device_get_parent (dev);
g_autofree gchar *port_str = NULL;
guint8 port;
if (!parent)
break;
port = g_usb_device_get_port_number (dev);
g_string_prepend (ports, g_strdup_printf ("%d.", port));
dev = parent;
port_str = g_strdup_printf ("%d.", port);
g_string_prepend (ports, port_str);
g_set_object (&dev, parent);
}
g_string_set_size (ports, ports->len - 1);
sysfs_wakeup = g_strdup_printf ("/sys/bus/usb/devices/%d-%s/power/wakeup", bus, ports->str);
fd = open (sysfs_wakeup, O_WRONLY);
if (fd < 0)
{
/* Wakeup not existing appears to be relatively normal. */
g_debug ("Failed to open %s", sysfs_wakeup);
}
else
{
r = write (fd, wakeup_command, strlen (wakeup_command));
if (r < 0)
g_warning ("Could not configure wakeup to %s by writing %s", wakeup_command, sysfs_wakeup);
close (fd);
}
res = update_attr (sysfs_wakeup, wakeup_command);
if (res < 0)
g_debug ("Failed to set %s to %s", sysfs_wakeup, wakeup_command);
/* Persist means that the kernel tries to keep the USB device open
* in case it is "replugged" due to suspend.
@@ -1603,20 +1743,9 @@ fpi_device_configure_wakeup (FpDevice *device, gboolean enabled)
* state. Instead, seeing an unplug and a new device makes more sense.
*/
sysfs_persist = g_strdup_printf ("/sys/bus/usb/devices/%d-%s/power/persist", bus, ports->str);
fd = open (sysfs_persist, O_WRONLY);
if (fd < 0)
{
g_warning ("Failed to open %s", sysfs_persist);
return;
}
else
{
r = write (fd, "0", 1);
if (r < 0)
g_message ("Could not disable USB persist by writing to %s", sysfs_persist);
close (fd);
}
res = update_attr (sysfs_persist, "0");
if (res < 0)
g_warning ("Failed to disable USB persist by writing to %s", sysfs_persist);
break;
}
@@ -1636,6 +1765,7 @@ fpi_device_configure_wakeup (FpDevice *device, gboolean enabled)
static void
fpi_device_suspend_completed (FpDevice *device)
{
g_autoptr(GTask) task = NULL;
FpDevicePrivate *priv = fp_device_get_instance_private (device);
/* We have an ongoing operation, allow the device to wake up the machine. */
@@ -1645,17 +1775,18 @@ fpi_device_suspend_completed (FpDevice *device)
if (priv->critical_section)
g_warning ("Driver was in a critical section at suspend time. It likely deadlocked!");
task = g_steal_pointer (&priv->suspend_resume_task);
if (priv->suspend_error)
g_task_return_error (g_steal_pointer (&priv->suspend_resume_task),
g_steal_pointer (&priv->suspend_error));
g_task_return_error (task, g_steal_pointer (&priv->suspend_error));
else
g_task_return_boolean (g_steal_pointer (&priv->suspend_resume_task), TRUE);
g_task_return_boolean (task, TRUE);
}
/**
* fpi_device_suspend_complete:
* @device: The #FpDevice
* @error: The #GError or %NULL on success
* @error: (nullable) (transfer full): The #GError or %NULL on success
*
* Finish a suspend request. Only return a %NULL error if suspend has been
* correctly configured and the current action as returned by
@@ -1677,11 +1808,12 @@ fpi_device_suspend_complete (FpDevice *device,
g_return_if_fail (priv->suspend_resume_task);
g_return_if_fail (priv->suspend_error == NULL);
priv->suspend_error = error;
priv->suspend_error = g_steal_pointer (&error);
priv->is_suspended = TRUE;
/* If there is no error, we have no running task, return immediately. */
if (error == NULL || !priv->current_task || g_task_get_completed (priv->current_task))
if (!priv->suspend_error || !priv->current_task ||
g_task_get_completed (priv->current_task))
{
fpi_device_suspend_completed (device);
return;
@@ -1705,7 +1837,7 @@ fpi_device_suspend_complete (FpDevice *device,
/**
* fpi_device_resume_complete:
* @device: The #FpDevice
* @error: The #GError or %NULL on success
* @error: (nullable) (transfer full): The #GError or %NULL on success
*
* Finish a resume request.
*/
@@ -1713,6 +1845,7 @@ void
fpi_device_resume_complete (FpDevice *device,
GError *error)
{
g_autoptr(GTask) task = NULL;
FpDevicePrivate *priv = fp_device_get_instance_private (device);
g_return_if_fail (FP_IS_DEVICE (device));
@@ -1721,16 +1854,18 @@ fpi_device_resume_complete (FpDevice *device,
priv->is_suspended = FALSE;
fpi_device_configure_wakeup (device, FALSE);
task = g_steal_pointer (&priv->suspend_resume_task);
if (error)
g_task_return_error (g_steal_pointer (&priv->suspend_resume_task), error);
g_task_return_error (task, error);
else
g_task_return_boolean (g_steal_pointer (&priv->suspend_resume_task), TRUE);
g_task_return_boolean (task, TRUE);
}
/**
* fpi_device_clear_storage_complete:
* @device: The #FpDevice
* @error: The #GError or %NULL on success
* @error: (nullable) (transfer full): The #GError or %NULL on success
*
* Finish an ongoing clear_storage operation.
*/
@@ -1761,7 +1896,7 @@ fpi_device_clear_storage_complete (FpDevice *device,
* @device: The #FpDevice
* @completed_stages: The number of stages that are completed at this point
* @print: (transfer floating): The #FpPrint for the newly completed stage or %NULL on failure
* @error: (transfer full): The #GError or %NULL on success
* @error: (nullable) (transfer full): The #GError or %NULL on success
*
* Notify about the progress of the enroll operation. This is important for UI interaction.
* The passed error may be used if a scan needs to be retried, use fpi_device_retry_new().
@@ -1881,12 +2016,26 @@ fpi_device_verify_report (FpDevice *device,
* fpi_device_identify_report:
* @device: The #FpDevice
* @match: (transfer none): The #FpPrint from the gallery that matched
* @print: (transfer floating): The scanned #FpPrint
* @error: A #GError if result is %FPI_MATCH_ERROR
* @print: (transfer floating): The scanned #FpPrint, set in the absence
* of an error.
* @error: A #GError of %FP_DEVICE_RETRY type if @match and @print are unset.
*
* Report the result of a identify operation. Note that the passed @error must be
* a retry error with the %FP_DEVICE_RETRY domain. For all other error cases,
* the error should passed to fpi_device_identify_complete().
* Report the results of an identify operation.
*
* In case of successful identification @match is expected to be set to a
* #FpPrint that matches one from the provided gallery, while @print
* represents the scanned print and will be different.
*
* If there are no errors, it's expected that the device always reports the
* recognized @print even if there is no @match with the provided gallery (that
* can be potentially empty). This is required for application logic further
* up in the stack, such as for enroll-duplicate checking. @print needs to be
* sufficiently filled to do a comparison.
*
* In case of error, both @match and @print are expected to be %NULL.
* Note that the passed @error must be a retry error from the %FP_DEVICE_RETRY
* domain. For all other error cases, the error should passed to
* fpi_device_identify_complete().
*/
void
fpi_device_identify_report (FpDevice *device,

View File

@@ -565,7 +565,7 @@ fpi_image_device_retry_scan (FpImageDevice *self, FpDeviceRetry retry)
/**
* fpi_image_device_session_error:
* @self: a #FpImageDevice imaging fingerprint device
* @error: The #GError to report
* @error: (nullable) (transfer full): The #GError to report.
*
* Report an error while interacting with the device. This effectively
* aborts the current ongoing action. Note that doing so will result in
@@ -624,7 +624,7 @@ fpi_image_device_session_error (FpImageDevice *self, GError *error)
/**
* fpi_image_device_activate_complete:
* @self: a #FpImageDevice imaging fingerprint device
* @error: A #GError or %NULL on success
* @error: (nullable) (transfer full): The #GError or %NULL on success
*
* Reports completion of device activation.
*/
@@ -663,7 +663,7 @@ fpi_image_device_activate_complete (FpImageDevice *self, GError *error)
/**
* fpi_image_device_deactivate_complete:
* @self: a #FpImageDevice imaging fingerprint device
* @error: A #GError or %NULL on success
* @error: (nullable) (transfer full): The #GError or %NULL on success
*
* Reports completion of device deactivation.
*/
@@ -690,7 +690,7 @@ fpi_image_device_deactivate_complete (FpImageDevice *self, GError *error)
/**
* fpi_image_device_open_complete:
* @self: a #FpImageDevice imaging fingerprint device
* @error: A #GError or %NULL on success
* @error: (nullable) (transfer full): The #GError or %NULL on success
*
* Reports completion of open operation.
*/
@@ -718,7 +718,7 @@ fpi_image_device_open_complete (FpImageDevice *self, GError *error)
/**
* fpi_image_device_close_complete:
* @self: a #FpImageDevice imaging fingerprint device
* @error: A #GError or %NULL on success
* @error: (nullable) (transfer full): The #GError or %NULL on success
*
* Reports completion of close operation.
*/

View File

@@ -24,8 +24,9 @@
#include "fpi-log.h"
#include <nbis.h>
#include <config.h>
#if HAVE_PIXMAN
#ifdef HAVE_PIXMAN
#include <pixman.h>
#endif
@@ -107,12 +108,12 @@ fpi_mean_sq_diff_norm (const guint8 *buf1,
return res / size;
}
#if HAVE_PIXMAN
FpImage *
fpi_image_resize (FpImage *orig_img,
guint w_factor,
guint h_factor)
{
#ifdef HAVE_PIXMAN
int new_width = orig_img->width * w_factor;
int new_height = orig_img->height * h_factor;
pixman_image_t *orig, *resized;
@@ -145,5 +146,9 @@ fpi_image_resize (FpImage *orig_img,
pixman_image_unref (resized);
return newimg;
}
#else
fp_err ("Libfprint compiled without pixman support, impossible to resize");
return g_object_ref (orig_img);
#endif
}

View File

@@ -20,7 +20,6 @@
#pragma once
#include <config.h>
#include "fp-image.h"
/**
@@ -34,6 +33,7 @@
* rely on the image to be normalized by libfprint before further processing.
*/
typedef enum {
FPI_IMAGE_NONE = 0,
FPI_IMAGE_V_FLIPPED = 1 << 0,
FPI_IMAGE_H_FLIPPED = 1 << 1,
FPI_IMAGE_COLORS_INVERTED = 1 << 2,
@@ -68,7 +68,8 @@ struct _FpImage
guint8 *binarized;
GPtrArray *minutiae;
guint ref_count;
gboolean detection_in_progress;
};
gint fpi_std_sq_dev (const guint8 *buf,
@@ -77,8 +78,6 @@ gint fpi_mean_sq_diff_norm (const guint8 *buf1,
const guint8 *buf2,
gint size);
#if HAVE_PIXMAN
FpImage *fpi_image_resize (FpImage *orig,
guint w_factor,
guint h_factor);
#endif

View File

@@ -79,13 +79,16 @@
*
* Uses fp_err() to print an error if the @condition is true.
*/
#define BUG_ON(condition) G_STMT_START \
if (condition) { \
#define BUG_ON(condition) \
G_STMT_START \
if (condition) \
{ \
char *s; \
s = g_strconcat ("BUG: (", #condition, ")", NULL); \
fp_err ("%s: %s() %s:%d", s, G_STRFUNC, __FILE__, __LINE__); \
g_free (s); \
} G_STMT_END
} \
G_STMT_END
/**
* BUG:

View File

@@ -50,7 +50,7 @@ fpi_print_add_print (FpPrint *print, FpPrint *add)
g_return_if_fail (add->type == FPI_PRINT_NBIS);
g_assert (add->prints->len == 1);
g_ptr_array_add (print->prints, g_memdup (add->prints->pdata[0], sizeof (struct xyt_struct)));
g_ptr_array_add (print->prints, g_memdup2 (add->prints->pdata[0], sizeof (struct xyt_struct)));
}
/**

View File

@@ -42,9 +42,9 @@ gboolean fpi_print_add_from_image (FpPrint *print,
FpImage *image,
GError **error);
FpiMatchResult fpi_print_bz3_match (FpPrint * template,
FpPrint * print,
gint bz3_threshold,
FpiMatchResult fpi_print_bz3_match (FpPrint *temp,
FpPrint *print,
gint bz3_threshold,
GError **error);
/* Helpers to encode metadata into user ID strings. */

View File

@@ -73,7 +73,7 @@
struct _FpiSsm
{
FpDevice *dev;
const char *name;
char *name;
FpiSsm *parentsm;
gpointer ssm_data;
GDestroyNotify ssm_data_destroy;

View File

@@ -0,0 +1,107 @@
/*
* Copyright (C) 2025 Marco Trevisan <marco.trevisan@canonical.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "glib.h"
#include "fpi-context.h"
#include "fpi-device.h"
#define METAINFO_BASE \
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" \
"<component>\n" \
" <id>org.freedesktop.libfprint</id>\n" \
" <name>libfprint</name>\n" \
" <metadata_license>CC0-1.0</metadata_license>\n" \
" <project_license>LGPL-2.1-or-later</project_license>\n" \
" <url type=\"homepage\">https://fprint.freedesktop.org</url>\n" \
" <url type=\"vcs-browser\">https://gitlab.freedesktop.org/libfprint/libfprint</url>\n" \
" <url type=\"help\">https://fprint.freedesktop.org/libfprint-dev</url>\n" \
" <url type=\"bugtracker\">https://gitlab.freedesktop.org/libfprint/libfprint/-/issues</url>\n" \
" <summary>Async fingerprint readers library</summary>\n" \
" <description>\n" \
" <p>\n" \
" The fprint project aims to support for consumer fingerprint reader devices.\n" \
" </p>\n" \
" </description>\n" \
" <provides>\n" \
"%s\n" \
" </provides>\n" \
"</component>\n"
static int
driver_compare (gconstpointer p1, gconstpointer p2)
{
g_autoptr(FpDeviceClass) cls1 = g_type_class_ref (*(GType *) p1);
g_autoptr(FpDeviceClass) cls2 = g_type_class_ref (*(GType *) p2);
return g_strcmp0 (cls1->id, cls2->id);
}
static void
usb_driver_devices_append (GPtrArray *devices_list,
const FpDeviceClass *cls)
{
const FpIdEntry *entry;
if (cls->type != FP_DEVICE_TYPE_USB)
return;
for (entry = cls->id_table; entry->vid != 0; entry++)
{
if (entry->vid == 0 || entry->pid == 0)
continue;
g_ptr_array_add (devices_list,
g_strdup_printf ("v%04xp%04x", entry->vid, entry->pid));
}
}
int
main (void)
{
g_autoptr(GPtrArray) devices_list = g_ptr_array_new_with_free_func (g_free);
g_autoptr(GArray) drivers = fpi_get_driver_types ();
g_autoptr(GString) provided_modules = g_string_new (NULL);
g_autoptr(GError) error = NULL;
g_array_sort (drivers, driver_compare);
for (guint i = 0; i < drivers->len; ++i)
{
GType driver = g_array_index (drivers, GType, i);
g_autoptr(FpDeviceClass) cls = g_type_class_ref (driver);
if (cls->type != FP_DEVICE_TYPE_USB)
continue;
usb_driver_devices_append (devices_list, cls);
}
for (guint i = 0; i < devices_list->len; ++i)
{
const char *device_id = g_ptr_array_index (devices_list, i);
g_string_append (provided_modules, " ");
g_string_append_printf (provided_modules, "<modalias>usb:%s*</modalias>",
device_id);
if (i < devices_list->len - 1)
g_string_append_c (provided_modules, '\n');
}
g_print (METAINFO_BASE, provided_modules->str);
}

View File

@@ -110,7 +110,7 @@ main (int argc, char **argv)
printed = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
g_print ("%% lifprint — Supported Devices\n");
g_print ("%% libfprint — Supported Devices\n");
g_print ("%% Bastien Nocera, Daniel Drake\n");
g_print ("%% 2018\n");
g_print ("\n");
@@ -132,7 +132,7 @@ main (int argc, char **argv)
g_print ("%s", (char *) l->data);
g_print ("\n");
g_list_free_full (usb_list, g_free);
g_list_free_full (g_steal_pointer (&usb_list), g_free);
g_print ("## SPI devices\n");
g_print ("\n");
@@ -146,7 +146,7 @@ main (int argc, char **argv)
g_print ("%s", (char *) l->data);
g_print ("\n");
g_list_free_full (usb_list, g_free);
g_list_free_full (g_steal_pointer (&spi_list), g_free);
g_hash_table_destroy (printed);

View File

@@ -24,17 +24,41 @@
#include "fpi-context.h"
#include "fpi-device.h"
static const FpIdEntry whitelist_id_table[] = {
static const FpIdEntry allowlist_id_table[] = {
/* Currently known and unsupported devices.
* You can generate this list from the wiki page using e.g.:
* gio cat https://gitlab.freedesktop.org/libfprint/wiki/-/wikis/Unsupported-Devices.md | sed -n 's!|.*\([0-9a-fA-F]\{4\}\):\([0-9a-fA-F]\{4\}\).*|.*! { .vid = 0x\1, .pid = 0x\2 },!p'
*/
{ .vid = 0x0a5c, .pid = 0x5802 },
{ .vid = 0x047d, .pid = 0x00f2 },
{ .vid = 0x047d, .pid = 0x8054 },
{ .vid = 0x047d, .pid = 0x8055 },
{ .vid = 0x04e8, .pid = 0x730b },
{ .vid = 0x04f3, .pid = 0x036b },
{ .vid = 0x04f3, .pid = 0x0c00 },
{ .vid = 0x04f3, .pid = 0x0c4c },
{ .vid = 0x04f3, .pid = 0x0c57 },
{ .vid = 0x04f3, .pid = 0x0c5e },
{ .vid = 0x04f3, .pid = 0x0c5a },
{ .vid = 0x04f3, .pid = 0x0c60 },
{ .vid = 0x04f3, .pid = 0x0c6c },
{ .vid = 0x04f3, .pid = 0x0c70 },
{ .vid = 0x04f3, .pid = 0x0c72 },
{ .vid = 0x04f3, .pid = 0x0c77 },
{ .vid = 0x04f3, .pid = 0x0c7c },
{ .vid = 0x04f3, .pid = 0x0c7f },
{ .vid = 0x04f3, .pid = 0x0c80 },
{ .vid = 0x04f3, .pid = 0x0c85 },
{ .vid = 0x04f3, .pid = 0x0c90 },
{ .vid = 0x04f3, .pid = 0x2706 },
{ .vid = 0x04f3, .pid = 0x3032 },
{ .vid = 0x04f3, .pid = 0x3057 },
{ .vid = 0x04f3, .pid = 0x3104 },
{ .vid = 0x04f3, .pid = 0x310d },
{ .vid = 0x04f3, .pid = 0x3128 },
{ .vid = 0x04f3, .pid = 0x0c8a },
{ .vid = 0x05ba, .pid = 0x000e },
{ .vid = 0x06cb, .pid = 0x0051 },
{ .vid = 0x06cb, .pid = 0x0081 },
{ .vid = 0x06cb, .pid = 0x0088 },
{ .vid = 0x06cb, .pid = 0x008a },
@@ -45,15 +69,16 @@ static const FpIdEntry whitelist_id_table[] = {
{ .vid = 0x06cb, .pid = 0x00b7 },
{ .vid = 0x06cb, .pid = 0x00bb },
{ .vid = 0x06cb, .pid = 0x00be },
{ .vid = 0x06cb, .pid = 0x00c4 },
{ .vid = 0x06cb, .pid = 0x00cb },
{ .vid = 0x06cb, .pid = 0x00c9 },
{ .vid = 0x06cb, .pid = 0x00d8 },
{ .vid = 0x06cb, .pid = 0x00da },
{ .vid = 0x06cb, .pid = 0x00dc },
{ .vid = 0x06cb, .pid = 0x00e4 },
{ .vid = 0x06cb, .pid = 0x00e7 },
{ .vid = 0x06cb, .pid = 0x00e9 },
{ .vid = 0x06cb, .pid = 0x00fd },
{ .vid = 0x06cb, .pid = 0x00ff },
{ .vid = 0x0a5c, .pid = 0x5801 },
{ .vid = 0x0a5c, .pid = 0x5805 },
{ .vid = 0x0a5c, .pid = 0x5834 },
@@ -63,9 +88,19 @@ static const FpIdEntry whitelist_id_table[] = {
{ .vid = 0x0a5c, .pid = 0x5843 },
{ .vid = 0x0a5c, .pid = 0x5844 },
{ .vid = 0x0a5c, .pid = 0x5845 },
{ .vid = 0x0a5c, .pid = 0x5860 },
{ .vid = 0x0a5c, .pid = 0x5863 },
{ .vid = 0x0a5c, .pid = 0x5864 },
{ .vid = 0x0a5c, .pid = 0x5865 },
{ .vid = 0x0a5c, .pid = 0x5866 },
{ .vid = 0x0a5c, .pid = 0x5867 },
{ .vid = 0x0bda, .pid = 0x5812 },
{ .vid = 0x10a5, .pid = 0x0007 },
{ .vid = 0x10a5, .pid = 0x9200 },
{ .vid = 0x10a5, .pid = 0x9800 },
{ .vid = 0x10a5, .pid = 0xa120 },
{ .vid = 0x10a5, .pid = 0xa900 },
{ .vid = 0x10a5, .pid = 0xe340 },
{ .vid = 0x1188, .pid = 0x9545 },
{ .vid = 0x138a, .pid = 0x0007 },
{ .vid = 0x138a, .pid = 0x003a },
@@ -78,51 +113,72 @@ static const FpIdEntry whitelist_id_table[] = {
{ .vid = 0x138a, .pid = 0x0097 },
{ .vid = 0x138a, .pid = 0x009d },
{ .vid = 0x138a, .pid = 0x00ab },
{ .vid = 0x138a, .pid = 0x00a6 },
{ .vid = 0x147e, .pid = 0x1002 },
{ .vid = 0x1491, .pid = 0x0088 },
{ .vid = 0x16d1, .pid = 0x1027 },
{ .vid = 0x1c7a, .pid = 0x0300 },
{ .vid = 0x1c7a, .pid = 0x0575 },
{ .vid = 0x1c7a, .pid = 0x0576 },
{ .vid = 0x1c7a, .pid = 0x0577 },
{ .vid = 0x1c7a, .pid = 0x057e },
{ .vid = 0x2541, .pid = 0x0236 },
{ .vid = 0x2541, .pid = 0x9711 },
{ .vid = 0x27c6, .pid = 0x5042 },
{ .vid = 0x27c6, .pid = 0x5110 },
{ .vid = 0x27c6, .pid = 0x5117 },
{ .vid = 0x27c6, .pid = 0x5120 },
{ .vid = 0x27c6, .pid = 0x5125 },
{ .vid = 0x27c6, .pid = 0x5201 },
{ .vid = 0x27c6, .pid = 0x521d },
{ .vid = 0x27c6, .pid = 0x5301 },
{ .vid = 0x27c6, .pid = 0x530c },
{ .vid = 0x27c6, .pid = 0x532d },
{ .vid = 0x27c6, .pid = 0x5335 },
{ .vid = 0x27c6, .pid = 0x533c },
{ .vid = 0x27c6, .pid = 0x5381 },
{ .vid = 0x27c6, .pid = 0x5385 },
{ .vid = 0x27c6, .pid = 0x538c },
{ .vid = 0x27c6, .pid = 0x538d },
{ .vid = 0x27c6, .pid = 0x5395 },
{ .vid = 0x27c6, .pid = 0x5503 },
{ .vid = 0x27c6, .pid = 0x550a },
{ .vid = 0x27c6, .pid = 0x550c },
{ .vid = 0x27c6, .pid = 0x5584 },
{ .vid = 0x27c6, .pid = 0x55a2 },
{ .vid = 0x27c6, .pid = 0x55a4 },
{ .vid = 0x27c6, .pid = 0x55b4 },
{ .vid = 0x27c6, .pid = 0x5740 },
{ .vid = 0x27c6, .pid = 0x5e0a },
{ .vid = 0x27c6, .pid = 0x581a },
{ .vid = 0x27c6, .pid = 0x589a },
{ .vid = 0x27c6, .pid = 0x5f10 },
{ .vid = 0x27c6, .pid = 0x6382 },
{ .vid = 0x2808, .pid = 0x9338 },
{ .vid = 0x2808, .pid = 0x9348 },
{ .vid = 0x2808, .pid = 0x93a9 },
{ .vid = 0x2808, .pid = 0xa658 },
{ .vid = 0x2808, .pid = 0xc652 },
{ .vid = 0x298d, .pid = 0x2020 },
{ .vid = 0x298d, .pid = 0x2033 },
{ .vid = 0x2df0, .pid = 0x0003 },
{ .vid = 0x3274, .pid = 0x8012 },
{ .vid = 0x3538, .pid = 0x0930 },
{ .vid = 0 },
};
static const FpIdEntry blacklist_id_table[] = {
static const FpIdEntry denylist_id_table[] = {
{ .vid = 0x0483, .pid = 0x2016 },
/* https://bugs.freedesktop.org/show_bug.cgi?id=66659 */
{ .vid = 0x045e, .pid = 0x00bb },
{ .vid = 0 },
};
static const FpDeviceClass whitelist = {
static const FpDeviceClass allowlist = {
.type = FP_DEVICE_TYPE_USB,
.id_table = whitelist_id_table,
.id = "whitelist",
.full_name = "Hardcoded whitelist"
.id_table = allowlist_id_table,
.id = "allowlist",
.full_name = "Hardcoded allowlist"
};
GHashTable *printed = NULL;
@@ -141,7 +197,7 @@ print_driver (const FpDeviceClass *cls)
const FpIdEntry *bl_entry;
char *key;
for (bl_entry = blacklist_id_table; bl_entry->vid != 0; bl_entry++)
for (bl_entry = denylist_id_table; bl_entry->vid != 0; bl_entry++)
if (entry->vid == bl_entry->vid && entry->pid == bl_entry->pid)
break;
@@ -152,7 +208,7 @@ print_driver (const FpDeviceClass *cls)
if (g_hash_table_lookup (printed, key) != NULL)
{
if (cls == &whitelist)
if (cls == &allowlist)
g_warning ("%s implemented by driver %s",
key, (const char *) g_hash_table_lookup (printed, key));
g_free (key);
@@ -163,7 +219,7 @@ print_driver (const FpDeviceClass *cls)
if (num_printed == 0)
{
if (cls != &whitelist)
if (cls != &allowlist)
g_print ("\n# Supported by libfprint driver %s\n", cls->id);
else
g_print ("\n# Known unsupported devices\n");
@@ -217,7 +273,7 @@ main (int argc, char **argv)
print_driver (cls);
}
print_driver (&whitelist);
print_driver (&allowlist);
g_hash_table_destroy (printed);

View File

@@ -1,3 +1,11 @@
spi_sources = []
spi_headers = []
if enabled_spi_drivers.length() > 0
spi_headers = ['fpi-spi-transfer.h']
spi_sources = ['fpi-spi-transfer.c']
endif
libfprint_sources = [
'fp-context.c',
'fp-device.c',
@@ -16,8 +24,7 @@ libfprint_private_sources = [
'fpi-print.c',
'fpi-ssm.c',
'fpi-usb-transfer.c',
'fpi-spi-transfer.c',
]
] + spi_sources
libfprint_public_headers = [
'fp-context.h',
@@ -41,9 +48,8 @@ libfprint_private_headers = [
'fpi-minutiae.h',
'fpi-print.h',
'fpi-usb-transfer.h',
'fpi-spi-transfer.h',
'fpi-ssm.h',
]
] + spi_headers
nbis_sources = [
'nbis/bozorth3/bozorth3.c',
@@ -119,6 +125,8 @@ driver_sources = {
[ 'drivers/etes603.c' ],
'egis0570' :
[ 'drivers/egis0570.c' ],
'egismoc' :
[ 'drivers/egismoc/egismoc.c' ],
'vfs0050' :
[ 'drivers/vfs0050.c' ],
'elan' :
@@ -139,6 +147,12 @@ driver_sources = {
[ 'drivers/synaptics/synaptics.c', 'drivers/synaptics/bmkt_message.c' ],
'goodixmoc' :
[ 'drivers/goodixmoc/goodix.c', 'drivers/goodixmoc/goodix_proto.c' ],
'fpcmoc' :
[ 'drivers/fpcmoc/fpc.c' ],
'realtek' :
[ 'drivers/realtek/realtek.c' ],
'focaltech_moc' :
[ 'drivers/focaltech_moc/focaltech_moc.c' ],
}
helper_sources = {
@@ -148,7 +162,7 @@ helper_sources = {
[ 'drivers/aesx660.c' ],
'aes3k' :
[ 'drivers/aes3k.c' ],
'nss' :
'openssl' :
[ ],
'udev' :
[ ],
@@ -260,8 +274,13 @@ libfprint_drivers = static_library('fprint-drivers',
link_with: libfprint_private,
install: false)
mapfile = files('libfprint.ver')
vflag = '-Wl,--version-script,@0@/@1@'.format(meson.source_root(), mapfile[0])
mapfile = files('libfprint.ver')[0]
if meson.version().version_compare('>=1.4')
mapfile_path = mapfile.full_path()
else
mapfile_path = meson.project_source_root() / '@0@'.format(mapfile)
endif
vflag = '-Wl,--version-script,@0@'.format(mapfile_path)
libfprint = shared_library(versioned_libname.split('lib')[1],
sources: [
@@ -313,6 +332,21 @@ udev_hwdb_generator = custom_target('udev-hwdb',
install: false,
)
metainfo = executable('fprint-list-metainfo',
'fprint-list-metainfo.c',
dependencies: libfprint_private_dep,
link_with: libfprint_drivers,
install: false)
metainfo_generator = custom_target('metainfo',
output: 'org.freedesktop.libfprint.metainfo.xml',
depend_files: drivers_sources,
capture: true,
command: [ metainfo ],
install: true,
install_dir: datadir / 'metainfo'
)
if install_udev_rules
udev_rules = executable('fprint-list-udev-rules',
'fprint-list-udev-rules.c',
@@ -330,17 +364,19 @@ if install_udev_rules
)
endif
custom_target('sync-udev-hwdb',
sync_udev_udb = custom_target('sync-udev-hwdb',
depends: udev_hwdb_generator,
output: 'sync-udev-hwdb',
install: false,
command: [
'cp', '-v',
udev_hwdb_generator.full_path(),
meson.source_root() / 'data'
meson.project_source_root() / 'data'
]
)
alias_target('sync-udev-hwdb', sync_udev_udb)
supported_devices = executable('fprint-list-supported-devices',
'fprint-list-supported-devices.c',
dependencies: libfprint_private_dep,

View File

@@ -0,0 +1,31 @@
From 2584d440afc87d463cb8dc809d48c660e091c2c4 Mon Sep 17 00:00:00 2001
From: Sam James <sam@gentoo.org>
Date: Thu, 23 Jun 2022 05:57:46 +0100
Subject: [PATCH] nbis: fix build on musl
Drop re-definition of stderr. There's no need for this anywhere
(including glibc). This breaks in particular on musl because
stderr (and stdin) are both const, and macros unlike in glibc.
Bug: https://bugs.gentoo.org/853811
---
nbis/include/bozorth.h | 2 --
1 file changed, 2 deletions(-)
diff --git a/nbis/include/bozorth.h b/nbis/include/bozorth.h
index a705da98..fd8975bf 100644
--- a/nbis/include/bozorth.h
+++ b/nbis/include/bozorth.h
@@ -217,8 +217,6 @@ struct xytq_struct {
/**************************************************************************/
/* Globals supporting command line options */
extern int verbose_threshold;
-/* Global supporting error reporting */
-extern FILE *stderr;
/**************************************************************************/
/* In: BZ_GBLS.C */
--
GitLab

View File

@@ -217,8 +217,6 @@ struct xytq_struct {
/**************************************************************************/
/* Globals supporting command line options */
extern int verbose_threshold;
/* Global supporting error reporting */
extern FILE *stderr;
/**************************************************************************/
/* In: BZ_GBLS.C */

View File

@@ -198,3 +198,6 @@ patch -p0 < fix-scan-build-reports.patch
# Add pass to remove perimeter points
patch -p0 < remove-perimeter-pts.patch
# Fix build on musl by dropping unnecessary redeclaration of stderr
patch -p0 < fix-musl-build.patch

View File

@@ -1,27 +1,38 @@
project('libfprint', [ 'c', 'cpp' ],
version: '1.94.3',
version: '1.94.9',
license: 'LGPLv2.1+',
default_options: [
'buildtype=debugoptimized',
'warning_level=1',
'c_std=gnu99',
],
meson_version: '>= 0.49.0')
meson_version: '>= 0.59.0')
fs = import('fs')
gnome = import('gnome')
libfprint_conf = configuration_data()
libfprint_conf.set_quoted('LIBFPRINT_VERSION', meson.project_version())
prefix = get_option('prefix')
libdir = prefix / get_option('libdir')
libexecdir = prefix / get_option('libexecdir')
datadir = prefix / get_option('datadir')
cc = meson.get_compiler('c')
cpp = meson.get_compiler('cpp')
host_system = host_machine.system()
glib_min_version = '2.56'
libfprint_sanitizers = get_option('b_sanitize').split(',')
if libfprint_sanitizers == ['none']
libfprint_sanitizers = []
endif
glib_min_version = '2.68'
glib_version_def = 'GLIB_VERSION_@0@_@1@'.format(
glib_min_version.split('.')[0], glib_min_version.split('.')[1])
common_cflags = cc.get_supported_arguments([
'-Wall',
'-Wcast-align',
'-Wformat-nonliteral',
'-Wformat-security',
@@ -86,11 +97,15 @@ gusb_dep = dependency('gusb', version: '>= 0.2.0')
mathlib_dep = cc.find_library('m', required: false)
# The following dependencies are only used for tests
sh = find_program('sh', required: true)
cairo_dep = dependency('cairo', required: false)
# introspection scanning and Gio-2.0.gir
gobject_introspection = dependency('gobject-introspection-1.0', required: get_option('introspection'))
# SPI
have_spi = host_machine.system() == 'linux'
# Drivers
drivers = get_option('drivers').split(',')
virtual_drivers = [
@@ -115,6 +130,7 @@ default_drivers = [
'vfs0050',
'etes603',
'egis0570',
'egismoc',
'vcom5s',
'synaptics',
'elan',
@@ -125,16 +141,43 @@ default_drivers = [
'upekts',
'goodixmoc',
'nb1010',
# SPI
'elanspi',
'fpcmoc',
'realtek',
'focaltech_moc',
]
spi_drivers = [
'elanspi'
]
if have_spi
default_drivers += spi_drivers
endif
# FIXME: All the drivers should be fixed by adjusting the byte order.
# See https://gitlab.freedesktop.org/libfprint/libfprint/-/issues/236
endian_independent_drivers = virtual_drivers + [
'aes1610',
'aes1660',
'aes2550',
'aes2660',
'aes3500',
'aes4000',
'egis0570',
'egismoc',
'elanmoc',
'etes603',
'focaltech_moc',
'nb1010',
'realtek',
'synaptics',
'upeksonly',
'upektc',
'upektc_img',
'upekts',
'vcom5s',
'vfs101',
'vfs7552',
]
all_drivers = default_drivers + virtual_drivers
@@ -147,6 +190,17 @@ if drivers == [ 'default' ]
drivers = default_drivers
endif
enabled_spi_drivers = []
foreach driver : spi_drivers
if driver in drivers
enabled_spi_drivers += driver
endif
endforeach
if enabled_spi_drivers.length() > 0 and not have_spi
error('SPI drivers @0@ are not supported'.format(enabled_spi_drivers))
endif
driver_helper_mapping = {
'aes1610' : [ 'aeslib' ],
'aes1660' : [ 'aeslib', 'aesx660' ],
@@ -155,7 +209,7 @@ driver_helper_mapping = {
'aes2660' : [ 'aeslib', 'aesx660' ],
'aes3500' : [ 'aeslib', 'aes3k' ],
'aes4000' : [ 'aeslib', 'aes3k' ],
'uru4000' : [ 'nss' ],
'uru4000' : [ 'openssl' ],
'elanspi' : [ 'udev' ],
'virtual_image' : [ 'virtual' ],
'virtual_device' : [ 'virtual' ],
@@ -212,13 +266,13 @@ foreach i : driver_helpers
libfprint_conf.set10('HAVE_PIXMAN', true)
optional_deps += imaging_dep
elif i == 'nss'
nss_dep = dependency('nss', required: false)
if not nss_dep.found()
error('nss is required for @0@ and possibly others'.format(driver))
elif i == 'openssl'
openssl_dep = dependency('openssl', version: '>= 3.0', required: false)
if not openssl_dep.found()
error('OpenSSL is required for @0@ and possibly others'.format(driver))
endif
optional_deps += nss_dep
optional_deps += openssl_dep
elif i == 'udev'
install_udev_rules = true
@@ -241,7 +295,7 @@ 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'
udev_rules_dir = udev_dep.get_variable(pkgconfig: 'udevdir') + '/rules.d'
endif
endif
@@ -278,15 +332,13 @@ if not udev_hwdb.disabled()
if udev_hwdb_dir == 'auto'
udev_dep = dependency('udev')
udev_hwdb_dir = udev_dep.get_pkgconfig_variable('udevdir') + '/hwdb.d'
udev_hwdb_dir = udev_dep.get_variable(pkgconfig: 'udevdir') + '/hwdb.d'
endif
else
udev_hwdb_dir = ''
endif
if get_option('gtk-examples')
gnome = import('gnome')
gtk_dep = dependency('gtk+-3.0', required: false)
if not gtk_dep.found()
error('GTK+ 3.x is required for GTK+ examples')
@@ -298,9 +350,7 @@ subdir('libfprint')
configure_file(output: 'config.h', configuration: libfprint_conf)
subdir('examples')
if get_option('doc')
gnome = import('gnome')
subdir('doc')
endif
if get_option('gtk-examples')
@@ -310,6 +360,8 @@ endif
subdir('data')
subdir('tests')
subdir('examples')
pkgconfig = import('pkgconfig')
pkgconfig.generate(
name: versioned_libname,
@@ -320,3 +372,5 @@ pkgconfig.generate(
subdirs: versioned_libname,
filebase: versioned_libname,
)
summary({'Drivers': drivers, }, section: 'Drivers')

View File

@@ -30,3 +30,7 @@ option('doc',
description: 'Whether to build the API documentation',
type: 'boolean',
value: true)
option('installed-tests',
description: 'Whether to install the installed tests',
type: 'boolean',
value: true)

View File

@@ -19,6 +19,7 @@ indent_func_proto_param false
indent_switch_case 0
indent_case_brace 2
indent_paren_close 1
pp_multiline_define_body_indent 2
# spacing
sp_arith Add
@@ -114,13 +115,14 @@ nl_create_for_one_liner False
nl_create_while_one_liner False
nl_after_semicolon True
nl_multi_line_cond true
nl_multi_line_define true
# mod
# I'd like these to be remove, but that removes brackets in if { if { foo } }, which i dislike
# Not clear what to do about that...
mod_full_brace_for Remove
mod_full_brace_if Remove
mod_full_brace_if_chain True
mod_full_brace_if_chain 1
mod_full_brace_while Remove
mod_full_brace_do Remove
mod_full_brace_nl 3

View File

@@ -1,10 +1,15 @@
#!/usr/bin/python3
import gi
gi.require_version('FPrint', '2.0')
from gi.repository import FPrint, GLib
import cairo
import sys
import traceback
import gi
gi.require_version('FPrint', '2.0')
from gi.repository import FPrint, GLib
# Exit with error on any exception, included those happening in async callbacks
sys.excepthook = lambda *args: (traceback.print_exception(*args), sys.exit(1))
if len(sys.argv) != 2:
print("Please specify exactly one argument, the output location for the capture image")

View File

@@ -44,7 +44,7 @@ if len(sys.argv) > 3:
sys.exit(1)
driver_name = sys.argv[1]
os.environ['FP_DRIVERS_WHITELIST'] = driver_name
os.environ['FP_DRIVERS_ALLOWLIST'] = driver_name
test_variant = None
if len(sys.argv) == 3:
@@ -105,6 +105,11 @@ process.wait()
# Run capture
# https://osqa-ask.wireshark.org/questions/53919/how-can-i-precisely-specify-a-usb-device-to-capture-with-tshark/
print(f'### Reseting USB port (as descriptors could be missing in the dump otherwise)')
usb_device.open()
usb_device.reset()
usb_device.close()
print(f'### Starting USB capture on usbmon{bus_num}')
capture_pid = os.fork()
assert(capture_pid >= 0)

5
tests/driver.test.in Normal file
View File

@@ -0,0 +1,5 @@
[Test]
Type=session
# We can't use TestEnvironment as per
# https://gitlab.gnome.org/GNOME/gnome-desktop-testing/-/issues/1
Exec=env @driver_env@ @installed_tests_execdir@/@umockdev_test_name@ @installed_tests_testdir@/@driver_test@

0
tests/egis0570/capture.pcapng Executable file → Normal file
View File

View File

@@ -24,7 +24,7 @@ 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
E: LIBFPRINT_DRIVER=Hardcoded allowlist
A: authorized=1\n
A: avoid_reset_quirk=0\n
A: bConfigurationValue=1\n

Binary file not shown.

156
tests/egismoc-0586/custom.py Executable file
View File

@@ -0,0 +1,156 @@
#!/usr/bin/python3
import traceback
import sys
import time
import gi
gi.require_version('FPrint', '2.0')
from gi.repository import FPrint, GLib
# Exit with error on any exception, included those happening in async callbacks
sys.excepthook = lambda *args: (traceback.print_exception(*args), sys.exit(1))
ctx = GLib.main_context_default()
c = FPrint.Context()
c.enumerate()
devices = c.get_devices()
d = devices[0]
del devices
d.open_sync()
assert d.get_driver() == "egismoc"
assert not d.has_feature(FPrint.DeviceFeature.CAPTURE)
assert d.has_feature(FPrint.DeviceFeature.IDENTIFY)
assert d.has_feature(FPrint.DeviceFeature.VERIFY)
assert d.has_feature(FPrint.DeviceFeature.DUPLICATES_CHECK)
assert d.has_feature(FPrint.DeviceFeature.STORAGE)
assert d.has_feature(FPrint.DeviceFeature.STORAGE_LIST)
assert d.has_feature(FPrint.DeviceFeature.STORAGE_DELETE)
assert d.has_feature(FPrint.DeviceFeature.STORAGE_CLEAR)
def enroll_progress(*args):
print("finger status: ", d.get_finger_status())
print('enroll progress: ' + str(args))
def identify_done(dev, res):
global identified
identified = True
identify_match, identify_print = dev.identify_finish(res)
print('indentification_done: ', identify_match, identify_print)
assert identify_match.equal(identify_print)
# Beginning with list and clear assumes you begin with >0 prints enrolled before capturing
print("listing - device should have prints")
stored = d.list_prints_sync()
assert len(stored) > 0
del stored
print("clear device storage")
d.clear_storage_sync()
print("clear done")
print("listing - device should be empty")
stored = d.list_prints_sync()
assert len(stored) == 0
del stored
print("enrolling")
template = FPrint.Print.new(d)
template.set_finger(FPrint.Finger.LEFT_INDEX)
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
p1 = d.enroll_sync(template, None, enroll_progress, None)
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
print("enroll done")
del template
print("listing - device should have 1 print")
stored = d.list_prints_sync()
assert len(stored) == 1
assert stored[0].equal(p1)
print("verifying")
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
verify_res, verify_print = d.verify_sync(p1)
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
print("verify done")
assert verify_res == True
identified = False
deserialized_prints = []
for p in stored:
deserialized_prints.append(FPrint.Print.deserialize(p.serialize()))
assert deserialized_prints[-1].equal(p)
del stored
print('async identifying')
d.identify(deserialized_prints, callback=identify_done)
del deserialized_prints
while not identified:
ctx.iteration(True)
print("try to enroll duplicate")
template = FPrint.Print.new(d)
template.set_finger(FPrint.Finger.RIGHT_INDEX)
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
try:
d.enroll_sync(template, None, enroll_progress, None)
except GLib.Error as error:
assert error.matches(FPrint.DeviceError.quark(),
FPrint.DeviceError.DATA_DUPLICATE)
except Exception as exc:
raise
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
print("duplicate enroll attempt done")
print("listing - device should still only have 1 print")
stored = d.list_prints_sync()
assert len(stored) == 1
assert stored[0].equal(p1)
del stored
print("enroll new finger")
template = FPrint.Print.new(d)
template.set_finger(FPrint.Finger.RIGHT_INDEX)
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
p2 = d.enroll_sync(template, None, enroll_progress, None)
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
print("enroll new finger done")
del template
print("listing - device should have 2 prints")
stored = d.list_prints_sync()
assert len(stored) == 2
assert (stored[0].equal(p1) and stored[1].equal(p2)) or (stored[0].equal(p2) and stored[1].equal(p1))
del stored
print("deleting first print")
d.delete_print_sync(p1)
print("delete done")
del p1
print("listing - device should only have second print")
stored = d.list_prints_sync()
assert len(stored) == 1
assert stored[0].equal(p2)
del stored
del p2
print("clear device storage")
d.clear_storage_sync()
print("clear done")
print("listing - device should be empty")
stored = d.list_prints_sync()
assert len(stored) == 0
del stored
d.close_sync()
del d
del c

255
tests/egismoc-0586/device Normal file
View File

@@ -0,0 +1,255 @@
P: /devices/pci0000:00/0000:00:14.0/usb1/1-7
N: bus/usb/001/021=12010002FF0000407A1C860556620102030109022700010100A0320904000003FF000000070581020002000705020200020007058303400005
E: BUSNUM=001
E: DEVNAME=/dev/bus/usb/001/021
E: DEVNUM=021
E: DEVTYPE=usb_device
E: DRIVER=usb
E: ID_AUTOSUSPEND=1
E: ID_BUS=usb
E: ID_MODEL=ETU905A88-E
E: ID_MODEL_ENC=ETU905A88-E
E: ID_MODEL_ID=0586
E: ID_PATH=pci-0000:00:14.0-usb-0:7
E: ID_PATH_TAG=pci-0000_00_14_0-usb-0_7
E: ID_PATH_WITH_USB_REVISION=pci-0000:00:14.0-usbv2-0:7
E: ID_PERSIST=0
E: ID_REVISION=6256
E: ID_SERIAL=EGIS_ETU905A88-E_0A5743PCU834
E: ID_SERIAL_SHORT=0A5743PCU834
E: ID_USB_INTERFACES=:ff0000:
E: ID_USB_MODEL=ETU905A88-E
E: ID_USB_MODEL_ENC=ETU905A88-E
E: ID_USB_MODEL_ID=0586
E: ID_USB_REVISION=6256
E: ID_USB_SERIAL=EGIS_ETU905A88-E_0A5743PCU834
E: ID_USB_SERIAL_SHORT=0A5743PCU834
E: ID_USB_VENDOR=EGIS
E: ID_USB_VENDOR_ENC=EGIS
E: ID_USB_VENDOR_ID=1c7a
E: ID_VENDOR=EGIS
E: ID_VENDOR_ENC=EGIS
E: ID_VENDOR_FROM_DATABASE=LighTuning Technology Inc.
E: ID_VENDOR_ID=1c7a
E: MAJOR=189
E: MINOR=20
E: PRODUCT=1c7a/586/6256
E: SUBSYSTEM=usb
E: TYPE=255/0/0
A: authorized=1\n
A: avoid_reset_quirk=0\n
A: bConfigurationValue=1\n
A: bDeviceClass=ff\n
A: bDeviceProtocol=00\n
A: bDeviceSubClass=00\n
A: bMaxPacketSize0=64\n
A: bMaxPower=100mA\n
A: bNumConfigurations=1\n
A: bNumInterfaces= 1\n
A: bcdDevice=6256\n
A: bmAttributes=a0\n
A: busnum=1\n
A: configuration=
H: descriptors=12010002FF0000407A1C860556620102030109022700010100A0320904000003FF000000070581020002000705020200020007058303400005
A: dev=189:20\n
A: devnum=21\n
A: devpath=7\n
L: driver=../../../../../bus/usb/drivers/usb
L: firmware_node=../../../../LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:4e/device:4f/device:56
A: idProduct=0586\n
A: idVendor=1c7a\n
A: ltm_capable=no\n
A: manufacturer=EGIS\n
A: maxchild=0\n
A: physical_location/dock=no\n
A: physical_location/horizontal_position=center\n
A: physical_location/lid=no\n
A: physical_location/panel=front\n
A: physical_location/vertical_position=center\n
L: port=../1-0:1.0/usb1-port7
A: power/active_duration=12644\n
A: power/autosuspend=2\n
A: power/autosuspend_delay_ms=2000\n
A: power/connected_duration=230907\n
A: power/control=auto\n
A: power/level=auto\n
A: power/persist=0\n
A: power/runtime_active_time=12929\n
A: power/runtime_status=active\n
A: power/runtime_suspended_time=217715\n
A: power/wakeup=disabled\n
A: power/wakeup_abort_count=\n
A: power/wakeup_active=\n
A: power/wakeup_active_count=\n
A: power/wakeup_count=\n
A: power/wakeup_expire_count=\n
A: power/wakeup_last_time_ms=\n
A: power/wakeup_max_time_ms=\n
A: power/wakeup_total_time_ms=\n
A: product=ETU905A88-E\n
A: quirks=0x0\n
A: removable=fixed\n
A: rx_lanes=1\n
A: serial=0A5743PCU834\n
A: speed=480\n
A: tx_lanes=1\n
A: urbnum=18\n
A: version= 2.00\n
P: /devices/pci0000:00/0000:00:14.0/usb1
N: bus/usb/001/001=12010002090001406B1D020008060302010109021900010100E0000904000001090000000705810304000C
E: BUSNUM=001
E: CURRENT_TAGS=:seat:
E: DEVNAME=/dev/bus/usb/001/001
E: DEVNUM=001
E: DEVTYPE=usb_device
E: DRIVER=usb
E: ID_AUTOSUSPEND=1
E: ID_BUS=usb
E: ID_FOR_SEAT=usb-pci-0000_00_14_0
E: ID_MODEL=xHCI_Host_Controller
E: ID_MODEL_ENC=xHCI\x20Host\x20Controller
E: ID_MODEL_FROM_DATABASE=2.0 root hub
E: ID_MODEL_ID=0002
E: ID_PATH=pci-0000:00:14.0
E: ID_PATH_TAG=pci-0000_00_14_0
E: ID_REVISION=0608
E: ID_SERIAL=Linux_6.8.5-arch1-1_xhci-hcd_xHCI_Host_Controller_0000:00:14.0
E: ID_SERIAL_SHORT=0000:00:14.0
E: ID_USB_INTERFACES=:090000:
E: ID_USB_MODEL=xHCI_Host_Controller
E: ID_USB_MODEL_ENC=xHCI\x20Host\x20Controller
E: ID_USB_MODEL_ID=0002
E: ID_USB_REVISION=0608
E: ID_USB_SERIAL=Linux_6.8.5-arch1-1_xhci-hcd_xHCI_Host_Controller_0000:00:14.0
E: ID_USB_SERIAL_SHORT=0000:00:14.0
E: ID_USB_VENDOR=Linux_6.8.5-arch1-1_xhci-hcd
E: ID_USB_VENDOR_ENC=Linux\x206.8.5-arch1-1\x20xhci-hcd
E: ID_USB_VENDOR_ID=1d6b
E: ID_VENDOR=Linux_6.8.5-arch1-1_xhci-hcd
E: ID_VENDOR_ENC=Linux\x206.8.5-arch1-1\x20xhci-hcd
E: ID_VENDOR_FROM_DATABASE=Linux Foundation
E: ID_VENDOR_ID=1d6b
E: MAJOR=189
E: MINOR=0
E: PRODUCT=1d6b/2/608
E: SUBSYSTEM=usb
E: TAGS=:seat:
E: TYPE=9/0/1
A: authorized=1\n
A: authorized_default=1\n
A: avoid_reset_quirk=0\n
A: bConfigurationValue=1\n
A: bDeviceClass=09\n
A: bDeviceProtocol=01\n
A: bDeviceSubClass=00\n
A: bMaxPacketSize0=64\n
A: bMaxPower=0mA\n
A: bNumConfigurations=1\n
A: bNumInterfaces= 1\n
A: bcdDevice=0608\n
A: bmAttributes=e0\n
A: busnum=1\n
A: configuration=
H: descriptors=12010002090001406B1D020008060302010109021900010100E0000904000001090000000705810304000C
A: dev=189:0\n
A: devnum=1\n
A: devpath=0\n
L: driver=../../../../bus/usb/drivers/usb
L: firmware_node=../../../LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:4e/device:4f
A: idProduct=0002\n
A: idVendor=1d6b\n
A: interface_authorized_default=1\n
A: ltm_capable=no\n
A: manufacturer=Linux 6.8.5-arch1-1 xhci-hcd\n
A: maxchild=12\n
A: power/active_duration=73066477\n
A: power/autosuspend=0\n
A: power/autosuspend_delay_ms=0\n
A: power/connected_duration=73071614\n
A: power/control=auto\n
A: power/level=auto\n
A: power/runtime_active_time=73070027\n
A: power/runtime_status=active\n
A: power/runtime_suspended_time=0\n
A: power/wakeup=disabled\n
A: power/wakeup_abort_count=\n
A: power/wakeup_active=\n
A: power/wakeup_active_count=\n
A: power/wakeup_count=\n
A: power/wakeup_expire_count=\n
A: power/wakeup_last_time_ms=\n
A: power/wakeup_max_time_ms=\n
A: power/wakeup_total_time_ms=\n
A: product=xHCI Host Controller\n
A: quirks=0x0\n
A: removable=unknown\n
A: rx_lanes=1\n
A: serial=0000:00:14.0\n
A: speed=480\n
A: tx_lanes=1\n
A: urbnum=1111\n
A: version= 2.00\n
P: /devices/pci0000:00/0000:00:14.0
E: DRIVER=xhci_hcd
E: ID_AUTOSUSPEND=1
E: ID_MODEL_FROM_DATABASE=Alder Lake PCH USB 3.2 xHCI Host Controller
E: ID_PATH=pci-0000:00:14.0
E: ID_PATH_TAG=pci-0000_00_14_0
E: ID_PCI_CLASS_FROM_DATABASE=Serial bus controller
E: ID_PCI_INTERFACE_FROM_DATABASE=XHCI
E: ID_PCI_SUBCLASS_FROM_DATABASE=USB controller
E: ID_VENDOR_FROM_DATABASE=Intel Corporation
E: MODALIAS=pci:v00008086d000051EDsv00001043sd0000201Fbc0Csc03i30
E: PCI_CLASS=C0330
E: PCI_ID=8086:51ED
E: PCI_SLOT_NAME=0000:00:14.0
E: PCI_SUBSYS_ID=1043:201F
E: SUBSYSTEM=pci
A: ari_enabled=0\n
A: broken_parity_status=0\n
A: class=0x0c0330\n
H: config=8680ED51060490020130030C000080000400220560000000000000000000000000000000000000000000000043101F20000000007000000000000000FF010000FD0134A089C27F8000000000000000003F6DD80F000000000000000000000000316000000000000000000000000000000180C2C10800000000000000000000000590B7001805E0FE000000000000000009B014F01000400100000000C10A080000080E00001800008F50020000010000090000018680C00009001014000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000B50F110112000000
A: consistent_dma_mask_bits=64\n
A: d3cold_allowed=1\n
A: device=0x51ed\n
A: dma_mask_bits=64\n
L: driver=../../../bus/pci/drivers/xhci_hcd
A: driver_override=(null)\n
A: enable=1\n
L: firmware_node=../../LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:4e
A: irq=143\n
A: local_cpulist=0-15\n
A: local_cpus=ffff\n
A: modalias=pci:v00008086d000051EDsv00001043sd0000201Fbc0Csc03i30\n
A: msi_bus=1\n
A: msi_irqs/143=msi\n
A: msi_irqs/144=msi\n
A: msi_irqs/145=msi\n
A: msi_irqs/146=msi\n
A: msi_irqs/147=msi\n
A: msi_irqs/148=msi\n
A: msi_irqs/149=msi\n
A: msi_irqs/150=msi\n
A: numa_node=-1\n
A: pools=poolinfo - 0.1\nbuffer-2048 0 0 2048 0\nbuffer-512 0 0 512 0\nbuffer-128 0 0 128 0\nbuffer-32 0 0 32 0\nxHCI 1KB stream ctx arrays 0 0 1024 0\nxHCI 256 byte stream ctx arrays 0 0 256 0\nxHCI input/output contexts 8 9 2112 9\nxHCI ring segments 43 53 4096 53\nbuffer-2048 0 16 2048 8\nbuffer-512 0 0 512 0\nbuffer-128 0 0 128 0\nbuffer-32 0 128 32 1\n
A: power/control=auto\n
A: power/runtime_active_time=73070690\n
A: power/runtime_status=active\n
A: power/runtime_suspended_time=0\n
A: power/wakeup=enabled\n
A: power/wakeup_abort_count=0\n
A: power/wakeup_active=0\n
A: power/wakeup_active_count=0\n
A: power/wakeup_count=0\n
A: power/wakeup_expire_count=0\n
A: power/wakeup_last_time_ms=0\n
A: power/wakeup_max_time_ms=0\n
A: power/wakeup_total_time_ms=0\n
A: power_state=D0\n
A: resource=0x0000006005220000 0x000000600522ffff 0x0000000000140204\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n
A: revision=0x01\n
A: subsystem_device=0x201f\n
A: subsystem_vendor=0x1043\n
A: vendor=0x8086\n

Binary file not shown.

156
tests/egismoc-0587/custom.py Executable file
View File

@@ -0,0 +1,156 @@
#!/usr/bin/python3
import traceback
import sys
import time
import gi
gi.require_version('FPrint', '2.0')
from gi.repository import FPrint, GLib
# Exit with error on any exception, included those happening in async callbacks
sys.excepthook = lambda *args: (traceback.print_exception(*args), sys.exit(1))
ctx = GLib.main_context_default()
c = FPrint.Context()
c.enumerate()
devices = c.get_devices()
d = devices[0]
del devices
d.open_sync()
assert d.get_driver() == "egismoc"
assert not d.has_feature(FPrint.DeviceFeature.CAPTURE)
assert d.has_feature(FPrint.DeviceFeature.IDENTIFY)
assert d.has_feature(FPrint.DeviceFeature.VERIFY)
assert d.has_feature(FPrint.DeviceFeature.DUPLICATES_CHECK)
assert d.has_feature(FPrint.DeviceFeature.STORAGE)
assert d.has_feature(FPrint.DeviceFeature.STORAGE_LIST)
assert d.has_feature(FPrint.DeviceFeature.STORAGE_DELETE)
assert d.has_feature(FPrint.DeviceFeature.STORAGE_CLEAR)
def enroll_progress(*args):
print("finger status: ", d.get_finger_status())
print('enroll progress: ' + str(args))
def identify_done(dev, res):
global identified
identified = True
identify_match, identify_print = dev.identify_finish(res)
print('indentification_done: ', identify_match, identify_print)
assert identify_match.equal(identify_print)
# Beginning with list and clear assumes you begin with >0 prints enrolled before capturing
print("listing - device should have prints")
stored = d.list_prints_sync()
assert len(stored) > 0
del stored
print("clear device storage")
d.clear_storage_sync()
print("clear done")
print("listing - device should be empty")
stored = d.list_prints_sync()
assert len(stored) == 0
del stored
print("enrolling")
template = FPrint.Print.new(d)
template.set_finger(FPrint.Finger.LEFT_INDEX)
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
p1 = d.enroll_sync(template, None, enroll_progress, None)
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
print("enroll done")
del template
print("listing - device should have 1 print")
stored = d.list_prints_sync()
assert len(stored) == 1
assert stored[0].equal(p1)
print("verifying")
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
verify_res, verify_print = d.verify_sync(p1)
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
print("verify done")
assert verify_res == True
identified = False
deserialized_prints = []
for p in stored:
deserialized_prints.append(FPrint.Print.deserialize(p.serialize()))
assert deserialized_prints[-1].equal(p)
del stored
print('async identifying')
d.identify(deserialized_prints, callback=identify_done)
del deserialized_prints
while not identified:
ctx.iteration(True)
print("try to enroll duplicate")
template = FPrint.Print.new(d)
template.set_finger(FPrint.Finger.RIGHT_INDEX)
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
try:
d.enroll_sync(template, None, enroll_progress, None)
except GLib.Error as error:
assert error.matches(FPrint.DeviceError.quark(),
FPrint.DeviceError.DATA_DUPLICATE)
except Exception as exc:
raise
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
print("duplicate enroll attempt done")
print("listing - device should still only have 1 print")
stored = d.list_prints_sync()
assert len(stored) == 1
assert stored[0].equal(p1)
del stored
print("enroll new finger")
template = FPrint.Print.new(d)
template.set_finger(FPrint.Finger.RIGHT_INDEX)
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
p2 = d.enroll_sync(template, None, enroll_progress, None)
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
print("enroll new finger done")
del template
print("listing - device should have 2 prints")
stored = d.list_prints_sync()
assert len(stored) == 2
assert (stored[0].equal(p1) and stored[1].equal(p2)) or (stored[0].equal(p2) and stored[1].equal(p1))
del stored
print("deleting first print")
d.delete_print_sync(p1)
print("delete done")
del p1
print("listing - device should only have second print")
stored = d.list_prints_sync()
assert len(stored) == 1
assert stored[0].equal(p2)
del stored
del p2
print("clear device storage")
d.clear_storage_sync()
print("clear done")
print("listing - device should be empty")
stored = d.list_prints_sync()
assert len(stored) == 0
del stored
d.close_sync()
del d
del c

270
tests/egismoc-0587/device Normal file
View File

@@ -0,0 +1,270 @@
P: /devices/pci0000:00/0000:00:14.0/usb3/3-5
N: bus/usb/003/009=12010002FF0000407A1C870567640102030109022700010100A0320904000003FF000000070581020002000705020200020007058303400005
E: BUSNUM=003
E: DEVNAME=/dev/bus/usb/003/009
E: DEVNUM=009
E: DEVTYPE=usb_device
E: DRIVER=usb
E: ID_AUTOSUSPEND=1
E: ID_BUS=usb
E: ID_MODEL=ETU905A88-E
E: ID_MODEL_ENC=ETU905A88-E
E: ID_MODEL_ID=0587
E: ID_PATH=pci-0000:00:14.0-usb-0:5
E: ID_PATH_TAG=pci-0000_00_14_0-usb-0_5
E: ID_PATH_WITH_USB_REVISION=pci-0000:00:14.0-usbv2-0:5
E: ID_PERSIST=0
E: ID_REVISION=6467
E: ID_SERIAL=EGIS_ETU905A88-E_198427PCU834
E: ID_SERIAL_SHORT=198427PCU834
E: ID_USB_INTERFACES=:ff0000:
E: ID_USB_MODEL=ETU905A88-E
E: ID_USB_MODEL_ENC=ETU905A88-E
E: ID_USB_MODEL_ID=0587
E: ID_USB_REVISION=6467
E: ID_USB_SERIAL=EGIS_ETU905A88-E_198427PCU834
E: ID_USB_SERIAL_SHORT=198427PCU834
E: ID_USB_VENDOR=EGIS
E: ID_USB_VENDOR_ENC=EGIS
E: ID_USB_VENDOR_ID=1c7a
E: ID_VENDOR=EGIS
E: ID_VENDOR_ENC=EGIS
E: ID_VENDOR_FROM_DATABASE=LighTuning Technology Inc.
E: ID_VENDOR_ID=1c7a
E: MAJOR=189
E: MINOR=264
E: PRODUCT=1c7a/587/6467
E: SUBSYSTEM=usb
E: TYPE=255/0/0
A: authorized=1\n
A: avoid_reset_quirk=0\n
A: bConfigurationValue=1\n
A: bDeviceClass=ff\n
A: bDeviceProtocol=00\n
A: bDeviceSubClass=00\n
A: bMaxPacketSize0=64\n
A: bMaxPower=100mA\n
A: bNumConfigurations=1\n
A: bNumInterfaces= 1\n
A: bcdDevice=6467\n
A: bmAttributes=a0\n
A: busnum=3\n
A: configuration=
H: descriptors=12010002FF0000407A1C870567640102030109022700010100A0320904000003FF000000070581020002000705020200020007058303400005
A: dev=189:264\n
A: devnum=9\n
A: devpath=5\n
L: driver=../../../../../bus/usb/drivers/usb
L: firmware_node=../../../../LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:4e/device:4f/device:54
A: idProduct=0587\n
A: idVendor=1c7a\n
A: ltm_capable=no\n
A: manufacturer=EGIS\n
A: maxchild=0\n
A: physical_location/dock=no\n
A: physical_location/horizontal_position=left\n
A: physical_location/lid=no\n
A: physical_location/panel=top\n
A: physical_location/vertical_position=upper\n
L: port=../3-0:1.0/usb3-port5
A: power/active_duration=58096\n
A: power/async=enabled\n
A: power/autosuspend=2\n
A: power/autosuspend_delay_ms=2000\n
A: power/connected_duration=183928\n
A: power/control=auto\n
A: power/level=auto\n
A: power/persist=0\n
A: power/runtime_active_kids=0\n
A: power/runtime_active_time=58510\n
A: power/runtime_enabled=enabled\n
A: power/runtime_status=active\n
A: power/runtime_suspended_time=125136\n
A: power/runtime_usage=0\n
A: power/wakeup=disabled\n
A: power/wakeup_abort_count=\n
A: power/wakeup_active=\n
A: power/wakeup_active_count=\n
A: power/wakeup_count=\n
A: power/wakeup_expire_count=\n
A: power/wakeup_last_time_ms=\n
A: power/wakeup_max_time_ms=\n
A: power/wakeup_total_time_ms=\n
A: product=ETU905A88-E\n
A: quirks=0x0\n
A: removable=fixed\n
A: rx_lanes=1\n
A: serial=198427PCU834\n
A: speed=480\n
A: tx_lanes=1\n
A: urbnum=547\n
A: version= 2.00\n
P: /devices/pci0000:00/0000:00:14.0/usb3
N: bus/usb/003/001=12010002090001406B1D020006060302010109021900010100E0000904000001090000000705810304000C
E: BUSNUM=003
E: CURRENT_TAGS=:seat:
E: DEVNAME=/dev/bus/usb/003/001
E: DEVNUM=001
E: DEVTYPE=usb_device
E: DRIVER=usb
E: ID_AUTOSUSPEND=1
E: ID_BUS=usb
E: ID_FOR_SEAT=usb-pci-0000_00_14_0
E: ID_MODEL=xHCI_Host_Controller
E: ID_MODEL_ENC=xHCI\x20Host\x20Controller
E: ID_MODEL_FROM_DATABASE=2.0 root hub
E: ID_MODEL_ID=0002
E: ID_PATH=pci-0000:00:14.0
E: ID_PATH_TAG=pci-0000_00_14_0
E: ID_REVISION=0606
E: ID_SERIAL=Linux_6.6.0-14-generic_xhci-hcd_xHCI_Host_Controller_0000:00:14.0
E: ID_SERIAL_SHORT=0000:00:14.0
E: ID_USB_INTERFACES=:090000:
E: ID_USB_MODEL=xHCI_Host_Controller
E: ID_USB_MODEL_ENC=xHCI\x20Host\x20Controller
E: ID_USB_MODEL_ID=0002
E: ID_USB_REVISION=0606
E: ID_USB_SERIAL=Linux_6.6.0-14-generic_xhci-hcd_xHCI_Host_Controller_0000:00:14.0
E: ID_USB_SERIAL_SHORT=0000:00:14.0
E: ID_USB_VENDOR=Linux_6.6.0-14-generic_xhci-hcd
E: ID_USB_VENDOR_ENC=Linux\x206.6.0-14-generic\x20xhci-hcd
E: ID_USB_VENDOR_ID=1d6b
E: ID_VENDOR=Linux_6.6.0-14-generic_xhci-hcd
E: ID_VENDOR_ENC=Linux\x206.6.0-14-generic\x20xhci-hcd
E: ID_VENDOR_FROM_DATABASE=Linux Foundation
E: ID_VENDOR_ID=1d6b
E: MAJOR=189
E: MINOR=256
E: PRODUCT=1d6b/2/606
E: SUBSYSTEM=usb
E: TAGS=:seat:
E: TYPE=9/0/1
A: authorized=1\n
A: authorized_default=1\n
A: avoid_reset_quirk=0\n
A: bConfigurationValue=1\n
A: bDeviceClass=09\n
A: bDeviceProtocol=01\n
A: bDeviceSubClass=00\n
A: bMaxPacketSize0=64\n
A: bMaxPower=0mA\n
A: bNumConfigurations=1\n
A: bNumInterfaces= 1\n
A: bcdDevice=0606\n
A: bmAttributes=e0\n
A: busnum=3\n
A: configuration=
H: descriptors=12010002090001406B1D020006060302010109021900010100E0000904000001090000000705810304000C
A: dev=189:256\n
A: devnum=1\n
A: devpath=0\n
L: driver=../../../../bus/usb/drivers/usb
L: firmware_node=../../../LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:4e/device:4f
A: idProduct=0002\n
A: idVendor=1d6b\n
A: interface_authorized_default=1\n
A: ltm_capable=no\n
A: manufacturer=Linux 6.6.0-14-generic xhci-hcd\n
A: maxchild=12\n
A: power/active_duration=5145268\n
A: power/async=enabled\n
A: power/autosuspend=0\n
A: power/autosuspend_delay_ms=0\n
A: power/connected_duration=5191200\n
A: power/control=auto\n
A: power/level=auto\n
A: power/runtime_active_kids=2\n
A: power/runtime_active_time=5145262\n
A: power/runtime_enabled=enabled\n
A: power/runtime_status=active\n
A: power/runtime_suspended_time=45937\n
A: power/runtime_usage=0\n
A: power/wakeup=disabled\n
A: power/wakeup_abort_count=\n
A: power/wakeup_active=\n
A: power/wakeup_active_count=\n
A: power/wakeup_count=\n
A: power/wakeup_expire_count=\n
A: power/wakeup_last_time_ms=\n
A: power/wakeup_max_time_ms=\n
A: power/wakeup_total_time_ms=\n
A: product=xHCI Host Controller\n
A: quirks=0x0\n
A: removable=unknown\n
A: rx_lanes=1\n
A: serial=0000:00:14.0\n
A: speed=480\n
A: tx_lanes=1\n
A: urbnum=637\n
A: version= 2.00\n
P: /devices/pci0000:00/0000:00:14.0
E: DRIVER=xhci_hcd
E: ID_AUTOSUSPEND=1
E: ID_MODEL_FROM_DATABASE=Alder Lake PCH USB 3.2 xHCI Host Controller
E: ID_PATH=pci-0000:00:14.0
E: ID_PATH_TAG=pci-0000_00_14_0
E: ID_PCI_CLASS_FROM_DATABASE=Serial bus controller
E: ID_PCI_INTERFACE_FROM_DATABASE=XHCI
E: ID_PCI_SUBCLASS_FROM_DATABASE=USB controller
E: ID_VENDOR_FROM_DATABASE=Intel Corporation
E: MODALIAS=pci:v00008086d000051EDsv00001043sd0000201Fbc0Csc03i30
E: PCI_CLASS=C0330
E: PCI_ID=8086:51ED
E: PCI_SLOT_NAME=0000:00:14.0
E: PCI_SUBSYS_ID=1043:201F
E: SUBSYSTEM=pci
A: ari_enabled=0\n
A: broken_parity_status=0\n
A: class=0x0c0330\n
H: config=8680ED51060490020130030C000080000400262F62000000000000000000000000000000000000000000000043101F20000000007000000000000000FF010000FD0134A089C27F8000000000000000003F6DD80F000000000000000000000000316000000000000000000000000000000180C2C1080000000000000000000000059087001805E0FE000000000000000009B014F01000400100000000C10A080000080E00001800008F50020000010000090000018680C00009001014000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000B50F110112000000
A: consistent_dma_mask_bits=64\n
A: d3cold_allowed=1\n
A: dbc=disabled\n
A: dbc_bInterfaceProtocol=01\n
A: dbc_bcdDevice=0010\n
A: dbc_idProduct=0010\n
A: dbc_idVendor=1d6b\n
A: device=0x51ed\n
A: dma_mask_bits=64\n
L: driver=../../../bus/pci/drivers/xhci_hcd
A: driver_override=(null)\n
A: enable=1\n
L: firmware_node=../../LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:4e
A: index=10\n
L: iommu=../../virtual/iommu/dmar1
L: iommu_group=../../../kernel/iommu_groups/11
A: irq=145\n
A: label=Onboard - Other\n
A: local_cpulist=0-19\n
A: local_cpus=fffff\n
A: modalias=pci:v00008086d000051EDsv00001043sd0000201Fbc0Csc03i30\n
A: msi_bus=1\n
A: msi_irqs/145=msi\n
A: numa_node=-1\n
A: pools=poolinfo - 0.1\nbuffer-2048 0 0 2048 0\nbuffer-512 0 0 512 0\nbuffer-128 1 32 128 1\nbuffer-32 0 0 32 0\nxHCI 1KB stream ctx arrays 0 0 1024 0\nxHCI 256 byte stream ctx arrays 0 0 256 0\nxHCI input/output contexts 10 11 2112 11\nxHCI ring segments 38 38 4096 38\nbuffer-2048 0 0 2048 0\nbuffer-512 0 0 512 0\nbuffer-128 6 32 128 1\nbuffer-32 0 0 32 0\n
A: power/async=enabled\n
A: power/control=auto\n
A: power/runtime_active_kids=2\n
A: power/runtime_active_time=5192072\n
A: power/runtime_enabled=enabled\n
A: power/runtime_status=active\n
A: power/runtime_suspended_time=0\n
A: power/runtime_usage=0\n
A: power/wakeup=enabled\n
A: power/wakeup_abort_count=0\n
A: power/wakeup_active=0\n
A: power/wakeup_active_count=0\n
A: power/wakeup_count=0\n
A: power/wakeup_expire_count=0\n
A: power/wakeup_last_time_ms=0\n
A: power/wakeup_max_time_ms=0\n
A: power/wakeup_total_time_ms=0\n
A: power_state=D0\n
A: resource=0x000000622f260000 0x000000622f26ffff 0x0000000000140204\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n
A: revision=0x01\n
A: subsystem_device=0x201f\n
A: subsystem_vendor=0x1043\n
A: vendor=0x8086\n

Binary file not shown.

156
tests/egismoc-05a1/custom.py Executable file
View File

@@ -0,0 +1,156 @@
#!/usr/bin/python3
import traceback
import sys
import time
import gi
gi.require_version('FPrint', '2.0')
from gi.repository import FPrint, GLib
# Exit with error on any exception, included those happening in async callbacks
sys.excepthook = lambda *args: (traceback.print_exception(*args), sys.exit(1))
ctx = GLib.main_context_default()
c = FPrint.Context()
c.enumerate()
devices = c.get_devices()
d = devices[0]
del devices
d.open_sync()
assert d.get_driver() == "egismoc"
assert not d.has_feature(FPrint.DeviceFeature.CAPTURE)
assert d.has_feature(FPrint.DeviceFeature.IDENTIFY)
assert d.has_feature(FPrint.DeviceFeature.VERIFY)
assert d.has_feature(FPrint.DeviceFeature.DUPLICATES_CHECK)
assert d.has_feature(FPrint.DeviceFeature.STORAGE)
assert d.has_feature(FPrint.DeviceFeature.STORAGE_LIST)
assert d.has_feature(FPrint.DeviceFeature.STORAGE_DELETE)
assert d.has_feature(FPrint.DeviceFeature.STORAGE_CLEAR)
def enroll_progress(*args):
print("finger status: ", d.get_finger_status())
print('enroll progress: ' + str(args))
def identify_done(dev, res):
global identified
identified = True
identify_match, identify_print = dev.identify_finish(res)
print('indentification_done: ', identify_match, identify_print)
assert identify_match.equal(identify_print)
# Beginning with list and clear assumes you begin with >0 prints enrolled before capturing
print("listing - device should have prints")
stored = d.list_prints_sync()
assert len(stored) > 0
del stored
print("clear device storage")
d.clear_storage_sync()
print("clear done")
print("listing - device should be empty")
stored = d.list_prints_sync()
assert len(stored) == 0
del stored
print("enrolling")
template = FPrint.Print.new(d)
template.set_finger(FPrint.Finger.LEFT_INDEX)
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
p1 = d.enroll_sync(template, None, enroll_progress, None)
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
print("enroll done")
del template
print("listing - device should have 1 print")
stored = d.list_prints_sync()
assert len(stored) == 1
assert stored[0].equal(p1)
print("verifying")
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
verify_res, verify_print = d.verify_sync(p1)
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
print("verify done")
assert verify_res == True
identified = False
deserialized_prints = []
for p in stored:
deserialized_prints.append(FPrint.Print.deserialize(p.serialize()))
assert deserialized_prints[-1].equal(p)
del stored
print('async identifying')
d.identify(deserialized_prints, callback=identify_done)
del deserialized_prints
while not identified:
ctx.iteration(True)
print("try to enroll duplicate")
template = FPrint.Print.new(d)
template.set_finger(FPrint.Finger.RIGHT_INDEX)
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
try:
d.enroll_sync(template, None, enroll_progress, None)
except GLib.Error as error:
assert error.matches(FPrint.DeviceError.quark(),
FPrint.DeviceError.DATA_DUPLICATE)
except Exception as exc:
raise
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
print("duplicate enroll attempt done")
print("listing - device should still only have 1 print")
stored = d.list_prints_sync()
assert len(stored) == 1
assert stored[0].equal(p1)
del stored
print("enroll new finger")
template = FPrint.Print.new(d)
template.set_finger(FPrint.Finger.RIGHT_INDEX)
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
p2 = d.enroll_sync(template, None, enroll_progress, None)
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
print("enroll new finger done")
del template
print("listing - device should have 2 prints")
stored = d.list_prints_sync()
assert len(stored) == 2
assert (stored[0].equal(p1) and stored[1].equal(p2)) or (stored[0].equal(p2) and stored[1].equal(p1))
del stored
print("deleting first print")
d.delete_print_sync(p1)
print("delete done")
del p1
print("listing - device should only have second print")
stored = d.list_prints_sync()
assert len(stored) == 1
assert stored[0].equal(p2)
del stored
del p2
print("clear device storage")
d.clear_storage_sync()
print("clear done")
print("listing - device should be empty")
stored = d.list_prints_sync()
assert len(stored) == 0
del stored
d.close_sync()
del d
del c

262
tests/egismoc-05a1/device Normal file
View File

@@ -0,0 +1,262 @@
P: /devices/pci0000:00/0000:00:14.0/usb1/1-5
N: bus/usb/001/003=12010002FF0000407A1CA10513120102030109022700010100A0320904000003FF000000070581020002000705020200020007058303400005
E: BUSNUM=001
E: DEVNAME=/dev/bus/usb/001/003
E: DEVNUM=003
E: DEVTYPE=usb_device
E: DRIVER=usb
E: ID_BUS=usb
E: ID_MODEL=ETU905A80-E
E: ID_MODEL_ENC=ETU905A80-E
E: ID_MODEL_ID=05a1
E: ID_REVISION=1213
E: ID_SERIAL=EGIS_ETU905A80-E_0C5A44PCU833
E: ID_SERIAL_SHORT=0C5A44PCU833
E: ID_USB_INTERFACES=:ff0000:
E: ID_USB_MODEL=ETU905A80-E
E: ID_USB_MODEL_ENC=ETU905A80-E
E: ID_USB_MODEL_ID=05a1
E: ID_USB_REVISION=1213
E: ID_USB_SERIAL=EGIS_ETU905A80-E_0C5A44PCU833
E: ID_USB_SERIAL_SHORT=0C5A44PCU833
E: ID_USB_VENDOR=EGIS
E: ID_USB_VENDOR_ENC=EGIS
E: ID_USB_VENDOR_ID=1c7a
E: ID_VENDOR=EGIS
E: ID_VENDOR_ENC=EGIS
E: ID_VENDOR_FROM_DATABASE=LighTuning Technology Inc.
E: ID_VENDOR_ID=1c7a
E: MAJOR=189
E: MINOR=2
E: PRODUCT=1c7a/5a1/1213
E: SUBSYSTEM=usb
E: TYPE=255/0/0
A: authorized=1\n
A: avoid_reset_quirk=0\n
A: bConfigurationValue=1\n
A: bDeviceClass=ff\n
A: bDeviceProtocol=00\n
A: bDeviceSubClass=00\n
A: bMaxPacketSize0=64\n
A: bMaxPower=100mA\n
A: bNumConfigurations=1\n
A: bNumInterfaces= 1\n
A: bcdDevice=1213\n
A: bmAttributes=a0\n
A: busnum=1\n
A: configuration=
H: descriptors=12010002FF0000407A1CA10513120102030109022700010100A0320904000003FF000000070581020002000705020200020007058303400005
A: dev=189:2\n
A: devnum=3\n
A: devpath=5\n
L: driver=../../../../../bus/usb/drivers/usb
L: firmware_node=../../../../LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:51/device:52/device:57
A: idProduct=05a1\n
A: idVendor=1c7a\n
A: ltm_capable=no\n
A: manufacturer=EGIS\n
A: maxchild=0\n
A: physical_location/dock=no\n
A: physical_location/horizontal_position=center\n
A: physical_location/lid=no\n
A: physical_location/panel=unknown\n
A: physical_location/vertical_position=center\n
L: port=../1-0:1.0/usb1-port5
A: power/active_duration=955612\n
A: power/async=enabled\n
A: power/autosuspend=2\n
A: power/autosuspend_delay_ms=2000\n
A: power/connected_duration=955612\n
A: power/control=on\n
A: power/level=on\n
A: power/persist=0\n
A: power/runtime_active_kids=0\n
A: power/runtime_active_time=955338\n
A: power/runtime_enabled=forbidden\n
A: power/runtime_status=active\n
A: power/runtime_suspended_time=0\n
A: power/runtime_usage=1\n
A: power/wakeup=disabled\n
A: power/wakeup_abort_count=\n
A: power/wakeup_active=\n
A: power/wakeup_active_count=\n
A: power/wakeup_count=\n
A: power/wakeup_expire_count=\n
A: power/wakeup_last_time_ms=\n
A: power/wakeup_max_time_ms=\n
A: power/wakeup_total_time_ms=\n
A: product=ETU905A80-E\n
A: quirks=0x0\n
A: removable=fixed\n
A: rx_lanes=1\n
A: serial=0C5A44PCU833\n
A: speed=480\n
A: tx_lanes=1\n
A: urbnum=491\n
A: version= 2.00\n
P: /devices/pci0000:00/0000:00:14.0/usb1
N: bus/usb/001/001=12010002090001406B1D020005060302010109021900010100E0000904000001090000000705810304000C
E: BUSNUM=001
E: CURRENT_TAGS=:seat:
E: DEVNAME=/dev/bus/usb/001/001
E: DEVNUM=001
E: DEVTYPE=usb_device
E: DRIVER=usb
E: ID_AUTOSUSPEND=1
E: ID_BUS=usb
E: ID_FOR_SEAT=usb-pci-0000_00_14_0
E: ID_MODEL=xHCI_Host_Controller
E: ID_MODEL_ENC=xHCI\x20Host\x20Controller
E: ID_MODEL_FROM_DATABASE=2.0 root hub
E: ID_MODEL_ID=0002
E: ID_PATH=pci-0000:00:14.0
E: ID_PATH_TAG=pci-0000_00_14_0
E: ID_REVISION=0605
E: ID_SERIAL=Linux_6.5.0-9-generic_xhci-hcd_xHCI_Host_Controller_0000:00:14.0
E: ID_SERIAL_SHORT=0000:00:14.0
E: ID_USB_INTERFACES=:090000:
E: ID_USB_MODEL=xHCI_Host_Controller
E: ID_USB_MODEL_ENC=xHCI\x20Host\x20Controller
E: ID_USB_MODEL_ID=0002
E: ID_USB_REVISION=0605
E: ID_USB_SERIAL=Linux_6.5.0-9-generic_xhci-hcd_xHCI_Host_Controller_0000:00:14.0
E: ID_USB_SERIAL_SHORT=0000:00:14.0
E: ID_USB_VENDOR=Linux_6.5.0-9-generic_xhci-hcd
E: ID_USB_VENDOR_ENC=Linux\x206.5.0-9-generic\x20xhci-hcd
E: ID_USB_VENDOR_ID=1d6b
E: ID_VENDOR=Linux_6.5.0-9-generic_xhci-hcd
E: ID_VENDOR_ENC=Linux\x206.5.0-9-generic\x20xhci-hcd
E: ID_VENDOR_FROM_DATABASE=Linux Foundation
E: ID_VENDOR_ID=1d6b
E: MAJOR=189
E: MINOR=0
E: PRODUCT=1d6b/2/605
E: SUBSYSTEM=usb
E: TAGS=:seat:
E: TYPE=9/0/1
A: authorized=1\n
A: authorized_default=1\n
A: avoid_reset_quirk=0\n
A: bConfigurationValue=1\n
A: bDeviceClass=09\n
A: bDeviceProtocol=01\n
A: bDeviceSubClass=00\n
A: bMaxPacketSize0=64\n
A: bMaxPower=0mA\n
A: bNumConfigurations=1\n
A: bNumInterfaces= 1\n
A: bcdDevice=0605\n
A: bmAttributes=e0\n
A: busnum=1\n
A: configuration=
H: descriptors=12010002090001406B1D020005060302010109021900010100E0000904000001090000000705810304000C
A: dev=189:0\n
A: devnum=1\n
A: devpath=0\n
L: driver=../../../../bus/usb/drivers/usb
L: firmware_node=../../../LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:51/device:52
A: idProduct=0002\n
A: idVendor=1d6b\n
A: interface_authorized_default=1\n
A: ltm_capable=no\n
A: manufacturer=Linux 6.5.0-9-generic xhci-hcd\n
A: maxchild=12\n
A: power/active_duration=956044\n
A: power/async=enabled\n
A: power/autosuspend=0\n
A: power/autosuspend_delay_ms=0\n
A: power/connected_duration=956044\n
A: power/control=auto\n
A: power/level=auto\n
A: power/runtime_active_kids=2\n
A: power/runtime_active_time=956041\n
A: power/runtime_enabled=enabled\n
A: power/runtime_status=active\n
A: power/runtime_suspended_time=0\n
A: power/runtime_usage=0\n
A: power/wakeup=disabled\n
A: power/wakeup_abort_count=\n
A: power/wakeup_active=\n
A: power/wakeup_active_count=\n
A: power/wakeup_count=\n
A: power/wakeup_expire_count=\n
A: power/wakeup_last_time_ms=\n
A: power/wakeup_max_time_ms=\n
A: power/wakeup_total_time_ms=\n
A: product=xHCI Host Controller\n
A: quirks=0x0\n
A: removable=unknown\n
A: rx_lanes=1\n
A: serial=0000:00:14.0\n
A: speed=480\n
A: tx_lanes=1\n
A: urbnum=181\n
A: version= 2.00\n
P: /devices/pci0000:00/0000:00:14.0
E: DRIVER=xhci_hcd
E: ID_MODEL_FROM_DATABASE=Alder Lake PCH USB 3.2 xHCI Host Controller
E: ID_PCI_CLASS_FROM_DATABASE=Serial bus controller
E: ID_PCI_INTERFACE_FROM_DATABASE=XHCI
E: ID_PCI_SUBCLASS_FROM_DATABASE=USB controller
E: ID_VENDOR_FROM_DATABASE=Intel Corporation
E: MODALIAS=pci:v00008086d000051EDsv0000144Dsd0000C1CAbc0Csc03i30
E: PCI_CLASS=C0330
E: PCI_ID=8086:51ED
E: PCI_SLOT_NAME=0000:00:14.0
E: PCI_SUBSYS_ID=144D:C1CA
E: SUBSYSTEM=pci
A: ari_enabled=0\n
A: broken_parity_status=0\n
A: class=0x0c0330\n
H: config=8680ED51060490020130030C0000800004001A3E6000000000000000000000000000000000000000000000004D14CAC1000000007000000000000000FF010000FD0134A089C27F8000000000000000003F6DD80F000000000000000000000000316000000000000000000000000000000180C2C108000000000000000000000005908700D804E0FE000000000000000009B014F01000400100000000C10A080000080E00001800008F50020000010000090000018680C00009001014000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000B50F110112000000
A: consistent_dma_mask_bits=64\n
A: d3cold_allowed=1\n
A: dbc=disabled\n
A: dbc_bInterfaceProtocol=01\n
A: dbc_bcdDevice=0010\n
A: dbc_idProduct=0010\n
A: dbc_idVendor=1d6b\n
A: device=0x51ed\n
A: dma_mask_bits=64\n
L: driver=../../../bus/pci/drivers/xhci_hcd
A: driver_override=(null)\n
A: enable=1\n
L: firmware_node=../../LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:51
A: index=9\n
L: iommu=../../virtual/iommu/dmar2
L: iommu_group=../../../kernel/iommu_groups/11
A: irq=142\n
A: label=Onboard - Other\n
A: local_cpulist=0-15\n
A: local_cpus=ffff\n
A: modalias=pci:v00008086d000051EDsv0000144Dsd0000C1CAbc0Csc03i30\n
A: msi_bus=1\n
A: msi_irqs/142=msi\n
A: numa_node=-1\n
A: pools=poolinfo - 0.1\nbuffer-2048 0 0 2048 0\nbuffer-512 0 0 512 0\nbuffer-128 0 0 128 0\nbuffer-32 0 0 32 0\nxHCI 1KB stream ctx arrays 0 0 1024 0\nxHCI 256 byte stream ctx arrays 0 0 256 0\nxHCI input/output contexts 6 7 2112 7\nxHCI ring segments 28 28 4096 28\nbuffer-2048 0 0 2048 0\nbuffer-512 0 0 512 0\nbuffer-128 1 32 128 1\nbuffer-32 0 0 32 0\n
A: power/async=enabled\n
A: power/control=auto\n
A: power/runtime_active_kids=1\n
A: power/runtime_active_time=957198\n
A: power/runtime_enabled=enabled\n
A: power/runtime_status=active\n
A: power/runtime_suspended_time=0\n
A: power/runtime_usage=0\n
A: power/wakeup=enabled\n
A: power/wakeup_abort_count=0\n
A: power/wakeup_active=0\n
A: power/wakeup_active_count=0\n
A: power/wakeup_count=0\n
A: power/wakeup_expire_count=0\n
A: power/wakeup_last_time_ms=0\n
A: power/wakeup_max_time_ms=0\n
A: power/wakeup_total_time_ms=0\n
A: power_state=D0\n
A: resource=0x000000603e1a0000 0x000000603e1affff 0x0000000000140204\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n
A: revision=0x01\n
A: subsystem_device=0xc1ca\n
A: subsystem_vendor=0x144d\n
A: vendor=0x8086\n

BIN
tests/egismoc/custom.pcapng Normal file

Binary file not shown.

156
tests/egismoc/custom.py Executable file
View File

@@ -0,0 +1,156 @@
#!/usr/bin/python3
import traceback
import sys
import time
import gi
gi.require_version('FPrint', '2.0')
from gi.repository import FPrint, GLib
# Exit with error on any exception, included those happening in async callbacks
sys.excepthook = lambda *args: (traceback.print_exception(*args), sys.exit(1))
ctx = GLib.main_context_default()
c = FPrint.Context()
c.enumerate()
devices = c.get_devices()
d = devices[0]
del devices
d.open_sync()
assert d.get_driver() == "egismoc"
assert not d.has_feature(FPrint.DeviceFeature.CAPTURE)
assert d.has_feature(FPrint.DeviceFeature.IDENTIFY)
assert d.has_feature(FPrint.DeviceFeature.VERIFY)
assert d.has_feature(FPrint.DeviceFeature.DUPLICATES_CHECK)
assert d.has_feature(FPrint.DeviceFeature.STORAGE)
assert d.has_feature(FPrint.DeviceFeature.STORAGE_LIST)
assert d.has_feature(FPrint.DeviceFeature.STORAGE_DELETE)
assert d.has_feature(FPrint.DeviceFeature.STORAGE_CLEAR)
def enroll_progress(*args):
print("finger status: ", d.get_finger_status())
print('enroll progress: ' + str(args))
def identify_done(dev, res):
global identified
identified = True
identify_match, identify_print = dev.identify_finish(res)
print('indentification_done: ', identify_match, identify_print)
assert identify_match.equal(identify_print)
# Beginning with list and clear assumes you begin with >0 prints enrolled before capturing
print("listing - device should have prints")
stored = d.list_prints_sync()
assert len(stored) > 0
del stored
print("clear device storage")
d.clear_storage_sync()
print("clear done")
print("listing - device should be empty")
stored = d.list_prints_sync()
assert len(stored) == 0
del stored
print("enrolling")
template = FPrint.Print.new(d)
template.set_finger(FPrint.Finger.LEFT_INDEX)
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
p1 = d.enroll_sync(template, None, enroll_progress, None)
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
print("enroll done")
del template
print("listing - device should have 1 print")
stored = d.list_prints_sync()
assert len(stored) == 1
assert stored[0].equal(p1)
print("verifying")
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
verify_res, verify_print = d.verify_sync(p1)
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
print("verify done")
assert verify_res == True
identified = False
deserialized_prints = []
for p in stored:
deserialized_prints.append(FPrint.Print.deserialize(p.serialize()))
assert deserialized_prints[-1].equal(p)
del stored
print('async identifying')
d.identify(deserialized_prints, callback=identify_done)
del deserialized_prints
while not identified:
ctx.iteration(True)
print("try to enroll duplicate")
template = FPrint.Print.new(d)
template.set_finger(FPrint.Finger.RIGHT_INDEX)
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
try:
d.enroll_sync(template, None, enroll_progress, None)
except GLib.Error as error:
assert error.matches(FPrint.DeviceError.quark(),
FPrint.DeviceError.DATA_DUPLICATE)
except Exception as exc:
raise
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
print("duplicate enroll attempt done")
print("listing - device should still only have 1 print")
stored = d.list_prints_sync()
assert len(stored) == 1
assert stored[0].equal(p1)
del stored
print("enroll new finger")
template = FPrint.Print.new(d)
template.set_finger(FPrint.Finger.RIGHT_INDEX)
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
p2 = d.enroll_sync(template, None, enroll_progress, None)
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
print("enroll new finger done")
del template
print("listing - device should have 2 prints")
stored = d.list_prints_sync()
assert len(stored) == 2
assert (stored[0].equal(p1) and stored[1].equal(p2)) or (stored[0].equal(p2) and stored[1].equal(p1))
del stored
print("deleting first print")
d.delete_print_sync(p1)
print("delete done")
del p1
print("listing - device should only have second print")
stored = d.list_prints_sync()
assert len(stored) == 1
assert stored[0].equal(p2)
del stored
del p2
print("clear device storage")
d.clear_storage_sync()
print("clear done")
print("listing - device should be empty")
stored = d.list_prints_sync()
assert len(stored) == 0
del stored
d.close_sync()
del d
del c

262
tests/egismoc/device Normal file
View File

@@ -0,0 +1,262 @@
P: /devices/pci0000:00/0000:00:14.0/usb3/3-5
N: bus/usb/003/012=12010002FF0000407A1C820581110102030109022700010100A0320904000003FF000000070581020002000705020200020007058303400005
E: BUSNUM=003
E: CURRENT_TAGS=:snap_cups_ippeveprinter:snap_cups_cupsd:
E: DEVNAME=/dev/bus/usb/003/012
E: DEVNUM=012
E: DEVTYPE=usb_device
E: DRIVER=usb
E: ID_BUS=usb
E: ID_MODEL=ETU905A80-E
E: ID_MODEL_ENC=ETU905A80-E
E: ID_MODEL_ID=0582
E: ID_PATH=pci-0000:00:14.0-usb-0:5
E: ID_PATH_TAG=pci-0000_00_14_0-usb-0_5
E: ID_REVISION=1181
E: ID_SERIAL=EGIS_ETU905A80-E_0E7828PBS393
E: ID_SERIAL_SHORT=0E7828PBS393
E: ID_USB_INTERFACES=:ff0000:
E: ID_USB_MODEL=ETU905A80-E
E: ID_USB_MODEL_ENC=ETU905A80-E
E: ID_USB_MODEL_ID=0582
E: ID_USB_REVISION=1181
E: ID_USB_SERIAL=EGIS_ETU905A80-E_0E7828PBS393
E: ID_USB_SERIAL_SHORT=0E7828PBS393
E: ID_USB_VENDOR=EGIS
E: ID_USB_VENDOR_ENC=EGIS
E: ID_USB_VENDOR_ID=1c7a
E: ID_VENDOR=EGIS
E: ID_VENDOR_ENC=EGIS
E: ID_VENDOR_FROM_DATABASE=LighTuning Technology Inc.
E: ID_VENDOR_ID=1c7a
E: MAJOR=189
E: MINOR=267
E: PRODUCT=1c7a/582/1181
E: SUBSYSTEM=usb
E: TAGS=:snap_cups_ippeveprinter:snap_cups_cupsd:
E: TYPE=255/0/0
A: authorized=1\n
A: avoid_reset_quirk=0\n
A: bConfigurationValue=1\n
A: bDeviceClass=ff\n
A: bDeviceProtocol=00\n
A: bDeviceSubClass=00\n
A: bMaxPacketSize0=64\n
A: bMaxPower=100mA\n
A: bNumConfigurations=1\n
A: bNumInterfaces= 1\n
A: bcdDevice=1181\n
A: bmAttributes=a0\n
A: busnum=3\n
A: configuration=
H: descriptors=12010002FF0000407A1C820581110102030109022700010100A0320904000003FF000000070581020002000705020200020007058303400005
A: dev=189:267\n
A: devnum=12\n
A: devpath=5\n
L: driver=../../../../../bus/usb/drivers/usb
L: firmware_node=../../../../LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:51/device:52/device:57
A: idProduct=0582\n
A: idVendor=1c7a\n
A: ltm_capable=no\n
A: manufacturer=EGIS\n
A: maxchild=0\n
A: physical_location/dock=no\n
A: physical_location/horizontal_position=center\n
A: physical_location/lid=no\n
A: physical_location/panel=unknown\n
A: physical_location/vertical_position=center\n
L: port=../3-0:1.0/usb3-port5
A: power/active_duration=1425996\n
A: power/async=enabled\n
A: power/autosuspend=2\n
A: power/autosuspend_delay_ms=2000\n
A: power/connected_duration=1426656\n
A: power/control=on\n
A: power/level=on\n
A: power/persist=0\n
A: power/runtime_active_kids=0\n
A: power/runtime_active_time=1426124\n
A: power/runtime_enabled=forbidden\n
A: power/runtime_status=active\n
A: power/runtime_suspended_time=0\n
A: power/runtime_usage=1\n
A: power/wakeup=disabled\n
A: power/wakeup_abort_count=\n
A: power/wakeup_active=\n
A: power/wakeup_active_count=\n
A: power/wakeup_count=\n
A: power/wakeup_expire_count=\n
A: power/wakeup_last_time_ms=\n
A: power/wakeup_max_time_ms=\n
A: power/wakeup_total_time_ms=\n
A: product=ETU905A80-E\n
A: quirks=0x0\n
A: removable=fixed\n
A: rx_lanes=1\n
A: serial=0E7828PBS393\n
A: speed=480\n
A: tx_lanes=1\n
A: urbnum=2803\n
A: version= 2.00\n
P: /devices/pci0000:00/0000:00:14.0/usb3
N: bus/usb/003/001=12010002090001406B1D020002060302010109021900010100E0000904000001090000000705810304000C
E: BUSNUM=003
E: CURRENT_TAGS=:seat:snap_cups_cupsd:snap_cups_ippeveprinter:
E: DEVNAME=/dev/bus/usb/003/001
E: DEVNUM=001
E: DEVTYPE=usb_device
E: DRIVER=usb
E: ID_AUTOSUSPEND=1
E: ID_BUS=usb
E: ID_FOR_SEAT=usb-pci-0000_00_14_0
E: ID_MODEL=xHCI_Host_Controller
E: ID_MODEL_ENC=xHCI\x20Host\x20Controller
E: ID_MODEL_FROM_DATABASE=2.0 root hub
E: ID_MODEL_ID=0002
E: ID_PATH=pci-0000:00:14.0
E: ID_PATH_TAG=pci-0000_00_14_0
E: ID_REVISION=0602
E: ID_SERIAL=Linux_6.2.0-34-generic_xhci-hcd_xHCI_Host_Controller_0000:00:14.0
E: ID_SERIAL_SHORT=0000:00:14.0
E: ID_USB_INTERFACES=:090000:
E: ID_USB_MODEL=xHCI_Host_Controller
E: ID_USB_MODEL_ENC=xHCI\x20Host\x20Controller
E: ID_USB_MODEL_ID=0002
E: ID_USB_REVISION=0602
E: ID_USB_SERIAL=Linux_6.2.0-34-generic_xhci-hcd_xHCI_Host_Controller_0000:00:14.0
E: ID_USB_SERIAL_SHORT=0000:00:14.0
E: ID_USB_VENDOR=Linux_6.2.0-34-generic_xhci-hcd
E: ID_USB_VENDOR_ENC=Linux\x206.2.0-34-generic\x20xhci-hcd
E: ID_USB_VENDOR_ID=1d6b
E: ID_VENDOR=Linux_6.2.0-34-generic_xhci-hcd
E: ID_VENDOR_ENC=Linux\x206.2.0-34-generic\x20xhci-hcd
E: ID_VENDOR_FROM_DATABASE=Linux Foundation
E: ID_VENDOR_ID=1d6b
E: MAJOR=189
E: MINOR=256
E: PRODUCT=1d6b/2/602
E: SUBSYSTEM=usb
E: TAGS=:snap_cups_cupsd:seat:snap_cups_ippeveprinter:
E: TYPE=9/0/1
A: authorized=1\n
A: authorized_default=1\n
A: avoid_reset_quirk=0\n
A: bConfigurationValue=1\n
A: bDeviceClass=09\n
A: bDeviceProtocol=01\n
A: bDeviceSubClass=00\n
A: bMaxPacketSize0=64\n
A: bMaxPower=0mA\n
A: bNumConfigurations=1\n
A: bNumInterfaces= 1\n
A: bcdDevice=0602\n
A: bmAttributes=e0\n
A: busnum=3\n
A: configuration=
H: descriptors=12010002090001406B1D020002060302010109021900010100E0000904000001090000000705810304000C
A: dev=189:256\n
A: devnum=1\n
A: devpath=0\n
L: driver=../../../../bus/usb/drivers/usb
L: firmware_node=../../../LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:51/device:52
A: idProduct=0002\n
A: idVendor=1d6b\n
A: interface_authorized_default=1\n
A: ltm_capable=no\n
A: manufacturer=Linux 6.2.0-34-generic xhci-hcd\n
A: maxchild=12\n
A: power/active_duration=337953872\n
A: power/async=enabled\n
A: power/autosuspend=0\n
A: power/autosuspend_delay_ms=0\n
A: power/connected_duration=337978524\n
A: power/control=auto\n
A: power/level=auto\n
A: power/runtime_active_kids=1\n
A: power/runtime_active_time=337962424\n
A: power/runtime_enabled=enabled\n
A: power/runtime_status=active\n
A: power/runtime_suspended_time=616\n
A: power/runtime_usage=0\n
A: power/wakeup=disabled\n
A: power/wakeup_abort_count=\n
A: power/wakeup_active=\n
A: power/wakeup_active_count=\n
A: power/wakeup_count=\n
A: power/wakeup_expire_count=\n
A: power/wakeup_last_time_ms=\n
A: power/wakeup_max_time_ms=\n
A: power/wakeup_total_time_ms=\n
A: product=xHCI Host Controller\n
A: quirks=0x0\n
A: removable=unknown\n
A: rx_lanes=1\n
A: serial=0000:00:14.0\n
A: speed=480\n
A: tx_lanes=1\n
A: urbnum=4969\n
A: version= 2.00\n
P: /devices/pci0000:00/0000:00:14.0
E: DRIVER=xhci_hcd
E: ID_MODEL_FROM_DATABASE=Alder Lake PCH USB 3.2 xHCI Host Controller
E: ID_PCI_CLASS_FROM_DATABASE=Serial bus controller
E: ID_PCI_INTERFACE_FROM_DATABASE=XHCI
E: ID_PCI_SUBCLASS_FROM_DATABASE=USB controller
E: ID_VENDOR_FROM_DATABASE=Intel Corporation
E: MODALIAS=pci:v00008086d000051EDsv0000144Dsd0000C870bc0Csc03i30
E: PCI_CLASS=C0330
E: PCI_ID=8086:51ED
E: PCI_SLOT_NAME=0000:00:14.0
E: PCI_SUBSYS_ID=144D:C870
E: SUBSYSTEM=pci
A: ari_enabled=0\n
A: broken_parity_status=0\n
A: class=0x0c0330\n
H: config=8680ED51060490020130030C000080000400161D6000000000000000000000000000000000000000000000004D1470C8000000007000000000000000FF010000FD0134A089C27F8000000000000000003F6DD80F000000000000000000000000316000000000000000000000000000000180C2C1080000000000000000000000059087007805E0FE000000000000000009B014F01000400100000000C10A080000080E00001800008F50020000010000090000018680C00009001014000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000B50F010112000000
A: consistent_dma_mask_bits=64\n
A: d3cold_allowed=1\n
A: dbc=disabled\n
A: device=0x51ed\n
A: dma_mask_bits=64\n
L: driver=../../../bus/pci/drivers/xhci_hcd
A: driver_override=(null)\n
A: enable=1\n
L: firmware_node=../../LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:51
A: index=7\n
L: iommu=../../virtual/iommu/dmar1
L: iommu_group=../../../kernel/iommu_groups/8
A: irq=145\n
A: label=Onboard - Other\n
A: local_cpulist=0-15\n
A: local_cpus=ffff\n
A: modalias=pci:v00008086d000051EDsv0000144Dsd0000C870bc0Csc03i30\n
A: msi_bus=1\n
A: msi_irqs/145=msi\n
A: numa_node=-1\n
A: pools=poolinfo - 0.1\nbuffer-2048 0 0 2048 0\nbuffer-512 0 0 512 0\nbuffer-128 0 0 128 0\nbuffer-32 0 0 32 0\nxHCI 1KB stream ctx arrays 0 0 1024 0\nxHCI 256 byte stream ctx arrays 0 0 256 0\nxHCI input/output contexts 6 9 2112 9\nxHCI ring segments 26 34 4096 34\nbuffer-2048 0 0 2048 0\nbuffer-512 0 0 512 0\nbuffer-128 0 32 128 1\nbuffer-32 0 0 32 0\n
A: power/async=enabled\n
A: power/control=auto\n
A: power/runtime_active_kids=1\n
A: power/runtime_active_time=337964621\n
A: power/runtime_enabled=enabled\n
A: power/runtime_status=active\n
A: power/runtime_suspended_time=438\n
A: power/runtime_usage=0\n
A: power/wakeup=enabled\n
A: power/wakeup_abort_count=0\n
A: power/wakeup_active=0\n
A: power/wakeup_active_count=7\n
A: power/wakeup_count=0\n
A: power/wakeup_expire_count=7\n
A: power/wakeup_last_time_ms=336554844\n
A: power/wakeup_max_time_ms=105\n
A: power/wakeup_total_time_ms=721\n
A: power_state=D0\n
A: resource=0x000000601d160000 0x000000601d16ffff 0x0000000000140204\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n
A: revision=0x01\n
A: subsystem_device=0xc870\n
A: subsystem_vendor=0x144d\n
A: vendor=0x8086\n

Binary file not shown.

View File

@@ -1,9 +1,15 @@
#!/usr/bin/python3
import traceback
import sys
import gi
gi.require_version('FPrint', '2.0')
from gi.repository import FPrint, GLib
# Exit with error on any exception, included those happening in async callbacks
sys.excepthook = lambda *args: (traceback.print_exception(*args), sys.exit(1))
ctx = GLib.main_context_default()
c = FPrint.Context()

View File

@@ -1,63 +1,67 @@
P: /devices/pci0000:00/0000:00:14.0/usb1/1-1
N: bus/usb/001/010=1201000200000040F3047E0C05030102000109025300010103A0320904000008FF0000000921100100012215000705810240000107050102400001070582024000010705020240000107058302400001070503024000010705840240000107050402400001
E: DEVNAME=/dev/bus/usb/001/010
P: /devices/pci0000:00/0000:00:14.0/usb1/1-9
N: bus/usb/001/003=1201000200000008F304880C04800102000109025300010100A0320904000008FF0000000921100100012215000705810240000107050102400001070582024000010705020240000107058302400001070503024000010705840240000107050402400001
E: DEVNAME=/dev/bus/usb/001/003
E: DEVTYPE=usb_device
E: DRIVER=usb
E: PRODUCT=4f3/c7e/305
E: PRODUCT=4f3/c88/8004
E: TYPE=0/0/0
E: BUSNUM=001
E: DEVNUM=010
E: DEVNUM=003
E: MAJOR=189
E: MINOR=9
E: MINOR=2
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=0305
E: ID_MODEL_ID=0c88
E: ID_REVISION=8004
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:1
E: ID_PATH_TAG=pci-0000_00_14_0-usb-0_1
E: ID_PATH=pci-0000:00:14.0-usb-0:9
E: ID_PATH_TAG=pci-0000_00_14_0-usb-0_9
E: ID_FOR_SEAT=usb-pci-0000_00_14_0-usb-0_9
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: bMaxPacketSize0=8\n
A: bMaxPower=100mA\n
A: bNumConfigurations=1\n
A: bNumInterfaces= 1\n
A: bcdDevice=0305\n
A: bcdDevice=8004\n
A: bmAttributes=a0\n
A: busnum=1\n
A: configuration=add909c9-e67e-4126-a6f7-1e31179e27d9\n
H: descriptors=1201000200000040F3047E0C05030102000109025300010103A0320904000008FF0000000921100100012215000705810240000107050102400001070582024000010705020240000107058302400001070503024000010705840240000107050402400001
A: dev=189:9\n
A: devnum=10\n
A: devpath=1\n
A: configuration=
H: descriptors=1201000200000008F304880C04800102000109025300010100A0320904000008FF0000000921100100012215000705810240000107050102400001070582024000010705020240000107058302400001070503024000010705840240000107050402400001
A: dev=189:2\n
A: devnum=3\n
A: devpath=9\n
L: driver=../../../../../bus/usb/drivers/usb
A: idProduct=0c7e\n
L: firmware_node=../../../../LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:3d/device:3e/device:47
A: idProduct=0c88\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-port1
A: power/active_duration=94712\n
L: port=../1-0:1.0/usb1-port9
A: power/active_duration=35269124\n
A: power/async=enabled\n
A: power/autosuspend=2\n
A: power/autosuspend_delay_ms=2000\n
A: power/connected_duration=94712\n
A: power/connected_duration=35283788\n
A: power/control=on\n
A: power/level=on\n
A: power/persist=1\n
A: power/persist=0\n
A: power/runtime_active_kids=0\n
A: power/runtime_active_time=94436\n
A: power/runtime_active_time=35276624\n
A: power/runtime_enabled=forbidden\n
A: power/runtime_status=active\n
A: power/runtime_suspended_time=0\n
@@ -77,38 +81,40 @@ A: removable=removable\n
A: rx_lanes=1\n
A: speed=12\n
A: tx_lanes=1\n
A: urbnum=12\n
A: urbnum=2773\n
A: version= 2.00\n
P: /devices/pci0000:00/0000:00:14.0/usb1
N: bus/usb/001/001=12010002090001406B1D020004050302010109021900010100E0000904000001090000000705810304000C
N: bus/usb/001/001=12010002090001406B1D020015050302010109021900010100E0000904000001090000000705810304000C
E: DEVNAME=/dev/bus/usb/001/001
E: DEVTYPE=usb_device
E: DRIVER=usb
E: PRODUCT=1d6b/2/504
E: PRODUCT=1d6b/2/515
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.4.0-42-generic_xhci-hcd
E: ID_VENDOR_ENC=Linux\x205.4.0-42-generic\x20xhci-hcd
E: ID_VENDOR=Linux_5.15.0-39-generic_xhci-hcd
E: ID_VENDOR_ENC=Linux\x205.15.0-39-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=0504
E: ID_SERIAL=Linux_5.4.0-42-generic_xhci-hcd_xHCI_Host_Controller_0000:00:14.0
E: ID_REVISION=0515
E: ID_SERIAL=Linux_5.15.0-39-generic_xhci-hcd_xHCI_Host_Controller_0000:00:14.0
E: ID_SERIAL_SHORT=0000:00:14.0
E: ID_BUS=usb
E: ID_USB_INTERFACES=:090000:
E: ID_VENDOR_FROM_DATABASE=Linux Foundation
E: ID_AUTOSUSPEND=1
E: ID_MODEL_FROM_DATABASE=2.0 root hub
E: ID_PATH=pci-0000:00:14.0
E: ID_PATH_TAG=pci-0000_00_14_0
E: ID_FOR_SEAT=usb-pci-0000_00_14_0
E: TAGS=:seat:
E: CURRENT_TAGS=:seat:
A: authorized=1\n
A: authorized_default=1\n
A: avoid_reset_quirk=0\n
@@ -120,30 +126,31 @@ A: bMaxPacketSize0=64\n
A: bMaxPower=0mA\n
A: bNumConfigurations=1\n
A: bNumInterfaces= 1\n
A: bcdDevice=0504\n
A: bcdDevice=0515\n
A: bmAttributes=e0\n
A: busnum=1\n
A: configuration=\n
H: descriptors=12010002090001406B1D020004050302010109021900010100E0000904000001090000000705810304000C
A: configuration=
H: descriptors=12010002090001406B1D020015050302010109021900010100E0000904000001090000000705810304000C
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:3d/device:3e
A: idProduct=0002\n
A: idVendor=1d6b\n
A: interface_authorized_default=1\n
A: ltm_capable=no\n
A: manufacturer=Linux 5.4.0-42-generic xhci-hcd\n
A: maxchild=12\n
A: power/active_duration=74604360\n
A: manufacturer=Linux 5.15.0-39-generic xhci-hcd\n
A: maxchild=14\n
A: power/active_duration=35270364\n
A: power/async=enabled\n
A: power/autosuspend=0\n
A: power/autosuspend_delay_ms=0\n
A: power/connected_duration=74606456\n
A: power/connected_duration=35284300\n
A: power/control=auto\n
A: power/level=auto\n
A: power/runtime_active_kids=4\n
A: power/runtime_active_time=74605838\n
A: power/runtime_active_kids=2\n
A: power/runtime_active_time=35277420\n
A: power/runtime_enabled=enabled\n
A: power/runtime_status=active\n
A: power/runtime_suspended_time=0\n
@@ -164,62 +171,63 @@ A: rx_lanes=1\n
A: serial=0000:00:14.0\n
A: speed=480\n
A: tx_lanes=1\n
A: urbnum=490\n
A: urbnum=549\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=103C:85EF
E: PCI_ID=8086:8C31
E: PCI_SUBSYS_ID=1043:201F
E: PCI_SLOT_NAME=0000:00:14.0
E: MODALIAS=pci:v00008086d00009DEDsv0000103Csd000085EFbc0Csc03i30
E: MODALIAS=pci:v00008086d00008C31sv00001043sd0000201Fbc0Csc03i30
E: SUBSYSTEM=pci
E: ID_PCI_CLASS_FROM_DATABASE=Serial bus controller
E: ID_PCI_SUBCLASS_FROM_DATABASE=USB controller
E: ID_PCI_INTERFACE_FROM_DATABASE=XHCI
E: ID_VENDOR_FROM_DATABASE=Intel Corporation
E: ID_MODEL_FROM_DATABASE=Cannon Point-LP USB 3.1 xHCI Controller
E: ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family USB xHCI
A: ari_enabled=0\n
A: broken_parity_status=0\n
A: class=0x0c0330\n
H: config=8680ED9D060490023030030C00008000040030A10000000000000000000000000000000000000000000000003C10EF85000000007000000000000000FF010000FD0134808FC6FF8300000000000000007F6DDC0F00000000181C030400000000316000000000000000000000000000000180C2C1080000000000000000000000059087007802E0FE0000000000000000090014F01000400100000000C10A080000080E00001800008F40020000010000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000B50F300112000000
H: config=8680318C060490020530030C000000000400A0F700000000000000000000000000000000000000000000000043101F200000000070000000000000000B010000FD01368089C60F8000000000000000009F6E8807000000000000000000000000302000000000000000000000000000000180C2C1080000000000000000000000050087000410E0FE000000002F00000000000000000000000000000000000000400100000000000000000000000000000F000100000000000000000000000000030420C0030C3000030C300000000000FF1A0000FF1A00003F0000003F000000A00000000000000000000000D8D8D8080000000000000000B10F060800000000
A: consistent_dma_mask_bits=64\n
A: d3cold_allowed=1\n
A: dbc=disabled\n
A: device=0x9ded\n
A: device=0x8c31\n
A: dma_mask_bits=64\n
L: driver=../../../bus/pci/drivers/xhci_hcd
A: driver_override=(null)\n
A: enable=1\n
A: irq=124\n
L: firmware_node=../../LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:3d
A: irq=31\n
A: local_cpulist=0-3\n
A: local_cpus=f\n
A: modalias=pci:v00008086d00009DEDsv0000103Csd000085EFbc0Csc03i30\n
A: modalias=pci:v00008086d00008C31sv00001043sd0000201Fbc0Csc03i30\n
A: msi_bus=1\n
A: msi_irqs/124=msi\n
A: msi_irqs/31=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 32 128 1\nbuffer-32 0 0 32 0\nxHCI 1KB stream ctx arrays 0 0 1024 0\nxHCI 256 byte stream ctx arrays 0 0 256 0\nxHCI input/output contexts 11 12 2112 12\nxHCI ring segments 54 54 4096 54\nbuffer-2048 0 0 2048 0\nbuffer-512 0 0 512 0\nbuffer-128 9 32 128 1\nbuffer-32 0 0 32 0\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 5 6 2112 6\nxHCI ring segments 24 24 4096 24\nbuffer-2048 0 0 2048 0\nbuffer-512 0 0 512 0\nbuffer-128 3 32 128 1\nbuffer-32 0 0 32 0\n
A: power/async=enabled\n
A: power/control=auto\n
A: power/control=on\n
A: power/runtime_active_kids=1\n
A: power/runtime_active_time=74606194\n
A: power/runtime_enabled=enabled\n
A: power/runtime_active_time=35278060\n
A: power/runtime_enabled=forbidden\n
A: power/runtime_status=active\n
A: power/runtime_suspended_time=0\n
A: power/runtime_usage=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_active_count=5\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=0x00000000a1300000 0x00000000a130ffff 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=0x30\n
A: subsystem_device=0x85ef\n
A: subsystem_vendor=0x103c\n
A: power/wakeup_expire_count=5\n
A: power/wakeup_last_time_ms=12694896\n
A: power/wakeup_max_time_ms=103\n
A: power/wakeup_total_time_ms=518\n
A: power_state=D0\n
A: resource=0x00000000f7a00000 0x00000000f7a0ffff 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=0x05\n
A: subsystem_device=0x201f\n
A: subsystem_vendor=0x1043\n
A: vendor=0x8086\n

Binary file not shown.

89
tests/focaltech_moc/custom.py Executable file
View File

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

385
tests/focaltech_moc/device Normal file

File diff suppressed because one or more lines are too long

BIN
tests/fpcmoc/custom.pcapng Normal file

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More