Compare commits

..

102 Commits

Author SHA1 Message Date
Benjamin Berg
f404a69b73 tests: Test finger removal after minutiae scan completion 2019-12-04 19:49:07 +00:00
Benjamin Berg
50a837573d tests: Update helper functions for new virtual-image features
This also changes the code to keep the connection open and adds
automatic mainloop iteration to ensure the driver processes the request.
This is important so we will not deadlock when we send multiple
requests.
2019-12-04 19:49:07 +00:00
Benjamin Berg
3e958ab7b4 virtual-image: Allow fine control over the finger state
Add commands to disable automatic finger reporting for images and to
send a specific finger report. This is useful to test more code paths
inside the image-device code.
2019-12-04 19:49:07 +00:00
Benjamin Berg
a8a2a757ed virtual-image: Only print warnings for actual errors
No need to warn for lost connections (if we don't expect more data) or
cancellations.
2019-12-04 19:49:07 +00:00
Benjamin Berg
702255b182 image-device: Print warning for incorrect deactivation
Drivers may not handle deactivation properly when they are awaiting a
finger. This should be prevented by the internal FpImageDevice state
machine.
2019-12-04 19:49:07 +00:00
Marco Trevisan (Treviño)
a64ac2296b vfs0051: Use named SSMs for usb async exchanges 2019-12-04 20:43:53 +01:00
Marco Trevisan (Treviño)
a522e3fd6f fpi-ssm: Improve debugging of SSM using driver infos
Always mention the driver that is triggering it
2019-12-04 20:43:53 +01:00
Marco Trevisan (Treviño)
65828e0e56 fpi-ssm: Support named SSMs and use a fallback macro
Add fpi_ssm_new_full() that allows to pass a name to the state-machine
constructor, not to change all the drivers, provide a fpi_ssm_new() macro
that stringifies the nr_parameters value (usually an enum value) as the name
so that we can use it for better debugging.
2019-12-04 20:43:53 +01:00
Marco Trevisan (Treviño)
fe967d0ac2 ci: Build flatpak automatically only on master and tagso
While allowing to build it manually in other cases
2019-12-04 19:49:40 +01:00
Benjamin Berg
10c5bdade7 uru4000: Fix control transfer request type
During porting the request type was accidentally changed from VENDOR to
DEVICE. Change the type back to VENDOR.

See: #205
2019-12-04 18:00:02 +00:00
Benjamin Berg
8f21aa1b26 uru4000: Fix state change from IRQ handler
The IRQ handler will re-register itself automatically. However, if this
happens after the callback is called, then the check whether the IRQ
handler is running fails.

Re-start the IRQ handler before calling the callback. This way the state
changes happening from the callback will see the correct IRQ handler
registration state.

See: #205
2019-12-04 18:00:02 +00:00
Benjamin Berg
7b68344394 image-device: Prevent deactivation when waiting for finger
At the end of enroll, the image device would put the driver into the
AWAIT_FINGER_ON state and then deactivate the device afterwards. Doing
this adds additional complexity to drivers which would need to handle
both cancellation and normal deactivation from that state.

Only put the device into the AWAIT_FINGER_ON state when we know that
another enroll stage is needed. This avoids the critical state
transition simplifying the driver state machine.

Fixes: #203
Fixes: 689aff0232
2019-12-04 18:00:02 +00:00
Benjamin Berg
dccb5b3ab2 elan: Fix internal state machine to ensure correct deactivation
During calibration, the internal state was stored as INACTIVE. This is
not true though, the device is actively running state machines.

Move the state update to the start of the operation, therefore ensuring
we don't deactivate without completing the SSM.

Note that this will prevent a crash, but the driver still does not
behave quite correctly when such a state change does happen. However,
this is just a safety measure as the state change should not happen in
the first place.

See: #203
2019-12-04 18:00:02 +00:00
Marco Trevisan (Treviño)
2fcc2deb43 ci: Use --werror by default in meson at build time 2019-12-04 18:52:20 +01:00
Marco Trevisan (Treviño)
c678b9021c meson: Use stricter C arguments to compile libfprint
These are based on what mutter does, being a quite strict project on c code
quality.
2019-12-04 18:52:20 +01:00
Marco Trevisan (Treviño)
b2e55308d6 meson: Move generated source to fpi- prefix and use more readable code
Instead of concatenating strings, use an array of strings and finally join
them using newline.
2019-12-04 18:52:20 +01:00
Marco Trevisan (Treviño)
a176fa1d34 meson: Include fpi-context.h in generated fp-drivers.c 2019-12-04 18:52:19 +01:00
Marco Trevisan (Treviño)
cacce50ef9 vfs0050: Use proper casting summing pointers first
Cast the pointers as what fpi usb transfer expects.
2019-12-04 18:52:19 +01:00
Marco Trevisan (Treviño)
5ab4d6c454 vfs5011: Cast gpointer data values to proper type to do math operations 2019-12-04 18:52:19 +01:00
Marco Trevisan (Treviño)
0c655be159 gtk-demo: Use G_DECLARE to avoid missing declarations 2019-12-04 18:52:19 +01:00
Marco Trevisan (Treviño)
2b8c524928 cleanup: Use static functions for non-declared methods 2019-12-04 18:52:19 +01:00
Marco Trevisan (Treviño)
2f2ea65d32 fp-device: Remove unused timeout function and source data
These were probably added in previous iterations, but they are not uneeded
anymore as the GSource embeds already a callback function.

So make just this clearer in the dispatch function.
2019-12-04 18:52:18 +01:00
Marco Trevisan (Treviño)
1d48b70f38 storage: Include storage header so that we have declarations 2019-12-04 18:52:18 +01:00
Marco Trevisan (Treviño)
35e9f19c0c nbis: Make the extern global bozworth 'y' variable as bz_y
Othewise this could create issues with other 'y' variable definitions
shadowing it.

Add a cocci file that performs the change automatically
2019-12-04 18:52:18 +01:00
Marco Trevisan (Treviño)
70a0d6f0fe nbis/log: Don't use old-style function declarations 2019-12-04 18:52:18 +01:00
Marco Trevisan (Treviño)
7ed9b0c2f9 cleanup: Don't make nbis depend on libfprint built-sources
Now that nbis is a static library it should be possible to compile it
without any fprint-built dependency, although since it included fp_internal
there was a compile-time dependency on the fp-enums that can be generated at
later times.

So:
 - Move nbis-helpers to nbis includes (and remove inclusion in fp_internal)
 - Move the Minutiae definitions inside a standalone fpi-minutiae header
 - Include fpi-minutiae.h in fp_internal.h
 - Include nbis-hepers.h and fpi-minutiae.h in nbis' lfs.h
 - Adapt missing definitions in libfprint
2019-12-04 18:50:46 +01:00
Marco Trevisan (Treviño)
6a090656b6 nbis: Add a global include file with all the definitions ignoring erros
The nbis headers are full of redundant declarations, we can't fix them all
now, so in the mean time let's use an header using pragma to ignore such
errors.

Add the error to nbis private include folder that should be used only by
headers of libfprint-nbis.
2019-12-04 18:44:39 +01:00
Marco Trevisan (Treviño)
e1d181887f meson: Add the include directories to deps
So we don't have to repeat them everywhere.
2019-12-04 16:57:39 +01:00
Benjamin Berg
e143f12e57 meson: Build nbis separately to allow changing flags
As nbis is an external source bundle, it does not necessarily make sense
to enable/fix all warnings to the extend we do for our own library code.

As such, separate the build process into multiple stages.
2019-12-04 16:06:24 +01:00
Marco Trevisan (Treviño)
e64c18f8de cpp-test: Fix indentation 2019-12-04 16:06:24 +01:00
Marco Trevisan (Treviño)
7e70344b4a meson: Use add_project_arguments for common cflags
We were passing around the common cflags and setting them for each library
or executable, but this is just a repetition given we can just use
add_project_arguments for this.
2019-12-04 16:06:24 +01:00
Marco Trevisan (Treviño)
44af2173a8 fp-print: Clear the data not the description when setting the property 2019-12-04 16:06:24 +01:00
Marco Trevisan (Treviño)
e7c7f368c9 drivers, examples: Don't use -Wno-pointer-sign and fix relative errors 2019-12-04 16:06:24 +01:00
Marco Trevisan (Treviño)
a29586f398 fpi-usb: Use unsigned length for USB async transfers
Properly follow function signature using a temporary gsize variable address
to make the function use the same pointer type and avoid troubles at
deferencing it, while use automatic-casting to switch to signed one if
transfer succeeded.
2019-12-04 16:06:24 +01:00
Marco Trevisan (Treviño)
98cd1c2680 ci: Use a docker image for builds and tests
Avoid repeating the machine updates and deps installation at every stage,
just reuse the docker image

Registered images are at:
  https://gitlab.freedesktop.org/libfprint/libfprint/container_registry
2019-12-04 14:59:03 +00:00
Benjamin Berg
ae285e790d tests: Fix image writing on big endian
The code tried to only write the RGB bytes of FORMAT_RGB24, however, the
in-memory layout is different on big-endian which would result in the
wrong bytes being written.

Fix this by simply also writing the byte we do not care about.
2019-12-04 13:23:08 +01:00
Marco Trevisan (Treviño)
1e2f19ea3d fpi-ssm: Mark a fpi-ssm completed on delay 2019-12-03 18:28:48 +01:00
Marco Trevisan (Treviño)
b0effae990 fpi-ssm: Bug on handler set to a NULL function
We would crash otherwise, while this is quite obvious there was no code
enforcing this.
2019-12-03 18:28:48 +01:00
Marco Trevisan (Treviño)
ff67bf5a16 fpi-ssm: Make delayed actions cancellable
Add a GCancellable parameter to fpi_ssm_nex_state_delayed and
fpi_ssm_jump_to_state_delayed() so that it's possible to cancel an action
from the caller and in case the driver wants to cancel a delayed operation
when a device action has been cancelled.
2019-12-03 18:28:48 +01:00
Marco Trevisan (Treviño)
bac6382f67 drivers: Use SSM delayed actions when possible 2019-12-03 17:31:22 +01:00
Marco Trevisan (Treviño)
e12978f402 fpi-ssm: Clarify the ownership of error in fpi_ssm_mark_failed 2019-12-03 17:31:22 +01:00
Marco Trevisan (Treviño)
1ba95db379 drivers: Use fpi_ssm_next_state_delayed instead of custom callbacks
As per this fpi_ssm_next_state_timeout_cb can be removed
2019-12-03 17:31:22 +01:00
Marco Trevisan (Treviño)
7ec2df2405 fpi-ssm: Add possibility to jump to a state (or next one) with delay
This allows to have an automatic cleanup of the timeout source when the
the callback is reached and to avoid to do further state changes in the
middle.
2019-12-03 17:31:22 +01:00
Marco Trevisan (Treviño)
3ed73aa17c fpi-device: Make possible to set a DestroyNotify for timeout data
Since GSource data can be automatically cleaned up on source destruction, we
can mimic this for the devices timeout easily as well.

Add an extra parameter, and let's use this cocci file to adapt all the
drivers like magic:

	@@
	expression e1, e2, e3, e4;
	@@
	fpi_device_add_timeout (e1, e2, e3, e4
	+  , NULL
  	)
2019-12-03 17:31:22 +01:00
Marco Trevisan (Treviño)
0241617713 fpi-ssm: Also bug-on negative state value
Being an integer, anything could happen.
2019-12-03 17:31:22 +01:00
Marco Trevisan (Treviño)
20a52593eb vfs301: Use a transfer autopointer to cleanup it on sync submission
Partially revert commit a855c0cc7, since the driver uses a sync transfer
and in such case the caller still keeps the ownership.
2019-12-03 13:58:42 +00:00
Marco Trevisan (Treviño)
42db16364d synaptics: Close the usb device if reset failed
If reseting the device failed, we still need to close the usb device before
returning.
2019-12-03 13:58:42 +00:00
Marco Trevisan (Treviño)
ee606ae49e synaptics: Use an autoptr to handle the FpiUsbTransfer sync transfers
When using fpi_usb_transfer_submit_sync we still need to unref the transfer
once done with it, so let's use an auto pointer so we free it also on
errors and early returns without having to handle this manually.
2019-12-03 13:58:42 +00:00
Benjamin Berg
f9b2c7f9c3 virtual-image: Fix driver reading insufficient data
In rare occasions it could happen that the driver was reading
insufficient data. Fix this by using g_input_stream_read_all_async
which will ensure that incomplete data will not be misinterpreted.

This fixes rare test failures seen in fprintd.
2019-12-02 17:04:05 +01:00
Benjamin Berg
4115ae7ced Fix indentation issues using newer uncrustify
Seems like the older uncrustify versions did not find these indentation
issues. Fix them.

Old versions of uncrustify will leave things as is, so this is not a
problem if developers are using an old version of uncrustify.
2019-12-02 17:04:05 +01:00
Benjamin Berg
8cc0fd321f assembling: Use fixed point for image assembly
Using floating point causes architecture dependent results due to
accuracy/rounding differences. It is not hard to switch to fixed point,
and while this does cause quite different rounding errors, the
difference is small.

Fixes: #200
2019-11-28 20:41:45 +00:00
Benjamin Berg
a7541b1f76 tests: Fix endianness issue in test suite
The test suite needs to compare greyscale images and was picking an
undefined byte in the pixel data on big-endian. Select a byte that works
on any endian instead.

See: #200
2019-11-28 20:41:45 +00:00
Marco Trevisan (Treviño)
b9ff75c4e9 fp-print: Set the aligned_data as the data used by the cleanup function
g_variant_new_from_data() allows to destroy some other user_data passed as
parameter that might be different from the aligned_data itself.

But since in this case they match, pass it to be set as g_free parameter
or it won't be free'd.
2019-11-28 21:30:17 +01:00
Marco Trevisan (Treviño)
4447a0d183 ci: Add a test case where we run tests with valgrind 2019-11-27 21:40:44 +01:00
Marco Trevisan (Treviño)
545af23536 tests: Use a loop for generating drivers tests and use suites
So we can just run drivers tests with --suite=drivers
2019-11-27 21:40:44 +01:00
Marco Trevisan (Treviño)
db905a2048 fp-device: Use g_clear_error instead of check + free 2019-11-27 21:40:44 +01:00
Marco Trevisan (Treviño)
712853d1e3 fp-device: Mark user data in FpEnrollProgress as transfer none
The data has its own DestroyNotify set, so while no generic DestroyNotify
exists for generic data, let's make it clear.
2019-11-27 21:40:44 +01:00
Marco Trevisan (Treviño)
c6298ede72 fp-device: Unref the print once we've notified the progress
When we notify the enroll progress with a print, this needs to be unreffed
once we're done, but this only was happening in case of error.

Since it's not up to the callback function to free it, let's do it at the
end of the function.

As per this, clarify the docs for FpEnrollProgress marking it as transfer
none.
2019-11-27 21:40:44 +01:00
Marco Trevisan (Treviño)
b1d99e7608 fp-device: Use an autopointer and steal the print when passed
Make it clearer that we're stealing the print when passing it away, instead
of just doing this silently.
2019-11-27 21:40:44 +01:00
Marco Trevisan (Treviño)
5927a205e3 virtual-image: Also unref the object when closing a the stream
While a stream is closed when completely unreffed, the other way around
isn't true, so always unref the object.
2019-11-27 21:40:44 +01:00
Marco Trevisan (Treviño)
8c05f3b78c fp-print: Unref print data and get static strings when deserializing 2019-11-27 21:40:44 +01:00
Marco Trevisan (Treviño)
92db82e3d4 fp-print: Assert the prints aren't set when initialized 2019-11-27 21:40:44 +01:00
Marco Trevisan (Treviño)
f6f689f9cd fp-print: Unref the prints on finalize 2019-11-27 21:40:44 +01:00
Marco Trevisan (Treviño)
5dc3edf07c fp-context: Run dispose on the usb context to deal with circular refs
Ensure that we dispose the USB context before unreffing it, so that it will
release any reference it has and destroy the internal libusb context.
2019-11-27 21:40:44 +01:00
Marco Trevisan (Treviño)
71625ec1cf fp-device: Unref the usb device on finalize
Each device adds a ref to the underlying usb device, but it doesn't remove
the reference on finalization.

So clear the object to fix the leak
2019-11-27 21:40:44 +01:00
Marco Trevisan (Treviño)
c9216cf96c tests: Add setup mode to run tests using valgrind
In such case we need to ignore the python errors, so including a suppression
file when using --setup=valgrind.
2019-11-27 21:40:43 +01:00
Marco Trevisan (Treviño)
53713c0098 tests: Add 'gdb' setup to run tests using gdb
When using --setup=gdb the tests will be running using gdb, however this
as per meson limitation allows only running a test when using verbose mode.
2019-11-27 21:40:43 +01:00
Marco Trevisan (Treviño)
222c33ec32 virtual-image: Re-run the test using the defined wrapper if any
In case a LIBFPRINT_TEST_WRAPPER is defined, execute again the script using
the same python processor but using the passed wrapper command.
2019-11-27 21:40:43 +01:00
Marco Trevisan (Treviño)
19a50cfdc3 umockdev-test: Make possible to use a wrapper to run tests
Support LIBFPRINT_TEST_WRAPPER env variable to run tests with a wrapper.
2019-11-27 21:40:43 +01:00
Marco Trevisan (Treviño)
9892eb1c03 fpi-ssm: Make clearer that data is unused in fpi_ssm_usb_transfer_cb 2019-11-27 21:02:20 +01:00
Marco Trevisan (Treviño)
587131a6bd drivers: Use more fpi_ssm_usb_transfer_cb when possible
Replace all the transfer callbacks where we just switch to the next state or
fail with fpi_ssm_usb_transfer_cb.
2019-11-27 21:02:20 +01:00
Marco Trevisan (Treviño)
65d0d5e3e0 fpi-ssm: Add a usb transfer callback with data as weak pointer
Allow to pass a double-pointer to be nullified as the transfer data in order
to mark it as NULL when the transfer is done.

This is useful if we're keeping the transfer around in order to check that
no one is currently running.
2019-11-27 21:02:19 +01:00
Marco Trevisan (Treviño)
2642fc6560 fpi-usb-transfer: Take ownership of the transfer when submitting it
When a transfer is completed, we automatically unref it since we can't
consider it valid anymore since this point.

Update the drivers not to free the transfer after submitting anymore.
2019-11-27 21:02:19 +01:00
Marco Trevisan (Treviño)
a855c0cc79 fpi-ssm: Take ownership of the SSM when completing it
When a machine is completed, we automatically free it since we can't
consider it valid anymore since this point.

Update the drivers not to free the SSM on completion callback anymore.
2019-11-27 21:02:19 +01:00
Marco Trevisan (Treviño)
876924df6a examples: Handle the cases where the print date is not set 2019-11-27 19:14:35 +01:00
Marco Trevisan (Treviño)
519b5acc91 synaptics: Initialize user_id autoptr to NULL 2019-11-27 18:54:21 +01:00
Marco Trevisan (Treviño)
e812653acd synaptics: Use GDate getters to retrieve the DMY values
As per commit 201b5a961 we use g_date_copy() to copy the date, however the
GLib implementation is done assuming that the GDate getters are always used
as the copy function doesn't preserve the original format of the date
(whether is using julian days or dmy), and the synaptics driver access to
the dmy values directly, without using the getter that would recompute the
proper values.
Causing a read error of unset values.

So, to avoid this, just use the g_date_get_* getters to retrieve the day
month and year for for defining the print enroll id.
2019-11-27 18:54:21 +01:00
Marco Trevisan (Treviño)
1b23f0efe1 drivers: Use clearer messages using parameters 2019-11-26 12:18:57 +00:00
Marco Trevisan (Treviño)
f6559ba8b1 fp-device: Support variadic arguments to error functions
Make possible to generate a formatted message when creating an error from
a device, without having save it first.
2019-11-26 12:18:57 +00:00
Marco Trevisan (Treviño)
3b72b925b0 gitlab-ci: Check indentation in an initial check-source stage 2019-11-25 19:08:31 +01:00
Marco Trevisan (Treviño)
15d218a112 fpi-log: Set fp_error as equal to g_critical 2019-11-25 18:59:46 +01:00
Marco Trevisan (Treviño)
0a08a24896 fpi-ssm: Remove any reference to fpi_timeout_add()
This doesn't exist anymore, while fpi_device_add_timeout does exists.
2019-11-25 18:59:46 +01:00
Marco Trevisan (Treviño)
cca6d3b04b fp-image-device: Use a GObject signal to notify image state changed
This is more GObject-friendly and we have the automatic call of the vfunc if
one is set.
2019-11-25 18:59:46 +01:00
Marco Trevisan (Treviño)
be367988ae fp-image-device: Add private "fp-image-device-state" property
In this way drivers may get this without having to keep a copy of it
2019-11-25 18:59:46 +01:00
Marco Trevisan (Treviño)
ea4da08af0 fp-image-device: Reactivate in idle on deactivation completed
This is the same logic we apply to fp-device by default: any completed
action should trigger the subsequent one when it is finished.
So in case we want reactivate after a deactivation, let's do it in an idle,
after removing the current pending timeout.
2019-11-25 18:59:46 +01:00
Marco Trevisan (Treviño)
60ad1ab9e3 fp-image-device: Clear the pending activation timeout on finalize 2019-11-25 18:59:46 +01:00
Marco Trevisan (Treviño)
201b5a9614 fp-print: Use g_date_copy
As per previous commit we depend on glib 2.56, we can use this utility
function as well.
2019-11-25 18:59:46 +01:00
Marco Trevisan (Treviño)
8b270141f3 image-device: Use g_clear_handle_id for timeouts
As per this depend on glib 2.56: it has been released almost 2 years ago,
I suppose we're fine with that.
2019-11-25 18:59:46 +01:00
Marco Trevisan (Treviño)
ceb62d7617 meson: Avoid repeating the needed glib version multiple times
Just define once and modify its syntax when needed.
Use a more verbose definition for the min/max version (instead of just
join the split version) so that in case we may depend on a specifc glib
micro release during development.
2019-11-25 18:59:46 +01:00
Marco Trevisan (Treviño)
099fa9f005 meson: Use preferred syntax everywhere
Meson files are normally using 4-spaces to indent and functions use first
parameter on the same line while others at next indentation level, not
following the parenthesis indentation.

So adapt libfprint to follow the meson standard.
2019-11-25 18:59:46 +01:00
Marco Trevisan (Treviño)
dd7d1baece meson: Use multiline-array for default dirvers listing
It will make reviews and diffs nicer to handle when adding new drivers.
2019-11-25 18:59:46 +01:00
Marco Trevisan (Treviño)
d8efa336e5 fpi-ssm, fp-device: Add missing copyright 2019-11-25 18:59:46 +01:00
Marco Trevisan (Treviño)
76dd4066f3 verify: Ensure we set set the autoptr value to NULL at definition 2019-11-25 18:59:46 +01:00
Benjamin Berg
9b48864c5b print: Ensure xyt struct is not leaked during deserialization
In the unlikely event of an error, the variable may have been leaked.
Fix this by using g_autoptr combined with a g_steal_pointer.
2019-11-25 18:46:14 +01:00
Benjamin Berg
14a41bdd48 print: Free temporary col variable
The variable was leaked during serialization. Free it.
2019-11-25 18:46:14 +01:00
Benjamin Berg
25bc89a4f5 image-device: Remove unused fpi_device_get_current_action call
There is a later call in the function which is sufficient. Simply remove
the first call.
2019-11-25 18:46:14 +01:00
Benjamin Berg
2f0824ab88 upeksonly: Add default clauses to switch statements
This effectively only annotates the code to make it clear that variables
set in the switch are always initialized.
2019-11-25 18:46:14 +01:00
Benjamin Berg
8ba6f4dad2 synaptics: Add an explicit assert on the response
The response must be non-NULL in the function. Add an explicit assert to
appease to static code analysis tools.
2019-11-25 18:46:14 +01:00
Benjamin Berg
ada5d488fa synaptics: Correctly unref pointer array
The pointer arrays were unref'ed using g_ptr_array_free rather than
g_ptr_array_unref from g_clear_pointer. Switch to the correct function.
2019-11-25 18:46:14 +01:00
Benjamin Berg
b16245ad58 elan: Fix switch in change_state
The switch in change_state had a useless break and a useless if clause.
Remove both.
2019-11-25 18:46:14 +01:00
Benjamin Berg
8b28133bee elan: Fix potential leak of dark frame
Dark frames would be leaked, add an explicit free to avoid this.
2019-11-25 18:46:14 +01:00
Benjamin Berg
7a4dd96406 udev-rules: Remove debug spew from udev rules
Some debug output was ending up inside the udev rules. Remove it again.
2019-11-22 17:07:56 +01:00
67 changed files with 1369 additions and 886 deletions

View File

@@ -1,35 +1,30 @@
image: fedora:rawhide
image: registry.freedesktop.org/libfprint/libfprint/master:v1
stages:
- check-source
- build
- test
- flatpack
variables:
DEPENDENCIES: libgusb-devel glib2-devel nss-devel pixman-devel systemd meson gtk-doc
gcc gcc-c++ glibc-devel libX11-devel libXv-devel gtk3-devel flatpak-builder
gobject-introspection-devel python3-cairo python3-gobject umockdev
BUNDLE: "org.freedesktop.libfprint.Demo.flatpak"
LAST_ABI_BREAK: "056ea541ddc97f5806cffbd99a12dc87e4da3546"
.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=$driver . _build
- meson --werror -Ddrivers=$driver . _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
- meson --werror -Ddrivers=all . _build
- ninja -C _build
- ninja -C _build install
.build_template: &check_abi
script:
- dnf update -y --nogpgcheck && dnf install -y --nogpgcheck $DEPENDENCIES doxygen libabigail git
- ./.ci/check-abi ${LAST_ABI_BREAK} $(git rev-parse HEAD)
build:
@@ -43,15 +38,20 @@ build:
test:
stage: test
script:
- dnf update -y --nogpgcheck && dnf install -y --nogpgcheck $DEPENDENCIES
- meson -Ddrivers=all . _build
- meson --werror -Ddrivers=all . _build
- ninja -C _build
- meson test -C _build --verbose --no-stdsplit
test_indent:
test_valgrind:
stage: test
script:
- dnf update -y --nogpgcheck && dnf install -y --nogpgcheck git uncrustify
- meson -Ddrivers=all . _build
- ninja -C _build
- meson test -C _build --verbose --no-stdsplit --setup=valgrind
test_indent:
stage: check-source
script:
- scripts/uncrustify.sh --check
.flatpak_script_template: &flatpak_script
@@ -77,7 +77,7 @@ test_indent:
<<: *flatpak_script
<<: *flatpak_artifacts
flatpak master:
.flatpak_master_template: &flatpak_master
image: registry.gitlab.gnome.org/gnome/gnome-runtime-images/gnome:3.32
stage: flatpack
variables:
@@ -87,3 +87,17 @@ flatpak master:
FLATPAK_MODULE: "libfprint"
DBUS_ID: "org.freedesktop.libfprint.Demo"
<<: *flatpak
flatpak-auto master:
<<: *flatpak_master
when: always
only:
- tags
- master
flatpak-manual master:
<<: *flatpak_master
when: manual
except:
- tags
- master

36
.gitlab-ci/Dockerfile Normal file
View File

@@ -0,0 +1,36 @@
# Rebuild and push with
#
# cd .gitlab-ci/
# docker build --no-cache -t registry.freedesktop.org/libfprint/libfprint/master:v1 .
# docker push registry.freedesktop.org/libfprint/libfprint/master:v1
#
FROM fedora:rawhide
RUN dnf -y update && dnf -y upgrade && \
dnf -y install \
doxygen \
flatpak-builder \
gcc \
gcc-c++ \
git \
glib2-devel \
glibc-devel \
gobject-introspection-devel \
gtk-doc \
gtk3-devel \
libabigail \
libgusb-devel \
libX11-devel \
libXv-devel \
meson \
nss-devel \
pixman-devel \
python3-cairo \
python3-gobject \
systemd \
umockdev \
uncrustify \
valgrind \
&& \
dnf clean all

View File

@@ -22,9 +22,11 @@
#include <gtk/gtk.h>
#include <libfprint/fprint.h>
typedef GtkApplication LibfprintDemo;
typedef GtkApplicationClass LibfprintDemoClass;
struct _LibfprintDemo
{
GtkApplication parent;
};
G_DECLARE_FINAL_TYPE (LibfprintDemo, libfprint_demo, FP, DEMO, GtkApplication)
G_DEFINE_TYPE (LibfprintDemo, libfprint_demo, GTK_TYPE_APPLICATION)
typedef enum {
@@ -33,7 +35,7 @@ typedef enum {
IMAGE_DISPLAY_BINARY = 1 << 1
} ImageDisplayFlags;
typedef struct
struct _LibfprintDemoWindow
{
GtkApplicationWindow parent_instance;
@@ -52,10 +54,9 @@ typedef struct
FpImage *img;
ImageDisplayFlags img_flags;
} LibfprintDemoWindow;
typedef GtkApplicationWindowClass LibfprintDemoWindowClass;
};
G_DECLARE_FINAL_TYPE (LibfprintDemoWindow, libfprint_demo_window, FP, DEMO_WINDOW, GtkApplicationWindow)
G_DEFINE_TYPE (LibfprintDemoWindow, libfprint_demo_window, GTK_TYPE_APPLICATION_WINDOW)
typedef enum {

View File

@@ -1,21 +1,21 @@
gtk_test_resources = gnome.compile_resources('gtk-test-resources', 'gtk-libfprint-test.gresource.xml',
source_dir : '.',
c_name : 'gtk_test')
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', 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)
[ 'gtk-libfprint-test.c', gtk_test_resources ],
dependencies: [ libfprint_dep, gtk_dep ],
include_directories: [
root_inc,
],
c_args: '-DPACKAGE_VERSION="' + meson.project_version() + '"',
install: true,
install_dir: bindir)
appdata = 'org.freedesktop.libfprint.Demo.appdata.xml'
install_data(appdata,

View File

@@ -211,11 +211,15 @@ fpi_print_bz3_match
FpiSsmCompletedCallback
FpiSsmHandlerCallback
fpi_ssm_new
fpi_ssm_new_full
fpi_ssm_free
fpi_ssm_start
fpi_ssm_start_subsm
fpi_ssm_next_state
fpi_ssm_next_state_delayed
fpi_ssm_jump_to_state
fpi_ssm_jump_to_state_delayed
fpi_ssm_cancel_delayed_state_change
fpi_ssm_mark_completed
fpi_ssm_mark_failed
fpi_ssm_set_data

View File

@@ -1,14 +1,14 @@
subdir('xml')
private_headers = [
'config.h',
'nbis-helpers.h',
'fprint.h',
'fp_internal.h',
'config.h',
'nbis-helpers.h',
'fprint.h',
'fp_internal.h',
# Subdirectories to ignore
'drivers',
'nbis',
# Subdirectories to ignore
'drivers',
'nbis',
]
html_images = [
@@ -25,20 +25,20 @@ 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: [
#'--rebuild-sections',
'--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)
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: [
#'--rebuild-sections',
'--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)

View File

@@ -7,4 +7,6 @@ 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)
configure_file(input: 'gtkdocentities.ent.in',
output: 'gtkdocentities.ent',
configuration: ent_conf)

View File

@@ -6,10 +6,10 @@
int main (int argc, char **argv)
{
FpContext *ctx;
FpContext *ctx;
ctx = fp_context_new ();
g_object_unref (ctx);
ctx = fp_context_new ();
g_object_unref (ctx);
return 0;
return 0;
}

View File

@@ -153,14 +153,19 @@ on_list_completed (FpDevice *dev,
for (i = 0; i < prints->len; ++i)
{
FpPrint * print = prints->pdata[i];
const GDate *date = fp_print_get_enroll_date (print);
g_date_strftime (buf, G_N_ELEMENTS (buf), "%Y-%m-%d",
fp_print_get_enroll_date (print));
g_print ("[%d] Print of %s finger for username %s, enrolled "
"on %s. Description: %s\n", i + 1,
g_print ("[%d] Print of %s finger for username %s", i + 1,
finger_to_string (fp_print_get_finger (print)),
fp_print_get_username (print), buf,
fp_print_get_description (print));
fp_print_get_username (print));
if (date)
{
g_date_strftime (buf, G_N_ELEMENTS (buf), "%Y-%m-%d\0", date);
g_print (", enrolled on %s", buf);
}
g_print (". Description: %s\n", fp_print_get_description (print));
}
if (prints->len)

View File

@@ -2,18 +2,16 @@
examples = [ 'enroll', 'verify', 'manage-prints' ]
foreach example: examples
executable(example,
[example + '.c', 'storage.c', 'utilities.c'],
dependencies: [libfprint_dep, glib_dep],
include_directories: [
root_inc,
],
c_args: common_cflags)
[ example + '.c', 'storage.c', 'utilities.c' ],
dependencies: [ libfprint_dep, glib_dep ],
include_directories: [
root_inc,
])
endforeach
executable('cpp-test',
'cpp-test.cpp',
dependencies: libfprint_dep,
include_directories: [
root_inc,
],
c_args: common_cflags)
'cpp-test.cpp',
dependencies: libfprint_dep,
include_directories: [
root_inc,
])

View File

@@ -20,6 +20,7 @@
*/
#include <libfprint/fprint.h>
#include "storage.h"
#include <errno.h>
#include <stdio.h>
@@ -57,7 +58,7 @@ load_data (void)
GVariantDict *res;
GVariant *var;
g_autofree gchar *contents = NULL;
gssize length = 0;
gsize length = 0;
if (!g_file_get_contents (STORAGE_FILE, &contents, &length, NULL))
{

View File

@@ -127,9 +127,14 @@ on_list_completed (FpDevice *dev, GAsyncResult *res, gpointer user_data)
if (fp_print_get_finger (print) == verify_data->finger &&
g_strcmp0 (fp_print_get_username (print), g_get_user_name ()) == 0)
{
if (!verify_print ||
(g_date_compare (fp_print_get_enroll_date (print),
fp_print_get_enroll_date (verify_print)) >= 0))
const GDate *verify_print_date = NULL;
const GDate *print_date = fp_print_get_enroll_date (print);
if (verify_print)
verify_print_date = fp_print_get_enroll_date (verify_print);
if (!verify_print || !print_date || !verify_print_date ||
g_date_compare (print_date, verify_print_date) >= 0)
verify_print = print;
}
}
@@ -182,7 +187,7 @@ start_verification (FpDevice *dev, VerifyData *verify_data)
{
g_print ("Loading previously enrolled %s finger data...\n",
finger_to_string (verify_data->finger));
g_autoptr(FpPrint) verify_print;
g_autoptr(FpPrint) verify_print = NULL;
verify_print = print_data_load (dev, verify_data->finger);

View File

@@ -116,18 +116,6 @@ stub_capture_stop_cb (FpImageDevice *dev, GError *error,
}
}
/* check that read succeeded but ignore all data */
static void
generic_ignore_data_cb (FpiUsbTransfer *transfer, FpDevice *device,
gpointer user_data, GError *error)
{
if (error)
fpi_ssm_mark_failed (transfer->ssm, error);
else
fpi_ssm_next_state (transfer->ssm);
}
static void
generic_write_regv_cb (FpImageDevice *dev, GError *error,
void *user_data)
@@ -154,8 +142,7 @@ generic_read_ignore_data (FpiSsm *ssm, FpDevice *dev,
transfer->ssm = ssm;
transfer->short_is_error = TRUE;
fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
generic_ignore_data_cb, NULL);
fpi_usb_transfer_unref (transfer);
fpi_ssm_usb_transfer_cb, NULL);
}
/****** FINGER PRESENCE DETECTION ******/
@@ -238,7 +225,6 @@ finger_det_reqs_cb (FpImageDevice *dev, GError *error,
transfer->short_is_error = TRUE;
fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
finger_det_data_cb, NULL);
fpi_usb_transfer_unref (transfer);
}
static void
@@ -683,7 +669,6 @@ capture_run_state (FpiSsm *ssm, FpDevice *_dev)
transfer->short_is_error = TRUE;
fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
capture_read_strip_cb, NULL);
fpi_usb_transfer_unref (transfer);
break;
}
;
@@ -710,7 +695,6 @@ capture_sm_complete (FpiSsm *ssm, FpDevice *_dev, GError *error)
{
start_finger_detection (dev);
}
fpi_ssm_free (ssm);
}
static void
@@ -774,7 +758,6 @@ activate_sm_complete (FpiSsm *ssm, FpDevice *_dev, GError *error)
if (!error)
start_finger_detection (dev);
fpi_ssm_free (ssm);
}
static void

