Compare commits

..

271 Commits

Author SHA1 Message Date
Benjamin Berg
88cd932203 fixup! Simplify Synaptics driver
Ignore zreo format length warning from GCC
2019-06-12 14:55:16 +02:00
Benjamin Berg
e85b607965 fixup! Simplify Synaptics driver
Remove invalid cast to (void*) from usb_check_interrupt returns
2019-06-12 14:55:11 +02:00
Benjamin Berg
40a298f43b fixup! Simplify Synaptics driver
missing BMKT_SUCCESS return in usb_check_interrupt
2019-06-12 14:55:06 +02:00
Benjamin Berg
f8eb329a65 fixup! Simplify Synaptics driver
??? Remove set but not used variable

This discards the return value from bmkt_sensor_handle_response, should
there be some sort of error handling there (e.g. printing a warning)?
2019-06-12 14:55:01 +02:00
Benjamin Berg
eb7edc43b8 fixup! Simplify Synaptics driver
Remove unused variables from usb_transport.c
2019-06-12 14:54:55 +02:00
Benjamin Berg
ebff2518ad fixup! Simplify Synaptics driver
remove unused cancel_resp function from synaptics.c
2019-06-12 14:54:50 +02:00
Benjamin Berg
445d46fb6f fixup! Simplify Synaptics driver
Remove unused variables in synaptics.c
2019-06-12 14:54:45 +02:00
Benjamin Berg
477df2a861 fixup! Simplify Synaptics driver
Remove "for (;;)" loop that never looped

It would either return or break at the end, so just remove the loop, it
is not needed.
2019-06-12 14:54:38 +02:00
Benjamin Berg
e4bac112aa fixup! Simplify Synaptics driver
This contains the following changes:
 * Remove the subdirectories for src/include
 * Drop the include directory logic from the build
   (not needed anymore with above, and it was also broken when
   the synaptics driver was not enabled)
2019-06-12 14:54:32 +02:00
Vincent Huang
4c42a090f7 Simplify Synaptics driver 2019-06-12 14:46:23 +02:00
Vincent Huang
65483d51b7 Add function to delete data in sensor.
Add example test app to test delete function.
  Remove sync database function in Synaptics driver.
2019-06-12 14:46:23 +02:00
Vincent Huang
e513848871 Add Synaptics driver 2019-06-12 14:46:23 +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
Bastien Nocera
da95af0f48 0.8.2 2018-07-17 13:48:13 +02:00
Bastien Nocera
28b6f643d8 Merge branch 'wip/hadess/downgrade-assert-2' into 'master'
Another assert downgrade

See merge request libfprint/libfprint!7
2018-07-17 11:47:10 +00:00
Bastien Nocera
22277c7277 build: Downgrade meson in CI script
It failed to finish the build otherwise:
https://github.com/mesonbuild/meson/issues/3892
2018-07-17 13:43:00 +02:00
Bastien Nocera
19e7b217c1 lib: Downgrade fp_err() to be non-fatal
Similarly to b1ac865abd, downgrade
fp_err() to be non-fatal. A number of drivers would spit out an error
when encountering this call, but not crash, carry on and most of the
time recover.

Make sure we don't assert in those cases.
2018-07-16 16:08:54 +02:00
Bastien Nocera
29d3541b74 lib: Downgrade BUG* assertions to work-around crashes #2
Same as b1ac865abd but for the drivers
API.
2018-07-16 16:07:25 +02:00
Bastien Nocera
b9e5b3a55c Merge branch 'wip/hadess/downgrade-assert' into 'master'
lib: Downgrade BUG* assertions to work-around crashes

Closes #77

See merge request libfprint/libfprint!6
2018-07-03 09:44:56 +00:00
Bastien Nocera
b1ac865abd lib: Downgrade BUG* assertions to work-around crashes
BUG() and BUG_ON() didn't use to assert, but only print an error if
debugging was enabled. This was hiding a lot of state bugs in drivers,
and transforming those into assertions causes crashes.

Downgrade the assertion to only print a warning, and hope that those
eventually get fixed in the drivers so we can re-enable them.

Closes: #77
2018-07-03 11:40:25 +02:00
Bastien Nocera
21504c0621 Merge branch 'wip/hadess/poll-retval' into 'master'
poll: Fix fp_get_pollfds retval type

See merge request libfprint/libfprint!5
2018-06-26 13:18:40 +00:00
Bastien Nocera
056ea541dd poll: Fix fp_get_pollfds retval type
fp_get_pollfds() is supposed to return a negative value on failure, but
size_t is an unsigned integer. Use ssize_t instead.
2018-06-26 14:53:53 +02:00
Bastien Nocera
871fddf5fb Merge branch 'wip/hadess/more-upekts-statuses' into 'master'
upekts: Fix enrollment never finishing on some upekts devices

See merge request libfprint/libfprint!3
2018-06-20 17:16:08 +00:00
Bastien Nocera
c284858d06 upekts: Fix enrollment never finishing on some upekts devices
Add support for more device status codes, brought back from the
now-removed UPEKE2 driver.

See 3bf55a3e07/libfprint/drivers/upeke2.c (L1013)
2018-06-19 11:11:04 +02:00
Bastien Nocera
bb4d888661 elan: Fix typo in comment 2018-06-18 18:07:24 +02:00
Bastien Nocera
ff77cfc9b5 doc: Update more website links 2018-06-18 14:56:40 +02:00
Bastien Nocera
80f91ecb7b Merge branch 'master' into 'master'
elan: Add USB ID for TNP Nano USB Fingerprint Reader (04f3:0c26)

See merge request libfprint/libfprint!1
2018-06-13 20:09:47 +00:00
Corentin Noël
6cb77465ab elan: Add USB ID for TNP Nano USB Fingerprint Reader (04f3:0c26)
The device works without any additional changes to the driver.

https://www.amazon.co.uk/gp/product/B075955HY7/
2018-06-13 20:22:29 +01:00
Bastien Nocera
6f6127cbb6 0.8.1 2018-06-12 16:05:45 +02:00
Bastien Nocera
e1d85fb636 build: Install udev rules in correct directory
The udevdir variable in udev.pc might not have a trailing slash.
2018-06-12 16:03:34 +02:00
140 changed files with 14695 additions and 8295 deletions

View File

@@ -1,20 +1,64 @@
image: fedora:rawhide image: fedora:rawhide
stages: stages:
- build - build
- test
variables: variables:
DEPENDENCIES: libusb1-devel glib2-devel nss-devel pixman-devel systemd meson gtk-doc 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"
.build_one_driver_template: &build_one_driver
before_script:
- dnf update -y --nogpgcheck && dnf install -y --nogpgcheck $DEPENDENCIES
build:
stage: build
script: 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
- ninja -C _build install - 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

35
NEWS
View File

@@ -1,6 +1,41 @@
This file lists notable changes in each release. For the full history of all This file lists notable changes in each release. For the full history of all
changes, see ChangeLog. changes, see ChangeLog.
2018-12-14: v0.99.0 release
* Library:
- All the internal API for device driver writers is now covered by the
documentation and has been enhanced to make it easier to write drivers
- Update internal NBIS fingerprint data processing library to one that's
nearly 10 years newer
- Re-add accessor for minutia coordinates which was used in the very
old fprint_demo program, but also by our new GTK+ test program (see below)
- Fix a crash when too many minutiae were detected in a capture
* Drivers:
- Support more devices in the Elan driver, stability improvements
* Tools:
- Add a test GTK+ application that will eventually be used for testing
drivers without modifying the OS installed version. Note that this
application currently requires manually changing permissions of USB
devices, this will be fixed when the infrastructure exists to access
those devices without additional permissions, as a normal user.
2018-07-15: v0.8.2 release
* Drivers:
- Add USB ID for TNP Nano USB Fingerprint Reader
- Fix UPEKTS enrollment never finishing on some devices
* Library:
- Fix fp_get_pollfds() retval type, a small ABI change
- Downgrade fatal errors to run-time warnings, as a number of drivers
used to throw silent errors and we made them fatal. Those will now
be visible warnings, hopefully helping with fixing them.
2018-06-12: v0.8.1 release
- Brown paperbag release to install the udev rules file in the correct
directory if the udev pkg-config file doesn't have a trailing slash
2018-06-12: v0.8.0 release 2018-06-12: v0.8.0 release
- Port to meson as the build system - Port to meson as the build system
- Port documentation to gtk-doc - Port documentation to gtk-doc

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, determined that it is fine to ship bozorth3 in an open source project,
see https://fprint.freedesktop.org/us-export-control.html 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

@@ -11,7 +11,7 @@
<para>This document is the API reference for the libfprint library.</para> <para>This document is the API reference for the libfprint library.</para>
<para> <para>
The latest version of libfprint, as well as the latest version of The latest version of libfprint, as well as the latest version of
this API reference, is <ulink role="online-location" url="https://www.freedesktop.org/wiki/Software/fprint/libfprint/">available online</ulink>. this API reference, is <ulink role="online-location" url="https://fprint.freedesktop.org/libfprint-dev/">available online</ulink>.
</para> </para>
</releaseinfo> </releaseinfo>
</bookinfo> </bookinfo>
@@ -24,7 +24,7 @@
</part> </part>
<part> <part>
<title>API Documentation</title> <title>Library API Documentation</title>
<xi:include href="xml/events.xml"/> <xi:include href="xml/events.xml"/>
<xi:include href="xml/discovery.xml"/> <xi:include href="xml/discovery.xml"/>
@@ -36,11 +36,31 @@
<xi:include href="xml/img.xml"/> <xi:include href="xml/img.xml"/>
</part> </part>
<!--
<part> <part>
<title>Writing Drivers</title> <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> </part>
-->
<index id="api-index"> <index id="api-index">
<title>API Index</title> <title>API Index</title>

View File

@@ -1,8 +1,9 @@
<INCLUDE>fprint.h</INCLUDE>
<SECTION> <SECTION>
<INCLUDE>fprint.h</INCLUDE>
<FILE>events</FILE> <FILE>events</FILE>
<TITLE>Initialisation and events handling</TITLE> <TITLE>Initialisation and events handling</TITLE>
LIBFPRINT_DEPRECATED
fp_set_debug fp_set_debug
fp_init fp_init
fp_exit fp_exit
@@ -17,6 +18,7 @@ fp_set_pollfd_notifiers
</SECTION> </SECTION>
<SECTION> <SECTION>
<INCLUDE>fprint.h</INCLUDE>
<FILE>discovery</FILE> <FILE>discovery</FILE>
<TITLE>Device discovery</TITLE> <TITLE>Device discovery</TITLE>
fp_dscv_dev fp_dscv_dev
@@ -32,15 +34,18 @@ fp_dscv_dev_for_dscv_print
</SECTION> </SECTION>
<SECTION> <SECTION>
<INCLUDE>fprint.h</INCLUDE>
<FILE>drv</FILE> <FILE>drv</FILE>
fp_driver fp_driver
fp_driver_get_name fp_driver_get_name
fp_driver_get_full_name fp_driver_get_full_name
fp_driver_get_driver_id fp_driver_get_driver_id
fp_driver_get_scan_type fp_driver_get_scan_type
fp_driver_supports_imaging
</SECTION> </SECTION>
<SECTION> <SECTION>
<INCLUDE>fprint.h</INCLUDE>
<FILE>dev</FILE> <FILE>dev</FILE>
fp_dev fp_dev
fp_scan_type fp_scan_type
@@ -91,10 +96,10 @@ fp_async_capture_stop
</SECTION> </SECTION>
<SECTION> <SECTION>
<INCLUDE>fprint.h</INCLUDE>
<FILE>print_data</FILE> <FILE>print_data</FILE>
fp_finger fp_finger
fp_print_data fp_print_data
fp_print_data
fp_print_data_get_data fp_print_data_get_data
fp_print_data_from_data fp_print_data_from_data
fp_print_data_save fp_print_data_save
@@ -107,6 +112,7 @@ fp_print_data_get_devtype
</SECTION> </SECTION>
<SECTION> <SECTION>
<INCLUDE>fprint.h</INCLUDE>
<FILE>dscv_print</FILE> <FILE>dscv_print</FILE>
fp_dscv_print fp_dscv_print
fp_discover_prints fp_discover_prints
@@ -118,6 +124,7 @@ fp_dscv_print_delete
</SECTION> </SECTION>
<SECTION> <SECTION>
<INCLUDE>fprint.h</INCLUDE>
<FILE>img</FILE> <FILE>img</FILE>
fp_img fp_img
fp_minutia fp_minutia
@@ -129,8 +136,136 @@ fp_img_save_to_file
fp_img_standardize fp_img_standardize
fp_img_binarize fp_img_binarize
fp_img_get_minutiae fp_img_get_minutiae
fp_minutia_get_coords
</SECTION> </SECTION>
<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> </SECTION>

View File

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

View File

@@ -1,10 +1,10 @@
ent_conf = configuration_data() ent_conf = configuration_data()
ent_conf.set('PACKAGE', 'libfprint') ent_conf.set('PACKAGE', 'libfprint')
ent_conf.set('PACKAGE_BUGREPORT', 'https://bugs.freedesktop.org/enter_bug.cgi?product=libfprint') ent_conf.set('PACKAGE_BUGREPORT', 'https://gitlab.freedesktop.org/libfprint/libfprint/issues')
ent_conf.set('PACKAGE_NAME', 'libfprint') ent_conf.set('PACKAGE_NAME', 'libfprint')
ent_conf.set('PACKAGE_STRING', 'libfprint') ent_conf.set('PACKAGE_STRING', 'libfprint')
ent_conf.set('PACKAGE_TARNAME', 'libfprint-' + meson.project_version()) ent_conf.set('PACKAGE_TARNAME', 'libfprint-' + meson.project_version())
ent_conf.set('PACKAGE_URL', 'https://www.freedesktop.org/wiki/Software/fprint/libfprint/') ent_conf.set('PACKAGE_URL', 'https://fprint.freedesktop.org/')
ent_conf.set('PACKAGE_VERSION', meson.project_version()) ent_conf.set('PACKAGE_VERSION', meson.project_version())
ent_conf.set('PACKAGE_API_VERSION', '1.0') ent_conf.set('PACKAGE_API_VERSION', '1.0')
configure_file(input: 'gtkdocentities.ent.in', output: 'gtkdocentities.ent', configuration: ent_conf) configure_file(input: 'gtkdocentities.ent.in', output: 'gtkdocentities.ent', configuration: ent_conf)

115
examples/delete.c Normal file
View File

@@ -0,0 +1,115 @@
/*
* Example fingerprint delete finger program, which delete the right index
* finger which has been previously enrolled to disk.
* Copyright (C) 2019 Synaptics Inc
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <libfprint/fprint.h>
struct fp_dscv_dev *discover_device(struct fp_dscv_dev **discovered_devs)
{
struct fp_dscv_dev *ddev = discovered_devs[0];
struct fp_driver *drv;
if (!ddev)
return NULL;
drv = fp_dscv_dev_get_driver(ddev);
printf("Found device claimed by %s driver\n", fp_driver_get_full_name(drv));
return ddev;
}
int main(void)
{
int r = 1;
struct fp_dscv_dev *ddev;
struct fp_dscv_dev **discovered_devs;
struct fp_dev *dev;
struct fp_print_data *data;
setenv ("G_MESSAGES_DEBUG", "all", 0);
setenv ("LIBUSB_DEBUG", "3", 0);
r = fp_init();
if (r < 0) {
fprintf(stderr, "Failed to initialize libfprint\n");
exit(1);
}
discovered_devs = fp_discover_devs();
if (!discovered_devs) {
fprintf(stderr, "Could not discover devices\n");
goto out;
}
ddev = discover_device(discovered_devs);
if (!ddev) {
fprintf(stderr, "No devices detected.\n");
goto out;
}
dev = fp_dev_open(ddev);
fp_dscv_devs_free(discovered_devs);
if (!dev) {
fprintf(stderr, "Could not open device.\n");
goto out;
}
printf("Opened device. Loading previously enrolled right index finger "
"data...\n");
r = fp_print_data_load(dev, RIGHT_INDEX, &data);
if (r != 0) {
fprintf(stderr, "Failed to load fingerprint, error %d\n", r);
fprintf(stderr, "Did you remember to enroll your right index finger "
"first?\n");
goto out_close;
}
printf("Print loaded. delete data in sensor.\n");
if(!fp_dev_supports_data_in_sensor(dev))
{
printf("This driver doesn't support to store data in sensor.\n");
goto out_close;
}
r = fp_delete_finger(dev, data);
fp_print_data_free(data);
if (r) {
printf("delete finger failed with error %d :(\n", r);
}
else
{
printf("sensor data deleted. now delete host data");
r = fp_print_data_delete(dev, RIGHT_INDEX);
if (r < 0) {
printf("Delete sensor data successfully but delete host data failed. %d :(\n", r);
}
}
out_close:
fp_dev_close(dev);
out:
fp_exit();
return r;
}

View File

@@ -45,8 +45,7 @@ struct fp_print_data *enroll(struct fp_dev *dev) {
do { do {
struct fp_img *img = NULL; struct fp_img *img = NULL;
sleep(1);
printf("\nScan your finger now.\n"); printf("\nScan your finger now.\n");
r = fp_enroll_finger_img(dev, &enrolled_print, &img); r = fp_enroll_finger_img(dev, &enrolled_print, &img);
@@ -143,7 +142,10 @@ int main(void)
if (!data) if (!data)
goto out_close; goto out_close;
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
r = fp_print_data_save(data, RIGHT_INDEX); r = fp_print_data_save(data, RIGHT_INDEX);
#pragma GCC diagnostic pop
if (r < 0) if (r < 0)
fprintf(stderr, "Data save failed, code %d\n", r); fprintf(stderr, "Data save failed, code %d\n", r);

View File

@@ -1,5 +1,5 @@
examples = [ 'verify_live', 'enroll', 'verify', 'img_capture' ] examples = [ 'verify_live', 'enroll', 'verify', 'img_capture', 'delete' ]
foreach example: examples foreach example: examples
executable(example, executable(example,
example + '.c', example + '.c',

View File

@@ -117,7 +117,10 @@ int main(void)
printf("Opened device. Loading previously enrolled right index finger " printf("Opened device. Loading previously enrolled right index finger "
"data...\n"); "data...\n");
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
r = fp_print_data_load(dev, RIGHT_INDEX, &data); r = fp_print_data_load(dev, RIGHT_INDEX, &data);
#pragma GCC diagnostic pop
if (r != 0) { if (r != 0) {
fprintf(stderr, "Failed to load fingerprint, error %d\n", r); fprintf(stderr, "Failed to load fingerprint, error %d\n", r);
fprintf(stderr, "Did you remember to enroll your right index finger " fprintf(stderr, "Did you remember to enroll your right index finger "

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)); "complete the process.\n", fp_dev_get_nr_enroll_stages(dev));
do { do {
sleep(1);
printf("\nScan your finger now.\n"); printf("\nScan your finger now.\n");
r = fp_enroll_finger(dev, &enrolled_print); r = fp_enroll_finger(dev, &enrolled_print);
if (r < 0) { if (r < 0) {

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 BULK_TIMEOUT 4000
#define FINGER_DETECTION_LEN 19
#define STRIP_CAPTURE_LEN 665
/* /*
* The AES1610 is an imaging device using a swipe-type sensor. It samples * The AES1610 is an imaging device using a swipe-type sensor. It samples
* the finger at preprogrammed intervals, sending a 128x8 frame to the * the finger at preprogrammed intervals, sending a 128x8 frame to the
@@ -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 */ /* check that read succeeded but ignore all data */
static void generic_ignore_data_cb(struct libusb_transfer *transfer) static void generic_ignore_data_cb(struct libusb_transfer *transfer)
{ {
struct fpi_ssm *ssm = transfer->user_data; fpi_ssm *ssm = transfer->user_data;
if (transfer->status != LIBUSB_TRANSFER_COMPLETED) if (transfer->status != LIBUSB_TRANSFER_COMPLETED)
fpi_ssm_mark_aborted(ssm, -EIO); fpi_ssm_mark_failed(ssm, -EIO);
else if (transfer->length != transfer->actual_length) else if (transfer->length != transfer->actual_length)
fpi_ssm_mark_aborted(ssm, -EPROTO); fpi_ssm_mark_failed(ssm, -EPROTO);
else else
fpi_ssm_next_state(ssm); fpi_ssm_next_state(ssm);
@@ -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, static void generic_write_regv_cb(struct fp_img_dev *dev, int result,
void *user_data) void *user_data)
{ {
struct fpi_ssm *ssm = user_data; fpi_ssm *ssm = user_data;
if (result == 0) if (result == 0)
fpi_ssm_next_state(ssm); fpi_ssm_next_state(ssm);
else else
fpi_ssm_mark_aborted(ssm, result); fpi_ssm_mark_failed(ssm, result);
} }
/* read the specified number of bytes from the IN endpoint but throw them /* read the specified number of bytes from the IN endpoint but throw them
* away, then increment the SSM */ * away, then increment the SSM */
static void generic_read_ignore_data(struct fpi_ssm *ssm, size_t bytes) static void generic_read_ignore_data(fpi_ssm *ssm, struct fp_dev *dev, size_t bytes)
{ {
struct libusb_transfer *transfer = libusb_alloc_transfer(0); struct libusb_transfer *transfer = fpi_usb_alloc();
unsigned char *data; unsigned char *data;
struct fp_dev *dev;
int r; int r;
if (!transfer) {
fpi_ssm_mark_aborted(ssm, -ENOMEM);
return;
}
data = g_malloc(bytes); 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, libusb_fill_bulk_transfer(transfer, fpi_dev_get_usb_dev(dev), EP_IN, data, bytes,
generic_ignore_data_cb, ssm, BULK_TIMEOUT); generic_ignore_data_cb, ssm, BULK_TIMEOUT);
@@ -147,7 +143,7 @@ static void generic_read_ignore_data(struct fpi_ssm *ssm, size_t bytes)
if (r < 0) { if (r < 0) {
g_free(data); g_free(data);
libusb_free_transfer(transfer); libusb_free_transfer(transfer);
fpi_ssm_mark_aborted(ssm, r); fpi_ssm_mark_failed(ssm, r);
} }
} }
@@ -226,14 +222,9 @@ static void finger_det_reqs_cb(struct fp_img_dev *dev, int result, void *user_da
return; return;
} }
transfer = libusb_alloc_transfer(0); transfer = fpi_usb_alloc();
if (!transfer) { data = g_malloc(FINGER_DETECTION_LEN);
fpi_imgdev_session_error(dev, -ENOMEM); libusb_fill_bulk_transfer(transfer, fpi_dev_get_usb_dev(FP_DEV(dev)), EP_IN, data, FINGER_DETECTION_LEN,
return;
}
data = g_malloc(19);
libusb_fill_bulk_transfer(transfer, fpi_imgdev_get_usb_dev(dev), EP_IN, data, 19,
finger_det_data_cb, dev, BULK_TIMEOUT); finger_det_data_cb, dev, BULK_TIMEOUT);
r = libusb_submit_transfer(transfer); 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) 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) { if (aesdev->deactivating) {
complete_deactivation(dev); complete_deactivation(dev);
@@ -557,17 +548,17 @@ enum capture_states {
static void capture_read_strip_cb(struct libusb_transfer *transfer) static void capture_read_strip_cb(struct libusb_transfer *transfer)
{ {
unsigned char *stripdata; 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 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; unsigned char *data = transfer->buffer;
int sum, i; int sum, i;
if (transfer->status != LIBUSB_TRANSFER_COMPLETED) { if (transfer->status != LIBUSB_TRANSFER_COMPLETED) {
fpi_ssm_mark_aborted(ssm, -EIO); fpi_ssm_mark_failed(ssm, -EIO);
goto out; goto out;
} else if (transfer->length != transfer->actual_length) { } else if (transfer->length != transfer->actual_length) {
fpi_ssm_mark_aborted(ssm, -EPROTO); fpi_ssm_mark_failed(ssm, -EPROTO);
goto out; goto out;
} }
@@ -594,7 +585,7 @@ static void capture_read_strip_cb(struct libusb_transfer *transfer)
} }
if (sum < 0) { if (sum < 0) {
fpi_ssm_mark_aborted(ssm, sum); fpi_ssm_mark_failed(ssm, sum);
goto out; goto out;
} }
fp_dbg("sum=%d", sum); fp_dbg("sum=%d", sum);
@@ -643,10 +634,10 @@ out:
libusb_free_transfer(transfer); 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;
struct aes1610_dev *aesdev = fpi_imgdev_get_user_data(dev); struct aes1610_dev *aesdev = FP_INSTANCE_DATA(_dev);
int r; int r;
switch (fpi_ssm_get_cur_state(ssm)) { switch (fpi_ssm_get_cur_state(ssm)) {
@@ -657,7 +648,7 @@ static void capture_run_state(struct fpi_ssm *ssm)
break; break;
case CAPTURE_READ_DATA: case CAPTURE_READ_DATA:
fp_dbg("read data"); fp_dbg("read data");
generic_read_ignore_data(ssm, 665); generic_read_ignore_data(ssm, _dev, STRIP_CAPTURE_LEN);
break; break;
case CAPTURE_REQUEST_STRIP: case CAPTURE_REQUEST_STRIP:
fp_dbg("request strip"); fp_dbg("request strip");
@@ -668,32 +659,27 @@ static void capture_run_state(struct fpi_ssm *ssm)
generic_write_regv_cb, ssm); generic_write_regv_cb, ssm);
break; break;
case CAPTURE_READ_STRIP: ; case CAPTURE_READ_STRIP: ;
struct libusb_transfer *transfer = libusb_alloc_transfer(0); struct libusb_transfer *transfer = fpi_usb_alloc();
unsigned char *data; unsigned char *data;
if (!transfer) { data = g_malloc(STRIP_CAPTURE_LEN);
fpi_ssm_mark_aborted(ssm, -ENOMEM); libusb_fill_bulk_transfer(transfer, fpi_dev_get_usb_dev(FP_DEV(dev)), EP_IN, data, STRIP_CAPTURE_LEN,
break;
}
data = g_malloc(665);
libusb_fill_bulk_transfer(transfer, fpi_imgdev_get_usb_dev(dev), EP_IN, data, 665,
capture_read_strip_cb, ssm, BULK_TIMEOUT); capture_read_strip_cb, ssm, BULK_TIMEOUT);
r = libusb_submit_transfer(transfer); r = libusb_submit_transfer(transfer);
if (r < 0) { if (r < 0) {
g_free(data); g_free(data);
libusb_free_transfer(transfer); libusb_free_transfer(transfer);
fpi_ssm_mark_aborted(ssm, r); fpi_ssm_mark_failed(ssm, r);
} }
break; 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 fp_img_dev *dev = user_data;
struct aes1610_dev *aesdev = fpi_imgdev_get_user_data(dev); struct aes1610_dev *aesdev = FP_INSTANCE_DATA(_dev);
G_DEBUG_HERE(); G_DEBUG_HERE();
if (aesdev->deactivating) 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) static void start_capture(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));
struct fpi_ssm *ssm; fpi_ssm *ssm;
if (aesdev->deactivating) { if (aesdev->deactivating) {
complete_deactivation(dev); complete_deactivation(dev);
return; 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(); G_DEBUG_HERE();
fpi_ssm_set_user_data(ssm, dev);
fpi_ssm_start(ssm, capture_sm_complete); fpi_ssm_start(ssm, capture_sm_complete);
} }
@@ -738,9 +723,9 @@ enum activate_states {
ACTIVATE_NUM_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 */ /* activation on aes1610 seems much more straightforward compared to aes2501 */
/* verify theres anything missing here */ /* verify theres anything missing here */
@@ -753,9 +738,9 @@ static void activate_run_state(struct fpi_ssm *ssm)
} }
/* jump to finger detection */ /* 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)); fp_dbg("status %d", fpi_ssm_get_error(ssm));
fpi_imgdev_activate_complete(dev, fpi_ssm_get_error(ssm)); fpi_imgdev_activate_complete(dev, fpi_ssm_get_error(ssm));
@@ -766,10 +751,9 @@ static void activate_sm_complete(struct fpi_ssm *ssm)
static int dev_activate(struct fp_img_dev *dev, enum fp_imgdev_state state) static int dev_activate(struct fp_img_dev *dev, enum fp_imgdev_state state)
{ {
struct aes1610_dev *aesdev = fpi_imgdev_get_user_data(dev); struct aes1610_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev));
struct fpi_ssm *ssm = fpi_ssm_new(fpi_imgdev_get_dev(dev), activate_run_state, fpi_ssm *ssm = fpi_ssm_new(FP_DEV(dev), activate_run_state,
ACTIVATE_NUM_STATES); ACTIVATE_NUM_STATES, dev);
fpi_ssm_set_user_data(ssm, dev);
aesdev->read_regs_retry_count = 0; aesdev->read_regs_retry_count = 0;
fpi_ssm_start(ssm, activate_sm_complete); fpi_ssm_start(ssm, activate_sm_complete);
return 0; 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) 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 /* FIXME: audit cancellation points, probably need more, specifically
* in error handling paths? */ * in error handling paths? */
aesdev->deactivating = TRUE; 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) 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(); G_DEBUG_HERE();
/* FIXME: if we're in the middle of a scan, we should cancel the scan. /* 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; int r;
struct aes1610_dev *aesdev; 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) { if (r < 0) {
fp_err("could not claim interface 0: %s", libusb_error_name(r)); fp_err("could not claim interface 0: %s", libusb_error_name(r));
return r; return r;
} }
aesdev = g_malloc0(sizeof(struct aes1610_dev)); 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); fpi_imgdev_open_complete(dev, 0);
return 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) static void dev_deinit(struct fp_img_dev *dev)
{ {
struct aes1610_dev *aesdev; struct aes1610_dev *aesdev;
aesdev = fpi_imgdev_get_user_data(dev); aesdev = FP_INSTANCE_DATA(FP_DEV(dev));
g_free(aesdev); 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); 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; int r;
struct aesX660_dev *aesdev; 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) { if (r < 0) {
fp_err("could not claim interface 0: %s", libusb_error_name(r)); fp_err("could not claim interface 0: %s", libusb_error_name(r));
return r; return r;
} }
aesdev = g_malloc0(sizeof(struct aesX660_dev)); 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->buffer = g_malloc0(AES1660_FRAME_SIZE + AESX660_HEADER_SIZE);
aesdev->init_seqs[0] = aes1660_init_1; aesdev->init_seqs[0] = aes1660_init_1;
aesdev->init_seqs_len[0] = G_N_ELEMENTS(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) 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->buffer);
g_free(aesdev); 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); 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 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 AES2501 is an imaging device using a swipe-type sensor. It samples
* the finger at preprogrammed intervals, sending a 192x16 frame to the * the finger at preprogrammed intervals, sending a 192x16 frame to the
@@ -83,9 +88,12 @@ struct aes2501_read_regs {
void *user_data; 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; unsigned char *retdata = NULL;
int r; 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); rdata->callback(rdata->dev, r, retdata, rdata->user_data);
g_free(rdata); 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) static void read_regs_rq_cb(struct fp_img_dev *dev, int result, void *user_data)
{ {
struct aes2501_read_regs *rdata = user_data; struct aes2501_read_regs *rdata = user_data;
struct libusb_transfer *transfer; fpi_usb_transfer *transfer;
unsigned char *data; unsigned char *data;
int r; 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) if (result != 0)
goto err; goto err;
transfer = libusb_alloc_transfer(0); data = g_malloc(READ_REGS_LEN);
if (!transfer) { transfer = fpi_usb_fill_bulk_transfer(FP_DEV(dev),
result = -ENOMEM; NULL,
goto err; EP_IN,
} data,
READ_REGS_LEN,
read_regs_data_cb,
rdata,
BULK_TIMEOUT);
data = g_malloc(126); r = fpi_usb_submit_transfer(transfer);
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);
if (r < 0) { if (r < 0) {
g_free(data);
libusb_free_transfer(transfer);
result = -EIO; result = -EIO;
goto err; 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, static void generic_write_regv_cb(struct fp_img_dev *dev, int result,
void *user_data) void *user_data)
{ {
struct fpi_ssm *ssm = user_data; fpi_ssm *ssm = user_data;
if (result == 0) if (result == 0)
fpi_ssm_next_state(ssm); fpi_ssm_next_state(ssm);
else else
fpi_ssm_mark_aborted(ssm, result); fpi_ssm_mark_failed(ssm, result);
} }
/* check that read succeeded but ignore all data */ /* check that read succeeded but ignore all data */
static void generic_ignore_data_cb(struct libusb_transfer *transfer) static void generic_ignore_data_cb(struct libusb_transfer *transfer,
struct fp_dev *dev,
fpi_ssm *ssm,
void *user_data)
{ {
struct fpi_ssm *ssm = transfer->user_data;
if (transfer->status != LIBUSB_TRANSFER_COMPLETED) if (transfer->status != LIBUSB_TRANSFER_COMPLETED)
fpi_ssm_mark_aborted(ssm, -EIO); fpi_ssm_mark_failed(ssm, -EIO);
else if (transfer->length != transfer->actual_length) else if (transfer->length != transfer->actual_length)
fpi_ssm_mark_aborted(ssm, -EPROTO); fpi_ssm_mark_failed(ssm, -EPROTO);
else else
fpi_ssm_next_state(ssm); fpi_ssm_next_state(ssm);
g_free(transfer->buffer);
libusb_free_transfer(transfer);
} }
/* read the specified number of bytes from the IN endpoint but throw them /* read the specified number of bytes from the IN endpoint but throw them
* away, then increment the SSM */ * away, then increment the SSM */
static void generic_read_ignore_data(struct fpi_ssm *ssm, size_t bytes) static void generic_read_ignore_data(fpi_ssm *ssm, struct fp_dev *dev, size_t bytes)
{ {
struct libusb_transfer *transfer = libusb_alloc_transfer(0); fpi_usb_transfer *transfer;
unsigned char *data; unsigned char *data;
struct fp_dev *dev = fpi_ssm_get_dev(ssm);
int r; int r;
if (!transfer) {
fpi_ssm_mark_aborted(ssm, -ENOMEM);
return;
}
data = g_malloc(bytes); data = g_malloc(bytes);
libusb_fill_bulk_transfer(transfer, fpi_dev_get_usb_dev(dev), EP_IN, data, bytes, transfer = fpi_usb_fill_bulk_transfer(dev,
generic_ignore_data_cb, ssm, BULK_TIMEOUT); ssm,
EP_IN,
data,
bytes,
generic_ignore_data_cb,
NULL,
BULK_TIMEOUT);
r = libusb_submit_transfer(transfer); r = fpi_usb_submit_transfer(transfer);
if (r < 0) { if (r < 0)
g_free(data); fpi_ssm_mark_failed(ssm, r);
libusb_free_transfer(transfer);
fpi_ssm_mark_aborted(ssm, r);
}
} }
/****** IMAGE PROCESSING ******/ /****** 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 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; unsigned char *data = transfer->buffer;
int i; int i;
int sum = 0; int sum = 0;
if (transfer->status != LIBUSB_TRANSFER_COMPLETED) { if (transfer->status != LIBUSB_TRANSFER_COMPLETED) {
fpi_imgdev_session_error(dev, -EIO); fpi_imgdev_session_error(dev, -EIO);
goto out; return;
} else if (transfer->length != transfer->actual_length) { } else if (transfer->length != transfer->actual_length) {
fpi_imgdev_session_error(dev, -EPROTO); fpi_imgdev_session_error(dev, -EPROTO);
goto out; return;
} }
/* examine histogram to determine finger presence */ /* 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 */ /* no finger, poll for a new histogram */
start_finger_detection(dev); 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, static void finger_det_reqs_cb(struct fp_img_dev *dev, int result,
void *user_data) void *user_data)
{ {
struct libusb_transfer *transfer; fpi_usb_transfer *transfer;
unsigned char *data; unsigned char *data;
int r; int r;
@@ -326,27 +324,24 @@ static void finger_det_reqs_cb(struct fp_img_dev *dev, int result,
return; return;
} }
transfer = libusb_alloc_transfer(0); data = g_malloc(FINGER_DETECTION_LEN);
if (!transfer) { transfer = fpi_usb_fill_bulk_transfer(FP_DEV(dev),
fpi_imgdev_session_error(dev, -ENOMEM); NULL,
return; EP_IN,
} data,
FINGER_DETECTION_LEN,
finger_det_data_cb,
NULL,
BULK_TIMEOUT);
data = g_malloc(20); r = fpi_usb_submit_transfer(transfer);
libusb_fill_bulk_transfer(transfer, fpi_imgdev_get_usb_dev(dev), EP_IN, data, 20, if (r < 0)
finger_det_data_cb, dev, BULK_TIMEOUT);
r = libusb_submit_transfer(transfer);
if (r < 0) {
g_free(data);
libusb_free_transfer(transfer);
fpi_imgdev_session_error(dev, r); fpi_imgdev_session_error(dev, r);
}
} }
static void start_finger_detection(struct fp_img_dev *dev) 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(); G_DEBUG_HERE();
if (aesdev->deactivating) { if (aesdev->deactivating) {
@@ -433,35 +428,37 @@ enum capture_states {
CAPTURE_NUM_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; unsigned char *stripdata;
struct fpi_ssm *ssm = transfer->user_data; struct fp_img_dev *dev = FP_IMG_DEV(_dev);
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm); struct aes2501_dev *aesdev = FP_INSTANCE_DATA(_dev);
struct aes2501_dev *aesdev = fpi_imgdev_get_user_data(dev);
unsigned char *data = transfer->buffer; unsigned char *data = transfer->buffer;
int sum; int sum;
int threshold; int threshold;
if (transfer->status != LIBUSB_TRANSFER_COMPLETED) { if (transfer->status != LIBUSB_TRANSFER_COMPLETED) {
fpi_ssm_mark_aborted(ssm, -EIO); fpi_ssm_mark_failed(ssm, -EIO);
goto out; return;
} else if (transfer->length != transfer->actual_length) { } else if (transfer->length != transfer->actual_length) {
fpi_ssm_mark_aborted(ssm, -EPROTO); fpi_ssm_mark_failed(ssm, -EPROTO);
goto out; return;
} }
threshold = regval_from_dump(data + 1 + 192*8 + 1 + 16*2 + 1 + 8, threshold = regval_from_dump(data + 1 + 192*8 + 1 + 16*2 + 1 + 8,
AES2501_REG_DATFMT); AES2501_REG_DATFMT);
if (threshold < 0) { if (threshold < 0) {
fpi_ssm_mark_aborted(ssm, threshold); fpi_ssm_mark_failed(ssm, threshold);
goto out; return;
} }
sum = sum_histogram_values(data + 1 + 192*8, threshold & 0x0f); sum = sum_histogram_values(data + 1 + 192*8, threshold & 0x0f);
if (sum < 0) { if (sum < 0) {
fpi_ssm_mark_aborted(ssm, sum); fpi_ssm_mark_failed(ssm, sum);
goto out; return;
} }
fp_dbg("sum=%d", sum); 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); 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 fp_img_dev *dev = user_data;
struct aes2501_dev *aesdev = fpi_imgdev_get_user_data(dev); struct aes2501_dev *aesdev = FP_INSTANCE_DATA(_dev);
int r; int r;
switch (fpi_ssm_get_cur_state(ssm)) { 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); generic_write_regv_cb, ssm);
break; break;
case CAPTURE_READ_DATA_1: case CAPTURE_READ_DATA_1:
generic_read_ignore_data(ssm, 159); generic_read_ignore_data(ssm, _dev, READ_REGS_RESP_LEN);
break; break;
case CAPTURE_WRITE_REQS_2: case CAPTURE_WRITE_REQS_2:
aes_write_regv(dev, capture_reqs_2, G_N_ELEMENTS(capture_reqs_2), aes_write_regv(dev, capture_reqs_2, G_N_ELEMENTS(capture_reqs_2),
generic_write_regv_cb, ssm); generic_write_regv_cb, ssm);
break; break;
case CAPTURE_READ_DATA_2: case CAPTURE_READ_DATA_2:
generic_read_ignore_data(ssm, 159); generic_read_ignore_data(ssm, _dev, READ_REGS_RESP_LEN);
break; break;
case CAPTURE_REQUEST_STRIP: case CAPTURE_REQUEST_STRIP:
if (aesdev->deactivating) if (aesdev->deactivating)
@@ -549,32 +542,30 @@ static void capture_run_state(struct fpi_ssm *ssm)
generic_write_regv_cb, ssm); generic_write_regv_cb, ssm);
break; break;
case CAPTURE_READ_STRIP: ; case CAPTURE_READ_STRIP: ;
struct libusb_transfer *transfer = libusb_alloc_transfer(0); fpi_usb_transfer *transfer;
unsigned char *data; unsigned char *data;
if (!transfer) { data = g_malloc(STRIP_CAPTURE_LEN);
fpi_ssm_mark_aborted(ssm, -ENOMEM); transfer = fpi_usb_fill_bulk_transfer(FP_DEV(dev),
break; ssm,
} EP_IN,
data,
STRIP_CAPTURE_LEN,
capture_read_strip_cb,
NULL,
BULK_TIMEOUT);
data = g_malloc(1705); r = fpi_usb_submit_transfer(transfer);
libusb_fill_bulk_transfer(transfer, fpi_imgdev_get_usb_dev(dev), EP_IN, data, 1705, if (r < 0)
capture_read_strip_cb, ssm, BULK_TIMEOUT); fpi_ssm_mark_failed(ssm, r);
r = libusb_submit_transfer(transfer);
if (r < 0) {
g_free(data);
libusb_free_transfer(transfer);
fpi_ssm_mark_aborted(ssm, r);
}
break; 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 fp_img_dev *dev = user_data;
struct aes2501_dev *aesdev = fpi_imgdev_get_user_data(dev); struct aes2501_dev *aesdev = FP_INSTANCE_DATA(_dev);
G_DEBUG_HERE(); G_DEBUG_HERE();
if (aesdev->deactivating) 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) static void start_capture(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));
struct fpi_ssm *ssm; fpi_ssm *ssm;
if (aesdev->deactivating) { if (aesdev->deactivating) {
complete_deactivation(dev); complete_deactivation(dev);
@@ -599,9 +590,8 @@ static void start_capture(struct fp_img_dev *dev)
aesdev->no_finger_cnt = 0; aesdev->no_finger_cnt = 0;
/* Reset gain */ /* Reset gain */
strip_scan_reqs[4].value = AES2501_ADREFHI_MAX_VALUE; 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(); G_DEBUG_HERE();
fpi_ssm_set_user_data(ssm, dev);
fpi_ssm_start(ssm, capture_sm_complete); 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, void activate_read_regs_cb(struct fp_img_dev *dev, int status,
unsigned char *regs, void *user_data) unsigned char *regs, void *user_data)
{ {
struct fpi_ssm *ssm = user_data; fpi_ssm *ssm = user_data;
struct aes2501_dev *aesdev = fpi_imgdev_get_user_data(dev); struct aes2501_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev));
if (status != 0) { if (status != 0) {
fpi_ssm_mark_aborted(ssm, status); fpi_ssm_mark_failed(ssm, status);
} else { } else {
fp_dbg("reg 0xaf = %x", regs[0x5f]); fp_dbg("reg 0xaf = %x", regs[0x5f]);
if (regs[0x5f] != 0x6b || ++aesdev->read_regs_retry_count == 13) 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, static void activate_init3_cb(struct fp_img_dev *dev, int result,
void *user_data) void *user_data)
{ {
struct fpi_ssm *ssm = user_data; fpi_ssm *ssm = user_data;
if (result == 0) if (result == 0)
fpi_ssm_jump_to_state(ssm, READ_REGS); fpi_ssm_jump_to_state(ssm, READ_REGS);
else 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 /* 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 * 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; break;
case READ_DATA_1: case READ_DATA_1:
fp_dbg("read data 1"); fp_dbg("read data 1");
generic_read_ignore_data(ssm, 20); generic_read_ignore_data(ssm, _dev, FINGER_DETECTION_LEN);
break; break;
case WRITE_INIT_2: case WRITE_INIT_2:
aes_write_regv(dev, init_2, G_N_ELEMENTS(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)); fp_dbg("status %d", fpi_ssm_get_error(ssm));
fpi_imgdev_activate_complete(dev, fpi_ssm_get_error(ssm)); fpi_imgdev_activate_complete(dev, fpi_ssm_get_error(ssm));
@@ -804,10 +794,9 @@ static void activate_sm_complete(struct fpi_ssm *ssm)
static int dev_activate(struct fp_img_dev *dev, enum fp_imgdev_state state) static int dev_activate(struct fp_img_dev *dev, enum fp_imgdev_state state)
{ {
struct aes2501_dev *aesdev = fpi_imgdev_get_user_data(dev); struct aes2501_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev));
struct fpi_ssm *ssm = fpi_ssm_new(fpi_imgdev_get_dev(dev), activate_run_state, fpi_ssm *ssm = fpi_ssm_new(FP_DEV(dev), activate_run_state,
ACTIVATE_NUM_STATES); ACTIVATE_NUM_STATES, dev);
fpi_ssm_set_user_data(ssm, dev);
aesdev->read_regs_retry_count = 0; aesdev->read_regs_retry_count = 0;
fpi_ssm_start(ssm, activate_sm_complete); fpi_ssm_start(ssm, activate_sm_complete);
return 0; 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) 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 /* FIXME: audit cancellation points, probably need more, specifically
* in error handling paths? */ * in error handling paths? */
aesdev->deactivating = TRUE; 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) 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(); G_DEBUG_HERE();
/* FIXME: if we're in the middle of a scan, we should cancel the scan. /* 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; int r;
struct aes2501_dev *aesdev; 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) { if (r < 0) {
fp_err("could not claim interface 0: %s", libusb_error_name(r)); fp_err("could not claim interface 0: %s", libusb_error_name(r));
return r; return r;
} }
aesdev = g_malloc0(sizeof(struct aes2501_dev)); 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); fpi_imgdev_open_complete(dev, 0);
return 0; return 0;
} }
static void dev_deinit(struct fp_img_dev *dev) 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); 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); 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; goto exit_free_transfer;
} }
transfer = libusb_alloc_transfer(0); transfer = fpi_usb_alloc();
if (!transfer) {
fpi_imgdev_session_error(dev, -ENOMEM);
goto exit_free_transfer;
}
/* 2 bytes of result */ /* 2 bytes of result */
data = g_malloc(AES2550_EP_IN_BUF_SIZE); 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); finger_det_data_cb, dev, BULK_TIMEOUT);
r = libusb_submit_transfer(transfer); r = libusb_submit_transfer(transfer);
@@ -149,7 +144,7 @@ exit_free_transfer:
static void start_finger_detection(struct fp_img_dev *dev) static void start_finger_detection(struct fp_img_dev *dev)
{ {
int r; 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; struct libusb_transfer *transfer;
G_DEBUG_HERE(); G_DEBUG_HERE();
@@ -158,12 +153,8 @@ static void start_finger_detection(struct fp_img_dev *dev)
return; return;
} }
transfer = libusb_alloc_transfer(0); transfer = fpi_usb_alloc();
if (!transfer) { libusb_fill_bulk_transfer(transfer, fpi_dev_get_usb_dev(FP_DEV(dev)), EP_OUT, finger_det_reqs,
fpi_imgdev_session_error(dev, -ENOMEM);
return;
}
libusb_fill_bulk_transfer(transfer, fpi_imgdev_get_usb_dev(dev), EP_OUT, finger_det_reqs,
sizeof(finger_det_reqs), finger_det_reqs_cb, dev, BULK_TIMEOUT); sizeof(finger_det_reqs), finger_det_reqs_cb, dev, BULK_TIMEOUT);
r = libusb_submit_transfer(transfer); r = libusb_submit_transfer(transfer);
if (r < 0) { if (r < 0) {
@@ -200,11 +191,10 @@ enum capture_states {
}; };
/* Returns number of processed bytes */ /* 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; unsigned char *stripdata;
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm); struct aes2550_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev));
struct aes2550_dev *aesdev = fpi_imgdev_get_user_data(dev);
struct fpi_frame *stripe; struct fpi_frame *stripe;
int len; 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) 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) && if ((transfer->status == LIBUSB_TRANSFER_COMPLETED) &&
(transfer->length == transfer->actual_length)) { (transfer->length == transfer->actual_length)) {
fpi_ssm_next_state(ssm); fpi_ssm_next_state(ssm);
} else { } else {
fpi_ssm_mark_aborted(ssm, -EIO); fpi_ssm_mark_failed(ssm, -EIO);
} }
libusb_free_transfer(transfer); libusb_free_transfer(transfer);
} }
static void capture_set_idle_reqs_cb(struct libusb_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 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) && if ((transfer->status == LIBUSB_TRANSFER_COMPLETED) &&
(transfer->length == transfer->actual_length) && (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 */ /* marking machine complete will re-trigger finger detection loop */
fpi_ssm_mark_completed(ssm); fpi_ssm_mark_completed(ssm);
} else { } else {
fpi_ssm_mark_aborted(ssm, -EIO); fpi_ssm_mark_failed(ssm, -EIO);
} }
libusb_free_transfer(transfer); libusb_free_transfer(transfer);
} }
static void capture_read_data_cb(struct libusb_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 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; unsigned char *data = transfer->buffer;
int r; int r;
if (transfer->status != LIBUSB_TRANSFER_COMPLETED) { if (transfer->status != LIBUSB_TRANSFER_COMPLETED) {
fp_dbg("request is not completed, %d", transfer->status); fp_dbg("request is not completed, %d", transfer->status);
fpi_ssm_mark_aborted(ssm, -EIO); fpi_ssm_mark_failed(ssm, -EIO);
goto out; goto out;
} }
@@ -290,10 +280,10 @@ static void capture_read_data_cb(struct libusb_transfer *transfer)
switch (transfer->actual_length) { switch (transfer->actual_length) {
case AES2550_STRIP_SIZE: case AES2550_STRIP_SIZE:
r = process_strip_data(ssm, data); r = process_strip_data(ssm, dev, data);
if (r < 0) { if (r < 0) {
fp_dbg("Processing strip data failed: %d", r); fp_dbg("Processing strip data failed: %d", r);
fpi_ssm_mark_aborted(ssm, -EPROTO); fpi_ssm_mark_failed(ssm, -EPROTO);
goto out; goto out;
} }
aesdev->heartbeat_cnt = 0; aesdev->heartbeat_cnt = 0;
@@ -323,73 +313,62 @@ out:
libusb_free_transfer(transfer); 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; int r;
switch (fpi_ssm_get_cur_state(ssm)) { switch (fpi_ssm_get_cur_state(ssm)) {
case CAPTURE_WRITE_REQS: case CAPTURE_WRITE_REQS:
{ {
struct libusb_transfer *transfer = libusb_alloc_transfer(0); struct libusb_transfer *transfer = fpi_usb_alloc();
if (!transfer) {
fpi_ssm_mark_aborted(ssm, -ENOMEM); libusb_fill_bulk_transfer(transfer, fpi_dev_get_usb_dev(FP_DEV(dev)), EP_OUT, capture_reqs,
return;
}
libusb_fill_bulk_transfer(transfer, fpi_imgdev_get_usb_dev(dev), EP_OUT, capture_reqs,
sizeof(capture_reqs), capture_reqs_cb, ssm, BULK_TIMEOUT); sizeof(capture_reqs), capture_reqs_cb, ssm, BULK_TIMEOUT);
r = libusb_submit_transfer(transfer); r = libusb_submit_transfer(transfer);
if (r < 0) { if (r < 0) {
libusb_free_transfer(transfer); libusb_free_transfer(transfer);
fpi_ssm_mark_aborted(ssm, -ENOMEM); fpi_ssm_mark_failed(ssm, -ENOMEM);
} }
} }
break; break;
case CAPTURE_READ_DATA: case CAPTURE_READ_DATA:
{ {
struct libusb_transfer *transfer = libusb_alloc_transfer(0); struct libusb_transfer *transfer = fpi_usb_alloc();
unsigned char *data; unsigned char *data;
if (!transfer) {
fpi_ssm_mark_aborted(ssm, -ENOMEM);
break;
}
data = g_malloc(AES2550_EP_IN_BUF_SIZE); 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); capture_read_data_cb, ssm, BULK_TIMEOUT);
r = libusb_submit_transfer(transfer); r = libusb_submit_transfer(transfer);
if (r < 0) { if (r < 0) {
g_free(data); g_free(data);
libusb_free_transfer(transfer); libusb_free_transfer(transfer);
fpi_ssm_mark_aborted(ssm, r); fpi_ssm_mark_failed(ssm, r);
} }
} }
break; break;
case CAPTURE_SET_IDLE: case CAPTURE_SET_IDLE:
{ {
struct libusb_transfer *transfer = libusb_alloc_transfer(0); struct libusb_transfer *transfer = fpi_usb_alloc();
if (!transfer) {
fpi_ssm_mark_aborted(ssm, -ENOMEM); libusb_fill_bulk_transfer(transfer, fpi_dev_get_usb_dev(FP_DEV(dev)), EP_OUT, capture_set_idle_reqs,
return;
}
libusb_fill_bulk_transfer(transfer, fpi_imgdev_get_usb_dev(dev), EP_OUT, capture_set_idle_reqs,
sizeof(capture_set_idle_reqs), capture_set_idle_reqs_cb, ssm, BULK_TIMEOUT); sizeof(capture_set_idle_reqs), capture_set_idle_reqs_cb, ssm, BULK_TIMEOUT);
r = libusb_submit_transfer(transfer); r = libusb_submit_transfer(transfer);
if (r < 0) { if (r < 0) {
libusb_free_transfer(transfer); libusb_free_transfer(transfer);
fpi_ssm_mark_aborted(ssm, -ENOMEM); fpi_ssm_mark_failed(ssm, -ENOMEM);
} }
} }
break; 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 fp_img_dev *dev = user_data;
struct aes2550_dev *aesdev = fpi_imgdev_get_user_data(dev); struct aes2550_dev *aesdev = FP_INSTANCE_DATA(_dev);
fp_dbg("Capture completed"); fp_dbg("Capture completed");
if (aesdev->deactivating) 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) static void start_capture(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));
struct fpi_ssm *ssm; fpi_ssm *ssm;
if (aesdev->deactivating) { if (aesdev->deactivating) {
complete_deactivation(dev); complete_deactivation(dev);
@@ -412,9 +391,8 @@ static void start_capture(struct fp_img_dev *dev)
} }
aesdev->heartbeat_cnt = 0; 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(); G_DEBUG_HERE();
fpi_ssm_set_user_data(ssm, dev);
fpi_ssm_start(ssm, capture_sm_complete); fpi_ssm_start(ssm, capture_sm_complete);
} }
@@ -444,25 +422,25 @@ enum activate_states {
static void init_reqs_cb(struct libusb_transfer *transfer) 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) && if ((transfer->status == LIBUSB_TRANSFER_COMPLETED) &&
(transfer->length == transfer->actual_length)) { (transfer->length == transfer->actual_length)) {
fpi_ssm_next_state(ssm); fpi_ssm_next_state(ssm);
} else { } else {
fpi_ssm_mark_aborted(ssm, -EIO); fpi_ssm_mark_failed(ssm, -EIO);
} }
libusb_free_transfer(transfer); libusb_free_transfer(transfer);
} }
static void init_read_data_cb(struct libusb_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) { if (transfer->status == LIBUSB_TRANSFER_COMPLETED) {
fpi_ssm_next_state(ssm); fpi_ssm_next_state(ssm);
} else { } else {
fpi_ssm_mark_aborted(ssm, -EIO); fpi_ssm_mark_failed(ssm, -EIO);
} }
g_free(transfer->buffer); g_free(transfer->buffer);
libusb_free_transfer(transfer); libusb_free_transfer(transfer);
@@ -472,105 +450,89 @@ static void init_read_data_cb(struct libusb_transfer *transfer)
* need more info for implementaion */ * need more info for implementaion */
static void calibrate_read_data_cb(struct libusb_transfer *transfer) 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) { if (transfer->status == LIBUSB_TRANSFER_COMPLETED) {
fpi_ssm_next_state(ssm); fpi_ssm_next_state(ssm);
} else { } else {
fpi_ssm_mark_aborted(ssm, -EIO); fpi_ssm_mark_failed(ssm, -EIO);
} }
g_free(transfer->buffer); g_free(transfer->buffer);
libusb_free_transfer(transfer); 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; int r;
switch (fpi_ssm_get_cur_state(ssm)) { switch (fpi_ssm_get_cur_state(ssm)) {
case WRITE_INIT: case WRITE_INIT:
{ {
struct libusb_transfer *transfer = libusb_alloc_transfer(0); struct libusb_transfer *transfer = fpi_usb_alloc();
if (!transfer) {
fpi_ssm_mark_aborted(ssm, -ENOMEM); libusb_fill_bulk_transfer(transfer, fpi_dev_get_usb_dev(FP_DEV(dev)), EP_OUT, init_reqs,
return;
}
libusb_fill_bulk_transfer(transfer, fpi_imgdev_get_usb_dev(dev), EP_OUT, init_reqs,
sizeof(init_reqs), init_reqs_cb, ssm, BULK_TIMEOUT); sizeof(init_reqs), init_reqs_cb, ssm, BULK_TIMEOUT);
r = libusb_submit_transfer(transfer); r = libusb_submit_transfer(transfer);
if (r < 0) { if (r < 0) {
libusb_free_transfer(transfer); libusb_free_transfer(transfer);
fpi_ssm_mark_aborted(ssm, -ENOMEM); fpi_ssm_mark_failed(ssm, -ENOMEM);
} }
} }
break; break;
case READ_DATA: case READ_DATA:
{ {
struct libusb_transfer *transfer = libusb_alloc_transfer(0); struct libusb_transfer *transfer = fpi_usb_alloc();
unsigned char *data; unsigned char *data;
if (!transfer) {
fpi_ssm_mark_aborted(ssm, -ENOMEM);
break;
}
data = g_malloc(AES2550_EP_IN_BUF_SIZE); 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); init_read_data_cb, ssm, BULK_TIMEOUT);
r = libusb_submit_transfer(transfer); r = libusb_submit_transfer(transfer);
if (r < 0) { if (r < 0) {
g_free(data); g_free(data);
libusb_free_transfer(transfer); libusb_free_transfer(transfer);
fpi_ssm_mark_aborted(ssm, r); fpi_ssm_mark_failed(ssm, r);
} }
} }
break; break;
case CALIBRATE: case CALIBRATE:
{ {
struct libusb_transfer *transfer = libusb_alloc_transfer(0); struct libusb_transfer *transfer = fpi_usb_alloc();
if (!transfer) {
fpi_ssm_mark_aborted(ssm, -ENOMEM); libusb_fill_bulk_transfer(transfer, fpi_dev_get_usb_dev(FP_DEV(dev)), EP_OUT, calibrate_reqs,
return;
}
libusb_fill_bulk_transfer(transfer, fpi_imgdev_get_usb_dev(dev), EP_OUT, calibrate_reqs,
sizeof(calibrate_reqs), init_reqs_cb, ssm, BULK_TIMEOUT); sizeof(calibrate_reqs), init_reqs_cb, ssm, BULK_TIMEOUT);
r = libusb_submit_transfer(transfer); r = libusb_submit_transfer(transfer);
if (r < 0) { if (r < 0) {
libusb_free_transfer(transfer); libusb_free_transfer(transfer);
fpi_ssm_mark_aborted(ssm, -ENOMEM); fpi_ssm_mark_failed(ssm, -ENOMEM);
} }
} }
break; break;
case READ_CALIB_TABLE: case READ_CALIB_TABLE:
{ {
struct libusb_transfer *transfer = libusb_alloc_transfer(0); struct libusb_transfer *transfer = fpi_usb_alloc();
unsigned char *data; unsigned char *data;
if (!transfer) {
fpi_ssm_mark_aborted(ssm, -ENOMEM);
break;
}
data = g_malloc(AES2550_EP_IN_BUF_SIZE); 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); calibrate_read_data_cb, ssm, BULK_TIMEOUT);
r = libusb_submit_transfer(transfer); r = libusb_submit_transfer(transfer);
if (r < 0) { if (r < 0) {
g_free(data); g_free(data);
libusb_free_transfer(transfer); libusb_free_transfer(transfer);
fpi_ssm_mark_aborted(ssm, r); fpi_ssm_mark_failed(ssm, r);
} }
} }
break; 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)); fp_dbg("status %d", fpi_ssm_get_error(ssm));
fpi_imgdev_activate_complete(dev, fpi_ssm_get_error(ssm)); fpi_imgdev_activate_complete(dev, fpi_ssm_get_error(ssm));
@@ -581,23 +543,22 @@ static void activate_sm_complete(struct fpi_ssm *ssm)
static int dev_activate(struct fp_img_dev *dev, enum fp_imgdev_state state) static int dev_activate(struct fp_img_dev *dev, enum fp_imgdev_state state)
{ {
struct fpi_ssm *ssm = fpi_ssm_new(fpi_imgdev_get_dev(dev), activate_run_state, fpi_ssm *ssm = fpi_ssm_new(FP_DEV(dev), activate_run_state,
ACTIVATE_NUM_STATES); ACTIVATE_NUM_STATES, dev);
fpi_ssm_set_user_data(ssm, dev);
fpi_ssm_start(ssm, activate_sm_complete); fpi_ssm_start(ssm, activate_sm_complete);
return 0; return 0;
} }
static void dev_deactivate(struct fp_img_dev *dev) 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; aesdev->deactivating = TRUE;
} }
static void complete_deactivation(struct fp_img_dev *dev) 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(); G_DEBUG_HERE();
aesdev->deactivating = FALSE; aesdev->deactivating = FALSE;
@@ -613,14 +574,14 @@ static int dev_init(struct fp_img_dev *dev, unsigned long driver_data)
int r; int r;
struct aes2550_dev *aes2550_dev; 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) { if (r < 0) {
fp_err("could not claim interface 0: %s", libusb_error_name(r)); fp_err("could not claim interface 0: %s", libusb_error_name(r));
return r; return r;
} }
aes2550_dev = g_malloc0(sizeof(struct aes2550_dev)); 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); fpi_imgdev_open_complete(dev, 0);
return 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) static void dev_deinit(struct fp_img_dev *dev)
{ {
struct aes2550_dev *aesdev; struct aes2550_dev *aesdev;
aesdev = fpi_imgdev_get_user_data(dev); aesdev = FP_INSTANCE_DATA(FP_DEV(dev));
g_free(aesdev); 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); 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; int r;
struct aesX660_dev *aesdev; 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) { if (r < 0) {
fp_err("could not claim interface 0: %s", libusb_error_name(r)); fp_err("could not claim interface 0: %s", libusb_error_name(r));
return r; return r;
} }
aesdev = g_malloc0(sizeof(struct aesX660_dev)); 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); aesdev->buffer = g_malloc0(AES2660_FRAME_SIZE + AESX660_HEADER_SIZE);
/* No scaling for AES2660 */ /* No scaling for AES2660 */
aesdev->init_seqs[0] = aes2660_init_1; 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) static void dev_deinit(struct fp_img_dev *dev)
{ {
struct aesX660_dev *aesdev; 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->buffer);
g_free(aesdev); 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); 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; int r;
struct aes3k_dev *aesdev; 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) { if (r < 0) {
fp_err("could not claim interface 0: %s", libusb_error_name(r)); fp_err("could not claim interface 0: %s", libusb_error_name(r));
return r; return r;
} }
aesdev = g_malloc0(sizeof(struct aes3k_dev)); 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) if (!aesdev)
return -ENOMEM; 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) 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); 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); 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) static void img_cb(struct libusb_transfer *transfer)
{ {
struct fp_img_dev *dev = transfer->user_data; 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; unsigned char *ptr = transfer->buffer;
struct fp_img *tmp; struct fp_img *tmp;
struct fp_img *img; 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 /* FIXME: this is an ugly hack to make the image big enough for NBIS
* to process reliably */ * 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); fp_img_free(tmp);
fpi_imgdev_image_captured(dev, img); fpi_imgdev_image_captured(dev, img);
@@ -112,18 +112,13 @@ err:
static void do_capture(struct fp_img_dev *dev) 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; unsigned char *data;
int r; int r;
aesdev->img_trf = libusb_alloc_transfer(0); aesdev->img_trf = fpi_usb_alloc();
if (!aesdev->img_trf) {
fpi_imgdev_session_error(dev, -EIO);
return;
}
data = g_malloc(aesdev->data_buflen); 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); aesdev->data_buflen, img_cb, dev, 0);
r = libusb_submit_transfer(aesdev->img_trf); r = libusb_submit_transfer(aesdev->img_trf);
@@ -144,14 +139,14 @@ static void init_reqs_cb(struct fp_img_dev *dev, int result, void *user_data)
int aes3k_dev_activate(struct fp_img_dev *dev, enum fp_imgdev_state state) int aes3k_dev_activate(struct fp_img_dev *dev, enum fp_imgdev_state state)
{ {
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); aes_write_regv(dev, aesdev->init_reqs, aesdev->init_reqs_len, init_reqs_cb, NULL);
return 0; return 0;
} }
void aes3k_dev_deactivate(struct fp_img_dev *dev) 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 /* FIXME: should wait for cancellation to complete before returning
* from deactivation, otherwise app may legally exit before we've * from deactivation, otherwise app may legally exit before we've

View File

@@ -119,14 +119,14 @@ static int dev_init(struct fp_img_dev *dev, unsigned long driver_data)
int r; int r;
struct aes3k_dev *aesdev; 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) { if (r < 0) {
fp_err("could not claim interface 0: %s", libusb_error_name(r)); fp_err("could not claim interface 0: %s", libusb_error_name(r));
return r; return r;
} }
aesdev = g_malloc0(sizeof(struct aes3k_dev)); 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) if (!aesdev)
return -ENOMEM; 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) 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); 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); fpi_imgdev_close_complete(dev);
} }

View File

@@ -24,10 +24,10 @@
#include <errno.h> #include <errno.h>
#include <string.h> #include <string.h>
#include <libusb.h>
#include <glib.h> #include <glib.h>
#include "assembling.h" #include "fpi-usb.h"
#include "fpi-assembling.h"
#include "aeslib.h" #include "aeslib.h"
#define MAX_REGWRITES_PER_REQUEST 16 #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 char *data = g_malloc(alloc_size);
unsigned int i; unsigned int i;
size_t data_offset = 0; size_t data_offset = 0;
struct libusb_transfer *transfer = libusb_alloc_transfer(0); struct libusb_transfer *transfer = fpi_usb_alloc();
int r; int r;
if (!transfer) {
g_free(data);
return -ENOMEM;
}
for (i = offset; i < offset + num; i++) { for (i = offset; i < offset + num; i++) {
const struct aes_regwrite *regwrite = &wdata->regs[i]; const struct aes_regwrite *regwrite = &wdata->regs[i];
data[data_offset++] = regwrite->reg; data[data_offset++] = regwrite->reg;
data[data_offset++] = regwrite->value; 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); alloc_size, write_regv_trf_complete, wdata, BULK_TIMEOUT);
r = libusb_submit_transfer(transfer); r = libusb_submit_transfer(transfer);
if (r < 0) { 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, 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) 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); fp_dbg("write %d regs", num_regs);
wdata = g_malloc(sizeof(*wdata));
wdata->imgdev = dev; wdata->imgdev = dev;
wdata->num_regs = num_regs; wdata->num_regs = num_regs;
wdata->regs = 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->callback = callback;
wdata->user_data = user_data; wdata->user_data = user_data;
continue_write_regv(wdata); continue_write_regv(wdata);
g_free(wdata);
} }
unsigned char aes_get_pixel(struct fpi_frame_asmbl_ctx *ctx, 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 BULK_TIMEOUT 4000
#define FRAME_HEIGHT AESX660_FRAME_HEIGHT #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, static void
size_t cmd_len, libusb_transfer_cb_fn callback, int timeout) 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 fp_img_dev *dev = FP_IMG_DEV(_dev);
struct libusb_transfer *transfer = libusb_alloc_transfer(0); struct libusb_transfer *transfer = fpi_usb_alloc();
int r; int r;
if (!transfer) { libusb_fill_bulk_transfer(transfer, fpi_dev_get_usb_dev(FP_DEV(dev)), EP_OUT,
fpi_ssm_mark_aborted(ssm, -ENOMEM);
return;
}
libusb_fill_bulk_transfer(transfer, fpi_imgdev_get_usb_dev(dev), EP_OUT,
(unsigned char *)cmd, cmd_len, (unsigned char *)cmd, cmd_len,
callback, ssm, timeout); callback, ssm, timeout);
r = libusb_submit_transfer(transfer); r = libusb_submit_transfer(transfer);
if (r < 0) { if (r < 0) {
fp_dbg("failed to submit transfer\n"); fp_dbg("failed to submit transfer\n");
libusb_free_transfer(transfer); 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, static void
size_t cmd_len, libusb_transfer_cb_fn callback) 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, static void
libusb_transfer_cb_fn callback) 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 fp_img_dev *dev = FP_IMG_DEV(_dev);
struct libusb_transfer *transfer = libusb_alloc_transfer(0); struct libusb_transfer *transfer = fpi_usb_alloc();
unsigned char *data; unsigned char *data;
int r; int r;
if (!transfer) {
fpi_ssm_mark_aborted(ssm, -ENOMEM);
return;
}
data = g_malloc(buf_len); 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, data, buf_len,
callback, ssm, BULK_TIMEOUT); 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); fp_dbg("Failed to submit rx transfer: %d\n", r);
g_free(data); g_free(data);
libusb_free_transfer(transfer); libusb_free_transfer(transfer);
fpi_ssm_mark_aborted(ssm, r); fpi_ssm_mark_failed(ssm, r);
} }
} }
static void aesX660_send_cmd_cb(struct libusb_transfer *transfer) 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) && if ((transfer->status == LIBUSB_TRANSFER_COMPLETED) &&
(transfer->length == transfer->actual_length)) { (transfer->length == transfer->actual_length)) {
@@ -103,25 +108,25 @@ static void aesX660_send_cmd_cb(struct libusb_transfer *transfer)
} else { } else {
fp_dbg("tx transfer status: %d, actual_len: %.4x\n", fp_dbg("tx transfer status: %d, actual_len: %.4x\n",
transfer->status, transfer->actual_length); transfer->status, transfer->actual_length);
fpi_ssm_mark_aborted(ssm, -EIO); fpi_ssm_mark_failed(ssm, -EIO);
} }
libusb_free_transfer(transfer); libusb_free_transfer(transfer);
} }
static void aesX660_read_calibrate_data_cb(struct libusb_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; unsigned char *data = transfer->buffer;
if ((transfer->status != LIBUSB_TRANSFER_COMPLETED) || if ((transfer->status != LIBUSB_TRANSFER_COMPLETED) ||
(transfer->length != transfer->actual_length)) { (transfer->length != transfer->actual_length)) {
fpi_ssm_mark_aborted(ssm, -EIO); fpi_ssm_mark_failed(ssm, -EIO);
goto out; goto out;
} }
/* Calibrate response was read correctly? */ /* Calibrate response was read correctly? */
if (data[AESX660_RESPONSE_TYPE_OFFSET] != AESX660_CALIBRATE_RESPONSE) { if (data[AESX660_RESPONSE_TYPE_OFFSET] != AESX660_CALIBRATE_RESPONSE) {
fp_dbg("Bogus calibrate response: %.2x\n", data[0]); fp_dbg("Bogus calibrate response: %.2x\n", data[0]);
fpi_ssm_mark_aborted(ssm, -EPROTO); fpi_ssm_mark_failed(ssm, -EPROTO);
goto out; goto out;
} }
@@ -143,9 +148,9 @@ enum finger_det_states {
static void finger_det_read_fd_data_cb(struct libusb_transfer *transfer) 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 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; unsigned char *data = transfer->buffer;
aesdev->fd_data_transfer = NULL; 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) || if ((transfer->status != LIBUSB_TRANSFER_COMPLETED) ||
(transfer->length != transfer->actual_length)) { (transfer->length != transfer->actual_length)) {
fp_dbg("Failed to read FD data\n"); fp_dbg("Failed to read FD data\n");
fpi_ssm_mark_aborted(ssm, -EIO); fpi_ssm_mark_failed(ssm, -EIO);
goto out; goto out;
} }
if (data[AESX660_RESPONSE_TYPE_OFFSET] != AESX660_FINGER_DET_RESPONSE) { if (data[AESX660_RESPONSE_TYPE_OFFSET] != AESX660_FINGER_DET_RESPONSE) {
fp_dbg("Bogus FD response: %.2x\n", data[0]); fp_dbg("Bogus FD response: %.2x\n", data[0]);
fpi_ssm_mark_aborted(ssm, -EPROTO); fpi_ssm_mark_failed(ssm, -EPROTO);
goto out; goto out;
} }
@@ -184,21 +189,21 @@ out:
static void finger_det_set_idle_cmd_cb(struct libusb_transfer *transfer) 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) && if ((transfer->status == LIBUSB_TRANSFER_COMPLETED) &&
(transfer->length == transfer->actual_length)) { (transfer->length == transfer->actual_length)) {
fpi_ssm_mark_completed(ssm); fpi_ssm_mark_completed(ssm);
} else { } else {
fpi_ssm_mark_aborted(ssm, -EIO); fpi_ssm_mark_failed(ssm, -EIO);
} }
libusb_free_transfer(transfer); 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 fp_img_dev *dev = user_data;
struct aesX660_dev *aesdev = fpi_imgdev_get_user_data(dev); struct aesX660_dev *aesdev = FP_INSTANCE_DATA(_dev);
int err = fpi_ssm_get_error(ssm); int err = fpi_ssm_get_error(ssm);
fp_dbg("Finger detection completed"); 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)) { switch (fpi_ssm_get_cur_state(ssm)) {
case FINGER_DET_SEND_LED_CMD: 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); aesX660_send_cmd_cb);
break; break;
case FINGER_DET_SEND_FD_CMD: 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); aesX660_send_cmd_cb, 0);
break; break;
case FINGER_DET_READ_FD_DATA: case FINGER_DET_READ_FD_DATA:
/* Should return 4 byte of response */ aesX660_read_response(ssm, dev, FINGER_DET_DATA_LEN, finger_det_read_fd_data_cb);
aesX660_read_response(ssm, 4, finger_det_read_fd_data_cb);
break; break;
case FINGER_DET_SET_IDLE: 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); finger_det_set_idle_cmd_cb);
break; 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) static void start_finger_detection(struct fp_img_dev *dev)
{ {
struct fpi_ssm *ssm; fpi_ssm *ssm;
struct aesX660_dev *aesdev = fpi_imgdev_get_user_data(dev); struct aesX660_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev));
if (aesdev->deactivating) { if (aesdev->deactivating) {
complete_deactivation(dev); complete_deactivation(dev);
return; return;
} }
ssm = fpi_ssm_new(fpi_imgdev_get_dev(dev), finger_det_run_state, FINGER_DET_NUM_STATES); ssm = fpi_ssm_new(FP_DEV(dev), finger_det_run_state, FINGER_DET_NUM_STATES, dev);
fpi_ssm_set_user_data(ssm, dev);
fpi_ssm_start(ssm, finger_det_sm_complete); fpi_ssm_start(ssm, finger_det_sm_complete);
} }
@@ -263,12 +266,11 @@ enum capture_states {
}; };
/* Returns number of processed bytes */ /* 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; struct fpi_frame *stripe;
unsigned char *stripdata; unsigned char *stripdata;
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm); struct aesX660_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev));
struct aesX660_dev *aesdev = fpi_imgdev_get_user_data(dev);
stripe = g_malloc(aesdev->assembling_ctx->frame_width * FRAME_HEIGHT / 2 + sizeof(struct fpi_frame)); /* 4 bpp */ stripe = g_malloc(aesdev->assembling_ctx->frame_width * FRAME_HEIGHT / 2 + sizeof(struct fpi_frame)); /* 4 bpp */
stripdata = stripe->data; 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 = g_slist_prepend(aesdev->strips, stripe);
aesdev->strips_len++; aesdev->strips_len++;
return (data[AESX660_LAST_FRAME_OFFSET] & AESX660_LAST_FRAME_BIT); 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) 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 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) && if ((transfer->status == LIBUSB_TRANSFER_COMPLETED) &&
(transfer->length == transfer->actual_length)) { (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_imgdev_report_finger_status(dev, FALSE);
fpi_ssm_mark_completed(ssm); fpi_ssm_mark_completed(ssm);
} else { } else {
fpi_ssm_mark_aborted(ssm, -EIO); fpi_ssm_mark_failed(ssm, -EIO);
} }
libusb_free_transfer(transfer); libusb_free_transfer(transfer);
} }
static void capture_read_stripe_data_cb(struct libusb_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 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; unsigned char *data = transfer->buffer;
int finger_missing = 0; int finger_missing = 0;
size_t copied, actual_len = transfer->actual_length; size_t copied, actual_len = transfer->actual_length;
if (transfer->status != LIBUSB_TRANSFER_COMPLETED) { if (transfer->status != LIBUSB_TRANSFER_COMPLETED) {
fpi_ssm_mark_aborted(ssm, -EIO); fpi_ssm_mark_failed(ssm, -EIO);
goto out; goto out;
} }
fp_dbg("Got %lu bytes of data", actual_len); fp_dbg("Got %lu bytes of data", actual_len);
do { 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, memcpy(aesdev->buffer + aesdev->buffer_size,
data, data,
copied); copied);
@@ -352,7 +354,7 @@ static void capture_read_stripe_data_cb(struct libusb_transfer *transfer)
aesdev->buffer_max); aesdev->buffer_max);
continue; continue;
} else { } 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_max = AESX660_HEADER_SIZE;
aesdev->buffer_size = 0; aesdev->buffer_size = 0;
} }
@@ -371,39 +373,38 @@ out:
libusb_free_transfer(transfer); 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 = FP_INSTANCE_DATA(_dev);
struct aesX660_dev *aesdev = fpi_imgdev_get_user_data(dev);
switch (fpi_ssm_get_cur_state(ssm)) { switch (fpi_ssm_get_cur_state(ssm)) {
case CAPTURE_SEND_LED_CMD: 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); aesX660_send_cmd_cb);
break; break;
case CAPTURE_SEND_CAPTURE_CMD: case CAPTURE_SEND_CAPTURE_CMD:
aesdev->buffer_size = 0; aesdev->buffer_size = 0;
aesdev->buffer_max = AESX660_HEADER_SIZE; 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, aesdev->start_imaging_cmd_len,
aesX660_send_cmd_cb); aesX660_send_cmd_cb);
break; break;
case CAPTURE_READ_STRIPE_DATA: 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); capture_read_stripe_data_cb);
break; break;
case CAPTURE_SET_IDLE: case CAPTURE_SET_IDLE:
fp_dbg("Got %lu frames\n", aesdev->strips_len); 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); capture_set_idle_cmd_cb);
break; 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 fp_img_dev *dev = user_data;
struct aesX660_dev *aesdev = fpi_imgdev_get_user_data(dev); struct aesX660_dev *aesdev = FP_INSTANCE_DATA(_dev);
int err = fpi_ssm_get_error(ssm); int err = fpi_ssm_get_error(ssm);
fp_dbg("Capture completed"); 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) static void start_capture(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));
struct fpi_ssm *ssm; fpi_ssm *ssm;
if (aesdev->deactivating) { if (aesdev->deactivating) {
complete_deactivation(dev); complete_deactivation(dev);
return; 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(); G_DEBUG_HERE();
fpi_ssm_set_user_data(ssm, dev);
fpi_ssm_start(ssm, capture_sm_complete); fpi_ssm_start(ssm, capture_sm_complete);
} }
@@ -448,15 +448,15 @@ enum activate_states {
static void activate_read_id_cb(struct libusb_transfer *transfer) 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 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; unsigned char *data = transfer->buffer;
if ((transfer->status != LIBUSB_TRANSFER_COMPLETED) || if ((transfer->status != LIBUSB_TRANSFER_COMPLETED) ||
(transfer->length != transfer->actual_length)) { (transfer->length != transfer->actual_length)) {
fp_dbg("read_id cmd failed\n"); fp_dbg("read_id cmd failed\n");
fpi_ssm_mark_aborted(ssm, -EIO); fpi_ssm_mark_failed(ssm, -EIO);
goto out; goto out;
} }
/* ID was read correctly */ /* 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]); data[4], data[3], data[5], data[6], data[7]);
} else { } else {
fp_dbg("Bogus read ID response: %.2x\n", data[AESX660_RESPONSE_TYPE_OFFSET]); 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; goto out;
} }
@@ -487,7 +487,7 @@ static void activate_read_id_cb(struct libusb_transfer *transfer)
break; break;
default: default:
fp_dbg("Failed to init device! init status: %.2x\n", data[7]); 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; break;
} }
@@ -499,9 +499,9 @@ out:
static void activate_read_init_cb(struct libusb_transfer *transfer) 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 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; unsigned char *data = transfer->buffer;
fp_dbg("read_init_cb\n"); 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) || if ((transfer->status != LIBUSB_TRANSFER_COMPLETED) ||
(transfer->length != transfer->actual_length)) { (transfer->length != transfer->actual_length)) {
fp_dbg("read_init transfer status: %d, actual_len: %d\n", transfer->status, 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; goto out;
} }
/* ID was read correctly */ /* ID was read correctly */
if (data[0] != 0x42 || data[3] != 0x01) { if (data[0] != 0x42 || data[3] != 0x01) {
fp_dbg("Bogus read init response: %.2x %.2x\n", data[0], fp_dbg("Bogus read init response: %.2x %.2x\n", data[0],
data[3]); data[3]);
fpi_ssm_mark_aborted(ssm, -EPROTO); fpi_ssm_mark_failed(ssm, -EPROTO);
goto out; goto out;
} }
aesdev->init_cmd_idx++; aesdev->init_cmd_idx++;
@@ -534,55 +534,52 @@ out:
libusb_free_transfer(transfer); 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;
struct aesX660_dev *aesdev = fpi_imgdev_get_user_data(dev); struct aesX660_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev));
switch (fpi_ssm_get_cur_state(ssm)) { switch (fpi_ssm_get_cur_state(ssm)) {
case ACTIVATE_SET_IDLE: case ACTIVATE_SET_IDLE:
aesdev->init_seq_idx = 0; aesdev->init_seq_idx = 0;
fp_dbg("Activate: set idle\n"); 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); aesX660_send_cmd_cb);
break; break;
case ACTIVATE_SEND_READ_ID_CMD: case ACTIVATE_SEND_READ_ID_CMD:
fp_dbg("Activate: read ID\n"); 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); aesX660_send_cmd_cb);
break; break;
case ACTIVATE_READ_ID: case ACTIVATE_READ_ID:
/* Should return 8-byte response */ aesX660_read_response(ssm, _dev, ID_LEN, activate_read_id_cb);
aesX660_read_response(ssm, 8, activate_read_id_cb);
break; break;
case ACTIVATE_SEND_INIT_CMD: case ACTIVATE_SEND_INIT_CMD:
fp_dbg("Activate: send init seq #%d cmd #%d\n", fp_dbg("Activate: send init seq #%d cmd #%d\n",
aesdev->init_seq_idx, aesdev->init_seq_idx,
aesdev->init_cmd_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].cmd,
aesdev->init_seq[aesdev->init_cmd_idx].len, aesdev->init_seq[aesdev->init_cmd_idx].len,
aesX660_send_cmd_cb); aesX660_send_cmd_cb);
break; break;
case ACTIVATE_READ_INIT_RESPONSE: case ACTIVATE_READ_INIT_RESPONSE:
fp_dbg("Activate: read init response\n"); fp_dbg("Activate: read init response\n");
/* Should return 4-byte response */ aesX660_read_response(ssm, _dev, INIT_LEN, activate_read_init_cb);
aesX660_read_response(ssm, 4, activate_read_init_cb);
break; break;
case ACTIVATE_SEND_CALIBRATE_CMD: 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); aesX660_send_cmd_cb);
break; break;
case ACTIVATE_READ_CALIBRATE_DATA: case ACTIVATE_READ_CALIBRATE_DATA:
/* Should return 4-byte response */ aesX660_read_response(ssm, _dev, CALIBRATE_DATA_LEN, aesX660_read_calibrate_data_cb);
aesX660_read_response(ssm, 4, aesX660_read_calibrate_data_cb);
break; 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); int err = fpi_ssm_get_error(ssm);
fp_dbg("status %d", err); fp_dbg("status %d", err);
fpi_imgdev_activate_complete(dev, err); fpi_imgdev_activate_complete(dev, err);
@@ -594,16 +591,15 @@ static void activate_sm_complete(struct fpi_ssm *ssm)
int aesX660_dev_activate(struct fp_img_dev *dev, enum fp_imgdev_state state) int aesX660_dev_activate(struct fp_img_dev *dev, enum fp_imgdev_state state)
{ {
struct fpi_ssm *ssm = fpi_ssm_new(fpi_imgdev_get_dev(dev), activate_run_state, fpi_ssm *ssm = fpi_ssm_new(FP_DEV(dev), activate_run_state,
ACTIVATE_NUM_STATES); ACTIVATE_NUM_STATES, dev);
fpi_ssm_set_user_data(ssm, dev);
fpi_ssm_start(ssm, activate_sm_complete); fpi_ssm_start(ssm, activate_sm_complete);
return 0; return 0;
} }
void aesX660_dev_deactivate(struct fp_img_dev *dev) 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) if (aesdev->fd_data_transfer)
libusb_cancel_transfer(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) 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(); G_DEBUG_HERE();
aesdev->deactivating = FALSE; aesdev->deactivating = FALSE;

View File

@@ -42,6 +42,7 @@ enum {
VFS5011_ID = 19, VFS5011_ID = 19,
VFS0050_ID = 20, VFS0050_ID = 20,
ELAN_ID = 21, ELAN_ID = 21,
SYNAPTICS_ID = 22,
}; };
#endif #endif

File diff suppressed because it is too large Load Diff

View File

@@ -21,26 +21,51 @@
#ifndef __ELAN_H #ifndef __ELAN_H
#define __ELAN_H #define __ELAN_H
#include <string.h>
#include <libusb.h> #include <libusb.h>
/* number of pixels to discard on left and right (along raw image height) #define ELAN_VEND_ID 0x04f3
* because they have different intensity from the rest of the frame */
#define ELAN_FRAME_MARGIN 12 /* 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 */ /* min and max frames in a capture */
#define ELAN_MIN_FRAMES 7 #define ELAN_MIN_FRAMES 7
#define ELAN_MAX_FRAMES 30 #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 /* number of frames to drop at the end of capture because frames captured
* while the finger is being lifted can be bad */ * 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_CMD_LEN 0x2
#define ELAN_EP_CMD_OUT (0x1 | LIBUSB_ENDPOINT_OUT) #define ELAN_EP_CMD_OUT (0x1 | LIBUSB_ENDPOINT_OUT)
#define ELAN_EP_CMD_IN (0x3 | LIBUSB_ENDPOINT_IN) #define ELAN_EP_CMD_IN (0x3 | LIBUSB_ENDPOINT_IN)
#define ELAN_EP_IMG_IN (0x2 | 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 /* usual command timeout and timeout for when we need to check if the finger is
* still on the device */ * still on the device */
#define ELAN_CMD_TIMEOUT 10000 #define ELAN_CMD_TIMEOUT 10000
@@ -50,127 +75,150 @@ struct elan_cmd {
unsigned char cmd[ELAN_CMD_LEN]; unsigned char cmd[ELAN_CMD_LEN];
int response_len; int response_len;
int response_in; int response_in;
unsigned short devices;
}; };
static const struct elan_cmd get_sensor_dim_cmds[] = { static const struct elan_cmd get_sensor_dim_cmd = {
{ .cmd = {0x00, 0x0c},
.cmd = {0x00, 0x0c}, .response_len = 0x4,
.response_len = 0x4, .response_in = ELAN_EP_CMD_IN,
.response_in = ELAN_EP_CMD_IN, .devices = ELAN_ALL_DEV,
},
}; };
static const size_t get_sensor_dim_cmds_len = static const struct elan_cmd get_fw_ver_cmd = {
G_N_ELEMENTS(get_sensor_dim_cmds); .cmd = {0x40, 0x19},
.response_len = 0x2,
static const struct elan_cmd init_start_cmds[] = { .response_in = ELAN_EP_CMD_IN,
{ .devices = ELAN_ALL_DEV,
.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 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[] = { static const struct elan_cmd get_image_cmd = {
/* raw frame sizes are calculated from image dimesions reported by the .cmd = {0x00, 0x09},
/* raw frame sizes are calculated from image dimensions reported by the
* device */ * device */
{ .response_len = -1,
.cmd = {0x00, 0x09}, .response_in = ELAN_EP_IMG_IN,
.response_len = -1, .devices = ELAN_ALL_DEV,
.response_in = ELAN_EP_IMG_IN,
},
}; };
const size_t read_cmds_len = G_N_ELEMENTS(read_cmds); static const struct elan_cmd read_sensor_status_cmd = {
.cmd = {0x40, 0x13},
/* issued after data reads during init and calibration */ .response_len = 0x1,
static const struct elan_cmd init_end_cmds[] = { .response_in = ELAN_EP_CMD_IN,
{ .devices = ELAN_ALL_DEV,
.cmd = {0x40, 0x24},
.response_len = 0x2,
.response_in = ELAN_EP_CMD_IN,
},
}; };
static const size_t init_end_cmds_len = G_N_ELEMENTS(init_end_cmds); static const struct elan_cmd get_calib_status_cmd = {
.cmd = {0x40, 0x23},
/* same command 2 times .response_len = 0x1,
* original driver may observe return value to determine how many times it .response_in = ELAN_EP_CMD_IN,
* should be repeated */ .devices = ELAN_ALL_DEV,
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 size_t calibrate_start_cmds_len = static const struct elan_cmd get_calib_mean_cmd = {
G_N_ELEMENTS(calibrate_start_cmds); .cmd = {0x40, 0x24},
.response_len = 0x2,
/* issued after data reads during init and calibration */ .response_in = ELAN_EP_CMD_IN,
static const struct elan_cmd calibrate_end_cmds[] = { .devices = ELAN_ALL_DEV,
{
.cmd = {0x40, 0x24},
.response_len = 0x2,
.response_in = ELAN_EP_CMD_IN,
},
}; };
static const size_t calibrate_end_cmds_len = static const struct elan_cmd led_on_cmd = {
G_N_ELEMENTS(calibrate_end_cmds); .cmd = {0x40, 0x31},
.response_len = ELAN_CMD_SKIP_READ,
static const struct elan_cmd capture_start_cmds[] = { .response_in = ELAN_EP_CMD_IN,
/* led on */ .devices = ELAN_ALL_DEV,
{
.cmd = {0x40, 0x31},
.response_len = 0x0,
.response_in = ELAN_EP_CMD_IN,
},
}; };
static size_t capture_start_cmds_len = G_N_ELEMENTS(capture_start_cmds); /* wait for finger
* subsequent read will not complete until finger is placed on the reader */
static const struct elan_cmd capture_wait_finger_cmds[] = { static const struct elan_cmd pre_scan_cmd = {
/* wait for finger .cmd = {0x40, 0x3f},
* subsequent read will not complete until finger is placed on the reader */ .response_len = 0x1,
{ .response_in = ELAN_EP_CMD_IN,
.cmd = {0x40, 0x3f}, .devices = ELAN_ALL_DEV,
.response_len = 0x1,
.response_in = ELAN_EP_CMD_IN,
},
}; };
static size_t capture_wait_finger_cmds_len = /* led off, stop waiting for finger */
G_N_ELEMENTS(capture_wait_finger_cmds); static const struct elan_cmd stop_cmd = {
.cmd = {0x00, 0x0b},
static const struct elan_cmd deactivate_cmds[] = { .response_len = ELAN_CMD_SKIP_READ,
/* led off */ .response_in = ELAN_EP_CMD_IN,
{ .devices = ELAN_ALL_DEV,
.cmd = {0x00, 0x0b},
.response_len = 0x0,
.response_in = ELAN_EP_CMD_IN,
},
}; };
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_done(fpi_ssm *ssm);
static void elan_cmd_read(struct fpi_ssm *ssm); static void elan_cmd_read(fpi_ssm *ssm, struct fp_img_dev *dev);
static void elan_run_next_cmd(struct fpi_ssm *ssm);
static void elan_calibrate(struct fp_img_dev *dev);
static void elan_capture(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 #endif

View File

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

View File

@@ -169,25 +169,25 @@ capture(struct fp_img_dev *dev, gboolean unconditional,
image = g_malloc0(RAW_IMAGE_SIZE); image = g_malloc0(RAW_IMAGE_SIZE);
if ((r = bulk_write_safe(fpi_imgdev_get_usb_dev(dev), LED_ON))) { if ((r = bulk_write_safe(fpi_dev_get_usb_dev(FP_DEV(dev)), LED_ON))) {
fp_err("Command: LED_ON"); fp_err("Command: LED_ON");
goto out; goto out;
} }
if ((r = bulk_write_safe(fpi_imgdev_get_usb_dev(dev), CAPTURE_READY))) { if ((r = bulk_write_safe(fpi_dev_get_usb_dev(FP_DEV(dev)), CAPTURE_READY))) {
fp_err("Command: CAPTURE_READY"); fp_err("Command: CAPTURE_READY");
goto out; goto out;
} }
read: read:
if ((r = bulk_write_safe(fpi_imgdev_get_usb_dev(dev), CAPTURE_READ))) { if ((r = bulk_write_safe(fpi_dev_get_usb_dev(FP_DEV(dev)), CAPTURE_READ))) {
fp_err("Command: CAPTURE_READ"); fp_err("Command: CAPTURE_READ");
goto out; goto out;
} }
/* Now we are ready to read from dev */ /* Now we are ready to read from dev */
r = libusb_bulk_transfer(fpi_imgdev_get_usb_dev(dev), &msg, &bytes, BULK_TIMEOUT * 10); r = libusb_bulk_transfer(fpi_dev_get_usb_dev(FP_DEV(dev)), &msg, &bytes, BULK_TIMEOUT * 10);
if (r < 0 || bytes < 1) if (r < 0 || bytes < 1)
goto read; goto read;
@@ -215,7 +215,7 @@ read:
p += sizeof SOL + 4; p += sizeof SOL + 4;
int j; int j;
for (j = 0; j < RAW_IMAGE_WIDTH; j++) { for (j = 0; j < RAW_IMAGE_WIDTH; j++) {
/** /*
* Convert from 4 to 8 bits * Convert from 4 to 8 bits
* The SECUGEN-FDU2000 has 4 lines of data, so we need to join 2 bytes into 1 * The SECUGEN-FDU2000 has 4 lines of data, so we need to join 2 bytes into 1
*/ */
@@ -228,12 +228,12 @@ read:
} }
} }
if ((r = bulk_write_safe(fpi_imgdev_get_usb_dev(dev), CAPTURE_END))) { if ((r = bulk_write_safe(fpi_dev_get_usb_dev(FP_DEV(dev)), CAPTURE_END))) {
fp_err("Command: CAPTURE_END"); fp_err("Command: CAPTURE_END");
goto out; goto out;
} }
if ((r = bulk_write_safe(fpi_imgdev_get_usb_dev(dev), LED_OFF))) { if ((r = bulk_write_safe(fpi_dev_get_usb_dev(FP_DEV(dev)), LED_OFF))) {
fp_err("Command: LED_OFF"); fp_err("Command: LED_OFF");
goto out; goto out;
} }
@@ -254,27 +254,27 @@ static
gint dev_init(struct fp_img_dev *dev, unsigned long driver_data) gint dev_init(struct fp_img_dev *dev, unsigned long driver_data)
{ {
gint r; gint r;
//if ( (r = usb_set_configuration(fpi_imgdev_get_usb_dev(dev), 1)) < 0 ) //if ( (r = usb_set_configuration(fpi_dev_get_usb_dev(FP_DEV(dev)), 1)) < 0 )
// goto out; // goto out;
if ( (r = libusb_claim_interface(fpi_imgdev_get_usb_dev(dev), 0)) < 0 ) { if ( (r = libusb_claim_interface(fpi_dev_get_usb_dev(FP_DEV(dev)), 0)) < 0 ) {
fp_err("could not claim interface 0: %s", libusb_error_name(r)); fp_err("could not claim interface 0: %s", libusb_error_name(r));
return r; return r;
} }
//if ( (r = usb_set_altinterface(fpi_imgdev_get_usb_dev(dev), 1)) < 0 ) //if ( (r = usb_set_altinterface(fpi_dev_get_usb_dev(FP_DEV(dev)), 1)) < 0 )
// goto out; // goto out;
//if ( (r = usb_clear_halt(fpi_imgdev_get_usb_dev(dev), EP_CMD)) < 0 ) //if ( (r = usb_clear_halt(fpi_dev_get_usb_dev(FP_DEV(dev)), EP_CMD)) < 0 )
// goto out; // goto out;
/* Make sure sensor mode is not capture_{ready|read} */ /* Make sure sensor mode is not capture_{ready|read} */
if ((r = bulk_write_safe(fpi_imgdev_get_usb_dev(dev), CAPTURE_END))) { if ((r = bulk_write_safe(fpi_dev_get_usb_dev(FP_DEV(dev)), CAPTURE_END))) {
fp_err("Command: CAPTURE_END"); fp_err("Command: CAPTURE_END");
goto out; goto out;
} }
if ((r = bulk_write_safe(fpi_imgdev_get_usb_dev(dev), LED_OFF))) { if ((r = bulk_write_safe(fpi_dev_get_usb_dev(FP_DEV(dev)), LED_OFF))) {
fp_err("Command: LED_OFF"); fp_err("Command: LED_OFF");
goto out; goto out;
} }
@@ -289,10 +289,10 @@ out:
static static
void dev_exit(struct fp_img_dev *dev) void dev_exit(struct fp_img_dev *dev)
{ {
if (bulk_write_safe(fpi_imgdev_get_usb_dev(dev), CAPTURE_END)) if (bulk_write_safe(fpi_dev_get_usb_dev(FP_DEV(dev)), CAPTURE_END))
fp_err("Command: CAPTURE_END"); fp_err("Command: CAPTURE_END");
libusb_release_interface(fpi_imgdev_get_usb_dev(dev), 0); libusb_release_interface(fpi_dev_get_usb_dev(FP_DEV(dev)), 0);
} }
static const struct usb_id id_table[] = { static const struct usb_id id_table[] = {

View File

@@ -0,0 +1,260 @@
/*
* Copyright (C) 2019 Synaptics Inc
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "bmkt_internal.h"
#include "bmkt_message.h"
#include "sensor.h"
struct bmkt_ctx
{
bmkt_sensor_t sensor;
};
bmkt_ctx_t g_ctx;
int bmkt_init(bmkt_ctx_t **ctx)
{
if (ctx == NULL)
{
return BMKT_INVALID_PARAM;
}
memset(&g_ctx, 0, sizeof(bmkt_ctx_t));
*ctx = &g_ctx;
bmkt_dbg_log("%s: context size: %ld", __func__, sizeof(bmkt_ctx_t));
return BMKT_SUCCESS;
}
void bmkt_exit(bmkt_ctx_t *ctx)
{
if (ctx == NULL)
{
return;
}
}
int bmkt_open(bmkt_ctx_t *ctx, bmkt_sensor_t **sensor,
bmkt_general_error_cb_t err_cb, void *err_cb_ctx, libusb_device_handle *usb_handle)
{
int ret;
if (ctx == NULL || sensor == NULL)
{
return BMKT_INVALID_PARAM;
}
*sensor = &ctx->sensor;
memset(*sensor, 0, sizeof(bmkt_sensor_t));
(*sensor)->usb_xport.handle = usb_handle;
ret = bmkt_sensor_open(*sensor, err_cb, err_cb_ctx);
if (ret != BMKT_SUCCESS)
{
return ret;
}
return BMKT_SUCCESS;
}
int bmkt_init_fps(bmkt_sensor_t *sensor)
{
int ret;
uint8_t *resp_buf;
int resp_len;
bmkt_response_t resp;
if (sensor->sensor_state != BMKT_SENSOR_STATE_UNINIT)
{
//sensor is already initialized
return BMKT_OPERATION_DENIED;
}
ret = bmkt_sensor_send_message_sync(sensor, BMKT_CMD_FPS_INIT, 0, NULL, &resp_buf, &resp_len, &resp);
if (ret != BMKT_SUCCESS)
{
return ret;
}
if (resp.result != BMKT_SUCCESS)
{
return resp.result;
}
return bmkt_sensor_init_fps(sensor);
}
int bmkt_close(bmkt_sensor_t *sensor)
{
if (sensor == NULL)
{
return BMKT_INVALID_PARAM;
}
return bmkt_sensor_close(sensor);
}
int bmkt_delete_enrolled_user(bmkt_sensor_t *sensor, uint8_t finger_id, const char *user_id, uint32_t user_id_len,
bmkt_resp_cb_t resp_cb, void *cb_ctx)
{
int ret;
uint8_t payload[BMKT_MAX_USER_ID_LEN + sizeof(finger_id)];
uint8_t payload_len;
if (sensor == NULL)
{
return BMKT_INVALID_PARAM;
}
if (user_id_len > BMKT_MAX_USER_ID_LEN)
{
return BMKT_INVALID_PARAM;
}
memset(payload, 0, sizeof(payload));
payload_len = user_id_len + sizeof(finger_id);
payload[0] = finger_id;
memcpy(&payload[1], user_id, user_id_len);
ret = bmkt_sensor_send_message(sensor, BMKT_CMD_DEL_USER_FP, payload_len, payload, resp_cb, cb_ctx);
if (ret != BMKT_SUCCESS)
{
return ret;
}
return BMKT_SUCCESS;
}
int bmkt_enroll(bmkt_sensor_t *sensor, const uint8_t *user_id, uint32_t user_id_len,
uint8_t finger_id, bmkt_resp_cb_t resp_cb, void *cb_ctx)
{
int ret = BMKT_GENERAL_ERROR;
/* Payload data for enroll_user [1 byte<backup option> 1 byte<finger Id> maximum length: 100 bytes]*/
uint8_t payload[BMKT_MAX_USER_ID_LEN + 2];
uint8_t payload_len = 0;
/* Backup options is not supported for Prometheus. */
uint8_t backup_opt = 0;
if (sensor == NULL || user_id == NULL)
{
return BMKT_INVALID_PARAM;
}
if (user_id_len > BMKT_MAX_USER_ID_LEN)
{
return BMKT_INVALID_PARAM;
}
payload_len = user_id_len + 2;
payload[0] = backup_opt;
payload[1] = finger_id;
memcpy(&payload[2], user_id, user_id_len);
ret = bmkt_sensor_send_message(sensor, BMKT_CMD_ENROLL_USER, payload_len, payload, resp_cb, cb_ctx);
if (ret != BMKT_SUCCESS)
{
return ret;
}
return BMKT_SUCCESS;
}
int bmkt_verify(bmkt_sensor_t *sensor, bmkt_user_id_t *user,
bmkt_resp_cb_t resp_cb, void *cb_ctx)
{
int ret;
uint8_t payload[BMKT_MAX_USER_ID_LEN + 1];
uint8_t payload_len;
if (sensor == NULL || user == NULL || user->user_id == NULL)
{
return BMKT_INVALID_PARAM;
}
if (user->user_id_len == 0 || user->user_id_len > BMKT_MAX_USER_ID_LEN)
{
return BMKT_INVALID_PARAM;
}
payload_len = user->user_id_len;
memset(payload, 0, sizeof(payload));
memcpy(&payload[0], user->user_id, user->user_id_len);
ret = bmkt_sensor_send_message(sensor, BMKT_CMD_VERIFY_USER, payload_len, payload, resp_cb,
cb_ctx);
if (ret != BMKT_SUCCESS)
{
return ret;
}
return BMKT_SUCCESS;
}
void bmkt_op_set_state(bmkt_sensor_t* sensor, bmkt_op_state_t state)
{
sensor->op_state = state;
}
void bmkt_op_sm(bmkt_sensor_t *sensor)
{
int ret;
int len = 0;
bmkt_dbg_log("bmkt_op_sm state = %d", sensor->op_state);
switch(sensor->op_state)
{
case BMKT_OP_STATE_GET_RESP:
ret = usb_receive_resp_async(&sensor->usb_xport, &len);
if (ret != BMKT_SUCCESS)
{
bmkt_dbg_log("bmkt_op_sm: usb_receive_resp_async failed %d", ret);
}
break;
case BMKT_OP_STATE_WAIT_INTERRUPT:
ret = usb_check_interrupt(&sensor->usb_xport);
if (ret != BMKT_SUCCESS)
{
bmkt_dbg_log("bmkt_op_sm: check_interrupt failed %d", ret);
}
break;
case BMKT_OP_STATE_SEND_ASYNC:
ret = bmkt_sensor_send_async_read_command(sensor);
if (ret != BMKT_SUCCESS)
{
bmkt_dbg_log("bmkt_op_sm: bmkt_sensor_send_async_read_command failed %d", ret);
}
break;
case BMKT_OP_STATE_COMPLETE:
break;
default:
break;
}
}
void bmkt_op_next_state(bmkt_sensor_t* sensor)
{
if(sensor->op_state != BMKT_OP_STATE_COMPLETE)
sensor->op_state = (sensor->op_state + 1) % BMKT_OP_STATE_COMPLETE;
bmkt_op_sm(sensor);
}

View File

@@ -0,0 +1,452 @@
/*
* Synaptics MiS Fingerprint Sensor Interface
* Copyright (C) 2019 Synaptics Inc
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _BMKT_H_
#define _BMKT_H_
/**< User ID maximum length allowed */
#define BMKT_MAX_USER_ID_LEN 100
/**< Software Part Number length */
#define BMKT_PART_NUM_LEN 10
/**< Software supplier identification length */
#define BMKT_SUPPLIER_ID_LEN 2
/**< Maximum namber of templates for storing in internal flash of the fingerprint sensor */
#define BMKT_MAX_NUM_TEMPLATES_INTERNAL_FLASH 15
#include <stdint.h>
#include "libusb-1.0/libusb.h"
#include "bmkt_response.h"
/*!
*******************************************************************************
** Type definition for result
*/
/** No error; Operation successfully completed. */
#define BMKT_SUCCESS 0
/** Fingerprint system not initialized */
#define BMKT_FP_SYSTEM_NOT_INITIALIZED 101
/** Fingerprint system busy performing another operation */
#define BMKT_FP_SYSTEM_BUSY 102
/** Operation not allowed */
#define BMKT_OPERATION_DENIED 103
/** System ran out of memory while performing operation */
#define BMKT_OUT_OF_MEMORY 104
/** Corrupt message, CRC check fail or truncated message */
#define BMKT_CORRUPT_MESSAGE 110
/** One of the command parameters is outside the range of valid values */
#define BMKT_INVALID_PARAM 111
/** Unrecognized message or message with invalid message ID */
#define BMKT_UNRECOGNIZED_MESSAGE 112
/** Operation time out */
#define BMKT_OP_TIME_OUT 113
/** General error cause of error cannot be determined */
#define BMKT_GENERAL_ERROR 114
#define BMKT_SET_SECURITY_LEVEL_FAIL 120
#define BMKT_GET_SECURITY_LEVEL_FAIL 121
/** Fingerprint sensor reset while operation was being performed */
#define BMKT_SENSOR_RESET 201
/** Fingerprint sensor malfunctioned */
#define BMKT_SENSOR_MALFUNCTION 202
/** Fingerprint sensor cannot be accessed despite repeated attempts */
#define BMKT_SENSOR_TAMPERED 203
/**
* BMKT_SENSOR_NOT_INIT:
* Fingerprint sensor module not initialized yet not ready for use
* (different from error code 101 which indicates that the entire system
* has not been initialized)
*/
#define BMKT_SENSOR_NOT_INIT 204
/** Number of re-pairing operations exceeded limit or re-pairing has been disabled */
#define BMKT_OWNERSHIP_RESET_MAX_EXCEEDED 205
/**
* BMKT_SENSOR_STIMULUS_ERROR:
* There is a finger or debris on the sensor that needs to be removed
* before issuing this command
*/
#define BMKT_SENSOR_STIMULUS_ERROR 213
/**
* BMKT_CORRUPT_TEMPLATE_DATA:
* One of the fingerprint templates stored on flash is corrupt.
* This error code is returned in case of failure in finding a fingerprint match
* during identify or verify operations while also detecting that one or more
* fingerprint templates stored on the flash has become corrupted
*/
#define BMKT_CORRUPT_TEMPLATE_DATA 300
/** Failed to extract features from fingerprint image acquired by sensor */
#define BMKT_FEATURE_EXTRACT_FAIL 301
/** Failed to generate fingerprint template */
#define BMKT_ENROLL_FAIL 302
/** Specified finger already enrolled for this user */
#define BMKT_ENROLLMENT_EXISTS 303
/** Invalid fingerprint image */
#define BMKT_INVALID_FP_IMAGE 304
/** No matching user fingerprint template found in database */
#define BMKT_FP_NO_MATCH 404
/** Fingerprint database is full */
#define BMKT_FP_DATABASE_FULL 501
/** Fingerprint database is empty */
#define BMKT_FP_DATABASE_EMPTY 502
/** Cannot access fingerprint database */
#define BMKT_FP_DATABASE_ACCESS_FAIL 503
/** Fingerprint template record does not exist */
#define BMKT_FP_DATABASE_NO_RECORD_EXISTS 504
/** Failed to read/write system parameters stored on flash */
#define BMKT_FP_PARAM_ACCESS_FAIL 505
/** Fingerprint is a spoof */
#define BMKT_FP_SPOOF_ALERT 801
/** Anti-spoof module failure */
#define BMKT_ANTI_SPOOF_MODULE_FAIL 802
#define BMKT_CORRUPT_UPDATE_IMAGE 901
#define BMKT_SYSTEM_UPDATE_FAIL 902
#define BMKT_EVENT_NOT_SET 1000
#define BMKT_SENSOR_NOT_READY 1001
#define BMKT_TIMEOUT 1002
#define BMKT_SENSOR_RESPONSE_PENDING 1003
#ifdef __cplusplus
extern "C" {
#endif
/**
* bmkt_mode:
* Fingerprint system operational mode values level 1
*/
typedef enum bmkt_mode
{
BMKT_STATE_UNINIT = 0xFF,
BMKT_STATE_IDLE = 0x00,
BMKT_STATE_ENROLL = 0x10,
BMKT_STATE_IDENTIFY = 0x20,
BMKT_STATE_VERIFY = 0x30,
BMKT_STATE_DB_OPS = 0x40,
BMKT_STATE_SYS_TEST = 0x50,
BMKT_STATE_SYS_OPS = 0x60,
} bmkt_mode_t;
/**
* bmkt_mode_level2:
* Fingerprint system operational mode values level 2
*/
typedef enum bmkt_mode_level2
{
BMKT_STATE_L2_IDLE = 0x00,
BMKT_STATE_L2_STARTING = 0x11,
BMKT_STATE_L2_WAITING_FOR_FINGER = 0x12,
BMKT_STATE_L2_CAPTURE_IMAGE = 0x13,
BMKT_STATE_L2_CAPTURE_COMPLETE = 0x14,
BMKT_STATE_L2_EXTRACT_FEATURE = 0x15,
BMKT_STATE_L2_CREATE_TEMPLATE = 0x16,
BMKT_STATE_L2_READING_FROM_FLASH = 0x17,
BMKT_STATE_L2_WRITING_TO_FLASH = 0x18,
BMKT_STATE_L2_FINISHING = 0x19,
BMKT_STATE_L2_CANCELING_OP = 0x20,
BMKT_STATE_L2_MATCHING = 0x21,
BMKT_STATE_L2_TRANSMITTING_RESPONSE = 0x22,
BMKT_STATE_L2_READY_POWER_DOWN = 0xF0,
} bmkt_mode_level2_t;
/**
* bmkt_transport_type:
* Fingerprint system transport types
*/
typedef enum bmkt_transport_type
{
BMKT_TRANSPORT_TYPE_USB = 0,
} bmkt_transport_type_t;
/**
* bmkt_usb_config:
* Structure represcontainingenting USB configuration details
*/
typedef struct bmkt_usb_config
{
int product_id; /**< USB device product ID */
} bmkt_usb_config_t;
/**
* bmkt_transport_config_t:
* Union containing transport configuration details
*/
typedef union
{
bmkt_usb_config_t usb_config;
} bmkt_transport_config_t;
/**
* bmkt_sensor_desc_t:
* Structure containing fingerprint system description
*/
typedef struct bmkt_sensor_desc
{
int product_id;
int flags;
} bmkt_sensor_desc_t;
/**
* bmkt_finger_state_t:
* Finger state representation values.
*/
typedef enum
{
BMKT_FINGER_STATE_UNKNOWN = 0,
BMKT_FINGER_STATE_ON_SENSOR,
BMKT_FINGER_STATE_NOT_ON_SENSOR,
} bmkt_finger_state_t;
/**
* bmkt_finger_event_t:
* Structure containing finger state
*/
typedef struct bmkt_finger_event
{
bmkt_finger_state_t finger_state;
} bmkt_finger_event_t;
typedef struct bmkt_user_id
{
uint8_t user_id_len;
uint8_t user_id[BMKT_MAX_USER_ID_LEN];
} bmkt_user_id_t;
typedef struct bmkt_ctx bmkt_ctx_t;
typedef struct bmkt_sensor bmkt_sensor_t;
typedef struct bmkt_sensor_desc bmkt_sensor_desc_t;
typedef struct bmkt_event bmkt_event_t;
typedef int (*bmkt_resp_cb_t)(bmkt_response_t *resp, void *cb_ctx);
typedef int (*bmkt_event_cb_t)(bmkt_finger_event_t *event, void *cb_ctx);
typedef int (*bmkt_general_error_cb_t)(uint16_t error, void *cb_ctx);
/**
* bmkt_init:
* @brief Initialize the bmkt library.
*
* @param[out] ctx A double pointer to return the created library module context pointer.
*
* @return BMKT_SUCCESS
* BMKT_INVALID_PARAM
*
* The bmkt_init function must be invoked to intialize the bmkt library before calling other functions.
* The library module context pointer is returned, which must be passed to all other library interface functions.
*/
int
bmkt_init(
bmkt_ctx_t ** ctx);
/**
* bmkt_exit:
* @brief Uninitialize the bmkt library.
*
* @param[in] ctx Context pointer created by bmkt_init.
*
* @return none
*
* The bmkt_exit function must be invoked when the module is no longer needed.
*/
void
bmkt_exit(
bmkt_ctx_t * ctx);
/**
* bmkt_open:
* @brief Open the specified sensor module.
*
* @param[in] ctx Context pointer created by bmkt_init.
* @param[out] sensor A double pointer to return the created sensor module pointer
* @param[in] err_cb General Error callback function
* @param[in] err_cb_ctx General Error callback user context
*
* @return VCS_RESULT_OK if success
*
* The bmkt_open function must be called to open a specific sensor module. Returned sensor module pointer
* must be passed to all other interface functions that expect a sensor pointer.
*/
int
bmkt_open(
bmkt_ctx_t * ctx,
bmkt_sensor_t ** sensor,
bmkt_general_error_cb_t err_cb,
void * err_cb_ctx,
libusb_device_handle * handle);
/**
* bmkt_close:
* @brief Close the specified sensor module, and release all the resources
*
* @param[in] sensor The sensor module pointer
*
* @return VCS_RESULT_OK if success
*
* The bmkt_close function must be invoked when the sensor module is no longer needed.
*/
int
bmkt_close(
bmkt_sensor_t * sensor);
/**
* bmkt_init_fps:
* @brief Initialize the sensor module.
*
* @param[in] sensor The sensor module pointer
*
* @return VCS_RESULT_OK if success
*
* Initializes the fingerprint sensor module. Must be the first command to be issued to the fingerprint sensor module, before any other commands are issued.
*/
int
bmkt_init_fps(
bmkt_sensor_t * sensor);
/**
* bmkt_enroll:
* @brief Put the fingerprint sensor module into enrollment mode to Enroll a users fingerprint into the system.
*
* @param[in] sensor The sensor module pointer
* @param[in] user_id Enrolled User ID
* @param[in] user_id_len Enrolled User ID lenght
* @param[in] finger_id Enrolled finger ID
* @param[in] resp_cb Responce callback function. Available responses:
* - BMKT_RSP_ENROLL_READY
* - BMKT_RSP_CAPTURE_COMPLETE
* - BMKT_RSP_ENROLL_REPORT
* - BMKT_RSP_ENROLL_PAUSED
* - BMKT_RSP_ENROLL_RESUMED
* - BMKT_RSP_ENROLL_FAIL
* - BMKT_RSP_ENROLL_OK
* @param[in] cb_ctx Responce callback user context
*
* @return VCS_RESULT_OK if success
*
* Enrolled users have to touch the fingerprint sensor multiple times based on cues provided by the system.
* After successful enrollment, a template is generated from features of the users fingerprint and stored
* in encrypted storage within the fingerprint sensor module.
* When this command is being executed, fingerprint sensor modules mode is: Enrollment
*/
int
bmkt_enroll(
bmkt_sensor_t * sensor,
const uint8_t * user_id,
uint32_t user_id_len,
uint8_t finger_id,
bmkt_resp_cb_t resp_cb,
void * cb_ctx);
/**
* bmkt_verify:
* @brief Put the fingerprint sensor module into verification mode.
*
* @param[in] sensor The sensor module pointer
* @param[in] user Enrolled User
* @param[in] resp_cb Responce callback function. Available responses:
* - BMKT_RSP_CAPTURE_COMPLETE
* - BMKT_RSP_VERIFY_READY
* - BMKT_RSP_VERIFY_FAIL
* - BMKT_RSP_VERIFY_OK
* @param[in] cb_ctx Responce callback user context
*
* @return VCS_RESULT_OK if success
*
* The user being verifyed has to touch the fingerprint sensor once based on a cue provided by the system.
* The Captured fingerprint is matched only against the stored templates corresponding to specifyed user ID,
* If a users fingerprint cannot be matched to any of the stored fingerprint templates of the specified user or
* if the fingerprint sensor module detects that the fingerprint being presented to the sensor is a spoof,
* then an error response is generated.
* When this command is being executed, fingerprint sensor modules mode is: Verification
*/
int
bmkt_verify(
bmkt_sensor_t * sensor,
bmkt_user_id_t* user,
bmkt_resp_cb_t resp_cb,
void * cb_ctx);
/**
* bmkt_delete_enrolled_user:
* @brief Delete a specific fingerprint template of an enrolled user from the database.
*
* @param[in] sensor The sensor module pointer
* @param[in] finger_id Finger ID to be deleted
* @param[in] user_id User ID to be deleted
* @param[in] user_id_len User ID lenght
* @param[in] resp_cb Responce callback function. Available responses:
* - BMKT_RSP_DEL_USER_FP_FAIL
* - BMKT_RSP_DEL_USER_FP_OK
* @param[in] cb_ctx Responce callback user context
*
* @return VCS_RESULT_OK if success
*
* If the value of finger ID is set equal to 0 then all fingerprints of that user will be deleted from the database.
* If the value of user ID is set to an empty string (string with length 0) and the finger ID is set equal to 0 then
* all templates stored in the fingerprint database which are marked as corrupt will be deleted.
* When this command is being executed, fingerprint sensor modules mode is: Database operations
*/
int
bmkt_delete_enrolled_user(
bmkt_sensor_t * sensor,
uint8_t finger_id,
const char * user_id,
uint32_t user_id_len,
bmkt_resp_cb_t resp_cb,
void * cb_ctx);
/**
* bmkt_register_finger_event_notification:
* @brief Register finger presence event callback function
*
* @param[in] sensor The sensor module pointer
* @param[in] cb Event callback function
* @param[in] cb_ctx Event callback user context
*
* @return VCS_RESULT_OK if success
*
* The registered callback function will be called whenever a finger is detected as being placed on the sensor or removed from the sensor.
*/
int
bmkt_register_finger_event_notification(
bmkt_sensor_t * sensor,
bmkt_event_cb_t cb,
void * cb_ctx);
typedef enum
{
BMKT_OP_STATE_START = -1,
BMKT_OP_STATE_GET_RESP,
BMKT_OP_STATE_WAIT_INTERRUPT,
BMKT_OP_STATE_SEND_ASYNC,
BMKT_OP_STATE_COMPLETE,
} bmkt_op_state_t;
void bmkt_op_set_state(bmkt_sensor_t* sensor, bmkt_op_state_t state);
#ifdef __cplusplus
}
#endif
#endif /* _BMKT_H_ */

View File

@@ -0,0 +1,44 @@
/*
* Copyright (C) 2019 Synaptics Inc
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _BMKT_INTERNAL_H_
#define _BMKT_INTERNAL_H_
#include "bmkt.h"
#include "bmkt_message.h"
#include <time.h>
#include <errno.h>
#include <stdarg.h>
#include <string.h>
#include <stdio.h>
#include "fp_internal.h"
uint32_t extract32(const uint8_t *buf, int *offset);
uint16_t extract16(const uint8_t *buf, int *offset);
uint8_t extract8(const uint8_t *buf, int *offset);
void print_buffer(uint8_t *buf, int len);
#define bmkt_dbg_log fp_dbg
#define bmkt_info_log fp_info
#define bmkt_warn_log fp_warn
#define bmkt_err_log fp_err
void bmkt_op_next_state(bmkt_sensor_t *sensor);
#endif /* _BMKT_INTERNAL_H_ */

View File

@@ -0,0 +1,397 @@
/*
* Copyright (C) 2019 Synaptics Inc
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "bmkt_internal.h"
#include "bmkt_response.h"
#include "bmkt_message.h"
#include "usb_transport.h"
#include "sensor.h"
static int parse_error_response(bmkt_msg_resp_t *msg_resp, bmkt_response_t *resp)
{
if (msg_resp->payload_len != 2)
{
return BMKT_UNRECOGNIZED_MESSAGE;
}
resp->result = (msg_resp->payload[0] << 8) | msg_resp->payload[1];
return BMKT_SUCCESS;
}
static int parse_init_ok(bmkt_msg_resp_t *msg_resp, bmkt_response_t *resp)
{
bmkt_init_resp_t *init_resp = &resp->response.init_resp;
if (msg_resp->payload_len != 1)
{
return BMKT_UNRECOGNIZED_MESSAGE;
}
init_resp->finger_presence = extract8(msg_resp->payload, NULL);
return BMKT_SUCCESS;
}
static int parse_fps_mode_report(bmkt_msg_resp_t *msg_resp, bmkt_response_t *resp)
{
int offset = 0;
bmkt_fps_mode_resp_t *fps_mode_resp = &resp->response.fps_mode_resp;
if (msg_resp->payload_len != sizeof(bmkt_fps_mode_resp_t))
{
return BMKT_UNRECOGNIZED_MESSAGE;
}
fps_mode_resp->mode = extract8(msg_resp->payload, &offset);
fps_mode_resp->level2_mode = extract8(msg_resp->payload, &offset);
fps_mode_resp->cmd_id = extract8(msg_resp->payload, &offset);
fps_mode_resp->finger_presence = extract8(msg_resp->payload, &offset);
return BMKT_SUCCESS;
}
static int parse_enroll_report(bmkt_msg_resp_t *msg_resp, bmkt_response_t *resp)
{
bmkt_enroll_resp_t *enroll_resp = &resp->response.enroll_resp;
if (msg_resp->payload_len != 1)
{
return BMKT_UNRECOGNIZED_MESSAGE;
}
enroll_resp->progress = extract8(msg_resp->payload, NULL);
return BMKT_SUCCESS;
}
static int parse_enroll_ok(bmkt_msg_resp_t *msg_resp, bmkt_response_t *resp)
{
bmkt_enroll_resp_t *enroll_resp = &resp->response.enroll_resp;
if (msg_resp->payload_len < 1 || msg_resp->payload_len > (BMKT_MAX_USER_ID_LEN + 1))
{
return BMKT_UNRECOGNIZED_MESSAGE;
}
enroll_resp->finger_id = msg_resp->payload[0];
memcpy(enroll_resp->user_id, &msg_resp->payload[1], msg_resp->payload_len - 1);
return BMKT_SUCCESS;
}
static int parse_auth_ok(bmkt_msg_resp_t *msg_resp, bmkt_response_t *resp)
{
bmkt_identify_resp_t *id_resp = &resp->response.id_resp;
if (msg_resp->payload_len < 3 || msg_resp->payload_len > (BMKT_MAX_USER_ID_LEN + 3))
{
return BMKT_UNRECOGNIZED_MESSAGE;
}
id_resp->match_result = (double)msg_resp->payload[0] + 0.01 * (double)msg_resp->payload[1];
id_resp->finger_id = msg_resp->payload[2];
memcpy(id_resp->user_id, &msg_resp->payload[3], msg_resp->payload_len - 3);
return BMKT_SUCCESS;
}
static int parse_security_level_report(bmkt_msg_resp_t *msg_resp, bmkt_response_t *resp)
{
bmkt_set_sec_level_resp_t *sec_level_resp = &resp->response.sec_level_resp;
if (msg_resp->payload_len != 1)
{
return BMKT_UNRECOGNIZED_MESSAGE;
}
sec_level_resp->sec_level = extract8(msg_resp->payload, NULL);
return BMKT_SUCCESS;
}
static int parse_del_all_users_progress_report(bmkt_msg_resp_t *msg_resp, bmkt_response_t *resp)
{
bmkt_del_all_users_resp_t *del_all_users_resp = &resp->response.del_all_users_resp;
if (msg_resp->payload_len != 1)
{
return BMKT_UNRECOGNIZED_MESSAGE;
}
del_all_users_resp->progress = extract8(msg_resp->payload, NULL);
return BMKT_SUCCESS;
}
static int parse_db_cap_report(bmkt_msg_resp_t *msg_resp, bmkt_response_t *resp)
{
bmkt_get_db_capacity_resp_t *db_cap_resp = &resp->response.db_cap_resp;
int offset = 0;
if (msg_resp->payload_len < 2 || msg_resp->payload_len > 4)
{
return BMKT_UNRECOGNIZED_MESSAGE;
}
db_cap_resp->total = extract8(msg_resp->payload, &offset);
db_cap_resp->empty = extract8(msg_resp->payload, &offset);
if (msg_resp->payload_len == 4)
{
db_cap_resp->bad_slots = extract8(msg_resp->payload, &offset);
db_cap_resp->corrupt_templates = extract8(msg_resp->payload, &offset);
}
return BMKT_SUCCESS;
}
static int parse_get_enrolled_fingers_report(bmkt_msg_resp_t *msg_resp, bmkt_response_t *resp)
{
int offset = 0;
int i = 0;
if (msg_resp->payload_len < 2)
{
return BMKT_UNRECOGNIZED_MESSAGE;
}
/* 2 bytes per finger so calculate the total number of fingers to process*/
int num_fingers = (msg_resp->payload_len) / 2;
bmkt_enrolled_fingers_resp_t *get_enrolled_fingers_resp = &resp->response.enrolled_fingers_resp;
for (i = 0; i < num_fingers; i++)
{
get_enrolled_fingers_resp->fingers[i].finger_id = extract8(msg_resp->payload, &offset);
get_enrolled_fingers_resp->fingers[i].template_status = extract8(msg_resp->payload, &offset);
}
return BMKT_SUCCESS;
}
static int parse_get_enrolled_users_report(bmkt_msg_resp_t *msg_resp, bmkt_response_t *resp)
{
int offset = 0;
int i = 0;
/* the payload is 2 bytes + template data */
if (msg_resp->payload_len < 2)
{
return BMKT_UNRECOGNIZED_MESSAGE;
}
bmkt_enroll_templates_resp_t *get_enroll_templates_resp = &resp->response.enroll_templates_resp;
get_enroll_templates_resp->total_query_messages = extract8(msg_resp->payload, &offset);
get_enroll_templates_resp->query_sequence = extract8(msg_resp->payload, &offset);
int n = 0;
for (n = 0; n < BMKT_MAX_NUM_TEMPLATES_INTERNAL_FLASH; n++)
{
if (offset >= msg_resp->payload_len)
break;
get_enroll_templates_resp->templates[n].user_id_len = extract8(msg_resp->payload, &offset) - 2;
if(get_enroll_templates_resp->templates[n].user_id_len > BMKT_MAX_USER_ID_LEN)
{
return BMKT_UNRECOGNIZED_MESSAGE;
}
get_enroll_templates_resp->templates[n].template_status = extract8(msg_resp->payload, &offset);
get_enroll_templates_resp->templates[n].finger_id = extract8(msg_resp->payload, &offset);
for (i = 0; i < get_enroll_templates_resp->templates[n].user_id_len; i++)
{
get_enroll_templates_resp->templates[n].user_id[i] = extract8(msg_resp->payload, &offset);
}
get_enroll_templates_resp->templates[n].user_id[i] = '\0';
}
return BMKT_SUCCESS;
}
static int parse_get_version_report(bmkt_msg_resp_t *msg_resp, bmkt_response_t *resp)
{
bmkt_get_version_resp_t *get_version_resp = &resp->response.get_version_resp;
int offset = 0;
if (msg_resp->payload_len != 15)
{
return BMKT_UNRECOGNIZED_MESSAGE;
}
memcpy(get_version_resp->part, msg_resp->payload, BMKT_PART_NUM_LEN);
offset += BMKT_PART_NUM_LEN;
get_version_resp->year = extract8(msg_resp->payload, &offset);
get_version_resp->week = extract8(msg_resp->payload, &offset);
get_version_resp->patch = extract8(msg_resp->payload, &offset);
memcpy(get_version_resp->supplier_id, msg_resp->payload + offset, BMKT_SUPPLIER_ID_LEN);
return BMKT_SUCCESS;
}
int bmkt_compose_message(uint8_t *cmd, int *cmd_len, uint8_t msg_id, uint8_t seq_num,
uint8_t payload_size, uint8_t *payload)
{
int message_len = BMKT_MESSAGE_HEADER_LEN + payload_size;
if (*cmd_len < message_len)
{
return BMKT_OUT_OF_MEMORY;
}
cmd[BMKT_MESSAGE_HEADER_ID_FIELD] = BMKT_MESSAGE_HEADER_ID;
cmd[BMKT_MESSAGE_SEQ_NUM_FIELD] = seq_num;
cmd[BMKT_MESSAGE_ID_FIELD] = msg_id;
cmd[BMKT_MESSAGE_PAYLOAD_LEN_FIELD] = payload_size;
memcpy(&cmd[BMKT_MESSAGE_PAYLOAD_FIELD], payload, payload_size);
*cmd_len = message_len;
return BMKT_SUCCESS;
}
int bmkt_parse_message_header(uint8_t *resp_buf, int resp_len, bmkt_msg_resp_t *msg_resp)
{
if (resp_buf[BMKT_MESSAGE_HEADER_ID_FIELD] != BMKT_MESSAGE_HEADER_ID)
{
return BMKT_CORRUPT_MESSAGE;
}
msg_resp->seq_num = resp_buf[BMKT_MESSAGE_SEQ_NUM_FIELD];
msg_resp->msg_id = resp_buf[BMKT_MESSAGE_ID_FIELD];
msg_resp->payload_len = resp_buf[BMKT_MESSAGE_PAYLOAD_LEN_FIELD];
if (msg_resp->payload_len > 0)
{
msg_resp->payload = &resp_buf[BMKT_MESSAGE_PAYLOAD_FIELD];
}
else
{
msg_resp->payload = NULL;
}
return BMKT_SUCCESS;
}
int bmkt_parse_message_payload(bmkt_msg_resp_t *msg_resp, bmkt_response_t *resp)
{
int ret = BMKT_SUCCESS;
memset(resp, 0, sizeof(bmkt_response_t));
resp->response_id = msg_resp->msg_id;
switch(msg_resp->msg_id)
{
case BMKT_RSP_CONTINUOUS_IMAGE_CAPTURE_FAIL:
case BMKT_RSP_SENSOR_MODULE_TEST_FAIL:
case BMKT_RSP_FPS_INIT_FAIL:
case BMKT_RSP_FPS_MODE_FAIL:
case BMKT_RSP_SET_SECURITY_LEVEL_FAIL:
case BMKT_RSP_GET_SECURITY_LEVEL_FAIL:
case BMKT_RSP_CANCEL_OP_FAIL:
case BMKT_RSP_ENROLL_FAIL:
case BMKT_RSP_ID_FAIL:
case BMKT_RSP_VERIFY_FAIL:
case BMKT_RSP_QUERY_FAIL:
case BMKT_RSP_DEL_USER_FP_FAIL:
case BMKT_RSP_DEL_FULL_DB_FAIL:
case BMKT_RSP_REPEAT_LAST_BMKT_RSP_FAIL:
case BMKT_RSP_POWER_DOWN_FAIL:
case BMKT_RSP_GET_VERSION_FAIL:
case BMKT_RSP_DISABLE_PAIRING_FAIL:
case BMKT_RSP_QUERY_PAIRING_FAIL:
case BMKT_RSP_SENSOR_STATUS_FAIL:
case BMKT_RSP_RETRIEVE_FINAL_RESULT_FAIL:
ret = parse_error_response(msg_resp, resp);
resp->complete = 1;
break;
case BMKT_RSP_FPS_INIT_OK:
ret = parse_init_ok(msg_resp, resp);
resp->complete = 1;
break;
case BMKT_RSP_CANCEL_OP_OK:
case BMKT_RSP_DEL_FULL_DB_OK:
case BMKT_RSP_DEL_USER_FP_OK:
/* responses with a payload of 0
so the response indicates success */
resp->result = BMKT_SUCCESS;
resp->complete = 1;
break;
case BMKT_RSP_FPS_MODE_REPORT:
// parse_fps_mode
ret = parse_fps_mode_report(msg_resp, resp);
resp->complete = 1;
break;
case BMKT_RSP_GET_SECURITY_LEVEL_REPORT:
case BMKT_RSP_SET_SECURITY_LEVEL_REPORT:
/* parse security level result */
ret = parse_security_level_report(msg_resp, resp);
resp->complete = 1;
break;
case BMKT_RSP_DELETE_PROGRESS:
ret = parse_del_all_users_progress_report(msg_resp, resp);
break;
case BMKT_RSP_CAPTURE_COMPLETE:
resp->result = BMKT_SUCCESS;
break;
case BMKT_RSP_ENROLL_READY:
resp->result = BMKT_SUCCESS;
break;
case BMKT_RSP_ENROLL_REPORT:
ret = parse_enroll_report(msg_resp, resp);
break;
case BMKT_RSP_ENROLL_OK:
resp->complete = 1;
ret = parse_enroll_ok(msg_resp, resp);
break;
case BMKT_RSP_ID_OK:
case BMKT_RSP_VERIFY_OK:
ret = parse_auth_ok(msg_resp, resp);
resp->complete = 1;
break;
case BMKT_RSP_GET_ENROLLED_FINGERS_REPORT:
ret = parse_get_enrolled_fingers_report(msg_resp, resp);
resp->complete = 1;
break;
case BMKT_RSP_DATABASE_CAPACITY_REPORT:
resp->complete = 1;
ret = parse_db_cap_report(msg_resp, resp);
break;
case BMKT_RSP_TEMPLATE_RECORDS_REPORT:
ret = parse_get_enrolled_users_report(msg_resp, resp);
break;
case BMKT_RSP_QUERY_RESPONSE_COMPLETE:
resp->complete = 1;
break;
case BMKT_RSP_VERSION_INFO:
ret = parse_get_version_report(msg_resp, resp);
resp->complete = 1;
break;
}
return ret;
}

View File

@@ -0,0 +1,94 @@
/*
* Copyright (C) 2019 Synaptics Inc
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef BMKT_MESSAGE_H_
#define BMKT_MESSAGE_H_
#include "bmkt_internal.h"
#define BMKT_MESSAGE_HEADER_ID 0xFE
#define BMKT_MESSAGE_HEADER_LEN (4)
#define BMKT_MESSAGE_CRC32_LEN (4)
#define BMKT_MESSAGE_HEADER_ID_FIELD 0
#define BMKT_MESSAGE_SEQ_NUM_FIELD 1
#define BMKT_MESSAGE_ID_FIELD 2
#define BMKT_MESSAGE_PAYLOAD_LEN_FIELD 3
#define BMKT_MESSAGE_PAYLOAD_FIELD 4
// Command messages
#define BMKT_CMD_CONTINUOUS_IMAGE_CAPTURE 0x01
#define BMKT_CMD_CONTINUOUS_IMAGE_CAPTURE_STOP 0x04
#define BMKT_CMD_SENSOR_MODULE_TEST 0x06
#define BMKT_CMD_SENSOR_MODULE_TEST_START 0x08
#define BMKT_CMD_NEXT_TEST_REPORT_CHUNK 0x0B
#define BMKT_CMD_FPS_INIT 0x11
#define BMKT_CMD_GET_FPS_MODE 0x21
#define BMKT_CMD_SET_SECURITY_LEVEL 0x31
#define BMKT_CMD_GET_SECURITY_LEVEL 0x34
#define BMKT_CMD_CANCEL_OP 0x41
#define BMKT_CMD_ENROLL_USER 0x51
#define BMKT_CMD_ENROLL_PAUSE 0x52
#define BMKT_CMD_ENROLL_RESUME 0x53
#define BMKT_CMD_ID_USER 0x61
#define BMKT_CMD_VERIFY_USER 0x65
#define BMKT_CMD_GET_TEMPLATE_RECORDS 0x71
#define BMKT_CMD_GET_NEXT_QUERY_RESPONSE 0x72
#define BMKT_CMD_GET_ENROLLED_FINGERS 0x73
#define BMKT_CMD_GET_DATABASE_CAPACITY 0x74
#define BMKT_CMD_DEL_USER_FP 0x81
#define BMKT_CMD_DEL_FULL_DB 0x84
#define BMKT_CMD_REPEAT_LAST_RSP 0x92
#define BMKT_CMD_POWER_DOWN_NOTIFY 0xA1
#define BMKT_CMD_GET_VERSION 0xB1
#define BMKT_CMD_DISABLE_PAIRING 0xC2
#define BMKT_CMD_QUERY_PAIRING 0xC5
#define BMKT_CMD_SENSOR_STATUS 0xD1
#define BMKT_CMD_ID_USER_IN_ORDER 0xE1
#define BMKT_CMD_ID_NEXT_USER 0xE3
#define BMKT_CMD_VERIFY_USER_IN_ORDER 0xF1
#define BMKT_CMD_VERIFY_FINGERS_IN_ORDER 0xF2
#define BMKT_CMD_GET_FINAL_RESULT 0xE4
#define BMKT_EVT_FINGER_REPORT 0x91
#define BMKT_EVT_FINGER_STATE_NOT_ON_SENSOR 0x00
#define BMKT_EVT_FINGER_STATE_ON_SENSOR 0x01
typedef struct bmkt_msg_resp
{
uint8_t msg_id;
uint8_t seq_num;
uint8_t payload_len;
uint8_t *payload;
int result;
} bmkt_msg_resp_t;
typedef struct bmkt_session_ctx
{
uint8_t seq_num;
bmkt_resp_cb_t resp_cb;
void *cb_ctx;
} bmkt_session_ctx_t;
int bmkt_compose_message(uint8_t *cmd, int *cmd_len, uint8_t msg_id, uint8_t seq_num,
uint8_t payload_size, uint8_t *payload);
int bmkt_parse_message_header(uint8_t *resp_buf, int resp_len, bmkt_msg_resp_t *msg_resp);
int bmkt_parse_message_payload(bmkt_msg_resp_t *msg_resp, bmkt_response_t *resp);
#endif /* BMKT_MESSAGE_H_ */

View File

@@ -0,0 +1,487 @@
/*
* Synaptics MiS Fingerprint Sensor Response Data Interface
* Copyright (C) 2019 Synaptics Inc
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _BMKT_RESPONSE_H_
#define _BMKT_RESPONSE_H_
/** List of response message IDs */
#define BMKT_RSP_CONTINUOUS_IMAGE_CAPTURE_FAIL 0x02
#define BMKT_RSP_CONTINUOUS_IMAGE_CAPTURE_READY 0x03
#define BMKT_RSP_CONTINUOUS_IMAGE_CAPTURE_STOPPED 0x05
#define BMKT_RSP_SENSOR_MODULE_TEST_READY 0x07
#define BMKT_RSP_SENSOR_MODULE_TEST_FAIL 0x09
#define BMKT_RSP_SENSOR_MODULE_TEST_REPORT 0x0A
#define BMKT_RSP_NEXT_TEST_REPORT_CHUNK 0x0C
/*! \addtogroup init
* Response IDs returned by fingerprint initialization operation
* @{
*/
/** Failed to initialize fingerprint sensor module */
#define BMKT_RSP_FPS_INIT_FAIL 0x12
/** Successfully initialized fingerprint sensor module */
#define BMKT_RSP_FPS_INIT_OK 0x13
/*! @} */
/*! \addtogroup mode
* Response IDs returned by get fingerprint mode operation
* @{
*/
/** Failed to get fingerprint sensor modules current operational mode */
#define BMKT_RSP_FPS_MODE_FAIL 0x22
/**
* BMKT_RSP_FPS_MODE_REPORT:
* Response containing the current operational mode of the fingerprint sensor module
* <br>Payload data represented in \ref bmkt_fps_mode_resp_t struct
*/
#define BMKT_RSP_FPS_MODE_REPORT 0x23
/*! @} */
/*! \addtogroup setseclevel
* Response IDs returned by set security level operation
* @{
*/
/** Failed to set fingerprint sensor module security level */
#define BMKT_RSP_SET_SECURITY_LEVEL_FAIL 0x32
/**
* BMKT_RSP_SET_SECURITY_LEVEL_REPORT:
* Security level of the fingerprint sensor module was set successfully
* <br>Contains payload data represented in \ref bmkt_set_sec_level_resp_t struct
*/
#define BMKT_RSP_SET_SECURITY_LEVEL_REPORT 0x33
/*! @} */
/*! \addtogroup getseclevel
* Response IDs returned by get security level operation
* @{
*/
/** Failed to get fingerprint sensor module security level */
#define BMKT_RSP_GET_SECURITY_LEVEL_FAIL 0x35
/**
* BMKT_RSP_GET_SECURITY_LEVEL_REPORT:
* Returns the current security level of the fingerprint sensor module
* <br>Contains payload data represented in \ref bmkt_set_sec_level_resp_t struct
*/
#define BMKT_RSP_GET_SECURITY_LEVEL_REPORT 0x36
/*! @} */
/*! \addtogroup cancelop
* Response IDs returned by cancel_operation operation
* @{
*/
/**
* BMKT_RSP_CANCEL_OP_OK:
* Successfully canceled the current operation and returned
* fingerprint sensor module to idle mode
*/
#define BMKT_RSP_CANCEL_OP_OK 0x42
/** Failed to cancel the current operation */
#define BMKT_RSP_CANCEL_OP_FAIL 0x43
/*! @} */
/*! \addtogroup enrollment
* Response IDs returned by enrollment operation
* @{
*/
/**
* BMKT_RSP_ENROLL_READY:
* Fingerprint enrollment session has begun and the user can place
* their finger on the sensor
*/
#define BMKT_RSP_ENROLL_READY 0x54
/** Progress of the currently on-going fingerprint enrollment session */
#define BMKT_RSP_ENROLL_REPORT 0x55
/** Enrollment has been paused */
#define BMKT_RSP_ENROLL_PAUSED 0x56
/** Enrollment has been resume */
#define BMKT_RSP_ENROLL_RESUMED 0x57
/** The current enrollment session has encountered an error */
#define BMKT_RSP_ENROLL_FAIL 0x58
/**
* BMKT_RSP_ENROLL_OK:
* User has been successfully enrolled into the fingerprint sensor module
* <br>Contains payload data represented in \ref bmkt_enroll_resp_t struct
*/
#define BMKT_RSP_ENROLL_OK 0x59
/**
* BMKT_RSP_CAPTURE_COMPLETE:
* Fingerprint image capture is complete and it is safe for the user
* to lift their finger off the sensor
*/
#define BMKT_RSP_CAPTURE_COMPLETE 0x60
/*! @} */
/*! \addtogroup identify
* Response IDs returned by identify operation.
* @{
*/
/* Fingerprint identification session has begun */
#define BMKT_RSP_ID_READY 0x62
/* Identification has failed */
#define BMKT_RSP_ID_FAIL 0x63
/**
* BMKT_RSP_ID_OK:
* User has been successfully identified
* <br>Contains payload data represented in \ref bmkt_auth_resp struct
*/
#define BMKT_RSP_ID_OK 0x64
/*! @} */
/*! \addtogroup verify
* Response IDs returned by identify operation.
* @{
*/
/** Fingerprint verification session has begun */
#define BMKT_RSP_VERIFY_READY 0x66
/** Verification has failed */
#define BMKT_RSP_VERIFY_FAIL 0x67
/**
* BMKT_RSP_VERIFY_OK:
* Users identity has been successfully verified
* <br>Contains payload data represented in \ref bmkt_auth_resp struct
*/
#define BMKT_RSP_VERIFY_OK 0x68
/*! @} */
/**
* BMKT_RSP_TEMPLATE_RECORDS_REPORT:
* Response ID returned by get enrolled users templates record operation
* <br>Returns list of template records containing user IDs and corresponding finger IDs
* <br>Payload data represented in \ref bmkt_enroll_templates_resp_t struct
*/
#define BMKT_RSP_TEMPLATE_RECORDS_REPORT 0x75
/**
* BMKT_RSP_QUERY_RESPONSE_COMPLETE:
* Response ID returned by get next query response operation
* <br>Complete sequence of messages containing the template records query response has been sent
*/
#define BMKT_RSP_QUERY_RESPONSE_COMPLETE 0x76
/**
* BMKT_RSP_GET_ENROLLED_FINGERS_REPORT:
* Response ID returned by get enrolled fingers operation
* <br> Returns list of IDs of enrolled fingers for a specific user,
* along with template record status corresponding to each enrolled finger
* <br>Contains payload data represented in \ref bmkt_enrolled_fingers_resp_t struct
*/
#define BMKT_RSP_GET_ENROLLED_FINGERS_REPORT 0x77
/*! \addtogroup dbcapacity
* Response IDs returned by get database capacity operation
* @{
*/
/**
* BMKT_RSP_DATABASE_CAPACITY_REPORT:
* Response specifying total capacity of fingerprint template database and
* how much free capacity is remaining along with how many templates are corrupted and
* how many bad (permanently unusable) storage slots are there.
* <br>Payload data represented in \ref bmkt_get_db_capacity_resp_t struct
*/
#define BMKT_RSP_DATABASE_CAPACITY_REPORT 0x78
/** Failed to execute database query */
#define BMKT_RSP_QUERY_FAIL 0x79
/*! @} */
/*! \addtogroup deluser
* Response IDs returned by delete fingerprint of specific user operation
* @{
*/
/** Failed to delete a users fingerprint template from the database */
#define BMKT_RSP_DEL_USER_FP_FAIL 0x82
/**
* BMKT_RSP_DEL_USER_FP_OK:
* Fingerprint template successfully deleted from the database.
* Returns the user ID and finger ID deleted. If value of finger ID is set equal to 0,
* then all fingerprint templates for that user have been deleted from the database
* <br>Payload data represented in \ref bmkt_del_user_resp_t struct
*/
#define BMKT_RSP_DEL_USER_FP_OK 0x83
/*! @} */
/*! \addtogroup delfulldb
* Response IDs returned by delete entire fingerprint template DB operation
* @{
*/
/** Failed to erase entire fingerprint template database */
#define BMKT_RSP_DEL_FULL_DB_FAIL 0x85
/** Successfully erased entire fingerprint template database */
#define BMKT_RSP_DEL_FULL_DB_OK 0x86
/**
* BMKT_RSP_DELETE_PROGRESS:
* Notify progress made during the on-going deletion of the full template database
* <br>Payload data represented in \ref bmkt_del_all_users_resp_t struct
*/
#define BMKT_RSP_DELETE_PROGRESS 0x87
/*! @} */
/**
* BMKT_RSP_REPEAT_LAST_BMKT_RSP_FAIL:
* Response ID returned by repeate last response operation
* <br>Failed to retrieve and re-send last response
*/
#define BMKT_RSP_REPEAT_LAST_BMKT_RSP_FAIL 0x93
/*! \addtogroup pwrdwn
* Response IDs returned by power down notify operation
* @{
*/
/** Fingerprint sensor module is ready to be powered down */
#define BMKT_RSP_POWER_DOWN_READY 0xA2
/** Failed to go into power down mode */
#define BMKT_RSP_POWER_DOWN_FAIL 0xA3
/*! @} */
/*! \addtogroup versioninfo
* Response IDs returned by get version operation
* @{
*/
/**
* BMKT_RSP_VERSION_INFO:
* System version information of the fingerprint sensor module
* <br>Payload data represented in \ref bmkt_get_version_resp_t struct
*/
#define BMKT_RSP_VERSION_INFO 0xB2
/* Failed to retrieve and send last response */
#define BMKT_RSP_GET_VERSION_FAIL 0xB3
/*! @} */
/**
* BMKT_RSP_GENERAL_ERROR:
* Not tied to a specific command-response session.
* <br>Could be caused by corrupt or truncated command message
*/
#define BMKT_RSP_GENERAL_ERROR 0xC1
#define BMKT_RSP_DISABLE_PAIRING_FAIL 0xC3
#define BMKT_RSP_DISABLE_PAIRING_OK 0xC4
#define BMKT_RSP_QUERY_PAIRING_FAIL 0xC6
#define BMKT_RSP_SENSOR_PAIRING_REPORT 0xC7
/*! \addtogroup versioninfo
* Response IDs returned by get sensor module status operation
* @{
*/
/**
* BMKT_RSP_SENSOR_STATUS_REPORT:
* Response returning the current status of the sensor module
* <br>Payload data represented in bmkt_XXX struct
*/
#define BMKT_RSP_SENSOR_STATUS_REPORT 0xD2
/** Failed to retrieve sensor status */
#define BMKT_RSP_SENSOR_STATUS_FAIL 0xD3
/*! @} */
/**
* BMKT_RSP_SEND_NEXT_USER_ID:
* Response ID returned by identify user in order operation
* <br>Notify to send the next batch of user IDs in the priority list
*/
#define BMKT_RSP_SEND_NEXT_USER_ID 0xE2
/**
* BMKT_RSP_RETRIEVE_FINAL_RESULT_FAIL:
* Response IDs returned by retrieve final result operation
* <br>Failed to retrieve and re-send cached final result
*/
#define BMKT_RSP_RETRIEVE_FINAL_RESULT_FAIL 0xE5
/**
* Response payload data structure returned by sensor initialization operation.
*/
typedef struct bmkt_init_resp
{
uint8_t finger_presence; /**< Indicates finger existence on the sensor during startup */
} bmkt_init_resp_t;
/**
* bmkt_enroll_resp:
* Response payload data structure returned by enrollment operation.
*/
typedef struct bmkt_enroll_resp
{
int progress; /**< Shows current progress stutus [0-100] */
uint8_t finger_id; /**< User's finger id [1-10] */
uint8_t user_id[BMKT_MAX_USER_ID_LEN]; /**< User name to be enrolled */
} bmkt_enroll_resp_t;
/**
* bmkt_auth_resp:
* Response payload data structure returned by identify and verify operations.
*/
struct bmkt_auth_resp
{
double match_result; /**< match result returned by matcher */
uint8_t finger_id; /**< Matched templates's finger id */
uint8_t user_id[BMKT_MAX_USER_ID_LEN]; /**< Matched template's user id */
};
typedef struct bmkt_auth_resp bmkt_verify_resp_t; /**< Returned by verify */
typedef struct bmkt_auth_resp bmkt_identify_resp_t; /**< Returned by identify */
/**
* bmkt_fps_mode_resp:
* Response payload data structure returned by get fingerprint mode operation.
*/
typedef struct bmkt_fps_mode_resp
{
uint8_t mode; /**< One of the Level I bmkt_mode_t values */
uint8_t level2_mode; /**< One of the Level II bmkt_mode_level2_t values */
uint8_t cmd_id; /**< Message ID of command being executed when bmkt_get_fps_mode was called */
uint8_t finger_presence; /**< Finger presence status value finger on sensor 1 / finger not on sensor 0 */
} bmkt_fps_mode_resp_t;
/**
* bmkt_get_version_resp:
* Response payload data structure returned by get version operation.
*/
typedef struct bmkt_get_version_resp
{
uint8_t part[BMKT_PART_NUM_LEN]; /**< Software Part Number */
uint8_t year; /**< Software Version Year */
uint8_t week; /**< Software Version Week */
uint8_t patch; /**< Software Version Patch Level */
uint8_t supplier_id[BMKT_SUPPLIER_ID_LEN]; /**< Software Supplier Identification */
} bmkt_get_version_resp_t;
/**
* bmkt_get_db_capacity_resp:
* Response payload data structure returned by get DB capacity operation.
*/
typedef struct bmkt_get_db_capacity_resp
{
uint8_t total; /**< Total Available Capacity: Total number of template records that can be stored */
uint8_t empty; /**< Free Capacity: Number of template records that can still be stored */
uint8_t bad_slots; /**< Number of bad template storage slots */
uint8_t corrupt_templates; /**< Number of corrupt templates */
} bmkt_get_db_capacity_resp_t;
/**
* bmkt_sec_level:
* Security level values.
*/
typedef enum bmkt_sec_level
{
BMKT_SECURITY_LEVEL_LOW = 0x10,
BMKT_SECURITY_LEVEL_MEDIUM = 0x40,
BMKT_SECURITY_LEVEL_HIGH = 0x60,
} bmkt_sec_level_t;
/**
* bmkt_set_sec_level_resp:
* Response payload data structure returned by get/set security level operations.
*/
typedef struct bmkt_set_sec_level_resp
{
bmkt_sec_level_t sec_level; /**< One of the bmkt_sec_level_t values */
} bmkt_set_sec_level_resp_t;
/**
* bmkt_del_all_users_resp:
* Response payload data structure returned by delete all enrolled users operation.
*/
typedef struct bmkt_del_all_users_resp
{
int progress; /**< Progress indicator as a percentage */
} bmkt_del_all_users_resp_t;
/**
* bmkt_del_user_resp:
* Response payload data structure returned by delete enrolled user operation.
*/
typedef struct bmkt_del_user_resp
{
int progress; /**< Progress indicator as a percentage */
} bmkt_del_user_resp_t;
/**
* bmkt_enroll_template:
* Structure of enrolled users template record data.
*/
typedef struct bmkt_enroll_template
{
uint8_t user_id_len; /**< Length of user_id string */
uint8_t template_status; /**< Template record status */
uint8_t finger_id; /**< ID of enrolled finger */
uint8_t user_id[BMKT_MAX_USER_ID_LEN + 1]; /**< Name of the enrolled user */
} bmkt_enroll_template_t;
/**
* bmkt_enroll_templates_resp:
* Response payload data structure returned by get enrolled user list operation.
*/
typedef struct bmkt_enroll_templates_resp
{
uint8_t total_query_messages; /**< Total query response messages */
uint8_t query_sequence; /**< Query response sequence number */
bmkt_enroll_template_t templates[BMKT_MAX_NUM_TEMPLATES_INTERNAL_FLASH]; /**< Enrolled user template records list */
} bmkt_enroll_templates_resp_t;
/**
* bmkt_enrolled_fingers:
* Structure of template record status corresponding to each enrolled finger.
*/
typedef struct bmkt_enrolled_fingers
{
uint8_t finger_id; /**< ID of enrolled finger */
uint8_t template_status; /**< Template record status of finger_id */
} bmkt_enrolled_fingers_t;
/**
* bmkt_enrolled_fingers_resp:
* Response payload data structure returned by get enrolled fingers operation.
*/
typedef struct bmkt_enrolled_fingers_resp
{
bmkt_enrolled_fingers_t fingers[10]; /**< List of enroled fingers, max number of supported fingers per user is 10 */
} bmkt_enrolled_fingers_resp_t;
/**
* bmkt_response_data_t:
* Union combining all response payload data types.
*/
typedef union {
bmkt_init_resp_t init_resp;
bmkt_enroll_resp_t enroll_resp;
bmkt_verify_resp_t verify_resp;
bmkt_identify_resp_t id_resp;
bmkt_fps_mode_resp_t fps_mode_resp;
bmkt_get_version_resp_t get_version_resp;
bmkt_get_db_capacity_resp_t db_cap_resp;
bmkt_set_sec_level_resp_t sec_level_resp;
bmkt_del_all_users_resp_t del_all_users_resp;
bmkt_enroll_templates_resp_t enroll_templates_resp;
bmkt_del_user_resp_t del_user_resp;
bmkt_enrolled_fingers_resp_t enrolled_fingers_resp;
} bmkt_response_data_t;
/**
* bmkt_response:
* Structure to abstract different response structure types in one API
* to be used in bmkt_resp_cb_t callback function.
*/
typedef struct bmkt_response
{
int response_id; /**< Response message ID, one of th BMKT_RSP_XXX */
int result; /**< Operation execution result code */
int complete; /**< Operation completion status 1: complete / 0: not completed */
bmkt_response_data_t response; /**< Operation specific response union */
} bmkt_response_t;
#endif /* _BMKT_RESPONSE_H_ */

View File

@@ -0,0 +1,481 @@
/*
* Copyright (C) 2019 Synaptics Inc
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "bmkt_internal.h"
#include "bmkt_message.h"
#include "sensor.h"
#define SENSOR_CMD_GET_VERSION 1
#define SENSOR_CMD_ACE_COMMAND 167
#define SENSOR_CMD_ASYNCMSG_READ 168
#define SENSOR_FW_CMD_HEADER_LEN 1
#define SENSOR_FW_REPLY_HEADER_LEN 2
static int get_version(bmkt_sensor_t *sensor, bmkt_sensor_version_t *mis_version)
{
int ret;
uint8_t *resp = NULL;
int resp_len = 40;
uint16_t status = 0;
uint8_t *cmd;
int cmd_len = 0;
int cmd_buf_len;
int offset = 0;
ret = usb_get_command_buffer(&sensor->usb_xport, &cmd, &cmd_buf_len);
if (ret != BMKT_SUCCESS)
{
return BMKT_OUT_OF_MEMORY;
}
if (cmd_buf_len < SENSOR_FW_CMD_HEADER_LEN)
{
return BMKT_OUT_OF_MEMORY;
}
cmd[0] = SENSOR_CMD_GET_VERSION;
cmd_len = 1;
ret = usb_send_command_sync(&sensor->usb_xport, cmd_len, &resp, &resp_len);
if (ret != BMKT_SUCCESS)
{
return ret;
}
status = extract16(resp, &offset);
if (status)
{
bmkt_err_log("The sensor reported an error when sending get version command: 0x%x",
status);
return BMKT_SENSOR_MALFUNCTION;
}
if (resp_len < 38)
{
return BMKT_SENSOR_MALFUNCTION;
}
mis_version->build_time = extract32(resp, &offset);
mis_version->build_num = extract32(resp, &offset);
mis_version->version_major = extract8(resp, &offset);
mis_version->version_minor = extract8(resp, &offset);
mis_version->target = extract8(resp, &offset);
mis_version->product = extract8(resp, &offset);
ret = usb_release_command_buffer(&sensor->usb_xport);
if (ret != BMKT_SUCCESS)
{
bmkt_dbg_log("%s: failed to release command buffer: %d", __func__, ret);
return ret;
}
return BMKT_SUCCESS;
}
static bmkt_session_ctx_t *get_empty_session_ctx(bmkt_sensor_t *sensor)
{
bmkt_session_ctx_t *ctx;
int i;
int idx;
for (i = 0; i < BMKT_MAX_PENDING_SESSIONS; i++)
{
idx = (sensor->empty_session_idx + i) % BMKT_MAX_PENDING_SESSIONS;
ctx = &sensor->pending_sessions[idx];
if (ctx->seq_num == 0)
{
sensor->empty_session_idx = (idx + 1) % BMKT_MAX_PENDING_SESSIONS;
return ctx;
}
}
return NULL;
}
static bmkt_session_ctx_t *get_session_ctx(bmkt_sensor_t *sensor, int seq_num)
{
int i;
bmkt_session_ctx_t *ctx;
/* Sequence number of 0 is not valid for a response to
a command.*/
if (seq_num == 0)
{
return NULL;
}
for (i = 0; i < BMKT_MAX_PENDING_SESSIONS; i++)
{
ctx = &sensor->pending_sessions[i];
if (ctx->seq_num == seq_num)
{
return ctx;
}
}
return NULL;
}
static int release_session_ctx(bmkt_sensor_t *sensor, bmkt_session_ctx_t *ctx)
{
memset(ctx, 0, sizeof(bmkt_session_ctx_t));
return BMKT_SUCCESS;
}
int bmkt_sensor_open(bmkt_sensor_t *sensor, bmkt_general_error_cb_t err_cb, void *err_cb_ctx)
{
int ret;
sensor->seq_num = 1;
sensor->sensor_state = BMKT_SENSOR_STATE_UNINIT;
sensor->usb_xport.sensor = sensor;
ret = usb_open(&sensor->usb_xport);
if (ret != BMKT_SUCCESS)
{
bmkt_err_log("Failed to open transport: %d", ret);
return ret;
}
sensor->gen_err_cb = err_cb;
sensor->gen_err_cb_ctx = err_cb_ctx;
ret = get_version(sensor, &sensor->version);
if (ret != BMKT_SUCCESS)
{
bmkt_err_log("Failed to get version info: %d", ret);
return ret;
}
bmkt_dbg_log("Build Time: %d", sensor->version.build_time);
bmkt_dbg_log("Build Num: %d", sensor->version.build_num);
bmkt_dbg_log("Version: %d.%d", sensor->version.version_major, sensor->version.version_minor);
bmkt_dbg_log("Target: %d", sensor->version.target);
bmkt_dbg_log("Product: %d", sensor->version.product);
return BMKT_SUCCESS;
}
int bmkt_sensor_close(bmkt_sensor_t *sensor)
{
int ret;
sensor->sensor_state = BMKT_SENSOR_STATE_EXIT;
ret = usb_close(&sensor->usb_xport);
if (ret != BMKT_SUCCESS)
{
return ret;
}
sensor->sensor_state = BMKT_SENSOR_STATE_EXIT;
return BMKT_SUCCESS;
}
int bmkt_sensor_init_fps(bmkt_sensor_t *sensor)
{
sensor->sensor_state = BMKT_SENSOR_STATE_INIT;
return BMKT_SUCCESS;
}
int bmkt_sensor_send_message(bmkt_sensor_t *sensor, uint8_t msg_id, uint8_t payload_size,
uint8_t *payload, bmkt_resp_cb_t resp_cb, void *cb_ctx)
{
int ret;
uint8_t *cmd;
int cmd_buf_len = 0;
int msg_len;
int seq_num = 0;
bmkt_session_ctx_t *session_ctx = get_empty_session_ctx(sensor);
if (session_ctx == NULL)
{
return BMKT_OPERATION_DENIED;
}
if (sensor->seq_num > 255) {
/* seq. number is in range [1 255]. After it reaches 255, it rolls over to 1 and starts over again.
(0 is reserved for special purposes) */
sensor->seq_num = 1;
}
session_ctx->seq_num = sensor->seq_num++;
session_ctx->resp_cb = resp_cb;
session_ctx->cb_ctx = cb_ctx;
bmkt_dbg_log("session_ctx->seq_num=%d, sensor->seq_num=%d", session_ctx->seq_num, sensor->seq_num);
bmkt_op_set_state(sensor, BMKT_OP_STATE_START);
ret = usb_get_command_buffer(&sensor->usb_xport, &cmd, &cmd_buf_len);
if (ret != BMKT_SUCCESS)
{
return BMKT_OUT_OF_MEMORY;
}
/* MIS sensors send ACE commands encapsulated in FW commands*/
cmd[0] = SENSOR_CMD_ACE_COMMAND;
msg_len = cmd_buf_len - SENSOR_FW_CMD_HEADER_LEN;
if (session_ctx != NULL)
{
seq_num = session_ctx->seq_num;
}
ret = bmkt_compose_message(&cmd[1], &msg_len, msg_id, seq_num, payload_size, payload);
if (ret != BMKT_SUCCESS)
{
bmkt_dbg_log("Failed to compose ace message: %d", ret);
goto cleanup;
}
ret = usb_send_command(&sensor->usb_xport, msg_len + SENSOR_FW_CMD_HEADER_LEN);
if (ret != BMKT_SUCCESS)
{
bmkt_dbg_log("%s: failed to send ACE command: %d", __func__, ret);
goto cleanup;
}
cleanup:
usb_release_command_buffer(&sensor->usb_xport);
if (ret != BMKT_SUCCESS)
{
release_session_ctx(sensor, session_ctx);
}
return ret;
}
int bmkt_sensor_send_async_read_command(bmkt_sensor_t *sensor)
{
int ret;
uint8_t *cmd;
int cmd_buf_len = 0;
ret = usb_get_command_buffer(&sensor->usb_xport, &cmd, &cmd_buf_len);
if (ret != BMKT_SUCCESS)
{
return BMKT_OUT_OF_MEMORY;
}
/* MIS sensors send ACE commands encapsulated in FW commands */
cmd[0] = SENSOR_CMD_ASYNCMSG_READ;
ret = usb_send_command(&sensor->usb_xport, SENSOR_FW_CMD_HEADER_LEN);
if (ret == BMKT_SENSOR_RESPONSE_PENDING)
{
/* The caller needs to handle the response before we can send this command */
goto cleanup;
}
else if (ret != BMKT_SUCCESS)
{
if (ret != BMKT_SENSOR_NOT_READY)
{
bmkt_dbg_log("%s: failed to send ACE ASYNC READ command: %d", __func__, ret);
}
goto cleanup;
}
cleanup:
usb_release_command_buffer(&sensor->usb_xport);
return ret;
}
int bmkt_sensor_send_message_sync(bmkt_sensor_t *sensor, uint8_t msg_id, uint8_t payload_size,
uint8_t *payload, uint8_t **resp_buf, int *resp_len, bmkt_response_t *resp)
{
int ret;
uint8_t *cmd;
int cmd_buf_len = 0;
int msg_len;
bmkt_msg_resp_t msg_resp;
*resp_len = BMKT_MAX_TRANSFER_LEN;
ret = usb_get_command_buffer(&sensor->usb_xport, &cmd, &cmd_buf_len);
if (ret != BMKT_SUCCESS)
{
return BMKT_OUT_OF_MEMORY;
}
cmd[0] = SENSOR_CMD_ACE_COMMAND;
msg_len = cmd_buf_len - SENSOR_FW_CMD_HEADER_LEN;
ret = bmkt_compose_message(&cmd[1], &msg_len, msg_id, sensor->seq_num++, payload_size,
payload);
if (ret != BMKT_SUCCESS)
{
bmkt_dbg_log("Failed to compose ace message: %d", ret);
goto cleanup;
}
ret = usb_send_command_sync(&sensor->usb_xport, msg_len + SENSOR_FW_CMD_HEADER_LEN,
resp_buf, resp_len);
if (ret != BMKT_SUCCESS)
{
bmkt_dbg_log("%s: failed to send ACE command: %d", __func__, ret);
goto cleanup;
}
ret = bmkt_parse_message_header(&(*resp_buf)[2], *resp_len - 2, &msg_resp);
if (ret != BMKT_SUCCESS)
{
goto cleanup;
}
ret = bmkt_parse_message_payload(&msg_resp, resp);
if (ret != BMKT_SUCCESS)
{
goto cleanup;
}
cleanup:
ret = usb_release_command_buffer(&sensor->usb_xport);
if (ret != BMKT_SUCCESS)
{
bmkt_dbg_log("%s: failed to release command buffer: %d", __func__, ret);
return ret;
}
return ret;
}
int bmkt_sensor_handle_response(bmkt_sensor_t *sensor, uint8_t *resp_buf, int resp_len, bmkt_msg_resp_t *msg_resp)
{
int ret;
bmkt_session_ctx_t *session_ctx;
bmkt_response_t resp;
int i;
ret = bmkt_parse_message_header(&resp_buf[2], resp_len - 2, msg_resp);
if (ret == BMKT_CORRUPT_MESSAGE)
{
bmkt_warn_log("Corrupt Message Received");
return ret;
}
else if (ret != BMKT_SUCCESS)
{
return ret;
}
if (msg_resp->msg_id == BMKT_EVT_FINGER_REPORT)
{
/* finger event message */
bmkt_info_log("Finger event!");
bmkt_finger_event_t finger_event;
if (msg_resp->payload_len != 1)
{
return BMKT_UNRECOGNIZED_MESSAGE;
}
if (msg_resp->payload[0] == 0x01)
{
finger_event.finger_state = BMKT_FINGER_STATE_ON_SENSOR;
}
else
{
finger_event.finger_state = BMKT_FINGER_STATE_NOT_ON_SENSOR;
}
if (sensor->finger_event_cb != NULL)
{
sensor->finger_event_cb(&finger_event, sensor->finger_cb_ctx);
}
return BMKT_SUCCESS;
}
if (msg_resp->seq_num == 0)
{
if (msg_resp->msg_id == BMKT_RSP_GENERAL_ERROR)
{
/* report general error */
bmkt_info_log("General Error!");
uint16_t err;
if (sensor->gen_err_cb != NULL)
{
err = (msg_resp->payload[0] << 8) | msg_resp->payload[1];
sensor->gen_err_cb(err, sensor->gen_err_cb_ctx);
}
return BMKT_SUCCESS;
}
}
ret = bmkt_parse_message_payload(msg_resp, &resp);
if (ret != BMKT_SUCCESS)
{
bmkt_warn_log("Failed to process response: %d", ret);
return ret;
}
session_ctx = get_session_ctx(sensor, msg_resp->seq_num);
if (session_ctx == NULL)
{
bmkt_warn_log("Response received with invalid sequence number: %d, return BMKT_UNRECOGNIZED_MESSAGE(112)", msg_resp->seq_num);
return BMKT_UNRECOGNIZED_MESSAGE;
}
if (session_ctx->resp_cb != NULL)
{
ret = session_ctx->resp_cb(&resp, session_ctx->cb_ctx);
if (ret != BMKT_SUCCESS)
{
bmkt_warn_log("response callback failed: %d", ret);
}
}
if (resp.complete == 1)
{
ret = release_session_ctx(sensor, session_ctx);
if (ret != BMKT_SUCCESS)
{
return ret;
}
}
if (resp.response_id == BMKT_RSP_CANCEL_OP_OK && resp.result == BMKT_SUCCESS)
{
/* The previous commands have been canceled. Release all session ctx */
for (i = 0; i < BMKT_MAX_PENDING_SESSIONS; i++)
{
release_session_ctx(sensor, &sensor->pending_sessions[i]);
}
}
return BMKT_SUCCESS;
}
int bmkt_register_finger_event_notification(bmkt_sensor_t *sensor, bmkt_event_cb_t cb, void *cb_ctx)
{
if (sensor == NULL || cb == NULL)
{
return BMKT_INVALID_PARAM;
}
sensor->finger_event_cb = cb;
sensor->finger_cb_ctx = cb_ctx;
return BMKT_SUCCESS;
}

View File

@@ -0,0 +1,82 @@
/*
* Copyright (C) 2019 Synaptics Inc
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _SENSOR_H_
#define _SENSOR_H_
#include "usb_transport.h"
#define BMKT_MAX_PENDING_SESSIONS 2
typedef enum bmkt_sensor_state
{
BMKT_SENSOR_STATE_UNINIT = 0,
BMKT_SENSOR_STATE_IDLE,
BMKT_SENSOR_STATE_INIT,
BMKT_SENSOR_STATE_EXIT,
} bmkt_sensor_state_t;
typedef struct bmkt_sensor_drv bmkt_sensor_drv_t;
typedef struct bmkt_sensor_version
{
uint32_t build_time;
uint32_t build_num;
uint8_t version_major;
uint8_t version_minor;
uint8_t target;
uint8_t product;
uint8_t silicon_rev;
uint8_t formal_release;
uint8_t platform;
uint8_t patch;
uint8_t serial_number[6];
uint16_t security;
uint8_t iface;
uint8_t device_type;
} bmkt_sensor_version_t;
typedef struct bmkt_sensor
{
bmkt_usb_transport_t usb_xport;
bmkt_sensor_version_t version;
bmkt_session_ctx_t pending_sessions[BMKT_MAX_PENDING_SESSIONS];
int empty_session_idx;
int flags;
int seq_num;
bmkt_sensor_state_t sensor_state;
bmkt_event_cb_t finger_event_cb;
void *finger_cb_ctx;
bmkt_general_error_cb_t gen_err_cb;
void *gen_err_cb_ctx;
bmkt_op_state_t op_state;
} bmkt_sensor_t;
int bmkt_sensor_open(bmkt_sensor_t *sensor,
bmkt_general_error_cb_t err_cb, void *err_cb_ctx);
int bmkt_sensor_close(bmkt_sensor_t *sensor);
int bmkt_sensor_init_fps(bmkt_sensor_t *sensor);
int bmkt_sensor_send_message(bmkt_sensor_t *sensor, uint8_t msg_id, uint8_t payload_size,
uint8_t *payload, bmkt_resp_cb_t resp_cb, void *resp_data);
int bmkt_sensor_send_message_sync(bmkt_sensor_t *sensor, uint8_t msg_id, uint8_t payload_size,
uint8_t *payload, uint8_t **resp_buf, int *resp_len, bmkt_response_t *resp);
int bmkt_sensor_handle_response(bmkt_sensor_t *sensor, uint8_t *resp_buf, int resp_len, bmkt_msg_resp_t *msg_resp);
int bmkt_sensor_send_async_read_command(bmkt_sensor_t *sensor);
#endif /* _SENSOR_H_ */

View File

@@ -0,0 +1,488 @@
/*
* Copyright (C) 2019 Synaptics Inc
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#define FP_COMPONENT "synaptics"
#include "drivers_api.h"
#include "fpi-async.h"
#include "fp_internal.h"
#include "synaptics.h"
static const struct usb_id id_table[] = {
{ .vendor = SYNAPTICS_VENDOR_ID, .product = SYNAPTICS_PRODUCT_ID_A9, },
{ 0, 0, 0, }, /* terminating entry */
};
static int general_error_callback(uint16_t error, void *ctx)
{
fp_err("Received General Error %d from the sensor", error);
return 0;
}
static int finger_event_callback(bmkt_finger_event_t *event, void *ctx)
{
struct fp_dev *dev=(struct fp_dev *)ctx;
synaptics_dev *sdev = FP_INSTANCE_DATA(dev);
switch (event->finger_state)
{
case BMKT_FINGER_STATE_UNKNOWN:
fp_info("Finger state is not known");
break;
case BMKT_FINGER_STATE_ON_SENSOR:
sdev->isFingerOnSensor = TRUE;
fp_info("Finger in on the sensor");
break;
case BMKT_FINGER_STATE_NOT_ON_SENSOR:
sdev->isFingerOnSensor = FALSE;
fp_info("Finger is not on the sensor");
if(sdev->state == SYNA_STATE_VERIFY_DELAY_RESULT)
{
fp_info("verify no match");
bmkt_op_set_state(sdev->sensor, BMKT_OP_STATE_COMPLETE);
fpi_drvcb_report_verify_result(dev, FP_VERIFY_NO_MATCH, NULL);
}
break;
}
return BMKT_SUCCESS;
}
struct syna_mis_print_data
{
uint8_t finger_id;
uint8_t user_id[BMKT_MAX_USER_ID_LEN];
};
static int enroll_response(bmkt_response_t *resp, void *ctx)
{
bmkt_enroll_resp_t *enroll_resp = &resp->response.enroll_resp;
struct fp_dev *dev=(struct fp_dev *)ctx;
synaptics_dev *sdev = FP_INSTANCE_DATA(dev);
switch (resp->response_id)
{
case BMKT_RSP_ENROLL_READY:
{
fpi_drvcb_enroll_started(dev, 0);
sdev->enroll_resp_data.progress = 0;
fp_info("Place Finger on the Sensor!");
break;
}
case BMKT_RSP_CAPTURE_COMPLETE:
{
fp_info("Fingerprint image capture complete!");
break;
}
case BMKT_RSP_ENROLL_REPORT:
{
fp_info("Enrollment is %d %% ", enroll_resp->progress);
if(enroll_resp->progress < 100)
{
if(sdev->enroll_resp_data.progress == enroll_resp->progress)
fpi_drvcb_enroll_stage_completed(dev, FP_ENROLL_RETRY, NULL, NULL);
else
fpi_drvcb_enroll_stage_completed(dev, FP_ENROLL_PASS, NULL, NULL);
}
sdev->enroll_resp_data.progress = enroll_resp->progress;
break;
}
case BMKT_RSP_ENROLL_PAUSED:
{
fp_info("Enrollment has been paused!");
break;
}
case BMKT_RSP_ENROLL_RESUMED:
{
fp_info("Enrollment has been resumed!");
break;
}
case BMKT_RSP_ENROLL_FAIL:
{
fp_info("Enrollment has failed!: %d", resp->result);
break;
}
case BMKT_RSP_ENROLL_OK:
{
struct syna_mis_print_data mis_data;
struct fp_print_data *fdata = NULL;
struct fp_print_data_item *item = NULL;
fdata = fpi_print_data_new(dev);
item = fpi_print_data_item_new(sizeof(mis_data));
fp_info("Enrollment was successful!");
mis_data.finger_id = enroll_resp->finger_id;
memcpy(mis_data.user_id, enroll_resp->user_id,
BMKT_MAX_USER_ID_LEN);
memcpy(item->data, &mis_data,
sizeof(struct syna_mis_print_data));
fdata->prints = g_slist_prepend(fdata->prints, item);
bmkt_op_set_state(sdev->sensor, BMKT_OP_STATE_COMPLETE);
fpi_drvcb_enroll_stage_completed(dev, 1, fdata, NULL);
break;
}
}
return 0;
}
static int dev_init(struct fp_dev *dev, unsigned long driver_data)
{
synaptics_dev *sdev = NULL;
int result = 0, ret = 0;
fp_info("%s ", __func__);
/* Set enroll stage number */
fpi_dev_set_nr_enroll_stages(dev, ENROLL_SAMPLES);
/* Initialize private structure */
sdev = g_malloc0(sizeof(synaptics_dev));
result = bmkt_init(&(sdev->ctx));
if (result != BMKT_SUCCESS)
{
fp_err("Failed to initialize bmkt context: %d", result);
return -1;
}
fp_info("bmkt_init successfully.");
result = bmkt_open(sdev->ctx, &sdev->sensor, general_error_callback, NULL, fpi_dev_get_usb_dev(dev));
if (result != BMKT_SUCCESS)
{
fp_err("Failed to open bmkt sensor: %d", result);
goto bmkt_cleanup;
}
result = bmkt_register_finger_event_notification(sdev->sensor, finger_event_callback, dev);
if (result != BMKT_SUCCESS)
{
fp_err("Failed to register finger event notification: %d", result);
goto bmkt_cleanup;
}
result = bmkt_init_fps(sdev->sensor);
if (result == BMKT_SUCCESS)
{
fp_info("Successfully initialized the FPS");
}
else if (result == BMKT_OPERATION_DENIED)
{
/* sensor already intialized...allow operations to continue */
fp_info("FPS already initialized");
result = BMKT_SUCCESS;
}
else
{
fp_err("Failed to initialize the FPS: %d", result);
goto bmkt_cleanup;
}
fp_dev_set_instance_data(dev, sdev);
/* Notify open complete */
fpi_drvcb_open_complete(dev, 0);
return result;
bmkt_cleanup:
ret = bmkt_close(sdev->sensor);
if (ret != BMKT_SUCCESS)
{
fp_err("Failed to close bmkt sensor: %d", ret);
goto cleanup;
}
bmkt_exit(sdev->ctx);
g_free(sdev);
cleanup:
fpi_drvcb_open_complete(dev, 1);
return result;
}
static void dev_exit(struct fp_dev *dev)
{
int ret = 0;
synaptics_dev *sdev = FP_INSTANCE_DATA(dev);
ret = bmkt_close(sdev->sensor);
if (ret != BMKT_SUCCESS)
{
fp_err("Failed to close bmkt sensor: %d", ret);
return;
}
bmkt_exit(sdev->ctx);
g_free(sdev);
fpi_drvcb_close_complete(dev);
}
static gboolean rand_string(char *str, size_t size)
{
const char charset[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
srand(time(NULL));
if (size) {
--size;
for (size_t n = 0; n < size; n++) {
int key = rand() % (int) (sizeof charset - 1);
str[n] = charset[key];
}
str[size] = '\0';
}
else
return FALSE;
return TRUE;
}
#define TEMPLATE_ID_SIZE 20
static int del_enrolled_user_resp(bmkt_response_t *resp, void *ctx)
{
bmkt_del_user_resp_t *del_user_resp = &resp->response.del_user_resp;
struct fp_dev *dev=(struct fp_dev *)ctx;
synaptics_dev *sdev = FP_INSTANCE_DATA(dev);
switch (resp->response_id)
{
case BMKT_RSP_DELETE_PROGRESS:
fp_info("Deleting Enrolled Users is %d%% complete",
del_user_resp->progress);
break;
case BMKT_RSP_DEL_USER_FP_FAIL:
fp_info("Failed to delete enrolled user: %d", resp->result);
bmkt_op_set_state(sdev->sensor, BMKT_OP_STATE_COMPLETE);
if(sdev->state == SYNA_STATE_DELETE)
{
/* Return result complete when record doesn't exist, otherwise host data
won't be deleted. */
if(resp->result == BMKT_FP_DATABASE_NO_RECORD_EXISTS)
fpi_drvcb_delete_complete(dev, FP_DELETE_COMPLETE);
else
fpi_drvcb_delete_complete(dev, FP_DELETE_FAIL);
}
break;
case BMKT_RSP_DEL_USER_FP_OK:
fp_info("Successfully deleted enrolled user");
bmkt_op_set_state(sdev->sensor, BMKT_OP_STATE_COMPLETE);
if(sdev->state == SYNA_STATE_DELETE)
{
fpi_drvcb_delete_complete(dev, FP_DELETE_COMPLETE);
}
break;
}
return 0;
}
static int enroll_start(struct fp_dev *dev)
{
synaptics_dev *sdev = FP_INSTANCE_DATA(dev);
int result = 0;
char userid[TEMPLATE_ID_SIZE + 1];
fp_info("enroll_start");
rand_string(userid, TEMPLATE_ID_SIZE);
int useridlength =0;
int finger_id;
finger_id = 1;
useridlength = strlen(userid);
sdev->state = SYNA_STATE_ENROLL;
result = bmkt_enroll(sdev->sensor, userid, useridlength,
finger_id, enroll_response, dev);
if (result)
{
fp_err("Failed to enroll finger: %d", result);
}
return 0;
}
static int enroll_stop(struct fp_dev *dev)
{
fp_info("syna enroll stop");
synaptics_dev *sdev = FP_INSTANCE_DATA(dev);
sdev->state = SYNA_STATE_IDLE;
fpi_drvcb_enroll_stopped(dev);
return 1;
}
static int verify_response(bmkt_response_t *resp, void *ctx)
{
bmkt_verify_resp_t *verify_resp = &resp->response.verify_resp;
struct fp_dev *dev=(struct fp_dev *)ctx;
synaptics_dev *sdev = FP_INSTANCE_DATA(dev);
switch (resp->response_id)
{
case BMKT_RSP_VERIFY_READY:
{
fp_info("Place Finger on the Sensor!");
fpi_drvcb_verify_started(dev, 0);
break;
}
case BMKT_RSP_CAPTURE_COMPLETE:
{
fp_info("Fingerprint image capture complete!");
break;
}
case BMKT_RSP_VERIFY_FAIL:
{
fp_err("Verify has failed!: %d", resp->result);
if(resp->result == BMKT_SENSOR_STIMULUS_ERROR || resp->result == BMKT_FP_NO_MATCH)
{
sdev->state = SYNA_STATE_VERIFY_DELAY_RESULT;
}
else
{
bmkt_op_set_state(sdev->sensor, BMKT_OP_STATE_COMPLETE);
fpi_drvcb_report_verify_result(dev, FP_VERIFY_NO_MATCH, NULL);
}
break;
}
case BMKT_RSP_VERIFY_OK:
{
fp_info("Verify was successful! for user: %s finger: %d score: %f",
verify_resp->user_id, verify_resp->finger_id, verify_resp->match_result);
bmkt_op_set_state(sdev->sensor, BMKT_OP_STATE_COMPLETE);
fpi_drvcb_report_verify_result(dev, FP_VERIFY_MATCH, NULL);
break;
}
}
return 0;
}
static int delete_finger(struct fp_dev *dev)
{
synaptics_dev *sdev = FP_INSTANCE_DATA(dev);
int result = 0;
struct fp_print_data *print = fpi_dev_get_delete_data(dev);;
struct fp_print_data_item *item = print->prints->data;
struct syna_mis_print_data *print_data;
bmkt_user_id_t user;
if(item->length != sizeof(struct syna_mis_print_data))
{
fp_err("print data is incorrect !");
goto cleanup;
}
print_data = (struct syna_mis_print_data *)item->data;
memset(&user, 0, sizeof(bmkt_user_id_t));
memcpy(user.user_id, print_data->user_id, sizeof(print_data->user_id));
fp_info("delete finger !");
user.user_id_len = strlen(user.user_id);
if (user.user_id_len <= 0 || user.user_id[0] == ' ')
{
fp_err("Invalid user name.");
goto cleanup;
}
sdev->state = SYNA_STATE_DELETE;
result = bmkt_delete_enrolled_user(sdev->sensor, 1, print_data->user_id,
user.user_id_len, del_enrolled_user_resp, dev);
if (result != BMKT_SUCCESS)
{
fp_err("Failed to delete enrolled user: %d", result);
goto cleanup;
}
return 0;
cleanup:
return -1;
}
static int verify_start(struct fp_dev *dev)
{
synaptics_dev *sdev = FP_INSTANCE_DATA(dev);
int result = 0;
struct fp_print_data *print = fpi_dev_get_verify_data(dev);;
struct fp_print_data_item *item = print->prints->data;
struct syna_mis_print_data *print_data;
bmkt_user_id_t user;
if(item->length != sizeof(struct syna_mis_print_data))
{
fp_err("print data is incorrect !");
goto cleanup;
}
print_data = (struct syna_mis_print_data *)item->data;
memset(&user, 0, sizeof(bmkt_user_id_t));
memcpy(user.user_id, print_data->user_id, sizeof(print_data->user_id));
fp_info("syna verify_start !");
user.user_id_len = strlen(user.user_id);
if (user.user_id_len <= 0 || user.user_id[0] == ' ')
{
fp_err("Invalid user name.");
goto cleanup;
}
sdev->state = SYNA_STATE_VERIFY;
result = bmkt_verify(sdev->sensor, &user, verify_response, dev);
if (result != BMKT_SUCCESS)
{
fp_err("Failed to verify finger: %d", result);
}
return 0;
cleanup:
fpi_drvcb_verify_started(dev, 1);
return -1;
}
static int verify_stop(struct fp_dev *dev, gboolean iterating)
{
fp_info("syna verify_stop");
synaptics_dev *sdev = FP_INSTANCE_DATA(dev);
sdev->state = SYNA_STATE_IDLE;
fpi_drvcb_verify_stopped(dev);
return 0;
}
struct fp_driver synaptics_driver = {
.id = SYNAPTICS_ID,
.name = FP_COMPONENT,
.full_name = SYNAPTICS_DRIVER_FULLNAME,
.id_table = id_table,
.scan_type = FP_SCAN_TYPE_PRESS,
.open = dev_init,
.close = dev_exit,
.enroll_start = enroll_start,
.enroll_stop = enroll_stop,
.verify_start = verify_start,
.verify_stop = verify_stop,
.delete_finger = delete_finger,
};

View File

@@ -0,0 +1,58 @@
/*
* Copyright (C) 2019 Synaptics Inc
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __synaptics_h__
#define __synaptics_h__
#define SYNAPTICS_VENDOR_ID 0x06cb
#define SYNAPTICS_PRODUCT_ID_A9 0x00a9
/* Number of enroll stages */
#define ENROLL_SAMPLES 12
#define SYNAPTICS_DRIVER_FULLNAME "Synaptics Sensors"
#include "bmkt.h"
#include "bmkt_response.h"
struct syna_enroll_resp_data
{
int progress;
};
typedef enum syna_state
{
SYNA_STATE_UNINIT = 0,
SYNA_STATE_IDLE ,
SYNA_STATE_ENROLL ,
SYNA_STATE_IDENTIFY ,
SYNA_STATE_IDENTIFY_DELAY_RESULT ,
SYNA_STATE_VERIFY ,
SYNA_STATE_VERIFY_DELAY_RESULT ,
SYNA_STATE_DELETE ,
} syna_state_t;
typedef struct synaptics_dev_s
{
bmkt_ctx_t *ctx;
bmkt_sensor_t *sensor;
struct syna_enroll_resp_data enroll_resp_data;
gboolean isFingerOnSensor;
syna_state_t state;
}synaptics_dev;
#endif //__synaptics_h__

View File

@@ -0,0 +1,386 @@
/*
* Copyright (C) 2019 Synaptics Inc
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "bmkt_internal.h"
#include "sensor.h"
#include "drivers_api.h"
#define USB_ASYNC_MESSAGE_PENDING 0x4
static void usb_int_callback(struct libusb_transfer *transfer)
{
bmkt_usb_transport_t *usb_xport = (bmkt_usb_transport_t *)transfer->user_data;
#ifdef TRANSPORT_DEBUG
bmkt_dbg_log("INTERRUPT: (%d) ", transfer->actual_length);
print_buffer(transfer->buffer, transfer->actual_length);
#endif
if (transfer->buffer[0] & USB_ASYNC_MESSAGE_PENDING)
{
libusb_free_transfer(transfer);
bmkt_op_next_state(usb_xport->sensor);
}
else
libusb_submit_transfer(transfer);
}
int usb_check_interrupt(bmkt_usb_transport_t *usb_xport)
{
int ret;
struct libusb_transfer *interrupt_xfer;
interrupt_xfer = libusb_alloc_transfer(0);
if (interrupt_xfer == NULL)
{
return BMKT_GENERAL_ERROR;
}
libusb_fill_interrupt_transfer(interrupt_xfer, usb_xport->handle, USB_EP_INTERRUPT,
usb_xport->interrupt_data, sizeof(usb_xport->interrupt_data), usb_int_callback, usb_xport, 0);
ret = libusb_submit_transfer(interrupt_xfer);
if (ret != LIBUSB_SUCCESS)
{
libusb_free_transfer(interrupt_xfer);
if (ret == LIBUSB_ERROR_NO_DEVICE)
{
return BMKT_SENSOR_MALFUNCTION;
}
else
{
return BMKT_GENERAL_ERROR;
}
}
return BMKT_SUCCESS;
}
int usb_open(bmkt_usb_transport_t *usb_xport)
{
int ret;
struct libusb_config_descriptor *configDesc;
const struct libusb_interface *iface;
const struct libusb_interface_descriptor *ifaceDesc;
const struct libusb_endpoint_descriptor *endpointDesc;
int config;
int i;
usb_xport->device = libusb_get_device(usb_xport->handle);
ret = libusb_reset_device(usb_xport->handle);
if (ret)
{
bmkt_dbg_log("Failed to reset device\n");
}
ret = libusb_get_config_descriptor(usb_xport->device, USB_DEFAULT_CONFIGURATION, &configDesc);
if (ret)
{
ret = BMKT_SENSOR_MALFUNCTION;
return ret;
}
ret = libusb_get_configuration(usb_xport->handle, &config);
if (ret)
{
ret = BMKT_SENSOR_MALFUNCTION;
goto free_config;
}
if (configDesc->bConfigurationValue != config)
{
ret = libusb_set_configuration(usb_xport->handle, config);
if (ret)
{
ret = BMKT_SENSOR_MALFUNCTION;
goto free_config;
}
}
ret = libusb_kernel_driver_active(usb_xport->handle, 0);
if (ret == 1)
{
bmkt_err_log("Failed to detect kernel driver\n");
ret = BMKT_SENSOR_MALFUNCTION;
goto free_config;
}
ret = libusb_claim_interface(usb_xport->handle, USB_DEFAULT_INTERFACE);
if (ret)
{
ret = BMKT_SENSOR_MALFUNCTION;
goto free_config;
}
iface = configDesc->interface + USB_DEFAULT_INTERFACE;
ifaceDesc = iface->altsetting + USB_DEFAULT_ALT_SETTING;
endpointDesc = ifaceDesc->endpoint;
for (i = 0; i < ifaceDesc->bNumEndpoints; i++)
{
ret = libusb_clear_halt(usb_xport->handle, endpointDesc->bEndpointAddress);
if (ret)
{
ret = BMKT_SENSOR_MALFUNCTION;
goto free_config;
}
++endpointDesc;
}
free_config:
libusb_free_config_descriptor(configDesc);
return ret;
}
int usb_close(bmkt_usb_transport_t *usb_xport)
{
if (usb_xport->handle)
{
libusb_release_interface(usb_xport->handle, USB_DEFAULT_INTERFACE);
}
return BMKT_SUCCESS;
}
void usb_in_cb(struct libusb_transfer *transfer)
{
uint8_t *resp_buf;
int resp_len;
bmkt_msg_resp_t msg_resp;
bmkt_usb_transport_t *usb_xport = (bmkt_usb_transport_t *)transfer->user_data;
#ifdef TRANSPORT_DEBUG
bmkt_dbg_log("RX_ASYNC: (%d) ", transfer->actual_length);
print_buffer(transfer->buffer, transfer->actual_length);
#endif
resp_buf = transfer->buffer;
resp_len = transfer->actual_length;
bmkt_sensor_handle_response(usb_xport->sensor, resp_buf, resp_len, &msg_resp);
libusb_free_transfer(transfer);
bmkt_op_next_state(usb_xport->sensor);
}
void usb_out_cb(struct libusb_transfer *transfer)
{
bmkt_usb_transport_t *usb_xport = (bmkt_usb_transport_t *)transfer->user_data;
libusb_free_transfer(transfer);
bmkt_op_next_state(usb_xport->sensor);
}
static int bulk_transfer_async(bmkt_usb_transport_t *usb_xport, uint8_t *buf, int size, uint8_t endpoint,
int *transferred, uint32_t timeout, libusb_transfer_cb_fn callback)
{
int ret;
struct libusb_transfer *transfer;
#ifdef TRANSPORT_DEBUG
if (!(endpoint & 0x80))
{
bmkt_dbg_log("TX2: (%d) ", size);
print_buffer(buf, size);
}
#endif
transfer = libusb_alloc_transfer(0);
libusb_fill_bulk_transfer( transfer, usb_xport->handle, endpoint,
buf, size, callback, usb_xport, 0);
ret = libusb_submit_transfer(transfer);
if (ret != LIBUSB_SUCCESS)
{
libusb_free_transfer(transfer);
if (ret == LIBUSB_ERROR_NO_DEVICE)
{
return BMKT_SENSOR_MALFUNCTION;
}
else
{
return BMKT_GENERAL_ERROR;
}
}
return BMKT_SUCCESS;
}
static int bulk_transfer(bmkt_usb_transport_t *usb_xport, uint8_t *buf, int size, uint8_t endpoint,
int *transferred, uint32_t timeout)
{
int ret;
#ifdef TRANSPORT_DEBUG
if (!(endpoint & 0x80))
{
bmkt_dbg_log("TX: (%d) ", size);
print_buffer(buf, size);
}
#endif
ret = libusb_bulk_transfer(usb_xport->handle, endpoint, buf, size, transferred, timeout);
if (ret)
{
bmkt_warn_log("libusb_bulk_transfer: bulk transfer failed: %d\n", ret);
if (ret == LIBUSB_ERROR_TIMEOUT)
{
return BMKT_OP_TIME_OUT;
}
else
{
return BMKT_SENSOR_MALFUNCTION;
}
}
bmkt_dbg_log("transferred: %d\n", *transferred);
#ifdef TRANSPORT_DEBUG
if (endpoint & 0x80)
{
bmkt_dbg_log("RX: (%d) ", *transferred);
print_buffer(buf, *transferred);
}
#endif
return BMKT_SUCCESS;
}
int usb_send_command(bmkt_usb_transport_t *usb_xport, int len)
{
int ret;
int tx_len = 0;
ret = bulk_transfer_async(usb_xport, usb_xport->transfer, len, USB_EP_REQUEST, &tx_len, 0, usb_out_cb);
if (ret != BMKT_SUCCESS)
{
bmkt_dbg_log("Failed to send usb command\n");
return ret;
}
return BMKT_SUCCESS;
}
int usb_get_command_buffer(bmkt_usb_transport_t *usb_xport, uint8_t **cmd, int *len)
{
*len = BMKT_MAX_TRANSFER_LEN;
*cmd = usb_xport->transfer;
return BMKT_SUCCESS;
}
int usb_get_response_buffer(bmkt_usb_transport_t *usb_xport, uint8_t **resp, int *len)
{
*len = BMKT_MAX_TRANSFER_LEN;
*resp = usb_xport->transfer;
return BMKT_SUCCESS;
}
int usb_receive_resp_async(bmkt_usb_transport_t *usb_xport, int *len)
{
int ret;
*len = BMKT_MAX_TRANSFER_LEN;
/* Check to make sure the buffer is clear */
memset(usb_xport->transfer, 0, BMKT_MAX_TRANSFER_LEN);
ret = bulk_transfer_async(usb_xport, usb_xport->transfer, *len, USB_EP_REPLY, len, 0, usb_in_cb);
if (ret != BMKT_SUCCESS)
{
bmkt_dbg_log("Failed to send usb command\n");
return ret;
}
return BMKT_SUCCESS;
}
int usb_receive_resp(bmkt_usb_transport_t *usb_xport, int *len)
{
int ret;
*len = BMKT_MAX_TRANSFER_LEN;
/* Check to make sure the buffer is clear */
memset(usb_xport->transfer, 0, BMKT_MAX_TRANSFER_LEN);
ret = bulk_transfer(usb_xport, usb_xport->transfer, *len, USB_EP_REPLY, len, 0);
if (ret != BMKT_SUCCESS)
{
bmkt_dbg_log("Failed to send usb command\n");
return ret;
}
return BMKT_SUCCESS;
}
int usb_send_command_sync(bmkt_usb_transport_t *usb_xport, int len, uint8_t **resp_buf,
int *resp_len)
{
int ret;
int tx_len = 0;
ret = bulk_transfer(usb_xport, usb_xport->transfer, len, USB_EP_REQUEST, &tx_len, 0);
if (ret != BMKT_SUCCESS)
{
bmkt_dbg_log("Failed to send usb command\n");
return ret;
}
/* Check to make sure the buffer is clear */
memset(usb_xport->transfer, 0, BMKT_MAX_TRANSFER_LEN);
ret = bulk_transfer(usb_xport, usb_xport->transfer, *resp_len, USB_EP_REPLY, resp_len, 0);
if (ret != BMKT_SUCCESS)
{
bmkt_dbg_log("Failed to send usb command\n");
return ret;
}
*resp_buf = usb_xport->transfer;
return BMKT_SUCCESS;
}
int usb_reset(bmkt_usb_transport_t *usb_xport)
{
return BMKT_OPERATION_DENIED;
}
int usb_release_command_buffer(bmkt_usb_transport_t *usb_xport)
{
return BMKT_SUCCESS;
}
int usb_release_response_buffer(bmkt_usb_transport_t *usb_xport)
{
return BMKT_SUCCESS;
}

View File

@@ -0,0 +1,76 @@
/*
* Copyright (C) 2019 Synaptics Inc
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _USB_TRANSPORT_H_
#define _USB_TRANSPORT_H_
#include "bmkt_internal.h"
#include "libusb-1.0/libusb.h"
#define BMKT_MAX_TRANSFER_LEN 263 + 1 /* SPI Header */ + 2 /* VCSFW header */
#define BMKT_XPORT_INT_NONE 0x0
#define BMKT_XPORT_INT_RESPONSE 0x1
#define BMKT_XPORT_INT_FINGER 0x2
#define BMKT_XPORT_INT_ASYNC 0x4
#define USB_DEFAULT_CONFIGURATION 0
#define USB_DEFAULT_INTERFACE 0
#define USB_DEFAULT_ALT_SETTING 0
#define USB_EP_REQUEST 0x01
#define USB_EP_REPLY 0x81
#define USB_EP_FINGERPRINT 0x82
#define USB_EP_INTERRUPT 0x83
#define USB_INTERRUPT_DATA_SIZE 7
typedef struct bmkt_usb_transport
{
libusb_context *ctx;
libusb_device *device;
libusb_device_handle *handle;
uint8_t interrupt_data[USB_INTERRUPT_DATA_SIZE];
bmkt_sensor_t *sensor;
uint8_t transfer[BMKT_MAX_TRANSFER_LEN];
} bmkt_usb_transport_t;
int usb_release_command_buffer(bmkt_usb_transport_t *xport);
int usb_release_response_buffer(bmkt_usb_transport_t *xport);
int usb_open(bmkt_usb_transport_t *xport);
int usb_close(bmkt_usb_transport_t *xport);
int usb_send_command(bmkt_usb_transport_t *xport, int len);
int usb_get_command_buffer(bmkt_usb_transport_t *xport, uint8_t **cmd, int *len);
int usb_get_response_buffer(bmkt_usb_transport_t *xport, uint8_t **resp, int *len);
int usb_receive_resp(bmkt_usb_transport_t *xport, int *len);
int usb_send_command_sync(bmkt_usb_transport_t *xport, int len, uint8_t **resp_buf,
int *resp_len);
int usb_receive_resp_async(bmkt_usb_transport_t *usb_xport, int *len);
int usb_check_interrupt(bmkt_usb_transport_t *usb_xport);
#endif /* _USB_TRANSPORT_H_ */

View File

@@ -0,0 +1,87 @@
/*
* Copyright (C) 2019 Synaptics Inc
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "bmkt_internal.h"
#include "sensor.h"
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wformat-zero-length"
void print_buffer(uint8_t *buf, int len)
{
int i;
for (i = 0; i < len; i++)
{
bmkt_dbg_log("0x%02x ", buf[i]);
if ((i % 16) == 15)
{
bmkt_dbg_log("");
}
}
bmkt_dbg_log("");
}
#pragma GCC diagnostic pop
uint32_t extract32(const uint8_t *buf, int *offset)
{
uint32_t ret = 0;
int off = 0;
if (offset)
{
off = *offset;
}
ret = GUINT32_FROM_LE(*(uint32_t*)(buf + off));
if (offset)
{
*offset += 4;
}
return ret;
}
uint16_t extract16(const uint8_t *buf, int *offset)
{
uint16_t ret = 0;
int off = 0;
if (offset)
{
off = *offset;
}
ret = GUINT16_FROM_LE(*(uint16_t*)(buf + off));
if (offset)
{
*offset += 2;
}
return ret;
}
uint8_t extract8(const uint8_t *buf, int *offset)
{
uint8_t ret = 0;
int off = 0;
if (offset)
{
off = *offset;
}
ret = *(buf + off);
if (offset)
{
*offset += 1;
}
return ret;
}

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 dev_model;
int img_width; int img_width;
struct fpi_ssm *loopsm; fpi_ssm *loopsm;
struct libusb_transfer *img_transfer[NUM_BULK_TRANSFERS]; struct libusb_transfer *img_transfer[NUM_BULK_TRANSFERS];
struct img_transfer_data *img_transfer_data; struct img_transfer_data *img_transfer_data;
int num_flying; int num_flying;
@@ -100,18 +100,21 @@ struct sonly_dev {
enum sonly_kill_transfers_action killing_transfers; enum sonly_kill_transfers_action killing_transfers;
int kill_status_code; int kill_status_code;
union { union {
struct fpi_ssm *kill_ssm; fpi_ssm *kill_ssm;
void (*kill_cb)(struct fp_img_dev *dev); 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, static int upeksonly_get_deviation2(struct fpi_line_asmbl_ctx *ctx,
GSList *line1, GSList *line2) GSList *line1, GSList *line2)
{ {
unsigned char *buf1 = line1->data, *buf2 = line2->data; unsigned char *buf1 = line1->data, *buf2 = line2->data;
int res = 0, mean = 0, i; int res = 0, mean = 0, i;
g_assert (ctx->line_width > 0);
for (i = 0; i < ctx->line_width; i+= 2) for (i = 0; i < ctx->line_width; i+= 2)
mean += (int)buf1[i + 1] + (int)buf2[i]; 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) 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) { switch (sdev->killing_transfers) {
case ABORT_SSM: case ABORT_SSM:
fp_dbg("abort ssm error %d", sdev->kill_status_code); 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; return;
case ITERATE_SSM: case ITERATE_SSM:
fp_dbg("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) 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; int i;
if (sdev->num_flying == 0) { 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) 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; struct fp_img *img;
GSList *elem = sdev->rows; 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) 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; sdev->rowbuf_offset = -1;
if (sdev->num_rows > 0) { if (sdev->num_rows > 0) {
@@ -340,7 +343,7 @@ static void row_complete(struct fp_img_dev *dev)
/* add data to row buffer */ /* add data to row buffer */
static void add_to_rowbuf(struct fp_img_dev *dev, unsigned char *data, int size) 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); memcpy(sdev->rowbuf + sdev->rowbuf_offset, data, size);
sdev->rowbuf_offset += 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) 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]; uint16_t seqnum = data[0] << 8 | data[1];
int abs_base_addr; int abs_base_addr;
int for_rowbuf; 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 img_transfer_data *idata = transfer->user_data;
struct fp_img_dev *dev = idata->dev; 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; int i;
idata->flying = FALSE; idata->flying = FALSE;
@@ -520,7 +523,7 @@ static void img_data_cb(struct libusb_transfer *transfer)
/***** STATE MACHINE HELPERS *****/ /***** STATE MACHINE HELPERS *****/
struct write_regs_data { struct write_regs_data {
struct fpi_ssm *ssm; fpi_ssm *ssm;
struct libusb_transfer *transfer; struct libusb_transfer *transfer;
const struct sonly_regwrite *regs; const struct sonly_regwrite *regs;
size_t num_regs; size_t num_regs;
@@ -534,7 +537,7 @@ static void write_regs_finished(struct write_regs_data *wrdata, int result)
if (result == 0) if (result == 0)
fpi_ssm_next_state(wrdata->ssm); fpi_ssm_next_state(wrdata->ssm);
else else
fpi_ssm_mark_aborted(wrdata->ssm, result); fpi_ssm_mark_failed(wrdata->ssm, result);
g_free(wrdata); g_free(wrdata);
} }
@@ -574,23 +577,18 @@ static void write_regs_cb(struct libusb_transfer *transfer)
write_regs_iterate(wrdata); write_regs_iterate(wrdata);
} }
static void sm_write_regs(struct fpi_ssm *ssm, static void
const struct sonly_regwrite *regs, size_t num_regs) 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)); struct write_regs_data *wrdata = g_malloc(sizeof(*wrdata));
unsigned char *data; 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); data = g_malloc(LIBUSB_CONTROL_SETUP_SIZE + 1);
libusb_fill_control_setup(data, 0x40, 0x0c, 0, 0, 1); libusb_fill_control_setup(data, 0x40, 0x0c, 0, 0, 1);
dev = fpi_ssm_get_dev(ssm);
libusb_fill_control_transfer(wrdata->transfer, libusb_fill_control_transfer(wrdata->transfer,
fpi_dev_get_usb_dev(dev), data, fpi_dev_get_usb_dev(dev), data,
write_regs_cb, wrdata, CTRL_TIMEOUT); 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) 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); g_free(transfer->buffer);
if (transfer->status != LIBUSB_TRANSFER_COMPLETED) if (transfer->status != LIBUSB_TRANSFER_COMPLETED)
fpi_ssm_mark_aborted(ssm, -EIO); fpi_ssm_mark_failed(ssm, -EIO);
else else
fpi_ssm_next_state(ssm); 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 = fpi_usb_alloc();
struct libusb_transfer *transfer = libusb_alloc_transfer(0);
unsigned char *data; unsigned char *data;
int r; int r;
if (!transfer) {
fpi_ssm_mark_aborted(ssm, -ENOMEM);
return;
}
fp_dbg("set %02x=%02x", reg, value); fp_dbg("set %02x=%02x", reg, value);
data = g_malloc(LIBUSB_CONTROL_SETUP_SIZE + 1); data = g_malloc(LIBUSB_CONTROL_SETUP_SIZE + 1);
libusb_fill_control_setup(data, 0x40, 0x0c, 0, reg, 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, data, sm_write_reg_cb,
ssm, CTRL_TIMEOUT); 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) { if (r < 0) {
g_free(data); g_free(data);
libusb_free_transfer(transfer); libusb_free_transfer(transfer);
fpi_ssm_mark_aborted(ssm, r); fpi_ssm_mark_failed(ssm, r);
} }
} }
static void sm_read_reg_cb(struct libusb_transfer *transfer) 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 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) { if (transfer->status != LIBUSB_TRANSFER_COMPLETED) {
fpi_ssm_mark_aborted(ssm, -EIO); fpi_ssm_mark_failed(ssm, -EIO);
} else { } else {
sdev->read_reg_result = libusb_control_transfer_get_data(transfer)[0]; sdev->read_reg_result = libusb_control_transfer_get_data(transfer)[0];
fp_dbg("read reg result = %02x", sdev->read_reg_result); 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); 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 = fpi_usb_alloc();
struct libusb_transfer *transfer = libusb_alloc_transfer(0);
unsigned char *data; unsigned char *data;
int r; int r;
if (!transfer) {
fpi_ssm_mark_aborted(ssm, -ENOMEM);
return;
}
fp_dbg("read reg %02x", reg); fp_dbg("read reg %02x", reg);
data = g_malloc(LIBUSB_CONTROL_SETUP_SIZE + 8); data = g_malloc(LIBUSB_CONTROL_SETUP_SIZE + 8);
libusb_fill_control_setup(data, 0xc0, 0x0c, 0, reg, 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, data, sm_read_reg_cb,
ssm, CTRL_TIMEOUT); ssm, CTRL_TIMEOUT);
transfer->flags = LIBUSB_TRANSFER_SHORT_NOT_OK | 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) { if (r < 0) {
g_free(data); g_free(data);
libusb_free_transfer(transfer); libusb_free_transfer(transfer);
fpi_ssm_mark_aborted(ssm, r); fpi_ssm_mark_failed(ssm, r);
} }
} }
static void sm_await_intr_cb(struct libusb_transfer *transfer) 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 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) { if (transfer->status != LIBUSB_TRANSFER_COMPLETED) {
g_free(transfer->buffer); g_free(transfer->buffer);
fpi_ssm_mark_aborted(ssm, transfer->status); fpi_ssm_mark_failed(ssm, transfer->status);
return; return;
} }
@@ -713,21 +706,17 @@ static void sm_await_intr_cb(struct libusb_transfer *transfer)
fpi_ssm_next_state(ssm); 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 = fpi_usb_alloc();
struct libusb_transfer *transfer = libusb_alloc_transfer(0);
unsigned char *data; unsigned char *data;
int r; int r;
if (!transfer) {
fpi_ssm_mark_aborted(ssm, -ENOMEM);
return;
}
G_DEBUG_HERE(); G_DEBUG_HERE();
data = g_malloc(4); 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, 0x83, data, 4,
sm_await_intr_cb, ssm, 0); sm_await_intr_cb, ssm, 0);
transfer->flags = LIBUSB_TRANSFER_SHORT_NOT_OK | transfer->flags = LIBUSB_TRANSFER_SHORT_NOT_OK |
@@ -737,7 +726,7 @@ static void sm_await_intr(struct fpi_ssm *ssm)
if (r < 0) { if (r < 0) {
libusb_free_transfer(transfer); libusb_free_transfer(transfer);
g_free(data); 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, 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 fp_img_dev *dev = user_data;
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)) { switch (fpi_ssm_get_cur_state(ssm)) {
case AWFSM_2016_WRITEV_1: 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; break;
case AWFSM_2016_READ_01: case AWFSM_2016_READ_01:
sm_read_reg(ssm, 0x01); sm_read_reg(ssm, dev, 0x01);
break; break;
case AWFSM_2016_WRITE_01: case AWFSM_2016_WRITE_01:
if (sdev->read_reg_result != 0xc6) if (sdev->read_reg_result != 0xc6)
sm_write_reg(ssm, 0x01, 0x46); sm_write_reg(ssm, dev, 0x01, 0x46);
else else
sm_write_reg(ssm, 0x01, 0xc6); sm_write_reg(ssm, dev, 0x01, 0xc6);
break; break;
case AWFSM_2016_WRITEV_2: 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; break;
case AWFSM_2016_READ_13: case AWFSM_2016_READ_13:
sm_read_reg(ssm, 0x13); sm_read_reg(ssm, dev, 0x13);
break; break;
case AWFSM_2016_WRITE_13: case AWFSM_2016_WRITE_13:
if (sdev->read_reg_result != 0x45) if (sdev->read_reg_result != 0x45)
sm_write_reg(ssm, 0x13, 0x05); sm_write_reg(ssm, dev, 0x13, 0x05);
else else
sm_write_reg(ssm, 0x13, 0x45); sm_write_reg(ssm, dev, 0x13, 0x45);
break; break;
case AWFSM_2016_WRITEV_3: 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; break;
case AWFSM_2016_READ_07: case AWFSM_2016_READ_07:
sm_read_reg(ssm, 0x07); sm_read_reg(ssm, dev, 0x07);
break; break;
case AWFSM_2016_WRITE_07: case AWFSM_2016_WRITE_07:
if (sdev->read_reg_result != 0x10 && sdev->read_reg_result != 0x90) if (sdev->read_reg_result != 0x10 && sdev->read_reg_result != 0x90)
fp_warn("odd reg7 value %x", sdev->read_reg_result); 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; break;
case AWFSM_2016_WRITEV_4: 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; 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)) { switch (fpi_ssm_get_cur_state(ssm)) {
case AWFSM_1000_WRITEV_1: 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; break;
case AWFSM_1000_WRITEV_2: 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; break;
} }
} }
@@ -851,17 +840,19 @@ enum capsm_1001_states {
CAPSM_1001_NUM_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 fp_img_dev *dev = FP_IMG_DEV(_dev);
struct sonly_dev *sdev = fpi_imgdev_get_user_data(dev); struct sonly_dev *sdev = FP_INSTANCE_DATA(_dev);
int i; int i;
for (i = 0; i < NUM_BULK_TRANSFERS; i++) { for (i = 0; i < NUM_BULK_TRANSFERS; i++) {
int r = libusb_submit_transfer(sdev->img_transfer[i]); int r = libusb_submit_transfer(sdev->img_transfer[i]);
if (r < 0) { if (r < 0) {
if (i == 0) { if (i == 0) {
/* first one failed: easy peasy */ /* first one failed: easy peasy */
fpi_ssm_mark_aborted(ssm, r); fpi_ssm_mark_failed(ssm, r);
return; return;
} }
@@ -881,10 +872,10 @@ static void capsm_fire_bulk(struct fpi_ssm *ssm)
fpi_ssm_next_state(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 fp_img_dev *dev = user_data;
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)) { switch (fpi_ssm_get_cur_state(ssm)) {
case CAPSM_2016_INIT: case CAPSM_2016_INIT:
@@ -899,24 +890,23 @@ static void capsm_2016_run_state(struct fpi_ssm *ssm)
fpi_ssm_next_state(ssm); fpi_ssm_next_state(ssm);
break; break;
case CAPSM_2016_WRITE_15: case CAPSM_2016_WRITE_15:
sm_write_reg(ssm, 0x15, 0x20); sm_write_reg(ssm, dev, 0x15, 0x20);
break; break;
case CAPSM_2016_WRITE_30: case CAPSM_2016_WRITE_30:
sm_write_reg(ssm, 0x30, 0xe0); sm_write_reg(ssm, dev, 0x30, 0xe0);
break; break;
case CAPSM_2016_FIRE_BULK: ; case CAPSM_2016_FIRE_BULK: ;
capsm_fire_bulk (ssm); capsm_fire_bulk (ssm, _dev);
break; break;
case CAPSM_2016_WRITEV: 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; 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 = FP_INSTANCE_DATA(_dev);
struct sonly_dev *sdev = fpi_imgdev_get_user_data(dev);
switch (fpi_ssm_get_cur_state(ssm)) { switch (fpi_ssm_get_cur_state(ssm)) {
case CAPSM_1000_INIT: case CAPSM_1000_INIT:
@@ -931,18 +921,17 @@ static void capsm_1000_run_state(struct fpi_ssm *ssm)
fpi_ssm_next_state(ssm); fpi_ssm_next_state(ssm);
break; break;
case CAPSM_1000_FIRE_BULK: ; case CAPSM_1000_FIRE_BULK: ;
capsm_fire_bulk (ssm); capsm_fire_bulk (ssm, _dev);
break; break;
case CAPSM_1000_WRITEV: 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; 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 = FP_INSTANCE_DATA(_dev);
struct sonly_dev *sdev = fpi_imgdev_get_user_data(dev);
switch (fpi_ssm_get_cur_state(ssm)) { switch (fpi_ssm_get_cur_state(ssm)) {
case CAPSM_1001_INIT: case CAPSM_1001_INIT:
@@ -957,22 +946,22 @@ static void capsm_1001_run_state(struct fpi_ssm *ssm)
fpi_ssm_next_state(ssm); fpi_ssm_next_state(ssm);
break; break;
case CAPSM_1001_FIRE_BULK: ; case CAPSM_1001_FIRE_BULK: ;
capsm_fire_bulk (ssm); capsm_fire_bulk (ssm, _dev);
break; break;
case CAPSM_1001_WRITEV_1: 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; break;
case CAPSM_1001_WRITEV_2: 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; break;
case CAPSM_1001_WRITEV_3: 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; break;
case CAPSM_1001_WRITEV_4: 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; break;
case CAPSM_1001_WRITEV_5: 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; break;
} }
} }
@@ -994,29 +983,29 @@ enum deinitsm_1001_states {
DEINITSM_1001_NUM_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)) { switch (fpi_ssm_get_cur_state(ssm)) {
case DEINITSM_2016_WRITEV: 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; 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)) { switch (fpi_ssm_get_cur_state(ssm)) {
case DEINITSM_1000_WRITEV: 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; 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)) { switch (fpi_ssm_get_cur_state(ssm)) {
case DEINITSM_1001_WRITEV: 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; break;
} }
} }
@@ -1048,62 +1037,62 @@ enum initsm_1001_states {
INITSM_1001_NUM_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 fp_img_dev *dev = user_data;
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)) { switch (fpi_ssm_get_cur_state(ssm)) {
case INITSM_2016_WRITEV_1: 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; break;
case INITSM_2016_READ_09: case INITSM_2016_READ_09:
sm_read_reg(ssm, 0x09); sm_read_reg(ssm, dev, 0x09);
break; break;
case INITSM_2016_WRITE_09: 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; break;
case INITSM_2016_READ_13: case INITSM_2016_READ_13:
sm_read_reg(ssm, 0x13); sm_read_reg(ssm, dev, 0x13);
break; break;
case INITSM_2016_WRITE_13: 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; break;
case INITSM_2016_WRITE_04: case INITSM_2016_WRITE_04:
sm_write_reg(ssm, 0x04, 0x00); sm_write_reg(ssm, dev, 0x04, 0x00);
break; break;
case INITSM_2016_WRITE_05: case INITSM_2016_WRITE_05:
sm_write_reg(ssm, 0x05, 0x00); sm_write_reg(ssm, dev, 0x05, 0x00);
break; 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)) { switch (fpi_ssm_get_cur_state(ssm)) {
case INITSM_1000_WRITEV_1: 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; 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)) { switch (fpi_ssm_get_cur_state(ssm)) {
case INITSM_1001_WRITEV_1: 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; break;
case INITSM_1001_WRITEV_2: 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; break;
case INITSM_1001_WRITEV_3: 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; break;
case INITSM_1001_WRITEV_4: 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; break;
case INITSM_1001_WRITEV_5: 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; break;
} }
} }
@@ -1120,10 +1109,10 @@ enum loopsm_states {
LOOPSM_NUM_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 fp_img_dev *dev = user_data;
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)) { switch (fpi_ssm_get_cur_state(ssm)) {
case LOOPSM_RUN_AWFSM: ; case LOOPSM_RUN_AWFSM: ;
@@ -1139,18 +1128,17 @@ static void loopsm_run_state(struct fpi_ssm *ssm)
if (sdev->deactivating) { if (sdev->deactivating) {
fpi_ssm_mark_completed(ssm); fpi_ssm_mark_completed(ssm);
} else { } else {
struct fpi_ssm *awfsm = NULL; fpi_ssm *awfsm = NULL;
switch (sdev->dev_model) { switch (sdev->dev_model) {
case UPEKSONLY_2016: case UPEKSONLY_2016:
awfsm = fpi_ssm_new(fpi_imgdev_get_dev(dev), awfsm_2016_run_state, awfsm = fpi_ssm_new(FP_DEV(dev), awfsm_2016_run_state,
AWFSM_2016_NUM_STATES); AWFSM_2016_NUM_STATES, dev);
break; break;
case UPEKSONLY_1000: case UPEKSONLY_1000:
awfsm = fpi_ssm_new(fpi_imgdev_get_dev(dev), awfsm_1000_run_state, awfsm = fpi_ssm_new(FP_DEV(dev), awfsm_1000_run_state,
AWFSM_1000_NUM_STATES); AWFSM_1000_NUM_STATES, dev);
break; break;
} }
fpi_ssm_set_user_data(awfsm, dev);
fpi_ssm_start_subsm(ssm, awfsm); fpi_ssm_start_subsm(ssm, awfsm);
} }
break; break;
@@ -1162,49 +1150,47 @@ static void loopsm_run_state(struct fpi_ssm *ssm)
fpi_ssm_next_state(ssm); fpi_ssm_next_state(ssm);
break; break;
default: default:
sm_await_intr(ssm); sm_await_intr(ssm, dev);
break; break;
} }
break; break;
case LOOPSM_RUN_CAPSM: ; case LOOPSM_RUN_CAPSM: ;
struct fpi_ssm *capsm = NULL; fpi_ssm *capsm = NULL;
switch (sdev->dev_model) { switch (sdev->dev_model) {
case UPEKSONLY_2016: case UPEKSONLY_2016:
capsm = fpi_ssm_new(fpi_imgdev_get_dev(dev), capsm_2016_run_state, capsm = fpi_ssm_new(FP_DEV(dev), capsm_2016_run_state,
CAPSM_2016_NUM_STATES); CAPSM_2016_NUM_STATES, dev);
break; break;
case UPEKSONLY_1000: case UPEKSONLY_1000:
capsm = fpi_ssm_new(fpi_imgdev_get_dev(dev), capsm_1000_run_state, capsm = fpi_ssm_new(FP_DEV(dev), capsm_1000_run_state,
CAPSM_1000_NUM_STATES); CAPSM_1000_NUM_STATES, dev);
break; break;
case UPEKSONLY_1001: case UPEKSONLY_1001:
capsm = fpi_ssm_new(fpi_imgdev_get_dev(dev), capsm_1001_run_state, capsm = fpi_ssm_new(FP_DEV(dev), capsm_1001_run_state,
CAPSM_1001_NUM_STATES); CAPSM_1001_NUM_STATES, dev);
break; break;
} }
fpi_ssm_set_user_data(capsm, dev);
fpi_ssm_start_subsm(ssm, capsm); fpi_ssm_start_subsm(ssm, capsm);
break; break;
case LOOPSM_CAPTURE: case LOOPSM_CAPTURE:
break; break;
case LOOPSM_RUN_DEINITSM: ; case LOOPSM_RUN_DEINITSM: ;
struct fpi_ssm *deinitsm = NULL; fpi_ssm *deinitsm = NULL;
switch (sdev->dev_model) { switch (sdev->dev_model) {
case UPEKSONLY_2016: case UPEKSONLY_2016:
deinitsm = fpi_ssm_new(fpi_imgdev_get_dev(dev), deinitsm_2016_run_state, deinitsm = fpi_ssm_new(FP_DEV(dev), deinitsm_2016_run_state,
DEINITSM_2016_NUM_STATES); DEINITSM_2016_NUM_STATES, dev);
break; break;
case UPEKSONLY_1000: case UPEKSONLY_1000:
deinitsm = fpi_ssm_new(fpi_imgdev_get_dev(dev), deinitsm_1000_run_state, deinitsm = fpi_ssm_new(FP_DEV(dev), deinitsm_1000_run_state,
DEINITSM_1000_NUM_STATES); DEINITSM_1000_NUM_STATES, dev);
break; break;
case UPEKSONLY_1001: case UPEKSONLY_1001:
deinitsm = fpi_ssm_new(fpi_imgdev_get_dev(dev), deinitsm_1001_run_state, deinitsm = fpi_ssm_new(FP_DEV(dev), deinitsm_1001_run_state,
DEINITSM_1001_NUM_STATES); DEINITSM_1001_NUM_STATES, dev);
break; break;
} }
sdev->capturing = FALSE; sdev->capturing = FALSE;
fpi_ssm_set_user_data(deinitsm, dev);
fpi_ssm_start_subsm(ssm, deinitsm); fpi_ssm_start_subsm(ssm, deinitsm);
break; break;
case LOOPSM_FINAL: 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) 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(); G_DEBUG_HERE();
free_img_transfers(sdev); 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) 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) { if (!sdev->capturing) {
deactivate_done(dev); deactivate_done(dev);
@@ -1248,10 +1234,10 @@ static void dev_deactivate(struct fp_img_dev *dev)
cancel_img_transfers(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 fp_img_dev *dev = user_data;
struct sonly_dev *sdev = fpi_imgdev_get_user_data(dev); struct sonly_dev *sdev = FP_INSTANCE_DATA(_dev);
int r = fpi_ssm_get_error(ssm); int r = fpi_ssm_get_error(ssm);
fpi_ssm_free(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 fp_img_dev *dev = user_data;
struct sonly_dev *sdev = fpi_imgdev_get_user_data(dev); struct sonly_dev *sdev = FP_INSTANCE_DATA(_dev);
int r = fpi_ssm_get_error(ssm); int r = fpi_ssm_get_error(ssm);
fpi_ssm_free(ssm); fpi_ssm_free(ssm);
@@ -1278,15 +1264,14 @@ static void initsm_complete(struct fpi_ssm *ssm)
if (r != 0) if (r != 0)
return; return;
sdev->loopsm = fpi_ssm_new(fpi_imgdev_get_dev(dev), loopsm_run_state, LOOPSM_NUM_STATES); sdev->loopsm = fpi_ssm_new(FP_DEV(dev), loopsm_run_state, LOOPSM_NUM_STATES, dev);
fpi_ssm_set_user_data(sdev->loopsm, dev);
fpi_ssm_start(sdev->loopsm, loopsm_complete); 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, enum fp_imgdev_state state)
{ {
struct sonly_dev *sdev = fpi_imgdev_get_user_data(dev); struct sonly_dev *sdev = FP_INSTANCE_DATA(FP_DEV(dev));
struct fpi_ssm *ssm = NULL; fpi_ssm *ssm = NULL;
int i; int i;
sdev->deactivating = FALSE; 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; sdev->num_flying = 0;
for (i = 0; i < NUM_BULK_TRANSFERS; i++) { for (i = 0; i < NUM_BULK_TRANSFERS; i++) {
unsigned char *data; unsigned char *data;
sdev->img_transfer[i] = libusb_alloc_transfer(0); sdev->img_transfer[i] = fpi_usb_alloc();
if (!sdev->img_transfer[i]) {
free_img_transfers(sdev);
return -ENOMEM;
}
sdev->img_transfer_data[i].idx = i; sdev->img_transfer_data[i].idx = i;
sdev->img_transfer_data[i].dev = dev; sdev->img_transfer_data[i].dev = dev;
data = g_malloc(4096); 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, 0x81, data,
4096, img_data_cb, &sdev->img_transfer_data[i], 0); 4096, img_data_cb, &sdev->img_transfer_data[i], 0);
} }
switch (sdev->dev_model) { switch (sdev->dev_model) {
case UPEKSONLY_2016: 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; break;
case UPEKSONLY_1000: 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; break;
case UPEKSONLY_1001: 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; break;
} }
fpi_ssm_set_user_data(ssm, dev);
fpi_ssm_start(ssm, initsm_complete); fpi_ssm_start(ssm, initsm_complete);
return 0; 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) static void dev_deinit(struct fp_img_dev *dev)
{ {
void *user_data; void *user_data;
user_data = fpi_imgdev_get_user_data(dev); user_data = FP_INSTANCE_DATA(FP_DEV(dev));
g_free(user_data); 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); fpi_imgdev_close_complete(dev);
} }
@@ -1387,20 +1367,20 @@ static int dev_init(struct fp_img_dev *dev, unsigned long driver_data)
int r; int r;
struct sonly_dev *sdev; 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) { if (r < 0) {
fp_err("could not set configuration 1"); fp_err("could not set configuration 1");
return r; 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) { if (r < 0) {
fp_err("could not claim interface 0: %s", libusb_error_name(r)); fp_err("could not claim interface 0: %s", libusb_error_name(r));
return r; return r;
} }
sdev = g_malloc0(sizeof(struct sonly_dev)); 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; sdev->dev_model = (int)driver_data;
switch (driver_data) { switch (driver_data) {
case UPEKSONLY_1000: case UPEKSONLY_1000:

View File

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

View File

@@ -20,6 +20,7 @@
#define FP_COMPONENT "upektc_img" #define FP_COMPONENT "upektc_img"
#include "drivers_api.h" #include "drivers_api.h"
#include "upek_proto.h"
#include "aeslib.h" #include "aeslib.h"
#include "upektc_img.h" #include "upektc_img.h"
@@ -51,50 +52,6 @@ struct upektc_img_dev {
/****** HELPERS ******/ /****** 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) static void upektc_img_cmd_fix_seq(unsigned char *cmd_buf, unsigned char seq)
{ {
uint8_t byte; 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; cmd_buf[size - 1] = (crc & 0xff00) >> 8;
} }
static void upektc_img_submit_req(struct fpi_ssm *ssm, static void
const unsigned char *buf, size_t buf_size, unsigned char seq, upektc_img_submit_req(fpi_ssm *ssm,
libusb_transfer_cb_fn cb) 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 = FP_INSTANCE_DATA(FP_DEV(dev));
struct upektc_img_dev *upekdev = fpi_imgdev_get_user_data(dev); struct libusb_transfer *transfer = fpi_usb_alloc();
struct libusb_transfer *transfer = libusb_alloc_transfer(0);
int r; int r;
BUG_ON(buf_size > MAX_CMD_SIZE); BUG_ON(buf_size > MAX_CMD_SIZE);
if (!transfer) {
fpi_ssm_mark_aborted(ssm, -ENOMEM);
return;
}
transfer->flags |= LIBUSB_TRANSFER_FREE_TRANSFER; transfer->flags |= LIBUSB_TRANSFER_FREE_TRANSFER;
memcpy(upekdev->cmd, buf, buf_size); memcpy(upekdev->cmd, buf, buf_size);
upektc_img_cmd_fix_seq(upekdev->cmd, seq); upektc_img_cmd_fix_seq(upekdev->cmd, seq);
upektc_img_cmd_update_crc(upekdev->cmd, buf_size); 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); cb, ssm, BULK_TIMEOUT);
r = libusb_submit_transfer(transfer); r = libusb_submit_transfer(transfer);
if (r < 0) { if (r < 0) {
libusb_free_transfer(transfer); 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 libusb_transfer *transfer = fpi_usb_alloc();
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm); struct upektc_img_dev *upekdev = FP_INSTANCE_DATA(FP_DEV(dev));
struct upektc_img_dev *upekdev = fpi_imgdev_get_user_data(dev);
int r; int r;
if (!transfer) {
fpi_ssm_mark_aborted(ssm, -ENOMEM);
return;
}
BUG_ON(buf_size > MAX_RESPONSE_SIZE); BUG_ON(buf_size > MAX_RESPONSE_SIZE);
transfer->flags |= LIBUSB_TRANSFER_FREE_TRANSFER; 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); cb, ssm, BULK_TIMEOUT);
r = libusb_submit_transfer(transfer); r = libusb_submit_transfer(transfer);
if (r < 0) { if (r < 0) {
libusb_free_transfer(transfer); 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) 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) || if ((transfer->status != LIBUSB_TRANSFER_COMPLETED) ||
(transfer->length != transfer->actual_length)) { (transfer->length != transfer->actual_length)) {
fpi_ssm_mark_aborted(ssm, -EIO); fpi_ssm_mark_failed(ssm, -EIO);
return; return;
} }
switch (fpi_ssm_get_cur_state(ssm)) { 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) 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 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; unsigned char *data = upekdev->response;
struct fp_img *img; struct fp_img *img;
size_t response_size; size_t response_size;
if (transfer->status != LIBUSB_TRANSFER_COMPLETED) { if (transfer->status != LIBUSB_TRANSFER_COMPLETED) {
fp_dbg("request is not completed, %d", transfer->status); fp_dbg("request is not completed, %d", transfer->status);
fpi_ssm_mark_aborted(ssm, -EIO); fpi_ssm_mark_failed(ssm, -EIO);
return; return;
} }
@@ -334,7 +288,7 @@ static void capture_read_data_cb(struct libusb_transfer *transfer)
break; break;
default: default:
fp_err("Uknown response!\n"); fp_err("Uknown response!\n");
fpi_ssm_mark_aborted(ssm, -EIO); fpi_ssm_mark_failed(ssm, -EIO);
break; break;
} }
break; break;
@@ -343,51 +297,51 @@ static void capture_read_data_cb(struct libusb_transfer *transfer)
break; break;
default: default:
fp_err("Not handled response!\n"); 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 fp_img_dev *dev = user_data;
struct upektc_img_dev *upekdev = fpi_imgdev_get_user_data(dev); struct upektc_img_dev *upekdev = FP_INSTANCE_DATA(_dev);
switch (fpi_ssm_get_cur_state(ssm)) { switch (fpi_ssm_get_cur_state(ssm)) {
case CAPTURE_INIT_CAPTURE: 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, capture_reqs_cb);
upekdev->seq++; upekdev->seq++;
break; break;
case CAPTURE_READ_DATA: case CAPTURE_READ_DATA:
case CAPTURE_READ_DATA_TERM: case CAPTURE_READ_DATA_TERM:
if (!upekdev->response_rest) 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 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); SHORT_RESPONSE_SIZE, capture_read_data_cb);
break; break;
case CAPTURE_ACK_00_28: case CAPTURE_ACK_00_28:
case CAPTURE_ACK_00_28_TERM: 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, capture_reqs_cb);
upekdev->seq++; upekdev->seq++;
break; break;
case CAPTURE_ACK_08: 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); 0, capture_reqs_cb);
break; break;
case CAPTURE_ACK_FRAME: 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, capture_reqs_cb);
upekdev->seq++; upekdev->seq++;
break; 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 fp_img_dev *dev = user_data;
struct upektc_img_dev *upekdev = fpi_imgdev_get_user_data(dev); struct upektc_img_dev *upekdev = FP_INSTANCE_DATA(_dev);
int err = fpi_ssm_get_error(ssm); int err = fpi_ssm_get_error(ssm);
fp_dbg("Capture completed, %d", err); 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) static void start_capture(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));
struct fpi_ssm *ssm; fpi_ssm *ssm;
upekdev->image_size = 0; upekdev->image_size = 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);
fpi_ssm_set_user_data(ssm, dev);
fpi_ssm_start(ssm, capture_sm_complete); fpi_ssm_start(ssm, capture_sm_complete);
} }
@@ -423,49 +376,49 @@ enum deactivate_states {
static void deactivate_reqs_cb(struct libusb_transfer *transfer) 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) && if ((transfer->status == LIBUSB_TRANSFER_COMPLETED) &&
(transfer->length == transfer->actual_length)) { (transfer->length == transfer->actual_length)) {
fpi_ssm_jump_to_state(ssm, CAPTURE_READ_DATA); fpi_ssm_jump_to_state(ssm, CAPTURE_READ_DATA);
} else { } else {
fpi_ssm_mark_aborted(ssm, -EIO); fpi_ssm_mark_failed(ssm, -EIO);
} }
} }
/* TODO: process response properly */ /* TODO: process response properly */
static void deactivate_read_data_cb(struct libusb_transfer *transfer) 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) { if (transfer->status == LIBUSB_TRANSFER_COMPLETED) {
fpi_ssm_mark_completed(ssm); fpi_ssm_mark_completed(ssm);
} else { } 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 fp_img_dev *dev = user_data;
struct upektc_img_dev *upekdev = fpi_imgdev_get_user_data(dev); struct upektc_img_dev *upekdev = FP_INSTANCE_DATA(_dev);
switch (fpi_ssm_get_cur_state(ssm)) { switch (fpi_ssm_get_cur_state(ssm)) {
case DEACTIVATE_DEINIT: 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, deactivate_reqs_cb);
upekdev->seq++; upekdev->seq++;
break; break;
case DEACTIVATE_READ_DEINIT_DATA: 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; 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 fp_img_dev *dev = user_data;
struct upektc_img_dev *upekdev = fpi_imgdev_get_user_data(dev); struct upektc_img_dev *upekdev = FP_INSTANCE_DATA(_dev);
int err = fpi_ssm_get_error(ssm); int err = fpi_ssm_get_error(ssm);
fp_dbg("Deactivate completed"); 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) static void start_deactivation(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));
struct fpi_ssm *ssm; fpi_ssm *ssm;
upekdev->image_size = 0; upekdev->image_size = 0;
ssm = fpi_ssm_new(fpi_imgdev_get_dev(dev), deactivate_run_state, DEACTIVATE_NUM_STATES); ssm = fpi_ssm_new(FP_DEV(dev), deactivate_run_state, DEACTIVATE_NUM_STATES, dev);
fpi_ssm_set_user_data(ssm, dev);
fpi_ssm_start(ssm, deactivate_sm_complete); fpi_ssm_start(ssm, deactivate_sm_complete);
} }
@@ -510,45 +462,44 @@ enum activate_states {
static void init_reqs_ctrl_cb(struct libusb_transfer *transfer) 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) { if (transfer->status == LIBUSB_TRANSFER_COMPLETED) {
fpi_ssm_next_state(ssm); fpi_ssm_next_state(ssm);
} else { } else {
fpi_ssm_mark_aborted(ssm, -EIO); fpi_ssm_mark_failed(ssm, -EIO);
} }
} }
static void init_reqs_cb(struct libusb_transfer *transfer) 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) && if ((transfer->status == LIBUSB_TRANSFER_COMPLETED) &&
(transfer->length == transfer->actual_length)) { (transfer->length == transfer->actual_length)) {
fpi_ssm_next_state(ssm); fpi_ssm_next_state(ssm);
} else { } else {
fpi_ssm_mark_aborted(ssm, -EIO); fpi_ssm_mark_failed(ssm, -EIO);
} }
} }
/* TODO: process response properly */ /* TODO: process response properly */
static void init_read_data_cb(struct libusb_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) { if (transfer->status == LIBUSB_TRANSFER_COMPLETED) {
fpi_ssm_next_state(ssm); fpi_ssm_next_state(ssm);
} else { } 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 libusb_transfer *transfer;
struct fp_img_dev *idev = fpi_ssm_get_user_data(ssm); struct fp_img_dev *idev = user_data;
struct upektc_img_dev *upekdev = fpi_imgdev_get_user_data(idev); struct upektc_img_dev *upekdev = FP_INSTANCE_DATA(dev);
struct fp_dev *dev = fpi_ssm_get_dev(ssm);
int r; int r;
switch (fpi_ssm_get_cur_state(ssm)) { switch (fpi_ssm_get_cur_state(ssm)) {
@@ -557,11 +508,7 @@ static void activate_run_state(struct fpi_ssm *ssm)
{ {
unsigned char *data; unsigned char *data;
transfer = libusb_alloc_transfer(0); transfer = fpi_usb_alloc();
if (!transfer) {
fpi_ssm_mark_aborted(ssm, -ENOMEM);
break;
}
transfer->flags |= LIBUSB_TRANSFER_FREE_BUFFER | transfer->flags |= LIBUSB_TRANSFER_FREE_BUFFER |
LIBUSB_TRANSFER_FREE_TRANSFER; LIBUSB_TRANSFER_FREE_TRANSFER;
@@ -574,24 +521,24 @@ static void activate_run_state(struct fpi_ssm *ssm)
if (r < 0) { if (r < 0) {
g_free(data); g_free(data);
libusb_free_transfer(transfer); libusb_free_transfer(transfer);
fpi_ssm_mark_aborted(ssm, r); fpi_ssm_mark_failed(ssm, r);
} }
} }
break; break;
case ACTIVATE_INIT_1: 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); 0, init_reqs_cb);
break; break;
case ACTIVATE_INIT_2: 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); 0, init_reqs_cb);
break; break;
case ACTIVATE_INIT_3: 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); 0, init_reqs_cb);
break; break;
case ACTIVATE_INIT_4: 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); upekdev->seq, init_reqs_cb);
/* Seq should be updated after 4th init */ /* Seq should be updated after 4th init */
upekdev->seq++; 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_2_RESP:
case ACTIVATE_READ_INIT_3_RESP: case ACTIVATE_READ_INIT_3_RESP:
case ACTIVATE_READ_INIT_4_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; 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); int err = fpi_ssm_get_error(ssm);
fpi_ssm_free(ssm); fpi_ssm_free(ssm);
@@ -622,10 +569,9 @@ static void activate_sm_complete(struct fpi_ssm *ssm)
static int dev_activate(struct fp_img_dev *dev, enum fp_imgdev_state state) static int dev_activate(struct fp_img_dev *dev, enum fp_imgdev_state state)
{ {
struct upektc_img_dev *upekdev = fpi_imgdev_get_user_data(dev); struct upektc_img_dev *upekdev = FP_INSTANCE_DATA(FP_DEV(dev));
struct fpi_ssm *ssm = fpi_ssm_new(fpi_imgdev_get_dev(dev), activate_run_state, fpi_ssm *ssm = fpi_ssm_new(FP_DEV(dev), activate_run_state,
ACTIVATE_NUM_STATES); ACTIVATE_NUM_STATES, dev);
fpi_ssm_set_user_data(ssm, dev);
upekdev->seq = 0; upekdev->seq = 0;
fpi_ssm_start(ssm, activate_sm_complete); fpi_ssm_start(ssm, activate_sm_complete);
return 0; 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) 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; upekdev->deactivating = TRUE;
} }
@@ -644,23 +590,23 @@ static int dev_init(struct fp_img_dev *dev, unsigned long driver_data)
int r; int r;
struct upektc_img_dev *upekdev; 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) { if (r < 0) {
fp_err("could not claim interface 0: %s", libusb_error_name(r)); fp_err("could not claim interface 0: %s", libusb_error_name(r));
return r; return r;
} }
upekdev = g_malloc0(sizeof(struct upektc_img_dev)); 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); fpi_imgdev_open_complete(dev, 0);
return 0; return 0;
} }
static void dev_deinit(struct fp_img_dev *dev) 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); 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); fpi_imgdev_close_complete(dev);
} }

View File

@@ -28,6 +28,8 @@
#define FP_COMPONENT "upekts" #define FP_COMPONENT "upekts"
#include "drivers_api.h" #include "drivers_api.h"
#include "fpi-async.h"
#include "upek_proto.h"
#define EP_IN (1 | LIBUSB_ENDPOINT_IN) #define EP_IN (1 | LIBUSB_ENDPOINT_IN)
#define EP_OUT (2 | LIBUSB_ENDPOINT_OUT) #define EP_OUT (2 | LIBUSB_ENDPOINT_OUT)
@@ -43,49 +45,7 @@ struct upekts_dev {
uint8_t seq; /* FIXME: improve/automate seq handling */ 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 * 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, unsigned char seq_a, unsigned char seq_b, const unsigned char *data,
uint16_t len, libusb_transfer_cb_fn callback, void *user_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; uint16_t crc;
const char *ciao = "Ciao"; 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; size_t urblen = len + 9;
unsigned char *buf; unsigned char *buf;
if (!transfer)
return NULL;
if (!data && len > 0) { if (!data && len > 0) {
fp_err("len>0 but no data?"); fp_err("len>0 but no data?");
return NULL; return NULL;
@@ -178,7 +135,7 @@ static struct libusb_transfer *alloc_send_cmd28_transfer(struct fp_dev *dev,
uint16_t _innerlen = innerlen; uint16_t _innerlen = innerlen;
size_t len = innerlen + 6; size_t len = innerlen + 6;
unsigned char *buf = g_malloc0(len); 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; uint8_t seq = upekdev->seq + CMD_SEQ_INCREMENT;
struct libusb_transfer *ret; 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. */ * to read the remainder. This is handled below. */
if (len > MAX_DATA_IN_READ_BUF) { if (len > MAX_DATA_IN_READ_BUF) {
int needed = 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; int r;
if (!transfer)
goto err;
fp_dbg("didn't fit in buffer, need to extend by %d bytes", needed); fp_dbg("didn't fit in buffer, need to extend by %d bytes", needed);
data = g_realloc((gpointer) data, MSG_READ_BUF_SIZE + 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) static int __read_msg_async(struct read_msg_data *udata)
{ {
unsigned char *buf = g_malloc(MSG_READ_BUF_SIZE); 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; int r;
if (!transfer) {
g_free(buf);
return -ENOMEM;
}
libusb_fill_bulk_transfer(transfer, fpi_dev_get_usb_dev(udata->dev), EP_IN, buf, libusb_fill_bulk_transfer(transfer, fpi_dev_get_usb_dev(udata->dev), EP_IN, buf,
MSG_READ_BUF_SIZE, read_msg_cb, udata, TIMEOUT); MSG_READ_BUF_SIZE, read_msg_cb, udata, TIMEOUT);
r = libusb_submit_transfer(transfer); r = libusb_submit_transfer(transfer);
@@ -525,25 +474,28 @@ enum initsm_states {
INITSM_NUM_STATES, INITSM_NUM_STATES,
}; };
static void initsm_read_msg_response_cb(struct fpi_ssm *ssm, static void
enum read_msg_status status, uint8_t seq, initsm_read_msg_response_cb(fpi_ssm *ssm,
unsigned char expect_subcmd, unsigned char subcmd) 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 = FP_INSTANCE_DATA(dev);
struct upekts_dev *upekdev = fpi_dev_get_user_data(dev);
if (status != READ_MSG_RESPONSE) { if (status != READ_MSG_RESPONSE) {
fp_err("expected response, got %d seq=%x in state %d", status, seq, fp_err("expected response, got %d seq=%x in state %d", status, seq,
fpi_ssm_get_cur_state(ssm)); fpi_ssm_get_cur_state(ssm));
fpi_ssm_mark_aborted(ssm, -1); fpi_ssm_mark_failed(ssm, -1);
} else if (subcmd != expect_subcmd) { } else if (subcmd != expect_subcmd) {
fp_warn("expected response to subcmd 0x%02x, got response to %02x in " fp_warn("expected response to subcmd 0x%02x, got response to %02x in "
"state %d", expect_subcmd, subcmd, fpi_ssm_get_cur_state(ssm)); "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) { } else if (seq != upekdev->seq) {
fp_err("expected response to cmd seq=%02x, got response to %02x " fp_err("expected response to cmd seq=%02x, got response to %02x "
"in state %d", upekdev->seq, seq, fpi_ssm_get_cur_state(ssm)); "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 { } else {
fp_dbg("state %d completed", fpi_ssm_get_cur_state(ssm)); fp_dbg("state %d completed", fpi_ssm_get_cur_state(ssm));
fpi_ssm_next_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, uint8_t seq, unsigned char subcmd, unsigned char *data, size_t data_len,
void *user_data) 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); 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, uint8_t seq, unsigned char subcmd, unsigned char *data, size_t data_len,
void *user_data) 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); 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, uint8_t seq, unsigned char subcmd, unsigned char *data, size_t data_len,
void *user_data) 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); 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, uint8_t seq, unsigned char subcmd, unsigned char *data, size_t data_len,
void *user_data) 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); 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, uint8_t seq, unsigned char subcmd, unsigned char *data, size_t data_len,
void *user_data) 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); 0x06, subcmd);
} }
static void initsm_read_msg_cmd_cb(struct fpi_ssm *ssm, static void
enum read_msg_status status, uint8_t expect_seq, uint8_t seq) 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 = FP_INSTANCE_DATA(dev);
struct upekts_dev *upekdev = fpi_dev_get_user_data(dev);
if (status == READ_MSG_ERROR) { if (status == READ_MSG_ERROR) {
fpi_ssm_mark_aborted(ssm, -1); fpi_ssm_mark_failed(ssm, -1);
return; return;
} else if (status != READ_MSG_CMD) { } else if (status != READ_MSG_CMD) {
fp_err("expected command, got %d seq=%x in state %d", status, seq, fp_err("expected command, got %d seq=%x in state %d", status, seq,
fpi_ssm_get_cur_state(ssm)); fpi_ssm_get_cur_state(ssm));
fpi_ssm_mark_aborted(ssm, -1); fpi_ssm_mark_failed(ssm, -1);
return; return;
} }
upekdev->seq = seq; upekdev->seq = seq;
if (seq != expect_seq) { if (seq != expect_seq) {
fp_err("expected seq=%x, got %x in state %d", expect_seq, seq, fp_err("expected seq=%x, got %x in state %d", expect_seq, seq,
fpi_ssm_get_cur_state(ssm)); fpi_ssm_get_cur_state(ssm));
fpi_ssm_mark_aborted(ssm, -1); fpi_ssm_mark_failed(ssm, -1);
return; 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, uint8_t seq, unsigned char subcmd, unsigned char *data, size_t data_len,
void *user_data) 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, 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, uint8_t seq, unsigned char subcmd, unsigned char *data, size_t data_len,
void *user_data) 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) static void ctrl400_cb(struct libusb_transfer *transfer)
{ {
struct fpi_ssm *ssm = transfer->user_data; fpi_ssm *ssm = transfer->user_data;
/* FIXME check length? */ /* FIXME check length? */
if (transfer->status == LIBUSB_TRANSFER_COMPLETED) if (transfer->status == LIBUSB_TRANSFER_COMPLETED)
fpi_ssm_next_state(ssm); fpi_ssm_next_state(ssm);
else else
fpi_ssm_mark_aborted(ssm, -1); fpi_ssm_mark_failed(ssm, -1);
g_free(transfer->buffer); g_free(transfer->buffer);
libusb_free_transfer(transfer); libusb_free_transfer(transfer);
} }
static void initsm_read_msg_handler(struct fpi_ssm *ssm, static void
read_msg_cb_fn callback) 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) { if (r < 0) {
fp_err("async read msg failed in state %d", fpi_ssm_get_cur_state(ssm)); 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) 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 if (transfer->status == LIBUSB_TRANSFER_COMPLETED
&& transfer->length == transfer->actual_length) { && transfer->length == transfer->actual_length) {
fp_dbg("state %d completed", fpi_ssm_get_cur_state(ssm)); 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 { } else {
fp_err("failed, state=%d rqlength=%d actual_length=%d", fpi_ssm_get_cur_state(ssm), fp_err("failed, state=%d rqlength=%d actual_length=%d", fpi_ssm_get_cur_state(ssm),
transfer->length, transfer->actual_length); transfer->length, transfer->actual_length);
fpi_ssm_mark_aborted(ssm, -1); fpi_ssm_mark_failed(ssm, -1);
} }
libusb_free_transfer(transfer); libusb_free_transfer(transfer);
} }
static void initsm_send_msg28_handler(struct fpi_ssm *ssm, static void
unsigned char subcmd, const unsigned char *data, uint16_t innerlen) 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; struct libusb_transfer *transfer;
int r; int r;
transfer = alloc_send_cmd28_transfer(dev, subcmd, data, innerlen, transfer = alloc_send_cmd28_transfer(dev, subcmd, data, innerlen,
initsm_send_msg_cb, ssm); initsm_send_msg_cb, ssm);
if (!transfer) { if (!transfer) {
fpi_ssm_mark_aborted(ssm, -ENOMEM); fpi_ssm_mark_failed(ssm, -ENOMEM);
return; 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)); fp_err("urb submission failed error %d in state %d", r, fpi_ssm_get_cur_state(ssm));
g_free(transfer->buffer); g_free(transfer->buffer);
libusb_free_transfer(transfer); 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 = FP_INSTANCE_DATA(dev);
struct upekts_dev *upekdev = fpi_dev_get_user_data(dev);
struct libusb_transfer *transfer; struct libusb_transfer *transfer;
int r; int r;
@@ -701,12 +660,7 @@ static void initsm_run_state(struct fpi_ssm *ssm)
case WRITE_CTRL400: ; case WRITE_CTRL400: ;
unsigned char *data; unsigned char *data;
transfer = libusb_alloc_transfer(0); transfer = fpi_usb_alloc();
if (!transfer) {
fpi_ssm_mark_aborted(ssm, -ENOMEM);
break;
}
data = g_malloc(LIBUSB_CONTROL_SETUP_SIZE + 1); data = g_malloc(LIBUSB_CONTROL_SETUP_SIZE + 1);
libusb_fill_control_setup(data, libusb_fill_control_setup(data,
LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE, 0x0c, 0x100, 0x0400, 1); 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) { if (r < 0) {
g_free(data); g_free(data);
libusb_free_transfer(transfer); libusb_free_transfer(transfer);
fpi_ssm_mark_aborted(ssm, r); fpi_ssm_mark_failed(ssm, r);
} }
break; break;
case READ_MSG03: case READ_MSG03:
initsm_read_msg_handler(ssm, read_msg03_cb); initsm_read_msg_handler(ssm, dev, read_msg03_cb);
break; break;
case SEND_RESP03: ; case SEND_RESP03: ;
transfer = alloc_send_cmdresponse_transfer(dev, ++upekdev->seq, transfer = alloc_send_cmdresponse_transfer(dev, ++upekdev->seq,
init_resp03, sizeof(init_resp03), initsm_send_msg_cb, ssm); init_resp03, sizeof(init_resp03), initsm_send_msg_cb, ssm);
if (!transfer) { if (!transfer) {
fpi_ssm_mark_aborted(ssm, -ENOMEM); fpi_ssm_mark_failed(ssm, -ENOMEM);
break; break;
} }
@@ -735,51 +689,52 @@ static void initsm_run_state(struct fpi_ssm *ssm)
if (r < 0) { if (r < 0) {
g_free(transfer->buffer); g_free(transfer->buffer);
libusb_free_transfer(transfer); libusb_free_transfer(transfer);
fpi_ssm_mark_aborted(ssm, r); fpi_ssm_mark_failed(ssm, r);
} }
break; break;
case READ_MSG05: case READ_MSG05:
initsm_read_msg_handler(ssm, read_msg05_cb); initsm_read_msg_handler(ssm, dev, read_msg05_cb);
break; break;
case SEND28_06: ; case SEND28_06: ;
unsigned char dummy28_06 = 0x04; unsigned char dummy28_06 = 0x04;
upekdev->seq = 0xf0; upekdev->seq = 0xf0;
initsm_send_msg28_handler(ssm, 0x06, &dummy28_06, 1); initsm_send_msg28_handler(ssm, dev, 0x06, &dummy28_06, 1);
break; break;
case READ28_06: case READ28_06:
initsm_read_msg_handler(ssm, read28_06_cb); initsm_read_msg_handler(ssm, dev, read28_06_cb);
break; break;
case SEND28_07: ; case SEND28_07: ;
unsigned char dummy28_07 = 0x04; 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; break;
case READ28_07: case READ28_07:
initsm_read_msg_handler(ssm, read28_07_cb); initsm_read_msg_handler(ssm, dev, read28_07_cb);
break; break;
case SEND28_08: 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; break;
case READ28_08: case READ28_08:
initsm_read_msg_handler(ssm, read28_08_cb); initsm_read_msg_handler(ssm, dev, read28_08_cb);
break; break;
case SEND28_0C: 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; break;
case READ28_0C: case READ28_0C:
initsm_read_msg_handler(ssm, read28_0c_cb); initsm_read_msg_handler(ssm, dev, read28_0c_cb);
break; break;
case SEND28_0B: 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; break;
case READ28_0B: case READ28_0B:
initsm_read_msg_handler(ssm, read28_0b_cb); initsm_read_msg_handler(ssm, dev, read28_0b_cb);
break; 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 { enum deinitsm_states {
@@ -790,11 +745,11 @@ enum deinitsm_states {
static void send_resp07_cb(struct libusb_transfer *transfer) 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) if (transfer->status != LIBUSB_TRANSFER_COMPLETED)
fpi_ssm_mark_aborted(ssm, -EIO); fpi_ssm_mark_failed(ssm, -EIO);
else if (transfer->length != transfer->actual_length) else if (transfer->length != transfer->actual_length)
fpi_ssm_mark_aborted(ssm, -EPROTO); fpi_ssm_mark_failed(ssm, -EPROTO);
else else
fpi_ssm_next_state(ssm); fpi_ssm_next_state(ssm);
libusb_free_transfer(transfer); 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, uint8_t seq, unsigned char subcmd, unsigned char *data, size_t data_len,
void *user_data) void *user_data)
{ {
struct fpi_ssm *ssm = user_data; fpi_ssm *ssm = user_data;
struct upekts_dev *upekdev = fpi_dev_get_user_data(dev); struct upekts_dev *upekdev = FP_INSTANCE_DATA(dev);
if (status == READ_MSG_ERROR) { if (status == READ_MSG_ERROR) {
fpi_ssm_mark_aborted(ssm, -1); fpi_ssm_mark_failed(ssm, -1);
return; return;
} else if (status != READ_MSG_CMD) { } else if (status != READ_MSG_CMD) {
fp_err("expected command, got %d seq=%x", status, seq); fp_err("expected command, got %d seq=%x", status, seq);
fpi_ssm_mark_aborted(ssm, -1); fpi_ssm_mark_failed(ssm, -1);
return; return;
} }
upekdev->seq = seq; upekdev->seq = seq;
if (seq != 1) { if (seq != 1) {
fp_err("expected seq=1, got %x", seq); fp_err("expected seq=1, got %x", seq);
fpi_ssm_mark_aborted(ssm, -1); fpi_ssm_mark_failed(ssm, -1);
return; return;
} }
fpi_ssm_next_state(ssm); 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; int r;
switch (fpi_ssm_get_cur_state(ssm)) { 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, transfer = alloc_send_cmdresponse_transfer(dev, 0x07, &dummy, 1,
send_resp07_cb, ssm); send_resp07_cb, ssm);
if (!transfer) { if (!transfer) {
fpi_ssm_mark_aborted(ssm, -ENOMEM); fpi_ssm_mark_failed(ssm, -ENOMEM);
break; break;
} }
@@ -846,20 +800,20 @@ static void deinitsm_state_handler(struct fpi_ssm *ssm)
if (r < 0) { if (r < 0) {
g_free(transfer->buffer); g_free(transfer->buffer);
libusb_free_transfer(transfer); libusb_free_transfer(transfer);
fpi_ssm_mark_aborted(ssm, r); fpi_ssm_mark_failed(ssm, r);
} }
break; break;
case READ_MSG01: ; case READ_MSG01: ;
r = read_msg_async(dev, read_msg01_cb, ssm); r = read_msg_async(dev, read_msg01_cb, ssm);
if (r < 0) if (r < 0)
fpi_ssm_mark_aborted(ssm, r); fpi_ssm_mark_failed(ssm, r);
break; 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) 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 = g_malloc(sizeof(*upekdev));
upekdev->seq = 0xf0; /* incremented to 0x00 before first cmd */ 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_dev_set_nr_enroll_stages(dev, 3);
fpi_drvcb_open_complete(dev, 0); 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) 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); libusb_release_interface(fpi_dev_get_usb_dev(dev), 0);
user_data = fpi_dev_get_user_data(dev); g_free(upekdev);
g_free(user_data);
fpi_drvcb_close_complete(dev); fpi_drvcb_close_complete(dev);
} }
@@ -909,14 +863,14 @@ enum enroll_start_sm_states {
}; };
/* Called when the device initialization state machine completes */ /* 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); int error = fpi_ssm_get_error(initsm);
fpi_ssm_free(initsm); fpi_ssm_free(initsm);
if (error) if (error)
fpi_ssm_mark_aborted(enroll_start_ssm, error); fpi_ssm_mark_failed(enroll_start_ssm, error);
else else
fpi_ssm_next_state(enroll_start_ssm); 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 */ /* called when enroll init URB has completed */
static void enroll_start_sm_cb_init(struct libusb_transfer *transfer) 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) if (transfer->status != LIBUSB_TRANSFER_COMPLETED)
fpi_ssm_mark_aborted(ssm, -EIO); fpi_ssm_mark_failed(ssm, -EIO);
else if (transfer->length != transfer->actual_length) else if (transfer->length != transfer->actual_length)
fpi_ssm_mark_aborted(ssm, -EPROTO); fpi_ssm_mark_failed(ssm, -EPROTO);
else else
fpi_ssm_next_state(ssm); fpi_ssm_next_state(ssm);
libusb_free_transfer(transfer); 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, enum read_msg_status status, uint8_t seq, unsigned char subcmd,
unsigned char *data, size_t data_len, void *user_data) 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);
struct fpi_ssm *ssm = user_data; fpi_ssm *ssm = user_data;
if (status != READ_MSG_RESPONSE) { if (status != READ_MSG_RESPONSE) {
fp_err("expected response, got %d seq=%x", status, seq); 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) { } else if (subcmd != 0) {
fp_warn("expected response to subcmd 0, got response to %02x", fp_warn("expected response to subcmd 0, got response to %02x",
subcmd); subcmd);
fpi_ssm_mark_aborted(ssm, -1); fpi_ssm_mark_failed(ssm, -1);
} else if (seq != upekdev->seq) { } else if (seq != upekdev->seq) {
fp_err("expected response to cmd seq=%02x, got response to %02x", fp_err("expected response to cmd seq=%02x, got response to %02x",
upekdev->seq, seq); upekdev->seq, seq);
fpi_ssm_mark_aborted(ssm, -1); fpi_ssm_mark_failed(ssm, -1);
} else { } else {
fpi_ssm_next_state(ssm); 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; int r;
switch (fpi_ssm_get_cur_state(ssm)) { switch (fpi_ssm_get_cur_state(ssm)) {
case RUN_INITSM: ; case RUN_INITSM: ;
struct fpi_ssm *initsm = initsm_new(dev); fpi_ssm *initsm = initsm_new(dev, ssm);
fpi_ssm_set_user_data(initsm, ssm);
fpi_ssm_start(initsm, enroll_start_sm_cb_initsm); fpi_ssm_start(initsm, enroll_start_sm_cb_initsm);
break; break;
case ENROLL_INIT: ; 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, transfer = alloc_send_cmd28_transfer(dev, 0x02, enroll_init,
sizeof(enroll_init), enroll_start_sm_cb_init, ssm); sizeof(enroll_init), enroll_start_sm_cb_init, ssm);
if (!transfer) { if (!transfer) {
fpi_ssm_mark_aborted(ssm, -ENOMEM); fpi_ssm_mark_failed(ssm, -ENOMEM);
break; break;
} }
@@ -981,7 +933,7 @@ static void enroll_start_sm_run_state(struct fpi_ssm *ssm)
if (r < 0) { if (r < 0) {
g_free(transfer->buffer); g_free(transfer->buffer);
libusb_free_transfer(transfer); libusb_free_transfer(transfer);
fpi_ssm_mark_aborted(ssm, r); fpi_ssm_mark_failed(ssm, r);
} }
break; break;
case READ_ENROLL_MSG28: ; 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? */ * include a 30 01 poll somewhere? */
r = read_msg_async(dev, enroll_start_sm_cb_msg28, ssm); r = read_msg_async(dev, enroll_start_sm_cb_msg28, ssm);
if (r < 0) if (r < 0)
fpi_ssm_mark_aborted(ssm, r); fpi_ssm_mark_failed(ssm, r);
break; 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, static void e_handle_resp00(struct fp_dev *dev, unsigned char *data,
size_t data_len) 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; unsigned char status;
int result = 0; int result = 0;
@@ -1018,6 +970,9 @@ static void e_handle_resp00(struct fp_dev *dev, unsigned char *data,
case 0x0c: case 0x0c:
case 0x0d: case 0x0d:
case 0x0e: case 0x0e:
case 0x26:
case 0x27:
case 0x2e:
/* if we previously completed a non-last enrollment stage, we'll /* if we previously completed a non-last enrollment stage, we'll
* get this code to indicate successful stage completion */ * get this code to indicate successful stage completion */
if (upekdev->enroll_passed) { if (upekdev->enroll_passed) {
@@ -1087,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)); item = fpi_print_data_item_new(data_len - sizeof(scan_comp));
memcpy(item->data, data + sizeof(scan_comp), memcpy(item->data, data + sizeof(scan_comp),
data_len - 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; result = FP_ENROLL_COMPLETE;
} }
@@ -1150,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)); fpi_drvcb_enroll_started(dev, fpi_ssm_get_error(ssm));
if (!fpi_ssm_get_error(ssm)) if (!fpi_ssm_get_error(ssm))
@@ -1163,41 +1117,41 @@ static void enroll_started(struct fpi_ssm *ssm)
static int enroll_start(struct fp_dev *dev) 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 */ /* do_init state machine first */
struct fpi_ssm *ssm = fpi_ssm_new(dev, enroll_start_sm_run_state, fpi_ssm *ssm = fpi_ssm_new(dev, enroll_start_sm_run_state,
ENROLL_START_NUM_STATES); ENROLL_START_NUM_STATES, NULL);
upekdev->enroll_passed = FALSE; upekdev->enroll_passed = FALSE;
fpi_ssm_start(ssm, enroll_started); fpi_ssm_start(ssm, enroll_started);
return 0; 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 */ /* don't really care about errors */
fpi_drvcb_enroll_stopped(fpi_ssm_get_dev(ssm)); fpi_drvcb_enroll_stopped(dev);
fpi_ssm_free(ssm); fpi_ssm_free(ssm);
} }
static int enroll_stop(struct fp_dev *dev) 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); fpi_ssm_start(ssm, enroll_stop_deinit_cb);
return 0; 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 */ /* don't really care about errors */
fpi_drvcb_verify_stopped(fpi_ssm_get_dev(ssm)); fpi_drvcb_verify_stopped(dev);
fpi_ssm_free(ssm); fpi_ssm_free(ssm);
} }
static void do_verify_stop(struct fp_dev *dev) 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); fpi_ssm_start(ssm, verify_stop_deinit_cb);
} }
@@ -1214,14 +1168,14 @@ enum {
}; };
/* Called when the device initialization state machine completes */ /* 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; int err;
err = fpi_ssm_get_error(initsm); err = fpi_ssm_get_error(initsm);
if (err) if (err)
fpi_ssm_mark_aborted(verify_start_ssm, err); fpi_ssm_mark_failed(verify_start_ssm, err);
else else
fpi_ssm_next_state(verify_start_ssm); fpi_ssm_next_state(verify_start_ssm);
fpi_ssm_free(initsm); fpi_ssm_free(initsm);
@@ -1229,30 +1183,28 @@ static void verify_start_sm_cb_initsm(struct fpi_ssm *initsm)
static void verify_init_2803_cb(struct libusb_transfer *transfer) 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) if (transfer->status != LIBUSB_TRANSFER_COMPLETED)
fpi_ssm_mark_aborted(ssm, -EIO); fpi_ssm_mark_failed(ssm, -EIO);
else if (transfer->length != transfer->actual_length) else if (transfer->length != transfer->actual_length)
fpi_ssm_mark_aborted(ssm, -EPROTO); fpi_ssm_mark_failed(ssm, -EPROTO);
else else
fpi_ssm_next_state(ssm); fpi_ssm_next_state(ssm);
libusb_free_transfer(transfer); 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; int r;
switch (fpi_ssm_get_cur_state(ssm)) { switch (fpi_ssm_get_cur_state(ssm)) {
case VERIFY_RUN_INITSM: ; case VERIFY_RUN_INITSM: ;
struct fpi_ssm *initsm = initsm_new(dev); fpi_ssm *initsm = initsm_new(dev, ssm);
fpi_ssm_set_user_data(initsm, ssm);
fpi_ssm_start(initsm, verify_start_sm_cb_initsm); fpi_ssm_start(initsm, verify_start_sm_cb_initsm);
break; break;
case VERIFY_INIT: ; case VERIFY_INIT: ;
struct fp_print_data *print = fpi_dev_get_verify_data(dev); 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; size_t data_len = sizeof(verify_hdr) + item->length;
unsigned char *data = g_malloc(data_len); unsigned char *data = g_malloc(data_len);
struct libusb_transfer *transfer; struct libusb_transfer *transfer;
@@ -1263,7 +1215,7 @@ static void verify_start_sm_run_state(struct fpi_ssm *ssm)
verify_init_2803_cb, ssm); verify_init_2803_cb, ssm);
g_free(data); g_free(data);
if (!transfer) { if (!transfer) {
fpi_ssm_mark_aborted(ssm, -ENOMEM); fpi_ssm_mark_failed(ssm, -ENOMEM);
break; break;
} }
@@ -1271,7 +1223,7 @@ static void verify_start_sm_run_state(struct fpi_ssm *ssm)
if (r < 0) { if (r < 0) {
g_free(transfer->buffer); g_free(transfer->buffer);
libusb_free_transfer(transfer); libusb_free_transfer(transfer);
fpi_ssm_mark_aborted(ssm, -EIO); fpi_ssm_mark_failed(ssm, -EIO);
} }
break; break;
} }
@@ -1357,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, uint8_t seq, unsigned char subcmd, unsigned char *data, size_t data_len,
void *user_data) 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) { if (msgstat != READ_MSG_RESPONSE) {
fp_err("expected response, got %d seq=%x", msgstat, seq); fp_err("expected response, got %d seq=%x", msgstat, seq);
@@ -1396,7 +1348,7 @@ static void verify_wr2800_cb(struct libusb_transfer *transfer)
static void verify_iterate(struct fp_dev *dev) 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) { if (upekdev->stop_verify) {
do_verify_stop(dev); do_verify_stop(dev);
@@ -1429,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 = FP_INSTANCE_DATA(dev);
struct upekts_dev *upekdev = fpi_dev_get_user_data(dev);
fpi_drvcb_verify_started(dev, fpi_ssm_get_error(ssm)); fpi_drvcb_verify_started(dev, fpi_ssm_get_error(ssm));
if (!fpi_ssm_get_error(ssm)) { if (!fpi_ssm_get_error(ssm)) {
@@ -1445,9 +1396,9 @@ static void verify_started(struct fpi_ssm *ssm)
static int verify_start(struct fp_dev *dev) static int verify_start(struct fp_dev *dev)
{ {
struct upekts_dev *upekdev = fpi_dev_get_user_data(dev); struct upekts_dev *upekdev = FP_INSTANCE_DATA(dev);
struct fpi_ssm *ssm = fpi_ssm_new(dev, verify_start_sm_run_state, fpi_ssm *ssm = fpi_ssm_new(dev, verify_start_sm_run_state,
VERIFY_NUM_STATES); VERIFY_NUM_STATES, NULL);
upekdev->stop_verify = FALSE; upekdev->stop_verify = FALSE;
fpi_ssm_start(ssm, verify_started); fpi_ssm_start(ssm, verify_started);
return 0; return 0;
@@ -1455,7 +1406,7 @@ static int verify_start(struct fp_dev *dev)
static int verify_stop(struct fp_dev *dev, gboolean iterating) 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) if (!iterating)
do_verify_stop(dev); do_verify_stop(dev);

View File

@@ -120,9 +120,10 @@ struct uru4k_dev {
unsigned char last_reg_rd[16]; unsigned char last_reg_rd[16];
unsigned char last_hwstat; unsigned char last_hwstat;
struct libusb_transfer *irq_transfer; fpi_usb_transfer *irq_transfer;
struct libusb_transfer *img_transfer; fpi_usb_transfer *img_transfer;
void *img_data; void *img_data;
int img_data_actual_length;
uint16_t img_lines_done, img_block; uint16_t img_lines_done, img_block;
uint32_t img_enc_seed; uint32_t img_enc_seed;
@@ -135,7 +136,7 @@ struct uru4k_dev {
unsigned char powerup_hwstat; unsigned char powerup_hwstat;
int scanpwr_irq_timeouts; int scanpwr_irq_timeouts;
struct fpi_timeout *scanpwr_irq_timeout; fpi_timeout *scanpwr_irq_timeout;
int fwfixer_offset; int fwfixer_offset;
unsigned char fwfixer_value; unsigned char fwfixer_value;
@@ -186,13 +187,10 @@ static int write_regs(struct fp_img_dev *dev, uint16_t first_reg,
void *user_data) void *user_data)
{ {
struct write_regs_data *wrdata; struct write_regs_data *wrdata;
struct libusb_transfer *transfer = libusb_alloc_transfer(0); struct libusb_transfer *transfer = fpi_usb_alloc();
unsigned char *data; unsigned char *data;
int r; int r;
if (!transfer)
return -ENOMEM;
wrdata = g_malloc(sizeof(*wrdata)); wrdata = g_malloc(sizeof(*wrdata));
wrdata->dev = dev; wrdata->dev = dev;
wrdata->callback = callback; 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); data = g_malloc(LIBUSB_CONTROL_SETUP_SIZE + num_regs);
memcpy(data + LIBUSB_CONTROL_SETUP_SIZE, values, 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_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); wrdata, CTRL_TIMEOUT);
r = libusb_submit_transfer(transfer); 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) uint16_t num_regs, read_regs_cb_fn callback, void *user_data)
{ {
struct read_regs_data *rrdata; struct read_regs_data *rrdata;
struct libusb_transfer *transfer = libusb_alloc_transfer(0); struct libusb_transfer *transfer = fpi_usb_alloc();
unsigned char *data; unsigned char *data;
int r; int r;
if (!transfer)
return -ENOMEM;
rrdata = g_malloc(sizeof(*rrdata)); rrdata = g_malloc(sizeof(*rrdata));
rrdata->dev = dev; rrdata->dev = dev;
rrdata->callback = callback; 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); 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_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); rrdata, CTRL_TIMEOUT);
r = libusb_submit_transfer(transfer); 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 * BIT 1: IRQ PENDING
* Just had a brainwave. This bit is set when the device is trying to deliver * 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) 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) if (status == 0)
fpi_ssm_next_state(ssm); fpi_ssm_next_state(ssm);
else else
fpi_ssm_mark_aborted(ssm, status); fpi_ssm_mark_failed(ssm, status);
} }
static void challenge_cb(struct fp_img_dev *dev, int status, static void challenge_cb(struct fp_img_dev *dev, int status,
uint16_t num_regs, unsigned char *data, void *user_data) uint16_t num_regs, unsigned char *data, void *user_data)
{ {
struct fpi_ssm *ssm = user_data; fpi_ssm *ssm = user_data;
struct uru4k_dev *urudev = fpi_imgdev_get_user_data(dev); struct uru4k_dev *urudev = FP_INSTANCE_DATA(FP_DEV(dev));
unsigned char *respdata; unsigned char *respdata;
PK11Context *ctx; PK11Context *ctx;
int r, outlen; int r, outlen;
r = status; r = status;
if (status != 0) { if (status != 0) {
fpi_ssm_mark_aborted(ssm, status); fpi_ssm_mark_failed(ssm, status);
return; return;
} }
@@ -346,7 +341,7 @@ static void challenge_cb(struct fp_img_dev *dev, int status,
g_free(respdata); g_free(respdata);
} }
if (r < 0) 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 * authentication scheme, where the device challenges the authenticity of the
* driver. * 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; int r;
G_DEBUG_HERE(); G_DEBUG_HERE();
r = read_regs(dev, REG_CHALLENGE, CR_LENGTH, challenge_cb, ssm); r = read_regs(dev, REG_CHALLENGE, CR_LENGTH, challenge_cb, ssm);
if (r < 0) if (r < 0)
fpi_ssm_mark_aborted(ssm, r); fpi_ssm_mark_failed(ssm, r);
} }
/***** INTERRUPT HANDLING *****/ /***** 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 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 fp_img_dev *dev = FP_IMG_DEV(_dev);
struct uru4k_dev *urudev = fpi_imgdev_get_user_data(dev); struct uru4k_dev *urudev = FP_INSTANCE_DATA(_dev);
unsigned char *data = transfer->buffer; unsigned char *data = transfer->buffer;
uint16_t type; uint16_t type;
int r = 0; int r = 0;
@@ -396,8 +395,6 @@ static void irq_handler(struct libusb_transfer *transfer)
type = GUINT16_FROM_BE(*((uint16_t *) data)); type = GUINT16_FROM_BE(*((uint16_t *) data));
fp_dbg("recv irq type %04x", type); 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) /* The 0800 interrupt seems to indicate imminent failure (0 bytes transfer)
* of the next scan. It still appears on occasion. */ * of the next scan. It still appears on occasion. */
@@ -413,47 +410,43 @@ static void irq_handler(struct libusb_transfer *transfer)
if (r == 0) if (r == 0)
return; return;
transfer = NULL;
data = NULL;
err: err:
if (urudev->irq_cb) if (urudev->irq_cb)
urudev->irq_cb(dev, r, 0, urudev->irq_cb_data); urudev->irq_cb(dev, r, 0, urudev->irq_cb_data);
out: out:
g_free(data);
libusb_free_transfer(transfer);
urudev->irq_transfer = NULL; urudev->irq_transfer = NULL;
} }
static int start_irq_handler(struct fp_img_dev *dev) static int start_irq_handler(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));
struct libusb_transfer *transfer = libusb_alloc_transfer(0); fpi_usb_transfer *transfer;
unsigned char *data; unsigned char *data;
int r; int r;
if (!transfer)
return -ENOMEM;
data = g_malloc(IRQ_LENGTH); data = g_malloc(IRQ_LENGTH);
libusb_fill_bulk_transfer(transfer, fpi_imgdev_get_usb_dev(dev), EP_INTR, data, IRQ_LENGTH, transfer = fpi_usb_fill_bulk_transfer(FP_DEV(dev),
irq_handler, dev, 0); NULL,
EP_INTR,
data,
IRQ_LENGTH,
irq_handler,
NULL,
0);
urudev->irq_transfer = transfer; urudev->irq_transfer = transfer;
r = libusb_submit_transfer(transfer); r = fpi_usb_submit_transfer(transfer);
if (r < 0) { if (r < 0)
g_free(data);
libusb_free_transfer(transfer);
urudev->irq_transfer = NULL; urudev->irq_transfer = NULL;
}
return r; return r;
} }
static void stop_irq_handler(struct fp_img_dev *dev, irqs_stopped_cb_fn cb) 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 uru4k_dev *urudev = FP_INSTANCE_DATA(FP_DEV(dev));
struct libusb_transfer *transfer = urudev->irq_transfer; fpi_usb_transfer *transfer = urudev->irq_transfer;
if (transfer) { if (transfer) {
libusb_cancel_transfer(transfer); fpi_usb_cancel_transfer(transfer);
urudev->irqs_stopped_cb = cb; 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) 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) { switch (state) {
case IMGDEV_STATE_INACTIVE: 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) 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) if (result)
fpi_ssm_mark_aborted(ssm, result); fpi_ssm_mark_failed(ssm, result);
else else
fpi_ssm_next_state(ssm); fpi_ssm_next_state(ssm);
} }
static void sm_write_regs(struct fpi_ssm *ssm, uint16_t first_reg, uint16_t num_regs, static void
void *data) 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); int r = write_regs(dev, first_reg, num_regs, data, sm_write_reg_cb, ssm);
if (r < 0) 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, static void
unsigned char value) 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, static void sm_read_reg_cb(struct fp_img_dev *dev, int result,
uint16_t num_regs, unsigned char *data, void *user_data) uint16_t num_regs, unsigned char *data, void *user_data)
{ {
struct fpi_ssm *ssm = user_data; fpi_ssm *ssm = user_data;
struct uru4k_dev *urudev = fpi_imgdev_get_user_data(dev); struct uru4k_dev *urudev = FP_INSTANCE_DATA(FP_DEV(dev));
if (result) { if (result) {
fpi_ssm_mark_aborted(ssm, result); fpi_ssm_mark_failed(ssm, result);
} else { } else {
memcpy(urudev->last_reg_rd, data, num_regs); memcpy(urudev->last_reg_rd, data, num_regs);
fp_dbg("reg value %x", urudev->last_reg_rd[0]); 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; int r;
if (num_regs > sizeof(urudev->last_reg_rd)) { if (num_regs > member_size(struct uru4k_dev, last_reg_rd)) {
fpi_ssm_mark_aborted(ssm, -EIO); fpi_ssm_mark_failed(ssm, -EIO);
return; return;
} }
fp_dbg("read %d regs at %x", num_regs, reg); fp_dbg("read %d regs at %x", num_regs, reg);
r = read_regs(dev, reg, num_regs, sm_read_reg_cb, ssm); r = read_regs(dev, reg, num_regs, sm_read_reg_cb, ssm);
if (r < 0) 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); fp_dbg("set %02x", value);
sm_write_reg(ssm, REG_HWSTAT, value); sm_write_reg(ssm, dev, REG_HWSTAT, value);
} }
/***** IMAGING LOOP *****/ /***** IMAGING LOOP *****/
@@ -585,28 +594,6 @@ enum imaging_states {
IMAGING_NUM_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 { struct uru4k_image {
uint8_t unknown_00[4]; uint8_t unknown_00[4];
uint16_t num_lines; uint16_t num_lines;
@@ -620,6 +607,33 @@ struct uru4k_image {
uint8_t data[IMAGE_HEIGHT][IMAGE_WIDTH]; 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) static uint32_t update_key(uint32_t key)
{ {
/* linear feedback shift register /* linear feedback shift register
@@ -687,35 +701,35 @@ static int calc_dev2(struct uru4k_image *img)
return res / IMAGE_WIDTH; 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 fp_img_dev *dev = user_data;
struct uru4k_dev *urudev = fpi_imgdev_get_user_data(dev); struct uru4k_dev *urudev = FP_INSTANCE_DATA(_dev);
struct uru4k_image *img = urudev->img_data; struct uru4k_image *img = urudev->img_data;
struct fp_img *fpimg; struct fp_img *fpimg;
uint32_t key; uint32_t key;
uint8_t flags, num_lines; uint8_t flags, num_lines;
int i, r, to, dev2; int i, r, to, dev2;
char buf[5]; unsigned char buf[5];
switch (fpi_ssm_get_cur_state(ssm)) { switch (fpi_ssm_get_cur_state(ssm)) {
case IMAGING_CAPTURE: case IMAGING_CAPTURE:
urudev->img_lines_done = 0; urudev->img_lines_done = 0;
urudev->img_block = 0; urudev->img_block = 0;
libusb_fill_bulk_transfer(urudev->img_transfer, fpi_imgdev_get_usb_dev(dev), EP_DATA, r = fpi_usb_submit_transfer(urudev->img_transfer);
urudev->img_data, sizeof(struct uru4k_image), image_transfer_cb, ssm, 0); if (r < 0) {
r = libusb_submit_transfer(urudev->img_transfer); urudev->img_transfer = NULL;
if (r < 0) fpi_ssm_mark_failed(ssm, -EIO);
fpi_ssm_mark_aborted(ssm, -EIO); }
break; break;
case IMAGING_SEND_INDEX: case IMAGING_SEND_INDEX:
fp_dbg("hw header lines %d", img->num_lines); fp_dbg("hw header lines %d", img->num_lines);
if (img->num_lines >= IMAGE_HEIGHT || 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", fp_err("bad captured image (%d lines) or size mismatch %d < %d",
img->num_lines, img->num_lines,
urudev->img_transfer->actual_length, urudev->img_data_actual_length,
img->num_lines * IMAGE_WIDTH + 64); img->num_lines * IMAGE_WIDTH + 64);
fpi_ssm_jump_to_state(ssm, IMAGING_CAPTURE); fpi_ssm_jump_to_state(ssm, IMAGING_CAPTURE);
return; return;
@@ -734,10 +748,10 @@ static void imaging_run_state(struct fpi_ssm *ssm)
buf[2] = urudev->img_enc_seed >> 8; buf[2] = urudev->img_enc_seed >> 8;
buf[3] = urudev->img_enc_seed >> 16; buf[3] = urudev->img_enc_seed >> 16;
buf[4] = urudev->img_enc_seed >> 24; 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; break;
case IMAGING_READ_KEY: case IMAGING_READ_KEY:
sm_read_regs(ssm, REG_SCRAMBLE_DATA_KEY, 4); sm_read_regs(ssm, dev, REG_SCRAMBLE_DATA_KEY, 4);
break; break;
case IMAGING_DECODE: case IMAGING_DECODE:
key = urudev->last_reg_rd[0]; 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 fp_img_dev *dev = user_data;
struct uru4k_dev *urudev = fpi_imgdev_get_user_data(dev); struct uru4k_dev *urudev = FP_INSTANCE_DATA(_dev);
int r = fpi_ssm_get_error(ssm); int r = fpi_ssm_get_error(ssm);
fpi_ssm_free(ssm); fpi_ssm_free(ssm);
@@ -823,11 +837,12 @@ static void imaging_complete(struct fpi_ssm *ssm)
if (r) if (r)
fpi_imgdev_session_error(dev, r); fpi_imgdev_session_error(dev, r);
/* Freed by callback or cancellation */
urudev->img_transfer = NULL;
g_free(urudev->img_data); g_free(urudev->img_data);
urudev->img_data = NULL; urudev->img_data = NULL;
urudev->img_data_actual_length = 0;
libusb_free_transfer(urudev->img_transfer);
urudev->img_transfer = NULL;
r = execute_state_change(dev); r = execute_state_change(dev);
if (r) 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 * 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 * 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 * 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 * 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 * right after reading the 0x85 hwstat, allowing some time to pass before it
@@ -860,32 +875,33 @@ enum rebootpwr_states {
REBOOTPWR_NUM_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; fpi_ssm *ssm = data;
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm); struct uru4k_dev *urudev = FP_INSTANCE_DATA(dev);
struct uru4k_dev *urudev = fpi_imgdev_get_user_data(dev);
if (!--urudev->rebootpwr_ctr) { if (!--urudev->rebootpwr_ctr) {
fp_err("could not reboot device power"); fp_err("could not reboot device power");
fpi_ssm_mark_aborted(ssm, -EIO); fpi_ssm_mark_failed(ssm, -EIO);
} else { } else {
fpi_ssm_jump_to_state(ssm, REBOOTPWR_GET_HWSTAT); 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 fp_img_dev *dev = user_data;
struct uru4k_dev *urudev = fpi_imgdev_get_user_data(dev); struct uru4k_dev *urudev = FP_INSTANCE_DATA(_dev);
switch (fpi_ssm_get_cur_state(ssm)) { switch (fpi_ssm_get_cur_state(ssm)) {
case REBOOTPWR_SET_HWSTAT: case REBOOTPWR_SET_HWSTAT:
urudev->rebootpwr_ctr = 100; urudev->rebootpwr_ctr = 100;
sm_set_hwstat(ssm, urudev->last_hwstat & 0xf); sm_set_hwstat(ssm, dev, urudev->last_hwstat & 0xf);
break; break;
case REBOOTPWR_GET_HWSTAT: case REBOOTPWR_GET_HWSTAT:
sm_read_reg(ssm, REG_HWSTAT); sm_read_reg(ssm, dev, REG_HWSTAT);
break; break;
case REBOOTPWR_CHECK_HWSTAT: case REBOOTPWR_CHECK_HWSTAT:
urudev->last_hwstat = urudev->last_reg_rd[0]; 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); fpi_ssm_next_state(ssm);
break; break;
case REBOOTPWR_PAUSE: case REBOOTPWR_PAUSE:
if (fpi_timeout_add(10, rebootpwr_pause_cb, ssm) == NULL) if (fpi_timeout_add(10, rebootpwr_pause_cb, _dev, ssm) == NULL)
fpi_ssm_mark_aborted(ssm, -ETIME); fpi_ssm_mark_failed(ssm, -ETIME);
break; 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 * 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 * 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, * for the hwstat write not to take effect. We have to loop a few times,
* authenticating each time, until the device wakes up. * authenticating each time, until the device wakes up.
* *
@@ -937,15 +953,16 @@ enum powerup_states {
POWERUP_NUM_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; fpi_ssm *ssm = data;
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm); struct uru4k_dev *urudev = FP_INSTANCE_DATA(dev);
struct uru4k_dev *urudev = fpi_imgdev_get_user_data(dev);
if (!--urudev->powerup_ctr) { if (!--urudev->powerup_ctr) {
fp_err("could not power device up"); 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) { } else if (!urudev->profile->auth_cr) {
fpi_ssm_jump_to_state(ssm, POWERUP_SET_HWSTAT); fpi_ssm_jump_to_state(ssm, POWERUP_SET_HWSTAT);
} else { } 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 fp_img_dev *dev = user_data;
struct uru4k_dev *urudev = fpi_imgdev_get_user_data(dev); struct uru4k_dev *urudev = FP_INSTANCE_DATA(_dev);
switch (fpi_ssm_get_cur_state(ssm)) { switch (fpi_ssm_get_cur_state(ssm)) {
case POWERUP_INIT: case POWERUP_INIT:
@@ -965,10 +982,10 @@ static void powerup_run_state(struct fpi_ssm *ssm)
fpi_ssm_next_state(ssm); fpi_ssm_next_state(ssm);
break; break;
case POWERUP_SET_HWSTAT: case POWERUP_SET_HWSTAT:
sm_set_hwstat(ssm, urudev->powerup_hwstat); sm_set_hwstat(ssm, dev, urudev->powerup_hwstat);
break; break;
case POWERUP_GET_HWSTAT: case POWERUP_GET_HWSTAT:
sm_read_reg(ssm, REG_HWSTAT); sm_read_reg(ssm, dev, REG_HWSTAT);
break; break;
case POWERUP_CHECK_HWSTAT: case POWERUP_CHECK_HWSTAT:
urudev->last_hwstat = urudev->last_reg_rd[0]; 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); fpi_ssm_next_state(ssm);
break; break;
case POWERUP_PAUSE: case POWERUP_PAUSE:
if (fpi_timeout_add(10, powerup_pause_cb, ssm) == NULL) if (fpi_timeout_add(10, powerup_pause_cb, _dev, ssm) == NULL)
fpi_ssm_mark_aborted(ssm, -ETIME); fpi_ssm_mark_failed(ssm, -ETIME);
break; break;
case POWERUP_CHALLENGE_RESPONSE: case POWERUP_CHALLENGE_RESPONSE:
sm_do_challenge_response(ssm); sm_do_challenge_response(ssm, dev);
break; break;
case POWERUP_CHALLENGE_RESPONSE_SUCCESS: case POWERUP_CHALLENGE_RESPONSE_SUCCESS:
fpi_ssm_jump_to_state(ssm, POWERUP_SET_HWSTAT); 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, static void init_scanpwr_irq_cb(struct fp_img_dev *dev, int status,
uint16_t type, void *user_data) uint16_t type, void *user_data)
{ {
struct fpi_ssm *ssm = user_data; fpi_ssm *ssm = user_data;
struct uru4k_dev *urudev = fpi_imgdev_get_user_data(dev); struct uru4k_dev *urudev = FP_INSTANCE_DATA(FP_DEV(dev));
if (status) if (status)
fpi_ssm_mark_aborted(ssm, status); fpi_ssm_mark_failed(ssm, status);
else if (type != IRQDATA_SCANPWR_ON) else if (type != IRQDATA_SCANPWR_ON)
fp_dbg("ignoring interrupt"); fp_dbg("ignoring interrupt");
else if (fpi_ssm_get_cur_state(ssm) != INIT_AWAIT_SCAN_POWER) { 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; fpi_ssm *ssm = user_data;
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm); struct uru4k_dev *urudev = FP_INSTANCE_DATA(dev);
struct uru4k_dev *urudev = fpi_imgdev_get_user_data(dev);
fp_warn("powerup timed out"); fp_warn("powerup timed out");
urudev->irq_cb = NULL; urudev->irq_cb = NULL;
@@ -1052,20 +1070,20 @@ static void init_scanpwr_timeout(void *user_data)
if (++urudev->scanpwr_irq_timeouts >= 3) { if (++urudev->scanpwr_irq_timeouts >= 3) {
fp_err("powerup timed out 3 times, giving up"); fp_err("powerup timed out 3 times, giving up");
fpi_ssm_mark_aborted(ssm, -ETIMEDOUT); fpi_ssm_mark_failed(ssm, -ETIMEDOUT);
} else { } else {
fpi_ssm_jump_to_state(ssm, INIT_GET_HWSTAT); 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 fp_img_dev *dev = user_data;
struct uru4k_dev *urudev = fpi_imgdev_get_user_data(dev); struct uru4k_dev *urudev = FP_INSTANCE_DATA(_dev);
switch (fpi_ssm_get_cur_state(ssm)) { switch (fpi_ssm_get_cur_state(ssm)) {
case INIT_GET_HWSTAT: case INIT_GET_HWSTAT:
sm_read_reg(ssm, REG_HWSTAT); sm_read_reg(ssm, dev, REG_HWSTAT);
break; break;
case INIT_CHECK_HWSTAT_REBOOT: case INIT_CHECK_HWSTAT_REBOOT:
urudev->last_hwstat = urudev->last_reg_rd[0]; 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); fpi_ssm_jump_to_state(ssm, INIT_CHECK_HWSTAT_POWERDOWN);
break; break;
case INIT_REBOOT_POWER: ; case INIT_REBOOT_POWER: ;
struct fpi_ssm *rebootsm = fpi_ssm_new(fpi_imgdev_get_dev(dev), rebootpwr_run_state, fpi_ssm *rebootsm = fpi_ssm_new(FP_DEV(dev), rebootpwr_run_state,
REBOOTPWR_NUM_STATES); REBOOTPWR_NUM_STATES, dev);
fpi_ssm_set_user_data(rebootsm, dev);
fpi_ssm_start_subsm(ssm, rebootsm); fpi_ssm_start_subsm(ssm, rebootsm);
break; break;
case INIT_CHECK_HWSTAT_POWERDOWN: case INIT_CHECK_HWSTAT_POWERDOWN:
if ((urudev->last_hwstat & 0x80) == 0) if ((urudev->last_hwstat & 0x80) == 0)
sm_set_hwstat(ssm, urudev->last_hwstat | 0x80); sm_set_hwstat(ssm, dev, urudev->last_hwstat | 0x80);
else else
fpi_ssm_next_state(ssm); fpi_ssm_next_state(ssm);
break; break;
case INIT_POWERUP: ; case INIT_POWERUP: ;
if (!IRQ_HANDLER_IS_RUNNING(urudev)) { if (!IRQ_HANDLER_IS_RUNNING(urudev)) {
fpi_ssm_mark_aborted(ssm, -EIO); fpi_ssm_mark_failed(ssm, -EIO);
break; break;
} }
urudev->irq_cb_data = ssm; urudev->irq_cb_data = ssm;
urudev->irq_cb = init_scanpwr_irq_cb; urudev->irq_cb = init_scanpwr_irq_cb;
struct fpi_ssm *powerupsm = fpi_ssm_new(fpi_imgdev_get_dev(dev), powerup_run_state, fpi_ssm *powerupsm = fpi_ssm_new(FP_DEV(dev), powerup_run_state,
POWERUP_NUM_STATES); POWERUP_NUM_STATES, dev);
fpi_ssm_set_user_data(powerupsm, dev);
fpi_ssm_start_subsm(ssm, powerupsm); fpi_ssm_start_subsm(ssm, powerupsm);
break; break;
case INIT_AWAIT_SCAN_POWER: 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 * so we include this timeout loop to retry the whole process 3 times
* if we don't get an irq any time soon. */ * if we don't get an irq any time soon. */
urudev->scanpwr_irq_timeout = fpi_timeout_add(300, urudev->scanpwr_irq_timeout = fpi_timeout_add(300,
init_scanpwr_timeout, ssm); init_scanpwr_timeout,
_dev, ssm);
if (!urudev->scanpwr_irq_timeout) { if (!urudev->scanpwr_irq_timeout) {
fpi_ssm_mark_aborted(ssm, -ETIME); fpi_ssm_mark_failed(ssm, -ETIME);
break; break;
} }
break; break;
@@ -1125,7 +1142,7 @@ static void init_run_state(struct fpi_ssm *ssm)
fpi_ssm_next_state(ssm); fpi_ssm_next_state(ssm);
break; break;
case INIT_GET_VERSION: case INIT_GET_VERSION:
sm_read_regs(ssm, REG_DEVICE_INFO, 16); sm_read_regs(ssm, dev, REG_DEVICE_INFO, 16);
break; break;
case INIT_REPORT_VERSION: case INIT_REPORT_VERSION:
/* Likely hardware revision, and firmware version. /* Likely hardware revision, and firmware version.
@@ -1138,9 +1155,9 @@ 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); int r = fpi_ssm_get_error(ssm);
fpi_ssm_free(ssm); fpi_ssm_free(ssm);
@@ -1159,8 +1176,8 @@ static void activate_initsm_complete(struct fpi_ssm *ssm)
* call. */ * call. */
static int dev_activate(struct fp_img_dev *dev, enum fp_imgdev_state state) static int dev_activate(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));
struct fpi_ssm *ssm; fpi_ssm *ssm;
int r; int r;
r = start_irq_handler(dev); r = start_irq_handler(dev);
@@ -1169,8 +1186,7 @@ static int dev_activate(struct fp_img_dev *dev, enum fp_imgdev_state state)
urudev->scanpwr_irq_timeouts = 0; urudev->scanpwr_irq_timeouts = 0;
urudev->activate_state = state; urudev->activate_state = state;
ssm = fpi_ssm_new(fpi_imgdev_get_dev(dev), init_run_state, INIT_NUM_STATES); ssm = fpi_ssm_new(FP_DEV(dev), init_run_state, INIT_NUM_STATES, dev);
fpi_ssm_set_user_data(ssm, dev);
fpi_ssm_start(ssm, activate_initsm_complete); fpi_ssm_start(ssm, activate_initsm_complete);
return 0; return 0;
} }
@@ -1195,8 +1211,9 @@ static void dev_deactivate(struct fp_img_dev *dev)
static int execute_state_change(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 uru4k_dev *urudev = FP_INSTANCE_DATA(FP_DEV(dev));
struct fpi_ssm *ssm; fpi_ssm *ssm;
void *img_data;
switch (urudev->activate_state) { switch (urudev->activate_state) {
case IMGDEV_STATE_INACTIVE: case IMGDEV_STATE_INACTIVE:
@@ -1219,12 +1236,18 @@ static int execute_state_change(struct fp_img_dev *dev)
fp_dbg("starting capture"); fp_dbg("starting capture");
urudev->irq_cb = NULL; urudev->irq_cb = NULL;
urudev->img_transfer = libusb_alloc_transfer(0); ssm = fpi_ssm_new(FP_DEV(dev), imaging_run_state, IMAGING_NUM_STATES, dev);
urudev->img_data = g_malloc(sizeof(struct uru4k_image)); img_data = g_malloc(sizeof(struct uru4k_image));
urudev->img_enc_seed = rand(); 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); fpi_ssm_start(ssm, imaging_complete);
return write_reg(dev, REG_MODE, MODE_CAPTURE, return write_reg(dev, REG_MODE, MODE_CAPTURE,
@@ -1257,7 +1280,7 @@ static int dev_init(struct fp_img_dev *dev, unsigned long driver_data)
int r; int r;
/* Find fingerprint interface */ /* 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) { if (r < 0) {
fp_err("Failed to get config descriptor"); fp_err("Failed to get config descriptor");
return r; return r;
@@ -1311,12 +1334,15 @@ static int dev_init(struct fp_img_dev *dev, unsigned long driver_data)
/* Device looks like a supported reader */ /* 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) { if (r < 0) {
fp_err("interface claim failed: %s", libusb_error_name(r)); fp_err("interface claim failed: %s", libusb_error_name(r));
goto out; goto out;
} }
/* Disable loading p11-kit's user configuration */
g_setenv ("P11_KIT_NO_USER_CONFIG", "1", TRUE);
/* Initialise NSS early */ /* Initialise NSS early */
rv = NSS_NoDB_Init("."); rv = NSS_NoDB_Init(".");
if (rv != SECSuccess) { if (rv != SECSuccess) {
@@ -1325,6 +1351,8 @@ static int dev_init(struct fp_img_dev *dev, unsigned long driver_data)
} }
urudev = g_malloc0(sizeof(*urudev)); urudev = g_malloc0(sizeof(*urudev));
fp_dev_set_instance_data(FP_DEV(dev), urudev);
urudev->profile = &uru4k_dev_info[driver_data]; urudev->profile = &uru4k_dev_info[driver_data];
urudev->interface = iface_desc->bInterfaceNumber; urudev->interface = iface_desc->bInterfaceNumber;
@@ -1351,7 +1379,6 @@ static int dev_init(struct fp_img_dev *dev, unsigned long driver_data)
} }
urudev->param = PK11_ParamFromIV(urudev->cipher, NULL); urudev->param = PK11_ParamFromIV(urudev->cipher, NULL);
fpi_imgdev_set_user_data(dev, urudev);
fpi_imgdev_open_complete(dev, 0); fpi_imgdev_open_complete(dev, 0);
out: out:
@@ -1361,14 +1388,14 @@ out:
static void dev_deinit(struct fp_img_dev *dev) 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) if (urudev->symkey)
PK11_FreeSymKey (urudev->symkey); PK11_FreeSymKey (urudev->symkey);
if (urudev->param) if (urudev->param)
SECITEM_FreeItem(urudev->param, PR_TRUE); SECITEM_FreeItem(urudev->param, PR_TRUE);
if (urudev->slot) if (urudev->slot)
PK11_FreeSlot(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); g_free(urudev);
fpi_imgdev_close_complete(dev); fpi_imgdev_close_complete(dev);
} }

View File

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

View File

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

View File

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

View File

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

View File

@@ -33,8 +33,8 @@
#include <unistd.h> #include <unistd.h>
#include <stdlib.h> #include <stdlib.h>
#include <glib.h> #include <glib.h>
#include <libusb-1.0/libusb.h>
#include "fpi-usb.h"
#include "vfs301_proto.h" #include "vfs301_proto.h"
#include "vfs301_proto_fragments.h" #include "vfs301_proto_fragments.h"
@@ -499,12 +499,7 @@ void vfs301_proto_process_event_start(
USB_RECV(VFS301_RECEIVE_ENDPOINT_DATA, 64); USB_RECV(VFS301_RECEIVE_ENDPOINT_DATA, 64);
/* now read the fingerprint data, while there are some */ /* now read the fingerprint data, while there are some */
transfer = libusb_alloc_transfer(0); transfer = fpi_usb_alloc();
if (!transfer) {
dev->recv_progress = VFS301_FAILURE;
return;
}
dev->recv_progress = VFS301_ONGOING; dev->recv_progress = VFS301_ONGOING;
dev->recv_exp_amt = VFS301_FP_RECV_LEN_1; 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) 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 usbexchange_data *data = fpi_ssm_get_user_data(ssm);
struct usb_action *action; struct usb_action *action;
if (fpi_ssm_get_cur_state(ssm) >= data->stepcount) { if (fpi_ssm_get_cur_state(ssm) >= data->stepcount) {
fp_err("Radiation detected!"); fp_err("Radiation detected!");
fpi_imgdev_session_error(data->device, -EINVAL); fpi_imgdev_session_error(data->device, -EINVAL);
fpi_ssm_mark_aborted(ssm, -EINVAL); fpi_ssm_mark_failed(ssm, -EINVAL);
goto out; goto out;
} }
@@ -90,7 +90,7 @@ static void async_send_cb(struct libusb_transfer *transfer)
if (action->type != ACTION_SEND) { if (action->type != ACTION_SEND) {
fp_err("Radiation detected!"); fp_err("Radiation detected!");
fpi_imgdev_session_error(data->device, -EINVAL); fpi_imgdev_session_error(data->device, -EINVAL);
fpi_ssm_mark_aborted(ssm, -EINVAL); fpi_ssm_mark_failed(ssm, -EINVAL);
goto out; goto out;
} }
@@ -98,7 +98,7 @@ static void async_send_cb(struct libusb_transfer *transfer)
/* Transfer not completed, return IO error */ /* Transfer not completed, return IO error */
fp_err("transfer not completed, status = %d", transfer->status); fp_err("transfer not completed, status = %d", transfer->status);
fpi_imgdev_session_error(data->device, -EIO); fpi_imgdev_session_error(data->device, -EIO);
fpi_ssm_mark_aborted(ssm, -EIO); fpi_ssm_mark_failed(ssm, -EIO);
goto out; goto out;
} }
if (transfer->length != transfer->actual_length) { 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", fp_err("length mismatch, got %d, expected %d",
transfer->actual_length, transfer->length); transfer->actual_length, transfer->length);
fpi_imgdev_session_error(data->device, -EIO); fpi_imgdev_session_error(data->device, -EIO);
fpi_ssm_mark_aborted(ssm, -EIO); fpi_ssm_mark_failed(ssm, -EIO);
goto out; goto out;
} }
@@ -119,7 +119,7 @@ out:
static void async_recv_cb(struct libusb_transfer *transfer) 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 usbexchange_data *data = fpi_ssm_get_user_data(ssm);
struct usb_action *action; struct usb_action *action;
@@ -127,14 +127,14 @@ static void async_recv_cb(struct libusb_transfer *transfer)
/* Transfer not completed, return IO error */ /* Transfer not completed, return IO error */
fp_err("transfer not completed, status = %d", transfer->status); fp_err("transfer not completed, status = %d", transfer->status);
fpi_imgdev_session_error(data->device, -EIO); fpi_imgdev_session_error(data->device, -EIO);
fpi_ssm_mark_aborted(ssm, -EIO); fpi_ssm_mark_failed(ssm, -EIO);
goto out; goto out;
} }
if (fpi_ssm_get_cur_state(ssm) >= data->stepcount) { if (fpi_ssm_get_cur_state(ssm) >= data->stepcount) {
fp_err("Radiation detected!"); fp_err("Radiation detected!");
fpi_imgdev_session_error(data->device, -EINVAL); fpi_imgdev_session_error(data->device, -EINVAL);
fpi_ssm_mark_aborted(ssm, -EINVAL); fpi_ssm_mark_failed(ssm, -EINVAL);
goto out; goto out;
} }
@@ -142,7 +142,7 @@ static void async_recv_cb(struct libusb_transfer *transfer)
if (action->type != ACTION_RECEIVE) { if (action->type != ACTION_RECEIVE) {
fp_err("Radiation detected!"); fp_err("Radiation detected!");
fpi_imgdev_session_error(data->device, -EINVAL); fpi_imgdev_session_error(data->device, -EINVAL);
fpi_ssm_mark_aborted(ssm, -EINVAL); fpi_ssm_mark_failed(ssm, -EINVAL);
goto out; goto out;
} }
@@ -152,14 +152,14 @@ static void async_recv_cb(struct libusb_transfer *transfer)
transfer->actual_length, transfer->actual_length,
action->correct_reply_size); action->correct_reply_size);
fpi_imgdev_session_error(data->device, -EIO); fpi_imgdev_session_error(data->device, -EIO);
fpi_ssm_mark_aborted(ssm, -EIO); fpi_ssm_mark_failed(ssm, -EIO);
goto out; goto out;
} }
if (memcmp(transfer->buffer, action->data, if (memcmp(transfer->buffer, action->data,
action->correct_reply_size) != 0) { action->correct_reply_size) != 0) {
fp_dbg("Wrong reply:"); fp_dbg("Wrong reply:");
fpi_imgdev_session_error(data->device, -EIO); fpi_imgdev_session_error(data->device, -EIO);
fpi_ssm_mark_aborted(ssm, -EIO); fpi_ssm_mark_failed(ssm, -EIO);
goto out; goto out;
} }
} else } else
@@ -171,14 +171,14 @@ out:
libusb_free_transfer(transfer); 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) { if (fpi_ssm_get_cur_state(ssm) >= data->stepcount) {
fp_err("Bug detected: state %d out of range, only %d steps", fp_err("Bug detected: state %d out of range, only %d steps",
fpi_ssm_get_cur_state(ssm), data->stepcount); fpi_ssm_get_cur_state(ssm), data->stepcount);
fpi_imgdev_session_error(data->device, -EINVAL); fpi_imgdev_session_error(data->device, -EINVAL);
fpi_ssm_mark_aborted(ssm, -EINVAL); fpi_ssm_mark_failed(ssm, -EINVAL);
return; return;
} }
@@ -189,14 +189,8 @@ static void usbexchange_loop(struct fpi_ssm *ssm)
switch (action->type) { switch (action->type) {
case ACTION_SEND: case ACTION_SEND:
fp_dbg("Sending %s", action->name); fp_dbg("Sending %s", action->name);
transfer = libusb_alloc_transfer(0); transfer = fpi_usb_alloc();
if (transfer == NULL) { libusb_fill_bulk_transfer(transfer, fpi_dev_get_usb_dev(FP_DEV(data->device)),
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),
action->endpoint, action->data, action->endpoint, action->data,
action->size, async_send_cb, ssm, action->size, async_send_cb, ssm,
data->timeout); data->timeout);
@@ -205,14 +199,8 @@ static void usbexchange_loop(struct fpi_ssm *ssm)
case ACTION_RECEIVE: case ACTION_RECEIVE:
fp_dbg("Receiving %d bytes", action->size); fp_dbg("Receiving %d bytes", action->size);
transfer = libusb_alloc_transfer(0); transfer = fpi_usb_alloc();
if (transfer == NULL) { libusb_fill_bulk_transfer(transfer, fpi_dev_get_usb_dev(FP_DEV(data->device)),
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),
action->endpoint, data->receive_buf, action->endpoint, data->receive_buf,
action->size, async_recv_cb, ssm, action->size, async_recv_cb, ssm,
data->timeout); data->timeout);
@@ -222,24 +210,24 @@ static void usbexchange_loop(struct fpi_ssm *ssm)
default: default:
fp_err("Bug detected: invalid action %d", action->type); fp_err("Bug detected: invalid action %d", action->type);
fpi_imgdev_session_error(data->device, -EINVAL); fpi_imgdev_session_error(data->device, -EINVAL);
fpi_ssm_mark_aborted(ssm, -EINVAL); fpi_ssm_mark_failed(ssm, -EINVAL);
return; return;
} }
if (ret != 0) { if (ret != 0) {
fp_err("USB transfer error: %s", strerror(ret)); fp_err("USB transfer error: %s", strerror(ret));
fpi_imgdev_session_error(data->device, 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 usbexchange_data *data)
{ {
struct fpi_ssm *subsm = fpi_ssm_new(fpi_imgdev_get_dev(data->device), fpi_ssm *subsm = fpi_ssm_new(FP_DEV(data->device),
usbexchange_loop, usbexchange_loop,
data->stepcount); data->stepcount,
fpi_ssm_set_user_data(subsm, data); data);
fpi_ssm_start_subsm(ssm, subsm); fpi_ssm_start_subsm(ssm, subsm);
} }
@@ -395,9 +383,11 @@ static int process_chunk(struct vfs5011_data *data, int transferred)
return 0; 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; struct fp_img *img;
if (data->lines_recorded == 0) { 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) 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 fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct vfs5011_data *data; struct vfs5011_data *data;
data = fpi_imgdev_get_user_data(dev); data = FP_INSTANCE_DATA(FP_DEV(dev));
if ((transfer->status == LIBUSB_TRANSFER_COMPLETED) || if ((transfer->status == LIBUSB_TRANSFER_COMPLETED) ||
(transfer->status == LIBUSB_TRANSFER_TIMED_OUT)) { (transfer->status == LIBUSB_TRANSFER_TIMED_OUT)) {
@@ -441,7 +431,7 @@ static void chunk_capture_callback(struct libusb_transfer *transfer)
} else { } else {
if (!data->deactivating) { if (!data->deactivating) {
fp_err("Failed to capture data"); fp_err("Failed to capture data");
fpi_ssm_mark_aborted(ssm, -1); fpi_ssm_mark_failed(ssm, -1);
} else { } else {
fpi_ssm_mark_completed(ssm); 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, static int capture_chunk_async(struct vfs5011_data *data,
libusb_device_handle *handle, int nline, 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", fp_dbg("capture_chunk_async: capture %d lines, already have %d",
nline, data->lines_recorded); nline, data->lines_recorded);
@@ -462,7 +452,7 @@ static int capture_chunk_async(struct vfs5011_data *data,
STOP_CHECK_LINES = 50 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, libusb_fill_bulk_transfer(data->flying_transfer, handle, VFS5011_IN_ENDPOINT_DATA,
data->capture_buffer, data->capture_buffer,
nline * VFS5011_LINE_SIZE, nline * VFS5011_LINE_SIZE,
@@ -470,13 +460,6 @@ static int capture_chunk_async(struct vfs5011_data *data,
return libusb_submit_transfer(data->flying_transfer); 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 * 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 * 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 ======================= */ /* ====================== 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}; 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; struct vfs5011_data *data;
int r; 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)); 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; break;
case DEV_ACTIVATE_READ_DATA: 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); READ_TIMEOUT, ssm);
if (r != 0) { if (r != 0) {
fp_err("Failed to capture data"); fp_err("Failed to capture data");
fpi_imgdev_session_error(dev, r); fpi_imgdev_session_error(dev, r);
fpi_ssm_mark_aborted(ssm, r); fpi_ssm_mark_failed(ssm, r);
} }
break; break;
case DEV_ACTIVATE_DATA_COMPLETE: 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) { if (timeout == NULL) {
/* Failed to add timeout */ /* Failed to add timeout */
fp_err("failed to add timeout"); fp_err("failed to add timeout");
fpi_imgdev_session_error(dev, -1); fpi_imgdev_session_error(dev, -1);
fpi_ssm_mark_aborted(ssm, -1); fpi_ssm_mark_failed(ssm, -1);
} }
break; 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; struct vfs5011_data *data;
int r = fpi_ssm_get_error(ssm); int r = fpi_ssm_get_error(ssm);
data = fpi_imgdev_get_user_data(dev); data = FP_INSTANCE_DATA(_dev);
fp_dbg("finishing"); fp_dbg("finishing");
if (data->init_sequence.receive_buf != NULL) if (data->init_sequence.receive_buf != NULL)
g_free(data->init_sequence.receive_buf); g_free(data->init_sequence.receive_buf);
data->init_sequence.receive_buf = NULL; data->init_sequence.receive_buf = NULL;
if (!data->deactivating && !r) { if (!data->deactivating && !r) {
submit_image(ssm, data); submit_image(ssm, data, dev);
fpi_imgdev_report_finger_status(dev, FALSE); fpi_imgdev_report_finger_status(dev, FALSE);
} }
fpi_ssm_free(ssm); 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; struct vfs5011_data *data;
data = fpi_imgdev_get_user_data(dev); data = FP_INSTANCE_DATA(_dev);
switch (fpi_ssm_get_cur_state(ssm)) { switch (fpi_ssm_get_cur_state(ssm)) {
case DEV_OPEN_START: 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; struct vfs5011_data *data;
data = fpi_imgdev_get_user_data(dev); data = FP_INSTANCE_DATA(_dev);
g_free(data->init_sequence.receive_buf); g_free(data->init_sequence.receive_buf);
data->init_sequence.receive_buf = NULL; 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 = (struct vfs5011_data *)g_malloc0(sizeof(*data));
data->capture_buffer = data->capture_buffer =
(unsigned char *)g_malloc0(CAPTURE_LINES * VFS5011_LINE_SIZE); (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) { if (r != 0) {
fp_err("Failed to reset the device"); fp_err("Failed to reset the device");
return r; 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) { if (r != 0) {
fp_err("Failed to claim interface: %s", libusb_error_name(r)); fp_err("Failed to claim interface: %s", libusb_error_name(r));
return r; return r;
} }
struct fpi_ssm *ssm; fpi_ssm *ssm;
ssm = fpi_ssm_new(fpi_imgdev_get_dev(dev), open_loop, DEV_OPEN_NUM_STATES); ssm = fpi_ssm_new(FP_DEV(dev), open_loop, DEV_OPEN_NUM_STATES, dev);
fpi_ssm_set_user_data(ssm, dev);
fpi_ssm_start(ssm, open_loop_complete); fpi_ssm_start(ssm, open_loop_complete);
return 0; 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) 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; struct vfs5011_data *data;
data = fpi_imgdev_get_user_data(dev); data = FP_INSTANCE_DATA(FP_DEV(dev));
if (data != NULL) { if (data != NULL) {
g_free(data->capture_buffer); g_free(data->capture_buffer);
g_slist_free_full(data->rows, g_free); g_slist_free_full(data->rows, g_free);
@@ -853,13 +835,12 @@ static void dev_close(struct fp_img_dev *dev)
static void start_scan(struct fp_img_dev *dev) static void start_scan(struct fp_img_dev *dev)
{ {
struct vfs5011_data *data; 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; data->loop_running = TRUE;
fp_dbg("creating ssm"); fp_dbg("creating ssm");
ssm = fpi_ssm_new(fpi_imgdev_get_dev(dev), activate_loop, DEV_ACTIVATE_NUM_STATES); ssm = fpi_ssm_new(FP_DEV(dev), activate_loop, DEV_ACTIVATE_NUM_STATES, dev);
fpi_ssm_set_user_data(ssm, dev);
fp_dbg("starting ssm"); fp_dbg("starting ssm");
fpi_ssm_start(ssm, activate_loop_complete); fpi_ssm_start(ssm, activate_loop_complete);
fp_dbg("ssm done, getting out"); fp_dbg("ssm done, getting out");
@@ -869,7 +850,7 @@ static int dev_activate(struct fp_img_dev *dev, enum fp_imgdev_state state)
{ {
struct vfs5011_data *data; struct vfs5011_data *data;
data = fpi_imgdev_get_user_data(dev); data = FP_INSTANCE_DATA(FP_DEV(dev));
fp_dbg("device initialized"); fp_dbg("device initialized");
data->deactivating = FALSE; data->deactivating = FALSE;
@@ -883,7 +864,7 @@ static void dev_deactivate(struct fp_img_dev *dev)
int r; int r;
struct vfs5011_data *data; struct vfs5011_data *data;
data = fpi_imgdev_get_user_data(dev); data = FP_INSTANCE_DATA(FP_DEV(dev));
if (data->loop_running) { if (data->loop_running) {
data->deactivating = TRUE; data->deactivating = TRUE;
if (data->flying_transfer) { if (data->flying_transfer) {
@@ -898,6 +879,7 @@ static void dev_deactivate(struct fp_img_dev *dev)
static const struct usb_id id_table[] = { static const struct usb_id id_table[] = {
{ .vendor = 0x138a, .product = 0x0010 /* Validity device from some Toshiba laptops */ }, { .vendor = 0x138a, .product = 0x0010 /* Validity device from some Toshiba laptops */ },
{ .vendor = 0x138a, .product = 0x0011 /* vfs5011 */ }, { .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 = 0x0017 /* Validity device from Lenovo T440 laptops */ },
{ .vendor = 0x138a, .product = 0x0018 /* one more Validity device */ }, { .vendor = 0x138a, .product = 0x0018 /* one more Validity device */ },
{ 0, 0, 0, }, { 0, 0, 0, },

View File

@@ -23,282 +23,17 @@
#include <config.h> #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 "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" #include "drivers/driver_ids.h"
#define fp_dbg g_debug
#define fp_info g_debug
#define fp_warn g_warning
#define fp_err g_error
#define BUG_ON(condition) g_assert(!(condition))
#define BUG() g_assert_not_reached()
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 #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,31 +22,39 @@
#include <config.h> #include <config.h>
#ifdef FP_COMPONENT
#undef G_LOG_DOMAIN
#define G_LOG_DOMAIN "libfprint-"FP_COMPONENT
#endif
#include <stdint.h> #include <stdint.h>
#include <errno.h> #include <errno.h>
#include <glib.h> #include <glib.h>
#include <libusb.h> #include <libusb.h>
#include "nbis-helpers.h"
#include "fprint.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" #include "drivers/driver_ids.h"
#define container_of(ptr, type, member) ({ \ /* Global variables */
const typeof( ((type *)0)->member ) *__mptr = (ptr); \ extern libusb_context *fpi_usb_ctx;
(type *)( (char *)__mptr - offsetof(type,member) );}) extern GSList *opened_devices;
#define fp_dbg g_debug /* fp_print_data structure definition */
#define fp_info g_debug enum fp_print_data_type {
#define fp_warn g_warning PRINT_DATA_RAW = 0, /* memset-imposed default */
#define fp_err g_error PRINT_DATA_NBIS_MINUTIAE
};
#define BUG_ON(condition) g_assert(!(condition)) struct fp_print_data {
#define BUG() g_assert_not_reached() uint16_t driver_id;
uint32_t devtype;
enum fp_print_data_type type;
GSList *prints;
};
/* fp_dev structure definition */
enum fp_dev_state { enum fp_dev_state {
DEV_STATE_INITIAL = 0, DEV_STATE_INITIAL = 0,
DEV_STATE_ERROR, DEV_STATE_ERROR,
@@ -69,21 +77,31 @@ enum fp_dev_state {
DEV_STATE_CAPTURING, DEV_STATE_CAPTURING,
DEV_STATE_CAPTURE_DONE, DEV_STATE_CAPTURE_DONE,
DEV_STATE_CAPTURE_STOPPING, DEV_STATE_CAPTURE_STOPPING,
DEV_STATE_DELETING,
DEV_STATE_DELETE_DONE,
DEV_STATE_DELETE_STOPPING,
}; };
struct fp_driver **fprint_get_drivers (void);
struct fp_dev { struct fp_dev {
struct fp_driver *drv; struct fp_driver *drv;
libusb_device_handle *udev;
uint32_t devtype; 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; int nr_enroll_stages;
/* FIXME: This will eventually have a bus type */
libusb_device_handle *udev;
/* read-only to drivers */ /* read-only to drivers */
struct fp_print_data *verify_data; struct fp_print_data *verify_data;
struct fp_print_data *delete_data;
/* drivers should not mess with any of the below */ /* drivers should not mess with any of the below */
enum fp_dev_state state; enum fp_dev_state state;
int __enroll_stage; int __enroll_stage;
@@ -111,44 +129,17 @@ struct fp_dev {
void *capture_cb_data; void *capture_cb_data;
fp_operation_stop_cb capture_stop_cb; fp_operation_stop_cb capture_stop_cb;
void *capture_stop_cb_data; void *capture_stop_cb_data;
fp_delete_cb delete_cb;
void *delete_cb_data;
/* FIXME: better place to put this? */ /* FIXME: better place to put this? */
struct fp_print_data **identify_gallery; struct fp_print_data **identify_gallery;
}; };
enum fp_imgdev_state { /* fp_img_dev structure definition */
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 { struct fp_img_dev {
struct fp_dev *dev; struct fp_dev *parent;
libusb_device_handle *udev;
enum fp_imgdev_action action; enum fp_imgdev_action action;
int action_state; int action_state;
@@ -160,78 +151,18 @@ struct fp_img_dev {
/* FIXME: better place to put this? */ /* FIXME: better place to put this? */
size_t identify_match_offset; size_t identify_match_offset;
void *priv;
}; };
int fpi_imgdev_get_img_width(struct fp_img_dev *imgdev); /* fp_driver structure definition */
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_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) \ #define fpi_driver_to_img_driver(drv) \
container_of((drv), struct fp_img_driver, driver) container_of((drv), struct fp_img_driver, driver)
/* fp_dscv_dev structure definition */
struct fp_dscv_dev { struct fp_dscv_dev {
struct libusb_device *udev; struct libusb_device *udev;
struct fp_driver *drv; struct fp_driver *drv;
@@ -239,6 +170,7 @@ struct fp_dscv_dev {
uint32_t devtype; uint32_t devtype;
}; };
/* fp_dscv_print structure definition */
struct fp_dscv_print { struct fp_dscv_print {
uint16_t driver_id; uint16_t driver_id;
uint32_t devtype; uint32_t devtype;
@@ -246,43 +178,7 @@ struct fp_dscv_print {
char *path; char *path;
}; };
enum fp_print_data_type { /* fp_minutia structure definition */
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);
struct fp_minutia { struct fp_minutia {
int x; int x;
int y; int y;
@@ -298,34 +194,32 @@ struct fp_minutia {
int num_nbrs; int num_nbrs;
}; };
/* fp_minutiae structure definition */
struct fp_minutiae { struct fp_minutiae {
int alloc; int alloc;
int num; int num;
struct fp_minutia **list; struct fp_minutia **list;
}; };
/* bit values for fp_img.flags */ /* Defined in fpi-dev-img.c */
#define FP_IMG_V_FLIPPED (1<<0) void fpi_img_driver_setup(struct fp_img_driver *idriver);
#define FP_IMG_H_FLIPPED (1<<1) int fpi_imgdev_get_img_width(struct fp_img_dev *imgdev);
#define FP_IMG_COLORS_INVERTED (1<<2) int fpi_imgdev_get_img_height(struct fp_img_dev *imgdev);
#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 \ /* Exported for use in command-line tools
| FP_IMG_COLORS_INVERTED) * Defined in fpi-core.c */
struct fp_driver **fprint_get_drivers (void);
struct fp_img { /* Defined in fpi-core.c */
int width; enum fp_print_data_type fpi_driver_get_data_type(struct fp_driver *drv);
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); /* Defined in fpi-data.c */
struct fp_img *fpi_img_resize(struct fp_img *img, size_t newsize); 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); gboolean fpi_img_is_sane(struct fp_img *img);
int fpi_img_to_print_data(struct fp_img_dev *imgdev, struct fp_img *img, int fpi_img_to_print_data(struct fp_img_dev *imgdev, struct fp_img *img,
struct fp_print_data **ret); struct fp_print_data **ret);
@@ -333,71 +227,23 @@ int fpi_img_compare_print_data(struct fp_print_data *enrolled_print,
struct fp_print_data *new_print); struct fp_print_data *new_print);
int fpi_img_compare_print_data_to_gallery(struct fp_print_data *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_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_init(void);
void fpi_poll_exit(void); void fpi_poll_exit(void);
typedef void (*fpi_timeout_fn)(void *data); /* Defined in fpi-async.c */
void fpi_drvcb_capture_started(struct fp_dev *dev, int status);
/* async drv <--> lib comms */ void fpi_drvcb_report_capture_result(struct fp_dev *dev, int result,
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,
struct fp_img *img); 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_identify_started(struct fp_dev *dev, int status);
void fpi_drvcb_report_identify_result(struct fp_dev *dev, int result, void fpi_drvcb_report_identify_result(struct fp_dev *dev, int result,
size_t match_offset, struct fp_img *img); size_t match_offset, struct fp_img *img);
void fpi_drvcb_identify_stopped(struct fp_dev *dev); void fpi_drvcb_identify_stopped(struct fp_dev *dev);
void fpi_drvcb_capture_started(struct fp_dev *dev, int status); #include "drivers_definitions.h"
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);
#endif #endif

View File

@@ -29,7 +29,18 @@
#include <libusb.h> #include <libusb.h>
#include <glib.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, static unsigned int calc_error(struct fpi_frame_asmbl_ctx *ctx,
struct fpi_frame *first_frame, 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; 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, void fpi_do_movement_estimation(struct fpi_frame_asmbl_ctx *ctx,
GSList *stripes, size_t num_stripes) 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, 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; GSList *stripe;
struct fp_img *img; struct fp_img *img;
@@ -235,7 +276,8 @@ struct fp_img *fpi_assemble_frames(struct fpi_frame_asmbl_ctx *ctx,
gboolean reverse = FALSE; gboolean reverse = FALSE;
struct fpi_frame *fpi_frame; 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); BUG_ON(ctx->image_width < ctx->frame_width);
/* Calculate height */ /* Calculate height */
@@ -252,7 +294,7 @@ struct fp_img *fpi_assemble_frames(struct fpi_frame_asmbl_ctx *ctx,
height += fpi_frame->delta_y; height += fpi_frame->delta_y;
i++; i++;
stripe = g_slist_next(stripe); stripe = g_slist_next(stripe);
} while (i < stripes_len); } while (i < num_stripes);
fp_dbg("height is %d", height); 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); stripe = g_slist_next(stripe);
i++; i++;
} while (i < stripes_len); } while (i < num_stripes);
return img; 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; } /**
* fpi_assemble_lines:
/* Rescale image to account for variable swiping speed */ * @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, 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 */ /* Number of output lines per distance between two scanners */
int i; int i;
GSList *row1, *row2; GSList *row1, *row2;
float y = 0.0; float y = 0.0;
int line_ind = 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); unsigned char *output = g_malloc0(ctx->line_width * ctx->max_height);
struct fp_img *img; struct fp_img *img;
g_return_val_if_fail (lines != NULL, NULL); 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()); fp_dbg("%"G_GINT64_FORMAT, g_get_real_time());
row1 = lines; 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 bestmatch = i;
int bestdiff = 0; int bestdiff = 0;
int j, firstrow, lastrow; int j, firstrow, lastrow;
firstrow = i + 1; 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); row2 = g_slist_next(row1);
for (j = firstrow; j <= lastrow; j++) { 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); 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()); 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]); fp_dbg("%d", offsets[i]);
row1 = lines; 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]; int offset = offsets[i/2];
if (offset > 0) { if (offset > 0) {
float ynext = y + (float)ctx->resolution / offset; 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" #define FP_COMPONENT "async"
#include "fp_internal.h" #include "fp_internal.h"
#include "fpi-async.h"
#include <config.h> #include <config.h>
#include <errno.h> #include <errno.h>
#include <glib.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 */ /* Drivers call this when device initialisation has completed */
void fpi_drvcb_open_complete(struct fp_dev *dev, int status) 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: * fp_async_dev_open:
* @ddev: * @ddev: the struct #fp_dscv_dev discovered device to open
* @callback: * @callback: the callback to call when the device has been opened
* @user_data * @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, API_EXPORTED int fp_async_dev_open(struct fp_dscv_dev *ddev, fp_dev_open_cb callback,
void *user_data) 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; int r;
g_return_val_if_fail(ddev != NULL, -ENODEV); g_return_val_if_fail(ddev != NULL, -ENODEV);
g_return_val_if_fail (callback != NULL, -EINVAL);
drv = ddev->drv; drv = ddev->drv;
@@ -93,6 +111,7 @@ void fpi_drvcb_close_complete(struct fp_dev *dev)
G_DEBUG_HERE(); G_DEBUG_HERE();
BUG_ON(dev->state != DEV_STATE_DEINITIALIZING); BUG_ON(dev->state != DEV_STATE_DEINITIALIZING);
dev->state = DEV_STATE_DEINITIALIZED; dev->state = DEV_STATE_DEINITIALIZED;
fpi_timeout_cancel_all_for_dev(dev);
libusb_close(dev->udev); libusb_close(dev->udev);
if (dev->close_cb) if (dev->close_cb)
dev->close_cb(dev, dev->close_cb_data); 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: * fp_async_dev_close:
* @dev: * @dev: the struct #fp_dev device
* @callback: * @callback: the callback to call when the device has been closed
* @user_data * @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, API_EXPORTED void fp_async_dev_close(struct fp_dev *dev,
fp_operation_stop_cb callback, void *user_data) 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: * fp_async_enroll_start:
* @dev: * @dev: the struct #fp_dev device
* @callback: * @callback: the callback to call for each stage of the enrollment
* @user_data: * @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, API_EXPORTED int fp_async_enroll_start(struct fp_dev *dev,
fp_enroll_stage_cb callback, void *user_data) 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; int r;
g_return_val_if_fail(dev != NULL, -ENODEV); g_return_val_if_fail(dev != NULL, -ENODEV);
g_return_val_if_fail (callback != NULL, -EINVAL);
drv = dev->drv; drv = dev->drv;
@@ -213,11 +240,13 @@ void fpi_drvcb_enroll_stopped(struct fp_dev *dev)
/** /**
* fp_async_enroll_stop: * fp_async_enroll_stop:
* @dev: * @dev: the struct #fp_dev device
* @callback: * @callback: the callback to call when the enrollment has been cancelled
* @user_data: * @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, API_EXPORTED int fp_async_enroll_stop(struct fp_dev *dev,
fp_operation_stop_cb callback, void *user_data) 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: * fp_async_verify_start:
* @dev: * @dev: the struct #fp_dev device
* @data: * @data: the print to verify against. Must have been previously
* @callback: * enrolled with a device compatible to the device selected to perform the scan
* @user_data: * @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, API_EXPORTED int fp_async_verify_start(struct fp_dev *dev,
struct fp_print_data *data, fp_img_operation_cb callback, void *user_data) 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; int r;
g_return_val_if_fail(dev != NULL, -ENODEV); g_return_val_if_fail(dev != NULL, -ENODEV);
g_return_val_if_fail (callback != NULL, -EINVAL);
drv = dev->drv; drv = dev->drv;
@@ -335,11 +370,13 @@ void fpi_drvcb_verify_stopped(struct fp_dev *dev)
/** /**
* fp_async_verify_stop: * fp_async_verify_stop:
* @dev: * @dev: the struct #fp_dev device
* @callback: * @callback: the callback to call to finish a verification
* @user_data: * @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, API_EXPORTED int fp_async_verify_stop(struct fp_dev *dev,
fp_operation_stop_cb callback, void *user_data) 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: * fp_async_identify_start:
* @dev: * @dev: the struct #fp_dev device
* @gallery: * @gallery: NULL-terminated array of pointers to the prints to
* @callback: * identify against. Each one must have been previously enrolled with a device
* @user_data: * 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, API_EXPORTED int fp_async_identify_start(struct fp_dev *dev,
struct fp_print_data **gallery, fp_identify_cb callback, void *user_data) struct fp_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; int r;
g_return_val_if_fail(dev != NULL, -ENODEV); g_return_val_if_fail(dev != NULL, -ENODEV);
g_return_val_if_fail (callback != NULL, -EINVAL);
drv = dev->drv; drv = dev->drv;
@@ -451,11 +494,13 @@ void fpi_drvcb_report_identify_result(struct fp_dev *dev, int result,
/** /**
* fp_async_identify_stop: * fp_async_identify_stop:
* @dev: * @dev: the struct #fp_dev device
* @callback: * @callback: the callback to call when the identification has stopped
* @user_data: * @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, API_EXPORTED int fp_async_identify_stop(struct fp_dev *dev,
fp_operation_stop_cb callback, void *user_data) 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: * fp_async_capture_start:
* @dev: * @dev: the struct #fp_dev device
* @unconditional: * @unconditional: whether to unconditionally capture an image, or to only capture when a finger is detected
* @callback: * @callback: the callback to call when the capture has finished
* @user_data: * @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, API_EXPORTED int fp_async_capture_start(struct fp_dev *dev, int unconditional,
fp_img_operation_cb callback, void *user_data) 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; int r;
g_return_val_if_fail(dev != NULL, -ENODEV); g_return_val_if_fail(dev != NULL, -ENODEV);
g_return_val_if_fail (callback != NULL, -EINVAL);
drv = dev->drv; drv = dev->drv;
@@ -536,7 +587,7 @@ API_EXPORTED int fp_async_capture_start(struct fp_dev *dev, int unconditional,
if (r < 0) { if (r < 0) {
dev->capture_cb = NULL; dev->capture_cb = NULL;
dev->state = DEV_STATE_ERROR; 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; return r;
} }
@@ -586,11 +637,13 @@ void fpi_drvcb_capture_stopped(struct fp_dev *dev)
/** /**
* fp_async_capture_stop: * fp_async_capture_stop:
* @dev: * @dev: the struct #fp_dev device
* @callback: * @callback: the callback to call when the capture has been stopped
* @user_data: * @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, API_EXPORTED int fp_async_capture_stop(struct fp_dev *dev,
fp_operation_stop_cb callback, void *user_data) fp_operation_stop_cb callback, void *user_data)
@@ -622,8 +675,63 @@ API_EXPORTED int fp_async_capture_stop(struct fp_dev *dev,
r = drv->capture_stop(dev); r = drv->capture_stop(dev);
if (r < 0) { if (r < 0) {
fp_err("failed to stop verification"); fp_err("failed to stop capture");
dev->capture_stop_cb = NULL; dev->capture_stop_cb = NULL;
} }
return r; return r;
} }
/**
* fp_async_delete_finger:
* @dev: the struct #fp_dev device
* @data: data to delete. Must have been previously enrolled.
* @callback: the callback to call when data deleted.
* @user_data: user data to pass to the callback
*
* Request to delete data in sensor.
*
* Returns: 0 on success, non-zero on error
*/
API_EXPORTED int fp_async_delete_finger(struct fp_dev *dev,
struct fp_print_data *data, fp_delete_cb callback, void *user_data)
{
struct fp_driver *drv;
int r;
g_return_val_if_fail(dev != NULL, -ENODEV);
g_return_val_if_fail (callback != NULL, -EINVAL);
drv = dev->drv;
G_DEBUG_HERE();
if (!drv->delete_finger)
return -ENOTSUP;
dev->state = DEV_STATE_DELETING;
dev->delete_cb = callback;
dev->delete_cb_data = user_data;
dev->delete_data = data;
r = drv->delete_finger(dev);
if (r < 0) {
dev->delete_cb = NULL;
dev->state = DEV_STATE_ERROR;
fp_err("failed to delete data, error %d", r);
}
return r;
}
/* Drivers call this when delete done */
void fpi_drvcb_delete_complete(struct fp_dev *dev, int status)
{
fp_dbg("status %d", status);
BUG_ON(dev->state != DEV_STATE_DELETING);
dev->state = (status) ? DEV_STATE_ERROR : DEV_STATE_DELETE_DONE;
if (dev->delete_cb)
dev->delete_cb(dev, status, dev->delete_cb_data);
}

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

@@ -0,0 +1,42 @@
/*
* 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);
void fpi_drvcb_delete_complete(struct fp_dev *dev, int status);
#endif

View File

@@ -33,6 +33,7 @@ GSList *opened_devices = NULL;
/** /**
* SECTION:discovery * SECTION:discovery
* @title: Device discovery * @title: Device discovery
* @short_description: Device discovery functions
* *
* These functions allow you to scan the system for supported fingerprint * These functions allow you to scan the system for supported fingerprint
* scanning hardware. This is your starting point when integrating libfprint * scanning hardware. This is your starting point when integrating libfprint
@@ -47,6 +48,7 @@ GSList *opened_devices = NULL;
/** /**
* SECTION:drv * SECTION:drv
* @title: Driver operations * @title: Driver operations
* @short_description: Driver operation functions
* *
* Internally, libfprint is abstracted into various drivers to communicate * Internally, libfprint is abstracted into various drivers to communicate
* with the different types of supported fingerprint readers. libfprint works * with the different types of supported fingerprint readers. libfprint works
@@ -61,6 +63,7 @@ GSList *opened_devices = NULL;
/** /**
* SECTION:dev * SECTION:dev
* @title: Devices operations * @title: Devices operations
* @short_description: Device operation functions
* *
* In order to interact with fingerprint scanners, your software will * In order to interact with fingerprint scanners, your software will
* interface primarily with libfprint's representation of devices, detailed * 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. * 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 GSList *registered_drivers = NULL;
static void register_driver(struct fp_driver *drv) 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: * fp_discover_devs:
* *
* Scans the system and returns a list of discovered devices. This is your * 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 * Returns: a nul-terminated list of discovered devices or %NULL on error.
* fp_dscv_devs_free() after use. * Must be freed with fp_dscv_devs_free() after use.
*/ */
API_EXPORTED struct fp_dscv_dev **fp_discover_devs(void) 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 r;
int i = 0; int i = 0;
if (registered_drivers == NULL) g_return_val_if_fail (registered_drivers != NULL, NULL);
return NULL;
r = libusb_get_device_list(fpi_usb_ctx, &devs); r = libusb_get_device_list(fpi_usb_ctx, &devs);
if (r < 0) { 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) 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; 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: * fp_dscv_dev_get_driver_id:
* @dev: a discovered fingerprint device * @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) 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)); 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) API_EXPORTED uint32_t fp_dscv_dev_get_devtype(struct fp_dscv_dev *dev)
{ {
g_return_val_if_fail(dev, 0);
return dev->devtype; 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, API_EXPORTED int fp_dscv_dev_supports_print_data(struct fp_dscv_dev *dev,
struct fp_print_data *print) 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, return fpi_print_data_compatible(dev->drv->id, dev->devtype,
fpi_driver_get_data_type(dev->drv), print->driver_id, print->devtype, fpi_driver_get_data_type(dev->drv), print->driver_id, print->devtype,
print->type); 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, API_EXPORTED int fp_dscv_dev_supports_dscv_print(struct fp_dscv_dev *dev,
struct fp_dscv_print *print) 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, return fpi_print_data_compatible(dev->drv->id, dev->devtype, 0,
print->driver_id, print->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; struct fp_dscv_dev *ddev;
int i; int i;
g_return_val_if_fail(devs, NULL);
g_return_val_if_fail(print, NULL);
for (i = 0; (ddev = devs[i]); i++) for (i = 0; (ddev = devs[i]); i++)
if (fp_dscv_dev_supports_print_data(ddev, print)) if (fp_dscv_dev_supports_print_data(ddev, print))
return ddev; 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; struct fp_dscv_dev *ddev;
int i; int i;
g_return_val_if_fail(devs, NULL);
g_return_val_if_fail(print, NULL);
for (i = 0; (ddev = devs[i]); i++) { for (i = 0; (ddev = devs[i]); i++) {
#pragma GCC diagnostic push #pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations" #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: * fp_dev_get_driver:
* @dev: the device * @dev: the struct #fp_dev device
* *
* Get the #fp_driver for a fingerprint 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) API_EXPORTED struct fp_driver *fp_dev_get_driver(struct fp_dev *dev)
{ {
g_return_val_if_fail(dev, NULL);
return dev->drv; return dev->drv;
} }
/** /**
* fp_dev_get_nr_enroll_stages: * 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 * Gets the number of [enroll stages](intro.html#enrollment) required to enroll a
* fingerprint with the device. * 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) 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; return dev->nr_enroll_stages;
} }
/** /**
* fp_dev_get_devtype: * fp_dev_get_devtype:
* @dev: the device * @dev: the struct #fp_dev device
* *
* Gets the [devtype](advanced-topics.html#device-types) for a 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) API_EXPORTED uint32_t fp_dev_get_devtype(struct fp_dev *dev)
{ {
g_return_val_if_fail(dev, 0);
return dev->devtype; return dev->devtype;
} }
/** /**
* fp_dev_supports_print_data: * fp_dev_supports_print_data:
* @dev: the device * @dev: the struct #fp_dev device
* @data: the stored print * @data: the stored print
* *
* Determines if a stored print is compatible with a certain device. * 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, API_EXPORTED int fp_dev_supports_print_data(struct fp_dev *dev,
struct fp_print_data *data) 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, return fpi_print_data_compatible(dev->drv->id, dev->devtype,
fpi_driver_get_data_type(dev->drv), data->driver_id, data->devtype, fpi_driver_get_data_type(dev->drv), data->driver_id, data->devtype,
data->type); data->type);
@@ -511,7 +566,7 @@ API_EXPORTED int fp_dev_supports_print_data(struct fp_dev *dev,
/** /**
* fp_dev_supports_dscv_print: * fp_dev_supports_dscv_print:
* @dev: the device * @dev: the struct #fp_dev device
* @print: the discovered print * @print: the discovered print
* *
* Determines if a #fp_dscv_print discovered print appears to be compatible * 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, API_EXPORTED int fp_dev_supports_dscv_print(struct fp_dev *dev,
struct fp_dscv_print *print) 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, return fpi_print_data_compatible(dev->drv->id, dev->devtype,
0, print->driver_id, print->devtype, 0); 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: * fp_driver_get_name:
* @drv: the driver * @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) API_EXPORTED const char *fp_driver_get_name(struct fp_driver *drv)
{ {
g_return_val_if_fail(drv, NULL);
return drv->name; 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) API_EXPORTED const char *fp_driver_get_full_name(struct fp_driver *drv)
{ {
g_return_val_if_fail(drv, NULL);
return drv->full_name; 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) API_EXPORTED uint16_t fp_driver_get_driver_id(struct fp_driver *drv)
{ {
g_return_val_if_fail(drv, 0);
return drv->id; 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) 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; 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) g_return_val_if_fail(drv, 0);
return NULL;
return dev->priv; return drv->capture_start != NULL;
} }
/** /**
* fp_dev_supports_imaging: * 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 * Determines if a device has imaging capabilities. If a device has imaging
* capabilities you are able to perform imaging operations such as retrieving * 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) API_EXPORTED int fp_dev_supports_imaging(struct fp_dev *dev)
{ {
g_return_val_if_fail(dev, 0);
return dev->drv->capture_start != NULL; return dev->drv->capture_start != NULL;
} }
/** /**
* fp_dev_supports_identification: * 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) * Determines if a device is capable of [identification](intro.html#identification)
* through fp_identify_finger() and similar. Not all devices support this * through fp_identify_finger() and similar. Not all devices support this
@@ -661,12 +698,29 @@ API_EXPORTED int fp_dev_supports_imaging(struct fp_dev *dev)
*/ */
API_EXPORTED int fp_dev_supports_identification(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; return dev->drv->identify_start != NULL;
} }
/**
* fp_dev_supports_data_in_sensor:
* @dev: the struct #fp_dev device
*
* Determines if a device is capable of storing print data in sensor.
* Not all devices support this functionality.
*
* Returns: 1 if the device is capable of storing data in sensor, 0 otherwise.
*/
API_EXPORTED int fp_dev_supports_data_in_sensor(struct fp_dev *dev)
{
return dev->drv->delete_finger != NULL;
}
/** /**
* fp_dev_get_img_width: * 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. * Gets the expected width of images that will be captured from the device.
* This function will return -1 for devices that are not * This function will return -1 for devices that are not
@@ -678,18 +732,19 @@ API_EXPORTED int fp_dev_supports_identification(struct fp_dev *dev)
*/ */
API_EXPORTED int fp_dev_get_img_width(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); g_return_val_if_fail(dev, -1);
if (!imgdev) {
if (!dev->img_dev) {
fp_dbg("get image width for non-imaging device"); fp_dbg("get image width for non-imaging device");
return -1; return -1;
} }
return fpi_imgdev_get_img_width(imgdev); return fpi_imgdev_get_img_width(dev->img_dev);
} }
/** /**
* fp_dev_get_img_height: * 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. * Gets the expected height of images that will be captured from the device.
* This function will return -1 for devices that are not * This function will return -1 for devices that are not
@@ -701,13 +756,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) API_EXPORTED int fp_dev_get_img_height(struct fp_dev *dev)
{ {
struct fp_img_dev *imgdev = dev_to_img_dev(dev); g_return_val_if_fail(dev, -1);
if (!imgdev) {
if (!dev->img_dev) {
fp_dbg("get image height for non-imaging device"); fp_dbg("get image height for non-imaging device");
return -1; return -1;
} }
return fpi_imgdev_get_img_height(imgdev); return fpi_imgdev_get_img_height(dev->img_dev);
} }
/** /**

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

@@ -0,0 +1,119 @@
/*
* 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);
int (*delete_finger)(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, 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);
};
#endif

View File

@@ -32,9 +32,23 @@
#define DIR_PERMS 0700 #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 * SECTION: print_data
* @title: Stored prints * @title: Stored prints
* @short_description: Stored prints functions
* *
* Stored prints are represented by a structure named #fp_print_data. * Stored prints are represented by a structure named #fp_print_data.
* Stored prints are originally obtained from an enrollment function such as * 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. * This page documents the various operations you can do with a stored print.
* Note that by default, "stored prints" are not actually stored anywhere * Note that by default, "stored prints" are not actually stored anywhere
* except in RAM. For the simple scenarios, libfprint provides a simple API * except in RAM. Storage needs to be handled by the API user by using the
* for you to save and load the stored prints referring to a single user in * fp_print_data_get_data() and fp_print_data_from_data(). This API allows
* their home directory. For more advanced users, libfprint provides APIs for * to convert print data into byte strings, and to reconstruct stored prints
* you to convert print data to a byte string, and to reconstruct stored prints
* from such data at a later point. You are welcome to store these byte strings * from such data at a later point. You are welcome to store these byte strings
* in any fashion that suits you. * 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; static char *base_store = NULL;
@@ -106,7 +133,7 @@ static struct fp_print_data *print_data_new(uint16_t driver_id,
return data; 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); 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)); 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: * fp_print_data_get_data:
* @data: the stored print * @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. * directory beneath the current user's home directory.
* *
* Returns: 0 on success, non-zero on error. * 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, API_EXPORTED int fp_print_data_save(struct fp_print_data *data,
enum fp_finger finger) 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); r = g_mkdir_with_parents(dirpath, DIR_PERMS);
if (r < 0) { if (r < 0) {
fp_err("couldn't create storage directory"); fp_err("couldn't create storage directory");
free(buf);
g_free(path); g_free(path);
g_free(dirpath); g_free(dirpath);
return r; return r;
@@ -440,12 +485,16 @@ static int load_from_file(char *path, struct fp_print_data **data)
* obscure error conditions (e.g. corruption). * obscure error conditions (e.g. corruption).
* *
* Returns: 0 on success, non-zero on error * 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, API_EXPORTED int fp_print_data_load(struct fp_dev *dev,
enum fp_finger finger, struct fp_print_data **data) enum fp_finger finger, struct fp_print_data **data)
{ {
gchar *path; gchar *path;
struct fp_print_data *fdata; struct fp_print_data *fdata = NULL;
int r; int r;
if (!base_store) 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(). * Removes a stored print from disk previously saved with fp_print_data_save().
* *
* Returns: 0 on success, negative on error * 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, API_EXPORTED int fp_print_data_delete(struct fp_dev *dev,
enum fp_finger finger) 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 * SECTION:dscv_print
* @title: Print discovery (deprecated) * @title: Print discovery (deprecated)
* @short_description: Print discovery functions
* *
* The [stored print](libfprint-Stored-prints.html) documentation detailed a simple API * The [stored print](libfprint-Stored-prints.html) documentation detailed a simple API
* for storing per-device prints for a single user, namely * 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; GError *err = NULL;
GSList *tmplist = NULL; GSList *tmplist = NULL;
GSList *elem; GSList *elem;
unsigned int tmplist_len; GPtrArray *array;
struct fp_dscv_print **list;
unsigned int i;
if (!base_store) if (!base_store)
storage_setup(); storage_setup();
@@ -732,15 +784,17 @@ API_EXPORTED struct fp_dscv_print **fp_discover_prints(void)
} }
g_dir_close(dir); g_dir_close(dir);
tmplist_len = g_slist_length(tmplist);
list = g_malloc(sizeof(*list) * (tmplist_len + 1)); if (tmplist == NULL)
elem = tmplist; return NULL;
for (i = 0; i < tmplist_len; i++, elem = g_slist_next(elem))
list[i] = elem->data; array = g_ptr_array_new();
list[tmplist_len] = NULL; /* NULL-terminate */ 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); 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 <glib.h>
#include "fpi-dev-img.h"
#include "fpi-async.h"
#include "fp_internal.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 MIN_ACCEPTABLE_MINUTIAE 10
#define BOZORTH3_DEFAULT_THRESHOLD 40 #define BOZORTH3_DEFAULT_THRESHOLD 40
#define IMG_ENROLL_STAGES 5 #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) 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_dev *imgdev = g_malloc0(sizeof(*imgdev));
struct fp_img_driver *imgdrv = fpi_driver_to_img_driver(dev->drv); struct fp_img_driver *imgdrv = fpi_driver_to_img_driver(dev->drv);
int r = 0; int r = 0;
imgdev->dev = dev; /* Set up back pointers */
imgdev->enroll_stage = 0; dev->img_dev = imgdev;
dev->priv = imgdev; imgdev->parent = dev;
dev->nr_enroll_stages = IMG_ENROLL_STAGES;
/* for consistency in driver code, allow udev access through imgdev */ imgdev->enroll_stage = 0;
imgdev->udev = dev->udev; dev->nr_enroll_stages = IMG_ENROLL_STAGES;
if (imgdrv->open) { if (imgdrv->open) {
r = imgdrv->open(imgdev, driver_data); r = imgdrv->open(imgdev, driver_data);
@@ -55,32 +123,45 @@ err:
return r; 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) 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) 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); struct fp_img_driver *imgdrv = fpi_driver_to_img_driver(dev->drv);
if (imgdrv->close) if (imgdrv->close)
imgdrv->close(imgdev); imgdrv->close(dev->img_dev);
else else
fpi_drvcb_close_complete(dev); 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) 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); g_free(imgdev);
} }
static int dev_change_state(struct fp_img_dev *imgdev, static int dev_change_state(struct fp_img_dev *imgdev,
enum fp_imgdev_state state) 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); struct fp_img_driver *imgdrv = fpi_driver_to_img_driver(drv);
if (!imgdrv->change_state) if (!imgdrv->change_state)
@@ -92,7 +173,7 @@ static int dev_change_state(struct fp_img_dev *imgdev,
* image after freeing the old one. */ * image after freeing the old one. */
static int sanitize_image(struct fp_img_dev *imgdev, struct fp_img **_img) 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_driver *imgdrv = fpi_driver_to_img_driver(drv);
struct fp_img *img = *_img; struct fp_img *img = *_img;
@@ -118,6 +199,14 @@ static int sanitize_image(struct fp_img_dev *imgdev, struct fp_img **_img)
return 0; 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, void fpi_imgdev_report_finger_status(struct fp_img_dev *imgdev,
gboolean present) gboolean present)
{ {
@@ -150,7 +239,7 @@ void fpi_imgdev_report_finger_status(struct fp_img_dev *imgdev,
if (r == FP_ENROLL_COMPLETE) { if (r == FP_ENROLL_COMPLETE) {
imgdev->enroll_data = NULL; 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, r == FP_ENROLL_COMPLETE ? data : NULL,
img); img);
/* the callback can cancel enrollment, so recheck current /* the callback can cancel enrollment, so recheck current
@@ -163,18 +252,18 @@ void fpi_imgdev_report_finger_status(struct fp_img_dev *imgdev,
} }
break; break;
case IMG_ACTION_VERIFY: 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; imgdev->action_result = 0;
fp_print_data_free(data); fp_print_data_free(data);
break; break;
case IMG_ACTION_IDENTIFY: 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->identify_match_offset, img);
imgdev->action_result = 0; imgdev->action_result = 0;
fp_print_data_free(data); fp_print_data_free(data);
break; break;
case IMG_ACTION_CAPTURE: 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; imgdev->action_result = 0;
break; break;
default: 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) 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 match_score = imgdrv->bz3_threshold;
int r; int r;
if (match_score == 0) if (match_score == 0)
match_score = BOZORTH3_DEFAULT_THRESHOLD; 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); imgdev->acquire_data);
if (r >= match_score) 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) 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; int match_score = imgdrv->bz3_threshold;
size_t match_offset; size_t match_offset;
int r; int r;
@@ -214,12 +303,20 @@ static void identify_process_img(struct fp_img_dev *imgdev)
match_score = BOZORTH3_DEFAULT_THRESHOLD; match_score = BOZORTH3_DEFAULT_THRESHOLD;
r = fpi_img_compare_print_data_to_gallery(imgdev->acquire_data, 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->action_result = r;
imgdev->identify_match_offset = match_offset; 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) void fpi_imgdev_abort_scan(struct fp_img_dev *imgdev, int result)
{ {
imgdev->action_result = 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); 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) 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; int r;
G_DEBUG_HERE(); G_DEBUG_HERE();
@@ -272,7 +376,7 @@ void fpi_imgdev_image_captured(struct fp_img_dev *imgdev, struct fp_img *img)
switch (imgdev->action) { switch (imgdev->action) {
case IMG_ACTION_ENROLL: case IMG_ACTION_ENROLL:
if (!imgdev->enroll_data) { 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); BUG_ON(g_slist_length(print->prints) != 1);
/* Move print data from acquire data into enroll_data */ /* 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); fp_print_data_free(imgdev->acquire_data);
imgdev->acquire_data = NULL; imgdev->acquire_data = NULL;
imgdev->enroll_stage++; 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; imgdev->action_result = FP_ENROLL_COMPLETE;
else else
imgdev->action_result = FP_ENROLL_PASS; imgdev->action_result = FP_ENROLL_PASS;
@@ -307,22 +411,29 @@ next_state:
dev_change_state(imgdev, IMGDEV_STATE_AWAIT_FINGER_OFF); 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) void fpi_imgdev_session_error(struct fp_img_dev *imgdev, int error)
{ {
fp_dbg("error %d", error); fp_dbg("error %d", error);
BUG_ON(error == 0); BUG_ON(error == 0);
switch (imgdev->action) { switch (imgdev->action) {
case IMG_ACTION_ENROLL: 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; break;
case IMG_ACTION_VERIFY: case IMG_ACTION_VERIFY:
fpi_drvcb_report_verify_result(imgdev->dev, error, NULL); fpi_drvcb_report_verify_result(FP_DEV(imgdev), error, NULL);
break; break;
case IMG_ACTION_IDENTIFY: 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; break;
case IMG_ACTION_CAPTURE: case IMG_ACTION_CAPTURE:
fpi_drvcb_report_capture_result(imgdev->dev, error, NULL); fpi_drvcb_report_capture_result(FP_DEV(imgdev), error, NULL);
break; break;
default: default:
fp_err("unhandled action %d", imgdev->action); 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) void fpi_imgdev_activate_complete(struct fp_img_dev *imgdev, int status)
{ {
fp_dbg("status %d", status); fp_dbg("status %d", status);
switch (imgdev->action) { switch (imgdev->action) {
case IMG_ACTION_ENROLL: case IMG_ACTION_ENROLL:
fpi_drvcb_enroll_started(imgdev->dev, status); fpi_drvcb_enroll_started(FP_DEV(imgdev), status);
break; break;
case IMG_ACTION_VERIFY: case IMG_ACTION_VERIFY:
fpi_drvcb_verify_started(imgdev->dev, status); fpi_drvcb_verify_started(FP_DEV(imgdev), status);
break; break;
case IMG_ACTION_IDENTIFY: case IMG_ACTION_IDENTIFY:
fpi_drvcb_identify_started(imgdev->dev, status); fpi_drvcb_identify_started(FP_DEV(imgdev), status);
break; break;
case IMG_ACTION_CAPTURE: case IMG_ACTION_CAPTURE:
fpi_drvcb_capture_started(imgdev->dev, status); fpi_drvcb_capture_started(FP_DEV(imgdev), status);
break; break;
default: default:
fp_err("unhandled action %d", imgdev->action); 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) void fpi_imgdev_deactivate_complete(struct fp_img_dev *imgdev)
{ {
G_DEBUG_HERE(); G_DEBUG_HERE();
switch (imgdev->action) { switch (imgdev->action) {
case IMG_ACTION_ENROLL: case IMG_ACTION_ENROLL:
fpi_drvcb_enroll_stopped(imgdev->dev); fpi_drvcb_enroll_stopped(FP_DEV(imgdev));
break; break;
case IMG_ACTION_VERIFY: case IMG_ACTION_VERIFY:
fpi_drvcb_verify_stopped(imgdev->dev); fpi_drvcb_verify_stopped(FP_DEV(imgdev));
break; break;
case IMG_ACTION_IDENTIFY: case IMG_ACTION_IDENTIFY:
fpi_drvcb_identify_stopped(imgdev->dev); fpi_drvcb_identify_stopped(FP_DEV(imgdev));
break; break;
case IMG_ACTION_CAPTURE: case IMG_ACTION_CAPTURE:
fpi_drvcb_capture_stopped(imgdev->dev); fpi_drvcb_capture_stopped(FP_DEV(imgdev));
break; break;
default: default:
fp_err("unhandled action %d", imgdev->action); 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) 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); struct fp_img_driver *imgdrv = fpi_driver_to_img_driver(drv);
int width = imgdrv->img_width; 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) 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); struct fp_img_driver *imgdrv = fpi_driver_to_img_driver(drv);
int height = imgdrv->img_height; int height = imgdrv->img_height;
@@ -410,7 +535,7 @@ int fpi_imgdev_get_img_height(struct fp_img_dev *imgdev)
static int dev_activate(struct fp_img_dev *imgdev, enum fp_imgdev_state state) static int dev_activate(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); struct fp_img_driver *imgdrv = fpi_driver_to_img_driver(drv);
if (!imgdrv->activate) if (!imgdrv->activate)
@@ -420,7 +545,7 @@ static int dev_activate(struct fp_img_dev *imgdev, enum fp_imgdev_state state)
static void dev_deactivate(struct fp_img_dev *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); struct fp_img_driver *imgdrv = fpi_driver_to_img_driver(drv);
if (!imgdrv->deactivate) if (!imgdrv->deactivate)
@@ -430,7 +555,7 @@ static void dev_deactivate(struct fp_img_dev *imgdev)
static int generic_acquire_start(struct fp_dev *dev, int action) 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; int r;
fp_dbg("action %d", action); fp_dbg("action %d", action);
imgdev->action = action; imgdev->action = action;
@@ -484,7 +609,7 @@ static int img_dev_capture_start(struct fp_dev *dev)
static int img_dev_enroll_stop(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); BUG_ON(imgdev->action != IMG_ACTION_ENROLL);
generic_acquire_stop(imgdev); generic_acquire_stop(imgdev);
return 0; 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) 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); BUG_ON(imgdev->action != IMG_ACTION_VERIFY);
generic_acquire_stop(imgdev); generic_acquire_stop(imgdev);
return 0; 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) 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); BUG_ON(imgdev->action != IMG_ACTION_IDENTIFY);
generic_acquire_stop(imgdev); generic_acquire_stop(imgdev);
imgdev->identify_match_offset = 0; 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) 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); BUG_ON(imgdev->action != IMG_ACTION_CAPTURE);
generic_acquire_stop(imgdev); generic_acquire_stop(imgdev);
return 0; 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

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

@@ -0,0 +1,164 @@
/*
* 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;
}
/**
* fpi_dev_get_delete_data:
* @dev: a struct #fp_dev
*
* Returns the delete data associated with @dev.
* Returns: a struct #fp_print_data pointer or %NULL
*/
struct fp_print_data *
fpi_dev_get_delete_data(struct fp_dev *dev)
{
return dev->delete_data;
}

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

@@ -0,0 +1,49 @@
/*
* 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);
struct fp_print_data *fpi_dev_get_delete_data(struct fp_dev *dev);
#endif

View File

@@ -23,7 +23,19 @@
#include "fp_internal.h" #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_width = img->width * w_factor;
int new_height = img->height * h_factor; int new_height = img->height * h_factor;

View File

@@ -31,6 +31,7 @@
/** /**
* SECTION:img * SECTION:img
* @title: Image operations * @title: Image operations
* @short_description: Image operation functions
* *
* libfprint offers several ways of retrieving images from imaging devices, * libfprint offers several ways of retrieving images from imaging devices,
* one example being the fp_dev_img_capture() function. The functions * one example being the fp_dev_img_capture() function. The functions
@@ -48,6 +49,25 @@
* natural upright orientation. * 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 *fpi_img_new(size_t length)
{ {
struct fp_img *img = g_malloc0(sizeof(*img) + 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; 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 *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 width = imgdrv->img_width;
int height = imgdrv->img_height; int height = imgdrv->img_height;
struct fp_img *img = fpi_img_new(width * 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; 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) gboolean fpi_img_is_sane(struct fp_img *img)
{ {
guint len;
/* basic checks */ /* basic checks */
if (!img->length || !img->width || !img->height) if (!img->length || img->width <= 0 || img->height <= 0)
return FALSE; return FALSE;
/* buffer is big enough? */ /* Are width and height just too big? */
if ((img->length * img->height) < img->length) 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 FALSE;
return TRUE; 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); return g_realloc(img, sizeof(*img) + newsize);
} }
/** /**
* fp_img_free: * 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. * 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 minutiae_struct c[MAX_FILE_MINUTIAE];
struct xyt_struct *xyt = (struct xyt_struct *) buf; struct xyt_struct *xyt = (struct xyt_struct *) buf;
/* FIXME: only considers first 150 minutiae (MAX_FILE_MINUTIAE) */ /* struct xyt_struct uses arrays of MAX_BOZORTH_MINUTIAE (200) */
/* nist does weird stuff with 150 vs 1000 limits */ int nmin = min(minutiae->num, MAX_BOZORTH_MINUTIAE);
int nmin = min(minutiae->num, MAX_FILE_MINUTIAE);
for (i = 0; i < nmin; i++){ for (i = 0; i < nmin; i++){
minutia = minutiae->list[i]; minutia = minutiae->list[i];
@@ -288,6 +343,9 @@ static void minutiae_to_xyt(struct fp_minutiae *minutiae, int bwidth,
xyt->nrows = nmin; 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) static int fpi_img_detect_minutiae(struct fp_img *img)
{ {
struct fp_minutiae *minutiae; struct fp_minutiae *minutiae;
@@ -300,13 +358,10 @@ static int fpi_img_detect_minutiae(struct fp_img *img)
GTimer *timer; GTimer *timer;
if (img->flags & FP_IMG_STANDARDIZATION_FLAGS) { 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; 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 */ /* 25.4 mm per inch */
timer = g_timer_new(); timer = g_timer_new();
r = get_minutiae(&minutiae, &quality_map, &direction_map, 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 /* FIXME: space is wasted if we dont hit the max minutiae count. would
* be good to make this dynamic. */ * 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)); item = fpi_print_data_item_new(sizeof(struct xyt_struct));
print->type = PRINT_DATA_NBIS_MINUTIAE; print->type = PRINT_DATA_NBIS_MINUTIAE;
minutiae_to_xyt(img->minutiae, img->width, img->height, item->data); 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; 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, * fpi_std_sq_dev:
void *user_data) * @buf: buffer (usually bitmap, one byte per pixel)
{ * @size: size of @buffer
imgdev->priv = user_data; *
} * Calculates the squared standard deviation of the individual
* pixels in the buffer, as per the following formula:
void * * |[<!-- -->
fpi_imgdev_get_user_data(struct fp_img_dev *imgdev) * mean = sum (buf[0..size]) / size
{ * sq_dev = sum ((buf[0.size] - mean) ^ 2)
return imgdev->priv; * ]|
} * This function is usually used to determine whether image
* is empty.
struct fp_dev * *
fpi_imgdev_get_dev(struct fp_img_dev *imgdev) * Returns: the squared standard deviation for @buffer
{ */
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 */
int fpi_std_sq_dev(const unsigned char *buf, int size) int fpi_std_sq_dev(const unsigned char *buf, int size)
{ {
int res = 0, mean = 0, i; int res = 0, mean = 0, i;
@@ -609,7 +653,23 @@ int fpi_std_sq_dev(const unsigned char *buf, int size)
return res / 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 fpi_mean_sq_diff_norm(unsigned char *buf1, unsigned char *buf2, int size)
{ {
int res = 0, i; 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" #define FP_COMPONENT "poll"
#include "fp_internal.h" #include "fp_internal.h"
#include "fpi-poll.h"
#include <config.h> #include <config.h>
#include <errno.h> #include <errno.h>
@@ -32,6 +33,7 @@
/** /**
* SECTION:events * SECTION:events
* @title: Initialisation and events handling * @title: Initialisation and events handling
* @short_description: Initialisation and events handling functions
* *
* These functions are only applicable to users of libfprint's asynchronous * These functions are only applicable to users of libfprint's asynchronous
* API. * API.
@@ -63,6 +65,16 @@
* your main loop. * 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 /* this is a singly-linked list of pending timers, sorted with the timer that
* is expiring soonest at the head. */ * is expiring soonest at the head. */
static GSList *active_timers = NULL; static GSList *active_timers = NULL;
@@ -74,13 +86,15 @@ static fp_pollfd_removed_cb fd_removed_cb = NULL;
struct fpi_timeout { struct fpi_timeout {
struct timeval expiry; struct timeval expiry;
fpi_timeout_fn callback; fpi_timeout_fn callback;
struct fp_dev *dev;
void *data; void *data;
char *name;
}; };
static int timeout_sort_fn(gconstpointer _a, gconstpointer _b) static int timeout_sort_fn(gconstpointer _a, gconstpointer _b)
{ {
struct fpi_timeout *a = (struct fpi_timeout *) _a; fpi_timeout *a = (fpi_timeout *) _a;
struct fpi_timeout *b = (struct fpi_timeout *) _b; fpi_timeout *b = (fpi_timeout *) _b;
struct timeval *tv_a = &a->expiry; struct timeval *tv_a = &a->expiry;
struct timeval *tv_b = &b->expiry; struct timeval *tv_b = &b->expiry;
@@ -92,27 +106,78 @@ static int timeout_sort_fn(gconstpointer _a, gconstpointer _b)
return 0; 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 * saying that you'd like to have a function invoked at a certain time in
* the future. */ * the future.
struct fpi_timeout *fpi_timeout_add(unsigned int msec, fpi_timeout_fn callback, *
void *data) * 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 timespec ts;
struct timeval add_msec; struct timeval add_msec;
struct fpi_timeout *timeout; fpi_timeout *timeout;
int r; int r;
g_return_val_if_fail (dev != NULL, NULL);
fp_dbg("in %dms", msec); fp_dbg("in %dms", msec);
r = clock_gettime(CLOCK_MONOTONIC, &ts); r = clock_gettime(CLOCK_MONOTONIC, &ts);
if (r < 0) { if (r < 0) {
fp_err("failed to read monotonic clock, errno=%d", errno); fp_err("failed to read monotonic clock, errno=%d", errno);
BUG();
return NULL; return NULL;
} }
timeout = g_malloc(sizeof(*timeout)); timeout = g_new0(fpi_timeout, 1);
timeout->callback = callback; timeout->callback = callback;
timeout->dev = dev;
timeout->data = data; timeout->data = data;
TIMESPEC_TO_TIMEVAL(&timeout->expiry, &ts); 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; 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(); G_DEBUG_HERE();
active_timers = g_slist_remove(active_timers, timeout); 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 /* 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; *out_timeout = next_timeout;
if (timercmp(&tv, &next_timeout->expiry, >=)) { 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); timerclear(out);
} else { } else {
timersub(&next_timeout->expiry, &tv, out); 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; return 1;
@@ -177,9 +256,9 @@ static int get_next_timeout_expiry(struct timeval *out,
static void handle_timeout(struct fpi_timeout *timeout) static void handle_timeout(struct fpi_timeout *timeout)
{ {
G_DEBUG_HERE(); G_DEBUG_HERE();
timeout->callback(timeout->data); timeout->callback(timeout->dev, timeout->data);
active_timers = g_slist_remove(active_timers, timeout); active_timers = g_slist_remove(active_timers, timeout);
g_free(timeout); fpi_timeout_free(timeout);
} }
static int handle_timeouts(void) static int handle_timeouts(void)
@@ -263,7 +342,7 @@ API_EXPORTED int fp_handle_events(void)
/** /**
* fp_get_next_timeout: * 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 * 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) API_EXPORTED int fp_get_next_timeout(struct timeval *tv)
{ {
struct timeval fprint_timeout; struct timeval fprint_timeout = { 0, 0 };
struct timeval libusb_timeout; struct timeval libusb_timeout = { 0, 0 };
int r_fprint; int r_fprint;
int r_libusb; 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, /* if we have no pending timeouts and the same is true for libusb,
* indicate that we have no pending timouts */ * indicate that we have no pending timouts */
if (r_fprint == 0 && r_libusb == 0) if (r_fprint <= 0 && r_libusb <= 0)
return 0; return 0;
/* if fprint have no pending timeouts return libusb timeout */ /* if fprint have no pending timeouts return libusb timeout */
@@ -313,14 +392,16 @@ API_EXPORTED int fp_get_next_timeout(struct timeval *tv)
* *
* Returns: the number of pollfds in the resultant list, or negative on error. * Returns: the number of pollfds in the resultant list, or negative on error.
*/ */
API_EXPORTED size_t fp_get_pollfds(struct fp_pollfd **pollfds) API_EXPORTED ssize_t fp_get_pollfds(struct fp_pollfd **pollfds)
{ {
const struct libusb_pollfd **usbfds; const struct libusb_pollfd **usbfds;
const struct libusb_pollfd *usbfd; const struct libusb_pollfd *usbfd;
struct fp_pollfd *ret; struct fp_pollfd *ret;
size_t cnt = 0; ssize_t cnt = 0;
size_t i = 0; size_t i = 0;
g_return_val_if_fail (fpi_usb_ctx != NULL, -EIO);
usbfds = libusb_get_pollfds(fpi_usb_ctx); usbfds = libusb_get_pollfds(fpi_usb_ctx);
if (!usbfds) { if (!usbfds) {
*pollfds = NULL; *pollfds = NULL;
@@ -376,10 +457,29 @@ void fpi_poll_init(void)
void fpi_poll_exit(void) void fpi_poll_exit(void)
{ {
g_slist_free(active_timers); g_slist_free_full(active_timers, (GDestroyNotify) fpi_timeout_free);
active_timers = NULL; active_timers = NULL;
fd_added_cb = NULL; fd_added_cb = NULL;
fd_removed_cb = NULL; fd_removed_cb = NULL;
libusb_set_pollfd_notifiers(fpi_usb_ctx, NULL, NULL, 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" #define FP_COMPONENT "sync"
#include "fp_internal.h" #include "fp_internal.h"
#include "fpi-dev.h"
#include <config.h> #include <config.h>
#include <errno.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: * 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 * 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 * 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: * 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. * a fingerprint device.
*/ */
API_EXPORTED void fp_dev_close(struct fp_dev *dev) 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: * fp_enroll_finger_img:
* @dev: the device * @dev: the struct #fp_dev device
* @print_data: a location to return the resultant enrollment data from * @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 * @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 * 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) * Performs an enroll stage. See [Enrolling](libfprint-Devices-operations.html#enrolling)
* for an explanation of enroll stages. * for an explanation of enroll stages.
@@ -289,9 +290,9 @@ err:
/** /**
* fp_enroll_finger: * fp_enroll_finger:
* @dev: the device * @dev: the struct #fp_dev device
* @print_data: a location to return the resultant enrollment data from * @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) * Performs an enroll stage. See [Enrolling](libfprint-Devices-operations.html#enrolling)
* for an explanation of enroll stages. This function is just a shortcut to * 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: * 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_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 * @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 * 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 * 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 * 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 * call this function even on non-imaging devices, just don't expect them to
@@ -422,9 +423,9 @@ err:
/** /**
* fp_verify_finger: * 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_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 * 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 * function is just a shortcut to calling fp_verify_finger_img() with a NULL
@@ -440,6 +441,72 @@ API_EXPORTED int fp_verify_finger(struct fp_dev *dev,
return fp_verify_finger_img(dev, enrolled_print, NULL); return fp_verify_finger_img(dev, enrolled_print, NULL);
} }
struct sync_delete_data {
gboolean populated;
int result;
};
static void sync_delete_cb(struct fp_dev *dev, int result, void *user_data)
{
struct sync_delete_data *ddata = user_data;
ddata->result = result;
ddata->populated = TRUE;
}
/**
* fp_delete_finger:
* @dev: the struct #fp_dev device to perform the operation.
* @enrolled_data: the id need to delete on sensor. This id is
* returned in previously enrolled with a MIS device.
*
* Perform a delete data operation on sensor. When print data is stored on sensor,
* this function is needed when host deletes enrolled finger.
*
* Returns: negative code on error, otherwise a code from #fp_delete_result
*/
API_EXPORTED int fp_delete_finger(struct fp_dev *dev,
struct fp_print_data *enrolled_data)
{
struct sync_delete_data *ddata;
gboolean stopped = FALSE;
int r;
if (!enrolled_data) {
fp_err("no print given");
return -EINVAL;
}
if (!fp_dev_supports_print_data(dev, enrolled_data)) {
fp_err("print is not compatible with device");
return -EINVAL;
}
fp_dbg("to be handled by %s", dev->drv->name);
ddata = g_malloc0(sizeof(struct sync_delete_data));
r = fp_async_delete_finger(dev, enrolled_data, sync_delete_cb, ddata);
if (r < 0) {
fp_dbg("delete_finger error %d", r);
g_free(ddata);
return r;
}
while (!ddata->populated) {
r = fp_handle_events();
if (r < 0)
goto out;
}
r = ddata->result;
fp_dbg("delete_finger result %d", r);
out:
g_free(ddata);
return r;
}
struct sync_identify_data { struct sync_identify_data {
gboolean populated; gboolean populated;
int result; int result;
@@ -466,16 +533,16 @@ static void identify_stop_cb(struct fp_dev *dev, void *user_data)
/** /**
* fp_identify_finger_img: * 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 * @print_gallery: NULL-terminated array of pointers to the prints to
* identify against. Each one must have been previously enrolled with a device * 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 * @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 * 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 * @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 * 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 * Performs a new scan and attempts to identify the scanned finger against
* a collection of previously enrolled fingerprints. * a collection of previously enrolled fingerprints.
@@ -564,13 +631,13 @@ err:
/** /**
* fp_identify_finger: * 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 * @print_gallery: %NULL-terminated array of pointers to the prints to
* identify against. Each one must have been previously enrolled with a device * 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 * @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 * 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 * Performs a new scan and attempts to identify the scanned finger against a
* collection of previously enrolled fingerprints. This function is just a * collection of previously enrolled fingerprints. This function is just a
@@ -610,10 +677,10 @@ static void capture_stop_cb(struct fp_dev *dev, void *user_data)
} }
/** /**
* fp_dev_img_capture: * 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 * @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 * @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 * 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. * image provided by the device, you may wish to [standardize](libfprint-Image-operations.html#img_std) it.
@@ -627,7 +694,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 * 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 * @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, API_EXPORTED int fp_dev_img_capture(struct fp_dev *dev, int unconditional,
struct fp_img **img) 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" #include "fp_internal.h"
static const struct usb_id whitelist_id_table[] = { 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 */ /* Unsupported (for now) Validity Sensors finger print readers */
{ .vendor = 0x138a, .product = 0x0090 }, /* Found on e.g. Lenovo T460s */ { .vendor = 0x138a, .product = 0x0090 }, /* Found on e.g. Lenovo T460s */
{ .vendor = 0x138a, .product = 0x0091 }, { .vendor = 0x138a, .product = 0x0091 },

View File

@@ -25,15 +25,24 @@ extern "C" {
#endif #endif
#include <stdint.h> #include <stdint.h>
#include <stddef.h>
#include <unistd.h>
#include <sys/time.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__)) #define LIBFPRINT_DEPRECATED __attribute__((__deprecated__))
/** /**
* fp_dscv_dev: * fp_dscv_dev:
* *
* #fp_dscv_dev is an opaque structure type. You must access it using the * #fp_dscv_dev is an opaque structure type. You must access it using the
* functions below. * functions in this section.
*/ */
struct fp_dscv_dev; struct fp_dscv_dev;
@@ -41,7 +50,7 @@ struct fp_dscv_dev;
* fp_dscv_print: * fp_dscv_print:
* *
* #fp_dscv_print is an opaque structure type. You must access it using the * #fp_dscv_print is an opaque structure type. You must access it using the
* functions below. * functions in this section.
*/ */
struct fp_dscv_print; struct fp_dscv_print;
@@ -49,7 +58,7 @@ struct fp_dscv_print;
* fp_dev: * fp_dev:
* *
* #fp_dev is an opaque structure type. You must access it using the * #fp_dev is an opaque structure type. You must access it using the
* functions below. * functions in this section.
*/ */
struct fp_dev; struct fp_dev;
@@ -57,7 +66,7 @@ struct fp_dev;
* fp_driver: * fp_driver:
* *
* #fp_driver is an opaque structure type. You must access it using the * #fp_driver is an opaque structure type. You must access it using the
* functions below. * functions in this section.
*/ */
struct fp_driver; struct fp_driver;
@@ -65,7 +74,7 @@ struct fp_driver;
* fp_print_data: * fp_print_data:
* *
* #fp_print_data is an opaque structure type. You must access it using the * #fp_print_data is an opaque structure type. You must access it using the
* functions below. * functions in this section.
*/ */
struct fp_print_data; struct fp_print_data;
@@ -73,7 +82,7 @@ struct fp_print_data;
* fp_img: * fp_img:
* *
* #fp_img is an opaque structure type. You must access it using the * #fp_img is an opaque structure type. You must access it using the
* functions below. * functions in this section.
*/ */
struct fp_img; 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); const char *fp_driver_get_full_name(struct fp_driver *drv);
uint16_t fp_driver_get_driver_id(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); enum fp_scan_type fp_driver_get_scan_type(struct fp_driver *drv);
int fp_driver_supports_imaging(struct fp_driver *drv);
/* Device discovery */ /* Device discovery */
struct fp_dscv_dev **fp_discover_devs(void); 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: * 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_COMPLETE: Capture completed successfully, the capture data has been returned to the caller.
* @FP_CAPTURE_FAIL: Capture failed * @FP_CAPTURE_FAIL: Capture failed
* *
* Whether a capture failed or completed.
*/ */
enum fp_capture_result { enum fp_capture_result {
FP_CAPTURE_COMPLETE = 0, FP_CAPTURE_COMPLETE = 0,
@@ -258,19 +267,26 @@ int fp_verify_finger(struct fp_dev *dev,
struct fp_print_data *enrolled_print); struct fp_print_data *enrolled_print);
int fp_dev_supports_identification(struct fp_dev *dev); int fp_dev_supports_identification(struct fp_dev *dev);
int fp_dev_supports_data_in_sensor(struct fp_dev *dev);
int fp_identify_finger_img(struct fp_dev *dev, int fp_identify_finger_img(struct fp_dev *dev,
struct fp_print_data **print_gallery, size_t *match_offset, struct fp_print_data **print_gallery, size_t *match_offset,
struct fp_img **img); struct fp_img **img);
int fp_identify_finger(struct fp_dev *dev, int fp_identify_finger(struct fp_dev *dev,
struct fp_print_data **print_gallery, size_t *match_offset); struct fp_print_data **print_gallery, size_t *match_offset);
int fp_delete_finger(struct fp_dev *dev,
struct fp_print_data *enrolled_print);
/* Data handling */ /* Data handling */
int fp_print_data_load(struct fp_dev *dev, enum fp_finger finger, 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, int fp_print_data_from_dscv_print(struct fp_dscv_print *print,
struct fp_print_data **data) LIBFPRINT_DEPRECATED; 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_save(struct fp_print_data *data, enum fp_finger finger)
int fp_print_data_delete(struct fp_dev *dev, 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); 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); 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, struct fp_print_data *fp_print_data_from_data(unsigned char *buf,
@@ -284,7 +300,7 @@ uint32_t fp_print_data_get_devtype(struct fp_print_data *data);
* fp_minutia: * fp_minutia:
* *
* #fp_minutia is an opaque structure type. You must access it using the * #fp_minutia is an opaque structure type. You must access it using the
* functions below. * functions in this section.
*/ */
struct fp_minutia; struct fp_minutia;
@@ -295,6 +311,7 @@ int fp_img_save_to_file(struct fp_img *img, char *path);
void fp_img_standardize(struct fp_img *img); void fp_img_standardize(struct fp_img *img);
struct fp_img *fp_img_binarize(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); 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); void fp_img_free(struct fp_img *img);
/* Polling and timing */ /* Polling and timing */
@@ -304,17 +321,17 @@ void fp_img_free(struct fp_img *img);
* @fd: a file descriptor * @fd: a file descriptor
* @events: Event flags to poll for from `<poll.h>` * @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(). * for, as returned by fp_get_pollfds().
*/ */
struct fp_pollfd { struct fp_pollfd {
int fd; int fd;
short events; short int events;
}; };
int fp_handle_events_timeout(struct timeval *timeout); int fp_handle_events_timeout(struct timeval *timeout);
int fp_handle_events(void); int fp_handle_events(void);
size_t fp_get_pollfds(struct fp_pollfd **pollfds); ssize_t fp_get_pollfds(struct fp_pollfd **pollfds);
int fp_get_next_timeout(struct timeval *tv); int fp_get_next_timeout(struct timeval *tv);
/** /**
@@ -326,7 +343,7 @@ int fp_get_next_timeout(struct timeval *tv);
* event source is added. The @events argument is a flag as defined in * 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(). * `<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: * fp_pollfd_removed_cb:
@@ -348,7 +365,7 @@ void fp_set_debug(int level) LIBFPRINT_DEPRECATED;
/** /**
* fp_operation_stop_cb: * fp_operation_stop_cb:
* @dev: the #fp_dev device * @dev: the struct #fp_dev device
* @user_data: user data passed to the callback * @user_data: user data passed to the callback
* *
* Type definition for a function that will be called when fp_async_dev_close(), * Type definition for a function that will be called when fp_async_dev_close(),
@@ -359,7 +376,7 @@ typedef void (*fp_operation_stop_cb)(struct fp_dev *dev, void *user_data);
/** /**
* fp_img_operation_cb: * 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 * @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 * for fp_async_capture_start(), or a negative value on error
* @img: the captured #fp_img if capture or verification was successful * @img: the captured #fp_img if capture or verification was successful
@@ -373,7 +390,7 @@ typedef void (*fp_img_operation_cb)(struct fp_dev *dev, int result,
/** /**
* fp_dev_open_cb: * 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 * @status: 0 on success, or a negative value on error
* @user_data: user data passed to the callback * @user_data: user data passed to the callback
* *
@@ -390,14 +407,15 @@ void fp_async_dev_close(struct fp_dev *dev, fp_operation_stop_cb callback,
/** /**
* fp_enroll_stage_cb: * 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 * @result: a #fp_enroll_result on success, or a negative value on failure
* @print: the enrollment data from the final stage * @print: the enrollment data from the final stage
* @img: an #fp_img to free with fp_img_free() * @img: an #fp_img to free with fp_img_free()
* @user_data: user data passed to the callback * @user_data: user data passed to the callback
* *
* Type definition for a function that will be called when * 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, typedef void (*fp_enroll_stage_cb)(struct fp_dev *dev, int result,
struct fp_print_data *print, struct fp_img *img, void *user_data); struct fp_print_data *print, struct fp_img *img, void *user_data);
@@ -416,7 +434,7 @@ int fp_async_verify_stop(struct fp_dev *dev, fp_operation_stop_cb callback,
/** /**
* fp_identify_cb: * 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. * @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). * @match_offset: the array index of the matched gallery print (if any was found).
* Only valid if %FP_VERIFY_MATCH was returned. * Only valid if %FP_VERIFY_MATCH was returned.
@@ -438,6 +456,22 @@ int fp_async_capture_start(struct fp_dev *dev, int unconditional, fp_img_operati
int fp_async_capture_stop(struct fp_dev *dev, fp_operation_stop_cb callback, void *user_data); int fp_async_capture_stop(struct fp_dev *dev, fp_operation_stop_cb callback, void *user_data);
/**
* fp_delete_result:
* @FP_DELETE_COMPLETE: Delete completed successfully.
* @FP_DELETE_FAIL: Delete failed
*
*/
enum fp_delete_result {
FP_DELETE_COMPLETE = 0,
FP_DELETE_FAIL = 1,
};
typedef void (*fp_delete_cb)(struct fp_dev *dev, int status, void *user_data);
int fp_async_delete_finger(struct fp_dev *dev, struct fp_print_data *data, fp_delete_cb callback, void *user_data);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@@ -1,16 +1,29 @@
libfprint_sources = [ libfprint_sources = [
'fp_internal.h', 'fp_internal.h',
'nbis-helpers.h',
'drivers_api.h', 'drivers_api.h',
'async.c', 'fpi-async.c',
'core.c', 'fpi-async.h',
'data.c', 'fpi-assembling.c',
'drv.c', 'fpi-assembling.h',
'img.c', 'fpi-core.c',
'imgdev.c', 'fpi-core.h',
'poll.c', 'fpi-data.c',
'sync.c', 'fpi-data.h',
'assembling.c', 'fpi-dev.c',
'assembling.h', 'fpi-dev.h',
'fpi-dev-img.c',
'fpi-dev-img.h',
'fpi-img.c',
'fpi-img.h',
'fpi-log.h',
'fpi-ssm.c',
'fpi-ssm.h',
'fpi-sync.c',
'fpi-poll.h',
'fpi-poll.c',
'fpi-usb.h',
'fpi-usb.c',
'drivers/driver_ids.h', 'drivers/driver_ids.h',
] ]
@@ -30,14 +43,17 @@ nbis_sources = [
'nbis/bozorth3/bz_sort.c', 'nbis/bozorth3/bz_sort.c',
'nbis/mindtct/binar.c', 'nbis/mindtct/binar.c',
'nbis/mindtct/block.c', 'nbis/mindtct/block.c',
'nbis/mindtct/chaincod.c',
'nbis/mindtct/contour.c', 'nbis/mindtct/contour.c',
'nbis/mindtct/detect.c', 'nbis/mindtct/detect.c',
'nbis/mindtct/dft.c', 'nbis/mindtct/dft.c',
'nbis/mindtct/free.c', 'nbis/mindtct/free.c',
'nbis/mindtct/getmin.c',
'nbis/mindtct/globals.c', 'nbis/mindtct/globals.c',
'nbis/mindtct/imgutil.c', 'nbis/mindtct/imgutil.c',
'nbis/mindtct/init.c', 'nbis/mindtct/init.c',
'nbis/mindtct/line.c', 'nbis/mindtct/line.c',
'nbis/mindtct/link.c',
'nbis/mindtct/log.c', 'nbis/mindtct/log.c',
'nbis/mindtct/loop.c', 'nbis/mindtct/loop.c',
'nbis/mindtct/maps.c', 'nbis/mindtct/maps.c',
@@ -50,6 +66,7 @@ nbis_sources = [
'nbis/mindtct/shape.c', 'nbis/mindtct/shape.c',
'nbis/mindtct/sort.c', 'nbis/mindtct/sort.c',
'nbis/mindtct/util.c', 'nbis/mindtct/util.c',
'nbis/mindtct/xytreps.c',
] ]
aeslib = false aeslib = false
@@ -57,12 +74,13 @@ aesx660 = false
aes3k = false aes3k = false
drivers_sources = [] drivers_sources = []
drivers_cflags = [] drivers_cflags = []
foreach driver: drivers foreach driver: drivers
if driver == 'upekts' if driver == 'upekts'
drivers_sources += [ 'drivers/upekts.c' ] drivers_sources += [ 'drivers/upekts.c' ]
endif endif
if driver == 'upektc' if driver == 'upektc'
drivers_sources += [ 'drivers/upektc.c', 'drivers/upektc.h' ] drivers_sources += [ 'drivers/upektc.c', 'drivers/upektc.h', 'drivers/upek_proto.c', 'drivers/upek_proto.h' ]
endif endif
if driver == 'upeksonly' if driver == 'upeksonly'
drivers_sources += [ 'drivers/upeksonly.c', 'drivers/upeksonly.h' ] drivers_sources += [ 'drivers/upeksonly.c', 'drivers/upeksonly.h' ]
@@ -118,7 +136,7 @@ foreach driver: drivers
drivers_sources += [ 'drivers/vfs5011.c', 'drivers/vfs5011_proto.h' ] drivers_sources += [ 'drivers/vfs5011.c', 'drivers/vfs5011_proto.h' ]
endif endif
if driver == 'upektc_img' if driver == 'upektc_img'
drivers_sources += [ 'drivers/upektc_img.c', 'drivers/upektc_img.h' ] drivers_sources += [ 'drivers/upektc_img.c', 'drivers/upektc_img.h', 'drivers/upek_proto.c', 'drivers/upek_proto.h' ]
endif endif
if driver == 'etes603' if driver == 'etes603'
drivers_sources += [ 'drivers/etes603.c' ] drivers_sources += [ 'drivers/etes603.c' ]
@@ -129,10 +147,20 @@ foreach driver: drivers
if driver == 'elan' if driver == 'elan'
drivers_sources += [ 'drivers/elan.c', 'drivers/elan.h' ] drivers_sources += [ 'drivers/elan.c', 'drivers/elan.h' ]
endif endif
if driver == 'synaptics'
drivers_sources += [
'drivers/synaptics/synaptics.c',
'drivers/synaptics/bmkt.c',
'drivers/synaptics/util.c',
'drivers/synaptics/bmkt_message.c',
'drivers/synaptics/sensor.c',
'drivers/synaptics/usb_transport.c',
]
endif
endforeach endforeach
if aeslib if aeslib
drivers_sources += [ 'aeslib.c', 'aeslib.h' ] drivers_sources += [ 'drivers/aeslib.c', 'drivers/aeslib.h' ]
endif endif
if aesx660 if aesx660
drivers_sources += ['drivers/aesx660.c', 'drivers/aesx660.h' ] drivers_sources += ['drivers/aesx660.c', 'drivers/aesx660.h' ]
@@ -143,7 +171,7 @@ endif
other_sources = [] other_sources = []
if imaging_dep.found() if imaging_dep.found()
other_sources += [ 'pixman.c' ] other_sources += [ 'fpi-img-pixman.c' ]
endif endif
libfprint_sources += configure_file(input: 'empty_file', libfprint_sources += configure_file(input: 'empty_file',
@@ -163,6 +191,7 @@ libfprint_sources += configure_file(input: 'empty_file',
]) ])
deps = [ mathlib_dep, glib_dep, libusb_dep, nss_dep, imaging_dep ] deps = [ mathlib_dep, glib_dep, libusb_dep, nss_dep, imaging_dep ]
libfprint = library('fprint', libfprint = library('fprint',
libfprint_sources + drivers_sources + nbis_sources + other_sources, libfprint_sources + drivers_sources + nbis_sources + other_sources,
soversion: soversion, soversion: soversion,

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: License:
This software was developed at the National Institute of Standards and This software and/or related materials was developed at the National Institute
Technology (NIST) by employees of the Federal Government in the course of Standards and Technology (NIST) by employees of the Federal Government
of their official duties. Pursuant to title 17 Section 105 of the in the course of their official duties. Pursuant to title 17 Section 105
United States Code, this software is not subject to copyright protection of the United States Code, this software is not subject to copyright
and is in the public domain. NIST assumes no responsibility whatsoever for protection and is in the public domain.
its use by other parties, and makes no guarantees, expressed or implied,
about its quality, reliability, or any other characteristic.
Disclaimer: This software and/or related materials have been determined to be not subject
This software was developed to promote biometric standards and biometric to the EAR (see Part 734.3 of the EAR for exact details) because it is
technology testing for the Federal Government in accordance with the USA a publicly available technology and software, and is freely distributed
PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act. to any interested party with no licensing requirements. Therefore, it is
Specific hardware and software products identified in this software were used permissible to distribute this software as a free download from the internet.
in order to perform the software development. In no case does such
identification imply recommendation or endorsement by the National Institute Disclaimer:
of Standards and Technology, nor does it imply that the products and equipment This software and/or related materials was developed to promote biometric
identified are necessarily the best available for the purpose. 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 <stdio.h>
#include <bozorth.h> #include <bozorth.h>
static const int verbose_bozorth = 0;
static const int m1_xyt = 0;
/***********************************************************************/ /***********************************************************************/
void bz_comp( void bz_comp(
int npoints, /* INPUT: # of points */ int npoints, /* INPUT: # of points */
@@ -160,7 +149,7 @@ for ( k = 0; k < npoints - 1; k++ ) {
else { else {
double dz; double dz;
if ( m1_xyt ) if ( 0 )
dz = ( 180.0F / PI_SINGLE ) * atanf( (float) -dy / (float) dx ); dz = ( 180.0F / PI_SINGLE ) * atanf( (float) -dy / (float) dx );
else else
dz = ( 180.0F / PI_SINGLE ) * atanf( (float) dy / (float) dx ); 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 ) { if ( table_index == 19999 ) {
#ifndef NOVERBOSE #ifndef NOVERBOSE
if ( verbose_bozorth ) if ( 0 )
printf( "bz_comp(): breaking loop to avoid table overflow\n" ); printf( "bz_comp(): breaking loop to avoid table overflow\n" );
#endif #endif
goto COMP_END; goto COMP_END;
@@ -392,7 +381,7 @@ static int * rtp[ ROT_SIZE_1 ];
/* extern int * scolpt[ SCOLPT_SIZE ]; INPUT */ /* extern int * scolpt[ SCOLPT_SIZE ]; INPUT */
/* extern int * fcolpt[ FCOLPT_SIZE ]; INPUT */ /* extern int * fcolpt[ FCOLPT_SIZE ]; INPUT */
/* extern int colp[ COLP_SIZE_1 ][ COLP_SIZE_2 ]; OUTPUT */ /* extern int colp[ COLP_SIZE_1 ][ COLP_SIZE_2 ]; OUTPUT */
/* extern int verbose_bozorth; */ /* extern int 0; */
/* extern FILE * stderr; */ /* extern FILE * stderr; */
/* extern char * get_progname( void ); */ /* extern char * get_progname( void ); */
/* extern char * get_probe_filename( void ); */ /* extern char * get_probe_filename( void ); */
@@ -401,6 +390,7 @@ static int * rtp[ ROT_SIZE_1 ];
st = 1; st = 1;
edge_pair_index = 0; edge_pair_index = 0;
rotptr = &rot[0][0]; rotptr = &rot[0][0];
@@ -570,7 +560,7 @@ for ( k = 1; k < probe_ptrlist_len; k++ ) {
if ( edge_pair_index == 19999 ) { if ( edge_pair_index == 19999 ) {
#ifndef NOVERBOSE #ifndef NOVERBOSE
if ( verbose_bozorth ) if ( 0 )
fprintf( stderr, "%s: bz_match(): WARNING: list is full, breaking loop early [p=%s; g=%s]\n", 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() ); get_progname(), get_probe_filename(), get_gallery_filename() );
#endif #endif
@@ -652,13 +642,13 @@ int avv[ AVV_SIZE_1 ][ AVV_SIZE_2 ];
if ( pstruct->nrows < MIN_COMPUTABLE_BOZORTH_MINUTIAE ) { if ( pstruct->nrows < MIN_COMPUTABLE_BOZORTH_MINUTIAE ) {
#ifndef NOVERBOSE #ifndef NOVERBOSE
if ( gstruct->nrows < MIN_COMPUTABLE_BOZORTH_MINUTIAE ) { 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", 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(), get_progname(),
pstruct->nrows, gstruct->nrows, MIN_COMPUTABLE_BOZORTH_MINUTIAE, pstruct->nrows, gstruct->nrows, MIN_COMPUTABLE_BOZORTH_MINUTIAE,
get_probe_filename(), get_gallery_filename() ); get_probe_filename(), get_gallery_filename() );
} else { } 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", 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(), get_progname(),
pstruct->nrows, MIN_COMPUTABLE_BOZORTH_MINUTIAE, pstruct->nrows, MIN_COMPUTABLE_BOZORTH_MINUTIAE,
@@ -672,7 +662,7 @@ if ( pstruct->nrows < MIN_COMPUTABLE_BOZORTH_MINUTIAE ) {
if ( gstruct->nrows < MIN_COMPUTABLE_BOZORTH_MINUTIAE ) { if ( gstruct->nrows < MIN_COMPUTABLE_BOZORTH_MINUTIAE ) {
#ifndef NOVERBOSE #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", 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(), get_progname(),
gstruct->nrows, MIN_COMPUTABLE_BOZORTH_MINUTIAE, gstruct->nrows, MIN_COMPUTABLE_BOZORTH_MINUTIAE,
@@ -711,7 +701,6 @@ tp = 0;
p1 = 0; p1 = 0;
tot = 0; tot = 0;
ftt = 0; ftt = 0;
kx = 0;
match_score = 0; match_score = 0;
for ( k = 0; k < np - 1; k++ ) { for ( k = 0; k < np - 1; k++ ) {
@@ -765,7 +754,7 @@ for ( k = 0; k < np - 1; k++ ) {
} }
#ifndef NOVERBOSE #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] ); 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 #endif
@@ -827,7 +816,6 @@ for ( k = 0; k < np - 1; k++ ) {
l = 1;
t = np + 1; t = np + 1;
b = kq; b = kq;
@@ -1167,7 +1155,7 @@ for ( k = 0; k < np - 1; k++ ) {
if ( ll ) { if ( ll ) {
if ( m1_xyt ) if ( 0 )
fi = ( 180.0F / PI_SINGLE ) * atanf( (float) -jj / (float) ll ); fi = ( 180.0F / PI_SINGLE ) * atanf( (float) -jj / (float) ll );
else else
fi = ( 180.0F / PI_SINGLE ) * atanf( (float) jj / (float) ll ); fi = ( 180.0F / PI_SINGLE ) * atanf( (float) jj / (float) ll );
@@ -1187,7 +1175,7 @@ for ( k = 0; k < np - 1; k++ ) {
jj += 360; jj += 360;
} else { } else {
if ( m1_xyt ) { if ( 0 ) {
if ( jj > 0 ) if ( jj > 0 )
jj = -90; jj = -90;
else else
@@ -1204,7 +1192,7 @@ for ( k = 0; k < np - 1; k++ ) {
if ( kk ) { if ( kk ) {
if ( m1_xyt ) if ( 0 )
fi = ( 180.0F / PI_SINGLE ) * atanf( (float) -j / (float) kk ); fi = ( 180.0F / PI_SINGLE ) * atanf( (float) -j / (float) kk );
else else
fi = ( 180.0F / PI_SINGLE ) * atanf( (float) j / (float) kk ); fi = ( 180.0F / PI_SINGLE ) * atanf( (float) j / (float) kk );
@@ -1224,7 +1212,7 @@ for ( k = 0; k < np - 1; k++ ) {
j += 360; j += 360;
} else { } else {
if ( m1_xyt ) { if ( 0 ) {
if ( j > 0 ) if ( j > 0 )
j = -90; j = -90;
else else
@@ -1611,7 +1599,7 @@ if ( n ) {
notfound = 1; notfound = 1;
#ifndef NOVERBOSE #ifndef NOVERBOSE
if ( verbose_bozorth ) { if ( 0 ) {
int * llptr = lptr; int * llptr = lptr;
printf( "bz_sift(): n: looking for l=%d in [", l ); printf( "bz_sift(): n: looking for l=%d in [", l );
for ( i = 0; i < lim; i++ ) { for ( i = 0; i < lim; i++ ) {
@@ -1657,7 +1645,7 @@ if ( t ) {
notfound = 1; notfound = 1;
#ifndef NOVERBOSE #ifndef NOVERBOSE
if ( verbose_bozorth ) { if ( 0 ) {
int * llptr = lptr; int * llptr = lptr;
printf( "bz_sift(): t: looking for kz=%d in [", kz ); printf( "bz_sift(): t: looking for kz=%d in [", kz );
for ( i = 0; i < lim; i++ ) { 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: License:
This software was developed at the National Institute of Standards and This software and/or related materials was developed at the National Institute
Technology (NIST) by employees of the Federal Government in the course of Standards and Technology (NIST) by employees of the Federal Government
of their official duties. Pursuant to title 17 Section 105 of the in the course of their official duties. Pursuant to title 17 Section 105
United States Code, this software is not subject to copyright protection of the United States Code, this software is not subject to copyright
and is in the public domain. NIST assumes no responsibility whatsoever for protection and is in the public domain.
its use by other parties, and makes no guarantees, expressed or implied,
about its quality, reliability, or any other characteristic.
Disclaimer: This software and/or related materials have been determined to be not subject
This software was developed to promote biometric standards and biometric to the EAR (see Part 734.3 of the EAR for exact details) because it is
technology testing for the Federal Government in accordance with the USA a publicly available technology and software, and is freely distributed
PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act. to any interested party with no licensing requirements. Therefore, it is
Specific hardware and software products identified in this software were used permissible to distribute this software as a free download from the internet.
in order to perform the software development. In no case does such
identification imply recommendation or endorsement by the National Institute Disclaimer:
of Standards and Technology, nor does it imply that the products and equipment This software and/or related materials was developed to promote biometric
identified are necessarily the best available for the purpose. 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 */ /* 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: License:
This software was developed at the National Institute of Standards and This software and/or related materials was developed at the National Institute
Technology (NIST) by employees of the Federal Government in the course of Standards and Technology (NIST) by employees of the Federal Government
of their official duties. Pursuant to title 17 Section 105 of the in the course of their official duties. Pursuant to title 17 Section 105
United States Code, this software is not subject to copyright protection of the United States Code, this software is not subject to copyright
and is in the public domain. NIST assumes no responsibility whatsoever for protection and is in the public domain.
its use by other parties, and makes no guarantees, expressed or implied,
about its quality, reliability, or any other characteristic.
Disclaimer: This software and/or related materials have been determined to be not subject
This software was developed to promote biometric standards and biometric to the EAR (see Part 734.3 of the EAR for exact details) because it is
technology testing for the Federal Government in accordance with the USA a publicly available technology and software, and is freely distributed
PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act. to any interested party with no licensing requirements. Therefore, it is
Specific hardware and software products identified in this software were used permissible to distribute this software as a free download from the internet.
in order to perform the software development. In no case does such
identification imply recommendation or endorsement by the National Institute Disclaimer:
of Standards and Technology, nor does it imply that the products and equipment This software and/or related materials was developed to promote biometric
identified are necessarily the best available for the purpose. 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: License:
This software was developed at the National Institute of Standards and This software and/or related materials was developed at the National Institute
Technology (NIST) by employees of the Federal Government in the course of Standards and Technology (NIST) by employees of the Federal Government
of their official duties. Pursuant to title 17 Section 105 of the in the course of their official duties. Pursuant to title 17 Section 105
United States Code, this software is not subject to copyright protection of the United States Code, this software is not subject to copyright
and is in the public domain. NIST assumes no responsibility whatsoever for protection and is in the public domain.
its use by other parties, and makes no guarantees, expressed or implied,
about its quality, reliability, or any other characteristic.
Disclaimer: This software and/or related materials have been determined to be not subject
This software was developed to promote biometric standards and biometric to the EAR (see Part 734.3 of the EAR for exact details) because it is
technology testing for the Federal Government in accordance with the USA a publicly available technology and software, and is freely distributed
PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act. to any interested party with no licensing requirements. Therefore, it is
Specific hardware and software products identified in this software were used permissible to distribute this software as a free download from the internet.
in order to perform the software development. In no case does such
identification imply recommendation or endorsement by the National Institute Disclaimer:
of Standards and Technology, nor does it imply that the products and equipment This software and/or related materials was developed to promote biometric
identified are necessarily the best available for the purpose. 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() */ /* Globals used significantly by sift() */
/**************************************************************************/ /**************************************************************************/
int rq[ RQ_SIZE ] = {}; #ifdef TARGET_OS
int tq[ TQ_SIZE ] = {}; int rq[ RQ_SIZE ];
int zz[ ZZ_SIZE ] = {}; int tq[ TQ_SIZE ];
int zz[ ZZ_SIZE ];
int rx[ RX_SIZE ] = {}; int rx[ RX_SIZE ];
int mm[ MM_SIZE ] = {}; int mm[ MM_SIZE ];
int nn[ NN_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 cp[ CP_SIZE ];
int rp[ RP_SIZE ] = {}; int rp[ RP_SIZE ];
int rf[RF_SIZE_1][RF_SIZE_2] = {}; int rf[RF_SIZE_1][RF_SIZE_2];
int cf[CF_SIZE_1][CF_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: License:
This software was developed at the National Institute of Standards and This software and/or related materials was developed at the National Institute
Technology (NIST) by employees of the Federal Government in the course of Standards and Technology (NIST) by employees of the Federal Government
of their official duties. Pursuant to title 17 Section 105 of the in the course of their official duties. Pursuant to title 17 Section 105
United States Code, this software is not subject to copyright protection of the United States Code, this software is not subject to copyright
and is in the public domain. NIST assumes no responsibility whatsoever for protection and is in the public domain.
its use by other parties, and makes no guarantees, expressed or implied,
about its quality, reliability, or any other characteristic.
Disclaimer: This software and/or related materials have been determined to be not subject
This software was developed to promote biometric standards and biometric to the EAR (see Part 734.3 of the EAR for exact details) because it is
technology testing for the Federal Government in accordance with the USA a publicly available technology and software, and is freely distributed
PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act. to any interested party with no licensing requirements. Therefore, it is
Specific hardware and software products identified in this software were used permissible to distribute this software as a free download from the internet.
in order to perform the software development. In no case does such
identification imply recommendation or endorsement by the National Institute Disclaimer:
of Standards and Technology, nor does it imply that the products and equipment This software and/or related materials was developed to promote biometric
identified are necessarily the best available for the purpose. 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) MODIFICATIONS: Michael D. Garris (NIST)
Stan Janet (NIST) Stan Janet (NIST)
DATE: 09/21/2004 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 Contains routines responsible for supporting command line
processing, file and data input to, and output from the 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 <sys/time.h>
#include <bozorth.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; 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 ) 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 */ /* 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]. 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 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 "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; */ 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
#define C1 0 to be returned, the highest-quality minutiae are returned.
#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;
}
/***********************************************************************/ /***********************************************************************/
#ifdef PARALLEL_SEARCH #ifdef PARALLEL_SEARCH
@@ -617,13 +171,13 @@ tv.tv_usec = 0;
retval = select( fd+1, &rfds, NULL, NULL, &tv ); retval = select( fd+1, &rfds, NULL, NULL, &tv );
if ( retval < 0 ) { if ( retval < 0 ) {
perror( "select() failed" ); perror( "select() failed" );
return 0; return 0;
} }
if ( FD_ISSET( fd, &rfds ) ) { if ( FD_ISSET( fd, &rfds ) ) {
/*fprintf( stderr, "data is available now.\n" );*/ /*fprintf( stderr, "data is available now.\n" );*/
return 1; return 1;
} }
/* fprintf( stderr, "no data is available\n" ); */ /* fprintf( stderr, "no data is available\n" ); */

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