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
139 changed files with 8362 additions and 14756 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',
@@ -27,7 +23,6 @@ private_headers = [
'vfs301_proto_fragments.h',
'vfs301_proto.h',
'vfs5011_proto.h',
'synaptics.h',
# NBIS
'morph.h',
@@ -37,7 +32,6 @@ private_headers = [
'log.h',
'bz_array.h',
'lfs.h',
'mytime.h',
]
html_images = [
@@ -60,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

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

View File

@@ -45,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);
@@ -142,10 +143,7 @@ int main(void)
if (!data)
goto out_close;
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
r = fp_print_data_save(data, RIGHT_INDEX);
#pragma GCC diagnostic pop
if (r < 0)
fprintf(stderr, "Data save failed, code %d\n", r);

View File

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

View File

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

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,63 +622,8 @@ 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;
}
/**
* fp_async_delete_finger:
* @dev: the struct #fp_dev device
* @data: data to delete. Must have been previously enrolled.
* @callback: the callback to call when data deleted.
* @user_data: user data to pass to the callback
*
* Request to delete data in sensor.
*
* Returns: 0 on success, non-zero on error
*/
API_EXPORTED int fp_async_delete_finger(struct fp_dev *dev,
struct fp_print_data *data, fp_delete_cb callback, void *user_data)
{
struct fp_driver *drv;
int r;
g_return_val_if_fail(dev != NULL, -ENODEV);
g_return_val_if_fail (callback != NULL, -EINVAL);
drv = dev->drv;
G_DEBUG_HERE();
if (!drv->delete_finger)
return -ENOTSUP;
dev->state = DEV_STATE_DELETING;
dev->delete_cb = callback;
dev->delete_cb_data = user_data;
dev->delete_data = data;
r = drv->delete_finger(dev);
if (r < 0) {
dev->delete_cb = NULL;
dev->state = DEV_STATE_ERROR;
fp_err("failed to delete data, error %d", r);
}
return r;
}
/* Drivers call this when delete done */
void fpi_drvcb_delete_complete(struct fp_dev *dev, int status)
{
fp_dbg("status %d", status);
BUG_ON(dev->state != DEV_STATE_DELETING);
dev->state = (status) ? DEV_STATE_ERROR : DEV_STATE_DELETE_DONE;
if (dev->delete_cb)
dev->delete_cb(dev, status, dev->delete_cb_data);
}

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,29 +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_supports_data_in_sensor:
* @dev: the struct #fp_dev device
*
* Determines if a device is capable of storing print data in sensor.
* Not all devices support this functionality.
*
* Returns: 1 if the device is capable of storing data in sensor, 0 otherwise.
*/
API_EXPORTED int fp_dev_supports_data_in_sensor(struct fp_dev *dev)
{
return dev->drv->delete_finger != NULL;
}
/**
* fp_dev_get_img_width:
* @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
@@ -732,19 +678,18 @@ API_EXPORTED int fp_dev_supports_data_in_sensor(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
@@ -756,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));
@@ -751,9 +766,10 @@ static void activate_sm_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_d
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, enum fp_imgdev_state state)
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));
@@ -794,9 +804,10 @@ static void activate_sm_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_d
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, enum fp_imgdev_state state)
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));
@@ -543,22 +581,23 @@ static void activate_sm_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_d
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);
@@ -139,14 +144,14 @@ static void init_reqs_cb(struct fp_img_dev *dev, int result, void *user_data)
int aes3k_dev_activate(struct fp_img_dev *dev, enum fp_imgdev_state state)
{
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

@@ -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);
@@ -591,15 +594,16 @@ static void activate_sm_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_d
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

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

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);
@@ -1392,8 +1400,8 @@ static void m_init_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
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);
@@ -1408,14 +1416,16 @@ static int dev_activate(struct fp_img_dev *idev, enum fp_imgdev_state state)
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;
@@ -1423,16 +1433,15 @@ static int dev_activate(struct fp_img_dev *idev, enum fp_imgdev_state state)
static void dev_deactivate(struct fp_img_dev *idev)
{
struct etes603_dev *dev = 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)
@@ -1441,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;
@@ -1459,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);
}

View File

@@ -169,25 +169,25 @@ capture(struct fp_img_dev *dev, gboolean unconditional,
image = g_malloc0(RAW_IMAGE_SIZE);
if ((r = bulk_write_safe(fpi_dev_get_usb_dev(FP_DEV(dev)), LED_ON))) {
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_dev_get_usb_dev(FP_DEV(dev)), CAPTURE_READY))) {
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_dev_get_usb_dev(FP_DEV(dev)), CAPTURE_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_dev_get_usb_dev(FP_DEV(dev)), &msg, &bytes, BULK_TIMEOUT * 10);
r = libusb_bulk_transfer(fpi_imgdev_get_usb_dev(dev), &msg, &bytes, BULK_TIMEOUT * 10);
if (r < 0 || bytes < 1)
goto read;
@@ -215,7 +215,7 @@ read:
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
*/
@@ -228,12 +228,12 @@ read:
}
}
if ((r = bulk_write_safe(fpi_dev_get_usb_dev(FP_DEV(dev)), CAPTURE_END))) {
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_dev_get_usb_dev(FP_DEV(dev)), LED_OFF))) {
if ((r = bulk_write_safe(fpi_imgdev_get_usb_dev(dev), LED_OFF))) {
fp_err("Command: LED_OFF");
goto out;
}
@@ -254,27 +254,27 @@ static
gint dev_init(struct fp_img_dev *dev, unsigned long driver_data)
{
gint r;
//if ( (r = usb_set_configuration(fpi_dev_get_usb_dev(FP_DEV(dev)), 1)) < 0 )
//if ( (r = usb_set_configuration(fpi_imgdev_get_usb_dev(dev), 1)) < 0 )
// goto out;
if ( (r = libusb_claim_interface(fpi_dev_get_usb_dev(FP_DEV(dev)), 0)) < 0 ) {
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_dev_get_usb_dev(FP_DEV(dev)), 1)) < 0 )
//if ( (r = usb_set_altinterface(fpi_imgdev_get_usb_dev(dev), 1)) < 0 )
// goto out;
//if ( (r = usb_clear_halt(fpi_dev_get_usb_dev(FP_DEV(dev)), EP_CMD)) < 0 )
//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_dev_get_usb_dev(FP_DEV(dev)), CAPTURE_END))) {
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_dev_get_usb_dev(FP_DEV(dev)), LED_OFF))) {
if ((r = bulk_write_safe(fpi_imgdev_get_usb_dev(dev), LED_OFF))) {
fp_err("Command: LED_OFF");
goto out;
}
@@ -289,10 +289,10 @@ out:
static
void dev_exit(struct fp_img_dev *dev)
{
if (bulk_write_safe(fpi_dev_get_usb_dev(FP_DEV(dev)), CAPTURE_END))
if (bulk_write_safe(fpi_imgdev_get_usb_dev(dev), CAPTURE_END))
fp_err("Command: CAPTURE_END");
libusb_release_interface(fpi_dev_get_usb_dev(FP_DEV(dev)), 0);
libusb_release_interface(fpi_imgdev_get_usb_dev(dev), 0);
}
static const struct usb_id id_table[] = {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -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, 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, enum fp_imgdev_state state)
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, 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, enum fp_imgdev_state state)
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);
@@ -569,9 +622,10 @@ static void activate_sm_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_d
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, enum fp_imgdev_state state)
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,9 +1138,9 @@ 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);
@@ -1176,8 +1159,8 @@ static void activate_initsm_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *us
* 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);
@@ -1186,7 +1169,8 @@ static int dev_activate(struct fp_img_dev *dev, enum fp_imgdev_state state)
urudev->scanpwr_irq_timeouts = 0;
urudev->activate_state = state;
ssm = fpi_ssm_new(FP_DEV(dev), init_run_state, INIT_NUM_STATES, dev);
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;
}
@@ -1211,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:
@@ -1236,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,
@@ -1280,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;
@@ -1334,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) {
@@ -1351,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;
@@ -1379,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:
@@ -1388,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);
@@ -304,9 +313,10 @@ static void loopsm_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
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, enum fp_imgdev_state state)
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;
@@ -686,14 +684,15 @@ 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, 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, enum fp_imgdev_state state)
/* 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);
}
@@ -1426,8 +1441,8 @@ 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, 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, enum fp_imgdev_state state)
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, enum fp_imgdev_state state)
/* 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);
}
@@ -193,10 +203,11 @@ 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, 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, enum fp_imgdev_state state)
/* Deactivate device */
static void dev_deactivate(struct fp_img_dev *dev)
{
vfs301_dev_t *vdev;
vdev = FP_INSTANCE_DATA(FP_DEV(dev));
vfs301_proto_deinit(fpi_dev_get_usb_dev(FP_DEV(dev)), vdev);
fpi_imgdev_deactivate_complete(dev);
}
@@ -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,12 +853,13 @@ 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");
@@ -850,7 +869,7 @@ 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,
@@ -77,31 +69,21 @@ enum fp_dev_state {
DEV_STATE_CAPTURING,
DEV_STATE_CAPTURE_DONE,
DEV_STATE_CAPTURE_STOPPING,
DEV_STATE_DELETING,
DEV_STATE_DELETE_DONE,
DEV_STATE_DELETE_STOPPING,
};
struct fp_driver **fprint_get_drivers (void);
struct fp_dev {
struct fp_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;
struct fp_print_data *delete_data;
/* drivers should not mess with any of the below */
enum fp_dev_state state;
int __enroll_stage;
@@ -129,17 +111,44 @@ struct fp_dev {
void *capture_cb_data;
fp_operation_stop_cb capture_stop_cb;
void *capture_stop_cb_data;
fp_delete_cb delete_cb;
void *delete_cb_data;
/* FIXME: better place to put this? */
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;
@@ -151,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;
@@ -170,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;
@@ -178,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;
@@ -194,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);
@@ -227,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,42 +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);
void fpi_drvcb_delete_complete(struct fp_dev *dev, int status);
#endif