View File

@@ -126,7 +126,6 @@ read_regs_rq_cb (FpImageDevice *dev, GError *error, void *user_data)
fpi_usb_transfer_fill_bulk (transfer, EP_IN, READ_REGS_LEN);
fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
read_regs_data_cb, rdata);
fpi_usb_transfer_unref (transfer);
}
static void
@@ -183,19 +182,6 @@ generic_write_regv_cb (FpImageDevice *dev, GError *error,
fpi_ssm_mark_failed (ssm, error);
}
/* check that read succeeded but ignore all data */
static void
generic_ignore_data_cb (FpiUsbTransfer *transfer, FpDevice *dev,
gpointer user_data, GError *error)
{
FpiSsm *ssm = transfer->ssm;
if (error)
fpi_ssm_mark_failed (ssm, error);
else
fpi_ssm_next_state (ssm);
}
/* read the specified number of bytes from the IN endpoint but throw them
* away, then increment the SSM */
static void
@@ -209,8 +195,7 @@ generic_read_ignore_data (FpiSsm *ssm, FpDevice *dev,
transfer->short_is_error = TRUE;
fpi_usb_transfer_fill_bulk (transfer, EP_IN, bytes);
fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
generic_ignore_data_cb, NULL);
fpi_usb_transfer_unref (transfer);
fpi_ssm_usb_transfer_cb, NULL);
}
/****** IMAGE PROCESSING ******/
@@ -315,7 +300,6 @@ finger_det_reqs_cb (FpImageDevice *dev, GError *error,
fpi_usb_transfer_fill_bulk (transfer, EP_IN, FINGER_DETECTION_LEN);
fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
finger_det_data_cb, NULL);
fpi_usb_transfer_unref (transfer);
}
static void
@@ -547,7 +531,6 @@ capture_run_state (FpiSsm *ssm, FpDevice *device)
fpi_usb_transfer_fill_bulk (transfer, EP_IN, STRIP_CAPTURE_LEN);
fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
capture_read_strip_cb, NULL);
fpi_usb_transfer_unref (transfer);
break;
}
}
@@ -575,7 +558,6 @@ capture_sm_complete (FpiSsm *ssm, FpDevice *_dev, GError *error)
{
start_finger_detection (dev);
}
fpi_ssm_free (ssm);
}
static void
@@ -704,7 +686,7 @@ enum activate_states {
ACTIVATE_NUM_STATES,
};
void
static void
activate_read_regs_cb (FpImageDevice *dev, GError *error,
unsigned char *regs, void *user_data)
{
@@ -806,7 +788,6 @@ activate_sm_complete (FpiSsm *ssm, FpDevice *dev, GError *error)
if (!error)
start_finger_detection (FP_IMAGE_DEVICE (dev));
fpi_ssm_free (ssm);
}
static void

View File

@@ -134,7 +134,6 @@ finger_det_reqs_cb (FpiUsbTransfer *t, FpDevice *device,
fpi_usb_transfer_fill_bulk (transfer, EP_IN, AES2550_EP_IN_BUF_SIZE);
fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
finger_det_data_cb, NULL);
fpi_usb_transfer_unref (transfer);
}
static void
@@ -157,7 +156,6 @@ start_finger_detection (FpImageDevice *dev)
sizeof (finger_det_reqs), NULL);
fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
finger_det_reqs_cb, NULL);
fpi_usb_transfer_unref (transfer);
}
/****** CAPTURE ******/
@@ -218,16 +216,6 @@ process_strip_data (FpiSsm *ssm, FpImageDevice *dev,
return TRUE;
}
static void
capture_reqs_cb (FpiUsbTransfer *transfer, FpDevice *device,
gpointer user_data, GError *error)
{
if (!error)
fpi_ssm_next_state (transfer->ssm);
else
fpi_ssm_mark_failed (transfer->ssm, error);
}
static void
capture_set_idle_reqs_cb (FpiUsbTransfer *transfer,
FpDevice *device, gpointer user_data,
@@ -334,8 +322,7 @@ capture_run_state (FpiSsm *ssm, FpDevice *dev)
transfer->ssm = ssm;
transfer->short_is_error = TRUE;
fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
capture_reqs_cb, NULL);
fpi_usb_transfer_unref (transfer);
fpi_ssm_usb_transfer_cb, NULL);
}
break;
@@ -347,7 +334,6 @@ capture_run_state (FpiSsm *ssm, FpDevice *dev)
transfer->ssm = ssm;
fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
capture_read_data_cb, NULL);
fpi_usb_transfer_unref (transfer);
}
break;
@@ -363,7 +349,6 @@ capture_run_state (FpiSsm *ssm, FpDevice *dev)
transfer->short_is_error = TRUE;
fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
capture_set_idle_reqs_cb, NULL);
fpi_usb_transfer_unref (transfer);
}
break;
}
@@ -391,7 +376,6 @@ capture_sm_complete (FpiSsm *ssm, FpDevice *_dev, GError *error)
{
start_finger_detection (dev);
}
fpi_ssm_free (ssm);
}
static void
@@ -436,36 +420,13 @@ enum activate_states {
ACTIVATE_NUM_STATES,
};
static void
init_reqs_cb (FpiUsbTransfer *transfer, FpDevice *device,
gpointer user_data, GError *error)
{
if (!error)
fpi_ssm_next_state (transfer->ssm);
else
fpi_ssm_mark_failed (transfer->ssm, error);
}
static void
init_read_data_cb (FpiUsbTransfer *transfer, FpDevice *device,
gpointer user_data, GError *error)
{
if (!error)
fpi_ssm_next_state (transfer->ssm);
else
fpi_ssm_mark_failed (transfer->ssm, error);
}
/* TODO: use calibration table, datasheet is rather terse on that
* need more info for implementation */
static void
calibrate_read_data_cb (FpiUsbTransfer *transfer, FpDevice *device,
gpointer user_data, GError *error)
{
if (!error)
fpi_ssm_next_state (transfer->ssm);
else
fpi_ssm_mark_failed (transfer->ssm, error);
fpi_ssm_usb_transfer_cb (transfer, device, user_data, error);
}
static void
@@ -482,8 +443,7 @@ activate_run_state (FpiSsm *ssm, FpDevice *dev)
transfer->ssm = ssm;
transfer->short_is_error = TRUE;
fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
init_reqs_cb, NULL);
fpi_usb_transfer_unref (transfer);
fpi_ssm_usb_transfer_cb, NULL);
}
break;
@@ -494,8 +454,7 @@ activate_run_state (FpiSsm *ssm, FpDevice *dev)
fpi_usb_transfer_fill_bulk (transfer, EP_IN, AES2550_EP_IN_BUF_SIZE);
transfer->ssm = ssm;
fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
init_read_data_cb, NULL);
fpi_usb_transfer_unref (transfer);
fpi_ssm_usb_transfer_cb, NULL);
}
break;
@@ -509,8 +468,7 @@ activate_run_state (FpiSsm *ssm, FpDevice *dev)
transfer->ssm = ssm;
transfer->short_is_error = TRUE;
fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
init_reqs_cb, NULL);
fpi_usb_transfer_unref (transfer);
fpi_ssm_usb_transfer_cb, NULL);
}
break;
@@ -522,7 +480,6 @@ activate_run_state (FpiSsm *ssm, FpDevice *dev)
transfer->ssm = ssm;
fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
calibrate_read_data_cb, NULL);
fpi_usb_transfer_unref (transfer);
}
break;
}
@@ -537,7 +494,6 @@ activate_sm_complete (FpiSsm *ssm, FpDevice *_dev, GError *error)
if (!error)
start_finger_detection (dev);
fpi_ssm_free (ssm);
}
static void

View File

@@ -142,7 +142,6 @@ do_capture (FpImageDevice *dev)
fpi_usb_transfer_submit (priv->img_trf, 0,
fpi_device_get_cancellable (FP_DEVICE (dev)),
img_cb, NULL);
fpi_usb_transfer_unref (priv->img_trf);
}
static void

View File

