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
129 changed files with 8733 additions and 11225 deletions

View File

@@ -1,64 +1,20 @@
image: fedora:rawhide
stages:
- build
- test
variables:
DEPENDENCIES: libusb1-devel glib2-devel nss-devel pixman-devel systemd meson gtk-doc
gcc gcc-c++ glibc-devel libX11-devel libXv-devel gtk3-devel flatpak-builder
BUNDLE: "org.freedesktop.libfprint.Demo.flatpak"
gcc gcc-c++ glibc-devel libX11-devel libXv-devel
.build_one_driver_template: &build_one_driver
script:
- dnf update -y --nogpgcheck && dnf install -y --nogpgcheck $DEPENDENCIES
# Build with a driver that doesn't need imaging, or nss
- meson -Ddrivers=elan . _build
- ninja -C _build
- rm -rf _build/
.build_template: &build
script:
- dnf update -y --nogpgcheck && dnf install -y --nogpgcheck $DEPENDENCIES
# And build with everything
- meson -Ddrivers=all . _build
- ninja -C _build
- ninja -C _build install
before_script:
- dnf update -y --nogpgcheck && dnf install -y --nogpgcheck $DEPENDENCIES
build:
stage: build
<<: *build_one_driver
<<: *build
script:
- meson . _build
- 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

31
NEWS
View File

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

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

View File

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

View File

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

View File

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

View File

@@ -2,8 +2,8 @@
examples = [ 'verify_live', 'enroll', 'verify', 'img_capture' ]
foreach example: examples
executable(example,
[example + '.c', 'storage.c'],
dependencies: [libfprint_dep, glib_dep],
example + '.c',
dependencies: libfprint_dep,
include_directories: [
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 "storage.h"
struct fp_dscv_dev *discover_device(struct fp_dscv_dev **discovered_devs)
{
struct fp_dscv_dev *ddev = discovered_devs[0];
@@ -119,8 +117,8 @@ int main(void)
printf("Opened device. Loading previously enrolled right index finger "
"data...\n");
data = print_data_load(dev, RIGHT_INDEX);
if (!data) {
r = fp_print_data_load(dev, RIGHT_INDEX, &data);
if (r != 0) {
fprintf(stderr, "Failed to load fingerprint, error %d\n", r);
fprintf(stderr, "Did you remember to enroll your right index finger "
"first?\n");

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

View File

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

View File

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

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

View File

@@ -33,7 +33,6 @@ GSList *opened_devices = NULL;
/**
* SECTION:discovery
* @title: Device discovery
* @short_description: Device discovery functions
*
* These functions allow you to scan the system for supported fingerprint
* scanning hardware. This is your starting point when integrating libfprint
@@ -48,7 +47,6 @@ GSList *opened_devices = NULL;
/**
* SECTION:drv
* @title: Driver operations
* @short_description: Driver operation functions
*
* Internally, libfprint is abstracted into various drivers to communicate
* with the different types of supported fingerprint readers. libfprint works
@@ -63,7 +61,6 @@ GSList *opened_devices = NULL;
/**
* SECTION:dev
* @title: Devices operations
* @short_description: Device operation functions
*
* In order to interact with fingerprint scanners, your software will
* interface primarily with libfprint's representation of devices, detailed
@@ -114,27 +111,6 @@ GSList *opened_devices = NULL;
* verification) on some devices which do not provide images.
*/
/**
* SECTION:fpi-core
* @title: Driver structures
* @short_description: Driver structures
*
* Driver structures need to be defined inside each driver in
* order for the core library to know what function to call, and the capabilities
* of the driver and the devices it supports.
*/
/**
* SECTION:fpi-core-img
* @title: Image driver structures
* @short_description: Image driver structures
*
* Image driver structures need to be defined inside each image driver in
* order for the core library to know what function to call, and the capabilities
* of the driver and the devices it supports. Its structure is based off the
* #fp_driver struct.
*/
static GSList *registered_drivers = NULL;
static void register_driver(struct fp_driver *drv)
@@ -270,12 +246,10 @@ static struct fp_dscv_dev *discover_dev(libusb_device *udev)
* fp_discover_devs:
*
* Scans the system and returns a list of discovered devices. This is your
* entry point into finding a fingerprint reader to operate. Note that %NULL
* is only returned on error. When there are no supported readers available,
* an empty list is returned instead.
* entry point into finding a fingerprint reader to operate.
*
* Returns: a nul-terminated list of discovered devices or %NULL on error.
* Must be freed with fp_dscv_devs_free() after use.
* Returns: a %NULL-terminated list of discovered devices. Must be freed with
* fp_dscv_devs_free() after use.
*/
API_EXPORTED struct fp_dscv_dev **fp_discover_devs(void)
{
@@ -285,7 +259,8 @@ API_EXPORTED struct fp_dscv_dev **fp_discover_devs(void)
int r;
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);
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)
{
g_return_val_if_fail(dev, NULL);
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:
* @dev: a discovered fingerprint device
*
* Returns a unique driver identifier for the underlying driver
* for that device.
*
* Returns: the ID for #dev
* Returns: the ID for the underlying driver for that device
*/
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));
}
@@ -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)
{
g_return_val_if_fail(dev, 0);
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,
struct fp_print_data *print)
{
g_return_val_if_fail(dev, 0);
g_return_val_if_fail(print, 0);
return fpi_print_data_compatible(dev->drv->id, dev->devtype,
fpi_driver_get_data_type(dev->drv), print->driver_id, print->devtype,
print->type);
@@ -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,
struct fp_dscv_print *print)
{
g_return_val_if_fail(dev, 0);
g_return_val_if_fail(print, 0);
return fpi_print_data_compatible(dev->drv->id, dev->devtype, 0,
print->driver_id, print->devtype, 0);
}
@@ -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;
int i;
g_return_val_if_fail(devs, NULL);
g_return_val_if_fail(print, NULL);
for (i = 0; (ddev = devs[i]); i++)
if (fp_dscv_dev_supports_print_data(ddev, print))
return ddev;
@@ -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;
int i;
g_return_val_if_fail(devs, NULL);
g_return_val_if_fail(print, NULL);
for (i = 0; (ddev = devs[i]); i++) {
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
@@ -500,7 +454,7 @@ API_EXPORTED struct fp_dscv_dev *fp_dscv_dev_for_dscv_print(struct fp_dscv_dev *
/**
* fp_dev_get_driver:
* @dev: the struct #fp_dev device
* @dev: the 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)
{
g_return_val_if_fail(dev, NULL);
return dev->drv;
}
/**
* 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
* 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)
{
g_return_val_if_fail(dev, 0);
return dev->nr_enroll_stages;
}
/**
* fp_dev_get_devtype:
* @dev: the struct #fp_dev device
* @dev: the 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)
{
g_return_val_if_fail(dev, 0);
return dev->devtype;
}
/**
* fp_dev_supports_print_data:
* @dev: the struct #fp_dev device
* @dev: the device
* @data: the stored print
*
* 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,
struct fp_print_data *data)
{
g_return_val_if_fail(dev, 0);
g_return_val_if_fail(data, 0);
return fpi_print_data_compatible(dev->drv->id, dev->devtype,
fpi_driver_get_data_type(dev->drv), data->driver_id, data->devtype,
data->type);
@@ -566,7 +511,7 @@ API_EXPORTED int fp_dev_supports_print_data(struct fp_dev *dev,
/**
* fp_dev_supports_dscv_print:
* @dev: the struct #fp_dev device
* @dev: the device
* @print: the discovered print
*
* 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,
struct fp_dscv_print *print)
{
g_return_val_if_fail(dev, 0);
g_return_val_if_fail(print, 0);
return fpi_print_data_compatible(dev->drv->id, dev->devtype,
0, print->driver_id, print->devtype, 0);
}
libusb_device_handle *
fpi_dev_get_usb_dev(struct fp_dev *dev)
{
return dev->udev;
}
void *
fpi_dev_get_user_data (struct fp_dev *dev)
{
return dev->priv;
}
void
fpi_dev_set_user_data (struct fp_dev *dev,
void *user_data)
{
dev->priv = user_data;
}
int
fpi_dev_get_nr_enroll_stages(struct fp_dev *dev)
{
return dev->nr_enroll_stages;
}
void
fpi_dev_set_nr_enroll_stages(struct fp_dev *dev,
int nr_enroll_stages)
{
dev->nr_enroll_stages = nr_enroll_stages;
}
struct fp_print_data *
fpi_dev_get_verify_data(struct fp_dev *dev)
{
return dev->verify_data;
}
enum fp_dev_state
fpi_dev_get_dev_state(struct fp_dev *dev)
{
return dev->state;
}
/**
* fp_driver_get_name:
* @drv: the driver
@@ -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)
{
g_return_val_if_fail(drv, NULL);
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)
{
g_return_val_if_fail(drv, NULL);
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)
{
g_return_val_if_fail(drv, 0);
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)
{
g_return_val_if_fail(drv, FP_SCAN_TYPE_PRESS);
return drv->scan_type;
}
/**
* 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)
static struct fp_img_dev *dev_to_img_dev(struct fp_dev *dev)
{
g_return_val_if_fail(drv, 0);
return drv->capture_start != NULL;
if (dev->drv->type != DRIVER_IMAGING)
return NULL;
return dev->priv;
}
/**
* 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
* 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)
{
g_return_val_if_fail(dev, 0);
return dev->drv->capture_start != NULL;
}
/**
* 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)
* 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)
{
g_return_val_if_fail(dev, 0);
return dev->drv->identify_start != NULL;
}
/**
* 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.
* 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)
{
g_return_val_if_fail(dev, -1);
if (!dev->img_dev) {
struct fp_img_dev *imgdev = dev_to_img_dev(dev);
if (!imgdev) {
fp_dbg("get image width for non-imaging device");
return -1;
}
return fpi_imgdev_get_img_width(dev->img_dev);
return fpi_imgdev_get_img_width(imgdev);
}
/**
* 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.
* 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)
{
g_return_val_if_fail(dev, -1);
if (!dev->img_dev) {
struct fp_img_dev *imgdev = dev_to_img_dev(dev);
if (!imgdev) {
fp_dbg("get image height for non-imaging device");
return -1;
}
return fpi_imgdev_get_img_height(dev->img_dev);
return fpi_imgdev_get_img_height(imgdev);
}
/**

View File

@@ -32,23 +32,9 @@
#define DIR_PERMS 0700
struct fpi_print_data_fp2 {
char prefix[3];
uint16_t driver_id;
uint32_t devtype;
unsigned char data_type;
unsigned char data[0];
} __attribute__((__packed__));
struct fpi_print_data_item_fp2 {
uint32_t length;
unsigned char data[0];
} __attribute__((__packed__));
/**
* SECTION: print_data
* @title: Stored prints
* @short_description: Stored prints functions
*
* Stored prints are represented by a structure named #fp_print_data.
* Stored prints are originally obtained from an enrollment function such as
@@ -56,25 +42,12 @@ struct fpi_print_data_item_fp2 {
*
* This page documents the various operations you can do with a stored print.
* Note that by default, "stored prints" are not actually stored anywhere
* except in RAM. Storage needs to be handled by the API user by using the
* fp_print_data_get_data() and fp_print_data_from_data(). This API allows
* to convert print data into byte strings, and to reconstruct stored prints
* except in RAM. For the simple scenarios, libfprint provides a simple API
* for you to save and load the stored prints referring to a single user in
* their home directory. For more advanced users, libfprint provides APIs for
* you to convert print data to a byte string, and to reconstruct stored prints
* from such data at a later point. You are welcome to store these byte strings
* in any fashion that suits you.
*
* The provided API to store data on disk is deprecated and should not be
* used anymore. This API stored the prints in the current user's home
* directory.
*/
/*
* SECTION: fpi-data
* @title: Stored prints creation
* @short_description: Stored prints creation functions
*
* Stored print can be loaded and created by certain drivers which do their own
* print matching in hardware. Most drivers will not be using those functions.
* See #fp_print_data for the public API counterpart.
*/
static char *base_store = NULL;
@@ -133,7 +106,7 @@ static struct fp_print_data *print_data_new(uint16_t driver_id,
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);
}
@@ -152,19 +125,6 @@ struct fp_print_data *fpi_print_data_new(struct fp_dev *dev)
fpi_driver_get_data_type(dev->drv));
}
struct fp_print_data_item *
fpi_print_data_get_item(struct fp_print_data *data)
{
return data->prints->data;
}
void
fpi_print_data_add_item(struct fp_print_data *data,
struct fp_print_data_item *item)
{
data->prints = g_slist_prepend(data->prints, item);
}
/**
* fp_print_data_get_data:
* @data: the stored print
@@ -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.
*
* Returns: 0 on success, non-zero on error.
*
* Deprecated: Data storage should be handled outside of libfprint.
* See <link linkend="libfprint-Stored-prints.description">stored prints description</link>
* for more information.
*/
API_EXPORTED int fp_print_data_save(struct fp_print_data *data,
enum fp_finger finger)
@@ -398,7 +354,6 @@ API_EXPORTED int fp_print_data_save(struct fp_print_data *data,
r = g_mkdir_with_parents(dirpath, DIR_PERMS);
if (r < 0) {
fp_err("couldn't create storage directory");
free(buf);
g_free(path);
g_free(dirpath);
return r;
@@ -485,16 +440,12 @@ static int load_from_file(char *path, struct fp_print_data **data)
* obscure error conditions (e.g. corruption).
*
* Returns: 0 on success, non-zero on error
*
* Deprecated: Data storage should be handled outside of libfprint.
* See <link linkend="libfprint-Stored-prints.description">stored prints description</link>
* for more information.
*/
API_EXPORTED int fp_print_data_load(struct fp_dev *dev,
enum fp_finger finger, struct fp_print_data **data)
{
gchar *path;
struct fp_print_data *fdata = NULL;
struct fp_print_data *fdata;
int r;
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().
*
* Returns: 0 on success, negative on error
*
* Deprecated: Data storage should be handled outside of libfprint.
* See <link linkend="libfprint-Stored-prints.description">stored prints description</link>
* for more information.
*/
API_EXPORTED int fp_print_data_delete(struct fp_dev *dev,
enum fp_finger finger)
@@ -613,7 +560,6 @@ API_EXPORTED uint32_t fp_print_data_get_devtype(struct fp_print_data *data)
/**
* SECTION:dscv_print
* @title: Print discovery (deprecated)
* @short_description: Print discovery functions
*
* The [stored print](libfprint-Stored-prints.html) documentation detailed a simple API
* for storing per-device prints for a single user, namely
@@ -749,7 +695,9 @@ API_EXPORTED struct fp_dscv_print **fp_discover_prints(void)
GError *err = NULL;
GSList *tmplist = NULL;
GSList *elem;
GPtrArray *array;
unsigned int tmplist_len;
struct fp_dscv_print **list;
unsigned int i;
if (!base_store)
storage_setup();
@@ -784,17 +732,15 @@ API_EXPORTED struct fp_dscv_print **fp_discover_prints(void)
}
g_dir_close(dir);
if (tmplist == NULL)
return NULL;
array = g_ptr_array_new();
for (elem = tmplist; elem != NULL; elem = elem->next)
g_ptr_array_add(array, elem->data);
g_ptr_array_add(array, NULL);
tmplist_len = g_slist_length(tmplist);
list = g_malloc(sizeof(*list) * (tmplist_len + 1));
elem = tmplist;
for (i = 0; i < tmplist_len; i++, elem = g_slist_next(elem))
list[i] = elem->data;
list[tmplist_len] = NULL; /* NULL-terminate */
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 FINGER_DETECTION_LEN 19
#define STRIP_CAPTURE_LEN 665
/*
* The AES1610 is an imaging device using a swipe-type sensor. It samples
* the finger at preprogrammed intervals, sending a 128x8 frame to the
@@ -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 */
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)
fpi_ssm_mark_failed(ssm, -EIO);
fpi_ssm_mark_aborted(ssm, -EIO);
else if (transfer->length != transfer->actual_length)
fpi_ssm_mark_failed(ssm, -EPROTO);
fpi_ssm_mark_aborted(ssm, -EPROTO);
else
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,
void *user_data)
{
fpi_ssm *ssm = user_data;
struct fpi_ssm *ssm = user_data;
if (result == 0)
fpi_ssm_next_state(ssm);
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
* 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;
struct fp_dev *dev;
int r;
if (!transfer) {
fpi_ssm_mark_aborted(ssm, -ENOMEM);
return;
}
data = g_malloc(bytes);
dev = fpi_ssm_get_dev(ssm);
libusb_fill_bulk_transfer(transfer, fpi_dev_get_usb_dev(dev), EP_IN, data, bytes,
generic_ignore_data_cb, ssm, BULK_TIMEOUT);
@@ -143,7 +147,7 @@ static void generic_read_ignore_data(fpi_ssm *ssm, struct fp_dev *dev, size_t by
if (r < 0) {
g_free(data);
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;
}
transfer = fpi_usb_alloc();
data = g_malloc(FINGER_DETECTION_LEN);
libusb_fill_bulk_transfer(transfer, fpi_dev_get_usb_dev(FP_DEV(dev)), EP_IN, data, FINGER_DETECTION_LEN,
transfer = libusb_alloc_transfer(0);
if (!transfer) {
fpi_imgdev_session_error(dev, -ENOMEM);
return;
}
data = g_malloc(19);
libusb_fill_bulk_transfer(transfer, fpi_imgdev_get_usb_dev(dev), EP_IN, data, 19,
finger_det_data_cb, dev, BULK_TIMEOUT);
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)
{
struct aes1610_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev));
struct aes1610_dev *aesdev = fpi_imgdev_get_user_data(dev);
if (aesdev->deactivating) {
complete_deactivation(dev);
@@ -548,17 +557,17 @@ enum capture_states {
static void capture_read_strip_cb(struct libusb_transfer *transfer)
{
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 aes1610_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev));
struct aes1610_dev *aesdev = fpi_imgdev_get_user_data(dev);
unsigned char *data = transfer->buffer;
int sum, i;
if (transfer->status != LIBUSB_TRANSFER_COMPLETED) {
fpi_ssm_mark_failed(ssm, -EIO);
fpi_ssm_mark_aborted(ssm, -EIO);
goto out;
} else if (transfer->length != transfer->actual_length) {
fpi_ssm_mark_failed(ssm, -EPROTO);
fpi_ssm_mark_aborted(ssm, -EPROTO);
goto out;
}
@@ -585,7 +594,7 @@ static void capture_read_strip_cb(struct libusb_transfer *transfer)
}
if (sum < 0) {
fpi_ssm_mark_failed(ssm, sum);
fpi_ssm_mark_aborted(ssm, sum);
goto out;
}
fp_dbg("sum=%d", sum);
@@ -634,10 +643,10 @@ out:
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 aes1610_dev *aesdev = FP_INSTANCE_DATA(_dev);
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct aes1610_dev *aesdev = fpi_imgdev_get_user_data(dev);
int r;
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;
case CAPTURE_READ_DATA:
fp_dbg("read data");
generic_read_ignore_data(ssm, _dev, STRIP_CAPTURE_LEN);
generic_read_ignore_data(ssm, 665);
break;
case CAPTURE_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);
break;
case CAPTURE_READ_STRIP: ;
struct libusb_transfer *transfer = fpi_usb_alloc();
struct libusb_transfer *transfer = libusb_alloc_transfer(0);
unsigned char *data;
data = g_malloc(STRIP_CAPTURE_LEN);
libusb_fill_bulk_transfer(transfer, fpi_dev_get_usb_dev(FP_DEV(dev)), EP_IN, data, STRIP_CAPTURE_LEN,
if (!transfer) {
fpi_ssm_mark_aborted(ssm, -ENOMEM);
break;
}
data = g_malloc(665);
libusb_fill_bulk_transfer(transfer, fpi_imgdev_get_usb_dev(dev), EP_IN, data, 665,
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_failed(ssm, r);
fpi_ssm_mark_aborted(ssm, r);
}
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 aes1610_dev *aesdev = FP_INSTANCE_DATA(_dev);
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct aes1610_dev *aesdev = fpi_imgdev_get_user_data(dev);
G_DEBUG_HERE();
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)
{
struct aes1610_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev));
fpi_ssm *ssm;
struct aes1610_dev *aesdev = fpi_imgdev_get_user_data(dev);
struct fpi_ssm *ssm;
if (aesdev->deactivating) {
complete_deactivation(dev);
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();
fpi_ssm_set_user_data(ssm, dev);
fpi_ssm_start(ssm, capture_sm_complete);
}
@@ -723,9 +738,9 @@ enum activate_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 */
/* verify theres anything missing here */
@@ -738,9 +753,9 @@ static void activate_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_dat
}
/* 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));
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);
}
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));
fpi_ssm *ssm = fpi_ssm_new(FP_DEV(dev), activate_run_state,
ACTIVATE_NUM_STATES, dev);
struct aes1610_dev *aesdev = fpi_imgdev_get_user_data(dev);
struct fpi_ssm *ssm = fpi_ssm_new(fpi_imgdev_get_dev(dev), activate_run_state,
ACTIVATE_NUM_STATES);
fpi_ssm_set_user_data(ssm, dev);
aesdev->read_regs_retry_count = 0;
fpi_ssm_start(ssm, activate_sm_complete);
return 0;
@@ -761,7 +777,7 @@ static int dev_activate(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
* in error handling paths? */
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)
{
struct aes1610_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev));
struct aes1610_dev *aesdev = fpi_imgdev_get_user_data(dev);
G_DEBUG_HERE();
/* 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;
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) {
fp_err("could not claim interface 0: %s", libusb_error_name(r));
return r;
}
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);
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)
{
struct aes1610_dev *aesdev;
aesdev = FP_INSTANCE_DATA(FP_DEV(dev));
aesdev = fpi_imgdev_get_user_data(dev);
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);
}

View File

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

View File

@@ -36,11 +36,6 @@ static void complete_deactivation(struct fp_img_dev *dev);
#define BULK_TIMEOUT 4000
#define FINGER_DETECTION_LEN 20
#define READ_REGS_LEN 126
#define READ_REGS_RESP_LEN 159
#define STRIP_CAPTURE_LEN 1705
/*
* The AES2501 is an imaging device using a swipe-type sensor. It samples
* the finger at preprogrammed intervals, sending a 192x16 frame to the
@@ -88,12 +83,9 @@ struct aes2501_read_regs {
void *user_data;
};
static void read_regs_data_cb(struct libusb_transfer *transfer,
struct fp_dev *dev,
fpi_ssm *ssm,
void *user_data)
static void read_regs_data_cb(struct libusb_transfer *transfer)
{
struct aes2501_read_regs *rdata = user_data;
struct aes2501_read_regs *rdata = transfer->user_data;
unsigned char *retdata = NULL;
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);
g_free(rdata);
g_free(transfer->buffer);
libusb_free_transfer(transfer);
}
static void read_regs_rq_cb(struct fp_img_dev *dev, int result, void *user_data)
{
struct aes2501_read_regs *rdata = user_data;
fpi_usb_transfer *transfer;
struct libusb_transfer *transfer;
unsigned char *data;
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)
goto err;
data = g_malloc(READ_REGS_LEN);
transfer = fpi_usb_fill_bulk_transfer(FP_DEV(dev),
NULL,
EP_IN,
data,
READ_REGS_LEN,
read_regs_data_cb,
rdata,
BULK_TIMEOUT);
transfer = libusb_alloc_transfer(0);
if (!transfer) {
result = -ENOMEM;
goto err;
}
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) {
g_free(data);
libusb_free_transfer(transfer);
result = -EIO;
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,
void *user_data)
{
fpi_ssm *ssm = user_data;
struct fpi_ssm *ssm = user_data;
if (result == 0)
fpi_ssm_next_state(ssm);
else
fpi_ssm_mark_failed(ssm, result);
fpi_ssm_mark_aborted(ssm, result);
}
/* check that read succeeded but ignore all data */
static void generic_ignore_data_cb(struct libusb_transfer *transfer,
struct fp_dev *dev,
fpi_ssm *ssm,
void *user_data)
static void generic_ignore_data_cb(struct libusb_transfer *transfer)
{
struct fpi_ssm *ssm = transfer->user_data;
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)
fpi_ssm_mark_failed(ssm, -EPROTO);
fpi_ssm_mark_aborted(ssm, -EPROTO);
else
fpi_ssm_next_state(ssm);
g_free(transfer->buffer);
libusb_free_transfer(transfer);
}
/* read the specified number of bytes from the IN endpoint but throw them
* away, then increment the SSM */
static void generic_read_ignore_data(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;
struct fp_dev *dev = fpi_ssm_get_dev(ssm);
int r;
data = g_malloc(bytes);
transfer = fpi_usb_fill_bulk_transfer(dev,
ssm,
EP_IN,
data,
bytes,
generic_ignore_data_cb,
NULL,
BULK_TIMEOUT);
if (!transfer) {
fpi_ssm_mark_aborted(ssm, -ENOMEM);
return;
}
r = fpi_usb_submit_transfer(transfer);
if (r < 0)
fpi_ssm_mark_failed(ssm, r);
data = g_malloc(bytes);
libusb_fill_bulk_transfer(transfer, fpi_dev_get_usb_dev(dev), EP_IN, data, bytes,
generic_ignore_data_cb, ssm, BULK_TIMEOUT);
r = libusb_submit_transfer(transfer);
if (r < 0) {
g_free(data);
libusb_free_transfer(transfer);
fpi_ssm_mark_aborted(ssm, r);
}
}
/****** 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 finger_det_data_cb(struct libusb_transfer *transfer,
struct fp_dev *_dev,
fpi_ssm *ssm,
void *user_data)
static void finger_det_data_cb(struct libusb_transfer *transfer)
{
struct fp_img_dev *dev = FP_IMG_DEV(_dev);
struct fp_img_dev *dev = transfer->user_data;
unsigned char *data = transfer->buffer;
int i;
int sum = 0;
if (transfer->status != LIBUSB_TRANSFER_COMPLETED) {
fpi_imgdev_session_error(dev, -EIO);
return;
goto out;
} else if (transfer->length != transfer->actual_length) {
fpi_imgdev_session_error(dev, -EPROTO);
return;
goto out;
}
/* 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 */
start_finger_detection(dev);
}
out:
g_free(data);
libusb_free_transfer(transfer);
}
static void finger_det_reqs_cb(struct fp_img_dev *dev, int result,
void *user_data)
{
fpi_usb_transfer *transfer;
struct libusb_transfer *transfer;
unsigned char *data;
int r;
@@ -324,24 +326,27 @@ static void finger_det_reqs_cb(struct fp_img_dev *dev, int result,
return;
}
data = g_malloc(FINGER_DETECTION_LEN);
transfer = fpi_usb_fill_bulk_transfer(FP_DEV(dev),
NULL,
EP_IN,
data,
FINGER_DETECTION_LEN,
finger_det_data_cb,
NULL,
BULK_TIMEOUT);
transfer = libusb_alloc_transfer(0);
if (!transfer) {
fpi_imgdev_session_error(dev, -ENOMEM);
return;
}
r = fpi_usb_submit_transfer(transfer);
if (r < 0)
data = g_malloc(20);
libusb_fill_bulk_transfer(transfer, fpi_imgdev_get_usb_dev(dev), EP_IN, data, 20,
finger_det_data_cb, dev, BULK_TIMEOUT);
r = libusb_submit_transfer(transfer);
if (r < 0) {
g_free(data);
libusb_free_transfer(transfer);
fpi_imgdev_session_error(dev, r);
}
}
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();
if (aesdev->deactivating) {
@@ -428,37 +433,35 @@ enum capture_states {
CAPTURE_NUM_STATES,
};
static void capture_read_strip_cb(struct libusb_transfer *transfer,
struct fp_dev *_dev,
fpi_ssm *ssm,
void *user_data)
static void capture_read_strip_cb(struct libusb_transfer *transfer)
{
unsigned char *stripdata;
struct fp_img_dev *dev = FP_IMG_DEV(_dev);
struct aes2501_dev *aesdev = FP_INSTANCE_DATA(_dev);
struct fpi_ssm *ssm = transfer->user_data;
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct aes2501_dev *aesdev = fpi_imgdev_get_user_data(dev);
unsigned char *data = transfer->buffer;
int sum;
int threshold;
if (transfer->status != LIBUSB_TRANSFER_COMPLETED) {
fpi_ssm_mark_failed(ssm, -EIO);
return;
fpi_ssm_mark_aborted(ssm, -EIO);
goto out;
} else if (transfer->length != transfer->actual_length) {
fpi_ssm_mark_failed(ssm, -EPROTO);
return;
fpi_ssm_mark_aborted(ssm, -EPROTO);
goto out;
}
threshold = regval_from_dump(data + 1 + 192*8 + 1 + 16*2 + 1 + 8,
AES2501_REG_DATFMT);
if (threshold < 0) {
fpi_ssm_mark_failed(ssm, threshold);
return;
fpi_ssm_mark_aborted(ssm, threshold);
goto out;
}
sum = sum_histogram_values(data + 1 + 192*8, threshold & 0x0f);
if (sum < 0) {
fpi_ssm_mark_failed(ssm, sum);
return;
fpi_ssm_mark_aborted(ssm, sum);
goto out;
}
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);
}
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 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);
int r;
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);
break;
case CAPTURE_READ_DATA_1:
generic_read_ignore_data(ssm, _dev, READ_REGS_RESP_LEN);
generic_read_ignore_data(ssm, 159);
break;
case CAPTURE_WRITE_REQS_2:
aes_write_regv(dev, capture_reqs_2, G_N_ELEMENTS(capture_reqs_2),
generic_write_regv_cb, ssm);
break;
case CAPTURE_READ_DATA_2:
generic_read_ignore_data(ssm, _dev, READ_REGS_RESP_LEN);
generic_read_ignore_data(ssm, 159);
break;
case CAPTURE_REQUEST_STRIP:
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);
break;
case CAPTURE_READ_STRIP: ;
fpi_usb_transfer *transfer;
struct libusb_transfer *transfer = libusb_alloc_transfer(0);
unsigned char *data;
data = g_malloc(STRIP_CAPTURE_LEN);
transfer = fpi_usb_fill_bulk_transfer(FP_DEV(dev),
ssm,
EP_IN,
data,
STRIP_CAPTURE_LEN,
capture_read_strip_cb,
NULL,
BULK_TIMEOUT);
if (!transfer) {
fpi_ssm_mark_aborted(ssm, -ENOMEM);
break;
}
r = fpi_usb_submit_transfer(transfer);
if (r < 0)
fpi_ssm_mark_failed(ssm, r);
data = g_malloc(1705);
libusb_fill_bulk_transfer(transfer, fpi_imgdev_get_usb_dev(dev), EP_IN, data, 1705,
capture_read_strip_cb, ssm, BULK_TIMEOUT);
r = libusb_submit_transfer(transfer);
if (r < 0) {
g_free(data);
libusb_free_transfer(transfer);
fpi_ssm_mark_aborted(ssm, r);
}
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 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);
G_DEBUG_HERE();
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)
{
struct aes2501_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev));
fpi_ssm *ssm;
struct aes2501_dev *aesdev = fpi_imgdev_get_user_data(dev);
struct fpi_ssm *ssm;
if (aesdev->deactivating) {
complete_deactivation(dev);
@@ -590,8 +599,9 @@ static void start_capture(struct fp_img_dev *dev)
aesdev->no_finger_cnt = 0;
/* Reset gain */
strip_scan_reqs[4].value = AES2501_ADREFHI_MAX_VALUE;
ssm = fpi_ssm_new(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();
fpi_ssm_set_user_data(ssm, dev);
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,
unsigned char *regs, void *user_data)
{
fpi_ssm *ssm = user_data;
struct aes2501_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev));
struct fpi_ssm *ssm = user_data;
struct aes2501_dev *aesdev = fpi_imgdev_get_user_data(dev);
if (status != 0) {
fpi_ssm_mark_failed(ssm, status);
fpi_ssm_mark_aborted(ssm, status);
} else {
fp_dbg("reg 0xaf = %x", regs[0x5f]);
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,
void *user_data)
{
fpi_ssm *ssm = user_data;
struct fpi_ssm *ssm = user_data;
if (result == 0)
fpi_ssm_jump_to_state(ssm, READ_REGS);
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
* 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;
case READ_DATA_1:
fp_dbg("read data 1");
generic_read_ignore_data(ssm, _dev, FINGER_DETECTION_LEN);
generic_read_ignore_data(ssm, 20);
break;
case WRITE_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));
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);
}
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));
fpi_ssm *ssm = fpi_ssm_new(FP_DEV(dev), activate_run_state,
ACTIVATE_NUM_STATES, dev);
struct aes2501_dev *aesdev = fpi_imgdev_get_user_data(dev);
struct fpi_ssm *ssm = fpi_ssm_new(fpi_imgdev_get_dev(dev), activate_run_state,
ACTIVATE_NUM_STATES);
fpi_ssm_set_user_data(ssm, dev);
aesdev->read_regs_retry_count = 0;
fpi_ssm_start(ssm, activate_sm_complete);
return 0;
@@ -804,7 +815,7 @@ static int dev_activate(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
* in error handling paths? */
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)
{
struct aes2501_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev));
struct aes2501_dev *aesdev = fpi_imgdev_get_user_data(dev);
G_DEBUG_HERE();
/* 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;
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) {
fp_err("could not claim interface 0: %s", libusb_error_name(r));
return r;
}
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);
return 0;
}
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);
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);
}

View File

@@ -125,10 +125,15 @@ static void finger_det_reqs_cb(struct libusb_transfer *t)
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 */
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);
r = libusb_submit_transfer(transfer);
@@ -144,7 +149,7 @@ exit_free_transfer:
static void start_finger_detection(struct fp_img_dev *dev)
{
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;
G_DEBUG_HERE();
@@ -153,8 +158,12 @@ static void start_finger_detection(struct fp_img_dev *dev)
return;
}
transfer = fpi_usb_alloc();
libusb_fill_bulk_transfer(transfer, fpi_dev_get_usb_dev(FP_DEV(dev)), EP_OUT, finger_det_reqs,
transfer = libusb_alloc_transfer(0);
if (!transfer) {
fpi_imgdev_session_error(dev, -ENOMEM);
return;
}
libusb_fill_bulk_transfer(transfer, fpi_imgdev_get_usb_dev(dev), EP_OUT, finger_det_reqs,
sizeof(finger_det_reqs), finger_det_reqs_cb, dev, BULK_TIMEOUT);
r = libusb_submit_transfer(transfer);
if (r < 0) {
@@ -191,10 +200,11 @@ enum capture_states {
};
/* 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;
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;
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)
{
fpi_ssm *ssm = transfer->user_data;
struct fpi_ssm *ssm = transfer->user_data;
if ((transfer->status == LIBUSB_TRANSFER_COMPLETED) &&
(transfer->length == transfer->actual_length)) {
fpi_ssm_next_state(ssm);
} else {
fpi_ssm_mark_failed(ssm, -EIO);
fpi_ssm_mark_aborted(ssm, -EIO);
}
libusb_free_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 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) &&
(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 */
fpi_ssm_mark_completed(ssm);
} else {
fpi_ssm_mark_failed(ssm, -EIO);
fpi_ssm_mark_aborted(ssm, -EIO);
}
libusb_free_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 aes2550_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev));
struct aes2550_dev *aesdev = fpi_imgdev_get_user_data(dev);
unsigned char *data = transfer->buffer;
int r;
if (transfer->status != LIBUSB_TRANSFER_COMPLETED) {
fp_dbg("request is not completed, %d", transfer->status);
fpi_ssm_mark_failed(ssm, -EIO);
fpi_ssm_mark_aborted(ssm, -EIO);
goto out;
}
@@ -280,10 +290,10 @@ static void capture_read_data_cb(struct libusb_transfer *transfer)
switch (transfer->actual_length) {
case AES2550_STRIP_SIZE:
r = process_strip_data(ssm, dev, data);
r = process_strip_data(ssm, data);
if (r < 0) {
fp_dbg("Processing strip data failed: %d", r);
fpi_ssm_mark_failed(ssm, -EPROTO);
fpi_ssm_mark_aborted(ssm, -EPROTO);
goto out;
}
aesdev->heartbeat_cnt = 0;
@@ -313,62 +323,73 @@ out:
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;
switch (fpi_ssm_get_cur_state(ssm)) {
case CAPTURE_WRITE_REQS:
{
struct libusb_transfer *transfer = fpi_usb_alloc();
libusb_fill_bulk_transfer(transfer, fpi_dev_get_usb_dev(FP_DEV(dev)), EP_OUT, capture_reqs,
struct libusb_transfer *transfer = libusb_alloc_transfer(0);
if (!transfer) {
fpi_ssm_mark_aborted(ssm, -ENOMEM);
return;
}
libusb_fill_bulk_transfer(transfer, fpi_imgdev_get_usb_dev(dev), EP_OUT, capture_reqs,
sizeof(capture_reqs), capture_reqs_cb, ssm, BULK_TIMEOUT);
r = libusb_submit_transfer(transfer);
if (r < 0) {
libusb_free_transfer(transfer);
fpi_ssm_mark_failed(ssm, -ENOMEM);
fpi_ssm_mark_aborted(ssm, -ENOMEM);
}
}
break;
case CAPTURE_READ_DATA:
{
struct libusb_transfer *transfer = fpi_usb_alloc();
struct libusb_transfer *transfer = libusb_alloc_transfer(0);
unsigned char *data;
if (!transfer) {
fpi_ssm_mark_aborted(ssm, -ENOMEM);
break;
}
data = g_malloc(AES2550_EP_IN_BUF_SIZE);
libusb_fill_bulk_transfer(transfer, fpi_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);
r = libusb_submit_transfer(transfer);
if (r < 0) {
g_free(data);
libusb_free_transfer(transfer);
fpi_ssm_mark_failed(ssm, r);
fpi_ssm_mark_aborted(ssm, r);
}
}
break;
case CAPTURE_SET_IDLE:
{
struct libusb_transfer *transfer = fpi_usb_alloc();
libusb_fill_bulk_transfer(transfer, fpi_dev_get_usb_dev(FP_DEV(dev)), EP_OUT, capture_set_idle_reqs,
struct libusb_transfer *transfer = libusb_alloc_transfer(0);
if (!transfer) {
fpi_ssm_mark_aborted(ssm, -ENOMEM);
return;
}
libusb_fill_bulk_transfer(transfer, fpi_imgdev_get_usb_dev(dev), EP_OUT, capture_set_idle_reqs,
sizeof(capture_set_idle_reqs), capture_set_idle_reqs_cb, ssm, BULK_TIMEOUT);
r = libusb_submit_transfer(transfer);
if (r < 0) {
libusb_free_transfer(transfer);
fpi_ssm_mark_failed(ssm, -ENOMEM);
fpi_ssm_mark_aborted(ssm, -ENOMEM);
}
}
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 aes2550_dev *aesdev = FP_INSTANCE_DATA(_dev);
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct aes2550_dev *aesdev = fpi_imgdev_get_user_data(dev);
fp_dbg("Capture completed");
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)
{
struct aes2550_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev));
fpi_ssm *ssm;
struct aes2550_dev *aesdev = fpi_imgdev_get_user_data(dev);
struct fpi_ssm *ssm;
if (aesdev->deactivating) {
complete_deactivation(dev);
@@ -391,8 +412,9 @@ static void start_capture(struct fp_img_dev *dev)
}
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();
fpi_ssm_set_user_data(ssm, dev);
fpi_ssm_start(ssm, capture_sm_complete);
}
@@ -422,25 +444,25 @@ enum activate_states {
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) &&
(transfer->length == transfer->actual_length)) {
fpi_ssm_next_state(ssm);
} else {
fpi_ssm_mark_failed(ssm, -EIO);
fpi_ssm_mark_aborted(ssm, -EIO);
}
libusb_free_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) {
fpi_ssm_next_state(ssm);
} else {
fpi_ssm_mark_failed(ssm, -EIO);
fpi_ssm_mark_aborted(ssm, -EIO);
}
g_free(transfer->buffer);
libusb_free_transfer(transfer);
@@ -450,89 +472,105 @@ static void init_read_data_cb(struct libusb_transfer *transfer)
* need more info for implementaion */
static void calibrate_read_data_cb(struct libusb_transfer *transfer)
{
fpi_ssm *ssm = transfer->user_data;
struct fpi_ssm *ssm = transfer->user_data;
if (transfer->status == LIBUSB_TRANSFER_COMPLETED) {
fpi_ssm_next_state(ssm);
} else {
fpi_ssm_mark_failed(ssm, -EIO);
fpi_ssm_mark_aborted(ssm, -EIO);
}
g_free(transfer->buffer);
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;
switch (fpi_ssm_get_cur_state(ssm)) {
case WRITE_INIT:
{
struct libusb_transfer *transfer = fpi_usb_alloc();
libusb_fill_bulk_transfer(transfer, fpi_dev_get_usb_dev(FP_DEV(dev)), EP_OUT, init_reqs,
struct libusb_transfer *transfer = libusb_alloc_transfer(0);
if (!transfer) {
fpi_ssm_mark_aborted(ssm, -ENOMEM);
return;
}
libusb_fill_bulk_transfer(transfer, fpi_imgdev_get_usb_dev(dev), EP_OUT, init_reqs,
sizeof(init_reqs), init_reqs_cb, ssm, BULK_TIMEOUT);
r = libusb_submit_transfer(transfer);
if (r < 0) {
libusb_free_transfer(transfer);
fpi_ssm_mark_failed(ssm, -ENOMEM);
fpi_ssm_mark_aborted(ssm, -ENOMEM);
}
}
break;
case READ_DATA:
{
struct libusb_transfer *transfer = fpi_usb_alloc();
struct libusb_transfer *transfer = libusb_alloc_transfer(0);
unsigned char *data;
if (!transfer) {
fpi_ssm_mark_aborted(ssm, -ENOMEM);
break;
}
data = g_malloc(AES2550_EP_IN_BUF_SIZE);
libusb_fill_bulk_transfer(transfer, fpi_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);
r = libusb_submit_transfer(transfer);
if (r < 0) {
g_free(data);
libusb_free_transfer(transfer);
fpi_ssm_mark_failed(ssm, r);
fpi_ssm_mark_aborted(ssm, r);
}
}
break;
case CALIBRATE:
{
struct libusb_transfer *transfer = fpi_usb_alloc();
libusb_fill_bulk_transfer(transfer, fpi_dev_get_usb_dev(FP_DEV(dev)), EP_OUT, calibrate_reqs,
struct libusb_transfer *transfer = libusb_alloc_transfer(0);
if (!transfer) {
fpi_ssm_mark_aborted(ssm, -ENOMEM);
return;
}
libusb_fill_bulk_transfer(transfer, fpi_imgdev_get_usb_dev(dev), EP_OUT, calibrate_reqs,
sizeof(calibrate_reqs), init_reqs_cb, ssm, BULK_TIMEOUT);
r = libusb_submit_transfer(transfer);
if (r < 0) {
libusb_free_transfer(transfer);
fpi_ssm_mark_failed(ssm, -ENOMEM);
fpi_ssm_mark_aborted(ssm, -ENOMEM);
}
}
break;
case READ_CALIB_TABLE:
{
struct libusb_transfer *transfer = fpi_usb_alloc();
struct libusb_transfer *transfer = libusb_alloc_transfer(0);
unsigned char *data;
if (!transfer) {
fpi_ssm_mark_aborted(ssm, -ENOMEM);
break;
}
data = g_malloc(AES2550_EP_IN_BUF_SIZE);
libusb_fill_bulk_transfer(transfer, fpi_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);
r = libusb_submit_transfer(transfer);
if (r < 0) {
g_free(data);
libusb_free_transfer(transfer);
fpi_ssm_mark_failed(ssm, r);
fpi_ssm_mark_aborted(ssm, r);
}
}
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));
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);
}
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,
ACTIVATE_NUM_STATES, dev);
struct fpi_ssm *ssm = fpi_ssm_new(fpi_imgdev_get_dev(dev), activate_run_state,
ACTIVATE_NUM_STATES);
fpi_ssm_set_user_data(ssm, dev);
fpi_ssm_start(ssm, activate_sm_complete);
return 0;
}
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;
}
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();
aesdev->deactivating = FALSE;
@@ -574,14 +613,14 @@ static int dev_init(struct fp_img_dev *dev, unsigned long driver_data)
int r;
struct aes2550_dev *aes2550_dev;
r = libusb_claim_interface(fpi_dev_get_usb_dev(FP_DEV(dev)), 0);
r = libusb_claim_interface(fpi_imgdev_get_usb_dev(dev), 0);
if (r < 0) {
fp_err("could not claim interface 0: %s", libusb_error_name(r));
return r;
}
aes2550_dev = g_malloc0(sizeof(struct aes2550_dev));
fp_dev_set_instance_data(FP_DEV(dev), aes2550_dev);
fpi_imgdev_set_user_data(dev, aes2550_dev);
fpi_imgdev_open_complete(dev, 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)
{
struct aes2550_dev *aesdev;
aesdev = FP_INSTANCE_DATA(FP_DEV(dev));
aesdev = fpi_imgdev_get_user_data(dev);
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);
}