View File

@@ -1,119 +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);
int (*delete_finger)(struct fp_dev *dev);
};
/**
* FpiImgDriverFlags:
* @FP_IMGDRV_SUPPORTS_UNCONDITIONAL_CAPTURE: Whether the driver supports
* unconditional image capture. No driver currently does.
*
* Flags used in the #fp_img_driver to advertise the capabilities of drivers.
*/
typedef enum {
FP_IMGDRV_SUPPORTS_UNCONDITIONAL_CAPTURE = 1 << 0
} FpiImgDriverFlags;
struct fp_img_driver {
struct fp_driver driver;
FpiImgDriverFlags flags;
int img_width;
int img_height;
int bz3_threshold;
/* Device operations */
int (*open)(struct fp_img_dev *dev, unsigned long driver_data);
void (*close)(struct fp_img_dev *dev);
int (*activate)(struct fp_img_dev *dev, enum fp_imgdev_state state);
int (*change_state)(struct fp_img_dev *dev, enum fp_imgdev_state state);
void (*deactivate)(struct fp_img_dev *dev);
};
#endif

View File

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

View File

@@ -1,49 +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);
struct fp_print_data *fpi_dev_get_delete_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,
@@ -267,26 +258,19 @@ int fp_verify_finger(struct fp_dev *dev,
struct fp_print_data *enrolled_print);
int fp_dev_supports_identification(struct fp_dev *dev);
int fp_dev_supports_data_in_sensor(struct fp_dev *dev);
int fp_identify_finger_img(struct fp_dev *dev,
struct fp_print_data **print_gallery, size_t *match_offset,
struct fp_img **img);
int fp_identify_finger(struct fp_dev *dev,
struct fp_print_data **print_gallery, size_t *match_offset);
int fp_delete_finger(struct fp_dev *dev,
struct fp_print_data *enrolled_print);
/* Data handling */
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,
@@ -300,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;
@@ -311,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 */
@@ -321,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);
/**
@@ -343,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:
@@ -365,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(),
@@ -376,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
@@ -390,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
*
@@ -407,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);
@@ -434,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.
@@ -456,22 +438,6 @@ int fp_async_capture_start(struct fp_dev *dev, int unconditional, fp_img_operati
int fp_async_capture_stop(struct fp_dev *dev, fp_operation_stop_cb callback, void *user_data);
/**
* fp_delete_result:
* @FP_DELETE_COMPLETE: Delete completed successfully.
* @FP_DELETE_FAIL: Delete failed
*
*/
enum fp_delete_result {
FP_DELETE_COMPLETE = 0,
FP_DELETE_FAIL = 1,
};
typedef void (*fp_delete_cb)(struct fp_dev *dev, int status, void *user_data);
int fp_async_delete_finger(struct fp_dev *dev, struct fp_print_data *data, fp_delete_cb callback, void *user_data);
#ifdef __cplusplus
}
#endif

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;
@@ -535,7 +410,7 @@ int fpi_imgdev_get_img_height(struct fp_img_dev *imgdev)
static int dev_activate(struct fp_img_dev *imgdev, enum fp_imgdev_state state)
{
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)
@@ -545,7 +420,7 @@ static int dev_activate(struct fp_img_dev *imgdev, enum fp_imgdev_state 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,7 +430,7 @@ 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;
@@ -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,29 +1,16 @@
libfprint_sources = [
'fp_internal.h',
'nbis-helpers.h',
'drivers_api.h',
'fpi-async.c',
'fpi-async.h',
'fpi-assembling.c',
'fpi-assembling.h',
'fpi-core.c',
'fpi-core.h',
'fpi-data.c',
'fpi-data.h',
'fpi-dev.c',
'fpi-dev.h',
'fpi-dev-img.c',
'fpi-dev-img.h',
'fpi-img.c',
'fpi-img.h',
'fpi-log.h',
'fpi-ssm.c',
'fpi-ssm.h',
'fpi-sync.c',
'fpi-poll.h',
'fpi-poll.c',
'fpi-usb.h',
'fpi-usb.c',
'async.c',
'core.c',
'data.c',
'drv.c',
'img.c',
'imgdev.c',
'poll.c',
'sync.c',
'assembling.c',
'assembling.h',
'drivers/driver_ids.h',
]
@@ -43,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',
@@ -66,7 +50,6 @@ nbis_sources = [
'nbis/mindtct/shape.c',
'nbis/mindtct/sort.c',
'nbis/mindtct/util.c',
'nbis/mindtct/xytreps.c',
]
aeslib = false
@@ -74,13 +57,12 @@ aesx660 = false
aes3k = false
drivers_sources = []
drivers_cflags = []
foreach driver: drivers
if driver == 'upekts'
drivers_sources += [ 'drivers/upekts.c' ]
endif
if driver == 'upektc'
drivers_sources += [ 'drivers/upektc.c', 'drivers/upektc.h', 'drivers/upek_proto.c', 'drivers/upek_proto.h' ]
drivers_sources += [ 'drivers/upektc.c', 'drivers/upektc.h' ]
endif
if driver == 'upeksonly'
drivers_sources += [ 'drivers/upeksonly.c', 'drivers/upeksonly.h' ]
@@ -136,7 +118,7 @@ foreach driver: drivers
drivers_sources += [ 'drivers/vfs5011.c', 'drivers/vfs5011_proto.h' ]
endif
if driver == 'upektc_img'
drivers_sources += [ 'drivers/upektc_img.c', 'drivers/upektc_img.h', 'drivers/upek_proto.c', 'drivers/upek_proto.h' ]
drivers_sources += [ 'drivers/upektc_img.c', 'drivers/upektc_img.h' ]
endif
if driver == 'etes603'
drivers_sources += [ 'drivers/etes603.c' ]
@@ -147,20 +129,10 @@ foreach driver: drivers
if driver == 'elan'
drivers_sources += [ 'drivers/elan.c', 'drivers/elan.h' ]
endif
if driver == 'synaptics'
drivers_sources += [
'drivers/synaptics/synaptics.c',
'drivers/synaptics/bmkt.c',
'drivers/synaptics/util.c',
'drivers/synaptics/bmkt_message.c',
'drivers/synaptics/sensor.c',
'drivers/synaptics/usb_transport.c',
]
endif
endforeach
if aeslib
drivers_sources += [ 'drivers/aeslib.c', 'drivers/aeslib.h' ]
drivers_sources += [ 'aeslib.c', 'aeslib.h' ]
endif
if aesx660
drivers_sources += ['drivers/aesx660.c', 'drivers/aesx660.h' ]
@@ -171,7 +143,7 @@ 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',
@@ -191,7 +163,6 @@ libfprint_sources += configure_file(input: 'empty_file',
])
deps = [ mathlib_dep, glib_dep, libusb_dep, nss_dep, imaging_dep ]
libfprint = library('fprint',
libfprint_sources + drivers_sources + nbis_sources + other_sources,
soversion: soversion,

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

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