@@ -88,7 +88,6 @@ do_write_regv (FpImageDevice *dev, struct write_regv_data *wdata, int upper_boun
transfer->short_is_error = TRUE;
fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
write_regv_trf_complete, wdata);
fpi_usb_transfer_unref (transfer);
}
/* write the next batch of registers to be written, or if there are no more,

View File

@@ -68,7 +68,6 @@ aesX660_send_cmd_timeout (FpiSsm *ssm,
cmd_len, NULL);
transfer->ssm = ssm;
fpi_usb_transfer_submit (transfer, timeout, NULL, callback, NULL);
fpi_usb_transfer_unref (transfer);
}
static void
@@ -100,17 +99,6 @@ aesX660_read_response (FpiSsm *ssm,
transfer->ssm = ssm;
transfer->short_is_error = short_is_error;
fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, cancel, callback, NULL);
fpi_usb_transfer_unref (transfer);
}
static void
aesX660_send_cmd_cb (FpiUsbTransfer *transfer, FpDevice *device,
gpointer user_data, GError *error)
{
if (!error)
fpi_ssm_next_state (transfer->ssm);
else
fpi_ssm_mark_failed (transfer->ssm, error);
}
static void
@@ -131,7 +119,9 @@ aesX660_read_calibrate_data_cb (FpiUsbTransfer *transfer,
fp_dbg ("Bogus calibrate response: %.2x\n", data[0]);
fpi_ssm_mark_failed (transfer->ssm,
fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
"Bogus calibrate response"));
"Bogus calibrate "
"response: %.2x",
data[0]));
return;
}
@@ -175,7 +165,8 @@ finger_det_read_fd_data_cb (FpiUsbTransfer *transfer,
fp_dbg ("Bogus FD response: %.2x\n", data[0]);
fpi_ssm_mark_failed (transfer->ssm,
fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
"Bogus FD response"));
"Bogus FD response %.2x",
data[0]));
return;
}
@@ -212,7 +203,6 @@ finger_det_sm_complete (FpiSsm *ssm, FpDevice *_dev, GError *error)
fp_dbg ("Finger detection completed");
fpi_image_device_report_finger_status (dev, TRUE);
fpi_ssm_free (ssm);
if (priv->deactivating)
{
@@ -238,12 +228,12 @@ finger_det_run_state (FpiSsm *ssm, FpDevice *dev)
{
case FINGER_DET_SEND_LED_CMD:
aesX660_send_cmd (ssm, dev, led_blink_cmd, sizeof (led_blink_cmd),
aesX660_send_cmd_cb);
fpi_ssm_usb_transfer_cb);
break;
case FINGER_DET_SEND_FD_CMD:
aesX660_send_cmd_timeout (ssm, dev, wait_for_finger_cmd, sizeof (wait_for_finger_cmd),
aesX660_send_cmd_cb, 0);
fpi_ssm_usb_transfer_cb, 0);
break;
case FINGER_DET_READ_FD_DATA:
@@ -433,14 +423,14 @@ capture_run_state (FpiSsm *ssm, FpDevice *_dev)
{
case CAPTURE_SEND_LED_CMD:
aesX660_send_cmd (ssm, _dev, led_solid_cmd, sizeof (led_solid_cmd),
aesX660_send_cmd_cb);
fpi_ssm_usb_transfer_cb);
break;
case CAPTURE_SEND_CAPTURE_CMD:
g_byte_array_set_size (priv->stripe_packet, 0);
aesX660_send_cmd (ssm, _dev, cls->start_imaging_cmd,
cls->start_imaging_cmd_len,
aesX660_send_cmd_cb);
fpi_ssm_usb_transfer_cb);
break;
case CAPTURE_READ_STRIPE_DATA:
@@ -463,7 +453,6 @@ capture_sm_complete (FpiSsm *ssm, FpDevice *device, GError *error)
FpiDeviceAesX660Private *priv = fpi_device_aes_x660_get_instance_private (self);
fp_dbg ("Capture completed");
fpi_ssm_free (ssm);
if (priv->deactivating)
{
@@ -538,7 +527,8 @@ activate_read_id_cb (FpiUsbTransfer *transfer, FpDevice *device,
fp_dbg ("Bogus read ID response: %.2x\n", data[AESX660_RESPONSE_TYPE_OFFSET]);
fpi_ssm_mark_failed (transfer->ssm,
fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
"Bogus read ID response"));
"Bogus read ID response %.2x",
data[AESX660_RESPONSE_TYPE_OFFSET]));
return;
}
@@ -565,7 +555,8 @@ activate_read_id_cb (FpiUsbTransfer *transfer, FpDevice *device,
fp_dbg ("Failed to init device! init status: %.2x\n", data[7]);
fpi_ssm_mark_failed (transfer->ssm,
fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
"Failed to init device"));
"Failed to init device %.2x",
data[7]));
break;
}
}
@@ -594,7 +585,8 @@ activate_read_init_cb (FpiUsbTransfer *transfer, FpDevice *device,
data[3]);
fpi_ssm_mark_failed (transfer->ssm,
fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
"Bogus read init response"));
"Bogus read init response: "
"%.2x %.2x", data[0], data[3]));
return;
}
priv->init_cmd_idx++;
@@ -623,13 +615,13 @@ activate_run_state (FpiSsm *ssm, FpDevice *_dev)
priv->init_seq_idx = 0;
fp_dbg ("Activate: set idle\n");
aesX660_send_cmd (ssm, _dev, set_idle_cmd, sizeof (set_idle_cmd),
aesX660_send_cmd_cb);
fpi_ssm_usb_transfer_cb);
break;
case ACTIVATE_SEND_READ_ID_CMD:
fp_dbg ("Activate: read ID\n");
aesX660_send_cmd (ssm, _dev, read_id_cmd, sizeof (read_id_cmd),
aesX660_send_cmd_cb);
fpi_ssm_usb_transfer_cb);
break;
case ACTIVATE_READ_ID:
@@ -643,7 +635,7 @@ activate_run_state (FpiSsm *ssm, FpDevice *_dev)
aesX660_send_cmd (ssm, _dev,
priv->init_seq[priv->init_cmd_idx].cmd,
priv->init_seq[priv->init_cmd_idx].len,
aesX660_send_cmd_cb);
fpi_ssm_usb_transfer_cb);
break;
case ACTIVATE_READ_INIT_RESPONSE:
@@ -653,7 +645,7 @@ activate_run_state (FpiSsm *ssm, FpDevice *_dev)
case ACTIVATE_SEND_CALIBRATE_CMD:
aesX660_send_cmd (ssm, _dev, calibrate_cmd, sizeof (calibrate_cmd),
aesX660_send_cmd_cb);
fpi_ssm_usb_transfer_cb);
break;
case ACTIVATE_READ_CALIBRATE_DATA:
@@ -666,7 +658,6 @@ static void
activate_sm_complete (FpiSsm *ssm, FpDevice *_dev, GError *error)
{
fpi_image_device_activate_complete (FP_IMAGE_DEVICE (_dev), error);
fpi_ssm_free (ssm);
if (!error)
start_finger_detection (FP_IMAGE_DEVICE (_dev));

View File

@@ -41,7 +41,7 @@
#include "drivers_api.h"
#include "elan.h"
unsigned char
static unsigned char
elan_get_pixel (struct fpi_frame_asmbl_ctx *ctx,
struct fpi_frame *frame, unsigned int x,
unsigned int y)
@@ -91,7 +91,7 @@ G_DECLARE_FINAL_TYPE (FpiDeviceElan, fpi_device_elan, FPI, DEVICE_ELAN,
FpImageDevice);
G_DEFINE_TYPE (FpiDeviceElan, fpi_device_elan, FP_TYPE_IMAGE_DEVICE);
int
static int
cmp_short (const void *a, const void *b)
{
return (int) (*(short *) a - *(short *) b);
@@ -223,6 +223,7 @@ elan_save_img_frame (FpiDeviceElan *elandev)
{
fp_dbg
("frame darker than background; finger present during calibration?");
g_free (frame);
return -1;
}
@@ -405,7 +406,6 @@ elan_cmd_read (FpiSsm *ssm, FpDevice *dev)
cancellable = fpi_device_get_cancellable (dev);
fpi_usb_transfer_submit (transfer, self->cmd_timeout, cancellable, elan_cmd_cb, NULL);
fpi_usb_transfer_unref (transfer);
}
static void
@@ -448,7 +448,6 @@ elan_run_cmd (FpiSsm *ssm,
cancellable,
elan_cmd_cb,
NULL);
fpi_usb_transfer_unref (transfer);
}
enum stop_capture_states {
@@ -478,7 +477,6 @@ stop_capture_complete (FpiSsm *ssm, FpDevice *_dev, GError *error)
G_DEBUG_HERE ();
fpi_ssm_free (ssm);
/* The device is inactive at this point. */
self->dev_state = FP_IMAGE_DEVICE_STATE_INACTIVE;
@@ -605,7 +603,6 @@ capture_complete (FpiSsm *ssm, FpDevice *_dev, GError *error)
fpi_image_device_session_error (dev, error);
}
fpi_ssm_free (ssm);
}
static void
@@ -752,15 +749,10 @@ calibrate_run_state (FpiSsm *ssm, FpDevice *dev)
}
else
{
GSource *timeout;
if (self->calib_status == 0x00 &&
self->last_read[0] == 0x01)
self->calib_status = 0x01;
timeout = fpi_device_add_timeout (dev, 50,
fpi_ssm_next_state_timeout_cb,
ssm);
g_source_set_name (timeout, "calibrate_run_state");
fpi_ssm_next_state_delayed (ssm, 50, NULL);
}
break;
@@ -784,11 +776,9 @@ calibrate_complete (FpiSsm *ssm, FpDevice *dev, GError *error)
}
else
{
self->dev_state = FP_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON;
elan_capture (dev);
}
fpi_ssm_free (ssm);
}
static void
@@ -885,7 +875,6 @@ activate_complete (FpiSsm *ssm, FpDevice *dev, GError *error)
fpi_image_device_activate_complete (idev, error);
fpi_ssm_free (ssm);
}
static void
@@ -974,10 +963,9 @@ elan_change_state (FpImageDevice *idev)
switch (next_state)
{
break;
case FP_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON:
/* activation completed or another enroll stage started */
self->dev_state = FP_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON;
elan_calibrate (dev);
break;
@@ -987,9 +975,8 @@ elan_change_state (FpImageDevice *idev)
case FP_IMAGE_DEVICE_STATE_INACTIVE:
case FP_IMAGE_DEVICE_STATE_AWAIT_FINGER_OFF:
if (self->dev_state != FP_IMAGE_DEVICE_STATE_INACTIVE ||
self->dev_state != FP_IMAGE_DEVICE_STATE_AWAIT_FINGER_OFF)
elan_stop_capture (dev);
elan_stop_capture (dev);
break;
}
}
@@ -1028,7 +1015,7 @@ dev_change_state (FpImageDevice *dev, FpImageDeviceState state)
self->dev_state_next = state;
timeout = fpi_device_add_timeout (FP_DEVICE (dev), 10,
elan_change_state_async,
NULL);
NULL, NULL);
name = g_strdup_printf ("dev_change_state to %d", state);
g_source_set_name (timeout, name);

View File

@@ -710,7 +710,6 @@ async_tx (FpDevice *dev, unsigned int ep, void *cb,
transfer->ssm = ssm;
fpi_usb_transfer_fill_bulk_full (transfer, ep, buffer, length, NULL);
fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL, cb, NULL);
fpi_usb_transfer_unref (transfer);
}
@@ -789,7 +788,6 @@ m_exit_complete (FpiSsm *ssm, FpDevice *dev, GError *error)
else
fp_dbg ("The device is now in idle state");
fpi_image_device_deactivate_complete (idev, error);
fpi_ssm_free (ssm);
}
static void
@@ -911,7 +909,6 @@ m_capture_complete (FpiSsm *ssm, FpDevice *dev, GError *error)
g_error_free (error);
}
}
fpi_ssm_free (ssm);
if (self->is_active == TRUE)
{
@@ -1061,7 +1058,6 @@ m_finger_complete (FpiSsm *ssm, FpDevice *dev, GError *error)
self->is_active = FALSE;
}
fpi_ssm_free (ssm);
}
static void
@@ -1265,7 +1261,6 @@ m_tunevrb_complete (FpiSsm *ssm, FpDevice *dev, GError *error)
if (!self->is_active)
m_exit_start (idev);
fpi_ssm_free (ssm);
}
/*
@@ -1409,7 +1404,6 @@ m_tunedc_complete (FpiSsm *ssm, FpDevice *dev, GError *error)
if (!self->is_active)
m_exit_start (idev);
fpi_ssm_free (ssm);
}
static void
@@ -1543,7 +1537,6 @@ m_init_complete (FpiSsm *ssm, FpDevice *dev, GError *error)
reset_param (FPI_DEVICE_ETES603 (dev));
fpi_image_device_session_error (idev, error);
}
fpi_ssm_free (ssm);
}
static void

View File

@@ -137,7 +137,8 @@ cmd_recieve_cb (FpiUsbTransfer *transfer,
fp_warn ("Received General Error %d from the sensor", (guint) err);
fpi_ssm_mark_failed (transfer->ssm,
fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
"Received general error from device"));
"Received general error %u from device",
(guint) err));
//fpi_ssm_jump_to_state (transfer->ssm, fpi_ssm_get_cur_state (transfer->ssm));
return;
}
@@ -204,7 +205,7 @@ static void
synaptics_cmd_run_state (FpiSsm *ssm,
FpDevice *dev)
{
g_autoptr(FpiUsbTransfer) transfer = NULL;
FpiUsbTransfer *transfer;
FpiDeviceSynaptics *self = FPI_DEVICE_SYNAPTICS (dev);
switch (fpi_ssm_get_cur_state (ssm))
@@ -218,7 +219,7 @@ synaptics_cmd_run_state (FpiSsm *ssm,
NULL,
fpi_ssm_usb_transfer_cb,
NULL);
g_clear_pointer (&self->cmd_pending_transfer, fpi_usb_transfer_unref);
self->cmd_pending_transfer = NULL;
}
else
{
@@ -289,7 +290,6 @@ cmd_ssm_done (FpiSsm *ssm, FpDevice *dev, GError *error)
}
self->cmd_complete_on_removal = FALSE;
g_clear_pointer (&self->cmd_complete_error, g_error_free);
fpi_ssm_free (ssm);
}
static void
@@ -317,7 +317,7 @@ synaptics_sensor_cmd (FpiDeviceSynaptics *self,
gssize payload_len,
SynCmdMsgCallback callback)
{
g_autoptr(FpiUsbTransfer) transfer = NULL;
FpiUsbTransfer *transfer;
guint8 real_seq_num;
gint msg_len;
gint res;
@@ -407,7 +407,7 @@ static gboolean
parse_print_data (GVariant *data,
guint8 *finger,
const guint8 **user_id,
gssize *user_id_len)
gsize *user_id_len)
{
g_autoptr(GVariant) user_id_var = NULL;
@@ -447,7 +447,7 @@ list_msg_cb (FpiDeviceSynaptics *self,
if (error)
{
g_clear_pointer (&self->list_result, g_ptr_array_free);
g_clear_pointer (&self->list_result, g_ptr_array_unref);
fpi_device_list_complete (FP_DEVICE (self), NULL, error);
return;
}
@@ -468,11 +468,12 @@ list_msg_cb (FpiDeviceSynaptics *self,
else
{
fp_info ("Failed to query enrolled users: %d", resp->result);
g_clear_pointer (&self->list_result, g_ptr_array_free);
g_clear_pointer (&self->list_result, g_ptr_array_unref);
fpi_device_list_complete (FP_DEVICE (self),
NULL,
fpi_device_error_new_msg (FP_DEVICE_ERROR_GENERAL,
"Failed to query enrolled users"));
"Failed to query enrolled users: %d",
resp->result));
}
break;
@@ -505,7 +506,7 @@ list_msg_cb (FpiDeviceSynaptics *self,
get_enroll_templates_resp->templates[n].user_id,
get_enroll_templates_resp->templates[n].finger_id);
userid = get_enroll_templates_resp->templates[n].user_id;
userid = (gchar *) get_enroll_templates_resp->templates[n].user_id;
print = fp_print_new (FP_DEVICE (self));
uid = g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE,
@@ -604,6 +605,8 @@ verify_msg_cb (FpiDeviceSynaptics *self,
return;
}
g_assert (resp != NULL);
verify_resp = &resp->response.verify_resp;
switch (resp->response_id)
@@ -768,7 +771,8 @@ enroll_msg_cb (FpiDeviceSynaptics *self,
fpi_device_enroll_complete (device,
NULL,
fpi_device_error_new_msg (FP_DEVICE_ERROR_GENERAL,
"Enrollment failed"));
"Enrollment failed (%d)",
resp->result));
}
break;
}
@@ -798,7 +802,7 @@ enroll (FpDevice *device)
GVariant *uid = NULL;
const gchar *username;
guint finger;
g_autofree gchar *user_id;
g_autofree gchar *user_id = NULL;
gssize user_id_len;
g_autofree guint8 *payload = NULL;
const GDate *date;
@@ -812,9 +816,9 @@ enroll (FpDevice *device)
date = fp_print_get_enroll_date (print);
if (date && g_date_valid (date))
{
y = date->year;
m = date->month;
d = date->day;
y = g_date_get_year (date);
m = g_date_get_month (date);
d = g_date_get_day (date);
}
else
{
@@ -946,7 +950,8 @@ dev_probe (FpDevice *device)
{
FpiDeviceSynaptics *self = FPI_DEVICE_SYNAPTICS (device);
GUsbDevice *usb_dev;
FpiUsbTransfer *transfer;
g_autoptr(FpiUsbTransfer) transfer = NULL;
FpiByteReader reader;
GError *error = NULL;
guint16 status;
@@ -965,10 +970,7 @@ dev_probe (FpDevice *device)
}
if (!g_usb_device_reset (fpi_device_get_usb_device (device), &error))
{
fpi_device_probe_complete (device, NULL, NULL, error);
return;
}
goto err_close;
if (!g_usb_device_claim_interface (fpi_device_get_usb_device (device), 0, 0, &error))
goto err_close;
@@ -980,9 +982,8 @@ dev_probe (FpDevice *device)
transfer->buffer[0] = SENSOR_CMD_GET_VERSION;
if (!fpi_usb_transfer_submit_sync (transfer, 1000, &error))
goto err_close;
fpi_usb_transfer_unref (transfer);
g_clear_pointer (&transfer, fpi_usb_transfer_unref);
transfer = fpi_usb_transfer_new (device);
fpi_usb_transfer_fill_bulk (transfer, USB_EP_REPLY, 40);
if (!fpi_usb_transfer_submit_sync (transfer, 1000, &error))
@@ -1035,7 +1036,6 @@ dev_probe (FpDevice *device)
fp_dbg ("Target: %d", self->mis_version.target);
fp_dbg ("Product: %d", self->mis_version.product);
fpi_usb_transfer_unref (transfer);
/* We need at least firmware version 10.1, and for 10.1 build 2989158 */
if (self->mis_version.version_major < 10 ||
@@ -1050,7 +1050,11 @@ dev_probe (FpDevice *device)
self->mis_version.build_num);
error = fpi_device_error_new_msg (FP_DEVICE_ERROR_GENERAL,
"Unsupported firmware version");
"Unsupported firmware version "
"(%d.%d with build number %d)",
self->mis_version.version_major,
self->mis_version.version_minor,
self->mis_version.build_num);
goto err_close;
}
@@ -1118,7 +1122,7 @@ fps_deinit_cb (FpiDeviceSynaptics *self,
case BMKT_RSP_POWER_DOWN_FAIL:
fp_info ("Failed to go to power down mode: %d", resp->result);
error = fpi_device_error_new_msg (FP_DEVICE_ERROR_GENERAL,
"Power down failed");
"Power down failed: %d", resp->result);
break;
}

View File

@@ -635,7 +635,6 @@ write_regs_iterate (struct write_regs_data *wrdata)
transfer->short_is_error = TRUE;
transfer->ssm = wrdata->ssm;
fpi_usb_transfer_submit (transfer, CTRL_TIMEOUT, NULL, write_regs_cb, NULL);
fpi_usb_transfer_unref (transfer);
transfer->buffer[0] = regwrite->value;
}
@@ -657,17 +656,6 @@ sm_write_regs (FpiSsm *ssm,
write_regs_iterate (wrdata);
}
static void
sm_write_reg_cb (FpiUsbTransfer *transfer, FpDevice *device,
gpointer user_data, GError *error)
{
if (error)
fpi_ssm_mark_failed (transfer->ssm, error);
else
fpi_ssm_next_state (transfer->ssm);
}
static void
sm_write_reg (FpiSsm *ssm,
FpImageDevice *dev,
@@ -687,8 +675,8 @@ sm_write_reg (FpiSsm *ssm,
1);
transfer->short_is_error = TRUE;
transfer->ssm = ssm;
fpi_usb_transfer_submit (transfer, CTRL_TIMEOUT, NULL, sm_write_reg_cb, NULL);
fpi_usb_transfer_unref (transfer);
fpi_usb_transfer_submit (transfer, CTRL_TIMEOUT, NULL,
fpi_ssm_usb_transfer_cb, NULL);
transfer->buffer[0] = value;
}
@@ -737,7 +725,6 @@ sm_read_reg (FpiSsm *ssm,
NULL,
sm_read_reg_cb,
NULL);
fpi_usb_transfer_unref (transfer);
}
static void
@@ -782,7 +769,6 @@ sm_await_intr (FpiSsm *ssm,
fpi_device_get_cancellable (FP_DEVICE (dev)),
sm_await_intr_cb,
NULL);
fpi_usb_transfer_unref (transfer);
}
/***** AWAIT FINGER *****/
@@ -1249,6 +1235,9 @@ loopsm_run_state (FpiSsm *ssm, FpDevice *_dev)
awfsm_1000_run_state,
AWFSM_1000_NUM_STATES);
break;
default:
g_assert_not_reached ();
}
fpi_ssm_start_subsm (ssm, awfsm);
}
@@ -1290,6 +1279,9 @@ loopsm_run_state (FpiSsm *ssm, FpDevice *_dev)
capsm_1001_run_state,
CAPSM_1001_NUM_STATES);
break;
default:
g_assert_not_reached ();
}
fpi_ssm_start_subsm (ssm, capsm);
break;
@@ -1318,6 +1310,9 @@ loopsm_run_state (FpiSsm *ssm, FpDevice *_dev)
deinitsm_1001_run_state,
DEINITSM_1001_NUM_STATES);
break;
default:
g_assert_not_reached ();
}
self->capturing = FALSE;
fpi_ssm_start_subsm (ssm, deinitsm);
@@ -1371,7 +1366,6 @@ loopsm_complete (FpiSsm *ssm, FpDevice *_dev, GError *error)
FpImageDevice *dev = FP_IMAGE_DEVICE (_dev);
FpiDeviceUpeksonly *self = FPI_DEVICE_UPEKSONLY (_dev);
fpi_ssm_free (ssm);
if (self->deactivating)
{
@@ -1392,7 +1386,6 @@ initsm_complete (FpiSsm *ssm, FpDevice *_dev, GError *error)
FpImageDevice *dev = FP_IMAGE_DEVICE (_dev);
FpiDeviceUpeksonly *self = FPI_DEVICE_UPEKSONLY (_dev);
fpi_ssm_free (ssm);
fpi_image_device_activate_complete (dev, error);
if (error)
return;
@@ -1412,7 +1405,6 @@ dev_activate (FpImageDevice *dev)
self->deactivating = FALSE;
self->capturing = FALSE;
self->img_transfers = g_ptr_array_new_full (NUM_BULK_TRANSFERS, (GDestroyNotify) fpi_usb_transfer_unref);
self->num_flying = 0;
for (i = 0; i < self->img_transfers->len; i++)
@@ -1441,6 +1433,9 @@ dev_activate (FpImageDevice *dev)
ssm = fpi_ssm_new (FP_DEVICE (dev), initsm_1001_run_state,
INITSM_1001_NUM_STATES);
break;
default:
g_assert_not_reached ();
}
fpi_ssm_start (ssm, initsm_complete);
}

View File

@@ -128,7 +128,6 @@ activate_run_state (FpiSsm *ssm, FpDevice *dev)
transfer->short_is_error = TRUE;
fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
write_init_cb, NULL);
fpi_usb_transfer_unref (transfer);
}
break;
@@ -142,7 +141,6 @@ activate_run_state (FpiSsm *ssm, FpDevice *dev)
transfer->ssm = ssm;
fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
read_init_data_cb, NULL);
fpi_usb_transfer_unref (transfer);
}
break;
}
@@ -157,7 +155,6 @@ activate_sm_complete (FpiSsm *ssm, FpDevice *_dev, GError *error)
if (!error)
start_finger_detection (dev);
fpi_ssm_free (ssm);
}
@@ -226,7 +223,6 @@ finger_det_cmd_cb (FpiUsbTransfer *t, FpDevice *device,
IMAGE_SIZE);
fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
finger_det_data_cb, NULL);
fpi_usb_transfer_unref (transfer);
}
static void
@@ -250,7 +246,6 @@ start_finger_detection (FpImageDevice *dev)
UPEKTC_CMD_LEN, NULL);
fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
finger_det_cmd_cb, NULL);
fpi_usb_transfer_unref (transfer);
}
/****** CAPTURE ******/
@@ -261,16 +256,6 @@ enum capture_states {
CAPTURE_NUM_STATES,
};
static void
capture_cmd_cb (FpiUsbTransfer *transfer, FpDevice *device,
gpointer user_data, GError *error)
{
if (!error)
fpi_ssm_next_state (transfer->ssm);
else
fpi_ssm_mark_failed (transfer->ssm, error);
}
static void
capture_read_data_cb (FpiUsbTransfer *transfer, FpDevice *device,
gpointer user_data, GError *error)
@@ -309,8 +294,7 @@ capture_run_state (FpiSsm *ssm, FpDevice *_dev)
transfer->ssm = ssm;
transfer->short_is_error = TRUE;
fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
capture_cmd_cb, NULL);
fpi_usb_transfer_unref (transfer);
fpi_ssm_usb_transfer_cb, NULL);
}
break;
@@ -324,7 +308,6 @@ capture_run_state (FpiSsm *ssm, FpDevice *_dev)
transfer->short_is_error = TRUE;
fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
capture_read_data_cb, NULL);
fpi_usb_transfer_unref (transfer);
}
break;
}
@@ -345,7 +328,6 @@ capture_sm_complete (FpiSsm *ssm, FpDevice *_dev, GError *error)
else
start_finger_detection (dev);
fpi_ssm_free (ssm);
}
static void