View File

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

View File

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

View File

@@ -63,7 +63,7 @@ static void aes3k_assemble_image(unsigned char *input, size_t width, size_t heig
static void img_cb(struct libusb_transfer *transfer)
{
struct fp_img_dev *dev = transfer->user_data;
struct aes3k_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev));
struct aes3k_dev *aesdev = fpi_imgdev_get_user_data(dev);
unsigned char *ptr = transfer->buffer;
struct fp_img *tmp;
struct fp_img *img;
@@ -94,7 +94,7 @@ static void img_cb(struct libusb_transfer *transfer)
/* FIXME: this is an ugly hack to make the image big enough for NBIS
* to process reliably */
img = fpi_img_resize(tmp, aesdev->enlarge_factor, aesdev->enlarge_factor);
img = fpi_im_resize(tmp, aesdev->enlarge_factor, aesdev->enlarge_factor);
fp_img_free(tmp);
fpi_imgdev_image_captured(dev, img);
@@ -112,13 +112,18 @@ err:
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;
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);
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);
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);
}
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);
return 0;
}
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
* 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);
#endif

View File

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

View File

@@ -35,57 +35,52 @@ static void complete_deactivation(struct fp_img_dev *dev);
#define BULK_TIMEOUT 4000
#define FRAME_HEIGHT AESX660_FRAME_HEIGHT
#define ID_LEN 8
#define INIT_LEN 4
#define CALIBRATE_DATA_LEN 4
#define FINGER_DET_DATA_LEN 4
#define min(a, b) (((a) < (b)) ? (a) : (b))
static void
aesX660_send_cmd_timeout(fpi_ssm *ssm,
struct fp_dev *_dev,
const unsigned char *cmd,
size_t cmd_len,
libusb_transfer_cb_fn callback,
int timeout)
static void aesX660_send_cmd_timeout(struct fpi_ssm *ssm, const unsigned char *cmd,
size_t cmd_len, libusb_transfer_cb_fn callback, int timeout)
{
struct fp_img_dev *dev = 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);
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,
callback, ssm, timeout);
r = libusb_submit_transfer(transfer);
if (r < 0) {
fp_dbg("failed to submit transfer\n");
libusb_free_transfer(transfer);
fpi_ssm_mark_failed(ssm, -ENOMEM);
fpi_ssm_mark_aborted(ssm, -ENOMEM);
}
}
static void
aesX660_send_cmd(fpi_ssm *ssm,
struct fp_dev *dev,
const unsigned char *cmd,
size_t cmd_len,
libusb_transfer_cb_fn callback)
static void aesX660_send_cmd(struct fpi_ssm *ssm, 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
aesX660_read_response(fpi_ssm *ssm,
struct fp_dev *_dev,
size_t buf_len,
libusb_transfer_cb_fn callback)
static void aesX660_read_response(struct fpi_ssm *ssm, size_t buf_len,
libusb_transfer_cb_fn callback)
{
struct fp_img_dev *dev = 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;
int r;
if (!transfer) {
fpi_ssm_mark_aborted(ssm, -ENOMEM);
return;
}
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,
callback, ssm, BULK_TIMEOUT);
@@ -94,13 +89,13 @@ aesX660_read_response(fpi_ssm *ssm,
fp_dbg("Failed to submit rx transfer: %d\n", r);
g_free(data);
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)
{
fpi_ssm *ssm = transfer->user_data;
struct fpi_ssm *ssm = transfer->user_data;
if ((transfer->status == LIBUSB_TRANSFER_COMPLETED) &&
(transfer->length == transfer->actual_length)) {
@@ -108,25 +103,25 @@ static void aesX660_send_cmd_cb(struct libusb_transfer *transfer)
} else {
fp_dbg("tx transfer status: %d, actual_len: %.4x\n",
transfer->status, transfer->actual_length);
fpi_ssm_mark_failed(ssm, -EIO);
fpi_ssm_mark_aborted(ssm, -EIO);
}
libusb_free_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;
if ((transfer->status != LIBUSB_TRANSFER_COMPLETED) ||
(transfer->length != transfer->actual_length)) {
fpi_ssm_mark_failed(ssm, -EIO);
fpi_ssm_mark_aborted(ssm, -EIO);
goto out;
}
/* Calibrate response was read correctly? */
if (data[AESX660_RESPONSE_TYPE_OFFSET] != AESX660_CALIBRATE_RESPONSE) {
fp_dbg("Bogus calibrate response: %.2x\n", data[0]);
fpi_ssm_mark_failed(ssm, -EPROTO);
fpi_ssm_mark_aborted(ssm, -EPROTO);
goto out;
}
@@ -148,9 +143,9 @@ enum finger_det_states {
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 aesX660_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev));
struct aesX660_dev *aesdev = fpi_imgdev_get_user_data(dev);
unsigned char *data = transfer->buffer;
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) ||
(transfer->length != transfer->actual_length)) {
fp_dbg("Failed to read FD data\n");
fpi_ssm_mark_failed(ssm, -EIO);
fpi_ssm_mark_aborted(ssm, -EIO);
goto out;
}
if (data[AESX660_RESPONSE_TYPE_OFFSET] != AESX660_FINGER_DET_RESPONSE) {
fp_dbg("Bogus FD response: %.2x\n", data[0]);
fpi_ssm_mark_failed(ssm, -EPROTO);
fpi_ssm_mark_aborted(ssm, -EPROTO);
goto out;
}
@@ -189,21 +184,21 @@ out:
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) &&
(transfer->length == transfer->actual_length)) {
fpi_ssm_mark_completed(ssm);
} else {
fpi_ssm_mark_failed(ssm, -EIO);
fpi_ssm_mark_aborted(ssm, -EIO);
}
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 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);
int err = fpi_ssm_get_error(ssm);
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)) {
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);
break;
case FINGER_DET_SEND_FD_CMD:
aesX660_send_cmd_timeout(ssm, dev, wait_for_finger_cmd, sizeof(wait_for_finger_cmd),
aesX660_send_cmd_timeout(ssm, wait_for_finger_cmd, sizeof(wait_for_finger_cmd),
aesX660_send_cmd_cb, 0);
break;
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;
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);
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)
{
fpi_ssm *ssm;
struct aesX660_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev));
struct fpi_ssm *ssm;
struct aesX660_dev *aesdev = fpi_imgdev_get_user_data(dev);
if (aesdev->deactivating) {
complete_deactivation(dev);
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);
}
@@ -266,11 +263,12 @@ enum capture_states {
};
/* 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;
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 */
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_len++;
return (data[AESX660_LAST_FRAME_OFFSET] & AESX660_LAST_FRAME_BIT);
} else {
return 0;
}
g_free(stripe);
return 0;
}
static void capture_set_idle_cmd_cb(struct libusb_transfer *transfer)
{
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 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) &&
(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_ssm_mark_completed(ssm);
} else {
fpi_ssm_mark_failed(ssm, -EIO);
fpi_ssm_mark_aborted(ssm, -EIO);
}
libusb_free_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 aesX660_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev));
struct aesX660_dev *aesdev = fpi_imgdev_get_user_data(dev);
unsigned char *data = transfer->buffer;
int finger_missing = 0;
size_t copied, actual_len = transfer->actual_length;
if (transfer->status != LIBUSB_TRANSFER_COMPLETED) {
fpi_ssm_mark_failed(ssm, -EIO);
fpi_ssm_mark_aborted(ssm, -EIO);
goto out;
}
fp_dbg("Got %lu bytes of data", actual_len);
do {
copied = MIN(aesdev->buffer_max - aesdev->buffer_size, actual_len);
copied = min(aesdev->buffer_max - aesdev->buffer_size, actual_len);
memcpy(aesdev->buffer + aesdev->buffer_size,
data,
copied);
@@ -354,7 +352,7 @@ static void capture_read_stripe_data_cb(struct libusb_transfer *transfer)
aesdev->buffer_max);
continue;
} 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_size = 0;
}
@@ -373,38 +371,39 @@ out:
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)) {
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);
break;
case CAPTURE_SEND_CAPTURE_CMD:
aesdev->buffer_size = 0;
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,
aesX660_send_cmd_cb);
break;
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);
break;
case CAPTURE_SET_IDLE:
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);
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 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);
int err = fpi_ssm_get_error(ssm);
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)
{
struct aesX660_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev));
fpi_ssm *ssm;
struct aesX660_dev *aesdev = fpi_imgdev_get_user_data(dev);
struct fpi_ssm *ssm;
if (aesdev->deactivating) {
complete_deactivation(dev);
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();
fpi_ssm_set_user_data(ssm, dev);
fpi_ssm_start(ssm, capture_sm_complete);
}
@@ -448,15 +448,15 @@ enum activate_states {
static void activate_read_id_cb(struct libusb_transfer *transfer)
{
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 aesX660_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev));
struct aesX660_dev *aesdev = fpi_imgdev_get_user_data(dev);
unsigned char *data = transfer->buffer;
if ((transfer->status != LIBUSB_TRANSFER_COMPLETED) ||
(transfer->length != transfer->actual_length)) {
fp_dbg("read_id cmd failed\n");
fpi_ssm_mark_failed(ssm, -EIO);
fpi_ssm_mark_aborted(ssm, -EIO);
goto out;
}
/* ID was read correctly */
@@ -465,7 +465,7 @@ static void activate_read_id_cb(struct libusb_transfer *transfer)
data[4], data[3], data[5], data[6], data[7]);
} else {
fp_dbg("Bogus read ID response: %.2x\n", data[AESX660_RESPONSE_TYPE_OFFSET]);
fpi_ssm_mark_failed(ssm, -EPROTO);
fpi_ssm_mark_aborted(ssm, -EPROTO);
goto out;
}
@@ -487,7 +487,7 @@ static void activate_read_id_cb(struct libusb_transfer *transfer)
break;
default:
fp_dbg("Failed to init device! init status: %.2x\n", data[7]);
fpi_ssm_mark_failed(ssm, -EPROTO);
fpi_ssm_mark_aborted(ssm, -EPROTO);
break;
}
@@ -499,9 +499,9 @@ out:
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 aesX660_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev));
struct aesX660_dev *aesdev = fpi_imgdev_get_user_data(dev);
unsigned char *data = transfer->buffer;
fp_dbg("read_init_cb\n");
@@ -509,14 +509,14 @@ static void activate_read_init_cb(struct libusb_transfer *transfer)
if ((transfer->status != LIBUSB_TRANSFER_COMPLETED) ||
(transfer->length != transfer->actual_length)) {
fp_dbg("read_init transfer status: %d, actual_len: %d\n", transfer->status, transfer->actual_length);
fpi_ssm_mark_failed(ssm, -EIO);
fpi_ssm_mark_aborted(ssm, -EIO);
goto out;
}
/* ID was read correctly */
if (data[0] != 0x42 || data[3] != 0x01) {
fp_dbg("Bogus read init response: %.2x %.2x\n", data[0],
data[3]);
fpi_ssm_mark_failed(ssm, -EPROTO);
fpi_ssm_mark_aborted(ssm, -EPROTO);
goto out;
}
aesdev->init_cmd_idx++;
@@ -534,52 +534,55 @@ out:
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 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);
switch (fpi_ssm_get_cur_state(ssm)) {
case ACTIVATE_SET_IDLE:
aesdev->init_seq_idx = 0;
fp_dbg("Activate: set idle\n");
aesX660_send_cmd(ssm, _dev, set_idle_cmd, sizeof(set_idle_cmd),
aesX660_send_cmd(ssm, set_idle_cmd, sizeof(set_idle_cmd),
aesX660_send_cmd_cb);
break;
case ACTIVATE_SEND_READ_ID_CMD:
fp_dbg("Activate: read ID\n");
aesX660_send_cmd(ssm, _dev, read_id_cmd, sizeof(read_id_cmd),
aesX660_send_cmd(ssm, read_id_cmd, sizeof(read_id_cmd),
aesX660_send_cmd_cb);
break;
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;
case ACTIVATE_SEND_INIT_CMD:
fp_dbg("Activate: send init seq #%d cmd #%d\n",
aesdev->init_seq_idx,
aesdev->init_cmd_idx);
aesX660_send_cmd(ssm, _dev,
aesX660_send_cmd(ssm,
aesdev->init_seq[aesdev->init_cmd_idx].cmd,
aesdev->init_seq[aesdev->init_cmd_idx].len,
aesX660_send_cmd_cb);
break;
case ACTIVATE_READ_INIT_RESPONSE:
fp_dbg("Activate: read init response\n");
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;
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);
break;
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;
}
}
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);
fp_dbg("status %d", 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);
}
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,
ACTIVATE_NUM_STATES, dev);
struct fpi_ssm *ssm = fpi_ssm_new(fpi_imgdev_get_dev(dev), activate_run_state,
ACTIVATE_NUM_STATES);
fpi_ssm_set_user_data(ssm, dev);
fpi_ssm_start(ssm, activate_sm_complete);
return 0;
}
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)
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)
{
struct aesX660_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev));
struct aesX660_dev *aesdev = fpi_imgdev_get_user_data(dev);
G_DEBUG_HERE();
aesdev->deactivating = FALSE;

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

