Compare commits

..

1 Commits

Author SHA1 Message Date
Bastien Nocera
35e8deba37 elan: Add ID for T-Bao TBook 12 Air reader (04f3:0c16)
Tested by Hans de Goede <hdegoede@redhat.com>
2018-06-18 18:07:44 +02:00
135 changed files with 8776 additions and 11468 deletions

View File

@@ -1,113 +0,0 @@
#!/usr/bin/python3
import argparse
import contextlib
import os
import shutil
import subprocess
import sys
def format_title(title):
box = {
'tl': '╔', 'tr': '╗', 'bl': '╚', 'br': '╝', 'h': '═', 'v': '║',
}
hline = box['h'] * (len(title) + 2)
return '\n'.join([
f"{box['tl']}{hline}{box['tr']}",
f"{box['v']} {title} {box['v']}",
f"{box['bl']}{hline}{box['br']}",
])
def rm_rf(path):
try:
shutil.rmtree(path)
except FileNotFoundError:
pass
def sanitize_path(name):
return name.replace('/', '-')
def get_current_revision():
revision = subprocess.check_output(['git', 'rev-parse', '--abbrev-ref', 'HEAD'],
encoding='utf-8').strip()
if revision == 'HEAD':
# This is a detached HEAD, get the commit hash
revision = subprocess.check_output(['git', 'rev-parse', 'HEAD']).strip().decode('utf-8')
return revision
@contextlib.contextmanager
def checkout_git_revision(revision):
current_revision = get_current_revision()
subprocess.check_call(['git', 'checkout', '-q', revision])
try:
yield
finally:
subprocess.check_call(['git', 'checkout', '-q', current_revision])
def build_install(revision):
build_dir = '_build'
dest_dir = os.path.abspath(sanitize_path(revision))
print(format_title(f'# Building and installing {revision} in {dest_dir}'),
end='\n\n', flush=True)
with checkout_git_revision(revision):
rm_rf(build_dir)
rm_rf(revision)
subprocess.check_call(['meson', build_dir,
'--prefix=/usr', '--libdir=lib',
'-Dx11-examples=false', '-Ddoc=false', '-Dgtk-examples=false'])
subprocess.check_call(['ninja', '-v', '-C', build_dir])
subprocess.check_call(['ninja', '-v', '-C', build_dir, 'install'],
env={'DESTDIR': dest_dir})
return dest_dir
def compare(old_tree, new_tree):
print(format_title(f'# Comparing the two ABIs'), end='\n\n', flush=True)
old_headers = os.path.join(old_tree, 'usr', 'include')
old_lib = os.path.join(old_tree, 'usr', 'lib', 'libfprint.so')
new_headers = os.path.join(new_tree, 'usr', 'include')
new_lib = os.path.join(new_tree, 'usr', 'lib', 'libfprint.so')
subprocess.check_call([
'abidiff', '--headers-dir1', old_headers, '--headers-dir2', new_headers,
'--drop-private-types', '--fail-no-debug-info', '--no-added-syms', old_lib, new_lib])
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument('old', help='the previous revision, considered the reference')
parser.add_argument('new', help='the new revision, to compare to the reference')
args = parser.parse_args()
if args.old == args.new:
print("Let's not waste time comparing something to itself")
sys.exit(0)
old_tree = build_install(args.old)
new_tree = build_install(args.new)
try:
compare(old_tree, new_tree)
except Exception:
sys.exit(1)
print(f'Hurray! {args.old} and {args.new} are ABI-compatible!')

View File

@@ -1,71 +1,20 @@
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 gtk3-devel flatpak-builder gcc gcc-c++ glibc-devel libX11-devel libXv-devel
BUNDLE: "org.freedesktop.libfprint.Demo.flatpak"
LAST_ABI_BREAK: "056ea541ddc97f5806cffbd99a12dc87e4da3546"
.build_one_driver_template: &build_one_driver
script:
- dnf update -y --nogpgcheck && dnf install -y --nogpgcheck $DEPENDENCIES
# Build with a driver that doesn't need imaging, or nss
- meson -Ddrivers=elan . _build
- ninja -C _build
- rm -rf _build/
.build_template: &build before_script:
script: - dnf update -y --nogpgcheck && dnf install -y --nogpgcheck $DEPENDENCIES
- dnf update -y --nogpgcheck && dnf install -y --nogpgcheck $DEPENDENCIES
# And build with everything
- meson -Ddrivers=all . _build
- ninja -C _build
- ninja -C _build install
.build_template: &check_abi
script:
- dnf update -y --nogpgcheck && dnf install -y --nogpgcheck $DEPENDENCIES doxygen libabigail git
- ./.ci/check-abi ${LAST_ABI_BREAK} $(git rev-parse HEAD)
build: build:
stage: build stage: build
<<: *build_one_driver script:
<<: *build - meson . _build
<<: *check_abi - ninja -C _build
- ninja -C _build install
.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

View File

@@ -3,29 +3,8 @@
## GLib ## GLib
Although the library uses GLib internally, libfprint is designed to provide Although the library uses GLib internally, libfprint is designed to provide
a completely neutral interface to its application users. So, the public a completely neutral interface to it's application users. So, the public
APIs should never return GLib data types. APIs should never return GLib data types or anything like that.
## License clarification
Although this library's license could allow for shims that hook up into
proprietary blobs to add driver support for some unsupported devices, the
intent of the original authors, and of current maintainers of the library,
was for this license to allow _integration into_ proprietary stacks, not
_integration of_ proprietary code in the library.
As such, no code to integrate proprietary drivers will be accepted in libfprint
upstream. Proprietary drivers would make it impossible to debug problems in
libfprint, as we wouldn't know what the proprietary driver does behind the
library's back. The closed source nature of drivers is usually used to hide
parts of the hardware setup, such as encryption keys, or protocols, in order
to protect the hardware's integrity. Unfortunately, this is only [security through
obscurity](https://en.wikipedia.org/wiki/Security_through_obscurity).
We however encourage potential contributors to take advantage of libfprint's
source availability to create such shims to make it easier to reverse-engineer
proprietary drivers in order to create new free software drivers, to the extent
permitted by local laws.
## Two-faced-ness ## Two-faced-ness

58
NEWS
View File

@@ -1,64 +1,6 @@
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.
2019-08-08: v1.0 release
* Library:
- Add guards to the public API and require GLib 2.50
- Deprecate print storage API
- Better documentation for fp_discover_devs()
- Remove unused internal fpi_timeout_cancel_for_dev()
- Remove state from fp_img_driver activate handler
- Bug fixes related to restarting a failed verification immediately
* Drivers:
- The Elan driver received a lot of bug fixes including a fix for a
hang when verifying prints with fprintd, quirks for some devices,
a memory leak fix and support for 04f3:0c42
- Fix a probable crash in all the AES drivers
- Add support for Lenovo Preferred Pro Keyboard (KUF1256) to vfs5011
- Prevent hang during enroll process in etes603 driver
- Fix possible integer overflow in uru4000
- Work-around SELinux AVC warnings when uru4000 driver starts
- Remove long-unmaintained and broken fdu2000 driver
* Tools/Examples:
- Fix examples not working due to an overly strict check
- Fix crash in GTK demo when there's no supported devices
- Disable GTK demo until we have a USB Flatpak portal
- Remove sleep() in enroll example which caused a crash in some drivers
- Add a simple storage implementation example
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 2018-06-12: v0.8.1 release
- Brown paperbag release to install the udev rules file in the correct - 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 directory if the udev pkg-config file doesn't have a trailing slash

10
README
View File

@@ -39,13 +39,3 @@ 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/

View File

@@ -1,3 +0,0 @@
This project and its community follow the [Freedesktop.org code of conduct]
[Freedesktop.org code of conduct]: https://www.freedesktop.org/wiki/CodeOfConduct/

View File

@@ -1,523 +0,0 @@
/*
* 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

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

View File

@@ -1,351 +0,0 @@
<?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>

View File

@@ -1,196 +0,0 @@
/*
* 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;
}

View File

@@ -1,27 +0,0 @@
/*
* 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

View File

@@ -1,30 +0,0 @@
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

@@ -1,28 +0,0 @@
<?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

@@ -1,10 +0,0 @@
[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

@@ -1,51 +0,0 @@
{
"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.

Before

Width:  |  Height:  |  Size: 24 KiB

View File

@@ -24,7 +24,7 @@
</part> </part>
<part> <part>
<title>Library API Documentation</title> <title>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,31 +36,11 @@
<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,9 +1,8 @@
<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
@@ -18,7 +17,6 @@ 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
@@ -34,18 +32,15 @@ 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
@@ -96,10 +91,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
@@ -112,7 +107,6 @@ 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
@@ -124,7 +118,6 @@ 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
@@ -136,136 +129,8 @@ 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>
<INCLUDE>fpi-log.h</INCLUDE> <FILE>poll</FILE>
<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,9 +6,6 @@ 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',
@@ -19,7 +16,6 @@ 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',
@@ -36,7 +32,6 @@ private_headers = [
'log.h', 'log.h',
'bz_array.h', 'bz_array.h',
'lfs.h', 'lfs.h',
'mytime.h',
] ]
html_images = [ html_images = [
@@ -59,6 +54,7 @@ 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

@@ -24,8 +24,6 @@
#include <libfprint/fprint.h> #include <libfprint/fprint.h>
#include "storage.h"
struct fp_dscv_dev *discover_device(struct fp_dscv_dev **discovered_devs) struct fp_dscv_dev *discover_device(struct fp_dscv_dev **discovered_devs)
{ {
struct fp_dscv_dev *ddev = discovered_devs[0]; struct fp_dscv_dev *ddev = discovered_devs[0];
@@ -47,7 +45,8 @@ 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);
@@ -144,7 +143,7 @@ int main(void)
if (!data) if (!data)
goto out_close; goto out_close;
r = print_data_save(data, RIGHT_INDEX); r = fp_print_data_save(data, RIGHT_INDEX);
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

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

View File

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

View File

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

View File

@@ -24,8 +24,6 @@
#include <libfprint/fprint.h> #include <libfprint/fprint.h>
#include "storage.h"
struct fp_dscv_dev *discover_device(struct fp_dscv_dev **discovered_devs) struct fp_dscv_dev *discover_device(struct fp_dscv_dev **discovered_devs)
{ {
struct fp_dscv_dev *ddev = discovered_devs[0]; struct fp_dscv_dev *ddev = discovered_devs[0];
@@ -119,8 +117,8 @@ 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");
data = print_data_load(dev, RIGHT_INDEX); r = fp_print_data_load(dev, RIGHT_INDEX, &data);
if (!data) { 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 "
"first?\n"); "first?\n");

View File

@@ -43,6 +43,7 @@ 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

@@ -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 "fpi-usb.h" #include "assembling.h"
#include "fpi-assembling.h"
#include "aeslib.h" #include "aeslib.h"
#define MAX_REGWRITES_PER_REQUEST 16 #define MAX_REGWRITES_PER_REQUEST 16
@@ -53,15 +53,12 @@ static void write_regv_trf_complete(struct libusb_transfer *transfer)
{ {
struct write_regv_data *wdata = transfer->user_data; struct write_regv_data *wdata = transfer->user_data;
if (transfer->status != LIBUSB_TRANSFER_COMPLETED) { if (transfer->status != LIBUSB_TRANSFER_COMPLETED)
wdata->callback(wdata->imgdev, -EIO, wdata->user_data); wdata->callback(wdata->imgdev, -EIO, wdata->user_data);
g_free(wdata); else if (transfer->length != transfer->actual_length)
} else if (transfer->length != transfer->actual_length) {
wdata->callback(wdata->imgdev, -EPROTO, wdata->user_data); wdata->callback(wdata->imgdev, -EPROTO, wdata->user_data);
g_free(wdata); else
} else {
continue_write_regv(wdata); continue_write_regv(wdata);
}
g_free(transfer->buffer); g_free(transfer->buffer);
libusb_free_transfer(transfer); libusb_free_transfer(transfer);
@@ -76,16 +73,21 @@ 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 = fpi_usb_alloc(); struct libusb_transfer *transfer = libusb_alloc_transfer(0);
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, FP_DEV(wdata->imgdev)->udev, EP_OUT, data, libusb_fill_bulk_transfer(transfer, 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) {
@@ -112,7 +114,6 @@ static void continue_write_regv(struct write_regv_data *wdata)
if (offset >= wdata->num_regs) { if (offset >= wdata->num_regs) {
fp_dbg("all registers written"); fp_dbg("all registers written");
wdata->callback(wdata->imgdev, 0, wdata->user_data); wdata->callback(wdata->imgdev, 0, wdata->user_data);
g_free(wdata);
return; return;
} }
if (wdata->regs[offset].reg) if (wdata->regs[offset].reg)
@@ -136,7 +137,6 @@ static void continue_write_regv(struct write_regv_data *wdata)
r = do_write_regv(wdata, upper_bound); r = do_write_regv(wdata, upper_bound);
if (r < 0) { if (r < 0) {
wdata->callback(wdata->imgdev, r, wdata->user_data); wdata->callback(wdata->imgdev, r, wdata->user_data);
g_free(wdata);
return; return;
} }
@@ -149,10 +149,8 @@ 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; struct write_regv_data *wdata = g_malloc(sizeof(*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;

View File

@@ -29,18 +29,7 @@
#include <libusb.h> #include <libusb.h>
#include <glib.h> #include <glib.h>
#include "fpi-assembling.h" #include "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,
@@ -163,22 +152,6 @@ 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)
{ {
@@ -252,22 +225,8 @@ 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 num_stripes) GSList *stripes, size_t stripes_len)
{ {
GSList *stripe; GSList *stripe;
struct fp_img *img; struct fp_img *img;
@@ -276,8 +235,7 @@ 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;
//FIXME g_return_if_fail BUG_ON(stripes_len == 0);
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 */
@@ -294,7 +252,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 < num_stripes); } while (i < stripes_len);
fp_dbg("height is %d", height); fp_dbg("height is %d", height);
@@ -336,7 +294,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 < num_stripes); } while (i < stripes_len);
return img; return img;
} }
@@ -365,7 +323,7 @@ static void median_filter(int *data, int size, int filtersize)
i1 = 0; i1 = 0;
if (i2 >= size) if (i2 >= size)
i2 = size-1; i2 = size-1;
memmove(sortbuf, data+i1, (i2-i1+1)*sizeof(int)); g_memmove(sortbuf, data+i1, (i2-i1+1)*sizeof(int));
g_qsort_with_data(sortbuf, i2-i1+1, sizeof(int), cmpint, NULL); g_qsort_with_data(sortbuf, i2-i1+1, sizeof(int), cmpint, NULL);
result[i] = sortbuf[(i2-i1+1)/2]; result[i] = sortbuf[(i2-i1+1)/2];
} }
@@ -392,45 +350,34 @@ 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:
* @ctx: #fpi_frame_asmbl_ctx - frame assembling context /* Rescale image to account for variable swiping speed */
* @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 num_lines) GSList *lines, size_t lines_len)
{ {
/* 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((num_lines / 2) * sizeof(int)); int *offsets = (int *)g_malloc0((lines_len / 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 (num_lines >= 2, NULL); g_return_val_if_fail (lines_len > 0, 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 < num_lines - 1) && row1; i += 2) { for (i = 0; (i < lines_len - 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, num_lines - 1); lastrow = min(i + ctx->max_search_offset, lines_len - 1);
row2 = g_slist_next(row1); row2 = g_slist_next(row1);
for (j = firstrow; j <= lastrow; j++) { for (j = firstrow; j <= lastrow; j++) {
@@ -450,13 +397,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, (num_lines / 2) - 1, ctx->median_filter_size); median_filter(offsets, (lines_len / 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 <= (num_lines / 2) - 1; i++) for (i = 0; i <= (lines_len / 2) - 1; i++)
fp_dbg("%d", offsets[i]); fp_dbg("%d", offsets[i]);
row1 = lines; row1 = lines;
for (i = 0; i < num_lines - 1; i++, row1 = g_slist_next(row1)) { for (i = 0; i < lines_len - 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;
@@ -480,7 +427,7 @@ out:
img->height = line_ind; img->height = line_ind;
img->width = ctx->line_width; img->width = ctx->line_width;
img->flags = FP_IMG_V_FLIPPED; img->flags = FP_IMG_V_FLIPPED;
memmove(img->data, output, ctx->line_width * line_ind); g_memmove(img->data, output, ctx->line_width * line_ind);
g_free(offsets); g_free(offsets);
g_free(output); g_free(output);
return img; return img;

65
libfprint/assembling.h Normal file
View File

@@ -0,0 +1,65 @@
/*
* 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

@@ -20,21 +20,11 @@
#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)
{ {
@@ -48,18 +38,11 @@ void fpi_drvcb_open_complete(struct fp_dev *dev, int status)
/** /**
* fp_async_dev_open: * fp_async_dev_open:
* @ddev: the struct #fp_dscv_dev discovered device to open * @ddev:
* @callback: the callback to call when the device has been opened * @callback:
* @user_data: user data to pass to the callback * @user_data
* *
* Opens and initialises a device. This is the function you call in order * Returns:
* 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)
@@ -70,7 +53,6 @@ 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;
@@ -111,7 +93,6 @@ 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);
@@ -120,12 +101,9 @@ void fpi_drvcb_close_complete(struct fp_dev *dev)
/** /**
* fp_async_dev_close: * fp_async_dev_close:
* @dev: the struct #fp_dev device * @dev:
* @callback: the callback to call when the device has been closed * @callback:
* @user_data: user data to pass to the callback * @user_data
*
* 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)
@@ -169,15 +147,11 @@ void fpi_drvcb_enroll_started(struct fp_dev *dev, int status)
/** /**
* fp_async_enroll_start: * fp_async_enroll_start:
* @dev: the struct #fp_dev device * @dev:
* @callback: the callback to call for each stage of the enrollment * @callback:
* @user_data: user data to pass to the callback * @user_data:
* *
* Starts an enrollment and calls @callback for each enrollment stage. * Returns:
* 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)
@@ -186,7 +160,6 @@ 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;
@@ -240,13 +213,11 @@ void fpi_drvcb_enroll_stopped(struct fp_dev *dev)
/** /**
* fp_async_enroll_stop: * fp_async_enroll_stop:
* @dev: the struct #fp_dev device * @dev:
* @callback: the callback to call when the enrollment has been cancelled * @callback:
* @user_data: user data to pass to the callback * @user_data:
* *
* Stops an ongoing enrollment started with fp_async_enroll_start(). * Returns:
*
* 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)
@@ -283,17 +254,12 @@ API_EXPORTED int fp_async_enroll_stop(struct fp_dev *dev,
/** /**
* fp_async_verify_start: * fp_async_verify_start:
* @dev: the struct #fp_dev device * @dev:
* @data: the print to verify against. Must have been previously * @data:
* enrolled with a device compatible to the device selected to perform the scan * @callback:
* @callback: the callback to call when the verification has finished * @user_data:
* @user_data: user data to pass to the callback
* *
* Starts a verification and calls @callback when the verification has * Returns:
* 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)
@@ -302,7 +268,6 @@ 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;
@@ -370,13 +335,11 @@ void fpi_drvcb_verify_stopped(struct fp_dev *dev)
/** /**
* fp_async_verify_stop: * fp_async_verify_stop:
* @dev: the struct #fp_dev device * @dev:
* @callback: the callback to call to finish a verification * @callback:
* @user_data: user data to pass to the callback * @user_data:
* *
* Finishes an ongoing verification started with fp_async_verify_start(). * Returns:
*
* 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)
@@ -387,21 +350,9 @@ API_EXPORTED int fp_async_verify_stop(struct fp_dev *dev,
g_return_val_if_fail(dev != NULL, -ENODEV); g_return_val_if_fail(dev != NULL, -ENODEV);
G_DEBUG_HERE();
if (dev->state == DEV_STATE_VERIFY_STOPPING) {
fp_dbg ("Already stopping verification, returning -EINPROGRESS");
return -EINPROGRESS;
}
if (dev->state == DEV_STATE_INITIALIZED) {
if (callback)
callback(dev, user_data);
return 0;
}
drv = dev->drv; drv = dev->drv;
G_DEBUG_HERE();
BUG_ON(dev->state != DEV_STATE_ERROR BUG_ON(dev->state != DEV_STATE_ERROR
&& dev->state != DEV_STATE_VERIFYING && dev->state != DEV_STATE_VERIFYING
&& dev->state != DEV_STATE_VERIFY_DONE); && dev->state != DEV_STATE_VERIFY_DONE);
@@ -429,17 +380,12 @@ API_EXPORTED int fp_async_verify_stop(struct fp_dev *dev,
/** /**
* fp_async_identify_start: * fp_async_identify_start:
* @dev: the struct #fp_dev device * @dev:
* @gallery: NULL-terminated array of pointers to the prints to * @gallery:
* identify against. Each one must have been previously enrolled with a device * @callback:
* compatible to the device selected to perform the scan * @user_data:
* @callback: the callback to call when the identification has finished
* @user_data: user data to pass to the callback
* *
* Performs a new scan and verifies it against a previously enrolled print. * Returns:
* 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)
@@ -448,7 +394,6 @@ 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;
@@ -506,13 +451,11 @@ void fpi_drvcb_report_identify_result(struct fp_dev *dev, int result,
/** /**
* fp_async_identify_stop: * fp_async_identify_stop:
* @dev: the struct #fp_dev device * @dev:
* @callback: the callback to call when the identification has stopped * @callback:
* @user_data: user data to pass to the callback * @user_data:
* *
* Stops an ongoing identification started with fp_async_identify_start(). * Returns:
*
* 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)
@@ -523,21 +466,9 @@ API_EXPORTED int fp_async_identify_stop(struct fp_dev *dev,
g_return_val_if_fail(dev != NULL, -ENODEV); g_return_val_if_fail(dev != NULL, -ENODEV);
G_DEBUG_HERE();
if (dev->state == DEV_STATE_IDENTIFY_STOPPING) {
fp_dbg ("Already stopping identification, returning -EINPROGRESS");
return -EINPROGRESS;
}
if (dev->state == DEV_STATE_INITIALIZED) {
if (callback)
callback(dev, user_data);
return 0;
}
drv = dev->drv; drv = dev->drv;
G_DEBUG_HERE();
BUG_ON(dev->state != DEV_STATE_IDENTIFYING BUG_ON(dev->state != DEV_STATE_IDENTIFYING
&& dev->state != DEV_STATE_IDENTIFY_DONE); && dev->state != DEV_STATE_IDENTIFY_DONE);
@@ -575,17 +506,12 @@ void fpi_drvcb_identify_stopped(struct fp_dev *dev)
/** /**
* fp_async_capture_start: * fp_async_capture_start:
* @dev: the struct #fp_dev device * @dev:
* @unconditional: whether to unconditionally capture an image, or to only capture when a finger is detected * @unconditional:
* @callback: the callback to call when the capture has finished * @callback:
* @user_data: user data to pass to the callback * @user_data:
* *
* Start the capture of an #fp_img from a device. When the @callback has been called, * Returns:
* 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)
@@ -594,7 +520,6 @@ 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;
@@ -611,7 +536,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 capture, error %d", r); fp_err("failed to start verification, error %d", r);
} }
return r; return r;
} }
@@ -661,13 +586,11 @@ void fpi_drvcb_capture_stopped(struct fp_dev *dev)
/** /**
* fp_async_capture_stop: * fp_async_capture_stop:
* @dev: the struct #fp_dev device * @dev:
* @callback: the callback to call when the capture has been stopped * @callback:
* @user_data: user data to pass to the callback * @user_data:
* *
* Stops an ongoing verification started with fp_async_capture_start(). * Returns:
*
* 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)
@@ -699,7 +622,7 @@ 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 capture"); fp_err("failed to stop verification");
dev->capture_stop_cb = NULL; dev->capture_stop_cb = NULL;
} }
return r; return r;

View File

@@ -33,7 +33,6 @@ 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
@@ -48,7 +47,6 @@ 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
@@ -63,7 +61,6 @@ 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
@@ -114,27 +111,6 @@ 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)
@@ -270,12 +246,10 @@ 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. Note that %NULL * entry point into finding a fingerprint reader to operate.
* is only returned on error. When there are no supported readers available,
* an empty list is returned instead.
* *
* Returns: a nul-terminated list of discovered devices or %NULL on error. * Returns: a %NULL-terminated list of discovered devices. Must be freed with
* Must be freed with fp_dscv_devs_free() after use. * 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)
{ {
@@ -285,7 +259,8 @@ API_EXPORTED struct fp_dscv_dev **fp_discover_devs(void)
int r; int r;
int i = 0; int i = 0;
g_return_val_if_fail (registered_drivers != NULL, NULL); if (registered_drivers == 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) {
@@ -346,8 +321,6 @@ 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;
} }
@@ -355,15 +328,10 @@ 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 a unique driver identifier for the underlying driver * Returns: the ID for the underlying driver for that device
* 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));
} }
@@ -377,8 +345,6 @@ 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;
} }
@@ -408,9 +374,6 @@ 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);
@@ -431,9 +394,6 @@ 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);
} }
@@ -457,9 +417,6 @@ 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;
@@ -485,9 +442,6 @@ 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"
@@ -500,7 +454,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 struct #fp_dev device * @dev: the device
* *
* Get the #fp_driver for a fingerprint device. * Get the #fp_driver for a fingerprint device.
* *
@@ -508,14 +462,12 @@ 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 struct #fp_dev device * @dev: the 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.
@@ -524,14 +476,12 @@ 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 struct #fp_dev device * @dev: the device
* *
* Gets the [devtype](advanced-topics.html#device-types) for a device. * Gets the [devtype](advanced-topics.html#device-types) for a device.
* *
@@ -539,14 +489,12 @@ 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 struct #fp_dev device * @dev: the 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.
@@ -556,9 +504,6 @@ 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);
@@ -566,7 +511,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 struct #fp_dev device * @dev: the 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
@@ -579,13 +524,54 @@ 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
@@ -596,8 +582,6 @@ API_EXPORTED int fp_dev_supports_dscv_print(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;
} }
@@ -611,8 +595,6 @@ 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;
} }
@@ -626,8 +608,6 @@ 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;
} }
@@ -641,34 +621,19 @@ 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)
{ {
g_return_val_if_fail(drv, 0); if (dev->drv->type != DRIVER_IMAGING)
return NULL;
return drv->capture_start != NULL; return dev->priv;
} }
/** /**
* fp_dev_supports_imaging: * fp_dev_supports_imaging:
* @dev: the struct #fp_dev device * @dev: the fingerprint 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
@@ -681,14 +646,12 @@ API_EXPORTED int fp_driver_supports_imaging(struct fp_driver *drv)
*/ */
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 struct #fp_dev device * @dev: the fingerprint 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
@@ -698,14 +661,12 @@ 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_get_img_width: * fp_dev_get_img_width:
* @dev: the struct #fp_dev device * @dev: the fingerprint 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
@@ -717,19 +678,18 @@ 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)
{ {
g_return_val_if_fail(dev, -1); struct fp_img_dev *imgdev = dev_to_img_dev(dev);
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(dev->img_dev); return fpi_imgdev_get_img_width(imgdev);
} }
/** /**
* fp_dev_get_img_height: * fp_dev_get_img_height:
* @dev: the struct #fp_dev device * @dev: the fingerprint 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
@@ -741,14 +701,13 @@ 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)
{ {
g_return_val_if_fail(dev, -1); struct fp_img_dev *imgdev = dev_to_img_dev(dev);
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(dev->img_dev); return fpi_imgdev_get_img_height(imgdev);
} }
/** /**

View File

@@ -32,23 +32,9 @@
#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
@@ -56,25 +42,12 @@ struct fpi_print_data_item_fp2 {
* *
* 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. Storage needs to be handled by the API user by using the * except in RAM. For the simple scenarios, libfprint provides a simple API
* fp_print_data_get_data() and fp_print_data_from_data(). This API allows * for you to save and load the stored prints referring to a single user in
* to convert print data into byte strings, and to reconstruct stored prints * their home directory. For more advanced users, libfprint provides APIs for
* you to convert print data to a byte string, and to reconstruct stored prints
* 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;
@@ -133,7 +106,7 @@ static struct fp_print_data *print_data_new(uint16_t driver_id,
return data; return data;
} }
static void fpi_print_data_item_free(struct fp_print_data_item *item) void fpi_print_data_item_free(struct fp_print_data_item *item)
{ {
g_free(item); g_free(item);
} }
@@ -152,19 +125,6 @@ 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
@@ -214,7 +174,7 @@ API_EXPORTED size_t fp_print_data_get_data(struct fp_print_data *data,
item = list_item->data; item = list_item->data;
out_item = (struct fpi_print_data_item_fp2 *)buf; out_item = (struct fpi_print_data_item_fp2 *)buf;
out_item->length = GUINT32_TO_LE(item->length); out_item->length = GUINT32_TO_LE(item->length);
/* FIXME: fp_print_data_item->data content is not endianness agnostic */ /* FIXME: fp_print_data_item->data content is not endianess agnostic */
memcpy(out_item->data, item->data, item->length); memcpy(out_item->data, item->data, item->length);
buf += sizeof(*out_item); buf += sizeof(*out_item);
buf += item->length; buf += item->length;
@@ -236,7 +196,7 @@ static struct fp_print_data *fpi_print_data_from_fp1_data(unsigned char *buf,
data = print_data_new(GUINT16_FROM_LE(raw->driver_id), data = print_data_new(GUINT16_FROM_LE(raw->driver_id),
GUINT32_FROM_LE(raw->devtype), raw->data_type); GUINT32_FROM_LE(raw->devtype), raw->data_type);
item = fpi_print_data_item_new(print_data_len); item = fpi_print_data_item_new(print_data_len);
/* FIXME: fp_print_data->data content is not endianness agnostic */ /* FIXME: fp_print_data->data content is not endianess agnostic */
memcpy(item->data, raw->data, print_data_len); memcpy(item->data, raw->data, print_data_len);
data->prints = g_slist_prepend(data->prints, item); data->prints = g_slist_prepend(data->prints, item);
@@ -272,7 +232,7 @@ static struct fp_print_data *fpi_print_data_from_fp2_data(unsigned char *buf,
total_data_len -= item_len; total_data_len -= item_len;
item = fpi_print_data_item_new(item_len); item = fpi_print_data_item_new(item_len);
/* FIXME: fp_print_data->data content is not endianness agnostic */ /* FIXME: fp_print_data->data content is not endianess agnostic */
memcpy(item->data, raw_item->data, item_len); memcpy(item->data, raw_item->data, item_len);
data->prints = g_slist_prepend(data->prints, item); data->prints = g_slist_prepend(data->prints, item);
@@ -369,10 +329,6 @@ 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)
@@ -398,7 +354,6 @@ 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;
@@ -485,16 +440,12 @@ 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 = NULL; struct fp_print_data *fdata;
int r; int r;
if (!base_store) if (!base_store)
@@ -524,10 +475,6 @@ 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)
@@ -613,7 +560,6 @@ 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
@@ -749,7 +695,9 @@ 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;
GPtrArray *array; unsigned int tmplist_len;
struct fp_dscv_print **list;
unsigned int i;
if (!base_store) if (!base_store)
storage_setup(); storage_setup();
@@ -784,17 +732,15 @@ API_EXPORTED struct fp_dscv_print **fp_discover_prints(void)
} }
g_dir_close(dir); g_dir_close(dir);
tmplist_len = g_slist_length(tmplist);
if (tmplist == NULL) list = g_malloc(sizeof(*list) * (tmplist_len + 1));
return NULL; elem = tmplist;
for (i = 0; i < tmplist_len; i++, elem = g_slist_next(elem))
array = g_ptr_array_new(); list[i] = elem->data;
for (elem = tmplist; elem != NULL; elem = elem->next) list[tmplist_len] = NULL; /* NULL-terminate */
g_ptr_array_add(array, elem->data);
g_ptr_array_add(array, NULL);
g_slist_free(tmplist); g_slist_free(tmplist);
return (struct fp_dscv_print **) g_ptr_array_free(array, FALSE); return list;
} }
/** /**

View File

@@ -44,9 +44,6 @@ 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
@@ -104,12 +101,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)
{ {
fpi_ssm *ssm = transfer->user_data; struct fpi_ssm *ssm = transfer->user_data;
if (transfer->status != LIBUSB_TRANSFER_COMPLETED) if (transfer->status != LIBUSB_TRANSFER_COMPLETED)
fpi_ssm_mark_failed(ssm, -EIO); fpi_ssm_mark_aborted(ssm, -EIO);
else if (transfer->length != transfer->actual_length) else if (transfer->length != transfer->actual_length)
fpi_ssm_mark_failed(ssm, -EPROTO); fpi_ssm_mark_aborted(ssm, -EPROTO);
else else
fpi_ssm_next_state(ssm); fpi_ssm_next_state(ssm);
@@ -120,22 +117,29 @@ 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)
{ {
fpi_ssm *ssm = user_data; struct 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_failed(ssm, result); fpi_ssm_mark_aborted(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(fpi_ssm *ssm, struct fp_dev *dev, size_t bytes) static void generic_read_ignore_data(struct fpi_ssm *ssm, size_t bytes)
{ {
struct libusb_transfer *transfer = fpi_usb_alloc(); struct libusb_transfer *transfer = libusb_alloc_transfer(0);
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);
@@ -143,7 +147,7 @@ static void generic_read_ignore_data(fpi_ssm *ssm, struct fp_dev *dev, size_t by
if (r < 0) { if (r < 0) {
g_free(data); g_free(data);
libusb_free_transfer(transfer); libusb_free_transfer(transfer);
fpi_ssm_mark_failed(ssm, r); fpi_ssm_mark_aborted(ssm, r);
} }
} }
@@ -222,9 +226,14 @@ static void finger_det_reqs_cb(struct fp_img_dev *dev, int result, void *user_da
return; return;
} }
transfer = fpi_usb_alloc(); transfer = libusb_alloc_transfer(0);
data = g_malloc(FINGER_DETECTION_LEN); if (!transfer) {
libusb_fill_bulk_transfer(transfer, fpi_dev_get_usb_dev(FP_DEV(dev)), EP_IN, data, FINGER_DETECTION_LEN, fpi_imgdev_session_error(dev, -ENOMEM);
return;
}
data = g_malloc(19);
libusb_fill_bulk_transfer(transfer, fpi_imgdev_get_usb_dev(dev), EP_IN, data, 19,
finger_det_data_cb, dev, BULK_TIMEOUT); finger_det_data_cb, dev, BULK_TIMEOUT);
r = libusb_submit_transfer(transfer); r = libusb_submit_transfer(transfer);
@@ -238,7 +247,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 = FP_INSTANCE_DATA(FP_DEV(dev)); struct aes1610_dev *aesdev = fpi_imgdev_get_user_data(dev);
if (aesdev->deactivating) { if (aesdev->deactivating) {
complete_deactivation(dev); complete_deactivation(dev);
@@ -404,7 +413,7 @@ static unsigned char list_BD_values[10] = {
/* /*
* Adjust the gain according to the histogram data * Adjust the gain according to the histogram data
* 0xbd, 0xbe, 0x29 and 0x2A registers are affected * 0xbd, 0xbe, 0x29 and 0x2A registers are affected
* Returns 0 if no problem occurred * Returns 0 if no problem occured
* TODO: This is a basic support for gain. It needs testing/tweaking. */ * TODO: This is a basic support for gain. It needs testing/tweaking. */
static int adjust_gain(unsigned char *buffer, int status) static int adjust_gain(unsigned char *buffer, int status)
{ {
@@ -412,7 +421,7 @@ static int adjust_gain(unsigned char *buffer, int status)
static int pos_list_BE = 0; static int pos_list_BE = 0;
static int pos_list_BD = 0; static int pos_list_BD = 0;
// This is the first adjustment (we begin acquisition) // This is the first adjustement (we begin acquisition)
// We adjust strip_scan_reqs for future strips and capture_reqs that is sent just after this step // We adjust strip_scan_reqs for future strips and capture_reqs that is sent just after this step
if (status == GAIN_STATUS_FIRST) { if (status == GAIN_STATUS_FIRST) {
if (buffer[1] > 0x78) { // maximum gain needed if (buffer[1] > 0x78) { // maximum gain needed
@@ -534,7 +543,7 @@ static void restore_gain(void)
/* capture SM movement: /* capture SM movement:
* request and read strip, * request and read strip,
* jump back to request UNLESS there's no finger, in which case exit SM, * jump back to request UNLESS theres no finger, in which case exit SM,
* report lack of finger presence, and move to finger detection */ * report lack of finger presence, and move to finger detection */
enum capture_states { enum capture_states {
@@ -548,17 +557,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;
fpi_ssm *ssm = transfer->user_data; struct 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 = FP_INSTANCE_DATA(FP_DEV(dev)); struct aes1610_dev *aesdev = fpi_imgdev_get_user_data(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_failed(ssm, -EIO); fpi_ssm_mark_aborted(ssm, -EIO);
goto out; goto out;
} else if (transfer->length != transfer->actual_length) { } else if (transfer->length != transfer->actual_length) {
fpi_ssm_mark_failed(ssm, -EPROTO); fpi_ssm_mark_aborted(ssm, -EPROTO);
goto out; goto out;
} }
@@ -585,7 +594,7 @@ static void capture_read_strip_cb(struct libusb_transfer *transfer)
} }
if (sum < 0) { if (sum < 0) {
fpi_ssm_mark_failed(ssm, sum); fpi_ssm_mark_aborted(ssm, sum);
goto out; goto out;
} }
fp_dbg("sum=%d", sum); fp_dbg("sum=%d", sum);
@@ -634,10 +643,10 @@ out:
libusb_free_transfer(transfer); libusb_free_transfer(transfer);
} }
static void capture_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) static void capture_run_state(struct fpi_ssm *ssm)
{ {
struct fp_img_dev *dev = user_data; struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct aes1610_dev *aesdev = FP_INSTANCE_DATA(_dev); struct aes1610_dev *aesdev = fpi_imgdev_get_user_data(dev);
int r; int r;
switch (fpi_ssm_get_cur_state(ssm)) { switch (fpi_ssm_get_cur_state(ssm)) {
@@ -648,7 +657,7 @@ static void capture_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data
break; break;
case CAPTURE_READ_DATA: case CAPTURE_READ_DATA:
fp_dbg("read data"); fp_dbg("read data");
generic_read_ignore_data(ssm, _dev, STRIP_CAPTURE_LEN); generic_read_ignore_data(ssm, 665);
break; break;
case CAPTURE_REQUEST_STRIP: case CAPTURE_REQUEST_STRIP:
fp_dbg("request strip"); fp_dbg("request strip");
@@ -659,27 +668,32 @@ static void capture_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data
generic_write_regv_cb, ssm); generic_write_regv_cb, ssm);
break; break;
case CAPTURE_READ_STRIP: ; case CAPTURE_READ_STRIP: ;
struct libusb_transfer *transfer = fpi_usb_alloc(); struct libusb_transfer *transfer = libusb_alloc_transfer(0);
unsigned char *data; unsigned char *data;
data = g_malloc(STRIP_CAPTURE_LEN); if (!transfer) {
libusb_fill_bulk_transfer(transfer, fpi_dev_get_usb_dev(FP_DEV(dev)), EP_IN, data, STRIP_CAPTURE_LEN, fpi_ssm_mark_aborted(ssm, -ENOMEM);
break;
}
data = g_malloc(665);
libusb_fill_bulk_transfer(transfer, fpi_imgdev_get_usb_dev(dev), EP_IN, data, 665,
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_failed(ssm, r); fpi_ssm_mark_aborted(ssm, r);
} }
break; break;
}; };
} }
static void capture_sm_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) static void capture_sm_complete(struct fpi_ssm *ssm)
{ {
struct fp_img_dev *dev = user_data; struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct aes1610_dev *aesdev = FP_INSTANCE_DATA(_dev); struct aes1610_dev *aesdev = fpi_imgdev_get_user_data(dev);
G_DEBUG_HERE(); G_DEBUG_HERE();
if (aesdev->deactivating) if (aesdev->deactivating)
@@ -693,16 +707,17 @@ static void capture_sm_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_da
static void start_capture(struct fp_img_dev *dev) static void start_capture(struct fp_img_dev *dev)
{ {
struct aes1610_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev)); struct aes1610_dev *aesdev = fpi_imgdev_get_user_data(dev);
fpi_ssm *ssm; struct fpi_ssm *ssm;
if (aesdev->deactivating) { if (aesdev->deactivating) {
complete_deactivation(dev); complete_deactivation(dev);
return; return;
} }
ssm = fpi_ssm_new(FP_DEV(dev), capture_run_state, CAPTURE_NUM_STATES, dev); ssm = fpi_ssm_new(fpi_imgdev_get_dev(dev), capture_run_state, CAPTURE_NUM_STATES);
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);
} }
@@ -723,12 +738,12 @@ enum activate_states {
ACTIVATE_NUM_STATES, ACTIVATE_NUM_STATES,
}; };
static void activate_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) static void activate_run_state(struct fpi_ssm *ssm)
{ {
struct fp_img_dev *dev = user_data; struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
/* activation on aes1610 seems much more straightforward compared to aes2501 */ /* activation on aes1610 seems much more straightforward compared to aes2501 */
/* verify there's anything missing here */ /* verify theres anything missing here */
switch (fpi_ssm_get_cur_state(ssm)) { switch (fpi_ssm_get_cur_state(ssm)) {
case WRITE_INIT: case WRITE_INIT:
fp_dbg("write init"); fp_dbg("write init");
@@ -738,9 +753,9 @@ static void activate_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_dat
} }
/* jump to finger detection */ /* jump to finger detection */
static void activate_sm_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) static void activate_sm_complete(struct fpi_ssm *ssm)
{ {
struct fp_img_dev *dev = user_data; struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
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));
@@ -749,11 +764,12 @@ static void activate_sm_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_d
fpi_ssm_free(ssm); fpi_ssm_free(ssm);
} }
static int dev_activate(struct fp_img_dev *dev) static int dev_activate(struct fp_img_dev *dev, enum fp_imgdev_state state)
{ {
struct aes1610_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev)); struct aes1610_dev *aesdev = fpi_imgdev_get_user_data(dev);
fpi_ssm *ssm = fpi_ssm_new(FP_DEV(dev), activate_run_state, struct fpi_ssm *ssm = fpi_ssm_new(fpi_imgdev_get_dev(dev), activate_run_state,
ACTIVATE_NUM_STATES, dev); ACTIVATE_NUM_STATES);
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;
@@ -761,7 +777,7 @@ static int dev_activate(struct fp_img_dev *dev)
static void dev_deactivate(struct fp_img_dev *dev) static void dev_deactivate(struct fp_img_dev *dev)
{ {
struct aes1610_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev)); struct aes1610_dev *aesdev = fpi_imgdev_get_user_data(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;
@@ -769,7 +785,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 = FP_INSTANCE_DATA(FP_DEV(dev)); struct aes1610_dev *aesdev = fpi_imgdev_get_user_data(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.
@@ -789,14 +805,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_dev_get_usb_dev(FP_DEV(dev)), 0); r = libusb_claim_interface(fpi_imgdev_get_usb_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));
fp_dev_set_instance_data(FP_DEV(dev), aesdev); fpi_imgdev_set_user_data(dev, aesdev);
fpi_imgdev_open_complete(dev, 0); fpi_imgdev_open_complete(dev, 0);
return 0; return 0;
} }
@@ -804,9 +820,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 = FP_INSTANCE_DATA(FP_DEV(dev)); aesdev = fpi_imgdev_get_user_data(dev);
g_free(aesdev); g_free(aesdev);
libusb_release_interface(fpi_dev_get_usb_dev(FP_DEV(dev)), 0); libusb_release_interface(fpi_imgdev_get_usb_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_dev_get_usb_dev(FP_DEV(dev)), 0); r = libusb_claim_interface(fpi_imgdev_get_usb_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));
fp_dev_set_instance_data(FP_DEV(dev), aesdev); fpi_imgdev_set_user_data(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 = FP_INSTANCE_DATA(FP_DEV(dev)); struct aesX660_dev *aesdev = fpi_imgdev_get_user_data(dev);
g_free(aesdev->buffer); g_free(aesdev->buffer);
g_free(aesdev); g_free(aesdev);
libusb_release_interface(fpi_dev_get_usb_dev(FP_DEV(dev)), 0); libusb_release_interface(fpi_imgdev_get_usb_dev(dev), 0);
fpi_imgdev_close_complete(dev); fpi_imgdev_close_complete(dev);
} }

View File

@@ -36,11 +36,6 @@ 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
@@ -88,12 +83,9 @@ 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 = user_data; struct aes2501_read_regs *rdata = transfer->user_data;
unsigned char *retdata = NULL; unsigned char *retdata = NULL;
int r; int r;
@@ -108,12 +100,14 @@ 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;
fpi_usb_transfer *transfer; struct libusb_transfer *transfer;
unsigned char *data; unsigned char *data;
int r; int r;
@@ -121,18 +115,20 @@ 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;
data = g_malloc(READ_REGS_LEN); transfer = libusb_alloc_transfer(0);
transfer = fpi_usb_fill_bulk_transfer(FP_DEV(dev), if (!transfer) {
NULL, result = -ENOMEM;
EP_IN, goto err;
data, }
READ_REGS_LEN,
read_regs_data_cb,
rdata,
BULK_TIMEOUT);
r = fpi_usb_submit_transfer(transfer); data = g_malloc(126);
libusb_fill_bulk_transfer(transfer, fpi_imgdev_get_usb_dev(dev), EP_IN, data, 126,
read_regs_data_cb, rdata, BULK_TIMEOUT);
r = libusb_submit_transfer(transfer);
if (r < 0) { if (r < 0) {
g_free(data);
libusb_free_transfer(transfer);
result = -EIO; result = -EIO;
goto err; goto err;
} }
@@ -184,48 +180,53 @@ 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)
{ {
fpi_ssm *ssm = user_data; struct 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_failed(ssm, result); fpi_ssm_mark_aborted(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_failed(ssm, -EIO); fpi_ssm_mark_aborted(ssm, -EIO);
else if (transfer->length != transfer->actual_length) else if (transfer->length != transfer->actual_length)
fpi_ssm_mark_failed(ssm, -EPROTO); fpi_ssm_mark_aborted(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(fpi_ssm *ssm, struct fp_dev *dev, size_t bytes) static void generic_read_ignore_data(struct fpi_ssm *ssm, size_t bytes)
{ {
fpi_usb_transfer *transfer; struct libusb_transfer *transfer = libusb_alloc_transfer(0);
unsigned char *data; unsigned char *data;
struct fp_dev *dev = fpi_ssm_get_dev(ssm);
int r; int r;
data = g_malloc(bytes); if (!transfer) {
transfer = fpi_usb_fill_bulk_transfer(dev, fpi_ssm_mark_aborted(ssm, -ENOMEM);
ssm, return;
EP_IN, }
data,
bytes,
generic_ignore_data_cb,
NULL,
BULK_TIMEOUT);
r = fpi_usb_submit_transfer(transfer); data = g_malloc(bytes);
if (r < 0) libusb_fill_bulk_transfer(transfer, fpi_dev_get_usb_dev(dev), EP_IN, data, bytes,
fpi_ssm_mark_failed(ssm, r); generic_ignore_data_cb, ssm, BULK_TIMEOUT);
r = libusb_submit_transfer(transfer);
if (r < 0) {
g_free(data);
libusb_free_transfer(transfer);
fpi_ssm_mark_aborted(ssm, r);
}
} }
/****** IMAGE PROCESSING ******/ /****** IMAGE PROCESSING ******/
@@ -281,22 +282,19 @@ 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 = FP_IMG_DEV(_dev); struct fp_img_dev *dev = transfer->user_data;
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);
return; goto out;
} 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);
return; goto out;
} }
/* examine histogram to determine finger presence */ /* examine histogram to determine finger presence */
@@ -310,12 +308,16 @@ 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)
{ {
fpi_usb_transfer *transfer; struct libusb_transfer *transfer;
unsigned char *data; unsigned char *data;
int r; int r;
@@ -324,24 +326,27 @@ static void finger_det_reqs_cb(struct fp_img_dev *dev, int result,
return; return;
} }
data = g_malloc(FINGER_DETECTION_LEN); transfer = libusb_alloc_transfer(0);
transfer = fpi_usb_fill_bulk_transfer(FP_DEV(dev), if (!transfer) {
NULL, fpi_imgdev_session_error(dev, -ENOMEM);
EP_IN, return;
data, }
FINGER_DETECTION_LEN,
finger_det_data_cb,
NULL,
BULK_TIMEOUT);
r = fpi_usb_submit_transfer(transfer); data = g_malloc(20);
if (r < 0) libusb_fill_bulk_transfer(transfer, fpi_imgdev_get_usb_dev(dev), EP_IN, data, 20,
finger_det_data_cb, dev, BULK_TIMEOUT);
r = libusb_submit_transfer(transfer);
if (r < 0) {
g_free(data);
libusb_free_transfer(transfer);
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 = FP_INSTANCE_DATA(FP_DEV(dev)); struct aes2501_dev *aesdev = fpi_imgdev_get_user_data(dev);
G_DEBUG_HERE(); G_DEBUG_HERE();
if (aesdev->deactivating) { if (aesdev->deactivating) {
@@ -415,7 +420,7 @@ static struct aes_regwrite strip_scan_reqs[] = {
/* capture SM movement: /* capture SM movement:
* write reqs and read data 1 + 2, * write reqs and read data 1 + 2,
* request and read strip, * request and read strip,
* jump back to request UNLESS there's no finger, in which case exit SM, * jump back to request UNLESS theres no finger, in which case exit SM,
* report lack of finger presence, and move to finger detection */ * report lack of finger presence, and move to finger detection */
enum capture_states { enum capture_states {
@@ -428,37 +433,35 @@ 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 fp_img_dev *dev = FP_IMG_DEV(_dev); struct fpi_ssm *ssm = transfer->user_data;
struct aes2501_dev *aesdev = FP_INSTANCE_DATA(_dev); struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
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_failed(ssm, -EIO); fpi_ssm_mark_aborted(ssm, -EIO);
return; goto out;
} else if (transfer->length != transfer->actual_length) { } else if (transfer->length != transfer->actual_length) {
fpi_ssm_mark_failed(ssm, -EPROTO); fpi_ssm_mark_aborted(ssm, -EPROTO);
return; goto out;
} }
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_failed(ssm, threshold); fpi_ssm_mark_aborted(ssm, threshold);
return; goto out;
} }
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_failed(ssm, sum); fpi_ssm_mark_aborted(ssm, sum);
return; goto out;
} }
fp_dbg("sum=%d", sum); fp_dbg("sum=%d", sum);
@@ -511,12 +514,16 @@ 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(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) static void capture_run_state(struct fpi_ssm *ssm)
{ {
struct fp_img_dev *dev = user_data; 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);
int r; int r;
switch (fpi_ssm_get_cur_state(ssm)) { switch (fpi_ssm_get_cur_state(ssm)) {
@@ -525,14 +532,14 @@ static void capture_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data
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, _dev, READ_REGS_RESP_LEN); generic_read_ignore_data(ssm, 159);
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, _dev, READ_REGS_RESP_LEN); generic_read_ignore_data(ssm, 159);
break; break;
case CAPTURE_REQUEST_STRIP: case CAPTURE_REQUEST_STRIP:
if (aesdev->deactivating) if (aesdev->deactivating)
@@ -542,30 +549,32 @@ static void capture_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data
generic_write_regv_cb, ssm); generic_write_regv_cb, ssm);
break; break;
case CAPTURE_READ_STRIP: ; case CAPTURE_READ_STRIP: ;
fpi_usb_transfer *transfer; struct libusb_transfer *transfer = libusb_alloc_transfer(0);
unsigned char *data; unsigned char *data;
data = g_malloc(STRIP_CAPTURE_LEN); if (!transfer) {
transfer = fpi_usb_fill_bulk_transfer(FP_DEV(dev), fpi_ssm_mark_aborted(ssm, -ENOMEM);
ssm, break;
EP_IN, }
data,
STRIP_CAPTURE_LEN,
capture_read_strip_cb,
NULL,
BULK_TIMEOUT);
r = fpi_usb_submit_transfer(transfer); data = g_malloc(1705);
if (r < 0) libusb_fill_bulk_transfer(transfer, fpi_imgdev_get_usb_dev(dev), EP_IN, data, 1705,
fpi_ssm_mark_failed(ssm, r); capture_read_strip_cb, ssm, BULK_TIMEOUT);
r = libusb_submit_transfer(transfer);
if (r < 0) {
g_free(data);
libusb_free_transfer(transfer);
fpi_ssm_mark_aborted(ssm, r);
}
break; break;
}; };
} }
static void capture_sm_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) static void capture_sm_complete(struct fpi_ssm *ssm)
{ {
struct fp_img_dev *dev = user_data; 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);
G_DEBUG_HERE(); G_DEBUG_HERE();
if (aesdev->deactivating) if (aesdev->deactivating)
@@ -579,8 +588,8 @@ static void capture_sm_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_da
static void start_capture(struct fp_img_dev *dev) static void start_capture(struct fp_img_dev *dev)
{ {
struct aes2501_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev)); struct aes2501_dev *aesdev = fpi_imgdev_get_user_data(dev);
fpi_ssm *ssm; struct fpi_ssm *ssm;
if (aesdev->deactivating) { if (aesdev->deactivating) {
complete_deactivation(dev); complete_deactivation(dev);
@@ -590,8 +599,9 @@ 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(FP_DEV(dev), capture_run_state, CAPTURE_NUM_STATES, dev); ssm = fpi_ssm_new(fpi_imgdev_get_dev(dev), capture_run_state, CAPTURE_NUM_STATES);
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);
} }
@@ -703,11 +713,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)
{ {
fpi_ssm *ssm = user_data; struct fpi_ssm *ssm = user_data;
struct aes2501_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev)); struct aes2501_dev *aesdev = fpi_imgdev_get_user_data(dev);
if (status != 0) { if (status != 0) {
fpi_ssm_mark_failed(ssm, status); fpi_ssm_mark_aborted(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)
@@ -720,16 +730,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)
{ {
fpi_ssm *ssm = user_data; struct 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_failed(ssm, result); fpi_ssm_mark_aborted(ssm, result);
} }
static void activate_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) static void activate_run_state(struct fpi_ssm *ssm)
{ {
struct fp_img_dev *dev = user_data; struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
/* 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
@@ -757,7 +767,7 @@ static void activate_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_dat
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, _dev, FINGER_DETECTION_LEN); generic_read_ignore_data(ssm, 20);
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),
@@ -781,9 +791,9 @@ static void activate_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_dat
} }
} }
static void activate_sm_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) static void activate_sm_complete(struct fpi_ssm *ssm)
{ {
struct fp_img_dev *dev = user_data; struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
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));
@@ -792,11 +802,12 @@ static void activate_sm_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_d
fpi_ssm_free(ssm); fpi_ssm_free(ssm);
} }
static int dev_activate(struct fp_img_dev *dev) static int dev_activate(struct fp_img_dev *dev, enum fp_imgdev_state state)
{ {
struct aes2501_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev)); struct aes2501_dev *aesdev = fpi_imgdev_get_user_data(dev);
fpi_ssm *ssm = fpi_ssm_new(FP_DEV(dev), activate_run_state, struct fpi_ssm *ssm = fpi_ssm_new(fpi_imgdev_get_dev(dev), activate_run_state,
ACTIVATE_NUM_STATES, dev); ACTIVATE_NUM_STATES);
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;
@@ -804,7 +815,7 @@ static int dev_activate(struct fp_img_dev *dev)
static void dev_deactivate(struct fp_img_dev *dev) static void dev_deactivate(struct fp_img_dev *dev)
{ {
struct aes2501_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev)); struct aes2501_dev *aesdev = fpi_imgdev_get_user_data(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;
@@ -812,7 +823,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 = FP_INSTANCE_DATA(FP_DEV(dev)); struct aes2501_dev *aesdev = fpi_imgdev_get_user_data(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.
@@ -831,23 +842,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_dev_get_usb_dev(FP_DEV(dev)), 0); r = libusb_claim_interface(fpi_imgdev_get_usb_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));
fp_dev_set_instance_data(FP_DEV(dev), aesdev); fpi_imgdev_set_user_data(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 = FP_INSTANCE_DATA(FP_DEV(dev)); struct aes2501_dev *aesdev = fpi_imgdev_get_user_data(dev);
g_free(aesdev); g_free(aesdev);
libusb_release_interface(fpi_dev_get_usb_dev(FP_DEV(dev)), 0); libusb_release_interface(fpi_imgdev_get_usb_dev(dev), 0);
fpi_imgdev_close_complete(dev); fpi_imgdev_close_complete(dev);
} }

View File

@@ -109,7 +109,7 @@ enum aes2501_mesure_drive {
/* Select (1=square | 0=sine) wave drive during measure */ /* Select (1=square | 0=sine) wave drive during measure */
#define AES2501_MEASDRV_SQUARE 0x20 #define AES2501_MEASDRV_SQUARE 0x20
/* 0 = use measure drive setting, 1 = when sine wave is selected */ /* 0 = use mesure drive setting, 1 = when sine wave is selected */
#define AES2501_MEASDRV_MEASURE_SQUARE 0x10 #define AES2501_MEASDRV_MEASURE_SQUARE 0x10
enum aes2501_measure_freq { enum aes2501_measure_freq {

View File

@@ -125,10 +125,15 @@ static void finger_det_reqs_cb(struct libusb_transfer *t)
goto exit_free_transfer; goto exit_free_transfer;
} }
transfer = fpi_usb_alloc(); transfer = libusb_alloc_transfer(0);
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_dev_get_usb_dev(FP_DEV(dev)), EP_IN, data, AES2550_EP_IN_BUF_SIZE, libusb_fill_bulk_transfer(transfer, fpi_imgdev_get_usb_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);
@@ -144,7 +149,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 = FP_INSTANCE_DATA(FP_DEV(dev)); struct aes2550_dev *aesdev = fpi_imgdev_get_user_data(dev);
struct libusb_transfer *transfer; struct libusb_transfer *transfer;
G_DEBUG_HERE(); G_DEBUG_HERE();
@@ -153,8 +158,12 @@ static void start_finger_detection(struct fp_img_dev *dev)
return; return;
} }
transfer = fpi_usb_alloc(); transfer = libusb_alloc_transfer(0);
libusb_fill_bulk_transfer(transfer, fpi_dev_get_usb_dev(FP_DEV(dev)), EP_OUT, finger_det_reqs, if (!transfer) {
fpi_imgdev_session_error(dev, -ENOMEM);
return;
}
libusb_fill_bulk_transfer(transfer, fpi_imgdev_get_usb_dev(dev), EP_OUT, finger_det_reqs,
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) {
@@ -191,10 +200,11 @@ enum capture_states {
}; };
/* Returns number of processed bytes */ /* Returns number of processed bytes */
static int process_strip_data(fpi_ssm *ssm, struct fp_img_dev *dev, unsigned char *data) static int process_strip_data(struct fpi_ssm *ssm, unsigned char *data)
{ {
unsigned char *stripdata; unsigned char *stripdata;
struct aes2550_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev)); struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct aes2550_dev *aesdev = fpi_imgdev_get_user_data(dev);
struct fpi_frame *stripe; struct fpi_frame *stripe;
int len; int len;
@@ -221,22 +231,22 @@ static int process_strip_data(fpi_ssm *ssm, struct fp_img_dev *dev, unsigned cha
static void capture_reqs_cb(struct libusb_transfer *transfer) static void capture_reqs_cb(struct libusb_transfer *transfer)
{ {
fpi_ssm *ssm = transfer->user_data; struct 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_failed(ssm, -EIO); fpi_ssm_mark_aborted(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)
{ {
fpi_ssm *ssm = transfer->user_data; struct 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 = FP_INSTANCE_DATA(FP_DEV(dev)); struct aes2550_dev *aesdev = fpi_imgdev_get_user_data(dev);
if ((transfer->status == LIBUSB_TRANSFER_COMPLETED) && if ((transfer->status == LIBUSB_TRANSFER_COMPLETED) &&
(transfer->length == transfer->actual_length) && (transfer->length == transfer->actual_length) &&
@@ -255,22 +265,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_failed(ssm, -EIO); fpi_ssm_mark_aborted(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)
{ {
fpi_ssm *ssm = transfer->user_data; struct 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 = FP_INSTANCE_DATA(FP_DEV(dev)); struct aes2550_dev *aesdev = fpi_imgdev_get_user_data(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_failed(ssm, -EIO); fpi_ssm_mark_aborted(ssm, -EIO);
goto out; goto out;
} }
@@ -280,10 +290,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, dev, data); r = process_strip_data(ssm, 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_failed(ssm, -EPROTO); fpi_ssm_mark_aborted(ssm, -EPROTO);
goto out; goto out;
} }
aesdev->heartbeat_cnt = 0; aesdev->heartbeat_cnt = 0;
@@ -313,62 +323,73 @@ out:
libusb_free_transfer(transfer); libusb_free_transfer(transfer);
} }
static void capture_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) static void capture_run_state(struct fpi_ssm *ssm)
{ {
struct fp_img_dev *dev = user_data; struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
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 = fpi_usb_alloc(); struct libusb_transfer *transfer = libusb_alloc_transfer(0);
if (!transfer) {
libusb_fill_bulk_transfer(transfer, fpi_dev_get_usb_dev(FP_DEV(dev)), EP_OUT, capture_reqs, fpi_ssm_mark_aborted(ssm, -ENOMEM);
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_failed(ssm, -ENOMEM); fpi_ssm_mark_aborted(ssm, -ENOMEM);
} }
} }
break; break;
case CAPTURE_READ_DATA: case CAPTURE_READ_DATA:
{ {
struct libusb_transfer *transfer = fpi_usb_alloc(); struct libusb_transfer *transfer = libusb_alloc_transfer(0);
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_dev_get_usb_dev(FP_DEV(dev)), EP_IN, data, AES2550_EP_IN_BUF_SIZE, libusb_fill_bulk_transfer(transfer, fpi_imgdev_get_usb_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_failed(ssm, r); fpi_ssm_mark_aborted(ssm, r);
} }
} }
break; break;
case CAPTURE_SET_IDLE: case CAPTURE_SET_IDLE:
{ {
struct libusb_transfer *transfer = fpi_usb_alloc(); struct libusb_transfer *transfer = libusb_alloc_transfer(0);
if (!transfer) {
libusb_fill_bulk_transfer(transfer, fpi_dev_get_usb_dev(FP_DEV(dev)), EP_OUT, capture_set_idle_reqs, fpi_ssm_mark_aborted(ssm, -ENOMEM);
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_failed(ssm, -ENOMEM); fpi_ssm_mark_aborted(ssm, -ENOMEM);
} }
} }
break; break;
}; };
} }
static void capture_sm_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) static void capture_sm_complete(struct fpi_ssm *ssm)
{ {
struct fp_img_dev *dev = user_data; struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct aes2550_dev *aesdev = FP_INSTANCE_DATA(_dev); struct aes2550_dev *aesdev = fpi_imgdev_get_user_data(dev);
fp_dbg("Capture completed"); fp_dbg("Capture completed");
if (aesdev->deactivating) if (aesdev->deactivating)
@@ -382,8 +403,8 @@ static void capture_sm_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_da
static void start_capture(struct fp_img_dev *dev) static void start_capture(struct fp_img_dev *dev)
{ {
struct aes2550_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev)); struct aes2550_dev *aesdev = fpi_imgdev_get_user_data(dev);
fpi_ssm *ssm; struct fpi_ssm *ssm;
if (aesdev->deactivating) { if (aesdev->deactivating) {
complete_deactivation(dev); complete_deactivation(dev);
@@ -391,8 +412,9 @@ static void start_capture(struct fp_img_dev *dev)
} }
aesdev->heartbeat_cnt = 0; aesdev->heartbeat_cnt = 0;
ssm = fpi_ssm_new(FP_DEV(dev), capture_run_state, CAPTURE_NUM_STATES, dev); ssm = fpi_ssm_new(fpi_imgdev_get_dev(dev), capture_run_state, CAPTURE_NUM_STATES);
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);
} }
@@ -422,117 +444,133 @@ enum activate_states {
static void init_reqs_cb(struct libusb_transfer *transfer) static void init_reqs_cb(struct libusb_transfer *transfer)
{ {
fpi_ssm *ssm = transfer->user_data; struct 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_failed(ssm, -EIO); fpi_ssm_mark_aborted(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)
{ {
fpi_ssm *ssm = transfer->user_data; struct 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_failed(ssm, -EIO); fpi_ssm_mark_aborted(ssm, -EIO);
} }
g_free(transfer->buffer); g_free(transfer->buffer);
libusb_free_transfer(transfer); libusb_free_transfer(transfer);
} }
/* TODO: use calibration table, datasheet is rather terse on that /* TODO: use calibration table, datasheet is rather terse on that
* need more info for implementation */ * 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)
{ {
fpi_ssm *ssm = transfer->user_data; struct 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_failed(ssm, -EIO); fpi_ssm_mark_aborted(ssm, -EIO);
} }
g_free(transfer->buffer); g_free(transfer->buffer);
libusb_free_transfer(transfer); libusb_free_transfer(transfer);
} }
static void activate_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) static void activate_run_state(struct fpi_ssm *ssm)
{ {
struct fp_img_dev *dev = user_data; struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
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 = fpi_usb_alloc(); struct libusb_transfer *transfer = libusb_alloc_transfer(0);
if (!transfer) {
libusb_fill_bulk_transfer(transfer, fpi_dev_get_usb_dev(FP_DEV(dev)), EP_OUT, init_reqs, fpi_ssm_mark_aborted(ssm, -ENOMEM);
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_failed(ssm, -ENOMEM); fpi_ssm_mark_aborted(ssm, -ENOMEM);
} }
} }
break; break;
case READ_DATA: case READ_DATA:
{ {
struct libusb_transfer *transfer = fpi_usb_alloc(); struct libusb_transfer *transfer = libusb_alloc_transfer(0);
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_dev_get_usb_dev(FP_DEV(dev)), EP_IN, data, AES2550_EP_IN_BUF_SIZE, libusb_fill_bulk_transfer(transfer, fpi_imgdev_get_usb_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_failed(ssm, r); fpi_ssm_mark_aborted(ssm, r);
} }
} }
break; break;
case CALIBRATE: case CALIBRATE:
{ {
struct libusb_transfer *transfer = fpi_usb_alloc(); struct libusb_transfer *transfer = libusb_alloc_transfer(0);
if (!transfer) {
libusb_fill_bulk_transfer(transfer, fpi_dev_get_usb_dev(FP_DEV(dev)), EP_OUT, calibrate_reqs, fpi_ssm_mark_aborted(ssm, -ENOMEM);
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_failed(ssm, -ENOMEM); fpi_ssm_mark_aborted(ssm, -ENOMEM);
} }
} }
break; break;
case READ_CALIB_TABLE: case READ_CALIB_TABLE:
{ {
struct libusb_transfer *transfer = fpi_usb_alloc(); struct libusb_transfer *transfer = libusb_alloc_transfer(0);
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_dev_get_usb_dev(FP_DEV(dev)), EP_IN, data, AES2550_EP_IN_BUF_SIZE, libusb_fill_bulk_transfer(transfer, fpi_imgdev_get_usb_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_failed(ssm, r); fpi_ssm_mark_aborted(ssm, r);
} }
} }
break; break;
} }
} }
static void activate_sm_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) static void activate_sm_complete(struct fpi_ssm *ssm)
{ {
struct fp_img_dev *dev = user_data; struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
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));
@@ -541,24 +579,25 @@ static void activate_sm_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_d
fpi_ssm_free(ssm); fpi_ssm_free(ssm);
} }
static int dev_activate(struct fp_img_dev *dev) static int dev_activate(struct fp_img_dev *dev, enum fp_imgdev_state state)
{ {
fpi_ssm *ssm = fpi_ssm_new(FP_DEV(dev), activate_run_state, struct fpi_ssm *ssm = fpi_ssm_new(fpi_imgdev_get_dev(dev), activate_run_state,
ACTIVATE_NUM_STATES, dev); ACTIVATE_NUM_STATES);
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 = FP_INSTANCE_DATA(FP_DEV(dev)); struct aes2550_dev *aesdev = fpi_imgdev_get_user_data(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 = FP_INSTANCE_DATA(FP_DEV(dev)); struct aes2550_dev *aesdev = fpi_imgdev_get_user_data(dev);
G_DEBUG_HERE(); G_DEBUG_HERE();
aesdev->deactivating = FALSE; aesdev->deactivating = FALSE;
@@ -574,14 +613,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_dev_get_usb_dev(FP_DEV(dev)), 0); r = libusb_claim_interface(fpi_imgdev_get_usb_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));
fp_dev_set_instance_data(FP_DEV(dev), aes2550_dev); fpi_imgdev_set_user_data(dev, aes2550_dev);
fpi_imgdev_open_complete(dev, 0); fpi_imgdev_open_complete(dev, 0);
return 0; return 0;
} }
@@ -589,9 +628,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 = FP_INSTANCE_DATA(FP_DEV(dev)); aesdev = fpi_imgdev_get_user_data(dev);
g_free(aesdev); g_free(aesdev);
libusb_release_interface(fpi_dev_get_usb_dev(FP_DEV(dev)), 0); libusb_release_interface(fpi_imgdev_get_usb_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_dev_get_usb_dev(FP_DEV(dev)), 0); r = libusb_claim_interface(fpi_imgdev_get_usb_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));
fp_dev_set_instance_data(FP_DEV(dev), aesdev); fpi_imgdev_set_user_data(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 = FP_INSTANCE_DATA(FP_DEV(dev)); aesdev = fpi_imgdev_get_user_data(dev);
g_free(aesdev->buffer); g_free(aesdev->buffer);
g_free(aesdev); g_free(aesdev);
libusb_release_interface(fpi_dev_get_usb_dev(FP_DEV(dev)), 0); libusb_release_interface(fpi_imgdev_get_usb_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_dev_get_usb_dev(FP_DEV(dev)), 0); r = libusb_claim_interface(fpi_imgdev_get_usb_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));
fp_dev_set_instance_data(FP_DEV(dev), aesdev); fpi_imgdev_set_user_data(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 = FP_INSTANCE_DATA(FP_DEV(dev)); struct aes3k_dev *aesdev = fpi_imgdev_get_user_data(dev);
g_free(aesdev); g_free(aesdev);
libusb_release_interface(fpi_dev_get_usb_dev(FP_DEV(dev)), 0); libusb_release_interface(fpi_imgdev_get_usb_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 = FP_INSTANCE_DATA(FP_DEV(dev)); struct aes3k_dev *aesdev = fpi_imgdev_get_user_data(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_img_resize(tmp, aesdev->enlarge_factor, aesdev->enlarge_factor); img = fpi_im_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,13 +112,18 @@ err:
static void do_capture(struct fp_img_dev *dev) static void do_capture(struct fp_img_dev *dev)
{ {
struct aes3k_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev)); struct aes3k_dev *aesdev = fpi_imgdev_get_user_data(dev);
unsigned char *data; unsigned char *data;
int r; int r;
aesdev->img_trf = fpi_usb_alloc(); aesdev->img_trf = libusb_alloc_transfer(0);
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_dev_get_usb_dev(FP_DEV(dev)), EP_IN, data, libusb_fill_bulk_transfer(aesdev->img_trf, fpi_imgdev_get_usb_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);
@@ -137,16 +142,16 @@ static void init_reqs_cb(struct fp_img_dev *dev, int result, void *user_data)
do_capture(dev); do_capture(dev);
} }
int aes3k_dev_activate(struct fp_img_dev *dev) int aes3k_dev_activate(struct fp_img_dev *dev, enum fp_imgdev_state state)
{ {
struct aes3k_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev)); struct aes3k_dev *aesdev = fpi_imgdev_get_user_data(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 = FP_INSTANCE_DATA(FP_DEV(dev)); struct aes3k_dev *aesdev = fpi_imgdev_get_user_data(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

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

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_dev_get_usb_dev(FP_DEV(dev)), 0); r = libusb_claim_interface(fpi_imgdev_get_usb_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));
fp_dev_set_instance_data(FP_DEV(dev), aesdev); fpi_imgdev_set_user_data(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 = FP_INSTANCE_DATA(FP_DEV(dev)); struct aes3k_dev *aesdev = fpi_imgdev_get_user_data(dev);
g_free(aesdev); g_free(aesdev);
libusb_release_interface(fpi_dev_get_usb_dev(FP_DEV(dev)), 0); libusb_release_interface(fpi_imgdev_get_usb_dev(dev), 0);
fpi_imgdev_close_complete(dev); fpi_imgdev_close_complete(dev);
} }

View File

@@ -35,57 +35,52 @@ 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 ID_LEN 8 #define min(a, b) (((a) < (b)) ? (a) : (b))
#define INIT_LEN 4
#define CALIBRATE_DATA_LEN 4
#define FINGER_DET_DATA_LEN 4
static void static void aesX660_send_cmd_timeout(struct fpi_ssm *ssm, const unsigned char *cmd,
aesX660_send_cmd_timeout(fpi_ssm *ssm, size_t cmd_len, libusb_transfer_cb_fn callback, int timeout)
struct fp_dev *_dev,
const unsigned char *cmd,
size_t cmd_len,
libusb_transfer_cb_fn callback,
int timeout)
{ {
struct fp_img_dev *dev = 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);
int r; int r;
libusb_fill_bulk_transfer(transfer, fpi_dev_get_usb_dev(FP_DEV(dev)), EP_OUT, if (!transfer) {
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_failed(ssm, -ENOMEM); fpi_ssm_mark_aborted(ssm, -ENOMEM);
} }
} }
static void static void aesX660_send_cmd(struct fpi_ssm *ssm, const unsigned char *cmd,
aesX660_send_cmd(fpi_ssm *ssm, size_t cmd_len, libusb_transfer_cb_fn callback)
struct fp_dev *dev,
const unsigned char *cmd,
size_t cmd_len,
libusb_transfer_cb_fn callback)
{ {
return aesX660_send_cmd_timeout(ssm, dev, cmd, cmd_len, callback, BULK_TIMEOUT); return aesX660_send_cmd_timeout(ssm, cmd, cmd_len, callback, BULK_TIMEOUT);
} }
static void static void aesX660_read_response(struct fpi_ssm *ssm, size_t buf_len,
aesX660_read_response(fpi_ssm *ssm, libusb_transfer_cb_fn callback)
struct fp_dev *_dev,
size_t buf_len,
libusb_transfer_cb_fn callback)
{ {
struct fp_img_dev *dev = 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;
}
data = g_malloc(buf_len); data = g_malloc(buf_len);
libusb_fill_bulk_transfer(transfer, fpi_dev_get_usb_dev(FP_DEV(dev)), EP_IN, libusb_fill_bulk_transfer(transfer, fpi_imgdev_get_usb_dev(dev), EP_IN,
data, buf_len, data, buf_len,
callback, ssm, BULK_TIMEOUT); callback, ssm, BULK_TIMEOUT);
@@ -94,13 +89,13 @@ aesX660_read_response(fpi_ssm *ssm,
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_failed(ssm, r); fpi_ssm_mark_aborted(ssm, r);
} }
} }
static void aesX660_send_cmd_cb(struct libusb_transfer *transfer) static void aesX660_send_cmd_cb(struct libusb_transfer *transfer)
{ {
fpi_ssm *ssm = transfer->user_data; struct 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)) {
@@ -108,25 +103,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_failed(ssm, -EIO); fpi_ssm_mark_aborted(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)
{ {
fpi_ssm *ssm = transfer->user_data; struct 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_failed(ssm, -EIO); fpi_ssm_mark_aborted(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_failed(ssm, -EPROTO); fpi_ssm_mark_aborted(ssm, -EPROTO);
goto out; goto out;
} }
@@ -148,9 +143,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)
{ {
fpi_ssm *ssm = transfer->user_data; struct 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 = FP_INSTANCE_DATA(FP_DEV(dev)); struct aesX660_dev *aesdev = fpi_imgdev_get_user_data(dev);
unsigned char *data = transfer->buffer; unsigned char *data = transfer->buffer;
aesdev->fd_data_transfer = NULL; aesdev->fd_data_transfer = NULL;
@@ -164,13 +159,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_failed(ssm, -EIO); fpi_ssm_mark_aborted(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_failed(ssm, -EPROTO); fpi_ssm_mark_aborted(ssm, -EPROTO);
goto out; goto out;
} }
@@ -189,21 +184,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)
{ {
fpi_ssm *ssm = transfer->user_data; struct 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_failed(ssm, -EIO); fpi_ssm_mark_aborted(ssm, -EIO);
} }
libusb_free_transfer(transfer); libusb_free_transfer(transfer);
} }
static void finger_det_sm_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) static void finger_det_sm_complete(struct fpi_ssm *ssm)
{ {
struct fp_img_dev *dev = 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);
int err = fpi_ssm_get_error(ssm); int err = fpi_ssm_get_error(ssm);
fp_dbg("Finger detection completed"); fp_dbg("Finger detection completed");
@@ -220,22 +215,23 @@ static void finger_det_sm_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user
} }
} }
static void finger_det_run_state(fpi_ssm *ssm, struct fp_dev *dev, void *user_data) static void finger_det_run_state(struct fpi_ssm *ssm)
{ {
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, dev, led_blink_cmd, sizeof(led_blink_cmd), aesX660_send_cmd(ssm, 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, dev, wait_for_finger_cmd, sizeof(wait_for_finger_cmd), aesX660_send_cmd_timeout(ssm, 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:
aesX660_read_response(ssm, dev, FINGER_DET_DATA_LEN, finger_det_read_fd_data_cb); /* Should return 4 byte of response */
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, dev, set_idle_cmd, sizeof(set_idle_cmd), aesX660_send_cmd(ssm, set_idle_cmd, sizeof(set_idle_cmd),
finger_det_set_idle_cmd_cb); finger_det_set_idle_cmd_cb);
break; break;
} }
@@ -243,15 +239,16 @@ static void finger_det_run_state(fpi_ssm *ssm, struct fp_dev *dev, void *user_da
static void start_finger_detection(struct fp_img_dev *dev) static void start_finger_detection(struct fp_img_dev *dev)
{ {
fpi_ssm *ssm; struct fpi_ssm *ssm;
struct aesX660_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev)); struct aesX660_dev *aesdev = fpi_imgdev_get_user_data(dev);
if (aesdev->deactivating) { if (aesdev->deactivating) {
complete_deactivation(dev); complete_deactivation(dev);
return; return;
} }
ssm = fpi_ssm_new(FP_DEV(dev), finger_det_run_state, FINGER_DET_NUM_STATES, dev); ssm = fpi_ssm_new(fpi_imgdev_get_dev(dev), finger_det_run_state, FINGER_DET_NUM_STATES);
fpi_ssm_set_user_data(ssm, dev);
fpi_ssm_start(ssm, finger_det_sm_complete); fpi_ssm_start(ssm, finger_det_sm_complete);
} }
@@ -266,11 +263,12 @@ enum capture_states {
}; };
/* Returns number of processed bytes */ /* Returns number of processed bytes */
static int process_stripe_data(fpi_ssm *ssm, struct fp_img_dev *dev, unsigned char *data) static int process_stripe_data(struct fpi_ssm *ssm, unsigned char *data)
{ {
struct fpi_frame *stripe; struct fpi_frame *stripe;
unsigned char *stripdata; unsigned char *stripdata;
struct aesX660_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev)); struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
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;
@@ -288,17 +286,17 @@ static int process_stripe_data(fpi_ssm *ssm, struct fp_img_dev *dev, unsigned ch
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)
{ {
fpi_ssm *ssm = transfer->user_data; struct 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 = FP_INSTANCE_DATA(FP_DEV(dev)); struct aesX660_dev *aesdev = fpi_imgdev_get_user_data(dev);
if ((transfer->status == LIBUSB_TRANSFER_COMPLETED) && if ((transfer->status == LIBUSB_TRANSFER_COMPLETED) &&
(transfer->length == transfer->actual_length)) { (transfer->length == transfer->actual_length)) {
@@ -315,28 +313,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_failed(ssm, -EIO); fpi_ssm_mark_aborted(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)
{ {
fpi_ssm *ssm = transfer->user_data; struct 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 = FP_INSTANCE_DATA(FP_DEV(dev)); struct aesX660_dev *aesdev = fpi_imgdev_get_user_data(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_failed(ssm, -EIO); fpi_ssm_mark_aborted(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);
@@ -354,7 +352,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, dev, aesdev->buffer); finger_missing |= process_stripe_data(ssm, aesdev->buffer);
aesdev->buffer_max = AESX660_HEADER_SIZE; aesdev->buffer_max = AESX660_HEADER_SIZE;
aesdev->buffer_size = 0; aesdev->buffer_size = 0;
} }
@@ -373,38 +371,39 @@ out:
libusb_free_transfer(transfer); libusb_free_transfer(transfer);
} }
static void capture_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) static void capture_run_state(struct fpi_ssm *ssm)
{ {
struct aesX660_dev *aesdev = FP_INSTANCE_DATA(_dev); struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
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, _dev, led_solid_cmd, sizeof(led_solid_cmd), aesX660_send_cmd(ssm, 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, _dev, aesdev->start_imaging_cmd, aesX660_send_cmd(ssm, 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, _dev, AESX660_BULK_TRANSFER_SIZE, aesX660_read_response(ssm, 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, _dev, set_idle_cmd, sizeof(set_idle_cmd), aesX660_send_cmd(ssm, set_idle_cmd, sizeof(set_idle_cmd),
capture_set_idle_cmd_cb); capture_set_idle_cmd_cb);
break; break;
} }
} }
static void capture_sm_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) static void capture_sm_complete(struct fpi_ssm *ssm)
{ {
struct fp_img_dev *dev = 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);
int err = fpi_ssm_get_error(ssm); int err = fpi_ssm_get_error(ssm);
fp_dbg("Capture completed"); fp_dbg("Capture completed");
@@ -420,16 +419,17 @@ static void capture_sm_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_da
static void start_capture(struct fp_img_dev *dev) static void start_capture(struct fp_img_dev *dev)
{ {
struct aesX660_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev)); struct aesX660_dev *aesdev = fpi_imgdev_get_user_data(dev);
fpi_ssm *ssm; struct fpi_ssm *ssm;
if (aesdev->deactivating) { if (aesdev->deactivating) {
complete_deactivation(dev); complete_deactivation(dev);
return; return;
} }
ssm = fpi_ssm_new(FP_DEV(dev), capture_run_state, CAPTURE_NUM_STATES, dev); ssm = fpi_ssm_new(fpi_imgdev_get_dev(dev), capture_run_state, CAPTURE_NUM_STATES);
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)
{ {
fpi_ssm *ssm = transfer->user_data; struct 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 = FP_INSTANCE_DATA(FP_DEV(dev)); struct aesX660_dev *aesdev = fpi_imgdev_get_user_data(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_failed(ssm, -EIO); fpi_ssm_mark_aborted(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_failed(ssm, -EPROTO); fpi_ssm_mark_aborted(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_failed(ssm, -EPROTO); fpi_ssm_mark_aborted(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)
{ {
fpi_ssm *ssm = transfer->user_data; struct 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 = FP_INSTANCE_DATA(FP_DEV(dev)); struct aesX660_dev *aesdev = fpi_imgdev_get_user_data(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_failed(ssm, -EIO); fpi_ssm_mark_aborted(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_failed(ssm, -EPROTO); fpi_ssm_mark_aborted(ssm, -EPROTO);
goto out; goto out;
} }
aesdev->init_cmd_idx++; aesdev->init_cmd_idx++;
@@ -534,52 +534,55 @@ out:
libusb_free_transfer(transfer); libusb_free_transfer(transfer);
} }
static void activate_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) static void activate_run_state(struct fpi_ssm *ssm)
{ {
struct fp_img_dev *dev = user_data; 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);
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, _dev, set_idle_cmd, sizeof(set_idle_cmd), aesX660_send_cmd(ssm, 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, _dev, read_id_cmd, sizeof(read_id_cmd), aesX660_send_cmd(ssm, 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:
aesX660_read_response(ssm, _dev, ID_LEN, activate_read_id_cb); /* Should return 8-byte response */
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, _dev, aesX660_send_cmd(ssm,
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");
aesX660_read_response(ssm, _dev, INIT_LEN, activate_read_init_cb); /* Should return 4-byte response */
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, _dev, calibrate_cmd, sizeof(calibrate_cmd), aesX660_send_cmd(ssm, 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:
aesX660_read_response(ssm, _dev, CALIBRATE_DATA_LEN, aesX660_read_calibrate_data_cb); /* Should return 4-byte response */
aesX660_read_response(ssm, 4, aesX660_read_calibrate_data_cb);
break; break;
} }
} }
static void activate_sm_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) static void activate_sm_complete(struct fpi_ssm *ssm)
{ {
struct fp_img_dev *dev = user_data; struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
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);
@@ -589,17 +592,18 @@ static void activate_sm_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_d
start_finger_detection(dev); start_finger_detection(dev);
} }
int aesX660_dev_activate(struct fp_img_dev *dev) int aesX660_dev_activate(struct fp_img_dev *dev, enum fp_imgdev_state state)
{ {
fpi_ssm *ssm = fpi_ssm_new(FP_DEV(dev), activate_run_state, struct fpi_ssm *ssm = fpi_ssm_new(fpi_imgdev_get_dev(dev), activate_run_state,
ACTIVATE_NUM_STATES, dev); ACTIVATE_NUM_STATES);
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 = FP_INSTANCE_DATA(FP_DEV(dev)); struct aesX660_dev *aesdev = fpi_imgdev_get_user_data(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);
@@ -609,7 +613,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 = FP_INSTANCE_DATA(FP_DEV(dev)); struct aesX660_dev *aesdev = fpi_imgdev_get_user_data(dev);
G_DEBUG_HERE(); G_DEBUG_HERE();
aesdev->deactivating = FALSE; aesdev->deactivating = FALSE;

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

@@ -21,51 +21,26 @@
#ifndef __ELAN_H #ifndef __ELAN_H
#define __ELAN_H #define __ELAN_H
#include <string.h>
#include <libusb.h> #include <libusb.h>
#define ELAN_VEND_ID 0x04f3 /* number of pixels to discard on left and right (along raw image height)
* because they have different intensity from the rest of the frame */
/* a default device type */ #define ELAN_FRAME_MARGIN 12
#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 2 #define ELAN_SKIP_LAST_FRAMES 1
#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
@@ -75,150 +50,127 @@ 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_cmd = { static const struct elan_cmd get_sensor_dim_cmds[] = {
.cmd = {0x00, 0x0c}, {
.response_len = 0x4, .cmd = {0x00, 0x0c},
.response_in = ELAN_EP_CMD_IN, .response_len = 0x4,
.devices = ELAN_ALL_DEV, .response_in = ELAN_EP_CMD_IN,
},
}; };
static const struct elan_cmd get_fw_ver_cmd = { static const size_t get_sensor_dim_cmds_len =
.cmd = {0x40, 0x19}, G_N_ELEMENTS(get_sensor_dim_cmds);
.response_len = 0x2,
.response_in = ELAN_EP_CMD_IN, static const struct elan_cmd init_start_cmds[] = {
.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,
},
}; };
/* unknown, returns 0x0 0x1 on 0907 */ static const size_t init_start_cmds_len = G_N_ELEMENTS(init_start_cmds);
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 get_image_cmd = { static const struct elan_cmd read_cmds[] = {
.cmd = {0x00, 0x09}, /* raw frame sizes are calculated from image dimesions reported by the
/* raw frame sizes are calculated from image dimensions reported by the
* device */ * device */
.response_len = -1, {
.response_in = ELAN_EP_IMG_IN, .cmd = {0x00, 0x09},
.devices = ELAN_ALL_DEV, .response_len = -1,
.response_in = ELAN_EP_IMG_IN,
},
}; };
static const struct elan_cmd read_sensor_status_cmd = { const size_t read_cmds_len = G_N_ELEMENTS(read_cmds);
.cmd = {0x40, 0x13},
.response_len = 0x1, /* issued after data reads during init and calibration */
.response_in = ELAN_EP_CMD_IN, static const struct elan_cmd init_end_cmds[] = {
.devices = ELAN_ALL_DEV, {
.cmd = {0x40, 0x24},
.response_len = 0x2,
.response_in = ELAN_EP_CMD_IN,
},
}; };
static const struct elan_cmd get_calib_status_cmd = { static const size_t init_end_cmds_len = G_N_ELEMENTS(init_end_cmds);
.cmd = {0x40, 0x23},
.response_len = 0x1, /* same command 2 times
.response_in = ELAN_EP_CMD_IN, * original driver may observe return value to determine how many times it
.devices = ELAN_ALL_DEV, * should be repeated */
static const struct elan_cmd calibrate_start_cmds[] = {
{
.cmd = {0x40, 0x23},
.response_len = 0x1,
.response_in = ELAN_EP_CMD_IN,
},
{
.cmd = {0x40, 0x23},
.response_len = 0x1,
.response_in = ELAN_EP_CMD_IN,
},
}; };
static const struct elan_cmd get_calib_mean_cmd = { static const size_t calibrate_start_cmds_len =
.cmd = {0x40, 0x24}, G_N_ELEMENTS(calibrate_start_cmds);
.response_len = 0x2,
.response_in = ELAN_EP_CMD_IN, /* issued after data reads during init and calibration */
.devices = ELAN_ALL_DEV, static const struct elan_cmd calibrate_end_cmds[] = {
{
.cmd = {0x40, 0x24},
.response_len = 0x2,
.response_in = ELAN_EP_CMD_IN,
},
}; };
static const struct elan_cmd led_on_cmd = { static const size_t calibrate_end_cmds_len =
.cmd = {0x40, 0x31}, G_N_ELEMENTS(calibrate_end_cmds);
.response_len = ELAN_CMD_SKIP_READ,
.response_in = ELAN_EP_CMD_IN, static const struct elan_cmd capture_start_cmds[] = {
.devices = ELAN_ALL_DEV, /* led on */
{
.cmd = {0x40, 0x31},
.response_len = 0x0,
.response_in = ELAN_EP_CMD_IN,
},
}; };
/* wait for finger static size_t capture_start_cmds_len = G_N_ELEMENTS(capture_start_cmds);
* subsequent read will not complete until finger is placed on the reader */
static const struct elan_cmd pre_scan_cmd = { static const struct elan_cmd capture_wait_finger_cmds[] = {
.cmd = {0x40, 0x3f}, /* wait for finger
.response_len = 0x1, * subsequent read will not complete until finger is placed on the reader */
.response_in = ELAN_EP_CMD_IN, {
.devices = ELAN_ALL_DEV, .cmd = {0x40, 0x3f},
.response_len = 0x1,
.response_in = ELAN_EP_CMD_IN,
},
}; };
/* led off, stop waiting for finger */ static size_t capture_wait_finger_cmds_len =
static const struct elan_cmd stop_cmd = { G_N_ELEMENTS(capture_wait_finger_cmds);
.cmd = {0x00, 0x0b},
.response_len = ELAN_CMD_SKIP_READ, static const struct elan_cmd deactivate_cmds[] = {
.response_in = ELAN_EP_CMD_IN, /* led off */
.devices = ELAN_ALL_DEV, {
.cmd = {0x00, 0x0b},
.response_len = 0x0,
.response_in = ELAN_EP_CMD_IN,
},
}; };
static const struct usb_id elan_id_table[] = { static const size_t deactivate_cmds_len = G_N_ELEMENTS(deactivate_cmds);
{.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_done(fpi_ssm *ssm); static void elan_cmd_cb(struct libusb_transfer *transfer);
static void elan_cmd_read(fpi_ssm *ssm, struct fp_img_dev *dev); static void elan_cmd_read(struct fpi_ssm *ssm);
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,11 +639,14 @@ 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 = FP_INSTANCE_DATA(FP_DEV(idev)); struct etes603_dev *dev = fpi_imgdev_get_user_data(idev);
struct libusb_transfer *transfer = fpi_usb_alloc(); struct libusb_transfer *transfer = libusb_alloc_transfer(0);
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;
@@ -653,7 +656,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_dev_get_usb_dev(FP_DEV(idev)), ep, buffer, length, libusb_fill_bulk_transfer(transfer, fpi_imgdev_get_usb_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)) {
@@ -666,14 +669,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)
{ {
fpi_ssm *ssm = transfer->user_data; struct 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 = FP_INSTANCE_DATA(FP_DEV(idev)); struct etes603_dev *dev = fpi_imgdev_get_user_data(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_failed(ssm, -EIO); fpi_ssm_mark_aborted(ssm, -EIO);
libusb_free_transfer(transfer); libusb_free_transfer(transfer);
} else { } else {
unsigned char endpoint = transfer->endpoint; unsigned char endpoint = transfer->endpoint;
@@ -688,7 +691,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_failed(ssm, -EIO); fpi_ssm_mark_aborted(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);
@@ -696,10 +699,10 @@ static void async_tx_cb(struct libusb_transfer *transfer)
} }
} }
static void m_exit_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) static void m_exit_state(struct fpi_ssm *ssm)
{ {
struct fp_img_dev *idev = user_data; struct fp_img_dev *idev = fpi_ssm_get_user_data(ssm);
struct etes603_dev *dev = FP_INSTANCE_DATA(_dev); struct etes603_dev *dev = fpi_imgdev_get_user_data(idev);
switch (fpi_ssm_get_cur_state(ssm)) { switch (fpi_ssm_get_cur_state(ssm)) {
case EXIT_SET_REGS_REQ: case EXIT_SET_REGS_REQ:
@@ -721,12 +724,12 @@ static void m_exit_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
return; return;
err: err:
fpi_ssm_mark_failed(ssm, -EIO); fpi_ssm_mark_aborted(ssm, -EIO);
} }
static void m_exit_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) static void m_exit_complete(struct fpi_ssm *ssm)
{ {
struct fp_img_dev *idev = user_data; struct fp_img_dev *idev = fpi_ssm_get_user_data(ssm);
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");
@@ -739,16 +742,17 @@ static void m_exit_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
static void m_exit_start(struct fp_img_dev *idev) static void m_exit_start(struct fp_img_dev *idev)
{ {
fpi_ssm *ssm = fpi_ssm_new(FP_DEV(idev), m_exit_state, struct fpi_ssm *ssm = fpi_ssm_new(fpi_imgdev_get_dev(idev), m_exit_state,
EXIT_NUM_STATES, idev); EXIT_NUM_STATES);
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(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) static void m_capture_state(struct fpi_ssm *ssm)
{ {
struct fp_img_dev *idev = user_data; struct fp_img_dev *idev = fpi_ssm_get_user_data(ssm);
struct etes603_dev *dev = FP_INSTANCE_DATA(_dev); struct etes603_dev *dev = fpi_imgdev_get_user_data(idev);
if (dev->is_active == FALSE) { if (dev->is_active == FALSE) {
fpi_ssm_mark_completed(ssm); fpi_ssm_mark_completed(ssm);
@@ -823,13 +827,13 @@ static void m_capture_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
return; return;
err: err:
fpi_ssm_mark_failed(ssm, -EIO); fpi_ssm_mark_aborted(ssm, -EIO);
} }
static void m_capture_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) static void m_capture_complete(struct fpi_ssm *ssm)
{ {
struct fp_img_dev *idev = user_data; struct fp_img_dev *idev = fpi_ssm_get_user_data(ssm);
struct etes603_dev *dev = FP_INSTANCE_DATA(_dev); struct etes603_dev *dev = fpi_imgdev_get_user_data(idev);
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) {
@@ -848,10 +852,10 @@ static void m_capture_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_dat
} }
} }
static void m_finger_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) static void m_finger_state(struct fpi_ssm *ssm)
{ {
struct fp_img_dev *idev = user_data; struct fp_img_dev *idev = fpi_ssm_get_user_data(ssm);
struct etes603_dev *dev = FP_INSTANCE_DATA(_dev); struct etes603_dev *dev = fpi_imgdev_get_user_data(idev);
if (dev->is_active == FALSE) { if (dev->is_active == FALSE) {
fpi_ssm_mark_completed(ssm); fpi_ssm_mark_completed(ssm);
@@ -941,18 +945,19 @@ static void m_finger_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
return; return;
err: err:
fpi_ssm_mark_failed(ssm, -EIO); fpi_ssm_mark_aborted(ssm, -EIO);
} }
static void m_finger_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) static void m_finger_complete(struct fpi_ssm *ssm)
{ {
struct fp_img_dev *idev = user_data; struct fp_img_dev *idev = fpi_ssm_get_user_data(ssm);
struct etes603_dev *dev = FP_INSTANCE_DATA(_dev); struct etes603_dev *dev = fpi_imgdev_get_user_data(idev);
if (!fpi_ssm_get_error(ssm)) { if (!fpi_ssm_get_error(ssm)) {
fpi_ssm *ssm_cap; struct fpi_ssm *ssm_cap;
ssm_cap = fpi_ssm_new(FP_DEV(idev), m_capture_state, ssm_cap = fpi_ssm_new(fpi_imgdev_get_dev(idev), m_capture_state,
CAP_NUM_STATES, idev); CAP_NUM_STATES);
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) {
@@ -968,18 +973,19 @@ static void m_finger_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data
static void m_start_fingerdetect(struct fp_img_dev *idev) static void m_start_fingerdetect(struct fp_img_dev *idev)
{ {
fpi_ssm *ssmf; struct fpi_ssm *ssmf;
ssmf = fpi_ssm_new(FP_DEV(idev), m_finger_state, FGR_NUM_STATES, idev); ssmf = fpi_ssm_new(fpi_imgdev_get_dev(idev), m_finger_state, FGR_NUM_STATES);
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(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) static void m_tunevrb_state(struct fpi_ssm *ssm)
{ {
struct fp_img_dev *idev = user_data; struct fp_img_dev *idev = fpi_ssm_get_user_data(ssm);
struct etes603_dev *dev = FP_INSTANCE_DATA(_dev); struct etes603_dev *dev = fpi_imgdev_get_user_data(idev);
float hist[5]; float hist[5];
if (dev->is_active == FALSE) { if (dev->is_active == FALSE) {
@@ -1125,19 +1131,19 @@ static void m_tunevrb_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
return; return;
err: err:
fpi_ssm_mark_failed(ssm, -EIO); fpi_ssm_mark_aborted(ssm, -EIO);
} }
static void m_tunevrb_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) static void m_tunevrb_complete(struct fpi_ssm *ssm)
{ {
struct fp_img_dev *idev = user_data; struct fp_img_dev *idev = fpi_ssm_get_user_data(ssm);
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 = FP_INSTANCE_DATA(_dev); struct etes603_dev *dev = fpi_imgdev_get_user_data(idev);
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);
@@ -1150,10 +1156,10 @@ static void m_tunevrb_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_dat
* 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(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) static void m_tunedc_state(struct fpi_ssm *ssm)
{ {
struct fp_img_dev *idev = user_data; struct fp_img_dev *idev = fpi_ssm_get_user_data(ssm);
struct etes603_dev *dev = FP_INSTANCE_DATA(_dev); struct etes603_dev *dev = fpi_imgdev_get_user_data(idev);
if (dev->is_active == FALSE) { if (dev->is_active == FALSE) {
fpi_ssm_mark_completed(ssm); fpi_ssm_mark_completed(ssm);
@@ -1249,20 +1255,21 @@ static void m_tunedc_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
return; return;
err: err:
fpi_ssm_mark_failed(ssm, -EIO); fpi_ssm_mark_aborted(ssm, -EIO);
} }
static void m_tunedc_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) static void m_tunedc_complete(struct fpi_ssm *ssm)
{ {
struct fp_img_dev *idev = user_data; struct fp_img_dev *idev = fpi_ssm_get_user_data(ssm);
if (!fpi_ssm_get_error(ssm)) { if (!fpi_ssm_get_error(ssm)) {
fpi_ssm *ssm_tune; struct fpi_ssm *ssm_tune;
ssm_tune = fpi_ssm_new(FP_DEV(idev), m_tunevrb_state, ssm_tune = fpi_ssm_new(fpi_imgdev_get_dev(idev), m_tunevrb_state,
TUNEVRB_NUM_STATES, idev); TUNEVRB_NUM_STATES);
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 = FP_INSTANCE_DATA(_dev); struct etes603_dev *dev = fpi_imgdev_get_user_data(idev);
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);
@@ -1271,10 +1278,10 @@ static void m_tunedc_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data
fpi_ssm_free(ssm); fpi_ssm_free(ssm);
} }
static void m_init_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) static void m_init_state(struct fpi_ssm *ssm)
{ {
struct fp_img_dev *idev = user_data; struct fp_img_dev *idev = fpi_ssm_get_user_data(ssm);
struct etes603_dev *dev = FP_INSTANCE_DATA(_dev); struct etes603_dev *dev = fpi_imgdev_get_user_data(idev);
if (dev->is_active == FALSE) { if (dev->is_active == FALSE) {
fpi_ssm_mark_completed(ssm); fpi_ssm_mark_completed(ssm);
@@ -1316,7 +1323,7 @@ static void m_init_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
fpi_ssm_next_state(ssm); fpi_ssm_next_state(ssm);
break; break;
case INIT_SENSOR_REQ: case INIT_SENSOR_REQ:
/* In captured traffic, those are split. */ /* In captured traffic, those are splitted. */
msg_set_regs(dev, 18, REG_MODE_CONTROL, REG_MODE_SLEEP, msg_set_regs(dev, 18, REG_MODE_CONTROL, REG_MODE_SLEEP,
REG_50, 0x0F, REG_GAIN, 0x04, REG_VRT, 0x08, REG_50, 0x0F, REG_GAIN, 0x04, REG_VRT, 0x08,
REG_VRB, 0x0D, REG_VCO_CONTROL, REG_VCO_RT, REG_VRB, 0x0D, REG_VCO_CONTROL, REG_VCO_RT,
@@ -1368,20 +1375,21 @@ static void m_init_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
return; return;
err: err:
fpi_ssm_mark_failed(ssm, -EIO); fpi_ssm_mark_aborted(ssm, -EIO);
} }
static void m_init_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) static void m_init_complete(struct fpi_ssm *ssm)
{ {
struct fp_img_dev *idev = user_data; struct fp_img_dev *idev = fpi_ssm_get_user_data(ssm);
if (!fpi_ssm_get_error(ssm)) { if (!fpi_ssm_get_error(ssm)) {
fpi_ssm *ssm_tune; struct fpi_ssm *ssm_tune;
ssm_tune = fpi_ssm_new(FP_DEV(idev), m_tunedc_state, ssm_tune = fpi_ssm_new(fpi_imgdev_get_dev(idev), m_tunedc_state,
TUNEDC_NUM_STATES, idev); TUNEDC_NUM_STATES);
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 = FP_INSTANCE_DATA(_dev); struct etes603_dev *dev = fpi_imgdev_get_user_data(idev);
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);
@@ -1390,26 +1398,34 @@ static void m_init_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
fpi_ssm_free(ssm); fpi_ssm_free(ssm);
} }
static int dev_activate(struct fp_img_dev *idev) static int dev_activate(struct fp_img_dev *idev, enum fp_imgdev_state state)
{ {
struct etes603_dev *dev = FP_INSTANCE_DATA(FP_DEV(idev)); struct etes603_dev *dev = fpi_imgdev_get_user_data(idev);
fpi_ssm *ssm; struct fpi_ssm *ssm;
g_assert(dev); g_assert(dev);
if (state != IMGDEV_STATE_AWAIT_FINGER_ON) {
fp_err("The driver is in an unexpected state: %d.", state);
fpi_imgdev_activate_complete(idev, 1);
return -1;
}
/* Reset info and data */ /* Reset info and data */
dev->is_active = TRUE; dev->is_active = TRUE;
if (dev->dcoffset == 0) { if (dev->dcoffset == 0) {
fp_dbg("Tuning device..."); fp_dbg("Tuning device...");
ssm = fpi_ssm_new(FP_DEV(idev), m_init_state, INIT_NUM_STATES, idev); ssm = fpi_ssm_new(fpi_imgdev_get_dev(idev), m_init_state, INIT_NUM_STATES);
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(FP_DEV(idev), m_finger_state, FGR_NUM_STATES, idev); ssm = fpi_ssm_new(fpi_imgdev_get_dev(idev), m_finger_state, FGR_NUM_STATES);
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;
@@ -1417,16 +1433,15 @@ static int dev_activate(struct fp_img_dev *idev)
static void dev_deactivate(struct fp_img_dev *idev) static void dev_deactivate(struct fp_img_dev *idev)
{ {
struct etes603_dev *dev = FP_INSTANCE_DATA(FP_DEV(idev)); struct etes603_dev *dev = fpi_imgdev_get_user_data(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)
@@ -1435,13 +1450,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));
fp_dev_set_instance_data(FP_DEV(idev), dev); fpi_imgdev_set_user_data(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_dev_get_usb_dev(FP_DEV(idev)), 0); ret = libusb_claim_interface(fpi_imgdev_get_usb_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;
@@ -1453,14 +1468,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 = FP_INSTANCE_DATA(FP_DEV(idev)); struct etes603_dev *dev = fpi_imgdev_get_user_data(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_dev_get_usb_dev(FP_DEV(idev)), 0); libusb_release_interface(fpi_imgdev_get_usb_dev(idev), 0);
fpi_imgdev_close_complete(idev); fpi_imgdev_close_complete(idev);
} }

318
libfprint/drivers/fdu2000.c Normal file
View File

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

View File

@@ -1,66 +0,0 @@
/*
* 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

@@ -1,24 +0,0 @@
/*
* 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;
fpi_ssm *loopsm; struct 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,21 +100,18 @@ 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 {
fpi_ssm *kill_ssm; struct fpi_ssm *kill_ssm;
void (*kill_cb)(struct fp_img_dev *dev); void (*kill_cb)(struct fp_img_dev *dev);
}; };
}; };
/* Calculate squared standard deviation of sum of two lines */ /* Calculade squared standand 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];
@@ -136,7 +133,7 @@ static unsigned char upeksonly_get_pixel(struct fpi_line_asmbl_ctx *ctx,
unsigned char *buf; unsigned char *buf;
unsigned offset; unsigned offset;
/* The scans from this device are rolled right by two columns */ /* The scans from this device are rolled right by two colums */
if (x < ctx->line_width - 2) if (x < ctx->line_width - 2)
offset = x + 2; offset = x + 2;
else if ((x > ctx->line_width - 2) && (x < ctx->line_width)) else if ((x > ctx->line_width - 2) && (x < ctx->line_width))
@@ -179,11 +176,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 = FP_INSTANCE_DATA(FP_DEV(dev)); struct sonly_dev *sdev = fpi_imgdev_get_user_data(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_failed(sdev->kill_ssm, sdev->kill_status_code); fpi_ssm_mark_aborted(sdev->kill_ssm, sdev->kill_status_code);
return; return;
case ITERATE_SSM: case ITERATE_SSM:
fp_dbg("iterate ssm"); fp_dbg("iterate ssm");
@@ -200,7 +197,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 = FP_INSTANCE_DATA(FP_DEV(dev)); struct sonly_dev *sdev = fpi_imgdev_get_user_data(dev);
int i; int i;
if (sdev->num_flying == 0) { if (sdev->num_flying == 0) {
@@ -227,7 +224,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 = FP_INSTANCE_DATA(FP_DEV(dev)); struct sonly_dev *sdev = fpi_imgdev_get_user_data(dev);
struct fp_img *img; struct fp_img *img;
GSList *elem = sdev->rows; GSList *elem = sdev->rows;
@@ -255,7 +252,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 = FP_INSTANCE_DATA(FP_DEV(dev)); struct sonly_dev *sdev = fpi_imgdev_get_user_data(dev);
sdev->rowbuf_offset = -1; sdev->rowbuf_offset = -1;
if (sdev->num_rows > 0) { if (sdev->num_rows > 0) {
@@ -296,12 +293,12 @@ static void row_complete(struct fp_img_dev *dev)
sdev->num_blank = 0; sdev->num_blank = 0;
} else { } else {
sdev->num_blank++; sdev->num_blank++;
/* Don't consider the scan complete unless there's at least /* Don't consider the scan complete unless theres at least
* MIN_ROWS recorded or very long blank read occurred. * MIN_ROWS recorded or very long blank read occurred.
* *
* Typical problem spot: one brief touch before starting the * Typical problem spot: one brief touch before starting the
* actual scan. Happens most commonly if scan is started * actual scan. Happens most commonly if scan is started
* from before the first joint resulting in a gap after the initial touch. * from before the first joint resulting in a gap after the inital touch.
*/ */
if (sdev->num_blank > FINGER_REMOVED_THRESHOLD) { if (sdev->num_blank > FINGER_REMOVED_THRESHOLD) {
sdev->finger_state = FINGER_REMOVED; sdev->finger_state = FINGER_REMOVED;
@@ -343,7 +340,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 = FP_INSTANCE_DATA(FP_DEV(dev)); struct sonly_dev *sdev = fpi_imgdev_get_user_data(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;
@@ -377,7 +374,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 = FP_INSTANCE_DATA(FP_DEV(dev)); struct sonly_dev *sdev = fpi_imgdev_get_user_data(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;
@@ -473,7 +470,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 = FP_INSTANCE_DATA(FP_DEV(dev)); struct sonly_dev *sdev = fpi_imgdev_get_user_data(dev);
int i; int i;
idata->flying = FALSE; idata->flying = FALSE;
@@ -523,7 +520,7 @@ static void img_data_cb(struct libusb_transfer *transfer)
/***** STATE MACHINE HELPERS *****/ /***** STATE MACHINE HELPERS *****/
struct write_regs_data { struct write_regs_data {
fpi_ssm *ssm; struct 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;
@@ -537,7 +534,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_failed(wrdata->ssm, result); fpi_ssm_mark_aborted(wrdata->ssm, result);
g_free(wrdata); g_free(wrdata);
} }
@@ -577,18 +574,23 @@ static void write_regs_cb(struct libusb_transfer *transfer)
write_regs_iterate(wrdata); write_regs_iterate(wrdata);
} }
static void static void sm_write_regs(struct fpi_ssm *ssm,
sm_write_regs(fpi_ssm *ssm, const struct sonly_regwrite *regs, size_t num_regs)
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);
@@ -603,29 +605,31 @@ sm_write_regs(fpi_ssm *ssm,
static void sm_write_reg_cb(struct libusb_transfer *transfer) static void sm_write_reg_cb(struct libusb_transfer *transfer)
{ {
fpi_ssm *ssm = transfer->user_data; struct 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_failed(ssm, -EIO); fpi_ssm_mark_aborted(ssm, -EIO);
else else
fpi_ssm_next_state(ssm); fpi_ssm_next_state(ssm);
} }
static void static void sm_write_reg(struct fpi_ssm *ssm, uint8_t reg, uint8_t value)
sm_write_reg(fpi_ssm *ssm,
struct fp_img_dev *dev,
uint8_t reg,
uint8_t value)
{ {
struct libusb_transfer *transfer = fpi_usb_alloc(); struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
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_dev_get_usb_dev(FP_DEV(dev)), libusb_fill_control_transfer(transfer, fpi_imgdev_get_usb_dev(dev),
data, sm_write_reg_cb, data, sm_write_reg_cb,
ssm, CTRL_TIMEOUT); ssm, CTRL_TIMEOUT);
@@ -637,18 +641,18 @@ sm_write_reg(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_failed(ssm, r); fpi_ssm_mark_aborted(ssm, r);
} }
} }
static void sm_read_reg_cb(struct libusb_transfer *transfer) static void sm_read_reg_cb(struct libusb_transfer *transfer)
{ {
fpi_ssm *ssm = transfer->user_data; struct 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 = FP_INSTANCE_DATA(FP_DEV(dev)); struct sonly_dev *sdev = fpi_imgdev_get_user_data(dev);
if (transfer->status != LIBUSB_TRANSFER_COMPLETED) { if (transfer->status != LIBUSB_TRANSFER_COMPLETED) {
fpi_ssm_mark_failed(ssm, -EIO); fpi_ssm_mark_aborted(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);
@@ -658,19 +662,22 @@ static void sm_read_reg_cb(struct libusb_transfer *transfer)
g_free(transfer->buffer); g_free(transfer->buffer);
} }
static void static void sm_read_reg(struct fpi_ssm *ssm, uint8_t reg)
sm_read_reg(fpi_ssm *ssm,
struct fp_img_dev *dev,
uint8_t reg)
{ {
struct libusb_transfer *transfer = fpi_usb_alloc(); struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
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_dev_get_usb_dev(FP_DEV(dev)), libusb_fill_control_transfer(transfer, fpi_imgdev_get_usb_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 |
@@ -680,19 +687,19 @@ sm_read_reg(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_failed(ssm, r); fpi_ssm_mark_aborted(ssm, r);
} }
} }
static void sm_await_intr_cb(struct libusb_transfer *transfer) static void sm_await_intr_cb(struct libusb_transfer *transfer)
{ {
fpi_ssm *ssm = transfer->user_data; struct 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 = FP_INSTANCE_DATA(FP_DEV(dev)); struct sonly_dev *sdev = fpi_imgdev_get_user_data(dev);
if (transfer->status != LIBUSB_TRANSFER_COMPLETED) { if (transfer->status != LIBUSB_TRANSFER_COMPLETED) {
g_free(transfer->buffer); g_free(transfer->buffer);
fpi_ssm_mark_failed(ssm, transfer->status); fpi_ssm_mark_aborted(ssm, transfer->status);
return; return;
} }
@@ -706,17 +713,21 @@ static void sm_await_intr_cb(struct libusb_transfer *transfer)
fpi_ssm_next_state(ssm); fpi_ssm_next_state(ssm);
} }
static void static void sm_await_intr(struct fpi_ssm *ssm)
sm_await_intr(fpi_ssm *ssm,
struct fp_img_dev *dev)
{ {
struct libusb_transfer *transfer = fpi_usb_alloc(); struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
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_dev_get_usb_dev(FP_DEV(dev)), libusb_fill_interrupt_transfer(transfer, fpi_imgdev_get_usb_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 |
@@ -726,7 +737,7 @@ sm_await_intr(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_failed(ssm, r); fpi_ssm_mark_aborted(ssm, r);
} }
} }
@@ -752,61 +763,61 @@ enum awfsm_1000_states {
AWFSM_1000_NUM_STATES, AWFSM_1000_NUM_STATES,
}; };
static void awfsm_2016_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) static void awfsm_2016_run_state(struct fpi_ssm *ssm)
{ {
struct fp_img_dev *dev = 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 AWFSM_2016_WRITEV_1: case AWFSM_2016_WRITEV_1:
sm_write_regs(ssm, _dev, awfsm_2016_writev_1, G_N_ELEMENTS(awfsm_2016_writev_1)); sm_write_regs(ssm, 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, dev, 0x01); sm_read_reg(ssm, 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, dev, 0x01, 0x46); sm_write_reg(ssm, 0x01, 0x46);
else else
sm_write_reg(ssm, dev, 0x01, 0xc6); sm_write_reg(ssm, 0x01, 0xc6);
break; break;
case AWFSM_2016_WRITEV_2: case AWFSM_2016_WRITEV_2:
sm_write_regs(ssm, _dev, awfsm_2016_writev_2, G_N_ELEMENTS(awfsm_2016_writev_2)); sm_write_regs(ssm, 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, dev, 0x13); sm_read_reg(ssm, 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, dev, 0x13, 0x05); sm_write_reg(ssm, 0x13, 0x05);
else else
sm_write_reg(ssm, dev, 0x13, 0x45); sm_write_reg(ssm, 0x13, 0x45);
break; break;
case AWFSM_2016_WRITEV_3: case AWFSM_2016_WRITEV_3:
sm_write_regs(ssm, _dev, awfsm_2016_writev_3, G_N_ELEMENTS(awfsm_2016_writev_3)); sm_write_regs(ssm, 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, dev, 0x07); sm_read_reg(ssm, 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, dev, 0x07, sdev->read_reg_result); sm_write_reg(ssm, 0x07, sdev->read_reg_result);
break; break;
case AWFSM_2016_WRITEV_4: case AWFSM_2016_WRITEV_4:
sm_write_regs(ssm, _dev, awfsm_2016_writev_4, G_N_ELEMENTS(awfsm_2016_writev_4)); sm_write_regs(ssm, awfsm_2016_writev_4, G_N_ELEMENTS(awfsm_2016_writev_4));
break; break;
} }
} }
static void awfsm_1000_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) static void awfsm_1000_run_state(struct fpi_ssm *ssm)
{ {
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, _dev, awfsm_1000_writev_1, G_N_ELEMENTS(awfsm_1000_writev_1)); sm_write_regs(ssm, 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, _dev, awfsm_1000_writev_2, G_N_ELEMENTS(awfsm_1000_writev_2)); sm_write_regs(ssm, awfsm_1000_writev_2, G_N_ELEMENTS(awfsm_1000_writev_2));
break; break;
} }
} }
@@ -840,19 +851,17 @@ enum capsm_1001_states {
CAPSM_1001_NUM_STATES, CAPSM_1001_NUM_STATES,
}; };
static void static void capsm_fire_bulk(struct fpi_ssm *ssm)
capsm_fire_bulk(fpi_ssm *ssm,
struct fp_dev *_dev)
{ {
struct fp_img_dev *dev = FP_IMG_DEV(_dev); 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);
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_failed(ssm, r); fpi_ssm_mark_aborted(ssm, r);
return; return;
} }
@@ -872,10 +881,10 @@ capsm_fire_bulk(fpi_ssm *ssm,
fpi_ssm_next_state(ssm); fpi_ssm_next_state(ssm);
} }
static void capsm_2016_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) static void capsm_2016_run_state(struct fpi_ssm *ssm)
{ {
struct fp_img_dev *dev = 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_2016_INIT: case CAPSM_2016_INIT:
@@ -890,23 +899,24 @@ static void capsm_2016_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_d
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, dev, 0x15, 0x20); sm_write_reg(ssm, 0x15, 0x20);
break; break;
case CAPSM_2016_WRITE_30: case CAPSM_2016_WRITE_30:
sm_write_reg(ssm, dev, 0x30, 0xe0); sm_write_reg(ssm, 0x30, 0xe0);
break; break;
case CAPSM_2016_FIRE_BULK: ; case CAPSM_2016_FIRE_BULK: ;
capsm_fire_bulk (ssm, _dev); capsm_fire_bulk (ssm);
break; break;
case CAPSM_2016_WRITEV: case CAPSM_2016_WRITEV:
sm_write_regs(ssm, _dev, capsm_2016_writev, G_N_ELEMENTS(capsm_2016_writev)); sm_write_regs(ssm, capsm_2016_writev, G_N_ELEMENTS(capsm_2016_writev));
break; break;
} }
} }
static void capsm_1000_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) static void capsm_1000_run_state(struct fpi_ssm *ssm)
{ {
struct sonly_dev *sdev = FP_INSTANCE_DATA(_dev); struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
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:
@@ -921,17 +931,18 @@ static void capsm_1000_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_d
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, _dev); capsm_fire_bulk (ssm);
break; break;
case CAPSM_1000_WRITEV: case CAPSM_1000_WRITEV:
sm_write_regs(ssm, _dev, capsm_1000_writev, G_N_ELEMENTS(capsm_1000_writev)); sm_write_regs(ssm, capsm_1000_writev, G_N_ELEMENTS(capsm_1000_writev));
break; break;
} }
} }
static void capsm_1001_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) static void capsm_1001_run_state(struct fpi_ssm *ssm)
{ {
struct sonly_dev *sdev = FP_INSTANCE_DATA(_dev); struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
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:
@@ -946,22 +957,22 @@ static void capsm_1001_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_d
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, _dev); capsm_fire_bulk (ssm);
break; break;
case CAPSM_1001_WRITEV_1: case CAPSM_1001_WRITEV_1:
sm_write_regs(ssm, _dev, capsm_1001_writev_1, G_N_ELEMENTS(capsm_1001_writev_1)); sm_write_regs(ssm, 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, _dev, capsm_1001_writev_2, G_N_ELEMENTS(capsm_1001_writev_2)); sm_write_regs(ssm, 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, _dev, capsm_1001_writev_3, G_N_ELEMENTS(capsm_1001_writev_3)); sm_write_regs(ssm, 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, _dev, capsm_1001_writev_4, G_N_ELEMENTS(capsm_1001_writev_4)); sm_write_regs(ssm, 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, _dev, capsm_1001_writev_5, G_N_ELEMENTS(capsm_1001_writev_5)); sm_write_regs(ssm, capsm_1001_writev_5, G_N_ELEMENTS(capsm_1001_writev_5));
break; break;
} }
} }
@@ -983,29 +994,29 @@ enum deinitsm_1001_states {
DEINITSM_1001_NUM_STATES, DEINITSM_1001_NUM_STATES,
}; };
static void deinitsm_2016_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) static void deinitsm_2016_run_state(struct fpi_ssm *ssm)
{ {
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, _dev, deinitsm_2016_writev, G_N_ELEMENTS(deinitsm_2016_writev)); sm_write_regs(ssm, deinitsm_2016_writev, G_N_ELEMENTS(deinitsm_2016_writev));
break; break;
} }
} }
static void deinitsm_1000_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) static void deinitsm_1000_run_state(struct fpi_ssm *ssm)
{ {
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, _dev, deinitsm_1000_writev, G_N_ELEMENTS(deinitsm_1000_writev)); sm_write_regs(ssm, deinitsm_1000_writev, G_N_ELEMENTS(deinitsm_1000_writev));
break; break;
} }
} }
static void deinitsm_1001_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) static void deinitsm_1001_run_state(struct fpi_ssm *ssm)
{ {
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, _dev, deinitsm_1001_writev, G_N_ELEMENTS(deinitsm_1001_writev)); sm_write_regs(ssm, deinitsm_1001_writev, G_N_ELEMENTS(deinitsm_1001_writev));
break; break;
} }
} }
@@ -1037,62 +1048,62 @@ enum initsm_1001_states {
INITSM_1001_NUM_STATES, INITSM_1001_NUM_STATES,
}; };
static void initsm_2016_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) static void initsm_2016_run_state(struct fpi_ssm *ssm)
{ {
struct fp_img_dev *dev = 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 INITSM_2016_WRITEV_1: case INITSM_2016_WRITEV_1:
sm_write_regs(ssm, _dev, initsm_2016_writev_1, G_N_ELEMENTS(initsm_2016_writev_1)); sm_write_regs(ssm, 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, dev, 0x09); sm_read_reg(ssm, 0x09);
break; break;
case INITSM_2016_WRITE_09: case INITSM_2016_WRITE_09:
sm_write_reg(ssm, dev, 0x09, sdev->read_reg_result & ~0x08); sm_write_reg(ssm, 0x09, sdev->read_reg_result & ~0x08);
break; break;
case INITSM_2016_READ_13: case INITSM_2016_READ_13:
sm_read_reg(ssm, dev, 0x13); sm_read_reg(ssm, 0x13);
break; break;
case INITSM_2016_WRITE_13: case INITSM_2016_WRITE_13:
sm_write_reg(ssm, dev, 0x13, sdev->read_reg_result & ~0x10); sm_write_reg(ssm, 0x13, sdev->read_reg_result & ~0x10);
break; break;
case INITSM_2016_WRITE_04: case INITSM_2016_WRITE_04:
sm_write_reg(ssm, dev, 0x04, 0x00); sm_write_reg(ssm, 0x04, 0x00);
break; break;
case INITSM_2016_WRITE_05: case INITSM_2016_WRITE_05:
sm_write_reg(ssm, dev, 0x05, 0x00); sm_write_reg(ssm, 0x05, 0x00);
break; break;
} }
} }
static void initsm_1000_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) static void initsm_1000_run_state(struct fpi_ssm *ssm)
{ {
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, _dev, initsm_1000_writev_1, G_N_ELEMENTS(initsm_1000_writev_1)); sm_write_regs(ssm, initsm_1000_writev_1, G_N_ELEMENTS(initsm_1000_writev_1));
break; break;
} }
} }
static void initsm_1001_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) static void initsm_1001_run_state(struct fpi_ssm *ssm)
{ {
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, _dev, initsm_1001_writev_1, G_N_ELEMENTS(initsm_1001_writev_1)); sm_write_regs(ssm, 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, _dev, initsm_1001_writev_2, G_N_ELEMENTS(initsm_1001_writev_2)); sm_write_regs(ssm, 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, _dev, initsm_1001_writev_3, G_N_ELEMENTS(initsm_1001_writev_3)); sm_write_regs(ssm, 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, _dev, initsm_1001_writev_4, G_N_ELEMENTS(initsm_1001_writev_4)); sm_write_regs(ssm, 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, _dev, initsm_1001_writev_5, G_N_ELEMENTS(initsm_1001_writev_5)); sm_write_regs(ssm, initsm_1001_writev_5, G_N_ELEMENTS(initsm_1001_writev_5));
break; break;
} }
} }
@@ -1109,10 +1120,10 @@ enum loopsm_states {
LOOPSM_NUM_STATES, LOOPSM_NUM_STATES,
}; };
static void loopsm_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) static void loopsm_run_state(struct fpi_ssm *ssm)
{ {
struct fp_img_dev *dev = 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 LOOPSM_RUN_AWFSM: ; case LOOPSM_RUN_AWFSM: ;
@@ -1128,17 +1139,18 @@ static void loopsm_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
if (sdev->deactivating) { if (sdev->deactivating) {
fpi_ssm_mark_completed(ssm); fpi_ssm_mark_completed(ssm);
} else { } else {
fpi_ssm *awfsm = NULL; struct fpi_ssm *awfsm = NULL;
switch (sdev->dev_model) { switch (sdev->dev_model) {
case UPEKSONLY_2016: case UPEKSONLY_2016:
awfsm = fpi_ssm_new(FP_DEV(dev), awfsm_2016_run_state, awfsm = fpi_ssm_new(fpi_imgdev_get_dev(dev), awfsm_2016_run_state,
AWFSM_2016_NUM_STATES, dev); AWFSM_2016_NUM_STATES);
break; break;
case UPEKSONLY_1000: case UPEKSONLY_1000:
awfsm = fpi_ssm_new(FP_DEV(dev), awfsm_1000_run_state, awfsm = fpi_ssm_new(fpi_imgdev_get_dev(dev), awfsm_1000_run_state,
AWFSM_1000_NUM_STATES, dev); AWFSM_1000_NUM_STATES);
break; break;
} }
fpi_ssm_set_user_data(awfsm, dev);
fpi_ssm_start_subsm(ssm, awfsm); fpi_ssm_start_subsm(ssm, awfsm);
} }
break; break;
@@ -1150,47 +1162,49 @@ static void loopsm_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
fpi_ssm_next_state(ssm); fpi_ssm_next_state(ssm);
break; break;
default: default:
sm_await_intr(ssm, dev); sm_await_intr(ssm);
break; break;
} }
break; break;
case LOOPSM_RUN_CAPSM: ; case LOOPSM_RUN_CAPSM: ;
fpi_ssm *capsm = NULL; struct fpi_ssm *capsm = NULL;
switch (sdev->dev_model) { switch (sdev->dev_model) {
case UPEKSONLY_2016: case UPEKSONLY_2016:
capsm = fpi_ssm_new(FP_DEV(dev), capsm_2016_run_state, capsm = fpi_ssm_new(fpi_imgdev_get_dev(dev), capsm_2016_run_state,
CAPSM_2016_NUM_STATES, dev); CAPSM_2016_NUM_STATES);
break; break;
case UPEKSONLY_1000: case UPEKSONLY_1000:
capsm = fpi_ssm_new(FP_DEV(dev), capsm_1000_run_state, capsm = fpi_ssm_new(fpi_imgdev_get_dev(dev), capsm_1000_run_state,
CAPSM_1000_NUM_STATES, dev); CAPSM_1000_NUM_STATES);
break; break;
case UPEKSONLY_1001: case UPEKSONLY_1001:
capsm = fpi_ssm_new(FP_DEV(dev), capsm_1001_run_state, capsm = fpi_ssm_new(fpi_imgdev_get_dev(dev), capsm_1001_run_state,
CAPSM_1001_NUM_STATES, dev); CAPSM_1001_NUM_STATES);
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: ;
fpi_ssm *deinitsm = NULL; struct fpi_ssm *deinitsm = NULL;
switch (sdev->dev_model) { switch (sdev->dev_model) {
case UPEKSONLY_2016: case UPEKSONLY_2016:
deinitsm = fpi_ssm_new(FP_DEV(dev), deinitsm_2016_run_state, deinitsm = fpi_ssm_new(fpi_imgdev_get_dev(dev), deinitsm_2016_run_state,
DEINITSM_2016_NUM_STATES, dev); DEINITSM_2016_NUM_STATES);
break; break;
case UPEKSONLY_1000: case UPEKSONLY_1000:
deinitsm = fpi_ssm_new(FP_DEV(dev), deinitsm_1000_run_state, deinitsm = fpi_ssm_new(fpi_imgdev_get_dev(dev), deinitsm_1000_run_state,
DEINITSM_1000_NUM_STATES, dev); DEINITSM_1000_NUM_STATES);
break; break;
case UPEKSONLY_1001: case UPEKSONLY_1001:
deinitsm = fpi_ssm_new(FP_DEV(dev), deinitsm_1001_run_state, deinitsm = fpi_ssm_new(fpi_imgdev_get_dev(dev), deinitsm_1001_run_state,
DEINITSM_1001_NUM_STATES, dev); DEINITSM_1001_NUM_STATES);
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:
@@ -1204,7 +1218,7 @@ static void loopsm_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
static void deactivate_done(struct fp_img_dev *dev) static void deactivate_done(struct fp_img_dev *dev)
{ {
struct sonly_dev *sdev = FP_INSTANCE_DATA(FP_DEV(dev)); struct sonly_dev *sdev = fpi_imgdev_get_user_data(dev);
G_DEBUG_HERE(); G_DEBUG_HERE();
free_img_transfers(sdev); free_img_transfers(sdev);
@@ -1221,7 +1235,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 = FP_INSTANCE_DATA(FP_DEV(dev)); struct sonly_dev *sdev = fpi_imgdev_get_user_data(dev);
if (!sdev->capturing) { if (!sdev->capturing) {
deactivate_done(dev); deactivate_done(dev);
@@ -1234,10 +1248,10 @@ static void dev_deactivate(struct fp_img_dev *dev)
cancel_img_transfers(dev); cancel_img_transfers(dev);
} }
static void loopsm_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) static void loopsm_complete(struct fpi_ssm *ssm)
{ {
struct fp_img_dev *dev = 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);
int r = fpi_ssm_get_error(ssm); int r = fpi_ssm_get_error(ssm);
fpi_ssm_free(ssm); fpi_ssm_free(ssm);
@@ -1253,10 +1267,10 @@ static void loopsm_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
} }
} }
static void initsm_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) static void initsm_complete(struct fpi_ssm *ssm)
{ {
struct fp_img_dev *dev = 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);
int r = fpi_ssm_get_error(ssm); int r = fpi_ssm_get_error(ssm);
fpi_ssm_free(ssm); fpi_ssm_free(ssm);
@@ -1264,14 +1278,15 @@ static void initsm_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
if (r != 0) if (r != 0)
return; return;
sdev->loopsm = fpi_ssm_new(FP_DEV(dev), loopsm_run_state, LOOPSM_NUM_STATES, dev); sdev->loopsm = fpi_ssm_new(fpi_imgdev_get_dev(dev), loopsm_run_state, LOOPSM_NUM_STATES);
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) static int dev_activate(struct fp_img_dev *dev, enum fp_imgdev_state state)
{ {
struct sonly_dev *sdev = FP_INSTANCE_DATA(FP_DEV(dev)); struct sonly_dev *sdev = fpi_imgdev_get_user_data(dev);
fpi_ssm *ssm = NULL; struct fpi_ssm *ssm = NULL;
int i; int i;
sdev->deactivating = FALSE; sdev->deactivating = FALSE;
@@ -1284,26 +1299,31 @@ static int dev_activate(struct fp_img_dev *dev)
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] = fpi_usb_alloc(); sdev->img_transfer[i] = libusb_alloc_transfer(0);
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_dev_get_usb_dev(FP_DEV(dev)), libusb_fill_bulk_transfer(sdev->img_transfer[i], fpi_imgdev_get_usb_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(FP_DEV(dev), initsm_2016_run_state, INITSM_2016_NUM_STATES, dev); ssm = fpi_ssm_new(fpi_imgdev_get_dev(dev), initsm_2016_run_state, INITSM_2016_NUM_STATES);
break; break;
case UPEKSONLY_1000: case UPEKSONLY_1000:
ssm = fpi_ssm_new(FP_DEV(dev), initsm_1000_run_state, INITSM_1000_NUM_STATES, dev); ssm = fpi_ssm_new(fpi_imgdev_get_dev(dev), initsm_1000_run_state, INITSM_1000_NUM_STATES);
break; break;
case UPEKSONLY_1001: case UPEKSONLY_1001:
ssm = fpi_ssm_new(FP_DEV(dev), initsm_1001_run_state, INITSM_1001_NUM_STATES, dev); ssm = fpi_ssm_new(fpi_imgdev_get_dev(dev), initsm_1001_run_state, INITSM_1001_NUM_STATES);
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;
} }
@@ -1313,9 +1333,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 = FP_INSTANCE_DATA(FP_DEV(dev)); user_data = fpi_imgdev_get_user_data(dev);
g_free(user_data); g_free(user_data);
libusb_release_interface(fpi_dev_get_usb_dev(FP_DEV(dev)), 0); libusb_release_interface(fpi_imgdev_get_usb_dev(dev), 0);
fpi_imgdev_close_complete(dev); fpi_imgdev_close_complete(dev);
} }
@@ -1367,20 +1387,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_dev_get_usb_dev(FP_DEV(dev)), 1); r = libusb_set_configuration(fpi_imgdev_get_usb_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_dev_get_usb_dev(FP_DEV(dev)), 0); r = libusb_claim_interface(fpi_imgdev_get_usb_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));
fp_dev_set_instance_data(FP_DEV(dev), sdev); fpi_imgdev_set_user_data(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,11 +56,10 @@ enum activate_states {
ACTIVATE_NUM_STATES, ACTIVATE_NUM_STATES,
}; };
static void static void upektc_next_init_cmd(struct fpi_ssm *ssm)
upektc_next_init_cmd(fpi_ssm *ssm,
struct fp_img_dev *dev)
{ {
struct upektc_dev *upekdev = FP_INSTANCE_DATA(FP_DEV(dev)); struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
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)
@@ -71,63 +70,70 @@ upektc_next_init_cmd(fpi_ssm *ssm,
static void write_init_cb(struct libusb_transfer *transfer) static void write_init_cb(struct libusb_transfer *transfer)
{ {
fpi_ssm *ssm = transfer->user_data; struct 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 = FP_INSTANCE_DATA(FP_DEV(dev)); struct upektc_dev *upekdev = fpi_imgdev_get_user_data(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, dev); upektc_next_init_cmd(ssm);
} else { } else {
fpi_ssm_mark_failed(ssm, -EIO); fpi_ssm_mark_aborted(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)
{ {
fpi_ssm *ssm = transfer->user_data; struct 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, dev); upektc_next_init_cmd(ssm);
else else
fpi_ssm_mark_failed(ssm, -EIO); fpi_ssm_mark_aborted(ssm, -EIO);
g_free(transfer->buffer); g_free(transfer->buffer);
libusb_free_transfer(transfer); libusb_free_transfer(transfer);
} }
static void activate_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) static void activate_run_state(struct fpi_ssm *ssm)
{ {
struct fp_img_dev *dev = user_data; struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct upektc_dev *upekdev = FP_INSTANCE_DATA(_dev); struct upektc_dev *upekdev = fpi_imgdev_get_user_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 = fpi_usb_alloc(); struct libusb_transfer *transfer = libusb_alloc_transfer(0);
if (!transfer) {
libusb_fill_bulk_transfer(transfer, fpi_dev_get_usb_dev(FP_DEV(dev)), upekdev->ep_out, fpi_ssm_mark_aborted(ssm, -ENOMEM);
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_failed(ssm, -ENOMEM); fpi_ssm_mark_aborted(ssm, -ENOMEM);
} }
} }
break; break;
case READ_DATA: case READ_DATA:
{ {
struct libusb_transfer *transfer = fpi_usb_alloc(); struct libusb_transfer *transfer = libusb_alloc_transfer(0);
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_dev_get_usb_dev(FP_DEV(dev)), upekdev->ep_in, data, libusb_fill_bulk_transfer(transfer, fpi_imgdev_get_usb_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);
@@ -135,16 +141,16 @@ static void activate_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_dat
if (r < 0) { if (r < 0) {
g_free(data); g_free(data);
libusb_free_transfer(transfer); libusb_free_transfer(transfer);
fpi_ssm_mark_failed(ssm, r); fpi_ssm_mark_aborted(ssm, r);
} }
} }
break; break;
} }
} }
static void activate_sm_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) static void activate_sm_complete(struct fpi_ssm *ssm)
{ {
struct fp_img_dev *dev = user_data; struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
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));
@@ -175,7 +181,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 = FP_INSTANCE_DATA(FP_DEV(dev)); struct upektc_dev *upekdev = fpi_imgdev_get_user_data(dev);
unsigned char *data = transfer->buffer; unsigned char *data = transfer->buffer;
if (transfer->status != LIBUSB_TRANSFER_COMPLETED) { if (transfer->status != LIBUSB_TRANSFER_COMPLETED) {
@@ -208,7 +214,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 = FP_INSTANCE_DATA(FP_DEV(dev)); struct upektc_dev *upekdev = fpi_imgdev_get_user_data(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);
@@ -220,9 +226,14 @@ static void finger_det_cmd_cb(struct libusb_transfer *t)
goto exit_free_transfer; goto exit_free_transfer;
} }
transfer = fpi_usb_alloc(); transfer = libusb_alloc_transfer(0);
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_dev_get_usb_dev(FP_DEV(dev)), upekdev->ep_in, data, IMAGE_SIZE, libusb_fill_bulk_transfer(transfer, fpi_imgdev_get_usb_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);
@@ -238,7 +249,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 = FP_INSTANCE_DATA(FP_DEV(dev)); struct upektc_dev *upekdev = fpi_imgdev_get_user_data(dev);
struct libusb_transfer *transfer; struct libusb_transfer *transfer;
G_DEBUG_HERE(); G_DEBUG_HERE();
@@ -247,8 +258,12 @@ static void start_finger_detection(struct fp_img_dev *dev)
return; return;
} }
transfer = fpi_usb_alloc(); transfer = libusb_alloc_transfer(0);
libusb_fill_bulk_transfer(transfer, fpi_dev_get_usb_dev(FP_DEV(dev)), upekdev->ep_out, if (!transfer) {
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);
@@ -268,31 +283,31 @@ enum capture_states {
static void capture_cmd_cb(struct libusb_transfer *transfer) static void capture_cmd_cb(struct libusb_transfer *transfer)
{ {
fpi_ssm *ssm = transfer->user_data; struct 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_failed(ssm, -EIO); fpi_ssm_mark_aborted(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)
{ {
fpi_ssm *ssm = transfer->user_data; struct 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_failed(ssm, -EIO); fpi_ssm_mark_aborted(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_failed(ssm, -EPROTO); fpi_ssm_mark_aborted(ssm, -EPROTO);
goto out; goto out;
} }
@@ -306,51 +321,59 @@ out:
libusb_free_transfer(transfer); libusb_free_transfer(transfer);
} }
static void capture_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) static void capture_run_state(struct fpi_ssm *ssm)
{ {
struct fp_img_dev *dev = user_data; struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct upektc_dev *upekdev = FP_INSTANCE_DATA(_dev); struct upektc_dev *upekdev = fpi_imgdev_get_user_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 = fpi_usb_alloc(); struct libusb_transfer *transfer = libusb_alloc_transfer(0);
if (!transfer) {
libusb_fill_bulk_transfer(transfer, fpi_dev_get_usb_dev(FP_DEV(dev)), upekdev->ep_out, fpi_ssm_mark_aborted(ssm, -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,
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_failed(ssm, -ENOMEM); fpi_ssm_mark_aborted(ssm, -ENOMEM);
} }
} }
break; break;
case CAPTURE_READ_DATA: case CAPTURE_READ_DATA:
{ {
struct libusb_transfer *transfer = fpi_usb_alloc(); struct libusb_transfer *transfer = libusb_alloc_transfer(0);
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_dev_get_usb_dev(FP_DEV(dev)), upekdev->ep_in, data, IMAGE_SIZE, libusb_fill_bulk_transfer(transfer, fpi_imgdev_get_usb_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_failed(ssm, r); fpi_ssm_mark_aborted(ssm, r);
} }
} }
break; break;
}; };
} }
static void capture_sm_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) static void capture_sm_complete(struct fpi_ssm *ssm)
{ {
struct fp_img_dev *dev = user_data; struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct upektc_dev *upekdev = FP_INSTANCE_DATA(_dev); struct upektc_dev *upekdev = fpi_imgdev_get_user_data(dev);
fp_dbg("Capture completed"); fp_dbg("Capture completed");
if (upekdev->deactivating) if (upekdev->deactivating)
@@ -364,24 +387,26 @@ static void capture_sm_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_da
static void start_capture(struct fp_img_dev *dev) static void start_capture(struct fp_img_dev *dev)
{ {
struct upektc_dev *upekdev = FP_INSTANCE_DATA(FP_DEV(dev)); struct upektc_dev *upekdev = fpi_imgdev_get_user_data(dev);
fpi_ssm *ssm; struct fpi_ssm *ssm;
if (upekdev->deactivating) { if (upekdev->deactivating) {
complete_deactivation(dev); complete_deactivation(dev);
return; return;
} }
ssm = fpi_ssm_new(FP_DEV(dev), capture_run_state, CAPTURE_NUM_STATES, dev); ssm = fpi_ssm_new(fpi_imgdev_get_dev(dev), capture_run_state, CAPTURE_NUM_STATES);
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) static int dev_activate(struct fp_img_dev *dev, enum fp_imgdev_state state)
{ {
struct upektc_dev *upekdev = FP_INSTANCE_DATA(FP_DEV(dev)); struct upektc_dev *upekdev = fpi_imgdev_get_user_data(dev);
fpi_ssm *ssm = fpi_ssm_new(FP_DEV(dev), activate_run_state, struct fpi_ssm *ssm = fpi_ssm_new(fpi_imgdev_get_dev(dev), activate_run_state,
ACTIVATE_NUM_STATES, dev); ACTIVATE_NUM_STATES);
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;
@@ -389,14 +414,14 @@ static int dev_activate(struct fp_img_dev *dev)
static void dev_deactivate(struct fp_img_dev *dev) static void dev_deactivate(struct fp_img_dev *dev)
{ {
struct upektc_dev *upekdev = FP_INSTANCE_DATA(FP_DEV(dev)); struct upektc_dev *upekdev = fpi_imgdev_get_user_data(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 = FP_INSTANCE_DATA(FP_DEV(dev)); struct upektc_dev *upekdev = fpi_imgdev_get_user_data(dev);
G_DEBUG_HERE(); G_DEBUG_HERE();
upekdev->deactivating = FALSE; upekdev->deactivating = FALSE;
@@ -409,14 +434,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_dev_get_usb_dev(FP_DEV(dev)), 0); r = libusb_claim_interface(fpi_imgdev_get_usb_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));
fp_dev_set_instance_data(FP_DEV(dev), upekdev); fpi_imgdev_set_user_data(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;
@@ -435,7 +460,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);
fp_dev_set_instance_data(FP_DEV(dev), NULL); fpi_imgdev_set_user_data(dev, NULL);
return -ENODEV; return -ENODEV;
break; break;
} }
@@ -446,9 +471,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 = FP_INSTANCE_DATA(FP_DEV(dev)); user_data = fpi_imgdev_get_user_data(dev);
g_free(user_data); g_free(user_data);
libusb_release_interface(fpi_dev_get_usb_dev(FP_DEV(dev)), 0); libusb_release_interface(fpi_imgdev_get_usb_dev(dev), 0);
fpi_imgdev_close_complete(dev); fpi_imgdev_close_complete(dev);
} }

View File

@@ -20,7 +20,6 @@
#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"
@@ -52,6 +51,50 @@ 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;
@@ -71,58 +114,61 @@ 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 static void upektc_img_submit_req(struct fpi_ssm *ssm,
upektc_img_submit_req(fpi_ssm *ssm, const unsigned char *buf, size_t buf_size, unsigned char seq,
struct fp_img_dev *dev, libusb_transfer_cb_fn cb)
const unsigned char *buf,
size_t buf_size,
unsigned char seq,
libusb_transfer_cb_fn cb)
{ {
struct upektc_img_dev *upekdev = FP_INSTANCE_DATA(FP_DEV(dev)); struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct libusb_transfer *transfer = fpi_usb_alloc(); struct upektc_img_dev *upekdev = fpi_imgdev_get_user_data(dev);
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_dev_get_usb_dev(FP_DEV(dev)), EP_OUT, upekdev->cmd, buf_size, libusb_fill_bulk_transfer(transfer, fpi_imgdev_get_usb_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_failed(ssm, r); fpi_ssm_mark_aborted(ssm, r);
} }
} }
static void static void upektc_img_read_data(struct fpi_ssm *ssm, size_t buf_size, size_t buf_offset, libusb_transfer_cb_fn cb)
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 = fpi_usb_alloc(); struct libusb_transfer *transfer = libusb_alloc_transfer(0);
struct upektc_img_dev *upekdev = FP_INSTANCE_DATA(FP_DEV(dev)); struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
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_dev_get_usb_dev(FP_DEV(dev)), EP_IN, upekdev->response + buf_offset, buf_size, libusb_fill_bulk_transfer(transfer, fpi_imgdev_get_usb_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_failed(ssm, r); fpi_ssm_mark_aborted(ssm, r);
} }
} }
@@ -141,11 +187,11 @@ enum capture_states {
static void capture_reqs_cb(struct libusb_transfer *transfer) static void capture_reqs_cb(struct libusb_transfer *transfer)
{ {
fpi_ssm *ssm = transfer->user_data; struct 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_failed(ssm, -EIO); fpi_ssm_mark_aborted(ssm, -EIO);
return; return;
} }
switch (fpi_ssm_get_cur_state(ssm)) { switch (fpi_ssm_get_cur_state(ssm)) {
@@ -178,16 +224,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)
{ {
fpi_ssm *ssm = transfer->user_data; struct 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 = FP_INSTANCE_DATA(FP_DEV(dev)); struct upektc_img_dev *upekdev = fpi_imgdev_get_user_data(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_failed(ssm, -EIO); fpi_ssm_mark_aborted(ssm, -EIO);
return; return;
} }
@@ -287,8 +333,8 @@ static void capture_read_data_cb(struct libusb_transfer *transfer)
fpi_ssm_mark_completed(ssm); fpi_ssm_mark_completed(ssm);
break; break;
default: default:
fp_err("Unknown response!\n"); fp_err("Uknown response!\n");
fpi_ssm_mark_failed(ssm, -EIO); fpi_ssm_mark_aborted(ssm, -EIO);
break; break;
} }
break; break;
@@ -297,51 +343,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_failed(ssm, -EIO); fpi_ssm_mark_aborted(ssm, -EIO);
} }
} }
static void capture_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) static void capture_run_state(struct fpi_ssm *ssm)
{ {
struct fp_img_dev *dev = user_data; struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct upektc_img_dev *upekdev = FP_INSTANCE_DATA(_dev); struct upektc_img_dev *upekdev = fpi_imgdev_get_user_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, dev, upek2020_init_capture, sizeof(upek2020_init_capture), upektc_img_submit_req(ssm, 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, dev, SHORT_RESPONSE_SIZE, 0, capture_read_data_cb); upektc_img_read_data(ssm, SHORT_RESPONSE_SIZE, 0, capture_read_data_cb);
else else
upektc_img_read_data(ssm, dev, MAX_RESPONSE_SIZE - SHORT_RESPONSE_SIZE, upektc_img_read_data(ssm, 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, dev, upek2020_ack_00_28, sizeof(upek2020_ack_00_28), upektc_img_submit_req(ssm, 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, dev, upek2020_ack_08, sizeof(upek2020_ack_08), upektc_img_submit_req(ssm, 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, dev, upek2020_ack_frame, sizeof(upek2020_ack_frame), upektc_img_submit_req(ssm, 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(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) static void capture_sm_complete(struct fpi_ssm *ssm)
{ {
struct fp_img_dev *dev = user_data; struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct upektc_img_dev *upekdev = FP_INSTANCE_DATA(_dev); struct upektc_img_dev *upekdev = fpi_imgdev_get_user_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);
@@ -357,12 +403,13 @@ static void capture_sm_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_da
static void start_capture(struct fp_img_dev *dev) static void start_capture(struct fp_img_dev *dev)
{ {
struct upektc_img_dev *upekdev = FP_INSTANCE_DATA(FP_DEV(dev)); struct upektc_img_dev *upekdev = fpi_imgdev_get_user_data(dev);
fpi_ssm *ssm; struct fpi_ssm *ssm;
upekdev->image_size = 0; upekdev->image_size = 0;
ssm = fpi_ssm_new(FP_DEV(dev), capture_run_state, CAPTURE_NUM_STATES, dev); ssm = fpi_ssm_new(fpi_imgdev_get_dev(dev), capture_run_state, CAPTURE_NUM_STATES);
fpi_ssm_set_user_data(ssm, dev);
fpi_ssm_start(ssm, capture_sm_complete); fpi_ssm_start(ssm, capture_sm_complete);
} }
@@ -376,49 +423,49 @@ enum deactivate_states {
static void deactivate_reqs_cb(struct libusb_transfer *transfer) static void deactivate_reqs_cb(struct libusb_transfer *transfer)
{ {
fpi_ssm *ssm = transfer->user_data; struct 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_failed(ssm, -EIO); fpi_ssm_mark_aborted(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)
{ {
fpi_ssm *ssm = transfer->user_data; struct 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_failed(ssm, -EIO); fpi_ssm_mark_aborted(ssm, -EIO);
} }
} }
static void deactivate_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) static void deactivate_run_state(struct fpi_ssm *ssm)
{ {
struct fp_img_dev *dev = user_data; struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct upektc_img_dev *upekdev = FP_INSTANCE_DATA(_dev); struct upektc_img_dev *upekdev = fpi_imgdev_get_user_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, dev, upek2020_deinit, sizeof(upek2020_deinit), upektc_img_submit_req(ssm, 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, dev, SHORT_RESPONSE_SIZE, 0, deactivate_read_data_cb); upektc_img_read_data(ssm, SHORT_RESPONSE_SIZE, 0, deactivate_read_data_cb);
break; break;
}; };
} }
static void deactivate_sm_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) static void deactivate_sm_complete(struct fpi_ssm *ssm)
{ {
struct fp_img_dev *dev = user_data; struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct upektc_img_dev *upekdev = FP_INSTANCE_DATA(_dev); struct upektc_img_dev *upekdev = fpi_imgdev_get_user_data(dev);
int err = fpi_ssm_get_error(ssm); int err = fpi_ssm_get_error(ssm);
fp_dbg("Deactivate completed"); fp_dbg("Deactivate completed");
@@ -435,12 +482,13 @@ static void deactivate_sm_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user
static void start_deactivation(struct fp_img_dev *dev) static void start_deactivation(struct fp_img_dev *dev)
{ {
struct upektc_img_dev *upekdev = FP_INSTANCE_DATA(FP_DEV(dev)); struct upektc_img_dev *upekdev = fpi_imgdev_get_user_data(dev);
fpi_ssm *ssm; struct fpi_ssm *ssm;
upekdev->image_size = 0; upekdev->image_size = 0;
ssm = fpi_ssm_new(FP_DEV(dev), deactivate_run_state, DEACTIVATE_NUM_STATES, dev); ssm = fpi_ssm_new(fpi_imgdev_get_dev(dev), deactivate_run_state, DEACTIVATE_NUM_STATES);
fpi_ssm_set_user_data(ssm, dev);
fpi_ssm_start(ssm, deactivate_sm_complete); fpi_ssm_start(ssm, deactivate_sm_complete);
} }
@@ -462,44 +510,45 @@ enum activate_states {
static void init_reqs_ctrl_cb(struct libusb_transfer *transfer) static void init_reqs_ctrl_cb(struct libusb_transfer *transfer)
{ {
fpi_ssm *ssm = transfer->user_data; struct 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_failed(ssm, -EIO); fpi_ssm_mark_aborted(ssm, -EIO);
} }
} }
static void init_reqs_cb(struct libusb_transfer *transfer) static void init_reqs_cb(struct libusb_transfer *transfer)
{ {
fpi_ssm *ssm = transfer->user_data; struct 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_failed(ssm, -EIO); fpi_ssm_mark_aborted(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)
{ {
fpi_ssm *ssm = transfer->user_data; struct 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_failed(ssm, -EIO); fpi_ssm_mark_aborted(ssm, -EIO);
} }
} }
static void activate_run_state(fpi_ssm *ssm, struct fp_dev *dev, void *user_data) static void activate_run_state(struct fpi_ssm *ssm)
{ {
struct libusb_transfer *transfer; struct libusb_transfer *transfer;
struct fp_img_dev *idev = user_data; struct fp_img_dev *idev = fpi_ssm_get_user_data(ssm);
struct upektc_img_dev *upekdev = FP_INSTANCE_DATA(dev); struct upektc_img_dev *upekdev = fpi_imgdev_get_user_data(idev);
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)) {
@@ -508,7 +557,11 @@ static void activate_run_state(fpi_ssm *ssm, struct fp_dev *dev, void *user_data
{ {
unsigned char *data; unsigned char *data;
transfer = fpi_usb_alloc(); transfer = libusb_alloc_transfer(0);
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;
@@ -521,24 +574,24 @@ static void activate_run_state(fpi_ssm *ssm, struct fp_dev *dev, void *user_data
if (r < 0) { if (r < 0) {
g_free(data); g_free(data);
libusb_free_transfer(transfer); libusb_free_transfer(transfer);
fpi_ssm_mark_failed(ssm, r); fpi_ssm_mark_aborted(ssm, r);
} }
} }
break; break;
case ACTIVATE_INIT_1: case ACTIVATE_INIT_1:
upektc_img_submit_req(ssm, idev, upek2020_init_1, sizeof(upek2020_init_1), upektc_img_submit_req(ssm, 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, idev, upek2020_init_2, sizeof(upek2020_init_2), upektc_img_submit_req(ssm, 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, idev, upek2020_init_3, sizeof(upek2020_init_3), upektc_img_submit_req(ssm, 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, idev, upek2020_init_4, sizeof(upek2020_init_4), upektc_img_submit_req(ssm, 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++;
@@ -549,14 +602,14 @@ static void activate_run_state(fpi_ssm *ssm, struct fp_dev *dev, void *user_data
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, idev, SHORT_RESPONSE_SIZE, 0, init_read_data_cb); upektc_img_read_data(ssm, SHORT_RESPONSE_SIZE, 0, init_read_data_cb);
break; break;
} }
} }
static void activate_sm_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) static void activate_sm_complete(struct fpi_ssm *ssm)
{ {
struct fp_img_dev *dev = user_data; struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
int err = fpi_ssm_get_error(ssm); int err = fpi_ssm_get_error(ssm);
fpi_ssm_free(ssm); fpi_ssm_free(ssm);
@@ -567,11 +620,12 @@ static void activate_sm_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_d
start_capture(dev); start_capture(dev);
} }
static int dev_activate(struct fp_img_dev *dev) static int dev_activate(struct fp_img_dev *dev, enum fp_imgdev_state state)
{ {
struct upektc_img_dev *upekdev = FP_INSTANCE_DATA(FP_DEV(dev)); struct upektc_img_dev *upekdev = fpi_imgdev_get_user_data(dev);
fpi_ssm *ssm = fpi_ssm_new(FP_DEV(dev), activate_run_state, struct fpi_ssm *ssm = fpi_ssm_new(fpi_imgdev_get_dev(dev), activate_run_state,
ACTIVATE_NUM_STATES, dev); ACTIVATE_NUM_STATES);
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;
@@ -579,7 +633,7 @@ static int dev_activate(struct fp_img_dev *dev)
static void dev_deactivate(struct fp_img_dev *dev) static void dev_deactivate(struct fp_img_dev *dev)
{ {
struct upektc_img_dev *upekdev = FP_INSTANCE_DATA(FP_DEV(dev)); struct upektc_img_dev *upekdev = fpi_imgdev_get_user_data(dev);
upekdev->deactivating = TRUE; upekdev->deactivating = TRUE;
} }
@@ -590,23 +644,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_dev_get_usb_dev(FP_DEV(dev)), 0); r = libusb_claim_interface(fpi_imgdev_get_usb_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));
fp_dev_set_instance_data(FP_DEV(dev), upekdev); fpi_imgdev_set_user_data(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 = FP_INSTANCE_DATA(FP_DEV(dev)); struct upektc_img_dev *upekdev = fpi_imgdev_get_user_data(dev);
g_free(upekdev); g_free(upekdev);
libusb_release_interface(fpi_dev_get_usb_dev(FP_DEV(dev)), 0); libusb_release_interface(fpi_imgdev_get_usb_dev(dev), 0);
fpi_imgdev_close_complete(dev); fpi_imgdev_close_complete(dev);
} }

View File

@@ -28,8 +28,6 @@
#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)
@@ -45,7 +43,49 @@ 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
@@ -91,7 +131,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 = fpi_usb_alloc(); struct libusb_transfer *transfer = libusb_alloc_transfer(0);
uint16_t crc; uint16_t crc;
const char *ciao = "Ciao"; const char *ciao = "Ciao";
@@ -100,6 +140,9 @@ 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;
@@ -135,7 +178,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 = FP_INSTANCE_DATA(dev); struct upekts_dev *upekdev = fpi_dev_get_user_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;
@@ -365,9 +408,12 @@ 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 = fpi_usb_alloc(); struct libusb_transfer *etransfer = libusb_alloc_transfer(0);
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);
@@ -402,9 +448,14 @@ 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 = fpi_usb_alloc(); struct libusb_transfer *transfer = libusb_alloc_transfer(0);
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);
@@ -474,28 +525,25 @@ enum initsm_states {
INITSM_NUM_STATES, INITSM_NUM_STATES,
}; };
static void static void initsm_read_msg_response_cb(struct fpi_ssm *ssm,
initsm_read_msg_response_cb(fpi_ssm *ssm, enum read_msg_status status, uint8_t seq,
struct fp_dev *dev, unsigned char expect_subcmd, unsigned char subcmd)
enum read_msg_status status,
uint8_t seq,
unsigned char expect_subcmd,
unsigned char subcmd)
{ {
struct upekts_dev *upekdev = FP_INSTANCE_DATA(dev); struct fp_dev *dev = fpi_ssm_get_dev(ssm);
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_failed(ssm, -1); fpi_ssm_mark_aborted(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_failed(ssm, -1); fpi_ssm_mark_aborted(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_failed(ssm, -1); fpi_ssm_mark_aborted(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);
@@ -506,7 +554,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((fpi_ssm *) user_data, dev, status, seq, initsm_read_msg_response_cb((struct fpi_ssm *) user_data, status, seq,
0x0b, subcmd); 0x0b, subcmd);
} }
@@ -514,7 +562,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((fpi_ssm *) user_data, dev, status, seq, initsm_read_msg_response_cb((struct fpi_ssm *) user_data, status, seq,
0x0c, subcmd); 0x0c, subcmd);
} }
@@ -522,7 +570,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((fpi_ssm *) user_data, dev, status, seq, initsm_read_msg_response_cb((struct fpi_ssm *) user_data, status, seq,
0x08, subcmd); 0x08, subcmd);
} }
@@ -530,7 +578,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((fpi_ssm *) user_data, dev, status, seq, initsm_read_msg_response_cb((struct fpi_ssm *) user_data, status, seq,
0x07, subcmd); 0x07, subcmd);
} }
@@ -538,33 +586,30 @@ 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((fpi_ssm *) user_data, dev, status, seq, initsm_read_msg_response_cb((struct fpi_ssm *) user_data, status, seq,
0x06, subcmd); 0x06, subcmd);
} }
static void static void initsm_read_msg_cmd_cb(struct fpi_ssm *ssm,
initsm_read_msg_cmd_cb(fpi_ssm *ssm, enum read_msg_status status, uint8_t expect_seq, uint8_t seq)
struct fp_dev *dev,
enum read_msg_status status,
uint8_t expect_seq,
uint8_t seq)
{ {
struct upekts_dev *upekdev = FP_INSTANCE_DATA(dev); struct fp_dev *dev = fpi_ssm_get_dev(ssm);
struct upekts_dev *upekdev = fpi_dev_get_user_data(dev);
if (status == READ_MSG_ERROR) { if (status == READ_MSG_ERROR) {
fpi_ssm_mark_failed(ssm, -1); fpi_ssm_mark_aborted(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_failed(ssm, -1); fpi_ssm_mark_aborted(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_failed(ssm, -1); fpi_ssm_mark_aborted(ssm, -1);
return; return;
} }
@@ -575,43 +620,41 @@ 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((fpi_ssm *) user_data, dev, status, 5, seq); initsm_read_msg_cmd_cb((struct fpi_ssm *) user_data, 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((fpi_ssm *) user_data, dev, status, 3, seq); initsm_read_msg_cmd_cb((struct fpi_ssm *) user_data, status, 3, seq);
} }
static void ctrl400_cb(struct libusb_transfer *transfer) static void ctrl400_cb(struct libusb_transfer *transfer)
{ {
fpi_ssm *ssm = transfer->user_data; struct 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_failed(ssm, -1); fpi_ssm_mark_aborted(ssm, -1);
g_free(transfer->buffer); g_free(transfer->buffer);
libusb_free_transfer(transfer); libusb_free_transfer(transfer);
} }
static void static void initsm_read_msg_handler(struct fpi_ssm *ssm,
initsm_read_msg_handler(fpi_ssm *ssm, read_msg_cb_fn callback)
struct fp_dev *dev,
read_msg_cb_fn callback)
{ {
int r = read_msg_async(dev, callback, ssm); int r = read_msg_async(fpi_ssm_get_dev(ssm), 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_failed(ssm, r); fpi_ssm_mark_aborted(ssm, r);
} }
} }
static void initsm_send_msg_cb(struct libusb_transfer *transfer) static void initsm_send_msg_cb(struct libusb_transfer *transfer)
{ {
fpi_ssm *ssm = transfer->user_data; struct 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));
@@ -619,25 +662,22 @@ 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_failed(ssm, -1); fpi_ssm_mark_aborted(ssm, -1);
} }
libusb_free_transfer(transfer); libusb_free_transfer(transfer);
} }
static void static void initsm_send_msg28_handler(struct fpi_ssm *ssm,
initsm_send_msg28_handler(fpi_ssm *ssm, unsigned char subcmd, const unsigned char *data, uint16_t innerlen)
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_failed(ssm, -ENOMEM); fpi_ssm_mark_aborted(ssm, -ENOMEM);
return; return;
} }
@@ -646,13 +686,14 @@ initsm_send_msg28_handler(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_failed(ssm, -EIO); fpi_ssm_mark_aborted(ssm, -EIO);
} }
} }
static void initsm_run_state(fpi_ssm *ssm, struct fp_dev *dev, void *user_data) static void initsm_run_state(struct fpi_ssm *ssm)
{ {
struct upekts_dev *upekdev = FP_INSTANCE_DATA(dev); struct fp_dev *dev = fpi_ssm_get_dev(ssm);
struct upekts_dev *upekdev = fpi_dev_get_user_data(dev);
struct libusb_transfer *transfer; struct libusb_transfer *transfer;
int r; int r;
@@ -660,7 +701,12 @@ static void initsm_run_state(fpi_ssm *ssm, struct fp_dev *dev, void *user_data)
case WRITE_CTRL400: ; case WRITE_CTRL400: ;
unsigned char *data; unsigned char *data;
transfer = fpi_usb_alloc(); transfer = libusb_alloc_transfer(0);
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);
@@ -671,17 +717,17 @@ static void initsm_run_state(fpi_ssm *ssm, struct fp_dev *dev, void *user_data)
if (r < 0) { if (r < 0) {
g_free(data); g_free(data);
libusb_free_transfer(transfer); libusb_free_transfer(transfer);
fpi_ssm_mark_failed(ssm, r); fpi_ssm_mark_aborted(ssm, r);
} }
break; break;
case READ_MSG03: case READ_MSG03:
initsm_read_msg_handler(ssm, dev, read_msg03_cb); initsm_read_msg_handler(ssm, 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_failed(ssm, -ENOMEM); fpi_ssm_mark_aborted(ssm, -ENOMEM);
break; break;
} }
@@ -689,52 +735,51 @@ static void initsm_run_state(fpi_ssm *ssm, struct fp_dev *dev, void *user_data)
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_failed(ssm, r); fpi_ssm_mark_aborted(ssm, r);
} }
break; break;
case READ_MSG05: case READ_MSG05:
initsm_read_msg_handler(ssm, dev, read_msg05_cb); initsm_read_msg_handler(ssm, 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, dev, 0x06, &dummy28_06, 1); initsm_send_msg28_handler(ssm, 0x06, &dummy28_06, 1);
break; break;
case READ28_06: case READ28_06:
initsm_read_msg_handler(ssm, dev, read28_06_cb); initsm_read_msg_handler(ssm, 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, dev, 0x07, &dummy28_07, 1); initsm_send_msg28_handler(ssm, 0x07, &dummy28_07, 1);
break; break;
case READ28_07: case READ28_07:
initsm_read_msg_handler(ssm, dev, read28_07_cb); initsm_read_msg_handler(ssm, read28_07_cb);
break; break;
case SEND28_08: case SEND28_08:
initsm_send_msg28_handler(ssm, dev, 0x08, init28_08, sizeof(init28_08)); initsm_send_msg28_handler(ssm, 0x08, init28_08, sizeof(init28_08));
break; break;
case READ28_08: case READ28_08:
initsm_read_msg_handler(ssm, dev, read28_08_cb); initsm_read_msg_handler(ssm, read28_08_cb);
break; break;
case SEND28_0C: case SEND28_0C:
initsm_send_msg28_handler(ssm, dev, 0x0c, init28_0c, sizeof(init28_0c)); initsm_send_msg28_handler(ssm, 0x0c, init28_0c, sizeof(init28_0c));
break; break;
case READ28_0C: case READ28_0C:
initsm_read_msg_handler(ssm, dev, read28_0c_cb); initsm_read_msg_handler(ssm, read28_0c_cb);
break; break;
case SEND28_0B: case SEND28_0B:
initsm_send_msg28_handler(ssm, dev, 0x0b, init28_0b, sizeof(init28_0b)); initsm_send_msg28_handler(ssm, 0x0b, init28_0b, sizeof(init28_0b));
break; break;
case READ28_0B: case READ28_0B:
initsm_read_msg_handler(ssm, dev, read28_0b_cb); initsm_read_msg_handler(ssm, read28_0b_cb);
break; break;
} }
} }
static fpi_ssm *initsm_new(struct fp_dev *dev, static struct fpi_ssm *initsm_new(struct fp_dev *dev)
void *user_data)
{ {
return fpi_ssm_new(dev, initsm_run_state, INITSM_NUM_STATES, user_data); return fpi_ssm_new(dev, initsm_run_state, INITSM_NUM_STATES);
} }
enum deinitsm_states { enum deinitsm_states {
@@ -745,11 +790,11 @@ enum deinitsm_states {
static void send_resp07_cb(struct libusb_transfer *transfer) static void send_resp07_cb(struct libusb_transfer *transfer)
{ {
fpi_ssm *ssm = transfer->user_data; struct fpi_ssm *ssm = transfer->user_data;
if (transfer->status != LIBUSB_TRANSFER_COMPLETED) if (transfer->status != LIBUSB_TRANSFER_COMPLETED)
fpi_ssm_mark_failed(ssm, -EIO); fpi_ssm_mark_aborted(ssm, -EIO);
else if (transfer->length != transfer->actual_length) else if (transfer->length != transfer->actual_length)
fpi_ssm_mark_failed(ssm, -EPROTO); fpi_ssm_mark_aborted(ssm, -EPROTO);
else else
fpi_ssm_next_state(ssm); fpi_ssm_next_state(ssm);
libusb_free_transfer(transfer); libusb_free_transfer(transfer);
@@ -759,29 +804,30 @@ 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)
{ {
fpi_ssm *ssm = user_data; struct fpi_ssm *ssm = user_data;
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_failed(ssm, -1); fpi_ssm_mark_aborted(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_failed(ssm, -1); fpi_ssm_mark_aborted(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_failed(ssm, -1); fpi_ssm_mark_aborted(ssm, -1);
return; return;
} }
fpi_ssm_next_state(ssm); fpi_ssm_next_state(ssm);
} }
static void deinitsm_state_handler(fpi_ssm *ssm, struct fp_dev *dev, void *user_data) static void deinitsm_state_handler(struct fpi_ssm *ssm)
{ {
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)) {
@@ -792,7 +838,7 @@ static void deinitsm_state_handler(fpi_ssm *ssm, struct fp_dev *dev, void *user_
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_failed(ssm, -ENOMEM); fpi_ssm_mark_aborted(ssm, -ENOMEM);
break; break;
} }
@@ -800,20 +846,20 @@ static void deinitsm_state_handler(fpi_ssm *ssm, struct fp_dev *dev, void *user_
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_failed(ssm, r); fpi_ssm_mark_aborted(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_failed(ssm, r); fpi_ssm_mark_aborted(ssm, r);
break; break;
} }
} }
static fpi_ssm *deinitsm_new(struct fp_dev *dev) static struct fpi_ssm *deinitsm_new(struct fp_dev *dev)
{ {
return fpi_ssm_new(dev, deinitsm_state_handler, DEINITSM_NUM_STATES, NULL); return fpi_ssm_new(dev, deinitsm_state_handler, DEINITSM_NUM_STATES);
} }
static int dev_init(struct fp_dev *dev, unsigned long driver_data) static int dev_init(struct fp_dev *dev, unsigned long driver_data)
@@ -829,7 +875,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 */
fp_dev_set_instance_data(dev, upekdev); fpi_dev_set_user_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);
@@ -838,10 +884,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)
{ {
struct upekts_dev *upekdev = FP_INSTANCE_DATA(dev); void *user_data;
libusb_release_interface(fpi_dev_get_usb_dev(dev), 0); libusb_release_interface(fpi_dev_get_usb_dev(dev), 0);
g_free(upekdev); user_data = fpi_dev_get_user_data(dev);
g_free(user_data);
fpi_drvcb_close_complete(dev); fpi_drvcb_close_complete(dev);
} }
@@ -863,14 +909,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(fpi_ssm *initsm, struct fp_dev *_dev, void *user_data) static void enroll_start_sm_cb_initsm(struct fpi_ssm *initsm)
{ {
fpi_ssm *enroll_start_ssm = user_data; struct fpi_ssm *enroll_start_ssm = fpi_ssm_get_user_data(initsm);
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_failed(enroll_start_ssm, error); fpi_ssm_mark_aborted(enroll_start_ssm, error);
else else
fpi_ssm_next_state(enroll_start_ssm); fpi_ssm_next_state(enroll_start_ssm);
} }
@@ -878,11 +924,11 @@ static void enroll_start_sm_cb_initsm(fpi_ssm *initsm, struct fp_dev *_dev, void
/* 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)
{ {
fpi_ssm *ssm = transfer->user_data; struct fpi_ssm *ssm = transfer->user_data;
if (transfer->status != LIBUSB_TRANSFER_COMPLETED) if (transfer->status != LIBUSB_TRANSFER_COMPLETED)
fpi_ssm_mark_failed(ssm, -EIO); fpi_ssm_mark_aborted(ssm, -EIO);
else if (transfer->length != transfer->actual_length) else if (transfer->length != transfer->actual_length)
fpi_ssm_mark_failed(ssm, -EPROTO); fpi_ssm_mark_aborted(ssm, -EPROTO);
else else
fpi_ssm_next_state(ssm); fpi_ssm_next_state(ssm);
libusb_free_transfer(transfer); libusb_free_transfer(transfer);
@@ -892,32 +938,34 @@ 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 = FP_INSTANCE_DATA(dev); struct upekts_dev *upekdev = fpi_dev_get_user_data(dev);
fpi_ssm *ssm = user_data; struct 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_failed(ssm, -1); fpi_ssm_mark_aborted(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_failed(ssm, -1); fpi_ssm_mark_aborted(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_failed(ssm, -1); fpi_ssm_mark_aborted(ssm, -1);
} else { } else {
fpi_ssm_next_state(ssm); fpi_ssm_next_state(ssm);
} }
} }
static void enroll_start_sm_run_state(fpi_ssm *ssm, struct fp_dev *dev, void *user_data) static void enroll_start_sm_run_state(struct fpi_ssm *ssm)
{ {
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: ;
fpi_ssm *initsm = initsm_new(dev, ssm); struct fpi_ssm *initsm = initsm_new(dev);
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: ;
@@ -925,7 +973,7 @@ static void enroll_start_sm_run_state(fpi_ssm *ssm, struct fp_dev *dev, void *us
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_failed(ssm, -ENOMEM); fpi_ssm_mark_aborted(ssm, -ENOMEM);
break; break;
} }
@@ -933,7 +981,7 @@ static void enroll_start_sm_run_state(fpi_ssm *ssm, struct fp_dev *dev, void *us
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_failed(ssm, r); fpi_ssm_mark_aborted(ssm, r);
} }
break; break;
case READ_ENROLL_MSG28: ; case READ_ENROLL_MSG28: ;
@@ -943,7 +991,7 @@ static void enroll_start_sm_run_state(fpi_ssm *ssm, struct fp_dev *dev, void *us
* 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_failed(ssm, r); fpi_ssm_mark_aborted(ssm, r);
break; break;
} }
} }
@@ -953,7 +1001,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 = FP_INSTANCE_DATA(dev); struct upekts_dev *upekdev = fpi_dev_get_user_data(dev);
unsigned char status; unsigned char status;
int result = 0; int result = 0;
@@ -970,9 +1018,6 @@ 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) {
@@ -1042,7 +1087,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));
fpi_print_data_add_item(fdata, item); fdata->prints = g_slist_prepend(fdata->prints, item);
result = FP_ENROLL_COMPLETE; result = FP_ENROLL_COMPLETE;
} }
@@ -1105,8 +1150,9 @@ static void enroll_iterate(struct fp_dev *dev)
} }
} }
static void enroll_started(fpi_ssm *ssm, struct fp_dev *dev, void *user_data) static void enroll_started(struct fpi_ssm *ssm)
{ {
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))
@@ -1117,41 +1163,41 @@ static void enroll_started(fpi_ssm *ssm, struct fp_dev *dev, void *user_data)
static int enroll_start(struct fp_dev *dev) static int enroll_start(struct fp_dev *dev)
{ {
struct upekts_dev *upekdev = FP_INSTANCE_DATA(dev); struct upekts_dev *upekdev = fpi_dev_get_user_data(dev);
/* do_init state machine first */ /* do_init state machine first */
fpi_ssm *ssm = fpi_ssm_new(dev, enroll_start_sm_run_state, struct fpi_ssm *ssm = fpi_ssm_new(dev, enroll_start_sm_run_state,
ENROLL_START_NUM_STATES, NULL); ENROLL_START_NUM_STATES);
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(fpi_ssm *ssm, struct fp_dev *dev, void *user_data) static void enroll_stop_deinit_cb(struct fpi_ssm *ssm)
{ {
/* don't really care about errors */ /* don't really care about errors */
fpi_drvcb_enroll_stopped(dev); fpi_drvcb_enroll_stopped(fpi_ssm_get_dev(ssm));
fpi_ssm_free(ssm); fpi_ssm_free(ssm);
} }
static int enroll_stop(struct fp_dev *dev) static int enroll_stop(struct fp_dev *dev)
{ {
fpi_ssm *ssm = deinitsm_new(dev); struct 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(fpi_ssm *ssm, struct fp_dev *dev, void *user_data) static void verify_stop_deinit_cb(struct fpi_ssm *ssm)
{ {
/* don't really care about errors */ /* don't really care about errors */
fpi_drvcb_verify_stopped(dev); fpi_drvcb_verify_stopped(fpi_ssm_get_dev(ssm));
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)
{ {
fpi_ssm *ssm = deinitsm_new(dev); struct fpi_ssm *ssm = deinitsm_new(dev);
fpi_ssm_start(ssm, verify_stop_deinit_cb); fpi_ssm_start(ssm, verify_stop_deinit_cb);
} }
@@ -1168,14 +1214,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(fpi_ssm *initsm, struct fp_dev *_dev, void *user_data) static void verify_start_sm_cb_initsm(struct fpi_ssm *initsm)
{ {
fpi_ssm *verify_start_ssm = user_data; struct fpi_ssm *verify_start_ssm = fpi_ssm_get_user_data(initsm);
int err; int err;
err = fpi_ssm_get_error(initsm); err = fpi_ssm_get_error(initsm);
if (err) if (err)
fpi_ssm_mark_failed(verify_start_ssm, err); fpi_ssm_mark_aborted(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);
@@ -1183,28 +1229,30 @@ static void verify_start_sm_cb_initsm(fpi_ssm *initsm, struct fp_dev *_dev, void
static void verify_init_2803_cb(struct libusb_transfer *transfer) static void verify_init_2803_cb(struct libusb_transfer *transfer)
{ {
fpi_ssm *ssm = transfer->user_data; struct fpi_ssm *ssm = transfer->user_data;
if (transfer->status != LIBUSB_TRANSFER_COMPLETED) if (transfer->status != LIBUSB_TRANSFER_COMPLETED)
fpi_ssm_mark_failed(ssm, -EIO); fpi_ssm_mark_aborted(ssm, -EIO);
else if (transfer->length != transfer->actual_length) else if (transfer->length != transfer->actual_length)
fpi_ssm_mark_failed(ssm, -EPROTO); fpi_ssm_mark_aborted(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(fpi_ssm *ssm, struct fp_dev *dev, void *user_data) static void verify_start_sm_run_state(struct fpi_ssm *ssm)
{ {
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: ;
fpi_ssm *initsm = initsm_new(dev, ssm); struct fpi_ssm *initsm = initsm_new(dev);
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 = fpi_print_data_get_item(print); struct fp_print_data_item *item = print->prints->data;
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;
@@ -1215,7 +1263,7 @@ static void verify_start_sm_run_state(fpi_ssm *ssm, struct fp_dev *dev, void *us
verify_init_2803_cb, ssm); verify_init_2803_cb, ssm);
g_free(data); g_free(data);
if (!transfer) { if (!transfer) {
fpi_ssm_mark_failed(ssm, -ENOMEM); fpi_ssm_mark_aborted(ssm, -ENOMEM);
break; break;
} }
@@ -1223,7 +1271,7 @@ static void verify_start_sm_run_state(fpi_ssm *ssm, struct fp_dev *dev, void *us
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_failed(ssm, -EIO); fpi_ssm_mark_aborted(ssm, -EIO);
} }
break; break;
} }
@@ -1309,7 +1357,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 = FP_INSTANCE_DATA(dev); struct upekts_dev *upekdev = fpi_dev_get_user_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);
@@ -1348,7 +1396,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 = FP_INSTANCE_DATA(dev); struct upekts_dev *upekdev = fpi_dev_get_user_data(dev);
if (upekdev->stop_verify) { if (upekdev->stop_verify) {
do_verify_stop(dev); do_verify_stop(dev);
@@ -1381,9 +1429,10 @@ static void verify_iterate(struct fp_dev *dev)
} }
} }
static void verify_started(fpi_ssm *ssm, struct fp_dev *dev, void *user_data) static void verify_started(struct fpi_ssm *ssm)
{ {
struct upekts_dev *upekdev = FP_INSTANCE_DATA(dev); struct fp_dev *dev = fpi_ssm_get_dev(ssm);
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)) {
@@ -1396,9 +1445,9 @@ static void verify_started(fpi_ssm *ssm, struct fp_dev *dev, void *user_data)
static int verify_start(struct fp_dev *dev) static int verify_start(struct fp_dev *dev)
{ {
struct upekts_dev *upekdev = FP_INSTANCE_DATA(dev); struct upekts_dev *upekdev = fpi_dev_get_user_data(dev);
fpi_ssm *ssm = fpi_ssm_new(dev, verify_start_sm_run_state, struct fpi_ssm *ssm = fpi_ssm_new(dev, verify_start_sm_run_state,
VERIFY_NUM_STATES, NULL); VERIFY_NUM_STATES);
upekdev->stop_verify = FALSE; upekdev->stop_verify = FALSE;
fpi_ssm_start(ssm, verify_started); fpi_ssm_start(ssm, verify_started);
return 0; return 0;
@@ -1406,7 +1455,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 = FP_INSTANCE_DATA(dev); struct upekts_dev *upekdev = fpi_dev_get_user_data(dev);
if (!iterating) if (!iterating)
do_verify_stop(dev); do_verify_stop(dev);

View File

@@ -120,10 +120,9 @@ struct uru4k_dev {
unsigned char last_reg_rd[16]; unsigned char last_reg_rd[16];
unsigned char last_hwstat; unsigned char last_hwstat;
fpi_usb_transfer *irq_transfer; struct libusb_transfer *irq_transfer;
fpi_usb_transfer *img_transfer; struct libusb_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;
@@ -136,7 +135,7 @@ struct uru4k_dev {
unsigned char powerup_hwstat; unsigned char powerup_hwstat;
int scanpwr_irq_timeouts; int scanpwr_irq_timeouts;
fpi_timeout *scanpwr_irq_timeout; struct fpi_timeout *scanpwr_irq_timeout;
int fwfixer_offset; int fwfixer_offset;
unsigned char fwfixer_value; unsigned char fwfixer_value;
@@ -187,10 +186,13 @@ 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 = fpi_usb_alloc(); struct libusb_transfer *transfer = libusb_alloc_transfer(0);
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;
@@ -199,7 +201,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_dev_get_usb_dev(FP_DEV(dev)), data, write_regs_cb, libusb_fill_control_transfer(transfer, fpi_imgdev_get_usb_dev(dev), data, write_regs_cb,
wrdata, CTRL_TIMEOUT); wrdata, CTRL_TIMEOUT);
r = libusb_submit_transfer(transfer); r = libusb_submit_transfer(transfer);
@@ -251,10 +253,13 @@ 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 = fpi_usb_alloc(); struct libusb_transfer *transfer = libusb_alloc_transfer(0);
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;
@@ -262,7 +267,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_dev_get_usb_dev(FP_DEV(dev)), data, read_regs_cb, libusb_fill_control_transfer(transfer, fpi_imgdev_get_usb_dev(dev), data, read_regs_cb,
rrdata, CTRL_TIMEOUT); rrdata, CTRL_TIMEOUT);
r = libusb_submit_transfer(transfer); r = libusb_submit_transfer(transfer);
@@ -296,30 +301,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
* an interrupt to the host. Maybe? * and 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)
{ {
fpi_ssm *ssm = user_data; struct 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_failed(ssm, status); fpi_ssm_mark_aborted(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)
{ {
fpi_ssm *ssm = user_data; struct fpi_ssm *ssm = user_data;
struct uru4k_dev *urudev = FP_INSTANCE_DATA(FP_DEV(dev)); struct uru4k_dev *urudev = fpi_imgdev_get_user_data(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_failed(ssm, status); fpi_ssm_mark_aborted(ssm, status);
return; return;
} }
@@ -341,7 +346,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_failed(ssm, r); fpi_ssm_mark_aborted(ssm, r);
} }
/* /*
@@ -349,16 +354,15 @@ 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 static void sm_do_challenge_response(struct fpi_ssm *ssm)
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_failed(ssm, r); fpi_ssm_mark_aborted(ssm, r);
} }
/***** INTERRUPT HANDLING *****/ /***** INTERRUPT HANDLING *****/
@@ -367,13 +371,10 @@ sm_do_challenge_response(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 = FP_IMG_DEV(_dev); struct fp_img_dev *dev = transfer->user_data;
struct uru4k_dev *urudev = FP_INSTANCE_DATA(_dev); struct uru4k_dev *urudev = fpi_imgdev_get_user_data(dev);
unsigned char *data = transfer->buffer; unsigned char *data = transfer->buffer;
uint16_t type; uint16_t type;
int r = 0; int r = 0;
@@ -395,6 +396,8 @@ 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. */
@@ -410,43 +413,47 @@ 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 = FP_INSTANCE_DATA(FP_DEV(dev)); struct uru4k_dev *urudev = fpi_imgdev_get_user_data(dev);
fpi_usb_transfer *transfer; struct libusb_transfer *transfer = libusb_alloc_transfer(0);
unsigned char *data; unsigned char *data;
int r; int r;
if (!transfer)
return -ENOMEM;
data = g_malloc(IRQ_LENGTH); data = g_malloc(IRQ_LENGTH);
transfer = fpi_usb_fill_bulk_transfer(FP_DEV(dev), libusb_fill_bulk_transfer(transfer, fpi_imgdev_get_usb_dev(dev), EP_INTR, data, IRQ_LENGTH,
NULL, irq_handler, dev, 0);
EP_INTR,
data,
IRQ_LENGTH,
irq_handler,
NULL,
0);
urudev->irq_transfer = transfer; urudev->irq_transfer = transfer;
r = fpi_usb_submit_transfer(transfer); r = libusb_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 = FP_INSTANCE_DATA(FP_DEV(dev)); struct uru4k_dev *urudev = fpi_imgdev_get_user_data(dev);
fpi_usb_transfer *transfer = urudev->irq_transfer; struct libusb_transfer *transfer = urudev->irq_transfer;
if (transfer) { if (transfer) {
fpi_usb_cancel_transfer(transfer); libusb_cancel_transfer(transfer);
urudev->irqs_stopped_cb = cb; urudev->irqs_stopped_cb = cb;
} }
} }
@@ -477,7 +484,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 = FP_INSTANCE_DATA(FP_DEV(dev)); struct uru4k_dev *urudev = fpi_imgdev_get_user_data(dev);
switch (state) { switch (state) {
case IMGDEV_STATE_INACTIVE: case IMGDEV_STATE_INACTIVE:
@@ -501,43 +508,37 @@ 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)
{ {
fpi_ssm *ssm = user_data; struct fpi_ssm *ssm = user_data;
if (result) if (result)
fpi_ssm_mark_failed(ssm, result); fpi_ssm_mark_aborted(ssm, result);
else else
fpi_ssm_next_state(ssm); fpi_ssm_next_state(ssm);
} }
static void static void sm_write_regs(struct fpi_ssm *ssm, uint16_t first_reg, uint16_t num_regs,
sm_write_regs(fpi_ssm *ssm, void *data)
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_failed(ssm, r); fpi_ssm_mark_aborted(ssm, r);
} }
static void static void sm_write_reg(struct fpi_ssm *ssm, uint16_t reg,
sm_write_reg(fpi_ssm *ssm, unsigned char value)
struct fp_img_dev *dev,
uint16_t reg,
unsigned char value)
{ {
sm_write_regs(ssm, dev, reg, 1, &value); sm_write_regs(ssm, 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)
{ {
fpi_ssm *ssm = user_data; struct fpi_ssm *ssm = user_data;
struct uru4k_dev *urudev = FP_INSTANCE_DATA(FP_DEV(dev)); struct uru4k_dev *urudev = fpi_imgdev_get_user_data(dev);
if (result) { if (result) {
fpi_ssm_mark_failed(ssm, result); fpi_ssm_mark_aborted(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]);
@@ -545,42 +546,32 @@ static void sm_read_reg_cb(struct fp_img_dev *dev, int result,
} }
} }
#define member_size(type, member) sizeof(((type *)0)->member) static void sm_read_regs(struct fpi_ssm *ssm, uint16_t reg, uint16_t num_regs)
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 > member_size(struct uru4k_dev, last_reg_rd)) { if (num_regs > sizeof(urudev->last_reg_rd)) {
fpi_ssm_mark_failed(ssm, -EIO); fpi_ssm_mark_aborted(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_failed(ssm, r); fpi_ssm_mark_aborted(ssm, r);
} }
static void static void sm_read_reg(struct fpi_ssm *ssm, uint16_t reg)
sm_read_reg(fpi_ssm *ssm,
struct fp_img_dev *dev,
uint16_t reg)
{ {
sm_read_regs(ssm, dev, reg, 1); sm_read_regs(ssm, reg, 1);
} }
static void static void sm_set_hwstat(struct fpi_ssm *ssm, unsigned char value)
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, dev, REG_HWSTAT, value); sm_write_reg(ssm, REG_HWSTAT, value);
} }
/***** IMAGING LOOP *****/ /***** IMAGING LOOP *****/
@@ -594,6 +585,28 @@ 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;
@@ -607,33 +620,6 @@ 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
@@ -668,7 +654,7 @@ static uint32_t do_decode(uint8_t *data, int num_bytes, uint32_t key)
data[i] = data[i+1] ^ xorbyte; data[i] = data[i+1] ^ xorbyte;
} }
/* the final byte is implicitly zero */ /* the final byte is implictly zero */
data[i] = 0; data[i] = 0;
return update_key(key); return update_key(key);
} }
@@ -701,35 +687,35 @@ static int calc_dev2(struct uru4k_image *img)
return res / IMAGE_WIDTH; return res / IMAGE_WIDTH;
} }
static void imaging_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) static void imaging_run_state(struct fpi_ssm *ssm)
{ {
struct fp_img_dev *dev = 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);
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;
unsigned char buf[5]; 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;
r = fpi_usb_submit_transfer(urudev->img_transfer); libusb_fill_bulk_transfer(urudev->img_transfer, fpi_imgdev_get_usb_dev(dev), EP_DATA,
if (r < 0) { urudev->img_data, sizeof(struct uru4k_image), image_transfer_cb, ssm, 0);
urudev->img_transfer = NULL; r = libusb_submit_transfer(urudev->img_transfer);
fpi_ssm_mark_failed(ssm, -EIO); if (r < 0)
} 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_data_actual_length < img->num_lines * IMAGE_WIDTH + 64) { urudev->img_transfer->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_data_actual_length, urudev->img_transfer->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;
@@ -748,10 +734,10 @@ static void imaging_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data
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, dev, REG_SCRAMBLE_DATA_INDEX, 5, buf); sm_write_regs(ssm, REG_SCRAMBLE_DATA_INDEX, 5, buf);
break; break;
case IMAGING_READ_KEY: case IMAGING_READ_KEY:
sm_read_regs(ssm, dev, REG_SCRAMBLE_DATA_KEY, 4); sm_read_regs(ssm, 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];
@@ -824,10 +810,10 @@ static void imaging_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data
} }
} }
static void imaging_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) static void imaging_complete(struct fpi_ssm *ssm)
{ {
struct fp_img_dev *dev = 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);
int r = fpi_ssm_get_error(ssm); int r = fpi_ssm_get_error(ssm);
fpi_ssm_free(ssm); fpi_ssm_free(ssm);
@@ -837,12 +823,11 @@ static void imaging_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
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)
@@ -855,7 +840,7 @@ static void imaging_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
* 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
@@ -875,33 +860,32 @@ enum rebootpwr_states {
REBOOTPWR_NUM_STATES, REBOOTPWR_NUM_STATES,
}; };
static void static void rebootpwr_pause_cb(void *data)
rebootpwr_pause_cb(struct fp_dev *dev,
void *data)
{ {
fpi_ssm *ssm = data; struct fpi_ssm *ssm = data;
struct uru4k_dev *urudev = FP_INSTANCE_DATA(dev); struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
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_failed(ssm, -EIO); fpi_ssm_mark_aborted(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(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) static void rebootpwr_run_state(struct fpi_ssm *ssm)
{ {
struct fp_img_dev *dev = 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);
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, dev, urudev->last_hwstat & 0xf); sm_set_hwstat(ssm, urudev->last_hwstat & 0xf);
break; break;
case REBOOTPWR_GET_HWSTAT: case REBOOTPWR_GET_HWSTAT:
sm_read_reg(ssm, dev, REG_HWSTAT); sm_read_reg(ssm, 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];
@@ -911,16 +895,16 @@ static void rebootpwr_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_da
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, _dev, ssm) == NULL) if (fpi_timeout_add(10, rebootpwr_pause_cb, ssm) == NULL)
fpi_ssm_mark_failed(ssm, -ETIME); fpi_ssm_mark_aborted(ssm, -ETIME);
break; break;
} }
} }
/* After messing with the device firmware in its low-power state, we have to /* After messing with the device firmware in it's 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 the 56aa interrupt and * my ms fp v2 device causes us not to get 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.
* *
@@ -953,16 +937,15 @@ enum powerup_states {
POWERUP_NUM_STATES, POWERUP_NUM_STATES,
}; };
static void static void powerup_pause_cb(void *data)
powerup_pause_cb(struct fp_dev *dev,
void *data)
{ {
fpi_ssm *ssm = data; struct fpi_ssm *ssm = data;
struct uru4k_dev *urudev = FP_INSTANCE_DATA(dev); struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
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_failed(ssm, -EIO); fpi_ssm_mark_aborted(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 {
@@ -970,10 +953,10 @@ powerup_pause_cb(struct fp_dev *dev,
} }
} }
static void powerup_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) static void powerup_run_state(struct fpi_ssm *ssm)
{ {
struct fp_img_dev *dev = 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);
switch (fpi_ssm_get_cur_state(ssm)) { switch (fpi_ssm_get_cur_state(ssm)) {
case POWERUP_INIT: case POWERUP_INIT:
@@ -982,10 +965,10 @@ static void powerup_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data
fpi_ssm_next_state(ssm); fpi_ssm_next_state(ssm);
break; break;
case POWERUP_SET_HWSTAT: case POWERUP_SET_HWSTAT:
sm_set_hwstat(ssm, dev, urudev->powerup_hwstat); sm_set_hwstat(ssm, urudev->powerup_hwstat);
break; break;
case POWERUP_GET_HWSTAT: case POWERUP_GET_HWSTAT:
sm_read_reg(ssm, dev, REG_HWSTAT); sm_read_reg(ssm, 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];
@@ -995,11 +978,11 @@ static void powerup_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data
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, _dev, ssm) == NULL) if (fpi_timeout_add(10, powerup_pause_cb, ssm) == NULL)
fpi_ssm_mark_failed(ssm, -ETIME); fpi_ssm_mark_aborted(ssm, -ETIME);
break; break;
case POWERUP_CHALLENGE_RESPONSE: case POWERUP_CHALLENGE_RESPONSE:
sm_do_challenge_response(ssm, dev); sm_do_challenge_response(ssm);
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);
@@ -1041,11 +1024,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)
{ {
fpi_ssm *ssm = user_data; struct fpi_ssm *ssm = user_data;
struct uru4k_dev *urudev = FP_INSTANCE_DATA(FP_DEV(dev)); struct uru4k_dev *urudev = fpi_imgdev_get_user_data(dev);
if (status) if (status)
fpi_ssm_mark_failed(ssm, status); fpi_ssm_mark_aborted(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) {
@@ -1057,12 +1040,11 @@ static void init_scanpwr_irq_cb(struct fp_img_dev *dev, int status,
} }
} }
static void static void init_scanpwr_timeout(void *user_data)
init_scanpwr_timeout(struct fp_dev *dev,
void *user_data)
{ {
fpi_ssm *ssm = user_data; struct fpi_ssm *ssm = user_data;
struct uru4k_dev *urudev = FP_INSTANCE_DATA(dev); struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
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;
@@ -1070,20 +1052,20 @@ init_scanpwr_timeout(struct fp_dev *dev,
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_failed(ssm, -ETIMEDOUT); fpi_ssm_mark_aborted(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(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) static void init_run_state(struct fpi_ssm *ssm)
{ {
struct fp_img_dev *dev = 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);
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, dev, REG_HWSTAT); sm_read_reg(ssm, 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];
@@ -1093,26 +1075,28 @@ static void init_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
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: ;
fpi_ssm *rebootsm = fpi_ssm_new(FP_DEV(dev), rebootpwr_run_state, struct fpi_ssm *rebootsm = fpi_ssm_new(fpi_imgdev_get_dev(dev), rebootpwr_run_state,
REBOOTPWR_NUM_STATES, dev); REBOOTPWR_NUM_STATES);
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, dev, urudev->last_hwstat | 0x80); sm_set_hwstat(ssm, 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_failed(ssm, -EIO); fpi_ssm_mark_aborted(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;
fpi_ssm *powerupsm = fpi_ssm_new(FP_DEV(dev), powerup_run_state, struct fpi_ssm *powerupsm = fpi_ssm_new(fpi_imgdev_get_dev(dev), powerup_run_state,
POWERUP_NUM_STATES, dev); POWERUP_NUM_STATES);
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:
@@ -1125,10 +1109,9 @@ static void init_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
* 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, init_scanpwr_timeout, ssm);
_dev, ssm);
if (!urudev->scanpwr_irq_timeout) { if (!urudev->scanpwr_irq_timeout) {
fpi_ssm_mark_failed(ssm, -ETIME); fpi_ssm_mark_aborted(ssm, -ETIME);
break; break;
} }
break; break;
@@ -1142,7 +1125,7 @@ static void init_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
fpi_ssm_next_state(ssm); fpi_ssm_next_state(ssm);
break; break;
case INIT_GET_VERSION: case INIT_GET_VERSION:
sm_read_regs(ssm, dev, REG_DEVICE_INFO, 16); sm_read_regs(ssm, 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.
@@ -1155,19 +1138,29 @@ static void init_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
} }
} }
static void activate_initsm_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) static void activate_initsm_complete(struct fpi_ssm *ssm)
{ {
struct fp_img_dev *dev = user_data; struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
int r = fpi_ssm_get_error(ssm); int r = fpi_ssm_get_error(ssm);
fpi_ssm_free(ssm); fpi_ssm_free(ssm);
if (r) {
fpi_imgdev_activate_complete(dev, r);
return;
}
r = execute_state_change(dev);
fpi_imgdev_activate_complete(dev, r); fpi_imgdev_activate_complete(dev, r);
} }
static int dev_activate(struct fp_img_dev *dev) /* FIXME: having state parameter here is kinda useless, will we ever
* see a scenario where the parameter is useful so early on in the activation
* process? asynchronity means that it'll only be used in a later function
* call. */
static int dev_activate(struct fp_img_dev *dev, enum fp_imgdev_state state)
{ {
struct uru4k_dev *urudev = FP_INSTANCE_DATA(FP_DEV(dev)); struct uru4k_dev *urudev = fpi_imgdev_get_user_data(dev);
fpi_ssm *ssm; struct fpi_ssm *ssm;
int r; int r;
r = start_irq_handler(dev); r = start_irq_handler(dev);
@@ -1175,7 +1168,9 @@ static int dev_activate(struct fp_img_dev *dev)
return r; return r;
urudev->scanpwr_irq_timeouts = 0; urudev->scanpwr_irq_timeouts = 0;
ssm = fpi_ssm_new(FP_DEV(dev), init_run_state, INIT_NUM_STATES, dev); urudev->activate_state = state;
ssm = fpi_ssm_new(fpi_imgdev_get_dev(dev), init_run_state, INIT_NUM_STATES);
fpi_ssm_set_user_data(ssm, dev);
fpi_ssm_start(ssm, activate_initsm_complete); fpi_ssm_start(ssm, activate_initsm_complete);
return 0; return 0;
} }
@@ -1200,9 +1195,8 @@ 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 = FP_INSTANCE_DATA(FP_DEV(dev)); struct uru4k_dev *urudev = fpi_imgdev_get_user_data(dev);
fpi_ssm *ssm; struct fpi_ssm *ssm;
void *img_data;
switch (urudev->activate_state) { switch (urudev->activate_state) {
case IMGDEV_STATE_INACTIVE: case IMGDEV_STATE_INACTIVE:
@@ -1225,18 +1219,12 @@ 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;
ssm = fpi_ssm_new(FP_DEV(dev), imaging_run_state, IMAGING_NUM_STATES, dev); urudev->img_transfer = libusb_alloc_transfer(0);
img_data = g_malloc(sizeof(struct uru4k_image)); urudev->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,
@@ -1269,7 +1257,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_dev_get_usb_dev(FP_DEV(dev))), 0, &config); r = libusb_get_config_descriptor(libusb_get_device(fpi_imgdev_get_usb_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;
@@ -1323,15 +1311,12 @@ 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_dev_get_usb_dev(FP_DEV(dev)), iface_desc->bInterfaceNumber); r = libusb_claim_interface(fpi_imgdev_get_usb_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) {
@@ -1340,8 +1325,6 @@ 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;
@@ -1368,6 +1351,7 @@ 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:
@@ -1377,14 +1361,14 @@ out:
static void dev_deinit(struct fp_img_dev *dev) static void dev_deinit(struct fp_img_dev *dev)
{ {
struct uru4k_dev *urudev = FP_INSTANCE_DATA(FP_DEV(dev)); struct uru4k_dev *urudev = fpi_imgdev_get_user_data(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_dev_get_usb_dev(FP_DEV(dev)), urudev->interface); libusb_release_interface(fpi_imgdev_get_usb_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)
{ {
fpi_ssm *ssm = transfer->user_data; struct fpi_ssm *ssm = transfer->user_data;
if (transfer->status != LIBUSB_TRANSFER_COMPLETED) if (transfer->status != LIBUSB_TRANSFER_COMPLETED)
fpi_ssm_mark_failed(ssm, -EIO); fpi_ssm_mark_aborted(ssm, -EIO);
else else
fpi_ssm_next_state(ssm); fpi_ssm_next_state(ssm);
@@ -85,35 +85,38 @@ static void sm_write_reg_cb(struct libusb_transfer *transfer)
libusb_free_transfer(transfer); libusb_free_transfer(transfer);
} }
static void static void sm_write_reg(struct fpi_ssm *ssm, unsigned char reg,
sm_write_reg(fpi_ssm *ssm, unsigned char value)
struct fp_img_dev *dev,
unsigned char reg,
unsigned char value)
{ {
struct libusb_transfer *transfer = fpi_usb_alloc(); struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
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_dev_get_usb_dev(FP_DEV(dev)), data, sm_write_reg_cb, libusb_fill_control_transfer(transfer, fpi_imgdev_get_usb_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_failed(ssm, r); fpi_ssm_mark_aborted(ssm, r);
} }
} }
static void sm_exec_cmd_cb(struct libusb_transfer *transfer) static void sm_exec_cmd_cb(struct libusb_transfer *transfer)
{ {
fpi_ssm *ssm = transfer->user_data; struct fpi_ssm *ssm = transfer->user_data;
if (transfer->status != LIBUSB_TRANSFER_COMPLETED) if (transfer->status != LIBUSB_TRANSFER_COMPLETED)
fpi_ssm_mark_failed(ssm, -EIO); fpi_ssm_mark_aborted(ssm, -EIO);
else else
fpi_ssm_next_state(ssm); fpi_ssm_next_state(ssm);
@@ -121,26 +124,29 @@ static void sm_exec_cmd_cb(struct libusb_transfer *transfer)
libusb_free_transfer(transfer); libusb_free_transfer(transfer);
} }
static void static void sm_exec_cmd(struct fpi_ssm *ssm, unsigned char cmd,
sm_exec_cmd(fpi_ssm *ssm, unsigned char param)
struct fp_img_dev *dev,
unsigned char cmd,
unsigned char param)
{ {
struct libusb_transfer *transfer = fpi_usb_alloc(); struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
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_dev_get_usb_dev(FP_DEV(dev)), data, sm_exec_cmd_cb, libusb_fill_control_transfer(transfer, fpi_imgdev_get_usb_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_failed(ssm, r); fpi_ssm_mark_aborted(ssm, r);
} }
} }
@@ -181,16 +187,16 @@ static gboolean finger_is_present(unsigned char *data)
/***** IMAGE ACQUISITION *****/ /***** IMAGE ACQUISITION *****/
static void capture_iterate(fpi_ssm *ssm, struct fp_img_dev *dev); static void capture_iterate(struct fpi_ssm *ssm);
static void capture_cb(struct libusb_transfer *transfer) static void capture_cb(struct libusb_transfer *transfer)
{ {
fpi_ssm *ssm = transfer->user_data; struct 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 = FP_INSTANCE_DATA(FP_DEV(dev)); struct v5s_dev *vdev = fpi_imgdev_get_user_data(dev);
if (transfer->status != LIBUSB_TRANSFER_COMPLETED) { if (transfer->status != LIBUSB_TRANSFER_COMPLETED) {
fpi_ssm_mark_failed(ssm, -EIO); fpi_ssm_mark_aborted(ssm, -EIO);
goto out; goto out;
} }
@@ -205,44 +211,47 @@ 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, dev); capture_iterate(ssm);
} }
out: out:
libusb_free_transfer(transfer); libusb_free_transfer(transfer);
} }
static void static void capture_iterate(struct fpi_ssm *ssm)
capture_iterate(fpi_ssm *ssm,
struct fp_img_dev *dev)
{ {
struct v5s_dev *vdev = FP_INSTANCE_DATA(FP_DEV(dev)); struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct v5s_dev *vdev = fpi_imgdev_get_user_data(dev);
int iteration = vdev->capture_iteration; int iteration = vdev->capture_iteration;
struct libusb_transfer *transfer = fpi_usb_alloc(); struct libusb_transfer *transfer = libusb_alloc_transfer(0);
int r; int r;
libusb_fill_bulk_transfer(transfer, fpi_dev_get_usb_dev(FP_DEV(dev)), EP_IN, if (!transfer) {
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_failed(ssm, r); fpi_ssm_mark_aborted(ssm, r);
} }
} }
static void static void sm_do_capture(struct fpi_ssm *ssm)
sm_do_capture(fpi_ssm *ssm,
struct fp_img_dev *dev)
{ {
struct v5s_dev *vdev = FP_INSTANCE_DATA(FP_DEV(dev)); struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
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, dev); capture_iterate(ssm);
} }
/***** CAPTURE LOOP *****/ /***** CAPTURE LOOP *****/
@@ -256,27 +265,27 @@ enum loop_states {
LOOP_NUM_STATES, LOOP_NUM_STATES,
}; };
static void loop_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) static void loop_run_state(struct fpi_ssm *ssm)
{ {
struct fp_img_dev *dev = user_data; struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct v5s_dev *vdev = FP_INSTANCE_DATA(_dev); struct v5s_dev *vdev = fpi_imgdev_get_user_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, dev, REG_CONTRAST, 0x01); sm_write_reg(ssm, REG_CONTRAST, 0x01);
break; break;
case LOOP_SET_GAIN: case LOOP_SET_GAIN:
sm_write_reg(ssm, dev, REG_GAIN, 0x29); sm_write_reg(ssm, 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, dev, CMD_SCAN, 0x00); sm_exec_cmd(ssm, CMD_SCAN, 0x00);
break; break;
case LOOP_CAPTURE: case LOOP_CAPTURE:
sm_do_capture(ssm, dev); sm_do_capture(ssm);
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);
@@ -284,10 +293,10 @@ static void loop_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
} }
} }
static void loopsm_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) static void loopsm_complete(struct fpi_ssm *ssm)
{ {
struct fp_img_dev *dev = user_data; struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct v5s_dev *vdev = FP_INSTANCE_DATA(_dev); struct v5s_dev *vdev = fpi_imgdev_get_user_data(dev);
int r = fpi_ssm_get_error(ssm); int r = fpi_ssm_get_error(ssm);
fpi_ssm_free(ssm); fpi_ssm_free(ssm);
@@ -302,11 +311,12 @@ static void loopsm_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
fpi_imgdev_deactivate_complete(dev); fpi_imgdev_deactivate_complete(dev);
} }
static int dev_activate(struct fp_img_dev *dev) static int dev_activate(struct fp_img_dev *dev, enum fp_imgdev_state state)
{ {
struct v5s_dev *vdev = FP_INSTANCE_DATA(FP_DEV(dev)); struct v5s_dev *vdev = fpi_imgdev_get_user_data(dev);
fpi_ssm *ssm = fpi_ssm_new(FP_DEV(dev), loop_run_state, struct fpi_ssm *ssm = fpi_ssm_new(fpi_imgdev_get_dev(dev), loop_run_state,
LOOP_NUM_STATES, dev); LOOP_NUM_STATES);
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;
@@ -316,7 +326,7 @@ static int dev_activate(struct fp_img_dev *dev)
static void dev_deactivate(struct fp_img_dev *dev) static void dev_deactivate(struct fp_img_dev *dev)
{ {
struct v5s_dev *vdev = FP_INSTANCE_DATA(FP_DEV(dev)); struct v5s_dev *vdev = fpi_imgdev_get_user_data(dev);
if (vdev->loop_running) if (vdev->loop_running)
vdev->deactivating = TRUE; vdev->deactivating = TRUE;
else else
@@ -329,9 +339,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));
fp_dev_set_instance_data(FP_DEV(dev), v5s_dev); fpi_imgdev_set_user_data(dev, v5s_dev);
r = libusb_claim_interface(fpi_dev_get_usb_dev(FP_DEV(dev)), 0); r = libusb_claim_interface(fpi_imgdev_get_usb_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));
@@ -344,9 +354,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 = FP_INSTANCE_DATA(FP_DEV(dev)); v5s_dev = fpi_imgdev_get_user_data(dev);
g_free(v5s_dev); g_free(v5s_dev);
libusb_release_interface(fpi_dev_get_usb_dev(FP_DEV(dev)), 0); libusb_release_interface(fpi_imgdev_get_usb_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)
{ {
fpi_ssm *ssm = transfer->user_data; struct 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_failed(ssm, -EIO); fpi_ssm_mark_aborted(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_failed(ssm, -EIO); fpi_ssm_mark_aborted(ssm, -EIO);
return; return;
} }
@@ -51,16 +51,13 @@ 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 static void async_write(struct fpi_ssm *ssm, void *data, int len)
async_write(fpi_ssm *ssm,
struct fp_img_dev *dev,
void *data,
int len)
{ {
struct libusb_device_handle *usb_dev = fpi_dev_get_usb_dev(FP_DEV(dev)); struct fp_img_dev *idev = fpi_ssm_get_user_data(ssm);
struct vfs_dev_t *vdev = FP_INSTANCE_DATA(FP_DEV(dev)); struct libusb_device_handle *usb_dev = fpi_imgdev_get_usb_dev(idev);
struct vfs_dev_t *vdev = fpi_imgdev_get_user_data(idev);
vdev->transfer = fpi_usb_alloc(); vdev->transfer = libusb_alloc_transfer(0);
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);
@@ -70,7 +67,7 @@ async_write(fpi_ssm *ssm,
/* 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)
{ {
fpi_ssm *ssm = transfer->user_data; struct 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 =
@@ -81,14 +78,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_failed(ssm, -EIO); fpi_ssm_mark_aborted(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_failed(ssm, -EIO); fpi_ssm_mark_aborted(ssm, -EIO);
return; return;
} }
@@ -96,20 +93,15 @@ 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 static void async_read(struct fpi_ssm *ssm, int ep, void *data, int len)
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_dev_get_usb_dev(FP_DEV(idev)); struct libusb_device_handle *usb_dev = fpi_imgdev_get_usb_dev(idev);
struct vfs_dev_t *vdev = FP_INSTANCE_DATA(FP_DEV(idev)); struct vfs_dev_t *vdev = fpi_imgdev_get_user_data(idev);
ep |= LIBUSB_ENDPOINT_IN; ep |= LIBUSB_ENDPOINT_IN;
vdev->transfer = fpi_usb_alloc(); vdev->transfer = libusb_alloc_transfer(0);
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 */
@@ -127,7 +119,7 @@ async_read(fpi_ssm *ssm,
/* 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)
{ {
fpi_ssm *ssm = transfer->user_data; struct 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;
@@ -142,7 +134,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_failed(ssm, -EIO); fpi_ssm_mark_aborted(ssm, -EIO);
return; return;
} }
@@ -155,18 +147,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(fpi_ssm *ssm, int ep) static void async_abort(struct 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_dev_get_usb_dev(FP_DEV(idev)); struct libusb_device_handle *usb_dev = fpi_imgdev_get_usb_dev(idev);
struct vfs_dev_t *vdev = FP_INSTANCE_DATA(FP_DEV(idev)); struct vfs_dev_t *vdev = fpi_imgdev_get_user_data(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 = fpi_usb_alloc(); vdev->transfer = libusb_alloc_transfer(0);
vdev->transfer->flags |= vdev->transfer->flags |=
LIBUSB_TRANSFER_FREE_TRANSFER | LIBUSB_TRANSFER_FREE_BUFFER; LIBUSB_TRANSFER_FREE_TRANSFER | LIBUSB_TRANSFER_FREE_BUFFER;
@@ -267,7 +259,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 = FP_INSTANCE_DATA(FP_DEV(idev)); struct vfs_dev_t *vdev = fpi_imgdev_get_user_data(idev);
/* We were not asked to submit image actually */ /* We were not asked to submit image actually */
if (!vdev->active) if (!vdev->active)
@@ -287,21 +279,20 @@ 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 static void clear_ep2_ssm(struct fpi_ssm *ssm)
clear_ep2_ssm(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
{ {
struct fp_img_dev *idev = user_data; struct fp_img_dev *idev = fpi_ssm_get_user_data(ssm);
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, idev, &command04, sizeof(command04)); async_write(ssm, &command04, sizeof(command04));
break; break;
case SUBSM1_RETURN_CODE: case SUBSM1_RETURN_CODE:
async_read(ssm, idev, 1, &result, sizeof(result)); async_read(ssm, 1, &result, sizeof(result));
break; break;
case SUBSM1_ABORT_2: case SUBSM1_ABORT_2:
@@ -311,35 +302,36 @@ clear_ep2_ssm(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
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_failed(ssm, -EIO); fpi_ssm_mark_aborted(ssm, -EIO);
} }
} }
/* Send command to clear EP2 */ /* Send command to clear EP2 */
static void static void clear_ep2(struct fpi_ssm *ssm)
clear_ep2(fpi_ssm *ssm,
struct fp_img_dev *idev)
{ {
fpi_ssm *subsm = struct fp_img_dev *idev = fpi_ssm_get_user_data(ssm);
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(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) static void send_control_packet_ssm(struct fpi_ssm *ssm)
{ {
struct fp_img_dev *idev = 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);
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, idev, vdev->control_packet, VFS_CONTROL_PACKET_SIZE); async_write(ssm, vdev->control_packet, VFS_CONTROL_PACKET_SIZE);
break; break;
case SUBSM2_RETURN_CODE: case SUBSM2_RETURN_CODE:
async_read(ssm, idev, 1, &result, sizeof(result)); async_read(ssm, 1, &result, sizeof(result));
break; break;
case SUBSM2_SEND_COMMIT: case SUBSM2_SEND_COMMIT:
@@ -350,19 +342,19 @@ static void send_control_packet_ssm(fpi_ssm *ssm, struct fp_dev *_dev, void *use
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, idev, commit_out, sizeof(commit_out)); async_write(ssm, 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, idev, 1, commit_result, VFS_COMMIT_RESPONSE_SIZE); async_read(ssm, 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, idev, 3, vdev->interrupt, VFS_INTERRUPT_SIZE); async_read(ssm, 3, vdev->interrupt, VFS_INTERRUPT_SIZE);
break; break;
case SUBSM2_ABORT_3: case SUBSM2_ABORT_3:
@@ -371,7 +363,7 @@ static void send_control_packet_ssm(fpi_ssm *ssm, struct fp_dev *_dev, void *use
(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_failed(ssm, -EIO); fpi_ssm_mark_aborted(ssm, -EIO);
break; break;
} }
async_abort(ssm, 3); async_abort(ssm, 3);
@@ -380,7 +372,7 @@ static void send_control_packet_ssm(fpi_ssm *ssm, struct fp_dev *_dev, void *use
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, idev); clear_ep2(ssm);
else else
fpi_ssm_next_state(ssm); fpi_ssm_next_state(ssm);
break; break;
@@ -388,17 +380,18 @@ static void send_control_packet_ssm(fpi_ssm *ssm, struct fp_dev *_dev, void *use
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_failed(ssm, -EIO); fpi_ssm_mark_aborted(ssm, -EIO);
} }
} }
/* Send device state control packet */ /* Send device state control packet */
static void static void send_control_packet(struct fpi_ssm *ssm)
send_control_packet(fpi_ssm *ssm,
struct fp_img_dev *idev)
{ {
fpi_ssm *subsm = struct fp_img_dev *idev = fpi_ssm_get_user_data(ssm);
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);
} }
@@ -413,9 +406,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)
{ {
fpi_ssm *ssm = transfer->user_data; struct 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 = FP_INSTANCE_DATA(FP_DEV(idev)); struct vfs_dev_t *vdev = fpi_imgdev_get_user_data(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;
@@ -430,7 +423,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_failed(ssm, -EIO); fpi_ssm_mark_aborted(ssm, -EIO);
return; return;
} }
@@ -439,7 +432,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_failed(ssm, -EIO); fpi_ssm_mark_aborted(ssm, -EIO);
return; return;
} }
@@ -468,14 +461,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_failed(ssm, -EIO); fpi_ssm_mark_aborted(ssm, -EIO);
} }
static void receive_callback(struct libusb_transfer *transfer) static void receive_callback(struct libusb_transfer *transfer)
{ {
fpi_ssm *ssm = transfer->user_data; struct 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 = FP_INSTANCE_DATA(FP_DEV(idev)); struct vfs_dev_t *vdev = fpi_imgdev_get_user_data(idev);
int transferred = transfer->actual_length, error = transfer->status; int transferred = transfer->actual_length, error = transfer->status;
@@ -483,7 +476,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_failed(ssm, -EIO); fpi_ssm_mark_aborted(ssm, -EIO);
return; return;
} }
@@ -499,12 +492,11 @@ 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 static void wait_interrupt(void *data)
wait_interrupt(struct fp_dev *dev,
void *data)
{ {
fpi_ssm *ssm = data; struct fpi_ssm *ssm = data;
struct vfs_dev_t *vdev = FP_INSTANCE_DATA(dev); struct fp_img_dev *idev = fpi_ssm_get_user_data(ssm);
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)
@@ -512,20 +504,25 @@ wait_interrupt(struct fp_dev *dev,
} }
/* 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 static void another_scan(void *data)
another_scan(struct fp_dev *dev,
void *data)
{ {
fpi_ssm *ssm = data; struct fpi_ssm *ssm = data;
fpi_ssm_jump_to_state(ssm, SSM_TURN_ON); fpi_ssm_jump_to_state(ssm, SSM_TURN_ON);
} }
/* Main SSM loop */ /* Another SSM stub to continue after waiting for probable vdev->active changes */
static void activate_ssm(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) static void scan_completed(void *data)
{ {
struct fp_img_dev *idev = user_data; struct fpi_ssm *ssm = data;
struct libusb_device_handle *usb_dev = fpi_dev_get_usb_dev(FP_DEV(idev)); fpi_ssm_next_state(ssm);
struct vfs_dev_t *vdev = FP_INSTANCE_DATA(_dev); }
/* Main SSM loop */
static void activate_ssm(struct fpi_ssm *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 vfs_dev_t *vdev = fpi_imgdev_get_user_data(idev);
switch (fpi_ssm_get_cur_state(ssm)) { switch (fpi_ssm_get_cur_state(ssm)) {
case SSM_INITIAL_ABORT_1: case SSM_INITIAL_ABORT_1:
@@ -541,14 +538,14 @@ static void activate_ssm(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
break; break;
case SSM_CLEAR_EP2: case SSM_CLEAR_EP2:
clear_ep2(ssm, idev); clear_ep2(ssm);
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, idev); send_control_packet(ssm);
break; break;
case SSM_TURN_ON: case SSM_TURN_ON:
@@ -565,7 +562,7 @@ static void activate_ssm(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
/* Set control_packet argument */ /* Set control_packet argument */
vdev->control_packet = turn_on; vdev->control_packet = turn_on;
send_control_packet(ssm, idev); send_control_packet(ssm);
break; break;
case SSM_ASK_INTERRUPT: case SSM_ASK_INTERRUPT:
@@ -577,8 +574,8 @@ static void activate_ssm(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
vdev->need_report = 0; vdev->need_report = 0;
} }
/* Asynchronously enquire an interrupt */ /* Asyncronously enquire an interrupt */
vdev->transfer = fpi_usb_alloc(); vdev->transfer = libusb_alloc_transfer(0);
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,
@@ -604,7 +601,7 @@ static void activate_ssm(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
} }
if (vdev->wait_interrupt) if (vdev->wait_interrupt)
fpi_timeout_add(VFS_SSM_TIMEOUT, wait_interrupt, _dev, ssm); fpi_timeout_add(VFS_SSM_TIMEOUT, wait_interrupt, ssm);
break; break;
case SSM_RECEIVE_FINGER: case SSM_RECEIVE_FINGER:
@@ -628,7 +625,7 @@ static void activate_ssm(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
} }
/* Receive chunk of data */ /* Receive chunk of data */
vdev->transfer = fpi_usb_alloc(); vdev->transfer = libusb_alloc_transfer(0);
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 +
@@ -643,7 +640,7 @@ static void activate_ssm(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
clear_data(vdev); clear_data(vdev);
/* Wait for probable vdev->active changing */ /* Wait for probable vdev->active changing */
fpi_timeout_add(VFS_SSM_TIMEOUT, fpi_ssm_next_state_timeout_cb, _dev, ssm); fpi_timeout_add(VFS_SSM_TIMEOUT, scan_completed, ssm);
break; break;
case SSM_NEXT_RECEIVE: case SSM_NEXT_RECEIVE:
@@ -656,27 +653,28 @@ static void activate_ssm(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
/* Set control_packet argument */ /* Set control_packet argument */
vdev->control_packet = next_receive_1; vdev->control_packet = next_receive_1;
send_control_packet(ssm, idev); send_control_packet(ssm);
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, _dev, ssm); fpi_timeout_add(VFS_SSM_ORANGE_TIMEOUT, another_scan, 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_failed(ssm, -EIO); fpi_ssm_mark_aborted(ssm, -EIO);
} }
} }
/* Driver functions */ /* Driver functions */
/* Callback for dev_activate ssm */ /* Callback for dev_activate ssm */
static void dev_activate_callback(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) static void dev_activate_callback(struct fpi_ssm *ssm)
{ {
struct vfs_dev_t *vdev = FP_INSTANCE_DATA(_dev); struct fp_img_dev *idev = fpi_ssm_get_user_data(ssm);
struct vfs_dev_t *vdev = fpi_imgdev_get_user_data(idev);
vdev->ssm_active = 0; vdev->ssm_active = 0;
@@ -684,16 +682,17 @@ static void dev_activate_callback(fpi_ssm *ssm, struct fp_dev *_dev, void *user_
} }
/* Activate device */ /* Activate device */
static int dev_activate(struct fp_img_dev *idev) static int dev_activate(struct fp_img_dev *idev, enum fp_imgdev_state state)
{ {
struct vfs_dev_t *vdev = FP_INSTANCE_DATA(FP_DEV(idev)); struct vfs_dev_t *vdev = fpi_imgdev_get_user_data(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;
fpi_ssm *ssm = fpi_ssm_new(FP_DEV(idev), activate_ssm, SSM_STATES, idev); struct fpi_ssm *ssm = fpi_ssm_new(fpi_imgdev_get_dev(idev), activate_ssm, SSM_STATES);
fpi_ssm_set_user_data(ssm, idev);
fpi_ssm_start(ssm, dev_activate_callback); fpi_ssm_start(ssm, dev_activate_callback);
return 0; return 0;
} }
@@ -701,7 +700,7 @@ static int dev_activate(struct fp_img_dev *idev)
/* 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 = FP_INSTANCE_DATA(FP_DEV(idev)); struct vfs_dev_t *vdev = fpi_imgdev_get_user_data(idev);
if (!vdev->ssm_active) { if (!vdev->ssm_active) {
fpi_imgdev_deactivate_complete(idev); fpi_imgdev_deactivate_complete(idev);
@@ -714,10 +713,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(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) static void dev_open_callback(struct fpi_ssm *ssm)
{ {
/* Notify open complete */ /* Notify open complete */
fpi_imgdev_open_complete(user_data, 0); fpi_imgdev_open_complete(fpi_ssm_get_user_data(ssm), 0);
fpi_ssm_free(ssm); fpi_ssm_free(ssm);
} }
@@ -727,7 +726,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_dev_get_usb_dev(FP_DEV(idev)), 0); int error = libusb_claim_interface(fpi_imgdev_get_usb_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");
@@ -736,10 +735,11 @@ 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));
fp_dev_set_instance_data(FP_DEV(idev), vdev); fpi_imgdev_set_user_data(idev, vdev);
/* Clearing previous device state */ /* Clearing previous device state */
fpi_ssm *ssm = fpi_ssm_new(FP_DEV(idev), activate_ssm, SSM_STATES, idev); struct fpi_ssm *ssm = fpi_ssm_new(fpi_imgdev_get_dev(idev), activate_ssm, SSM_STATES);
fpi_ssm_set_user_data(ssm, idev);
fpi_ssm_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 = FP_INSTANCE_DATA(FP_DEV(idev)); vdev = fpi_imgdev_get_user_data(idev);
g_free(vdev); g_free(vdev);
/* Release usb interface */ /* Release usb interface */
libusb_release_interface(fpi_dev_get_usb_dev(FP_DEV(idev)), 0); libusb_release_interface(fpi_imgdev_get_usb_dev(idev), 0);
/* Notify close complete */ /* Notify close complete */
fpi_imgdev_close_complete(idev); fpi_imgdev_close_complete(idev);

View File

@@ -47,7 +47,7 @@
/* Minimum image height */ /* Minimum image height */
#define VFS_IMG_MIN_HEIGHT 200 #define VFS_IMG_MIN_HEIGHT 200
/* Scan level threshold */ /* Scan level thresold */
#define VFS_IMG_SLT_BEGIN 768 #define VFS_IMG_SLT_BEGIN 768
#define VFS_IMG_SLT_END 64 #define VFS_IMG_SLT_END 64
#define VFS_IMG_SLT_LINES 4 #define VFS_IMG_SLT_LINES 4
@@ -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_CONTRAST 128 #define VFS_IMG_BEST_CONRAST 128
/* Device parameters address */ /* Device parameters address */
#define VFS_PAR_000E 0x000e #define VFS_PAR_000E 0x000e
@@ -105,6 +105,9 @@ 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;
@@ -196,9 +199,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)
{ {
fpi_ssm *ssm = transfer->user_data; struct 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 = FP_INSTANCE_DATA(FP_DEV(dev)); struct vfs101_dev *vdev = fpi_imgdev_get_user_data(dev);
/* Cleanup transfer */ /* Cleanup transfer */
vdev->transfer = NULL; vdev->transfer = NULL;
@@ -211,7 +214,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_failed(ssm, -EIO); fpi_ssm_mark_aborted(ssm, -EIO);
goto out; goto out;
} }
@@ -221,7 +224,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_failed(ssm, -EIO); fpi_ssm_mark_aborted(ssm, -EIO);
goto out; goto out;
} }
} }
@@ -239,15 +242,22 @@ out:
} }
/* Submit asynchronous send */ /* Submit asynchronous send */
static void static void async_send(struct fpi_ssm *ssm)
async_send(fpi_ssm *ssm,
struct fp_img_dev *dev)
{ {
struct vfs101_dev *vdev = FP_INSTANCE_DATA(FP_DEV(dev)); struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct vfs101_dev *vdev = fpi_imgdev_get_user_data(dev);
int r; int r;
/* Allocation of transfer */ /* Allocation of transfer */
vdev->transfer = fpi_usb_alloc(); vdev->transfer = libusb_alloc_transfer(0);
if (!vdev->transfer)
{
/* Allocation transfer failed, return no memory error */
fp_err("allocation of usb transfer failed");
fpi_imgdev_session_error(dev, -ENOMEM);
fpi_ssm_mark_aborted(ssm, -ENOMEM);
return;
}
/* Put sequential number into the buffer */ /* Put sequential number into the buffer */
vdev->seqnum++; vdev->seqnum++;
@@ -255,7 +265,7 @@ async_send(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_dev_get_usb_dev(FP_DEV(dev)), EP_OUT(1), vdev->buffer, vdev->length, async_send_cb, ssm, BULK_TIMEOUT); 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);
/* Submit transfer */ /* Submit transfer */
r = libusb_submit_transfer(vdev->transfer); r = libusb_submit_transfer(vdev->transfer);
@@ -265,7 +275,7 @@ async_send(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_failed(ssm, -EIO); fpi_ssm_mark_aborted(ssm, -EIO);
return; return;
} }
} }
@@ -273,9 +283,9 @@ async_send(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)
{ {
fpi_ssm *ssm = transfer->user_data; struct 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 = FP_INSTANCE_DATA(FP_DEV(dev)); struct vfs101_dev *vdev = fpi_imgdev_get_user_data(dev);
/* Cleanup transfer */ /* Cleanup transfer */
vdev->transfer = NULL; vdev->transfer = NULL;
@@ -288,7 +298,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_failed(ssm, -EIO); fpi_ssm_mark_aborted(ssm, -EIO);
goto out; goto out;
} }
@@ -298,7 +308,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_failed(ssm, -EIO); fpi_ssm_mark_aborted(ssm, -EIO);
goto out; goto out;
} }
} }
@@ -319,18 +329,25 @@ out:
} }
/* Submit asynchronous recv */ /* Submit asynchronous recv */
static void static void async_recv(struct fpi_ssm *ssm)
async_recv(fpi_ssm *ssm,
struct fp_img_dev *dev)
{ {
struct vfs101_dev *vdev = FP_INSTANCE_DATA(FP_DEV(dev)); struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct vfs101_dev *vdev = fpi_imgdev_get_user_data(dev);
int r; int r;
/* Allocation of transfer */ /* Allocation of transfer */
vdev->transfer = fpi_usb_alloc(); vdev->transfer = libusb_alloc_transfer(0);
if (!vdev->transfer)
{
/* Allocation transfer failed, return no memory error */
fp_err("allocation of usb transfer failed");
fpi_imgdev_session_error(dev, -ENOMEM);
fpi_ssm_mark_aborted(ssm, -ENOMEM);
return;
}
/* Prepare bulk transfer */ /* Prepare bulk transfer */
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); libusb_fill_bulk_transfer(vdev->transfer, fpi_imgdev_get_usb_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);
@@ -340,19 +357,19 @@ async_recv(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_failed(ssm, -EIO); fpi_ssm_mark_aborted(ssm, -EIO);
return; return;
} }
} }
static void async_load(fpi_ssm *ssm, struct fp_img_dev *dev); static void async_load(struct fpi_ssm *ssm);
/* 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)
{ {
fpi_ssm *ssm = transfer->user_data; struct 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 = FP_INSTANCE_DATA(FP_DEV(dev)); struct vfs101_dev *vdev = fpi_imgdev_get_user_data(dev);
/* Cleanup transfer */ /* Cleanup transfer */
vdev->transfer = NULL; vdev->transfer = NULL;
@@ -365,7 +382,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_failed(ssm, -EIO); fpi_ssm_mark_aborted(ssm, -EIO);
goto out; goto out;
} }
@@ -374,7 +391,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_failed(ssm, -EIO); fpi_ssm_mark_aborted(ssm, -EIO);
goto out; goto out;
} }
} }
@@ -389,12 +406,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_failed(ssm, -ENOMEM); fpi_ssm_mark_aborted(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, dev); async_load(ssm);
} }
else else
{ {
@@ -413,22 +430,29 @@ out:
} }
/* Submit asynchronous load */ /* Submit asynchronous load */
static void static void async_load(struct fpi_ssm *ssm)
async_load(fpi_ssm *ssm,
struct fp_img_dev *dev)
{ {
struct vfs101_dev *vdev = FP_INSTANCE_DATA(FP_DEV(dev)); struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
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 = fpi_usb_alloc(); vdev->transfer = libusb_alloc_transfer(0);
if (!vdev->transfer)
{
/* Allocation transfer failed, return no memory error */
fp_err("allocation of usb transfer failed");
fpi_imgdev_session_error(dev, -ENOMEM);
fpi_ssm_mark_aborted(ssm, -ENOMEM);
return;
}
/* 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_dev_get_usb_dev(FP_DEV(dev)), EP_IN(2), buffer, VFS_BLOCK_SIZE, async_load_cb, ssm, BULK_TIMEOUT); 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);
/* Submit transfer */ /* Submit transfer */
r = libusb_submit_transfer(vdev->transfer); r = libusb_submit_transfer(vdev->transfer);
@@ -438,23 +462,39 @@ async_load(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_failed(ssm, -EIO); fpi_ssm_mark_aborted(ssm, -EIO);
return; return;
} }
} }
/* Submit asynchronous sleep */ /* Callback of asynchronous sleep */
static void static void async_sleep_cb(void *data)
async_sleep(unsigned int msec,
fpi_ssm *ssm,
struct fp_img_dev *dev)
{ {
if (fpi_timeout_add(msec, fpi_ssm_next_state_timeout_cb, FP_DEV(dev), ssm) == NULL) struct fpi_ssm *ssm = data;
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct vfs101_dev *vdev = fpi_imgdev_get_user_data(dev);
/* Cleanup timeout */
vdev->timeout = NULL;
fpi_ssm_next_state(ssm);
}
/* Submit asynchronous sleep */
static void async_sleep(unsigned int msec, struct fpi_ssm *ssm)
{
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct vfs101_dev *vdev = fpi_imgdev_get_user_data(dev);
/* Add timeout */
vdev->timeout = fpi_timeout_add(msec, async_sleep_cb, ssm);
if (vdev->timeout == NULL)
{ {
/* 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_failed(ssm, -ETIME); fpi_ssm_mark_aborted(ssm, -ETIME);
} }
} }
@@ -467,31 +507,28 @@ enum
}; };
/* Exec swap sequential state machine */ /* Exec swap sequential state machine */
static void m_swap_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) static void m_swap_state(struct fpi_ssm *ssm)
{ {
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, user_data); async_send(ssm);
break; break;
case M_SWAP_RECV: case M_SWAP_RECV:
/* Recv response */ /* Recv response */
async_recv(ssm, user_data); async_recv(ssm);
break; break;
} }
} }
/* Start swap sequential state machine */ /* Start swap sequential state machine */
static void static void m_swap(struct fpi_ssm *ssm, unsigned char *data, size_t length)
m_swap(fpi_ssm *ssm,
struct fp_img_dev *dev,
unsigned char *data,
size_t length)
{ {
struct vfs101_dev *vdev = FP_INSTANCE_DATA(FP_DEV(dev)); struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
fpi_ssm *subsm; struct vfs101_dev *vdev = fpi_imgdev_get_user_data(dev);
struct fpi_ssm *subsm;
/* Prepare data for sending */ /* Prepare data for sending */
memcpy(vdev->buffer, data, length); memcpy(vdev->buffer, data, length);
@@ -499,16 +536,13 @@ m_swap(fpi_ssm *ssm,
vdev->length = length; vdev->length = length;
/* Start swap ssm */ /* Start swap ssm */
subsm = fpi_ssm_new(FP_DEV(dev), m_swap_state, M_SWAP_NUM_STATES, dev); subsm = fpi_ssm_new(fpi_imgdev_get_dev(dev), m_swap_state, M_SWAP_NUM_STATES);
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 static void vfs_get_print(struct fpi_ssm *ssm, unsigned int param, int type)
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,
@@ -524,15 +558,11 @@ vfs_get_print(fpi_ssm *ssm,
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, dev, data[type], 0x0e); m_swap(ssm, data[type], 0x0e);
} }
/* Set a parameter value on the device */ /* Set a parameter value on the device */
static void static void vfs_set_param(struct fpi_ssm *ssm, unsigned int param, unsigned int value)
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 };
@@ -545,29 +575,22 @@ vfs_set_param(fpi_ssm *ssm,
data[9] = byte(1, value); data[9] = byte(1, value);
/* Run swap sequential state machine */ /* Run swap sequential state machine */
m_swap(ssm, dev, data, 0x0a); m_swap(ssm, data, 0x0a);
} }
/* Abort previous print */ /* Abort previous print */
static void static void vfs_abort_print(struct fpi_ssm *ssm)
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, dev, data, 0x06); m_swap (ssm, data, 0x06);
} }
/* Poke a value on a region */ /* Poke a value on a region */
static void static void vfs_poke(struct fpi_ssm *ssm, unsigned int addr, unsigned int value, unsigned int size)
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 };
@@ -585,28 +608,25 @@ vfs_poke(fpi_ssm *ssm,
data[14] = byte(0, size); data[14] = byte(0, size);
/* Run swap sequential state machine */ /* Run swap sequential state machine */
m_swap(ssm, dev, data, 0x0f); m_swap(ssm, data, 0x0f);
} }
/* Get current finger state */ /* Get current finger state */
static void static void vfs_get_finger_state(struct fpi_ssm *ssm)
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, dev, data, 0x06); m_swap (ssm, data, 0x06);
} }
/* Load raw image from reader */ /* Load raw image from reader */
static void static void vfs_img_load(struct fpi_ssm *ssm)
vfs_img_load(fpi_ssm *ssm,
struct fp_img_dev *dev)
{ {
struct vfs101_dev *vdev = FP_INSTANCE_DATA(FP_DEV(dev)); struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct vfs101_dev *vdev = fpi_imgdev_get_user_data(dev);
G_DEBUG_HERE(); G_DEBUG_HERE();
@@ -618,16 +638,16 @@ vfs_img_load(fpi_ssm *ssm,
vdev->height = -1; vdev->height = -1;
/* Asynchronous load */ /* Asynchronous load */
async_load(ssm, dev); async_load(ssm);
} }
/* 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 = FP_INSTANCE_DATA(FP_DEV(dev)); struct vfs101_dev *vdev = fpi_imgdev_get_user_data(dev);
if ((fpi_imgdev_get_action(dev) == IMG_ACTION_ENROLL) && if ((fpi_imgdev_get_action(dev) == IMG_ACTION_ENROLL) &&
(vdev->enroll_stage < fp_dev_get_nr_enroll_stages(FP_DEV(dev)))) (vdev->enroll_stage < fpi_dev_get_nr_enroll_stages(fpi_imgdev_get_dev(dev))))
/* Enroll not completed, return false */ /* Enroll not completed, return false */
return FALSE; return FALSE;
@@ -641,7 +661,7 @@ static int action_completed(struct fp_img_dev *dev)
#define offset(x, y) ((x) + ((y) * VFS_FRAME_SIZE)) #define offset(x, y) ((x) + ((y) * VFS_FRAME_SIZE))
/* Screen image to remove noise and find bottom line and height of image */ /* Screen image to remove noise and find bottom line and height od image */
static void img_screen(struct vfs101_dev *vdev) static void img_screen(struct vfs101_dev *vdev)
{ {
int y, x, count, top; int y, x, count, top;
@@ -654,7 +674,7 @@ static void img_screen(struct vfs101_dev *vdev)
/* Image returned from sensor can contain many empty lines, /* Image returned from sensor can contain many empty lines,
* for remove these lines compare byte 282-283 (scan level information) * for remove these lines compare byte 282-283 (scan level information)
* with two different thresholds, one for the begin of finger image and * with two differents threshold, one for the begin of finger image and
* one for the end. To increase stability of the code use a counter * one for the end. To increase stability of the code use a counter
* of lines that satisfy the threshold. * of lines that satisfy the threshold.
*/ */
@@ -700,7 +720,7 @@ static void img_screen(struct vfs101_dev *vdev)
vdev->height = top - vdev->bottom + 1; vdev->height = top - vdev->bottom + 1;
/* Check max height */ /* Checkk max height */
if (vdev->height > VFS_IMG_MAX_HEIGHT) if (vdev->height > VFS_IMG_MAX_HEIGHT)
vdev->height = VFS_IMG_MAX_HEIGHT; vdev->height = VFS_IMG_MAX_HEIGHT;
@@ -734,11 +754,10 @@ 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 static void img_extract(struct fpi_ssm *ssm)
img_extract(fpi_ssm *ssm,
struct fp_img_dev *dev)
{ {
struct vfs101_dev *vdev = FP_INSTANCE_DATA(FP_DEV(dev)); struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
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 */
@@ -767,11 +786,6 @@ img_extract(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 &&
@@ -856,7 +870,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 (labs(count - VFS_IMG_BEST_CONTRAST) < abs(vdev->best_clevel - VFS_IMG_BEST_CONTRAST)) if (abs(count - VFS_IMG_BEST_CONRAST) < abs(vdev->best_clevel - VFS_IMG_BEST_CONRAST))
{ {
/* Better contrast found, use it */ /* Better contrast found, use it */
vdev->best_contrast = vdev->contrast; vdev->best_contrast = vdev->contrast;
@@ -898,10 +912,10 @@ enum
}; };
/* Exec loop sequential state machine */ /* Exec loop sequential state machine */
static void m_loop_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) static void m_loop_state(struct fpi_ssm *ssm)
{ {
struct fp_img_dev *dev = user_data; struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct vfs101_dev *vdev = FP_INSTANCE_DATA(_dev); struct vfs101_dev *vdev = fpi_imgdev_get_user_data(dev);
/* Check action state */ /* Check action state */
if (!vdev->active) if (!vdev->active)
@@ -915,17 +929,17 @@ static void m_loop_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
{ {
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, dev, VFS_BUFFER_HEIGHT, 1); vfs_get_print(ssm, 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, dev); async_sleep(50, ssm);
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, dev); vfs_get_finger_state(ssm);
break; break;
case M_LOOP_0_LOAD_IMAGE: case M_LOOP_0_LOAD_IMAGE:
@@ -940,14 +954,14 @@ static void m_loop_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
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, dev); vfs_img_load(ssm);
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_failed(ssm, -EIO); fpi_ssm_mark_aborted(ssm, -EIO);
break; break;
} }
break; break;
@@ -956,10 +970,10 @@ static void m_loop_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
/* 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, dev); img_extract(ssm);
/* Wait handling image */ /* Wait handling image */
async_sleep(10, ssm, dev); async_sleep(10, ssm);
break; break;
case M_LOOP_0_CHECK_ACTION: case M_LOOP_0_CHECK_ACTION:
@@ -979,7 +993,7 @@ static void m_loop_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
case M_LOOP_1_GET_STATE: case M_LOOP_1_GET_STATE:
/* Get finger state */ /* Get finger state */
vfs_get_finger_state(ssm, dev); vfs_get_finger_state(ssm);
break; break;
case M_LOOP_1_CHECK_STATE: case M_LOOP_1_CHECK_STATE:
@@ -997,14 +1011,14 @@ static void m_loop_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
/* Wait removing finger */ /* Wait removing finger */
vdev->counter++; vdev->counter++;
async_sleep(250, ssm, dev); async_sleep(250, ssm);
} }
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_failed(ssm, -EIO); fpi_ssm_mark_aborted(ssm, -EIO);
} }
} }
else else
@@ -1035,13 +1049,13 @@ static void m_loop_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
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, dev, VFS_BUFFER_HEIGHT, 1); vfs_get_print(ssm, 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, dev); vfs_img_load(ssm);
break; break;
case M_LOOP_1_LOOP: case M_LOOP_1_LOOP:
@@ -1051,29 +1065,29 @@ static void m_loop_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
case M_LOOP_1_SLEEP: case M_LOOP_1_SLEEP:
/* Wait fingerprint scanning */ /* Wait fingerprint scanning */
async_sleep(10, ssm, dev); async_sleep(10, ssm);
break; break;
case M_LOOP_2_ABORT_PRINT: case M_LOOP_2_ABORT_PRINT:
/* Abort print command */ /* Abort print command */
vfs_abort_print(ssm, dev); vfs_abort_print(ssm);
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, dev); vfs_img_load(ssm);
break; break;
case M_LOOP_3_GET_PRINT: case M_LOOP_3_GET_PRINT:
/* Get empty image */ /* Get empty image */
vfs_get_print(ssm, dev, 0x000a, 0); vfs_get_print(ssm, 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, dev); vfs_img_load(ssm);
break; break;
case M_LOOP_3_CHECK_IMAGE: case M_LOOP_3_CHECK_IMAGE:
@@ -1087,14 +1101,14 @@ static void m_loop_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
{ {
/* Wait aborting */ /* Wait aborting */
vdev->counter++; vdev->counter++;
async_sleep(100, ssm, dev); async_sleep(100, ssm);
} }
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_failed(ssm, -EIO); fpi_ssm_mark_aborted(ssm, -EIO);
} }
break; break;
@@ -1106,7 +1120,7 @@ static void m_loop_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
} }
/* Complete loop sequential state machine */ /* Complete loop sequential state machine */
static void m_loop_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) static void m_loop_complete(struct fpi_ssm *ssm)
{ {
/* Free sequential state machine */ /* Free sequential state machine */
fpi_ssm_free(ssm); fpi_ssm_free(ssm);
@@ -1162,10 +1176,10 @@ enum
}; };
/* Exec init sequential state machine */ /* Exec init sequential state machine */
static void m_init_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) static void m_init_state(struct fpi_ssm *ssm)
{ {
struct fp_img_dev *dev = user_data; struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct vfs101_dev *vdev = FP_INSTANCE_DATA(_dev); struct vfs101_dev *vdev = fpi_imgdev_get_user_data(dev);
/* Check action state */ /* Check action state */
if (!vdev->active) if (!vdev->active)
@@ -1178,31 +1192,31 @@ static void m_init_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_INIT_0_RECV_DIRTY: case M_INIT_0_RECV_DIRTY:
/* Recv eventually dirty data */ /* Recv eventualy dirty data */
vdev->ignore_error = TRUE; vdev->ignore_error = TRUE;
async_recv(ssm, dev); async_recv(ssm);
break; break;
case M_INIT_0_ABORT_PRINT: case M_INIT_0_ABORT_PRINT:
/* Abort print command */ /* Abort print command */
vfs_abort_print(ssm, dev); vfs_abort_print(ssm);
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, dev); vfs_img_load(ssm);
break; break;
case M_INIT_1_GET_PRINT: case M_INIT_1_GET_PRINT:
/* Get empty image */ /* Get empty image */
vfs_get_print(ssm, dev, 0x000a, 0); vfs_get_print(ssm, 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, dev); vfs_img_load(ssm);
break; break;
case M_INIT_1_CHECK_IMAGE: case M_INIT_1_CHECK_IMAGE:
@@ -1216,14 +1230,14 @@ static void m_init_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
{ {
/* Wait aborting */ /* Wait aborting */
vdev->counter++; vdev->counter++;
async_sleep(100, ssm, dev); async_sleep(100, ssm);
} }
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_failed(ssm, -EIO); fpi_ssm_mark_aborted(ssm, -EIO);
} }
break; break;
@@ -1234,7 +1248,7 @@ static void m_init_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
case M_INIT_2_GET_STATE: case M_INIT_2_GET_STATE:
/* Get finger state */ /* Get finger state */
vfs_get_finger_state(ssm, dev); vfs_get_finger_state(ssm);
break; break;
case M_INIT_2_CHECK_STATE: case M_INIT_2_CHECK_STATE:
@@ -1252,14 +1266,14 @@ static void m_init_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
/* Wait removing finger */ /* Wait removing finger */
vdev->counter++; vdev->counter++;
async_sleep(250, ssm, dev); async_sleep(250, ssm);
} }
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_failed(ssm, -EIO); fpi_ssm_mark_aborted(ssm, -EIO);
} }
} }
else else
@@ -1279,13 +1293,13 @@ static void m_init_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
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, dev, VFS_BUFFER_HEIGHT, 1); vfs_get_print(ssm, 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, dev); vfs_img_load(ssm);
break; break;
case M_INIT_2_LOOP: case M_INIT_2_LOOP:
@@ -1295,68 +1309,68 @@ static void m_init_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
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, dev, VFS_PAR_000E, VFS_VAL_000E); vfs_set_param(ssm, 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, dev, VFS_PAR_0011, VFS_VAL_0011); vfs_set_param(ssm, 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, dev, VFS_PAR_0076, VFS_VAL_0076); vfs_set_param(ssm, 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, dev, VFS_PAR_0078, VFS_VAL_0078); vfs_set_param(ssm, 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, dev, VFS_PAR_THRESHOLD, VFS_VAL_THRESHOLD); vfs_set_param(ssm, 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, dev, VFS_PAR_STATE_3, VFS_VAL_STATE_3); vfs_set_param(ssm, 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, dev, VFS_PAR_STATE_5, VFS_VAL_STATE_5); vfs_set_param(ssm, 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, dev, VFS_PAR_INFO_CONTRAST, 10); vfs_set_param(ssm, 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, dev, VFS_PAR_INFO_RATE, 32); vfs_set_param(ssm, 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, dev, VFS_REG_IMG_EXPOSURE, 0x4000, 0x02); vfs_poke(ssm, 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, dev, VFS_REG_IMG_CONTRAST, vdev->contrast, 0x01); vfs_poke(ssm, 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, dev, 0x000a, 0); vfs_get_print(ssm, 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, dev); vfs_img_load(ssm);
break; break;
case M_INIT_4_CHECK_CONTRAST: case M_INIT_4_CHECK_CONTRAST:
@@ -1382,32 +1396,32 @@ static void m_init_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
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, dev, VFS_REG_IMG_EXPOSURE, VFS_VAL_IMG_EXPOSURE, 0x02); vfs_poke(ssm, 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, dev, VFS_REG_IMG_CONTRAST, vdev->contrast, 0x01); vfs_poke(ssm, 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, dev, VFS_PAR_INFO_CONTRAST, vdev->contrast); vfs_set_param(ssm, 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, dev, VFS_PAR_INFO_RATE, VFS_VAL_INFO_RATE); vfs_set_param(ssm, 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(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) static void m_init_complete(struct fpi_ssm *ssm)
{ {
struct fp_img_dev *dev = user_data; struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct vfs101_dev *vdev = FP_INSTANCE_DATA(_dev); struct vfs101_dev *vdev = fpi_imgdev_get_user_data(dev);
fpi_ssm *ssm_loop; struct fpi_ssm *ssm_loop;
if (!fpi_ssm_get_error(ssm) && vdev->active) if (!fpi_ssm_get_error(ssm) && vdev->active)
{ {
@@ -1415,7 +1429,8 @@ static void m_init_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
fpi_imgdev_activate_complete(dev, 0); fpi_imgdev_activate_complete(dev, 0);
/* Start loop ssm */ /* Start loop ssm */
ssm_loop = fpi_ssm_new(FP_DEV(dev), m_loop_state, M_LOOP_NUM_STATES, dev); ssm_loop = fpi_ssm_new(fpi_imgdev_get_dev(dev), m_loop_state, M_LOOP_NUM_STATES);
fpi_ssm_set_user_data(ssm_loop, dev);
fpi_ssm_start(ssm_loop, m_loop_complete); fpi_ssm_start(ssm_loop, m_loop_complete);
} }
@@ -1424,10 +1439,10 @@ static void m_init_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
} }
/* Activate device */ /* Activate device */
static int dev_activate(struct fp_img_dev *dev) static int dev_activate(struct fp_img_dev *dev, enum fp_imgdev_state state)
{ {
struct vfs101_dev *vdev = FP_INSTANCE_DATA(FP_DEV(dev)); struct vfs101_dev *vdev = fpi_imgdev_get_user_data(dev);
fpi_ssm *ssm; struct fpi_ssm *ssm;
/* Check if already active */ /* Check if already active */
if (vdev->active) if (vdev->active)
@@ -1449,7 +1464,8 @@ static int dev_activate(struct fp_img_dev *dev)
vdev->enroll_stage = 0; vdev->enroll_stage = 0;
/* Start init ssm */ /* Start init ssm */
ssm = fpi_ssm_new(FP_DEV(dev), m_init_state, M_INIT_NUM_STATES, dev); ssm = fpi_ssm_new(fpi_imgdev_get_dev(dev), m_init_state, M_INIT_NUM_STATES);
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;
@@ -1458,13 +1474,13 @@ static int dev_activate(struct fp_img_dev *dev)
/* 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 = FP_INSTANCE_DATA(FP_DEV(dev)); struct vfs101_dev *vdev = fpi_imgdev_get_user_data(dev);
/* Reset active state */ /* Reset active state */
vdev->active = FALSE; vdev->active = FALSE;
/* Handle eventually existing events */ /* Handle eventualy existing events */
while (vdev->transfer) while (vdev->transfer || vdev->timeout)
fp_handle_events(); fp_handle_events();
/* Notify deactivate complete */ /* Notify deactivate complete */
@@ -1478,7 +1494,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_dev_get_usb_dev(FP_DEV(dev)), 0); r = libusb_claim_interface(fpi_imgdev_get_usb_dev(dev), 0);
if (r < 0) if (r < 0)
{ {
/* Interface not claimed, return error */ /* Interface not claimed, return error */
@@ -1489,7 +1505,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;
fp_dev_set_instance_data(FP_DEV(dev), vdev); fpi_imgdev_set_user_data(dev, vdev);
/* Notify open complete */ /* Notify open complete */
fpi_imgdev_open_complete(dev, 0); fpi_imgdev_open_complete(dev, 0);
@@ -1503,11 +1519,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 = FP_INSTANCE_DATA(FP_DEV(dev)); vdev = fpi_imgdev_get_user_data(dev);
g_free(vdev); g_free(vdev);
/* Release usb interface */ /* Release usb interface */
libusb_release_interface(fpi_dev_get_usb_dev(FP_DEV(dev)), 0); libusb_release_interface(fpi_imgdev_get_usb_dev(dev), 0);
/* Notify close complete */ /* Notify close complete */
fpi_imgdev_close_complete(dev); fpi_imgdev_close_complete(dev);

View File

@@ -26,26 +26,35 @@
/************************** GENERIC STUFF *************************************/ /************************** GENERIC STUFF *************************************/
/* Submit asynchronous sleep */ /* Callback of asynchronous sleep */
static void static void async_sleep_cb(void *data)
async_sleep(unsigned int msec,
fpi_ssm *ssm,
struct fp_img_dev *dev)
{ {
struct fpi_ssm *ssm = data;
fpi_ssm_next_state(ssm);
}
/* Submit asynchronous sleep */
static void async_sleep(unsigned int msec, struct fpi_ssm *ssm)
{
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct fpi_timeout *timeout;
/* Add timeout */ /* Add timeout */
if (fpi_timeout_add(msec, fpi_ssm_next_state_timeout_cb, FP_DEV(dev), ssm) == NULL) { timeout = fpi_timeout_add(msec, async_sleep_cb, ssm);
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_failed(ssm, -ETIME); fpi_ssm_mark_aborted(ssm, -ETIME);
} }
} }
static int static int submit_image(struct fpi_ssm *ssm)
submit_image(fpi_ssm *ssm,
struct fp_img_dev *dev)
{ {
vfs301_dev_t *vdev = FP_INSTANCE_DATA(FP_DEV(dev)); struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
vfs301_dev_t *vdev = fpi_imgdev_get_user_data(dev);
int height; int height;
struct fp_img *img; struct fp_img *img;
@@ -71,7 +80,7 @@ submit_image(fpi_ssm *ssm,
img->width = VFS301_FP_OUTPUT_WIDTH; img->width = VFS301_FP_OUTPUT_WIDTH;
img->height = height; img->height = height;
img = fpi_img_realloc(img, img->height * img->width); img = fpi_img_resize(img, img->height * img->width);
fpi_imgdev_image_captured(dev, img); fpi_imgdev_image_captured(dev, img);
return 1; return 1;
@@ -94,24 +103,24 @@ enum
}; };
/* Exec loop sequential state machine */ /* Exec loop sequential state machine */
static void m_loop_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) static void m_loop_state(struct fpi_ssm *ssm)
{ {
struct fp_img_dev *dev = user_data; struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
vfs301_dev_t *vdev = FP_INSTANCE_DATA(_dev); vfs301_dev_t *vdev = fpi_imgdev_get_user_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_dev_get_usb_dev(FP_DEV(dev)), vdev); vfs301_proto_request_fingerprint(fpi_imgdev_get_usb_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, dev); async_sleep(200, ssm);
break; break;
case M_CHECK_PRINT: case M_CHECK_PRINT:
if (!vfs301_proto_peek_event(fpi_dev_get_usb_dev(FP_DEV(dev)), vdev)) if (!vfs301_proto_peek_event(fpi_imgdev_get_usb_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);
@@ -119,18 +128,18 @@ static void m_loop_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
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_dev_get_usb_dev(FP_DEV(dev)), vdev); vfs301_proto_process_event_start(fpi_imgdev_get_usb_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, dev); async_sleep(200, ssm);
break; break;
case M_READ_PRINT_POLL: case M_READ_PRINT_POLL:
{ {
int rv = vfs301_proto_process_event_poll(fpi_dev_get_usb_dev(FP_DEV(dev)), vdev); int rv = vfs301_proto_process_event_poll(fpi_imgdev_get_usb_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);
@@ -140,7 +149,7 @@ static void m_loop_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
break; break;
case M_SUBMIT_PRINT: case M_SUBMIT_PRINT:
if (submit_image(ssm, dev)) { if (submit_image(ssm)) {
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);
@@ -152,37 +161,38 @@ static void m_loop_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
} }
/* Complete loop sequential state machine */ /* Complete loop sequential state machine */
static void m_loop_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) static void m_loop_complete(struct fpi_ssm *ssm)
{ {
/* 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(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) static void m_init_state(struct fpi_ssm *ssm)
{ {
struct fp_img_dev *dev = user_data; struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
vfs301_dev_t *vdev = FP_INSTANCE_DATA(_dev); vfs301_dev_t *vdev = fpi_imgdev_get_user_data(dev);
g_assert(fpi_ssm_get_cur_state(ssm) == 0); g_assert(fpi_ssm_get_cur_state(ssm) == 0);
vfs301_proto_init(fpi_dev_get_usb_dev(FP_DEV(dev)), vdev); vfs301_proto_init(fpi_imgdev_get_usb_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(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) static void m_init_complete(struct fpi_ssm *ssm)
{ {
struct fp_img_dev *dev = user_data; struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
fpi_ssm *ssm_loop; struct 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(FP_DEV(dev), m_loop_state, M_LOOP_NUM_STATES, dev); ssm_loop = fpi_ssm_new(fpi_imgdev_get_dev(dev), m_loop_state, M_LOOP_NUM_STATES);
fpi_ssm_set_user_data(ssm_loop, dev);
fpi_ssm_start(ssm_loop, m_loop_complete); fpi_ssm_start(ssm_loop, m_loop_complete);
} }
@@ -191,12 +201,13 @@ static void m_init_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
} }
/* Activate device */ /* Activate device */
static int dev_activate(struct fp_img_dev *dev) static int dev_activate(struct fp_img_dev *dev, enum fp_imgdev_state state)
{ {
fpi_ssm *ssm; struct fpi_ssm *ssm;
/* Start init ssm */ /* Start init ssm */
ssm = fpi_ssm_new(FP_DEV(dev), m_init_state, 1, dev); ssm = fpi_ssm_new(fpi_imgdev_get_dev(dev), m_init_state, 1);
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;
@@ -205,10 +216,6 @@ static int dev_activate(struct fp_img_dev *dev)
/* 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);
} }
@@ -218,7 +225,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_dev_get_usb_dev(FP_DEV(dev)), 0); r = libusb_claim_interface(fpi_imgdev_get_usb_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));
@@ -227,7 +234,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));
fp_dev_set_instance_data(FP_DEV(dev), vdev); fpi_imgdev_set_user_data(dev, vdev);
vdev->scanline_buf = malloc(0); vdev->scanline_buf = malloc(0);
vdev->scanline_count = 0; vdev->scanline_count = 0;
@@ -243,12 +250,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 = FP_INSTANCE_DATA(FP_DEV(dev)); vdev = fpi_imgdev_get_user_data(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_dev_get_usb_dev(FP_DEV(dev)), 0); libusb_release_interface(fpi_imgdev_get_usb_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,7 +499,12 @@ 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 = fpi_usb_alloc(); transfer = libusb_alloc_transfer(0);
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

@@ -109,7 +109,7 @@ typedef struct {
unsigned char scan[VFS301_FP_WIDTH]; unsigned char scan[VFS301_FP_WIDTH];
/* A offsetted, stretched, inverted copy of scan... probably could /* A offseted, stretched, inverted copy of scan... probably could
* serve finger motion speed detection? * serve finger motion speed detection?
* Seems to be subdivided to some 10B + 53B + 1B blocks */ * Seems to be subdivided to some 10B + 53B + 1B blocks */
unsigned char mirror[64]; unsigned char mirror[64];

View File

@@ -1147,7 +1147,7 @@ static const unsigned char vfs301_24[] = { /* 119 B */
* *
* The contents of PACKET() inside this blob seems to be some kind * The contents of PACKET() inside this blob seems to be some kind
* of a micro-program, which specifies which columns contain what. LE seems * of a micro-program, which specifies which columns contain what. LE seems
* to be used also here. Not necessarily is 1 output column described * to be used also here. Not neccessarily is 1 output column described
* by 1 operation. For example the vfs301_line_t::sum section seems * by 1 operation. For example the vfs301_line_t::sum section seems
* to perform 2 operations for each column - probably some kind of diff between * to perform 2 operations for each column - probably some kind of diff between
* input lines? * input lines?

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)
{ {
fpi_ssm *ssm = transfer->user_data; struct 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_failed(ssm, -EINVAL); fpi_ssm_mark_aborted(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_failed(ssm, -EINVAL); fpi_ssm_mark_aborted(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_failed(ssm, -EIO); fpi_ssm_mark_aborted(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_failed(ssm, -EIO); fpi_ssm_mark_aborted(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)
{ {
fpi_ssm *ssm = transfer->user_data; struct 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_failed(ssm, -EIO); fpi_ssm_mark_aborted(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_failed(ssm, -EINVAL); fpi_ssm_mark_aborted(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_failed(ssm, -EINVAL); fpi_ssm_mark_aborted(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_failed(ssm, -EIO); fpi_ssm_mark_aborted(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_failed(ssm, -EIO); fpi_ssm_mark_aborted(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(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) static void usbexchange_loop(struct fpi_ssm *ssm)
{ {
struct usbexchange_data *data = user_data; struct usbexchange_data *data = fpi_ssm_get_user_data(ssm);
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_failed(ssm, -EINVAL); fpi_ssm_mark_aborted(ssm, -EINVAL);
return; return;
} }
@@ -189,8 +189,14 @@ static void usbexchange_loop(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
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 = fpi_usb_alloc(); transfer = libusb_alloc_transfer(0);
libusb_fill_bulk_transfer(transfer, fpi_dev_get_usb_dev(FP_DEV(data->device)), if (transfer == NULL) {
fp_err("Failed to allocate transfer");
fpi_imgdev_session_error(data->device, -ENOMEM);
fpi_ssm_mark_aborted(ssm, -ENOMEM);
return;
}
libusb_fill_bulk_transfer(transfer, fpi_imgdev_get_usb_dev(data->device),
action->endpoint, action->data, action->endpoint, action->data,
action->size, async_send_cb, ssm, action->size, async_send_cb, ssm,
data->timeout); data->timeout);
@@ -199,8 +205,14 @@ static void usbexchange_loop(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
case ACTION_RECEIVE: case ACTION_RECEIVE:
fp_dbg("Receiving %d bytes", action->size); fp_dbg("Receiving %d bytes", action->size);
transfer = fpi_usb_alloc(); transfer = libusb_alloc_transfer(0);
libusb_fill_bulk_transfer(transfer, fpi_dev_get_usb_dev(FP_DEV(data->device)), if (transfer == NULL) {
fp_err("Failed to allocate transfer");
fpi_imgdev_session_error(data->device, -ENOMEM);
fpi_ssm_mark_aborted(ssm, -ENOMEM);
return;
}
libusb_fill_bulk_transfer(transfer, fpi_imgdev_get_usb_dev(data->device),
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);
@@ -210,24 +222,24 @@ static void usbexchange_loop(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
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_failed(ssm, -EINVAL); fpi_ssm_mark_aborted(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_failed(ssm, ret); fpi_ssm_mark_aborted(ssm, ret);
} }
} }
static void usb_exchange_async(fpi_ssm *ssm, static void usb_exchange_async(struct fpi_ssm *ssm,
struct usbexchange_data *data) struct usbexchange_data *data)
{ {
fpi_ssm *subsm = fpi_ssm_new(FP_DEV(data->device), struct fpi_ssm *subsm = fpi_ssm_new(fpi_imgdev_get_dev(data->device),
usbexchange_loop, usbexchange_loop,
data->stepcount, data->stepcount);
data); fpi_ssm_set_user_data(subsm, data);
fpi_ssm_start_subsm(ssm, subsm); fpi_ssm_start_subsm(ssm, subsm);
} }
@@ -371,7 +383,7 @@ static int process_chunk(struct vfs5011_data *data, int transferred)
VFS5011_IMAGE_WIDTH) >= DIFFERENCE_THRESHOLD)) { VFS5011_IMAGE_WIDTH) >= DIFFERENCE_THRESHOLD)) {
data->lastline = g_malloc(VFS5011_LINE_SIZE); data->lastline = g_malloc(VFS5011_LINE_SIZE);
data->rows = g_slist_prepend(data->rows, data->lastline); data->rows = g_slist_prepend(data->rows, data->lastline);
memmove(data->lastline, linebuf, VFS5011_LINE_SIZE); g_memmove(data->lastline, linebuf, VFS5011_LINE_SIZE);
data->lines_recorded++; data->lines_recorded++;
if (data->lines_recorded >= data->max_lines_recorded) { if (data->lines_recorded >= data->max_lines_recorded) {
fp_dbg("process_chunk: recorded %d lines, finishing", fp_dbg("process_chunk: recorded %d lines, finishing",
@@ -383,11 +395,9 @@ static int process_chunk(struct vfs5011_data *data, int transferred)
return 0; return 0;
} }
static void void submit_image(struct fpi_ssm *ssm, struct vfs5011_data *data)
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) {
@@ -405,18 +415,18 @@ submit_image(fpi_ssm *ssm,
g_slist_free_full(data->rows, g_free); g_slist_free_full(data->rows, g_free);
data->rows = NULL; data->rows = NULL;
fp_dbg("Image captured, committing"); fp_dbg("Image captured, commiting");
fpi_imgdev_image_captured(dev, img); fpi_imgdev_image_captured(dev, img);
} }
static void chunk_capture_callback(struct libusb_transfer *transfer) static void chunk_capture_callback(struct libusb_transfer *transfer)
{ {
fpi_ssm *ssm = (fpi_ssm *)transfer->user_data; struct fpi_ssm *ssm = (struct 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 = FP_INSTANCE_DATA(FP_DEV(dev)); data = fpi_imgdev_get_user_data(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)) {
@@ -431,7 +441,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_failed(ssm, -1); fpi_ssm_mark_aborted(ssm, -1);
} else { } else {
fpi_ssm_mark_completed(ssm); fpi_ssm_mark_completed(ssm);
} }
@@ -442,7 +452,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, fpi_ssm *ssm) int timeout, struct 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);
@@ -452,7 +462,7 @@ static int capture_chunk_async(struct vfs5011_data *data,
STOP_CHECK_LINES = 50 STOP_CHECK_LINES = 50
}; };
data->flying_transfer = fpi_usb_alloc(); data->flying_transfer = libusb_alloc_transfer(0);
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,
@@ -460,6 +470,13 @@ 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
@@ -648,16 +665,16 @@ struct usb_action vfs5011_initiate_capture[] = {
/* ====================== lifprint interface ======================= */ /* ====================== lifprint interface ======================= */
static void activate_loop(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) static void activate_loop(struct fpi_ssm *ssm)
{ {
enum {READ_TIMEOUT = 0}; enum {READ_TIMEOUT = 0};
struct fp_img_dev *dev = user_data; struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct vfs5011_data *data; struct vfs5011_data *data;
int r; int r;
fpi_timeout *timeout; struct fpi_timeout *timeout;
data = FP_INSTANCE_DATA(_dev); data = fpi_imgdev_get_user_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));
@@ -690,23 +707,23 @@ static void activate_loop(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
break; break;
case DEV_ACTIVATE_READ_DATA: case DEV_ACTIVATE_READ_DATA:
r = capture_chunk_async(data, fpi_dev_get_usb_dev(FP_DEV(dev)), CAPTURE_LINES, r = capture_chunk_async(data, fpi_imgdev_get_usb_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_failed(ssm, r); fpi_ssm_mark_aborted(ssm, r);
} }
break; break;
case DEV_ACTIVATE_DATA_COMPLETE: case DEV_ACTIVATE_DATA_COMPLETE:
timeout = fpi_timeout_add(1, fpi_ssm_next_state_timeout_cb, _dev, ssm); timeout = fpi_timeout_add(1, async_sleep_cb, 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_failed(ssm, -1); fpi_ssm_mark_aborted(ssm, -1);
} }
break; break;
@@ -725,20 +742,20 @@ static void activate_loop(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
} }
} }
static void activate_loop_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) static void activate_loop_complete(struct fpi_ssm *ssm)
{ {
struct fp_img_dev *dev = user_data; struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct vfs5011_data *data; struct vfs5011_data *data;
int r = fpi_ssm_get_error(ssm); int r = fpi_ssm_get_error(ssm);
data = FP_INSTANCE_DATA(_dev); data = fpi_imgdev_get_user_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, dev); submit_image(ssm, data);
fpi_imgdev_report_finger_status(dev, FALSE); fpi_imgdev_report_finger_status(dev, FALSE);
} }
fpi_ssm_free(ssm); fpi_ssm_free(ssm);
@@ -755,12 +772,12 @@ static void activate_loop_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user
} }
static void open_loop(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) static void open_loop(struct fpi_ssm *ssm)
{ {
struct fp_img_dev *dev = user_data; struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct vfs5011_data *data; struct vfs5011_data *data;
data = FP_INSTANCE_DATA(_dev); data = fpi_imgdev_get_user_data(dev);
switch (fpi_ssm_get_cur_state(ssm)) { switch (fpi_ssm_get_cur_state(ssm)) {
case DEV_OPEN_START: case DEV_OPEN_START:
@@ -776,12 +793,12 @@ static void open_loop(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
}; };
} }
static void open_loop_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data) static void open_loop_complete(struct fpi_ssm *ssm)
{ {
struct fp_img_dev *dev = user_data; struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct vfs5011_data *data; struct vfs5011_data *data;
data = FP_INSTANCE_DATA(_dev); data = fpi_imgdev_get_user_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;
@@ -798,22 +815,23 @@ 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);
fp_dev_set_instance_data(FP_DEV(dev), data); fpi_imgdev_set_user_data(dev, data);
r = libusb_reset_device(fpi_dev_get_usb_dev(FP_DEV(dev))); r = libusb_reset_device(fpi_imgdev_get_usb_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_dev_get_usb_dev(FP_DEV(dev)), 0); r = libusb_claim_interface(fpi_imgdev_get_usb_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;
} }
fpi_ssm *ssm; struct fpi_ssm *ssm;
ssm = fpi_ssm_new(FP_DEV(dev), open_loop, DEV_OPEN_NUM_STATES, dev); ssm = fpi_ssm_new(fpi_imgdev_get_dev(dev), open_loop, DEV_OPEN_NUM_STATES);
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;
@@ -821,9 +839,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_dev_get_usb_dev(FP_DEV(dev)), 0); libusb_release_interface(fpi_imgdev_get_usb_dev(dev), 0);
struct vfs5011_data *data; struct vfs5011_data *data;
data = FP_INSTANCE_DATA(FP_DEV(dev)); data = fpi_imgdev_get_user_data(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);
@@ -835,22 +853,23 @@ 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;
fpi_ssm *ssm; struct fpi_ssm *ssm;
data = FP_INSTANCE_DATA(FP_DEV(dev)); data = fpi_imgdev_get_user_data(dev);
data->loop_running = TRUE; data->loop_running = TRUE;
fp_dbg("creating ssm"); fp_dbg("creating ssm");
ssm = fpi_ssm_new(FP_DEV(dev), activate_loop, DEV_ACTIVATE_NUM_STATES, dev); ssm = fpi_ssm_new(fpi_imgdev_get_dev(dev), activate_loop, DEV_ACTIVATE_NUM_STATES);
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");
} }
static int dev_activate(struct fp_img_dev *dev) static int dev_activate(struct fp_img_dev *dev, enum fp_imgdev_state state)
{ {
struct vfs5011_data *data; struct vfs5011_data *data;
data = FP_INSTANCE_DATA(FP_DEV(dev)); data = fpi_imgdev_get_user_data(dev);
fp_dbg("device initialized"); fp_dbg("device initialized");
data->deactivating = FALSE; data->deactivating = FALSE;
@@ -864,7 +883,7 @@ static void dev_deactivate(struct fp_img_dev *dev)
int r; int r;
struct vfs5011_data *data; struct vfs5011_data *data;
data = FP_INSTANCE_DATA(FP_DEV(dev)); data = fpi_imgdev_get_user_data(dev);
if (data->loop_running) { if (data->loop_running) {
data->deactivating = TRUE; data->deactivating = TRUE;
if (data->flying_transfer) { if (data->flying_transfer) {
@@ -879,7 +898,6 @@ 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,17 +23,282 @@
#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 "fpi-log.h" #include "assembling.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

199
libfprint/drv.c Normal file
View File

@@ -0,0 +1,199 @@
/*
* 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,39 +22,31 @@
#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"
/* Global variables */ #define container_of(ptr, type, member) ({ \
extern libusb_context *fpi_usb_ctx; const typeof( ((type *)0)->member ) *__mptr = (ptr); \
extern GSList *opened_devices; (type *)( (char *)__mptr - offsetof(type,member) );})
/* fp_print_data structure definition */ #define fp_dbg g_debug
enum fp_print_data_type { #define fp_info g_debug
PRINT_DATA_RAW = 0, /* memset-imposed default */ #define fp_warn g_warning
PRINT_DATA_NBIS_MINUTIAE #define fp_err g_error
};
struct fp_print_data { #define BUG_ON(condition) g_assert(!(condition))
uint16_t driver_id; #define BUG() g_assert_not_reached()
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,
@@ -79,20 +71,16 @@ enum fp_dev_state {
DEV_STATE_CAPTURE_STOPPING, DEV_STATE_CAPTURE_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;
@@ -128,10 +116,39 @@ struct fp_dev {
struct fp_print_data **identify_gallery; struct fp_print_data **identify_gallery;
}; };
/* fp_img_dev structure definition */ enum fp_imgdev_state {
struct fp_img_dev { IMGDEV_STATE_INACTIVE,
struct fp_dev *parent; 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_dev *dev;
libusb_device_handle *udev;
enum fp_imgdev_action action; enum fp_imgdev_action action;
int action_state; int action_state;
@@ -143,18 +160,78 @@ 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;
}; };
/* fp_driver structure definition */ int fpi_imgdev_get_img_width(struct fp_img_dev *imgdev);
int fpi_imgdev_get_img_height(struct fp_img_dev *imgdev);
struct usb_id {
uint16_t vendor;
uint16_t product;
unsigned long driver_data;
};
enum fp_driver_type {
DRIVER_PRIMITIVE = 0,
DRIVER_IMAGING = 1,
};
struct fp_driver {
const uint16_t id;
const char *name;
const char *full_name;
const struct usb_id * const id_table;
enum fp_driver_type type;
enum fp_scan_type scan_type;
void *priv;
/* Device operations */
int (*discover)(struct libusb_device_descriptor *dsc, uint32_t *devtype);
int (*open)(struct fp_dev *dev, unsigned long driver_data);
void (*close)(struct fp_dev *dev);
int (*enroll_start)(struct fp_dev *dev);
int (*enroll_stop)(struct fp_dev *dev);
int (*verify_start)(struct fp_dev *dev);
int (*verify_stop)(struct fp_dev *dev, gboolean iterating);
int (*identify_start)(struct fp_dev *dev);
int (*identify_stop)(struct fp_dev *dev, gboolean iterating);
int (*capture_start)(struct fp_dev *dev);
int (*capture_stop)(struct fp_dev *dev);
};
enum fp_print_data_type fpi_driver_get_data_type(struct fp_driver *drv);
/* flags for fp_img_driver.flags */
#define FP_IMGDRV_SUPPORTS_UNCONDITIONAL_CAPTURE (1 << 0)
struct fp_img_driver {
struct fp_driver driver;
uint16_t flags;
int img_width;
int img_height;
int bz3_threshold;
/* Device operations */
int (*open)(struct fp_img_dev *dev, unsigned long driver_data);
void (*close)(struct fp_img_dev *dev);
int (*activate)(struct fp_img_dev *dev, enum fp_imgdev_state state);
int (*change_state)(struct fp_img_dev *dev, enum fp_imgdev_state state);
void (*deactivate)(struct fp_img_dev *dev);
};
#include "drivers_definitions.h"
extern libusb_context *fpi_usb_ctx;
extern GSList *opened_devices;
void fpi_img_driver_setup(struct fp_img_driver *idriver);
/* fp_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;
@@ -162,7 +239,6 @@ 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;
@@ -170,7 +246,43 @@ struct fp_dscv_print {
char *path; char *path;
}; };
/* fp_minutia structure definition */ enum fp_print_data_type {
PRINT_DATA_RAW = 0, /* memset-imposed default */
PRINT_DATA_NBIS_MINUTIAE,
};
struct fp_print_data_item {
size_t length;
unsigned char data[0];
};
struct fp_print_data {
uint16_t driver_id;
uint32_t devtype;
enum fp_print_data_type type;
GSList *prints;
};
struct fpi_print_data_fp2 {
char prefix[3];
uint16_t driver_id;
uint32_t devtype;
unsigned char data_type;
unsigned char data[0];
} __attribute__((__packed__));
struct fpi_print_data_item_fp2 {
uint32_t length;
unsigned char data[0];
} __attribute__((__packed__));
void fpi_data_exit(void);
struct fp_print_data *fpi_print_data_new(struct fp_dev *dev);
struct fp_print_data_item *fpi_print_data_item_new(size_t length);
gboolean fpi_print_data_compatible(uint16_t driver_id1, uint32_t devtype1,
enum fp_print_data_type type1, uint16_t driver_id2, uint32_t devtype2,
enum fp_print_data_type type2);
struct fp_minutia { struct fp_minutia {
int x; int x;
int y; int y;
@@ -186,32 +298,34 @@ 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;
}; };
/* Defined in fpi-dev-img.c */ /* bit values for fp_img.flags */
void fpi_img_driver_setup(struct fp_img_driver *idriver); #define FP_IMG_V_FLIPPED (1<<0)
int fpi_imgdev_get_img_width(struct fp_img_dev *imgdev); #define FP_IMG_H_FLIPPED (1<<1)
int fpi_imgdev_get_img_height(struct fp_img_dev *imgdev); #define FP_IMG_COLORS_INVERTED (1<<2)
#define FP_IMG_BINARIZED_FORM (1<<3)
#define FP_IMG_PARTIAL (1<<4)
/* Exported for use in command-line tools #define FP_IMG_STANDARDIZATION_FLAGS (FP_IMG_V_FLIPPED | FP_IMG_H_FLIPPED \
* Defined in fpi-core.c */ | FP_IMG_COLORS_INVERTED)
struct fp_driver **fprint_get_drivers (void);
/* Defined in fpi-core.c */ struct fp_img {
enum fp_print_data_type fpi_driver_get_data_type(struct fp_driver *drv); int width;
int height;
size_t length;
uint16_t flags;
struct fp_minutiae *minutiae;
unsigned char *binarized;
unsigned char data[0];
};
/* Defined in fpi-data.c */ struct fp_img *fpi_img_new(size_t length);
void fpi_data_exit(void); struct fp_img *fpi_img_resize(struct fp_img *img, size_t newsize);
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);
@@ -219,23 +333,71 @@ 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);
/* Defined in fpi-async.c */ typedef void (*fpi_timeout_fn)(void *data);
void fpi_drvcb_capture_started(struct fp_dev *dev, int status);
void fpi_drvcb_report_capture_result(struct fp_dev *dev, int result, /* async drv <--> lib comms */
struct fpi_ssm;
typedef void (*ssm_completed_fn)(struct fpi_ssm *ssm);
typedef void (*ssm_handler_fn)(struct fpi_ssm *ssm);
/* sequential state machine: state machine that iterates sequentially over
* a predefined series of states. can be aborted by either completion or
* abortion error conditions. */
struct fpi_ssm {
struct fp_dev *dev;
struct fpi_ssm *parentsm;
void *priv;
int nr_states;
int cur_state;
gboolean completed;
int error;
ssm_completed_fn callback;
ssm_handler_fn handler;
};
/* for library and drivers */
struct fpi_ssm *fpi_ssm_new(struct fp_dev *dev, ssm_handler_fn handler,
int nr_states);
void fpi_ssm_free(struct fpi_ssm *machine);
void fpi_ssm_start(struct fpi_ssm *machine, ssm_completed_fn callback);
/* for drivers */
void fpi_ssm_next_state(struct fpi_ssm *machine);
void fpi_ssm_jump_to_state(struct fpi_ssm *machine, int state);
void fpi_ssm_mark_completed(struct fpi_ssm *machine);
void fpi_ssm_mark_aborted(struct fpi_ssm *machine, int error);
void fpi_drvcb_open_complete(struct fp_dev *dev, int status);
void fpi_drvcb_close_complete(struct fp_dev *dev);
void fpi_drvcb_enroll_started(struct fp_dev *dev, int status);
void fpi_drvcb_enroll_stage_completed(struct fp_dev *dev, int result,
struct fp_print_data *data, struct fp_img *img);
void fpi_drvcb_enroll_stopped(struct fp_dev *dev);
void fpi_drvcb_verify_started(struct fp_dev *dev, int status);
void fpi_drvcb_report_verify_result(struct fp_dev *dev, int result,
struct fp_img *img); struct fp_img *img);
void fpi_drvcb_capture_stopped(struct fp_dev *dev); void fpi_drvcb_verify_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);
#include "drivers_definitions.h" 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);
#endif #endif

View File

@@ -1,115 +0,0 @@
/*
* 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

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

View File

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

View File

@@ -1,34 +0,0 @@
/*
* 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

@@ -1,101 +0,0 @@
/*
* 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

View File

@@ -1,150 +0,0 @@
/*
* 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;
}

View File

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

View File

@@ -1,85 +0,0 @@
/*
* 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

View File

@@ -1,98 +0,0 @@
/*
* 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

@@ -1,51 +0,0 @@
/*
* 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

View File

@@ -1,317 +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 "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;
}

View File

@@ -1,86 +0,0 @@
/*
* 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

@@ -1,236 +0,0 @@
/*
* 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);
}

View File

@@ -1,70 +0,0 @@
/*
* 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,6 +24,10 @@
#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,24 +25,15 @@ 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 in this section. * functions below.
*/ */
struct fp_dscv_dev; struct fp_dscv_dev;
@@ -50,7 +41,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 in this section. * functions below.
*/ */
struct fp_dscv_print; struct fp_dscv_print;
@@ -58,7 +49,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 in this section. * functions below.
*/ */
struct fp_dev; struct fp_dev;
@@ -66,7 +57,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 in this section. * functions below.
*/ */
struct fp_driver; struct fp_driver;
@@ -74,7 +65,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 in this section. * functions below.
*/ */
struct fp_print_data; struct fp_print_data;
@@ -82,7 +73,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 in this section. * functions below.
*/ */
struct fp_img; struct fp_img;
@@ -137,7 +128,6 @@ 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);
@@ -173,10 +163,11 @@ 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,
@@ -275,13 +266,11 @@ int fp_identify_finger(struct fp_dev *dev,
/* 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) LIBFPRINT_DEPRECATED; struct fp_print_data **data);
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);
LIBFPRINT_DEPRECATED; int fp_print_data_delete(struct fp_dev *dev, enum fp_finger finger);
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,
@@ -295,7 +284,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 in this section. * functions below.
*/ */
struct fp_minutia; struct fp_minutia;
@@ -306,7 +295,6 @@ 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 */
@@ -316,17 +304,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 int events; short 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);
ssize_t fp_get_pollfds(struct fp_pollfd **pollfds); size_t fp_get_pollfds(struct fp_pollfd **pollfds);
int fp_get_next_timeout(struct timeval *tv); int fp_get_next_timeout(struct timeval *tv);
/** /**
@@ -338,7 +326,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 int events); typedef void (*fp_pollfd_added_cb)(int fd, short events);
/** /**
* fp_pollfd_removed_cb: * fp_pollfd_removed_cb:
@@ -360,7 +348,7 @@ void fp_set_debug(int level) LIBFPRINT_DEPRECATED;
/** /**
* fp_operation_stop_cb: * fp_operation_stop_cb:
* @dev: the struct #fp_dev device * @dev: the #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(),
@@ -371,7 +359,7 @@ typedef void (*fp_operation_stop_cb)(struct fp_dev *dev, void *user_data);
/** /**
* fp_img_operation_cb: * fp_img_operation_cb:
* @dev: the struct #fp_dev device * @dev: the #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
@@ -385,7 +373,7 @@ typedef void (*fp_img_operation_cb)(struct fp_dev *dev, int result,
/** /**
* fp_dev_open_cb: * fp_dev_open_cb:
* @dev: the struct #fp_dev device * @dev: the #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
* *
@@ -402,15 +390,14 @@ void fp_async_dev_close(struct fp_dev *dev, fp_operation_stop_cb callback,
/** /**
* fp_enroll_stage_cb: * fp_enroll_stage_cb:
* @dev: the struct #fp_dev device * @dev: the #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. See fp_enroll_finger_img() for * fp_async_enroll_start() finishes.
* 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);
@@ -429,7 +416,7 @@ int fp_async_verify_stop(struct fp_dev *dev, fp_operation_stop_cb callback,
/** /**
* fp_identify_cb: * fp_identify_cb:
* @dev: the struct #fp_dev device * @dev: the #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.

View File

@@ -31,7 +31,6 @@
/** /**
* 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
@@ -49,25 +48,6 @@
* 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);
@@ -76,19 +56,9 @@ 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(FP_DEV(imgdev)->drv); struct fp_img_driver *imgdrv = fpi_driver_to_img_driver(imgdev->dev->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);
@@ -97,53 +67,27 @@ 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 <= 0 || img->height <= 0) if (!img->length || !img->width || !img->height)
return FALSE; return FALSE;
/* Are width and height just too big? */ /* buffer is big enough? */
if (!g_uint_checked_mul(&len, img->width, img->height) || if ((img->length * img->height) < img->length)
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.
*/ */
@@ -318,8 +262,9 @@ 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;
/* struct xyt_struct uses arrays of MAX_BOZORTH_MINUTIAE (200) */ /* FIXME: only considers first 150 minutiae (MAX_FILE_MINUTIAE) */
int nmin = min(minutiae->num, MAX_BOZORTH_MINUTIAE); /* nist does weird stuff with 150 vs 1000 limits */
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];
@@ -343,9 +288,6 @@ 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;
@@ -358,10 +300,13 @@ 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("Cannot detect minutiae for non-standardized images"); fp_err("cant detect minutiae for non-standardized image");
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,
@@ -405,9 +350,9 @@ int fpi_img_to_print_data(struct fp_img_dev *imgdev, struct fp_img *img,
} }
} }
/* FIXME: space is wasted if we don't 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(FP_DEV(imgdev)); print = fpi_print_data_new(imgdev->dev);
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);
@@ -591,46 +536,57 @@ API_EXPORTED struct fp_minutia **fp_img_get_minutiae(struct fp_img *img,
return img->minutiae->list; return img->minutiae->list;
} }
/** libusb_device_handle *
* fp_minutia_get_coords: fpi_imgdev_get_usb_dev(struct fp_img_dev *dev)
* @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)
{ {
g_return_val_if_fail (minutia != NULL, -1); return dev->udev;
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_std_sq_dev: fpi_imgdev_set_user_data(struct fp_img_dev *imgdev,
* @buf: buffer (usually bitmap, one byte per pixel) void *user_data)
* @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 *
* mean = sum (buf[0..size]) / size fpi_imgdev_get_user_data(struct fp_img_dev *imgdev)
* 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 *
* Returns: the squared standard deviation for @buffer fpi_imgdev_get_dev(struct fp_img_dev *imgdev)
*/ {
return imgdev->dev;
}
enum fp_imgdev_enroll_state
fpi_imgdev_get_action_state(struct fp_img_dev *imgdev)
{
return imgdev->action_state;
}
enum fp_imgdev_action
fpi_imgdev_get_action(struct fp_img_dev *imgdev)
{
return imgdev->action;
}
int
fpi_imgdev_get_action_result(struct fp_img_dev *imgdev)
{
return imgdev->action_result;
}
void
fpi_imgdev_set_action_result(struct fp_img_dev *imgdev,
int action_result)
{
imgdev->action_result = action_result;
}
/* Calculate squared standand deviation */
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;
@@ -653,23 +609,7 @@ 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;

View File

@@ -21,94 +21,26 @@
#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;
/* Set up back pointers */ imgdev->dev = dev;
dev->img_dev = imgdev;
imgdev->parent = dev;
imgdev->enroll_stage = 0; imgdev->enroll_stage = 0;
dev->priv = imgdev;
dev->nr_enroll_stages = IMG_ENROLL_STAGES; dev->nr_enroll_stages = IMG_ENROLL_STAGES;
/* for consistency in driver code, allow udev access through imgdev */
imgdev->udev = dev->udev;
if (imgdrv->open) { if (imgdrv->open) {
r = imgdrv->open(imgdev, driver_data); r = imgdrv->open(imgdev, driver_data);
if (r) if (r)
@@ -123,45 +55,32 @@ 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(FP_DEV(imgdev), status); fpi_drvcb_open_complete(imgdev->dev, 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(dev->img_dev); imgdrv->close(imgdev);
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(FP_DEV(imgdev)); fpi_drvcb_close_complete(imgdev->dev);
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 = FP_DEV(imgdev)->drv; struct fp_driver *drv = imgdev->dev->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)
@@ -173,7 +92,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 = FP_DEV(imgdev)->drv; struct fp_driver *drv = imgdev->dev->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;
@@ -199,14 +118,6 @@ 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)
{ {
@@ -239,7 +150,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(FP_DEV(imgdev), r, fpi_drvcb_enroll_stage_completed(imgdev->dev, 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
@@ -252,18 +163,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(FP_DEV(imgdev), r, img); fpi_drvcb_report_verify_result(imgdev->dev, 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(FP_DEV(imgdev), r, fpi_drvcb_report_identify_result(imgdev->dev, 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(FP_DEV(imgdev), r, img); fpi_drvcb_report_capture_result(imgdev->dev, r, img);
imgdev->action_result = 0; imgdev->action_result = 0;
break; break;
default: default:
@@ -274,14 +185,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(FP_DEV(imgdev)->drv); struct fp_img_driver *imgdrv = fpi_driver_to_img_driver(imgdev->dev->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(FP_DEV(imgdev)->verify_data, r = fpi_img_compare_print_data(imgdev->dev->verify_data,
imgdev->acquire_data); imgdev->acquire_data);
if (r >= match_score) if (r >= match_score)
@@ -294,7 +205,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(FP_DEV(imgdev)->drv); struct fp_img_driver *imgdrv = fpi_driver_to_img_driver(imgdev->dev->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;
@@ -303,20 +214,12 @@ 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,
FP_DEV(imgdev)->identify_gallery, match_score, &match_offset); imgdev->dev->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;
@@ -324,16 +227,9 @@ 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 = NULL; struct fp_print_data *print;
int r; int r;
G_DEBUG_HERE(); G_DEBUG_HERE();
@@ -376,7 +272,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(FP_DEV(imgdev)); imgdev->enroll_data = fpi_print_data_new(imgdev->dev);
} }
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 */
@@ -387,7 +283,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 == FP_DEV(imgdev)->nr_enroll_stages) if (imgdev->enroll_stage == imgdev->dev->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;
@@ -411,29 +307,22 @@ 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(FP_DEV(imgdev), error, NULL, NULL); fpi_drvcb_enroll_stage_completed(imgdev->dev, error, NULL, NULL);
break; break;
case IMG_ACTION_VERIFY: case IMG_ACTION_VERIFY:
fpi_drvcb_report_verify_result(FP_DEV(imgdev), error, NULL); fpi_drvcb_report_verify_result(imgdev->dev, error, NULL);
break; break;
case IMG_ACTION_IDENTIFY: case IMG_ACTION_IDENTIFY:
fpi_drvcb_report_identify_result(FP_DEV(imgdev), error, 0, NULL); fpi_drvcb_report_identify_result(imgdev->dev, error, 0, NULL);
break; break;
case IMG_ACTION_CAPTURE: case IMG_ACTION_CAPTURE:
fpi_drvcb_report_capture_result(FP_DEV(imgdev), error, NULL); fpi_drvcb_report_capture_result(imgdev->dev, error, NULL);
break; break;
default: default:
fp_err("unhandled action %d", imgdev->action); fp_err("unhandled action %d", imgdev->action);
@@ -441,30 +330,22 @@ 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(FP_DEV(imgdev), status); fpi_drvcb_enroll_started(imgdev->dev, status);
break; break;
case IMG_ACTION_VERIFY: case IMG_ACTION_VERIFY:
fpi_drvcb_verify_started(FP_DEV(imgdev), status); fpi_drvcb_verify_started(imgdev->dev, status);
break; break;
case IMG_ACTION_IDENTIFY: case IMG_ACTION_IDENTIFY:
fpi_drvcb_identify_started(FP_DEV(imgdev), status); fpi_drvcb_identify_started(imgdev->dev, status);
break; break;
case IMG_ACTION_CAPTURE: case IMG_ACTION_CAPTURE:
fpi_drvcb_capture_started(FP_DEV(imgdev), status); fpi_drvcb_capture_started(imgdev->dev, status);
break; break;
default: default:
fp_err("unhandled action %d", imgdev->action); fp_err("unhandled action %d", imgdev->action);
@@ -477,44 +358,35 @@ 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)
{ {
enum fp_imgdev_action action;
G_DEBUG_HERE(); G_DEBUG_HERE();
action = imgdev->action; switch (imgdev->action) {
imgdev->action = IMG_ACTION_NONE;
imgdev->action_state = 0;
switch (action) {
case IMG_ACTION_ENROLL: case IMG_ACTION_ENROLL:
fpi_drvcb_enroll_stopped(FP_DEV(imgdev)); fpi_drvcb_enroll_stopped(imgdev->dev);
break; break;
case IMG_ACTION_VERIFY: case IMG_ACTION_VERIFY:
fpi_drvcb_verify_stopped(FP_DEV(imgdev)); fpi_drvcb_verify_stopped(imgdev->dev);
break; break;
case IMG_ACTION_IDENTIFY: case IMG_ACTION_IDENTIFY:
fpi_drvcb_identify_stopped(FP_DEV(imgdev)); fpi_drvcb_identify_stopped(imgdev->dev);
break; break;
case IMG_ACTION_CAPTURE: case IMG_ACTION_CAPTURE:
fpi_drvcb_capture_stopped(FP_DEV(imgdev)); fpi_drvcb_capture_stopped(imgdev->dev);
break; break;
default: default:
fp_err("unhandled action %d", imgdev->action); fp_err("unhandled action %d", imgdev->action);
break; break;
} }
imgdev->action = IMG_ACTION_NONE;
imgdev->action_state = 0;
} }
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 = FP_DEV(imgdev)->drv; struct fp_driver *drv = imgdev->dev->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;
@@ -526,7 +398,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 = FP_DEV(imgdev)->drv; struct fp_driver *drv = imgdev->dev->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;
@@ -536,19 +408,19 @@ int fpi_imgdev_get_img_height(struct fp_img_dev *imgdev)
return height; return height;
} }
static int dev_activate(struct fp_img_dev *imgdev) static int dev_activate(struct fp_img_dev *imgdev, enum fp_imgdev_state state)
{ {
struct fp_driver *drv = FP_DEV(imgdev)->drv; struct fp_driver *drv = imgdev->dev->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)
return 0; return 0;
return imgdrv->activate(imgdev); return imgdrv->activate(imgdev, state);
} }
static void dev_deactivate(struct fp_img_dev *imgdev) static void dev_deactivate(struct fp_img_dev *imgdev)
{ {
struct fp_driver *drv = FP_DEV(imgdev)->drv; struct fp_driver *drv = imgdev->dev->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)
@@ -558,14 +430,14 @@ 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->img_dev; struct fp_img_dev *imgdev = dev->priv;
int r; int r;
fp_dbg("action %d", action); fp_dbg("action %d", action);
imgdev->action = action; imgdev->action = action;
imgdev->action_state = IMG_ACQUIRE_STATE_ACTIVATING; imgdev->action_state = IMG_ACQUIRE_STATE_ACTIVATING;
imgdev->enroll_stage = 0; imgdev->enroll_stage = 0;
r = dev_activate(imgdev); r = dev_activate(imgdev, IMGDEV_STATE_AWAIT_FINGER_ON);
if (r < 0) if (r < 0)
fp_err("activation failed with error %d", r); fp_err("activation failed with error %d", r);
@@ -612,7 +484,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->img_dev; struct fp_img_dev *imgdev = dev->priv;
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;
@@ -620,7 +492,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->img_dev; struct fp_img_dev *imgdev = dev->priv;
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;
@@ -628,7 +500,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->img_dev; struct fp_img_dev *imgdev = dev->priv;
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;
@@ -637,7 +509,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->img_dev; struct fp_img_dev *imgdev = dev->priv;
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;

View File

@@ -1,18 +1,27 @@
libfprint_sources = [ libfprint_sources = [
'fpi-async.c', 'fp_internal.h',
'fpi-assembling.c', 'drivers_api.h',
'fpi-core.c', 'async.c',
'fpi-data.c', 'core.c',
'fpi-dev.c', 'data.c',
'fpi-dev-img.c', 'drv.c',
'fpi-img.c', 'img.c',
'fpi-ssm.c', 'imgdev.c',
'fpi-sync.c', 'poll.c',
'fpi-poll.c', 'sync.c',
'fpi-usb.c', 'assembling.c',
'assembling.h',
'drivers/driver_ids.h',
] ]
nbis_sources = [ nbis_sources = [
'nbis/include/bozorth.h',
'nbis/include/bz_array.h',
'nbis/include/defs.h',
'nbis/include/lfs.h',
'nbis/include/log.h',
'nbis/include/morph.h',
'nbis/include/sunrast.h',
'nbis/bozorth3/bozorth3.c', 'nbis/bozorth3/bozorth3.c',
'nbis/bozorth3/bz_alloc.c', 'nbis/bozorth3/bz_alloc.c',
'nbis/bozorth3/bz_drvrs.c', 'nbis/bozorth3/bz_drvrs.c',
@@ -21,17 +30,14 @@ 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',
@@ -44,7 +50,6 @@ 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
@@ -54,13 +59,13 @@ drivers_sources = []
drivers_cflags = [] drivers_cflags = []
foreach driver: drivers foreach driver: drivers
if driver == 'upekts' if driver == 'upekts'
drivers_sources += [ 'drivers/upekts.c', 'drivers/upek_proto.c' ] drivers_sources += [ 'drivers/upekts.c' ]
endif endif
if driver == 'upektc' if driver == 'upektc'
drivers_sources += [ 'drivers/upektc.c' ] drivers_sources += [ 'drivers/upektc.c', 'drivers/upektc.h' ]
endif endif
if driver == 'upeksonly' if driver == 'upeksonly'
drivers_sources += [ 'drivers/upeksonly.c' ] drivers_sources += [ 'drivers/upeksonly.c', 'drivers/upeksonly.h' ]
endif endif
if driver == 'uru4000' if driver == 'uru4000'
drivers_sources += [ 'drivers/uru4000.c' ] drivers_sources += [ 'drivers/uru4000.c' ]
@@ -70,20 +75,20 @@ foreach driver: drivers
aeslib = true aeslib = true
endif endif
if driver == 'aes1660' if driver == 'aes1660'
drivers_sources += [ 'drivers/aes1660.c' ] drivers_sources += [ 'drivers/aes1660.c', 'drivers/aes1660.h' ]
aeslib = true aeslib = true
aesx660 = true aesx660 = true
endif endif
if driver == 'aes2501' if driver == 'aes2501'
drivers_sources += [ 'drivers/aes2501.c' ] drivers_sources += [ 'drivers/aes2501.c', 'drivers/aes2501.h' ]
aeslib = true aeslib = true
endif endif
if driver == 'aes2550' if driver == 'aes2550'
drivers_sources += [ 'drivers/aes2550.c' ] drivers_sources += [ 'drivers/aes2550.c', 'drivers/aes2550.h' ]
aeslib = true aeslib = true
endif endif
if driver == 'aes2660' if driver == 'aes2660'
drivers_sources += [ 'drivers/aes2660.c' ] drivers_sources += [ 'drivers/aes2660.c', 'drivers/aes2660.h' ]
aeslib = true aeslib = true
aesx660 = true aesx660 = true
endif endif
@@ -97,6 +102,9 @@ foreach driver: drivers
aeslib = true aeslib = true
aes3k = true aes3k = true
endif endif
if driver == 'fdu2000'
drivers_sources += [ 'drivers/fdu2000.c' ]
endif
if driver == 'vcom5s' if driver == 'vcom5s'
drivers_sources += [ 'drivers/vcom5s.c' ] drivers_sources += [ 'drivers/vcom5s.c' ]
endif endif
@@ -104,38 +112,38 @@ foreach driver: drivers
drivers_sources += [ 'drivers/vfs101.c' ] drivers_sources += [ 'drivers/vfs101.c' ]
endif endif
if driver == 'vfs301' if driver == 'vfs301'
drivers_sources += [ 'drivers/vfs301.c', 'drivers/vfs301_proto.c' ] drivers_sources += [ 'drivers/vfs301.c', 'drivers/vfs301_proto.c', 'drivers/vfs301_proto.h', 'drivers/vfs301_proto_fragments.h' ]
endif endif
if driver == 'vfs5011' if driver == 'vfs5011'
drivers_sources += [ 'drivers/vfs5011.c' ] 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/upek_proto.c' ] drivers_sources += [ 'drivers/upektc_img.c', 'drivers/upektc_img.h' ]
endif endif
if driver == 'etes603' if driver == 'etes603'
drivers_sources += [ 'drivers/etes603.c' ] drivers_sources += [ 'drivers/etes603.c' ]
endif endif
if driver == 'vfs0050' if driver == 'vfs0050'
drivers_sources += [ 'drivers/vfs0050.c' ] drivers_sources += [ 'drivers/vfs0050.c', 'drivers/vfs0050.h' ]
endif endif
if driver == 'elan' if driver == 'elan'
drivers_sources += [ 'drivers/elan.c' ] drivers_sources += [ 'drivers/elan.c', 'drivers/elan.h' ]
endif endif
endforeach endforeach
if aeslib if aeslib
drivers_sources += [ 'drivers/aeslib.c' ] drivers_sources += [ 'aeslib.c', 'aeslib.h' ]
endif endif
if aesx660 if aesx660
drivers_sources += ['drivers/aesx660.c' ] drivers_sources += ['drivers/aesx660.c', 'drivers/aesx660.h' ]
endif endif
if aes3k if aes3k
drivers_sources += ['drivers/aes3k.c' ] drivers_sources += ['drivers/aes3k.c', 'drivers/aes3k.h' ]
endif endif
other_sources = [] other_sources = []
if imaging_dep.found() if imaging_dep.found()
other_sources += [ 'fpi-img-pixman.c' ] other_sources += [ 'pixman.c' ]
endif endif
libfprint_sources += configure_file(input: 'empty_file', libfprint_sources += configure_file(input: 'empty_file',

View File

@@ -1,33 +0,0 @@
/*
* 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,43 +1,51 @@
/******************************************************************************
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 and/or related materials was developed at the National Institute This software was developed at the National Institute of Standards and
of Standards and Technology (NIST) by employees of the Federal Government Technology (NIST) by employees of the Federal Government in the course
in the course of their official duties. Pursuant to title 17 Section 105 of their official duties. Pursuant to title 17 Section 105 of the
of the United States Code, this software is not subject to copyright United States Code, this software is not subject to copyright protection
protection and is in the public domain. and is in the public domain. NIST assumes no responsibility whatsoever for
its use by other parties, and makes no guarantees, expressed or implied,
about its quality, reliability, or any other characteristic.
This software and/or related materials have been determined to be not subject Disclaimer:
to the EAR (see Part 734.3 of the EAR for exact details) because it is This software was developed to promote biometric standards and biometric
a publicly available technology and software, and is freely distributed technology testing for the Federal Government in accordance with the USA
to any interested party with no licensing requirements. Therefore, it is PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act.
permissible to distribute this software as a free download from the internet. Specific hardware and software products identified in this software were used
in order to perform the software development. In no case does such
Disclaimer: identification imply recommendation or endorsement by the National Institute
This software and/or related materials was developed to promote biometric of Standards and Technology, nor does it imply that the products and equipment
standards and biometric technology testing for the Federal Government identified are necessarily the best available for the purpose.
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.
*******************************************************************************/ *******************************************************************************/
@@ -81,6 +89,9 @@ of the software.
#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 */
@@ -149,7 +160,7 @@ for ( k = 0; k < npoints - 1; k++ ) {
else { else {
double dz; double dz;
if ( 0 ) if ( m1_xyt )
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 );
@@ -250,7 +261,7 @@ for ( k = 0; k < npoints - 1; k++ ) {
if ( table_index == 19999 ) { if ( table_index == 19999 ) {
#ifndef NOVERBOSE #ifndef NOVERBOSE
if ( 0 ) if ( verbose_bozorth )
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;
@@ -381,7 +392,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 0; */ /* extern int verbose_bozorth; */
/* 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 ); */
@@ -390,7 +401,6 @@ 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];
@@ -560,7 +570,7 @@ for ( k = 1; k < probe_ptrlist_len; k++ ) {
if ( edge_pair_index == 19999 ) { if ( edge_pair_index == 19999 ) {
#ifndef NOVERBOSE #ifndef NOVERBOSE
if ( 0 ) if ( verbose_bozorth )
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
@@ -642,13 +652,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 ( 0 ) if ( verbose_bozorth )
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 ( 0 ) if ( verbose_bozorth )
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,
@@ -662,7 +672,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 ( 0 ) if ( verbose_bozorth )
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,
@@ -701,6 +711,7 @@ 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++ ) {
@@ -754,7 +765,7 @@ for ( k = 0; k < np - 1; k++ ) {
} }
#ifndef NOVERBOSE #ifndef NOVERBOSE
if ( 0 ) if ( verbose_bozorth )
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
@@ -816,6 +827,7 @@ for ( k = 0; k < np - 1; k++ ) {
l = 1;
t = np + 1; t = np + 1;
b = kq; b = kq;
@@ -1155,7 +1167,7 @@ for ( k = 0; k < np - 1; k++ ) {
if ( ll ) { if ( ll ) {
if ( 0 ) if ( m1_xyt )
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 );
@@ -1175,7 +1187,7 @@ for ( k = 0; k < np - 1; k++ ) {
jj += 360; jj += 360;
} else { } else {
if ( 0 ) { if ( m1_xyt ) {
if ( jj > 0 ) if ( jj > 0 )
jj = -90; jj = -90;
else else
@@ -1192,7 +1204,7 @@ for ( k = 0; k < np - 1; k++ ) {
if ( kk ) { if ( kk ) {
if ( 0 ) if ( m1_xyt )
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 );
@@ -1212,7 +1224,7 @@ for ( k = 0; k < np - 1; k++ ) {
j += 360; j += 360;
} else { } else {
if ( 0 ) { if ( m1_xyt ) {
if ( j > 0 ) if ( j > 0 )
j = -90; j = -90;
else else
@@ -1599,7 +1611,7 @@ if ( n ) {
notfound = 1; notfound = 1;
#ifndef NOVERBOSE #ifndef NOVERBOSE
if ( 0 ) { if ( verbose_bozorth ) {
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++ ) {
@@ -1645,7 +1657,7 @@ if ( t ) {
notfound = 1; notfound = 1;
#ifndef NOVERBOSE #ifndef NOVERBOSE
if ( 0 ) { if ( verbose_bozorth ) {
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,43 +1,51 @@
/******************************************************************************
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 and/or related materials was developed at the National Institute This software was developed at the National Institute of Standards and
of Standards and Technology (NIST) by employees of the Federal Government Technology (NIST) by employees of the Federal Government in the course
in the course of their official duties. Pursuant to title 17 Section 105 of their official duties. Pursuant to title 17 Section 105 of the
of the United States Code, this software is not subject to copyright United States Code, this software is not subject to copyright protection
protection and is in the public domain. and is in the public domain. NIST assumes no responsibility whatsoever for
its use by other parties, and makes no guarantees, expressed or implied,
about its quality, reliability, or any other characteristic.
This software and/or related materials have been determined to be not subject Disclaimer:
to the EAR (see Part 734.3 of the EAR for exact details) because it is This software was developed to promote biometric standards and biometric
a publicly available technology and software, and is freely distributed technology testing for the Federal Government in accordance with the USA
to any interested party with no licensing requirements. Therefore, it is PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act.
permissible to distribute this software as a free download from the internet. Specific hardware and software products identified in this software were used
in order to perform the software development. In no case does such
Disclaimer: identification imply recommendation or endorsement by the National Institute
This software and/or related materials was developed to promote biometric of Standards and Technology, nor does it imply that the products and equipment
standards and biometric technology testing for the Federal Government identified are necessarily the best available for the purpose.
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.
*******************************************************************************/ *******************************************************************************/
@@ -69,6 +77,43 @@ of the software.
/***********************************************************************/ /***********************************************************************/
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,43 +1,51 @@
/******************************************************************************
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 and/or related materials was developed at the National Institute This software was developed at the National Institute of Standards and
of Standards and Technology (NIST) by employees of the Federal Government Technology (NIST) by employees of the Federal Government in the course
in the course of their official duties. Pursuant to title 17 Section 105 of their official duties. Pursuant to title 17 Section 105 of the
of the United States Code, this software is not subject to copyright United States Code, this software is not subject to copyright protection
protection and is in the public domain. and is in the public domain. NIST assumes no responsibility whatsoever for
its use by other parties, and makes no guarantees, expressed or implied,
about its quality, reliability, or any other characteristic.
This software and/or related materials have been determined to be not subject Disclaimer:
to the EAR (see Part 734.3 of the EAR for exact details) because it is This software was developed to promote biometric standards and biometric
a publicly available technology and software, and is freely distributed technology testing for the Federal Government in accordance with the USA
to any interested party with no licensing requirements. Therefore, it is PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act.
permissible to distribute this software as a free download from the internet. Specific hardware and software products identified in this software were used
in order to perform the software development. In no case does such
Disclaimer: identification imply recommendation or endorsement by the National Institute
This software and/or related materials was developed to promote biometric of Standards and Technology, nor does it imply that the products and equipment
standards and biometric technology testing for the Federal Government identified are necessarily the best available for the purpose.
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.
*******************************************************************************/ *******************************************************************************/
@@ -169,3 +177,47 @@ 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,43 +1,51 @@
/******************************************************************************
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 and/or related materials was developed at the National Institute This software was developed at the National Institute of Standards and
of Standards and Technology (NIST) by employees of the Federal Government Technology (NIST) by employees of the Federal Government in the course
in the course of their official duties. Pursuant to title 17 Section 105 of their official duties. Pursuant to title 17 Section 105 of the
of the United States Code, this software is not subject to copyright United States Code, this software is not subject to copyright protection
protection and is in the public domain. and is in the public domain. NIST assumes no responsibility whatsoever for
its use by other parties, and makes no guarantees, expressed or implied,
about its quality, reliability, or any other characteristic.
This software and/or related materials have been determined to be not subject Disclaimer:
to the EAR (see Part 734.3 of the EAR for exact details) because it is This software was developed to promote biometric standards and biometric
a publicly available technology and software, and is freely distributed technology testing for the Federal Government in accordance with the USA
to any interested party with no licensing requirements. Therefore, it is PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act.
permissible to distribute this software as a free download from the internet. Specific hardware and software products identified in this software were used
in order to perform the software development. In no case does such
Disclaimer: identification imply recommendation or endorsement by the National Institute
This software and/or related materials was developed to promote biometric of Standards and Technology, nor does it imply that the products and equipment
standards and biometric technology testing for the Federal Government identified are necessarily the best available for the purpose.
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.
*******************************************************************************/ *******************************************************************************/
@@ -83,45 +91,23 @@ int yl[ YL_SIZE_1 ][ YL_SIZE_2 ];
/**************************************************************************/ /**************************************************************************/
/* Globals used significantly by sift() */ /* Globals used significantly by sift() */
/**************************************************************************/ /**************************************************************************/
#ifdef TARGET_OS int rq[ RQ_SIZE ] = {};
int rq[ RQ_SIZE ]; int tq[ TQ_SIZE ] = {};
int tq[ TQ_SIZE ]; int zz[ ZZ_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,43 +1,51 @@
/******************************************************************************
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 and/or related materials was developed at the National Institute This software was developed at the National Institute of Standards and
of Standards and Technology (NIST) by employees of the Federal Government Technology (NIST) by employees of the Federal Government in the course
in the course of their official duties. Pursuant to title 17 Section 105 of their official duties. Pursuant to title 17 Section 105 of the
of the United States Code, this software is not subject to copyright United States Code, this software is not subject to copyright protection
protection and is in the public domain. and is in the public domain. NIST assumes no responsibility whatsoever for
its use by other parties, and makes no guarantees, expressed or implied,
about its quality, reliability, or any other characteristic.
This software and/or related materials have been determined to be not subject Disclaimer:
to the EAR (see Part 734.3 of the EAR for exact details) because it is This software was developed to promote biometric standards and biometric
a publicly available technology and software, and is freely distributed technology testing for the Federal Government in accordance with the USA
to any interested party with no licensing requirements. Therefore, it is PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act.
permissible to distribute this software as a free download from the internet. Specific hardware and software products identified in this software were used
in order to perform the software development. In no case does such
Disclaimer: identification imply recommendation or endorsement by the National Institute
This software and/or related materials was developed to promote biometric of Standards and Technology, nor does it imply that the products and equipment
standards and biometric technology testing for the Federal Government identified are necessarily the best available for the purpose.
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.
*******************************************************************************/ *******************************************************************************/
@@ -49,9 +57,6 @@ of the software.
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
@@ -95,7 +100,50 @@ of the software.
#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;
}
/***********************************************************************/ /***********************************************************************/
@@ -105,10 +153,25 @@ 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 )
@@ -129,15 +192,171 @@ 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
@@ -145,14 +364,241 @@ 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 */
Load a XYTQ structure and return a XYT struct. /* extern FILE * stderr; */
Row 3's value is an angle which is normalized to the interval (-180,180].
A maximum of MAX_BOZORTH_MINUTIAE minutiae can be returned -- fewer if
"DEFAULT_BOZORTH_MINUTIAE" is smaller. If the file contains more minutiae than are
to be returned, the highest-quality minutiae are returned. #define C1 0
*************************************************************************/ #define C2 1
fp = fopen( xyt_file, "r" );
if ( fp == (FILE *) NULL ) {
fprintf( stderr, "%s: ERROR: fopen() of minutiae file \"%s\" failed: %s\n",
get_progname(), xyt_file, strerror(errno) );
return XYT_NULL;
}
nminutiae = 0;
nargs_expected = 0;
while ( fgets( xyt_line, sizeof xyt_line, fp ) != CNULL ) {
m = sscanf( xyt_line, "%d %d %d %d",
&xvals_lng[nminutiae],
&yvals_lng[nminutiae],
&tvals_lng[nminutiae],
&qvals_lng[nminutiae] );
if ( nminutiae == 0 ) {
if ( m != 3 && m != 4 ) {
fprintf( stderr, "%s: ERROR: sscanf() failed on line %u in minutiae file \"%s\"\n",
get_progname(), nminutiae+1, xyt_file );
return XYT_NULL;
}
nargs_expected = m;
} else {
if ( m != nargs_expected ) {
fprintf( stderr, "%s: ERROR: inconsistent argument count on line %u of minutiae file \"%s\"\n",
get_progname(), nminutiae+1, xyt_file );
return XYT_NULL;
}
}
if ( m == 3 )
qvals_lng[nminutiae] = 1;
if ( tvals_lng[nminutiae] > 180 )
tvals_lng[nminutiae] -= 360;
/*
if ( C1 ) {
c[nminutiae].col[0] = xvals_lng[nminutiae];
c[nminutiae].col[1] = yvals_lng[nminutiae];
c[nminutiae].col[2] = tvals_lng[nminutiae];
c[nminutiae].col[3] = qvals_lng[nminutiae];
}
*/
++nminutiae;
if ( nminutiae == MAX_FILE_MINUTIAE )
break;
}
if ( fclose(fp) != 0 ) {
fprintf( stderr, "%s: ERROR: fclose() of minutiae file \"%s\" failed: %s\n",
get_progname(), xyt_file, strerror(errno) );
return XYT_NULL;
}
if ( nminutiae > DEFAULT_BOZORTH_MINUTIAE ) {
if ( verbose_load )
fprintf( stderr, "%s: WARNING: bz_load(): trimming minutiae to the %d of highest quality\n",
get_progname(), DEFAULT_BOZORTH_MINUTIAE );
if ( verbose_load )
fprintf( stderr, "Before quality sort:\n" );
if ( sort_order_decreasing( qvals_lng, nminutiae, order )) {
fprintf( stderr, "%s: ERROR: sort failed and returned on error\n", get_progname());
return XYT_NULL;
}
for ( j = 0; j < nminutiae; j++ ) {
if ( verbose_load )
fprintf( stderr, " %3d: %3d %3d %3d ---> order = %3d\n",
j, xvals_lng[j], yvals_lng[j], qvals_lng[j], order[j] );
if ( j == 0 )
continue;
if ( qvals_lng[order[j]] > qvals_lng[order[j-1]] ) {
fprintf( stderr, "%s: ERROR: sort failed: j=%d; qvals_lng[%d] > qvals_lng[%d]\n",
get_progname(), j, order[j], order[j-1] );
return XYT_NULL;
}
}
if ( verbose_load )
fprintf( stderr, "\nAfter quality sort:\n" );
for ( j = 0; j < DEFAULT_BOZORTH_MINUTIAE; j++ ) {
xvals[j] = xvals_lng[order[j]];
yvals[j] = yvals_lng[order[j]];
tvals[j] = tvals_lng[order[j]];
qvals[j] = qvals_lng[order[j]];
if ( verbose_load )
fprintf( stderr, " %3d: %3d %3d %3d\n", j, xvals[j], yvals[j], qvals[j] );
}
if ( C1 ) {
if ( verbose_load )
fprintf( stderr, "\nAfter qsort():\n" );
qsort( (void *) &c, (size_t) nminutiae, sizeof(struct minutiae_struct), sort_quality_decreasing );
for ( j = 0; j < nminutiae; j++ ) {
if ( verbose_load )
fprintf( stderr, "Q %3d: %3d %3d %3d\n",
j, c[j].col[0], c[j].col[1], c[j].col[3] );
if ( j > 0 && c[j].col[3] > c[j-1].col[3] ) {
fprintf( stderr, "%s: ERROR: sort failed: c[%d].col[3] > c[%d].col[3]\n",
get_progname(), j, j-1 );
return XYT_NULL;
}
}
}
if ( verbose_load )
fprintf( stderr, "\n" );
xptr = xvals;
yptr = yvals;
tptr = tvals;
qptr = qvals;
nminutiae = DEFAULT_BOZORTH_MINUTIAE;
} else{
xptr = xvals_lng;
yptr = yvals_lng;
tptr = tvals_lng;
qptr = qvals_lng;
}
for ( j=0; j < nminutiae; j++ ) {
c[j].col[0] = xptr[j];
c[j].col[1] = yptr[j];
c[j].col[2] = tptr[j];
c[j].col[3] = qptr[j];
}
qsort( (void *) &c, (size_t) nminutiae, sizeof(struct minutiae_struct), sort_x_y );
if ( verbose_load ) {
fprintf( stderr, "\nSorted on increasing x, then increasing y\n" );
for ( j = 0; j < nminutiae; j++ ) {
fprintf( stderr, "%d : %3d, %3d, %3d, %3d\n", j, c[j].col[0], c[j].col[1], c[j].col[2], c[j].col[3] );
if ( j > 0 ) {
if ( c[j].col[0] < c[j-1].col[0] ) {
fprintf( stderr, "%s: ERROR: sort failed: c[%d].col[0]=%d > c[%d].col[0]=%d\n",
get_progname(),
j, c[j].col[0], j-1, c[j-1].col[0]
);
return XYT_NULL;
}
if ( c[j].col[0] == c[j-1].col[0] && c[j].col[1] < c[j-1].col[1] ) {
fprintf( stderr, "%s: ERROR: sort failed: c[%d].col[0]=%d == c[%d].col[0]=%d; c[%d].col[0]=%d == c[%d].col[0]=%d\n",
get_progname(),
j, c[j].col[0], j-1, c[j-1].col[0],
j, c[j].col[1], j-1, c[j-1].col[1]
);
return XYT_NULL;
}
}
}
}
s = (struct xyt_struct *) malloc( sizeof( struct xyt_struct ) );
if ( s == XYT_NULL ) {
fprintf( stderr, "%s: ERROR: malloc() failure while loading minutiae file \"%s\" failed: %s\n",
get_progname(),
xyt_file,
strerror(errno)
);
return XYT_NULL;
}
for ( j = 0; j < nminutiae; j++ ) {
s->xcol[j] = c[j].col[0];
s->ycol[j] = c[j].col[1];
s->thetacol[j] = c[j].col[2];
}
s->nrows = nminutiae;
if ( verbose_load )
fprintf( stderr, "Loaded %s\n", xyt_file );
return s;
}
/***********************************************************************/ /***********************************************************************/
#ifdef PARALLEL_SEARCH #ifdef PARALLEL_SEARCH
@@ -171,13 +617,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" ); */

View File

@@ -1,43 +1,51 @@
/******************************************************************************
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 and/or related materials was developed at the National Institute This software was developed at the National Institute of Standards and
of Standards and Technology (NIST) by employees of the Federal Government Technology (NIST) by employees of the Federal Government in the course
in the course of their official duties. Pursuant to title 17 Section 105 of their official duties. Pursuant to title 17 Section 105 of the
of the United States Code, this software is not subject to copyright United States Code, this software is not subject to copyright protection
protection and is in the public domain. and is in the public domain. NIST assumes no responsibility whatsoever for
its use by other parties, and makes no guarantees, expressed or implied,
about its quality, reliability, or any other characteristic.
This software and/or related materials have been determined to be not subject Disclaimer:
to the EAR (see Part 734.3 of the EAR for exact details) because it is This software was developed to promote biometric standards and biometric
a publicly available technology and software, and is freely distributed technology testing for the Federal Government in accordance with the USA
to any interested party with no licensing requirements. Therefore, it is PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act.
permissible to distribute this software as a free download from the internet. Specific hardware and software products identified in this software were used
in order to perform the software development. In no case does such
Disclaimer: identification imply recommendation or endorsement by the National Institute
This software and/or related materials was developed to promote biometric of Standards and Technology, nor does it imply that the products and equipment
standards and biometric technology testing for the Federal Government identified are necessarily the best available for the purpose.
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.
*******************************************************************************/ *******************************************************************************/
@@ -70,10 +78,23 @@ of the software.
#include <bozorth.h> #include <bozorth.h>
/* These are now externally defined in bozorth.h */ /* These are now externally defined in bozorth.h */
/* extern FILE * stderr; */
/* extern char * get_progname( void ); */ /* extern char * get_progname( void ); */
/***********************************************************************/ /***********************************************************************/
int sort_quality_decreasing( const void * a, const void * b )
{
struct minutiae_struct * af;
struct minutiae_struct * bf;
af = (struct minutiae_struct *) a;
bf = (struct minutiae_struct *) b;
if ( af->col[3] > bf->col[3] )
return -1;
if ( af->col[3] < bf->col[3] )
return 1;
return 0;
}
/***********************************************************************/ /***********************************************************************/
int sort_x_y( const void * a, const void * b ) int sort_x_y( const void * a, const void * b )
@@ -103,18 +124,67 @@ qsort_decreasing() - quicksort an array of integers in decreasing
and Ted Zwiesler, 1986] and Ted Zwiesler, 1986]
********************************************************/ ********************************************************/
/* Used by custom quicksort code below */ /* Used by custom quicksort code below */
static int stack[BZ_STACKSIZE];
static int * stack_pointer = stack;
/***********************************************************************/ /***********************************************************************/
/* return values: 0 == successful, 1 == error */ /* return values: 0 == successful, 1 == error */
static int popstack( int *popval )
{
if ( --stack_pointer < stack ) {
fprintf( stderr, "%s: ERROR: popstack(): stack underflow\n", get_progname() );
return 1;
}
*popval = *stack_pointer;
return 0;
}
/***********************************************************************/ /***********************************************************************/
/* return values: 0 == successful, 1 == error */ /* return values: 0 == successful, 1 == error */
static int pushstack( int position )
{
*stack_pointer++ = position;
if ( stack_pointer > ( stack + BZ_STACKSIZE ) ) {
fprintf( stderr, "%s: ERROR: pushstack(): stack overflow\n", get_progname() );
return 1;
}
return 0;
}
/***********************************************************************/ /***********************************************************************/
/******************************************************************* /*******************************************************************
select_pivot() select_pivot()
selects a pivot from a list being sorted using the Singleton Method. selects a pivot from a list being sorted using the Singleton Method.
*******************************************************************/ *******************************************************************/
static int select_pivot( struct cell v[], int left, int right )
{
int midpoint;
midpoint = ( left + right ) / 2;
if ( v[left].index <= v[midpoint].index ) {
if ( v[midpoint].index <= v[right].index ) {
return midpoint;
} else {
if ( v[right].index > v[left].index ) {
return right;
} else {
return left;
}
}
} else {
if ( v[left].index < v[right].index ) {
return left;
} else {
if ( v[right].index < v[midpoint].index ) {
return midpoint;
} else {
return right;
}
}
}
}
/***********************************************************************/ /***********************************************************************/
/******************************************************** /********************************************************
@@ -122,6 +192,41 @@ partition_dec()
Inputs a pivot element making comparisons and swaps with other elements in a list, Inputs a pivot element making comparisons and swaps with other elements in a list,
until pivot resides at its correct position in the list. until pivot resides at its correct position in the list.
********************************************************/ ********************************************************/
static void partition_dec( struct cell v[], int *llen, int *rlen, int *ll, int *lr, int *rl, int *rr, int p, int l, int r )
{
#define iswap(a,b) { int itmp = (a); a = (b); b = itmp; }
*ll = l;
*rr = r;
while ( 1 ) {
if ( l < p ) {
if ( v[l].index < v[p].index ) {
iswap( v[l].index, v[p].index )
iswap( v[l].item, v[p].item )
p = l;
} else {
l++;
}
} else {
if ( r > p ) {
if ( v[r].index > v[p].index ) {
iswap( v[r].index, v[p].index )
iswap( v[r].item, v[p].item )
p = r;
l++;
} else {
r--;
}
} else {
*lr = p - 1;
*rl = p + 1;
*llen = *lr - *ll + 1;
*rlen = *rr - *rl + 1;
break;
}
}
}
}
/***********************************************************************/ /***********************************************************************/
/******************************************************** /********************************************************
@@ -131,6 +236,80 @@ sorted, a left subscript pointing to where the sort is to begin in the index ar
subscript where to end. This module invokes a decreasing quick-sort sorting the index array from l to r. subscript where to end. This module invokes a decreasing quick-sort sorting the index array from l to r.
********************************************************/ ********************************************************/
/* return values: 0 == successful, 1 == error */ /* return values: 0 == successful, 1 == error */
static int qsort_decreasing( struct cell v[], int left, int right )
{
int pivot;
int llen, rlen;
int lleft, lright, rleft, rright;
if ( pushstack( left ))
return 1;
if ( pushstack( right ))
return 2;
while ( stack_pointer != stack ) {
if (popstack(&right))
return 3;
if (popstack(&left ))
return 4;
if ( right - left > 0 ) {
pivot = select_pivot( v, left, right );
partition_dec( v, &llen, &rlen, &lleft, &lright, &rleft, &rright, pivot, left, right );
if ( llen > rlen ) {
if ( pushstack( lleft ))
return 5;
if ( pushstack( lright ))
return 6;
if ( pushstack( rleft ))
return 7;
if ( pushstack( rright ))
return 8;
} else{
if ( pushstack( rleft ))
return 9;
if ( pushstack( rright ))
return 10;
if ( pushstack( lleft ))
return 11;
if ( pushstack( lright ))
return 12;
}
}
}
return 0;
}
/***********************************************************************/ /***********************************************************************/
/* return values: 0 == successful, 1 == error */ /* return values: 0 == successful, 1 == error */
int sort_order_decreasing(
int values[], /* INPUT: the unsorted values themselves */
int num, /* INPUT: the number of values */
int order[] /* OUTPUT: the order for each of the values if sorted */
)
{
int i;
struct cell * cells;
cells = (struct cell *) malloc( num * sizeof(struct cell) );
if ( cells == (struct cell *) NULL ){
fprintf( stderr, "%s: ERROR: malloc(): struct cell\n", get_progname() );
return 1;
}
for( i = 0; i < num; i++ ) {
cells[i].index = values[i];
cells[i].item = i;
}
if ( qsort_decreasing( cells, 0, num-1 ) < 0)
return 2;
for( i = 0; i < num; i++ ) {
order[i] = cells[i].item;
}
free( (void *) cells );
return 0;
}

View File

@@ -1,43 +1,23 @@
/******************************************************************************* /*******************************************************************************
License: License:
This software and/or related materials was developed at the National Institute This software was developed at the National Institute of Standards and
of Standards and Technology (NIST) by employees of the Federal Government Technology (NIST) by employees of the Federal Government in the course
in the course of their official duties. Pursuant to title 17 Section 105 of their official duties. Pursuant to title 17 Section 105 of the
of the United States Code, this software is not subject to copyright United States Code, this software is not subject to copyright protection
protection and is in the public domain. and is in the public domain. NIST assumes no responsibility whatsoever for
its use by other parties, and makes no guarantees, expressed or implied,
about its quality, reliability, or any other characteristic.
This software and/or related materials have been determined to be not subject Disclaimer:
to the EAR (see Part 734.3 of the EAR for exact details) because it is This software was developed to promote biometric standards and biometric
a publicly available technology and software, and is freely distributed technology testing for the Federal Government in accordance with the USA
to any interested party with no licensing requirements. Therefore, it is PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act.
permissible to distribute this software as a free download from the internet. Specific hardware and software products identified in this software were used
in order to perform the software development. In no case does such
Disclaimer: identification imply recommendation or endorsement by the National Institute
This software and/or related materials was developed to promote biometric of Standards and Technology, nor does it imply that the products and equipment
standards and biometric technology testing for the Federal Government identified are necessarily the best available for the purpose.
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.
*******************************************************************************/ *******************************************************************************/
@@ -183,7 +163,7 @@ struct cell {
}; };
/**************************************************************************/ /**************************************************************************/
/* In BZ_IO : Supports the loading and manipulation of XYT and XYTQ data */ /* In BZ_IO : Supports the loading and manipulation of XYT data */
/**************************************************************************/ /**************************************************************************/
#define MAX_FILE_MINUTIAE 1000 /* bz_load() */ #define MAX_FILE_MINUTIAE 1000 /* bz_load() */
@@ -194,17 +174,7 @@ struct xyt_struct {
int thetacol[ MAX_BOZORTH_MINUTIAE ]; int thetacol[ MAX_BOZORTH_MINUTIAE ];
}; };
struct xytq_struct {
int nrows;
int xcol[ MAX_FILE_MINUTIAE ];
int ycol[ MAX_FILE_MINUTIAE ];
int thetacol[ MAX_FILE_MINUTIAE ];
int qualitycol[ MAX_FILE_MINUTIAE ];
};
#define XYT_NULL ( (struct xyt_struct *) NULL ) /* bz_load() */ #define XYT_NULL ( (struct xyt_struct *) NULL ) /* bz_load() */
#define XYTQ_NULL ( (struct xytq_struct *) NULL ) /* bz_load() */
/**************************************************************************/ /**************************************************************************/
@@ -217,8 +187,6 @@ struct xytq_struct {
/**************************************************************************/ /**************************************************************************/
/* Globals supporting command line options */ /* Globals supporting command line options */
extern int verbose_threshold; extern int verbose_threshold;
/* Global supporting error reporting */
extern FILE *stderr;
/**************************************************************************/ /**************************************************************************/
/* In: BZ_GBLS.C */ /* In: BZ_GBLS.C */
@@ -279,7 +247,6 @@ extern char *get_next_file(char *, FILE *, FILE *, int *, int *, char *,
extern char *get_score_filename(const char *, const char *); extern char *get_score_filename(const char *, const char *);
extern char *get_score_line(const char *, const char *, int, int, const char *); extern char *get_score_line(const char *, const char *, int, int, const char *);
extern struct xyt_struct *bz_load(const char *); extern struct xyt_struct *bz_load(const char *);
extern struct xyt_struct *bz_prune(struct xytq_struct *, int);
extern int fd_readable(int); extern int fd_readable(int);
/* In: BZ_SORT.C */ /* In: BZ_SORT.C */
extern int sort_quality_decreasing(const void *, const void *); extern int sort_quality_decreasing(const void *, const void *);

View File

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

View File

@@ -1,43 +1,23 @@
/******************************************************************************* /*******************************************************************************
License: License:
This software and/or related materials was developed at the National Institute This software was developed at the National Institute of Standards and
of Standards and Technology (NIST) by employees of the Federal Government Technology (NIST) by employees of the Federal Government in the course
in the course of their official duties. Pursuant to title 17 Section 105 of their official duties. Pursuant to title 17 Section 105 of the
of the United States Code, this software is not subject to copyright United States Code, this software is not subject to copyright protection
protection and is in the public domain. and is in the public domain. NIST assumes no responsibility whatsoever for
its use by other parties, and makes no guarantees, expressed or implied,
about its quality, reliability, or any other characteristic.
This software and/or related materials have been determined to be not subject Disclaimer:
to the EAR (see Part 734.3 of the EAR for exact details) because it is This software was developed to promote biometric standards and biometric
a publicly available technology and software, and is freely distributed technology testing for the Federal Government in accordance with the USA
to any interested party with no licensing requirements. Therefore, it is PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act.
permissible to distribute this software as a free download from the internet. Specific hardware and software products identified in this software were used
in order to perform the software development. In no case does such
Disclaimer: identification imply recommendation or endorsement by the National Institute
This software and/or related materials was developed to promote biometric of Standards and Technology, nor does it imply that the products and equipment
standards and biometric technology testing for the Federal Government identified are necessarily the best available for the purpose.
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.
*******************************************************************************/ *******************************************************************************/
@@ -73,6 +53,7 @@ of the software.
#define min(a, b) ((a) < (b) ? (a) : (b)) #define min(a, b) ((a) < (b) ? (a) : (b))
#define sround(x) ((int) (((x)<0) ? (x)-0.5 : (x)+0.5)) #define sround(x) ((int) (((x)<0) ? (x)-0.5 : (x)+0.5))
#define sround_uint(x) ((unsigned int) (((x)<0) ? (x)-0.5 : (x)+0.5)) #define sround_uint(x) ((unsigned int) (((x)<0) ? (x)-0.5 : (x)+0.5))
#define xor(a, b) (!(a && b) && (a || b))
#define align_to_16(_v_) ((((_v_)+15)>>4)<<4) #define align_to_16(_v_) ((((_v_)+15)>>4)<<4)
#define align_to_32(_v_) ((((_v_)+31)>>5)<<5) #define align_to_32(_v_) ((((_v_)+31)>>5)<<5)
#ifndef CHUNKS #ifndef CHUNKS

View File

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

View File

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

View File

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

View File

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

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