View File

@@ -100,7 +100,6 @@ upektc_img_submit_req (FpiSsm *ssm,
transfer->ssm = ssm;
transfer->short_is_error = TRUE;
fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL, cb, NULL);
fpi_usb_transfer_unref (transfer);
}
static void
@@ -120,7 +119,6 @@ upektc_img_read_data (FpiSsm *ssm,
NULL);
transfer->ssm = ssm;
fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL, cb, NULL);
fpi_usb_transfer_unref (transfer);
}
/****** CAPTURE ******/
@@ -389,7 +387,6 @@ capture_sm_complete (FpiSsm *ssm, FpDevice *_dev, GError *error_arg)
g_autoptr(GError) error = error_arg;
fpi_ssm_free (ssm);
/* Note: We assume that the error is a cancellation in the deactivation case */
if (self->deactivating)
@@ -470,7 +467,6 @@ deactivate_sm_complete (FpiSsm *ssm, FpDevice *_dev, GError *error)
FpiDeviceUpektcImg *self = FPI_DEVICE_UPEKTC_IMG (_dev);
fp_dbg ("Deactivate completed");
fpi_ssm_free (ssm);
self->deactivating = FALSE;
fpi_image_device_deactivate_complete (dev, error);
@@ -505,16 +501,6 @@ enum activate_states {
ACTIVATE_NUM_STATES,
};
static void
init_reqs_ctrl_cb (FpiUsbTransfer *transfer, FpDevice *device,
gpointer user_data, GError *error)
{
if (!error)
fpi_ssm_next_state (transfer->ssm);
else
fpi_ssm_mark_failed (transfer->ssm, error);
}
static void
init_reqs_cb (FpiUsbTransfer *transfer, FpDevice *device,
gpointer user_data, GError *error)
@@ -558,8 +544,7 @@ activate_run_state (FpiSsm *ssm, FpDevice *dev)
transfer->buffer[0] = '\0';
transfer->ssm = ssm;
fpi_usb_transfer_submit (transfer, CTRL_TIMEOUT, NULL,
init_reqs_ctrl_cb, NULL);
fpi_usb_transfer_unref (transfer);
fpi_ssm_usb_transfer_cb, NULL);
}
break;
@@ -601,7 +586,6 @@ activate_sm_complete (FpiSsm *ssm, FpDevice *_dev, GError *error)
{
FpImageDevice *dev = FP_IMAGE_DEVICE (_dev);
fpi_ssm_free (ssm);
fpi_image_device_activate_complete (dev, error);
if (!error)

View File

@@ -226,7 +226,6 @@ busy_ack_retry_read (FpDevice *device, struct read_msg_data *udata)
transfer->short_is_error = TRUE;
fpi_usb_transfer_submit (transfer, TIMEOUT, NULL, busy_ack_sent_cb, udata);
fpi_usb_transfer_unref (transfer);
}
/* Returns 0 if message was handled, 1 if it was a device-busy message, and
@@ -288,7 +287,7 @@ __handle_incoming_msg (FpDevice *device,
{
fp_warn ("cmd response too short (%d)", len);
error = fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
"CMD response too short");
"CMD response too short (%d)", len);
goto err;
}
if (innerbuf[0] != 0x28)
@@ -371,11 +370,12 @@ read_msg_cb (FpiUsbTransfer *transfer, FpDevice *device,
fp_err ("async msg read too short (%d)",
(gint) transfer->actual_length);
error = fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
"Packet from device was too short");
"Packet from device was too short (%lu)",
transfer->actual_length);
goto err;
}
if (strncmp (udata->buffer, "Ciao", 4) != 0)
if (strncmp ((char *) udata->buffer, "Ciao", 4) != 0)
{
fp_err ("no Ciao for you!!");
error = fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
@@ -415,7 +415,6 @@ read_msg_cb (FpiUsbTransfer *transfer, FpDevice *device,
fpi_usb_transfer_submit (etransfer, TIMEOUT,
NULL,
read_msg_extend_cb, udata);
fpi_usb_transfer_unref (etransfer);
return;
}
@@ -441,7 +440,6 @@ __read_msg_async (FpDevice *device, struct read_msg_data *udata)
fpi_usb_transfer_fill_bulk_full (transfer, EP_IN, udata->buffer, udata->buflen, NULL);
fpi_usb_transfer_submit (transfer, TIMEOUT, NULL, read_msg_cb, udata);
fpi_usb_transfer_unref (transfer);
}
static void
@@ -675,7 +673,6 @@ initsm_send_msg28_handler (FpiSsm *ssm,
transfer->ssm = ssm;
transfer->short_is_error = TRUE;
fpi_usb_transfer_submit (transfer, TIMEOUT, NULL, fpi_ssm_usb_transfer_cb, NULL);
fpi_usb_transfer_unref (transfer);
}
static void
@@ -696,7 +693,6 @@ initsm_run_state (FpiSsm *ssm, FpDevice *dev)
transfer->ssm = ssm;
transfer->short_is_error = TRUE;
fpi_usb_transfer_submit (transfer, TIMEOUT, NULL, fpi_ssm_usb_transfer_cb, NULL);
fpi_usb_transfer_unref (transfer);
break;
case READ_MSG03:
@@ -708,7 +704,6 @@ initsm_run_state (FpiSsm *ssm, FpDevice *dev)
transfer->ssm = ssm;
transfer->short_is_error = TRUE;
fpi_usb_transfer_submit (transfer, TIMEOUT, NULL, fpi_ssm_usb_transfer_cb, NULL);
fpi_usb_transfer_unref (transfer);
break;
case READ_MSG05:
@@ -798,7 +793,8 @@ read_msg01_cb (FpDevice *dev, enum read_msg_type type,
{
fp_err ("expected seq=1, got %x", seq);
fpi_ssm_mark_failed (ssm, fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
"Got wrong sequence number"));
"Got wrong sequence number (%x)",
seq));
return;
}
@@ -818,7 +814,6 @@ deinitsm_state_handler (FpiSsm *ssm, FpDevice *dev)
transfer->short_is_error = TRUE;
transfer->ssm = ssm;
fpi_usb_transfer_submit (transfer, TIMEOUT, NULL, fpi_ssm_usb_transfer_cb, NULL);
fpi_usb_transfer_unref (transfer);
break;
case READ_MSG01:;
@@ -951,7 +946,6 @@ enroll_start_sm_run_state (FpiSsm *ssm, FpDevice *dev)
transfer->ssm = ssm;
fpi_usb_transfer_submit (transfer, TIMEOUT, NULL, fpi_ssm_usb_transfer_cb, NULL);
fpi_usb_transfer_unref (transfer);
break;
case READ_ENROLL_MSG28:;
@@ -988,7 +982,6 @@ enroll_stop_deinit_cb (FpiSsm *ssm, FpDevice *dev, GError *error)
fp_warn ("Error deinitializing: %s", error->message);
fpi_device_enroll_complete (dev, data->print, data->error);
fpi_ssm_free (ssm);
}
static void
@@ -1204,7 +1197,6 @@ enroll_iterate (FpDevice *dev)
transfer->short_is_error = TRUE;
fpi_usb_transfer_submit (transfer, TIMEOUT, NULL, enroll_iterate_cmd_cb, NULL);
fpi_usb_transfer_unref (transfer);
}
static void
@@ -1215,7 +1207,6 @@ enroll_started (FpiSsm *ssm, FpDevice *dev, GError *error)
else
enroll_iterate (dev);
fpi_ssm_free (ssm);
}
static void
@@ -1254,7 +1245,6 @@ verify_stop_deinit_cb (FpiSsm *ssm, FpDevice *dev, GError *error)
fp_warn ("Error deinitializing: %s", error->message);
fpi_device_verify_complete (dev, data->res, NULL, data->error);
fpi_ssm_free (ssm);
}
static void
@@ -1320,7 +1310,6 @@ verify_start_sm_run_state (FpiSsm *ssm, FpDevice *dev)
transfer->short_is_error = TRUE;
transfer->ssm = ssm;
fpi_usb_transfer_submit (transfer, TIMEOUT, NULL, fpi_ssm_usb_transfer_cb, NULL);
fpi_usb_transfer_unref (transfer);
break;
}
@@ -1520,7 +1509,6 @@ verify_iterate (FpDevice *dev)
transfer->short_is_error = TRUE;
fpi_usb_transfer_submit (transfer, TIMEOUT, NULL, verify_wr2800_cb, NULL);
fpi_usb_transfer_unref (transfer);
}
}
@@ -1538,7 +1526,6 @@ verify_started (FpiSsm *ssm, FpDevice *dev, GError *error)
upekdev->first_verify_iteration = TRUE;
verify_iterate (dev);
fpi_ssm_free (ssm);
}
static void

View File

@@ -175,13 +175,12 @@ write_regs (FpImageDevice *dev, uint16_t first_reg,
transfer->short_is_error = TRUE;
fpi_usb_transfer_fill_control (transfer,
G_USB_DEVICE_DIRECTION_HOST_TO_DEVICE,
G_USB_DEVICE_REQUEST_TYPE_STANDARD,
G_USB_DEVICE_REQUEST_TYPE_VENDOR,
G_USB_DEVICE_RECIPIENT_DEVICE,
USB_RQ, first_reg, 0,
num_regs);
memcpy (transfer->buffer, values, num_regs);
fpi_usb_transfer_submit (transfer, CTRL_TIMEOUT, NULL, callback, user_data);
fpi_usb_transfer_unref (transfer);
}
static void
@@ -203,11 +202,10 @@ read_regs (FpImageDevice *dev, uint16_t first_reg,
fpi_usb_transfer_fill_control (transfer,
G_USB_DEVICE_DIRECTION_DEVICE_TO_HOST,
G_USB_DEVICE_REQUEST_TYPE_STANDARD,
G_USB_DEVICE_REQUEST_TYPE_VENDOR,
G_USB_DEVICE_RECIPIENT_DEVICE,
USB_RQ, first_reg, 0, num_regs);
fpi_usb_transfer_submit (transfer, CTRL_TIMEOUT, NULL, callback, user_data);
fpi_usb_transfer_unref (transfer);
}
/*
@@ -334,6 +332,8 @@ irq_handler (FpiUsbTransfer *transfer,
return;
}
start_irq_handler (imgdev);
type = GUINT16_FROM_BE (*((uint16_t *) data));
fp_dbg ("recv irq type %04x", type);
@@ -346,8 +346,6 @@ irq_handler (FpiUsbTransfer *transfer,
urudev->irq_cb (imgdev, NULL, type, urudev->irq_cb_data);
else
fp_dbg ("ignoring interrupt");
start_irq_handler (imgdev);
}
static void
@@ -365,7 +363,6 @@ start_irq_handler (FpImageDevice *dev)
EP_INTR,
IRQ_LENGTH);
fpi_usb_transfer_submit (transfer, 0, self->irq_cancellable, irq_handler, NULL);
fpi_usb_transfer_unref (transfer);
}
static void
@@ -789,7 +786,6 @@ imaging_complete (FpiSsm *ssm, FpDevice *dev, GError *error)
{
FpiDeviceUru4000 *self = FPI_DEVICE_URU4000 (dev);
fpi_ssm_free (ssm);
/* Report error before exiting imaging loop - the error handler
* can request state change, which needs to be postponed to end of
@@ -833,26 +829,6 @@ enum rebootpwr_states {
REBOOTPWR_NUM_STATES,
};
static void
rebootpwr_pause_cb (FpDevice *dev,
void *data)
{
FpiSsm *ssm = data;
FpiDeviceUru4000 *self = FPI_DEVICE_URU4000 (dev);
if (!--self->rebootpwr_ctr)
{
fp_err ("could not reboot device power");
fpi_ssm_mark_failed (ssm,
fpi_device_error_new_msg (FP_DEVICE_ERROR,
"Could not reboot device"));
}
else
{
fpi_ssm_jump_to_state (ssm, REBOOTPWR_GET_HWSTAT);
}
}
static void
rebootpwr_run_state (FpiSsm *ssm, FpDevice *_dev)
{
@@ -879,7 +855,17 @@ rebootpwr_run_state (FpiSsm *ssm, FpDevice *_dev)
break;
case REBOOTPWR_PAUSE:
fpi_device_add_timeout (_dev, 10, rebootpwr_pause_cb, ssm);
if (!--self->rebootpwr_ctr)
{
fp_err ("could not reboot device power");
fpi_ssm_mark_failed (ssm,
fpi_device_error_new_msg (FP_DEVICE_ERROR,
"Could not reboot device"));
}
else
{
fpi_ssm_jump_to_state_delayed (ssm, 10, REBOOTPWR_GET_HWSTAT, NULL);
}
break;
}
}
@@ -920,30 +906,6 @@ enum powerup_states {
POWERUP_NUM_STATES,
};
static void
powerup_pause_cb (FpDevice *dev,
void *data)
{
FpiSsm *ssm = data;
FpiDeviceUru4000 *self = FPI_DEVICE_URU4000 (dev);
if (!--self->powerup_ctr)
{
fp_err ("could not power device up");
fpi_ssm_mark_failed (ssm,
fpi_device_error_new_msg (FP_DEVICE_ERROR_GENERAL,
"could not power device up"));
}
else if (!self->profile->auth_cr)
{
fpi_ssm_jump_to_state (ssm, POWERUP_SET_HWSTAT);
}
else
{
fpi_ssm_next_state (ssm);
}
}
static void
powerup_run_state (FpiSsm *ssm, FpDevice *_dev)
{
@@ -975,7 +937,21 @@ powerup_run_state (FpiSsm *ssm, FpDevice *_dev)
break;
case POWERUP_PAUSE:
fpi_device_add_timeout (_dev, 10, powerup_pause_cb, ssm);
if (!--self->powerup_ctr)
{
fp_err ("could not power device up");
fpi_ssm_mark_failed (ssm,
fpi_device_error_new_msg (FP_DEVICE_ERROR_GENERAL,
"could not power device up"));
}
else if (!self->profile->auth_cr)
{
fpi_ssm_jump_to_state_delayed (ssm, POWERUP_SET_HWSTAT, 10, NULL);
}
else
{
fpi_ssm_next_state_delayed (ssm, 10, NULL);
}
break;
case POWERUP_CHALLENGE_RESPONSE:
@@ -1134,7 +1110,7 @@ init_run_state (FpiSsm *ssm, FpDevice *_dev)
self->scanpwr_irq_timeout = fpi_device_add_timeout (_dev,
300,
init_scanpwr_timeout,
ssm);
ssm, NULL);
break;
case INIT_DONE:

View File

@@ -76,16 +76,6 @@ enum v5s_cmd {
/***** REGISTER I/O *****/
static void
sm_write_reg_cb (FpiUsbTransfer *transfer, FpDevice *device,
gpointer user_data, GError *error)
{
if (error)
fpi_ssm_mark_failed (transfer->ssm, error);
else
fpi_ssm_next_state (transfer->ssm);
}
static void
sm_write_reg (FpiSsm *ssm,
FpDevice *dev,
@@ -101,19 +91,8 @@ sm_write_reg (FpiSsm *ssm,
G_USB_DEVICE_RECIPIENT_DEVICE,
reg, value, 0, 0);
transfer->ssm = ssm;
fpi_usb_transfer_submit (transfer, CTRL_TIMEOUT, NULL, sm_write_reg_cb,
NULL);
fpi_usb_transfer_unref (transfer);
}
static void
sm_exec_cmd_cb (FpiUsbTransfer *transfer, FpDevice *device,
gpointer user_data, GError *error)
{
if (error)
fpi_ssm_mark_failed (transfer->ssm, error);
else
fpi_ssm_next_state (transfer->ssm);
fpi_usb_transfer_submit (transfer, CTRL_TIMEOUT, NULL,
fpi_ssm_usb_transfer_cb, NULL);
}
static void
@@ -131,9 +110,8 @@ sm_exec_cmd (FpiSsm *ssm,
G_USB_DEVICE_RECIPIENT_DEVICE,
cmd, param, 0, 0);
transfer->ssm = ssm;
fpi_usb_transfer_submit (transfer, CTRL_TIMEOUT, NULL, sm_exec_cmd_cb,
NULL);
fpi_usb_transfer_unref (transfer);
fpi_usb_transfer_submit (transfer, CTRL_TIMEOUT, NULL,
fpi_ssm_usb_transfer_cb, NULL);
}
/***** FINGER DETECTION *****/
@@ -227,7 +205,6 @@ capture_iterate (FpiSsm *ssm,
NULL);
fpi_usb_transfer_submit (transfer, CTRL_TIMEOUT, NULL, capture_cb, NULL);
fpi_usb_transfer_unref (transfer);
}
@@ -301,7 +278,6 @@ loopsm_complete (FpiSsm *ssm, FpDevice *dev, GError *error)
FpImageDevice *imgdev = FP_IMAGE_DEVICE (dev);
FpDeviceVcom5s *self = FPI_DEVICE_VCOM5S (dev);
fpi_ssm_free (ssm);
g_object_unref (self->capture_img);
self->capture_img = NULL;
self->loop_running = FALSE;

View File

@@ -56,7 +56,6 @@ async_write (FpiSsm *ssm,
transfer->short_is_error = TRUE;
fpi_usb_transfer_submit (transfer, VFS_USB_TIMEOUT, NULL,
async_write_callback, NULL);
fpi_usb_transfer_unref (transfer);
}
/* Callback for async_read */
@@ -108,7 +107,6 @@ async_read (FpiSsm *ssm,
fpi_usb_transfer_submit (transfer, VFS_USB_TIMEOUT, NULL,
async_read_callback, NULL);
fpi_usb_transfer_unref (transfer);
}
/* Callback for async_abort */
@@ -160,7 +158,6 @@ async_abort (FpDevice *dev, FpiSsm *ssm, int ep)
fpi_usb_transfer_submit (transfer, VFS_USB_ABORT_TIMEOUT, NULL,
async_abort_callback, NULL);
fpi_usb_transfer_unref (transfer);
}
/* Image processing functions */
@@ -402,7 +399,7 @@ interrupt_callback (FpiUsbTransfer *transfer, FpDevice *device,
gpointer user_data, GError *error)
{
FpDeviceVfs0050 *self = FPI_DEVICE_VFS0050 (device);
char *interrupt = transfer->buffer;
unsigned char *interrupt = transfer->buffer;
/* we expect a cancellation error when the device is deactivating
* go into the SSM_CLEAR_EP2 state in that case. */
@@ -482,16 +479,6 @@ receive_callback (FpiUsbTransfer *transfer, FpDevice *device,
}
}
/* SSM stub to prepare device to another scan after orange light was on */
static void
another_scan (FpDevice *dev,
void *data)
{
FpiSsm *ssm = data;
fpi_ssm_jump_to_state (ssm, SSM_TURN_ON);
}
/* Main SSM loop */
static void
activate_ssm (FpiSsm *ssm, FpDevice *dev)
@@ -564,7 +551,6 @@ activate_ssm (FpiSsm *ssm, FpDevice *dev)
0,
fpi_device_get_cancellable (dev),
interrupt_callback, NULL);
fpi_usb_transfer_unref (transfer);
/* I've put it here to be sure that data is cleared */
clear_data (self);
@@ -609,12 +595,12 @@ activate_ssm (FpiSsm *ssm, FpDevice *dev)
/* Receive chunk of data */
transfer = fpi_usb_transfer_new (dev);
fpi_usb_transfer_fill_bulk_full (transfer, 0x82,
(void *) self->lines_buffer + self->bytes,
(guint8 *)
(self->lines_buffer + self->bytes),
VFS_USB_BUFFER_SIZE, NULL);
transfer->ssm = ssm;
fpi_usb_transfer_submit (transfer, VFS_USB_TIMEOUT, NULL,
receive_callback, NULL);
fpi_usb_transfer_unref (transfer);
break;
}
@@ -623,8 +609,7 @@ activate_ssm (FpiSsm *ssm, FpDevice *dev)
clear_data (self);
/* Wait for probable vdev->active changing */
fpi_device_add_timeout (dev, VFS_SSM_TIMEOUT,
fpi_ssm_next_state_timeout_cb, ssm);
fpi_ssm_next_state_delayed (ssm, VFS_SSM_TIMEOUT, NULL);
break;
case SSM_NEXT_RECEIVE:
@@ -643,8 +628,8 @@ activate_ssm (FpiSsm *ssm, FpDevice *dev)
case SSM_WAIT_ANOTHER_SCAN:
/* Orange light is on now */
fpi_device_add_timeout (dev, VFS_SSM_ORANGE_TIMEOUT,
another_scan, ssm);
fpi_ssm_jump_to_state_delayed (ssm, SSM_TURN_ON, VFS_SSM_ORANGE_TIMEOUT,
NULL);
break;
default:
@@ -669,7 +654,6 @@ dev_activate_callback (FpiSsm *ssm, FpDevice *dev, GError *error)
g_error_free (error);
}
fpi_ssm_free (ssm);
}
/* Activate device */
@@ -710,7 +694,6 @@ dev_open_callback (FpiSsm *ssm, FpDevice *dev, GError *error)
{
/* Notify open complete */
fpi_image_device_open_complete (FP_IMAGE_DEVICE (dev), error);
fpi_ssm_free (ssm);
}
/* Open device */

View File

