Compare commits

...

253 Commits

Author SHA1 Message Date
Benjamin Berg
400cacf867 elan: Fix memory leak in elan_submit_image
elan_submit_image would modify the list of received frames in place,
without freeing the associated memory. Fix this by using a local
variable so that the list remains unmodified and is fully released by
elan_dev_reset.
2019-06-18 22:36:38 +02:00
Benjamin Berg
4cec28416e lib: Remove state from fp_img_driver activate handler
The state was always AWAIT_FINGER and it was never used by any driver
(except for error checking). So remove it, in particular as a correct
state change will be done after activation anyway.

The only driver with code that actually did anything based on this was
the URU4000 driver. However, all it did was an explicit state change
execution. This is not necessary, as the state_change handler is called
anyway (i.e. we now only write the AWAIT_FINGER register once rather
than twice).

Manual changes plus:

@ init @
identifier driver_name;
identifier activate_func;
@@
struct fp_img_driver driver_name = {
    ...,
    .activate = activate_func,
    ...,
};
@ remove_arg @
identifier dev;
identifier state;
identifier init.activate_func;
@@
activate_func (
	struct fp_img_dev *dev
-	, enum fp_imgdev_state state
	)
{
	<...
-	if (state != IMGDEV_STATE_AWAIT_FINGER_ON) { ... }
	...>
}
2019-06-18 18:19:38 +02:00
Benjamin Berg
3b32baccf6 fdu2000: Remove driver as it has been defunct for long
The driver was never ported to the new asynchronous model, meaning it
has been defunct since some time in 2008. Remove the driver, as
seemingly no one has complained about this and we have no proper way to
even verify a port is correct.
2019-06-18 15:54:57 +00:00
Benjamin Berg
16875d7776 examples: Port enroll and verify examples to new storage
This ports the enroll and verify examples to the new storage so that
they do not need any deprecated API anymore.
2019-06-13 13:12:15 +00:00
Benjamin Berg
a9600e23a1 examples: Link examples to the new GVariant based storage
For now just compile and link it, we do not yet use the new storage
code.
2019-06-13 13:12:15 +00:00
Benjamin Berg
a4b6813ebf examples: Add simple storage implementation using GVariant
This is useful so that the enroll and verify examples will not use the
deprecated API anymore.
2019-06-13 13:12:15 +00:00
Benjamin Berg
ef90938eb9 build: Bump GLib dependency to 2.50 and add guards
libfprint already uses G_DEBUG_HERE in a lot of places which requires
GLib 2.50. Also add the appropriate defines so that usage of newer API
will result in warnings.
2019-06-13 13:56:35 +02:00
Benjamin Berg
66891274a7 build: Remove header files from nbis_sources
There is no need to list them in the sources.
2019-06-12 16:10:04 +02:00
Benjamin Berg
f52276bd06 build: Remove header files from libfprint_sources
There is no need to list them in the sources.
2019-06-12 16:07:44 +02:00
Benjamin Berg
7dce8dbfaa build: Remove header files from drivers_sources
It is not necessary to list all the headers in the drivers_sources list,
so remove them.
2019-06-12 16:07:08 +02:00
Benjamin Berg
3b757ee738 build: Fix source files of upekts and upketc drivers
The upekts driver needs upek_proto.c while the upektc driver does not.
Move the corresponding source file entries so that both drivers compile
standalone.
2019-06-12 16:07:05 +02:00
Benjamin Berg
0a45ed7af6 data: Deprecate print storage API
The only API user currently seems to be the examples. fprintd has its
own storage and that will be a good idea in general.

So deprecate the API, we'll need to find a different solution for the
examples eventually.
2019-06-11 18:23:56 +02:00
Benjamin Berg
1db2dc3f58 core: Add guards to public API
Add appropriate g_return_val_if_fail macros to all public API functions
to guard against NULL pointers being passed into libfprint.
2019-06-11 18:23:56 +02:00
Benjamin Berg
953c75575b poll: Remove fpi_timeout_cancel_for_dev
The function was committed by accident as part of commit d18e1053
(lib: Add a way to name timeouts). It is not used anywhere and
fpi_timeout_cancel_all_for_dev exists, is exported and used and serves
the same purpose.
2019-06-11 16:00:19 +02:00
Dave
8c7ff259af elan: Add 04f3:0c42 to the supported devices
Now that all the quirks are in place to support it.
2019-06-06 12:19:31 +02:00
Dave
3e666130c2 elan: Skip more final frames to avoid bulging captures
If users put their finger on the sensor between the bulge and
"un-bulge" area first and then swipe, the captured image would
be bad.

Skipping more frames can reduce the impact, so bump
ELAN_SKIP_LAST_FRAMES to 2.
2019-06-06 12:19:31 +02:00
Dave
2babfa0625 elan: Simplify calibration check for ELAN_0C42
Check for the mean calibration being outside of range to know whether we
require a recalibration. Continue with the usual checks if the
calibration value is within range.
2019-06-06 12:19:31 +02:00
Dave
83af40679a elan: ELAN_0C42 always supports calibration
Split off calibration support checks into elan_supports_calibration()
2019-06-06 12:19:31 +02:00
Dave
ce31c1d704 elan: Work-around one-byte responses being two-bytes long
On the ELAN_0C42 device, one-byte responses are 2 bytes long.
Adapt our expected response length.
2019-06-06 12:19:31 +02:00
Dave
b20a74a22c elan: Work-around sensors returning incorrect dimensions
The dimensions some sensors return is the maximum zero-based index
rather than the number of pixels. Assuming every sensor has an
even number of pixels is safe.
2019-06-06 12:19:31 +02:00
Dave
66461e4c81 elan: Add quirk definition for device 04f3:0c42 2019-06-06 12:19:07 +02:00
Peter Maatman
6ba9439bbb examples: Remove sleep call in enroll examples
The call to sleep(1) inside of the enrollment loop caused a crash
on at least the etes603 driver.

Because in fp_enroll_finger_img the function enters an event
handling loop. This loop needs to start before the next libusb
event timeout. Which would not happen in the etes603 driver
because the timeout there was set to 1 second as well.
2019-05-14 11:38:33 +02:00
Peter Maatman
6764ec79ae etes603: Prevent hang during enroll process
This commit fixes a hang in gnome-settings when trying to enroll a finger.

The same issue could be seen in the enroll example. Previously the enroll
example would hang on "deactivating" because at some point dev->is_active
is set to false and m_exit_start is never called.
2019-05-14 11:37:19 +02:00
Diego
6f4c378933 vfs5011: Add support for Lenovo Preferred Pro Keyboard (KUF1256)
Add support for the Lenovo Preferred Pro USB Fingerprint Keyboard KUF1256
by declaring support for USB ID 138a:0015.

Closes: #125
2019-05-06 09:55:40 +02:00
Bastien Nocera
b121fa2cc9 uru4000: Work-around SELinux AVC warnings when driver starts
Work-around SELinux AVC warnings caused by p11-kit (which is an NSS
dependency) trying to load the root user's p11-kit configs. We disable
this feature using the P11_KIT_NO_USER_CONFIG envvar.

See https://bugzilla.redhat.com/show_bug.cgi?id=1688583
2019-03-21 16:54:06 +01:00
Seong-Joong Kim
ca26e85fd4 uru4000: Fix integer overflow in imaging_run_state()
‘img->key_number’ variable is originally from the device through bulk
endpoint of USB. The variable is immediately assigned to ‘buf[0]’ for
sending to control endpoint of the device. Here, integer overflow may
occur when the ‘img->key_number’ attempts to assign a value that is
outside of type range of ‘char’ to the ‘buf[0]’
2019-02-21 19:06:06 +09:00
Bastien Nocera
0714380360 build: Disable GTK+ demo app by default
Given that it's not usable yet.
2019-01-21 14:38:35 +00:00
Bastien Nocera
b9af7952a4 demo: Fix crash when there are no supported devices
Handle the empty list output from fp_discover_devs() when there are no
supported devices.

Closes: #146
2019-01-21 14:38:35 +00:00
Bastien Nocera
ea6820ed51 lib: Better docs for no devices case in fp_discover_devs()
Document the behaviour of fp_discover_devs() when there are no supported
devices, rather than errors listing the devices.
2019-01-21 14:38:35 +00:00
Bastien Nocera
a1e46de462 lib: Fix examples not working
Remove the sanity check added in commit b1afa9d, having a poll setup
isn't necessary to use timeouts, as long as only sync functions are
used.

Closes: #139
2018-12-30 16:35:33 +01:00
Bastien Nocera
1abe213844 0.99.0 2018-12-14 13:18:08 +01:00
Bastien Nocera
0372ae8ba5 mindtct: Check for multiplication overflow in alloc_power_stats()
Assert if any of the multiplications, which are then used to allocate
memory, would overflow.

Closes: #91
2018-12-13 15:48:25 +01:00
Bastien Nocera
a1e69a0e9d mindtct: Check for multiplication overflow in morph_TF_map()
Assert if any of the multiplications, which are then used to allocate
memory and run a loop, would overflow.

Closes: #92
2018-12-13 15:48:25 +01:00
Bastien Nocera
49e1e98914 mindtct: Check for multiplication overflow in pixelize_map()
Assert if any of the multiplications, which are then used to allocate
memory, would overflow.

Closes: #96
2018-12-13 15:48:25 +01:00
Bastien Nocera
34b316d7d5 mindtct: Check for multiplication overflow in allocate_contour()
Assert if any of the multiplications, which are then used to allocate
memory, would overflow.

Closes: #97
2018-12-13 15:48:25 +01:00
Bastien Nocera
9abc6791c7 mindtct: Check for multiplication overflow in gen_initial_maps()
Assert if any of the multiplications, which are then used to allocate
memory, would overflow.

Closes: #99
2018-12-13 15:48:25 +01:00
Bastien Nocera
5459823667 mindtct: Check for multiplication overflow in interpolate_direction_map()
Assert if any of the multiplications, which are then used to allocate
memory, would overflow.

Closes: #100
2018-12-13 15:48:25 +01:00
Bastien Nocera
4fa8c5ec47 mindtct: Check for multiplication overflow in gen_high_curve_map()
Assert if any of the multiplications, which are then used to allocate
memory, would overflow.

Closes: #101
2018-12-13 15:48:25 +01:00
Bastien Nocera
239034714f mindtct: Check for multiplication overflow in gen_quality_map()
Assert if any of the multiplications, which are then used to allocate
memory, would overflow.

Closes: #103
2018-12-13 15:48:25 +01:00
Bastien Nocera
8a3a974ea3 lib: Add helper for NBIS copy-paste library
This will allow us to segragate helper functions that we want to use
within NBIS. The first helper will be a macro checking for overflow in
multiplications.
2018-12-13 15:48:25 +01:00
Bastien Nocera
db607c4a6f mindtct: Fix memory leak in error path in find_neighbors()
libfprint/nbis/mindtct/ridges.c:284:13: warning: Potential leak of memory pointed to by 'nbr_list'
            free(nbr_sqr_dists);
            ^~~~
2018-12-13 11:59:24 +01:00
Bastien Nocera
a53f07a8f6 mindtct: Fix memory leak in error path in gen_image_maps()
Free the maps if we're not returning them.

libfprint/nbis/mindtct/maps.c:176:14: warning: Potential leak of memory pointed to by 'direction_map'
      return(ret);
             ^~~
libfprint/nbis/mindtct/maps.c:195:14: warning: Potential leak of memory pointed to by 'low_contrast_map'
      return(ret);
             ^~~
libfprint/nbis/mindtct/maps.c:195:14: warning: Potential leak of memory pointed to by 'low_flow_map'
      return(ret);
             ^~~
2018-12-13 11:33:39 +01:00
Bastien Nocera
c3e996b96c mindtct: Fix memory leak in error path in shape_from_contour()
libfprint/nbis/mindtct/shape.c:263:13: warning: Potential leak of memory pointed to by 'shape'
            fprintf(stderr,
            ^~~~~~~
2018-12-13 11:27:00 +01:00
Bastien Nocera
a218437cf4 mindtct: Fix uninitialised value usage in count_minutia_ridges()
libfprint/nbis/mindtct/ridges.c:153:7: warning: 1st function call argument is an uninitialized value
      free(nbr_list);
      ^~~~~~~~~~~~~~
2018-12-12 17:24:45 +01:00
Bastien Nocera
0add0ca9b1 bozorth3: Remove unused assignments in bz_match_score()
libfprint/nbis/bozorth3/bozorth3.c:704:1: warning: Value stored to 'kx' is never read
kx  = 0;
^     ~
libfprint/nbis/bozorth3/bozorth3.c:820:4: warning: Value stored to 'l' is never read
                        l = 1;
                        ^   ~
2018-12-12 17:17:35 +01:00
Bastien Nocera
eaa4aa964c mindtct: Fix memory leaks in get_centered_contour()
The first contour wasn't freed if we failed on the second contour.

libfprint/nbis/mindtct/contour.c:521:14: warning: Potential leak of memory pointed to by 'half1_ex'
      return(ret);
             ^~~
libfprint/nbis/mindtct/contour.c:521:14: warning: Potential leak of memory pointed to by 'half1_ey'
      return(ret);
             ^~~
libfprint/nbis/mindtct/contour.c:521:14: warning: Potential leak of memory pointed to by 'half1_x'
      return(ret);
             ^~~
libfprint/nbis/mindtct/contour.c:521:14: warning: Potential leak of memory pointed to by 'half1_y'
      return(ret);
             ^~~
2018-12-12 17:14:21 +01:00
Bastien Nocera
74bb899ce2 mindtct: Fix "garbage value" error in dft_dir_powers()
libfprint/nbis/mindtct/dft.c:212:30: warning: The left operand of '*' is a garbage value
      cospart += (rowsums[i] * wave->cos[i]);
                  ~~~~~~~~~~ ^
2018-12-12 17:06:36 +01:00
Bastien Nocera
69fe7a1b8c elan: Fix "garbage value" errors in elan_cmd_cb()
libfprint/drivers/elan.c:351:4: warning: 2nd function call argument is an uninitialized value
                        dbg_buf(elandev->last_read, transfer->actual_length);
                        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
libfprint/drivers/elan.c:46:5: note: expanded from macro 'dbg_buf'
    fp_dbg("%02x", buf[0]);                                  \
    ^~~~~~~~~~~~~~~~~~~~~~
../../../../../../Projects/jhbuild/libfprint/libfprint/fpi-log.h:52:16: note: expanded from macro 'fp_dbg'
 #define fp_dbg g_debug
               ^
libfprint/drivers/elan.c:351:4: warning: The left operand of '<<' is a garbage value
                        dbg_buf(elandev->last_read, transfer->actual_length);
                        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
libfprint/drivers/elan.c:48:27: note: expanded from macro 'dbg_buf'
    fp_dbg("%04x", buf[0] << 8 | buf[1]);                    \
                   ~~~~~~ ^
libfprint/drivers/elan.c:351:4: warning: The left operand of '<<' is a garbage value
                        dbg_buf(elandev->last_read, transfer->actual_length);
                        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
libfprint/drivers/elan.c:50:41: note: expanded from macro 'dbg_buf'
    fp_dbg("%04x... (%d bytes)", buf[0] << 8 | buf[1], len)
                                 ~~~~~~ ^
2018-12-12 16:56:33 +01:00
Bastien Nocera
ce856efa25 elan: Assert on a possible division by zero in elan_need_calibration()
libfprint/drivers/elan.c:598:10: warning: Division by zero
        bg_mean /= frame_size;
        ~~~~~~~~^~~~~~~~~~~~~
2018-12-12 16:30:26 +01:00
Bastien Nocera
b54514df6e elan: Assert on a possible division by zero in elan_process_frame_linear()
libfprint/drivers/elan.c:249:26: warning: Division by zero
                px = (px - min) * 0xff / (max - min);
                     ~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~
2018-12-12 16:24:05 +01:00
Bastien Nocera
551616c3ab aesx660: Fix memory leak in process_stripe_data()
libfprint/drivers/aesx660.c:292:10: warning: Potential leak of memory pointed to by 'stripe'
                return 0;
                       ^
2018-12-12 16:19:20 +01:00
Bastien Nocera
cec307ce7f aeslib: Fix memory leak in aes_write_regv()
libfprint/drivers/aeslib.c:156:1: warning: Potential leak of memory pointed to by 'wdata'
}
^
2018-12-12 16:17:32 +01:00
Bastien Nocera
e7bc8e03fc upeksonly: Fix typos in upeksonly_get_deviation2() comment 2018-12-12 16:13:29 +01:00
Bastien Nocera
9a025bde8b upeksonly: Fix possible division by zero in upeksonly_get_deviation2()
By asserting if we have a zero line width.

libfprint/drivers/upeksonly.c:118:7: warning: Division by zero
        mean /= (ctx->line_width / 2);
        ~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
2018-12-12 16:13:15 +01:00
Bastien Nocera
6845e400cd uru4000: Fix memory leak on error in dev_init()
libfprint/drivers/uru4000.c:1357:3: warning: Potential leak of memory pointed to by 'urudev'
                fp_err("could not get encryption slot");
                ^~~~~~
2018-12-12 16:06:03 +01:00
Bastien Nocera
25d0fa42e2 uru4000: Fix unused value in sm_read_regs()
We don't need to assign urudev if we only want the size of one of its
members.

libfprint/drivers/uru4000.c:554:20: warning: Value stored to 'urudev' during its initialization is never read
        struct uru4k_dev *urudev = FP_INSTANCE_DATA(FP_DEV(dev));
                          ^~~~~~   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2018-12-12 16:04:35 +01:00
Bastien Nocera
52208a6606 lib: Fix baroque code in fp_discover_prints()
Use GPtrArray to simplify the implementation.

libfprint/fpi-data.c:777:13: warning: Access to field 'data' results in a dereference of a null pointer (loaded from variable 'elem')
                list[i] = elem->data;
                          ^~~~~~~~~~
2018-12-12 15:47:29 +01:00
Bastien Nocera
6725b22fd4 lib: Fix uninitialised value in fp_print_data_load()
libfprint/fpi-data.c:497:7: warning: 2nd function call argument is an uninitialized value
        if (!fp_dev_supports_print_data(dev, fdata)) {
             ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2018-12-12 15:47:29 +01:00
Bastien Nocera
21bac43015 lib: Fix memory leak on error in fp_print_data_save()
libfprint/fpi-data.c:393:3: warning: Potential leak of memory pointed to by 'buf'
                fp_err("couldn't create storage directory");
                ^~~~~~
libfprint/fpi-log.h:75:16: note: expanded from macro 'fp_err'
 #define fp_err g_warning
               ^~~~~~~~~
2018-12-12 15:47:29 +01:00
Bastien Nocera
0ddd11f81b lib: Fix unintialised variable warning in fp_get_next_timeout()
libfprint/fpi-poll.c:398:11: warning: The left operand of '==' is a garbage value
        else if (timercmp(&fprint_timeout, &libusb_timeout, <))
                 ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/include/sys/time.h:162:17: note: expanded from macro 'timercmp'
  (((a)->tv_sec == (b)->tv_sec) ?                                             \
    ~~~~~~~~~~~ ^
2018-12-12 15:47:29 +01:00
Bastien Nocera
6d47c44335 lib: Fix possible dereference in fpi_ssm_next_state()
libfprint/fpi-ssm.c:244:9: warning: Access to field 'completed' results in a dereference of a null pointer (loaded from variable 'machine')
        BUG_ON(machine->completed);
               ^~~~~~~~~~~~~~~~~~
libfprint/fpi-log.h:84:6: note: expanded from macro 'BUG_ON'
        if (condition) {                        \
            ^~~~~~~~~
2018-12-12 15:47:29 +01:00
Bastien Nocera
3cbc908a6e lib: Add better guard against huge malloc
See dda6857fee
and https://bugzilla.redhat.com/show_bug.cgi?id=1656518

When the number of lines to assemble is 1, the median_filter() function
would be passed -1 as its size as it was calculated with:
(num_lines / 2) - 1
so (1 / 2) - 1 = 0 - 1 = -1

Add a guard to stop drivers trying to assemble single lines. This
doesn't however fix the vfs5011 driver that tried to do that.
2018-12-06 10:58:35 +01:00
Bastien Nocera
95b1e75f1b Revert "ci: Disable Flatpak generation for now"
This reverts commit bcfe0ad12c.
2018-12-04 17:43:19 +01:00
Bastien Nocera
bcfe0ad12c ci: Disable Flatpak generation for now
It's currently broken on our CI runners, we'll need to reactivate
it again in the future.
2018-12-04 17:09:00 +01:00
Vasily Khoruzhick
2088a6177f lib: Document assembling functions 2018-12-03 16:06:53 +01:00
Vasily Khoruzhick
c9733d27df lib: Add API docs for fpi_img comparison functions 2018-12-03 14:22:12 +01:00
Bastien Nocera
dd24cf57c6 README: Add links to historical resources 2018-11-30 17:57:40 +01:00
Bastien Nocera
451a4c0969 lib: Remove duplicated structs from fp_internal.h
They are already declared in fpi-core.h. Also move their API docs
to fpi-core.h.
2018-11-30 16:08:42 +01:00
Bastien Nocera
dabcae7b4d lib: Document fpi_imgdev_*() functions 2018-11-29 17:32:37 +01:00
Bastien Nocera
eae5721f8e vfs101: Add FIXME about fpi_imgdev_set_action_result usage
We shouldn't need to use fpi_imgdev_set_action_result(), because
as fpi_imgdev_image_captured() is already there.
2018-11-29 17:32:37 +01:00
Bastien Nocera
ce1a675dd5 lib: Reword "use the functions below" docs
Those usually appear in struct definitions which will be at the bottom
of the docs, so there's nothing but the bottom of the page below.
2018-11-29 17:32:37 +01:00
Bastien Nocera
6ba1016024 lib: Hide struct fp_minutiae from the docs
It's only used internally.
2018-11-29 17:32:37 +01:00
Bastien Nocera
b5f175b78e lib: Move action state functions to correct C file 2018-11-29 17:32:37 +01:00
Bastien Nocera
aff7efd891 lib: Remove upekts used headers from the docs
They're only used by this super quirky driver that stores data
internally.

See #127
2018-11-29 17:32:37 +01:00
Bastien Nocera
1d00c2d4b4 lib: Make 6 async reporting funcs private
As those aren't used in any driver.
2018-11-29 17:32:37 +01:00
Bastien Nocera
61483a4c47 lib: Make the fp_print_data structure private
And add a couple of helpers for the upekts driver to use.
2018-11-29 17:32:37 +01:00
Bastien Nocera
2b21430abe lib: Fix lack of description for fp_dscv_dev_get_driver_id()
We documented the return value, but without writing out the function
description.
2018-11-29 17:32:36 +01:00
Bastien Nocera
1781ad140e lib: Remove unused fp_imgdev_verify_state enum 2018-11-29 17:32:36 +01:00
Bastien Nocera
d2e3ad4dbc lib: Add API docs for 3 enums 2018-11-29 17:32:36 +01:00
Bastien Nocera
7615aaef7a lib: Document fp_img functions
And fix fpi_img_new_for_imgdev()'s argument names to match between the
header and the C file.
2018-11-29 13:15:03 +01:00
Bastien Nocera
92e3168309 lib: Add documentation for fp_driver_type 2018-11-25 12:42:11 +00:00
Bastien Nocera
ca148cbcf1 lib: Add documentation for usb_id 2018-11-25 12:42:11 +00:00
Bastien Nocera
e57f037a10 lib: Document FP_IMG_DEV
...and add "Returns" docs to fpi-dev.c

We might need to do this more, documenting what the function does in
prose, as well as a short explanation of the returned data.
2018-11-25 12:42:11 +00:00
Bastien Nocera
46ad86fab2 doc: Remove empty "poll" section
In commit 231b8f9, when porting from doxygen to gtk-doc, we created a
section for "poll" functions, but we renamed that section to "events"
during the porting process. We ended up with an empty "poll" section,
and a correctly migrated "events" section.
2018-11-25 12:42:11 +00:00
Bastien Nocera
511e164f17 lib: Add @short_description for all the sections
So gtk-doc doesn't warn about them any more.
2018-11-25 12:42:11 +00:00
Bastien Nocera
6f18fc4bf4 lib: Document all the internal symbols in fpi-dev.c 2018-11-25 12:42:11 +00:00
Bastien Nocera
8ca34303f2 lib: Transform fp_img_driver flags into a FpiImgDriverFlags enum
And document it.
2018-11-25 12:42:11 +00:00
Bastien Nocera
882fc8ab54 lib: Fix sloppy grammar in error output 2018-11-25 12:42:11 +00:00
Bastien Nocera
9e5ae25abf lib: Transform fp_img flags into a FpiImgFlags enum
And document it.
2018-11-25 12:42:11 +00:00
Bastien Nocera
9316dfed2e ci: Generate Flatpak and export it 2018-11-23 15:05:00 +01:00
Bastien Nocera
702932c69b demo: Add Flatpak manifest for the demo application 2018-11-23 15:05:00 +01:00
Bastien Nocera
29461fa910 demo: Add GTK+ test application 2018-11-23 15:05:00 +01:00
Bastien Nocera
f7173e6645 ci: Add GTK+ to the CI 2018-11-20 05:20:55 +01:00
Bastien Nocera
11b11a9d71 lib: Fix get_next_timeout_expiry
If get_next_timeout_expiry() fails, and libusb_get_next_timeout()
has no timeouts or failed, fprint_timeout will not be set, and
we cannot compare it to libusb_timeout.

Exit early if both failed or have empty queues.
2018-11-13 11:54:41 +01:00
Bastien Nocera
9da69dfc36 elan: Fix format mismatch warnings in debug output
libfprint/drivers/elan.c:351:12: warning: format specifies type 'unsigned short' but the argument has type 'unsigned char' [-Wformat]
                        dbg_buf(elandev->last_read, transfer->actual_length);
                        ~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
libfprint/drivers/elan.c:46:21: note: expanded from macro 'dbg_buf'
    fp_dbg("%02hx", buf[0]);                                  \
    ~~~~~~~~~~~~~~~~^~~~~~~
include/glib-2.0/glib/gmessages.h:345:32: note: expanded from macro 'g_debug'
                               __VA_ARGS__)
                               ^~~~~~~~~~~
libfprint/drivers/elan.c:351:12: warning: format specifies type 'unsigned short' but the argument has type 'int' [-Wformat]
                        dbg_buf(elandev->last_read, transfer->actual_length);
                        ~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
libfprint/drivers/elan.c:48:21: note: expanded from macro 'dbg_buf'
    fp_dbg("%04hx", buf[0] << 8 | buf[1]);                    \
    ~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~
include/glib-2.0/glib/gmessages.h:345:32: note: expanded from macro 'g_debug'
                               __VA_ARGS__)
                               ^~~~~~~~~~~
libfprint/drivers/elan.c:351:12: warning: format specifies type 'unsigned short' but the argument has type 'int' [-Wformat]
                        dbg_buf(elandev->last_read, transfer->actual_length);
                        ~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
libfprint/drivers/elan.c:50:35: note: expanded from macro 'dbg_buf'
    fp_dbg("%04hx... (%d bytes)", buf[0] << 8 | buf[1], len)
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~
include/glib-2.0/glib/gmessages.h:345:32: note: expanded from macro 'g_debug'
                               __VA_ARGS__)
                               ^~~~~~~~~~~
libfprint/drivers/elan.c:413:10: warning: format specifies type 'unsigned short' but the argument has type 'unsigned char' [-Wformat]
        dbg_buf(cmd->cmd, 2);
        ~~~~~~~~^~~~~~~~~~~~
libfprint/drivers/elan.c:46:21: note: expanded from macro 'dbg_buf'
    fp_dbg("%02hx", buf[0]);                                  \
    ~~~~~~~~~~~~~~~~^~~~~~~
include/glib-2.0/glib/gmessages.h:345:32: note: expanded from macro 'g_debug'
                               __VA_ARGS__)
                               ^~~~~~~~~~~
libfprint/drivers/elan.c:413:10: warning: format specifies type 'unsigned short' but the argument has type 'int' [-Wformat]
        dbg_buf(cmd->cmd, 2);
        ~~~~~~~~^~~~~~~~~~~~
libfprint/drivers/elan.c:48:21: note: expanded from macro 'dbg_buf'
    fp_dbg("%04hx", buf[0] << 8 | buf[1]);                    \
    ~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~
include/glib-2.0/glib/gmessages.h:345:32: note: expanded from macro 'g_debug'
                               __VA_ARGS__)
                               ^~~~~~~~~~~
libfprint/drivers/elan.c:413:10: warning: format specifies type 'unsigned short' but the argument has type 'int' [-Wformat]
        dbg_buf(cmd->cmd, 2);
        ~~~~~~~~^~~~~~~~~~~~
libfprint/drivers/elan.c:50:35: note: expanded from macro 'dbg_buf'
    fp_dbg("%04hx... (%d bytes)", buf[0] << 8 | buf[1], len)
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~
include/glib-2.0/glib/gmessages.h:345:32: note: expanded from macro 'g_debug'
                               __VA_ARGS__)
                               ^~~~~~~~~~~
2018-11-13 11:54:41 +01:00
Bastien Nocera
e5f4021a4f vfs101: Fix warning about value truncation
libfprint/drivers/vfs101.c:854:6: warning: absolute value function 'abs' given an argument of type 'long' but has parameter of type 'int' which may cause truncation of value [-Wabsolute-value]
        if (abs(count - VFS_IMG_BEST_CONTRAST) < abs(vdev->best_clevel - VFS_IMG_BEST_CONTRAST))
            ^
libfprint/drivers/vfs101.c:854:6: note: use function 'labs' instead
        if (abs(count - VFS_IMG_BEST_CONTRAST) < abs(vdev->best_clevel - VFS_IMG_BEST_CONTRAST))
            ^~~
            labs
2018-11-13 11:54:41 +01:00
Bastien Nocera
4dcbc6a3aa vfs101: Fix typo in "VFS_IMG_BEST_CONRAST" constant
It's contrast, says so above the definition.
2018-11-13 11:54:41 +01:00
Bastien Nocera
7a72d8fd58 lib: Fix uninitialised variable in fpi_imgdev_image_captured()
libfprint/fpi-dev-img.c:255:6: warning: variable 'print' is used uninitialized whenever 'if' condition is false [-Wsometimes-uninitialized]
        if (imgdev->action != IMG_ACTION_CAPTURE) {
            ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
libfprint/fpi-dev-img.c:271:25: note: uninitialized use occurs here
        imgdev->acquire_data = print;
                               ^~~~~
libfprint/fpi-dev-img.c:255:2: note: remove the 'if' if its condition is always true
        if (imgdev->action != IMG_ACTION_CAPTURE) {
        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
libfprint/fpi-dev-img.c:232:29: note: initialize the variable 'print' to silence this warning
        struct fp_print_data *print;
                                   ^
                                    = NULL
2018-11-13 11:54:41 +01:00
Bastien Nocera
5edfd55e00 doc: Fix typo in chapter title 2018-11-12 12:10:11 +01:00
Bastien Nocera
2951daaa01 doc: Split driver docs into chapters 2018-11-09 15:32:39 +01:00
Bastien Nocera
23f7c4aaf7 doc: Hide G_LOG_DOMAIN from gtk-doc
It's only used internally, and doesn't need to be documented here,
as FP_COMPONENT which uses it already is.
2018-11-09 15:32:39 +01:00
Bastien Nocera
3dc5c4a6de doc: Add LIBFPRINT_DEPRECATED to the docs 2018-11-09 15:32:39 +01:00
Bastien Nocera
a97ae3bc35 doc: Add fpi-async section to the docs 2018-11-09 15:32:39 +01:00
Bastien Nocera
53d2fb3ad2 doc: Add more functions to fpi-dev section
And rename section to match that of fpi-dev-img
2018-11-09 15:32:39 +01:00
Bastien Nocera
4f7e507716 doc: Add fpi-dev-img section to the docs 2018-11-09 15:32:39 +01:00
Bastien Nocera
f2e3a840db doc: Add fpi-core and fpi-core-img sections to the docs 2018-11-09 15:32:39 +01:00
Bastien Nocera
f45c18116a doc: Add fpi-data section to the docs 2018-11-09 15:32:39 +01:00
Bastien Nocera
2365c608f9 lib: Change "unsigned" to "unsigned int"
To appease gtk-doc's struct parser, which chokes on the short name for
the data type.

See https://gitlab.gnome.org/GNOME/gtk-doc/issues/63
2018-11-09 14:20:19 +01:00
Bastien Nocera
6c6daaa619 doc: Add fpi-assembling section to the docs 2018-11-09 14:08:04 +01:00
Bastien Nocera
857a399bfa doc: Fix parameter names in fp_minutia_get_coords() docs
The API docs for fp_minutia_get_coords() as added in commit 1006467
had the parameters in the docs not match the actual names used.
2018-11-09 13:58:21 +01:00
Bastien Nocera
6e230f0a07 doc: Add missing fpi_timeout_set_name() to the docs 2018-11-09 13:58:21 +01:00
Bastien Nocera
7402401057 doc: Add fpi-img section to the docs 2018-11-09 13:58:21 +01:00
Bastien Nocera
fe17dfe01d lib: Rename fpi_im_resize() to fpi_img_resize()
Now that this name is free. This makes all the image manipulation
functions have the same "fpi_img_" prefix.
2018-11-09 13:36:52 +01:00
Bastien Nocera
4885b38be5 lib: Rename fpi_img_resize() to fpi_img_realloc()
To better match what it does. It does not resize an image, but
reallocate its internal data structure's size.
2018-11-09 13:35:40 +01:00
Bastien Nocera
5d4a5981d0 lib: Make fpi_poll_is_setup() private
As it's not used in other parts of the library after the changes in
commit 422f81b.
2018-11-09 13:33:02 +01:00
Bastien Nocera
0fcb4533b5 doc: Add more headers to ignore list
Those are not public headers, so don't need to be documented. This
removes 18 symbols from the undocumented symbols list.
2018-11-09 13:29:56 +01:00
Bastien Nocera
422f81b60c Revert "lib: Async functions cannot be started without a mainloop"
This reverts commit 700c5791f8.

We don't need a poll setup to be able to call sync functions, which then
use async functions for implementation internally.

Closes: #124

Conflicts:
	libfprint/fpi-async.c
2018-11-09 12:22:45 +01:00
Bastien Nocera
e0d2f3ae53 lib: Link to fp_enroll_finger_img() in fp_enroll_stage_cb() doc 2018-10-23 11:24:56 +02:00
Bastien Nocera
531d9048b3 lib: Fix up third-person usage in API docs 2018-10-23 11:24:56 +02:00
Bastien Nocera
18495d122d lib: Fix up @dev argument docs 2018-10-23 11:24:56 +02:00
Bastien Nocera
9bcacd97df lib: Require a callback for a number of async calls
Otherwise the caller won't be able to call the appropriate _finish()
calls when done.

See https://gitlab.freedesktop.org/libfprint/libfprint/issues/119 for
the long-term plan
2018-10-23 11:24:56 +02:00
Bastien Nocera
d91eae26e5 lib: Add API docs for the async functions 2018-10-23 11:24:56 +02:00
Bastien Nocera
d113ed9d83 docs: Update API docs style
No period at the end of parameter docs.
2018-10-23 11:24:56 +02:00
Bastien Nocera
e113754312 docs: Add "struct #fp_dev" to the API docs 2018-10-23 11:24:56 +02:00
Bastien Nocera
b1afa9da5d lib: No mainloop, no timeouts either 2018-10-23 10:59:15 +02:00
Bastien Nocera
700c5791f8 lib: Async functions cannot be started without a mainloop
No mainloop, no async.
2018-10-23 10:59:15 +02:00
Bastien Nocera
97d0a6dfe6 lib: Add fpi_poll_is_setup() sanity check
This checks whether polling was correctly setup for integration with a
mainloop.
2018-10-23 10:59:15 +02:00
Bastien Nocera
a54d020c97 lib: Make fp_get_pollfds() fail when fp_init() wasn't called
So things can't be called out-of-order.
2018-10-23 10:59:15 +02:00
Bastien Nocera
36b696f433 lib: Fix error messages in async capture functions
They mentioned verification instead of capture.
2018-10-23 10:59:15 +02:00
Bastien Nocera
f42cd6eefd lib: Add fp_driver_supports_imaging()
So we don't need to open a device before checking whether it supports
imaging.
2018-10-23 10:59:15 +02:00
Bastien Nocera
46ebb39f65 lib: Throw an error if fp_init() wasn't called
You can't call fp_discover_devs() without calling fp_init() and having
it not fail, otherwise there's nothing to discover...
2018-10-23 10:59:15 +02:00
Bastien Nocera
c88a51cce8 build: Refuse to build without any drivers 2018-10-23 10:59:15 +02:00
Bastien Nocera
3a7b03f022 lib: Fix crash when too many minutiae were detected
struct xyt_struct uses a fixed-sized array to fit MAX_BOZORTH_MINUTIAE (200)
minutiae. MAX_FILE_MINUTIAE is 1000. So if we detected more than
MAX_BOZORTH_MINUTIAE, we would crash copying the data from the capture
to the structure.

We might want to use dynamically allocated arrays in the future (or
bigger ones) so that we don't lose minutiae.

Closes: #116
2018-10-12 12:27:37 +02:00
Bastien Nocera
94450a1d74 lib: Fix fpi_img_is_sane()
The checks weren't:
- checking whether the width or height were negative
- whether img->width * img->height would overflow, or
  was bigger than G_MAXINT
- whether img->width * img->height was bigger than the total
  length of the buffer

The last one looks like a thinko, it checked for:
(img->length * img->height) < img->length
which is equivalent to:
img->height < 1
which we already check for earlier.

Closes: #85
2018-10-12 00:54:39 +00:00
Bastien Nocera
c35ad20249 mindtct: Fix a memory leak in morph_TF_map()
cimage is leaked when mimage fails to allocate.

Spotted by Seth Arnold

Closes: #82
2018-10-12 00:54:39 +00:00
Bastien Nocera
5e8b4a81e9 mindtct: Fix leak in pixelize_map()
pmap was not freed in error cases.

Spotted by Seth Arnold

Closes: #83
2018-10-12 00:54:39 +00:00
Bastien Nocera
21a779235d mindtct: Fix powmax_dirs leak on error
A copy/paste error meant we were trying to free a variable we only just
failed to allocate.

Spotted by Seth Arnold

Closes: #81
2018-10-12 00:54:39 +00:00
Bastien Nocera
1006467f33 lib: Add accessor for minutia coordinates
Add fp_minutia_get_coords() so that debugging applications can show the
detected minutiae along with the captured image.

This will also help fix the positively ancient fprint_demo.

See https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=907470
2018-10-08 16:50:59 +02:00
Bastien Nocera
cffe49de5c build: Fix "already configured" meson warning 2018-10-08 16:50:59 +02:00
Bastien Nocera
7962d8cdab build: Fix build with no drivers using imaging_dep
Closes: #109
2018-09-28 15:59:45 +02:00
Bastien Nocera
36dba33808 build: Test builds with a single driver with no deps
So that we can be sure that the build doesn't break when those drivers
are not built.
2018-09-28 15:55:56 +02:00
Bastien Nocera
c273908471 lib: Tidy fp_internal.h
Group global variables, structure definitions, and functions, and
group functions by which C source they're defined in.

This also removes the FP_IMGDRV_SUPPORTS_UNCONDITIONAL_CAPTURE
definition that's already available in the drivers API-accessible
fpi-core.h
2018-09-28 15:12:39 +02:00
Bastien Nocera
bf8661bf45 lib: Include "fpi-dev.h" in drivers header 2018-09-28 15:12:39 +02:00
Bastien Nocera
499b522183 lib: Remove titles from headers
The purpose of the headers is (or will be) explained in more details
inside each one of the matching C files.
2018-09-28 15:12:39 +02:00
Bastien Nocera
13bfe7a65c lib: Move driver definitions to fpi-core.h 2018-09-28 15:12:39 +02:00
Bastien Nocera
e90ec04441 lib: Move fp_minutiae to fpi-img.h 2018-09-28 15:12:39 +02:00
Bastien Nocera
a59a5caaf3 lib: Add missing includes
Headers for size_t and ssize_t, as used in the header itself.
2018-09-28 15:12:39 +02:00
Bastien Nocera
5b9f81fb46 lib: Move fp_dev helpers to fpi-dev.h from fpi-core.h 2018-09-28 15:12:39 +02:00
Bastien Nocera
d3aaebb352 lib: Add include guards to fpi-dev.h 2018-09-28 15:12:39 +02:00
Bastien Nocera
a99f920fe0 lib: Add include guards to fpi-poll.h 2018-09-28 15:12:39 +02:00
Bastien Nocera
fb5527c58c lib: Split off imgdev functions
They now live in fpi-dev-img.[ch]
2018-09-28 15:12:39 +02:00
Bastien Nocera
fcd3c1dd89 lib: Split off core.c drivers API 2018-09-28 15:12:39 +02:00
Bastien Nocera
3a9500be67 lib: Move fpi-img utils to fpi-img's header 2018-09-28 15:12:39 +02:00
Bastien Nocera
1d93b86569 lib: Rename assembling.[ch]
This is already self-contained.
2018-09-28 15:12:39 +02:00
Bastien Nocera
aca2cd41d8 lib: Rename sync.c to fpi-sync.c
All the functions there are public, so no matching header.
2018-09-28 15:12:39 +02:00
Bastien Nocera
1035f733aa lib: Split off async functions
And don't add the new fpi-async.h to the driver imports, it will only
be used by the upekts driver.
2018-09-28 15:12:39 +02:00
Bastien Nocera
2818d94010 lib: Split off fp_img helpers
And rename img.c to fpi-img.c, as well as pixman.c to fpi-img-pixman.c
2018-09-28 15:12:39 +02:00
Bastien Nocera
1d1c34eb60 lib: Make fpi_print_data_item_free() static 2018-09-28 15:12:39 +02:00
Bastien Nocera
ca06fae22e lib: Split off fpi_print_data helpers
And rename data.c to fpi-data.c
2018-09-28 15:12:39 +02:00
Bastien Nocera
36f527269b Revert "lib: Mark fpi_ssm_get_user_data as deprecated"
This reverts commit 1fd82b5162.

This was causing too many warnings at this stage of porting. We'll add
it again when most of the drivers are ported.
2018-09-28 15:12:39 +02:00
Bastien Nocera
7cfe20e07f lib: Fix gtk-doc warning
warning: no link for: "timeval" -> (<code class="literal">timeval</code>)
2018-09-27 16:08:21 +02:00
Bastien Nocera
1fd82b5162 lib: Mark fpi_ssm_get_user_data as deprecated 2018-09-27 16:07:58 +02:00
Bastien Nocera
0ace5f64f8 elan: Fix use-after-free if USB transfer is cancelled 2018-09-27 15:19:00 +02:00
Bastien Nocera
e532524c7e elan: Name our timeouts 2018-09-27 15:17:15 +02:00
Bastien Nocera
ebd96f892e lib: Make fpi_timeout_add() never fail
It will now assert if the monotonic clock isn't available. If that's the
case, we'll have bigger problems anyway.
2018-09-27 15:14:05 +02:00
Bastien Nocera
4b9b34fa4d elan: Use USB helpers 2018-09-27 15:09:59 +02:00
Bastien Nocera
bcc1e7ae73 aes2501: Use USB helpers
Nice little cleanups.
2018-09-27 14:49:50 +02:00
Bastien Nocera
27accf42f2 uru4000: Port URU4000 driver to USB helpers
Doesn't look very useful.
2018-09-27 14:49:50 +02:00
Bastien Nocera
96f2e07cdd lib: Add USB transfer helpers
Those helpers will provide more arguments in their callbacks, and handle
the libusb_transfer lifecycle, making it easier to use for drivers.
2018-09-27 14:49:50 +02:00
Bastien Nocera
192c4f3cfc aesx660: Use constants for buffer sizes 2018-09-27 14:49:50 +02:00
Bastien Nocera
cb274032da aes2501: Use constants for buffer sizes 2018-09-27 14:49:50 +02:00
Bastien Nocera
b890fa56d8 aes1610: Use constants for buffer sizes 2018-09-27 14:49:50 +02:00
Bastien Nocera
b817b46494 lib: Remove home-grown min() implementation
And use GLib's.
2018-09-27 14:49:50 +02:00
Bastien Nocera
49ba59369a aesx660: Remove home-grown min() implementation
And use GLib's.
2018-09-27 14:49:50 +02:00
Bastien Nocera
d09cb88e9a uru4000: Fix typos in comments 2018-09-27 14:49:50 +02:00
Bastien Nocera
44c3f4f772 lib: Cancel pending timeouts on close
So that the drivers don't call back into themselves once freed.
2018-09-27 14:49:50 +02:00
Bastien Nocera
948a67a51f lib: Add internal fpi_timeout_cancel_all_for_dev()
This will be used to disable all timeouts for a device that's about
to be closed, and freed.
2018-09-27 14:49:50 +02:00
Bastien Nocera
de79609550 lib: Use timeout name in debug messages when available 2018-09-27 14:49:41 +02:00
Bastien Nocera
d18e10535e lib: Add a way to name timeouts
To make it easier to print debug information about where timeouts are
coming from.
2018-09-27 14:49:41 +02:00
Bastien Nocera
2954583373 lib: Fix memory leak in fpi_poll_exit()
The active_timers list was freed, but not the elements themselves.
2018-09-27 14:36:06 +02:00
Bastien Nocera
ccdecdea11 lib: Document fpi_ssm_jump_to_state() 2018-09-26 15:57:25 +02:00
Bastien Nocera
946388d1e9 lib: Fix incorrect guard in FP_IMG_DEV()
The check for the DRIVER_IMAGING type was reversed.
2018-09-26 15:53:52 +02:00
Bastien Nocera
10ae8ffb55 drivers: Simplify libusb_alloc_transfer(0) calls
By using our new, never-failing, USB allocation wrapper. As it can never
fail, we can also remove all the error paths for the allocations
failing.
2018-09-19 17:06:17 +02:00
Bastien Nocera
bdba9990fb lib: Add libusb allocation helper 2018-09-19 17:04:55 +02:00
Bastien Nocera
50166e88c0 lib: Add fpi_ssm_next_state_timeout_cb() helper
To be used in 5 drivers.
2018-09-19 15:46:29 +02:00
Bastien Nocera
f2bc826a20 lib: Move aeslib.[ch] to the drivers directory
As it's used by drivers, and isn't a set of generic helpers.
2018-09-19 15:16:40 +02:00
Bastien Nocera
ac48d66203 lib: Mention that fpi_timeout gets freed 2018-09-18 20:02:14 +02:00
Bastien Nocera
f68e7fcb9f lib: Add fp_dev argument to timeout callback
To cut down on the fpi_ssm_get_user_data() usage again.
2018-09-18 20:00:59 +02:00
Bastien Nocera
0c3a22758b drivers: Simplify FP_INSTANCE_DATA(FP_DEV()) calls
When fp_dev is already available, don't use the fp_img_dev struct to get
to fp_dev with FP_DEV(), use the fp_dev directly.
2018-09-18 18:30:42 +02:00
Bastien Nocera
9cc859a318 drivers: Diminish fpi_ssm_get_user_data() usage
Can't remove it yet, as libusb transfers and timeouts don't pass the
fp_dev or fp_img_dev separately.
2018-09-18 18:30:42 +02:00
Bastien Nocera
7dfc8f3364 lib: Remove fpi_ssm_get_dev()
Usually by passing the dev it from an fpi_ssm callback, or simply
using that callback argument.
2018-09-18 14:02:23 +02:00
Bastien Nocera
e397571f83 lib: Add more args to fpi_ssm callbacks
Pass the struct fp_dev and user_data to fpi_ssm callbacks, so that we
might be able to get rid of the fpi_ssm_get_user_data(), and
fpi_ssm_get_dev() as most drivers just get those from the ssm anyway
in their callbacks.
2018-09-18 13:46:39 +02:00
Bastien Nocera
d34d7c26de lib: Remove fpi_ssm_set_user_data()
And pass the user_data in fpi_ssm_new() instead.
2018-09-18 13:45:33 +02:00
Bastien Nocera
77defa1d8b lib: Remove fpi_dev_get_nr_enroll_stages()
It's the same as fp_dev_get_nr_enroll_stages()
2018-09-15 01:23:02 +02:00
Bastien Nocera
5d01497b8b lib: Remove dev_to_img_dev() helper
We can access the img_dev struct member directly, and we don't have
to double check that the img_dev member is actually an img_dev type,
as it always is.
2018-09-15 01:20:59 +02:00
Bastien Nocera
cb8732b255 lib: Remove priv struct member in fp_driver
It's unused.
2018-09-15 01:18:14 +02:00
Bastien Nocera
3f64b2ea5a lib: Remove fpi_imgdev_get_usb_dev()
We now use fpi_get_usb_dev(FP_DEV()) instead.
2018-09-15 01:12:18 +02:00
Bastien Nocera
57b38a2876 lib: Remove fpi_imgdev_get_dev()
This is now handled by FP_DEV()
2018-09-15 01:12:18 +02:00
Bastien Nocera
058f91909d lib: Remove fp_img_dev->priv
And use the new instance data helper.
2018-09-15 01:12:18 +02:00
Bastien Nocera
4f75e63e25 lib: Remove fp_dev->priv
Not precise enough, and it was only used in upekts to get/set the
instance private struct and keep it around, so add a new, more precisely
defined field to fp_dev for that.
2018-09-15 01:12:18 +02:00
Bastien Nocera
2e50ff5e7c lib: Add some TODO items to fp_dev struct 2018-09-15 01:09:50 +02:00
Bastien Nocera
0b7477e72c lib: Use fp_dev to access USB device
Instead of having own own pointer in fp_img_dev
2018-09-15 01:09:50 +02:00
Bastien Nocera
4dc8aa6dfa docs: Add fpi-dev helpers to API docs 2018-09-15 01:09:50 +02:00
Bastien Nocera
161c3ccf1c lib: Link fp_dev to fp_img_dev and back
So it's easy to switch between the 2 structs, and remove fp_img_dev->dev
direct access, as well as fp_dev->priv "user data" usage.
2018-09-15 01:09:39 +02:00
Bastien Nocera
170da7fec1 lib: Move fp_dev definition and helpers to separate header 2018-09-15 01:09:39 +02:00
Bastien Nocera
d7af9a4498 Merge branch 'wip/hadess/fpi-log-docs' into 'master'
Logging API docs

See merge request libfprint/libfprint!16
2018-09-07 10:59:56 +00:00
Bastien Nocera
3cb3b1d63a lib: Add Logging API documentation 2018-09-06 14:44:45 +02:00
Bastien Nocera
fc66919e1f lib: Make BUG_ON() use fp_err()
So that when we change fp_err() to an assertion, BUG_ON() is changed as
well.
2018-09-06 14:42:33 +02:00
Bastien Nocera
de5b4e7dcb lib: Split off logging helpers 2018-09-06 13:24:41 +02:00
Bastien Nocera
561576961c Merge branch 'wip/hadess/fpi-timeout-docs' into 'master'
fpi_timeout API docs

See merge request libfprint/libfprint!15
2018-09-05 15:53:15 +00:00
Bastien Nocera
2946dabd24 lib: Typedef fpi_timeout 2018-09-05 17:49:02 +02:00
Bastien Nocera
969eefc81f lib: Add fpi_timeout API documentation 2018-09-05 17:48:43 +02:00
Bastien Nocera
efee7262b6 lib: Split off timeout helpers
And rename poll.c to fpi-poll.c
2018-09-05 17:15:20 +02:00
Bastien Nocera
1102d6e478 Merge branch 'wip/hadess/fpi-ssm-docs' into 'master'
Add fpi_ssm API docs

See merge request libfprint/libfprint!14
2018-09-05 14:37:09 +00:00
Bastien Nocera
603aab0a81 lib: Rename fpi_ssm_mark_aborted to fpi_ssm_mark_failed 2018-09-05 16:29:26 +02:00
Bastien Nocera
10e934e234 lib: Add fpi_ssm API documentation 2018-09-05 16:25:34 +02:00
Bastien Nocera
48b9e6c517 lib: Typedef fpi_ssm 2018-09-05 15:40:34 +02:00
Bastien Nocera
5ae2ef5407 lib: Split off fpi_ssm functions
Rename drv.c to something more fitting to its contents, and move state
machine code to its own header.
2018-09-05 15:40:01 +02:00
Bastien Nocera
cafa05dab5 doc: Add include to each section rather than globally
So that we can document internal driver APIs and mention the correct
include.
2018-09-05 15:39:05 +02:00
Bastien Nocera
6345835b02 doc: %NULL changes 2018-09-04 15:58:23 +02:00
Bastien Nocera
1d453b5732 doc: Fix warning about fp_capture_result
The enum values need to be documented before the enum itself, otherwise
this warning is thrown:
warning: Value descriptions for fp_capture_result are missing in source code comment block.
2018-09-04 15:57:46 +02:00
Bastien Nocera
d3a1b86ea4 doc: Fix warnings about user_data
Such as:
warning: Parameter description for *::user_data is missing in source code comment block.
2018-09-04 15:56:32 +02:00
Bastien Nocera
bb27ca5720 lib: Work-around gtk-doc's handling of the short type
gtk-doc thinks "short" is only a modifier, not a type of its own (short
== short int). This work-around does not change the ABI.

See https://gitlab.gnome.org/GNOME/gtk-doc/issues/44
2018-09-04 15:45:18 +02:00
Bastien Nocera
065c0b6202 fdu2000: This comment is not API docs
So format it in a way that gtk-doc doesn't think it's API docs.
2018-09-04 15:44:26 +02:00
Bastien Nocera
b4819701b4 doc: Fix warning about fp_print_data
It was listed twice in the sections declaration.
2018-09-04 15:42:57 +02:00
Bastien Nocera
daed05755a lib: Remove unused fp_imgdev_verify_state from drivers API 2018-09-04 14:46:25 +02:00
Bastien Nocera
fb192f706c lib: Remove unused fp_dev_state from drivers API 2018-09-04 14:45:49 +02:00
Bastien Nocera
350b0a38e2 drivers: De-duplicate udf_crc() helper
Was in both the upektc_img and upekts drivers
2018-09-04 14:05:37 +02:00
Bastien Nocera
9ccbda4a40 Merge branch 'wip/hadess/update-nbis-5-0-0' into 'master'
Update to NBIS 5.0.0

See merge request libfprint/libfprint!12
2018-08-28 09:35:46 +00:00
Bastien Nocera
821cbae187 loop: Remove unused variable
mindtct/loop.c: In function ‘process_loop_V2’:
mindtct/loop.c:713:8: warning: variable ‘halfway’ set but not used [-Wunused-but-set-variable]
    int halfway;
        ^~~~~~~
2018-08-27 20:01:00 +02:00
Bastien Nocera
528f3556ea vfs301: Use vfs301_proto_deinit()
Even though it does nothing, make sure to use it so it's useful once it
does something.
2018-08-27 20:01:00 +02:00
Bastien Nocera
489afea605 lib: Remove unused fpi_dev_get_dev_state()
This internal-only function was never used.
2018-08-27 20:01:00 +02:00
Bastien Nocera
688a133f3f morph: Fix misleading indentation
mindtct/morph.c: In function ‘get_south8_2’:
mindtct/morph.c:173:4: warning: this ‘if’ clause does not guard... [-Wmisleading-indentation]
    if (row >= ih-1) /* catch case where image is undefined southwards   */
    ^~
mindtct/morph.c:176:7: note: ...this statement, but the latter is misleadingly indented as if it were guarded by the ‘if’
       return *(ptr+iw);
       ^~~~~~
mindtct/morph.c: In function ‘get_north8_2’:
mindtct/morph.c:197:4: warning: this ‘if’ clause does not guard... [-Wmisleading-indentation]
    if (row < 1)     /* catch case where image is undefined northwards   */
    ^~
mindtct/morph.c:200:7: note: ...this statement, but the latter is misleadingly indented as if it were guarded by the ‘if’
       return *(ptr-iw);
       ^~~~~~
mindtct/morph.c: In function ‘get_east8_2’:
mindtct/morph.c:221:4: warning: this ‘if’ clause does not guard... [-Wmisleading-indentation]
    if (col >= iw-1) /* catch case where image is undefined eastwards    */
    ^~
mindtct/morph.c:224:7: note: ...this statement, but the latter is misleadingly indented as if it were guarded by the ‘if’
       return *(ptr+ 1);
       ^~~~~~
mindtct/morph.c: In function ‘get_west8_2’:
mindtct/morph.c:243:4: warning: this ‘if’ clause does not guard... [-Wmisleading-indentation]
    if (col < 1)     /* catch case where image is undefined westwards     */
    ^~
mindtct/morph.c:246:7: note: ...this statement, but the latter is misleadingly indented as if it were guarded by the ‘if’
       return *(ptr- 1);
       ^~~~~~
2018-08-27 20:01:00 +02:00
Bastien Nocera
0cd37b0142 block: Remove unused variable
mindtct/block.c: In function ‘block_offsets’:
mindtct/block.c:108:18: warning: variable ‘ph’ set but not used [-Wunused-but-set-variable]
    int pad2, pw, ph;
                  ^~
2018-08-27 20:01:00 +02:00
Bastien Nocera
9fb789dc78 nbis: Update to NBIS 5.0.0
This updates NBIS to its latest 5.0.0 version, dated 04/03/2015, from a
1.x version, dated 2007.

Original sources are available at:
https://www.nist.gov/itl/iad/image-group/products-and-services/image-group-open-source-server-nigos#Releases

And full change log at:
https://www.nist.gov/sites/default/files/documents/2016/12/14/changelog.txt
2018-08-27 20:01:00 +02:00
Bastien Nocera
770444af55 nbis: Add script to update NBIS and apply changes
NBIS is pretty complicated to update, seeing as we've made quite a few
changes to get it to compile as a library. With those scripts, we can
easily trim headers to remove functions we don't use, rename global
variables, and do any sort of fixups that are necessary right now.

In the future, removing unused NBIS functions might be as easy as
updating that script, re-running it, and pushing the changes.

Note that remove-function.lua is a very crude parser that only supports
NBIS' style of declaration, with the return type on the same line as the
function name. I wouldn't recommend trying to use it in another project.

Callcatcher (https://github.com/caolanm/callcatcher) was also used to
remove additional unused functions.
2018-08-27 20:01:00 +02:00
Bastien Nocera
703d9b2a07 img: Remove remove_perimeter_pts setting
It's gone in NBIS 5.0.0, and will need to be replaced after the update.
2018-08-24 16:11:07 +02:00
Bastien Nocera
a96509f286 Merge branch 'iafilatov/libfprint-elan-prepare-merge' into 'master'
elan: Send stop cmd and recalibrate after each capture

See merge request libfprint/libfprint!11
2018-08-10 12:36:01 +00:00
Igor Filatov
8553f2e41c elan: Send stop cmd and recalibrate after each capture
This seems to fix the lock-up issue with 0903
2018-08-10 14:21:36 +02:00
Bastien Nocera
56c96dde8b Merge branch 'wip/hadess/elan-update' into 'master'
Update Elan driver

See merge request libfprint/libfprint!10
2018-08-10 12:06:35 +00:00
Bastien Nocera
9793d60c5a elan: Remove unused string.h include 2018-08-10 13:45:29 +02:00
Igor Filatov
4ff97e7cbd elan: Increase bz3 threshold to 24
Based on experience. Values more than 24 seem to work just after
enrollment, but it becomes very hard to verify in a day or so.
2018-08-10 13:45:29 +02:00
Igor Filatov
75fe328f64 elan: Don't rotate frames on 0x0c03
There has been a report that a 0x0c03 was installed straight (other
readers so far have produced images that are 90 degrees rotated). There
is no way for the dirver to know how a device is installed, so for now just
make an exception.
2018-08-10 13:45:29 +02:00
Igor Filatov
b28b006d61 elan: Use IMGDEV_STATE_* events instead of pre-set capture path 2018-08-10 13:45:29 +02:00
Igor Filatov
c3b1c982bc elan: Set max frame height to 50, add note about performance
Frame height is a loosely experience-backed guesstimation. 50 seems to be
a good middle ground between swipe speed and quality.
2018-08-10 13:45:29 +02:00
Igor Filatov
b098399bbc elan: Support 0x0c01~0x0c33 2018-08-10 13:45:29 +02:00
Igor Filatov
65bbdff3fc elan: Stop doing sensor reset, change calibration and frame logic
Sensor reset code has been removed because it is not needed during normal
operation.

Calibration and frame processing logic has been improved according to
recommendations from Elantech.
2018-08-10 13:45:29 +02:00
Igor Filatov
fba3e682ea elan: Remove supported devices from udev whitelist 2018-08-09 14:45:15 +02:00
Igor Filatov
bccff4ffef elan: Change command structs, support more devices
Make each command a separate struct to get finer control over which
commands are called on which devices. Update ssm's accordingly. Add
sensor_reset and fuse_load commands.

Support 0x0903, 0x0c03, 0x0c16, 0x0c1a, 0x0c26
2018-08-09 14:42:25 +02:00
Bastien Nocera
9843c2d764 Merge branch 'wip/hadess/gtk-doc-meson-regression' into 'master'
build: Fix build with newer meson

See merge request libfprint/libfprint!9
2018-07-20 10:36:28 +00:00
Bastien Nocera
c9abbec48a build: Fix build with newer meson
The gtk-doc meson helper regressed in that it didn't expect the
libfprint.types file to not exist, as earlier versions did. Remove
the --rebuild-types call so that it is not generated, and meson carries
on compiling the rest of the library.

See https://gitlab.gnome.org/GNOME/gtk-doc/issues/48
See https://github.com/mesonbuild/meson/issues/3892
See https://bugzilla.redhat.com/show_bug.cgi?id=1604585
2018-07-20 12:22:50 +02:00
Bastien Nocera
bc79f9504b Merge branch 'wip/hadess/more-string-h' into 'master'
lib: Include more standard headers for drivers to use

See merge request libfprint/libfprint!8
2018-07-18 09:08:41 +00:00
Bastien Nocera
626b0f1a8f lib: Include more standard headers for drivers to use
Such as string.h and stdlib.h, to be able to compile on older
toolchains like that of Fedora 27.
2018-07-17 16:14:09 +02:00
129 changed files with 11139 additions and 8672 deletions

View File

@@ -1,20 +1,64 @@
image: fedora:rawhide
stages:
- build
- test
variables:
DEPENDENCIES: libusb1-devel glib2-devel nss-devel pixman-devel systemd meson gtk-doc
gcc gcc-c++ glibc-devel libX11-devel libXv-devel
gcc gcc-c++ glibc-devel libX11-devel libXv-devel gtk3-devel flatpak-builder
BUNDLE: "org.freedesktop.libfprint.Demo.flatpak"
before_script:
- dnf update -y --nogpgcheck && dnf install -y --nogpgcheck $DEPENDENCIES && rpm -Uvh --oldpackage https://kojipkgs.fedoraproject.org//packages/meson/0.46.1/2.fc29/noarch/meson-0.46.1-2.fc29.noarch.rpm
build:
stage: build
.build_one_driver_template: &build_one_driver
script:
- meson . _build
- dnf update -y --nogpgcheck && dnf install -y --nogpgcheck $DEPENDENCIES
# Build with a driver that doesn't need imaging, or nss
- meson -Ddrivers=elan . _build
- ninja -C _build
- rm -rf _build/
.build_template: &build
script:
- dnf update -y --nogpgcheck && dnf install -y --nogpgcheck $DEPENDENCIES
# And build with everything
- meson -Ddrivers=all . _build
- ninja -C _build
- ninja -C _build install
build:
stage: build
<<: *build_one_driver
<<: *build
.flatpak_script_template: &flatpak_script
script:
- flatpak-builder --stop-at=${FLATPAK_MODULE} app ${MANIFEST_PATH}
# Make sure to keep this in sync with the Flatpak manifest, all arguments
# are passed except the config-args because we build it ourselves
- flatpak build app meson --prefix=/app --libdir=lib ${MESON_ARGS} _build
- flatpak build app ninja -C _build install
- flatpak build app rm -rf /app/include/ /app/lib/pkgconfig/
- flatpak-builder --finish-only --repo=repo app ${MANIFEST_PATH}
# Generate a Flatpak bundle
- flatpak build-bundle repo ${BUNDLE} --runtime-repo=${RUNTIME_REPO} ${DBUS_ID}
.flatpak_artifacts_template: &flatpak_artifacts
artifacts:
paths:
- ${BUNDLE}
when: always
expire_in: 30 days
.flatpak_template: &flatpak
<<: *flatpak_script
<<: *flatpak_artifacts
flatpak master:
image: registry.gitlab.gnome.org/gnome/gnome-runtime-images/gnome:master
stage: test
variables:
MANIFEST_PATH: "demo/org.freedesktop.libfprint.Demo.json"
# From demo/org.freedesktop.libfprint.Demo.json
MESON_ARGS: "-Dudev_rules=false -Dx11-examples=false -Dgtk-examples=true"
FLATPAK_MODULE: "libfprint"
DBUS_ID: "org.freedesktop.libfprint.Demo"
<<: *flatpak

20
NEWS
View File

@@ -1,6 +1,26 @@
This file lists notable changes in each release. For the full history of all
changes, see ChangeLog.
2018-12-14: v0.99.0 release
* Library:
- All the internal API for device driver writers is now covered by the
documentation and has been enhanced to make it easier to write drivers
- Update internal NBIS fingerprint data processing library to one that's
nearly 10 years newer
- Re-add accessor for minutia coordinates which was used in the very
old fprint_demo program, but also by our new GTK+ test program (see below)
- Fix a crash when too many minutiae were detected in a capture
* Drivers:
- Support more devices in the Elan driver, stability improvements
* Tools:
- Add a test GTK+ application that will eventually be used for testing
drivers without modifying the OS installed version. Note that this
application currently requires manually changing permissions of USB
devices, this will be fixed when the infrastructure exists to access
those devices without additional permissions, as a normal user.
2018-07-15: v0.8.2 release
* Drivers:
- Add USB ID for TNP Nano USB Fingerprint Reader

10
README
View File

@@ -39,3 +39,13 @@ We include bozorth3 from the US export controlled distribution. We have
determined that it is fine to ship bozorth3 in an open source project,
see https://fprint.freedesktop.org/us-export-control.html
## Historical links
Older versions of libfprint are available at:
https://sourceforge.net/projects/fprint/files/
Historical mailing-list archives:
http://www.reactivated.net/fprint_list_archives/
Historical website:
http://web.archive.org/web/*/https://www.freedesktop.org/wiki/Software/fprint/

523
demo/gtk-libfprint-test.c Normal file
View File

@@ -0,0 +1,523 @@
/*
* Example libfprint GTK+ image capture program
* Copyright (C) 2018 Bastien Nocera <hadess@hadess.net>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "config.h"
#include <gtk/gtk.h>
#include <libfprint/fprint.h>
#include "loop.h"
typedef GtkApplication LibfprintDemo;
typedef GtkApplicationClass LibfprintDemoClass;
G_DEFINE_TYPE (LibfprintDemo, libfprint_demo, GTK_TYPE_APPLICATION)
typedef enum {
IMAGE_DISPLAY_NONE = 0,
IMAGE_DISPLAY_MINUTIAE = 1 << 0,
IMAGE_DISPLAY_BINARY = 1 << 1
} ImageDisplayFlags;
typedef struct {
GtkApplicationWindow parent_instance;
GtkWidget *header_bar;
GtkWidget *mode_stack;
GtkWidget *capture_button;
GtkWidget *capture_image;
GtkWidget *spinner;
GtkWidget *instructions;
struct fp_dscv_dev *ddev;
struct fp_dev *dev;
struct fp_img *img;
ImageDisplayFlags img_flags;
} LibfprintDemoWindow;
typedef GtkApplicationWindowClass LibfprintDemoWindowClass;
G_DEFINE_TYPE (LibfprintDemoWindow, libfprint_demo_window, GTK_TYPE_APPLICATION_WINDOW)
typedef enum {
EMPTY_MODE,
NOIMAGING_MODE,
CAPTURE_MODE,
SPINNER_MODE,
ERROR_MODE
} LibfprintDemoMode;
static void libfprint_demo_set_mode (LibfprintDemoWindow *win,
LibfprintDemoMode mode);
static void
pixbuf_destroy (guchar *pixels, gpointer data)
{
if (pixels == NULL)
return;
g_free (pixels);
}
static unsigned char *
img_to_rgbdata (struct fp_img *img,
int width,
int height)
{
int size = width * height;
unsigned char *imgdata = fp_img_get_data (img);
unsigned char *rgbdata = g_malloc (size * 3);
size_t i;
size_t rgb_offset = 0;
for (i = 0; i < size; i++) {
unsigned char pixel = imgdata[i];
rgbdata[rgb_offset++] = pixel;
rgbdata[rgb_offset++] = pixel;
rgbdata[rgb_offset++] = pixel;
}
return rgbdata;
}
static void
plot_minutiae (unsigned char *rgbdata,
int width,
int height,
struct fp_minutia **minlist,
int nr_minutiae)
{
int i;
#define write_pixel(num) do { \
rgbdata[((num) * 3)] = 0xff; \
rgbdata[((num) * 3) + 1] = 0; \
rgbdata[((num) * 3) + 2] = 0; \
} while(0)
for (i = 0; i < nr_minutiae; i++) {
struct fp_minutia *min = minlist[i];
int x, y;
size_t pixel_offset;
fp_minutia_get_coords(min, &x, &y);
pixel_offset = (y * width) + x;
write_pixel(pixel_offset - 2);
write_pixel(pixel_offset - 1);
write_pixel(pixel_offset);
write_pixel(pixel_offset + 1);
write_pixel(pixel_offset + 2);
write_pixel(pixel_offset - (width * 2));
write_pixel(pixel_offset - (width * 1) - 1);
write_pixel(pixel_offset - (width * 1));
write_pixel(pixel_offset - (width * 1) + 1);
write_pixel(pixel_offset + (width * 1) - 1);
write_pixel(pixel_offset + (width * 1));
write_pixel(pixel_offset + (width * 1) + 1);
write_pixel(pixel_offset + (width * 2));
}
}
static GdkPixbuf *
img_to_pixbuf (struct fp_img *img,
ImageDisplayFlags flags)
{
int width;
int height;
unsigned char *rgbdata;
width = fp_img_get_width (img);
height = fp_img_get_height (img);
if (flags & IMAGE_DISPLAY_BINARY) {
struct fp_img *binary;
binary = fp_img_binarize (img);
rgbdata = img_to_rgbdata (binary, width, height);
fp_img_free (binary);
} else {
rgbdata = img_to_rgbdata (img, width, height);
}
if (flags & IMAGE_DISPLAY_MINUTIAE) {
struct fp_minutia **minlist;
int nr_minutiae;
minlist = fp_img_get_minutiae (img, &nr_minutiae);
plot_minutiae (rgbdata, width, height, minlist, nr_minutiae);
}
return gdk_pixbuf_new_from_data (rgbdata, GDK_COLORSPACE_RGB,
FALSE, 8, width, height,
width * 3, pixbuf_destroy,
NULL);
}
static void
update_image (LibfprintDemoWindow *win)
{
GdkPixbuf *pixbuf;
if (win->img == NULL) {
gtk_image_clear (GTK_IMAGE (win->capture_image));
return;
}
g_debug ("Updating image, minutiae %s, binary mode %s",
win->img_flags & IMAGE_DISPLAY_MINUTIAE ? "shown" : "hidden",
win->img_flags & IMAGE_DISPLAY_BINARY ? "on" : "off");
pixbuf = img_to_pixbuf (win->img, win->img_flags);
gtk_image_set_from_pixbuf (GTK_IMAGE (win->capture_image), pixbuf);
g_object_unref (pixbuf);
}
static void
libfprint_demo_set_spinner_label (LibfprintDemoWindow *win,
const char *message)
{
char *label;
label = g_strdup_printf ("<b><span size=\"large\">%s</span></b>", message);
gtk_label_set_markup (GTK_LABEL (win->instructions), label);
g_free (label);
}
static void
libfprint_demo_set_capture_label (LibfprintDemoWindow *win)
{
struct fp_driver *drv;
enum fp_scan_type scan_type;
const char *message;
drv = fp_dscv_dev_get_driver (win->ddev);
scan_type = fp_driver_get_scan_type(drv);
switch (scan_type) {
case FP_SCAN_TYPE_PRESS:
message = "Place your finger on the fingerprint reader";
break;
case FP_SCAN_TYPE_SWIPE:
message = "Swipe your finger across the fingerprint reader";
break;
default:
g_assert_not_reached ();
}
libfprint_demo_set_spinner_label (win, message);
}
static void
dev_capture_start_cb (struct fp_dev *dev,
int result,
struct fp_img *img,
void *user_data)
{
LibfprintDemoWindow *win = user_data;
if (result < 0) {
libfprint_demo_set_mode (win, ERROR_MODE);
return;
}
fp_async_capture_stop (dev, NULL, NULL);
win->img = img;
update_image (win);
libfprint_demo_set_mode (win, CAPTURE_MODE);
}
static void
dev_open_cb (struct fp_dev *dev, int status, void *user_data)
{
LibfprintDemoWindow *win = user_data;
int r;
if (status < 0) {
libfprint_demo_set_mode (win, ERROR_MODE);
return;
}
libfprint_demo_set_capture_label (win);
win->dev = dev;
r = fp_async_capture_start (win->dev, FALSE, dev_capture_start_cb, user_data);
if (r < 0) {
g_warning ("fp_async_capture_start failed: %d", r);
libfprint_demo_set_mode (win, ERROR_MODE);
return;
}
}
static void
activate_capture (GSimpleAction *action,
GVariant *parameter,
gpointer user_data)
{
LibfprintDemoWindow *win = user_data;
int r;
libfprint_demo_set_mode (win, SPINNER_MODE);
g_clear_pointer (&win->img, fp_img_free);
if (win->dev != NULL) {
dev_open_cb (win->dev, 0, user_data);
return;
}
libfprint_demo_set_spinner_label (win, "Opening fingerprint reader");
r = fp_async_dev_open (win->ddev, dev_open_cb, user_data);
if (r < 0) {
g_warning ("fp_async_dev_open failed: %d", r);
libfprint_demo_set_mode (win, ERROR_MODE);
return;
}
}
static void
activate_quit (GSimpleAction *action,
GVariant *parameter,
gpointer user_data)
{
GtkApplication *app = user_data;
GtkWidget *win;
GList *list, *next;
list = gtk_application_get_windows (app);
while (list)
{
win = list->data;
next = list->next;
gtk_widget_destroy (GTK_WIDGET (win));
list = next;
}
}
static void
activate_show_minutiae (GSimpleAction *action,
GVariant *parameter,
gpointer user_data)
{
LibfprintDemoWindow *win = user_data;
GVariant *state;
gboolean new_state;
state = g_action_get_state (G_ACTION (action));
new_state = !g_variant_get_boolean (state);
g_action_change_state (G_ACTION (action), g_variant_new_boolean (new_state));
g_variant_unref (state);
if (new_state)
win->img_flags |= IMAGE_DISPLAY_MINUTIAE;
else
win->img_flags &= ~IMAGE_DISPLAY_MINUTIAE;
update_image (win);
}
static void
activate_show_binary (GSimpleAction *action,
GVariant *parameter,
gpointer user_data)
{
LibfprintDemoWindow *win = user_data;
GVariant *state;
gboolean new_state;
state = g_action_get_state (G_ACTION (action));
new_state = !g_variant_get_boolean (state);
g_action_change_state (G_ACTION (action), g_variant_new_boolean (new_state));
g_variant_unref (state);
if (new_state)
win->img_flags |= IMAGE_DISPLAY_BINARY;
else
win->img_flags &= ~IMAGE_DISPLAY_BINARY;
update_image (win);
}
static void
change_show_minutiae_state (GSimpleAction *action,
GVariant *state,
gpointer user_data)
{
g_simple_action_set_state (action, state);
}
static void
change_show_binary_state (GSimpleAction *action,
GVariant *state,
gpointer user_data)
{
g_simple_action_set_state (action, state);
}
static GActionEntry app_entries[] = {
{ "quit", activate_quit, NULL, NULL, NULL },
};
static GActionEntry win_entries[] = {
{ "show-minutiae", activate_show_minutiae, NULL, "false", change_show_minutiae_state },
{ "show-binary", activate_show_binary, NULL, "false", change_show_binary_state },
{ "capture", activate_capture, NULL, NULL, NULL }
};
static void
activate (GApplication *app)
{
LibfprintDemoWindow *window;
window = g_object_new (libfprint_demo_window_get_type (),
"application", app,
NULL);
gtk_widget_show (GTK_WIDGET (window));
}
static void
libfprint_demo_set_mode (LibfprintDemoWindow *win,
LibfprintDemoMode mode)
{
struct fp_driver *drv;
char *title;
switch (mode) {
case EMPTY_MODE:
gtk_stack_set_visible_child_name (GTK_STACK (win->mode_stack), "empty-mode");
gtk_widget_set_sensitive (win->capture_button, FALSE);
gtk_spinner_stop (GTK_SPINNER (win->spinner));
break;
case NOIMAGING_MODE:
gtk_stack_set_visible_child_name (GTK_STACK (win->mode_stack), "noimaging-mode");
gtk_widget_set_sensitive (win->capture_button, FALSE);
gtk_spinner_stop (GTK_SPINNER (win->spinner));
break;
case CAPTURE_MODE:
gtk_stack_set_visible_child_name (GTK_STACK (win->mode_stack), "capture-mode");
gtk_widget_set_sensitive (win->capture_button, TRUE);
drv = fp_dscv_dev_get_driver (win->ddev);
title = g_strdup_printf ("%s Test", fp_driver_get_full_name (drv));
gtk_header_bar_set_title (GTK_HEADER_BAR (win->header_bar), title);
g_free (title);
gtk_spinner_stop (GTK_SPINNER (win->spinner));
break;
case SPINNER_MODE:
gtk_stack_set_visible_child_name (GTK_STACK (win->mode_stack), "spinner-mode");
gtk_widget_set_sensitive (win->capture_button, FALSE);
gtk_spinner_start (GTK_SPINNER (win->spinner));
break;
case ERROR_MODE:
gtk_stack_set_visible_child_name (GTK_STACK (win->mode_stack), "error-mode");
gtk_widget_set_sensitive (win->capture_button, FALSE);
gtk_spinner_stop (GTK_SPINNER (win->spinner));
break;
default:
g_assert_not_reached ();
}
}
static void
libfprint_demo_init (LibfprintDemo *app)
{
g_action_map_add_action_entries (G_ACTION_MAP (app),
app_entries, G_N_ELEMENTS (app_entries),
app);
}
static void
libfprint_demo_class_init (LibfprintDemoClass *class)
{
GApplicationClass *app_class = G_APPLICATION_CLASS (class);
app_class->activate = activate;
}
static void
libfprint_demo_window_init (LibfprintDemoWindow *window)
{
struct fp_dscv_dev **discovered_devs;
gtk_widget_init_template (GTK_WIDGET (window));
gtk_window_set_default_size (GTK_WINDOW (window), 700, 500);
g_action_map_add_action_entries (G_ACTION_MAP (window),
win_entries, G_N_ELEMENTS (win_entries),
window);
if (fp_init () < 0) {
libfprint_demo_set_mode (window, ERROR_MODE);
return;
}
setup_pollfds ();
discovered_devs = fp_discover_devs();
if (!discovered_devs) {
libfprint_demo_set_mode (window, ERROR_MODE);
return;
}
/* Empty list? */
if (discovered_devs[0] == NULL) {
fp_dscv_devs_free (discovered_devs);
libfprint_demo_set_mode (window, EMPTY_MODE);
return;
}
if (!fp_driver_supports_imaging(fp_dscv_dev_get_driver(discovered_devs[0]))) {
libfprint_demo_set_mode (window, NOIMAGING_MODE);
return;
}
window->ddev = discovered_devs[0];
libfprint_demo_set_mode (window, CAPTURE_MODE);
}
static void
libfprint_demo_window_class_init (LibfprintDemoWindowClass *class)
{
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
gtk_widget_class_set_template_from_resource (widget_class, "/libfprint_demo/gtk-libfprint-test.ui");
gtk_widget_class_bind_template_child (widget_class, LibfprintDemoWindow, header_bar);
gtk_widget_class_bind_template_child (widget_class, LibfprintDemoWindow, mode_stack);
gtk_widget_class_bind_template_child (widget_class, LibfprintDemoWindow, capture_button);
gtk_widget_class_bind_template_child (widget_class, LibfprintDemoWindow, capture_image);
gtk_widget_class_bind_template_child (widget_class, LibfprintDemoWindow, spinner);
gtk_widget_class_bind_template_child (widget_class, LibfprintDemoWindow, instructions);
//FIXME setup dispose
}
int main (int argc, char **argv)
{
GtkApplication *app;
app = GTK_APPLICATION (g_object_new (libfprint_demo_get_type (),
"application-id", "org.freedesktop.libfprint.Demo",
"flags", G_APPLICATION_FLAGS_NONE,
NULL));
return g_application_run (G_APPLICATION (app), 0, NULL);
}

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<gresources>
<gresource prefix="/libfprint_demo">
<file>gtk-libfprint-test.ui</file>
</gresource>
</gresources>

351
demo/gtk-libfprint-test.ui Normal file
View File

@@ -0,0 +1,351 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.22.1 -->
<interface>
<requires lib="gtk+" version="3.20"/>
<template class="LibfprintDemoWindow" parent="GtkApplicationWindow">
<property name="can_focus">False</property>
<property name="default_width">500</property>
<property name="default_height">400</property>
<property name="show_menubar">False</property>
<child type="titlebar">
<object class="GtkHeaderBar" id="header_bar">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="title">Fingerprint Reader Test</property>
<property name="subtitle">Capture test</property>
<property name="show_close_button">True</property>
<child>
<object class="GtkMenuButton" id="option-menu-button">
<property name="visible">True</property>
<property name="sensitive">False</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="valign">center</property>
<property name="menu-model">options-menu</property>
<child>
<object class="GtkImage">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="icon_name">open-menu-symbolic</property>
</object>
</child>
</object>
<packing>
<property name="pack_type">end</property>
</packing>
</child>
<child>
<object class="GtkButton" id="capture_button">
<property name="visible">True</property>
<property name="sensitive">False</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="valign">center</property>
<property name="action_name">win.capture</property>
<child>
<object class="GtkLabel" id="capture_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">_Capture</property>
<property name="use_underline">True</property>
</object>
</child>
<style>
<class name="text-button"/>
</style>
</object>
<packing>
<property name="pack_type">end</property>
</packing>
</child>
</object>
</child>
<child>
<object class="GtkStack" id="mode_stack">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkGrid" id="spinner-mode">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">center</property>
<property name="valign">center</property>
<property name="hexpand">True</property>
<property name="vexpand">True</property>
<property name="orientation">vertical</property>
<property name="row_spacing">12</property>
<child>
<object class="GtkSpinner" id="spinner">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_bottom">9</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">0</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="instructions">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_top">9</property>
<property name="label" translatable="yes">&lt;b&gt;&lt;span size="large"&gt;Please press finger on reader&lt;/span&gt;&lt;/b&gt;</property>
<property name="use_markup">True</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">1</property>
</packing>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<style>
<class name="dim-label"/>
</style>
</object>
<packing>
<property name="name">spinner-mode</property>
<property name="title">spinner-mode</property>
</packing>
</child>
<child>
<object class="GtkGrid" id="empty-mode">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">center</property>
<property name="valign">center</property>
<property name="hexpand">True</property>
<property name="vexpand">True</property>
<property name="orientation">vertical</property>
<property name="row_spacing">12</property>
<child>
<object class="GtkImage">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_bottom">9</property>
<property name="pixel_size">192</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">0</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_top">9</property>
<property name="label" translatable="yes">&lt;b&gt;&lt;span size="large"&gt;No fingerprint readers found&lt;/span&gt;&lt;/b&gt;</property>
<property name="use_markup">True</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">1</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Please connect a supported fingerprint reader and start the application again</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">2</property>
</packing>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<style>
<class name="dim-label"/>
</style>
</object>
<packing>
<property name="name">empty-mode</property>
<property name="title">empty-mode</property>
</packing>
</child>
<child>
<object class="GtkAspectFrame" id="capture-mode">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label_xalign">0</property>
<property name="shadow_type">none</property>
<property name="ratio">1.2999999523162842</property>
<child>
<object class="GtkImage" id="capture_image">
<property name="visible">True</property>
<property name="can_focus">False</property>
</object>
</child>
</object>
<packing>
<property name="name">capture-mode</property>
<property name="title">capture-mode</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkGrid" id="error-mode">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">center</property>
<property name="valign">center</property>
<property name="hexpand">True</property>
<property name="vexpand">True</property>
<property name="orientation">vertical</property>
<property name="row_spacing">12</property>
<child>
<object class="GtkImage">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_bottom">9</property>
<property name="pixel_size">192</property>
<property name="icon_name">dialog-warning-symbolic</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">0</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_top">9</property>
<property name="label" translatable="yes">&lt;b&gt;&lt;span size="large"&gt;An error occurred trying to access the fingerprint reader&lt;/span&gt;&lt;/b&gt;</property>
<property name="use_markup">True</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">1</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Please consult the debugging output before restarting the application</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">2</property>
</packing>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<style>
<class name="dim-label"/>
</style>
</object>
<packing>
<property name="name">error-mode</property>
<property name="title">error-mode</property>
<property name="position">2</property>
</packing>
</child>
<child>
<object class="GtkGrid" id="noimaging-mode">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">center</property>
<property name="valign">center</property>
<property name="hexpand">True</property>
<property name="vexpand">True</property>
<property name="orientation">vertical</property>
<property name="row_spacing">12</property>
<child>
<object class="GtkImage">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_bottom">9</property>
<property name="pixel_size">192</property>
<property name="icon_name">scanner-symbolic</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">0</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_top">9</property>
<property name="label" translatable="yes">&lt;b&gt;&lt;span size="large"&gt;Fingerprint reader does not support capturing images&lt;/span&gt;&lt;/b&gt;</property>
<property name="use_markup">True</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">1</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Please connect a supported fingerprint reader and start the application again</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">2</property>
</packing>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<style>
<class name="dim-label"/>
</style>
</object>
<packing>
<property name="name">noimaging-mode</property>
<property name="title">noimaging-mode</property>
<property name="position">3</property>
</packing>
</child>
</object>
</child>
</template>
<menu id="options-menu">
<section>
<item>
<attribute name="label" translatable="yes">Show Minutiae</attribute>
<attribute name="action">win.show-minutiae</attribute>
</item>
<item>
<attribute name="label" translatable="yes">Show Binary</attribute>
<attribute name="action">win.show-binary</attribute>
</item>
</section>
</menu>
</interface>

196
demo/loop.c Normal file
View File

@@ -0,0 +1,196 @@
/*
* fprint D-Bus daemon
* Copyright (C) 2008 Daniel Drake <dsd@gentoo.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "config.h"
#include <glib.h>
#include <libfprint/fprint.h>
#include <poll.h>
#include <stdlib.h>
#include "loop.h"
struct fdsource {
GSource source;
GSList *pollfds;
};
static gboolean source_prepare(GSource *source, gint *timeout)
{
int r;
struct timeval tv;
r = fp_get_next_timeout(&tv);
if (r == 0) {
*timeout = -1;
return FALSE;
}
if (!timerisset(&tv))
return TRUE;
*timeout = (tv.tv_sec * 1000) + (tv.tv_usec / 1000);
return FALSE;
}
static gboolean source_check(GSource *source)
{
struct fdsource *_fdsource = (struct fdsource *) source;
GSList *l;
struct timeval tv;
int r;
if (!_fdsource->pollfds)
return FALSE;
for (l = _fdsource->pollfds; l != NULL; l = l->next) {
GPollFD *pollfd = l->data;
if (pollfd->revents)
return TRUE;
}
r = fp_get_next_timeout(&tv);
if (r == 1 && !timerisset(&tv))
return TRUE;
return FALSE;
}
static gboolean source_dispatch(GSource *source, GSourceFunc callback,
gpointer data)
{
struct timeval zerotimeout = {
.tv_sec = 0,
.tv_usec = 0,
};
/* FIXME error handling */
fp_handle_events_timeout(&zerotimeout);
/* FIXME whats the return value used for? */
return TRUE;
}
static void source_finalize(GSource *source)
{
struct fdsource *_fdsource = (struct fdsource *) source;
GSList *l;
if (!_fdsource->pollfds)
return;
for (l = _fdsource->pollfds; l != NULL; l = l->next) {
GPollFD *pollfd = l->data;
g_source_remove_poll((GSource *) _fdsource, pollfd);
g_slice_free(GPollFD, pollfd);
_fdsource->pollfds = g_slist_delete_link(_fdsource->pollfds, l);
}
g_slist_free(_fdsource->pollfds);
}
static GSourceFuncs sourcefuncs = {
.prepare = source_prepare,
.check = source_check,
.dispatch = source_dispatch,
.finalize = source_finalize,
};
static struct fdsource *fdsource = NULL;
static void pollfd_add(int fd, short events)
{
GPollFD *pollfd;
pollfd = g_slice_new(GPollFD);
pollfd->fd = fd;
pollfd->events = 0;
pollfd->revents = 0;
if (events & POLLIN)
pollfd->events |= G_IO_IN;
if (events & POLLOUT)
pollfd->events |= G_IO_OUT;
fdsource->pollfds = g_slist_prepend(fdsource->pollfds, pollfd);
g_source_add_poll((GSource *) fdsource, pollfd);
}
static void pollfd_added_cb(int fd, short events)
{
g_debug("now monitoring fd %d", fd);
pollfd_add(fd, events);
}
static void pollfd_removed_cb(int fd)
{
GSList *l;
g_debug("no longer monitoring fd %d", fd);
if (!fdsource->pollfds) {
g_debug("cannot remove from list as list is empty?");
return;
}
for (l = fdsource->pollfds; l != NULL; l = l->next) {
GPollFD *pollfd = l->data;
if (pollfd->fd != fd)
continue;
g_source_remove_poll((GSource *) fdsource, pollfd);
g_slice_free(GPollFD, pollfd);
fdsource->pollfds = g_slist_delete_link(fdsource->pollfds, l);
return;
}
g_error("couldn't find fd %d in list\n", fd);
}
int setup_pollfds(void)
{
ssize_t numfds;
size_t i;
struct fp_pollfd *fpfds;
GSource *gsource;
gsource = g_source_new(&sourcefuncs, sizeof(struct fdsource));
fdsource = (struct fdsource *) gsource;
fdsource->pollfds = NULL;
numfds = fp_get_pollfds(&fpfds);
if (numfds < 0) {
if (fpfds)
free(fpfds);
return (int) numfds;
} else if (numfds > 0) {
for (i = 0; i < numfds; i++) {
struct fp_pollfd *fpfd = &fpfds[i];
pollfd_add(fpfd->fd, fpfd->events);
}
}
free(fpfds);
fp_set_pollfd_notifiers(pollfd_added_cb, pollfd_removed_cb);
g_source_attach(gsource, NULL);
return 0;
}

27
demo/loop.h Normal file
View File

@@ -0,0 +1,27 @@
/*
* Copyright (C) 2008 Daniel Drake <dsd@gentoo.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
*/
#ifndef POLL_H
#define POLL_H
int setup_pollfds(void);
#endif

30
demo/meson.build Normal file
View File

@@ -0,0 +1,30 @@
gtk_test_resources = gnome.compile_resources('gtk-test-resources', 'gtk-libfprint-test.gresource.xml',
source_dir : '.',
c_name : 'gtk_test')
prefix = get_option('prefix')
bindir = join_paths(prefix, get_option('bindir'))
datadir = join_paths(prefix, get_option('datadir'))
executable('gtk-libfprint-test',
[ 'gtk-libfprint-test.c', 'loop.c', 'loop.h', gtk_test_resources ],
dependencies: [ libfprint_dep, gtk_dep ],
include_directories: [
root_inc,
],
c_args: [ common_cflags,
'-DPACKAGE_VERSION="' + meson.project_version() + '"' ],
install: true,
install_dir: bindir)
appdata = 'org.freedesktop.libfprint.Demo.appdata.xml'
install_data(appdata,
install_dir: join_paths(datadir, 'metainfo'))
desktop = 'org.freedesktop.libfprint.Demo.desktop'
install_data(desktop,
install_dir: join_paths(datadir, 'applications'))
icon = 'org.freedesktop.libfprint.Demo.png'
install_data(icon,
install_dir: join_paths(datadir, 'icons'))

View File

@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<component type="desktop">
<id>org.freedesktop.libfprint.Demo.desktop</id>
<name>Fingerprint Reader Demo</name>
<summary>Test fingerprint readers</summary>
<metadata_license>CC0-1.0</metadata_license>
<project_license>LGPL-2.1+</project_license>
<description>
<p>
Fingerprint Reader Demo is a test application for the libfprint
fingerprint reader library. Its purpose is to test drivers, new and old,
in a sandbox, to make sure that the drivers and associated functions
work correctly.
</p>
<p>
Fingerprint Reader Demo does not modify the system, or replace integration
in desktop environments.
</p>
</description>
<url type="homepage">https://fprint.freedesktop.org</url>
<screenshots>
<screenshot type="default" width="1024" height="576">https://git.gnome.org/browse/totem/plain/data/appdata/ss-main.png</screenshot>
<screenshot width="1024" height="576">https://git.gnome.org/browse/totem/plain/data/appdata/ss-music-playlist.png</screenshot>
</screenshots>
<updatecontact>hadess@hadess.net</updatecontact>
<!-- Incorrect, but appstream-util won't validate without it -->
<translation type="gettext">libfprint</translation>
</component>

View File

@@ -0,0 +1,10 @@
[Desktop Entry]
Name=Fingerprint Reader Demo
Comment=Test fingerprint readers
Keywords=finger;print;fingerprint;fprint;demo;driver;reader;
Exec=gtk-libfprint-test
Icon=org.freedesktop.libfprint.Demo
Terminal=false
Type=Application
Categories=GTK;GNOME;Development;System;
StartupNotify=true

View File

@@ -0,0 +1,51 @@
{
"app-id": "org.freedesktop.libfprint.Demo",
"runtime": "org.gnome.Platform",
"runtime-version": "master",
"sdk": "org.gnome.Sdk",
"command": "gtk-libfprint-test",
"finish-args": [
/* X11 + XShm access */
"--share=ipc", "--socket=x11",
/* Wayland access */
"--socket=wayland",
/* OpenGL access */
"--device=dri",
/* USB access */
"--device=all"
],
"cleanup": [ "/include", "/lib/pkgconfig/" ],
"modules": [
{
"name": "libusb",
"config-opts": [ "--disable-static", "--disable-udev" ],
"cleanup": [
"/lib/*.la",
"/lib/pkgconfig",
"/include"
],
"sources": [
{
"type": "archive",
"url": "https://github.com/libusb/libusb/archive/v1.0.22.tar.gz",
"sha256": "3500f7b182750cd9ccf9be8b1df998f83df56a39ab264976bdb3307773e16f48"
}
],
"post-install": [
"install -Dm644 COPYING /app/share/licenses/libusb/COPYING"
]
},
{
"name": "libfprint",
"buildsystem": "meson",
"config-opts": [ "-Dudev_rules=false", "-Dx11-examples=false", "-Dgtk-examples=true" ],
"sources": [
{
"type": "git",
"url": "https://gitlab.freedesktop.org/libfprint/libfprint.git",
"branch": "wip/hadess/gtk-example"
}
]
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

View File

@@ -24,7 +24,7 @@
</part>
<part>
<title>API Documentation</title>
<title>Library API Documentation</title>
<xi:include href="xml/events.xml"/>
<xi:include href="xml/discovery.xml"/>
@@ -36,11 +36,31 @@
<xi:include href="xml/img.xml"/>
</part>
<!--
<part>
<title>Writing Drivers</title>
<chapter id="driver-helpers">
<title>Logging, and async machinery</title>
<xi:include href="xml/fpi-log.xml"/>
<xi:include href="xml/fpi-ssm.xml"/>
<xi:include href="xml/fpi-poll.xml"/>
</chapter>
<chapter id="driver-dev">
<title>Device and driver structures</title>
<xi:include href="xml/fpi-dev.xml"/>
<xi:include href="xml/fpi-dev-img.xml"/>
<xi:include href="xml/fpi-core.xml"/>
<xi:include href="xml/fpi-core-img.xml"/>
</chapter>
<chapter id="driver-img">
<title>Image manipulation</title>
<xi:include href="xml/fpi-img.xml"/>
<xi:include href="xml/fpi-assembling.xml"/>
</chapter>
<xi:include href="xml/fpi-usb.xml"/>
</part>
-->
<index id="api-index">
<title>API Index</title>

View File

@@ -1,8 +1,9 @@
<INCLUDE>fprint.h</INCLUDE>
<SECTION>
<INCLUDE>fprint.h</INCLUDE>
<FILE>events</FILE>
<TITLE>Initialisation and events handling</TITLE>
LIBFPRINT_DEPRECATED
fp_set_debug
fp_init
fp_exit
@@ -17,6 +18,7 @@ fp_set_pollfd_notifiers
</SECTION>
<SECTION>
<INCLUDE>fprint.h</INCLUDE>
<FILE>discovery</FILE>
<TITLE>Device discovery</TITLE>
fp_dscv_dev
@@ -32,15 +34,18 @@ fp_dscv_dev_for_dscv_print
</SECTION>
<SECTION>
<INCLUDE>fprint.h</INCLUDE>
<FILE>drv</FILE>
fp_driver
fp_driver_get_name
fp_driver_get_full_name
fp_driver_get_driver_id
fp_driver_get_scan_type
fp_driver_supports_imaging
</SECTION>
<SECTION>
<INCLUDE>fprint.h</INCLUDE>
<FILE>dev</FILE>
fp_dev
fp_scan_type
@@ -91,10 +96,10 @@ fp_async_capture_stop
</SECTION>
<SECTION>
<INCLUDE>fprint.h</INCLUDE>
<FILE>print_data</FILE>
fp_finger
fp_print_data
fp_print_data
fp_print_data_get_data
fp_print_data_from_data
fp_print_data_save
@@ -107,6 +112,7 @@ fp_print_data_get_devtype
</SECTION>
<SECTION>
<INCLUDE>fprint.h</INCLUDE>
<FILE>dscv_print</FILE>
fp_dscv_print
fp_discover_prints
@@ -118,6 +124,7 @@ fp_dscv_print_delete
</SECTION>
<SECTION>
<INCLUDE>fprint.h</INCLUDE>
<FILE>img</FILE>
fp_img
fp_minutia
@@ -129,8 +136,136 @@ fp_img_save_to_file
fp_img_standardize
fp_img_binarize
fp_img_get_minutiae
fp_minutia_get_coords
</SECTION>
<SECTION>
<FILE>poll</FILE>
<INCLUDE>fpi-log.h</INCLUDE>
<FILE>fpi-log</FILE>
fp_dbg
fp_info
fp_warn
fp_err
BUG_ON
BUG
</SECTION>
<SECTION>
<INCLUDE>fpi-ssm.h</INCLUDE>
<FILE>fpi-ssm</FILE>
fpi_ssm
ssm_completed_fn
ssm_handler_fn
fpi_ssm_new
fpi_ssm_free
fpi_ssm_start
fpi_ssm_start_subsm
fpi_ssm_next_state
fpi_ssm_next_state_timeout_cb
fpi_ssm_jump_to_state
fpi_ssm_mark_completed
fpi_ssm_mark_failed
fpi_ssm_get_user_data
fpi_ssm_get_error
fpi_ssm_get_cur_state
</SECTION>
<SECTION>
<INCLUDE>fpi-poll.h</INCLUDE>
<FILE>fpi-poll</FILE>
fpi_timeout
fpi_timeout_fn
fpi_timeout_add
fpi_timeout_set_name
fpi_timeout_cancel
</SECTION>
<SECTION>
<INCLUDE>fpi-dev.h</INCLUDE>
<FILE>fpi-dev</FILE>
fp_img_dev
FP_DEV
FP_IMG_DEV
fp_dev_set_instance_data
FP_INSTANCE_DATA
fpi_dev_get_usb_dev
fpi_dev_get_verify_data
fpi_dev_set_nr_enroll_stages
</SECTION>
<SECTION>
<INCLUDE>fpi-dev-img.h</INCLUDE>
<FILE>fpi-dev-img</FILE>
fp_imgdev_action
fp_imgdev_state
fp_imgdev_enroll_state
fpi_imgdev_abort_scan
fpi_imgdev_activate_complete
fpi_imgdev_close_complete
fpi_imgdev_deactivate_complete
fpi_imgdev_get_action
fpi_imgdev_get_action_result
fpi_imgdev_get_action_state
fpi_imgdev_image_captured
fpi_imgdev_open_complete
fpi_imgdev_report_finger_status
fpi_imgdev_session_error
fpi_imgdev_set_action_result
</SECTION>
<SECTION>
<INCLUDE>fpi-core.h</INCLUDE>
<FILE>fpi-core</FILE>
usb_id
fp_driver_type
</SECTION>
<SECTION>
<INCLUDE>fpi-core.h</INCLUDE>
<FILE>fpi-core-img</FILE>
FpiImgDriverFlags
fp_img_driver
</SECTION>
<SECTION>
<INCLUDE>fpi-img.h</INCLUDE>
<FILE>fpi-img</FILE>
FpiImgFlags
fpi_img_new
fpi_img_new_for_imgdev
fpi_img_realloc
fpi_img_resize
fpi_std_sq_dev
fpi_mean_sq_diff_norm
</SECTION>
<SECTION>
<INCLUDE>fpi-assembling.h</INCLUDE>
<FILE>fpi-assembling</FILE>
fpi_frame
fpi_frame_asmbl_ctx
fpi_line_asmbl_ctx
fpi_do_movement_estimation
fpi_assemble_frames
fpi_assemble_lines
</SECTION>
<SECTION>
<INCLUDE>fpi-usb.h</INCLUDE>
<FILE>fpi-usb</FILE>
fpi_usb_transfer
fpi_usb_transfer_cb_fn
fpi_usb_alloc
fpi_usb_fill_bulk_transfer
fpi_usb_submit_transfer
fpi_usb_cancel_transfer
</SECTION>

View File

@@ -6,6 +6,9 @@ private_headers = [
'aeslib.h',
'assembling.h',
'fp_internal.h',
'nbis-helpers.h',
'fpi-async.h',
'fpi-data.h',
# Drivers
'aes1660.h',
@@ -16,6 +19,7 @@ private_headers = [
'aesx660.h',
'driver_ids.h',
'elan.h',
'upek_proto.h',
'upeksonly.h',
'upektc.h',
'upektc_img.h',
@@ -32,6 +36,7 @@ private_headers = [
'log.h',
'bz_array.h',
'lfs.h',
'mytime.h',
]
html_images = [
@@ -54,7 +59,6 @@ gnome.gtkdoc('libfprint',
content_files: content_files,
expand_content_files: expand_content_files,
scan_args: [
'--rebuild-types',
'--ignore-decorators=API_EXPORTED',
'--ignore-headers=' + ' '.join(private_headers),
],

View File

@@ -24,6 +24,8 @@
#include <libfprint/fprint.h>
#include "storage.h"
struct fp_dscv_dev *discover_device(struct fp_dscv_dev **discovered_devs)
{
struct fp_dscv_dev *ddev = discovered_devs[0];
@@ -45,8 +47,7 @@ struct fp_print_data *enroll(struct fp_dev *dev) {
do {
struct fp_img *img = NULL;
sleep(1);
printf("\nScan your finger now.\n");
r = fp_enroll_finger_img(dev, &enrolled_print, &img);
@@ -143,7 +144,7 @@ int main(void)
if (!data)
goto out_close;
r = fp_print_data_save(data, RIGHT_INDEX);
r = print_data_save(data, RIGHT_INDEX);
if (r < 0)
fprintf(stderr, "Data save failed, code %d\n", r);

View File

@@ -2,8 +2,8 @@
examples = [ 'verify_live', 'enroll', 'verify', 'img_capture' ]
foreach example: examples
executable(example,
example + '.c',
dependencies: libfprint_dep,
[example + '.c', 'storage.c'],
dependencies: [libfprint_dep, glib_dep],
include_directories: [
root_inc,
],

136
examples/storage.c Normal file
View File

@@ -0,0 +1,136 @@
/*
* Trivial storage driver for example programs
*
* Copyright (C) 2019 Benjamin Berg <bberg@redhat.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <glib.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <libfprint/fprint.h>
#define STORAGE_FILE "test-storage.variant"
static char *
get_print_data_descriptor (struct fp_print_data *data, struct fp_dev *dev, enum fp_finger finger)
{
gint drv_id;
gint devtype;
if (data) {
drv_id = fp_print_data_get_driver_id (data);
devtype = fp_print_data_get_devtype (data);
} else {
drv_id = fp_driver_get_driver_id(fp_dev_get_driver (dev));
devtype = fp_dev_get_devtype (dev);
}
return g_strdup_printf("%x/%08x/%x",
drv_id,
devtype,
finger);
}
static GVariantDict*
load_data(void)
{
GVariantDict *res;
GVariant *var;
gchar *contents = NULL;
gssize length = 0;
if (!g_file_get_contents (STORAGE_FILE, &contents, &length, NULL)) {
g_warning ("Error loading storage, assuming it is empty");
return g_variant_dict_new(NULL);
}
var = g_variant_new_from_data (G_VARIANT_TYPE_VARDICT, contents, length, FALSE, NULL, NULL);
res = g_variant_dict_new(var);
g_variant_unref(var);
return res;
}
static int
save_data(GVariant *data)
{
const gchar *contents = NULL;
gsize length;
length = g_variant_get_size(data);
contents = (gchar*) g_variant_get_data (data);
if (!g_file_set_contents (STORAGE_FILE, contents, length, NULL)) {
g_warning ("Error saving storage,!");
return -1;
}
g_variant_ref_sink(data);
g_variant_unref(data);
return 0;
}
int
print_data_save(struct fp_print_data *fp_data, enum fp_finger finger)
{
gchar *descr = get_print_data_descriptor (fp_data, NULL, finger);
GVariantDict *dict;
GVariant *val;
guchar *data;
gsize size;
int res;
dict = load_data();
size = fp_print_data_get_data(fp_data, &data);
val = g_variant_new_fixed_array (G_VARIANT_TYPE("y"), data, size, 1);
g_variant_dict_insert_value (dict, descr, val);
res = save_data(g_variant_dict_end(dict));
g_variant_dict_unref(dict);
return res;
}
struct fp_print_data*
print_data_load(struct fp_dev *dev, enum fp_finger finger)
{
gchar *descr = get_print_data_descriptor (NULL, dev, finger);
GVariantDict *dict;
guchar *stored_data;
gsize stored_len;
GVariant *val;
struct fp_print_data *res = NULL;
dict = load_data();
val = g_variant_dict_lookup_value (dict, descr, G_VARIANT_TYPE ("ay"));
if (val) {
stored_data = (guchar*) g_variant_get_fixed_array (val, &stored_len, 1);
res = fp_print_data_from_data(stored_data, stored_len);
g_variant_unref(val);
}
g_variant_dict_unref(dict);
g_free(descr);
return res;
}

27
examples/storage.h Normal file
View File

@@ -0,0 +1,27 @@
/*
* Trivial storage driver for example programs
*
* Copyright (C) 2019 Benjamin Berg <bberg@redhat.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __STORAGE_H
#define __STORAGE_H
int print_data_save(struct fp_print_data *fp_data, enum fp_finger finger);
struct fp_print_data* print_data_load(struct fp_dev *dev, enum fp_finger finger);
#endif /* __STORAGE_H */

View File

@@ -24,6 +24,8 @@
#include <libfprint/fprint.h>
#include "storage.h"
struct fp_dscv_dev *discover_device(struct fp_dscv_dev **discovered_devs)
{
struct fp_dscv_dev *ddev = discovered_devs[0];
@@ -117,8 +119,8 @@ int main(void)
printf("Opened device. Loading previously enrolled right index finger "
"data...\n");
r = fp_print_data_load(dev, RIGHT_INDEX, &data);
if (r != 0) {
data = print_data_load(dev, RIGHT_INDEX);
if (!data) {
fprintf(stderr, "Failed to load fingerprint, error %d\n", r);
fprintf(stderr, "Did you remember to enroll your right index finger "
"first?\n");

View File

@@ -43,7 +43,6 @@ struct fp_print_data *enroll(struct fp_dev *dev) {
"complete the process.\n", fp_dev_get_nr_enroll_stages(dev));
do {
sleep(1);
printf("\nScan your finger now.\n");
r = fp_enroll_finger(dev, &enrolled_print);
if (r < 0) {

View File

@@ -1,65 +0,0 @@
/*
* Image assembling routines
* Shared functions between libfprint Authentec drivers
* Copyright (C) 2007 Daniel Drake <dsd@gentoo.org>
* Copyright (C) 2015 Vasily Khoruzhick <anarsoul@gmail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __ASSEMBLING_H__
#define __ASSEMBLING_H__
#include <fprint.h>
struct fpi_frame {
int delta_x;
int delta_y;
unsigned char data[0];
};
struct fpi_frame_asmbl_ctx {
unsigned frame_width;
unsigned frame_height;
unsigned image_width;
unsigned char (*get_pixel)(struct fpi_frame_asmbl_ctx *ctx,
struct fpi_frame *frame,
unsigned x,
unsigned y);
};
void fpi_do_movement_estimation(struct fpi_frame_asmbl_ctx *ctx,
GSList *stripes, size_t stripes_len);
struct fp_img *fpi_assemble_frames(struct fpi_frame_asmbl_ctx *ctx,
GSList *stripes, size_t stripes_len);
struct fpi_line_asmbl_ctx {
unsigned line_width;
unsigned max_height;
unsigned resolution;
unsigned median_filter_size;
unsigned max_search_offset;
int (*get_deviation)(struct fpi_line_asmbl_ctx *ctx,
GSList *line1, GSList *line2);
unsigned char (*get_pixel)(struct fpi_line_asmbl_ctx *ctx,
GSList *line,
unsigned x);
};
struct fp_img *fpi_assemble_lines(struct fpi_line_asmbl_ctx *ctx,
GSList *lines, size_t lines_len);
#endif

View File

@@ -44,6 +44,9 @@ static int adjust_gain(unsigned char *buffer, int status);
#define BULK_TIMEOUT 4000
#define FINGER_DETECTION_LEN 19
#define STRIP_CAPTURE_LEN 665
/*
* The AES1610 is an imaging device using a swipe-type sensor. It samples
* the finger at preprogrammed intervals, sending a 128x8 frame to the
@@ -101,12 +104,12 @@ static void stub_capture_stop_cb(struct fp_img_dev *dev, int result, void *user_
/* check that read succeeded but ignore all data */
static void generic_ignore_data_cb(struct libusb_transfer *transfer)
{
struct fpi_ssm *ssm = transfer->user_data;
fpi_ssm *ssm = transfer->user_data;
if (transfer->status != LIBUSB_TRANSFER_COMPLETED)
fpi_ssm_mark_aborted(ssm, -EIO);
fpi_ssm_mark_failed(ssm, -EIO);
else if (transfer->length != transfer->actual_length)
fpi_ssm_mark_aborted(ssm, -EPROTO);
fpi_ssm_mark_failed(ssm, -EPROTO);
else
fpi_ssm_next_state(ssm);
@@ -117,29 +120,22 @@ static void generic_ignore_data_cb(struct libusb_transfer *transfer)
static void generic_write_regv_cb(struct fp_img_dev *dev, int result,
void *user_data)
{
struct fpi_ssm *ssm = user_data;
fpi_ssm *ssm = user_data;
if (result == 0)
fpi_ssm_next_state(ssm);
else
fpi_ssm_mark_aborted(ssm, result);
fpi_ssm_mark_failed(ssm, result);
}
/* read the specified number of bytes from the IN endpoint but throw them
* away, then increment the SSM */
static void generic_read_ignore_data(struct fpi_ssm *ssm, size_t bytes)
static void generic_read_ignore_data(fpi_ssm *ssm, struct fp_dev *dev, size_t bytes)
{
struct libusb_transfer *transfer = libusb_alloc_transfer(0);
struct libusb_transfer *transfer = fpi_usb_alloc();
unsigned char *data;
struct fp_dev *dev;
int r;
if (!transfer) {
fpi_ssm_mark_aborted(ssm, -ENOMEM);
return;
}
data = g_malloc(bytes);
dev = fpi_ssm_get_dev(ssm);
libusb_fill_bulk_transfer(transfer, fpi_dev_get_usb_dev(dev), EP_IN, data, bytes,
generic_ignore_data_cb, ssm, BULK_TIMEOUT);
@@ -147,7 +143,7 @@ static void generic_read_ignore_data(struct fpi_ssm *ssm, size_t bytes)
if (r < 0) {
g_free(data);
libusb_free_transfer(transfer);
fpi_ssm_mark_aborted(ssm, r);
fpi_ssm_mark_failed(ssm, r);
}
}
@@ -226,14 +222,9 @@ static void finger_det_reqs_cb(struct fp_img_dev *dev, int result, void *user_da
return;
}
transfer = libusb_alloc_transfer(0);
if (!transfer) {
fpi_imgdev_session_error(dev, -ENOMEM);
return;
}
data = g_malloc(19);
libusb_fill_bulk_transfer(transfer, fpi_imgdev_get_usb_dev(dev), EP_IN, data, 19,
transfer = fpi_usb_alloc();
data = g_malloc(FINGER_DETECTION_LEN);
libusb_fill_bulk_transfer(transfer, fpi_dev_get_usb_dev(FP_DEV(dev)), EP_IN, data, FINGER_DETECTION_LEN,
finger_det_data_cb, dev, BULK_TIMEOUT);
r = libusb_submit_transfer(transfer);
@@ -247,7 +238,7 @@ static void finger_det_reqs_cb(struct fp_img_dev *dev, int result, void *user_da
static void start_finger_detection(struct fp_img_dev *dev)
{
struct aes1610_dev *aesdev = fpi_imgdev_get_user_data(dev);
struct aes1610_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev));
if (aesdev->deactivating) {
complete_deactivation(dev);
@@ -557,17 +548,17 @@ enum capture_states {
static void capture_read_strip_cb(struct libusb_transfer *transfer)
{
unsigned char *stripdata;
struct fpi_ssm *ssm = transfer->user_data;
fpi_ssm *ssm = transfer->user_data;
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct aes1610_dev *aesdev = fpi_imgdev_get_user_data(dev);
struct aes1610_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev));
unsigned char *data = transfer->buffer;
int sum, i;
if (transfer->status != LIBUSB_TRANSFER_COMPLETED) {
fpi_ssm_mark_aborted(ssm, -EIO);
fpi_ssm_mark_failed(ssm, -EIO);
goto out;
} else if (transfer->length != transfer->actual_length) {
fpi_ssm_mark_aborted(ssm, -EPROTO);
fpi_ssm_mark_failed(ssm, -EPROTO);
goto out;
}
@@ -594,7 +585,7 @@ static void capture_read_strip_cb(struct libusb_transfer *transfer)
}
if (sum < 0) {
fpi_ssm_mark_aborted(ssm, sum);
fpi_ssm_mark_failed(ssm, sum);
goto out;
}
fp_dbg("sum=%d", sum);
@@ -643,10 +634,10 @@ out:
libusb_free_transfer(transfer);
}
static void capture_run_state(struct fpi_ssm *ssm)
static void capture_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
{
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct aes1610_dev *aesdev = fpi_imgdev_get_user_data(dev);
struct fp_img_dev *dev = user_data;
struct aes1610_dev *aesdev = FP_INSTANCE_DATA(_dev);
int r;
switch (fpi_ssm_get_cur_state(ssm)) {
@@ -657,7 +648,7 @@ static void capture_run_state(struct fpi_ssm *ssm)
break;
case CAPTURE_READ_DATA:
fp_dbg("read data");
generic_read_ignore_data(ssm, 665);
generic_read_ignore_data(ssm, _dev, STRIP_CAPTURE_LEN);
break;
case CAPTURE_REQUEST_STRIP:
fp_dbg("request strip");
@@ -668,32 +659,27 @@ static void capture_run_state(struct fpi_ssm *ssm)
generic_write_regv_cb, ssm);
break;
case CAPTURE_READ_STRIP: ;
struct libusb_transfer *transfer = libusb_alloc_transfer(0);
struct libusb_transfer *transfer = fpi_usb_alloc();
unsigned char *data;
if (!transfer) {
fpi_ssm_mark_aborted(ssm, -ENOMEM);
break;
}
data = g_malloc(665);
libusb_fill_bulk_transfer(transfer, fpi_imgdev_get_usb_dev(dev), EP_IN, data, 665,
data = g_malloc(STRIP_CAPTURE_LEN);
libusb_fill_bulk_transfer(transfer, fpi_dev_get_usb_dev(FP_DEV(dev)), EP_IN, data, STRIP_CAPTURE_LEN,
capture_read_strip_cb, ssm, BULK_TIMEOUT);
r = libusb_submit_transfer(transfer);
if (r < 0) {
g_free(data);
libusb_free_transfer(transfer);
fpi_ssm_mark_aborted(ssm, r);
fpi_ssm_mark_failed(ssm, r);
}
break;
};
}
static void capture_sm_complete(struct fpi_ssm *ssm)
static void capture_sm_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
{
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct aes1610_dev *aesdev = fpi_imgdev_get_user_data(dev);
struct fp_img_dev *dev = user_data;
struct aes1610_dev *aesdev = FP_INSTANCE_DATA(_dev);
G_DEBUG_HERE();
if (aesdev->deactivating)
@@ -707,17 +693,16 @@ static void capture_sm_complete(struct fpi_ssm *ssm)
static void start_capture(struct fp_img_dev *dev)
{
struct aes1610_dev *aesdev = fpi_imgdev_get_user_data(dev);
struct fpi_ssm *ssm;
struct aes1610_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev));
fpi_ssm *ssm;
if (aesdev->deactivating) {
complete_deactivation(dev);
return;
}
ssm = fpi_ssm_new(fpi_imgdev_get_dev(dev), capture_run_state, CAPTURE_NUM_STATES);
ssm = fpi_ssm_new(FP_DEV(dev), capture_run_state, CAPTURE_NUM_STATES, dev);
G_DEBUG_HERE();
fpi_ssm_set_user_data(ssm, dev);
fpi_ssm_start(ssm, capture_sm_complete);
}
@@ -738,9 +723,9 @@ enum activate_states {
ACTIVATE_NUM_STATES,
};
static void activate_run_state(struct fpi_ssm *ssm)
static void activate_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
{
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct fp_img_dev *dev = user_data;
/* activation on aes1610 seems much more straightforward compared to aes2501 */
/* verify theres anything missing here */
@@ -753,9 +738,9 @@ static void activate_run_state(struct fpi_ssm *ssm)
}
/* jump to finger detection */
static void activate_sm_complete(struct fpi_ssm *ssm)
static void activate_sm_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
{
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct fp_img_dev *dev = user_data;
fp_dbg("status %d", fpi_ssm_get_error(ssm));
fpi_imgdev_activate_complete(dev, fpi_ssm_get_error(ssm));
@@ -764,12 +749,11 @@ static void activate_sm_complete(struct fpi_ssm *ssm)
fpi_ssm_free(ssm);
}
static int dev_activate(struct fp_img_dev *dev, enum fp_imgdev_state state)
static int dev_activate(struct fp_img_dev *dev)
{
struct aes1610_dev *aesdev = fpi_imgdev_get_user_data(dev);
struct fpi_ssm *ssm = fpi_ssm_new(fpi_imgdev_get_dev(dev), activate_run_state,
ACTIVATE_NUM_STATES);
fpi_ssm_set_user_data(ssm, dev);
struct aes1610_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev));
fpi_ssm *ssm = fpi_ssm_new(FP_DEV(dev), activate_run_state,
ACTIVATE_NUM_STATES, dev);
aesdev->read_regs_retry_count = 0;
fpi_ssm_start(ssm, activate_sm_complete);
return 0;
@@ -777,7 +761,7 @@ static int dev_activate(struct fp_img_dev *dev, enum fp_imgdev_state state)
static void dev_deactivate(struct fp_img_dev *dev)
{
struct aes1610_dev *aesdev = fpi_imgdev_get_user_data(dev);
struct aes1610_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev));
/* FIXME: audit cancellation points, probably need more, specifically
* in error handling paths? */
aesdev->deactivating = TRUE;
@@ -785,7 +769,7 @@ static void dev_deactivate(struct fp_img_dev *dev)
static void complete_deactivation(struct fp_img_dev *dev)
{
struct aes1610_dev *aesdev = fpi_imgdev_get_user_data(dev);
struct aes1610_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev));
G_DEBUG_HERE();
/* FIXME: if we're in the middle of a scan, we should cancel the scan.
@@ -805,14 +789,14 @@ static int dev_init(struct fp_img_dev *dev, unsigned long driver_data)
int r;
struct aes1610_dev *aesdev;
r = libusb_claim_interface(fpi_imgdev_get_usb_dev(dev), 0);
r = libusb_claim_interface(fpi_dev_get_usb_dev(FP_DEV(dev)), 0);
if (r < 0) {
fp_err("could not claim interface 0: %s", libusb_error_name(r));
return r;
}
aesdev = g_malloc0(sizeof(struct aes1610_dev));
fpi_imgdev_set_user_data(dev, aesdev);
fp_dev_set_instance_data(FP_DEV(dev), aesdev);
fpi_imgdev_open_complete(dev, 0);
return 0;
}
@@ -820,9 +804,9 @@ static int dev_init(struct fp_img_dev *dev, unsigned long driver_data)
static void dev_deinit(struct fp_img_dev *dev)
{
struct aes1610_dev *aesdev;
aesdev = fpi_imgdev_get_user_data(dev);
aesdev = FP_INSTANCE_DATA(FP_DEV(dev));
g_free(aesdev);
libusb_release_interface(fpi_imgdev_get_usb_dev(dev), 0);
libusb_release_interface(fpi_dev_get_usb_dev(FP_DEV(dev)), 0);
fpi_imgdev_close_complete(dev);
}

View File

@@ -40,14 +40,14 @@ static int dev_init(struct fp_img_dev *dev, unsigned long driver_data)
int r;
struct aesX660_dev *aesdev;
r = libusb_claim_interface(fpi_imgdev_get_usb_dev(dev), 0);
r = libusb_claim_interface(fpi_dev_get_usb_dev(FP_DEV(dev)), 0);
if (r < 0) {
fp_err("could not claim interface 0: %s", libusb_error_name(r));
return r;
}
aesdev = g_malloc0(sizeof(struct aesX660_dev));
fpi_imgdev_set_user_data(dev, aesdev);
fp_dev_set_instance_data(FP_DEV(dev), aesdev);
aesdev->buffer = g_malloc0(AES1660_FRAME_SIZE + AESX660_HEADER_SIZE);
aesdev->init_seqs[0] = aes1660_init_1;
aesdev->init_seqs_len[0] = G_N_ELEMENTS(aes1660_init_1);
@@ -64,10 +64,10 @@ static int dev_init(struct fp_img_dev *dev, unsigned long driver_data)
static void dev_deinit(struct fp_img_dev *dev)
{
struct aesX660_dev *aesdev = fpi_imgdev_get_user_data(dev);
struct aesX660_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev));
g_free(aesdev->buffer);
g_free(aesdev);
libusb_release_interface(fpi_imgdev_get_usb_dev(dev), 0);
libusb_release_interface(fpi_dev_get_usb_dev(FP_DEV(dev)), 0);
fpi_imgdev_close_complete(dev);
}

View File

@@ -36,6 +36,11 @@ static void complete_deactivation(struct fp_img_dev *dev);
#define BULK_TIMEOUT 4000
#define FINGER_DETECTION_LEN 20
#define READ_REGS_LEN 126
#define READ_REGS_RESP_LEN 159
#define STRIP_CAPTURE_LEN 1705
/*
* The AES2501 is an imaging device using a swipe-type sensor. It samples
* the finger at preprogrammed intervals, sending a 192x16 frame to the
@@ -83,9 +88,12 @@ struct aes2501_read_regs {
void *user_data;
};
static void read_regs_data_cb(struct libusb_transfer *transfer)
static void read_regs_data_cb(struct libusb_transfer *transfer,
struct fp_dev *dev,
fpi_ssm *ssm,
void *user_data)
{
struct aes2501_read_regs *rdata = transfer->user_data;
struct aes2501_read_regs *rdata = user_data;
unsigned char *retdata = NULL;
int r;
@@ -100,14 +108,12 @@ static void read_regs_data_cb(struct libusb_transfer *transfer)
rdata->callback(rdata->dev, r, retdata, rdata->user_data);
g_free(rdata);
g_free(transfer->buffer);
libusb_free_transfer(transfer);
}
static void read_regs_rq_cb(struct fp_img_dev *dev, int result, void *user_data)
{
struct aes2501_read_regs *rdata = user_data;
struct libusb_transfer *transfer;
fpi_usb_transfer *transfer;
unsigned char *data;
int r;
@@ -115,20 +121,18 @@ static void read_regs_rq_cb(struct fp_img_dev *dev, int result, void *user_data)
if (result != 0)
goto err;
transfer = libusb_alloc_transfer(0);
if (!transfer) {
result = -ENOMEM;
goto err;
}
data = g_malloc(READ_REGS_LEN);
transfer = fpi_usb_fill_bulk_transfer(FP_DEV(dev),
NULL,
EP_IN,
data,
READ_REGS_LEN,
read_regs_data_cb,
rdata,
BULK_TIMEOUT);
data = g_malloc(126);
libusb_fill_bulk_transfer(transfer, fpi_imgdev_get_usb_dev(dev), EP_IN, data, 126,
read_regs_data_cb, rdata, BULK_TIMEOUT);
r = libusb_submit_transfer(transfer);
r = fpi_usb_submit_transfer(transfer);
if (r < 0) {
g_free(data);
libusb_free_transfer(transfer);
result = -EIO;
goto err;
}
@@ -180,53 +184,48 @@ static int regval_from_dump(unsigned char *data, uint8_t target)
static void generic_write_regv_cb(struct fp_img_dev *dev, int result,
void *user_data)
{
struct fpi_ssm *ssm = user_data;
fpi_ssm *ssm = user_data;
if (result == 0)
fpi_ssm_next_state(ssm);
else
fpi_ssm_mark_aborted(ssm, result);
fpi_ssm_mark_failed(ssm, result);
}
/* check that read succeeded but ignore all data */
static void generic_ignore_data_cb(struct libusb_transfer *transfer)
static void generic_ignore_data_cb(struct libusb_transfer *transfer,
struct fp_dev *dev,
fpi_ssm *ssm,
void *user_data)
{
struct fpi_ssm *ssm = transfer->user_data;
if (transfer->status != LIBUSB_TRANSFER_COMPLETED)
fpi_ssm_mark_aborted(ssm, -EIO);
fpi_ssm_mark_failed(ssm, -EIO);
else if (transfer->length != transfer->actual_length)
fpi_ssm_mark_aborted(ssm, -EPROTO);
fpi_ssm_mark_failed(ssm, -EPROTO);
else
fpi_ssm_next_state(ssm);
g_free(transfer->buffer);
libusb_free_transfer(transfer);
}
/* read the specified number of bytes from the IN endpoint but throw them
* away, then increment the SSM */
static void generic_read_ignore_data(struct fpi_ssm *ssm, size_t bytes)
static void generic_read_ignore_data(fpi_ssm *ssm, struct fp_dev *dev, size_t bytes)
{
struct libusb_transfer *transfer = libusb_alloc_transfer(0);
fpi_usb_transfer *transfer;
unsigned char *data;
struct fp_dev *dev = fpi_ssm_get_dev(ssm);
int r;
if (!transfer) {
fpi_ssm_mark_aborted(ssm, -ENOMEM);
return;
}
data = g_malloc(bytes);
libusb_fill_bulk_transfer(transfer, fpi_dev_get_usb_dev(dev), EP_IN, data, bytes,
generic_ignore_data_cb, ssm, BULK_TIMEOUT);
transfer = fpi_usb_fill_bulk_transfer(dev,
ssm,
EP_IN,
data,
bytes,
generic_ignore_data_cb,
NULL,
BULK_TIMEOUT);
r = libusb_submit_transfer(transfer);
if (r < 0) {
g_free(data);
libusb_free_transfer(transfer);
fpi_ssm_mark_aborted(ssm, r);
}
r = fpi_usb_submit_transfer(transfer);
if (r < 0)
fpi_ssm_mark_failed(ssm, r);
}
/****** IMAGE PROCESSING ******/
@@ -282,19 +281,22 @@ static const struct aes_regwrite finger_det_reqs[] = {
static void start_finger_detection(struct fp_img_dev *dev);
static void finger_det_data_cb(struct libusb_transfer *transfer)
static void finger_det_data_cb(struct libusb_transfer *transfer,
struct fp_dev *_dev,
fpi_ssm *ssm,
void *user_data)
{
struct fp_img_dev *dev = transfer->user_data;
struct fp_img_dev *dev = FP_IMG_DEV(_dev);
unsigned char *data = transfer->buffer;
int i;
int sum = 0;
if (transfer->status != LIBUSB_TRANSFER_COMPLETED) {
fpi_imgdev_session_error(dev, -EIO);
goto out;
return;
} else if (transfer->length != transfer->actual_length) {
fpi_imgdev_session_error(dev, -EPROTO);
goto out;
return;
}
/* examine histogram to determine finger presence */
@@ -308,16 +310,12 @@ static void finger_det_data_cb(struct libusb_transfer *transfer)
/* no finger, poll for a new histogram */
start_finger_detection(dev);
}
out:
g_free(data);
libusb_free_transfer(transfer);
}
static void finger_det_reqs_cb(struct fp_img_dev *dev, int result,
void *user_data)
{
struct libusb_transfer *transfer;
fpi_usb_transfer *transfer;
unsigned char *data;
int r;
@@ -326,27 +324,24 @@ static void finger_det_reqs_cb(struct fp_img_dev *dev, int result,
return;
}
transfer = libusb_alloc_transfer(0);
if (!transfer) {
fpi_imgdev_session_error(dev, -ENOMEM);
return;
}
data = g_malloc(FINGER_DETECTION_LEN);
transfer = fpi_usb_fill_bulk_transfer(FP_DEV(dev),
NULL,
EP_IN,
data,
FINGER_DETECTION_LEN,
finger_det_data_cb,
NULL,
BULK_TIMEOUT);
data = g_malloc(20);
libusb_fill_bulk_transfer(transfer, fpi_imgdev_get_usb_dev(dev), EP_IN, data, 20,
finger_det_data_cb, dev, BULK_TIMEOUT);
r = libusb_submit_transfer(transfer);
if (r < 0) {
g_free(data);
libusb_free_transfer(transfer);
r = fpi_usb_submit_transfer(transfer);
if (r < 0)
fpi_imgdev_session_error(dev, r);
}
}
static void start_finger_detection(struct fp_img_dev *dev)
{
struct aes2501_dev *aesdev = fpi_imgdev_get_user_data(dev);
struct aes2501_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev));
G_DEBUG_HERE();
if (aesdev->deactivating) {
@@ -433,35 +428,37 @@ enum capture_states {
CAPTURE_NUM_STATES,
};
static void capture_read_strip_cb(struct libusb_transfer *transfer)
static void capture_read_strip_cb(struct libusb_transfer *transfer,
struct fp_dev *_dev,
fpi_ssm *ssm,
void *user_data)
{
unsigned char *stripdata;
struct fpi_ssm *ssm = transfer->user_data;
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct aes2501_dev *aesdev = fpi_imgdev_get_user_data(dev);
struct fp_img_dev *dev = FP_IMG_DEV(_dev);
struct aes2501_dev *aesdev = FP_INSTANCE_DATA(_dev);
unsigned char *data = transfer->buffer;
int sum;
int threshold;
if (transfer->status != LIBUSB_TRANSFER_COMPLETED) {
fpi_ssm_mark_aborted(ssm, -EIO);
goto out;
fpi_ssm_mark_failed(ssm, -EIO);
return;
} else if (transfer->length != transfer->actual_length) {
fpi_ssm_mark_aborted(ssm, -EPROTO);
goto out;
fpi_ssm_mark_failed(ssm, -EPROTO);
return;
}
threshold = regval_from_dump(data + 1 + 192*8 + 1 + 16*2 + 1 + 8,
AES2501_REG_DATFMT);
if (threshold < 0) {
fpi_ssm_mark_aborted(ssm, threshold);
goto out;
fpi_ssm_mark_failed(ssm, threshold);
return;
}
sum = sum_histogram_values(data + 1 + 192*8, threshold & 0x0f);
if (sum < 0) {
fpi_ssm_mark_aborted(ssm, sum);
goto out;
fpi_ssm_mark_failed(ssm, sum);
return;
}
fp_dbg("sum=%d", sum);
@@ -514,16 +511,12 @@ static void capture_read_strip_cb(struct libusb_transfer *transfer)
fpi_ssm_jump_to_state(ssm, CAPTURE_REQUEST_STRIP);
}
out:
g_free(data);
libusb_free_transfer(transfer);
}
static void capture_run_state(struct fpi_ssm *ssm)
static void capture_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
{
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct aes2501_dev *aesdev = fpi_imgdev_get_user_data(dev);
struct fp_img_dev *dev = user_data;
struct aes2501_dev *aesdev = FP_INSTANCE_DATA(_dev);
int r;
switch (fpi_ssm_get_cur_state(ssm)) {
@@ -532,14 +525,14 @@ static void capture_run_state(struct fpi_ssm *ssm)
generic_write_regv_cb, ssm);
break;
case CAPTURE_READ_DATA_1:
generic_read_ignore_data(ssm, 159);
generic_read_ignore_data(ssm, _dev, READ_REGS_RESP_LEN);
break;
case CAPTURE_WRITE_REQS_2:
aes_write_regv(dev, capture_reqs_2, G_N_ELEMENTS(capture_reqs_2),
generic_write_regv_cb, ssm);
break;
case CAPTURE_READ_DATA_2:
generic_read_ignore_data(ssm, 159);
generic_read_ignore_data(ssm, _dev, READ_REGS_RESP_LEN);
break;
case CAPTURE_REQUEST_STRIP:
if (aesdev->deactivating)
@@ -549,32 +542,30 @@ static void capture_run_state(struct fpi_ssm *ssm)
generic_write_regv_cb, ssm);
break;
case CAPTURE_READ_STRIP: ;
struct libusb_transfer *transfer = libusb_alloc_transfer(0);
fpi_usb_transfer *transfer;
unsigned char *data;
if (!transfer) {
fpi_ssm_mark_aborted(ssm, -ENOMEM);
break;
}
data = g_malloc(STRIP_CAPTURE_LEN);
transfer = fpi_usb_fill_bulk_transfer(FP_DEV(dev),
ssm,
EP_IN,
data,
STRIP_CAPTURE_LEN,
capture_read_strip_cb,
NULL,
BULK_TIMEOUT);
data = g_malloc(1705);
libusb_fill_bulk_transfer(transfer, fpi_imgdev_get_usb_dev(dev), EP_IN, data, 1705,
capture_read_strip_cb, ssm, BULK_TIMEOUT);
r = libusb_submit_transfer(transfer);
if (r < 0) {
g_free(data);
libusb_free_transfer(transfer);
fpi_ssm_mark_aborted(ssm, r);
}
r = fpi_usb_submit_transfer(transfer);
if (r < 0)
fpi_ssm_mark_failed(ssm, r);
break;
};
}
static void capture_sm_complete(struct fpi_ssm *ssm)
static void capture_sm_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
{
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct aes2501_dev *aesdev = fpi_imgdev_get_user_data(dev);
struct fp_img_dev *dev = user_data;
struct aes2501_dev *aesdev = FP_INSTANCE_DATA(_dev);
G_DEBUG_HERE();
if (aesdev->deactivating)
@@ -588,8 +579,8 @@ static void capture_sm_complete(struct fpi_ssm *ssm)
static void start_capture(struct fp_img_dev *dev)
{
struct aes2501_dev *aesdev = fpi_imgdev_get_user_data(dev);
struct fpi_ssm *ssm;
struct aes2501_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev));
fpi_ssm *ssm;
if (aesdev->deactivating) {
complete_deactivation(dev);
@@ -599,9 +590,8 @@ static void start_capture(struct fp_img_dev *dev)
aesdev->no_finger_cnt = 0;
/* Reset gain */
strip_scan_reqs[4].value = AES2501_ADREFHI_MAX_VALUE;
ssm = fpi_ssm_new(fpi_imgdev_get_dev(dev), capture_run_state, CAPTURE_NUM_STATES);
ssm = fpi_ssm_new(FP_DEV(dev), capture_run_state, CAPTURE_NUM_STATES, dev);
G_DEBUG_HERE();
fpi_ssm_set_user_data(ssm, dev);
fpi_ssm_start(ssm, capture_sm_complete);
}
@@ -713,11 +703,11 @@ enum activate_states {
void activate_read_regs_cb(struct fp_img_dev *dev, int status,
unsigned char *regs, void *user_data)
{
struct fpi_ssm *ssm = user_data;
struct aes2501_dev *aesdev = fpi_imgdev_get_user_data(dev);
fpi_ssm *ssm = user_data;
struct aes2501_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev));
if (status != 0) {
fpi_ssm_mark_aborted(ssm, status);
fpi_ssm_mark_failed(ssm, status);
} else {
fp_dbg("reg 0xaf = %x", regs[0x5f]);
if (regs[0x5f] != 0x6b || ++aesdev->read_regs_retry_count == 13)
@@ -730,16 +720,16 @@ void activate_read_regs_cb(struct fp_img_dev *dev, int status,
static void activate_init3_cb(struct fp_img_dev *dev, int result,
void *user_data)
{
struct fpi_ssm *ssm = user_data;
fpi_ssm *ssm = user_data;
if (result == 0)
fpi_ssm_jump_to_state(ssm, READ_REGS);
else
fpi_ssm_mark_aborted(ssm, result);
fpi_ssm_mark_failed(ssm, result);
}
static void activate_run_state(struct fpi_ssm *ssm)
static void activate_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
{
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct fp_img_dev *dev = user_data;
/* This state machine isn't as linear as it may appear. After doing init1
* and init2 register configuration writes, we have to poll a register
@@ -767,7 +757,7 @@ static void activate_run_state(struct fpi_ssm *ssm)
break;
case READ_DATA_1:
fp_dbg("read data 1");
generic_read_ignore_data(ssm, 20);
generic_read_ignore_data(ssm, _dev, FINGER_DETECTION_LEN);
break;
case WRITE_INIT_2:
aes_write_regv(dev, init_2, G_N_ELEMENTS(init_2),
@@ -791,9 +781,9 @@ static void activate_run_state(struct fpi_ssm *ssm)
}
}
static void activate_sm_complete(struct fpi_ssm *ssm)
static void activate_sm_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
{
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct fp_img_dev *dev = user_data;
fp_dbg("status %d", fpi_ssm_get_error(ssm));
fpi_imgdev_activate_complete(dev, fpi_ssm_get_error(ssm));
@@ -802,12 +792,11 @@ static void activate_sm_complete(struct fpi_ssm *ssm)
fpi_ssm_free(ssm);
}
static int dev_activate(struct fp_img_dev *dev, enum fp_imgdev_state state)
static int dev_activate(struct fp_img_dev *dev)
{
struct aes2501_dev *aesdev = fpi_imgdev_get_user_data(dev);
struct fpi_ssm *ssm = fpi_ssm_new(fpi_imgdev_get_dev(dev), activate_run_state,
ACTIVATE_NUM_STATES);
fpi_ssm_set_user_data(ssm, dev);
struct aes2501_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev));
fpi_ssm *ssm = fpi_ssm_new(FP_DEV(dev), activate_run_state,
ACTIVATE_NUM_STATES, dev);
aesdev->read_regs_retry_count = 0;
fpi_ssm_start(ssm, activate_sm_complete);
return 0;
@@ -815,7 +804,7 @@ static int dev_activate(struct fp_img_dev *dev, enum fp_imgdev_state state)
static void dev_deactivate(struct fp_img_dev *dev)
{
struct aes2501_dev *aesdev = fpi_imgdev_get_user_data(dev);
struct aes2501_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev));
/* FIXME: audit cancellation points, probably need more, specifically
* in error handling paths? */
aesdev->deactivating = TRUE;
@@ -823,7 +812,7 @@ static void dev_deactivate(struct fp_img_dev *dev)
static void complete_deactivation(struct fp_img_dev *dev)
{
struct aes2501_dev *aesdev = fpi_imgdev_get_user_data(dev);
struct aes2501_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev));
G_DEBUG_HERE();
/* FIXME: if we're in the middle of a scan, we should cancel the scan.
@@ -842,23 +831,23 @@ static int dev_init(struct fp_img_dev *dev, unsigned long driver_data)
int r;
struct aes2501_dev *aesdev;
r = libusb_claim_interface(fpi_imgdev_get_usb_dev(dev), 0);
r = libusb_claim_interface(fpi_dev_get_usb_dev(FP_DEV(dev)), 0);
if (r < 0) {
fp_err("could not claim interface 0: %s", libusb_error_name(r));
return r;
}
aesdev = g_malloc0(sizeof(struct aes2501_dev));
fpi_imgdev_set_user_data(dev, aesdev);
fp_dev_set_instance_data(FP_DEV(dev), aesdev);
fpi_imgdev_open_complete(dev, 0);
return 0;
}
static void dev_deinit(struct fp_img_dev *dev)
{
struct aes2501_dev *aesdev = fpi_imgdev_get_user_data(dev);
struct aes2501_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev));
g_free(aesdev);
libusb_release_interface(fpi_imgdev_get_usb_dev(dev), 0);
libusb_release_interface(fpi_dev_get_usb_dev(FP_DEV(dev)), 0);
fpi_imgdev_close_complete(dev);
}

View File

@@ -125,15 +125,10 @@ static void finger_det_reqs_cb(struct libusb_transfer *t)
goto exit_free_transfer;
}
transfer = libusb_alloc_transfer(0);
if (!transfer) {
fpi_imgdev_session_error(dev, -ENOMEM);
goto exit_free_transfer;
}
transfer = fpi_usb_alloc();
/* 2 bytes of result */
data = g_malloc(AES2550_EP_IN_BUF_SIZE);
libusb_fill_bulk_transfer(transfer, fpi_imgdev_get_usb_dev(dev), EP_IN, data, AES2550_EP_IN_BUF_SIZE,
libusb_fill_bulk_transfer(transfer, fpi_dev_get_usb_dev(FP_DEV(dev)), EP_IN, data, AES2550_EP_IN_BUF_SIZE,
finger_det_data_cb, dev, BULK_TIMEOUT);
r = libusb_submit_transfer(transfer);
@@ -149,7 +144,7 @@ exit_free_transfer:
static void start_finger_detection(struct fp_img_dev *dev)
{
int r;
struct aes2550_dev *aesdev = fpi_imgdev_get_user_data(dev);
struct aes2550_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev));
struct libusb_transfer *transfer;
G_DEBUG_HERE();
@@ -158,12 +153,8 @@ static void start_finger_detection(struct fp_img_dev *dev)
return;
}
transfer = libusb_alloc_transfer(0);
if (!transfer) {
fpi_imgdev_session_error(dev, -ENOMEM);
return;
}
libusb_fill_bulk_transfer(transfer, fpi_imgdev_get_usb_dev(dev), EP_OUT, finger_det_reqs,
transfer = fpi_usb_alloc();
libusb_fill_bulk_transfer(transfer, fpi_dev_get_usb_dev(FP_DEV(dev)), EP_OUT, finger_det_reqs,
sizeof(finger_det_reqs), finger_det_reqs_cb, dev, BULK_TIMEOUT);
r = libusb_submit_transfer(transfer);
if (r < 0) {
@@ -200,11 +191,10 @@ enum capture_states {
};
/* Returns number of processed bytes */
static int process_strip_data(struct fpi_ssm *ssm, unsigned char *data)
static int process_strip_data(fpi_ssm *ssm, struct fp_img_dev *dev, unsigned char *data)
{
unsigned char *stripdata;
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct aes2550_dev *aesdev = fpi_imgdev_get_user_data(dev);
struct aes2550_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev));
struct fpi_frame *stripe;
int len;
@@ -231,22 +221,22 @@ static int process_strip_data(struct fpi_ssm *ssm, unsigned char *data)
static void capture_reqs_cb(struct libusb_transfer *transfer)
{
struct fpi_ssm *ssm = transfer->user_data;
fpi_ssm *ssm = transfer->user_data;
if ((transfer->status == LIBUSB_TRANSFER_COMPLETED) &&
(transfer->length == transfer->actual_length)) {
fpi_ssm_next_state(ssm);
} else {
fpi_ssm_mark_aborted(ssm, -EIO);
fpi_ssm_mark_failed(ssm, -EIO);
}
libusb_free_transfer(transfer);
}
static void capture_set_idle_reqs_cb(struct libusb_transfer *transfer)
{
struct fpi_ssm *ssm = transfer->user_data;
fpi_ssm *ssm = transfer->user_data;
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct aes2550_dev *aesdev = fpi_imgdev_get_user_data(dev);
struct aes2550_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev));
if ((transfer->status == LIBUSB_TRANSFER_COMPLETED) &&
(transfer->length == transfer->actual_length) &&
@@ -265,22 +255,22 @@ static void capture_set_idle_reqs_cb(struct libusb_transfer *transfer)
/* marking machine complete will re-trigger finger detection loop */
fpi_ssm_mark_completed(ssm);
} else {
fpi_ssm_mark_aborted(ssm, -EIO);
fpi_ssm_mark_failed(ssm, -EIO);
}
libusb_free_transfer(transfer);
}
static void capture_read_data_cb(struct libusb_transfer *transfer)
{
struct fpi_ssm *ssm = transfer->user_data;
fpi_ssm *ssm = transfer->user_data;
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct aes2550_dev *aesdev = fpi_imgdev_get_user_data(dev);
struct aes2550_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev));
unsigned char *data = transfer->buffer;
int r;
if (transfer->status != LIBUSB_TRANSFER_COMPLETED) {
fp_dbg("request is not completed, %d", transfer->status);
fpi_ssm_mark_aborted(ssm, -EIO);
fpi_ssm_mark_failed(ssm, -EIO);
goto out;
}
@@ -290,10 +280,10 @@ static void capture_read_data_cb(struct libusb_transfer *transfer)
switch (transfer->actual_length) {
case AES2550_STRIP_SIZE:
r = process_strip_data(ssm, data);
r = process_strip_data(ssm, dev, data);
if (r < 0) {
fp_dbg("Processing strip data failed: %d", r);
fpi_ssm_mark_aborted(ssm, -EPROTO);
fpi_ssm_mark_failed(ssm, -EPROTO);
goto out;
}
aesdev->heartbeat_cnt = 0;
@@ -323,73 +313,62 @@ out:
libusb_free_transfer(transfer);
}
static void capture_run_state(struct fpi_ssm *ssm)
static void capture_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
{
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct fp_img_dev *dev = user_data;
int r;
switch (fpi_ssm_get_cur_state(ssm)) {
case CAPTURE_WRITE_REQS:
{
struct libusb_transfer *transfer = libusb_alloc_transfer(0);
if (!transfer) {
fpi_ssm_mark_aborted(ssm, -ENOMEM);
return;
}
libusb_fill_bulk_transfer(transfer, fpi_imgdev_get_usb_dev(dev), EP_OUT, capture_reqs,
struct libusb_transfer *transfer = fpi_usb_alloc();
libusb_fill_bulk_transfer(transfer, fpi_dev_get_usb_dev(FP_DEV(dev)), EP_OUT, capture_reqs,
sizeof(capture_reqs), capture_reqs_cb, ssm, BULK_TIMEOUT);
r = libusb_submit_transfer(transfer);
if (r < 0) {
libusb_free_transfer(transfer);
fpi_ssm_mark_aborted(ssm, -ENOMEM);
fpi_ssm_mark_failed(ssm, -ENOMEM);
}
}
break;
case CAPTURE_READ_DATA:
{
struct libusb_transfer *transfer = libusb_alloc_transfer(0);
struct libusb_transfer *transfer = fpi_usb_alloc();
unsigned char *data;
if (!transfer) {
fpi_ssm_mark_aborted(ssm, -ENOMEM);
break;
}
data = g_malloc(AES2550_EP_IN_BUF_SIZE);
libusb_fill_bulk_transfer(transfer, fpi_imgdev_get_usb_dev(dev), EP_IN, data, AES2550_EP_IN_BUF_SIZE,
libusb_fill_bulk_transfer(transfer, fpi_dev_get_usb_dev(FP_DEV(dev)), EP_IN, data, AES2550_EP_IN_BUF_SIZE,
capture_read_data_cb, ssm, BULK_TIMEOUT);
r = libusb_submit_transfer(transfer);
if (r < 0) {
g_free(data);
libusb_free_transfer(transfer);
fpi_ssm_mark_aborted(ssm, r);
fpi_ssm_mark_failed(ssm, r);
}
}
break;
case CAPTURE_SET_IDLE:
{
struct libusb_transfer *transfer = libusb_alloc_transfer(0);
if (!transfer) {
fpi_ssm_mark_aborted(ssm, -ENOMEM);
return;
}
libusb_fill_bulk_transfer(transfer, fpi_imgdev_get_usb_dev(dev), EP_OUT, capture_set_idle_reqs,
struct libusb_transfer *transfer = fpi_usb_alloc();
libusb_fill_bulk_transfer(transfer, fpi_dev_get_usb_dev(FP_DEV(dev)), EP_OUT, capture_set_idle_reqs,
sizeof(capture_set_idle_reqs), capture_set_idle_reqs_cb, ssm, BULK_TIMEOUT);
r = libusb_submit_transfer(transfer);
if (r < 0) {
libusb_free_transfer(transfer);
fpi_ssm_mark_aborted(ssm, -ENOMEM);
fpi_ssm_mark_failed(ssm, -ENOMEM);
}
}
break;
};
}
static void capture_sm_complete(struct fpi_ssm *ssm)
static void capture_sm_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
{
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct aes2550_dev *aesdev = fpi_imgdev_get_user_data(dev);
struct fp_img_dev *dev = user_data;
struct aes2550_dev *aesdev = FP_INSTANCE_DATA(_dev);
fp_dbg("Capture completed");
if (aesdev->deactivating)
@@ -403,8 +382,8 @@ static void capture_sm_complete(struct fpi_ssm *ssm)
static void start_capture(struct fp_img_dev *dev)
{
struct aes2550_dev *aesdev = fpi_imgdev_get_user_data(dev);
struct fpi_ssm *ssm;
struct aes2550_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev));
fpi_ssm *ssm;
if (aesdev->deactivating) {
complete_deactivation(dev);
@@ -412,9 +391,8 @@ static void start_capture(struct fp_img_dev *dev)
}
aesdev->heartbeat_cnt = 0;
ssm = fpi_ssm_new(fpi_imgdev_get_dev(dev), capture_run_state, CAPTURE_NUM_STATES);
ssm = fpi_ssm_new(FP_DEV(dev), capture_run_state, CAPTURE_NUM_STATES, dev);
G_DEBUG_HERE();
fpi_ssm_set_user_data(ssm, dev);
fpi_ssm_start(ssm, capture_sm_complete);
}
@@ -444,25 +422,25 @@ enum activate_states {
static void init_reqs_cb(struct libusb_transfer *transfer)
{
struct fpi_ssm *ssm = transfer->user_data;
fpi_ssm *ssm = transfer->user_data;
if ((transfer->status == LIBUSB_TRANSFER_COMPLETED) &&
(transfer->length == transfer->actual_length)) {
fpi_ssm_next_state(ssm);
} else {
fpi_ssm_mark_aborted(ssm, -EIO);
fpi_ssm_mark_failed(ssm, -EIO);
}
libusb_free_transfer(transfer);
}
static void init_read_data_cb(struct libusb_transfer *transfer)
{
struct fpi_ssm *ssm = transfer->user_data;
fpi_ssm *ssm = transfer->user_data;
if (transfer->status == LIBUSB_TRANSFER_COMPLETED) {
fpi_ssm_next_state(ssm);
} else {
fpi_ssm_mark_aborted(ssm, -EIO);
fpi_ssm_mark_failed(ssm, -EIO);
}
g_free(transfer->buffer);
libusb_free_transfer(transfer);
@@ -472,105 +450,89 @@ static void init_read_data_cb(struct libusb_transfer *transfer)
* need more info for implementaion */
static void calibrate_read_data_cb(struct libusb_transfer *transfer)
{
struct fpi_ssm *ssm = transfer->user_data;
fpi_ssm *ssm = transfer->user_data;
if (transfer->status == LIBUSB_TRANSFER_COMPLETED) {
fpi_ssm_next_state(ssm);
} else {
fpi_ssm_mark_aborted(ssm, -EIO);
fpi_ssm_mark_failed(ssm, -EIO);
}
g_free(transfer->buffer);
libusb_free_transfer(transfer);
}
static void activate_run_state(struct fpi_ssm *ssm)
static void activate_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
{
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct fp_img_dev *dev = user_data;
int r;
switch (fpi_ssm_get_cur_state(ssm)) {
case WRITE_INIT:
{
struct libusb_transfer *transfer = libusb_alloc_transfer(0);
if (!transfer) {
fpi_ssm_mark_aborted(ssm, -ENOMEM);
return;
}
libusb_fill_bulk_transfer(transfer, fpi_imgdev_get_usb_dev(dev), EP_OUT, init_reqs,
struct libusb_transfer *transfer = fpi_usb_alloc();
libusb_fill_bulk_transfer(transfer, fpi_dev_get_usb_dev(FP_DEV(dev)), EP_OUT, init_reqs,
sizeof(init_reqs), init_reqs_cb, ssm, BULK_TIMEOUT);
r = libusb_submit_transfer(transfer);
if (r < 0) {
libusb_free_transfer(transfer);
fpi_ssm_mark_aborted(ssm, -ENOMEM);
fpi_ssm_mark_failed(ssm, -ENOMEM);
}
}
break;
case READ_DATA:
{
struct libusb_transfer *transfer = libusb_alloc_transfer(0);
struct libusb_transfer *transfer = fpi_usb_alloc();
unsigned char *data;
if (!transfer) {
fpi_ssm_mark_aborted(ssm, -ENOMEM);
break;
}
data = g_malloc(AES2550_EP_IN_BUF_SIZE);
libusb_fill_bulk_transfer(transfer, fpi_imgdev_get_usb_dev(dev), EP_IN, data, AES2550_EP_IN_BUF_SIZE,
libusb_fill_bulk_transfer(transfer, fpi_dev_get_usb_dev(FP_DEV(dev)), EP_IN, data, AES2550_EP_IN_BUF_SIZE,
init_read_data_cb, ssm, BULK_TIMEOUT);
r = libusb_submit_transfer(transfer);
if (r < 0) {
g_free(data);
libusb_free_transfer(transfer);
fpi_ssm_mark_aborted(ssm, r);
fpi_ssm_mark_failed(ssm, r);
}
}
break;
case CALIBRATE:
{
struct libusb_transfer *transfer = libusb_alloc_transfer(0);
if (!transfer) {
fpi_ssm_mark_aborted(ssm, -ENOMEM);
return;
}
libusb_fill_bulk_transfer(transfer, fpi_imgdev_get_usb_dev(dev), EP_OUT, calibrate_reqs,
struct libusb_transfer *transfer = fpi_usb_alloc();
libusb_fill_bulk_transfer(transfer, fpi_dev_get_usb_dev(FP_DEV(dev)), EP_OUT, calibrate_reqs,
sizeof(calibrate_reqs), init_reqs_cb, ssm, BULK_TIMEOUT);
r = libusb_submit_transfer(transfer);
if (r < 0) {
libusb_free_transfer(transfer);
fpi_ssm_mark_aborted(ssm, -ENOMEM);
fpi_ssm_mark_failed(ssm, -ENOMEM);
}
}
break;
case READ_CALIB_TABLE:
{
struct libusb_transfer *transfer = libusb_alloc_transfer(0);
struct libusb_transfer *transfer = fpi_usb_alloc();
unsigned char *data;
if (!transfer) {
fpi_ssm_mark_aborted(ssm, -ENOMEM);
break;
}
data = g_malloc(AES2550_EP_IN_BUF_SIZE);
libusb_fill_bulk_transfer(transfer, fpi_imgdev_get_usb_dev(dev), EP_IN, data, AES2550_EP_IN_BUF_SIZE,
libusb_fill_bulk_transfer(transfer, fpi_dev_get_usb_dev(FP_DEV(dev)), EP_IN, data, AES2550_EP_IN_BUF_SIZE,
calibrate_read_data_cb, ssm, BULK_TIMEOUT);
r = libusb_submit_transfer(transfer);
if (r < 0) {
g_free(data);
libusb_free_transfer(transfer);
fpi_ssm_mark_aborted(ssm, r);
fpi_ssm_mark_failed(ssm, r);
}
}
break;
}
}
static void activate_sm_complete(struct fpi_ssm *ssm)
static void activate_sm_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
{
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct fp_img_dev *dev = user_data;
fp_dbg("status %d", fpi_ssm_get_error(ssm));
fpi_imgdev_activate_complete(dev, fpi_ssm_get_error(ssm));
@@ -579,25 +541,24 @@ static void activate_sm_complete(struct fpi_ssm *ssm)
fpi_ssm_free(ssm);
}
static int dev_activate(struct fp_img_dev *dev, enum fp_imgdev_state state)
static int dev_activate(struct fp_img_dev *dev)
{
struct fpi_ssm *ssm = fpi_ssm_new(fpi_imgdev_get_dev(dev), activate_run_state,
ACTIVATE_NUM_STATES);
fpi_ssm_set_user_data(ssm, dev);
fpi_ssm *ssm = fpi_ssm_new(FP_DEV(dev), activate_run_state,
ACTIVATE_NUM_STATES, dev);
fpi_ssm_start(ssm, activate_sm_complete);
return 0;
}
static void dev_deactivate(struct fp_img_dev *dev)
{
struct aes2550_dev *aesdev = fpi_imgdev_get_user_data(dev);
struct aes2550_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev));
aesdev->deactivating = TRUE;
}
static void complete_deactivation(struct fp_img_dev *dev)
{
struct aes2550_dev *aesdev = fpi_imgdev_get_user_data(dev);
struct aes2550_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev));
G_DEBUG_HERE();
aesdev->deactivating = FALSE;
@@ -613,14 +574,14 @@ static int dev_init(struct fp_img_dev *dev, unsigned long driver_data)
int r;
struct aes2550_dev *aes2550_dev;
r = libusb_claim_interface(fpi_imgdev_get_usb_dev(dev), 0);
r = libusb_claim_interface(fpi_dev_get_usb_dev(FP_DEV(dev)), 0);
if (r < 0) {
fp_err("could not claim interface 0: %s", libusb_error_name(r));
return r;
}
aes2550_dev = g_malloc0(sizeof(struct aes2550_dev));
fpi_imgdev_set_user_data(dev, aes2550_dev);
fp_dev_set_instance_data(FP_DEV(dev), aes2550_dev);
fpi_imgdev_open_complete(dev, 0);
return 0;
}
@@ -628,9 +589,9 @@ static int dev_init(struct fp_img_dev *dev, unsigned long driver_data)
static void dev_deinit(struct fp_img_dev *dev)
{
struct aes2550_dev *aesdev;
aesdev = fpi_imgdev_get_user_data(dev);
aesdev = FP_INSTANCE_DATA(FP_DEV(dev));
g_free(aesdev);
libusb_release_interface(fpi_imgdev_get_usb_dev(dev), 0);
libusb_release_interface(fpi_dev_get_usb_dev(FP_DEV(dev)), 0);
fpi_imgdev_close_complete(dev);
}

View File

@@ -40,14 +40,14 @@ static int dev_init(struct fp_img_dev *dev, unsigned long driver_data)
int r;
struct aesX660_dev *aesdev;
r = libusb_claim_interface(fpi_imgdev_get_usb_dev(dev), 0);
r = libusb_claim_interface(fpi_dev_get_usb_dev(FP_DEV(dev)), 0);
if (r < 0) {
fp_err("could not claim interface 0: %s", libusb_error_name(r));
return r;
}
aesdev = g_malloc0(sizeof(struct aesX660_dev));
fpi_imgdev_set_user_data(dev, aesdev);
fp_dev_set_instance_data(FP_DEV(dev), aesdev);
aesdev->buffer = g_malloc0(AES2660_FRAME_SIZE + AESX660_HEADER_SIZE);
/* No scaling for AES2660 */
aesdev->init_seqs[0] = aes2660_init_1;
@@ -66,10 +66,10 @@ static int dev_init(struct fp_img_dev *dev, unsigned long driver_data)
static void dev_deinit(struct fp_img_dev *dev)
{
struct aesX660_dev *aesdev;
aesdev = fpi_imgdev_get_user_data(dev);
aesdev = FP_INSTANCE_DATA(FP_DEV(dev));
g_free(aesdev->buffer);
g_free(aesdev);
libusb_release_interface(fpi_imgdev_get_usb_dev(dev), 0);
libusb_release_interface(fpi_dev_get_usb_dev(FP_DEV(dev)), 0);
fpi_imgdev_close_complete(dev);
}

View File

@@ -122,14 +122,14 @@ static int dev_init(struct fp_img_dev *dev, unsigned long driver_data)
int r;
struct aes3k_dev *aesdev;
r = libusb_claim_interface(fpi_imgdev_get_usb_dev(dev), 0);
r = libusb_claim_interface(fpi_dev_get_usb_dev(FP_DEV(dev)), 0);
if (r < 0) {
fp_err("could not claim interface 0: %s", libusb_error_name(r));
return r;
}
aesdev = g_malloc0(sizeof(struct aes3k_dev));
fpi_imgdev_set_user_data(dev, aesdev);
fp_dev_set_instance_data(FP_DEV(dev), aesdev);
if (!aesdev)
return -ENOMEM;
@@ -148,9 +148,9 @@ static int dev_init(struct fp_img_dev *dev, unsigned long driver_data)
static void dev_deinit(struct fp_img_dev *dev)
{
struct aes3k_dev *aesdev = fpi_imgdev_get_user_data(dev);
struct aes3k_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev));
g_free(aesdev);
libusb_release_interface(fpi_imgdev_get_usb_dev(dev), 0);
libusb_release_interface(fpi_dev_get_usb_dev(FP_DEV(dev)), 0);
fpi_imgdev_close_complete(dev);
}

View File

@@ -63,7 +63,7 @@ static void aes3k_assemble_image(unsigned char *input, size_t width, size_t heig
static void img_cb(struct libusb_transfer *transfer)
{
struct fp_img_dev *dev = transfer->user_data;
struct aes3k_dev *aesdev = fpi_imgdev_get_user_data(dev);
struct aes3k_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev));
unsigned char *ptr = transfer->buffer;
struct fp_img *tmp;
struct fp_img *img;
@@ -94,7 +94,7 @@ static void img_cb(struct libusb_transfer *transfer)
/* FIXME: this is an ugly hack to make the image big enough for NBIS
* to process reliably */
img = fpi_im_resize(tmp, aesdev->enlarge_factor, aesdev->enlarge_factor);
img = fpi_img_resize(tmp, aesdev->enlarge_factor, aesdev->enlarge_factor);
fp_img_free(tmp);
fpi_imgdev_image_captured(dev, img);
@@ -112,18 +112,13 @@ err:
static void do_capture(struct fp_img_dev *dev)
{
struct aes3k_dev *aesdev = fpi_imgdev_get_user_data(dev);
struct aes3k_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev));
unsigned char *data;
int r;
aesdev->img_trf = libusb_alloc_transfer(0);
if (!aesdev->img_trf) {
fpi_imgdev_session_error(dev, -EIO);
return;
}
aesdev->img_trf = fpi_usb_alloc();
data = g_malloc(aesdev->data_buflen);
libusb_fill_bulk_transfer(aesdev->img_trf, fpi_imgdev_get_usb_dev(dev), EP_IN, data,
libusb_fill_bulk_transfer(aesdev->img_trf, fpi_dev_get_usb_dev(FP_DEV(dev)), EP_IN, data,
aesdev->data_buflen, img_cb, dev, 0);
r = libusb_submit_transfer(aesdev->img_trf);
@@ -142,16 +137,16 @@ static void init_reqs_cb(struct fp_img_dev *dev, int result, void *user_data)
do_capture(dev);
}
int aes3k_dev_activate(struct fp_img_dev *dev, enum fp_imgdev_state state)
int aes3k_dev_activate(struct fp_img_dev *dev)
{
struct aes3k_dev *aesdev = fpi_imgdev_get_user_data(dev);
struct aes3k_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev));
aes_write_regv(dev, aesdev->init_reqs, aesdev->init_reqs_len, init_reqs_cb, NULL);
return 0;
}
void aes3k_dev_deactivate(struct fp_img_dev *dev)
{
struct aes3k_dev *aesdev = fpi_imgdev_get_user_data(dev);
struct aes3k_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev));
/* FIXME: should wait for cancellation to complete before returning
* from deactivation, otherwise app may legally exit before we've

View File

@@ -52,7 +52,7 @@ struct aes3k_dev {
};
int aes3k_dev_activate(struct fp_img_dev *dev, enum fp_imgdev_state state);
int aes3k_dev_activate(struct fp_img_dev *dev);
void aes3k_dev_deactivate(struct fp_img_dev *dev);
#endif

View File

@@ -119,14 +119,14 @@ static int dev_init(struct fp_img_dev *dev, unsigned long driver_data)
int r;
struct aes3k_dev *aesdev;
r = libusb_claim_interface(fpi_imgdev_get_usb_dev(dev), 0);
r = libusb_claim_interface(fpi_dev_get_usb_dev(FP_DEV(dev)), 0);
if (r < 0) {
fp_err("could not claim interface 0: %s", libusb_error_name(r));
return r;
}
aesdev = g_malloc0(sizeof(struct aes3k_dev));
fpi_imgdev_set_user_data(dev, aesdev);
fp_dev_set_instance_data(FP_DEV(dev), aesdev);
if (!aesdev)
return -ENOMEM;
@@ -145,9 +145,9 @@ static int dev_init(struct fp_img_dev *dev, unsigned long driver_data)
static void dev_deinit(struct fp_img_dev *dev)
{
struct aes3k_dev *aesdev = fpi_imgdev_get_user_data(dev);
struct aes3k_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev));
g_free(aesdev);
libusb_release_interface(fpi_imgdev_get_usb_dev(dev), 0);
libusb_release_interface(fpi_dev_get_usb_dev(FP_DEV(dev)), 0);
fpi_imgdev_close_complete(dev);
}

View File

@@ -24,10 +24,10 @@
#include <errno.h>
#include <string.h>
#include <libusb.h>
#include <glib.h>
#include "assembling.h"
#include "fpi-usb.h"
#include "fpi-assembling.h"
#include "aeslib.h"
#define MAX_REGWRITES_PER_REQUEST 16
@@ -73,21 +73,16 @@ static int do_write_regv(struct write_regv_data *wdata, int upper_bound)
unsigned char *data = g_malloc(alloc_size);
unsigned int i;
size_t data_offset = 0;
struct libusb_transfer *transfer = libusb_alloc_transfer(0);
struct libusb_transfer *transfer = fpi_usb_alloc();
int r;
if (!transfer) {
g_free(data);
return -ENOMEM;
}
for (i = offset; i < offset + num; i++) {
const struct aes_regwrite *regwrite = &wdata->regs[i];
data[data_offset++] = regwrite->reg;
data[data_offset++] = regwrite->value;
}
libusb_fill_bulk_transfer(transfer, wdata->imgdev->udev, EP_OUT, data,
libusb_fill_bulk_transfer(transfer, FP_DEV(wdata->imgdev)->udev, EP_OUT, data,
alloc_size, write_regv_trf_complete, wdata, BULK_TIMEOUT);
r = libusb_submit_transfer(transfer);
if (r < 0) {
@@ -149,8 +144,10 @@ static void continue_write_regv(struct write_regv_data *wdata)
void aes_write_regv(struct fp_img_dev *dev, const struct aes_regwrite *regs,
unsigned int num_regs, aes_write_regv_cb callback, void *user_data)
{
struct write_regv_data *wdata = g_malloc(sizeof(*wdata));
struct write_regv_data *wdata;
fp_dbg("write %d regs", num_regs);
wdata = g_malloc(sizeof(*wdata));
wdata->imgdev = dev;
wdata->num_regs = num_regs;
wdata->regs = regs;
@@ -158,6 +155,8 @@ void aes_write_regv(struct fp_img_dev *dev, const struct aes_regwrite *regs,
wdata->callback = callback;
wdata->user_data = user_data;
continue_write_regv(wdata);
g_free(wdata);
}
unsigned char aes_get_pixel(struct fpi_frame_asmbl_ctx *ctx,

View File

@@ -35,52 +35,57 @@ static void complete_deactivation(struct fp_img_dev *dev);
#define BULK_TIMEOUT 4000
#define FRAME_HEIGHT AESX660_FRAME_HEIGHT
#define min(a, b) (((a) < (b)) ? (a) : (b))
#define ID_LEN 8
#define INIT_LEN 4
#define CALIBRATE_DATA_LEN 4
#define FINGER_DET_DATA_LEN 4
static void aesX660_send_cmd_timeout(struct fpi_ssm *ssm, const unsigned char *cmd,
size_t cmd_len, libusb_transfer_cb_fn callback, int timeout)
static void
aesX660_send_cmd_timeout(fpi_ssm *ssm,
struct fp_dev *_dev,
const unsigned char *cmd,
size_t cmd_len,
libusb_transfer_cb_fn callback,
int timeout)
{
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct libusb_transfer *transfer = libusb_alloc_transfer(0);
struct fp_img_dev *dev = FP_IMG_DEV(_dev);
struct libusb_transfer *transfer = fpi_usb_alloc();
int r;
if (!transfer) {
fpi_ssm_mark_aborted(ssm, -ENOMEM);
return;
}
libusb_fill_bulk_transfer(transfer, fpi_imgdev_get_usb_dev(dev), EP_OUT,
libusb_fill_bulk_transfer(transfer, fpi_dev_get_usb_dev(FP_DEV(dev)), EP_OUT,
(unsigned char *)cmd, cmd_len,
callback, ssm, timeout);
r = libusb_submit_transfer(transfer);
if (r < 0) {
fp_dbg("failed to submit transfer\n");
libusb_free_transfer(transfer);
fpi_ssm_mark_aborted(ssm, -ENOMEM);
fpi_ssm_mark_failed(ssm, -ENOMEM);
}
}
static void aesX660_send_cmd(struct fpi_ssm *ssm, const unsigned char *cmd,
size_t cmd_len, libusb_transfer_cb_fn callback)
static void
aesX660_send_cmd(fpi_ssm *ssm,
struct fp_dev *dev,
const unsigned char *cmd,
size_t cmd_len,
libusb_transfer_cb_fn callback)
{
return aesX660_send_cmd_timeout(ssm, cmd, cmd_len, callback, BULK_TIMEOUT);
return aesX660_send_cmd_timeout(ssm, dev, cmd, cmd_len, callback, BULK_TIMEOUT);
}
static void aesX660_read_response(struct fpi_ssm *ssm, size_t buf_len,
libusb_transfer_cb_fn callback)
static void
aesX660_read_response(fpi_ssm *ssm,
struct fp_dev *_dev,
size_t buf_len,
libusb_transfer_cb_fn callback)
{
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct libusb_transfer *transfer = libusb_alloc_transfer(0);
struct fp_img_dev *dev = FP_IMG_DEV(_dev);
struct libusb_transfer *transfer = fpi_usb_alloc();
unsigned char *data;
int r;
if (!transfer) {
fpi_ssm_mark_aborted(ssm, -ENOMEM);
return;
}
data = g_malloc(buf_len);
libusb_fill_bulk_transfer(transfer, fpi_imgdev_get_usb_dev(dev), EP_IN,
libusb_fill_bulk_transfer(transfer, fpi_dev_get_usb_dev(FP_DEV(dev)), EP_IN,
data, buf_len,
callback, ssm, BULK_TIMEOUT);
@@ -89,13 +94,13 @@ static void aesX660_read_response(struct fpi_ssm *ssm, size_t buf_len,
fp_dbg("Failed to submit rx transfer: %d\n", r);
g_free(data);
libusb_free_transfer(transfer);
fpi_ssm_mark_aborted(ssm, r);
fpi_ssm_mark_failed(ssm, r);
}
}
static void aesX660_send_cmd_cb(struct libusb_transfer *transfer)
{
struct fpi_ssm *ssm = transfer->user_data;
fpi_ssm *ssm = transfer->user_data;
if ((transfer->status == LIBUSB_TRANSFER_COMPLETED) &&
(transfer->length == transfer->actual_length)) {
@@ -103,25 +108,25 @@ static void aesX660_send_cmd_cb(struct libusb_transfer *transfer)
} else {
fp_dbg("tx transfer status: %d, actual_len: %.4x\n",
transfer->status, transfer->actual_length);
fpi_ssm_mark_aborted(ssm, -EIO);
fpi_ssm_mark_failed(ssm, -EIO);
}
libusb_free_transfer(transfer);
}
static void aesX660_read_calibrate_data_cb(struct libusb_transfer *transfer)
{
struct fpi_ssm *ssm = transfer->user_data;
fpi_ssm *ssm = transfer->user_data;
unsigned char *data = transfer->buffer;
if ((transfer->status != LIBUSB_TRANSFER_COMPLETED) ||
(transfer->length != transfer->actual_length)) {
fpi_ssm_mark_aborted(ssm, -EIO);
fpi_ssm_mark_failed(ssm, -EIO);
goto out;
}
/* Calibrate response was read correctly? */
if (data[AESX660_RESPONSE_TYPE_OFFSET] != AESX660_CALIBRATE_RESPONSE) {
fp_dbg("Bogus calibrate response: %.2x\n", data[0]);
fpi_ssm_mark_aborted(ssm, -EPROTO);
fpi_ssm_mark_failed(ssm, -EPROTO);
goto out;
}
@@ -143,9 +148,9 @@ enum finger_det_states {
static void finger_det_read_fd_data_cb(struct libusb_transfer *transfer)
{
struct fpi_ssm *ssm = transfer->user_data;
fpi_ssm *ssm = transfer->user_data;
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct aesX660_dev *aesdev = fpi_imgdev_get_user_data(dev);
struct aesX660_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev));
unsigned char *data = transfer->buffer;
aesdev->fd_data_transfer = NULL;
@@ -159,13 +164,13 @@ static void finger_det_read_fd_data_cb(struct libusb_transfer *transfer)
if ((transfer->status != LIBUSB_TRANSFER_COMPLETED) ||
(transfer->length != transfer->actual_length)) {
fp_dbg("Failed to read FD data\n");
fpi_ssm_mark_aborted(ssm, -EIO);
fpi_ssm_mark_failed(ssm, -EIO);
goto out;
}
if (data[AESX660_RESPONSE_TYPE_OFFSET] != AESX660_FINGER_DET_RESPONSE) {
fp_dbg("Bogus FD response: %.2x\n", data[0]);
fpi_ssm_mark_aborted(ssm, -EPROTO);
fpi_ssm_mark_failed(ssm, -EPROTO);
goto out;
}
@@ -184,21 +189,21 @@ out:
static void finger_det_set_idle_cmd_cb(struct libusb_transfer *transfer)
{
struct fpi_ssm *ssm = transfer->user_data;
fpi_ssm *ssm = transfer->user_data;
if ((transfer->status == LIBUSB_TRANSFER_COMPLETED) &&
(transfer->length == transfer->actual_length)) {
fpi_ssm_mark_completed(ssm);
} else {
fpi_ssm_mark_aborted(ssm, -EIO);
fpi_ssm_mark_failed(ssm, -EIO);
}
libusb_free_transfer(transfer);
}
static void finger_det_sm_complete(struct fpi_ssm *ssm)
static void finger_det_sm_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
{
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct aesX660_dev *aesdev = fpi_imgdev_get_user_data(dev);
struct fp_img_dev *dev = user_data;
struct aesX660_dev *aesdev = FP_INSTANCE_DATA(_dev);
int err = fpi_ssm_get_error(ssm);
fp_dbg("Finger detection completed");
@@ -215,23 +220,22 @@ static void finger_det_sm_complete(struct fpi_ssm *ssm)
}
}
static void finger_det_run_state(struct fpi_ssm *ssm)
static void finger_det_run_state(fpi_ssm *ssm, struct fp_dev *dev, void *user_data)
{
switch (fpi_ssm_get_cur_state(ssm)) {
case FINGER_DET_SEND_LED_CMD:
aesX660_send_cmd(ssm, led_blink_cmd, sizeof(led_blink_cmd),
aesX660_send_cmd(ssm, dev, led_blink_cmd, sizeof(led_blink_cmd),
aesX660_send_cmd_cb);
break;
case FINGER_DET_SEND_FD_CMD:
aesX660_send_cmd_timeout(ssm, wait_for_finger_cmd, sizeof(wait_for_finger_cmd),
aesX660_send_cmd_timeout(ssm, dev, wait_for_finger_cmd, sizeof(wait_for_finger_cmd),
aesX660_send_cmd_cb, 0);
break;
case FINGER_DET_READ_FD_DATA:
/* Should return 4 byte of response */
aesX660_read_response(ssm, 4, finger_det_read_fd_data_cb);
aesX660_read_response(ssm, dev, FINGER_DET_DATA_LEN, finger_det_read_fd_data_cb);
break;
case FINGER_DET_SET_IDLE:
aesX660_send_cmd(ssm, set_idle_cmd, sizeof(set_idle_cmd),
aesX660_send_cmd(ssm, dev, set_idle_cmd, sizeof(set_idle_cmd),
finger_det_set_idle_cmd_cb);
break;
}
@@ -239,16 +243,15 @@ static void finger_det_run_state(struct fpi_ssm *ssm)
static void start_finger_detection(struct fp_img_dev *dev)
{
struct fpi_ssm *ssm;
struct aesX660_dev *aesdev = fpi_imgdev_get_user_data(dev);
fpi_ssm *ssm;
struct aesX660_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev));
if (aesdev->deactivating) {
complete_deactivation(dev);
return;
}
ssm = fpi_ssm_new(fpi_imgdev_get_dev(dev), finger_det_run_state, FINGER_DET_NUM_STATES);
fpi_ssm_set_user_data(ssm, dev);
ssm = fpi_ssm_new(FP_DEV(dev), finger_det_run_state, FINGER_DET_NUM_STATES, dev);
fpi_ssm_start(ssm, finger_det_sm_complete);
}
@@ -263,12 +266,11 @@ enum capture_states {
};
/* Returns number of processed bytes */
static int process_stripe_data(struct fpi_ssm *ssm, unsigned char *data)
static int process_stripe_data(fpi_ssm *ssm, struct fp_img_dev *dev, unsigned char *data)
{
struct fpi_frame *stripe;
unsigned char *stripdata;
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct aesX660_dev *aesdev = fpi_imgdev_get_user_data(dev);
struct aesX660_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev));
stripe = g_malloc(aesdev->assembling_ctx->frame_width * FRAME_HEIGHT / 2 + sizeof(struct fpi_frame)); /* 4 bpp */
stripdata = stripe->data;
@@ -286,17 +288,17 @@ static int process_stripe_data(struct fpi_ssm *ssm, unsigned char *data)
aesdev->strips = g_slist_prepend(aesdev->strips, stripe);
aesdev->strips_len++;
return (data[AESX660_LAST_FRAME_OFFSET] & AESX660_LAST_FRAME_BIT);
} else {
return 0;
}
g_free(stripe);
return 0;
}
static void capture_set_idle_cmd_cb(struct libusb_transfer *transfer)
{
struct fpi_ssm *ssm = transfer->user_data;
fpi_ssm *ssm = transfer->user_data;
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct aesX660_dev *aesdev = fpi_imgdev_get_user_data(dev);
struct aesX660_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev));
if ((transfer->status == LIBUSB_TRANSFER_COMPLETED) &&
(transfer->length == transfer->actual_length)) {
@@ -313,28 +315,28 @@ static void capture_set_idle_cmd_cb(struct libusb_transfer *transfer)
fpi_imgdev_report_finger_status(dev, FALSE);
fpi_ssm_mark_completed(ssm);
} else {
fpi_ssm_mark_aborted(ssm, -EIO);
fpi_ssm_mark_failed(ssm, -EIO);
}
libusb_free_transfer(transfer);
}
static void capture_read_stripe_data_cb(struct libusb_transfer *transfer)
{
struct fpi_ssm *ssm = transfer->user_data;
fpi_ssm *ssm = transfer->user_data;
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct aesX660_dev *aesdev = fpi_imgdev_get_user_data(dev);
struct aesX660_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev));
unsigned char *data = transfer->buffer;
int finger_missing = 0;
size_t copied, actual_len = transfer->actual_length;
if (transfer->status != LIBUSB_TRANSFER_COMPLETED) {
fpi_ssm_mark_aborted(ssm, -EIO);
fpi_ssm_mark_failed(ssm, -EIO);
goto out;
}
fp_dbg("Got %lu bytes of data", actual_len);
do {
copied = min(aesdev->buffer_max - aesdev->buffer_size, actual_len);
copied = MIN(aesdev->buffer_max - aesdev->buffer_size, actual_len);
memcpy(aesdev->buffer + aesdev->buffer_size,
data,
copied);
@@ -352,7 +354,7 @@ static void capture_read_stripe_data_cb(struct libusb_transfer *transfer)
aesdev->buffer_max);
continue;
} else {
finger_missing |= process_stripe_data(ssm, aesdev->buffer);
finger_missing |= process_stripe_data(ssm, dev, aesdev->buffer);
aesdev->buffer_max = AESX660_HEADER_SIZE;
aesdev->buffer_size = 0;
}
@@ -371,39 +373,38 @@ out:
libusb_free_transfer(transfer);
}
static void capture_run_state(struct fpi_ssm *ssm)
static void capture_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
{
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct aesX660_dev *aesdev = fpi_imgdev_get_user_data(dev);
struct aesX660_dev *aesdev = FP_INSTANCE_DATA(_dev);
switch (fpi_ssm_get_cur_state(ssm)) {
case CAPTURE_SEND_LED_CMD:
aesX660_send_cmd(ssm, led_solid_cmd, sizeof(led_solid_cmd),
aesX660_send_cmd(ssm, _dev, led_solid_cmd, sizeof(led_solid_cmd),
aesX660_send_cmd_cb);
break;
case CAPTURE_SEND_CAPTURE_CMD:
aesdev->buffer_size = 0;
aesdev->buffer_max = AESX660_HEADER_SIZE;
aesX660_send_cmd(ssm, aesdev->start_imaging_cmd,
aesX660_send_cmd(ssm, _dev, aesdev->start_imaging_cmd,
aesdev->start_imaging_cmd_len,
aesX660_send_cmd_cb);
break;
case CAPTURE_READ_STRIPE_DATA:
aesX660_read_response(ssm, AESX660_BULK_TRANSFER_SIZE,
aesX660_read_response(ssm, _dev, AESX660_BULK_TRANSFER_SIZE,
capture_read_stripe_data_cb);
break;
case CAPTURE_SET_IDLE:
fp_dbg("Got %lu frames\n", aesdev->strips_len);
aesX660_send_cmd(ssm, set_idle_cmd, sizeof(set_idle_cmd),
aesX660_send_cmd(ssm, _dev, set_idle_cmd, sizeof(set_idle_cmd),
capture_set_idle_cmd_cb);
break;
}
}
static void capture_sm_complete(struct fpi_ssm *ssm)
static void capture_sm_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
{
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct aesX660_dev *aesdev = fpi_imgdev_get_user_data(dev);
struct fp_img_dev *dev = user_data;
struct aesX660_dev *aesdev = FP_INSTANCE_DATA(_dev);
int err = fpi_ssm_get_error(ssm);
fp_dbg("Capture completed");
@@ -419,17 +420,16 @@ static void capture_sm_complete(struct fpi_ssm *ssm)
static void start_capture(struct fp_img_dev *dev)
{
struct aesX660_dev *aesdev = fpi_imgdev_get_user_data(dev);
struct fpi_ssm *ssm;
struct aesX660_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev));
fpi_ssm *ssm;
if (aesdev->deactivating) {
complete_deactivation(dev);
return;
}
ssm = fpi_ssm_new(fpi_imgdev_get_dev(dev), capture_run_state, CAPTURE_NUM_STATES);
ssm = fpi_ssm_new(FP_DEV(dev), capture_run_state, CAPTURE_NUM_STATES, dev);
G_DEBUG_HERE();
fpi_ssm_set_user_data(ssm, dev);
fpi_ssm_start(ssm, capture_sm_complete);
}
@@ -448,15 +448,15 @@ enum activate_states {
static void activate_read_id_cb(struct libusb_transfer *transfer)
{
struct fpi_ssm *ssm = transfer->user_data;
fpi_ssm *ssm = transfer->user_data;
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct aesX660_dev *aesdev = fpi_imgdev_get_user_data(dev);
struct aesX660_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev));
unsigned char *data = transfer->buffer;
if ((transfer->status != LIBUSB_TRANSFER_COMPLETED) ||
(transfer->length != transfer->actual_length)) {
fp_dbg("read_id cmd failed\n");
fpi_ssm_mark_aborted(ssm, -EIO);
fpi_ssm_mark_failed(ssm, -EIO);
goto out;
}
/* ID was read correctly */
@@ -465,7 +465,7 @@ static void activate_read_id_cb(struct libusb_transfer *transfer)
data[4], data[3], data[5], data[6], data[7]);
} else {
fp_dbg("Bogus read ID response: %.2x\n", data[AESX660_RESPONSE_TYPE_OFFSET]);
fpi_ssm_mark_aborted(ssm, -EPROTO);
fpi_ssm_mark_failed(ssm, -EPROTO);
goto out;
}
@@ -487,7 +487,7 @@ static void activate_read_id_cb(struct libusb_transfer *transfer)
break;
default:
fp_dbg("Failed to init device! init status: %.2x\n", data[7]);
fpi_ssm_mark_aborted(ssm, -EPROTO);
fpi_ssm_mark_failed(ssm, -EPROTO);
break;
}
@@ -499,9 +499,9 @@ out:
static void activate_read_init_cb(struct libusb_transfer *transfer)
{
struct fpi_ssm *ssm = transfer->user_data;
fpi_ssm *ssm = transfer->user_data;
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct aesX660_dev *aesdev = fpi_imgdev_get_user_data(dev);
struct aesX660_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev));
unsigned char *data = transfer->buffer;
fp_dbg("read_init_cb\n");
@@ -509,14 +509,14 @@ static void activate_read_init_cb(struct libusb_transfer *transfer)
if ((transfer->status != LIBUSB_TRANSFER_COMPLETED) ||
(transfer->length != transfer->actual_length)) {
fp_dbg("read_init transfer status: %d, actual_len: %d\n", transfer->status, transfer->actual_length);
fpi_ssm_mark_aborted(ssm, -EIO);
fpi_ssm_mark_failed(ssm, -EIO);
goto out;
}
/* ID was read correctly */
if (data[0] != 0x42 || data[3] != 0x01) {
fp_dbg("Bogus read init response: %.2x %.2x\n", data[0],
data[3]);
fpi_ssm_mark_aborted(ssm, -EPROTO);
fpi_ssm_mark_failed(ssm, -EPROTO);
goto out;
}
aesdev->init_cmd_idx++;
@@ -534,55 +534,52 @@ out:
libusb_free_transfer(transfer);
}
static void activate_run_state(struct fpi_ssm *ssm)
static void activate_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
{
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct aesX660_dev *aesdev = fpi_imgdev_get_user_data(dev);
struct fp_img_dev *dev = user_data;
struct aesX660_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev));
switch (fpi_ssm_get_cur_state(ssm)) {
case ACTIVATE_SET_IDLE:
aesdev->init_seq_idx = 0;
fp_dbg("Activate: set idle\n");
aesX660_send_cmd(ssm, set_idle_cmd, sizeof(set_idle_cmd),
aesX660_send_cmd(ssm, _dev, set_idle_cmd, sizeof(set_idle_cmd),
aesX660_send_cmd_cb);
break;
case ACTIVATE_SEND_READ_ID_CMD:
fp_dbg("Activate: read ID\n");
aesX660_send_cmd(ssm, read_id_cmd, sizeof(read_id_cmd),
aesX660_send_cmd(ssm, _dev, read_id_cmd, sizeof(read_id_cmd),
aesX660_send_cmd_cb);
break;
case ACTIVATE_READ_ID:
/* Should return 8-byte response */
aesX660_read_response(ssm, 8, activate_read_id_cb);
aesX660_read_response(ssm, _dev, ID_LEN, activate_read_id_cb);
break;
case ACTIVATE_SEND_INIT_CMD:
fp_dbg("Activate: send init seq #%d cmd #%d\n",
aesdev->init_seq_idx,
aesdev->init_cmd_idx);
aesX660_send_cmd(ssm,
aesX660_send_cmd(ssm, _dev,
aesdev->init_seq[aesdev->init_cmd_idx].cmd,
aesdev->init_seq[aesdev->init_cmd_idx].len,
aesX660_send_cmd_cb);
break;
case ACTIVATE_READ_INIT_RESPONSE:
fp_dbg("Activate: read init response\n");
/* Should return 4-byte response */
aesX660_read_response(ssm, 4, activate_read_init_cb);
aesX660_read_response(ssm, _dev, INIT_LEN, activate_read_init_cb);
break;
case ACTIVATE_SEND_CALIBRATE_CMD:
aesX660_send_cmd(ssm, calibrate_cmd, sizeof(calibrate_cmd),
aesX660_send_cmd(ssm, _dev, calibrate_cmd, sizeof(calibrate_cmd),
aesX660_send_cmd_cb);
break;
case ACTIVATE_READ_CALIBRATE_DATA:
/* Should return 4-byte response */
aesX660_read_response(ssm, 4, aesX660_read_calibrate_data_cb);
aesX660_read_response(ssm, _dev, CALIBRATE_DATA_LEN, aesX660_read_calibrate_data_cb);
break;
}
}
static void activate_sm_complete(struct fpi_ssm *ssm)
static void activate_sm_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
{
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct fp_img_dev *dev = user_data;
int err = fpi_ssm_get_error(ssm);
fp_dbg("status %d", err);
fpi_imgdev_activate_complete(dev, err);
@@ -592,18 +589,17 @@ static void activate_sm_complete(struct fpi_ssm *ssm)
start_finger_detection(dev);
}
int aesX660_dev_activate(struct fp_img_dev *dev, enum fp_imgdev_state state)
int aesX660_dev_activate(struct fp_img_dev *dev)
{
struct fpi_ssm *ssm = fpi_ssm_new(fpi_imgdev_get_dev(dev), activate_run_state,
ACTIVATE_NUM_STATES);
fpi_ssm_set_user_data(ssm, dev);
fpi_ssm *ssm = fpi_ssm_new(FP_DEV(dev), activate_run_state,
ACTIVATE_NUM_STATES, dev);
fpi_ssm_start(ssm, activate_sm_complete);
return 0;
}
void aesX660_dev_deactivate(struct fp_img_dev *dev)
{
struct aesX660_dev *aesdev = fpi_imgdev_get_user_data(dev);
struct aesX660_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev));
if (aesdev->fd_data_transfer)
libusb_cancel_transfer(aesdev->fd_data_transfer);
@@ -613,7 +609,7 @@ void aesX660_dev_deactivate(struct fp_img_dev *dev)
static void complete_deactivation(struct fp_img_dev *dev)
{
struct aesX660_dev *aesdev = fpi_imgdev_get_user_data(dev);
struct aesX660_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev));
G_DEBUG_HERE();
aesdev->deactivating = FALSE;

View File

@@ -116,7 +116,7 @@ static const unsigned char calibrate_cmd[] = {
0x06,
};
int aesX660_dev_activate(struct fp_img_dev *dev, enum fp_imgdev_state state);
int aesX660_dev_activate(struct fp_img_dev *dev);
void aesX660_dev_deactivate(struct fp_img_dev *dev);
#endif

View File

@@ -27,7 +27,7 @@ enum {
AES2501_ID = 4,
UPEKTC_ID = 5,
AES1610_ID = 6,
FDU2000_ID = 7,
/* FDU2000_ID = 7, */
VCOM5S_ID = 8,
UPEKSONLY_ID = 9,
VFS101_ID = 10,

File diff suppressed because it is too large Load Diff

View File

@@ -21,26 +21,51 @@
#ifndef __ELAN_H
#define __ELAN_H
#include <string.h>
#include <libusb.h>
/* number of pixels to discard on left and right (along raw image height)
* because they have different intensity from the rest of the frame */
#define ELAN_FRAME_MARGIN 12
#define ELAN_VEND_ID 0x04f3
/* a default device type */
#define ELAN_ALL_DEV 0
/* devices with quirks */
#define ELAN_0907 (1 << 0)
#define ELAN_0C03 (1 << 1)
#define ELAN_0C42 (1 << 2)
/* devices which don't require frame rotation before assembling */
#define ELAN_NOT_ROTATED ELAN_0C03
/* min FW version that supports calibration */
#define ELAN_MIN_CALIBRATION_FW 0x0138
/* max difference between background image mean and calibration mean
* (the response value of get_calib_mean_cmd)*/
#define ELAN_CALIBRATION_MAX_DELTA 500
/* times to retry reading calibration status during one session
* generally prevents calibration from looping indefinitely */
#define ELAN_CALIBRATION_ATTEMPTS 10
/* min and max frames in a capture */
#define ELAN_MIN_FRAMES 7
#define ELAN_MAX_FRAMES 30
/* crop frames to this height to improve stitching */
#define ELAN_MAX_FRAME_HEIGHT 50
/* number of frames to drop at the end of capture because frames captured
* while the finger is being lifted can be bad */
#define ELAN_SKIP_LAST_FRAMES 1
#define ELAN_SKIP_LAST_FRAMES 2
#define ELAN_CMD_LEN 0x2
#define ELAN_EP_CMD_OUT (0x1 | LIBUSB_ENDPOINT_OUT)
#define ELAN_EP_CMD_IN (0x3 | LIBUSB_ENDPOINT_IN)
#define ELAN_EP_IMG_IN (0x2 | LIBUSB_ENDPOINT_IN)
/* used as response length to tell the driver to skip reading response */
#define ELAN_CMD_SKIP_READ 0
/* usual command timeout and timeout for when we need to check if the finger is
* still on the device */
#define ELAN_CMD_TIMEOUT 10000
@@ -50,127 +75,150 @@ struct elan_cmd {
unsigned char cmd[ELAN_CMD_LEN];
int response_len;
int response_in;
unsigned short devices;
};
static const struct elan_cmd get_sensor_dim_cmds[] = {
{
.cmd = {0x00, 0x0c},
.response_len = 0x4,
.response_in = ELAN_EP_CMD_IN,
},
static const struct elan_cmd get_sensor_dim_cmd = {
.cmd = {0x00, 0x0c},
.response_len = 0x4,
.response_in = ELAN_EP_CMD_IN,
.devices = ELAN_ALL_DEV,
};
static const size_t get_sensor_dim_cmds_len =
G_N_ELEMENTS(get_sensor_dim_cmds);
static const struct elan_cmd init_start_cmds[] = {
{
.cmd = {0x40, 0x19},
.response_len = 0x2,
.response_in = ELAN_EP_CMD_IN,
},
{
.cmd = {0x40, 0x2a},
.response_len = 0x2,
.response_in = ELAN_EP_CMD_IN,
},
static const struct elan_cmd get_fw_ver_cmd = {
.cmd = {0x40, 0x19},
.response_len = 0x2,
.response_in = ELAN_EP_CMD_IN,
.devices = ELAN_ALL_DEV,
};
static const size_t init_start_cmds_len = G_N_ELEMENTS(init_start_cmds);
/* unknown, returns 0x0 0x1 on 0907 */
static const struct elan_cmd activate_cmd_1 = {
.cmd = {0x40, 0x2a},
.response_len = 0x2,
.response_in = ELAN_EP_CMD_IN,
.devices = ELAN_0907,
};
static const struct elan_cmd read_cmds[] = {
/* raw frame sizes are calculated from image dimesions reported by the
static const struct elan_cmd get_image_cmd = {
.cmd = {0x00, 0x09},
/* raw frame sizes are calculated from image dimensions reported by the
* device */
{
.cmd = {0x00, 0x09},
.response_len = -1,
.response_in = ELAN_EP_IMG_IN,
},
.response_len = -1,
.response_in = ELAN_EP_IMG_IN,
.devices = ELAN_ALL_DEV,
};
const size_t read_cmds_len = G_N_ELEMENTS(read_cmds);
/* issued after data reads during init and calibration */
static const struct elan_cmd init_end_cmds[] = {
{
.cmd = {0x40, 0x24},
.response_len = 0x2,
.response_in = ELAN_EP_CMD_IN,
},
static const struct elan_cmd read_sensor_status_cmd = {
.cmd = {0x40, 0x13},
.response_len = 0x1,
.response_in = ELAN_EP_CMD_IN,
.devices = ELAN_ALL_DEV,
};
static const size_t init_end_cmds_len = G_N_ELEMENTS(init_end_cmds);
/* same command 2 times
* original driver may observe return value to determine how many times it
* should be repeated */
static const struct elan_cmd calibrate_start_cmds[] = {
{
.cmd = {0x40, 0x23},
.response_len = 0x1,
.response_in = ELAN_EP_CMD_IN,
},
{
.cmd = {0x40, 0x23},
.response_len = 0x1,
.response_in = ELAN_EP_CMD_IN,
},
static const struct elan_cmd get_calib_status_cmd = {
.cmd = {0x40, 0x23},
.response_len = 0x1,
.response_in = ELAN_EP_CMD_IN,
.devices = ELAN_ALL_DEV,
};
static const size_t calibrate_start_cmds_len =
G_N_ELEMENTS(calibrate_start_cmds);
/* issued after data reads during init and calibration */
static const struct elan_cmd calibrate_end_cmds[] = {
{
.cmd = {0x40, 0x24},
.response_len = 0x2,
.response_in = ELAN_EP_CMD_IN,
},
static const struct elan_cmd get_calib_mean_cmd = {
.cmd = {0x40, 0x24},
.response_len = 0x2,
.response_in = ELAN_EP_CMD_IN,
.devices = ELAN_ALL_DEV,
};
static const size_t calibrate_end_cmds_len =
G_N_ELEMENTS(calibrate_end_cmds);
static const struct elan_cmd capture_start_cmds[] = {
/* led on */
{
.cmd = {0x40, 0x31},
.response_len = 0x0,
.response_in = ELAN_EP_CMD_IN,
},
static const struct elan_cmd led_on_cmd = {
.cmd = {0x40, 0x31},
.response_len = ELAN_CMD_SKIP_READ,
.response_in = ELAN_EP_CMD_IN,
.devices = ELAN_ALL_DEV,
};
static size_t capture_start_cmds_len = G_N_ELEMENTS(capture_start_cmds);
static const struct elan_cmd capture_wait_finger_cmds[] = {
/* wait for finger
* subsequent read will not complete until finger is placed on the reader */
{
.cmd = {0x40, 0x3f},
.response_len = 0x1,
.response_in = ELAN_EP_CMD_IN,
},
/* wait for finger
* subsequent read will not complete until finger is placed on the reader */
static const struct elan_cmd pre_scan_cmd = {
.cmd = {0x40, 0x3f},
.response_len = 0x1,
.response_in = ELAN_EP_CMD_IN,
.devices = ELAN_ALL_DEV,
};
static size_t capture_wait_finger_cmds_len =
G_N_ELEMENTS(capture_wait_finger_cmds);
static const struct elan_cmd deactivate_cmds[] = {
/* led off */
{
.cmd = {0x00, 0x0b},
.response_len = 0x0,
.response_in = ELAN_EP_CMD_IN,
},
/* led off, stop waiting for finger */
static const struct elan_cmd stop_cmd = {
.cmd = {0x00, 0x0b},
.response_len = ELAN_CMD_SKIP_READ,
.response_in = ELAN_EP_CMD_IN,
.devices = ELAN_ALL_DEV,
};
static const size_t deactivate_cmds_len = G_N_ELEMENTS(deactivate_cmds);
static const struct usb_id elan_id_table[] = {
{.vendor = ELAN_VEND_ID,.product = 0x0903,.driver_data = ELAN_ALL_DEV},
{.vendor = ELAN_VEND_ID,.product = 0x0907,.driver_data = ELAN_0907},
{.vendor = ELAN_VEND_ID,.product = 0x0c01,.driver_data = ELAN_ALL_DEV},
{.vendor = ELAN_VEND_ID,.product = 0x0c02,.driver_data = ELAN_ALL_DEV},
{.vendor = ELAN_VEND_ID,.product = 0x0c03,.driver_data = ELAN_0C03},
{.vendor = ELAN_VEND_ID,.product = 0x0c04,.driver_data = ELAN_ALL_DEV},
{.vendor = ELAN_VEND_ID,.product = 0x0c05,.driver_data = ELAN_ALL_DEV},
{.vendor = ELAN_VEND_ID,.product = 0x0c06,.driver_data = ELAN_ALL_DEV},
{.vendor = ELAN_VEND_ID,.product = 0x0c07,.driver_data = ELAN_ALL_DEV},
{.vendor = ELAN_VEND_ID,.product = 0x0c08,.driver_data = ELAN_ALL_DEV},
{.vendor = ELAN_VEND_ID,.product = 0x0c09,.driver_data = ELAN_ALL_DEV},
{.vendor = ELAN_VEND_ID,.product = 0x0c0a,.driver_data = ELAN_ALL_DEV},
{.vendor = ELAN_VEND_ID,.product = 0x0c0b,.driver_data = ELAN_ALL_DEV},
{.vendor = ELAN_VEND_ID,.product = 0x0c0c,.driver_data = ELAN_ALL_DEV},
{.vendor = ELAN_VEND_ID,.product = 0x0c0d,.driver_data = ELAN_ALL_DEV},
{.vendor = ELAN_VEND_ID,.product = 0x0c0e,.driver_data = ELAN_ALL_DEV},
{.vendor = ELAN_VEND_ID,.product = 0x0c0f,.driver_data = ELAN_ALL_DEV},
{.vendor = ELAN_VEND_ID,.product = 0x0c10,.driver_data = ELAN_ALL_DEV},
{.vendor = ELAN_VEND_ID,.product = 0x0c11,.driver_data = ELAN_ALL_DEV},
{.vendor = ELAN_VEND_ID,.product = 0x0c12,.driver_data = ELAN_ALL_DEV},
{.vendor = ELAN_VEND_ID,.product = 0x0c13,.driver_data = ELAN_ALL_DEV},
{.vendor = ELAN_VEND_ID,.product = 0x0c14,.driver_data = ELAN_ALL_DEV},
{.vendor = ELAN_VEND_ID,.product = 0x0c15,.driver_data = ELAN_ALL_DEV},
{.vendor = ELAN_VEND_ID,.product = 0x0c16,.driver_data = ELAN_ALL_DEV},
{.vendor = ELAN_VEND_ID,.product = 0x0c17,.driver_data = ELAN_ALL_DEV},
{.vendor = ELAN_VEND_ID,.product = 0x0c18,.driver_data = ELAN_ALL_DEV},
{.vendor = ELAN_VEND_ID,.product = 0x0c19,.driver_data = ELAN_ALL_DEV},
{.vendor = ELAN_VEND_ID,.product = 0x0c1a,.driver_data = ELAN_ALL_DEV},
{.vendor = ELAN_VEND_ID,.product = 0x0c1b,.driver_data = ELAN_ALL_DEV},
{.vendor = ELAN_VEND_ID,.product = 0x0c1c,.driver_data = ELAN_ALL_DEV},
{.vendor = ELAN_VEND_ID,.product = 0x0c1d,.driver_data = ELAN_ALL_DEV},
{.vendor = ELAN_VEND_ID,.product = 0x0c1e,.driver_data = ELAN_ALL_DEV},
{.vendor = ELAN_VEND_ID,.product = 0x0c1f,.driver_data = ELAN_ALL_DEV},
{.vendor = ELAN_VEND_ID,.product = 0x0c20,.driver_data = ELAN_ALL_DEV},
{.vendor = ELAN_VEND_ID,.product = 0x0c21,.driver_data = ELAN_ALL_DEV},
{.vendor = ELAN_VEND_ID,.product = 0x0c22,.driver_data = ELAN_ALL_DEV},
{.vendor = ELAN_VEND_ID,.product = 0x0c23,.driver_data = ELAN_ALL_DEV},
{.vendor = ELAN_VEND_ID,.product = 0x0c24,.driver_data = ELAN_ALL_DEV},
{.vendor = ELAN_VEND_ID,.product = 0x0c25,.driver_data = ELAN_ALL_DEV},
{.vendor = ELAN_VEND_ID,.product = 0x0c26,.driver_data = ELAN_ALL_DEV},
{.vendor = ELAN_VEND_ID,.product = 0x0c27,.driver_data = ELAN_ALL_DEV},
{.vendor = ELAN_VEND_ID,.product = 0x0c28,.driver_data = ELAN_ALL_DEV},
{.vendor = ELAN_VEND_ID,.product = 0x0c29,.driver_data = ELAN_ALL_DEV},
{.vendor = ELAN_VEND_ID,.product = 0x0c2a,.driver_data = ELAN_ALL_DEV},
{.vendor = ELAN_VEND_ID,.product = 0x0c2b,.driver_data = ELAN_ALL_DEV},
{.vendor = ELAN_VEND_ID,.product = 0x0c2c,.driver_data = ELAN_ALL_DEV},
{.vendor = ELAN_VEND_ID,.product = 0x0c2d,.driver_data = ELAN_ALL_DEV},
{.vendor = ELAN_VEND_ID,.product = 0x0c2e,.driver_data = ELAN_ALL_DEV},
{.vendor = ELAN_VEND_ID,.product = 0x0c2f,.driver_data = ELAN_ALL_DEV},
{.vendor = ELAN_VEND_ID,.product = 0x0c30,.driver_data = ELAN_ALL_DEV},
{.vendor = ELAN_VEND_ID,.product = 0x0c31,.driver_data = ELAN_ALL_DEV},
{.vendor = ELAN_VEND_ID,.product = 0x0c32,.driver_data = ELAN_ALL_DEV},
{.vendor = ELAN_VEND_ID,.product = 0x0c33,.driver_data = ELAN_ALL_DEV},
{.vendor = ELAN_VEND_ID,.product = 0x0c42,.driver_data = ELAN_0C42},
{0, 0, 0,},
};
static void elan_cmd_cb(struct libusb_transfer *transfer);
static void elan_cmd_read(struct fpi_ssm *ssm);
static void elan_run_next_cmd(struct fpi_ssm *ssm);
static void elan_cmd_done(fpi_ssm *ssm);
static void elan_cmd_read(fpi_ssm *ssm, struct fp_img_dev *dev);
static void elan_calibrate(struct fp_img_dev *dev);
static void elan_capture(struct fp_img_dev *dev);
static void elan_deactivate(struct fp_img_dev *dev);
static int dev_change_state(struct fp_img_dev *dev, enum fp_imgdev_state state);
#endif

View File

@@ -639,14 +639,11 @@ enum {
static int async_tx(struct fp_img_dev *idev, unsigned int ep, void *cb,
void *cb_arg)
{
struct etes603_dev *dev = fpi_imgdev_get_user_data(idev);
struct libusb_transfer *transfer = libusb_alloc_transfer(0);
struct etes603_dev *dev = FP_INSTANCE_DATA(FP_DEV(idev));
struct libusb_transfer *transfer = fpi_usb_alloc();
unsigned char *buffer;
int length;
if (!transfer)
return -ENOMEM;
if (ep == EP_OUT) {
buffer = (unsigned char *)dev->req;
length = dev->req_len;
@@ -656,7 +653,7 @@ static int async_tx(struct fp_img_dev *idev, unsigned int ep, void *cb,
} else {
return -EIO;
}
libusb_fill_bulk_transfer(transfer, fpi_imgdev_get_usb_dev(idev), ep, buffer, length,
libusb_fill_bulk_transfer(transfer, fpi_dev_get_usb_dev(FP_DEV(idev)), ep, buffer, length,
cb, cb_arg, BULK_TIMEOUT);
if (libusb_submit_transfer(transfer)) {
@@ -669,14 +666,14 @@ static int async_tx(struct fp_img_dev *idev, unsigned int ep, void *cb,
static void async_tx_cb(struct libusb_transfer *transfer)
{
struct fpi_ssm *ssm = transfer->user_data;
fpi_ssm *ssm = transfer->user_data;
struct fp_img_dev *idev = fpi_ssm_get_user_data(ssm);
struct etes603_dev *dev = fpi_imgdev_get_user_data(idev);
struct etes603_dev *dev = FP_INSTANCE_DATA(FP_DEV(idev));
if (transfer->status != LIBUSB_TRANSFER_COMPLETED) {
fp_warn("transfer is not completed (status=%d)",
transfer->status);
fpi_ssm_mark_aborted(ssm, -EIO);
fpi_ssm_mark_failed(ssm, -EIO);
libusb_free_transfer(transfer);
} else {
unsigned char endpoint = transfer->endpoint;
@@ -691,7 +688,7 @@ static void async_tx_cb(struct libusb_transfer *transfer)
length, actual_length);
/* Chained with the answer */
if (async_tx(idev, EP_IN, async_tx_cb, ssm))
fpi_ssm_mark_aborted(ssm, -EIO);
fpi_ssm_mark_failed(ssm, -EIO);
} else if (endpoint == EP_IN) {
dev->ans_len = actual_length;
fpi_ssm_next_state(ssm);
@@ -699,10 +696,10 @@ static void async_tx_cb(struct libusb_transfer *transfer)
}
}
static void m_exit_state(struct fpi_ssm *ssm)
static void m_exit_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
{
struct fp_img_dev *idev = fpi_ssm_get_user_data(ssm);
struct etes603_dev *dev = fpi_imgdev_get_user_data(idev);
struct fp_img_dev *idev = user_data;
struct etes603_dev *dev = FP_INSTANCE_DATA(_dev);
switch (fpi_ssm_get_cur_state(ssm)) {
case EXIT_SET_REGS_REQ:
@@ -724,12 +721,12 @@ static void m_exit_state(struct fpi_ssm *ssm)
return;
err:
fpi_ssm_mark_aborted(ssm, -EIO);
fpi_ssm_mark_failed(ssm, -EIO);
}
static void m_exit_complete(struct fpi_ssm *ssm)
static void m_exit_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
{
struct fp_img_dev *idev = fpi_ssm_get_user_data(ssm);
struct fp_img_dev *idev = user_data;
if (fpi_ssm_get_error(ssm)) {
fp_err("Error switching the device to idle state");
@@ -742,17 +739,16 @@ static void m_exit_complete(struct fpi_ssm *ssm)
static void m_exit_start(struct fp_img_dev *idev)
{
struct fpi_ssm *ssm = fpi_ssm_new(fpi_imgdev_get_dev(idev), m_exit_state,
EXIT_NUM_STATES);
fpi_ssm *ssm = fpi_ssm_new(FP_DEV(idev), m_exit_state,
EXIT_NUM_STATES, idev);
fp_dbg("Switching device to idle mode");
fpi_ssm_set_user_data(ssm, idev);
fpi_ssm_start(ssm, m_exit_complete);
}
static void m_capture_state(struct fpi_ssm *ssm)
static void m_capture_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
{
struct fp_img_dev *idev = fpi_ssm_get_user_data(ssm);
struct etes603_dev *dev = fpi_imgdev_get_user_data(idev);
struct fp_img_dev *idev = user_data;
struct etes603_dev *dev = FP_INSTANCE_DATA(_dev);
if (dev->is_active == FALSE) {
fpi_ssm_mark_completed(ssm);
@@ -827,13 +823,13 @@ static void m_capture_state(struct fpi_ssm *ssm)
return;
err:
fpi_ssm_mark_aborted(ssm, -EIO);
fpi_ssm_mark_failed(ssm, -EIO);
}
static void m_capture_complete(struct fpi_ssm *ssm)
static void m_capture_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
{
struct fp_img_dev *idev = fpi_ssm_get_user_data(ssm);
struct etes603_dev *dev = fpi_imgdev_get_user_data(idev);
struct fp_img_dev *idev = user_data;
struct etes603_dev *dev = FP_INSTANCE_DATA(_dev);
if (fpi_ssm_get_error(ssm)) {
if (fpi_imgdev_get_action_state(idev) != IMG_ACQUIRE_STATE_DEACTIVATING) {
@@ -852,10 +848,10 @@ static void m_capture_complete(struct fpi_ssm *ssm)
}
}
static void m_finger_state(struct fpi_ssm *ssm)
static void m_finger_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
{
struct fp_img_dev *idev = fpi_ssm_get_user_data(ssm);
struct etes603_dev *dev = fpi_imgdev_get_user_data(idev);
struct fp_img_dev *idev = user_data;
struct etes603_dev *dev = FP_INSTANCE_DATA(_dev);
if (dev->is_active == FALSE) {
fpi_ssm_mark_completed(ssm);
@@ -945,19 +941,18 @@ static void m_finger_state(struct fpi_ssm *ssm)
return;
err:
fpi_ssm_mark_aborted(ssm, -EIO);
fpi_ssm_mark_failed(ssm, -EIO);
}
static void m_finger_complete(struct fpi_ssm *ssm)
static void m_finger_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
{
struct fp_img_dev *idev = fpi_ssm_get_user_data(ssm);
struct etes603_dev *dev = fpi_imgdev_get_user_data(idev);
struct fp_img_dev *idev = user_data;
struct etes603_dev *dev = FP_INSTANCE_DATA(_dev);
if (!fpi_ssm_get_error(ssm)) {
struct fpi_ssm *ssm_cap;
ssm_cap = fpi_ssm_new(fpi_imgdev_get_dev(idev), m_capture_state,
CAP_NUM_STATES);
fpi_ssm_set_user_data(ssm_cap, idev);
fpi_ssm *ssm_cap;
ssm_cap = fpi_ssm_new(FP_DEV(idev), m_capture_state,
CAP_NUM_STATES, idev);
fpi_ssm_start(ssm_cap, m_capture_complete);
} else {
if (fpi_imgdev_get_action_state(idev) != IMG_ACQUIRE_STATE_DEACTIVATING) {
@@ -973,19 +968,18 @@ static void m_finger_complete(struct fpi_ssm *ssm)
static void m_start_fingerdetect(struct fp_img_dev *idev)
{
struct fpi_ssm *ssmf;
ssmf = fpi_ssm_new(fpi_imgdev_get_dev(idev), m_finger_state, FGR_NUM_STATES);
fpi_ssm_set_user_data(ssmf, idev);
fpi_ssm *ssmf;
ssmf = fpi_ssm_new(FP_DEV(idev), m_finger_state, FGR_NUM_STATES, idev);
fpi_ssm_start(ssmf, m_finger_complete);
}
/*
* Tune value of VRT and VRB for contrast and brightness.
*/
static void m_tunevrb_state(struct fpi_ssm *ssm)
static void m_tunevrb_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
{
struct fp_img_dev *idev = fpi_ssm_get_user_data(ssm);
struct etes603_dev *dev = fpi_imgdev_get_user_data(idev);
struct fp_img_dev *idev = user_data;
struct etes603_dev *dev = FP_INSTANCE_DATA(_dev);
float hist[5];
if (dev->is_active == FALSE) {
@@ -1131,19 +1125,19 @@ static void m_tunevrb_state(struct fpi_ssm *ssm)
return;
err:
fpi_ssm_mark_aborted(ssm, -EIO);
fpi_ssm_mark_failed(ssm, -EIO);
}
static void m_tunevrb_complete(struct fpi_ssm *ssm)
static void m_tunevrb_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
{
struct fp_img_dev *idev = fpi_ssm_get_user_data(ssm);
struct fp_img_dev *idev = user_data;
fpi_imgdev_activate_complete(idev, fpi_ssm_get_error(ssm) != 0);
if (!fpi_ssm_get_error(ssm)) {
fp_dbg("Tuning is done. Starting finger detection.");
m_start_fingerdetect(idev);
} else {
struct etes603_dev *dev = fpi_imgdev_get_user_data(idev);
struct etes603_dev *dev = FP_INSTANCE_DATA(_dev);
fp_err("Error while tuning VRT");
dev->is_active = FALSE;
reset_param(dev);
@@ -1156,10 +1150,10 @@ static void m_tunevrb_complete(struct fpi_ssm *ssm)
* This function tunes the DCoffset value and adjusts the gain value if
* required.
*/
static void m_tunedc_state(struct fpi_ssm *ssm)
static void m_tunedc_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
{
struct fp_img_dev *idev = fpi_ssm_get_user_data(ssm);
struct etes603_dev *dev = fpi_imgdev_get_user_data(idev);
struct fp_img_dev *idev = user_data;
struct etes603_dev *dev = FP_INSTANCE_DATA(_dev);
if (dev->is_active == FALSE) {
fpi_ssm_mark_completed(ssm);
@@ -1255,21 +1249,20 @@ static void m_tunedc_state(struct fpi_ssm *ssm)
return;
err:
fpi_ssm_mark_aborted(ssm, -EIO);
fpi_ssm_mark_failed(ssm, -EIO);
}
static void m_tunedc_complete(struct fpi_ssm *ssm)
static void m_tunedc_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
{
struct fp_img_dev *idev = fpi_ssm_get_user_data(ssm);
struct fp_img_dev *idev = user_data;
if (!fpi_ssm_get_error(ssm)) {
struct fpi_ssm *ssm_tune;
ssm_tune = fpi_ssm_new(fpi_imgdev_get_dev(idev), m_tunevrb_state,
TUNEVRB_NUM_STATES);
fpi_ssm_set_user_data(ssm_tune, idev);
fpi_ssm *ssm_tune;
ssm_tune = fpi_ssm_new(FP_DEV(idev), m_tunevrb_state,
TUNEVRB_NUM_STATES, idev);
fpi_ssm_start(ssm_tune, m_tunevrb_complete);
} else {
struct etes603_dev *dev = fpi_imgdev_get_user_data(idev);
struct etes603_dev *dev = FP_INSTANCE_DATA(_dev);
fp_err("Error while tuning DCOFFSET");
dev->is_active = FALSE;
reset_param(dev);
@@ -1278,10 +1271,10 @@ static void m_tunedc_complete(struct fpi_ssm *ssm)
fpi_ssm_free(ssm);
}
static void m_init_state(struct fpi_ssm *ssm)
static void m_init_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
{
struct fp_img_dev *idev = fpi_ssm_get_user_data(ssm);
struct etes603_dev *dev = fpi_imgdev_get_user_data(idev);
struct fp_img_dev *idev = user_data;
struct etes603_dev *dev = FP_INSTANCE_DATA(_dev);
if (dev->is_active == FALSE) {
fpi_ssm_mark_completed(ssm);
@@ -1375,21 +1368,20 @@ static void m_init_state(struct fpi_ssm *ssm)
return;
err:
fpi_ssm_mark_aborted(ssm, -EIO);
fpi_ssm_mark_failed(ssm, -EIO);
}
static void m_init_complete(struct fpi_ssm *ssm)
static void m_init_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
{
struct fp_img_dev *idev = fpi_ssm_get_user_data(ssm);
struct fp_img_dev *idev = user_data;
if (!fpi_ssm_get_error(ssm)) {
struct fpi_ssm *ssm_tune;
ssm_tune = fpi_ssm_new(fpi_imgdev_get_dev(idev), m_tunedc_state,
TUNEDC_NUM_STATES);
fpi_ssm_set_user_data(ssm_tune, idev);
fpi_ssm *ssm_tune;
ssm_tune = fpi_ssm_new(FP_DEV(idev), m_tunedc_state,
TUNEDC_NUM_STATES, idev);
fpi_ssm_start(ssm_tune, m_tunedc_complete);
} else {
struct etes603_dev *dev = fpi_imgdev_get_user_data(idev);
struct etes603_dev *dev = FP_INSTANCE_DATA(_dev);
fp_err("Error initializing the device");
dev->is_active = FALSE;
reset_param(dev);
@@ -1398,34 +1390,26 @@ static void m_init_complete(struct fpi_ssm *ssm)
fpi_ssm_free(ssm);
}
static int dev_activate(struct fp_img_dev *idev, enum fp_imgdev_state state)
static int dev_activate(struct fp_img_dev *idev)
{
struct etes603_dev *dev = fpi_imgdev_get_user_data(idev);
struct fpi_ssm *ssm;
struct etes603_dev *dev = FP_INSTANCE_DATA(FP_DEV(idev));
fpi_ssm *ssm;
g_assert(dev);
if (state != IMGDEV_STATE_AWAIT_FINGER_ON) {
fp_err("The driver is in an unexpected state: %d.", state);
fpi_imgdev_activate_complete(idev, 1);
return -1;
}
/* Reset info and data */
dev->is_active = TRUE;
if (dev->dcoffset == 0) {
fp_dbg("Tuning device...");
ssm = fpi_ssm_new(fpi_imgdev_get_dev(idev), m_init_state, INIT_NUM_STATES);
fpi_ssm_set_user_data(ssm, idev);
ssm = fpi_ssm_new(FP_DEV(idev), m_init_state, INIT_NUM_STATES, idev);
fpi_ssm_start(ssm, m_init_complete);
} else {
fp_dbg("Using previous tuning (DCOFFSET=0x%02X,VRT=0x%02X,"
"VRB=0x%02X,GAIN=0x%02X).", dev->dcoffset, dev->vrt,
dev->vrb, dev->gain);
fpi_imgdev_activate_complete(idev, 0);
ssm = fpi_ssm_new(fpi_imgdev_get_dev(idev), m_finger_state, FGR_NUM_STATES);
fpi_ssm_set_user_data(ssm, idev);
ssm = fpi_ssm_new(FP_DEV(idev), m_finger_state, FGR_NUM_STATES, idev);
fpi_ssm_start(ssm, m_finger_complete);
}
return 0;
@@ -1433,15 +1417,16 @@ static int dev_activate(struct fp_img_dev *idev, enum fp_imgdev_state state)
static void dev_deactivate(struct fp_img_dev *idev)
{
struct etes603_dev *dev = fpi_imgdev_get_user_data(idev);
struct etes603_dev *dev = FP_INSTANCE_DATA(FP_DEV(idev));
fp_dbg("deactivating");
/* this can be called even if still activated. */
if (dev->is_active == TRUE) {
dev->is_active = FALSE;
m_exit_start(idev);
}
m_exit_start(idev);
}
static int dev_open(struct fp_img_dev *idev, unsigned long driver_data)
@@ -1450,13 +1435,13 @@ static int dev_open(struct fp_img_dev *idev, unsigned long driver_data)
struct etes603_dev *dev;
dev = g_malloc0(sizeof(struct etes603_dev));
fpi_imgdev_set_user_data(idev, dev);
fp_dev_set_instance_data(FP_DEV(idev), dev);
dev->req = g_malloc(sizeof(struct egis_msg));
dev->ans = g_malloc(FE_SIZE);
dev->fp = g_malloc(FE_SIZE * 4);
ret = libusb_claim_interface(fpi_imgdev_get_usb_dev(idev), 0);
ret = libusb_claim_interface(fpi_dev_get_usb_dev(FP_DEV(idev)), 0);
if (ret != LIBUSB_SUCCESS) {
fp_err("libusb_claim_interface failed on interface 0: %s", libusb_error_name(ret));
return ret;
@@ -1468,14 +1453,14 @@ static int dev_open(struct fp_img_dev *idev, unsigned long driver_data)
static void dev_close(struct fp_img_dev *idev)
{
struct etes603_dev *dev = fpi_imgdev_get_user_data(idev);
struct etes603_dev *dev = FP_INSTANCE_DATA(FP_DEV(idev));
g_free(dev->req);
g_free(dev->ans);
g_free(dev->fp);
g_free(dev);
libusb_release_interface(fpi_imgdev_get_usb_dev(idev), 0);
libusb_release_interface(fpi_dev_get_usb_dev(FP_DEV(idev)), 0);
fpi_imgdev_close_complete(idev);
}

View File

@@ -1,318 +0,0 @@
/*
* Secugen FDU2000 driver for libfprint
* Copyright (C) 2007 Gustavo Chain <g@0xff.cl>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#define FP_COMPONENT "fdu2000"
#include "drivers_api.h"
#ifndef HAVE_MEMMEM
gpointer
memmem(const gpointer haystack, size_t haystack_len, const gpointer needle, size_t needle_len) {
const gchar *begin;
const char *const last_possible = (const char *) haystack + haystack_len - needle_len;
/* The first occurrence of the empty string is deemed to occur at
* the beginning of the string. */
if (needle_len == 0)
return (void *) haystack;
/* Sanity check, otherwise the loop might search through the whole
* memory. */
if (haystack_len < needle_len)
return NULL;
for (begin = (const char *) haystack; begin <= last_possible; ++begin)
if (begin[0] == ((const char *) needle)[0] &&
!memcmp((const void *) &begin[1],
(const void *) ((const char *) needle + 1),
needle_len - 1))
return (void *) begin;
return NULL;
}
#endif /* HAVE_MEMMEM */
#define EP_IMAGE ( 0x02 | LIBUSB_ENDPOINT_IN )
#define EP_REPLY ( 0x01 | LIBUSB_ENDPOINT_IN )
#define EP_CMD ( 0x01 | LIBUSB_ENDPOINT_OUT )
#define BULK_TIMEOUT 200
/* fdu_req[] index */
typedef enum {
CAPTURE_READY,
CAPTURE_READ,
CAPTURE_END,
LED_OFF,
LED_ON
} req_index;
#define CMD_LEN 2
#define ACK_LEN 8
static const struct fdu2000_req {
const gchar cmd[CMD_LEN]; // Command to send
const gchar ack[ACK_LEN]; // Expected ACK
const guint ack_len; // ACK has variable length
} fdu_req[] = {
/* Capture */
{
.cmd = { 0x00, 0x04 },
.ack = { 0x00, 0x04, 0x01, 0x01 },
.ack_len = 4
},
{
.cmd = { 0x00, 0x01 },
.ack = { 0x00, 0x01, 0x01, 0x01 },
.ack_len = 4
},
{
.cmd = { 0x00, 0x05 },
.ack = { 0x00, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },
.ack_len = 8
},
/* Led */
{
.cmd = { 0x05, 0x00 },
.ack = {},
.ack_len = 0
},
{
.cmd = { 0x05, 0x01 },
.ack = {},
.ack_len = 0
}
};
/*
* Write a command and verify reponse
*/
static gint
bulk_write_safe(libusb_dev_handle *dev, req_index rIndex) {
gchar reponse[ACK_LEN];
gint r;
gchar *cmd = (gchar *)fdu_req[rIndex].cmd;
gchar *ack = (gchar *)fdu_req[rIndex].ack;
gint ack_len = fdu_req[rIndex].ack_len;
struct libusb_bulk_transfer wrmsg = {
.endpoint = EP_CMD,
.data = cmd,
.length = sizeof(cmd),
};
struct libusb_bulk_transfer readmsg = {
.endpoint = EP_REPLY,
.data = reponse,
.length = sizeof(reponse),
};
int trf;
r = libusb_bulk_transfer(dev, &wrmsg, &trf, BULK_TIMEOUT);
if (r < 0)
return r;
if (ack_len == 0)
return 0;
/* Check reply from FP */
r = libusb_bulk_transfer(dev, &readmsg, &trf, BULK_TIMEOUT);
if (r < 0)
return r;
if (!strncmp(ack, reponse, ack_len))
return 0;
fp_err("Expected different ACK from dev");
return 1; /* Error */
}
static gint
capture(struct fp_img_dev *dev, gboolean unconditional,
struct fp_img **ret)
{
#define RAW_IMAGE_WIDTH 398
#define RAW_IMAGE_HEIGTH 301
#define RAW_IMAGE_SIZE (RAW_IMAGE_WIDTH * RAW_IMAGE_HEIGTH)
struct fp_img *img = NULL;
int bytes, r;
const gchar SOF[] = { 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x0c, 0x07 }; // Start of frame
const gchar SOL[] = { 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x0b, 0x06 }; // Start of line + { L L } (L: Line num) (8 nibbles)
gchar *buffer = g_malloc0(RAW_IMAGE_SIZE * 6);
gchar *image;
gchar *p;
guint offset;
struct libusb_bulk_transfer msg = {
.endpoint = EP_IMAGE,
.data = buffer,
.length = RAW_IMAGE_SIZE * 6,
};
image = g_malloc0(RAW_IMAGE_SIZE);
if ((r = bulk_write_safe(fpi_imgdev_get_usb_dev(dev), LED_ON))) {
fp_err("Command: LED_ON");
goto out;
}
if ((r = bulk_write_safe(fpi_imgdev_get_usb_dev(dev), CAPTURE_READY))) {
fp_err("Command: CAPTURE_READY");
goto out;
}
read:
if ((r = bulk_write_safe(fpi_imgdev_get_usb_dev(dev), CAPTURE_READ))) {
fp_err("Command: CAPTURE_READ");
goto out;
}
/* Now we are ready to read from dev */
r = libusb_bulk_transfer(fpi_imgdev_get_usb_dev(dev), &msg, &bytes, BULK_TIMEOUT * 10);
if (r < 0 || bytes < 1)
goto read;
/*
* Find SOF (start of line)
*/
p = memmem(buffer, RAW_IMAGE_SIZE * 6,
(const gpointer)SOF, sizeof SOF);
fp_dbg("Read %d byte/s from dev", bytes);
if (!p)
goto out;
p += sizeof SOF;
int i = 0;
bytes = 0;
while(p) {
if ( i >= RAW_IMAGE_HEIGTH )
break;
offset = p - buffer;
p = memmem(p, (RAW_IMAGE_SIZE * 6) - (offset),
(const gpointer)SOL, sizeof SOL);
if (p) {
p += sizeof SOL + 4;
int j;
for (j = 0; j < RAW_IMAGE_WIDTH; j++) {
/**
* Convert from 4 to 8 bits
* The SECUGEN-FDU2000 has 4 lines of data, so we need to join 2 bytes into 1
*/
*(image + bytes + j) = *(p + (j * 2) + 0) << 4 & 0xf0;
*(image + bytes + j) |= *(p + (j * 2) + 1) & 0x0f;
}
p += RAW_IMAGE_WIDTH * 2;
bytes += RAW_IMAGE_WIDTH;
i++;
}
}
if ((r = bulk_write_safe(fpi_imgdev_get_usb_dev(dev), CAPTURE_END))) {
fp_err("Command: CAPTURE_END");
goto out;
}
if ((r = bulk_write_safe(fpi_imgdev_get_usb_dev(dev), LED_OFF))) {
fp_err("Command: LED_OFF");
goto out;
}
img = fpi_img_new_for_imgdev(dev);
memcpy(img->data, image, RAW_IMAGE_SIZE);
img->flags = FP_IMG_COLORS_INVERTED | FP_IMG_V_FLIPPED | FP_IMG_H_FLIPPED;
*ret = img;
out:
g_free(buffer);
g_free(image);
return r;
}
static
gint dev_init(struct fp_img_dev *dev, unsigned long driver_data)
{
gint r;
//if ( (r = usb_set_configuration(fpi_imgdev_get_usb_dev(dev), 1)) < 0 )
// goto out;
if ( (r = libusb_claim_interface(fpi_imgdev_get_usb_dev(dev), 0)) < 0 ) {
fp_err("could not claim interface 0: %s", libusb_error_name(r));
return r;
}
//if ( (r = usb_set_altinterface(fpi_imgdev_get_usb_dev(dev), 1)) < 0 )
// goto out;
//if ( (r = usb_clear_halt(fpi_imgdev_get_usb_dev(dev), EP_CMD)) < 0 )
// goto out;
/* Make sure sensor mode is not capture_{ready|read} */
if ((r = bulk_write_safe(fpi_imgdev_get_usb_dev(dev), CAPTURE_END))) {
fp_err("Command: CAPTURE_END");
goto out;
}
if ((r = bulk_write_safe(fpi_imgdev_get_usb_dev(dev), LED_OFF))) {
fp_err("Command: LED_OFF");
goto out;
}
return 0;
out:
fp_err("could not init dev");
return r;
}
static
void dev_exit(struct fp_img_dev *dev)
{
if (bulk_write_safe(fpi_imgdev_get_usb_dev(dev), CAPTURE_END))
fp_err("Command: CAPTURE_END");
libusb_release_interface(fpi_imgdev_get_usb_dev(dev), 0);
}
static const struct usb_id id_table[] = {
{ .vendor = 0x1162, .product = 0x0300 },
{ 0, 0, 0, },
};
struct fp_img_driver fdu2000_driver = {
.driver = {
.id = FDU2000_ID,
.name = FP_COMPONENT,
.full_name = "Secugen FDU 2000",
.id_table = id_table,
.scan_type = FP_SCAN_TYPE_PRESS,
},
.img_height = RAW_IMAGE_HEIGTH,
.img_width = RAW_IMAGE_WIDTH,
.bz3_threshold = 23,
.init = dev_init,
.exit = dev_exit,
.capture = capture,
};

View File

@@ -0,0 +1,66 @@
/*
* LGPL CRC code copied from GStreamer-0.10.10:
* Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
* Copyright (C) 2004,2006 Thomas Vander Stichele <thomas at apestaart dot org>
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; version
* 2.1 of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "upek_proto.h"
static const uint16_t crc_table[256] = {
0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
};
uint16_t
udf_crc(unsigned char *buffer, size_t size)
{
uint16_t crc = 0;
while (size--)
crc = (uint16_t) ((crc << 8) ^
crc_table[((crc >> 8) & 0x00ff) ^ *buffer++]);
return crc;
}

View File

@@ -0,0 +1,24 @@
/*
* LGPL CRC code copied from GStreamer-0.10.10:
* Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
* Copyright (C) 2004,2006 Thomas Vander Stichele <thomas at apestaart dot org>
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; version
* 2.1 of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <stdint.h>
#include <stddef.h>
uint16_t udf_crc(unsigned char *buffer, size_t size);

View File

@@ -81,7 +81,7 @@ struct sonly_dev {
int dev_model;
int img_width;
struct fpi_ssm *loopsm;
fpi_ssm *loopsm;
struct libusb_transfer *img_transfer[NUM_BULK_TRANSFERS];
struct img_transfer_data *img_transfer_data;
int num_flying;
@@ -100,18 +100,21 @@ struct sonly_dev {
enum sonly_kill_transfers_action killing_transfers;
int kill_status_code;
union {
struct fpi_ssm *kill_ssm;
fpi_ssm *kill_ssm;
void (*kill_cb)(struct fp_img_dev *dev);
};
};
/* Calculade squared standand deviation of sum of two lines */
/* Calculate squared standard deviation of sum of two lines */
static int upeksonly_get_deviation2(struct fpi_line_asmbl_ctx *ctx,
GSList *line1, GSList *line2)
{
unsigned char *buf1 = line1->data, *buf2 = line2->data;
int res = 0, mean = 0, i;
g_assert (ctx->line_width > 0);
for (i = 0; i < ctx->line_width; i+= 2)
mean += (int)buf1[i + 1] + (int)buf2[i];
@@ -176,11 +179,11 @@ static void free_img_transfers(struct sonly_dev *sdev)
static void last_transfer_killed(struct fp_img_dev *dev)
{
struct sonly_dev *sdev = fpi_imgdev_get_user_data(dev);
struct sonly_dev *sdev = FP_INSTANCE_DATA(FP_DEV(dev));
switch (sdev->killing_transfers) {
case ABORT_SSM:
fp_dbg("abort ssm error %d", sdev->kill_status_code);
fpi_ssm_mark_aborted(sdev->kill_ssm, sdev->kill_status_code);
fpi_ssm_mark_failed(sdev->kill_ssm, sdev->kill_status_code);
return;
case ITERATE_SSM:
fp_dbg("iterate ssm");
@@ -197,7 +200,7 @@ static void last_transfer_killed(struct fp_img_dev *dev)
static void cancel_img_transfers(struct fp_img_dev *dev)
{
struct sonly_dev *sdev = fpi_imgdev_get_user_data(dev);
struct sonly_dev *sdev = FP_INSTANCE_DATA(FP_DEV(dev));
int i;
if (sdev->num_flying == 0) {
@@ -224,7 +227,7 @@ static gboolean is_capturing(struct sonly_dev *sdev)
static void handoff_img(struct fp_img_dev *dev)
{
struct sonly_dev *sdev = fpi_imgdev_get_user_data(dev);
struct sonly_dev *sdev = FP_INSTANCE_DATA(FP_DEV(dev));
struct fp_img *img;
GSList *elem = sdev->rows;
@@ -252,7 +255,7 @@ static void handoff_img(struct fp_img_dev *dev)
static void row_complete(struct fp_img_dev *dev)
{
struct sonly_dev *sdev = fpi_imgdev_get_user_data(dev);
struct sonly_dev *sdev = FP_INSTANCE_DATA(FP_DEV(dev));
sdev->rowbuf_offset = -1;
if (sdev->num_rows > 0) {
@@ -340,7 +343,7 @@ static void row_complete(struct fp_img_dev *dev)
/* add data to row buffer */
static void add_to_rowbuf(struct fp_img_dev *dev, unsigned char *data, int size)
{
struct sonly_dev *sdev = fpi_imgdev_get_user_data(dev);
struct sonly_dev *sdev = FP_INSTANCE_DATA(FP_DEV(dev));
memcpy(sdev->rowbuf + sdev->rowbuf_offset, data, size);
sdev->rowbuf_offset += size;
@@ -374,7 +377,7 @@ static int rowbuf_remaining(struct sonly_dev *sdev)
static void handle_packet(struct fp_img_dev *dev, unsigned char *data)
{
struct sonly_dev *sdev = fpi_imgdev_get_user_data(dev);
struct sonly_dev *sdev = FP_INSTANCE_DATA(FP_DEV(dev));
uint16_t seqnum = data[0] << 8 | data[1];
int abs_base_addr;
int for_rowbuf;
@@ -470,7 +473,7 @@ static void img_data_cb(struct libusb_transfer *transfer)
{
struct img_transfer_data *idata = transfer->user_data;
struct fp_img_dev *dev = idata->dev;
struct sonly_dev *sdev = fpi_imgdev_get_user_data(dev);
struct sonly_dev *sdev = FP_INSTANCE_DATA(FP_DEV(dev));
int i;
idata->flying = FALSE;
@@ -520,7 +523,7 @@ static void img_data_cb(struct libusb_transfer *transfer)
/***** STATE MACHINE HELPERS *****/
struct write_regs_data {
struct fpi_ssm *ssm;
fpi_ssm *ssm;
struct libusb_transfer *transfer;
const struct sonly_regwrite *regs;
size_t num_regs;
@@ -534,7 +537,7 @@ static void write_regs_finished(struct write_regs_data *wrdata, int result)
if (result == 0)
fpi_ssm_next_state(wrdata->ssm);
else
fpi_ssm_mark_aborted(wrdata->ssm, result);
fpi_ssm_mark_failed(wrdata->ssm, result);
g_free(wrdata);
}
@@ -574,23 +577,18 @@ static void write_regs_cb(struct libusb_transfer *transfer)
write_regs_iterate(wrdata);
}
static void sm_write_regs(struct fpi_ssm *ssm,
const struct sonly_regwrite *regs, size_t num_regs)
static void
sm_write_regs(fpi_ssm *ssm,
struct fp_dev *dev,
const struct sonly_regwrite *regs,
size_t num_regs)
{
struct write_regs_data *wrdata = g_malloc(sizeof(*wrdata));
unsigned char *data;
struct fp_dev *dev;
wrdata->transfer = libusb_alloc_transfer(0);
if (!wrdata->transfer) {
g_free(wrdata);
fpi_ssm_mark_aborted(ssm, -ENOMEM);
return;
}
wrdata->transfer = fpi_usb_alloc();
data = g_malloc(LIBUSB_CONTROL_SETUP_SIZE + 1);
libusb_fill_control_setup(data, 0x40, 0x0c, 0, 0, 1);
dev = fpi_ssm_get_dev(ssm);
libusb_fill_control_transfer(wrdata->transfer,
fpi_dev_get_usb_dev(dev), data,
write_regs_cb, wrdata, CTRL_TIMEOUT);
@@ -605,31 +603,29 @@ static void sm_write_regs(struct fpi_ssm *ssm,
static void sm_write_reg_cb(struct libusb_transfer *transfer)
{
struct fpi_ssm *ssm = transfer->user_data;
fpi_ssm *ssm = transfer->user_data;
g_free(transfer->buffer);
if (transfer->status != LIBUSB_TRANSFER_COMPLETED)
fpi_ssm_mark_aborted(ssm, -EIO);
fpi_ssm_mark_failed(ssm, -EIO);
else
fpi_ssm_next_state(ssm);
}
static void sm_write_reg(struct fpi_ssm *ssm, uint8_t reg, uint8_t value)
static void
sm_write_reg(fpi_ssm *ssm,
struct fp_img_dev *dev,
uint8_t reg,
uint8_t value)
{
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct libusb_transfer *transfer = libusb_alloc_transfer(0);
struct libusb_transfer *transfer = fpi_usb_alloc();
unsigned char *data;
int r;
if (!transfer) {
fpi_ssm_mark_aborted(ssm, -ENOMEM);
return;
}
fp_dbg("set %02x=%02x", reg, value);
data = g_malloc(LIBUSB_CONTROL_SETUP_SIZE + 1);
libusb_fill_control_setup(data, 0x40, 0x0c, 0, reg, 1);
libusb_fill_control_transfer(transfer, fpi_imgdev_get_usb_dev(dev),
libusb_fill_control_transfer(transfer, fpi_dev_get_usb_dev(FP_DEV(dev)),
data, sm_write_reg_cb,
ssm, CTRL_TIMEOUT);
@@ -641,18 +637,18 @@ static void sm_write_reg(struct fpi_ssm *ssm, uint8_t reg, uint8_t value)
if (r < 0) {
g_free(data);
libusb_free_transfer(transfer);
fpi_ssm_mark_aborted(ssm, r);
fpi_ssm_mark_failed(ssm, r);
}
}
static void sm_read_reg_cb(struct libusb_transfer *transfer)
{
struct fpi_ssm *ssm = transfer->user_data;
fpi_ssm *ssm = transfer->user_data;
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct sonly_dev *sdev = fpi_imgdev_get_user_data(dev);
struct sonly_dev *sdev = FP_INSTANCE_DATA(FP_DEV(dev));
if (transfer->status != LIBUSB_TRANSFER_COMPLETED) {
fpi_ssm_mark_aborted(ssm, -EIO);
fpi_ssm_mark_failed(ssm, -EIO);
} else {
sdev->read_reg_result = libusb_control_transfer_get_data(transfer)[0];
fp_dbg("read reg result = %02x", sdev->read_reg_result);
@@ -662,22 +658,19 @@ static void sm_read_reg_cb(struct libusb_transfer *transfer)
g_free(transfer->buffer);
}
static void sm_read_reg(struct fpi_ssm *ssm, uint8_t reg)
static void
sm_read_reg(fpi_ssm *ssm,
struct fp_img_dev *dev,
uint8_t reg)
{
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct libusb_transfer *transfer = libusb_alloc_transfer(0);
struct libusb_transfer *transfer = fpi_usb_alloc();
unsigned char *data;
int r;
if (!transfer) {
fpi_ssm_mark_aborted(ssm, -ENOMEM);
return;
}
fp_dbg("read reg %02x", reg);
data = g_malloc(LIBUSB_CONTROL_SETUP_SIZE + 8);
libusb_fill_control_setup(data, 0xc0, 0x0c, 0, reg, 8);
libusb_fill_control_transfer(transfer, fpi_imgdev_get_usb_dev(dev),
libusb_fill_control_transfer(transfer, fpi_dev_get_usb_dev(FP_DEV(dev)),
data, sm_read_reg_cb,
ssm, CTRL_TIMEOUT);
transfer->flags = LIBUSB_TRANSFER_SHORT_NOT_OK |
@@ -687,19 +680,19 @@ static void sm_read_reg(struct fpi_ssm *ssm, uint8_t reg)
if (r < 0) {
g_free(data);
libusb_free_transfer(transfer);
fpi_ssm_mark_aborted(ssm, r);
fpi_ssm_mark_failed(ssm, r);
}
}
static void sm_await_intr_cb(struct libusb_transfer *transfer)
{
struct fpi_ssm *ssm = transfer->user_data;
fpi_ssm *ssm = transfer->user_data;
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct sonly_dev *sdev = fpi_imgdev_get_user_data(dev);
struct sonly_dev *sdev = FP_INSTANCE_DATA(FP_DEV(dev));
if (transfer->status != LIBUSB_TRANSFER_COMPLETED) {
g_free(transfer->buffer);
fpi_ssm_mark_aborted(ssm, transfer->status);
fpi_ssm_mark_failed(ssm, transfer->status);
return;
}
@@ -713,21 +706,17 @@ static void sm_await_intr_cb(struct libusb_transfer *transfer)
fpi_ssm_next_state(ssm);
}
static void sm_await_intr(struct fpi_ssm *ssm)
static void
sm_await_intr(fpi_ssm *ssm,
struct fp_img_dev *dev)
{
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct libusb_transfer *transfer = libusb_alloc_transfer(0);
struct libusb_transfer *transfer = fpi_usb_alloc();
unsigned char *data;
int r;
if (!transfer) {
fpi_ssm_mark_aborted(ssm, -ENOMEM);
return;
}
G_DEBUG_HERE();
data = g_malloc(4);
libusb_fill_interrupt_transfer(transfer, fpi_imgdev_get_usb_dev(dev),
libusb_fill_interrupt_transfer(transfer, fpi_dev_get_usb_dev(FP_DEV(dev)),
0x83, data, 4,
sm_await_intr_cb, ssm, 0);
transfer->flags = LIBUSB_TRANSFER_SHORT_NOT_OK |
@@ -737,7 +726,7 @@ static void sm_await_intr(struct fpi_ssm *ssm)
if (r < 0) {
libusb_free_transfer(transfer);
g_free(data);
fpi_ssm_mark_aborted(ssm, r);
fpi_ssm_mark_failed(ssm, r);
}
}
@@ -763,61 +752,61 @@ enum awfsm_1000_states {
AWFSM_1000_NUM_STATES,
};
static void awfsm_2016_run_state(struct fpi_ssm *ssm)
static void awfsm_2016_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
{
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct sonly_dev *sdev = fpi_imgdev_get_user_data(dev);
struct fp_img_dev *dev = user_data;
struct sonly_dev *sdev = FP_INSTANCE_DATA(_dev);
switch (fpi_ssm_get_cur_state(ssm)) {
case AWFSM_2016_WRITEV_1:
sm_write_regs(ssm, awfsm_2016_writev_1, G_N_ELEMENTS(awfsm_2016_writev_1));
sm_write_regs(ssm, _dev, awfsm_2016_writev_1, G_N_ELEMENTS(awfsm_2016_writev_1));
break;
case AWFSM_2016_READ_01:
sm_read_reg(ssm, 0x01);
sm_read_reg(ssm, dev, 0x01);
break;
case AWFSM_2016_WRITE_01:
if (sdev->read_reg_result != 0xc6)
sm_write_reg(ssm, 0x01, 0x46);
sm_write_reg(ssm, dev, 0x01, 0x46);
else
sm_write_reg(ssm, 0x01, 0xc6);
sm_write_reg(ssm, dev, 0x01, 0xc6);
break;
case AWFSM_2016_WRITEV_2:
sm_write_regs(ssm, awfsm_2016_writev_2, G_N_ELEMENTS(awfsm_2016_writev_2));
sm_write_regs(ssm, _dev, awfsm_2016_writev_2, G_N_ELEMENTS(awfsm_2016_writev_2));
break;
case AWFSM_2016_READ_13:
sm_read_reg(ssm, 0x13);
sm_read_reg(ssm, dev, 0x13);
break;
case AWFSM_2016_WRITE_13:
if (sdev->read_reg_result != 0x45)
sm_write_reg(ssm, 0x13, 0x05);
sm_write_reg(ssm, dev, 0x13, 0x05);
else
sm_write_reg(ssm, 0x13, 0x45);
sm_write_reg(ssm, dev, 0x13, 0x45);
break;
case AWFSM_2016_WRITEV_3:
sm_write_regs(ssm, awfsm_2016_writev_3, G_N_ELEMENTS(awfsm_2016_writev_3));
sm_write_regs(ssm, _dev, awfsm_2016_writev_3, G_N_ELEMENTS(awfsm_2016_writev_3));
break;
case AWFSM_2016_READ_07:
sm_read_reg(ssm, 0x07);
sm_read_reg(ssm, dev, 0x07);
break;
case AWFSM_2016_WRITE_07:
if (sdev->read_reg_result != 0x10 && sdev->read_reg_result != 0x90)
fp_warn("odd reg7 value %x", sdev->read_reg_result);
sm_write_reg(ssm, 0x07, sdev->read_reg_result);
sm_write_reg(ssm, dev, 0x07, sdev->read_reg_result);
break;
case AWFSM_2016_WRITEV_4:
sm_write_regs(ssm, awfsm_2016_writev_4, G_N_ELEMENTS(awfsm_2016_writev_4));
sm_write_regs(ssm, _dev, awfsm_2016_writev_4, G_N_ELEMENTS(awfsm_2016_writev_4));
break;
}
}
static void awfsm_1000_run_state(struct fpi_ssm *ssm)
static void awfsm_1000_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
{
switch (fpi_ssm_get_cur_state(ssm)) {
case AWFSM_1000_WRITEV_1:
sm_write_regs(ssm, awfsm_1000_writev_1, G_N_ELEMENTS(awfsm_1000_writev_1));
sm_write_regs(ssm, _dev, awfsm_1000_writev_1, G_N_ELEMENTS(awfsm_1000_writev_1));
break;
case AWFSM_1000_WRITEV_2:
sm_write_regs(ssm, awfsm_1000_writev_2, G_N_ELEMENTS(awfsm_1000_writev_2));
sm_write_regs(ssm, _dev, awfsm_1000_writev_2, G_N_ELEMENTS(awfsm_1000_writev_2));
break;
}
}
@@ -851,17 +840,19 @@ enum capsm_1001_states {
CAPSM_1001_NUM_STATES,
};
static void capsm_fire_bulk(struct fpi_ssm *ssm)
static void
capsm_fire_bulk(fpi_ssm *ssm,
struct fp_dev *_dev)
{
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct sonly_dev *sdev = fpi_imgdev_get_user_data(dev);
struct fp_img_dev *dev = FP_IMG_DEV(_dev);
struct sonly_dev *sdev = FP_INSTANCE_DATA(_dev);
int i;
for (i = 0; i < NUM_BULK_TRANSFERS; i++) {
int r = libusb_submit_transfer(sdev->img_transfer[i]);
if (r < 0) {
if (i == 0) {
/* first one failed: easy peasy */
fpi_ssm_mark_aborted(ssm, r);
fpi_ssm_mark_failed(ssm, r);
return;
}
@@ -881,10 +872,10 @@ static void capsm_fire_bulk(struct fpi_ssm *ssm)
fpi_ssm_next_state(ssm);
}
static void capsm_2016_run_state(struct fpi_ssm *ssm)
static void capsm_2016_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
{
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct sonly_dev *sdev = fpi_imgdev_get_user_data(dev);
struct fp_img_dev *dev = user_data;
struct sonly_dev *sdev = FP_INSTANCE_DATA(_dev);
switch (fpi_ssm_get_cur_state(ssm)) {
case CAPSM_2016_INIT:
@@ -899,24 +890,23 @@ static void capsm_2016_run_state(struct fpi_ssm *ssm)
fpi_ssm_next_state(ssm);
break;
case CAPSM_2016_WRITE_15:
sm_write_reg(ssm, 0x15, 0x20);
sm_write_reg(ssm, dev, 0x15, 0x20);
break;
case CAPSM_2016_WRITE_30:
sm_write_reg(ssm, 0x30, 0xe0);
sm_write_reg(ssm, dev, 0x30, 0xe0);
break;
case CAPSM_2016_FIRE_BULK: ;
capsm_fire_bulk (ssm);
capsm_fire_bulk (ssm, _dev);
break;
case CAPSM_2016_WRITEV:
sm_write_regs(ssm, capsm_2016_writev, G_N_ELEMENTS(capsm_2016_writev));
sm_write_regs(ssm, _dev, capsm_2016_writev, G_N_ELEMENTS(capsm_2016_writev));
break;
}
}
static void capsm_1000_run_state(struct fpi_ssm *ssm)
static void capsm_1000_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
{
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct sonly_dev *sdev = fpi_imgdev_get_user_data(dev);
struct sonly_dev *sdev = FP_INSTANCE_DATA(_dev);
switch (fpi_ssm_get_cur_state(ssm)) {
case CAPSM_1000_INIT:
@@ -931,18 +921,17 @@ static void capsm_1000_run_state(struct fpi_ssm *ssm)
fpi_ssm_next_state(ssm);
break;
case CAPSM_1000_FIRE_BULK: ;
capsm_fire_bulk (ssm);
capsm_fire_bulk (ssm, _dev);
break;
case CAPSM_1000_WRITEV:
sm_write_regs(ssm, capsm_1000_writev, G_N_ELEMENTS(capsm_1000_writev));
sm_write_regs(ssm, _dev, capsm_1000_writev, G_N_ELEMENTS(capsm_1000_writev));
break;
}
}
static void capsm_1001_run_state(struct fpi_ssm *ssm)
static void capsm_1001_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
{
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct sonly_dev *sdev = fpi_imgdev_get_user_data(dev);
struct sonly_dev *sdev = FP_INSTANCE_DATA(_dev);
switch (fpi_ssm_get_cur_state(ssm)) {
case CAPSM_1001_INIT:
@@ -957,22 +946,22 @@ static void capsm_1001_run_state(struct fpi_ssm *ssm)
fpi_ssm_next_state(ssm);
break;
case CAPSM_1001_FIRE_BULK: ;
capsm_fire_bulk (ssm);
capsm_fire_bulk (ssm, _dev);
break;
case CAPSM_1001_WRITEV_1:
sm_write_regs(ssm, capsm_1001_writev_1, G_N_ELEMENTS(capsm_1001_writev_1));
sm_write_regs(ssm, _dev, capsm_1001_writev_1, G_N_ELEMENTS(capsm_1001_writev_1));
break;
case CAPSM_1001_WRITEV_2:
sm_write_regs(ssm, capsm_1001_writev_2, G_N_ELEMENTS(capsm_1001_writev_2));
sm_write_regs(ssm, _dev, capsm_1001_writev_2, G_N_ELEMENTS(capsm_1001_writev_2));
break;
case CAPSM_1001_WRITEV_3:
sm_write_regs(ssm, capsm_1001_writev_3, G_N_ELEMENTS(capsm_1001_writev_3));
sm_write_regs(ssm, _dev, capsm_1001_writev_3, G_N_ELEMENTS(capsm_1001_writev_3));
break;
case CAPSM_1001_WRITEV_4:
sm_write_regs(ssm, capsm_1001_writev_4, G_N_ELEMENTS(capsm_1001_writev_4));
sm_write_regs(ssm, _dev, capsm_1001_writev_4, G_N_ELEMENTS(capsm_1001_writev_4));
break;
case CAPSM_1001_WRITEV_5:
sm_write_regs(ssm, capsm_1001_writev_5, G_N_ELEMENTS(capsm_1001_writev_5));
sm_write_regs(ssm, _dev, capsm_1001_writev_5, G_N_ELEMENTS(capsm_1001_writev_5));
break;
}
}
@@ -994,29 +983,29 @@ enum deinitsm_1001_states {
DEINITSM_1001_NUM_STATES,
};
static void deinitsm_2016_run_state(struct fpi_ssm *ssm)
static void deinitsm_2016_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
{
switch (fpi_ssm_get_cur_state(ssm)) {
case DEINITSM_2016_WRITEV:
sm_write_regs(ssm, deinitsm_2016_writev, G_N_ELEMENTS(deinitsm_2016_writev));
sm_write_regs(ssm, _dev, deinitsm_2016_writev, G_N_ELEMENTS(deinitsm_2016_writev));
break;
}
}
static void deinitsm_1000_run_state(struct fpi_ssm *ssm)
static void deinitsm_1000_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
{
switch (fpi_ssm_get_cur_state(ssm)) {
case DEINITSM_1000_WRITEV:
sm_write_regs(ssm, deinitsm_1000_writev, G_N_ELEMENTS(deinitsm_1000_writev));
sm_write_regs(ssm, _dev, deinitsm_1000_writev, G_N_ELEMENTS(deinitsm_1000_writev));
break;
}
}
static void deinitsm_1001_run_state(struct fpi_ssm *ssm)
static void deinitsm_1001_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
{
switch (fpi_ssm_get_cur_state(ssm)) {
case DEINITSM_1001_WRITEV:
sm_write_regs(ssm, deinitsm_1001_writev, G_N_ELEMENTS(deinitsm_1001_writev));
sm_write_regs(ssm, _dev, deinitsm_1001_writev, G_N_ELEMENTS(deinitsm_1001_writev));
break;
}
}
@@ -1048,62 +1037,62 @@ enum initsm_1001_states {
INITSM_1001_NUM_STATES,
};
static void initsm_2016_run_state(struct fpi_ssm *ssm)
static void initsm_2016_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
{
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct sonly_dev *sdev = fpi_imgdev_get_user_data(dev);
struct fp_img_dev *dev = user_data;
struct sonly_dev *sdev = FP_INSTANCE_DATA(_dev);
switch (fpi_ssm_get_cur_state(ssm)) {
case INITSM_2016_WRITEV_1:
sm_write_regs(ssm, initsm_2016_writev_1, G_N_ELEMENTS(initsm_2016_writev_1));
sm_write_regs(ssm, _dev, initsm_2016_writev_1, G_N_ELEMENTS(initsm_2016_writev_1));
break;
case INITSM_2016_READ_09:
sm_read_reg(ssm, 0x09);
sm_read_reg(ssm, dev, 0x09);
break;
case INITSM_2016_WRITE_09:
sm_write_reg(ssm, 0x09, sdev->read_reg_result & ~0x08);
sm_write_reg(ssm, dev, 0x09, sdev->read_reg_result & ~0x08);
break;
case INITSM_2016_READ_13:
sm_read_reg(ssm, 0x13);
sm_read_reg(ssm, dev, 0x13);
break;
case INITSM_2016_WRITE_13:
sm_write_reg(ssm, 0x13, sdev->read_reg_result & ~0x10);
sm_write_reg(ssm, dev, 0x13, sdev->read_reg_result & ~0x10);
break;
case INITSM_2016_WRITE_04:
sm_write_reg(ssm, 0x04, 0x00);
sm_write_reg(ssm, dev, 0x04, 0x00);
break;
case INITSM_2016_WRITE_05:
sm_write_reg(ssm, 0x05, 0x00);
sm_write_reg(ssm, dev, 0x05, 0x00);
break;
}
}
static void initsm_1000_run_state(struct fpi_ssm *ssm)
static void initsm_1000_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
{
switch (fpi_ssm_get_cur_state(ssm)) {
case INITSM_1000_WRITEV_1:
sm_write_regs(ssm, initsm_1000_writev_1, G_N_ELEMENTS(initsm_1000_writev_1));
sm_write_regs(ssm, _dev, initsm_1000_writev_1, G_N_ELEMENTS(initsm_1000_writev_1));
break;
}
}
static void initsm_1001_run_state(struct fpi_ssm *ssm)
static void initsm_1001_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
{
switch (fpi_ssm_get_cur_state(ssm)) {
case INITSM_1001_WRITEV_1:
sm_write_regs(ssm, initsm_1001_writev_1, G_N_ELEMENTS(initsm_1001_writev_1));
sm_write_regs(ssm, _dev, initsm_1001_writev_1, G_N_ELEMENTS(initsm_1001_writev_1));
break;
case INITSM_1001_WRITEV_2:
sm_write_regs(ssm, initsm_1001_writev_2, G_N_ELEMENTS(initsm_1001_writev_2));
sm_write_regs(ssm, _dev, initsm_1001_writev_2, G_N_ELEMENTS(initsm_1001_writev_2));
break;
case INITSM_1001_WRITEV_3:
sm_write_regs(ssm, initsm_1001_writev_3, G_N_ELEMENTS(initsm_1001_writev_3));
sm_write_regs(ssm, _dev, initsm_1001_writev_3, G_N_ELEMENTS(initsm_1001_writev_3));
break;
case INITSM_1001_WRITEV_4:
sm_write_regs(ssm, initsm_1001_writev_4, G_N_ELEMENTS(initsm_1001_writev_4));
sm_write_regs(ssm, _dev, initsm_1001_writev_4, G_N_ELEMENTS(initsm_1001_writev_4));
break;
case INITSM_1001_WRITEV_5:
sm_write_regs(ssm, initsm_1001_writev_5, G_N_ELEMENTS(initsm_1001_writev_5));
sm_write_regs(ssm, _dev, initsm_1001_writev_5, G_N_ELEMENTS(initsm_1001_writev_5));
break;
}
}
@@ -1120,10 +1109,10 @@ enum loopsm_states {
LOOPSM_NUM_STATES,
};
static void loopsm_run_state(struct fpi_ssm *ssm)
static void loopsm_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
{
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct sonly_dev *sdev = fpi_imgdev_get_user_data(dev);
struct fp_img_dev *dev = user_data;
struct sonly_dev *sdev = FP_INSTANCE_DATA(_dev);
switch (fpi_ssm_get_cur_state(ssm)) {
case LOOPSM_RUN_AWFSM: ;
@@ -1139,18 +1128,17 @@ static void loopsm_run_state(struct fpi_ssm *ssm)
if (sdev->deactivating) {
fpi_ssm_mark_completed(ssm);
} else {
struct fpi_ssm *awfsm = NULL;
fpi_ssm *awfsm = NULL;
switch (sdev->dev_model) {
case UPEKSONLY_2016:
awfsm = fpi_ssm_new(fpi_imgdev_get_dev(dev), awfsm_2016_run_state,
AWFSM_2016_NUM_STATES);
awfsm = fpi_ssm_new(FP_DEV(dev), awfsm_2016_run_state,
AWFSM_2016_NUM_STATES, dev);
break;
case UPEKSONLY_1000:
awfsm = fpi_ssm_new(fpi_imgdev_get_dev(dev), awfsm_1000_run_state,
AWFSM_1000_NUM_STATES);
awfsm = fpi_ssm_new(FP_DEV(dev), awfsm_1000_run_state,
AWFSM_1000_NUM_STATES, dev);
break;
}
fpi_ssm_set_user_data(awfsm, dev);
fpi_ssm_start_subsm(ssm, awfsm);
}
break;
@@ -1162,49 +1150,47 @@ static void loopsm_run_state(struct fpi_ssm *ssm)
fpi_ssm_next_state(ssm);
break;
default:
sm_await_intr(ssm);
sm_await_intr(ssm, dev);
break;
}
break;
case LOOPSM_RUN_CAPSM: ;
struct fpi_ssm *capsm = NULL;
fpi_ssm *capsm = NULL;
switch (sdev->dev_model) {
case UPEKSONLY_2016:
capsm = fpi_ssm_new(fpi_imgdev_get_dev(dev), capsm_2016_run_state,
CAPSM_2016_NUM_STATES);
capsm = fpi_ssm_new(FP_DEV(dev), capsm_2016_run_state,
CAPSM_2016_NUM_STATES, dev);
break;
case UPEKSONLY_1000:
capsm = fpi_ssm_new(fpi_imgdev_get_dev(dev), capsm_1000_run_state,
CAPSM_1000_NUM_STATES);
capsm = fpi_ssm_new(FP_DEV(dev), capsm_1000_run_state,
CAPSM_1000_NUM_STATES, dev);
break;
case UPEKSONLY_1001:
capsm = fpi_ssm_new(fpi_imgdev_get_dev(dev), capsm_1001_run_state,
CAPSM_1001_NUM_STATES);
capsm = fpi_ssm_new(FP_DEV(dev), capsm_1001_run_state,
CAPSM_1001_NUM_STATES, dev);
break;
}
fpi_ssm_set_user_data(capsm, dev);
fpi_ssm_start_subsm(ssm, capsm);
break;
case LOOPSM_CAPTURE:
break;
case LOOPSM_RUN_DEINITSM: ;
struct fpi_ssm *deinitsm = NULL;
fpi_ssm *deinitsm = NULL;
switch (sdev->dev_model) {
case UPEKSONLY_2016:
deinitsm = fpi_ssm_new(fpi_imgdev_get_dev(dev), deinitsm_2016_run_state,
DEINITSM_2016_NUM_STATES);
deinitsm = fpi_ssm_new(FP_DEV(dev), deinitsm_2016_run_state,
DEINITSM_2016_NUM_STATES, dev);
break;
case UPEKSONLY_1000:
deinitsm = fpi_ssm_new(fpi_imgdev_get_dev(dev), deinitsm_1000_run_state,
DEINITSM_1000_NUM_STATES);
deinitsm = fpi_ssm_new(FP_DEV(dev), deinitsm_1000_run_state,
DEINITSM_1000_NUM_STATES, dev);
break;
case UPEKSONLY_1001:
deinitsm = fpi_ssm_new(fpi_imgdev_get_dev(dev), deinitsm_1001_run_state,
DEINITSM_1001_NUM_STATES);
deinitsm = fpi_ssm_new(FP_DEV(dev), deinitsm_1001_run_state,
DEINITSM_1001_NUM_STATES, dev);
break;
}
sdev->capturing = FALSE;
fpi_ssm_set_user_data(deinitsm, dev);
fpi_ssm_start_subsm(ssm, deinitsm);
break;
case LOOPSM_FINAL:
@@ -1218,7 +1204,7 @@ static void loopsm_run_state(struct fpi_ssm *ssm)
static void deactivate_done(struct fp_img_dev *dev)
{
struct sonly_dev *sdev = fpi_imgdev_get_user_data(dev);
struct sonly_dev *sdev = FP_INSTANCE_DATA(FP_DEV(dev));
G_DEBUG_HERE();
free_img_transfers(sdev);
@@ -1235,7 +1221,7 @@ static void deactivate_done(struct fp_img_dev *dev)
static void dev_deactivate(struct fp_img_dev *dev)
{
struct sonly_dev *sdev = fpi_imgdev_get_user_data(dev);
struct sonly_dev *sdev = FP_INSTANCE_DATA(FP_DEV(dev));
if (!sdev->capturing) {
deactivate_done(dev);
@@ -1248,10 +1234,10 @@ static void dev_deactivate(struct fp_img_dev *dev)
cancel_img_transfers(dev);
}
static void loopsm_complete(struct fpi_ssm *ssm)
static void loopsm_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
{
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct sonly_dev *sdev = fpi_imgdev_get_user_data(dev);
struct fp_img_dev *dev = user_data;
struct sonly_dev *sdev = FP_INSTANCE_DATA(_dev);
int r = fpi_ssm_get_error(ssm);
fpi_ssm_free(ssm);
@@ -1267,10 +1253,10 @@ static void loopsm_complete(struct fpi_ssm *ssm)
}
}
static void initsm_complete(struct fpi_ssm *ssm)
static void initsm_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
{
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct sonly_dev *sdev = fpi_imgdev_get_user_data(dev);
struct fp_img_dev *dev = user_data;
struct sonly_dev *sdev = FP_INSTANCE_DATA(_dev);
int r = fpi_ssm_get_error(ssm);
fpi_ssm_free(ssm);
@@ -1278,15 +1264,14 @@ static void initsm_complete(struct fpi_ssm *ssm)
if (r != 0)
return;
sdev->loopsm = fpi_ssm_new(fpi_imgdev_get_dev(dev), loopsm_run_state, LOOPSM_NUM_STATES);
fpi_ssm_set_user_data(sdev->loopsm, dev);
sdev->loopsm = fpi_ssm_new(FP_DEV(dev), loopsm_run_state, LOOPSM_NUM_STATES, dev);
fpi_ssm_start(sdev->loopsm, loopsm_complete);
}
static int dev_activate(struct fp_img_dev *dev, enum fp_imgdev_state state)
static int dev_activate(struct fp_img_dev *dev)
{
struct sonly_dev *sdev = fpi_imgdev_get_user_data(dev);
struct fpi_ssm *ssm = NULL;
struct sonly_dev *sdev = FP_INSTANCE_DATA(FP_DEV(dev));
fpi_ssm *ssm = NULL;
int i;
sdev->deactivating = FALSE;
@@ -1299,31 +1284,26 @@ static int dev_activate(struct fp_img_dev *dev, enum fp_imgdev_state state)
sdev->num_flying = 0;
for (i = 0; i < NUM_BULK_TRANSFERS; i++) {
unsigned char *data;
sdev->img_transfer[i] = libusb_alloc_transfer(0);
if (!sdev->img_transfer[i]) {
free_img_transfers(sdev);
return -ENOMEM;
}
sdev->img_transfer[i] = fpi_usb_alloc();
sdev->img_transfer_data[i].idx = i;
sdev->img_transfer_data[i].dev = dev;
data = g_malloc(4096);
libusb_fill_bulk_transfer(sdev->img_transfer[i], fpi_imgdev_get_usb_dev(dev),
libusb_fill_bulk_transfer(sdev->img_transfer[i], fpi_dev_get_usb_dev(FP_DEV(dev)),
0x81, data,
4096, img_data_cb, &sdev->img_transfer_data[i], 0);
}
switch (sdev->dev_model) {
case UPEKSONLY_2016:
ssm = fpi_ssm_new(fpi_imgdev_get_dev(dev), initsm_2016_run_state, INITSM_2016_NUM_STATES);
ssm = fpi_ssm_new(FP_DEV(dev), initsm_2016_run_state, INITSM_2016_NUM_STATES, dev);
break;
case UPEKSONLY_1000:
ssm = fpi_ssm_new(fpi_imgdev_get_dev(dev), initsm_1000_run_state, INITSM_1000_NUM_STATES);
ssm = fpi_ssm_new(FP_DEV(dev), initsm_1000_run_state, INITSM_1000_NUM_STATES, dev);
break;
case UPEKSONLY_1001:
ssm = fpi_ssm_new(fpi_imgdev_get_dev(dev), initsm_1001_run_state, INITSM_1001_NUM_STATES);
ssm = fpi_ssm_new(FP_DEV(dev), initsm_1001_run_state, INITSM_1001_NUM_STATES, dev);
break;
}
fpi_ssm_set_user_data(ssm, dev);
fpi_ssm_start(ssm, initsm_complete);
return 0;
}
@@ -1333,9 +1313,9 @@ static int dev_init(struct fp_img_dev *dev, unsigned long driver_data);
static void dev_deinit(struct fp_img_dev *dev)
{
void *user_data;
user_data = fpi_imgdev_get_user_data(dev);
user_data = FP_INSTANCE_DATA(FP_DEV(dev));
g_free(user_data);
libusb_release_interface(fpi_imgdev_get_usb_dev(dev), 0);
libusb_release_interface(fpi_dev_get_usb_dev(FP_DEV(dev)), 0);
fpi_imgdev_close_complete(dev);
}
@@ -1387,20 +1367,20 @@ static int dev_init(struct fp_img_dev *dev, unsigned long driver_data)
int r;
struct sonly_dev *sdev;
r = libusb_set_configuration(fpi_imgdev_get_usb_dev(dev), 1);
r = libusb_set_configuration(fpi_dev_get_usb_dev(FP_DEV(dev)), 1);
if (r < 0) {
fp_err("could not set configuration 1");
return r;
}
r = libusb_claim_interface(fpi_imgdev_get_usb_dev(dev), 0);
r = libusb_claim_interface(fpi_dev_get_usb_dev(FP_DEV(dev)), 0);
if (r < 0) {
fp_err("could not claim interface 0: %s", libusb_error_name(r));
return r;
}
sdev = g_malloc0(sizeof(struct sonly_dev));
fpi_imgdev_set_user_data(dev, sdev);
fp_dev_set_instance_data(FP_DEV(dev), sdev);
sdev->dev_model = (int)driver_data;
switch (driver_data) {
case UPEKSONLY_1000:

View File

@@ -56,10 +56,11 @@ enum activate_states {
ACTIVATE_NUM_STATES,
};
static void upektc_next_init_cmd(struct fpi_ssm *ssm)
static void
upektc_next_init_cmd(fpi_ssm *ssm,
struct fp_img_dev *dev)
{
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct upektc_dev *upekdev = fpi_imgdev_get_user_data(dev);
struct upektc_dev *upekdev = FP_INSTANCE_DATA(FP_DEV(dev));
upekdev->init_idx += 1;
if (upekdev->init_idx == upekdev->setup_commands_len)
@@ -70,70 +71,63 @@ static void upektc_next_init_cmd(struct fpi_ssm *ssm)
static void write_init_cb(struct libusb_transfer *transfer)
{
struct fpi_ssm *ssm = transfer->user_data;
fpi_ssm *ssm = transfer->user_data;
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct upektc_dev *upekdev = fpi_imgdev_get_user_data(dev);
struct upektc_dev *upekdev = FP_INSTANCE_DATA(FP_DEV(dev));
if ((transfer->status == LIBUSB_TRANSFER_COMPLETED) &&
(transfer->length == transfer->actual_length)) {
if (upekdev->setup_commands[upekdev->init_idx].response_len)
fpi_ssm_next_state(ssm);
else
upektc_next_init_cmd(ssm);
upektc_next_init_cmd(ssm, dev);
} else {
fpi_ssm_mark_aborted(ssm, -EIO);
fpi_ssm_mark_failed(ssm, -EIO);
}
libusb_free_transfer(transfer);
}
static void read_init_data_cb(struct libusb_transfer *transfer)
{
struct fpi_ssm *ssm = transfer->user_data;
fpi_ssm *ssm = transfer->user_data;
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
if (transfer->status == LIBUSB_TRANSFER_COMPLETED)
upektc_next_init_cmd(ssm);
upektc_next_init_cmd(ssm, dev);
else
fpi_ssm_mark_aborted(ssm, -EIO);
fpi_ssm_mark_failed(ssm, -EIO);
g_free(transfer->buffer);
libusb_free_transfer(transfer);
}
static void activate_run_state(struct fpi_ssm *ssm)
static void activate_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
{
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct upektc_dev *upekdev = fpi_imgdev_get_user_data(dev);
struct fp_img_dev *dev = user_data;
struct upektc_dev *upekdev = FP_INSTANCE_DATA(_dev);
int r;
switch (fpi_ssm_get_cur_state(ssm)) {
case WRITE_INIT:
{
struct libusb_transfer *transfer = libusb_alloc_transfer(0);
if (!transfer) {
fpi_ssm_mark_aborted(ssm, -ENOMEM);
return;
}
libusb_fill_bulk_transfer(transfer, fpi_imgdev_get_usb_dev(dev), upekdev->ep_out,
struct libusb_transfer *transfer = fpi_usb_alloc();
libusb_fill_bulk_transfer(transfer, fpi_dev_get_usb_dev(FP_DEV(dev)), upekdev->ep_out,
(unsigned char*)upekdev->setup_commands[upekdev->init_idx].cmd,
UPEKTC_CMD_LEN, write_init_cb, ssm, BULK_TIMEOUT);
r = libusb_submit_transfer(transfer);
if (r < 0) {
libusb_free_transfer(transfer);
fpi_ssm_mark_aborted(ssm, -ENOMEM);
fpi_ssm_mark_failed(ssm, -ENOMEM);
}
}
break;
case READ_DATA:
{
struct libusb_transfer *transfer = libusb_alloc_transfer(0);
struct libusb_transfer *transfer = fpi_usb_alloc();
unsigned char *data;
if (!transfer) {
fpi_ssm_mark_aborted(ssm, -ENOMEM);
break;
}
data = g_malloc(upekdev->setup_commands[upekdev->init_idx].response_len);
libusb_fill_bulk_transfer(transfer, fpi_imgdev_get_usb_dev(dev), upekdev->ep_in, data,
libusb_fill_bulk_transfer(transfer, fpi_dev_get_usb_dev(FP_DEV(dev)), upekdev->ep_in, data,
upekdev->setup_commands[upekdev->init_idx].response_len,
read_init_data_cb, ssm, BULK_TIMEOUT);
@@ -141,16 +135,16 @@ static void activate_run_state(struct fpi_ssm *ssm)
if (r < 0) {
g_free(data);
libusb_free_transfer(transfer);
fpi_ssm_mark_aborted(ssm, r);
fpi_ssm_mark_failed(ssm, r);
}
}
break;
}
}
static void activate_sm_complete(struct fpi_ssm *ssm)
static void activate_sm_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
{
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct fp_img_dev *dev = user_data;
fp_dbg("status %d", fpi_ssm_get_error(ssm));
fpi_imgdev_activate_complete(dev, fpi_ssm_get_error(ssm));
@@ -181,7 +175,7 @@ static int finger_present(unsigned char *img, size_t len, int sum_threshold)
static void finger_det_data_cb(struct libusb_transfer *transfer)
{
struct fp_img_dev *dev = transfer->user_data;
struct upektc_dev *upekdev = fpi_imgdev_get_user_data(dev);
struct upektc_dev *upekdev = FP_INSTANCE_DATA(FP_DEV(dev));
unsigned char *data = transfer->buffer;
if (transfer->status != LIBUSB_TRANSFER_COMPLETED) {
@@ -214,7 +208,7 @@ static void finger_det_cmd_cb(struct libusb_transfer *t)
unsigned char *data;
int r;
struct fp_img_dev *dev = t->user_data;
struct upektc_dev *upekdev = fpi_imgdev_get_user_data(dev);
struct upektc_dev *upekdev = FP_INSTANCE_DATA(FP_DEV(dev));
if (t->status != LIBUSB_TRANSFER_COMPLETED) {
fp_dbg("req transfer status %d\n", t->status);
@@ -226,14 +220,9 @@ static void finger_det_cmd_cb(struct libusb_transfer *t)
goto exit_free_transfer;
}
transfer = libusb_alloc_transfer(0);
if (!transfer) {
fpi_imgdev_session_error(dev, -ENOMEM);
goto exit_free_transfer;
}
transfer = fpi_usb_alloc();
data = g_malloc(IMAGE_SIZE);
libusb_fill_bulk_transfer(transfer, fpi_imgdev_get_usb_dev(dev), upekdev->ep_in, data, IMAGE_SIZE,
libusb_fill_bulk_transfer(transfer, fpi_dev_get_usb_dev(FP_DEV(dev)), upekdev->ep_in, data, IMAGE_SIZE,
finger_det_data_cb, dev, BULK_TIMEOUT);
r = libusb_submit_transfer(transfer);
@@ -249,7 +238,7 @@ exit_free_transfer:
static void start_finger_detection(struct fp_img_dev *dev)
{
int r;
struct upektc_dev *upekdev = fpi_imgdev_get_user_data(dev);
struct upektc_dev *upekdev = FP_INSTANCE_DATA(FP_DEV(dev));
struct libusb_transfer *transfer;
G_DEBUG_HERE();
@@ -258,12 +247,8 @@ static void start_finger_detection(struct fp_img_dev *dev)
return;
}
transfer = libusb_alloc_transfer(0);
if (!transfer) {
fpi_imgdev_session_error(dev, -ENOMEM);
return;
}
libusb_fill_bulk_transfer(transfer, fpi_imgdev_get_usb_dev(dev), upekdev->ep_out,
transfer = fpi_usb_alloc();
libusb_fill_bulk_transfer(transfer, fpi_dev_get_usb_dev(FP_DEV(dev)), upekdev->ep_out,
(unsigned char *)scan_cmd, UPEKTC_CMD_LEN,
finger_det_cmd_cb, dev, BULK_TIMEOUT);
r = libusb_submit_transfer(transfer);
@@ -283,31 +268,31 @@ enum capture_states {
static void capture_cmd_cb(struct libusb_transfer *transfer)
{
struct fpi_ssm *ssm = transfer->user_data;
fpi_ssm *ssm = transfer->user_data;
if ((transfer->status == LIBUSB_TRANSFER_COMPLETED) &&
(transfer->length == transfer->actual_length)) {
fpi_ssm_next_state(ssm);
} else {
fpi_ssm_mark_aborted(ssm, -EIO);
fpi_ssm_mark_failed(ssm, -EIO);
}
libusb_free_transfer(transfer);
}
static void capture_read_data_cb(struct libusb_transfer *transfer)
{
struct fpi_ssm *ssm = transfer->user_data;
fpi_ssm *ssm = transfer->user_data;
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
unsigned char *data = transfer->buffer;
struct fp_img *img;
if (transfer->status != LIBUSB_TRANSFER_COMPLETED) {
fp_dbg("request is not completed, %d", transfer->status);
fpi_ssm_mark_aborted(ssm, -EIO);
fpi_ssm_mark_failed(ssm, -EIO);
goto out;
} else if (transfer->length != transfer->actual_length) {
fp_dbg("expected %d, sent %d bytes", transfer->length, transfer->actual_length);
fpi_ssm_mark_aborted(ssm, -EPROTO);
fpi_ssm_mark_failed(ssm, -EPROTO);
goto out;
}
@@ -321,59 +306,51 @@ out:
libusb_free_transfer(transfer);
}
static void capture_run_state(struct fpi_ssm *ssm)
static void capture_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
{
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct upektc_dev *upekdev = fpi_imgdev_get_user_data(dev);
struct fp_img_dev *dev = user_data;
struct upektc_dev *upekdev = FP_INSTANCE_DATA(_dev);
int r;
switch (fpi_ssm_get_cur_state(ssm)) {
case CAPTURE_WRITE_CMD:
{
struct libusb_transfer *transfer = libusb_alloc_transfer(0);
if (!transfer) {
fpi_ssm_mark_aborted(ssm, -ENOMEM);
return;
}
libusb_fill_bulk_transfer(transfer, fpi_imgdev_get_usb_dev(dev), upekdev->ep_out,
struct libusb_transfer *transfer = fpi_usb_alloc();
libusb_fill_bulk_transfer(transfer, fpi_dev_get_usb_dev(FP_DEV(dev)), upekdev->ep_out,
(unsigned char *)scan_cmd, UPEKTC_CMD_LEN,
capture_cmd_cb, ssm, BULK_TIMEOUT);
r = libusb_submit_transfer(transfer);
if (r < 0) {
libusb_free_transfer(transfer);
fpi_ssm_mark_aborted(ssm, -ENOMEM);
fpi_ssm_mark_failed(ssm, -ENOMEM);
}
}
break;
case CAPTURE_READ_DATA:
{
struct libusb_transfer *transfer = libusb_alloc_transfer(0);
struct libusb_transfer *transfer = fpi_usb_alloc();
unsigned char *data;
if (!transfer) {
fpi_ssm_mark_aborted(ssm, -ENOMEM);
break;
}
data = g_malloc(IMAGE_SIZE);
libusb_fill_bulk_transfer(transfer, fpi_imgdev_get_usb_dev(dev), upekdev->ep_in, data, IMAGE_SIZE,
libusb_fill_bulk_transfer(transfer, fpi_dev_get_usb_dev(FP_DEV(dev)), upekdev->ep_in, data, IMAGE_SIZE,
capture_read_data_cb, ssm, BULK_TIMEOUT);
r = libusb_submit_transfer(transfer);
if (r < 0) {
g_free(data);
libusb_free_transfer(transfer);
fpi_ssm_mark_aborted(ssm, r);
fpi_ssm_mark_failed(ssm, r);
}
}
break;
};
}
static void capture_sm_complete(struct fpi_ssm *ssm)
static void capture_sm_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
{
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct upektc_dev *upekdev = fpi_imgdev_get_user_data(dev);
struct fp_img_dev *dev = user_data;
struct upektc_dev *upekdev = FP_INSTANCE_DATA(_dev);
fp_dbg("Capture completed");
if (upekdev->deactivating)
@@ -387,26 +364,24 @@ static void capture_sm_complete(struct fpi_ssm *ssm)
static void start_capture(struct fp_img_dev *dev)
{
struct upektc_dev *upekdev = fpi_imgdev_get_user_data(dev);
struct fpi_ssm *ssm;
struct upektc_dev *upekdev = FP_INSTANCE_DATA(FP_DEV(dev));
fpi_ssm *ssm;
if (upekdev->deactivating) {
complete_deactivation(dev);
return;
}
ssm = fpi_ssm_new(fpi_imgdev_get_dev(dev), capture_run_state, CAPTURE_NUM_STATES);
ssm = fpi_ssm_new(FP_DEV(dev), capture_run_state, CAPTURE_NUM_STATES, dev);
G_DEBUG_HERE();
fpi_ssm_set_user_data(ssm, dev);
fpi_ssm_start(ssm, capture_sm_complete);
}
static int dev_activate(struct fp_img_dev *dev, enum fp_imgdev_state state)
static int dev_activate(struct fp_img_dev *dev)
{
struct upektc_dev *upekdev = fpi_imgdev_get_user_data(dev);
struct fpi_ssm *ssm = fpi_ssm_new(fpi_imgdev_get_dev(dev), activate_run_state,
ACTIVATE_NUM_STATES);
fpi_ssm_set_user_data(ssm, dev);
struct upektc_dev *upekdev = FP_INSTANCE_DATA(FP_DEV(dev));
fpi_ssm *ssm = fpi_ssm_new(FP_DEV(dev), activate_run_state,
ACTIVATE_NUM_STATES, dev);
upekdev->init_idx = 0;
fpi_ssm_start(ssm, activate_sm_complete);
return 0;
@@ -414,14 +389,14 @@ static int dev_activate(struct fp_img_dev *dev, enum fp_imgdev_state state)
static void dev_deactivate(struct fp_img_dev *dev)
{
struct upektc_dev *upekdev = fpi_imgdev_get_user_data(dev);
struct upektc_dev *upekdev = FP_INSTANCE_DATA(FP_DEV(dev));
upekdev->deactivating = TRUE;
}
static void complete_deactivation(struct fp_img_dev *dev)
{
struct upektc_dev *upekdev = fpi_imgdev_get_user_data(dev);
struct upektc_dev *upekdev = FP_INSTANCE_DATA(FP_DEV(dev));
G_DEBUG_HERE();
upekdev->deactivating = FALSE;
@@ -434,14 +409,14 @@ static int dev_init(struct fp_img_dev *dev, unsigned long driver_data)
int r;
struct upektc_dev *upekdev;
r = libusb_claim_interface(fpi_imgdev_get_usb_dev(dev), 0);
r = libusb_claim_interface(fpi_dev_get_usb_dev(FP_DEV(dev)), 0);
if (r < 0) {
fp_err("could not claim interface 0: %s", libusb_error_name(r));
return r;
}
upekdev = g_malloc0(sizeof(struct upektc_dev));
fpi_imgdev_set_user_data(dev, upekdev);
fp_dev_set_instance_data(FP_DEV(dev), upekdev);
switch (driver_data) {
case UPEKTC_2015:
upekdev->ep_in = UPEKTC_EP_IN;
@@ -460,7 +435,7 @@ static int dev_init(struct fp_img_dev *dev, unsigned long driver_data)
default:
fp_err("Device variant %lu is not known\n", driver_data);
g_free(upekdev);
fpi_imgdev_set_user_data(dev, NULL);
fp_dev_set_instance_data(FP_DEV(dev), NULL);
return -ENODEV;
break;
}
@@ -471,9 +446,9 @@ static int dev_init(struct fp_img_dev *dev, unsigned long driver_data)
static void dev_deinit(struct fp_img_dev *dev)
{
void *user_data;
user_data = fpi_imgdev_get_user_data(dev);
user_data = FP_INSTANCE_DATA(FP_DEV(dev));
g_free(user_data);
libusb_release_interface(fpi_imgdev_get_usb_dev(dev), 0);
libusb_release_interface(fpi_dev_get_usb_dev(FP_DEV(dev)), 0);
fpi_imgdev_close_complete(dev);
}

View File

@@ -20,6 +20,7 @@
#define FP_COMPONENT "upektc_img"
#include "drivers_api.h"
#include "upek_proto.h"
#include "aeslib.h"
#include "upektc_img.h"
@@ -51,50 +52,6 @@ struct upektc_img_dev {
/****** HELPERS ******/
static const uint16_t crc_table[256] = {
0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
};
static uint16_t udf_crc(unsigned char *buffer, size_t size)
{
uint16_t crc = 0;
while (size--)
crc = (uint16_t) ((crc << 8) ^
crc_table[((crc >> 8) & 0x00ff) ^ *buffer++]);
return crc;
}
static void upektc_img_cmd_fix_seq(unsigned char *cmd_buf, unsigned char seq)
{
uint8_t byte;
@@ -114,61 +71,58 @@ static void upektc_img_cmd_update_crc(unsigned char *cmd_buf, size_t size)
cmd_buf[size - 1] = (crc & 0xff00) >> 8;
}
static void upektc_img_submit_req(struct fpi_ssm *ssm,
const unsigned char *buf, size_t buf_size, unsigned char seq,
libusb_transfer_cb_fn cb)
static void
upektc_img_submit_req(fpi_ssm *ssm,
struct fp_img_dev *dev,
const unsigned char *buf,
size_t buf_size,
unsigned char seq,
libusb_transfer_cb_fn cb)
{
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct upektc_img_dev *upekdev = fpi_imgdev_get_user_data(dev);
struct libusb_transfer *transfer = libusb_alloc_transfer(0);
struct upektc_img_dev *upekdev = FP_INSTANCE_DATA(FP_DEV(dev));
struct libusb_transfer *transfer = fpi_usb_alloc();
int r;
BUG_ON(buf_size > MAX_CMD_SIZE);
if (!transfer) {
fpi_ssm_mark_aborted(ssm, -ENOMEM);
return;
}
transfer->flags |= LIBUSB_TRANSFER_FREE_TRANSFER;
memcpy(upekdev->cmd, buf, buf_size);
upektc_img_cmd_fix_seq(upekdev->cmd, seq);
upektc_img_cmd_update_crc(upekdev->cmd, buf_size);
libusb_fill_bulk_transfer(transfer, fpi_imgdev_get_usb_dev(dev), EP_OUT, upekdev->cmd, buf_size,
libusb_fill_bulk_transfer(transfer, fpi_dev_get_usb_dev(FP_DEV(dev)), EP_OUT, upekdev->cmd, buf_size,
cb, ssm, BULK_TIMEOUT);
r = libusb_submit_transfer(transfer);
if (r < 0) {
libusb_free_transfer(transfer);
fpi_ssm_mark_aborted(ssm, r);
fpi_ssm_mark_failed(ssm, r);
}
}
static void upektc_img_read_data(struct fpi_ssm *ssm, size_t buf_size, size_t buf_offset, libusb_transfer_cb_fn cb)
static void
upektc_img_read_data(fpi_ssm *ssm,
struct fp_img_dev *dev,
size_t buf_size,
size_t buf_offset,
libusb_transfer_cb_fn cb)
{
struct libusb_transfer *transfer = libusb_alloc_transfer(0);
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct upektc_img_dev *upekdev = fpi_imgdev_get_user_data(dev);
struct libusb_transfer *transfer = fpi_usb_alloc();
struct upektc_img_dev *upekdev = FP_INSTANCE_DATA(FP_DEV(dev));
int r;
if (!transfer) {
fpi_ssm_mark_aborted(ssm, -ENOMEM);
return;
}
BUG_ON(buf_size > MAX_RESPONSE_SIZE);
transfer->flags |= LIBUSB_TRANSFER_FREE_TRANSFER;
libusb_fill_bulk_transfer(transfer, fpi_imgdev_get_usb_dev(dev), EP_IN, upekdev->response + buf_offset, buf_size,
libusb_fill_bulk_transfer(transfer, fpi_dev_get_usb_dev(FP_DEV(dev)), EP_IN, upekdev->response + buf_offset, buf_size,
cb, ssm, BULK_TIMEOUT);
r = libusb_submit_transfer(transfer);
if (r < 0) {
libusb_free_transfer(transfer);
fpi_ssm_mark_aborted(ssm, r);
fpi_ssm_mark_failed(ssm, r);
}
}
@@ -187,11 +141,11 @@ enum capture_states {
static void capture_reqs_cb(struct libusb_transfer *transfer)
{
struct fpi_ssm *ssm = transfer->user_data;
fpi_ssm *ssm = transfer->user_data;
if ((transfer->status != LIBUSB_TRANSFER_COMPLETED) ||
(transfer->length != transfer->actual_length)) {
fpi_ssm_mark_aborted(ssm, -EIO);
fpi_ssm_mark_failed(ssm, -EIO);
return;
}
switch (fpi_ssm_get_cur_state(ssm)) {
@@ -224,16 +178,16 @@ static int upektc_img_process_image_frame(unsigned char *image_buf, unsigned cha
static void capture_read_data_cb(struct libusb_transfer *transfer)
{
struct fpi_ssm *ssm = transfer->user_data;
fpi_ssm *ssm = transfer->user_data;
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct upektc_img_dev *upekdev = fpi_imgdev_get_user_data(dev);
struct upektc_img_dev *upekdev = FP_INSTANCE_DATA(FP_DEV(dev));
unsigned char *data = upekdev->response;
struct fp_img *img;
size_t response_size;
if (transfer->status != LIBUSB_TRANSFER_COMPLETED) {
fp_dbg("request is not completed, %d", transfer->status);
fpi_ssm_mark_aborted(ssm, -EIO);
fpi_ssm_mark_failed(ssm, -EIO);
return;
}
@@ -334,7 +288,7 @@ static void capture_read_data_cb(struct libusb_transfer *transfer)
break;
default:
fp_err("Uknown response!\n");
fpi_ssm_mark_aborted(ssm, -EIO);
fpi_ssm_mark_failed(ssm, -EIO);
break;
}
break;
@@ -343,51 +297,51 @@ static void capture_read_data_cb(struct libusb_transfer *transfer)
break;
default:
fp_err("Not handled response!\n");
fpi_ssm_mark_aborted(ssm, -EIO);
fpi_ssm_mark_failed(ssm, -EIO);
}
}
static void capture_run_state(struct fpi_ssm *ssm)
static void capture_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
{
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct upektc_img_dev *upekdev = fpi_imgdev_get_user_data(dev);
struct fp_img_dev *dev = user_data;
struct upektc_img_dev *upekdev = FP_INSTANCE_DATA(_dev);
switch (fpi_ssm_get_cur_state(ssm)) {
case CAPTURE_INIT_CAPTURE:
upektc_img_submit_req(ssm, upek2020_init_capture, sizeof(upek2020_init_capture),
upektc_img_submit_req(ssm, dev, upek2020_init_capture, sizeof(upek2020_init_capture),
upekdev->seq, capture_reqs_cb);
upekdev->seq++;
break;
case CAPTURE_READ_DATA:
case CAPTURE_READ_DATA_TERM:
if (!upekdev->response_rest)
upektc_img_read_data(ssm, SHORT_RESPONSE_SIZE, 0, capture_read_data_cb);
upektc_img_read_data(ssm, dev, SHORT_RESPONSE_SIZE, 0, capture_read_data_cb);
else
upektc_img_read_data(ssm, MAX_RESPONSE_SIZE - SHORT_RESPONSE_SIZE,
upektc_img_read_data(ssm, dev, MAX_RESPONSE_SIZE - SHORT_RESPONSE_SIZE,
SHORT_RESPONSE_SIZE, capture_read_data_cb);
break;
case CAPTURE_ACK_00_28:
case CAPTURE_ACK_00_28_TERM:
upektc_img_submit_req(ssm, upek2020_ack_00_28, sizeof(upek2020_ack_00_28),
upektc_img_submit_req(ssm, dev, upek2020_ack_00_28, sizeof(upek2020_ack_00_28),
upekdev->seq, capture_reqs_cb);
upekdev->seq++;
break;
case CAPTURE_ACK_08:
upektc_img_submit_req(ssm, upek2020_ack_08, sizeof(upek2020_ack_08),
upektc_img_submit_req(ssm, dev, upek2020_ack_08, sizeof(upek2020_ack_08),
0, capture_reqs_cb);
break;
case CAPTURE_ACK_FRAME:
upektc_img_submit_req(ssm, upek2020_ack_frame, sizeof(upek2020_ack_frame),
upektc_img_submit_req(ssm, dev, upek2020_ack_frame, sizeof(upek2020_ack_frame),
upekdev->seq, capture_reqs_cb);
upekdev->seq++;
break;
};
}
static void capture_sm_complete(struct fpi_ssm *ssm)
static void capture_sm_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
{
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct upektc_img_dev *upekdev = fpi_imgdev_get_user_data(dev);
struct fp_img_dev *dev = user_data;
struct upektc_img_dev *upekdev = FP_INSTANCE_DATA(_dev);
int err = fpi_ssm_get_error(ssm);
fp_dbg("Capture completed, %d", err);
@@ -403,13 +357,12 @@ static void capture_sm_complete(struct fpi_ssm *ssm)
static void start_capture(struct fp_img_dev *dev)
{
struct upektc_img_dev *upekdev = fpi_imgdev_get_user_data(dev);
struct fpi_ssm *ssm;
struct upektc_img_dev *upekdev = FP_INSTANCE_DATA(FP_DEV(dev));
fpi_ssm *ssm;
upekdev->image_size = 0;
ssm = fpi_ssm_new(fpi_imgdev_get_dev(dev), capture_run_state, CAPTURE_NUM_STATES);
fpi_ssm_set_user_data(ssm, dev);
ssm = fpi_ssm_new(FP_DEV(dev), capture_run_state, CAPTURE_NUM_STATES, dev);
fpi_ssm_start(ssm, capture_sm_complete);
}
@@ -423,49 +376,49 @@ enum deactivate_states {
static void deactivate_reqs_cb(struct libusb_transfer *transfer)
{
struct fpi_ssm *ssm = transfer->user_data;
fpi_ssm *ssm = transfer->user_data;
if ((transfer->status == LIBUSB_TRANSFER_COMPLETED) &&
(transfer->length == transfer->actual_length)) {
fpi_ssm_jump_to_state(ssm, CAPTURE_READ_DATA);
} else {
fpi_ssm_mark_aborted(ssm, -EIO);
fpi_ssm_mark_failed(ssm, -EIO);
}
}
/* TODO: process response properly */
static void deactivate_read_data_cb(struct libusb_transfer *transfer)
{
struct fpi_ssm *ssm = transfer->user_data;
fpi_ssm *ssm = transfer->user_data;
if (transfer->status == LIBUSB_TRANSFER_COMPLETED) {
fpi_ssm_mark_completed(ssm);
} else {
fpi_ssm_mark_aborted(ssm, -EIO);
fpi_ssm_mark_failed(ssm, -EIO);
}
}
static void deactivate_run_state(struct fpi_ssm *ssm)
static void deactivate_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
{
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct upektc_img_dev *upekdev = fpi_imgdev_get_user_data(dev);
struct fp_img_dev *dev = user_data;
struct upektc_img_dev *upekdev = FP_INSTANCE_DATA(_dev);
switch (fpi_ssm_get_cur_state(ssm)) {
case DEACTIVATE_DEINIT:
upektc_img_submit_req(ssm, upek2020_deinit, sizeof(upek2020_deinit),
upektc_img_submit_req(ssm, dev, upek2020_deinit, sizeof(upek2020_deinit),
upekdev->seq, deactivate_reqs_cb);
upekdev->seq++;
break;
case DEACTIVATE_READ_DEINIT_DATA:
upektc_img_read_data(ssm, SHORT_RESPONSE_SIZE, 0, deactivate_read_data_cb);
upektc_img_read_data(ssm, dev, SHORT_RESPONSE_SIZE, 0, deactivate_read_data_cb);
break;
};
}
static void deactivate_sm_complete(struct fpi_ssm *ssm)
static void deactivate_sm_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
{
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct upektc_img_dev *upekdev = fpi_imgdev_get_user_data(dev);
struct fp_img_dev *dev = user_data;
struct upektc_img_dev *upekdev = FP_INSTANCE_DATA(_dev);
int err = fpi_ssm_get_error(ssm);
fp_dbg("Deactivate completed");
@@ -482,13 +435,12 @@ static void deactivate_sm_complete(struct fpi_ssm *ssm)
static void start_deactivation(struct fp_img_dev *dev)
{
struct upektc_img_dev *upekdev = fpi_imgdev_get_user_data(dev);
struct fpi_ssm *ssm;
struct upektc_img_dev *upekdev = FP_INSTANCE_DATA(FP_DEV(dev));
fpi_ssm *ssm;
upekdev->image_size = 0;
ssm = fpi_ssm_new(fpi_imgdev_get_dev(dev), deactivate_run_state, DEACTIVATE_NUM_STATES);
fpi_ssm_set_user_data(ssm, dev);
ssm = fpi_ssm_new(FP_DEV(dev), deactivate_run_state, DEACTIVATE_NUM_STATES, dev);
fpi_ssm_start(ssm, deactivate_sm_complete);
}
@@ -510,45 +462,44 @@ enum activate_states {
static void init_reqs_ctrl_cb(struct libusb_transfer *transfer)
{
struct fpi_ssm *ssm = transfer->user_data;
fpi_ssm *ssm = transfer->user_data;
if (transfer->status == LIBUSB_TRANSFER_COMPLETED) {
fpi_ssm_next_state(ssm);
} else {
fpi_ssm_mark_aborted(ssm, -EIO);
fpi_ssm_mark_failed(ssm, -EIO);
}
}
static void init_reqs_cb(struct libusb_transfer *transfer)
{
struct fpi_ssm *ssm = transfer->user_data;
fpi_ssm *ssm = transfer->user_data;
if ((transfer->status == LIBUSB_TRANSFER_COMPLETED) &&
(transfer->length == transfer->actual_length)) {
fpi_ssm_next_state(ssm);
} else {
fpi_ssm_mark_aborted(ssm, -EIO);
fpi_ssm_mark_failed(ssm, -EIO);
}
}
/* TODO: process response properly */
static void init_read_data_cb(struct libusb_transfer *transfer)
{
struct fpi_ssm *ssm = transfer->user_data;
fpi_ssm *ssm = transfer->user_data;
if (transfer->status == LIBUSB_TRANSFER_COMPLETED) {
fpi_ssm_next_state(ssm);
} else {
fpi_ssm_mark_aborted(ssm, -EIO);
fpi_ssm_mark_failed(ssm, -EIO);
}
}
static void activate_run_state(struct fpi_ssm *ssm)
static void activate_run_state(fpi_ssm *ssm, struct fp_dev *dev, void *user_data)
{
struct libusb_transfer *transfer;
struct fp_img_dev *idev = fpi_ssm_get_user_data(ssm);
struct upektc_img_dev *upekdev = fpi_imgdev_get_user_data(idev);
struct fp_dev *dev = fpi_ssm_get_dev(ssm);
struct fp_img_dev *idev = user_data;
struct upektc_img_dev *upekdev = FP_INSTANCE_DATA(dev);
int r;
switch (fpi_ssm_get_cur_state(ssm)) {
@@ -557,11 +508,7 @@ static void activate_run_state(struct fpi_ssm *ssm)
{
unsigned char *data;
transfer = libusb_alloc_transfer(0);
if (!transfer) {
fpi_ssm_mark_aborted(ssm, -ENOMEM);
break;
}
transfer = fpi_usb_alloc();
transfer->flags |= LIBUSB_TRANSFER_FREE_BUFFER |
LIBUSB_TRANSFER_FREE_TRANSFER;
@@ -574,24 +521,24 @@ static void activate_run_state(struct fpi_ssm *ssm)
if (r < 0) {
g_free(data);
libusb_free_transfer(transfer);
fpi_ssm_mark_aborted(ssm, r);
fpi_ssm_mark_failed(ssm, r);
}
}
break;
case ACTIVATE_INIT_1:
upektc_img_submit_req(ssm, upek2020_init_1, sizeof(upek2020_init_1),
upektc_img_submit_req(ssm, idev, upek2020_init_1, sizeof(upek2020_init_1),
0, init_reqs_cb);
break;
case ACTIVATE_INIT_2:
upektc_img_submit_req(ssm, upek2020_init_2, sizeof(upek2020_init_2),
upektc_img_submit_req(ssm, idev, upek2020_init_2, sizeof(upek2020_init_2),
0, init_reqs_cb);
break;
case ACTIVATE_INIT_3:
upektc_img_submit_req(ssm, upek2020_init_3, sizeof(upek2020_init_3),
upektc_img_submit_req(ssm, idev, upek2020_init_3, sizeof(upek2020_init_3),
0, init_reqs_cb);
break;
case ACTIVATE_INIT_4:
upektc_img_submit_req(ssm, upek2020_init_4, sizeof(upek2020_init_4),
upektc_img_submit_req(ssm, idev, upek2020_init_4, sizeof(upek2020_init_4),
upekdev->seq, init_reqs_cb);
/* Seq should be updated after 4th init */
upekdev->seq++;
@@ -602,14 +549,14 @@ static void activate_run_state(struct fpi_ssm *ssm)
case ACTIVATE_READ_INIT_2_RESP:
case ACTIVATE_READ_INIT_3_RESP:
case ACTIVATE_READ_INIT_4_RESP:
upektc_img_read_data(ssm, SHORT_RESPONSE_SIZE, 0, init_read_data_cb);
upektc_img_read_data(ssm, idev, SHORT_RESPONSE_SIZE, 0, init_read_data_cb);
break;
}
}
static void activate_sm_complete(struct fpi_ssm *ssm)
static void activate_sm_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
{
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct fp_img_dev *dev = user_data;
int err = fpi_ssm_get_error(ssm);
fpi_ssm_free(ssm);
@@ -620,12 +567,11 @@ static void activate_sm_complete(struct fpi_ssm *ssm)
start_capture(dev);
}
static int dev_activate(struct fp_img_dev *dev, enum fp_imgdev_state state)
static int dev_activate(struct fp_img_dev *dev)
{
struct upektc_img_dev *upekdev = fpi_imgdev_get_user_data(dev);
struct fpi_ssm *ssm = fpi_ssm_new(fpi_imgdev_get_dev(dev), activate_run_state,
ACTIVATE_NUM_STATES);
fpi_ssm_set_user_data(ssm, dev);
struct upektc_img_dev *upekdev = FP_INSTANCE_DATA(FP_DEV(dev));
fpi_ssm *ssm = fpi_ssm_new(FP_DEV(dev), activate_run_state,
ACTIVATE_NUM_STATES, dev);
upekdev->seq = 0;
fpi_ssm_start(ssm, activate_sm_complete);
return 0;
@@ -633,7 +579,7 @@ static int dev_activate(struct fp_img_dev *dev, enum fp_imgdev_state state)
static void dev_deactivate(struct fp_img_dev *dev)
{
struct upektc_img_dev *upekdev = fpi_imgdev_get_user_data(dev);
struct upektc_img_dev *upekdev = FP_INSTANCE_DATA(FP_DEV(dev));
upekdev->deactivating = TRUE;
}
@@ -644,23 +590,23 @@ static int dev_init(struct fp_img_dev *dev, unsigned long driver_data)
int r;
struct upektc_img_dev *upekdev;
r = libusb_claim_interface(fpi_imgdev_get_usb_dev(dev), 0);
r = libusb_claim_interface(fpi_dev_get_usb_dev(FP_DEV(dev)), 0);
if (r < 0) {
fp_err("could not claim interface 0: %s", libusb_error_name(r));
return r;
}
upekdev = g_malloc0(sizeof(struct upektc_img_dev));
fpi_imgdev_set_user_data(dev, upekdev);
fp_dev_set_instance_data(FP_DEV(dev), upekdev);
fpi_imgdev_open_complete(dev, 0);
return 0;
}
static void dev_deinit(struct fp_img_dev *dev)
{
struct upektc_img_dev *upekdev = fpi_imgdev_get_user_data(dev);
struct upektc_img_dev *upekdev = FP_INSTANCE_DATA(FP_DEV(dev));
g_free(upekdev);
libusb_release_interface(fpi_imgdev_get_usb_dev(dev), 0);
libusb_release_interface(fpi_dev_get_usb_dev(FP_DEV(dev)), 0);
fpi_imgdev_close_complete(dev);
}

View File

@@ -28,6 +28,8 @@
#define FP_COMPONENT "upekts"
#include "drivers_api.h"
#include "fpi-async.h"
#include "upek_proto.h"
#define EP_IN (1 | LIBUSB_ENDPOINT_IN)
#define EP_OUT (2 | LIBUSB_ENDPOINT_OUT)
@@ -43,49 +45,7 @@ struct upekts_dev {
uint8_t seq; /* FIXME: improve/automate seq handling */
};
static const uint16_t crc_table[256] = {
0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
};
static uint16_t udf_crc(unsigned char *buffer, size_t size)
{
uint16_t crc = 0;
while (size--)
crc = (uint16_t) ((crc << 8) ^
crc_table[((crc >> 8) & 0x00ff) ^ *buffer++]);
return crc;
}
/*
* MESSAGE FORMAT
@@ -131,7 +91,7 @@ static struct libusb_transfer *alloc_send_cmd_transfer(struct fp_dev *dev,
unsigned char seq_a, unsigned char seq_b, const unsigned char *data,
uint16_t len, libusb_transfer_cb_fn callback, void *user_data)
{
struct libusb_transfer *transfer = libusb_alloc_transfer(0);
struct libusb_transfer *transfer = fpi_usb_alloc();
uint16_t crc;
const char *ciao = "Ciao";
@@ -140,9 +100,6 @@ static struct libusb_transfer *alloc_send_cmd_transfer(struct fp_dev *dev,
size_t urblen = len + 9;
unsigned char *buf;
if (!transfer)
return NULL;
if (!data && len > 0) {
fp_err("len>0 but no data?");
return NULL;
@@ -178,7 +135,7 @@ static struct libusb_transfer *alloc_send_cmd28_transfer(struct fp_dev *dev,
uint16_t _innerlen = innerlen;
size_t len = innerlen + 6;
unsigned char *buf = g_malloc0(len);
struct upekts_dev *upekdev = fpi_dev_get_user_data(dev);
struct upekts_dev *upekdev = FP_INSTANCE_DATA(dev);
uint8_t seq = upekdev->seq + CMD_SEQ_INCREMENT;
struct libusb_transfer *ret;
@@ -408,12 +365,9 @@ static void read_msg_cb(struct libusb_transfer *transfer)
* to read the remainder. This is handled below. */
if (len > MAX_DATA_IN_READ_BUF) {
int needed = len - MAX_DATA_IN_READ_BUF;
struct libusb_transfer *etransfer = libusb_alloc_transfer(0);
struct libusb_transfer *etransfer = fpi_usb_alloc();
int r;
if (!transfer)
goto err;
fp_dbg("didn't fit in buffer, need to extend by %d bytes", needed);
data = g_realloc((gpointer) data, MSG_READ_BUF_SIZE + needed);
@@ -448,14 +402,9 @@ out:
static int __read_msg_async(struct read_msg_data *udata)
{
unsigned char *buf = g_malloc(MSG_READ_BUF_SIZE);
struct libusb_transfer *transfer = libusb_alloc_transfer(0);
struct libusb_transfer *transfer = fpi_usb_alloc();
int r;
if (!transfer) {
g_free(buf);
return -ENOMEM;
}
libusb_fill_bulk_transfer(transfer, fpi_dev_get_usb_dev(udata->dev), EP_IN, buf,
MSG_READ_BUF_SIZE, read_msg_cb, udata, TIMEOUT);
r = libusb_submit_transfer(transfer);
@@ -525,25 +474,28 @@ enum initsm_states {
INITSM_NUM_STATES,
};
static void initsm_read_msg_response_cb(struct fpi_ssm *ssm,
enum read_msg_status status, uint8_t seq,
unsigned char expect_subcmd, unsigned char subcmd)
static void
initsm_read_msg_response_cb(fpi_ssm *ssm,
struct fp_dev *dev,
enum read_msg_status status,
uint8_t seq,
unsigned char expect_subcmd,
unsigned char subcmd)
{
struct fp_dev *dev = fpi_ssm_get_dev(ssm);
struct upekts_dev *upekdev = fpi_dev_get_user_data(dev);
struct upekts_dev *upekdev = FP_INSTANCE_DATA(dev);
if (status != READ_MSG_RESPONSE) {
fp_err("expected response, got %d seq=%x in state %d", status, seq,
fpi_ssm_get_cur_state(ssm));
fpi_ssm_mark_aborted(ssm, -1);
fpi_ssm_mark_failed(ssm, -1);
} else if (subcmd != expect_subcmd) {
fp_warn("expected response to subcmd 0x%02x, got response to %02x in "
"state %d", expect_subcmd, subcmd, fpi_ssm_get_cur_state(ssm));
fpi_ssm_mark_aborted(ssm, -1);
fpi_ssm_mark_failed(ssm, -1);
} else if (seq != upekdev->seq) {
fp_err("expected response to cmd seq=%02x, got response to %02x "
"in state %d", upekdev->seq, seq, fpi_ssm_get_cur_state(ssm));
fpi_ssm_mark_aborted(ssm, -1);
fpi_ssm_mark_failed(ssm, -1);
} else {
fp_dbg("state %d completed", fpi_ssm_get_cur_state(ssm));
fpi_ssm_next_state(ssm);
@@ -554,7 +506,7 @@ static void read28_0b_cb(struct fp_dev *dev, enum read_msg_status status,
uint8_t seq, unsigned char subcmd, unsigned char *data, size_t data_len,
void *user_data)
{
initsm_read_msg_response_cb((struct fpi_ssm *) user_data, status, seq,
initsm_read_msg_response_cb((fpi_ssm *) user_data, dev, status, seq,
0x0b, subcmd);
}
@@ -562,7 +514,7 @@ static void read28_0c_cb(struct fp_dev *dev, enum read_msg_status status,
uint8_t seq, unsigned char subcmd, unsigned char *data, size_t data_len,
void *user_data)
{
initsm_read_msg_response_cb((struct fpi_ssm *) user_data, status, seq,
initsm_read_msg_response_cb((fpi_ssm *) user_data, dev, status, seq,
0x0c, subcmd);
}
@@ -570,7 +522,7 @@ static void read28_08_cb(struct fp_dev *dev, enum read_msg_status status,
uint8_t seq, unsigned char subcmd, unsigned char *data, size_t data_len,
void *user_data)
{
initsm_read_msg_response_cb((struct fpi_ssm *) user_data, status, seq,
initsm_read_msg_response_cb((fpi_ssm *) user_data, dev, status, seq,
0x08, subcmd);
}
@@ -578,7 +530,7 @@ static void read28_07_cb(struct fp_dev *dev, enum read_msg_status status,
uint8_t seq, unsigned char subcmd, unsigned char *data, size_t data_len,
void *user_data)
{
initsm_read_msg_response_cb((struct fpi_ssm *) user_data, status, seq,
initsm_read_msg_response_cb((fpi_ssm *) user_data, dev, status, seq,
0x07, subcmd);
}
@@ -586,30 +538,33 @@ static void read28_06_cb(struct fp_dev *dev, enum read_msg_status status,
uint8_t seq, unsigned char subcmd, unsigned char *data, size_t data_len,
void *user_data)
{
initsm_read_msg_response_cb((struct fpi_ssm *) user_data, status, seq,
initsm_read_msg_response_cb((fpi_ssm *) user_data, dev, status, seq,
0x06, subcmd);
}
static void initsm_read_msg_cmd_cb(struct fpi_ssm *ssm,
enum read_msg_status status, uint8_t expect_seq, uint8_t seq)
static void
initsm_read_msg_cmd_cb(fpi_ssm *ssm,
struct fp_dev *dev,
enum read_msg_status status,
uint8_t expect_seq,
uint8_t seq)
{
struct fp_dev *dev = fpi_ssm_get_dev(ssm);
struct upekts_dev *upekdev = fpi_dev_get_user_data(dev);
struct upekts_dev *upekdev = FP_INSTANCE_DATA(dev);
if (status == READ_MSG_ERROR) {
fpi_ssm_mark_aborted(ssm, -1);
fpi_ssm_mark_failed(ssm, -1);
return;
} else if (status != READ_MSG_CMD) {
fp_err("expected command, got %d seq=%x in state %d", status, seq,
fpi_ssm_get_cur_state(ssm));
fpi_ssm_mark_aborted(ssm, -1);
fpi_ssm_mark_failed(ssm, -1);
return;
}
upekdev->seq = seq;
if (seq != expect_seq) {
fp_err("expected seq=%x, got %x in state %d", expect_seq, seq,
fpi_ssm_get_cur_state(ssm));
fpi_ssm_mark_aborted(ssm, -1);
fpi_ssm_mark_failed(ssm, -1);
return;
}
@@ -620,41 +575,43 @@ static void read_msg05_cb(struct fp_dev *dev, enum read_msg_status status,
uint8_t seq, unsigned char subcmd, unsigned char *data, size_t data_len,
void *user_data)
{
initsm_read_msg_cmd_cb((struct fpi_ssm *) user_data, status, 5, seq);
initsm_read_msg_cmd_cb((fpi_ssm *) user_data, dev, status, 5, seq);
}
static void read_msg03_cb(struct fp_dev *dev, enum read_msg_status status,
uint8_t seq, unsigned char subcmd, unsigned char *data, size_t data_len,
void *user_data)
{
initsm_read_msg_cmd_cb((struct fpi_ssm *) user_data, status, 3, seq);
initsm_read_msg_cmd_cb((fpi_ssm *) user_data, dev, status, 3, seq);
}
static void ctrl400_cb(struct libusb_transfer *transfer)
{
struct fpi_ssm *ssm = transfer->user_data;
fpi_ssm *ssm = transfer->user_data;
/* FIXME check length? */
if (transfer->status == LIBUSB_TRANSFER_COMPLETED)
fpi_ssm_next_state(ssm);
else
fpi_ssm_mark_aborted(ssm, -1);
fpi_ssm_mark_failed(ssm, -1);
g_free(transfer->buffer);
libusb_free_transfer(transfer);
}
static void initsm_read_msg_handler(struct fpi_ssm *ssm,
read_msg_cb_fn callback)
static void
initsm_read_msg_handler(fpi_ssm *ssm,
struct fp_dev *dev,
read_msg_cb_fn callback)
{
int r = read_msg_async(fpi_ssm_get_dev(ssm), callback, ssm);
int r = read_msg_async(dev, callback, ssm);
if (r < 0) {
fp_err("async read msg failed in state %d", fpi_ssm_get_cur_state(ssm));
fpi_ssm_mark_aborted(ssm, r);
fpi_ssm_mark_failed(ssm, r);
}
}
static void initsm_send_msg_cb(struct libusb_transfer *transfer)
{
struct fpi_ssm *ssm = transfer->user_data;
fpi_ssm *ssm = transfer->user_data;
if (transfer->status == LIBUSB_TRANSFER_COMPLETED
&& transfer->length == transfer->actual_length) {
fp_dbg("state %d completed", fpi_ssm_get_cur_state(ssm));
@@ -662,22 +619,25 @@ static void initsm_send_msg_cb(struct libusb_transfer *transfer)
} else {
fp_err("failed, state=%d rqlength=%d actual_length=%d", fpi_ssm_get_cur_state(ssm),
transfer->length, transfer->actual_length);
fpi_ssm_mark_aborted(ssm, -1);
fpi_ssm_mark_failed(ssm, -1);
}
libusb_free_transfer(transfer);
}
static void initsm_send_msg28_handler(struct fpi_ssm *ssm,
unsigned char subcmd, const unsigned char *data, uint16_t innerlen)
static void
initsm_send_msg28_handler(fpi_ssm *ssm,
struct fp_dev *dev,
unsigned char subcmd,
const unsigned char *data,
uint16_t innerlen)
{
struct fp_dev *dev = fpi_ssm_get_dev(ssm);
struct libusb_transfer *transfer;
int r;
transfer = alloc_send_cmd28_transfer(dev, subcmd, data, innerlen,
initsm_send_msg_cb, ssm);
if (!transfer) {
fpi_ssm_mark_aborted(ssm, -ENOMEM);
fpi_ssm_mark_failed(ssm, -ENOMEM);
return;
}
@@ -686,14 +646,13 @@ static void initsm_send_msg28_handler(struct fpi_ssm *ssm,
fp_err("urb submission failed error %d in state %d", r, fpi_ssm_get_cur_state(ssm));
g_free(transfer->buffer);
libusb_free_transfer(transfer);
fpi_ssm_mark_aborted(ssm, -EIO);
fpi_ssm_mark_failed(ssm, -EIO);
}
}
static void initsm_run_state(struct fpi_ssm *ssm)
static void initsm_run_state(fpi_ssm *ssm, struct fp_dev *dev, void *user_data)
{
struct fp_dev *dev = fpi_ssm_get_dev(ssm);
struct upekts_dev *upekdev = fpi_dev_get_user_data(dev);
struct upekts_dev *upekdev = FP_INSTANCE_DATA(dev);
struct libusb_transfer *transfer;
int r;
@@ -701,12 +660,7 @@ static void initsm_run_state(struct fpi_ssm *ssm)
case WRITE_CTRL400: ;
unsigned char *data;
transfer = libusb_alloc_transfer(0);
if (!transfer) {
fpi_ssm_mark_aborted(ssm, -ENOMEM);
break;
}
transfer = fpi_usb_alloc();
data = g_malloc(LIBUSB_CONTROL_SETUP_SIZE + 1);
libusb_fill_control_setup(data,
LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE, 0x0c, 0x100, 0x0400, 1);
@@ -717,17 +671,17 @@ static void initsm_run_state(struct fpi_ssm *ssm)
if (r < 0) {
g_free(data);
libusb_free_transfer(transfer);
fpi_ssm_mark_aborted(ssm, r);
fpi_ssm_mark_failed(ssm, r);
}
break;
case READ_MSG03:
initsm_read_msg_handler(ssm, read_msg03_cb);
initsm_read_msg_handler(ssm, dev, read_msg03_cb);
break;
case SEND_RESP03: ;
transfer = alloc_send_cmdresponse_transfer(dev, ++upekdev->seq,
init_resp03, sizeof(init_resp03), initsm_send_msg_cb, ssm);
if (!transfer) {
fpi_ssm_mark_aborted(ssm, -ENOMEM);
fpi_ssm_mark_failed(ssm, -ENOMEM);
break;
}
@@ -735,51 +689,52 @@ static void initsm_run_state(struct fpi_ssm *ssm)
if (r < 0) {
g_free(transfer->buffer);
libusb_free_transfer(transfer);
fpi_ssm_mark_aborted(ssm, r);
fpi_ssm_mark_failed(ssm, r);
}
break;
case READ_MSG05:
initsm_read_msg_handler(ssm, read_msg05_cb);
initsm_read_msg_handler(ssm, dev, read_msg05_cb);
break;
case SEND28_06: ;
unsigned char dummy28_06 = 0x04;
upekdev->seq = 0xf0;
initsm_send_msg28_handler(ssm, 0x06, &dummy28_06, 1);
initsm_send_msg28_handler(ssm, dev, 0x06, &dummy28_06, 1);
break;
case READ28_06:
initsm_read_msg_handler(ssm, read28_06_cb);
initsm_read_msg_handler(ssm, dev, read28_06_cb);
break;
case SEND28_07: ;
unsigned char dummy28_07 = 0x04;
initsm_send_msg28_handler(ssm, 0x07, &dummy28_07, 1);
initsm_send_msg28_handler(ssm, dev, 0x07, &dummy28_07, 1);
break;
case READ28_07:
initsm_read_msg_handler(ssm, read28_07_cb);
initsm_read_msg_handler(ssm, dev, read28_07_cb);
break;
case SEND28_08:
initsm_send_msg28_handler(ssm, 0x08, init28_08, sizeof(init28_08));
initsm_send_msg28_handler(ssm, dev, 0x08, init28_08, sizeof(init28_08));
break;
case READ28_08:
initsm_read_msg_handler(ssm, read28_08_cb);
initsm_read_msg_handler(ssm, dev, read28_08_cb);
break;
case SEND28_0C:
initsm_send_msg28_handler(ssm, 0x0c, init28_0c, sizeof(init28_0c));
initsm_send_msg28_handler(ssm, dev, 0x0c, init28_0c, sizeof(init28_0c));
break;
case READ28_0C:
initsm_read_msg_handler(ssm, read28_0c_cb);
initsm_read_msg_handler(ssm, dev, read28_0c_cb);
break;
case SEND28_0B:
initsm_send_msg28_handler(ssm, 0x0b, init28_0b, sizeof(init28_0b));
initsm_send_msg28_handler(ssm, dev, 0x0b, init28_0b, sizeof(init28_0b));
break;
case READ28_0B:
initsm_read_msg_handler(ssm, read28_0b_cb);
initsm_read_msg_handler(ssm, dev, read28_0b_cb);
break;
}
}
static struct fpi_ssm *initsm_new(struct fp_dev *dev)
static fpi_ssm *initsm_new(struct fp_dev *dev,
void *user_data)
{
return fpi_ssm_new(dev, initsm_run_state, INITSM_NUM_STATES);
return fpi_ssm_new(dev, initsm_run_state, INITSM_NUM_STATES, user_data);
}
enum deinitsm_states {
@@ -790,11 +745,11 @@ enum deinitsm_states {
static void send_resp07_cb(struct libusb_transfer *transfer)
{
struct fpi_ssm *ssm = transfer->user_data;
fpi_ssm *ssm = transfer->user_data;
if (transfer->status != LIBUSB_TRANSFER_COMPLETED)
fpi_ssm_mark_aborted(ssm, -EIO);
fpi_ssm_mark_failed(ssm, -EIO);
else if (transfer->length != transfer->actual_length)
fpi_ssm_mark_aborted(ssm, -EPROTO);
fpi_ssm_mark_failed(ssm, -EPROTO);
else
fpi_ssm_next_state(ssm);
libusb_free_transfer(transfer);
@@ -804,30 +759,29 @@ static void read_msg01_cb(struct fp_dev *dev, enum read_msg_status status,
uint8_t seq, unsigned char subcmd, unsigned char *data, size_t data_len,
void *user_data)
{
struct fpi_ssm *ssm = user_data;
struct upekts_dev *upekdev = fpi_dev_get_user_data(dev);
fpi_ssm *ssm = user_data;
struct upekts_dev *upekdev = FP_INSTANCE_DATA(dev);
if (status == READ_MSG_ERROR) {
fpi_ssm_mark_aborted(ssm, -1);
fpi_ssm_mark_failed(ssm, -1);
return;
} else if (status != READ_MSG_CMD) {
fp_err("expected command, got %d seq=%x", status, seq);
fpi_ssm_mark_aborted(ssm, -1);
fpi_ssm_mark_failed(ssm, -1);
return;
}
upekdev->seq = seq;
if (seq != 1) {
fp_err("expected seq=1, got %x", seq);
fpi_ssm_mark_aborted(ssm, -1);
fpi_ssm_mark_failed(ssm, -1);
return;
}
fpi_ssm_next_state(ssm);
}
static void deinitsm_state_handler(struct fpi_ssm *ssm)
static void deinitsm_state_handler(fpi_ssm *ssm, struct fp_dev *dev, void *user_data)
{
struct fp_dev *dev = fpi_ssm_get_dev(ssm);
int r;
switch (fpi_ssm_get_cur_state(ssm)) {
@@ -838,7 +792,7 @@ static void deinitsm_state_handler(struct fpi_ssm *ssm)
transfer = alloc_send_cmdresponse_transfer(dev, 0x07, &dummy, 1,
send_resp07_cb, ssm);
if (!transfer) {
fpi_ssm_mark_aborted(ssm, -ENOMEM);
fpi_ssm_mark_failed(ssm, -ENOMEM);
break;
}
@@ -846,20 +800,20 @@ static void deinitsm_state_handler(struct fpi_ssm *ssm)
if (r < 0) {
g_free(transfer->buffer);
libusb_free_transfer(transfer);
fpi_ssm_mark_aborted(ssm, r);
fpi_ssm_mark_failed(ssm, r);
}
break;
case READ_MSG01: ;
r = read_msg_async(dev, read_msg01_cb, ssm);
if (r < 0)
fpi_ssm_mark_aborted(ssm, r);
fpi_ssm_mark_failed(ssm, r);
break;
}
}
static struct fpi_ssm *deinitsm_new(struct fp_dev *dev)
static fpi_ssm *deinitsm_new(struct fp_dev *dev)
{
return fpi_ssm_new(dev, deinitsm_state_handler, DEINITSM_NUM_STATES);
return fpi_ssm_new(dev, deinitsm_state_handler, DEINITSM_NUM_STATES, NULL);
}
static int dev_init(struct fp_dev *dev, unsigned long driver_data)
@@ -875,7 +829,7 @@ static int dev_init(struct fp_dev *dev, unsigned long driver_data)
upekdev = g_malloc(sizeof(*upekdev));
upekdev->seq = 0xf0; /* incremented to 0x00 before first cmd */
fpi_dev_set_user_data(dev, upekdev);
fp_dev_set_instance_data(dev, upekdev);
fpi_dev_set_nr_enroll_stages(dev, 3);
fpi_drvcb_open_complete(dev, 0);
@@ -884,10 +838,10 @@ static int dev_init(struct fp_dev *dev, unsigned long driver_data)
static void dev_exit(struct fp_dev *dev)
{
void *user_data;
struct upekts_dev *upekdev = FP_INSTANCE_DATA(dev);
libusb_release_interface(fpi_dev_get_usb_dev(dev), 0);
user_data = fpi_dev_get_user_data(dev);
g_free(user_data);
g_free(upekdev);
fpi_drvcb_close_complete(dev);
}
@@ -909,14 +863,14 @@ enum enroll_start_sm_states {
};
/* Called when the device initialization state machine completes */
static void enroll_start_sm_cb_initsm(struct fpi_ssm *initsm)
static void enroll_start_sm_cb_initsm(fpi_ssm *initsm, struct fp_dev *_dev, void *user_data)
{
struct fpi_ssm *enroll_start_ssm = fpi_ssm_get_user_data(initsm);
fpi_ssm *enroll_start_ssm = user_data;
int error = fpi_ssm_get_error(initsm);
fpi_ssm_free(initsm);
if (error)
fpi_ssm_mark_aborted(enroll_start_ssm, error);
fpi_ssm_mark_failed(enroll_start_ssm, error);
else
fpi_ssm_next_state(enroll_start_ssm);
}
@@ -924,11 +878,11 @@ static void enroll_start_sm_cb_initsm(struct fpi_ssm *initsm)
/* called when enroll init URB has completed */
static void enroll_start_sm_cb_init(struct libusb_transfer *transfer)
{
struct fpi_ssm *ssm = transfer->user_data;
fpi_ssm *ssm = transfer->user_data;
if (transfer->status != LIBUSB_TRANSFER_COMPLETED)
fpi_ssm_mark_aborted(ssm, -EIO);
fpi_ssm_mark_failed(ssm, -EIO);
else if (transfer->length != transfer->actual_length)
fpi_ssm_mark_aborted(ssm, -EPROTO);
fpi_ssm_mark_failed(ssm, -EPROTO);
else
fpi_ssm_next_state(ssm);
libusb_free_transfer(transfer);
@@ -938,34 +892,32 @@ static void enroll_start_sm_cb_msg28(struct fp_dev *dev,
enum read_msg_status status, uint8_t seq, unsigned char subcmd,
unsigned char *data, size_t data_len, void *user_data)
{
struct upekts_dev *upekdev = fpi_dev_get_user_data(dev);
struct fpi_ssm *ssm = user_data;
struct upekts_dev *upekdev = FP_INSTANCE_DATA(dev);
fpi_ssm *ssm = user_data;
if (status != READ_MSG_RESPONSE) {
fp_err("expected response, got %d seq=%x", status, seq);
fpi_ssm_mark_aborted(ssm, -1);
fpi_ssm_mark_failed(ssm, -1);
} else if (subcmd != 0) {
fp_warn("expected response to subcmd 0, got response to %02x",
subcmd);
fpi_ssm_mark_aborted(ssm, -1);
fpi_ssm_mark_failed(ssm, -1);
} else if (seq != upekdev->seq) {
fp_err("expected response to cmd seq=%02x, got response to %02x",
upekdev->seq, seq);
fpi_ssm_mark_aborted(ssm, -1);
fpi_ssm_mark_failed(ssm, -1);
} else {
fpi_ssm_next_state(ssm);
}
}
static void enroll_start_sm_run_state(struct fpi_ssm *ssm)
static void enroll_start_sm_run_state(fpi_ssm *ssm, struct fp_dev *dev, void *user_data)
{
struct fp_dev *dev = fpi_ssm_get_dev(ssm);
int r;
switch (fpi_ssm_get_cur_state(ssm)) {
case RUN_INITSM: ;
struct fpi_ssm *initsm = initsm_new(dev);
fpi_ssm_set_user_data(initsm, ssm);
fpi_ssm *initsm = initsm_new(dev, ssm);
fpi_ssm_start(initsm, enroll_start_sm_cb_initsm);
break;
case ENROLL_INIT: ;
@@ -973,7 +925,7 @@ static void enroll_start_sm_run_state(struct fpi_ssm *ssm)
transfer = alloc_send_cmd28_transfer(dev, 0x02, enroll_init,
sizeof(enroll_init), enroll_start_sm_cb_init, ssm);
if (!transfer) {
fpi_ssm_mark_aborted(ssm, -ENOMEM);
fpi_ssm_mark_failed(ssm, -ENOMEM);
break;
}
@@ -981,7 +933,7 @@ static void enroll_start_sm_run_state(struct fpi_ssm *ssm)
if (r < 0) {
g_free(transfer->buffer);
libusb_free_transfer(transfer);
fpi_ssm_mark_aborted(ssm, r);
fpi_ssm_mark_failed(ssm, r);
}
break;
case READ_ENROLL_MSG28: ;
@@ -991,7 +943,7 @@ static void enroll_start_sm_run_state(struct fpi_ssm *ssm)
* include a 30 01 poll somewhere? */
r = read_msg_async(dev, enroll_start_sm_cb_msg28, ssm);
if (r < 0)
fpi_ssm_mark_aborted(ssm, r);
fpi_ssm_mark_failed(ssm, r);
break;
}
}
@@ -1001,7 +953,7 @@ static void enroll_iterate(struct fp_dev *dev);
static void e_handle_resp00(struct fp_dev *dev, unsigned char *data,
size_t data_len)
{
struct upekts_dev *upekdev = fpi_dev_get_user_data(dev);
struct upekts_dev *upekdev = FP_INSTANCE_DATA(dev);
unsigned char status;
int result = 0;
@@ -1090,7 +1042,7 @@ static void e_handle_resp02(struct fp_dev *dev, unsigned char *data,
item = fpi_print_data_item_new(data_len - sizeof(scan_comp));
memcpy(item->data, data + sizeof(scan_comp),
data_len - sizeof(scan_comp));
fdata->prints = g_slist_prepend(fdata->prints, item);
fpi_print_data_add_item(fdata, item);
result = FP_ENROLL_COMPLETE;
}
@@ -1153,9 +1105,8 @@ static void enroll_iterate(struct fp_dev *dev)
}
}
static void enroll_started(struct fpi_ssm *ssm)
static void enroll_started(fpi_ssm *ssm, struct fp_dev *dev, void *user_data)
{
struct fp_dev *dev = fpi_ssm_get_dev(ssm);
fpi_drvcb_enroll_started(dev, fpi_ssm_get_error(ssm));
if (!fpi_ssm_get_error(ssm))
@@ -1166,41 +1117,41 @@ static void enroll_started(struct fpi_ssm *ssm)
static int enroll_start(struct fp_dev *dev)
{
struct upekts_dev *upekdev = fpi_dev_get_user_data(dev);
struct upekts_dev *upekdev = FP_INSTANCE_DATA(dev);
/* do_init state machine first */
struct fpi_ssm *ssm = fpi_ssm_new(dev, enroll_start_sm_run_state,
ENROLL_START_NUM_STATES);
fpi_ssm *ssm = fpi_ssm_new(dev, enroll_start_sm_run_state,
ENROLL_START_NUM_STATES, NULL);
upekdev->enroll_passed = FALSE;
fpi_ssm_start(ssm, enroll_started);
return 0;
}
static void enroll_stop_deinit_cb(struct fpi_ssm *ssm)
static void enroll_stop_deinit_cb(fpi_ssm *ssm, struct fp_dev *dev, void *user_data)
{
/* don't really care about errors */
fpi_drvcb_enroll_stopped(fpi_ssm_get_dev(ssm));
fpi_drvcb_enroll_stopped(dev);
fpi_ssm_free(ssm);
}
static int enroll_stop(struct fp_dev *dev)
{
struct fpi_ssm *ssm = deinitsm_new(dev);
fpi_ssm *ssm = deinitsm_new(dev);
fpi_ssm_start(ssm, enroll_stop_deinit_cb);
return 0;
}
static void verify_stop_deinit_cb(struct fpi_ssm *ssm)
static void verify_stop_deinit_cb(fpi_ssm *ssm, struct fp_dev *dev, void *user_data)
{
/* don't really care about errors */
fpi_drvcb_verify_stopped(fpi_ssm_get_dev(ssm));
fpi_drvcb_verify_stopped(dev);
fpi_ssm_free(ssm);
}
static void do_verify_stop(struct fp_dev *dev)
{
struct fpi_ssm *ssm = deinitsm_new(dev);
fpi_ssm *ssm = deinitsm_new(dev);
fpi_ssm_start(ssm, verify_stop_deinit_cb);
}
@@ -1217,14 +1168,14 @@ enum {
};
/* Called when the device initialization state machine completes */
static void verify_start_sm_cb_initsm(struct fpi_ssm *initsm)
static void verify_start_sm_cb_initsm(fpi_ssm *initsm, struct fp_dev *_dev, void *user_data)
{
struct fpi_ssm *verify_start_ssm = fpi_ssm_get_user_data(initsm);
fpi_ssm *verify_start_ssm = user_data;
int err;
err = fpi_ssm_get_error(initsm);
if (err)
fpi_ssm_mark_aborted(verify_start_ssm, err);
fpi_ssm_mark_failed(verify_start_ssm, err);
else
fpi_ssm_next_state(verify_start_ssm);
fpi_ssm_free(initsm);
@@ -1232,30 +1183,28 @@ static void verify_start_sm_cb_initsm(struct fpi_ssm *initsm)
static void verify_init_2803_cb(struct libusb_transfer *transfer)
{
struct fpi_ssm *ssm = transfer->user_data;
fpi_ssm *ssm = transfer->user_data;
if (transfer->status != LIBUSB_TRANSFER_COMPLETED)
fpi_ssm_mark_aborted(ssm, -EIO);
fpi_ssm_mark_failed(ssm, -EIO);
else if (transfer->length != transfer->actual_length)
fpi_ssm_mark_aborted(ssm, -EPROTO);
fpi_ssm_mark_failed(ssm, -EPROTO);
else
fpi_ssm_next_state(ssm);
libusb_free_transfer(transfer);
}
static void verify_start_sm_run_state(struct fpi_ssm *ssm)
static void verify_start_sm_run_state(fpi_ssm *ssm, struct fp_dev *dev, void *user_data)
{
struct fp_dev *dev = fpi_ssm_get_dev(ssm);
int r;
switch (fpi_ssm_get_cur_state(ssm)) {
case VERIFY_RUN_INITSM: ;
struct fpi_ssm *initsm = initsm_new(dev);
fpi_ssm_set_user_data(initsm, ssm);
fpi_ssm *initsm = initsm_new(dev, ssm);
fpi_ssm_start(initsm, verify_start_sm_cb_initsm);
break;
case VERIFY_INIT: ;
struct fp_print_data *print = fpi_dev_get_verify_data(dev);
struct fp_print_data_item *item = print->prints->data;
struct fp_print_data_item *item = fpi_print_data_get_item(print);
size_t data_len = sizeof(verify_hdr) + item->length;
unsigned char *data = g_malloc(data_len);
struct libusb_transfer *transfer;
@@ -1266,7 +1215,7 @@ static void verify_start_sm_run_state(struct fpi_ssm *ssm)
verify_init_2803_cb, ssm);
g_free(data);
if (!transfer) {
fpi_ssm_mark_aborted(ssm, -ENOMEM);
fpi_ssm_mark_failed(ssm, -ENOMEM);
break;
}
@@ -1274,7 +1223,7 @@ static void verify_start_sm_run_state(struct fpi_ssm *ssm)
if (r < 0) {
g_free(transfer->buffer);
libusb_free_transfer(transfer);
fpi_ssm_mark_aborted(ssm, -EIO);
fpi_ssm_mark_failed(ssm, -EIO);
}
break;
}
@@ -1360,7 +1309,7 @@ static void verify_rd2800_cb(struct fp_dev *dev, enum read_msg_status msgstat,
uint8_t seq, unsigned char subcmd, unsigned char *data, size_t data_len,
void *user_data)
{
struct upekts_dev *upekdev = fpi_dev_get_user_data(dev);
struct upekts_dev *upekdev = FP_INSTANCE_DATA(dev);
if (msgstat != READ_MSG_RESPONSE) {
fp_err("expected response, got %d seq=%x", msgstat, seq);
@@ -1399,7 +1348,7 @@ static void verify_wr2800_cb(struct libusb_transfer *transfer)
static void verify_iterate(struct fp_dev *dev)
{
struct upekts_dev *upekdev = fpi_dev_get_user_data(dev);
struct upekts_dev *upekdev = FP_INSTANCE_DATA(dev);
if (upekdev->stop_verify) {
do_verify_stop(dev);
@@ -1432,10 +1381,9 @@ static void verify_iterate(struct fp_dev *dev)
}
}
static void verify_started(struct fpi_ssm *ssm)
static void verify_started(fpi_ssm *ssm, struct fp_dev *dev, void *user_data)
{
struct fp_dev *dev = fpi_ssm_get_dev(ssm);
struct upekts_dev *upekdev = fpi_dev_get_user_data(dev);
struct upekts_dev *upekdev = FP_INSTANCE_DATA(dev);
fpi_drvcb_verify_started(dev, fpi_ssm_get_error(ssm));
if (!fpi_ssm_get_error(ssm)) {
@@ -1448,9 +1396,9 @@ static void verify_started(struct fpi_ssm *ssm)
static int verify_start(struct fp_dev *dev)
{
struct upekts_dev *upekdev = fpi_dev_get_user_data(dev);
struct fpi_ssm *ssm = fpi_ssm_new(dev, verify_start_sm_run_state,
VERIFY_NUM_STATES);
struct upekts_dev *upekdev = FP_INSTANCE_DATA(dev);
fpi_ssm *ssm = fpi_ssm_new(dev, verify_start_sm_run_state,
VERIFY_NUM_STATES, NULL);
upekdev->stop_verify = FALSE;
fpi_ssm_start(ssm, verify_started);
return 0;
@@ -1458,7 +1406,7 @@ static int verify_start(struct fp_dev *dev)
static int verify_stop(struct fp_dev *dev, gboolean iterating)
{
struct upekts_dev *upekdev = fpi_dev_get_user_data(dev);
struct upekts_dev *upekdev = FP_INSTANCE_DATA(dev);
if (!iterating)
do_verify_stop(dev);

View File

@@ -120,9 +120,10 @@ struct uru4k_dev {
unsigned char last_reg_rd[16];
unsigned char last_hwstat;
struct libusb_transfer *irq_transfer;
struct libusb_transfer *img_transfer;
fpi_usb_transfer *irq_transfer;
fpi_usb_transfer *img_transfer;
void *img_data;
int img_data_actual_length;
uint16_t img_lines_done, img_block;
uint32_t img_enc_seed;
@@ -135,7 +136,7 @@ struct uru4k_dev {
unsigned char powerup_hwstat;
int scanpwr_irq_timeouts;
struct fpi_timeout *scanpwr_irq_timeout;
fpi_timeout *scanpwr_irq_timeout;
int fwfixer_offset;
unsigned char fwfixer_value;
@@ -186,13 +187,10 @@ static int write_regs(struct fp_img_dev *dev, uint16_t first_reg,
void *user_data)
{
struct write_regs_data *wrdata;
struct libusb_transfer *transfer = libusb_alloc_transfer(0);
struct libusb_transfer *transfer = fpi_usb_alloc();
unsigned char *data;
int r;
if (!transfer)
return -ENOMEM;
wrdata = g_malloc(sizeof(*wrdata));
wrdata->dev = dev;
wrdata->callback = callback;
@@ -201,7 +199,7 @@ static int write_regs(struct fp_img_dev *dev, uint16_t first_reg,
data = g_malloc(LIBUSB_CONTROL_SETUP_SIZE + num_regs);
memcpy(data + LIBUSB_CONTROL_SETUP_SIZE, values, num_regs);
libusb_fill_control_setup(data, CTRL_OUT, USB_RQ, first_reg, 0, num_regs);
libusb_fill_control_transfer(transfer, fpi_imgdev_get_usb_dev(dev), data, write_regs_cb,
libusb_fill_control_transfer(transfer, fpi_dev_get_usb_dev(FP_DEV(dev)), data, write_regs_cb,
wrdata, CTRL_TIMEOUT);
r = libusb_submit_transfer(transfer);
@@ -253,13 +251,10 @@ static int read_regs(struct fp_img_dev *dev, uint16_t first_reg,
uint16_t num_regs, read_regs_cb_fn callback, void *user_data)
{
struct read_regs_data *rrdata;
struct libusb_transfer *transfer = libusb_alloc_transfer(0);
struct libusb_transfer *transfer = fpi_usb_alloc();
unsigned char *data;
int r;
if (!transfer)
return -ENOMEM;
rrdata = g_malloc(sizeof(*rrdata));
rrdata->dev = dev;
rrdata->callback = callback;
@@ -267,7 +262,7 @@ static int read_regs(struct fp_img_dev *dev, uint16_t first_reg,
data = g_malloc(LIBUSB_CONTROL_SETUP_SIZE + num_regs);
libusb_fill_control_setup(data, CTRL_IN, USB_RQ, first_reg, 0, num_regs);
libusb_fill_control_transfer(transfer, fpi_imgdev_get_usb_dev(dev), data, read_regs_cb,
libusb_fill_control_transfer(transfer, fpi_dev_get_usb_dev(FP_DEV(dev)), data, read_regs_cb,
rrdata, CTRL_TIMEOUT);
r = libusb_submit_transfer(transfer);
@@ -301,30 +296,30 @@ static int read_regs(struct fp_img_dev *dev, uint16_t first_reg,
*
* BIT 1: IRQ PENDING
* Just had a brainwave. This bit is set when the device is trying to deliver
* and interrupt to the host. Maybe?
* an interrupt to the host. Maybe?
*/
static void response_cb(struct fp_img_dev *dev, int status, void *user_data)
{
struct fpi_ssm *ssm = user_data;
fpi_ssm *ssm = user_data;
if (status == 0)
fpi_ssm_next_state(ssm);
else
fpi_ssm_mark_aborted(ssm, status);
fpi_ssm_mark_failed(ssm, status);
}
static void challenge_cb(struct fp_img_dev *dev, int status,
uint16_t num_regs, unsigned char *data, void *user_data)
{
struct fpi_ssm *ssm = user_data;
struct uru4k_dev *urudev = fpi_imgdev_get_user_data(dev);
fpi_ssm *ssm = user_data;
struct uru4k_dev *urudev = FP_INSTANCE_DATA(FP_DEV(dev));
unsigned char *respdata;
PK11Context *ctx;
int r, outlen;
r = status;
if (status != 0) {
fpi_ssm_mark_aborted(ssm, status);
fpi_ssm_mark_failed(ssm, status);
return;
}
@@ -346,7 +341,7 @@ static void challenge_cb(struct fp_img_dev *dev, int status,
g_free(respdata);
}
if (r < 0)
fpi_ssm_mark_aborted(ssm, r);
fpi_ssm_mark_failed(ssm, r);
}
/*
@@ -354,15 +349,16 @@ static void challenge_cb(struct fp_img_dev *dev, int status,
* authentication scheme, where the device challenges the authenticity of the
* driver.
*/
static void sm_do_challenge_response(struct fpi_ssm *ssm)
static void
sm_do_challenge_response(fpi_ssm *ssm,
struct fp_img_dev *dev)
{
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
int r;
G_DEBUG_HERE();
r = read_regs(dev, REG_CHALLENGE, CR_LENGTH, challenge_cb, ssm);
if (r < 0)
fpi_ssm_mark_aborted(ssm, r);
fpi_ssm_mark_failed(ssm, r);
}
/***** INTERRUPT HANDLING *****/
@@ -371,10 +367,13 @@ static void sm_do_challenge_response(struct fpi_ssm *ssm)
static int start_irq_handler(struct fp_img_dev *dev);
static void irq_handler(struct libusb_transfer *transfer)
static void irq_handler(struct libusb_transfer *transfer,
struct fp_dev *_dev,
fpi_ssm *ssm,
void *user_data)
{
struct fp_img_dev *dev = transfer->user_data;
struct uru4k_dev *urudev = fpi_imgdev_get_user_data(dev);
struct fp_img_dev *dev = FP_IMG_DEV(_dev);
struct uru4k_dev *urudev = FP_INSTANCE_DATA(_dev);
unsigned char *data = transfer->buffer;
uint16_t type;
int r = 0;
@@ -396,8 +395,6 @@ static void irq_handler(struct libusb_transfer *transfer)
type = GUINT16_FROM_BE(*((uint16_t *) data));
fp_dbg("recv irq type %04x", type);
g_free(data);
libusb_free_transfer(transfer);
/* The 0800 interrupt seems to indicate imminent failure (0 bytes transfer)
* of the next scan. It still appears on occasion. */
@@ -413,47 +410,43 @@ static void irq_handler(struct libusb_transfer *transfer)
if (r == 0)
return;
transfer = NULL;
data = NULL;
err:
if (urudev->irq_cb)
urudev->irq_cb(dev, r, 0, urudev->irq_cb_data);
out:
g_free(data);
libusb_free_transfer(transfer);
urudev->irq_transfer = NULL;
}
static int start_irq_handler(struct fp_img_dev *dev)
{
struct uru4k_dev *urudev = fpi_imgdev_get_user_data(dev);
struct libusb_transfer *transfer = libusb_alloc_transfer(0);
struct uru4k_dev *urudev = FP_INSTANCE_DATA(FP_DEV(dev));
fpi_usb_transfer *transfer;
unsigned char *data;
int r;
if (!transfer)
return -ENOMEM;
data = g_malloc(IRQ_LENGTH);
libusb_fill_bulk_transfer(transfer, fpi_imgdev_get_usb_dev(dev), EP_INTR, data, IRQ_LENGTH,
irq_handler, dev, 0);
transfer = fpi_usb_fill_bulk_transfer(FP_DEV(dev),
NULL,
EP_INTR,
data,
IRQ_LENGTH,
irq_handler,
NULL,
0);
urudev->irq_transfer = transfer;
r = libusb_submit_transfer(transfer);
if (r < 0) {
g_free(data);
libusb_free_transfer(transfer);
r = fpi_usb_submit_transfer(transfer);
if (r < 0)
urudev->irq_transfer = NULL;
}
return r;
}
static void stop_irq_handler(struct fp_img_dev *dev, irqs_stopped_cb_fn cb)
{
struct uru4k_dev *urudev = fpi_imgdev_get_user_data(dev);
struct libusb_transfer *transfer = urudev->irq_transfer;
struct uru4k_dev *urudev = FP_INSTANCE_DATA(FP_DEV(dev));
fpi_usb_transfer *transfer = urudev->irq_transfer;
if (transfer) {
libusb_cancel_transfer(transfer);
fpi_usb_cancel_transfer(transfer);
urudev->irqs_stopped_cb = cb;
}
}
@@ -484,7 +477,7 @@ static void change_state_write_reg_cb(struct fp_img_dev *dev, int status,
static int dev_change_state(struct fp_img_dev *dev, enum fp_imgdev_state state)
{
struct uru4k_dev *urudev = fpi_imgdev_get_user_data(dev);
struct uru4k_dev *urudev = FP_INSTANCE_DATA(FP_DEV(dev));
switch (state) {
case IMGDEV_STATE_INACTIVE:
@@ -508,37 +501,43 @@ static int dev_change_state(struct fp_img_dev *dev, enum fp_imgdev_state state)
static void sm_write_reg_cb(struct fp_img_dev *dev, int result, void *user_data)
{
struct fpi_ssm *ssm = user_data;
fpi_ssm *ssm = user_data;
if (result)
fpi_ssm_mark_aborted(ssm, result);
fpi_ssm_mark_failed(ssm, result);
else
fpi_ssm_next_state(ssm);
}
static void sm_write_regs(struct fpi_ssm *ssm, uint16_t first_reg, uint16_t num_regs,
void *data)
static void
sm_write_regs(fpi_ssm *ssm,
struct fp_img_dev *dev,
uint16_t first_reg,
uint16_t num_regs,
void *data)
{
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
int r = write_regs(dev, first_reg, num_regs, data, sm_write_reg_cb, ssm);
if (r < 0)
fpi_ssm_mark_aborted(ssm, r);
fpi_ssm_mark_failed(ssm, r);
}
static void sm_write_reg(struct fpi_ssm *ssm, uint16_t reg,
unsigned char value)
static void
sm_write_reg(fpi_ssm *ssm,
struct fp_img_dev *dev,
uint16_t reg,
unsigned char value)
{
sm_write_regs(ssm, reg, 1, &value);
sm_write_regs(ssm, dev, reg, 1, &value);
}
static void sm_read_reg_cb(struct fp_img_dev *dev, int result,
uint16_t num_regs, unsigned char *data, void *user_data)
{
struct fpi_ssm *ssm = user_data;
struct uru4k_dev *urudev = fpi_imgdev_get_user_data(dev);
fpi_ssm *ssm = user_data;
struct uru4k_dev *urudev = FP_INSTANCE_DATA(FP_DEV(dev));
if (result) {
fpi_ssm_mark_aborted(ssm, result);
fpi_ssm_mark_failed(ssm, result);
} else {
memcpy(urudev->last_reg_rd, data, num_regs);
fp_dbg("reg value %x", urudev->last_reg_rd[0]);
@@ -546,32 +545,42 @@ static void sm_read_reg_cb(struct fp_img_dev *dev, int result,
}
}
static void sm_read_regs(struct fpi_ssm *ssm, uint16_t reg, uint16_t num_regs)
#define member_size(type, member) sizeof(((type *)0)->member)
static void
sm_read_regs(fpi_ssm *ssm,
struct fp_img_dev *dev,
uint16_t reg,
uint16_t num_regs)
{
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct uru4k_dev *urudev = fpi_imgdev_get_user_data(dev);
int r;
if (num_regs > sizeof(urudev->last_reg_rd)) {
fpi_ssm_mark_aborted(ssm, -EIO);
if (num_regs > member_size(struct uru4k_dev, last_reg_rd)) {
fpi_ssm_mark_failed(ssm, -EIO);
return;
}
fp_dbg("read %d regs at %x", num_regs, reg);
r = read_regs(dev, reg, num_regs, sm_read_reg_cb, ssm);
if (r < 0)
fpi_ssm_mark_aborted(ssm, r);
fpi_ssm_mark_failed(ssm, r);
}
static void sm_read_reg(struct fpi_ssm *ssm, uint16_t reg)
static void
sm_read_reg(fpi_ssm *ssm,
struct fp_img_dev *dev,
uint16_t reg)
{
sm_read_regs(ssm, reg, 1);
sm_read_regs(ssm, dev, reg, 1);
}
static void sm_set_hwstat(struct fpi_ssm *ssm, unsigned char value)
static void
sm_set_hwstat(fpi_ssm *ssm,
struct fp_img_dev *dev,
unsigned char value)
{
fp_dbg("set %02x", value);
sm_write_reg(ssm, REG_HWSTAT, value);
sm_write_reg(ssm, dev, REG_HWSTAT, value);
}
/***** IMAGING LOOP *****/
@@ -585,28 +594,6 @@ enum imaging_states {
IMAGING_NUM_STATES
};
static void image_transfer_cb(struct libusb_transfer *transfer)
{
struct fpi_ssm *ssm = transfer->user_data;
if (transfer->status == LIBUSB_TRANSFER_CANCELLED) {
fp_dbg("cancelled");
fpi_ssm_mark_aborted(ssm, -ECANCELED);
} else if (transfer->status != LIBUSB_TRANSFER_COMPLETED) {
fp_dbg("error");
fpi_ssm_mark_aborted(ssm, -EIO);
} else {
fpi_ssm_next_state(ssm);
}
}
enum {
BLOCKF_CHANGE_KEY = 0x80,
BLOCKF_NO_KEY_UPDATE = 0x04,
BLOCKF_ENCRYPTED = 0x02,
BLOCKF_NOT_PRESENT = 0x01,
};
struct uru4k_image {
uint8_t unknown_00[4];
uint16_t num_lines;
@@ -620,6 +607,33 @@ struct uru4k_image {
uint8_t data[IMAGE_HEIGHT][IMAGE_WIDTH];
};
static void image_transfer_cb(struct libusb_transfer *transfer,
struct fp_dev *dev,
fpi_ssm *ssm,
void *user_data)
{
if (transfer->status == LIBUSB_TRANSFER_CANCELLED) {
fp_dbg("cancelled");
fpi_ssm_mark_failed(ssm, -ECANCELED);
} else if (transfer->status != LIBUSB_TRANSFER_COMPLETED) {
fp_dbg("error");
fpi_ssm_mark_failed(ssm, -EIO);
} else {
struct uru4k_dev *urudev = FP_INSTANCE_DATA(dev);
urudev->img_data = g_memdup(transfer->buffer, sizeof(struct uru4k_image));
urudev->img_data_actual_length = transfer->actual_length;
fpi_ssm_next_state(ssm);
}
}
enum {
BLOCKF_CHANGE_KEY = 0x80,
BLOCKF_NO_KEY_UPDATE = 0x04,
BLOCKF_ENCRYPTED = 0x02,
BLOCKF_NOT_PRESENT = 0x01,
};
static uint32_t update_key(uint32_t key)
{
/* linear feedback shift register
@@ -687,35 +701,35 @@ static int calc_dev2(struct uru4k_image *img)
return res / IMAGE_WIDTH;
}
static void imaging_run_state(struct fpi_ssm *ssm)
static void imaging_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
{
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct uru4k_dev *urudev = fpi_imgdev_get_user_data(dev);
struct fp_img_dev *dev = user_data;
struct uru4k_dev *urudev = FP_INSTANCE_DATA(_dev);
struct uru4k_image *img = urudev->img_data;
struct fp_img *fpimg;
uint32_t key;
uint8_t flags, num_lines;
int i, r, to, dev2;
char buf[5];
unsigned char buf[5];
switch (fpi_ssm_get_cur_state(ssm)) {
case IMAGING_CAPTURE:
urudev->img_lines_done = 0;
urudev->img_block = 0;
libusb_fill_bulk_transfer(urudev->img_transfer, fpi_imgdev_get_usb_dev(dev), EP_DATA,
urudev->img_data, sizeof(struct uru4k_image), image_transfer_cb, ssm, 0);
r = libusb_submit_transfer(urudev->img_transfer);
if (r < 0)
fpi_ssm_mark_aborted(ssm, -EIO);
r = fpi_usb_submit_transfer(urudev->img_transfer);
if (r < 0) {
urudev->img_transfer = NULL;
fpi_ssm_mark_failed(ssm, -EIO);
}
break;
case IMAGING_SEND_INDEX:
fp_dbg("hw header lines %d", img->num_lines);
if (img->num_lines >= IMAGE_HEIGHT ||
urudev->img_transfer->actual_length < img->num_lines * IMAGE_WIDTH + 64) {
urudev->img_data_actual_length < img->num_lines * IMAGE_WIDTH + 64) {
fp_err("bad captured image (%d lines) or size mismatch %d < %d",
img->num_lines,
urudev->img_transfer->actual_length,
urudev->img_data_actual_length,
img->num_lines * IMAGE_WIDTH + 64);
fpi_ssm_jump_to_state(ssm, IMAGING_CAPTURE);
return;
@@ -734,10 +748,10 @@ static void imaging_run_state(struct fpi_ssm *ssm)
buf[2] = urudev->img_enc_seed >> 8;
buf[3] = urudev->img_enc_seed >> 16;
buf[4] = urudev->img_enc_seed >> 24;
sm_write_regs(ssm, REG_SCRAMBLE_DATA_INDEX, 5, buf);
sm_write_regs(ssm, dev, REG_SCRAMBLE_DATA_INDEX, 5, buf);
break;
case IMAGING_READ_KEY:
sm_read_regs(ssm, REG_SCRAMBLE_DATA_KEY, 4);
sm_read_regs(ssm, dev, REG_SCRAMBLE_DATA_KEY, 4);
break;
case IMAGING_DECODE:
key = urudev->last_reg_rd[0];
@@ -810,10 +824,10 @@ static void imaging_run_state(struct fpi_ssm *ssm)
}
}
static void imaging_complete(struct fpi_ssm *ssm)
static void imaging_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
{
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct uru4k_dev *urudev = fpi_imgdev_get_user_data(dev);
struct fp_img_dev *dev = user_data;
struct uru4k_dev *urudev = FP_INSTANCE_DATA(_dev);
int r = fpi_ssm_get_error(ssm);
fpi_ssm_free(ssm);
@@ -823,11 +837,12 @@ static void imaging_complete(struct fpi_ssm *ssm)
if (r)
fpi_imgdev_session_error(dev, r);
/* Freed by callback or cancellation */
urudev->img_transfer = NULL;
g_free(urudev->img_data);
urudev->img_data = NULL;
libusb_free_transfer(urudev->img_transfer);
urudev->img_transfer = NULL;
urudev->img_data_actual_length = 0;
r = execute_state_change(dev);
if (r)
@@ -840,7 +855,7 @@ static void imaging_complete(struct fpi_ssm *ssm)
* confused state and returns hwstat 0x85. On next app run, we don't get the
* 56aa interrupt. This is the best way I've found to fix it: mess around
* with hwstat until it starts returning more recognisable values. This
* doesn't happen on my other devices: uru4000, uru4000b, ms fp rdr v2
* doesn't happen on my other devices: uru4000, uru4000b, ms fp rdr v2
*
* The windows driver copes with this OK, but then again it uploads firmware
* right after reading the 0x85 hwstat, allowing some time to pass before it
@@ -860,32 +875,33 @@ enum rebootpwr_states {
REBOOTPWR_NUM_STATES,
};
static void rebootpwr_pause_cb(void *data)
static void
rebootpwr_pause_cb(struct fp_dev *dev,
void *data)
{
struct fpi_ssm *ssm = data;
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct uru4k_dev *urudev = fpi_imgdev_get_user_data(dev);
fpi_ssm *ssm = data;
struct uru4k_dev *urudev = FP_INSTANCE_DATA(dev);
if (!--urudev->rebootpwr_ctr) {
fp_err("could not reboot device power");
fpi_ssm_mark_aborted(ssm, -EIO);
fpi_ssm_mark_failed(ssm, -EIO);
} else {
fpi_ssm_jump_to_state(ssm, REBOOTPWR_GET_HWSTAT);
}
}
static void rebootpwr_run_state(struct fpi_ssm *ssm)
static void rebootpwr_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
{
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct uru4k_dev *urudev = fpi_imgdev_get_user_data(dev);
struct fp_img_dev *dev = user_data;
struct uru4k_dev *urudev = FP_INSTANCE_DATA(_dev);
switch (fpi_ssm_get_cur_state(ssm)) {
case REBOOTPWR_SET_HWSTAT:
urudev->rebootpwr_ctr = 100;
sm_set_hwstat(ssm, urudev->last_hwstat & 0xf);
sm_set_hwstat(ssm, dev, urudev->last_hwstat & 0xf);
break;
case REBOOTPWR_GET_HWSTAT:
sm_read_reg(ssm, REG_HWSTAT);
sm_read_reg(ssm, dev, REG_HWSTAT);
break;
case REBOOTPWR_CHECK_HWSTAT:
urudev->last_hwstat = urudev->last_reg_rd[0];
@@ -895,16 +911,16 @@ static void rebootpwr_run_state(struct fpi_ssm *ssm)
fpi_ssm_next_state(ssm);
break;
case REBOOTPWR_PAUSE:
if (fpi_timeout_add(10, rebootpwr_pause_cb, ssm) == NULL)
fpi_ssm_mark_aborted(ssm, -ETIME);
if (fpi_timeout_add(10, rebootpwr_pause_cb, _dev, ssm) == NULL)
fpi_ssm_mark_failed(ssm, -ETIME);
break;
}
}
/* After messing with the device firmware in it's low-power state, we have to
/* After messing with the device firmware in its low-power state, we have to
* power it back up and wait for interrupt notification. It's not quite as easy
* as that: the combination of both modifying firmware *and* doing C-R auth on
* my ms fp v2 device causes us not to get to get the 56aa interrupt and
* my ms fp v2 device causes us not to get the 56aa interrupt and
* for the hwstat write not to take effect. We have to loop a few times,
* authenticating each time, until the device wakes up.
*
@@ -937,15 +953,16 @@ enum powerup_states {
POWERUP_NUM_STATES,
};
static void powerup_pause_cb(void *data)
static void
powerup_pause_cb(struct fp_dev *dev,
void *data)
{
struct fpi_ssm *ssm = data;
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct uru4k_dev *urudev = fpi_imgdev_get_user_data(dev);
fpi_ssm *ssm = data;
struct uru4k_dev *urudev = FP_INSTANCE_DATA(dev);
if (!--urudev->powerup_ctr) {
fp_err("could not power device up");
fpi_ssm_mark_aborted(ssm, -EIO);
fpi_ssm_mark_failed(ssm, -EIO);
} else if (!urudev->profile->auth_cr) {
fpi_ssm_jump_to_state(ssm, POWERUP_SET_HWSTAT);
} else {
@@ -953,10 +970,10 @@ static void powerup_pause_cb(void *data)
}
}
static void powerup_run_state(struct fpi_ssm *ssm)
static void powerup_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
{
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct uru4k_dev *urudev = fpi_imgdev_get_user_data(dev);
struct fp_img_dev *dev = user_data;
struct uru4k_dev *urudev = FP_INSTANCE_DATA(_dev);
switch (fpi_ssm_get_cur_state(ssm)) {
case POWERUP_INIT:
@@ -965,10 +982,10 @@ static void powerup_run_state(struct fpi_ssm *ssm)
fpi_ssm_next_state(ssm);
break;
case POWERUP_SET_HWSTAT:
sm_set_hwstat(ssm, urudev->powerup_hwstat);
sm_set_hwstat(ssm, dev, urudev->powerup_hwstat);
break;
case POWERUP_GET_HWSTAT:
sm_read_reg(ssm, REG_HWSTAT);
sm_read_reg(ssm, dev, REG_HWSTAT);
break;
case POWERUP_CHECK_HWSTAT:
urudev->last_hwstat = urudev->last_reg_rd[0];
@@ -978,11 +995,11 @@ static void powerup_run_state(struct fpi_ssm *ssm)
fpi_ssm_next_state(ssm);
break;
case POWERUP_PAUSE:
if (fpi_timeout_add(10, powerup_pause_cb, ssm) == NULL)
fpi_ssm_mark_aborted(ssm, -ETIME);
if (fpi_timeout_add(10, powerup_pause_cb, _dev, ssm) == NULL)
fpi_ssm_mark_failed(ssm, -ETIME);
break;
case POWERUP_CHALLENGE_RESPONSE:
sm_do_challenge_response(ssm);
sm_do_challenge_response(ssm, dev);
break;
case POWERUP_CHALLENGE_RESPONSE_SUCCESS:
fpi_ssm_jump_to_state(ssm, POWERUP_SET_HWSTAT);
@@ -1024,11 +1041,11 @@ enum init_states {
static void init_scanpwr_irq_cb(struct fp_img_dev *dev, int status,
uint16_t type, void *user_data)
{
struct fpi_ssm *ssm = user_data;
struct uru4k_dev *urudev = fpi_imgdev_get_user_data(dev);
fpi_ssm *ssm = user_data;
struct uru4k_dev *urudev = FP_INSTANCE_DATA(FP_DEV(dev));
if (status)
fpi_ssm_mark_aborted(ssm, status);
fpi_ssm_mark_failed(ssm, status);
else if (type != IRQDATA_SCANPWR_ON)
fp_dbg("ignoring interrupt");
else if (fpi_ssm_get_cur_state(ssm) != INIT_AWAIT_SCAN_POWER) {
@@ -1040,11 +1057,12 @@ static void init_scanpwr_irq_cb(struct fp_img_dev *dev, int status,
}
}
static void init_scanpwr_timeout(void *user_data)
static void
init_scanpwr_timeout(struct fp_dev *dev,
void *user_data)
{
struct fpi_ssm *ssm = user_data;
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct uru4k_dev *urudev = fpi_imgdev_get_user_data(dev);
fpi_ssm *ssm = user_data;
struct uru4k_dev *urudev = FP_INSTANCE_DATA(dev);
fp_warn("powerup timed out");
urudev->irq_cb = NULL;
@@ -1052,20 +1070,20 @@ static void init_scanpwr_timeout(void *user_data)
if (++urudev->scanpwr_irq_timeouts >= 3) {
fp_err("powerup timed out 3 times, giving up");
fpi_ssm_mark_aborted(ssm, -ETIMEDOUT);
fpi_ssm_mark_failed(ssm, -ETIMEDOUT);
} else {
fpi_ssm_jump_to_state(ssm, INIT_GET_HWSTAT);
}
}
static void init_run_state(struct fpi_ssm *ssm)
static void init_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
{
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct uru4k_dev *urudev = fpi_imgdev_get_user_data(dev);
struct fp_img_dev *dev = user_data;
struct uru4k_dev *urudev = FP_INSTANCE_DATA(_dev);
switch (fpi_ssm_get_cur_state(ssm)) {
case INIT_GET_HWSTAT:
sm_read_reg(ssm, REG_HWSTAT);
sm_read_reg(ssm, dev, REG_HWSTAT);
break;
case INIT_CHECK_HWSTAT_REBOOT:
urudev->last_hwstat = urudev->last_reg_rd[0];
@@ -1075,28 +1093,26 @@ static void init_run_state(struct fpi_ssm *ssm)
fpi_ssm_jump_to_state(ssm, INIT_CHECK_HWSTAT_POWERDOWN);
break;
case INIT_REBOOT_POWER: ;
struct fpi_ssm *rebootsm = fpi_ssm_new(fpi_imgdev_get_dev(dev), rebootpwr_run_state,
REBOOTPWR_NUM_STATES);
fpi_ssm_set_user_data(rebootsm, dev);
fpi_ssm *rebootsm = fpi_ssm_new(FP_DEV(dev), rebootpwr_run_state,
REBOOTPWR_NUM_STATES, dev);
fpi_ssm_start_subsm(ssm, rebootsm);
break;
case INIT_CHECK_HWSTAT_POWERDOWN:
if ((urudev->last_hwstat & 0x80) == 0)
sm_set_hwstat(ssm, urudev->last_hwstat | 0x80);
sm_set_hwstat(ssm, dev, urudev->last_hwstat | 0x80);
else
fpi_ssm_next_state(ssm);
break;
case INIT_POWERUP: ;
if (!IRQ_HANDLER_IS_RUNNING(urudev)) {
fpi_ssm_mark_aborted(ssm, -EIO);
fpi_ssm_mark_failed(ssm, -EIO);
break;
}
urudev->irq_cb_data = ssm;
urudev->irq_cb = init_scanpwr_irq_cb;
struct fpi_ssm *powerupsm = fpi_ssm_new(fpi_imgdev_get_dev(dev), powerup_run_state,
POWERUP_NUM_STATES);
fpi_ssm_set_user_data(powerupsm, dev);
fpi_ssm *powerupsm = fpi_ssm_new(FP_DEV(dev), powerup_run_state,
POWERUP_NUM_STATES, dev);
fpi_ssm_start_subsm(ssm, powerupsm);
break;
case INIT_AWAIT_SCAN_POWER:
@@ -1109,9 +1125,10 @@ static void init_run_state(struct fpi_ssm *ssm)
* so we include this timeout loop to retry the whole process 3 times
* if we don't get an irq any time soon. */
urudev->scanpwr_irq_timeout = fpi_timeout_add(300,
init_scanpwr_timeout, ssm);
init_scanpwr_timeout,
_dev, ssm);
if (!urudev->scanpwr_irq_timeout) {
fpi_ssm_mark_aborted(ssm, -ETIME);
fpi_ssm_mark_failed(ssm, -ETIME);
break;
}
break;
@@ -1125,7 +1142,7 @@ static void init_run_state(struct fpi_ssm *ssm)
fpi_ssm_next_state(ssm);
break;
case INIT_GET_VERSION:
sm_read_regs(ssm, REG_DEVICE_INFO, 16);
sm_read_regs(ssm, dev, REG_DEVICE_INFO, 16);
break;
case INIT_REPORT_VERSION:
/* Likely hardware revision, and firmware version.
@@ -1138,29 +1155,19 @@ static void init_run_state(struct fpi_ssm *ssm)
}
}
static void activate_initsm_complete(struct fpi_ssm *ssm)
static void activate_initsm_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
{
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct fp_img_dev *dev = user_data;
int r = fpi_ssm_get_error(ssm);
fpi_ssm_free(ssm);
if (r) {
fpi_imgdev_activate_complete(dev, r);
return;
}
r = execute_state_change(dev);
fpi_imgdev_activate_complete(dev, r);
}
/* FIXME: having state parameter here is kinda useless, will we ever
* see a scenario where the parameter is useful so early on in the activation
* process? asynchronity means that it'll only be used in a later function
* call. */
static int dev_activate(struct fp_img_dev *dev, enum fp_imgdev_state state)
static int dev_activate(struct fp_img_dev *dev)
{
struct uru4k_dev *urudev = fpi_imgdev_get_user_data(dev);
struct fpi_ssm *ssm;
struct uru4k_dev *urudev = FP_INSTANCE_DATA(FP_DEV(dev));
fpi_ssm *ssm;
int r;
r = start_irq_handler(dev);
@@ -1168,9 +1175,7 @@ static int dev_activate(struct fp_img_dev *dev, enum fp_imgdev_state state)
return r;
urudev->scanpwr_irq_timeouts = 0;
urudev->activate_state = state;
ssm = fpi_ssm_new(fpi_imgdev_get_dev(dev), init_run_state, INIT_NUM_STATES);
fpi_ssm_set_user_data(ssm, dev);
ssm = fpi_ssm_new(FP_DEV(dev), init_run_state, INIT_NUM_STATES, dev);
fpi_ssm_start(ssm, activate_initsm_complete);
return 0;
}
@@ -1195,8 +1200,9 @@ static void dev_deactivate(struct fp_img_dev *dev)
static int execute_state_change(struct fp_img_dev *dev)
{
struct uru4k_dev *urudev = fpi_imgdev_get_user_data(dev);
struct fpi_ssm *ssm;
struct uru4k_dev *urudev = FP_INSTANCE_DATA(FP_DEV(dev));
fpi_ssm *ssm;
void *img_data;
switch (urudev->activate_state) {
case IMGDEV_STATE_INACTIVE:
@@ -1219,12 +1225,18 @@ static int execute_state_change(struct fp_img_dev *dev)
fp_dbg("starting capture");
urudev->irq_cb = NULL;
urudev->img_transfer = libusb_alloc_transfer(0);
urudev->img_data = g_malloc(sizeof(struct uru4k_image));
ssm = fpi_ssm_new(FP_DEV(dev), imaging_run_state, IMAGING_NUM_STATES, dev);
img_data = g_malloc(sizeof(struct uru4k_image));
urudev->img_enc_seed = rand();
urudev->img_transfer = fpi_usb_fill_bulk_transfer(FP_DEV(dev),
ssm,
EP_DATA,
img_data,
sizeof(struct uru4k_image),
image_transfer_cb,
NULL,
0);
ssm = fpi_ssm_new(fpi_imgdev_get_dev(dev), imaging_run_state, IMAGING_NUM_STATES);
fpi_ssm_set_user_data(ssm, dev);
fpi_ssm_start(ssm, imaging_complete);
return write_reg(dev, REG_MODE, MODE_CAPTURE,
@@ -1257,7 +1269,7 @@ static int dev_init(struct fp_img_dev *dev, unsigned long driver_data)
int r;
/* Find fingerprint interface */
r = libusb_get_config_descriptor(libusb_get_device(fpi_imgdev_get_usb_dev(dev)), 0, &config);
r = libusb_get_config_descriptor(libusb_get_device(fpi_dev_get_usb_dev(FP_DEV(dev))), 0, &config);
if (r < 0) {
fp_err("Failed to get config descriptor");
return r;
@@ -1311,12 +1323,15 @@ static int dev_init(struct fp_img_dev *dev, unsigned long driver_data)
/* Device looks like a supported reader */
r = libusb_claim_interface(fpi_imgdev_get_usb_dev(dev), iface_desc->bInterfaceNumber);
r = libusb_claim_interface(fpi_dev_get_usb_dev(FP_DEV(dev)), iface_desc->bInterfaceNumber);
if (r < 0) {
fp_err("interface claim failed: %s", libusb_error_name(r));
goto out;
}
/* Disable loading p11-kit's user configuration */
g_setenv ("P11_KIT_NO_USER_CONFIG", "1", TRUE);
/* Initialise NSS early */
rv = NSS_NoDB_Init(".");
if (rv != SECSuccess) {
@@ -1325,6 +1340,8 @@ static int dev_init(struct fp_img_dev *dev, unsigned long driver_data)
}
urudev = g_malloc0(sizeof(*urudev));
fp_dev_set_instance_data(FP_DEV(dev), urudev);
urudev->profile = &uru4k_dev_info[driver_data];
urudev->interface = iface_desc->bInterfaceNumber;
@@ -1351,7 +1368,6 @@ static int dev_init(struct fp_img_dev *dev, unsigned long driver_data)
}
urudev->param = PK11_ParamFromIV(urudev->cipher, NULL);
fpi_imgdev_set_user_data(dev, urudev);
fpi_imgdev_open_complete(dev, 0);
out:
@@ -1361,14 +1377,14 @@ out:
static void dev_deinit(struct fp_img_dev *dev)
{
struct uru4k_dev *urudev = fpi_imgdev_get_user_data(dev);
struct uru4k_dev *urudev = FP_INSTANCE_DATA(FP_DEV(dev));
if (urudev->symkey)
PK11_FreeSymKey (urudev->symkey);
if (urudev->param)
SECITEM_FreeItem(urudev->param, PR_TRUE);
if (urudev->slot)
PK11_FreeSlot(urudev->slot);
libusb_release_interface(fpi_imgdev_get_usb_dev(dev), urudev->interface);
libusb_release_interface(fpi_dev_get_usb_dev(FP_DEV(dev)), urudev->interface);
g_free(urudev);
fpi_imgdev_close_complete(dev);
}

View File

@@ -74,10 +74,10 @@ enum v5s_cmd {
static void sm_write_reg_cb(struct libusb_transfer *transfer)
{
struct fpi_ssm *ssm = transfer->user_data;
fpi_ssm *ssm = transfer->user_data;
if (transfer->status != LIBUSB_TRANSFER_COMPLETED)
fpi_ssm_mark_aborted(ssm, -EIO);
fpi_ssm_mark_failed(ssm, -EIO);
else
fpi_ssm_next_state(ssm);
@@ -85,38 +85,35 @@ static void sm_write_reg_cb(struct libusb_transfer *transfer)
libusb_free_transfer(transfer);
}
static void sm_write_reg(struct fpi_ssm *ssm, unsigned char reg,
unsigned char value)
static void
sm_write_reg(fpi_ssm *ssm,
struct fp_img_dev *dev,
unsigned char reg,
unsigned char value)
{
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct libusb_transfer *transfer = libusb_alloc_transfer(0);
struct libusb_transfer *transfer = fpi_usb_alloc();
unsigned char *data;
int r;
if (!transfer) {
fpi_ssm_mark_aborted(ssm, -ENOMEM);
return;
}
fp_dbg("set %02x=%02x", reg, value);
data = g_malloc(LIBUSB_CONTROL_SETUP_SIZE);
libusb_fill_control_setup(data, CTRL_OUT, reg, value, 0, 0);
libusb_fill_control_transfer(transfer, fpi_imgdev_get_usb_dev(dev), data, sm_write_reg_cb,
libusb_fill_control_transfer(transfer, fpi_dev_get_usb_dev(FP_DEV(dev)), data, sm_write_reg_cb,
ssm, CTRL_TIMEOUT);
r = libusb_submit_transfer(transfer);
if (r < 0) {
g_free(data);
libusb_free_transfer(transfer);
fpi_ssm_mark_aborted(ssm, r);
fpi_ssm_mark_failed(ssm, r);
}
}
static void sm_exec_cmd_cb(struct libusb_transfer *transfer)
{
struct fpi_ssm *ssm = transfer->user_data;
fpi_ssm *ssm = transfer->user_data;
if (transfer->status != LIBUSB_TRANSFER_COMPLETED)
fpi_ssm_mark_aborted(ssm, -EIO);
fpi_ssm_mark_failed(ssm, -EIO);
else
fpi_ssm_next_state(ssm);
@@ -124,29 +121,26 @@ static void sm_exec_cmd_cb(struct libusb_transfer *transfer)
libusb_free_transfer(transfer);
}
static void sm_exec_cmd(struct fpi_ssm *ssm, unsigned char cmd,
unsigned char param)
static void
sm_exec_cmd(fpi_ssm *ssm,
struct fp_img_dev *dev,
unsigned char cmd,
unsigned char param)
{
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct libusb_transfer *transfer = libusb_alloc_transfer(0);
struct libusb_transfer *transfer = fpi_usb_alloc();
unsigned char *data;
int r;
if (!transfer) {
fpi_ssm_mark_aborted(ssm, -ENOMEM);
return;
}
fp_dbg("cmd %02x param %02x", cmd, param);
data = g_malloc(LIBUSB_CONTROL_SETUP_SIZE);
libusb_fill_control_setup(data, CTRL_IN, cmd, param, 0, 0);
libusb_fill_control_transfer(transfer, fpi_imgdev_get_usb_dev(dev), data, sm_exec_cmd_cb,
libusb_fill_control_transfer(transfer, fpi_dev_get_usb_dev(FP_DEV(dev)), data, sm_exec_cmd_cb,
ssm, CTRL_TIMEOUT);
r = libusb_submit_transfer(transfer);
if (r < 0) {
g_free(data);
libusb_free_transfer(transfer);
fpi_ssm_mark_aborted(ssm, r);
fpi_ssm_mark_failed(ssm, r);
}
}
@@ -187,16 +181,16 @@ static gboolean finger_is_present(unsigned char *data)
/***** IMAGE ACQUISITION *****/
static void capture_iterate(struct fpi_ssm *ssm);
static void capture_iterate(fpi_ssm *ssm, struct fp_img_dev *dev);
static void capture_cb(struct libusb_transfer *transfer)
{
struct fpi_ssm *ssm = transfer->user_data;
fpi_ssm *ssm = transfer->user_data;
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct v5s_dev *vdev = fpi_imgdev_get_user_data(dev);
struct v5s_dev *vdev = FP_INSTANCE_DATA(FP_DEV(dev));
if (transfer->status != LIBUSB_TRANSFER_COMPLETED) {
fpi_ssm_mark_aborted(ssm, -EIO);
fpi_ssm_mark_failed(ssm, -EIO);
goto out;
}
@@ -211,47 +205,44 @@ static void capture_cb(struct libusb_transfer *transfer)
fpi_imgdev_image_captured(dev, img);
fpi_ssm_next_state(ssm);
} else {
capture_iterate(ssm);
capture_iterate(ssm, dev);
}
out:
libusb_free_transfer(transfer);
}
static void capture_iterate(struct fpi_ssm *ssm)
static void
capture_iterate(fpi_ssm *ssm,
struct fp_img_dev *dev)
{
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct v5s_dev *vdev = fpi_imgdev_get_user_data(dev);
struct v5s_dev *vdev = FP_INSTANCE_DATA(FP_DEV(dev));
int iteration = vdev->capture_iteration;
struct libusb_transfer *transfer = libusb_alloc_transfer(0);
struct libusb_transfer *transfer = fpi_usb_alloc();
int r;
if (!transfer) {
fpi_ssm_mark_aborted(ssm, -ENOMEM);
return;
}
libusb_fill_bulk_transfer(transfer, fpi_imgdev_get_usb_dev(dev), EP_IN,
libusb_fill_bulk_transfer(transfer, fpi_dev_get_usb_dev(FP_DEV(dev)), EP_IN,
vdev->capture_img->data + (RQ_SIZE * iteration), RQ_SIZE,
capture_cb, ssm, CTRL_TIMEOUT);
transfer->flags = LIBUSB_TRANSFER_SHORT_NOT_OK;
r = libusb_submit_transfer(transfer);
if (r < 0) {
libusb_free_transfer(transfer);
fpi_ssm_mark_aborted(ssm, r);
fpi_ssm_mark_failed(ssm, r);
}
}
static void sm_do_capture(struct fpi_ssm *ssm)
static void
sm_do_capture(fpi_ssm *ssm,
struct fp_img_dev *dev)
{
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct v5s_dev *vdev = fpi_imgdev_get_user_data(dev);
struct v5s_dev *vdev = FP_INSTANCE_DATA(FP_DEV(dev));
G_DEBUG_HERE();
vdev->capture_img = fpi_img_new_for_imgdev(dev);
vdev->capture_iteration = 0;
capture_iterate(ssm);
capture_iterate(ssm, dev);
}
/***** CAPTURE LOOP *****/
@@ -265,27 +256,27 @@ enum loop_states {
LOOP_NUM_STATES,
};
static void loop_run_state(struct fpi_ssm *ssm)
static void loop_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
{
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct v5s_dev *vdev = fpi_imgdev_get_user_data(dev);
struct fp_img_dev *dev = user_data;
struct v5s_dev *vdev = FP_INSTANCE_DATA(_dev);
switch (fpi_ssm_get_cur_state(ssm)) {
case LOOP_SET_CONTRAST:
sm_write_reg(ssm, REG_CONTRAST, 0x01);
sm_write_reg(ssm, dev, REG_CONTRAST, 0x01);
break;
case LOOP_SET_GAIN:
sm_write_reg(ssm, REG_GAIN, 0x29);
sm_write_reg(ssm, dev, REG_GAIN, 0x29);
break;
case LOOP_CMD_SCAN:
if (vdev->deactivating) {
fp_dbg("deactivating, marking completed");
fpi_ssm_mark_completed(ssm);
} else
sm_exec_cmd(ssm, CMD_SCAN, 0x00);
sm_exec_cmd(ssm, dev, CMD_SCAN, 0x00);
break;
case LOOP_CAPTURE:
sm_do_capture(ssm);
sm_do_capture(ssm, dev);
break;
case LOOP_CAPTURE_DONE:
fpi_ssm_jump_to_state(ssm, LOOP_CMD_SCAN);
@@ -293,10 +284,10 @@ static void loop_run_state(struct fpi_ssm *ssm)
}
}
static void loopsm_complete(struct fpi_ssm *ssm)
static void loopsm_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
{
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct v5s_dev *vdev = fpi_imgdev_get_user_data(dev);
struct fp_img_dev *dev = user_data;
struct v5s_dev *vdev = FP_INSTANCE_DATA(_dev);
int r = fpi_ssm_get_error(ssm);
fpi_ssm_free(ssm);
@@ -311,12 +302,11 @@ static void loopsm_complete(struct fpi_ssm *ssm)
fpi_imgdev_deactivate_complete(dev);
}
static int dev_activate(struct fp_img_dev *dev, enum fp_imgdev_state state)
static int dev_activate(struct fp_img_dev *dev)
{
struct v5s_dev *vdev = fpi_imgdev_get_user_data(dev);
struct fpi_ssm *ssm = fpi_ssm_new(fpi_imgdev_get_dev(dev), loop_run_state,
LOOP_NUM_STATES);
fpi_ssm_set_user_data(ssm, dev);
struct v5s_dev *vdev = FP_INSTANCE_DATA(FP_DEV(dev));
fpi_ssm *ssm = fpi_ssm_new(FP_DEV(dev), loop_run_state,
LOOP_NUM_STATES, dev);
vdev->deactivating = FALSE;
fpi_ssm_start(ssm, loopsm_complete);
vdev->loop_running = TRUE;
@@ -326,7 +316,7 @@ static int dev_activate(struct fp_img_dev *dev, enum fp_imgdev_state state)
static void dev_deactivate(struct fp_img_dev *dev)
{
struct v5s_dev *vdev = fpi_imgdev_get_user_data(dev);
struct v5s_dev *vdev = FP_INSTANCE_DATA(FP_DEV(dev));
if (vdev->loop_running)
vdev->deactivating = TRUE;
else
@@ -339,9 +329,9 @@ static int dev_init(struct fp_img_dev *dev, unsigned long driver_data)
struct v5s_dev *v5s_dev;
v5s_dev = g_malloc0(sizeof(struct v5s_dev));
fpi_imgdev_set_user_data(dev, v5s_dev);
fp_dev_set_instance_data(FP_DEV(dev), v5s_dev);
r = libusb_claim_interface(fpi_imgdev_get_usb_dev(dev), 0);
r = libusb_claim_interface(fpi_dev_get_usb_dev(FP_DEV(dev)), 0);
if (r < 0)
fp_err("could not claim interface 0: %s", libusb_error_name(r));
@@ -354,9 +344,9 @@ static int dev_init(struct fp_img_dev *dev, unsigned long driver_data)
static void dev_deinit(struct fp_img_dev *dev)
{
struct v5s_dev *v5s_dev;
v5s_dev = fpi_imgdev_get_user_data(dev);
v5s_dev = FP_INSTANCE_DATA(FP_DEV(dev));
g_free(v5s_dev);
libusb_release_interface(fpi_imgdev_get_usb_dev(dev), 0);
libusb_release_interface(fpi_dev_get_usb_dev(FP_DEV(dev)), 0);
fpi_imgdev_close_complete(dev);
}

View File

@@ -27,7 +27,7 @@
/* Callback for async_write */
static void async_write_callback(struct libusb_transfer *transfer)
{
struct fpi_ssm *ssm = transfer->user_data;
fpi_ssm *ssm = transfer->user_data;
struct fp_img_dev *idev = fpi_ssm_get_user_data(ssm);
int transferred = transfer->actual_length, error =
@@ -36,14 +36,14 @@ static void async_write_callback(struct libusb_transfer *transfer)
if (error != 0) {
fp_err("USB write transfer: %s", libusb_error_name(error));
fpi_imgdev_session_error(idev, -EIO);
fpi_ssm_mark_aborted(ssm, -EIO);
fpi_ssm_mark_failed(ssm, -EIO);
return;
}
if (transferred != len) {
fp_err("Written only %d of %d bytes", transferred, len);
fpi_imgdev_session_error(idev, -EIO);
fpi_ssm_mark_aborted(ssm, -EIO);
fpi_ssm_mark_failed(ssm, -EIO);
return;
}
@@ -51,13 +51,16 @@ static void async_write_callback(struct libusb_transfer *transfer)
}
/* Send data to EP1, the only out endpoint */
static void async_write(struct fpi_ssm *ssm, void *data, int len)
static void
async_write(fpi_ssm *ssm,
struct fp_img_dev *dev,
void *data,
int len)
{
struct fp_img_dev *idev = fpi_ssm_get_user_data(ssm);
struct libusb_device_handle *usb_dev = fpi_imgdev_get_usb_dev(idev);
struct vfs_dev_t *vdev = fpi_imgdev_get_user_data(idev);
struct libusb_device_handle *usb_dev = fpi_dev_get_usb_dev(FP_DEV(dev));
struct vfs_dev_t *vdev = FP_INSTANCE_DATA(FP_DEV(dev));
vdev->transfer = libusb_alloc_transfer(0);
vdev->transfer = fpi_usb_alloc();
vdev->transfer->flags |= LIBUSB_TRANSFER_FREE_TRANSFER;
libusb_fill_bulk_transfer(vdev->transfer, usb_dev, 0x01, data, len,
async_write_callback, ssm, VFS_USB_TIMEOUT);
@@ -67,7 +70,7 @@ static void async_write(struct fpi_ssm *ssm, void *data, int len)
/* Callback for async_read */
static void async_read_callback(struct libusb_transfer *transfer)
{
struct fpi_ssm *ssm = transfer->user_data;
fpi_ssm *ssm = transfer->user_data;
struct fp_img_dev *idev = fpi_ssm_get_user_data(ssm);
int transferred = transfer->actual_length, error =
@@ -78,14 +81,14 @@ static void async_read_callback(struct libusb_transfer *transfer)
fp_err("USB read transfer on endpoint %d: %s", ep - 0x80,
libusb_error_name(error));
fpi_imgdev_session_error(idev, -EIO);
fpi_ssm_mark_aborted(ssm, -EIO);
fpi_ssm_mark_failed(ssm, -EIO);
return;
}
if (transferred != len) {
fp_err("Received %d instead of %d bytes", transferred, len);
fpi_imgdev_session_error(idev, -EIO);
fpi_ssm_mark_aborted(ssm, -EIO);
fpi_ssm_mark_failed(ssm, -EIO);
return;
}
@@ -93,15 +96,20 @@ static void async_read_callback(struct libusb_transfer *transfer)
}
/* Receive data from the given ep and compare with expected */
static void async_read(struct fpi_ssm *ssm, int ep, void *data, int len)
static void
async_read(fpi_ssm *ssm,
struct fp_img_dev *dev,
int ep,
void *data,
int len)
{
struct fp_img_dev *idev = fpi_ssm_get_user_data(ssm);
struct libusb_device_handle *usb_dev = fpi_imgdev_get_usb_dev(idev);
struct vfs_dev_t *vdev = fpi_imgdev_get_user_data(idev);
struct libusb_device_handle *usb_dev = fpi_dev_get_usb_dev(FP_DEV(idev));
struct vfs_dev_t *vdev = FP_INSTANCE_DATA(FP_DEV(idev));
ep |= LIBUSB_ENDPOINT_IN;
vdev->transfer = libusb_alloc_transfer(0);
vdev->transfer = fpi_usb_alloc();
vdev->transfer->flags |= LIBUSB_TRANSFER_FREE_TRANSFER;
/* 0x83 is the only interrupt endpoint */
@@ -119,7 +127,7 @@ static void async_read(struct fpi_ssm *ssm, int ep, void *data, int len)
/* Callback for async_read */
static void async_abort_callback(struct libusb_transfer *transfer)
{
struct fpi_ssm *ssm = transfer->user_data;
fpi_ssm *ssm = transfer->user_data;
struct fp_img_dev *idev = fpi_ssm_get_user_data(ssm);
int transferred = transfer->actual_length, error = transfer->status;
@@ -134,7 +142,7 @@ static void async_abort_callback(struct libusb_transfer *transfer)
if (error != 0) {
fp_err("USB write transfer: %s", libusb_error_name(error));
fpi_imgdev_session_error(idev, -EIO);
fpi_ssm_mark_aborted(ssm, -EIO);
fpi_ssm_mark_failed(ssm, -EIO);
return;
}
@@ -147,18 +155,18 @@ static void async_abort_callback(struct libusb_transfer *transfer)
}
/* Receive data from the given ep and compare with expected */
static void async_abort(struct fpi_ssm *ssm, int ep)
static void async_abort(fpi_ssm *ssm, int ep)
{
struct fp_img_dev *idev = fpi_ssm_get_user_data(ssm);
struct libusb_device_handle *usb_dev = fpi_imgdev_get_usb_dev(idev);
struct vfs_dev_t *vdev = fpi_imgdev_get_user_data(idev);
struct libusb_device_handle *usb_dev = fpi_dev_get_usb_dev(FP_DEV(idev));
struct vfs_dev_t *vdev = FP_INSTANCE_DATA(FP_DEV(idev));
int len = VFS_USB_BUFFER_SIZE;
unsigned char *data = g_malloc(VFS_USB_BUFFER_SIZE);
ep |= LIBUSB_ENDPOINT_IN;
vdev->transfer = libusb_alloc_transfer(0);
vdev->transfer = fpi_usb_alloc();
vdev->transfer->flags |=
LIBUSB_TRANSFER_FREE_TRANSFER | LIBUSB_TRANSFER_FREE_BUFFER;
@@ -259,7 +267,7 @@ static struct fp_img *prepare_image(struct vfs_dev_t *vdev)
/* Processes and submits image after fingerprint received */
static void submit_image(struct fp_img_dev *idev)
{
struct vfs_dev_t *vdev = fpi_imgdev_get_user_data(idev);
struct vfs_dev_t *vdev = FP_INSTANCE_DATA(FP_DEV(idev));
/* We were not asked to submit image actually */
if (!vdev->active)
@@ -279,20 +287,21 @@ static void submit_image(struct fp_img_dev *idev)
/* Proto functions */
/* SSM loop for clear_ep2 */
static void clear_ep2_ssm(struct fpi_ssm *ssm)
static void
clear_ep2_ssm(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
{
struct fp_img_dev *idev = fpi_ssm_get_user_data(ssm);
struct fp_img_dev *idev = user_data;
short result;
char command04 = 0x04;
switch (fpi_ssm_get_cur_state(ssm)) {
case SUBSM1_COMMAND_04:
async_write(ssm, &command04, sizeof(command04));
async_write(ssm, idev, &command04, sizeof(command04));
break;
case SUBSM1_RETURN_CODE:
async_read(ssm, 1, &result, sizeof(result));
async_read(ssm, idev, 1, &result, sizeof(result));
break;
case SUBSM1_ABORT_2:
@@ -302,36 +311,35 @@ static void clear_ep2_ssm(struct fpi_ssm *ssm)
default:
fp_err("Unknown SUBSM1 state");
fpi_imgdev_session_error(idev, -EIO);
fpi_ssm_mark_aborted(ssm, -EIO);
fpi_ssm_mark_failed(ssm, -EIO);
}
}
/* Send command to clear EP2 */
static void clear_ep2(struct fpi_ssm *ssm)
static void
clear_ep2(fpi_ssm *ssm,
struct fp_img_dev *idev)
{
struct fp_img_dev *idev = fpi_ssm_get_user_data(ssm);
struct fpi_ssm *subsm =
fpi_ssm_new(fpi_imgdev_get_dev(idev), clear_ep2_ssm, SUBSM1_STATES);
fpi_ssm_set_user_data(subsm, idev);
fpi_ssm *subsm =
fpi_ssm_new(FP_DEV(idev), clear_ep2_ssm, SUBSM1_STATES, idev);
fpi_ssm_start_subsm(ssm, subsm);
}
static void send_control_packet_ssm(struct fpi_ssm *ssm)
static void send_control_packet_ssm(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
{
struct fp_img_dev *idev = fpi_ssm_get_user_data(ssm);
struct vfs_dev_t *vdev = fpi_imgdev_get_user_data(idev);
struct fp_img_dev *idev = user_data;
struct vfs_dev_t *vdev = FP_INSTANCE_DATA(_dev);
short result;
unsigned char *commit_result = NULL;
switch (fpi_ssm_get_cur_state(ssm)) {
case SUBSM2_SEND_CONTROL:
async_write(ssm, vdev->control_packet, VFS_CONTROL_PACKET_SIZE);
async_write(ssm, idev, vdev->control_packet, VFS_CONTROL_PACKET_SIZE);
break;
case SUBSM2_RETURN_CODE:
async_read(ssm, 1, &result, sizeof(result));
async_read(ssm, idev, 1, &result, sizeof(result));
break;
case SUBSM2_SEND_COMMIT:
@@ -342,19 +350,19 @@ static void send_control_packet_ssm(struct fpi_ssm *ssm)
break;
}
/* commit_out in Windows differs in each commit, but I send the same each time */
async_write(ssm, commit_out, sizeof(commit_out));
async_write(ssm, idev, commit_out, sizeof(commit_out));
break;
case SUBSM2_COMMIT_RESPONSE:
commit_result = g_malloc(VFS_COMMIT_RESPONSE_SIZE);
async_read(ssm, 1, commit_result, VFS_COMMIT_RESPONSE_SIZE);
async_read(ssm, idev, 1, commit_result, VFS_COMMIT_RESPONSE_SIZE);
break;
case SUBSM2_READ_EMPTY_INTERRUPT:
/* I don't know how to check result, it could be different */
g_free(commit_result);
async_read(ssm, 3, vdev->interrupt, VFS_INTERRUPT_SIZE);
async_read(ssm, idev, 3, vdev->interrupt, VFS_INTERRUPT_SIZE);
break;
case SUBSM2_ABORT_3:
@@ -363,7 +371,7 @@ static void send_control_packet_ssm(struct fpi_ssm *ssm)
(vdev->interrupt, empty_interrupt, VFS_INTERRUPT_SIZE)) {
fp_err("Unknown SUBSM2 state");
fpi_imgdev_session_error(idev, -EIO);
fpi_ssm_mark_aborted(ssm, -EIO);
fpi_ssm_mark_failed(ssm, -EIO);
break;
}
async_abort(ssm, 3);
@@ -372,7 +380,7 @@ static void send_control_packet_ssm(struct fpi_ssm *ssm)
case SUBSM2_CLEAR_EP2:
/* After turn_on Windows doesn't clear EP2 */
if (vdev->control_packet != turn_on)
clear_ep2(ssm);
clear_ep2(ssm, idev);
else
fpi_ssm_next_state(ssm);
break;
@@ -380,18 +388,17 @@ static void send_control_packet_ssm(struct fpi_ssm *ssm)
default:
fp_err("Unknown SUBSM2 state");
fpi_imgdev_session_error(idev, -EIO);
fpi_ssm_mark_aborted(ssm, -EIO);
fpi_ssm_mark_failed(ssm, -EIO);
}
}
/* Send device state control packet */
static void send_control_packet(struct fpi_ssm *ssm)
static void
send_control_packet(fpi_ssm *ssm,
struct fp_img_dev *idev)
{
struct fp_img_dev *idev = fpi_ssm_get_user_data(ssm);
struct fpi_ssm *subsm =
fpi_ssm_new(fpi_imgdev_get_dev(idev), send_control_packet_ssm, SUBSM2_STATES);
fpi_ssm_set_user_data(subsm, idev);
fpi_ssm *subsm =
fpi_ssm_new(FP_DEV(idev), send_control_packet_ssm, SUBSM2_STATES, idev);
fpi_ssm_start_subsm(ssm, subsm);
}
@@ -406,9 +413,9 @@ static void clear_data(struct vfs_dev_t *vdev)
/* After receiving interrupt from EP3 */
static void interrupt_callback(struct libusb_transfer *transfer)
{
struct fpi_ssm *ssm = transfer->user_data;
fpi_ssm *ssm = transfer->user_data;
struct fp_img_dev *idev = fpi_ssm_get_user_data(ssm);
struct vfs_dev_t *vdev = fpi_imgdev_get_user_data(idev);
struct vfs_dev_t *vdev = FP_INSTANCE_DATA(FP_DEV(idev));
char *interrupt = vdev->interrupt;
int error = transfer->status, transferred = transfer->actual_length;
@@ -423,7 +430,7 @@ static void interrupt_callback(struct libusb_transfer *transfer)
fp_err("USB read interrupt transfer: %s",
libusb_error_name(error));
fpi_imgdev_session_error(idev, -EIO);
fpi_ssm_mark_aborted(ssm, -EIO);
fpi_ssm_mark_failed(ssm, -EIO);
return;
}
@@ -432,7 +439,7 @@ static void interrupt_callback(struct libusb_transfer *transfer)
fp_err("Unknown interrupt size %d", transferred);
/* Abort ssm */
fpi_imgdev_session_error(idev, -EIO);
fpi_ssm_mark_aborted(ssm, -EIO);
fpi_ssm_mark_failed(ssm, -EIO);
return;
}
@@ -461,14 +468,14 @@ static void interrupt_callback(struct libusb_transfer *transfer)
/* Abort ssm */
fpi_imgdev_session_error(idev, -EIO);
fpi_ssm_mark_aborted(ssm, -EIO);
fpi_ssm_mark_failed(ssm, -EIO);
}
static void receive_callback(struct libusb_transfer *transfer)
{
struct fpi_ssm *ssm = transfer->user_data;
fpi_ssm *ssm = transfer->user_data;
struct fp_img_dev *idev = fpi_ssm_get_user_data(ssm);
struct vfs_dev_t *vdev = fpi_imgdev_get_user_data(idev);
struct vfs_dev_t *vdev = FP_INSTANCE_DATA(FP_DEV(idev));
int transferred = transfer->actual_length, error = transfer->status;
@@ -476,7 +483,7 @@ static void receive_callback(struct libusb_transfer *transfer)
fp_err("USB read transfer: %s", libusb_error_name(error));
fpi_imgdev_session_error(idev, -EIO);
fpi_ssm_mark_aborted(ssm, -EIO);
fpi_ssm_mark_failed(ssm, -EIO);
return;
}
@@ -492,11 +499,12 @@ static void receive_callback(struct libusb_transfer *transfer)
}
/* Stub to keep SSM alive when waiting an interrupt */
static void wait_interrupt(void *data)
static void
wait_interrupt(struct fp_dev *dev,
void *data)
{
struct fpi_ssm *ssm = data;
struct fp_img_dev *idev = fpi_ssm_get_user_data(ssm);
struct vfs_dev_t *vdev = fpi_imgdev_get_user_data(idev);
fpi_ssm *ssm = data;
struct vfs_dev_t *vdev = FP_INSTANCE_DATA(dev);
/* Keep sleeping while this flag is on */
if (vdev->wait_interrupt)
@@ -504,25 +512,20 @@ static void wait_interrupt(void *data)
}
/* SSM stub to prepare device to another scan after orange light was on */
static void another_scan(void *data)
static void
another_scan(struct fp_dev *dev,
void *data)
{
struct fpi_ssm *ssm = data;
fpi_ssm *ssm = data;
fpi_ssm_jump_to_state(ssm, SSM_TURN_ON);
}
/* Another SSM stub to continue after waiting for probable vdev->active changes */
static void scan_completed(void *data)
{
struct fpi_ssm *ssm = data;
fpi_ssm_next_state(ssm);
}
/* Main SSM loop */
static void activate_ssm(struct fpi_ssm *ssm)
static void activate_ssm(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
{
struct fp_img_dev *idev = fpi_ssm_get_user_data(ssm);
struct libusb_device_handle *usb_dev = fpi_imgdev_get_usb_dev(idev);
struct vfs_dev_t *vdev = fpi_imgdev_get_user_data(idev);
struct fp_img_dev *idev = user_data;
struct libusb_device_handle *usb_dev = fpi_dev_get_usb_dev(FP_DEV(idev));
struct vfs_dev_t *vdev = FP_INSTANCE_DATA(_dev);
switch (fpi_ssm_get_cur_state(ssm)) {
case SSM_INITIAL_ABORT_1:
@@ -538,14 +541,14 @@ static void activate_ssm(struct fpi_ssm *ssm)
break;
case SSM_CLEAR_EP2:
clear_ep2(ssm);
clear_ep2(ssm, idev);
break;
case SSM_TURN_OFF:
/* Set control_packet argument */
vdev->control_packet = turn_off;
send_control_packet(ssm);
send_control_packet(ssm, idev);
break;
case SSM_TURN_ON:
@@ -562,7 +565,7 @@ static void activate_ssm(struct fpi_ssm *ssm)
/* Set control_packet argument */
vdev->control_packet = turn_on;
send_control_packet(ssm);
send_control_packet(ssm, idev);
break;
case SSM_ASK_INTERRUPT:
@@ -575,7 +578,7 @@ static void activate_ssm(struct fpi_ssm *ssm)
}
/* Asyncronously enquire an interrupt */
vdev->transfer = libusb_alloc_transfer(0);
vdev->transfer = fpi_usb_alloc();
vdev->transfer->flags |= LIBUSB_TRANSFER_FREE_TRANSFER;
libusb_fill_interrupt_transfer(vdev->transfer, usb_dev, 0x83,
vdev->interrupt,
@@ -601,7 +604,7 @@ static void activate_ssm(struct fpi_ssm *ssm)
}
if (vdev->wait_interrupt)
fpi_timeout_add(VFS_SSM_TIMEOUT, wait_interrupt, ssm);
fpi_timeout_add(VFS_SSM_TIMEOUT, wait_interrupt, _dev, ssm);
break;
case SSM_RECEIVE_FINGER:
@@ -625,7 +628,7 @@ static void activate_ssm(struct fpi_ssm *ssm)
}
/* Receive chunk of data */
vdev->transfer = libusb_alloc_transfer(0);
vdev->transfer = fpi_usb_alloc();
vdev->transfer->flags |= LIBUSB_TRANSFER_FREE_TRANSFER;
libusb_fill_bulk_transfer(vdev->transfer, usb_dev, 0x82,
(void *)vdev->lines_buffer +
@@ -640,7 +643,7 @@ static void activate_ssm(struct fpi_ssm *ssm)
clear_data(vdev);
/* Wait for probable vdev->active changing */
fpi_timeout_add(VFS_SSM_TIMEOUT, scan_completed, ssm);
fpi_timeout_add(VFS_SSM_TIMEOUT, fpi_ssm_next_state_timeout_cb, _dev, ssm);
break;
case SSM_NEXT_RECEIVE:
@@ -653,28 +656,27 @@ static void activate_ssm(struct fpi_ssm *ssm)
/* Set control_packet argument */
vdev->control_packet = next_receive_1;
send_control_packet(ssm);
send_control_packet(ssm, idev);
break;
case SSM_WAIT_ANOTHER_SCAN:
/* Orange light is on now */
fpi_timeout_add(VFS_SSM_ORANGE_TIMEOUT, another_scan, ssm);
fpi_timeout_add(VFS_SSM_ORANGE_TIMEOUT, another_scan, _dev, ssm);
break;
default:
fp_err("Unknown state");
fpi_imgdev_session_error(idev, -EIO);
fpi_ssm_mark_aborted(ssm, -EIO);
fpi_ssm_mark_failed(ssm, -EIO);
}
}
/* Driver functions */
/* Callback for dev_activate ssm */
static void dev_activate_callback(struct fpi_ssm *ssm)
static void dev_activate_callback(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
{
struct fp_img_dev *idev = fpi_ssm_get_user_data(ssm);
struct vfs_dev_t *vdev = fpi_imgdev_get_user_data(idev);
struct vfs_dev_t *vdev = FP_INSTANCE_DATA(_dev);
vdev->ssm_active = 0;
@@ -682,17 +684,16 @@ static void dev_activate_callback(struct fpi_ssm *ssm)
}
/* Activate device */
static int dev_activate(struct fp_img_dev *idev, enum fp_imgdev_state state)
static int dev_activate(struct fp_img_dev *idev)
{
struct vfs_dev_t *vdev = fpi_imgdev_get_user_data(idev);
struct vfs_dev_t *vdev = FP_INSTANCE_DATA(FP_DEV(idev));
/* Initialize flags */
vdev->active = 1;
vdev->need_report = 1;
vdev->ssm_active = 1;
struct fpi_ssm *ssm = fpi_ssm_new(fpi_imgdev_get_dev(idev), activate_ssm, SSM_STATES);
fpi_ssm_set_user_data(ssm, idev);
fpi_ssm *ssm = fpi_ssm_new(FP_DEV(idev), activate_ssm, SSM_STATES, idev);
fpi_ssm_start(ssm, dev_activate_callback);
return 0;
}
@@ -700,7 +701,7 @@ static int dev_activate(struct fp_img_dev *idev, enum fp_imgdev_state state)
/* Deactivate device */
static void dev_deactivate(struct fp_img_dev *idev)
{
struct vfs_dev_t *vdev = fpi_imgdev_get_user_data(idev);
struct vfs_dev_t *vdev = FP_INSTANCE_DATA(FP_DEV(idev));
if (!vdev->ssm_active) {
fpi_imgdev_deactivate_complete(idev);
@@ -713,10 +714,10 @@ static void dev_deactivate(struct fp_img_dev *idev)
}
/* Callback for dev_open ssm */
static void dev_open_callback(struct fpi_ssm *ssm)
static void dev_open_callback(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
{
/* Notify open complete */
fpi_imgdev_open_complete(fpi_ssm_get_user_data(ssm), 0);
fpi_imgdev_open_complete(user_data, 0);
fpi_ssm_free(ssm);
}
@@ -726,7 +727,7 @@ static int dev_open(struct fp_img_dev *idev, unsigned long driver_data)
struct vfs_dev_t *vdev;
/* Claim usb interface */
int error = libusb_claim_interface(fpi_imgdev_get_usb_dev(idev), 0);
int error = libusb_claim_interface(fpi_dev_get_usb_dev(FP_DEV(idev)), 0);
if (error < 0) {
/* Interface not claimed, return error */
fp_err("could not claim interface 0");
@@ -735,11 +736,10 @@ static int dev_open(struct fp_img_dev *idev, unsigned long driver_data)
/* Initialize private structure */
vdev = g_malloc0(sizeof(struct vfs_dev_t));
fpi_imgdev_set_user_data(idev, vdev);
fp_dev_set_instance_data(FP_DEV(idev), vdev);
/* Clearing previous device state */
struct fpi_ssm *ssm = fpi_ssm_new(fpi_imgdev_get_dev(idev), activate_ssm, SSM_STATES);
fpi_ssm_set_user_data(ssm, idev);
fpi_ssm *ssm = fpi_ssm_new(FP_DEV(idev), activate_ssm, SSM_STATES, idev);
fpi_ssm_start(ssm, dev_open_callback);
return 0;
}
@@ -750,11 +750,11 @@ static void dev_close(struct fp_img_dev *idev)
struct vfs_dev_t *vdev;
/* Release private structure */
vdev = fpi_imgdev_get_user_data(idev);
vdev = FP_INSTANCE_DATA(FP_DEV(idev));
g_free(vdev);
/* Release usb interface */
libusb_release_interface(fpi_imgdev_get_usb_dev(idev), 0);
libusb_release_interface(fpi_dev_get_usb_dev(FP_DEV(idev)), 0);
/* Notify close complete */
fpi_imgdev_close_complete(idev);

View File

@@ -56,7 +56,7 @@
#define VFS_IMG_MIN_IMAGE_LEVEL 144
/* Best image contrast */
#define VFS_IMG_BEST_CONRAST 128
#define VFS_IMG_BEST_CONTRAST 128
/* Device parameters address */
#define VFS_PAR_000E 0x000e
@@ -105,9 +105,6 @@ struct vfs101_dev
/* Ignore usb error */
int ignore_error;
/* Timeout */
struct fpi_timeout *timeout;
/* Loop counter */
int counter;
@@ -199,9 +196,9 @@ static int result_code(struct fp_img_dev *dev, int result)
/* Callback of asynchronous send */
static void async_send_cb(struct libusb_transfer *transfer)
{
struct fpi_ssm *ssm = transfer->user_data;
fpi_ssm *ssm = transfer->user_data;
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct vfs101_dev *vdev = fpi_imgdev_get_user_data(dev);
struct vfs101_dev *vdev = FP_INSTANCE_DATA(FP_DEV(dev));
/* Cleanup transfer */
vdev->transfer = NULL;
@@ -214,7 +211,7 @@ static void async_send_cb(struct libusb_transfer *transfer)
/* Transfer not completed, return IO error */
fp_err("transfer not completed, status = %d", transfer->status);
fpi_imgdev_session_error(dev, -EIO);
fpi_ssm_mark_aborted(ssm, -EIO);
fpi_ssm_mark_failed(ssm, -EIO);
goto out;
}
@@ -224,7 +221,7 @@ static void async_send_cb(struct libusb_transfer *transfer)
fp_err("length mismatch, got %d, expected %d",
transfer->actual_length, transfer->length);
fpi_imgdev_session_error(dev, -EIO);
fpi_ssm_mark_aborted(ssm, -EIO);
fpi_ssm_mark_failed(ssm, -EIO);
goto out;
}
}
@@ -242,22 +239,15 @@ out:
}
/* Submit asynchronous send */
static void async_send(struct fpi_ssm *ssm)
static void
async_send(fpi_ssm *ssm,
struct fp_img_dev *dev)
{
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct vfs101_dev *vdev = fpi_imgdev_get_user_data(dev);
struct vfs101_dev *vdev = FP_INSTANCE_DATA(FP_DEV(dev));
int r;
/* Allocation of transfer */
vdev->transfer = libusb_alloc_transfer(0);
if (!vdev->transfer)
{
/* Allocation transfer failed, return no memory error */
fp_err("allocation of usb transfer failed");
fpi_imgdev_session_error(dev, -ENOMEM);
fpi_ssm_mark_aborted(ssm, -ENOMEM);
return;
}
vdev->transfer = fpi_usb_alloc();
/* Put sequential number into the buffer */
vdev->seqnum++;
@@ -265,7 +255,7 @@ static void async_send(struct fpi_ssm *ssm)
vdev->buffer[1] = byte(1, vdev->seqnum);
/* Prepare bulk transfer */
libusb_fill_bulk_transfer(vdev->transfer, fpi_imgdev_get_usb_dev(dev), EP_OUT(1), vdev->buffer, vdev->length, async_send_cb, ssm, BULK_TIMEOUT);
libusb_fill_bulk_transfer(vdev->transfer, fpi_dev_get_usb_dev(FP_DEV(dev)), EP_OUT(1), vdev->buffer, vdev->length, async_send_cb, ssm, BULK_TIMEOUT);
/* Submit transfer */
r = libusb_submit_transfer(vdev->transfer);
@@ -275,7 +265,7 @@ static void async_send(struct fpi_ssm *ssm)
libusb_free_transfer(vdev->transfer);
fp_err("submit of usb transfer failed");
fpi_imgdev_session_error(dev, -EIO);
fpi_ssm_mark_aborted(ssm, -EIO);
fpi_ssm_mark_failed(ssm, -EIO);
return;
}
}
@@ -283,9 +273,9 @@ static void async_send(struct fpi_ssm *ssm)
/* Callback of asynchronous recv */
static void async_recv_cb(struct libusb_transfer *transfer)
{
struct fpi_ssm *ssm = transfer->user_data;
fpi_ssm *ssm = transfer->user_data;
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct vfs101_dev *vdev = fpi_imgdev_get_user_data(dev);
struct vfs101_dev *vdev = FP_INSTANCE_DATA(FP_DEV(dev));
/* Cleanup transfer */
vdev->transfer = NULL;
@@ -298,7 +288,7 @@ static void async_recv_cb(struct libusb_transfer *transfer)
/* Transfer not completed, return IO error */
fp_err("transfer not completed, status = %d", transfer->status);
fpi_imgdev_session_error(dev, -EIO);
fpi_ssm_mark_aborted(ssm, -EIO);
fpi_ssm_mark_failed(ssm, -EIO);
goto out;
}
@@ -308,7 +298,7 @@ static void async_recv_cb(struct libusb_transfer *transfer)
fp_err("seqnum mismatch, got %04x, expected %04x",
get_seqnum(vdev->buffer[1], vdev->buffer[0]), vdev->seqnum);
fpi_imgdev_session_error(dev, -EIO);
fpi_ssm_mark_aborted(ssm, -EIO);
fpi_ssm_mark_failed(ssm, -EIO);
goto out;
}
}
@@ -329,25 +319,18 @@ out:
}
/* Submit asynchronous recv */
static void async_recv(struct fpi_ssm *ssm)
static void
async_recv(fpi_ssm *ssm,
struct fp_img_dev *dev)
{
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct vfs101_dev *vdev = fpi_imgdev_get_user_data(dev);
struct vfs101_dev *vdev = FP_INSTANCE_DATA(FP_DEV(dev));
int r;
/* Allocation of transfer */
vdev->transfer = libusb_alloc_transfer(0);
if (!vdev->transfer)
{
/* Allocation transfer failed, return no memory error */
fp_err("allocation of usb transfer failed");
fpi_imgdev_session_error(dev, -ENOMEM);
fpi_ssm_mark_aborted(ssm, -ENOMEM);
return;
}
vdev->transfer = fpi_usb_alloc();
/* Prepare bulk transfer */
libusb_fill_bulk_transfer(vdev->transfer, fpi_imgdev_get_usb_dev(dev), EP_IN(1), vdev->buffer, 0x0f, async_recv_cb, ssm, BULK_TIMEOUT);
libusb_fill_bulk_transfer(vdev->transfer, fpi_dev_get_usb_dev(FP_DEV(dev)), EP_IN(1), vdev->buffer, 0x0f, async_recv_cb, ssm, BULK_TIMEOUT);
/* Submit transfer */
r = libusb_submit_transfer(vdev->transfer);
@@ -357,19 +340,19 @@ static void async_recv(struct fpi_ssm *ssm)
libusb_free_transfer(vdev->transfer);
fp_err("submit of usb transfer failed");
fpi_imgdev_session_error(dev, -EIO);
fpi_ssm_mark_aborted(ssm, -EIO);
fpi_ssm_mark_failed(ssm, -EIO);
return;
}
}
static void async_load(struct fpi_ssm *ssm);
static void async_load(fpi_ssm *ssm, struct fp_img_dev *dev);
/* Callback of asynchronous load */
static void async_load_cb(struct libusb_transfer *transfer)
{
struct fpi_ssm *ssm = transfer->user_data;
fpi_ssm *ssm = transfer->user_data;
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct vfs101_dev *vdev = fpi_imgdev_get_user_data(dev);
struct vfs101_dev *vdev = FP_INSTANCE_DATA(FP_DEV(dev));
/* Cleanup transfer */
vdev->transfer = NULL;
@@ -382,7 +365,7 @@ static void async_load_cb(struct libusb_transfer *transfer)
/* Transfer not completed */
fp_err("transfer not completed, status = %d, length = %d", transfer->status, vdev->length);
fpi_imgdev_session_error(dev, -EIO);
fpi_ssm_mark_aborted(ssm, -EIO);
fpi_ssm_mark_failed(ssm, -EIO);
goto out;
}
@@ -391,7 +374,7 @@ static void async_load_cb(struct libusb_transfer *transfer)
/* Received incomplete frame, return protocol error */
fp_err("received incomplete frame");
fpi_imgdev_session_error(dev, -EIO);
fpi_ssm_mark_aborted(ssm, -EIO);
fpi_ssm_mark_failed(ssm, -EIO);
goto out;
}
}
@@ -406,12 +389,12 @@ static void async_load_cb(struct libusb_transfer *transfer)
/* Buffer full, image too large, return no memory error */
fp_err("buffer full, image too large");
fpi_imgdev_session_error(dev, -ENOMEM);
fpi_ssm_mark_aborted(ssm, -ENOMEM);
fpi_ssm_mark_failed(ssm, -ENOMEM);
goto out;
}
else
/* Image load not completed, submit another asynchronous load */
async_load(ssm);
async_load(ssm, dev);
}
else
{
@@ -430,29 +413,22 @@ out:
}
/* Submit asynchronous load */
static void async_load(struct fpi_ssm *ssm)
static void
async_load(fpi_ssm *ssm,
struct fp_img_dev *dev)
{
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct vfs101_dev *vdev = fpi_imgdev_get_user_data(dev);
struct vfs101_dev *vdev = FP_INSTANCE_DATA(FP_DEV(dev));
unsigned char *buffer;
int r;
/* Allocation of transfer */
vdev->transfer = libusb_alloc_transfer(0);
if (!vdev->transfer)
{
/* Allocation transfer failed, return no memory error */
fp_err("allocation of usb transfer failed");
fpi_imgdev_session_error(dev, -ENOMEM);
fpi_ssm_mark_aborted(ssm, -ENOMEM);
return;
}
vdev->transfer = fpi_usb_alloc();
/* Append new data into the buffer */
buffer = vdev->buffer + vdev->length;
/* Prepare bulk transfer */
libusb_fill_bulk_transfer(vdev->transfer, fpi_imgdev_get_usb_dev(dev), EP_IN(2), buffer, VFS_BLOCK_SIZE, async_load_cb, ssm, BULK_TIMEOUT);
libusb_fill_bulk_transfer(vdev->transfer, fpi_dev_get_usb_dev(FP_DEV(dev)), EP_IN(2), buffer, VFS_BLOCK_SIZE, async_load_cb, ssm, BULK_TIMEOUT);
/* Submit transfer */
r = libusb_submit_transfer(vdev->transfer);
@@ -462,39 +438,23 @@ static void async_load(struct fpi_ssm *ssm)
libusb_free_transfer(vdev->transfer);
fp_err("submit of usb transfer failed");
fpi_imgdev_session_error(dev, -EIO);
fpi_ssm_mark_aborted(ssm, -EIO);
fpi_ssm_mark_failed(ssm, -EIO);
return;
}
}
/* Callback of asynchronous sleep */
static void async_sleep_cb(void *data)
{
struct fpi_ssm *ssm = data;
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct vfs101_dev *vdev = fpi_imgdev_get_user_data(dev);
/* Cleanup timeout */
vdev->timeout = NULL;
fpi_ssm_next_state(ssm);
}
/* Submit asynchronous sleep */
static void async_sleep(unsigned int msec, struct fpi_ssm *ssm)
static void
async_sleep(unsigned int msec,
fpi_ssm *ssm,
struct fp_img_dev *dev)
{
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct vfs101_dev *vdev = fpi_imgdev_get_user_data(dev);
/* Add timeout */
vdev->timeout = fpi_timeout_add(msec, async_sleep_cb, ssm);
if (vdev->timeout == NULL)
if (fpi_timeout_add(msec, fpi_ssm_next_state_timeout_cb, FP_DEV(dev), ssm) == NULL)
{
/* Failed to add timeout */
fp_err("failed to add timeout");
fpi_imgdev_session_error(dev, -ETIME);
fpi_ssm_mark_aborted(ssm, -ETIME);
fpi_ssm_mark_failed(ssm, -ETIME);
}
}
@@ -507,28 +467,31 @@ enum
};
/* Exec swap sequential state machine */
static void m_swap_state(struct fpi_ssm *ssm)
static void m_swap_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
{
switch (fpi_ssm_get_cur_state(ssm))
{
case M_SWAP_SEND:
/* Send data */
async_send(ssm);
async_send(ssm, user_data);
break;
case M_SWAP_RECV:
/* Recv response */
async_recv(ssm);
async_recv(ssm, user_data);
break;
}
}
/* Start swap sequential state machine */
static void m_swap(struct fpi_ssm *ssm, unsigned char *data, size_t length)
static void
m_swap(fpi_ssm *ssm,
struct fp_img_dev *dev,
unsigned char *data,
size_t length)
{
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct vfs101_dev *vdev = fpi_imgdev_get_user_data(dev);
struct fpi_ssm *subsm;
struct vfs101_dev *vdev = FP_INSTANCE_DATA(FP_DEV(dev));
fpi_ssm *subsm;
/* Prepare data for sending */
memcpy(vdev->buffer, data, length);
@@ -536,13 +499,16 @@ static void m_swap(struct fpi_ssm *ssm, unsigned char *data, size_t length)
vdev->length = length;
/* Start swap ssm */
subsm = fpi_ssm_new(fpi_imgdev_get_dev(dev), m_swap_state, M_SWAP_NUM_STATES);
fpi_ssm_set_user_data(subsm, dev);
subsm = fpi_ssm_new(FP_DEV(dev), m_swap_state, M_SWAP_NUM_STATES, dev);
fpi_ssm_start_subsm(ssm, subsm);
}
/* Retrieve fingerprint image */
static void vfs_get_print(struct fpi_ssm *ssm, unsigned int param, int type)
static void
vfs_get_print(fpi_ssm *ssm,
struct fp_img_dev *dev,
unsigned int param,
int type)
{
unsigned char data[2][0x0e] = {
{ 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00,
@@ -558,11 +524,15 @@ static void vfs_get_print(struct fpi_ssm *ssm, unsigned int param, int type)
data[type][7] = byte(1, param);
/* Run swap sequential state machine */
m_swap(ssm, data[type], 0x0e);
m_swap(ssm, dev, data[type], 0x0e);
}
/* Set a parameter value on the device */
static void vfs_set_param(struct fpi_ssm *ssm, unsigned int param, unsigned int value)
static void
vfs_set_param(fpi_ssm *ssm,
struct fp_img_dev *dev,
unsigned int param,
unsigned int value)
{
unsigned char data[0x0a] = { 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00 };
@@ -575,22 +545,29 @@ static void vfs_set_param(struct fpi_ssm *ssm, unsigned int param, unsigned int
data[9] = byte(1, value);
/* Run swap sequential state machine */
m_swap(ssm, data, 0x0a);
m_swap(ssm, dev, data, 0x0a);
}
/* Abort previous print */
static void vfs_abort_print(struct fpi_ssm *ssm)
static void
vfs_abort_print(fpi_ssm *ssm,
struct fp_img_dev *dev)
{
unsigned char data[0x06] = { 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00 };
G_DEBUG_HERE();
/* Run swap sequential state machine */
m_swap (ssm, data, 0x06);
m_swap (ssm, dev, data, 0x06);
}
/* Poke a value on a region */
static void vfs_poke(struct fpi_ssm *ssm, unsigned int addr, unsigned int value, unsigned int size)
static void
vfs_poke(fpi_ssm *ssm,
struct fp_img_dev *dev,
unsigned int addr,
unsigned int value,
unsigned int size)
{
unsigned char data[0x0f] = { 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
@@ -608,25 +585,28 @@ static void vfs_poke(struct fpi_ssm *ssm, unsigned int addr, unsigned int value,
data[14] = byte(0, size);
/* Run swap sequential state machine */
m_swap(ssm, data, 0x0f);
m_swap(ssm, dev, data, 0x0f);
}
/* Get current finger state */
static void vfs_get_finger_state(struct fpi_ssm *ssm)
static void
vfs_get_finger_state(fpi_ssm *ssm,
struct fp_img_dev *dev)
{
unsigned char data[0x06] = { 0x00, 0x00, 0x00, 0x00, 0x16, 0x00 };
G_DEBUG_HERE();
/* Run swap sequential state machine */
m_swap (ssm, data, 0x06);
m_swap (ssm, dev, data, 0x06);
}
/* Load raw image from reader */
static void vfs_img_load(struct fpi_ssm *ssm)
static void
vfs_img_load(fpi_ssm *ssm,
struct fp_img_dev *dev)
{
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct vfs101_dev *vdev = fpi_imgdev_get_user_data(dev);
struct vfs101_dev *vdev = FP_INSTANCE_DATA(FP_DEV(dev));
G_DEBUG_HERE();
@@ -638,16 +618,16 @@ static void vfs_img_load(struct fpi_ssm *ssm)
vdev->height = -1;
/* Asynchronous load */
async_load(ssm);
async_load(ssm, dev);
}
/* Check if action is completed */
static int action_completed(struct fp_img_dev *dev)
{
struct vfs101_dev *vdev = fpi_imgdev_get_user_data(dev);
struct vfs101_dev *vdev = FP_INSTANCE_DATA(FP_DEV(dev));
if ((fpi_imgdev_get_action(dev) == IMG_ACTION_ENROLL) &&
(vdev->enroll_stage < fpi_dev_get_nr_enroll_stages(fpi_imgdev_get_dev(dev))))
(vdev->enroll_stage < fp_dev_get_nr_enroll_stages(FP_DEV(dev))))
/* Enroll not completed, return false */
return FALSE;
@@ -754,10 +734,11 @@ static void img_copy(struct vfs101_dev *vdev, struct fp_img *img)
}
/* Extract fingerpint image from raw data */
static void img_extract(struct fpi_ssm *ssm)
static void
img_extract(fpi_ssm *ssm,
struct fp_img_dev *dev)
{
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct vfs101_dev *vdev = fpi_imgdev_get_user_data(dev);
struct vfs101_dev *vdev = FP_INSTANCE_DATA(FP_DEV(dev));
struct fp_img *img;
/* Screen image to remove noise and find top and bottom line */
@@ -786,6 +767,11 @@ static void img_extract(struct fpi_ssm *ssm)
/* Notify image captured */
fpi_imgdev_image_captured(dev, img);
/* FIXME
* What is this for? The action result, and the enroll stages should
* already be handled in fpi_imgdev_image_captured()
*/
/* Check captured result */
if (fpi_imgdev_get_action_result(dev) >= 0 &&
fpi_imgdev_get_action_result(dev) != FP_ENROLL_RETRY &&
@@ -870,7 +856,7 @@ static void vfs_check_contrast(struct vfs101_dev *vdev)
fp_dbg("contrast = %d, level = %ld", vdev->contrast, count);
if (abs(count - VFS_IMG_BEST_CONRAST) < abs(vdev->best_clevel - VFS_IMG_BEST_CONRAST))
if (labs(count - VFS_IMG_BEST_CONTRAST) < abs(vdev->best_clevel - VFS_IMG_BEST_CONTRAST))
{
/* Better contrast found, use it */
vdev->best_contrast = vdev->contrast;
@@ -912,10 +898,10 @@ enum
};
/* Exec loop sequential state machine */
static void m_loop_state(struct fpi_ssm *ssm)
static void m_loop_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
{
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct vfs101_dev *vdev = fpi_imgdev_get_user_data(dev);
struct fp_img_dev *dev = user_data;
struct vfs101_dev *vdev = FP_INSTANCE_DATA(_dev);
/* Check action state */
if (!vdev->active)
@@ -929,17 +915,17 @@ static void m_loop_state(struct fpi_ssm *ssm)
{
case M_LOOP_0_GET_PRINT:
/* Send get print command to the reader */
vfs_get_print(ssm, VFS_BUFFER_HEIGHT, 1);
vfs_get_print(ssm, dev, VFS_BUFFER_HEIGHT, 1);
break;
case M_LOOP_0_SLEEP:
/* Wait fingerprint scanning */
async_sleep(50, ssm);
async_sleep(50, ssm, dev);
break;
case M_LOOP_0_GET_STATE:
/* Get finger state */
vfs_get_finger_state(ssm);
vfs_get_finger_state(ssm, dev);
break;
case M_LOOP_0_LOAD_IMAGE:
@@ -954,14 +940,14 @@ static void m_loop_state(struct fpi_ssm *ssm)
case VFS_FINGER_PRESENT:
/* Load image from reader */
vdev->ignore_error = TRUE;
vfs_img_load(ssm);
vfs_img_load(ssm, dev);
break;
default:
/* Unknown state */
fp_err("unknown device state 0x%02x", vdev->buffer[0x0a]);
fpi_imgdev_session_error(dev, -EIO);
fpi_ssm_mark_aborted(ssm, -EIO);
fpi_ssm_mark_failed(ssm, -EIO);
break;
}
break;
@@ -970,10 +956,10 @@ static void m_loop_state(struct fpi_ssm *ssm)
/* Check if image is loaded */
if (vdev->height > 0)
/* Fingerprint is loaded, extract image from raw data */
img_extract(ssm);
img_extract(ssm, dev);
/* Wait handling image */
async_sleep(10, ssm);
async_sleep(10, ssm, dev);
break;
case M_LOOP_0_CHECK_ACTION:
@@ -993,7 +979,7 @@ static void m_loop_state(struct fpi_ssm *ssm)
case M_LOOP_1_GET_STATE:
/* Get finger state */
vfs_get_finger_state(ssm);
vfs_get_finger_state(ssm, dev);
break;
case M_LOOP_1_CHECK_STATE:
@@ -1011,14 +997,14 @@ static void m_loop_state(struct fpi_ssm *ssm)
/* Wait removing finger */
vdev->counter++;
async_sleep(250, ssm);
async_sleep(250, ssm, dev);
}
else
{
/* reach max loop counter, return protocol error */
fp_err("finger not removed from the scanner");
fpi_imgdev_session_error(dev, -EIO);
fpi_ssm_mark_aborted(ssm, -EIO);
fpi_ssm_mark_failed(ssm, -EIO);
}
}
else
@@ -1049,13 +1035,13 @@ static void m_loop_state(struct fpi_ssm *ssm)
case M_LOOP_1_GET_PRINT:
/* Send get print command to the reader */
vfs_get_print(ssm, VFS_BUFFER_HEIGHT, 1);
vfs_get_print(ssm, dev, VFS_BUFFER_HEIGHT, 1);
break;
case M_LOOP_1_LOAD_IMAGE:
/* Load image */
vdev->ignore_error = TRUE;
vfs_img_load(ssm);
vfs_img_load(ssm, dev);
break;
case M_LOOP_1_LOOP:
@@ -1065,29 +1051,29 @@ static void m_loop_state(struct fpi_ssm *ssm)
case M_LOOP_1_SLEEP:
/* Wait fingerprint scanning */
async_sleep(10, ssm);
async_sleep(10, ssm, dev);
break;
case M_LOOP_2_ABORT_PRINT:
/* Abort print command */
vfs_abort_print(ssm);
vfs_abort_print(ssm, dev);
break;
case M_LOOP_2_LOAD_IMAGE:
/* Load abort image */
vdev->ignore_error = TRUE;
vfs_img_load(ssm);
vfs_img_load(ssm, dev);
break;
case M_LOOP_3_GET_PRINT:
/* Get empty image */
vfs_get_print(ssm, 0x000a, 0);
vfs_get_print(ssm, dev, 0x000a, 0);
break;
case M_LOOP_3_LOAD_IMAGE:
/* Load abort image */
vdev->ignore_error = TRUE;
vfs_img_load(ssm);
vfs_img_load(ssm, dev);
break;
case M_LOOP_3_CHECK_IMAGE:
@@ -1101,14 +1087,14 @@ static void m_loop_state(struct fpi_ssm *ssm)
{
/* Wait aborting */
vdev->counter++;
async_sleep(100, ssm);
async_sleep(100, ssm, dev);
}
else
{
/* reach max loop counter, return protocol error */
fp_err("waiting abort reach max loop counter");
fpi_imgdev_session_error(dev, -EIO);
fpi_ssm_mark_aborted(ssm, -EIO);
fpi_ssm_mark_failed(ssm, -EIO);
}
break;
@@ -1120,7 +1106,7 @@ static void m_loop_state(struct fpi_ssm *ssm)
}
/* Complete loop sequential state machine */
static void m_loop_complete(struct fpi_ssm *ssm)
static void m_loop_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
{
/* Free sequential state machine */
fpi_ssm_free(ssm);
@@ -1176,10 +1162,10 @@ enum
};
/* Exec init sequential state machine */
static void m_init_state(struct fpi_ssm *ssm)
static void m_init_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
{
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct vfs101_dev *vdev = fpi_imgdev_get_user_data(dev);
struct fp_img_dev *dev = user_data;
struct vfs101_dev *vdev = FP_INSTANCE_DATA(_dev);
/* Check action state */
if (!vdev->active)
@@ -1194,29 +1180,29 @@ static void m_init_state(struct fpi_ssm *ssm)
case M_INIT_0_RECV_DIRTY:
/* Recv eventualy dirty data */
vdev->ignore_error = TRUE;
async_recv(ssm);
async_recv(ssm, dev);
break;
case M_INIT_0_ABORT_PRINT:
/* Abort print command */
vfs_abort_print(ssm);
vfs_abort_print(ssm, dev);
break;
case M_INIT_0_LOAD_IMAGE:
/* Load abort image */
vdev->ignore_error = TRUE;
vfs_img_load(ssm);
vfs_img_load(ssm, dev);
break;
case M_INIT_1_GET_PRINT:
/* Get empty image */
vfs_get_print(ssm, 0x000a, 0);
vfs_get_print(ssm, dev, 0x000a, 0);
break;
case M_INIT_1_LOAD_IMAGE:
/* Load abort image */
vdev->ignore_error = TRUE;
vfs_img_load(ssm);
vfs_img_load(ssm, dev);
break;
case M_INIT_1_CHECK_IMAGE:
@@ -1230,14 +1216,14 @@ static void m_init_state(struct fpi_ssm *ssm)
{
/* Wait aborting */
vdev->counter++;
async_sleep(100, ssm);
async_sleep(100, ssm, dev);
}
else
{
/* reach max loop counter, return protocol error */
fp_err("waiting abort reach max loop counter");
fpi_imgdev_session_error(dev, -EIO);
fpi_ssm_mark_aborted(ssm, -EIO);
fpi_ssm_mark_failed(ssm, -EIO);
}
break;
@@ -1248,7 +1234,7 @@ static void m_init_state(struct fpi_ssm *ssm)
case M_INIT_2_GET_STATE:
/* Get finger state */
vfs_get_finger_state(ssm);
vfs_get_finger_state(ssm, dev);
break;
case M_INIT_2_CHECK_STATE:
@@ -1266,14 +1252,14 @@ static void m_init_state(struct fpi_ssm *ssm)
/* Wait removing finger */
vdev->counter++;
async_sleep(250, ssm);
async_sleep(250, ssm, dev);
}
else
{
/* reach max loop counter, return protocol error */
fp_err("finger not removed from the scanner");
fpi_imgdev_session_error(dev, -EIO);
fpi_ssm_mark_aborted(ssm, -EIO);
fpi_ssm_mark_failed(ssm, -EIO);
}
}
else
@@ -1293,13 +1279,13 @@ static void m_init_state(struct fpi_ssm *ssm)
case M_INIT_2_GET_PRINT:
/* Send get print command to the reader */
vfs_get_print(ssm, VFS_BUFFER_HEIGHT, 1);
vfs_get_print(ssm, dev, VFS_BUFFER_HEIGHT, 1);
break;
case M_INIT_2_LOAD_IMAGE:
/* Load unexpected image */
vdev->ignore_error = TRUE;
vfs_img_load(ssm);
vfs_img_load(ssm, dev);
break;
case M_INIT_2_LOOP:
@@ -1309,68 +1295,68 @@ static void m_init_state(struct fpi_ssm *ssm)
case M_INIT_3_SET_000E:
/* Set param 0x000e, required for take image */
vfs_set_param(ssm, VFS_PAR_000E, VFS_VAL_000E);
vfs_set_param(ssm, dev, VFS_PAR_000E, VFS_VAL_000E);
break;
case M_INIT_3_SET_0011:
/* Set param 0x0011, required for take image */
vfs_set_param(ssm, VFS_PAR_0011, VFS_VAL_0011);
vfs_set_param(ssm, dev, VFS_PAR_0011, VFS_VAL_0011);
break;
case M_INIT_3_SET_0076:
/* Set param 0x0076, required for use info line */
vfs_set_param(ssm, VFS_PAR_0076, VFS_VAL_0076);
vfs_set_param(ssm, dev, VFS_PAR_0076, VFS_VAL_0076);
break;
case M_INIT_3_SET_0078:
/* Set param 0x0078, required for use info line */
vfs_set_param(ssm, VFS_PAR_0078, VFS_VAL_0078);
vfs_set_param(ssm, dev, VFS_PAR_0078, VFS_VAL_0078);
break;
case M_INIT_3_SET_THRESHOLD:
/* Set threshold */
vfs_set_param(ssm, VFS_PAR_THRESHOLD, VFS_VAL_THRESHOLD);
vfs_set_param(ssm, dev, VFS_PAR_THRESHOLD, VFS_VAL_THRESHOLD);
break;
case M_INIT_3_SET_STATE3_COUNT:
/* Set state 3 count */
vfs_set_param(ssm, VFS_PAR_STATE_3, VFS_VAL_STATE_3);
vfs_set_param(ssm, dev, VFS_PAR_STATE_3, VFS_VAL_STATE_3);
break;
case M_INIT_3_SET_STATE5_COUNT:
/* Set state 5 count */
vfs_set_param(ssm, VFS_PAR_STATE_5, VFS_VAL_STATE_5);
vfs_set_param(ssm, dev, VFS_PAR_STATE_5, VFS_VAL_STATE_5);
break;
case M_INIT_3_SET_INFO_CONTRAST:
/* Set info line contrast */
vfs_set_param(ssm, VFS_PAR_INFO_CONTRAST, 10);
vfs_set_param(ssm, dev, VFS_PAR_INFO_CONTRAST, 10);
break;
case M_INIT_3_SET_INFO_RATE:
/* Set info line rate */
vfs_set_param(ssm, VFS_PAR_INFO_RATE, 32);
vfs_set_param(ssm, dev, VFS_PAR_INFO_RATE, 32);
break;
case M_INIT_4_SET_EXPOSURE:
/* Set exposure level of reader */
vfs_poke(ssm, VFS_REG_IMG_EXPOSURE, 0x4000, 0x02);
vfs_poke(ssm, dev, VFS_REG_IMG_EXPOSURE, 0x4000, 0x02);
vdev->counter = 1;
break;
case M_INIT_4_SET_CONTRAST:
/* Set contrast level of reader */
vfs_poke(ssm, VFS_REG_IMG_CONTRAST, vdev->contrast, 0x01);
vfs_poke(ssm, dev, VFS_REG_IMG_CONTRAST, vdev->contrast, 0x01);
break;
case M_INIT_4_GET_PRINT:
/* Get empty image */
vfs_get_print(ssm, 0x000a, 0);
vfs_get_print(ssm, dev, 0x000a, 0);
break;
case M_INIT_4_LOAD_IMAGE:
/* Load empty image */
vfs_img_load(ssm);
vfs_img_load(ssm, dev);
break;
case M_INIT_4_CHECK_CONTRAST:
@@ -1396,32 +1382,32 @@ static void m_init_state(struct fpi_ssm *ssm)
case M_INIT_5_SET_EXPOSURE:
/* Set exposure level of reader */
vfs_poke(ssm, VFS_REG_IMG_EXPOSURE, VFS_VAL_IMG_EXPOSURE, 0x02);
vfs_poke(ssm, dev, VFS_REG_IMG_EXPOSURE, VFS_VAL_IMG_EXPOSURE, 0x02);
break;
case M_INIT_5_SET_CONTRAST:
/* Set contrast level of reader */
vfs_poke(ssm, VFS_REG_IMG_CONTRAST, vdev->contrast, 0x01);
vfs_poke(ssm, dev, VFS_REG_IMG_CONTRAST, vdev->contrast, 0x01);
break;
case M_INIT_5_SET_INFO_CONTRAST:
/* Set info line contrast */
vfs_set_param(ssm, VFS_PAR_INFO_CONTRAST, vdev->contrast);
vfs_set_param(ssm, dev, VFS_PAR_INFO_CONTRAST, vdev->contrast);
break;
case M_INIT_5_SET_INFO_RATE:
/* Set info line rate */
vfs_set_param(ssm, VFS_PAR_INFO_RATE, VFS_VAL_INFO_RATE);
vfs_set_param(ssm, dev, VFS_PAR_INFO_RATE, VFS_VAL_INFO_RATE);
break;
}
}
/* Complete init sequential state machine */
static void m_init_complete(struct fpi_ssm *ssm)
static void m_init_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
{
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct vfs101_dev *vdev = fpi_imgdev_get_user_data(dev);
struct fpi_ssm *ssm_loop;
struct fp_img_dev *dev = user_data;
struct vfs101_dev *vdev = FP_INSTANCE_DATA(_dev);
fpi_ssm *ssm_loop;
if (!fpi_ssm_get_error(ssm) && vdev->active)
{
@@ -1429,8 +1415,7 @@ static void m_init_complete(struct fpi_ssm *ssm)
fpi_imgdev_activate_complete(dev, 0);
/* Start loop ssm */
ssm_loop = fpi_ssm_new(fpi_imgdev_get_dev(dev), m_loop_state, M_LOOP_NUM_STATES);
fpi_ssm_set_user_data(ssm_loop, dev);
ssm_loop = fpi_ssm_new(FP_DEV(dev), m_loop_state, M_LOOP_NUM_STATES, dev);
fpi_ssm_start(ssm_loop, m_loop_complete);
}
@@ -1439,10 +1424,10 @@ static void m_init_complete(struct fpi_ssm *ssm)
}
/* Activate device */
static int dev_activate(struct fp_img_dev *dev, enum fp_imgdev_state state)
static int dev_activate(struct fp_img_dev *dev)
{
struct vfs101_dev *vdev = fpi_imgdev_get_user_data(dev);
struct fpi_ssm *ssm;
struct vfs101_dev *vdev = FP_INSTANCE_DATA(FP_DEV(dev));
fpi_ssm *ssm;
/* Check if already active */
if (vdev->active)
@@ -1464,8 +1449,7 @@ static int dev_activate(struct fp_img_dev *dev, enum fp_imgdev_state state)
vdev->enroll_stage = 0;
/* Start init ssm */
ssm = fpi_ssm_new(fpi_imgdev_get_dev(dev), m_init_state, M_INIT_NUM_STATES);
fpi_ssm_set_user_data(ssm, dev);
ssm = fpi_ssm_new(FP_DEV(dev), m_init_state, M_INIT_NUM_STATES, dev);
fpi_ssm_start(ssm, m_init_complete);
return 0;
@@ -1474,13 +1458,13 @@ static int dev_activate(struct fp_img_dev *dev, enum fp_imgdev_state state)
/* Deactivate device */
static void dev_deactivate(struct fp_img_dev *dev)
{
struct vfs101_dev *vdev = fpi_imgdev_get_user_data(dev);
struct vfs101_dev *vdev = FP_INSTANCE_DATA(FP_DEV(dev));
/* Reset active state */
vdev->active = FALSE;
/* Handle eventualy existing events */
while (vdev->transfer || vdev->timeout)
while (vdev->transfer)
fp_handle_events();
/* Notify deactivate complete */
@@ -1494,7 +1478,7 @@ static int dev_open(struct fp_img_dev *dev, unsigned long driver_data)
int r;
/* Claim usb interface */
r = libusb_claim_interface(fpi_imgdev_get_usb_dev(dev), 0);
r = libusb_claim_interface(fpi_dev_get_usb_dev(FP_DEV(dev)), 0);
if (r < 0)
{
/* Interface not claimed, return error */
@@ -1505,7 +1489,7 @@ static int dev_open(struct fp_img_dev *dev, unsigned long driver_data)
/* Initialize private structure */
vdev = g_malloc0(sizeof(struct vfs101_dev));
vdev->seqnum = -1;
fpi_imgdev_set_user_data(dev, vdev);
fp_dev_set_instance_data(FP_DEV(dev), vdev);
/* Notify open complete */
fpi_imgdev_open_complete(dev, 0);
@@ -1519,11 +1503,11 @@ static void dev_close(struct fp_img_dev *dev)
struct vfs101_dev *vdev;
/* Release private structure */
vdev = fpi_imgdev_get_user_data(dev);
vdev = FP_INSTANCE_DATA(FP_DEV(dev));
g_free(vdev);
/* Release usb interface */
libusb_release_interface(fpi_imgdev_get_usb_dev(dev), 0);
libusb_release_interface(fpi_dev_get_usb_dev(FP_DEV(dev)), 0);
/* Notify close complete */
fpi_imgdev_close_complete(dev);

View File

@@ -26,35 +26,26 @@
/************************** GENERIC STUFF *************************************/
/* Callback of asynchronous sleep */
static void async_sleep_cb(void *data)
{
struct fpi_ssm *ssm = data;
fpi_ssm_next_state(ssm);
}
/* Submit asynchronous sleep */
static void async_sleep(unsigned int msec, struct fpi_ssm *ssm)
static void
async_sleep(unsigned int msec,
fpi_ssm *ssm,
struct fp_img_dev *dev)
{
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct fpi_timeout *timeout;
/* Add timeout */
timeout = fpi_timeout_add(msec, async_sleep_cb, ssm);
if (timeout == NULL) {
if (fpi_timeout_add(msec, fpi_ssm_next_state_timeout_cb, FP_DEV(dev), ssm) == NULL) {
/* Failed to add timeout */
fp_err("failed to add timeout");
fpi_imgdev_session_error(dev, -ETIME);
fpi_ssm_mark_aborted(ssm, -ETIME);
fpi_ssm_mark_failed(ssm, -ETIME);
}
}
static int submit_image(struct fpi_ssm *ssm)
static int
submit_image(fpi_ssm *ssm,
struct fp_img_dev *dev)
{
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
vfs301_dev_t *vdev = fpi_imgdev_get_user_data(dev);
vfs301_dev_t *vdev = FP_INSTANCE_DATA(FP_DEV(dev));
int height;
struct fp_img *img;
@@ -80,7 +71,7 @@ static int submit_image(struct fpi_ssm *ssm)
img->width = VFS301_FP_OUTPUT_WIDTH;
img->height = height;
img = fpi_img_resize(img, img->height * img->width);
img = fpi_img_realloc(img, img->height * img->width);
fpi_imgdev_image_captured(dev, img);
return 1;
@@ -103,24 +94,24 @@ enum
};
/* Exec loop sequential state machine */
static void m_loop_state(struct fpi_ssm *ssm)
static void m_loop_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
{
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
vfs301_dev_t *vdev = fpi_imgdev_get_user_data(dev);
struct fp_img_dev *dev = user_data;
vfs301_dev_t *vdev = FP_INSTANCE_DATA(_dev);
switch (fpi_ssm_get_cur_state(ssm)) {
case M_REQUEST_PRINT:
vfs301_proto_request_fingerprint(fpi_imgdev_get_usb_dev(dev), vdev);
vfs301_proto_request_fingerprint(fpi_dev_get_usb_dev(FP_DEV(dev)), vdev);
fpi_ssm_next_state(ssm);
break;
case M_WAIT_PRINT:
/* Wait fingerprint scanning */
async_sleep(200, ssm);
async_sleep(200, ssm, dev);
break;
case M_CHECK_PRINT:
if (!vfs301_proto_peek_event(fpi_imgdev_get_usb_dev(dev), vdev))
if (!vfs301_proto_peek_event(fpi_dev_get_usb_dev(FP_DEV(dev)), vdev))
fpi_ssm_jump_to_state(ssm, M_WAIT_PRINT);
else
fpi_ssm_next_state(ssm);
@@ -128,18 +119,18 @@ static void m_loop_state(struct fpi_ssm *ssm)
case M_READ_PRINT_START:
fpi_imgdev_report_finger_status(dev, TRUE);
vfs301_proto_process_event_start(fpi_imgdev_get_usb_dev(dev), vdev);
vfs301_proto_process_event_start(fpi_dev_get_usb_dev(FP_DEV(dev)), vdev);
fpi_ssm_next_state(ssm);
break;
case M_READ_PRINT_WAIT:
/* Wait fingerprint scanning */
async_sleep(200, ssm);
async_sleep(200, ssm, dev);
break;
case M_READ_PRINT_POLL:
{
int rv = vfs301_proto_process_event_poll(fpi_imgdev_get_usb_dev(dev), vdev);
int rv = vfs301_proto_process_event_poll(fpi_dev_get_usb_dev(FP_DEV(dev)), vdev);
g_assert(rv != VFS301_FAILURE);
if (rv == VFS301_ONGOING)
fpi_ssm_jump_to_state(ssm, M_READ_PRINT_WAIT);
@@ -149,7 +140,7 @@ static void m_loop_state(struct fpi_ssm *ssm)
break;
case M_SUBMIT_PRINT:
if (submit_image(ssm)) {
if (submit_image(ssm, dev)) {
fpi_ssm_mark_completed(ssm);
/* NOTE: finger off is expected only after submitting image... */
fpi_imgdev_report_finger_status(dev, FALSE);
@@ -161,38 +152,37 @@ static void m_loop_state(struct fpi_ssm *ssm)
}
/* Complete loop sequential state machine */
static void m_loop_complete(struct fpi_ssm *ssm)
static void m_loop_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
{
/* Free sequential state machine */
fpi_ssm_free(ssm);
}
/* Exec init sequential state machine */
static void m_init_state(struct fpi_ssm *ssm)
static void m_init_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
{
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
vfs301_dev_t *vdev = fpi_imgdev_get_user_data(dev);
struct fp_img_dev *dev = user_data;
vfs301_dev_t *vdev = FP_INSTANCE_DATA(_dev);
g_assert(fpi_ssm_get_cur_state(ssm) == 0);
vfs301_proto_init(fpi_imgdev_get_usb_dev(dev), vdev);
vfs301_proto_init(fpi_dev_get_usb_dev(FP_DEV(dev)), vdev);
fpi_ssm_mark_completed(ssm);
}
/* Complete init sequential state machine */
static void m_init_complete(struct fpi_ssm *ssm)
static void m_init_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
{
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct fpi_ssm *ssm_loop;
struct fp_img_dev *dev = user_data;
fpi_ssm *ssm_loop;
if (!fpi_ssm_get_error(ssm)) {
/* Notify activate complete */
fpi_imgdev_activate_complete(dev, 0);
/* Start loop ssm */
ssm_loop = fpi_ssm_new(fpi_imgdev_get_dev(dev), m_loop_state, M_LOOP_NUM_STATES);
fpi_ssm_set_user_data(ssm_loop, dev);
ssm_loop = fpi_ssm_new(FP_DEV(dev), m_loop_state, M_LOOP_NUM_STATES, dev);
fpi_ssm_start(ssm_loop, m_loop_complete);
}
@@ -201,13 +191,12 @@ static void m_init_complete(struct fpi_ssm *ssm)
}
/* Activate device */
static int dev_activate(struct fp_img_dev *dev, enum fp_imgdev_state state)
static int dev_activate(struct fp_img_dev *dev)
{
struct fpi_ssm *ssm;
fpi_ssm *ssm;
/* Start init ssm */
ssm = fpi_ssm_new(fpi_imgdev_get_dev(dev), m_init_state, 1);
fpi_ssm_set_user_data(ssm, dev);
ssm = fpi_ssm_new(FP_DEV(dev), m_init_state, 1, dev);
fpi_ssm_start(ssm, m_init_complete);
return 0;
@@ -216,6 +205,10 @@ static int dev_activate(struct fp_img_dev *dev, enum fp_imgdev_state state)
/* Deactivate device */
static void dev_deactivate(struct fp_img_dev *dev)
{
vfs301_dev_t *vdev;
vdev = FP_INSTANCE_DATA(FP_DEV(dev));
vfs301_proto_deinit(fpi_dev_get_usb_dev(FP_DEV(dev)), vdev);
fpi_imgdev_deactivate_complete(dev);
}
@@ -225,7 +218,7 @@ static int dev_open(struct fp_img_dev *dev, unsigned long driver_data)
int r;
/* Claim usb interface */
r = libusb_claim_interface(fpi_imgdev_get_usb_dev(dev), 0);
r = libusb_claim_interface(fpi_dev_get_usb_dev(FP_DEV(dev)), 0);
if (r < 0) {
/* Interface not claimed, return error */
fp_err("could not claim interface 0: %s", libusb_error_name(r));
@@ -234,7 +227,7 @@ static int dev_open(struct fp_img_dev *dev, unsigned long driver_data)
/* Initialize private structure */
vdev = g_malloc0(sizeof(vfs301_dev_t));
fpi_imgdev_set_user_data(dev, vdev);
fp_dev_set_instance_data(FP_DEV(dev), vdev);
vdev->scanline_buf = malloc(0);
vdev->scanline_count = 0;
@@ -250,12 +243,12 @@ static void dev_close(struct fp_img_dev *dev)
vfs301_dev_t *vdev;
/* Release private structure */
vdev = fpi_imgdev_get_user_data(dev);
vdev = FP_INSTANCE_DATA(FP_DEV(dev));
free(vdev->scanline_buf);
g_free(vdev);
/* Release usb interface */
libusb_release_interface(fpi_imgdev_get_usb_dev(dev), 0);
libusb_release_interface(fpi_dev_get_usb_dev(FP_DEV(dev)), 0);
/* Notify close complete */
fpi_imgdev_close_complete(dev);

View File

@@ -33,8 +33,8 @@
#include <unistd.h>
#include <stdlib.h>
#include <glib.h>
#include <libusb-1.0/libusb.h>
#include "fpi-usb.h"
#include "vfs301_proto.h"
#include "vfs301_proto_fragments.h"
@@ -499,12 +499,7 @@ void vfs301_proto_process_event_start(
USB_RECV(VFS301_RECEIVE_ENDPOINT_DATA, 64);
/* now read the fingerprint data, while there are some */
transfer = libusb_alloc_transfer(0);
if (!transfer) {
dev->recv_progress = VFS301_FAILURE;
return;
}
transfer = fpi_usb_alloc();
dev->recv_progress = VFS301_ONGOING;
dev->recv_exp_amt = VFS301_FP_RECV_LEN_1;

View File

@@ -75,14 +75,14 @@ static void start_scan(struct fp_img_dev *dev);
static void async_send_cb(struct libusb_transfer *transfer)
{
struct fpi_ssm *ssm = transfer->user_data;
fpi_ssm *ssm = transfer->user_data;
struct usbexchange_data *data = fpi_ssm_get_user_data(ssm);
struct usb_action *action;
if (fpi_ssm_get_cur_state(ssm) >= data->stepcount) {
fp_err("Radiation detected!");
fpi_imgdev_session_error(data->device, -EINVAL);
fpi_ssm_mark_aborted(ssm, -EINVAL);
fpi_ssm_mark_failed(ssm, -EINVAL);
goto out;
}
@@ -90,7 +90,7 @@ static void async_send_cb(struct libusb_transfer *transfer)
if (action->type != ACTION_SEND) {
fp_err("Radiation detected!");
fpi_imgdev_session_error(data->device, -EINVAL);
fpi_ssm_mark_aborted(ssm, -EINVAL);
fpi_ssm_mark_failed(ssm, -EINVAL);
goto out;
}
@@ -98,7 +98,7 @@ static void async_send_cb(struct libusb_transfer *transfer)
/* Transfer not completed, return IO error */
fp_err("transfer not completed, status = %d", transfer->status);
fpi_imgdev_session_error(data->device, -EIO);
fpi_ssm_mark_aborted(ssm, -EIO);
fpi_ssm_mark_failed(ssm, -EIO);
goto out;
}
if (transfer->length != transfer->actual_length) {
@@ -106,7 +106,7 @@ static void async_send_cb(struct libusb_transfer *transfer)
fp_err("length mismatch, got %d, expected %d",
transfer->actual_length, transfer->length);
fpi_imgdev_session_error(data->device, -EIO);
fpi_ssm_mark_aborted(ssm, -EIO);
fpi_ssm_mark_failed(ssm, -EIO);
goto out;
}
@@ -119,7 +119,7 @@ out:
static void async_recv_cb(struct libusb_transfer *transfer)
{
struct fpi_ssm *ssm = transfer->user_data;
fpi_ssm *ssm = transfer->user_data;
struct usbexchange_data *data = fpi_ssm_get_user_data(ssm);
struct usb_action *action;
@@ -127,14 +127,14 @@ static void async_recv_cb(struct libusb_transfer *transfer)
/* Transfer not completed, return IO error */
fp_err("transfer not completed, status = %d", transfer->status);
fpi_imgdev_session_error(data->device, -EIO);
fpi_ssm_mark_aborted(ssm, -EIO);
fpi_ssm_mark_failed(ssm, -EIO);
goto out;
}
if (fpi_ssm_get_cur_state(ssm) >= data->stepcount) {
fp_err("Radiation detected!");
fpi_imgdev_session_error(data->device, -EINVAL);
fpi_ssm_mark_aborted(ssm, -EINVAL);
fpi_ssm_mark_failed(ssm, -EINVAL);
goto out;
}
@@ -142,7 +142,7 @@ static void async_recv_cb(struct libusb_transfer *transfer)
if (action->type != ACTION_RECEIVE) {
fp_err("Radiation detected!");
fpi_imgdev_session_error(data->device, -EINVAL);
fpi_ssm_mark_aborted(ssm, -EINVAL);
fpi_ssm_mark_failed(ssm, -EINVAL);
goto out;
}
@@ -152,14 +152,14 @@ static void async_recv_cb(struct libusb_transfer *transfer)
transfer->actual_length,
action->correct_reply_size);
fpi_imgdev_session_error(data->device, -EIO);
fpi_ssm_mark_aborted(ssm, -EIO);
fpi_ssm_mark_failed(ssm, -EIO);
goto out;
}
if (memcmp(transfer->buffer, action->data,
action->correct_reply_size) != 0) {
fp_dbg("Wrong reply:");
fpi_imgdev_session_error(data->device, -EIO);
fpi_ssm_mark_aborted(ssm, -EIO);
fpi_ssm_mark_failed(ssm, -EIO);
goto out;
}
} else
@@ -171,14 +171,14 @@ out:
libusb_free_transfer(transfer);
}
static void usbexchange_loop(struct fpi_ssm *ssm)
static void usbexchange_loop(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
{
struct usbexchange_data *data = fpi_ssm_get_user_data(ssm);
struct usbexchange_data *data = user_data;
if (fpi_ssm_get_cur_state(ssm) >= data->stepcount) {
fp_err("Bug detected: state %d out of range, only %d steps",
fpi_ssm_get_cur_state(ssm), data->stepcount);
fpi_imgdev_session_error(data->device, -EINVAL);
fpi_ssm_mark_aborted(ssm, -EINVAL);
fpi_ssm_mark_failed(ssm, -EINVAL);
return;
}
@@ -189,14 +189,8 @@ static void usbexchange_loop(struct fpi_ssm *ssm)
switch (action->type) {
case ACTION_SEND:
fp_dbg("Sending %s", action->name);
transfer = libusb_alloc_transfer(0);
if (transfer == NULL) {
fp_err("Failed to allocate transfer");
fpi_imgdev_session_error(data->device, -ENOMEM);
fpi_ssm_mark_aborted(ssm, -ENOMEM);
return;
}
libusb_fill_bulk_transfer(transfer, fpi_imgdev_get_usb_dev(data->device),
transfer = fpi_usb_alloc();
libusb_fill_bulk_transfer(transfer, fpi_dev_get_usb_dev(FP_DEV(data->device)),
action->endpoint, action->data,
action->size, async_send_cb, ssm,
data->timeout);
@@ -205,14 +199,8 @@ static void usbexchange_loop(struct fpi_ssm *ssm)
case ACTION_RECEIVE:
fp_dbg("Receiving %d bytes", action->size);
transfer = libusb_alloc_transfer(0);
if (transfer == NULL) {
fp_err("Failed to allocate transfer");
fpi_imgdev_session_error(data->device, -ENOMEM);
fpi_ssm_mark_aborted(ssm, -ENOMEM);
return;
}
libusb_fill_bulk_transfer(transfer, fpi_imgdev_get_usb_dev(data->device),
transfer = fpi_usb_alloc();
libusb_fill_bulk_transfer(transfer, fpi_dev_get_usb_dev(FP_DEV(data->device)),
action->endpoint, data->receive_buf,
action->size, async_recv_cb, ssm,
data->timeout);
@@ -222,24 +210,24 @@ static void usbexchange_loop(struct fpi_ssm *ssm)
default:
fp_err("Bug detected: invalid action %d", action->type);
fpi_imgdev_session_error(data->device, -EINVAL);
fpi_ssm_mark_aborted(ssm, -EINVAL);
fpi_ssm_mark_failed(ssm, -EINVAL);
return;
}
if (ret != 0) {
fp_err("USB transfer error: %s", strerror(ret));
fpi_imgdev_session_error(data->device, ret);
fpi_ssm_mark_aborted(ssm, ret);
fpi_ssm_mark_failed(ssm, ret);
}
}
static void usb_exchange_async(struct fpi_ssm *ssm,
static void usb_exchange_async(fpi_ssm *ssm,
struct usbexchange_data *data)
{
struct fpi_ssm *subsm = fpi_ssm_new(fpi_imgdev_get_dev(data->device),
usbexchange_loop,
data->stepcount);
fpi_ssm_set_user_data(subsm, data);
fpi_ssm *subsm = fpi_ssm_new(FP_DEV(data->device),
usbexchange_loop,
data->stepcount,
data);
fpi_ssm_start_subsm(ssm, subsm);
}
@@ -395,9 +383,11 @@ static int process_chunk(struct vfs5011_data *data, int transferred)
return 0;
}
void submit_image(struct fpi_ssm *ssm, struct vfs5011_data *data)
static void
submit_image(fpi_ssm *ssm,
struct vfs5011_data *data,
struct fp_img_dev *dev)
{
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct fp_img *img;
if (data->lines_recorded == 0) {
@@ -422,11 +412,11 @@ void submit_image(struct fpi_ssm *ssm, struct vfs5011_data *data)
static void chunk_capture_callback(struct libusb_transfer *transfer)
{
struct fpi_ssm *ssm = (struct fpi_ssm *)transfer->user_data;
fpi_ssm *ssm = (fpi_ssm *)transfer->user_data;
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct vfs5011_data *data;
data = fpi_imgdev_get_user_data(dev);
data = FP_INSTANCE_DATA(FP_DEV(dev));
if ((transfer->status == LIBUSB_TRANSFER_COMPLETED) ||
(transfer->status == LIBUSB_TRANSFER_TIMED_OUT)) {
@@ -441,7 +431,7 @@ static void chunk_capture_callback(struct libusb_transfer *transfer)
} else {
if (!data->deactivating) {
fp_err("Failed to capture data");
fpi_ssm_mark_aborted(ssm, -1);
fpi_ssm_mark_failed(ssm, -1);
} else {
fpi_ssm_mark_completed(ssm);
}
@@ -452,7 +442,7 @@ static void chunk_capture_callback(struct libusb_transfer *transfer)
static int capture_chunk_async(struct vfs5011_data *data,
libusb_device_handle *handle, int nline,
int timeout, struct fpi_ssm *ssm)
int timeout, fpi_ssm *ssm)
{
fp_dbg("capture_chunk_async: capture %d lines, already have %d",
nline, data->lines_recorded);
@@ -462,7 +452,7 @@ static int capture_chunk_async(struct vfs5011_data *data,
STOP_CHECK_LINES = 50
};
data->flying_transfer = libusb_alloc_transfer(0);
data->flying_transfer = fpi_usb_alloc();
libusb_fill_bulk_transfer(data->flying_transfer, handle, VFS5011_IN_ENDPOINT_DATA,
data->capture_buffer,
nline * VFS5011_LINE_SIZE,
@@ -470,13 +460,6 @@ static int capture_chunk_async(struct vfs5011_data *data,
return libusb_submit_transfer(data->flying_transfer);
}
static void async_sleep_cb(void *data)
{
struct fpi_ssm *ssm = data;
fpi_ssm_next_state(ssm);
}
/*
* Device initialization. Windows driver only does it when the device is
* plugged in, but it doesn't harm to do this every time before scanning the
@@ -665,16 +648,16 @@ struct usb_action vfs5011_initiate_capture[] = {
/* ====================== lifprint interface ======================= */
static void activate_loop(struct fpi_ssm *ssm)
static void activate_loop(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
{
enum {READ_TIMEOUT = 0};
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct fp_img_dev *dev = user_data;
struct vfs5011_data *data;
int r;
struct fpi_timeout *timeout;
fpi_timeout *timeout;
data = fpi_imgdev_get_user_data(dev);
data = FP_INSTANCE_DATA(_dev);
fp_dbg("main_loop: state %d", fpi_ssm_get_cur_state(ssm));
@@ -707,23 +690,23 @@ static void activate_loop(struct fpi_ssm *ssm)
break;
case DEV_ACTIVATE_READ_DATA:
r = capture_chunk_async(data, fpi_imgdev_get_usb_dev(dev), CAPTURE_LINES,
r = capture_chunk_async(data, fpi_dev_get_usb_dev(FP_DEV(dev)), CAPTURE_LINES,
READ_TIMEOUT, ssm);
if (r != 0) {
fp_err("Failed to capture data");
fpi_imgdev_session_error(dev, r);
fpi_ssm_mark_aborted(ssm, r);
fpi_ssm_mark_failed(ssm, r);
}
break;
case DEV_ACTIVATE_DATA_COMPLETE:
timeout = fpi_timeout_add(1, async_sleep_cb, ssm);
timeout = fpi_timeout_add(1, fpi_ssm_next_state_timeout_cb, _dev, ssm);
if (timeout == NULL) {
/* Failed to add timeout */
fp_err("failed to add timeout");
fpi_imgdev_session_error(dev, -1);
fpi_ssm_mark_aborted(ssm, -1);
fpi_ssm_mark_failed(ssm, -1);
}
break;
@@ -742,20 +725,20 @@ static void activate_loop(struct fpi_ssm *ssm)
}
}
static void activate_loop_complete(struct fpi_ssm *ssm)
static void activate_loop_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
{
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct fp_img_dev *dev = user_data;
struct vfs5011_data *data;
int r = fpi_ssm_get_error(ssm);
data = fpi_imgdev_get_user_data(dev);
data = FP_INSTANCE_DATA(_dev);
fp_dbg("finishing");
if (data->init_sequence.receive_buf != NULL)
g_free(data->init_sequence.receive_buf);
data->init_sequence.receive_buf = NULL;
if (!data->deactivating && !r) {
submit_image(ssm, data);
submit_image(ssm, data, dev);
fpi_imgdev_report_finger_status(dev, FALSE);
}
fpi_ssm_free(ssm);
@@ -772,12 +755,12 @@ static void activate_loop_complete(struct fpi_ssm *ssm)
}
static void open_loop(struct fpi_ssm *ssm)
static void open_loop(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
{
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct fp_img_dev *dev = user_data;
struct vfs5011_data *data;
data = fpi_imgdev_get_user_data(dev);
data = FP_INSTANCE_DATA(_dev);
switch (fpi_ssm_get_cur_state(ssm)) {
case DEV_OPEN_START:
@@ -793,12 +776,12 @@ static void open_loop(struct fpi_ssm *ssm)
};
}
static void open_loop_complete(struct fpi_ssm *ssm)
static void open_loop_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
{
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct fp_img_dev *dev = user_data;
struct vfs5011_data *data;
data = fpi_imgdev_get_user_data(dev);
data = FP_INSTANCE_DATA(_dev);
g_free(data->init_sequence.receive_buf);
data->init_sequence.receive_buf = NULL;
@@ -815,23 +798,22 @@ static int dev_open(struct fp_img_dev *dev, unsigned long driver_data)
data = (struct vfs5011_data *)g_malloc0(sizeof(*data));
data->capture_buffer =
(unsigned char *)g_malloc0(CAPTURE_LINES * VFS5011_LINE_SIZE);
fpi_imgdev_set_user_data(dev, data);
fp_dev_set_instance_data(FP_DEV(dev), data);
r = libusb_reset_device(fpi_imgdev_get_usb_dev(dev));
r = libusb_reset_device(fpi_dev_get_usb_dev(FP_DEV(dev)));
if (r != 0) {
fp_err("Failed to reset the device");
return r;
}
r = libusb_claim_interface(fpi_imgdev_get_usb_dev(dev), 0);
r = libusb_claim_interface(fpi_dev_get_usb_dev(FP_DEV(dev)), 0);
if (r != 0) {
fp_err("Failed to claim interface: %s", libusb_error_name(r));
return r;
}
struct fpi_ssm *ssm;
ssm = fpi_ssm_new(fpi_imgdev_get_dev(dev), open_loop, DEV_OPEN_NUM_STATES);
fpi_ssm_set_user_data(ssm, dev);
fpi_ssm *ssm;
ssm = fpi_ssm_new(FP_DEV(dev), open_loop, DEV_OPEN_NUM_STATES, dev);
fpi_ssm_start(ssm, open_loop_complete);
return 0;
@@ -839,9 +821,9 @@ static int dev_open(struct fp_img_dev *dev, unsigned long driver_data)
static void dev_close(struct fp_img_dev *dev)
{
libusb_release_interface(fpi_imgdev_get_usb_dev(dev), 0);
libusb_release_interface(fpi_dev_get_usb_dev(FP_DEV(dev)), 0);
struct vfs5011_data *data;
data = fpi_imgdev_get_user_data(dev);
data = FP_INSTANCE_DATA(FP_DEV(dev));
if (data != NULL) {
g_free(data->capture_buffer);
g_slist_free_full(data->rows, g_free);
@@ -853,23 +835,22 @@ static void dev_close(struct fp_img_dev *dev)
static void start_scan(struct fp_img_dev *dev)
{
struct vfs5011_data *data;
struct fpi_ssm *ssm;
fpi_ssm *ssm;
data = fpi_imgdev_get_user_data(dev);
data = FP_INSTANCE_DATA(FP_DEV(dev));
data->loop_running = TRUE;
fp_dbg("creating ssm");
ssm = fpi_ssm_new(fpi_imgdev_get_dev(dev), activate_loop, DEV_ACTIVATE_NUM_STATES);
fpi_ssm_set_user_data(ssm, dev);
ssm = fpi_ssm_new(FP_DEV(dev), activate_loop, DEV_ACTIVATE_NUM_STATES, dev);
fp_dbg("starting ssm");
fpi_ssm_start(ssm, activate_loop_complete);
fp_dbg("ssm done, getting out");
}
static int dev_activate(struct fp_img_dev *dev, enum fp_imgdev_state state)
static int dev_activate(struct fp_img_dev *dev)
{
struct vfs5011_data *data;
data = fpi_imgdev_get_user_data(dev);
data = FP_INSTANCE_DATA(FP_DEV(dev));
fp_dbg("device initialized");
data->deactivating = FALSE;
@@ -883,7 +864,7 @@ static void dev_deactivate(struct fp_img_dev *dev)
int r;
struct vfs5011_data *data;
data = fpi_imgdev_get_user_data(dev);
data = FP_INSTANCE_DATA(FP_DEV(dev));
if (data->loop_running) {
data->deactivating = TRUE;
if (data->flying_transfer) {
@@ -898,6 +879,7 @@ static void dev_deactivate(struct fp_img_dev *dev)
static const struct usb_id id_table[] = {
{ .vendor = 0x138a, .product = 0x0010 /* Validity device from some Toshiba laptops */ },
{ .vendor = 0x138a, .product = 0x0011 /* vfs5011 */ },
{ .vendor = 0x138a, .product = 0x0015 /* Validity device from Lenovo Preferred Pro USB Fingerprint Keyboard KUF1256 */ },
{ .vendor = 0x138a, .product = 0x0017 /* Validity device from Lenovo T440 laptops */ },
{ .vendor = 0x138a, .product = 0x0018 /* one more Validity device */ },
{ 0, 0, 0, },

View File

@@ -23,288 +23,17 @@
#include <config.h>
#ifdef FP_COMPONENT
#undef G_LOG_DOMAIN
#define G_LOG_DOMAIN "libfprint-"FP_COMPONENT
#endif
#include <stdint.h>
#include <errno.h>
#include <glib.h>
#include <libusb.h>
#include "fprint.h"
#include "assembling.h"
#include "fpi-log.h"
#include "fpi-dev.h"
#include "fpi-dev-img.h"
#include "fpi-core.h"
#include "fpi-ssm.h"
#include "fpi-poll.h"
#include "fpi-dev.h"
#include "fpi-usb.h"
#include "fpi-img.h"
#include "fpi-assembling.h"
#include "drivers/driver_ids.h"
#define fp_dbg g_debug
#define fp_info g_debug
#define fp_warn g_warning
#define fp_err g_warning
#define BUG_ON(condition) G_STMT_START \
if (condition) { \
char *s; \
s = g_strconcat ("BUG: (", #condition, ")", NULL); \
g_warning ("%s: %s() %s:%d", s, G_STRFUNC, __FILE__, __LINE__); \
g_free (s); \
} G_STMT_END
#define BUG() BUG_ON(1)
enum fp_dev_state {
DEV_STATE_INITIAL = 0,
DEV_STATE_ERROR,
DEV_STATE_INITIALIZING,
DEV_STATE_INITIALIZED,
DEV_STATE_DEINITIALIZING,
DEV_STATE_DEINITIALIZED,
DEV_STATE_ENROLL_STARTING,
DEV_STATE_ENROLLING,
DEV_STATE_ENROLL_STOPPING,
DEV_STATE_VERIFY_STARTING,
DEV_STATE_VERIFYING,
DEV_STATE_VERIFY_DONE,
DEV_STATE_VERIFY_STOPPING,
DEV_STATE_IDENTIFY_STARTING,
DEV_STATE_IDENTIFYING,
DEV_STATE_IDENTIFY_DONE,
DEV_STATE_IDENTIFY_STOPPING,
DEV_STATE_CAPTURE_STARTING,
DEV_STATE_CAPTURING,
DEV_STATE_CAPTURE_DONE,
DEV_STATE_CAPTURE_STOPPING,
};
struct fp_dev;
libusb_device_handle *fpi_dev_get_usb_dev(struct fp_dev *dev);
void *fpi_dev_get_user_data (struct fp_dev *dev);
void fpi_dev_set_user_data (struct fp_dev *dev, void *user_data);
int fpi_dev_get_nr_enroll_stages(struct fp_dev *dev);
void fpi_dev_set_nr_enroll_stages(struct fp_dev *dev, int nr_enroll_stages);
struct fp_print_data *fpi_dev_get_verify_data(struct fp_dev *dev);
enum fp_dev_state fpi_dev_get_dev_state(struct fp_dev *dev);
enum fp_imgdev_state {
IMGDEV_STATE_INACTIVE,
IMGDEV_STATE_AWAIT_FINGER_ON,
IMGDEV_STATE_CAPTURE,
IMGDEV_STATE_AWAIT_FINGER_OFF,
};
enum fp_imgdev_action {
IMG_ACTION_NONE = 0,
IMG_ACTION_ENROLL,
IMG_ACTION_VERIFY,
IMG_ACTION_IDENTIFY,
IMG_ACTION_CAPTURE,
};
enum fp_imgdev_enroll_state {
IMG_ACQUIRE_STATE_NONE = 0,
IMG_ACQUIRE_STATE_ACTIVATING,
IMG_ACQUIRE_STATE_AWAIT_FINGER_ON,
IMG_ACQUIRE_STATE_AWAIT_IMAGE,
IMG_ACQUIRE_STATE_AWAIT_FINGER_OFF,
IMG_ACQUIRE_STATE_DONE,
IMG_ACQUIRE_STATE_DEACTIVATING,
};
enum fp_imgdev_verify_state {
IMG_VERIFY_STATE_NONE = 0,
IMG_VERIFY_STATE_ACTIVATING
};
struct fp_img_dev;
libusb_device_handle *fpi_imgdev_get_usb_dev(struct fp_img_dev *dev);
void fpi_imgdev_set_user_data(struct fp_img_dev *imgdev,
void *user_data);
void *fpi_imgdev_get_user_data(struct fp_img_dev *imgdev);
struct fp_dev *fpi_imgdev_get_dev(struct fp_img_dev *imgdev);
enum fp_imgdev_enroll_state fpi_imgdev_get_action_state(struct fp_img_dev *imgdev);
enum fp_imgdev_action fpi_imgdev_get_action(struct fp_img_dev *imgdev);
int fpi_imgdev_get_action_result(struct fp_img_dev *imgdev);
void fpi_imgdev_set_action_result(struct fp_img_dev *imgdev, int action_result);
int fpi_imgdev_get_img_width(struct fp_img_dev *imgdev);
int fpi_imgdev_get_img_height(struct fp_img_dev *imgdev);
struct usb_id {
uint16_t vendor;
uint16_t product;
unsigned long driver_data;
};
enum fp_driver_type {
DRIVER_PRIMITIVE = 0,
DRIVER_IMAGING = 1,
};
struct fp_driver {
const uint16_t id;
const char *name;
const char *full_name;
const struct usb_id * const id_table;
enum fp_driver_type type;
enum fp_scan_type scan_type;
void *priv;
/* Device operations */
int (*discover)(struct libusb_device_descriptor *dsc, uint32_t *devtype);
int (*open)(struct fp_dev *dev, unsigned long driver_data);
void (*close)(struct fp_dev *dev);
int (*enroll_start)(struct fp_dev *dev);
int (*enroll_stop)(struct fp_dev *dev);
int (*verify_start)(struct fp_dev *dev);
int (*verify_stop)(struct fp_dev *dev, gboolean iterating);
int (*identify_start)(struct fp_dev *dev);
int (*identify_stop)(struct fp_dev *dev, gboolean iterating);
int (*capture_start)(struct fp_dev *dev);
int (*capture_stop)(struct fp_dev *dev);
};
/* flags for fp_img_driver.flags */
#define FP_IMGDRV_SUPPORTS_UNCONDITIONAL_CAPTURE (1 << 0)
struct fp_img_driver {
struct fp_driver driver;
uint16_t flags;
int img_width;
int img_height;
int bz3_threshold;
/* Device operations */
int (*open)(struct fp_img_dev *dev, unsigned long driver_data);
void (*close)(struct fp_img_dev *dev);
int (*activate)(struct fp_img_dev *dev, enum fp_imgdev_state state);
int (*change_state)(struct fp_img_dev *dev, enum fp_imgdev_state state);
void (*deactivate)(struct fp_img_dev *dev);
};
enum fp_print_data_type {
PRINT_DATA_RAW = 0, /* memset-imposed default */
PRINT_DATA_NBIS_MINUTIAE,
};
struct fp_print_data_item {
size_t length;
unsigned char data[0];
};
struct fp_print_data {
uint16_t driver_id;
uint32_t devtype;
enum fp_print_data_type type;
GSList *prints;
};
struct fp_print_data *fpi_print_data_new(struct fp_dev *dev);
struct fp_print_data_item *fpi_print_data_item_new(size_t length);
gboolean fpi_print_data_compatible(uint16_t driver_id1, uint32_t devtype1,
enum fp_print_data_type type1, uint16_t driver_id2, uint32_t devtype2,
enum fp_print_data_type type2);
struct fp_minutiae;
/* bit values for fp_img.flags */
#define FP_IMG_V_FLIPPED (1<<0)
#define FP_IMG_H_FLIPPED (1<<1)
#define FP_IMG_COLORS_INVERTED (1<<2)
#define FP_IMG_BINARIZED_FORM (1<<3)
#define FP_IMG_PARTIAL (1<<4)
#define FP_IMG_STANDARDIZATION_FLAGS (FP_IMG_V_FLIPPED | FP_IMG_H_FLIPPED \
| FP_IMG_COLORS_INVERTED)
struct fp_img {
int width;
int height;
size_t length;
uint16_t flags;
struct fp_minutiae *minutiae;
unsigned char *binarized;
unsigned char data[0];
};
struct fp_img *fpi_img_new(size_t length);
struct fp_img *fpi_img_new_for_imgdev(struct fp_img_dev *dev);
struct fp_img *fpi_img_resize(struct fp_img *img, size_t newsize);
struct fp_img *fpi_im_resize(struct fp_img *img, unsigned int w_factor, unsigned int h_factor);
/* polling and timeouts */
typedef void (*fpi_timeout_fn)(void *data);
struct fpi_timeout;
struct fpi_timeout *fpi_timeout_add(unsigned int msec, fpi_timeout_fn callback,
void *data);
void fpi_timeout_cancel(struct fpi_timeout *timeout);
/* async drv <--> lib comms */
struct fpi_ssm;
typedef void (*ssm_completed_fn)(struct fpi_ssm *ssm);
typedef void (*ssm_handler_fn)(struct fpi_ssm *ssm);
/* sequential state machine: state machine that iterates sequentially over
* a predefined series of states. can be aborted by either completion or
* abortion error conditions. */
/* for library and drivers */
struct fpi_ssm *fpi_ssm_new(struct fp_dev *dev, ssm_handler_fn handler,
int nr_states);
void fpi_ssm_free(struct fpi_ssm *machine);
void fpi_ssm_start(struct fpi_ssm *machine, ssm_completed_fn callback);
void fpi_ssm_start_subsm(struct fpi_ssm *parent, struct fpi_ssm *child);
/* for drivers */
void fpi_ssm_next_state(struct fpi_ssm *machine);
void fpi_ssm_jump_to_state(struct fpi_ssm *machine, int state);
void fpi_ssm_mark_completed(struct fpi_ssm *machine);
void fpi_ssm_mark_aborted(struct fpi_ssm *machine, int error);
struct fp_dev *fpi_ssm_get_dev(struct fpi_ssm *machine);
void fpi_ssm_set_user_data(struct fpi_ssm *machine,
void *user_data);
void *fpi_ssm_get_user_data(struct fpi_ssm *machine);
int fpi_ssm_get_error(struct fpi_ssm *machine);
int fpi_ssm_get_cur_state(struct fpi_ssm *machine);
void fpi_drvcb_open_complete(struct fp_dev *dev, int status);
void fpi_drvcb_close_complete(struct fp_dev *dev);
void fpi_drvcb_enroll_started(struct fp_dev *dev, int status);
void fpi_drvcb_enroll_stage_completed(struct fp_dev *dev, int result,
struct fp_print_data *data, struct fp_img *img);
void fpi_drvcb_enroll_stopped(struct fp_dev *dev);
void fpi_drvcb_verify_started(struct fp_dev *dev, int status);
void fpi_drvcb_report_verify_result(struct fp_dev *dev, int result,
struct fp_img *img);
void fpi_drvcb_verify_stopped(struct fp_dev *dev);
void fpi_drvcb_identify_started(struct fp_dev *dev, int status);
void fpi_drvcb_report_identify_result(struct fp_dev *dev, int result,
size_t match_offset, struct fp_img *img);
void fpi_drvcb_identify_stopped(struct fp_dev *dev);
void fpi_drvcb_capture_started(struct fp_dev *dev, int status);
void fpi_drvcb_report_capture_result(struct fp_dev *dev, int result,
struct fp_img *img);
void fpi_drvcb_capture_stopped(struct fp_dev *dev);
/* for image drivers */
void fpi_imgdev_open_complete(struct fp_img_dev *imgdev, int status);
void fpi_imgdev_close_complete(struct fp_img_dev *imgdev);
void fpi_imgdev_activate_complete(struct fp_img_dev *imgdev, int status);
void fpi_imgdev_deactivate_complete(struct fp_img_dev *imgdev);
void fpi_imgdev_report_finger_status(struct fp_img_dev *imgdev,
gboolean present);
void fpi_imgdev_image_captured(struct fp_img_dev *imgdev, struct fp_img *img);
void fpi_imgdev_abort_scan(struct fp_img_dev *imgdev, int result);
void fpi_imgdev_session_error(struct fp_img_dev *imgdev, int error);
/* utils */
int fpi_std_sq_dev(const unsigned char *buf, int size);
int fpi_mean_sq_diff_norm(unsigned char *buf1, unsigned char *buf2, int size);
#endif

View File

@@ -1,199 +0,0 @@
/*
* Functions to assist with asynchronous driver <---> library communications
* 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
*/
#define FP_COMPONENT "drv"
#include "fp_internal.h"
#include <config.h>
#include <errno.h>
/* SSM: sequential state machine
* Asynchronous driver design encourages some kind of state machine behind it.
* In most cases, the state machine is entirely linear - you only go to the
* next state, you never jump or go backwards. The SSM functions help you
* implement such a machine.
*
* e.g. S1 --> S2 --> S3 --> S4
* S1 is the start state
* There is also an implicit error state and an implicit accepting state
* (both with implicit edges from every state).
*
* You can also jump to any arbitrary state (while marking completion of the
* current state) while the machine is running. In other words there are
* implicit edges linking one state to every other state. OK, we're stretching
* the "state machine" description at this point.
*
* To create a ssm, you pass a state handler function and the total number of
* states (4 in the above example).
*
* To start a ssm, you pass in a completion callback function which gets
* called when the ssm completes (both on error and on failure).
*
* 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
* the ssm as successfully completed.
*
* To mark successful completion of a SSM, either iterate beyond the final
* state or call fpi_ssm_mark_completed() from any state.
*
* To mark failed completion of a SSM, call fpi_ssm_mark_aborted() from any
* state. You must pass a non-zero error code.
*
* Your state handling function looks at ssm->cur_state in order to determine
* the current state and hence which operations to perform (a switch statement
* is appropriate).
* Typically, the state handling function fires off an asynchronous libusb
* transfer, and the callback function iterates the machine to the next state
* upon success (or aborts the machine on transfer failure).
*
* Your completion callback should examine ssm->error in order to determine
* whether the ssm completed or failed. An error code of zero indicates
* successful completion.
*/
/* Allocate a new ssm */
struct fpi_ssm *fpi_ssm_new(struct fp_dev *dev, ssm_handler_fn handler,
int nr_states)
{
struct fpi_ssm *machine;
BUG_ON(nr_states < 1);
machine = g_malloc0(sizeof(*machine));
machine->handler = handler;
machine->nr_states = nr_states;
machine->dev = dev;
machine->completed = TRUE;
return machine;
}
struct fp_dev *
fpi_ssm_get_dev(struct fpi_ssm *machine)
{
return machine->dev;
}
void
fpi_ssm_set_user_data(struct fpi_ssm *machine,
void *user_data)
{
machine->priv = user_data;
}
void *
fpi_ssm_get_user_data(struct fpi_ssm *machine)
{
return machine->priv;
}
/* Free a ssm */
void fpi_ssm_free(struct fpi_ssm *machine)
{
if (!machine)
return;
g_free(machine);
}
/* Invoke the state handler */
static void __ssm_call_handler(struct fpi_ssm *machine)
{
fp_dbg("%p entering state %d", machine, machine->cur_state);
machine->handler(machine);
}
/* Start a ssm. You can also restart a completed or aborted ssm. */
void fpi_ssm_start(struct fpi_ssm *ssm, ssm_completed_fn callback)
{
BUG_ON(!ssm->completed);
ssm->callback = callback;
ssm->cur_state = 0;
ssm->completed = FALSE;
ssm->error = 0;
__ssm_call_handler(ssm);
}
static void __subsm_complete(struct fpi_ssm *ssm)
{
struct fpi_ssm *parent = ssm->parentsm;
BUG_ON(!parent);
if (ssm->error)
fpi_ssm_mark_aborted(parent, ssm->error);
else
fpi_ssm_next_state(parent);
fpi_ssm_free(ssm);
}
/* start a SSM as a child of another. if the child completes successfully, the
* parent will be advanced to the next state. if the child aborts, the parent
* will be aborted with the same error code. the child will be automatically
* freed upon completion/abortion. */
void fpi_ssm_start_subsm(struct fpi_ssm *parent, struct fpi_ssm *child)
{
child->parentsm = parent;
fpi_ssm_start(child, __subsm_complete);
}
/* Mark a ssm as completed successfully. */
void fpi_ssm_mark_completed(struct fpi_ssm *machine)
{
BUG_ON(machine->completed);
machine->completed = TRUE;
fp_dbg("%p completed with status %d", machine, machine->error);
if (machine->callback)
machine->callback(machine);
}
/* Mark a ssm as aborted with error. */
void fpi_ssm_mark_aborted(struct fpi_ssm *machine, int error)
{
fp_dbg("error %d from state %d", error, machine->cur_state);
BUG_ON(error == 0);
machine->error = error;
fpi_ssm_mark_completed(machine);
}
/* Iterate to next state of a ssm */
void fpi_ssm_next_state(struct fpi_ssm *machine)
{
BUG_ON(machine->completed);
machine->cur_state++;
if (machine->cur_state == machine->nr_states) {
fpi_ssm_mark_completed(machine);
} else {
__ssm_call_handler(machine);
}
}
void fpi_ssm_jump_to_state(struct fpi_ssm *machine, int state)
{
BUG_ON(machine->completed);
BUG_ON(state >= machine->nr_states);
machine->cur_state = state;
__ssm_call_handler(machine);
}
int fpi_ssm_get_cur_state(struct fpi_ssm *machine)
{
return machine->cur_state;
}
int fpi_ssm_get_error(struct fpi_ssm *machine)
{
return machine->error;
}

View File

@@ -22,37 +22,39 @@
#include <config.h>
#ifdef FP_COMPONENT
#undef G_LOG_DOMAIN
#define G_LOG_DOMAIN "libfprint-"FP_COMPONENT
#endif
#include <stdint.h>
#include <errno.h>
#include <glib.h>
#include <libusb.h>
#include "nbis-helpers.h"
#include "fprint.h"
#include "fpi-dev.h"
#include "fpi-core.h"
#include "fpi-log.h"
#include "fpi-dev-img.h"
#include "fpi-data.h"
#include "fpi-img.h"
#include "drivers/driver_ids.h"
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - offsetof(type,member) );})
/* Global variables */
extern libusb_context *fpi_usb_ctx;
extern GSList *opened_devices;
#define fp_dbg g_debug
#define fp_info g_debug
#define fp_warn g_warning
#define fp_err g_warning
/* fp_print_data structure definition */
enum fp_print_data_type {
PRINT_DATA_RAW = 0, /* memset-imposed default */
PRINT_DATA_NBIS_MINUTIAE
};
#define BUG_ON(condition) G_STMT_START \
if (condition) { \
char *s; \
s = g_strconcat ("BUG: (", #condition, ")", NULL); \
g_warning ("%s: %s() %s:%d", s, G_STRFUNC, __FILE__, __LINE__); \
g_free (s); \
} G_STMT_END
#define BUG() BUG_ON(1)
struct fp_print_data {
uint16_t driver_id;
uint32_t devtype;
enum fp_print_data_type type;
GSList *prints;
};
/* fp_dev structure definition */
enum fp_dev_state {
DEV_STATE_INITIAL = 0,
DEV_STATE_ERROR,
@@ -77,16 +79,20 @@ enum fp_dev_state {
DEV_STATE_CAPTURE_STOPPING,
};
struct fp_driver **fprint_get_drivers (void);
struct fp_dev {
struct fp_driver *drv;
libusb_device_handle *udev;
uint32_t devtype;
void *priv;
/* only valid if drv->type == DRIVER_IMAGING */
struct fp_img_dev *img_dev;
/* Link to the instance specific struct */
void *instance_data;
int nr_enroll_stages;
/* FIXME: This will eventually have a bus type */
libusb_device_handle *udev;
/* read-only to drivers */
struct fp_print_data *verify_data;
@@ -122,39 +128,10 @@ struct fp_dev {
struct fp_print_data **identify_gallery;
};
enum fp_imgdev_state {
IMGDEV_STATE_INACTIVE,
IMGDEV_STATE_AWAIT_FINGER_ON,
IMGDEV_STATE_CAPTURE,
IMGDEV_STATE_AWAIT_FINGER_OFF,
};
enum fp_imgdev_action {
IMG_ACTION_NONE = 0,
IMG_ACTION_ENROLL,
IMG_ACTION_VERIFY,
IMG_ACTION_IDENTIFY,
IMG_ACTION_CAPTURE,
};
enum fp_imgdev_enroll_state {
IMG_ACQUIRE_STATE_NONE = 0,
IMG_ACQUIRE_STATE_ACTIVATING,
IMG_ACQUIRE_STATE_AWAIT_FINGER_ON,
IMG_ACQUIRE_STATE_AWAIT_IMAGE,
IMG_ACQUIRE_STATE_AWAIT_FINGER_OFF,
IMG_ACQUIRE_STATE_DONE,
IMG_ACQUIRE_STATE_DEACTIVATING,
};
enum fp_imgdev_verify_state {
IMG_VERIFY_STATE_NONE = 0,
IMG_VERIFY_STATE_ACTIVATING
};
/* fp_img_dev structure definition */
struct fp_img_dev {
struct fp_dev *dev;
libusb_device_handle *udev;
struct fp_dev *parent;
enum fp_imgdev_action action;
int action_state;
@@ -166,78 +143,18 @@ struct fp_img_dev {
/* FIXME: better place to put this? */
size_t identify_match_offset;
void *priv;
};
int fpi_imgdev_get_img_width(struct fp_img_dev *imgdev);
int fpi_imgdev_get_img_height(struct fp_img_dev *imgdev);
struct usb_id {
uint16_t vendor;
uint16_t product;
unsigned long driver_data;
};
enum fp_driver_type {
DRIVER_PRIMITIVE = 0,
DRIVER_IMAGING = 1,
};
struct fp_driver {
const uint16_t id;
const char *name;
const char *full_name;
const struct usb_id * const id_table;
enum fp_driver_type type;
enum fp_scan_type scan_type;
void *priv;
/* Device operations */
int (*discover)(struct libusb_device_descriptor *dsc, uint32_t *devtype);
int (*open)(struct fp_dev *dev, unsigned long driver_data);
void (*close)(struct fp_dev *dev);
int (*enroll_start)(struct fp_dev *dev);
int (*enroll_stop)(struct fp_dev *dev);
int (*verify_start)(struct fp_dev *dev);
int (*verify_stop)(struct fp_dev *dev, gboolean iterating);
int (*identify_start)(struct fp_dev *dev);
int (*identify_stop)(struct fp_dev *dev, gboolean iterating);
int (*capture_start)(struct fp_dev *dev);
int (*capture_stop)(struct fp_dev *dev);
};
enum fp_print_data_type fpi_driver_get_data_type(struct fp_driver *drv);
/* flags for fp_img_driver.flags */
#define FP_IMGDRV_SUPPORTS_UNCONDITIONAL_CAPTURE (1 << 0)
struct fp_img_driver {
struct fp_driver driver;
uint16_t flags;
int img_width;
int img_height;
int bz3_threshold;
/* Device operations */
int (*open)(struct fp_img_dev *dev, unsigned long driver_data);
void (*close)(struct fp_img_dev *dev);
int (*activate)(struct fp_img_dev *dev, enum fp_imgdev_state state);
int (*change_state)(struct fp_img_dev *dev, enum fp_imgdev_state state);
void (*deactivate)(struct fp_img_dev *dev);
};
#include "drivers_definitions.h"
extern libusb_context *fpi_usb_ctx;
extern GSList *opened_devices;
void fpi_img_driver_setup(struct fp_img_driver *idriver);
/* fp_driver structure definition */
/* fp_img_driver structure definition */
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - offsetof(type,member) );})
#define fpi_driver_to_img_driver(drv) \
container_of((drv), struct fp_img_driver, driver)
/* fp_dscv_dev structure definition */
struct fp_dscv_dev {
struct libusb_device *udev;
struct fp_driver *drv;
@@ -245,6 +162,7 @@ struct fp_dscv_dev {
uint32_t devtype;
};
/* fp_dscv_print structure definition */
struct fp_dscv_print {
uint16_t driver_id;
uint32_t devtype;
@@ -252,43 +170,7 @@ struct fp_dscv_print {
char *path;
};
enum fp_print_data_type {
PRINT_DATA_RAW = 0, /* memset-imposed default */
PRINT_DATA_NBIS_MINUTIAE,
};
struct fp_print_data_item {
size_t length;
unsigned char data[0];
};
struct fp_print_data {
uint16_t driver_id;
uint32_t devtype;
enum fp_print_data_type type;
GSList *prints;
};
struct fpi_print_data_fp2 {
char prefix[3];
uint16_t driver_id;
uint32_t devtype;
unsigned char data_type;
unsigned char data[0];
} __attribute__((__packed__));
struct fpi_print_data_item_fp2 {
uint32_t length;
unsigned char data[0];
} __attribute__((__packed__));
void fpi_data_exit(void);
struct fp_print_data *fpi_print_data_new(struct fp_dev *dev);
struct fp_print_data_item *fpi_print_data_item_new(size_t length);
gboolean fpi_print_data_compatible(uint16_t driver_id1, uint32_t devtype1,
enum fp_print_data_type type1, uint16_t driver_id2, uint32_t devtype2,
enum fp_print_data_type type2);
/* fp_minutia structure definition */
struct fp_minutia {
int x;
int y;
@@ -304,34 +186,32 @@ struct fp_minutia {
int num_nbrs;
};
/* fp_minutiae structure definition */
struct fp_minutiae {
int alloc;
int num;
struct fp_minutia **list;
};
/* bit values for fp_img.flags */
#define FP_IMG_V_FLIPPED (1<<0)
#define FP_IMG_H_FLIPPED (1<<1)
#define FP_IMG_COLORS_INVERTED (1<<2)
#define FP_IMG_BINARIZED_FORM (1<<3)
#define FP_IMG_PARTIAL (1<<4)
/* Defined in fpi-dev-img.c */
void fpi_img_driver_setup(struct fp_img_driver *idriver);
int fpi_imgdev_get_img_width(struct fp_img_dev *imgdev);
int fpi_imgdev_get_img_height(struct fp_img_dev *imgdev);
#define FP_IMG_STANDARDIZATION_FLAGS (FP_IMG_V_FLIPPED | FP_IMG_H_FLIPPED \
| FP_IMG_COLORS_INVERTED)
/* Exported for use in command-line tools
* Defined in fpi-core.c */
struct fp_driver **fprint_get_drivers (void);
struct fp_img {
int width;
int height;
size_t length;
uint16_t flags;
struct fp_minutiae *minutiae;
unsigned char *binarized;
unsigned char data[0];
};
/* Defined in fpi-core.c */
enum fp_print_data_type fpi_driver_get_data_type(struct fp_driver *drv);
struct fp_img *fpi_img_new(size_t length);
struct fp_img *fpi_img_resize(struct fp_img *img, size_t newsize);
/* Defined in fpi-data.c */
void fpi_data_exit(void);
gboolean fpi_print_data_compatible(uint16_t driver_id1, uint32_t devtype1,
enum fp_print_data_type type1, uint16_t driver_id2, uint32_t devtype2,
enum fp_print_data_type type2);
/* Defined in fpi-img.c */
gboolean fpi_img_is_sane(struct fp_img *img);
int fpi_img_to_print_data(struct fp_img_dev *imgdev, struct fp_img *img,
struct fp_print_data **ret);
@@ -339,71 +219,23 @@ int fpi_img_compare_print_data(struct fp_print_data *enrolled_print,
struct fp_print_data *new_print);
int fpi_img_compare_print_data_to_gallery(struct fp_print_data *print,
struct fp_print_data **gallery, int match_threshold, size_t *match_offset);
struct fp_img *fpi_im_resize(struct fp_img *img, unsigned int w_factor, unsigned int h_factor);
/* polling and timeouts */
/* Defined in fpi-poll.c */
void fpi_timeout_cancel_all_for_dev(struct fp_dev *dev);
void fpi_poll_init(void);
void fpi_poll_exit(void);
typedef void (*fpi_timeout_fn)(void *data);
/* async drv <--> lib comms */
struct fpi_ssm;
typedef void (*ssm_completed_fn)(struct fpi_ssm *ssm);
typedef void (*ssm_handler_fn)(struct fpi_ssm *ssm);
/* sequential state machine: state machine that iterates sequentially over
* a predefined series of states. can be aborted by either completion or
* abortion error conditions. */
struct fpi_ssm {
struct fp_dev *dev;
struct fpi_ssm *parentsm;
void *priv;
int nr_states;
int cur_state;
gboolean completed;
int error;
ssm_completed_fn callback;
ssm_handler_fn handler;
};
/* for library and drivers */
struct fpi_ssm *fpi_ssm_new(struct fp_dev *dev, ssm_handler_fn handler,
int nr_states);
void fpi_ssm_free(struct fpi_ssm *machine);
void fpi_ssm_start(struct fpi_ssm *machine, ssm_completed_fn callback);
/* for drivers */
void fpi_ssm_next_state(struct fpi_ssm *machine);
void fpi_ssm_jump_to_state(struct fpi_ssm *machine, int state);
void fpi_ssm_mark_completed(struct fpi_ssm *machine);
void fpi_ssm_mark_aborted(struct fpi_ssm *machine, int error);
void fpi_drvcb_open_complete(struct fp_dev *dev, int status);
void fpi_drvcb_close_complete(struct fp_dev *dev);
void fpi_drvcb_enroll_started(struct fp_dev *dev, int status);
void fpi_drvcb_enroll_stage_completed(struct fp_dev *dev, int result,
struct fp_print_data *data, struct fp_img *img);
void fpi_drvcb_enroll_stopped(struct fp_dev *dev);
void fpi_drvcb_verify_started(struct fp_dev *dev, int status);
void fpi_drvcb_report_verify_result(struct fp_dev *dev, int result,
/* Defined in fpi-async.c */
void fpi_drvcb_capture_started(struct fp_dev *dev, int status);
void fpi_drvcb_report_capture_result(struct fp_dev *dev, int result,
struct fp_img *img);
void fpi_drvcb_verify_stopped(struct fp_dev *dev);
void fpi_drvcb_capture_stopped(struct fp_dev *dev);
void fpi_drvcb_identify_started(struct fp_dev *dev, int status);
void fpi_drvcb_report_identify_result(struct fp_dev *dev, int result,
size_t match_offset, struct fp_img *img);
void fpi_drvcb_identify_stopped(struct fp_dev *dev);
void fpi_drvcb_capture_started(struct fp_dev *dev, int status);
void fpi_drvcb_report_capture_result(struct fp_dev *dev, int result,
struct fp_img *img);
void fpi_drvcb_capture_stopped(struct fp_dev *dev);
#include "drivers_definitions.h"
#endif

View File

@@ -29,7 +29,18 @@
#include <libusb.h>
#include <glib.h>
#include "assembling.h"
#include "fpi-assembling.h"
/**
* SECTION:fpi-assembling
* @title: Image frame assembly
* @short_description: Image frame assembly helpers
*
* Those are the helpers to manipulate capture data from fingerprint readers
* into a uniform image that can be further processed. This is usually used
* by drivers for devices which have a small sensor and thus need to capture
* data in small stripes.
*/
static unsigned int calc_error(struct fpi_frame_asmbl_ctx *ctx,
struct fpi_frame *first_frame,
@@ -152,6 +163,22 @@ static unsigned int do_movement_estimation(struct fpi_frame_asmbl_ctx *ctx,
return total_error / num_stripes;
}
/**
* fpi_do_movement_estimation:
* @ctx: #fpi_frame_asmbl_ctx - frame assembling context
* @stripes: a singly-linked list of #fpi_frame
* @num_stripes: number of items in @stripes to process
*
* fpi_do_movement_estimation() estimates the movement between adjacent
* frames, populating @delta_x and @delta_y values for each #fpi_frame.
*
* This function is used for devices that don't do movement estimation
* in hardware. If hardware movement estimation is supported, the driver
* should populate @delta_x and @delta_y instead.
*
* Note that @num_stripes might be shorter than the length of the list,
* if some stripes should be skipped.
*/
void fpi_do_movement_estimation(struct fpi_frame_asmbl_ctx *ctx,
GSList *stripes, size_t num_stripes)
{
@@ -225,8 +252,22 @@ static inline void aes_blit_stripe(struct fpi_frame_asmbl_ctx *ctx,
}
}
/**
* fpi_assemble_frames:
* @ctx: #fpi_frame_asmbl_ctx - frame assembling context
* @stripes: linked list of #fpi_frame
* @num_stripes: number of items in @stripes to process
*
* fpi_assemble_frames() assembles individual frames into a single image.
* It expects @delta_x and @delta_y of #fpi_frame to be populated.
*
* Note that @num_stripes might be shorter than the length of the list,
* if some stripes should be skipped.
*
* Returns: a newly allocated #fp_img.
*/
struct fp_img *fpi_assemble_frames(struct fpi_frame_asmbl_ctx *ctx,
GSList *stripes, size_t stripes_len)
GSList *stripes, size_t num_stripes)
{
GSList *stripe;
struct fp_img *img;
@@ -235,7 +276,8 @@ struct fp_img *fpi_assemble_frames(struct fpi_frame_asmbl_ctx *ctx,
gboolean reverse = FALSE;
struct fpi_frame *fpi_frame;
BUG_ON(stripes_len == 0);
//FIXME g_return_if_fail
BUG_ON(num_stripes == 0);
BUG_ON(ctx->image_width < ctx->frame_width);
/* Calculate height */
@@ -252,7 +294,7 @@ struct fp_img *fpi_assemble_frames(struct fpi_frame_asmbl_ctx *ctx,
height += fpi_frame->delta_y;
i++;
stripe = g_slist_next(stripe);
} while (i < stripes_len);
} while (i < num_stripes);
fp_dbg("height is %d", height);
@@ -294,7 +336,7 @@ struct fp_img *fpi_assemble_frames(struct fpi_frame_asmbl_ctx *ctx,
stripe = g_slist_next(stripe);
i++;
} while (i < stripes_len);
} while (i < num_stripes);
return img;
}
@@ -350,34 +392,45 @@ static void interpolate_lines(struct fpi_line_asmbl_ctx *ctx,
}
}
static int min(int a, int b) {return (a < b) ? a : b; }
/* Rescale image to account for variable swiping speed */
/**
* fpi_assemble_lines:
* @ctx: #fpi_frame_asmbl_ctx - frame assembling context
* @lines: linked list of lines
* @num_lines: number of items in @lines to process
*
* #fpi_assemble_lines assembles individual lines into a single image.
* It also rescales image to account variable swiping speed.
*
* Note that @num_lines might be shorter than the length of the list,
* if some lines should be skipped.
*
* Returns: a newly allocated #fp_img.
*/
struct fp_img *fpi_assemble_lines(struct fpi_line_asmbl_ctx *ctx,
GSList *lines, size_t lines_len)
GSList *lines, size_t num_lines)
{
/* Number of output lines per distance between two scanners */
int i;
GSList *row1, *row2;
float y = 0.0;
int line_ind = 0;
int *offsets = (int *)g_malloc0((lines_len / 2) * sizeof(int));
int *offsets = (int *)g_malloc0((num_lines / 2) * sizeof(int));
unsigned char *output = g_malloc0(ctx->line_width * ctx->max_height);
struct fp_img *img;
g_return_val_if_fail (lines != NULL, NULL);
g_return_val_if_fail (lines_len > 0, NULL);
g_return_val_if_fail (num_lines >= 2, NULL);
fp_dbg("%"G_GINT64_FORMAT, g_get_real_time());
row1 = lines;
for (i = 0; (i < lines_len - 1) && row1; i += 2) {
for (i = 0; (i < num_lines - 1) && row1; i += 2) {
int bestmatch = i;
int bestdiff = 0;
int j, firstrow, lastrow;
firstrow = i + 1;
lastrow = min(i + ctx->max_search_offset, lines_len - 1);
lastrow = MIN(i + ctx->max_search_offset, num_lines - 1);
row2 = g_slist_next(row1);
for (j = firstrow; j <= lastrow; j++) {
@@ -397,13 +450,13 @@ struct fp_img *fpi_assemble_lines(struct fpi_line_asmbl_ctx *ctx,
row1 = g_slist_next(row1);
}
median_filter(offsets, (lines_len / 2) - 1, ctx->median_filter_size);
median_filter(offsets, (num_lines / 2) - 1, ctx->median_filter_size);
fp_dbg("offsets_filtered: %"G_GINT64_FORMAT, g_get_real_time());
for (i = 0; i <= (lines_len / 2) - 1; i++)
for (i = 0; i <= (num_lines / 2) - 1; i++)
fp_dbg("%d", offsets[i]);
row1 = lines;
for (i = 0; i < lines_len - 1; i++, row1 = g_slist_next(row1)) {
for (i = 0; i < num_lines - 1; i++, row1 = g_slist_next(row1)) {
int offset = offsets[i/2];
if (offset > 0) {
float ynext = y + (float)ctx->resolution / offset;

115
libfprint/fpi-assembling.h Normal file
View File

@@ -0,0 +1,115 @@
/*
* Copyright (C) 2007 Daniel Drake <dsd@gentoo.org>
* Copyright (C) 2015 Vasily Khoruzhick <anarsoul@gmail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __FPI_ASSEMBLING_H__
#define __FPI_ASSEMBLING_H__
#include <fprint.h>
/**
* fpi_frame:
* @delta_x: X offset of the frame
* @delta_y: Y offset of the frame
* @data: bitmap
*
* #fpi_frame is used to store frames for swipe sensors. Drivers should
* populate delta_x and delta_y if the device supports hardware movement
* estimation.
*/
struct fpi_frame {
int delta_x;
int delta_y;
unsigned char data[0];
};
/**
* fpi_frame_asmbl_ctx:
* @frame_width: width of the frame
* @frame_height: height of the frame
* @image_width: resulting image width
* @get_pixel: pixel accessor, returns pixel brightness at x,y of frame
*
* #fpi_frame_asmbl_ctx is a structure holding the context for frame
* assembling routines.
*
* Drivers should define their own #fpi_frame_asmbl_ctx depending on
* hardware parameters of scanner. @image_width is usually 25% wider than
* @frame_width to take horizontal movement into account.
*/
struct fpi_frame_asmbl_ctx {
unsigned int frame_width;
unsigned int frame_height;
unsigned int image_width;
unsigned char (*get_pixel)(struct fpi_frame_asmbl_ctx *ctx,
struct fpi_frame *frame,
unsigned int x,
unsigned int y);
};
void fpi_do_movement_estimation(struct fpi_frame_asmbl_ctx *ctx,
GSList *stripes, size_t num_stripes);
struct fp_img *fpi_assemble_frames(struct fpi_frame_asmbl_ctx *ctx,
GSList *stripes, size_t num_stripes);
/**
* fpi_line_asmbl_ctx:
* @line_width: width of line
* @max_height: maximal height of assembled image
* @resolution: scale factor used for line assembling routines.
* @median_filter_size: size of median filter for movement estimation
* @max_search_offset: the number of lines to search for the next line
* @get_deviation: pointer to a function that returns the numerical difference
* between two lines
* @get_pixel: pixel accessor, returns pixel brightness at x of line
*
* #fpi_line_asmbl_ctx is a structure holding the context for line assembling
* routines.
*
* Drivers should define their own #fpi_line_asmbl_ctx depending on
* the hardware parameters of the scanner. Swipe scanners of this type usually
* return two lines, the second line is often narrower than first and is used
* for movement estimation.
*
* The @max_search_offset value indicates how many lines forward the assembling
* routines should look while searching for next line. This value depends on
* how fast the hardware sends frames.
*
* The function pointed to by @get_deviation should return the numerical difference
* between two lines. Higher values means lines are more different. If the reader
* returns two lines at a time, this function should be used to estimate the
* difference between pairs of lines.
*/
struct fpi_line_asmbl_ctx {
unsigned int line_width;
unsigned int max_height;
unsigned int resolution;
unsigned int median_filter_size;
unsigned int max_search_offset;
int (*get_deviation)(struct fpi_line_asmbl_ctx *ctx,
GSList *line1, GSList *line2);
unsigned char (*get_pixel)(struct fpi_line_asmbl_ctx *ctx,
GSList *line,
unsigned int x);
};
struct fp_img *fpi_assemble_lines(struct fpi_line_asmbl_ctx *ctx,
GSList *lines, size_t num_lines);
#endif

View File

@@ -20,11 +20,21 @@
#define FP_COMPONENT "async"
#include "fp_internal.h"
#include "fpi-async.h"
#include <config.h>
#include <errno.h>
#include <glib.h>
/*
* SECTION:fpi-async
* @title: Asynchronous operations reporting
* @short_description: Asynchronous operations reporting functions
*
* Those functions are used by primitive drivers to report back their
* current status. Most drivers, imaging ones, do not need to use them.
*/
/* Drivers call this when device initialisation has completed */
void fpi_drvcb_open_complete(struct fp_dev *dev, int status)
{
@@ -38,11 +48,18 @@ void fpi_drvcb_open_complete(struct fp_dev *dev, int status)
/**
* fp_async_dev_open:
* @ddev:
* @callback:
* @user_data
* @ddev: the struct #fp_dscv_dev discovered device to open
* @callback: the callback to call when the device has been opened
* @user_data: user data to pass to the callback
*
* Returns:
* Opens and initialises a device. This is the function you call in order
* to convert a #fp_dscv_dev discovered device into an actual device handle
* that you can perform operations with.
*
* The error status of the opening will be provided as an argument to the
* #fp_dev_open_cb callback.
*
* Returns: 0 on success, non-zero on error
*/
API_EXPORTED int fp_async_dev_open(struct fp_dscv_dev *ddev, fp_dev_open_cb callback,
void *user_data)
@@ -53,6 +70,7 @@ API_EXPORTED int fp_async_dev_open(struct fp_dscv_dev *ddev, fp_dev_open_cb call
int r;
g_return_val_if_fail(ddev != NULL, -ENODEV);
g_return_val_if_fail (callback != NULL, -EINVAL);
drv = ddev->drv;
@@ -93,6 +111,7 @@ void fpi_drvcb_close_complete(struct fp_dev *dev)
G_DEBUG_HERE();
BUG_ON(dev->state != DEV_STATE_DEINITIALIZING);
dev->state = DEV_STATE_DEINITIALIZED;
fpi_timeout_cancel_all_for_dev(dev);
libusb_close(dev->udev);
if (dev->close_cb)
dev->close_cb(dev, dev->close_cb_data);
@@ -101,9 +120,12 @@ void fpi_drvcb_close_complete(struct fp_dev *dev)
/**
* fp_async_dev_close:
* @dev:
* @callback:
* @user_data
* @dev: the struct #fp_dev device
* @callback: the callback to call when the device has been closed
* @user_data: user data to pass to the callback
*
* Closes a device. You must call this function when you have finished using
* a fingerprint device.
*/
API_EXPORTED void fp_async_dev_close(struct fp_dev *dev,
fp_operation_stop_cb callback, void *user_data)
@@ -147,11 +169,15 @@ void fpi_drvcb_enroll_started(struct fp_dev *dev, int status)
/**
* fp_async_enroll_start:
* @dev:
* @callback:
* @user_data:
* @dev: the struct #fp_dev device
* @callback: the callback to call for each stage of the enrollment
* @user_data: user data to pass to the callback
*
* Returns:
* Starts an enrollment and calls @callback for each enrollment stage.
* See [Enrolling](libfprint-Devices-operations.html#enrolling)
* for an explanation of enroll stages.
*
* Returns: 0 on success, non-zero on error
*/
API_EXPORTED int fp_async_enroll_start(struct fp_dev *dev,
fp_enroll_stage_cb callback, void *user_data)
@@ -160,6 +186,7 @@ API_EXPORTED int fp_async_enroll_start(struct fp_dev *dev,
int r;
g_return_val_if_fail(dev != NULL, -ENODEV);
g_return_val_if_fail (callback != NULL, -EINVAL);
drv = dev->drv;
@@ -213,11 +240,13 @@ void fpi_drvcb_enroll_stopped(struct fp_dev *dev)
/**
* fp_async_enroll_stop:
* @dev:
* @callback:
* @user_data:
* @dev: the struct #fp_dev device
* @callback: the callback to call when the enrollment has been cancelled
* @user_data: user data to pass to the callback
*
* Returns:
* Stops an ongoing enrollment started with fp_async_enroll_start().
*
* Returns: 0 on success, non-zero on error
*/
API_EXPORTED int fp_async_enroll_stop(struct fp_dev *dev,
fp_operation_stop_cb callback, void *user_data)
@@ -254,12 +283,17 @@ API_EXPORTED int fp_async_enroll_stop(struct fp_dev *dev,
/**
* fp_async_verify_start:
* @dev:
* @data:
* @callback:
* @user_data:
* @dev: the struct #fp_dev device
* @data: the print to verify against. Must have been previously
* enrolled with a device compatible to the device selected to perform the scan
* @callback: the callback to call when the verification has finished
* @user_data: user data to pass to the callback
*
* Returns:
* Starts a verification and calls @callback when the verification has
* finished. See fp_verify_finger_img() for the synchronous API. When the
* @callback has been called, you must call fp_async_verify_stop().
*
* Returns: 0 on success, non-zero on error
*/
API_EXPORTED int fp_async_verify_start(struct fp_dev *dev,
struct fp_print_data *data, fp_img_operation_cb callback, void *user_data)
@@ -268,6 +302,7 @@ API_EXPORTED int fp_async_verify_start(struct fp_dev *dev,
int r;
g_return_val_if_fail(dev != NULL, -ENODEV);
g_return_val_if_fail (callback != NULL, -EINVAL);
drv = dev->drv;
@@ -335,11 +370,13 @@ void fpi_drvcb_verify_stopped(struct fp_dev *dev)
/**
* fp_async_verify_stop:
* @dev:
* @callback:
* @user_data:
* @dev: the struct #fp_dev device
* @callback: the callback to call to finish a verification
* @user_data: user data to pass to the callback
*
* Returns:
* Finishes an ongoing verification started with fp_async_verify_start().
*
* Returns: 0 on success, non-zero on error
*/
API_EXPORTED int fp_async_verify_stop(struct fp_dev *dev,
fp_operation_stop_cb callback, void *user_data)
@@ -380,12 +417,17 @@ API_EXPORTED int fp_async_verify_stop(struct fp_dev *dev,
/**
* fp_async_identify_start:
* @dev:
* @gallery:
* @callback:
* @user_data:
* @dev: the struct #fp_dev device
* @gallery: NULL-terminated array of pointers to the prints to
* identify against. Each one must have been previously enrolled with a device
* compatible to the device selected to perform the scan
* @callback: the callback to call when the identification has finished
* @user_data: user data to pass to the callback
*
* Returns:
* Performs a new scan and verifies it against a previously enrolled print.
* See also: fp_verify_finger_img()
*
* Returns: 0 on success, non-zero on error
*/
API_EXPORTED int fp_async_identify_start(struct fp_dev *dev,
struct fp_print_data **gallery, fp_identify_cb callback, void *user_data)
@@ -394,6 +436,7 @@ API_EXPORTED int fp_async_identify_start(struct fp_dev *dev,
int r;
g_return_val_if_fail(dev != NULL, -ENODEV);
g_return_val_if_fail (callback != NULL, -EINVAL);
drv = dev->drv;
@@ -451,11 +494,13 @@ void fpi_drvcb_report_identify_result(struct fp_dev *dev, int result,
/**
* fp_async_identify_stop:
* @dev:
* @callback:
* @user_data:
* @dev: the struct #fp_dev device
* @callback: the callback to call when the identification has stopped
* @user_data: user data to pass to the callback
*
* Returns:
* Stops an ongoing identification started with fp_async_identify_start().
*
* Returns: 0 on success, non-zero on error
*/
API_EXPORTED int fp_async_identify_stop(struct fp_dev *dev,
fp_operation_stop_cb callback, void *user_data)
@@ -506,12 +551,17 @@ void fpi_drvcb_identify_stopped(struct fp_dev *dev)
/**
* fp_async_capture_start:
* @dev:
* @unconditional:
* @callback:
* @user_data:
* @dev: the struct #fp_dev device
* @unconditional: whether to unconditionally capture an image, or to only capture when a finger is detected
* @callback: the callback to call when the capture has finished
* @user_data: user data to pass to the callback
*
* Returns:
* Start the capture of an #fp_img from a device. When the @callback has been called,
* you must call fp_async_capture_stop().
*
* Returns: 0 on success, non-zero on error. -ENOTSUP indicates that either the
* @unconditional flag was set but the device does not support this, or that the
* device does not support imaging
*/
API_EXPORTED int fp_async_capture_start(struct fp_dev *dev, int unconditional,
fp_img_operation_cb callback, void *user_data)
@@ -520,6 +570,7 @@ API_EXPORTED int fp_async_capture_start(struct fp_dev *dev, int unconditional,
int r;
g_return_val_if_fail(dev != NULL, -ENODEV);
g_return_val_if_fail (callback != NULL, -EINVAL);
drv = dev->drv;
@@ -536,7 +587,7 @@ API_EXPORTED int fp_async_capture_start(struct fp_dev *dev, int unconditional,
if (r < 0) {
dev->capture_cb = NULL;
dev->state = DEV_STATE_ERROR;
fp_err("failed to start verification, error %d", r);
fp_err("failed to start capture, error %d", r);
}
return r;
}
@@ -586,11 +637,13 @@ void fpi_drvcb_capture_stopped(struct fp_dev *dev)
/**
* fp_async_capture_stop:
* @dev:
* @callback:
* @user_data:
* @dev: the struct #fp_dev device
* @callback: the callback to call when the capture has been stopped
* @user_data: user data to pass to the callback
*
* Returns:
* Stops an ongoing verification started with fp_async_capture_start().
*
* Returns: 0 on success, non-zero on error
*/
API_EXPORTED int fp_async_capture_stop(struct fp_dev *dev,
fp_operation_stop_cb callback, void *user_data)
@@ -622,7 +675,7 @@ API_EXPORTED int fp_async_capture_stop(struct fp_dev *dev,
r = drv->capture_stop(dev);
if (r < 0) {
fp_err("failed to stop verification");
fp_err("failed to stop capture");
dev->capture_stop_cb = NULL;
}
return r;

39
libfprint/fpi-async.h Normal file
View File

@@ -0,0 +1,39 @@
/*
* Copyright (C) 2007-2008 Daniel Drake <dsd@gentoo.org>
* Copyright (C) 2018 Bastien Nocera <hadess@hadess.net>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __FPI_ASYNC_H__
#define __FPI_ASYNC_H__
#include "fpi-dev.h"
#include "fpi-data.h"
void fpi_drvcb_open_complete(struct fp_dev *dev, int status);
void fpi_drvcb_close_complete(struct fp_dev *dev);
void fpi_drvcb_enroll_started(struct fp_dev *dev, int status);
void fpi_drvcb_enroll_stage_completed(struct fp_dev *dev, int result,
struct fp_print_data *data, struct fp_img *img);
void fpi_drvcb_enroll_stopped(struct fp_dev *dev);
void fpi_drvcb_verify_started(struct fp_dev *dev, int status);
void fpi_drvcb_report_verify_result(struct fp_dev *dev, int result,
struct fp_img *img);
void fpi_drvcb_verify_stopped(struct fp_dev *dev);
#endif

View File

@@ -33,6 +33,7 @@ GSList *opened_devices = NULL;
/**
* SECTION:discovery
* @title: Device discovery
* @short_description: Device discovery functions
*
* These functions allow you to scan the system for supported fingerprint
* scanning hardware. This is your starting point when integrating libfprint
@@ -47,6 +48,7 @@ GSList *opened_devices = NULL;
/**
* SECTION:drv
* @title: Driver operations
* @short_description: Driver operation functions
*
* Internally, libfprint is abstracted into various drivers to communicate
* with the different types of supported fingerprint readers. libfprint works
@@ -61,6 +63,7 @@ GSList *opened_devices = NULL;
/**
* SECTION:dev
* @title: Devices operations
* @short_description: Device operation functions
*
* In order to interact with fingerprint scanners, your software will
* interface primarily with libfprint's representation of devices, detailed
@@ -111,6 +114,27 @@ GSList *opened_devices = NULL;
* verification) on some devices which do not provide images.
*/
/**
* SECTION:fpi-core
* @title: Driver structures
* @short_description: Driver structures
*
* Driver structures need to be defined inside each driver in
* order for the core library to know what function to call, and the capabilities
* of the driver and the devices it supports.
*/
/**
* SECTION:fpi-core-img
* @title: Image driver structures
* @short_description: Image driver structures
*
* Image driver structures need to be defined inside each image driver in
* order for the core library to know what function to call, and the capabilities
* of the driver and the devices it supports. Its structure is based off the
* #fp_driver struct.
*/
static GSList *registered_drivers = NULL;
static void register_driver(struct fp_driver *drv)
@@ -246,10 +270,12 @@ static struct fp_dscv_dev *discover_dev(libusb_device *udev)
* fp_discover_devs:
*
* Scans the system and returns a list of discovered devices. This is your
* entry point into finding a fingerprint reader to operate.
* entry point into finding a fingerprint reader to operate. Note that %NULL
* is only returned on error. When there are no supported readers available,
* an empty list is returned instead.
*
* Returns: a %NULL-terminated list of discovered devices. Must be freed with
* fp_dscv_devs_free() after use.
* Returns: a nul-terminated list of discovered devices or %NULL on error.
* Must be freed with fp_dscv_devs_free() after use.
*/
API_EXPORTED struct fp_dscv_dev **fp_discover_devs(void)
{
@@ -259,8 +285,7 @@ API_EXPORTED struct fp_dscv_dev **fp_discover_devs(void)
int r;
int i = 0;
if (registered_drivers == NULL)
return NULL;
g_return_val_if_fail (registered_drivers != NULL, NULL);
r = libusb_get_device_list(fpi_usb_ctx, &devs);
if (r < 0) {
@@ -321,6 +346,8 @@ API_EXPORTED void fp_dscv_devs_free(struct fp_dscv_dev **devs)
*/
API_EXPORTED struct fp_driver *fp_dscv_dev_get_driver(struct fp_dscv_dev *dev)
{
g_return_val_if_fail(dev, NULL);
return dev->drv;
}
@@ -328,10 +355,15 @@ API_EXPORTED struct fp_driver *fp_dscv_dev_get_driver(struct fp_dscv_dev *dev)
* fp_dscv_dev_get_driver_id:
* @dev: a discovered fingerprint device
*
* Returns: the ID for the underlying driver for that device
* Returns a unique driver identifier for the underlying driver
* for that device.
*
* Returns: the ID for #dev
*/
API_EXPORTED uint16_t fp_dscv_dev_get_driver_id(struct fp_dscv_dev *dev)
{
g_return_val_if_fail(dev, 0);
return fp_driver_get_driver_id(fp_dscv_dev_get_driver(dev));
}
@@ -345,6 +377,8 @@ API_EXPORTED uint16_t fp_dscv_dev_get_driver_id(struct fp_dscv_dev *dev)
*/
API_EXPORTED uint32_t fp_dscv_dev_get_devtype(struct fp_dscv_dev *dev)
{
g_return_val_if_fail(dev, 0);
return dev->devtype;
}
@@ -374,6 +408,9 @@ enum fp_print_data_type fpi_driver_get_data_type(struct fp_driver *drv)
API_EXPORTED int fp_dscv_dev_supports_print_data(struct fp_dscv_dev *dev,
struct fp_print_data *print)
{
g_return_val_if_fail(dev, 0);
g_return_val_if_fail(print, 0);
return fpi_print_data_compatible(dev->drv->id, dev->devtype,
fpi_driver_get_data_type(dev->drv), print->driver_id, print->devtype,
print->type);
@@ -394,6 +431,9 @@ API_EXPORTED int fp_dscv_dev_supports_print_data(struct fp_dscv_dev *dev,
API_EXPORTED int fp_dscv_dev_supports_dscv_print(struct fp_dscv_dev *dev,
struct fp_dscv_print *print)
{
g_return_val_if_fail(dev, 0);
g_return_val_if_fail(print, 0);
return fpi_print_data_compatible(dev->drv->id, dev->devtype, 0,
print->driver_id, print->devtype, 0);
}
@@ -417,6 +457,9 @@ API_EXPORTED struct fp_dscv_dev *fp_dscv_dev_for_print_data(struct fp_dscv_dev *
struct fp_dscv_dev *ddev;
int i;
g_return_val_if_fail(devs, NULL);
g_return_val_if_fail(print, NULL);
for (i = 0; (ddev = devs[i]); i++)
if (fp_dscv_dev_supports_print_data(ddev, print))
return ddev;
@@ -442,6 +485,9 @@ API_EXPORTED struct fp_dscv_dev *fp_dscv_dev_for_dscv_print(struct fp_dscv_dev *
struct fp_dscv_dev *ddev;
int i;
g_return_val_if_fail(devs, NULL);
g_return_val_if_fail(print, NULL);
for (i = 0; (ddev = devs[i]); i++) {
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
@@ -454,7 +500,7 @@ API_EXPORTED struct fp_dscv_dev *fp_dscv_dev_for_dscv_print(struct fp_dscv_dev *
/**
* fp_dev_get_driver:
* @dev: the device
* @dev: the struct #fp_dev device
*
* Get the #fp_driver for a fingerprint device.
*
@@ -462,12 +508,14 @@ API_EXPORTED struct fp_dscv_dev *fp_dscv_dev_for_dscv_print(struct fp_dscv_dev *
*/
API_EXPORTED struct fp_driver *fp_dev_get_driver(struct fp_dev *dev)
{
g_return_val_if_fail(dev, NULL);
return dev->drv;
}
/**
* fp_dev_get_nr_enroll_stages:
* @dev: the device
* @dev: the struct #fp_dev device
*
* Gets the number of [enroll stages](intro.html#enrollment) required to enroll a
* fingerprint with the device.
@@ -476,12 +524,14 @@ API_EXPORTED struct fp_driver *fp_dev_get_driver(struct fp_dev *dev)
*/
API_EXPORTED int fp_dev_get_nr_enroll_stages(struct fp_dev *dev)
{
g_return_val_if_fail(dev, 0);
return dev->nr_enroll_stages;
}
/**
* fp_dev_get_devtype:
* @dev: the device
* @dev: the struct #fp_dev device
*
* Gets the [devtype](advanced-topics.html#device-types) for a device.
*
@@ -489,12 +539,14 @@ API_EXPORTED int fp_dev_get_nr_enroll_stages(struct fp_dev *dev)
*/
API_EXPORTED uint32_t fp_dev_get_devtype(struct fp_dev *dev)
{
g_return_val_if_fail(dev, 0);
return dev->devtype;
}
/**
* fp_dev_supports_print_data:
* @dev: the device
* @dev: the struct #fp_dev device
* @data: the stored print
*
* Determines if a stored print is compatible with a certain device.
@@ -504,6 +556,9 @@ API_EXPORTED uint32_t fp_dev_get_devtype(struct fp_dev *dev)
API_EXPORTED int fp_dev_supports_print_data(struct fp_dev *dev,
struct fp_print_data *data)
{
g_return_val_if_fail(dev, 0);
g_return_val_if_fail(data, 0);
return fpi_print_data_compatible(dev->drv->id, dev->devtype,
fpi_driver_get_data_type(dev->drv), data->driver_id, data->devtype,
data->type);
@@ -511,7 +566,7 @@ API_EXPORTED int fp_dev_supports_print_data(struct fp_dev *dev,
/**
* fp_dev_supports_dscv_print:
* @dev: the device
* @dev: the struct #fp_dev device
* @print: the discovered print
*
* Determines if a #fp_dscv_print discovered print appears to be compatible
@@ -524,54 +579,13 @@ API_EXPORTED int fp_dev_supports_print_data(struct fp_dev *dev,
API_EXPORTED int fp_dev_supports_dscv_print(struct fp_dev *dev,
struct fp_dscv_print *print)
{
g_return_val_if_fail(dev, 0);
g_return_val_if_fail(print, 0);
return fpi_print_data_compatible(dev->drv->id, dev->devtype,
0, print->driver_id, print->devtype, 0);
}
libusb_device_handle *
fpi_dev_get_usb_dev(struct fp_dev *dev)
{
return dev->udev;
}
void *
fpi_dev_get_user_data (struct fp_dev *dev)
{
return dev->priv;
}
void
fpi_dev_set_user_data (struct fp_dev *dev,
void *user_data)
{
dev->priv = user_data;
}
int
fpi_dev_get_nr_enroll_stages(struct fp_dev *dev)
{
return dev->nr_enroll_stages;
}
void
fpi_dev_set_nr_enroll_stages(struct fp_dev *dev,
int nr_enroll_stages)
{
dev->nr_enroll_stages = nr_enroll_stages;
}
struct fp_print_data *
fpi_dev_get_verify_data(struct fp_dev *dev)
{
return dev->verify_data;
}
enum fp_dev_state
fpi_dev_get_dev_state(struct fp_dev *dev)
{
return dev->state;
}
/**
* fp_driver_get_name:
* @drv: the driver
@@ -582,6 +596,8 @@ fpi_dev_get_dev_state(struct fp_dev *dev)
*/
API_EXPORTED const char *fp_driver_get_name(struct fp_driver *drv)
{
g_return_val_if_fail(drv, NULL);
return drv->name;
}
@@ -595,6 +611,8 @@ API_EXPORTED const char *fp_driver_get_name(struct fp_driver *drv)
*/
API_EXPORTED const char *fp_driver_get_full_name(struct fp_driver *drv)
{
g_return_val_if_fail(drv, NULL);
return drv->full_name;
}
@@ -608,6 +626,8 @@ API_EXPORTED const char *fp_driver_get_full_name(struct fp_driver *drv)
*/
API_EXPORTED uint16_t fp_driver_get_driver_id(struct fp_driver *drv)
{
g_return_val_if_fail(drv, 0);
return drv->id;
}
@@ -621,19 +641,34 @@ API_EXPORTED uint16_t fp_driver_get_driver_id(struct fp_driver *drv)
*/
API_EXPORTED enum fp_scan_type fp_driver_get_scan_type(struct fp_driver *drv)
{
g_return_val_if_fail(drv, FP_SCAN_TYPE_PRESS);
return drv->scan_type;
}
static struct fp_img_dev *dev_to_img_dev(struct fp_dev *dev)
/**
* fp_driver_supports_imaging:
* @drv: the driver
*
* Determines if a driver has imaging capabilities. If a driver has imaging
* capabilities you are able to perform imaging operations such as retrieving
* scan images using fp_dev_img_capture(). However, not all drivers support
* imaging devices some do all processing in hardware. This function will
* indicate which class a device in question falls into.
*
* Returns: 1 if the device is an imaging device, 0 if the device does not
* provide images to the host computer
*/
API_EXPORTED int fp_driver_supports_imaging(struct fp_driver *drv)
{
if (dev->drv->type != DRIVER_IMAGING)
return NULL;
return dev->priv;
g_return_val_if_fail(drv, 0);
return drv->capture_start != NULL;
}
/**
* fp_dev_supports_imaging:
* @dev: the fingerprint device
* @dev: the struct #fp_dev device
*
* Determines if a device has imaging capabilities. If a device has imaging
* capabilities you are able to perform imaging operations such as retrieving
@@ -646,12 +681,14 @@ static struct fp_img_dev *dev_to_img_dev(struct fp_dev *dev)
*/
API_EXPORTED int fp_dev_supports_imaging(struct fp_dev *dev)
{
g_return_val_if_fail(dev, 0);
return dev->drv->capture_start != NULL;
}
/**
* fp_dev_supports_identification:
* @dev: the fingerprint device
* @dev: the struct #fp_dev device
*
* Determines if a device is capable of [identification](intro.html#identification)
* through fp_identify_finger() and similar. Not all devices support this
@@ -661,12 +698,14 @@ API_EXPORTED int fp_dev_supports_imaging(struct fp_dev *dev)
*/
API_EXPORTED int fp_dev_supports_identification(struct fp_dev *dev)
{
g_return_val_if_fail(dev, 0);
return dev->drv->identify_start != NULL;
}
/**
* fp_dev_get_img_width:
* @dev: the fingerprint device
* @dev: the struct #fp_dev device
*
* Gets the expected width of images that will be captured from the device.
* This function will return -1 for devices that are not
@@ -678,18 +717,19 @@ API_EXPORTED int fp_dev_supports_identification(struct fp_dev *dev)
*/
API_EXPORTED int fp_dev_get_img_width(struct fp_dev *dev)
{
struct fp_img_dev *imgdev = dev_to_img_dev(dev);
if (!imgdev) {
g_return_val_if_fail(dev, -1);
if (!dev->img_dev) {
fp_dbg("get image width for non-imaging device");
return -1;
}
return fpi_imgdev_get_img_width(imgdev);
return fpi_imgdev_get_img_width(dev->img_dev);
}
/**
* fp_dev_get_img_height:
* @dev: the fingerprint device
* @dev: the struct #fp_dev device
*
* Gets the expected height of images that will be captured from the device.
* This function will return -1 for devices that are not
@@ -701,13 +741,14 @@ API_EXPORTED int fp_dev_get_img_width(struct fp_dev *dev)
*/
API_EXPORTED int fp_dev_get_img_height(struct fp_dev *dev)
{
struct fp_img_dev *imgdev = dev_to_img_dev(dev);
if (!imgdev) {
g_return_val_if_fail(dev, -1);
if (!dev->img_dev) {
fp_dbg("get image height for non-imaging device");
return -1;
}
return fpi_imgdev_get_img_height(imgdev);
return fpi_imgdev_get_img_height(dev->img_dev);
}
/**

118
libfprint/fpi-core.h Normal file
View File

@@ -0,0 +1,118 @@
/*
* Copyright (C) 2007-2008 Daniel Drake <dsd@gentoo.org>
* Copyright (C) 2018 Bastien Nocera <hadess@hadess.net>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __FPI_CORE_H__
#define __FPI_CORE_H__
#include <fprint.h>
#include "fpi-dev-img.h"
/**
* usb_id:
* @vendor: the USB vendor ID
* @product: the USB product ID
* @driver_data: data to differentiate devices of different
* vendor and product IDs.
*
* The struct #usb_id is used to declare devices supported by a
* particular driver. The @driver_data information is used to
* differentiate different models of devices which only need
* small changes compared to the default driver behaviour to function.
*
* For example, a device might have a different initialisation from
* the stock device, so the driver could do:
*
* |[<!-- language="C" -->
* if (driver_data == MY_DIFFERENT_DEVICE_QUIRK) {
* ...
* } else {
* ...
* }
* ]|
*
* The default value is zero, so the @driver_data needs to be a
* non-zero to be useful.
*/
struct usb_id {
uint16_t vendor;
uint16_t product;
unsigned long driver_data;
};
/**
* fp_driver_type:
* @DRIVER_PRIMITIVE: primitive, non-imaging, driver
* @DRIVER_IMAGING: imaging driver
*
* The type of device the driver supports.
*/
enum fp_driver_type {
DRIVER_PRIMITIVE = 0,
DRIVER_IMAGING = 1,
};
struct fp_driver {
const uint16_t id;
const char *name;
const char *full_name;
const struct usb_id * const id_table;
enum fp_driver_type type;
enum fp_scan_type scan_type;
/* Device operations */
int (*discover)(struct libusb_device_descriptor *dsc, uint32_t *devtype);
int (*open)(struct fp_dev *dev, unsigned long driver_data);
void (*close)(struct fp_dev *dev);
int (*enroll_start)(struct fp_dev *dev);
int (*enroll_stop)(struct fp_dev *dev);
int (*verify_start)(struct fp_dev *dev);
int (*verify_stop)(struct fp_dev *dev, gboolean iterating);
int (*identify_start)(struct fp_dev *dev);
int (*identify_stop)(struct fp_dev *dev, gboolean iterating);
int (*capture_start)(struct fp_dev *dev);
int (*capture_stop)(struct fp_dev *dev);
};
/**
* FpiImgDriverFlags:
* @FP_IMGDRV_SUPPORTS_UNCONDITIONAL_CAPTURE: Whether the driver supports
* unconditional image capture. No driver currently does.
*
* Flags used in the #fp_img_driver to advertise the capabilities of drivers.
*/
typedef enum {
FP_IMGDRV_SUPPORTS_UNCONDITIONAL_CAPTURE = 1 << 0
} FpiImgDriverFlags;
struct fp_img_driver {
struct fp_driver driver;
FpiImgDriverFlags flags;
int img_width;
int img_height;
int bz3_threshold;
/* Device operations */
int (*open)(struct fp_img_dev *dev, unsigned long driver_data);
void (*close)(struct fp_img_dev *dev);
int (*activate)(struct fp_img_dev *dev);
int (*change_state)(struct fp_img_dev *dev, enum fp_imgdev_state state);
void (*deactivate)(struct fp_img_dev *dev);
};
#endif

View File

@@ -32,9 +32,23 @@
#define DIR_PERMS 0700
struct fpi_print_data_fp2 {
char prefix[3];
uint16_t driver_id;
uint32_t devtype;
unsigned char data_type;
unsigned char data[0];
} __attribute__((__packed__));
struct fpi_print_data_item_fp2 {
uint32_t length;
unsigned char data[0];
} __attribute__((__packed__));
/**
* SECTION: print_data
* @title: Stored prints
* @short_description: Stored prints functions
*
* Stored prints are represented by a structure named #fp_print_data.
* Stored prints are originally obtained from an enrollment function such as
@@ -42,12 +56,25 @@
*
* This page documents the various operations you can do with a stored print.
* Note that by default, "stored prints" are not actually stored anywhere
* except in RAM. For the simple scenarios, libfprint provides a simple API
* for you to save and load the stored prints referring to a single user in
* their home directory. For more advanced users, libfprint provides APIs for
* you to convert print data to a byte string, and to reconstruct stored prints
* except in RAM. Storage needs to be handled by the API user by using the
* fp_print_data_get_data() and fp_print_data_from_data(). This API allows
* to convert print data into byte strings, and to reconstruct stored prints
* from such data at a later point. You are welcome to store these byte strings
* in any fashion that suits you.
*
* The provided API to store data on disk is deprecated and should not be
* used anymore. This API stored the prints in the current user's home
* directory.
*/
/*
* SECTION: fpi-data
* @title: Stored prints creation
* @short_description: Stored prints creation functions
*
* Stored print can be loaded and created by certain drivers which do their own
* print matching in hardware. Most drivers will not be using those functions.
* See #fp_print_data for the public API counterpart.
*/
static char *base_store = NULL;
@@ -106,7 +133,7 @@ static struct fp_print_data *print_data_new(uint16_t driver_id,
return data;
}
void fpi_print_data_item_free(struct fp_print_data_item *item)
static void fpi_print_data_item_free(struct fp_print_data_item *item)
{
g_free(item);
}
@@ -125,6 +152,19 @@ struct fp_print_data *fpi_print_data_new(struct fp_dev *dev)
fpi_driver_get_data_type(dev->drv));
}
struct fp_print_data_item *
fpi_print_data_get_item(struct fp_print_data *data)
{
return data->prints->data;
}
void
fpi_print_data_add_item(struct fp_print_data *data,
struct fp_print_data_item *item)
{
data->prints = g_slist_prepend(data->prints, item);
}
/**
* fp_print_data_get_data:
* @data: the stored print
@@ -329,6 +369,10 @@ static char *get_path_to_print(struct fp_dev *dev, enum fp_finger finger)
* directory beneath the current user's home directory.
*
* Returns: 0 on success, non-zero on error.
*
* Deprecated: Data storage should be handled outside of libfprint.
* See <link linkend="libfprint-Stored-prints.description">stored prints description</link>
* for more information.
*/
API_EXPORTED int fp_print_data_save(struct fp_print_data *data,
enum fp_finger finger)
@@ -354,6 +398,7 @@ API_EXPORTED int fp_print_data_save(struct fp_print_data *data,
r = g_mkdir_with_parents(dirpath, DIR_PERMS);
if (r < 0) {
fp_err("couldn't create storage directory");
free(buf);
g_free(path);
g_free(dirpath);
return r;
@@ -440,12 +485,16 @@ static int load_from_file(char *path, struct fp_print_data **data)
* obscure error conditions (e.g. corruption).
*
* Returns: 0 on success, non-zero on error
*
* Deprecated: Data storage should be handled outside of libfprint.
* See <link linkend="libfprint-Stored-prints.description">stored prints description</link>
* for more information.
*/
API_EXPORTED int fp_print_data_load(struct fp_dev *dev,
enum fp_finger finger, struct fp_print_data **data)
{
gchar *path;
struct fp_print_data *fdata;
struct fp_print_data *fdata = NULL;
int r;
if (!base_store)
@@ -475,6 +524,10 @@ API_EXPORTED int fp_print_data_load(struct fp_dev *dev,
* Removes a stored print from disk previously saved with fp_print_data_save().
*
* Returns: 0 on success, negative on error
*
* Deprecated: Data storage should be handled outside of libfprint.
* See <link linkend="libfprint-Stored-prints.description">stored prints description</link>
* for more information.
*/
API_EXPORTED int fp_print_data_delete(struct fp_dev *dev,
enum fp_finger finger)
@@ -560,6 +613,7 @@ API_EXPORTED uint32_t fp_print_data_get_devtype(struct fp_print_data *data)
/**
* SECTION:dscv_print
* @title: Print discovery (deprecated)
* @short_description: Print discovery functions
*
* The [stored print](libfprint-Stored-prints.html) documentation detailed a simple API
* for storing per-device prints for a single user, namely
@@ -695,9 +749,7 @@ API_EXPORTED struct fp_dscv_print **fp_discover_prints(void)
GError *err = NULL;
GSList *tmplist = NULL;
GSList *elem;
unsigned int tmplist_len;
struct fp_dscv_print **list;
unsigned int i;
GPtrArray *array;
if (!base_store)
storage_setup();
@@ -732,15 +784,17 @@ API_EXPORTED struct fp_dscv_print **fp_discover_prints(void)
}
g_dir_close(dir);
tmplist_len = g_slist_length(tmplist);
list = g_malloc(sizeof(*list) * (tmplist_len + 1));
elem = tmplist;
for (i = 0; i < tmplist_len; i++, elem = g_slist_next(elem))
list[i] = elem->data;
list[tmplist_len] = NULL; /* NULL-terminate */
if (tmplist == NULL)
return NULL;
array = g_ptr_array_new();
for (elem = tmplist; elem != NULL; elem = elem->next)
g_ptr_array_add(array, elem->data);
g_ptr_array_add(array, NULL);
g_slist_free(tmplist);
return list;
return (struct fp_dscv_print **) g_ptr_array_free(array, FALSE);
}
/**

34
libfprint/fpi-data.h Normal file
View File

@@ -0,0 +1,34 @@
/*
* Copyright (C) 2007-2008 Daniel Drake <dsd@gentoo.org>
* Copyright (C) 2018 Bastien Nocera <hadess@hadess.net>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __FPI_DATA_H__
#define __FPI_DATA_H__
struct fp_print_data;
struct fp_print_data_item {
size_t length;
unsigned char data[0];
};
struct fp_print_data *fpi_print_data_new(struct fp_dev *dev);
struct fp_print_data_item *fpi_print_data_item_new(size_t length);
struct fp_print_data_item *fpi_print_data_get_item(struct fp_print_data *data);
void fpi_print_data_add_item(struct fp_print_data *data, struct fp_print_data_item *item);
#endif

View File

@@ -21,25 +21,93 @@
#include <glib.h>
#include "fpi-dev-img.h"
#include "fpi-async.h"
#include "fp_internal.h"
/**
* SECTION:fpi-dev-img
* @title: Image device operations
* @short_description: Image device operation functions
*
* As drivers work through different operations, they need to report back
* to the core as to their internal state, so errors and successes can be
* reported back to front-ends.
*/
#define MIN_ACCEPTABLE_MINUTIAE 10
#define BOZORTH3_DEFAULT_THRESHOLD 40
#define IMG_ENROLL_STAGES 5
/**
* fpi_imgdev_get_action_state:
* @imgdev: a #fp_img_dev imaging fingerprint device
*
* Returns the state of an imaging device while enrolling a fingerprint.
*
* Returns: a enum #fp_imgdev_enroll_state
*/
enum fp_imgdev_enroll_state
fpi_imgdev_get_action_state(struct fp_img_dev *imgdev)
{
return imgdev->action_state;
}
/**
* fpi_imgdev_get_action:
* @imgdev: a #fp_img_dev imaging fingerprint device
*
* Returns the current action being performed by an imaging device.
*
* Returns: a enum #fp_imgdev_action
*/
enum fp_imgdev_action
fpi_imgdev_get_action(struct fp_img_dev *imgdev)
{
return imgdev->action;
}
/**
* fpi_imgdev_get_action_result:
* @imgdev: a #fp_img_dev imaging fingerprint device
*
* Returns an integer representing the result of an action. Which enum
* the result code is taken from depends on the current action being performed.
* See #fp_capture_result, #fp_enroll_result and #fp_verify_result.
*/
int
fpi_imgdev_get_action_result(struct fp_img_dev *imgdev)
{
return imgdev->action_result;
}
/**
* fpi_imgdev_set_action_result:
* @imgdev: a #fp_img_dev imaging fingerprint device
* @action_result: an action result
*
* Drivers should use fpi_imgdev_image_captured() instead. This function
* should not be used, and will be removed soon.
*/
void
fpi_imgdev_set_action_result(struct fp_img_dev *imgdev,
int action_result)
{
imgdev->action_result = action_result;
}
static int img_dev_open(struct fp_dev *dev, unsigned long driver_data)
{
struct fp_img_dev *imgdev = g_malloc0(sizeof(*imgdev));
struct fp_img_driver *imgdrv = fpi_driver_to_img_driver(dev->drv);
int r = 0;
imgdev->dev = dev;
imgdev->enroll_stage = 0;
dev->priv = imgdev;
dev->nr_enroll_stages = IMG_ENROLL_STAGES;
/* Set up back pointers */
dev->img_dev = imgdev;
imgdev->parent = dev;
/* for consistency in driver code, allow udev access through imgdev */
imgdev->udev = dev->udev;
imgdev->enroll_stage = 0;
dev->nr_enroll_stages = IMG_ENROLL_STAGES;
if (imgdrv->open) {
r = imgdrv->open(imgdev, driver_data);
@@ -55,32 +123,45 @@ err:
return r;
}
/**
* fpi_imgdev_open_complete:
* @imgdev: a #fp_img_dev imaging fingerprint device
* @status: an error code
*
* Function to call when the device has been opened, whether
* successfully of not.
*/
void fpi_imgdev_open_complete(struct fp_img_dev *imgdev, int status)
{
fpi_drvcb_open_complete(imgdev->dev, status);
fpi_drvcb_open_complete(FP_DEV(imgdev), status);
}
static void img_dev_close(struct fp_dev *dev)
{
struct fp_img_dev *imgdev = dev->priv;
struct fp_img_driver *imgdrv = fpi_driver_to_img_driver(dev->drv);
if (imgdrv->close)
imgdrv->close(imgdev);
imgdrv->close(dev->img_dev);
else
fpi_drvcb_close_complete(dev);
}
/**
* fpi_imgdev_close_complete:
* @imgdev: a #fp_img_dev imaging fingerprint device
*
* Function to call when the device has been closed.
*/
void fpi_imgdev_close_complete(struct fp_img_dev *imgdev)
{
fpi_drvcb_close_complete(imgdev->dev);
fpi_drvcb_close_complete(FP_DEV(imgdev));
g_free(imgdev);
}
static int dev_change_state(struct fp_img_dev *imgdev,
enum fp_imgdev_state state)
{
struct fp_driver *drv = imgdev->dev->drv;
struct fp_driver *drv = FP_DEV(imgdev)->drv;
struct fp_img_driver *imgdrv = fpi_driver_to_img_driver(drv);
if (!imgdrv->change_state)
@@ -92,7 +173,7 @@ static int dev_change_state(struct fp_img_dev *imgdev,
* image after freeing the old one. */
static int sanitize_image(struct fp_img_dev *imgdev, struct fp_img **_img)
{
struct fp_driver *drv = imgdev->dev->drv;
struct fp_driver *drv = FP_DEV(imgdev)->drv;
struct fp_img_driver *imgdrv = fpi_driver_to_img_driver(drv);
struct fp_img *img = *_img;
@@ -118,6 +199,14 @@ static int sanitize_image(struct fp_img_dev *imgdev, struct fp_img **_img)
return 0;
}
/**
* fpi_imgdev_report_finger_status:
* @imgdev: a #fp_img_dev imaging fingerprint device
* @present: whether the finger is present on the sensor
*
* Reports from the driver whether the user's finger is on
* the sensor.
*/
void fpi_imgdev_report_finger_status(struct fp_img_dev *imgdev,
gboolean present)
{
@@ -150,7 +239,7 @@ void fpi_imgdev_report_finger_status(struct fp_img_dev *imgdev,
if (r == FP_ENROLL_COMPLETE) {
imgdev->enroll_data = NULL;
}
fpi_drvcb_enroll_stage_completed(imgdev->dev, r,
fpi_drvcb_enroll_stage_completed(FP_DEV(imgdev), r,
r == FP_ENROLL_COMPLETE ? data : NULL,
img);
/* the callback can cancel enrollment, so recheck current
@@ -163,18 +252,18 @@ void fpi_imgdev_report_finger_status(struct fp_img_dev *imgdev,
}
break;
case IMG_ACTION_VERIFY:
fpi_drvcb_report_verify_result(imgdev->dev, r, img);
fpi_drvcb_report_verify_result(FP_DEV(imgdev), r, img);
imgdev->action_result = 0;
fp_print_data_free(data);
break;
case IMG_ACTION_IDENTIFY:
fpi_drvcb_report_identify_result(imgdev->dev, r,
fpi_drvcb_report_identify_result(FP_DEV(imgdev), r,
imgdev->identify_match_offset, img);
imgdev->action_result = 0;
fp_print_data_free(data);
break;
case IMG_ACTION_CAPTURE:
fpi_drvcb_report_capture_result(imgdev->dev, r, img);
fpi_drvcb_report_capture_result(FP_DEV(imgdev), r, img);
imgdev->action_result = 0;
break;
default:
@@ -185,14 +274,14 @@ void fpi_imgdev_report_finger_status(struct fp_img_dev *imgdev,
static void verify_process_img(struct fp_img_dev *imgdev)
{
struct fp_img_driver *imgdrv = fpi_driver_to_img_driver(imgdev->dev->drv);
struct fp_img_driver *imgdrv = fpi_driver_to_img_driver(FP_DEV(imgdev)->drv);
int match_score = imgdrv->bz3_threshold;
int r;
if (match_score == 0)
match_score = BOZORTH3_DEFAULT_THRESHOLD;
r = fpi_img_compare_print_data(imgdev->dev->verify_data,
r = fpi_img_compare_print_data(FP_DEV(imgdev)->verify_data,
imgdev->acquire_data);
if (r >= match_score)
@@ -205,7 +294,7 @@ static void verify_process_img(struct fp_img_dev *imgdev)
static void identify_process_img(struct fp_img_dev *imgdev)
{
struct fp_img_driver *imgdrv = fpi_driver_to_img_driver(imgdev->dev->drv);
struct fp_img_driver *imgdrv = fpi_driver_to_img_driver(FP_DEV(imgdev)->drv);
int match_score = imgdrv->bz3_threshold;
size_t match_offset;
int r;
@@ -214,12 +303,20 @@ static void identify_process_img(struct fp_img_dev *imgdev)
match_score = BOZORTH3_DEFAULT_THRESHOLD;
r = fpi_img_compare_print_data_to_gallery(imgdev->acquire_data,
imgdev->dev->identify_gallery, match_score, &match_offset);
FP_DEV(imgdev)->identify_gallery, match_score, &match_offset);
imgdev->action_result = r;
imgdev->identify_match_offset = match_offset;
}
/**
* fpi_imgdev_abort_scan:
* @imgdev: a #fp_img_dev imaging fingerprint device
* @result: the scan result
*
* Aborts a scan after an error, and set the action result. See
* fpi_imgdev_get_action_result() for possible values.
*/
void fpi_imgdev_abort_scan(struct fp_img_dev *imgdev, int result)
{
imgdev->action_result = result;
@@ -227,9 +324,16 @@ void fpi_imgdev_abort_scan(struct fp_img_dev *imgdev, int result)
dev_change_state(imgdev, IMGDEV_STATE_AWAIT_FINGER_OFF);
}
/**
* fpi_imgdev_image_captured:
* @imgdev: a #fp_img_dev imaging fingerprint device
* @img: an #fp_img image
*
* Report to the core that the driver captured this image from the sensor.
*/
void fpi_imgdev_image_captured(struct fp_img_dev *imgdev, struct fp_img *img)
{
struct fp_print_data *print;
struct fp_print_data *print = NULL;
int r;
G_DEBUG_HERE();
@@ -272,7 +376,7 @@ void fpi_imgdev_image_captured(struct fp_img_dev *imgdev, struct fp_img *img)
switch (imgdev->action) {
case IMG_ACTION_ENROLL:
if (!imgdev->enroll_data) {
imgdev->enroll_data = fpi_print_data_new(imgdev->dev);
imgdev->enroll_data = fpi_print_data_new(FP_DEV(imgdev));
}
BUG_ON(g_slist_length(print->prints) != 1);
/* Move print data from acquire data into enroll_data */
@@ -283,7 +387,7 @@ void fpi_imgdev_image_captured(struct fp_img_dev *imgdev, struct fp_img *img)
fp_print_data_free(imgdev->acquire_data);
imgdev->acquire_data = NULL;
imgdev->enroll_stage++;
if (imgdev->enroll_stage == imgdev->dev->nr_enroll_stages)
if (imgdev->enroll_stage == FP_DEV(imgdev)->nr_enroll_stages)
imgdev->action_result = FP_ENROLL_COMPLETE;
else
imgdev->action_result = FP_ENROLL_PASS;
@@ -307,22 +411,29 @@ next_state:
dev_change_state(imgdev, IMGDEV_STATE_AWAIT_FINGER_OFF);
}
/**
* fpi_imgdev_session_error:
* @imgdev: a #fp_img_dev imaging fingerprint device
* @error: an error code
*
* Report an error that occurred in the driver.
*/
void fpi_imgdev_session_error(struct fp_img_dev *imgdev, int error)
{
fp_dbg("error %d", error);
BUG_ON(error == 0);
switch (imgdev->action) {
case IMG_ACTION_ENROLL:
fpi_drvcb_enroll_stage_completed(imgdev->dev, error, NULL, NULL);
fpi_drvcb_enroll_stage_completed(FP_DEV(imgdev), error, NULL, NULL);
break;
case IMG_ACTION_VERIFY:
fpi_drvcb_report_verify_result(imgdev->dev, error, NULL);
fpi_drvcb_report_verify_result(FP_DEV(imgdev), error, NULL);
break;
case IMG_ACTION_IDENTIFY:
fpi_drvcb_report_identify_result(imgdev->dev, error, 0, NULL);
fpi_drvcb_report_identify_result(FP_DEV(imgdev), error, 0, NULL);
break;
case IMG_ACTION_CAPTURE:
fpi_drvcb_report_capture_result(imgdev->dev, error, NULL);
fpi_drvcb_report_capture_result(FP_DEV(imgdev), error, NULL);
break;
default:
fp_err("unhandled action %d", imgdev->action);
@@ -330,22 +441,30 @@ void fpi_imgdev_session_error(struct fp_img_dev *imgdev, int error)
}
}
/**
* fpi_imgdev_activate_complete:
* @imgdev: a #fp_img_dev imaging fingerprint device
* @status: the activation result
*
* Marks an activation as complete, whether successful or not.
* See fpi_imgdev_get_action_result() for possible values.
*/
void fpi_imgdev_activate_complete(struct fp_img_dev *imgdev, int status)
{
fp_dbg("status %d", status);
switch (imgdev->action) {
case IMG_ACTION_ENROLL:
fpi_drvcb_enroll_started(imgdev->dev, status);
fpi_drvcb_enroll_started(FP_DEV(imgdev), status);
break;
case IMG_ACTION_VERIFY:
fpi_drvcb_verify_started(imgdev->dev, status);
fpi_drvcb_verify_started(FP_DEV(imgdev), status);
break;
case IMG_ACTION_IDENTIFY:
fpi_drvcb_identify_started(imgdev->dev, status);
fpi_drvcb_identify_started(FP_DEV(imgdev), status);
break;
case IMG_ACTION_CAPTURE:
fpi_drvcb_capture_started(imgdev->dev, status);
fpi_drvcb_capture_started(FP_DEV(imgdev), status);
break;
default:
fp_err("unhandled action %d", imgdev->action);
@@ -358,22 +477,28 @@ void fpi_imgdev_activate_complete(struct fp_img_dev *imgdev, int status)
}
}
/**
* fpi_imgdev_deactivate_complete:
* @imgdev: a #fp_img_dev imaging fingerprint device
*
* Marks a deactivation as complete.
*/
void fpi_imgdev_deactivate_complete(struct fp_img_dev *imgdev)
{
G_DEBUG_HERE();
switch (imgdev->action) {
case IMG_ACTION_ENROLL:
fpi_drvcb_enroll_stopped(imgdev->dev);
fpi_drvcb_enroll_stopped(FP_DEV(imgdev));
break;
case IMG_ACTION_VERIFY:
fpi_drvcb_verify_stopped(imgdev->dev);
fpi_drvcb_verify_stopped(FP_DEV(imgdev));
break;
case IMG_ACTION_IDENTIFY:
fpi_drvcb_identify_stopped(imgdev->dev);
fpi_drvcb_identify_stopped(FP_DEV(imgdev));
break;
case IMG_ACTION_CAPTURE:
fpi_drvcb_capture_stopped(imgdev->dev);
fpi_drvcb_capture_stopped(FP_DEV(imgdev));
break;
default:
fp_err("unhandled action %d", imgdev->action);
@@ -386,7 +511,7 @@ void fpi_imgdev_deactivate_complete(struct fp_img_dev *imgdev)
int fpi_imgdev_get_img_width(struct fp_img_dev *imgdev)
{
struct fp_driver *drv = imgdev->dev->drv;
struct fp_driver *drv = FP_DEV(imgdev)->drv;
struct fp_img_driver *imgdrv = fpi_driver_to_img_driver(drv);
int width = imgdrv->img_width;
@@ -398,7 +523,7 @@ int fpi_imgdev_get_img_width(struct fp_img_dev *imgdev)
int fpi_imgdev_get_img_height(struct fp_img_dev *imgdev)
{
struct fp_driver *drv = imgdev->dev->drv;
struct fp_driver *drv = FP_DEV(imgdev)->drv;
struct fp_img_driver *imgdrv = fpi_driver_to_img_driver(drv);
int height = imgdrv->img_height;
@@ -408,19 +533,19 @@ int fpi_imgdev_get_img_height(struct fp_img_dev *imgdev)
return height;
}
static int dev_activate(struct fp_img_dev *imgdev, enum fp_imgdev_state state)
static int dev_activate(struct fp_img_dev *imgdev)
{
struct fp_driver *drv = imgdev->dev->drv;
struct fp_driver *drv = FP_DEV(imgdev)->drv;
struct fp_img_driver *imgdrv = fpi_driver_to_img_driver(drv);
if (!imgdrv->activate)
return 0;
return imgdrv->activate(imgdev, state);
return imgdrv->activate(imgdev);
}
static void dev_deactivate(struct fp_img_dev *imgdev)
{
struct fp_driver *drv = imgdev->dev->drv;
struct fp_driver *drv = FP_DEV(imgdev)->drv;
struct fp_img_driver *imgdrv = fpi_driver_to_img_driver(drv);
if (!imgdrv->deactivate)
@@ -430,14 +555,14 @@ static void dev_deactivate(struct fp_img_dev *imgdev)
static int generic_acquire_start(struct fp_dev *dev, int action)
{
struct fp_img_dev *imgdev = dev->priv;
struct fp_img_dev *imgdev = dev->img_dev;
int r;
fp_dbg("action %d", action);
imgdev->action = action;
imgdev->action_state = IMG_ACQUIRE_STATE_ACTIVATING;
imgdev->enroll_stage = 0;
r = dev_activate(imgdev, IMGDEV_STATE_AWAIT_FINGER_ON);
r = dev_activate(imgdev);
if (r < 0)
fp_err("activation failed with error %d", r);
@@ -484,7 +609,7 @@ static int img_dev_capture_start(struct fp_dev *dev)
static int img_dev_enroll_stop(struct fp_dev *dev)
{
struct fp_img_dev *imgdev = dev->priv;
struct fp_img_dev *imgdev = dev->img_dev;
BUG_ON(imgdev->action != IMG_ACTION_ENROLL);
generic_acquire_stop(imgdev);
return 0;
@@ -492,7 +617,7 @@ static int img_dev_enroll_stop(struct fp_dev *dev)
static int img_dev_verify_stop(struct fp_dev *dev, gboolean iterating)
{
struct fp_img_dev *imgdev = dev->priv;
struct fp_img_dev *imgdev = dev->img_dev;
BUG_ON(imgdev->action != IMG_ACTION_VERIFY);
generic_acquire_stop(imgdev);
return 0;
@@ -500,7 +625,7 @@ static int img_dev_verify_stop(struct fp_dev *dev, gboolean iterating)
static int img_dev_identify_stop(struct fp_dev *dev, gboolean iterating)
{
struct fp_img_dev *imgdev = dev->priv;
struct fp_img_dev *imgdev = dev->img_dev;
BUG_ON(imgdev->action != IMG_ACTION_IDENTIFY);
generic_acquire_stop(imgdev);
imgdev->identify_match_offset = 0;
@@ -509,7 +634,7 @@ static int img_dev_identify_stop(struct fp_dev *dev, gboolean iterating)
static int img_dev_capture_stop(struct fp_dev *dev)
{
struct fp_img_dev *imgdev = dev->priv;
struct fp_img_dev *imgdev = dev->img_dev;
BUG_ON(imgdev->action != IMG_ACTION_CAPTURE);
generic_acquire_stop(imgdev);
return 0;

101
libfprint/fpi-dev-img.h Normal file
View File

@@ -0,0 +1,101 @@
/*
* Copyright (C) 2007-2008 Daniel Drake <dsd@gentoo.org>
* Copyright (C) 2018 Bastien Nocera <hadess@hadess.net>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __FPI_DEV_IMG_H__
#define __FPI_DEV_IMG_H__
#include "fpi-dev.h"
#include "fpi-img.h"
/**
* fp_imgdev_action:
* @IMG_ACTION_NONE: no action
* @IMG_ACTION_ENROLL: device action is enrolling
* @IMG_ACTION_VERIFY: device action is verifying
* @IMG_ACTION_IDENTIFY: device action is identifying
* @IMG_ACTION_CAPTURE: device action is capturing
*
* The current action being performed by an imaging device. The current
* action can be gathered inside the driver using fpi_imgdev_get_action().
*/
enum fp_imgdev_action {
IMG_ACTION_NONE = 0,
IMG_ACTION_ENROLL,
IMG_ACTION_VERIFY,
IMG_ACTION_IDENTIFY,
IMG_ACTION_CAPTURE,
};
/**
* fp_imgdev_state:
* @IMGDEV_STATE_INACTIVE: inactive
* @IMGDEV_STATE_AWAIT_FINGER_ON: waiting for the finger to be pressed or swiped
* @IMGDEV_STATE_CAPTURE: capturing an image
* @IMGDEV_STATE_AWAIT_FINGER_OFF: waiting for the finger to be removed
*
* The state of an imaging device while doing a capture. The state is
* passed through to the driver using the ::activate() or ::change_state() vfuncs.
*/
enum fp_imgdev_state {
IMGDEV_STATE_INACTIVE,
IMGDEV_STATE_AWAIT_FINGER_ON,
IMGDEV_STATE_CAPTURE,
IMGDEV_STATE_AWAIT_FINGER_OFF,
};
/**
* fp_imgdev_enroll_state:
* @IMG_ACQUIRE_STATE_NONE: doing nothing
* @IMG_ACQUIRE_STATE_ACTIVATING: activating the device
* @IMG_ACQUIRE_STATE_AWAIT_FINGER_ON: waiting for the finger to be pressed or swiped
* @IMG_ACQUIRE_STATE_AWAIT_IMAGE: waiting for the image to be captured
* @IMG_ACQUIRE_STATE_AWAIT_FINGER_OFF: waiting for the finger to be removed
* @IMG_ACQUIRE_STATE_DONE: enrollment has all the images it needs
* @IMG_ACQUIRE_STATE_DEACTIVATING: deactivating the device
*
* The state of an imaging device while enrolling a fingerprint. Given that enrollment
* requires multiple captures, a number of those states will be repeated before
* the state is @IMG_ACQUIRE_STATE_DONE.
*/
enum fp_imgdev_enroll_state {
IMG_ACQUIRE_STATE_NONE = 0,
IMG_ACQUIRE_STATE_ACTIVATING,
IMG_ACQUIRE_STATE_AWAIT_FINGER_ON,
IMG_ACQUIRE_STATE_AWAIT_IMAGE,
IMG_ACQUIRE_STATE_AWAIT_FINGER_OFF,
IMG_ACQUIRE_STATE_DONE,
IMG_ACQUIRE_STATE_DEACTIVATING,
};
void fpi_imgdev_open_complete(struct fp_img_dev *imgdev, int status);
void fpi_imgdev_close_complete(struct fp_img_dev *imgdev);
void fpi_imgdev_activate_complete(struct fp_img_dev *imgdev, int status);
void fpi_imgdev_deactivate_complete(struct fp_img_dev *imgdev);
void fpi_imgdev_report_finger_status(struct fp_img_dev *imgdev,
gboolean present);
void fpi_imgdev_image_captured(struct fp_img_dev *imgdev, struct fp_img *img);
void fpi_imgdev_abort_scan(struct fp_img_dev *imgdev, int result);
void fpi_imgdev_session_error(struct fp_img_dev *imgdev, int error);
enum fp_imgdev_enroll_state fpi_imgdev_get_action_state(struct fp_img_dev *imgdev);
enum fp_imgdev_action fpi_imgdev_get_action(struct fp_img_dev *imgdev);
int fpi_imgdev_get_action_result(struct fp_img_dev *imgdev);
void fpi_imgdev_set_action_result(struct fp_img_dev *imgdev, int action_result);
#endif

150
libfprint/fpi-dev.c Normal file
View File

@@ -0,0 +1,150 @@
/*
* fp_dev types manipulation
* Copyright (C) 2018 Bastien Nocera <hadess@hadess.net>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "fp_internal.h"
#include <glib.h>
/**
* SECTION:fpi-dev
* @title: Device operations
* @short_description: Device operation functions
*
* Those macros and functions will help get access to and from struct #fp_dev,
* and struct #fp_img_dev types, as well as get and set the instance struct
* data, eg. the structure containing the data specific to each driver.
*/
/**
* FP_DEV:
* @dev: a struct #fp_img_dev
*
* Returns the struct #fp_dev associated with @dev, or %NULL on failure.
*
* Returns: a struct #fp_dev or %NULL
*/
struct fp_dev *
FP_DEV(struct fp_img_dev *dev)
{
struct fp_img_dev *imgdev;
g_return_val_if_fail (dev, NULL);
imgdev = (struct fp_img_dev *) dev;
return imgdev->parent;
}
/**
* FP_IMG_DEV:
* @dev: a struct #fp_dev representing an imaging device.
*
* Returns a struct #fp_img_dev associated with @dev, or %NULL on failure.
*
* Returns: a struct #fp_img_dev or %NULL
*/
struct fp_img_dev *
FP_IMG_DEV(struct fp_dev *dev)
{
g_return_val_if_fail (dev, NULL);
g_return_val_if_fail (dev->drv, NULL);
g_return_val_if_fail (dev->drv->type == DRIVER_IMAGING, NULL);
return dev->img_dev;
}
/**
* fp_dev_set_instance_data:
* @dev: a struct #fp_dev
* @instance_data: a pointer to the instance data
*
* Set the instance data for a struct #fp_dev. This is usually a structure
* private to the driver used to keep state and pass it as user_data to
* asynchronous functions.
*
* The core does not do any memory management for this data, so the driver
* itself will have to create and free its own structure when appropriate.
*/
void
fp_dev_set_instance_data (struct fp_dev *dev,
void *instance_data)
{
g_return_if_fail (dev);
g_return_if_fail (instance_data != NULL);
g_return_if_fail (dev->instance_data == NULL);
dev->instance_data = instance_data;
}
/**
* FP_INSTANCE_DATA:
* @dev: a struct #fp_dev
*
* Returns the instance data set using fp_dev_set_instance_data().
*/
void *
FP_INSTANCE_DATA (struct fp_dev *dev)
{
g_return_val_if_fail (dev, NULL);
return dev->instance_data;
}
/**
* fpi_dev_get_usb_dev:
* @dev: a struct #fp_dev
*
* Returns the #libusb_device_handle associated with @dev or %NULL
* if none are associated.
*
* Returns: a #libusb_device_handle pointer or %NULL
*/
libusb_device_handle *
fpi_dev_get_usb_dev(struct fp_dev *dev)
{
return dev->udev;
}
/**
* fpi_dev_set_nr_enroll_stages:
* @dev: a struct #fp_dev
* @nr_enroll_stages: the number of enroll stages
*
* Sets the number of enroll stages that this device uses. This is
* usually only necessary for primitive devices which have a hard-coded
* number of enroll stages baked into their protocol.
*/
void
fpi_dev_set_nr_enroll_stages(struct fp_dev *dev,
int nr_enroll_stages)
{
dev->nr_enroll_stages = nr_enroll_stages;
}
/**
* fpi_dev_get_verify_data:
* @dev: a struct #fp_dev
*
* Returns the verify data associated with @dev.
* This is usually only necessary for primitive devices which need to
* have access to the raw verify data as it might have been stored on disk.
*
* Returns: a struct #fp_print_data pointer or %NULL
*/
struct fp_print_data *
fpi_dev_get_verify_data(struct fp_dev *dev)
{
return dev->verify_data;
}

47
libfprint/fpi-dev.h Normal file
View File

@@ -0,0 +1,47 @@
/*
* Copyright (C) 2018 Bastien Nocera <hadess@hadess.net>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __FPI_DEV_H__
#define __FPI_DEV_H__
#include <libusb.h>
#include <fprint.h>
struct fp_dev;
/**
* fp_img_dev:
*
* #fp_img_dev is an opaque structure type. You must access it using the
* appropriate functions.
*/
struct fp_img_dev;
struct fp_dev *FP_DEV (struct fp_img_dev *dev);
struct fp_img_dev *FP_IMG_DEV (struct fp_dev *dev);
void fp_dev_set_instance_data (struct fp_dev *dev,
void *instance_data);
void *FP_INSTANCE_DATA (struct fp_dev *dev);
libusb_device_handle *fpi_dev_get_usb_dev(struct fp_dev *dev);
void fpi_dev_set_nr_enroll_stages(struct fp_dev *dev,
int nr_enroll_stages);
struct fp_print_data *fpi_dev_get_verify_data(struct fp_dev *dev);
#endif

View File

@@ -23,7 +23,19 @@
#include "fp_internal.h"
struct fp_img *fpi_im_resize(struct fp_img *img, unsigned int w_factor, unsigned int h_factor)
/**
* fpi_img_resize:
* @img: an #fp_img image
* @w_factor: horizontal factor to resize the image by
* @h_factor: vertical factor to resize the image by
*
* Resizes the #fp_img image by scaling it by @w_factor times horizontally
* and @h_factor times vertically.
*
* Returns: a newly allocated #fp_img, the original @img will not be modified
* and will also need to be freed
*/
struct fp_img *fpi_img_resize(struct fp_img *img, unsigned int w_factor, unsigned int h_factor)
{
int new_width = img->width * w_factor;
int new_height = img->height * h_factor;

View File

@@ -31,6 +31,7 @@
/**
* SECTION:img
* @title: Image operations
* @short_description: Image operation functions
*
* libfprint offers several ways of retrieving images from imaging devices,
* one example being the fp_dev_img_capture() function. The functions
@@ -48,6 +49,25 @@
* natural upright orientation.
*/
/**
* SECTION:fpi-img
* @title: Driver Image operations
* @short_description: Driver image operation functions
*
* Those are the driver-specific helpers for #fp_img manipulation. See #fp_img's
* documentation for more information about data formats, and their uses in
* front-end applications.
*/
/**
* fpi_img_new:
* @length: the length of data to allocate
*
* Creates a new #fp_img structure with @length bytes of data allocated
* to hold the image.
*
* Returns: a new #fp_img to free with fp_img_free()
*/
struct fp_img *fpi_img_new(size_t length)
{
struct fp_img *img = g_malloc0(sizeof(*img) + length);
@@ -56,9 +76,19 @@ struct fp_img *fpi_img_new(size_t length)
return img;
}
/**
* fpi_img_new_for_imgdev:
* @imgdev: a #fp_img_dev imaging fingerprint device
*
* Creates a new #fp_img structure, like fpi_img_new(), but uses the
* driver's advertised height and width to calculate the size of the
* length of data to allocate.
*
* Returns: a new #fp_img to free with fp_img_free()
*/
struct fp_img *fpi_img_new_for_imgdev(struct fp_img_dev *imgdev)
{
struct fp_img_driver *imgdrv = fpi_driver_to_img_driver(imgdev->dev->drv);
struct fp_img_driver *imgdrv = fpi_driver_to_img_driver(FP_DEV(imgdev)->drv);
int width = imgdrv->img_width;
int height = imgdrv->img_height;
struct fp_img *img = fpi_img_new(width * height);
@@ -67,27 +97,53 @@ struct fp_img *fpi_img_new_for_imgdev(struct fp_img_dev *imgdev)
return img;
}
/**
* fpi_img_is_sane:
* @img: a #fp_img image
*
* Checks whether an #fp_img structure passes some basic checks, such
* as length, width and height being non-zero, and the buffer being
* big enough to hold the image of said size.
*
* Returns: %TRUE if the image is sane, %FALSE otherwise
*/
gboolean fpi_img_is_sane(struct fp_img *img)
{
guint len;
/* basic checks */
if (!img->length || !img->width || !img->height)
if (!img->length || img->width <= 0 || img->height <= 0)
return FALSE;
/* buffer is big enough? */
if ((img->length * img->height) < img->length)
/* Are width and height just too big? */
if (!g_uint_checked_mul(&len, img->width, img->height) ||
len > G_MAXINT)
return FALSE;
/* buffer big enough? */
if (len > img->length)
return FALSE;
return TRUE;
}
struct fp_img *fpi_img_resize(struct fp_img *img, size_t newsize)
/**
* fpi_img_realloc:
* @img: an #fp_img image
* @newsize: the new length of the image
*
* Changes the size of the data part of the #fp_img.
*
* Returns: the modified #fp_img, the same as the first argument to this function
*/
struct fp_img *fpi_img_realloc(struct fp_img *img, size_t newsize)
{
return g_realloc(img, sizeof(*img) + newsize);
}
/**
* fp_img_free:
* @img: the image to destroy. If NULL, function simply returns.
* @img: the image to destroy. If %NULL, function simply returns.
*
* Frees an image. Must be called when you are finished working with an image.
*/
@@ -262,9 +318,8 @@ static void minutiae_to_xyt(struct fp_minutiae *minutiae, int bwidth,
struct minutiae_struct c[MAX_FILE_MINUTIAE];
struct xyt_struct *xyt = (struct xyt_struct *) buf;
/* FIXME: only considers first 150 minutiae (MAX_FILE_MINUTIAE) */
/* nist does weird stuff with 150 vs 1000 limits */
int nmin = min(minutiae->num, MAX_FILE_MINUTIAE);
/* struct xyt_struct uses arrays of MAX_BOZORTH_MINUTIAE (200) */
int nmin = min(minutiae->num, MAX_BOZORTH_MINUTIAE);
for (i = 0; i < nmin; i++){
minutia = minutiae->list[i];
@@ -288,6 +343,9 @@ static void minutiae_to_xyt(struct fp_minutiae *minutiae, int bwidth,
xyt->nrows = nmin;
}
#define FP_IMG_STANDARDIZATION_FLAGS (FP_IMG_V_FLIPPED | FP_IMG_H_FLIPPED \
| FP_IMG_COLORS_INVERTED)
static int fpi_img_detect_minutiae(struct fp_img *img)
{
struct fp_minutiae *minutiae;
@@ -300,13 +358,10 @@ static int fpi_img_detect_minutiae(struct fp_img *img)
GTimer *timer;
if (img->flags & FP_IMG_STANDARDIZATION_FLAGS) {
fp_err("cant detect minutiae for non-standardized image");
fp_err("Cannot detect minutiae for non-standardized images");
return -EINVAL;
}
/* Remove perimeter points from partial image */
g_lfsparms_V2.remove_perimeter_pts = img->flags & FP_IMG_PARTIAL ? TRUE : FALSE;
/* 25.4 mm per inch */
timer = g_timer_new();
r = get_minutiae(&minutiae, &quality_map, &direction_map,
@@ -352,7 +407,7 @@ int fpi_img_to_print_data(struct fp_img_dev *imgdev, struct fp_img *img,
/* FIXME: space is wasted if we dont hit the max minutiae count. would
* be good to make this dynamic. */
print = fpi_print_data_new(imgdev->dev);
print = fpi_print_data_new(FP_DEV(imgdev));
item = fpi_print_data_item_new(sizeof(struct xyt_struct));
print->type = PRINT_DATA_NBIS_MINUTIAE;
minutiae_to_xyt(img->minutiae, img->width, img->height, item->data);
@@ -536,57 +591,46 @@ API_EXPORTED struct fp_minutia **fp_img_get_minutiae(struct fp_img *img,
return img->minutiae->list;
}
libusb_device_handle *
fpi_imgdev_get_usb_dev(struct fp_img_dev *dev)
/**
* fp_minutia_get_coords:
* @minutia: a struct #fp_minutia
* @coord_x: the return variable for the X coordinate of the minutia
* @coord_y: the return variable for the Y coordinate of the minutia
*
* Sets @coord_x and @coord_y to be the coordinates of the detected minutia, so it
* can be presented in a more verbose user interface. This is usually only
* used for debugging purposes.
*
* Returns: 0 on success, -1 on error.
*/
API_EXPORTED int fp_minutia_get_coords(struct fp_minutia *minutia, int *coord_x, int *coord_y)
{
return dev->udev;
g_return_val_if_fail (minutia != NULL, -1);
g_return_val_if_fail (coord_x != NULL, -1);
g_return_val_if_fail (coord_y != NULL, -1);
*coord_x = minutia->x;
*coord_y = minutia->y;
return 0;
}
void
fpi_imgdev_set_user_data(struct fp_img_dev *imgdev,
void *user_data)
{
imgdev->priv = user_data;
}
void *
fpi_imgdev_get_user_data(struct fp_img_dev *imgdev)
{
return imgdev->priv;
}
struct fp_dev *
fpi_imgdev_get_dev(struct fp_img_dev *imgdev)
{
return imgdev->dev;
}
enum fp_imgdev_enroll_state
fpi_imgdev_get_action_state(struct fp_img_dev *imgdev)
{
return imgdev->action_state;
}
enum fp_imgdev_action
fpi_imgdev_get_action(struct fp_img_dev *imgdev)
{
return imgdev->action;
}
int
fpi_imgdev_get_action_result(struct fp_img_dev *imgdev)
{
return imgdev->action_result;
}
void
fpi_imgdev_set_action_result(struct fp_img_dev *imgdev,
int action_result)
{
imgdev->action_result = action_result;
}
/* Calculate squared standand deviation */
/**
* fpi_std_sq_dev:
* @buf: buffer (usually bitmap, one byte per pixel)
* @size: size of @buffer
*
* Calculates the squared standard deviation of the individual
* pixels in the buffer, as per the following formula:
* |[<!-- -->
* mean = sum (buf[0..size]) / size
* sq_dev = sum ((buf[0.size] - mean) ^ 2)
* ]|
* This function is usually used to determine whether image
* is empty.
*
* Returns: the squared standard deviation for @buffer
*/
int fpi_std_sq_dev(const unsigned char *buf, int size)
{
int res = 0, mean = 0, i;
@@ -609,7 +653,23 @@ int fpi_std_sq_dev(const unsigned char *buf, int size)
return res / size;
}
/* Calculate normalized mean square difference of two lines */
/**
* fpi_mean_sq_diff_norm:
* @buf1: buffer (usually bitmap, one byte per pixel)
* @buf2: buffer (usually bitmap, one byte per pixel)
* @size: buffer size of smallest buffer
*
* This function calculates the normalized mean square difference of
* two buffers, usually two lines, as per the following formula:
* |[<!-- -->
* sq_diff = sum ((buf1[0..size] - buf2[0..size]) ^ 2) / size
* ]|
*
* This functions is usually used to get numerical difference
* between two images.
*
* Returns: the normalized mean squared difference between @buf1 and @buf2
*/
int fpi_mean_sq_diff_norm(unsigned char *buf1, unsigned char *buf2, int size)
{
int res = 0, i;

85
libfprint/fpi-img.h Normal file
View File

@@ -0,0 +1,85 @@
/*
* Copyright (C) 2007-2008 Daniel Drake <dsd@gentoo.org>
* Copyright (C) 2018 Bastien Nocera <hadess@hadess.net>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __FPI_IMG_H__
#define __FPI_IMG_H__
#include <stdint.h>
struct fp_minutiae;
/**
* FpiImgFlags:
* @FP_IMG_V_FLIPPED: the image is vertically flipped
* @FP_IMG_H_FLIPPED: the image is horizontally flipped
* @FP_IMG_COLORS_INVERTED: the colours are inverted
* @FP_IMG_BINARIZED_FORM: binarised image, see fp_img_binarize()
* @FP_IMG_PARTIAL: the image is partial, useful for driver to keep track
* of incomplete captures
*
* Flags used in the #fp_img structure to describe the image contained
* into the structure. Note that a number of functions will refuse to
* handle images which haven't been standardised through fp_img_standardize()
* (meaning the @FP_IMG_V_FLIPPED, @FP_IMG_H_FLIPPED and @FP_IMG_COLORS_INVERTED
* should all be unset when the image needs to be analysed).
*/
typedef enum {
FP_IMG_V_FLIPPED = 1 << 0,
FP_IMG_H_FLIPPED = 1 << 1,
FP_IMG_COLORS_INVERTED = 1 << 2,
FP_IMG_BINARIZED_FORM = 1 << 3,
FP_IMG_PARTIAL = 1 << 4
} FpiImgFlags;
/**
* fp_img:
* @width: the width of the image
* @height: the height of the image
* @length: the length of the data associated with the image
* @flags: @FpiImgFlags flags describing the image contained in the structure
* @minutiae: an opaque structure representing the detected minutiae
* @binarized: the binarized image data
* @data: the start of the image data, which will be of @length size.
*
* A structure representing a captured, or processed image. The @flags member
* will show its current state, including whether whether the binarized form
* if present, whether it is complete, and whether it needs particular changes
* before being processed.
*/
struct fp_img {
int width;
int height;
size_t length;
FpiImgFlags flags;
/*< private >*/
struct fp_minutiae *minutiae;
/*< public >*/
unsigned char *binarized;
unsigned char data[0];
};
struct fp_img *fpi_img_new(size_t length);
struct fp_img *fpi_img_new_for_imgdev(struct fp_img_dev *imgdev);
struct fp_img *fpi_img_realloc(struct fp_img *img, size_t newsize);
struct fp_img *fpi_img_resize(struct fp_img *img, unsigned int w_factor, unsigned int h_factor);
int fpi_std_sq_dev(const unsigned char *buf, int size);
int fpi_mean_sq_diff_norm(unsigned char *buf1, unsigned char *buf2, int size);
#endif

98
libfprint/fpi-log.h Normal file
View File

@@ -0,0 +1,98 @@
/*
* Copyright (C) 2007-2008 Daniel Drake <dsd@gentoo.org>
* Copyright (C) 2018 Bastien Nocera <hadess@hadess.net>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __FPI_LOG_H__
#define __FPI_LOG_H__
/**
* SECTION:fpi-log
* @title: Logging
* @short_description: Logging functions
*
* Logging in libfprint is handled through GLib's logging system, and behave the same
* way as in the GLib [Message Output and Debugging Functions](https://developer.gnome.org/glib/stable/glib-Message-Logging.html)
* documentation.
*
* You should include `fpi-log.h` as early as possible in your sources, just after
* setting the `FP_COMPONENT` define to a string unique to your sources. This will
* set the suffix of the `G_LOG_DOMAIN` used for printing.
*/
#ifdef FP_COMPONENT
#undef G_LOG_DOMAIN
#ifndef __GTK_DOC_IGNORE__
#define G_LOG_DOMAIN "libfprint-"FP_COMPONENT
#endif
#endif
#include <glib.h>
/**
* fp_dbg:
*
* Same as g_debug().
*
*/
#define fp_dbg g_debug
/**
* fp_info:
*
* Same as g_debug().
*/
#define fp_info g_debug
/**
* fp_warn:
*
* Same as g_warning().
*/
#define fp_warn g_warning
/**
* fp_err:
*
* Same as g_warning(). 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
/**
* BUG_ON:
* @condition: the condition to check
*
* Uses fp_err() to print an error if the @condition is true.
*/
#define BUG_ON(condition) G_STMT_START \
if (condition) { \
char *s; \
s = g_strconcat ("BUG: (", #condition, ")", NULL); \
fp_err ("%s: %s() %s:%d", s, G_STRFUNC, __FILE__, __LINE__); \
g_free (s); \
} G_STMT_END
/**
* BUG:
*
* Same as BUG_ON() but is always true.
*/
#define BUG() BUG_ON(1)
#endif

View File

@@ -20,6 +20,7 @@
#define FP_COMPONENT "poll"
#include "fp_internal.h"
#include "fpi-poll.h"
#include <config.h>
#include <errno.h>
@@ -32,6 +33,7 @@
/**
* SECTION:events
* @title: Initialisation and events handling
* @short_description: Initialisation and events handling functions
*
* These functions are only applicable to users of libfprint's asynchronous
* API.
@@ -63,6 +65,16 @@
* your main loop.
*/
/**
* SECTION:fpi-poll
* @title: Timeouts
* @short_description: Timeout handling helpers
*
* Helper functions to schedule a function call to be made after a timeout. This
* is useful to avoid making blocking calls while waiting for hardware to answer
* for example.
*/
/* this is a singly-linked list of pending timers, sorted with the timer that
* is expiring soonest at the head. */
static GSList *active_timers = NULL;
@@ -74,13 +86,15 @@ static fp_pollfd_removed_cb fd_removed_cb = NULL;
struct fpi_timeout {
struct timeval expiry;
fpi_timeout_fn callback;
struct fp_dev *dev;
void *data;
char *name;
};
static int timeout_sort_fn(gconstpointer _a, gconstpointer _b)
{
struct fpi_timeout *a = (struct fpi_timeout *) _a;
struct fpi_timeout *b = (struct fpi_timeout *) _b;
fpi_timeout *a = (fpi_timeout *) _a;
fpi_timeout *b = (fpi_timeout *) _b;
struct timeval *tv_a = &a->expiry;
struct timeval *tv_b = &b->expiry;
@@ -92,27 +106,78 @@ static int timeout_sort_fn(gconstpointer _a, gconstpointer _b)
return 0;
}
/* A timeout is the asynchronous equivalent of sleeping. You create a timeout
static void
fpi_timeout_free(fpi_timeout *timeout)
{
if (timeout == NULL)
return;
g_free(timeout->name);
g_free(timeout);
}
/**
* fpi_timeout_set_name:
* @timeout: a #fpi_timeout
* @name: the name to give the timeout
*
* Sets a name for a timeout, allowing that name to be printed
* along with any timeout related debug.
*/
void
fpi_timeout_set_name(fpi_timeout *timeout,
const char *name)
{
g_return_if_fail (timeout != NULL);
g_return_if_fail (name != NULL);
g_return_if_fail (timeout->name == NULL);
timeout->name = g_strdup(name);
}
/**
* fpi_timeout_add:
* @msec: the time before calling the function, in milliseconds (1/1000ths of a second)
* @callback: function to callback
* @dev: a struct #fp_dev
* @data: data to pass to @callback, or %NULL
*
* A timeout is the asynchronous equivalent of sleeping. You create a timeout
* saying that you'd like to have a function invoked at a certain time in
* the future. */
struct fpi_timeout *fpi_timeout_add(unsigned int msec, fpi_timeout_fn callback,
void *data)
* the future.
*
* Note that you should hold onto the return value of this function to cancel it
* use fpi_timeout_cancel(), otherwise the callback could be called while the driver
* is being torn down.
*
* This function can be considered to never fail.
*
* Returns: an #fpi_timeout structure
*/
fpi_timeout *fpi_timeout_add(unsigned int msec,
fpi_timeout_fn callback,
struct fp_dev *dev,
void *data)
{
struct timespec ts;
struct timeval add_msec;
struct fpi_timeout *timeout;
fpi_timeout *timeout;
int r;
g_return_val_if_fail (dev != NULL, NULL);
fp_dbg("in %dms", msec);
r = clock_gettime(CLOCK_MONOTONIC, &ts);
if (r < 0) {
fp_err("failed to read monotonic clock, errno=%d", errno);
BUG();
return NULL;
}
timeout = g_malloc(sizeof(*timeout));
timeout = g_new0(fpi_timeout, 1);
timeout->callback = callback;
timeout->dev = dev;
timeout->data = data;
TIMESPEC_TO_TIMEVAL(&timeout->expiry, &ts);
@@ -128,11 +193,18 @@ struct fpi_timeout *fpi_timeout_add(unsigned int msec, fpi_timeout_fn callback,
return timeout;
}
void fpi_timeout_cancel(struct fpi_timeout *timeout)
/**
* fpi_timeout_cancel:
* @timeout: an #fpi_timeout structure
*
* Cancels a timeout scheduled with fpi_timeout_add(), and frees the
* @timeout structure.
*/
void fpi_timeout_cancel(fpi_timeout *timeout)
{
G_DEBUG_HERE();
active_timers = g_slist_remove(active_timers, timeout);
g_free(timeout);
fpi_timeout_free(timeout);
}
/* get the expiry time and optionally the timeout structure for the next
@@ -163,11 +235,18 @@ static int get_next_timeout_expiry(struct timeval *out,
*out_timeout = next_timeout;
if (timercmp(&tv, &next_timeout->expiry, >=)) {
fp_dbg("first timeout already expired");
if (next_timeout->name)
fp_dbg("first timeout '%s' already expired", next_timeout->name);
else
fp_dbg("first timeout already expired");
timerclear(out);
} else {
timersub(&next_timeout->expiry, &tv, out);
fp_dbg("next timeout in %ld.%06lds", out->tv_sec, out->tv_usec);
if (next_timeout->name)
fp_dbg("next timeout '%s' in %ld.%06lds", next_timeout->name,
out->tv_sec, out->tv_usec);
else
fp_dbg("next timeout in %ld.%06lds", out->tv_sec, out->tv_usec);
}
return 1;
@@ -177,9 +256,9 @@ static int get_next_timeout_expiry(struct timeval *out,
static void handle_timeout(struct fpi_timeout *timeout)
{
G_DEBUG_HERE();
timeout->callback(timeout->data);
timeout->callback(timeout->dev, timeout->data);
active_timers = g_slist_remove(active_timers, timeout);
g_free(timeout);
fpi_timeout_free(timeout);
}
static int handle_timeouts(void)
@@ -263,7 +342,7 @@ API_EXPORTED int fp_handle_events(void)
/**
* fp_get_next_timeout:
* @tv: a %timeval structure containing the duration to the next timeout.
* @tv: a #timeval structure containing the duration to the next timeout.
*
* A zero filled @tv timeout means events are to be handled immediately
*
@@ -271,8 +350,8 @@ API_EXPORTED int fp_handle_events(void)
*/
API_EXPORTED int fp_get_next_timeout(struct timeval *tv)
{
struct timeval fprint_timeout;
struct timeval libusb_timeout;
struct timeval fprint_timeout = { 0, 0 };
struct timeval libusb_timeout = { 0, 0 };
int r_fprint;
int r_libusb;
@@ -281,7 +360,7 @@ API_EXPORTED int fp_get_next_timeout(struct timeval *tv)
/* if we have no pending timeouts and the same is true for libusb,
* indicate that we have no pending timouts */
if (r_fprint == 0 && r_libusb == 0)
if (r_fprint <= 0 && r_libusb <= 0)
return 0;
/* if fprint have no pending timeouts return libusb timeout */
@@ -321,6 +400,8 @@ API_EXPORTED ssize_t fp_get_pollfds(struct fp_pollfd **pollfds)
ssize_t cnt = 0;
size_t i = 0;
g_return_val_if_fail (fpi_usb_ctx != NULL, -EIO);
usbfds = libusb_get_pollfds(fpi_usb_ctx);
if (!usbfds) {
*pollfds = NULL;
@@ -376,10 +457,29 @@ void fpi_poll_init(void)
void fpi_poll_exit(void)
{
g_slist_free(active_timers);
g_slist_free_full(active_timers, (GDestroyNotify) fpi_timeout_free);
active_timers = NULL;
fd_added_cb = NULL;
fd_removed_cb = NULL;
libusb_set_pollfd_notifiers(fpi_usb_ctx, NULL, NULL, NULL);
}
void
fpi_timeout_cancel_all_for_dev(struct fp_dev *dev)
{
GSList *l;
g_return_if_fail (dev != NULL);
l = active_timers;
while (l) {
struct fpi_timeout *timeout = l->data;
GSList *current = l;
l = l->next;
if (timeout->dev == dev) {
g_free (timeout);
active_timers = g_slist_delete_link (active_timers, current);
}
}
}

51
libfprint/fpi-poll.h Normal file
View File

@@ -0,0 +1,51 @@
/*
* Copyright (C) 2008 Daniel Drake <dsd@gentoo.org>
* Copyright (C) 2018 Bastien Nocera <hadess@hadess.net>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __FPI_POLL_H__
#define __FPI_POLL_H__
#include "fprint.h"
/**
* fpi_timeout_fn:
* @dev: the struct #fp_dev passed to fpi_timeout_add()
* @data: the data passed to fpi_timeout_add()
*
* The prototype of the callback function for fpi_timeout_add().
* Note that after the callback is called, the #fpi_timeout structure will
* be freed.
*/
typedef void (*fpi_timeout_fn)(struct fp_dev *dev, void *data);
/**
* fpi_timeout:
*
* An opaque structure representing a scheduled function call, created with
* fpi_timeout_add().
*/
typedef struct fpi_timeout fpi_timeout;
fpi_timeout *fpi_timeout_add(unsigned int msec,
fpi_timeout_fn callback,
struct fp_dev *dev,
void *data);
void fpi_timeout_set_name(fpi_timeout *timeout,
const char *name);
void fpi_timeout_cancel(fpi_timeout *timeout);
#endif

317
libfprint/fpi-ssm.c Normal file
View File

@@ -0,0 +1,317 @@
/*
* Functions to assist with asynchronous driver <---> library communications
* 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
*/
#define FP_COMPONENT "drv"
#include "fp_internal.h"
#include "fpi-ssm.h"
#include <config.h>
#include <errno.h>
/**
* SECTION:fpi-ssm
* @title: Sequential state machine
* @short_description: State machine helpers
*
* Asynchronous driver design encourages some kind of state machine behind it.
* In most cases, the state machine is entirely linear - you only go to the
* next state, you never jump or go backwards. The #fpi_ssm functions help you
* implement such a machine.
*
* e.g. `S1` ↦ `S2` ↦ `S3` ↦ `S4`
*
* `S1` is the start state
* There is also an implicit error state and an implicit accepting state
* (both with implicit edges from every state).
*
* You can also jump to any arbitrary state (while marking completion of the
* current state) while the machine is running. In other words there are
* implicit edges linking one state to every other state.
*
* To create an #fpi_ssm, you pass a state handler function and the total number of
* states (4 in the above example) to fpi_ssm_new(). Note that the state numbers
* start at zero, making them match the first value in a C enumeration.
*
* 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).
*
* 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
* the ssm as successfully completed.
*
* To mark successful completion of a SSM, either iterate beyond the final
* state or call fpi_ssm_mark_completed() from any state.
*
* To mark failed completion of a SSM, call fpi_ssm_mark_failed() from any
* state. You must pass a non-zero error code.
*
* Your state handling function looks at the return value of
* fpi_ssm_get_cur_state() in order to determine the current state and hence
* which operations to perform (a switch statement is appropriate).
*
* Typically, the state handling function fires off an asynchronous
* communication with the device (such as a libsub transfer), and the
* callback function iterates the machine to the next state
* upon success (or fails).
*
* Your completion callback should examine the return value of
* fpi_ssm_get_error() in order to determine whether the #fpi_ssm completed or
* failed. An error code of zero indicates successful completion.
*/
struct fpi_ssm {
struct fp_dev *dev;
fpi_ssm *parentsm;
void *user_data;
int nr_states;
int cur_state;
gboolean completed;
int error;
ssm_completed_fn callback;
ssm_handler_fn handler;
};
/**
* fpi_ssm_new:
* @dev: a #fp_dev fingerprint device
* @handler: the callback function
* @nr_states: the number of states
* @user_data: the user data to pass to callbacks
*
* Allocate a new ssm, with @nr_states states. The @handler callback
* will be called after each state transition.
*
* Returns: a new #fpi_ssm state machine
*/
fpi_ssm *fpi_ssm_new(struct fp_dev *dev,
ssm_handler_fn handler,
int nr_states,
void *user_data)
{
fpi_ssm *machine;
BUG_ON(nr_states < 1);
machine = g_malloc0(sizeof(*machine));
machine->handler = handler;
machine->nr_states = nr_states;
machine->dev = dev;
machine->completed = TRUE;
machine->user_data = user_data;
return machine;
}
/**
* fpi_ssm_get_user_data:
* @machine: an #fpi_ssm state machine
*
* Retrieve the pointer to user data set when fpi_ssm_new()
* is called.
*
* Returns: a pointer
*/
void *
fpi_ssm_get_user_data(fpi_ssm *machine)
{
return machine->user_data;
}
/**
* fpi_ssm_free:
* @machine: an #fpi_ssm state machine
*
* Frees a state machine. This does not call any error or success
* callbacks, so you need to do this yourself.
*/
void fpi_ssm_free(fpi_ssm *machine)
{
if (!machine)
return;
g_free(machine);
}
/* Invoke the state handler */
static void __ssm_call_handler(fpi_ssm *machine)
{
fp_dbg("%p entering state %d", machine, machine->cur_state);
machine->handler(machine, machine->dev, machine->user_data);
}
/**
* fpi_ssm_start:
* @ssm: an #fpi_ssm state machine
* @callback: the #ssm_completed_fn 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.
*/
void fpi_ssm_start(fpi_ssm *ssm, ssm_completed_fn callback)
{
BUG_ON(!ssm->completed);
ssm->callback = callback;
ssm->cur_state = 0;
ssm->completed = FALSE;
ssm->error = 0;
__ssm_call_handler(ssm);
}
static void __subsm_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
{
fpi_ssm *parent = ssm->parentsm;
BUG_ON(!parent);
if (ssm->error)
fpi_ssm_mark_failed(parent, ssm->error);
else
fpi_ssm_next_state(parent);
fpi_ssm_free(ssm);
}
/**
* fpi_ssm_start_subsm:
* @parent: an #fpi_ssm state machine
* @child: an #fpi_ssm state machine
*
* Starts a state machine as a child of another. if the child completes
* successfully, the parent will be advanced to the next state. if the
* child fails, the parent will be marked as failed with the same error code.
*
* The child will be automatically freed upon completion or failure.
*/
void fpi_ssm_start_subsm(fpi_ssm *parent, fpi_ssm *child)
{
child->parentsm = parent;
fpi_ssm_start(child, __subsm_complete);
}
/**
* fpi_ssm_mark_completed:
* @machine: an #fpi_ssm state machine
*
* Mark a ssm as completed successfully. The callback set when creating
* the state machine with fpi_ssm_new() will be called synchronously.
*/
void fpi_ssm_mark_completed(fpi_ssm *machine)
{
BUG_ON(machine->completed);
machine->completed = TRUE;
fp_dbg("%p completed with status %d", machine, machine->error);
if (machine->callback)
machine->callback(machine, machine->dev, machine->user_data);
}
/**
* fpi_ssm_mark_failed:
* @machine: an #fpi_ssm state machine
* @error: the error code
*
* Mark a state machine as failed with @error as the error code.
*/
void fpi_ssm_mark_failed(fpi_ssm *machine, int error)
{
fp_dbg("error %d from state %d", error, machine->cur_state);
BUG_ON(error == 0);
machine->error = error;
fpi_ssm_mark_completed(machine);
}
/**
* fpi_ssm_next_state:
* @machine: an #fpi_ssm state machine
*
* Iterate to next state of a state machine. If the current state is the
* last state, then the state machine will be marked as completed, as
* if calling fpi_ssm_mark_completed().
*/
void fpi_ssm_next_state(fpi_ssm *machine)
{
g_return_if_fail (machine != NULL);
BUG_ON(machine->completed);
machine->cur_state++;
if (machine->cur_state == machine->nr_states) {
fpi_ssm_mark_completed(machine);
} else {
__ssm_call_handler(machine);
}
}
/**
* fpi_ssm_next_state_timeout_cb:
* @dev: a struct #fp_dev
* @data: a pointer to an #fpi_ssm 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 #fpi_ssm as the `user_data` argument
* for that fpi_timeout_add() call.
*/
void
fpi_ssm_next_state_timeout_cb(struct fp_dev *dev,
void *data)
{
g_return_if_fail (dev != NULL);
g_return_if_fail (data != NULL);
fpi_ssm_next_state(data);
}
/**
* fpi_ssm_jump_to_state:
* @machine: an #fpi_ssm state machine
* @state: the state to jump to
*
* Jump to the @state state, bypassing intermediary states.
*/
void fpi_ssm_jump_to_state(fpi_ssm *machine, int state)
{
BUG_ON(machine->completed);
BUG_ON(state >= machine->nr_states);
machine->cur_state = state;
__ssm_call_handler(machine);
}
/**
* fpi_ssm_get_cur_state:
* @machine: an #fpi_ssm state machine
*
* Returns the value of the current state. Note that states are
* 0-indexed, so a value of 0 means “the first state”.
*
* Returns: the current state.
*/
int fpi_ssm_get_cur_state(fpi_ssm *machine)
{
return machine->cur_state;
}
/**
* fpi_ssm_get_error:
* @machine: an #fpi_ssm state machine
*
* Returns the error code set by fpi_ssm_mark_failed().
*
* Returns: a error code
*/
int fpi_ssm_get_error(fpi_ssm *machine)
{
return machine->error;
}

86
libfprint/fpi-ssm.h Normal file
View File

@@ -0,0 +1,86 @@
/*
* Copyright (C) 2007-2008 Daniel Drake <dsd@gentoo.org>
* Copyright (C) 2018 Bastien Nocera <hadess@hadess.net>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __FPI_SSM_H__
#define __FPI_SSM_H__
#include <stdint.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <glib.h>
#include <libusb.h>
/* async drv <--> lib comms */
/**
* fpi_ssm:
*
* Sequential state machine that iterates sequentially over
* a predefined series of states. Can be terminated by either completion or
* failure error conditions.
*/
typedef struct fpi_ssm fpi_ssm;
/**
* ssm_completed_fn:
* @ssm: a #fpi_ssm state machine
* @dev: the #fp_dev fingerprint device
* @user_data: the user data passed to fpi_ssm_new()
*
* The callback called when a state machine completes successfully,
* as set when calling fpi_ssm_start().
*/
typedef void (*ssm_completed_fn)(fpi_ssm *ssm,
struct fp_dev *dev,
void *user_data);
/**
* ssm_handler_fn:
* @ssm: a #fpi_ssm state machine
* @dev: the #fp_dev fingerprint device
* @user_data: the user data passed to fpi_ssm_new()
*
* The callback called when a state machine transitions from one
* state to the next, as set when calling fpi_ssm_new().
*/
typedef void (*ssm_handler_fn)(fpi_ssm *ssm,
struct fp_dev *dev,
void *user_data);
/* for library and drivers */
fpi_ssm *fpi_ssm_new(struct fp_dev *dev,
ssm_handler_fn handler,
int nr_states,
void *user_data);
void fpi_ssm_free(fpi_ssm *machine);
void fpi_ssm_start(fpi_ssm *ssm, ssm_completed_fn callback);
void fpi_ssm_start_subsm(fpi_ssm *parent, fpi_ssm *child);
/* for drivers */
void fpi_ssm_next_state(fpi_ssm *machine);
void fpi_ssm_next_state_timeout_cb(struct fp_dev *dev, void *data);
void fpi_ssm_jump_to_state(fpi_ssm *machine, int state);
void fpi_ssm_mark_completed(fpi_ssm *machine);
void fpi_ssm_mark_failed(fpi_ssm *machine, int error);
void *fpi_ssm_get_user_data(fpi_ssm *machine);
int fpi_ssm_get_error(fpi_ssm *machine);
int fpi_ssm_get_cur_state(fpi_ssm *machine);
#endif

View File

@@ -20,6 +20,7 @@
#define FP_COMPONENT "sync"
#include "fp_internal.h"
#include "fpi-dev.h"
#include <config.h>
#include <errno.h>
@@ -39,7 +40,7 @@ static void sync_open_cb(struct fp_dev *dev, int status, void *user_data)
/**
* fp_dev_open:
* @ddev: the discovered device to open
* @ddev: the struct #fp_dscv_dev discovered device to open
*
* Opens and initialises a device. This is the function you call in order
* to convert a #fp_dscv_dev discovered device into an actual device handle
@@ -81,9 +82,9 @@ static void sync_close_cb(struct fp_dev *dev, void *user_data)
/**
* fp_dev_close:
* @dev: the device to close. If %NULL, function simply returns.
* @dev: the struct #fp_dev device to close. If %NULL, function simply returns
*
* Close a device. You must call this function when you are finished using
* Closes a device. You must call this function when you have finished using
* a fingerprint device.
*/
API_EXPORTED void fp_dev_close(struct fp_dev *dev)
@@ -127,12 +128,12 @@ static void enroll_stop_cb(struct fp_dev *dev, void *user_data)
/**
* fp_enroll_finger_img:
* @dev: the device
* @dev: the struct #fp_dev device
* @print_data: a location to return the resultant enrollment data from
* the final stage. Must be freed with fp_print_data_free() after use.
* the final stage. Must be freed with fp_print_data_free() after use
* @img: location to store the scan image. accepts %NULL for no image
* storage. If an image is returned, it must be freed with fp_img_free() after
* use.
* use
*
* Performs an enroll stage. See [Enrolling](libfprint-Devices-operations.html#enrolling)
* for an explanation of enroll stages.
@@ -289,9 +290,9 @@ err:
/**
* fp_enroll_finger:
* @dev: the device
* @dev: the struct #fp_dev device
* @print_data: a location to return the resultant enrollment data from
* the final stage. Must be freed with fp_print_data_free() after use.
* the final stage. Must be freed with fp_print_data_free() after use
*
* Performs an enroll stage. See [Enrolling](libfprint-Devices-operations.html#enrolling)
* for an explanation of enroll stages. This function is just a shortcut to
@@ -330,14 +331,14 @@ static void verify_stop_cb(struct fp_dev *dev, void *user_data)
/**
* fp_verify_finger_img:
* @dev: the device to perform the scan.
* @dev: the struct #fp_dev device to perform the scan on
* @enrolled_print: the print to verify against. Must have been previously
* enrolled with a device compatible to the device selected to perform the scan.
* enrolled with a device compatible to the device selected to perform the scan
* @img: location to store the scan image. accepts %NULL for no image
* storage. If an image is returned, it must be freed with fp_img_free() after
* use.
* use
* Performs a new scan and verify it against a previously enrolled print.
* Performs a new scan and verifies it against a previously enrolled print.
* If the device is an imaging device, it can also return the image from
* the scan, even when the verify fails with a RETRY code. It is legal to
* call this function even on non-imaging devices, just don't expect them to
@@ -422,9 +423,9 @@ err:
/**
* fp_verify_finger:
* @dev: the device to perform the scan.
* @dev: the struct #fp_dev device to perform the scan on
* @enrolled_print: the print to verify against. Must have been previously
* enrolled with a device compatible to the device selected to perform the scan.
* enrolled with a device compatible to the device selected to perform the scan
*
* Performs a new scan and verify it against a previously enrolled print. This
* function is just a shortcut to calling fp_verify_finger_img() with a NULL
@@ -466,16 +467,16 @@ static void identify_stop_cb(struct fp_dev *dev, void *user_data)
/**
* fp_identify_finger_img:
* @dev: the device to perform the scan.
* @dev: the struct #fp_dev device to perform the scan on
* @print_gallery: NULL-terminated array of pointers to the prints to
* identify against. Each one must have been previously enrolled with a device
* compatible to the device selected to perform the scan.
* compatible to the device selected to perform the scan
* @match_offset: output location to store the array index of the matched
* gallery print (if any was found). Only valid if %FP_VERIFY_MATCH was
* returned.
* returned
* @img: location to store the scan image. accepts %NULL for no image
* storage. If an image is returned, it must be freed with fp_img_free() after
* use.
* use
* Performs a new scan and attempts to identify the scanned finger against
* a collection of previously enrolled fingerprints.
@@ -564,13 +565,13 @@ err:
/**
* fp_identify_finger:
* @dev: the device to perform the scan.
* @dev: the struct #fp_dev device to perform the scan on
* @print_gallery: %NULL-terminated array of pointers to the prints to
* identify against. Each one must have been previously enrolled with a device
* compatible to the device selected to perform the scan.
* compatible to the device selected to perform the scan
* @match_offset: output location to store the array index of the matched
* gallery print (if any was found). Only valid if %FP_VERIFY_MATCH was
* returned.
* returned
* Performs a new scan and attempts to identify the scanned finger against a
* collection of previously enrolled fingerprints. This function is just a
@@ -610,10 +611,10 @@ static void capture_stop_cb(struct fp_dev *dev, void *user_data)
}
/**
* fp_dev_img_capture:
* @dev: the device
* @dev: the struct #fp_dev device
* @unconditional: whether to unconditionally capture an image, or to only capture when a finger is detected
* @img: a location to return the captured image. Must be freed with
* fp_img_free() after use.
* fp_img_free() after use
*
* Captures a #fp_img from a device. The returned image is the raw
* image provided by the device, you may wish to [standardize](libfprint-Image-operations.html#img_std) it.
@@ -627,7 +628,7 @@ static void capture_stop_cb(struct fp_dev *dev, void *user_data)
*
* Returns: 0 on success, non-zero on error. -ENOTSUP indicates that either the
* @unconditional flag was set but the device does not support this, or that the
* device does not support imaging.
* device does not support imaging
*/
API_EXPORTED int fp_dev_img_capture(struct fp_dev *dev, int unconditional,
struct fp_img **img)

236
libfprint/fpi-usb.c Normal file
View File

@@ -0,0 +1,236 @@
/*
* Driver API definitions
* Copyright (C) 2018 Bastien Nocera <hadess@hadess.net>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "fpi-usb.h"
#include "drivers_api.h"
/**
* SECTION:fpi-usb
* @title: Helpers for libusb
* @short_description: libusb-related helpers
*
* A collection of [libusb helpers](http://libusb.sourceforge.net/api-1.0/group__poll.html#details)
* to make driver development easier. Please refer to the libusb API documentation for more
* information about the original API.
*/
/* Helpers from glib */
#include <glib.h>
#include <glib/gprintf.h>
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
/* special helpers to avoid gmessage.c dependency */
static void mem_error (const char *format, ...) G_GNUC_PRINTF (1,2);
#define mem_assert(cond) do { if (G_LIKELY (cond)) ; else mem_error ("assertion failed: %s", #cond); } while (0)
static void
mem_error (const char *format,
...)
{
const char *pname;
va_list args;
/* at least, put out "MEMORY-ERROR", in case we segfault during the rest of the function */
fputs ("\n***MEMORY-ERROR***: ", stderr);
pname = g_get_prgname();
g_fprintf (stderr, "%s[%ld]: ", pname ? pname : "", (long)getpid());
va_start (args, format);
g_vfprintf (stderr, format, args);
va_end (args);
fputs ("\n", stderr);
abort();
_exit (1);
}
struct fpi_usb_transfer {
struct libusb_transfer *transfer;
fpi_ssm *ssm;
struct fp_dev *dev;
fpi_usb_transfer_cb_fn callback;
void *user_data;
};
/**
* fpi_usb_alloc:
*
* Returns a struct libusb_transfer, similar to calling
* `libusb_alloc_transfer(0)`[[1](http://libusb.sourceforge.net/api-1.0/group__asyncio.html#ga13cc69ea40c702181c430c950121c000)]. As libfprint uses GLib internally,
* and [memory allocation failures will make applications fail](https://developer.gnome.org/glib/stable/glib-Memory-Allocation.html#glib-Memory-Allocation.description),
* this helper will assert when the libusb call fails.
*/
struct libusb_transfer *
fpi_usb_alloc(void)
{
struct libusb_transfer *transfer;
transfer = libusb_alloc_transfer(0);
mem_assert(transfer);
return transfer;
}
static fpi_usb_transfer *
fpi_usb_transfer_new(struct fp_dev *dev,
fpi_ssm *ssm,
fpi_usb_transfer_cb_fn callback,
void *user_data)
{
fpi_usb_transfer *transfer;
transfer = g_new0(fpi_usb_transfer, 1);
transfer->transfer = fpi_usb_alloc();
transfer->dev = dev;
transfer->ssm = ssm;
transfer->callback = callback;
transfer->user_data = user_data;
return transfer;
}
void
fpi_usb_transfer_free(fpi_usb_transfer *transfer)
{
if (transfer == NULL)
return;
g_free(transfer->transfer->buffer);
libusb_free_transfer(transfer->transfer);
g_free(transfer);
}
static void
fpi_usb_transfer_cb (struct libusb_transfer *transfer)
{
fpi_usb_transfer *t;
g_assert(transfer);
g_assert(transfer->user_data);
t = transfer->user_data;
BUG_ON(transfer->callback == NULL);
(t->callback) (transfer, t->dev, t->ssm, t->user_data);
fpi_usb_transfer_free(t);
}
/**
* fpi_usb_fill_bulk_transfer:
* @dev: a struct #fp_dev fingerprint device
* @ssm: the current #fpi_ssm state machine
* @endpoint: the USB end point
* @buffer: a buffer allocated with g_malloc() or another GLib function.
* Note that the returned #fpi_usb_transfer will own this buffer, so it
* should not be freed manually.
* @length: the size of @buffer
* @callback: the callback function that will be called once the fpi_usb_submit_transfer()
* call finishes.
* @user_data: a user data pointer to pass to the callback
* @timeout: timeout for the transfer in milliseconds, or 0 for no timeout
*
* This function is similar to calling [`libusb_alloc_transfer(0)`](http://libusb.sourceforge.net/api-1.0/group__asyncio.html#ga13cc69ea40c702181c430c950121c000)]
* followed by calling [`libusb_fill_bulk_transfer()`](http://libusb.sourceforge.net/api-1.0/group__asyncio.html#gad4ddb1a5c6c7fefc979a44d7300b95d7).
* The #fpi_usb_transfer_cb_fn callback will however provide more arguments
* relevant to libfprint drivers, making it a good replacement for the raw libusb
* calls.
*
* Returns: a #fpi_usb_transfer transfer struct, to be passed to
* fpi_usb_submit_transfer().
*/
fpi_usb_transfer *
fpi_usb_fill_bulk_transfer (struct fp_dev *dev,
fpi_ssm *ssm,
unsigned char endpoint,
unsigned char *buffer,
int length,
fpi_usb_transfer_cb_fn callback,
void *user_data,
unsigned int timeout)
{
fpi_usb_transfer *transfer;
g_return_val_if_fail (dev != NULL, NULL);
g_return_val_if_fail (callback != NULL, NULL);
transfer = fpi_usb_transfer_new(dev,
ssm,
callback,
user_data);
libusb_fill_bulk_transfer(transfer->transfer,
fpi_dev_get_usb_dev(dev),
endpoint,
buffer,
length,
fpi_usb_transfer_cb,
transfer,
timeout);
return transfer;
}
/**
* fpi_usb_submit_transfer:
* @transfer: a #fpi_usb_transfer struct
*
* Start a transfer to the device with the provided #fpi_usb_transfer.
* On error, the #fpi_usb_transfer struct will be freed, otherwise it will
* be freed once the callback provided to fpi_usb_fill_bulk_transfer() has
* been called.
*
* Returns: 0 on success, or the same errors as [libusb_submit_transfer](http://libusb.sourceforge.net/api-1.0/group__asyncio.html#gabb0932601f2c7dad2fee4b27962848ce)
* on failure.
*/
int
fpi_usb_submit_transfer(fpi_usb_transfer *transfer)
{
int r;
g_return_val_if_fail (transfer != NULL, LIBUSB_ERROR_INVALID_PARAM);
r = libusb_submit_transfer(transfer->transfer);
if (r < 0)
fpi_usb_transfer_free(transfer);
return r;
}
/**
* fpi_usb_cancel_transfer:
* @transfer: a #fpi_usb_transfer struct
*
* Cancel a transfer to the device with the provided #fpi_usb_transfer.
* Note that this will not complete the cancellation, as your transfer
* callback will be called with the `LIBUSB_TRANSFER_CANCELLED` status,
* as [libusb_cancel_transfer](http://libusb.sourceforge.net/api-1.0/group__asyncio.html#ga685eb7731f9a0593f75beb99727bbe54)
* would.
*
* You should not access anything but the given struct #libusb_transfer
* in the callback before checking whether `LIBUSB_TRANSFER_CANCELLED` has
* been called, as that might cause memory access violations.
*
* Returns: 0 on success, or the same errors as [libusb_cancel_transfer](http://libusb.sourceforge.net/api-1.0/group__asyncio.html#ga685eb7731f9a0593f75beb99727bbe54)
* on failure.
*/
int
fpi_usb_cancel_transfer(fpi_usb_transfer *transfer)
{
g_return_val_if_fail (transfer != NULL, LIBUSB_ERROR_NOT_FOUND);
return libusb_cancel_transfer(transfer->transfer);
}

70
libfprint/fpi-usb.h Normal file
View File

@@ -0,0 +1,70 @@
/*
* Copyright (C) 2018 Bastien Nocera <hadess@hadess.net>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __FPI_USB_H__
#define __FPI_USB_H__
#include <libusb.h>
#include "fpi-dev.h"
#include "fpi-ssm.h"
/**
* fpi_usb_transfer:
*
* A structure containing the arguments passed to fpi_usb_fill_bulk_transfer()
* to be used with fpi_usb_submit_transfer().
*/
typedef struct fpi_usb_transfer fpi_usb_transfer;
/**
* fpi_usb_transfer_cb_fn:
* @transfer: a struct #libusb_transfer
* @dev: the struct #fp_dev on which the operation was performed
* @ssm: the #fpi_ssm state machine
* @user_data: the user data passed to fpi_usb_fill_bulk_transfer()
*
* This callback will be called in response to a libusb bulk transfer
* triggered via fpi_usb_fill_bulk_transfer() finishing. Note that the
* struct #libusb_transfer does not need to be freed, as it will be
* freed after the callback returns, similarly to
* the [LIBUSB_TRANSFER_FREE_TRANSFER flag](http://libusb.sourceforge.net/api-1.0/group__asyncio.html#gga1fb47dd0f7c209b60a3609ff0c03d56dacf3f064997b283a14097c9f4d6f8ccc1).
*
* Note that the cancelled status of the transfer should be checked
* first thing, as the @dev, @ssm and @user_data pointers might not
* be pointing to valid values anymore. See fpi_usb_cancel_transfer()
* for more information.
*/
typedef void(*fpi_usb_transfer_cb_fn) (struct libusb_transfer *transfer,
struct fp_dev *dev,
fpi_ssm *ssm,
void *user_data);
struct libusb_transfer *fpi_usb_alloc(void) __attribute__((returns_nonnull));
fpi_usb_transfer *fpi_usb_fill_bulk_transfer (struct fp_dev *dev,
fpi_ssm *ssm,
unsigned char endpoint,
unsigned char *buffer,
int length,
fpi_usb_transfer_cb_fn callback,
void *user_data,
unsigned int timeout);
int fpi_usb_submit_transfer (fpi_usb_transfer *transfer);
int fpi_usb_cancel_transfer (fpi_usb_transfer *transfer);
#endif

View File

@@ -24,10 +24,6 @@
#include "fp_internal.h"
static const struct usb_id whitelist_id_table[] = {
/* Unsupported (for now) Elantech finger print readers */
{ .vendor = 0x04f3, .product = 0x0c03 },
{ .vendor = 0x04f3, .product = 0x0c16 },
{ .vendor = 0x04f3, .product = 0x0c26 },
/* Unsupported (for now) Validity Sensors finger print readers */
{ .vendor = 0x138a, .product = 0x0090 }, /* Found on e.g. Lenovo T460s */
{ .vendor = 0x138a, .product = 0x0091 },

View File

@@ -25,15 +25,24 @@ extern "C" {
#endif
#include <stdint.h>
#include <stddef.h>
#include <unistd.h>
#include <sys/time.h>
/**
* LIBFPRINT_DEPRECATED:
*
* Expands to the GNU C deprecated attribute if the compiler is `gcc`. When
* called with the `-Wdeprecated-declarations` option, `gcc` will generate warnings
* when deprecated interfaces are used.
*/
#define LIBFPRINT_DEPRECATED __attribute__((__deprecated__))
/**
* fp_dscv_dev:
*
* #fp_dscv_dev is an opaque structure type. You must access it using the
* functions below.
* functions in this section.
*/
struct fp_dscv_dev;
@@ -41,7 +50,7 @@ struct fp_dscv_dev;
* fp_dscv_print:
*
* #fp_dscv_print is an opaque structure type. You must access it using the
* functions below.
* functions in this section.
*/
struct fp_dscv_print;
@@ -49,7 +58,7 @@ struct fp_dscv_print;
* fp_dev:
*
* #fp_dev is an opaque structure type. You must access it using the
* functions below.
* functions in this section.
*/
struct fp_dev;
@@ -57,7 +66,7 @@ struct fp_dev;
* fp_driver:
*
* #fp_driver is an opaque structure type. You must access it using the
* functions below.
* functions in this section.
*/
struct fp_driver;
@@ -65,7 +74,7 @@ struct fp_driver;
* fp_print_data:
*
* #fp_print_data is an opaque structure type. You must access it using the
* functions below.
* functions in this section.
*/
struct fp_print_data;
@@ -73,7 +82,7 @@ struct fp_print_data;
* fp_img:
*
* #fp_img is an opaque structure type. You must access it using the
* functions below.
* functions in this section.
*/
struct fp_img;
@@ -128,6 +137,7 @@ const char *fp_driver_get_name(struct fp_driver *drv);
const char *fp_driver_get_full_name(struct fp_driver *drv);
uint16_t fp_driver_get_driver_id(struct fp_driver *drv);
enum fp_scan_type fp_driver_get_scan_type(struct fp_driver *drv);
int fp_driver_supports_imaging(struct fp_driver *drv);
/* Device discovery */
struct fp_dscv_dev **fp_discover_devs(void);
@@ -163,11 +173,10 @@ int fp_dev_supports_dscv_print(struct fp_dev *dev, struct fp_dscv_print *print)
/**
* fp_capture_result:
* Whether a capture failed or completed.
*
* @FP_CAPTURE_COMPLETE: Capture completed successfully, the capture data has been returned to the caller.
* @FP_CAPTURE_FAIL: Capture failed
*
* Whether a capture failed or completed.
*/
enum fp_capture_result {
FP_CAPTURE_COMPLETE = 0,
@@ -266,11 +275,13 @@ int fp_identify_finger(struct fp_dev *dev,
/* Data handling */
int fp_print_data_load(struct fp_dev *dev, enum fp_finger finger,
struct fp_print_data **data);
struct fp_print_data **data) LIBFPRINT_DEPRECATED;
int fp_print_data_from_dscv_print(struct fp_dscv_print *print,
struct fp_print_data **data) LIBFPRINT_DEPRECATED;
int fp_print_data_save(struct fp_print_data *data, enum fp_finger finger);
int fp_print_data_delete(struct fp_dev *dev, enum fp_finger finger);
int fp_print_data_save(struct fp_print_data *data, enum fp_finger finger)
LIBFPRINT_DEPRECATED;
int fp_print_data_delete(struct fp_dev *dev, enum fp_finger finger)
LIBFPRINT_DEPRECATED;
void fp_print_data_free(struct fp_print_data *data);
size_t fp_print_data_get_data(struct fp_print_data *data, unsigned char **ret);
struct fp_print_data *fp_print_data_from_data(unsigned char *buf,
@@ -284,7 +295,7 @@ uint32_t fp_print_data_get_devtype(struct fp_print_data *data);
* fp_minutia:
*
* #fp_minutia is an opaque structure type. You must access it using the
* functions below.
* functions in this section.
*/
struct fp_minutia;
@@ -295,6 +306,7 @@ int fp_img_save_to_file(struct fp_img *img, char *path);
void fp_img_standardize(struct fp_img *img);
struct fp_img *fp_img_binarize(struct fp_img *img);
struct fp_minutia **fp_img_get_minutiae(struct fp_img *img, int *nr_minutiae);
int fp_minutia_get_coords(struct fp_minutia *minutia, int *coord_x, int *coord_y);
void fp_img_free(struct fp_img *img);
/* Polling and timing */
@@ -304,12 +316,12 @@ void fp_img_free(struct fp_img *img);
* @fd: a file descriptor
* @events: Event flags to poll for from `<poll.h>`
*
* A structure representing a file descriptor and the events to poll
* A structure representing a file descriptor and the @events to poll
* for, as returned by fp_get_pollfds().
*/
struct fp_pollfd {
int fd;
short events;
short int events;
};
int fp_handle_events_timeout(struct timeval *timeout);
@@ -326,7 +338,7 @@ int fp_get_next_timeout(struct timeval *tv);
* event source is added. The @events argument is a flag as defined in
* `<poll.h>` such as `POLLIN`, or `POLLOUT`. See fp_set_pollfd_notifiers().
*/
typedef void (*fp_pollfd_added_cb)(int fd, short events);
typedef void (*fp_pollfd_added_cb)(int fd, short int events);
/**
* fp_pollfd_removed_cb:
@@ -348,7 +360,7 @@ void fp_set_debug(int level) LIBFPRINT_DEPRECATED;
/**
* fp_operation_stop_cb:
* @dev: the #fp_dev device
* @dev: the struct #fp_dev device
* @user_data: user data passed to the callback
*
* Type definition for a function that will be called when fp_async_dev_close(),
@@ -359,7 +371,7 @@ typedef void (*fp_operation_stop_cb)(struct fp_dev *dev, void *user_data);
/**
* fp_img_operation_cb:
* @dev: the #fp_dev device
* @dev: the struct #fp_dev device
* @result: an #fp_verify_result for fp_async_verify_start(), or an #fp_capture_result
* for fp_async_capture_start(), or a negative value on error
* @img: the captured #fp_img if capture or verification was successful
@@ -373,7 +385,7 @@ typedef void (*fp_img_operation_cb)(struct fp_dev *dev, int result,
/**
* fp_dev_open_cb:
* @dev: the #fp_dev device
* @dev: the struct #fp_dev device
* @status: 0 on success, or a negative value on error
* @user_data: user data passed to the callback
*
@@ -390,14 +402,15 @@ void fp_async_dev_close(struct fp_dev *dev, fp_operation_stop_cb callback,
/**
* fp_enroll_stage_cb:
* @dev: the #fp_dev device
* @dev: the struct #fp_dev device
* @result: a #fp_enroll_result on success, or a negative value on failure
* @print: the enrollment data from the final stage
* @img: an #fp_img to free with fp_img_free()
* @user_data: user data passed to the callback
*
* Type definition for a function that will be called when
* fp_async_enroll_start() finishes.
* fp_async_enroll_start() finishes. See fp_enroll_finger_img() for
* the expected behaviour of your program based on the @result.
*/
typedef void (*fp_enroll_stage_cb)(struct fp_dev *dev, int result,
struct fp_print_data *print, struct fp_img *img, void *user_data);
@@ -416,7 +429,7 @@ int fp_async_verify_stop(struct fp_dev *dev, fp_operation_stop_cb callback,
/**
* fp_identify_cb:
* @dev: the #fp_dev device
* @dev: the struct #fp_dev device
* @result: a #fp_verify_result on success, or a negative value on error.
* @match_offset: the array index of the matched gallery print (if any was found).
* Only valid if %FP_VERIFY_MATCH was returned.

View File

@@ -1,27 +1,18 @@
libfprint_sources = [
'fp_internal.h',
'drivers_api.h',
'async.c',
'core.c',
'data.c',
'drv.c',
'img.c',
'imgdev.c',
'poll.c',
'sync.c',
'assembling.c',
'assembling.h',
'drivers/driver_ids.h',
'fpi-async.c',
'fpi-assembling.c',
'fpi-core.c',
'fpi-data.c',
'fpi-dev.c',
'fpi-dev-img.c',
'fpi-img.c',
'fpi-ssm.c',
'fpi-sync.c',
'fpi-poll.c',
'fpi-usb.c',
]
nbis_sources = [
'nbis/include/bozorth.h',
'nbis/include/bz_array.h',
'nbis/include/defs.h',
'nbis/include/lfs.h',
'nbis/include/log.h',
'nbis/include/morph.h',
'nbis/include/sunrast.h',
'nbis/bozorth3/bozorth3.c',
'nbis/bozorth3/bz_alloc.c',
'nbis/bozorth3/bz_drvrs.c',
@@ -30,14 +21,17 @@ nbis_sources = [
'nbis/bozorth3/bz_sort.c',
'nbis/mindtct/binar.c',
'nbis/mindtct/block.c',
'nbis/mindtct/chaincod.c',
'nbis/mindtct/contour.c',
'nbis/mindtct/detect.c',
'nbis/mindtct/dft.c',
'nbis/mindtct/free.c',
'nbis/mindtct/getmin.c',
'nbis/mindtct/globals.c',
'nbis/mindtct/imgutil.c',
'nbis/mindtct/init.c',
'nbis/mindtct/line.c',
'nbis/mindtct/link.c',
'nbis/mindtct/log.c',
'nbis/mindtct/loop.c',
'nbis/mindtct/maps.c',
@@ -50,6 +44,7 @@ nbis_sources = [
'nbis/mindtct/shape.c',
'nbis/mindtct/sort.c',
'nbis/mindtct/util.c',
'nbis/mindtct/xytreps.c',
]
aeslib = false
@@ -59,13 +54,13 @@ drivers_sources = []
drivers_cflags = []
foreach driver: drivers
if driver == 'upekts'
drivers_sources += [ 'drivers/upekts.c' ]
drivers_sources += [ 'drivers/upekts.c', 'drivers/upek_proto.c' ]
endif
if driver == 'upektc'
drivers_sources += [ 'drivers/upektc.c', 'drivers/upektc.h' ]
drivers_sources += [ 'drivers/upektc.c' ]
endif
if driver == 'upeksonly'
drivers_sources += [ 'drivers/upeksonly.c', 'drivers/upeksonly.h' ]
drivers_sources += [ 'drivers/upeksonly.c' ]
endif
if driver == 'uru4000'
drivers_sources += [ 'drivers/uru4000.c' ]
@@ -75,20 +70,20 @@ foreach driver: drivers
aeslib = true
endif
if driver == 'aes1660'
drivers_sources += [ 'drivers/aes1660.c', 'drivers/aes1660.h' ]
drivers_sources += [ 'drivers/aes1660.c' ]
aeslib = true
aesx660 = true
endif
if driver == 'aes2501'
drivers_sources += [ 'drivers/aes2501.c', 'drivers/aes2501.h' ]
drivers_sources += [ 'drivers/aes2501.c' ]
aeslib = true
endif
if driver == 'aes2550'
drivers_sources += [ 'drivers/aes2550.c', 'drivers/aes2550.h' ]
drivers_sources += [ 'drivers/aes2550.c' ]
aeslib = true
endif
if driver == 'aes2660'
drivers_sources += [ 'drivers/aes2660.c', 'drivers/aes2660.h' ]
drivers_sources += [ 'drivers/aes2660.c' ]
aeslib = true
aesx660 = true
endif
@@ -102,9 +97,6 @@ foreach driver: drivers
aeslib = true
aes3k = true
endif
if driver == 'fdu2000'
drivers_sources += [ 'drivers/fdu2000.c' ]
endif
if driver == 'vcom5s'
drivers_sources += [ 'drivers/vcom5s.c' ]
endif
@@ -112,38 +104,38 @@ foreach driver: drivers
drivers_sources += [ 'drivers/vfs101.c' ]
endif
if driver == 'vfs301'
drivers_sources += [ 'drivers/vfs301.c', 'drivers/vfs301_proto.c', 'drivers/vfs301_proto.h', 'drivers/vfs301_proto_fragments.h' ]
drivers_sources += [ 'drivers/vfs301.c', 'drivers/vfs301_proto.c' ]
endif
if driver == 'vfs5011'
drivers_sources += [ 'drivers/vfs5011.c', 'drivers/vfs5011_proto.h' ]
drivers_sources += [ 'drivers/vfs5011.c' ]
endif
if driver == 'upektc_img'
drivers_sources += [ 'drivers/upektc_img.c', 'drivers/upektc_img.h' ]
drivers_sources += [ 'drivers/upektc_img.c', 'drivers/upek_proto.c' ]
endif
if driver == 'etes603'
drivers_sources += [ 'drivers/etes603.c' ]
endif
if driver == 'vfs0050'
drivers_sources += [ 'drivers/vfs0050.c', 'drivers/vfs0050.h' ]
drivers_sources += [ 'drivers/vfs0050.c' ]
endif
if driver == 'elan'
drivers_sources += [ 'drivers/elan.c', 'drivers/elan.h' ]
drivers_sources += [ 'drivers/elan.c' ]
endif
endforeach
if aeslib
drivers_sources += [ 'aeslib.c', 'aeslib.h' ]
drivers_sources += [ 'drivers/aeslib.c' ]
endif
if aesx660
drivers_sources += ['drivers/aesx660.c', 'drivers/aesx660.h' ]
drivers_sources += ['drivers/aesx660.c' ]
endif
if aes3k
drivers_sources += ['drivers/aes3k.c', 'drivers/aes3k.h' ]
drivers_sources += ['drivers/aes3k.c' ]
endif
other_sources = []
if imaging_dep.found()
other_sources += [ 'pixman.c' ]
other_sources += [ 'fpi-img-pixman.c' ]
endif
libfprint_sources += configure_file(input: 'empty_file',

33
libfprint/nbis-helpers.h Normal file
View File

@@ -0,0 +1,33 @@
/*
* Helpers to use within the NBIS copy/paste library
* Copyright (C) 2018 Bastien Nocera <hadess@hadess.net>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <glib.h>
#define ASSERT_SIZE_MUL(a,b) \
{ \
gsize dest; \
g_assert(g_size_checked_mul(&dest, a, b)); \
}
#define ASSERT_INT_MUL(a, b) \
{ \
gsize dest; \
g_assert(g_size_checked_mul(&dest, a, b)); \
g_assert(dest < G_MAXINT); \
}

View File

@@ -1,51 +1,43 @@
/******************************************************************************
This file is part of the Export Control subset of the United States NIST
Biometric Image Software (NBIS) distribution:
http://fingerprint.nist.gov/NBIS/index.html
It is our understanding that this falls within ECCN 3D980, which covers
software associated with the development, production or use of certain
equipment controlled in accordance with U.S. concerns about crime control
practices in specific countries.
Therefore, this file should not be exported, or made available on fileservers,
except as allowed by U.S. export control laws.
Do not remove this notice.
******************************************************************************/
/* NOTE: Despite the above notice (which I have not removed), this file is
* being legally distributed within libfprint; the U.S. Export Administration
* Regulations do not place export restrictions upon distribution of
* "publicly available technology and software", as stated in EAR section
* 734.3(b)(3)(i). libfprint qualifies as publicly available technology as per
* the definition in section 734.7(a)(1).
*
* For further information, see https://fprint.freedesktop.org/us-export-control.html
*/
/*******************************************************************************
License:
This software was developed at the National Institute of Standards and
Technology (NIST) by employees of the Federal Government in the course
of their official duties. Pursuant to title 17 Section 105 of the
United States Code, this software is not subject to copyright protection
and is in the public domain. NIST assumes no responsibility whatsoever for
its use by other parties, and makes no guarantees, expressed or implied,
about its quality, reliability, or any other characteristic.
License:
This software and/or related materials was developed at the National Institute
of Standards and Technology (NIST) by employees of the Federal Government
in the course of their official duties. Pursuant to title 17 Section 105
of the United States Code, this software is not subject to copyright
protection and is in the public domain.
Disclaimer:
This software was developed to promote biometric standards and biometric
technology testing for the Federal Government in accordance with the USA
PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act.
Specific hardware and software products identified in this software were used
in order to perform the software development. In no case does such
identification imply recommendation or endorsement by the National Institute
of Standards and Technology, nor does it imply that the products and equipment
identified are necessarily the best available for the purpose.
This software and/or related materials have been determined to be not subject
to the EAR (see Part 734.3 of the EAR for exact details) because it is
a publicly available technology and software, and is freely distributed
to any interested party with no licensing requirements. Therefore, it is
permissible to distribute this software as a free download from the internet.
Disclaimer:
This software and/or related materials was developed to promote biometric
standards and biometric technology testing for the Federal Government
in accordance with the USA PATRIOT Act and the Enhanced Border Security
and Visa Entry Reform Act. Specific hardware and software products identified
in this software were used in order to perform the software development.
In no case does such identification imply recommendation or endorsement
by the National Institute of Standards and Technology, nor does it imply that
the products and equipment identified are necessarily the best available
for the purpose.
This software and/or related materials are provided "AS-IS" without warranty
of any kind including NO WARRANTY OF PERFORMANCE, MERCHANTABILITY,
NO WARRANTY OF NON-INFRINGEMENT OF ANY 3RD PARTY INTELLECTUAL PROPERTY
or FITNESS FOR A PARTICULAR PURPOSE or for any purpose whatsoever, for the
licensed product, however used. In no event shall NIST be liable for any
damages and/or costs, including but not limited to incidental or consequential
damages of any kind, including economic damage or injury to property and lost
profits, regardless of whether NIST shall be advised, have reason to know,
or in fact shall know of the possibility.
By using this software, you agree to bear all risk relating to quality,
use and performance of the software and/or related materials. You agree
to hold the Government harmless from any claim arising from your use
of the software.
*******************************************************************************/
@@ -89,9 +81,6 @@ identified are necessarily the best available for the purpose.
#include <stdio.h>
#include <bozorth.h>
static const int verbose_bozorth = 0;
static const int m1_xyt = 0;
/***********************************************************************/
void bz_comp(
int npoints, /* INPUT: # of points */
@@ -160,7 +149,7 @@ for ( k = 0; k < npoints - 1; k++ ) {
else {
double dz;
if ( m1_xyt )
if ( 0 )
dz = ( 180.0F / PI_SINGLE ) * atanf( (float) -dy / (float) dx );
else
dz = ( 180.0F / PI_SINGLE ) * atanf( (float) dy / (float) dx );
@@ -261,7 +250,7 @@ for ( k = 0; k < npoints - 1; k++ ) {
if ( table_index == 19999 ) {
#ifndef NOVERBOSE
if ( verbose_bozorth )
if ( 0 )
printf( "bz_comp(): breaking loop to avoid table overflow\n" );
#endif
goto COMP_END;
@@ -392,7 +381,7 @@ static int * rtp[ ROT_SIZE_1 ];
/* extern int * scolpt[ SCOLPT_SIZE ]; INPUT */
/* extern int * fcolpt[ FCOLPT_SIZE ]; INPUT */
/* extern int colp[ COLP_SIZE_1 ][ COLP_SIZE_2 ]; OUTPUT */
/* extern int verbose_bozorth; */
/* extern int 0; */
/* extern FILE * stderr; */
/* extern char * get_progname( void ); */
/* extern char * get_probe_filename( void ); */
@@ -401,6 +390,7 @@ static int * rtp[ ROT_SIZE_1 ];
st = 1;
edge_pair_index = 0;
rotptr = &rot[0][0];
@@ -570,7 +560,7 @@ for ( k = 1; k < probe_ptrlist_len; k++ ) {
if ( edge_pair_index == 19999 ) {
#ifndef NOVERBOSE
if ( verbose_bozorth )
if ( 0 )
fprintf( stderr, "%s: bz_match(): WARNING: list is full, breaking loop early [p=%s; g=%s]\n",
get_progname(), get_probe_filename(), get_gallery_filename() );
#endif
@@ -652,13 +642,13 @@ int avv[ AVV_SIZE_1 ][ AVV_SIZE_2 ];
if ( pstruct->nrows < MIN_COMPUTABLE_BOZORTH_MINUTIAE ) {
#ifndef NOVERBOSE
if ( gstruct->nrows < MIN_COMPUTABLE_BOZORTH_MINUTIAE ) {
if ( verbose_bozorth )
if ( 0 )
fprintf( stderr, "%s: bz_match_score(): both probe and gallery file have too few minutiae (%d,%d) to compute a real Bozorth match score; min. is %d [p=%s; g=%s]\n",
get_progname(),
pstruct->nrows, gstruct->nrows, MIN_COMPUTABLE_BOZORTH_MINUTIAE,
get_probe_filename(), get_gallery_filename() );
} else {
if ( verbose_bozorth )
if ( 0 )
fprintf( stderr, "%s: bz_match_score(): probe file has too few minutiae (%d) to compute a real Bozorth match score; min. is %d [p=%s; g=%s]\n",
get_progname(),
pstruct->nrows, MIN_COMPUTABLE_BOZORTH_MINUTIAE,
@@ -672,7 +662,7 @@ if ( pstruct->nrows < MIN_COMPUTABLE_BOZORTH_MINUTIAE ) {
if ( gstruct->nrows < MIN_COMPUTABLE_BOZORTH_MINUTIAE ) {
#ifndef NOVERBOSE
if ( verbose_bozorth )
if ( 0 )
fprintf( stderr, "%s: bz_match_score(): gallery file has too few minutiae (%d) to compute a real Bozorth match score; min. is %d [p=%s; g=%s]\n",
get_progname(),
gstruct->nrows, MIN_COMPUTABLE_BOZORTH_MINUTIAE,
@@ -711,7 +701,6 @@ tp = 0;
p1 = 0;
tot = 0;
ftt = 0;
kx = 0;
match_score = 0;
for ( k = 0; k < np - 1; k++ ) {
@@ -765,7 +754,7 @@ for ( k = 0; k < np - 1; k++ ) {
}
#ifndef NOVERBOSE
if ( verbose_bozorth )
if ( 0 )
printf( "x1 %d %d %d %d %d %d\n", kx, colp[kx][0], colp[kx][1], colp[kx][2], colp[kx][3], colp[kx][4] );
#endif
@@ -827,7 +816,6 @@ for ( k = 0; k < np - 1; k++ ) {
l = 1;
t = np + 1;
b = kq;
@@ -1167,7 +1155,7 @@ for ( k = 0; k < np - 1; k++ ) {
if ( ll ) {
if ( m1_xyt )
if ( 0 )
fi = ( 180.0F / PI_SINGLE ) * atanf( (float) -jj / (float) ll );
else
fi = ( 180.0F / PI_SINGLE ) * atanf( (float) jj / (float) ll );
@@ -1187,7 +1175,7 @@ for ( k = 0; k < np - 1; k++ ) {
jj += 360;
} else {
if ( m1_xyt ) {
if ( 0 ) {
if ( jj > 0 )
jj = -90;
else
@@ -1204,7 +1192,7 @@ for ( k = 0; k < np - 1; k++ ) {
if ( kk ) {
if ( m1_xyt )
if ( 0 )
fi = ( 180.0F / PI_SINGLE ) * atanf( (float) -j / (float) kk );
else
fi = ( 180.0F / PI_SINGLE ) * atanf( (float) j / (float) kk );
@@ -1224,7 +1212,7 @@ for ( k = 0; k < np - 1; k++ ) {
j += 360;
} else {
if ( m1_xyt ) {
if ( 0 ) {
if ( j > 0 )
j = -90;
else
@@ -1611,7 +1599,7 @@ if ( n ) {
notfound = 1;
#ifndef NOVERBOSE
if ( verbose_bozorth ) {
if ( 0 ) {
int * llptr = lptr;
printf( "bz_sift(): n: looking for l=%d in [", l );
for ( i = 0; i < lim; i++ ) {
@@ -1657,7 +1645,7 @@ if ( t ) {
notfound = 1;
#ifndef NOVERBOSE
if ( verbose_bozorth ) {
if ( 0 ) {
int * llptr = lptr;
printf( "bz_sift(): t: looking for kz=%d in [", kz );
for ( i = 0; i < lim; i++ ) {

View File

@@ -1,51 +1,43 @@
/******************************************************************************
This file is part of the Export Control subset of the United States NIST
Biometric Image Software (NBIS) distribution:
http://fingerprint.nist.gov/NBIS/index.html
It is our understanding that this falls within ECCN 3D980, which covers
software associated with the development, production or use of certain
equipment controlled in accordance with U.S. concerns about crime control
practices in specific countries.
Therefore, this file should not be exported, or made available on fileservers,
except as allowed by U.S. export control laws.
Do not remove this notice.
******************************************************************************/
/* NOTE: Despite the above notice (which I have not removed), this file is
* being legally distributed within libfprint; the U.S. Export Administration
* Regulations do not place export restrictions upon distribution of
* "publicly available technology and software", as stated in EAR section
* 734.3(b)(3)(i). libfprint qualifies as publicly available technology as per
* the definition in section 734.7(a)(1).
*
* For further information, see https://fprint.freedesktop.org/us-export-control.html
*/
/*******************************************************************************
License:
This software was developed at the National Institute of Standards and
Technology (NIST) by employees of the Federal Government in the course
of their official duties. Pursuant to title 17 Section 105 of the
United States Code, this software is not subject to copyright protection
and is in the public domain. NIST assumes no responsibility whatsoever for
its use by other parties, and makes no guarantees, expressed or implied,
about its quality, reliability, or any other characteristic.
License:
This software and/or related materials was developed at the National Institute
of Standards and Technology (NIST) by employees of the Federal Government
in the course of their official duties. Pursuant to title 17 Section 105
of the United States Code, this software is not subject to copyright
protection and is in the public domain.
Disclaimer:
This software was developed to promote biometric standards and biometric
technology testing for the Federal Government in accordance with the USA
PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act.
Specific hardware and software products identified in this software were used
in order to perform the software development. In no case does such
identification imply recommendation or endorsement by the National Institute
of Standards and Technology, nor does it imply that the products and equipment
identified are necessarily the best available for the purpose.
This software and/or related materials have been determined to be not subject
to the EAR (see Part 734.3 of the EAR for exact details) because it is
a publicly available technology and software, and is freely distributed
to any interested party with no licensing requirements. Therefore, it is
permissible to distribute this software as a free download from the internet.
Disclaimer:
This software and/or related materials was developed to promote biometric
standards and biometric technology testing for the Federal Government
in accordance with the USA PATRIOT Act and the Enhanced Border Security
and Visa Entry Reform Act. Specific hardware and software products identified
in this software were used in order to perform the software development.
In no case does such identification imply recommendation or endorsement
by the National Institute of Standards and Technology, nor does it imply that
the products and equipment identified are necessarily the best available
for the purpose.
This software and/or related materials are provided "AS-IS" without warranty
of any kind including NO WARRANTY OF PERFORMANCE, MERCHANTABILITY,
NO WARRANTY OF NON-INFRINGEMENT OF ANY 3RD PARTY INTELLECTUAL PROPERTY
or FITNESS FOR A PARTICULAR PURPOSE or for any purpose whatsoever, for the
licensed product, however used. In no event shall NIST be liable for any
damages and/or costs, including but not limited to incidental or consequential
damages of any kind, including economic damage or injury to property and lost
profits, regardless of whether NIST shall be advised, have reason to know,
or in fact shall know of the possibility.
By using this software, you agree to bear all risk relating to quality,
use and performance of the software and/or related materials. You agree
to hold the Government harmless from any claim arising from your use
of the software.
*******************************************************************************/
@@ -77,43 +69,6 @@ identified are necessarily the best available for the purpose.
/***********************************************************************/
char * malloc_or_exit( int nbytes, const char * what )
{
char * p;
/* These are now externally defined in bozorth.h */
/* extern FILE * stderr; */
/* extern char * get_progname( void ); */
p = malloc( (size_t) nbytes );
if ( p == CNULL ) {
fprintf( stderr, "%s: ERROR: malloc() of %d bytes for %s failed: %s\n",
get_progname(),
nbytes,
what,
strerror( errno )
);
exit(1);
}
return p;
}
/***********************************************************************/
/* returns CNULL on error */
char * malloc_or_return_error( int nbytes, const char * what )
{
char * p;
p = malloc( (size_t) nbytes );
if ( p == CNULL ) {
fprintf( stderr, "%s: ERROR: malloc() of %d bytes for %s failed: %s\n",
get_progname(),
nbytes,
what,
strerror( errno )
);
return(CNULL);
}
return p;
}

View File

@@ -1,51 +1,43 @@
/******************************************************************************
This file is part of the Export Control subset of the United States NIST
Biometric Image Software (NBIS) distribution:
http://fingerprint.nist.gov/NBIS/index.html
It is our understanding that this falls within ECCN 3D980, which covers
software associated with the development, production or use of certain
equipment controlled in accordance with U.S. concerns about crime control
practices in specific countries.
Therefore, this file should not be exported, or made available on fileservers,
except as allowed by U.S. export control laws.
Do not remove this notice.
******************************************************************************/
/* NOTE: Despite the above notice (which I have not removed), this file is
* being legally distributed within libfprint; the U.S. Export Administration
* Regulations do not place export restrictions upon distribution of
* "publicly available technology and software", as stated in EAR section
* 734.3(b)(3)(i). libfprint qualifies as publicly available technology as per
* the definition in section 734.7(a)(1).
*
* For further information, see https://fprint.freedesktop.org/us-export-control.html
*/
/*******************************************************************************
License:
This software was developed at the National Institute of Standards and
Technology (NIST) by employees of the Federal Government in the course
of their official duties. Pursuant to title 17 Section 105 of the
United States Code, this software is not subject to copyright protection
and is in the public domain. NIST assumes no responsibility whatsoever for
its use by other parties, and makes no guarantees, expressed or implied,
about its quality, reliability, or any other characteristic.
License:
This software and/or related materials was developed at the National Institute
of Standards and Technology (NIST) by employees of the Federal Government
in the course of their official duties. Pursuant to title 17 Section 105
of the United States Code, this software is not subject to copyright
protection and is in the public domain.
Disclaimer:
This software was developed to promote biometric standards and biometric
technology testing for the Federal Government in accordance with the USA
PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act.
Specific hardware and software products identified in this software were used
in order to perform the software development. In no case does such
identification imply recommendation or endorsement by the National Institute
of Standards and Technology, nor does it imply that the products and equipment
identified are necessarily the best available for the purpose.
This software and/or related materials have been determined to be not subject
to the EAR (see Part 734.3 of the EAR for exact details) because it is
a publicly available technology and software, and is freely distributed
to any interested party with no licensing requirements. Therefore, it is
permissible to distribute this software as a free download from the internet.
Disclaimer:
This software and/or related materials was developed to promote biometric
standards and biometric technology testing for the Federal Government
in accordance with the USA PATRIOT Act and the Enhanced Border Security
and Visa Entry Reform Act. Specific hardware and software products identified
in this software were used in order to perform the software development.
In no case does such identification imply recommendation or endorsement
by the National Institute of Standards and Technology, nor does it imply that
the products and equipment identified are necessarily the best available
for the purpose.
This software and/or related materials are provided "AS-IS" without warranty
of any kind including NO WARRANTY OF PERFORMANCE, MERCHANTABILITY,
NO WARRANTY OF NON-INFRINGEMENT OF ANY 3RD PARTY INTELLECTUAL PROPERTY
or FITNESS FOR A PARTICULAR PURPOSE or for any purpose whatsoever, for the
licensed product, however used. In no event shall NIST be liable for any
damages and/or costs, including but not limited to incidental or consequential
damages of any kind, including economic damage or injury to property and lost
profits, regardless of whether NIST shall be advised, have reason to know,
or in fact shall know of the possibility.
By using this software, you agree to bear all risk relating to quality,
use and performance of the software and/or related materials. You agree
to hold the Government harmless from any claim arising from your use
of the software.
*******************************************************************************/
@@ -177,47 +169,3 @@ return bz_match_score( np, pstruct, gstruct );
/**************************************************************************/
int bozorth_main(
struct xyt_struct * pstruct,
struct xyt_struct * gstruct
)
{
int ms;
int np;
int probe_len;
int gallery_len;
#ifdef DEBUG
printf( "PROBE_INIT() called\n" );
#endif
probe_len = bozorth_probe_init( pstruct );
#ifdef DEBUG
printf( "GALLERY_INIT() called\n" );
#endif
gallery_len = bozorth_gallery_init( gstruct );
#ifdef DEBUG
printf( "BZ_MATCH() called\n" );
#endif
np = bz_match( probe_len, gallery_len );
#ifdef DEBUG
printf( "BZ_MATCH() returned %d edge pairs\n", np );
printf( "COMPUTE() called\n" );
#endif
ms = bz_match_score( np, pstruct, gstruct );
#ifdef DEBUG
printf( "COMPUTE() returned %d\n", ms );
#endif
return ms;
}

View File

@@ -1,51 +1,43 @@
/******************************************************************************
This file is part of the Export Control subset of the United States NIST
Biometric Image Software (NBIS) distribution:
http://fingerprint.nist.gov/NBIS/index.html
It is our understanding that this falls within ECCN 3D980, which covers
software associated with the development, production or use of certain
equipment controlled in accordance with U.S. concerns about crime control
practices in specific countries.
Therefore, this file should not be exported, or made available on fileservers,
except as allowed by U.S. export control laws.
Do not remove this notice.
******************************************************************************/
/* NOTE: Despite the above notice (which I have not removed), this file is
* being legally distributed within libfprint; the U.S. Export Administration
* Regulations do not place export restrictions upon distribution of
* "publicly available technology and software", as stated in EAR section
* 734.3(b)(3)(i). libfprint qualifies as publicly available technology as per
* the definition in section 734.7(a)(1).
*
* For further information, see https://fprint.freedesktop.org/us-export-control.html
*/
/*******************************************************************************
License:
This software was developed at the National Institute of Standards and
Technology (NIST) by employees of the Federal Government in the course
of their official duties. Pursuant to title 17 Section 105 of the
United States Code, this software is not subject to copyright protection
and is in the public domain. NIST assumes no responsibility whatsoever for
its use by other parties, and makes no guarantees, expressed or implied,
about its quality, reliability, or any other characteristic.
License:
This software and/or related materials was developed at the National Institute
of Standards and Technology (NIST) by employees of the Federal Government
in the course of their official duties. Pursuant to title 17 Section 105
of the United States Code, this software is not subject to copyright
protection and is in the public domain.
Disclaimer:
This software was developed to promote biometric standards and biometric
technology testing for the Federal Government in accordance with the USA
PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act.
Specific hardware and software products identified in this software were used
in order to perform the software development. In no case does such
identification imply recommendation or endorsement by the National Institute
of Standards and Technology, nor does it imply that the products and equipment
identified are necessarily the best available for the purpose.
This software and/or related materials have been determined to be not subject
to the EAR (see Part 734.3 of the EAR for exact details) because it is
a publicly available technology and software, and is freely distributed
to any interested party with no licensing requirements. Therefore, it is
permissible to distribute this software as a free download from the internet.
Disclaimer:
This software and/or related materials was developed to promote biometric
standards and biometric technology testing for the Federal Government
in accordance with the USA PATRIOT Act and the Enhanced Border Security
and Visa Entry Reform Act. Specific hardware and software products identified
in this software were used in order to perform the software development.
In no case does such identification imply recommendation or endorsement
by the National Institute of Standards and Technology, nor does it imply that
the products and equipment identified are necessarily the best available
for the purpose.
This software and/or related materials are provided "AS-IS" without warranty
of any kind including NO WARRANTY OF PERFORMANCE, MERCHANTABILITY,
NO WARRANTY OF NON-INFRINGEMENT OF ANY 3RD PARTY INTELLECTUAL PROPERTY
or FITNESS FOR A PARTICULAR PURPOSE or for any purpose whatsoever, for the
licensed product, however used. In no event shall NIST be liable for any
damages and/or costs, including but not limited to incidental or consequential
damages of any kind, including economic damage or injury to property and lost
profits, regardless of whether NIST shall be advised, have reason to know,
or in fact shall know of the possibility.
By using this software, you agree to bear all risk relating to quality,
use and performance of the software and/or related materials. You agree
to hold the Government harmless from any claim arising from your use
of the software.
*******************************************************************************/
@@ -91,23 +83,45 @@ int yl[ YL_SIZE_1 ][ YL_SIZE_2 ];
/**************************************************************************/
/* Globals used significantly by sift() */
/**************************************************************************/
int rq[ RQ_SIZE ] = {};
int tq[ TQ_SIZE ] = {};
int zz[ ZZ_SIZE ] = {};
#ifdef TARGET_OS
int rq[ RQ_SIZE ];
int tq[ TQ_SIZE ];
int zz[ ZZ_SIZE ];
int rx[ RX_SIZE ] = {};
int mm[ MM_SIZE ] = {};
int nn[ NN_SIZE ] = {};
int rx[ RX_SIZE ];
int mm[ MM_SIZE ];
int nn[ NN_SIZE ];
int qq[ QQ_SIZE ] = {};
int qq[ QQ_SIZE ];
int rk[ RK_SIZE ] = {};
int rk[ RK_SIZE ];
int cp[ CP_SIZE ] = {};
int rp[ RP_SIZE ] = {};
int cp[ CP_SIZE ];
int rp[ RP_SIZE ];
int rf[RF_SIZE_1][RF_SIZE_2] = {};
int cf[CF_SIZE_1][CF_SIZE_2] = {};
int rf[RF_SIZE_1][RF_SIZE_2];
int cf[CF_SIZE_1][CF_SIZE_2];
int y[20000] = {};
int y[20000];
#else
int rq[ RQ_SIZE ] = {};
int tq[ TQ_SIZE ] = {};
int zz[ ZZ_SIZE ] = {};
int rx[ RX_SIZE ] = {};
int mm[ MM_SIZE ] = {};
int nn[ NN_SIZE ] = {};
int qq[ QQ_SIZE ] = {};
int rk[ RK_SIZE ] = {};
int cp[ CP_SIZE ] = {};
int rp[ RP_SIZE ] = {};
int rf[RF_SIZE_1][RF_SIZE_2] = {};
int cf[CF_SIZE_1][CF_SIZE_2] = {};
int y[20000] = {};
#endif

View File

@@ -1,51 +1,43 @@
/******************************************************************************
This file is part of the Export Control subset of the United States NIST
Biometric Image Software (NBIS) distribution:
http://fingerprint.nist.gov/NBIS/index.html
It is our understanding that this falls within ECCN 3D980, which covers
software associated with the development, production or use of certain
equipment controlled in accordance with U.S. concerns about crime control
practices in specific countries.
Therefore, this file should not be exported, or made available on fileservers,
except as allowed by U.S. export control laws.
Do not remove this notice.
******************************************************************************/
/* NOTE: Despite the above notice (which I have not removed), this file is
* being legally distributed within libfprint; the U.S. Export Administration
* Regulations do not place export restrictions upon distribution of
* "publicly available technology and software", as stated in EAR section
* 734.3(b)(3)(i). libfprint qualifies as publicly available technology as per
* the definition in section 734.7(a)(1).
*
* For further information, see https://fprint.freedesktop.org/us-export-control.html
*/
/*******************************************************************************
License:
This software was developed at the National Institute of Standards and
Technology (NIST) by employees of the Federal Government in the course
of their official duties. Pursuant to title 17 Section 105 of the
United States Code, this software is not subject to copyright protection
and is in the public domain. NIST assumes no responsibility whatsoever for
its use by other parties, and makes no guarantees, expressed or implied,
about its quality, reliability, or any other characteristic.
License:
This software and/or related materials was developed at the National Institute
of Standards and Technology (NIST) by employees of the Federal Government
in the course of their official duties. Pursuant to title 17 Section 105
of the United States Code, this software is not subject to copyright
protection and is in the public domain.
Disclaimer:
This software was developed to promote biometric standards and biometric
technology testing for the Federal Government in accordance with the USA
PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act.
Specific hardware and software products identified in this software were used
in order to perform the software development. In no case does such
identification imply recommendation or endorsement by the National Institute
of Standards and Technology, nor does it imply that the products and equipment
identified are necessarily the best available for the purpose.
This software and/or related materials have been determined to be not subject
to the EAR (see Part 734.3 of the EAR for exact details) because it is
a publicly available technology and software, and is freely distributed
to any interested party with no licensing requirements. Therefore, it is
permissible to distribute this software as a free download from the internet.
Disclaimer:
This software and/or related materials was developed to promote biometric
standards and biometric technology testing for the Federal Government
in accordance with the USA PATRIOT Act and the Enhanced Border Security
and Visa Entry Reform Act. Specific hardware and software products identified
in this software were used in order to perform the software development.
In no case does such identification imply recommendation or endorsement
by the National Institute of Standards and Technology, nor does it imply that
the products and equipment identified are necessarily the best available
for the purpose.
This software and/or related materials are provided "AS-IS" without warranty
of any kind including NO WARRANTY OF PERFORMANCE, MERCHANTABILITY,
NO WARRANTY OF NON-INFRINGEMENT OF ANY 3RD PARTY INTELLECTUAL PROPERTY
or FITNESS FOR A PARTICULAR PURPOSE or for any purpose whatsoever, for the
licensed product, however used. In no event shall NIST be liable for any
damages and/or costs, including but not limited to incidental or consequential
damages of any kind, including economic damage or injury to property and lost
profits, regardless of whether NIST shall be advised, have reason to know,
or in fact shall know of the possibility.
By using this software, you agree to bear all risk relating to quality,
use and performance of the software and/or related materials. You agree
to hold the Government harmless from any claim arising from your use
of the software.
*******************************************************************************/
@@ -57,6 +49,9 @@ identified are necessarily the best available for the purpose.
MODIFICATIONS: Michael D. Garris (NIST)
Stan Janet (NIST)
DATE: 09/21/2004
UPDATED: 01/11/2012 by Kenneth Ko
UPDATED: 03/08/2012 by Kenneth Ko
UPDATED: 07/10/2014 by Kenneth Ko
Contains routines responsible for supporting command line
processing, file and data input to, and output from the
@@ -100,50 +95,7 @@ identified are necessarily the best available for the purpose.
#include <sys/time.h>
#include <bozorth.h>
static const int verbose_load = 0;
static const int verbose_main = 0;
/***********************************************************************/
int parse_line_range( const char * sb, int * begin, int * end )
{
int ib, ie;
char * se;
if ( ! isdigit(*sb) )
return -1;
ib = atoi( sb );
se = strchr( sb, '-' );
if ( se != (char *) NULL ) {
se++;
if ( ! isdigit(*se) )
return -2;
ie = atoi( se );
} else {
ie = ib;
}
if ( ib <= 0 ) {
if ( ie <= 0 ) {
return -3;
} else {
return -4;
}
}
if ( ie <= 0 ) {
return -5;
}
if ( ib > ie )
return -6;
*begin = ib;
*end = ie;
return 0;
}
/***********************************************************************/
@@ -153,25 +105,10 @@ static char * pfile;
static char * gfile;
/***********************************************************************/
void set_progname( int use_pid, char * basename, pid_t pid )
{
if ( use_pid )
sprintf( program_buffer, "%s pid %ld", basename, (long) pid );
else
sprintf( program_buffer, "%s", basename );
}
/***********************************************************************/
void set_probe_filename( char * filename )
{
pfile = filename;
}
/***********************************************************************/
void set_gallery_filename( char * filename )
{
gfile = filename;
}
/***********************************************************************/
char * get_progname( void )
@@ -192,171 +129,15 @@ return gfile;
}
/***********************************************************************/
char * get_next_file(
char * fixed_file,
FILE * list_fp,
FILE * mates_fp,
int * done_now,
int * done_afterwards,
char * line,
int argc,
char ** argv,
int * optind,
int * lineno,
int begin,
int end
)
{
char * p;
FILE * fp;
if ( fixed_file != (char *) NULL ) {
if ( verbose_main )
fprintf( stderr, "returning fixed filename: %s\n", fixed_file );
return fixed_file;
}
fp = list_fp;
if ( fp == (FILE *) NULL )
fp = mates_fp;
if ( fp != (FILE *) NULL ) {
while (1) {
if ( fgets( line, MAX_LINE_LENGTH, fp ) == (char *) NULL ) {
*done_now = 1;
if ( verbose_main )
fprintf( stderr, "returning NULL -- reached EOF\n" );
return (char *) NULL;
}
++*lineno;
if ( begin <= 0 ) /* no line number range was specified */
break;
if ( *lineno > end ) {
*done_now = 1;
if ( verbose_main )
fprintf( stderr, "returning NULL -- current line (%d) > end line (%d)\n",
*lineno, end );
return (char *) NULL;
}
if ( *lineno >= begin ) {
break;
}
/* Otherwise ( *lineno < begin ) so read another line */
}
p = strchr( line, '\n' );
if ( p == (char *) NULL ) {
*done_now = 1;
if ( verbose_main )
fprintf( stderr, "returning NULL -- missing newline character\n" );
return (char *) NULL;
}
*p = '\0';
p = line;
if ( verbose_main )
fprintf( stderr, "returning filename from next line: %s\n", p );
return p;
}
p = argv[*optind];
++*optind;
if ( *optind >= argc )
*done_afterwards = 1;
if ( verbose_main )
fprintf( stderr, "returning next argv: %s [done_afterwards=%d]\n", p, *done_afterwards );
return p;
}
/***********************************************************************/
/* returns CNULL on error */
char * get_score_filename( const char * outdir, const char * listfile )
{
const char * basename;
int baselen;
int dirlen;
int extlen;
char * outfile;
/* These are now exteranlly defined in bozorth.h */
/* extern FILE * stderr; */
/* extern char * get_progname( void ); */
basename = strrchr( listfile, '/' );
if ( basename == CNULL ) {
basename = listfile;
} else {
++basename;
}
baselen = strlen( basename );
if ( baselen == 0 ) {
fprintf( stderr, "%s: ERROR: couldn't find basename of %s\n", get_progname(), listfile );
return(CNULL);
}
dirlen = strlen( outdir );
if ( dirlen == 0 ) {
fprintf( stderr, "%s: ERROR: illegal output directory %s\n", get_progname(), outdir );
return(CNULL);
}
extlen = strlen( SCOREFILE_EXTENSION );
outfile = malloc_or_return_error( dirlen + baselen + extlen + 2, "output filename" );
if ( outfile == CNULL)
return(CNULL);
sprintf( outfile, "%s/%s%s", outdir, basename, SCOREFILE_EXTENSION );
return outfile;
}
/***********************************************************************/
char * get_score_line(
const char * probe_file,
const char * gallery_file,
int n,
int static_flag,
const char * fmt
)
{
int nchars;
char * bufptr;
static char linebuf[1024];
nchars = 0;
bufptr = &linebuf[0];
while ( *fmt ) {
if ( nchars++ > 0 )
*bufptr++ = ' ';
switch ( *fmt++ ) {
case 's':
sprintf( bufptr, "%d", n );
break;
case 'p':
sprintf( bufptr, "%s", probe_file );
break;
case 'g':
sprintf( bufptr, "%s", gallery_file );
break;
default:
return (char *) NULL;
}
bufptr = strchr( bufptr, '\0' );
}
*bufptr++ = '\n';
*bufptr = '\0';
return static_flag ? &linebuf[0] : strdup( linebuf );
}
/************************************************************************
Load a 3-4 column (X,Y,T[,Q]) set of minutiae from the specified file.
Load a 3-4 column (X,Y,T[,Q]) set of minutiae from the specified file
and return a XYT sturcture.
Row 3's value is an angle which is normalized to the interval (-180,180].
A maximum of MAX_BOZORTH_MINUTIAE minutiae can be returned -- fewer if
"DEFAULT_BOZORTH_MINUTIAE" is smaller. If the file contains more minutiae than are
@@ -364,241 +145,14 @@ to be returned, the highest-quality minutiae are returned.
*************************************************************************/
/***********************************************************************/
struct xyt_struct * bz_load( const char * xyt_file )
{
int nminutiae;
int j;
int m;
int nargs_expected;
FILE * fp;
struct xyt_struct * s;
int * xptr;
int * yptr;
int * tptr;
int * qptr;
struct minutiae_struct c[MAX_FILE_MINUTIAE];
int xvals_lng[MAX_FILE_MINUTIAE], /* Temporary lists to store all the minutaie from a file */
yvals_lng[MAX_FILE_MINUTIAE],
tvals_lng[MAX_FILE_MINUTIAE],
qvals_lng[MAX_FILE_MINUTIAE];
int order[MAX_FILE_MINUTIAE]; /* The ranked order, after sort, for each index */
int xvals[MAX_BOZORTH_MINUTIAE], /* Temporary lists to hold input coordinates */
yvals[MAX_BOZORTH_MINUTIAE],
tvals[MAX_BOZORTH_MINUTIAE],
qvals[MAX_BOZORTH_MINUTIAE];
char xyt_line[ MAX_LINE_LENGTH ];
/* This is now externally defined in bozorth.h */
/* extern FILE * stderr; */
#define C1 0
#define C2 1
fp = fopen( xyt_file, "r" );
if ( fp == (FILE *) NULL ) {
fprintf( stderr, "%s: ERROR: fopen() of minutiae file \"%s\" failed: %s\n",
get_progname(), xyt_file, strerror(errno) );
return XYT_NULL;
}
nminutiae = 0;
nargs_expected = 0;
while ( fgets( xyt_line, sizeof xyt_line, fp ) != CNULL ) {
m = sscanf( xyt_line, "%d %d %d %d",
&xvals_lng[nminutiae],
&yvals_lng[nminutiae],
&tvals_lng[nminutiae],
&qvals_lng[nminutiae] );
if ( nminutiae == 0 ) {
if ( m != 3 && m != 4 ) {
fprintf( stderr, "%s: ERROR: sscanf() failed on line %u in minutiae file \"%s\"\n",
get_progname(), nminutiae+1, xyt_file );
return XYT_NULL;
}
nargs_expected = m;
} else {
if ( m != nargs_expected ) {
fprintf( stderr, "%s: ERROR: inconsistent argument count on line %u of minutiae file \"%s\"\n",
get_progname(), nminutiae+1, xyt_file );
return XYT_NULL;
}
}
if ( m == 3 )
qvals_lng[nminutiae] = 1;
if ( tvals_lng[nminutiae] > 180 )
tvals_lng[nminutiae] -= 360;
/*
if ( C1 ) {
c[nminutiae].col[0] = xvals_lng[nminutiae];
c[nminutiae].col[1] = yvals_lng[nminutiae];
c[nminutiae].col[2] = tvals_lng[nminutiae];
c[nminutiae].col[3] = qvals_lng[nminutiae];
}
*/
++nminutiae;
if ( nminutiae == MAX_FILE_MINUTIAE )
break;
}
if ( fclose(fp) != 0 ) {
fprintf( stderr, "%s: ERROR: fclose() of minutiae file \"%s\" failed: %s\n",
get_progname(), xyt_file, strerror(errno) );
return XYT_NULL;
}
if ( nminutiae > DEFAULT_BOZORTH_MINUTIAE ) {
if ( verbose_load )
fprintf( stderr, "%s: WARNING: bz_load(): trimming minutiae to the %d of highest quality\n",
get_progname(), DEFAULT_BOZORTH_MINUTIAE );
if ( verbose_load )
fprintf( stderr, "Before quality sort:\n" );
if ( sort_order_decreasing( qvals_lng, nminutiae, order )) {
fprintf( stderr, "%s: ERROR: sort failed and returned on error\n", get_progname());
return XYT_NULL;
}
for ( j = 0; j < nminutiae; j++ ) {
if ( verbose_load )
fprintf( stderr, " %3d: %3d %3d %3d ---> order = %3d\n",
j, xvals_lng[j], yvals_lng[j], qvals_lng[j], order[j] );
if ( j == 0 )
continue;
if ( qvals_lng[order[j]] > qvals_lng[order[j-1]] ) {
fprintf( stderr, "%s: ERROR: sort failed: j=%d; qvals_lng[%d] > qvals_lng[%d]\n",
get_progname(), j, order[j], order[j-1] );
return XYT_NULL;
}
}
if ( verbose_load )
fprintf( stderr, "\nAfter quality sort:\n" );
for ( j = 0; j < DEFAULT_BOZORTH_MINUTIAE; j++ ) {
xvals[j] = xvals_lng[order[j]];
yvals[j] = yvals_lng[order[j]];
tvals[j] = tvals_lng[order[j]];
qvals[j] = qvals_lng[order[j]];
if ( verbose_load )
fprintf( stderr, " %3d: %3d %3d %3d\n", j, xvals[j], yvals[j], qvals[j] );
}
if ( C1 ) {
if ( verbose_load )
fprintf( stderr, "\nAfter qsort():\n" );
qsort( (void *) &c, (size_t) nminutiae, sizeof(struct minutiae_struct), sort_quality_decreasing );
for ( j = 0; j < nminutiae; j++ ) {
if ( verbose_load )
fprintf( stderr, "Q %3d: %3d %3d %3d\n",
j, c[j].col[0], c[j].col[1], c[j].col[3] );
if ( j > 0 && c[j].col[3] > c[j-1].col[3] ) {
fprintf( stderr, "%s: ERROR: sort failed: c[%d].col[3] > c[%d].col[3]\n",
get_progname(), j, j-1 );
return XYT_NULL;
}
}
}
if ( verbose_load )
fprintf( stderr, "\n" );
xptr = xvals;
yptr = yvals;
tptr = tvals;
qptr = qvals;
nminutiae = DEFAULT_BOZORTH_MINUTIAE;
} else{
xptr = xvals_lng;
yptr = yvals_lng;
tptr = tvals_lng;
qptr = qvals_lng;
}
for ( j=0; j < nminutiae; j++ ) {
c[j].col[0] = xptr[j];
c[j].col[1] = yptr[j];
c[j].col[2] = tptr[j];
c[j].col[3] = qptr[j];
}
qsort( (void *) &c, (size_t) nminutiae, sizeof(struct minutiae_struct), sort_x_y );
if ( verbose_load ) {
fprintf( stderr, "\nSorted on increasing x, then increasing y\n" );
for ( j = 0; j < nminutiae; j++ ) {
fprintf( stderr, "%d : %3d, %3d, %3d, %3d\n", j, c[j].col[0], c[j].col[1], c[j].col[2], c[j].col[3] );
if ( j > 0 ) {
if ( c[j].col[0] < c[j-1].col[0] ) {
fprintf( stderr, "%s: ERROR: sort failed: c[%d].col[0]=%d > c[%d].col[0]=%d\n",
get_progname(),
j, c[j].col[0], j-1, c[j-1].col[0]
);
return XYT_NULL;
}
if ( c[j].col[0] == c[j-1].col[0] && c[j].col[1] < c[j-1].col[1] ) {
fprintf( stderr, "%s: ERROR: sort failed: c[%d].col[0]=%d == c[%d].col[0]=%d; c[%d].col[0]=%d == c[%d].col[0]=%d\n",
get_progname(),
j, c[j].col[0], j-1, c[j-1].col[0],
j, c[j].col[1], j-1, c[j-1].col[1]
);
return XYT_NULL;
}
}
}
}
s = (struct xyt_struct *) malloc( sizeof( struct xyt_struct ) );
if ( s == XYT_NULL ) {
fprintf( stderr, "%s: ERROR: malloc() failure while loading minutiae file \"%s\" failed: %s\n",
get_progname(),
xyt_file,
strerror(errno)
);
return XYT_NULL;
}
for ( j = 0; j < nminutiae; j++ ) {
s->xcol[j] = c[j].col[0];
s->ycol[j] = c[j].col[1];
s->thetacol[j] = c[j].col[2];
}
s->nrows = nminutiae;
if ( verbose_load )
fprintf( stderr, "Loaded %s\n", xyt_file );
return s;
}
/************************************************************************
Load a XYTQ structure and return a XYT struct.
Row 3's value is an angle which is normalized to the interval (-180,180].
A maximum of MAX_BOZORTH_MINUTIAE minutiae can be returned -- fewer if
"DEFAULT_BOZORTH_MINUTIAE" is smaller. If the file contains more minutiae than are
to be returned, the highest-quality minutiae are returned.
*************************************************************************/
/***********************************************************************/
#ifdef PARALLEL_SEARCH
@@ -617,13 +171,13 @@ tv.tv_usec = 0;
retval = select( fd+1, &rfds, NULL, NULL, &tv );
if ( retval < 0 ) {
perror( "select() failed" );
return 0;
perror( "select() failed" );
return 0;
}
if ( FD_ISSET( fd, &rfds ) ) {
/*fprintf( stderr, "data is available now.\n" );*/
return 1;
/*fprintf( stderr, "data is available now.\n" );*/
return 1;
}
/* fprintf( stderr, "no data is available\n" ); */

View File

@@ -1,51 +1,43 @@
/******************************************************************************
This file is part of the Export Control subset of the United States NIST
Biometric Image Software (NBIS) distribution:
http://fingerprint.nist.gov/NBIS/index.html
It is our understanding that this falls within ECCN 3D980, which covers
software associated with the development, production or use of certain
equipment controlled in accordance with U.S. concerns about crime control
practices in specific countries.
Therefore, this file should not be exported, or made available on fileservers,
except as allowed by U.S. export control laws.
Do not remove this notice.
******************************************************************************/
/* NOTE: Despite the above notice (which I have not removed), this file is
* being legally distributed within libfprint; the U.S. Export Administration
* Regulations do not place export restrictions upon distribution of
* "publicly available technology and software", as stated in EAR section
* 734.3(b)(3)(i). libfprint qualifies as publicly available technology as per
* the definition in section 734.7(a)(1).
*
* For further information, see https://fprint.freedesktop.org/us-export-control.html
*/
/*******************************************************************************
License:
This software was developed at the National Institute of Standards and
Technology (NIST) by employees of the Federal Government in the course
of their official duties. Pursuant to title 17 Section 105 of the
United States Code, this software is not subject to copyright protection
and is in the public domain. NIST assumes no responsibility whatsoever for
its use by other parties, and makes no guarantees, expressed or implied,
about its quality, reliability, or any other characteristic.
License:
This software and/or related materials was developed at the National Institute
of Standards and Technology (NIST) by employees of the Federal Government
in the course of their official duties. Pursuant to title 17 Section 105
of the United States Code, this software is not subject to copyright
protection and is in the public domain.
Disclaimer:
This software was developed to promote biometric standards and biometric
technology testing for the Federal Government in accordance with the USA
PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act.
Specific hardware and software products identified in this software were used
in order to perform the software development. In no case does such
identification imply recommendation or endorsement by the National Institute
of Standards and Technology, nor does it imply that the products and equipment
identified are necessarily the best available for the purpose.
This software and/or related materials have been determined to be not subject
to the EAR (see Part 734.3 of the EAR for exact details) because it is
a publicly available technology and software, and is freely distributed
to any interested party with no licensing requirements. Therefore, it is
permissible to distribute this software as a free download from the internet.
Disclaimer:
This software and/or related materials was developed to promote biometric
standards and biometric technology testing for the Federal Government
in accordance with the USA PATRIOT Act and the Enhanced Border Security
and Visa Entry Reform Act. Specific hardware and software products identified
in this software were used in order to perform the software development.
In no case does such identification imply recommendation or endorsement
by the National Institute of Standards and Technology, nor does it imply that
the products and equipment identified are necessarily the best available
for the purpose.
This software and/or related materials are provided "AS-IS" without warranty
of any kind including NO WARRANTY OF PERFORMANCE, MERCHANTABILITY,
NO WARRANTY OF NON-INFRINGEMENT OF ANY 3RD PARTY INTELLECTUAL PROPERTY
or FITNESS FOR A PARTICULAR PURPOSE or for any purpose whatsoever, for the
licensed product, however used. In no event shall NIST be liable for any
damages and/or costs, including but not limited to incidental or consequential
damages of any kind, including economic damage or injury to property and lost
profits, regardless of whether NIST shall be advised, have reason to know,
or in fact shall know of the possibility.
By using this software, you agree to bear all risk relating to quality,
use and performance of the software and/or related materials. You agree
to hold the Government harmless from any claim arising from your use
of the software.
*******************************************************************************/
@@ -78,23 +70,10 @@ identified are necessarily the best available for the purpose.
#include <bozorth.h>
/* These are now externally defined in bozorth.h */
/* extern FILE * stderr; */
/* extern char * get_progname( void ); */
/***********************************************************************/
int sort_quality_decreasing( const void * a, const void * b )
{
struct minutiae_struct * af;
struct minutiae_struct * bf;
af = (struct minutiae_struct *) a;
bf = (struct minutiae_struct *) b;
if ( af->col[3] > bf->col[3] )
return -1;
if ( af->col[3] < bf->col[3] )
return 1;
return 0;
}
/***********************************************************************/
int sort_x_y( const void * a, const void * b )
@@ -124,67 +103,18 @@ qsort_decreasing() - quicksort an array of integers in decreasing
and Ted Zwiesler, 1986]
********************************************************/
/* Used by custom quicksort code below */
static int stack[BZ_STACKSIZE];
static int * stack_pointer = stack;
/***********************************************************************/
/* return values: 0 == successful, 1 == error */
static int popstack( int *popval )
{
if ( --stack_pointer < stack ) {
fprintf( stderr, "%s: ERROR: popstack(): stack underflow\n", get_progname() );
return 1;
}
*popval = *stack_pointer;
return 0;
}
/***********************************************************************/
/* return values: 0 == successful, 1 == error */
static int pushstack( int position )
{
*stack_pointer++ = position;
if ( stack_pointer > ( stack + BZ_STACKSIZE ) ) {
fprintf( stderr, "%s: ERROR: pushstack(): stack overflow\n", get_progname() );
return 1;
}
return 0;
}
/***********************************************************************/
/*******************************************************************
select_pivot()
selects a pivot from a list being sorted using the Singleton Method.
*******************************************************************/
static int select_pivot( struct cell v[], int left, int right )
{
int midpoint;
midpoint = ( left + right ) / 2;
if ( v[left].index <= v[midpoint].index ) {
if ( v[midpoint].index <= v[right].index ) {
return midpoint;
} else {
if ( v[right].index > v[left].index ) {
return right;
} else {
return left;
}
}
} else {
if ( v[left].index < v[right].index ) {
return left;
} else {
if ( v[right].index < v[midpoint].index ) {
return midpoint;
} else {
return right;
}
}
}
}
/***********************************************************************/
/********************************************************
@@ -192,41 +122,6 @@ partition_dec()
Inputs a pivot element making comparisons and swaps with other elements in a list,
until pivot resides at its correct position in the list.
********************************************************/
static void partition_dec( struct cell v[], int *llen, int *rlen, int *ll, int *lr, int *rl, int *rr, int p, int l, int r )
{
#define iswap(a,b) { int itmp = (a); a = (b); b = itmp; }
*ll = l;
*rr = r;
while ( 1 ) {
if ( l < p ) {
if ( v[l].index < v[p].index ) {
iswap( v[l].index, v[p].index )
iswap( v[l].item, v[p].item )
p = l;
} else {
l++;
}
} else {
if ( r > p ) {
if ( v[r].index > v[p].index ) {
iswap( v[r].index, v[p].index )
iswap( v[r].item, v[p].item )
p = r;
l++;
} else {
r--;
}
} else {
*lr = p - 1;
*rl = p + 1;
*llen = *lr - *ll + 1;
*rlen = *rr - *rl + 1;
break;
}
}
}
}
/***********************************************************************/
/********************************************************
@@ -236,80 +131,6 @@ sorted, a left subscript pointing to where the sort is to begin in the index ar
subscript where to end. This module invokes a decreasing quick-sort sorting the index array from l to r.
********************************************************/
/* return values: 0 == successful, 1 == error */
static int qsort_decreasing( struct cell v[], int left, int right )
{
int pivot;
int llen, rlen;
int lleft, lright, rleft, rright;
if ( pushstack( left ))
return 1;
if ( pushstack( right ))
return 2;
while ( stack_pointer != stack ) {
if (popstack(&right))
return 3;
if (popstack(&left ))
return 4;
if ( right - left > 0 ) {
pivot = select_pivot( v, left, right );
partition_dec( v, &llen, &rlen, &lleft, &lright, &rleft, &rright, pivot, left, right );
if ( llen > rlen ) {
if ( pushstack( lleft ))
return 5;
if ( pushstack( lright ))
return 6;
if ( pushstack( rleft ))
return 7;
if ( pushstack( rright ))
return 8;
} else{
if ( pushstack( rleft ))
return 9;
if ( pushstack( rright ))
return 10;
if ( pushstack( lleft ))
return 11;
if ( pushstack( lright ))
return 12;
}
}
}
return 0;
}
/***********************************************************************/
/* return values: 0 == successful, 1 == error */
int sort_order_decreasing(
int values[], /* INPUT: the unsorted values themselves */
int num, /* INPUT: the number of values */
int order[] /* OUTPUT: the order for each of the values if sorted */
)
{
int i;
struct cell * cells;
cells = (struct cell *) malloc( num * sizeof(struct cell) );
if ( cells == (struct cell *) NULL ){
fprintf( stderr, "%s: ERROR: malloc(): struct cell\n", get_progname() );
return 1;
}
for( i = 0; i < num; i++ ) {
cells[i].index = values[i];
cells[i].item = i;
}
if ( qsort_decreasing( cells, 0, num-1 ) < 0)
return 2;
for( i = 0; i < num; i++ ) {
order[i] = cells[i].item;
}
free( (void *) cells );
return 0;
}

View File

@@ -1,23 +1,43 @@
/*******************************************************************************
License:
This software was developed at the National Institute of Standards and
Technology (NIST) by employees of the Federal Government in the course
of their official duties. Pursuant to title 17 Section 105 of the
United States Code, this software is not subject to copyright protection
and is in the public domain. NIST assumes no responsibility whatsoever for
its use by other parties, and makes no guarantees, expressed or implied,
about its quality, reliability, or any other characteristic.
License:
This software and/or related materials was developed at the National Institute
of Standards and Technology (NIST) by employees of the Federal Government
in the course of their official duties. Pursuant to title 17 Section 105
of the United States Code, this software is not subject to copyright
protection and is in the public domain.
Disclaimer:
This software was developed to promote biometric standards and biometric
technology testing for the Federal Government in accordance with the USA
PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act.
Specific hardware and software products identified in this software were used
in order to perform the software development. In no case does such
identification imply recommendation or endorsement by the National Institute
of Standards and Technology, nor does it imply that the products and equipment
identified are necessarily the best available for the purpose.
This software and/or related materials have been determined to be not subject
to the EAR (see Part 734.3 of the EAR for exact details) because it is
a publicly available technology and software, and is freely distributed
to any interested party with no licensing requirements. Therefore, it is
permissible to distribute this software as a free download from the internet.
Disclaimer:
This software and/or related materials was developed to promote biometric
standards and biometric technology testing for the Federal Government
in accordance with the USA PATRIOT Act and the Enhanced Border Security
and Visa Entry Reform Act. Specific hardware and software products identified
in this software were used in order to perform the software development.
In no case does such identification imply recommendation or endorsement
by the National Institute of Standards and Technology, nor does it imply that
the products and equipment identified are necessarily the best available
for the purpose.
This software and/or related materials are provided "AS-IS" without warranty
of any kind including NO WARRANTY OF PERFORMANCE, MERCHANTABILITY,
NO WARRANTY OF NON-INFRINGEMENT OF ANY 3RD PARTY INTELLECTUAL PROPERTY
or FITNESS FOR A PARTICULAR PURPOSE or for any purpose whatsoever, for the
licensed product, however used. In no event shall NIST be liable for any
damages and/or costs, including but not limited to incidental or consequential
damages of any kind, including economic damage or injury to property and lost
profits, regardless of whether NIST shall be advised, have reason to know,
or in fact shall know of the possibility.
By using this software, you agree to bear all risk relating to quality,
use and performance of the software and/or related materials. You agree
to hold the Government harmless from any claim arising from your use
of the software.
*******************************************************************************/
@@ -163,7 +183,7 @@ struct cell {
};
/**************************************************************************/
/* In BZ_IO : Supports the loading and manipulation of XYT data */
/* In BZ_IO : Supports the loading and manipulation of XYT and XYTQ data */
/**************************************************************************/
#define MAX_FILE_MINUTIAE 1000 /* bz_load() */
@@ -174,7 +194,17 @@ struct xyt_struct {
int thetacol[ MAX_BOZORTH_MINUTIAE ];
};
struct xytq_struct {
int nrows;
int xcol[ MAX_FILE_MINUTIAE ];
int ycol[ MAX_FILE_MINUTIAE ];
int thetacol[ MAX_FILE_MINUTIAE ];
int qualitycol[ MAX_FILE_MINUTIAE ];
};
#define XYT_NULL ( (struct xyt_struct *) NULL ) /* bz_load() */
#define XYTQ_NULL ( (struct xytq_struct *) NULL ) /* bz_load() */
/**************************************************************************/
@@ -187,6 +217,8 @@ struct xyt_struct {
/**************************************************************************/
/* Globals supporting command line options */
extern int verbose_threshold;
/* Global supporting error reporting */
extern FILE *stderr;
/**************************************************************************/
/* In: BZ_GBLS.C */
@@ -247,6 +279,7 @@ extern char *get_next_file(char *, FILE *, FILE *, int *, int *, char *,
extern char *get_score_filename(const char *, const char *);
extern char *get_score_line(const char *, const char *, int, int, const char *);
extern struct xyt_struct *bz_load(const char *);
extern struct xyt_struct *bz_prune(struct xytq_struct *, int);
extern int fd_readable(int);
/* In: BZ_SORT.C */
extern int sort_quality_decreasing(const void *, const void *);

View File

@@ -1,23 +1,43 @@
/*******************************************************************************
License:
This software was developed at the National Institute of Standards and
Technology (NIST) by employees of the Federal Government in the course
of their official duties. Pursuant to title 17 Section 105 of the
United States Code, this software is not subject to copyright protection
and is in the public domain. NIST assumes no responsibility whatsoever for
its use by other parties, and makes no guarantees, expressed or implied,
about its quality, reliability, or any other characteristic.
License:
This software and/or related materials was developed at the National Institute
of Standards and Technology (NIST) by employees of the Federal Government
in the course of their official duties. Pursuant to title 17 Section 105
of the United States Code, this software is not subject to copyright
protection and is in the public domain.
Disclaimer:
This software was developed to promote biometric standards and biometric
technology testing for the Federal Government in accordance with the USA
PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act.
Specific hardware and software products identified in this software were used
in order to perform the software development. In no case does such
identification imply recommendation or endorsement by the National Institute
of Standards and Technology, nor does it imply that the products and equipment
identified are necessarily the best available for the purpose.
This software and/or related materials have been determined to be not subject
to the EAR (see Part 734.3 of the EAR for exact details) because it is
a publicly available technology and software, and is freely distributed
to any interested party with no licensing requirements. Therefore, it is
permissible to distribute this software as a free download from the internet.
Disclaimer:
This software and/or related materials was developed to promote biometric
standards and biometric technology testing for the Federal Government
in accordance with the USA PATRIOT Act and the Enhanced Border Security
and Visa Entry Reform Act. Specific hardware and software products identified
in this software were used in order to perform the software development.
In no case does such identification imply recommendation or endorsement
by the National Institute of Standards and Technology, nor does it imply that
the products and equipment identified are necessarily the best available
for the purpose.
This software and/or related materials are provided "AS-IS" without warranty
of any kind including NO WARRANTY OF PERFORMANCE, MERCHANTABILITY,
NO WARRANTY OF NON-INFRINGEMENT OF ANY 3RD PARTY INTELLECTUAL PROPERTY
or FITNESS FOR A PARTICULAR PURPOSE or for any purpose whatsoever, for the
licensed product, however used. In no event shall NIST be liable for any
damages and/or costs, including but not limited to incidental or consequential
damages of any kind, including economic damage or injury to property and lost
profits, regardless of whether NIST shall be advised, have reason to know,
or in fact shall know of the possibility.
By using this software, you agree to bear all risk relating to quality,
use and performance of the software and/or related materials. You agree
to hold the Government harmless from any claim arising from your use
of the software.
*******************************************************************************/

View File

@@ -1,23 +1,43 @@
/*******************************************************************************
License:
This software was developed at the National Institute of Standards and
Technology (NIST) by employees of the Federal Government in the course
of their official duties. Pursuant to title 17 Section 105 of the
United States Code, this software is not subject to copyright protection
and is in the public domain. NIST assumes no responsibility whatsoever for
its use by other parties, and makes no guarantees, expressed or implied,
about its quality, reliability, or any other characteristic.
License:
This software and/or related materials was developed at the National Institute
of Standards and Technology (NIST) by employees of the Federal Government
in the course of their official duties. Pursuant to title 17 Section 105
of the United States Code, this software is not subject to copyright
protection and is in the public domain.
Disclaimer:
This software was developed to promote biometric standards and biometric
technology testing for the Federal Government in accordance with the USA
PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act.
Specific hardware and software products identified in this software were used
in order to perform the software development. In no case does such
identification imply recommendation or endorsement by the National Institute
of Standards and Technology, nor does it imply that the products and equipment
identified are necessarily the best available for the purpose.
This software and/or related materials have been determined to be not subject
to the EAR (see Part 734.3 of the EAR for exact details) because it is
a publicly available technology and software, and is freely distributed
to any interested party with no licensing requirements. Therefore, it is
permissible to distribute this software as a free download from the internet.
Disclaimer:
This software and/or related materials was developed to promote biometric
standards and biometric technology testing for the Federal Government
in accordance with the USA PATRIOT Act and the Enhanced Border Security
and Visa Entry Reform Act. Specific hardware and software products identified
in this software were used in order to perform the software development.
In no case does such identification imply recommendation or endorsement
by the National Institute of Standards and Technology, nor does it imply that
the products and equipment identified are necessarily the best available
for the purpose.
This software and/or related materials are provided "AS-IS" without warranty
of any kind including NO WARRANTY OF PERFORMANCE, MERCHANTABILITY,
NO WARRANTY OF NON-INFRINGEMENT OF ANY 3RD PARTY INTELLECTUAL PROPERTY
or FITNESS FOR A PARTICULAR PURPOSE or for any purpose whatsoever, for the
licensed product, however used. In no event shall NIST be liable for any
damages and/or costs, including but not limited to incidental or consequential
damages of any kind, including economic damage or injury to property and lost
profits, regardless of whether NIST shall be advised, have reason to know,
or in fact shall know of the possibility.
By using this software, you agree to bear all risk relating to quality,
use and performance of the software and/or related materials. You agree
to hold the Government harmless from any claim arising from your use
of the software.
*******************************************************************************/
@@ -53,7 +73,6 @@ identified are necessarily the best available for the purpose.
#define min(a, b) ((a) < (b) ? (a) : (b))
#define sround(x) ((int) (((x)<0) ? (x)-0.5 : (x)+0.5))
#define sround_uint(x) ((unsigned int) (((x)<0) ? (x)-0.5 : (x)+0.5))
#define xor(a, b) (!(a && b) && (a || b))
#define align_to_16(_v_) ((((_v_)+15)>>4)<<4)
#define align_to_32(_v_) ((((_v_)+31)>>5)<<5)
#ifndef CHUNKS

View File

@@ -1,23 +1,43 @@
/*******************************************************************************
License:
This software was developed at the National Institute of Standards and
Technology (NIST) by employees of the Federal Government in the course
of their official duties. Pursuant to title 17 Section 105 of the
United States Code, this software is not subject to copyright protection
and is in the public domain. NIST assumes no responsibility whatsoever for
its use by other parties, and makes no guarantees, expressed or implied,
about its quality, reliability, or any other characteristic.
License:
This software and/or related materials was developed at the National Institute
of Standards and Technology (NIST) by employees of the Federal Government
in the course of their official duties. Pursuant to title 17 Section 105
of the United States Code, this software is not subject to copyright
protection and is in the public domain.
Disclaimer:
This software was developed to promote biometric standards and biometric
technology testing for the Federal Government in accordance with the USA
PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act.
Specific hardware and software products identified in this software were used
in order to perform the software development. In no case does such
identification imply recommendation or endorsement by the National Institute
of Standards and Technology, nor does it imply that the products and equipment
identified are necessarily the best available for the purpose.
This software and/or related materials have been determined to be not subject
to the EAR (see Part 734.3 of the EAR for exact details) because it is
a publicly available technology and software, and is freely distributed
to any interested party with no licensing requirements. Therefore, it is
permissible to distribute this software as a free download from the internet.
Disclaimer:
This software and/or related materials was developed to promote biometric
standards and biometric technology testing for the Federal Government
in accordance with the USA PATRIOT Act and the Enhanced Border Security
and Visa Entry Reform Act. Specific hardware and software products identified
in this software were used in order to perform the software development.
In no case does such identification imply recommendation or endorsement
by the National Institute of Standards and Technology, nor does it imply that
the products and equipment identified are necessarily the best available
for the purpose.
This software and/or related materials are provided "AS-IS" without warranty
of any kind including NO WARRANTY OF PERFORMANCE, MERCHANTABILITY,
NO WARRANTY OF NON-INFRINGEMENT OF ANY 3RD PARTY INTELLECTUAL PROPERTY
or FITNESS FOR A PARTICULAR PURPOSE or for any purpose whatsoever, for the
licensed product, however used. In no event shall NIST be liable for any
damages and/or costs, including but not limited to incidental or consequential
damages of any kind, including economic damage or injury to property and lost
profits, regardless of whether NIST shall be advised, have reason to know,
or in fact shall know of the possibility.
By using this software, you agree to bear all risk relating to quality,
use and performance of the software and/or related materials. You agree
to hold the Government harmless from any claim arising from your use
of the software.
*******************************************************************************/
@@ -33,6 +53,9 @@ identified are necessarily the best available for the purpose.
Comments added to guide changes to blocksize
or number of detected directions.
UPDATED: 03/11/2005 by MDG
UPDATED: 01/31/2008 by Kenneth Ko
UPDATED: 09/04/2008 by Kenneth Ko
UPDATED: 01/11/2012 by Kenneth Ko
FILE: LFS.H
@@ -160,7 +183,7 @@ typedef struct shape{
/* Parameters used by LFS for setting thresholds and */
/* defining testing criterion. */
typedef struct lfsparms{
typedef struct g_lfsparms{
/* Image Controls */
int pad_value;
int join_line_radius;
@@ -236,8 +259,6 @@ typedef struct lfsparms{
int pores_steps_bwd;
double pores_min_dist2;
double pores_max_ratio;
int remove_perimeter_pts;
int min_pp_distance;
/* Ridge Counting Controls */
int max_nbrs;
@@ -382,7 +403,7 @@ typedef struct lfsparms{
/* Thresholds and factors used by HO39. Renamed */
/* here to give more meaning. */
/* HO39 Name=Value */
/* Minimum DFT power allowable in any one direction. */
/* Minimum DFT power allowable in any one direction. */
#define POWMAX_MIN 100000.0 /* thrhf=1e5f */
/* Minimum normalized power allowable in any one */
@@ -587,9 +608,6 @@ typedef struct lfsparms{
/* contour points to be considered a pore. */
#define PORES_MAX_RATIO 2.25
/* Points which are closer than this distance to scan perimeter will be removed */
#define PERIMETER_PTS_DISTANCE 10
/***** RIDGE COUNTING CONSTANTS *****/
@@ -689,15 +707,24 @@ typedef struct lfsparms{
/*************************************************************************/
/* binar.c */
extern int binarize(unsigned char **, int *, int *,
unsigned char *, const int, const int,
int *, const int, const int,
const ROTGRIDS *, const LFSPARMS *);
extern int binarize_V2(unsigned char **, int *, int *,
unsigned char *, const int, const int,
int *, const int, const int,
const ROTGRIDS *, const LFSPARMS *);
extern int binarize_image(unsigned char **, int *, int *,
unsigned char *, const int, const int,
const int *, const int, const int, const int,
const ROTGRIDS *, const int);
extern int binarize_image_V2(unsigned char **, int *, int *,
unsigned char *, const int, const int,
const int *, const int, const int,
const int, const ROTGRIDS *);
extern int dirbinarize(const unsigned char *, const int, const ROTGRIDS *);
extern int isobinarize(unsigned char *, const int, const int, const int);
/* block.c */
extern int block_offsets(int **, int *, int *, const int, const int,
@@ -709,9 +736,12 @@ extern int find_valid_block(int *, int *, int *, int *, int *,
const int, const int);
extern void set_margin_blocks(int *, const int, const int, const int);
/* chaincod.c */
extern int chain_code_loop(int **, int *, const int *, const int *, const int);
extern int is_chain_clockwise(const int *, const int, const int);
/* contour.c */
int allocate_contour(int **ocontour_x, int **ocontour_y,
int **ocontour_ex, int **ocontour_ey, const int ncontour);
extern int allocate_contour(int **, int **, int **, int **, const int);
extern void free_contour(int *, int *, int *, int *);
extern int get_high_curvature_contour(int **, int **, int **, int **, int *,
const int, const int, const int, const int, const int,
@@ -726,6 +756,11 @@ extern int trace_contour(int **, int **, int **, int **, int *,
extern int search_contour(const int, const int, const int,
const int, const int, const int, const int, const int,
unsigned char *, const int, const int);
extern int next_contour_pixel(int *, int *, int *, int *,
const int, const int, const int, const int, const int,
unsigned char *, const int, const int);
extern int start_scan_nbr(const int, const int, const int, const int);
extern int next_scan_nbr(const int, const int);
extern int min_contour_theta(int *, double *, const int, const int *,
const int *, const int);
extern void contour_limits(int *, int *, int *, int *, const int *,
@@ -734,18 +769,29 @@ extern void fix_edge_pixel_pair(int *, int *, int *, int *,
unsigned char *, const int, const int);
/* detect.c */
extern int get_minutiae(MINUTIAE **, int **, int **, int **,
int **, int **, int *, int *,
unsigned char **, int *, int *, int *,
unsigned char *, const int, const int,
const int, const double, const LFSPARMS *);
extern int lfs_detect_minutiae( MINUTIAE **,
int **, int **, int *, int *,
unsigned char **, int *, int *,
unsigned char *, const int, const int,
const LFSPARMS *);
extern int lfs_detect_minutiae_V2(MINUTIAE **,
int **, int **, int **, int **, int *, int *,
unsigned char **, int *, int *,
unsigned char *, const int, const int,
const LFSPARMS *);
/* dft.c */
extern int dft_dir_powers(double **, unsigned char *, const int,
const int, const int, const DFTWAVES *,
const ROTGRIDS *);
extern void sum_rot_block_rows(int *, const unsigned char *, const int *,
const int);
extern void dft_power(double *, const int *, const DFTWAVE *, const int);
extern int dft_power_stats(int *, double *, int *, double *, double **,
const int, const int, const int);
extern void get_max_norm(double *, int *, double *, const double *, const int);
extern int sort_dft_waves(int *, const double *, const double *, const int);
/* free.c */
extern void free_dir2rad(DIR2RAD *);
@@ -753,6 +799,13 @@ extern void free_dftwaves(DFTWAVES *);
extern void free_rotgrids(ROTGRIDS *);
extern void free_dir_powers(double **, const int);
/* getmin.c */
extern int get_minutiae(MINUTIAE **, int **, int **, int **,
int **, int **, int *, int *,
unsigned char **, int *, int *, int *,
unsigned char *, const int, const int,
const int, const double, const LFSPARMS *);
/* imgutil.c */
extern void bits_6to8(unsigned char *, const int, const int);
extern void bits_8to6(unsigned char *, const int, const int);
@@ -771,15 +824,41 @@ extern int search_in_direction(int *, int *, int *, int *, const int,
/* init.c */
extern int init_dir2rad(DIR2RAD **, const int);
extern int init_dftwaves(DFTWAVES **, const double *, const int, const int);
extern int get_max_padding(const int, const int, const int, const int);
extern int get_max_padding_V2(const int, const int, const int, const int);
extern int init_rotgrids(ROTGRIDS **, const int, const int, const int,
const double, const int, const int, const int, const int);
extern int alloc_dir_powers(double ***, const int, const int);
extern int alloc_power_stats(int **, double **, int **, double **, const int);
/* isempty.c */
extern int is_image_empty(int *, const int, const int);
extern int is_qmap_empty(int *, const int, const int);
/* line.c */
extern int line_points(int **, int **, int *,
const int, const int, const int, const int);
extern int bresenham_line_points(int **, int **, int *,
const int, const int, const int, const int);
/* link.c */
extern int link_minutiae(MINUTIAE *, unsigned char *, const int, const int,
int *, const int, const int, const LFSPARMS *);
extern int create_link_table(int **, int **, int **, int *, int *, int *,
const int, const int, const MINUTIAE *, const int *,
int *, const int, const int, unsigned char *,
const int, const int, const LFSPARMS *);
extern int update_link_table(int *, int *, int *, int *, int *, int *,
const int, int *, int *, int *, int *,
const int, const int, const int);
extern int order_link_table(int *, int *, int *, const int, const int,
const int, const int, const MINUTIAE *, const int);
extern int process_link_table(const int *, const int *, const int *,
const int, const int, const int, const int, MINUTIAE *,
int *, unsigned char *, const int, const int,
const LFSPARMS *);
extern double link_score(const double, const double, const LFSPARMS *);
/* loop.c */
extern int get_loop_list(int **, MINUTIAE *, const int, unsigned char *,
@@ -799,8 +878,16 @@ extern int process_loop_V2(MINUTIAE *, const int *, const int *,
const int *, const int *, const int,
unsigned char *, const int, const int,
int *, const LFSPARMS *);
extern void get_loop_aspect(int *, int *, double *, int *, int *, double *,
const int *, const int *, const int);
extern int fill_loop(const int *, const int *, const int,
unsigned char *, const int, const int);
extern void fill_partial_row(const int, const int, const int, const int,
unsigned char *, const int, const int);
extern void flood_loop(const int *, const int *, const int,
unsigned char *, const int, const int);
extern void flood_fill4(const int, const int, const int,
unsigned char *, const int, const int);
/* maps.c */
extern int gen_image_maps(int **, int **, int **, int **, int *, int *,
@@ -820,6 +907,10 @@ extern void smooth_direction_map(int *, int *, const int, const int,
const DIR2RAD *, const LFSPARMS *);
extern int gen_high_curve_map(int **, int *, const int, const int,
const LFSPARMS *);
extern int gen_imap(int **, int *, int *,
unsigned char *, const int, const int,
const DIR2RAD *, const DFTWAVES *, const ROTGRIDS *,
const LFSPARMS *);
extern int gen_initial_imap(int **, int *, const int, const int,
unsigned char *, const int, const int,
const DFTWAVES *, const ROTGRIDS *, const LFSPARMS *);
@@ -850,6 +941,7 @@ extern void average_8nbr_dir(int *, double *, int *, int *, const int,
extern int num_valid_8nbrs(int *, const int, const int, const int, const int);
extern void smooth_imap(int *, const int, const int, const DIR2RAD *,
const LFSPARMS *);
extern int gen_nmap(int **, int *, const int, const int, const LFSPARMS *);
extern int vorticity(int *, const int, const int, const int, const int,
const int);
extern void accum_nbr_vorticity(int *, const int, const int, const int);
@@ -868,6 +960,9 @@ extern void skip_repeated_vertical_pair(int *, const int,
/* minutia.c */
extern int alloc_minutiae(MINUTIAE **, const int);
extern int realloc_minutiae(MINUTIAE *, const int);
extern int detect_minutiae(MINUTIAE *, unsigned char *, const int, const int,
const int *, const int *, const int, const int,
const LFSPARMS *);
extern int detect_minutiae_V2(MINUTIAE *,
unsigned char *, const int, const int,
int *, int *, int *, const int, const int,
@@ -972,8 +1067,6 @@ extern int adjust_high_curvature_minutia_V2(int *, int *, int *,
int *, MINUTIAE *, const LFSPARMS *);
extern int get_low_curvature_direction(const int, const int, const int,
const int);
void lfs2nist_minutia_XYT(int *ox, int *oy, int *ot,
const MINUTIA *minutia, const int iw, const int ih);
/* quality.c */
extern int gen_quality_map(int **, int *, int *, int *, int *,
@@ -981,6 +1074,12 @@ extern int gen_quality_map(int **, int *, int *, int *, int *,
extern int combined_minutia_quality(MINUTIAE *, int *, const int, const int,
const int, unsigned char *, const int, const int,
const int, const double);
double grayscale_reliability(MINUTIA *, unsigned char *,
const int, const int, const int);
extern void get_neighborhood_stats(double *, double *, MINUTIA *,
unsigned char *, const int, const int, const int);
extern int reliability_fr_quality_map(MINUTIAE *, int *, const int,
const int, const int, const int, const int);
/* remove.c */
extern int remove_false_minutia(MINUTIAE *,
@@ -990,15 +1089,93 @@ extern int remove_false_minutia_V2(MINUTIAE *,
unsigned char *, const int, const int,
int *, int *, int *, const int, const int,
const LFSPARMS *);
extern int remove_holes(MINUTIAE *, unsigned char *, const int, const int,
const LFSPARMS *);
extern int remove_hooks(MINUTIAE *,
unsigned char *, const int, const int, const LFSPARMS *);
extern int remove_hooks_islands_lakes_overlaps(MINUTIAE *, unsigned char *,
const int, const int, const LFSPARMS *);
extern int remove_islands_and_lakes(MINUTIAE *,
unsigned char *, const int, const int, const LFSPARMS *);
extern int remove_malformations(MINUTIAE *,
unsigned char *, const int, const int,
int *, const int, const int, const LFSPARMS *);
extern int remove_near_invblock(MINUTIAE *, int *, const int, const int,
const LFSPARMS *);
extern int remove_near_invblock_V2(MINUTIAE *, int *,
const int, const int, const LFSPARMS *);
extern int remove_pointing_invblock(MINUTIAE *, int *, const int, const int,
const LFSPARMS *);
extern int remove_pointing_invblock_V2(MINUTIAE *,
int *, const int, const int, const LFSPARMS *);
extern int remove_overlaps(MINUTIAE *,
unsigned char *, const int, const int, const LFSPARMS *);
extern int remove_pores(MINUTIAE *,
unsigned char *, const int, const int,
int *, const int, const int, const LFSPARMS *);
extern int remove_pores_V2(MINUTIAE *,
unsigned char *, const int, const int,
int *, int *, int *, const int, const int,
const LFSPARMS *);
extern int remove_or_adjust_side_minutiae(MINUTIAE *, unsigned char *,
const int, const int, const LFSPARMS *);
extern int remove_or_adjust_side_minutiae_V2(MINUTIAE *,
unsigned char *, const int, const int,
int *, const int, const int, const LFSPARMS *);
/* results.c */
extern int write_text_results(char *, const int, const int, const int,
const MINUTIAE *, int *, int *, int *, int *, int *,
const int, const int);
extern int write_minutiae_XYTQ(char *ofile, const int,
const MINUTIAE *, const int, const int);
extern void dump_map(FILE *, int *, const int, const int);
extern int drawimap(int *, const int, const int, unsigned char *,
const int, const int, const ROTGRIDS *, const int);
extern void drawimap2(int *, const int *, const int, const int,
unsigned char *, const int, const int,
const double, const int, const int);
extern void drawblocks(const int *, const int, const int,
unsigned char *, const int, const int, const int );
extern int drawrotgrid(const ROTGRIDS *, const int, unsigned char *,
const int, const int, const int, const int);
extern void dump_link_table(FILE *, const int *, const int *, const int *,
const int, const int, const int, const MINUTIAE *);
extern int draw_direction_map(char *, int *,
int *, const int, const int, const int,
unsigned char *, const int, const int, const int);
extern int draw_TF_map(char *, int *,
int *, const int, const int, const int,
unsigned char *, const int, const int, const int);
/* ridges.c */
extern int count_minutiae_ridges(MINUTIAE *,
unsigned char *, const int, const int,
const LFSPARMS *);
extern int count_minutia_ridges(const int, MINUTIAE *,
unsigned char *, const int, const int,
const LFSPARMS *);
extern int find_neighbors(int **, int *, const int, const int, MINUTIAE *);
extern int update_nbr_dists(int *, double *, int *, const int,
const int, const int, MINUTIAE *);
extern int insert_neighbor(const int, const int, const double,
int *, double *, int *, const int);
extern int sort_neighbors(int *, const int, const int, MINUTIAE *);
extern int ridge_count(const int, const int, MINUTIAE *,
unsigned char *, const int, const int, const LFSPARMS *);
extern int find_transition(int *, const int, const int,
const int *, const int *, const int,
unsigned char *, const int, const int);
extern int validate_ridge_crossing(const int, const int,
const int *, const int *, const int,
unsigned char *, const int, const int, const int);
/* shape.c */
extern int alloc_shape(SHAPE **, const int, const int, const int, const int);
extern void free_shape(SHAPE *);
extern void dump_shape(FILE *, const SHAPE *);
extern int shape_from_contour(SHAPE **, const int *, const int *, const int);
extern void sort_row_on_x(ROW *);
/* sort.c */
extern int sort_indices_int_inc(int **, int *, const int);
@@ -1023,6 +1200,12 @@ extern int line2direction(const int, const int, const int, const int,
const int);
extern int closest_dir_dist(const int, const int, const int);
/* xytreps.c */
extern void lfs2nist_minutia_XYT(int *, int *, int *,
const MINUTIA *, const int, const int);
extern void lfs2m1_minutia_XYT(int *, int *, int *, const MINUTIA *);
extern void lfs2nist_format(MINUTIAE *, int, int);
/*************************************************************************/
/* EXTERNAL GLOBAL VARIABLE DEFINITIONS */
/*************************************************************************/

View File

@@ -1,26 +1,47 @@
/*******************************************************************************
License:
This software was developed at the National Institute of Standards and
Technology (NIST) by employees of the Federal Government in the course
of their official duties. Pursuant to title 17 Section 105 of the
United States Code, this software is not subject to copyright protection
and is in the public domain. NIST assumes no responsibility whatsoever for
its use by other parties, and makes no guarantees, expressed or implied,
about its quality, reliability, or any other characteristic.
License:
This software and/or related materials was developed at the National Institute
of Standards and Technology (NIST) by employees of the Federal Government
in the course of their official duties. Pursuant to title 17 Section 105
of the United States Code, this software is not subject to copyright
protection and is in the public domain.
Disclaimer:
This software was developed to promote biometric standards and biometric
technology testing for the Federal Government in accordance with the USA
PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act.
Specific hardware and software products identified in this software were used
in order to perform the software development. In no case does such
identification imply recommendation or endorsement by the National Institute
of Standards and Technology, nor does it imply that the products and equipment
identified are necessarily the best available for the purpose.
This software and/or related materials have been determined to be not subject
to the EAR (see Part 734.3 of the EAR for exact details) because it is
a publicly available technology and software, and is freely distributed
to any interested party with no licensing requirements. Therefore, it is
permissible to distribute this software as a free download from the internet.
Disclaimer:
This software and/or related materials was developed to promote biometric
standards and biometric technology testing for the Federal Government
in accordance with the USA PATRIOT Act and the Enhanced Border Security
and Visa Entry Reform Act. Specific hardware and software products identified
in this software were used in order to perform the software development.
In no case does such identification imply recommendation or endorsement
by the National Institute of Standards and Technology, nor does it imply that
the products and equipment identified are necessarily the best available
for the purpose.
This software and/or related materials are provided "AS-IS" without warranty
of any kind including NO WARRANTY OF PERFORMANCE, MERCHANTABILITY,
NO WARRANTY OF NON-INFRINGEMENT OF ANY 3RD PARTY INTELLECTUAL PROPERTY
or FITNESS FOR A PARTICULAR PURPOSE or for any purpose whatsoever, for the
licensed product, however used. In no event shall NIST be liable for any
damages and/or costs, including but not limited to incidental or consequential
damages of any kind, including economic damage or injury to property and lost
profits, regardless of whether NIST shall be advised, have reason to know,
or in fact shall know of the possibility.
By using this software, you agree to bear all risk relating to quality,
use and performance of the software and/or related materials. You agree
to hold the Government harmless from any claim arising from your use
of the software.
*******************************************************************************/
#ifndef _LOG_H
#define _LOG_H
@@ -36,10 +57,6 @@ identified are necessarily the best available for the purpose.
#define LOG_FILE "log.txt"
#endif
extern FILE *g_logfp;
extern int g_avrdir;
extern float g_dir_strength;
extern int g_nvalid;
extern int open_logfile(void);
extern int close_logfile(void);

View File

@@ -1,26 +1,47 @@
/*******************************************************************************
License:
This software was developed at the National Institute of Standards and
Technology (NIST) by employees of the Federal Government in the course
of their official duties. Pursuant to title 17 Section 105 of the
United States Code, this software is not subject to copyright protection
and is in the public domain. NIST assumes no responsibility whatsoever for
its use by other parties, and makes no guarantees, expressed or implied,
about its quality, reliability, or any other characteristic.
License:
This software and/or related materials was developed at the National Institute
of Standards and Technology (NIST) by employees of the Federal Government
in the course of their official duties. Pursuant to title 17 Section 105
of the United States Code, this software is not subject to copyright
protection and is in the public domain.
Disclaimer:
This software was developed to promote biometric standards and biometric
technology testing for the Federal Government in accordance with the USA
PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act.
Specific hardware and software products identified in this software were used
in order to perform the software development. In no case does such
identification imply recommendation or endorsement by the National Institute
of Standards and Technology, nor does it imply that the products and equipment
identified are necessarily the best available for the purpose.
This software and/or related materials have been determined to be not subject
to the EAR (see Part 734.3 of the EAR for exact details) because it is
a publicly available technology and software, and is freely distributed
to any interested party with no licensing requirements. Therefore, it is
permissible to distribute this software as a free download from the internet.
Disclaimer:
This software and/or related materials was developed to promote biometric
standards and biometric technology testing for the Federal Government
in accordance with the USA PATRIOT Act and the Enhanced Border Security
and Visa Entry Reform Act. Specific hardware and software products identified
in this software were used in order to perform the software development.
In no case does such identification imply recommendation or endorsement
by the National Institute of Standards and Technology, nor does it imply that
the products and equipment identified are necessarily the best available
for the purpose.
This software and/or related materials are provided "AS-IS" without warranty
of any kind including NO WARRANTY OF PERFORMANCE, MERCHANTABILITY,
NO WARRANTY OF NON-INFRINGEMENT OF ANY 3RD PARTY INTELLECTUAL PROPERTY
or FITNESS FOR A PARTICULAR PURPOSE or for any purpose whatsoever, for the
licensed product, however used. In no event shall NIST be liable for any
damages and/or costs, including but not limited to incidental or consequential
damages of any kind, including economic damage or injury to property and lost
profits, regardless of whether NIST shall be advised, have reason to know,
or in fact shall know of the possibility.
By using this software, you agree to bear all risk relating to quality,
use and performance of the software and/or related materials. You agree
to hold the Government harmless from any claim arising from your use
of the software.
*******************************************************************************/
#ifndef __MORPH_H__
#define __MORPH_H__

View File

@@ -0,0 +1,106 @@
/*******************************************************************************
License:
This software and/or related materials was developed at the National Institute
of Standards and Technology (NIST) by employees of the Federal Government
in the course of their official duties. Pursuant to title 17 Section 105
of the United States Code, this software is not subject to copyright
protection and is in the public domain.
This software and/or related materials have been determined to be not subject
to the EAR (see Part 734.3 of the EAR for exact details) because it is
a publicly available technology and software, and is freely distributed
to any interested party with no licensing requirements. Therefore, it is
permissible to distribute this software as a free download from the internet.
Disclaimer:
This software and/or related materials was developed to promote biometric
standards and biometric technology testing for the Federal Government
in accordance with the USA PATRIOT Act and the Enhanced Border Security
and Visa Entry Reform Act. Specific hardware and software products identified
in this software were used in order to perform the software development.
In no case does such identification imply recommendation or endorsement
by the National Institute of Standards and Technology, nor does it imply that
the products and equipment identified are necessarily the best available
for the purpose.
This software and/or related materials are provided "AS-IS" without warranty
of any kind including NO WARRANTY OF PERFORMANCE, MERCHANTABILITY,
NO WARRANTY OF NON-INFRINGEMENT OF ANY 3RD PARTY INTELLECTUAL PROPERTY
or FITNESS FOR A PARTICULAR PURPOSE or for any purpose whatsoever, for the
licensed product, however used. In no event shall NIST be liable for any
damages and/or costs, including but not limited to incidental or consequential
damages of any kind, including economic damage or injury to property and lost
profits, regardless of whether NIST shall be advised, have reason to know,
or in fact shall know of the possibility.
By using this software, you agree to bear all risk relating to quality,
use and performance of the software and/or related materials. You agree
to hold the Government harmless from any claim arising from your use
of the software.
*******************************************************************************/
#ifndef _MYTIME_H
#define _MYTIME_H
/* this file needed to support timer and ticks */
/* UPDATED: 03/16/2005 by MDG */
#ifdef TIMER
#include <sys/types.h>
#endif
#ifdef __MSYS__
#include <sys/time.h>
#else
#include <sys/times.h>
#endif
#ifdef TIMER
#define set_timer(_timer_); \
{ \
_timer_ = ticks();
#else
#define set_timer(_timer_);
#endif
#ifdef TIMER
#define time_accum(_timer_, _var_); \
_var_ += (ticks() - _timer_)/(float)ticksPerSec(); \
}
#else
#define time_accum(_timer_, _var_);
#endif
#ifdef TIMER
#define print_time(_fp_, _fmt_, _var_); \
fprintf(_fp_, _fmt_, _var_);
#else
#define print_time(_fp_, _fmt_, _var_);
#endif
extern clock_t ticks(void);
extern int ticksPerSec(void);
extern clock_t total_timer;
extern float total_time;
extern clock_t imap_timer;
extern float imap_time;
extern clock_t bin_timer;
extern float bin_time;
extern clock_t minutia_timer;
extern float minutia_time;
extern clock_t rm_minutia_timer;
extern float rm_minutia_time;
extern clock_t ridge_count_timer;
extern float ridge_count_time;
#endif

View File

@@ -1,26 +1,47 @@
/*******************************************************************************
License:
This software was developed at the National Institute of Standards and
Technology (NIST) by employees of the Federal Government in the course
of their official duties. Pursuant to title 17 Section 105 of the
United States Code, this software is not subject to copyright protection
and is in the public domain. NIST assumes no responsibility whatsoever for
its use by other parties, and makes no guarantees, expressed or implied,
about its quality, reliability, or any other characteristic.
License:
This software and/or related materials was developed at the National Institute
of Standards and Technology (NIST) by employees of the Federal Government
in the course of their official duties. Pursuant to title 17 Section 105
of the United States Code, this software is not subject to copyright
protection and is in the public domain.
Disclaimer:
This software was developed to promote biometric standards and biometric
technology testing for the Federal Government in accordance with the USA
PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act.
Specific hardware and software products identified in this software were used
in order to perform the software development. In no case does such
identification imply recommendation or endorsement by the National Institute
of Standards and Technology, nor does it imply that the products and equipment
identified are necessarily the best available for the purpose.
This software and/or related materials have been determined to be not subject
to the EAR (see Part 734.3 of the EAR for exact details) because it is
a publicly available technology and software, and is freely distributed
to any interested party with no licensing requirements. Therefore, it is
permissible to distribute this software as a free download from the internet.
Disclaimer:
This software and/or related materials was developed to promote biometric
standards and biometric technology testing for the Federal Government
in accordance with the USA PATRIOT Act and the Enhanced Border Security
and Visa Entry Reform Act. Specific hardware and software products identified
in this software were used in order to perform the software development.
In no case does such identification imply recommendation or endorsement
by the National Institute of Standards and Technology, nor does it imply that
the products and equipment identified are necessarily the best available
for the purpose.
This software and/or related materials are provided "AS-IS" without warranty
of any kind including NO WARRANTY OF PERFORMANCE, MERCHANTABILITY,
NO WARRANTY OF NON-INFRINGEMENT OF ANY 3RD PARTY INTELLECTUAL PROPERTY
or FITNESS FOR A PARTICULAR PURPOSE or for any purpose whatsoever, for the
licensed product, however used. In no event shall NIST be liable for any
damages and/or costs, including but not limited to incidental or consequential
damages of any kind, including economic damage or injury to property and lost
profits, regardless of whether NIST shall be advised, have reason to know,
or in fact shall know of the possibility.
By using this software, you agree to bear all risk relating to quality,
use and performance of the software and/or related materials. You agree
to hold the Government harmless from any claim arising from your use
of the software.
*******************************************************************************/
#ifndef _SUNRAST_H
#define _SUNRAST_H

View File

@@ -0,0 +1,58 @@
--- 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 <math.h>
#include <stdio.h>
-#include <an2k.h> /* Needed by to_type9.c */
+#include <fp_internal.h>
/*************************************************************************/
/* OUTPUT FILE EXTENSIONS */
@@ -154,26 +131,8 @@ typedef struct rotgrids{
#define DISAPPEARING 0
#define APPEARING 1
-typedef struct 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;
-} MINUTIA;
-
-typedef struct minutiae{
- int alloc;
- int num;
- MINUTIA **list;
-} MINUTIAE;
+typedef struct fp_minutia MINUTIA;
+typedef struct fp_minutiae MINUTIAE;
typedef struct feature_pattern{
int type;
@@ -1185,17 +1185,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);
-/* to_type9.c */
-extern int minutiae2type_9(RECORD **, const int, MINUTIAE *, const int,
- const int, const double);
-extern int mintiae2field_12(FIELD **, MINUTIAE *, const int, const int,
- const double);
-
-/* update.c */
-extern int update_ANSI_NIST_lfs_results(ANSI_NIST *, MINUTIAE *,
- unsigned char *, const int, const int,
- const int, const double, const int, const int);
-
/* util.c */
extern int maxv(const int *, const int);
extern int minv(const int *, const int);

View File

@@ -1,26 +1,47 @@
/*******************************************************************************
License:
This software was developed at the National Institute of Standards and
Technology (NIST) by employees of the Federal Government in the course
of their official duties. Pursuant to title 17 Section 105 of the
United States Code, this software is not subject to copyright protection
and is in the public domain. NIST assumes no responsibility whatsoever for
its use by other parties, and makes no guarantees, expressed or implied,
about its quality, reliability, or any other characteristic.
License:
This software and/or related materials was developed at the National Institute
of Standards and Technology (NIST) by employees of the Federal Government
in the course of their official duties. Pursuant to title 17 Section 105
of the United States Code, this software is not subject to copyright
protection and is in the public domain.
Disclaimer:
This software was developed to promote biometric standards and biometric
technology testing for the Federal Government in accordance with the USA
PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act.
Specific hardware and software products identified in this software were used
in order to perform the software development. In no case does such
identification imply recommendation or endorsement by the National Institute
of Standards and Technology, nor does it imply that the products and equipment
identified are necessarily the best available for the purpose.
This software and/or related materials have been determined to be not subject
to the EAR (see Part 734.3 of the EAR for exact details) because it is
a publicly available technology and software, and is freely distributed
to any interested party with no licensing requirements. Therefore, it is
permissible to distribute this software as a free download from the internet.
Disclaimer:
This software and/or related materials was developed to promote biometric
standards and biometric technology testing for the Federal Government
in accordance with the USA PATRIOT Act and the Enhanced Border Security
and Visa Entry Reform Act. Specific hardware and software products identified
in this software were used in order to perform the software development.
In no case does such identification imply recommendation or endorsement
by the National Institute of Standards and Technology, nor does it imply that
the products and equipment identified are necessarily the best available
for the purpose.
This software and/or related materials are provided "AS-IS" without warranty
of any kind including NO WARRANTY OF PERFORMANCE, MERCHANTABILITY,
NO WARRANTY OF NON-INFRINGEMENT OF ANY 3RD PARTY INTELLECTUAL PROPERTY
or FITNESS FOR A PARTICULAR PURPOSE or for any purpose whatsoever, for the
licensed product, however used. In no event shall NIST be liable for any
damages and/or costs, including but not limited to incidental or consequential
damages of any kind, including economic damage or injury to property and lost
profits, regardless of whether NIST shall be advised, have reason to know,
or in fact shall know of the possibility.
By using this software, you agree to bear all risk relating to quality,
use and performance of the software and/or related materials. You agree
to hold the Government harmless from any claim arising from your use
of the software.
*******************************************************************************/
/***********************************************************************
LIBRARY: LFS - NIST Latent Fingerprint System
@@ -36,16 +57,44 @@ identified are necessarily the best available for the purpose.
***********************************************************************
ROUTINES:
binarize()
binarize_V2()
binarize_image()
binarize_image_V2()
dirbinarize()
isobinarize()
***********************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <lfs.h>
/*************************************************************************
**************************************************************************
#cat: binarize - Takes a padded grayscale input image and its associated ridge
#cat: direction flow NMAP and produces a binarized version of the
#cat: image. It then fills horizontal and vertical "holes" in the
#cat: binary image results.
Input:
pdata - padded input grayscale image
pw - padded width (in pixels) of input image
ph - padded height (in pixels) of input image
nmap - 2-D vector of IMAP directions and other codes
mw - width (in blocks) of the NMAP
mh - height (in blocks) of the NMAP
dirbingrids - set of rotated grid offsets used for directional
binarization
lfsparms - parameters and thresholds for controlling LFS
Output:
optr - points to created (unpadded) binary image
ow - width of binary image
oh - height of binary image
Return Code:
Zero - successful completion
Negative - system error
**************************************************************************/
/*************************************************************************
**************************************************************************
#cat: binarize_V2 - Takes a padded grayscale input image and its associated
@@ -101,6 +150,32 @@ int binarize_V2(unsigned char **odata, int *ow, int *oh,
return(0);
}
/*************************************************************************
**************************************************************************
#cat: binarize_image - Takes a grayscale input image and its associated
#cat: NMAP and generates a binarized version of the image.
Input:
pdata - padded input grayscale image
pw - padded width (in pixels) of input image
ph - padded height (in pixels) of input image
nmap - 2-D vector of IMAP directions and other codes
mw - width (in blocks) of the NMAP
mh - height (in blocks) of the NMAP
imap_blocksize - dimension (in pixels) of each NMAP block
dirbingrids - set of rotated grid offsets used for directional
binarization
isobin_grid_dim - dimension (in pixels) of grid used for isotropic
binarization
Output:
optr - points to binary image results
ow - points to binary image width
oh - points to binary image height
Return Code:
Zero - successful completion
Negative - system error
**************************************************************************/
/*************************************************************************
**************************************************************************
#cat: binarize_image_V2 - Takes a grayscale input image and its associated
@@ -247,3 +322,27 @@ int dirbinarize(const unsigned char *pptr, const int idir,
return(WHITE_PIXEL);
}
/*************************************************************************
**************************************************************************
#cat: isobinarize - Determines the binary value of a grayscale pixel based
#cat: on comparing the grayscale value with a surrounding
#cat: neighborhood grid of pixels. If the current pixel (treated
#cat: as an average) is less than the sum of the pixels in
#cat: the neighborhood, then the binary value is set to BLACK,
#cat: otherwise it is set to WHITE. This binarization technique
#cat: is used when there is no VALID IMAP direction for the
#cat: block in which the current pixel resides.
CAUTION: The image to which the input pixel points must be appropriately
padded to account for the radius of the neighborhood. Otherwise,
this routine may access "unkown" memory.
Input:
pptr - pointer to curent grayscale pixel
pw - padded width (in pixels) of the grayscale image
ph - padded height (in pixels) of the grayscale image
isobin_grid_dim - dimension (in pixels) of the neighborhood
Return Code:
BLACK_PIXEL - pixel intensity for BLACK
WHITE_PIXEL - pixel intensity of WHITE
**************************************************************************/

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