@@ -639,11 +639,14 @@ enum {
static int async_tx(struct fp_img_dev *idev, unsigned int ep, void *cb,
void *cb_arg)
{
struct etes603_dev *dev = FP_INSTANCE_DATA(FP_DEV(idev));
struct libusb_transfer *transfer = fpi_usb_alloc();
struct etes603_dev *dev = fpi_imgdev_get_user_data(idev);
struct libusb_transfer *transfer = libusb_alloc_transfer(0);
unsigned char *buffer;
int length;
if (!transfer)
return -ENOMEM;
if (ep == EP_OUT) {
buffer = (unsigned char *)dev->req;
length = dev->req_len;
@@ -653,7 +656,7 @@ static int async_tx(struct fp_img_dev *idev, unsigned int ep, void *cb,
} else {
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);
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)
{
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 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) {
fp_warn("transfer is not completed (status=%d)",
transfer->status);
fpi_ssm_mark_failed(ssm, -EIO);
fpi_ssm_mark_aborted(ssm, -EIO);
libusb_free_transfer(transfer);
} else {
unsigned char endpoint = transfer->endpoint;
@@ -688,7 +691,7 @@ static void async_tx_cb(struct libusb_transfer *transfer)
length, actual_length);
/* Chained with the answer */
if (async_tx(idev, EP_IN, async_tx_cb, ssm))
fpi_ssm_mark_failed(ssm, -EIO);
fpi_ssm_mark_aborted(ssm, -EIO);
} else if (endpoint == EP_IN) {
dev->ans_len = actual_length;
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 etes603_dev *dev = FP_INSTANCE_DATA(_dev);
struct fp_img_dev *idev = fpi_ssm_get_user_data(ssm);
struct etes603_dev *dev = fpi_imgdev_get_user_data(idev);
switch (fpi_ssm_get_cur_state(ssm)) {
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;
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)) {
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)
{
fpi_ssm *ssm = fpi_ssm_new(FP_DEV(idev), m_exit_state,
EXIT_NUM_STATES, idev);
struct fpi_ssm *ssm = fpi_ssm_new(fpi_imgdev_get_dev(idev), m_exit_state,
EXIT_NUM_STATES);
fp_dbg("Switching device to idle mode");
fpi_ssm_set_user_data(ssm, idev);
fpi_ssm_start(ssm, m_exit_complete);
}
static void m_capture_state(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 etes603_dev *dev = FP_INSTANCE_DATA(_dev);
struct fp_img_dev *idev = fpi_ssm_get_user_data(ssm);
struct etes603_dev *dev = fpi_imgdev_get_user_data(idev);
if (dev->is_active == FALSE) {
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;
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 etes603_dev *dev = FP_INSTANCE_DATA(_dev);
struct fp_img_dev *idev = fpi_ssm_get_user_data(ssm);
struct etes603_dev *dev = fpi_imgdev_get_user_data(idev);
if (fpi_ssm_get_error(ssm)) {
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 etes603_dev *dev = FP_INSTANCE_DATA(_dev);
struct fp_img_dev *idev = fpi_ssm_get_user_data(ssm);
struct etes603_dev *dev = fpi_imgdev_get_user_data(idev);
if (dev->is_active == FALSE) {
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;
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 etes603_dev *dev = FP_INSTANCE_DATA(_dev);
struct fp_img_dev *idev = fpi_ssm_get_user_data(ssm);
struct etes603_dev *dev = fpi_imgdev_get_user_data(idev);
if (!fpi_ssm_get_error(ssm)) {
fpi_ssm *ssm_cap;
ssm_cap = fpi_ssm_new(FP_DEV(idev), m_capture_state,
CAP_NUM_STATES, idev);
struct fpi_ssm *ssm_cap;
ssm_cap = fpi_ssm_new(fpi_imgdev_get_dev(idev), m_capture_state,
CAP_NUM_STATES);
fpi_ssm_set_user_data(ssm_cap, idev);
fpi_ssm_start(ssm_cap, m_capture_complete);
} else {
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)
{
fpi_ssm *ssmf;
ssmf = fpi_ssm_new(FP_DEV(idev), m_finger_state, FGR_NUM_STATES, idev);
struct fpi_ssm *ssmf;
ssmf = fpi_ssm_new(fpi_imgdev_get_dev(idev), m_finger_state, FGR_NUM_STATES);
fpi_ssm_set_user_data(ssmf, idev);
fpi_ssm_start(ssmf, m_finger_complete);
}
/*
* 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 etes603_dev *dev = FP_INSTANCE_DATA(_dev);
struct fp_img_dev *idev = fpi_ssm_get_user_data(ssm);
struct etes603_dev *dev = fpi_imgdev_get_user_data(idev);
float hist[5];
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;
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);
if (!fpi_ssm_get_error(ssm)) {
fp_dbg("Tuning is done. Starting finger detection.");
m_start_fingerdetect(idev);
} 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");
dev->is_active = FALSE;
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
* 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 etes603_dev *dev = FP_INSTANCE_DATA(_dev);
struct fp_img_dev *idev = fpi_ssm_get_user_data(ssm);
struct etes603_dev *dev = fpi_imgdev_get_user_data(idev);
if (dev->is_active == FALSE) {
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;
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)) {
fpi_ssm *ssm_tune;
ssm_tune = fpi_ssm_new(FP_DEV(idev), m_tunevrb_state,
TUNEVRB_NUM_STATES, idev);
struct fpi_ssm *ssm_tune;
ssm_tune = fpi_ssm_new(fpi_imgdev_get_dev(idev), m_tunevrb_state,
TUNEVRB_NUM_STATES);
fpi_ssm_set_user_data(ssm_tune, idev);
fpi_ssm_start(ssm_tune, m_tunevrb_complete);
} 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");
dev->is_active = FALSE;
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);
}
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 etes603_dev *dev = FP_INSTANCE_DATA(_dev);
struct fp_img_dev *idev = fpi_ssm_get_user_data(ssm);
struct etes603_dev *dev = fpi_imgdev_get_user_data(idev);
if (dev->is_active == FALSE) {
fpi_ssm_mark_completed(ssm);
@@ -1368,20 +1375,21 @@ static void m_init_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
return;
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)) {
fpi_ssm *ssm_tune;
ssm_tune = fpi_ssm_new(FP_DEV(idev), m_tunedc_state,
TUNEDC_NUM_STATES, idev);
struct fpi_ssm *ssm_tune;
ssm_tune = fpi_ssm_new(fpi_imgdev_get_dev(idev), m_tunedc_state,
TUNEDC_NUM_STATES);
fpi_ssm_set_user_data(ssm_tune, idev);
fpi_ssm_start(ssm_tune, m_tunedc_complete);
} 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");
dev->is_active = FALSE;
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);
}
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));
fpi_ssm *ssm;
struct etes603_dev *dev = fpi_imgdev_get_user_data(idev);
struct fpi_ssm *ssm;
g_assert(dev);
if (state != IMGDEV_STATE_AWAIT_FINGER_ON) {
fp_err("The driver is in an unexpected state: %d.", state);
fpi_imgdev_activate_complete(idev, 1);
return -1;
}
/* Reset info and data */
dev->is_active = TRUE;
if (dev->dcoffset == 0) {
fp_dbg("Tuning device...");
ssm = fpi_ssm_new(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);
} else {
fp_dbg("Using previous tuning (DCOFFSET=0x%02X,VRT=0x%02X,"
"VRB=0x%02X,GAIN=0x%02X).", dev->dcoffset, dev->vrt,
dev->vrb, dev->gain);
fpi_imgdev_activate_complete(idev, 0);
ssm = fpi_ssm_new(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);
}
return 0;
@@ -1417,16 +1433,15 @@ static int dev_activate(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");
/* this can be called even if still activated. */
if (dev->is_active == TRUE) {
dev->is_active = FALSE;
m_exit_start(idev);
}
m_exit_start(idev);
}
static int dev_open(struct fp_img_dev *idev, unsigned long driver_data)
@@ -1435,13 +1450,13 @@ static int dev_open(struct fp_img_dev *idev, unsigned long driver_data)
struct etes603_dev *dev;
dev = g_malloc0(sizeof(struct etes603_dev));
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->ans = g_malloc(FE_SIZE);
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) {
fp_err("libusb_claim_interface failed on interface 0: %s", libusb_error_name(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)
{
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->ans);
g_free(dev->fp);
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);
}

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 img_width;
fpi_ssm *loopsm;
struct fpi_ssm *loopsm;
struct libusb_transfer *img_transfer[NUM_BULK_TRANSFERS];
struct img_transfer_data *img_transfer_data;
int num_flying;
@@ -100,21 +100,18 @@ struct sonly_dev {
enum sonly_kill_transfers_action killing_transfers;
int kill_status_code;
union {
fpi_ssm *kill_ssm;
struct fpi_ssm *kill_ssm;
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,
GSList *line1, GSList *line2)
{
unsigned char *buf1 = line1->data, *buf2 = line2->data;
int res = 0, mean = 0, i;
g_assert (ctx->line_width > 0);
for (i = 0; i < ctx->line_width; i+= 2)
mean += (int)buf1[i + 1] + (int)buf2[i];
@@ -179,11 +176,11 @@ static void free_img_transfers(struct sonly_dev *sdev)
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) {
case ABORT_SSM:
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;
case 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)
{
struct sonly_dev *sdev = FP_INSTANCE_DATA(FP_DEV(dev));
struct sonly_dev *sdev = fpi_imgdev_get_user_data(dev);
int i;
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)
{
struct sonly_dev *sdev = FP_INSTANCE_DATA(FP_DEV(dev));
struct sonly_dev *sdev = fpi_imgdev_get_user_data(dev);
struct fp_img *img;
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)
{
struct sonly_dev *sdev = FP_INSTANCE_DATA(FP_DEV(dev));
struct sonly_dev *sdev = fpi_imgdev_get_user_data(dev);
sdev->rowbuf_offset = -1;
if (sdev->num_rows > 0) {
@@ -343,7 +340,7 @@ static void row_complete(struct fp_img_dev *dev)
/* add data to row buffer */
static void add_to_rowbuf(struct fp_img_dev *dev, unsigned char *data, int size)
{
struct sonly_dev *sdev = FP_INSTANCE_DATA(FP_DEV(dev));
struct sonly_dev *sdev = fpi_imgdev_get_user_data(dev);
memcpy(sdev->rowbuf + sdev->rowbuf_offset, data, 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)
{
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];
int abs_base_addr;
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 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;
idata->flying = FALSE;
@@ -523,7 +520,7 @@ static void img_data_cb(struct libusb_transfer *transfer)
/***** STATE MACHINE HELPERS *****/
struct write_regs_data {
fpi_ssm *ssm;
struct fpi_ssm *ssm;
struct libusb_transfer *transfer;
const struct sonly_regwrite *regs;
size_t num_regs;
@@ -537,7 +534,7 @@ static void write_regs_finished(struct write_regs_data *wrdata, int result)
if (result == 0)
fpi_ssm_next_state(wrdata->ssm);
else
fpi_ssm_mark_failed(wrdata->ssm, result);
fpi_ssm_mark_aborted(wrdata->ssm, result);
g_free(wrdata);
}
@@ -577,18 +574,23 @@ static void write_regs_cb(struct libusb_transfer *transfer)
write_regs_iterate(wrdata);
}
static void
sm_write_regs(fpi_ssm *ssm,
struct fp_dev *dev,
const struct sonly_regwrite *regs,
size_t num_regs)
static void sm_write_regs(struct fpi_ssm *ssm,
const struct sonly_regwrite *regs, size_t num_regs)
{
struct write_regs_data *wrdata = g_malloc(sizeof(*wrdata));
unsigned char *data;
struct fp_dev *dev;
wrdata->transfer = libusb_alloc_transfer(0);
if (!wrdata->transfer) {
g_free(wrdata);
fpi_ssm_mark_aborted(ssm, -ENOMEM);
return;
}
wrdata->transfer = fpi_usb_alloc();
data = g_malloc(LIBUSB_CONTROL_SETUP_SIZE + 1);
libusb_fill_control_setup(data, 0x40, 0x0c, 0, 0, 1);
dev = fpi_ssm_get_dev(ssm);
libusb_fill_control_transfer(wrdata->transfer,
fpi_dev_get_usb_dev(dev), data,
write_regs_cb, wrdata, CTRL_TIMEOUT);
@@ -603,29 +605,31 @@ sm_write_regs(fpi_ssm *ssm,
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);
if (transfer->status != LIBUSB_TRANSFER_COMPLETED)
fpi_ssm_mark_failed(ssm, -EIO);
fpi_ssm_mark_aborted(ssm, -EIO);
else
fpi_ssm_next_state(ssm);
}
static void
sm_write_reg(fpi_ssm *ssm,
struct fp_img_dev *dev,
uint8_t reg,
uint8_t value)
static void sm_write_reg(struct fpi_ssm *ssm, 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;
int r;
if (!transfer) {
fpi_ssm_mark_aborted(ssm, -ENOMEM);
return;
}
fp_dbg("set %02x=%02x", reg, value);
data = g_malloc(LIBUSB_CONTROL_SETUP_SIZE + 1);
libusb_fill_control_setup(data, 0x40, 0x0c, 0, reg, 1);
libusb_fill_control_transfer(transfer, fpi_dev_get_usb_dev(FP_DEV(dev)),
libusb_fill_control_transfer(transfer, fpi_imgdev_get_usb_dev(dev),
data, sm_write_reg_cb,
ssm, CTRL_TIMEOUT);
@@ -637,18 +641,18 @@ sm_write_reg(fpi_ssm *ssm,
if (r < 0) {
g_free(data);
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)
{
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 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) {
fpi_ssm_mark_failed(ssm, -EIO);
fpi_ssm_mark_aborted(ssm, -EIO);
} else {
sdev->read_reg_result = libusb_control_transfer_get_data(transfer)[0];
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);
}
static void
sm_read_reg(fpi_ssm *ssm,
struct fp_img_dev *dev,
uint8_t reg)
static void sm_read_reg(struct fpi_ssm *ssm, 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;
int r;
if (!transfer) {
fpi_ssm_mark_aborted(ssm, -ENOMEM);
return;
}
fp_dbg("read reg %02x", reg);
data = g_malloc(LIBUSB_CONTROL_SETUP_SIZE + 8);
libusb_fill_control_setup(data, 0xc0, 0x0c, 0, reg, 8);
libusb_fill_control_transfer(transfer, fpi_dev_get_usb_dev(FP_DEV(dev)),
libusb_fill_control_transfer(transfer, fpi_imgdev_get_usb_dev(dev),
data, sm_read_reg_cb,
ssm, CTRL_TIMEOUT);
transfer->flags = LIBUSB_TRANSFER_SHORT_NOT_OK |
@@ -680,19 +687,19 @@ sm_read_reg(fpi_ssm *ssm,
if (r < 0) {
g_free(data);
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)
{
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 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) {
g_free(transfer->buffer);
fpi_ssm_mark_failed(ssm, transfer->status);
fpi_ssm_mark_aborted(ssm, transfer->status);
return;
}
@@ -706,17 +713,21 @@ static void sm_await_intr_cb(struct libusb_transfer *transfer)
fpi_ssm_next_state(ssm);
}
static void
sm_await_intr(fpi_ssm *ssm,
struct fp_img_dev *dev)
static void sm_await_intr(struct fpi_ssm *ssm)
{
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;
int r;
if (!transfer) {
fpi_ssm_mark_aborted(ssm, -ENOMEM);
return;
}
G_DEBUG_HERE();
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,
sm_await_intr_cb, ssm, 0);
transfer->flags = LIBUSB_TRANSFER_SHORT_NOT_OK |
@@ -726,7 +737,7 @@ sm_await_intr(fpi_ssm *ssm,
if (r < 0) {
libusb_free_transfer(transfer);
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,
};
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 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)) {
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;
case AWFSM_2016_READ_01:
sm_read_reg(ssm, dev, 0x01);
sm_read_reg(ssm, 0x01);
break;
case AWFSM_2016_WRITE_01:
if (sdev->read_reg_result != 0xc6)
sm_write_reg(ssm, dev, 0x01, 0x46);
sm_write_reg(ssm, 0x01, 0x46);
else
sm_write_reg(ssm, dev, 0x01, 0xc6);
sm_write_reg(ssm, 0x01, 0xc6);
break;
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;
case AWFSM_2016_READ_13:
sm_read_reg(ssm, dev, 0x13);
sm_read_reg(ssm, 0x13);
break;
case AWFSM_2016_WRITE_13:
if (sdev->read_reg_result != 0x45)
sm_write_reg(ssm, dev, 0x13, 0x05);
sm_write_reg(ssm, 0x13, 0x05);
else
sm_write_reg(ssm, dev, 0x13, 0x45);
sm_write_reg(ssm, 0x13, 0x45);
break;
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;
case AWFSM_2016_READ_07:
sm_read_reg(ssm, dev, 0x07);
sm_read_reg(ssm, 0x07);
break;
case AWFSM_2016_WRITE_07:
if (sdev->read_reg_result != 0x10 && sdev->read_reg_result != 0x90)
fp_warn("odd reg7 value %x", sdev->read_reg_result);
sm_write_reg(ssm, dev, 0x07, sdev->read_reg_result);
sm_write_reg(ssm, 0x07, sdev->read_reg_result);
break;
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;
}
}
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)) {
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;
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;
}
}
@@ -840,19 +851,17 @@ enum capsm_1001_states {
CAPSM_1001_NUM_STATES,
};
static void
capsm_fire_bulk(fpi_ssm *ssm,
struct fp_dev *_dev)
static void capsm_fire_bulk(struct fpi_ssm *ssm)
{
struct fp_img_dev *dev = FP_IMG_DEV(_dev);
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);
int i;
for (i = 0; i < NUM_BULK_TRANSFERS; i++) {
int r = libusb_submit_transfer(sdev->img_transfer[i]);
if (r < 0) {
if (i == 0) {
/* first one failed: easy peasy */
fpi_ssm_mark_failed(ssm, r);
fpi_ssm_mark_aborted(ssm, r);
return;
}
@@ -872,10 +881,10 @@ capsm_fire_bulk(fpi_ssm *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 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)) {
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);
break;
case CAPSM_2016_WRITE_15:
sm_write_reg(ssm, dev, 0x15, 0x20);
sm_write_reg(ssm, 0x15, 0x20);
break;
case CAPSM_2016_WRITE_30:
sm_write_reg(ssm, dev, 0x30, 0xe0);
sm_write_reg(ssm, 0x30, 0xe0);
break;
case CAPSM_2016_FIRE_BULK: ;
capsm_fire_bulk (ssm, _dev);
capsm_fire_bulk (ssm);
break;
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;
}
}
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)) {
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);
break;
case CAPSM_1000_FIRE_BULK: ;
capsm_fire_bulk (ssm, _dev);
capsm_fire_bulk (ssm);
break;
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;
}
}
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)) {
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);
break;
case CAPSM_1001_FIRE_BULK: ;
capsm_fire_bulk (ssm, _dev);
capsm_fire_bulk (ssm);
break;
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;
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;
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;
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;
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;
}
}
@@ -983,29 +994,29 @@ enum deinitsm_1001_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)) {
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;
}
}
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)) {
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;
}
}
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)) {
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;
}
}
@@ -1037,62 +1048,62 @@ enum initsm_1001_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 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)) {
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;
case INITSM_2016_READ_09:
sm_read_reg(ssm, dev, 0x09);
sm_read_reg(ssm, 0x09);
break;
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;
case INITSM_2016_READ_13:
sm_read_reg(ssm, dev, 0x13);
sm_read_reg(ssm, 0x13);
break;
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;
case INITSM_2016_WRITE_04:
sm_write_reg(ssm, dev, 0x04, 0x00);
sm_write_reg(ssm, 0x04, 0x00);
break;
case INITSM_2016_WRITE_05:
sm_write_reg(ssm, dev, 0x05, 0x00);
sm_write_reg(ssm, 0x05, 0x00);
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)) {
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;
}
}
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)) {
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;
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;
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;
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;
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;
}
}
@@ -1109,10 +1120,10 @@ enum loopsm_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 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)) {
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) {
fpi_ssm_mark_completed(ssm);
} else {
fpi_ssm *awfsm = NULL;
struct fpi_ssm *awfsm = NULL;
switch (sdev->dev_model) {
case UPEKSONLY_2016:
awfsm = fpi_ssm_new(FP_DEV(dev), awfsm_2016_run_state,
AWFSM_2016_NUM_STATES, dev);
awfsm = fpi_ssm_new(fpi_imgdev_get_dev(dev), awfsm_2016_run_state,
AWFSM_2016_NUM_STATES);
break;
case UPEKSONLY_1000:
awfsm = fpi_ssm_new(FP_DEV(dev), awfsm_1000_run_state,
AWFSM_1000_NUM_STATES, dev);
awfsm = fpi_ssm_new(fpi_imgdev_get_dev(dev), awfsm_1000_run_state,
AWFSM_1000_NUM_STATES);
break;
}
fpi_ssm_set_user_data(awfsm, dev);
fpi_ssm_start_subsm(ssm, awfsm);
}
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);
break;
default:
sm_await_intr(ssm, dev);
sm_await_intr(ssm);
break;
}
break;
case LOOPSM_RUN_CAPSM: ;
fpi_ssm *capsm = NULL;
struct fpi_ssm *capsm = NULL;
switch (sdev->dev_model) {
case UPEKSONLY_2016:
capsm = fpi_ssm_new(FP_DEV(dev), capsm_2016_run_state,
CAPSM_2016_NUM_STATES, dev);
capsm = fpi_ssm_new(fpi_imgdev_get_dev(dev), capsm_2016_run_state,
CAPSM_2016_NUM_STATES);
break;
case UPEKSONLY_1000:
capsm = fpi_ssm_new(FP_DEV(dev), capsm_1000_run_state,
CAPSM_1000_NUM_STATES, dev);
capsm = fpi_ssm_new(fpi_imgdev_get_dev(dev), capsm_1000_run_state,
CAPSM_1000_NUM_STATES);
break;
case UPEKSONLY_1001:
capsm = fpi_ssm_new(FP_DEV(dev), capsm_1001_run_state,
CAPSM_1001_NUM_STATES, dev);
capsm = fpi_ssm_new(fpi_imgdev_get_dev(dev), capsm_1001_run_state,
CAPSM_1001_NUM_STATES);
break;
}
fpi_ssm_set_user_data(capsm, dev);
fpi_ssm_start_subsm(ssm, capsm);
break;
case LOOPSM_CAPTURE:
break;
case LOOPSM_RUN_DEINITSM: ;
fpi_ssm *deinitsm = NULL;
struct fpi_ssm *deinitsm = NULL;
switch (sdev->dev_model) {
case UPEKSONLY_2016:
deinitsm = fpi_ssm_new(FP_DEV(dev), deinitsm_2016_run_state,
DEINITSM_2016_NUM_STATES, dev);
deinitsm = fpi_ssm_new(fpi_imgdev_get_dev(dev), deinitsm_2016_run_state,
DEINITSM_2016_NUM_STATES);
break;
case UPEKSONLY_1000:
deinitsm = fpi_ssm_new(FP_DEV(dev), deinitsm_1000_run_state,
DEINITSM_1000_NUM_STATES, dev);
deinitsm = fpi_ssm_new(fpi_imgdev_get_dev(dev), deinitsm_1000_run_state,
DEINITSM_1000_NUM_STATES);
break;
case UPEKSONLY_1001:
deinitsm = fpi_ssm_new(FP_DEV(dev), deinitsm_1001_run_state,
DEINITSM_1001_NUM_STATES, dev);
deinitsm = fpi_ssm_new(fpi_imgdev_get_dev(dev), deinitsm_1001_run_state,
DEINITSM_1001_NUM_STATES);
break;
}
sdev->capturing = FALSE;
fpi_ssm_set_user_data(deinitsm, dev);
fpi_ssm_start_subsm(ssm, deinitsm);
break;
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)
{
struct sonly_dev *sdev = FP_INSTANCE_DATA(FP_DEV(dev));
struct sonly_dev *sdev = fpi_imgdev_get_user_data(dev);
G_DEBUG_HERE();
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)
{
struct sonly_dev *sdev = FP_INSTANCE_DATA(FP_DEV(dev));
struct sonly_dev *sdev = fpi_imgdev_get_user_data(dev);
if (!sdev->capturing) {
deactivate_done(dev);
@@ -1234,10 +1248,10 @@ static void dev_deactivate(struct fp_img_dev *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 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);
int r = fpi_ssm_get_error(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 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);
int r = fpi_ssm_get_error(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)
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);
}
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));
fpi_ssm *ssm = NULL;
struct sonly_dev *sdev = fpi_imgdev_get_user_data(dev);
struct fpi_ssm *ssm = NULL;
int i;
sdev->deactivating = FALSE;
@@ -1284,26 +1299,31 @@ static int dev_activate(struct fp_img_dev *dev)
sdev->num_flying = 0;
for (i = 0; i < NUM_BULK_TRANSFERS; i++) {
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].dev = dev;
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,
4096, img_data_cb, &sdev->img_transfer_data[i], 0);
}
switch (sdev->dev_model) {
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;
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;
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;
}
fpi_ssm_set_user_data(ssm, dev);
fpi_ssm_start(ssm, initsm_complete);
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)
{
void *user_data;
user_data = FP_INSTANCE_DATA(FP_DEV(dev));
user_data = fpi_imgdev_get_user_data(dev);
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);
}
@@ -1367,20 +1387,20 @@ static int dev_init(struct fp_img_dev *dev, unsigned long driver_data)
int r;
struct sonly_dev *sdev;
r = libusb_set_configuration(fpi_dev_get_usb_dev(FP_DEV(dev)), 1);
r = libusb_set_configuration(fpi_imgdev_get_usb_dev(dev), 1);
if (r < 0) {
fp_err("could not set configuration 1");
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) {
fp_err("could not claim interface 0: %s", libusb_error_name(r));
return r;
}
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;
switch (driver_data) {
case UPEKSONLY_1000:

View File

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

View File

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

View File

@@ -28,8 +28,6 @@
#define FP_COMPONENT "upekts"
#include "drivers_api.h"
#include "fpi-async.h"
#include "upek_proto.h"
#define EP_IN (1 | LIBUSB_ENDPOINT_IN)
#define EP_OUT (2 | LIBUSB_ENDPOINT_OUT)
@@ -45,7 +43,49 @@ struct upekts_dev {
uint8_t seq; /* FIXME: improve/automate seq handling */
};
static const uint16_t crc_table[256] = {
0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
};
static uint16_t udf_crc(unsigned char *buffer, size_t size)
{
uint16_t crc = 0;
while (size--)
crc = (uint16_t) ((crc << 8) ^
crc_table[((crc >> 8) & 0x00ff) ^ *buffer++]);
return crc;
}
/*
* MESSAGE FORMAT
@@ -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,
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;
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;
unsigned char *buf;
if (!transfer)
return NULL;
if (!data && len > 0) {
fp_err("len>0 but no data?");
return NULL;
@@ -135,7 +178,7 @@ static struct libusb_transfer *alloc_send_cmd28_transfer(struct fp_dev *dev,
uint16_t _innerlen = innerlen;
size_t len = innerlen + 6;
unsigned char *buf = g_malloc0(len);
struct upekts_dev *upekdev = FP_INSTANCE_DATA(dev);
struct upekts_dev *upekdev = fpi_dev_get_user_data(dev);
uint8_t seq = upekdev->seq + CMD_SEQ_INCREMENT;
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. */
if (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;
if (!transfer)
goto err;
fp_dbg("didn't fit in buffer, need to extend by %d bytes", needed);
data = g_realloc((gpointer) data, MSG_READ_BUF_SIZE + needed);
@@ -402,9 +448,14 @@ out:
static int __read_msg_async(struct read_msg_data *udata)
{
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;
if (!transfer) {
g_free(buf);
return -ENOMEM;
}
libusb_fill_bulk_transfer(transfer, fpi_dev_get_usb_dev(udata->dev), EP_IN, buf,
MSG_READ_BUF_SIZE, read_msg_cb, udata, TIMEOUT);
r = libusb_submit_transfer(transfer);
@@ -474,28 +525,25 @@ enum initsm_states {
INITSM_NUM_STATES,
};
static void
initsm_read_msg_response_cb(fpi_ssm *ssm,
struct fp_dev *dev,
enum read_msg_status status,
uint8_t seq,
unsigned char expect_subcmd,
unsigned char subcmd)
static void initsm_read_msg_response_cb(struct fpi_ssm *ssm,
enum read_msg_status status, uint8_t seq,
unsigned char expect_subcmd, unsigned char subcmd)
{
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) {
fp_err("expected response, got %d seq=%x in state %d", status, seq,
fpi_ssm_get_cur_state(ssm));
fpi_ssm_mark_failed(ssm, -1);
fpi_ssm_mark_aborted(ssm, -1);
} else if (subcmd != expect_subcmd) {
fp_warn("expected response to subcmd 0x%02x, got response to %02x in "
"state %d", expect_subcmd, subcmd, fpi_ssm_get_cur_state(ssm));
fpi_ssm_mark_failed(ssm, -1);
fpi_ssm_mark_aborted(ssm, -1);
} else if (seq != upekdev->seq) {
fp_err("expected response to cmd seq=%02x, got response to %02x "
"in state %d", upekdev->seq, seq, fpi_ssm_get_cur_state(ssm));
fpi_ssm_mark_failed(ssm, -1);
fpi_ssm_mark_aborted(ssm, -1);
} else {
fp_dbg("state %d completed", fpi_ssm_get_cur_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,
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);
}
@@ -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,
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);
}
@@ -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,
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);
}
@@ -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,
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);
}
@@ -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,
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);
}
static void
initsm_read_msg_cmd_cb(fpi_ssm *ssm,
struct fp_dev *dev,
enum read_msg_status status,
uint8_t expect_seq,
uint8_t seq)
static void initsm_read_msg_cmd_cb(struct fpi_ssm *ssm,
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) {
fpi_ssm_mark_failed(ssm, -1);
fpi_ssm_mark_aborted(ssm, -1);
return;
} else if (status != READ_MSG_CMD) {
fp_err("expected command, got %d seq=%x in state %d", status, seq,
fpi_ssm_get_cur_state(ssm));
fpi_ssm_mark_failed(ssm, -1);
fpi_ssm_mark_aborted(ssm, -1);
return;
}
upekdev->seq = seq;
if (seq != expect_seq) {
fp_err("expected seq=%x, got %x in state %d", expect_seq, seq,
fpi_ssm_get_cur_state(ssm));
fpi_ssm_mark_failed(ssm, -1);
fpi_ssm_mark_aborted(ssm, -1);
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,
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,
uint8_t seq, unsigned char subcmd, unsigned char *data, size_t data_len,
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)
{
fpi_ssm *ssm = transfer->user_data;
struct fpi_ssm *ssm = transfer->user_data;
/* FIXME check length? */
if (transfer->status == LIBUSB_TRANSFER_COMPLETED)
fpi_ssm_next_state(ssm);
else
fpi_ssm_mark_failed(ssm, -1);
fpi_ssm_mark_aborted(ssm, -1);
g_free(transfer->buffer);
libusb_free_transfer(transfer);
}
static void
initsm_read_msg_handler(fpi_ssm *ssm,
struct fp_dev *dev,
read_msg_cb_fn callback)
static void initsm_read_msg_handler(struct fpi_ssm *ssm,
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) {
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)
{
fpi_ssm *ssm = transfer->user_data;
struct fpi_ssm *ssm = transfer->user_data;
if (transfer->status == LIBUSB_TRANSFER_COMPLETED
&& transfer->length == transfer->actual_length) {
fp_dbg("state %d completed", fpi_ssm_get_cur_state(ssm));
@@ -619,25 +662,22 @@ static void initsm_send_msg_cb(struct libusb_transfer *transfer)
} else {
fp_err("failed, state=%d rqlength=%d actual_length=%d", fpi_ssm_get_cur_state(ssm),
transfer->length, transfer->actual_length);
fpi_ssm_mark_failed(ssm, -1);
fpi_ssm_mark_aborted(ssm, -1);
}
libusb_free_transfer(transfer);
}
static void
initsm_send_msg28_handler(fpi_ssm *ssm,
struct fp_dev *dev,
unsigned char subcmd,
const unsigned char *data,
uint16_t innerlen)
static void initsm_send_msg28_handler(struct fpi_ssm *ssm,
unsigned char subcmd, const unsigned char *data, uint16_t innerlen)
{
struct fp_dev *dev = fpi_ssm_get_dev(ssm);
struct libusb_transfer *transfer;
int r;
transfer = alloc_send_cmd28_transfer(dev, subcmd, data, innerlen,
initsm_send_msg_cb, ssm);
if (!transfer) {
fpi_ssm_mark_failed(ssm, -ENOMEM);
fpi_ssm_mark_aborted(ssm, -ENOMEM);
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));
g_free(transfer->buffer);
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;
int r;
@@ -660,7 +701,12 @@ static void initsm_run_state(fpi_ssm *ssm, struct fp_dev *dev, void *user_data)
case WRITE_CTRL400: ;
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);
libusb_fill_control_setup(data,
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) {
g_free(data);
libusb_free_transfer(transfer);
fpi_ssm_mark_failed(ssm, r);
fpi_ssm_mark_aborted(ssm, r);
}
break;
case READ_MSG03:
initsm_read_msg_handler(ssm, dev, read_msg03_cb);
initsm_read_msg_handler(ssm, read_msg03_cb);
break;
case SEND_RESP03: ;
transfer = alloc_send_cmdresponse_transfer(dev, ++upekdev->seq,
init_resp03, sizeof(init_resp03), initsm_send_msg_cb, ssm);
if (!transfer) {
fpi_ssm_mark_failed(ssm, -ENOMEM);
fpi_ssm_mark_aborted(ssm, -ENOMEM);
break;
}
@@ -689,52 +735,51 @@ static void initsm_run_state(fpi_ssm *ssm, struct fp_dev *dev, void *user_data)
if (r < 0) {
g_free(transfer->buffer);
libusb_free_transfer(transfer);
fpi_ssm_mark_failed(ssm, r);
fpi_ssm_mark_aborted(ssm, r);
}
break;
case READ_MSG05:
initsm_read_msg_handler(ssm, dev, read_msg05_cb);
initsm_read_msg_handler(ssm, read_msg05_cb);
break;
case SEND28_06: ;
unsigned char dummy28_06 = 0x04;
upekdev->seq = 0xf0;
initsm_send_msg28_handler(ssm, dev, 0x06, &dummy28_06, 1);
initsm_send_msg28_handler(ssm, 0x06, &dummy28_06, 1);
break;
case READ28_06:
initsm_read_msg_handler(ssm, dev, read28_06_cb);
initsm_read_msg_handler(ssm, read28_06_cb);
break;
case SEND28_07: ;
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;
case READ28_07:
initsm_read_msg_handler(ssm, dev, read28_07_cb);
initsm_read_msg_handler(ssm, read28_07_cb);
break;
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;
case READ28_08:
initsm_read_msg_handler(ssm, dev, read28_08_cb);
initsm_read_msg_handler(ssm, read28_08_cb);
break;
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;
case READ28_0C:
initsm_read_msg_handler(ssm, dev, read28_0c_cb);
initsm_read_msg_handler(ssm, read28_0c_cb);
break;
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;
case READ28_0B:
initsm_read_msg_handler(ssm, dev, read28_0b_cb);
initsm_read_msg_handler(ssm, read28_0b_cb);
break;
}
}
static fpi_ssm *initsm_new(struct fp_dev *dev,
void *user_data)
static struct fpi_ssm *initsm_new(struct fp_dev *dev)
{
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 {
@@ -745,11 +790,11 @@ enum deinitsm_states {
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)
fpi_ssm_mark_failed(ssm, -EIO);
fpi_ssm_mark_aborted(ssm, -EIO);
else if (transfer->length != transfer->actual_length)
fpi_ssm_mark_failed(ssm, -EPROTO);
fpi_ssm_mark_aborted(ssm, -EPROTO);
else
fpi_ssm_next_state(ssm);
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,
void *user_data)
{
fpi_ssm *ssm = user_data;
struct upekts_dev *upekdev = FP_INSTANCE_DATA(dev);
struct fpi_ssm *ssm = user_data;
struct upekts_dev *upekdev = fpi_dev_get_user_data(dev);
if (status == READ_MSG_ERROR) {
fpi_ssm_mark_failed(ssm, -1);
fpi_ssm_mark_aborted(ssm, -1);
return;
} else if (status != READ_MSG_CMD) {
fp_err("expected command, got %d seq=%x", status, seq);
fpi_ssm_mark_failed(ssm, -1);
fpi_ssm_mark_aborted(ssm, -1);
return;
}
upekdev->seq = seq;
if (seq != 1) {
fp_err("expected seq=1, got %x", seq);
fpi_ssm_mark_failed(ssm, -1);
fpi_ssm_mark_aborted(ssm, -1);
return;
}
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;
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,
send_resp07_cb, ssm);
if (!transfer) {
fpi_ssm_mark_failed(ssm, -ENOMEM);
fpi_ssm_mark_aborted(ssm, -ENOMEM);
break;
}
@@ -800,20 +846,20 @@ static void deinitsm_state_handler(fpi_ssm *ssm, struct fp_dev *dev, void *user_
if (r < 0) {
g_free(transfer->buffer);
libusb_free_transfer(transfer);
fpi_ssm_mark_failed(ssm, r);
fpi_ssm_mark_aborted(ssm, r);
}
break;
case READ_MSG01: ;
r = read_msg_async(dev, read_msg01_cb, ssm);
if (r < 0)
fpi_ssm_mark_failed(ssm, r);
fpi_ssm_mark_aborted(ssm, r);
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)
@@ -829,7 +875,7 @@ static int dev_init(struct fp_dev *dev, unsigned long driver_data)
upekdev = g_malloc(sizeof(*upekdev));
upekdev->seq = 0xf0; /* incremented to 0x00 before first cmd */
fp_dev_set_instance_data(dev, upekdev);
fpi_dev_set_user_data(dev, upekdev);
fpi_dev_set_nr_enroll_stages(dev, 3);
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)
{
struct upekts_dev *upekdev = FP_INSTANCE_DATA(dev);
void *user_data;
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);
}
@@ -863,14 +909,14 @@ enum enroll_start_sm_states {
};
/* 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);
fpi_ssm_free(initsm);
if (error)
fpi_ssm_mark_failed(enroll_start_ssm, error);
fpi_ssm_mark_aborted(enroll_start_ssm, error);
else
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 */
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)
fpi_ssm_mark_failed(ssm, -EIO);
fpi_ssm_mark_aborted(ssm, -EIO);
else if (transfer->length != transfer->actual_length)
fpi_ssm_mark_failed(ssm, -EPROTO);
fpi_ssm_mark_aborted(ssm, -EPROTO);
else
fpi_ssm_next_state(ssm);
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,
unsigned char *data, size_t data_len, void *user_data)
{
struct upekts_dev *upekdev = FP_INSTANCE_DATA(dev);
fpi_ssm *ssm = user_data;
struct upekts_dev *upekdev = fpi_dev_get_user_data(dev);
struct fpi_ssm *ssm = user_data;
if (status != READ_MSG_RESPONSE) {
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) {
fp_warn("expected response to subcmd 0, got response to %02x",
subcmd);
fpi_ssm_mark_failed(ssm, -1);
fpi_ssm_mark_aborted(ssm, -1);
} else if (seq != upekdev->seq) {
fp_err("expected response to cmd seq=%02x, got response to %02x",
upekdev->seq, seq);
fpi_ssm_mark_failed(ssm, -1);
fpi_ssm_mark_aborted(ssm, -1);
} else {
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;
switch (fpi_ssm_get_cur_state(ssm)) {
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);
break;
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,
sizeof(enroll_init), enroll_start_sm_cb_init, ssm);
if (!transfer) {
fpi_ssm_mark_failed(ssm, -ENOMEM);
fpi_ssm_mark_aborted(ssm, -ENOMEM);
break;
}
@@ -933,7 +981,7 @@ static void enroll_start_sm_run_state(fpi_ssm *ssm, struct fp_dev *dev, void *us
if (r < 0) {
g_free(transfer->buffer);
libusb_free_transfer(transfer);
fpi_ssm_mark_failed(ssm, r);
fpi_ssm_mark_aborted(ssm, r);
}
break;
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? */
r = read_msg_async(dev, enroll_start_sm_cb_msg28, ssm);
if (r < 0)
fpi_ssm_mark_failed(ssm, r);
fpi_ssm_mark_aborted(ssm, r);
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,
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;
int result = 0;
@@ -970,9 +1018,6 @@ static void e_handle_resp00(struct fp_dev *dev, unsigned char *data,
case 0x0c:
case 0x0d:
case 0x0e:
case 0x26:
case 0x27:
case 0x2e:
/* if we previously completed a non-last enrollment stage, we'll
* get this code to indicate successful stage completion */
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));
memcpy(item->data, data + 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;
}
@@ -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));
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)
{
struct upekts_dev *upekdev = FP_INSTANCE_DATA(dev);
struct upekts_dev *upekdev = fpi_dev_get_user_data(dev);
/* do_init state machine first */
fpi_ssm *ssm = fpi_ssm_new(dev, enroll_start_sm_run_state,
ENROLL_START_NUM_STATES, NULL);
struct fpi_ssm *ssm = fpi_ssm_new(dev, enroll_start_sm_run_state,
ENROLL_START_NUM_STATES);
upekdev->enroll_passed = FALSE;
fpi_ssm_start(ssm, enroll_started);
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 */
fpi_drvcb_enroll_stopped(dev);
fpi_drvcb_enroll_stopped(fpi_ssm_get_dev(ssm));
fpi_ssm_free(ssm);
}
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);
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 */
fpi_drvcb_verify_stopped(dev);
fpi_drvcb_verify_stopped(fpi_ssm_get_dev(ssm));
fpi_ssm_free(ssm);
}
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);
}
@@ -1168,14 +1214,14 @@ enum {
};
/* 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;
err = fpi_ssm_get_error(initsm);
if (err)
fpi_ssm_mark_failed(verify_start_ssm, err);
fpi_ssm_mark_aborted(verify_start_ssm, err);
else
fpi_ssm_next_state(verify_start_ssm);
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)
{
fpi_ssm *ssm = transfer->user_data;
struct fpi_ssm *ssm = transfer->user_data;
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)
fpi_ssm_mark_failed(ssm, -EPROTO);
fpi_ssm_mark_aborted(ssm, -EPROTO);
else
fpi_ssm_next_state(ssm);
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;
switch (fpi_ssm_get_cur_state(ssm)) {
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);
break;
case VERIFY_INIT: ;
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;
unsigned char *data = g_malloc(data_len);
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);
g_free(data);
if (!transfer) {
fpi_ssm_mark_failed(ssm, -ENOMEM);
fpi_ssm_mark_aborted(ssm, -ENOMEM);
break;
}
@@ -1223,7 +1271,7 @@ static void verify_start_sm_run_state(fpi_ssm *ssm, struct fp_dev *dev, void *us
if (r < 0) {
g_free(transfer->buffer);
libusb_free_transfer(transfer);
fpi_ssm_mark_failed(ssm, -EIO);
fpi_ssm_mark_aborted(ssm, -EIO);
}
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,
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) {
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)
{
struct upekts_dev *upekdev = FP_INSTANCE_DATA(dev);
struct upekts_dev *upekdev = fpi_dev_get_user_data(dev);
if (upekdev->stop_verify) {
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));
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)
{
struct upekts_dev *upekdev = FP_INSTANCE_DATA(dev);
fpi_ssm *ssm = fpi_ssm_new(dev, verify_start_sm_run_state,
VERIFY_NUM_STATES, NULL);
struct upekts_dev *upekdev = fpi_dev_get_user_data(dev);
struct fpi_ssm *ssm = fpi_ssm_new(dev, verify_start_sm_run_state,
VERIFY_NUM_STATES);
upekdev->stop_verify = FALSE;
fpi_ssm_start(ssm, verify_started);
return 0;
@@ -1406,7 +1455,7 @@ static int verify_start(struct fp_dev *dev)
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)
do_verify_stop(dev);

View File

@@ -120,10 +120,9 @@ struct uru4k_dev {
unsigned char last_reg_rd[16];
unsigned char last_hwstat;
fpi_usb_transfer *irq_transfer;
fpi_usb_transfer *img_transfer;
struct libusb_transfer *irq_transfer;
struct libusb_transfer *img_transfer;
void *img_data;
int img_data_actual_length;
uint16_t img_lines_done, img_block;
uint32_t img_enc_seed;
@@ -136,7 +135,7 @@ struct uru4k_dev {
unsigned char powerup_hwstat;
int scanpwr_irq_timeouts;
fpi_timeout *scanpwr_irq_timeout;
struct fpi_timeout *scanpwr_irq_timeout;
int fwfixer_offset;
unsigned char fwfixer_value;
@@ -187,10 +186,13 @@ static int write_regs(struct fp_img_dev *dev, uint16_t first_reg,
void *user_data)
{
struct write_regs_data *wrdata;
struct libusb_transfer *transfer = fpi_usb_alloc();
struct libusb_transfer *transfer = libusb_alloc_transfer(0);
unsigned char *data;
int r;
if (!transfer)
return -ENOMEM;
wrdata = g_malloc(sizeof(*wrdata));
wrdata->dev = dev;
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);
memcpy(data + LIBUSB_CONTROL_SETUP_SIZE, values, num_regs);
libusb_fill_control_setup(data, CTRL_OUT, USB_RQ, first_reg, 0, num_regs);
libusb_fill_control_transfer(transfer, fpi_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);
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)
{
struct read_regs_data *rrdata;
struct libusb_transfer *transfer = fpi_usb_alloc();
struct libusb_transfer *transfer = libusb_alloc_transfer(0);
unsigned char *data;
int r;
if (!transfer)
return -ENOMEM;
rrdata = g_malloc(sizeof(*rrdata));
rrdata->dev = dev;
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);
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);
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
* 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)
{
fpi_ssm *ssm = user_data;
struct fpi_ssm *ssm = user_data;
if (status == 0)
fpi_ssm_next_state(ssm);
else
fpi_ssm_mark_failed(ssm, status);
fpi_ssm_mark_aborted(ssm, status);
}
static void challenge_cb(struct fp_img_dev *dev, int status,
uint16_t num_regs, unsigned char *data, void *user_data)
{
fpi_ssm *ssm = user_data;
struct uru4k_dev *urudev = FP_INSTANCE_DATA(FP_DEV(dev));
struct fpi_ssm *ssm = user_data;
struct uru4k_dev *urudev = fpi_imgdev_get_user_data(dev);
unsigned char *respdata;
PK11Context *ctx;
int r, outlen;
r = status;
if (status != 0) {
fpi_ssm_mark_failed(ssm, status);
fpi_ssm_mark_aborted(ssm, status);
return;
}
@@ -341,7 +346,7 @@ static void challenge_cb(struct fp_img_dev *dev, int status,
g_free(respdata);
}
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
* driver.
*/
static void
sm_do_challenge_response(fpi_ssm *ssm,
struct fp_img_dev *dev)
static void sm_do_challenge_response(struct fpi_ssm *ssm)
{
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
int r;
G_DEBUG_HERE();
r = read_regs(dev, REG_CHALLENGE, CR_LENGTH, challenge_cb, ssm);
if (r < 0)
fpi_ssm_mark_failed(ssm, r);
fpi_ssm_mark_aborted(ssm, r);
}
/***** INTERRUPT HANDLING *****/
@@ -367,13 +371,10 @@ sm_do_challenge_response(fpi_ssm *ssm,
static int start_irq_handler(struct fp_img_dev *dev);
static void irq_handler(struct libusb_transfer *transfer,
struct fp_dev *_dev,
fpi_ssm *ssm,
void *user_data)
static void irq_handler(struct libusb_transfer *transfer)
{
struct fp_img_dev *dev = FP_IMG_DEV(_dev);
struct uru4k_dev *urudev = FP_INSTANCE_DATA(_dev);
struct fp_img_dev *dev = transfer->user_data;
struct uru4k_dev *urudev = fpi_imgdev_get_user_data(dev);
unsigned char *data = transfer->buffer;
uint16_t type;
int r = 0;
@@ -395,6 +396,8 @@ static void irq_handler(struct libusb_transfer *transfer,
type = GUINT16_FROM_BE(*((uint16_t *) data));
fp_dbg("recv irq type %04x", type);
g_free(data);
libusb_free_transfer(transfer);
/* The 0800 interrupt seems to indicate imminent failure (0 bytes transfer)
* of the next scan. It still appears on occasion. */
@@ -410,43 +413,47 @@ static void irq_handler(struct libusb_transfer *transfer,
if (r == 0)
return;
transfer = NULL;
data = NULL;
err:
if (urudev->irq_cb)
urudev->irq_cb(dev, r, 0, urudev->irq_cb_data);
out:
g_free(data);
libusb_free_transfer(transfer);
urudev->irq_transfer = NULL;
}
static int start_irq_handler(struct fp_img_dev *dev)
{
struct uru4k_dev *urudev = FP_INSTANCE_DATA(FP_DEV(dev));
fpi_usb_transfer *transfer;
struct uru4k_dev *urudev = fpi_imgdev_get_user_data(dev);
struct libusb_transfer *transfer = libusb_alloc_transfer(0);
unsigned char *data;
int r;
if (!transfer)
return -ENOMEM;
data = g_malloc(IRQ_LENGTH);
transfer = fpi_usb_fill_bulk_transfer(FP_DEV(dev),
NULL,
EP_INTR,
data,
IRQ_LENGTH,
irq_handler,
NULL,
0);
libusb_fill_bulk_transfer(transfer, fpi_imgdev_get_usb_dev(dev), EP_INTR, data, IRQ_LENGTH,
irq_handler, dev, 0);
urudev->irq_transfer = transfer;
r = fpi_usb_submit_transfer(transfer);
if (r < 0)
r = libusb_submit_transfer(transfer);
if (r < 0) {
g_free(data);
libusb_free_transfer(transfer);
urudev->irq_transfer = NULL;
}
return r;
}
static void stop_irq_handler(struct fp_img_dev *dev, irqs_stopped_cb_fn cb)
{
struct uru4k_dev *urudev = FP_INSTANCE_DATA(FP_DEV(dev));
fpi_usb_transfer *transfer = urudev->irq_transfer;
struct uru4k_dev *urudev = fpi_imgdev_get_user_data(dev);
struct libusb_transfer *transfer = urudev->irq_transfer;
if (transfer) {
fpi_usb_cancel_transfer(transfer);
libusb_cancel_transfer(transfer);
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)
{
struct uru4k_dev *urudev = FP_INSTANCE_DATA(FP_DEV(dev));
struct uru4k_dev *urudev = fpi_imgdev_get_user_data(dev);
switch (state) {
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)
{
fpi_ssm *ssm = user_data;
struct fpi_ssm *ssm = user_data;
if (result)
fpi_ssm_mark_failed(ssm, result);
fpi_ssm_mark_aborted(ssm, result);
else
fpi_ssm_next_state(ssm);
}
static void
sm_write_regs(fpi_ssm *ssm,
struct fp_img_dev *dev,
uint16_t first_reg,
uint16_t num_regs,
void *data)
static void sm_write_regs(struct fpi_ssm *ssm, uint16_t first_reg, uint16_t num_regs,
void *data)
{
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
int r = write_regs(dev, first_reg, num_regs, data, sm_write_reg_cb, ssm);
if (r < 0)
fpi_ssm_mark_failed(ssm, r);
fpi_ssm_mark_aborted(ssm, r);
}
static void
sm_write_reg(fpi_ssm *ssm,
struct fp_img_dev *dev,
uint16_t reg,
unsigned char value)
static void sm_write_reg(struct fpi_ssm *ssm, 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,
uint16_t num_regs, unsigned char *data, void *user_data)
{
fpi_ssm *ssm = user_data;
struct uru4k_dev *urudev = FP_INSTANCE_DATA(FP_DEV(dev));
struct fpi_ssm *ssm = user_data;
struct uru4k_dev *urudev = fpi_imgdev_get_user_data(dev);
if (result) {
fpi_ssm_mark_failed(ssm, result);
fpi_ssm_mark_aborted(ssm, result);
} else {
memcpy(urudev->last_reg_rd, data, num_regs);
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(fpi_ssm *ssm,
struct fp_img_dev *dev,
uint16_t reg,
uint16_t num_regs)
static void sm_read_regs(struct fpi_ssm *ssm, uint16_t reg, uint16_t num_regs)
{
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct uru4k_dev *urudev = fpi_imgdev_get_user_data(dev);
int r;
if (num_regs > member_size(struct uru4k_dev, last_reg_rd)) {
fpi_ssm_mark_failed(ssm, -EIO);
if (num_regs > sizeof(urudev->last_reg_rd)) {
fpi_ssm_mark_aborted(ssm, -EIO);
return;
}
fp_dbg("read %d regs at %x", num_regs, reg);
r = read_regs(dev, reg, num_regs, sm_read_reg_cb, ssm);
if (r < 0)
fpi_ssm_mark_failed(ssm, r);
fpi_ssm_mark_aborted(ssm, r);
}
static void
sm_read_reg(fpi_ssm *ssm,
struct fp_img_dev *dev,
uint16_t reg)
static void sm_read_reg(struct fpi_ssm *ssm, uint16_t reg)
{
sm_read_regs(ssm, dev, reg, 1);
sm_read_regs(ssm, reg, 1);
}
static void
sm_set_hwstat(fpi_ssm *ssm,
struct fp_img_dev *dev,
unsigned char value)
static void sm_set_hwstat(struct fpi_ssm *ssm, unsigned char value)
{
fp_dbg("set %02x", value);
sm_write_reg(ssm, dev, REG_HWSTAT, value);
sm_write_reg(ssm, REG_HWSTAT, value);
}
/***** IMAGING LOOP *****/
@@ -594,6 +585,28 @@ enum imaging_states {
IMAGING_NUM_STATES
};
static void image_transfer_cb(struct libusb_transfer *transfer)
{
struct fpi_ssm *ssm = transfer->user_data;
if (transfer->status == LIBUSB_TRANSFER_CANCELLED) {
fp_dbg("cancelled");
fpi_ssm_mark_aborted(ssm, -ECANCELED);
} else if (transfer->status != LIBUSB_TRANSFER_COMPLETED) {
fp_dbg("error");
fpi_ssm_mark_aborted(ssm, -EIO);
} else {
fpi_ssm_next_state(ssm);
}
}
enum {
BLOCKF_CHANGE_KEY = 0x80,
BLOCKF_NO_KEY_UPDATE = 0x04,
BLOCKF_ENCRYPTED = 0x02,
BLOCKF_NOT_PRESENT = 0x01,
};
struct uru4k_image {
uint8_t unknown_00[4];
uint16_t num_lines;
@@ -607,33 +620,6 @@ struct uru4k_image {
uint8_t data[IMAGE_HEIGHT][IMAGE_WIDTH];
};
static void image_transfer_cb(struct libusb_transfer *transfer,
struct fp_dev *dev,
fpi_ssm *ssm,
void *user_data)
{
if (transfer->status == LIBUSB_TRANSFER_CANCELLED) {
fp_dbg("cancelled");
fpi_ssm_mark_failed(ssm, -ECANCELED);
} else if (transfer->status != LIBUSB_TRANSFER_COMPLETED) {
fp_dbg("error");
fpi_ssm_mark_failed(ssm, -EIO);
} else {
struct uru4k_dev *urudev = FP_INSTANCE_DATA(dev);
urudev->img_data = g_memdup(transfer->buffer, sizeof(struct uru4k_image));
urudev->img_data_actual_length = transfer->actual_length;
fpi_ssm_next_state(ssm);
}
}
enum {
BLOCKF_CHANGE_KEY = 0x80,
BLOCKF_NO_KEY_UPDATE = 0x04,
BLOCKF_ENCRYPTED = 0x02,
BLOCKF_NOT_PRESENT = 0x01,
};
static uint32_t update_key(uint32_t key)
{
/* linear feedback shift register
@@ -701,35 +687,35 @@ static int calc_dev2(struct uru4k_image *img)
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 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);
struct uru4k_image *img = urudev->img_data;
struct fp_img *fpimg;
uint32_t key;
uint8_t flags, num_lines;
int i, r, to, dev2;
unsigned char buf[5];
char buf[5];
switch (fpi_ssm_get_cur_state(ssm)) {
case IMAGING_CAPTURE:
urudev->img_lines_done = 0;
urudev->img_block = 0;
r = fpi_usb_submit_transfer(urudev->img_transfer);
if (r < 0) {
urudev->img_transfer = NULL;
fpi_ssm_mark_failed(ssm, -EIO);
}
libusb_fill_bulk_transfer(urudev->img_transfer, fpi_imgdev_get_usb_dev(dev), EP_DATA,
urudev->img_data, sizeof(struct uru4k_image), image_transfer_cb, ssm, 0);
r = libusb_submit_transfer(urudev->img_transfer);
if (r < 0)
fpi_ssm_mark_aborted(ssm, -EIO);
break;
case IMAGING_SEND_INDEX:
fp_dbg("hw header lines %d", img->num_lines);
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",
img->num_lines,
urudev->img_data_actual_length,
urudev->img_transfer->actual_length,
img->num_lines * IMAGE_WIDTH + 64);
fpi_ssm_jump_to_state(ssm, IMAGING_CAPTURE);
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[3] = urudev->img_enc_seed >> 16;
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;
case IMAGING_READ_KEY:
sm_read_regs(ssm, dev, REG_SCRAMBLE_DATA_KEY, 4);
sm_read_regs(ssm, REG_SCRAMBLE_DATA_KEY, 4);
break;
case IMAGING_DECODE:
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 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);
int r = fpi_ssm_get_error(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)
fpi_imgdev_session_error(dev, r);
/* Freed by callback or cancellation */
urudev->img_transfer = NULL;
g_free(urudev->img_data);
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);
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
* 56aa interrupt. This is the best way I've found to fix it: mess around
* with hwstat until it starts returning more recognisable values. This
* doesn't happen on my other devices: uru4000, uru4000b, ms fp rdr v2
* doesn't happen on my other devices: uru4000, uru4000b, ms fp rdr v2
*
* The windows driver copes with this OK, but then again it uploads firmware
* right after reading the 0x85 hwstat, allowing some time to pass before it
@@ -875,33 +860,32 @@ enum rebootpwr_states {
REBOOTPWR_NUM_STATES,
};
static void
rebootpwr_pause_cb(struct fp_dev *dev,
void *data)
static void rebootpwr_pause_cb(void *data)
{
fpi_ssm *ssm = data;
struct uru4k_dev *urudev = FP_INSTANCE_DATA(dev);
struct fpi_ssm *ssm = data;
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct uru4k_dev *urudev = fpi_imgdev_get_user_data(dev);
if (!--urudev->rebootpwr_ctr) {
fp_err("could not reboot device power");
fpi_ssm_mark_failed(ssm, -EIO);
fpi_ssm_mark_aborted(ssm, -EIO);
} else {
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 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);
switch (fpi_ssm_get_cur_state(ssm)) {
case REBOOTPWR_SET_HWSTAT:
urudev->rebootpwr_ctr = 100;
sm_set_hwstat(ssm, dev, urudev->last_hwstat & 0xf);
sm_set_hwstat(ssm, urudev->last_hwstat & 0xf);
break;
case REBOOTPWR_GET_HWSTAT:
sm_read_reg(ssm, dev, REG_HWSTAT);
sm_read_reg(ssm, REG_HWSTAT);
break;
case REBOOTPWR_CHECK_HWSTAT:
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);
break;
case REBOOTPWR_PAUSE:
if (fpi_timeout_add(10, rebootpwr_pause_cb, _dev, ssm) == NULL)
fpi_ssm_mark_failed(ssm, -ETIME);
if (fpi_timeout_add(10, rebootpwr_pause_cb, ssm) == NULL)
fpi_ssm_mark_aborted(ssm, -ETIME);
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
* 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,
* authenticating each time, until the device wakes up.
*
@@ -953,16 +937,15 @@ enum powerup_states {
POWERUP_NUM_STATES,
};
static void
powerup_pause_cb(struct fp_dev *dev,
void *data)
static void powerup_pause_cb(void *data)
{
fpi_ssm *ssm = data;
struct uru4k_dev *urudev = FP_INSTANCE_DATA(dev);
struct fpi_ssm *ssm = data;
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct uru4k_dev *urudev = fpi_imgdev_get_user_data(dev);
if (!--urudev->powerup_ctr) {
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) {
fpi_ssm_jump_to_state(ssm, POWERUP_SET_HWSTAT);
} 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 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);
switch (fpi_ssm_get_cur_state(ssm)) {
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);
break;
case POWERUP_SET_HWSTAT:
sm_set_hwstat(ssm, dev, urudev->powerup_hwstat);
sm_set_hwstat(ssm, urudev->powerup_hwstat);
break;
case POWERUP_GET_HWSTAT:
sm_read_reg(ssm, dev, REG_HWSTAT);
sm_read_reg(ssm, REG_HWSTAT);
break;
case POWERUP_CHECK_HWSTAT:
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);
break;
case POWERUP_PAUSE:
if (fpi_timeout_add(10, powerup_pause_cb, _dev, ssm) == NULL)
fpi_ssm_mark_failed(ssm, -ETIME);
if (fpi_timeout_add(10, powerup_pause_cb, ssm) == NULL)
fpi_ssm_mark_aborted(ssm, -ETIME);
break;
case POWERUP_CHALLENGE_RESPONSE:
sm_do_challenge_response(ssm, dev);
sm_do_challenge_response(ssm);
break;
case POWERUP_CHALLENGE_RESPONSE_SUCCESS:
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,
uint16_t type, void *user_data)
{
fpi_ssm *ssm = user_data;
struct uru4k_dev *urudev = FP_INSTANCE_DATA(FP_DEV(dev));
struct fpi_ssm *ssm = user_data;
struct uru4k_dev *urudev = fpi_imgdev_get_user_data(dev);
if (status)
fpi_ssm_mark_failed(ssm, status);
fpi_ssm_mark_aborted(ssm, status);
else if (type != IRQDATA_SCANPWR_ON)
fp_dbg("ignoring interrupt");
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
init_scanpwr_timeout(struct fp_dev *dev,
void *user_data)
static void init_scanpwr_timeout(void *user_data)
{
fpi_ssm *ssm = user_data;
struct uru4k_dev *urudev = FP_INSTANCE_DATA(dev);
struct fpi_ssm *ssm = user_data;
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct uru4k_dev *urudev = fpi_imgdev_get_user_data(dev);
fp_warn("powerup timed out");
urudev->irq_cb = NULL;
@@ -1070,20 +1052,20 @@ init_scanpwr_timeout(struct fp_dev *dev,
if (++urudev->scanpwr_irq_timeouts >= 3) {
fp_err("powerup timed out 3 times, giving up");
fpi_ssm_mark_failed(ssm, -ETIMEDOUT);
fpi_ssm_mark_aborted(ssm, -ETIMEDOUT);
} else {
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 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);
switch (fpi_ssm_get_cur_state(ssm)) {
case INIT_GET_HWSTAT:
sm_read_reg(ssm, dev, REG_HWSTAT);
sm_read_reg(ssm, REG_HWSTAT);
break;
case INIT_CHECK_HWSTAT_REBOOT:
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);
break;
case INIT_REBOOT_POWER: ;
fpi_ssm *rebootsm = fpi_ssm_new(FP_DEV(dev), rebootpwr_run_state,
REBOOTPWR_NUM_STATES, dev);
struct fpi_ssm *rebootsm = fpi_ssm_new(fpi_imgdev_get_dev(dev), rebootpwr_run_state,
REBOOTPWR_NUM_STATES);
fpi_ssm_set_user_data(rebootsm, dev);
fpi_ssm_start_subsm(ssm, rebootsm);
break;
case INIT_CHECK_HWSTAT_POWERDOWN:
if ((urudev->last_hwstat & 0x80) == 0)
sm_set_hwstat(ssm, dev, urudev->last_hwstat | 0x80);
sm_set_hwstat(ssm, urudev->last_hwstat | 0x80);
else
fpi_ssm_next_state(ssm);
break;
case INIT_POWERUP: ;
if (!IRQ_HANDLER_IS_RUNNING(urudev)) {
fpi_ssm_mark_failed(ssm, -EIO);
fpi_ssm_mark_aborted(ssm, -EIO);
break;
}
urudev->irq_cb_data = ssm;
urudev->irq_cb = init_scanpwr_irq_cb;
fpi_ssm *powerupsm = fpi_ssm_new(FP_DEV(dev), powerup_run_state,
POWERUP_NUM_STATES, dev);
struct fpi_ssm *powerupsm = fpi_ssm_new(fpi_imgdev_get_dev(dev), powerup_run_state,
POWERUP_NUM_STATES);
fpi_ssm_set_user_data(powerupsm, dev);
fpi_ssm_start_subsm(ssm, powerupsm);
break;
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
* if we don't get an irq any time soon. */
urudev->scanpwr_irq_timeout = fpi_timeout_add(300,
init_scanpwr_timeout,
_dev, ssm);
init_scanpwr_timeout, ssm);
if (!urudev->scanpwr_irq_timeout) {
fpi_ssm_mark_failed(ssm, -ETIME);
fpi_ssm_mark_aborted(ssm, -ETIME);
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);
break;
case INIT_GET_VERSION:
sm_read_regs(ssm, dev, REG_DEVICE_INFO, 16);
sm_read_regs(ssm, REG_DEVICE_INFO, 16);
break;
case INIT_REPORT_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);
fpi_ssm_free(ssm);
if (r) {
fpi_imgdev_activate_complete(dev, r);
return;
}
r = execute_state_change(dev);
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));
fpi_ssm *ssm;
struct uru4k_dev *urudev = fpi_imgdev_get_user_data(dev);
struct fpi_ssm *ssm;
int r;
r = start_irq_handler(dev);
@@ -1175,7 +1168,9 @@ static int dev_activate(struct fp_img_dev *dev)
return r;
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);
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)
{
struct uru4k_dev *urudev = FP_INSTANCE_DATA(FP_DEV(dev));
fpi_ssm *ssm;
void *img_data;
struct uru4k_dev *urudev = fpi_imgdev_get_user_data(dev);
struct fpi_ssm *ssm;
switch (urudev->activate_state) {
case IMGDEV_STATE_INACTIVE:
@@ -1225,18 +1219,12 @@ static int execute_state_change(struct fp_img_dev *dev)
fp_dbg("starting capture");
urudev->irq_cb = NULL;
ssm = fpi_ssm_new(FP_DEV(dev), imaging_run_state, IMAGING_NUM_STATES, dev);
img_data = g_malloc(sizeof(struct uru4k_image));
urudev->img_transfer = libusb_alloc_transfer(0);
urudev->img_data = g_malloc(sizeof(struct uru4k_image));
urudev->img_enc_seed = rand();
urudev->img_transfer = fpi_usb_fill_bulk_transfer(FP_DEV(dev),
ssm,
EP_DATA,
img_data,
sizeof(struct uru4k_image),
image_transfer_cb,
NULL,
0);
ssm = fpi_ssm_new(fpi_imgdev_get_dev(dev), imaging_run_state, IMAGING_NUM_STATES);
fpi_ssm_set_user_data(ssm, dev);
fpi_ssm_start(ssm, imaging_complete);
return write_reg(dev, REG_MODE, MODE_CAPTURE,
@@ -1269,7 +1257,7 @@ static int dev_init(struct fp_img_dev *dev, unsigned long driver_data)
int r;
/* Find fingerprint interface */
r = libusb_get_config_descriptor(libusb_get_device(fpi_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) {
fp_err("Failed to get config descriptor");
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 */
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) {
fp_err("interface claim failed: %s", libusb_error_name(r));
goto out;
}
/* Disable loading p11-kit's user configuration */
g_setenv ("P11_KIT_NO_USER_CONFIG", "1", TRUE);
/* Initialise NSS early */
rv = NSS_NoDB_Init(".");
if (rv != SECSuccess) {
@@ -1340,8 +1325,6 @@ static int dev_init(struct fp_img_dev *dev, unsigned long driver_data)
}
urudev = g_malloc0(sizeof(*urudev));
fp_dev_set_instance_data(FP_DEV(dev), urudev);
urudev->profile = &uru4k_dev_info[driver_data];
urudev->interface = iface_desc->bInterfaceNumber;
@@ -1368,6 +1351,7 @@ static int dev_init(struct fp_img_dev *dev, unsigned long driver_data)
}
urudev->param = PK11_ParamFromIV(urudev->cipher, NULL);
fpi_imgdev_set_user_data(dev, urudev);
fpi_imgdev_open_complete(dev, 0);
out:
@@ -1377,14 +1361,14 @@ out:
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)
PK11_FreeSymKey (urudev->symkey);
if (urudev->param)
SECITEM_FreeItem(urudev->param, PR_TRUE);
if (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);
fpi_imgdev_close_complete(dev);
}

View File

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

View File

@@ -27,7 +27,7 @@
/* Callback for async_write */
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);
int transferred = transfer->actual_length, error =
@@ -36,14 +36,14 @@ static void async_write_callback(struct libusb_transfer *transfer)
if (error != 0) {
fp_err("USB write transfer: %s", libusb_error_name(error));
fpi_imgdev_session_error(idev, -EIO);
fpi_ssm_mark_failed(ssm, -EIO);
fpi_ssm_mark_aborted(ssm, -EIO);
return;
}
if (transferred != len) {
fp_err("Written only %d of %d bytes", transferred, len);
fpi_imgdev_session_error(idev, -EIO);
fpi_ssm_mark_failed(ssm, -EIO);
fpi_ssm_mark_aborted(ssm, -EIO);
return;
}
@@ -51,16 +51,13 @@ static void async_write_callback(struct libusb_transfer *transfer)
}
/* Send data to EP1, the only out endpoint */
static void
async_write(fpi_ssm *ssm,
struct fp_img_dev *dev,
void *data,
int len)
static void async_write(struct fpi_ssm *ssm, void *data, int len)
{
struct libusb_device_handle *usb_dev = fpi_dev_get_usb_dev(FP_DEV(dev));
struct vfs_dev_t *vdev = FP_INSTANCE_DATA(FP_DEV(dev));
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);
vdev->transfer = fpi_usb_alloc();
vdev->transfer = libusb_alloc_transfer(0);
vdev->transfer->flags |= LIBUSB_TRANSFER_FREE_TRANSFER;
libusb_fill_bulk_transfer(vdev->transfer, usb_dev, 0x01, data, len,
async_write_callback, ssm, VFS_USB_TIMEOUT);
@@ -70,7 +67,7 @@ async_write(fpi_ssm *ssm,
/* Callback for async_read */
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);
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,
libusb_error_name(error));
fpi_imgdev_session_error(idev, -EIO);
fpi_ssm_mark_failed(ssm, -EIO);
fpi_ssm_mark_aborted(ssm, -EIO);
return;
}
if (transferred != len) {
fp_err("Received %d instead of %d bytes", transferred, len);
fpi_imgdev_session_error(idev, -EIO);
fpi_ssm_mark_failed(ssm, -EIO);
fpi_ssm_mark_aborted(ssm, -EIO);
return;
}
@@ -96,20 +93,15 @@ static void async_read_callback(struct libusb_transfer *transfer)
}
/* Receive data from the given ep and compare with expected */
static void
async_read(fpi_ssm *ssm,
struct fp_img_dev *dev,
int ep,
void *data,
int len)
static void async_read(struct fpi_ssm *ssm, int ep, void *data, int len)
{
struct fp_img_dev *idev = fpi_ssm_get_user_data(ssm);
struct libusb_device_handle *usb_dev = fpi_dev_get_usb_dev(FP_DEV(idev));
struct vfs_dev_t *vdev = FP_INSTANCE_DATA(FP_DEV(idev));
struct libusb_device_handle *usb_dev = fpi_imgdev_get_usb_dev(idev);
struct vfs_dev_t *vdev = fpi_imgdev_get_user_data(idev);
ep |= LIBUSB_ENDPOINT_IN;
vdev->transfer = fpi_usb_alloc();
vdev->transfer = libusb_alloc_transfer(0);
vdev->transfer->flags |= LIBUSB_TRANSFER_FREE_TRANSFER;
/* 0x83 is the only interrupt endpoint */
@@ -127,7 +119,7 @@ async_read(fpi_ssm *ssm,
/* Callback for async_read */
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);
int transferred = transfer->actual_length, error = transfer->status;
@@ -142,7 +134,7 @@ static void async_abort_callback(struct libusb_transfer *transfer)
if (error != 0) {
fp_err("USB write transfer: %s", libusb_error_name(error));
fpi_imgdev_session_error(idev, -EIO);
fpi_ssm_mark_failed(ssm, -EIO);
fpi_ssm_mark_aborted(ssm, -EIO);
return;
}
@@ -155,18 +147,18 @@ static void async_abort_callback(struct libusb_transfer *transfer)
}
/* 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 libusb_device_handle *usb_dev = fpi_dev_get_usb_dev(FP_DEV(idev));
struct vfs_dev_t *vdev = FP_INSTANCE_DATA(FP_DEV(idev));
struct libusb_device_handle *usb_dev = fpi_imgdev_get_usb_dev(idev);
struct vfs_dev_t *vdev = fpi_imgdev_get_user_data(idev);
int len = VFS_USB_BUFFER_SIZE;
unsigned char *data = g_malloc(VFS_USB_BUFFER_SIZE);
ep |= LIBUSB_ENDPOINT_IN;
vdev->transfer = fpi_usb_alloc();
vdev->transfer = libusb_alloc_transfer(0);
vdev->transfer->flags |=
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 */
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 */
if (!vdev->active)
@@ -287,21 +279,20 @@ static void submit_image(struct fp_img_dev *idev)
/* Proto functions */
/* SSM loop for clear_ep2 */
static void
clear_ep2_ssm(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
static void clear_ep2_ssm(struct fpi_ssm *ssm)
{
struct fp_img_dev *idev = user_data;
struct fp_img_dev *idev = fpi_ssm_get_user_data(ssm);
short result;
char command04 = 0x04;
switch (fpi_ssm_get_cur_state(ssm)) {
case SUBSM1_COMMAND_04:
async_write(ssm, idev, &command04, sizeof(command04));
async_write(ssm, &command04, sizeof(command04));
break;
case SUBSM1_RETURN_CODE:
async_read(ssm, idev, 1, &result, sizeof(result));
async_read(ssm, 1, &result, sizeof(result));
break;
case SUBSM1_ABORT_2:
@@ -311,35 +302,36 @@ clear_ep2_ssm(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
default:
fp_err("Unknown SUBSM1 state");
fpi_imgdev_session_error(idev, -EIO);
fpi_ssm_mark_failed(ssm, -EIO);
fpi_ssm_mark_aborted(ssm, -EIO);
}
}
/* Send command to clear EP2 */
static void
clear_ep2(fpi_ssm *ssm,
struct fp_img_dev *idev)
static void clear_ep2(struct fpi_ssm *ssm)
{
fpi_ssm *subsm =
fpi_ssm_new(FP_DEV(idev), clear_ep2_ssm, SUBSM1_STATES, idev);
struct fp_img_dev *idev = fpi_ssm_get_user_data(ssm);
struct fpi_ssm *subsm =
fpi_ssm_new(fpi_imgdev_get_dev(idev), clear_ep2_ssm, SUBSM1_STATES);
fpi_ssm_set_user_data(subsm, idev);
fpi_ssm_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 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);
short result;
unsigned char *commit_result = NULL;
switch (fpi_ssm_get_cur_state(ssm)) {
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;
case SUBSM2_RETURN_CODE:
async_read(ssm, idev, 1, &result, sizeof(result));
async_read(ssm, 1, &result, sizeof(result));
break;
case SUBSM2_SEND_COMMIT:
@@ -350,19 +342,19 @@ static void send_control_packet_ssm(fpi_ssm *ssm, struct fp_dev *_dev, void *use
break;
}
/* 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;
case SUBSM2_COMMIT_RESPONSE:
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;
case SUBSM2_READ_EMPTY_INTERRUPT:
/* I don't know how to check result, it could be different */
g_free(commit_result);
async_read(ssm, idev, 3, vdev->interrupt, VFS_INTERRUPT_SIZE);
async_read(ssm, 3, vdev->interrupt, VFS_INTERRUPT_SIZE);
break;
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)) {
fp_err("Unknown SUBSM2 state");
fpi_imgdev_session_error(idev, -EIO);
fpi_ssm_mark_failed(ssm, -EIO);
fpi_ssm_mark_aborted(ssm, -EIO);
break;
}
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:
/* After turn_on Windows doesn't clear EP2 */
if (vdev->control_packet != turn_on)
clear_ep2(ssm, idev);
clear_ep2(ssm);
else
fpi_ssm_next_state(ssm);
break;
@@ -388,17 +380,18 @@ static void send_control_packet_ssm(fpi_ssm *ssm, struct fp_dev *_dev, void *use
default:
fp_err("Unknown SUBSM2 state");
fpi_imgdev_session_error(idev, -EIO);
fpi_ssm_mark_failed(ssm, -EIO);
fpi_ssm_mark_aborted(ssm, -EIO);
}
}
/* Send device state control packet */
static void
send_control_packet(fpi_ssm *ssm,
struct fp_img_dev *idev)
static void send_control_packet(struct fpi_ssm *ssm)
{
fpi_ssm *subsm =
fpi_ssm_new(FP_DEV(idev), send_control_packet_ssm, SUBSM2_STATES, idev);
struct fp_img_dev *idev = fpi_ssm_get_user_data(ssm);
struct fpi_ssm *subsm =
fpi_ssm_new(fpi_imgdev_get_dev(idev), send_control_packet_ssm, SUBSM2_STATES);
fpi_ssm_set_user_data(subsm, idev);
fpi_ssm_start_subsm(ssm, subsm);
}
@@ -413,9 +406,9 @@ static void clear_data(struct vfs_dev_t *vdev)
/* After receiving interrupt from EP3 */
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 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;
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",
libusb_error_name(error));
fpi_imgdev_session_error(idev, -EIO);
fpi_ssm_mark_failed(ssm, -EIO);
fpi_ssm_mark_aborted(ssm, -EIO);
return;
}
@@ -439,7 +432,7 @@ static void interrupt_callback(struct libusb_transfer *transfer)
fp_err("Unknown interrupt size %d", transferred);
/* Abort ssm */
fpi_imgdev_session_error(idev, -EIO);
fpi_ssm_mark_failed(ssm, -EIO);
fpi_ssm_mark_aborted(ssm, -EIO);
return;
}
@@ -468,14 +461,14 @@ static void interrupt_callback(struct libusb_transfer *transfer)
/* Abort ssm */
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)
{
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 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;
@@ -483,7 +476,7 @@ static void receive_callback(struct libusb_transfer *transfer)
fp_err("USB read transfer: %s", libusb_error_name(error));
fpi_imgdev_session_error(idev, -EIO);
fpi_ssm_mark_failed(ssm, -EIO);
fpi_ssm_mark_aborted(ssm, -EIO);
return;
}
@@ -499,12 +492,11 @@ static void receive_callback(struct libusb_transfer *transfer)
}
/* Stub to keep SSM alive when waiting an interrupt */
static void
wait_interrupt(struct fp_dev *dev,
void *data)
static void wait_interrupt(void *data)
{
fpi_ssm *ssm = data;
struct vfs_dev_t *vdev = FP_INSTANCE_DATA(dev);
struct fpi_ssm *ssm = data;
struct fp_img_dev *idev = fpi_ssm_get_user_data(ssm);
struct vfs_dev_t *vdev = fpi_imgdev_get_user_data(idev);
/* Keep sleeping while this flag is on */
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 */
static void
another_scan(struct fp_dev *dev,
void *data)
static void another_scan(void *data)
{
fpi_ssm *ssm = data;
struct fpi_ssm *ssm = data;
fpi_ssm_jump_to_state(ssm, SSM_TURN_ON);
}
/* Main SSM loop */
static void activate_ssm(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
/* Another SSM stub to continue after waiting for probable vdev->active changes */
static void scan_completed(void *data)
{
struct fp_img_dev *idev = user_data;
struct libusb_device_handle *usb_dev = fpi_dev_get_usb_dev(FP_DEV(idev));
struct vfs_dev_t *vdev = FP_INSTANCE_DATA(_dev);
struct fpi_ssm *ssm = data;
fpi_ssm_next_state(ssm);
}
/* 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)) {
case SSM_INITIAL_ABORT_1:
@@ -541,14 +538,14 @@ static void activate_ssm(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
break;
case SSM_CLEAR_EP2:
clear_ep2(ssm, idev);
clear_ep2(ssm);
break;
case SSM_TURN_OFF:
/* Set control_packet argument */
vdev->control_packet = turn_off;
send_control_packet(ssm, idev);
send_control_packet(ssm);
break;
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 */
vdev->control_packet = turn_on;
send_control_packet(ssm, idev);
send_control_packet(ssm);
break;
case SSM_ASK_INTERRUPT:
@@ -578,7 +575,7 @@ static void activate_ssm(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
}
/* Asyncronously enquire an interrupt */
vdev->transfer = fpi_usb_alloc();
vdev->transfer = libusb_alloc_transfer(0);
vdev->transfer->flags |= LIBUSB_TRANSFER_FREE_TRANSFER;
libusb_fill_interrupt_transfer(vdev->transfer, usb_dev, 0x83,
vdev->interrupt,
@@ -604,7 +601,7 @@ static void activate_ssm(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
}
if (vdev->wait_interrupt)
fpi_timeout_add(VFS_SSM_TIMEOUT, wait_interrupt, _dev, ssm);
fpi_timeout_add(VFS_SSM_TIMEOUT, wait_interrupt, ssm);
break;
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 */
vdev->transfer = fpi_usb_alloc();
vdev->transfer = libusb_alloc_transfer(0);
vdev->transfer->flags |= LIBUSB_TRANSFER_FREE_TRANSFER;
libusb_fill_bulk_transfer(vdev->transfer, usb_dev, 0x82,
(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);
/* 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;
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 */
vdev->control_packet = next_receive_1;
send_control_packet(ssm, idev);
send_control_packet(ssm);
break;
case SSM_WAIT_ANOTHER_SCAN:
/* 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;
default:
fp_err("Unknown state");
fpi_imgdev_session_error(idev, -EIO);
fpi_ssm_mark_failed(ssm, -EIO);
fpi_ssm_mark_aborted(ssm, -EIO);
}
}
/* Driver functions */
/* 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;
@@ -684,16 +682,17 @@ static void dev_activate_callback(fpi_ssm *ssm, struct fp_dev *_dev, void *user_
}
/* 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 */
vdev->active = 1;
vdev->need_report = 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);
return 0;
}
@@ -701,7 +700,7 @@ static int dev_activate(struct fp_img_dev *idev)
/* Deactivate device */
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) {
fpi_imgdev_deactivate_complete(idev);
@@ -714,10 +713,10 @@ static void dev_deactivate(struct fp_img_dev *idev)
}
/* 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 */
fpi_imgdev_open_complete(user_data, 0);
fpi_imgdev_open_complete(fpi_ssm_get_user_data(ssm), 0);
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;
/* 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) {
/* Interface not claimed, return error */
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 */
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 */
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);
return 0;
}
@@ -750,11 +750,11 @@ static void dev_close(struct fp_img_dev *idev)
struct vfs_dev_t *vdev;
/* Release private structure */
vdev = FP_INSTANCE_DATA(FP_DEV(idev));
vdev = fpi_imgdev_get_user_data(idev);
g_free(vdev);
/* 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 */
fpi_imgdev_close_complete(idev);

