mirror of
https://gitlab.freedesktop.org/libfprint/libfprint.git
synced 2026-09-10 13:00:08 +00:00
Compare commits
501
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
88cd932203 | ||
|
|
e85b607965 | ||
|
|
40a298f43b | ||
|
|
f8eb329a65 | ||
|
|
eb7edc43b8 | ||
|
|
ebff2518ad | ||
|
|
445d46fb6f | ||
|
|
477df2a861 | ||
|
|
e4bac112aa | ||
|
|
4c42a090f7 | ||
|
|
65483d51b7 | ||
|
|
e513848871 | ||
|
|
0a45ed7af6 | ||
|
|
1db2dc3f58 | ||
|
|
953c75575b | ||
|
|
8c7ff259af | ||
|
|
3e666130c2 | ||
|
|
2babfa0625 | ||
|
|
83af40679a | ||
|
|
ce31c1d704 | ||
|
|
b20a74a22c | ||
|
|
66461e4c81 | ||
|
|
6ba9439bbb | ||
|
|
6764ec79ae | ||
|
|
6f4c378933 | ||
|
|
b121fa2cc9 | ||
|
|
ca26e85fd4 | ||
|
|
0714380360 | ||
|
|
b9af7952a4 | ||
|
|
ea6820ed51 | ||
|
|
a1e46de462 | ||
|
|
1abe213844 | ||
|
|
0372ae8ba5 | ||
|
|
a1e69a0e9d | ||
|
|
49e1e98914 | ||
|
|
34b316d7d5 | ||
|
|
9abc6791c7 | ||
|
|
5459823667 | ||
|
|
4fa8c5ec47 | ||
|
|
239034714f | ||
|
|
8a3a974ea3 | ||
|
|
db607c4a6f | ||
|
|
a53f07a8f6 | ||
|
|
c3e996b96c | ||
|
|
a218437cf4 | ||
|
|
0add0ca9b1 | ||
|
|
eaa4aa964c | ||
|
|
74bb899ce2 | ||
|
|
69fe7a1b8c | ||
|
|
ce856efa25 | ||
|
|
b54514df6e | ||
|
|
551616c3ab | ||
|
|
cec307ce7f | ||
|
|
e7bc8e03fc | ||
|
|
9a025bde8b | ||
|
|
6845e400cd | ||
|
|
25d0fa42e2 | ||
|
|
52208a6606 | ||
|
|
6725b22fd4 | ||
|
|
21bac43015 | ||
|
|
0ddd11f81b | ||
|
|
6d47c44335 | ||
|
|
3cbc908a6e | ||
|
|
95b1e75f1b | ||
|
|
bcfe0ad12c | ||
|
|
2088a6177f | ||
|
|
c9733d27df | ||
|
|
dd24cf57c6 | ||
|
|
451a4c0969 | ||
|
|
dabcae7b4d | ||
|
|
eae5721f8e | ||
|
|
ce1a675dd5 | ||
|
|
6ba1016024 | ||
|
|
b5f175b78e | ||
|
|
aff7efd891 | ||
|
|
1d00c2d4b4 | ||
|
|
61483a4c47 | ||
|
|
2b21430abe | ||
|
|
1781ad140e | ||
|
|
d2e3ad4dbc | ||
|
|
7615aaef7a | ||
|
|
92e3168309 | ||
|
|
ca148cbcf1 | ||
|
|
e57f037a10 | ||
|
|
46ad86fab2 | ||
|
|
511e164f17 | ||
|
|
6f18fc4bf4 | ||
|
|
8ca34303f2 | ||
|
|
882fc8ab54 | ||
|
|
9e5ae25abf | ||
|
|
9316dfed2e | ||
|
|
702932c69b | ||
|
|
29461fa910 | ||
|
|
f7173e6645 | ||
|
|
11b11a9d71 | ||
|
|
9da69dfc36 | ||
|
|
e5f4021a4f | ||
|
|
4dcbc6a3aa | ||
|
|
7a72d8fd58 | ||
|
|
5edfd55e00 | ||
|
|
2951daaa01 | ||
|
|
23f7c4aaf7 | ||
|
|
3dc5c4a6de | ||
|
|
a97ae3bc35 | ||
|
|
53d2fb3ad2 | ||
|
|
4f7e507716 | ||
|
|
f2e3a840db | ||
|
|
f45c18116a | ||
|
|
2365c608f9 | ||
|
|
6c6daaa619 | ||
|
|
857a399bfa | ||
|
|
6e230f0a07 | ||
|
|
7402401057 | ||
|
|
fe17dfe01d | ||
|
|
4885b38be5 | ||
|
|
5d4a5981d0 | ||
|
|
0fcb4533b5 | ||
|
|
422f81b60c | ||
|
|
e0d2f3ae53 | ||
|
|
531d9048b3 | ||
|
|
18495d122d | ||
|
|
9bcacd97df | ||
|
|
d91eae26e5 | ||
|
|
d113ed9d83 | ||
|
|
e113754312 | ||
|
|
b1afa9da5d | ||
|
|
700c5791f8 | ||
|
|
97d0a6dfe6 | ||
|
|
a54d020c97 | ||
|
|
36b696f433 | ||
|
|
f42cd6eefd | ||
|
|
46ebb39f65 | ||
|
|
c88a51cce8 | ||
|
|
3a7b03f022 | ||
|
|
94450a1d74 | ||
|
|
c35ad20249 | ||
|
|
5e8b4a81e9 | ||
|
|
21a779235d | ||
|
|
1006467f33 | ||
|
|
cffe49de5c | ||
|
|
7962d8cdab | ||
|
|
36dba33808 | ||
|
|
c273908471 | ||
|
|
bf8661bf45 | ||
|
|
499b522183 | ||
|
|
13bfe7a65c | ||
|
|
e90ec04441 | ||
|
|
a59a5caaf3 | ||
|
|
5b9f81fb46 | ||
|
|
d3aaebb352 | ||
|
|
a99f920fe0 | ||
|
|
fb5527c58c | ||
|
|
fcd3c1dd89 | ||
|
|
3a9500be67 | ||
|
|
1d93b86569 | ||
|
|
aca2cd41d8 | ||
|
|
1035f733aa | ||
|
|
2818d94010 | ||
|
|
1d1c34eb60 | ||
|
|
ca06fae22e | ||
|
|
36f527269b | ||
|
|
7cfe20e07f | ||
|
|
1fd82b5162 | ||
|
|
0ace5f64f8 | ||
|
|
e532524c7e | ||
|
|
ebd96f892e | ||
|
|
4b9b34fa4d | ||
|
|
bcc1e7ae73 | ||
|
|
27accf42f2 | ||
|
|
96f2e07cdd | ||
|
|
192c4f3cfc | ||
|
|
cb274032da | ||
|
|
b890fa56d8 | ||
|
|
b817b46494 | ||
|
|
49ba59369a | ||
|
|
d09cb88e9a | ||
|
|
44c3f4f772 | ||
|
|
948a67a51f | ||
|
|
de79609550 | ||
|
|
d18e10535e | ||
|
|
2954583373 | ||
|
|
ccdecdea11 | ||
|
|
946388d1e9 | ||
|
|
10ae8ffb55 | ||
|
|
bdba9990fb | ||
|
|
50166e88c0 | ||
|
|
f2bc826a20 | ||
|
|
ac48d66203 | ||
|
|
f68e7fcb9f | ||
|
|
0c3a22758b | ||
|
|
9cc859a318 | ||
|
|
7dfc8f3364 | ||
|
|
e397571f83 | ||
|
|
d34d7c26de | ||
|
|
77defa1d8b | ||
|
|
5d01497b8b | ||
|
|
cb8732b255 | ||
|
|
3f64b2ea5a | ||
|
|
57b38a2876 | ||
|
|
058f91909d | ||
|
|
4f75e63e25 | ||
|
|
2e50ff5e7c | ||
|
|
0b7477e72c | ||
|
|
4dc8aa6dfa | ||
|
|
161c3ccf1c | ||
|
|
170da7fec1 | ||
|
|
d7af9a4498 | ||
|
|
3cb3b1d63a | ||
|
|
fc66919e1f | ||
|
|
de5b4e7dcb | ||
|
|
561576961c | ||
|
|
2946dabd24 | ||
|
|
969eefc81f | ||
|
|
efee7262b6 | ||
|
|
1102d6e478 | ||
|
|
603aab0a81 | ||
|
|
10e934e234 | ||
|
|
48b9e6c517 | ||
|
|
5ae2ef5407 | ||
|
|
cafa05dab5 | ||
|
|
6345835b02 | ||
|
|
1d453b5732 | ||
|
|
d3a1b86ea4 | ||
|
|
bb27ca5720 | ||
|
|
065c0b6202 | ||
|
|
b4819701b4 | ||
|
|
daed05755a | ||
|
|
fb192f706c | ||
|
|
350b0a38e2 | ||
|
|
9ccbda4a40 | ||
|
|
821cbae187 | ||
|
|
528f3556ea | ||
|
|
489afea605 | ||
|
|
688a133f3f | ||
|
|
0cd37b0142 | ||
|
|
9fb789dc78 | ||
|
|
770444af55 | ||
|
|
703d9b2a07 | ||
|
|
a96509f286 | ||
|
|
8553f2e41c | ||
|
|
56c96dde8b | ||
|
|
9793d60c5a | ||
|
|
4ff97e7cbd | ||
|
|
75fe328f64 | ||
|
|
b28b006d61 | ||
|
|
c3b1c982bc | ||
|
|
b098399bbc | ||
|
|
65bbdff3fc | ||
|
|
fba3e682ea | ||
|
|
bccff4ffef | ||
|
|
9843c2d764 | ||
|
|
c9abbec48a | ||
|
|
bc79f9504b | ||
|
|
626b0f1a8f | ||
|
|
da95af0f48 | ||
|
|
28b6f643d8 | ||
|
|
22277c7277 | ||
|
|
19e7b217c1 | ||
|
|
29d3541b74 | ||
|
|
b9e5b3a55c | ||
|
|
b1ac865abd | ||
|
|
21504c0621 | ||
|
|
056ea541dd | ||
|
|
871fddf5fb | ||
|
|
c284858d06 | ||
|
|
bb4d888661 | ||
|
|
ff77cfc9b5 | ||
|
|
80f91ecb7b | ||
|
|
6cb77465ab | ||
|
|
6f6127cbb6 | ||
|
|
e1d85fb636 | ||
|
|
74b5c92787 | ||
|
|
ac1f97e2eb | ||
|
|
40f486b108 | ||
|
|
b62e67401c | ||
|
|
dd0a0134a6 | ||
|
|
5e24000799 | ||
|
|
c5cdfcb120 | ||
|
|
549a6694d2 | ||
|
|
14e34e1d15 | ||
|
|
e5393bf46a | ||
|
|
878a201bb1 | ||
|
|
b0e4619e0a | ||
|
|
aec65777a7 | ||
|
|
31bad8ddd2 | ||
|
|
79d65c907f | ||
|
|
92231d984f | ||
|
|
2fbc77955e | ||
|
|
c91819f551 | ||
|
|
b3f6ff5a36 | ||
|
|
52f84bee3c | ||
|
|
dda6857fee | ||
|
|
0215483fb3 | ||
|
|
37bb59df13 | ||
|
|
db34837d2d | ||
|
|
ba49677794 | ||
|
|
1a376c1bfa | ||
|
|
ef807d9d0e | ||
|
|
2a4893d946 | ||
|
|
cee061b363 | ||
|
|
1bbdf304ab | ||
|
|
6155068f9e | ||
|
|
0c4e3bb1c4 | ||
|
|
4547ff0c19 | ||
|
|
b7cce4d91d | ||
|
|
475250ce71 | ||
|
|
f40f231a63 | ||
|
|
d83d92adf2 | ||
|
|
d15282bff1 | ||
|
|
00637c4f0b | ||
|
|
2e035a7f45 | ||
|
|
17577175f8 | ||
|
|
933fab6ed4 | ||
|
|
7e5661caff | ||
|
|
19dfb138a6 | ||
|
|
0930f2614c | ||
|
|
1b20521e5c | ||
|
|
0e351db91a | ||
|
|
9cca501650 | ||
|
|
2481cbe4ab | ||
|
|
bc3959d1e0 | ||
|
|
1ac815e457 | ||
|
|
55b83062d0 | ||
|
|
391f77ce5e | ||
|
|
bc30a3d2e5 | ||
|
|
ff5de4ff03 | ||
|
|
f433a4d67c | ||
|
|
994061af44 | ||
|
|
501020921e | ||
|
|
53c09405b2 | ||
|
|
1f0079a274 | ||
|
|
15afe43cf0 | ||
|
|
eb8f7ba3b2 | ||
|
|
901a6f7fed | ||
|
|
fc92f62136 | ||
|
|
ff09456cf5 | ||
|
|
32fcfde86b | ||
|
|
363a1b3371 | ||
|
|
c376c6fb02 | ||
|
|
8e6e23b8d0 | ||
|
|
63e5d56441 | ||
|
|
e9bfd943fc | ||
|
|
614e2286c2 | ||
|
|
768a74c4bf | ||
|
|
612e9e11de | ||
|
|
06c72d54be | ||
|
|
be68bacc94 | ||
|
|
317d7bc988 | ||
|
|
b44e417bca | ||
|
|
9d67ce484d | ||
|
|
78b8602cf6 | ||
|
|
83a0a7681b | ||
|
|
c5e0e41ce7 | ||
|
|
b3fe4a1e91 | ||
|
|
f59bf389d9 | ||
|
|
231b8f9f92 | ||
|
|
dac153d24a | ||
|
|
3661d146a7 | ||
|
|
3bf55a3e07 | ||
|
|
5226467fc2 | ||
|
|
54deaa1b24 | ||
|
|
7ff667f58d | ||
|
|
58ba9b02ed | ||
|
|
d35da0ce99 | ||
|
|
041e6a1078 | ||
|
|
1c73c36ed7 | ||
|
|
69de32f700 | ||
|
|
4bfee76ead | ||
|
|
4d7afd9b4f | ||
|
|
cfe60c0640 | ||
|
|
d82847a6b4 | ||
|
|
5a7e6e07ff | ||
|
|
2162aa9f48 | ||
|
|
a1f36c71c9 | ||
|
|
e4eedef27e | ||
|
|
5e29695969 | ||
|
|
49a46668ad | ||
|
|
76269decdd | ||
|
|
8454a25ecf | ||
|
|
a0bbbd7d32 | ||
|
|
12f6dae8cd | ||
|
|
9570c36fd4 | ||
|
|
487dae0d2f | ||
|
|
d71018bd8f | ||
|
|
61fa57b05d | ||
|
|
fc1781e317 | ||
|
|
ffef6c2bcc | ||
|
|
67d29f7936 | ||
|
|
9437c98d54 | ||
|
|
f7d00a828d | ||
|
|
0f0a4b2da6 | ||
|
|
c9cdbaf880 | ||
|
|
83f29dad9f | ||
|
|
c2a11c5918 | ||
|
|
3746b2ad5c | ||
|
|
b51fa446e3 | ||
|
|
6fc5293e83 | ||
|
|
aab3daa28b | ||
|
|
e40f7bd1f7 | ||
|
|
6664f87d8f | ||
|
|
6e8d5cd6a1 | ||
|
|
9f7e1ecf40 | ||
|
|
d9567002e4 | ||
|
|
a656a4a9f3 | ||
|
|
2944a35e74 | ||
|
|
391373fb0c | ||
|
|
985e8c4577 | ||
|
|
bd0d4258e4 | ||
|
|
9bbd9b208a | ||
|
|
59fe0fb699 | ||
|
|
f1fdd71613 | ||
|
|
bb66780cb5 | ||
|
|
45fb6d7908 | ||
|
|
9f408bf51b | ||
|
|
ee32166267 | ||
|
|
a3c90f2b24 | ||
|
|
dc537ef2c9 | ||
|
|
061a457658 | ||
|
|
82ae7c1c09 | ||
|
|
79d79c3c87 | ||
|
|
35e356f625 | ||
|
|
948ab02d1a | ||
|
|
a6101026d2 | ||
|
|
e0966cb20f | ||
|
|
e278e8321c | ||
|
|
e1728e7c25 | ||
|
|
e215b05094 | ||
|
|
fe3fdd1f50 | ||
|
|
5ff45658c0 | ||
|
|
d12b294783 | ||
|
|
2bba4fb073 | ||
|
|
aeca32fc12 | ||
|
|
12c1088777 | ||
|
|
9e2f8b5e75 | ||
|
|
c14ebd8b63 | ||
|
|
a6339a30ef | ||
|
|
f3dd55815e | ||
|
|
6d65bfcf80 | ||
|
|
1acd647b29 | ||
|
|
0e843ad6b3 | ||
|
|
7eafca7bab | ||
|
|
3b3679c900 | ||
|
|
43eca622cd | ||
|
|
02509e1073 | ||
|
|
0b2d33c712 | ||
|
|
7751fcb375 | ||
|
|
8a87ba448c | ||
|
|
7e1646c382 | ||
|
|
a5ec0b30e1 | ||
|
|
29cf86a02e | ||
|
|
7892c943e6 | ||
|
|
a7d6b7c30a | ||
|
|
258ac2d4da | ||
|
|
31cf7a9383 | ||
|
|
f335256cbe | ||
|
|
c02cb3083d | ||
|
|
2084724115 | ||
|
|
59925d2027 | ||
|
|
118c610e29 | ||
|
|
313bfede77 | ||
|
|
c1da647aed | ||
|
|
22d204cc68 | ||
|
|
bc497f1b26 | ||
|
|
8c5f2e6434 | ||
|
|
5b20892dd4 | ||
|
|
b2a53a459c | ||
|
|
45ac0eefb0 | ||
|
|
ea6d5ba6d6 | ||
|
|
ed2c75842a | ||
|
|
b307dd1a6a | ||
|
|
39902374ce | ||
|
|
9e92d4cf2c | ||
|
|
6b84c6664f | ||
|
|
f569d0bf44 | ||
|
|
1cfd14b7fe | ||
|
|
5d32102efe | ||
|
|
9e10edd422 | ||
|
|
fecf6d6fe5 | ||
|
|
e32fa8cc38 | ||
|
|
d8aae30a67 | ||
|
|
84b97ea15b | ||
|
|
8f98743857 | ||
|
|
be29f27e25 | ||
|
|
d003f08855 | ||
|
|
0f7ad00fc4 | ||
|
|
83333bce3f | ||
|
|
132b178304 | ||
|
|
c3689665db | ||
|
|
3d222ddda7 | ||
|
|
080c414ce9 | ||
|
|
ff02115b0f | ||
|
|
3b409c767c | ||
|
|
d05c69698c | ||
|
|
2d09b10a27 | ||
|
|
bc03d56186 | ||
|
|
96e7224a23 | ||
|
|
0f4a75ff61 | ||
|
|
dfff16f3e3 | ||
|
|
3d2e545264 | ||
|
|
c96fa32da4 | ||
|
|
48ec64f683 |
@@ -0,0 +1,64 @@
|
|||||||
|
image: fedora:rawhide
|
||||||
|
stages:
|
||||||
|
- build
|
||||||
|
- test
|
||||||
|
|
||||||
|
variables:
|
||||||
|
DEPENDENCIES: libusb1-devel glib2-devel nss-devel pixman-devel systemd meson gtk-doc
|
||||||
|
gcc gcc-c++ glibc-devel libX11-devel libXv-devel gtk3-devel flatpak-builder
|
||||||
|
BUNDLE: "org.freedesktop.libfprint.Demo.flatpak"
|
||||||
|
|
||||||
|
.build_one_driver_template: &build_one_driver
|
||||||
|
script:
|
||||||
|
- dnf update -y --nogpgcheck && dnf install -y --nogpgcheck $DEPENDENCIES
|
||||||
|
# Build with a driver that doesn't need imaging, or nss
|
||||||
|
- meson -Ddrivers=elan . _build
|
||||||
|
- ninja -C _build
|
||||||
|
- rm -rf _build/
|
||||||
|
|
||||||
|
.build_template: &build
|
||||||
|
script:
|
||||||
|
- dnf update -y --nogpgcheck && dnf install -y --nogpgcheck $DEPENDENCIES
|
||||||
|
# And build with everything
|
||||||
|
- meson -Ddrivers=all . _build
|
||||||
|
- ninja -C _build
|
||||||
|
- ninja -C _build install
|
||||||
|
|
||||||
|
build:
|
||||||
|
stage: build
|
||||||
|
<<: *build_one_driver
|
||||||
|
<<: *build
|
||||||
|
|
||||||
|
.flatpak_script_template: &flatpak_script
|
||||||
|
script:
|
||||||
|
- flatpak-builder --stop-at=${FLATPAK_MODULE} app ${MANIFEST_PATH}
|
||||||
|
# Make sure to keep this in sync with the Flatpak manifest, all arguments
|
||||||
|
# are passed except the config-args because we build it ourselves
|
||||||
|
- flatpak build app meson --prefix=/app --libdir=lib ${MESON_ARGS} _build
|
||||||
|
- flatpak build app ninja -C _build install
|
||||||
|
- flatpak build app rm -rf /app/include/ /app/lib/pkgconfig/
|
||||||
|
- flatpak-builder --finish-only --repo=repo app ${MANIFEST_PATH}
|
||||||
|
# Generate a Flatpak bundle
|
||||||
|
- flatpak build-bundle repo ${BUNDLE} --runtime-repo=${RUNTIME_REPO} ${DBUS_ID}
|
||||||
|
|
||||||
|
.flatpak_artifacts_template: &flatpak_artifacts
|
||||||
|
artifacts:
|
||||||
|
paths:
|
||||||
|
- ${BUNDLE}
|
||||||
|
when: always
|
||||||
|
expire_in: 30 days
|
||||||
|
|
||||||
|
.flatpak_template: &flatpak
|
||||||
|
<<: *flatpak_script
|
||||||
|
<<: *flatpak_artifacts
|
||||||
|
|
||||||
|
flatpak master:
|
||||||
|
image: registry.gitlab.gnome.org/gnome/gnome-runtime-images/gnome:master
|
||||||
|
stage: test
|
||||||
|
variables:
|
||||||
|
MANIFEST_PATH: "demo/org.freedesktop.libfprint.Demo.json"
|
||||||
|
# From demo/org.freedesktop.libfprint.Demo.json
|
||||||
|
MESON_ARGS: "-Dudev_rules=false -Dx11-examples=false -Dgtk-examples=true"
|
||||||
|
FLATPAK_MODULE: "libfprint"
|
||||||
|
DBUS_ID: "org.freedesktop.libfprint.Demo"
|
||||||
|
<<: *flatpak
|
||||||
@@ -4,7 +4,8 @@ Copyright (C) 2006 Pavel Machek <pavel@suse.cz>
|
|||||||
Copyright (C) 1999 Erik Walthinsen <omega@cse.ogi.edu>
|
Copyright (C) 1999 Erik Walthinsen <omega@cse.ogi.edu>
|
||||||
Copyright (C) 2004,2006 Thomas Vander Stichele <thomas at apestaart dot org>
|
Copyright (C) 2004,2006 Thomas Vander Stichele <thomas at apestaart dot org>
|
||||||
Copyright (C) 2007 Cyrille Bagard
|
Copyright (C) 2007 Cyrille Bagard
|
||||||
Copyright (C) 2007 Vasily Khoruzhick
|
Copyright (C) 2007-2008,2012 Vasily Khoruzhick <anarsoul@gmail.com>
|
||||||
Copyright (C) 2007 Jan-Michael Brummer <buzz2@gmx.de>
|
Copyright (C) 2007 Jan-Michael Brummer <buzz2@gmx.de>
|
||||||
Copyright (C) 2007 Anthony Bretaudeau <wxcover@users.sourceforge.net>
|
Copyright (C) 2007 Anthony Bretaudeau <wxcover@users.sourceforge.net>
|
||||||
Copyright (C) 2010 Hugo Grostabussiat <dw23.devel@gmail.com>
|
Copyright (C) 2010 Hugo Grostabussiat <dw23.devel@gmail.com>
|
||||||
|
Copyright (C) 2012 Timo Teräs <timo.teras@iki.fi>
|
||||||
|
|||||||
@@ -1,96 +0,0 @@
|
|||||||
Copyright notices
|
|
||||||
=================
|
|
||||||
|
|
||||||
If you make a contribution substantial enough to add or update a copyright
|
|
||||||
notice on a file, such notice must be mirrored in the AUTHORS file. This is
|
|
||||||
to make it easy for people to comply to section 6 of the LGPL, which states
|
|
||||||
that a "work that uses the Library" must include copyright notices from
|
|
||||||
this library. By providing them all in one place, hopefully we save such
|
|
||||||
users some time.
|
|
||||||
|
|
||||||
|
|
||||||
USB
|
|
||||||
===
|
|
||||||
|
|
||||||
At the time of development, there are no known consumer fingerprint readers
|
|
||||||
which do not operate over the USB bus. Therefore the library is designed around
|
|
||||||
the fact that each driver drivers USB devices, and each device is a USB device.
|
|
||||||
If we were to ever support a non-USB device, some rearchitecting would be
|
|
||||||
needed, but this would not be a substantial task.
|
|
||||||
|
|
||||||
|
|
||||||
GLib
|
|
||||||
====
|
|
||||||
|
|
||||||
Although the library uses GLib internally, libfprint is designed to provide
|
|
||||||
a completely neutral interface to it's application users. So, the public
|
|
||||||
APIs should never return GLib data types or anything like that.
|
|
||||||
|
|
||||||
|
|
||||||
Two-faced-ness
|
|
||||||
==============
|
|
||||||
|
|
||||||
Like any decent library, this one is designed to provide a stable and
|
|
||||||
documented API to it's users: applications. Clear distinction is made between
|
|
||||||
data available internally in the library, and data/functions available to
|
|
||||||
the applications.
|
|
||||||
|
|
||||||
This library is confused a little by the fact that there is another 'interface'
|
|
||||||
at hand: the internal interface provided to drivers. So, we effectively end
|
|
||||||
up with 2 APIs:
|
|
||||||
|
|
||||||
1. The external-facing API for applications
|
|
||||||
2. The internal API for fingerprint drivers
|
|
||||||
|
|
||||||
Non-static functions which are intended for internal use only are prepended
|
|
||||||
with the "fpi_" prefix.
|
|
||||||
|
|
||||||
|
|
||||||
API stability
|
|
||||||
=============
|
|
||||||
|
|
||||||
No API stability has been promised to anyone: go wild, there's no issue with
|
|
||||||
breaking APIs at this point in time.
|
|
||||||
|
|
||||||
|
|
||||||
Portability
|
|
||||||
===========
|
|
||||||
|
|
||||||
libfprint is primarily written for Linux. However, I'm interested in
|
|
||||||
supporting efforts to port this to other operating systems too.
|
|
||||||
|
|
||||||
You should ensure code is portable wherever possible. Try and use GLib rather
|
|
||||||
than OS-specific features.
|
|
||||||
|
|
||||||
Endianness must be considered in all code. libfprint must support both big-
|
|
||||||
and little-endian systems.
|
|
||||||
|
|
||||||
|
|
||||||
Coding Style
|
|
||||||
============
|
|
||||||
|
|
||||||
This project follows Linux kernel coding style but with a tab width of 4.
|
|
||||||
|
|
||||||
|
|
||||||
Documentation
|
|
||||||
=============
|
|
||||||
|
|
||||||
All additions of public API functions must be accompanied with doxygen
|
|
||||||
comments.
|
|
||||||
|
|
||||||
All changes which potentially change the behaviour of the public API must
|
|
||||||
be reflected by updating the appropriate doxygen comments.
|
|
||||||
|
|
||||||
|
|
||||||
Contributing
|
|
||||||
============
|
|
||||||
|
|
||||||
Patches should be sent to the fprint mailing list detailed on the website.
|
|
||||||
A subscription is required.
|
|
||||||
|
|
||||||
Information about libfprint development repositories can be found here:
|
|
||||||
http://www.reactivated.net/fprint/Libfprint_development
|
|
||||||
|
|
||||||
If you're looking for ideas for things to work on, look at the TODO file or
|
|
||||||
grep the source code for FIXMEs.
|
|
||||||
|
|
||||||
+52
@@ -0,0 +1,52 @@
|
|||||||
|
# Contributing to libfprint
|
||||||
|
|
||||||
|
## GLib
|
||||||
|
|
||||||
|
Although the library uses GLib internally, libfprint is designed to provide
|
||||||
|
a completely neutral interface to it's application users. So, the public
|
||||||
|
APIs should never return GLib data types or anything like that.
|
||||||
|
|
||||||
|
## Two-faced-ness
|
||||||
|
|
||||||
|
Like any decent library, this one is designed to provide a stable and
|
||||||
|
documented API to its users: applications. Clear distinction is made between
|
||||||
|
data available internally in the library, and data/functions available to
|
||||||
|
the applications.
|
||||||
|
|
||||||
|
This library is confused a little by the fact that there is another 'interface'
|
||||||
|
at hand: the internal interface provided to drivers. So, we effectively end
|
||||||
|
up with 2 APIs:
|
||||||
|
|
||||||
|
1. The [external-facing API for applications](libfprint/fprint.h)
|
||||||
|
2. The [internal API for fingerprint drivers](libfprint/drivers_api.h)
|
||||||
|
|
||||||
|
Non-static functions which are intended for internal use only are prepended
|
||||||
|
with the "fpi_" prefix.
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
All additions of public API functions must be accompanied with gtk-doc
|
||||||
|
comments.
|
||||||
|
|
||||||
|
All changes which potentially change the behaviour of the public API must
|
||||||
|
be reflected by updating the appropriate gtk-doc comments.
|
||||||
|
|
||||||
|
|
||||||
|
## Contributing
|
||||||
|
|
||||||
|
Patches should be sent as merge requests to the gitlab page:
|
||||||
|
https://gitlab.freedesktop.org/libfprint/libfprint/merge_requests
|
||||||
|
|
||||||
|
Drivers are not usually written by libfprint developers, but when they
|
||||||
|
are, we require:
|
||||||
|
- 3 stand-alone devices. Not in a laptop or another embedded device, as
|
||||||
|
space is scarce, unless the device has special integration with that
|
||||||
|
hardware.
|
||||||
|
- specifications of the protocol.
|
||||||
|
|
||||||
|
If you are an end-user, you can file a feature request with the "Driver Request"
|
||||||
|
tag on [libfprint's issue page](https://gitlab.freedesktop.org/libfprint/libfprint/issues?scope=all&utf8=%E2%9C%93&state=opened&label_name[]=Driver%20Request),
|
||||||
|
or subscribe to an existing feature request there.
|
||||||
|
|
||||||
|
If you are an enterprising hacker, please file a new merge request with
|
||||||
|
the driver patches integrated.
|
||||||
@@ -1,234 +1,6 @@
|
|||||||
Installation Instructions
|
libfprint uses the Meson build system. See
|
||||||
*************************
|
http://mesonbuild.com/Quick-guide.html for details on how to
|
||||||
|
compile libfprint.
|
||||||
Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005,
|
|
||||||
2006 Free Software Foundation, Inc.
|
|
||||||
|
|
||||||
This file is free documentation; the Free Software Foundation gives
|
|
||||||
unlimited permission to copy, distribute and modify it.
|
|
||||||
|
|
||||||
Basic Installation
|
|
||||||
==================
|
|
||||||
|
|
||||||
Briefly, the shell commands `./configure; make; make install' should
|
|
||||||
configure, build, and install this package. The following
|
|
||||||
more-detailed instructions are generic; see the `README' file for
|
|
||||||
instructions specific to this package.
|
|
||||||
|
|
||||||
The `configure' shell script attempts to guess correct values for
|
|
||||||
various system-dependent variables used during compilation. It uses
|
|
||||||
those values to create a `Makefile' in each directory of the package.
|
|
||||||
It may also create one or more `.h' files containing system-dependent
|
|
||||||
definitions. Finally, it creates a shell script `config.status' that
|
|
||||||
you can run in the future to recreate the current configuration, and a
|
|
||||||
file `config.log' containing compiler output (useful mainly for
|
|
||||||
debugging `configure').
|
|
||||||
|
|
||||||
It can also use an optional file (typically called `config.cache'
|
|
||||||
and enabled with `--cache-file=config.cache' or simply `-C') that saves
|
|
||||||
the results of its tests to speed up reconfiguring. Caching is
|
|
||||||
disabled by default to prevent problems with accidental use of stale
|
|
||||||
cache files.
|
|
||||||
|
|
||||||
If you need to do unusual things to compile the package, please try
|
|
||||||
to figure out how `configure' could check whether to do them, and mail
|
|
||||||
diffs or instructions to the address given in the `README' so they can
|
|
||||||
be considered for the next release. If you are using the cache, and at
|
|
||||||
some point `config.cache' contains results you don't want to keep, you
|
|
||||||
may remove or edit it.
|
|
||||||
|
|
||||||
The file `configure.ac' (or `configure.in') is used to create
|
|
||||||
`configure' by a program called `autoconf'. You need `configure.ac' if
|
|
||||||
you want to change it or regenerate `configure' using a newer version
|
|
||||||
of `autoconf'.
|
|
||||||
|
|
||||||
The simplest way to compile this package is:
|
|
||||||
|
|
||||||
1. `cd' to the directory containing the package's source code and type
|
|
||||||
`./configure' to configure the package for your system.
|
|
||||||
|
|
||||||
Running `configure' might take a while. While running, it prints
|
|
||||||
some messages telling which features it is checking for.
|
|
||||||
|
|
||||||
2. Type `make' to compile the package.
|
|
||||||
|
|
||||||
3. Optionally, type `make check' to run any self-tests that come with
|
|
||||||
the package.
|
|
||||||
|
|
||||||
4. Type `make install' to install the programs and any data files and
|
|
||||||
documentation.
|
|
||||||
|
|
||||||
5. You can remove the program binaries and object files from the
|
|
||||||
source code directory by typing `make clean'. To also remove the
|
|
||||||
files that `configure' created (so you can compile the package for
|
|
||||||
a different kind of computer), type `make distclean'. There is
|
|
||||||
also a `make maintainer-clean' target, but that is intended mainly
|
|
||||||
for the package's developers. If you use it, you may have to get
|
|
||||||
all sorts of other programs in order to regenerate files that came
|
|
||||||
with the distribution.
|
|
||||||
|
|
||||||
Compilers and Options
|
|
||||||
=====================
|
|
||||||
|
|
||||||
Some systems require unusual options for compilation or linking that the
|
|
||||||
`configure' script does not know about. Run `./configure --help' for
|
|
||||||
details on some of the pertinent environment variables.
|
|
||||||
|
|
||||||
You can give `configure' initial values for configuration parameters
|
|
||||||
by setting variables in the command line or in the environment. Here
|
|
||||||
is an example:
|
|
||||||
|
|
||||||
./configure CC=c99 CFLAGS=-g LIBS=-lposix
|
|
||||||
|
|
||||||
*Note Defining Variables::, for more details.
|
|
||||||
|
|
||||||
Compiling For Multiple Architectures
|
|
||||||
====================================
|
|
||||||
|
|
||||||
You can compile the package for more than one kind of computer at the
|
|
||||||
same time, by placing the object files for each architecture in their
|
|
||||||
own directory. To do this, you can use GNU `make'. `cd' to the
|
|
||||||
directory where you want the object files and executables to go and run
|
|
||||||
the `configure' script. `configure' automatically checks for the
|
|
||||||
source code in the directory that `configure' is in and in `..'.
|
|
||||||
|
|
||||||
With a non-GNU `make', it is safer to compile the package for one
|
|
||||||
architecture at a time in the source code directory. After you have
|
|
||||||
installed the package for one architecture, use `make distclean' before
|
|
||||||
reconfiguring for another architecture.
|
|
||||||
|
|
||||||
Installation Names
|
|
||||||
==================
|
|
||||||
|
|
||||||
By default, `make install' installs the package's commands under
|
|
||||||
`/usr/local/bin', include files under `/usr/local/include', etc. You
|
|
||||||
can specify an installation prefix other than `/usr/local' by giving
|
|
||||||
`configure' the option `--prefix=PREFIX'.
|
|
||||||
|
|
||||||
You can specify separate installation prefixes for
|
|
||||||
architecture-specific files and architecture-independent files. If you
|
|
||||||
pass the option `--exec-prefix=PREFIX' to `configure', the package uses
|
|
||||||
PREFIX as the prefix for installing programs and libraries.
|
|
||||||
Documentation and other data files still use the regular prefix.
|
|
||||||
|
|
||||||
In addition, if you use an unusual directory layout you can give
|
|
||||||
options like `--bindir=DIR' to specify different values for particular
|
|
||||||
kinds of files. Run `configure --help' for a list of the directories
|
|
||||||
you can set and what kinds of files go in them.
|
|
||||||
|
|
||||||
If the package supports it, you can cause programs to be installed
|
|
||||||
with an extra prefix or suffix on their names by giving `configure' the
|
|
||||||
option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
|
|
||||||
|
|
||||||
Optional Features
|
|
||||||
=================
|
|
||||||
|
|
||||||
Some packages pay attention to `--enable-FEATURE' options to
|
|
||||||
`configure', where FEATURE indicates an optional part of the package.
|
|
||||||
They may also pay attention to `--with-PACKAGE' options, where PACKAGE
|
|
||||||
is something like `gnu-as' or `x' (for the X Window System). The
|
|
||||||
`README' should mention any `--enable-' and `--with-' options that the
|
|
||||||
package recognizes.
|
|
||||||
|
|
||||||
For packages that use the X Window System, `configure' can usually
|
|
||||||
find the X include and library files automatically, but if it doesn't,
|
|
||||||
you can use the `configure' options `--x-includes=DIR' and
|
|
||||||
`--x-libraries=DIR' to specify their locations.
|
|
||||||
|
|
||||||
Specifying the System Type
|
|
||||||
==========================
|
|
||||||
|
|
||||||
There may be some features `configure' cannot figure out automatically,
|
|
||||||
but needs to determine by the type of machine the package will run on.
|
|
||||||
Usually, assuming the package is built to be run on the _same_
|
|
||||||
architectures, `configure' can figure that out, but if it prints a
|
|
||||||
message saying it cannot guess the machine type, give it the
|
|
||||||
`--build=TYPE' option. TYPE can either be a short name for the system
|
|
||||||
type, such as `sun4', or a canonical name which has the form:
|
|
||||||
|
|
||||||
CPU-COMPANY-SYSTEM
|
|
||||||
|
|
||||||
where SYSTEM can have one of these forms:
|
|
||||||
|
|
||||||
OS KERNEL-OS
|
|
||||||
|
|
||||||
See the file `config.sub' for the possible values of each field. If
|
|
||||||
`config.sub' isn't included in this package, then this package doesn't
|
|
||||||
need to know the machine type.
|
|
||||||
|
|
||||||
If you are _building_ compiler tools for cross-compiling, you should
|
|
||||||
use the option `--target=TYPE' to select the type of system they will
|
|
||||||
produce code for.
|
|
||||||
|
|
||||||
If you want to _use_ a cross compiler, that generates code for a
|
|
||||||
platform different from the build platform, you should specify the
|
|
||||||
"host" platform (i.e., that on which the generated programs will
|
|
||||||
eventually be run) with `--host=TYPE'.
|
|
||||||
|
|
||||||
Sharing Defaults
|
|
||||||
================
|
|
||||||
|
|
||||||
If you want to set default values for `configure' scripts to share, you
|
|
||||||
can create a site shell script called `config.site' that gives default
|
|
||||||
values for variables like `CC', `cache_file', and `prefix'.
|
|
||||||
`configure' looks for `PREFIX/share/config.site' if it exists, then
|
|
||||||
`PREFIX/etc/config.site' if it exists. Or, you can set the
|
|
||||||
`CONFIG_SITE' environment variable to the location of the site script.
|
|
||||||
A warning: not all `configure' scripts look for a site script.
|
|
||||||
|
|
||||||
Defining Variables
|
|
||||||
==================
|
|
||||||
|
|
||||||
Variables not defined in a site shell script can be set in the
|
|
||||||
environment passed to `configure'. However, some packages may run
|
|
||||||
configure again during the build, and the customized values of these
|
|
||||||
variables may be lost. In order to avoid this problem, you should set
|
|
||||||
them in the `configure' command line, using `VAR=value'. For example:
|
|
||||||
|
|
||||||
./configure CC=/usr/local2/bin/gcc
|
|
||||||
|
|
||||||
causes the specified `gcc' to be used as the C compiler (unless it is
|
|
||||||
overridden in the site shell script).
|
|
||||||
|
|
||||||
Unfortunately, this technique does not work for `CONFIG_SHELL' due to
|
|
||||||
an Autoconf bug. Until the bug is fixed you can use this workaround:
|
|
||||||
|
|
||||||
CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash
|
|
||||||
|
|
||||||
`configure' Invocation
|
|
||||||
======================
|
|
||||||
|
|
||||||
`configure' recognizes the following options to control how it operates.
|
|
||||||
|
|
||||||
`--help'
|
|
||||||
`-h'
|
|
||||||
Print a summary of the options to `configure', and exit.
|
|
||||||
|
|
||||||
`--version'
|
|
||||||
`-V'
|
|
||||||
Print the version of Autoconf used to generate the `configure'
|
|
||||||
script, and exit.
|
|
||||||
|
|
||||||
`--cache-file=FILE'
|
|
||||||
Enable the cache: use and save the results of the tests in FILE,
|
|
||||||
traditionally `config.cache'. FILE defaults to `/dev/null' to
|
|
||||||
disable caching.
|
|
||||||
|
|
||||||
`--config-cache'
|
|
||||||
`-C'
|
|
||||||
Alias for `--cache-file=config.cache'.
|
|
||||||
|
|
||||||
`--quiet'
|
|
||||||
`--silent'
|
|
||||||
`-q'
|
|
||||||
Do not print messages saying which checks are being made. To
|
|
||||||
suppress all normal output, redirect it to `/dev/null' (any error
|
|
||||||
messages will still be shown).
|
|
||||||
|
|
||||||
`--srcdir=DIR'
|
|
||||||
Look for the package's source code in directory DIR. Usually
|
|
||||||
`configure' can determine that directory automatically.
|
|
||||||
|
|
||||||
`configure' also accepts some other, not widely useful, options. Run
|
|
||||||
`configure --help' for more details.
|
|
||||||
|
|
||||||
|
The "meson configure" command will give you a list of available
|
||||||
|
command-line options.
|
||||||
|
|||||||
-22
@@ -1,22 +0,0 @@
|
|||||||
AUTOMAKE_OPTIONS = dist-bzip2
|
|
||||||
ACLOCAL_AMFLAGS = -I m4
|
|
||||||
EXTRA_DIST = THANKS TODO HACKING libfprint.pc.in
|
|
||||||
DISTCLEANFILES = ChangeLog libfprint.pc
|
|
||||||
|
|
||||||
SUBDIRS = libfprint doc
|
|
||||||
|
|
||||||
if BUILD_EXAMPLES
|
|
||||||
SUBDIRS += examples
|
|
||||||
endif
|
|
||||||
|
|
||||||
pkgconfigdir=$(libdir)/pkgconfig
|
|
||||||
pkgconfig_DATA=libfprint.pc
|
|
||||||
|
|
||||||
.PHONY: ChangeLog dist-up
|
|
||||||
ChangeLog:
|
|
||||||
git --git-dir $(top_srcdir)/.git log > ChangeLog || touch ChangeLog
|
|
||||||
|
|
||||||
dist-hook: ChangeLog
|
|
||||||
|
|
||||||
dist-up: dist
|
|
||||||
rsync $(distdir).tar.bz2 frs.sourceforge.net:uploads/
|
|
||||||
@@ -1,6 +1,140 @@
|
|||||||
This file lists notable changes in each release. For the full history of all
|
This file lists notable changes in each release. For the full history of all
|
||||||
changes, see ChangeLog.
|
changes, see ChangeLog.
|
||||||
|
|
||||||
|
2018-12-14: v0.99.0 release
|
||||||
|
* Library:
|
||||||
|
- All the internal API for device driver writers is now covered by the
|
||||||
|
documentation and has been enhanced to make it easier to write drivers
|
||||||
|
- Update internal NBIS fingerprint data processing library to one that's
|
||||||
|
nearly 10 years newer
|
||||||
|
- Re-add accessor for minutia coordinates which was used in the very
|
||||||
|
old fprint_demo program, but also by our new GTK+ test program (see below)
|
||||||
|
- Fix a crash when too many minutiae were detected in a capture
|
||||||
|
|
||||||
|
* Drivers:
|
||||||
|
- Support more devices in the Elan driver, stability improvements
|
||||||
|
|
||||||
|
* Tools:
|
||||||
|
- Add a test GTK+ application that will eventually be used for testing
|
||||||
|
drivers without modifying the OS installed version. Note that this
|
||||||
|
application currently requires manually changing permissions of USB
|
||||||
|
devices, this will be fixed when the infrastructure exists to access
|
||||||
|
those devices without additional permissions, as a normal user.
|
||||||
|
|
||||||
|
2018-07-15: v0.8.2 release
|
||||||
|
* Drivers:
|
||||||
|
- Add USB ID for TNP Nano USB Fingerprint Reader
|
||||||
|
- Fix UPEKTS enrollment never finishing on some devices
|
||||||
|
|
||||||
|
* Library:
|
||||||
|
- Fix fp_get_pollfds() retval type, a small ABI change
|
||||||
|
- Downgrade fatal errors to run-time warnings, as a number of drivers
|
||||||
|
used to throw silent errors and we made them fatal. Those will now
|
||||||
|
be visible warnings, hopefully helping with fixing them.
|
||||||
|
|
||||||
|
2018-06-12: v0.8.1 release
|
||||||
|
- Brown paperbag release to install the udev rules file in the correct
|
||||||
|
directory if the udev pkg-config file doesn't have a trailing slash
|
||||||
|
|
||||||
|
2018-06-12: v0.8.0 release
|
||||||
|
- Port to meson as the build system
|
||||||
|
- Port documentation to gtk-doc
|
||||||
|
|
||||||
|
* Drivers:
|
||||||
|
- Add Elan driver
|
||||||
|
- Increase threshold to detect encryption on URU4000 devices
|
||||||
|
- Remove already replaced UPEKE2 driver
|
||||||
|
- Fix possible crash caused by vfs5011 when no lines were captured
|
||||||
|
|
||||||
|
* Library:
|
||||||
|
- Fix a number of memory and file descriptor leaks and warnings
|
||||||
|
- Make NSS (and URU4000) driver optional
|
||||||
|
- Fix assembling of frames for non-reverse and non reverse stripes
|
||||||
|
- Split internal private header to clarify drivers API
|
||||||
|
- Simplify logging system, now all the builds can be used to output
|
||||||
|
debug information
|
||||||
|
- Mark fp_dscv_print functions as deprecated
|
||||||
|
|
||||||
|
* Udev rules:
|
||||||
|
- Add some unsupported devices to the whitelist
|
||||||
|
|
||||||
|
2017-05-14: v0.7.0 release
|
||||||
|
* Drivers:
|
||||||
|
- Add VFS0050 driver
|
||||||
|
- Fix possible crash in AES3500 and AES4000
|
||||||
|
- Fix broken enrollment in VFS101
|
||||||
|
- Better verification with small sensor scanners
|
||||||
|
- Plenty of fixes in VFS5011
|
||||||
|
- Fix memory corruption in AES1610
|
||||||
|
- Improve calibration settings for AES1610
|
||||||
|
- Improve image assembling in upeksonly driver
|
||||||
|
- Autodetect whether image is encrypted in uru4k
|
||||||
|
|
||||||
|
* Library:
|
||||||
|
- NBIS: Remove false minutia at the edge of partial image
|
||||||
|
- Introduce routines to assemble image from lines (used in VFS5011 and upeksonly)
|
||||||
|
- Fix a bug that can cause driver state machine to enter into endless loop.
|
||||||
|
|
||||||
|
* Udev rules:
|
||||||
|
- Add driver name to the USB properties
|
||||||
|
|
||||||
|
* Plenty of build fixes
|
||||||
|
|
||||||
|
2015-02-03: v0.6.0 release
|
||||||
|
|
||||||
|
* Drivers:
|
||||||
|
- Reduce duplication between AES3500 and AES4000 drivers and
|
||||||
|
add support for AES3500 device
|
||||||
|
- Add support for UPEK 147e:2020 and Upek Eikon 2 devices
|
||||||
|
- Add EgisTec ES603 driver
|
||||||
|
- Add VFS5011 driver
|
||||||
|
- Always perform 5 scans for image enrollment
|
||||||
|
- Better verification with AES1660 driver
|
||||||
|
- Better verification for a number of AES drivers
|
||||||
|
|
||||||
|
* Library:
|
||||||
|
- Always use Pixman for image manipulation, gdk-pixbuf and ImageMagick
|
||||||
|
are not supported any more.
|
||||||
|
|
||||||
|
* Udev rules:
|
||||||
|
- Fix warning when USB hub or system does not support power management
|
||||||
|
|
||||||
|
2013-08-11: v0.5.1 release
|
||||||
|
|
||||||
|
* Drivers
|
||||||
|
- Add support for 147e:2020 to upeke2 driver
|
||||||
|
- Fix possible race condition, and cancellation in uru4000 driver
|
||||||
|
|
||||||
|
* Udev rules:
|
||||||
|
- Add Microsoft keyboard to the suspend blacklist
|
||||||
|
|
||||||
|
* Plenty of build fixes
|
||||||
|
|
||||||
|
2012-12-03: v0.5.0 release
|
||||||
|
|
||||||
|
* Drivers:
|
||||||
|
- New VFS300/VFS301 driver
|
||||||
|
- New AES2550/AES2810 drivers
|
||||||
|
- New AES1660 driver
|
||||||
|
- New AES2660 driver
|
||||||
|
- New DigitalPersona URU4500 driver
|
||||||
|
- Avoid empty capture and improve image contrast in the
|
||||||
|
AES2501 and AES2550 drivers
|
||||||
|
- Update upektc driver, add support for Eikon Touch 300
|
||||||
|
- Fix UrU4000 image capture on ARM
|
||||||
|
|
||||||
|
* Library:
|
||||||
|
- Fix global variable collisions with libusb and other system headers
|
||||||
|
- Fix possible crash in NBIS image processing with some fingerprints
|
||||||
|
|
||||||
|
* Udev rules:
|
||||||
|
- Fix power control path for newer kernels
|
||||||
|
- Move udev rules to the correct directory
|
||||||
|
- Don't print duplicated udev rules
|
||||||
|
- Include udev rules in the tarball
|
||||||
|
- Allow disabling of udev rules for cross-compiling
|
||||||
|
- Add driver names in the generated rules
|
||||||
|
|
||||||
2011-04-18: v0.4.0 release
|
2011-04-18: v0.4.0 release
|
||||||
* Add support for Validity VFS101 (USB ID 138a:0001)
|
* Add support for Validity VFS101 (USB ID 138a:0001)
|
||||||
* Fix crasher when resizing a fingerprint image
|
* Fix crasher when resizing a fingerprint image
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ libfprint
|
|||||||
=========
|
=========
|
||||||
|
|
||||||
libfprint is part of the fprint project:
|
libfprint is part of the fprint project:
|
||||||
http://www.reactivated.net/fprint
|
https://fprint.freedesktop.org/
|
||||||
|
|
||||||
libfprint was originally developed as part of an academic project at the
|
libfprint was originally developed as part of an academic project at the
|
||||||
University of Manchester with the aim of hiding differences between different
|
University of Manchester with the aim of hiding differences between different
|
||||||
@@ -22,7 +22,7 @@ university computers and the project is not hosted at the university either.
|
|||||||
|
|
||||||
For more information on libfprint, supported devices, API documentation, etc.,
|
For more information on libfprint, supported devices, API documentation, etc.,
|
||||||
see the homepage:
|
see the homepage:
|
||||||
http://www.reactivated.net/fprint/Libfprint
|
https://fprint.freedesktop.org/
|
||||||
|
|
||||||
libfprint is licensed under the GNU LGPL version 2.1. See the COPYING file
|
libfprint is licensed under the GNU LGPL version 2.1. See the COPYING file
|
||||||
for the license text.
|
for the license text.
|
||||||
@@ -37,5 +37,15 @@ libfprint includes code from NIST's NBIS software distribution:
|
|||||||
http://fingerprint.nist.gov/NBIS/index.html
|
http://fingerprint.nist.gov/NBIS/index.html
|
||||||
We include bozorth3 from the US export controlled distribution. We have
|
We include bozorth3 from the US export controlled distribution. We have
|
||||||
determined that it is fine to ship bozorth3 in an open source project,
|
determined that it is fine to ship bozorth3 in an open source project,
|
||||||
see http://reactivated.net/fprint/wiki/US_export_control
|
see https://fprint.freedesktop.org/us-export-control.html
|
||||||
|
|
||||||
|
## Historical links
|
||||||
|
|
||||||
|
Older versions of libfprint are available at:
|
||||||
|
https://sourceforge.net/projects/fprint/files/
|
||||||
|
|
||||||
|
Historical mailing-list archives:
|
||||||
|
http://www.reactivated.net/fprint_list_archives/
|
||||||
|
|
||||||
|
Historical website:
|
||||||
|
http://web.archive.org/web/*/https://www.freedesktop.org/wiki/Software/fprint/
|
||||||
|
|||||||
@@ -8,3 +8,4 @@ Toby Howard (University of Manchester)
|
|||||||
Seemant Kulleen
|
Seemant Kulleen
|
||||||
Pavel Herrman
|
Pavel Herrman
|
||||||
Bastien Nocera
|
Bastien Nocera
|
||||||
|
Greg Kerr and Martin Konecny from AuthenTec Inc - hardware donations (AES2550 device), datasheets for AES2550 and AES2810
|
||||||
|
|||||||
@@ -1,8 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
libtoolize --copy --force || exit 1
|
|
||||||
aclocal || exit 1
|
|
||||||
autoheader || exit 1
|
|
||||||
autoconf || exit 1
|
|
||||||
automake -a -c || exit 1
|
|
||||||
./configure --enable-maintainer-mode --enable-examples-build \
|
|
||||||
--enable-x11-examples-build --enable-debug-log $*
|
|
||||||
-288
@@ -1,288 +0,0 @@
|
|||||||
AC_INIT([libfprint], [0.4.0])
|
|
||||||
AM_INIT_AUTOMAKE([1.11 dist-bzip2 no-dist-gzip check-news])
|
|
||||||
AC_CONFIG_MACRO_DIR([m4])
|
|
||||||
AC_CONFIG_SRCDIR([libfprint/core.c])
|
|
||||||
AM_CONFIG_HEADER([config.h])
|
|
||||||
|
|
||||||
# Enable silent build when available (Automake 1.11)
|
|
||||||
m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])])
|
|
||||||
|
|
||||||
AC_PREREQ([2.50])
|
|
||||||
AC_PROG_CC
|
|
||||||
AC_PROG_LIBTOOL
|
|
||||||
AC_C_INLINE
|
|
||||||
AM_PROG_CC_C_O
|
|
||||||
AC_PROG_CXX
|
|
||||||
AC_DEFINE([_GNU_SOURCE], [], [Use GNU extensions])
|
|
||||||
|
|
||||||
# Library versioning
|
|
||||||
lt_major="0"
|
|
||||||
lt_revision="0"
|
|
||||||
lt_age="0"
|
|
||||||
AC_SUBST(lt_major)
|
|
||||||
AC_SUBST(lt_revision)
|
|
||||||
AC_SUBST(lt_age)
|
|
||||||
|
|
||||||
all_drivers="upeke2 upekts upektc upeksonly vcom5s uru4000 fdu2000 aes1610 aes2501 aes4000 vfs101"
|
|
||||||
|
|
||||||
require_imaging='no'
|
|
||||||
require_aeslib='no'
|
|
||||||
enable_upeke2='no'
|
|
||||||
enable_upekts='no'
|
|
||||||
enable_upektc='no'
|
|
||||||
enable_upeksonly='no'
|
|
||||||
enable_vcom5s='no'
|
|
||||||
enable_uru4000='no'
|
|
||||||
enable_fdu2000='no'
|
|
||||||
enable_aes1610='no'
|
|
||||||
enable_aes2501='no'
|
|
||||||
enable_aes4000='no'
|
|
||||||
enable_vfs101='no'
|
|
||||||
|
|
||||||
AC_ARG_WITH([drivers],[AS_HELP_STRING([--with-drivers],
|
|
||||||
[List of drivers to enable])],
|
|
||||||
[drivers="$withval"],
|
|
||||||
[drivers="$all_drivers"])
|
|
||||||
|
|
||||||
for driver in `echo ${drivers} | sed -e 's/,/ /g' -e 's/,$//g'`; do
|
|
||||||
case ${driver} in
|
|
||||||
upekts)
|
|
||||||
AC_DEFINE([ENABLE_UPEKTS], [], [Build UPEK TouchStrip driver])
|
|
||||||
enable_upekts="yes"
|
|
||||||
;;
|
|
||||||
upeke2)
|
|
||||||
AC_DEFINE([ENABLE_UPEKE2], [], [Build UPEK Eikon 2])
|
|
||||||
enable_upeke2="yes"
|
|
||||||
;;
|
|
||||||
upektc)
|
|
||||||
AC_DEFINE([ENABLE_UPEKTC], [], [Build UPEK TouchChip driver])
|
|
||||||
enable_upektc="no"
|
|
||||||
# Driver not ported
|
|
||||||
;;
|
|
||||||
upeksonly)
|
|
||||||
AC_DEFINE([ENABLE_UPEKSONLY], [], [Build UPEK TouchStrip sensor-only driver])
|
|
||||||
enable_upeksonly="yes"
|
|
||||||
;;
|
|
||||||
uru4000)
|
|
||||||
AC_DEFINE([ENABLE_URU4000], [], [Build Digital Persona U.are.U 4000 driver])
|
|
||||||
enable_uru4000="yes"
|
|
||||||
;;
|
|
||||||
fdu2000)
|
|
||||||
AC_DEFINE([ENABLE_FDU2000], [], [Build Secugen FDU 2000 driver])
|
|
||||||
enable_fdu2000="no"
|
|
||||||
# Driver not ported
|
|
||||||
;;
|
|
||||||
vcom5s)
|
|
||||||
AC_DEFINE([ENABLE_VCOM5S], [], [Build Veridicom 5thSense driver])
|
|
||||||
enable_vcom5s="yes"
|
|
||||||
;;
|
|
||||||
aes2501)
|
|
||||||
AC_DEFINE([ENABLE_AES2501], [], [Build AuthenTec AES2501 driver])
|
|
||||||
require_aeslib="yes"
|
|
||||||
enable_aes2501="yes"
|
|
||||||
;;
|
|
||||||
aes1610)
|
|
||||||
AC_DEFINE([ENABLE_AES1610], [], [Build AuthenTec AES1610 driver])
|
|
||||||
require_aeslib="yes"
|
|
||||||
enable_aes1610="yes"
|
|
||||||
;;
|
|
||||||
aes4000)
|
|
||||||
AC_DEFINE([ENABLE_AES4000], [], [Build AuthenTec AES4000 driver])
|
|
||||||
require_aeslib="yes"
|
|
||||||
require_imaging="yes"
|
|
||||||
enable_aes4000="yes"
|
|
||||||
;;
|
|
||||||
vfs101)
|
|
||||||
AC_DEFINE([ENABLE_VFS101], [], [Build Validity VFS101 driver])
|
|
||||||
enable_vfs101="yes"
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
|
|
||||||
AM_CONDITIONAL([ENABLE_UPEKTS], [test "$enable_upekts" = "yes"])
|
|
||||||
AM_CONDITIONAL([ENABLE_UPEKE2], [test "$enable_upeke2" = "yes"])
|
|
||||||
#AM_CONDITIONAL([ENABLE_UPEKTC], [test "$enable_upektc" = "yes"])
|
|
||||||
AM_CONDITIONAL([ENABLE_UPEKSONLY], [test "$enable_upeksonly" = "yes"])
|
|
||||||
AM_CONDITIONAL([ENABLE_VCOM5S], [test "$enable_vcom5s" = "yes"])
|
|
||||||
AM_CONDITIONAL([ENABLE_URU4000], [test "$enable_uru4000" = "yes"])
|
|
||||||
AM_CONDITIONAL([ENABLE_FDU2000], [test "$enable_fdu2000" = "yes"])
|
|
||||||
AM_CONDITIONAL([ENABLE_AES1610], [test "$enable_aes1610" = "yes"])
|
|
||||||
AM_CONDITIONAL([ENABLE_AES2501], [test "$enable_aes2501" = "yes"])
|
|
||||||
AM_CONDITIONAL([ENABLE_AES4000], [test "$enable_aes4000" = "yes"])
|
|
||||||
AM_CONDITIONAL([REQUIRE_AESLIB], [test "$require_aeslib" = "yes"])
|
|
||||||
AM_CONDITIONAL([ENABLE_VFS101], [test "$enable_vfs101" = "yes"])
|
|
||||||
|
|
||||||
|
|
||||||
PKG_CHECK_MODULES(LIBUSB, [libusb-1.0 >= 0.9.1])
|
|
||||||
AC_SUBST(LIBUSB_CFLAGS)
|
|
||||||
AC_SUBST(LIBUSB_LIBS)
|
|
||||||
|
|
||||||
# check for OpenSSL's libcrypto
|
|
||||||
PKG_CHECK_MODULES(CRYPTO, nss)
|
|
||||||
AC_SUBST(CRYPTO_CFLAGS)
|
|
||||||
AC_SUBST(CRYPTO_LIBS)
|
|
||||||
|
|
||||||
PKG_CHECK_MODULES(GLIB, "glib-2.0")
|
|
||||||
AC_SUBST(GLIB_CFLAGS)
|
|
||||||
AC_SUBST(GLIB_LIBS)
|
|
||||||
|
|
||||||
imagemagick_found=no
|
|
||||||
gdkpixbuf_found=no
|
|
||||||
|
|
||||||
if test "$require_imaging" = "yes"; then
|
|
||||||
PKG_CHECK_MODULES(IMAGING, gthread-2.0 gdk-pixbuf-2.0, [gdkpixbuf_found=yes], [gdkpixbuf_found=no])
|
|
||||||
if test "$gdkpixbuf_found" != "yes"; then
|
|
||||||
PKG_CHECK_MODULES(IMAGING, ImageMagick, [imagemagick_found=yes], [imagemagick_found=no])
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
if test "$require_imaging" = "yes"; then
|
|
||||||
if test "$gdkpixbuf_found" != "yes" && test "$imagemagick_found" != "yes"; then
|
|
||||||
AC_MSG_ERROR([gdk-pixbuf or ImageMagick is required for imaging support])
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
AM_CONDITIONAL([REQUIRE_GDKPIXBUF], [test "$gdkpixbuf_found" = "yes"])
|
|
||||||
AM_CONDITIONAL([REQUIRE_IMAGEMAGICK], [test "$imagemagick_found" = "yes"])
|
|
||||||
AC_SUBST(IMAGING_CFLAGS)
|
|
||||||
AC_SUBST(IMAGING_LIBS)
|
|
||||||
|
|
||||||
# Examples build
|
|
||||||
AC_ARG_ENABLE([examples-build], [AS_HELP_STRING([--enable-examples-build],
|
|
||||||
[build example applications (default n)])],
|
|
||||||
[build_examples=$enableval],
|
|
||||||
[build_examples='no'])
|
|
||||||
AM_CONDITIONAL([BUILD_EXAMPLES], [test "x$build_examples" != "xno"])
|
|
||||||
|
|
||||||
# Examples build
|
|
||||||
AC_ARG_ENABLE([x11-examples-build], [AS_HELP_STRING([--enable-x11-examples-build],
|
|
||||||
[build X11 example applications (default n)])],
|
|
||||||
[build_x11_examples=$enableval],
|
|
||||||
[build_x11_examples='no'])
|
|
||||||
AM_CONDITIONAL([BUILD_X11_EXAMPLES], [test "x$build_x11_examples" != "xno"])
|
|
||||||
|
|
||||||
|
|
||||||
if test "x$build_x11_examples" != "xno"; then
|
|
||||||
# check for Xv extensions
|
|
||||||
# imported from Coriander
|
|
||||||
AC_DEFUN([AC_CHECK_XV],[
|
|
||||||
AC_SUBST(XV_CFLAGS)
|
|
||||||
AC_SUBST(XV_LIBS)
|
|
||||||
AC_MSG_CHECKING(for Xv extensions)
|
|
||||||
AC_TRY_COMPILE([
|
|
||||||
#include <X11/Xlib.h>
|
|
||||||
#include <X11/extensions/Xvlib.h>],[
|
|
||||||
int main(void) { (void) XvGetPortAttribute(0, 0, 0, 0); return 0; }
|
|
||||||
],xv=yes,xv=no);
|
|
||||||
AC_MSG_RESULT($xv)
|
|
||||||
if test x$xv = xyes; then
|
|
||||||
XV_LIBS="-lXv -lXext"
|
|
||||||
XV_CFLAGS=""
|
|
||||||
AC_DEFINE(HAVE_XV,1,[defined if XV video overlay is available])
|
|
||||||
else
|
|
||||||
AC_MSG_ERROR([XV is required for X11 examples])
|
|
||||||
fi
|
|
||||||
])
|
|
||||||
AC_CHECK_XV
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Message logging
|
|
||||||
AC_ARG_ENABLE([log], [AS_HELP_STRING([--disable-log], [disable all logging])],
|
|
||||||
[log_enabled=$enableval],
|
|
||||||
[log_enabled='yes'])
|
|
||||||
if test "x$log_enabled" != "xno"; then
|
|
||||||
AC_DEFINE([ENABLE_LOGGING], 1, [Message logging])
|
|
||||||
fi
|
|
||||||
|
|
||||||
AC_ARG_ENABLE([debug-log], [AS_HELP_STRING([--enable-debug-log],
|
|
||||||
[enable debug logging (default n)])],
|
|
||||||
[debug_log_enabled=$enableval],
|
|
||||||
[debug_log_enabled='no'])
|
|
||||||
if test "x$debug_log_enabled" != "xno"; then
|
|
||||||
AC_DEFINE([ENABLE_DEBUG_LOGGING], 1, [Debug message logging])
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Restore gnu89 inline semantics on gcc 4.3 and newer
|
|
||||||
saved_cflags="$CFLAGS"
|
|
||||||
CFLAGS="$CFLAGS -fgnu89-inline"
|
|
||||||
AC_COMPILE_IFELSE(AC_LANG_PROGRAM([]), inline_cflags="-fgnu89-inline", inline_cflags="")
|
|
||||||
CFLAGS="$saved_cflags"
|
|
||||||
|
|
||||||
AC_DEFINE([API_EXPORTED], [__attribute__((visibility("default")))], [Default visibility])
|
|
||||||
AM_CFLAGS="-std=gnu99 $inline_cflags -Wall -Wundef -Wunused -Wstrict-prototypes -Werror-implicit-function-declaration -Wno-pointer-sign -Wshadow"
|
|
||||||
AC_SUBST(AM_CFLAGS)
|
|
||||||
|
|
||||||
if test "$require_imaging" = "yes"; then
|
|
||||||
if test x$gdkpixbuf_found != no; then
|
|
||||||
AC_MSG_NOTICE([** Using gdk-pixbuf for imaging])
|
|
||||||
else
|
|
||||||
AC_MSG_NOTICE([** Using ImageMagick for imaging])
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
AC_MSG_NOTICE([ Imaging support disabled])
|
|
||||||
fi
|
|
||||||
|
|
||||||
if test x$enable_upekts != xno ; then
|
|
||||||
AC_MSG_NOTICE([** upekts driver enabled])
|
|
||||||
else
|
|
||||||
AC_MSG_NOTICE([ upekts driver disabled])
|
|
||||||
fi
|
|
||||||
if test x$enable_upeke2 != xno ; then
|
|
||||||
AC_MSG_NOTICE([** upeke2 driver enabled])
|
|
||||||
else
|
|
||||||
AC_MSG_NOTICE([ upeke2 driver disabled])
|
|
||||||
fi
|
|
||||||
if test x$enable_upektc != xno ; then
|
|
||||||
AC_MSG_NOTICE([** upektc driver enabled])
|
|
||||||
else
|
|
||||||
AC_MSG_NOTICE([ upektc driver disabled])
|
|
||||||
fi
|
|
||||||
if test x$enable_upeksonly != xno ; then
|
|
||||||
AC_MSG_NOTICE([** upeksonly driver enabled])
|
|
||||||
else
|
|
||||||
AC_MSG_NOTICE([ upeksonly driver disabled])
|
|
||||||
fi
|
|
||||||
if test x$enable_vcom5s != xno ; then
|
|
||||||
AC_MSG_NOTICE([** vcom5s driver enabled])
|
|
||||||
else
|
|
||||||
AC_MSG_NOTICE([ vcom5s driver disabled])
|
|
||||||
fi
|
|
||||||
if test x$enable_uru4000 != xno ; then
|
|
||||||
AC_MSG_NOTICE([** uru4000 driver enabled])
|
|
||||||
else
|
|
||||||
AC_MSG_NOTICE([ uru4000 driver disabled])
|
|
||||||
fi
|
|
||||||
if test x$enable_fdu2000 != xno ; then
|
|
||||||
AC_MSG_NOTICE([** fdu2000 driver enabled])
|
|
||||||
else
|
|
||||||
AC_MSG_NOTICE([ fdu2000 driver disabled])
|
|
||||||
fi
|
|
||||||
if test x$enable_aes1610 != xno ; then
|
|
||||||
AC_MSG_NOTICE([** aes1610 driver enabled])
|
|
||||||
else
|
|
||||||
AC_MSG_NOTICE([ aes1610 driver disabled])
|
|
||||||
fi
|
|
||||||
if test x$enable_aes2501 != xno ; then
|
|
||||||
AC_MSG_NOTICE([** aes2501 driver enabled])
|
|
||||||
else
|
|
||||||
AC_MSG_NOTICE([ aes2501 driver disabled])
|
|
||||||
fi
|
|
||||||
if test x$enable_aes4000 != xno ; then
|
|
||||||
AC_MSG_NOTICE([** aes4000 driver enabled])
|
|
||||||
else
|
|
||||||
AC_MSG_NOTICE([ aes4000 driver disabled])
|
|
||||||
fi
|
|
||||||
if test x$enable_vfs101 != xno ; then
|
|
||||||
AC_MSG_NOTICE([** vfs101 driver enabled])
|
|
||||||
else
|
|
||||||
AC_MSG_NOTICE([ vfs101 driver disabled])
|
|
||||||
fi
|
|
||||||
if test x$require_aeslib != xno ; then
|
|
||||||
AC_MSG_NOTICE([** aeslib helper functions enabled])
|
|
||||||
else
|
|
||||||
AC_MSG_NOTICE([ aeslib helper functions disabled])
|
|
||||||
fi
|
|
||||||
|
|
||||||
AC_CONFIG_FILES([libfprint.pc] [Makefile] [libfprint/Makefile] [examples/Makefile] [doc/Makefile])
|
|
||||||
AC_OUTPUT
|
|
||||||
|
|
||||||
@@ -0,0 +1,523 @@
|
|||||||
|
/*
|
||||||
|
* Example libfprint GTK+ image capture program
|
||||||
|
* Copyright (C) 2018 Bastien Nocera <hadess@hadess.net>
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <gtk/gtk.h>
|
||||||
|
#include <libfprint/fprint.h>
|
||||||
|
|
||||||
|
#include "loop.h"
|
||||||
|
|
||||||
|
typedef GtkApplication LibfprintDemo;
|
||||||
|
typedef GtkApplicationClass LibfprintDemoClass;
|
||||||
|
|
||||||
|
G_DEFINE_TYPE (LibfprintDemo, libfprint_demo, GTK_TYPE_APPLICATION)
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
IMAGE_DISPLAY_NONE = 0,
|
||||||
|
IMAGE_DISPLAY_MINUTIAE = 1 << 0,
|
||||||
|
IMAGE_DISPLAY_BINARY = 1 << 1
|
||||||
|
} ImageDisplayFlags;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
GtkApplicationWindow parent_instance;
|
||||||
|
|
||||||
|
GtkWidget *header_bar;
|
||||||
|
GtkWidget *mode_stack;
|
||||||
|
GtkWidget *capture_button;
|
||||||
|
GtkWidget *capture_image;
|
||||||
|
GtkWidget *spinner;
|
||||||
|
GtkWidget *instructions;
|
||||||
|
|
||||||
|
struct fp_dscv_dev *ddev;
|
||||||
|
struct fp_dev *dev;
|
||||||
|
|
||||||
|
struct fp_img *img;
|
||||||
|
ImageDisplayFlags img_flags;
|
||||||
|
} LibfprintDemoWindow;
|
||||||
|
|
||||||
|
typedef GtkApplicationWindowClass LibfprintDemoWindowClass;
|
||||||
|
|
||||||
|
G_DEFINE_TYPE (LibfprintDemoWindow, libfprint_demo_window, GTK_TYPE_APPLICATION_WINDOW)
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
EMPTY_MODE,
|
||||||
|
NOIMAGING_MODE,
|
||||||
|
CAPTURE_MODE,
|
||||||
|
SPINNER_MODE,
|
||||||
|
ERROR_MODE
|
||||||
|
} LibfprintDemoMode;
|
||||||
|
|
||||||
|
static void libfprint_demo_set_mode (LibfprintDemoWindow *win,
|
||||||
|
LibfprintDemoMode mode);
|
||||||
|
|
||||||
|
static void
|
||||||
|
pixbuf_destroy (guchar *pixels, gpointer data)
|
||||||
|
{
|
||||||
|
if (pixels == NULL)
|
||||||
|
return;
|
||||||
|
g_free (pixels);
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned char *
|
||||||
|
img_to_rgbdata (struct fp_img *img,
|
||||||
|
int width,
|
||||||
|
int height)
|
||||||
|
{
|
||||||
|
int size = width * height;
|
||||||
|
unsigned char *imgdata = fp_img_get_data (img);
|
||||||
|
unsigned char *rgbdata = g_malloc (size * 3);
|
||||||
|
size_t i;
|
||||||
|
size_t rgb_offset = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < size; i++) {
|
||||||
|
unsigned char pixel = imgdata[i];
|
||||||
|
|
||||||
|
rgbdata[rgb_offset++] = pixel;
|
||||||
|
rgbdata[rgb_offset++] = pixel;
|
||||||
|
rgbdata[rgb_offset++] = pixel;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rgbdata;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
plot_minutiae (unsigned char *rgbdata,
|
||||||
|
int width,
|
||||||
|
int height,
|
||||||
|
struct fp_minutia **minlist,
|
||||||
|
int nr_minutiae)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
#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 < nr_minutiae; i++) {
|
||||||
|
struct fp_minutia *min = minlist[i];
|
||||||
|
int x, y;
|
||||||
|
size_t pixel_offset;
|
||||||
|
|
||||||
|
fp_minutia_get_coords(min, &x, &y);
|
||||||
|
pixel_offset = (y * width) + x;
|
||||||
|
write_pixel(pixel_offset - 2);
|
||||||
|
write_pixel(pixel_offset - 1);
|
||||||
|
write_pixel(pixel_offset);
|
||||||
|
write_pixel(pixel_offset + 1);
|
||||||
|
write_pixel(pixel_offset + 2);
|
||||||
|
|
||||||
|
write_pixel(pixel_offset - (width * 2));
|
||||||
|
write_pixel(pixel_offset - (width * 1) - 1);
|
||||||
|
write_pixel(pixel_offset - (width * 1));
|
||||||
|
write_pixel(pixel_offset - (width * 1) + 1);
|
||||||
|
write_pixel(pixel_offset + (width * 1) - 1);
|
||||||
|
write_pixel(pixel_offset + (width * 1));
|
||||||
|
write_pixel(pixel_offset + (width * 1) + 1);
|
||||||
|
write_pixel(pixel_offset + (width * 2));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static GdkPixbuf *
|
||||||
|
img_to_pixbuf (struct fp_img *img,
|
||||||
|
ImageDisplayFlags flags)
|
||||||
|
{
|
||||||
|
int width;
|
||||||
|
int height;
|
||||||
|
unsigned char *rgbdata;
|
||||||
|
|
||||||
|
width = fp_img_get_width (img);
|
||||||
|
height = fp_img_get_height (img);
|
||||||
|
|
||||||
|
if (flags & IMAGE_DISPLAY_BINARY) {
|
||||||
|
struct fp_img *binary;
|
||||||
|
binary = fp_img_binarize (img);
|
||||||
|
rgbdata = img_to_rgbdata (binary, width, height);
|
||||||
|
fp_img_free (binary);
|
||||||
|
} else {
|
||||||
|
rgbdata = img_to_rgbdata (img, width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags & IMAGE_DISPLAY_MINUTIAE) {
|
||||||
|
struct fp_minutia **minlist;
|
||||||
|
int nr_minutiae;
|
||||||
|
|
||||||
|
minlist = fp_img_get_minutiae (img, &nr_minutiae);
|
||||||
|
plot_minutiae (rgbdata, width, height, minlist, nr_minutiae);
|
||||||
|
}
|
||||||
|
|
||||||
|
return gdk_pixbuf_new_from_data (rgbdata, GDK_COLORSPACE_RGB,
|
||||||
|
FALSE, 8, width, height,
|
||||||
|
width * 3, pixbuf_destroy,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
update_image (LibfprintDemoWindow *win)
|
||||||
|
{
|
||||||
|
GdkPixbuf *pixbuf;
|
||||||
|
|
||||||
|
if (win->img == NULL) {
|
||||||
|
gtk_image_clear (GTK_IMAGE (win->capture_image));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_debug ("Updating image, minutiae %s, binary mode %s",
|
||||||
|
win->img_flags & IMAGE_DISPLAY_MINUTIAE ? "shown" : "hidden",
|
||||||
|
win->img_flags & IMAGE_DISPLAY_BINARY ? "on" : "off");
|
||||||
|
pixbuf = img_to_pixbuf (win->img, win->img_flags);
|
||||||
|
gtk_image_set_from_pixbuf (GTK_IMAGE (win->capture_image), pixbuf);
|
||||||
|
g_object_unref (pixbuf);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
libfprint_demo_set_spinner_label (LibfprintDemoWindow *win,
|
||||||
|
const char *message)
|
||||||
|
{
|
||||||
|
char *label;
|
||||||
|
|
||||||
|
label = g_strdup_printf ("<b><span size=\"large\">%s</span></b>", message);
|
||||||
|
gtk_label_set_markup (GTK_LABEL (win->instructions), label);
|
||||||
|
g_free (label);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
libfprint_demo_set_capture_label (LibfprintDemoWindow *win)
|
||||||
|
{
|
||||||
|
struct fp_driver *drv;
|
||||||
|
enum fp_scan_type scan_type;
|
||||||
|
const char *message;
|
||||||
|
|
||||||
|
drv = fp_dscv_dev_get_driver (win->ddev);
|
||||||
|
scan_type = fp_driver_get_scan_type(drv);
|
||||||
|
|
||||||
|
switch (scan_type) {
|
||||||
|
case FP_SCAN_TYPE_PRESS:
|
||||||
|
message = "Place your finger on the fingerprint reader";
|
||||||
|
break;
|
||||||
|
case FP_SCAN_TYPE_SWIPE:
|
||||||
|
message = "Swipe your finger across the fingerprint reader";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
g_assert_not_reached ();
|
||||||
|
}
|
||||||
|
|
||||||
|
libfprint_demo_set_spinner_label (win, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
dev_capture_start_cb (struct fp_dev *dev,
|
||||||
|
int result,
|
||||||
|
struct fp_img *img,
|
||||||
|
void *user_data)
|
||||||
|
{
|
||||||
|
LibfprintDemoWindow *win = user_data;
|
||||||
|
|
||||||
|
if (result < 0) {
|
||||||
|
libfprint_demo_set_mode (win, ERROR_MODE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
fp_async_capture_stop (dev, NULL, NULL);
|
||||||
|
|
||||||
|
win->img = img;
|
||||||
|
update_image (win);
|
||||||
|
|
||||||
|
libfprint_demo_set_mode (win, CAPTURE_MODE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
dev_open_cb (struct fp_dev *dev, int status, void *user_data)
|
||||||
|
{
|
||||||
|
LibfprintDemoWindow *win = user_data;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
if (status < 0) {
|
||||||
|
libfprint_demo_set_mode (win, ERROR_MODE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
libfprint_demo_set_capture_label (win);
|
||||||
|
|
||||||
|
win->dev = dev;
|
||||||
|
r = fp_async_capture_start (win->dev, FALSE, dev_capture_start_cb, user_data);
|
||||||
|
if (r < 0) {
|
||||||
|
g_warning ("fp_async_capture_start failed: %d", r);
|
||||||
|
libfprint_demo_set_mode (win, ERROR_MODE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
activate_capture (GSimpleAction *action,
|
||||||
|
GVariant *parameter,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
LibfprintDemoWindow *win = user_data;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
libfprint_demo_set_mode (win, SPINNER_MODE);
|
||||||
|
g_clear_pointer (&win->img, fp_img_free);
|
||||||
|
|
||||||
|
if (win->dev != NULL) {
|
||||||
|
dev_open_cb (win->dev, 0, user_data);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
libfprint_demo_set_spinner_label (win, "Opening fingerprint reader");
|
||||||
|
|
||||||
|
r = fp_async_dev_open (win->ddev, dev_open_cb, user_data);
|
||||||
|
if (r < 0) {
|
||||||
|
g_warning ("fp_async_dev_open failed: %d", r);
|
||||||
|
libfprint_demo_set_mode (win, ERROR_MODE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
activate_quit (GSimpleAction *action,
|
||||||
|
GVariant *parameter,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
GtkApplication *app = user_data;
|
||||||
|
GtkWidget *win;
|
||||||
|
GList *list, *next;
|
||||||
|
|
||||||
|
list = gtk_application_get_windows (app);
|
||||||
|
while (list)
|
||||||
|
{
|
||||||
|
win = list->data;
|
||||||
|
next = list->next;
|
||||||
|
|
||||||
|
gtk_widget_destroy (GTK_WIDGET (win));
|
||||||
|
|
||||||
|
list = next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
activate_show_minutiae (GSimpleAction *action,
|
||||||
|
GVariant *parameter,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
LibfprintDemoWindow *win = user_data;
|
||||||
|
GVariant *state;
|
||||||
|
gboolean new_state;
|
||||||
|
|
||||||
|
state = g_action_get_state (G_ACTION (action));
|
||||||
|
new_state = !g_variant_get_boolean (state);
|
||||||
|
g_action_change_state (G_ACTION (action), g_variant_new_boolean (new_state));
|
||||||
|
g_variant_unref (state);
|
||||||
|
|
||||||
|
if (new_state)
|
||||||
|
win->img_flags |= IMAGE_DISPLAY_MINUTIAE;
|
||||||
|
else
|
||||||
|
win->img_flags &= ~IMAGE_DISPLAY_MINUTIAE;
|
||||||
|
|
||||||
|
update_image (win);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
activate_show_binary (GSimpleAction *action,
|
||||||
|
GVariant *parameter,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
LibfprintDemoWindow *win = user_data;
|
||||||
|
GVariant *state;
|
||||||
|
gboolean new_state;
|
||||||
|
|
||||||
|
state = g_action_get_state (G_ACTION (action));
|
||||||
|
new_state = !g_variant_get_boolean (state);
|
||||||
|
g_action_change_state (G_ACTION (action), g_variant_new_boolean (new_state));
|
||||||
|
g_variant_unref (state);
|
||||||
|
|
||||||
|
if (new_state)
|
||||||
|
win->img_flags |= IMAGE_DISPLAY_BINARY;
|
||||||
|
else
|
||||||
|
win->img_flags &= ~IMAGE_DISPLAY_BINARY;
|
||||||
|
|
||||||
|
update_image (win);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
change_show_minutiae_state (GSimpleAction *action,
|
||||||
|
GVariant *state,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
g_simple_action_set_state (action, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
change_show_binary_state (GSimpleAction *action,
|
||||||
|
GVariant *state,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
g_simple_action_set_state (action, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
static GActionEntry app_entries[] = {
|
||||||
|
{ "quit", activate_quit, NULL, NULL, NULL },
|
||||||
|
};
|
||||||
|
|
||||||
|
static GActionEntry win_entries[] = {
|
||||||
|
{ "show-minutiae", activate_show_minutiae, NULL, "false", change_show_minutiae_state },
|
||||||
|
{ "show-binary", activate_show_binary, NULL, "false", change_show_binary_state },
|
||||||
|
{ "capture", activate_capture, NULL, NULL, NULL }
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
activate (GApplication *app)
|
||||||
|
{
|
||||||
|
LibfprintDemoWindow *window;
|
||||||
|
|
||||||
|
window = g_object_new (libfprint_demo_window_get_type (),
|
||||||
|
"application", app,
|
||||||
|
NULL);
|
||||||
|
gtk_widget_show (GTK_WIDGET (window));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
libfprint_demo_set_mode (LibfprintDemoWindow *win,
|
||||||
|
LibfprintDemoMode mode)
|
||||||
|
{
|
||||||
|
struct fp_driver *drv;
|
||||||
|
char *title;
|
||||||
|
|
||||||
|
switch (mode) {
|
||||||
|
case EMPTY_MODE:
|
||||||
|
gtk_stack_set_visible_child_name (GTK_STACK (win->mode_stack), "empty-mode");
|
||||||
|
gtk_widget_set_sensitive (win->capture_button, FALSE);
|
||||||
|
gtk_spinner_stop (GTK_SPINNER (win->spinner));
|
||||||
|
break;
|
||||||
|
case NOIMAGING_MODE:
|
||||||
|
gtk_stack_set_visible_child_name (GTK_STACK (win->mode_stack), "noimaging-mode");
|
||||||
|
gtk_widget_set_sensitive (win->capture_button, FALSE);
|
||||||
|
gtk_spinner_stop (GTK_SPINNER (win->spinner));
|
||||||
|
break;
|
||||||
|
case CAPTURE_MODE:
|
||||||
|
gtk_stack_set_visible_child_name (GTK_STACK (win->mode_stack), "capture-mode");
|
||||||
|
gtk_widget_set_sensitive (win->capture_button, TRUE);
|
||||||
|
|
||||||
|
drv = fp_dscv_dev_get_driver (win->ddev);
|
||||||
|
title = g_strdup_printf ("%s Test", fp_driver_get_full_name (drv));
|
||||||
|
gtk_header_bar_set_title (GTK_HEADER_BAR (win->header_bar), title);
|
||||||
|
g_free (title);
|
||||||
|
|
||||||
|
gtk_spinner_stop (GTK_SPINNER (win->spinner));
|
||||||
|
break;
|
||||||
|
case SPINNER_MODE:
|
||||||
|
gtk_stack_set_visible_child_name (GTK_STACK (win->mode_stack), "spinner-mode");
|
||||||
|
gtk_widget_set_sensitive (win->capture_button, FALSE);
|
||||||
|
gtk_spinner_start (GTK_SPINNER (win->spinner));
|
||||||
|
break;
|
||||||
|
case ERROR_MODE:
|
||||||
|
gtk_stack_set_visible_child_name (GTK_STACK (win->mode_stack), "error-mode");
|
||||||
|
gtk_widget_set_sensitive (win->capture_button, FALSE);
|
||||||
|
gtk_spinner_stop (GTK_SPINNER (win->spinner));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
g_assert_not_reached ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
libfprint_demo_init (LibfprintDemo *app)
|
||||||
|
{
|
||||||
|
g_action_map_add_action_entries (G_ACTION_MAP (app),
|
||||||
|
app_entries, G_N_ELEMENTS (app_entries),
|
||||||
|
app);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
libfprint_demo_class_init (LibfprintDemoClass *class)
|
||||||
|
{
|
||||||
|
GApplicationClass *app_class = G_APPLICATION_CLASS (class);
|
||||||
|
|
||||||
|
app_class->activate = activate;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
libfprint_demo_window_init (LibfprintDemoWindow *window)
|
||||||
|
{
|
||||||
|
struct fp_dscv_dev **discovered_devs;
|
||||||
|
|
||||||
|
gtk_widget_init_template (GTK_WIDGET (window));
|
||||||
|
gtk_window_set_default_size (GTK_WINDOW (window), 700, 500);
|
||||||
|
|
||||||
|
g_action_map_add_action_entries (G_ACTION_MAP (window),
|
||||||
|
win_entries, G_N_ELEMENTS (win_entries),
|
||||||
|
window);
|
||||||
|
|
||||||
|
if (fp_init () < 0) {
|
||||||
|
libfprint_demo_set_mode (window, ERROR_MODE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setup_pollfds ();
|
||||||
|
|
||||||
|
discovered_devs = fp_discover_devs();
|
||||||
|
if (!discovered_devs) {
|
||||||
|
libfprint_demo_set_mode (window, ERROR_MODE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Empty list? */
|
||||||
|
if (discovered_devs[0] == NULL) {
|
||||||
|
fp_dscv_devs_free (discovered_devs);
|
||||||
|
libfprint_demo_set_mode (window, EMPTY_MODE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!fp_driver_supports_imaging(fp_dscv_dev_get_driver(discovered_devs[0]))) {
|
||||||
|
libfprint_demo_set_mode (window, NOIMAGING_MODE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
window->ddev = discovered_devs[0];
|
||||||
|
libfprint_demo_set_mode (window, CAPTURE_MODE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
libfprint_demo_window_class_init (LibfprintDemoWindowClass *class)
|
||||||
|
{
|
||||||
|
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
|
||||||
|
|
||||||
|
gtk_widget_class_set_template_from_resource (widget_class, "/libfprint_demo/gtk-libfprint-test.ui");
|
||||||
|
gtk_widget_class_bind_template_child (widget_class, LibfprintDemoWindow, header_bar);
|
||||||
|
gtk_widget_class_bind_template_child (widget_class, LibfprintDemoWindow, mode_stack);
|
||||||
|
gtk_widget_class_bind_template_child (widget_class, LibfprintDemoWindow, capture_button);
|
||||||
|
gtk_widget_class_bind_template_child (widget_class, LibfprintDemoWindow, capture_image);
|
||||||
|
gtk_widget_class_bind_template_child (widget_class, LibfprintDemoWindow, spinner);
|
||||||
|
gtk_widget_class_bind_template_child (widget_class, LibfprintDemoWindow, instructions);
|
||||||
|
|
||||||
|
//FIXME setup dispose
|
||||||
|
}
|
||||||
|
|
||||||
|
int main (int argc, char **argv)
|
||||||
|
{
|
||||||
|
GtkApplication *app;
|
||||||
|
|
||||||
|
app = GTK_APPLICATION (g_object_new (libfprint_demo_get_type (),
|
||||||
|
"application-id", "org.freedesktop.libfprint.Demo",
|
||||||
|
"flags", G_APPLICATION_FLAGS_NONE,
|
||||||
|
NULL));
|
||||||
|
|
||||||
|
return g_application_run (G_APPLICATION (app), 0, NULL);
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<gresources>
|
||||||
|
<gresource prefix="/libfprint_demo">
|
||||||
|
<file>gtk-libfprint-test.ui</file>
|
||||||
|
</gresource>
|
||||||
|
</gresources>
|
||||||
@@ -0,0 +1,351 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!-- Generated with glade 3.22.1 -->
|
||||||
|
<interface>
|
||||||
|
<requires lib="gtk+" version="3.20"/>
|
||||||
|
<template class="LibfprintDemoWindow" parent="GtkApplicationWindow">
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="default_width">500</property>
|
||||||
|
<property name="default_height">400</property>
|
||||||
|
<property name="show_menubar">False</property>
|
||||||
|
<child type="titlebar">
|
||||||
|
<object class="GtkHeaderBar" id="header_bar">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="title">Fingerprint Reader Test</property>
|
||||||
|
<property name="subtitle">Capture test</property>
|
||||||
|
<property name="show_close_button">True</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkMenuButton" id="option-menu-button">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="sensitive">False</property>
|
||||||
|
<property name="can_focus">True</property>
|
||||||
|
<property name="receives_default">False</property>
|
||||||
|
<property name="valign">center</property>
|
||||||
|
<property name="menu-model">options-menu</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkImage">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="icon_name">open-menu-symbolic</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="pack_type">end</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkButton" id="capture_button">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="sensitive">False</property>
|
||||||
|
<property name="can_focus">True</property>
|
||||||
|
<property name="receives_default">False</property>
|
||||||
|
<property name="valign">center</property>
|
||||||
|
<property name="action_name">win.capture</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkLabel" id="capture_label">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="label" translatable="yes">_Capture</property>
|
||||||
|
<property name="use_underline">True</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<style>
|
||||||
|
<class name="text-button"/>
|
||||||
|
</style>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="pack_type">end</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkStack" id="mode_stack">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkGrid" id="spinner-mode">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="halign">center</property>
|
||||||
|
<property name="valign">center</property>
|
||||||
|
<property name="hexpand">True</property>
|
||||||
|
<property name="vexpand">True</property>
|
||||||
|
<property name="orientation">vertical</property>
|
||||||
|
<property name="row_spacing">12</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkSpinner" id="spinner">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="margin_bottom">9</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="left_attach">1</property>
|
||||||
|
<property name="top_attach">0</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkLabel" id="instructions">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="margin_top">9</property>
|
||||||
|
<property name="label" translatable="yes"><b><span size="large">Please press finger on reader</span></b></property>
|
||||||
|
<property name="use_markup">True</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="left_attach">1</property>
|
||||||
|
<property name="top_attach">1</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<placeholder/>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<placeholder/>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<placeholder/>
|
||||||
|
</child>
|
||||||
|
<style>
|
||||||
|
<class name="dim-label"/>
|
||||||
|
</style>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="name">spinner-mode</property>
|
||||||
|
<property name="title">spinner-mode</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkGrid" id="empty-mode">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="halign">center</property>
|
||||||
|
<property name="valign">center</property>
|
||||||
|
<property name="hexpand">True</property>
|
||||||
|
<property name="vexpand">True</property>
|
||||||
|
<property name="orientation">vertical</property>
|
||||||
|
<property name="row_spacing">12</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkImage">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="margin_bottom">9</property>
|
||||||
|
<property name="pixel_size">192</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="left_attach">1</property>
|
||||||
|
<property name="top_attach">0</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkLabel">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="margin_top">9</property>
|
||||||
|
<property name="label" translatable="yes"><b><span size="large">No fingerprint readers found</span></b></property>
|
||||||
|
<property name="use_markup">True</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="left_attach">1</property>
|
||||||
|
<property name="top_attach">1</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkLabel">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="label" translatable="yes">Please connect a supported fingerprint reader and start the application again</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="left_attach">1</property>
|
||||||
|
<property name="top_attach">2</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<placeholder/>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<placeholder/>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<placeholder/>
|
||||||
|
</child>
|
||||||
|
<style>
|
||||||
|
<class name="dim-label"/>
|
||||||
|
</style>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="name">empty-mode</property>
|
||||||
|
<property name="title">empty-mode</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkAspectFrame" id="capture-mode">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="label_xalign">0</property>
|
||||||
|
<property name="shadow_type">none</property>
|
||||||
|
<property name="ratio">1.2999999523162842</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkImage" id="capture_image">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="name">capture-mode</property>
|
||||||
|
<property name="title">capture-mode</property>
|
||||||
|
<property name="position">1</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkGrid" id="error-mode">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="halign">center</property>
|
||||||
|
<property name="valign">center</property>
|
||||||
|
<property name="hexpand">True</property>
|
||||||
|
<property name="vexpand">True</property>
|
||||||
|
<property name="orientation">vertical</property>
|
||||||
|
<property name="row_spacing">12</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkImage">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="margin_bottom">9</property>
|
||||||
|
<property name="pixel_size">192</property>
|
||||||
|
<property name="icon_name">dialog-warning-symbolic</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="left_attach">1</property>
|
||||||
|
<property name="top_attach">0</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkLabel">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="margin_top">9</property>
|
||||||
|
<property name="label" translatable="yes"><b><span size="large">An error occurred trying to access the fingerprint reader</span></b></property>
|
||||||
|
<property name="use_markup">True</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="left_attach">1</property>
|
||||||
|
<property name="top_attach">1</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkLabel">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="label" translatable="yes">Please consult the debugging output before restarting the application</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="left_attach">1</property>
|
||||||
|
<property name="top_attach">2</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<placeholder/>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<placeholder/>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<placeholder/>
|
||||||
|
</child>
|
||||||
|
<style>
|
||||||
|
<class name="dim-label"/>
|
||||||
|
</style>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="name">error-mode</property>
|
||||||
|
<property name="title">error-mode</property>
|
||||||
|
<property name="position">2</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkGrid" id="noimaging-mode">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="halign">center</property>
|
||||||
|
<property name="valign">center</property>
|
||||||
|
<property name="hexpand">True</property>
|
||||||
|
<property name="vexpand">True</property>
|
||||||
|
<property name="orientation">vertical</property>
|
||||||
|
<property name="row_spacing">12</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkImage">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="margin_bottom">9</property>
|
||||||
|
<property name="pixel_size">192</property>
|
||||||
|
<property name="icon_name">scanner-symbolic</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="left_attach">1</property>
|
||||||
|
<property name="top_attach">0</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkLabel">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="margin_top">9</property>
|
||||||
|
<property name="label" translatable="yes"><b><span size="large">Fingerprint reader does not support capturing images</span></b></property>
|
||||||
|
<property name="use_markup">True</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="left_attach">1</property>
|
||||||
|
<property name="top_attach">1</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkLabel">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="label" translatable="yes">Please connect a supported fingerprint reader and start the application again</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="left_attach">1</property>
|
||||||
|
<property name="top_attach">2</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<placeholder/>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<placeholder/>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<placeholder/>
|
||||||
|
</child>
|
||||||
|
<style>
|
||||||
|
<class name="dim-label"/>
|
||||||
|
</style>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="name">noimaging-mode</property>
|
||||||
|
<property name="title">noimaging-mode</property>
|
||||||
|
<property name="position">3</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<menu id="options-menu">
|
||||||
|
<section>
|
||||||
|
<item>
|
||||||
|
<attribute name="label" translatable="yes">Show Minutiae</attribute>
|
||||||
|
<attribute name="action">win.show-minutiae</attribute>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<attribute name="label" translatable="yes">Show Binary</attribute>
|
||||||
|
<attribute name="action">win.show-binary</attribute>
|
||||||
|
</item>
|
||||||
|
</section>
|
||||||
|
</menu>
|
||||||
|
</interface>
|
||||||
+196
@@ -0,0 +1,196 @@
|
|||||||
|
/*
|
||||||
|
* fprint D-Bus daemon
|
||||||
|
* Copyright (C) 2008 Daniel Drake <dsd@gentoo.org>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program 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 General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
#include <libfprint/fprint.h>
|
||||||
|
|
||||||
|
#include <poll.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "loop.h"
|
||||||
|
|
||||||
|
struct fdsource {
|
||||||
|
GSource source;
|
||||||
|
GSList *pollfds;
|
||||||
|
};
|
||||||
|
|
||||||
|
static gboolean source_prepare(GSource *source, gint *timeout)
|
||||||
|
{
|
||||||
|
int r;
|
||||||
|
struct timeval tv;
|
||||||
|
|
||||||
|
r = fp_get_next_timeout(&tv);
|
||||||
|
if (r == 0) {
|
||||||
|
*timeout = -1;
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!timerisset(&tv))
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
*timeout = (tv.tv_sec * 1000) + (tv.tv_usec / 1000);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean source_check(GSource *source)
|
||||||
|
{
|
||||||
|
struct fdsource *_fdsource = (struct fdsource *) source;
|
||||||
|
GSList *l;
|
||||||
|
struct timeval tv;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
if (!_fdsource->pollfds)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
for (l = _fdsource->pollfds; l != NULL; l = l->next) {
|
||||||
|
GPollFD *pollfd = l->data;
|
||||||
|
|
||||||
|
if (pollfd->revents)
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = fp_get_next_timeout(&tv);
|
||||||
|
if (r == 1 && !timerisset(&tv))
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean source_dispatch(GSource *source, GSourceFunc callback,
|
||||||
|
gpointer data)
|
||||||
|
{
|
||||||
|
struct timeval zerotimeout = {
|
||||||
|
.tv_sec = 0,
|
||||||
|
.tv_usec = 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* FIXME error handling */
|
||||||
|
fp_handle_events_timeout(&zerotimeout);
|
||||||
|
|
||||||
|
/* FIXME whats the return value used for? */
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void source_finalize(GSource *source)
|
||||||
|
{
|
||||||
|
struct fdsource *_fdsource = (struct fdsource *) source;
|
||||||
|
GSList *l;
|
||||||
|
|
||||||
|
if (!_fdsource->pollfds)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (l = _fdsource->pollfds; l != NULL; l = l->next) {
|
||||||
|
GPollFD *pollfd = l->data;
|
||||||
|
|
||||||
|
g_source_remove_poll((GSource *) _fdsource, pollfd);
|
||||||
|
g_slice_free(GPollFD, pollfd);
|
||||||
|
_fdsource->pollfds = g_slist_delete_link(_fdsource->pollfds, l);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_slist_free(_fdsource->pollfds);
|
||||||
|
}
|
||||||
|
|
||||||
|
static GSourceFuncs sourcefuncs = {
|
||||||
|
.prepare = source_prepare,
|
||||||
|
.check = source_check,
|
||||||
|
.dispatch = source_dispatch,
|
||||||
|
.finalize = source_finalize,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct fdsource *fdsource = NULL;
|
||||||
|
|
||||||
|
static void pollfd_add(int fd, short events)
|
||||||
|
{
|
||||||
|
GPollFD *pollfd;
|
||||||
|
|
||||||
|
pollfd = g_slice_new(GPollFD);
|
||||||
|
pollfd->fd = fd;
|
||||||
|
pollfd->events = 0;
|
||||||
|
pollfd->revents = 0;
|
||||||
|
if (events & POLLIN)
|
||||||
|
pollfd->events |= G_IO_IN;
|
||||||
|
if (events & POLLOUT)
|
||||||
|
pollfd->events |= G_IO_OUT;
|
||||||
|
|
||||||
|
fdsource->pollfds = g_slist_prepend(fdsource->pollfds, pollfd);
|
||||||
|
g_source_add_poll((GSource *) fdsource, pollfd);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void pollfd_added_cb(int fd, short events)
|
||||||
|
{
|
||||||
|
g_debug("now monitoring fd %d", fd);
|
||||||
|
pollfd_add(fd, events);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void pollfd_removed_cb(int fd)
|
||||||
|
{
|
||||||
|
GSList *l;
|
||||||
|
|
||||||
|
g_debug("no longer monitoring fd %d", fd);
|
||||||
|
|
||||||
|
if (!fdsource->pollfds) {
|
||||||
|
g_debug("cannot remove from list as list is empty?");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (l = fdsource->pollfds; l != NULL; l = l->next) {
|
||||||
|
GPollFD *pollfd = l->data;
|
||||||
|
|
||||||
|
if (pollfd->fd != fd)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
g_source_remove_poll((GSource *) fdsource, pollfd);
|
||||||
|
g_slice_free(GPollFD, pollfd);
|
||||||
|
fdsource->pollfds = g_slist_delete_link(fdsource->pollfds, l);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_error("couldn't find fd %d in list\n", fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
int setup_pollfds(void)
|
||||||
|
{
|
||||||
|
ssize_t numfds;
|
||||||
|
size_t i;
|
||||||
|
struct fp_pollfd *fpfds;
|
||||||
|
GSource *gsource;
|
||||||
|
|
||||||
|
gsource = g_source_new(&sourcefuncs, sizeof(struct fdsource));
|
||||||
|
fdsource = (struct fdsource *) gsource;
|
||||||
|
fdsource->pollfds = NULL;
|
||||||
|
|
||||||
|
numfds = fp_get_pollfds(&fpfds);
|
||||||
|
if (numfds < 0) {
|
||||||
|
if (fpfds)
|
||||||
|
free(fpfds);
|
||||||
|
return (int) numfds;
|
||||||
|
} else if (numfds > 0) {
|
||||||
|
for (i = 0; i < numfds; i++) {
|
||||||
|
struct fp_pollfd *fpfd = &fpfds[i];
|
||||||
|
pollfd_add(fpfd->fd, fpfd->events);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
free(fpfds);
|
||||||
|
fp_set_pollfd_notifiers(pollfd_added_cb, pollfd_removed_cb);
|
||||||
|
g_source_attach(gsource, NULL);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
+27
@@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2008 Daniel Drake <dsd@gentoo.org>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program 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 General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef POLL_H
|
||||||
|
|
||||||
|
#define POLL_H
|
||||||
|
|
||||||
|
int setup_pollfds(void);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
gtk_test_resources = gnome.compile_resources('gtk-test-resources', 'gtk-libfprint-test.gresource.xml',
|
||||||
|
source_dir : '.',
|
||||||
|
c_name : 'gtk_test')
|
||||||
|
|
||||||
|
prefix = get_option('prefix')
|
||||||
|
bindir = join_paths(prefix, get_option('bindir'))
|
||||||
|
datadir = join_paths(prefix, get_option('datadir'))
|
||||||
|
|
||||||
|
executable('gtk-libfprint-test',
|
||||||
|
[ 'gtk-libfprint-test.c', 'loop.c', 'loop.h', gtk_test_resources ],
|
||||||
|
dependencies: [ libfprint_dep, gtk_dep ],
|
||||||
|
include_directories: [
|
||||||
|
root_inc,
|
||||||
|
],
|
||||||
|
c_args: [ common_cflags,
|
||||||
|
'-DPACKAGE_VERSION="' + meson.project_version() + '"' ],
|
||||||
|
install: true,
|
||||||
|
install_dir: bindir)
|
||||||
|
|
||||||
|
appdata = 'org.freedesktop.libfprint.Demo.appdata.xml'
|
||||||
|
install_data(appdata,
|
||||||
|
install_dir: join_paths(datadir, 'metainfo'))
|
||||||
|
|
||||||
|
desktop = 'org.freedesktop.libfprint.Demo.desktop'
|
||||||
|
install_data(desktop,
|
||||||
|
install_dir: join_paths(datadir, 'applications'))
|
||||||
|
|
||||||
|
icon = 'org.freedesktop.libfprint.Demo.png'
|
||||||
|
install_data(icon,
|
||||||
|
install_dir: join_paths(datadir, 'icons'))
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<component type="desktop">
|
||||||
|
<id>org.freedesktop.libfprint.Demo.desktop</id>
|
||||||
|
<name>Fingerprint Reader Demo</name>
|
||||||
|
<summary>Test fingerprint readers</summary>
|
||||||
|
<metadata_license>CC0-1.0</metadata_license>
|
||||||
|
<project_license>LGPL-2.1+</project_license>
|
||||||
|
<description>
|
||||||
|
<p>
|
||||||
|
Fingerprint Reader Demo is a test application for the libfprint
|
||||||
|
fingerprint reader library. Its purpose is to test drivers, new and old,
|
||||||
|
in a sandbox, to make sure that the drivers and associated functions
|
||||||
|
work correctly.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Fingerprint Reader Demo does not modify the system, or replace integration
|
||||||
|
in desktop environments.
|
||||||
|
</p>
|
||||||
|
</description>
|
||||||
|
<url type="homepage">https://fprint.freedesktop.org</url>
|
||||||
|
<screenshots>
|
||||||
|
<screenshot type="default" width="1024" height="576">https://git.gnome.org/browse/totem/plain/data/appdata/ss-main.png</screenshot>
|
||||||
|
<screenshot width="1024" height="576">https://git.gnome.org/browse/totem/plain/data/appdata/ss-music-playlist.png</screenshot>
|
||||||
|
</screenshots>
|
||||||
|
<updatecontact>hadess@hadess.net</updatecontact>
|
||||||
|
<!-- Incorrect, but appstream-util won't validate without it -->
|
||||||
|
<translation type="gettext">libfprint</translation>
|
||||||
|
</component>
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
[Desktop Entry]
|
||||||
|
Name=Fingerprint Reader Demo
|
||||||
|
Comment=Test fingerprint readers
|
||||||
|
Keywords=finger;print;fingerprint;fprint;demo;driver;reader;
|
||||||
|
Exec=gtk-libfprint-test
|
||||||
|
Icon=org.freedesktop.libfprint.Demo
|
||||||
|
Terminal=false
|
||||||
|
Type=Application
|
||||||
|
Categories=GTK;GNOME;Development;System;
|
||||||
|
StartupNotify=true
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
{
|
||||||
|
"app-id": "org.freedesktop.libfprint.Demo",
|
||||||
|
"runtime": "org.gnome.Platform",
|
||||||
|
"runtime-version": "master",
|
||||||
|
"sdk": "org.gnome.Sdk",
|
||||||
|
"command": "gtk-libfprint-test",
|
||||||
|
"finish-args": [
|
||||||
|
/* X11 + XShm access */
|
||||||
|
"--share=ipc", "--socket=x11",
|
||||||
|
/* Wayland access */
|
||||||
|
"--socket=wayland",
|
||||||
|
/* OpenGL access */
|
||||||
|
"--device=dri",
|
||||||
|
/* USB access */
|
||||||
|
"--device=all"
|
||||||
|
],
|
||||||
|
"cleanup": [ "/include", "/lib/pkgconfig/" ],
|
||||||
|
"modules": [
|
||||||
|
{
|
||||||
|
"name": "libusb",
|
||||||
|
"config-opts": [ "--disable-static", "--disable-udev" ],
|
||||||
|
"cleanup": [
|
||||||
|
"/lib/*.la",
|
||||||
|
"/lib/pkgconfig",
|
||||||
|
"/include"
|
||||||
|
],
|
||||||
|
"sources": [
|
||||||
|
{
|
||||||
|
"type": "archive",
|
||||||
|
"url": "https://github.com/libusb/libusb/archive/v1.0.22.tar.gz",
|
||||||
|
"sha256": "3500f7b182750cd9ccf9be8b1df998f83df56a39ab264976bdb3307773e16f48"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"post-install": [
|
||||||
|
"install -Dm644 COPYING /app/share/licenses/libusb/COPYING"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "libfprint",
|
||||||
|
"buildsystem": "meson",
|
||||||
|
"config-opts": [ "-Dudev_rules=false", "-Dx11-examples=false", "-Dgtk-examples=true" ],
|
||||||
|
"sources": [
|
||||||
|
{
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://gitlab.freedesktop.org/libfprint/libfprint.git",
|
||||||
|
"branch": "wip/hadess/gtk-example"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 24 KiB |
@@ -1,10 +0,0 @@
|
|||||||
EXTRA_DIST = doxygen.cfg
|
|
||||||
|
|
||||||
docs: doxygen.cfg
|
|
||||||
doxygen $^
|
|
||||||
|
|
||||||
docs-upload: docs
|
|
||||||
ln -s html api
|
|
||||||
ncftpput -f ~/.ncftp/reactivated -m -R httpdocs/fprint api/
|
|
||||||
rm -f api
|
|
||||||
|
|
||||||
@@ -0,0 +1,115 @@
|
|||||||
|
<?xml version="1.0"?>
|
||||||
|
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
|
||||||
|
"http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd" [
|
||||||
|
]>
|
||||||
|
<chapter id="advanced-topics" xmlns:xi="http://www.w3.org/2003/XInclude">
|
||||||
|
<title>Advanced Topics</title>
|
||||||
|
|
||||||
|
<refsect2 id="compatibility">
|
||||||
|
<title>Device and print compatibility</title>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
Moving off generic conceptual ideas and onto libfprint-specific
|
||||||
|
implementation details, here are some introductory notes regarding how
|
||||||
|
libfprint copes with compatibility of fingerprints.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
libfprint deals with a whole variety of different fingerprint readers and
|
||||||
|
the design includes considerations of compatibility and interoperability
|
||||||
|
between multiple devices. Your application should also be prepared to
|
||||||
|
work with more than one type of fingerprint reader and should consider that
|
||||||
|
enrolled fingerprint X may not be compatible with the device the user has
|
||||||
|
plugged in today.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
libfprint implements the principle that fingerprints from different devices
|
||||||
|
are not necessarily compatible. For example, different devices may see
|
||||||
|
significantly different areas of fingerprint surface, and comparing images
|
||||||
|
between the devices would be unreliable. Also, devices can stretch and
|
||||||
|
distort images in different ways.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
libfprint also implements the principle that in some cases, fingerprints
|
||||||
|
<emphasis>are</emphasis> compatible between different devices. If you go and buy two
|
||||||
|
identical fingerprint readers, it seems logical that you should be able
|
||||||
|
to enroll on one and verify on another without problems.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
libfprint takes a fairly simplistic approach to these issues. Internally,
|
||||||
|
fingerprint hardware is driven by individual drivers. libfprint enforces
|
||||||
|
that a fingerprint that came from a device backed by driver X is never
|
||||||
|
compared to a fingerprint that came from a device backed by driver Y.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
Additionally, libfprint is designed for the situation where a single driver
|
||||||
|
may support a range of devices which differ in imaging or scanning
|
||||||
|
properties. For example, a driver may support two ranges of devices which
|
||||||
|
even though are programmed over the same interface, one device sees
|
||||||
|
substantially less of the finger flesh, therefore images from the two
|
||||||
|
device types should be incompatible despite being from the same driver. To
|
||||||
|
implement this, each driver assigns a <emphasis>device type</emphasis> to each device
|
||||||
|
that it detects based on its imaging characteristics. libfprint ensures that
|
||||||
|
two prints being compared have the same device type.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
In summary, libfprint represents fingerprints in several internal structures
|
||||||
|
and each representation will offer you a way of determining the
|
||||||
|
<ulink url="#driver_id">driver ID</ulink> and <ulink url="#device-types">devtype</ulink> of the print in
|
||||||
|
question. Prints are only compatible if the driver ID <emphasis role="strong">and</emphasis> devtypes
|
||||||
|
match. libfprint does offer you some "is this print compatible?" helper
|
||||||
|
functions, so you don't have to worry about these details too much.
|
||||||
|
</para>
|
||||||
|
</refsect2>
|
||||||
|
|
||||||
|
<refsect2 id="driver_id">
|
||||||
|
<title>Driver IDs</title>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
Each driver is assigned a unique ID by the project maintainer. These
|
||||||
|
assignments are
|
||||||
|
<ulink url="https://gitlab.freedesktop.org/libfprint/libfprint/blob/master/libfprint/drivers/driver_ids.h">
|
||||||
|
documented in the sources</ulink> and will never change.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
The only reason you may be interested in retrieving the driver ID for a
|
||||||
|
driver is for the purpose of checking if some print data is compatible
|
||||||
|
with a device. libfprint uses the driver ID as one way of checking that
|
||||||
|
the print you are trying to verify is compatible with the device in
|
||||||
|
question - it ensures that enrollment data from one driver is never fed to
|
||||||
|
another. Note that libfprint does provide you with helper functions to
|
||||||
|
determine whether a print is compatible with a device, so under most
|
||||||
|
circumstances, you don't have to worry about driver IDs at all.
|
||||||
|
</para>
|
||||||
|
</refsect2>
|
||||||
|
|
||||||
|
<refsect2 id="device-types">
|
||||||
|
<title>Device types</title>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
Internally, the <ulink url="libfprint-Driver-operations.html#libfprint-Driver-operations.description">driver</ulink> behind a device assigns a 32-bit
|
||||||
|
<emphasis>devtype</emphasis> identifier to the device. This cannot be used as a unique
|
||||||
|
ID for a specific device as many devices under the same range may share
|
||||||
|
the same devtype. The devtype may even be 0 in all cases.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
The only reason you may be interested in retrieving the devtype for a
|
||||||
|
device is for the purpose of checking if some print data is compatible
|
||||||
|
with a device. libfprint uses the devtype as one way of checking that the
|
||||||
|
print you are verifying is compatible with the device in question - the
|
||||||
|
devtypes must be equal. This effectively allows drivers to support more
|
||||||
|
than one type of device where the data from each one is not compatible with
|
||||||
|
the other. Note that libfprint does provide you with helper functions to
|
||||||
|
determine whether a print is compatible with a device, so under most
|
||||||
|
circumstances, you don't have to worry about devtypes at all.
|
||||||
|
</para>
|
||||||
|
</refsect2>
|
||||||
|
|
||||||
|
</chapter>
|
||||||
-1294
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,30 @@
|
|||||||
|
<?xml version="1.0"?>
|
||||||
|
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
|
||||||
|
"http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd" [
|
||||||
|
]>
|
||||||
|
<chapter id="getting-started" xmlns:xi="http://www.w3.org/2003/XInclude">
|
||||||
|
<title>Getting Started</title>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
libfprint includes several simple functional examples under the <computeroutput>examples/</computeroutput>
|
||||||
|
directory in the libfprint source distribution. Those are good starting
|
||||||
|
points.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
Usually the first thing you want to do is determine which fingerprint
|
||||||
|
devices are present. This is done through <ulink url="libfprint-Device-discovery.html">device discovery</ulink>.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
Once you have found a device you would like to operate, you should open it.
|
||||||
|
Refer to <ulink url="libfprint-Devices-operations.html">device operations</ulink>. This section also details enrollment,
|
||||||
|
image capture, and verification.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
That should be enough to get you started, but do remember there are
|
||||||
|
documentation pages on other aspects of libfprint's API (see the modules
|
||||||
|
page).
|
||||||
|
</para>
|
||||||
|
</chapter>
|
||||||
+106
@@ -0,0 +1,106 @@
|
|||||||
|
<?xml version="1.0"?>
|
||||||
|
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
|
||||||
|
"http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd" [
|
||||||
|
]>
|
||||||
|
<chapter id="intro" xmlns:xi="http://www.w3.org/2003/XInclude">
|
||||||
|
<title>Introduction</title>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
libfprint is an open source library to provide access to fingerprint
|
||||||
|
scanning devices. For more info, see the
|
||||||
|
<ulink url="https://fprint.freedesktop.org/">libfprint project homepage</ulink>.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
This documentation is aimed at application developers who wish to integrate
|
||||||
|
fingerprint-related functionality into their software. libfprint has been
|
||||||
|
designed so that you only have to do this once – by integrating your
|
||||||
|
software with libfprint, you'll be supporting all the fingerprint readers
|
||||||
|
that we have got our hands on. As such, the API is rather general (and
|
||||||
|
therefore hopefully easy to comprehend!), and does its best to hide the
|
||||||
|
technical details that required to operate the hardware.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
This documentation is not aimed at developers wishing to develop and
|
||||||
|
contribute fingerprint device drivers to libfprint.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
Feedback on this API and its associated documentation is appreciated. Was
|
||||||
|
anything unclear? Does anything seem unreasonably complicated? Is anything
|
||||||
|
missing? Let us know on the
|
||||||
|
<ulink url="https://lists.freedesktop.org/mailman/listinfo/fprint">mailing list</ulink>.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<refsect2 id="enrollment">
|
||||||
|
<title>Enrollment</title>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
Before you dive into the API, it's worth introducing a couple of concepts.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
The process of enrolling a finger is where you effectively scan your
|
||||||
|
finger for the purposes of teaching the system what your finger looks like.
|
||||||
|
This means that you scan your fingerprint, then the system processes it and
|
||||||
|
stores some data about your fingerprint to refer to later.
|
||||||
|
</para>
|
||||||
|
</refsect2>
|
||||||
|
|
||||||
|
<refsect2 id="verification">
|
||||||
|
<title>Verification</title>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
Verification is what most people think of when they think about fingerprint
|
||||||
|
scanning. The process of verification is effectively performing a fresh
|
||||||
|
fingerprint scan, and then comparing that scan to a finger that was
|
||||||
|
previously enrolled.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
As an example scenario, verification can be used to implement what people
|
||||||
|
would picture as fingerprint login (i.e. fingerprint replaces password).
|
||||||
|
For example:
|
||||||
|
</para>
|
||||||
|
<itemizedlist mark='dot'>
|
||||||
|
<listitem>
|
||||||
|
I enroll my fingerprint through some software that trusts I am who I say
|
||||||
|
I am. This is a prerequisite before I can perform fingerprint-based
|
||||||
|
login for my account.
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
Some time later, I want to login to my computer. I enter my username,
|
||||||
|
but instead of prompting me for a password, it asks me to scan my finger.
|
||||||
|
I scan my finger.
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
The system compares the finger I just scanned to the one that was
|
||||||
|
enrolled earlier. If the system decides that the fingerprints match,
|
||||||
|
I am successfully logged in. Otherwise, the system informs me that I am
|
||||||
|
not authorised to login as that user.
|
||||||
|
</listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
</refsect2>
|
||||||
|
|
||||||
|
<refsect2 id="identification">
|
||||||
|
<title>Identification</title>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
Identification is the process of comparing a freshly scanned fingerprint
|
||||||
|
to a <emphasis>collection</emphasis> of previously enrolled fingerprints. For example,
|
||||||
|
imagine there are 100 people in an organisation, and they all have enrolled
|
||||||
|
their fingerprints. One user walks up to a fingerprint scanner and scans
|
||||||
|
their finger. With <emphasis>no other knowledge</emphasis> of who that user might be,
|
||||||
|
the system examines their fingerprint, looks in the database, and determines
|
||||||
|
that the user is user number #61.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
In other words, verification might be seen as a one-to-one fingerprint
|
||||||
|
comparison where you know the identity of the user that you wish to
|
||||||
|
authenticate, whereas identification is a one-to-many comparison where you
|
||||||
|
do not know the identity of the user that you wish to authenticate.
|
||||||
|
</para>
|
||||||
|
</refsect2>
|
||||||
|
</chapter>
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
<?xml version="1.0"?>
|
||||||
|
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
|
||||||
|
"http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd"
|
||||||
|
[
|
||||||
|
<!ENTITY % local.common.attrib "xmlns:xi CDATA #FIXED 'http://www.w3.org/2003/XInclude'">
|
||||||
|
]>
|
||||||
|
<book id="index">
|
||||||
|
<bookinfo>
|
||||||
|
<title>libfprint Reference Manual</title>
|
||||||
|
<releaseinfo>
|
||||||
|
<para>This document is the API reference for the libfprint library.</para>
|
||||||
|
<para>
|
||||||
|
The latest version of libfprint, as well as the latest version of
|
||||||
|
this API reference, is <ulink role="online-location" url="https://fprint.freedesktop.org/libfprint-dev/">available online</ulink>.
|
||||||
|
</para>
|
||||||
|
</releaseinfo>
|
||||||
|
</bookinfo>
|
||||||
|
|
||||||
|
<part>
|
||||||
|
<title>Library Overview</title>
|
||||||
|
<xi:include href="intro.xml"/>
|
||||||
|
<xi:include href="advanced-topics.xml"/>
|
||||||
|
<xi:include href="getting-started.xml"/>
|
||||||
|
</part>
|
||||||
|
|
||||||
|
<part>
|
||||||
|
<title>Library API Documentation</title>
|
||||||
|
<xi:include href="xml/events.xml"/>
|
||||||
|
<xi:include href="xml/discovery.xml"/>
|
||||||
|
|
||||||
|
<xi:include href="xml/drv.xml"/>
|
||||||
|
<xi:include href="xml/dev.xml"/>
|
||||||
|
<xi:include href="xml/print_data.xml"/>
|
||||||
|
<!-- FIXME https://bugs.freedesktop.org/show_bug.cgi?id=106550 -->
|
||||||
|
<xi:include href="xml/dscv_print.xml"/>
|
||||||
|
<xi:include href="xml/img.xml"/>
|
||||||
|
</part>
|
||||||
|
|
||||||
|
<part>
|
||||||
|
<title>Writing Drivers</title>
|
||||||
|
<chapter id="driver-helpers">
|
||||||
|
<title>Logging, and async machinery</title>
|
||||||
|
<xi:include href="xml/fpi-log.xml"/>
|
||||||
|
<xi:include href="xml/fpi-ssm.xml"/>
|
||||||
|
<xi:include href="xml/fpi-poll.xml"/>
|
||||||
|
</chapter>
|
||||||
|
|
||||||
|
<chapter id="driver-dev">
|
||||||
|
<title>Device and driver structures</title>
|
||||||
|
<xi:include href="xml/fpi-dev.xml"/>
|
||||||
|
<xi:include href="xml/fpi-dev-img.xml"/>
|
||||||
|
<xi:include href="xml/fpi-core.xml"/>
|
||||||
|
<xi:include href="xml/fpi-core-img.xml"/>
|
||||||
|
</chapter>
|
||||||
|
|
||||||
|
<chapter id="driver-img">
|
||||||
|
<title>Image manipulation</title>
|
||||||
|
<xi:include href="xml/fpi-img.xml"/>
|
||||||
|
<xi:include href="xml/fpi-assembling.xml"/>
|
||||||
|
</chapter>
|
||||||
|
|
||||||
|
<xi:include href="xml/fpi-usb.xml"/>
|
||||||
|
</part>
|
||||||
|
|
||||||
|
<index id="api-index">
|
||||||
|
<title>API Index</title>
|
||||||
|
<xi:include href="xml/api-index-full.xml"><xi:fallback /></xi:include>
|
||||||
|
</index>
|
||||||
|
<index id="deprecated-api-index" role="deprecated">
|
||||||
|
<title>Index of deprecated API</title>
|
||||||
|
<xi:include href="xml/api-index-deprecated.xml"><xi:fallback /></xi:include>
|
||||||
|
</index>
|
||||||
|
</book>
|
||||||
@@ -0,0 +1,271 @@
|
|||||||
|
|
||||||
|
<SECTION>
|
||||||
|
<INCLUDE>fprint.h</INCLUDE>
|
||||||
|
<FILE>events</FILE>
|
||||||
|
<TITLE>Initialisation and events handling</TITLE>
|
||||||
|
LIBFPRINT_DEPRECATED
|
||||||
|
fp_set_debug
|
||||||
|
fp_init
|
||||||
|
fp_exit
|
||||||
|
fp_pollfd
|
||||||
|
fp_handle_events_timeout
|
||||||
|
fp_handle_events
|
||||||
|
fp_get_next_timeout
|
||||||
|
fp_get_pollfds
|
||||||
|
fp_pollfd_added_cb
|
||||||
|
fp_pollfd_removed_cb
|
||||||
|
fp_set_pollfd_notifiers
|
||||||
|
</SECTION>
|
||||||
|
|
||||||
|
<SECTION>
|
||||||
|
<INCLUDE>fprint.h</INCLUDE>
|
||||||
|
<FILE>discovery</FILE>
|
||||||
|
<TITLE>Device discovery</TITLE>
|
||||||
|
fp_dscv_dev
|
||||||
|
fp_discover_devs
|
||||||
|
fp_dscv_devs_free
|
||||||
|
fp_dscv_dev_get_driver
|
||||||
|
fp_dscv_dev_get_devtype
|
||||||
|
fp_dscv_dev_get_driver_id
|
||||||
|
fp_dscv_dev_supports_print_data
|
||||||
|
fp_dscv_dev_supports_dscv_print
|
||||||
|
fp_dscv_dev_for_print_data
|
||||||
|
fp_dscv_dev_for_dscv_print
|
||||||
|
</SECTION>
|
||||||
|
|
||||||
|
<SECTION>
|
||||||
|
<INCLUDE>fprint.h</INCLUDE>
|
||||||
|
<FILE>drv</FILE>
|
||||||
|
fp_driver
|
||||||
|
fp_driver_get_name
|
||||||
|
fp_driver_get_full_name
|
||||||
|
fp_driver_get_driver_id
|
||||||
|
fp_driver_get_scan_type
|
||||||
|
fp_driver_supports_imaging
|
||||||
|
</SECTION>
|
||||||
|
|
||||||
|
<SECTION>
|
||||||
|
<INCLUDE>fprint.h</INCLUDE>
|
||||||
|
<FILE>dev</FILE>
|
||||||
|
fp_dev
|
||||||
|
fp_scan_type
|
||||||
|
fp_capture_result
|
||||||
|
fp_enroll_result
|
||||||
|
fp_verify_result
|
||||||
|
|
||||||
|
fp_dev_get_driver
|
||||||
|
fp_dev_get_nr_enroll_stages
|
||||||
|
fp_dev_get_devtype
|
||||||
|
fp_dev_supports_print_data
|
||||||
|
fp_dev_supports_imaging
|
||||||
|
fp_dev_supports_identification
|
||||||
|
fp_dev_supports_dscv_print
|
||||||
|
fp_dev_get_img_width
|
||||||
|
fp_dev_get_img_height
|
||||||
|
|
||||||
|
fp_operation_stop_cb
|
||||||
|
fp_img_operation_cb
|
||||||
|
fp_dev_open_cb
|
||||||
|
fp_enroll_stage_cb
|
||||||
|
fp_identify_cb
|
||||||
|
|
||||||
|
fp_dev_open
|
||||||
|
fp_async_dev_open
|
||||||
|
|
||||||
|
fp_dev_close
|
||||||
|
fp_async_dev_close
|
||||||
|
|
||||||
|
fp_enroll_finger
|
||||||
|
fp_enroll_finger_img
|
||||||
|
fp_async_enroll_start
|
||||||
|
fp_async_enroll_stop
|
||||||
|
|
||||||
|
fp_verify_finger
|
||||||
|
fp_verify_finger_img
|
||||||
|
fp_async_verify_start
|
||||||
|
fp_async_verify_stop
|
||||||
|
|
||||||
|
fp_identify_finger
|
||||||
|
fp_identify_finger_img
|
||||||
|
fp_async_identify_start
|
||||||
|
fp_async_identify_stop
|
||||||
|
|
||||||
|
fp_dev_img_capture
|
||||||
|
fp_async_capture_start
|
||||||
|
fp_async_capture_stop
|
||||||
|
</SECTION>
|
||||||
|
|
||||||
|
<SECTION>
|
||||||
|
<INCLUDE>fprint.h</INCLUDE>
|
||||||
|
<FILE>print_data</FILE>
|
||||||
|
fp_finger
|
||||||
|
fp_print_data
|
||||||
|
fp_print_data_get_data
|
||||||
|
fp_print_data_from_data
|
||||||
|
fp_print_data_save
|
||||||
|
fp_print_data_load
|
||||||
|
fp_print_data_delete
|
||||||
|
fp_print_data_from_dscv_print
|
||||||
|
fp_print_data_free
|
||||||
|
fp_print_data_get_driver_id
|
||||||
|
fp_print_data_get_devtype
|
||||||
|
</SECTION>
|
||||||
|
|
||||||
|
<SECTION>
|
||||||
|
<INCLUDE>fprint.h</INCLUDE>
|
||||||
|
<FILE>dscv_print</FILE>
|
||||||
|
fp_dscv_print
|
||||||
|
fp_discover_prints
|
||||||
|
fp_dscv_prints_free
|
||||||
|
fp_dscv_print_get_driver_id
|
||||||
|
fp_dscv_print_get_devtype
|
||||||
|
fp_dscv_print_get_finger
|
||||||
|
fp_dscv_print_delete
|
||||||
|
</SECTION>
|
||||||
|
|
||||||
|
<SECTION>
|
||||||
|
<INCLUDE>fprint.h</INCLUDE>
|
||||||
|
<FILE>img</FILE>
|
||||||
|
fp_img
|
||||||
|
fp_minutia
|
||||||
|
fp_img_free
|
||||||
|
fp_img_get_height
|
||||||
|
fp_img_get_width
|
||||||
|
fp_img_get_data
|
||||||
|
fp_img_save_to_file
|
||||||
|
fp_img_standardize
|
||||||
|
fp_img_binarize
|
||||||
|
fp_img_get_minutiae
|
||||||
|
fp_minutia_get_coords
|
||||||
|
</SECTION>
|
||||||
|
|
||||||
|
<SECTION>
|
||||||
|
<INCLUDE>fpi-log.h</INCLUDE>
|
||||||
|
<FILE>fpi-log</FILE>
|
||||||
|
fp_dbg
|
||||||
|
fp_info
|
||||||
|
fp_warn
|
||||||
|
fp_err
|
||||||
|
BUG_ON
|
||||||
|
BUG
|
||||||
|
</SECTION>
|
||||||
|
|
||||||
|
<SECTION>
|
||||||
|
<INCLUDE>fpi-ssm.h</INCLUDE>
|
||||||
|
<FILE>fpi-ssm</FILE>
|
||||||
|
fpi_ssm
|
||||||
|
ssm_completed_fn
|
||||||
|
ssm_handler_fn
|
||||||
|
|
||||||
|
fpi_ssm_new
|
||||||
|
fpi_ssm_free
|
||||||
|
fpi_ssm_start
|
||||||
|
fpi_ssm_start_subsm
|
||||||
|
|
||||||
|
fpi_ssm_next_state
|
||||||
|
fpi_ssm_next_state_timeout_cb
|
||||||
|
fpi_ssm_jump_to_state
|
||||||
|
fpi_ssm_mark_completed
|
||||||
|
fpi_ssm_mark_failed
|
||||||
|
fpi_ssm_get_user_data
|
||||||
|
fpi_ssm_get_error
|
||||||
|
fpi_ssm_get_cur_state
|
||||||
|
</SECTION>
|
||||||
|
|
||||||
|
<SECTION>
|
||||||
|
<INCLUDE>fpi-poll.h</INCLUDE>
|
||||||
|
<FILE>fpi-poll</FILE>
|
||||||
|
fpi_timeout
|
||||||
|
fpi_timeout_fn
|
||||||
|
fpi_timeout_add
|
||||||
|
fpi_timeout_set_name
|
||||||
|
fpi_timeout_cancel
|
||||||
|
</SECTION>
|
||||||
|
|
||||||
|
<SECTION>
|
||||||
|
<INCLUDE>fpi-dev.h</INCLUDE>
|
||||||
|
<FILE>fpi-dev</FILE>
|
||||||
|
fp_img_dev
|
||||||
|
|
||||||
|
FP_DEV
|
||||||
|
FP_IMG_DEV
|
||||||
|
fp_dev_set_instance_data
|
||||||
|
FP_INSTANCE_DATA
|
||||||
|
|
||||||
|
fpi_dev_get_usb_dev
|
||||||
|
fpi_dev_get_verify_data
|
||||||
|
fpi_dev_set_nr_enroll_stages
|
||||||
|
</SECTION>
|
||||||
|
|
||||||
|
<SECTION>
|
||||||
|
<INCLUDE>fpi-dev-img.h</INCLUDE>
|
||||||
|
<FILE>fpi-dev-img</FILE>
|
||||||
|
fp_imgdev_action
|
||||||
|
fp_imgdev_state
|
||||||
|
fp_imgdev_enroll_state
|
||||||
|
|
||||||
|
fpi_imgdev_abort_scan
|
||||||
|
fpi_imgdev_activate_complete
|
||||||
|
fpi_imgdev_close_complete
|
||||||
|
fpi_imgdev_deactivate_complete
|
||||||
|
fpi_imgdev_get_action
|
||||||
|
fpi_imgdev_get_action_result
|
||||||
|
fpi_imgdev_get_action_state
|
||||||
|
fpi_imgdev_image_captured
|
||||||
|
fpi_imgdev_open_complete
|
||||||
|
fpi_imgdev_report_finger_status
|
||||||
|
fpi_imgdev_session_error
|
||||||
|
fpi_imgdev_set_action_result
|
||||||
|
</SECTION>
|
||||||
|
|
||||||
|
<SECTION>
|
||||||
|
<INCLUDE>fpi-core.h</INCLUDE>
|
||||||
|
<FILE>fpi-core</FILE>
|
||||||
|
usb_id
|
||||||
|
fp_driver_type
|
||||||
|
</SECTION>
|
||||||
|
|
||||||
|
<SECTION>
|
||||||
|
<INCLUDE>fpi-core.h</INCLUDE>
|
||||||
|
<FILE>fpi-core-img</FILE>
|
||||||
|
FpiImgDriverFlags
|
||||||
|
fp_img_driver
|
||||||
|
</SECTION>
|
||||||
|
|
||||||
|
<SECTION>
|
||||||
|
<INCLUDE>fpi-img.h</INCLUDE>
|
||||||
|
<FILE>fpi-img</FILE>
|
||||||
|
FpiImgFlags
|
||||||
|
|
||||||
|
fpi_img_new
|
||||||
|
fpi_img_new_for_imgdev
|
||||||
|
fpi_img_realloc
|
||||||
|
fpi_img_resize
|
||||||
|
|
||||||
|
fpi_std_sq_dev
|
||||||
|
fpi_mean_sq_diff_norm
|
||||||
|
</SECTION>
|
||||||
|
|
||||||
|
<SECTION>
|
||||||
|
<INCLUDE>fpi-assembling.h</INCLUDE>
|
||||||
|
<FILE>fpi-assembling</FILE>
|
||||||
|
fpi_frame
|
||||||
|
fpi_frame_asmbl_ctx
|
||||||
|
fpi_line_asmbl_ctx
|
||||||
|
|
||||||
|
fpi_do_movement_estimation
|
||||||
|
fpi_assemble_frames
|
||||||
|
fpi_assemble_lines
|
||||||
|
</SECTION>
|
||||||
|
|
||||||
|
<SECTION>
|
||||||
|
<INCLUDE>fpi-usb.h</INCLUDE>
|
||||||
|
<FILE>fpi-usb</FILE>
|
||||||
|
fpi_usb_transfer
|
||||||
|
|
||||||
|
fpi_usb_transfer_cb_fn
|
||||||
|
fpi_usb_alloc
|
||||||
|
fpi_usb_fill_bulk_transfer
|
||||||
|
fpi_usb_submit_transfer
|
||||||
|
fpi_usb_cancel_transfer
|
||||||
|
</SECTION>
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
subdir('xml')
|
||||||
|
|
||||||
|
private_headers = [
|
||||||
|
'config.h',
|
||||||
|
|
||||||
|
'aeslib.h',
|
||||||
|
'assembling.h',
|
||||||
|
'fp_internal.h',
|
||||||
|
'nbis-helpers.h',
|
||||||
|
'fpi-async.h',
|
||||||
|
'fpi-data.h',
|
||||||
|
|
||||||
|
# Drivers
|
||||||
|
'aes1660.h',
|
||||||
|
'aes2501.h',
|
||||||
|
'aes2550.h',
|
||||||
|
'aes2660.h',
|
||||||
|
'aes3k.h',
|
||||||
|
'aesx660.h',
|
||||||
|
'driver_ids.h',
|
||||||
|
'elan.h',
|
||||||
|
'upek_proto.h',
|
||||||
|
'upeksonly.h',
|
||||||
|
'upektc.h',
|
||||||
|
'upektc_img.h',
|
||||||
|
'vfs0050.h',
|
||||||
|
'vfs301_proto_fragments.h',
|
||||||
|
'vfs301_proto.h',
|
||||||
|
'vfs5011_proto.h',
|
||||||
|
'synaptics.h',
|
||||||
|
|
||||||
|
# NBIS
|
||||||
|
'morph.h',
|
||||||
|
'sunrast.h',
|
||||||
|
'bozorth.h',
|
||||||
|
'defs.h',
|
||||||
|
'log.h',
|
||||||
|
'bz_array.h',
|
||||||
|
'lfs.h',
|
||||||
|
'mytime.h',
|
||||||
|
]
|
||||||
|
|
||||||
|
html_images = [
|
||||||
|
]
|
||||||
|
|
||||||
|
content_files = [
|
||||||
|
'intro.xml'
|
||||||
|
]
|
||||||
|
|
||||||
|
expand_content_files = content_files
|
||||||
|
|
||||||
|
glib_prefix = dependency('glib-2.0').get_pkgconfig_variable('prefix')
|
||||||
|
glib_docpath = join_paths(glib_prefix, 'share', 'gtk-doc', 'html')
|
||||||
|
docpath = join_paths(get_option('datadir'), 'gtk-doc', 'html')
|
||||||
|
|
||||||
|
gnome.gtkdoc('libfprint',
|
||||||
|
main_xml: 'libfprint-docs.xml',
|
||||||
|
src_dir: join_paths(meson.source_root(), 'libfprint'),
|
||||||
|
dependencies: libfprint_dep,
|
||||||
|
content_files: content_files,
|
||||||
|
expand_content_files: expand_content_files,
|
||||||
|
scan_args: [
|
||||||
|
'--ignore-decorators=API_EXPORTED',
|
||||||
|
'--ignore-headers=' + ' '.join(private_headers),
|
||||||
|
],
|
||||||
|
fixxref_args: [
|
||||||
|
'--html-dir=@0@'.format(docpath),
|
||||||
|
'--extra-dir=@0@'.format(join_paths(glib_docpath, 'glib')),
|
||||||
|
'--extra-dir=@0@'.format(join_paths(glib_docpath, 'gobject')),
|
||||||
|
],
|
||||||
|
html_assets: html_images,
|
||||||
|
install: true)
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
<!ENTITY package "@PACKAGE@">
|
||||||
|
<!ENTITY package_bugreport "@PACKAGE_BUGREPORT@">
|
||||||
|
<!ENTITY package_name "@PACKAGE_NAME@">
|
||||||
|
<!ENTITY package_string "@PACKAGE_STRING@">
|
||||||
|
<!ENTITY package_tarname "@PACKAGE_TARNAME@">
|
||||||
|
<!ENTITY package_url "@PACKAGE_URL@">
|
||||||
|
<!ENTITY package_version "@PACKAGE_VERSION@">
|
||||||
|
<!ENTITY package_api_version "@PACKAGE_API_VERSION@">
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
ent_conf = configuration_data()
|
||||||
|
ent_conf.set('PACKAGE', 'libfprint')
|
||||||
|
ent_conf.set('PACKAGE_BUGREPORT', 'https://gitlab.freedesktop.org/libfprint/libfprint/issues')
|
||||||
|
ent_conf.set('PACKAGE_NAME', 'libfprint')
|
||||||
|
ent_conf.set('PACKAGE_STRING', 'libfprint')
|
||||||
|
ent_conf.set('PACKAGE_TARNAME', 'libfprint-' + meson.project_version())
|
||||||
|
ent_conf.set('PACKAGE_URL', 'https://fprint.freedesktop.org/')
|
||||||
|
ent_conf.set('PACKAGE_VERSION', meson.project_version())
|
||||||
|
ent_conf.set('PACKAGE_API_VERSION', '1.0')
|
||||||
|
configure_file(input: 'gtkdocentities.ent.in', output: 'gtkdocentities.ent', configuration: ent_conf)
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
INCLUDES = -I$(top_srcdir)
|
|
||||||
noinst_PROGRAMS = verify_live enroll verify img_capture cpp-test
|
|
||||||
|
|
||||||
verify_live_SOURCES = verify_live.c
|
|
||||||
verify_live_LDADD = ../libfprint/libfprint.la
|
|
||||||
|
|
||||||
enroll_SOURCES = enroll.c
|
|
||||||
enroll_LDADD = ../libfprint/libfprint.la
|
|
||||||
|
|
||||||
verify_SOURCES = verify.c
|
|
||||||
verify_LDADD = ../libfprint/libfprint.la
|
|
||||||
|
|
||||||
img_capture_SOURCES = img_capture.c
|
|
||||||
img_capture_LDADD = ../libfprint/libfprint.la
|
|
||||||
|
|
||||||
cpp_test_SOURCES = cpp-test.cpp
|
|
||||||
cpp_test_LDADD = ../libfprint/libfprint.la
|
|
||||||
|
|
||||||
if BUILD_X11_EXAMPLES
|
|
||||||
noinst_PROGRAMS += img_capture_continuous
|
|
||||||
|
|
||||||
img_capture_continuous_CFLAGS = $(X_CFLAGS) $(XV_CFLAGS)
|
|
||||||
img_capture_continuous_SOURCES = img_capture_continuous.c
|
|
||||||
img_capture_continuous_LDADD = ../libfprint/libfprint.la $(X_LIBS) $(X_PRE_LIBS) $(XV_LIBS) -lX11 $(X_EXTRA_LIBS);
|
|
||||||
endif
|
|
||||||
|
|
||||||
@@ -0,0 +1,115 @@
|
|||||||
|
/*
|
||||||
|
* Example fingerprint delete finger program, which delete the right index
|
||||||
|
* finger which has been previously enrolled to disk.
|
||||||
|
* Copyright (C) 2019 Synaptics Inc
|
||||||
|
*
|
||||||
|
* 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 <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <libfprint/fprint.h>
|
||||||
|
|
||||||
|
struct fp_dscv_dev *discover_device(struct fp_dscv_dev **discovered_devs)
|
||||||
|
{
|
||||||
|
struct fp_dscv_dev *ddev = discovered_devs[0];
|
||||||
|
struct fp_driver *drv;
|
||||||
|
if (!ddev)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
drv = fp_dscv_dev_get_driver(ddev);
|
||||||
|
printf("Found device claimed by %s driver\n", fp_driver_get_full_name(drv));
|
||||||
|
return ddev;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
int r = 1;
|
||||||
|
struct fp_dscv_dev *ddev;
|
||||||
|
struct fp_dscv_dev **discovered_devs;
|
||||||
|
struct fp_dev *dev;
|
||||||
|
struct fp_print_data *data;
|
||||||
|
|
||||||
|
setenv ("G_MESSAGES_DEBUG", "all", 0);
|
||||||
|
setenv ("LIBUSB_DEBUG", "3", 0);
|
||||||
|
|
||||||
|
r = fp_init();
|
||||||
|
if (r < 0) {
|
||||||
|
fprintf(stderr, "Failed to initialize libfprint\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
discovered_devs = fp_discover_devs();
|
||||||
|
if (!discovered_devs) {
|
||||||
|
fprintf(stderr, "Could not discover devices\n");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
ddev = discover_device(discovered_devs);
|
||||||
|
if (!ddev) {
|
||||||
|
fprintf(stderr, "No devices detected.\n");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
dev = fp_dev_open(ddev);
|
||||||
|
fp_dscv_devs_free(discovered_devs);
|
||||||
|
if (!dev) {
|
||||||
|
fprintf(stderr, "Could not open device.\n");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Opened device. Loading previously enrolled right index finger "
|
||||||
|
"data...\n");
|
||||||
|
|
||||||
|
r = fp_print_data_load(dev, RIGHT_INDEX, &data);
|
||||||
|
if (r != 0) {
|
||||||
|
fprintf(stderr, "Failed to load fingerprint, error %d\n", r);
|
||||||
|
fprintf(stderr, "Did you remember to enroll your right index finger "
|
||||||
|
"first?\n");
|
||||||
|
goto out_close;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Print loaded. delete data in sensor.\n");
|
||||||
|
if(!fp_dev_supports_data_in_sensor(dev))
|
||||||
|
{
|
||||||
|
printf("This driver doesn't support to store data in sensor.\n");
|
||||||
|
goto out_close;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = fp_delete_finger(dev, data);
|
||||||
|
fp_print_data_free(data);
|
||||||
|
if (r) {
|
||||||
|
printf("delete finger failed with error %d :(\n", r);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("sensor data deleted. now delete host data");
|
||||||
|
r = fp_print_data_delete(dev, RIGHT_INDEX);
|
||||||
|
if (r < 0) {
|
||||||
|
printf("Delete sensor data successfully but delete host data failed. %d :(\n", r);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
out_close:
|
||||||
|
fp_dev_close(dev);
|
||||||
|
out:
|
||||||
|
fp_exit();
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
+7
-3
@@ -45,8 +45,7 @@ struct fp_print_data *enroll(struct fp_dev *dev) {
|
|||||||
|
|
||||||
do {
|
do {
|
||||||
struct fp_img *img = NULL;
|
struct fp_img *img = NULL;
|
||||||
|
|
||||||
sleep(1);
|
|
||||||
printf("\nScan your finger now.\n");
|
printf("\nScan your finger now.\n");
|
||||||
|
|
||||||
r = fp_enroll_finger_img(dev, &enrolled_print, &img);
|
r = fp_enroll_finger_img(dev, &enrolled_print, &img);
|
||||||
@@ -110,12 +109,14 @@ int main(void)
|
|||||||
"Ctrl+C\n");
|
"Ctrl+C\n");
|
||||||
getchar();
|
getchar();
|
||||||
|
|
||||||
|
setenv ("G_MESSAGES_DEBUG", "all", 0);
|
||||||
|
setenv ("LIBUSB_DEBUG", "3", 0);
|
||||||
|
|
||||||
r = fp_init();
|
r = fp_init();
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
fprintf(stderr, "Failed to initialize libfprint\n");
|
fprintf(stderr, "Failed to initialize libfprint\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
fp_set_debug(3);
|
|
||||||
|
|
||||||
discovered_devs = fp_discover_devs();
|
discovered_devs = fp_discover_devs();
|
||||||
if (!discovered_devs) {
|
if (!discovered_devs) {
|
||||||
@@ -141,7 +142,10 @@ int main(void)
|
|||||||
if (!data)
|
if (!data)
|
||||||
goto out_close;
|
goto out_close;
|
||||||
|
|
||||||
|
#pragma GCC diagnostic push
|
||||||
|
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||||
r = fp_print_data_save(data, RIGHT_INDEX);
|
r = fp_print_data_save(data, RIGHT_INDEX);
|
||||||
|
#pragma GCC diagnostic pop
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
fprintf(stderr, "Data save failed, code %d\n", r);
|
fprintf(stderr, "Data save failed, code %d\n", r);
|
||||||
|
|
||||||
|
|||||||
@@ -42,12 +42,14 @@ int main(void)
|
|||||||
struct fp_dev *dev;
|
struct fp_dev *dev;
|
||||||
struct fp_img *img = NULL;
|
struct fp_img *img = NULL;
|
||||||
|
|
||||||
|
setenv ("G_MESSAGES_DEBUG", "all", 0);
|
||||||
|
setenv ("LIBUSB_DEBUG", "3", 0);
|
||||||
|
|
||||||
r = fp_init();
|
r = fp_init();
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
fprintf(stderr, "Failed to initialize libfprint\n");
|
fprintf(stderr, "Failed to initialize libfprint\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
fp_set_debug(3);
|
|
||||||
|
|
||||||
discovered_devs = fp_discover_devs();
|
discovered_devs = fp_discover_devs();
|
||||||
if (!discovered_devs) {
|
if (!discovered_devs) {
|
||||||
@@ -57,6 +59,7 @@ int main(void)
|
|||||||
|
|
||||||
ddev = discover_device(discovered_devs);
|
ddev = discover_device(discovered_devs);
|
||||||
if (!ddev) {
|
if (!ddev) {
|
||||||
|
fp_dscv_devs_free(discovered_devs);
|
||||||
fprintf(stderr, "No devices detected.\n");
|
fprintf(stderr, "No devices detected.\n");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,7 +29,7 @@
|
|||||||
#define FORMAT 0x32595559
|
#define FORMAT 0x32595559
|
||||||
|
|
||||||
static int adaptor = -1;
|
static int adaptor = -1;
|
||||||
static unsigned char *framebuffer = NULL;
|
static char *framebuffer = NULL;
|
||||||
|
|
||||||
static Display *display = NULL;
|
static Display *display = NULL;
|
||||||
static Window window=(Window)NULL;
|
static Window window=(Window)NULL;
|
||||||
@@ -50,10 +50,10 @@ static int connection = -1;
|
|||||||
u = u > 255 ? 255 : u;\
|
u = u > 255 ? 255 : u;\
|
||||||
v = v > 255 ? 255 : v
|
v = v > 255 ? 255 : v
|
||||||
|
|
||||||
static void grey2yuy2 (unsigned char *grey, unsigned char *YUV, int num) {
|
static void grey2yuy2 (unsigned char *grey, char *YUV, int num) {
|
||||||
int i, j;
|
int i, j;
|
||||||
int y0, y1, u0, u1, v0, v1;
|
int y0, y1, u0, u1, v0, v1;
|
||||||
int gval;
|
uint64_t gval;
|
||||||
|
|
||||||
for (i = 0, j = 0; i < num; i += 2, j += 4)
|
for (i = 0, j = 0; i < num; i += 2, j += 4)
|
||||||
{
|
{
|
||||||
@@ -84,9 +84,9 @@ static void display_frame(struct fp_img *img)
|
|||||||
0, 0, width, height, 0, 0, width, height);
|
0, 0, width, height, 0, 0, width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void QueryXv()
|
static void QueryXv(void)
|
||||||
{
|
{
|
||||||
int num_adaptors;
|
unsigned int num_adaptors;
|
||||||
int num_formats;
|
int num_formats;
|
||||||
XvImageFormatValues *formats = NULL;
|
XvImageFormatValues *formats = NULL;
|
||||||
int i,j;
|
int i,j;
|
||||||
@@ -141,12 +141,14 @@ int main(void)
|
|||||||
int img_height;
|
int img_height;
|
||||||
int standardize = 0;
|
int standardize = 0;
|
||||||
|
|
||||||
|
setenv ("G_MESSAGES_DEBUG", "all", 0);
|
||||||
|
setenv ("LIBUSB_DEBUG", "3", 0);
|
||||||
|
|
||||||
r = fp_init();
|
r = fp_init();
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
fprintf(stderr, "Failed to initialize libfprint\n");
|
fprintf(stderr, "Failed to initialize libfprint\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
fp_set_debug(3);
|
|
||||||
|
|
||||||
discovered_devs = fp_discover_devs();
|
discovered_devs = fp_discover_devs();
|
||||||
if (!discovered_devs) {
|
if (!discovered_devs) {
|
||||||
|
|||||||
@@ -0,0 +1,29 @@
|
|||||||
|
|
||||||
|
examples = [ 'verify_live', 'enroll', 'verify', 'img_capture', 'delete' ]
|
||||||
|
foreach example: examples
|
||||||
|
executable(example,
|
||||||
|
example + '.c',
|
||||||
|
dependencies: libfprint_dep,
|
||||||
|
include_directories: [
|
||||||
|
root_inc,
|
||||||
|
],
|
||||||
|
c_args: common_cflags)
|
||||||
|
endforeach
|
||||||
|
|
||||||
|
executable('cpp-test',
|
||||||
|
'cpp-test.cpp',
|
||||||
|
dependencies: libfprint_dep,
|
||||||
|
include_directories: [
|
||||||
|
root_inc,
|
||||||
|
],
|
||||||
|
c_args: common_cflags)
|
||||||
|
|
||||||
|
if get_option('x11-examples')
|
||||||
|
executable('img_capture_continuous',
|
||||||
|
'img_capture_continuous.c',
|
||||||
|
dependencies: [ libfprint_dep, xv_dep, x11_dep ],
|
||||||
|
include_directories: [
|
||||||
|
root_inc,
|
||||||
|
],
|
||||||
|
c_args: common_cflags)
|
||||||
|
endif
|
||||||
+6
-1
@@ -86,12 +86,14 @@ int main(void)
|
|||||||
struct fp_dev *dev;
|
struct fp_dev *dev;
|
||||||
struct fp_print_data *data;
|
struct fp_print_data *data;
|
||||||
|
|
||||||
|
setenv ("G_MESSAGES_DEBUG", "all", 0);
|
||||||
|
setenv ("LIBUSB_DEBUG", "3", 0);
|
||||||
|
|
||||||
r = fp_init();
|
r = fp_init();
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
fprintf(stderr, "Failed to initialize libfprint\n");
|
fprintf(stderr, "Failed to initialize libfprint\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
fp_set_debug(3);
|
|
||||||
|
|
||||||
discovered_devs = fp_discover_devs();
|
discovered_devs = fp_discover_devs();
|
||||||
if (!discovered_devs) {
|
if (!discovered_devs) {
|
||||||
@@ -115,7 +117,10 @@ int main(void)
|
|||||||
printf("Opened device. Loading previously enrolled right index finger "
|
printf("Opened device. Loading previously enrolled right index finger "
|
||||||
"data...\n");
|
"data...\n");
|
||||||
|
|
||||||
|
#pragma GCC diagnostic push
|
||||||
|
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||||
r = fp_print_data_load(dev, RIGHT_INDEX, &data);
|
r = fp_print_data_load(dev, RIGHT_INDEX, &data);
|
||||||
|
#pragma GCC diagnostic pop
|
||||||
if (r != 0) {
|
if (r != 0) {
|
||||||
fprintf(stderr, "Failed to load fingerprint, error %d\n", r);
|
fprintf(stderr, "Failed to load fingerprint, error %d\n", r);
|
||||||
fprintf(stderr, "Did you remember to enroll your right index finger "
|
fprintf(stderr, "Did you remember to enroll your right index finger "
|
||||||
|
|||||||
@@ -43,7 +43,6 @@ struct fp_print_data *enroll(struct fp_dev *dev) {
|
|||||||
"complete the process.\n", fp_dev_get_nr_enroll_stages(dev));
|
"complete the process.\n", fp_dev_get_nr_enroll_stages(dev));
|
||||||
|
|
||||||
do {
|
do {
|
||||||
sleep(1);
|
|
||||||
printf("\nScan your finger now.\n");
|
printf("\nScan your finger now.\n");
|
||||||
r = fp_enroll_finger(dev, &enrolled_print);
|
r = fp_enroll_finger(dev, &enrolled_print);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
@@ -129,12 +128,14 @@ int main(void)
|
|||||||
struct fp_dev *dev;
|
struct fp_dev *dev;
|
||||||
struct fp_print_data *data;
|
struct fp_print_data *data;
|
||||||
|
|
||||||
|
setenv ("G_MESSAGES_DEBUG", "all", 0);
|
||||||
|
setenv ("LIBUSB_DEBUG", "3", 0);
|
||||||
|
|
||||||
r = fp_init();
|
r = fp_init();
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
fprintf(stderr, "Failed to initialize libfprint\n");
|
fprintf(stderr, "Failed to initialize libfprint\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
fp_set_debug(3);
|
|
||||||
|
|
||||||
discovered_devs = fp_discover_devs();
|
discovered_devs = fp_discover_devs();
|
||||||
if (!discovered_devs) {
|
if (!discovered_devs) {
|
||||||
|
|||||||
@@ -1,11 +0,0 @@
|
|||||||
prefix=@prefix@
|
|
||||||
exec_prefix=@exec_prefix@
|
|
||||||
libdir=@libdir@
|
|
||||||
includedir=@includedir@
|
|
||||||
|
|
||||||
Name: libfprint
|
|
||||||
Description: Generic C API for fingerprint reader access
|
|
||||||
Version: @VERSION@
|
|
||||||
Libs: -L${libdir} -lfprint
|
|
||||||
Cflags: -I${includedir}/libfprint
|
|
||||||
|
|
||||||
@@ -1,161 +0,0 @@
|
|||||||
lib_LTLIBRARIES = libfprint.la
|
|
||||||
noinst_PROGRAMS = fprint-list-udev-rules
|
|
||||||
MOSTLYCLEANFILES = $(udev_rules_DATA)
|
|
||||||
|
|
||||||
UPEKE2_SRC = drivers/upeke2.c
|
|
||||||
UPEKTS_SRC = drivers/upekts.c
|
|
||||||
UPEKTC_SRC = drivers/upektc.c
|
|
||||||
UPEKSONLY_SRC = drivers/upeksonly.c
|
|
||||||
URU4000_SRC = drivers/uru4000.c
|
|
||||||
AES1610_SRC = drivers/aes1610.c
|
|
||||||
AES2501_SRC = drivers/aes2501.c drivers/aes2501.h
|
|
||||||
AES4000_SRC = drivers/aes4000.c
|
|
||||||
FDU2000_SRC = drivers/fdu2000.c
|
|
||||||
VCOM5S_SRC = drivers/vcom5s.c
|
|
||||||
VFS101_SRC = drivers/vfs101.c
|
|
||||||
|
|
||||||
EXTRA_DIST = \
|
|
||||||
$(UPEKE2_SRC) \
|
|
||||||
$(UPEKTS_SRC) \
|
|
||||||
$(UPEKTC_SRC) \
|
|
||||||
$(UPEKSONLY_SRC) \
|
|
||||||
$(URU4000_SRC) \
|
|
||||||
$(AES1610_SRC) \
|
|
||||||
$(AES2501_SRC) \
|
|
||||||
$(AES4000_SRC) \
|
|
||||||
$(FDU2000_SRC) \
|
|
||||||
$(VCOM5S_SRC) \
|
|
||||||
$(VFS101_SRC) \
|
|
||||||
aeslib.c aeslib.h \
|
|
||||||
imagemagick.c \
|
|
||||||
gdkpixbuf.c
|
|
||||||
|
|
||||||
DRIVER_SRC =
|
|
||||||
OTHER_SRC =
|
|
||||||
|
|
||||||
NBIS_SRC = \
|
|
||||||
nbis/include/bozorth.h \
|
|
||||||
nbis/include/bz_array.h \
|
|
||||||
nbis/include/defs.h \
|
|
||||||
nbis/include/lfs.h \
|
|
||||||
nbis/include/log.h \
|
|
||||||
nbis/include/morph.h \
|
|
||||||
nbis/include/sunrast.h \
|
|
||||||
nbis/bozorth3/bozorth3.c \
|
|
||||||
nbis/bozorth3/bz_alloc.c \
|
|
||||||
nbis/bozorth3/bz_drvrs.c \
|
|
||||||
nbis/bozorth3/bz_gbls.c \
|
|
||||||
nbis/bozorth3/bz_io.c \
|
|
||||||
nbis/bozorth3/bz_sort.c \
|
|
||||||
nbis/mindtct/binar.c \
|
|
||||||
nbis/mindtct/block.c \
|
|
||||||
nbis/mindtct/contour.c \
|
|
||||||
nbis/mindtct/detect.c \
|
|
||||||
nbis/mindtct/dft.c \
|
|
||||||
nbis/mindtct/free.c \
|
|
||||||
nbis/mindtct/globals.c \
|
|
||||||
nbis/mindtct/imgutil.c \
|
|
||||||
nbis/mindtct/init.c \
|
|
||||||
nbis/mindtct/line.c \
|
|
||||||
nbis/mindtct/log.c \
|
|
||||||
nbis/mindtct/loop.c \
|
|
||||||
nbis/mindtct/maps.c \
|
|
||||||
nbis/mindtct/matchpat.c \
|
|
||||||
nbis/mindtct/minutia.c \
|
|
||||||
nbis/mindtct/morph.c \
|
|
||||||
nbis/mindtct/quality.c \
|
|
||||||
nbis/mindtct/remove.c \
|
|
||||||
nbis/mindtct/ridges.c \
|
|
||||||
nbis/mindtct/shape.c \
|
|
||||||
nbis/mindtct/sort.c \
|
|
||||||
nbis/mindtct/util.c
|
|
||||||
|
|
||||||
libfprint_la_CFLAGS = -fvisibility=hidden -I$(srcdir)/nbis/include $(LIBUSB_CFLAGS) $(GLIB_CFLAGS) $(CRYPTO_CFLAGS) $(AM_CFLAGS)
|
|
||||||
libfprint_la_LDFLAGS = -version-info @lt_major@:@lt_revision@:@lt_age@
|
|
||||||
libfprint_la_LIBADD = -lm $(LIBUSB_LIBS) $(GLIB_LIBS) $(CRYPTO_LIBS)
|
|
||||||
|
|
||||||
fprint_list_udev_rules_SOURCES = fprint-list-udev-rules.c
|
|
||||||
fprint_list_udev_rules_CFLAGS = -fvisibility=hidden -I$(srcdir)/nbis/include $(LIBUSB_CFLAGS) $(GLIB_CFLAGS) $(IMAGEMAGICK_CFLAGS) $(CRYPTO_CFLAGS) $(AM_CFLAGS)
|
|
||||||
fprint_list_udev_rules_LDADD = $(builddir)/libfprint.la
|
|
||||||
|
|
||||||
udev_rules_DATA = 60-fprint-autosuspend.rules
|
|
||||||
udev_rulesdir = $(sysconfdir)/udev/rules.d/
|
|
||||||
|
|
||||||
$(udev_rules_DATA): fprint-list-udev-rules
|
|
||||||
$(builddir)/fprint-list-udev-rules > $@
|
|
||||||
|
|
||||||
if ENABLE_UPEKE2
|
|
||||||
DRIVER_SRC += $(UPEKE2_SRC)
|
|
||||||
endif
|
|
||||||
|
|
||||||
if ENABLE_UPEKTS
|
|
||||||
DRIVER_SRC += $(UPEKTS_SRC)
|
|
||||||
endif
|
|
||||||
|
|
||||||
if ENABLE_UPEKSONLY
|
|
||||||
DRIVER_SRC += $(UPEKSONLY_SRC)
|
|
||||||
endif
|
|
||||||
|
|
||||||
#if ENABLE_UPEKTC
|
|
||||||
#DRIVER_SRC += $(UPEKTC_SRC)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if ENABLE_URU4000
|
|
||||||
DRIVER_SRC += $(URU4000_SRC)
|
|
||||||
endif
|
|
||||||
|
|
||||||
if ENABLE_VCOM5S
|
|
||||||
DRIVER_SRC += $(VCOM5S_SRC)
|
|
||||||
endif
|
|
||||||
|
|
||||||
#if ENABLE_FDU2000
|
|
||||||
#DRIVER_SRC += $(FDU2000_SRC)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if ENABLE_AES1610
|
|
||||||
DRIVER_SRC += $(AES1610_SRC)
|
|
||||||
endif
|
|
||||||
|
|
||||||
if ENABLE_AES2501
|
|
||||||
DRIVER_SRC += $(AES2501_SRC)
|
|
||||||
endif
|
|
||||||
|
|
||||||
if ENABLE_AES4000
|
|
||||||
DRIVER_SRC += $(AES4000_SRC)
|
|
||||||
endif
|
|
||||||
|
|
||||||
if ENABLE_VFS101
|
|
||||||
DRIVER_SRC += $(VFS101_SRC)
|
|
||||||
endif
|
|
||||||
|
|
||||||
if REQUIRE_IMAGEMAGICK
|
|
||||||
OTHER_SRC += imagemagick.c
|
|
||||||
libfprint_la_CFLAGS += $(IMAGING_CFLAGS)
|
|
||||||
libfprint_la_LIBADD += $(IMAGING_LIBS)
|
|
||||||
endif
|
|
||||||
|
|
||||||
if REQUIRE_GDKPIXBUF
|
|
||||||
OTHER_SRC += gdkpixbuf.c
|
|
||||||
libfprint_la_CFLAGS += $(IMAGING_CFLAGS)
|
|
||||||
libfprint_la_LIBADD += $(IMAGING_LIBS)
|
|
||||||
endif
|
|
||||||
|
|
||||||
if REQUIRE_AESLIB
|
|
||||||
OTHER_SRC += aeslib.c aeslib.h
|
|
||||||
endif
|
|
||||||
|
|
||||||
libfprint_la_SOURCES = \
|
|
||||||
fp_internal.h \
|
|
||||||
async.c \
|
|
||||||
core.c \
|
|
||||||
data.c \
|
|
||||||
drv.c \
|
|
||||||
img.c \
|
|
||||||
imgdev.c \
|
|
||||||
poll.c \
|
|
||||||
sync.c \
|
|
||||||
$(DRIVER_SRC) \
|
|
||||||
$(OTHER_SRC) \
|
|
||||||
$(NBIS_SRC)
|
|
||||||
|
|
||||||
pkginclude_HEADERS = fprint.h
|
|
||||||
@@ -1,414 +0,0 @@
|
|||||||
/*
|
|
||||||
* Asynchronous I/O functionality
|
|
||||||
* Copyright (C) 2008 Daniel Drake <dsd@gentoo.org>
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
|
||||||
* License as published by the Free Software Foundation; 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 "async"
|
|
||||||
|
|
||||||
#include <config.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <glib.h>
|
|
||||||
|
|
||||||
#include "fp_internal.h"
|
|
||||||
|
|
||||||
/* Drivers call this when device initialisation has completed */
|
|
||||||
void fpi_drvcb_open_complete(struct fp_dev *dev, int status)
|
|
||||||
{
|
|
||||||
fp_dbg("status %d", status);
|
|
||||||
BUG_ON(dev->state != DEV_STATE_INITIALIZING);
|
|
||||||
dev->state = (status) ? DEV_STATE_ERROR : DEV_STATE_INITIALIZED;
|
|
||||||
opened_devices = g_slist_prepend(opened_devices, dev);
|
|
||||||
if (dev->open_cb)
|
|
||||||
dev->open_cb(dev, status, dev->open_cb_data);
|
|
||||||
}
|
|
||||||
|
|
||||||
API_EXPORTED int fp_async_dev_open(struct fp_dscv_dev *ddev, fp_dev_open_cb cb,
|
|
||||||
void *user_data)
|
|
||||||
{
|
|
||||||
struct fp_driver *drv = ddev->drv;
|
|
||||||
struct fp_dev *dev;
|
|
||||||
libusb_device_handle *udevh;
|
|
||||||
int r;
|
|
||||||
|
|
||||||
fp_dbg("");
|
|
||||||
r = libusb_open(ddev->udev, &udevh);
|
|
||||||
if (r < 0) {
|
|
||||||
fp_err("usb_open failed, error %d", r);
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
dev = g_malloc0(sizeof(*dev));
|
|
||||||
dev->drv = drv;
|
|
||||||
dev->udev = udevh;
|
|
||||||
dev->__enroll_stage = -1;
|
|
||||||
dev->state = DEV_STATE_INITIALIZING;
|
|
||||||
dev->open_cb = cb;
|
|
||||||
dev->open_cb_data = user_data;
|
|
||||||
|
|
||||||
if (!drv->open) {
|
|
||||||
fpi_drvcb_open_complete(dev, 0);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
dev->state = DEV_STATE_INITIALIZING;
|
|
||||||
r = drv->open(dev, ddev->driver_data);
|
|
||||||
if (r) {
|
|
||||||
fp_err("device initialisation failed, driver=%s", drv->name);
|
|
||||||
libusb_close(udevh);
|
|
||||||
g_free(dev);
|
|
||||||
}
|
|
||||||
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Drivers call this when device deinitialisation has completed */
|
|
||||||
void fpi_drvcb_close_complete(struct fp_dev *dev)
|
|
||||||
{
|
|
||||||
fp_dbg("");
|
|
||||||
BUG_ON(dev->state != DEV_STATE_DEINITIALIZING);
|
|
||||||
dev->state = DEV_STATE_DEINITIALIZED;
|
|
||||||
libusb_close(dev->udev);
|
|
||||||
if (dev->close_cb)
|
|
||||||
dev->close_cb(dev, dev->close_cb_data);
|
|
||||||
g_free(dev);
|
|
||||||
}
|
|
||||||
|
|
||||||
API_EXPORTED void fp_async_dev_close(struct fp_dev *dev,
|
|
||||||
fp_dev_close_cb callback, void *user_data)
|
|
||||||
{
|
|
||||||
struct fp_driver *drv = dev->drv;
|
|
||||||
|
|
||||||
if (g_slist_index(opened_devices, (gconstpointer) dev) == -1)
|
|
||||||
fp_err("device %p not in opened list!", dev);
|
|
||||||
opened_devices = g_slist_remove(opened_devices, (gconstpointer) dev);
|
|
||||||
|
|
||||||
dev->close_cb = callback;
|
|
||||||
dev->close_cb_data = user_data;
|
|
||||||
|
|
||||||
if (!drv->close) {
|
|
||||||
fpi_drvcb_close_complete(dev);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
dev->state = DEV_STATE_DEINITIALIZING;
|
|
||||||
drv->close(dev);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Drivers call this when enrollment has started */
|
|
||||||
void fpi_drvcb_enroll_started(struct fp_dev *dev, int status)
|
|
||||||
{
|
|
||||||
fp_dbg("status %d", status);
|
|
||||||
BUG_ON(dev->state != DEV_STATE_ENROLL_STARTING);
|
|
||||||
if (status) {
|
|
||||||
if (status > 0) {
|
|
||||||
status = -status;
|
|
||||||
fp_dbg("adjusted to %d", status);
|
|
||||||
}
|
|
||||||
dev->state = DEV_STATE_ERROR;
|
|
||||||
if (dev->enroll_stage_cb)
|
|
||||||
dev->enroll_stage_cb(dev, status, NULL, NULL,
|
|
||||||
dev->enroll_stage_cb_data);
|
|
||||||
} else {
|
|
||||||
dev->state = DEV_STATE_ENROLLING;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
API_EXPORTED int fp_async_enroll_start(struct fp_dev *dev,
|
|
||||||
fp_enroll_stage_cb callback, void *user_data)
|
|
||||||
{
|
|
||||||
struct fp_driver *drv = dev->drv;
|
|
||||||
int r;
|
|
||||||
|
|
||||||
if (!dev->nr_enroll_stages || !drv->enroll_start) {
|
|
||||||
fp_err("driver %s has 0 enroll stages or no enroll func",
|
|
||||||
drv->name);
|
|
||||||
return -ENOTSUP;
|
|
||||||
}
|
|
||||||
|
|
||||||
fp_dbg("starting enrollment");
|
|
||||||
dev->enroll_stage_cb = callback;
|
|
||||||
dev->enroll_stage_cb_data = user_data;
|
|
||||||
|
|
||||||
dev->state = DEV_STATE_ENROLL_STARTING;
|
|
||||||
r = drv->enroll_start(dev);
|
|
||||||
if (r < 0) {
|
|
||||||
dev->enroll_stage_cb = NULL;
|
|
||||||
fp_err("failed to start enrollment");
|
|
||||||
dev->state = DEV_STATE_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Drivers call this when an enroll stage has completed */
|
|
||||||
void fpi_drvcb_enroll_stage_completed(struct fp_dev *dev, int result,
|
|
||||||
struct fp_print_data *data, struct fp_img *img)
|
|
||||||
{
|
|
||||||
BUG_ON(dev->state != DEV_STATE_ENROLLING);
|
|
||||||
fp_dbg("result %d", result);
|
|
||||||
if (!dev->enroll_stage_cb) {
|
|
||||||
fp_dbg("ignoring enroll result as no callback is subscribed");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (result == FP_ENROLL_COMPLETE && !data) {
|
|
||||||
fp_err("BUG: complete but no data?");
|
|
||||||
result = FP_ENROLL_FAIL;
|
|
||||||
}
|
|
||||||
dev->enroll_stage_cb(dev, result, data, img, dev->enroll_stage_cb_data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Drivers call this when enrollment has stopped */
|
|
||||||
void fpi_drvcb_enroll_stopped(struct fp_dev *dev)
|
|
||||||
{
|
|
||||||
fp_dbg("");
|
|
||||||
BUG_ON(dev->state != DEV_STATE_ENROLL_STOPPING);
|
|
||||||
dev->state = DEV_STATE_INITIALIZED;
|
|
||||||
if (dev->enroll_stop_cb)
|
|
||||||
dev->enroll_stop_cb(dev, dev->enroll_stop_cb_data);
|
|
||||||
}
|
|
||||||
|
|
||||||
API_EXPORTED int fp_async_enroll_stop(struct fp_dev *dev,
|
|
||||||
fp_enroll_stop_cb callback, void *user_data)
|
|
||||||
{
|
|
||||||
struct fp_driver *drv = dev->drv;
|
|
||||||
int r;
|
|
||||||
|
|
||||||
fp_dbg("");
|
|
||||||
if (!drv->enroll_start)
|
|
||||||
return -ENOTSUP;
|
|
||||||
|
|
||||||
dev->enroll_stage_cb = NULL;
|
|
||||||
dev->enroll_stop_cb = callback;
|
|
||||||
dev->enroll_stop_cb_data = user_data;
|
|
||||||
dev->state = DEV_STATE_ENROLL_STOPPING;
|
|
||||||
|
|
||||||
if (!drv->enroll_stop) {
|
|
||||||
fpi_drvcb_enroll_stopped(dev);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
r = drv->enroll_stop(dev);
|
|
||||||
if (r < 0) {
|
|
||||||
fp_err("failed to stop enrollment");
|
|
||||||
dev->enroll_stop_cb = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
API_EXPORTED int fp_async_verify_start(struct fp_dev *dev,
|
|
||||||
struct fp_print_data *data, fp_verify_cb callback, void *user_data)
|
|
||||||
{
|
|
||||||
struct fp_driver *drv = dev->drv;
|
|
||||||
int r;
|
|
||||||
|
|
||||||
fp_dbg("");
|
|
||||||
if (!drv->verify_start)
|
|
||||||
return -ENOTSUP;
|
|
||||||
|
|
||||||
dev->state = DEV_STATE_VERIFY_STARTING;
|
|
||||||
dev->verify_cb = callback;
|
|
||||||
dev->verify_cb_data = user_data;
|
|
||||||
dev->verify_data = data;
|
|
||||||
|
|
||||||
r = drv->verify_start(dev);
|
|
||||||
if (r < 0) {
|
|
||||||
dev->verify_cb = NULL;
|
|
||||||
dev->state = DEV_STATE_ERROR;
|
|
||||||
fp_err("failed to start verification, error %d", r);
|
|
||||||
}
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Drivers call this when verification has started */
|
|
||||||
void fpi_drvcb_verify_started(struct fp_dev *dev, int status)
|
|
||||||
{
|
|
||||||
fp_dbg("");
|
|
||||||
BUG_ON(dev->state != DEV_STATE_VERIFY_STARTING);
|
|
||||||
if (status) {
|
|
||||||
if (status > 0) {
|
|
||||||
status = -status;
|
|
||||||
fp_dbg("adjusted to %d", status);
|
|
||||||
}
|
|
||||||
dev->state = DEV_STATE_ERROR;
|
|
||||||
if (dev->verify_cb)
|
|
||||||
dev->verify_cb(dev, status, NULL, dev->verify_cb_data);
|
|
||||||
} else {
|
|
||||||
dev->state = DEV_STATE_VERIFYING;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Drivers call this to report a verify result (which might mark completion) */
|
|
||||||
void fpi_drvcb_report_verify_result(struct fp_dev *dev, int result,
|
|
||||||
struct fp_img *img)
|
|
||||||
{
|
|
||||||
fp_dbg("result %d", result);
|
|
||||||
BUG_ON(dev->state != DEV_STATE_VERIFYING);
|
|
||||||
if (result < 0 || result == FP_VERIFY_NO_MATCH
|
|
||||||
|| result == FP_VERIFY_MATCH)
|
|
||||||
dev->state = DEV_STATE_VERIFY_DONE;
|
|
||||||
|
|
||||||
if (dev->verify_cb)
|
|
||||||
dev->verify_cb(dev, result, img, dev->verify_cb_data);
|
|
||||||
else
|
|
||||||
fp_dbg("ignoring verify result as no callback is subscribed");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Drivers call this when verification has stopped */
|
|
||||||
void fpi_drvcb_verify_stopped(struct fp_dev *dev)
|
|
||||||
{
|
|
||||||
fp_dbg("");
|
|
||||||
BUG_ON(dev->state != DEV_STATE_VERIFY_STOPPING);
|
|
||||||
dev->state = DEV_STATE_INITIALIZED;
|
|
||||||
if (dev->verify_stop_cb)
|
|
||||||
dev->verify_stop_cb(dev, dev->verify_stop_cb_data);
|
|
||||||
}
|
|
||||||
|
|
||||||
API_EXPORTED int fp_async_verify_stop(struct fp_dev *dev,
|
|
||||||
fp_verify_stop_cb callback, void *user_data)
|
|
||||||
{
|
|
||||||
struct fp_driver *drv = dev->drv;
|
|
||||||
gboolean iterating = (dev->state == DEV_STATE_VERIFYING);
|
|
||||||
int r;
|
|
||||||
|
|
||||||
fp_dbg("");
|
|
||||||
BUG_ON(dev->state != DEV_STATE_ERROR
|
|
||||||
&& dev->state != DEV_STATE_VERIFYING
|
|
||||||
&& dev->state != DEV_STATE_VERIFY_DONE);
|
|
||||||
|
|
||||||
dev->verify_cb = NULL;
|
|
||||||
dev->verify_stop_cb = callback;
|
|
||||||
dev->verify_stop_cb_data = user_data;
|
|
||||||
dev->state = DEV_STATE_VERIFY_STOPPING;
|
|
||||||
|
|
||||||
if (!drv->verify_start)
|
|
||||||
return -ENOTSUP;
|
|
||||||
if (!drv->verify_stop) {
|
|
||||||
dev->state = DEV_STATE_INITIALIZED;
|
|
||||||
fpi_drvcb_verify_stopped(dev);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
r = drv->verify_stop(dev, iterating);
|
|
||||||
if (r < 0) {
|
|
||||||
fp_err("failed to stop verification");
|
|
||||||
dev->verify_stop_cb = NULL;
|
|
||||||
}
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
API_EXPORTED int fp_async_identify_start(struct fp_dev *dev,
|
|
||||||
struct fp_print_data **gallery, fp_identify_cb callback, void *user_data)
|
|
||||||
{
|
|
||||||
struct fp_driver *drv = dev->drv;
|
|
||||||
int r;
|
|
||||||
|
|
||||||
fp_dbg("");
|
|
||||||
if (!drv->identify_start)
|
|
||||||
return -ENOTSUP;
|
|
||||||
dev->state = DEV_STATE_IDENTIFY_STARTING;
|
|
||||||
dev->identify_cb = callback;
|
|
||||||
dev->identify_cb_data = user_data;
|
|
||||||
dev->identify_gallery = gallery;
|
|
||||||
|
|
||||||
r = drv->identify_start(dev);
|
|
||||||
if (r < 0) {
|
|
||||||
fp_err("identify_start failed with error %d", r);
|
|
||||||
dev->identify_cb = NULL;
|
|
||||||
dev->state = DEV_STATE_ERROR;
|
|
||||||
}
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Driver-lib: identification has started, expect results soon */
|
|
||||||
void fpi_drvcb_identify_started(struct fp_dev *dev, int status)
|
|
||||||
{
|
|
||||||
fp_dbg("status %d", status);
|
|
||||||
BUG_ON(dev->state != DEV_STATE_IDENTIFY_STARTING);
|
|
||||||
if (status) {
|
|
||||||
if (status > 0) {
|
|
||||||
status = -status;
|
|
||||||
fp_dbg("adjusted to %d", status);
|
|
||||||
}
|
|
||||||
dev->state = DEV_STATE_ERROR;
|
|
||||||
if (dev->identify_cb)
|
|
||||||
dev->identify_cb(dev, status, 0, NULL, dev->identify_cb_data);
|
|
||||||
} else {
|
|
||||||
dev->state = DEV_STATE_IDENTIFYING;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Drivers report an identify result (which might mark completion) */
|
|
||||||
void fpi_drvcb_report_identify_result(struct fp_dev *dev, int result,
|
|
||||||
size_t match_offset, struct fp_img *img)
|
|
||||||
{
|
|
||||||
fp_dbg("result %d", result);
|
|
||||||
BUG_ON(dev->state != DEV_STATE_IDENTIFYING
|
|
||||||
&& dev->state != DEV_STATE_ERROR);
|
|
||||||
if (result < 0 || result == FP_VERIFY_NO_MATCH
|
|
||||||
|| result == FP_VERIFY_MATCH)
|
|
||||||
dev->state = DEV_STATE_IDENTIFY_DONE;
|
|
||||||
|
|
||||||
if (dev->identify_cb)
|
|
||||||
dev->identify_cb(dev, result, match_offset, img, dev->identify_cb_data);
|
|
||||||
else
|
|
||||||
fp_dbg("ignoring verify result as no callback is subscribed");
|
|
||||||
}
|
|
||||||
|
|
||||||
API_EXPORTED int fp_async_identify_stop(struct fp_dev *dev,
|
|
||||||
fp_identify_stop_cb callback, void *user_data)
|
|
||||||
{
|
|
||||||
struct fp_driver *drv = dev->drv;
|
|
||||||
gboolean iterating = (dev->state == DEV_STATE_IDENTIFYING);
|
|
||||||
int r;
|
|
||||||
|
|
||||||
fp_dbg("");
|
|
||||||
BUG_ON(dev->state != DEV_STATE_IDENTIFYING
|
|
||||||
&& dev->state != DEV_STATE_IDENTIFY_DONE);
|
|
||||||
|
|
||||||
dev->state = DEV_STATE_IDENTIFY_STOPPING;
|
|
||||||
dev->identify_cb = NULL;
|
|
||||||
dev->identify_stop_cb = callback;
|
|
||||||
dev->identify_stop_cb_data = user_data;
|
|
||||||
|
|
||||||
if (!drv->identify_start)
|
|
||||||
return -ENOTSUP;
|
|
||||||
if (!drv->identify_stop) {
|
|
||||||
dev->state = DEV_STATE_INITIALIZED;
|
|
||||||
fpi_drvcb_identify_stopped(dev);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
r = drv->identify_stop(dev, iterating);
|
|
||||||
if (r < 0) {
|
|
||||||
fp_err("failed to stop identification");
|
|
||||||
dev->identify_stop_cb = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Drivers call this when identification has stopped */
|
|
||||||
void fpi_drvcb_identify_stopped(struct fp_dev *dev)
|
|
||||||
{
|
|
||||||
fp_dbg("");
|
|
||||||
BUG_ON(dev->state != DEV_STATE_IDENTIFY_STOPPING);
|
|
||||||
dev->state = DEV_STATE_INITIALIZED;
|
|
||||||
if (dev->identify_stop_cb)
|
|
||||||
dev->identify_stop_cb(dev, dev->identify_stop_cb_data);
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,974 +0,0 @@
|
|||||||
/*
|
|
||||||
* Core functions for libfprint
|
|
||||||
* Copyright (C) 2007-2008 Daniel Drake <dsd@gentoo.org>
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
|
||||||
* License as published by the Free Software Foundation; either
|
|
||||||
* version 2.1 of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <config.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
#include <glib.h>
|
|
||||||
#include <libusb.h>
|
|
||||||
|
|
||||||
#include "fp_internal.h"
|
|
||||||
|
|
||||||
static int log_level = 0;
|
|
||||||
static int log_level_fixed = 0;
|
|
||||||
|
|
||||||
libusb_context *fpi_usb_ctx = NULL;
|
|
||||||
GSList *opened_devices = NULL;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \mainpage libfprint API Reference
|
|
||||||
* libfprint is an open source library to provide access to fingerprint
|
|
||||||
* scanning devices. For more info, see the
|
|
||||||
* <a href="http://www.reactivated.net/fprint/Libfprint">libfprint project
|
|
||||||
* homepage</a>.
|
|
||||||
*
|
|
||||||
* This documentation is aimed at application developers who wish to integrate
|
|
||||||
* fingerprint-related functionality into their software. libfprint has been
|
|
||||||
* designed so that you only have to do this once - by integrating your
|
|
||||||
* software with libfprint, you'll be supporting all the fingerprint readers
|
|
||||||
* that we have got our hands on. As such, the API is rather general (and
|
|
||||||
* therefore hopefully easy to comprehend!), and does its best to hide the
|
|
||||||
* technical details that required to operate the hardware.
|
|
||||||
*
|
|
||||||
* This documentation is not aimed at developers wishing to develop and
|
|
||||||
* contribute fingerprint device drivers to libfprint.
|
|
||||||
*
|
|
||||||
* Feedback on this API and its associated documentation is appreciated. Was
|
|
||||||
* anything unclear? Does anything seem unreasonably complicated? Is anything
|
|
||||||
* missing? Let us know on the
|
|
||||||
* <a href="http://www.reactivated.net/fprint/Mailing_list">mailing list</a>.
|
|
||||||
*
|
|
||||||
* \section enrollment Enrollment
|
|
||||||
*
|
|
||||||
* Before you dive into the API, it's worth introducing a couple of concepts.
|
|
||||||
*
|
|
||||||
* The process of enrolling a finger is where you effectively scan your
|
|
||||||
* finger for the purposes of teaching the system what your finger looks like.
|
|
||||||
* This means that you scan your fingerprint, then the system processes it and
|
|
||||||
* stores some data about your fingerprint to refer to later.
|
|
||||||
*
|
|
||||||
* \section verification Verification
|
|
||||||
*
|
|
||||||
* Verification is what most people think of when they think about fingerprint
|
|
||||||
* scanning. The process of verification is effectively performing a fresh
|
|
||||||
* fingerprint scan, and then comparing that scan to a finger that was
|
|
||||||
* previously enrolled.
|
|
||||||
*
|
|
||||||
* As an example scenario, verification can be used to implement what people
|
|
||||||
* would picture as fingerprint login (i.e. fingerprint replaces password).
|
|
||||||
* For example:
|
|
||||||
* - I enroll my fingerprint through some software that trusts I am who I say
|
|
||||||
* I am. This is a prerequisite before I can perform fingerprint-based
|
|
||||||
* login for my account.
|
|
||||||
* - Some time later, I want to login to my computer. I enter my username,
|
|
||||||
* but instead of prompting me for a password, it asks me to scan my finger.
|
|
||||||
* I scan my finger.
|
|
||||||
* - The system compares the finger I just scanned to the one that was
|
|
||||||
* enrolled earlier. If the system decides that the fingerprints match,
|
|
||||||
* I am successfully logged in. Otherwise, the system informs me that I am
|
|
||||||
* not authorised to login as that user.
|
|
||||||
*
|
|
||||||
* \section identification Identification
|
|
||||||
*
|
|
||||||
* Identification is the process of comparing a freshly scanned fingerprint
|
|
||||||
* to a <em>collection</em> of previously enrolled fingerprints. For example,
|
|
||||||
* imagine there are 100 people in an organisation, and they all have enrolled
|
|
||||||
* their fingerprints. One user walks up to a fingerprint scanner and scans
|
|
||||||
* their finger. With <em>no other knowledge</em> of who that user might be,
|
|
||||||
* the system examines their fingerprint, looks in the database, and determines
|
|
||||||
* that the user is user number #61.
|
|
||||||
*
|
|
||||||
* In other words, verification might be seen as a one-to-one fingerprint
|
|
||||||
* comparison where you know the identity of the user that you wish to
|
|
||||||
* authenticate, whereas identification is a one-to-many comparison where you
|
|
||||||
* do not know the identity of the user that you wish to authenticate.
|
|
||||||
*
|
|
||||||
* \section compat_general Device and print compatibility
|
|
||||||
* Moving off generic conceptual ideas and onto libfprint-specific
|
|
||||||
* implementation details, here are some introductory notes regarding how
|
|
||||||
* libfprint copes with compatibility of fingerprints.
|
|
||||||
*
|
|
||||||
* libfprint deals with a whole variety of different fingerprint readers and
|
|
||||||
* the design includes considerations of compatibility and interoperability
|
|
||||||
* between multiple devices. Your application should also be prepared to
|
|
||||||
* work with more than one type of fingerprint reader and should consider that
|
|
||||||
* enrolled fingerprint X may not be compatible with the device the user has
|
|
||||||
* plugged in today.
|
|
||||||
*
|
|
||||||
* libfprint implements the principle that fingerprints from different devices
|
|
||||||
* are not necessarily compatible. For example, different devices may see
|
|
||||||
* significantly different areas of fingerprint surface, and comparing images
|
|
||||||
* between the devices would be unreliable. Also, devices can stretch and
|
|
||||||
* distort images in different ways.
|
|
||||||
*
|
|
||||||
* libfprint also implements the principle that in some cases, fingerprints
|
|
||||||
* <em>are</em> compatible between different devices. If you go and buy two
|
|
||||||
* identical fingerprint readers, it seems logical that you should be able
|
|
||||||
* to enroll on one and verify on another without problems.
|
|
||||||
*
|
|
||||||
* libfprint takes a fairly simplistic approach to these issues. Internally,
|
|
||||||
* fingerprint hardware is driven by individual drivers. libfprint enforces
|
|
||||||
* that a fingerprint that came from a device backed by driver X is never
|
|
||||||
* compared to a fingerprint that came from a device backed by driver Y.
|
|
||||||
*
|
|
||||||
* Additionally, libfprint is designed for the situation where a single driver
|
|
||||||
* may support a range of devices which differ in imaging or scanning
|
|
||||||
* properties. For example, a driver may support two ranges of devices which
|
|
||||||
* even though are programmed over the same interface, one device sees
|
|
||||||
* substantially less of the finger flesh, therefore images from the two
|
|
||||||
* device types should be incompatible despite being from the same driver. To
|
|
||||||
* implement this, each driver assigns a <em>device type</em> to each device
|
|
||||||
* that it detects based on its imaging characteristics. libfprint ensures that
|
|
||||||
* two prints being compared have the same device type.
|
|
||||||
*
|
|
||||||
* In summary, libfprint represents fingerprints in several internal structures
|
|
||||||
* and each representation will offer you a way of determining the
|
|
||||||
* \ref driver_id "driver ID" and \ref devtype "devtype" of the print in
|
|
||||||
* question. Prints are only compatible if the driver ID <b>and</b> devtypes
|
|
||||||
* match. libfprint does offer you some "is this print compatible?" helper
|
|
||||||
* functions, so you don't have to worry about these details too much.
|
|
||||||
*
|
|
||||||
* \section sync Synchronity/asynchronity
|
|
||||||
*
|
|
||||||
* Currently, all data acquisition operations are synchronous and can
|
|
||||||
* potentially block for extended periods of time. For example, the enroll
|
|
||||||
* function will block for an unpredictable amount of time until the user
|
|
||||||
* scans their finger.
|
|
||||||
*
|
|
||||||
* Alternative asynchronous/non-blocking functionality will be offered in
|
|
||||||
* future but has not been implemented yet.
|
|
||||||
*
|
|
||||||
* \section getting_started Getting started
|
|
||||||
*
|
|
||||||
* libfprint includes several simple functional examples under the examples/
|
|
||||||
* directory in the libfprint source distribution. Those are good starting
|
|
||||||
* points.
|
|
||||||
*
|
|
||||||
* Usually the first thing you want to do is determine which fingerprint
|
|
||||||
* devices are present. This is done through \ref dscv_dev "device discovery".
|
|
||||||
*
|
|
||||||
* Once you have found a device you would like to operate, you should open it.
|
|
||||||
* Refer to \ref dev "device operations". This section also details enrollment,
|
|
||||||
* image capture, and verification.
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* That should be enough to get you started, but do remember there are
|
|
||||||
* documentation pages on other aspects of libfprint's API (see the modules
|
|
||||||
* page).
|
|
||||||
*/
|
|
||||||
|
|
||||||
/** @defgroup core Core library operations */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @defgroup dev Device operations
|
|
||||||
* In order to interact with fingerprint scanners, your software will
|
|
||||||
* interface primarily with libfprint's representation of devices, detailed
|
|
||||||
* on this page.
|
|
||||||
*
|
|
||||||
* \section enrolling Enrolling
|
|
||||||
* Enrolling is represented within libfprint as a multi-stage process. This
|
|
||||||
* slightly complicates things for application developers, but is required
|
|
||||||
* for a smooth process.
|
|
||||||
*
|
|
||||||
* Some devices require the user to scan their finger multiple times in
|
|
||||||
* order to complete the enrollment process. libfprint must return control
|
|
||||||
* to your application inbetween each scan in order for your application to
|
|
||||||
* instruct the user to swipe their finger again. Each scan is referred to
|
|
||||||
* as a stage, so a device that requires 3 scans for enrollment corresponds
|
|
||||||
* to you running 3 enrollment stages using libfprint.
|
|
||||||
*
|
|
||||||
* The fp_dev_get_nr_enroll_stages() function can be used to find out how
|
|
||||||
* many enroll stages are needed.
|
|
||||||
*
|
|
||||||
* In order to complete an enroll stage, you call an enroll function such
|
|
||||||
* as fp_enroll_finger(). The return of this function does not necessarily
|
|
||||||
* indicate that a stage has completed though, as the user may not have
|
|
||||||
* produced a good enough scan. Each stage may have to be retried several
|
|
||||||
* times.
|
|
||||||
*
|
|
||||||
* The exact semantics of the enroll functions are described in the
|
|
||||||
* fp_enroll_finger() documentation. You should pay careful attention to the
|
|
||||||
* details.
|
|
||||||
*
|
|
||||||
* \section imaging Imaging
|
|
||||||
* libfprint provides you with some ways to retrieve images of scanned
|
|
||||||
* fingers, such as the fp_dev_img_capture() function, or some enroll/verify
|
|
||||||
* function variants which provide images. You may wish to do something with
|
|
||||||
* such images in your application.
|
|
||||||
*
|
|
||||||
* However, you must be aware that not all hardware supported by libfprint
|
|
||||||
* operates like this. Most hardware does operate simply by sending
|
|
||||||
* fingerprint images to the host computer for further processing, but some
|
|
||||||
* devices do all fingerprint processing in hardware and do not present images
|
|
||||||
* to the host computer.
|
|
||||||
*
|
|
||||||
* You can use fp_dev_supports_imaging() to see if image capture is possible
|
|
||||||
* on a particular device. Your application must be able to cope with the
|
|
||||||
* fact that libfprint does support regular operations (e.g. enrolling and
|
|
||||||
* verification) on some devices which do not provide images.
|
|
||||||
*
|
|
||||||
* \section devtype Devtypes
|
|
||||||
* Internally, the \ref drv "driver" behind a device assigns a 32-bit
|
|
||||||
* <em>devtype</em> identifier to the device. This cannot be used as a unique
|
|
||||||
* ID for a specific device as many devices under the same range may share
|
|
||||||
* the same devtype. The devtype may even be 0 in all cases.
|
|
||||||
*
|
|
||||||
* The only reason you may be interested in retrieving the devtype for a
|
|
||||||
* device is for the purpose of checking if some print data is compatible
|
|
||||||
* with a device. libfprint uses the devtype as one way of checking that the
|
|
||||||
* print you are verifying is compatible with the device in question - the
|
|
||||||
* devtypes must be equal. This effectively allows drivers to support more
|
|
||||||
* than one type of device where the data from each one is not compatible with
|
|
||||||
* the other. Note that libfprint does provide you with helper functions to
|
|
||||||
* determine whether a print is compatible with a device, so under most
|
|
||||||
* circumstances, you don't have to worry about devtypes at all.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/** @defgroup dscv_dev Device discovery
|
|
||||||
* These functions allow you to scan the system for supported fingerprint
|
|
||||||
* scanning hardware. This is your starting point when integrating libfprint
|
|
||||||
* into your software.
|
|
||||||
*
|
|
||||||
* When you've identified a discovered device that you would like to control,
|
|
||||||
* you can open it with fp_dev_open(). Note that discovered devices may no
|
|
||||||
* longer be available at the time when you want to open them, for example
|
|
||||||
* the user may have unplugged the device.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/** @defgroup drv Driver operations
|
|
||||||
* Internally, libfprint is abstracted into various drivers to communicate
|
|
||||||
* with the different types of supported fingerprint readers. libfprint works
|
|
||||||
* hard so that you don't have to care about these internal abstractions,
|
|
||||||
* however there are some situations where you may be interested in a little
|
|
||||||
* behind-the-scenes driver info.
|
|
||||||
*
|
|
||||||
* You can obtain the driver for a device using fp_dev_get_driver(), which
|
|
||||||
* you can pass to the functions documented on this page.
|
|
||||||
*
|
|
||||||
* \section driver_id Driver IDs
|
|
||||||
* Each driver is assigned a unique ID by the project maintainer. These
|
|
||||||
* assignments are
|
|
||||||
* <a href="http://www.reactivated.net/fprint/Driver_ID_assignments">
|
|
||||||
* documented on the wiki</a> and will never change.
|
|
||||||
*
|
|
||||||
* The only reason you may be interested in retrieving the driver ID for a
|
|
||||||
* driver is for the purpose of checking if some print data is compatible
|
|
||||||
* with a device. libfprint uses the driver ID as one way of checking that
|
|
||||||
* the print you are trying to verify is compatible with the device in
|
|
||||||
* question - it ensures that enrollment data from one driver is never fed to
|
|
||||||
* another. Note that libfprint does provide you with helper functions to
|
|
||||||
* determine whether a print is compatible with a device, so under most
|
|
||||||
* circumstances, you don't have to worry about driver IDs at all.
|
|
||||||
*/
|
|
||||||
|
|
||||||
static GSList *registered_drivers = NULL;
|
|
||||||
|
|
||||||
void fpi_log(enum fpi_log_level level, const char *component,
|
|
||||||
const char *function, const char *format, ...)
|
|
||||||
{
|
|
||||||
va_list args;
|
|
||||||
FILE *stream = stdout;
|
|
||||||
const char *prefix;
|
|
||||||
|
|
||||||
#ifndef ENABLE_DEBUG_LOGGING
|
|
||||||
if (!log_level)
|
|
||||||
return;
|
|
||||||
if (level == LOG_LEVEL_WARNING && log_level < 2)
|
|
||||||
return;
|
|
||||||
if (level == LOG_LEVEL_INFO && log_level < 3)
|
|
||||||
return;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
switch (level) {
|
|
||||||
case LOG_LEVEL_INFO:
|
|
||||||
prefix = "info";
|
|
||||||
break;
|
|
||||||
case LOG_LEVEL_WARNING:
|
|
||||||
stream = stderr;
|
|
||||||
prefix = "warning";
|
|
||||||
break;
|
|
||||||
case LOG_LEVEL_ERROR:
|
|
||||||
stream = stderr;
|
|
||||||
prefix = "error";
|
|
||||||
break;
|
|
||||||
case LOG_LEVEL_DEBUG:
|
|
||||||
stream = stderr;
|
|
||||||
prefix = "debug";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
stream = stderr;
|
|
||||||
prefix = "unknown";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
fprintf(stream, "%s:%s [%s] ", component ? component : "fp", prefix,
|
|
||||||
function);
|
|
||||||
|
|
||||||
va_start (args, format);
|
|
||||||
vfprintf(stream, format, args);
|
|
||||||
va_end (args);
|
|
||||||
|
|
||||||
fprintf(stream, "\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void register_driver(struct fp_driver *drv)
|
|
||||||
{
|
|
||||||
if (drv->id == 0) {
|
|
||||||
fp_err("not registering driver %s: driver ID is 0", drv->name);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
registered_drivers = g_slist_prepend(registered_drivers, (gpointer) drv);
|
|
||||||
fp_dbg("registered driver %s", drv->name);
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct fp_driver * const primitive_drivers[] = {
|
|
||||||
#ifdef ENABLE_UPEKTS
|
|
||||||
&upekts_driver,
|
|
||||||
#endif
|
|
||||||
#ifdef ENABLE_UPEKE2
|
|
||||||
&upeke2_driver,
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct fp_img_driver * const img_drivers[] = {
|
|
||||||
#ifdef ENABLE_AES4000
|
|
||||||
&aes4000_driver,
|
|
||||||
#endif
|
|
||||||
#ifdef ENABLE_AES2501
|
|
||||||
&aes2501_driver,
|
|
||||||
#endif
|
|
||||||
#ifdef ENABLE_URU4000
|
|
||||||
&uru4000_driver,
|
|
||||||
#endif
|
|
||||||
#ifdef ENABLE_VCOM5S
|
|
||||||
&vcom5s_driver,
|
|
||||||
#endif
|
|
||||||
#ifdef ENABLE_UPEKSONLY
|
|
||||||
&upeksonly_driver,
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef ENABLE_AES1610
|
|
||||||
&aes1610_driver,
|
|
||||||
#endif
|
|
||||||
#ifdef ENABLE_VFS101
|
|
||||||
&vfs101_driver,
|
|
||||||
#endif
|
|
||||||
/*#ifdef ENABLE_UPEKTC
|
|
||||||
&upektc_driver,
|
|
||||||
#endif
|
|
||||||
#ifdef ENABLE_FDU2000
|
|
||||||
&fdu2000_driver,
|
|
||||||
#endif
|
|
||||||
*/
|
|
||||||
};
|
|
||||||
|
|
||||||
static void register_drivers(void)
|
|
||||||
{
|
|
||||||
unsigned int i;
|
|
||||||
|
|
||||||
for (i = 0; i < G_N_ELEMENTS(primitive_drivers); i++)
|
|
||||||
register_driver(primitive_drivers[i]);
|
|
||||||
|
|
||||||
for (i = 0; i < G_N_ELEMENTS(img_drivers); i++) {
|
|
||||||
struct fp_img_driver *imgdriver = img_drivers[i];
|
|
||||||
fpi_img_driver_setup(imgdriver);
|
|
||||||
register_driver(&imgdriver->driver);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
API_EXPORTED struct fp_driver **fprint_get_drivers (void)
|
|
||||||
{
|
|
||||||
GPtrArray *array;
|
|
||||||
unsigned int i;
|
|
||||||
|
|
||||||
array = g_ptr_array_new ();
|
|
||||||
for (i = 0; i < G_N_ELEMENTS(primitive_drivers); i++)
|
|
||||||
g_ptr_array_add (array, primitive_drivers[i]);
|
|
||||||
|
|
||||||
for (i = 0; i < G_N_ELEMENTS(img_drivers); i++)
|
|
||||||
g_ptr_array_add (array, &(img_drivers[i]->driver));
|
|
||||||
|
|
||||||
/* Add a null item terminating the array */
|
|
||||||
g_ptr_array_add (array, NULL);
|
|
||||||
|
|
||||||
return (struct fp_driver **) g_ptr_array_free (array, FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct fp_driver *find_supporting_driver(libusb_device *udev,
|
|
||||||
const struct usb_id **usb_id, uint32_t *devtype)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
GSList *elem = registered_drivers;
|
|
||||||
struct libusb_device_descriptor dsc;
|
|
||||||
|
|
||||||
const struct usb_id *best_usb_id;
|
|
||||||
struct fp_driver *best_drv;
|
|
||||||
uint32_t best_devtype;
|
|
||||||
int drv_score = 0;
|
|
||||||
|
|
||||||
ret = libusb_get_device_descriptor(udev, &dsc);
|
|
||||||
if (ret < 0) {
|
|
||||||
fp_err("Failed to get device descriptor");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
best_drv = NULL;
|
|
||||||
best_devtype = 0;
|
|
||||||
|
|
||||||
do {
|
|
||||||
struct fp_driver *drv = elem->data;
|
|
||||||
uint32_t type = 0;
|
|
||||||
const struct usb_id *id;
|
|
||||||
|
|
||||||
for (id = drv->id_table; id->vendor; id++) {
|
|
||||||
if (dsc.idVendor == id->vendor && dsc.idProduct == id->product) {
|
|
||||||
if (drv->discover) {
|
|
||||||
int r = drv->discover(&dsc, &type);
|
|
||||||
if (r < 0)
|
|
||||||
fp_err("%s discover failed, code %d", drv->name, r);
|
|
||||||
if (r <= 0)
|
|
||||||
continue;
|
|
||||||
/* Has a discover function, and matched our device */
|
|
||||||
drv_score = 100;
|
|
||||||
} else {
|
|
||||||
/* Already got a driver as good */
|
|
||||||
if (drv_score >= 50)
|
|
||||||
continue;
|
|
||||||
drv_score = 50;
|
|
||||||
}
|
|
||||||
fp_dbg("driver %s supports USB device %04x:%04x",
|
|
||||||
drv->name, id->vendor, id->product);
|
|
||||||
best_usb_id = id;
|
|
||||||
best_drv = drv;
|
|
||||||
best_devtype = type;
|
|
||||||
|
|
||||||
/* We found the best possible driver */
|
|
||||||
if (drv_score == 100)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} while ((elem = g_slist_next(elem)));
|
|
||||||
|
|
||||||
if (best_drv != NULL) {
|
|
||||||
fp_dbg("selected driver %s supports USB device %04x:%04x",
|
|
||||||
best_drv->name, dsc.idVendor, dsc.idProduct);
|
|
||||||
*devtype = best_devtype;
|
|
||||||
*usb_id = best_usb_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
return best_drv;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct fp_dscv_dev *discover_dev(libusb_device *udev)
|
|
||||||
{
|
|
||||||
const struct usb_id *usb_id;
|
|
||||||
struct fp_driver *drv;
|
|
||||||
struct fp_dscv_dev *ddev;
|
|
||||||
uint32_t devtype;
|
|
||||||
|
|
||||||
drv = find_supporting_driver(udev, &usb_id, &devtype);
|
|
||||||
|
|
||||||
if (!drv)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
ddev = g_malloc0(sizeof(*ddev));
|
|
||||||
ddev->drv = drv;
|
|
||||||
ddev->udev = udev;
|
|
||||||
ddev->driver_data = usb_id->driver_data;
|
|
||||||
ddev->devtype = devtype;
|
|
||||||
return ddev;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** \ingroup dscv_dev
|
|
||||||
* Scans the system and returns a list of discovered devices. This is your
|
|
||||||
* entry point into finding a fingerprint reader to operate.
|
|
||||||
* \returns a NULL-terminated list of discovered devices. Must be freed with
|
|
||||||
* fp_dscv_devs_free() after use.
|
|
||||||
*/
|
|
||||||
API_EXPORTED struct fp_dscv_dev **fp_discover_devs(void)
|
|
||||||
{
|
|
||||||
GSList *tmplist = NULL;
|
|
||||||
struct fp_dscv_dev **list;
|
|
||||||
libusb_device *udev;
|
|
||||||
libusb_device **devs;
|
|
||||||
int dscv_count = 0;
|
|
||||||
int r;
|
|
||||||
int i = 0;
|
|
||||||
|
|
||||||
if (registered_drivers == NULL)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
r = libusb_get_device_list(fpi_usb_ctx, &devs);
|
|
||||||
if (r < 0) {
|
|
||||||
fp_err("couldn't enumerate USB devices, error %d", r);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check each device against each driver, temporarily storing successfully
|
|
||||||
* discovered devices in a GSList.
|
|
||||||
*
|
|
||||||
* Quite inefficient but excusable as we'll only be dealing with small
|
|
||||||
* sets of drivers against small sets of USB devices */
|
|
||||||
while ((udev = devs[i++]) != NULL) {
|
|
||||||
struct fp_dscv_dev *ddev = discover_dev(udev);
|
|
||||||
if (!ddev)
|
|
||||||
continue;
|
|
||||||
tmplist = g_slist_prepend(tmplist, (gpointer) ddev);
|
|
||||||
dscv_count++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Convert our temporary GSList into a standard NULL-terminated pointer
|
|
||||||
* array. */
|
|
||||||
list = g_malloc(sizeof(*list) * (dscv_count + 1));
|
|
||||||
if (dscv_count > 0) {
|
|
||||||
GSList *elem = tmplist;
|
|
||||||
i = 0;
|
|
||||||
do {
|
|
||||||
list[i++] = elem->data;
|
|
||||||
} while ((elem = g_slist_next(elem)));
|
|
||||||
}
|
|
||||||
list[dscv_count] = NULL; /* NULL-terminate */
|
|
||||||
|
|
||||||
g_slist_free(tmplist);
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** \ingroup dscv_dev
|
|
||||||
* Free a list of discovered devices. This function destroys the list and all
|
|
||||||
* discovered devices that it included, so make sure you have opened your
|
|
||||||
* discovered device <b>before</b> freeing the list.
|
|
||||||
* \param devs the list of discovered devices. If NULL, function simply
|
|
||||||
* returns.
|
|
||||||
*/
|
|
||||||
API_EXPORTED void fp_dscv_devs_free(struct fp_dscv_dev **devs)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
if (!devs)
|
|
||||||
return;
|
|
||||||
|
|
||||||
for (i = 0; devs[i]; i++)
|
|
||||||
g_free(devs[i]);
|
|
||||||
g_free(devs);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** \ingroup dscv_dev
|
|
||||||
* Gets the \ref drv "driver" for a discovered device.
|
|
||||||
* \param dev the discovered device
|
|
||||||
* \returns the driver backing the device
|
|
||||||
*/
|
|
||||||
API_EXPORTED struct fp_driver *fp_dscv_dev_get_driver(struct fp_dscv_dev *dev)
|
|
||||||
{
|
|
||||||
return dev->drv;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** \ingroup dscv_dev
|
|
||||||
* Gets the \ref devtype "devtype" for a discovered device.
|
|
||||||
* \param dev the discovered device
|
|
||||||
* \returns the devtype of the device
|
|
||||||
*/
|
|
||||||
API_EXPORTED uint32_t fp_dscv_dev_get_devtype(struct fp_dscv_dev *dev)
|
|
||||||
{
|
|
||||||
return dev->devtype;
|
|
||||||
}
|
|
||||||
|
|
||||||
enum fp_print_data_type fpi_driver_get_data_type(struct fp_driver *drv)
|
|
||||||
{
|
|
||||||
switch (drv->type) {
|
|
||||||
case DRIVER_PRIMITIVE:
|
|
||||||
return PRINT_DATA_RAW;
|
|
||||||
case DRIVER_IMAGING:
|
|
||||||
return PRINT_DATA_NBIS_MINUTIAE;
|
|
||||||
default:
|
|
||||||
fp_err("unrecognised drv type %d", drv->type);
|
|
||||||
return PRINT_DATA_RAW;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** \ingroup dscv_dev
|
|
||||||
* Determines if a specific \ref print_data "stored print" appears to be
|
|
||||||
* compatible with a discovered device.
|
|
||||||
* \param dev the discovered device
|
|
||||||
* \param data the print for compatibility checking
|
|
||||||
* \returns 1 if the print is compatible with the device, 0 otherwise
|
|
||||||
*/
|
|
||||||
API_EXPORTED int fp_dscv_dev_supports_print_data(struct fp_dscv_dev *dev,
|
|
||||||
struct fp_print_data *data)
|
|
||||||
{
|
|
||||||
return fpi_print_data_compatible(dev->drv->id, dev->devtype,
|
|
||||||
fpi_driver_get_data_type(dev->drv), data->driver_id, data->devtype,
|
|
||||||
data->type);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** \ingroup dscv_dev
|
|
||||||
* Determines if a specific \ref dscv_print "discovered print" appears to be
|
|
||||||
* compatible with a discovered device.
|
|
||||||
* \param dev the discovered device
|
|
||||||
* \param data the discovered print for compatibility checking
|
|
||||||
* \returns 1 if the print is compatible with the device, 0 otherwise
|
|
||||||
*/
|
|
||||||
API_EXPORTED int fp_dscv_dev_supports_dscv_print(struct fp_dscv_dev *dev,
|
|
||||||
struct fp_dscv_print *data)
|
|
||||||
{
|
|
||||||
return fpi_print_data_compatible(dev->drv->id, dev->devtype, 0,
|
|
||||||
data->driver_id, data->devtype, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** \ingroup dscv_dev
|
|
||||||
* Searches a list of discovered devices for a device that appears to be
|
|
||||||
* compatible with a \ref print_data "stored print".
|
|
||||||
* \param devs a list of discovered devices
|
|
||||||
* \param data the print under inspection
|
|
||||||
* \returns the first discovered device that appears to support the print, or
|
|
||||||
* NULL if no apparently compatible devices could be found
|
|
||||||
*/
|
|
||||||
API_EXPORTED struct fp_dscv_dev *fp_dscv_dev_for_print_data(struct fp_dscv_dev **devs,
|
|
||||||
struct fp_print_data *data)
|
|
||||||
{
|
|
||||||
struct fp_dscv_dev *ddev;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; (ddev = devs[i]); i++)
|
|
||||||
if (fp_dscv_dev_supports_print_data(ddev, data))
|
|
||||||
return ddev;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** \ingroup dscv_dev
|
|
||||||
* Searches a list of discovered devices for a device that appears to be
|
|
||||||
* compatible with a \ref dscv_print "discovered print".
|
|
||||||
* \param devs a list of discovered devices
|
|
||||||
* \param print the print under inspection
|
|
||||||
* \returns the first discovered device that appears to support the print, or
|
|
||||||
* NULL if no apparently compatible devices could be found
|
|
||||||
*/
|
|
||||||
API_EXPORTED struct fp_dscv_dev *fp_dscv_dev_for_dscv_print(struct fp_dscv_dev **devs,
|
|
||||||
struct fp_dscv_print *print)
|
|
||||||
{
|
|
||||||
struct fp_dscv_dev *ddev;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; (ddev = devs[i]); i++)
|
|
||||||
if (fp_dscv_dev_supports_dscv_print(ddev, print))
|
|
||||||
return ddev;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** \ingroup dev
|
|
||||||
* Get the \ref drv "driver" for a fingerprint device.
|
|
||||||
* \param dev the device
|
|
||||||
* \returns the driver controlling the device
|
|
||||||
*/
|
|
||||||
API_EXPORTED struct fp_driver *fp_dev_get_driver(struct fp_dev *dev)
|
|
||||||
{
|
|
||||||
return dev->drv;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** \ingroup dev
|
|
||||||
* Gets the number of \ref enrolling "enroll stages" required to enroll a
|
|
||||||
* fingerprint with the device.
|
|
||||||
* \param dev the device
|
|
||||||
* \returns the number of enroll stages
|
|
||||||
*/
|
|
||||||
API_EXPORTED int fp_dev_get_nr_enroll_stages(struct fp_dev *dev)
|
|
||||||
{
|
|
||||||
return dev->nr_enroll_stages;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** \ingroup dev
|
|
||||||
* Gets the \ref devtype "devtype" for a device.
|
|
||||||
* \param dev the device
|
|
||||||
* \returns the devtype
|
|
||||||
*/
|
|
||||||
API_EXPORTED uint32_t fp_dev_get_devtype(struct fp_dev *dev)
|
|
||||||
{
|
|
||||||
return dev->devtype;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** \ingroup dev
|
|
||||||
* Determines if a stored print is compatible with a certain device.
|
|
||||||
* \param dev the device
|
|
||||||
* \param data the stored print
|
|
||||||
* \returns 1 if the print is compatible with the device, 0 if not
|
|
||||||
*/
|
|
||||||
API_EXPORTED int fp_dev_supports_print_data(struct fp_dev *dev,
|
|
||||||
struct fp_print_data *data)
|
|
||||||
{
|
|
||||||
return fpi_print_data_compatible(dev->drv->id, dev->devtype,
|
|
||||||
fpi_driver_get_data_type(dev->drv), data->driver_id, data->devtype,
|
|
||||||
data->type);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** \ingroup dev
|
|
||||||
* Determines if a \ref dscv_print "discovered print" appears to be compatible
|
|
||||||
* with a certain device.
|
|
||||||
* \param dev the device
|
|
||||||
* \param data the discovered print
|
|
||||||
* \returns 1 if the print is compatible with the device, 0 if not
|
|
||||||
*/
|
|
||||||
API_EXPORTED int fp_dev_supports_dscv_print(struct fp_dev *dev,
|
|
||||||
struct fp_dscv_print *data)
|
|
||||||
{
|
|
||||||
return fpi_print_data_compatible(dev->drv->id, dev->devtype,
|
|
||||||
0, data->driver_id, data->devtype, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** \ingroup drv
|
|
||||||
* Retrieves the name of the driver. For example: "upekts"
|
|
||||||
* \param drv the driver
|
|
||||||
* \returns the driver name. Must not be modified or freed.
|
|
||||||
*/
|
|
||||||
API_EXPORTED const char *fp_driver_get_name(struct fp_driver *drv)
|
|
||||||
{
|
|
||||||
return drv->name;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** \ingroup drv
|
|
||||||
* Retrieves a descriptive name of the driver. For example: "UPEK TouchStrip"
|
|
||||||
* \param drv the driver
|
|
||||||
* \returns the descriptive name. Must not be modified or freed.
|
|
||||||
*/
|
|
||||||
API_EXPORTED const char *fp_driver_get_full_name(struct fp_driver *drv)
|
|
||||||
{
|
|
||||||
return drv->full_name;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** \ingroup drv
|
|
||||||
* Retrieves the driver ID code for a driver.
|
|
||||||
* \param drv the driver
|
|
||||||
* \returns the driver ID
|
|
||||||
*/
|
|
||||||
API_EXPORTED uint16_t fp_driver_get_driver_id(struct fp_driver *drv)
|
|
||||||
{
|
|
||||||
return drv->id;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** \ingroup drv
|
|
||||||
* Retrieves the scan type for the devices associated with the driver.
|
|
||||||
* \param drv the driver
|
|
||||||
* \returns the scan type
|
|
||||||
*/
|
|
||||||
API_EXPORTED enum fp_scan_type fp_driver_get_scan_type(struct fp_driver *drv)
|
|
||||||
{
|
|
||||||
return drv->scan_type;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct fp_img_dev *dev_to_img_dev(struct fp_dev *dev)
|
|
||||||
{
|
|
||||||
if (dev->drv->type != DRIVER_IMAGING)
|
|
||||||
return NULL;
|
|
||||||
return dev->priv;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** \ingroup dev
|
|
||||||
* Determines if a device has imaging capabilities. If a device has imaging
|
|
||||||
* capabilities you are able to perform imaging operations such as retrieving
|
|
||||||
* scan images using fp_dev_img_capture(). However, not all devices are
|
|
||||||
* imaging devices - some do all processing in hardware. This function will
|
|
||||||
* indicate which class a device in question falls into.
|
|
||||||
* \param dev the fingerprint device
|
|
||||||
* \returns 1 if the device is an imaging device, 0 if the device does not
|
|
||||||
* provide images to the host computer
|
|
||||||
*/
|
|
||||||
API_EXPORTED int fp_dev_supports_imaging(struct fp_dev *dev)
|
|
||||||
{
|
|
||||||
return dev->drv->type == DRIVER_IMAGING;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** \ingroup dev
|
|
||||||
* Determines if a device is capable of \ref identification "identification"
|
|
||||||
* through fp_identify_finger() and similar. Not all devices support this
|
|
||||||
* functionality.
|
|
||||||
* \param dev the fingerprint device
|
|
||||||
* \returns 1 if the device is capable of identification, 0 otherwise.
|
|
||||||
*/
|
|
||||||
API_EXPORTED int fp_dev_supports_identification(struct fp_dev *dev)
|
|
||||||
{
|
|
||||||
return dev->drv->identify_start != NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** \ingroup dev
|
|
||||||
* Captures an \ref img "image" from a device. The returned image is the raw
|
|
||||||
* image provided by the device, you may wish to \ref img_std "standardize" it.
|
|
||||||
*
|
|
||||||
* If set, the <tt>unconditional</tt> flag indicates that the device should
|
|
||||||
* capture an image unconditionally, regardless of whether a finger is there
|
|
||||||
* or not. If unset, this function will block until a finger is detected on
|
|
||||||
* the sensor.
|
|
||||||
*
|
|
||||||
* \param dev the device
|
|
||||||
* \param unconditional whether to unconditionally capture an image, or to only capture when a finger is detected
|
|
||||||
* \param image a location to return the captured image. Must be freed with
|
|
||||||
* fp_img_free() after use.
|
|
||||||
* \return 0 on success, non-zero on error. -ENOTSUP indicates that either the
|
|
||||||
* unconditional flag was set but the device does not support this, or that the
|
|
||||||
* device does not support imaging.
|
|
||||||
* \sa fp_dev_supports_imaging()
|
|
||||||
*/
|
|
||||||
API_EXPORTED int fp_dev_img_capture(struct fp_dev *dev, int unconditional,
|
|
||||||
struct fp_img **image)
|
|
||||||
{
|
|
||||||
struct fp_img_dev *imgdev = dev_to_img_dev(dev);
|
|
||||||
if (!imgdev) {
|
|
||||||
fp_dbg("image capture on non-imaging device");
|
|
||||||
return -ENOTSUP;
|
|
||||||
}
|
|
||||||
|
|
||||||
//return fpi_imgdev_capture(imgdev, unconditional, image);
|
|
||||||
/* FIXME reimplement async */
|
|
||||||
return -ENOTSUP;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** \ingroup dev
|
|
||||||
* Gets the expected width of images that will be captured from the device.
|
|
||||||
* This function will return -1 for devices that are not
|
|
||||||
* \ref imaging "imaging devices". If the width of images from this device
|
|
||||||
* can vary, 0 will be returned.
|
|
||||||
* \param dev the device
|
|
||||||
* \returns the expected image width, or 0 for variable, or -1 for non-imaging
|
|
||||||
* devices.
|
|
||||||
*/
|
|
||||||
API_EXPORTED int fp_dev_get_img_width(struct fp_dev *dev)
|
|
||||||
{
|
|
||||||
struct fp_img_dev *imgdev = dev_to_img_dev(dev);
|
|
||||||
if (!imgdev) {
|
|
||||||
fp_dbg("get image width for non-imaging device");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return fpi_imgdev_get_img_width(imgdev);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** \ingroup dev
|
|
||||||
* Gets the expected height of images that will be captured from the device.
|
|
||||||
* This function will return -1 for devices that are not
|
|
||||||
* \ref imaging "imaging devices". If the height of images from this device
|
|
||||||
* can vary, 0 will be returned.
|
|
||||||
* \param dev the device
|
|
||||||
* \returns the expected image height, or 0 for variable, or -1 for non-imaging
|
|
||||||
* devices.
|
|
||||||
*/
|
|
||||||
API_EXPORTED int fp_dev_get_img_height(struct fp_dev *dev)
|
|
||||||
{
|
|
||||||
struct fp_img_dev *imgdev = dev_to_img_dev(dev);
|
|
||||||
if (!imgdev) {
|
|
||||||
fp_dbg("get image height for non-imaging device");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return fpi_imgdev_get_img_height(imgdev);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** \ingroup core
|
|
||||||
* Set message verbosity.
|
|
||||||
* - Level 0: no messages ever printed by the library (default)
|
|
||||||
* - Level 1: error messages are printed to stderr
|
|
||||||
* - Level 2: warning and error messages are printed to stderr
|
|
||||||
* - Level 3: informational messages are printed to stdout, warning and error
|
|
||||||
* messages are printed to stderr
|
|
||||||
*
|
|
||||||
* The default level is 0, which means no messages are ever printed. If you
|
|
||||||
* choose to increase the message verbosity level, ensure that your
|
|
||||||
* application does not close the stdout/stderr file descriptors.
|
|
||||||
*
|
|
||||||
* You are advised to set level 3. libfprint is conservative with its message
|
|
||||||
* logging and most of the time, will only log messages that explain error
|
|
||||||
* conditions and other oddities. This will help you debug your software.
|
|
||||||
*
|
|
||||||
* If the LIBFPRINT_DEBUG environment variable was set when libfprint was
|
|
||||||
* initialized, this function does nothing: the message verbosity is fixed
|
|
||||||
* to the value in the environment variable.
|
|
||||||
*
|
|
||||||
* If libfprint was compiled without any message logging, this function does
|
|
||||||
* nothing: you'll never get any messages.
|
|
||||||
*
|
|
||||||
* If libfprint was compiled with verbose debug message logging, this function
|
|
||||||
* does nothing: you'll always get messages from all levels.
|
|
||||||
*
|
|
||||||
* \param ctx the context to operate on, or NULL for the default context
|
|
||||||
* \param level debug level to set
|
|
||||||
*/
|
|
||||||
API_EXPORTED void fp_set_debug(int level)
|
|
||||||
{
|
|
||||||
if (log_level_fixed)
|
|
||||||
return;
|
|
||||||
|
|
||||||
log_level = level;
|
|
||||||
libusb_set_debug(fpi_usb_ctx, level);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** \ingroup core
|
|
||||||
* Initialise libfprint. This function must be called before you attempt to
|
|
||||||
* use the library in any way.
|
|
||||||
* \return 0 on success, non-zero on error.
|
|
||||||
*/
|
|
||||||
API_EXPORTED int fp_init(void)
|
|
||||||
{
|
|
||||||
char *dbg = getenv("LIBFPRINT_DEBUG");
|
|
||||||
int r;
|
|
||||||
fp_dbg("");
|
|
||||||
|
|
||||||
r = libusb_init(&fpi_usb_ctx);
|
|
||||||
if (r < 0)
|
|
||||||
return r;
|
|
||||||
|
|
||||||
if (dbg) {
|
|
||||||
log_level = atoi(dbg);
|
|
||||||
if (log_level) {
|
|
||||||
log_level_fixed = 1;
|
|
||||||
libusb_set_debug(fpi_usb_ctx, log_level);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
register_drivers();
|
|
||||||
fpi_poll_init();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** \ingroup core
|
|
||||||
* Deinitialise libfprint. This function should be called during your program
|
|
||||||
* exit sequence. You must not use any libfprint functions after calling this
|
|
||||||
* function, unless you call fp_init() again.
|
|
||||||
*/
|
|
||||||
API_EXPORTED void fp_exit(void)
|
|
||||||
{
|
|
||||||
fp_dbg("");
|
|
||||||
|
|
||||||
if (opened_devices) {
|
|
||||||
GSList *copy = g_slist_copy(opened_devices);
|
|
||||||
GSList *elem = copy;
|
|
||||||
fp_dbg("naughty app left devices open on exit!");
|
|
||||||
|
|
||||||
do
|
|
||||||
fp_dev_close((struct fp_dev *) elem->data);
|
|
||||||
while ((elem = g_slist_next(elem)));
|
|
||||||
|
|
||||||
g_slist_free(copy);
|
|
||||||
g_slist_free(opened_devices);
|
|
||||||
opened_devices = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
fpi_data_exit();
|
|
||||||
fpi_poll_exit();
|
|
||||||
g_slist_free(registered_drivers);
|
|
||||||
registered_drivers = NULL;
|
|
||||||
libusb_exit(fpi_usb_ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
+105
-398
@@ -4,6 +4,7 @@
|
|||||||
* Copyright (C) 2007 Cyrille Bagard
|
* Copyright (C) 2007 Cyrille Bagard
|
||||||
* Copyright (C) 2007 Vasily Khoruzhick
|
* Copyright (C) 2007 Vasily Khoruzhick
|
||||||
* Copyright (C) 2009 Guido Grazioli <guido.grazioli@gmail.com>
|
* Copyright (C) 2009 Guido Grazioli <guido.grazioli@gmail.com>
|
||||||
|
* Copyright (C) 2012 Vasily Khoruzhick <anarsoul@gmail.com>
|
||||||
*
|
*
|
||||||
* Based on code from libfprint aes2501 driver.
|
* Based on code from libfprint aes2501 driver.
|
||||||
*
|
*
|
||||||
@@ -24,13 +25,8 @@
|
|||||||
|
|
||||||
#define FP_COMPONENT "aes1610"
|
#define FP_COMPONENT "aes1610"
|
||||||
|
|
||||||
#include <errno.h>
|
#include "drivers_api.h"
|
||||||
#include <string.h>
|
#include "aeslib.h"
|
||||||
|
|
||||||
#include <libusb.h>
|
|
||||||
|
|
||||||
#include <aeslib.h>
|
|
||||||
#include <fp_internal.h>
|
|
||||||
|
|
||||||
static void start_capture(struct fp_img_dev *dev);
|
static void start_capture(struct fp_img_dev *dev);
|
||||||
static void complete_deactivation(struct fp_img_dev *dev);
|
static void complete_deactivation(struct fp_img_dev *dev);
|
||||||
@@ -48,6 +44,9 @@ static int adjust_gain(unsigned char *buffer, int status);
|
|||||||
|
|
||||||
#define BULK_TIMEOUT 4000
|
#define BULK_TIMEOUT 4000
|
||||||
|
|
||||||
|
#define FINGER_DETECTION_LEN 19
|
||||||
|
#define STRIP_CAPTURE_LEN 665
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The AES1610 is an imaging device using a swipe-type sensor. It samples
|
* The AES1610 is an imaging device using a swipe-type sensor. It samples
|
||||||
* the finger at preprogrammed intervals, sending a 128x8 frame to the
|
* the finger at preprogrammed intervals, sending a 128x8 frame to the
|
||||||
@@ -63,6 +62,7 @@ static int adjust_gain(unsigned char *buffer, int status);
|
|||||||
#define FRAME_WIDTH 128
|
#define FRAME_WIDTH 128
|
||||||
#define FRAME_HEIGHT 8
|
#define FRAME_HEIGHT 8
|
||||||
#define FRAME_SIZE (FRAME_WIDTH * FRAME_HEIGHT)
|
#define FRAME_SIZE (FRAME_WIDTH * FRAME_HEIGHT)
|
||||||
|
#define IMAGE_WIDTH (FRAME_WIDTH + (FRAME_WIDTH / 2))
|
||||||
/* maximum number of frames to read during a scan */
|
/* maximum number of frames to read during a scan */
|
||||||
/* FIXME reduce substantially */
|
/* FIXME reduce substantially */
|
||||||
#define MAX_FRAMES 350
|
#define MAX_FRAMES 350
|
||||||
@@ -77,6 +77,13 @@ struct aes1610_dev {
|
|||||||
uint8_t blanks_count;
|
uint8_t blanks_count;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static struct fpi_frame_asmbl_ctx assembling_ctx = {
|
||||||
|
.frame_width = FRAME_WIDTH,
|
||||||
|
.frame_height = FRAME_HEIGHT,
|
||||||
|
.image_width = IMAGE_WIDTH,
|
||||||
|
.get_pixel = aes_get_pixel,
|
||||||
|
};
|
||||||
|
|
||||||
typedef void (*aes1610_read_regs_cb)(struct fp_img_dev *dev, int status,
|
typedef void (*aes1610_read_regs_cb)(struct fp_img_dev *dev, int status,
|
||||||
unsigned char *regs, void *user_data);
|
unsigned char *regs, void *user_data);
|
||||||
|
|
||||||
@@ -97,12 +104,12 @@ static void stub_capture_stop_cb(struct fp_img_dev *dev, int result, void *user_
|
|||||||
/* check that read succeeded but ignore all data */
|
/* check that read succeeded but ignore all data */
|
||||||
static void generic_ignore_data_cb(struct libusb_transfer *transfer)
|
static void generic_ignore_data_cb(struct libusb_transfer *transfer)
|
||||||
{
|
{
|
||||||
struct fpi_ssm *ssm = transfer->user_data;
|
fpi_ssm *ssm = transfer->user_data;
|
||||||
|
|
||||||
if (transfer->status != LIBUSB_TRANSFER_COMPLETED)
|
if (transfer->status != LIBUSB_TRANSFER_COMPLETED)
|
||||||
fpi_ssm_mark_aborted(ssm, -EIO);
|
fpi_ssm_mark_failed(ssm, -EIO);
|
||||||
else if (transfer->length != transfer->actual_length)
|
else if (transfer->length != transfer->actual_length)
|
||||||
fpi_ssm_mark_aborted(ssm, -EPROTO);
|
fpi_ssm_mark_failed(ssm, -EPROTO);
|
||||||
else
|
else
|
||||||
fpi_ssm_next_state(ssm);
|
fpi_ssm_next_state(ssm);
|
||||||
|
|
||||||
@@ -110,284 +117,36 @@ static void generic_ignore_data_cb(struct libusb_transfer *transfer)
|
|||||||
libusb_free_transfer(transfer);
|
libusb_free_transfer(transfer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void read_regs_data_cb(struct libusb_transfer *transfer)
|
|
||||||
{
|
|
||||||
struct aes1610_read_regs *rdata = transfer->user_data;
|
|
||||||
unsigned char *retdata = NULL;
|
|
||||||
int r;
|
|
||||||
|
|
||||||
if (transfer->status != LIBUSB_TRANSFER_COMPLETED) {
|
|
||||||
r = -EIO;
|
|
||||||
} else if (transfer->length != transfer->actual_length) {
|
|
||||||
r = -EPROTO;
|
|
||||||
} else {
|
|
||||||
r = 0;
|
|
||||||
retdata = transfer->buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
rdata->callback(rdata->dev, r, retdata, rdata->user_data);
|
|
||||||
g_free(rdata);
|
|
||||||
g_free(transfer->buffer);
|
|
||||||
libusb_free_transfer(transfer);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void read_regs_rq_cb(struct fp_img_dev *dev, int result, void *user_data)
|
|
||||||
{
|
|
||||||
struct aes1610_read_regs *rdata = user_data;
|
|
||||||
struct libusb_transfer *transfer;
|
|
||||||
unsigned char *data;
|
|
||||||
int r;
|
|
||||||
|
|
||||||
g_free(rdata->regwrite);
|
|
||||||
if (result != 0)
|
|
||||||
goto err;
|
|
||||||
|
|
||||||
transfer = libusb_alloc_transfer(0);
|
|
||||||
if (!transfer) {
|
|
||||||
result = -ENOMEM;
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
|
|
||||||
data = g_malloc(126);
|
|
||||||
libusb_fill_bulk_transfer(transfer, dev->udev, EP_IN, data, 126,
|
|
||||||
read_regs_data_cb, rdata, BULK_TIMEOUT);
|
|
||||||
|
|
||||||
r = libusb_submit_transfer(transfer);
|
|
||||||
if (r < 0) {
|
|
||||||
g_free(data);
|
|
||||||
libusb_free_transfer(transfer);
|
|
||||||
result = -EIO;
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
err:
|
|
||||||
rdata->callback(dev, result, NULL, rdata->user_data);
|
|
||||||
g_free(rdata);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// XXX: this comes from aes2501 driver but it is unused here
|
|
||||||
static void read_regs(struct fp_img_dev *dev, aes1610_read_regs_cb callback,
|
|
||||||
void *user_data)
|
|
||||||
{
|
|
||||||
/* FIXME: regwrite is dynamic because of asynchronity. is this really
|
|
||||||
* required? */
|
|
||||||
struct aes_regwrite *regwrite = g_malloc(sizeof(*regwrite));
|
|
||||||
struct aes1610_read_regs *rdata = g_malloc(sizeof(*rdata));
|
|
||||||
|
|
||||||
fp_dbg("");
|
|
||||||
//regwrite->reg = AES1610_REG_CTRL2;
|
|
||||||
//regwrite->value = AES1610_CTRL2_READ_REGS;
|
|
||||||
rdata->dev = dev;
|
|
||||||
rdata->callback = callback;
|
|
||||||
rdata->user_data = user_data;
|
|
||||||
rdata->regwrite = regwrite;
|
|
||||||
|
|
||||||
//aes_write_regv(dev, (const struct aes_regwrite *) regwrite, 1,
|
|
||||||
// read_regs_rq_cb, rdata);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Read the value of a specific register from a register dump */
|
|
||||||
static int regval_from_dump(unsigned char *data, uint8_t target)
|
|
||||||
{
|
|
||||||
if (*data != FIRST_AES1610_REG) {
|
|
||||||
fp_err("not a register dump");
|
|
||||||
return -EILSEQ;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(FIRST_AES1610_REG <= target && target <= LAST_AES1610_REG)) {
|
|
||||||
fp_err("out of range");
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
target -= FIRST_AES1610_REG;
|
|
||||||
target *= 2;
|
|
||||||
return data[target + 1];
|
|
||||||
}
|
|
||||||
|
|
||||||
static void generic_write_regv_cb(struct fp_img_dev *dev, int result,
|
static void generic_write_regv_cb(struct fp_img_dev *dev, int result,
|
||||||
void *user_data)
|
void *user_data)
|
||||||
{
|
{
|
||||||
struct fpi_ssm *ssm = user_data;
|
fpi_ssm *ssm = user_data;
|
||||||
if (result == 0)
|
if (result == 0)
|
||||||
fpi_ssm_next_state(ssm);
|
fpi_ssm_next_state(ssm);
|
||||||
else
|
else
|
||||||
fpi_ssm_mark_aborted(ssm, result);
|
fpi_ssm_mark_failed(ssm, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* read the specified number of bytes from the IN endpoint but throw them
|
/* read the specified number of bytes from the IN endpoint but throw them
|
||||||
* away, then increment the SSM */
|
* away, then increment the SSM */
|
||||||
static void generic_read_ignore_data(struct fpi_ssm *ssm, size_t bytes)
|
static void generic_read_ignore_data(fpi_ssm *ssm, struct fp_dev *dev, size_t bytes)
|
||||||
{
|
{
|
||||||
struct libusb_transfer *transfer = libusb_alloc_transfer(0);
|
struct libusb_transfer *transfer = fpi_usb_alloc();
|
||||||
unsigned char *data;
|
unsigned char *data;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
if (!transfer) {
|
|
||||||
fpi_ssm_mark_aborted(ssm, -ENOMEM);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
data = g_malloc(bytes);
|
data = g_malloc(bytes);
|
||||||
libusb_fill_bulk_transfer(transfer, ssm->dev->udev, EP_IN, data, bytes,
|
libusb_fill_bulk_transfer(transfer, fpi_dev_get_usb_dev(dev), EP_IN, data, bytes,
|
||||||
generic_ignore_data_cb, ssm, BULK_TIMEOUT);
|
generic_ignore_data_cb, ssm, BULK_TIMEOUT);
|
||||||
|
|
||||||
r = libusb_submit_transfer(transfer);
|
r = libusb_submit_transfer(transfer);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
g_free(data);
|
g_free(data);
|
||||||
libusb_free_transfer(transfer);
|
libusb_free_transfer(transfer);
|
||||||
fpi_ssm_mark_aborted(ssm, r);
|
fpi_ssm_mark_failed(ssm, r);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/****** IMAGE PROCESSING ******/
|
|
||||||
|
|
||||||
static int sum_histogram_values(unsigned char *data, uint8_t threshold)
|
|
||||||
{
|
|
||||||
int r = 0;
|
|
||||||
int i;
|
|
||||||
uint16_t *histogram = (uint16_t *)(data + 1);
|
|
||||||
|
|
||||||
if (*data != 0xde)
|
|
||||||
return -EILSEQ;
|
|
||||||
|
|
||||||
if (threshold > 0x0f)
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
/* FIXME endianness */
|
|
||||||
for (i = threshold; i < 16; i++)
|
|
||||||
r += histogram[i];
|
|
||||||
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* find overlapping parts of frames */
|
|
||||||
static unsigned int find_overlap(unsigned char *first_frame,
|
|
||||||
unsigned char *second_frame, unsigned int *min_error)
|
|
||||||
{
|
|
||||||
unsigned int dy;
|
|
||||||
unsigned int not_overlapped_height = 0;
|
|
||||||
*min_error = 255 * FRAME_SIZE;
|
|
||||||
for (dy = 0; dy < FRAME_HEIGHT; dy++) {
|
|
||||||
/* Calculating difference (error) between parts of frames */
|
|
||||||
unsigned int i;
|
|
||||||
unsigned int error = 0;
|
|
||||||
for (i = 0; i < FRAME_WIDTH * (FRAME_HEIGHT - dy); i++) {
|
|
||||||
/* Using ? operator to avoid abs function */
|
|
||||||
error += first_frame[i] > second_frame[i] ?
|
|
||||||
(first_frame[i] - second_frame[i]) :
|
|
||||||
(second_frame[i] - first_frame[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Normalize error */
|
|
||||||
error *= 15;
|
|
||||||
error /= i;
|
|
||||||
if (error < *min_error) {
|
|
||||||
*min_error = error;
|
|
||||||
not_overlapped_height = dy;
|
|
||||||
}
|
|
||||||
first_frame += FRAME_WIDTH;
|
|
||||||
}
|
|
||||||
|
|
||||||
return not_overlapped_height;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* assemble a series of frames into a single image */
|
|
||||||
static unsigned int assemble(struct aes1610_dev *aesdev, unsigned char *output,
|
|
||||||
gboolean reverse, unsigned int *errors_sum)
|
|
||||||
{
|
|
||||||
uint8_t *assembled = output;
|
|
||||||
int frame;
|
|
||||||
uint32_t image_height = FRAME_HEIGHT;
|
|
||||||
unsigned int min_error;
|
|
||||||
size_t num_strips = aesdev->strips_len;
|
|
||||||
GSList *list_entry = aesdev->strips;
|
|
||||||
*errors_sum = 0;
|
|
||||||
|
|
||||||
if (num_strips < 1)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
/* Rotating given data by 90 degrees
|
|
||||||
* Taken from document describing aes1610 image format
|
|
||||||
* TODO: move reversing detection here */
|
|
||||||
|
|
||||||
if (reverse)
|
|
||||||
output += (num_strips - 1) * FRAME_SIZE;
|
|
||||||
for (frame = 0; frame < num_strips; frame++) {
|
|
||||||
aes_assemble_image(list_entry->data, FRAME_WIDTH, FRAME_HEIGHT, output);
|
|
||||||
|
|
||||||
if (reverse)
|
|
||||||
output -= FRAME_SIZE;
|
|
||||||
else
|
|
||||||
output += FRAME_SIZE;
|
|
||||||
list_entry = g_slist_next(list_entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Detecting where frames overlaped */
|
|
||||||
output = assembled;
|
|
||||||
for (frame = 1; frame < num_strips; frame++) {
|
|
||||||
int not_overlapped;
|
|
||||||
|
|
||||||
output += FRAME_SIZE;
|
|
||||||
not_overlapped = find_overlap(assembled, output, &min_error);
|
|
||||||
*errors_sum += min_error;
|
|
||||||
image_height += not_overlapped;
|
|
||||||
assembled += FRAME_WIDTH * not_overlapped;
|
|
||||||
memcpy(assembled, output, FRAME_SIZE);
|
|
||||||
}
|
|
||||||
return image_height;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void assemble_and_submit_image(struct fp_img_dev *dev)
|
|
||||||
{
|
|
||||||
struct aes1610_dev *aesdev = dev->priv;
|
|
||||||
size_t final_size;
|
|
||||||
struct fp_img *img;
|
|
||||||
unsigned int errors_sum, r_errors_sum;
|
|
||||||
|
|
||||||
fp_dbg("");
|
|
||||||
|
|
||||||
BUG_ON(aesdev->strips_len == 0);
|
|
||||||
|
|
||||||
/* reverse list */
|
|
||||||
aesdev->strips = g_slist_reverse(aesdev->strips);
|
|
||||||
|
|
||||||
/* create buffer big enough for max image */
|
|
||||||
img = fpi_img_new(aesdev->strips_len * FRAME_SIZE);
|
|
||||||
|
|
||||||
img->flags = FP_IMG_COLORS_INVERTED;
|
|
||||||
img->height = assemble(aesdev, img->data, FALSE, &errors_sum);
|
|
||||||
img->height = assemble(aesdev, img->data, TRUE, &r_errors_sum);
|
|
||||||
|
|
||||||
if (r_errors_sum > errors_sum) {
|
|
||||||
img->height = assemble(aesdev, img->data, FALSE, &errors_sum);
|
|
||||||
img->flags |= FP_IMG_V_FLIPPED | FP_IMG_H_FLIPPED;
|
|
||||||
fp_dbg("normal scan direction");
|
|
||||||
} else {
|
|
||||||
fp_dbg("reversed scan direction");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* now that overlap has been removed, resize output image buffer */
|
|
||||||
final_size = img->height * FRAME_WIDTH;
|
|
||||||
img = fpi_img_resize(img, final_size);
|
|
||||||
/* FIXME: ugly workaround */
|
|
||||||
if (img->height < 12)
|
|
||||||
img->height = 12;
|
|
||||||
fpi_imgdev_image_captured(dev, img);
|
|
||||||
|
|
||||||
/* free strips and strip list */
|
|
||||||
g_slist_foreach(aesdev->strips, (GFunc) g_free, NULL);
|
|
||||||
g_slist_free(aesdev->strips);
|
|
||||||
aesdev->strips = NULL;
|
|
||||||
aesdev->strips_len = 0;
|
|
||||||
aesdev->blanks_count = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/****** FINGER PRESENCE DETECTION ******/
|
/****** FINGER PRESENCE DETECTION ******/
|
||||||
|
|
||||||
|
|
||||||
@@ -416,15 +175,6 @@ static const struct aes_regwrite finger_det_reqs[] = {
|
|||||||
{ 0x81, 0x04 }
|
{ 0x81, 0x04 }
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct aes_regwrite finger_det_none[] = {
|
|
||||||
{ 0x80, 0x01 },
|
|
||||||
{ 0x82, 0x00 },
|
|
||||||
{ 0x86, 0x00 },
|
|
||||||
{ 0xB1, 0x28 },
|
|
||||||
{ 0x1D, 0x00 }
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
static void start_finger_detection(struct fp_img_dev *dev);
|
static void start_finger_detection(struct fp_img_dev *dev);
|
||||||
|
|
||||||
static void finger_det_data_cb(struct libusb_transfer *transfer)
|
static void finger_det_data_cb(struct libusb_transfer *transfer)
|
||||||
@@ -461,12 +211,6 @@ out:
|
|||||||
libusb_free_transfer(transfer);
|
libusb_free_transfer(transfer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void finger_det_none_cb(struct fp_img_dev *dev, int result, void *user_data) | |||||||