@@ -219,7 +219,6 @@ async_send (FpiSsm *ssm,
transfer->short_is_error = TRUE;
fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
async_send_cb, NULL);
fpi_usb_transfer_unref (transfer);
}
/* Callback of asynchronous recv */
@@ -282,7 +281,6 @@ async_recv (FpiSsm *ssm,
transfer->ssm = ssm;
fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
async_recv_cb, NULL);
fpi_usb_transfer_unref (transfer);
}
static void async_load (FpiSsm *ssm,
@@ -369,17 +367,6 @@ async_load (FpiSsm *ssm,
transfer->ssm = ssm;
fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
async_load_cb, NULL);
fpi_usb_transfer_unref (transfer);
}
/* Submit asynchronous sleep */
static void
async_sleep (unsigned int msec,
FpiSsm *ssm,
FpImageDevice *dev)
{
fpi_device_add_timeout (FP_DEVICE (dev), msec,
fpi_ssm_next_state_timeout_cb, ssm);
}
/* Swap ssm states */
@@ -798,7 +785,7 @@ m_loop_state (FpiSsm *ssm, FpDevice *_dev)
case M_LOOP_0_SLEEP:
/* Wait fingerprint scanning */
async_sleep (50, ssm, dev);
fpi_ssm_next_state_delayed (ssm, 50, NULL);
break;
case M_LOOP_0_GET_STATE:
@@ -841,7 +828,7 @@ m_loop_state (FpiSsm *ssm, FpDevice *_dev)
img_extract (ssm, dev);
/* Wait handling image */
async_sleep (10, ssm, dev);
fpi_ssm_next_state_delayed (ssm, 10, NULL);
break;
case M_LOOP_0_CHECK_ACTION:
@@ -864,7 +851,7 @@ m_loop_state (FpiSsm *ssm, FpDevice *_dev)
if (vfs_finger_state (self) == VFS_FINGER_PRESENT)
{
fpi_image_device_report_finger_status (dev, TRUE);
async_sleep (250, ssm, dev);
fpi_ssm_next_state_delayed (ssm, 250, NULL);
}
else
{
@@ -894,7 +881,7 @@ m_loop_state (FpiSsm *ssm, FpDevice *_dev)
case M_LOOP_1_SLEEP:
/* Wait fingerprint scanning */
async_sleep (10, ssm, dev);
fpi_ssm_next_state_delayed (ssm, 10, NULL);
break;
case M_LOOP_2_ABORT_PRINT:
@@ -930,7 +917,7 @@ m_loop_state (FpiSsm *ssm, FpDevice *_dev)
{
/* Wait aborting */
self->counter++;
async_sleep (100, ssm, dev);
fpi_ssm_next_state_delayed (ssm, 100, NULL);
}
else
{
@@ -960,7 +947,6 @@ m_loop_complete (FpiSsm *ssm, FpDevice *dev, GError *error)
self->active = FALSE;
fpi_ssm_free (ssm);
}
/* Init ssm states */
@@ -1069,7 +1055,7 @@ m_init_state (FpiSsm *ssm, FpDevice *_dev)
{
/* Wait aborting */
self->counter++;
async_sleep (100, ssm, dev);
fpi_ssm_next_state_delayed (ssm, 100, NULL);
}
else
{
@@ -1098,7 +1084,7 @@ m_init_state (FpiSsm *ssm, FpDevice *_dev)
{
/* Wait removing finger */
self->counter++;
async_sleep (250, ssm, dev);
fpi_ssm_next_state_delayed (ssm, 250, NULL);
}
else
{
@@ -1268,7 +1254,6 @@ m_init_complete (FpiSsm *ssm, FpDevice *_dev, GError *error)
}
/* Free sequential state machine */
fpi_ssm_free (ssm);
}
/* Activate device */

View File

@@ -28,17 +28,6 @@ G_DEFINE_TYPE (FpDeviceVfs301, fpi_device_vfs301, FP_TYPE_IMAGE_DEVICE)
/************************** GENERIC STUFF *************************************/
/* Submit asynchronous sleep */
static void
async_sleep (unsigned int msec,
FpiSsm *ssm,
FpImageDevice *dev)
{
/* Add timeout */
fpi_device_add_timeout (FP_DEVICE (dev), msec,
fpi_ssm_next_state_timeout_cb, ssm);
}
static int
submit_image (FpiSsm *ssm,
FpImageDevice *dev)
@@ -108,7 +97,7 @@ m_loop_state (FpiSsm *ssm, FpDevice *_dev)
case M_WAIT_PRINT:
/* Wait fingerprint scanning */
async_sleep (200, ssm, dev);
fpi_ssm_next_state_delayed (ssm, 200, NULL);
break;
case M_CHECK_PRINT:
@@ -126,7 +115,7 @@ m_loop_state (FpiSsm *ssm, FpDevice *_dev)
case M_READ_PRINT_WAIT:
/* Wait fingerprint scanning */
async_sleep (200, ssm, dev);
fpi_ssm_next_state_delayed (ssm, 200, NULL);
break;
case M_READ_PRINT_POLL:
@@ -168,7 +157,6 @@ m_loop_complete (FpiSsm *ssm, FpDevice *_dev, GError *error)
g_error_free (error);
}
/* Free sequential state machine */
fpi_ssm_free (ssm);
}
/* Exec init sequential state machine */
@@ -201,7 +189,6 @@ m_init_complete (FpiSsm *ssm, FpDevice *dev, GError *error)
}
/* Free sequential state machine */
fpi_ssm_free (ssm);
}
/* Activate device */

View File

@@ -79,7 +79,6 @@ usb_recv (FpDeviceVfs301 *dev, guint8 endpoint, int max_bytes, FpiUsbTransfer **
fpi_usb_transfer_submit_sync (transfer, VFS301_DEFAULT_WAIT_TIMEOUT, &err);
#ifdef DEBUG
usb_print_packet (0, err, transfer->buffer, transfer->actual_length);
#endif
@@ -471,7 +470,7 @@ int
vfs301_proto_peek_event (FpDeviceVfs301 *dev)
{
g_autoptr(GError) error = NULL;
g_autoptr(FpiUsbTransfer) transfer = NULL;
FpiUsbTransfer *transfer;
const char no_event[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
const char got_event[] = {0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00};
@@ -500,7 +499,7 @@ vfs301_proto_peek_event (FpDeviceVfs301 *dev)
usb_recv (dev, e1, l1, NULL, &error); \
usb_recv (dev, e2, l2, NULL, NULL); \
if (g_error_matches (error, G_USB_DEVICE_ERROR, G_USB_DEVICE_ERROR_TIMED_OUT)) \
usb_recv(dev, e1, l1, NULL, NULL); \
usb_recv (dev, e1, l1, NULL, NULL); \
}
static void
@@ -540,7 +539,6 @@ vfs301_proto_process_event_cb (FpiUsbTransfer *transfer,
fpi_usb_transfer_fill_bulk (new, VFS301_RECEIVE_ENDPOINT_DATA, VFS301_FP_RECV_LEN_2);
fpi_usb_transfer_submit (new, VFS301_FP_RECV_TIMEOUT, NULL,
vfs301_proto_process_event_cb, NULL);
fpi_usb_transfer_unref (new);
return;
}
}
@@ -580,7 +578,6 @@ vfs301_proto_process_event_start (FpDeviceVfs301 *dev)
fpi_usb_transfer_fill_bulk (transfer, VFS301_RECEIVE_ENDPOINT_DATA, VFS301_FP_RECV_LEN_1);
fpi_usb_transfer_submit (transfer, VFS301_FP_RECV_TIMEOUT, NULL,
vfs301_proto_process_event_cb, NULL);
fpi_usb_transfer_unref (transfer);
}
int

View File

@@ -168,7 +168,6 @@ usbexchange_loop (FpiSsm *ssm, FpDevice *_dev)
transfer->short_is_error = TRUE;
fpi_usb_transfer_submit (transfer, data->timeout, NULL,
async_send_cb, NULL);
fpi_usb_transfer_unref (transfer);
break;
case ACTION_RECEIVE:
@@ -180,7 +179,6 @@ usbexchange_loop (FpiSsm *ssm, FpDevice *_dev)
transfer->ssm = ssm;
fpi_usb_transfer_submit (transfer, data->timeout, NULL,
async_recv_cb, NULL);
fpi_usb_transfer_unref (transfer);
break;
default:
@@ -192,11 +190,13 @@ usbexchange_loop (FpiSsm *ssm, FpDevice *_dev)
static void
usb_exchange_async (FpiSsm *ssm,
struct usbexchange_data *data)
struct usbexchange_data *data,
const char *exchange_name)
{
FpiSsm *subsm = fpi_ssm_new (FP_DEVICE (data->device),
usbexchange_loop,
data->stepcount);
FpiSsm *subsm = fpi_ssm_new_full (FP_DEVICE (data->device),
usbexchange_loop,
data->stepcount,
exchange_name);
fpi_ssm_set_data (subsm, data, NULL);
fpi_ssm_start_subsm (ssm, subsm);
@@ -212,8 +212,8 @@ vfs5011_get_deviation2 (struct fpi_line_asmbl_ctx *ctx, GSList *row1, GSList *ro
int res = 0, mean = 0, i;
const int size = 64;
buf1 = row1->data + 56;
buf2 = row2->data + 168;
buf1 = (unsigned char *) row1->data + 56;
buf2 = (unsigned char *) row2->data + 168;
for (i = 0; i < size; i++)
mean += (int) buf1[i] + (int) buf2[i];
@@ -234,7 +234,7 @@ vfs5011_get_pixel (struct fpi_line_asmbl_ctx *ctx,
GSList *row,
unsigned x)
{
unsigned char *data = row->data + 8;
unsigned char *data = (unsigned char *) row->data + 8;
return data[x];
}
@@ -466,7 +466,6 @@ capture_chunk_async (FpDeviceVfs5011 *self,
transfer->ssm = ssm;
fpi_usb_transfer_submit (transfer, timeout, fpi_device_get_cancellable (FP_DEVICE (self)),
chunk_capture_callback, NULL);
fpi_usb_transfer_unref (transfer);
}
/*
@@ -687,7 +686,7 @@ activate_loop (FpiSsm *ssm, FpDevice *_dev)
self->init_sequence.receive_buf =
g_malloc0 (VFS5011_RECEIVE_BUF_SIZE);
self->init_sequence.timeout = 1000;
usb_exchange_async (ssm, &self->init_sequence);
usb_exchange_async (ssm, &self->init_sequence, "ACTIVATE REQUEST");
break;
case DEV_ACTIVATE_INIT_COMPLETE:
@@ -707,10 +706,7 @@ activate_loop (FpiSsm *ssm, FpDevice *_dev)
break;
case DEV_ACTIVATE_DATA_COMPLETE:
fpi_device_add_timeout (_dev, 1,
fpi_ssm_next_state_timeout_cb,
ssm);
fpi_ssm_next_state_delayed (ssm, 1, NULL);
break;
case DEV_ACTIVATE_PREPARE_NEXT_CAPTURE:
@@ -722,7 +718,7 @@ activate_loop (FpiSsm *ssm, FpDevice *_dev)
self->init_sequence.receive_buf =
g_malloc0 (VFS5011_RECEIVE_BUF_SIZE);
self->init_sequence.timeout = VFS5011_DEFAULT_WAIT_TIMEOUT;
usb_exchange_async (ssm, &self->init_sequence);
usb_exchange_async (ssm, &self->init_sequence, "PREPARE CAPTURE");
break;
}
@@ -745,7 +741,6 @@ activate_loop_complete (FpiSsm *ssm, FpDevice *_dev, GError *error)
submit_image (ssm, self, dev);
fpi_image_device_report_finger_status (dev, FALSE);
}
fpi_ssm_free (ssm);
self->loop_running = FALSE;
@@ -776,7 +771,7 @@ open_loop (FpiSsm *ssm, FpDevice *_dev)
self->init_sequence.receive_buf =
g_malloc0 (VFS5011_RECEIVE_BUF_SIZE);
self->init_sequence.timeout = VFS5011_DEFAULT_WAIT_TIMEOUT;
usb_exchange_async (ssm, &self->init_sequence);
usb_exchange_async (ssm, &self->init_sequence, "DEVICE OPEN");
break;
}
;
@@ -793,7 +788,6 @@ open_loop_complete (FpiSsm *ssm, FpDevice *_dev, GError *error)
self->init_sequence.receive_buf = NULL;
fpi_image_device_open_complete (dev, error);
fpi_ssm_free (ssm);
}
static void

View File

@@ -47,6 +47,7 @@ struct _FpDeviceVirtualImage
gint socket_fd;
gint client_fd;
gboolean automatic_finger;
FpImage *recv_img;
gint recv_img_hdr[2];
};
@@ -66,31 +67,34 @@ recv_image_img_recv_cb (GObject *source_object,
g_autoptr(GError) error = NULL;
FpDeviceVirtualImage *self;
FpImageDevice *device;
gssize bytes;
gboolean success;
gsize bytes = 0;
bytes = g_input_stream_read_finish (G_INPUT_STREAM (source_object), res, &error);
success = g_input_stream_read_all_finish (G_INPUT_STREAM (source_object), res, &bytes, &error);
if (bytes <= 0)
if (!success || bytes == 0)
{
if (bytes < 0)
if (!success)
{
g_warning ("Error receiving header for image data: %s", error->message);
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
return;
g_warning ("Error receiving header for image data: %s", error->message);
}
self = FPI_DEVICE_VIRTUAL_IMAGE (user_data);
g_io_stream_close (G_IO_STREAM (self->connection), NULL, NULL);
self->connection = NULL;
g_clear_object (&self->connection);
return;
}
self = FPI_DEVICE_VIRTUAL_IMAGE (user_data);
device = FP_IMAGE_DEVICE (self);
fpi_image_device_report_finger_status (device, TRUE);
if (self->automatic_finger)
fpi_image_device_report_finger_status (device, TRUE);
fpi_image_device_image_captured (device, g_steal_pointer (&self->recv_img));
fpi_image_device_report_finger_status (device, FALSE);
if (self->automatic_finger)
fpi_image_device_report_finger_status (device, FALSE);
/* And, listen for more images from the same client. */
recv_image (self, G_INPUT_STREAM (source_object));
@@ -103,22 +107,24 @@ recv_image_hdr_recv_cb (GObject *source_object,
{
g_autoptr(GError) error = NULL;
FpDeviceVirtualImage *self;
gssize bytes;
gboolean success;
gsize bytes;
bytes = g_input_stream_read_finish (G_INPUT_STREAM (source_object), res, &error);
success = g_input_stream_read_all_finish (G_INPUT_STREAM (source_object), res, &bytes, &error);
if (bytes <= 0)
if (!success || bytes == 0)
{
if (bytes < 0)
if (!success)
{
g_warning ("Error receiving header for image data: %s", error->message);
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED) ||
g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CLOSED))
return;
g_warning ("Error receiving header for image data: %s", error->message);
}
self = FPI_DEVICE_VIRTUAL_IMAGE (user_data);
g_io_stream_close (G_IO_STREAM (self->connection), NULL, NULL);
self->connection = NULL;
g_clear_object (&self->connection);
return;
}
@@ -127,7 +133,7 @@ recv_image_hdr_recv_cb (GObject *source_object,
{
g_warning ("Image header suggests an unrealistically large image, disconnecting client.");
g_io_stream_close (G_IO_STREAM (self->connection), NULL, NULL);
self->connection = NULL;
g_clear_object (&self->connection);
}
if (self->recv_img_hdr[0] < 0 || self->recv_img_hdr[1] < 0)
@@ -145,10 +151,21 @@ recv_image_hdr_recv_cb (GObject *source_object,
fpi_device_error_new (self->recv_img_hdr[1]));
break;
case -3:
/* -3 sets/clears automatic finger detection for images */
self->automatic_finger = !!self->recv_img_hdr[1];
break;
case -4:
/* -4 submits a finger detection report */
fpi_image_device_report_finger_status (FP_IMAGE_DEVICE (self),
!!self->recv_img_hdr[1]);
break;
default:
/* disconnect client, it didn't play fair */
g_io_stream_close (G_IO_STREAM (self->connection), NULL, NULL);
self->connection = NULL;
g_clear_object (&self->connection);
}
/* And, listen for more images from the same client. */
@@ -158,25 +175,25 @@ recv_image_hdr_recv_cb (GObject *source_object,
self->recv_img = fp_image_new (self->recv_img_hdr[0], self->recv_img_hdr[1]);
g_debug ("image data: %p", self->recv_img->data);
g_input_stream_read_async (G_INPUT_STREAM (source_object),
(guint8 *) self->recv_img->data,
self->recv_img->width * self->recv_img->height,
G_PRIORITY_DEFAULT,
self->cancellable,
recv_image_img_recv_cb,
self);
g_input_stream_read_all_async (G_INPUT_STREAM (source_object),
(guint8 *) self->recv_img->data,
self->recv_img->width * self->recv_img->height,
G_PRIORITY_DEFAULT,
self->cancellable,
recv_image_img_recv_cb,
self);
}
static void
recv_image (FpDeviceVirtualImage *dev, GInputStream *stream)
{
g_input_stream_read_async (stream,
dev->recv_img_hdr,
sizeof (dev->recv_img_hdr),
G_PRIORITY_DEFAULT,
dev->cancellable,
recv_image_hdr_recv_cb,
dev);
g_input_stream_read_all_async (stream,
dev->recv_img_hdr,
sizeof (dev->recv_img_hdr),
G_PRIORITY_DEFAULT,
dev->cancellable,
recv_image_hdr_recv_cb,
dev);
}
static void
@@ -206,10 +223,12 @@ new_connection_cb (GObject *source_object, GAsyncResult *res, gpointer user_data
if (dev->connection)
{
g_io_stream_close (G_IO_STREAM (connection), NULL, NULL);
g_object_unref (connection);
return;
}
dev->connection = connection;
dev->automatic_finger = TRUE;
stream = g_io_stream_get_input_stream (G_IO_STREAM (connection));
recv_image (dev, stream);

View File

@@ -186,6 +186,8 @@ fp_context_finalize (GObject *object)
g_cancellable_cancel (priv->cancellable);
g_clear_object (&priv->cancellable);
g_clear_pointer (&priv->drivers, g_array_unref);
g_object_run_dispose (G_OBJECT (priv->usb_ctx));
g_clear_object (&priv->usb_ctx);
G_OBJECT_CLASS (fp_context_parent_class)->finalize (object);

View File

@@ -1,6 +1,7 @@
/*
* FpDevice - A fingerprint reader device
* Copyright (C) 2019 Benjamin Berg <bberg@redhat.com>
* Copyright (C) 2019 Marco Trevisan <marco.trevisan@canonical.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -242,9 +243,18 @@ fpi_device_error_new (FpDeviceError error)
* and similar calls.
*/
GError *
fpi_device_retry_new_msg (FpDeviceRetry error, const gchar *msg)
fpi_device_retry_new_msg (FpDeviceRetry device_error,
const gchar *msg,
...)
{
return g_error_new_literal (FP_DEVICE_RETRY, error, msg);
GError *error;
va_list args;
va_start (args, msg);
error = g_error_new_valist (FP_DEVICE_RETRY, device_error, msg, args);
va_end (args);
return error;
}
/**
@@ -256,9 +266,18 @@ fpi_device_retry_new_msg (FpDeviceRetry error, const gchar *msg)
* and similar calls.
*/
GError *
fpi_device_error_new_msg (FpDeviceError error, const gchar *msg)
fpi_device_error_new_msg (FpDeviceError device_error,
const gchar *msg,
...)
{
return g_error_new_literal (FP_DEVICE_ERROR, error, msg);
GError *error;
va_list args;
va_start (args, msg);
error = g_error_new_valist (FP_DEVICE_ERROR, device_error, msg, args);
va_end (args);
return error;
}
static gboolean
@@ -363,6 +382,7 @@ fp_device_finalize (GObject *object)
g_clear_pointer (&priv->device_id, g_free);
g_clear_pointer (&priv->device_name, g_free);
g_clear_object (&priv->usb_device);
G_OBJECT_CLASS (fp_device_parent_class)->finalize (object);
}
@@ -1362,23 +1382,11 @@ fp_device_list_prints_finish (FpDevice *device,
typedef struct
{
GSource source;
FpDevice *device;
FpTimeoutFunc callback;
gpointer user_data;
GSource source;
FpDevice *device;
} FpDeviceTimeoutSource;
gboolean
device_timeout_cb (gpointer user_data)
{
FpDeviceTimeoutSource *source = user_data;
source->callback (source->device, source->user_data);
return G_SOURCE_REMOVE;
}
void
static void
timeout_finalize (GSource *source)
{
FpDeviceTimeoutSource *timeout_source = (FpDeviceTimeoutSource *) source;
@@ -1389,11 +1397,12 @@ timeout_finalize (GSource *source)
}
static gboolean
timeout_dispatch (GSource *source, GSourceFunc callback, gpointer user_data)
timeout_dispatch (GSource *source, GSourceFunc gsource_func, gpointer user_data)
{
FpDeviceTimeoutSource *timeout_source = (FpDeviceTimeoutSource *) source;
FpTimeoutFunc callback = (FpTimeoutFunc) gsource_func;
((FpTimeoutFunc) callback)(timeout_source->device, user_data);
callback (timeout_source->device, user_data);
return G_SOURCE_REMOVE;
}
@@ -1455,7 +1464,8 @@ fpi_device_set_scan_type (FpDevice *device,
* @device: The #FpDevice
* @interval: The interval in milliseconds
* @func: The #FpTimeoutFunc to call on timeout
* @user_data: User data to pass to the callback
* @user_data: (nullable): User data to pass to the callback
* @destroy_notify: (nullable): #GDestroyNotify for @user_data
*
* Register a timeout to run. Drivers should always make sure that timers are
* cancelled when appropriate.
@@ -1463,10 +1473,11 @@ fpi_device_set_scan_type (FpDevice *device,
* Returns: (transfer none): A newly created and attached #GSource
*/
GSource *
fpi_device_add_timeout (FpDevice *device,
gint interval,
FpTimeoutFunc func,
gpointer user_data)
fpi_device_add_timeout (FpDevice *device,
gint interval,
FpTimeoutFunc func,
gpointer user_data,
GDestroyNotify destroy_notify)
{
FpDevicePrivate *priv = fp_device_get_instance_private (device);
FpDeviceTimeoutSource *source;
@@ -1474,10 +1485,9 @@ fpi_device_add_timeout (FpDevice *device,
source = (FpDeviceTimeoutSource *) g_source_new (&timeout_funcs,
sizeof (FpDeviceTimeoutSource));
source->device = device;
source->user_data = user_data;
g_source_attach (&source->source, NULL);
g_source_set_callback (&source->source, (GSourceFunc) func, user_data, NULL);
g_source_set_callback (&source->source, (GSourceFunc) func, user_data, destroy_notify);
g_source_set_ready_time (&source->source,
g_source_get_time (&source->source) + interval * (guint64) 1000);
priv->sources = g_slist_prepend (priv->sources, source);
@@ -2322,8 +2332,9 @@ fpi_device_enroll_progress (FpDevice *device,
data->enroll_progress_data,
error);
}
if (error)
g_error_free (error);
g_clear_error (&error);
g_clear_object (&print);
}

View File

@@ -113,8 +113,8 @@ GQuark fp_device_error_quark (void);
* FpEnrollProgress:
* @device: a #FpDevice
* @completed_stages: Number of completed stages
* @print: (nullable): The last scaned print
* @user_data: (nullable): User provided data
* @print: (nullable) (transfer none): The last scaned print
* @user_data: (nullable) (transfer none): User provided data
* @error: (nullable) (transfer none): #GError or %NULL
*
* The passed error is guaranteed to be of type %FP_DEVICE_RETRY if set.

View File

@@ -21,6 +21,7 @@
#include "fpi-log.h"
#include "fpi-image-device.h"
#include "fpi-enums.h"
#include "fpi-print.h"
#include "fpi-image.h"
@@ -49,7 +50,9 @@ typedef struct
{
FpImageDeviceState state;
gboolean active;
gboolean cancelling;
gboolean enroll_await_on_pending;
gint enroll_stage;
guint pending_activation_timeout_id;
@@ -60,6 +63,21 @@ typedef struct
G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (FpImageDevice, fp_image_device, FP_TYPE_DEVICE)
enum {
PROP_0,
PROP_FPI_STATE,
N_PROPS
};
static GParamSpec *properties[N_PROPS];
enum {
FPI_STATE_CHANGED,
LAST_SIGNAL
};
static guint signals[LAST_SIGNAL] = { 0 };
/*******************************************************/
@@ -73,27 +91,19 @@ static void
fp_image_device_change_state (FpImageDevice *self, FpImageDeviceState state)
{
FpImageDevicePrivate *priv = fp_image_device_get_instance_private (self);
FpImageDeviceClass *cls = FP_IMAGE_DEVICE_GET_CLASS (self);
/* Cannot change to inactive using this function. */
g_assert (state != FP_IMAGE_DEVICE_STATE_INACTIVE);
/* We might have been waiting for the finger to go OFF to start the
* next operation. */
if (priv->pending_activation_timeout_id)
{
g_source_remove (priv->pending_activation_timeout_id);
priv->pending_activation_timeout_id = 0;
}
g_clear_handle_id (&priv->pending_activation_timeout_id, g_source_remove);
fp_dbg ("Image device internal state change from %d to %d\n", priv->state, state);
priv->state = state;
/* change_state is the only callback which is optional and does not
* have a default implementation. */
if (cls->change_state)
cls->change_state (self, state);
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_FPI_STATE]);
g_signal_emit (self, signals[FPI_STATE_CHANGED], 0, priv->state);
}
static void
@@ -107,14 +117,11 @@ fp_image_device_activate (FpImageDevice *self)
/* We don't have a neutral ACTIVE state, but we always will
* go into WAIT_FINGER_ON afterwards. */
priv->state = FP_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON;
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_FPI_STATE]);
/* We might have been waiting for deactivation to finish before
* starting the next operation. */
if (priv->pending_activation_timeout_id)
{
g_source_remove (priv->pending_activation_timeout_id);
priv->pending_activation_timeout_id = 0;
}
g_clear_handle_id (&priv->pending_activation_timeout_id, g_source_remove);
fp_dbg ("Activating image device\n");
cls->activate (self);
@@ -134,7 +141,11 @@ fp_image_device_deactivate (FpDevice *device)
fp_dbg ("Already deactivated, ignoring request.");
return;
}
if (!priv->cancelling && priv->state == FP_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON)
g_warning ("Deactivating image device while waiting for finger, this should not happen.");
priv->state = FP_IMAGE_DEVICE_STATE_INACTIVE;
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_FPI_STATE]);
fp_dbg ("Deactivating image device\n");
cls->deactivate (self);
@@ -196,6 +207,7 @@ static void
fp_image_device_cancel_action (FpDevice *device)
{
FpImageDevice *self = FP_IMAGE_DEVICE (device);
FpImageDevicePrivate *priv = fp_image_device_get_instance_private (self);
FpDeviceAction action;
action = fpi_device_get_current_action (device);
@@ -207,7 +219,9 @@ fp_image_device_cancel_action (FpDevice *device)
action == FP_DEVICE_ACTION_IDENTIFY ||
action == FP_DEVICE_ACTION_CAPTURE)
{
priv->cancelling = TRUE;
fp_image_device_deactivate (FP_DEVICE (self));
priv->cancelling = FALSE;
/* XXX: Some nicer way of doing this would be good. */
fpi_device_action_error (FP_DEVICE (self),
@@ -250,6 +264,7 @@ fp_image_device_start_capture_action (FpDevice *device)
}
priv->enroll_stage = 0;
priv->enroll_await_on_pending = FALSE;
/* The device might still be deactivating from a previous call.
* In that situation, try to wait for a bit before reporting back an
@@ -286,6 +301,7 @@ fp_image_device_finalize (GObject *object)
FpImageDevicePrivate *priv = fp_image_device_get_instance_private (self);
g_assert (priv->active == FALSE);
g_clear_handle_id (&priv->pending_activation_timeout_id, g_source_remove);
G_OBJECT_CLASS (fp_image_device_parent_class)->finalize (object);
}
@@ -302,6 +318,26 @@ fp_image_device_default_deactivate (FpImageDevice *self)
fpi_image_device_deactivate_complete (self, NULL);
}
static void
fp_image_device_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
FpImageDevice *self = FP_IMAGE_DEVICE (object);
FpImageDevicePrivate *priv = fp_image_device_get_instance_private (self);
switch (prop_id)
{
case PROP_FPI_STATE:
g_value_set_enum (value, priv->state);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
static void
fp_image_device_class_init (FpImageDeviceClass *klass)
{
@@ -309,6 +345,7 @@ fp_image_device_class_init (FpImageDeviceClass *klass)
FpDeviceClass *fp_device_class = FP_DEVICE_CLASS (klass);
object_class->finalize = fp_image_device_finalize;
object_class->get_property = fp_image_device_get_property;
fp_device_class->open = fp_image_device_open;
fp_device_class->close = fp_image_device_close;
@@ -322,6 +359,24 @@ fp_image_device_class_init (FpImageDeviceClass *klass)
/* Default implementations */
klass->activate = fp_image_device_default_activate;
klass->deactivate = fp_image_device_default_deactivate;
properties[PROP_FPI_STATE] =
g_param_spec_enum ("fp-image-device-state",
"Image Device State",
"Private: The state of the image device",
FP_TYPE_IMAGE_DEVICE_STATE,
FP_IMAGE_DEVICE_STATE_INACTIVE,
G_PARAM_STATIC_STRINGS | G_PARAM_READABLE);
signals[FPI_STATE_CHANGED] =
g_signal_new ("fp-image-device-state-changed",
G_TYPE_FROM_CLASS (object_class),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (FpImageDeviceClass, change_state),
NULL, NULL, NULL,
G_TYPE_NONE, 1, FP_TYPE_IMAGE_DEVICE_STATE);
g_object_class_install_properties (object_class, N_PROPS, properties);
}
static void
@@ -339,12 +394,28 @@ fp_image_device_init (FpImageDevice *self)
}
static void
fp_image_device_enroll_maybe_await_finger_on (FpImageDevice *self)
{
FpImageDevicePrivate *priv = fp_image_device_get_instance_private (self);
if (priv->enroll_await_on_pending)
{
priv->enroll_await_on_pending = FALSE;
fp_image_device_change_state (self, FP_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON);
}
else
{
priv->enroll_await_on_pending = TRUE;
}
}
static void
fpi_image_device_minutiae_detected (GObject *source_object, GAsyncResult *res, gpointer user_data)
{
g_autoptr(FpImage) image = FP_IMAGE (source_object);
g_autoptr(FpPrint) print = NULL;
GError *error = NULL;
FpPrint *print = NULL;
FpDevice *device = FP_DEVICE (user_data);
FpImageDevicePrivate *priv;
FpDeviceAction action;
@@ -397,13 +468,19 @@ fpi_image_device_minutiae_detected (GObject *source_object, GAsyncResult *res, g
priv->enroll_stage += 1;
}
fpi_device_enroll_progress (device, priv->enroll_stage, print, error);
fpi_device_enroll_progress (device, priv->enroll_stage,
g_steal_pointer (&print), error);
/* Start another scan or deactivate. */
if (priv->enroll_stage == IMG_ENROLL_STAGES)
{
fpi_device_enroll_complete (device, g_object_ref (enroll_print), NULL);
fp_image_device_deactivate (device);
}
else
{
fp_image_device_enroll_maybe_await_finger_on (FP_IMAGE_DEVICE (device));
}
}
else if (action == FP_DEVICE_ACTION_VERIFY)
{
@@ -416,7 +493,7 @@ fpi_image_device_minutiae_detected (GObject *source_object, GAsyncResult *res, g
else
result = FPI_MATCH_ERROR;
fpi_device_verify_complete (device, result, print, error);
fpi_device_verify_complete (device, result, g_steal_pointer (&print), error);
fp_image_device_deactivate (device);
}
else if (action == FP_DEVICE_ACTION_IDENTIFY)
@@ -437,7 +514,7 @@ fpi_image_device_minutiae_detected (GObject *source_object, GAsyncResult *res, g
}
}
fpi_device_identify_complete (device, result, print, error);
fpi_device_identify_complete (device, result, g_steal_pointer (&print), error);
fp_image_device_deactivate (device);
}
else
@@ -493,8 +570,6 @@ fpi_image_device_report_finger_status (FpImageDevice *self,
FpImageDevicePrivate *priv = fp_image_device_get_instance_private (self);
FpDeviceAction action;
action = fpi_device_get_current_action (device);
if (priv->state == FP_IMAGE_DEVICE_STATE_INACTIVE)
{
/* Do we really want to always ignore such reports? We could
@@ -527,13 +602,15 @@ fpi_image_device_report_finger_status (FpImageDevice *self,
* 2. We are still deactivating the device after an action completed
* 3. We were waiting for finger removal to start the new action
* Either way, we always end up deactivating except for the enroll case.
* XXX: This is not quite correct though, as we assume we need another finger
* scan even though we might be processing the last one (successfully).
*
* The enroll case is special as AWAIT_FINGER_ON should only happen after
* minutiae detection to prevent deactivation (without cancellation)
* from the AWAIT_FINGER_ON state.
*/
if (action != FP_DEVICE_ACTION_ENROLL)
fp_image_device_deactivate (device);
else
fp_image_device_change_state (self, FP_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON);
fp_image_device_enroll_maybe_await_finger_on (self);
}
}
@@ -741,7 +818,11 @@ fpi_image_device_deactivate_complete (FpImageDevice *self, GError *error)
/* We might be waiting to be able to activate again. */
if (priv->pending_activation_timeout_id)
fp_image_device_activate (self);
{
g_clear_handle_id (&priv->pending_activation_timeout_id, g_source_remove);
priv->pending_activation_timeout_id =
g_idle_add ((GSourceFunc) fp_image_device_activate, self);
}
}
/**
@@ -765,6 +846,7 @@ fpi_image_device_open_complete (FpImageDevice *self, GError *error)
g_debug ("Image device open completed");
priv->state = FP_IMAGE_DEVICE_STATE_INACTIVE;
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_FPI_STATE]);
fpi_device_open_complete (FP_DEVICE (self), error);
}
@@ -790,6 +872,7 @@ fpi_image_device_close_complete (FpImageDevice *self, GError *error)
g_return_if_fail (action == FP_DEVICE_ACTION_CLOSE);
priv->state = FP_IMAGE_DEVICE_STATE_INACTIVE;
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_FPI_STATE]);
fpi_device_close_complete (FP_DEVICE (self), error);
}

View File

@@ -19,8 +19,9 @@
*/
#include "fpi-image.h"
#include "fpi-log.h"
#include "nbis/include/lfs.h"
#include <nbis.h>
#if HAVE_PIXMAN
#include <pixman.h>