View File

@@ -56,7 +56,7 @@
#define VFS_IMG_MIN_IMAGE_LEVEL 144
/* Best image contrast */
#define VFS_IMG_BEST_CONTRAST 128
#define VFS_IMG_BEST_CONRAST 128
/* Device parameters address */
#define VFS_PAR_000E 0x000e
@@ -105,6 +105,9 @@ struct vfs101_dev
/* Ignore usb error */
int ignore_error;
/* Timeout */
struct fpi_timeout *timeout;
/* Loop counter */
int counter;
@@ -196,9 +199,9 @@ static int result_code(struct fp_img_dev *dev, int result)
/* Callback of asynchronous send */
static void async_send_cb(struct libusb_transfer *transfer)
{
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 vfs101_dev *vdev = FP_INSTANCE_DATA(FP_DEV(dev));
struct vfs101_dev *vdev = fpi_imgdev_get_user_data(dev);
/* Cleanup transfer */
vdev->transfer = NULL;
@@ -211,7 +214,7 @@ static void async_send_cb(struct libusb_transfer *transfer)
/* Transfer not completed, return IO error */
fp_err("transfer not completed, status = %d", transfer->status);
fpi_imgdev_session_error(dev, -EIO);
fpi_ssm_mark_failed(ssm, -EIO);
fpi_ssm_mark_aborted(ssm, -EIO);
goto out;
}
@@ -221,7 +224,7 @@ static void async_send_cb(struct libusb_transfer *transfer)
fp_err("length mismatch, got %d, expected %d",
transfer->actual_length, transfer->length);
fpi_imgdev_session_error(dev, -EIO);
fpi_ssm_mark_failed(ssm, -EIO);
fpi_ssm_mark_aborted(ssm, -EIO);
goto out;
}
}
@@ -239,15 +242,22 @@ out:
}
/* Submit asynchronous send */
static void
async_send(fpi_ssm *ssm,
struct fp_img_dev *dev)
static void async_send(struct fpi_ssm *ssm)
{
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;
/* 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 */
vdev->seqnum++;
@@ -255,7 +265,7 @@ async_send(fpi_ssm *ssm,
vdev->buffer[1] = byte(1, vdev->seqnum);
/* 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 */
r = libusb_submit_transfer(vdev->transfer);
@@ -265,7 +275,7 @@ async_send(fpi_ssm *ssm,
libusb_free_transfer(vdev->transfer);
fp_err("submit of usb transfer failed");
fpi_imgdev_session_error(dev, -EIO);
fpi_ssm_mark_failed(ssm, -EIO);
fpi_ssm_mark_aborted(ssm, -EIO);
return;
}
}
@@ -273,9 +283,9 @@ async_send(fpi_ssm *ssm,
/* Callback of asynchronous recv */
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 vfs101_dev *vdev = FP_INSTANCE_DATA(FP_DEV(dev));
struct vfs101_dev *vdev = fpi_imgdev_get_user_data(dev);
/* Cleanup transfer */
vdev->transfer = NULL;
@@ -288,7 +298,7 @@ static void async_recv_cb(struct libusb_transfer *transfer)
/* Transfer not completed, return IO error */
fp_err("transfer not completed, status = %d", transfer->status);
fpi_imgdev_session_error(dev, -EIO);
fpi_ssm_mark_failed(ssm, -EIO);
fpi_ssm_mark_aborted(ssm, -EIO);
goto out;
}
@@ -298,7 +308,7 @@ static void async_recv_cb(struct libusb_transfer *transfer)
fp_err("seqnum mismatch, got %04x, expected %04x",
get_seqnum(vdev->buffer[1], vdev->buffer[0]), vdev->seqnum);
fpi_imgdev_session_error(dev, -EIO);
fpi_ssm_mark_failed(ssm, -EIO);
fpi_ssm_mark_aborted(ssm, -EIO);
goto out;
}
}
@@ -319,18 +329,25 @@ out:
}
/* Submit asynchronous recv */
static void
async_recv(fpi_ssm *ssm,
struct fp_img_dev *dev)
static void async_recv(struct fpi_ssm *ssm)
{
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;
/* 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 */
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 */
r = libusb_submit_transfer(vdev->transfer);
@@ -340,19 +357,19 @@ async_recv(fpi_ssm *ssm,
libusb_free_transfer(vdev->transfer);
fp_err("submit of usb transfer failed");
fpi_imgdev_session_error(dev, -EIO);
fpi_ssm_mark_failed(ssm, -EIO);
fpi_ssm_mark_aborted(ssm, -EIO);
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 */
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 vfs101_dev *vdev = FP_INSTANCE_DATA(FP_DEV(dev));
struct vfs101_dev *vdev = fpi_imgdev_get_user_data(dev);
/* Cleanup transfer */
vdev->transfer = NULL;
@@ -365,7 +382,7 @@ static void async_load_cb(struct libusb_transfer *transfer)
/* Transfer not completed */
fp_err("transfer not completed, status = %d, length = %d", transfer->status, vdev->length);
fpi_imgdev_session_error(dev, -EIO);
fpi_ssm_mark_failed(ssm, -EIO);
fpi_ssm_mark_aborted(ssm, -EIO);
goto out;
}
@@ -374,7 +391,7 @@ static void async_load_cb(struct libusb_transfer *transfer)
/* Received incomplete frame, return protocol error */
fp_err("received incomplete frame");
fpi_imgdev_session_error(dev, -EIO);
fpi_ssm_mark_failed(ssm, -EIO);
fpi_ssm_mark_aborted(ssm, -EIO);
goto out;
}
}
@@ -389,12 +406,12 @@ static void async_load_cb(struct libusb_transfer *transfer)
/* Buffer full, image too large, return no memory error */
fp_err("buffer full, image too large");
fpi_imgdev_session_error(dev, -ENOMEM);
fpi_ssm_mark_failed(ssm, -ENOMEM);
fpi_ssm_mark_aborted(ssm, -ENOMEM);
goto out;
}
else
/* Image load not completed, submit another asynchronous load */
async_load(ssm, dev);
async_load(ssm);
}
else
{
@@ -413,22 +430,29 @@ out:
}
/* Submit asynchronous load */
static void
async_load(fpi_ssm *ssm,
struct fp_img_dev *dev)
static void async_load(struct fpi_ssm *ssm)
{
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;
int r;
/* 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 */
buffer = vdev->buffer + vdev->length;
/* 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 */
r = libusb_submit_transfer(vdev->transfer);
@@ -438,23 +462,39 @@ async_load(fpi_ssm *ssm,
libusb_free_transfer(vdev->transfer);
fp_err("submit of usb transfer failed");
fpi_imgdev_session_error(dev, -EIO);
fpi_ssm_mark_failed(ssm, -EIO);
fpi_ssm_mark_aborted(ssm, -EIO);
return;
}
}
/* Submit asynchronous sleep */
static void
async_sleep(unsigned int msec,
fpi_ssm *ssm,
struct fp_img_dev *dev)
/* Callback of asynchronous sleep */
static void async_sleep_cb(void *data)
{
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 */
fp_err("failed to add timeout");
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 */
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))
{
case M_SWAP_SEND:
/* Send data */
async_send(ssm, user_data);
async_send(ssm);
break;
case M_SWAP_RECV:
/* Recv response */
async_recv(ssm, user_data);
async_recv(ssm);
break;
}
}
/* Start swap sequential state machine */
static void
m_swap(fpi_ssm *ssm,
struct fp_img_dev *dev,
unsigned char *data,
size_t length)
static void m_swap(struct fpi_ssm *ssm, unsigned char *data, size_t length)
{
struct vfs101_dev *vdev = FP_INSTANCE_DATA(FP_DEV(dev));
fpi_ssm *subsm;
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct vfs101_dev *vdev = fpi_imgdev_get_user_data(dev);
struct fpi_ssm *subsm;
/* Prepare data for sending */
memcpy(vdev->buffer, data, length);
@@ -499,16 +536,13 @@ m_swap(fpi_ssm *ssm,
vdev->length = length;
/* 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);
}
/* Retrieve fingerprint image */
static void
vfs_get_print(fpi_ssm *ssm,
struct fp_img_dev *dev,
unsigned int param,
int type)
static void vfs_get_print(struct fpi_ssm *ssm, unsigned int param, int type)
{
unsigned char data[2][0x0e] = {
{ 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00,
@@ -524,15 +558,11 @@ vfs_get_print(fpi_ssm *ssm,
data[type][7] = byte(1, param);
/* 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 */
static void
vfs_set_param(fpi_ssm *ssm,
struct fp_img_dev *dev,
unsigned int param,
unsigned int value)
static void vfs_set_param(struct fpi_ssm *ssm, unsigned int param, unsigned int value)
{
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);
/* Run swap sequential state machine */
m_swap(ssm, dev, data, 0x0a);
m_swap(ssm, data, 0x0a);
}
/* Abort previous print */
static void
vfs_abort_print(fpi_ssm *ssm,
struct fp_img_dev *dev)
static void vfs_abort_print(struct fpi_ssm *ssm)
{
unsigned char data[0x06] = { 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00 };
G_DEBUG_HERE();
/* Run swap sequential state machine */
m_swap (ssm, dev, data, 0x06);
m_swap (ssm, data, 0x06);
}
/* Poke a value on a region */
static void
vfs_poke(fpi_ssm *ssm,
struct fp_img_dev *dev,
unsigned int addr,
unsigned int value,
unsigned int size)
static void vfs_poke(struct fpi_ssm *ssm, 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 };
@@ -585,28 +608,25 @@ vfs_poke(fpi_ssm *ssm,
data[14] = byte(0, size);
/* Run swap sequential state machine */
m_swap(ssm, dev, data, 0x0f);
m_swap(ssm, data, 0x0f);
}
/* Get current finger state */
static void
vfs_get_finger_state(fpi_ssm *ssm,
struct fp_img_dev *dev)
static void vfs_get_finger_state(struct fpi_ssm *ssm)
{
unsigned char data[0x06] = { 0x00, 0x00, 0x00, 0x00, 0x16, 0x00 };
G_DEBUG_HERE();
/* Run swap sequential state machine */
m_swap (ssm, dev, data, 0x06);
m_swap (ssm, data, 0x06);
}
/* Load raw image from reader */
static void
vfs_img_load(fpi_ssm *ssm,
struct fp_img_dev *dev)
static void vfs_img_load(struct fpi_ssm *ssm)
{
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();
@@ -618,16 +638,16 @@ vfs_img_load(fpi_ssm *ssm,
vdev->height = -1;
/* Asynchronous load */
async_load(ssm, dev);
async_load(ssm);
}
/* Check if action is completed */
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) &&
(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 */
return FALSE;
@@ -734,11 +754,10 @@ static void img_copy(struct vfs101_dev *vdev, struct fp_img *img)
}
/* Extract fingerpint image from raw data */
static void
img_extract(fpi_ssm *ssm,
struct fp_img_dev *dev)
static void img_extract(struct fpi_ssm *ssm)
{
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;
/* Screen image to remove noise and find top and bottom line */
@@ -767,11 +786,6 @@ img_extract(fpi_ssm *ssm,
/* Notify image captured */
fpi_imgdev_image_captured(dev, img);
/* FIXME
* What is this for? The action result, and the enroll stages should
* already be handled in fpi_imgdev_image_captured()
*/
/* Check captured result */
if (fpi_imgdev_get_action_result(dev) >= 0 &&
fpi_imgdev_get_action_result(dev) != FP_ENROLL_RETRY &&
@@ -856,7 +870,7 @@ static void vfs_check_contrast(struct vfs101_dev *vdev)
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 */
vdev->best_contrast = vdev->contrast;
@@ -898,10 +912,10 @@ enum
};
/* 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 vfs101_dev *vdev = FP_INSTANCE_DATA(_dev);
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct vfs101_dev *vdev = fpi_imgdev_get_user_data(dev);
/* Check action state */
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:
/* 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;
case M_LOOP_0_SLEEP:
/* Wait fingerprint scanning */
async_sleep(50, ssm, dev);
async_sleep(50, ssm);
break;
case M_LOOP_0_GET_STATE:
/* Get finger state */
vfs_get_finger_state(ssm, dev);
vfs_get_finger_state(ssm);
break;
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:
/* Load image from reader */
vdev->ignore_error = TRUE;
vfs_img_load(ssm, dev);
vfs_img_load(ssm);
break;
default:
/* Unknown state */
fp_err("unknown device state 0x%02x", vdev->buffer[0x0a]);
fpi_imgdev_session_error(dev, -EIO);
fpi_ssm_mark_failed(ssm, -EIO);
fpi_ssm_mark_aborted(ssm, -EIO);
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 */
if (vdev->height > 0)
/* Fingerprint is loaded, extract image from raw data */
img_extract(ssm, dev);
img_extract(ssm);
/* Wait handling image */
async_sleep(10, ssm, dev);
async_sleep(10, ssm);
break;
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:
/* Get finger state */
vfs_get_finger_state(ssm, dev);
vfs_get_finger_state(ssm);
break;
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 */
vdev->counter++;
async_sleep(250, ssm, dev);
async_sleep(250, ssm);
}
else
{
/* reach max loop counter, return protocol error */
fp_err("finger not removed from the scanner");
fpi_imgdev_session_error(dev, -EIO);
fpi_ssm_mark_failed(ssm, -EIO);
fpi_ssm_mark_aborted(ssm, -EIO);
}
}
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:
/* 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;
case M_LOOP_1_LOAD_IMAGE:
/* Load image */
vdev->ignore_error = TRUE;
vfs_img_load(ssm, dev);
vfs_img_load(ssm);
break;
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:
/* Wait fingerprint scanning */
async_sleep(10, ssm, dev);
async_sleep(10, ssm);
break;
case M_LOOP_2_ABORT_PRINT:
/* Abort print command */
vfs_abort_print(ssm, dev);
vfs_abort_print(ssm);
break;
case M_LOOP_2_LOAD_IMAGE:
/* Load abort image */
vdev->ignore_error = TRUE;
vfs_img_load(ssm, dev);
vfs_img_load(ssm);
break;
case M_LOOP_3_GET_PRINT:
/* Get empty image */
vfs_get_print(ssm, dev, 0x000a, 0);
vfs_get_print(ssm, 0x000a, 0);
break;
case M_LOOP_3_LOAD_IMAGE:
/* Load abort image */
vdev->ignore_error = TRUE;
vfs_img_load(ssm, dev);
vfs_img_load(ssm);
break;
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 */
vdev->counter++;
async_sleep(100, ssm, dev);
async_sleep(100, ssm);
}
else
{
/* reach max loop counter, return protocol error */
fp_err("waiting abort reach max loop counter");
fpi_imgdev_session_error(dev, -EIO);
fpi_ssm_mark_failed(ssm, -EIO);
fpi_ssm_mark_aborted(ssm, -EIO);
}
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 */
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 */
fpi_ssm_free(ssm);
@@ -1162,10 +1176,10 @@ enum
};
/* 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 vfs101_dev *vdev = FP_INSTANCE_DATA(_dev);
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct vfs101_dev *vdev = fpi_imgdev_get_user_data(dev);
/* Check action state */
if (!vdev->active)
@@ -1180,29 +1194,29 @@ static void m_init_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
case M_INIT_0_RECV_DIRTY:
/* Recv eventualy dirty data */
vdev->ignore_error = TRUE;
async_recv(ssm, dev);
async_recv(ssm);
break;
case M_INIT_0_ABORT_PRINT:
/* Abort print command */
vfs_abort_print(ssm, dev);
vfs_abort_print(ssm);
break;
case M_INIT_0_LOAD_IMAGE:
/* Load abort image */
vdev->ignore_error = TRUE;
vfs_img_load(ssm, dev);
vfs_img_load(ssm);
break;
case M_INIT_1_GET_PRINT:
/* Get empty image */
vfs_get_print(ssm, dev, 0x000a, 0);
vfs_get_print(ssm, 0x000a, 0);
break;
case M_INIT_1_LOAD_IMAGE:
/* Load abort image */
vdev->ignore_error = TRUE;
vfs_img_load(ssm, dev);
vfs_img_load(ssm);
break;
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 */
vdev->counter++;
async_sleep(100, ssm, dev);
async_sleep(100, ssm);
}
else
{
/* reach max loop counter, return protocol error */
fp_err("waiting abort reach max loop counter");
fpi_imgdev_session_error(dev, -EIO);
fpi_ssm_mark_failed(ssm, -EIO);
fpi_ssm_mark_aborted(ssm, -EIO);
}
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:
/* Get finger state */
vfs_get_finger_state(ssm, dev);
vfs_get_finger_state(ssm);
break;
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 */
vdev->counter++;
async_sleep(250, ssm, dev);
async_sleep(250, ssm);
}
else
{
/* reach max loop counter, return protocol error */
fp_err("finger not removed from the scanner");
fpi_imgdev_session_error(dev, -EIO);
fpi_ssm_mark_failed(ssm, -EIO);
fpi_ssm_mark_aborted(ssm, -EIO);
}
}
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:
/* 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;
case M_INIT_2_LOAD_IMAGE:
/* Load unexpected image */
vdev->ignore_error = TRUE;
vfs_img_load(ssm, dev);
vfs_img_load(ssm);
break;
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:
/* 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;
case M_INIT_3_SET_0011:
/* 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;
case M_INIT_3_SET_0076:
/* 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;
case M_INIT_3_SET_0078:
/* 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;
case M_INIT_3_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;
case M_INIT_3_SET_STATE3_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;
case M_INIT_3_SET_STATE5_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;
case M_INIT_3_SET_INFO_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;
case M_INIT_3_SET_INFO_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;
case M_INIT_4_SET_EXPOSURE:
/* 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;
break;
case M_INIT_4_SET_CONTRAST:
/* 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;
case M_INIT_4_GET_PRINT:
/* Get empty image */
vfs_get_print(ssm, dev, 0x000a, 0);
vfs_get_print(ssm, 0x000a, 0);
break;
case M_INIT_4_LOAD_IMAGE:
/* Load empty image */
vfs_img_load(ssm, dev);
vfs_img_load(ssm);
break;
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:
/* 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;
case M_INIT_5_SET_CONTRAST:
/* 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;
case M_INIT_5_SET_INFO_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;
case M_INIT_5_SET_INFO_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;
}
}
/* 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 vfs101_dev *vdev = FP_INSTANCE_DATA(_dev);
fpi_ssm *ssm_loop;
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct vfs101_dev *vdev = fpi_imgdev_get_user_data(dev);
struct fpi_ssm *ssm_loop;
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);
/* 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);
}
@@ -1424,10 +1439,10 @@ static void m_init_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
}
/* 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));
fpi_ssm *ssm;
struct vfs101_dev *vdev = fpi_imgdev_get_user_data(dev);
struct fpi_ssm *ssm;
/* Check if already active */
if (vdev->active)
@@ -1449,7 +1464,8 @@ static int dev_activate(struct fp_img_dev *dev)
vdev->enroll_stage = 0;
/* 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);
return 0;
@@ -1458,13 +1474,13 @@ static int dev_activate(struct fp_img_dev *dev)
/* Deactivate device */
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 */
vdev->active = FALSE;
/* Handle eventualy existing events */
while (vdev->transfer)
while (vdev->transfer || vdev->timeout)
fp_handle_events();
/* Notify deactivate complete */
@@ -1478,7 +1494,7 @@ static int dev_open(struct fp_img_dev *dev, unsigned long driver_data)
int r;
/* 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)
{
/* 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 */
vdev = g_malloc0(sizeof(struct vfs101_dev));
vdev->seqnum = -1;
fp_dev_set_instance_data(FP_DEV(dev), vdev);
fpi_imgdev_set_user_data(dev, vdev);
/* Notify open complete */
fpi_imgdev_open_complete(dev, 0);
@@ -1503,11 +1519,11 @@ static void dev_close(struct fp_img_dev *dev)
struct vfs101_dev *vdev;
/* Release private structure */
vdev = FP_INSTANCE_DATA(FP_DEV(dev));
vdev = fpi_imgdev_get_user_data(dev);
g_free(vdev);
/* 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 */
fpi_imgdev_close_complete(dev);

