Uncrustify everything except for nbis

This commit is contained in:
Marco Trevisan (Treviño) 2019-11-19 21:13:11 +01:00 committed by Benjamin Berg
parent fd5f511b33
commit d1fb1e26f3
60 changed files with 30386 additions and 28683 deletions

View file

@ -22,35 +22,36 @@
#include <gtk/gtk.h>
#include <libfprint/fprint.h>
typedef GtkApplication LibfprintDemo;
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
IMAGE_DISPLAY_NONE = 0,
IMAGE_DISPLAY_MINUTIAE = 1 << 0,
IMAGE_DISPLAY_BINARY = 1 << 1
} ImageDisplayFlags;
typedef struct {
GtkApplicationWindow parent_instance;
typedef struct
{
GtkApplicationWindow parent_instance;
GtkWidget *header_bar;
GtkWidget *mode_stack;
GtkWidget *capture_button;
GtkWidget *cancel_button;
GtkWidget *capture_image;
GtkWidget *spinner;
GtkWidget *instructions;
GtkWidget *header_bar;
GtkWidget *mode_stack;
GtkWidget *capture_button;
GtkWidget *cancel_button;
GtkWidget *capture_image;
GtkWidget *spinner;
GtkWidget *instructions;
GCancellable *cancellable;
GCancellable *cancellable;
gboolean opened;
FpDevice *dev;
gboolean opened;
FpDevice *dev;
FpImage *img;
ImageDisplayFlags img_flags;
FpImage *img;
ImageDisplayFlags img_flags;
} LibfprintDemoWindow;
typedef GtkApplicationWindowClass LibfprintDemoWindowClass;
@ -58,483 +59,506 @@ 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,
RETRY_MODE
EMPTY_MODE,
NOIMAGING_MODE,
CAPTURE_MODE,
SPINNER_MODE,
ERROR_MODE,
RETRY_MODE
} LibfprintDemoMode;
static void libfprint_demo_set_mode (LibfprintDemoWindow *win,
LibfprintDemoMode mode);
LibfprintDemoMode mode);
static unsigned char *
img_to_rgbdata (const guint8 *imgdata,
int width,
int height)
int width,
int height)
{
int size = width * height;
guint8 *rgbdata = g_malloc (size * 3);
size_t i;
size_t rgb_offset = 0;
int size = width * height;
guint8 *rgbdata = g_malloc (size * 3);
size_t i;
size_t rgb_offset = 0;
for (i = 0; i < size; i++) {
guint8 pixel = imgdata[i];
for (i = 0; i < size; i++)
{
guint8 pixel = imgdata[i];
rgbdata[rgb_offset++] = pixel;
rgbdata[rgb_offset++] = pixel;
rgbdata[rgb_offset++] = pixel;
}
rgbdata[rgb_offset++] = pixel;
rgbdata[rgb_offset++] = pixel;
rgbdata[rgb_offset++] = pixel;
}
return rgbdata;
return rgbdata;
}
static void
plot_minutiae (unsigned char *rgbdata,
int width,
int height,
GPtrArray *minutiae)
plot_minutiae (unsigned char *rgbdata,
int width,
int height,
GPtrArray *minutiae)
{
int i;
int i;
#define write_pixel(num) do { \
rgbdata[((num) * 3)] = 0xff; \
rgbdata[((num) * 3) + 1] = 0; \
rgbdata[((num) * 3) + 2] = 0; \
} while(0)
rgbdata[((num) * 3)] = 0xff; \
rgbdata[((num) * 3) + 1] = 0; \
rgbdata[((num) * 3) + 2] = 0; \
} while(0)
for (i = 0; i < minutiae->len; i++) {
struct fp_minutia *min = g_ptr_array_index (minutiae, i);
int x, y;
size_t pixel_offset;
for (i = 0; i < minutiae->len; i++)
{
struct fp_minutia *min = g_ptr_array_index (minutiae, 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);
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));
}
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 (FpImage *img,
ImageDisplayFlags flags)
img_to_pixbuf (FpImage *img,
ImageDisplayFlags flags)
{
int width;
int height;
const guint8 *data;
unsigned char *rgbdata;
int width;
int height;
const guint8 *data;
unsigned char *rgbdata;
width = fp_image_get_width (img);
height = fp_image_get_height (img);
width = fp_image_get_width (img);
height = fp_image_get_height (img);
if (flags & IMAGE_DISPLAY_BINARY)
data = fp_image_get_binarized (img, NULL);
else
data = fp_image_get_data (img, NULL);
if (flags & IMAGE_DISPLAY_BINARY)
data = fp_image_get_binarized (img, NULL);
else
data = fp_image_get_data (img, NULL);
if (!data)
return NULL;
if (!data)
return NULL;
rgbdata = img_to_rgbdata (data, width, height);
rgbdata = img_to_rgbdata (data, width, height);
if (flags & IMAGE_DISPLAY_MINUTIAE) {
GPtrArray *minutiae;
if (flags & IMAGE_DISPLAY_MINUTIAE)
{
GPtrArray *minutiae;
minutiae = fp_image_get_minutiae (img);
plot_minutiae (rgbdata, width, height, minutiae);
}
minutiae = fp_image_get_minutiae (img);
plot_minutiae (rgbdata, width, height, minutiae);
}
return gdk_pixbuf_new_from_data (rgbdata, GDK_COLORSPACE_RGB,
FALSE, 8, width, height,
width * 3, (GdkPixbufDestroyNotify) g_free,
NULL);
return gdk_pixbuf_new_from_data (rgbdata, GDK_COLORSPACE_RGB,
FALSE, 8, width, height,
width * 3, (GdkPixbufDestroyNotify) g_free,
NULL);
}
static void
update_image (LibfprintDemoWindow *win)
{
GdkPixbuf *pixbuf;
GdkPixbuf *pixbuf;
if (win->img == NULL) {
gtk_image_clear (GTK_IMAGE (win->capture_image));
return;
}
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);
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)
const char *message)
{
char *label;
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);
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)
{
FpScanType scan_type;
const char *message;
FpScanType scan_type;
const char *message;
scan_type = fp_device_get_scan_type(win->dev);
scan_type = fp_device_get_scan_type (win->dev);
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 ();
}
switch (scan_type)
{
case FP_SCAN_TYPE_PRESS:
message = "Place your finger on the fingerprint reader";
break;
libfprint_demo_set_spinner_label (win, message);
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 (FpDevice *dev,
GAsyncResult *res,
void *user_data)
dev_capture_start_cb (FpDevice *dev,
GAsyncResult *res,
void *user_data)
{
g_autoptr(GError) error = NULL;
LibfprintDemoWindow *win = user_data;
FpImage *image = NULL;
g_autoptr(GError) error = NULL;
LibfprintDemoWindow *win = user_data;
FpImage *image = NULL;
g_clear_object (&win->cancellable);
g_clear_object (&win->cancellable);
image = fp_device_capture_finish (dev, res, &error);
if (!image) {
g_warning ("Error capturing data: %s", error->message);
if (error->domain == FP_DEVICE_RETRY ||
g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
libfprint_demo_set_mode (win, RETRY_MODE);
else
libfprint_demo_set_mode (win, ERROR_MODE);
return;
}
image = fp_device_capture_finish (dev, res, &error);
if (!image)
{
g_warning ("Error capturing data: %s", error->message);
if (error->domain == FP_DEVICE_RETRY ||
g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
libfprint_demo_set_mode (win, RETRY_MODE);
else
libfprint_demo_set_mode (win, ERROR_MODE);
return;
}
g_clear_object (&win->img);
win->img = image;
update_image (win);
g_clear_object (&win->img);
win->img = image;
update_image (win);
libfprint_demo_set_mode (win, CAPTURE_MODE);
libfprint_demo_set_mode (win, CAPTURE_MODE);
}
static void
dev_start_capture (LibfprintDemoWindow *win)
{
libfprint_demo_set_capture_label (win);
libfprint_demo_set_capture_label (win);
fp_device_capture (win->dev, TRUE, win->cancellable, (GAsyncReadyCallback) dev_capture_start_cb, win);
fp_device_capture (win->dev, TRUE, win->cancellable, (GAsyncReadyCallback) dev_capture_start_cb, win);
}
static void
dev_open_cb (FpDevice *dev, GAsyncResult *res, void *user_data)
{
LibfprintDemoWindow *win = user_data;
g_autoptr(GError) error = NULL;
LibfprintDemoWindow *win = user_data;
if (!fp_device_open_finish (dev, res, &error)) {
g_warning ("Failed to open device: %s", error->message);
libfprint_demo_set_mode (win, ERROR_MODE);
return;
}
g_autoptr(GError) error = NULL;
dev_start_capture(win);
if (!fp_device_open_finish (dev, res, &error))
{
g_warning ("Failed to open device: %s", error->message);
libfprint_demo_set_mode (win, ERROR_MODE);
return;
}
dev_start_capture (win);
}
static void
activate_capture (GSimpleAction *action,
GVariant *parameter,
gpointer user_data)
GVariant *parameter,
gpointer user_data)
{
LibfprintDemoWindow *win = user_data;
LibfprintDemoWindow *win = user_data;
libfprint_demo_set_mode (win, SPINNER_MODE);
g_clear_pointer (&win->img, g_object_unref);
libfprint_demo_set_mode (win, SPINNER_MODE);
g_clear_pointer (&win->img, g_object_unref);
g_clear_object (&win->cancellable);
win->cancellable = g_cancellable_new ();
g_clear_object (&win->cancellable);
win->cancellable = g_cancellable_new ();
if (win->opened) {
dev_start_capture (win);
return;
}
if (win->opened)
{
dev_start_capture (win);
return;
}
libfprint_demo_set_spinner_label (win, "Opening fingerprint reader");
libfprint_demo_set_spinner_label (win, "Opening fingerprint reader");
win->opened = TRUE;
fp_device_open (win->dev, win->cancellable, (GAsyncReadyCallback) dev_open_cb, user_data);
win->opened = TRUE;
fp_device_open (win->dev, win->cancellable, (GAsyncReadyCallback) dev_open_cb, user_data);
}
static void
cancel_capture (GSimpleAction *action,
GVariant *parameter,
gpointer user_data)
GVariant *parameter,
gpointer user_data)
{
LibfprintDemoWindow *win = user_data;
LibfprintDemoWindow *win = user_data;
g_debug ("cancelling %p", win->cancellable);
g_debug ("cancelling %p", win->cancellable);
if (win->cancellable)
g_cancellable_cancel (win->cancellable);
if (win->cancellable)
g_cancellable_cancel (win->cancellable);
}
static void
activate_quit (GSimpleAction *action,
GVariant *parameter,
gpointer user_data)
GVariant *parameter,
gpointer user_data)
{
GtkApplication *app = user_data;
GtkWidget *win;
GList *list, *next;
GtkApplication *app = user_data;
GtkWidget *win;
GList *list, *next;
list = gtk_application_get_windows (app);
while (list)
{
win = list->data;
next = list->next;
list = gtk_application_get_windows (app);
while (list)
{
win = list->data;
next = list->next;
gtk_widget_destroy (GTK_WIDGET (win));
gtk_widget_destroy (GTK_WIDGET (win));
list = next;
}
list = next;
}
}
static void
activate_show_minutiae (GSimpleAction *action,
GVariant *parameter,
gpointer user_data)
GVariant *parameter,
gpointer user_data)
{
LibfprintDemoWindow *win = user_data;
GVariant *state;
gboolean new_state;
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);
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;
if (new_state)
win->img_flags |= IMAGE_DISPLAY_MINUTIAE;
else
win->img_flags &= ~IMAGE_DISPLAY_MINUTIAE;
update_image (win);
update_image (win);
}
static void
activate_show_binary (GSimpleAction *action,
GVariant *parameter,
gpointer user_data)
GVariant *parameter,
gpointer user_data)
{
LibfprintDemoWindow *win = user_data;
GVariant *state;
gboolean new_state;
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);
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;
if (new_state)
win->img_flags |= IMAGE_DISPLAY_BINARY;
else
win->img_flags &= ~IMAGE_DISPLAY_BINARY;
update_image (win);
update_image (win);
}
static void
change_show_minutiae_state (GSimpleAction *action,
GVariant *state,
gpointer user_data)
GVariant *state,
gpointer user_data)
{
g_simple_action_set_state (action, state);
g_simple_action_set_state (action, state);
}
static void
change_show_binary_state (GSimpleAction *action,
GVariant *state,
gpointer user_data)
GVariant *state,
gpointer user_data)
{
g_simple_action_set_state (action, state);
g_simple_action_set_state (action, state);
}
static GActionEntry app_entries[] = {
{ "quit", activate_quit, NULL, NULL, NULL },
{ "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 },
{ "cancel", cancel_capture, NULL, NULL, NULL }
{ "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 },
{ "cancel", cancel_capture, NULL, NULL, NULL }
};
static void
activate (GApplication *app)
{
LibfprintDemoWindow *window;
LibfprintDemoWindow *window;
window = g_object_new (libfprint_demo_window_get_type (),
"application", app,
NULL);
gtk_widget_show (GTK_WIDGET (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)
LibfprintDemoMode mode)
{
char *title;
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_widget_set_sensitive (win->cancel_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_widget_set_sensitive (win->cancel_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);
gtk_widget_set_sensitive (win->cancel_button, FALSE);
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_widget_set_sensitive (win->cancel_button, FALSE);
gtk_spinner_stop (GTK_SPINNER (win->spinner));
break;
title = g_strdup_printf ("%s Test", fp_device_get_name (win->dev));
gtk_header_bar_set_title (GTK_HEADER_BAR (win->header_bar), title);
g_free (title);
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_widget_set_sensitive (win->cancel_button, FALSE);
gtk_spinner_stop (GTK_SPINNER (win->spinner));
break;
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_widget_set_sensitive (win->cancel_button, TRUE);
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_widget_set_sensitive (win->cancel_button, FALSE);
gtk_spinner_stop (GTK_SPINNER (win->spinner));
break;
case RETRY_MODE:
gtk_stack_set_visible_child_name (GTK_STACK (win->mode_stack), "retry-mode");
gtk_widget_set_sensitive (win->capture_button, TRUE);
gtk_widget_set_sensitive (win->cancel_button, FALSE);
gtk_spinner_stop (GTK_SPINNER (win->spinner));
break;
default:
g_assert_not_reached ();
}
case CAPTURE_MODE:
gtk_stack_set_visible_child_name (GTK_STACK (win->mode_stack), "capture-mode");
gtk_widget_set_sensitive (win->capture_button, TRUE);
gtk_widget_set_sensitive (win->cancel_button, FALSE);
title = g_strdup_printf ("%s Test", fp_device_get_name (win->dev));
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_widget_set_sensitive (win->cancel_button, TRUE);
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_widget_set_sensitive (win->cancel_button, FALSE);
gtk_spinner_stop (GTK_SPINNER (win->spinner));
break;
case RETRY_MODE:
gtk_stack_set_visible_child_name (GTK_STACK (win->mode_stack), "retry-mode");
gtk_widget_set_sensitive (win->capture_button, TRUE);
gtk_widget_set_sensitive (win->cancel_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);
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);
GApplicationClass *app_class = G_APPLICATION_CLASS (class);
app_class->activate = activate;
app_class->activate = activate;
}
static void
libfprint_demo_window_init (LibfprintDemoWindow *window)
{
FpContext *ctx;
GPtrArray *devices;
FpContext *ctx;
GPtrArray *devices;
gtk_widget_init_template (GTK_WIDGET (window));
gtk_window_set_default_size (GTK_WINDOW (window), 700, 500);
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);
g_action_map_add_action_entries (G_ACTION_MAP (window),
win_entries, G_N_ELEMENTS (win_entries),
window);
ctx = fp_context_new ();
ctx = fp_context_new ();
devices = fp_context_get_devices(ctx);
if (!devices) {
libfprint_demo_set_mode (window, ERROR_MODE);
return;
}
devices = fp_context_get_devices (ctx);
if (!devices)
{
libfprint_demo_set_mode (window, ERROR_MODE);
return;
}
/* Empty list? */
if (devices->len == 0) {
libfprint_demo_set_mode (window, EMPTY_MODE);
return;
}
/* Empty list? */
if (devices->len == 0)
{
libfprint_demo_set_mode (window, EMPTY_MODE);
return;
}
if (!fp_device_supports_capture(g_ptr_array_index (devices, 0))) {
libfprint_demo_set_mode (window, NOIMAGING_MODE);
return;
}
if (!fp_device_supports_capture (g_ptr_array_index (devices, 0)))
{
libfprint_demo_set_mode (window, NOIMAGING_MODE);
return;
}
window->dev = g_object_ref (g_ptr_array_index (devices, 0));
libfprint_demo_set_mode (window, CAPTURE_MODE);
window->dev = g_object_ref (g_ptr_array_index (devices, 0));
libfprint_demo_set_mode (window, CAPTURE_MODE);
}
static void
libfprint_demo_window_class_init (LibfprintDemoWindowClass *class)
{
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (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, cancel_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);
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, cancel_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
//FIXME setup dispose
}
int main (int argc, char **argv)
int
main (int argc, char **argv)
{
GtkApplication *app;
GtkApplication *app;
app = GTK_APPLICATION (g_object_new (libfprint_demo_get_type (),
"application-id", "org.freedesktop.libfprint.Demo",
"flags", G_APPLICATION_FLAGS_NONE,
NULL));
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);
return g_application_run (G_APPLICATION (app), 0, NULL);
}

View file

@ -24,155 +24,171 @@
#include "storage.h"
typedef struct _EnrollData {
GMainLoop *loop;
int ret_value;
typedef struct _EnrollData
{
GMainLoop *loop;
int ret_value;
} EnrollData;
static void
enroll_data_free (EnrollData *enroll_data)
{
g_main_loop_unref (enroll_data->loop);
g_free (enroll_data);
g_main_loop_unref (enroll_data->loop);
g_free (enroll_data);
}
G_DEFINE_AUTOPTR_CLEANUP_FUNC (EnrollData, enroll_data_free)
FpDevice *discover_device (GPtrArray *devices)
FpDevice *discover_device (GPtrArray * devices)
{
FpDevice *dev;
if (!devices->len)
return NULL;
FpDevice *dev;
dev = g_ptr_array_index (devices, 0);
printf("Found device claimed by %s driver\n", fp_device_get_driver (dev));
return dev;
if (!devices->len)
return NULL;
dev = g_ptr_array_index (devices, 0);
printf ("Found device claimed by %s driver\n", fp_device_get_driver (dev));
return dev;
}
static void
on_device_closed (FpDevice *dev, GAsyncResult *res, void *user_data) {
EnrollData *enroll_data = user_data;
g_autoptr(GError) error = NULL;
on_device_closed (FpDevice *dev, GAsyncResult *res, void *user_data)
{
EnrollData *enroll_data = user_data;
fp_device_close_finish (dev, res, &error);
g_autoptr(GError) error = NULL;
if (error)
g_warning ("Failed closing device %s\n", error->message);
fp_device_close_finish (dev, res, &error);
g_main_loop_quit (enroll_data->loop);
if (error)
g_warning ("Failed closing device %s\n", error->message);
g_main_loop_quit (enroll_data->loop);
}
static void
on_enroll_completed (FpDevice *dev, GAsyncResult *res, void *user_data) {
EnrollData *enroll_data = user_data;
g_autoptr(FpPrint) print = NULL;
g_autoptr(GError) error = NULL;
on_enroll_completed (FpDevice *dev, GAsyncResult *res, void *user_data)
{
EnrollData *enroll_data = user_data;
print = fp_device_enroll_finish (dev, res, &error);
g_autoptr(FpPrint) print = NULL;
g_autoptr(GError) error = NULL;
if (!error) {
enroll_data->ret_value = EXIT_SUCCESS;
print = fp_device_enroll_finish (dev, res, &error);
if (!fp_device_has_storage (dev)) {
g_debug("Device has not storage, saving locally");
int r = print_data_save(print, FP_FINGER_RIGHT_INDEX);
if (r < 0) {
g_warning("Data save failed, code %d", r);
enroll_data->ret_value = EXIT_FAILURE;
}
}
} else {
g_warning("Enroll failed with error %s\n", error->message);
}
if (!error)
{
enroll_data->ret_value = EXIT_SUCCESS;
fp_device_close (dev, NULL, (GAsyncReadyCallback) on_device_closed,
enroll_data);
if (!fp_device_has_storage (dev))
{
g_debug ("Device has not storage, saving locally");
int r = print_data_save (print, FP_FINGER_RIGHT_INDEX);
if (r < 0)
{
g_warning ("Data save failed, code %d", r);
enroll_data->ret_value = EXIT_FAILURE;
}
}
}
else
{
g_warning ("Enroll failed with error %s\n", error->message);
}
fp_device_close (dev, NULL, (GAsyncReadyCallback) on_device_closed,
enroll_data);
}
static void
on_enroll_progress (FpDevice *device,
gint completed_stages,
FpPrint *print,
gpointer user_data,
GError *error)
gint completed_stages,
FpPrint *print,
gpointer user_data,
GError *error)
{
if (error) {
g_warning ("Enroll stage %d of %d failed with error %s",
completed_stages,
fp_device_get_nr_enroll_stages (device),
error->message);
return;
}
if (error)
{
g_warning ("Enroll stage %d of %d failed with error %s",
completed_stages,
fp_device_get_nr_enroll_stages (device),
error->message);
return;
}
if (fp_device_supports_capture (device) &&
print_image_save (print, "enrolled.pgm")) {
printf ("Wrote scanned image to enrolled.pgm\n");
}
if (fp_device_supports_capture (device) &&
print_image_save (print, "enrolled.pgm"))
printf ("Wrote scanned image to enrolled.pgm\n");
printf ("Enroll stage %d of %d passed. Yay!\n", completed_stages,
fp_device_get_nr_enroll_stages (device));
printf ("Enroll stage %d of %d passed. Yay!\n", completed_stages,
fp_device_get_nr_enroll_stages (device));
}
static void
on_device_opened (FpDevice *dev, GAsyncResult *res, void *user_data)
{
EnrollData *enroll_data = user_data;
FpPrint *print_template;
g_autoptr(GError) error = NULL;
EnrollData *enroll_data = user_data;
FpPrint *print_template;
if (!fp_device_open_finish (dev, res, &error)) {
g_warning ("Failed to open device: %s", error->message);
g_main_loop_quit (enroll_data->loop);
return;
}
g_autoptr(GError) error = NULL;
printf ("Opened device. It's now time to enroll your finger.\n\n");
printf ("You will need to successfully scan your finger %d times to "
"complete the process.\n\n", fp_device_get_nr_enroll_stages (dev));
printf ("Scan your finger now.\n");
if (!fp_device_open_finish (dev, res, &error))
{
g_warning ("Failed to open device: %s", error->message);
g_main_loop_quit (enroll_data->loop);
return;
}
print_template = print_create_template (dev, FP_FINGER_RIGHT_INDEX);
fp_device_enroll (dev, print_template, NULL, on_enroll_progress, NULL,
NULL, (GAsyncReadyCallback) on_enroll_completed,
enroll_data);
printf ("Opened device. It's now time to enroll your finger.\n\n");
printf ("You will need to successfully scan your finger %d times to "
"complete the process.\n\n", fp_device_get_nr_enroll_stages (dev));
printf ("Scan your finger now.\n");
print_template = print_create_template (dev, FP_FINGER_RIGHT_INDEX);
fp_device_enroll (dev, print_template, NULL, on_enroll_progress, NULL,
NULL, (GAsyncReadyCallback) on_enroll_completed,
enroll_data);
}
int main(void)
int
main (void)
{
g_autoptr (FpContext) ctx = NULL;
g_autoptr (EnrollData) enroll_data = NULL;
GPtrArray *devices;
FpDevice *dev;
g_autoptr(FpContext) ctx = NULL;
g_autoptr(EnrollData) enroll_data = NULL;
GPtrArray *devices;
FpDevice *dev;
printf("This program will enroll your right index finger, "
"unconditionally overwriting any right-index print that was enrolled "
"previously. If you want to continue, press enter, otherwise hit "
"Ctrl+C\n");
getchar();
printf ("This program will enroll your right index finger, "
"unconditionally overwriting any right-index print that was enrolled "
"previously. If you want to continue, press enter, otherwise hit "
"Ctrl+C\n");
getchar ();
setenv ("G_MESSAGES_DEBUG", "all", 0);
setenv ("G_MESSAGES_DEBUG", "all", 0);
ctx = fp_context_new ();
ctx = fp_context_new ();
devices = fp_context_get_devices (ctx);
if (!devices) {
g_warning("Impossible to get devices");
return EXIT_FAILURE;
}
devices = fp_context_get_devices (ctx);
if (!devices)
{
g_warning ("Impossible to get devices");
return EXIT_FAILURE;
}
dev = discover_device (devices);
if (!dev) {
g_warning("No devices detected.");
return EXIT_FAILURE;
}
dev = discover_device (devices);
if (!dev)
{
g_warning ("No devices detected.");
return EXIT_FAILURE;
}
enroll_data = g_new0 (EnrollData, 1);
enroll_data->ret_value = EXIT_FAILURE;
enroll_data->loop = g_main_loop_new (NULL, FALSE);
enroll_data = g_new0 (EnrollData, 1);
enroll_data->ret_value = EXIT_FAILURE;
enroll_data->loop = g_main_loop_new (NULL, FALSE);
fp_device_open (dev, NULL, (GAsyncReadyCallback) on_device_opened,
enroll_data);
fp_device_open (dev, NULL, (GAsyncReadyCallback) on_device_opened,
enroll_data);
g_main_loop_run (enroll_data->loop);
g_main_loop_run (enroll_data->loop);
return enroll_data->ret_value;
return enroll_data->ret_value;
}

View file

@ -122,8 +122,9 @@ delete_data_free (DeleteData *delete_data)
}
G_DEFINE_AUTOPTR_CLEANUP_FUNC (DeleteData, delete_data_free);
static void
on_print_deleted (FpDevice *dev, GAsyncResult *res, gpointer user_data);
static void on_print_deleted (FpDevice *dev,
GAsyncResult *res,
gpointer user_data);
static void
delete_next_print (FpDevice *dev,
@ -145,6 +146,7 @@ on_print_deleted (FpDevice *dev,
gpointer user_data)
{
ListData *list_data = user_data;
g_autoptr(GError) error = NULL;
g_autoptr(FpPrint) print = NULL;
GList *deleted_link;
@ -157,12 +159,14 @@ on_print_deleted (FpDevice *dev,
if (error)
{
g_warning("Failed to remove print %s: %s",
fp_print_get_description (print), error->message);
g_warning ("Failed to remove print %s: %s",
fp_print_get_description (print), error->message);
list_data->any_failed = TRUE;
}
else
g_debug ("Deleted print %s from device", fp_print_get_description (print));
{
g_debug ("Deleted print %s from device", fp_print_get_description (print));
}
if (list_data->to_delete != NULL)
{
@ -184,6 +188,7 @@ on_list_completed (FpDevice *dev,
gpointer user_data)
{
ListData *list_data = user_data;
g_autoptr(GPtrArray) prints = NULL;
g_autoptr(GError) error = NULL;
@ -198,7 +203,7 @@ on_list_completed (FpDevice *dev,
for (i = 0; i < prints->len; ++i)
{
FpPrint* print = prints->pdata[i];
FpPrint * print = prints->pdata[i];
g_date_strftime (buf, G_N_ELEMENTS (buf), "%Y-%m-%d",
fp_print_get_enroll_date (print));
@ -247,10 +252,8 @@ on_list_completed (FpDevice *dev,
if (list_data->to_delete)
delete_next_print (dev, list_data);
else
{
fp_device_close (dev, NULL, (GAsyncReadyCallback) on_device_closed,
list_data);
}
fp_device_close (dev, NULL, (GAsyncReadyCallback) on_device_closed,
list_data);
}
else
{

View file

@ -31,183 +31,196 @@
static char *
get_print_data_descriptor (FpPrint *print, FpDevice *dev, FpFinger finger)
{
const char *driver;
const char *dev_id;
const char *driver;
const char *dev_id;
if (print) {
driver = fp_print_get_driver (print);
dev_id = fp_print_get_device_id (print);
} else {
driver = fp_device_get_driver (dev);
dev_id = fp_device_get_device_id (dev);
}
if (print)
{
driver = fp_print_get_driver (print);
dev_id = fp_print_get_device_id (print);
}
else
{
driver = fp_device_get_driver (dev);
dev_id = fp_device_get_device_id (dev);
}
return g_strdup_printf("%s/%s/%x",
driver,
dev_id,
finger);
return g_strdup_printf ("%s/%s/%x",
driver,
dev_id,
finger);
}
static GVariantDict *
load_data(void)
load_data (void)
{
GVariantDict *res;
GVariant *var;
g_autofree gchar *contents = NULL;
gssize length = 0;
GVariantDict *res;
GVariant *var;
g_autofree gchar *contents = NULL;
gssize length = 0;
if (!g_file_get_contents (STORAGE_FILE, &contents, &length, NULL)) {
g_warning ("Error loading storage, assuming it is empty");
return g_variant_dict_new(NULL);
}
if (!g_file_get_contents (STORAGE_FILE, &contents, &length, NULL))
{
g_warning ("Error loading storage, assuming it is empty");
return g_variant_dict_new (NULL);
}
var = g_variant_new_from_data (G_VARIANT_TYPE_VARDICT, contents, length, FALSE, NULL, NULL);
var = g_variant_new_from_data (G_VARIANT_TYPE_VARDICT, contents, length, FALSE, NULL, NULL);
res = g_variant_dict_new(var);
g_variant_unref(var);
return res;
res = g_variant_dict_new (var);
g_variant_unref (var);
return res;
}
static int
save_data(GVariant *data)
save_data (GVariant *data)
{
const gchar *contents = NULL;
gsize length;
const gchar *contents = NULL;
gsize length;
length = g_variant_get_size(data);
contents = (gchar*) g_variant_get_data (data);
length = g_variant_get_size (data);
contents = (gchar *) g_variant_get_data (data);
if (!g_file_set_contents (STORAGE_FILE, contents, length, NULL)) {
g_warning ("Error saving storage,!");
return -1;
}
if (!g_file_set_contents (STORAGE_FILE, contents, length, NULL))
{
g_warning ("Error saving storage,!");
return -1;
}
g_variant_ref_sink(data);
g_variant_unref(data);
g_variant_ref_sink (data);
g_variant_unref (data);
return 0;
return 0;
}
int
print_data_save(FpPrint *print, FpFinger finger)
print_data_save (FpPrint *print, FpFinger finger)
{
g_autofree gchar *descr = get_print_data_descriptor (print, NULL, finger);
g_autoptr (GError) error = NULL;
g_autoptr (GVariantDict) dict = NULL;
g_autofree guchar *data = NULL;
GVariant *val;
gsize size;
int res;
g_autofree gchar *descr = get_print_data_descriptor (print, NULL, finger);
dict = load_data();
g_autoptr(GError) error = NULL;
g_autoptr(GVariantDict) dict = NULL;
g_autofree guchar *data = NULL;
GVariant *val;
gsize size;
int res;
fp_print_serialize (print, &data, &size, &error);
if (error) {
g_warning ("Error serializing data: %s", error->message);
return -1;
}
val = g_variant_new_fixed_array (G_VARIANT_TYPE("y"), data, size, 1);
g_variant_dict_insert_value (dict, descr, val);
dict = load_data ();
res = save_data(g_variant_dict_end(dict));
fp_print_serialize (print, &data, &size, &error);
if (error)
{
g_warning ("Error serializing data: %s", error->message);
return -1;
}
val = g_variant_new_fixed_array (G_VARIANT_TYPE ("y"), data, size, 1);
g_variant_dict_insert_value (dict, descr, val);
return res;
res = save_data (g_variant_dict_end (dict));
return res;
}
FpPrint *
print_data_load(FpDevice *dev, FpFinger finger)
print_data_load (FpDevice *dev, FpFinger finger)
{
g_autofree gchar *descr = get_print_data_descriptor (NULL, dev, finger);
g_autoptr (GVariant) val = NULL;
g_autoptr (GVariantDict) dict = NULL;
g_autofree guchar *stored_data = NULL;
gsize stored_len;
g_autofree gchar *descr = get_print_data_descriptor (NULL, dev, finger);
dict = load_data();
val = g_variant_dict_lookup_value (dict, descr, G_VARIANT_TYPE ("ay"));
g_autoptr(GVariant) val = NULL;
g_autoptr(GVariantDict) dict = NULL;
g_autofree guchar *stored_data = NULL;
gsize stored_len;
if (val) {
FpPrint *print;
g_autoptr (GError) error = NULL;
dict = load_data ();
val = g_variant_dict_lookup_value (dict, descr, G_VARIANT_TYPE ("ay"));
stored_data = (guchar*) g_variant_get_fixed_array (val, &stored_len, 1);
print = fp_print_deserialize (stored_data, stored_len, &error);
if (val)
{
FpPrint *print;
g_autoptr(GError) error = NULL;
if (error)
g_warning ("Error deserializing data: %s", error->message);
stored_data = (guchar *) g_variant_get_fixed_array (val, &stored_len, 1);
print = fp_print_deserialize (stored_data, stored_len, &error);
return print;
}
if (error)
g_warning ("Error deserializing data: %s", error->message);
return NULL;
return print;
}
return NULL;
}
FpPrint *
print_create_template (FpDevice *dev, FpFinger finger)
{
g_autoptr(GDateTime) datetime = NULL;
FpPrint *template = NULL;
GDate *date = NULL;
gint year, month, day;
g_autoptr(GDateTime) datetime = NULL;
FpPrint *template = NULL;
GDate *date = NULL;
gint year, month, day;
template = fp_print_new (dev);
fp_print_set_finger (template, finger);
fp_print_set_username (template, g_get_user_name ());
datetime = g_date_time_new_now_local ();
g_date_time_get_ymd (datetime, &year, &month, &day);
date = g_date_new_dmy (day, month, year);
fp_print_set_enroll_date (template, date);
g_date_free (date);
template = fp_print_new (dev);
fp_print_set_finger (template, finger);
fp_print_set_username (template, g_get_user_name ());
datetime = g_date_time_new_now_local ();
g_date_time_get_ymd (datetime, &year, &month, &day);
date = g_date_new_dmy (day, month, year);
fp_print_set_enroll_date (template, date);
g_date_free (date);
return template;
return template;
}
static gboolean
save_image_to_pgm (FpImage *img, const char *path)
{
FILE *fd = fopen (path, "w");
size_t write_size;
const guchar *data = fp_image_get_data (img, &write_size);
int r;
FILE *fd = fopen (path, "w");
size_t write_size;
const guchar *data = fp_image_get_data (img, &write_size);
int r;
if (!fd) {
g_warning("could not open '%s' for writing: %d", path, errno);
return FALSE;
}
if (!fd)
{
g_warning ("could not open '%s' for writing: %d", path, errno);
return FALSE;
}
r = fprintf (fd, "P5 %d %d 255\n",
fp_image_get_width (img), fp_image_get_height (img));
if (r < 0) {
fclose(fd);
g_critical("pgm header write failed, error %d", r);
return FALSE;
}
r = fprintf (fd, "P5 %d %d 255\n",
fp_image_get_width (img), fp_image_get_height (img));
if (r < 0)
{
fclose (fd);
g_critical ("pgm header write failed, error %d", r);
return FALSE;
}
r = fwrite (data, 1, write_size, fd);
if (r < write_size) {
fclose(fd);
g_critical("short write (%d)", r);
return FALSE;
}
r = fwrite (data, 1, write_size, fd);
if (r < write_size)
{
fclose (fd);
g_critical ("short write (%d)", r);
return FALSE;
}
fclose (fd);
g_debug ("written to '%s'", path);
fclose (fd);
g_debug ("written to '%s'", path);
return TRUE;
return TRUE;
}
gboolean print_image_save (FpPrint *print, const char *path)
gboolean
print_image_save (FpPrint *print, const char *path)
{
g_autoptr(FpImage) img = NULL;
g_autoptr(FpImage) img = NULL;
g_return_val_if_fail (FP_IS_PRINT (print), FALSE);
g_return_val_if_fail (path != NULL, FALSE);
g_return_val_if_fail (FP_IS_PRINT (print), FALSE);
g_return_val_if_fail (path != NULL, FALSE);
img = fp_print_get_image (print);
img = fp_print_get_image (print);
if (img)
return save_image_to_pgm (img, path);
if (img)
return save_image_to_pgm (img, path);
return FALSE;
return FALSE;
}

View file

@ -22,9 +22,13 @@
#define __STORAGE_H
int print_data_save(FpPrint *print, FpFinger finger);
FpPrint * print_data_load(FpDevice *dev, FpFinger finger);
FpPrint * print_create_template(FpDevice *dev, FpFinger finger);
gboolean print_image_save(FpPrint *print, const char *path);
int print_data_save (FpPrint *print,
FpFinger finger);
FpPrint * print_data_load (FpDevice *dev,
FpFinger finger);
FpPrint * print_create_template (FpDevice *dev,
FpFinger finger);
gboolean print_image_save (FpPrint *print,
const char *path);
#endif /* __STORAGE_H */

View file

@ -24,212 +24,236 @@
#include "storage.h"
typedef struct _VerifyData {
GMainLoop *loop;
int ret_value;
typedef struct _VerifyData
{
GMainLoop *loop;
int ret_value;
} VerifyData;
static void
verify_data_free (VerifyData *verify_data)
{
g_main_loop_unref (verify_data->loop);
g_free (verify_data);
g_main_loop_unref (verify_data->loop);
g_free (verify_data);
}
G_DEFINE_AUTOPTR_CLEANUP_FUNC (VerifyData, verify_data_free)
FpDevice *discover_device (GPtrArray *devices)
FpDevice *discover_device (GPtrArray * devices)
{
FpDevice *dev;
if (!devices->len)
return NULL;
FpDevice *dev;
dev = g_ptr_array_index (devices, 0);
printf("Found device claimed by %s driver\n", fp_device_get_driver (dev));
return dev;
if (!devices->len)
return NULL;
dev = g_ptr_array_index (devices, 0);
printf ("Found device claimed by %s driver\n", fp_device_get_driver (dev));
return dev;
}
static void
on_device_closed (FpDevice *dev, GAsyncResult *res, void *user_data) {
VerifyData *verify_data = user_data;
g_autoptr(GError) error = NULL;
on_device_closed (FpDevice *dev, GAsyncResult *res, void *user_data)
{
VerifyData *verify_data = user_data;
fp_device_close_finish (dev, res, &error);
g_autoptr(GError) error = NULL;
if (error)
g_warning ("Failed closing device %s\n", error->message);
fp_device_close_finish (dev, res, &error);
g_main_loop_quit (verify_data->loop);
if (error)
g_warning ("Failed closing device %s\n", error->message);
g_main_loop_quit (verify_data->loop);
}
static void start_verification (FpDevice *dev, VerifyData *verify_data);
static void start_verification (FpDevice *dev,
VerifyData *verify_data);
static void
on_verify_completed (FpDevice *dev, GAsyncResult *res, void *user_data)
{
VerifyData *verify_data = user_data;
g_autoptr(FpPrint) print = NULL;
g_autoptr(GError) error = NULL;
char buffer[20];
gboolean match;
VerifyData *verify_data = user_data;
if (!fp_device_verify_finish (dev, res, &match, &print, &error)) {
g_warning ("Failed to verify print: %s", error->message);
g_main_loop_quit (verify_data->loop);
return;
}
g_autoptr(FpPrint) print = NULL;
g_autoptr(GError) error = NULL;
char buffer[20];
gboolean match;
if (match) {
g_print ("MATCH!\n");
if (fp_device_supports_capture (dev) &&
print_image_save (print, "verify.pgm")) {
g_print("Print image saved as verify.pgm");
}
if (!fp_device_verify_finish (dev, res, &match, &print, &error))
{
g_warning ("Failed to verify print: %s", error->message);
g_main_loop_quit (verify_data->loop);
return;
}
verify_data->ret_value = EXIT_SUCCESS;
} else {
g_print ("NO MATCH!\n");
verify_data->ret_value = EXIT_FAILURE;
}
if (match)
{
g_print ("MATCH!\n");
if (fp_device_supports_capture (dev) &&
print_image_save (print, "verify.pgm"))
g_print ("Print image saved as verify.pgm");
g_print ("Verify again? [Y/n]? ");
if (fgets (buffer, sizeof (buffer), stdin) &&
(buffer[0] == 'Y' || buffer[0] == 'y')) {
start_verification (dev, verify_data);
return;
}
verify_data->ret_value = EXIT_SUCCESS;
}
else
{
g_print ("NO MATCH!\n");
verify_data->ret_value = EXIT_FAILURE;
}
fp_device_close (dev, NULL, (GAsyncReadyCallback) on_device_closed,
verify_data);
g_print ("Verify again? [Y/n]? ");
if (fgets (buffer, sizeof (buffer), stdin) &&
(buffer[0] == 'Y' || buffer[0] == 'y'))
{
start_verification (dev, verify_data);
return;
}
fp_device_close (dev, NULL, (GAsyncReadyCallback) on_device_closed,
verify_data);
}
static void
on_list_completed (FpDevice *dev, GAsyncResult *res, gpointer user_data)
{
VerifyData *verify_data = user_data;
g_autoptr(GPtrArray) prints = NULL;
g_autoptr(GError) error = NULL;
VerifyData *verify_data = user_data;
prints = fp_device_list_prints_finish (dev, res, &error);
g_autoptr(GPtrArray) prints = NULL;
g_autoptr(GError) error = NULL;
if (!error) {
FpPrint *verify_print = NULL;
guint i;
prints = fp_device_list_prints_finish (dev, res, &error);
if (!prints->len)
g_warning ("No prints saved on device");
if (!error)
{
FpPrint *verify_print = NULL;
guint i;
for (i = 0; i < prints->len; ++i) {
FpPrint *print = prints->pdata[i];
if (!prints->len)
g_warning ("No prints saved on device");
if (fp_print_get_finger (print) == FP_FINGER_RIGHT_INDEX &&
g_strcmp0 (fp_print_get_username (print), g_get_user_name ()) == 0) {
if (!verify_print ||
(g_date_compare (fp_print_get_enroll_date (print),
fp_print_get_enroll_date (verify_print)) >= 0))
verify_print = print;
}
}
for (i = 0; i < prints->len; ++i)
{
FpPrint *print = prints->pdata[i];
if (!verify_print) {
g_warning ("Did you remember to enroll your right index "
"finger first?");
g_main_loop_quit (verify_data->loop);
return;
}
if (fp_print_get_finger (print) == FP_FINGER_RIGHT_INDEX &&
g_strcmp0 (fp_print_get_username (print), g_get_user_name ()) == 0)
{
if (!verify_print ||
(g_date_compare (fp_print_get_enroll_date (print),
fp_print_get_enroll_date (verify_print)) >= 0))
verify_print = print;
}
}
g_debug ("Comparing print with %s",
fp_print_get_description (verify_print));
if (!verify_print)
{
g_warning ("Did you remember to enroll your right index "
"finger first?");
g_main_loop_quit (verify_data->loop);
return;
}
g_print ("Print loaded. Time to verify!\n");
fp_device_verify (dev, verify_print, NULL,
(GAsyncReadyCallback) on_verify_completed,
verify_data);
} else {
g_warning ("Loading prints failed with error %s", error->message);
g_main_loop_quit (verify_data->loop);
}
g_debug ("Comparing print with %s",
fp_print_get_description (verify_print));
g_print ("Print loaded. Time to verify!\n");
fp_device_verify (dev, verify_print, NULL,
(GAsyncReadyCallback) on_verify_completed,
verify_data);
}
else
{
g_warning ("Loading prints failed with error %s", error->message);
g_main_loop_quit (verify_data->loop);
}
}
static void
start_verification (FpDevice *dev, VerifyData *verify_data)
{
if (fp_device_has_storage (dev)) {
g_print ("Creating finger template, using device storage...\n");
fp_device_list_prints (dev, NULL,
(GAsyncReadyCallback) on_list_completed,
verify_data);
} else {
g_print ("Loading previously enrolled right index finger data...\n");
g_autoptr(FpPrint) verify_print;
if (fp_device_has_storage (dev))
{
g_print ("Creating finger template, using device storage...\n");
fp_device_list_prints (dev, NULL,
(GAsyncReadyCallback) on_list_completed,
verify_data);
}
else
{
g_print ("Loading previously enrolled right index finger data...\n");
g_autoptr(FpPrint) verify_print;
verify_print = print_data_load (dev, FP_FINGER_RIGHT_INDEX);
verify_print = print_data_load (dev, FP_FINGER_RIGHT_INDEX);
if (!verify_print) {
g_warning ("Failed to load fingerprint data");
g_warning ("Did you remember to enroll your right index "
"finger first?");
g_main_loop_quit (verify_data->loop);
return;
}
if (!verify_print)
{
g_warning ("Failed to load fingerprint data");
g_warning ("Did you remember to enroll your right index "
"finger first?");
g_main_loop_quit (verify_data->loop);
return;
}
g_print ("Print loaded. Time to verify!\n");
fp_device_verify (dev, verify_print, NULL,
(GAsyncReadyCallback) on_verify_completed,
verify_data);
}
g_print ("Print loaded. Time to verify!\n");
fp_device_verify (dev, verify_print, NULL,
(GAsyncReadyCallback) on_verify_completed,
verify_data);
}
}
static void
on_device_opened (FpDevice *dev, GAsyncResult *res, void *user_data)
{
VerifyData *verify_data = user_data;
g_autoptr(GError) error = NULL;
VerifyData *verify_data = user_data;
if (!fp_device_open_finish (dev, res, &error)) {
g_warning ("Failed to open device: %s", error->message);
g_main_loop_quit (verify_data->loop);
return;
}
g_autoptr(GError) error = NULL;
g_print ("Opened device. ");
if (!fp_device_open_finish (dev, res, &error))
{
g_warning ("Failed to open device: %s", error->message);
g_main_loop_quit (verify_data->loop);
return;
}
start_verification (dev, verify_data);
g_print ("Opened device. ");
start_verification (dev, verify_data);
}
int main(void)
int
main (void)
{
g_autoptr (FpContext) ctx = NULL;
g_autoptr (VerifyData) verify_data = NULL;
GPtrArray *devices;
FpDevice *dev;
g_autoptr(FpContext) ctx = NULL;
g_autoptr(VerifyData) verify_data = NULL;
GPtrArray *devices;
FpDevice *dev;
setenv ("G_MESSAGES_DEBUG", "all", 0);
setenv ("LIBUSB_DEBUG", "3", 0);
setenv ("G_MESSAGES_DEBUG", "all", 0);
setenv ("LIBUSB_DEBUG", "3", 0);
ctx = fp_context_new ();
ctx = fp_context_new ();
devices = fp_context_get_devices (ctx);
if (!devices) {
g_warning("Impossible to get devices");
return EXIT_FAILURE;
}
devices = fp_context_get_devices (ctx);
if (!devices)
{
g_warning ("Impossible to get devices");
return EXIT_FAILURE;
}
dev = discover_device (devices);
if (!dev) {
g_warning("No devices detected.");
return EXIT_FAILURE;
}
dev = discover_device (devices);
if (!dev)
{
g_warning ("No devices detected.");
return EXIT_FAILURE;
}
verify_data = g_new0 (VerifyData, 1);
verify_data->ret_value = EXIT_FAILURE;
verify_data->loop = g_main_loop_new (NULL, FALSE);
verify_data = g_new0 (VerifyData, 1);
verify_data->ret_value = EXIT_FAILURE;
verify_data->loop = g_main_loop_new (NULL, FALSE);
fp_device_open (dev, NULL, (GAsyncReadyCallback) on_device_opened,
verify_data);
fp_device_open (dev, NULL, (GAsyncReadyCallback) on_device_opened,
verify_data);
g_main_loop_run (verify_data->loop);
g_main_loop_run (verify_data->loop);
return verify_data->ret_value;
return verify_data->ret_value;
}

File diff suppressed because it is too large Load diff

View file

@ -25,66 +25,71 @@
#include "aes1660.h"
#define FRAME_WIDTH 128
#define IMAGE_WIDTH (FRAME_WIDTH + (FRAME_WIDTH / 2))
#define IMAGE_WIDTH (FRAME_WIDTH + (FRAME_WIDTH / 2))
struct _FpiDeviceAes1660 {
FpiDeviceAesX660 parent;
struct _FpiDeviceAes1660
{
FpiDeviceAesX660 parent;
};
G_DECLARE_FINAL_TYPE(FpiDeviceAes1660, fpi_device_aes1660, FPI,
DEVICE_AES1660, FpiDeviceAesX660);
G_DEFINE_TYPE(FpiDeviceAes1660, fpi_device_aes1660, FPI_TYPE_DEVICE_AES_X660);
G_DECLARE_FINAL_TYPE (FpiDeviceAes1660, fpi_device_aes1660, FPI,
DEVICE_AES1660, FpiDeviceAesX660);
G_DEFINE_TYPE (FpiDeviceAes1660, fpi_device_aes1660, FPI_TYPE_DEVICE_AES_X660);
static struct fpi_frame_asmbl_ctx assembling_ctx = {
.frame_width = FRAME_WIDTH,
.frame_height = AESX660_FRAME_HEIGHT,
.image_width = IMAGE_WIDTH,
.get_pixel = aes_get_pixel,
.frame_width = FRAME_WIDTH,
.frame_height = AESX660_FRAME_HEIGHT,
.image_width = IMAGE_WIDTH,
.get_pixel = aes_get_pixel,
};
static const FpIdEntry id_table [ ] = {
{ .vid = 0x08ff, .pid = 0x1660, },
{ .vid = 0x08ff, .pid = 0x1680, },
{ .vid = 0x08ff, .pid = 0x1681, },
{ .vid = 0x08ff, .pid = 0x1682, },
{ .vid = 0x08ff, .pid = 0x1683, },
{ .vid = 0x08ff, .pid = 0x1684, },
{ .vid = 0x08ff, .pid = 0x1685, },
{ .vid = 0x08ff, .pid = 0x1686, },
{ .vid = 0x08ff, .pid = 0x1687, },
{ .vid = 0x08ff, .pid = 0x1688, },
{ .vid = 0x08ff, .pid = 0x1689, },
{ .vid = 0x08ff, .pid = 0x168a, },
{ .vid = 0x08ff, .pid = 0x168b, },
{ .vid = 0x08ff, .pid = 0x168c, },
{ .vid = 0x08ff, .pid = 0x168d, },
{ .vid = 0x08ff, .pid = 0x168e, },
{ .vid = 0x08ff, .pid = 0x168f, },
{ .vid = 0, .pid = 0, .driver_data = 0 },
static const FpIdEntry id_table[] = {
{ .vid = 0x08ff, .pid = 0x1660, },
{ .vid = 0x08ff, .pid = 0x1680, },
{ .vid = 0x08ff, .pid = 0x1681, },
{ .vid = 0x08ff, .pid = 0x1682, },
{ .vid = 0x08ff, .pid = 0x1683, },
{ .vid = 0x08ff, .pid = 0x1684, },
{ .vid = 0x08ff, .pid = 0x1685, },
{ .vid = 0x08ff, .pid = 0x1686, },
{ .vid = 0x08ff, .pid = 0x1687, },
{ .vid = 0x08ff, .pid = 0x1688, },
{ .vid = 0x08ff, .pid = 0x1689, },
{ .vid = 0x08ff, .pid = 0x168a, },
{ .vid = 0x08ff, .pid = 0x168b, },
{ .vid = 0x08ff, .pid = 0x168c, },
{ .vid = 0x08ff, .pid = 0x168d, },
{ .vid = 0x08ff, .pid = 0x168e, },
{ .vid = 0x08ff, .pid = 0x168f, },
{ .vid = 0, .pid = 0, .driver_data = 0 },
};
static void fpi_device_aes1660_init(FpiDeviceAes1660 *self) {
static void
fpi_device_aes1660_init (FpiDeviceAes1660 *self)
{
}
static void fpi_device_aes1660_class_init(FpiDeviceAes1660Class *klass) {
FpDeviceClass *dev_class = FP_DEVICE_CLASS(klass);
FpImageDeviceClass *img_class = FP_IMAGE_DEVICE_CLASS(klass);
FpiDeviceAesX660Class *aes_class = FPI_DEVICE_AES_X660_CLASS (klass);
static void
fpi_device_aes1660_class_init (FpiDeviceAes1660Class *klass)
{
FpDeviceClass *dev_class = FP_DEVICE_CLASS (klass);
FpImageDeviceClass *img_class = FP_IMAGE_DEVICE_CLASS (klass);
FpiDeviceAesX660Class *aes_class = FPI_DEVICE_AES_X660_CLASS (klass);
dev_class->id = "aes1660";
dev_class->full_name = "AuthenTec AES1660";
dev_class->type = FP_DEVICE_TYPE_USB;
dev_class->id_table = id_table;
dev_class->scan_type = FP_SCAN_TYPE_SWIPE;
dev_class->id = "aes1660";
dev_class->full_name = "AuthenTec AES1660";
dev_class->type = FP_DEVICE_TYPE_USB;
dev_class->id_table = id_table;
dev_class->scan_type = FP_SCAN_TYPE_SWIPE;
img_class->bz3_threshold = 20;
img_class->bz3_threshold = 20;
img_class->img_width = FRAME_WIDTH + FRAME_WIDTH / 2;
img_class->img_height = -1;
img_class->img_width = FRAME_WIDTH + FRAME_WIDTH / 2;
img_class->img_height = -1;
aes_class->init_seqs[0] = aes1660_init_1;
aes_class->init_seqs_len[0] = G_N_ELEMENTS(aes1660_init_1);
aes_class->init_seqs[1] = aes1660_init_2;
aes_class->init_seqs_len[1] = G_N_ELEMENTS(aes1660_init_2);
aes_class->start_imaging_cmd = (unsigned char *)aes1660_start_imaging_cmd;
aes_class->start_imaging_cmd_len = sizeof(aes1660_start_imaging_cmd);
aes_class->assembling_ctx = &assembling_ctx;
aes_class->init_seqs[0] = aes1660_init_1;
aes_class->init_seqs_len[0] = G_N_ELEMENTS (aes1660_init_1);
aes_class->init_seqs[1] = aes1660_init_2;
aes_class->init_seqs_len[1] = G_N_ELEMENTS (aes1660_init_2);
aes_class->start_imaging_cmd = (unsigned char *) aes1660_start_imaging_cmd;
aes_class->start_imaging_cmd_len = sizeof (aes1660_start_imaging_cmd);
aes_class->assembling_ctx = &assembling_ctx;
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -23,149 +23,149 @@
#define __AES2501_H
enum aes2501_regs {
AES2501_REG_CTRL1 = 0x80,
AES2501_REG_CTRL2 = 0x81,
AES2501_REG_EXCITCTRL = 0x82, /* excitation control */
AES2501_REG_DETCTRL = 0x83, /* detect control */
AES2501_REG_COLSCAN = 0x88, /* column scan rate register */
AES2501_REG_MEASDRV = 0x89, /* measure drive */
AES2501_REG_MEASFREQ = 0x8a, /* measure frequency */
AES2501_REG_DEMODPHASE1 = 0x8d,
AES2501_REG_DEMODPHASE2 = 0x8c,
AES2501_REG_CHANGAIN = 0x8e, /* channel gain */
AES2501_REG_ADREFHI = 0x91, /* A/D reference high */
AES2501_REG_ADREFLO = 0x92, /* A/D reference low */
AES2501_REG_STRTROW = 0x93, /* start row */
AES2501_REG_ENDROW = 0x94, /* end row */
AES2501_REG_STRTCOL = 0x95, /* start column */
AES2501_REG_ENDCOL = 0x96, /* end column */
AES2501_REG_DATFMT = 0x97, /* data format */
AES2501_REG_IMAGCTRL = 0x98, /* image data */
AES2501_REG_STAT = 0x9a,
AES2501_REG_CHWORD1 = 0x9b, /* challenge word 1 */
AES2501_REG_CHWORD2 = 0x9c,
AES2501_REG_CHWORD3 = 0x9d,
AES2501_REG_CHWORD4 = 0x9e,
AES2501_REG_CHWORD5 = 0x9f,
AES2501_REG_TREG1 = 0xa1, /* test register 1 */
AES2501_REG_AUTOCALOFFSET = 0xa8,
AES2501_REG_TREGC = 0xac,
AES2501_REG_TREGD = 0xad,
AES2501_REG_LPONT = 0xb4, /* low power oscillator on time */
AES2501_REG_CTRL1 = 0x80,
AES2501_REG_CTRL2 = 0x81,
AES2501_REG_EXCITCTRL = 0x82, /* excitation control */
AES2501_REG_DETCTRL = 0x83, /* detect control */
AES2501_REG_COLSCAN = 0x88, /* column scan rate register */
AES2501_REG_MEASDRV = 0x89, /* measure drive */
AES2501_REG_MEASFREQ = 0x8a, /* measure frequency */
AES2501_REG_DEMODPHASE1 = 0x8d,
AES2501_REG_DEMODPHASE2 = 0x8c,
AES2501_REG_CHANGAIN = 0x8e, /* channel gain */
AES2501_REG_ADREFHI = 0x91, /* A/D reference high */
AES2501_REG_ADREFLO = 0x92, /* A/D reference low */
AES2501_REG_STRTROW = 0x93, /* start row */
AES2501_REG_ENDROW = 0x94, /* end row */
AES2501_REG_STRTCOL = 0x95, /* start column */
AES2501_REG_ENDCOL = 0x96, /* end column */
AES2501_REG_DATFMT = 0x97, /* data format */
AES2501_REG_IMAGCTRL = 0x98, /* image data */
AES2501_REG_STAT = 0x9a,
AES2501_REG_CHWORD1 = 0x9b, /* challenge word 1 */
AES2501_REG_CHWORD2 = 0x9c,
AES2501_REG_CHWORD3 = 0x9d,
AES2501_REG_CHWORD4 = 0x9e,
AES2501_REG_CHWORD5 = 0x9f,
AES2501_REG_TREG1 = 0xa1, /* test register 1 */
AES2501_REG_AUTOCALOFFSET = 0xa8,
AES2501_REG_TREGC = 0xac,
AES2501_REG_TREGD = 0xad,
AES2501_REG_LPONT = 0xb4, /* low power oscillator on time */
};
#define FIRST_AES2501_REG AES2501_REG_CTRL1
#define LAST_AES2501_REG AES2501_REG_CHWORD5
#define FIRST_AES2501_REG AES2501_REG_CTRL1
#define LAST_AES2501_REG AES2501_REG_CHWORD5
#define AES2501_CTRL1_MASTER_RESET (1<<0)
#define AES2501_CTRL1_SCAN_RESET (1<<1) /* stop + restart scan sequencer */
#define AES2501_CTRL1_MASTER_RESET (1 << 0)
#define AES2501_CTRL1_SCAN_RESET (1 << 1) /* stop + restart scan sequencer */
/* 1 = continuously updated, 0 = updated prior to starting a scan */
#define AES2501_CTRL1_REG_UPDATE (1<<2)
#define AES2501_CTRL1_REG_UPDATE (1 << 2)
/* 1 = continuous scans, 0 = single scans */
#define AES2501_CTRL2_CONTINUOUS 0x01
#define AES2501_CTRL2_READ_REGS 0x02 /* dump registers */
#define AES2501_CTRL2_SET_ONE_SHOT 0x04
#define AES2501_CTRL2_CLR_ONE_SHOT 0x08
#define AES2501_CTRL2_READ_ID 0x10
#define AES2501_CTRL2_CONTINUOUS 0x01
#define AES2501_CTRL2_READ_REGS 0x02 /* dump registers */
#define AES2501_CTRL2_SET_ONE_SHOT 0x04
#define AES2501_CTRL2_CLR_ONE_SHOT 0x08
#define AES2501_CTRL2_READ_ID 0x10
enum aes2501_detection_rate {
/* rate of detection cycles: */
AES2501_DETCTRL_DRATE_CONTINUOUS = 0x00, /* continuously */
AES2501_DETCTRL_DRATE_16_MS = 0x01, /* every 16.62ms */
AES2501_DETCTRL_DRATE_31_MS = 0x02, /* every 31.24ms */
AES2501_DETCTRL_DRATE_62_MS = 0x03, /* every 62.50ms */
AES2501_DETCTRL_DRATE_125_MS = 0x04, /* every 125.0ms */
AES2501_DETCTRL_DRATE_250_MS = 0x05, /* every 250.0ms */
AES2501_DETCTRL_DRATE_500_MS = 0x06, /* every 500.0ms */
AES2501_DETCTRL_DRATE_1_S = 0x07, /* every 1s */
/* rate of detection cycles: */
AES2501_DETCTRL_DRATE_CONTINUOUS = 0x00, /* continuously */
AES2501_DETCTRL_DRATE_16_MS = 0x01, /* every 16.62ms */
AES2501_DETCTRL_DRATE_31_MS = 0x02, /* every 31.24ms */
AES2501_DETCTRL_DRATE_62_MS = 0x03, /* every 62.50ms */
AES2501_DETCTRL_DRATE_125_MS = 0x04, /* every 125.0ms */
AES2501_DETCTRL_DRATE_250_MS = 0x05, /* every 250.0ms */
AES2501_DETCTRL_DRATE_500_MS = 0x06, /* every 500.0ms */
AES2501_DETCTRL_DRATE_1_S = 0x07, /* every 1s */
};
enum aes2501_settling_delay {
AES2501_DETCTRL_SDELAY_31_MS = 0x00, /* 31.25ms */
AES2501_DETCTRL_SSDELAY_62_MS = 0x10, /* 62.5ms */
AES2501_DETCTRL_SSDELAY_125_MS = 0x20, /* 125ms */
AES2501_DETCTRL_SSDELAY_250_MS = 0x30 /* 250ms */
AES2501_DETCTRL_SDELAY_31_MS = 0x00, /* 31.25ms */
AES2501_DETCTRL_SSDELAY_62_MS = 0x10, /* 62.5ms */
AES2501_DETCTRL_SSDELAY_125_MS = 0x20, /* 125ms */
AES2501_DETCTRL_SSDELAY_250_MS = 0x30 /* 250ms */
};
enum aes2501_col_scan_rate {
AES2501_COLSCAN_SRATE_32_US = 0x00, /* 32us */
AES2501_COLSCAN_SRATE_64_US = 0x01, /* 64us */
AES2501_COLSCAN_SRATE_128_US = 0x02, /* 128us */
AES2501_COLSCAN_SRATE_256_US = 0x03, /* 256us */
AES2501_COLSCAN_SRATE_512_US = 0x04, /* 512us */
AES2501_COLSCAN_SRATE_1024_US = 0x05, /* 1024us */
AES2501_COLSCAN_SRATE_2048_US = 0x06, /* 2048us */
AES2501_COLSCAN_SRATE_32_US = 0x00, /* 32us */
AES2501_COLSCAN_SRATE_64_US = 0x01, /* 64us */
AES2501_COLSCAN_SRATE_128_US = 0x02, /* 128us */
AES2501_COLSCAN_SRATE_256_US = 0x03, /* 256us */
AES2501_COLSCAN_SRATE_512_US = 0x04, /* 512us */
AES2501_COLSCAN_SRATE_1024_US = 0x05, /* 1024us */
AES2501_COLSCAN_SRATE_2048_US = 0x06, /* 2048us */
};
enum aes2501_mesure_drive {
AES2501_MEASDRV_MDRIVE_0_325 = 0x00, /* 0.325 Vpp */
AES2501_MEASDRV_MDRIVE_0_65 = 0x01, /* 0.65 Vpp */
AES2501_MEASDRV_MDRIVE_1_3 = 0x02, /* 1.3 Vpp */
AES2501_MEASDRV_MDRIVE_2_6 = 0x03 /* 2.6 Vpp */
AES2501_MEASDRV_MDRIVE_0_325 = 0x00, /* 0.325 Vpp */
AES2501_MEASDRV_MDRIVE_0_65 = 0x01, /* 0.65 Vpp */
AES2501_MEASDRV_MDRIVE_1_3 = 0x02, /* 1.3 Vpp */
AES2501_MEASDRV_MDRIVE_2_6 = 0x03 /* 2.6 Vpp */
};
/* Select (1=square | 0=sine) wave drive during measure */
#define AES2501_MEASDRV_SQUARE 0x20
#define AES2501_MEASDRV_SQUARE 0x20
/* 0 = use measure drive setting, 1 = when sine wave is selected */
#define AES2501_MEASDRV_MEASURE_SQUARE 0x10
#define AES2501_MEASDRV_MEASURE_SQUARE 0x10
enum aes2501_measure_freq {
AES2501_MEASFREQ_125K = 0x01, /* 125 kHz */
AES2501_MEASFREQ_250K = 0x02, /* 250 kHz */
AES2501_MEASFREQ_500K = 0x03, /* 500 kHz */
AES2501_MEASFREQ_1M = 0x04, /* 1 MHz */
AES2501_MEASFREQ_2M = 0x05 /* 2 MHz */
AES2501_MEASFREQ_125K = 0x01, /* 125 kHz */
AES2501_MEASFREQ_250K = 0x02, /* 250 kHz */
AES2501_MEASFREQ_500K = 0x03, /* 500 kHz */
AES2501_MEASFREQ_1M = 0x04, /* 1 MHz */
AES2501_MEASFREQ_2M = 0x05 /* 2 MHz */
};
#define DEMODPHASE_NONE 0x00
#define DEMODPHASE_180_00 0x40 /* 180 degrees */
#define DEMODPHASE_2_81 0x01 /* 2.8125 degrees */
#define DEMODPHASE_NONE 0x00
#define DEMODPHASE_180_00 0x40 /* 180 degrees */
#define DEMODPHASE_2_81 0x01 /* 2.8125 degrees */
#define AES2501_REG_DEMODPHASE1 0x8d
#define DEMODPHASE_1_40 0x40 /* 1.40625 degrees */
#define DEMODPHASE_0_02 0x01 /* 0.02197256 degrees */
#define DEMODPHASE_1_40 0x40 /* 1.40625 degrees */
#define DEMODPHASE_0_02 0x01 /* 0.02197256 degrees */
enum aes2501_sensor_gain1 {
AES2501_CHANGAIN_STAGE1_2X = 0x00, /* 2x */
AES2501_CHANGAIN_STAGE1_4X = 0x01, /* 4x */
AES2501_CHANGAIN_STAGE1_8X = 0x02, /* 8x */
AES2501_CHANGAIN_STAGE1_16X = 0x03 /* 16x */
AES2501_CHANGAIN_STAGE1_2X = 0x00, /* 2x */
AES2501_CHANGAIN_STAGE1_4X = 0x01, /* 4x */
AES2501_CHANGAIN_STAGE1_8X = 0x02, /* 8x */
AES2501_CHANGAIN_STAGE1_16X = 0x03 /* 16x */
};
enum aes2501_sensor_gain2 {
AES2501_CHANGAIN_STAGE2_2X = 0x00, /* 2x */
AES2501_CHANGAIN_STAGE2_4X = 0x10, /* 4x */
AES2501_CHANGAIN_STAGE2_8X = 0x20, /* 8x */
AES2501_CHANGAIN_STAGE2_16X = 0x30 /* 16x */
AES2501_CHANGAIN_STAGE2_2X = 0x00, /* 2x */
AES2501_CHANGAIN_STAGE2_4X = 0x10, /* 4x */
AES2501_CHANGAIN_STAGE2_8X = 0x20, /* 8x */
AES2501_CHANGAIN_STAGE2_16X = 0x30 /* 16x */
};
#define AES2501_DATFMT_EIGHT 0x40 /* 1 = 8-bit data, 0 = 4-bit data */
#define AES2501_DATFMT_LOW_RES 0x20
#define AES2501_DATFMT_BIN_IMG 0x10
#define AES2501_DATFMT_EIGHT 0x40 /* 1 = 8-bit data, 0 = 4-bit data */
#define AES2501_DATFMT_LOW_RES 0x20
#define AES2501_DATFMT_BIN_IMG 0x10
/* don't send image or authentication messages when imaging */
#define AES2501_IMAGCTRL_IMG_DATA_DISABLE 0x01
#define AES2501_IMAGCTRL_IMG_DATA_DISABLE 0x01
/* send histogram when imaging */
#define AES2501_IMAGCTRL_HISTO_DATA_ENABLE 0x02
#define AES2501_IMAGCTRL_HISTO_DATA_ENABLE 0x02
/* send histogram at end of each row rather than each scan */
#define AES2501_IMAGCTRL_HISTO_EACH_ROW 0x04
#define AES2501_IMAGCTRL_HISTO_EACH_ROW 0x04
/* send full image array rather than 64x64 center */
#define AES2501_IMAGCTRL_HISTO_FULL_ARRAY 0x08
#define AES2501_IMAGCTRL_HISTO_FULL_ARRAY 0x08
/* return registers before data (rather than after) */
#define AES2501_IMAGCTRL_REG_FIRST 0x10
#define AES2501_IMAGCTRL_REG_FIRST 0x10
/* return test registers with register dump */
#define AES2501_IMAGCTRL_TST_REG_ENABLE 0x20
#define AES2501_IMAGCTRL_TST_REG_ENABLE 0x20
#define AES2501_CHWORD1_IS_FINGER 0x01 /* If set, finger is present */
#define AES2501_CHWORD1_IS_FINGER 0x01 /* If set, finger is present */
/* Enable the reading of the register in TREGD */
#define AES2501_TREGC_ENABLE 0x01
#define AES2501_TREGC_ENABLE 0x01
#define AES2501_LPONT_MIN_VALUE 0x00 /* 0 ms */
#define AES2501_LPONT_MAX_VALUE 0x1f /* About 16 ms */
#define AES2501_LPONT_MIN_VALUE 0x00 /* 0 ms */
#define AES2501_LPONT_MAX_VALUE 0x1f /* About 16 ms */
#define AES2501_ADREFHI_MIN_VALUE 0x28
#define AES2501_ADREFHI_MAX_VALUE 0x58
@ -173,4 +173,4 @@ enum aes2501_sensor_gain2 {
#define AES2501_SUM_HIGH_THRESH 1000
#define AES2501_SUM_LOW_THRESH 700
#endif /* __AES2501_H */
#endif /* __AES2501_H */

View file

@ -27,11 +27,11 @@
#include "aes2550.h"
#include "aeslib.h"
static void start_capture(FpImageDevice *dev);
static void complete_deactivation(FpImageDevice *dev);
static void start_capture (FpImageDevice *dev);
static void complete_deactivation (FpImageDevice *dev);
#define EP_IN (1 | FPI_USB_ENDPOINT_IN)
#define EP_OUT (2 | FPI_USB_ENDPOINT_OUT)
#define EP_IN (1 | FPI_USB_ENDPOINT_IN)
#define EP_OUT (2 | FPI_USB_ENDPOINT_OUT)
#define BULK_TIMEOUT 4000
/*
@ -46,528 +46,583 @@ static void complete_deactivation(FpImageDevice *dev);
* images returned from this driver vary in height.
*/
#define FRAME_WIDTH 192
#define FRAME_HEIGHT 8
#define FRAME_SIZE (FRAME_WIDTH * FRAME_HEIGHT)
#define IMAGE_WIDTH (FRAME_WIDTH + (FRAME_WIDTH / 2))
#define FRAME_WIDTH 192
#define FRAME_HEIGHT 8
#define FRAME_SIZE (FRAME_WIDTH * FRAME_HEIGHT)
#define IMAGE_WIDTH (FRAME_WIDTH + (FRAME_WIDTH / 2))
struct _FpiDeviceAes2550 {
FpImageDevice parent;
struct _FpiDeviceAes2550
{
FpImageDevice parent;
GSList *strips;
size_t strips_len;
gboolean deactivating;
int heartbeat_cnt;
GSList *strips;
size_t strips_len;
gboolean deactivating;
int heartbeat_cnt;
};
G_DECLARE_FINAL_TYPE(FpiDeviceAes2550, fpi_device_aes2550, FPI, DEVICE_AES2550,
FpImageDevice);
G_DEFINE_TYPE(FpiDeviceAes2550, fpi_device_aes2550, FP_TYPE_IMAGE_DEVICE);
G_DECLARE_FINAL_TYPE (FpiDeviceAes2550, fpi_device_aes2550, FPI, DEVICE_AES2550,
FpImageDevice);
G_DEFINE_TYPE (FpiDeviceAes2550, fpi_device_aes2550, FP_TYPE_IMAGE_DEVICE);
static struct fpi_frame_asmbl_ctx assembling_ctx = {
.frame_width = FRAME_WIDTH,
.frame_height = FRAME_HEIGHT,
.image_width = IMAGE_WIDTH,
.get_pixel = aes_get_pixel,
.frame_width = FRAME_WIDTH,
.frame_height = FRAME_HEIGHT,
.image_width = IMAGE_WIDTH,
.get_pixel = aes_get_pixel,
};
/****** FINGER PRESENCE DETECTION ******/
static unsigned char finger_det_reqs[] = {
0x80, AES2550_REG80_MASTER_RESET,
0x95, (8 << AES2550_REG95_COL_SCANNED_OFS) | (1 << AES2550_REG95_EPIX_AVG_OFS),
0xad, 0x00,
0xbd, (0 << AES2550_REGBD_LPO_IN_15_8_OFS),
0xbe, (0 << AES2550_REGBE_LPO_IN_7_0_OFS),
0xcf, AES2550_REGCF_INTERFERENCE_CHK_EN,
AES2550_CMD_HEARTBEAT, 0x00, 0x01, 0x00, /* Heart beat off */
AES2550_CMD_RUN_FD,
0x80, AES2550_REG80_MASTER_RESET,
0x95, (8 << AES2550_REG95_COL_SCANNED_OFS) | (1 << AES2550_REG95_EPIX_AVG_OFS),
0xad, 0x00,
0xbd, (0 << AES2550_REGBD_LPO_IN_15_8_OFS),
0xbe, (0 << AES2550_REGBE_LPO_IN_7_0_OFS),
0xcf, AES2550_REGCF_INTERFERENCE_CHK_EN,
AES2550_CMD_HEARTBEAT, 0x00, 0x01, 0x00, /* Heart beat off */
AES2550_CMD_RUN_FD,
};
static void start_finger_detection(FpImageDevice *dev);
static void start_finger_detection (FpImageDevice *dev);
static void finger_det_data_cb(FpiUsbTransfer *transfer, FpDevice *device,
gpointer user_data, GError *error)
static void
finger_det_data_cb (FpiUsbTransfer *transfer, FpDevice *device,
gpointer user_data, GError *error)
{
FpImageDevice *dev = FP_IMAGE_DEVICE(device);
unsigned char *data = transfer->buffer;
FpImageDevice *dev = FP_IMAGE_DEVICE (device);
unsigned char *data = transfer->buffer;
if (error) {
fpi_image_device_session_error(FP_IMAGE_DEVICE(device), error);
return;
}
if (error)
{
fpi_image_device_session_error (FP_IMAGE_DEVICE (device), error);
return;
}
fp_dbg("transfer completed, len: %.4x, data: %.2x %.2x",
(gint)transfer->actual_length, (int)data[0], (int)data[1]);
fp_dbg ("transfer completed, len: %.4x, data: %.2x %.2x",
(gint) transfer->actual_length, (int) data[0], (int) data[1]);
/* Check if we got 2 bytes, reg address 0x83 and its value */
if ((transfer->actual_length >= 2) && (data[0] == 0x83) && (data[1] & AES2550_REG83_FINGER_PRESENT)) {
/* finger present, start capturing */
fpi_image_device_report_finger_status(dev, TRUE);
start_capture(dev);
} else {
/* no finger, poll for a new histogram */
start_finger_detection(dev);
}
/* Check if we got 2 bytes, reg address 0x83 and its value */
if ((transfer->actual_length >= 2) && (data[0] == 0x83) && (data[1] & AES2550_REG83_FINGER_PRESENT))
{
/* finger present, start capturing */
fpi_image_device_report_finger_status (dev, TRUE);
start_capture (dev);
}
else
{
/* no finger, poll for a new histogram */
start_finger_detection (dev);
}
}
static void finger_det_reqs_cb(FpiUsbTransfer *t, FpDevice *device,
gpointer user_data, GError *error)
static void
finger_det_reqs_cb (FpiUsbTransfer *t, FpDevice *device,
gpointer user_data, GError *error)
{
FpiUsbTransfer *transfer;
FpImageDevice *dev = user_data;
FpiUsbTransfer *transfer;
FpImageDevice *dev = user_data;
if (error) {
fpi_image_device_session_error(dev, error);
return;
}
if (error)
{
fpi_image_device_session_error (dev, error);
return;
}
transfer = fpi_usb_transfer_new (device);
/* 2 bytes of result */
fpi_usb_transfer_fill_bulk (transfer, EP_IN, AES2550_EP_IN_BUF_SIZE);
fpi_usb_transfer_submit(transfer, BULK_TIMEOUT, NULL,
finger_det_data_cb, NULL);
fpi_usb_transfer_unref(transfer);
transfer = fpi_usb_transfer_new (device);
/* 2 bytes of result */
fpi_usb_transfer_fill_bulk (transfer, EP_IN, AES2550_EP_IN_BUF_SIZE);
fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
finger_det_data_cb, NULL);
fpi_usb_transfer_unref (transfer);
}
static void start_finger_detection(FpImageDevice *dev)
static void
start_finger_detection (FpImageDevice *dev)
{
FpiDeviceAes2550 *self = FPI_DEVICE_AES2550(dev);
FpiUsbTransfer *transfer;
G_DEBUG_HERE();
FpiDeviceAes2550 *self = FPI_DEVICE_AES2550 (dev);
FpiUsbTransfer *transfer;
if (self->deactivating) {
complete_deactivation(dev);
return;
}
G_DEBUG_HERE ();
transfer = fpi_usb_transfer_new(FP_DEVICE(dev));
transfer->short_is_error = TRUE;
fpi_usb_transfer_fill_bulk_full(transfer, EP_OUT, finger_det_reqs,
sizeof(finger_det_reqs), NULL);
fpi_usb_transfer_submit(transfer, BULK_TIMEOUT, NULL,
finger_det_reqs_cb, NULL);
fpi_usb_transfer_unref(transfer);
if (self->deactivating)
{
complete_deactivation (dev);
return;
}
transfer = fpi_usb_transfer_new (FP_DEVICE (dev));
transfer->short_is_error = TRUE;
fpi_usb_transfer_fill_bulk_full (transfer, EP_OUT, finger_det_reqs,
sizeof (finger_det_reqs), NULL);
fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
finger_det_reqs_cb, NULL);
fpi_usb_transfer_unref (transfer);
}
/****** CAPTURE ******/
static unsigned char capture_reqs[] = {
0x80, AES2550_REG80_MASTER_RESET,
0x80, (1 << AES2550_REG80_SENSOR_MODE_OFS) | (AES2550_REG80_HGC_ENABLE),
0x85, AES2550_REG85_FLUSH_PER_FRAME,
0x8f, AES2550_REG8F_AUTH_DISABLE | AES2550_REG8F_EHISTO_DISABLE,
0xbf, AES2550_REGBF_RSR_DIR_UPDOWN_MOTION | AES2550_REGBF_RSR_LEVEL_SUPER_RSR,
0xcf, (3 << AES2550_REGCF_INTERFERENCE_AVG_OFFS) | AES2550_REGCF_INTERFERENCE_AVG_EN,
0xdc, (1 << AES2550_REGDC_BP_NUM_REF_SWEEP_OFS),
AES2550_CMD_HEARTBEAT, 0x00, 0x01, 0x03, /* Heart beat cmd, 3 * 16 cycles without sending image */
AES2550_CMD_GET_ENROLL_IMG,
0x80, AES2550_REG80_MASTER_RESET,
0x80, (1 << AES2550_REG80_SENSOR_MODE_OFS) | (AES2550_REG80_HGC_ENABLE),
0x85, AES2550_REG85_FLUSH_PER_FRAME,
0x8f, AES2550_REG8F_AUTH_DISABLE | AES2550_REG8F_EHISTO_DISABLE,
0xbf, AES2550_REGBF_RSR_DIR_UPDOWN_MOTION | AES2550_REGBF_RSR_LEVEL_SUPER_RSR,
0xcf, (3 << AES2550_REGCF_INTERFERENCE_AVG_OFFS) | AES2550_REGCF_INTERFERENCE_AVG_EN,
0xdc, (1 << AES2550_REGDC_BP_NUM_REF_SWEEP_OFS),
AES2550_CMD_HEARTBEAT, 0x00, 0x01, 0x03, /* Heart beat cmd, 3 * 16 cycles without sending image */
AES2550_CMD_GET_ENROLL_IMG,
};
static unsigned char capture_set_idle_reqs[] = {
0x80, AES2550_REG80_MASTER_RESET,
AES2550_CMD_HEARTBEAT, 0x00, 0x01, 0x00, /* Heart beat off */
AES2550_CMD_SET_IDLE_MODE,
0x80, AES2550_REG80_MASTER_RESET,
AES2550_CMD_HEARTBEAT, 0x00, 0x01, 0x00, /* Heart beat off */
AES2550_CMD_SET_IDLE_MODE,
};
enum capture_states {
CAPTURE_WRITE_REQS,
CAPTURE_READ_DATA,
CAPTURE_SET_IDLE,
CAPTURE_NUM_STATES,
CAPTURE_WRITE_REQS,
CAPTURE_READ_DATA,
CAPTURE_SET_IDLE,
CAPTURE_NUM_STATES,
};
/* Returns number of processed bytes */
static gboolean process_strip_data(FpiSsm *ssm, FpImageDevice *dev,
unsigned char *data)
static gboolean
process_strip_data (FpiSsm *ssm, FpImageDevice *dev,
unsigned char *data)
{
unsigned char *stripdata;
FpiDeviceAes2550 *self = FPI_DEVICE_AES2550(dev);
struct fpi_frame *stripe;
int len;
unsigned char *stripdata;
FpiDeviceAes2550 *self = FPI_DEVICE_AES2550 (dev);
struct fpi_frame *stripe;
int len;
if (data[0] != AES2550_EDATA_MAGIC) {
fp_dbg("Bogus magic: %.2x\n", (int)(data[0]));
return FALSE;
}
len = data[1] * 256 + data[2];
if (len != (AES2550_STRIP_SIZE - 3)) {
fp_dbg("Bogus frame len: %.4x\n", len);
}
stripe = g_malloc0(FRAME_WIDTH * FRAME_HEIGHT / 2 + sizeof(struct fpi_frame)); /* 4 bits per pixel */
stripe->delta_x = (int8_t)data[6];
stripe->delta_y = -(int8_t)data[7];
stripdata = stripe->data;
memcpy(stripdata, data + 33, FRAME_WIDTH * FRAME_HEIGHT / 2);
self->strips = g_slist_prepend(self->strips, stripe);
self->strips_len++;
if (data[0] != AES2550_EDATA_MAGIC)
{
fp_dbg ("Bogus magic: %.2x\n", (int) (data[0]));
return FALSE;
}
len = data[1] * 256 + data[2];
if (len != (AES2550_STRIP_SIZE - 3))
fp_dbg ("Bogus frame len: %.4x\n", len);
stripe = g_malloc0 (FRAME_WIDTH * FRAME_HEIGHT / 2 + sizeof (struct fpi_frame)); /* 4 bits per pixel */
stripe->delta_x = (int8_t) data[6];
stripe->delta_y = -(int8_t) data[7];
stripdata = stripe->data;
memcpy (stripdata, data + 33, FRAME_WIDTH * FRAME_HEIGHT / 2);
self->strips = g_slist_prepend (self->strips, stripe);
self->strips_len++;
fp_dbg("deltas: %dx%d", stripe->delta_x, stripe->delta_y);
fp_dbg ("deltas: %dx%d", stripe->delta_x, stripe->delta_y);
return TRUE;
return TRUE;
}
static void capture_reqs_cb(FpiUsbTransfer *transfer, FpDevice *device,
gpointer user_data, GError *error)
static void
capture_reqs_cb (FpiUsbTransfer *transfer, FpDevice *device,
gpointer user_data, GError *error)
{
if (!error) {
fpi_ssm_next_state(transfer->ssm);
} else {
fpi_ssm_mark_failed(transfer->ssm, error);
}
if (!error)
fpi_ssm_next_state (transfer->ssm);
else
fpi_ssm_mark_failed (transfer->ssm, error);
}
static void capture_set_idle_reqs_cb(FpiUsbTransfer *transfer,
FpDevice *device, gpointer user_data,
GError *error)
static void
capture_set_idle_reqs_cb (FpiUsbTransfer *transfer,
FpDevice *device, gpointer user_data,
GError *error)
{
FpImageDevice *dev = FP_IMAGE_DEVICE(device);
FpiDeviceAes2550 *self = FPI_DEVICE_AES2550(dev);
FpImageDevice *dev = FP_IMAGE_DEVICE (device);
FpiDeviceAes2550 *self = FPI_DEVICE_AES2550 (dev);
if (!error && self->strips_len) {
FpImage *img;
if (!error && self->strips_len)
{
FpImage *img;
self->strips = g_slist_reverse(self->strips);
img = fpi_assemble_frames(&assembling_ctx, self->strips);
g_slist_free_full(self->strips, g_free);
self->strips = NULL;
self->strips_len = 0;
fpi_image_device_image_captured(dev, img);
fpi_image_device_report_finger_status(dev, FALSE);
/* marking machine complete will re-trigger finger detection loop */
fpi_ssm_mark_completed(transfer->ssm);
} else {
if (error)
fpi_ssm_mark_failed(transfer->ssm, error);
else
fpi_ssm_mark_failed(transfer->ssm,
fpi_device_error_new (FP_DEVICE_ERROR_PROTO));
}
self->strips = g_slist_reverse (self->strips);
img = fpi_assemble_frames (&assembling_ctx, self->strips);
g_slist_free_full (self->strips, g_free);
self->strips = NULL;
self->strips_len = 0;
fpi_image_device_image_captured (dev, img);
fpi_image_device_report_finger_status (dev, FALSE);
/* marking machine complete will re-trigger finger detection loop */
fpi_ssm_mark_completed (transfer->ssm);
}
else
{
if (error)
fpi_ssm_mark_failed (transfer->ssm, error);
else
fpi_ssm_mark_failed (transfer->ssm,
fpi_device_error_new (FP_DEVICE_ERROR_PROTO));
}
}
static void capture_read_data_cb(FpiUsbTransfer *transfer, FpDevice *device,
gpointer user_data, GError *error)
static void
capture_read_data_cb (FpiUsbTransfer *transfer, FpDevice *device,
gpointer user_data, GError *error)
{
FpImageDevice *dev = FP_IMAGE_DEVICE(device);
FpiDeviceAes2550 *self = FPI_DEVICE_AES2550(dev);
unsigned char *data = transfer->buffer;
FpImageDevice *dev = FP_IMAGE_DEVICE (device);
FpiDeviceAes2550 *self = FPI_DEVICE_AES2550 (dev);
unsigned char *data = transfer->buffer;
if (error) {
fpi_ssm_mark_failed(transfer->ssm, error);
return;
}
if (error)
{
fpi_ssm_mark_failed (transfer->ssm, error);
return;
}
fp_dbg("request completed, len: %.4x", (gint)transfer->actual_length);
if (transfer->actual_length >= 2)
fp_dbg("data: %.2x %.2x", (int)data[0], (int)data[1]);
fp_dbg ("request completed, len: %.4x", (gint) transfer->actual_length);
if (transfer->actual_length >= 2)
fp_dbg ("data: %.2x %.2x", (int) data[0], (int) data[1]);
switch (transfer->actual_length) {
case AES2550_STRIP_SIZE:
if (!process_strip_data(transfer->ssm, dev, data)) {
fp_dbg("Processing strip data failed");
fpi_ssm_mark_failed(transfer->ssm,
fpi_device_error_new (FP_DEVICE_ERROR_PROTO));
return;
}
self->heartbeat_cnt = 0;
fpi_ssm_jump_to_state(transfer->ssm, CAPTURE_READ_DATA);
break;
case AES2550_HEARTBEAT_SIZE:
if (data[0] == AES2550_HEARTBEAT_MAGIC) {
/* No data for a long time => finger was removed or there's no movement */
self->heartbeat_cnt++;
if (self->heartbeat_cnt == 3) {
/* Got 3 heartbeat message, that's enough to consider that finger was removed,
* assemble image and submit it to the library */
fp_dbg("Got 3 heartbeats => finger removed");
fpi_ssm_next_state(transfer->ssm);
} else {
fpi_ssm_jump_to_state(transfer->ssm,
CAPTURE_READ_DATA);
}
}
break;
default:
fp_dbg("Short frame %d, skip",
(gint)transfer->actual_length);
fpi_ssm_jump_to_state(transfer->ssm, CAPTURE_READ_DATA);
break;
}
switch (transfer->actual_length)
{
case AES2550_STRIP_SIZE:
if (!process_strip_data (transfer->ssm, dev, data))
{
fp_dbg ("Processing strip data failed");
fpi_ssm_mark_failed (transfer->ssm,
fpi_device_error_new (FP_DEVICE_ERROR_PROTO));
return;
}
self->heartbeat_cnt = 0;
fpi_ssm_jump_to_state (transfer->ssm, CAPTURE_READ_DATA);
break;
case AES2550_HEARTBEAT_SIZE:
if (data[0] == AES2550_HEARTBEAT_MAGIC)
{
/* No data for a long time => finger was removed or there's no movement */
self->heartbeat_cnt++;
if (self->heartbeat_cnt == 3)
{
/* Got 3 heartbeat message, that's enough to consider that finger was removed,
* assemble image and submit it to the library */
fp_dbg ("Got 3 heartbeats => finger removed");
fpi_ssm_next_state (transfer->ssm);
}
else
{
fpi_ssm_jump_to_state (transfer->ssm,
CAPTURE_READ_DATA);
}
}
break;
default:
fp_dbg ("Short frame %d, skip",
(gint) transfer->actual_length);
fpi_ssm_jump_to_state (transfer->ssm, CAPTURE_READ_DATA);
break;
}
}
static void capture_run_state(FpiSsm *ssm, FpDevice *dev, void *user_data)
static void
capture_run_state (FpiSsm *ssm, FpDevice *dev, void *user_data)
{
switch (fpi_ssm_get_cur_state(ssm)) {
case CAPTURE_WRITE_REQS:
{
FpiUsbTransfer *transfer = fpi_usb_transfer_new(dev);
switch (fpi_ssm_get_cur_state (ssm))
{
case CAPTURE_WRITE_REQS:
{
FpiUsbTransfer *transfer = fpi_usb_transfer_new (dev);
fpi_usb_transfer_fill_bulk_full(transfer, EP_OUT, capture_reqs,
sizeof(capture_reqs), NULL);
transfer->ssm = ssm;
transfer->short_is_error = TRUE;
fpi_usb_transfer_submit(transfer, BULK_TIMEOUT, NULL,
capture_reqs_cb, NULL);
fpi_usb_transfer_unref(transfer);
}
break;
case CAPTURE_READ_DATA:
{
FpiUsbTransfer *transfer = fpi_usb_transfer_new(dev);
fpi_usb_transfer_fill_bulk_full (transfer, EP_OUT, capture_reqs,
sizeof (capture_reqs), NULL);
transfer->ssm = ssm;
transfer->short_is_error = TRUE;
fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
capture_reqs_cb, NULL);
fpi_usb_transfer_unref (transfer);
}
break;
fpi_usb_transfer_fill_bulk (transfer, EP_IN, AES2550_EP_IN_BUF_SIZE);
transfer->ssm = ssm;
fpi_usb_transfer_submit(transfer, BULK_TIMEOUT, NULL,
capture_read_data_cb, NULL);
fpi_usb_transfer_unref(transfer);
}
break;
case CAPTURE_SET_IDLE:
{
FpiUsbTransfer *transfer = fpi_usb_transfer_new(dev);
case CAPTURE_READ_DATA:
{
FpiUsbTransfer *transfer = fpi_usb_transfer_new (dev);
fpi_usb_transfer_fill_bulk_full(transfer, EP_OUT,
capture_set_idle_reqs,
sizeof(capture_set_idle_reqs),
NULL);
transfer->ssm = ssm;
transfer->short_is_error = TRUE;
fpi_usb_transfer_submit(transfer, BULK_TIMEOUT, NULL,
capture_set_idle_reqs_cb, NULL);
fpi_usb_transfer_unref(transfer);
}
break;
};
fpi_usb_transfer_fill_bulk (transfer, EP_IN, AES2550_EP_IN_BUF_SIZE);
transfer->ssm = ssm;
fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
capture_read_data_cb, NULL);
fpi_usb_transfer_unref (transfer);
}
break;
case CAPTURE_SET_IDLE:
{
FpiUsbTransfer *transfer = fpi_usb_transfer_new (dev);
fpi_usb_transfer_fill_bulk_full (transfer, EP_OUT,
capture_set_idle_reqs,
sizeof (capture_set_idle_reqs),
NULL);
transfer->ssm = ssm;
transfer->short_is_error = TRUE;
fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
capture_set_idle_reqs_cb, NULL);
fpi_usb_transfer_unref (transfer);
}
break;
}
;
}
static void capture_sm_complete(FpiSsm *ssm, FpDevice *_dev, void *user_data,
GError *error)
static void
capture_sm_complete (FpiSsm *ssm, FpDevice *_dev, void *user_data,
GError *error)
{
FpImageDevice *dev = user_data;
FpiDeviceAes2550 *self = FPI_DEVICE_AES2550(_dev);
FpImageDevice *dev = user_data;
FpiDeviceAes2550 *self = FPI_DEVICE_AES2550 (_dev);
fp_dbg("Capture completed");
fp_dbg ("Capture completed");
if (self->deactivating) {
complete_deactivation(dev);
g_clear_pointer (&error, g_error_free);
} else if (error) {
fpi_image_device_session_error(dev, error);
} else {
start_finger_detection(dev);
}
fpi_ssm_free(ssm);
if (self->deactivating)
{
complete_deactivation (dev);
g_clear_pointer (&error, g_error_free);
}
else if (error)
{
fpi_image_device_session_error (dev, error);
}
else
{
start_finger_detection (dev);
}
fpi_ssm_free (ssm);
}
static void start_capture(FpImageDevice *dev)
static void
start_capture (FpImageDevice *dev)
{
FpiDeviceAes2550 *self = FPI_DEVICE_AES2550(dev);
FpiSsm *ssm;
FpiDeviceAes2550 *self = FPI_DEVICE_AES2550 (dev);
FpiSsm *ssm;
if (self->deactivating) {
complete_deactivation(dev);
return;
}
if (self->deactivating)
{
complete_deactivation (dev);
return;
}
self->heartbeat_cnt = 0;
ssm = fpi_ssm_new(FP_DEVICE(dev), capture_run_state,
CAPTURE_NUM_STATES, dev);
G_DEBUG_HERE();
fpi_ssm_start(ssm, capture_sm_complete);
self->heartbeat_cnt = 0;
ssm = fpi_ssm_new (FP_DEVICE (dev), capture_run_state,
CAPTURE_NUM_STATES, dev);
G_DEBUG_HERE ();
fpi_ssm_start (ssm, capture_sm_complete);
}
/****** INITIALIZATION/DEINITIALIZATION ******/
static unsigned char init_reqs[] = {
0x80, AES2550_REG80_MASTER_RESET, /* Master reset */
0x80, (1 << AES2550_REG80_SENSOR_MODE_OFS) | (AES2550_REG80_FORCE_FINGER_PRESENT),
0x85, AES2550_REG85_FLUSH_PER_FRAME,
0xa8, AES2550_REGA8_DIG_BIT_EN,
0x81, AES2550_REG81_NSHOT,
0x80, AES2550_REG80_MASTER_RESET, /* Master reset */
0x80, (1 << AES2550_REG80_SENSOR_MODE_OFS) | (AES2550_REG80_FORCE_FINGER_PRESENT),
0x85, AES2550_REG85_FLUSH_PER_FRAME,
0xa8, AES2550_REGA8_DIG_BIT_EN,
0x81, AES2550_REG81_NSHOT,
};
static unsigned char calibrate_reqs[] = {
0x80, AES2550_REG80_MASTER_RESET, /* Master reset */
AES2550_CMD_CALIBRATE,
AES2550_CMD_READ_CALIBRATION_DATA,
0x80, AES2550_REG80_MASTER_RESET, /* Master reset */
AES2550_CMD_CALIBRATE,
AES2550_CMD_READ_CALIBRATION_DATA,
};
enum activate_states {
WRITE_INIT,
READ_DATA,
CALIBRATE,
READ_CALIB_TABLE,
ACTIVATE_NUM_STATES,
WRITE_INIT,
READ_DATA,
CALIBRATE,
READ_CALIB_TABLE,
ACTIVATE_NUM_STATES,
};
static void init_reqs_cb(FpiUsbTransfer *transfer, FpDevice *device,
gpointer user_data, GError *error)
static void
init_reqs_cb (FpiUsbTransfer *transfer, FpDevice *device,
gpointer user_data, GError *error)
{
if (!error) {
fpi_ssm_next_state(transfer->ssm);
} else {
fpi_ssm_mark_failed(transfer->ssm, error);
}
if (!error)
fpi_ssm_next_state (transfer->ssm);
else
fpi_ssm_mark_failed (transfer->ssm, error);
}
static void init_read_data_cb(FpiUsbTransfer *transfer, FpDevice *device,
gpointer user_data, GError *error)
static void
init_read_data_cb (FpiUsbTransfer *transfer, FpDevice *device,
gpointer user_data, GError *error)
{
if (!error) {
fpi_ssm_next_state(transfer->ssm);
} else {
fpi_ssm_mark_failed(transfer->ssm, error);
}
if (!error)
fpi_ssm_next_state (transfer->ssm);
else
fpi_ssm_mark_failed (transfer->ssm, error);
}
/* TODO: use calibration table, datasheet is rather terse on that
* need more info for implementation */
static void calibrate_read_data_cb(FpiUsbTransfer *transfer, FpDevice *device,
gpointer user_data, GError *error)
static void
calibrate_read_data_cb (FpiUsbTransfer *transfer, FpDevice *device,
gpointer user_data, GError *error)
{
if (!error) {
fpi_ssm_next_state(transfer->ssm);
} else {
fpi_ssm_mark_failed(transfer->ssm, error);
}
if (!error)
fpi_ssm_next_state (transfer->ssm);
else
fpi_ssm_mark_failed (transfer->ssm, error);
}
static void activate_run_state(FpiSsm *ssm, FpDevice *dev, void *user_data)
static void
activate_run_state (FpiSsm *ssm, FpDevice *dev, void *user_data)
{
switch (fpi_ssm_get_cur_state(ssm)) {
case WRITE_INIT:
{
FpiUsbTransfer *transfer = fpi_usb_transfer_new(dev);
switch (fpi_ssm_get_cur_state (ssm))
{
case WRITE_INIT:
{
FpiUsbTransfer *transfer = fpi_usb_transfer_new (dev);
fpi_usb_transfer_fill_bulk_full(transfer, EP_OUT, init_reqs,
sizeof(init_reqs), NULL);
transfer->ssm = ssm;
transfer->short_is_error = TRUE;
fpi_usb_transfer_submit(transfer, BULK_TIMEOUT, NULL,
init_reqs_cb, NULL);
fpi_usb_transfer_unref(transfer);
}
break;
case READ_DATA:
{
FpiUsbTransfer *transfer = fpi_usb_transfer_new(dev);
fpi_usb_transfer_fill_bulk_full (transfer, EP_OUT, init_reqs,
sizeof (init_reqs), NULL);
transfer->ssm = ssm;
transfer->short_is_error = TRUE;
fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
init_reqs_cb, NULL);
fpi_usb_transfer_unref (transfer);
}
break;
fpi_usb_transfer_fill_bulk(transfer, EP_IN, AES2550_EP_IN_BUF_SIZE);
transfer->ssm = ssm;
fpi_usb_transfer_submit(transfer, BULK_TIMEOUT, NULL,
init_read_data_cb, NULL);
fpi_usb_transfer_unref(transfer);
}
break;
case CALIBRATE:
{
FpiUsbTransfer *transfer = fpi_usb_transfer_new(dev);
case READ_DATA:
{
FpiUsbTransfer *transfer = fpi_usb_transfer_new (dev);
fpi_usb_transfer_fill_bulk_full(transfer, EP_OUT,
calibrate_reqs,
sizeof(calibrate_reqs), NULL);
transfer->ssm = ssm;
transfer->short_is_error = TRUE;
fpi_usb_transfer_submit(transfer, BULK_TIMEOUT, NULL,
init_reqs_cb, NULL);
fpi_usb_transfer_unref(transfer);
}
break;
case READ_CALIB_TABLE:
{
FpiUsbTransfer *transfer = fpi_usb_transfer_new(dev);
fpi_usb_transfer_fill_bulk (transfer, EP_IN, AES2550_EP_IN_BUF_SIZE);
transfer->ssm = ssm;
fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
init_read_data_cb, NULL);
fpi_usb_transfer_unref (transfer);
}
break;
fpi_usb_transfer_fill_bulk(transfer, EP_IN, AES2550_EP_IN_BUF_SIZE);
transfer->ssm = ssm;
fpi_usb_transfer_submit(transfer, BULK_TIMEOUT, NULL,
calibrate_read_data_cb, NULL);
fpi_usb_transfer_unref(transfer);
}
break;
}
case CALIBRATE:
{
FpiUsbTransfer *transfer = fpi_usb_transfer_new (dev);
fpi_usb_transfer_fill_bulk_full (transfer, EP_OUT,
calibrate_reqs,
sizeof (calibrate_reqs), NULL);
transfer->ssm = ssm;
transfer->short_is_error = TRUE;
fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
init_reqs_cb, NULL);
fpi_usb_transfer_unref (transfer);
}
break;
case READ_CALIB_TABLE:
{
FpiUsbTransfer *transfer = fpi_usb_transfer_new (dev);
fpi_usb_transfer_fill_bulk (transfer, EP_IN, AES2550_EP_IN_BUF_SIZE);
transfer->ssm = ssm;
fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
calibrate_read_data_cb, NULL);
fpi_usb_transfer_unref (transfer);
}
break;
}
}
static void activate_sm_complete(FpiSsm *ssm, FpDevice *_dev,
void *user_data, GError *error)
static void
activate_sm_complete (FpiSsm *ssm, FpDevice *_dev,
void *user_data, GError *error)
{
FpImageDevice *dev = user_data;
FpImageDevice *dev = user_data;
fpi_image_device_activate_complete(dev, error);
fpi_image_device_activate_complete (dev, error);
if (!error)
start_finger_detection(dev);
fpi_ssm_free(ssm);
if (!error)
start_finger_detection (dev);
fpi_ssm_free (ssm);
}
static void dev_activate(FpImageDevice *dev)
static void
dev_activate (FpImageDevice *dev)
{
FpiSsm *ssm = fpi_ssm_new(FP_DEVICE(dev), activate_run_state,
ACTIVATE_NUM_STATES, dev);
fpi_ssm_start(ssm, activate_sm_complete);
FpiSsm *ssm = fpi_ssm_new (FP_DEVICE (dev), activate_run_state,
ACTIVATE_NUM_STATES, dev);
fpi_ssm_start (ssm, activate_sm_complete);
}
static void dev_deactivate(FpImageDevice *dev)
static void
dev_deactivate (FpImageDevice *dev)
{
FpiDeviceAes2550 *self = FPI_DEVICE_AES2550(dev);
FpiDeviceAes2550 *self = FPI_DEVICE_AES2550 (dev);
self->deactivating = TRUE;
self->deactivating = TRUE;
}
static void complete_deactivation(FpImageDevice *dev)
static void
complete_deactivation (FpImageDevice *dev)
{
FpiDeviceAes2550 *self = FPI_DEVICE_AES2550(dev);
G_DEBUG_HERE();
FpiDeviceAes2550 *self = FPI_DEVICE_AES2550 (dev);
self->deactivating = FALSE;
g_slist_free(self->strips);
self->strips = NULL;
self->strips_len = 0;
fpi_image_device_deactivate_complete(dev, NULL);
G_DEBUG_HERE ();
self->deactivating = FALSE;
g_slist_free (self->strips);
self->strips = NULL;
self->strips_len = 0;
fpi_image_device_deactivate_complete (dev, NULL);
}
static void dev_init(FpImageDevice *dev)
static void
dev_init (FpImageDevice *dev)
{
GError *error = NULL;
/* TODO check that device has endpoints we're using */
GError *error = NULL;
g_usb_device_claim_interface(fpi_device_get_usb_device(FP_DEVICE(dev)), 0, 0, &error);
/* TODO check that device has endpoints we're using */
fpi_image_device_open_complete(dev, error);
g_usb_device_claim_interface (fpi_device_get_usb_device (FP_DEVICE (dev)), 0, 0, &error);
fpi_image_device_open_complete (dev, error);
}
static void dev_deinit(FpImageDevice *dev)
static void
dev_deinit (FpImageDevice *dev)
{
GError *error = NULL;
GError *error = NULL;
g_usb_device_release_interface(fpi_device_get_usb_device(FP_DEVICE(dev)),
0, 0, &error);
fpi_image_device_close_complete(dev, error);
g_usb_device_release_interface (fpi_device_get_usb_device (FP_DEVICE (dev)),
0, 0, &error);
fpi_image_device_close_complete (dev, error);
}
static const FpIdEntry id_table [ ] = {
{ .vid = 0x08ff, .pid = 0x2550,
}, /* AES2550 */
{ .vid = 0x08ff, .pid = 0x2810,
}, /* AES2810 */
{ .vid = 0, .pid = 0, .driver_data = 0 },
static const FpIdEntry id_table[] = {
{ .vid = 0x08ff, .pid = 0x2550, },/* AES2550 */
{ .vid = 0x08ff, .pid = 0x2810, },/* AES2810 */
{ .vid = 0, .pid = 0, .driver_data = 0 },
};
static void fpi_device_aes2550_init(FpiDeviceAes2550 *self) {
static void
fpi_device_aes2550_init (FpiDeviceAes2550 *self)
{
}
static void fpi_device_aes2550_class_init(FpiDeviceAes2550Class *klass) {
FpDeviceClass *dev_class = FP_DEVICE_CLASS(klass);
FpImageDeviceClass *img_class = FP_IMAGE_DEVICE_CLASS(klass);
static void
fpi_device_aes2550_class_init (FpiDeviceAes2550Class *klass)
{
FpDeviceClass *dev_class = FP_DEVICE_CLASS (klass);
FpImageDeviceClass *img_class = FP_IMAGE_DEVICE_CLASS (klass);
dev_class->id = "aes2550";
dev_class->full_name = "AuthenTec AES2550/AES2810";
dev_class->type = FP_DEVICE_TYPE_USB;
dev_class->id_table = id_table;
dev_class->scan_type = FP_SCAN_TYPE_SWIPE;
dev_class->id = "aes2550";
dev_class->full_name = "AuthenTec AES2550/AES2810";
dev_class->type = FP_DEVICE_TYPE_USB;
dev_class->id_table = id_table;
dev_class->scan_type = FP_SCAN_TYPE_SWIPE;
img_class->img_open = dev_init;
img_class->img_close = dev_deinit;
img_class->activate = dev_activate;
img_class->deactivate = dev_deactivate;
img_class->img_open = dev_init;
img_class->img_close = dev_deinit;
img_class->activate = dev_activate;
img_class->deactivate = dev_deactivate;
img_class->img_width = FRAME_WIDTH + FRAME_WIDTH / 2;
img_class->img_height = -1;
img_class->img_width = FRAME_WIDTH + FRAME_WIDTH / 2;
img_class->img_height = -1;
}

View file

@ -22,93 +22,93 @@
/* Registers bits */
#define AES2550_REG80_MASTER_RESET (1 << 0)
#define AES2550_REG80_FORCE_FINGER_PRESENT (1 << 1)
#define AES2550_REG80_LPO_START (1 << 2)
#define AES2550_REG80_HGC_ENABLE (1 << 3)
#define AES2550_REG80_SENSOR_MODE_OFS (4)
#define AES2550_REG80_AUTO_RESTART_FD (1 << 6)
#define AES2550_REG80_EXT_REG_ENABLE (1 << 7)
#define AES2550_REG80_MASTER_RESET (1 << 0)
#define AES2550_REG80_FORCE_FINGER_PRESENT (1 << 1)
#define AES2550_REG80_LPO_START (1 << 2)
#define AES2550_REG80_HGC_ENABLE (1 << 3)
#define AES2550_REG80_SENSOR_MODE_OFS (4)
#define AES2550_REG80_AUTO_RESTART_FD (1 << 6)
#define AES2550_REG80_EXT_REG_ENABLE (1 << 7)
#define AES2550_REG81_CONT_SCAN (1 << 0)
#define AES2550_REG81_READ_REG (1 << 1)
#define AES2550_REG81_NSHOT (1 << 2)
#define AES2550_REG81_RUN_FD (1 << 3)
#define AES2550_REG81_READ_ID (1 << 4)
#define AES2550_REG81_RUN_CAL (1 << 5)
#define AES2550_REG81_RUN_TIMER (1 << 6)
#define AES2550_REG81_RUN_BIST (1 << 7)
#define AES2550_REG81_CONT_SCAN (1 << 0)
#define AES2550_REG81_READ_REG (1 << 1)
#define AES2550_REG81_NSHOT (1 << 2)
#define AES2550_REG81_RUN_FD (1 << 3)
#define AES2550_REG81_READ_ID (1 << 4)
#define AES2550_REG81_RUN_CAL (1 << 5)
#define AES2550_REG81_RUN_TIMER (1 << 6)
#define AES2550_REG81_RUN_BIST (1 << 7)
#define AES2550_REG83_FINGER_PRESENT (1 << 7)
#define AES2550_REG83_FINGER_PRESENT (1 << 7)
#define AES2550_REG85_FLUSH_PER_FRAME (1 << 7)
#define AES2550_REG85_FLUSH_PER_FRAME (1 << 7)
#define AES2550_REG8F_EDATA_DISABLE (1 << 1)
#define AES2550_REG8F_AUTH_DISABLE (1 << 2)
#define AES2550_REG8F_EHISTO_DISABLE (1 << 3)
#define AES2550_REG8F_HISTO64 (1 << 4)
#define AES2550_REG8F_SINGLE_REG_ENABLE (1 << 6)
#define AES2550_REG8F_EDATA_DISABLE (1 << 1)
#define AES2550_REG8F_AUTH_DISABLE (1 << 2)
#define AES2550_REG8F_EHISTO_DISABLE (1 << 3)
#define AES2550_REG8F_HISTO64 (1 << 4)
#define AES2550_REG8F_SINGLE_REG_ENABLE (1 << 6)
#define AES2550_REG95_COL_SCANNED_OFS (0)
#define AES2550_REG95_EPIX_AVG_OFS (4)
#define AES2550_REG95_COL_SCANNED_OFS (0)
#define AES2550_REG95_EPIX_AVG_OFS (4)
#define AES2550_REGA8_DIG_BIT_DATA_OFS (0)
#define AES2550_REGA8_DIG_BIT_EN (1 << 4)
#define AES2550_REGA8_FIXED_BIT_DATA (1 << 5)
#define AES2550_REGA8_INVERT_BIT_DATA (1 << 6)
#define AES2550_REGA8_DIG_BIT_DATA_OFS (0)
#define AES2550_REGA8_DIG_BIT_EN (1 << 4)
#define AES2550_REGA8_FIXED_BIT_DATA (1 << 5)
#define AES2550_REGA8_INVERT_BIT_DATA (1 << 6)
#define AES2550_REGAD_LPFD_AVG_OFS (0)
#define AES2550_REGAD_DETECT_FGROFF (1 << 4)
#define AES2550_REGAD_ADVRANGE_2V (1 << 6)
#define AES2550_REGAD_LPFD_AVG_OFS (0)
#define AES2550_REGAD_DETECT_FGROFF (1 << 4)
#define AES2550_REGAD_ADVRANGE_2V (1 << 6)
#define AES2550_REGB1_ATE_CONT_IMAGE (1 << 1)
#define AES2550_REGB1_ANALOG_RESET (1 << 2)
#define AES2550_REGB1_ANALOG_PD (1 << 3)
#define AES2550_REGB1_TEST_EMBD_WORD (1 << 4)
#define AES2550_REGB1_ORIG_EMBD_WORD (1 << 5)
#define AES2550_REGB1_RESET_UHSM (1 << 6)
#define AES2550_REGB1_RESET_SENSOR (1 << 7)
#define AES2550_REGB1_ATE_CONT_IMAGE (1 << 1)
#define AES2550_REGB1_ANALOG_RESET (1 << 2)
#define AES2550_REGB1_ANALOG_PD (1 << 3)
#define AES2550_REGB1_TEST_EMBD_WORD (1 << 4)
#define AES2550_REGB1_ORIG_EMBD_WORD (1 << 5)
#define AES2550_REGB1_RESET_UHSM (1 << 6)
#define AES2550_REGB1_RESET_SENSOR (1 << 7)
#define AES2550_REGBD_LPO_IN_15_8_OFS (0)
#define AES2550_REGBE_LPO_IN_7_0_OFS (0)
#define AES2550_REGBD_LPO_IN_15_8_OFS (0)
#define AES2550_REGBE_LPO_IN_7_0_OFS (0)
#define AES2550_REGBF_RSR_LEVEL_DISABLED (0 << 0)
#define AES2550_REGBF_RSR_LEVEL_LEADING_RSR (1 << 0)
#define AES2550_REGBF_RSR_LEVEL_SIMPLE_RSR (2 << 0)
#define AES2550_REGBF_RSR_LEVEL_SUPER_RSR (3 << 0)
#define AES2550_REGBF_RSR_DIR_DOWN_MOTION (0 << 2)
#define AES2550_REGBF_RSR_DIR_UP_MOTION (1 << 2)
#define AES2550_REGBF_RSR_DIR_UPDOWN_MOTION (2 << 2)
#define AES2550_REGBF_NOISE_FLOOR_MODE (1 << 4)
#define AES2550_REGBF_QUADRATURE_MODE (1 << 5)
#define AES2550_REGBF_RSR_LEVEL_DISABLED (0 << 0)
#define AES2550_REGBF_RSR_LEVEL_LEADING_RSR (1 << 0)
#define AES2550_REGBF_RSR_LEVEL_SIMPLE_RSR (2 << 0)
#define AES2550_REGBF_RSR_LEVEL_SUPER_RSR (3 << 0)
#define AES2550_REGBF_RSR_DIR_DOWN_MOTION (0 << 2)
#define AES2550_REGBF_RSR_DIR_UP_MOTION (1 << 2)
#define AES2550_REGBF_RSR_DIR_UPDOWN_MOTION (2 << 2)
#define AES2550_REGBF_NOISE_FLOOR_MODE (1 << 4)
#define AES2550_REGBF_QUADRATURE_MODE (1 << 5)
#define AES2550_REGCF_INTERFERENCE_CHK_EN (1 << 0)
#define AES2550_REGCF_INTERFERENCE_AVG_EN (1 << 1)
#define AES2550_REGCF_INTERFERENCE_AVG_OFFS (4)
#define AES2550_REGCF_INTERFERENCE_CHK_EN (1 << 0)
#define AES2550_REGCF_INTERFERENCE_AVG_EN (1 << 1)
#define AES2550_REGCF_INTERFERENCE_AVG_OFFS (4)
#define AES2550_REGDC_BP_NUM_REF_SWEEP_OFS (0)
#define AES2550_REGDC_DEBUG_CTRL2_OFS (3)
#define AES2550_REGDC_BP_NUM_REF_SWEEP_OFS (0)
#define AES2550_REGDC_DEBUG_CTRL2_OFS (3)
#define AES2550_REGDD_DEBUG_CTRL1_OFS (0)
#define AES2550_REGDD_DEBUG_CTRL1_OFS (0)
/* Commands */
enum aes2550_cmds {
AES2550_CMD_SET_IDLE_MODE = 0x00,
AES2550_CMD_RUN_FD = 0x01,
AES2550_CMD_GET_ENROLL_IMG = 0x02,
AES2550_CMD_CALIBRATE = 0x06,
AES2550_CMD_READ_CALIBRATION_DATA = 0x10,
AES2550_CMD_HEARTBEAT = 0x70,
AES2550_CMD_SET_IDLE_MODE = 0x00,
AES2550_CMD_RUN_FD = 0x01,
AES2550_CMD_GET_ENROLL_IMG = 0x02,
AES2550_CMD_CALIBRATE = 0x06,
AES2550_CMD_READ_CALIBRATION_DATA = 0x10,
AES2550_CMD_HEARTBEAT = 0x70,
};
/* Messages */
#define AES2550_STRIP_SIZE (0x31e + 3)
#define AES2550_HEARTBEAT_SIZE (4 + 3)
#define AES2550_EDATA_MAGIC 0xe0
#define AES2550_HEARTBEAT_MAGIC 0xdb
#define AES2550_STRIP_SIZE (0x31e + 3)
#define AES2550_HEARTBEAT_SIZE (4 + 3)
#define AES2550_EDATA_MAGIC 0xe0
#define AES2550_HEARTBEAT_MAGIC 0xdb
#define AES2550_EP_IN_BUF_SIZE 8192
#define AES2550_EP_IN_BUF_SIZE 8192
#endif

View file

@ -25,68 +25,73 @@
#include "aes2660.h"
#define FRAME_WIDTH 192
#define IMAGE_WIDTH (FRAME_WIDTH + (FRAME_WIDTH / 2))
#define IMAGE_WIDTH (FRAME_WIDTH + (FRAME_WIDTH / 2))
struct _FpiDeviceAes2660 {
FpiDeviceAesX660 parent;
struct _FpiDeviceAes2660
{
FpiDeviceAesX660 parent;
};
G_DECLARE_FINAL_TYPE(FpiDeviceAes2660, fpi_device_aes2660, FPI,
DEVICE_AES2660, FpiDeviceAesX660);
G_DEFINE_TYPE(FpiDeviceAes2660, fpi_device_aes2660, FPI_TYPE_DEVICE_AES_X660);
G_DECLARE_FINAL_TYPE (FpiDeviceAes2660, fpi_device_aes2660, FPI,
DEVICE_AES2660, FpiDeviceAesX660);
G_DEFINE_TYPE (FpiDeviceAes2660, fpi_device_aes2660, FPI_TYPE_DEVICE_AES_X660);
static struct fpi_frame_asmbl_ctx assembling_ctx = {
.frame_width = FRAME_WIDTH,
.frame_height = AESX660_FRAME_HEIGHT,
.image_width = IMAGE_WIDTH,
.get_pixel = aes_get_pixel,
.frame_width = FRAME_WIDTH,
.frame_height = AESX660_FRAME_HEIGHT,
.image_width = IMAGE_WIDTH,
.get_pixel = aes_get_pixel,
};
static const FpIdEntry id_table [ ] = {
{ .vid = 0x08ff, .pid = 0x2660, },
{ .vid = 0x08ff, .pid = 0x2680, },
{ .vid = 0x08ff, .pid = 0x2681, },
{ .vid = 0x08ff, .pid = 0x2682, },
{ .vid = 0x08ff, .pid = 0x2683, },
{ .vid = 0x08ff, .pid = 0x2684, },
{ .vid = 0x08ff, .pid = 0x2685, },
{ .vid = 0x08ff, .pid = 0x2686, },
{ .vid = 0x08ff, .pid = 0x2687, },
{ .vid = 0x08ff, .pid = 0x2688, },
{ .vid = 0x08ff, .pid = 0x2689, },
{ .vid = 0x08ff, .pid = 0x268a, },
{ .vid = 0x08ff, .pid = 0x268b, },
{ .vid = 0x08ff, .pid = 0x268c, },
{ .vid = 0x08ff, .pid = 0x268d, },
{ .vid = 0x08ff, .pid = 0x268e, },
{ .vid = 0x08ff, .pid = 0x268f, },
{ .vid = 0x08ff, .pid = 0x2691, },
{ .vid = 0, .pid = 0, .driver_data = 0 },
static const FpIdEntry id_table[] = {
{ .vid = 0x08ff, .pid = 0x2660, },
{ .vid = 0x08ff, .pid = 0x2680, },
{ .vid = 0x08ff, .pid = 0x2681, },
{ .vid = 0x08ff, .pid = 0x2682, },
{ .vid = 0x08ff, .pid = 0x2683, },
{ .vid = 0x08ff, .pid = 0x2684, },
{ .vid = 0x08ff, .pid = 0x2685, },
{ .vid = 0x08ff, .pid = 0x2686, },
{ .vid = 0x08ff, .pid = 0x2687, },
{ .vid = 0x08ff, .pid = 0x2688, },
{ .vid = 0x08ff, .pid = 0x2689, },
{ .vid = 0x08ff, .pid = 0x268a, },
{ .vid = 0x08ff, .pid = 0x268b, },
{ .vid = 0x08ff, .pid = 0x268c, },
{ .vid = 0x08ff, .pid = 0x268d, },
{ .vid = 0x08ff, .pid = 0x268e, },
{ .vid = 0x08ff, .pid = 0x268f, },
{ .vid = 0x08ff, .pid = 0x2691, },
{ .vid = 0, .pid = 0, .driver_data = 0 },
};
static void fpi_device_aes2660_init(FpiDeviceAes2660 *self) {
static void
fpi_device_aes2660_init (FpiDeviceAes2660 *self)
{
}
static void fpi_device_aes2660_class_init(FpiDeviceAes2660Class *klass) {
FpDeviceClass *dev_class = FP_DEVICE_CLASS(klass);
FpImageDeviceClass *img_class = FP_IMAGE_DEVICE_CLASS(klass);
FpiDeviceAesX660Class *aes_class = FPI_DEVICE_AES_X660_CLASS (klass);
static void
fpi_device_aes2660_class_init (FpiDeviceAes2660Class *klass)
{
FpDeviceClass *dev_class = FP_DEVICE_CLASS (klass);
FpImageDeviceClass *img_class = FP_IMAGE_DEVICE_CLASS (klass);
FpiDeviceAesX660Class *aes_class = FPI_DEVICE_AES_X660_CLASS (klass);
dev_class->id = "aes2660";
dev_class->full_name = "AuthenTec AES2660";
dev_class->type = FP_DEVICE_TYPE_USB;
dev_class->id_table = id_table;
dev_class->scan_type = FP_SCAN_TYPE_SWIPE;
dev_class->id = "aes2660";
dev_class->full_name = "AuthenTec AES2660";
dev_class->type = FP_DEVICE_TYPE_USB;
dev_class->id_table = id_table;
dev_class->scan_type = FP_SCAN_TYPE_SWIPE;
img_class->bz3_threshold = 20;
img_class->bz3_threshold = 20;
img_class->img_width = FRAME_WIDTH + FRAME_WIDTH / 2;
img_class->img_height = -1;
img_class->img_width = FRAME_WIDTH + FRAME_WIDTH / 2;
img_class->img_height = -1;
aes_class->init_seqs[0] = aes2660_init_1;
aes_class->init_seqs_len[0] = G_N_ELEMENTS(aes2660_init_1);
aes_class->init_seqs[1] = aes2660_init_2;
aes_class->init_seqs_len[1] = G_N_ELEMENTS(aes2660_init_2);
aes_class->start_imaging_cmd = (unsigned char *)aes2660_start_imaging_cmd;
aes_class->start_imaging_cmd_len = sizeof(aes2660_start_imaging_cmd);
aes_class->assembling_ctx = &assembling_ctx;
aes_class->init_seqs[0] = aes2660_init_1;
aes_class->init_seqs_len[0] = G_N_ELEMENTS (aes2660_init_1);
aes_class->init_seqs[1] = aes2660_init_2;
aes_class->init_seqs_len[1] = G_N_ELEMENTS (aes2660_init_2);
aes_class->start_imaging_cmd = (unsigned char *) aes2660_start_imaging_cmd;
aes_class->start_imaging_cmd_len = sizeof (aes2660_start_imaging_cmd);
aes_class->assembling_ctx = &assembling_ctx;
}

File diff suppressed because it is too large Load diff

View file

@ -31,123 +31,128 @@
#include "aes3k.h"
#define DATA_BUFLEN 0x2089
#define DATA_BUFLEN 0x2089
/* image size = FRAME_WIDTH x FRAME_WIDTH */
#define FRAME_WIDTH 128
#define FRAME_SIZE (FRAME_WIDTH * AES3K_FRAME_HEIGHT / 2)
#define FRAME_NUMBER (FRAME_WIDTH / AES3K_FRAME_HEIGHT)
#define ENLARGE_FACTOR 2
#define FRAME_WIDTH 128
#define FRAME_SIZE (FRAME_WIDTH * AES3K_FRAME_HEIGHT / 2)
#define FRAME_NUMBER (FRAME_WIDTH / AES3K_FRAME_HEIGHT)
#define ENLARGE_FACTOR 2
static struct aes_regwrite init_reqs[] = {
/* master reset */
{ 0x80, 0x01 },
{ 0, 0 },
{ 0x80, 0x00 },
{ 0, 0 },
/* master reset */
{ 0x80, 0x01 },
{ 0, 0 },
{ 0x80, 0x00 },
{ 0, 0 },
{ 0x81, 0x00 },
{ 0x80, 0x00 },
{ 0, 0 },
{ 0x81, 0x00 },
{ 0x80, 0x00 },
{ 0, 0 },
/* scan reset */
{ 0x80, 0x02 },
{ 0, 0 },
{ 0x80, 0x00 },
{ 0, 0 },
/* scan reset */
{ 0x80, 0x02 },
{ 0, 0 },
{ 0x80, 0x00 },
{ 0, 0 },
/* disable register buffering */
{ 0x80, 0x04 },
{ 0, 0 },
{ 0x80, 0x00 },
{ 0, 0 },
/* disable register buffering */
{ 0x80, 0x04 },
{ 0, 0 },
{ 0x80, 0x00 },
{ 0, 0 },
{ 0x81, 0x00 },
{ 0, 0 },
/* windows driver reads registers now (81 02) */
{ 0x80, 0x00 },
{ 0x81, 0x00 },
{ 0x81, 0x00 },
{ 0, 0 },
/* windows driver reads registers now (81 02) */
{ 0x80, 0x00 },
{ 0x81, 0x00 },
/* set excitation bias current: 2mhz drive ring frequency,
* 4V drive ring voltage, 16.5mA excitation bias */
{ 0x82, 0x04 },
/* set excitation bias current: 2mhz drive ring frequency,
* 4V drive ring voltage, 16.5mA excitation bias */
{ 0x82, 0x04 },
/* continuously sample drive ring for finger detection,
* 62.50ms debounce delay */
{ 0x83, 0x13 },
/* continuously sample drive ring for finger detection,
* 62.50ms debounce delay */
{ 0x83, 0x13 },
{ 0x84, 0x07 }, /* set calibration resistance to 12 kiloohms */
{ 0x85, 0x3d }, /* set calibration capacitance */
{ 0x86, 0x03 }, /* detect drive voltage */
{ 0x87, 0x01 }, /* set detection frequency to 125khz */
{ 0x88, 0x02 }, /* set column scan period */
{ 0x89, 0x02 }, /* set measure drive */
{ 0x8a, 0x33 }, /* set measure frequency and sense amplifier bias */
{ 0x8b, 0x33 }, /* set matrix pattern */
{ 0x8c, 0x0f }, /* set demodulation phase 1 */
{ 0x8d, 0x04 }, /* set demodulation phase 2 */
{ 0x8e, 0x23 }, /* set sensor gain */
{ 0x8f, 0x07 }, /* set image parameters */
{ 0x90, 0x00 }, /* carrier offset null */
{ 0x91, 0x1c }, /* set A/D reference high */
{ 0x92, 0x08 }, /* set A/D reference low */
{ 0x93, 0x00 }, /* set start row to 0 */
{ 0x94, 0x07 }, /* set end row */
{ 0x95, 0x00 }, /* set start column to 0 */
{ 0x96, 0x1f }, /* set end column */
{ 0x97, 0x04 }, /* data format and thresholds */
{ 0x98, 0x28 }, /* image data control */
{ 0x99, 0x00 }, /* disable general purpose outputs */
{ 0x9a, 0x0b }, /* set initial scan state */
{ 0x9b, 0x00 }, /* clear challenge word bits */
{ 0x9c, 0x00 }, /* clear challenge word bits */
{ 0x9d, 0x09 }, /* set some challenge word bits */
{ 0x9e, 0x53 }, /* clear challenge word bits */
{ 0x9f, 0x6b }, /* set some challenge word bits */
{ 0, 0 },
{ 0x84, 0x07 }, /* set calibration resistance to 12 kiloohms */
{ 0x85, 0x3d }, /* set calibration capacitance */
{ 0x86, 0x03 }, /* detect drive voltage */
{ 0x87, 0x01 }, /* set detection frequency to 125khz */
{ 0x88, 0x02 }, /* set column scan period */
{ 0x89, 0x02 }, /* set measure drive */
{ 0x8a, 0x33 }, /* set measure frequency and sense amplifier bias */
{ 0x8b, 0x33 }, /* set matrix pattern */
{ 0x8c, 0x0f }, /* set demodulation phase 1 */
{ 0x8d, 0x04 }, /* set demodulation phase 2 */
{ 0x8e, 0x23 }, /* set sensor gain */
{ 0x8f, 0x07 }, /* set image parameters */
{ 0x90, 0x00 }, /* carrier offset null */
{ 0x91, 0x1c }, /* set A/D reference high */
{ 0x92, 0x08 }, /* set A/D reference low */
{ 0x93, 0x00 }, /* set start row to 0 */
{ 0x94, 0x07 }, /* set end row */
{ 0x95, 0x00 }, /* set start column to 0 */
{ 0x96, 0x1f }, /* set end column */
{ 0x97, 0x04 }, /* data format and thresholds */
{ 0x98, 0x28 }, /* image data control */
{ 0x99, 0x00 }, /* disable general purpose outputs */
{ 0x9a, 0x0b }, /* set initial scan state */
{ 0x9b, 0x00 }, /* clear challenge word bits */
{ 0x9c, 0x00 }, /* clear challenge word bits */
{ 0x9d, 0x09 }, /* set some challenge word bits */
{ 0x9e, 0x53 }, /* clear challenge word bits */
{ 0x9f, 0x6b }, /* set some challenge word bits */
{ 0, 0 },
{ 0x80, 0x00 },
{ 0x81, 0x00 },
{ 0, 0 },
{ 0x81, 0x04 },
{ 0, 0 },
{ 0x81, 0x00 },
{ 0x80, 0x00 },
{ 0x81, 0x00 },
{ 0, 0 },
{ 0x81, 0x04 },
{ 0, 0 },
{ 0x81, 0x00 },
};
struct _FpiDeviceAes3500 {
FpiDeviceAes3k parent;
struct _FpiDeviceAes3500
{
FpiDeviceAes3k parent;
};
G_DECLARE_FINAL_TYPE(FpiDeviceAes3500, fpi_device_aes3500, FPI,
DEVICE_AES3500, FpiDeviceAes3k);
G_DEFINE_TYPE(FpiDeviceAes3500, fpi_device_aes3500, FPI_TYPE_DEVICE_AES3K);
G_DECLARE_FINAL_TYPE (FpiDeviceAes3500, fpi_device_aes3500, FPI,
DEVICE_AES3500, FpiDeviceAes3k);
G_DEFINE_TYPE (FpiDeviceAes3500, fpi_device_aes3500, FPI_TYPE_DEVICE_AES3K);
static const FpIdEntry id_table [ ] = {
{ .vid = 0x08ff, .pid = 0x5731 },
{ .vid = 0, .pid = 0, .driver_data = 0 },
static const FpIdEntry id_table[] = {
{ .vid = 0x08ff, .pid = 0x5731 },
{ .vid = 0, .pid = 0, .driver_data = 0 },
};
static void fpi_device_aes3500_init(FpiDeviceAes3500 *self) {
static void
fpi_device_aes3500_init (FpiDeviceAes3500 *self)
{
}
static void fpi_device_aes3500_class_init(FpiDeviceAes3500Class *klass) {
FpDeviceClass *dev_class = FP_DEVICE_CLASS(klass);
FpImageDeviceClass *img_class = FP_IMAGE_DEVICE_CLASS(klass);
FpiDeviceAes3kClass *aes_class = FPI_DEVICE_AES3K_CLASS (klass);
static void
fpi_device_aes3500_class_init (FpiDeviceAes3500Class *klass)
{
FpDeviceClass *dev_class = FP_DEVICE_CLASS (klass);
FpImageDeviceClass *img_class = FP_IMAGE_DEVICE_CLASS (klass);
FpiDeviceAes3kClass *aes_class = FPI_DEVICE_AES3K_CLASS (klass);
dev_class->id = "aes3500";
dev_class->full_name = "AuthenTec AES3500";
dev_class->id_table = id_table;
dev_class->id = "aes3500";
dev_class->full_name = "AuthenTec AES3500";
dev_class->id_table = id_table;
img_class->img_height = FRAME_WIDTH * ENLARGE_FACTOR;
img_class->img_width = FRAME_WIDTH * ENLARGE_FACTOR;
img_class->img_height = FRAME_WIDTH * ENLARGE_FACTOR;
img_class->img_width = FRAME_WIDTH * ENLARGE_FACTOR;
aes_class->data_buflen = DATA_BUFLEN;
aes_class->frame_width = FRAME_WIDTH;
aes_class->frame_size = FRAME_SIZE;
aes_class->frame_number = FRAME_NUMBER;
aes_class->enlarge_factor = ENLARGE_FACTOR;
aes_class->init_reqs = init_reqs;
aes_class->init_reqs_len = G_N_ELEMENTS(init_reqs);
aes_class->data_buflen = DATA_BUFLEN;
aes_class->frame_width = FRAME_WIDTH;
aes_class->frame_size = FRAME_SIZE;
aes_class->frame_number = FRAME_NUMBER;
aes_class->enlarge_factor = ENLARGE_FACTOR;
aes_class->init_reqs = init_reqs;
aes_class->init_reqs_len = G_N_ELEMENTS (init_reqs);
}

View file

@ -40,169 +40,188 @@
#include "aeslib.h"
#include "aes3k.h"
typedef struct {
FpiUsbTransfer *img_trf;
gboolean deactivating;
typedef struct
{
FpiUsbTransfer *img_trf;
gboolean deactivating;
} FpiDeviceAes3kPrivate;
#define CTRL_TIMEOUT 1000
#define EP_IN (1 | FPI_USB_ENDPOINT_IN)
#define EP_OUT (2 | FPI_USB_ENDPOINT_OUT)
#define CTRL_TIMEOUT 1000
#define EP_IN (1 | FPI_USB_ENDPOINT_IN)
#define EP_OUT (2 | FPI_USB_ENDPOINT_OUT)
static void do_capture(FpImageDevice *dev);
static void do_capture (FpImageDevice *dev);
G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE(FpiDeviceAes3k, fpi_device_aes3k, FP_TYPE_IMAGE_DEVICE);
G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (FpiDeviceAes3k, fpi_device_aes3k, FP_TYPE_IMAGE_DEVICE);
static void aes3k_assemble_image(unsigned char *input, size_t width, size_t height,
unsigned char *output)
static void
aes3k_assemble_image (unsigned char *input, size_t width, size_t height,
unsigned char *output)
{
size_t row, column;
size_t row, column;
for (column = 0; column < width; column++) {
for (row = 0; row < height; row += 2) {
output[width * row + column] = (*input & 0x0f) * 17;
output[width * (row + 1) + column] = ((*input & 0xf0) >> 4) * 17;
input++;
}
}
for (column = 0; column < width; column++)
{
for (row = 0; row < height; row += 2)
{
output[width * row + column] = (*input & 0x0f) * 17;
output[width * (row + 1) + column] = ((*input & 0xf0) >> 4) * 17;
input++;
}
}
}
static void img_cb(FpiUsbTransfer *transfer, FpDevice *device,
gpointer user_data, GError *error)
static void
img_cb (FpiUsbTransfer *transfer, FpDevice *device,
gpointer user_data, GError *error)
{
FpImageDevice *dev = FP_IMAGE_DEVICE (device);
FpiDeviceAes3k *self = FPI_DEVICE_AES3K (device);
FpiDeviceAes3kPrivate *priv = fpi_device_aes3k_get_instance_private (self);
FpiDeviceAes3kClass *cls = FPI_DEVICE_AES3K_GET_CLASS (self);
unsigned char *ptr = transfer->buffer;
FpImage *tmp;
FpImage *img;
int i;
FpImageDevice *dev = FP_IMAGE_DEVICE (device);
FpiDeviceAes3k *self = FPI_DEVICE_AES3K (device);
FpiDeviceAes3kPrivate *priv = fpi_device_aes3k_get_instance_private (self);
FpiDeviceAes3kClass *cls = FPI_DEVICE_AES3K_GET_CLASS (self);
unsigned char *ptr = transfer->buffer;
FpImage *tmp;
FpImage *img;
int i;
priv->img_trf = NULL;
priv->img_trf = NULL;
if (error) {
if (g_error_matches (error,
G_IO_ERROR,
G_IO_ERROR_CANCELLED)) {
/* Deactivation was completed. */
g_error_free (error);
if (priv->deactivating)
fpi_image_device_deactivate_complete(dev, NULL);
return;
}
if (error)
{
if (g_error_matches (error,
G_IO_ERROR,
G_IO_ERROR_CANCELLED))
{
/* Deactivation was completed. */
g_error_free (error);
if (priv->deactivating)
fpi_image_device_deactivate_complete (dev, NULL);
return;
}
fpi_image_device_session_error (dev, error);
}
fpi_image_device_session_error (dev, error);
}
fpi_image_device_report_finger_status(dev, TRUE);
fpi_image_device_report_finger_status (dev, TRUE);
tmp = fp_image_new(cls->frame_width, cls->frame_width);
tmp->width = cls->frame_width;
tmp->height = cls->frame_width;
tmp->flags = FPI_IMAGE_COLORS_INVERTED | FPI_IMAGE_V_FLIPPED | FPI_IMAGE_H_FLIPPED;
for (i = 0; i < cls->frame_number; i++) {
fp_dbg("frame header byte %02x", *ptr);
ptr++;
aes3k_assemble_image(ptr, cls->frame_width, AES3K_FRAME_HEIGHT, tmp->data + (i * cls->frame_width * AES3K_FRAME_HEIGHT));
ptr += cls->frame_size;
}
tmp = fp_image_new (cls->frame_width, cls->frame_width);
tmp->width = cls->frame_width;
tmp->height = cls->frame_width;
tmp->flags = FPI_IMAGE_COLORS_INVERTED | FPI_IMAGE_V_FLIPPED | FPI_IMAGE_H_FLIPPED;
for (i = 0; i < cls->frame_number; i++)
{
fp_dbg ("frame header byte %02x", *ptr);
ptr++;
aes3k_assemble_image (ptr, cls->frame_width, AES3K_FRAME_HEIGHT, tmp->data + (i * cls->frame_width * AES3K_FRAME_HEIGHT));
ptr += cls->frame_size;
}
/* FIXME: this is an ugly hack to make the image big enough for NBIS
* to process reliably */
img = fpi_image_resize(tmp, cls->enlarge_factor, cls->enlarge_factor);
g_object_unref (tmp);
fpi_image_device_image_captured(dev, img);
/* FIXME: this is an ugly hack to make the image big enough for NBIS
* to process reliably */
img = fpi_image_resize (tmp, cls->enlarge_factor, cls->enlarge_factor);
g_object_unref (tmp);
fpi_image_device_image_captured (dev, img);
/* FIXME: rather than assuming finger has gone, we should poll regs until
* it really has, then restart the capture */
fpi_image_device_report_finger_status(dev, FALSE);
/* FIXME: rather than assuming finger has gone, we should poll regs until
* it really has, then restart the capture */
fpi_image_device_report_finger_status (dev, FALSE);
do_capture(dev);
do_capture (dev);
}
static void do_capture(FpImageDevice *dev)
static void
do_capture (FpImageDevice *dev)
{
FpiDeviceAes3k *self = FPI_DEVICE_AES3K (dev);
FpiDeviceAes3kPrivate *priv = fpi_device_aes3k_get_instance_private (self);
FpiDeviceAes3kClass *cls = FPI_DEVICE_AES3K_GET_CLASS (self);
FpiDeviceAes3k *self = FPI_DEVICE_AES3K (dev);
FpiDeviceAes3kPrivate *priv = fpi_device_aes3k_get_instance_private (self);
FpiDeviceAes3kClass *cls = FPI_DEVICE_AES3K_GET_CLASS (self);
priv->img_trf = fpi_usb_transfer_new (FP_DEVICE (dev));
fpi_usb_transfer_fill_bulk(priv->img_trf, EP_IN, cls->data_buflen);
priv->img_trf->short_is_error = TRUE;
fpi_usb_transfer_submit(priv->img_trf, 0,
fpi_device_get_cancellable (FP_DEVICE (dev)),
img_cb, NULL);
fpi_usb_transfer_unref(priv->img_trf);
priv->img_trf = fpi_usb_transfer_new (FP_DEVICE (dev));
fpi_usb_transfer_fill_bulk (priv->img_trf, EP_IN, cls->data_buflen);
priv->img_trf->short_is_error = TRUE;
fpi_usb_transfer_submit (priv->img_trf, 0,
fpi_device_get_cancellable (FP_DEVICE (dev)),
img_cb, NULL);
fpi_usb_transfer_unref (priv->img_trf);
}
static void init_reqs_cb(FpImageDevice *dev, GError *result, void *user_data)
static void
init_reqs_cb (FpImageDevice *dev, GError *result, void *user_data)
{
fpi_image_device_activate_complete (dev, result);
if (!result)
do_capture(dev);
fpi_image_device_activate_complete (dev, result);
if (!result)
do_capture (dev);
}
static void aes3k_dev_activate(FpImageDevice *dev)
static void
aes3k_dev_activate (FpImageDevice *dev)
{
FpiDeviceAes3k *self = FPI_DEVICE_AES3K (dev);
FpiDeviceAes3kPrivate *priv = fpi_device_aes3k_get_instance_private (self);
FpiDeviceAes3kClass *cls = FPI_DEVICE_AES3K_GET_CLASS (self);
FpiDeviceAes3k *self = FPI_DEVICE_AES3K (dev);
FpiDeviceAes3kPrivate *priv = fpi_device_aes3k_get_instance_private (self);
FpiDeviceAes3kClass *cls = FPI_DEVICE_AES3K_GET_CLASS (self);
priv->deactivating = FALSE;
aes_write_regv(dev, cls->init_reqs, cls->init_reqs_len, init_reqs_cb, NULL);
priv->deactivating = FALSE;
aes_write_regv (dev, cls->init_reqs, cls->init_reqs_len, init_reqs_cb, NULL);
}
static void aes3k_dev_deactivate(FpImageDevice *dev)
static void
aes3k_dev_deactivate (FpImageDevice *dev)
{
FpiDeviceAes3k *self = FPI_DEVICE_AES3K (dev);
FpiDeviceAes3kPrivate *priv = fpi_device_aes3k_get_instance_private (self);
FpiDeviceAes3k *self = FPI_DEVICE_AES3K (dev);
FpiDeviceAes3kPrivate *priv = fpi_device_aes3k_get_instance_private (self);
priv->deactivating = TRUE;
if (priv->img_trf)
return;
fpi_image_device_deactivate_complete(dev, NULL);
priv->deactivating = TRUE;
if (priv->img_trf)
return;
fpi_image_device_deactivate_complete (dev, NULL);
}
static void fpi_device_aes3k_init(FpiDeviceAes3k *self) {
}
static void aes3k_dev_init(FpImageDevice *dev)
static void
fpi_device_aes3k_init (FpiDeviceAes3k *self)
{
GError *error = NULL;
if (!g_usb_device_claim_interface(fpi_device_get_usb_device(FP_DEVICE(dev)), 0, 0, &error)) {
fpi_image_device_open_complete(dev, error);
return;
}
fpi_image_device_open_complete(dev, NULL);
}
static void aes3k_dev_deinit(FpImageDevice *dev)
static void
aes3k_dev_init (FpImageDevice *dev)
{
GError *error = NULL;
GError *error = NULL;
g_usb_device_release_interface(fpi_device_get_usb_device(FP_DEVICE(dev)),
0, 0, &error);
fpi_image_device_close_complete(dev, error);
if (!g_usb_device_claim_interface (fpi_device_get_usb_device (FP_DEVICE (dev)), 0, 0, &error))
{
fpi_image_device_open_complete (dev, error);
return;
}
fpi_image_device_open_complete (dev, NULL);
}
static void
aes3k_dev_deinit (FpImageDevice *dev)
{
GError *error = NULL;
g_usb_device_release_interface (fpi_device_get_usb_device (FP_DEVICE (dev)),
0, 0, &error);
fpi_image_device_close_complete (dev, error);
}
static void fpi_device_aes3k_class_init(FpiDeviceAes3kClass *klass) {
FpDeviceClass *dev_class = FP_DEVICE_CLASS(klass);
FpImageDeviceClass *img_class = FP_IMAGE_DEVICE_CLASS(klass);
static void
fpi_device_aes3k_class_init (FpiDeviceAes3kClass *klass)
{
FpDeviceClass *dev_class = FP_DEVICE_CLASS (klass);
FpImageDeviceClass *img_class = FP_IMAGE_DEVICE_CLASS (klass);
dev_class->type = FP_DEVICE_TYPE_USB;
dev_class->scan_type = FP_SCAN_TYPE_PRESS;
dev_class->type = FP_DEVICE_TYPE_USB;
dev_class->scan_type = FP_SCAN_TYPE_PRESS;
img_class->img_open = aes3k_dev_init;
img_class->img_close = aes3k_dev_deinit;
img_class->activate = aes3k_dev_activate;
img_class->deactivate = aes3k_dev_deactivate;
img_class->img_open = aes3k_dev_init;
img_class->img_close = aes3k_dev_deinit;
img_class->activate = aes3k_dev_activate;
img_class->deactivate = aes3k_dev_deactivate;
/* Extremely low due to low image quality. */
img_class->bz3_threshold = 9;
/* Extremely low due to low image quality. */
img_class->bz3_threshold = 9;
/* Everything else is set by the subclasses. */
/* Everything else is set by the subclasses. */
}

View file

@ -38,22 +38,23 @@
#include "fpi-image-device.h"
#include "aeslib.h"
#define AES3K_FRAME_HEIGHT 16
#define AES3K_FRAME_HEIGHT 16
G_DECLARE_DERIVABLE_TYPE(FpiDeviceAes3k, fpi_device_aes3k, FPI,
DEVICE_AES3K, FpImageDevice)
G_DECLARE_DERIVABLE_TYPE (FpiDeviceAes3k, fpi_device_aes3k, FPI,
DEVICE_AES3K, FpImageDevice)
#define FPI_TYPE_DEVICE_AES3K (fpi_device_aes3k_get_type ())
struct _FpiDeviceAes3kClass {
FpImageDeviceClass parent;
struct _FpiDeviceAes3kClass
{
FpImageDeviceClass parent;
gsize frame_width; /* image size = frame_width x frame_width */
gsize frame_size; /* 4 bits/pixel: frame_width x AES3K_FRAME_HEIGHT / 2 */
gsize frame_number; /* number of frames */
gsize enlarge_factor;
gsize frame_width; /* image size = frame_width x frame_width */
gsize frame_size; /* 4 bits/pixel: frame_width x AES3K_FRAME_HEIGHT / 2 */
gsize frame_number; /* number of frames */
gsize enlarge_factor;
gsize data_buflen; /* buffer length of usb bulk transfer */
struct aes_regwrite *init_reqs; /* initial values sent to device */
gsize init_reqs_len;
gsize data_buflen; /* buffer length of usb bulk transfer */
struct aes_regwrite *init_reqs; /* initial values sent to device */
gsize init_reqs_len;
};

View file

@ -28,123 +28,128 @@
#include "aes3k.h"
#define DATA_BUFLEN 0x1259
#define DATA_BUFLEN 0x1259
/* image size = FRAME_WIDTH x FRAME_WIDTH */
#define FRAME_WIDTH 96
#define FRAME_SIZE (FRAME_WIDTH * AES3K_FRAME_HEIGHT / 2)
#define FRAME_NUMBER (FRAME_WIDTH / AES3K_FRAME_HEIGHT)
#define ENLARGE_FACTOR 3
#define FRAME_WIDTH 96
#define FRAME_SIZE (FRAME_WIDTH * AES3K_FRAME_HEIGHT / 2)
#define FRAME_NUMBER (FRAME_WIDTH / AES3K_FRAME_HEIGHT)
#define ENLARGE_FACTOR 3
static struct aes_regwrite init_reqs[] = {
/* master reset */
{ 0x80, 0x01 },
{ 0, 0 },
{ 0x80, 0x00 },
{ 0, 0 },
/* master reset */
{ 0x80, 0x01 },
{ 0, 0 },
{ 0x80, 0x00 },
{ 0, 0 },
{ 0x81, 0x00 },
{ 0x80, 0x00 },
{ 0, 0 },
{ 0x81, 0x00 },
{ 0x80, 0x00 },
{ 0, 0 },
/* scan reset */
{ 0x80, 0x02 },
{ 0, 0 },
{ 0x80, 0x00 },
{ 0, 0 },
/* scan reset */
{ 0x80, 0x02 },
{ 0, 0 },
{ 0x80, 0x00 },
{ 0, 0 },
/* disable register buffering */
{ 0x80, 0x04 },
{ 0, 0 },
{ 0x80, 0x00 },
{ 0, 0 },
/* disable register buffering */
{ 0x80, 0x04 },
{ 0, 0 },
{ 0x80, 0x00 },
{ 0, 0 },
{ 0x81, 0x00 },
{ 0, 0 },
/* windows driver reads registers now (81 02) */
{ 0x80, 0x00 },
{ 0x81, 0x00 },
{ 0x81, 0x00 },
{ 0, 0 },
/* windows driver reads registers now (81 02) */
{ 0x80, 0x00 },
{ 0x81, 0x00 },
/* set excitation bias current: 2mhz drive ring frequency,
* 4V drive ring voltage, 16.5mA excitation bias */
{ 0x82, 0x04 },
/* set excitation bias current: 2mhz drive ring frequency,
* 4V drive ring voltage, 16.5mA excitation bias */
{ 0x82, 0x04 },
/* continuously sample drive ring for finger detection,
* 62.50ms debounce delay */
{ 0x83, 0x13 },
/* continuously sample drive ring for finger detection,
* 62.50ms debounce delay */
{ 0x83, 0x13 },
{ 0x84, 0x07 }, /* set calibration resistance to 12 kiloohms */
{ 0x85, 0x3d }, /* set calibration capacitance */
{ 0x86, 0x03 }, /* detect drive voltage */
{ 0x87, 0x01 }, /* set detection frequency to 125khz */
{ 0x88, 0x02 }, /* set column scan period */
{ 0x89, 0x02 }, /* set measure drive */
{ 0x8a, 0x33 }, /* set measure frequency and sense amplifier bias */
{ 0x8b, 0x33 }, /* set matrix pattern */
{ 0x8c, 0x0f }, /* set demodulation phase 1 */
{ 0x8d, 0x04 }, /* set demodulation phase 2 */
{ 0x8e, 0x23 }, /* set sensor gain */
{ 0x8f, 0x07 }, /* set image parameters */
{ 0x90, 0x00 }, /* carrier offset null */
{ 0x91, 0x1c }, /* set A/D reference high */
{ 0x92, 0x08 }, /* set A/D reference low */
{ 0x93, 0x00 }, /* set start row to 0 */
{ 0x94, 0x05 }, /* set end row to 5 */
{ 0x95, 0x00 }, /* set start column to 0 */
{ 0x96, 0x18 }, /* set end column to 24*4=96 */
{ 0x97, 0x04 }, /* data format and thresholds */
{ 0x98, 0x28 }, /* image data control */
{ 0x99, 0x00 }, /* disable general purpose outputs */
{ 0x9a, 0x0b }, /* set initial scan state */
{ 0x9b, 0x00 }, /* clear challenge word bits */
{ 0x9c, 0x00 }, /* clear challenge word bits */
{ 0x9d, 0x09 }, /* set some challenge word bits */
{ 0x9e, 0x53 }, /* clear challenge word bits */
{ 0x9f, 0x6b }, /* set some challenge word bits */
{ 0, 0 },
{ 0x84, 0x07 }, /* set calibration resistance to 12 kiloohms */
{ 0x85, 0x3d }, /* set calibration capacitance */
{ 0x86, 0x03 }, /* detect drive voltage */
{ 0x87, 0x01 }, /* set detection frequency to 125khz */
{ 0x88, 0x02 }, /* set column scan period */
{ 0x89, 0x02 }, /* set measure drive */
{ 0x8a, 0x33 }, /* set measure frequency and sense amplifier bias */
{ 0x8b, 0x33 }, /* set matrix pattern */
{ 0x8c, 0x0f }, /* set demodulation phase 1 */
{ 0x8d, 0x04 }, /* set demodulation phase 2 */
{ 0x8e, 0x23 }, /* set sensor gain */
{ 0x8f, 0x07 }, /* set image parameters */
{ 0x90, 0x00 }, /* carrier offset null */
{ 0x91, 0x1c }, /* set A/D reference high */
{ 0x92, 0x08 }, /* set A/D reference low */
{ 0x93, 0x00 }, /* set start row to 0 */
{ 0x94, 0x05 }, /* set end row to 5 */
{ 0x95, 0x00 }, /* set start column to 0 */
{ 0x96, 0x18 }, /* set end column to 24*4=96 */
{ 0x97, 0x04 }, /* data format and thresholds */
{ 0x98, 0x28 }, /* image data control */
{ 0x99, 0x00 }, /* disable general purpose outputs */
{ 0x9a, 0x0b }, /* set initial scan state */
{ 0x9b, 0x00 }, /* clear challenge word bits */
{ 0x9c, 0x00 }, /* clear challenge word bits */
{ 0x9d, 0x09 }, /* set some challenge word bits */
{ 0x9e, 0x53 }, /* clear challenge word bits */
{ 0x9f, 0x6b }, /* set some challenge word bits */
{ 0, 0 },
{ 0x80, 0x00 },
{ 0x81, 0x00 },
{ 0, 0 },
{ 0x81, 0x04 },
{ 0, 0 },
{ 0x81, 0x00 },
{ 0x80, 0x00 },
{ 0x81, 0x00 },
{ 0, 0 },
{ 0x81, 0x04 },
{ 0, 0 },
{ 0x81, 0x00 },
};
struct _FpiDeviceAes4000 {
FpiDeviceAes3k parent;
struct _FpiDeviceAes4000
{
FpiDeviceAes3k parent;
};
G_DECLARE_FINAL_TYPE(FpiDeviceAes4000, fpi_device_aes4000, FPI,
DEVICE_AES4000, FpiDeviceAes3k);
G_DEFINE_TYPE(FpiDeviceAes4000, fpi_device_aes4000, FPI_TYPE_DEVICE_AES3K);
G_DECLARE_FINAL_TYPE (FpiDeviceAes4000, fpi_device_aes4000, FPI,
DEVICE_AES4000, FpiDeviceAes3k);
G_DEFINE_TYPE (FpiDeviceAes4000, fpi_device_aes4000, FPI_TYPE_DEVICE_AES3K);
static const FpIdEntry id_table [ ] = {
{ .pid = 0x08ff, .vid = 0x5501 },
{ .vid = 0, .pid = 0, .driver_data = 0 },
static const FpIdEntry id_table[] = {
{ .pid = 0x08ff, .vid = 0x5501 },
{ .vid = 0, .pid = 0, .driver_data = 0 },
};
static void fpi_device_aes4000_init(FpiDeviceAes4000 *self) {
static void
fpi_device_aes4000_init (FpiDeviceAes4000 *self)
{
}
static void fpi_device_aes4000_class_init(FpiDeviceAes4000Class *klass) {
FpDeviceClass *dev_class = FP_DEVICE_CLASS(klass);
FpImageDeviceClass *img_class = FP_IMAGE_DEVICE_CLASS(klass);
FpiDeviceAes3kClass *aes_class = FPI_DEVICE_AES3K_CLASS (klass);
static void
fpi_device_aes4000_class_init (FpiDeviceAes4000Class *klass)
{
FpDeviceClass *dev_class = FP_DEVICE_CLASS (klass);
FpImageDeviceClass *img_class = FP_IMAGE_DEVICE_CLASS (klass);
FpiDeviceAes3kClass *aes_class = FPI_DEVICE_AES3K_CLASS (klass);
dev_class->id = "aes4000";
dev_class->full_name = "AuthenTec AES4000";
dev_class->id_table = id_table;
dev_class->id = "aes4000";
dev_class->full_name = "AuthenTec AES4000";
dev_class->id_table = id_table;
img_class->img_height = FRAME_WIDTH * ENLARGE_FACTOR;
img_class->img_width = FRAME_WIDTH * ENLARGE_FACTOR;
img_class->img_height = FRAME_WIDTH * ENLARGE_FACTOR;
img_class->img_width = FRAME_WIDTH * ENLARGE_FACTOR;
aes_class->data_buflen = DATA_BUFLEN;
aes_class->frame_width = FRAME_WIDTH;
aes_class->frame_size = FRAME_SIZE;
aes_class->frame_number = FRAME_NUMBER;
aes_class->enlarge_factor = ENLARGE_FACTOR;
aes_class->init_reqs = init_reqs;
aes_class->init_reqs_len = G_N_ELEMENTS(init_reqs);
aes_class->data_buflen = DATA_BUFLEN;
aes_class->frame_width = FRAME_WIDTH;
aes_class->frame_size = FRAME_SIZE;
aes_class->frame_number = FRAME_NUMBER;
aes_class->enlarge_factor = ENLARGE_FACTOR;
aes_class->init_reqs = init_reqs;
aes_class->init_reqs_len = G_N_ELEMENTS (init_reqs);
}

View file

@ -28,131 +28,145 @@
#include "fpi-assembling.h"
#include "aeslib.h"
#define MAX_REGWRITES_PER_REQUEST 16
#define MAX_REGWRITES_PER_REQUEST 16
#define BULK_TIMEOUT 4000
#define EP_IN (1 | FPI_USB_ENDPOINT_IN)
#define EP_OUT (2 | FPI_USB_ENDPOINT_OUT)
#define BULK_TIMEOUT 4000
#define EP_IN (1 | FPI_USB_ENDPOINT_IN)
#define EP_OUT (2 | FPI_USB_ENDPOINT_OUT)
struct write_regv_data {
unsigned int num_regs;
const struct aes_regwrite *regs;
unsigned int offset;
aes_write_regv_cb callback;
void *user_data;
struct write_regv_data
{
unsigned int num_regs;
const struct aes_regwrite *regs;
unsigned int offset;
aes_write_regv_cb callback;
void *user_data;
};
static void continue_write_regv(FpImageDevice *dev, struct write_regv_data *wdata);
static void continue_write_regv (FpImageDevice *dev,
struct write_regv_data *wdata);
/* libusb bulk callback for regv write completion transfer. continues the
* transaction */
static void write_regv_trf_complete(FpiUsbTransfer *transfer, FpDevice *device,
gpointer user_data, GError *error)
static void
write_regv_trf_complete (FpiUsbTransfer *transfer, FpDevice *device,
gpointer user_data, GError *error)
{
struct write_regv_data *wdata = user_data;
struct write_regv_data *wdata = user_data;
if (error) {
wdata->callback(FP_IMAGE_DEVICE (device), error, wdata->user_data);
g_free(wdata);
} else {
continue_write_regv(FP_IMAGE_DEVICE (device), wdata);
}
if (error)
{
wdata->callback (FP_IMAGE_DEVICE (device), error, wdata->user_data);
g_free (wdata);
}
else
{
continue_write_regv (FP_IMAGE_DEVICE (device), wdata);
}
}
/* write from wdata->offset to upper_bound (inclusive) of wdata->regs */
static void do_write_regv(FpImageDevice *dev, struct write_regv_data *wdata, int upper_bound)
static void
do_write_regv (FpImageDevice *dev, struct write_regv_data *wdata, int upper_bound)
{
unsigned int offset = wdata->offset;
unsigned int num = upper_bound - offset + 1;
size_t alloc_size = num * 2;
unsigned int i;
size_t data_offset = 0;
FpiUsbTransfer *transfer = fpi_usb_transfer_new(FP_DEVICE (dev));
unsigned int offset = wdata->offset;
unsigned int num = upper_bound - offset + 1;
size_t alloc_size = num * 2;
unsigned int i;
size_t data_offset = 0;
FpiUsbTransfer *transfer = fpi_usb_transfer_new (FP_DEVICE (dev));
fpi_usb_transfer_fill_bulk (transfer, EP_OUT, alloc_size);
fpi_usb_transfer_fill_bulk (transfer, EP_OUT, alloc_size);
for (i = offset; i < offset + num; i++) {
const struct aes_regwrite *regwrite = &wdata->regs[i];
transfer->buffer[data_offset++] = regwrite->reg;
transfer->buffer[data_offset++] = regwrite->value;
}
for (i = offset; i < offset + num; i++)
{
const struct aes_regwrite *regwrite = &wdata->regs[i];
transfer->buffer[data_offset++] = regwrite->reg;
transfer->buffer[data_offset++] = regwrite->value;
}
transfer->short_is_error = TRUE;
fpi_usb_transfer_submit(transfer, BULK_TIMEOUT, NULL,
write_regv_trf_complete, wdata);
fpi_usb_transfer_unref (transfer);
transfer->short_is_error = TRUE;
fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
write_regv_trf_complete, wdata);
fpi_usb_transfer_unref (transfer);
}
/* write the next batch of registers to be written, or if there are no more,
* indicate completion to the caller */
static void continue_write_regv(FpImageDevice *dev, struct write_regv_data *wdata)
static void
continue_write_regv (FpImageDevice *dev, struct write_regv_data *wdata)
{
unsigned int offset = wdata->offset;
unsigned int regs_remaining;
unsigned int limit;
unsigned int upper_bound;
int i;
unsigned int offset = wdata->offset;
unsigned int regs_remaining;
unsigned int limit;
unsigned int upper_bound;
int i;
/* skip all zeros and ensure there is still work to do */
while (TRUE) {
if (offset >= wdata->num_regs) {
fp_dbg("all registers written");
wdata->callback(dev, 0, wdata->user_data);
g_free(wdata);
return;
}
if (wdata->regs[offset].reg)
break;
offset++;
}
/* skip all zeros and ensure there is still work to do */
while (TRUE)
{
if (offset >= wdata->num_regs)
{
fp_dbg ("all registers written");
wdata->callback (dev, 0, wdata->user_data);
g_free (wdata);
return;
}
if (wdata->regs[offset].reg)
break;
offset++;
}
wdata->offset = offset;
regs_remaining = wdata->num_regs - offset;
limit = MIN(regs_remaining, MAX_REGWRITES_PER_REQUEST);
upper_bound = offset + limit - 1;
wdata->offset = offset;
regs_remaining = wdata->num_regs - offset;
limit = MIN (regs_remaining, MAX_REGWRITES_PER_REQUEST);
upper_bound = offset + limit - 1;
/* determine if we can write the entire of the regs at once, or if there
* is a zero dividing things up */
for (i = offset; i <= upper_bound; i++)
if (!wdata->regs[i].reg) {
upper_bound = i - 1;
break;
}
/* determine if we can write the entire of the regs at once, or if there
* is a zero dividing things up */
for (i = offset; i <= upper_bound; i++)
if (!wdata->regs[i].reg)
{
upper_bound = i - 1;
break;
}
do_write_regv(dev, wdata, upper_bound);
do_write_regv (dev, wdata, upper_bound);
wdata->offset = upper_bound + 1;
wdata->offset = upper_bound + 1;
}
/* write a load of registers to the device, combining multiple writes in a
* single URB up to a limit. insert writes to non-existent register 0 to force
* specific groups of writes to be separated by different URBs. */
void aes_write_regv(FpImageDevice *dev, const struct aes_regwrite *regs,
unsigned int num_regs, aes_write_regv_cb callback,
void *user_data)
void
aes_write_regv (FpImageDevice *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;
fp_dbg("write %d regs", num_regs);
wdata = g_malloc(sizeof(*wdata));
wdata->num_regs = num_regs;
wdata->regs = regs;
wdata->offset = 0;
wdata->callback = callback;
wdata->user_data = user_data;
continue_write_regv(dev, wdata);
fp_dbg ("write %d regs", num_regs);
wdata = g_malloc (sizeof (*wdata));
wdata->num_regs = num_regs;
wdata->regs = regs;
wdata->offset = 0;
wdata->callback = callback;
wdata->user_data = user_data;
continue_write_regv (dev, wdata);
}
unsigned char aes_get_pixel(struct fpi_frame_asmbl_ctx *ctx,
struct fpi_frame *frame,
unsigned int x,
unsigned int y)
unsigned char
aes_get_pixel (struct fpi_frame_asmbl_ctx *ctx,
struct fpi_frame *frame,
unsigned int x,
unsigned int y)
{
unsigned char ret;
unsigned char ret;
ret = frame->data[x * (ctx->frame_height >> 1) + (y >> 1)];
ret = y % 2 ? ret >> 4 : ret & 0xf;
ret *= 17;
ret = frame->data[x * (ctx->frame_height >> 1) + (y >> 1)];
ret = y % 2 ? ret >> 4 : ret & 0xf;
ret *= 17;
return ret;
return ret;
}

View file

@ -22,25 +22,28 @@
#include <fprint.h>
struct aes_regwrite {
unsigned char reg;
unsigned char value;
struct aes_regwrite
{
unsigned char reg;
unsigned char value;
};
struct fpi_frame;
struct fpi_frame_asmbl_ctx;
typedef void (*aes_write_regv_cb)(FpImageDevice *dev, GError *error,
void *user_data);
typedef void (*aes_write_regv_cb)(FpImageDevice *dev,
GError *error,
void *user_data);
void aes_write_regv(FpImageDevice *dev, const struct aes_regwrite *regs,
unsigned int num_regs, aes_write_regv_cb callback,
void *user_data);
void aes_write_regv (FpImageDevice *dev,
const struct aes_regwrite *regs,
unsigned int num_regs,
aes_write_regv_cb callback,
void *user_data);
unsigned char aes_get_pixel(struct fpi_frame_asmbl_ctx *ctx,
struct fpi_frame *frame,
unsigned int x,
unsigned int y);
unsigned char aes_get_pixel (struct fpi_frame_asmbl_ctx *ctx,
struct fpi_frame *frame,
unsigned int x,
unsigned int y);
#endif

File diff suppressed because it is too large Load diff

View file

@ -42,69 +42,70 @@
#define AESX660_FRAME_HEIGHT 8
G_DECLARE_DERIVABLE_TYPE(FpiDeviceAesX660, fpi_device_aes_x660, FPI,
DEVICE_AES_X660, FpImageDevice)
G_DECLARE_DERIVABLE_TYPE (FpiDeviceAesX660, fpi_device_aes_x660, FPI,
DEVICE_AES_X660, FpImageDevice)
#define FPI_TYPE_DEVICE_AES_X660 (fpi_device_aes_x660_get_type ())
struct _FpiDeviceAesX660Class {
FpImageDeviceClass parent;
struct _FpiDeviceAesX660Class
{
FpImageDeviceClass parent;
struct aesX660_cmd *init_seqs[2];
gsize init_seqs_len[2];
guint8 *start_imaging_cmd;
gsize start_imaging_cmd_len;
struct aesX660_cmd *init_seqs[2];
gsize init_seqs_len[2];
guint8 *start_imaging_cmd;
gsize start_imaging_cmd_len;
struct fpi_frame_asmbl_ctx *assembling_ctx;
};
struct aesX660_cmd {
struct aesX660_cmd
{
const guint8 *cmd;
gsize len;
gsize len;
};
/* 0x77 cmd seems to control LED, this sequence
* makes LED blink
*/
static const guint8 led_blink_cmd[] = {
0x77, 0x18, 0x00,
0x00, 0x3f, 0x00, 0xff, 0x00,
0x01, 0x01, 0x00, 0x00, 0x00, 0xf3, 0x01, 0x00,
0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0xf3,
0x01, 0x00, 0x7f
0x77, 0x18, 0x00,
0x00, 0x3f, 0x00, 0xff, 0x00,
0x01, 0x01, 0x00, 0x00, 0x00, 0xf3, 0x01, 0x00,
0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0xf3,
0x01, 0x00, 0x7f
};
/* This sequence makes LED light solid
*/
static const guint8 led_solid_cmd[] = {
0x77, 0x18, 0x00, 0x00, 0x3f, 0x00, 0xff, 0x00,
0x01, 0x01, 0x00, 0x00, 0x00, 0xe7, 0x03, 0x00,
0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7f
0x77, 0x18, 0x00, 0x00, 0x3f, 0x00, 0xff, 0x00,
0x01, 0x01, 0x00, 0x00, 0x00, 0xe7, 0x03, 0x00,
0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7f
};
static const guint8 wait_for_finger_cmd[] = {
0x20,
0x40, 0x04, 0x00, 0x02, 0x1e, 0x00, 0x32
0x20,
0x40, 0x04, 0x00, 0x02, 0x1e, 0x00, 0x32
};
/* 0x40 cmd response
*
static const guint8 pkt1371[] = {
0x40, 0x01, 0x00, 0x01
};
*/
static const guint8 pkt1371[] = {
0x40, 0x01, 0x00, 0x01
};
*/
static const guint8 set_idle_cmd[] = {
0x0d, /* Reset or "set idle"? */
0x0d, /* Reset or "set idle"? */
};
static const guint8 read_id_cmd[] = {
0x44, 0x02, 0x00, 0x08, 0x00, /* Max transfer size is 8 */
0x07, /* Read ID? */
0x44, 0x02, 0x00, 0x08, 0x00, /* Max transfer size is 8 */
0x07, /* Read ID? */
};
static const guint8 calibrate_cmd[] = {
0x44, 0x02, 0x00, 0x04, 0x00,
0x06,
0x44, 0x02, 0x00, 0x04, 0x00,
0x06,
};

View file

@ -21,27 +21,27 @@
#define __DRIVER_IDS
enum {
UPEKTS_ID = 1,
URU4000_ID = 2,
AES4000_ID = 3,
AES2501_ID = 4,
UPEKTC_ID = 5,
AES1610_ID = 6,
/* FDU2000_ID = 7, */
VCOM5S_ID = 8,
UPEKSONLY_ID = 9,
VFS101_ID = 10,
VFS301_ID = 11,
AES2550_ID = 12,
/* UPEKE2_ID = 13 */
AES1660_ID = 14,
AES2660_ID = 15,
AES3500_ID = 16,
UPEKTC_IMG_ID = 17,
ETES603_ID = 18,
VFS5011_ID = 19,
VFS0050_ID = 20,
ELAN_ID = 21,
UPEKTS_ID = 1,
URU4000_ID = 2,
AES4000_ID = 3,
AES2501_ID = 4,
UPEKTC_ID = 5,
AES1610_ID = 6,
/* FDU2000_ID = 7, */
VCOM5S_ID = 8,
UPEKSONLY_ID = 9,
VFS101_ID = 10,
VFS301_ID = 11,
AES2550_ID = 12,
/* UPEKE2_ID = 13 */
AES1660_ID = 14,
AES2660_ID = 15,
AES3500_ID = 16,
UPEKTC_IMG_ID = 17,
ETES603_ID = 18,
VFS5011_ID = 19,
VFS0050_ID = 20,
ELAN_ID = 21,
};
#endif

File diff suppressed because it is too large Load diff

View file

@ -71,155 +71,158 @@
#define ELAN_CMD_TIMEOUT 10000
#define ELAN_FINGER_TIMEOUT 200
struct elan_cmd {
unsigned char cmd[ELAN_CMD_LEN];
int response_len;
int response_in;
unsigned short devices;
gboolean never_cancel;
struct elan_cmd
{
unsigned char cmd[ELAN_CMD_LEN];
int response_len;
int response_in;
unsigned short devices;
gboolean never_cancel;
};
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,
.cmd = {0x00, 0x0c},
.response_len = 0x4,
.response_in = ELAN_EP_CMD_IN,
.devices = ELAN_ALL_DEV,
};
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,
.cmd = {0x40, 0x19},
.response_len = 0x2,
.response_in = ELAN_EP_CMD_IN,
.devices = ELAN_ALL_DEV,
};
/* 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,
.cmd = {0x40, 0x2a},
.response_len = 0x2,
.response_in = ELAN_EP_CMD_IN,
.devices = ELAN_0907,
};
static const struct elan_cmd get_image_cmd = {
.cmd = {0x00, 0x09},
/* raw frame sizes are calculated from image dimensions reported by the
* device */
.response_len = -1,
.response_in = ELAN_EP_IMG_IN,
.devices = ELAN_ALL_DEV,
.cmd = {0x00, 0x09},
/* raw frame sizes are calculated from image dimensions reported by the
* device */
.response_len = -1,
.response_in = ELAN_EP_IMG_IN,
.devices = ELAN_ALL_DEV,
};
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,
.cmd = {0x40, 0x13},
.response_len = 0x1,
.response_in = ELAN_EP_CMD_IN,
.devices = ELAN_ALL_DEV,
};
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,
.cmd = {0x40, 0x23},
.response_len = 0x1,
.response_in = ELAN_EP_CMD_IN,
.devices = ELAN_ALL_DEV,
};
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,
.cmd = {0x40, 0x24},
.response_len = 0x2,
.response_in = ELAN_EP_CMD_IN,
.devices = ELAN_ALL_DEV,
};
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,
.cmd = {0x40, 0x31},
.response_len = ELAN_CMD_SKIP_READ,
.response_in = ELAN_EP_CMD_IN,
.devices = ELAN_ALL_DEV,
};
/* 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,
.cmd = {0x40, 0x3f},
.response_len = 0x1,
.response_in = ELAN_EP_CMD_IN,
.devices = ELAN_ALL_DEV,
};
/* 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,
.never_cancel = TRUE,
.cmd = {0x00, 0x0b},
.response_len = ELAN_CMD_SKIP_READ,
.response_in = ELAN_EP_CMD_IN,
.devices = ELAN_ALL_DEV,
.never_cancel = TRUE,
};
static const FpIdEntry elan_id_table [ ] = {
{.vid = ELAN_VEND_ID, .pid = 0x0903, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0907, .driver_data = ELAN_0907},
{.vid = ELAN_VEND_ID, .pid = 0x0c01, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c02, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c03, .driver_data = ELAN_0C03},
{.vid = ELAN_VEND_ID, .pid = 0x0c04, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c05, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c06, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c07, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c08, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c09, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c0a, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c0b, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c0c, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c0d, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c0e, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c0f, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c10, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c11, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c12, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c13, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c14, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c15, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c16, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c17, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c18, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c19, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c1a, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c1b, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c1c, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c1d, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c1e, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c1f, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c20, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c21, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c22, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c23, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c24, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c25, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c26, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c27, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c28, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c29, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c2a, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c2b, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c2c, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c2d, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c2e, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c2f, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c30, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c31, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c32, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c33, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c42, .driver_data = ELAN_0C42},
{.vid = 0, .pid = 0, .driver_data = 0},
static const FpIdEntry elan_id_table[] = {
{.vid = ELAN_VEND_ID, .pid = 0x0903, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0907, .driver_data = ELAN_0907},
{.vid = ELAN_VEND_ID, .pid = 0x0c01, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c02, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c03, .driver_data = ELAN_0C03},
{.vid = ELAN_VEND_ID, .pid = 0x0c04, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c05, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c06, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c07, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c08, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c09, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c0a, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c0b, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c0c, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c0d, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c0e, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c0f, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c10, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c11, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c12, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c13, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c14, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c15, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c16, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c17, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c18, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c19, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c1a, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c1b, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c1c, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c1d, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c1e, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c1f, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c20, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c21, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c22, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c23, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c24, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c25, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c26, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c27, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c28, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c29, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c2a, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c2b, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c2c, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c2d, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c2e, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c2f, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c30, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c31, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c32, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c33, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c42, .driver_data = ELAN_0C42},
{.vid = 0, .pid = 0, .driver_data = 0},
};
static void elan_cmd_done(FpiSsm *ssm);
static void elan_cmd_read(FpiSsm *ssm, FpDevice *dev);
static void elan_cmd_done (FpiSsm *ssm);
static void elan_cmd_read (FpiSsm *ssm,
FpDevice *dev);
static void elan_calibrate(FpDevice *dev);
static void elan_capture(FpDevice *dev);
static void elan_calibrate (FpDevice *dev);
static void elan_capture (FpDevice *dev);
static void dev_change_state(FpImageDevice *dev, FpImageDeviceState state);
static void dev_change_state (FpImageDevice *dev,
FpImageDeviceState state);
#endif

File diff suppressed because it is too large Load diff

View file

@ -21,107 +21,107 @@
#define _BMKT_H_
/**< User ID maximum length allowed */
#define BMKT_MAX_USER_ID_LEN 100
#define BMKT_MAX_USER_ID_LEN 100
/**< Software Part Number length */
#define BMKT_PART_NUM_LEN 10
#define BMKT_PART_NUM_LEN 10
/**< Software supplier identification length */
#define BMKT_SUPPLIER_ID_LEN 2
#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
#define BMKT_MAX_NUM_TEMPLATES_INTERNAL_FLASH 15
#include <stdint.h>
#include "bmkt_response.h"
/*!
*******************************************************************************
** Type definition for result
*/
*******************************************************************************
** Type definition for result
*/
/** No error; Operation successfully completed. */
#define BMKT_SUCCESS 0
#define BMKT_SUCCESS 0
/** Fingerprint system not initialized */
#define BMKT_FP_SYSTEM_NOT_INITIALIZED 101
#define BMKT_FP_SYSTEM_NOT_INITIALIZED 101
/** Fingerprint system busy performing another operation */
#define BMKT_FP_SYSTEM_BUSY 102
#define BMKT_FP_SYSTEM_BUSY 102
/** Operation not allowed */
#define BMKT_OPERATION_DENIED 103
#define BMKT_OPERATION_DENIED 103
/** System ran out of memory while performing operation */
#define BMKT_OUT_OF_MEMORY 104
#define BMKT_OUT_OF_MEMORY 104
/** Corrupt message, CRC check fail or truncated message */
#define BMKT_CORRUPT_MESSAGE 110
#define BMKT_CORRUPT_MESSAGE 110
/** One of the command parameters is outside the range of valid values */
#define BMKT_INVALID_PARAM 111
#define BMKT_INVALID_PARAM 111
/** Unrecognized message or message with invalid message ID */
#define BMKT_UNRECOGNIZED_MESSAGE 112
#define BMKT_UNRECOGNIZED_MESSAGE 112
/** Operation time out */
#define BMKT_OP_TIME_OUT 113
#define BMKT_OP_TIME_OUT 113
/** General error cause of error cannot be determined */
#define BMKT_GENERAL_ERROR 114
#define BMKT_GENERAL_ERROR 114
#define BMKT_SET_SECURITY_LEVEL_FAIL 120
#define BMKT_GET_SECURITY_LEVEL_FAIL 121
#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
#define BMKT_SENSOR_RESET 201
/** Fingerprint sensor malfunctioned */
#define BMKT_SENSOR_MALFUNCTION 202
#define BMKT_SENSOR_MALFUNCTION 202
/** Fingerprint sensor cannot be accessed despite repeated attempts */
#define BMKT_SENSOR_TAMPERED 203
#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
* 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
#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_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
* 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
#define BMKT_FEATURE_EXTRACT_FAIL 301
/** Failed to generate fingerprint template */
#define BMKT_ENROLL_FAIL 302
#define BMKT_ENROLL_FAIL 302
/** Specified finger already enrolled for this user */
#define BMKT_ENROLLMENT_EXISTS 303
#define BMKT_ENROLLMENT_EXISTS 303
/** Invalid fingerprint image */
#define BMKT_INVALID_FP_IMAGE 304
#define BMKT_INVALID_FP_IMAGE 304
/** No matching user fingerprint template found in database */
#define BMKT_FP_NO_MATCH 404
#define BMKT_FP_NO_MATCH 404
/** Fingerprint database is full */
#define BMKT_FP_DATABASE_FULL 501
#define BMKT_FP_DATABASE_FULL 501
/** Fingerprint database is empty */
#define BMKT_FP_DATABASE_EMPTY 502
#define BMKT_FP_DATABASE_EMPTY 502
/** Cannot access fingerprint database */
#define BMKT_FP_DATABASE_ACCESS_FAIL 503
#define BMKT_FP_DATABASE_ACCESS_FAIL 503
/** Fingerprint template record does not exist */
#define BMKT_FP_DATABASE_NO_RECORD_EXISTS 504
#define BMKT_FP_DATABASE_NO_RECORD_EXISTS 504
/** Failed to read/write system parameters stored on flash */
#define BMKT_FP_PARAM_ACCESS_FAIL 505
#define BMKT_FP_PARAM_ACCESS_FAIL 505
/** Fingerprint is a spoof */
#define BMKT_FP_SPOOF_ALERT 801
#define BMKT_FP_SPOOF_ALERT 801
/** Anti-spoof module failure */
#define BMKT_ANTI_SPOOF_MODULE_FAIL 802
#define BMKT_ANTI_SPOOF_MODULE_FAIL 802
#define BMKT_CORRUPT_UPDATE_IMAGE 901
#define BMKT_SYSTEM_UPDATE_FAIL 902
#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
#define BMKT_EVENT_NOT_SET 1000
#define BMKT_SENSOR_NOT_READY 1001
#define BMKT_TIMEOUT 1002
#define BMKT_SENSOR_RESPONSE_PENDING 1003
#ifdef __cplusplus
@ -129,104 +129,100 @@ 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:
* 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:
* 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:
* 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
*/
* bmkt_usb_config:
* Structure represcontainingenting USB configuration details
*/
typedef struct bmkt_usb_config
{
int product_id; /**< USB device product ID */
int product_id; /**< USB device product ID */
} bmkt_usb_config_t;
/**
* bmkt_transport_config_t:
* Union containing transport configuration details
*/
* bmkt_transport_config_t:
* Union containing transport configuration details
*/
typedef union
{
bmkt_usb_config_t usb_config;
bmkt_usb_config_t usb_config;
} bmkt_transport_config_t;
/**
* bmkt_sensor_desc_t:
* Structure containing fingerprint system description
*/
* bmkt_sensor_desc_t:
* Structure containing fingerprint system description
*/
typedef struct bmkt_sensor_desc
{
int product_id;
int flags;
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:
* 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
*/
* bmkt_finger_event_t:
* Structure containing finger state
*/
typedef struct bmkt_finger_event
{
bmkt_finger_state_t finger_state;
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];
uint8_t user_id_len;
uint8_t user_id[BMKT_MAX_USER_ID_LEN];
} bmkt_user_id_t;
#ifdef __cplusplus

View file

@ -20,395 +20,381 @@
#include "bmkt_response.h"
#include "bmkt_message.h"
static uint8_t extract8(const uint8_t *buf, int *offset)
static uint8_t
extract8 (const uint8_t *buf, int *offset)
{
uint8_t ret = 0;
int off = 0;
if (offset)
off = *offset;
uint8_t ret = 0;
int off = 0;
ret = *(buf + off);
if (offset)
off = *offset;
if (offset)
*offset += 1;
ret = *(buf + off);
return ret;
if (offset)
*offset += 1;
return ret;
}
static int parse_error_response(bmkt_msg_resp_t *msg_resp, bmkt_response_t *resp)
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;
}
if (msg_resp->payload_len != 2)
return BMKT_UNRECOGNIZED_MESSAGE;
resp->result = (msg_resp->payload[0] << 8) | msg_resp->payload[1];
resp->result = (msg_resp->payload[0] << 8) | msg_resp->payload[1];
return BMKT_SUCCESS;
return BMKT_SUCCESS;
}
static int parse_init_ok(bmkt_msg_resp_t *msg_resp, bmkt_response_t *resp)
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;
bmkt_init_resp_t *init_resp = &resp->response.init_resp;
if (msg_resp->payload_len != 1)
{
return BMKT_UNRECOGNIZED_MESSAGE;
}
if (msg_resp->payload_len != 1)
return BMKT_UNRECOGNIZED_MESSAGE;
init_resp->finger_presence = extract8(msg_resp->payload, NULL);
init_resp->finger_presence = extract8 (msg_resp->payload, NULL);
return BMKT_SUCCESS;
return BMKT_SUCCESS;
}
static int parse_fps_mode_report(bmkt_msg_resp_t *msg_resp, bmkt_response_t *resp)
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;
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;
}
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);
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;
return BMKT_SUCCESS;
}
static int parse_enroll_report(bmkt_msg_resp_t *msg_resp, bmkt_response_t *resp)
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;
bmkt_enroll_resp_t *enroll_resp = &resp->response.enroll_resp;
if (msg_resp->payload_len != 1)
{
return BMKT_UNRECOGNIZED_MESSAGE;
}
if (msg_resp->payload_len != 1)
return BMKT_UNRECOGNIZED_MESSAGE;
enroll_resp->progress = extract8(msg_resp->payload, NULL);
enroll_resp->progress = extract8 (msg_resp->payload, NULL);
return BMKT_SUCCESS;
return BMKT_SUCCESS;
}
static int parse_enroll_ok(bmkt_msg_resp_t *msg_resp, bmkt_response_t *resp)
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;
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;
}
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);
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;
return BMKT_SUCCESS;
}
static int parse_auth_ok(bmkt_msg_resp_t *msg_resp, bmkt_response_t *resp)
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;
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;
}
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);
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;
return BMKT_SUCCESS;
}
static int parse_security_level_report(bmkt_msg_resp_t *msg_resp, bmkt_response_t *resp)
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;
bmkt_set_sec_level_resp_t *sec_level_resp = &resp->response.sec_level_resp;
if (msg_resp->payload_len != 1)
{
return BMKT_UNRECOGNIZED_MESSAGE;
}
if (msg_resp->payload_len != 1)
return BMKT_UNRECOGNIZED_MESSAGE;
sec_level_resp->sec_level = extract8(msg_resp->payload, NULL);
sec_level_resp->sec_level = extract8 (msg_resp->payload, NULL);
return BMKT_SUCCESS;
return BMKT_SUCCESS;
}
static int parse_del_all_users_progress_report(bmkt_msg_resp_t *msg_resp, bmkt_response_t *resp)
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;
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;
}
if (msg_resp->payload_len != 1)
return BMKT_UNRECOGNIZED_MESSAGE;
del_all_users_resp->progress = extract8(msg_resp->payload, NULL);
del_all_users_resp->progress = extract8 (msg_resp->payload, NULL);
return BMKT_SUCCESS;
return BMKT_SUCCESS;
}
static int parse_db_cap_report(bmkt_msg_resp_t *msg_resp, bmkt_response_t *resp)
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;
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;
}
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);
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);
}
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;
return BMKT_SUCCESS;
}
static int parse_get_enrolled_fingers_report(bmkt_msg_resp_t *msg_resp, bmkt_response_t *resp)
static int
parse_get_enrolled_fingers_report (bmkt_msg_resp_t *msg_resp, bmkt_response_t *resp)
{
int offset = 0;
int i = 0;
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;
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;
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);
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;
}
return BMKT_SUCCESS;
}
static int parse_get_enrolled_users_report(bmkt_msg_resp_t *msg_resp, bmkt_response_t *resp)
static int
parse_get_enrolled_users_report (bmkt_msg_resp_t *msg_resp, bmkt_response_t *resp)
{
int offset = 0;
int i = 0;
int offset = 0;
int i = 0;
/* the payload is 2 bytes + template data */
if (msg_resp->payload_len < 2)
{
return BMKT_UNRECOGNIZED_MESSAGE;
}
/* 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;
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);
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';
}
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;
return BMKT_SUCCESS;
}
static int parse_get_version_report(bmkt_msg_resp_t *msg_resp, bmkt_response_t *resp)
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;
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;
}
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);
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;
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, const uint8_t *payload)
int
bmkt_compose_message (uint8_t *cmd, int *cmd_len, uint8_t msg_id, uint8_t seq_num,
uint8_t payload_size, const uint8_t *payload)
{
int message_len = BMKT_MESSAGE_HEADER_LEN + payload_size;
int message_len = BMKT_MESSAGE_HEADER_LEN + payload_size;
if (*cmd_len < message_len)
{
return BMKT_OUT_OF_MEMORY;
}
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[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;
*cmd_len = message_len;
return BMKT_SUCCESS;
return BMKT_SUCCESS;
}
int bmkt_parse_message_header(uint8_t *resp_buf, int resp_len, bmkt_msg_resp_t *msg_resp)
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;
}
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;
}
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;
return BMKT_SUCCESS;
}
int bmkt_parse_message_payload(bmkt_msg_resp_t *msg_resp, bmkt_response_t *resp)
int
bmkt_parse_message_payload (bmkt_msg_resp_t *msg_resp, bmkt_response_t *resp)
{
int ret = BMKT_SUCCESS;
int ret = BMKT_SUCCESS;
memset(resp, 0, sizeof(bmkt_response_t));
memset (resp, 0, sizeof (bmkt_response_t));
resp->response_id = msg_resp->msg_id;
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;
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_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_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_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_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_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_CAPTURE_COMPLETE:
resp->result = BMKT_SUCCESS;
break;
case BMKT_RSP_ENROLL_READY:
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_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_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_ID_OK:
case BMKT_RSP_VERIFY_OK:
ret = parse_auth_ok (msg_resp, resp);
resp->complete = 1;
break;
case BMKT_RSP_VERSION_INFO:
ret = parse_get_version_report(msg_resp, resp);
resp->complete = 1;
break;
case BMKT_RSP_POWER_DOWN_READY:
resp->complete = 1;
break;
}
case BMKT_RSP_GET_ENROLLED_FINGERS_REPORT:
ret = parse_get_enrolled_fingers_report (msg_resp, resp);
resp->complete = 1;
break;
return ret;
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;
case BMKT_RSP_POWER_DOWN_READY:
resp->complete = 1;
break;
}
return ret;
}

View file

@ -21,66 +21,73 @@
#define BMKT_MESSAGE_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
#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_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_REPORT 0x91
#define BMKT_EVT_FINGER_STATE_NOT_ON_SENSOR 0x00
#define BMKT_EVT_FINGER_STATE_ON_SENSOR 0x01
#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;
uint8_t msg_id;
uint8_t seq_num;
uint8_t payload_len;
uint8_t *payload;
int result;
} bmkt_msg_resp_t;
int bmkt_compose_message(uint8_t *cmd, int *cmd_len, uint8_t msg_id, uint8_t seq_num,
uint8_t payload_size, const uint8_t *payload);
int bmkt_compose_message (uint8_t *cmd,
int *cmd_len,
uint8_t msg_id,
uint8_t seq_num,
uint8_t payload_size,
const 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);
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

@ -24,466 +24,466 @@
#include "bmkt.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_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
#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
* @{
*/
* Response IDs returned by fingerprint initialization operation
* @{
*/
/** Failed to initialize fingerprint sensor module */
#define BMKT_RSP_FPS_INIT_FAIL 0x12
#define BMKT_RSP_FPS_INIT_FAIL 0x12
/** Successfully initialized fingerprint sensor module */
#define BMKT_RSP_FPS_INIT_OK 0x13
#define BMKT_RSP_FPS_INIT_OK 0x13
/*! @} */
/*! \addtogroup mode
* Response IDs returned by get fingerprint mode operation
* @{
*/
* Response IDs returned by get fingerprint mode operation
* @{
*/
/** Failed to get fingerprint sensor modules current operational mode */
#define BMKT_RSP_FPS_MODE_FAIL 0x22
#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
* 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
* @{
*/
* Response IDs returned by set security level operation
* @{
*/
/** Failed to set fingerprint sensor module security level */
#define BMKT_RSP_SET_SECURITY_LEVEL_FAIL 0x32
#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
* 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
* @{
*/
* Response IDs returned by get security level operation
* @{
*/
/** Failed to get fingerprint sensor module security level */
#define BMKT_RSP_GET_SECURITY_LEVEL_FAIL 0x35
#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
* 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
* @{
*/
* 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
* 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
#define BMKT_RSP_CANCEL_OP_FAIL 0x43
/*! @} */
/*! \addtogroup enrollment
* Response IDs returned by enrollment operation
* @{
*/
* 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
* 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
#define BMKT_RSP_ENROLL_REPORT 0x55
/** Enrollment has been paused */
#define BMKT_RSP_ENROLL_PAUSED 0x56
#define BMKT_RSP_ENROLL_PAUSED 0x56
/** Enrollment has been resume */
#define BMKT_RSP_ENROLL_RESUMED 0x57
#define BMKT_RSP_ENROLL_RESUMED 0x57
/** The current enrollment session has encountered an error */
#define BMKT_RSP_ENROLL_FAIL 0x58
#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_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
* 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.
* @{
*/
* Response IDs returned by identify operation.
* @{
*/
/* Fingerprint identification session has begun */
#define BMKT_RSP_ID_READY 0x62
#define BMKT_RSP_ID_READY 0x62
/* Identification has failed */
#define BMKT_RSP_ID_FAIL 0x63
#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
* 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.
* @{
*/
* Response IDs returned by identify operation.
* @{
*/
/** Fingerprint verification session has begun */
#define BMKT_RSP_VERIFY_READY 0x66
#define BMKT_RSP_VERIFY_READY 0x66
/** Verification has failed */
#define BMKT_RSP_VERIFY_FAIL 0x67
#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_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_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_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
* 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
* @{
*/
* 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
* 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
#define BMKT_RSP_QUERY_FAIL 0x79
/*! @} */
/*! \addtogroup deluser
* Response IDs returned by delete fingerprint of specific user operation
* @{
*/
* 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
#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
* 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
* @{
*/
* 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
#define BMKT_RSP_DEL_FULL_DB_FAIL 0x85
/** Successfully erased entire fingerprint template database */
#define BMKT_RSP_DEL_FULL_DB_OK 0x86
#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_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
* 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
* @{
*/
* Response IDs returned by power down notify operation
* @{
*/
/** Fingerprint sensor module is ready to be powered down */
#define BMKT_RSP_POWER_DOWN_READY 0xA2
#define BMKT_RSP_POWER_DOWN_READY 0xA2
/** Failed to go into power down mode */
#define BMKT_RSP_POWER_DOWN_FAIL 0xA3
#define BMKT_RSP_POWER_DOWN_FAIL 0xA3
/*! @} */
/*! \addtogroup versioninfo
* Response IDs returned by get version operation
* @{
*/
* 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
* 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
#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
* 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
* @{
*/
* 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
* 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
#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_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
* 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.
*/
* 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 */
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.
*/
* 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 */
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.
*/
* 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 */
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.
*/
* 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 */
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.
*/
* 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 */
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.
*/
* 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 */
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:
* 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.
*/
* 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_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.
*/
* 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 */
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.
*/
* 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 */
int progress; /**< Progress indicator as a percentage */
} bmkt_del_user_resp_t;
/**
* bmkt_enroll_template:
* Structure of enrolled users template record data.
*/
* 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 */
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.
*/
* 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 */
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.
*/
* 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 */
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.
*/
* 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_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:
* 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.
*/
* 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 */
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

@ -20,61 +20,68 @@
#define _SENSOR_H_
#include "usb_transport.h"
#define BMKT_MAX_PENDING_SESSIONS 2
#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,
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;
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_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_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_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_handle_response(bmkt_sensor_t *sensor, uint8_t *resp_buf, int resp_len, bmkt_msg_resp_t *msg_resp);
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_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);
int bmkt_sensor_send_async_read_command (bmkt_sensor_t *sensor);
#endif /* _SENSOR_H_ */

File diff suppressed because it is too large Load diff

View file

@ -22,109 +22,109 @@
#include "fpi-device.h"
#include "fpi-ssm.h"
#define SYNAPTICS_VENDOR_ID 0x06cb
#define SYNAPTICS_VENDOR_ID 0x06cb
G_DECLARE_FINAL_TYPE(FpiDeviceSynaptics, fpi_device_synaptics, FPI, DEVICE_SYNAPTICS, FpDevice)
G_DECLARE_FINAL_TYPE (FpiDeviceSynaptics, fpi_device_synaptics, FPI, DEVICE_SYNAPTICS, FpDevice)
#define MAX_TRANSFER_LEN 263 + 1 /* SPI Header */ + 2 /* VCSFW header */
#define MAX_TRANSFER_LEN 263 + 1 /* SPI Header */ + 2 /* VCSFW header */
#define USB_EP_REQUEST 0x01
#define USB_EP_REPLY 0x81
#define USB_EP_FINGERPRINT 0x82
#define USB_EP_INTERRUPT 0x83
#define USB_EP_REQUEST 0x01
#define USB_EP_REPLY 0x81
#define USB_EP_FINGERPRINT 0x82
#define USB_EP_INTERRUPT 0x83
#define USB_ASYNC_MESSAGE_PENDING 0x4
#define USB_INTERRUPT_DATA_SIZE 7
#define USB_ASYNC_MESSAGE_PENDING 0x4
#define USB_INTERRUPT_DATA_SIZE 7
#define SENSOR_CMD_GET_VERSION 1
#define SENSOR_CMD_ACE_COMMAND 167
#define SENSOR_CMD_ASYNCMSG_READ 168
#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
#define SENSOR_FW_CMD_HEADER_LEN 1
#define SENSOR_FW_REPLY_HEADER_LEN 2
/* Number of enroll stages */
#define ENROLL_SAMPLES 8
#define ENROLL_SAMPLES 8
#define SYNAPTICS_DRIVER_FULLNAME "Synaptics Sensors"
#define SYNAPTICS_DRIVER_FULLNAME "Synaptics Sensors"
#include "bmkt.h"
#include "bmkt_response.h"
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;
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;
struct syna_enroll_resp_data
{
int progress;
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 ,
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 enum
{
SYNAPTICS_CMD_SEND_PENDING = 0,
SYNAPTICS_CMD_GET_RESP,
SYNAPTICS_CMD_WAIT_INTERRUPT,
SYNAPTICS_CMD_SEND_ASYNC,
SYNAPTICS_CMD_RESTART,
SYNAPTICS_CMD_NUM_STATES,
typedef enum {
SYNAPTICS_CMD_SEND_PENDING = 0,
SYNAPTICS_CMD_GET_RESP,
SYNAPTICS_CMD_WAIT_INTERRUPT,
SYNAPTICS_CMD_SEND_ASYNC,
SYNAPTICS_CMD_RESTART,
SYNAPTICS_CMD_NUM_STATES,
} SynapticsCmdState;
typedef void (*SynCmdMsgCallback) (FpiDeviceSynaptics *self, bmkt_response_t *resp, GError *error);
typedef void (*SynCmdMsgCallback) (FpiDeviceSynaptics *self,
bmkt_response_t *resp,
GError *error);
struct _FpiDeviceSynaptics
{
FpDevice parent;
FpDevice parent;
guint8 cmd_seq_num;
guint8 last_seq_num;
FpiSsm *cmd_ssm;
FpiUsbTransfer *cmd_pending_transfer;
gboolean cmd_complete_on_removal;
GError *cmd_complete_error;
void *cmd_complete_data;
guint8 cmd_seq_num;
guint8 last_seq_num;
FpiSsm *cmd_ssm;
FpiUsbTransfer *cmd_pending_transfer;
gboolean cmd_complete_on_removal;
GError *cmd_complete_error;
void *cmd_complete_data;
bmkt_sensor_version_t mis_version;
bmkt_sensor_version_t mis_version;
GCancellable *interrupt_cancellable;
GCancellable *interrupt_cancellable;
gint enroll_stage;
gboolean finger_on_sensor;
GPtrArray *list_result;
gint enroll_stage;
gboolean finger_on_sensor;
GPtrArray *list_result;
struct syna_enroll_resp_data enroll_resp_data;
syna_state_t state;
struct syna_enroll_resp_data enroll_resp_data;
syna_state_t state;
};
#endif //__synaptics_h__

View file

@ -21,46 +21,47 @@
#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
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)
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;
uint16_t crc = 0;
while (size--)
crc = (uint16_t) ((crc << 8) ^
crc_table[((crc >> 8) & 0x00ff) ^ *buffer++]);
return crc;
}

View file

@ -21,4 +21,5 @@
#include <stdint.h>
#include <stddef.h>
uint16_t udf_crc(unsigned char *buffer, size_t size);
uint16_t udf_crc (unsigned char *buffer,
size_t size);

File diff suppressed because it is too large Load diff

View file

@ -23,297 +23,298 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#define IMG_WIDTH_2016 288
#define IMG_WIDTH_1000 288
#define IMG_WIDTH_1001 216
#define IMG_WIDTH_2016 288
#define IMG_WIDTH_1000 288
#define IMG_WIDTH_1001 216
struct sonly_regwrite {
guint8 reg;
guint8 value;
struct sonly_regwrite
{
guint8 reg;
guint8 value;
};
/***** AWAIT FINGER *****/
static const struct sonly_regwrite awfsm_2016_writev_1[] = {
{ 0x0a, 0x00 }, { 0x0a, 0x00 }, { 0x09, 0x20 }, { 0x03, 0x3b },
{ 0x00, 0x67 }, { 0x00, 0x67 },
{ 0x0a, 0x00 }, { 0x0a, 0x00 }, { 0x09, 0x20 }, { 0x03, 0x3b },
{ 0x00, 0x67 }, { 0x00, 0x67 },
};
static const struct sonly_regwrite awfsm_1000_writev_1[] = {
/* Initialize sensor settings */
{ 0x0a, 0x00 }, { 0x09, 0x20 }, { 0x03, 0x37 }, { 0x00, 0x5f },
{ 0x01, 0x6e }, { 0x01, 0xee }, { 0x0c, 0x13 }, { 0x0d, 0x0d },
{ 0x0e, 0x0e }, { 0x0f, 0x0d },
/* Initialize sensor settings */
{ 0x0a, 0x00 }, { 0x09, 0x20 }, { 0x03, 0x37 }, { 0x00, 0x5f },
{ 0x01, 0x6e }, { 0x01, 0xee }, { 0x0c, 0x13 }, { 0x0d, 0x0d },
{ 0x0e, 0x0e }, { 0x0f, 0x0d },
{ 0x13, 0x05 }, { 0x13, 0x45 },
{ 0x13, 0x05 }, { 0x13, 0x45 },
/* Initialize finger detection registers (not enabling yet) */
{ 0x30, 0xe0 }, { 0x15, 0x26 },
/* Initialize finger detection registers (not enabling yet) */
{ 0x30, 0xe0 }, { 0x15, 0x26 },
{ 0x12, 0x01 }, { 0x20, 0x01 }, { 0x07, 0x10 },
{ 0x10, 0x00 }, { 0x11, 0xbf },
{ 0x12, 0x01 }, { 0x20, 0x01 }, { 0x07, 0x10 },
{ 0x10, 0x00 }, { 0x11, 0xbf },
};
static const struct sonly_regwrite awfsm_2016_writev_2[] = {
{ 0x01, 0xc6 }, { 0x0c, 0x13 }, { 0x0d, 0x0d }, { 0x0e, 0x0e },
{ 0x0f, 0x0d }, { 0x0b, 0x00 },
{ 0x01, 0xc6 }, { 0x0c, 0x13 }, { 0x0d, 0x0d }, { 0x0e, 0x0e },
{ 0x0f, 0x0d }, { 0x0b, 0x00 },
};
static const struct sonly_regwrite awfsm_1000_writev_2[] = {
/* Enable finger detection */
{ 0x30, 0xe1 }, { 0x15, 0x06 }, { 0x15, 0x86 },
/* Enable finger detection */
{ 0x30, 0xe1 }, { 0x15, 0x06 }, { 0x15, 0x86 },
};
static const struct sonly_regwrite awfsm_2016_writev_3[] = {
{ 0x13, 0x45 }, { 0x30, 0xe0 }, { 0x12, 0x01 }, { 0x20, 0x01 },
{ 0x09, 0x20 }, { 0x0a, 0x00 }, { 0x30, 0xe0 }, { 0x20, 0x01 },
{ 0x13, 0x45 }, { 0x30, 0xe0 }, { 0x12, 0x01 }, { 0x20, 0x01 },
{ 0x09, 0x20 }, { 0x0a, 0x00 }, { 0x30, 0xe0 }, { 0x20, 0x01 },
};
static const struct sonly_regwrite awfsm_2016_writev_4[] = {
{ 0x08, 0x00 }, { 0x10, 0x00 }, { 0x12, 0x01 }, { 0x11, 0xbf },
{ 0x12, 0x01 }, { 0x07, 0x10 }, { 0x07, 0x10 }, { 0x04, 0x00 },\
{ 0x05, 0x00 }, { 0x0b, 0x00 },
/* enter finger detection mode */
{ 0x15, 0x20 }, { 0x30, 0xe1 }, { 0x15, 0x24 }, { 0x15, 0x04 },
{ 0x15, 0x84 },
{ 0x08, 0x00 }, { 0x10, 0x00 }, { 0x12, 0x01 }, { 0x11, 0xbf },
{ 0x12, 0x01 }, { 0x07, 0x10 }, { 0x07, 0x10 }, { 0x04, 0x00 }, \
{ 0x05, 0x00 }, { 0x0b, 0x00 },
/* enter finger detection mode */
{ 0x15, 0x20 }, { 0x30, 0xe1 }, { 0x15, 0x24 }, { 0x15, 0x04 },
{ 0x15, 0x84 },
};
/***** CAPTURE MODE *****/
static const struct sonly_regwrite capsm_2016_writev[] = {
/* enter capture mode */
{ 0x09, 0x28 }, { 0x13, 0x55 }, { 0x0b, 0x80 }, { 0x04, 0x00 },
{ 0x05, 0x00 },
/* enter capture mode */
{ 0x09, 0x28 }, { 0x13, 0x55 }, { 0x0b, 0x80 }, { 0x04, 0x00 },
{ 0x05, 0x00 },
};
static const struct sonly_regwrite capsm_1000_writev[] = {
{ 0x08, 0x80 }, { 0x13, 0x55 }, { 0x0b, 0x80 }, /* Enter capture mode */
{ 0x08, 0x80 }, { 0x13, 0x55 }, { 0x0b, 0x80 }, /* Enter capture mode */
};
static const struct sonly_regwrite capsm_1001_writev_1[] = {
{ 0x1a, 0x02 },
{ 0x4a, 0x9d },
{ 0x4e, 0x05 },
{ 0x1a, 0x02 },
{ 0x4a, 0x9d },
{ 0x4e, 0x05 },
};
static const struct sonly_regwrite capsm_1001_writev_2[] = {
{ 0x4d, 0xc0 }, { 0x4e, 0x09 },
{ 0x4d, 0xc0 }, { 0x4e, 0x09 },
};
static const struct sonly_regwrite capsm_1001_writev_3[] = {
{ 0x4a, 0x9c },
{ 0x1a, 0x00 },
{ 0x0b, 0x00 },
{ 0x04, 0x00 },
{ 0x05, 0x00 },
{ 0x1a, 0x02 },
{ 0x4a, 0x9d },
{ 0x4d, 0x40 }, { 0x4e, 0x09 },
{ 0x4a, 0x9c },
{ 0x1a, 0x00 },
{ 0x0b, 0x00 },
{ 0x04, 0x00 },
{ 0x05, 0x00 },
{ 0x1a, 0x02 },
{ 0x4a, 0x9d },
{ 0x4d, 0x40 }, { 0x4e, 0x09 },
};
static const struct sonly_regwrite capsm_1001_writev_4[] = {
{ 0x4a, 0x9c },
{ 0x1a, 0x00 },
{ 0x1a, 0x02 },
{ 0x4a, 0x9d },
{ 0x4e, 0x08 },
{ 0x4a, 0x9c },
{ 0x1a, 0x00 },
{ 0x1a, 0x02 },
{ 0x4a, 0x9d },
{ 0x4e, 0x08 },
};
static const struct sonly_regwrite capsm_1001_writev_5[] = {
{ 0x4a, 0x9c },
{ 0x1a, 0x00 },
{ 0x1a, 0x02 },
{ 0x00, 0x5f }, { 0x01, 0xee },
{ 0x03, 0x2c },
{ 0x07, 0x00 }, { 0x08, 0x00 }, { 0x09, 0x29 }, { 0x0a, 0x00 }, { 0x0b, 0x00 }, { 0x0c, 0x13 }, { 0x0d, 0x0d }, { 0x0e, 0x0e },
{ 0x0f, 0x0d }, { 0x10, 0x00 }, { 0x11, 0x8f }, { 0x12, 0x01 }, { 0x13, 0x45 },
{ 0x15, 0x26 },
{ 0x1e, 0x02 },
{ 0x20, 0x01 },
{ 0x25, 0x8f },
{ 0x27, 0x23 },
{ 0x30, 0xe0 },
{ 0x07, 0x10 },
{ 0x09, 0x21 },
{ 0x13, 0x75 },
{ 0x0b, 0x80 },
{ 0x4a, 0x9c },
{ 0x1a, 0x00 },
{ 0x1a, 0x02 },
{ 0x00, 0x5f }, { 0x01, 0xee },
{ 0x03, 0x2c },
{ 0x07, 0x00 }, { 0x08, 0x00 }, { 0x09, 0x29 }, { 0x0a, 0x00 }, { 0x0b, 0x00 }, { 0x0c, 0x13 }, { 0x0d, 0x0d }, { 0x0e, 0x0e },
{ 0x0f, 0x0d }, { 0x10, 0x00 }, { 0x11, 0x8f }, { 0x12, 0x01 }, { 0x13, 0x45 },
{ 0x15, 0x26 },
{ 0x1e, 0x02 },
{ 0x20, 0x01 },
{ 0x25, 0x8f },
{ 0x27, 0x23 },
{ 0x30, 0xe0 },
{ 0x07, 0x10 },
{ 0x09, 0x21 },
{ 0x13, 0x75 },
{ 0x0b, 0x80 },
};
/***** DEINITIALIZATION *****/
static const struct sonly_regwrite deinitsm_2016_writev[] = {
/* reset + enter low power mode */
{ 0x0b, 0x00 }, { 0x09, 0x20 }, { 0x13, 0x45 }, { 0x13, 0x45 },
/* reset + enter low power mode */
{ 0x0b, 0x00 }, { 0x09, 0x20 }, { 0x13, 0x45 }, { 0x13, 0x45 },
};
static const struct sonly_regwrite deinitsm_1000_writev[] = {
{ 0x15, 0x26 }, { 0x30, 0xe0 }, /* Disable finger detection */
{ 0x15, 0x26 }, { 0x30, 0xe0 }, /* Disable finger detection */
{ 0x0b, 0x00 }, { 0x13, 0x45 }, { 0x08, 0x00 }, /* Disable capture mode */
{ 0x0b, 0x00 }, { 0x13, 0x45 }, { 0x08, 0x00 }, /* Disable capture mode */
};
static const struct sonly_regwrite deinitsm_1001_writev[] = {
{ 0x0b, 0x00 },
{ 0x13, 0x45 },
{ 0x09, 0x29 },
{ 0x1a, 0x00 },
{ 0x0b, 0x00 },
{ 0x13, 0x45 },
{ 0x09, 0x29 },
{ 0x1a, 0x00 },
};
/***** INITIALIZATION *****/
static const struct sonly_regwrite initsm_2016_writev_1[] = {
{ 0x49, 0x00 },
/* BSAPI writes different values to register 0x3e each time. I initially
* thought this was some kind of clever authentication, but just blasting
* these sniffed values each time seems to work. */
{ 0x3e, 0x83 }, { 0x3e, 0x4f }, { 0x3e, 0x0f }, { 0x3e, 0xbf },
{ 0x3e, 0x45 }, { 0x3e, 0x35 }, { 0x3e, 0x1c }, { 0x3e, 0xae },
{ 0x49, 0x00 },
{ 0x44, 0x01 }, { 0x43, 0x06 }, { 0x43, 0x05 }, { 0x43, 0x04 },
{ 0x44, 0x00 }, { 0x0b, 0x00 },
/* BSAPI writes different values to register 0x3e each time. I initially
* thought this was some kind of clever authentication, but just blasting
* these sniffed values each time seems to work. */
{ 0x3e, 0x83 }, { 0x3e, 0x4f }, { 0x3e, 0x0f }, { 0x3e, 0xbf },
{ 0x3e, 0x45 }, { 0x3e, 0x35 }, { 0x3e, 0x1c }, { 0x3e, 0xae },
{ 0x44, 0x01 }, { 0x43, 0x06 }, { 0x43, 0x05 }, { 0x43, 0x04 },
{ 0x44, 0x00 }, { 0x0b, 0x00 },
};
static const struct sonly_regwrite initsm_1000_writev_1[] = {
{ 0x49, 0x00 }, /* Encryption disabled */
{ 0x49, 0x00 }, /* Encryption disabled */
/* Setting encryption key. Doesn't need to be random since we don't use any
* encryption. */
{ 0x3e, 0x7f }, { 0x3e, 0x7f }, { 0x3e, 0x7f }, { 0x3e, 0x7f },
{ 0x3e, 0x7f }, { 0x3e, 0x7f }, { 0x3e, 0x7f }, { 0x3e, 0x7f },
/* Setting encryption key. Doesn't need to be random since we don't use any
* encryption. */
{ 0x3e, 0x7f }, { 0x3e, 0x7f }, { 0x3e, 0x7f }, { 0x3e, 0x7f },
{ 0x3e, 0x7f }, { 0x3e, 0x7f }, { 0x3e, 0x7f }, { 0x3e, 0x7f },
{ 0x04, 0x00 }, { 0x05, 0x00 },
{ 0x04, 0x00 }, { 0x05, 0x00 },
{ 0x0b, 0x00 }, { 0x08, 0x00 }, /* Initialize capture control registers */
{ 0x0b, 0x00 }, { 0x08, 0x00 }, /* Initialize capture control registers */
};
static const struct sonly_regwrite initsm_1001_writev_1[] = {
{ 0x4a, 0x9d },
{ 0x4f, 0x06 },
{ 0x4f, 0x05 },
{ 0x4f, 0x04 },
{ 0x4a, 0x9c },
{ 0x3e, 0xa6 },
{ 0x3e, 0x01 },
{ 0x3e, 0x68 },
{ 0x3e, 0xfd },
{ 0x3e, 0x72 },
{ 0x3e, 0xef },
{ 0x3e, 0x5d },
{ 0x3e, 0xc5 },
{ 0x1a, 0x02 },
{ 0x4a, 0x9d },
{ 0x4c, 0x1f }, { 0x4d, 0xb8 }, { 0x4e, 0x00 },
{ 0x4a, 0x9d },
{ 0x4f, 0x06 },
{ 0x4f, 0x05 },
{ 0x4f, 0x04 },
{ 0x4a, 0x9c },
{ 0x3e, 0xa6 },
{ 0x3e, 0x01 },
{ 0x3e, 0x68 },
{ 0x3e, 0xfd },
{ 0x3e, 0x72 },
{ 0x3e, 0xef },
{ 0x3e, 0x5d },
{ 0x3e, 0xc5 },
{ 0x1a, 0x02 },
{ 0x4a, 0x9d },
{ 0x4c, 0x1f }, { 0x4d, 0xb8 }, { 0x4e, 0x00 },
};
static const struct sonly_regwrite initsm_1001_writev_2[] = {
{ 0x4c, 0x03 }, { 0x4d, 0xb8 }, { 0x4e, 0x00 },
{ 0x4c, 0x03 }, { 0x4d, 0xb8 }, { 0x4e, 0x00 },
};
static const struct sonly_regwrite initsm_1001_writev_3[] = {
{ 0x4a, 0x9c },
{ 0x1a, 0x00 },
{ 0x1a, 0x02 },
{ 0x4a, 0x9d },
{ 0x4c, 0xff }, { 0x4d, 0xc0 }, { 0x4e, 0x00 },
{ 0x4a, 0x9c },
{ 0x1a, 0x00 },
{ 0x1a, 0x02 },
{ 0x4a, 0x9d },
{ 0x4c, 0xff }, { 0x4d, 0xc0 }, { 0x4e, 0x00 },
};
static const struct sonly_regwrite initsm_1001_writev_4[] = {
{ 0x4a, 0x9c },
{ 0x1a, 0x00 },
{ 0x09, 0x27 },
{ 0x1a, 0x02 },
{ 0x49, 0x01 },
{ 0x47, 0x02 },
{ 0x47, 0x02 },
{ 0x47, 0x02 },
{ 0x47, 0x02 },
{ 0x47, 0x02 },
{ 0x47, 0x02 },
{ 0x47, 0x02 },
{ 0x47, 0x0a },
{ 0x47, 0x00 },
{ 0x47, 0x04 },
{ 0x47, 0x04 },
{ 0x47, 0x04 },
{ 0x47, 0x04 },
{ 0x47, 0x04 },
{ 0x47, 0x04 },
{ 0x47, 0x04 },
{ 0x47, 0x04 },
{ 0x47, 0x02 },
{ 0x47, 0x02 },
{ 0x47, 0x02 },
{ 0x47, 0x02 },
{ 0x47, 0x02 },
{ 0x47, 0x02 },
{ 0x47, 0x02 },
{ 0x47, 0x0a },
{ 0x47, 0x00 },
{ 0x47, 0x04 },
{ 0x47, 0x04 },
{ 0x47, 0x04 },
{ 0x47, 0x04 },
{ 0x47, 0x04 },
{ 0x47, 0x04 },
{ 0x47, 0x04 },
{ 0x47, 0x04 },
{ 0x47, 0x02 },
{ 0x47, 0x02 },
{ 0x47, 0x02 },
{ 0x47, 0x02 },
{ 0x47, 0x02 },
{ 0x47, 0x02 },
{ 0x47, 0x02 },
{ 0x47, 0x0a },
{ 0x47, 0x00 },
{ 0x47, 0x04 },
{ 0x47, 0x04 },
{ 0x47, 0x04 },
{ 0x47, 0x04 },
{ 0x47, 0x04 },
{ 0x47, 0x04 },
{ 0x47, 0x04 },
{ 0x47, 0x04 },
{ 0x47, 0x02 },
{ 0x47, 0x02 },
{ 0x47, 0x02 },
{ 0x47, 0x02 },
{ 0x47, 0x02 },
{ 0x47, 0x02 },
{ 0x47, 0x02 },
{ 0x47, 0x0a },
{ 0x47, 0x00 },
{ 0x47, 0x04 },
{ 0x47, 0x04 },
{ 0x47, 0x04 },
{ 0x47, 0x04 },
{ 0x47, 0x04 },
{ 0x47, 0x04 },
{ 0x47, 0x04 },
{ 0x47, 0x04 },
{ 0x49, 0x00 },
{ 0x3e, 0x90 },
{ 0x3e, 0xbd },
{ 0x3e, 0xbf },
{ 0x3e, 0x48 },
{ 0x3e, 0x2a },
{ 0x3e, 0xe3 },
{ 0x3e, 0xd2 },
{ 0x3e, 0x58 },
{ 0x09, 0x2f },
{ 0x1a, 0x00 },
{ 0x1a, 0x02 },
{ 0x4a, 0x9d },
{ 0x4d, 0x40 }, { 0x4e, 0x03 },
{ 0x4a, 0x9c },
{ 0x1a, 0x00 },
{ 0x09, 0x27 },
{ 0x1a, 0x02 },
{ 0x49, 0x01 },
{ 0x47, 0x02 },
{ 0x47, 0x02 },
{ 0x47, 0x02 },
{ 0x47, 0x02 },
{ 0x47, 0x02 },
{ 0x47, 0x02 },
{ 0x47, 0x02 },
{ 0x47, 0x0a },
{ 0x47, 0x00 },
{ 0x47, 0x04 },
{ 0x47, 0x04 },
{ 0x47, 0x04 },
{ 0x47, 0x04 },
{ 0x47, 0x04 },
{ 0x47, 0x04 },
{ 0x47, 0x04 },
{ 0x47, 0x04 },
{ 0x47, 0x02 },
{ 0x47, 0x02 },
{ 0x47, 0x02 },
{ 0x47, 0x02 },
{ 0x47, 0x02 },
{ 0x47, 0x02 },
{ 0x47, 0x02 },
{ 0x47, 0x0a },
{ 0x47, 0x00 },
{ 0x47, 0x04 },
{ 0x47, 0x04 },
{ 0x47, 0x04 },
{ 0x47, 0x04 },
{ 0x47, 0x04 },
{ 0x47, 0x04 },
{ 0x47, 0x04 },
{ 0x47, 0x04 },
{ 0x47, 0x02 },
{ 0x47, 0x02 },
{ 0x47, 0x02 },
{ 0x47, 0x02 },
{ 0x47, 0x02 },
{ 0x47, 0x02 },
{ 0x47, 0x02 },
{ 0x47, 0x0a },
{ 0x47, 0x00 },
{ 0x47, 0x04 },
{ 0x47, 0x04 },
{ 0x47, 0x04 },
{ 0x47, 0x04 },
{ 0x47, 0x04 },
{ 0x47, 0x04 },
{ 0x47, 0x04 },
{ 0x47, 0x04 },
{ 0x47, 0x02 },
{ 0x47, 0x02 },
{ 0x47, 0x02 },
{ 0x47, 0x02 },
{ 0x47, 0x02 },
{ 0x47, 0x02 },
{ 0x47, 0x02 },
{ 0x47, 0x0a },
{ 0x47, 0x00 },
{ 0x47, 0x04 },
{ 0x47, 0x04 },
{ 0x47, 0x04 },
{ 0x47, 0x04 },
{ 0x47, 0x04 },
{ 0x47, 0x04 },
{ 0x47, 0x04 },
{ 0x47, 0x04 },
{ 0x49, 0x00 },
{ 0x3e, 0x90 },
{ 0x3e, 0xbd },
{ 0x3e, 0xbf },
{ 0x3e, 0x48 },
{ 0x3e, 0x2a },
{ 0x3e, 0xe3 },
{ 0x3e, 0xd2 },
{ 0x3e, 0x58 },
{ 0x09, 0x2f },
{ 0x1a, 0x00 },
{ 0x1a, 0x02 },
{ 0x4a, 0x9d },
{ 0x4d, 0x40 }, { 0x4e, 0x03 },
};
static const struct sonly_regwrite initsm_1001_writev_5[] = {
{ 0x4a, 0x9c },
{ 0x1a, 0x00 },
{ 0x4a, 0x9c },
{ 0x1a, 0x00 },
};

View file

@ -29,412 +29,456 @@
#define UPEKET_EP_OUT (2 | FPI_USB_ENDPOINT_OUT)
#define BULK_TIMEOUT 4000
struct _FpiDeviceUpektc {
FpImageDevice parent;
struct _FpiDeviceUpektc
{
FpImageDevice parent;
gboolean deactivating;
const struct setup_cmd *setup_commands;
size_t setup_commands_len;
int ep_in;
int ep_out;
int init_idx;
int sum_threshold;
gboolean deactivating;
const struct setup_cmd *setup_commands;
size_t setup_commands_len;
int ep_in;
int ep_out;
int init_idx;
int sum_threshold;
};
G_DECLARE_FINAL_TYPE(FpiDeviceUpektc, fpi_device_upektc, FPI, DEVICE_UPEKTC,
FpImageDevice);
G_DEFINE_TYPE(FpiDeviceUpektc, fpi_device_upektc, FP_TYPE_IMAGE_DEVICE);
G_DECLARE_FINAL_TYPE (FpiDeviceUpektc, fpi_device_upektc, FPI, DEVICE_UPEKTC,
FpImageDevice);
G_DEFINE_TYPE (FpiDeviceUpektc, fpi_device_upektc, FP_TYPE_IMAGE_DEVICE);
enum upektc_driver_data {
UPEKTC_2015,
UPEKTC_3001,
UPEKTC_2015,
UPEKTC_3001,
};
static void start_capture(FpImageDevice *dev);
static void complete_deactivation(FpImageDevice *dev, GError *error);
static void start_finger_detection(FpImageDevice *dev);
static void start_capture (FpImageDevice *dev);
static void complete_deactivation (FpImageDevice *dev,
GError *error);
static void start_finger_detection (FpImageDevice *dev);
/****** INITIALIZATION/DEINITIALIZATION ******/
enum activate_states {
WRITE_INIT,
READ_DATA,
ACTIVATE_NUM_STATES,
WRITE_INIT,
READ_DATA,
ACTIVATE_NUM_STATES,
};
static void
upektc_next_init_cmd(FpiSsm *ssm,
FpImageDevice *dev)
upektc_next_init_cmd (FpiSsm *ssm,
FpImageDevice *dev)
{
FpiDeviceUpektc *self = FPI_DEVICE_UPEKTC(dev);
FpiDeviceUpektc *self = FPI_DEVICE_UPEKTC (dev);
self->init_idx += 1;
if (self->init_idx == self->setup_commands_len)
fpi_ssm_mark_completed(ssm);
else
fpi_ssm_jump_to_state(ssm, WRITE_INIT);
self->init_idx += 1;
if (self->init_idx == self->setup_commands_len)
fpi_ssm_mark_completed (ssm);
else
fpi_ssm_jump_to_state (ssm, WRITE_INIT);
}
static void write_init_cb(FpiUsbTransfer *transfer, FpDevice *device,
gpointer user_data, GError *error)
static void
write_init_cb (FpiUsbTransfer *transfer, FpDevice *device,
gpointer user_data, GError *error)
{
FpImageDevice *dev = FP_IMAGE_DEVICE(device);
FpiDeviceUpektc *self = FPI_DEVICE_UPEKTC(dev);
FpImageDevice *dev = FP_IMAGE_DEVICE (device);
FpiDeviceUpektc *self = FPI_DEVICE_UPEKTC (dev);
if (!error) {
if (self->setup_commands[self->init_idx].response_len)
fpi_ssm_next_state(transfer->ssm);
else
upektc_next_init_cmd(transfer->ssm, dev);
} else {
fpi_ssm_mark_failed(transfer->ssm, error);
}
if (!error)
{
if (self->setup_commands[self->init_idx].response_len)
fpi_ssm_next_state (transfer->ssm);
else
upektc_next_init_cmd (transfer->ssm, dev);
}
else
{
fpi_ssm_mark_failed (transfer->ssm, error);
}
}
static void read_init_data_cb(FpiUsbTransfer *transfer, FpDevice *device,
gpointer user_data, GError *error)
static void
read_init_data_cb (FpiUsbTransfer *transfer, FpDevice *device,
gpointer user_data, GError *error)
{
FpImageDevice *dev = FP_IMAGE_DEVICE(device);
FpImageDevice *dev = FP_IMAGE_DEVICE (device);
if (!error)
upektc_next_init_cmd(transfer->ssm, dev);
else
fpi_ssm_mark_failed(transfer->ssm, error);
if (!error)
upektc_next_init_cmd (transfer->ssm, dev);
else
fpi_ssm_mark_failed (transfer->ssm, error);
}
static void activate_run_state(FpiSsm *ssm, FpDevice *dev, void *user_data)
static void
activate_run_state (FpiSsm *ssm, FpDevice *dev, void *user_data)
{
FpiDeviceUpektc *self = FPI_DEVICE_UPEKTC(dev);
FpiDeviceUpektc *self = FPI_DEVICE_UPEKTC (dev);
switch (fpi_ssm_get_cur_state(ssm)) {
case WRITE_INIT:
{
FpiUsbTransfer *transfer = fpi_usb_transfer_new(dev);
switch (fpi_ssm_get_cur_state (ssm))
{
case WRITE_INIT:
{
FpiUsbTransfer *transfer = fpi_usb_transfer_new (dev);
fpi_usb_transfer_fill_bulk_full(transfer,
self->ep_out,
(unsigned char *) self->setup_commands[self->init_idx].cmd,
UPEKTC_CMD_LEN,
NULL);
transfer->ssm = ssm;
transfer->short_is_error = TRUE;
fpi_usb_transfer_submit(transfer, BULK_TIMEOUT, NULL,
write_init_cb, NULL);
fpi_usb_transfer_unref(transfer);
}
break;
case READ_DATA:
{
FpiUsbTransfer *transfer = fpi_usb_transfer_new(dev);
fpi_usb_transfer_fill_bulk_full (transfer,
self->ep_out,
(unsigned char *) self->setup_commands[self->init_idx].cmd,
UPEKTC_CMD_LEN,
NULL);
transfer->ssm = ssm;
transfer->short_is_error = TRUE;
fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
write_init_cb, NULL);
fpi_usb_transfer_unref (transfer);
}
break;
fpi_usb_transfer_fill_bulk (transfer,
self->ep_in,
self->setup_commands[self->init_idx].response_len);
transfer->ssm = ssm;
fpi_usb_transfer_submit(transfer, BULK_TIMEOUT, NULL,
read_init_data_cb, NULL);
fpi_usb_transfer_unref(transfer);
}
break;
}
case READ_DATA:
{
FpiUsbTransfer *transfer = fpi_usb_transfer_new (dev);
fpi_usb_transfer_fill_bulk (transfer,
self->ep_in,
self->setup_commands[self->init_idx].response_len);
transfer->ssm = ssm;
fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
read_init_data_cb, NULL);
fpi_usb_transfer_unref (transfer);
}
break;
}
}
static void activate_sm_complete(FpiSsm *ssm, FpDevice *_dev,
void *user_data, GError *error)
static void
activate_sm_complete (FpiSsm *ssm, FpDevice *_dev,
void *user_data, GError *error)
{
FpImageDevice *dev = FP_IMAGE_DEVICE(_dev);
FpImageDevice *dev = FP_IMAGE_DEVICE (_dev);
fpi_image_device_activate_complete(dev, error);
fpi_image_device_activate_complete (dev, error);
if (!error)
start_finger_detection(dev);
fpi_ssm_free(ssm);
if (!error)
start_finger_detection (dev);
fpi_ssm_free (ssm);
}
/****** FINGER PRESENCE DETECTION ******/
static int finger_present(unsigned char *img, size_t len, int sum_threshold)
static int
finger_present (unsigned char *img, size_t len, int sum_threshold)
{
int i, sum;
int i, sum;
sum = 0;
sum = 0;
for (i = 0; i < len; i++) {
if (img[i] < 160) {
sum++;
}
}
for (i = 0; i < len; i++)
if (img[i] < 160)
sum++;
fp_dbg("finger_present: sum is %d\n", sum);
return sum < sum_threshold ? 0 : 1;
fp_dbg ("finger_present: sum is %d\n", sum);
return sum < sum_threshold ? 0 : 1;
}
static void finger_det_data_cb(FpiUsbTransfer *transfer, FpDevice *device,
gpointer user_data, GError *error)
static void
finger_det_data_cb (FpiUsbTransfer *transfer, FpDevice *device,
gpointer user_data, GError *error)
{
FpImageDevice *dev = FP_IMAGE_DEVICE(device);
FpiDeviceUpektc *self = FPI_DEVICE_UPEKTC(dev);
FpImageDevice *dev = FP_IMAGE_DEVICE (device);
FpiDeviceUpektc *self = FPI_DEVICE_UPEKTC (dev);
if (error) {
fp_dbg("data transfer status %s\n", error->message);
fpi_image_device_session_error(dev, error);
return;
}
if (error)
{
fp_dbg ("data transfer status %s\n", error->message);
fpi_image_device_session_error (dev, error);
return;
}
if (finger_present(transfer->buffer, IMAGE_SIZE, self->sum_threshold)) {
/* finger present, start capturing */
fpi_image_device_report_finger_status(dev, TRUE);
start_capture(dev);
} else {
/* no finger, poll for a new histogram */
start_finger_detection(dev);
}
if (finger_present (transfer->buffer, IMAGE_SIZE, self->sum_threshold))
{
/* finger present, start capturing */
fpi_image_device_report_finger_status (dev, TRUE);
start_capture (dev);
}
else
{
/* no finger, poll for a new histogram */
start_finger_detection (dev);
}
}
static void finger_det_cmd_cb(FpiUsbTransfer *t, FpDevice *device,
gpointer user_data, GError *error)
static void
finger_det_cmd_cb (FpiUsbTransfer *t, FpDevice *device,
gpointer user_data, GError *error)
{
FpiUsbTransfer *transfer;
FpImageDevice *dev = FP_IMAGE_DEVICE (device);
FpiDeviceUpektc *self = FPI_DEVICE_UPEKTC(dev);
FpiUsbTransfer *transfer;
FpImageDevice *dev = FP_IMAGE_DEVICE (device);
FpiDeviceUpektc *self = FPI_DEVICE_UPEKTC (dev);
if (error) {
fp_dbg("req transfer status %s\n", error->message);
fpi_image_device_session_error(dev, error);
return;
}
if (error)
{
fp_dbg ("req transfer status %s\n", error->message);
fpi_image_device_session_error (dev, error);
return;
}
transfer = fpi_usb_transfer_new (device);
transfer->short_is_error = TRUE;
fpi_usb_transfer_fill_bulk(transfer, self->ep_in,
IMAGE_SIZE);
fpi_usb_transfer_submit(transfer, BULK_TIMEOUT, NULL,
finger_det_data_cb, NULL);
fpi_usb_transfer_unref(transfer);
transfer = fpi_usb_transfer_new (device);
transfer->short_is_error = TRUE;
fpi_usb_transfer_fill_bulk (transfer, self->ep_in,
IMAGE_SIZE);
fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
finger_det_data_cb, NULL);
fpi_usb_transfer_unref (transfer);
}
static void start_finger_detection(FpImageDevice *dev)
static void
start_finger_detection (FpImageDevice *dev)
{
FpiDeviceUpektc *self = FPI_DEVICE_UPEKTC(dev);
FpiUsbTransfer *transfer;
G_DEBUG_HERE();
FpiDeviceUpektc *self = FPI_DEVICE_UPEKTC (dev);
FpiUsbTransfer *transfer;
if (self->deactivating) {
complete_deactivation(dev, NULL);
return;
}
G_DEBUG_HERE ();
transfer = fpi_usb_transfer_new(FP_DEVICE(dev));
transfer->short_is_error = TRUE;
fpi_usb_transfer_fill_bulk_full(transfer, self->ep_out,
(unsigned char *)scan_cmd,
UPEKTC_CMD_LEN, NULL);
fpi_usb_transfer_submit(transfer, BULK_TIMEOUT, NULL,
finger_det_cmd_cb, NULL);
fpi_usb_transfer_unref(transfer);
if (self->deactivating)
{
complete_deactivation (dev, NULL);
return;
}
transfer = fpi_usb_transfer_new (FP_DEVICE (dev));
transfer->short_is_error = TRUE;
fpi_usb_transfer_fill_bulk_full (transfer, self->ep_out,
(unsigned char *) scan_cmd,
UPEKTC_CMD_LEN, NULL);
fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
finger_det_cmd_cb, NULL);
fpi_usb_transfer_unref (transfer);
}
/****** CAPTURE ******/
enum capture_states {
CAPTURE_WRITE_CMD,
CAPTURE_READ_DATA,
CAPTURE_NUM_STATES,
CAPTURE_WRITE_CMD,
CAPTURE_READ_DATA,
CAPTURE_NUM_STATES,
};
static void capture_cmd_cb(FpiUsbTransfer *transfer, FpDevice *device,
gpointer user_data, GError *error)
static void
capture_cmd_cb (FpiUsbTransfer *transfer, FpDevice *device,
gpointer user_data, GError *error)
{
if (!error) {
fpi_ssm_next_state(transfer->ssm);
} else {
fpi_ssm_mark_failed(transfer->ssm, error);
}
if (!error)
fpi_ssm_next_state (transfer->ssm);
else
fpi_ssm_mark_failed (transfer->ssm, error);
}
static void capture_read_data_cb(FpiUsbTransfer *transfer, FpDevice *device,
gpointer user_data, GError *error)
static void
capture_read_data_cb (FpiUsbTransfer *transfer, FpDevice *device,
gpointer user_data, GError *error)
{
FpImageDevice *dev = FP_IMAGE_DEVICE(device);
FpImage *img;
FpImageDevice *dev = FP_IMAGE_DEVICE (device);
FpImage *img;
if (error) {
fp_dbg("request is not completed, %s", error->message);
fpi_ssm_mark_failed(transfer->ssm, error);
return;
}
if (error)
{
fp_dbg ("request is not completed, %s", error->message);
fpi_ssm_mark_failed (transfer->ssm, error);
return;
}
img = fp_image_new(IMAGE_WIDTH, IMAGE_HEIGHT);
memcpy(img->data, transfer->buffer, IMAGE_SIZE);
fpi_image_device_image_captured(dev, img);
fpi_image_device_report_finger_status(dev, FALSE);
fpi_ssm_mark_completed(transfer->ssm);
img = fp_image_new (IMAGE_WIDTH, IMAGE_HEIGHT);
memcpy (img->data, transfer->buffer, IMAGE_SIZE);
fpi_image_device_image_captured (dev, img);
fpi_image_device_report_finger_status (dev, FALSE);
fpi_ssm_mark_completed (transfer->ssm);
}
static void capture_run_state(FpiSsm *ssm, FpDevice *_dev, void *user_data)
static void
capture_run_state (FpiSsm *ssm, FpDevice *_dev, void *user_data)
{
FpiDeviceUpektc *self = FPI_DEVICE_UPEKTC(_dev);
FpiDeviceUpektc *self = FPI_DEVICE_UPEKTC (_dev);
switch (fpi_ssm_get_cur_state(ssm)) {
case CAPTURE_WRITE_CMD:
{
FpiUsbTransfer *transfer = fpi_usb_transfer_new(_dev);
switch (fpi_ssm_get_cur_state (ssm))
{
case CAPTURE_WRITE_CMD:
{
FpiUsbTransfer *transfer = fpi_usb_transfer_new (_dev);
fpi_usb_transfer_fill_bulk_full(transfer, self->ep_out,
(unsigned char *)scan_cmd,
UPEKTC_CMD_LEN, NULL);
transfer->ssm = ssm;
transfer->short_is_error = TRUE;
fpi_usb_transfer_submit(transfer, BULK_TIMEOUT, NULL,
capture_cmd_cb, NULL);
fpi_usb_transfer_unref(transfer);
}
break;
case CAPTURE_READ_DATA:
{
FpiUsbTransfer *transfer = fpi_usb_transfer_new(_dev);
fpi_usb_transfer_fill_bulk_full (transfer, self->ep_out,
(unsigned char *) scan_cmd,
UPEKTC_CMD_LEN, NULL);
transfer->ssm = ssm;
transfer->short_is_error = TRUE;
fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
capture_cmd_cb, NULL);
fpi_usb_transfer_unref (transfer);
}
break;
fpi_usb_transfer_fill_bulk(transfer, self->ep_in,
IMAGE_SIZE);
transfer->ssm = ssm;
transfer->short_is_error = TRUE;
fpi_usb_transfer_submit(transfer, BULK_TIMEOUT, NULL,
capture_read_data_cb, NULL);
fpi_usb_transfer_unref(transfer);
}
break;
};
case CAPTURE_READ_DATA:
{
FpiUsbTransfer *transfer = fpi_usb_transfer_new (_dev);
fpi_usb_transfer_fill_bulk (transfer, self->ep_in,
IMAGE_SIZE);
transfer->ssm = ssm;
transfer->short_is_error = TRUE;
fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
capture_read_data_cb, NULL);
fpi_usb_transfer_unref (transfer);
}
break;
}
;
}
static void capture_sm_complete(FpiSsm *ssm, FpDevice *_dev, void *user_data,
GError *error)
static void
capture_sm_complete (FpiSsm *ssm, FpDevice *_dev, void *user_data,
GError *error)
{
FpImageDevice *dev = user_data;
FpiDeviceUpektc *self = FPI_DEVICE_UPEKTC(_dev);
FpImageDevice *dev = user_data;
FpiDeviceUpektc *self = FPI_DEVICE_UPEKTC (_dev);
fp_dbg("Capture completed");
if (self->deactivating)
complete_deactivation(dev, error);
else if (error)
fpi_image_device_session_error(dev, error);
else
start_finger_detection(dev);
fp_dbg ("Capture completed");
if (self->deactivating)
complete_deactivation (dev, error);
else if (error)
fpi_image_device_session_error (dev, error);
else
start_finger_detection (dev);
fpi_ssm_free(ssm);
fpi_ssm_free (ssm);
}
static void start_capture(FpImageDevice *dev)
static void
start_capture (FpImageDevice *dev)
{
FpiDeviceUpektc *self = FPI_DEVICE_UPEKTC(dev);
FpiSsm *ssm;
FpiDeviceUpektc *self = FPI_DEVICE_UPEKTC (dev);
FpiSsm *ssm;
if (self->deactivating) {
complete_deactivation(dev, NULL);
return;
}
if (self->deactivating)
{
complete_deactivation (dev, NULL);
return;
}
ssm = fpi_ssm_new(FP_DEVICE(dev), capture_run_state,
CAPTURE_NUM_STATES, dev);
G_DEBUG_HERE();
fpi_ssm_start(ssm, capture_sm_complete);
ssm = fpi_ssm_new (FP_DEVICE (dev), capture_run_state,
CAPTURE_NUM_STATES, dev);
G_DEBUG_HERE ();
fpi_ssm_start (ssm, capture_sm_complete);
}
static void dev_activate(FpImageDevice *dev)
static void
dev_activate (FpImageDevice *dev)
{
FpiDeviceUpektc *self = FPI_DEVICE_UPEKTC(dev);
FpiSsm *ssm = fpi_ssm_new(FP_DEVICE(dev), activate_run_state,
ACTIVATE_NUM_STATES, dev);
self->init_idx = 0;
fpi_ssm_start(ssm, activate_sm_complete);
FpiDeviceUpektc *self = FPI_DEVICE_UPEKTC (dev);
FpiSsm *ssm = fpi_ssm_new (FP_DEVICE (dev), activate_run_state,
ACTIVATE_NUM_STATES, dev);
self->init_idx = 0;
fpi_ssm_start (ssm, activate_sm_complete);
}
static void dev_deactivate(FpImageDevice *dev)
static void
dev_deactivate (FpImageDevice *dev)
{
FpiDeviceUpektc *self = FPI_DEVICE_UPEKTC(dev);
FpiDeviceUpektc *self = FPI_DEVICE_UPEKTC (dev);
self->deactivating = TRUE;
self->deactivating = TRUE;
}
static void complete_deactivation(FpImageDevice *dev, GError *error)
static void
complete_deactivation (FpImageDevice *dev, GError *error)
{
FpiDeviceUpektc *self = FPI_DEVICE_UPEKTC(dev);
G_DEBUG_HERE();
FpiDeviceUpektc *self = FPI_DEVICE_UPEKTC (dev);
self->deactivating = FALSE;
fpi_image_device_deactivate_complete(dev, error);
G_DEBUG_HERE ();
self->deactivating = FALSE;
fpi_image_device_deactivate_complete (dev, error);
}
static void dev_init(FpImageDevice *dev)
static void
dev_init (FpImageDevice *dev)
{
GError *error = NULL;
FpiDeviceUpektc *self = FPI_DEVICE_UPEKTC(dev);
guint64 driver_data = fpi_device_get_driver_data (FP_DEVICE (dev));
GError *error = NULL;
FpiDeviceUpektc *self = FPI_DEVICE_UPEKTC (dev);
guint64 driver_data = fpi_device_get_driver_data (FP_DEVICE (dev));
/* TODO check that device has endpoints we're using */
/* TODO check that device has endpoints we're using */
if (!g_usb_device_claim_interface(fpi_device_get_usb_device(FP_DEVICE(dev)), 0, 0, &error)) {
fpi_image_device_open_complete(dev, error);
return;
}
if (!g_usb_device_claim_interface (fpi_device_get_usb_device (FP_DEVICE (dev)), 0, 0, &error))
{
fpi_image_device_open_complete (dev, error);
return;
}
switch (driver_data) {
case UPEKTC_2015:
self->ep_in = UPEKTC_EP_IN;
self->ep_out = UPEKTC_EP_OUT;
self->setup_commands = upektc_setup_commands;
self->setup_commands_len = G_N_ELEMENTS(upektc_setup_commands);
self->sum_threshold = UPEKTC_SUM_THRESHOLD;
break;
case UPEKTC_3001:
self->ep_in = UPEKET_EP_IN;
self->ep_out = UPEKET_EP_OUT;
self->setup_commands = upeket_setup_commands;
self->setup_commands_len = G_N_ELEMENTS(upeket_setup_commands);
self->sum_threshold = UPEKET_SUM_THRESHOLD;
break;
default:
fp_err("Device variant %lu is not known\n", driver_data);
g_assert_not_reached ();
fpi_image_device_open_complete(dev, fpi_device_error_new (FP_DEVICE_ERROR_GENERAL));
return;
}
fpi_image_device_open_complete(dev, NULL);
switch (driver_data)
{
case UPEKTC_2015:
self->ep_in = UPEKTC_EP_IN;
self->ep_out = UPEKTC_EP_OUT;
self->setup_commands = upektc_setup_commands;
self->setup_commands_len = G_N_ELEMENTS (upektc_setup_commands);
self->sum_threshold = UPEKTC_SUM_THRESHOLD;
break;
case UPEKTC_3001:
self->ep_in = UPEKET_EP_IN;
self->ep_out = UPEKET_EP_OUT;
self->setup_commands = upeket_setup_commands;
self->setup_commands_len = G_N_ELEMENTS (upeket_setup_commands);
self->sum_threshold = UPEKET_SUM_THRESHOLD;
break;
default:
fp_err ("Device variant %lu is not known\n", driver_data);
g_assert_not_reached ();
fpi_image_device_open_complete (dev, fpi_device_error_new (FP_DEVICE_ERROR_GENERAL));
return;
}
fpi_image_device_open_complete (dev, NULL);
}
static void dev_deinit(FpImageDevice *dev)
static void
dev_deinit (FpImageDevice *dev)
{
GError *error = NULL;
GError *error = NULL;
g_usb_device_release_interface(fpi_device_get_usb_device(FP_DEVICE(dev)),
0, 0, &error);
fpi_image_device_close_complete(dev, error);
g_usb_device_release_interface (fpi_device_get_usb_device (FP_DEVICE (dev)),
0, 0, &error);
fpi_image_device_close_complete (dev, error);
}
static const FpIdEntry id_table [ ] = {
{ .vid = 0x0483, .pid = 0x2015, .driver_data = UPEKTC_2015 },
{ .vid = 0x147e, .pid = 0x3001, .driver_data = UPEKTC_3001 },
{ .vid = 0, .pid = 0, .driver_data = 0 },
static const FpIdEntry id_table[] = {
{ .vid = 0x0483, .pid = 0x2015, .driver_data = UPEKTC_2015 },
{ .vid = 0x147e, .pid = 0x3001, .driver_data = UPEKTC_3001 },
{ .vid = 0, .pid = 0, .driver_data = 0 },
};
static void fpi_device_upektc_init(FpiDeviceUpektc *self) {
static void
fpi_device_upektc_init (FpiDeviceUpektc *self)
{
}
static void fpi_device_upektc_class_init(FpiDeviceUpektcClass *klass) {
FpDeviceClass *dev_class = FP_DEVICE_CLASS(klass);
FpImageDeviceClass *img_class = FP_IMAGE_DEVICE_CLASS(klass);
static void
fpi_device_upektc_class_init (FpiDeviceUpektcClass *klass)
{
FpDeviceClass *dev_class = FP_DEVICE_CLASS (klass);
FpImageDeviceClass *img_class = FP_IMAGE_DEVICE_CLASS (klass);
dev_class->id = "upektc";
dev_class->full_name = "UPEK TouchChip/Eikon Touch 300";
dev_class->type = FP_DEVICE_TYPE_USB;
dev_class->id_table = id_table;
dev_class->scan_type = FP_SCAN_TYPE_PRESS;
dev_class->id = "upektc";
dev_class->full_name = "UPEK TouchChip/Eikon Touch 300";
dev_class->type = FP_DEVICE_TYPE_USB;
dev_class->id_table = id_table;
dev_class->scan_type = FP_SCAN_TYPE_PRESS;
img_class->img_open = dev_init;
img_class->img_close = dev_deinit;
img_class->activate = dev_activate;
img_class->deactivate = dev_deactivate;
img_class->img_open = dev_init;
img_class->img_close = dev_deinit;
img_class->activate = dev_activate;
img_class->deactivate = dev_deactivate;
img_class->bz3_threshold = 30;
img_class->bz3_threshold = 30;
img_class->img_width = IMAGE_WIDTH;
img_class->img_height = IMAGE_HEIGHT;
img_class->img_width = IMAGE_WIDTH;
img_class->img_height = IMAGE_HEIGHT;
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -21,124 +21,124 @@
#define __UPEKTC_IMG_H
static const unsigned char upek2020_init_1[] = {
'C', 'i', 'a', 'o',
0x04,
0x00, 0x0d,
0x01, 0x00, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
0x01, 0x00, 0x00, 0x00,
0xda, 0xc1
'C', 'i', 'a', 'o',
0x04,
0x00, 0x0d,
0x01, 0x00, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
0x01, 0x00, 0x00, 0x00,
0xda, 0xc1
};
static const unsigned char upek2020_init_2[] = {
0x43, 0x69, 0x61, 0x6f,
0x07,
0x00, 0x01,
0x01,
0x3d, 0x72
0x43, 0x69, 0x61, 0x6f,
0x07,
0x00, 0x01,
0x01,
0x3d, 0x72
};
static const unsigned char upek2020_init_3[] = {
'C', 'i', 'a', 'o',
0x04,
0x00, 0x0d,
0x01, 0x00, 0xbc, 0x02, 0x00, 0x00, 0x00, 0x00, 0x01,
0x01, 0x00, 0x00, 0x00,
0x55, 0x2f
'C', 'i', 'a', 'o',
0x04,
0x00, 0x0d,
0x01, 0x00, 0xbc, 0x02, 0x00, 0x00, 0x00, 0x00, 0x01,
0x01, 0x00, 0x00, 0x00,
0x55, 0x2f
};
static const unsigned char upek2020_init_4[] = {
'C', 'i', 'a', 'o',
0x00,
0x00, 0x07,
0x28, 0x04, 0x00, 0x00, 0x00, 0x06, 0x04,
0xc0, 0xd6
'C', 'i', 'a', 'o',
0x00,
0x00, 0x07,
0x28, 0x04, 0x00, 0x00, 0x00, 0x06, 0x04,
0xc0, 0xd6
};
static const unsigned char upek2020_deinit[] = {
'C', 'i', 'a', 'o',
0x07,
0x00, 0x01,
0x01,
0x3d,
0x72
'C', 'i', 'a', 'o',
0x07,
0x00, 0x01,
0x01,
0x3d,
0x72
};
static const unsigned char upek2020_init_capture[] = {
'C', 'i', 'a', 'o',
0x00,
0x00, 0x0e, /* Seq = 7, len = 0x00e */
0x28, /* CMD = 0x28 */
0x0b, 0x00, /* Inner len = 0x000b */
0x00, 0x00,
0x0e, /* SUBCMD = 0x0e */
0x02,
0xfe, 0xff, 0xff, 0xff, /* timeout = -2 = 0xfffffffe = infinite time */
0x02,
0x00, /* Wait for acceptable finger */
0x02,
0x14, 0x9a /* CRC */
'C', 'i', 'a', 'o',
0x00,
0x00, 0x0e, /* Seq = 7, len = 0x00e */
0x28, /* CMD = 0x28 */
0x0b, 0x00, /* Inner len = 0x000b */
0x00, 0x00,
0x0e, /* SUBCMD = 0x0e */
0x02,
0xfe, 0xff, 0xff, 0xff, /* timeout = -2 = 0xfffffffe = infinite time */
0x02,
0x00, /* Wait for acceptable finger */
0x02,
0x14, 0x9a /* CRC */
};
#if 0
static const unsigned char finger_status[] = {
'C', 'i', 'a', 'o',
0x00,
0x70, 0x14, /* Seq = 7, len = 0x014 */
0x28, /* CMD = 0x28 */
0x11, 0x00, /* Inner len = 0x0011 */
0x00, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, 0x00,
0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00,
0x26, 0x03, /* CRC */
0x00, 0x00, 0x00, /* Rest is garbage */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
'C', 'i', 'a', 'o',
0x00,
0x70, 0x14, /* Seq = 7, len = 0x014 */
0x28, /* CMD = 0x28 */
0x11, 0x00, /* Inner len = 0x0011 */
0x00, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, 0x00,
0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00,
0x26, 0x03, /* CRC */
0x00, 0x00, 0x00, /* Rest is garbage */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
#endif
static const unsigned char upek2020_ack_00_28[] = {
'C', 'i', 'a', 'o',
0x00,
0x80, 0x08, /* Seq = 8, len = 0x008 */
0x28, /* CMD = 0x28 */
0x05, 0x00, /* Inner len = 0x0005 */
0x00, 0x00, 0x00, 0x30, 0x01,
0x6a, 0xc4 /* CRC */
'C', 'i', 'a', 'o',
0x00,
0x80, 0x08, /* Seq = 8, len = 0x008 */
0x28, /* CMD = 0x28 */
0x05, 0x00, /* Inner len = 0x0005 */
0x00, 0x00, 0x00, 0x30, 0x01,
0x6a, 0xc4 /* CRC */
};
#if 0
/* No seq should be tracked here */
static const unsigned char got_finger[] = {
'C', 'i', 'a', 'o',
0x08,
0x00, 0x00, /* Seq = 0, len = 0x000 */
0xa1, 0xa9, /* CRC */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Rest is garbage */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
'C', 'i', 'a', 'o',
0x08,
0x00, 0x00, /* Seq = 0, len = 0x000 */
0xa1, 0xa9, /* CRC */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Rest is garbage */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
#endif
/* No seq should be put in there */
static const unsigned char upek2020_ack_08[] = {
'C', 'i', 'a', 'o',
0x09,
0x00, 0x00, /* Seq = 0, len = 0x0 */
0x91, 0x9e /* CRC */
'C', 'i', 'a', 'o',
0x09,
0x00, 0x00, /* Seq = 0, len = 0x0 */
0x91, 0x9e /* CRC */
};
static const unsigned char upek2020_ack_frame[] = {
'C', 'i', 'a', 'o',
0x00,
0x50, 0x01, /* Seq = 5, len = 0x001 */
0x30,
0xac, 0x5b /* CRC */
'C', 'i', 'a', 'o',
0x00,
0x50, 0x01, /* Seq = 5, len = 0x001 */
0x30,
0xac, 0x5b /* CRC */
};
#endif

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -28,109 +28,112 @@
* powerdown? does windows do anything special on exit?
*/
#define CTRL_TIMEOUT 1000
#define EP_IN (1 | FPI_USB_ENDPOINT_IN)
#define CTRL_TIMEOUT 1000
#define EP_IN (1 | FPI_USB_ENDPOINT_IN)
#define IMG_WIDTH 300
#define IMG_HEIGHT 288
#define ROWS_PER_RQ 12
#define NR_REQS (IMG_HEIGHT / ROWS_PER_RQ)
#define RQ_SIZE (IMG_WIDTH * ROWS_PER_RQ)
#define IMG_SIZE (IMG_WIDTH * IMG_HEIGHT)
#define IMG_WIDTH 300
#define IMG_HEIGHT 288
#define ROWS_PER_RQ 12
#define NR_REQS (IMG_HEIGHT / ROWS_PER_RQ)
#define RQ_SIZE (IMG_WIDTH * ROWS_PER_RQ)
#define IMG_SIZE (IMG_WIDTH * IMG_HEIGHT)
struct _FpDeviceVcom5s {
FpImageDevice parent;
struct _FpDeviceVcom5s
{
FpImageDevice parent;
int capture_iteration;
FpImage *capture_img;
gboolean loop_running;
gboolean deactivating;
int capture_iteration;
FpImage *capture_img;
gboolean loop_running;
gboolean deactivating;
};
G_DECLARE_FINAL_TYPE(FpDeviceVcom5s, fpi_device_vcom5s, FPI, DEVICE_VCOM5S,
FpImageDevice);
G_DEFINE_TYPE(FpDeviceVcom5s, fpi_device_vcom5s, FP_TYPE_IMAGE_DEVICE);
G_DECLARE_FINAL_TYPE (FpDeviceVcom5s, fpi_device_vcom5s, FPI, DEVICE_VCOM5S,
FpImageDevice);
G_DEFINE_TYPE (FpDeviceVcom5s, fpi_device_vcom5s, FP_TYPE_IMAGE_DEVICE);
enum v5s_regs {
/* when using gain 0x29:
* a value of 0x00 produces mostly-black image
* 0x09 destroys ridges (too white)
* 0x01 or 0x02 seem good values */
REG_CONTRAST = 0x02,
/* when using gain 0x29:
* a value of 0x00 produces mostly-black image
* 0x09 destroys ridges (too white)
* 0x01 or 0x02 seem good values */
REG_CONTRAST = 0x02,
/* when using contrast 0x01:
* a value of 0x00 will produce an all-black image.
* 0x29 produces a good contrast image: ridges quite dark, but some
* light grey noise as background
* 0x46 produces all-white image with grey ridges (not very dark) */
REG_GAIN = 0x03,
/* when using contrast 0x01:
* a value of 0x00 will produce an all-black image.
* 0x29 produces a good contrast image: ridges quite dark, but some
* light grey noise as background
* 0x46 produces all-white image with grey ridges (not very dark) */
REG_GAIN = 0x03,
};
enum v5s_cmd {
/* scan one row. has parameter, at a guess this is which row to scan? */
CMD_SCAN_ONE_ROW = 0xc0,
/* scan one row. has parameter, at a guess this is which row to scan? */
CMD_SCAN_ONE_ROW = 0xc0,
/* scan whole image */
CMD_SCAN = 0xc1,
/* scan whole image */
CMD_SCAN = 0xc1,
};
/***** REGISTER I/O *****/
static void sm_write_reg_cb(FpiUsbTransfer *transfer, FpDevice *device,
gpointer user_data, GError *error)
static void
sm_write_reg_cb (FpiUsbTransfer *transfer, FpDevice *device,
gpointer user_data, GError *error)
{
if (error)
fpi_ssm_mark_failed(transfer->ssm, error);
else
fpi_ssm_next_state(transfer->ssm);
if (error)
fpi_ssm_mark_failed (transfer->ssm, error);
else
fpi_ssm_next_state (transfer->ssm);
}
static void
sm_write_reg(FpiSsm *ssm,
FpDevice *dev,
unsigned char reg,
unsigned char value)
sm_write_reg (FpiSsm *ssm,
FpDevice *dev,
unsigned char reg,
unsigned char value)
{
FpiUsbTransfer *transfer = fpi_usb_transfer_new(dev);
FpiUsbTransfer *transfer = fpi_usb_transfer_new (dev);
fp_dbg("set %02x=%02x", reg, value);
fpi_usb_transfer_fill_control(transfer,
G_USB_DEVICE_DIRECTION_HOST_TO_DEVICE,
G_USB_DEVICE_REQUEST_TYPE_VENDOR,
G_USB_DEVICE_RECIPIENT_DEVICE,
reg, value, 0, 0);
transfer->ssm = ssm;
fpi_usb_transfer_submit(transfer, CTRL_TIMEOUT, NULL, sm_write_reg_cb,
NULL);
fpi_usb_transfer_unref(transfer);
}
static void sm_exec_cmd_cb(FpiUsbTransfer *transfer, FpDevice *device,
gpointer user_data, GError *error)
{
if (error)
fpi_ssm_mark_failed(transfer->ssm, error);
else
fpi_ssm_next_state(transfer->ssm);
fp_dbg ("set %02x=%02x", reg, value);
fpi_usb_transfer_fill_control (transfer,
G_USB_DEVICE_DIRECTION_HOST_TO_DEVICE,
G_USB_DEVICE_REQUEST_TYPE_VENDOR,
G_USB_DEVICE_RECIPIENT_DEVICE,
reg, value, 0, 0);
transfer->ssm = ssm;
fpi_usb_transfer_submit (transfer, CTRL_TIMEOUT, NULL, sm_write_reg_cb,
NULL);
fpi_usb_transfer_unref (transfer);
}
static void
sm_exec_cmd(FpiSsm *ssm,
FpDevice *dev,
unsigned char cmd,
unsigned char param)
sm_exec_cmd_cb (FpiUsbTransfer *transfer, FpDevice *device,
gpointer user_data, GError *error)
{
FpiUsbTransfer *transfer = fpi_usb_transfer_new(dev);
if (error)
fpi_ssm_mark_failed (transfer->ssm, error);
else
fpi_ssm_next_state (transfer->ssm);
}
fp_dbg("cmd %02x param %02x", cmd, param);
fpi_usb_transfer_fill_control(transfer,
G_USB_DEVICE_DIRECTION_DEVICE_TO_HOST,
G_USB_DEVICE_REQUEST_TYPE_VENDOR,
G_USB_DEVICE_RECIPIENT_DEVICE,
cmd, param, 0, 0);
transfer->ssm = ssm;
fpi_usb_transfer_submit(transfer, CTRL_TIMEOUT, NULL, sm_exec_cmd_cb,
NULL);
fpi_usb_transfer_unref(transfer);
static void
sm_exec_cmd (FpiSsm *ssm,
FpDevice *dev,
unsigned char cmd,
unsigned char param)
{
FpiUsbTransfer *transfer = fpi_usb_transfer_new (dev);
fp_dbg ("cmd %02x param %02x", cmd, param);
fpi_usb_transfer_fill_control (transfer,
G_USB_DEVICE_DIRECTION_DEVICE_TO_HOST,
G_USB_DEVICE_REQUEST_TYPE_VENDOR,
G_USB_DEVICE_RECIPIENT_DEVICE,
cmd, param, 0, 0);
transfer->ssm = ssm;
fpi_usb_transfer_submit (transfer, CTRL_TIMEOUT, NULL, sm_exec_cmd_cb,
NULL);
fpi_usb_transfer_unref (transfer);
}
/***** FINGER DETECTION *****/
@ -145,217 +148,246 @@ sm_exec_cmd(FpiSsm *ssm,
#define DETBOX_COL_END (DETBOX_COL_START + DETBOX_COLS)
#define FINGER_PRESENCE_THRESHOLD 100
static gboolean finger_is_present(unsigned char *data)
static gboolean
finger_is_present (unsigned char *data)
{
int row;
guint16 imgavg = 0;
int row;
guint16 imgavg = 0;
for (row = DETBOX_ROW_START; row < DETBOX_ROW_END; row++) {
unsigned char *rowdata = data + (row * IMG_WIDTH);
guint16 rowavg = 0;
int col;
for (row = DETBOX_ROW_START; row < DETBOX_ROW_END; row++)
{
unsigned char *rowdata = data + (row * IMG_WIDTH);
guint16 rowavg = 0;
int col;
for (col = DETBOX_COL_START; col < DETBOX_COL_END; col++)
rowavg += rowdata[col];
rowavg /= DETBOX_COLS;
imgavg += rowavg;
}
imgavg /= DETBOX_ROWS;
fp_dbg("img avg %d", imgavg);
for (col = DETBOX_COL_START; col < DETBOX_COL_END; col++)
rowavg += rowdata[col];
rowavg /= DETBOX_COLS;
imgavg += rowavg;
}
imgavg /= DETBOX_ROWS;
fp_dbg ("img avg %d", imgavg);
return (imgavg <= FINGER_PRESENCE_THRESHOLD);
return imgavg <= FINGER_PRESENCE_THRESHOLD;
}
/***** IMAGE ACQUISITION *****/
static void capture_iterate(FpiSsm *ssm, FpDevice *dev);
static void capture_iterate (FpiSsm *ssm,
FpDevice *dev);
static void capture_cb(FpiUsbTransfer *transfer, FpDevice *device,
gpointer user_data, GError *error)
static void
capture_cb (FpiUsbTransfer *transfer, FpDevice *device,
gpointer user_data, GError *error)
{
FpImageDevice *imgdev = FP_IMAGE_DEVICE(device);
FpDeviceVcom5s *self = FPI_DEVICE_VCOM5S(device);
FpImageDevice *imgdev = FP_IMAGE_DEVICE (device);
FpDeviceVcom5s *self = FPI_DEVICE_VCOM5S (device);
if (error) {
fpi_ssm_mark_failed(transfer->ssm, error);
return;
}
if (error)
{
fpi_ssm_mark_failed (transfer->ssm, error);
return;
}
if (++self->capture_iteration == NR_REQS) {
FpImage *img = self->capture_img;
/* must clear this early, otherwise the call chain takes us into
* loopsm_complete where we would free it, when in fact we are
* supposed to be handing off this image */
self->capture_img = NULL;
if (++self->capture_iteration == NR_REQS)
{
FpImage *img = self->capture_img;
/* must clear this early, otherwise the call chain takes us into
* loopsm_complete where we would free it, when in fact we are
* supposed to be handing off this image */
self->capture_img = NULL;
fpi_image_device_report_finger_status(imgdev,
finger_is_present(img->data));
fpi_image_device_image_captured(imgdev, img);
fpi_ssm_next_state(transfer->ssm);
} else {
capture_iterate(transfer->ssm, device);
}
fpi_image_device_report_finger_status (imgdev,
finger_is_present (img->data));
fpi_image_device_image_captured (imgdev, img);
fpi_ssm_next_state (transfer->ssm);
}
else
{
capture_iterate (transfer->ssm, device);
}
}
static void
capture_iterate(FpiSsm *ssm,
FpDevice *dev)
capture_iterate (FpiSsm *ssm,
FpDevice *dev)
{
FpDeviceVcom5s *self = FPI_DEVICE_VCOM5S(dev);
int iteration = self->capture_iteration;
FpiUsbTransfer *transfer = fpi_usb_transfer_new(FP_DEVICE(dev));
FpDeviceVcom5s *self = FPI_DEVICE_VCOM5S (dev);
int iteration = self->capture_iteration;
FpiUsbTransfer *transfer = fpi_usb_transfer_new (FP_DEVICE (dev));
transfer->ssm = ssm;
transfer->short_is_error = TRUE;
fpi_usb_transfer_fill_bulk_full (transfer,
EP_IN,
self->capture_img->data + (RQ_SIZE * iteration),
RQ_SIZE,
NULL);
transfer->ssm = ssm;
transfer->short_is_error = TRUE;
fpi_usb_transfer_fill_bulk_full (transfer,
EP_IN,
self->capture_img->data + (RQ_SIZE * iteration),
RQ_SIZE,
NULL);
fpi_usb_transfer_submit (transfer, CTRL_TIMEOUT, NULL, capture_cb, NULL);
fpi_usb_transfer_unref (transfer);
fpi_usb_transfer_submit (transfer, CTRL_TIMEOUT, NULL, capture_cb, NULL);
fpi_usb_transfer_unref (transfer);
}
static void
sm_do_capture(FpiSsm *ssm,
FpDevice *dev)
sm_do_capture (FpiSsm *ssm,
FpDevice *dev)
{
FpDeviceVcom5s *self = FPI_DEVICE_VCOM5S(dev);
FpImageDeviceClass *cls = FP_IMAGE_DEVICE_GET_CLASS (dev);
FpDeviceVcom5s *self = FPI_DEVICE_VCOM5S (dev);
FpImageDeviceClass *cls = FP_IMAGE_DEVICE_GET_CLASS (dev);
G_DEBUG_HERE();
self->capture_img = fp_image_new (cls->img_width, cls->img_height);
self->capture_iteration = 0;
capture_iterate(ssm, dev);
G_DEBUG_HERE ();
self->capture_img = fp_image_new (cls->img_width, cls->img_height);
self->capture_iteration = 0;
capture_iterate (ssm, dev);
}
/***** CAPTURE LOOP *****/
enum loop_states {
LOOP_SET_CONTRAST,
LOOP_SET_GAIN,
LOOP_CMD_SCAN,
LOOP_CAPTURE,
LOOP_CAPTURE_DONE,
LOOP_NUM_STATES,
LOOP_SET_CONTRAST,
LOOP_SET_GAIN,
LOOP_CMD_SCAN,
LOOP_CAPTURE,
LOOP_CAPTURE_DONE,
LOOP_NUM_STATES,
};
static void loop_run_state(FpiSsm *ssm, FpDevice *dev, void *user_data)
static void
loop_run_state (FpiSsm *ssm, FpDevice *dev, void *user_data)
{
FpDeviceVcom5s *self = FPI_DEVICE_VCOM5S(dev);
FpDeviceVcom5s *self = FPI_DEVICE_VCOM5S (dev);
switch (fpi_ssm_get_cur_state(ssm)) {
case LOOP_SET_CONTRAST:
sm_write_reg(ssm, dev, REG_CONTRAST, 0x01);
break;
case LOOP_SET_GAIN:
sm_write_reg(ssm, dev, REG_GAIN, 0x29);
break;
case LOOP_CMD_SCAN:
if (self->deactivating) {
fp_dbg("deactivating, marking completed");
fpi_ssm_mark_completed(ssm);
} else
sm_exec_cmd(ssm, dev, CMD_SCAN, 0x00);
break;
case LOOP_CAPTURE:
sm_do_capture(ssm, dev);
break;
case LOOP_CAPTURE_DONE:
fpi_ssm_jump_to_state(ssm, LOOP_CMD_SCAN);
break;
default:
g_assert_not_reached ();
}
switch (fpi_ssm_get_cur_state (ssm))
{
case LOOP_SET_CONTRAST:
sm_write_reg (ssm, dev, REG_CONTRAST, 0x01);
break;
case LOOP_SET_GAIN:
sm_write_reg (ssm, dev, REG_GAIN, 0x29);
break;
case LOOP_CMD_SCAN:
if (self->deactivating)
{
fp_dbg ("deactivating, marking completed");
fpi_ssm_mark_completed (ssm);
}
else
{
sm_exec_cmd (ssm, dev, CMD_SCAN, 0x00);
}
break;
case LOOP_CAPTURE:
sm_do_capture (ssm, dev);
break;
case LOOP_CAPTURE_DONE:
fpi_ssm_jump_to_state (ssm, LOOP_CMD_SCAN);
break;
default:
g_assert_not_reached ();
}
}
static void loopsm_complete(FpiSsm *ssm, FpDevice *dev, void *user_data,
GError *error)
static void
loopsm_complete (FpiSsm *ssm, FpDevice *dev, void *user_data,
GError *error)
{
FpImageDevice *imgdev = FP_IMAGE_DEVICE (dev);
FpDeviceVcom5s *self = FPI_DEVICE_VCOM5S(dev);
FpImageDevice *imgdev = FP_IMAGE_DEVICE (dev);
FpDeviceVcom5s *self = FPI_DEVICE_VCOM5S (dev);
fpi_ssm_free(ssm);
g_object_unref (self->capture_img);
self->capture_img = NULL;
self->loop_running = FALSE;
fpi_ssm_free (ssm);
g_object_unref (self->capture_img);
self->capture_img = NULL;
self->loop_running = FALSE;
if (error && !self->deactivating)
fpi_image_device_session_error(imgdev, error);
else if (error)
g_error_free (error);
if (error && !self->deactivating)
fpi_image_device_session_error (imgdev, error);
else if (error)
g_error_free (error);
if (self->deactivating)
fpi_image_device_deactivate_complete(imgdev, NULL);
if (self->deactivating)
fpi_image_device_deactivate_complete (imgdev, NULL);
}
static void dev_activate(FpImageDevice *dev)
static void
dev_activate (FpImageDevice *dev)
{
FpDeviceVcom5s *self = FPI_DEVICE_VCOM5S(dev);
FpiSsm *ssm = fpi_ssm_new(FP_DEVICE(dev), loop_run_state,
LOOP_NUM_STATES, dev);
self->deactivating = FALSE;
fpi_ssm_start(ssm, loopsm_complete);
self->loop_running = TRUE;
fpi_image_device_activate_complete(dev, NULL);
FpDeviceVcom5s *self = FPI_DEVICE_VCOM5S (dev);
FpiSsm *ssm = fpi_ssm_new (FP_DEVICE (dev), loop_run_state,
LOOP_NUM_STATES, dev);
self->deactivating = FALSE;
fpi_ssm_start (ssm, loopsm_complete);
self->loop_running = TRUE;
fpi_image_device_activate_complete (dev, NULL);
}
static void dev_deactivate(FpImageDevice *dev)
static void
dev_deactivate (FpImageDevice *dev)
{
FpDeviceVcom5s *self = FPI_DEVICE_VCOM5S(dev);
if (self->loop_running)
self->deactivating = TRUE;
else
fpi_image_device_deactivate_complete(dev, NULL);
FpDeviceVcom5s *self = FPI_DEVICE_VCOM5S (dev);
if (self->loop_running)
self->deactivating = TRUE;
else
fpi_image_device_deactivate_complete (dev, NULL);
}
static void dev_init(FpImageDevice *dev)
static void
dev_init (FpImageDevice *dev)
{
GError *error = NULL;
GError *error = NULL;
g_usb_device_claim_interface (fpi_device_get_usb_device(FP_DEVICE(dev)), 0, 0, &error);
g_usb_device_claim_interface (fpi_device_get_usb_device (FP_DEVICE (dev)), 0, 0, &error);
fpi_image_device_open_complete(dev, error);
fpi_image_device_open_complete (dev, error);
}
static void dev_deinit(FpImageDevice *dev)
static void
dev_deinit (FpImageDevice *dev)
{
GError *error = NULL;
GError *error = NULL;
g_usb_device_release_interface(fpi_device_get_usb_device(FP_DEVICE(dev)),
0, 0, &error);
g_usb_device_release_interface (fpi_device_get_usb_device (FP_DEVICE (dev)),
0, 0, &error);
fpi_image_device_close_complete(dev, error);
fpi_image_device_close_complete (dev, error);
}
static const FpIdEntry id_table [ ] = {
{ .vid = 0x061a, .pid = 0x0110, },
{ .vid = 0, .pid = 0, .driver_data = 0 },
static const FpIdEntry id_table[] = {
{ .vid = 0x061a, .pid = 0x0110, },
{ .vid = 0, .pid = 0, .driver_data = 0 },
};
static void fpi_device_vcom5s_init(FpDeviceVcom5s *self) {
static void
fpi_device_vcom5s_init (FpDeviceVcom5s *self)
{
}
static void fpi_device_vcom5s_class_init(FpDeviceVcom5sClass *klass) {
FpDeviceClass *dev_class = FP_DEVICE_CLASS(klass);
FpImageDeviceClass *img_class = FP_IMAGE_DEVICE_CLASS(klass);
static void
fpi_device_vcom5s_class_init (FpDeviceVcom5sClass *klass)
{
FpDeviceClass *dev_class = FP_DEVICE_CLASS (klass);
FpImageDeviceClass *img_class = FP_IMAGE_DEVICE_CLASS (klass);
dev_class->id = "vcom5s";
dev_class->full_name = "Veridicom 5thSense";
dev_class->type = FP_DEVICE_TYPE_USB;
dev_class->id_table = id_table;
dev_class->scan_type = FP_SCAN_TYPE_PRESS;
dev_class->id = "vcom5s";
dev_class->full_name = "Veridicom 5thSense";
dev_class->type = FP_DEVICE_TYPE_USB;
dev_class->id_table = id_table;
dev_class->scan_type = FP_SCAN_TYPE_PRESS;
img_class->img_open = dev_init;
img_class->img_close = dev_deinit;
img_class->activate = dev_activate;
img_class->deactivate = dev_deactivate;
img_class->img_open = dev_init;
img_class->img_close = dev_deinit;
img_class->activate = dev_activate;
img_class->deactivate = dev_deactivate;
img_class->img_width = IMG_WIDTH;
img_class->img_height = IMG_HEIGHT;
img_class->img_width = IMG_WIDTH;
img_class->img_height = IMG_HEIGHT;
}

File diff suppressed because it is too large Load diff

View file

@ -51,334 +51,336 @@
#define EP3_IN 0x83
/* Fingerprint horizontal line */
struct vfs_line {
/* It must be always 0x01 */
unsigned char _0x01;
/* It must be always 0xfe */
unsigned char _0xfe;
struct vfs_line
{
/* It must be always 0x01 */
unsigned char _0x01;
/* It must be always 0xfe */
unsigned char _0xfe;
/* line number starting from some number in Little-Endian */
unsigned short id;
/* line number starting from some number in Little-Endian */
unsigned short id;
/* Some hashes which are useful to detect noise */
unsigned char noise_hash_1;
unsigned char noise_hash_2;
/* Some hashes which are useful to detect noise */
unsigned char noise_hash_1;
unsigned char noise_hash_2;
/* The first byte of _somedata is always 0x00, the second is strange useless cyclic line number */
unsigned short _somedata;
/* The first byte of _somedata is always 0x00, the second is strange useless cyclic line number */
unsigned short _somedata;
/* Fingerprint image */
unsigned char data[VFS_IMAGE_WIDTH];
/* Fingerprint image */
unsigned char data[VFS_IMAGE_WIDTH];
/* Narrow fingerprint part from the center used for variable speed lines assembling */
unsigned char next_line_part[VFS_NEXT_LINE_WIDTH];
/* Narrow fingerprint part from the center used for variable speed lines assembling */
unsigned char next_line_part[VFS_NEXT_LINE_WIDTH];
/* scan_data is 0xfb except some rare cases, it's skipped */
unsigned char scan_data[8];
} __attribute__ ((__packed__));
/* scan_data is 0xfb except some rare cases, it's skipped */
unsigned char scan_data[8];
} __attribute__((__packed__));
/* The main driver structure */
struct _FpDeviceVfs0050 {
FpImageDevice parent;
struct _FpDeviceVfs0050
{
FpImageDevice parent;
/* One if we were asked to read fingerprint, zero otherwise */
char active;
/* One if we were asked to read fingerprint, zero otherwise */
char active;
/* Control packet parameter for send_control_packet */
unsigned char *control_packet;
/* Control packet parameter for send_control_packet */
unsigned char *control_packet;
/* For dev_deactivate to check whether ssm still running or not */
char ssm_active;
/* For dev_deactivate to check whether ssm still running or not */
char ssm_active;
/* Should we call fpi_imgdev_activate_complete or fpi_imgdev_deactivate_complete */
char need_report;
/* Should we call fpi_imgdev_activate_complete or fpi_imgdev_deactivate_complete */
char need_report;
/* Received fingerprint raw lines */
struct vfs_line *lines_buffer;
/* Received fingerprint raw lines */
struct vfs_line *lines_buffer;
/* Current number of received bytes and current memory used by data */
int bytes, memory;
/* Current number of received bytes and current memory used by data */
int bytes, memory;
/* USB buffer for fingerprint */
char *usb_buffer;
/* USB buffer for fingerprint */
char *usb_buffer;
/* Received interrupt data */
unsigned char interrupt[8];
/* Received interrupt data */
unsigned char interrupt[8];
};
G_DECLARE_FINAL_TYPE (FpDeviceVfs0050, fpi_device_vfs0050, FPI, DEVICE_VFS0050, FpImageDevice)
/* SSM states for clear_ep2 */
enum SUBSM1 {
SUBSM1_COMMAND_04,
SUBSM1_RETURN_CODE,
SUBSM1_ABORT_2,
SUBSM1_COMMAND_04,
SUBSM1_RETURN_CODE,
SUBSM1_ABORT_2,
SUBSM1_STATES,
SUBSM1_STATES,
};
/* SSM states for control */
enum SUBSM2 {
SUBSM2_SEND_CONTROL,
SUBSM2_RETURN_CODE, /* If next_receive, send another control packet */
SUBSM2_SEND_CONTROL,
SUBSM2_RETURN_CODE, /* If next_receive, send another control packet */
SUBSM2_SEND_COMMIT,
SUBSM2_COMMIT_RESPONSE,
SUBSM2_READ_EMPTY_INTERRUPT,
SUBSM2_ABORT_3,
SUBSM2_CLEAR_EP2,
SUBSM2_SEND_COMMIT,
SUBSM2_COMMIT_RESPONSE,
SUBSM2_READ_EMPTY_INTERRUPT,
SUBSM2_ABORT_3,
SUBSM2_CLEAR_EP2,
SUBSM2_STATES,
SUBSM2_STATES,
};
/* SSM states for activate_ssm */
enum SSM_STATE {
SSM_INITIAL_ABORT_1,
SSM_INITIAL_ABORT_2,
SSM_INITIAL_ABORT_3,
SSM_CLEAR_EP2,
SSM_TURN_OFF,
SSM_INITIAL_ABORT_1,
SSM_INITIAL_ABORT_2,
SSM_INITIAL_ABORT_3,
SSM_CLEAR_EP2,
SSM_TURN_OFF,
/* Here the device is turned off; if not active, complete ssm */
SSM_TURN_ON,
/* Here the device is turned off; if not active, complete ssm */
SSM_TURN_ON,
SSM_ASK_INTERRUPT,
SSM_WAIT_INTERRUPT,
SSM_ASK_INTERRUPT,
SSM_WAIT_INTERRUPT,
SSM_RECEIVE_FINGER,
SSM_SUBMIT_IMAGE,
SSM_RECEIVE_FINGER,
SSM_SUBMIT_IMAGE,
/* If not active, jump to CLEAR_EP2 */
SSM_NEXT_RECEIVE,
SSM_WAIT_ANOTHER_SCAN,
/* Jump to TURN_ON */
/* If not active, jump to CLEAR_EP2 */
SSM_NEXT_RECEIVE,
SSM_WAIT_ANOTHER_SCAN,
/* Jump to TURN_ON */
SSM_STATES
SSM_STATES
};
/* Blocks of data from USB sniffer */
/* Turns on the light */
static unsigned char turn_on[] = {
0x39, 0x20, 0xBF, 0x02, 0x00, 0xF4, 0x01, 0x00, 0x00, 0x01, 0xD1, 0x00,
0x20, 0xD1, 0xD1, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF4, 0x01, 0x00,
0x00, 0x01, 0x00, 0x00,
0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0xF4, 0x01, 0x00,
0x00, 0x02, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0xF4, 0x01, 0x00, 0x00, 0x02, 0xD1, 0x00, 0x20, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00,
0x39, 0x20, 0xBF, 0x02, 0x00, 0xF4, 0x01, 0x00, 0x00, 0x01, 0xD1, 0x00,
0x20, 0xD1, 0xD1, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF4, 0x01, 0x00,
0x00, 0x01, 0x00, 0x00,
0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0xF4, 0x01, 0x00,
0x00, 0x02, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0xF4, 0x01, 0x00, 0x00, 0x02, 0xD1, 0x00, 0x20, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00,
};
/* Power off */
static unsigned char turn_off[] = {
0x39, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00,
0x39, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00,
};
/* Turns on orange light */
static unsigned char next_receive_1[] = {
0x39, 0xB8, 0x0B, 0x00, 0x00, 0xB8, 0x0B, 0x00, 0x00, 0x01, 0xD1, 0x00,
0x20, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xD1, 0xD1, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x01, 0x00, 0x00,
0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x02, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0xB8, 0x0B, 0x00, 0x00, 0x02, 0xD1, 0x00, 0x20, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00,
0x39, 0xB8, 0x0B, 0x00, 0x00, 0xB8, 0x0B, 0x00, 0x00, 0x01, 0xD1, 0x00,
0x20, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xD1, 0xD1, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x01, 0x00, 0x00,
0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x02, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0xB8, 0x0B, 0x00, 0x00, 0x02, 0xD1, 0x00, 0x20, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00,
};
/* Packet directly after next_receive_1 */
static unsigned char next_receive_2[] = {
0x39, 0xE8, 0x03, 0x00, 0x00, 0xE8, 0x03, 0x00, 0x00, 0x01, 0xD1, 0x00,
0x20, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xD1, 0xD1, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x01, 0x00, 0x00,
0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x02, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0xE8, 0x03, 0x00, 0x00, 0x02, 0xD1, 0x00, 0x20, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00,
0x39, 0xE8, 0x03, 0x00, 0x00, 0xE8, 0x03, 0x00, 0x00, 0x01, 0xD1, 0x00,
0x20, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xD1, 0xD1, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x01, 0x00, 0x00,
0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x02, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0xE8, 0x03, 0x00, 0x00, 0x02, 0xD1, 0x00, 0x20, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00,
};
/* Commit message */
static unsigned char commit_out[] = {
0x02, 0x94, 0x00, 0x00, 0x00, 0x20, 0x00, 0x08, 0x00, 0x2C, 0x03, 0x00,
0x30, 0x1B, 0x00, 0x00,
0x00, 0x20, 0x00, 0x08, 0x00, 0x20, 0x03, 0x00, 0x30, 0x3D, 0x10, 0x00,
0x00, 0x20, 0x00, 0x08,
0x00, 0x18, 0x03, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x08,
0x00, 0x24, 0x03, 0x00,
0x30, 0x08, 0x00, 0x00, 0x00, 0x20, 0x00, 0x08, 0x00, 0x28, 0x03, 0x00,
0x30, 0x08, 0x00, 0x00,
0x00, 0x20, 0x00, 0x08, 0x00, 0x30, 0x03, 0x00, 0x30, 0x00, 0x00, 0x00,
0x00, 0x20, 0x00, 0x08,
0x00, 0x38, 0x03, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x08,
0x00, 0x3C, 0x03, 0x00,
0x30, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x08, 0x00, 0x44, 0x03, 0x00,
0x30, 0x14, 0x00, 0x00,
0x00, 0x20, 0x00, 0x08, 0x00, 0x48, 0x03, 0x00, 0x30, 0x01, 0x04, 0x02,
0x00, 0x20, 0x00, 0x08,
0x00, 0x4C, 0x03, 0x00, 0x30, 0x01, 0x0C, 0x02, 0x00, 0x20, 0x00, 0x08,
0x00, 0x54, 0x03, 0x00,
0x30, 0x20, 0x00, 0x00, 0x00, 0x20, 0x00, 0x08, 0x00, 0x5C, 0x03, 0x00,
0x30, 0x90, 0x01, 0x02,
0x00, 0x20, 0x00, 0x08, 0x00, 0x60, 0x03, 0x00, 0x30, 0x2C, 0x01, 0x19,
0x00, 0x20, 0x00, 0x08,
0x00, 0x64, 0x03, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x08,
0x00, 0x6C, 0x03, 0x00,
0x30, 0x1E, 0x00, 0x00, 0x00, 0x20, 0x00, 0x08, 0x00, 0x70, 0x03, 0x00,
0x30, 0x21, 0x80, 0x00,
0x00, 0x20, 0x00, 0x08, 0x00, 0x78, 0x03, 0x00, 0x30, 0x09, 0x00, 0x02,
0x00, 0x20, 0x00, 0x08,
0x00, 0x7C, 0x03, 0x00, 0x30, 0x0B, 0x00, 0x19, 0x00, 0x20, 0x00, 0x08,
0x00, 0x80, 0x03, 0x00,
0x30, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x08, 0x00, 0x84, 0x03, 0x00,
0x30, 0x3A, 0x00, 0x00,
0x00, 0x20, 0x00, 0x08, 0x00, 0x88, 0x03, 0x00, 0x30, 0x14, 0x00, 0x00,
0x00, 0x20, 0x00, 0x08,
0x00, 0x8C, 0x03, 0x00, 0x30, 0x02, 0x00, 0x00, 0x00, 0x20, 0x00, 0x08,
0x00, 0x90, 0x03, 0x00,
0x30, 0x02, 0x00, 0x00, 0x00, 0x20, 0x00, 0x08, 0x00, 0x94, 0x03, 0x00,
0x30, 0x08, 0x00, 0x00,
0x00, 0x20, 0x00, 0x08, 0x00, 0x98, 0x03, 0x00, 0x30, 0x00, 0x00, 0xA1,
0x01, 0x20, 0x00, 0x08,
0x00, 0x9C, 0x03, 0x00, 0x30, 0x00, 0x00, 0xA1, 0x01, 0x20, 0x00, 0x08,
0x00, 0xA8, 0x03, 0x00,
0x30, 0x64, 0x01, 0x00, 0x00, 0x20, 0x00, 0x08, 0x00, 0xAC, 0x03, 0x00,
0x30, 0x64, 0x01, 0x00,
0x00, 0x20, 0x00, 0x08, 0x00, 0xB0, 0x03, 0x00, 0x30, 0x00, 0x01, 0x00,
0x00, 0x20, 0x00, 0x08,
0x00, 0xB4, 0x03, 0x00, 0x30, 0x00, 0x01, 0x00, 0x00, 0x20, 0x00, 0x08,
0x00, 0xB8, 0x03, 0x00,
0x30, 0x05, 0x00, 0x00, 0x00, 0x20, 0x00, 0x08, 0x00, 0xBC, 0x03, 0x00,
0x30, 0x05, 0x00, 0x00,
0x00, 0x20, 0x00, 0x08, 0x00, 0xC0, 0x03, 0x00, 0x30, 0x00, 0x00, 0x00,
0x00, 0x20, 0x00, 0x08,
0x00, 0x84, 0x03, 0x00, 0x30, 0x3B, 0x00, 0x00, 0x00, 0x20, 0x00, 0x08,
0x00, 0x08, 0x07, 0x00,
0x30, 0x03, 0x00, 0x00, 0x00, 0x20, 0x00, 0x08, 0x00, 0x0C, 0x07, 0x00,
0x30, 0x00, 0x00, 0x00,
0x00, 0x20, 0x00, 0x08, 0x00, 0x14, 0x07, 0x00, 0x30, 0x20, 0x00, 0x00,
0x00, 0x20, 0x00, 0x08,
0x00, 0x1C, 0x07, 0x00, 0x30, 0x1A, 0x00, 0x00, 0x00, 0x20, 0x00, 0x08,
0x00, 0x70, 0x0D, 0x00,
0x30, 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x28, 0x00, 0x10, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x02, 0x00, 0x90, 0x00, 0x00, 0x00, 0x2B, 0xFF, 0x2B, 0xFF, 0x2B,
0xED, 0x00, 0x00, 0x2B,
0xFB, 0x00, 0x00, 0x2B, 0xC5, 0x00, 0x00, 0x2B, 0x05, 0x80, 0x70, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x24, 0xD3, 0x2E, 0xC0, 0x2C, 0x3B, 0x08, 0xF0, 0x3B, 0x09, 0x24,
0xBB, 0x3B, 0x0B, 0x24,
0xAA, 0x3B, 0x1F, 0xF8, 0x00, 0x3B, 0x3F, 0xF0, 0x00, 0x3B, 0x35, 0xC0,
0x00, 0x38, 0x80, 0x2C,
0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x38, 0x80, 0x2C, 0x70, 0x00,
0x00, 0x00, 0x00, 0xC0,
0x3A, 0x80, 0x2C, 0x70, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x3B, 0x0A, 0x80,
0x2E, 0x83, 0x24, 0xDB,
0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0xC3, 0x2C, 0x31, 0x83, 0x2C, 0x70,
0x00, 0x00, 0x00, 0x00,
0xCB, 0x33, 0x1B, 0x83, 0x2C, 0x70, 0x00, 0x00, 0x00, 0x00, 0xCB, 0x31,
0x83, 0x2C, 0x70, 0x00,
0x00, 0x00, 0x00, 0xCB, 0x00, 0x33, 0x1E, 0x83, 0x2E, 0x25, 0xFF, 0xC4,
0x00, 0x2F, 0x06, 0x84,
0x2E, 0x00, 0x00, 0x10, 0x20, 0x29, 0x00, 0x04, 0x00, 0x10, 0x00, 0x00,
0x00, 0x23, 0x00, 0x00,
0x00, 0x21, 0x00, 0x10, 0x00, 0x48, 0x03, 0x00, 0x30, 0xFF, 0xF0, 0xFF,
0xFF, 0x00, 0x00, 0x00,
0x00, 0x00, 0x04, 0x00, 0x00, 0x21, 0x00, 0x10, 0x00, 0x4C, 0x03, 0x00,
0x30, 0xFF, 0xF0, 0xFF,
0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x21, 0x00, 0x10,
0x00, 0x20, 0x03, 0x00,
0x30, 0x7F, 0x00, 0xFC, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x80, 0x10, 0x00,
0x00, 0x20, 0x00, 0x08,
0x00, 0x24, 0x03, 0x00, 0x30, 0x08, 0x00, 0x00, 0x00, 0x20, 0x00, 0x08,
0x00, 0x1C, 0x07, 0x00,
0x30, 0x1A, 0x00, 0x00, 0x00, 0x21, 0x00, 0x10, 0x00, 0x20, 0x03, 0x00,
0x30, 0xC3, 0xFF, 0xFF,
0xFF, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x20, 0x00, 0x08,
0x00, 0x80, 0x03, 0x00,
0x30, 0x02, 0x00, 0x00, 0x00, 0x24, 0x00, 0x84, 0x00, 0x31, 0x65, 0x77,
0x77, 0x77, 0x78, 0x88,
0x77, 0x77, 0x76, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x78, 0x77, 0x67,
0x66, 0x66, 0x66, 0x66,
0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x76, 0x67, 0x66, 0x66, 0x66, 0x66,
0x66, 0x77, 0x66, 0x66,
0x66, 0x66, 0x67, 0x66, 0x66, 0x66, 0x66, 0x66, 0x76, 0x76, 0x66, 0x56,
0x66, 0x66, 0x56, 0x55,
0x65, 0x66, 0x66, 0x66, 0x65, 0x66, 0x66, 0x55, 0x66, 0x66, 0x65, 0x66,
0x76, 0x76, 0x77, 0x77,
0x66, 0x66, 0x66, 0x76, 0x67, 0x66, 0x77, 0x67, 0x66, 0x66, 0x66, 0x56,
0x65, 0x66, 0x65, 0x66,
0x66, 0x55, 0x55, 0x54, 0x55, 0x65, 0x66, 0x66, 0x66, 0x76, 0x77, 0x87,
0x88, 0x77, 0x66, 0x66,
0x66, 0x66, 0x66, 0x66, 0x66, 0x65, 0x66, 0x55, 0x55, 0x65, 0x56, 0x55,
0x55, 0x55, 0x54, 0x45,
0x54, 0x55, 0x55, 0x55, 0x66, 0x66, 0x66, 0x66, 0x66, 0x77, 0x77, 0x77,
0x66, 0x26, 0x00, 0x28,
0x00, 0xFF, 0x00, 0x0F, 0x00, 0xF0, 0xF0, 0x0F, 0x00, 0x20, 0x00, 0x00,
0x00, 0x30, 0x01, 0x02,
0x00, 0x2C, 0x01, 0x28, 0x00, 0x20, 0x80, 0x00, 0x00, 0x0A, 0x00, 0x02,
0x00, 0x0B, 0x00, 0x19,
0x00, 0x40, 0x1F, 0x10, 0x27, 0x00, 0x0F, 0x03, 0x00,
0x02, 0x94, 0x00, 0x00, 0x00, 0x20, 0x00, 0x08, 0x00, 0x2C, 0x03, 0x00,
0x30, 0x1B, 0x00, 0x00,
0x00, 0x20, 0x00, 0x08, 0x00, 0x20, 0x03, 0x00, 0x30, 0x3D, 0x10, 0x00,
0x00, 0x20, 0x00, 0x08,
0x00, 0x18, 0x03, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x08,
0x00, 0x24, 0x03, 0x00,
0x30, 0x08, 0x00, 0x00, 0x00, 0x20, 0x00, 0x08, 0x00, 0x28, 0x03, 0x00,
0x30, 0x08, 0x00, 0x00,
0x00, 0x20, 0x00, 0x08, 0x00, 0x30, 0x03, 0x00, 0x30, 0x00, 0x00, 0x00,
0x00, 0x20, 0x00, 0x08,
0x00, 0x38, 0x03, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x08,
0x00, 0x3C, 0x03, 0x00,
0x30, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x08, 0x00, 0x44, 0x03, 0x00,
0x30, 0x14, 0x00, 0x00,
0x00, 0x20, 0x00, 0x08, 0x00, 0x48, 0x03, 0x00, 0x30, 0x01, 0x04, 0x02,
0x00, 0x20, 0x00, 0x08,
0x00, 0x4C, 0x03, 0x00, 0x30, 0x01, 0x0C, 0x02, 0x00, 0x20, 0x00, 0x08,
0x00, 0x54, 0x03, 0x00,
0x30, 0x20, 0x00, 0x00, 0x00, 0x20, 0x00, 0x08, 0x00, 0x5C, 0x03, 0x00,
0x30, 0x90, 0x01, 0x02,
0x00, 0x20, 0x00, 0x08, 0x00, 0x60, 0x03, 0x00, 0x30, 0x2C, 0x01, 0x19,
0x00, 0x20, 0x00, 0x08,
0x00, 0x64, 0x03, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x08,
0x00, 0x6C, 0x03, 0x00,
0x30, 0x1E, 0x00, 0x00, 0x00, 0x20, 0x00, 0x08, 0x00, 0x70, 0x03, 0x00,
0x30, 0x21, 0x80, 0x00,
0x00, 0x20, 0x00, 0x08, 0x00, 0x78, 0x03, 0x00, 0x30, 0x09, 0x00, 0x02,
0x00, 0x20, 0x00, 0x08,
0x00, 0x7C, 0x03, 0x00, 0x30, 0x0B, 0x00, 0x19, 0x00, 0x20, 0x00, 0x08,
0x00, 0x80, 0x03, 0x00,
0x30, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x08, 0x00, 0x84, 0x03, 0x00,
0x30, 0x3A, 0x00, 0x00,
0x00, 0x20, 0x00, 0x08, 0x00, 0x88, 0x03, 0x00, 0x30, 0x14, 0x00, 0x00,
0x00, 0x20, 0x00, 0x08,
0x00, 0x8C, 0x03, 0x00, 0x30, 0x02, 0x00, 0x00, 0x00, 0x20, 0x00, 0x08,
0x00, 0x90, 0x03, 0x00,
0x30, 0x02, 0x00, 0x00, 0x00, 0x20, 0x00, 0x08, 0x00, 0x94, 0x03, 0x00,
0x30, 0x08, 0x00, 0x00,
0x00, 0x20, 0x00, 0x08, 0x00, 0x98, 0x03, 0x00, 0x30, 0x00, 0x00, 0xA1,
0x01, 0x20, 0x00, 0x08,
0x00, 0x9C, 0x03, 0x00, 0x30, 0x00, 0x00, 0xA1, 0x01, 0x20, 0x00, 0x08,
0x00, 0xA8, 0x03, 0x00,
0x30, 0x64, 0x01, 0x00, 0x00, 0x20, 0x00, 0x08, 0x00, 0xAC, 0x03, 0x00,
0x30, 0x64, 0x01, 0x00,
0x00, 0x20, 0x00, 0x08, 0x00, 0xB0, 0x03, 0x00, 0x30, 0x00, 0x01, 0x00,
0x00, 0x20, 0x00, 0x08,
0x00, 0xB4, 0x03, 0x00, 0x30, 0x00, 0x01, 0x00, 0x00, 0x20, 0x00, 0x08,
0x00, 0xB8, 0x03, 0x00,
0x30, 0x05, 0x00, 0x00, 0x00, 0x20, 0x00, 0x08, 0x00, 0xBC, 0x03, 0x00,
0x30, 0x05, 0x00, 0x00,
0x00, 0x20, 0x00, 0x08, 0x00, 0xC0, 0x03, 0x00, 0x30, 0x00, 0x00, 0x00,
0x00, 0x20, 0x00, 0x08,
0x00, 0x84, 0x03, 0x00, 0x30, 0x3B, 0x00, 0x00, 0x00, 0x20, 0x00, 0x08,
0x00, 0x08, 0x07, 0x00,
0x30, 0x03, 0x00, 0x00, 0x00, 0x20, 0x00, 0x08, 0x00, 0x0C, 0x07, 0x00,
0x30, 0x00, 0x00, 0x00,
0x00, 0x20, 0x00, 0x08, 0x00, 0x14, 0x07, 0x00, 0x30, 0x20, 0x00, 0x00,
0x00, 0x20, 0x00, 0x08,
0x00, 0x1C, 0x07, 0x00, 0x30, 0x1A, 0x00, 0x00, 0x00, 0x20, 0x00, 0x08,
0x00, 0x70, 0x0D, 0x00,
0x30, 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x28, 0x00, 0x10, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x02, 0x00, 0x90, 0x00, 0x00, 0x00, 0x2B, 0xFF, 0x2B, 0xFF, 0x2B,
0xED, 0x00, 0x00, 0x2B,
0xFB, 0x00, 0x00, 0x2B, 0xC5, 0x00, 0x00, 0x2B, 0x05, 0x80, 0x70, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x24, 0xD3, 0x2E, 0xC0, 0x2C, 0x3B, 0x08, 0xF0, 0x3B, 0x09, 0x24,
0xBB, 0x3B, 0x0B, 0x24,
0xAA, 0x3B, 0x1F, 0xF8, 0x00, 0x3B, 0x3F, 0xF0, 0x00, 0x3B, 0x35, 0xC0,
0x00, 0x38, 0x80, 0x2C,
0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x38, 0x80, 0x2C, 0x70, 0x00,
0x00, 0x00, 0x00, 0xC0,
0x3A, 0x80, 0x2C, 0x70, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x3B, 0x0A, 0x80,
0x2E, 0x83, 0x24, 0xDB,
0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0xC3, 0x2C, 0x31, 0x83, 0x2C, 0x70,
0x00, 0x00, 0x00, 0x00,
0xCB, 0x33, 0x1B, 0x83, 0x2C, 0x70, 0x00, 0x00, 0x00, 0x00, 0xCB, 0x31,
0x83, 0x2C, 0x70, 0x00,
0x00, 0x00, 0x00, 0xCB, 0x00, 0x33, 0x1E, 0x83, 0x2E, 0x25, 0xFF, 0xC4,
0x00, 0x2F, 0x06, 0x84,
0x2E, 0x00, 0x00, 0x10, 0x20, 0x29, 0x00, 0x04, 0x00, 0x10, 0x00, 0x00,
0x00, 0x23, 0x00, 0x00,
0x00, 0x21, 0x00, 0x10, 0x00, 0x48, 0x03, 0x00, 0x30, 0xFF, 0xF0, 0xFF,
0xFF, 0x00, 0x00, 0x00,
0x00, 0x00, 0x04, 0x00, 0x00, 0x21, 0x00, 0x10, 0x00, 0x4C, 0x03, 0x00,
0x30, 0xFF, 0xF0, 0xFF,
0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x21, 0x00, 0x10,
0x00, 0x20, 0x03, 0x00,
0x30, 0x7F, 0x00, 0xFC, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x80, 0x10, 0x00,
0x00, 0x20, 0x00, 0x08,
0x00, 0x24, 0x03, 0x00, 0x30, 0x08, 0x00, 0x00, 0x00, 0x20, 0x00, 0x08,
0x00, 0x1C, 0x07, 0x00,
0x30, 0x1A, 0x00, 0x00, 0x00, 0x21, 0x00, 0x10, 0x00, 0x20, 0x03, 0x00,
0x30, 0xC3, 0xFF, 0xFF,
0xFF, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x20, 0x00, 0x08,
0x00, 0x80, 0x03, 0x00,
0x30, 0x02, 0x00, 0x00, 0x00, 0x24, 0x00, 0x84, 0x00, 0x31, 0x65, 0x77,
0x77, 0x77, 0x78, 0x88,
0x77, 0x77, 0x76, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x78, 0x77, 0x67,
0x66, 0x66, 0x66, 0x66,
0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x76, 0x67, 0x66, 0x66, 0x66, 0x66,
0x66, 0x77, 0x66, 0x66,
0x66, 0x66, 0x67, 0x66, 0x66, 0x66, 0x66, 0x66, 0x76, 0x76, 0x66, 0x56,
0x66, 0x66, 0x56, 0x55,
0x65, 0x66, 0x66, 0x66, 0x65, 0x66, 0x66, 0x55, 0x66, 0x66, 0x65, 0x66,
0x76, 0x76, 0x77, 0x77,
0x66, 0x66, 0x66, 0x76, 0x67, 0x66, 0x77, 0x67, 0x66, 0x66, 0x66, 0x56,
0x65, 0x66, 0x65, 0x66,
0x66, 0x55, 0x55, 0x54, 0x55, 0x65, 0x66, 0x66, 0x66, 0x76, 0x77, 0x87,
0x88, 0x77, 0x66, 0x66,
0x66, 0x66, 0x66, 0x66, 0x66, 0x65, 0x66, 0x55, 0x55, 0x65, 0x56, 0x55,
0x55, 0x55, 0x54, 0x45,
0x54, 0x55, 0x55, 0x55, 0x66, 0x66, 0x66, 0x66, 0x66, 0x77, 0x77, 0x77,
0x66, 0x26, 0x00, 0x28,
0x00, 0xFF, 0x00, 0x0F, 0x00, 0xF0, 0xF0, 0x0F, 0x00, 0x20, 0x00, 0x00,
0x00, 0x30, 0x01, 0x02,
0x00, 0x2C, 0x01, 0x28, 0x00, 0x20, 0x80, 0x00, 0x00, 0x0A, 0x00, 0x02,
0x00, 0x0B, 0x00, 0x19,
0x00, 0x40, 0x1F, 0x10, 0x27, 0x00, 0x0F, 0x03, 0x00,
};
/* Known interrupts */
static unsigned char empty_interrupt[] = {
0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00,
};
static unsigned char interrupt1[] = {
0x02, 0x00, 0x0E, 0x00, 0xF0,
0x02, 0x00, 0x0E, 0x00, 0xF0,
};
static unsigned char interrupt2[] = {
0x02, 0x04, 0x0A, 0x00, 0xF0,
0x02, 0x04, 0x0A, 0x00, 0xF0,
};
static unsigned char interrupt3[] = {
0x02, 0x00, 0x0A, 0x00, 0xF0,
0x02, 0x00, 0x0A, 0x00, 0xF0,
};

File diff suppressed because it is too large Load diff

View file

@ -30,249 +30,268 @@ G_DEFINE_TYPE (FpDeviceVfs301, fpi_device_vfs301, FP_TYPE_IMAGE_DEVICE)
/* Submit asynchronous sleep */
static void
async_sleep(unsigned int msec,
FpiSsm *ssm,
FpImageDevice *dev)
async_sleep (unsigned int msec,
FpiSsm *ssm,
FpImageDevice *dev)
{
/* Add timeout */
fpi_device_add_timeout(FP_DEVICE(dev), msec,
fpi_ssm_next_state_timeout_cb, ssm);
/* Add timeout */
fpi_device_add_timeout (FP_DEVICE (dev), msec,
fpi_ssm_next_state_timeout_cb, ssm);
}
static int
submit_image(FpiSsm *ssm,
FpImageDevice *dev)
submit_image (FpiSsm *ssm,
FpImageDevice *dev)
{
FpDeviceVfs301 *self = FPI_DEVICE_VFS301(dev);
int height;
FpImage *img;
FpDeviceVfs301 *self = FPI_DEVICE_VFS301 (dev);
int height;
FpImage *img;
#if 0
/* XXX: This is probably handled by libfprint automagically? */
if (vdev->scanline_count < 20) {
fpi_ssm_jump_to_state(ssm, M_REQUEST_PRINT);
return 0;
}
/* XXX: This is probably handled by libfprint automagically? */
if (vdev->scanline_count < 20)
{
fpi_ssm_jump_to_state (ssm, M_REQUEST_PRINT);
return 0;
}
#endif
img = fp_image_new(VFS301_FP_OUTPUT_WIDTH, self->scanline_count);
if (img == NULL)
return 0;
img = fp_image_new (VFS301_FP_OUTPUT_WIDTH, self->scanline_count);
if (img == NULL)
return 0;
vfs301_extract_image(self, img->data, &height);
vfs301_extract_image (self, img->data, &height);
/* TODO: how to detect flip? should the resulting image be
* oriented so that it is equal e.g. to a fingerprint on a paper,
* or to the finger when I look at it?) */
img->flags = FPI_IMAGE_COLORS_INVERTED | FPI_IMAGE_V_FLIPPED;
/* TODO: how to detect flip? should the resulting image be
* oriented so that it is equal e.g. to a fingerprint on a paper,
* or to the finger when I look at it?) */
img->flags = FPI_IMAGE_COLORS_INVERTED | FPI_IMAGE_V_FLIPPED;
/* The image buffer is larger at this point, but that does not
* matter. */
img->width = VFS301_FP_OUTPUT_WIDTH;
img->height = height;
/* The image buffer is larger at this point, but that does not
* matter. */
img->width = VFS301_FP_OUTPUT_WIDTH;
img->height = height;
fpi_image_device_image_captured(dev, img);
fpi_image_device_image_captured (dev, img);
return 1;
return 1;
}
/* Loop ssm states */
enum
{
/* Step 0 - Scan finger */
M_REQUEST_PRINT,
M_WAIT_PRINT,
M_CHECK_PRINT,
M_READ_PRINT_START,
M_READ_PRINT_WAIT,
M_READ_PRINT_POLL,
M_SUBMIT_PRINT,
enum {
/* Step 0 - Scan finger */
M_REQUEST_PRINT,
M_WAIT_PRINT,
M_CHECK_PRINT,
M_READ_PRINT_START,
M_READ_PRINT_WAIT,
M_READ_PRINT_POLL,
M_SUBMIT_PRINT,
/* Number of states */
M_LOOP_NUM_STATES,
/* Number of states */
M_LOOP_NUM_STATES,
};
/* Exec loop sequential state machine */
static void m_loop_state(FpiSsm *ssm, FpDevice *_dev, void *user_data)
static void
m_loop_state (FpiSsm *ssm, FpDevice *_dev, void *user_data)
{
FpImageDevice *dev = user_data;
FpDeviceVfs301 *self = FPI_DEVICE_VFS301(_dev);
FpImageDevice *dev = user_data;
FpDeviceVfs301 *self = FPI_DEVICE_VFS301 (_dev);
switch (fpi_ssm_get_cur_state(ssm)) {
case M_REQUEST_PRINT:
vfs301_proto_request_fingerprint(self);
fpi_ssm_next_state(ssm);
break;
switch (fpi_ssm_get_cur_state (ssm))
{
case M_REQUEST_PRINT:
vfs301_proto_request_fingerprint (self);
fpi_ssm_next_state (ssm);
break;
case M_WAIT_PRINT:
/* Wait fingerprint scanning */
async_sleep(200, ssm, dev);
break;
case M_WAIT_PRINT:
/* Wait fingerprint scanning */
async_sleep (200, ssm, dev);
break;
case M_CHECK_PRINT:
if (!vfs301_proto_peek_event(self))
fpi_ssm_jump_to_state(ssm, M_WAIT_PRINT);
else
fpi_ssm_next_state(ssm);
break;
case M_CHECK_PRINT:
if (!vfs301_proto_peek_event (self))
fpi_ssm_jump_to_state (ssm, M_WAIT_PRINT);
else
fpi_ssm_next_state (ssm);
break;
case M_READ_PRINT_START:
fpi_image_device_report_finger_status(dev, TRUE);
vfs301_proto_process_event_start(self);
fpi_ssm_next_state(ssm);
break;
case M_READ_PRINT_START:
fpi_image_device_report_finger_status (dev, TRUE);
vfs301_proto_process_event_start (self);
fpi_ssm_next_state (ssm);
break;
case M_READ_PRINT_WAIT:
/* Wait fingerprint scanning */
async_sleep(200, ssm, dev);
break;
case M_READ_PRINT_WAIT:
/* Wait fingerprint scanning */
async_sleep (200, ssm, dev);
break;
case M_READ_PRINT_POLL:
{
int rv = vfs301_proto_process_event_poll(self);
g_assert(rv != VFS301_FAILURE);
if (rv == VFS301_ONGOING)
fpi_ssm_jump_to_state(ssm, M_READ_PRINT_WAIT);
else
fpi_ssm_next_state(ssm);
}
break;
case M_READ_PRINT_POLL:
{
int rv = vfs301_proto_process_event_poll (self);
g_assert (rv != VFS301_FAILURE);
if (rv == VFS301_ONGOING)
fpi_ssm_jump_to_state (ssm, M_READ_PRINT_WAIT);
else
fpi_ssm_next_state (ssm);
}
break;
case M_SUBMIT_PRINT:
if (submit_image(ssm, dev)) {
fpi_ssm_mark_completed(ssm);
/* NOTE: finger off is expected only after submitting image... */
fpi_image_device_report_finger_status(dev, FALSE);
} else {
fpi_ssm_jump_to_state(ssm, M_REQUEST_PRINT);
}
break;
default:
g_assert_not_reached ();
}
case M_SUBMIT_PRINT:
if (submit_image (ssm, dev))
{
fpi_ssm_mark_completed (ssm);
/* NOTE: finger off is expected only after submitting image... */
fpi_image_device_report_finger_status (dev, FALSE);
}
else
{
fpi_ssm_jump_to_state (ssm, M_REQUEST_PRINT);
}
break;
default:
g_assert_not_reached ();
}
}
/* Complete loop sequential state machine */
static void m_loop_complete(FpiSsm *ssm, FpDevice *_dev, void *user_data,
GError *error)
static void
m_loop_complete (FpiSsm *ssm, FpDevice *_dev, void *user_data,
GError *error)
{
if (error) {
g_warning ("State machine completed with an error: %s", error->message);
g_error_free (error);
}
/* Free sequential state machine */
fpi_ssm_free(ssm);
if (error)
{
g_warning ("State machine completed with an error: %s", error->message);
g_error_free (error);
}
/* Free sequential state machine */
fpi_ssm_free (ssm);
}
/* Exec init sequential state machine */
static void m_init_state(FpiSsm *ssm, FpDevice *_dev, void *user_data)
static void
m_init_state (FpiSsm *ssm, FpDevice *_dev, void *user_data)
{
FpDeviceVfs301 *self = FPI_DEVICE_VFS301(_dev);
FpDeviceVfs301 *self = FPI_DEVICE_VFS301 (_dev);
g_assert(fpi_ssm_get_cur_state(ssm) == 0);
g_assert (fpi_ssm_get_cur_state (ssm) == 0);
vfs301_proto_init(self);
vfs301_proto_init (self);
fpi_ssm_mark_completed(ssm);
fpi_ssm_mark_completed (ssm);
}
/* Complete init sequential state machine */
static void m_init_complete(FpiSsm *ssm, FpDevice *dev, void *user_data,
GError *error)
static void
m_init_complete (FpiSsm *ssm, FpDevice *dev, void *user_data,
GError *error)
{
FpiSsm *ssm_loop;
FpiSsm *ssm_loop;
fpi_image_device_activate_complete(FP_IMAGE_DEVICE (dev), error);
if (!error) {
/* Notify activate complete */
fpi_image_device_activate_complete (FP_IMAGE_DEVICE (dev), error);
if (!error)
{
/* Notify activate complete */
/* Start loop ssm */
ssm_loop = fpi_ssm_new(dev, m_loop_state,
M_LOOP_NUM_STATES, dev);
fpi_ssm_start(ssm_loop, m_loop_complete);
}
/* Start loop ssm */
ssm_loop = fpi_ssm_new (dev, m_loop_state,
M_LOOP_NUM_STATES, dev);
fpi_ssm_start (ssm_loop, m_loop_complete);
}
/* Free sequential state machine */
fpi_ssm_free(ssm);
/* Free sequential state machine */
fpi_ssm_free (ssm);
}
/* Activate device */
static void dev_activate(FpImageDevice *dev)
static void
dev_activate (FpImageDevice *dev)
{
FpiSsm *ssm;
FpiSsm *ssm;
/* Start init ssm */
ssm = fpi_ssm_new(FP_DEVICE(dev), m_init_state, 1, dev);
fpi_ssm_start(ssm, m_init_complete);
/* Start init ssm */
ssm = fpi_ssm_new (FP_DEVICE (dev), m_init_state, 1, dev);
fpi_ssm_start (ssm, m_init_complete);
}
/* Deactivate device */
static void dev_deactivate(FpImageDevice *dev)
static void
dev_deactivate (FpImageDevice *dev)
{
FpDeviceVfs301 *self;
FpDeviceVfs301 *self;
self = FPI_DEVICE_VFS301(dev);
vfs301_proto_deinit(self);
fpi_image_device_deactivate_complete(dev, NULL);
self = FPI_DEVICE_VFS301 (dev);
vfs301_proto_deinit (self);
fpi_image_device_deactivate_complete (dev, NULL);
}
static void dev_open(FpImageDevice *dev)
static void
dev_open (FpImageDevice *dev)
{
FpDeviceVfs301 *self = FPI_DEVICE_VFS301(dev);
GError *error = NULL;
FpDeviceVfs301 *self = FPI_DEVICE_VFS301 (dev);
GError *error = NULL;
/* Claim usb interface */
g_usb_device_claim_interface(fpi_device_get_usb_device(FP_DEVICE(dev)), 0, 0, &error);
/* Claim usb interface */
g_usb_device_claim_interface (fpi_device_get_usb_device (FP_DEVICE (dev)), 0, 0, &error);
/* Initialize private structure */
self->scanline_count = 0;
/* Initialize private structure */
self->scanline_count = 0;
/* Notify open complete */
fpi_image_device_open_complete(dev, error);
/* Notify open complete */
fpi_image_device_open_complete (dev, error);
}
static void dev_close(FpImageDevice *dev)
static void
dev_close (FpImageDevice *dev)
{
FpDeviceVfs301 *self = FPI_DEVICE_VFS301(dev);
GError *error = NULL;
FpDeviceVfs301 *self = FPI_DEVICE_VFS301 (dev);
GError *error = NULL;
/* Release private structure */
g_clear_pointer (&self->scanline_buf, g_free);
/* Release private structure */
g_clear_pointer (&self->scanline_buf, g_free);
/* Release usb interface */
g_usb_device_release_interface(fpi_device_get_usb_device(FP_DEVICE(dev)),
0, 0, &error);
/* Release usb interface */
g_usb_device_release_interface (fpi_device_get_usb_device (FP_DEVICE (dev)),
0, 0, &error);
/* Notify close complete */
fpi_image_device_close_complete(dev, error);
/* Notify close complete */
fpi_image_device_close_complete (dev, error);
}
/* Usb id table of device */
static const FpIdEntry id_table [ ] = {
{ /* vfs301 */ .vid = 0x138a, .pid = 0x0005, },
{ /* vfs300 */ .vid = 0x138a, .pid = 0x0008, },
{ .vid = 0, .pid = 0, .driver_data = 0 },
static const FpIdEntry id_table[] = {
{ /* vfs301 */ .vid = 0x138a, .pid = 0x0005, },
{ /* vfs300 */ .vid = 0x138a, .pid = 0x0008, },
{ .vid = 0, .pid = 0, .driver_data = 0 },
};
static void fpi_device_vfs301_init(FpDeviceVfs301 *self) {
static void
fpi_device_vfs301_init (FpDeviceVfs301 *self)
{
}
static void fpi_device_vfs301_class_init(FpDeviceVfs301Class *klass) {
FpDeviceClass *dev_class = FP_DEVICE_CLASS(klass);
FpImageDeviceClass *img_class = FP_IMAGE_DEVICE_CLASS(klass);
static void
fpi_device_vfs301_class_init (FpDeviceVfs301Class *klass)
{
FpDeviceClass *dev_class = FP_DEVICE_CLASS (klass);
FpImageDeviceClass *img_class = FP_IMAGE_DEVICE_CLASS (klass);
dev_class->id = "vfs301";
dev_class->full_name = "Validity VFS301";
dev_class->type = FP_DEVICE_TYPE_USB;
dev_class->id_table = id_table;
dev_class->scan_type = FP_SCAN_TYPE_SWIPE;
dev_class->id = "vfs301";
dev_class->full_name = "Validity VFS301";
dev_class->type = FP_DEVICE_TYPE_USB;
dev_class->id_table = id_table;
dev_class->scan_type = FP_SCAN_TYPE_SWIPE;
img_class->img_open = dev_open;
img_class->img_close = dev_close;
img_class->activate = dev_activate;
img_class->deactivate = dev_deactivate;
img_class->img_open = dev_open;
img_class->img_close = dev_close;
img_class->activate = dev_activate;
img_class->deactivate = dev_deactivate;
img_class->bz3_threshold = 24;
img_class->bz3_threshold = 24;
img_class->img_width = VFS301_FP_WIDTH;
img_class->img_height = -1;
img_class->img_width = VFS301_FP_WIDTH;
img_class->img_height = -1;
}

View file

@ -25,113 +25,118 @@
#include "fpi-image-device.h"
enum {
VFS301_DEFAULT_WAIT_TIMEOUT = 300,
VFS301_DEFAULT_WAIT_TIMEOUT = 300,
VFS301_SEND_ENDPOINT = 0x01,
VFS301_RECEIVE_ENDPOINT_CTRL = 0x81,
VFS301_RECEIVE_ENDPOINT_DATA = 0x82
VFS301_SEND_ENDPOINT = 0x01,
VFS301_RECEIVE_ENDPOINT_CTRL = 0x81,
VFS301_RECEIVE_ENDPOINT_DATA = 0x82
};
#define VFS301_FP_RECV_LEN_1 (84032)
#define VFS301_FP_RECV_LEN_2 (84096)
struct _FpDeviceVfs301 {
FpImageDevice parent;
struct _FpDeviceVfs301
{
FpImageDevice parent;
/* buffer to hold raw scanlines */
unsigned char *scanline_buf;
int scanline_count;
/* buffer to hold raw scanlines */
unsigned char *scanline_buf;
int scanline_count;
enum {
VFS301_ONGOING = 0,
VFS301_ENDED = 1,
VFS301_FAILURE = -1
} recv_progress;
int recv_exp_amt;
enum {
VFS301_ONGOING = 0,
VFS301_ENDED = 1,
VFS301_FAILURE = -1
} recv_progress;
int recv_exp_amt;
};
G_DECLARE_FINAL_TYPE (FpDeviceVfs301, fpi_device_vfs301, FPI, DEVICE_VFS301, FpImageDevice)
enum {
/* Width of the scanned data in px */
VFS301_FP_WIDTH = 200,
/* Width of the scanned data in px */
VFS301_FP_WIDTH = 200,
/* sizeof(fp_line_t) */
VFS301_FP_FRAME_SIZE = 288,
/* Width of output line */
/* sizeof(fp_line_t) */
VFS301_FP_FRAME_SIZE = 288,
/* Width of output line */
#ifndef OUTPUT_RAW
VFS301_FP_OUTPUT_WIDTH = VFS301_FP_WIDTH,
VFS301_FP_OUTPUT_WIDTH = VFS301_FP_WIDTH,
#else
VFS301_FP_OUTPUT_WIDTH = VFS301_FP_FRAME_SIZE,
VFS301_FP_OUTPUT_WIDTH = VFS301_FP_FRAME_SIZE,
#endif
VFS301_FP_SUM_LINES = 3,
VFS301_FP_SUM_LINES = 3,
#ifdef SCAN_FINISH_DETECTION
/* TODO: The following changes (seen ~60 and ~80) In that
* case we'll need to calibrate this from empty data somehow... */
VFS301_FP_SUM_MEDIAN = 60,
VFS301_FP_SUM_EMPTY_RANGE = 5,
/* TODO: The following changes (seen ~60 and ~80) In that
* case we'll need to calibrate this from empty data somehow... */
VFS301_FP_SUM_MEDIAN = 60,
VFS301_FP_SUM_EMPTY_RANGE = 5,
#endif
/* Minimum average difference between returned lines */
VFS301_FP_LINE_DIFF_THRESHOLD = 15,
/* Minimum average difference between returned lines */
VFS301_FP_LINE_DIFF_THRESHOLD = 15,
/* Maximum waiting time for a single fingerprint frame */
VFS301_FP_RECV_TIMEOUT = 2000
/* Maximum waiting time for a single fingerprint frame */
VFS301_FP_RECV_TIMEOUT = 2000
};
/* Arrays of this structure is returned during the initialization as a response
* to the 0x02D0 messages.
* It seems to be always the same - what is it for? Some kind of confirmation?
*/
typedef struct {
unsigned char sync_0x01;
unsigned char sync_0xfe;
typedef struct
{
unsigned char sync_0x01;
unsigned char sync_0xfe;
unsigned char counter_lo;
unsigned char counter_hi; /* FIXME ? */
unsigned char counter_lo;
unsigned char counter_hi; /* FIXME ? */
unsigned char flags[3];
unsigned char flags[3];
unsigned char sync_0x00;
unsigned char sync_0x00;
unsigned char scan[VFS301_FP_WIDTH];
unsigned char scan[VFS301_FP_WIDTH];
} vfs301_init_line_t;
typedef struct {
unsigned char sync_0x01;
unsigned char sync_0xfe;
typedef struct
{
unsigned char sync_0x01;
unsigned char sync_0xfe;
unsigned char counter_lo;
unsigned char counter_hi;
unsigned char counter_lo;
unsigned char counter_hi;
unsigned char sync_0x08[2]; /* XXX: always? 0x08 0x08 */
/* 0x08 | 0x18 - Looks like 0x08 marks good quality lines */
unsigned char flag_1;
unsigned char sync_0x00;
unsigned char sync_0x08[2]; /* XXX: always? 0x08 0x08 */
/* 0x08 | 0x18 - Looks like 0x08 marks good quality lines */
unsigned char flag_1;
unsigned char sync_0x00;
unsigned char scan[VFS301_FP_WIDTH];
unsigned char scan[VFS301_FP_WIDTH];
/* A offsetted, stretched, inverted copy of scan... probably could
* serve finger motion speed detection?
* Seems to be subdivided to some 10B + 53B + 1B blocks */
unsigned char mirror[64];
/* A offsetted, stretched, inverted copy of scan... probably could
* serve finger motion speed detection?
* Seems to be subdivided to some 10B + 53B + 1B blocks */
unsigned char mirror[64];
/* Some kind of sum of the scan, very low contrast */
unsigned char sum1[2];
unsigned char sum2[11];
unsigned char sum3[3];
/* Some kind of sum of the scan, very low contrast */
unsigned char sum1[2];
unsigned char sum2[11];
unsigned char sum3[3];
} vfs301_line_t;
void vfs301_proto_init(FpDeviceVfs301 *dev);
void vfs301_proto_deinit(FpDeviceVfs301 *dev);
void vfs301_proto_init (FpDeviceVfs301 *dev);
void vfs301_proto_deinit (FpDeviceVfs301 *dev);
void vfs301_proto_request_fingerprint(FpDeviceVfs301 *dev);
void vfs301_proto_request_fingerprint (FpDeviceVfs301 *dev);
/** returns 0 if no event is ready, or 1 if there is one... */
int vfs301_proto_peek_event(FpDeviceVfs301 *dev);
void vfs301_proto_process_event_start(FpDeviceVfs301 *dev);
int vfs301_proto_process_event_poll(FpDeviceVfs301 *dev);
int vfs301_proto_peek_event (FpDeviceVfs301 *dev);
void vfs301_proto_process_event_start (FpDeviceVfs301 *dev);
int vfs301_proto_process_event_poll (FpDeviceVfs301 *dev);
void vfs301_extract_image(FpDeviceVfs301 *vfs, unsigned char *output, int *output_height);
void vfs301_extract_image (FpDeviceVfs301 *vfs,
unsigned char *output,
int *output_height);

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -36,60 +36,64 @@
#include <gio/gio.h>
#include <gio/gunixsocketaddress.h>
struct _FpDeviceVirtualImage {
FpImageDevice parent;
struct _FpDeviceVirtualImage
{
FpImageDevice parent;
GSocketListener *listener;
GSocketConnection *connection;
GCancellable *cancellable;
GSocketListener *listener;
GSocketConnection *connection;
GCancellable *cancellable;
gint socket_fd;
gint client_fd;
gint socket_fd;
gint client_fd;
FpImage *recv_img;
gint recv_img_hdr[2];
FpImage *recv_img;
gint recv_img_hdr[2];
};
G_DECLARE_FINAL_TYPE (FpDeviceVirtualImage, fpi_device_virtual_image, FPI, DEVICE_VIRTUAL_IMAGE, FpImageDevice)
G_DEFINE_TYPE (FpDeviceVirtualImage, fpi_device_virtual_image, FP_TYPE_IMAGE_DEVICE)
static void start_listen (FpDeviceVirtualImage *dev);
static void recv_image (FpDeviceVirtualImage *dev, GInputStream *stream);
static void recv_image (FpDeviceVirtualImage *dev,
GInputStream *stream);
static void
recv_image_img_recv_cb (GObject *source_object,
GAsyncResult *res,
gpointer user_data)
{
g_autoptr(GError) error = NULL;
FpDeviceVirtualImage *self;
FpImageDevice *device;
gssize bytes;
g_autoptr(GError) error = NULL;
FpDeviceVirtualImage *self;
FpImageDevice *device;
gssize bytes;
bytes = g_input_stream_read_finish (G_INPUT_STREAM (source_object), res, &error);
bytes = g_input_stream_read_finish (G_INPUT_STREAM (source_object), res, &error);
if (bytes <= 0) {
if (bytes < 0) {
g_warning ("Error receiving header for image data: %s", error->message);
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
return;
}
if (bytes <= 0)
{
if (bytes < 0)
{
g_warning ("Error receiving header for image data: %s", error->message);
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
return;
}
self = FPI_DEVICE_VIRTUAL_IMAGE (user_data);
g_io_stream_close (G_IO_STREAM (self->connection), NULL, NULL);
self->connection = NULL;
return;
}
self = FPI_DEVICE_VIRTUAL_IMAGE (user_data);
g_io_stream_close (G_IO_STREAM (self->connection), NULL, NULL);
self->connection = NULL;
return;
}
self = FPI_DEVICE_VIRTUAL_IMAGE (user_data);
device = FP_IMAGE_DEVICE (self);
self = FPI_DEVICE_VIRTUAL_IMAGE (user_data);
device = FP_IMAGE_DEVICE (self);
fpi_image_device_report_finger_status (device, TRUE);
fpi_image_device_image_captured (device, g_steal_pointer (&self->recv_img));
fpi_image_device_report_finger_status (device, FALSE);
fpi_image_device_report_finger_status (device, TRUE);
fpi_image_device_image_captured (device, g_steal_pointer (&self->recv_img));
fpi_image_device_report_finger_status (device, FALSE);
/* And, listen for more images from the same client. */
recv_image(self, G_INPUT_STREAM (source_object));
/* And, listen for more images from the same client. */
recv_image (self, G_INPUT_STREAM (source_object));
}
static void
@ -97,180 +101,189 @@ recv_image_hdr_recv_cb (GObject *source_object,
GAsyncResult *res,
gpointer user_data)
{
g_autoptr(GError) error = NULL;
FpDeviceVirtualImage *self;
gssize bytes;
g_autoptr(GError) error = NULL;
FpDeviceVirtualImage *self;
gssize bytes;
bytes = g_input_stream_read_finish (G_INPUT_STREAM (source_object), res, &error);
bytes = g_input_stream_read_finish (G_INPUT_STREAM (source_object), res, &error);
if (bytes <= 0) {
if (bytes < 0) {
g_warning ("Error receiving header for image data: %s", error->message);
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
return;
}
if (bytes <= 0)
{
if (bytes < 0)
{
g_warning ("Error receiving header for image data: %s", error->message);
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
return;
}
self = FPI_DEVICE_VIRTUAL_IMAGE (user_data);
g_io_stream_close (G_IO_STREAM (self->connection), NULL, NULL);
self->connection = NULL;
return;
}
self = FPI_DEVICE_VIRTUAL_IMAGE (user_data);
g_io_stream_close (G_IO_STREAM (self->connection), NULL, NULL);
self->connection = NULL;
return;
}
self = FPI_DEVICE_VIRTUAL_IMAGE (user_data);
if (self->recv_img_hdr[0] > 5000 || self->recv_img_hdr[1] > 5000) {
g_warning ("Image header suggests an unrealistically large image, disconnecting client.");
g_io_stream_close (G_IO_STREAM (self->connection), NULL, NULL);
self->connection = NULL;
}
self = FPI_DEVICE_VIRTUAL_IMAGE (user_data);
if (self->recv_img_hdr[0] > 5000 || self->recv_img_hdr[1] > 5000)
{
g_warning ("Image header suggests an unrealistically large image, disconnecting client.");
g_io_stream_close (G_IO_STREAM (self->connection), NULL, NULL);
self->connection = NULL;
}
if (self->recv_img_hdr[0] < 0 || self->recv_img_hdr[1] < 0) {
switch (self->recv_img_hdr[0]) {
case -1:
/* -1 is a retry error, just pass it through */
fpi_image_device_retry_scan (FP_IMAGE_DEVICE (self), self->recv_img_hdr[1]);
break;
if (self->recv_img_hdr[0] < 0 || self->recv_img_hdr[1] < 0)
{
switch (self->recv_img_hdr[0])
{
case -1:
/* -1 is a retry error, just pass it through */
fpi_image_device_retry_scan (FP_IMAGE_DEVICE (self), self->recv_img_hdr[1]);
break;
case -2:
/* -2 is a fatal error, just pass it through*/
fpi_image_device_session_error (FP_IMAGE_DEVICE (self),
fpi_device_error_new (self->recv_img_hdr[1]));
break;
case -2:
/* -2 is a fatal error, just pass it through*/
fpi_image_device_session_error (FP_IMAGE_DEVICE (self),
fpi_device_error_new (self->recv_img_hdr[1]));
break;
default:
/* disconnect client, it didn't play fair */
g_io_stream_close (G_IO_STREAM (self->connection), NULL, NULL);
self->connection = NULL;
}
default:
/* disconnect client, it didn't play fair */
g_io_stream_close (G_IO_STREAM (self->connection), NULL, NULL);
self->connection = NULL;
}
/* And, listen for more images from the same client. */
recv_image(self, G_INPUT_STREAM (source_object));
return;
}
/* And, listen for more images from the same client. */
recv_image (self, G_INPUT_STREAM (source_object));
return;
}
self->recv_img = fp_image_new (self->recv_img_hdr[0], self->recv_img_hdr[1]);
g_debug ("image data: %p", self->recv_img->data);
g_input_stream_read_async (G_INPUT_STREAM (source_object),
(guint8*)self->recv_img->data,
self->recv_img->width * self->recv_img->height,
G_PRIORITY_DEFAULT,
self->cancellable,
recv_image_img_recv_cb,
self);
self->recv_img = fp_image_new (self->recv_img_hdr[0], self->recv_img_hdr[1]);
g_debug ("image data: %p", self->recv_img->data);
g_input_stream_read_async (G_INPUT_STREAM (source_object),
(guint8 *) self->recv_img->data,
self->recv_img->width * self->recv_img->height,
G_PRIORITY_DEFAULT,
self->cancellable,
recv_image_img_recv_cb,
self);
}
static void
recv_image (FpDeviceVirtualImage *dev, GInputStream *stream)
{
g_input_stream_read_async (stream,
dev->recv_img_hdr,
sizeof(dev->recv_img_hdr),
G_PRIORITY_DEFAULT,
dev->cancellable,
recv_image_hdr_recv_cb,
dev);
g_input_stream_read_async (stream,
dev->recv_img_hdr,
sizeof (dev->recv_img_hdr),
G_PRIORITY_DEFAULT,
dev->cancellable,
recv_image_hdr_recv_cb,
dev);
}
static void
new_connection_cb (GObject *source_object, GAsyncResult *res, gpointer user_data)
{
g_autoptr(GError) error = NULL;
GSocketConnection *connection;
GInputStream *stream;
FpDeviceVirtualImage *dev = user_data;
g_autoptr(GError) error = NULL;
GSocketConnection *connection;
GInputStream *stream;
FpDeviceVirtualImage *dev = user_data;
connection = g_socket_listener_accept_finish (G_SOCKET_LISTENER (source_object),
res,
NULL,
&error);
if (!connection) {
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
return;
connection = g_socket_listener_accept_finish (G_SOCKET_LISTENER (source_object),
res,
NULL,
&error);
if (!connection)
{
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
return;
g_warning ("Error accepting a new connection: %s", error->message);
start_listen(dev);
}
g_warning ("Error accepting a new connection: %s", error->message);
start_listen (dev);
}
/* Always further connections (but we disconnect them immediately
* if we already have a connection). */
start_listen(dev);
if (dev->connection) {
g_io_stream_close (G_IO_STREAM (connection), NULL, NULL);
return;
}
/* Always further connections (but we disconnect them immediately
* if we already have a connection). */
start_listen (dev);
if (dev->connection)
{
g_io_stream_close (G_IO_STREAM (connection), NULL, NULL);
return;
}
dev->connection = connection;
stream = g_io_stream_get_input_stream (G_IO_STREAM (connection));
dev->connection = connection;
stream = g_io_stream_get_input_stream (G_IO_STREAM (connection));
recv_image (dev, stream);
recv_image (dev, stream);
fp_dbg("Got a new connection!");
fp_dbg ("Got a new connection!");
}
static void
start_listen (FpDeviceVirtualImage *dev)
{
g_socket_listener_accept_async (dev->listener,
dev->cancellable,
new_connection_cb,
dev);
g_socket_listener_accept_async (dev->listener,
dev->cancellable,
new_connection_cb,
dev);
}
static void
dev_init(FpImageDevice *dev)
dev_init (FpImageDevice *dev)
{
g_autoptr(GError) error = NULL;
g_autoptr(GSocketListener) listener = NULL;
FpDeviceVirtualImage *self = FPI_DEVICE_VIRTUAL_IMAGE (dev);
const char *env;
g_autoptr(GSocketAddress) addr = NULL;
G_DEBUG_HERE();
g_autoptr(GError) error = NULL;
g_autoptr(GSocketListener) listener = NULL;
FpDeviceVirtualImage *self = FPI_DEVICE_VIRTUAL_IMAGE (dev);
const char *env;
g_autoptr(GSocketAddress) addr = NULL;
G_DEBUG_HERE ();
self->client_fd = -1;
self->client_fd = -1;
env = fpi_device_get_virtual_env (FP_DEVICE (self));
env = fpi_device_get_virtual_env (FP_DEVICE (self));
listener = g_socket_listener_new ();
g_socket_listener_set_backlog (listener, 1);
listener = g_socket_listener_new ();
g_socket_listener_set_backlog (listener, 1);
/* Remove any left over socket. */
g_unlink (env);
/* Remove any left over socket. */
g_unlink (env);
addr = g_unix_socket_address_new (env);
addr = g_unix_socket_address_new (env);
if (!g_socket_listener_add_address (listener,
addr,
G_SOCKET_TYPE_STREAM,
G_SOCKET_PROTOCOL_DEFAULT,
NULL,
NULL,
&error)) {
g_warning ("Could not listen on unix socket: %s", error->message);
if (!g_socket_listener_add_address (listener,
addr,
G_SOCKET_TYPE_STREAM,
G_SOCKET_PROTOCOL_DEFAULT,
NULL,
NULL,
&error))
{
g_warning ("Could not listen on unix socket: %s", error->message);
fpi_image_device_open_complete (FP_IMAGE_DEVICE (dev), g_steal_pointer (&error));
fpi_image_device_open_complete (FP_IMAGE_DEVICE (dev), g_steal_pointer (&error));
return;
}
return;
}
self->listener = g_steal_pointer (&listener);
self->cancellable = g_cancellable_new ();
self->listener = g_steal_pointer (&listener);
self->cancellable = g_cancellable_new ();
start_listen (self);
start_listen (self);
fpi_image_device_open_complete (dev, NULL);
fpi_image_device_open_complete (dev, NULL);
}
static void dev_deinit(FpImageDevice *dev)
static void
dev_deinit (FpImageDevice *dev)
{
FpDeviceVirtualImage *self = FPI_DEVICE_VIRTUAL_IMAGE (dev);
FpDeviceVirtualImage *self = FPI_DEVICE_VIRTUAL_IMAGE (dev);
G_DEBUG_HERE();
G_DEBUG_HERE ();
g_cancellable_cancel (self->cancellable);
g_clear_object (&self->cancellable);
g_clear_object (&self->listener);
g_clear_object (&self->connection);
g_cancellable_cancel (self->cancellable);
g_clear_object (&self->cancellable);
g_clear_object (&self->listener);
g_clear_object (&self->connection);
fpi_image_device_close_complete(dev, NULL);
fpi_image_device_close_complete (dev, NULL);
}
static void
@ -279,22 +292,21 @@ fpi_device_virtual_image_init (FpDeviceVirtualImage *self)
}
static const FpIdEntry driver_ids[] = {
{ .virtual_envvar = "FP_VIRTUAL_IMAGE" },
{ .virtual_envvar = NULL }
{ .virtual_envvar = "FP_VIRTUAL_IMAGE" },
{ .virtual_envvar = NULL }
};
static void
fpi_device_virtual_image_class_init (FpDeviceVirtualImageClass *klass)
{
FpDeviceClass *dev_class = FP_DEVICE_CLASS (klass);
FpImageDeviceClass *img_class = FP_IMAGE_DEVICE_CLASS (klass);
FpDeviceClass *dev_class = FP_DEVICE_CLASS (klass);
FpImageDeviceClass *img_class = FP_IMAGE_DEVICE_CLASS (klass);
dev_class->id = FP_COMPONENT;
dev_class->full_name = "Virtual image device for debugging";
dev_class->type = FP_DEVICE_TYPE_VIRTUAL;
dev_class->id_table = driver_ids;
dev_class->id = FP_COMPONENT;
dev_class->full_name = "Virtual image device for debugging";
dev_class->type = FP_DEVICE_TYPE_VIRTUAL;
dev_class->id_table = driver_ids;
img_class->img_open = dev_init;
img_class->img_close = dev_deinit;
img_class->img_open = dev_init;
img_class->img_close = dev_deinit;
}

View file

@ -26,26 +26,28 @@
#include "fpi-image-device.h"
/* fp_minutia structure definition */
struct fp_minutia {
int x;
int y;
int ex;
int ey;
int direction;
double reliability;
int type;
int appearing;
int feature_id;
int *nbrs;
int *ridge_counts;
int num_nbrs;
struct fp_minutia
{
int x;
int y;
int ex;
int ey;
int direction;
double reliability;
int type;
int appearing;
int feature_id;
int *nbrs;
int *ridge_counts;
int num_nbrs;
};
/* fp_minutiae structure definition */
struct fp_minutiae {
int alloc;
int num;
struct fp_minutia **list;
struct fp_minutiae
{
int alloc;
int num;
struct fp_minutia **list;
};

View file

@ -1,5 +1,5 @@
/*
* Copyright (C) 2009 Red Hat <mjg@redhat.com>
* Copyright (C) 2009 Red Hat <mjg@redhat.com>
* Copyright (C) 2008 Bastien Nocera <hadess@hadess.net>
* Copyright (C) 2008 Timo Hoenig <thoenig@suse.de>, <thoenig@nouse.net>
* Coypright (C) 2019 Benjamin Berg <bberg@redhat.com>
@ -28,9 +28,10 @@
GHashTable *printed = NULL;
static GList *insert_drivers (GList *list)
static GList *
insert_drivers (GList *list)
{
g_autoptr(GArray) drivers = g_array_new (FALSE, FALSE, sizeof(GType));
g_autoptr(GArray) drivers = g_array_new (FALSE, FALSE, sizeof (GType));
gint i;
fpi_get_driver_types (drivers);
@ -42,10 +43,11 @@ static GList *insert_drivers (GList *list)
FpDeviceClass *cls = FP_DEVICE_CLASS (g_type_class_ref (driver));
const FpIdEntry *entry;
if (cls->type != FP_DEVICE_TYPE_USB) {
g_type_class_unref (cls);
continue;
}
if (cls->type != FP_DEVICE_TYPE_USB)
{
g_type_class_unref (cls);
continue;
}
for (entry = cls->id_table; entry->vid; entry++)
{
@ -53,53 +55,55 @@ static GList *insert_drivers (GList *list)
key = g_strdup_printf ("%04x:%04x", entry->vid, entry->pid);
if (g_hash_table_lookup (printed, key) != NULL) {
g_free (key);
continue;
}
if (g_hash_table_lookup (printed, key) != NULL)
{
g_free (key);
continue;
}
g_hash_table_insert (printed, key, GINT_TO_POINTER (1));
g_hash_table_insert (printed, key, GINT_TO_POINTER (1));
list = g_list_prepend (list, g_strdup_printf ("%s | %s\n", key, cls->full_name));
list = g_list_prepend (list, g_strdup_printf ("%s | %s\n", key, cls->full_name));
}
g_type_class_unref (cls);
}
return list;
return list;
}
int main (int argc, char **argv)
int
main (int argc, char **argv)
{
GList *list, *l;
GList *list, *l;
setlocale (LC_ALL, "");
setlocale (LC_ALL, "");
printed = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
printed = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
g_print ("%% lifprint — Supported Devices\n");
g_print ("%% Bastien Nocera, Daniel Drake\n");
g_print ("%% 2018\n");
g_print ("\n");
g_print ("%% lifprint — Supported Devices\n");
g_print ("%% Bastien Nocera, Daniel Drake\n");
g_print ("%% 2018\n");
g_print ("\n");
g_print ("# Supported Devices\n");
g_print ("\n");
g_print ("This is a list of supported devices in libfprint's development version. Those drivers might not all be available in the stable, released version. If in doubt, contact your distribution or systems integrator for details.\n");
g_print ("\n");
g_print ("## USB devices\n");
g_print ("\n");
g_print ("USB ID | Driver\n");
g_print ("------------ | ------------\n");
g_print ("# Supported Devices\n");
g_print ("\n");
g_print ("This is a list of supported devices in libfprint's development version. Those drivers might not all be available in the stable, released version. If in doubt, contact your distribution or systems integrator for details.\n");
g_print ("\n");
g_print ("## USB devices\n");
g_print ("\n");
g_print ("USB ID | Driver\n");
g_print ("------------ | ------------\n");
list = NULL;
list = insert_drivers (list);
list = NULL;
list = insert_drivers (list);
list = g_list_sort (list, (GCompareFunc) g_strcmp0);
for (l = list; l != NULL; l = l->next)
g_print ("%s", (char *) l->data);
list = g_list_sort (list, (GCompareFunc) g_strcmp0);
for (l = list; l != NULL; l = l->next)
g_print ("%s", (char *) l->data);
g_list_free_full (list, g_free);
g_hash_table_destroy (printed);
g_list_free_full (list, g_free);
g_hash_table_destroy (printed);
return 0;
return 0;
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (C) 2009 Red Hat <mjg@redhat.com>
* Copyright (C) 2009 Red Hat <mjg@redhat.com>
* Copyright (C) 2008 Bastien Nocera <hadess@hadess.net>
* Copyright (C) 2008 Timo Hoenig <thoenig@suse.de>, <thoenig@nouse.net>
* Coypright (C) 2019 Benjamin Berg <bberg@redhat.com>
@ -25,100 +25,105 @@
#include "fpi-device.h"
static const FpIdEntry whitelist_id_table[] = {
/* Unsupported (for now) Validity Sensors finger print readers */
{ .vid = 0x138a, .pid = 0x0090 }, /* Found on e.g. Lenovo T460s */
{ .vid = 0x138a, .pid = 0x0091 },
{ .vid = 0x138a, .pid = 0x0094 },
{ .vid = 0x138a, .pid = 0x0097 }, /* Found on e.g. Lenovo T470s */
{ .vid = 0 },
/* Unsupported (for now) Validity Sensors finger print readers */
{ .vid = 0x138a, .pid = 0x0090 }, /* Found on e.g. Lenovo T460s */
{ .vid = 0x138a, .pid = 0x0091 },
{ .vid = 0x138a, .pid = 0x0094 },
{ .vid = 0x138a, .pid = 0x0097 }, /* Found on e.g. Lenovo T470s */
{ .vid = 0 },
};
static const FpIdEntry blacklist_id_table[] = {
{ .vid = 0x0483, .pid = 0x2016 },
/* https://bugs.freedesktop.org/show_bug.cgi?id=66659 */
{ .vid = 0x045e, .pid = 0x00bb },
{ .vid = 0 },
{ .vid = 0x0483, .pid = 0x2016 },
/* https://bugs.freedesktop.org/show_bug.cgi?id=66659 */
{ .vid = 0x045e, .pid = 0x00bb },
{ .vid = 0 },
};
static const FpDeviceClass whitelist = {
.type = FP_DEVICE_TYPE_USB,
.id_table = whitelist_id_table,
.full_name = "Hardcoded whitelist"
.type = FP_DEVICE_TYPE_USB,
.id_table = whitelist_id_table,
.full_name = "Hardcoded whitelist"
};
GHashTable *printed = NULL;
static void print_driver (const FpDeviceClass *cls)
static void
print_driver (const FpDeviceClass *cls)
{
const FpIdEntry *entry;
gint num_printed = 0;
const FpIdEntry *entry;
gint num_printed = 0;
if (cls->type != FP_DEVICE_TYPE_USB)
return;
if (cls->type != FP_DEVICE_TYPE_USB)
return;
for (entry = cls->id_table; entry->vid != 0; entry++) {
const FpIdEntry *bl_entry;
char *key;
for (entry = cls->id_table; entry->vid != 0; entry++)
{
const FpIdEntry *bl_entry;
char *key;
for (bl_entry = blacklist_id_table; bl_entry->vid != 0; bl_entry++) {
if (entry->vid == bl_entry->vid && entry->pid == bl_entry->pid) {
break;
}
}
if (bl_entry->vid != 0)
continue;
for (bl_entry = blacklist_id_table; bl_entry->vid != 0; bl_entry++)
if (entry->vid == bl_entry->vid && entry->pid == bl_entry->pid)
break;
key = g_strdup_printf ("%04x:%04x", entry->vid, entry->pid);
if (bl_entry->vid != 0)
continue;
if (g_hash_table_lookup (printed, key) != NULL) {
g_free (key);
continue;
}
key = g_strdup_printf ("%04x:%04x", entry->vid, entry->pid);
g_hash_table_insert (printed, key, GINT_TO_POINTER (1));
if (g_hash_table_lookup (printed, key) != NULL)
{
g_free (key);
continue;
}
if (num_printed == 0)
g_print ("# %s\n", cls->full_name);
g_hash_table_insert (printed, key, GINT_TO_POINTER (1));
g_print ("SUBSYSTEM==\"usb\", ATTRS{idVendor}==\"%04x\", ATTRS{idProduct}==\"%04x\", ATTRS{dev}==\"*\", TEST==\"power/control\", ATTR{power/control}=\"auto\"\n",
entry->vid, entry->pid);
g_print ("SUBSYSTEM==\"usb\", ATTRS{idVendor}==\"%04x\", ATTRS{idProduct}==\"%04x\", ENV{LIBFPRINT_DRIVER}=\"%s\"\n",
entry->vid, entry->pid, cls->full_name);
num_printed++;
if (num_printed == 0)
g_print ("# %s\n", cls->full_name);
g_print ("SUBSYSTEM==\"usb\", ATTRS{idVendor}==\"%04x\", ATTRS{idProduct}==\"%04x\", ATTRS{dev}==\"*\", TEST==\"power/control\", ATTR{power/control}=\"auto\"\n",
entry->vid, entry->pid);
g_print ("SUBSYSTEM==\"usb\", ATTRS{idVendor}==\"%04x\", ATTRS{idProduct}==\"%04x\", ENV{LIBFPRINT_DRIVER}=\"%s\"\n",
entry->vid, entry->pid, cls->full_name);
num_printed++;
}
if (num_printed > 0)
g_print ("\n");
if (num_printed > 0)
g_print ("\n");
}
int main (int argc, char **argv)
int
main (int argc, char **argv)
{
g_autoptr(GArray) drivers = g_array_new (FALSE, FALSE, sizeof(GType));
guint i;
g_autoptr(GArray) drivers = g_array_new (FALSE, FALSE, sizeof (GType));
guint i;
g_print ("%p\n", drivers);
g_print ("%p\n", fpi_get_driver_types);
fpi_get_driver_types (drivers);
g_print ("%p\n", drivers);
g_print ("%p\n", fpi_get_driver_types);
fpi_get_driver_types (drivers);
printed = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
printed = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
for (i = 0; i < drivers->len; i++) {
GType driver = g_array_index (drivers, GType, i);
FpDeviceClass *cls = FP_DEVICE_CLASS (g_type_class_ref (driver));
for (i = 0; i < drivers->len; i++)
{
GType driver = g_array_index (drivers, GType, i);
FpDeviceClass *cls = FP_DEVICE_CLASS (g_type_class_ref (driver));
if (cls->type != FP_DEVICE_TYPE_USB) {
g_type_class_unref (cls);
continue;
}
if (cls->type != FP_DEVICE_TYPE_USB)
{
g_type_class_unref (cls);
continue;
}
print_driver (cls);
print_driver (cls);
g_type_class_unref (cls);
g_type_class_unref (cls);
}
print_driver (&whitelist);
print_driver (&whitelist);
g_hash_table_destroy (printed);
g_hash_table_destroy (printed);
return 0;
return 0;
}

View file

@ -22,4 +22,3 @@
#include "fp-context.h"
#include "fp-device.h"
#include "fp-image.h"

View file

@ -13,7 +13,7 @@ case "$1" in
esac
pushd "$SRCROOT"
uncrustify -c "$CFG" $OPTS `git ls-tree --name-only -r HEAD | grep -E '(fp|fpi)-.*\.[ch]$' | grep -v nbis | grep -v fpi-byte | grep -v build/`
uncrustify -c "$CFG" $OPTS `git ls-tree --name-only -r HEAD | grep -E '.*\.[ch]$' | grep -v nbis | grep -v fpi-byte | grep -v build/`
RES=$?
popd
exit $RES