View File

@@ -20,10 +20,10 @@
#include "fpi-print.h"
#include "fpi-image.h"
#include "fpi-log.h"
#include "fpi-device.h"
#include "nbis/include/bozorth.h"
#include "nbis/include/lfs.h"
#include <nbis.h>
/**
* SECTION: fp-print
@@ -101,6 +101,7 @@ fp_print_finalize (GObject *object)
g_clear_pointer (&self->description, g_free);
g_clear_pointer (&self->enroll_date, g_date_free);
g_clear_pointer (&self->data, g_variant_unref);
g_clear_pointer (&self->prints, g_ptr_array_unref);
G_OBJECT_CLASS (fp_print_parent_class)->finalize (object);
}
@@ -206,7 +207,7 @@ fp_print_set_property (GObject *object,
break;
case PROP_FPI_DATA:
g_clear_pointer (&self->description, g_variant_unref);
g_clear_pointer (&self->data, g_variant_unref);
self->data = g_value_dup_variant (value);
break;
@@ -534,11 +535,8 @@ fp_print_set_enroll_date (FpPrint *print,
g_clear_pointer (&print->enroll_date, g_date_free);
if (enroll_date)
{
/* XXX: Should use g_date_copy, but that is new in 2.56. */
print->enroll_date = g_date_new ();
*print->enroll_date = *enroll_date;
}
print->enroll_date = g_date_copy (enroll_date);
g_object_notify_by_pspec (G_OBJECT (print), properties[PROP_ENROLL_DATE]);
}
@@ -582,7 +580,10 @@ fpi_print_set_type (FpPrint *print,
print->type = type;
if (print->type == FP_PRINT_NBIS)
print->prints = g_ptr_array_new_with_free_func (g_free);
{
g_assert_null (print->prints);
print->prints = g_ptr_array_new_with_free_func (g_free);
}
g_object_notify_by_pspec (G_OBJECT (print), properties[PROP_FPI_TYPE]);
}
@@ -921,6 +922,7 @@ fp_print_serialize (FpPrint *print,
xyt->nrows,
sizeof (col[0])));
g_variant_builder_close (&nested);
g_free (col);
}
g_variant_builder_close (&nested);
@@ -976,6 +978,7 @@ fp_print_deserialize (const guchar *data,
g_autoptr(FpPrint) result = NULL;
g_autoptr(GVariant) raw_value = NULL;
g_autoptr(GVariant) value = NULL;
g_autoptr(GVariant) print_data = NULL;
guchar *aligned_data = NULL;
GDate *date = NULL;
guint8 finger_int8;
@@ -987,7 +990,6 @@ fp_print_deserialize (const guchar *data,
const gchar *driver;
const gchar *device_id;
gboolean device_stored;
GVariant *print_data;
g_assert (data);
g_assert (length > 3);
@@ -1007,7 +1009,7 @@ fp_print_deserialize (const guchar *data,
memcpy (aligned_data, data + 3, length - 3);
raw_value = g_variant_new_from_data (FP_PRINT_VARIANT_TYPE,
aligned_data, length - 3,
FALSE, g_free, NULL);
FALSE, g_free, aligned_data);
if (!raw_value)
goto invalid_format;
@@ -1018,7 +1020,7 @@ fp_print_deserialize (const guchar *data,
value = g_variant_get_normal_form (raw_value);
g_variant_get (value,
"(issbymsmsi@a{sv}v)",
"(i&s&sbymsmsi@a{sv}v)",
&type,
&driver,
&device_id,
@@ -1046,7 +1048,7 @@ fp_print_deserialize (const guchar *data,
fpi_print_set_type (result, FP_PRINT_NBIS);
for (i = 0; i < g_variant_n_children (prints); i++)
{
struct xyt_struct *xyt = g_new0 (struct xyt_struct, 1);
g_autofree struct xyt_struct *xyt = g_new0 (struct xyt_struct, 1);
const gint32 *xcol, *ycol, *thetacol;
gsize xlen, ylen, thetalen;
g_autoptr(GVariant) xyt_data = NULL;
@@ -1077,7 +1079,7 @@ fp_print_deserialize (const guchar *data,
memcpy (xyt->ycol, ycol, sizeof (xcol[0]) * xlen);
memcpy (xyt->thetacol, thetacol, sizeof (xcol[0]) * xlen);
g_ptr_array_add (result->prints, xyt);
g_ptr_array_add (result->prints, g_steal_pointer (&xyt));
}
}
else if (type == FP_PRINT_RAW)

View File

@@ -1,6 +1,6 @@
/*
* Internal/private definitions for libfprint
* Copyright (C) 2007-2008 Daniel Drake <dsd@gentoo.org>
* Copyright (C) 2019 Marco Trevisan <marco.trevisan@canonical.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -17,38 +17,9 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __FPRINT_INTERNAL_H__
#define __FPRINT_INTERNAL_H__
#pragma once
#include "fpi-log.h"
#include "nbis-helpers.h"
#include "fpi-image.h"
#include "fpi-image-device.h"
/* fp_minutia structure definition */
struct fp_minutia
{
int x;
int y;
int ex;
int ey;
int direction;
double reliability;
int type;
int appearing;
int feature_id;
int *nbrs;
int *ridge_counts;
int num_nbrs;
};
/* fp_minutiae structure definition */
struct fp_minutiae
{
int alloc;
int num;
struct fp_minutia **list;
};
#endif
#include "fpi-minutiae.h"

View File

@@ -385,8 +385,10 @@ median_filter (int *data, int size, int filtersize)
static void
interpolate_lines (struct fpi_line_asmbl_ctx *ctx,
GSList *line1, float y1, GSList *line2,
float y2, unsigned char *output, float yi, int size)
GSList *line1, gint32 y1_f,
GSList *line2, gint32 y2_f,
unsigned char *output, gint32 yi_f,
int size)
{
int i;
unsigned char p1, p2;
@@ -396,10 +398,12 @@ interpolate_lines (struct fpi_line_asmbl_ctx *ctx,
for (i = 0; i < size; i++)
{
gint unscaled;
p1 = ctx->get_pixel (ctx, line1, i);
p2 = ctx->get_pixel (ctx, line2, i);
output[i] = (float) p1
+ (yi - y1) / (y2 - y1) * (p2 - p1);
unscaled = (yi_f - y1_f) * p2 + (y2_f - yi_f) * p1;
output[i] = (unscaled) / (y2_f - y1_f);
}
}
@@ -424,7 +428,13 @@ fpi_assemble_lines (struct fpi_line_asmbl_ctx *ctx,
/* Number of output lines per distance between two scanners */
int i;
GSList *row1, *row2;
float y = 0.0;
/* The y coordinate is tracked as a 16.16 fixed point number. All
* variables postfixed with _f follow this format here and in
* interpolate_lines.
* We could also use floating point here, but using fixed point means
* we get consistent results across architectures.
*/
gint32 y_f = 0;
int line_ind = 0;
int *offsets = g_new0 (int, num_lines / 2);
unsigned char *output = g_malloc0 (ctx->line_width * ctx->max_height);
@@ -476,21 +486,21 @@ fpi_assemble_lines (struct fpi_line_asmbl_ctx *ctx,
int offset = offsets[i / 2];
if (offset > 0)
{
float ynext = y + (float) ctx->resolution / offset;
while (line_ind < ynext)
gint32 ynext_f = y_f + (ctx->resolution << 16) / offset;
while ((line_ind << 16) < ynext_f)
{
if (line_ind > ctx->max_height - 1)
goto out;
interpolate_lines (ctx,
row1, y,
row1, y_f,
g_slist_next (row1),
ynext,
ynext_f,
output + line_ind * ctx->line_width,
line_ind,
line_ind << 16,
ctx->line_width);
line_ind++;
}
y = ynext;
y_f = ynext_f;
}
}
out:

View File

@@ -181,9 +181,11 @@ GError * fpi_device_retry_new (FpDeviceRetry error);
GError * fpi_device_error_new (FpDeviceError error);
GError * fpi_device_retry_new_msg (FpDeviceRetry error,
const gchar *msg);
const gchar *msg,
...) G_GNUC_PRINTF (2, 3);
GError * fpi_device_error_new_msg (FpDeviceError error,
const gchar *msg);
const gchar *msg,
...) G_GNUC_PRINTF (2, 3);
guint64 fpi_device_get_driver_data (FpDevice *device);
@@ -201,11 +203,11 @@ void fpi_device_get_delete_data (FpDevice *device,
GCancellable *fpi_device_get_cancellable (FpDevice *device);
GSource * fpi_device_add_timeout (FpDevice *device,
gint interval,
FpTimeoutFunc func,
gpointer user_data);
GSource * fpi_device_add_timeout (FpDevice *device,
gint interval,
FpTimeoutFunc func,
gpointer user_data,
GDestroyNotify destroy_notify);
void fpi_device_set_nr_enroll_stages (FpDevice *device,
gint enroll_stages);

View File

@@ -68,11 +68,11 @@
/**
* fp_err:
*
* Same as g_warning(). In the future, this might be changed to a
* Same as g_critical(). In the future, this might be changed to a
* g_assert() instead, so bear this in mind when adding those calls
* to your driver.
*/
#define fp_err g_warning
#define fp_err g_critical
/**
* BUG_ON:

45
libfprint/fpi-minutiae.h Normal file
View File

@@ -0,0 +1,45 @@
/*
* Internal/private definitions 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
*/
#pragma once
/* fp_minutia structure definition */
struct fp_minutia
{
int x;
int y;
int ex;
int ey;
int direction;
double reliability;
int type;
int appearing;
int feature_id;
int *nbrs;
int *ridge_counts;
int num_nbrs;
};
/* fp_minutiae structure definition */
struct fp_minutiae
{
int alloc;
int num;
struct fp_minutia **list;
};

View File

@@ -43,7 +43,7 @@ gboolean fpi_print_add_from_image (FpPrint *print,
GError **error);
FpiMatchResult fpi_print_bz3_match (FpPrint * template,
FpPrint *print,
FpPrint * print,
gint bz3_threshold,
GError **error);

View File

@@ -2,6 +2,7 @@
* Functions to assist with asynchronous driver <---> library communications
* Copyright (C) 2007-2008 Daniel Drake <dsd@gentoo.org>
* Copyright (C) 2019 Benjamin Berg <bberg@redhat.com>
* Copyright (C) 2019 Marco Trevisan <marco.trevisan@canonical.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -50,6 +51,7 @@
*
* To start a ssm, you pass in a completion callback function to fpi_ssm_start()
* which gets called when the ssm completes (both on error and on failure).
* Starting a ssm also takes ownership of it.
*
* To iterate to the next state, call fpi_ssm_next_state(). It is legal to
* attempt to iterate beyond the final state - this is equivalent to marking
@@ -57,6 +59,7 @@
*
* To mark successful completion of a SSM, either iterate beyond the final
* state or call fpi_ssm_mark_completed() from any state.
* This will also invalidate the machine, freeing it.
*
* To mark failed completion of a SSM, call fpi_ssm_mark_failed() from any
* state. You must pass a non-zero error code.
@@ -78,12 +81,16 @@
struct _FpiSsm
{
FpDevice *dev;
const char *name;
FpiSsm *parentsm;
gpointer ssm_data;
GDestroyNotify ssm_data_destroy;
int nr_states;
int cur_state;
gboolean completed;
GSource *timeout;
GCancellable *cancellable;
gulong cancellable_id;
GError *error;
FpiSsmCompletedCallback callback;
FpiSsmHandlerCallback handler;
@@ -97,22 +104,40 @@ struct _FpiSsm
*
* Allocate a new ssm, with @nr_states states. The @handler callback
* will be called after each state transition.
* This is a macro that calls fpi_ssm_new_full() using the stringified
* version of @nr_states, so will work better with named parameters.
*
* Returns: a new #FpiSsm state machine
*/
/**
* fpi_ssm_new_full:
* @dev: a #fp_dev fingerprint device
* @handler: the callback function
* @nr_states: the number of states
* @name: the name of the state machine (for debug purposes)
*
* Allocate a new ssm, with @nr_states states. The @handler callback
* will be called after each state transition.
*
* Returns: a new #FpiSsm state machine
*/
FpiSsm *
fpi_ssm_new (FpDevice *dev,
FpiSsmHandlerCallback handler,
int nr_states)
fpi_ssm_new_full (FpDevice *dev,
FpiSsmHandlerCallback handler,
int nr_states,
const char *name)
{
FpiSsm *machine;
BUG_ON (nr_states < 1);
BUG_ON (handler == NULL);
machine = g_new0 (FpiSsm, 1);
machine->handler = handler;
machine->nr_states = nr_states;
machine->dev = dev;
machine->name = g_strdup (name);
machine->completed = TRUE;
return machine;
}
@@ -124,7 +149,6 @@ fpi_ssm_new (FpDevice *dev,
* @ssm_data_destroy: (nullable): #GDestroyNotify for @ssm_data
*
* Sets @machine's data (freeing the existing data, if any).
*
*/
void
fpi_ssm_set_data (FpiSsm *machine,
@@ -152,6 +176,81 @@ fpi_ssm_get_data (FpiSsm *machine)
return machine->ssm_data;
}
static void
fpi_ssm_clear_delayed_action (FpiSsm *machine)
{
if (machine->cancellable_id)
{
g_cancellable_disconnect (machine->cancellable, machine->cancellable_id);
machine->cancellable_id = 0;
}
g_clear_object (&machine->cancellable);
g_clear_pointer (&machine->timeout, g_source_destroy);
}
typedef struct _CancelledActionIdleData
{
gulong cancellable_id;
GCancellable *cancellable;
} CancelledActionIdleData;
static gboolean
on_delayed_action_cancelled_idle (gpointer user_data)
{
CancelledActionIdleData *data = user_data;
g_cancellable_disconnect (data->cancellable, data->cancellable_id);
g_object_unref (data->cancellable);
g_free (data);
return G_SOURCE_REMOVE;
}
static void
on_delayed_action_cancelled (GCancellable *cancellable,
FpiSsm *machine)
{
CancelledActionIdleData *data;
g_clear_pointer (&machine->timeout, g_source_destroy);
data = g_new0 (CancelledActionIdleData, 1);
data->cancellable = g_steal_pointer (&machine->cancellable);
data->cancellable_id = machine->cancellable_id;
machine->cancellable_id = 0;
g_idle_add_full (G_PRIORITY_HIGH_IDLE, on_delayed_action_cancelled_idle,
data, NULL);
}
static void
fpi_ssm_set_delayed_action_timeout (FpiSsm *machine,
int delay,
FpTimeoutFunc callback,
GCancellable *cancellable,
gpointer user_data,
GDestroyNotify destroy_func)
{
BUG_ON (machine->completed);
BUG_ON (machine->timeout != NULL);
fpi_ssm_clear_delayed_action (machine);
if (cancellable != NULL)
{
g_set_object (&machine->cancellable, cancellable);
machine->cancellable_id =
g_cancellable_connect (machine->cancellable,
G_CALLBACK (on_delayed_action_cancelled),
machine, NULL);
}
machine->timeout = fpi_device_add_timeout (machine->dev, delay, callback,
user_data, destroy_func);
}
/**
* fpi_ssm_free:
* @machine: an #FpiSsm state machine
@@ -165,9 +264,13 @@ fpi_ssm_free (FpiSsm *machine)
if (!machine)
return;
BUG_ON (machine->timeout != NULL);
if (machine->ssm_data_destroy)
g_clear_pointer (&machine->ssm_data, machine->ssm_data_destroy);
g_clear_pointer (&machine->error, g_error_free);
g_clear_pointer (&machine->name, g_free);
fpi_ssm_clear_delayed_action (machine);
g_free (machine);
}
@@ -175,18 +278,23 @@ fpi_ssm_free (FpiSsm *machine)
static void
__ssm_call_handler (FpiSsm *machine)
{
fp_dbg ("%p entering state %d", machine, machine->cur_state);
fp_dbg ("[%s] %s entering state %d", fp_device_get_driver (machine->dev),
machine->name, machine->cur_state);
machine->handler (machine, machine->dev);
}
/**
* fpi_ssm_start:
* @ssm: an #FpiSsm state machine
* @ssm: (transfer full): an #FpiSsm state machine
* @callback: the #FpiSsmCompletedCallback callback to call on completion
*
* Starts a state machine. You can also use this function to restart
* a completed or failed state machine. The @callback will be called
* on completion.
*
* Note that @ssm will be stolen when this function is called.
* So that all associated data will be free'ed automatically, after the
* @callback is ran.
*/
void
fpi_ssm_start (FpiSsm *ssm, FpiSsmCompletedCallback callback)
@@ -209,7 +317,6 @@ __subsm_complete (FpiSsm *ssm, FpDevice *_dev, GError *error)
fpi_ssm_mark_failed (parent, error);
else
fpi_ssm_next_state (parent);
fpi_ssm_free (ssm);
}
/**
@@ -226,7 +333,9 @@ __subsm_complete (FpiSsm *ssm, FpDevice *_dev, GError *error)
void
fpi_ssm_start_subsm (FpiSsm *parent, FpiSsm *child)
{
BUG_ON (parent->timeout);
child->parentsm = parent;
g_clear_pointer (&parent->timeout, g_source_destroy);
fpi_ssm_start (child, __subsm_complete);
}
@@ -241,25 +350,73 @@ void
fpi_ssm_mark_completed (FpiSsm *machine)
{
BUG_ON (machine->completed);
BUG_ON (machine->timeout != NULL);
fpi_ssm_clear_delayed_action (machine);
machine->completed = TRUE;
if (machine->error)
fp_dbg ("%p completed with error: %s", machine, machine->error->message);
fp_dbg ("[%s] %s completed with error: %s", fp_device_get_driver (machine->dev),
machine->name, machine->error->message);
else
fp_dbg ("%p completed successfully", machine);
fp_dbg ("[%s] %s completed successfully", fp_device_get_driver (machine->dev),
machine->name);
if (machine->callback)
{
GError *error = machine->error ? g_error_copy (machine->error) : NULL;
machine->callback (machine, machine->dev, error);
}
fpi_ssm_free (machine);
}
static void
on_device_timeout_complete (FpDevice *dev,
gpointer user_data)
{
FpiSsm *machine = user_data;
machine->timeout = NULL;
fpi_ssm_mark_completed (machine);
}
/**
* fpi_ssm_mark_completed_delayed:
* @machine: an #FpiSsm state machine
* @delay: the milliseconds to wait before switching to the next state
* @cancellable: (nullable): a #GCancellable to cancel the delayed operation
*
* Mark a ssm as completed successfully with a delay of @delay ms.
* The callback set when creating the state machine with fpi_ssm_new () will be
* called when the timeout is over.
* The request can be cancelled passing a #GCancellable as @cancellable.
*/
void
fpi_ssm_mark_completed_delayed (FpiSsm *machine,
int delay,
GCancellable *cancellable)
{
g_autofree char *source_name = NULL;
g_return_if_fail (machine != NULL);
fpi_ssm_set_delayed_action_timeout (machine, delay,
on_device_timeout_complete, cancellable,
machine, NULL);
source_name = g_strdup_printf ("[%s] ssm %s complete %d",
fp_device_get_device_id (machine->dev),
machine->name, machine->cur_state + 1);
g_source_set_name (machine->timeout, source_name);
}
/**
* fpi_ssm_mark_failed:
* @machine: an #FpiSsm state machine
* @error: a #GError
* @error: (transfer full): a #GError
*
* Mark a state machine as failed with @error as the error code.
* Mark a state machine as failed with @error as the error code, completing it.
*/
void
fpi_ssm_mark_failed (FpiSsm *machine, GError *error)
@@ -267,13 +424,16 @@ fpi_ssm_mark_failed (FpiSsm *machine, GError *error)
g_assert (error);
if (machine->error)
{
fp_warn ("SSM already has an error set, ignoring new error %s", error->message);
fp_warn ("[%s] SSM %s already has an error set, ignoring new error %s",
fp_device_get_driver (machine->dev), machine->name, error->message);
g_error_free (error);
return;
}
fp_dbg ("SSM failed in state %d with error: %s", machine->cur_state, error->message);
machine->error = error;
fp_dbg ("[%s] SSM %s failed in state %d with error: %s",
fp_device_get_driver (machine->dev), machine->name,
machine->cur_state, error->message);
machine->error = g_steal_pointer (&error);
fpi_ssm_mark_completed (machine);
}
@@ -291,6 +451,10 @@ fpi_ssm_next_state (FpiSsm *machine)
g_return_if_fail (machine != NULL);
BUG_ON (machine->completed);
BUG_ON (machine->timeout != NULL);
fpi_ssm_clear_delayed_action (machine);
machine->cur_state++;
if (machine->cur_state == machine->nr_states)
fpi_ssm_mark_completed (machine);
@@ -298,22 +462,134 @@ fpi_ssm_next_state (FpiSsm *machine)
__ssm_call_handler (machine);
}
void
fpi_ssm_cancel_delayed_state_change (FpiSsm *machine)
{
g_return_if_fail (machine);
BUG_ON (machine->completed);
BUG_ON (machine->timeout == NULL);
fpi_ssm_clear_delayed_action (machine);
}
static void
on_device_timeout_next_state (FpDevice *dev,
gpointer user_data)
{
FpiSsm *machine = user_data;
machine->timeout = NULL;
fpi_ssm_next_state (machine);
}
/**
* fpi_ssm_next_state_delayed:
* @machine: an #FpiSsm state machine
* @delay: the milliseconds to wait before switching to the next state
* @cancellable: (nullable): a #GCancellable to cancel the delayed operation
*
* Iterate to next state of a state machine with a delay of @delay ms. If the
* current state is the last state, then the state machine will be marked as
* completed, as if calling fpi_ssm_mark_completed().
* Passing a valid #GCancellable will cause the action to be cancelled when
* @cancellable is.
*/
void
fpi_ssm_next_state_delayed (FpiSsm *machine,
int delay,
GCancellable *cancellable)
{
g_autofree char *source_name = NULL;
g_return_if_fail (machine != NULL);
fpi_ssm_set_delayed_action_timeout (machine, delay,
on_device_timeout_next_state, cancellable,
machine, NULL);
source_name = g_strdup_printf ("[%s] ssm %s jump to next state %d",
fp_device_get_device_id (machine->dev),
machine->name, machine->cur_state + 1);
g_source_set_name (machine->timeout, source_name);
}
/**
* fpi_ssm_jump_to_state:
* @machine: an #FpiSsm state machine
* @state: the state to jump to
*
* Jump to the @state state, bypassing intermediary states.
* If @state is the last state, the machine won't be completed unless
* fpi_ssm_mark_completed() isn't explicitly called.
*/
void
fpi_ssm_jump_to_state (FpiSsm *machine, int state)
{
BUG_ON (machine->completed);
BUG_ON (state >= machine->nr_states);
BUG_ON (state < 0 || state >= machine->nr_states);
BUG_ON (machine->timeout != NULL);
fpi_ssm_clear_delayed_action (machine);
machine->cur_state = state;
__ssm_call_handler (machine);
}
typedef struct
{
FpiSsm *machine;
int next_state;
} FpiSsmJumpToStateDelayedData;
static void
on_device_timeout_jump_to_state (FpDevice *dev,
gpointer user_data)
{
FpiSsmJumpToStateDelayedData *data = user_data;
data->machine->timeout = NULL;
fpi_ssm_jump_to_state (data->machine, data->next_state);
}
/**
* fpi_ssm_jump_to_state_delayed:
* @machine: an #FpiSsm state machine
* @state: the state to jump to
* @delay: the milliseconds to wait before switching to @state state
* @cancellable: (nullable): a #GCancellable to cancel the delayed operation
*
* Jump to the @state state with a delay of @delay milliseconds, bypassing
* intermediary states.
* Passing a valid #GCancellable will cause the action to be cancelled when
* @cancellable is.
*/
void
fpi_ssm_jump_to_state_delayed (FpiSsm *machine,
int state,
int delay,
GCancellable *cancellable)
{
FpiSsmJumpToStateDelayedData *data;
g_autofree char *source_name = NULL;
g_return_if_fail (machine != NULL);
BUG_ON (machine->completed);
BUG_ON (machine->timeout != NULL);
data = g_new0 (FpiSsmJumpToStateDelayedData, 1);
data->machine = machine;
data->next_state = state;
fpi_ssm_set_delayed_action_timeout (machine, delay,
on_device_timeout_jump_to_state,
cancellable, data, g_free);
source_name = g_strdup_printf ("[%s] ssm %s jump to state %d",
fp_device_get_device_id (machine->dev),
machine->name, state);
g_source_set_name (machine->timeout, source_name);
}
/**
* fpi_ssm_get_cur_state:
* @machine: an #FpiSsm state machine
@@ -360,33 +636,11 @@ fpi_ssm_dup_error (FpiSsm *machine)
return NULL;
}
/**
* fpi_ssm_next_state_timeout_cb:
* @dev: a struct #fp_dev
* @data: a pointer to an #FpiSsm state machine
*
* Same as fpi_ssm_next_state(), but to be used as a callback
* for an fpi_timeout_add() callback, when the state change needs
* to happen after a timeout.
*
* Make sure to pass the #FpiSsm as the `ssm_data` argument
* for that fpi_timeout_add() call.
*/
void
fpi_ssm_next_state_timeout_cb (FpDevice *dev,
void *data)
{
g_return_if_fail (dev != NULL);
g_return_if_fail (data != NULL);
fpi_ssm_next_state (data);
}
/**
* fpi_ssm_usb_transfer_cb:
* @transfer: a #FpiUsbTransfer
* @device: a #FpDevice
* @ssm_data: User data (unused)
* @unused_data: User data (unused)
* @error: The #GError or %NULL
*
* Can be used in as a #FpiUsbTransfer callback handler to automatically
@@ -396,7 +650,7 @@ fpi_ssm_next_state_timeout_cb (FpDevice *dev,
*/
void
fpi_ssm_usb_transfer_cb (FpiUsbTransfer *transfer, FpDevice *device,
gpointer ssm_data, GError *error)
gpointer unused_data, GError *error)
{
g_return_if_fail (transfer->ssm);
@@ -405,3 +659,32 @@ fpi_ssm_usb_transfer_cb (FpiUsbTransfer *transfer, FpDevice *device,
else
fpi_ssm_next_state (transfer->ssm);
}
/**
* fpi_ssm_usb_transfer_with_weak_pointer_cb:
* @transfer: a #FpiUsbTransfer
* @device: a #FpDevice
* @weak_ptr: A #gpointer pointer to nullify. You can pass a pointer to any
* #gpointer to nullify when the callback is completed. I.e a
* pointer to the current #FpiUsbTransfer.
* @error: The #GError or %NULL
*
* Can be used in as a #FpiUsbTransfer callback handler to automatically
* advance or fail a statemachine on transfer completion.
* Passing a #gpointer* as @weak_ptr permits to nullify it once we're done
* with the transfer.
*
* Make sure to set the #FpiSsm on the transfer.
*/
void
fpi_ssm_usb_transfer_with_weak_pointer_cb (FpiUsbTransfer *transfer,
FpDevice *device, gpointer weak_ptr,
GError *error)
{
g_return_if_fail (transfer->ssm);
if (weak_ptr)
g_nullify_pointer ((gpointer *) weak_ptr);
fpi_ssm_usb_transfer_cb (transfer, device, weak_ptr, error);
}

View File

@@ -2,6 +2,7 @@
* Copyright (C) 2007-2008 Daniel Drake <dsd@gentoo.org>
* Copyright (C) 2018 Bastien Nocera <hadess@hadess.net>
* Copyright (C) 2019 Benjamin Berg <bberg@redhat.com>
* Copyright (C) 2019 Marco Trevisan <marco.trevisan@canonical.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -59,9 +60,12 @@ typedef void (*FpiSsmHandlerCallback)(FpiSsm *ssm,
FpDevice *dev);
/* for library and drivers */
FpiSsm *fpi_ssm_new (FpDevice *dev,
FpiSsmHandlerCallback handler,
int nr_states);
#define fpi_ssm_new(dev, handler, nr_states) \
fpi_ssm_new_full (dev, handler, nr_states, #nr_states)
FpiSsm *fpi_ssm_new_full (FpDevice *dev,
FpiSsmHandlerCallback handler,
int nr_states,
const char *machine_name);
void fpi_ssm_free (FpiSsm *machine);
void fpi_ssm_start (FpiSsm *ssm,
FpiSsmCompletedCallback callback);
@@ -72,7 +76,18 @@ void fpi_ssm_start_subsm (FpiSsm *parent,
void fpi_ssm_next_state (FpiSsm *machine);
void fpi_ssm_jump_to_state (FpiSsm *machine,
int state);
void fpi_ssm_next_state_delayed (FpiSsm *machine,
int delay,
GCancellable *cancellable);
void fpi_ssm_jump_to_state_delayed (FpiSsm *machine,
int state,
int delay,
GCancellable *cancellable);
void fpi_ssm_cancel_delayed_state_change (FpiSsm *machine);
void fpi_ssm_mark_completed (FpiSsm *machine);
void fpi_ssm_mark_completed_delayed (FpiSsm *machine,
int delay,
GCancellable *cancellable);
void fpi_ssm_mark_failed (FpiSsm *machine,
GError *error);
void fpi_ssm_set_data (FpiSsm *machine,
@@ -86,9 +101,11 @@ int fpi_ssm_get_cur_state (FpiSsm *machine);
/* Callbacks to be used by the driver instead of implementing their own
* logic.
*/
void fpi_ssm_next_state_timeout_cb (FpDevice *dev,
void *data);
void fpi_ssm_usb_transfer_cb (FpiUsbTransfer *transfer,
FpDevice *device,
gpointer user_data,
gpointer unused_data,
GError *error);
void fpi_ssm_usb_transfer_with_weak_pointer_cb (FpiUsbTransfer *transfer,
FpDevice *device,
gpointer weak_ptr,
GError *error);

View File

@@ -298,7 +298,7 @@ fpi_usb_transfer_fill_interrupt_full (FpiUsbTransfer *transfer,
transfer->free_buffer = free_func;
}
void
static void
transfer_finish_cb (GObject *source_object, GAsyncResult *res, gpointer user_data)
{
GError *error = NULL;
@@ -356,7 +356,7 @@ transfer_finish_cb (GObject *source_object, GAsyncResult *res, gpointer user_dat
/**
* fpi_usb_transfer_submit:
* @transfer: The transfer to submit, must have been filled.
* @transfer: (transfer full): The transfer to submit, must have been filled.
* @timeout_ms: Timeout for the transfer in ms
* @cancellable: Cancellable to use, e.g. fpi_device_get_cancellable()
* @callback: Callback on completion or error
@@ -364,10 +364,9 @@ transfer_finish_cb (GObject *source_object, GAsyncResult *res, gpointer user_dat
*
* Submit a USB transfer with a specific timeout and callback functions.
*
* Note that #FpiUsbTransfer is owned by the user. In most cases, you
* should call fpi_usb_transfer_unref() just after calling this function.
* Doing so means that all associated data will be free'ed automatically
* after the callback ran.
* Note that #FpiUsbTransfer will be stolen when this function is called.
* So that all associated data will be free'ed automatically, after the
* callback ran unless fpi_usb_transfer_ref() is explictly called.
*/
void
fpi_usb_transfer_submit (FpiUsbTransfer *transfer,
@@ -385,11 +384,6 @@ fpi_usb_transfer_submit (FpiUsbTransfer *transfer,
transfer->callback = callback;
transfer->user_data = user_data;
/* Grab a reference, this means that one can simply unref after submit and
* trust for the data to disappear without explicit management by the callback
* function. */
fpi_usb_transfer_ref (transfer);
log_transfer (transfer, TRUE, NULL);
switch (transfer->type)
@@ -460,6 +454,7 @@ fpi_usb_transfer_submit_sync (FpiUsbTransfer *transfer,
GError **error)
{
gboolean res;
gsize actual_length;
g_return_val_if_fail (transfer, FALSE);
@@ -475,7 +470,7 @@ fpi_usb_transfer_submit_sync (FpiUsbTransfer *transfer,
transfer->endpoint,
transfer->buffer,
transfer->length,
&transfer->actual_length,
&actual_length,
timeout_ms,
NULL,
error);
@@ -491,7 +486,7 @@ fpi_usb_transfer_submit_sync (FpiUsbTransfer *transfer,
transfer->idx,
transfer->buffer,
transfer->length,
&transfer->actual_length,
&actual_length,
timeout_ms,
NULL,
error);
@@ -502,7 +497,7 @@ fpi_usb_transfer_submit_sync (FpiUsbTransfer *transfer,
transfer->endpoint,
transfer->buffer,
transfer->length,
&transfer->actual_length,
&actual_length,
timeout_ms,
NULL,
error);
@@ -517,6 +512,8 @@ fpi_usb_transfer_submit_sync (FpiUsbTransfer *transfer,
if (!res)
transfer->actual_length = -1;
else
transfer->actual_length = actual_length;
return res;
}

View File

@@ -99,8 +99,6 @@ main (int argc, char **argv)
g_autoptr(GArray) drivers = g_array_new (FALSE, FALSE, sizeof (GType));
guint i;
g_print ("%p\n", drivers);
g_print ("%p\n", fpi_get_driver_types);
fpi_get_driver_types (drivers);
printed = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);

View File

@@ -162,73 +162,81 @@ endif
other_sources = []
fp_enums = gnome.mkenums_simple('fp-enums',
sources: libfprint_public_headers,
install_header : true)
sources: libfprint_public_headers,
install_header : true)
fp_enums_h = fp_enums[1]
fpi_enums = gnome.mkenums_simple('fpi-enums',
sources: libfprint_private_headers,
install_header : true)
sources: libfprint_private_headers,
install_header : true)
fpi_enums_h = fpi_enums[1]
drivers_sources += configure_file(input: 'empty_file',
output: 'fp-drivers.c',
capture: true,
command: [
'echo',
drivers_type_list + '\n\n' + drivers_type_func
])
output: 'fpi-drivers.c',
capture: true,
command: [
'echo',
'\n'.join(drivers_type_list + [] + drivers_type_func)
])
mapfile = 'libfprint.ver'
vflag = '-Wl,--version-script,@0@/@1@'.format(meson.current_source_dir(), mapfile)
deps = [ mathlib_dep, glib_dep, gusb_dep, nss_dep, imaging_dep, gio_dep ]
deps += declare_dependency(include_directories: [
root_inc,
include_directories('nbis/include'),
include_directories('nbis/libfprint-include'),
])
libnbis = static_library('nbis',
nbis_sources,
dependencies: deps,
c_args: cc.get_supported_arguments([
'-Wno-error=redundant-decls',
'-Wno-redundant-decls',
'-Wno-discarded-qualifiers',
]),
install: false)
libfprint = library('fprint',
libfprint_sources + fp_enums + fpi_enums +
drivers_sources + nbis_sources + other_sources,
soversion: soversion,
version: libversion,
c_args: common_cflags + drivers_cflags,
include_directories: [
root_inc,
include_directories('nbis/include'),
],
link_args : vflag,
link_depends : mapfile,
dependencies: deps,
install: true)
libfprint_sources + fp_enums + fpi_enums +
drivers_sources + other_sources,
soversion: soversion,
version: libversion,
c_args: drivers_cflags,
link_args : vflag,
link_depends : mapfile,
link_with: libnbis,
dependencies: deps,
install: true)
libfprint_dep = declare_dependency(link_with: libfprint,
sources: [ fp_enums_h ],
include_directories: root_inc,
dependencies: [glib_dep, gusb_dep, gio_dep])
sources: [ fp_enums_h ],
include_directories: root_inc,
dependencies: [ glib_dep, gusb_dep, gio_dep ])
install_headers(['fprint.h'] + libfprint_public_headers, subdir: 'libfprint')
udev_rules = executable('fprint-list-udev-rules',
'fprint-list-udev-rules.c',
include_directories: [
root_inc,
],
dependencies: [ deps, libfprint_dep ],
install: false)
'fprint-list-udev-rules.c',
dependencies: [ deps, libfprint_dep ],
install: false)
if get_option('udev_rules')
custom_target('udev-rules',
output: '60-fprint-autosuspend.rules',
capture: true,
command: [ udev_rules ],
install: true,
install_dir: udev_rules_dir)
output: '60-fprint-autosuspend.rules',
capture: true,
command: [ udev_rules ],
install: true,
install_dir: udev_rules_dir)
endif
supported_devices = executable('fprint-list-supported-devices',
'fprint-list-supported-devices.c',
include_directories: [
root_inc,
],
dependencies: [ deps, libfprint_dep ],
install: false)
'fprint-list-supported-devices.c',
dependencies: [ deps, libfprint_dep ],
install: false)
if get_option('introspection')
@@ -256,8 +264,7 @@ if get_option('introspection')
'GObject-2.0',
'GUsb-1.0',
],
install : true
)
install : true)
libfprint_gir = libfprint_girtarget[0]
libfprint_typelib = libfprint_girtarget[1]
endif