View File

@@ -26,26 +26,35 @@
/************************** GENERIC STUFF *************************************/
/* Submit asynchronous sleep */
static void
async_sleep(unsigned int msec,
fpi_ssm *ssm,
struct fp_img_dev *dev)
/* Callback of asynchronous sleep */
static void async_sleep_cb(void *data)
{
struct fpi_ssm *ssm = data;
fpi_ssm_next_state(ssm);
}
/* Submit asynchronous sleep */
static void async_sleep(unsigned int msec, struct fpi_ssm *ssm)
{
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct fpi_timeout *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 */
fp_err("failed to add timeout");
fpi_imgdev_session_error(dev, -ETIME);
fpi_ssm_mark_failed(ssm, -ETIME);
fpi_ssm_mark_aborted(ssm, -ETIME);
}
}
static int
submit_image(fpi_ssm *ssm,
struct fp_img_dev *dev)
static int submit_image(struct fpi_ssm *ssm)
{
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;
struct fp_img *img;
@@ -71,7 +80,7 @@ submit_image(fpi_ssm *ssm,
img->width = VFS301_FP_OUTPUT_WIDTH;
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);
return 1;
@@ -94,24 +103,24 @@ enum
};
/* 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;
vfs301_dev_t *vdev = FP_INSTANCE_DATA(_dev);
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
vfs301_dev_t *vdev = fpi_imgdev_get_user_data(dev);
switch (fpi_ssm_get_cur_state(ssm)) {
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);
break;
case M_WAIT_PRINT:
/* Wait fingerprint scanning */
async_sleep(200, ssm, dev);
async_sleep(200, ssm);
break;
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);
else
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:
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);
break;
case M_READ_PRINT_WAIT:
/* Wait fingerprint scanning */
async_sleep(200, ssm, dev);
async_sleep(200, ssm);
break;
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);
if (rv == VFS301_ONGOING)
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;
case M_SUBMIT_PRINT:
if (submit_image(ssm, dev)) {
if (submit_image(ssm)) {
fpi_ssm_mark_completed(ssm);
/* NOTE: finger off is expected only after submitting image... */
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 */
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 */
fpi_ssm_free(ssm);
}
/* 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;
vfs301_dev_t *vdev = FP_INSTANCE_DATA(_dev);
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
vfs301_dev_t *vdev = fpi_imgdev_get_user_data(dev);
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);
}
/* 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;
fpi_ssm *ssm_loop;
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct fpi_ssm *ssm_loop;
if (!fpi_ssm_get_error(ssm)) {
/* Notify activate complete */
fpi_imgdev_activate_complete(dev, 0);
/* Start loop ssm */
ssm_loop = fpi_ssm_new(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);
}
@@ -191,12 +201,13 @@ static void m_init_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
}
/* 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 */
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);
return 0;
@@ -205,10 +216,6 @@ static int dev_activate(struct fp_img_dev *dev)
/* Deactivate device */
static void dev_deactivate(struct fp_img_dev *dev)
{
vfs301_dev_t *vdev;
vdev = FP_INSTANCE_DATA(FP_DEV(dev));
vfs301_proto_deinit(fpi_dev_get_usb_dev(FP_DEV(dev)), vdev);
fpi_imgdev_deactivate_complete(dev);
}
@@ -218,7 +225,7 @@ static int dev_open(struct fp_img_dev *dev, unsigned long driver_data)
int r;
/* 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) {
/* Interface not claimed, return error */
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 */
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_count = 0;
@@ -243,12 +250,12 @@ static void dev_close(struct fp_img_dev *dev)
vfs301_dev_t *vdev;
/* Release private structure */
vdev = FP_INSTANCE_DATA(FP_DEV(dev));
vdev = fpi_imgdev_get_user_data(dev);
free(vdev->scanline_buf);
g_free(vdev);
/* 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 */
fpi_imgdev_close_complete(dev);

View File