View File

@@ -896,7 +896,7 @@ for ( k = 0; k < np - 1; k++ ) {
for ( i = 0; i < tot; i++ ) {
int colp_value = colp[ y[i]-1 ][0];
int colp_value = colp[ bz_y[i]-1 ][0];
if ( colp_value < 0 ) {
kk += colp_value;
n++;
@@ -933,7 +933,7 @@ for ( k = 0; k < np - 1; k++ ) {
kk = 0;
for ( i = 0; i < tot; i++ ) {
int diff = colp[ y[i]-1 ][0] - jj;
int diff = colp[ bz_y[i]-1 ][0] - jj;
j = SQUARED( diff );
@@ -942,7 +942,7 @@ for ( k = 0; k < np - 1; k++ ) {
if ( j > TXS && j < CTXS )
kk++;
else
y[i-kk] = y[i];
bz_y[i-kk] = bz_y[i];
} /* END FOR i */
tot -= kk; /* Adjust the total edge pairs TOT based on # of edge pairs skipped */
@@ -958,7 +958,7 @@ for ( k = 0; k < np - 1; k++ ) {
for ( i = tot-1 ; i >= 0; i-- ) {
int idx = y[i] - 1;
int idx = bz_y[i] - 1;
if ( rk[idx] == 0 ) {
sc[idx] = -1;
} else {
@@ -976,7 +976,7 @@ for ( k = 0; k < np - 1; k++ ) {
int pd = 0;
for ( i = 0; i < tot; i++ ) {
int idx = y[i] - 1;
int idx = bz_y[i] - 1;
for ( ii = 1; ii < 4; ii++ ) {
@@ -1476,7 +1476,7 @@ return match_score;
/* extern int rk[ RK_SIZE ]; */
/* extern int cp[ CP_SIZE ]; */
/* extern int rp[ RP_SIZE ]; */
/* extern int y[ Y_SIZE ]; */
/* extern int bz_y[ Y_SIZE ]; */
void bz_sift(
int * ww, /* INPUT and OUTPUT; endpoint groups index; *ww may be bumped by one or by two */
@@ -1507,7 +1507,7 @@ if ( n == 0 && t == 0 ) {
if ( sc[kx-1] != ftt ) {
y[ (*tot)++ ] = kx;
bz_y[ (*tot)++ ] = kx;
rk[kx-1] = sc[kx-1];
sc[kx-1] = ftt;
}
@@ -1553,7 +1553,7 @@ if ( n == l ) {
qq[*qh] = kz;
zz[kz-1] = (*qh)++;
}
y[(*tot)++] = kx;
bz_y[(*tot)++] = kx;
rk[kx-1] = sc[kx-1];
sc[kx-1] = ftt;
}
@@ -1697,12 +1697,12 @@ for ( ii = 0; ii < tp; ii++ ) { /* For each index up to the current value of
}
t = 0;
y[0] = lim;
bz_y[0] = lim;
cp[0] = 1;
b = 0;
n = 1;
do { /* looping until T < 0 ... */
if ( y[t] - cp[t] > 1 ) {
if (bz_y[t] - cp[t] > 1 ) {
k = sct[cp[t]][t];
j = ctt[k] + 1;
for ( i = 0; i < j; i++ ) {
@@ -1715,25 +1715,25 @@ for ( ii = 0; ii < tp; ii++ ) { /* For each index up to the current value of
do {
while ( rp[jj] < sct[kk][t] && jj < j )
jj++;
while ( rp[jj] > sct[kk][t] && kk < y[t] )
while ( rp[jj] > sct[kk][t] && kk < bz_y[t] )
kk++;
while ( rp[jj] == sct[kk][t] && kk < y[t] && jj < j ) {
while ( rp[jj] == sct[kk][t] && kk < bz_y[t] && jj < j ) {
sct[k][t+1] = sct[kk][t];
k++;
kk++;
jj++;
}
} while ( kk < y[t] && jj < j );
} while ( kk < bz_y[t] && jj < j );
t++;
cp[t] = 1;
y[t] = k;
bz_y[t] = k;
b = t;
n = 1;
} else {
int tot = 0;
lim = y[t];
lim = bz_y[t];
for ( i = n-1; i < lim; i++ ) {
tot += ct[ sct[i][t] ];
}
@@ -1750,7 +1750,7 @@ for ( ii = 0; ii < tp; ii++ ) { /* For each index up to the current value of
{
int rk_index = b;
lim = y[t];
lim = bz_y[t];
for ( i = n-1; i < lim; ) {
rk[ rk_index++ ] = sct[ i++ ][ t ];
}
@@ -1760,7 +1760,7 @@ for ( ii = 0; ii < tp; ii++ ) { /* For each index up to the current value of
t--;
if ( t >= 0 ) {
++cp[t];
n = y[t];
n = bz_y[t];
}
} /* END IF */

View File

@@ -102,7 +102,7 @@ int yl[ YL_SIZE_1 ][ YL_SIZE_2 ];
int rf[RF_SIZE_1][RF_SIZE_2];
int cf[CF_SIZE_1][CF_SIZE_2];
int y[20000];
int bz_y[20000];
#else
int rq[ RQ_SIZE ] = {};
int tq[ TQ_SIZE ] = {};
@@ -122,6 +122,6 @@ int yl[ YL_SIZE_1 ][ YL_SIZE_2 ];
int rf[RF_SIZE_1][RF_SIZE_2] = {};
int cf[CF_SIZE_1][CF_SIZE_2] = {};
int y[20000] = {};
int bz_y[20000] = {};
#endif

View File

@@ -245,7 +245,7 @@ extern int cp[ CP_SIZE ];
extern int rp[ RP_SIZE ];
extern int rf[RF_SIZE_1][RF_SIZE_2];
extern int cf[CF_SIZE_1][CF_SIZE_2];
extern int y[20000];
extern int bz_y[20000];
/**************************************************************************/
/**************************************************************************/

View File

@@ -66,7 +66,8 @@ of the software.
#include <math.h>
#include <stdio.h>
#include <fp_internal.h>
#include <nbis-helpers.h>
#include <fpi-minutiae.h>
/*************************************************************************/
/* OUTPUT FILE EXTENSIONS */

View File

@@ -1,15 +1,16 @@
--- include/lfs.h 2018-08-24 15:31:54.535579623 +0200
+++ include/lfs.h.orig 2018-08-24 15:31:48.781587933 +0200
@@ -66,7 +43,7 @@ of the software.
--- include/lfs.h
+++ include/lfs.h
@@ -66,7 +66,8 @@ of the software.
#include <math.h>
#include <stdio.h>
-#include <an2k.h> /* Needed by to_type9.c */
+#include <fp_internal.h>
+#include <nbis-helpers.h>
+#include <fpi-minutiae.h>
/*************************************************************************/
/* OUTPUT FILE EXTENSIONS */
@@ -154,26 +131,8 @@ typedef struct rotgrids{
@@ -154,26 +155,8 @@ typedef struct rotgrids{
#define DISAPPEARING 0
#define APPEARING 1
@@ -38,7 +39,7 @@
typedef struct feature_pattern{
int type;
@@ -1185,17 +1185,6 @@ extern void bubble_sort_double_inc_2(double *, int *, const int);
@@ -1203,17 +1186,6 @@ extern void bubble_sort_double_inc_2(double *, int *, const int);
extern void bubble_sort_double_dec_2(double *, int *, const int);
extern void bubble_sort_int_inc(int *, const int);

View File

@@ -0,0 +1,35 @@
/*
* Example fingerprint device prints listing and deletion
* Enrolls your right index finger and saves the print to disk
* Copyright (C) 2019 Marco Trevisan <marco.trevisan@canonical.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#pragma once
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wredundant-decls"
#include <bozorth.h>
#include <bz_array.h>
#include <defs.h>
#include <lfs.h>
#include <log.h>
#include <morph.h>
#include <mytime.h>
#include <sunrast.h>
#pragma GCC diagnostic pop

View File

@@ -66,7 +66,7 @@ of the software.
/***************************************************************************/
/***************************************************************************/
int open_logfile()
int open_logfile(void)
{
#ifdef LOG_REPORT
fprintf(stderr, "ERROR : open_logfile : fopen : %s\n", LOG_FILE);
@@ -91,7 +91,7 @@ void print2log(char *fmt, ...)
/***************************************************************************/
/***************************************************************************/
int close_logfile()
int close_logfile(void)
{
#ifdef LOG_REPORT
fprintf(stderr, "ERROR : close_logfile : fclose : %s\n", LOG_FILE);

View File

@@ -0,0 +1,21 @@
@ global_y @
identifier y;
@@
int
- y
+ bz_y
[20000];
@@
identifier global_y.y;
@@
- y
+ bz_y
[...]
@@
@@
int
- y
+ bz_y
[20000] = {};

View File

@@ -179,9 +179,16 @@ sed -i 's/[ \t]*$//' `find -name "*.[ch]"`
# Remove usebsd.h
sed -i '/usebsd.h/d' `find -name "*.[ch]"`
# Replace functions with empty parameters using (void)
sed -i 's/^\([[:space:]]*[[:alnum:]_]\+[\*[:space:]]\+'\
'[[:alnum:]_]\+[[:space:]]*\)([[:space:]]*)/\1(void)/g' `find -name "*.[ch]"`
# Use GLib memory management
spatch --sp-file glib-memory.cocci --dir . --in-place
# Rename global "y" variable in "bz_y"
spatch --sp-file remove-global-y.cocci bozorth3/* include/bozorth.h --in-place
# The above leaves an unused variable around, triggering a warning
# remove it.
patch -p0 < glib-mem-warning.patch
patch -p0 < glib-mem-warning.patch

View File

@@ -1,38 +1,72 @@
project('libfprint', [ 'c', 'cpp' ],
version: '1.90.0',
license: 'LGPLv2.1+',
default_options: [
'buildtype=debugoptimized',
'warning_level=1',
'c_std=c99',
],
meson_version: '>= 0.46.0')
version: '1.90.0',
license: 'LGPLv2.1+',
default_options: [
'buildtype=debugoptimized',
'warning_level=1',
'c_std=c99',
],
meson_version: '>= 0.46.0')
gnome = import('gnome')
add_project_arguments([ '-D_GNU_SOURCE' ], language: 'c')
add_project_arguments([ '-DG_LOG_DOMAIN="libfprint"' ], language: 'c')
libfprint_conf = configuration_data()
cc = meson.get_compiler('c')
cpp = meson.get_compiler('cpp')
host_system = host_machine.system()
glib_min_version = '2.56'
glib_version_def = 'GLIB_VERSION_@0@_@1@'.format(
glib_min_version.split('.')[0], glib_min_version.split('.')[1])
common_cflags = cc.get_supported_arguments([
'-fgnu89-inline',
'-std=gnu99',
'-Wall',
'-Wcast-align',
'-Wformat-nonliteral',
'-Wformat-security',
'-Wformat=2',
'-Wignored-qualifiers',
'-Wlogical-op',
'-Wmissing-declarations',
'-Wmissing-format-attribute',
'-Wmissing-include-dirs',
'-Wmissing-noreturn',
'-Wpointer-arith',
'-Wshadow',
'-Wtype-limits',
'-Wundef',
'-Wunused',
'-Wstrict-prototypes',
'-Werror-implicit-function-declaration',
'-Wno-pointer-sign',
'-Wshadow',
'-DGLIB_VERSION_MIN_REQUIRED=GLIB_VERSION_2_50',
'-DGLIB_VERSION_MAX_ALLOWED=GLIB_VERSION_2_50',
'-Werror=address',
'-Werror=array-bounds',
'-Werror=empty-body',
'-Werror=init-self',
'-Werror=int-to-pointer-cast',
'-Werror=main',
'-Werror=missing-braces',
'-Werror=nonnull',
'-Werror=redundant-decls',
'-Werror=return-type',
'-Werror=sequence-point',
'-Werror=trigraphs',
'-Werror=write-strings',
'-fno-strict-aliasing',
'-DGLIB_VERSION_MIN_REQUIRED=' + glib_version_def,
'-DGLIB_VERSION_MAX_ALLOWED=' + glib_version_def,
'-D_GNU_SOURCE',
'-DG_LOG_DOMAIN="libfprint"',
])
c_cflags = cc.get_supported_arguments([
'-std=gnu99',
'-Wimplicit-function-declaration',
'-Wmissing-prototypes',
'-Wnested-externs',
'-Wold-style-definition',
'-Wstrict-prototypes',
'-Werror=implicit',
'-Werror=pointer-to-int-cast',
])
add_project_arguments(common_cflags + c_cflags, language: 'c')
add_project_arguments(common_cflags, language: 'cpp')
# maintaining compatibility with the previous libtool versioning
# current = binary - interface
@@ -43,15 +77,36 @@ revision = 0
libversion = '@0@.@1@.@2@'.format(soversion, current, revision)
# Dependencies
glib_dep = dependency('glib-2.0', version: '>= 2.50')
gio_dep = dependency('gio-unix-2.0', version: '>= 2.44.0')
glib_dep = dependency('glib-2.0', version: '>=' + glib_min_version)
gio_dep = dependency('gio-unix-2.0', version: '>=' + glib_min_version)
gusb_dep = dependency('gusb', version: '>= 0.3.0')
mathlib_dep = cc.find_library('m', required: false)
# Drivers
drivers = get_option('drivers').split(',')
virtual_drivers = [ 'virtual_image' ]
default_drivers = [ 'upektc_img', 'vfs5011', 'aes3500', 'aes4000', 'aes1610', 'aes1660', 'aes2660', 'aes2501', 'aes2550', 'vfs101', 'vfs301', 'vfs0050', 'etes603', 'vcom5s', 'synaptics', 'elan', 'uru4000', 'upektc', 'upeksonly', 'upekts' ]
default_drivers = [
'upektc_img',
'vfs5011',
'aes3500',
'aes4000',
'aes1610',
'aes1660',
'aes2660',
'aes2501',
'aes2550',
'vfs101',
'vfs301',
'vfs0050',
'etes603',
'vcom5s',
'synaptics',
'elan',
'uru4000',
'upektc',
'upeksonly',
'upekts',
]
all_drivers = default_drivers + virtual_drivers
@@ -91,14 +146,22 @@ foreach driver: drivers
endforeach
# Export the drivers' types to the core code
drivers_type_list = '#include <glib-object.h>\n'
drivers_type_func = 'void fpi_get_driver_types(GArray *drivers)\n{\n\tGType t;\n'
drivers_type_list = []
drivers_type_func = []
drivers_type_list += '#include <glib-object.h>'
drivers_type_list += '#include "fpi-context.h"'
drivers_type_list += ''
drivers_type_func += 'void fpi_get_driver_types (GArray *drivers)'
drivers_type_func += ' {'
drivers_type_func += ' GType t;'
drivers_type_func += ''
foreach driver: drivers
drivers_type_list += 'extern GType (fpi_device_' + driver + '_get_type) (void);\n'
drivers_type_func += ' t = fpi_device_' + driver + '_get_type(); g_array_append_val (drivers, t);\n'
drivers_type_list += 'extern GType (fpi_device_' + driver + '_get_type) (void);'
drivers_type_func += ' t = fpi_device_' + driver + '_get_type ();'
drivers_type_func += ' g_array_append_val (drivers, t);\n'
endforeach
drivers_type_list += ''
drivers_type_func += '};'
drivers_type_func += '}'
root_inc = include_directories('.')
@@ -139,11 +202,10 @@ endif
pkgconfig = import('pkgconfig')
pkgconfig.generate(
name: 'libfprint',
description: 'Generic C API for fingerprint reader access',
version: meson.project_version(),
libraries: libfprint,
subdirs: 'libfprint',
filebase: 'libfprint2',
install_dir: join_paths(get_option('libdir'), 'pkgconfig'),
)
name: 'libfprint',
description: 'Generic C API for fingerprint reader access',
version: meson.project_version(),
libraries: libfprint,
subdirs: 'libfprint',
filebase: 'libfprint2',
install_dir: join_paths(get_option('libdir'), 'pkgconfig'))

View File

@@ -36,10 +36,12 @@ c_buf = c_img.get_data()
for x in range(width):
for y in range(height):
# The upper byte is don't care, but the location depends on endianness,
# so just set all of them.
c_buf[y * c_rowstride + x * 4 + 0] = buf[y * width + x]
c_buf[y * c_rowstride + x * 4 + 1] = buf[y * width + x]
c_buf[y * c_rowstride + x * 4 + 2] = buf[y * width + x]
# Byte 4 is don't care
c_buf[y * c_rowstride + x * 4 + 3] = buf[y * width + x]
c_img.mark_dirty()
c_img.write_to_png(sys.argv[1])

View File

@@ -16,8 +16,7 @@ envs.set('NO_AT_BRIDGE', '1')
if get_option('introspection')
if 'virtual_image' in drivers
test(
'virtual-image',
test('virtual-image',
find_program('virtual-image.py'),
args: '--verbose',
env: envs,
@@ -25,25 +24,45 @@ if get_option('introspection')
)
endif
if 'vfs5011' in drivers
test(
'vfs5011',
find_program('umockdev-test.py'),
args: join_paths(meson.current_source_dir(), 'vfs5011'),
env: envs,
timeout: 10,
depends: libfprint_typelib,
)
endif
drivers_tests = [
'vfs5011',
'synaptics',
]
if 'synaptics' in drivers
test(
'synaptics',
foreach driver_test: drivers_tests
test(driver_test,
find_program('umockdev-test.py'),
args: join_paths(meson.current_source_dir(), 'synaptics'),
args: join_paths(meson.current_source_dir(), driver_test),
env: envs,
suite: ['drivers'],
timeout: 10,
depends: libfprint_typelib,
)
endif
endforeach
endif
gdb = find_program('gdb', required: false)
if gdb.found()
add_test_setup('gdb',
timeout_multiplier: 1000,
env: [
'LIBFPRINT_TEST_WRAPPER=@0@ --args'.format(
gdb.path())
])
endif
valgrind = find_program('valgrind', required: false)
if valgrind.found()
glib_share = glib_dep.get_pkgconfig_variable('prefix') / 'share' / glib_dep.name()
glib_suppressions = glib_share + '/valgrind/glib.supp'
python_suppressions = '@0@/@1@'.format(meson.source_root(),
files('valgrind-python.supp')[0])
add_test_setup('valgrind',
timeout_multiplier: 10,
env: [
'G_SLICE=always-malloc',
('LIBFPRINT_TEST_WRAPPER=@0@ --tool=memcheck --leak-check=full ' +
'--suppressions=@1@ --suppressions=@2@').format(
valgrind.path(), glib_suppressions, python_suppressions)
])
endif

View File

@@ -48,20 +48,28 @@ def cmp_pngs(png_a, png_b):
for x in range(img_a.get_width()):
for y in range(img_a.get_height()):
assert(data_a[y * stride + x * 4] == data_b[y * stride + x * 4])
# RGB24 format is endian dependent, using +1 means we test either
# the G or B component, which works on any endian for the greyscale
# test.
assert(data_a[y * stride + x * 4 + 1] == data_b[y * stride + x * 4 + 1])
def capture():
ioctl = os.path.join(ddir, "capture.ioctl")
def get_umockdev_runner(ioctl_basename):
ioctl = os.path.join(ddir, "{}.ioctl".format(ioctl_basename))
device = os.path.join(ddir, "device")
dev = open(ioctl).readline().strip()
assert dev.startswith('@DEV ')
dev = dev[5:]
subprocess.check_call(['umockdev-run', '-d', device,
'-i', "%s=%s" % (dev, ioctl),
'--',
'%s' % os.path.join(edir, "capture.py"),
'%s' % os.path.join(tmpdir, "capture.png")])
umockdev = ['umockdev-run', '-d', device,
'-i', "%s=%s" % (dev, ioctl),
'--']
wrapper = os.getenv('LIBFPRINT_TEST_WRAPPER')
return umockdev + (wrapper.split(' ') if wrapper else []) + [sys.executable]
def capture():
subprocess.check_call(get_umockdev_runner("capture") +
['%s' % os.path.join(edir, "capture.py"),
'%s' % os.path.join(tmpdir, "capture.png")])
assert os.path.isfile(os.path.join(tmpdir, "capture.png"))
if os.path.isfile(os.path.join(ddir, "capture.png")):
@@ -69,16 +77,8 @@ def capture():
cmp_pngs(os.path.join(tmpdir, "capture.png"), os.path.join(ddir, "capture.png"))
def custom():
ioctl = os.path.join(ddir, "custom.ioctl")
device = os.path.join(ddir, "device")
dev = open(ioctl).readline().strip()
assert dev.startswith('@DEV ')
dev = dev[5:]
subprocess.check_call(['umockdev-run', '-d', device,
'-i', "%s=%s" % (dev, ioctl),
'--',
'%s' % os.path.join(ddir, "custom.py")])
subprocess.check_call(get_umockdev_runner("custom") +
['%s' % os.path.join(ddir, "custom.py")])
try:
if os.path.exists(os.path.join(ddir, "capture.ioctl")):

View File

@@ -0,0 +1,55 @@
{
ignore_py_cond
Memcheck:Cond
...
fun:Py*
}
{
ignore__py_cond
Memcheck:Cond
...
fun:_Py*
}
{
ignore_py_value8
Memcheck:Value8
...
fun:Py*
}
{
ignore__py_value8
Memcheck:Value8
...
fun:_Py*
}
{
ignore_py_addr4
Memcheck:Addr4
...
fun:Py*
}
{
ignore__py_addr4
Memcheck:Addr4
...
fun:_Py*
}
{
ignore_py_leaks
Memcheck:Leak
...
fun:Py*
}
{
ignore__py_leaks
Memcheck:Leak
...
fun:_Py*
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 64 KiB

After

Width:  |  Height:  |  Size: 64 KiB

View File

@@ -10,24 +10,19 @@ import sys
import unittest
import socket
import struct
import subprocess
import shutil
import glob
import cairo
import tempfile
class Connection:
def __init__(self, addr):
self.addr = addr
def __enter__(self):
self.con = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
self.con.connect(self.addr)
return self.con
def __exit__(self, exc_type, exc_val, exc_tb):
self.con.close()
del self.con
# Re-run the test with the passed wrapper if set
wrapper = os.getenv('LIBFPRINT_TEST_WRAPPER')
if wrapper:
wrap_cmd = wrapper.split(' ') + [sys.executable, os.path.abspath(__file__)] + \
sys.argv[1:]
os.unsetenv('LIBFPRINT_TEST_WRAPPER')
sys.exit(subprocess.check_call(wrap_cmd))
def load_image(img):
png = cairo.ImageSurface.create_from_png(img)
@@ -92,24 +87,51 @@ class VirtualImage(unittest.TestCase):
def setUp(self):
self.dev.open_sync()
self.con = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
self.con.connect(self.sockaddr)
def tearDown(self):
self.con.close()
del self.con
self.dev.close_sync()
def report_finger(self, state):
with Connection(self.sockaddr) as con:
con.write(struct.pack('ii', -1, 1 if state else 0))
def send_retry(self, retry_error=1, iterate=True):
# The default (1) is too-short
self.sendall(struct.pack('ii', -1, retry_error))
while iterate and ctx.pending():
ctx.iteration(False)
def send_image(self, image):
def send_error(self, device_error=0, iterate=True):
# The default (0) is a generic error
self.sendall(struct.pack('ii', -1, retry_error))
while iterate and ctx.pending():
ctx.iteration(False)
def send_finger_automatic(self, automatic, iterate=True):
# Set whether finger on/off is reported around images
self.con.sendall(struct.pack('ii', -3, 1 if automatic else 0))
while iterate and ctx.pending():
ctx.iteration(False)
def send_finger_report(self, has_finger, iterate=True):
# Send finger on/off
self.con.sendall(struct.pack('ii', -4, 1 if has_finger else 0))
while iterate and ctx.pending():
ctx.iteration(False)
def send_image(self, image, iterate=True):
img = self.prints[image]
with Connection(self.sockaddr) as con:
mem = img.get_data()
mem = mem.tobytes()
assert len(mem) == img.get_width() * img.get_height()
encoded_img = struct.pack('ii', img.get_width(), img.get_height())
encoded_img += mem
mem = img.get_data()
mem = mem.tobytes()
assert len(mem) == img.get_width() * img.get_height()
con.sendall(encoded_img)
encoded_img = struct.pack('ii', img.get_width(), img.get_height())
encoded_img += mem
self.con.sendall(encoded_img)
while iterate and ctx.pending():
ctx.iteration(False)
def test_capture_prevents_close(self):
cancel = Gio.Cancellable()
@@ -160,10 +182,16 @@ class VirtualImage(unittest.TestCase):
while self._step < 1:
ctx.iteration(True)
# Test the image-device path where the finger is removed after
# the minutiae scan is completed.
self.send_finger_automatic(False)
self.send_finger_report(True)
self.send_image(image)
while self._step < 2:
ctx.iteration(True)
self.send_finger_report(False)
self.send_finger_automatic(True)
self.send_image(image)
while self._step < 3:
ctx.iteration(True)
@@ -274,7 +302,6 @@ class VirtualImage(unittest.TestCase):
ctx.iteration(True)
assert(not self._verify_match)
# avoid writing to stderr
unittest.main(testRunner=unittest.TextTestRunner(stream=sys.stdout, verbosity=2))