@@ -33,8 +33,8 @@
#include <unistd.h>
#include <stdlib.h>
#include <glib.h>
#include <libusb-1.0/libusb.h>
#include "fpi-usb.h"
#include "vfs301_proto.h"
#include "vfs301_proto_fragments.h"
@@ -499,7 +499,12 @@ void vfs301_proto_process_event_start(
USB_RECV(VFS301_RECEIVE_ENDPOINT_DATA, 64);
/* 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_exp_amt = VFS301_FP_RECV_LEN_1;

View File

@@ -75,14 +75,14 @@ static void start_scan(struct fp_img_dev *dev);
static void async_send_cb(struct libusb_transfer *transfer)
{
fpi_ssm *ssm = transfer->user_data;
struct fpi_ssm *ssm = transfer->user_data;
struct usbexchange_data *data = fpi_ssm_get_user_data(ssm);
struct usb_action *action;
if (fpi_ssm_get_cur_state(ssm) >= data->stepcount) {
fp_err("Radiation detected!");
fpi_imgdev_session_error(data->device, -EINVAL);
fpi_ssm_mark_failed(ssm, -EINVAL);
fpi_ssm_mark_aborted(ssm, -EINVAL);
goto out;
}
@@ -90,7 +90,7 @@ static void async_send_cb(struct libusb_transfer *transfer)
if (action->type != ACTION_SEND) {
fp_err("Radiation detected!");
fpi_imgdev_session_error(data->device, -EINVAL);
fpi_ssm_mark_failed(ssm, -EINVAL);
fpi_ssm_mark_aborted(ssm, -EINVAL);
goto out;
}
@@ -98,7 +98,7 @@ static void async_send_cb(struct libusb_transfer *transfer)
/* Transfer not completed, return IO error */
fp_err("transfer not completed, status = %d", transfer->status);
fpi_imgdev_session_error(data->device, -EIO);
fpi_ssm_mark_failed(ssm, -EIO);
fpi_ssm_mark_aborted(ssm, -EIO);
goto out;
}
if (transfer->length != transfer->actual_length) {
@@ -106,7 +106,7 @@ static void async_send_cb(struct libusb_transfer *transfer)
fp_err("length mismatch, got %d, expected %d",
transfer->actual_length, transfer->length);
fpi_imgdev_session_error(data->device, -EIO);
fpi_ssm_mark_failed(ssm, -EIO);
fpi_ssm_mark_aborted(ssm, -EIO);
goto out;
}
@@ -119,7 +119,7 @@ out:
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 usb_action *action;
@@ -127,14 +127,14 @@ static void async_recv_cb(struct libusb_transfer *transfer)
/* Transfer not completed, return IO error */
fp_err("transfer not completed, status = %d", transfer->status);
fpi_imgdev_session_error(data->device, -EIO);
fpi_ssm_mark_failed(ssm, -EIO);
fpi_ssm_mark_aborted(ssm, -EIO);
goto out;
}
if (fpi_ssm_get_cur_state(ssm) >= data->stepcount) {
fp_err("Radiation detected!");
fpi_imgdev_session_error(data->device, -EINVAL);
fpi_ssm_mark_failed(ssm, -EINVAL);
fpi_ssm_mark_aborted(ssm, -EINVAL);
goto out;
}
@@ -142,7 +142,7 @@ static void async_recv_cb(struct libusb_transfer *transfer)
if (action->type != ACTION_RECEIVE) {
fp_err("Radiation detected!");
fpi_imgdev_session_error(data->device, -EINVAL);
fpi_ssm_mark_failed(ssm, -EINVAL);
fpi_ssm_mark_aborted(ssm, -EINVAL);
goto out;
}
@@ -152,14 +152,14 @@ static void async_recv_cb(struct libusb_transfer *transfer)
transfer->actual_length,
action->correct_reply_size);
fpi_imgdev_session_error(data->device, -EIO);
fpi_ssm_mark_failed(ssm, -EIO);
fpi_ssm_mark_aborted(ssm, -EIO);
goto out;
}
if (memcmp(transfer->buffer, action->data,
action->correct_reply_size) != 0) {
fp_dbg("Wrong reply:");
fpi_imgdev_session_error(data->device, -EIO);
fpi_ssm_mark_failed(ssm, -EIO);
fpi_ssm_mark_aborted(ssm, -EIO);
goto out;
}
} else
@@ -171,14 +171,14 @@ out:
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) {
fp_err("Bug detected: state %d out of range, only %d steps",
fpi_ssm_get_cur_state(ssm), data->stepcount);
fpi_imgdev_session_error(data->device, -EINVAL);
fpi_ssm_mark_failed(ssm, -EINVAL);
fpi_ssm_mark_aborted(ssm, -EINVAL);
return;
}
@@ -189,8 +189,14 @@ static void usbexchange_loop(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
switch (action->type) {
case ACTION_SEND:
fp_dbg("Sending %s", action->name);
transfer = fpi_usb_alloc();
libusb_fill_bulk_transfer(transfer, fpi_dev_get_usb_dev(FP_DEV(data->device)),
transfer = libusb_alloc_transfer(0);
if (transfer == NULL) {
fp_err("Failed to allocate transfer");
fpi_imgdev_session_error(data->device, -ENOMEM);
fpi_ssm_mark_aborted(ssm, -ENOMEM);
return;
}
libusb_fill_bulk_transfer(transfer, fpi_imgdev_get_usb_dev(data->device),
action->endpoint, action->data,
action->size, async_send_cb, ssm,
data->timeout);
@@ -199,8 +205,14 @@ static void usbexchange_loop(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
case ACTION_RECEIVE:
fp_dbg("Receiving %d bytes", action->size);
transfer = fpi_usb_alloc();
libusb_fill_bulk_transfer(transfer, fpi_dev_get_usb_dev(FP_DEV(data->device)),
transfer = libusb_alloc_transfer(0);
if (transfer == NULL) {
fp_err("Failed to allocate transfer");
fpi_imgdev_session_error(data->device, -ENOMEM);
fpi_ssm_mark_aborted(ssm, -ENOMEM);
return;
}
libusb_fill_bulk_transfer(transfer, fpi_imgdev_get_usb_dev(data->device),
action->endpoint, data->receive_buf,
action->size, async_recv_cb, ssm,
data->timeout);
@@ -210,24 +222,24 @@ static void usbexchange_loop(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
default:
fp_err("Bug detected: invalid action %d", action->type);
fpi_imgdev_session_error(data->device, -EINVAL);
fpi_ssm_mark_failed(ssm, -EINVAL);
fpi_ssm_mark_aborted(ssm, -EINVAL);
return;
}
if (ret != 0) {
fp_err("USB transfer error: %s", strerror(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)
{
fpi_ssm *subsm = fpi_ssm_new(FP_DEV(data->device),
usbexchange_loop,
data->stepcount,
data);
struct fpi_ssm *subsm = fpi_ssm_new(fpi_imgdev_get_dev(data->device),
usbexchange_loop,
data->stepcount);
fpi_ssm_set_user_data(subsm, data);
fpi_ssm_start_subsm(ssm, subsm);
}
@@ -383,11 +395,9 @@ static int process_chunk(struct vfs5011_data *data, int transferred)
return 0;
}
static void
submit_image(fpi_ssm *ssm,
struct vfs5011_data *data,
struct fp_img_dev *dev)
void submit_image(struct fpi_ssm *ssm, struct vfs5011_data *data)
{
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct fp_img *img;
if (data->lines_recorded == 0) {
@@ -412,11 +422,11 @@ submit_image(fpi_ssm *ssm,
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 vfs5011_data *data;
data = FP_INSTANCE_DATA(FP_DEV(dev));
data = fpi_imgdev_get_user_data(dev);
if ((transfer->status == LIBUSB_TRANSFER_COMPLETED) ||
(transfer->status == LIBUSB_TRANSFER_TIMED_OUT)) {
@@ -431,7 +441,7 @@ static void chunk_capture_callback(struct libusb_transfer *transfer)
} else {
if (!data->deactivating) {
fp_err("Failed to capture data");
fpi_ssm_mark_failed(ssm, -1);
fpi_ssm_mark_aborted(ssm, -1);
} else {
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,
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",
nline, data->lines_recorded);
@@ -452,7 +462,7 @@ static int capture_chunk_async(struct vfs5011_data *data,
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,
data->capture_buffer,
nline * VFS5011_LINE_SIZE,
@@ -460,6 +470,13 @@ static int capture_chunk_async(struct vfs5011_data *data,
return libusb_submit_transfer(data->flying_transfer);
}
static void async_sleep_cb(void *data)
{
struct fpi_ssm *ssm = data;
fpi_ssm_next_state(ssm);
}
/*
* Device initialization. Windows driver only does it when the device is
* plugged in, but it doesn't harm to do this every time before scanning the
@@ -648,16 +665,16 @@ struct usb_action vfs5011_initiate_capture[] = {
/* ====================== 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};
struct fp_img_dev *dev = user_data;
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
struct vfs5011_data *data;
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));
@@ -690,23 +707,23 @@ static void activate_loop(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
break;
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);
if (r != 0) {
fp_err("Failed to capture data");
fpi_imgdev_session_error(dev, r);
fpi_ssm_mark_failed(ssm, r);
fpi_ssm_mark_aborted(ssm, r);
}
break;
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) {
/* Failed to add timeout */
fp_err("failed to add timeout");
fpi_imgdev_session_error(dev, -1);
fpi_ssm_mark_failed(ssm, -1);
fpi_ssm_mark_aborted(ssm, -1);
}
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;
int r = fpi_ssm_get_error(ssm);
data = FP_INSTANCE_DATA(_dev);
data = fpi_imgdev_get_user_data(dev);
fp_dbg("finishing");
if (data->init_sequence.receive_buf != NULL)
g_free(data->init_sequence.receive_buf);
data->init_sequence.receive_buf = NULL;
if (!data->deactivating && !r) {
submit_image(ssm, data, dev);
submit_image(ssm, data);
fpi_imgdev_report_finger_status(dev, FALSE);
}
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;
data = FP_INSTANCE_DATA(_dev);
data = fpi_imgdev_get_user_data(dev);
switch (fpi_ssm_get_cur_state(ssm)) {
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;
data = FP_INSTANCE_DATA(_dev);
data = fpi_imgdev_get_user_data(dev);
g_free(data->init_sequence.receive_buf);
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->capture_buffer =
(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) {
fp_err("Failed to reset the device");
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) {
fp_err("Failed to claim interface: %s", libusb_error_name(r));
return r;
}
fpi_ssm *ssm;
ssm = fpi_ssm_new(FP_DEV(dev), open_loop, DEV_OPEN_NUM_STATES, dev);
struct fpi_ssm *ssm;
ssm = fpi_ssm_new(fpi_imgdev_get_dev(dev), open_loop, DEV_OPEN_NUM_STATES);
fpi_ssm_set_user_data(ssm, dev);
fpi_ssm_start(ssm, open_loop_complete);
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)
{
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;
data = FP_INSTANCE_DATA(FP_DEV(dev));
data = fpi_imgdev_get_user_data(dev);
if (data != NULL) {
g_free(data->capture_buffer);
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)
{
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;
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");
fpi_ssm_start(ssm, activate_loop_complete);
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;
data = FP_INSTANCE_DATA(FP_DEV(dev));
data = fpi_imgdev_get_user_data(dev);
fp_dbg("device initialized");
data->deactivating = FALSE;
@@ -864,7 +883,7 @@ static void dev_deactivate(struct fp_img_dev *dev)
int r;
struct vfs5011_data *data;
data = FP_INSTANCE_DATA(FP_DEV(dev));
data = fpi_imgdev_get_user_data(dev);
if (data->loop_running) {
data->deactivating = TRUE;
if (data->flying_transfer) {
@@ -879,7 +898,6 @@ static void dev_deactivate(struct fp_img_dev *dev)
static const struct usb_id id_table[] = {
{ .vendor = 0x138a, .product = 0x0010 /* Validity device from some Toshiba laptops */ },
{ .vendor = 0x138a, .product = 0x0011 /* vfs5011 */ },
{ .vendor = 0x138a, .product = 0x0015 /* Validity device from Lenovo Preferred Pro USB Fingerprint Keyboard KUF1256 */ },
{ .vendor = 0x138a, .product = 0x0017 /* Validity device from Lenovo T440 laptops */ },
{ .vendor = 0x138a, .product = 0x0018 /* one more Validity device */ },
{ 0, 0, 0, },

View File

@@ -23,17 +23,282 @@
#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 "fpi-log.h"
#include "fpi-dev.h"
#include "fpi-dev-img.h"
#include "fpi-core.h"
#include "fpi-ssm.h"
#include "fpi-poll.h"
#include "fpi-dev.h"
#include "fpi-usb.h"
#include "fpi-img.h"
#include "fpi-assembling.h"
#include "assembling.h"
#include "drivers/driver_ids.h"
#define fp_dbg g_debug
#define fp_info g_debug
#define fp_warn g_warning
#define fp_err g_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

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>
#ifdef FP_COMPONENT
#undef G_LOG_DOMAIN
#define G_LOG_DOMAIN "libfprint-"FP_COMPONENT
#endif
#include <stdint.h>
#include <errno.h>
#include <glib.h>
#include <libusb.h>
#include "nbis-helpers.h"
#include "fprint.h"
#include "fpi-dev.h"
#include "fpi-core.h"
#include "fpi-log.h"
#include "fpi-dev-img.h"
#include "fpi-data.h"
#include "fpi-img.h"
#include "drivers/driver_ids.h"
/* Global variables */
extern libusb_context *fpi_usb_ctx;
extern GSList *opened_devices;
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - offsetof(type,member) );})
/* fp_print_data structure definition */
enum fp_print_data_type {
PRINT_DATA_RAW = 0, /* memset-imposed default */
PRINT_DATA_NBIS_MINUTIAE
};
#define fp_dbg g_debug
#define fp_info g_debug
#define fp_warn g_warning
#define fp_err g_error
struct fp_print_data {
uint16_t driver_id;
uint32_t devtype;
enum fp_print_data_type type;
GSList *prints;
};
#define BUG_ON(condition) g_assert(!(condition))
#define BUG() g_assert_not_reached()
/* fp_dev structure definition */
enum fp_dev_state {
DEV_STATE_INITIAL = 0,
DEV_STATE_ERROR,
@@ -79,20 +71,16 @@ enum fp_dev_state {
DEV_STATE_CAPTURE_STOPPING,
};
struct fp_driver **fprint_get_drivers (void);
struct fp_dev {
struct fp_driver *drv;
libusb_device_handle *udev;
uint32_t devtype;
/* only valid if drv->type == DRIVER_IMAGING */
struct fp_img_dev *img_dev;
/* Link to the instance specific struct */
void *instance_data;
void *priv;
int nr_enroll_stages;
/* FIXME: This will eventually have a bus type */
libusb_device_handle *udev;
/* read-only to drivers */
struct fp_print_data *verify_data;
@@ -128,10 +116,39 @@ struct fp_dev {
struct fp_print_data **identify_gallery;
};
/* fp_img_dev structure definition */
struct fp_img_dev {
struct fp_dev *parent;
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 {
struct fp_dev *dev;
libusb_device_handle *udev;
enum fp_imgdev_action action;
int action_state;
@@ -143,18 +160,78 @@ struct fp_img_dev {
/* FIXME: better place to put this? */
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) \
container_of((drv), struct fp_img_driver, driver)
/* fp_dscv_dev structure definition */
struct fp_dscv_dev {
struct libusb_device *udev;
struct fp_driver *drv;
@@ -162,7 +239,6 @@ struct fp_dscv_dev {
uint32_t devtype;
};
/* fp_dscv_print structure definition */
struct fp_dscv_print {
uint16_t driver_id;
uint32_t devtype;
@@ -170,7 +246,43 @@ struct fp_dscv_print {
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 {
int x;
int y;
@@ -186,32 +298,34 @@ struct fp_minutia {
int num_nbrs;
};
/* fp_minutiae structure definition */
struct fp_minutiae {
int alloc;
int num;
struct fp_minutia **list;
};
/* Defined in fpi-dev-img.c */
void fpi_img_driver_setup(struct fp_img_driver *idriver);
int fpi_imgdev_get_img_width(struct fp_img_dev *imgdev);
int fpi_imgdev_get_img_height(struct fp_img_dev *imgdev);
/* 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)
/* Exported for use in command-line tools
* Defined in fpi-core.c */
struct fp_driver **fprint_get_drivers (void);
#define FP_IMG_STANDARDIZATION_FLAGS (FP_IMG_V_FLIPPED | FP_IMG_H_FLIPPED \
| FP_IMG_COLORS_INVERTED)
/* Defined in fpi-core.c */
enum fp_print_data_type fpi_driver_get_data_type(struct fp_driver *drv);
struct fp_img {
int width;
int height;
size_t length;
uint16_t flags;
struct fp_minutiae *minutiae;
unsigned char *binarized;
unsigned char data[0];
};
/* Defined in fpi-data.c */
void fpi_data_exit(void);
gboolean fpi_print_data_compatible(uint16_t driver_id1, uint32_t devtype1,
enum fp_print_data_type type1, uint16_t driver_id2, uint32_t devtype2,
enum fp_print_data_type type2);
/* Defined in fpi-img.c */
struct fp_img *fpi_img_new(size_t length);
struct fp_img *fpi_img_resize(struct fp_img *img, size_t newsize);
gboolean fpi_img_is_sane(struct fp_img *img);
int fpi_img_to_print_data(struct fp_img_dev *imgdev, struct fp_img *img,
struct fp_print_data **ret);
@@ -219,23 +333,71 @@ int fpi_img_compare_print_data(struct fp_print_data *enrolled_print,
struct fp_print_data *new_print);
int fpi_img_compare_print_data_to_gallery(struct fp_print_data *print,
struct fp_print_data **gallery, int match_threshold, size_t *match_offset);
struct fp_img *fpi_im_resize(struct fp_img *img, unsigned int w_factor, unsigned int h_factor);
/* polling and timeouts */
/* Defined in fpi-poll.c */
void fpi_timeout_cancel_all_for_dev(struct fp_dev *dev);
void fpi_poll_init(void);
void fpi_poll_exit(void);
/* Defined in fpi-async.c */
void fpi_drvcb_capture_started(struct fp_dev *dev, int status);
void fpi_drvcb_report_capture_result(struct fp_dev *dev, int result,
typedef void (*fpi_timeout_fn)(void *data);
/* async drv <--> lib comms */
struct fpi_ssm;
typedef void (*ssm_completed_fn)(struct fpi_ssm *ssm);
typedef void (*ssm_handler_fn)(struct fpi_ssm *ssm);
/* sequential state machine: state machine that iterates sequentially over
* a predefined series of states. can be aborted by either completion or
* abortion error conditions. */
struct fpi_ssm {
struct fp_dev *dev;
struct fpi_ssm *parentsm;
void *priv;
int nr_states;
int cur_state;
gboolean completed;
int error;
ssm_completed_fn callback;
ssm_handler_fn handler;
};
/* for library and drivers */
struct fpi_ssm *fpi_ssm_new(struct fp_dev *dev, ssm_handler_fn handler,
int nr_states);
void fpi_ssm_free(struct fpi_ssm *machine);
void fpi_ssm_start(struct fpi_ssm *machine, ssm_completed_fn callback);
/* for drivers */
void fpi_ssm_next_state(struct fpi_ssm *machine);
void fpi_ssm_jump_to_state(struct fpi_ssm *machine, int state);
void fpi_ssm_mark_completed(struct fpi_ssm *machine);
void fpi_ssm_mark_aborted(struct fpi_ssm *machine, int error);
void fpi_drvcb_open_complete(struct fp_dev *dev, int status);
void fpi_drvcb_close_complete(struct fp_dev *dev);
void fpi_drvcb_enroll_started(struct fp_dev *dev, int status);
void fpi_drvcb_enroll_stage_completed(struct fp_dev *dev, int result,
struct fp_print_data *data, struct fp_img *img);
void fpi_drvcb_enroll_stopped(struct fp_dev *dev);
void fpi_drvcb_verify_started(struct fp_dev *dev, int status);
void fpi_drvcb_report_verify_result(struct fp_dev *dev, int result,
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_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);
#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

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"
static const struct usb_id whitelist_id_table[] = {
/* Unsupported (for now) Elantech finger print readers */
{ .vendor = 0x04f3, .product = 0x0c03 },
{ .vendor = 0x04f3, .product = 0x0c16 },
{ .vendor = 0x04f3, .product = 0x0c26 },
/* Unsupported (for now) Validity Sensors finger print readers */
{ .vendor = 0x138a, .product = 0x0090 }, /* Found on e.g. Lenovo T460s */
{ .vendor = 0x138a, .product = 0x0091 },

View File

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

View File

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

View File

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

View File

@@ -1,18 +1,27 @@
libfprint_sources = [
'fpi-async.c',
'fpi-assembling.c',
'fpi-core.c',
'fpi-data.c',
'fpi-dev.c',
'fpi-dev-img.c',
'fpi-img.c',
'fpi-ssm.c',
'fpi-sync.c',
'fpi-poll.c',
'fpi-usb.c',
'fp_internal.h',
'drivers_api.h',
'async.c',
'core.c',
'data.c',
'drv.c',
'img.c',
'imgdev.c',
'poll.c',
'sync.c',
'assembling.c',
'assembling.h',
'drivers/driver_ids.h',
]
nbis_sources = [
'nbis/include/bozorth.h',
'nbis/include/bz_array.h',
'nbis/include/defs.h',
'nbis/include/lfs.h',
'nbis/include/log.h',
'nbis/include/morph.h',
'nbis/include/sunrast.h',
'nbis/bozorth3/bozorth3.c',
'nbis/bozorth3/bz_alloc.c',
'nbis/bozorth3/bz_drvrs.c',
@@ -21,17 +30,14 @@ nbis_sources = [
'nbis/bozorth3/bz_sort.c',
'nbis/mindtct/binar.c',
'nbis/mindtct/block.c',
'nbis/mindtct/chaincod.c',
'nbis/mindtct/contour.c',
'nbis/mindtct/detect.c',
'nbis/mindtct/dft.c',
'nbis/mindtct/free.c',
'nbis/mindtct/getmin.c',
'nbis/mindtct/globals.c',
'nbis/mindtct/imgutil.c',
'nbis/mindtct/init.c',
'nbis/mindtct/line.c',
'nbis/mindtct/link.c',
'nbis/mindtct/log.c',
'nbis/mindtct/loop.c',
'nbis/mindtct/maps.c',
@@ -44,7 +50,6 @@ nbis_sources = [
'nbis/mindtct/shape.c',
'nbis/mindtct/sort.c',
'nbis/mindtct/util.c',
'nbis/mindtct/xytreps.c',
]
aeslib = false
@@ -54,13 +59,13 @@ drivers_sources = []
drivers_cflags = []
foreach driver: drivers
if driver == 'upekts'
drivers_sources += [ 'drivers/upekts.c', 'drivers/upek_proto.c' ]
drivers_sources += [ 'drivers/upekts.c' ]
endif
if driver == 'upektc'
drivers_sources += [ 'drivers/upektc.c' ]
drivers_sources += [ 'drivers/upektc.c', 'drivers/upektc.h' ]
endif
if driver == 'upeksonly'
drivers_sources += [ 'drivers/upeksonly.c' ]
drivers_sources += [ 'drivers/upeksonly.c', 'drivers/upeksonly.h' ]
endif
if driver == 'uru4000'
drivers_sources += [ 'drivers/uru4000.c' ]
@@ -70,20 +75,20 @@ foreach driver: drivers
aeslib = true
endif
if driver == 'aes1660'
drivers_sources += [ 'drivers/aes1660.c' ]
drivers_sources += [ 'drivers/aes1660.c', 'drivers/aes1660.h' ]
aeslib = true
aesx660 = true
endif
if driver == 'aes2501'
drivers_sources += [ 'drivers/aes2501.c' ]
drivers_sources += [ 'drivers/aes2501.c', 'drivers/aes2501.h' ]
aeslib = true
endif
if driver == 'aes2550'
drivers_sources += [ 'drivers/aes2550.c' ]
drivers_sources += [ 'drivers/aes2550.c', 'drivers/aes2550.h' ]
aeslib = true
endif
if driver == 'aes2660'
drivers_sources += [ 'drivers/aes2660.c' ]
drivers_sources += [ 'drivers/aes2660.c', 'drivers/aes2660.h' ]
aeslib = true
aesx660 = true
endif
@@ -97,6 +102,9 @@ foreach driver: drivers
aeslib = true
aes3k = true
endif
if driver == 'fdu2000'
drivers_sources += [ 'drivers/fdu2000.c' ]
endif
if driver == 'vcom5s'
drivers_sources += [ 'drivers/vcom5s.c' ]
endif
@@ -104,38 +112,38 @@ foreach driver: drivers
drivers_sources += [ 'drivers/vfs101.c' ]
endif
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
if driver == 'vfs5011'
drivers_sources += [ 'drivers/vfs5011.c' ]
drivers_sources += [ 'drivers/vfs5011.c', 'drivers/vfs5011_proto.h' ]
endif
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
if driver == 'etes603'
drivers_sources += [ 'drivers/etes603.c' ]
endif
if driver == 'vfs0050'
drivers_sources += [ 'drivers/vfs0050.c' ]
drivers_sources += [ 'drivers/vfs0050.c', 'drivers/vfs0050.h' ]
endif
if driver == 'elan'
drivers_sources += [ 'drivers/elan.c' ]
drivers_sources += [ 'drivers/elan.c', 'drivers/elan.h' ]
endif
endforeach
if aeslib
drivers_sources += [ 'drivers/aeslib.c' ]
drivers_sources += [ 'aeslib.c', 'aeslib.h' ]
endif
if aesx660
drivers_sources += ['drivers/aesx660.c' ]
drivers_sources += ['drivers/aesx660.c', 'drivers/aesx660.h' ]
endif
if aes3k
drivers_sources += ['drivers/aes3k.c' ]
drivers_sources += ['drivers/aes3k.c', 'drivers/aes3k.h' ]
endif
other_sources = []
if imaging_dep.found()
other_sources += [ 'fpi-img-pixman.c' ]
other_sources += [ 'pixman.c' ]
endif
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:
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.
License:
This software was developed at the National Institute of Standards and
Technology (NIST) by employees of the Federal Government in the course
of their official duties. Pursuant to title 17 Section 105 of the
United States Code, this software is not subject to copyright protection
and is in the public domain. NIST assumes no responsibility whatsoever for
its use by other parties, and makes no guarantees, expressed or implied,
about its quality, reliability, or any other characteristic.
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.
Disclaimer:
This software was developed to promote biometric standards and biometric
technology testing for the Federal Government in accordance with the USA
PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act.
Specific hardware and software products identified in this software were used
in order to perform the software development. In no case does such
identification imply recommendation or endorsement by the National Institute
of Standards and Technology, nor does it imply that the products and equipment
identified are necessarily the best available for the purpose.
*******************************************************************************/
@@ -81,6 +89,9 @@ of the software.
#include <stdio.h>
#include <bozorth.h>
static const int verbose_bozorth = 0;
static const int m1_xyt = 0;
/***********************************************************************/
void bz_comp(
int npoints, /* INPUT: # of points */
@@ -149,7 +160,7 @@ for ( k = 0; k < npoints - 1; k++ ) {
else {
double dz;
if ( 0 )
if ( m1_xyt )
dz = ( 180.0F / PI_SINGLE ) * atanf( (float) -dy / (float) dx );
else
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 ) {
#ifndef NOVERBOSE
if ( 0 )
if ( verbose_bozorth )
printf( "bz_comp(): breaking loop to avoid table overflow\n" );
#endif
goto COMP_END;
@@ -381,7 +392,7 @@ static int * rtp[ ROT_SIZE_1 ];
/* extern int * scolpt[ SCOLPT_SIZE ]; INPUT */
/* extern int * fcolpt[ FCOLPT_SIZE ]; INPUT */
/* extern int colp[ COLP_SIZE_1 ][ COLP_SIZE_2 ]; OUTPUT */
/* extern int 0; */
/* extern int verbose_bozorth; */
/* extern FILE * stderr; */
/* extern char * get_progname( void ); */
/* extern char * get_probe_filename( void ); */
@@ -390,7 +401,6 @@ static int * rtp[ ROT_SIZE_1 ];
st = 1;
edge_pair_index = 0;
rotptr = &rot[0][0];
@@ -560,7 +570,7 @@ for ( k = 1; k < probe_ptrlist_len; k++ ) {
if ( edge_pair_index == 19999 ) {
#ifndef NOVERBOSE
if ( 0 )
if ( verbose_bozorth )
fprintf( stderr, "%s: bz_match(): WARNING: list is full, breaking loop early [p=%s; g=%s]\n",
get_progname(), get_probe_filename(), get_gallery_filename() );
#endif
@@ -642,13 +652,13 @@ int avv[ AVV_SIZE_1 ][ AVV_SIZE_2 ];
if ( pstruct->nrows < MIN_COMPUTABLE_BOZORTH_MINUTIAE ) {
#ifndef NOVERBOSE
if ( gstruct->nrows < MIN_COMPUTABLE_BOZORTH_MINUTIAE ) {
if ( 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",
get_progname(),
pstruct->nrows, gstruct->nrows, MIN_COMPUTABLE_BOZORTH_MINUTIAE,
get_probe_filename(), get_gallery_filename() );
} 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",
get_progname(),
pstruct->nrows, MIN_COMPUTABLE_BOZORTH_MINUTIAE,
@@ -662,7 +672,7 @@ if ( pstruct->nrows < MIN_COMPUTABLE_BOZORTH_MINUTIAE ) {
if ( gstruct->nrows < MIN_COMPUTABLE_BOZORTH_MINUTIAE ) {
#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",
get_progname(),
gstruct->nrows, MIN_COMPUTABLE_BOZORTH_MINUTIAE,
@@ -701,6 +711,7 @@ tp = 0;
p1 = 0;
tot = 0;
ftt = 0;
kx = 0;
match_score = 0;
for ( k = 0; k < np - 1; k++ ) {
@@ -754,7 +765,7 @@ for ( k = 0; k < np - 1; k++ ) {
}
#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] );
#endif
@@ -816,6 +827,7 @@ for ( k = 0; k < np - 1; k++ ) {
l = 1;
t = np + 1;
b = kq;
@@ -1155,7 +1167,7 @@ for ( k = 0; k < np - 1; k++ ) {
if ( ll ) {
if ( 0 )
if ( m1_xyt )
fi = ( 180.0F / PI_SINGLE ) * atanf( (float) -jj / (float) ll );
else
fi = ( 180.0F / PI_SINGLE ) * atanf( (float) jj / (float) ll );
@@ -1175,7 +1187,7 @@ for ( k = 0; k < np - 1; k++ ) {
jj += 360;
} else {
if ( 0 ) {
if ( m1_xyt ) {
if ( jj > 0 )
jj = -90;
else
@@ -1192,7 +1204,7 @@ for ( k = 0; k < np - 1; k++ ) {
if ( kk ) {
if ( 0 )
if ( m1_xyt )
fi = ( 180.0F / PI_SINGLE ) * atanf( (float) -j / (float) kk );
else
fi = ( 180.0F / PI_SINGLE ) * atanf( (float) j / (float) kk );
@@ -1212,7 +1224,7 @@ for ( k = 0; k < np - 1; k++ ) {
j += 360;
} else {
if ( 0 ) {
if ( m1_xyt ) {
if ( j > 0 )
j = -90;
else
@@ -1599,7 +1611,7 @@ if ( n ) {
notfound = 1;
#ifndef NOVERBOSE
if ( 0 ) {
if ( verbose_bozorth ) {
int * llptr = lptr;
printf( "bz_sift(): n: looking for l=%d in [", l );
for ( i = 0; i < lim; i++ ) {
@@ -1645,7 +1657,7 @@ if ( t ) {
notfound = 1;
#ifndef NOVERBOSE
if ( 0 ) {
if ( verbose_bozorth ) {
int * llptr = lptr;
printf( "bz_sift(): t: looking for kz=%d in [", kz );
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:
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.
License:
This software was developed at the National Institute of Standards and
Technology (NIST) by employees of the Federal Government in the course
of their official duties. Pursuant to title 17 Section 105 of the
United States Code, this software is not subject to copyright protection
and is in the public domain. NIST assumes no responsibility whatsoever for
its use by other parties, and makes no guarantees, expressed or implied,
about its quality, reliability, or any other characteristic.
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.
Disclaimer:
This software was developed to promote biometric standards and biometric
technology testing for the Federal Government in accordance with the USA
PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act.
Specific hardware and software products identified in this software were used
in order to perform the software development. In no case does such
identification imply recommendation or endorsement by the National Institute
of Standards and Technology, nor does it imply that the products and equipment
identified are necessarily the best available for the purpose.
*******************************************************************************/
@@ -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 */
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:
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.
License:
This software was developed at the National Institute of Standards and
Technology (NIST) by employees of the Federal Government in the course
of their official duties. Pursuant to title 17 Section 105 of the
United States Code, this software is not subject to copyright protection
and is in the public domain. NIST assumes no responsibility whatsoever for
its use by other parties, and makes no guarantees, expressed or implied,
about its quality, reliability, or any other characteristic.
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.
Disclaimer:
This software was developed to promote biometric standards and biometric
technology testing for the Federal Government in accordance with the USA
PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act.
Specific hardware and software products identified in this software were used
in order to perform the software development. In no case does such
identification imply recommendation or endorsement by the National Institute
of Standards and Technology, nor does it imply that the products and equipment
identified are necessarily the best available for the purpose.
*******************************************************************************/
@@ -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:
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.
License:
This software was developed at the National Institute of Standards and
Technology (NIST) by employees of the Federal Government in the course
of their official duties. Pursuant to title 17 Section 105 of the
United States Code, this software is not subject to copyright protection
and is in the public domain. NIST assumes no responsibility whatsoever for
its use by other parties, and makes no guarantees, expressed or implied,
about its quality, reliability, or any other characteristic.
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.
Disclaimer:
This software was developed to promote biometric standards and biometric
technology testing for the Federal Government in accordance with the USA
PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act.
Specific hardware and software products identified in this software were used
in order to perform the software development. In no case does such
identification imply recommendation or endorsement by the National Institute
of Standards and Technology, nor does it imply that the products and equipment
identified are necessarily the best available for the purpose.
*******************************************************************************/
@@ -83,45 +91,23 @@ int yl[ YL_SIZE_1 ][ YL_SIZE_2 ];
/**************************************************************************/
/* Globals used significantly by sift() */
/**************************************************************************/
#ifdef TARGET_OS
int rq[ RQ_SIZE ];
int tq[ TQ_SIZE ];
int zz[ ZZ_SIZE ];
int rq[ RQ_SIZE ] = {};
int tq[ TQ_SIZE ] = {};
int zz[ ZZ_SIZE ] = {};
int rx[ RX_SIZE ];
int mm[ MM_SIZE ];
int nn[ NN_SIZE ];
int rx[ RX_SIZE ] = {};
int mm[ MM_SIZE ] = {};
int nn[ NN_SIZE ] = {};
int qq[ QQ_SIZE ];
int qq[ QQ_SIZE ] = {};
int rk[ RK_SIZE ];
int rk[ RK_SIZE ] = {};
int cp[ CP_SIZE ];
int rp[ RP_SIZE ];
int cp[ CP_SIZE ] = {};
int rp[ RP_SIZE ] = {};
int rf[RF_SIZE_1][RF_SIZE_2];
int cf[CF_SIZE_1][CF_SIZE_2];
int rf[RF_SIZE_1][RF_SIZE_2] = {};
int cf[CF_SIZE_1][CF_SIZE_2] = {};
int y[20000];
#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
int y[20000] = {};

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:
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.
License:
This software was developed at the National Institute of Standards and
Technology (NIST) by employees of the Federal Government in the course
of their official duties. Pursuant to title 17 Section 105 of the
United States Code, this software is not subject to copyright protection
and is in the public domain. NIST assumes no responsibility whatsoever for
its use by other parties, and makes no guarantees, expressed or implied,
about its quality, reliability, or any other characteristic.
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.
Disclaimer:
This software was developed to promote biometric standards and biometric
technology testing for the Federal Government in accordance with the USA
PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act.
Specific hardware and software products identified in this software were used
in order to perform the software development. In no case does such
identification imply recommendation or endorsement by the National Institute
of Standards and Technology, nor does it imply that the products and equipment
identified are necessarily the best available for the purpose.
*******************************************************************************/
@@ -49,9 +57,6 @@ of the software.
MODIFICATIONS: Michael D. Garris (NIST)
Stan Janet (NIST)
DATE: 09/21/2004
UPDATED: 01/11/2012 by Kenneth Ko
UPDATED: 03/08/2012 by Kenneth Ko
UPDATED: 07/10/2014 by Kenneth Ko
Contains routines responsible for supporting command line
processing, file and data input to, and output from the
@@ -95,7 +100,50 @@ of the software.
#include <sys/time.h>
#include <bozorth.h>
static const int verbose_load = 0;
static const int verbose_main = 0;
/***********************************************************************/
int parse_line_range( const char * sb, int * begin, int * end )
{
int ib, ie;
char * se;
if ( ! isdigit(*sb) )
return -1;
ib = atoi( sb );
se = strchr( sb, '-' );
if ( se != (char *) NULL ) {
se++;
if ( ! isdigit(*se) )
return -2;
ie = atoi( se );
} else {
ie = ib;
}
if ( ib <= 0 ) {
if ( ie <= 0 ) {
return -3;
} else {
return -4;
}
}
if ( ie <= 0 ) {
return -5;
}
if ( ib > ie )
return -6;
*begin = ib;
*end = ie;
return 0;
}
/***********************************************************************/
@@ -105,10 +153,25 @@ static char * pfile;
static char * gfile;
/***********************************************************************/
void set_progname( int use_pid, char * basename, pid_t pid )
{
if ( use_pid )
sprintf( program_buffer, "%s pid %ld", basename, (long) pid );
else
sprintf( program_buffer, "%s", basename );
}
/***********************************************************************/
void set_probe_filename( char * filename )
{
pfile = filename;
}
/***********************************************************************/
void set_gallery_filename( char * filename )
{
gfile = filename;
}
/***********************************************************************/
char * get_progname( void )
@@ -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 */
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
and return a XYT sturcture.
Load a 3-4 column (X,Y,T[,Q]) set of minutiae from the specified file.
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
@@ -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 ];
/************************************************************************
Load a XYTQ structure and return a XYT struct.
Row 3's value is an angle which is normalized to the interval (-180,180].
A maximum of MAX_BOZORTH_MINUTIAE minutiae can be returned -- fewer if
"DEFAULT_BOZORTH_MINUTIAE" is smaller. If the file contains more minutiae than are
to be returned, the highest-quality minutiae are returned.
*************************************************************************/
/* This is now externally defined in bozorth.h */
/* extern FILE * stderr; */
#define C1 0
#define C2 1
fp = fopen( xyt_file, "r" );
if ( fp == (FILE *) NULL ) {
fprintf( stderr, "%s: ERROR: fopen() of minutiae file \"%s\" failed: %s\n",
get_progname(), xyt_file, strerror(errno) );
return XYT_NULL;
}
nminutiae = 0;
nargs_expected = 0;
while ( fgets( xyt_line, sizeof xyt_line, fp ) != CNULL ) {
m = sscanf( xyt_line, "%d %d %d %d",
&xvals_lng[nminutiae],
&yvals_lng[nminutiae],
&tvals_lng[nminutiae],
&qvals_lng[nminutiae] );
if ( nminutiae == 0 ) {
if ( m != 3 && m != 4 ) {
fprintf( stderr, "%s: ERROR: sscanf() failed on line %u in minutiae file \"%s\"\n",
get_progname(), nminutiae+1, xyt_file );
return XYT_NULL;
}
nargs_expected = m;
} else {
if ( m != nargs_expected ) {
fprintf( stderr, "%s: ERROR: inconsistent argument count on line %u of minutiae file \"%s\"\n",
get_progname(), nminutiae+1, xyt_file );
return XYT_NULL;
}
}
if ( m == 3 )
qvals_lng[nminutiae] = 1;
if ( tvals_lng[nminutiae] > 180 )
tvals_lng[nminutiae] -= 360;
/*
if ( C1 ) {
c[nminutiae].col[0] = xvals_lng[nminutiae];
c[nminutiae].col[1] = yvals_lng[nminutiae];
c[nminutiae].col[2] = tvals_lng[nminutiae];
c[nminutiae].col[3] = qvals_lng[nminutiae];
}
*/
++nminutiae;
if ( nminutiae == MAX_FILE_MINUTIAE )
break;
}
if ( fclose(fp) != 0 ) {
fprintf( stderr, "%s: ERROR: fclose() of minutiae file \"%s\" failed: %s\n",
get_progname(), xyt_file, strerror(errno) );
return XYT_NULL;
}
if ( nminutiae > DEFAULT_BOZORTH_MINUTIAE ) {
if ( verbose_load )
fprintf( stderr, "%s: WARNING: bz_load(): trimming minutiae to the %d of highest quality\n",
get_progname(), DEFAULT_BOZORTH_MINUTIAE );
if ( verbose_load )
fprintf( stderr, "Before quality sort:\n" );
if ( sort_order_decreasing( qvals_lng, nminutiae, order )) {
fprintf( stderr, "%s: ERROR: sort failed and returned on error\n", get_progname());
return XYT_NULL;
}
for ( j = 0; j < nminutiae; j++ ) {
if ( verbose_load )
fprintf( stderr, " %3d: %3d %3d %3d ---> order = %3d\n",
j, xvals_lng[j], yvals_lng[j], qvals_lng[j], order[j] );
if ( j == 0 )
continue;
if ( qvals_lng[order[j]] > qvals_lng[order[j-1]] ) {
fprintf( stderr, "%s: ERROR: sort failed: j=%d; qvals_lng[%d] > qvals_lng[%d]\n",
get_progname(), j, order[j], order[j-1] );
return XYT_NULL;
}
}
if ( verbose_load )
fprintf( stderr, "\nAfter quality sort:\n" );
for ( j = 0; j < DEFAULT_BOZORTH_MINUTIAE; j++ ) {
xvals[j] = xvals_lng[order[j]];
yvals[j] = yvals_lng[order[j]];
tvals[j] = tvals_lng[order[j]];
qvals[j] = qvals_lng[order[j]];
if ( verbose_load )
fprintf( stderr, " %3d: %3d %3d %3d\n", j, xvals[j], yvals[j], qvals[j] );
}
if ( C1 ) {
if ( verbose_load )
fprintf( stderr, "\nAfter qsort():\n" );
qsort( (void *) &c, (size_t) nminutiae, sizeof(struct minutiae_struct), sort_quality_decreasing );
for ( j = 0; j < nminutiae; j++ ) {
if ( verbose_load )
fprintf( stderr, "Q %3d: %3d %3d %3d\n",
j, c[j].col[0], c[j].col[1], c[j].col[3] );
if ( j > 0 && c[j].col[3] > c[j-1].col[3] ) {
fprintf( stderr, "%s: ERROR: sort failed: c[%d].col[3] > c[%d].col[3]\n",
get_progname(), j, j-1 );
return XYT_NULL;
}
}
}
if ( verbose_load )
fprintf( stderr, "\n" );
xptr = xvals;
yptr = yvals;
tptr = tvals;
qptr = qvals;
nminutiae = DEFAULT_BOZORTH_MINUTIAE;
} else{
xptr = xvals_lng;
yptr = yvals_lng;
tptr = tvals_lng;
qptr = qvals_lng;
}
for ( j=0; j < nminutiae; j++ ) {
c[j].col[0] = xptr[j];
c[j].col[1] = yptr[j];
c[j].col[2] = tptr[j];
c[j].col[3] = qptr[j];
}
qsort( (void *) &c, (size_t) nminutiae, sizeof(struct minutiae_struct), sort_x_y );
if ( verbose_load ) {
fprintf( stderr, "\nSorted on increasing x, then increasing y\n" );
for ( j = 0; j < nminutiae; j++ ) {
fprintf( stderr, "%d : %3d, %3d, %3d, %3d\n", j, c[j].col[0], c[j].col[1], c[j].col[2], c[j].col[3] );
if ( j > 0 ) {
if ( c[j].col[0] < c[j-1].col[0] ) {
fprintf( stderr, "%s: ERROR: sort failed: c[%d].col[0]=%d > c[%d].col[0]=%d\n",
get_progname(),
j, c[j].col[0], j-1, c[j-1].col[0]
);
return XYT_NULL;
}
if ( c[j].col[0] == c[j-1].col[0] && c[j].col[1] < c[j-1].col[1] ) {
fprintf( stderr, "%s: ERROR: sort failed: c[%d].col[0]=%d == c[%d].col[0]=%d; c[%d].col[0]=%d == c[%d].col[0]=%d\n",
get_progname(),
j, c[j].col[0], j-1, c[j-1].col[0],
j, c[j].col[1], j-1, c[j-1].col[1]
);
return XYT_NULL;
}
}
}
}
s = (struct xyt_struct *) malloc( sizeof( struct xyt_struct ) );
if ( s == XYT_NULL ) {
fprintf( stderr, "%s: ERROR: malloc() failure while loading minutiae file \"%s\" failed: %s\n",
get_progname(),
xyt_file,
strerror(errno)
);
return XYT_NULL;
}
for ( j = 0; j < nminutiae; j++ ) {
s->xcol[j] = c[j].col[0];
s->ycol[j] = c[j].col[1];
s->thetacol[j] = c[j].col[2];
}
s->nrows = nminutiae;
if ( verbose_load )
fprintf( stderr, "Loaded %s\n", xyt_file );
return s;
}
/***********************************************************************/
#ifdef PARALLEL_SEARCH
@@ -171,13 +617,13 @@ tv.tv_usec = 0;
retval = select( fd+1, &rfds, NULL, NULL, &tv );
if ( retval < 0 ) {
perror( "select() failed" );
return 0;
perror( "select() failed" );
return 0;
}
if ( FD_ISSET( fd, &rfds ) ) {
/*fprintf( stderr, "data is available now.\n" );*/
return 1;
/*fprintf( stderr, "data is available now.\n" );*/
return 1;
}
/* fprintf( stderr, "no data is available\n" ); */

View File

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

View File

@@ -1,43 +1,23 @@
/*******************************************************************************
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.
License:
This software was developed at the National Institute of Standards and
Technology (NIST) by employees of the Federal Government in the course
of their official duties. Pursuant to title 17 Section 105 of the
United States Code, this software is not subject to copyright protection
and is in the public domain. NIST assumes no responsibility whatsoever for
its use by other parties, and makes no guarantees, expressed or implied,
about its quality, reliability, or any other characteristic.
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.
Disclaimer:
This software was developed to promote biometric standards and biometric
technology testing for the Federal Government in accordance with the USA
PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act.
Specific hardware and software products identified in this software were used
in order to perform the software development. In no case does such
identification imply recommendation or endorsement by the National Institute
of Standards and Technology, nor does it imply that the products and equipment
identified are necessarily the best available for the purpose.
*******************************************************************************/
@@ -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() */
@@ -194,17 +174,7 @@ struct xyt_struct {
int thetacol[ MAX_BOZORTH_MINUTIAE ];
};
struct xytq_struct {
int nrows;
int xcol[ MAX_FILE_MINUTIAE ];
int ycol[ MAX_FILE_MINUTIAE ];
int thetacol[ MAX_FILE_MINUTIAE ];
int qualitycol[ MAX_FILE_MINUTIAE ];
};
#define XYT_NULL ( (struct xyt_struct *) NULL ) /* bz_load() */
#define XYTQ_NULL ( (struct xytq_struct *) NULL ) /* bz_load() */
/**************************************************************************/
@@ -217,8 +187,6 @@ struct xytq_struct {
/**************************************************************************/
/* Globals supporting command line options */
extern int verbose_threshold;
/* Global supporting error reporting */
extern FILE *stderr;
/**************************************************************************/
/* 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_line(const char *, const char *, int, int, const char *);
extern struct xyt_struct *bz_load(const char *);
extern struct xyt_struct *bz_prune(struct xytq_struct *, int);
extern int fd_readable(int);
/* In: BZ_SORT.C */
extern int sort_quality_decreasing(const void *, const void *);

View File

@@ -1,43 +1,23 @@
/*******************************************************************************
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.
License:
This software was developed at the National Institute of Standards and
Technology (NIST) by employees of the Federal Government in the course
of their official duties. Pursuant to title 17 Section 105 of the
United States Code, this software is not subject to copyright protection
and is in the public domain. NIST assumes no responsibility whatsoever for
its use by other parties, and makes no guarantees, expressed or implied,
about its quality, reliability, or any other characteristic.
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.
Disclaimer:
This software was developed to promote biometric standards and biometric
technology testing for the Federal Government in accordance with the USA
PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act.
Specific hardware and software products identified in this software were used
in order to perform the software development. In no case does such
identification imply recommendation or endorsement by the National Institute
of Standards and Technology, nor does it imply that the products and equipment
identified are necessarily the best available for the purpose.
*******************************************************************************/

View File

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

View File

@@ -1,43 +1,23 @@
/*******************************************************************************
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.
License:
This software was developed at the National Institute of Standards and
Technology (NIST) by employees of the Federal Government in the course
of their official duties. Pursuant to title 17 Section 105 of the
United States Code, this software is not subject to copyright protection
and is in the public domain. NIST assumes no responsibility whatsoever for
its use by other parties, and makes no guarantees, expressed or implied,
about its quality, reliability, or any other characteristic.
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.
Disclaimer:
This software was developed to promote biometric standards and biometric
technology testing for the Federal Government in accordance with the USA
PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act.
Specific hardware and software products identified in this software were used
in order to perform the software development. In no case does such
identification imply recommendation or endorsement by the National Institute
of Standards and Technology, nor does it imply that the products and equipment
identified are necessarily the best available for the purpose.
*******************************************************************************/
@@ -53,9 +33,6 @@ of the software.
Comments added to guide changes to blocksize
or number of detected directions.
UPDATED: 03/11/2005 by MDG
UPDATED: 01/31/2008 by Kenneth Ko
UPDATED: 09/04/2008 by Kenneth Ko
UPDATED: 01/11/2012 by Kenneth Ko
FILE: LFS.H
@@ -183,7 +160,7 @@ typedef struct shape{
/* Parameters used by LFS for setting thresholds and */
/* defining testing criterion. */
typedef struct g_lfsparms{
typedef struct lfsparms{
/* Image Controls */
int pad_value;
int join_line_radius;
@@ -259,6 +236,8 @@ typedef struct g_lfsparms{
int pores_steps_bwd;
double pores_min_dist2;
double pores_max_ratio;
int remove_perimeter_pts;
int min_pp_distance;
/* Ridge Counting Controls */
int max_nbrs;
@@ -403,7 +382,7 @@ typedef struct g_lfsparms{
/* Thresholds and factors used by HO39. Renamed */
/* here to give more meaning. */
/* HO39 Name=Value */
/* Minimum DFT power allowable in any one direction. */
/* Minimum DFT power allowable in any one direction. */
#define POWMAX_MIN 100000.0 /* thrhf=1e5f */
/* Minimum normalized power allowable in any one */
@@ -608,6 +587,9 @@ typedef struct g_lfsparms{
/* contour points to be considered a pore. */
#define PORES_MAX_RATIO 2.25
/* Points which are closer than this distance to scan perimeter will be removed */
#define PERIMETER_PTS_DISTANCE 10
/***** RIDGE COUNTING CONSTANTS *****/
@@ -707,24 +689,15 @@ typedef struct g_lfsparms{
/*************************************************************************/
/* binar.c */
extern int binarize(unsigned char **, int *, int *,
unsigned char *, const int, const int,
int *, const int, const int,
const ROTGRIDS *, const LFSPARMS *);
extern int binarize_V2(unsigned char **, int *, int *,
unsigned char *, const int, const int,
int *, const int, const int,
const ROTGRIDS *, const LFSPARMS *);
extern int binarize_image(unsigned char **, int *, int *,
unsigned char *, const int, const int,
const int *, const int, const int, const int,
const ROTGRIDS *, const int);
extern int binarize_image_V2(unsigned char **, int *, int *,
unsigned char *, const int, const int,
const int *, const int, const int,
const int, const ROTGRIDS *);
extern int dirbinarize(const unsigned char *, const int, const ROTGRIDS *);
extern int isobinarize(unsigned char *, const int, const int, const int);
/* block.c */
extern int block_offsets(int **, int *, int *, const int, const int,
@@ -736,12 +709,9 @@ extern int find_valid_block(int *, int *, int *, int *, int *,
const int, const int);
extern void set_margin_blocks(int *, const int, const int, const int);
/* chaincod.c */
extern int chain_code_loop(int **, int *, const int *, const int *, const int);
extern int is_chain_clockwise(const int *, const int, const int);
/* contour.c */
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 int get_high_curvature_contour(int **, int **, int **, int **, 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,
const int, const int, const int, const int, const int,
unsigned char *, const int, const int);
extern int next_contour_pixel(int *, int *, int *, int *,
const int, const int, const int, const int, const int,
unsigned char *, const int, const int);
extern int start_scan_nbr(const int, const int, const int, const int);
extern int next_scan_nbr(const int, const int);
extern int min_contour_theta(int *, double *, const int, const int *,
const int *, const int);
extern void contour_limits(int *, int *, int *, int *, const int *,
@@ -769,29 +734,18 @@ extern void fix_edge_pixel_pair(int *, int *, int *, int *,
unsigned char *, const int, const int);
/* detect.c */
extern int lfs_detect_minutiae( MINUTIAE **,
int **, int **, int *, int *,
unsigned char **, int *, int *,
unsigned char *, const int, const int,
const LFSPARMS *);
extern int lfs_detect_minutiae_V2(MINUTIAE **,
int **, int **, int **, int **, int *, int *,
unsigned char **, int *, int *,
unsigned char *, const int, const int,
const LFSPARMS *);
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 *);
/* dft.c */
extern int dft_dir_powers(double **, unsigned char *, const int,
const int, const int, const DFTWAVES *,
const ROTGRIDS *);
extern void sum_rot_block_rows(int *, const unsigned char *, const int *,
const int);
extern void dft_power(double *, const int *, const DFTWAVE *, const int);
extern int dft_power_stats(int *, double *, int *, double *, double **,
const int, const int, const int);
extern void get_max_norm(double *, int *, double *, const double *, const int);
extern int sort_dft_waves(int *, const double *, const double *, const int);
/* free.c */
extern void free_dir2rad(DIR2RAD *);
@@ -799,13 +753,6 @@ extern void free_dftwaves(DFTWAVES *);
extern void free_rotgrids(ROTGRIDS *);
extern void free_dir_powers(double **, const int);
/* getmin.c */
extern int get_minutiae(MINUTIAE **, int **, int **, int **,
int **, int **, int *, int *,
unsigned char **, int *, int *, int *,
unsigned char *, const int, const int,
const int, const double, const LFSPARMS *);
/* imgutil.c */
extern void bits_6to8(unsigned char *, const int, const int);
extern void bits_8to6(unsigned char *, const int, const int);
@@ -824,41 +771,15 @@ extern int search_in_direction(int *, int *, int *, int *, const int,
/* init.c */
extern int init_dir2rad(DIR2RAD **, const int);
extern int init_dftwaves(DFTWAVES **, const double *, const int, const int);
extern int get_max_padding(const int, const int, const int, const int);
extern int get_max_padding_V2(const int, const int, const int, const int);
extern int init_rotgrids(ROTGRIDS **, const int, const int, const int,
const double, const int, const int, const int, const int);
extern int alloc_dir_powers(double ***, const int, const int);
extern int alloc_power_stats(int **, double **, int **, double **, const int);
/* isempty.c */
extern int is_image_empty(int *, const int, const int);
extern int is_qmap_empty(int *, const int, const int);
/* line.c */
extern int line_points(int **, int **, int *,
const int, const int, const int, const int);
extern int bresenham_line_points(int **, int **, int *,
const int, const int, const int, const int);
/* link.c */
extern int link_minutiae(MINUTIAE *, unsigned char *, const int, const int,
int *, const int, const int, const LFSPARMS *);
extern int create_link_table(int **, int **, int **, int *, int *, int *,
const int, const int, const MINUTIAE *, const int *,
int *, const int, const int, unsigned char *,
const int, const int, const LFSPARMS *);
extern int update_link_table(int *, int *, int *, int *, int *, int *,
const int, int *, int *, int *, int *,
const int, const int, const int);
extern int order_link_table(int *, int *, int *, const int, const int,
const int, const int, const MINUTIAE *, const int);
extern int process_link_table(const int *, const int *, const int *,
const int, const int, const int, const int, MINUTIAE *,
int *, unsigned char *, const int, const int,
const LFSPARMS *);
extern double link_score(const double, const double, const LFSPARMS *);
/* loop.c */
extern int get_loop_list(int **, MINUTIAE *, const int, unsigned char *,
@@ -878,16 +799,8 @@ extern int process_loop_V2(MINUTIAE *, const int *, const int *,
const int *, const int *, const int,
unsigned char *, const int, const int,
int *, const LFSPARMS *);
extern void get_loop_aspect(int *, int *, double *, int *, int *, double *,
const int *, const int *, const int);
extern int fill_loop(const int *, const int *, const int,
unsigned char *, const int, const int);
extern void fill_partial_row(const int, const int, const int, const int,
unsigned char *, const int, const int);
extern void flood_loop(const int *, const int *, const int,
unsigned char *, const int, const int);
extern void flood_fill4(const int, const int, const int,
unsigned char *, const int, const int);
/* maps.c */
extern int gen_image_maps(int **, int **, int **, int **, int *, int *,
@@ -907,10 +820,6 @@ extern void smooth_direction_map(int *, int *, const int, const int,
const DIR2RAD *, const LFSPARMS *);
extern int gen_high_curve_map(int **, int *, const int, const int,
const LFSPARMS *);
extern int gen_imap(int **, int *, int *,
unsigned char *, const int, const int,
const DIR2RAD *, const DFTWAVES *, const ROTGRIDS *,
const LFSPARMS *);
extern int gen_initial_imap(int **, int *, const int, const int,
unsigned char *, const int, const int,
const DFTWAVES *, const ROTGRIDS *, const LFSPARMS *);
@@ -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 void smooth_imap(int *, const int, const int, const DIR2RAD *,
const LFSPARMS *);
extern int gen_nmap(int **, int *, const int, const int, const LFSPARMS *);
extern int vorticity(int *, const int, const int, const int, const int,
const int);
extern void accum_nbr_vorticity(int *, const int, const int, const int);
@@ -960,9 +868,6 @@ extern void skip_repeated_vertical_pair(int *, const int,
/* minutia.c */
extern int alloc_minutiae(MINUTIAE **, const int);
extern int realloc_minutiae(MINUTIAE *, const int);
extern int detect_minutiae(MINUTIAE *, unsigned char *, const int, const int,
const int *, const int *, const int, const int,
const LFSPARMS *);
extern int detect_minutiae_V2(MINUTIAE *,
unsigned char *, const int, const int,
int *, int *, int *, const int, const int,
@@ -1067,6 +972,8 @@ extern int adjust_high_curvature_minutia_V2(int *, int *, int *,
int *, MINUTIAE *, const LFSPARMS *);
extern int get_low_curvature_direction(const int, const int, const int,
const int);
void lfs2nist_minutia_XYT(int *ox, int *oy, int *ot,
const MINUTIA *minutia, const int iw, const int ih);
/* quality.c */
extern int gen_quality_map(int **, int *, int *, int *, int *,
@@ -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,
const int, unsigned char *, const int, const int,
const int, const double);
double grayscale_reliability(MINUTIA *, unsigned char *,
const int, const int, const int);
extern void get_neighborhood_stats(double *, double *, MINUTIA *,
unsigned char *, const int, const int, const int);
extern int reliability_fr_quality_map(MINUTIAE *, int *, const int,
const int, const int, const int, const int);
/* remove.c */
extern int remove_false_minutia(MINUTIAE *,
@@ -1089,93 +990,15 @@ extern int remove_false_minutia_V2(MINUTIAE *,
unsigned char *, const int, const int,
int *, int *, int *, const int, const int,
const LFSPARMS *);
extern int remove_holes(MINUTIAE *, unsigned char *, const int, const int,
const LFSPARMS *);
extern int remove_hooks(MINUTIAE *,
unsigned char *, const int, const int, const LFSPARMS *);
extern int remove_hooks_islands_lakes_overlaps(MINUTIAE *, unsigned char *,
const int, const int, const LFSPARMS *);
extern int remove_islands_and_lakes(MINUTIAE *,
unsigned char *, const int, const int, const LFSPARMS *);
extern int remove_malformations(MINUTIAE *,
unsigned char *, const int, const int,
int *, const int, const int, const LFSPARMS *);
extern int remove_near_invblock(MINUTIAE *, int *, const int, const int,
const LFSPARMS *);
extern int remove_near_invblock_V2(MINUTIAE *, int *,
const int, const int, const LFSPARMS *);
extern int remove_pointing_invblock(MINUTIAE *, int *, const int, const int,
const LFSPARMS *);
extern int remove_pointing_invblock_V2(MINUTIAE *,
int *, const int, const int, const LFSPARMS *);
extern int remove_overlaps(MINUTIAE *,
unsigned char *, const int, const int, const LFSPARMS *);
extern int remove_pores(MINUTIAE *,
unsigned char *, const int, const int,
int *, const int, const int, const LFSPARMS *);
extern int remove_pores_V2(MINUTIAE *,
unsigned char *, const int, const int,
int *, int *, int *, const int, const int,
const LFSPARMS *);
extern int remove_or_adjust_side_minutiae(MINUTIAE *, unsigned char *,
const int, const int, const LFSPARMS *);
extern int remove_or_adjust_side_minutiae_V2(MINUTIAE *,
unsigned char *, const int, const int,
int *, const int, const int, const LFSPARMS *);
/* results.c */
extern int write_text_results(char *, const int, const int, const int,
const MINUTIAE *, int *, int *, int *, int *, int *,
const int, const int);
extern int write_minutiae_XYTQ(char *ofile, const int,
const MINUTIAE *, const int, const int);
extern void dump_map(FILE *, int *, const int, const int);
extern int drawimap(int *, const int, const int, unsigned char *,
const int, const int, const ROTGRIDS *, const int);
extern void drawimap2(int *, const int *, const int, const int,
unsigned char *, const int, const int,
const double, const int, const int);
extern void drawblocks(const int *, const int, const int,
unsigned char *, const int, const int, const int );
extern int drawrotgrid(const ROTGRIDS *, const int, unsigned char *,
const int, const int, const int, const int);
extern void dump_link_table(FILE *, const int *, const int *, const int *,
const int, const int, const int, const MINUTIAE *);
extern int draw_direction_map(char *, int *,
int *, const int, const int, const int,
unsigned char *, const int, const int, const int);
extern int draw_TF_map(char *, int *,
int *, const int, const int, const int,
unsigned char *, const int, const int, const int);
/* ridges.c */
extern int count_minutiae_ridges(MINUTIAE *,
unsigned char *, const int, const int,
const LFSPARMS *);
extern int count_minutia_ridges(const int, MINUTIAE *,
unsigned char *, const int, const int,
const LFSPARMS *);
extern int find_neighbors(int **, int *, const int, const int, MINUTIAE *);
extern int update_nbr_dists(int *, double *, int *, const int,
const int, const int, MINUTIAE *);
extern int insert_neighbor(const int, const int, const double,
int *, double *, int *, const int);
extern int sort_neighbors(int *, const int, const int, MINUTIAE *);
extern int ridge_count(const int, const int, MINUTIAE *,
unsigned char *, const int, const int, const LFSPARMS *);
extern int find_transition(int *, const int, const int,
const int *, const int *, const int,
unsigned char *, const int, const int);
extern int validate_ridge_crossing(const int, const int,
const int *, const int *, const int,
unsigned char *, const int, const int, const int);
/* shape.c */
extern int alloc_shape(SHAPE **, const int, const int, const int, const int);
extern void free_shape(SHAPE *);
extern void dump_shape(FILE *, const SHAPE *);
extern int shape_from_contour(SHAPE **, const int *, const int *, const int);
extern void sort_row_on_x(ROW *);
/* sort.c */
extern int sort_indices_int_inc(int **, int *, const int);
@@ -1200,12 +1023,6 @@ extern int line2direction(const int, const int, const int, const int,
const int);
extern int closest_dir_dist(const int, const int, const int);
/* xytreps.c */
extern void lfs2nist_minutia_XYT(int *, int *, int *,
const MINUTIA *, const int, const int);
extern void lfs2m1_minutia_XYT(int *, int *, int *, const MINUTIA *);
extern void lfs2nist_format(MINUTIAE *, int, int);
/*************************************************************************/
/* EXTERNAL GLOBAL VARIABLE DEFINITIONS */
/*************************************************************************/

View File

@@ -1,47 +1,26 @@
/*******************************************************************************
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.
License:
This software was developed at the National Institute of Standards and
Technology (NIST) by employees of the Federal Government in the course
of their official duties. Pursuant to title 17 Section 105 of the
United States Code, this software is not subject to copyright protection
and is in the public domain. NIST assumes no responsibility whatsoever for
its use by other parties, and makes no guarantees, expressed or implied,
about its quality, reliability, or any other characteristic.
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.
Disclaimer:
This software was developed to promote biometric standards and biometric
technology testing for the Federal Government in accordance with the USA
PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act.
Specific hardware and software products identified in this software were used
in order to perform the software development. In no case does such
identification imply recommendation or endorsement by the National Institute
of Standards and Technology, nor does it imply that the products and equipment
identified are necessarily the best available for the purpose.
*******************************************************************************/
#ifndef _LOG_H
#define _LOG_H
@@ -57,6 +36,10 @@ of the software.
#define LOG_FILE "log.txt"
#endif
extern FILE *g_logfp;
extern int g_avrdir;
extern float g_dir_strength;
extern int g_nvalid;
extern int open_logfile(void);
extern int close_logfile(void);

View File

@@ -1,47 +1,26 @@
/*******************************************************************************
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.
License:
This software was developed at the National Institute of Standards and
Technology (NIST) by employees of the Federal Government in the course
of their official duties. Pursuant to title 17 Section 105 of the
United States Code, this software is not subject to copyright protection
and is in the public domain. NIST assumes no responsibility whatsoever for
its use by other parties, and makes no guarantees, expressed or implied,
about its quality, reliability, or any other characteristic.
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.
Disclaimer:
This software was developed to promote biometric standards and biometric
technology testing for the Federal Government in accordance with the USA
PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act.
Specific hardware and software products identified in this software were used
in order to perform the software development. In no case does such
identification imply recommendation or endorsement by the National Institute
of Standards and Technology, nor does it imply that the products and equipment
identified are necessarily the best available for the purpose.
*******************************************************************************/
#ifndef __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

View File

@@ -1,47 +1,26 @@
/*******************************************************************************
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.
License:
This software was developed at the National Institute of Standards and
Technology (NIST) by employees of the Federal Government in the course
of their official duties. Pursuant to title 17 Section 105 of the
United States Code, this software is not subject to copyright protection
and is in the public domain. NIST assumes no responsibility whatsoever for
its use by other parties, and makes no guarantees, expressed or implied,
about its quality, reliability, or any other characteristic.
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.
Disclaimer:
This software was developed to promote biometric standards and biometric
technology testing for the Federal Government in accordance with the USA
PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act.
Specific hardware and software products identified in this software were used
in order to perform the software development. In no case does such
identification imply recommendation or endorsement by the National Institute
of Standards and Technology, nor does it imply that the products and equipment
identified are necessarily the best available for the purpose.
*******************************************************************************/
#ifndef _SUNRAST_H
#define _SUNRAST_H

View File

@@ -1,58 +0,0 @@
--- include/lfs.h 2018-08-24 15:31:54.535579623 +0200
+++ include/lfs.h.orig 2018-08-24 15:31:48.781587933 +0200
@@ -66,7 +43,7 @@ of the software.
#include <math.h>
#include <stdio.h>
-#include <an2k.h> /* Needed by to_type9.c */
+#include <fp_internal.h>
/*************************************************************************/
/* OUTPUT FILE EXTENSIONS */
@@ -154,26 +131,8 @@ typedef struct rotgrids{
#define DISAPPEARING 0
#define APPEARING 1
-typedef struct minutia{
- int x;
- int y;
- int ex;
- int ey;
- int direction;
- double reliability;
- int type;
- int appearing;
- int feature_id;
- int *nbrs;
- int *ridge_counts;
- int num_nbrs;
-} MINUTIA;
-
-typedef struct minutiae{
- int alloc;
- int num;
- MINUTIA **list;
-} MINUTIAE;
+typedef struct fp_minutia MINUTIA;
+typedef struct fp_minutiae MINUTIAE;
typedef struct feature_pattern{
int type;
@@ -1185,17 +1185,6 @@ extern void bubble_sort_double_inc_2(double *, int *, const int);
extern void bubble_sort_double_dec_2(double *, int *, const int);
extern void bubble_sort_int_inc(int *, const int);
-/* to_type9.c */
-extern int minutiae2type_9(RECORD **, const int, MINUTIAE *, const int,
- const int, const double);
-extern int mintiae2field_12(FIELD **, MINUTIAE *, const int, const int,
- const double);
-
-/* update.c */
-extern int update_ANSI_NIST_lfs_results(ANSI_NIST *, MINUTIAE *,
- unsigned char *, const int, const int,
- const int, const double, const int, const int);
-
/* util.c */
extern int maxv(const int *, const int);
extern int minv(const int *, const int);

View File

@@ -1,47 +1,26 @@
/*******************************************************************************
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.
License:
This software was developed at the National Institute of Standards and
Technology (NIST) by employees of the Federal Government in the course
of their official duties. Pursuant to title 17 Section 105 of the
United States Code, this software is not subject to copyright protection
and is in the public domain. NIST assumes no responsibility whatsoever for
its use by other parties, and makes no guarantees, expressed or implied,
about its quality, reliability, or any other characteristic.
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.
Disclaimer:
This software was developed to promote biometric standards and biometric
technology testing for the Federal Government in accordance with the USA
PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act.
Specific hardware and software products identified in this software were used
in order to perform the software development. In no case does such
identification imply recommendation or endorsement by the National Institute
of Standards and Technology, nor does it imply that the products and equipment
identified are necessarily the best available for the purpose.
*******************************************************************************/
/***********************************************************************
LIBRARY: LFS - NIST Latent Fingerprint System
@@ -57,44 +36,16 @@ of the software.
***********************************************************************
ROUTINES:
binarize()
binarize_V2()
binarize_image()
binarize_image_V2()
dirbinarize()
isobinarize()
***********************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <lfs.h>
/*************************************************************************
**************************************************************************
#cat: binarize - Takes a padded grayscale input image and its associated ridge
#cat: direction flow NMAP and produces a binarized version of the
#cat: image. It then fills horizontal and vertical "holes" in the
#cat: binary image results.
Input:
pdata - padded input grayscale image
pw - padded width (in pixels) of input image
ph - padded height (in pixels) of input image
nmap - 2-D vector of IMAP directions and other codes
mw - width (in blocks) of the NMAP
mh - height (in blocks) of the NMAP
dirbingrids - set of rotated grid offsets used for directional
binarization
lfsparms - parameters and thresholds for controlling LFS
Output:
optr - points to created (unpadded) binary image
ow - width of binary image
oh - height of binary image
Return Code:
Zero - successful completion
Negative - system error
**************************************************************************/
/*************************************************************************
**************************************************************************
#cat: binarize_V2 - Takes a padded grayscale input image and its associated
@@ -150,32 +101,6 @@ int binarize_V2(unsigned char **odata, int *ow, int *oh,
return(0);
}
/*************************************************************************
**************************************************************************
#cat: binarize_image - Takes a grayscale input image and its associated
#cat: NMAP and generates a binarized version of the image.
Input:
pdata - padded input grayscale image
pw - padded width (in pixels) of input image
ph - padded height (in pixels) of input image
nmap - 2-D vector of IMAP directions and other codes
mw - width (in blocks) of the NMAP
mh - height (in blocks) of the NMAP
imap_blocksize - dimension (in pixels) of each NMAP block
dirbingrids - set of rotated grid offsets used for directional
binarization
isobin_grid_dim - dimension (in pixels) of grid used for isotropic
binarization
Output:
optr - points to binary image results
ow - points to binary image width
oh - points to binary image height
Return Code:
Zero - successful completion
Negative - system error
**************************************************************************/
/*************************************************************************
**************************************************************************
#cat: binarize_image_V2 - Takes a grayscale input image and its associated
@@ -322,27 +247,3 @@ int dirbinarize(const unsigned char *pptr, const int idir,
return(WHITE_PIXEL);
}
/*************************************************************************
**************************************************************************
#cat: isobinarize - Determines the binary value of a grayscale pixel based
#cat: on comparing the grayscale value with a surrounding
#cat: neighborhood grid of pixels. If the current pixel (treated
#cat: as an average) is less than the sum of the pixels in
#cat: the neighborhood, then the binary value is set to BLACK,
#cat: otherwise it is set to WHITE. This binarization technique
#cat: is used when there is no VALID IMAP direction for the
#cat: block in which the current pixel resides.
CAUTION: The image to which the input pixel points must be appropriately
padded to account for the radius of the neighborhood. Otherwise,
this routine may access "unkown" memory.
Input:
pptr - pointer to curent grayscale pixel
pw - padded width (in pixels) of the grayscale image
ph - padded height (in pixels) of the grayscale image
isobin_grid_dim - dimension (in pixels) of the neighborhood
Return Code:
BLACK_PIXEL - pixel intensity for BLACK
WHITE_PIXEL - pixel intensity of WHITE
**************************************************************************/

View File

@@ -1,47 +1,26 @@
/*******************************************************************************
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.
License:
This software was developed at the National Institute of Standards and
Technology (NIST) by employees of the Federal Government in the course
of their official duties. Pursuant to title 17 Section 105 of the
United States Code, this software is not subject to copyright protection
and is in the public domain. NIST assumes no responsibility whatsoever for
its use by other parties, and makes no guarantees, expressed or implied,
about its quality, reliability, or any other characteristic.
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.
Disclaimer:
This software was developed to promote biometric standards and biometric
technology testing for the Federal Government in accordance with the USA
PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act.
Specific hardware and software products identified in this software were used
in order to perform the software development. In no case does such
identification imply recommendation or endorsement by the National Institute
of Standards and Technology, nor does it imply that the products and equipment
identified are necessarily the best available for the purpose.
*******************************************************************************/
/***********************************************************************
LIBRARY: LFS - NIST Latent Fingerprint System
@@ -65,6 +44,8 @@ of the software.
***********************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <lfs.h>
/*************************************************************************
@@ -115,7 +96,7 @@ int block_offsets(int **optr, int *ow, int *oh,
return(-80);
}
/* Compute padded width of image */
/* Compute padded width and height of image */
pad2 = pad<<1;
pw = iw + pad2;

View File

@@ -1,211 +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.
*******************************************************************************/
/***********************************************************************
LIBRARY: LFS - NIST Latent Fingerprint System
FILE: CHAINCODE.C
AUTHOR: Michael D. Garris
DATE: 05/11/1999
Contains routines responsible for generating and manipulating
chain codes as part of the NIST Latent Fingerprint System (LFS).
***********************************************************************
ROUTINES:
chain_code_loop()
is_chain_clockwise()
***********************************************************************/
#include <stdio.h>
#include <lfs.h>
/*************************************************************************
**************************************************************************
#cat: chain_code_loop - Converts a feature's contour points into an
#cat: 8-connected chain code vector. This encoding represents
#cat: the direction taken between each adjacent point in the
#cat: contour. Chain codes may be used for many purposes, such
#cat: as computing the perimeter or area of an object, and they
#cat: may be used in object detection and recognition.
Input:
contour_x - x-coord list for feature's contour points
contour_y - y-coord list for feature's contour points
ncontour - number of points in contour
Output:
ochain - resulting vector of chain codes
onchain - number of codes in chain
(same as number of points in contour)
Return Code:
Zero - chain code successful derived
Negative - system error
**************************************************************************/
int chain_code_loop(int **ochain, int *onchain,
const int *contour_x, const int *contour_y, const int ncontour)
{
int *chain;
int i, j, dx, dy;
/* If we don't have at least 3 points in the contour ... */
if(ncontour <= 3){
/* Then we don't have a loop, so set chain length to 0 */
/* and return without any allocations. */
*onchain = 0;
return(0);
}
/* Allocate chain code vector. It will be the same length as the */
/* number of points in the contour. There will be one chain code */
/* between each point on the contour including a code between the */
/* last to the first point on the contour (completing the loop). */
chain = (int *)malloc(ncontour * sizeof(int));
/* If the allocation fails ... */
if(chain == (int *)NULL){
fprintf(stderr, "ERROR : chain_code_loop : malloc : chain\n");
return(-170);
}
/* For each neighboring point in the list (with "i" pointing to the */
/* previous neighbor and "j" pointing to the next neighbor... */
for(i = 0, j=1; i < ncontour-1; i++, j++){
/* Compute delta in X between neighbors. */
dx = contour_x[j] - contour_x[i];
/* Compute delta in Y between neighbors. */
dy = contour_y[j] - contour_y[i];
/* Derive chain code index from neighbor deltas. */
/* The deltas are on the range [-1..1], so to use them as indices */
/* into the code list, they must first be incremented by one. */
chain[i] = *(g_chaincodes_nbr8+((dy+1)*NBR8_DIM)+dx+1);
}
/* Now derive chain code between last and first points in the */
/* contour list. */
dx = contour_x[0] - contour_x[i];
dy = contour_y[0] - contour_y[i];
chain[i] = *(g_chaincodes_nbr8+((dy+1)*NBR8_DIM)+dx+1);
/* Store results to the output pointers. */
*ochain = chain;
*onchain = ncontour;
/* Return normally. */
return(0);
}
/*************************************************************************
**************************************************************************
#cat: is_chain_clockwise - Takes an 8-connected chain code vector and
#cat: determines if the codes are ordered clockwise or
#cat: counter-clockwise.
#cat: The routine also requires a default return value be
#cat: specified in the case the the routine is not able to
#cat: definitively determine the chains direction. This allows
#cat: the default response to be application-specific.
Input:
chain - chain code vector
nchain - number of codes in chain
default_ret - default return code (used when we can't tell the order)
Return Code:
TRUE - chain determined to be ordered clockwise
FALSE - chain determined to be ordered counter-clockwise
Default - could not determine the order of the chain
**************************************************************************/
int is_chain_clockwise(const int *chain, const int nchain,
const int default_ret)
{
int i, j, d, sum;
/* Initialize turn-accumulator to 0. */
sum = 0;
/* Foreach neighboring code in chain, compute the difference in */
/* direction and accumulate. Left-hand turns increment, whereas */
/* right-hand decrement. */
for(i = 0, j =1; i < nchain-1; i++, j++){
/* Compute delta in neighbor direction. */
d = chain[j] - chain[i];
/* Make the delta the "inner" distance. */
/* If delta >= 4, for example if chain_i==2 and chain_j==7 (which */
/* means the contour went from a step up to step down-to-the-right) */
/* then 5=(7-2) which is >=4, so -3=(5-8) which means that the */
/* change in direction is a righ-hand turn of 3 units). */
if(d >= 4)
d -= 8;
/* If delta <= -4, for example if chain_i==7 and chain_j==2 (which */
/* means the contour went from a step down-to-the-right to step up) */
/* then -5=(2-7) which is <=-4, so 3=(-5+8) which means that the */
/* change in direction is a left-hand turn of 3 units). */
else if (d <= -4)
d += 8;
/* The delta direction is then accumulated. */
sum += d;
}
/* Now we need to add in the final delta direction between the last */
/* and first codes in the chain. */
d = chain[0] - chain[i];
if(d >= 4)
d -= 8;
else if (d <= -4)
d += 8;
sum += d;
/* If the final turn_accumulator == 0, then we CAN'T TELL the */
/* direction of the chain code, so return the default return value. */
if(sum == 0)
return(default_ret);
/* Otherwise, if the final turn-accumulator is positive ... */
else if(sum > 0)
/* Then we had a greater amount of left-hand turns than right-hand */
/* turns, so the chain is in COUNTER-CLOCKWISE order, so return FALSE. */
return(FALSE);
/* Otherwise, the final turn-accumulator is negative ... */
else
/* So we had a greater amount of right-hand turns than left-hand */
/* turns, so the chain is in CLOCKWISE order, so return TRUE. */
return(TRUE);
}

View File

@@ -1,47 +1,26 @@
/*******************************************************************************
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.
License:
This software was developed at the National Institute of Standards and
Technology (NIST) by employees of the Federal Government in the course
of their official duties. Pursuant to title 17 Section 105 of the
United States Code, this software is not subject to copyright protection
and is in the public domain. NIST assumes no responsibility whatsoever for
its use by other parties, and makes no guarantees, expressed or implied,
about its quality, reliability, or any other characteristic.
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.
Disclaimer:
This software was developed to promote biometric standards and biometric
technology testing for the Federal Government in accordance with the USA
PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act.
Specific hardware and software products identified in this software were used
in order to perform the software development. In no case does such
identification imply recommendation or endorsement by the National Institute
of Standards and Technology, nor does it imply that the products and equipment
identified are necessarily the best available for the purpose.
*******************************************************************************/
/***********************************************************************
LIBRARY: LFS - NIST Latent Fingerprint System
@@ -71,6 +50,7 @@ of the software.
***********************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <lfs.h>
/*************************************************************************
@@ -107,8 +87,6 @@ int allocate_contour(int **ocontour_x, int **ocontour_y,
{
int *contour_x, *contour_y, *contour_ex, *contour_ey;
ASSERT_SIZE_MUL(ncontour, sizeof(int));
/* Allocate contour's x-coord list. */
contour_x = (int *)malloc(ncontour*sizeof(int));
/* If allocation error... */
@@ -519,8 +497,6 @@ int get_centered_contour(int **ocontour_x, int **ocontour_y,
/* If system error occurred on 2nd trace ... */
if(ret < 0){
/* Deallocate loop's contour. */
free_contour(half1_x, half1_y, half1_ex, half1_ey);
/* Return error code. */
return(ret);
}
@@ -615,6 +591,236 @@ int get_centered_contour(int **ocontour_x, int **ocontour_y,
return(0);
}
/*************************************************************************
**************************************************************************
#cat: start_scan_nbr - Takes a two pixel coordinates that are either
#cat: aligned north-to-south or east-to-west, and returns the
#cat: position the second pixel is in realtionship to the first.
#cat: The positions returned are based on 8-connectedness.
#cat: NOTE, this routine does NOT account for diagonal positions.
Input:
x_prev - x-coord of first point
y_prev - y-coord of first point
x_next - x-coord of second point
y_next - y-coord of second point
Return Code:
NORTH - second pixel above first
SOUTH - second pixel below first
EAST - second pixel right of first
WEST - second pixel left of first
**************************************************************************/
static int start_scan_nbr(const int x_prev, const int y_prev,
const int x_next, const int y_next)
{
if((x_prev==x_next) && (y_next > y_prev))
return(SOUTH);
else if ((x_prev==x_next) && (y_next < y_prev))
return(NORTH);
else if ((x_next > x_prev) && (y_prev==y_next))
return(EAST);
else if ((x_next < x_prev) && (y_prev==y_next))
return(WEST);
/* Added by MDG on 03-16-05 */
/* Should never reach here. Added to remove compiler warning. */
return(INVALID_DIR); /* -1 */
}
/*************************************************************************
**************************************************************************
#cat: next_scan_nbr - Advances the given 8-connected neighbor index
#cat: on location in the specifiec direction (clockwise or
#cat: counter-clockwise).
Input:
nbr_i - current 8-connected neighbor index
scan_clock - direction in which the neighbor index is to be advanced
Return Code:
Next neighbor - 8-connected index of next neighbor
**************************************************************************/
static int next_scan_nbr(const int nbr_i, const int scan_clock)
{
int new_i;
/* If scanning neighbors clockwise ... */
if(scan_clock == SCAN_CLOCKWISE)
/* Advance one neighbor clockwise. */
new_i = (nbr_i+1)%8;
/* Otherwise, scanning neighbors counter-clockwise ... */
else
/* Advance one neighbor counter-clockwise. */
/* There are 8 pixels in the neighborhood, so to */
/* decrement with wrapping from 0 around to 7, add */
/* the nieghbor index by 7 and mod with 8. */
new_i = (nbr_i+7)%8;
/* Return the new neighbor index. */
return(new_i);
}
/*************************************************************************
**************************************************************************
#cat: next_contour_pixel - Takes a pixel coordinate of a point determined
#cat: to be on the interior edge of a feature (ridge or valley-
#cat: ending), and attempts to locate a neighboring pixel on the
#cat: feature's contour. Neighbors of the current feature pixel
#cat: are searched in a specified direction (clockwise or counter-
#cat: clockwise) and the first pair of adjacent/neigboring pixels
#cat: found with the first pixel having the color of the feature
#cat: and the second the opposite color are returned as the next
#cat: point on the contour. One exception happens when the new
#cat: point is on an "exposed" corner.
Input:
cur_x_loc - x-pixel coord of current point on feature's
interior contour
cur_y_loc - y-pixel coord of current point on feature's
interior contour
cur_x_edge - x-pixel coord of corresponding edge pixel
(exterior to feature)
cur_y_edge - y-pixel coord of corresponding edge pixel
(exterior to feature)
scan_clock - direction in which neighboring pixels are to be scanned
for the next contour pixel
bdata - binary image data (0==while & 1==black)
iw - width (in pixels) of image
ih - height (in pixels) of image
Output:
next_x_loc - x-pixel coord of next point on feature's interior contour
next_y_loc - y-pixel coord of next point on feature's interior contour
next_x_edge - x-pixel coord of corresponding edge (exterior to feature)
next_y_edge - y-pixel coord of corresponding edge (exterior to feature)
Return Code:
TRUE - next contour point found and returned
FALSE - next contour point NOT found
**************************************************************************/
/*************************************************************************/
static int next_contour_pixel(int *next_x_loc, int *next_y_loc,
int *next_x_edge, int *next_y_edge,
const int cur_x_loc, const int cur_y_loc,
const int cur_x_edge, const int cur_y_edge,
const int scan_clock,
unsigned char *bdata, const int iw, const int ih)
{
int feature_pix, edge_pix;
int prev_nbr_pix, prev_nbr_x, prev_nbr_y;
int cur_nbr_pix, cur_nbr_x, cur_nbr_y;
int ni, nx, ny, npix;
int nbr_i, i;
/* Get the feature's pixel value. */
feature_pix = *(bdata + (cur_y_loc * iw) + cur_x_loc);
/* Get the feature's edge pixel value. */
edge_pix = *(bdata + (cur_y_edge * iw) + cur_x_edge);
/* Get the nieghbor position of the feature's edge pixel in relationship */
/* to the feature's actual position. */
/* REMEBER: The feature's position is always interior and on a ridge */
/* ending (black pixel) or (for bifurcations) on a valley ending (white */
/* pixel). The feature's edge pixel is an adjacent pixel to the feature */
/* pixel that is exterior to the ridge or valley ending and opposite in */
/* pixel value. */
nbr_i = start_scan_nbr(cur_x_loc, cur_y_loc, cur_x_edge, cur_y_edge);
/* Set current neighbor scan pixel to the feature's edge pixel. */
cur_nbr_x = cur_x_edge;
cur_nbr_y = cur_y_edge;
cur_nbr_pix = edge_pix;
/* Foreach pixel neighboring the feature pixel ... */
for(i = 0; i < 8; i++){
/* Set current neighbor scan pixel to previous scan pixel. */
prev_nbr_x = cur_nbr_x;
prev_nbr_y = cur_nbr_y;
prev_nbr_pix = cur_nbr_pix;
/* Bump pixel neighbor index clockwise or counter-clockwise. */
nbr_i = next_scan_nbr(nbr_i, scan_clock);
/* Set current scan pixel to the new neighbor. */
/* REMEMBER: the neighbors are being scanned around the original */
/* feature point. */
cur_nbr_x = cur_x_loc + g_nbr8_dx[nbr_i];
cur_nbr_y = cur_y_loc + g_nbr8_dy[nbr_i];
/* If new neighbor is not within image boundaries... */
if((cur_nbr_x < 0) || (cur_nbr_x >= iw) ||
(cur_nbr_y < 0) || (cur_nbr_y >= ih))
/* Return (FALSE==>Failure) if neighbor out of bounds. */
return(FALSE);
/* Get the new neighbor's pixel value. */
cur_nbr_pix = *(bdata + (cur_nbr_y * iw) + cur_nbr_x);
/* If the new neighbor's pixel value is the same as the feature's */
/* pixel value AND the previous neighbor's pixel value is the same */
/* as the features's edge, then we have "likely" found our next */
/* contour pixel. */
if((cur_nbr_pix == feature_pix) && (prev_nbr_pix == edge_pix)){
/* Check to see if current neighbor is on the corner of the */
/* neighborhood, and if so, test to see if it is "exposed". */
/* The neighborhood corners have odd neighbor indicies. */
if(nbr_i % 2){
/* To do this, look ahead one more neighbor pixel. */
ni = next_scan_nbr(nbr_i, scan_clock);
nx = cur_x_loc + g_nbr8_dx[ni];
ny = cur_y_loc + g_nbr8_dy[ni];
/* If new neighbor is not within image boundaries... */
if((nx < 0) || (nx >= iw) ||
(ny < 0) || (ny >= ih))
/* Return (FALSE==>Failure) if neighbor out of bounds. */
return(FALSE);
npix = *(bdata + (ny * iw) + nx);
/* If the next neighbor's value is also the same as the */
/* feature's pixel, then corner is NOT exposed... */
if(npix == feature_pix){
/* Assign the current neighbor pair to the output pointers. */
*next_x_loc = cur_nbr_x;
*next_y_loc = cur_nbr_y;
*next_x_edge = prev_nbr_x;
*next_y_edge = prev_nbr_y;
/* Return TRUE==>Success. */
return(TRUE);
}
/* Otherwise, corner pixel is "exposed" so skip it. */
else{
/* Skip current corner neighbor by resetting it to the */
/* next neighbor, which upon the iteration will immediately */
/* become the previous neighbor. */
cur_nbr_x = nx;
cur_nbr_y = ny;
cur_nbr_pix = npix;
/* Advance neighbor index. */
nbr_i = ni;
/* Advance neighbor count. */
i++;
}
}
/* Otherwise, current neighbor is not a corner ... */
else{
/* Assign the current neighbor pair to the output pointers. */
*next_x_loc = cur_nbr_x;
*next_y_loc = cur_nbr_y;
*next_x_edge = prev_nbr_x;
*next_y_edge = prev_nbr_y;
/* Return TRUE==>Success. */
return(TRUE);
}
}
}
/* If we get here, then we did not find the next contour pixel */
/* within the 8 neighbors of the current feature pixel so */
/* return (FALSE==>Failure). */
/* NOTE: This must mean we found a single isolated pixel. */
/* Perhaps this should be filled? */
return(FALSE);
}
/*************************************************************************
**************************************************************************
#cat: trace_contour - Takes the pixel coordinate of a detected minutia
@@ -840,236 +1046,6 @@ int search_contour(const int x_search, const int y_search,
return(NOT_FOUND);
}
/*************************************************************************
**************************************************************************
#cat: next_contour_pixel - Takes a pixel coordinate of a point determined
#cat: to be on the interior edge of a feature (ridge or valley-
#cat: ending), and attempts to locate a neighboring pixel on the
#cat: feature's contour. Neighbors of the current feature pixel
#cat: are searched in a specified direction (clockwise or counter-
#cat: clockwise) and the first pair of adjacent/neigboring pixels
#cat: found with the first pixel having the color of the feature
#cat: and the second the opposite color are returned as the next
#cat: point on the contour. One exception happens when the new
#cat: point is on an "exposed" corner.
Input:
cur_x_loc - x-pixel coord of current point on feature's
interior contour
cur_y_loc - y-pixel coord of current point on feature's
interior contour
cur_x_edge - x-pixel coord of corresponding edge pixel
(exterior to feature)
cur_y_edge - y-pixel coord of corresponding edge pixel
(exterior to feature)
scan_clock - direction in which neighboring pixels are to be scanned
for the next contour pixel
bdata - binary image data (0==while & 1==black)
iw - width (in pixels) of image
ih - height (in pixels) of image
Output:
next_x_loc - x-pixel coord of next point on feature's interior contour
next_y_loc - y-pixel coord of next point on feature's interior contour
next_x_edge - x-pixel coord of corresponding edge (exterior to feature)
next_y_edge - y-pixel coord of corresponding edge (exterior to feature)
Return Code:
TRUE - next contour point found and returned
FALSE - next contour point NOT found
**************************************************************************/
/*************************************************************************/
int next_contour_pixel(int *next_x_loc, int *next_y_loc,
int *next_x_edge, int *next_y_edge,
const int cur_x_loc, const int cur_y_loc,
const int cur_x_edge, const int cur_y_edge,
const int scan_clock,
unsigned char *bdata, const int iw, const int ih)
{
int feature_pix, edge_pix;
int prev_nbr_pix, prev_nbr_x, prev_nbr_y;
int cur_nbr_pix, cur_nbr_x, cur_nbr_y;
int ni, nx, ny, npix;
int nbr_i, i;
/* Get the feature's pixel value. */
feature_pix = *(bdata + (cur_y_loc * iw) + cur_x_loc);
/* Get the feature's edge pixel value. */
edge_pix = *(bdata + (cur_y_edge * iw) + cur_x_edge);
/* Get the nieghbor position of the feature's edge pixel in relationship */
/* to the feature's actual position. */
/* REMEBER: The feature's position is always interior and on a ridge */
/* ending (black pixel) or (for bifurcations) on a valley ending (white */
/* pixel). The feature's edge pixel is an adjacent pixel to the feature */
/* pixel that is exterior to the ridge or valley ending and opposite in */
/* pixel value. */
nbr_i = start_scan_nbr(cur_x_loc, cur_y_loc, cur_x_edge, cur_y_edge);
/* Set current neighbor scan pixel to the feature's edge pixel. */
cur_nbr_x = cur_x_edge;
cur_nbr_y = cur_y_edge;
cur_nbr_pix = edge_pix;
/* Foreach pixel neighboring the feature pixel ... */
for(i = 0; i < 8; i++){
/* Set current neighbor scan pixel to previous scan pixel. */
prev_nbr_x = cur_nbr_x;
prev_nbr_y = cur_nbr_y;
prev_nbr_pix = cur_nbr_pix;
/* Bump pixel neighbor index clockwise or counter-clockwise. */
nbr_i = next_scan_nbr(nbr_i, scan_clock);
/* Set current scan pixel to the new neighbor. */
/* REMEMBER: the neighbors are being scanned around the original */
/* feature point. */
cur_nbr_x = cur_x_loc + g_nbr8_dx[nbr_i];
cur_nbr_y = cur_y_loc + g_nbr8_dy[nbr_i];
/* If new neighbor is not within image boundaries... */
if((cur_nbr_x < 0) || (cur_nbr_x >= iw) ||
(cur_nbr_y < 0) || (cur_nbr_y >= ih))
/* Return (FALSE==>Failure) if neighbor out of bounds. */
return(FALSE);
/* Get the new neighbor's pixel value. */
cur_nbr_pix = *(bdata + (cur_nbr_y * iw) + cur_nbr_x);
/* If the new neighbor's pixel value is the same as the feature's */
/* pixel value AND the previous neighbor's pixel value is the same */
/* as the features's edge, then we have "likely" found our next */
/* contour pixel. */
if((cur_nbr_pix == feature_pix) && (prev_nbr_pix == edge_pix)){
/* Check to see if current neighbor is on the corner of the */
/* neighborhood, and if so, test to see if it is "exposed". */
/* The neighborhood corners have odd neighbor indicies. */
if(nbr_i % 2){
/* To do this, look ahead one more neighbor pixel. */
ni = next_scan_nbr(nbr_i, scan_clock);
nx = cur_x_loc + g_nbr8_dx[ni];
ny = cur_y_loc + g_nbr8_dy[ni];
/* If new neighbor is not within image boundaries... */
if((nx < 0) || (nx >= iw) ||
(ny < 0) || (ny >= ih))
/* Return (FALSE==>Failure) if neighbor out of bounds. */
return(FALSE);
npix = *(bdata + (ny * iw) + nx);
/* If the next neighbor's value is also the same as the */
/* feature's pixel, then corner is NOT exposed... */
if(npix == feature_pix){
/* Assign the current neighbor pair to the output pointers. */
*next_x_loc = cur_nbr_x;
*next_y_loc = cur_nbr_y;
*next_x_edge = prev_nbr_x;
*next_y_edge = prev_nbr_y;
/* Return TRUE==>Success. */
return(TRUE);
}
/* Otherwise, corner pixel is "exposed" so skip it. */
else{
/* Skip current corner neighbor by resetting it to the */
/* next neighbor, which upon the iteration will immediately */
/* become the previous neighbor. */
cur_nbr_x = nx;
cur_nbr_y = ny;
cur_nbr_pix = npix;
/* Advance neighbor index. */
nbr_i = ni;
/* Advance neighbor count. */
i++;
}
}
/* Otherwise, current neighbor is not a corner ... */
else{
/* Assign the current neighbor pair to the output pointers. */
*next_x_loc = cur_nbr_x;
*next_y_loc = cur_nbr_y;
*next_x_edge = prev_nbr_x;
*next_y_edge = prev_nbr_y;
/* Return TRUE==>Success. */
return(TRUE);
}
}
}
/* If we get here, then we did not find the next contour pixel */
/* within the 8 neighbors of the current feature pixel so */
/* return (FALSE==>Failure). */
/* NOTE: This must mean we found a single isolated pixel. */
/* Perhaps this should be filled? */
return(FALSE);
}
/*************************************************************************
**************************************************************************
#cat: start_scan_nbr - Takes a two pixel coordinates that are either
#cat: aligned north-to-south or east-to-west, and returns the
#cat: position the second pixel is in realtionship to the first.
#cat: The positions returned are based on 8-connectedness.
#cat: NOTE, this routine does NOT account for diagonal positions.
Input:
x_prev - x-coord of first point
y_prev - y-coord of first point
x_next - x-coord of second point
y_next - y-coord of second point
Return Code:
NORTH - second pixel above first
SOUTH - second pixel below first
EAST - second pixel right of first
WEST - second pixel left of first
**************************************************************************/
int start_scan_nbr(const int x_prev, const int y_prev,
const int x_next, const int y_next)
{
if((x_prev==x_next) && (y_next > y_prev))
return(SOUTH);
else if ((x_prev==x_next) && (y_next < y_prev))
return(NORTH);
else if ((x_next > x_prev) && (y_prev==y_next))
return(EAST);
else if ((x_next < x_prev) && (y_prev==y_next))
return(WEST);
/* Added by MDG on 03-16-05 */
/* Should never reach here. Added to remove compiler warning. */
return(INVALID_DIR); /* -1 */
}
/*************************************************************************
**************************************************************************
#cat: next_scan_nbr - Advances the given 8-connected neighbor index
#cat: on location in the specifiec direction (clockwise or
#cat: counter-clockwise).
Input:
nbr_i - current 8-connected neighbor index
scan_clock - direction in which the neighbor index is to be advanced
Return Code:
Next neighbor - 8-connected index of next neighbor
**************************************************************************/
int next_scan_nbr(const int nbr_i, const int scan_clock)
{
int new_i;
/* If scanning neighbors clockwise ... */
if(scan_clock == SCAN_CLOCKWISE)
/* Advance one neighbor clockwise. */
new_i = (nbr_i+1)%8;
/* Otherwise, scanning neighbors counter-clockwise ... */
else
/* Advance one neighbor counter-clockwise. */
/* There are 8 pixels in the neighborhood, so to */
/* decrement with wrapping from 0 around to 7, add */
/* the nieghbor index by 7 and mod with 8. */
new_i = (nbr_i+7)%8;
/* Return the new neighbor index. */
return(new_i);
}
/*************************************************************************
**************************************************************************
#cat: min_contour_theta - Takes a contour list and analyzes it locating the

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