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

@ -33,7 +33,8 @@ typedef enum {
IMAGE_DISPLAY_BINARY = 1 << 1 IMAGE_DISPLAY_BINARY = 1 << 1
} ImageDisplayFlags; } ImageDisplayFlags;
typedef struct { typedef struct
{
GtkApplicationWindow parent_instance; GtkApplicationWindow parent_instance;
GtkWidget *header_bar; GtkWidget *header_bar;
@ -79,7 +80,8 @@ img_to_rgbdata (const guint8 *imgdata,
size_t i; size_t i;
size_t rgb_offset = 0; size_t rgb_offset = 0;
for (i = 0; i < size; i++) { for (i = 0; i < size; i++)
{
guint8 pixel = imgdata[i]; guint8 pixel = imgdata[i];
rgbdata[rgb_offset++] = pixel; rgbdata[rgb_offset++] = pixel;
@ -97,33 +99,35 @@ plot_minutiae (unsigned char *rgbdata,
GPtrArray *minutiae) GPtrArray *minutiae)
{ {
int i; int i;
#define write_pixel(num) do { \ #define write_pixel(num) do { \
rgbdata[((num) * 3)] = 0xff; \ rgbdata[((num) * 3)] = 0xff; \
rgbdata[((num) * 3) + 1] = 0; \ rgbdata[((num) * 3) + 1] = 0; \
rgbdata[((num) * 3) + 2] = 0; \ rgbdata[((num) * 3) + 2] = 0; \
} while(0) } while(0)
for (i = 0; i < minutiae->len; i++) { for (i = 0; i < minutiae->len; i++)
{
struct fp_minutia *min = g_ptr_array_index (minutiae, i); struct fp_minutia *min = g_ptr_array_index (minutiae, i);
int x, y; int x, y;
size_t pixel_offset; size_t pixel_offset;
fp_minutia_get_coords(min, &x, &y); fp_minutia_get_coords (min, &x, &y);
pixel_offset = (y * width) + x; pixel_offset = (y * width) + x;
write_pixel(pixel_offset - 2); write_pixel (pixel_offset - 2);
write_pixel(pixel_offset - 1); write_pixel (pixel_offset - 1);
write_pixel(pixel_offset); write_pixel (pixel_offset);
write_pixel(pixel_offset + 1); write_pixel (pixel_offset + 1);
write_pixel(pixel_offset + 2); write_pixel (pixel_offset + 2);
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) - 1);
write_pixel(pixel_offset - (width * 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) - 1); write_pixel (pixel_offset + (width * 1) - 1);
write_pixel(pixel_offset + (width * 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 * 2)); write_pixel (pixel_offset + (width * 2));
} }
} }
@ -149,7 +153,8 @@ img_to_pixbuf (FpImage *img,
rgbdata = img_to_rgbdata (data, width, height); rgbdata = img_to_rgbdata (data, width, height);
if (flags & IMAGE_DISPLAY_MINUTIAE) { if (flags & IMAGE_DISPLAY_MINUTIAE)
{
GPtrArray *minutiae; GPtrArray *minutiae;
minutiae = fp_image_get_minutiae (img); minutiae = fp_image_get_minutiae (img);
@ -167,7 +172,8 @@ update_image (LibfprintDemoWindow *win)
{ {
GdkPixbuf *pixbuf; GdkPixbuf *pixbuf;
if (win->img == NULL) { if (win->img == NULL)
{
gtk_image_clear (GTK_IMAGE (win->capture_image)); gtk_image_clear (GTK_IMAGE (win->capture_image));
return; return;
} }
@ -197,15 +203,18 @@ libfprint_demo_set_capture_label (LibfprintDemoWindow *win)
FpScanType scan_type; FpScanType scan_type;
const char *message; const char *message;
scan_type = fp_device_get_scan_type(win->dev); scan_type = fp_device_get_scan_type (win->dev);
switch (scan_type) { switch (scan_type)
{
case FP_SCAN_TYPE_PRESS: case FP_SCAN_TYPE_PRESS:
message = "Place your finger on the fingerprint reader"; message = "Place your finger on the fingerprint reader";
break; break;
case FP_SCAN_TYPE_SWIPE: case FP_SCAN_TYPE_SWIPE:
message = "Swipe your finger across the fingerprint reader"; message = "Swipe your finger across the fingerprint reader";
break; break;
default: default:
g_assert_not_reached (); g_assert_not_reached ();
} }
@ -225,7 +234,8 @@ dev_capture_start_cb (FpDevice *dev,
g_clear_object (&win->cancellable); g_clear_object (&win->cancellable);
image = fp_device_capture_finish (dev, res, &error); image = fp_device_capture_finish (dev, res, &error);
if (!image) { if (!image)
{
g_warning ("Error capturing data: %s", error->message); g_warning ("Error capturing data: %s", error->message);
if (error->domain == FP_DEVICE_RETRY || if (error->domain == FP_DEVICE_RETRY ||
g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
@ -254,15 +264,17 @@ static void
dev_open_cb (FpDevice *dev, GAsyncResult *res, void *user_data) dev_open_cb (FpDevice *dev, GAsyncResult *res, void *user_data)
{ {
LibfprintDemoWindow *win = user_data; LibfprintDemoWindow *win = user_data;
g_autoptr(GError) error = NULL; g_autoptr(GError) error = NULL;
if (!fp_device_open_finish (dev, res, &error)) { if (!fp_device_open_finish (dev, res, &error))
{
g_warning ("Failed to open device: %s", error->message); g_warning ("Failed to open device: %s", error->message);
libfprint_demo_set_mode (win, ERROR_MODE); libfprint_demo_set_mode (win, ERROR_MODE);
return; return;
} }
dev_start_capture(win); dev_start_capture (win);
} }
static void static void
@ -278,7 +290,8 @@ activate_capture (GSimpleAction *action,
g_clear_object (&win->cancellable); g_clear_object (&win->cancellable);
win->cancellable = g_cancellable_new (); win->cancellable = g_cancellable_new ();
if (win->opened) { if (win->opened)
{
dev_start_capture (win); dev_start_capture (win);
return; return;
} }
@ -411,19 +424,22 @@ libfprint_demo_set_mode (LibfprintDemoWindow *win,
{ {
char *title; char *title;
switch (mode) { switch (mode)
{
case EMPTY_MODE: case EMPTY_MODE:
gtk_stack_set_visible_child_name (GTK_STACK (win->mode_stack), "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->capture_button, FALSE);
gtk_widget_set_sensitive (win->cancel_button, FALSE); gtk_widget_set_sensitive (win->cancel_button, FALSE);
gtk_spinner_stop (GTK_SPINNER (win->spinner)); gtk_spinner_stop (GTK_SPINNER (win->spinner));
break; break;
case NOIMAGING_MODE: case NOIMAGING_MODE:
gtk_stack_set_visible_child_name (GTK_STACK (win->mode_stack), "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->capture_button, FALSE);
gtk_widget_set_sensitive (win->cancel_button, FALSE); gtk_widget_set_sensitive (win->cancel_button, FALSE);
gtk_spinner_stop (GTK_SPINNER (win->spinner)); gtk_spinner_stop (GTK_SPINNER (win->spinner));
break; break;
case CAPTURE_MODE: case CAPTURE_MODE:
gtk_stack_set_visible_child_name (GTK_STACK (win->mode_stack), "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->capture_button, TRUE);
@ -435,24 +451,28 @@ libfprint_demo_set_mode (LibfprintDemoWindow *win,
gtk_spinner_stop (GTK_SPINNER (win->spinner)); gtk_spinner_stop (GTK_SPINNER (win->spinner));
break; break;
case SPINNER_MODE: case SPINNER_MODE:
gtk_stack_set_visible_child_name (GTK_STACK (win->mode_stack), "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->capture_button, FALSE);
gtk_widget_set_sensitive (win->cancel_button, TRUE); gtk_widget_set_sensitive (win->cancel_button, TRUE);
gtk_spinner_start (GTK_SPINNER (win->spinner)); gtk_spinner_start (GTK_SPINNER (win->spinner));
break; break;
case ERROR_MODE: case ERROR_MODE:
gtk_stack_set_visible_child_name (GTK_STACK (win->mode_stack), "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->capture_button, FALSE);
gtk_widget_set_sensitive (win->cancel_button, FALSE); gtk_widget_set_sensitive (win->cancel_button, FALSE);
gtk_spinner_stop (GTK_SPINNER (win->spinner)); gtk_spinner_stop (GTK_SPINNER (win->spinner));
break; break;
case RETRY_MODE: case RETRY_MODE:
gtk_stack_set_visible_child_name (GTK_STACK (win->mode_stack), "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->capture_button, TRUE);
gtk_widget_set_sensitive (win->cancel_button, FALSE); gtk_widget_set_sensitive (win->cancel_button, FALSE);
gtk_spinner_stop (GTK_SPINNER (win->spinner)); gtk_spinner_stop (GTK_SPINNER (win->spinner));
break; break;
default: default:
g_assert_not_reached (); g_assert_not_reached ();
} }
@ -489,19 +509,22 @@ libfprint_demo_window_init (LibfprintDemoWindow *window)
ctx = fp_context_new (); ctx = fp_context_new ();
devices = fp_context_get_devices(ctx); devices = fp_context_get_devices (ctx);
if (!devices) { if (!devices)
{
libfprint_demo_set_mode (window, ERROR_MODE); libfprint_demo_set_mode (window, ERROR_MODE);
return; return;
} }
/* Empty list? */ /* Empty list? */
if (devices->len == 0) { if (devices->len == 0)
{
libfprint_demo_set_mode (window, EMPTY_MODE); libfprint_demo_set_mode (window, EMPTY_MODE);
return; return;
} }
if (!fp_device_supports_capture(g_ptr_array_index (devices, 0))) { if (!fp_device_supports_capture (g_ptr_array_index (devices, 0)))
{
libfprint_demo_set_mode (window, NOIMAGING_MODE); libfprint_demo_set_mode (window, NOIMAGING_MODE);
return; return;
} }
@ -527,7 +550,8 @@ libfprint_demo_window_class_init (LibfprintDemoWindowClass *class)
//FIXME setup dispose //FIXME setup dispose
} }
int main (int argc, char **argv) int
main (int argc, char **argv)
{ {
GtkApplication *app; GtkApplication *app;

View file

@ -24,7 +24,8 @@
#include "storage.h" #include "storage.h"
typedef struct _EnrollData { typedef struct _EnrollData
{
GMainLoop *loop; GMainLoop *loop;
int ret_value; int ret_value;
} EnrollData; } EnrollData;
@ -37,20 +38,23 @@ enroll_data_free (EnrollData *enroll_data)
} }
G_DEFINE_AUTOPTR_CLEANUP_FUNC (EnrollData, enroll_data_free) G_DEFINE_AUTOPTR_CLEANUP_FUNC (EnrollData, enroll_data_free)
FpDevice *discover_device (GPtrArray *devices) FpDevice *discover_device (GPtrArray * devices)
{ {
FpDevice *dev; FpDevice *dev;
if (!devices->len) if (!devices->len)
return NULL; return NULL;
dev = g_ptr_array_index (devices, 0); dev = g_ptr_array_index (devices, 0);
printf("Found device claimed by %s driver\n", fp_device_get_driver (dev)); printf ("Found device claimed by %s driver\n", fp_device_get_driver (dev));
return dev; return dev;
} }
static void static void
on_device_closed (FpDevice *dev, GAsyncResult *res, void *user_data) { on_device_closed (FpDevice *dev, GAsyncResult *res, void *user_data)
{
EnrollData *enroll_data = user_data; EnrollData *enroll_data = user_data;
g_autoptr(GError) error = NULL; g_autoptr(GError) error = NULL;
fp_device_close_finish (dev, res, &error); fp_device_close_finish (dev, res, &error);
@ -62,26 +66,33 @@ on_device_closed (FpDevice *dev, GAsyncResult *res, void *user_data) {
} }
static void static void
on_enroll_completed (FpDevice *dev, GAsyncResult *res, void *user_data) { on_enroll_completed (FpDevice *dev, GAsyncResult *res, void *user_data)
{
EnrollData *enroll_data = user_data; EnrollData *enroll_data = user_data;
g_autoptr(FpPrint) print = NULL; g_autoptr(FpPrint) print = NULL;
g_autoptr(GError) error = NULL; g_autoptr(GError) error = NULL;
print = fp_device_enroll_finish (dev, res, &error); print = fp_device_enroll_finish (dev, res, &error);
if (!error) { if (!error)
{
enroll_data->ret_value = EXIT_SUCCESS; enroll_data->ret_value = EXIT_SUCCESS;
if (!fp_device_has_storage (dev)) { if (!fp_device_has_storage (dev))
g_debug("Device has not storage, saving locally"); {
int r = print_data_save(print, FP_FINGER_RIGHT_INDEX); g_debug ("Device has not storage, saving locally");
if (r < 0) { int r = print_data_save (print, FP_FINGER_RIGHT_INDEX);
g_warning("Data save failed, code %d", r); if (r < 0)
{
g_warning ("Data save failed, code %d", r);
enroll_data->ret_value = EXIT_FAILURE; enroll_data->ret_value = EXIT_FAILURE;
} }
} }
} else { }
g_warning("Enroll failed with error %s\n", error->message); else
{
g_warning ("Enroll failed with error %s\n", error->message);
} }
fp_device_close (dev, NULL, (GAsyncReadyCallback) on_device_closed, fp_device_close (dev, NULL, (GAsyncReadyCallback) on_device_closed,
@ -95,7 +106,8 @@ on_enroll_progress (FpDevice *device,
gpointer user_data, gpointer user_data,
GError *error) GError *error)
{ {
if (error) { if (error)
{
g_warning ("Enroll stage %d of %d failed with error %s", g_warning ("Enroll stage %d of %d failed with error %s",
completed_stages, completed_stages,
fp_device_get_nr_enroll_stages (device), fp_device_get_nr_enroll_stages (device),
@ -104,9 +116,8 @@ on_enroll_progress (FpDevice *device,
} }
if (fp_device_supports_capture (device) && if (fp_device_supports_capture (device) &&
print_image_save (print, "enrolled.pgm")) { print_image_save (print, "enrolled.pgm"))
printf ("Wrote scanned image to enrolled.pgm\n"); printf ("Wrote scanned image to enrolled.pgm\n");
}
printf ("Enroll stage %d of %d passed. Yay!\n", completed_stages, printf ("Enroll stage %d of %d passed. Yay!\n", completed_stages,
fp_device_get_nr_enroll_stages (device)); fp_device_get_nr_enroll_stages (device));
@ -117,9 +128,11 @@ on_device_opened (FpDevice *dev, GAsyncResult *res, void *user_data)
{ {
EnrollData *enroll_data = user_data; EnrollData *enroll_data = user_data;
FpPrint *print_template; FpPrint *print_template;
g_autoptr(GError) error = NULL; g_autoptr(GError) error = NULL;
if (!fp_device_open_finish (dev, res, &error)) { if (!fp_device_open_finish (dev, res, &error))
{
g_warning ("Failed to open device: %s", error->message); g_warning ("Failed to open device: %s", error->message);
g_main_loop_quit (enroll_data->loop); g_main_loop_quit (enroll_data->loop);
return; return;
@ -136,32 +149,35 @@ on_device_opened (FpDevice *dev, GAsyncResult *res, void *user_data)
enroll_data); enroll_data);
} }
int main(void) int
main (void)
{ {
g_autoptr (FpContext) ctx = NULL; g_autoptr(FpContext) ctx = NULL;
g_autoptr (EnrollData) enroll_data = NULL; g_autoptr(EnrollData) enroll_data = NULL;
GPtrArray *devices; GPtrArray *devices;
FpDevice *dev; FpDevice *dev;
printf("This program will enroll your right index finger, " printf ("This program will enroll your right index finger, "
"unconditionally overwriting any right-index print that was enrolled " "unconditionally overwriting any right-index print that was enrolled "
"previously. If you want to continue, press enter, otherwise hit " "previously. If you want to continue, press enter, otherwise hit "
"Ctrl+C\n"); "Ctrl+C\n");
getchar(); 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); devices = fp_context_get_devices (ctx);
if (!devices) { if (!devices)
g_warning("Impossible to get devices"); {
g_warning ("Impossible to get devices");
return EXIT_FAILURE; return EXIT_FAILURE;
} }
dev = discover_device (devices); dev = discover_device (devices);
if (!dev) { if (!dev)
g_warning("No devices detected."); {
g_warning ("No devices detected.");
return EXIT_FAILURE; return EXIT_FAILURE;
} }

View file

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

View file

@ -34,103 +34,112 @@ get_print_data_descriptor (FpPrint *print, FpDevice *dev, FpFinger finger)
const char *driver; const char *driver;
const char *dev_id; const char *dev_id;
if (print) { if (print)
{
driver = fp_print_get_driver (print); driver = fp_print_get_driver (print);
dev_id = fp_print_get_device_id (print); dev_id = fp_print_get_device_id (print);
} else { }
else
{
driver = fp_device_get_driver (dev); driver = fp_device_get_driver (dev);
dev_id = fp_device_get_device_id (dev); dev_id = fp_device_get_device_id (dev);
} }
return g_strdup_printf("%s/%s/%x", return g_strdup_printf ("%s/%s/%x",
driver, driver,
dev_id, dev_id,
finger); finger);
} }
static GVariantDict * static GVariantDict *
load_data(void) load_data (void)
{ {
GVariantDict *res; GVariantDict *res;
GVariant *var; GVariant *var;
g_autofree gchar *contents = NULL; g_autofree gchar *contents = NULL;
gssize length = 0; gssize length = 0;
if (!g_file_get_contents (STORAGE_FILE, &contents, &length, NULL)) { if (!g_file_get_contents (STORAGE_FILE, &contents, &length, NULL))
{
g_warning ("Error loading storage, assuming it is empty"); g_warning ("Error loading storage, assuming it is empty");
return g_variant_dict_new(NULL); 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); res = g_variant_dict_new (var);
g_variant_unref(var); g_variant_unref (var);
return res; return res;
} }
static int static int
save_data(GVariant *data) save_data (GVariant *data)
{ {
const gchar *contents = NULL; const gchar *contents = NULL;
gsize length; gsize length;
length = g_variant_get_size(data); length = g_variant_get_size (data);
contents = (gchar*) g_variant_get_data (data); contents = (gchar *) g_variant_get_data (data);
if (!g_file_set_contents (STORAGE_FILE, contents, length, NULL)) { if (!g_file_set_contents (STORAGE_FILE, contents, length, NULL))
{
g_warning ("Error saving storage,!"); g_warning ("Error saving storage,!");
return -1; return -1;
} }
g_variant_ref_sink(data); g_variant_ref_sink (data);
g_variant_unref(data); g_variant_unref (data);
return 0; return 0;
} }
int 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_autofree gchar *descr = get_print_data_descriptor (print, NULL, finger);
g_autoptr (GError) error = NULL;
g_autoptr (GVariantDict) dict = NULL; g_autoptr(GError) error = NULL;
g_autoptr(GVariantDict) dict = NULL;
g_autofree guchar *data = NULL; g_autofree guchar *data = NULL;
GVariant *val; GVariant *val;
gsize size; gsize size;
int res; int res;
dict = load_data(); dict = load_data ();
fp_print_serialize (print, &data, &size, &error); fp_print_serialize (print, &data, &size, &error);
if (error) { if (error)
{
g_warning ("Error serializing data: %s", error->message); g_warning ("Error serializing data: %s", error->message);
return -1; return -1;
} }
val = g_variant_new_fixed_array (G_VARIANT_TYPE("y"), data, size, 1); val = g_variant_new_fixed_array (G_VARIANT_TYPE ("y"), data, size, 1);
g_variant_dict_insert_value (dict, descr, val); g_variant_dict_insert_value (dict, descr, val);
res = save_data(g_variant_dict_end(dict)); res = save_data (g_variant_dict_end (dict));
return res; return res;
} }
FpPrint * 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_autofree gchar *descr = get_print_data_descriptor (NULL, dev, finger);
g_autoptr (GVariant) val = NULL;
g_autoptr (GVariantDict) dict = NULL; g_autoptr(GVariant) val = NULL;
g_autoptr(GVariantDict) dict = NULL;
g_autofree guchar *stored_data = NULL; g_autofree guchar *stored_data = NULL;
gsize stored_len; gsize stored_len;
dict = load_data(); dict = load_data ();
val = g_variant_dict_lookup_value (dict, descr, G_VARIANT_TYPE ("ay")); val = g_variant_dict_lookup_value (dict, descr, G_VARIANT_TYPE ("ay"));
if (val) { if (val)
{
FpPrint *print; FpPrint *print;
g_autoptr (GError) error = NULL; g_autoptr(GError) error = NULL;
stored_data = (guchar*) g_variant_get_fixed_array (val, &stored_len, 1); stored_data = (guchar *) g_variant_get_fixed_array (val, &stored_len, 1);
print = fp_print_deserialize (stored_data, stored_len, &error); print = fp_print_deserialize (stored_data, stored_len, &error);
if (error) if (error)
@ -171,23 +180,26 @@ save_image_to_pgm (FpImage *img, const char *path)
const guchar *data = fp_image_get_data (img, &write_size); const guchar *data = fp_image_get_data (img, &write_size);
int r; int r;
if (!fd) { if (!fd)
g_warning("could not open '%s' for writing: %d", path, errno); {
g_warning ("could not open '%s' for writing: %d", path, errno);
return FALSE; return FALSE;
} }
r = fprintf (fd, "P5 %d %d 255\n", r = fprintf (fd, "P5 %d %d 255\n",
fp_image_get_width (img), fp_image_get_height (img)); fp_image_get_width (img), fp_image_get_height (img));
if (r < 0) { if (r < 0)
fclose(fd); {
g_critical("pgm header write failed, error %d", r); fclose (fd);
g_critical ("pgm header write failed, error %d", r);
return FALSE; return FALSE;
} }
r = fwrite (data, 1, write_size, fd); r = fwrite (data, 1, write_size, fd);
if (r < write_size) { if (r < write_size)
fclose(fd); {
g_critical("short write (%d)", r); fclose (fd);
g_critical ("short write (%d)", r);
return FALSE; return FALSE;
} }
@ -197,7 +209,8 @@ save_image_to_pgm (FpImage *img, const char *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;

View file

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

View file

@ -24,7 +24,8 @@
#include "storage.h" #include "storage.h"
typedef struct _VerifyData { typedef struct _VerifyData
{
GMainLoop *loop; GMainLoop *loop;
int ret_value; int ret_value;
} VerifyData; } VerifyData;
@ -37,20 +38,23 @@ verify_data_free (VerifyData *verify_data)
} }
G_DEFINE_AUTOPTR_CLEANUP_FUNC (VerifyData, verify_data_free) G_DEFINE_AUTOPTR_CLEANUP_FUNC (VerifyData, verify_data_free)
FpDevice *discover_device (GPtrArray *devices) FpDevice *discover_device (GPtrArray * devices)
{ {
FpDevice *dev; FpDevice *dev;
if (!devices->len) if (!devices->len)
return NULL; return NULL;
dev = g_ptr_array_index (devices, 0); dev = g_ptr_array_index (devices, 0);
printf("Found device claimed by %s driver\n", fp_device_get_driver (dev)); printf ("Found device claimed by %s driver\n", fp_device_get_driver (dev));
return dev; return dev;
} }
static void static void
on_device_closed (FpDevice *dev, GAsyncResult *res, void *user_data) { on_device_closed (FpDevice *dev, GAsyncResult *res, void *user_data)
{
VerifyData *verify_data = user_data; VerifyData *verify_data = user_data;
g_autoptr(GError) error = NULL; g_autoptr(GError) error = NULL;
fp_device_close_finish (dev, res, &error); fp_device_close_finish (dev, res, &error);
@ -61,39 +65,45 @@ on_device_closed (FpDevice *dev, GAsyncResult *res, void *user_data) {
g_main_loop_quit (verify_data->loop); 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 static void
on_verify_completed (FpDevice *dev, GAsyncResult *res, void *user_data) on_verify_completed (FpDevice *dev, GAsyncResult *res, void *user_data)
{ {
VerifyData *verify_data = user_data; VerifyData *verify_data = user_data;
g_autoptr(FpPrint) print = NULL; g_autoptr(FpPrint) print = NULL;
g_autoptr(GError) error = NULL; g_autoptr(GError) error = NULL;
char buffer[20]; char buffer[20];
gboolean match; gboolean match;
if (!fp_device_verify_finish (dev, res, &match, &print, &error)) { if (!fp_device_verify_finish (dev, res, &match, &print, &error))
{
g_warning ("Failed to verify print: %s", error->message); g_warning ("Failed to verify print: %s", error->message);
g_main_loop_quit (verify_data->loop); g_main_loop_quit (verify_data->loop);
return; return;
} }
if (match) { if (match)
{
g_print ("MATCH!\n"); g_print ("MATCH!\n");
if (fp_device_supports_capture (dev) && if (fp_device_supports_capture (dev) &&
print_image_save (print, "verify.pgm")) { print_image_save (print, "verify.pgm"))
g_print("Print image saved as verify.pgm"); g_print ("Print image saved as verify.pgm");
}
verify_data->ret_value = EXIT_SUCCESS; verify_data->ret_value = EXIT_SUCCESS;
} else { }
else
{
g_print ("NO MATCH!\n"); g_print ("NO MATCH!\n");
verify_data->ret_value = EXIT_FAILURE; verify_data->ret_value = EXIT_FAILURE;
} }
g_print ("Verify again? [Y/n]? "); g_print ("Verify again? [Y/n]? ");
if (fgets (buffer, sizeof (buffer), stdin) && if (fgets (buffer, sizeof (buffer), stdin) &&
(buffer[0] == 'Y' || buffer[0] == 'y')) { (buffer[0] == 'Y' || buffer[0] == 'y'))
{
start_verification (dev, verify_data); start_verification (dev, verify_data);
return; return;
} }
@ -106,23 +116,27 @@ static void
on_list_completed (FpDevice *dev, GAsyncResult *res, gpointer user_data) on_list_completed (FpDevice *dev, GAsyncResult *res, gpointer user_data)
{ {
VerifyData *verify_data = user_data; VerifyData *verify_data = user_data;
g_autoptr(GPtrArray) prints = NULL; g_autoptr(GPtrArray) prints = NULL;
g_autoptr(GError) error = NULL; g_autoptr(GError) error = NULL;
prints = fp_device_list_prints_finish (dev, res, &error); prints = fp_device_list_prints_finish (dev, res, &error);
if (!error) { if (!error)
{
FpPrint *verify_print = NULL; FpPrint *verify_print = NULL;
guint i; guint i;
if (!prints->len) if (!prints->len)
g_warning ("No prints saved on device"); g_warning ("No prints saved on device");
for (i = 0; i < prints->len; ++i) { for (i = 0; i < prints->len; ++i)
{
FpPrint *print = prints->pdata[i]; FpPrint *print = prints->pdata[i];
if (fp_print_get_finger (print) == FP_FINGER_RIGHT_INDEX && if (fp_print_get_finger (print) == FP_FINGER_RIGHT_INDEX &&
g_strcmp0 (fp_print_get_username (print), g_get_user_name ()) == 0) { g_strcmp0 (fp_print_get_username (print), g_get_user_name ()) == 0)
{
if (!verify_print || if (!verify_print ||
(g_date_compare (fp_print_get_enroll_date (print), (g_date_compare (fp_print_get_enroll_date (print),
fp_print_get_enroll_date (verify_print)) >= 0)) fp_print_get_enroll_date (verify_print)) >= 0))
@ -130,7 +144,8 @@ on_list_completed (FpDevice *dev, GAsyncResult *res, gpointer user_data)
} }
} }
if (!verify_print) { if (!verify_print)
{
g_warning ("Did you remember to enroll your right index " g_warning ("Did you remember to enroll your right index "
"finger first?"); "finger first?");
g_main_loop_quit (verify_data->loop); g_main_loop_quit (verify_data->loop);
@ -144,7 +159,9 @@ on_list_completed (FpDevice *dev, GAsyncResult *res, gpointer user_data)
fp_device_verify (dev, verify_print, NULL, fp_device_verify (dev, verify_print, NULL,
(GAsyncReadyCallback) on_verify_completed, (GAsyncReadyCallback) on_verify_completed,
verify_data); verify_data);
} else { }
else
{
g_warning ("Loading prints failed with error %s", error->message); g_warning ("Loading prints failed with error %s", error->message);
g_main_loop_quit (verify_data->loop); g_main_loop_quit (verify_data->loop);
} }
@ -153,18 +170,22 @@ on_list_completed (FpDevice *dev, GAsyncResult *res, gpointer user_data)
static void static void
start_verification (FpDevice *dev, VerifyData *verify_data) start_verification (FpDevice *dev, VerifyData *verify_data)
{ {
if (fp_device_has_storage (dev)) { if (fp_device_has_storage (dev))
{
g_print ("Creating finger template, using device storage...\n"); g_print ("Creating finger template, using device storage...\n");
fp_device_list_prints (dev, NULL, fp_device_list_prints (dev, NULL,
(GAsyncReadyCallback) on_list_completed, (GAsyncReadyCallback) on_list_completed,
verify_data); verify_data);
} else { }
else
{
g_print ("Loading previously enrolled right index finger data...\n"); g_print ("Loading previously enrolled right index finger data...\n");
g_autoptr(FpPrint) verify_print; 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) { if (!verify_print)
{
g_warning ("Failed to load fingerprint data"); g_warning ("Failed to load fingerprint data");
g_warning ("Did you remember to enroll your right index " g_warning ("Did you remember to enroll your right index "
"finger first?"); "finger first?");
@ -183,9 +204,11 @@ static void
on_device_opened (FpDevice *dev, GAsyncResult *res, void *user_data) on_device_opened (FpDevice *dev, GAsyncResult *res, void *user_data)
{ {
VerifyData *verify_data = user_data; VerifyData *verify_data = user_data;
g_autoptr(GError) error = NULL; g_autoptr(GError) error = NULL;
if (!fp_device_open_finish (dev, res, &error)) { if (!fp_device_open_finish (dev, res, &error))
{
g_warning ("Failed to open device: %s", error->message); g_warning ("Failed to open device: %s", error->message);
g_main_loop_quit (verify_data->loop); g_main_loop_quit (verify_data->loop);
return; return;
@ -196,10 +219,11 @@ on_device_opened (FpDevice *dev, GAsyncResult *res, void *user_data)
start_verification (dev, verify_data); start_verification (dev, verify_data);
} }
int main(void) int
main (void)
{ {
g_autoptr (FpContext) ctx = NULL; g_autoptr(FpContext) ctx = NULL;
g_autoptr (VerifyData) verify_data = NULL; g_autoptr(VerifyData) verify_data = NULL;
GPtrArray *devices; GPtrArray *devices;
FpDevice *dev; FpDevice *dev;
@ -209,14 +233,16 @@ int main(void)
ctx = fp_context_new (); ctx = fp_context_new ();
devices = fp_context_get_devices (ctx); devices = fp_context_get_devices (ctx);
if (!devices) { if (!devices)
g_warning("Impossible to get devices"); {
g_warning ("Impossible to get devices");
return EXIT_FAILURE; return EXIT_FAILURE;
} }
dev = discover_device (devices); dev = discover_device (devices);
if (!dev) { if (!dev)
g_warning("No devices detected."); {
g_warning ("No devices detected.");
return EXIT_FAILURE; return EXIT_FAILURE;
} }
@ -231,5 +257,3 @@ int main(void)
return verify_data->ret_value; return verify_data->ret_value;
} }

View file

@ -28,9 +28,10 @@
#include "drivers_api.h" #include "drivers_api.h"
#include "aeslib.h" #include "aeslib.h"
static void start_capture(FpImageDevice *dev); static void start_capture (FpImageDevice *dev);
static void complete_deactivation(FpImageDevice *dev); static void complete_deactivation (FpImageDevice *dev);
static int adjust_gain(unsigned char *buffer, int status); static int adjust_gain (unsigned char *buffer,
int status);
#define FIRST_AES1610_REG 0x1B #define FIRST_AES1610_REG 0x1B
#define LAST_AES1610_REG 0xFF #define LAST_AES1610_REG 0xFF
@ -69,7 +70,8 @@ static int adjust_gain(unsigned char *buffer, int status);
/****** GENERAL FUNCTIONS ******/ /****** GENERAL FUNCTIONS ******/
struct _FpiDeviceAes1610 { struct _FpiDeviceAes1610
{
FpImageDevice parent; FpImageDevice parent;
guint8 read_regs_retry_count; guint8 read_regs_retry_count;
@ -78,9 +80,9 @@ struct _FpiDeviceAes1610 {
gboolean deactivating; gboolean deactivating;
guint8 blanks_count; guint8 blanks_count;
}; };
G_DECLARE_FINAL_TYPE(FpiDeviceAes1610, fpi_device_aes1610, FPI, DEVICE_AES1610, G_DECLARE_FINAL_TYPE (FpiDeviceAes1610, fpi_device_aes1610, FPI, DEVICE_AES1610,
FpImageDevice); FpImageDevice);
G_DEFINE_TYPE(FpiDeviceAes1610, fpi_device_aes1610, FP_TYPE_IMAGE_DEVICE); G_DEFINE_TYPE (FpiDeviceAes1610, fpi_device_aes1610, FP_TYPE_IMAGE_DEVICE);
static struct fpi_frame_asmbl_ctx assembling_ctx = { static struct fpi_frame_asmbl_ctx assembling_ctx = {
.frame_width = FRAME_WIDTH, .frame_width = FRAME_WIDTH,
@ -89,10 +91,13 @@ static struct fpi_frame_asmbl_ctx assembling_ctx = {
.get_pixel = aes_get_pixel, .get_pixel = aes_get_pixel,
}; };
typedef void (*aes1610_read_regs_cb)(FpImageDevice *dev, int status, typedef void (*aes1610_read_regs_cb)(FpImageDevice *dev,
unsigned char *regs, void *user_data); int status,
unsigned char *regs,
void *user_data);
struct aes1610_read_regs { struct aes1610_read_regs
{
FpImageDevice *dev; FpImageDevice *dev;
aes1610_read_regs_cb callback; aes1610_read_regs_cb callback;
struct aes_regwrite *regwrite; struct aes_regwrite *regwrite;
@ -100,10 +105,12 @@ struct aes1610_read_regs {
}; };
/* FIXME: what to do here? */ /* FIXME: what to do here? */
static void stub_capture_stop_cb(FpImageDevice *dev, GError *error, static void
stub_capture_stop_cb (FpImageDevice *dev, GError *error,
void *user_data) void *user_data)
{ {
if (error) { if (error)
{
fp_warn ("Error stopping capture: %s", error->message); fp_warn ("Error stopping capture: %s", error->message);
g_error_free (error); g_error_free (error);
} }
@ -111,40 +118,44 @@ static void stub_capture_stop_cb(FpImageDevice *dev, GError *error,
/* check that read succeeded but ignore all data */ /* check that read succeeded but ignore all data */
static void generic_ignore_data_cb(FpiUsbTransfer *transfer, FpDevice *device, static void
generic_ignore_data_cb (FpiUsbTransfer *transfer, FpDevice *device,
gpointer user_data, GError *error) gpointer user_data, GError *error)
{ {
if (error) if (error)
fpi_ssm_mark_failed(transfer->ssm, error); fpi_ssm_mark_failed (transfer->ssm, error);
else else
fpi_ssm_next_state(transfer->ssm); fpi_ssm_next_state (transfer->ssm);
} }
static void generic_write_regv_cb(FpImageDevice *dev, GError *error, static void
generic_write_regv_cb (FpImageDevice *dev, GError *error,
void *user_data) void *user_data)
{ {
FpiSsm *ssm = user_data; FpiSsm *ssm = user_data;
if (!error) if (!error)
fpi_ssm_next_state(ssm); fpi_ssm_next_state (ssm);
else else
fpi_ssm_mark_failed(ssm, error); fpi_ssm_mark_failed (ssm, error);
} }
/* read the specified number of bytes from the IN endpoint but throw them /* read the specified number of bytes from the IN endpoint but throw them
* away, then increment the SSM */ * away, then increment the SSM */
static void generic_read_ignore_data(FpiSsm *ssm, FpDevice *dev, static void
generic_read_ignore_data (FpiSsm *ssm, FpDevice *dev,
size_t bytes) size_t bytes)
{ {
FpiUsbTransfer *transfer = fpi_usb_transfer_new(dev); FpiUsbTransfer *transfer = fpi_usb_transfer_new (dev);
unsigned char *data; unsigned char *data;
data = g_malloc(bytes); data = g_malloc (bytes);
fpi_usb_transfer_fill_bulk_full(transfer, EP_IN, data, bytes, NULL); fpi_usb_transfer_fill_bulk_full (transfer, EP_IN, data, bytes, NULL);
transfer->ssm = ssm; transfer->ssm = ssm;
transfer->short_is_error = TRUE; transfer->short_is_error = TRUE;
fpi_usb_transfer_submit(transfer, BULK_TIMEOUT, NULL, fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
generic_ignore_data_cb, NULL); generic_ignore_data_cb, NULL);
fpi_usb_transfer_unref(transfer); fpi_usb_transfer_unref (transfer);
} }
/****** FINGER PRESENCE DETECTION ******/ /****** FINGER PRESENCE DETECTION ******/
@ -175,17 +186,19 @@ static const struct aes_regwrite finger_det_reqs[] = {
{ 0x81, 0x04 } { 0x81, 0x04 }
}; };
static void start_finger_detection(FpImageDevice *dev); static void start_finger_detection (FpImageDevice *dev);
static void finger_det_data_cb(FpiUsbTransfer *transfer, FpDevice *device, static void
finger_det_data_cb (FpiUsbTransfer *transfer, FpDevice *device,
gpointer user_data, GError *error) gpointer user_data, GError *error)
{ {
FpImageDevice *dev = FP_IMAGE_DEVICE(device); FpImageDevice *dev = FP_IMAGE_DEVICE (device);
unsigned char *data = transfer->buffer; unsigned char *data = transfer->buffer;
int i; int i;
int sum = 0; int sum = 0;
if (error) { if (error)
{
fpi_image_device_session_error (dev, error); fpi_image_device_session_error (dev, error);
return; return;
} }
@ -193,46 +206,53 @@ static void finger_det_data_cb(FpiUsbTransfer *transfer, FpDevice *device,
/* examine histogram to determine finger presence */ /* examine histogram to determine finger presence */
for (i = 3; i < 17; i++) for (i = 3; i < 17; i++)
sum += (data[i] & 0xf) + (data[i] >> 4); sum += (data[i] & 0xf) + (data[i] >> 4);
if (sum > 20) { if (sum > 20)
{
/* reset default gain */ /* reset default gain */
adjust_gain(data,GAIN_STATUS_FIRST); adjust_gain (data, GAIN_STATUS_FIRST);
/* finger present, start capturing */ /* finger present, start capturing */
fpi_image_device_report_finger_status(dev, TRUE); fpi_image_device_report_finger_status (dev, TRUE);
start_capture(dev); start_capture (dev);
} else { }
else
{
/* no finger, poll for a new histogram */ /* no finger, poll for a new histogram */
start_finger_detection(dev); start_finger_detection (dev);
} }
} }
static void finger_det_reqs_cb(FpImageDevice *dev, GError *error, static void
finger_det_reqs_cb (FpImageDevice *dev, GError *error,
void *user_data) void *user_data)
{ {
FpiUsbTransfer *transfer; FpiUsbTransfer *transfer;
if (error) { if (error)
fpi_image_device_session_error(dev, error); {
fpi_image_device_session_error (dev, error);
return; return;
} }
transfer = fpi_usb_transfer_new(FP_DEVICE(dev)); transfer = fpi_usb_transfer_new (FP_DEVICE (dev));
fpi_usb_transfer_fill_bulk (transfer, EP_IN, FINGER_DETECTION_LEN); fpi_usb_transfer_fill_bulk (transfer, EP_IN, FINGER_DETECTION_LEN);
transfer->short_is_error = TRUE; transfer->short_is_error = TRUE;
fpi_usb_transfer_submit(transfer, BULK_TIMEOUT, NULL, fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
finger_det_data_cb, NULL); finger_det_data_cb, NULL);
fpi_usb_transfer_unref(transfer); fpi_usb_transfer_unref (transfer);
} }
static void start_finger_detection(FpImageDevice *dev) static void
start_finger_detection (FpImageDevice *dev)
{ {
FpiDeviceAes1610 *self = FPI_DEVICE_AES1610(dev); FpiDeviceAes1610 *self = FPI_DEVICE_AES1610 (dev);
if (self->deactivating) { if (self->deactivating)
complete_deactivation(dev); {
complete_deactivation (dev);
return; return;
} }
aes_write_regv(dev, finger_det_reqs, G_N_ELEMENTS(finger_det_reqs), finger_det_reqs_cb, NULL); aes_write_regv (dev, finger_det_reqs, G_N_ELEMENTS (finger_det_reqs), finger_det_reqs_cb, NULL);
} }
@ -373,7 +393,7 @@ static struct aes_regwrite strip_scan_reqs[] = {
}; };
static const struct aes_regwrite capture_stop[] = { static const struct aes_regwrite capture_stop[] = {
{ 0x81,0x00 } { 0x81, 0x00 }
}; };
/* /*
@ -393,7 +413,8 @@ static unsigned char list_BD_values[10] = {
* 0xbd, 0xbe, 0x29 and 0x2A registers are affected * 0xbd, 0xbe, 0x29 and 0x2A registers are affected
* Returns 0 if no problem occurred * Returns 0 if no problem occurred
* TODO: This is a basic support for gain. It needs testing/tweaking. */ * TODO: This is a basic support for gain. It needs testing/tweaking. */
static int adjust_gain(unsigned char *buffer, int status) static int
adjust_gain (unsigned char *buffer, int status)
{ {
// The position in the array of possible values for 0xBE and 0xBD registers // The position in the array of possible values for 0xBE and 0xBD registers
static int pos_list_BE = 0; static int pos_list_BE = 0;
@ -401,26 +422,31 @@ static int adjust_gain(unsigned char *buffer, int status)
// This is the first adjustment (we begin acquisition) // This is the first adjustment (we begin acquisition)
// We adjust strip_scan_reqs for future strips and capture_reqs that is sent just after this step // We adjust strip_scan_reqs for future strips and capture_reqs that is sent just after this step
if (status == GAIN_STATUS_FIRST) { if (status == GAIN_STATUS_FIRST)
if (buffer[1] > 0x78) { // maximum gain needed {
if (buffer[1] > 0x78) // maximum gain needed
{
strip_scan_reqs[0].value = 0x6B; strip_scan_reqs[0].value = 0x6B;
strip_scan_reqs[1].value = 0x06; strip_scan_reqs[1].value = 0x06;
strip_scan_reqs[2].value = 0x35; strip_scan_reqs[2].value = 0x35;
strip_scan_reqs[3].value = 0x4B; strip_scan_reqs[3].value = 0x4B;
} }
else if (buffer[1] > 0x55) { else if (buffer[1] > 0x55)
{
strip_scan_reqs[0].value = 0x63; strip_scan_reqs[0].value = 0x63;
strip_scan_reqs[1].value = 0x15; strip_scan_reqs[1].value = 0x15;
strip_scan_reqs[2].value = 0x35; strip_scan_reqs[2].value = 0x35;
strip_scan_reqs[3].value = 0x3b; strip_scan_reqs[3].value = 0x3b;
} }
else if (buffer[1] > 0x40 || buffer[16] > 0x19) { else if (buffer[1] > 0x40 || buffer[16] > 0x19)
{
strip_scan_reqs[0].value = 0x43; strip_scan_reqs[0].value = 0x43;
strip_scan_reqs[1].value = 0x13; strip_scan_reqs[1].value = 0x13;
strip_scan_reqs[2].value = 0x35; strip_scan_reqs[2].value = 0x35;
strip_scan_reqs[3].value = 0x30; strip_scan_reqs[3].value = 0x30;
} }
else { // minimum gain needed else // minimum gain needed
{
strip_scan_reqs[0].value = 0x23; strip_scan_reqs[0].value = 0x23;
strip_scan_reqs[1].value = 0x07; strip_scan_reqs[1].value = 0x07;
strip_scan_reqs[2].value = 0x35; strip_scan_reqs[2].value = 0x35;
@ -433,14 +459,15 @@ static int adjust_gain(unsigned char *buffer, int status)
capture_reqs[10].value = strip_scan_reqs[2].value; capture_reqs[10].value = strip_scan_reqs[2].value;
capture_reqs[21].value = strip_scan_reqs[3].value; capture_reqs[21].value = strip_scan_reqs[3].value;
fp_dbg("first gain: %x %x %x %x %x %x %x %x", strip_scan_reqs[0].reg, strip_scan_reqs[0].value, strip_scan_reqs[1].reg, strip_scan_reqs[1].value, strip_scan_reqs[2].reg, strip_scan_reqs[2].value, strip_scan_reqs[3].reg, strip_scan_reqs[3].value); fp_dbg ("first gain: %x %x %x %x %x %x %x %x", strip_scan_reqs[0].reg, strip_scan_reqs[0].value, strip_scan_reqs[1].reg, strip_scan_reqs[1].value, strip_scan_reqs[2].reg, strip_scan_reqs[2].value, strip_scan_reqs[3].reg, strip_scan_reqs[3].value);
} }
// Every 2/3 strips // Every 2/3 strips
// We try to soften big changes of the gain (at least for 0xBE and 0xBD // We try to soften big changes of the gain (at least for 0xBE and 0xBD
// FIXME: This softenning will need testing and tweaking too // FIXME: This softenning will need testing and tweaking too
else if (status == GAIN_STATUS_NORMAL) { else if (status == GAIN_STATUS_NORMAL)
if (buffer[514] > 0x78) { // maximum gain needed {
if (buffer[514] > 0x78) // maximum gain needed
{
if (pos_list_BE < 7) if (pos_list_BE < 7)
pos_list_BE++; pos_list_BE++;
@ -450,7 +477,8 @@ static int adjust_gain(unsigned char *buffer, int status)
strip_scan_reqs[1].value = 0x04; strip_scan_reqs[1].value = 0x04;
strip_scan_reqs[2].value = 0x35; strip_scan_reqs[2].value = 0x35;
} }
else if (buffer[514] > 0x55) { else if (buffer[514] > 0x55)
{
if (pos_list_BE < 2) if (pos_list_BE < 2)
pos_list_BE++; pos_list_BE++;
else if (pos_list_BE > 2) else if (pos_list_BE > 2)
@ -464,7 +492,8 @@ static int adjust_gain(unsigned char *buffer, int status)
strip_scan_reqs[1].value = 0x15; strip_scan_reqs[1].value = 0x15;
strip_scan_reqs[2].value = 0x35; strip_scan_reqs[2].value = 0x35;
} }
else if (buffer[514] > 0x40 || buffer[529] > 0x19) { else if (buffer[514] > 0x40 || buffer[529] > 0x19)
{
if (pos_list_BE < 1) if (pos_list_BE < 1)
pos_list_BE++; pos_list_BE++;
else if (pos_list_BE > 1) else if (pos_list_BE > 1)
@ -478,7 +507,8 @@ static int adjust_gain(unsigned char *buffer, int status)
strip_scan_reqs[1].value = 0x13; strip_scan_reqs[1].value = 0x13;
strip_scan_reqs[2].value = 0x35; strip_scan_reqs[2].value = 0x35;
} }
else { // minimum gain needed else // minimum gain needed
{
if (pos_list_BE > 0) if (pos_list_BE > 0)
pos_list_BE--; pos_list_BE--;
@ -492,11 +522,12 @@ static int adjust_gain(unsigned char *buffer, int status)
strip_scan_reqs[0].value = list_BE_values[pos_list_BE]; strip_scan_reqs[0].value = list_BE_values[pos_list_BE];
strip_scan_reqs[3].value = list_BD_values[pos_list_BD]; strip_scan_reqs[3].value = list_BD_values[pos_list_BD];
fp_dbg("gain: %x %x %x %x %x %x %x %x", strip_scan_reqs[0].reg, strip_scan_reqs[0].value, strip_scan_reqs[1].reg, strip_scan_reqs[1].value, strip_scan_reqs[2].reg, strip_scan_reqs[2].value, strip_scan_reqs[3].reg, strip_scan_reqs[3].value); fp_dbg ("gain: %x %x %x %x %x %x %x %x", strip_scan_reqs[0].reg, strip_scan_reqs[0].value, strip_scan_reqs[1].reg, strip_scan_reqs[1].value, strip_scan_reqs[2].reg, strip_scan_reqs[2].value, strip_scan_reqs[3].reg, strip_scan_reqs[3].value);
} }
// Unknown status // Unknown status
else { else
fp_err("Unexpected gain status."); {
fp_err ("Unexpected gain status.");
return 1; return 1;
} }
@ -505,7 +536,8 @@ static int adjust_gain(unsigned char *buffer, int status)
/* /*
* Restore the default gain values */ * Restore the default gain values */
static void restore_gain(void) static void
restore_gain (void)
{ {
strip_scan_reqs[0].value = list_BE_values[0]; strip_scan_reqs[0].value = list_BE_values[0];
strip_scan_reqs[1].value = 0x04; strip_scan_reqs[1].value = 0x04;
@ -532,16 +564,18 @@ enum capture_states {
CAPTURE_NUM_STATES, CAPTURE_NUM_STATES,
}; };
static void capture_read_strip_cb(FpiUsbTransfer *transfer, FpDevice *device, static void
capture_read_strip_cb (FpiUsbTransfer *transfer, FpDevice *device,
gpointer user_data, GError *error) gpointer user_data, GError *error)
{ {
unsigned char *stripdata; unsigned char *stripdata;
FpImageDevice *dev = FP_IMAGE_DEVICE (device); FpImageDevice *dev = FP_IMAGE_DEVICE (device);
FpiDeviceAes1610 *self = FPI_DEVICE_AES1610(dev); FpiDeviceAes1610 *self = FPI_DEVICE_AES1610 (dev);
unsigned char *data = transfer->buffer; unsigned char *data = transfer->buffer;
gint sum, i; gint sum, i;
if (error) { if (error)
{
fpi_ssm_mark_failed (transfer->ssm, error); fpi_ssm_mark_failed (transfer->ssm, error);
return; return;
} }
@ -550,134 +584,152 @@ static void capture_read_strip_cb(FpiUsbTransfer *transfer, FpDevice *device,
sum = 0; sum = 0;
for (i = 516; i < 530; i++) for (i = 516; i < 530; i++)
{
/* histogram[i] = number of pixels of value i /* histogram[i] = number of pixels of value i
Only the pixel values from 10 to 15 are used to detect finger. */ Only the pixel values from 10 to 15 are used to detect finger. */
sum += data[i]; sum += data[i];
}
fp_dbg("sum=%d", sum); fp_dbg ("sum=%d", sum);
if (sum > 0) { if (sum > 0)
{
/* FIXME: would preallocating strip buffers be a decent optimization? */ /* FIXME: would preallocating strip buffers be a decent optimization? */
struct fpi_frame *stripe = g_malloc(FRAME_WIDTH * (FRAME_HEIGHT / 2) + sizeof(struct fpi_frame)); struct fpi_frame *stripe = g_malloc (FRAME_WIDTH * (FRAME_HEIGHT / 2) + sizeof (struct fpi_frame));
stripe->delta_x = 0; stripe->delta_x = 0;
stripe->delta_y = 0; stripe->delta_y = 0;
stripdata = stripe->data; stripdata = stripe->data;
memcpy(stripdata, data + 1, FRAME_WIDTH * (FRAME_HEIGHT / 2)); memcpy (stripdata, data + 1, FRAME_WIDTH * (FRAME_HEIGHT / 2));
self->strips = g_slist_prepend(self->strips, stripe); self->strips = g_slist_prepend (self->strips, stripe);
self->strips_len++; self->strips_len++;
self->blanks_count = 0; self->blanks_count = 0;
} else { }
else
{
/* FIXME: 0 might be too low as a threshold */ /* FIXME: 0 might be too low as a threshold */
/* FIXME: sometimes we get 0 in the middle of a scan, should we wait for /* FIXME: sometimes we get 0 in the middle of a scan, should we wait for
* a few consecutive zeroes? */ * a few consecutive zeroes? */
/* sum cannot be negative, so is 0 */ /* sum cannot be negative, so is 0 */
self->blanks_count++; self->blanks_count++;
fp_dbg("got blank frame"); fp_dbg ("got blank frame");
} }
/* use histogram data above for gain calibration (0xbd, 0xbe, 0x29 and 0x2A ) */ /* use histogram data above for gain calibration (0xbd, 0xbe, 0x29 and 0x2A ) */
adjust_gain(data, GAIN_STATUS_NORMAL); adjust_gain (data, GAIN_STATUS_NORMAL);
/* stop capturing if MAX_FRAMES is reached */ /* stop capturing if MAX_FRAMES is reached */
if (self->blanks_count > 10 || g_slist_length(self->strips) >= MAX_FRAMES) { if (self->blanks_count > 10 || g_slist_length (self->strips) >= MAX_FRAMES)
{
FpImage *img; FpImage *img;
fp_dbg("sending stop capture.... blanks=%d frames=%d", fp_dbg ("sending stop capture.... blanks=%d frames=%d",
self->blanks_count, g_slist_length(self->strips)); self->blanks_count, g_slist_length (self->strips));
/* send stop capture bits */ /* send stop capture bits */
aes_write_regv(dev, capture_stop, G_N_ELEMENTS(capture_stop), stub_capture_stop_cb, NULL); aes_write_regv (dev, capture_stop, G_N_ELEMENTS (capture_stop), stub_capture_stop_cb, NULL);
self->strips = g_slist_reverse(self->strips); self->strips = g_slist_reverse (self->strips);
fpi_do_movement_estimation(&assembling_ctx, self->strips); fpi_do_movement_estimation (&assembling_ctx, self->strips);
img = fpi_assemble_frames(&assembling_ctx, self->strips); img = fpi_assemble_frames (&assembling_ctx, self->strips);
g_slist_free_full(self->strips, g_free); g_slist_free_full (self->strips, g_free);
self->strips = NULL; self->strips = NULL;
self->strips_len = 0; self->strips_len = 0;
self->blanks_count = 0; self->blanks_count = 0;
fpi_image_device_image_captured(dev, img); fpi_image_device_image_captured (dev, img);
fpi_image_device_report_finger_status(dev, FALSE); fpi_image_device_report_finger_status (dev, FALSE);
/* marking machine complete will re-trigger finger detection loop */ /* marking machine complete will re-trigger finger detection loop */
fpi_ssm_mark_completed(transfer->ssm); fpi_ssm_mark_completed (transfer->ssm);
/* Acquisition finished: restore default gain values */ /* Acquisition finished: restore default gain values */
restore_gain(); restore_gain ();
} else { }
else
{
/* obtain next strip */ /* obtain next strip */
fpi_ssm_jump_to_state(transfer->ssm, CAPTURE_REQUEST_STRIP); fpi_ssm_jump_to_state (transfer->ssm, CAPTURE_REQUEST_STRIP);
} }
} }
static void capture_run_state(FpiSsm *ssm, FpDevice *_dev, void *user_data) static void
capture_run_state (FpiSsm *ssm, FpDevice *_dev, void *user_data)
{ {
FpImageDevice *dev = user_data; FpImageDevice *dev = user_data;
FpiDeviceAes1610 *self = FPI_DEVICE_AES1610(_dev); FpiDeviceAes1610 *self = FPI_DEVICE_AES1610 (_dev);
switch (fpi_ssm_get_cur_state(ssm)) { switch (fpi_ssm_get_cur_state (ssm))
{
case CAPTURE_WRITE_REQS: case CAPTURE_WRITE_REQS:
fp_dbg("write reqs"); fp_dbg ("write reqs");
aes_write_regv(dev, capture_reqs, G_N_ELEMENTS(capture_reqs), aes_write_regv (dev, capture_reqs, G_N_ELEMENTS (capture_reqs),
generic_write_regv_cb, ssm); generic_write_regv_cb, ssm);
break; break;
case CAPTURE_READ_DATA: case CAPTURE_READ_DATA:
fp_dbg("read data"); fp_dbg ("read data");
generic_read_ignore_data(ssm, _dev, STRIP_CAPTURE_LEN); generic_read_ignore_data (ssm, _dev, STRIP_CAPTURE_LEN);
break; break;
case CAPTURE_REQUEST_STRIP: case CAPTURE_REQUEST_STRIP:
fp_dbg("request strip"); fp_dbg ("request strip");
if (self->deactivating) if (self->deactivating)
fpi_ssm_mark_completed(ssm); fpi_ssm_mark_completed (ssm);
else else
aes_write_regv(dev, strip_scan_reqs, G_N_ELEMENTS(strip_scan_reqs), aes_write_regv (dev, strip_scan_reqs, G_N_ELEMENTS (strip_scan_reqs),
generic_write_regv_cb, ssm); generic_write_regv_cb, ssm);
break; break;
case CAPTURE_READ_STRIP: ;
FpiUsbTransfer *transfer = fpi_usb_transfer_new(_dev); case CAPTURE_READ_STRIP:;
FpiUsbTransfer *transfer = fpi_usb_transfer_new (_dev);
fpi_usb_transfer_fill_bulk (transfer, EP_IN, STRIP_CAPTURE_LEN); fpi_usb_transfer_fill_bulk (transfer, EP_IN, STRIP_CAPTURE_LEN);
transfer->ssm = ssm; transfer->ssm = ssm;
transfer->short_is_error = TRUE; transfer->short_is_error = TRUE;
fpi_usb_transfer_submit(transfer, BULK_TIMEOUT, NULL, fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
capture_read_strip_cb, NULL); capture_read_strip_cb, NULL);
fpi_usb_transfer_unref(transfer); fpi_usb_transfer_unref (transfer);
break; break;
}; }
;
} }
static void capture_sm_complete(FpiSsm *ssm, FpDevice *_dev, void *user_data, static void
capture_sm_complete (FpiSsm *ssm, FpDevice *_dev, void *user_data,
GError *error) GError *error)
{ {
FpImageDevice *dev = user_data; FpImageDevice *dev = user_data;
FpiDeviceAes1610 *self = FPI_DEVICE_AES1610(_dev); FpiDeviceAes1610 *self = FPI_DEVICE_AES1610 (_dev);
G_DEBUG_HERE(); G_DEBUG_HERE ();
if (self->deactivating) { if (self->deactivating)
complete_deactivation(dev); {
complete_deactivation (dev);
if (error) if (error)
g_error_free (error); g_error_free (error);
} else if (error) {
fpi_image_device_session_error(dev, error);
} else {
start_finger_detection(dev);
} }
fpi_ssm_free(ssm); 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)
{ {
FpiDeviceAes1610 *self = FPI_DEVICE_AES1610(dev); FpiDeviceAes1610 *self = FPI_DEVICE_AES1610 (dev);
FpiSsm *ssm; FpiSsm *ssm;
if (self->deactivating) { if (self->deactivating)
complete_deactivation(dev); {
complete_deactivation (dev);
return; return;
} }
ssm = fpi_ssm_new(FP_DEVICE(dev), capture_run_state, ssm = fpi_ssm_new (FP_DEVICE (dev), capture_run_state,
CAPTURE_NUM_STATES, dev); CAPTURE_NUM_STATES, dev);
G_DEBUG_HERE(); G_DEBUG_HERE ();
fpi_ssm_start(ssm, capture_sm_complete); fpi_ssm_start (ssm, capture_sm_complete);
} }
/****** INITIALIZATION/DEINITIALIZATION ******/ /****** INITIALIZATION/DEINITIALIZATION ******/
@ -687,108 +739,125 @@ static const struct aes_regwrite init[] = {
}; };
/* /*
static const struct aes_regwrite stop_reader[] = { static const struct aes_regwrite stop_reader[] = {
{ 0xFF, 0x00 } { 0xFF, 0x00 }
}; };
*/ */
enum activate_states { enum activate_states {
WRITE_INIT, WRITE_INIT,
ACTIVATE_NUM_STATES, ACTIVATE_NUM_STATES,
}; };
static void activate_run_state(FpiSsm *ssm, FpDevice *_dev, void *user_data) static void
activate_run_state (FpiSsm *ssm, FpDevice *_dev, void *user_data)
{ {
FpImageDevice *dev = user_data; FpImageDevice *dev = user_data;
/* activation on aes1610 seems much more straightforward compared to aes2501 */ /* activation on aes1610 seems much more straightforward compared to aes2501 */
/* verify there's anything missing here */ /* verify there's anything missing here */
switch (fpi_ssm_get_cur_state(ssm)) { switch (fpi_ssm_get_cur_state (ssm))
{
case WRITE_INIT: case WRITE_INIT:
fp_dbg("write init"); fp_dbg ("write init");
aes_write_regv(dev, init, G_N_ELEMENTS(init), generic_write_regv_cb, ssm); aes_write_regv (dev, init, G_N_ELEMENTS (init), generic_write_regv_cb, ssm);
break; break;
} }
} }
/* jump to finger detection */ /* jump to finger detection */
static void activate_sm_complete(FpiSsm *ssm, FpDevice *_dev, static void
activate_sm_complete (FpiSsm *ssm, FpDevice *_dev,
void *user_data, GError *error) 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) if (!error)
start_finger_detection(dev); start_finger_detection (dev);
fpi_ssm_free(ssm); fpi_ssm_free (ssm);
} }
static void dev_activate(FpImageDevice *dev) static void
dev_activate (FpImageDevice *dev)
{ {
FpiDeviceAes1610 *self = FPI_DEVICE_AES1610(dev); FpiDeviceAes1610 *self = FPI_DEVICE_AES1610 (dev);
FpiSsm *ssm = fpi_ssm_new(FP_DEVICE(dev), activate_run_state, FpiSsm *ssm = fpi_ssm_new (FP_DEVICE (dev), activate_run_state,
ACTIVATE_NUM_STATES, dev); ACTIVATE_NUM_STATES, dev);
self->read_regs_retry_count = 0; self->read_regs_retry_count = 0;
fpi_ssm_start(ssm, activate_sm_complete); fpi_ssm_start (ssm, activate_sm_complete);
} }
static void dev_deactivate(FpImageDevice *dev) static void
dev_deactivate (FpImageDevice *dev)
{ {
FpiDeviceAes1610 *self = FPI_DEVICE_AES1610(dev); FpiDeviceAes1610 *self = FPI_DEVICE_AES1610 (dev);
/* FIXME: audit cancellation points, probably need more, specifically /* FIXME: audit cancellation points, probably need more, specifically
* in error handling paths? */ * in error handling paths? */
self->deactivating = TRUE; self->deactivating = TRUE;
} }
static void complete_deactivation(FpImageDevice *dev) static void
complete_deactivation (FpImageDevice *dev)
{ {
FpiDeviceAes1610 *self = FPI_DEVICE_AES1610(dev); FpiDeviceAes1610 *self = FPI_DEVICE_AES1610 (dev);
G_DEBUG_HERE();
G_DEBUG_HERE ();
/* FIXME: if we're in the middle of a scan, we should cancel the scan. /* FIXME: if we're in the middle of a scan, we should cancel the scan.
* maybe we can do this with a master reset, unconditionally? */ * maybe we can do this with a master reset, unconditionally? */
self->deactivating = FALSE; self->deactivating = FALSE;
g_slist_free(self->strips); g_slist_free (self->strips);
self->strips = NULL; self->strips = NULL;
self->strips_len = 0; self->strips_len = 0;
self->blanks_count = 0; self->blanks_count = 0;
fpi_image_device_deactivate_complete(dev, NULL); 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;
/* FIXME check endpoints */ /* FIXME check endpoints */
if (!g_usb_device_claim_interface(fpi_device_get_usb_device(FP_DEVICE(dev)), 0, 0, &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); {
fpi_image_device_open_complete (dev, error);
return; return;
} }
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)
{ {
GError *error = NULL; GError *error = NULL;
g_usb_device_release_interface(fpi_device_get_usb_device(FP_DEVICE(dev)), g_usb_device_release_interface (fpi_device_get_usb_device (FP_DEVICE (dev)),
0, 0, &error); 0, 0, &error);
fpi_image_device_close_complete(dev, error); fpi_image_device_close_complete (dev, error);
} }
static const FpIdEntry id_table [ ] = { static const FpIdEntry id_table[] = {
{ .vid = 0x08ff, .pid = 0x1600, { .vid = 0x08ff, .pid = 0x1600, },/* AES1600 */
}, /* AES1600 */
{ .vid = 0, .pid = 0, .driver_data = 0 }, { .vid = 0, .pid = 0, .driver_data = 0 },
}; };
static void fpi_device_aes1610_init(FpiDeviceAes1610 *self) { static void
fpi_device_aes1610_init (FpiDeviceAes1610 *self)
{
} }
static void fpi_device_aes1610_class_init(FpiDeviceAes1610Class *klass) { static void
FpDeviceClass *dev_class = FP_DEVICE_CLASS(klass); fpi_device_aes1610_class_init (FpiDeviceAes1610Class *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 = "aes1610"; dev_class->id = "aes1610";
dev_class->full_name = "AuthenTec AES1610"; dev_class->full_name = "AuthenTec AES1610";
@ -806,4 +875,3 @@ static void fpi_device_aes1610_class_init(FpiDeviceAes1610Class *klass) {
img_class->img_width = IMAGE_WIDTH; img_class->img_width = IMAGE_WIDTH;
img_class->img_height = -1; img_class->img_height = -1;
} }

View file

@ -27,12 +27,13 @@
#define FRAME_WIDTH 128 #define FRAME_WIDTH 128
#define IMAGE_WIDTH (FRAME_WIDTH + (FRAME_WIDTH / 2)) #define IMAGE_WIDTH (FRAME_WIDTH + (FRAME_WIDTH / 2))
struct _FpiDeviceAes1660 { struct _FpiDeviceAes1660
{
FpiDeviceAesX660 parent; FpiDeviceAesX660 parent;
}; };
G_DECLARE_FINAL_TYPE(FpiDeviceAes1660, fpi_device_aes1660, FPI, G_DECLARE_FINAL_TYPE (FpiDeviceAes1660, fpi_device_aes1660, FPI,
DEVICE_AES1660, FpiDeviceAesX660); DEVICE_AES1660, FpiDeviceAesX660);
G_DEFINE_TYPE(FpiDeviceAes1660, fpi_device_aes1660, FPI_TYPE_DEVICE_AES_X660); G_DEFINE_TYPE (FpiDeviceAes1660, fpi_device_aes1660, FPI_TYPE_DEVICE_AES_X660);
static struct fpi_frame_asmbl_ctx assembling_ctx = { static struct fpi_frame_asmbl_ctx assembling_ctx = {
.frame_width = FRAME_WIDTH, .frame_width = FRAME_WIDTH,
@ -41,7 +42,7 @@ static struct fpi_frame_asmbl_ctx assembling_ctx = {
.get_pixel = aes_get_pixel, .get_pixel = aes_get_pixel,
}; };
static const FpIdEntry id_table [ ] = { static const FpIdEntry id_table[] = {
{ .vid = 0x08ff, .pid = 0x1660, }, { .vid = 0x08ff, .pid = 0x1660, },
{ .vid = 0x08ff, .pid = 0x1680, }, { .vid = 0x08ff, .pid = 0x1680, },
{ .vid = 0x08ff, .pid = 0x1681, }, { .vid = 0x08ff, .pid = 0x1681, },
@ -62,11 +63,15 @@ static const FpIdEntry id_table [ ] = {
{ .vid = 0, .pid = 0, .driver_data = 0 }, { .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) { static void
FpDeviceClass *dev_class = FP_DEVICE_CLASS(klass); fpi_device_aes1660_class_init (FpiDeviceAes1660Class *klass)
FpImageDeviceClass *img_class = FP_IMAGE_DEVICE_CLASS(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); FpiDeviceAesX660Class *aes_class = FPI_DEVICE_AES_X660_CLASS (klass);
dev_class->id = "aes1660"; dev_class->id = "aes1660";
@ -81,10 +86,10 @@ static void fpi_device_aes1660_class_init(FpiDeviceAes1660Class *klass) {
img_class->img_height = -1; img_class->img_height = -1;
aes_class->init_seqs[0] = aes1660_init_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_len[0] = G_N_ELEMENTS (aes1660_init_1);
aes_class->init_seqs[1] = aes1660_init_2; aes_class->init_seqs[1] = aes1660_init_2;
aes_class->init_seqs_len[1] = G_N_ELEMENTS(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 = (unsigned char *) aes1660_start_imaging_cmd;
aes_class->start_imaging_cmd_len = sizeof(aes1660_start_imaging_cmd); aes_class->start_imaging_cmd_len = sizeof (aes1660_start_imaging_cmd);
aes_class->assembling_ctx = &assembling_ctx; aes_class->assembling_ctx = &assembling_ctx;
} }

File diff suppressed because it is too large Load diff

View file

@ -27,8 +27,8 @@
#include "aeslib.h" #include "aeslib.h"
#include "aes2501.h" #include "aes2501.h"
static void start_capture(FpImageDevice *dev); static void start_capture (FpImageDevice *dev);
static void complete_deactivation(FpImageDevice *dev); static void complete_deactivation (FpImageDevice *dev);
/* FIXME these need checking */ /* FIXME these need checking */
#define EP_IN (1 | FPI_USB_ENDPOINT_IN) #define EP_IN (1 | FPI_USB_ENDPOINT_IN)
@ -63,7 +63,8 @@ static void complete_deactivation(FpImageDevice *dev);
/****** GENERAL FUNCTIONS ******/ /****** GENERAL FUNCTIONS ******/
struct _FpiDeviceAes2501 { struct _FpiDeviceAes2501
{
FpImageDevice parent; FpImageDevice parent;
guint8 read_regs_retry_count; guint8 read_regs_retry_count;
@ -72,9 +73,9 @@ struct _FpiDeviceAes2501 {
gboolean deactivating; gboolean deactivating;
int no_finger_cnt; int no_finger_cnt;
}; };
G_DECLARE_FINAL_TYPE(FpiDeviceAes2501, fpi_device_aes2501, FPI, DEVICE_AES2501, G_DECLARE_FINAL_TYPE (FpiDeviceAes2501, fpi_device_aes2501, FPI, DEVICE_AES2501,
FpImageDevice); FpImageDevice);
G_DEFINE_TYPE(FpiDeviceAes2501, fpi_device_aes2501, FP_TYPE_IMAGE_DEVICE); G_DEFINE_TYPE (FpiDeviceAes2501, fpi_device_aes2501, FP_TYPE_IMAGE_DEVICE);
static struct fpi_frame_asmbl_ctx assembling_ctx = { static struct fpi_frame_asmbl_ctx assembling_ctx = {
.frame_width = FRAME_WIDTH, .frame_width = FRAME_WIDTH,
@ -83,54 +84,61 @@ static struct fpi_frame_asmbl_ctx assembling_ctx = {
.get_pixel = aes_get_pixel, .get_pixel = aes_get_pixel,
}; };
typedef void (*aes2501_read_regs_cb)(FpImageDevice *dev, GError *error, typedef void (*aes2501_read_regs_cb)(FpImageDevice *dev,
unsigned char *regs, void *user_data); GError *error,
unsigned char *regs,
void *user_data);
struct aes2501_read_regs { struct aes2501_read_regs
{
FpImageDevice *dev; FpImageDevice *dev;
aes2501_read_regs_cb callback; aes2501_read_regs_cb callback;
struct aes_regwrite *regwrite; struct aes_regwrite *regwrite;
void *user_data; void *user_data;
}; };
static void read_regs_data_cb(FpiUsbTransfer *transfer, FpDevice *dev, static void
read_regs_data_cb (FpiUsbTransfer *transfer, FpDevice *dev,
gpointer user_data, GError *error) gpointer user_data, GError *error)
{ {
struct aes2501_read_regs *rdata = user_data; struct aes2501_read_regs *rdata = user_data;
rdata->callback(rdata->dev, error, transfer->buffer, rdata->user_data); rdata->callback (rdata->dev, error, transfer->buffer, rdata->user_data);
g_free(rdata); g_free (rdata);
} }
static void read_regs_rq_cb(FpImageDevice *dev, GError *error, void *user_data) static void
read_regs_rq_cb (FpImageDevice *dev, GError *error, void *user_data)
{ {
struct aes2501_read_regs *rdata = user_data; struct aes2501_read_regs *rdata = user_data;
FpiUsbTransfer *transfer; FpiUsbTransfer *transfer;
g_free(rdata->regwrite); g_free (rdata->regwrite);
if (error) { if (error)
rdata->callback(dev, error, NULL, rdata->user_data); {
rdata->callback (dev, error, NULL, rdata->user_data);
g_free (rdata); g_free (rdata);
return; return;
} }
transfer = fpi_usb_transfer_new(FP_DEVICE(dev)); transfer = fpi_usb_transfer_new (FP_DEVICE (dev));
transfer->short_is_error = TRUE; transfer->short_is_error = TRUE;
fpi_usb_transfer_fill_bulk(transfer, EP_IN, READ_REGS_LEN); fpi_usb_transfer_fill_bulk (transfer, EP_IN, READ_REGS_LEN);
fpi_usb_transfer_submit(transfer, BULK_TIMEOUT, NULL, fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
read_regs_data_cb, rdata); read_regs_data_cb, rdata);
fpi_usb_transfer_unref(transfer); fpi_usb_transfer_unref (transfer);
} }
static void read_regs(FpImageDevice *dev, aes2501_read_regs_cb callback, static void
read_regs (FpImageDevice *dev, aes2501_read_regs_cb callback,
void *user_data) void *user_data)
{ {
/* FIXME: regwrite is dynamic because of asynchronity. is this really /* FIXME: regwrite is dynamic because of asynchronity. is this really
* required? */ * required? */
struct aes_regwrite *regwrite = g_malloc(sizeof(*regwrite)); struct aes_regwrite *regwrite = g_malloc (sizeof (*regwrite));
struct aes2501_read_regs *rdata = g_malloc(sizeof(*rdata)); struct aes2501_read_regs *rdata = g_malloc (sizeof (*rdata));
G_DEBUG_HERE(); G_DEBUG_HERE ();
regwrite->reg = AES2501_REG_CTRL2; regwrite->reg = AES2501_REG_CTRL2;
regwrite->value = AES2501_CTRL2_READ_REGS; regwrite->value = AES2501_CTRL2_READ_REGS;
rdata->dev = dev; rdata->dev = dev;
@ -138,20 +146,23 @@ static void read_regs(FpImageDevice *dev, aes2501_read_regs_cb callback,
rdata->user_data = user_data; rdata->user_data = user_data;
rdata->regwrite = regwrite; rdata->regwrite = regwrite;
aes_write_regv(dev, (const struct aes_regwrite *) regwrite, 1, aes_write_regv (dev, (const struct aes_regwrite *) regwrite, 1,
read_regs_rq_cb, rdata); read_regs_rq_cb, rdata);
} }
/* Read the value of a specific register from a register dump */ /* Read the value of a specific register from a register dump */
static int regval_from_dump(unsigned char *data, guint8 target) static int
regval_from_dump (unsigned char *data, guint8 target)
{ {
if (*data != FIRST_AES2501_REG) { if (*data != FIRST_AES2501_REG)
fp_err("not a register dump"); {
fp_err ("not a register dump");
return -1; return -1;
} }
if (!(FIRST_AES2501_REG <= target && target <= LAST_AES2501_REG)) { if (!(FIRST_AES2501_REG <= target && target <= LAST_AES2501_REG))
fp_err("out of range"); {
fp_err ("out of range");
return -1; return -1;
} }
@ -160,50 +171,56 @@ static int regval_from_dump(unsigned char *data, guint8 target)
return data[target + 1]; return data[target + 1];
} }
static void generic_write_regv_cb(FpImageDevice *dev, GError *error, static void
generic_write_regv_cb (FpImageDevice *dev, GError *error,
void *user_data) void *user_data)
{ {
FpiSsm *ssm = user_data; FpiSsm *ssm = user_data;
if (!error) if (!error)
fpi_ssm_next_state(ssm); fpi_ssm_next_state (ssm);
else else
fpi_ssm_mark_failed(ssm, error); fpi_ssm_mark_failed (ssm, error);
} }
/* check that read succeeded but ignore all data */ /* check that read succeeded but ignore all data */
static void generic_ignore_data_cb(FpiUsbTransfer *transfer, FpDevice *dev, static void
generic_ignore_data_cb (FpiUsbTransfer *transfer, FpDevice *dev,
gpointer user_data, GError *error) gpointer user_data, GError *error)
{ {
FpiSsm *ssm = transfer->ssm; FpiSsm *ssm = transfer->ssm;
if (error) if (error)
fpi_ssm_mark_failed(ssm, error); fpi_ssm_mark_failed (ssm, error);
else else
fpi_ssm_next_state(ssm); fpi_ssm_next_state (ssm);
} }
/* read the specified number of bytes from the IN endpoint but throw them /* read the specified number of bytes from the IN endpoint but throw them
* away, then increment the SSM */ * away, then increment the SSM */
static void generic_read_ignore_data(FpiSsm *ssm, FpDevice *dev, static void
generic_read_ignore_data (FpiSsm *ssm, FpDevice *dev,
size_t bytes) size_t bytes)
{ {
FpiUsbTransfer *transfer; FpiUsbTransfer *transfer;
transfer = fpi_usb_transfer_new(dev); transfer = fpi_usb_transfer_new (dev);
transfer->ssm = ssm; transfer->ssm = ssm;
transfer->short_is_error = TRUE; transfer->short_is_error = TRUE;
fpi_usb_transfer_fill_bulk(transfer, EP_IN, bytes); fpi_usb_transfer_fill_bulk (transfer, EP_IN, bytes);
fpi_usb_transfer_submit(transfer, BULK_TIMEOUT, NULL, fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
generic_ignore_data_cb, NULL); generic_ignore_data_cb, NULL);
fpi_usb_transfer_unref(transfer); fpi_usb_transfer_unref (transfer);
} }
/****** IMAGE PROCESSING ******/ /****** IMAGE PROCESSING ******/
static int sum_histogram_values(unsigned char *data, guint8 threshold) static int
sum_histogram_values (unsigned char *data, guint8 threshold)
{ {
int r = 0; int r = 0;
int i; int i;
guint16 *histogram = (guint16 *)(data + 1); guint16 *histogram = (guint16 *) (data + 1);
if (*data != 0xde) if (*data != 0xde)
return -1; return -1;
@ -248,63 +265,73 @@ static const struct aes_regwrite finger_det_reqs[] = {
{ AES2501_REG_LPONT, AES2501_LPONT_MIN_VALUE }, { AES2501_REG_LPONT, AES2501_LPONT_MIN_VALUE },
}; };
static void start_finger_detection(FpImageDevice *dev); static void start_finger_detection (FpImageDevice *dev);
static void finger_det_data_cb(FpiUsbTransfer *transfer, FpDevice *_dev, static void
finger_det_data_cb (FpiUsbTransfer *transfer, FpDevice *_dev,
gpointer user_data, GError *error) gpointer user_data, GError *error)
{ {
FpImageDevice *dev = FP_IMAGE_DEVICE(_dev); FpImageDevice *dev = FP_IMAGE_DEVICE (_dev);
unsigned char *data = transfer->buffer; unsigned char *data = transfer->buffer;
int i; int i;
int sum = 0; int sum = 0;
if (error) { if (error)
fpi_image_device_session_error(dev, error); {
fpi_image_device_session_error (dev, error);
return; return;
} }
/* examine histogram to determine finger presence */ /* examine histogram to determine finger presence */
for (i = 1; i < 9; i++) for (i = 1; i < 9; i++)
sum += (data[i] & 0xf) + (data[i] >> 4); sum += (data[i] & 0xf) + (data[i] >> 4);
if (sum > 20) { if (sum > 20)
{
/* finger present, start capturing */ /* finger present, start capturing */
fpi_image_device_report_finger_status(dev, TRUE); fpi_image_device_report_finger_status (dev, TRUE);
start_capture(dev); start_capture (dev);
} else { }
else
{
/* no finger, poll for a new histogram */ /* no finger, poll for a new histogram */
start_finger_detection(dev); start_finger_detection (dev);
} }
} }
static void finger_det_reqs_cb(FpImageDevice *dev, GError *error, static void
finger_det_reqs_cb (FpImageDevice *dev, GError *error,
void *user_data) void *user_data)
{ {
FpiUsbTransfer *transfer; FpiUsbTransfer *transfer;
if (error) { if (error)
{
fpi_image_device_session_error (dev, error); fpi_image_device_session_error (dev, error);
return; return;
} }
transfer = fpi_usb_transfer_new(FP_DEVICE(dev)); transfer = fpi_usb_transfer_new (FP_DEVICE (dev));
transfer->short_is_error = TRUE; transfer->short_is_error = TRUE;
fpi_usb_transfer_fill_bulk(transfer, EP_IN, FINGER_DETECTION_LEN); fpi_usb_transfer_fill_bulk (transfer, EP_IN, FINGER_DETECTION_LEN);
fpi_usb_transfer_submit(transfer, BULK_TIMEOUT, NULL, fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
finger_det_data_cb, NULL); finger_det_data_cb, NULL);
fpi_usb_transfer_unref(transfer); fpi_usb_transfer_unref (transfer);
} }
static void start_finger_detection(FpImageDevice *dev) static void
start_finger_detection (FpImageDevice *dev)
{ {
FpiDeviceAes2501 *self = FPI_DEVICE_AES2501(dev); FpiDeviceAes2501 *self = FPI_DEVICE_AES2501 (dev);
G_DEBUG_HERE();
if (self->deactivating) { G_DEBUG_HERE ();
complete_deactivation(dev);
if (self->deactivating)
{
complete_deactivation (dev);
return; return;
} }
aes_write_regv(dev, finger_det_reqs, G_N_ELEMENTS(finger_det_reqs), aes_write_regv (dev, finger_det_reqs, G_N_ELEMENTS (finger_det_reqs),
finger_det_reqs_cb, NULL); finger_det_reqs_cb, NULL);
} }
@ -383,165 +410,194 @@ enum capture_states {
CAPTURE_NUM_STATES, CAPTURE_NUM_STATES,
}; };
static void capture_read_strip_cb(FpiUsbTransfer *transfer, FpDevice *_dev, static void
capture_read_strip_cb (FpiUsbTransfer *transfer, FpDevice *_dev,
gpointer user_data, GError *error) gpointer user_data, GError *error)
{ {
FpiSsm *ssm = transfer->ssm; FpiSsm *ssm = transfer->ssm;
unsigned char *stripdata; unsigned char *stripdata;
FpImageDevice *dev = FP_IMAGE_DEVICE(_dev); FpImageDevice *dev = FP_IMAGE_DEVICE (_dev);
FpiDeviceAes2501 *self = FPI_DEVICE_AES2501(_dev); FpiDeviceAes2501 *self = FPI_DEVICE_AES2501 (_dev);
unsigned char *data = transfer->buffer; unsigned char *data = transfer->buffer;
int sum; int sum;
int threshold; int threshold;
if (error) { if (error)
fpi_ssm_mark_failed(ssm, error); {
fpi_ssm_mark_failed (ssm, error);
return; return;
} }
threshold = regval_from_dump(data + 1 + 192*8 + 1 + 16*2 + 1 + 8, threshold = regval_from_dump (data + 1 + 192 * 8 + 1 + 16 * 2 + 1 + 8,
AES2501_REG_DATFMT); AES2501_REG_DATFMT);
if (threshold < 0) { if (threshold < 0)
fpi_ssm_mark_failed(ssm, {
fpi_ssm_mark_failed (ssm,
fpi_device_error_new (FP_DEVICE_ERROR_PROTO)); fpi_device_error_new (FP_DEVICE_ERROR_PROTO));
return; return;
} }
sum = sum_histogram_values(data + 1 + 192*8, threshold & 0x0f); sum = sum_histogram_values (data + 1 + 192 * 8, threshold & 0x0f);
if (sum < 0) { if (sum < 0)
fpi_ssm_mark_failed(ssm, {
fpi_ssm_mark_failed (ssm,
fpi_device_error_new (FP_DEVICE_ERROR_PROTO)); fpi_device_error_new (FP_DEVICE_ERROR_PROTO));
return; return;
} }
fp_dbg("sum=%d", sum); fp_dbg ("sum=%d", sum);
if (sum < AES2501_SUM_LOW_THRESH) { if (sum < AES2501_SUM_LOW_THRESH)
{
strip_scan_reqs[4].value -= 0x8; strip_scan_reqs[4].value -= 0x8;
if (strip_scan_reqs[4].value < AES2501_ADREFHI_MIN_VALUE) if (strip_scan_reqs[4].value < AES2501_ADREFHI_MIN_VALUE)
strip_scan_reqs[4].value = AES2501_ADREFHI_MIN_VALUE; strip_scan_reqs[4].value = AES2501_ADREFHI_MIN_VALUE;
} else if (sum > AES2501_SUM_HIGH_THRESH) { }
else if (sum > AES2501_SUM_HIGH_THRESH)
{
strip_scan_reqs[4].value += 0x8; strip_scan_reqs[4].value += 0x8;
if (strip_scan_reqs[4].value > AES2501_ADREFHI_MAX_VALUE) if (strip_scan_reqs[4].value > AES2501_ADREFHI_MAX_VALUE)
strip_scan_reqs[4].value = AES2501_ADREFHI_MAX_VALUE; strip_scan_reqs[4].value = AES2501_ADREFHI_MAX_VALUE;
} }
fp_dbg("ADREFHI is %.2x", strip_scan_reqs[4].value); fp_dbg ("ADREFHI is %.2x", strip_scan_reqs[4].value);
/* Sum is 0, maybe finger was removed? Wait for 3 empty frames /* Sum is 0, maybe finger was removed? Wait for 3 empty frames
* to ensure * to ensure
*/ */
if (sum == 0) { if (sum == 0)
{
self->no_finger_cnt++; self->no_finger_cnt++;
if (self->no_finger_cnt == 3) { if (self->no_finger_cnt == 3)
{
FpImage *img; FpImage *img;
self->strips = g_slist_reverse(self->strips); self->strips = g_slist_reverse (self->strips);
fpi_do_movement_estimation(&assembling_ctx, self->strips); fpi_do_movement_estimation (&assembling_ctx, self->strips);
img = fpi_assemble_frames(&assembling_ctx, img = fpi_assemble_frames (&assembling_ctx,
self->strips); self->strips);
g_slist_free_full(self->strips, g_free); g_slist_free_full (self->strips, g_free);
self->strips = NULL; self->strips = NULL;
self->strips_len = 0; self->strips_len = 0;
fpi_image_device_image_captured(dev, img); fpi_image_device_image_captured (dev, img);
fpi_image_device_report_finger_status(dev, FALSE); fpi_image_device_report_finger_status (dev, FALSE);
/* marking machine complete will re-trigger finger detection loop */ /* marking machine complete will re-trigger finger detection loop */
fpi_ssm_mark_completed(ssm); fpi_ssm_mark_completed (ssm);
} else {
fpi_ssm_jump_to_state(ssm, CAPTURE_REQUEST_STRIP);
} }
} else { else
{
fpi_ssm_jump_to_state (ssm, CAPTURE_REQUEST_STRIP);
}
}
else
{
/* obtain next strip */ /* obtain next strip */
/* FIXME: would preallocating strip buffers be a decent optimization? */ /* FIXME: would preallocating strip buffers be a decent optimization? */
struct fpi_frame *stripe = g_malloc(FRAME_WIDTH * FRAME_HEIGHT / 2 + sizeof(struct fpi_frame)); struct fpi_frame *stripe = g_malloc (FRAME_WIDTH * FRAME_HEIGHT / 2 + sizeof (struct fpi_frame));
stripe->delta_x = 0; stripe->delta_x = 0;
stripe->delta_y = 0; stripe->delta_y = 0;
stripdata = stripe->data; stripdata = stripe->data;
memcpy(stripdata, data + 1, 192*8); memcpy (stripdata, data + 1, 192 * 8);
self->no_finger_cnt = 0; self->no_finger_cnt = 0;
self->strips = g_slist_prepend(self->strips, stripe); self->strips = g_slist_prepend (self->strips, stripe);
self->strips_len++; self->strips_len++;
fpi_ssm_jump_to_state(ssm, CAPTURE_REQUEST_STRIP); fpi_ssm_jump_to_state (ssm, CAPTURE_REQUEST_STRIP);
} }
} }
static void capture_run_state(FpiSsm *ssm, FpDevice *device, void *user_data) static void
capture_run_state (FpiSsm *ssm, FpDevice *device, void *user_data)
{ {
FpImageDevice *dev = user_data; FpImageDevice *dev = user_data;
FpiDeviceAes2501 *self = FPI_DEVICE_AES2501(device); FpiDeviceAes2501 *self = FPI_DEVICE_AES2501 (device);
switch (fpi_ssm_get_cur_state(ssm)) { switch (fpi_ssm_get_cur_state (ssm))
{
case CAPTURE_WRITE_REQS_1: case CAPTURE_WRITE_REQS_1:
aes_write_regv(dev, capture_reqs_1, G_N_ELEMENTS(capture_reqs_1), aes_write_regv (dev, capture_reqs_1, G_N_ELEMENTS (capture_reqs_1),
generic_write_regv_cb, ssm); generic_write_regv_cb, ssm);
break; break;
case CAPTURE_READ_DATA_1: case CAPTURE_READ_DATA_1:
generic_read_ignore_data(ssm, device, READ_REGS_RESP_LEN); generic_read_ignore_data (ssm, device, READ_REGS_RESP_LEN);
break; break;
case CAPTURE_WRITE_REQS_2: case CAPTURE_WRITE_REQS_2:
aes_write_regv(dev, capture_reqs_2, G_N_ELEMENTS(capture_reqs_2), aes_write_regv (dev, capture_reqs_2, G_N_ELEMENTS (capture_reqs_2),
generic_write_regv_cb, ssm); generic_write_regv_cb, ssm);
break; break;
case CAPTURE_READ_DATA_2: case CAPTURE_READ_DATA_2:
generic_read_ignore_data(ssm, device, READ_REGS_RESP_LEN); generic_read_ignore_data (ssm, device, READ_REGS_RESP_LEN);
break; break;
case CAPTURE_REQUEST_STRIP: case CAPTURE_REQUEST_STRIP:
if (self->deactivating) if (self->deactivating)
fpi_ssm_mark_completed(ssm); fpi_ssm_mark_completed (ssm);
else else
aes_write_regv(dev, strip_scan_reqs, G_N_ELEMENTS(strip_scan_reqs), aes_write_regv (dev, strip_scan_reqs, G_N_ELEMENTS (strip_scan_reqs),
generic_write_regv_cb, ssm); generic_write_regv_cb, ssm);
break; break;
case CAPTURE_READ_STRIP: { case CAPTURE_READ_STRIP: {
FpiUsbTransfer *transfer; FpiUsbTransfer *transfer;
transfer = fpi_usb_transfer_new(device); transfer = fpi_usb_transfer_new (device);
transfer->ssm = ssm; transfer->ssm = ssm;
transfer->short_is_error = TRUE; transfer->short_is_error = TRUE;
fpi_usb_transfer_fill_bulk(transfer, EP_IN, STRIP_CAPTURE_LEN); fpi_usb_transfer_fill_bulk (transfer, EP_IN, STRIP_CAPTURE_LEN);
fpi_usb_transfer_submit(transfer, BULK_TIMEOUT, NULL, fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
capture_read_strip_cb, NULL); capture_read_strip_cb, NULL);
fpi_usb_transfer_unref(transfer); fpi_usb_transfer_unref (transfer);
break; break;
} }
}; }
;
} }
static void capture_sm_complete(FpiSsm *ssm, FpDevice *_dev, void *user_data, static void
capture_sm_complete (FpiSsm *ssm, FpDevice *_dev, void *user_data,
GError *error) GError *error)
{ {
FpImageDevice *dev = user_data; FpImageDevice *dev = user_data;
FpiDeviceAes2501 *self = FPI_DEVICE_AES2501(_dev); FpiDeviceAes2501 *self = FPI_DEVICE_AES2501 (_dev);
G_DEBUG_HERE(); G_DEBUG_HERE ();
if (self->deactivating) { if (self->deactivating)
complete_deactivation(dev); {
complete_deactivation (dev);
g_clear_pointer (&error, g_error_free); 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); 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)
{ {
FpiDeviceAes2501 *self = FPI_DEVICE_AES2501(dev); FpiDeviceAes2501 *self = FPI_DEVICE_AES2501 (dev);
FpiSsm *ssm; FpiSsm *ssm;
if (self->deactivating) { if (self->deactivating)
complete_deactivation(dev); {
complete_deactivation (dev);
return; return;
} }
self->no_finger_cnt = 0; self->no_finger_cnt = 0;
/* Reset gain */ /* Reset gain */
strip_scan_reqs[4].value = AES2501_ADREFHI_MAX_VALUE; strip_scan_reqs[4].value = AES2501_ADREFHI_MAX_VALUE;
ssm = fpi_ssm_new(FP_DEVICE(dev), capture_run_state, ssm = fpi_ssm_new (FP_DEVICE (dev), capture_run_state,
CAPTURE_NUM_STATES, dev); CAPTURE_NUM_STATES, dev);
G_DEBUG_HERE(); G_DEBUG_HERE ();
fpi_ssm_start(ssm, capture_sm_complete); fpi_ssm_start (ssm, capture_sm_complete);
} }
/****** INITIALIZATION/DEINITIALIZATION ******/ /****** INITIALIZATION/DEINITIALIZATION ******/
@ -649,34 +705,41 @@ enum activate_states {
ACTIVATE_NUM_STATES, ACTIVATE_NUM_STATES,
}; };
void activate_read_regs_cb(FpImageDevice *dev, GError *error, void
activate_read_regs_cb (FpImageDevice *dev, GError *error,
unsigned char *regs, void *user_data) unsigned char *regs, void *user_data)
{ {
FpiSsm *ssm = user_data; FpiSsm *ssm = user_data;
FpiDeviceAes2501 *self = FPI_DEVICE_AES2501(dev); FpiDeviceAes2501 *self = FPI_DEVICE_AES2501 (dev);
if (error) { if (error)
fpi_ssm_mark_failed(ssm, error); {
} else { fpi_ssm_mark_failed (ssm, error);
fp_dbg("reg 0xaf = %x", regs[0x5f]); }
if (regs[0x5f] != 0x6b || ++self->read_regs_retry_count == 13)
fpi_ssm_jump_to_state(ssm, WRITE_INIT_4);
else else
fpi_ssm_next_state(ssm); {
fp_dbg ("reg 0xaf = %x", regs[0x5f]);
if (regs[0x5f] != 0x6b || ++self->read_regs_retry_count == 13)
fpi_ssm_jump_to_state (ssm, WRITE_INIT_4);
else
fpi_ssm_next_state (ssm);
} }
} }
static void activate_init3_cb(FpImageDevice *dev, GError *error, static void
activate_init3_cb (FpImageDevice *dev, GError *error,
void *user_data) void *user_data)
{ {
FpiSsm *ssm = user_data; FpiSsm *ssm = user_data;
if (!error) if (!error)
fpi_ssm_jump_to_state(ssm, READ_REGS); fpi_ssm_jump_to_state (ssm, READ_REGS);
else else
fpi_ssm_mark_failed(ssm, error); fpi_ssm_mark_failed (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)
{ {
FpImageDevice *dev = user_data; FpImageDevice *dev = user_data;
@ -699,110 +762,129 @@ static void activate_run_state(FpiSsm *ssm, FpDevice *_dev, void *user_data)
aes_write_regv(init_4); aes_write_regv(init_4);
*/ */
switch (fpi_ssm_get_cur_state(ssm)) { switch (fpi_ssm_get_cur_state (ssm))
{
case WRITE_INIT_1: case WRITE_INIT_1:
aes_write_regv(dev, init_1, G_N_ELEMENTS(init_1), aes_write_regv (dev, init_1, G_N_ELEMENTS (init_1),
generic_write_regv_cb, ssm); generic_write_regv_cb, ssm);
break; break;
case READ_DATA_1: case READ_DATA_1:
fp_dbg("read data 1"); fp_dbg ("read data 1");
generic_read_ignore_data(ssm, _dev, FINGER_DETECTION_LEN); generic_read_ignore_data (ssm, _dev, FINGER_DETECTION_LEN);
break; break;
case WRITE_INIT_2: case WRITE_INIT_2:
aes_write_regv(dev, init_2, G_N_ELEMENTS(init_2), aes_write_regv (dev, init_2, G_N_ELEMENTS (init_2),
generic_write_regv_cb, ssm); generic_write_regv_cb, ssm);
break; break;
case READ_REGS: case READ_REGS:
read_regs(dev, activate_read_regs_cb, ssm); read_regs (dev, activate_read_regs_cb, ssm);
break; break;
case WRITE_INIT_3: case WRITE_INIT_3:
aes_write_regv(dev, init_3, G_N_ELEMENTS(init_3), aes_write_regv (dev, init_3, G_N_ELEMENTS (init_3),
activate_init3_cb, ssm); activate_init3_cb, ssm);
break; break;
case WRITE_INIT_4: case WRITE_INIT_4:
aes_write_regv(dev, init_4, G_N_ELEMENTS(init_4), aes_write_regv (dev, init_4, G_N_ELEMENTS (init_4),
generic_write_regv_cb, ssm); generic_write_regv_cb, ssm);
break; break;
case WRITE_INIT_5: case WRITE_INIT_5:
aes_write_regv(dev, init_5, G_N_ELEMENTS(init_5), aes_write_regv (dev, init_5, G_N_ELEMENTS (init_5),
generic_write_regv_cb, ssm); generic_write_regv_cb, ssm);
break; break;
} }
} }
static void activate_sm_complete(FpiSsm *ssm, FpDevice *dev, static void
activate_sm_complete (FpiSsm *ssm, FpDevice *dev,
void *user_data, GError *error) void *user_data, GError *error)
{ {
fpi_image_device_activate_complete(FP_IMAGE_DEVICE (dev), error); fpi_image_device_activate_complete (FP_IMAGE_DEVICE (dev), error);
if (!error) if (!error)
start_finger_detection(FP_IMAGE_DEVICE (dev)); start_finger_detection (FP_IMAGE_DEVICE (dev));
fpi_ssm_free(ssm); fpi_ssm_free (ssm);
} }
static void dev_activate(FpImageDevice *dev) static void
dev_activate (FpImageDevice *dev)
{ {
FpiDeviceAes2501 *self = FPI_DEVICE_AES2501(dev); FpiDeviceAes2501 *self = FPI_DEVICE_AES2501 (dev);
FpiSsm *ssm = fpi_ssm_new(FP_DEVICE(dev), activate_run_state, FpiSsm *ssm = fpi_ssm_new (FP_DEVICE (dev), activate_run_state,
ACTIVATE_NUM_STATES, dev); ACTIVATE_NUM_STATES, dev);
self->read_regs_retry_count = 0; self->read_regs_retry_count = 0;
fpi_ssm_start(ssm, activate_sm_complete); fpi_ssm_start (ssm, activate_sm_complete);
} }
static void dev_deactivate(FpImageDevice *dev) static void
dev_deactivate (FpImageDevice *dev)
{ {
FpiDeviceAes2501 *self = FPI_DEVICE_AES2501(dev); FpiDeviceAes2501 *self = FPI_DEVICE_AES2501 (dev);
/* FIXME: audit cancellation points, probably need more, specifically /* FIXME: audit cancellation points, probably need more, specifically
* in error handling paths? */ * in error handling paths? */
self->deactivating = TRUE; self->deactivating = TRUE;
} }
static void complete_deactivation(FpImageDevice *dev) static void
complete_deactivation (FpImageDevice *dev)
{ {
FpiDeviceAes2501 *self = FPI_DEVICE_AES2501(dev); FpiDeviceAes2501 *self = FPI_DEVICE_AES2501 (dev);
G_DEBUG_HERE();
G_DEBUG_HERE ();
/* FIXME: if we're in the middle of a scan, we should cancel the scan. /* FIXME: if we're in the middle of a scan, we should cancel the scan.
* maybe we can do this with a master reset, unconditionally? */ * maybe we can do this with a master reset, unconditionally? */
self->deactivating = FALSE; self->deactivating = FALSE;
g_slist_free(self->strips); g_slist_free (self->strips);
self->strips = NULL; self->strips = NULL;
self->strips_len = 0; self->strips_len = 0;
fpi_image_device_deactivate_complete(dev, NULL); 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;
/* FIXME check endpoints */ /* FIXME check endpoints */
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)), g_usb_device_release_interface (fpi_device_get_usb_device (FP_DEVICE (dev)),
0, 0, &error); 0, 0, &error);
fpi_image_device_close_complete(dev, error); fpi_image_device_close_complete (dev, error);
} }
static const FpIdEntry id_table [ ] = { static const FpIdEntry id_table[] = {
{ .vid = 0x08ff, .pid = 0x2500, { .vid = 0x08ff, .pid = 0x2500, },/* AES2500 */
}, /* AES2500 */ { .vid = 0x08ff, .pid = 0x2580, },/* AES2501 */
{ .vid = 0x08ff, .pid = 0x2580,
}, /* AES2501 */
{ .vid = 0, .pid = 0, .driver_data = 0 }, { .vid = 0, .pid = 0, .driver_data = 0 },
}; };
static void fpi_device_aes2501_init(FpiDeviceAes2501 *self) { static void
fpi_device_aes2501_init (FpiDeviceAes2501 *self)
{
} }
static void fpi_device_aes2501_class_init(FpiDeviceAes2501Class *klass) { static void
FpDeviceClass *dev_class = FP_DEVICE_CLASS(klass); fpi_device_aes2501_class_init (FpiDeviceAes2501Class *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 = "aes2501"; dev_class->id = "aes2501";
dev_class->full_name = "AuthenTec AES2501"; dev_class->full_name = "AuthenTec AES2501";
@ -818,4 +900,3 @@ static void fpi_device_aes2501_class_init(FpiDeviceAes2501Class *klass) {
img_class->img_width = IMAGE_WIDTH; img_class->img_width = IMAGE_WIDTH;
img_class->img_height = -1; img_class->img_height = -1;
} }

View file

@ -57,10 +57,10 @@ enum aes2501_regs {
#define FIRST_AES2501_REG AES2501_REG_CTRL1 #define FIRST_AES2501_REG AES2501_REG_CTRL1
#define LAST_AES2501_REG AES2501_REG_CHWORD5 #define LAST_AES2501_REG AES2501_REG_CHWORD5
#define AES2501_CTRL1_MASTER_RESET (1<<0) #define AES2501_CTRL1_MASTER_RESET (1 << 0)
#define AES2501_CTRL1_SCAN_RESET (1<<1) /* stop + restart scan sequencer */ #define AES2501_CTRL1_SCAN_RESET (1 << 1) /* stop + restart scan sequencer */
/* 1 = continuously updated, 0 = updated prior to starting a scan */ /* 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 */ /* 1 = continuous scans, 0 = single scans */
#define AES2501_CTRL2_CONTINUOUS 0x01 #define AES2501_CTRL2_CONTINUOUS 0x01

View file

@ -27,8 +27,8 @@
#include "aes2550.h" #include "aes2550.h"
#include "aeslib.h" #include "aeslib.h"
static void start_capture(FpImageDevice *dev); static void start_capture (FpImageDevice *dev);
static void complete_deactivation(FpImageDevice *dev); static void complete_deactivation (FpImageDevice *dev);
#define EP_IN (1 | FPI_USB_ENDPOINT_IN) #define EP_IN (1 | FPI_USB_ENDPOINT_IN)
#define EP_OUT (2 | FPI_USB_ENDPOINT_OUT) #define EP_OUT (2 | FPI_USB_ENDPOINT_OUT)
@ -51,7 +51,8 @@ static void complete_deactivation(FpImageDevice *dev);
#define FRAME_SIZE (FRAME_WIDTH * FRAME_HEIGHT) #define FRAME_SIZE (FRAME_WIDTH * FRAME_HEIGHT)
#define IMAGE_WIDTH (FRAME_WIDTH + (FRAME_WIDTH / 2)) #define IMAGE_WIDTH (FRAME_WIDTH + (FRAME_WIDTH / 2))
struct _FpiDeviceAes2550 { struct _FpiDeviceAes2550
{
FpImageDevice parent; FpImageDevice parent;
GSList *strips; GSList *strips;
@ -59,9 +60,9 @@ struct _FpiDeviceAes2550 {
gboolean deactivating; gboolean deactivating;
int heartbeat_cnt; int heartbeat_cnt;
}; };
G_DECLARE_FINAL_TYPE(FpiDeviceAes2550, fpi_device_aes2550, FPI, DEVICE_AES2550, G_DECLARE_FINAL_TYPE (FpiDeviceAes2550, fpi_device_aes2550, FPI, DEVICE_AES2550,
FpImageDevice); FpImageDevice);
G_DEFINE_TYPE(FpiDeviceAes2550, fpi_device_aes2550, FP_TYPE_IMAGE_DEVICE); G_DEFINE_TYPE (FpiDeviceAes2550, fpi_device_aes2550, FP_TYPE_IMAGE_DEVICE);
static struct fpi_frame_asmbl_ctx assembling_ctx = { static struct fpi_frame_asmbl_ctx assembling_ctx = {
.frame_width = FRAME_WIDTH, .frame_width = FRAME_WIDTH,
@ -83,70 +84,80 @@ static unsigned char finger_det_reqs[] = {
AES2550_CMD_RUN_FD, 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, static void
finger_det_data_cb (FpiUsbTransfer *transfer, FpDevice *device,
gpointer user_data, GError *error) gpointer user_data, GError *error)
{ {
FpImageDevice *dev = FP_IMAGE_DEVICE(device); FpImageDevice *dev = FP_IMAGE_DEVICE (device);
unsigned char *data = transfer->buffer; unsigned char *data = transfer->buffer;
if (error) { if (error)
fpi_image_device_session_error(FP_IMAGE_DEVICE(device), error); {
fpi_image_device_session_error (FP_IMAGE_DEVICE (device), error);
return; return;
} }
fp_dbg("transfer completed, len: %.4x, data: %.2x %.2x", fp_dbg ("transfer completed, len: %.4x, data: %.2x %.2x",
(gint)transfer->actual_length, (int)data[0], (int)data[1]); (gint) transfer->actual_length, (int) data[0], (int) data[1]);
/* Check if we got 2 bytes, reg address 0x83 and its value */ /* 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)) { if ((transfer->actual_length >= 2) && (data[0] == 0x83) && (data[1] & AES2550_REG83_FINGER_PRESENT))
{
/* finger present, start capturing */ /* finger present, start capturing */
fpi_image_device_report_finger_status(dev, TRUE); fpi_image_device_report_finger_status (dev, TRUE);
start_capture(dev); start_capture (dev);
} else { }
else
{
/* no finger, poll for a new histogram */ /* no finger, poll for a new histogram */
start_finger_detection(dev); start_finger_detection (dev);
} }
} }
static void finger_det_reqs_cb(FpiUsbTransfer *t, FpDevice *device, static void
finger_det_reqs_cb (FpiUsbTransfer *t, FpDevice *device,
gpointer user_data, GError *error) gpointer user_data, GError *error)
{ {
FpiUsbTransfer *transfer; FpiUsbTransfer *transfer;
FpImageDevice *dev = user_data; FpImageDevice *dev = user_data;
if (error) { if (error)
fpi_image_device_session_error(dev, error); {
fpi_image_device_session_error (dev, error);
return; return;
} }
transfer = fpi_usb_transfer_new (device); transfer = fpi_usb_transfer_new (device);
/* 2 bytes of result */ /* 2 bytes of result */
fpi_usb_transfer_fill_bulk (transfer, EP_IN, AES2550_EP_IN_BUF_SIZE); fpi_usb_transfer_fill_bulk (transfer, EP_IN, AES2550_EP_IN_BUF_SIZE);
fpi_usb_transfer_submit(transfer, BULK_TIMEOUT, NULL, fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
finger_det_data_cb, NULL); finger_det_data_cb, NULL);
fpi_usb_transfer_unref(transfer); 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); FpiDeviceAes2550 *self = FPI_DEVICE_AES2550 (dev);
FpiUsbTransfer *transfer; FpiUsbTransfer *transfer;
G_DEBUG_HERE();
if (self->deactivating) { G_DEBUG_HERE ();
complete_deactivation(dev);
if (self->deactivating)
{
complete_deactivation (dev);
return; return;
} }
transfer = fpi_usb_transfer_new(FP_DEVICE(dev)); transfer = fpi_usb_transfer_new (FP_DEVICE (dev));
transfer->short_is_error = TRUE; transfer->short_is_error = TRUE;
fpi_usb_transfer_fill_bulk_full(transfer, EP_OUT, finger_det_reqs, fpi_usb_transfer_fill_bulk_full (transfer, EP_OUT, finger_det_reqs,
sizeof(finger_det_reqs), NULL); sizeof (finger_det_reqs), NULL);
fpi_usb_transfer_submit(transfer, BULK_TIMEOUT, NULL, fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
finger_det_reqs_cb, NULL); finger_det_reqs_cb, NULL);
fpi_usb_transfer_unref(transfer); fpi_usb_transfer_unref (transfer);
} }
/****** CAPTURE ******/ /****** CAPTURE ******/
@ -177,202 +188,230 @@ enum capture_states {
}; };
/* Returns number of processed bytes */ /* Returns number of processed bytes */
static gboolean process_strip_data(FpiSsm *ssm, FpImageDevice *dev, static gboolean
process_strip_data (FpiSsm *ssm, FpImageDevice *dev,
unsigned char *data) unsigned char *data)
{ {
unsigned char *stripdata; unsigned char *stripdata;
FpiDeviceAes2550 *self = FPI_DEVICE_AES2550(dev); FpiDeviceAes2550 *self = FPI_DEVICE_AES2550 (dev);
struct fpi_frame *stripe; struct fpi_frame *stripe;
int len; int len;
if (data[0] != AES2550_EDATA_MAGIC) { if (data[0] != AES2550_EDATA_MAGIC)
fp_dbg("Bogus magic: %.2x\n", (int)(data[0])); {
fp_dbg ("Bogus magic: %.2x\n", (int) (data[0]));
return FALSE; return FALSE;
} }
len = data[1] * 256 + data[2]; len = data[1] * 256 + data[2];
if (len != (AES2550_STRIP_SIZE - 3)) { if (len != (AES2550_STRIP_SIZE - 3))
fp_dbg("Bogus frame len: %.4x\n", len); 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 = g_malloc0(FRAME_WIDTH * FRAME_HEIGHT / 2 + sizeof(struct fpi_frame)); /* 4 bits per pixel */ stripe->delta_x = (int8_t) data[6];
stripe->delta_x = (int8_t)data[6]; stripe->delta_y = -(int8_t) data[7];
stripe->delta_y = -(int8_t)data[7];
stripdata = stripe->data; stripdata = stripe->data;
memcpy(stripdata, data + 33, FRAME_WIDTH * FRAME_HEIGHT / 2); memcpy (stripdata, data + 33, FRAME_WIDTH * FRAME_HEIGHT / 2);
self->strips = g_slist_prepend(self->strips, stripe); self->strips = g_slist_prepend (self->strips, stripe);
self->strips_len++; 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, static void
capture_reqs_cb (FpiUsbTransfer *transfer, FpDevice *device,
gpointer user_data, GError *error) gpointer user_data, GError *error)
{ {
if (!error) { if (!error)
fpi_ssm_next_state(transfer->ssm); fpi_ssm_next_state (transfer->ssm);
} else { else
fpi_ssm_mark_failed(transfer->ssm, error); fpi_ssm_mark_failed (transfer->ssm, error);
}
} }
static void capture_set_idle_reqs_cb(FpiUsbTransfer *transfer, static void
capture_set_idle_reqs_cb (FpiUsbTransfer *transfer,
FpDevice *device, gpointer user_data, FpDevice *device, gpointer user_data,
GError *error) GError *error)
{ {
FpImageDevice *dev = FP_IMAGE_DEVICE(device); FpImageDevice *dev = FP_IMAGE_DEVICE (device);
FpiDeviceAes2550 *self = FPI_DEVICE_AES2550(dev); FpiDeviceAes2550 *self = FPI_DEVICE_AES2550 (dev);
if (!error && self->strips_len) { if (!error && self->strips_len)
{
FpImage *img; FpImage *img;
self->strips = g_slist_reverse(self->strips); self->strips = g_slist_reverse (self->strips);
img = fpi_assemble_frames(&assembling_ctx, self->strips); img = fpi_assemble_frames (&assembling_ctx, self->strips);
g_slist_free_full(self->strips, g_free); g_slist_free_full (self->strips, g_free);
self->strips = NULL; self->strips = NULL;
self->strips_len = 0; self->strips_len = 0;
fpi_image_device_image_captured(dev, img); fpi_image_device_image_captured (dev, img);
fpi_image_device_report_finger_status(dev, FALSE); fpi_image_device_report_finger_status (dev, FALSE);
/* marking machine complete will re-trigger finger detection loop */ /* marking machine complete will re-trigger finger detection loop */
fpi_ssm_mark_completed(transfer->ssm); fpi_ssm_mark_completed (transfer->ssm);
} else { }
if (error)
fpi_ssm_mark_failed(transfer->ssm, error);
else else
fpi_ssm_mark_failed(transfer->ssm, {
if (error)
fpi_ssm_mark_failed (transfer->ssm, error);
else
fpi_ssm_mark_failed (transfer->ssm,
fpi_device_error_new (FP_DEVICE_ERROR_PROTO)); fpi_device_error_new (FP_DEVICE_ERROR_PROTO));
} }
} }
static void capture_read_data_cb(FpiUsbTransfer *transfer, FpDevice *device, static void
capture_read_data_cb (FpiUsbTransfer *transfer, FpDevice *device,
gpointer user_data, GError *error) gpointer user_data, GError *error)
{ {
FpImageDevice *dev = FP_IMAGE_DEVICE(device); FpImageDevice *dev = FP_IMAGE_DEVICE (device);
FpiDeviceAes2550 *self = FPI_DEVICE_AES2550(dev); FpiDeviceAes2550 *self = FPI_DEVICE_AES2550 (dev);
unsigned char *data = transfer->buffer; unsigned char *data = transfer->buffer;
if (error) { if (error)
fpi_ssm_mark_failed(transfer->ssm, error); {
fpi_ssm_mark_failed (transfer->ssm, error);
return; return;
} }
fp_dbg("request completed, len: %.4x", (gint)transfer->actual_length); fp_dbg ("request completed, len: %.4x", (gint) transfer->actual_length);
if (transfer->actual_length >= 2) if (transfer->actual_length >= 2)
fp_dbg("data: %.2x %.2x", (int)data[0], (int)data[1]); fp_dbg ("data: %.2x %.2x", (int) data[0], (int) data[1]);
switch (transfer->actual_length) { switch (transfer->actual_length)
{
case AES2550_STRIP_SIZE: case AES2550_STRIP_SIZE:
if (!process_strip_data(transfer->ssm, dev, data)) { if (!process_strip_data (transfer->ssm, dev, data))
fp_dbg("Processing strip data failed"); {
fpi_ssm_mark_failed(transfer->ssm, fp_dbg ("Processing strip data failed");
fpi_ssm_mark_failed (transfer->ssm,
fpi_device_error_new (FP_DEVICE_ERROR_PROTO)); fpi_device_error_new (FP_DEVICE_ERROR_PROTO));
return; return;
} }
self->heartbeat_cnt = 0; self->heartbeat_cnt = 0;
fpi_ssm_jump_to_state(transfer->ssm, CAPTURE_READ_DATA); fpi_ssm_jump_to_state (transfer->ssm, CAPTURE_READ_DATA);
break; break;
case AES2550_HEARTBEAT_SIZE: case AES2550_HEARTBEAT_SIZE:
if (data[0] == AES2550_HEARTBEAT_MAGIC) { if (data[0] == AES2550_HEARTBEAT_MAGIC)
{
/* No data for a long time => finger was removed or there's no movement */ /* No data for a long time => finger was removed or there's no movement */
self->heartbeat_cnt++; self->heartbeat_cnt++;
if (self->heartbeat_cnt == 3) { if (self->heartbeat_cnt == 3)
{
/* Got 3 heartbeat message, that's enough to consider that finger was removed, /* Got 3 heartbeat message, that's enough to consider that finger was removed,
* assemble image and submit it to the library */ * assemble image and submit it to the library */
fp_dbg("Got 3 heartbeats => finger removed"); fp_dbg ("Got 3 heartbeats => finger removed");
fpi_ssm_next_state(transfer->ssm); fpi_ssm_next_state (transfer->ssm);
} else { }
fpi_ssm_jump_to_state(transfer->ssm, else
{
fpi_ssm_jump_to_state (transfer->ssm,
CAPTURE_READ_DATA); CAPTURE_READ_DATA);
} }
} }
break; break;
default: default:
fp_dbg("Short frame %d, skip", fp_dbg ("Short frame %d, skip",
(gint)transfer->actual_length); (gint) transfer->actual_length);
fpi_ssm_jump_to_state(transfer->ssm, CAPTURE_READ_DATA); fpi_ssm_jump_to_state (transfer->ssm, CAPTURE_READ_DATA);
break; 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)) { switch (fpi_ssm_get_cur_state (ssm))
{
case CAPTURE_WRITE_REQS: case CAPTURE_WRITE_REQS:
{ {
FpiUsbTransfer *transfer = fpi_usb_transfer_new(dev); FpiUsbTransfer *transfer = fpi_usb_transfer_new (dev);
fpi_usb_transfer_fill_bulk_full(transfer, EP_OUT, capture_reqs, fpi_usb_transfer_fill_bulk_full (transfer, EP_OUT, capture_reqs,
sizeof(capture_reqs), NULL); sizeof (capture_reqs), NULL);
transfer->ssm = ssm; transfer->ssm = ssm;
transfer->short_is_error = TRUE; transfer->short_is_error = TRUE;
fpi_usb_transfer_submit(transfer, BULK_TIMEOUT, NULL, fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
capture_reqs_cb, NULL); capture_reqs_cb, NULL);
fpi_usb_transfer_unref(transfer); fpi_usb_transfer_unref (transfer);
} }
break; break;
case CAPTURE_READ_DATA: case CAPTURE_READ_DATA:
{ {
FpiUsbTransfer *transfer = fpi_usb_transfer_new(dev); FpiUsbTransfer *transfer = fpi_usb_transfer_new (dev);
fpi_usb_transfer_fill_bulk (transfer, EP_IN, AES2550_EP_IN_BUF_SIZE); fpi_usb_transfer_fill_bulk (transfer, EP_IN, AES2550_EP_IN_BUF_SIZE);
transfer->ssm = ssm; transfer->ssm = ssm;
fpi_usb_transfer_submit(transfer, BULK_TIMEOUT, NULL, fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
capture_read_data_cb, NULL); capture_read_data_cb, NULL);
fpi_usb_transfer_unref(transfer); fpi_usb_transfer_unref (transfer);
} }
break; break;
case CAPTURE_SET_IDLE: case CAPTURE_SET_IDLE:
{ {
FpiUsbTransfer *transfer = fpi_usb_transfer_new(dev); FpiUsbTransfer *transfer = fpi_usb_transfer_new (dev);
fpi_usb_transfer_fill_bulk_full(transfer, EP_OUT, fpi_usb_transfer_fill_bulk_full (transfer, EP_OUT,
capture_set_idle_reqs, capture_set_idle_reqs,
sizeof(capture_set_idle_reqs), sizeof (capture_set_idle_reqs),
NULL); NULL);
transfer->ssm = ssm; transfer->ssm = ssm;
transfer->short_is_error = TRUE; transfer->short_is_error = TRUE;
fpi_usb_transfer_submit(transfer, BULK_TIMEOUT, NULL, fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
capture_set_idle_reqs_cb, NULL); capture_set_idle_reqs_cb, NULL);
fpi_usb_transfer_unref(transfer); fpi_usb_transfer_unref (transfer);
} }
break; break;
}; }
;
} }
static void capture_sm_complete(FpiSsm *ssm, FpDevice *_dev, void *user_data, static void
capture_sm_complete (FpiSsm *ssm, FpDevice *_dev, void *user_data,
GError *error) GError *error)
{ {
FpImageDevice *dev = user_data; FpImageDevice *dev = user_data;
FpiDeviceAes2550 *self = FPI_DEVICE_AES2550(_dev); FpiDeviceAes2550 *self = FPI_DEVICE_AES2550 (_dev);
fp_dbg("Capture completed"); fp_dbg ("Capture completed");
if (self->deactivating) { if (self->deactivating)
complete_deactivation(dev); {
complete_deactivation (dev);
g_clear_pointer (&error, g_error_free); 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); 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); FpiDeviceAes2550 *self = FPI_DEVICE_AES2550 (dev);
FpiSsm *ssm; FpiSsm *ssm;
if (self->deactivating) { if (self->deactivating)
complete_deactivation(dev); {
complete_deactivation (dev);
return; return;
} }
self->heartbeat_cnt = 0; self->heartbeat_cnt = 0;
ssm = fpi_ssm_new(FP_DEVICE(dev), capture_run_state, ssm = fpi_ssm_new (FP_DEVICE (dev), capture_run_state,
CAPTURE_NUM_STATES, dev); CAPTURE_NUM_STATES, dev);
G_DEBUG_HERE(); G_DEBUG_HERE ();
fpi_ssm_start(ssm, capture_sm_complete); fpi_ssm_start (ssm, capture_sm_complete);
} }
/****** INITIALIZATION/DEINITIALIZATION ******/ /****** INITIALIZATION/DEINITIALIZATION ******/
@ -399,163 +438,179 @@ enum activate_states {
ACTIVATE_NUM_STATES, ACTIVATE_NUM_STATES,
}; };
static void init_reqs_cb(FpiUsbTransfer *transfer, FpDevice *device, static void
init_reqs_cb (FpiUsbTransfer *transfer, FpDevice *device,
gpointer user_data, GError *error) gpointer user_data, GError *error)
{ {
if (!error) { if (!error)
fpi_ssm_next_state(transfer->ssm); fpi_ssm_next_state (transfer->ssm);
} else { else
fpi_ssm_mark_failed(transfer->ssm, error); fpi_ssm_mark_failed (transfer->ssm, error);
}
} }
static void init_read_data_cb(FpiUsbTransfer *transfer, FpDevice *device, static void
init_read_data_cb (FpiUsbTransfer *transfer, FpDevice *device,
gpointer user_data, GError *error) gpointer user_data, GError *error)
{ {
if (!error) { if (!error)
fpi_ssm_next_state(transfer->ssm); fpi_ssm_next_state (transfer->ssm);
} else { else
fpi_ssm_mark_failed(transfer->ssm, error); fpi_ssm_mark_failed (transfer->ssm, error);
}
} }
/* TODO: use calibration table, datasheet is rather terse on that /* TODO: use calibration table, datasheet is rather terse on that
* need more info for implementation */ * need more info for implementation */
static void calibrate_read_data_cb(FpiUsbTransfer *transfer, FpDevice *device, static void
calibrate_read_data_cb (FpiUsbTransfer *transfer, FpDevice *device,
gpointer user_data, GError *error) gpointer user_data, GError *error)
{ {
if (!error) { if (!error)
fpi_ssm_next_state(transfer->ssm); fpi_ssm_next_state (transfer->ssm);
} else { else
fpi_ssm_mark_failed(transfer->ssm, error); 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)) { switch (fpi_ssm_get_cur_state (ssm))
{
case WRITE_INIT: case WRITE_INIT:
{ {
FpiUsbTransfer *transfer = fpi_usb_transfer_new(dev); FpiUsbTransfer *transfer = fpi_usb_transfer_new (dev);
fpi_usb_transfer_fill_bulk_full(transfer, EP_OUT, init_reqs, fpi_usb_transfer_fill_bulk_full (transfer, EP_OUT, init_reqs,
sizeof(init_reqs), NULL); sizeof (init_reqs), NULL);
transfer->ssm = ssm; transfer->ssm = ssm;
transfer->short_is_error = TRUE; transfer->short_is_error = TRUE;
fpi_usb_transfer_submit(transfer, BULK_TIMEOUT, NULL, fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
init_reqs_cb, NULL); init_reqs_cb, NULL);
fpi_usb_transfer_unref(transfer); fpi_usb_transfer_unref (transfer);
} }
break; break;
case READ_DATA: case READ_DATA:
{ {
FpiUsbTransfer *transfer = fpi_usb_transfer_new(dev); FpiUsbTransfer *transfer = fpi_usb_transfer_new (dev);
fpi_usb_transfer_fill_bulk(transfer, EP_IN, AES2550_EP_IN_BUF_SIZE); fpi_usb_transfer_fill_bulk (transfer, EP_IN, AES2550_EP_IN_BUF_SIZE);
transfer->ssm = ssm; transfer->ssm = ssm;
fpi_usb_transfer_submit(transfer, BULK_TIMEOUT, NULL, fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
init_read_data_cb, NULL); init_read_data_cb, NULL);
fpi_usb_transfer_unref(transfer); fpi_usb_transfer_unref (transfer);
} }
break; break;
case CALIBRATE: case CALIBRATE:
{ {
FpiUsbTransfer *transfer = fpi_usb_transfer_new(dev); FpiUsbTransfer *transfer = fpi_usb_transfer_new (dev);
fpi_usb_transfer_fill_bulk_full(transfer, EP_OUT, fpi_usb_transfer_fill_bulk_full (transfer, EP_OUT,
calibrate_reqs, calibrate_reqs,
sizeof(calibrate_reqs), NULL); sizeof (calibrate_reqs), NULL);
transfer->ssm = ssm; transfer->ssm = ssm;
transfer->short_is_error = TRUE; transfer->short_is_error = TRUE;
fpi_usb_transfer_submit(transfer, BULK_TIMEOUT, NULL, fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
init_reqs_cb, NULL); init_reqs_cb, NULL);
fpi_usb_transfer_unref(transfer); fpi_usb_transfer_unref (transfer);
} }
break; break;
case READ_CALIB_TABLE: case READ_CALIB_TABLE:
{ {
FpiUsbTransfer *transfer = fpi_usb_transfer_new(dev); FpiUsbTransfer *transfer = fpi_usb_transfer_new (dev);
fpi_usb_transfer_fill_bulk(transfer, EP_IN, AES2550_EP_IN_BUF_SIZE); fpi_usb_transfer_fill_bulk (transfer, EP_IN, AES2550_EP_IN_BUF_SIZE);
transfer->ssm = ssm; transfer->ssm = ssm;
fpi_usb_transfer_submit(transfer, BULK_TIMEOUT, NULL, fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
calibrate_read_data_cb, NULL); calibrate_read_data_cb, NULL);
fpi_usb_transfer_unref(transfer); fpi_usb_transfer_unref (transfer);
} }
break; break;
} }
} }
static void activate_sm_complete(FpiSsm *ssm, FpDevice *_dev, static void
activate_sm_complete (FpiSsm *ssm, FpDevice *_dev,
void *user_data, GError *error) 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) if (!error)
start_finger_detection(dev); start_finger_detection (dev);
fpi_ssm_free(ssm); 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, FpiSsm *ssm = fpi_ssm_new (FP_DEVICE (dev), activate_run_state,
ACTIVATE_NUM_STATES, dev); ACTIVATE_NUM_STATES, dev);
fpi_ssm_start(ssm, activate_sm_complete);
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); FpiDeviceAes2550 *self = FPI_DEVICE_AES2550 (dev);
G_DEBUG_HERE();
G_DEBUG_HERE ();
self->deactivating = FALSE; self->deactivating = FALSE;
g_slist_free(self->strips); g_slist_free (self->strips);
self->strips = NULL; self->strips = NULL;
self->strips_len = 0; self->strips_len = 0;
fpi_image_device_deactivate_complete(dev, NULL); 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;
/* TODO check that device has endpoints we're using */ /* TODO check that device has endpoints we're using */
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)), g_usb_device_release_interface (fpi_device_get_usb_device (FP_DEVICE (dev)),
0, 0, &error); 0, 0, &error);
fpi_image_device_close_complete(dev, error); fpi_image_device_close_complete (dev, error);
} }
static const FpIdEntry id_table [ ] = { static const FpIdEntry id_table[] = {
{ .vid = 0x08ff, .pid = 0x2550, { .vid = 0x08ff, .pid = 0x2550, },/* AES2550 */
}, /* AES2550 */ { .vid = 0x08ff, .pid = 0x2810, },/* AES2810 */
{ .vid = 0x08ff, .pid = 0x2810,
}, /* AES2810 */
{ .vid = 0, .pid = 0, .driver_data = 0 }, { .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) { static void
FpDeviceClass *dev_class = FP_DEVICE_CLASS(klass); fpi_device_aes2550_class_init (FpiDeviceAes2550Class *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 = "aes2550"; dev_class->id = "aes2550";
dev_class->full_name = "AuthenTec AES2550/AES2810"; dev_class->full_name = "AuthenTec AES2550/AES2810";

View file

@ -27,12 +27,13 @@
#define FRAME_WIDTH 192 #define FRAME_WIDTH 192
#define IMAGE_WIDTH (FRAME_WIDTH + (FRAME_WIDTH / 2)) #define IMAGE_WIDTH (FRAME_WIDTH + (FRAME_WIDTH / 2))
struct _FpiDeviceAes2660 { struct _FpiDeviceAes2660
{
FpiDeviceAesX660 parent; FpiDeviceAesX660 parent;
}; };
G_DECLARE_FINAL_TYPE(FpiDeviceAes2660, fpi_device_aes2660, FPI, G_DECLARE_FINAL_TYPE (FpiDeviceAes2660, fpi_device_aes2660, FPI,
DEVICE_AES2660, FpiDeviceAesX660); DEVICE_AES2660, FpiDeviceAesX660);
G_DEFINE_TYPE(FpiDeviceAes2660, fpi_device_aes2660, FPI_TYPE_DEVICE_AES_X660); G_DEFINE_TYPE (FpiDeviceAes2660, fpi_device_aes2660, FPI_TYPE_DEVICE_AES_X660);
static struct fpi_frame_asmbl_ctx assembling_ctx = { static struct fpi_frame_asmbl_ctx assembling_ctx = {
.frame_width = FRAME_WIDTH, .frame_width = FRAME_WIDTH,
@ -41,7 +42,7 @@ static struct fpi_frame_asmbl_ctx assembling_ctx = {
.get_pixel = aes_get_pixel, .get_pixel = aes_get_pixel,
}; };
static const FpIdEntry id_table [ ] = { static const FpIdEntry id_table[] = {
{ .vid = 0x08ff, .pid = 0x2660, }, { .vid = 0x08ff, .pid = 0x2660, },
{ .vid = 0x08ff, .pid = 0x2680, }, { .vid = 0x08ff, .pid = 0x2680, },
{ .vid = 0x08ff, .pid = 0x2681, }, { .vid = 0x08ff, .pid = 0x2681, },
@ -63,12 +64,16 @@ static const FpIdEntry id_table [ ] = {
{ .vid = 0, .pid = 0, .driver_data = 0 }, { .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) { static void
FpDeviceClass *dev_class = FP_DEVICE_CLASS(klass); fpi_device_aes2660_class_init (FpiDeviceAes2660Class *klass)
FpImageDeviceClass *img_class = FP_IMAGE_DEVICE_CLASS(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); FpiDeviceAesX660Class *aes_class = FPI_DEVICE_AES_X660_CLASS (klass);
dev_class->id = "aes2660"; dev_class->id = "aes2660";
@ -83,10 +88,10 @@ static void fpi_device_aes2660_class_init(FpiDeviceAes2660Class *klass) {
img_class->img_height = -1; img_class->img_height = -1;
aes_class->init_seqs[0] = aes2660_init_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_len[0] = G_N_ELEMENTS (aes2660_init_1);
aes_class->init_seqs[1] = aes2660_init_2; aes_class->init_seqs[1] = aes2660_init_2;
aes_class->init_seqs_len[1] = G_N_ELEMENTS(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 = (unsigned char *) aes2660_start_imaging_cmd;
aes_class->start_imaging_cmd_len = sizeof(aes2660_start_imaging_cmd); aes_class->start_imaging_cmd_len = sizeof (aes2660_start_imaging_cmd);
aes_class->assembling_ctx = &assembling_ctx; aes_class->assembling_ctx = &assembling_ctx;
} }

File diff suppressed because it is too large Load diff

View file

@ -115,25 +115,30 @@ static struct aes_regwrite init_reqs[] = {
{ 0x81, 0x00 }, { 0x81, 0x00 },
}; };
struct _FpiDeviceAes3500 { struct _FpiDeviceAes3500
{
FpiDeviceAes3k parent; FpiDeviceAes3k parent;
}; };
G_DECLARE_FINAL_TYPE(FpiDeviceAes3500, fpi_device_aes3500, FPI, G_DECLARE_FINAL_TYPE (FpiDeviceAes3500, fpi_device_aes3500, FPI,
DEVICE_AES3500, FpiDeviceAes3k); DEVICE_AES3500, FpiDeviceAes3k);
G_DEFINE_TYPE(FpiDeviceAes3500, fpi_device_aes3500, FPI_TYPE_DEVICE_AES3K); G_DEFINE_TYPE (FpiDeviceAes3500, fpi_device_aes3500, FPI_TYPE_DEVICE_AES3K);
static const FpIdEntry id_table [ ] = { static const FpIdEntry id_table[] = {
{ .vid = 0x08ff, .pid = 0x5731 }, { .vid = 0x08ff, .pid = 0x5731 },
{ .vid = 0, .pid = 0, .driver_data = 0 }, { .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) { static void
FpDeviceClass *dev_class = FP_DEVICE_CLASS(klass); fpi_device_aes3500_class_init (FpiDeviceAes3500Class *klass)
FpImageDeviceClass *img_class = FP_IMAGE_DEVICE_CLASS(klass); {
FpDeviceClass *dev_class = FP_DEVICE_CLASS (klass);
FpImageDeviceClass *img_class = FP_IMAGE_DEVICE_CLASS (klass);
FpiDeviceAes3kClass *aes_class = FPI_DEVICE_AES3K_CLASS (klass); FpiDeviceAes3kClass *aes_class = FPI_DEVICE_AES3K_CLASS (klass);
dev_class->id = "aes3500"; dev_class->id = "aes3500";
@ -149,5 +154,5 @@ static void fpi_device_aes3500_class_init(FpiDeviceAes3500Class *klass) {
aes_class->frame_number = FRAME_NUMBER; aes_class->frame_number = FRAME_NUMBER;
aes_class->enlarge_factor = ENLARGE_FACTOR; aes_class->enlarge_factor = ENLARGE_FACTOR;
aes_class->init_reqs = init_reqs; aes_class->init_reqs = init_reqs;
aes_class->init_reqs_len = G_N_ELEMENTS(init_reqs); aes_class->init_reqs_len = G_N_ELEMENTS (init_reqs);
} }

View file

@ -40,7 +40,8 @@
#include "aeslib.h" #include "aeslib.h"
#include "aes3k.h" #include "aes3k.h"
typedef struct { typedef struct
{
FpiUsbTransfer *img_trf; FpiUsbTransfer *img_trf;
gboolean deactivating; gboolean deactivating;
} FpiDeviceAes3kPrivate; } FpiDeviceAes3kPrivate;
@ -49,17 +50,20 @@ typedef struct {
#define EP_IN (1 | FPI_USB_ENDPOINT_IN) #define EP_IN (1 | FPI_USB_ENDPOINT_IN)
#define EP_OUT (2 | FPI_USB_ENDPOINT_OUT) #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, static void
aes3k_assemble_image (unsigned char *input, size_t width, size_t height,
unsigned char *output) unsigned char *output)
{ {
size_t row, column; size_t row, column;
for (column = 0; column < width; column++) { for (column = 0; column < width; column++)
for (row = 0; row < height; row += 2) { {
for (row = 0; row < height; row += 2)
{
output[width * row + column] = (*input & 0x0f) * 17; output[width * row + column] = (*input & 0x0f) * 17;
output[width * (row + 1) + column] = ((*input & 0xf0) >> 4) * 17; output[width * (row + 1) + column] = ((*input & 0xf0) >> 4) * 17;
input++; input++;
@ -67,7 +71,8 @@ static void aes3k_assemble_image(unsigned char *input, size_t width, size_t heig
} }
} }
static void img_cb(FpiUsbTransfer *transfer, FpDevice *device, static void
img_cb (FpiUsbTransfer *transfer, FpDevice *device,
gpointer user_data, GError *error) gpointer user_data, GError *error)
{ {
FpImageDevice *dev = FP_IMAGE_DEVICE (device); FpImageDevice *dev = FP_IMAGE_DEVICE (device);
@ -81,79 +86,86 @@ static void img_cb(FpiUsbTransfer *transfer, FpDevice *device,
priv->img_trf = NULL; priv->img_trf = NULL;
if (error) { if (error)
{
if (g_error_matches (error, if (g_error_matches (error,
G_IO_ERROR, G_IO_ERROR,
G_IO_ERROR_CANCELLED)) { G_IO_ERROR_CANCELLED))
{
/* Deactivation was completed. */ /* Deactivation was completed. */
g_error_free (error); g_error_free (error);
if (priv->deactivating) if (priv->deactivating)
fpi_image_device_deactivate_complete(dev, NULL); fpi_image_device_deactivate_complete (dev, NULL);
return; 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 = fp_image_new (cls->frame_width, cls->frame_width);
tmp->width = cls->frame_width; tmp->width = cls->frame_width;
tmp->height = cls->frame_width; tmp->height = cls->frame_width;
tmp->flags = FPI_IMAGE_COLORS_INVERTED | FPI_IMAGE_V_FLIPPED | FPI_IMAGE_H_FLIPPED; tmp->flags = FPI_IMAGE_COLORS_INVERTED | FPI_IMAGE_V_FLIPPED | FPI_IMAGE_H_FLIPPED;
for (i = 0; i < cls->frame_number; i++) { for (i = 0; i < cls->frame_number; i++)
fp_dbg("frame header byte %02x", *ptr); {
fp_dbg ("frame header byte %02x", *ptr);
ptr++; ptr++;
aes3k_assemble_image(ptr, cls->frame_width, AES3K_FRAME_HEIGHT, tmp->data + (i * cls->frame_width * AES3K_FRAME_HEIGHT)); aes3k_assemble_image (ptr, cls->frame_width, AES3K_FRAME_HEIGHT, tmp->data + (i * cls->frame_width * AES3K_FRAME_HEIGHT));
ptr += cls->frame_size; ptr += cls->frame_size;
} }
/* FIXME: this is an ugly hack to make the image big enough for NBIS /* FIXME: this is an ugly hack to make the image big enough for NBIS
* to process reliably */ * to process reliably */
img = fpi_image_resize(tmp, cls->enlarge_factor, cls->enlarge_factor); img = fpi_image_resize (tmp, cls->enlarge_factor, cls->enlarge_factor);
g_object_unref (tmp); g_object_unref (tmp);
fpi_image_device_image_captured(dev, img); fpi_image_device_image_captured (dev, img);
/* FIXME: rather than assuming finger has gone, we should poll regs until /* FIXME: rather than assuming finger has gone, we should poll regs until
* it really has, then restart the capture */ * it really has, then restart the capture */
fpi_image_device_report_finger_status(dev, FALSE); 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); FpiDeviceAes3k *self = FPI_DEVICE_AES3K (dev);
FpiDeviceAes3kPrivate *priv = fpi_device_aes3k_get_instance_private (self); FpiDeviceAes3kPrivate *priv = fpi_device_aes3k_get_instance_private (self);
FpiDeviceAes3kClass *cls = FPI_DEVICE_AES3K_GET_CLASS (self); FpiDeviceAes3kClass *cls = FPI_DEVICE_AES3K_GET_CLASS (self);
priv->img_trf = fpi_usb_transfer_new (FP_DEVICE (dev)); priv->img_trf = fpi_usb_transfer_new (FP_DEVICE (dev));
fpi_usb_transfer_fill_bulk(priv->img_trf, EP_IN, cls->data_buflen); fpi_usb_transfer_fill_bulk (priv->img_trf, EP_IN, cls->data_buflen);
priv->img_trf->short_is_error = TRUE; priv->img_trf->short_is_error = TRUE;
fpi_usb_transfer_submit(priv->img_trf, 0, fpi_usb_transfer_submit (priv->img_trf, 0,
fpi_device_get_cancellable (FP_DEVICE (dev)), fpi_device_get_cancellable (FP_DEVICE (dev)),
img_cb, NULL); img_cb, NULL);
fpi_usb_transfer_unref(priv->img_trf); 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); fpi_image_device_activate_complete (dev, result);
if (!result) if (!result)
do_capture(dev); do_capture (dev);
} }
static void aes3k_dev_activate(FpImageDevice *dev) static void
aes3k_dev_activate (FpImageDevice *dev)
{ {
FpiDeviceAes3k *self = FPI_DEVICE_AES3K (dev); FpiDeviceAes3k *self = FPI_DEVICE_AES3K (dev);
FpiDeviceAes3kPrivate *priv = fpi_device_aes3k_get_instance_private (self); FpiDeviceAes3kPrivate *priv = fpi_device_aes3k_get_instance_private (self);
FpiDeviceAes3kClass *cls = FPI_DEVICE_AES3K_GET_CLASS (self); FpiDeviceAes3kClass *cls = FPI_DEVICE_AES3K_GET_CLASS (self);
priv->deactivating = FALSE; priv->deactivating = FALSE;
aes_write_regv(dev, cls->init_reqs, cls->init_reqs_len, init_reqs_cb, NULL); 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); FpiDeviceAes3k *self = FPI_DEVICE_AES3K (dev);
FpiDeviceAes3kPrivate *priv = fpi_device_aes3k_get_instance_private (self); FpiDeviceAes3kPrivate *priv = fpi_device_aes3k_get_instance_private (self);
@ -161,37 +173,44 @@ static void aes3k_dev_deactivate(FpImageDevice *dev)
priv->deactivating = TRUE; priv->deactivating = TRUE;
if (priv->img_trf) if (priv->img_trf)
return; return;
fpi_image_device_deactivate_complete(dev, NULL); fpi_image_device_deactivate_complete (dev, NULL);
} }
static void fpi_device_aes3k_init(FpiDeviceAes3k *self) { static void
fpi_device_aes3k_init (FpiDeviceAes3k *self)
{
} }
static void aes3k_dev_init(FpImageDevice *dev) static void
aes3k_dev_init (FpImageDevice *dev)
{ {
GError *error = NULL; GError *error = NULL;
if (!g_usb_device_claim_interface(fpi_device_get_usb_device(FP_DEVICE(dev)), 0, 0, &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); {
fpi_image_device_open_complete (dev, error);
return; return;
} }
fpi_image_device_open_complete(dev, NULL); fpi_image_device_open_complete (dev, NULL);
} }
static void aes3k_dev_deinit(FpImageDevice *dev) static void
aes3k_dev_deinit (FpImageDevice *dev)
{ {
GError *error = NULL; GError *error = NULL;
g_usb_device_release_interface(fpi_device_get_usb_device(FP_DEVICE(dev)), g_usb_device_release_interface (fpi_device_get_usb_device (FP_DEVICE (dev)),
0, 0, &error); 0, 0, &error);
fpi_image_device_close_complete(dev, error); fpi_image_device_close_complete (dev, error);
} }
static void fpi_device_aes3k_class_init(FpiDeviceAes3kClass *klass) { static void
FpDeviceClass *dev_class = FP_DEVICE_CLASS(klass); fpi_device_aes3k_class_init (FpiDeviceAes3kClass *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->type = FP_DEVICE_TYPE_USB; dev_class->type = FP_DEVICE_TYPE_USB;
dev_class->scan_type = FP_SCAN_TYPE_PRESS; dev_class->scan_type = FP_SCAN_TYPE_PRESS;

View file

@ -40,12 +40,13 @@
#define AES3K_FRAME_HEIGHT 16 #define AES3K_FRAME_HEIGHT 16
G_DECLARE_DERIVABLE_TYPE(FpiDeviceAes3k, fpi_device_aes3k, FPI, G_DECLARE_DERIVABLE_TYPE (FpiDeviceAes3k, fpi_device_aes3k, FPI,
DEVICE_AES3K, FpImageDevice) DEVICE_AES3K, FpImageDevice)
#define FPI_TYPE_DEVICE_AES3K (fpi_device_aes3k_get_type ()) #define FPI_TYPE_DEVICE_AES3K (fpi_device_aes3k_get_type ())
struct _FpiDeviceAes3kClass { struct _FpiDeviceAes3kClass
{
FpImageDeviceClass parent; FpImageDeviceClass parent;
gsize frame_width; /* image size = frame_width x frame_width */ gsize frame_width; /* image size = frame_width x frame_width */

View file

@ -112,25 +112,30 @@ static struct aes_regwrite init_reqs[] = {
{ 0x81, 0x00 }, { 0x81, 0x00 },
}; };
struct _FpiDeviceAes4000 { struct _FpiDeviceAes4000
{
FpiDeviceAes3k parent; FpiDeviceAes3k parent;
}; };
G_DECLARE_FINAL_TYPE(FpiDeviceAes4000, fpi_device_aes4000, FPI, G_DECLARE_FINAL_TYPE (FpiDeviceAes4000, fpi_device_aes4000, FPI,
DEVICE_AES4000, FpiDeviceAes3k); DEVICE_AES4000, FpiDeviceAes3k);
G_DEFINE_TYPE(FpiDeviceAes4000, fpi_device_aes4000, FPI_TYPE_DEVICE_AES3K); G_DEFINE_TYPE (FpiDeviceAes4000, fpi_device_aes4000, FPI_TYPE_DEVICE_AES3K);
static const FpIdEntry id_table [ ] = { static const FpIdEntry id_table[] = {
{ .pid = 0x08ff, .vid = 0x5501 }, { .pid = 0x08ff, .vid = 0x5501 },
{ .vid = 0, .pid = 0, .driver_data = 0 }, { .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) { static void
FpDeviceClass *dev_class = FP_DEVICE_CLASS(klass); fpi_device_aes4000_class_init (FpiDeviceAes4000Class *klass)
FpImageDeviceClass *img_class = FP_IMAGE_DEVICE_CLASS(klass); {
FpDeviceClass *dev_class = FP_DEVICE_CLASS (klass);
FpImageDeviceClass *img_class = FP_IMAGE_DEVICE_CLASS (klass);
FpiDeviceAes3kClass *aes_class = FPI_DEVICE_AES3K_CLASS (klass); FpiDeviceAes3kClass *aes_class = FPI_DEVICE_AES3K_CLASS (klass);
dev_class->id = "aes4000"; dev_class->id = "aes4000";
@ -146,5 +151,5 @@ static void fpi_device_aes4000_class_init(FpiDeviceAes4000Class *klass) {
aes_class->frame_number = FRAME_NUMBER; aes_class->frame_number = FRAME_NUMBER;
aes_class->enlarge_factor = ENLARGE_FACTOR; aes_class->enlarge_factor = ENLARGE_FACTOR;
aes_class->init_reqs = init_reqs; aes_class->init_reqs = init_reqs;
aes_class->init_reqs_len = G_N_ELEMENTS(init_reqs); aes_class->init_reqs_len = G_N_ELEMENTS (init_reqs);
} }

View file

@ -34,7 +34,8 @@
#define EP_IN (1 | FPI_USB_ENDPOINT_IN) #define EP_IN (1 | FPI_USB_ENDPOINT_IN)
#define EP_OUT (2 | FPI_USB_ENDPOINT_OUT) #define EP_OUT (2 | FPI_USB_ENDPOINT_OUT)
struct write_regv_data { struct write_regv_data
{
unsigned int num_regs; unsigned int num_regs;
const struct aes_regwrite *regs; const struct aes_regwrite *regs;
unsigned int offset; unsigned int offset;
@ -42,50 +43,58 @@ struct write_regv_data {
void *user_data; 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 /* libusb bulk callback for regv write completion transfer. continues the
* transaction */ * transaction */
static void write_regv_trf_complete(FpiUsbTransfer *transfer, FpDevice *device, static void
write_regv_trf_complete (FpiUsbTransfer *transfer, FpDevice *device,
gpointer user_data, GError *error) gpointer user_data, GError *error)
{ {
struct write_regv_data *wdata = user_data; struct write_regv_data *wdata = user_data;
if (error) { if (error)
wdata->callback(FP_IMAGE_DEVICE (device), error, wdata->user_data); {
g_free(wdata); wdata->callback (FP_IMAGE_DEVICE (device), error, wdata->user_data);
} else { g_free (wdata);
continue_write_regv(FP_IMAGE_DEVICE (device), wdata); }
else
{
continue_write_regv (FP_IMAGE_DEVICE (device), wdata);
} }
} }
/* write from wdata->offset to upper_bound (inclusive) of wdata->regs */ /* 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 offset = wdata->offset;
unsigned int num = upper_bound - offset + 1; unsigned int num = upper_bound - offset + 1;
size_t alloc_size = num * 2; size_t alloc_size = num * 2;
unsigned int i; unsigned int i;
size_t data_offset = 0; size_t data_offset = 0;
FpiUsbTransfer *transfer = fpi_usb_transfer_new(FP_DEVICE (dev)); 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++) { for (i = offset; i < offset + num; i++)
{
const struct aes_regwrite *regwrite = &wdata->regs[i]; const struct aes_regwrite *regwrite = &wdata->regs[i];
transfer->buffer[data_offset++] = regwrite->reg; transfer->buffer[data_offset++] = regwrite->reg;
transfer->buffer[data_offset++] = regwrite->value; transfer->buffer[data_offset++] = regwrite->value;
} }
transfer->short_is_error = TRUE; transfer->short_is_error = TRUE;
fpi_usb_transfer_submit(transfer, BULK_TIMEOUT, NULL, fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
write_regv_trf_complete, wdata); write_regv_trf_complete, wdata);
fpi_usb_transfer_unref (transfer); fpi_usb_transfer_unref (transfer);
} }
/* write the next batch of registers to be written, or if there are no more, /* write the next batch of registers to be written, or if there are no more,
* indicate completion to the caller */ * 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 offset = wdata->offset;
unsigned int regs_remaining; unsigned int regs_remaining;
@ -94,11 +103,13 @@ static void continue_write_regv(FpImageDevice *dev, struct write_regv_data *wdat
int i; int i;
/* skip all zeros and ensure there is still work to do */ /* skip all zeros and ensure there is still work to do */
while (TRUE) { while (TRUE)
if (offset >= wdata->num_regs) { {
fp_dbg("all registers written"); if (offset >= wdata->num_regs)
wdata->callback(dev, 0, wdata->user_data); {
g_free(wdata); fp_dbg ("all registers written");
wdata->callback (dev, 0, wdata->user_data);
g_free (wdata);
return; return;
} }
if (wdata->regs[offset].reg) if (wdata->regs[offset].reg)
@ -108,18 +119,19 @@ static void continue_write_regv(FpImageDevice *dev, struct write_regv_data *wdat
wdata->offset = offset; wdata->offset = offset;
regs_remaining = wdata->num_regs - offset; regs_remaining = wdata->num_regs - offset;
limit = MIN(regs_remaining, MAX_REGWRITES_PER_REQUEST); limit = MIN (regs_remaining, MAX_REGWRITES_PER_REQUEST);
upper_bound = offset + limit - 1; upper_bound = offset + limit - 1;
/* determine if we can write the entire of the regs at once, or if there /* determine if we can write the entire of the regs at once, or if there
* is a zero dividing things up */ * is a zero dividing things up */
for (i = offset; i <= upper_bound; i++) for (i = offset; i <= upper_bound; i++)
if (!wdata->regs[i].reg) { if (!wdata->regs[i].reg)
{
upper_bound = i - 1; upper_bound = i - 1;
break; 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;
} }
@ -127,23 +139,25 @@ static void continue_write_regv(FpImageDevice *dev, struct write_regv_data *wdat
/* write a load of registers to the device, combining multiple writes in a /* 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 * 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. */ * specific groups of writes to be separated by different URBs. */
void aes_write_regv(FpImageDevice *dev, const struct aes_regwrite *regs, void
aes_write_regv (FpImageDevice *dev, const struct aes_regwrite *regs,
unsigned int num_regs, aes_write_regv_cb callback, unsigned int num_regs, aes_write_regv_cb callback,
void *user_data) void *user_data)
{ {
struct write_regv_data *wdata; struct write_regv_data *wdata;
fp_dbg("write %d regs", num_regs); fp_dbg ("write %d regs", num_regs);
wdata = g_malloc(sizeof(*wdata)); wdata = g_malloc (sizeof (*wdata));
wdata->num_regs = num_regs; wdata->num_regs = num_regs;
wdata->regs = regs; wdata->regs = regs;
wdata->offset = 0; wdata->offset = 0;
wdata->callback = callback; wdata->callback = callback;
wdata->user_data = user_data; wdata->user_data = user_data;
continue_write_regv(dev, wdata); continue_write_regv (dev, wdata);
} }
unsigned char aes_get_pixel(struct fpi_frame_asmbl_ctx *ctx, unsigned char
aes_get_pixel (struct fpi_frame_asmbl_ctx *ctx,
struct fpi_frame *frame, struct fpi_frame *frame,
unsigned int x, unsigned int x,
unsigned int y) unsigned int y)

View file

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

View file

@ -27,7 +27,8 @@
#include "aeslib.h" #include "aeslib.h"
#include "aesx660.h" #include "aesx660.h"
typedef struct { typedef struct
{
GByteArray *stripe_packet; GByteArray *stripe_packet;
GSList *strips; GSList *strips;
size_t strips_len; size_t strips_len;
@ -38,10 +39,10 @@ typedef struct {
unsigned int init_seq_idx; unsigned int init_seq_idx;
} FpiDeviceAesX660Private; } FpiDeviceAesX660Private;
G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE(FpiDeviceAesX660, fpi_device_aes_x660, FP_TYPE_IMAGE_DEVICE); G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (FpiDeviceAesX660, fpi_device_aes_x660, FP_TYPE_IMAGE_DEVICE);
static void start_capture(FpImageDevice *dev); static void start_capture (FpImageDevice *dev);
static void complete_deactivation(FpImageDevice *dev); static void complete_deactivation (FpImageDevice *dev);
#define EP_IN (1 | FPI_USB_ENDPOINT_IN) #define EP_IN (1 | FPI_USB_ENDPOINT_IN)
#define EP_OUT (2 | FPI_USB_ENDPOINT_OUT) #define EP_OUT (2 | FPI_USB_ENDPOINT_OUT)
@ -54,84 +55,87 @@ static void complete_deactivation(FpImageDevice *dev);
#define FINGER_DET_DATA_LEN 4 #define FINGER_DET_DATA_LEN 4
static void static void
aesX660_send_cmd_timeout(FpiSsm *ssm, aesX660_send_cmd_timeout (FpiSsm *ssm,
FpDevice *_dev, FpDevice *_dev,
const unsigned char *cmd, const unsigned char *cmd,
size_t cmd_len, size_t cmd_len,
FpiUsbTransferCallback callback, FpiUsbTransferCallback callback,
int timeout) int timeout)
{ {
FpiUsbTransfer *transfer = fpi_usb_transfer_new(_dev); FpiUsbTransfer *transfer = fpi_usb_transfer_new (_dev);
fpi_usb_transfer_fill_bulk_full(transfer, EP_OUT, (unsigned char *)cmd, fpi_usb_transfer_fill_bulk_full (transfer, EP_OUT, (unsigned char *) cmd,
cmd_len, NULL); cmd_len, NULL);
transfer->ssm = ssm; transfer->ssm = ssm;
fpi_usb_transfer_submit(transfer, timeout, NULL, callback, NULL); fpi_usb_transfer_submit (transfer, timeout, NULL, callback, NULL);
fpi_usb_transfer_unref(transfer); fpi_usb_transfer_unref (transfer);
} }
static void static void
aesX660_send_cmd(FpiSsm *ssm, aesX660_send_cmd (FpiSsm *ssm,
FpDevice *dev, FpDevice *dev,
const unsigned char *cmd, const unsigned char *cmd,
size_t cmd_len, size_t cmd_len,
FpiUsbTransferCallback callback) FpiUsbTransferCallback callback)
{ {
return aesX660_send_cmd_timeout(ssm, dev, cmd, cmd_len, callback, BULK_TIMEOUT); return aesX660_send_cmd_timeout (ssm, dev, cmd, cmd_len, callback, BULK_TIMEOUT);
} }
static void static void
aesX660_read_response(FpiSsm *ssm, aesX660_read_response (FpiSsm *ssm,
FpDevice *_dev, FpDevice *_dev,
gboolean short_is_error, gboolean short_is_error,
gboolean cancellable, gboolean cancellable,
size_t buf_len, size_t buf_len,
FpiUsbTransferCallback callback) FpiUsbTransferCallback callback)
{ {
FpiUsbTransfer *transfer = fpi_usb_transfer_new(_dev); FpiUsbTransfer *transfer = fpi_usb_transfer_new (_dev);
unsigned char *data; unsigned char *data;
GCancellable *cancel = NULL; GCancellable *cancel = NULL;
if (cancellable) if (cancellable)
cancel = fpi_device_get_cancellable (_dev); cancel = fpi_device_get_cancellable (_dev);
data = g_malloc(buf_len); data = g_malloc (buf_len);
fpi_usb_transfer_fill_bulk_full(transfer, EP_IN, data, buf_len, NULL); fpi_usb_transfer_fill_bulk_full (transfer, EP_IN, data, buf_len, NULL);
transfer->ssm = ssm; transfer->ssm = ssm;
transfer->short_is_error = short_is_error; transfer->short_is_error = short_is_error;
fpi_usb_transfer_submit(transfer, BULK_TIMEOUT, cancel, callback, NULL); fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, cancel, callback, NULL);
fpi_usb_transfer_unref(transfer); fpi_usb_transfer_unref (transfer);
} }
static void aesX660_send_cmd_cb(FpiUsbTransfer *transfer, FpDevice *device, static void
aesX660_send_cmd_cb (FpiUsbTransfer *transfer, FpDevice *device,
gpointer user_data, GError *error) gpointer user_data, GError *error)
{ {
if (!error) { if (!error)
fpi_ssm_next_state(transfer->ssm); fpi_ssm_next_state (transfer->ssm);
} else { else
fpi_ssm_mark_failed(transfer->ssm, error); fpi_ssm_mark_failed (transfer->ssm, error);
}
} }
static void aesX660_read_calibrate_data_cb(FpiUsbTransfer *transfer, static void
aesX660_read_calibrate_data_cb (FpiUsbTransfer *transfer,
FpDevice *device, FpDevice *device,
gpointer user_data, GError *error) gpointer user_data, GError *error)
{ {
unsigned char *data = transfer->buffer; unsigned char *data = transfer->buffer;
if (error) { if (error)
fpi_ssm_mark_failed(transfer->ssm, error); {
fpi_ssm_mark_failed (transfer->ssm, error);
return; return;
} }
/* Calibrate response was read correctly? */ /* Calibrate response was read correctly? */
if (data[AESX660_RESPONSE_TYPE_OFFSET] != AESX660_CALIBRATE_RESPONSE) { if (data[AESX660_RESPONSE_TYPE_OFFSET] != AESX660_CALIBRATE_RESPONSE)
fp_dbg("Bogus calibrate response: %.2x\n", data[0]); {
fpi_ssm_mark_failed(transfer->ssm, fp_dbg ("Bogus calibrate response: %.2x\n", data[0]);
fpi_ssm_mark_failed (transfer->ssm,
fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO, fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
"Bogus calibrate response")); "Bogus calibrate response"));
return; return;
} }
fpi_ssm_next_state(transfer->ssm); fpi_ssm_next_state (transfer->ssm);
} }
/****** FINGER PRESENCE DETECTION ******/ /****** FINGER PRESENCE DETECTION ******/
@ -144,7 +148,8 @@ enum finger_det_states {
FINGER_DET_NUM_STATES, FINGER_DET_NUM_STATES,
}; };
static void finger_det_read_fd_data_cb(FpiUsbTransfer *transfer, static void
finger_det_read_fd_data_cb (FpiUsbTransfer *transfer,
FpDevice *device, gpointer user_data, FpDevice *device, gpointer user_data,
GError *error) GError *error)
{ {
@ -152,104 +157,123 @@ static void finger_det_read_fd_data_cb(FpiUsbTransfer *transfer,
FpiDeviceAesX660Private *priv = fpi_device_aes_x660_get_instance_private (self); FpiDeviceAesX660Private *priv = fpi_device_aes_x660_get_instance_private (self);
unsigned char *data = transfer->buffer; unsigned char *data = transfer->buffer;
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
fpi_ssm_next_state(transfer->ssm); {
fpi_ssm_next_state (transfer->ssm);
return; return;
} }
if (error) { if (error)
fp_dbg("Failed to read FD data\n"); {
fpi_ssm_mark_failed(transfer->ssm, error); fp_dbg ("Failed to read FD data\n");
fpi_ssm_mark_failed (transfer->ssm, error);
return; return;
} }
if (data[AESX660_RESPONSE_TYPE_OFFSET] != AESX660_FINGER_DET_RESPONSE) { if (data[AESX660_RESPONSE_TYPE_OFFSET] != AESX660_FINGER_DET_RESPONSE)
fp_dbg("Bogus FD response: %.2x\n", data[0]); {
fpi_ssm_mark_failed(transfer->ssm, fp_dbg ("Bogus FD response: %.2x\n", data[0]);
fpi_ssm_mark_failed (transfer->ssm,
fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO, fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
"Bogus FD response")); "Bogus FD response"));
return; return;
} }
if (data[AESX660_FINGER_PRESENT_OFFSET] == AESX660_FINGER_PRESENT || priv->deactivating) { if (data[AESX660_FINGER_PRESENT_OFFSET] == AESX660_FINGER_PRESENT || priv->deactivating)
{
/* Finger present or we're deactivating... */ /* Finger present or we're deactivating... */
fpi_ssm_next_state(transfer->ssm); fpi_ssm_next_state (transfer->ssm);
} else { }
fp_dbg("Wait for finger returned %.2x as result\n", else
{
fp_dbg ("Wait for finger returned %.2x as result\n",
data[AESX660_FINGER_PRESENT_OFFSET]); data[AESX660_FINGER_PRESENT_OFFSET]);
fpi_ssm_jump_to_state(transfer->ssm, FINGER_DET_SEND_FD_CMD); fpi_ssm_jump_to_state (transfer->ssm, FINGER_DET_SEND_FD_CMD);
} }
} }
static void finger_det_set_idle_cmd_cb(FpiUsbTransfer *transfer, static void
finger_det_set_idle_cmd_cb (FpiUsbTransfer *transfer,
FpDevice *device, gpointer user_data, FpDevice *device, gpointer user_data,
GError *error) GError *error)
{ {
if (!error) { if (!error)
fpi_ssm_mark_completed(transfer->ssm); fpi_ssm_mark_completed (transfer->ssm);
} else { else
fpi_ssm_mark_failed(transfer->ssm, error); fpi_ssm_mark_failed (transfer->ssm, error);
}
} }
static void finger_det_sm_complete(FpiSsm *ssm, FpDevice *_dev, static void
finger_det_sm_complete (FpiSsm *ssm, FpDevice *_dev,
void *user_data, GError *error) void *user_data, GError *error)
{ {
FpImageDevice *dev = FP_IMAGE_DEVICE (_dev); FpImageDevice *dev = FP_IMAGE_DEVICE (_dev);
FpiDeviceAesX660 *self = FPI_DEVICE_AES_X660 (_dev); FpiDeviceAesX660 *self = FPI_DEVICE_AES_X660 (_dev);
FpiDeviceAesX660Private *priv = fpi_device_aes_x660_get_instance_private (self); FpiDeviceAesX660Private *priv = fpi_device_aes_x660_get_instance_private (self);
fp_dbg("Finger detection completed"); fp_dbg ("Finger detection completed");
fpi_image_device_report_finger_status(dev, TRUE); fpi_image_device_report_finger_status (dev, TRUE);
fpi_ssm_free(ssm); fpi_ssm_free (ssm);
if (priv->deactivating) { if (priv->deactivating)
complete_deactivation(dev); {
complete_deactivation (dev);
if (error) if (error)
g_error_free (error); g_error_free (error);
} else if (error) { }
fpi_image_device_session_error(dev, error); else if (error)
} else { {
fpi_image_device_report_finger_status(dev, TRUE); fpi_image_device_session_error (dev, error);
start_capture(dev); }
else
{
fpi_image_device_report_finger_status (dev, TRUE);
start_capture (dev);
} }
} }
static void finger_det_run_state(FpiSsm *ssm, FpDevice *dev, void *user_data) static void
finger_det_run_state (FpiSsm *ssm, FpDevice *dev, void *user_data)
{ {
switch (fpi_ssm_get_cur_state(ssm)) { switch (fpi_ssm_get_cur_state (ssm))
{
case FINGER_DET_SEND_LED_CMD: case FINGER_DET_SEND_LED_CMD:
aesX660_send_cmd(ssm, dev, led_blink_cmd, sizeof(led_blink_cmd), aesX660_send_cmd (ssm, dev, led_blink_cmd, sizeof (led_blink_cmd),
aesX660_send_cmd_cb); aesX660_send_cmd_cb);
break; break;
case FINGER_DET_SEND_FD_CMD: case FINGER_DET_SEND_FD_CMD:
aesX660_send_cmd_timeout(ssm, dev, wait_for_finger_cmd, sizeof(wait_for_finger_cmd), aesX660_send_cmd_timeout (ssm, dev, wait_for_finger_cmd, sizeof (wait_for_finger_cmd),
aesX660_send_cmd_cb, 0); aesX660_send_cmd_cb, 0);
break; break;
case FINGER_DET_READ_FD_DATA: case FINGER_DET_READ_FD_DATA:
aesX660_read_response(ssm, dev, TRUE, TRUE, FINGER_DET_DATA_LEN, finger_det_read_fd_data_cb); aesX660_read_response (ssm, dev, TRUE, TRUE, FINGER_DET_DATA_LEN, finger_det_read_fd_data_cb);
break; break;
case FINGER_DET_SET_IDLE: case FINGER_DET_SET_IDLE:
aesX660_send_cmd(ssm, dev, set_idle_cmd, sizeof(set_idle_cmd), aesX660_send_cmd (ssm, dev, set_idle_cmd, sizeof (set_idle_cmd),
finger_det_set_idle_cmd_cb); finger_det_set_idle_cmd_cb);
break; break;
} }
} }
static void start_finger_detection(FpImageDevice *dev) static void
start_finger_detection (FpImageDevice *dev)
{ {
FpiDeviceAesX660 *self = FPI_DEVICE_AES_X660 (dev); FpiDeviceAesX660 *self = FPI_DEVICE_AES_X660 (dev);
FpiDeviceAesX660Private *priv = fpi_device_aes_x660_get_instance_private (self); FpiDeviceAesX660Private *priv = fpi_device_aes_x660_get_instance_private (self);
FpiSsm *ssm; FpiSsm *ssm;
if (priv->deactivating) { if (priv->deactivating)
complete_deactivation(dev); {
complete_deactivation (dev);
return; return;
} }
ssm = fpi_ssm_new(FP_DEVICE(dev), finger_det_run_state, ssm = fpi_ssm_new (FP_DEVICE (dev), finger_det_run_state,
FINGER_DET_NUM_STATES, dev); FINGER_DET_NUM_STATES, dev);
fpi_ssm_start(ssm, finger_det_sm_complete); fpi_ssm_start (ssm, finger_det_sm_complete);
} }
/****** CAPTURE ******/ /****** CAPTURE ******/
@ -263,7 +287,8 @@ enum capture_states {
}; };
/* Returns number of processed bytes */ /* Returns number of processed bytes */
static int process_stripe_data(FpiSsm *ssm, FpiDeviceAesX660 *self, static int
process_stripe_data (FpiSsm *ssm, FpiDeviceAesX660 *self,
unsigned char *data, gsize length) unsigned char *data, gsize length)
{ {
FpiDeviceAesX660Private *priv = fpi_device_aes_x660_get_instance_private (self); FpiDeviceAesX660Private *priv = fpi_device_aes_x660_get_instance_private (self);
@ -271,36 +296,39 @@ static int process_stripe_data(FpiSsm *ssm, FpiDeviceAesX660 *self,
struct fpi_frame *stripe; struct fpi_frame *stripe;
unsigned char *stripdata; unsigned char *stripdata;
if (length < AESX660_IMAGE_OFFSET + cls->assembling_ctx->frame_width * FRAME_HEIGHT / 2) { if (length < AESX660_IMAGE_OFFSET + cls->assembling_ctx->frame_width * FRAME_HEIGHT / 2)
{
fp_warn ("Received stripe data is too short, got %zi expected %i bytes!", fp_warn ("Received stripe data is too short, got %zi expected %i bytes!",
length, length,
AESX660_IMAGE_OFFSET + cls->assembling_ctx->frame_width * FRAME_HEIGHT / 2); AESX660_IMAGE_OFFSET + cls->assembling_ctx->frame_width * FRAME_HEIGHT / 2);
return 0; return 0;
} }
stripe = g_malloc(cls->assembling_ctx->frame_width * FRAME_HEIGHT / 2 + sizeof(struct fpi_frame)); /* 4 bpp */ stripe = g_malloc (cls->assembling_ctx->frame_width * FRAME_HEIGHT / 2 + sizeof (struct fpi_frame)); /* 4 bpp */
stripdata = stripe->data; stripdata = stripe->data;
fp_dbg("Processing frame %.2x %.2x", data[AESX660_IMAGE_OK_OFFSET], fp_dbg ("Processing frame %.2x %.2x", data[AESX660_IMAGE_OK_OFFSET],
data[AESX660_LAST_FRAME_OFFSET]); data[AESX660_LAST_FRAME_OFFSET]);
stripe->delta_x = (int8_t)data[AESX660_FRAME_DELTA_X_OFFSET]; stripe->delta_x = (int8_t) data[AESX660_FRAME_DELTA_X_OFFSET];
stripe->delta_y = -(int8_t)data[AESX660_FRAME_DELTA_Y_OFFSET]; stripe->delta_y = -(int8_t) data[AESX660_FRAME_DELTA_Y_OFFSET];
fp_dbg("Offset to previous frame: %d %d", stripe->delta_x, stripe->delta_y); fp_dbg ("Offset to previous frame: %d %d", stripe->delta_x, stripe->delta_y);
if (data[AESX660_IMAGE_OK_OFFSET] == AESX660_IMAGE_OK) { if (data[AESX660_IMAGE_OK_OFFSET] == AESX660_IMAGE_OK)
memcpy(stripdata, data + AESX660_IMAGE_OFFSET, cls->assembling_ctx->frame_width * FRAME_HEIGHT / 2); {
memcpy (stripdata, data + AESX660_IMAGE_OFFSET, cls->assembling_ctx->frame_width * FRAME_HEIGHT / 2);
priv->strips = g_slist_prepend(priv->strips, stripe); priv->strips = g_slist_prepend (priv->strips, stripe);
priv->strips_len++; priv->strips_len++;
return (data[AESX660_LAST_FRAME_OFFSET] & AESX660_LAST_FRAME_BIT); return data[AESX660_LAST_FRAME_OFFSET] & AESX660_LAST_FRAME_BIT;
} }
g_free(stripe); g_free (stripe);
return 0; return 0;
} }
static void capture_set_idle_cmd_cb(FpiUsbTransfer *transfer, FpDevice *device, static void
capture_set_idle_cmd_cb (FpiUsbTransfer *transfer, FpDevice *device,
gpointer user_data, GError *error) gpointer user_data, GError *error)
{ {
FpImageDevice *dev = FP_IMAGE_DEVICE (device); FpImageDevice *dev = FP_IMAGE_DEVICE (device);
@ -308,24 +336,28 @@ static void capture_set_idle_cmd_cb(FpiUsbTransfer *transfer, FpDevice *device,
FpiDeviceAesX660Private *priv = fpi_device_aes_x660_get_instance_private (self); FpiDeviceAesX660Private *priv = fpi_device_aes_x660_get_instance_private (self);
FpiDeviceAesX660Class *cls = FPI_DEVICE_AES_X660_GET_CLASS (self); FpiDeviceAesX660Class *cls = FPI_DEVICE_AES_X660_GET_CLASS (self);
if (!error) { if (!error)
{
FpImage *img; FpImage *img;
priv->strips = g_slist_reverse(priv->strips); priv->strips = g_slist_reverse (priv->strips);
img = fpi_assemble_frames(cls->assembling_ctx, priv->strips); img = fpi_assemble_frames (cls->assembling_ctx, priv->strips);
g_slist_foreach(priv->strips, (GFunc) g_free, NULL); g_slist_foreach (priv->strips, (GFunc) g_free, NULL);
g_slist_free(priv->strips); g_slist_free (priv->strips);
priv->strips = NULL; priv->strips = NULL;
priv->strips_len = 0; priv->strips_len = 0;
fpi_image_device_image_captured(dev, img); fpi_image_device_image_captured (dev, img);
fpi_image_device_report_finger_status(dev, FALSE); fpi_image_device_report_finger_status (dev, FALSE);
fpi_ssm_mark_completed(transfer->ssm); fpi_ssm_mark_completed (transfer->ssm);
} else { }
fpi_ssm_mark_failed(transfer->ssm, error); else
{
fpi_ssm_mark_failed (transfer->ssm, error);
} }
} }
static void capture_read_stripe_data_cb(FpiUsbTransfer *transfer, static void
capture_read_stripe_data_cb (FpiUsbTransfer *transfer,
FpDevice *device, gpointer user_data, FpDevice *device, gpointer user_data,
GError *error) GError *error)
{ {
@ -335,14 +367,16 @@ static void capture_read_stripe_data_cb(FpiUsbTransfer *transfer,
int finger_missing = 0; int finger_missing = 0;
size_t actual_length = transfer->actual_length; size_t actual_length = transfer->actual_length;
if (error) { if (error)
{
g_byte_array_set_size (priv->stripe_packet, 0); g_byte_array_set_size (priv->stripe_packet, 0);
fpi_ssm_mark_failed(transfer->ssm, error); fpi_ssm_mark_failed (transfer->ssm, error);
return; return;
} }
fp_dbg("Got %lu bytes of data", actual_length); fp_dbg ("Got %lu bytes of data", actual_length);
while (actual_length) { while (actual_length)
{
gssize payload_length; gssize payload_length;
gssize still_needed_len; gssize still_needed_len;
gssize copy_len; gssize copy_len;
@ -359,7 +393,7 @@ static void capture_read_stripe_data_cb(FpiUsbTransfer *transfer,
payload_length = priv->stripe_packet->data[AESX660_RESPONSE_SIZE_LSB_OFFSET] + payload_length = priv->stripe_packet->data[AESX660_RESPONSE_SIZE_LSB_OFFSET] +
(priv->stripe_packet->data[AESX660_RESPONSE_SIZE_MSB_OFFSET] << 8); (priv->stripe_packet->data[AESX660_RESPONSE_SIZE_MSB_OFFSET] << 8);
fp_dbg("Got frame, type %.2x payload of size %.4lx", fp_dbg ("Got frame, type %.2x payload of size %.4lx",
priv->stripe_packet->data[AESX660_RESPONSE_TYPE_OFFSET], priv->stripe_packet->data[AESX660_RESPONSE_TYPE_OFFSET],
payload_length); payload_length);
@ -373,7 +407,7 @@ static void capture_read_stripe_data_cb(FpiUsbTransfer *transfer,
if (priv->stripe_packet->len < payload_length + AESX660_HEADER_SIZE) if (priv->stripe_packet->len < payload_length + AESX660_HEADER_SIZE)
break; break;
finger_missing |= process_stripe_data(transfer->ssm, finger_missing |= process_stripe_data (transfer->ssm,
self, self,
priv->stripe_packet->data, priv->stripe_packet->data,
priv->stripe_packet->len); priv->stripe_packet->len);
@ -381,79 +415,91 @@ static void capture_read_stripe_data_cb(FpiUsbTransfer *transfer,
g_byte_array_set_size (priv->stripe_packet, 0); g_byte_array_set_size (priv->stripe_packet, 0);
} }
fp_dbg("finger %s\n", finger_missing ? "missing" : "present"); fp_dbg ("finger %s\n", finger_missing ? "missing" : "present");
if (finger_missing) { if (finger_missing)
fpi_ssm_next_state(transfer->ssm); fpi_ssm_next_state (transfer->ssm);
} else { else
fpi_ssm_jump_to_state(transfer->ssm, CAPTURE_READ_STRIPE_DATA); fpi_ssm_jump_to_state (transfer->ssm, CAPTURE_READ_STRIPE_DATA);
}
} }
static void capture_run_state(FpiSsm *ssm, FpDevice *_dev, void *user_data) static void
capture_run_state (FpiSsm *ssm, FpDevice *_dev, void *user_data)
{ {
FpiDeviceAesX660 *self = FPI_DEVICE_AES_X660 (_dev); FpiDeviceAesX660 *self = FPI_DEVICE_AES_X660 (_dev);
FpiDeviceAesX660Private *priv = fpi_device_aes_x660_get_instance_private (self); FpiDeviceAesX660Private *priv = fpi_device_aes_x660_get_instance_private (self);
FpiDeviceAesX660Class *cls = FPI_DEVICE_AES_X660_GET_CLASS (self); FpiDeviceAesX660Class *cls = FPI_DEVICE_AES_X660_GET_CLASS (self);
switch (fpi_ssm_get_cur_state(ssm)) { switch (fpi_ssm_get_cur_state (ssm))
{
case CAPTURE_SEND_LED_CMD: case CAPTURE_SEND_LED_CMD:
aesX660_send_cmd(ssm, _dev, led_solid_cmd, sizeof(led_solid_cmd), aesX660_send_cmd (ssm, _dev, led_solid_cmd, sizeof (led_solid_cmd),
aesX660_send_cmd_cb); aesX660_send_cmd_cb);
break; break;
case CAPTURE_SEND_CAPTURE_CMD: case CAPTURE_SEND_CAPTURE_CMD:
g_byte_array_set_size (priv->stripe_packet, 0); g_byte_array_set_size (priv->stripe_packet, 0);
aesX660_send_cmd(ssm, _dev, cls->start_imaging_cmd, aesX660_send_cmd (ssm, _dev, cls->start_imaging_cmd,
cls->start_imaging_cmd_len, cls->start_imaging_cmd_len,
aesX660_send_cmd_cb); aesX660_send_cmd_cb);
break; break;
case CAPTURE_READ_STRIPE_DATA: case CAPTURE_READ_STRIPE_DATA:
aesX660_read_response(ssm, _dev, FALSE, FALSE, AESX660_BULK_TRANSFER_SIZE, aesX660_read_response (ssm, _dev, FALSE, FALSE, AESX660_BULK_TRANSFER_SIZE,
capture_read_stripe_data_cb); capture_read_stripe_data_cb);
break; break;
case CAPTURE_SET_IDLE: case CAPTURE_SET_IDLE:
fp_dbg("Got %lu frames\n", priv->strips_len); fp_dbg ("Got %lu frames\n", priv->strips_len);
aesX660_send_cmd(ssm, _dev, set_idle_cmd, sizeof(set_idle_cmd), aesX660_send_cmd (ssm, _dev, set_idle_cmd, sizeof (set_idle_cmd),
capture_set_idle_cmd_cb); capture_set_idle_cmd_cb);
break; break;
} }
} }
static void capture_sm_complete(FpiSsm *ssm, FpDevice *device, void *user_data, static void
capture_sm_complete (FpiSsm *ssm, FpDevice *device, void *user_data,
GError *error) GError *error)
{ {
FpiDeviceAesX660 *self = FPI_DEVICE_AES_X660 (device); FpiDeviceAesX660 *self = FPI_DEVICE_AES_X660 (device);
FpiDeviceAesX660Private *priv = fpi_device_aes_x660_get_instance_private (self); FpiDeviceAesX660Private *priv = fpi_device_aes_x660_get_instance_private (self);
fp_dbg("Capture completed"); fp_dbg ("Capture completed");
fpi_ssm_free(ssm); fpi_ssm_free (ssm);
if (priv->deactivating) { if (priv->deactivating)
complete_deactivation(FP_IMAGE_DEVICE (device)); {
complete_deactivation (FP_IMAGE_DEVICE (device));
if (error) if (error)
g_error_free (error); g_error_free (error);
} else if (error) { }
else if (error)
{
fpi_image_device_session_error (FP_IMAGE_DEVICE (device), error); fpi_image_device_session_error (FP_IMAGE_DEVICE (device), error);
} else { }
start_finger_detection(FP_IMAGE_DEVICE (device)); else
{
start_finger_detection (FP_IMAGE_DEVICE (device));
} }
} }
static void start_capture(FpImageDevice *dev) static void
start_capture (FpImageDevice *dev)
{ {
FpiDeviceAesX660 *self = FPI_DEVICE_AES_X660 (dev); FpiDeviceAesX660 *self = FPI_DEVICE_AES_X660 (dev);
FpiDeviceAesX660Private *priv = fpi_device_aes_x660_get_instance_private (self); FpiDeviceAesX660Private *priv = fpi_device_aes_x660_get_instance_private (self);
FpiSsm *ssm; FpiSsm *ssm;
if (priv->deactivating) { if (priv->deactivating)
complete_deactivation(dev); {
complete_deactivation (dev);
return; return;
} }
ssm = fpi_ssm_new(FP_DEVICE(dev), capture_run_state, ssm = fpi_ssm_new (FP_DEVICE (dev), capture_run_state,
CAPTURE_NUM_STATES, dev); CAPTURE_NUM_STATES, dev);
G_DEBUG_HERE(); G_DEBUG_HERE ();
fpi_ssm_start(ssm, capture_sm_complete); fpi_ssm_start (ssm, capture_sm_complete);
} }
/****** INITIALIZATION/DEINITIALIZATION ******/ /****** INITIALIZATION/DEINITIALIZATION ******/
@ -469,7 +515,8 @@ enum activate_states {
ACTIVATE_NUM_STATES, ACTIVATE_NUM_STATES,
}; };
static void activate_read_id_cb(FpiUsbTransfer *transfer, FpDevice *device, static void
activate_read_id_cb (FpiUsbTransfer *transfer, FpDevice *device,
gpointer user_data, GError *error) gpointer user_data, GError *error)
{ {
FpiDeviceAesX660 *self = FPI_DEVICE_AES_X660 (device); FpiDeviceAesX660 *self = FPI_DEVICE_AES_X660 (device);
@ -477,146 +524,169 @@ static void activate_read_id_cb(FpiUsbTransfer *transfer, FpDevice *device,
FpiDeviceAesX660Class *cls = FPI_DEVICE_AES_X660_GET_CLASS (self); FpiDeviceAesX660Class *cls = FPI_DEVICE_AES_X660_GET_CLASS (self);
unsigned char *data = transfer->buffer; unsigned char *data = transfer->buffer;
if (error) { if (error)
fp_dbg("read_id cmd failed\n"); {
fpi_ssm_mark_failed(transfer->ssm, error); fp_dbg ("read_id cmd failed\n");
fpi_ssm_mark_failed (transfer->ssm, error);
return; return;
} }
/* ID was read correctly */ /* ID was read correctly */
if (data[0] == 0x07) { if (data[0] == 0x07)
fp_dbg("Sensor device id: %.2x%2x, bcdDevice: %.2x.%.2x, init status: %.2x\n", {
fp_dbg ("Sensor device id: %.2x%2x, bcdDevice: %.2x.%.2x, init status: %.2x\n",
data[4], data[3], data[5], data[6], data[7]); data[4], data[3], data[5], data[6], data[7]);
} else { }
fp_dbg("Bogus read ID response: %.2x\n", data[AESX660_RESPONSE_TYPE_OFFSET]); else
fpi_ssm_mark_failed(transfer->ssm, {
fp_dbg ("Bogus read ID response: %.2x\n", data[AESX660_RESPONSE_TYPE_OFFSET]);
fpi_ssm_mark_failed (transfer->ssm,
fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO, fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
"Bogus read ID response")); "Bogus read ID response"));
return; return;
} }
switch (priv->init_seq_idx) { switch (priv->init_seq_idx)
{
case 0: case 0:
priv->init_seq = cls->init_seqs[0]; priv->init_seq = cls->init_seqs[0];
priv->init_seq_len = cls->init_seqs_len[0]; priv->init_seq_len = cls->init_seqs_len[0];
priv->init_seq_idx = 1; priv->init_seq_idx = 1;
priv->init_cmd_idx = 0; priv->init_cmd_idx = 0;
/* Do calibration only after 1st init sequence */ /* Do calibration only after 1st init sequence */
fpi_ssm_jump_to_state(transfer->ssm, ACTIVATE_SEND_INIT_CMD); fpi_ssm_jump_to_state (transfer->ssm, ACTIVATE_SEND_INIT_CMD);
break; break;
case 1: case 1:
priv->init_seq = cls->init_seqs[1]; priv->init_seq = cls->init_seqs[1];
priv->init_seq_len = cls->init_seqs_len[1]; priv->init_seq_len = cls->init_seqs_len[1];
priv->init_seq_idx = 2; priv->init_seq_idx = 2;
priv->init_cmd_idx = 0; priv->init_cmd_idx = 0;
fpi_ssm_next_state(transfer->ssm); fpi_ssm_next_state (transfer->ssm);
break; break;
default: default:
fp_dbg("Failed to init device! init status: %.2x\n", data[7]); fp_dbg ("Failed to init device! init status: %.2x\n", data[7]);
fpi_ssm_mark_failed(transfer->ssm, fpi_ssm_mark_failed (transfer->ssm,
fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO, fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
"Failed to init device")); "Failed to init device"));
break; break;
} }
} }
static void activate_read_init_cb(FpiUsbTransfer *transfer, FpDevice *device, static void
activate_read_init_cb (FpiUsbTransfer *transfer, FpDevice *device,
gpointer user_data, GError *error) gpointer user_data, GError *error)
{ {
FpiDeviceAesX660 *self = FPI_DEVICE_AES_X660 (device); FpiDeviceAesX660 *self = FPI_DEVICE_AES_X660 (device);
FpiDeviceAesX660Private *priv = fpi_device_aes_x660_get_instance_private (self); FpiDeviceAesX660Private *priv = fpi_device_aes_x660_get_instance_private (self);
unsigned char *data = transfer->buffer; unsigned char *data = transfer->buffer;
fp_dbg("read_init_cb\n"); fp_dbg ("read_init_cb\n");
if (error) { if (error)
fp_dbg("read_init transfer status: %s, actual_len: %d\n", error->message, {
(gint)transfer->actual_length); fp_dbg ("read_init transfer status: %s, actual_len: %d\n", error->message,
fpi_ssm_mark_failed(transfer->ssm, error); (gint) transfer->actual_length);
fpi_ssm_mark_failed (transfer->ssm, error);
return; return;
} }
/* ID was read correctly */ /* ID was read correctly */
if (data[0] != 0x42 || data[3] != 0x01) { if (data[0] != 0x42 || data[3] != 0x01)
fp_dbg("Bogus read init response: %.2x %.2x\n", data[0], {
fp_dbg ("Bogus read init response: %.2x %.2x\n", data[0],
data[3]); data[3]);
fpi_ssm_mark_failed(transfer->ssm, fpi_ssm_mark_failed (transfer->ssm,
fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO, fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
"Bogus read init response")); "Bogus read init response"));
return; return;
} }
priv->init_cmd_idx++; priv->init_cmd_idx++;
if (priv->init_cmd_idx == priv->init_seq_len) { if (priv->init_cmd_idx == priv->init_seq_len)
{
if (priv->init_seq_idx < 2) if (priv->init_seq_idx < 2)
fpi_ssm_jump_to_state(transfer->ssm, fpi_ssm_jump_to_state (transfer->ssm,
ACTIVATE_SEND_READ_ID_CMD); ACTIVATE_SEND_READ_ID_CMD);
else else
fpi_ssm_mark_completed(transfer->ssm); fpi_ssm_mark_completed (transfer->ssm);
return; return;
} }
fpi_ssm_jump_to_state(transfer->ssm, ACTIVATE_SEND_INIT_CMD); fpi_ssm_jump_to_state (transfer->ssm, ACTIVATE_SEND_INIT_CMD);
} }
static void activate_run_state(FpiSsm *ssm, FpDevice *_dev, void *user_data) static void
activate_run_state (FpiSsm *ssm, FpDevice *_dev, void *user_data)
{ {
FpiDeviceAesX660 *self = FPI_DEVICE_AES_X660 (_dev); FpiDeviceAesX660 *self = FPI_DEVICE_AES_X660 (_dev);
FpiDeviceAesX660Private *priv = fpi_device_aes_x660_get_instance_private (self); FpiDeviceAesX660Private *priv = fpi_device_aes_x660_get_instance_private (self);
switch (fpi_ssm_get_cur_state(ssm)) { switch (fpi_ssm_get_cur_state (ssm))
{
case ACTIVATE_SET_IDLE: case ACTIVATE_SET_IDLE:
priv->init_seq_idx = 0; priv->init_seq_idx = 0;
fp_dbg("Activate: set idle\n"); fp_dbg ("Activate: set idle\n");
aesX660_send_cmd(ssm, _dev, set_idle_cmd, sizeof(set_idle_cmd), aesX660_send_cmd (ssm, _dev, set_idle_cmd, sizeof (set_idle_cmd),
aesX660_send_cmd_cb); aesX660_send_cmd_cb);
break; break;
case ACTIVATE_SEND_READ_ID_CMD: case ACTIVATE_SEND_READ_ID_CMD:
fp_dbg("Activate: read ID\n"); fp_dbg ("Activate: read ID\n");
aesX660_send_cmd(ssm, _dev, read_id_cmd, sizeof(read_id_cmd), aesX660_send_cmd (ssm, _dev, read_id_cmd, sizeof (read_id_cmd),
aesX660_send_cmd_cb); aesX660_send_cmd_cb);
break; break;
case ACTIVATE_READ_ID: case ACTIVATE_READ_ID:
aesX660_read_response(ssm, _dev, TRUE, FALSE, ID_LEN, activate_read_id_cb); aesX660_read_response (ssm, _dev, TRUE, FALSE, ID_LEN, activate_read_id_cb);
break; break;
case ACTIVATE_SEND_INIT_CMD: case ACTIVATE_SEND_INIT_CMD:
fp_dbg("Activate: send init seq #%d cmd #%d\n", fp_dbg ("Activate: send init seq #%d cmd #%d\n",
priv->init_seq_idx, priv->init_seq_idx,
priv->init_cmd_idx); priv->init_cmd_idx);
aesX660_send_cmd(ssm, _dev, aesX660_send_cmd (ssm, _dev,
priv->init_seq[priv->init_cmd_idx].cmd, priv->init_seq[priv->init_cmd_idx].cmd,
priv->init_seq[priv->init_cmd_idx].len, priv->init_seq[priv->init_cmd_idx].len,
aesX660_send_cmd_cb); aesX660_send_cmd_cb);
break; break;
case ACTIVATE_READ_INIT_RESPONSE: case ACTIVATE_READ_INIT_RESPONSE:
fp_dbg("Activate: read init response\n"); fp_dbg ("Activate: read init response\n");
aesX660_read_response(ssm, _dev, TRUE, FALSE, INIT_LEN, activate_read_init_cb); aesX660_read_response (ssm, _dev, TRUE, FALSE, INIT_LEN, activate_read_init_cb);
break; break;
case ACTIVATE_SEND_CALIBRATE_CMD: case ACTIVATE_SEND_CALIBRATE_CMD:
aesX660_send_cmd(ssm, _dev, calibrate_cmd, sizeof(calibrate_cmd), aesX660_send_cmd (ssm, _dev, calibrate_cmd, sizeof (calibrate_cmd),
aesX660_send_cmd_cb); aesX660_send_cmd_cb);
break; break;
case ACTIVATE_READ_CALIBRATE_DATA: case ACTIVATE_READ_CALIBRATE_DATA:
aesX660_read_response(ssm, _dev, TRUE, FALSE, CALIBRATE_DATA_LEN, aesX660_read_calibrate_data_cb); aesX660_read_response (ssm, _dev, TRUE, FALSE, CALIBRATE_DATA_LEN, aesX660_read_calibrate_data_cb);
break; break;
} }
} }
static void activate_sm_complete(FpiSsm *ssm, FpDevice *_dev, static void
activate_sm_complete (FpiSsm *ssm, FpDevice *_dev,
void *user_data, GError *error) void *user_data, GError *error)
{ {
fpi_image_device_activate_complete (FP_IMAGE_DEVICE (_dev), error); fpi_image_device_activate_complete (FP_IMAGE_DEVICE (_dev), error);
fpi_ssm_free(ssm); fpi_ssm_free (ssm);
if (!error) if (!error)
start_finger_detection(FP_IMAGE_DEVICE (_dev)); start_finger_detection (FP_IMAGE_DEVICE (_dev));
} }
static void aesX660_dev_activate(FpImageDevice *dev) static void
aesX660_dev_activate (FpImageDevice *dev)
{ {
FpiSsm *ssm = fpi_ssm_new(FP_DEVICE(dev), activate_run_state, FpiSsm *ssm = fpi_ssm_new (FP_DEVICE (dev), activate_run_state,
ACTIVATE_NUM_STATES, dev); ACTIVATE_NUM_STATES, dev);
fpi_ssm_start(ssm, activate_sm_complete);
fpi_ssm_start (ssm, activate_sm_complete);
} }
static void aesX660_dev_deactivate(FpImageDevice *dev) static void
aesX660_dev_deactivate (FpImageDevice *dev)
{ {
FpiDeviceAesX660 *self = FPI_DEVICE_AES_X660 (dev); FpiDeviceAesX660 *self = FPI_DEVICE_AES_X660 (dev);
FpiDeviceAesX660Private *priv = fpi_device_aes_x660_get_instance_private (self); FpiDeviceAesX660Private *priv = fpi_device_aes_x660_get_instance_private (self);
@ -624,54 +694,61 @@ static void aesX660_dev_deactivate(FpImageDevice *dev)
priv->deactivating = TRUE; priv->deactivating = TRUE;
} }
static void aesX660_dev_init(FpImageDevice *dev) static void
aesX660_dev_init (FpImageDevice *dev)
{ {
FpiDeviceAesX660 *self = FPI_DEVICE_AES_X660 (dev); FpiDeviceAesX660 *self = FPI_DEVICE_AES_X660 (dev);
FpiDeviceAesX660Private *priv = fpi_device_aes_x660_get_instance_private (self); FpiDeviceAesX660Private *priv = fpi_device_aes_x660_get_instance_private (self);
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);
priv->stripe_packet = g_byte_array_new (); priv->stripe_packet = g_byte_array_new ();
fpi_image_device_open_complete(dev, error); fpi_image_device_open_complete (dev, error);
} }
static void aesX660_dev_deinit(FpImageDevice *dev) static void
aesX660_dev_deinit (FpImageDevice *dev)
{ {
FpiDeviceAesX660 *self = FPI_DEVICE_AES_X660 (dev); FpiDeviceAesX660 *self = FPI_DEVICE_AES_X660 (dev);
FpiDeviceAesX660Private *priv = fpi_device_aes_x660_get_instance_private (self); FpiDeviceAesX660Private *priv = fpi_device_aes_x660_get_instance_private (self);
GError *error = NULL; GError *error = NULL;
g_usb_device_release_interface(fpi_device_get_usb_device(FP_DEVICE(dev)), g_usb_device_release_interface (fpi_device_get_usb_device (FP_DEVICE (dev)),
0, 0, &error); 0, 0, &error);
g_clear_pointer (&priv->stripe_packet, g_byte_array_unref); g_clear_pointer (&priv->stripe_packet, g_byte_array_unref);
fpi_image_device_close_complete(dev, error); fpi_image_device_close_complete (dev, error);
} }
static void complete_deactivation(FpImageDevice *dev) static void
complete_deactivation (FpImageDevice *dev)
{ {
FpiDeviceAesX660 *self = FPI_DEVICE_AES_X660 (dev); FpiDeviceAesX660 *self = FPI_DEVICE_AES_X660 (dev);
FpiDeviceAesX660Private *priv = fpi_device_aes_x660_get_instance_private (self); FpiDeviceAesX660Private *priv = fpi_device_aes_x660_get_instance_private (self);
G_DEBUG_HERE(); G_DEBUG_HERE ();
priv->deactivating = FALSE; priv->deactivating = FALSE;
g_slist_free(priv->strips); g_slist_free (priv->strips);
priv->strips = NULL; priv->strips = NULL;
priv->strips_len = 0; priv->strips_len = 0;
fpi_image_device_deactivate_complete(dev, NULL); fpi_image_device_deactivate_complete (dev, NULL);
} }
static void fpi_device_aes_x660_init(FpiDeviceAesX660 *self) { static void
fpi_device_aes_x660_init (FpiDeviceAesX660 *self)
{
} }
static void fpi_device_aes_x660_class_init(FpiDeviceAesX660Class *klass) { static void
FpDeviceClass *dev_class = FP_DEVICE_CLASS(klass); fpi_device_aes_x660_class_init (FpiDeviceAesX660Class *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->type = FP_DEVICE_TYPE_USB; dev_class->type = FP_DEVICE_TYPE_USB;
dev_class->scan_type = FP_SCAN_TYPE_SWIPE; dev_class->scan_type = FP_SCAN_TYPE_SWIPE;

View file

@ -42,12 +42,13 @@
#define AESX660_FRAME_HEIGHT 8 #define AESX660_FRAME_HEIGHT 8
G_DECLARE_DERIVABLE_TYPE(FpiDeviceAesX660, fpi_device_aes_x660, FPI, G_DECLARE_DERIVABLE_TYPE (FpiDeviceAesX660, fpi_device_aes_x660, FPI,
DEVICE_AES_X660, FpImageDevice) DEVICE_AES_X660, FpImageDevice)
#define FPI_TYPE_DEVICE_AES_X660 (fpi_device_aes_x660_get_type ()) #define FPI_TYPE_DEVICE_AES_X660 (fpi_device_aes_x660_get_type ())
struct _FpiDeviceAesX660Class { struct _FpiDeviceAesX660Class
{
FpImageDeviceClass parent; FpImageDeviceClass parent;
struct aesX660_cmd *init_seqs[2]; struct aesX660_cmd *init_seqs[2];
@ -57,7 +58,8 @@ struct _FpiDeviceAesX660Class {
struct fpi_frame_asmbl_ctx *assembling_ctx; struct fpi_frame_asmbl_ctx *assembling_ctx;
}; };
struct aesX660_cmd { struct aesX660_cmd
{
const guint8 *cmd; const guint8 *cmd;
gsize len; gsize len;
}; };
@ -66,33 +68,33 @@ struct aesX660_cmd {
* makes LED blink * makes LED blink
*/ */
static const guint8 led_blink_cmd[] = { static const guint8 led_blink_cmd[] = {
0x77, 0x18, 0x00, 0x77, 0x18, 0x00,
0x00, 0x3f, 0x00, 0xff, 0x00, 0x00, 0x3f, 0x00, 0xff, 0x00,
0x01, 0x01, 0x00, 0x00, 0x00, 0xf3, 0x01, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0xf3, 0x01, 0x00,
0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0xf3, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0xf3,
0x01, 0x00, 0x7f 0x01, 0x00, 0x7f
}; };
/* This sequence makes LED light solid /* This sequence makes LED light solid
*/ */
static const guint8 led_solid_cmd[] = { static const guint8 led_solid_cmd[] = {
0x77, 0x18, 0x00, 0x00, 0x3f, 0x00, 0xff, 0x00, 0x77, 0x18, 0x00, 0x00, 0x3f, 0x00, 0xff, 0x00,
0x01, 0x01, 0x00, 0x00, 0x00, 0xe7, 0x03, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0xe7, 0x03, 0x00,
0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7f 0x00, 0x00, 0x7f
}; };
static const guint8 wait_for_finger_cmd[] = { static const guint8 wait_for_finger_cmd[] = {
0x20, 0x20,
0x40, 0x04, 0x00, 0x02, 0x1e, 0x00, 0x32 0x40, 0x04, 0x00, 0x02, 0x1e, 0x00, 0x32
}; };
/* 0x40 cmd response /* 0x40 cmd response
* *
static const guint8 pkt1371[] = { static const guint8 pkt1371[] = {
0x40, 0x01, 0x00, 0x01 0x40, 0x01, 0x00, 0x01
}; };
*/ */
static const guint8 set_idle_cmd[] = { static const guint8 set_idle_cmd[] = {
0x0d, /* Reset or "set idle"? */ 0x0d, /* Reset or "set idle"? */
@ -107,4 +109,3 @@ static const guint8 calibrate_cmd[] = {
0x44, 0x02, 0x00, 0x04, 0x00, 0x44, 0x02, 0x00, 0x04, 0x00,
0x06, 0x06,
}; };

File diff suppressed because it is too large Load diff

View file

@ -71,7 +71,8 @@
#define ELAN_CMD_TIMEOUT 10000 #define ELAN_CMD_TIMEOUT 10000
#define ELAN_FINGER_TIMEOUT 200 #define ELAN_FINGER_TIMEOUT 200
struct elan_cmd { struct elan_cmd
{
unsigned char cmd[ELAN_CMD_LEN]; unsigned char cmd[ELAN_CMD_LEN];
int response_len; int response_len;
int response_in; int response_in;
@ -156,7 +157,7 @@ static const struct elan_cmd stop_cmd = {
.never_cancel = TRUE, .never_cancel = TRUE,
}; };
static const FpIdEntry elan_id_table [ ] = { static const FpIdEntry elan_id_table[] = {
{.vid = ELAN_VEND_ID, .pid = 0x0903, .driver_data = ELAN_ALL_DEV}, {.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 = 0x0907, .driver_data = ELAN_0907},
{.vid = ELAN_VEND_ID, .pid = 0x0c01, .driver_data = ELAN_ALL_DEV}, {.vid = ELAN_VEND_ID, .pid = 0x0c01, .driver_data = ELAN_ALL_DEV},
@ -214,12 +215,14 @@ static const FpIdEntry elan_id_table [ ] = {
{.vid = 0, .pid = 0, .driver_data = 0}, {.vid = 0, .pid = 0, .driver_data = 0},
}; };
static void elan_cmd_done(FpiSsm *ssm); static void elan_cmd_done (FpiSsm *ssm);
static void elan_cmd_read(FpiSsm *ssm, FpDevice *dev); static void elan_cmd_read (FpiSsm *ssm,
FpDevice *dev);
static void elan_calibrate(FpDevice *dev); static void elan_calibrate (FpDevice *dev);
static void elan_capture(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 #endif

File diff suppressed because it is too large Load diff

View file

@ -34,9 +34,9 @@
#include "bmkt_response.h" #include "bmkt_response.h"
/*! /*!
******************************************************************************* *******************************************************************************
** Type definition for result ** Type definition for result
*/ */
/** No error; Operation successfully completed. */ /** No error; Operation successfully completed. */
#define BMKT_SUCCESS 0 #define BMKT_SUCCESS 0
/** Fingerprint system not initialized */ /** Fingerprint system not initialized */
@ -68,27 +68,27 @@
/** Fingerprint sensor cannot be accessed despite repeated attempts */ /** Fingerprint sensor cannot be accessed despite repeated attempts */
#define BMKT_SENSOR_TAMPERED 203 #define BMKT_SENSOR_TAMPERED 203
/** /**
* BMKT_SENSOR_NOT_INIT: * BMKT_SENSOR_NOT_INIT:
* Fingerprint sensor module not initialized yet not ready for use * Fingerprint sensor module not initialized yet not ready for use
* (different from error code 101 which indicates that the entire system * (different from error code 101 which indicates that the entire system
* has not been initialized) * has not been initialized)
*/ */
#define BMKT_SENSOR_NOT_INIT 204 #define BMKT_SENSOR_NOT_INIT 204
/** Number of re-pairing operations exceeded limit or re-pairing has been disabled */ /** 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: * BMKT_SENSOR_STIMULUS_ERROR:
* There is a finger or debris on the sensor that needs to be removed * There is a finger or debris on the sensor that needs to be removed
* before issuing this command * before issuing this command
*/ */
#define BMKT_SENSOR_STIMULUS_ERROR 213 #define BMKT_SENSOR_STIMULUS_ERROR 213
/** /**
* BMKT_CORRUPT_TEMPLATE_DATA: * BMKT_CORRUPT_TEMPLATE_DATA:
* One of the fingerprint templates stored on flash is corrupt. * One of the fingerprint templates stored on flash is corrupt.
* This error code is returned in case of failure in finding a fingerprint match * 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 * during identify or verify operations while also detecting that one or more
* fingerprint templates stored on the flash has become corrupted * fingerprint templates stored on the flash has become corrupted
*/ */
#define BMKT_CORRUPT_TEMPLATE_DATA 300 #define BMKT_CORRUPT_TEMPLATE_DATA 300
/** Failed to extract features from fingerprint image acquired by sensor */ /** Failed to extract features from fingerprint image acquired by sensor */
#define BMKT_FEATURE_EXTRACT_FAIL 301 #define BMKT_FEATURE_EXTRACT_FAIL 301
@ -129,11 +129,10 @@ extern "C" {
#endif #endif
/** /**
* bmkt_mode: * bmkt_mode:
* Fingerprint system operational mode values level 1 * Fingerprint system operational mode values level 1
*/ */
typedef enum bmkt_mode typedef enum bmkt_mode {
{
BMKT_STATE_UNINIT = 0xFF, BMKT_STATE_UNINIT = 0xFF,
BMKT_STATE_IDLE = 0x00, BMKT_STATE_IDLE = 0x00,
BMKT_STATE_ENROLL = 0x10, BMKT_STATE_ENROLL = 0x10,
@ -145,11 +144,10 @@ typedef enum bmkt_mode
} bmkt_mode_t; } bmkt_mode_t;
/** /**
* bmkt_mode_level2: * bmkt_mode_level2:
* Fingerprint system operational mode values level 2 * Fingerprint system operational mode values level 2
*/ */
typedef enum bmkt_mode_level2 typedef enum bmkt_mode_level2 {
{
BMKT_STATE_L2_IDLE = 0x00, BMKT_STATE_L2_IDLE = 0x00,
BMKT_STATE_L2_STARTING = 0x11, BMKT_STATE_L2_STARTING = 0x11,
BMKT_STATE_L2_WAITING_FOR_FINGER = 0x12, BMKT_STATE_L2_WAITING_FOR_FINGER = 0x12,
@ -167,36 +165,35 @@ typedef enum bmkt_mode_level2
} bmkt_mode_level2_t; } bmkt_mode_level2_t;
/** /**
* bmkt_transport_type: * bmkt_transport_type:
* Fingerprint system transport types * Fingerprint system transport types
*/ */
typedef enum bmkt_transport_type typedef enum bmkt_transport_type {
{
BMKT_TRANSPORT_TYPE_USB = 0, BMKT_TRANSPORT_TYPE_USB = 0,
} bmkt_transport_type_t; } bmkt_transport_type_t;
/** /**
* bmkt_usb_config: * bmkt_usb_config:
* Structure represcontainingenting USB configuration details * Structure represcontainingenting USB configuration details
*/ */
typedef struct bmkt_usb_config typedef struct bmkt_usb_config
{ {
int product_id; /**< USB device product ID */ int product_id; /**< USB device product ID */
} bmkt_usb_config_t; } bmkt_usb_config_t;
/** /**
* bmkt_transport_config_t: * bmkt_transport_config_t:
* Union containing transport configuration details * Union containing transport configuration details
*/ */
typedef union typedef union
{ {
bmkt_usb_config_t usb_config; bmkt_usb_config_t usb_config;
} bmkt_transport_config_t; } bmkt_transport_config_t;
/** /**
* bmkt_sensor_desc_t: * bmkt_sensor_desc_t:
* Structure containing fingerprint system description * Structure containing fingerprint system description
*/ */
typedef struct bmkt_sensor_desc typedef struct bmkt_sensor_desc
{ {
int product_id; int product_id;
@ -204,20 +201,19 @@ typedef struct bmkt_sensor_desc
} bmkt_sensor_desc_t; } bmkt_sensor_desc_t;
/** /**
* bmkt_finger_state_t: * bmkt_finger_state_t:
* Finger state representation values. * Finger state representation values.
*/ */
typedef enum typedef enum {
{
BMKT_FINGER_STATE_UNKNOWN = 0, BMKT_FINGER_STATE_UNKNOWN = 0,
BMKT_FINGER_STATE_ON_SENSOR, BMKT_FINGER_STATE_ON_SENSOR,
BMKT_FINGER_STATE_NOT_ON_SENSOR, BMKT_FINGER_STATE_NOT_ON_SENSOR,
} bmkt_finger_state_t; } bmkt_finger_state_t;
/** /**
* bmkt_finger_event_t: * bmkt_finger_event_t:
* Structure containing finger state * Structure containing finger state
*/ */
typedef struct bmkt_finger_event typedef struct bmkt_finger_event
{ {
bmkt_finger_state_t finger_state; bmkt_finger_state_t finger_state;

View file

@ -20,10 +20,12 @@
#include "bmkt_response.h" #include "bmkt_response.h"
#include "bmkt_message.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; uint8_t ret = 0;
int off = 0; int off = 0;
if (offset) if (offset)
off = *offset; off = *offset;
@ -36,155 +38,145 @@ static uint8_t extract8(const uint8_t *buf, int *offset)
} }
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) if (msg_resp->payload_len != 2)
{
return BMKT_UNRECOGNIZED_MESSAGE; 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) if (msg_resp->payload_len != 1)
{
return BMKT_UNRECOGNIZED_MESSAGE; 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; int offset = 0;
bmkt_fps_mode_resp_t *fps_mode_resp = &resp->response.fps_mode_resp; bmkt_fps_mode_resp_t *fps_mode_resp = &resp->response.fps_mode_resp;
if (msg_resp->payload_len != sizeof(bmkt_fps_mode_resp_t)) if (msg_resp->payload_len != sizeof (bmkt_fps_mode_resp_t))
{
return BMKT_UNRECOGNIZED_MESSAGE; return BMKT_UNRECOGNIZED_MESSAGE;
}
fps_mode_resp->mode = 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->level2_mode = extract8 (msg_resp->payload, &offset);
fps_mode_resp->cmd_id = 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->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) if (msg_resp->payload_len != 1)
{
return BMKT_UNRECOGNIZED_MESSAGE; 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)) if (msg_resp->payload_len < 1 || msg_resp->payload_len > (BMKT_MAX_USER_ID_LEN + 1))
{
return BMKT_UNRECOGNIZED_MESSAGE; return BMKT_UNRECOGNIZED_MESSAGE;
}
enroll_resp->finger_id = msg_resp->payload[0]; enroll_resp->finger_id = msg_resp->payload[0];
memcpy(enroll_resp->user_id, &msg_resp->payload[1], msg_resp->payload_len - 1); 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)) if (msg_resp->payload_len < 3 || msg_resp->payload_len > (BMKT_MAX_USER_ID_LEN + 3))
{
return BMKT_UNRECOGNIZED_MESSAGE; return BMKT_UNRECOGNIZED_MESSAGE;
}
id_resp->match_result = (double)msg_resp->payload[0] + 0.01 * (double)msg_resp->payload[1]; id_resp->match_result = (double) msg_resp->payload[0] + 0.01 * (double) msg_resp->payload[1];
id_resp->finger_id = msg_resp->payload[2]; id_resp->finger_id = msg_resp->payload[2];
memcpy(id_resp->user_id, &msg_resp->payload[3], msg_resp->payload_len - 3); 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) if (msg_resp->payload_len != 1)
{
return BMKT_UNRECOGNIZED_MESSAGE; 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) if (msg_resp->payload_len != 1)
{
return BMKT_UNRECOGNIZED_MESSAGE; 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; bmkt_get_db_capacity_resp_t *db_cap_resp = &resp->response.db_cap_resp;
int offset = 0; int offset = 0;
if (msg_resp->payload_len < 2 || msg_resp->payload_len > 4) if (msg_resp->payload_len < 2 || msg_resp->payload_len > 4)
{
return BMKT_UNRECOGNIZED_MESSAGE; return BMKT_UNRECOGNIZED_MESSAGE;
}
db_cap_resp->total = extract8(msg_resp->payload, &offset); db_cap_resp->total = extract8 (msg_resp->payload, &offset);
db_cap_resp->empty = extract8(msg_resp->payload, &offset); db_cap_resp->empty = extract8 (msg_resp->payload, &offset);
if (msg_resp->payload_len == 4) if (msg_resp->payload_len == 4)
{ {
db_cap_resp->bad_slots = extract8(msg_resp->payload, &offset); db_cap_resp->bad_slots = extract8 (msg_resp->payload, &offset);
db_cap_resp->corrupt_templates = 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 offset = 0;
int i = 0; int i = 0;
if (msg_resp->payload_len < 2) if (msg_resp->payload_len < 2)
{
return BMKT_UNRECOGNIZED_MESSAGE; return BMKT_UNRECOGNIZED_MESSAGE;
}
/* 2 bytes per finger so calculate the total number of fingers to process*/ /* 2 bytes per finger so calculate the total number of fingers to process*/
int num_fingers = (msg_resp->payload_len) / 2; int num_fingers = (msg_resp->payload_len) / 2;
@ -192,118 +184,107 @@ static int parse_get_enrolled_fingers_report(bmkt_msg_resp_t *msg_resp, bmkt_res
for (i = 0; i < num_fingers; i++) 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].finger_id = extract8 (msg_resp->payload, &offset);
get_enrolled_fingers_resp->fingers[i].template_status = 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 offset = 0;
int i = 0; int i = 0;
/* the payload is 2 bytes + template data */ /* the payload is 2 bytes + template data */
if (msg_resp->payload_len < 2) if (msg_resp->payload_len < 2)
{
return BMKT_UNRECOGNIZED_MESSAGE; 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->total_query_messages = extract8 (msg_resp->payload, &offset);
get_enroll_templates_resp->query_sequence = extract8(msg_resp->payload, &offset); get_enroll_templates_resp->query_sequence = extract8 (msg_resp->payload, &offset);
int n = 0; int n = 0;
for (n = 0; n < BMKT_MAX_NUM_TEMPLATES_INTERNAL_FLASH; n++) for (n = 0; n < BMKT_MAX_NUM_TEMPLATES_INTERNAL_FLASH; n++)
{ {
if (offset >= msg_resp->payload_len) if (offset >= msg_resp->payload_len)
break; break;
get_enroll_templates_resp->templates[n].user_id_len = extract8(msg_resp->payload, &offset) - 2; 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) if(get_enroll_templates_resp->templates[n].user_id_len > BMKT_MAX_USER_ID_LEN)
{
return BMKT_UNRECOGNIZED_MESSAGE; return BMKT_UNRECOGNIZED_MESSAGE;
} get_enroll_templates_resp->templates[n].template_status = extract8 (msg_resp->payload, &offset);
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);
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++) 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] = extract8(msg_resp->payload, &offset);
}
get_enroll_templates_resp->templates[n].user_id[i] = '\0'; 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; bmkt_get_version_resp_t *get_version_resp = &resp->response.get_version_resp;
int offset = 0; int offset = 0;
if (msg_resp->payload_len != 15) if (msg_resp->payload_len != 15)
{
return BMKT_UNRECOGNIZED_MESSAGE; return BMKT_UNRECOGNIZED_MESSAGE;
}
memcpy(get_version_resp->part, msg_resp->payload, BMKT_PART_NUM_LEN); memcpy (get_version_resp->part, msg_resp->payload, BMKT_PART_NUM_LEN);
offset += BMKT_PART_NUM_LEN; offset += BMKT_PART_NUM_LEN;
get_version_resp->year = extract8(msg_resp->payload, &offset); get_version_resp->year = extract8 (msg_resp->payload, &offset);
get_version_resp->week = extract8(msg_resp->payload, &offset); get_version_resp->week = extract8 (msg_resp->payload, &offset);
get_version_resp->patch = 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->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, 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) 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) if (*cmd_len < message_len)
{
return BMKT_OUT_OF_MEMORY; return BMKT_OUT_OF_MEMORY;
}
cmd[BMKT_MESSAGE_HEADER_ID_FIELD] = BMKT_MESSAGE_HEADER_ID; cmd[BMKT_MESSAGE_HEADER_ID_FIELD] = BMKT_MESSAGE_HEADER_ID;
cmd[BMKT_MESSAGE_SEQ_NUM_FIELD] = seq_num; cmd[BMKT_MESSAGE_SEQ_NUM_FIELD] = seq_num;
cmd[BMKT_MESSAGE_ID_FIELD] = msg_id; cmd[BMKT_MESSAGE_ID_FIELD] = msg_id;
cmd[BMKT_MESSAGE_PAYLOAD_LEN_FIELD] = payload_size; cmd[BMKT_MESSAGE_PAYLOAD_LEN_FIELD] = payload_size;
memcpy(&cmd[BMKT_MESSAGE_PAYLOAD_FIELD], payload, 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) if (resp_buf[BMKT_MESSAGE_HEADER_ID_FIELD] != BMKT_MESSAGE_HEADER_ID)
{
return BMKT_CORRUPT_MESSAGE; return BMKT_CORRUPT_MESSAGE;
}
msg_resp->seq_num = resp_buf[BMKT_MESSAGE_SEQ_NUM_FIELD]; msg_resp->seq_num = resp_buf[BMKT_MESSAGE_SEQ_NUM_FIELD];
msg_resp->msg_id = resp_buf[BMKT_MESSAGE_ID_FIELD]; msg_resp->msg_id = resp_buf[BMKT_MESSAGE_ID_FIELD];
msg_resp->payload_len = resp_buf[BMKT_MESSAGE_PAYLOAD_LEN_FIELD]; msg_resp->payload_len = resp_buf[BMKT_MESSAGE_PAYLOAD_LEN_FIELD];
if (msg_resp->payload_len > 0) if (msg_resp->payload_len > 0)
{
msg_resp->payload = &resp_buf[BMKT_MESSAGE_PAYLOAD_FIELD]; msg_resp->payload = &resp_buf[BMKT_MESSAGE_PAYLOAD_FIELD];
}
else else
{
msg_resp->payload = NULL; 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;
@ -329,12 +310,12 @@ int bmkt_parse_message_payload(bmkt_msg_resp_t *msg_resp, bmkt_response_t *resp)
case BMKT_RSP_QUERY_PAIRING_FAIL: case BMKT_RSP_QUERY_PAIRING_FAIL:
case BMKT_RSP_SENSOR_STATUS_FAIL: case BMKT_RSP_SENSOR_STATUS_FAIL:
case BMKT_RSP_RETRIEVE_FINAL_RESULT_FAIL: case BMKT_RSP_RETRIEVE_FINAL_RESULT_FAIL:
ret = parse_error_response(msg_resp, resp); ret = parse_error_response (msg_resp, resp);
resp->complete = 1; resp->complete = 1;
break; break;
case BMKT_RSP_FPS_INIT_OK: case BMKT_RSP_FPS_INIT_OK:
ret = parse_init_ok(msg_resp, resp); ret = parse_init_ok (msg_resp, resp);
resp->complete = 1; resp->complete = 1;
break; break;
@ -349,19 +330,19 @@ int bmkt_parse_message_payload(bmkt_msg_resp_t *msg_resp, bmkt_response_t *resp)
case BMKT_RSP_FPS_MODE_REPORT: case BMKT_RSP_FPS_MODE_REPORT:
// parse_fps_mode // parse_fps_mode
ret = parse_fps_mode_report(msg_resp, resp); ret = parse_fps_mode_report (msg_resp, resp);
resp->complete = 1; resp->complete = 1;
break; break;
case BMKT_RSP_GET_SECURITY_LEVEL_REPORT: case BMKT_RSP_GET_SECURITY_LEVEL_REPORT:
case BMKT_RSP_SET_SECURITY_LEVEL_REPORT: case BMKT_RSP_SET_SECURITY_LEVEL_REPORT:
/* parse security level result */ /* parse security level result */
ret = parse_security_level_report(msg_resp, resp); ret = parse_security_level_report (msg_resp, resp);
resp->complete = 1; resp->complete = 1;
break; break;
case BMKT_RSP_DELETE_PROGRESS: case BMKT_RSP_DELETE_PROGRESS:
ret = parse_del_all_users_progress_report(msg_resp, resp); ret = parse_del_all_users_progress_report (msg_resp, resp);
break; break;
case BMKT_RSP_CAPTURE_COMPLETE: case BMKT_RSP_CAPTURE_COMPLETE:
@ -373,38 +354,43 @@ int bmkt_parse_message_payload(bmkt_msg_resp_t *msg_resp, bmkt_response_t *resp)
break; break;
case BMKT_RSP_ENROLL_REPORT: case BMKT_RSP_ENROLL_REPORT:
ret = parse_enroll_report(msg_resp, resp); ret = parse_enroll_report (msg_resp, resp);
break; break;
case BMKT_RSP_ENROLL_OK: case BMKT_RSP_ENROLL_OK:
resp->complete = 1; resp->complete = 1;
ret = parse_enroll_ok(msg_resp, resp); ret = parse_enroll_ok (msg_resp, resp);
break; break;
case BMKT_RSP_ID_OK: case BMKT_RSP_ID_OK:
case BMKT_RSP_VERIFY_OK: case BMKT_RSP_VERIFY_OK:
ret = parse_auth_ok(msg_resp, resp); ret = parse_auth_ok (msg_resp, resp);
resp->complete = 1; resp->complete = 1;
break; break;
case BMKT_RSP_GET_ENROLLED_FINGERS_REPORT: case BMKT_RSP_GET_ENROLLED_FINGERS_REPORT:
ret = parse_get_enrolled_fingers_report(msg_resp, resp); ret = parse_get_enrolled_fingers_report (msg_resp, resp);
resp->complete = 1; resp->complete = 1;
break; break;
case BMKT_RSP_DATABASE_CAPACITY_REPORT: case BMKT_RSP_DATABASE_CAPACITY_REPORT:
resp->complete = 1; resp->complete = 1;
ret = parse_db_cap_report(msg_resp, resp); ret = parse_db_cap_report (msg_resp, resp);
break; break;
case BMKT_RSP_TEMPLATE_RECORDS_REPORT: case BMKT_RSP_TEMPLATE_RECORDS_REPORT:
ret = parse_get_enrolled_users_report(msg_resp, resp); ret = parse_get_enrolled_users_report (msg_resp, resp);
break; break;
case BMKT_RSP_QUERY_RESPONSE_COMPLETE: case BMKT_RSP_QUERY_RESPONSE_COMPLETE:
resp->complete = 1; resp->complete = 1;
break; break;
case BMKT_RSP_VERSION_INFO: case BMKT_RSP_VERSION_INFO:
ret = parse_get_version_report(msg_resp, resp); ret = parse_get_version_report (msg_resp, resp);
resp->complete = 1; resp->complete = 1;
break; break;
case BMKT_RSP_POWER_DOWN_READY: case BMKT_RSP_POWER_DOWN_READY:
resp->complete = 1; resp->complete = 1;
break; break;

View file

@ -78,9 +78,16 @@ typedef struct bmkt_msg_resp
int result; int result;
} bmkt_msg_resp_t; } bmkt_msg_resp_t;
int bmkt_compose_message(uint8_t *cmd, int *cmd_len, uint8_t msg_id, uint8_t seq_num, int bmkt_compose_message (uint8_t *cmd,
uint8_t payload_size, const uint8_t *payload); 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_header (uint8_t *resp_buf,
int bmkt_parse_message_payload(bmkt_msg_resp_t *msg_resp, bmkt_response_t *resp); 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_ */ #endif /* BMKT_MESSAGE_H_ */

View file

@ -33,9 +33,9 @@
#define BMKT_RSP_NEXT_TEST_REPORT_CHUNK 0x0C #define BMKT_RSP_NEXT_TEST_REPORT_CHUNK 0x0C
/*! \addtogroup init /*! \addtogroup init
* Response IDs returned by fingerprint initialization operation * Response IDs returned by fingerprint initialization operation
* @{ * @{
*/ */
/** Failed to initialize fingerprint sensor module */ /** 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 */ /** Successfully initialized fingerprint sensor module */
@ -43,70 +43,70 @@
/*! @} */ /*! @} */
/*! \addtogroup mode /*! \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 */ /** 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: * BMKT_RSP_FPS_MODE_REPORT:
* Response containing the current operational mode of the fingerprint sensor module * Response containing the current operational mode of the fingerprint sensor module
* <br>Payload data represented in \ref bmkt_fps_mode_resp_t struct * <br>Payload data represented in \ref bmkt_fps_mode_resp_t struct
*/ */
#define BMKT_RSP_FPS_MODE_REPORT 0x23 #define BMKT_RSP_FPS_MODE_REPORT 0x23
/*! @} */ /*! @} */
/*! \addtogroup setseclevel /*! \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 */ /** 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: * BMKT_RSP_SET_SECURITY_LEVEL_REPORT:
* Security level of the fingerprint sensor module was set successfully * Security level of the fingerprint sensor module was set successfully
* <br>Contains payload data represented in \ref bmkt_set_sec_level_resp_t struct * <br>Contains payload data represented in \ref bmkt_set_sec_level_resp_t struct
*/ */
#define BMKT_RSP_SET_SECURITY_LEVEL_REPORT 0x33 #define BMKT_RSP_SET_SECURITY_LEVEL_REPORT 0x33
/*! @} */ /*! @} */
/*! \addtogroup getseclevel /*! \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 */ /** 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: * BMKT_RSP_GET_SECURITY_LEVEL_REPORT:
* Returns the current security level of the fingerprint sensor module * Returns the current security level of the fingerprint sensor module
* <br>Contains payload data represented in \ref bmkt_set_sec_level_resp_t struct * <br>Contains payload data represented in \ref bmkt_set_sec_level_resp_t struct
*/ */
#define BMKT_RSP_GET_SECURITY_LEVEL_REPORT 0x36 #define BMKT_RSP_GET_SECURITY_LEVEL_REPORT 0x36
/*! @} */ /*! @} */
/*! \addtogroup cancelop /*! \addtogroup cancelop
* Response IDs returned by cancel_operation operation * Response IDs returned by cancel_operation operation
* @{ * @{
*/ */
/** /**
* BMKT_RSP_CANCEL_OP_OK: * BMKT_RSP_CANCEL_OP_OK:
* Successfully canceled the current operation and returned * Successfully canceled the current operation and returned
* fingerprint sensor module to idle mode * fingerprint sensor module to idle mode
*/ */
#define BMKT_RSP_CANCEL_OP_OK 0x42 #define BMKT_RSP_CANCEL_OP_OK 0x42
/** Failed to cancel the current operation */ /** Failed to cancel the current operation */
#define BMKT_RSP_CANCEL_OP_FAIL 0x43 #define BMKT_RSP_CANCEL_OP_FAIL 0x43
/*! @} */ /*! @} */
/*! \addtogroup enrollment /*! \addtogroup enrollment
* Response IDs returned by enrollment operation * Response IDs returned by enrollment operation
* @{ * @{
*/ */
/** /**
* BMKT_RSP_ENROLL_READY: * BMKT_RSP_ENROLL_READY:
* Fingerprint enrollment session has begun and the user can place * Fingerprint enrollment session has begun and the user can place
* their finger on the sensor * their finger on the sensor
*/ */
#define BMKT_RSP_ENROLL_READY 0x54 #define BMKT_RSP_ENROLL_READY 0x54
/** Progress of the currently on-going fingerprint enrollment session */ /** Progress of the currently on-going fingerprint enrollment session */
#define BMKT_RSP_ENROLL_REPORT 0x55 #define BMKT_RSP_ENROLL_REPORT 0x55
@ -117,135 +117,135 @@
/** The current enrollment session has encountered an error */ /** The current enrollment session has encountered an error */
#define BMKT_RSP_ENROLL_FAIL 0x58 #define BMKT_RSP_ENROLL_FAIL 0x58
/** /**
* BMKT_RSP_ENROLL_OK: * BMKT_RSP_ENROLL_OK:
* User has been successfully enrolled into the fingerprint sensor module * User has been successfully enrolled into the fingerprint sensor module
* <br>Contains payload data represented in \ref bmkt_enroll_resp_t struct * <br>Contains payload data represented in \ref bmkt_enroll_resp_t struct
*/ */
#define BMKT_RSP_ENROLL_OK 0x59 #define BMKT_RSP_ENROLL_OK 0x59
/** /**
* BMKT_RSP_CAPTURE_COMPLETE: * BMKT_RSP_CAPTURE_COMPLETE:
* Fingerprint image capture is complete and it is safe for the user * Fingerprint image capture is complete and it is safe for the user
* to lift their finger off the sensor * to lift their finger off the sensor
*/ */
#define BMKT_RSP_CAPTURE_COMPLETE 0x60 #define BMKT_RSP_CAPTURE_COMPLETE 0x60
/*! @} */ /*! @} */
/*! \addtogroup identify /*! \addtogroup identify
* Response IDs returned by identify operation. * Response IDs returned by identify operation.
* @{ * @{
*/ */
/* Fingerprint identification session has begun */ /* Fingerprint identification session has begun */
#define BMKT_RSP_ID_READY 0x62 #define BMKT_RSP_ID_READY 0x62
/* Identification has failed */ /* Identification has failed */
#define BMKT_RSP_ID_FAIL 0x63 #define BMKT_RSP_ID_FAIL 0x63
/** /**
* BMKT_RSP_ID_OK: * BMKT_RSP_ID_OK:
* User has been successfully identified * User has been successfully identified
* <br>Contains payload data represented in \ref bmkt_auth_resp struct * <br>Contains payload data represented in \ref bmkt_auth_resp struct
*/ */
#define BMKT_RSP_ID_OK 0x64 #define BMKT_RSP_ID_OK 0x64
/*! @} */ /*! @} */
/*! \addtogroup verify /*! \addtogroup verify
* Response IDs returned by identify operation. * Response IDs returned by identify operation.
* @{ * @{
*/ */
/** Fingerprint verification session has begun */ /** Fingerprint verification session has begun */
#define BMKT_RSP_VERIFY_READY 0x66 #define BMKT_RSP_VERIFY_READY 0x66
/** Verification has failed */ /** Verification has failed */
#define BMKT_RSP_VERIFY_FAIL 0x67 #define BMKT_RSP_VERIFY_FAIL 0x67
/** /**
* BMKT_RSP_VERIFY_OK: * BMKT_RSP_VERIFY_OK:
* Users identity has been successfully verified * Users identity has been successfully verified
* <br>Contains payload data represented in \ref bmkt_auth_resp struct * <br>Contains payload data represented in \ref bmkt_auth_resp struct
*/ */
#define BMKT_RSP_VERIFY_OK 0x68 #define BMKT_RSP_VERIFY_OK 0x68
/*! @} */ /*! @} */
/** /**
* BMKT_RSP_TEMPLATE_RECORDS_REPORT: * BMKT_RSP_TEMPLATE_RECORDS_REPORT:
* Response ID returned by get enrolled users templates record operation * Response ID returned by get enrolled users templates record operation
* <br>Returns list of template records containing user IDs and corresponding finger IDs * <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 * <br>Payload data represented in \ref bmkt_enroll_templates_resp_t struct
*/ */
#define BMKT_RSP_TEMPLATE_RECORDS_REPORT 0x75 #define BMKT_RSP_TEMPLATE_RECORDS_REPORT 0x75
/** /**
* BMKT_RSP_QUERY_RESPONSE_COMPLETE: * BMKT_RSP_QUERY_RESPONSE_COMPLETE:
* Response ID returned by get next query response operation * Response ID returned by get next query response operation
* <br>Complete sequence of messages containing the template records query response has been sent * <br>Complete sequence of messages containing the template records query response has been sent
*/ */
#define BMKT_RSP_QUERY_RESPONSE_COMPLETE 0x76 #define BMKT_RSP_QUERY_RESPONSE_COMPLETE 0x76
/** /**
* BMKT_RSP_GET_ENROLLED_FINGERS_REPORT: * BMKT_RSP_GET_ENROLLED_FINGERS_REPORT:
* Response ID returned by get enrolled fingers operation * Response ID returned by get enrolled fingers operation
* <br> Returns list of IDs of enrolled fingers for a specific user, * <br> Returns list of IDs of enrolled fingers for a specific user,
* along with template record status corresponding to each enrolled finger * along with template record status corresponding to each enrolled finger
* <br>Contains payload data represented in \ref bmkt_enrolled_fingers_resp_t struct * <br>Contains payload data represented in \ref bmkt_enrolled_fingers_resp_t struct
*/ */
#define BMKT_RSP_GET_ENROLLED_FINGERS_REPORT 0x77 #define BMKT_RSP_GET_ENROLLED_FINGERS_REPORT 0x77
/*! \addtogroup dbcapacity /*! \addtogroup dbcapacity
* Response IDs returned by get database capacity operation * Response IDs returned by get database capacity operation
* @{ * @{
*/ */
/** /**
* BMKT_RSP_DATABASE_CAPACITY_REPORT: * BMKT_RSP_DATABASE_CAPACITY_REPORT:
* Response specifying total capacity of fingerprint template database and * Response specifying total capacity of fingerprint template database and
* how much free capacity is remaining along with how many templates are corrupted and * how much free capacity is remaining along with how many templates are corrupted and
* how many bad (permanently unusable) storage slots are there. * how many bad (permanently unusable) storage slots are there.
* <br>Payload data represented in \ref bmkt_get_db_capacity_resp_t struct * <br>Payload data represented in \ref bmkt_get_db_capacity_resp_t struct
*/ */
#define BMKT_RSP_DATABASE_CAPACITY_REPORT 0x78 #define BMKT_RSP_DATABASE_CAPACITY_REPORT 0x78
/** Failed to execute database query */ /** Failed to execute database query */
#define BMKT_RSP_QUERY_FAIL 0x79 #define BMKT_RSP_QUERY_FAIL 0x79
/*! @} */ /*! @} */
/*! \addtogroup deluser /*! \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 */ /** 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: * BMKT_RSP_DEL_USER_FP_OK:
* Fingerprint template successfully deleted from the database. * 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, * 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 * 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 * <br>Payload data represented in \ref bmkt_del_user_resp_t struct
*/ */
#define BMKT_RSP_DEL_USER_FP_OK 0x83 #define BMKT_RSP_DEL_USER_FP_OK 0x83
/*! @} */ /*! @} */
/*! \addtogroup delfulldb /*! \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 */ /** 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 */ /** 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: * BMKT_RSP_DELETE_PROGRESS:
* Notify progress made during the on-going deletion of the full template database * 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 * <br>Payload data represented in \ref bmkt_del_all_users_resp_t struct
*/ */
#define BMKT_RSP_DELETE_PROGRESS 0x87 #define BMKT_RSP_DELETE_PROGRESS 0x87
/*! @} */ /*! @} */
/** /**
* BMKT_RSP_REPEAT_LAST_BMKT_RSP_FAIL: * BMKT_RSP_REPEAT_LAST_BMKT_RSP_FAIL:
* Response ID returned by repeate last response operation * Response ID returned by repeate last response operation
* <br>Failed to retrieve and re-send last response * <br>Failed to retrieve and re-send last response
*/ */
#define BMKT_RSP_REPEAT_LAST_BMKT_RSP_FAIL 0x93 #define BMKT_RSP_REPEAT_LAST_BMKT_RSP_FAIL 0x93
/*! \addtogroup pwrdwn /*! \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 */ /** 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 */ /** Failed to go into power down mode */
@ -253,24 +253,24 @@
/*! @} */ /*! @} */
/*! \addtogroup versioninfo /*! \addtogroup versioninfo
* Response IDs returned by get version operation * Response IDs returned by get version operation
* @{ * @{
*/ */
/** /**
* BMKT_RSP_VERSION_INFO: * BMKT_RSP_VERSION_INFO:
* System version information of the fingerprint sensor module * System version information of the fingerprint sensor module
* <br>Payload data represented in \ref bmkt_get_version_resp_t struct * <br>Payload data represented in \ref bmkt_get_version_resp_t struct
*/ */
#define BMKT_RSP_VERSION_INFO 0xB2 #define BMKT_RSP_VERSION_INFO 0xB2
/* Failed to retrieve and send last response */ /* 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: * BMKT_RSP_GENERAL_ERROR:
* Not tied to a specific command-response session. * Not tied to a specific command-response session.
* <br>Could be caused by corrupt or truncated command message * <br>Could be caused by corrupt or truncated command message
*/ */
#define BMKT_RSP_GENERAL_ERROR 0xC1 #define BMKT_RSP_GENERAL_ERROR 0xC1
#define BMKT_RSP_DISABLE_PAIRING_FAIL 0xC3 #define BMKT_RSP_DISABLE_PAIRING_FAIL 0xC3
#define BMKT_RSP_DISABLE_PAIRING_OK 0xC4 #define BMKT_RSP_DISABLE_PAIRING_OK 0xC4
@ -278,44 +278,44 @@
#define BMKT_RSP_SENSOR_PAIRING_REPORT 0xC7 #define BMKT_RSP_SENSOR_PAIRING_REPORT 0xC7
/*! \addtogroup versioninfo /*! \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: * BMKT_RSP_SENSOR_STATUS_REPORT:
* Response returning the current status of the sensor module * Response returning the current status of the sensor module
* <br>Payload data represented in bmkt_XXX struct * <br>Payload data represented in bmkt_XXX struct
*/ */
#define BMKT_RSP_SENSOR_STATUS_REPORT 0xD2 #define BMKT_RSP_SENSOR_STATUS_REPORT 0xD2
/** Failed to retrieve sensor status */ /** 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: * BMKT_RSP_SEND_NEXT_USER_ID:
* Response ID returned by identify user in order operation * Response ID returned by identify user in order operation
* <br>Notify to send the next batch of user IDs in the priority list * <br>Notify to send the next batch of user IDs in the priority list
*/ */
#define BMKT_RSP_SEND_NEXT_USER_ID 0xE2 #define BMKT_RSP_SEND_NEXT_USER_ID 0xE2
/** /**
* BMKT_RSP_RETRIEVE_FINAL_RESULT_FAIL: * BMKT_RSP_RETRIEVE_FINAL_RESULT_FAIL:
* Response IDs returned by retrieve final result operation * Response IDs returned by retrieve final result operation
* <br>Failed to retrieve and re-send cached final result * <br>Failed to retrieve and re-send cached final result
*/ */
#define BMKT_RSP_RETRIEVE_FINAL_RESULT_FAIL 0xE5 #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 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_init_resp_t;
/** /**
* bmkt_enroll_resp: * bmkt_enroll_resp:
* Response payload data structure returned by enrollment operation. * Response payload data structure returned by enrollment operation.
*/ */
typedef struct bmkt_enroll_resp typedef struct bmkt_enroll_resp
{ {
int progress; /**< Shows current progress stutus [0-100] */ int progress; /**< Shows current progress stutus [0-100] */
@ -324,9 +324,9 @@ typedef struct bmkt_enroll_resp
} bmkt_enroll_resp_t; } bmkt_enroll_resp_t;
/** /**
* bmkt_auth_resp: * bmkt_auth_resp:
* Response payload data structure returned by identify and verify operations. * Response payload data structure returned by identify and verify operations.
*/ */
struct bmkt_auth_resp struct bmkt_auth_resp
{ {
double match_result; /**< match result returned by matcher */ double match_result; /**< match result returned by matcher */
@ -338,9 +338,9 @@ typedef struct bmkt_auth_resp bmkt_verify_resp_t; /**< Returned by verify */
typedef struct bmkt_auth_resp bmkt_identify_resp_t; /**< Returned by identify */ typedef struct bmkt_auth_resp bmkt_identify_resp_t; /**< Returned by identify */
/** /**
* bmkt_fps_mode_resp: * bmkt_fps_mode_resp:
* Response payload data structure returned by get fingerprint mode operation. * Response payload data structure returned by get fingerprint mode operation.
*/ */
typedef struct bmkt_fps_mode_resp typedef struct bmkt_fps_mode_resp
{ {
uint8_t mode; /**< One of the Level I bmkt_mode_t values */ uint8_t mode; /**< One of the Level I bmkt_mode_t values */
@ -350,9 +350,9 @@ typedef struct bmkt_fps_mode_resp
} bmkt_fps_mode_resp_t; } bmkt_fps_mode_resp_t;
/** /**
* bmkt_get_version_resp: * bmkt_get_version_resp:
* Response payload data structure returned by get version operation. * Response payload data structure returned by get version operation.
*/ */
typedef struct bmkt_get_version_resp typedef struct bmkt_get_version_resp
{ {
uint8_t part[BMKT_PART_NUM_LEN]; /**< Software Part Number */ uint8_t part[BMKT_PART_NUM_LEN]; /**< Software Part Number */
@ -363,9 +363,9 @@ typedef struct bmkt_get_version_resp
} bmkt_get_version_resp_t; } bmkt_get_version_resp_t;
/** /**
* bmkt_get_db_capacity_resp: * bmkt_get_db_capacity_resp:
* Response payload data structure returned by get DB capacity operation. * Response payload data structure returned by get DB capacity operation.
*/ */
typedef struct bmkt_get_db_capacity_resp typedef struct bmkt_get_db_capacity_resp
{ {
uint8_t total; /**< Total Available Capacity: Total number of template records that can be stored */ uint8_t total; /**< Total Available Capacity: Total number of template records that can be stored */
@ -375,47 +375,46 @@ typedef struct bmkt_get_db_capacity_resp
} bmkt_get_db_capacity_resp_t; } bmkt_get_db_capacity_resp_t;
/** /**
* bmkt_sec_level: * bmkt_sec_level:
* Security level values. * Security level values.
*/ */
typedef enum bmkt_sec_level typedef enum bmkt_sec_level {
{
BMKT_SECURITY_LEVEL_LOW = 0x10, BMKT_SECURITY_LEVEL_LOW = 0x10,
BMKT_SECURITY_LEVEL_MEDIUM = 0x40, BMKT_SECURITY_LEVEL_MEDIUM = 0x40,
BMKT_SECURITY_LEVEL_HIGH = 0x60, BMKT_SECURITY_LEVEL_HIGH = 0x60,
} bmkt_sec_level_t; } bmkt_sec_level_t;
/** /**
* bmkt_set_sec_level_resp: * bmkt_set_sec_level_resp:
* Response payload data structure returned by get/set security level operations. * Response payload data structure returned by get/set security level operations.
*/ */
typedef struct bmkt_set_sec_level_resp 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_set_sec_level_resp_t;
/** /**
* bmkt_del_all_users_resp: * bmkt_del_all_users_resp:
* Response payload data structure returned by delete all enrolled users operation. * Response payload data structure returned by delete all enrolled users operation.
*/ */
typedef struct bmkt_del_all_users_resp 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_all_users_resp_t;
/** /**
* bmkt_del_user_resp: * bmkt_del_user_resp:
* Response payload data structure returned by delete enrolled user operation. * Response payload data structure returned by delete enrolled user operation.
*/ */
typedef struct bmkt_del_user_resp 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_del_user_resp_t;
/** /**
* bmkt_enroll_template: * bmkt_enroll_template:
* Structure of enrolled users template record data. * Structure of enrolled users template record data.
*/ */
typedef struct bmkt_enroll_template typedef struct bmkt_enroll_template
{ {
uint8_t user_id_len; /**< Length of user_id string */ uint8_t user_id_len; /**< Length of user_id string */
@ -425,9 +424,9 @@ typedef struct bmkt_enroll_template
} bmkt_enroll_template_t; } bmkt_enroll_template_t;
/** /**
* bmkt_enroll_templates_resp: * bmkt_enroll_templates_resp:
* Response payload data structure returned by get enrolled user list operation. * Response payload data structure returned by get enrolled user list operation.
*/ */
typedef struct bmkt_enroll_templates_resp typedef struct bmkt_enroll_templates_resp
{ {
uint8_t total_query_messages; /**< Total query response messages */ uint8_t total_query_messages; /**< Total query response messages */
@ -436,9 +435,9 @@ typedef struct bmkt_enroll_templates_resp
} bmkt_enroll_templates_resp_t; } bmkt_enroll_templates_resp_t;
/** /**
* bmkt_enrolled_fingers: * bmkt_enrolled_fingers:
* Structure of template record status corresponding to each enrolled finger. * Structure of template record status corresponding to each enrolled finger.
*/ */
typedef struct bmkt_enrolled_fingers typedef struct bmkt_enrolled_fingers
{ {
uint8_t finger_id; /**< ID of enrolled finger */ uint8_t finger_id; /**< ID of enrolled finger */
@ -446,19 +445,20 @@ typedef struct bmkt_enrolled_fingers
} bmkt_enrolled_fingers_t; } bmkt_enrolled_fingers_t;
/** /**
* bmkt_enrolled_fingers_resp: * bmkt_enrolled_fingers_resp:
* Response payload data structure returned by get enrolled fingers operation. * Response payload data structure returned by get enrolled fingers operation.
*/ */
typedef struct bmkt_enrolled_fingers_resp 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_enrolled_fingers_resp_t;
/** /**
* bmkt_response_data_t: * bmkt_response_data_t:
* Union combining all response payload data types. * Union combining all response payload data types.
*/ */
typedef union { typedef union
{
bmkt_init_resp_t init_resp; bmkt_init_resp_t init_resp;
bmkt_enroll_resp_t enroll_resp; bmkt_enroll_resp_t enroll_resp;
bmkt_verify_resp_t verify_resp; bmkt_verify_resp_t verify_resp;
@ -474,10 +474,10 @@ typedef union {
} bmkt_response_data_t; } bmkt_response_data_t;
/** /**
* bmkt_response: * bmkt_response:
* Structure to abstract different response structure types in one API * Structure to abstract different response structure types in one API
* to be used in bmkt_resp_cb_t callback function. * to be used in bmkt_resp_cb_t callback function.
*/ */
typedef struct bmkt_response typedef struct bmkt_response
{ {
int response_id; /**< Response message ID, one of th BMKT_RSP_XXX */ int response_id; /**< Response message ID, one of th BMKT_RSP_XXX */

View file

@ -22,8 +22,7 @@
#include "usb_transport.h" #include "usb_transport.h"
#define BMKT_MAX_PENDING_SESSIONS 2 #define BMKT_MAX_PENDING_SESSIONS 2
typedef enum bmkt_sensor_state typedef enum bmkt_sensor_state {
{
BMKT_SENSOR_STATE_UNINIT = 0, BMKT_SENSOR_STATE_UNINIT = 0,
BMKT_SENSOR_STATE_IDLE, BMKT_SENSOR_STATE_IDLE,
BMKT_SENSOR_STATE_INIT, BMKT_SENSOR_STATE_INIT,
@ -66,15 +65,23 @@ typedef struct bmkt_sensor
bmkt_op_state_t op_state; bmkt_op_state_t op_state;
} bmkt_sensor_t; } bmkt_sensor_t;
int bmkt_sensor_open(bmkt_sensor_t *sensor, int bmkt_sensor_open (bmkt_sensor_t *sensor,
bmkt_general_error_cb_t err_cb, void *err_cb_ctx); bmkt_general_error_cb_t err_cb,
int bmkt_sensor_close(bmkt_sensor_t *sensor); 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, int bmkt_sensor_send_message (bmkt_sensor_t *sensor,
uint8_t *payload, bmkt_resp_cb_t resp_cb, void *resp_data); uint8_t msg_id,
int bmkt_sensor_handle_response(bmkt_sensor_t *sensor, uint8_t *resp_buf, int resp_len, bmkt_msg_resp_t *msg_resp); 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_ */ #endif /* _SENSOR_H_ */

View file

@ -25,9 +25,9 @@
#include "synaptics.h" #include "synaptics.h"
#include "bmkt_message.h" #include "bmkt_message.h"
G_DEFINE_TYPE(FpiDeviceSynaptics, fpi_device_synaptics, FP_TYPE_DEVICE) G_DEFINE_TYPE (FpiDeviceSynaptics, fpi_device_synaptics, FP_TYPE_DEVICE)
static const FpIdEntry id_table [ ] = { static const FpIdEntry id_table[] = {
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0xBD, }, { .vid = SYNAPTICS_VENDOR_ID, .pid = 0xBD, },
{ .vid = 0, .pid = 0, .driver_data = 0 }, /* terminating entry */ { .vid = 0, .pid = 0, .driver_data = 0 }, /* terminating entry */
@ -46,16 +46,18 @@ cmd_recieve_cb (FpiUsbTransfer *transfer,
bmkt_msg_resp_t msg_resp; bmkt_msg_resp_t msg_resp;
bmkt_response_t resp; bmkt_response_t resp;
if (error) { if (error)
{
/* NOTE: assumes timeout should never happen for receiving. */ /* NOTE: assumes timeout should never happen for receiving. */
fpi_ssm_mark_failed (transfer->ssm, error); fpi_ssm_mark_failed (transfer->ssm, error);
return; return;
} }
res = bmkt_parse_message_header(&transfer->buffer[SENSOR_FW_REPLY_HEADER_LEN], res = bmkt_parse_message_header (&transfer->buffer[SENSOR_FW_REPLY_HEADER_LEN],
transfer->actual_length - SENSOR_FW_REPLY_HEADER_LEN, transfer->actual_length - SENSOR_FW_REPLY_HEADER_LEN,
&msg_resp); &msg_resp);
if (res != BMKT_SUCCESS) { if (res != BMKT_SUCCESS)
{
g_warning ("Corrupted message received"); g_warning ("Corrupted message received");
fpi_ssm_mark_failed (transfer->ssm, fpi_ssm_mark_failed (transfer->ssm,
fpi_device_error_new (FP_DEVICE_ERROR_PROTO)); fpi_device_error_new (FP_DEVICE_ERROR_PROTO));
@ -63,19 +65,25 @@ cmd_recieve_cb (FpiUsbTransfer *transfer,
} }
/* Special case events */ /* Special case events */
if (msg_resp.msg_id == BMKT_EVT_FINGER_REPORT) { if (msg_resp.msg_id == BMKT_EVT_FINGER_REPORT)
if (msg_resp.payload_len != 1) { {
if (msg_resp.payload_len != 1)
{
g_warning ("Corrupted finger report received"); g_warning ("Corrupted finger report received");
fpi_ssm_mark_failed (transfer->ssm, fpi_ssm_mark_failed (transfer->ssm,
fpi_device_error_new (FP_DEVICE_ERROR_PROTO)); fpi_device_error_new (FP_DEVICE_ERROR_PROTO));
return; return;
} }
if (msg_resp.payload[0] == 0x01) { if (msg_resp.payload[0] == 0x01)
{
self->finger_on_sensor = TRUE; self->finger_on_sensor = TRUE;
} else { }
else
{
self->finger_on_sensor = FALSE; self->finger_on_sensor = FALSE;
if (self->cmd_complete_on_removal) { if (self->cmd_complete_on_removal)
{
fpi_ssm_mark_completed (transfer->ssm); fpi_ssm_mark_completed (transfer->ssm);
return; return;
} }
@ -87,7 +95,8 @@ cmd_recieve_cb (FpiUsbTransfer *transfer,
} }
res = bmkt_parse_message_payload (&msg_resp, &resp); res = bmkt_parse_message_payload (&msg_resp, &resp);
if (res != BMKT_SUCCESS) { if (res != BMKT_SUCCESS)
{
g_warning ("Could not parse message payload: %i", res); g_warning ("Could not parse message payload: %i", res);
fpi_ssm_mark_failed (transfer->ssm, fpi_ssm_mark_failed (transfer->ssm,
fpi_device_error_new (FP_DEVICE_ERROR_PROTO)); fpi_device_error_new (FP_DEVICE_ERROR_PROTO));
@ -95,14 +104,18 @@ cmd_recieve_cb (FpiUsbTransfer *transfer,
} }
/* Special cancellation handling */ /* Special cancellation handling */
if (resp.response_id == BMKT_RSP_CANCEL_OP_OK || resp.response_id == BMKT_RSP_CANCEL_OP_FAIL) { if (resp.response_id == BMKT_RSP_CANCEL_OP_OK || resp.response_id == BMKT_RSP_CANCEL_OP_FAIL)
if (resp.response_id == BMKT_RSP_CANCEL_OP_OK) { {
if (resp.response_id == BMKT_RSP_CANCEL_OP_OK)
{
fp_dbg ("Received cancellation success resonse"); fp_dbg ("Received cancellation success resonse");
fpi_ssm_mark_failed (transfer->ssm, fpi_ssm_mark_failed (transfer->ssm,
g_error_new_literal (G_IO_ERROR, g_error_new_literal (G_IO_ERROR,
G_IO_ERROR_CANCELLED, G_IO_ERROR_CANCELLED,
"Device reported cancellation of operation")); "Device reported cancellation of operation"));
} else { }
else
{
fp_dbg ("Cancellation failed, this should not happen"); fp_dbg ("Cancellation failed, this should not happen");
fpi_ssm_mark_failed (transfer->ssm, fpi_ssm_mark_failed (transfer->ssm,
fpi_device_error_new (FP_DEVICE_ERROR_PROTO)); fpi_device_error_new (FP_DEVICE_ERROR_PROTO));
@ -110,22 +123,26 @@ cmd_recieve_cb (FpiUsbTransfer *transfer,
return; return;
} }
if (msg_resp.seq_num == 0) { if (msg_resp.seq_num == 0)
{
/* XXX: Should we really abort the command on general error? /* XXX: Should we really abort the command on general error?
* The original code did not! */ * The original code did not! */
if (msg_resp.msg_id == BMKT_RSP_GENERAL_ERROR) { if (msg_resp.msg_id == BMKT_RSP_GENERAL_ERROR)
{
guint16 err; guint16 err;
/* XXX: It is weird that this is big endian. */ /* XXX: It is weird that this is big endian. */
err = FP_READ_UINT16_BE(msg_resp.payload); err = FP_READ_UINT16_BE (msg_resp.payload);
fp_warn("Received General Error %d from the sensor", (guint) err); fp_warn ("Received General Error %d from the sensor", (guint) err);
fpi_ssm_mark_failed (transfer->ssm, fpi_ssm_mark_failed (transfer->ssm,
fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO, fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
"Received general error from device")); "Received general error from device"));
//fpi_ssm_jump_to_state (transfer->ssm, fpi_ssm_get_cur_state (transfer->ssm)); //fpi_ssm_jump_to_state (transfer->ssm, fpi_ssm_get_cur_state (transfer->ssm));
return; return;
} else { }
else
{
fp_dbg ("Received message with 0 sequence number 0x%02x, ignoring!", fp_dbg ("Received message with 0 sequence number 0x%02x, ignoring!",
msg_resp.msg_id); msg_resp.msg_id);
fpi_ssm_next_state (transfer->ssm); fpi_ssm_next_state (transfer->ssm);
@ -135,7 +152,8 @@ cmd_recieve_cb (FpiUsbTransfer *transfer,
/* We should only ever have one command running, and the sequence num needs /* We should only ever have one command running, and the sequence num needs
* to match. */ * to match. */
if (msg_resp.seq_num != self->cmd_seq_num) { if (msg_resp.seq_num != self->cmd_seq_num)
{
fp_warn ("Got unexpected sequence number from device, %d instead of %d", fp_warn ("Got unexpected sequence number from device, %d instead of %d",
msg_resp.seq_num, msg_resp.seq_num,
self->cmd_seq_num); self->cmd_seq_num);
@ -162,8 +180,10 @@ cmd_interrupt_cb (FpiUsbTransfer *transfer,
GError *error) GError *error)
{ {
g_debug ("interrupt transfer done"); g_debug ("interrupt transfer done");
if (error) { if (error)
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { {
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
{
g_error_free (error); g_error_free (error);
fpi_ssm_jump_to_state (transfer->ssm, SYNAPTICS_CMD_GET_RESP); fpi_ssm_jump_to_state (transfer->ssm, SYNAPTICS_CMD_GET_RESP);
return; return;
@ -181,16 +201,18 @@ cmd_interrupt_cb (FpiUsbTransfer *transfer,
} }
static void static void
synaptics_cmd_run_state(FpiSsm *ssm, synaptics_cmd_run_state (FpiSsm *ssm,
FpDevice *dev, FpDevice *dev,
void *user_data) void *user_data)
{ {
g_autoptr(FpiUsbTransfer) transfer = NULL; g_autoptr(FpiUsbTransfer) transfer = NULL;
FpiDeviceSynaptics *self = FPI_DEVICE_SYNAPTICS (dev); FpiDeviceSynaptics *self = FPI_DEVICE_SYNAPTICS (dev);
switch (fpi_ssm_get_cur_state(ssm)) { switch (fpi_ssm_get_cur_state (ssm))
{
case SYNAPTICS_CMD_SEND_PENDING: case SYNAPTICS_CMD_SEND_PENDING:
if (self->cmd_pending_transfer) { if (self->cmd_pending_transfer)
{
self->cmd_pending_transfer->ssm = ssm; self->cmd_pending_transfer->ssm = ssm;
fpi_usb_transfer_submit (self->cmd_pending_transfer, fpi_usb_transfer_submit (self->cmd_pending_transfer,
1000, 1000,
@ -198,7 +220,9 @@ synaptics_cmd_run_state(FpiSsm *ssm,
fpi_ssm_usb_transfer_cb, fpi_ssm_usb_transfer_cb,
NULL); NULL);
g_clear_pointer (&self->cmd_pending_transfer, fpi_usb_transfer_unref); g_clear_pointer (&self->cmd_pending_transfer, fpi_usb_transfer_unref);
} else { }
else
{
fpi_ssm_next_state (ssm); fpi_ssm_next_state (ssm);
} }
break; break;
@ -258,9 +282,12 @@ cmd_ssm_done (FpiSsm *ssm,
self->cmd_ssm = NULL; self->cmd_ssm = NULL;
/* Notify about the SSM failure from here instead. */ /* Notify about the SSM failure from here instead. */
if (error) { if (error)
{
callback (self, NULL, error); callback (self, NULL, error);
} else if (self->cmd_complete_on_removal) { }
else if (self->cmd_complete_on_removal)
{
callback (self, NULL, self->cmd_complete_error); callback (self, NULL, self->cmd_complete_error);
self->cmd_complete_error = NULL; self->cmd_complete_error = NULL;
} }
@ -275,10 +302,13 @@ cmd_forget_cb (FpiUsbTransfer *transfer,
gpointer user_data, gpointer user_data,
GError *error) GError *error)
{ {
if (error) { if (error)
{
g_warning ("Async command sending failed: %s", error->message); g_warning ("Async command sending failed: %s", error->message);
g_error_free (error); g_error_free (error);
} else { }
else
{
g_debug ("Async command sent successfully"); g_debug ("Async command sent successfully");
} }
} }
@ -287,7 +317,7 @@ static void
synaptics_sensor_cmd (FpiDeviceSynaptics *self, synaptics_sensor_cmd (FpiDeviceSynaptics *self,
gint seq_num, gint seq_num,
guint8 msg_id, guint8 msg_id,
const guint8* payload, const guint8 * payload,
gssize payload_len, gssize payload_len,
SynCmdMsgCallback callback) SynCmdMsgCallback callback)
{ {
@ -304,12 +334,15 @@ synaptics_sensor_cmd (FpiDeviceSynaptics *self,
/* seq_num of 0 means a normal command, -1 means the current commands /* seq_num of 0 means a normal command, -1 means the current commands
* sequence number should not be udpated (i.e. second async command which * sequence number should not be udpated (i.e. second async command which
* may only be a cancellation currently). */ * may only be a cancellation currently). */
if (seq_num <= 0) { if (seq_num <= 0)
self->last_seq_num = MAX(1, self->last_seq_num + 1); {
self->last_seq_num = MAX (1, self->last_seq_num + 1);
real_seq_num = self->last_seq_num; real_seq_num = self->last_seq_num;
if (seq_num == 0) if (seq_num == 0)
self->cmd_seq_num = self->last_seq_num; self->cmd_seq_num = self->last_seq_num;
} else { }
else
{
real_seq_num = seq_num; real_seq_num = seq_num;
self->last_seq_num = real_seq_num; self->last_seq_num = real_seq_num;
} }
@ -338,23 +371,29 @@ synaptics_sensor_cmd (FpiDeviceSynaptics *self,
/* Special case for async command sending (should only be used for /* Special case for async command sending (should only be used for
* cancellation). */ * cancellation). */
if (seq_num == -1) { if (seq_num == -1)
g_assert(callback == NULL); {
g_assert (callback == NULL);
/* We just send and forget here. */ /* We just send and forget here. */
fpi_usb_transfer_submit (transfer, 1000, NULL, cmd_forget_cb, NULL); fpi_usb_transfer_submit (transfer, 1000, NULL, cmd_forget_cb, NULL);
} else { }
else
{
/* Command should be send using the state machine. */ /* Command should be send using the state machine. */
g_assert (self->cmd_pending_transfer == NULL); g_assert (self->cmd_pending_transfer == NULL);
self->cmd_pending_transfer = g_steal_pointer (&transfer); self->cmd_pending_transfer = g_steal_pointer (&transfer);
if (self->cmd_ssm) { if (self->cmd_ssm)
{
/* Continued command, we already have an SSM with a callback. /* Continued command, we already have an SSM with a callback.
* There is nothing to do in this case, the command will be * There is nothing to do in this case, the command will be
* sent automatically. */ * sent automatically. */
g_assert (callback == NULL); g_assert (callback == NULL);
} else { }
else
{
/* Start of a new command, create the state machine. */ /* Start of a new command, create the state machine. */
g_assert (callback != NULL); g_assert (callback != NULL);
@ -387,7 +426,7 @@ parse_print_data (GVariant *data,
if (!g_variant_check_format_string (data, "(y@ay)", FALSE)) if (!g_variant_check_format_string (data, "(y@ay)", FALSE))
return FALSE; return FALSE;
g_variant_get(data, g_variant_get (data,
"(y@ay)", "(y@ay)",
finger, finger,
&user_id_var); &user_id_var);
@ -404,13 +443,14 @@ parse_print_data (GVariant *data,
} }
static void static void
list_msg_cb(FpiDeviceSynaptics *self, list_msg_cb (FpiDeviceSynaptics *self,
bmkt_response_t *resp, bmkt_response_t *resp,
GError *error) GError *error)
{ {
bmkt_enroll_templates_resp_t *get_enroll_templates_resp; bmkt_enroll_templates_resp_t *get_enroll_templates_resp;
if (error) { if (error)
{
g_clear_pointer (&self->list_result, g_ptr_array_free); g_clear_pointer (&self->list_result, g_ptr_array_free);
fpi_device_list_complete (FP_DEVICE (self), NULL, error); fpi_device_list_complete (FP_DEVICE (self), NULL, error);
return; return;
@ -421,14 +461,17 @@ list_msg_cb(FpiDeviceSynaptics *self,
switch (resp->response_id) switch (resp->response_id)
{ {
case BMKT_RSP_QUERY_FAIL: case BMKT_RSP_QUERY_FAIL:
if (resp->result == BMKT_FP_DATABASE_EMPTY) { if (resp->result == BMKT_FP_DATABASE_EMPTY)
fp_info("Database is empty"); {
fp_info ("Database is empty");
fpi_device_list_complete (FP_DEVICE (self), fpi_device_list_complete (FP_DEVICE (self),
g_steal_pointer (&self->list_result), g_steal_pointer (&self->list_result),
NULL); NULL);
} else { }
fp_info("Failed to query enrolled users: %d", resp->result); else
{
fp_info ("Failed to query enrolled users: %d", resp->result);
g_clear_pointer (&self->list_result, g_ptr_array_free); g_clear_pointer (&self->list_result, g_ptr_array_free);
fpi_device_list_complete (FP_DEVICE (self), fpi_device_list_complete (FP_DEVICE (self),
NULL, NULL,
@ -436,14 +479,16 @@ list_msg_cb(FpiDeviceSynaptics *self,
"Failed to query enrolled users")); "Failed to query enrolled users"));
} }
break; break;
case BMKT_RSP_QUERY_RESPONSE_COMPLETE: case BMKT_RSP_QUERY_RESPONSE_COMPLETE:
fp_info("Query complete!"); fp_info ("Query complete!");
fpi_device_list_complete (FP_DEVICE (self), fpi_device_list_complete (FP_DEVICE (self),
g_steal_pointer (&self->list_result), g_steal_pointer (&self->list_result),
NULL); NULL);
break; break;
case BMKT_RSP_TEMPLATE_RECORDS_REPORT: case BMKT_RSP_TEMPLATE_RECORDS_REPORT:
for (int n = 0; n < BMKT_MAX_NUM_TEMPLATES_INTERNAL_FLASH; n++) for (int n = 0; n < BMKT_MAX_NUM_TEMPLATES_INTERNAL_FLASH; n++)
@ -456,7 +501,7 @@ list_msg_cb(FpiDeviceSynaptics *self,
if (get_enroll_templates_resp->templates[n].user_id_len == 0) if (get_enroll_templates_resp->templates[n].user_id_len == 0)
continue; continue;
fp_info("![query %d of %d] template %d: status=0x%x, userId=%s, fingerId=%d", fp_info ("![query %d of %d] template %d: status=0x%x, userId=%s, fingerId=%d",
get_enroll_templates_resp->query_sequence, get_enroll_templates_resp->query_sequence,
get_enroll_templates_resp->total_query_messages, get_enroll_templates_resp->total_query_messages,
n, n,
@ -481,9 +526,10 @@ list_msg_cb(FpiDeviceSynaptics *self,
g_object_set (print, "description", get_enroll_templates_resp->templates[n].user_id, NULL); g_object_set (print, "description", get_enroll_templates_resp->templates[n].user_id, NULL);
/* The format has 24 bytes at the start and some dashes in the right places */ /* The format has 24 bytes at the start and some dashes in the right places */
if (g_str_has_prefix (userid, "FP1-") && strlen(userid) >= 24 && if (g_str_has_prefix (userid, "FP1-") && strlen (userid) >= 24 &&
userid[12] == '-' && userid[14] == '-' && userid[23] == '-') { userid[12] == '-' && userid[14] == '-' && userid[23] == '-')
g_autofree gchar *copy = g_strdup(userid); {
g_autofree gchar *copy = g_strdup (userid);
gint32 date_ymd; gint32 date_ymd;
GDate *date = NULL; GDate *date = NULL;
gint32 finger; gint32 finger;
@ -510,7 +556,7 @@ list_msg_cb(FpiDeviceSynaptics *self,
* Then comes the username; nobody is the default if the metadata * Then comes the username; nobody is the default if the metadata
* is unknown */ * is unknown */
username = copy + 24; username = copy + 24;
if (strlen(username) > 0 && g_strcmp0 (username, "nobody") != 0) if (strlen (username) > 0 && g_strcmp0 (username, "nobody") != 0)
fp_print_set_username (print, username); fp_print_set_username (print, username);
} }
@ -529,30 +575,32 @@ list_msg_cb(FpiDeviceSynaptics *self,
} }
static void static void
list(FpDevice *device) list (FpDevice *device)
{ {
FpiDeviceSynaptics *self = FPI_DEVICE_SYNAPTICS (device); FpiDeviceSynaptics *self = FPI_DEVICE_SYNAPTICS (device);
G_DEBUG_HERE(); G_DEBUG_HERE ();
self->list_result = g_ptr_array_new_with_free_func (g_object_unref); self->list_result = g_ptr_array_new_with_free_func (g_object_unref);
synaptics_sensor_cmd (self, 0, BMKT_CMD_GET_TEMPLATE_RECORDS, NULL, 0, list_msg_cb); synaptics_sensor_cmd (self, 0, BMKT_CMD_GET_TEMPLATE_RECORDS, NULL, 0, list_msg_cb);
} }
static void static void
verify_msg_cb(FpiDeviceSynaptics *self, verify_msg_cb (FpiDeviceSynaptics *self,
bmkt_response_t *resp, bmkt_response_t *resp,
GError *error) GError *error)
{ {
FpDevice *device = FP_DEVICE (self); FpDevice *device = FP_DEVICE (self);
bmkt_verify_resp_t *verify_resp; bmkt_verify_resp_t *verify_resp;
if (error) { if (error)
{
fpi_device_verify_complete (device, FPI_MATCH_ERROR, NULL, error); fpi_device_verify_complete (device, FPI_MATCH_ERROR, NULL, error);
return; return;
} }
if (resp == NULL && self->cmd_complete_on_removal) { if (resp == NULL && self->cmd_complete_on_removal)
{
fpi_device_verify_complete (device, fpi_device_verify_complete (device,
GPOINTER_TO_INT (self->cmd_complete_data), GPOINTER_TO_INT (self->cmd_complete_data),
NULL, NULL,
@ -565,38 +613,45 @@ verify_msg_cb(FpiDeviceSynaptics *self,
switch (resp->response_id) switch (resp->response_id)
{ {
case BMKT_RSP_VERIFY_READY: case BMKT_RSP_VERIFY_READY:
fp_info("Place Finger on the Sensor!"); fp_info ("Place Finger on the Sensor!");
break; break;
case BMKT_RSP_CAPTURE_COMPLETE: case BMKT_RSP_CAPTURE_COMPLETE:
fp_info("Fingerprint image capture complete!"); fp_info ("Fingerprint image capture complete!");
break; break;
case BMKT_RSP_VERIFY_FAIL: case BMKT_RSP_VERIFY_FAIL:
if(resp->result == BMKT_SENSOR_STIMULUS_ERROR) { if(resp->result == BMKT_SENSOR_STIMULUS_ERROR)
{
fp_dbg ("delaying retry error until after finger removal!"); fp_dbg ("delaying retry error until after finger removal!");
self->cmd_complete_on_removal = TRUE; self->cmd_complete_on_removal = TRUE;
self->cmd_complete_data = GINT_TO_POINTER (FPI_MATCH_ERROR); self->cmd_complete_data = GINT_TO_POINTER (FPI_MATCH_ERROR);
self->cmd_complete_error = fpi_device_retry_new (FP_DEVICE_RETRY_GENERAL); self->cmd_complete_error = fpi_device_retry_new (FP_DEVICE_RETRY_GENERAL);
} else if (resp->result == BMKT_FP_NO_MATCH) { }
else if (resp->result == BMKT_FP_NO_MATCH)
{
fp_dbg ("delaying match failure until after finger removal!"); fp_dbg ("delaying match failure until after finger removal!");
self->cmd_complete_on_removal = TRUE; self->cmd_complete_on_removal = TRUE;
self->cmd_complete_data = GINT_TO_POINTER (FPI_MATCH_FAIL); self->cmd_complete_data = GINT_TO_POINTER (FPI_MATCH_FAIL);
self->cmd_complete_error = NULL; self->cmd_complete_error = NULL;
} else if (BMKT_FP_DATABASE_NO_RECORD_EXISTS) { }
fp_info("Print is not in database"); else if (BMKT_FP_DATABASE_NO_RECORD_EXISTS)
{
fp_info ("Print is not in database");
fpi_device_verify_complete (device, fpi_device_verify_complete (device,
FPI_MATCH_ERROR, FPI_MATCH_ERROR,
NULL, NULL,
fpi_device_error_new (FP_DEVICE_ERROR_DATA_NOT_FOUND)); fpi_device_error_new (FP_DEVICE_ERROR_DATA_NOT_FOUND));
} else { }
fp_warn("Verify has failed: %d", resp->result); else
{
fp_warn ("Verify has failed: %d", resp->result);
fpi_device_verify_complete (device, FPI_MATCH_FAIL, NULL, NULL); fpi_device_verify_complete (device, FPI_MATCH_FAIL, NULL, NULL);
} }
break; break;
case BMKT_RSP_VERIFY_OK: case BMKT_RSP_VERIFY_OK:
fp_info("Verify was successful! for user: %s finger: %d score: %f", fp_info ("Verify was successful! for user: %s finger: %d score: %f",
verify_resp->user_id, verify_resp->finger_id, verify_resp->match_result); verify_resp->user_id, verify_resp->finger_id, verify_resp->match_result);
fpi_device_verify_complete (device, FPI_MATCH_SUCCESS, NULL, NULL); fpi_device_verify_complete (device, FPI_MATCH_SUCCESS, NULL, NULL);
break; break;
@ -604,10 +659,11 @@ verify_msg_cb(FpiDeviceSynaptics *self,
} }
static void static void
verify(FpDevice *device) verify (FpDevice *device)
{ {
FpiDeviceSynaptics *self = FPI_DEVICE_SYNAPTICS (device); FpiDeviceSynaptics *self = FPI_DEVICE_SYNAPTICS (device);
FpPrint *print = NULL; FpPrint *print = NULL;
g_autoptr(GVariant) data = NULL; g_autoptr(GVariant) data = NULL;
guint8 finger; guint8 finger;
const guint8 *user_id; const guint8 *user_id;
@ -617,7 +673,8 @@ verify(FpDevice *device)
g_object_get (print, "fp-data", &data, NULL); g_object_get (print, "fp-data", &data, NULL);
g_debug ("data is %p", data); g_debug ("data is %p", data);
if (!parse_print_data (data, &finger, &user_id, &user_id_len)) { if (!parse_print_data (data, &finger, &user_id, &user_id_len))
{
fpi_device_verify_complete (device, fpi_device_verify_complete (device,
FPI_MATCH_ERROR, FPI_MATCH_ERROR,
NULL, NULL,
@ -625,20 +682,21 @@ verify(FpDevice *device)
return; return;
} }
G_DEBUG_HERE(); G_DEBUG_HERE ();
synaptics_sensor_cmd (self, 0, BMKT_CMD_VERIFY_USER, user_id, user_id_len, verify_msg_cb); synaptics_sensor_cmd (self, 0, BMKT_CMD_VERIFY_USER, user_id, user_id_len, verify_msg_cb);
} }
static void static void
enroll_msg_cb(FpiDeviceSynaptics *self, enroll_msg_cb (FpiDeviceSynaptics *self,
bmkt_response_t *resp, bmkt_response_t *resp,
GError *error) GError *error)
{ {
FpDevice *device = FP_DEVICE (self); FpDevice *device = FP_DEVICE (self);
bmkt_enroll_resp_t *enroll_resp; bmkt_enroll_resp_t *enroll_resp;
if (error) { if (error)
{
fpi_device_enroll_complete (device, NULL, error); fpi_device_enroll_complete (device, NULL, error);
return; return;
} }
@ -650,67 +708,80 @@ enroll_msg_cb(FpiDeviceSynaptics *self,
case BMKT_RSP_ENROLL_READY: case BMKT_RSP_ENROLL_READY:
{ {
self->enroll_stage = 0; self->enroll_stage = 0;
fp_info("Place Finger on the Sensor!"); fp_info ("Place Finger on the Sensor!");
break; break;
} }
case BMKT_RSP_CAPTURE_COMPLETE: case BMKT_RSP_CAPTURE_COMPLETE:
{ {
fp_info("Fingerprint image capture complete!"); fp_info ("Fingerprint image capture complete!");
break; break;
} }
case BMKT_RSP_ENROLL_REPORT: case BMKT_RSP_ENROLL_REPORT:
{ {
gint done_stages; gint done_stages;
fp_info("Enrollment is %d %% ", enroll_resp->progress); fp_info ("Enrollment is %d %% ", enroll_resp->progress);
done_stages = (enroll_resp->progress * ENROLL_SAMPLES + 99) / 100; done_stages = (enroll_resp->progress * ENROLL_SAMPLES + 99) / 100;
if (enroll_resp->progress < 100) if (enroll_resp->progress < 100)
done_stages = MIN(done_stages, ENROLL_SAMPLES - 1); done_stages = MIN (done_stages, ENROLL_SAMPLES - 1);
/* Emit a retry error if there has been no discernable /* Emit a retry error if there has been no discernable
* progress. Some firmware revisions report more required * progress. Some firmware revisions report more required
* touches. */ * touches. */
if (self->enroll_stage == done_stages) if (self->enroll_stage == done_stages)
{
fpi_device_enroll_progress (device, fpi_device_enroll_progress (device,
done_stages, done_stages,
NULL, NULL,
fpi_device_retry_new (FP_DEVICE_RETRY_GENERAL)); fpi_device_retry_new (FP_DEVICE_RETRY_GENERAL));
}
while (self->enroll_stage < done_stages) { while (self->enroll_stage < done_stages)
{
self->enroll_stage += 1; self->enroll_stage += 1;
fpi_device_enroll_progress (device, self->enroll_stage, NULL, NULL); fpi_device_enroll_progress (device, self->enroll_stage, NULL, NULL);
} }
break; break;
} }
case BMKT_RSP_ENROLL_PAUSED: case BMKT_RSP_ENROLL_PAUSED:
{ {
fp_info("Enrollment has been paused!"); fp_info ("Enrollment has been paused!");
break; break;
} }
case BMKT_RSP_ENROLL_RESUMED: case BMKT_RSP_ENROLL_RESUMED:
{ {
fp_info("Enrollment has been resumed!"); fp_info ("Enrollment has been resumed!");
break; break;
} }
case BMKT_RSP_ENROLL_FAIL: case BMKT_RSP_ENROLL_FAIL:
{ {
fp_info("Enrollment has failed!: %d", resp->result); fp_info ("Enrollment has failed!: %d", resp->result);
if (resp->result == BMKT_FP_DATABASE_FULL) if (resp->result == BMKT_FP_DATABASE_FULL)
{
fpi_device_enroll_complete (device, fpi_device_enroll_complete (device,
NULL, NULL,
fpi_device_error_new (FP_DEVICE_ERROR_DATA_FULL)); fpi_device_error_new (FP_DEVICE_ERROR_DATA_FULL));
}
else else
{
fpi_device_enroll_complete (device, fpi_device_enroll_complete (device,
NULL, NULL,
fpi_device_error_new_msg (FP_DEVICE_ERROR_GENERAL, fpi_device_error_new_msg (FP_DEVICE_ERROR_GENERAL,
"Enrollment failed")); "Enrollment failed"));
}
break; break;
} }
case BMKT_RSP_ENROLL_OK: case BMKT_RSP_ENROLL_OK:
{ {
FpPrint *print = NULL; FpPrint *print = NULL;
fp_info("Enrollment was successful!"); fp_info ("Enrollment was successful!");
fpi_device_get_enroll_data (device, &print); fpi_device_get_enroll_data (device, &print);
@ -723,7 +794,7 @@ enroll_msg_cb(FpiDeviceSynaptics *self,
#define TEMPLATE_ID_SIZE 20 #define TEMPLATE_ID_SIZE 20
static void static void
enroll(FpDevice *device) enroll (FpDevice *device)
{ {
FpiDeviceSynaptics *self = FPI_DEVICE_SYNAPTICS (device); FpiDeviceSynaptics *self = FPI_DEVICE_SYNAPTICS (device);
FpPrint *print = NULL; FpPrint *print = NULL;
@ -740,14 +811,17 @@ enroll(FpDevice *device)
fpi_device_get_enroll_data (device, &print); fpi_device_get_enroll_data (device, &print);
G_DEBUG_HERE(); G_DEBUG_HERE ();
date = fp_print_get_enroll_date (print); date = fp_print_get_enroll_date (print);
if (date && g_date_valid (date)) { if (date && g_date_valid (date))
{
y = date->year; y = date->year;
m = date->month; m = date->month;
d = date->day; d = date->day;
} else { }
else
{
y = 0; y = 0;
m = 0; m = 0;
d = 0; d = 0;
@ -760,7 +834,7 @@ enroll(FpDevice *device)
if (g_strcmp0 (g_getenv ("FP_DEVICE_EMULATION"), "1") == 0) if (g_strcmp0 (g_getenv ("FP_DEVICE_EMULATION"), "1") == 0)
rand_id = 0; rand_id = 0;
else else
rand_id = g_random_int(); rand_id = g_random_int ();
user_id = g_strdup_printf ("FP1-%04d%02d%02d-%X-%08X-%s", user_id = g_strdup_printf ("FP1-%04d%02d%02d-%X-%08X-%s",
y, m, d, y, m, d,
@ -769,7 +843,7 @@ enroll(FpDevice *device)
username); username);
user_id_len = strlen (user_id); user_id_len = strlen (user_id);
user_id_len = MIN(BMKT_MAX_USER_ID_LEN, user_id_len); user_id_len = MIN (BMKT_MAX_USER_ID_LEN, user_id_len);
/* We currently always use finger 1 from the devices piont of view */ /* We currently always use finger 1 from the devices piont of view */
finger = 1; finger = 1;
@ -787,9 +861,9 @@ enroll(FpDevice *device)
g_object_set (print, "fp-data", data, NULL); g_object_set (print, "fp-data", data, NULL);
g_object_set (print, "description", user_id, NULL); g_object_set (print, "description", user_id, NULL);
g_debug("user_id: %s, finger: %d", user_id, finger); g_debug ("user_id: %s, finger: %d", user_id, finger);
payload = g_malloc0(user_id_len + 2); payload = g_malloc0 (user_id_len + 2);
/* Backup options are not supported for Prometheus */ /* Backup options are not supported for Prometheus */
payload[0] = 0; payload[0] = 0;
@ -800,14 +874,15 @@ enroll(FpDevice *device)
} }
static void static void
delete_msg_cb(FpiDeviceSynaptics *self, delete_msg_cb (FpiDeviceSynaptics *self,
bmkt_response_t *resp, bmkt_response_t *resp,
GError *error) GError *error)
{ {
FpDevice *device = FP_DEVICE (self); FpDevice *device = FP_DEVICE (self);
bmkt_del_user_resp_t *del_user_resp; bmkt_del_user_resp_t *del_user_resp;
if (error) { if (error)
{
fpi_device_delete_complete (device, error); fpi_device_delete_complete (device, error);
return; return;
} }
@ -817,11 +892,12 @@ delete_msg_cb(FpiDeviceSynaptics *self,
switch (resp->response_id) switch (resp->response_id)
{ {
case BMKT_RSP_DELETE_PROGRESS: case BMKT_RSP_DELETE_PROGRESS:
fp_info("Deleting Enrolled Users is %d%% complete", fp_info ("Deleting Enrolled Users is %d%% complete",
del_user_resp->progress); del_user_resp->progress);
break; break;
case BMKT_RSP_DEL_USER_FP_FAIL: case BMKT_RSP_DEL_USER_FP_FAIL:
fp_info("Failed to delete enrolled user: %d", resp->result); fp_info ("Failed to delete enrolled user: %d", resp->result);
if (resp->result == BMKT_FP_DATABASE_NO_RECORD_EXISTS) if (resp->result == BMKT_FP_DATABASE_NO_RECORD_EXISTS)
fpi_device_delete_complete (device, fpi_device_delete_complete (device,
fpi_device_error_new (FP_DEVICE_ERROR_DATA_NOT_FOUND)); fpi_device_error_new (FP_DEVICE_ERROR_DATA_NOT_FOUND));
@ -829,18 +905,20 @@ delete_msg_cb(FpiDeviceSynaptics *self,
fpi_device_delete_complete (device, fpi_device_delete_complete (device,
fpi_device_error_new (FP_DEVICE_ERROR_GENERAL)); fpi_device_error_new (FP_DEVICE_ERROR_GENERAL));
break; break;
case BMKT_RSP_DEL_USER_FP_OK: case BMKT_RSP_DEL_USER_FP_OK:
fp_info("Successfully deleted enrolled user"); fp_info ("Successfully deleted enrolled user");
fpi_device_delete_complete (device, NULL); fpi_device_delete_complete (device, NULL);
break; break;
} }
} }
static void static void
delete_print(FpDevice *device) delete_print (FpDevice *device)
{ {
FpiDeviceSynaptics *self = FPI_DEVICE_SYNAPTICS (device); FpiDeviceSynaptics *self = FPI_DEVICE_SYNAPTICS (device);
FpPrint *print = NULL; FpPrint *print = NULL;
g_autoptr(GVariant) data = NULL; g_autoptr(GVariant) data = NULL;
guint8 finger; guint8 finger;
const guint8 *user_id; const guint8 *user_id;
@ -851,13 +929,14 @@ delete_print(FpDevice *device)
g_object_get (print, "fp-data", &data, NULL); g_object_get (print, "fp-data", &data, NULL);
g_debug ("data is %p", data); g_debug ("data is %p", data);
if (!parse_print_data (data, &finger, &user_id, &user_id_len)) { if (!parse_print_data (data, &finger, &user_id, &user_id_len))
{
fpi_device_delete_complete (device, fpi_device_delete_complete (device,
fpi_device_error_new (FP_DEVICE_ERROR_DATA_INVALID)); fpi_device_error_new (FP_DEVICE_ERROR_DATA_INVALID));
return; return;
} }
G_DEBUG_HERE(); G_DEBUG_HERE ();
payload = g_malloc0 (1 + user_id_len); payload = g_malloc0 (1 + user_id_len);
payload[0] = finger; payload[0] = finger;
@ -867,7 +946,7 @@ delete_print(FpDevice *device)
} }
static void static void
dev_probe(FpDevice *device) dev_probe (FpDevice *device)
{ {
FpiDeviceSynaptics *self = FPI_DEVICE_SYNAPTICS (device); FpiDeviceSynaptics *self = FPI_DEVICE_SYNAPTICS (device);
GUsbDevice *usb_dev; GUsbDevice *usb_dev;
@ -879,21 +958,23 @@ dev_probe(FpDevice *device)
gboolean read_ok = TRUE; gboolean read_ok = TRUE;
g_autofree gchar *serial = NULL; g_autofree gchar *serial = NULL;
G_DEBUG_HERE(); G_DEBUG_HERE ();
/* Claim usb interface */ /* Claim usb interface */
usb_dev = fpi_device_get_usb_device(device); usb_dev = fpi_device_get_usb_device (device);
if (!g_usb_device_open (usb_dev, &error)) { if (!g_usb_device_open (usb_dev, &error))
{
fpi_device_probe_complete (device, NULL, NULL, error); fpi_device_probe_complete (device, NULL, NULL, error);
return; return;
} }
if (!g_usb_device_reset (fpi_device_get_usb_device (device), &error)) { if (!g_usb_device_reset (fpi_device_get_usb_device (device), &error))
{
fpi_device_probe_complete (device, NULL, NULL, error); fpi_device_probe_complete (device, NULL, NULL, error);
return; return;
} }
if (!g_usb_device_claim_interface (fpi_device_get_usb_device(device), 0, 0, &error)) if (!g_usb_device_claim_interface (fpi_device_get_usb_device (device), 0, 0, &error))
goto err_close; goto err_close;
/* TODO: Do not do this synchronous. */ /* TODO: Do not do this synchronous. */
@ -913,12 +994,14 @@ dev_probe(FpDevice *device)
fpi_byte_reader_init (&reader, transfer->buffer, transfer->actual_length); fpi_byte_reader_init (&reader, transfer->buffer, transfer->actual_length);
if (!fpi_byte_reader_get_uint16_le (&reader, &status)) { if (!fpi_byte_reader_get_uint16_le (&reader, &status))
{
g_warning ("Transfer in response to version query was too short"); g_warning ("Transfer in response to version query was too short");
error = fpi_device_error_new (FP_DEVICE_ERROR_PROTO); error = fpi_device_error_new (FP_DEVICE_ERROR_PROTO);
goto err_close; goto err_close;
} }
if (status != 0) { if (status != 0)
{
g_warning ("Device responded with error: %d", status); g_warning ("Device responded with error: %d", status);
error = fpi_device_error_new (FP_DEVICE_ERROR_PROTO); error = fpi_device_error_new (FP_DEVICE_ERROR_PROTO);
goto err_close; goto err_close;
@ -935,25 +1018,26 @@ dev_probe(FpDevice *device)
read_ok &= fpi_byte_reader_get_uint8 (&reader, &self->mis_version.formal_release); read_ok &= fpi_byte_reader_get_uint8 (&reader, &self->mis_version.formal_release);
read_ok &= fpi_byte_reader_get_uint8 (&reader, &self->mis_version.platform); read_ok &= fpi_byte_reader_get_uint8 (&reader, &self->mis_version.platform);
read_ok &= fpi_byte_reader_get_uint8 (&reader, &self->mis_version.patch); read_ok &= fpi_byte_reader_get_uint8 (&reader, &self->mis_version.patch);
if (fpi_byte_reader_get_data (&reader, sizeof(self->mis_version.serial_number), &data)) if (fpi_byte_reader_get_data (&reader, sizeof (self->mis_version.serial_number), &data))
memcpy (self->mis_version.serial_number, data, sizeof(self->mis_version.serial_number)); memcpy (self->mis_version.serial_number, data, sizeof (self->mis_version.serial_number));
else else
read_ok = FALSE; read_ok = FALSE;
read_ok &= fpi_byte_reader_get_uint16_le (&reader, &self->mis_version.security); read_ok &= fpi_byte_reader_get_uint16_le (&reader, &self->mis_version.security);
read_ok &= fpi_byte_reader_get_uint8 (&reader, &self->mis_version.iface); read_ok &= fpi_byte_reader_get_uint8 (&reader, &self->mis_version.iface);
read_ok &= fpi_byte_reader_get_uint8 (&reader, &self->mis_version.device_type); read_ok &= fpi_byte_reader_get_uint8 (&reader, &self->mis_version.device_type);
if (!read_ok) { if (!read_ok)
{
g_warning ("Transfer in response to verison query was too short"); g_warning ("Transfer in response to verison query was too short");
error = fpi_device_error_new (FP_DEVICE_ERROR_PROTO); error = fpi_device_error_new (FP_DEVICE_ERROR_PROTO);
goto err_close; goto err_close;
} }
fp_dbg("Build Time: %d", self->mis_version.build_time); fp_dbg ("Build Time: %d", self->mis_version.build_time);
fp_dbg("Build Num: %d", self->mis_version.build_num); fp_dbg ("Build Num: %d", self->mis_version.build_num);
fp_dbg("Version: %d.%d", self->mis_version.version_major, self->mis_version.version_minor); fp_dbg ("Version: %d.%d", self->mis_version.version_major, self->mis_version.version_minor);
fp_dbg("Target: %d", self->mis_version.target); fp_dbg ("Target: %d", self->mis_version.target);
fp_dbg("Product: %d", self->mis_version.product); fp_dbg ("Product: %d", self->mis_version.product);
fpi_usb_transfer_unref (transfer); fpi_usb_transfer_unref (transfer);
@ -995,48 +1079,55 @@ err_close:
} }
static void static void
fps_init_msg_cb(FpiDeviceSynaptics *self, fps_init_msg_cb (FpiDeviceSynaptics *self,
bmkt_response_t *resp, bmkt_response_t *resp,
GError *error) GError *error)
{ {
if (error) { if (error)
{
fpi_device_open_complete (FP_DEVICE (self), error); fpi_device_open_complete (FP_DEVICE (self), error);
return; return;
} }
/* BMKT_OPERATION_DENIED is returned if the sensor is already initialized */ /* BMKT_OPERATION_DENIED is returned if the sensor is already initialized */
if (resp->result == BMKT_SUCCESS || resp->result == BMKT_OPERATION_DENIED) { if (resp->result == BMKT_SUCCESS || resp->result == BMKT_OPERATION_DENIED)
{
fpi_device_open_complete (FP_DEVICE (self), NULL); fpi_device_open_complete (FP_DEVICE (self), NULL);
} else { }
else
{
g_warning ("Initializing fingerprint sensor failed with %d!", resp->result); g_warning ("Initializing fingerprint sensor failed with %d!", resp->result);
fpi_device_open_complete (FP_DEVICE (self), fpi_device_open_complete (FP_DEVICE (self),
fpi_device_error_new (FP_DEVICE_ERROR_GENERAL)); fpi_device_error_new (FP_DEVICE_ERROR_GENERAL));
} }
} }
static void static void
fps_deinit_cb(FpiDeviceSynaptics *self, fps_deinit_cb (FpiDeviceSynaptics *self,
bmkt_response_t *resp, bmkt_response_t *resp,
GError *error) GError *error)
{ {
/* Release usb interface */ /* Release usb interface */
g_usb_device_release_interface(fpi_device_get_usb_device(FP_DEVICE (self)), 0, 0, &error); g_usb_device_release_interface (fpi_device_get_usb_device (FP_DEVICE (self)), 0, 0, &error);
g_clear_object (&self->interrupt_cancellable); g_clear_object (&self->interrupt_cancellable);
if (!error) { if (!error)
switch (resp->response_id) { {
switch (resp->response_id)
{
case BMKT_RSP_POWER_DOWN_READY: case BMKT_RSP_POWER_DOWN_READY:
fp_info("Fingerprint sensor ready to be powered down"); fp_info ("Fingerprint sensor ready to be powered down");
break; break;
case BMKT_RSP_POWER_DOWN_FAIL: case BMKT_RSP_POWER_DOWN_FAIL:
fp_info("Failed to go to power down mode: %d", resp->result); fp_info ("Failed to go to power down mode: %d", resp->result);
error = fpi_device_error_new_msg (FP_DEVICE_ERROR_GENERAL, error = fpi_device_error_new_msg (FP_DEVICE_ERROR_GENERAL,
"Power down failed"); "Power down failed");
break; break;
} }
} }
fpi_device_close_complete(FP_DEVICE (self), error); fpi_device_close_complete (FP_DEVICE (self), error);
} }
static void static void
@ -1045,7 +1136,7 @@ dev_init (FpDevice *device)
FpiDeviceSynaptics *self = FPI_DEVICE_SYNAPTICS (device); FpiDeviceSynaptics *self = FPI_DEVICE_SYNAPTICS (device);
GError *error = NULL; GError *error = NULL;
G_DEBUG_HERE(); G_DEBUG_HERE ();
self->interrupt_cancellable = g_cancellable_new (); self->interrupt_cancellable = g_cancellable_new ();
@ -1065,19 +1156,19 @@ error:
} }
static void static void
dev_exit(FpDevice *device) dev_exit (FpDevice *device)
{ {
FpiDeviceSynaptics *self = FPI_DEVICE_SYNAPTICS (device); FpiDeviceSynaptics *self = FPI_DEVICE_SYNAPTICS (device);
G_DEBUG_HERE(); G_DEBUG_HERE ();
synaptics_sensor_cmd (self, 0, BMKT_CMD_POWER_DOWN_NOTIFY, NULL, 0, fps_deinit_cb); synaptics_sensor_cmd (self, 0, BMKT_CMD_POWER_DOWN_NOTIFY, NULL, 0, fps_deinit_cb);
} }
static void static void
cancel(FpDevice *dev) cancel (FpDevice *dev)
{ {
FpiDeviceSynaptics *self = FPI_DEVICE_SYNAPTICS(dev); FpiDeviceSynaptics *self = FPI_DEVICE_SYNAPTICS (dev);
/* We just send out a cancel command and hope for the best. */ /* We just send out a cancel command and hope for the best. */
synaptics_sensor_cmd (self, -1, BMKT_CMD_CANCEL_OP, NULL, 0, NULL); synaptics_sensor_cmd (self, -1, BMKT_CMD_CANCEL_OP, NULL, 0, NULL);
@ -1091,12 +1182,14 @@ cancel(FpDevice *dev)
} }
static void static void
fpi_device_synaptics_init(FpiDeviceSynaptics *self) { fpi_device_synaptics_init (FpiDeviceSynaptics *self)
{
} }
static void static void
fpi_device_synaptics_class_init(FpiDeviceSynapticsClass *klass) { fpi_device_synaptics_class_init (FpiDeviceSynapticsClass *klass)
FpDeviceClass *dev_class = FP_DEVICE_CLASS(klass); {
FpDeviceClass *dev_class = FP_DEVICE_CLASS (klass);
dev_class->id = FP_COMPONENT; dev_class->id = FP_COMPONENT;
dev_class->full_name = SYNAPTICS_DRIVER_FULLNAME; dev_class->full_name = SYNAPTICS_DRIVER_FULLNAME;

View file

@ -24,7 +24,7 @@
#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 */
@ -77,20 +77,18 @@ struct syna_enroll_resp_data
{ {
int progress; int progress;
}; };
typedef enum syna_state typedef enum syna_state {
{
SYNA_STATE_UNINIT = 0, SYNA_STATE_UNINIT = 0,
SYNA_STATE_IDLE , SYNA_STATE_IDLE,
SYNA_STATE_ENROLL , SYNA_STATE_ENROLL,
SYNA_STATE_IDENTIFY , SYNA_STATE_IDENTIFY,
SYNA_STATE_IDENTIFY_DELAY_RESULT , SYNA_STATE_IDENTIFY_DELAY_RESULT,
SYNA_STATE_VERIFY , SYNA_STATE_VERIFY,
SYNA_STATE_VERIFY_DELAY_RESULT , SYNA_STATE_VERIFY_DELAY_RESULT,
SYNA_STATE_DELETE , SYNA_STATE_DELETE,
} syna_state_t; } syna_state_t;
typedef enum typedef enum {
{
SYNAPTICS_CMD_SEND_PENDING = 0, SYNAPTICS_CMD_SEND_PENDING = 0,
SYNAPTICS_CMD_GET_RESP, SYNAPTICS_CMD_GET_RESP,
SYNAPTICS_CMD_WAIT_INTERRUPT, SYNAPTICS_CMD_WAIT_INTERRUPT,
@ -100,7 +98,9 @@ typedef enum
} SynapticsCmdState; } 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 struct _FpiDeviceSynaptics
{ {

View file

@ -56,9 +56,10 @@ static const uint16_t crc_table[256] = {
}; };
uint16_t uint16_t
udf_crc(unsigned char *buffer, size_t size) udf_crc (unsigned char *buffer, size_t size)
{ {
uint16_t crc = 0; uint16_t crc = 0;
while (size--) while (size--)
crc = (uint16_t) ((crc << 8) ^ crc = (uint16_t) ((crc << 8) ^
crc_table[((crc >> 8) & 0x00ff) ^ *buffer++]); crc_table[((crc >> 8) & 0x00ff) ^ *buffer++]);

View file

@ -21,4 +21,5 @@
#include <stdint.h> #include <stdint.h>
#include <stddef.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

@ -27,7 +27,8 @@
#define IMG_WIDTH_1000 288 #define IMG_WIDTH_1000 288
#define IMG_WIDTH_1001 216 #define IMG_WIDTH_1001 216
struct sonly_regwrite { struct sonly_regwrite
{
guint8 reg; guint8 reg;
guint8 value; guint8 value;
}; };
@ -71,7 +72,7 @@ static const struct sonly_regwrite awfsm_2016_writev_3[] = {
static const struct sonly_regwrite awfsm_2016_writev_4[] = { static const struct sonly_regwrite awfsm_2016_writev_4[] = {
{ 0x08, 0x00 }, { 0x10, 0x00 }, { 0x12, 0x01 }, { 0x11, 0xbf }, { 0x08, 0x00 }, { 0x10, 0x00 }, { 0x12, 0x01 }, { 0x11, 0xbf },
{ 0x12, 0x01 }, { 0x07, 0x10 }, { 0x07, 0x10 }, { 0x04, 0x00 },\ { 0x12, 0x01 }, { 0x07, 0x10 }, { 0x07, 0x10 }, { 0x04, 0x00 }, \
{ 0x05, 0x00 }, { 0x0b, 0x00 }, { 0x05, 0x00 }, { 0x0b, 0x00 },
/* enter finger detection mode */ /* enter finger detection mode */

View file

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

View file

@ -29,7 +29,8 @@
#define UPEKTC_SUM_THRESHOLD 10000 #define UPEKTC_SUM_THRESHOLD 10000
#define UPEKET_SUM_THRESHOLD 5000 #define UPEKET_SUM_THRESHOLD 5000
struct setup_cmd { struct setup_cmd
{
unsigned char cmd[0x40]; unsigned char cmd[0x40];
int response_len; int response_len;
}; };

View file

@ -23,8 +23,8 @@
#include "upek_proto.h" #include "upek_proto.h"
#include "upektc_img.h" #include "upektc_img.h"
static void start_capture(FpImageDevice *dev); static void start_capture (FpImageDevice *dev);
static void start_deactivation(FpImageDevice *dev); static void start_deactivation (FpImageDevice *dev);
#define EP_IN (1 | FPI_USB_ENDPOINT_IN) #define EP_IN (1 | FPI_USB_ENDPOINT_IN)
#define EP_OUT (2 | FPI_USB_ENDPOINT_OUT) #define EP_OUT (2 | FPI_USB_ENDPOINT_OUT)
@ -39,7 +39,8 @@ static void start_deactivation(FpImageDevice *dev);
#define MAX_RESPONSE_SIZE 2052 #define MAX_RESPONSE_SIZE 2052
#define SHORT_RESPONSE_SIZE 64 #define SHORT_RESPONSE_SIZE 64
struct _FpiDeviceUpektcImg { struct _FpiDeviceUpektcImg
{
FpImageDevice parent; FpImageDevice parent;
unsigned char cmd[MAX_CMD_SIZE]; unsigned char cmd[MAX_CMD_SIZE];
@ -50,13 +51,14 @@ struct _FpiDeviceUpektcImg {
size_t response_rest; size_t response_rest;
gboolean deactivating; gboolean deactivating;
}; };
G_DECLARE_FINAL_TYPE(FpiDeviceUpektcImg, fpi_device_upektc_img, FPI, G_DECLARE_FINAL_TYPE (FpiDeviceUpektcImg, fpi_device_upektc_img, FPI,
DEVICE_UPEKTC_IMG, FpImageDevice); DEVICE_UPEKTC_IMG, FpImageDevice);
G_DEFINE_TYPE(FpiDeviceUpektcImg, fpi_device_upektc_img, FP_TYPE_IMAGE_DEVICE); G_DEFINE_TYPE (FpiDeviceUpektcImg, fpi_device_upektc_img, FP_TYPE_IMAGE_DEVICE);
/****** HELPERS ******/ /****** HELPERS ******/
static void upektc_img_cmd_fix_seq(unsigned char *cmd_buf, unsigned char seq) static void
upektc_img_cmd_fix_seq (unsigned char *cmd_buf, unsigned char seq)
{ {
uint8_t byte; uint8_t byte;
@ -66,58 +68,59 @@ static void upektc_img_cmd_fix_seq(unsigned char *cmd_buf, unsigned char seq)
cmd_buf[5] = byte; cmd_buf[5] = byte;
} }
static void upektc_img_cmd_update_crc(unsigned char *cmd_buf, size_t size) static void
upektc_img_cmd_update_crc (unsigned char *cmd_buf, size_t size)
{ {
/* CRC does not cover Ciao prefix (4 bytes) and CRC location (2 bytes) */ /* CRC does not cover Ciao prefix (4 bytes) and CRC location (2 bytes) */
uint16_t crc = udf_crc(cmd_buf + 4, size - 6); uint16_t crc = udf_crc (cmd_buf + 4, size - 6);
cmd_buf[size - 2] = (crc & 0x00ff); cmd_buf[size - 2] = (crc & 0x00ff);
cmd_buf[size - 1] = (crc & 0xff00) >> 8; cmd_buf[size - 1] = (crc & 0xff00) >> 8;
} }
static void static void
upektc_img_submit_req(FpiSsm *ssm, upektc_img_submit_req (FpiSsm *ssm,
FpImageDevice *dev, FpImageDevice *dev,
const unsigned char *buf, const unsigned char *buf,
size_t buf_size, size_t buf_size,
unsigned char seq, unsigned char seq,
FpiUsbTransferCallback cb) FpiUsbTransferCallback cb)
{ {
FpiDeviceUpektcImg *self = FPI_DEVICE_UPEKTC_IMG(dev); FpiDeviceUpektcImg *self = FPI_DEVICE_UPEKTC_IMG (dev);
FpiUsbTransfer *transfer = fpi_usb_transfer_new(FP_DEVICE(dev)); FpiUsbTransfer *transfer = fpi_usb_transfer_new (FP_DEVICE (dev));
BUG_ON(buf_size > MAX_CMD_SIZE); BUG_ON (buf_size > MAX_CMD_SIZE);
memcpy(self->cmd, buf, buf_size); memcpy (self->cmd, buf, buf_size);
upektc_img_cmd_fix_seq(self->cmd, seq); upektc_img_cmd_fix_seq (self->cmd, seq);
upektc_img_cmd_update_crc(self->cmd, buf_size); upektc_img_cmd_update_crc (self->cmd, buf_size);
fpi_usb_transfer_fill_bulk_full(transfer, EP_OUT, self->cmd, buf_size, fpi_usb_transfer_fill_bulk_full (transfer, EP_OUT, self->cmd, buf_size,
NULL); NULL);
transfer->ssm = ssm; transfer->ssm = ssm;
transfer->short_is_error = TRUE; transfer->short_is_error = TRUE;
fpi_usb_transfer_submit(transfer, BULK_TIMEOUT, NULL, cb, NULL); fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL, cb, NULL);
fpi_usb_transfer_unref(transfer); fpi_usb_transfer_unref (transfer);
} }
static void static void
upektc_img_read_data(FpiSsm *ssm, upektc_img_read_data (FpiSsm *ssm,
FpImageDevice *dev, FpImageDevice *dev,
size_t buf_size, size_t buf_size,
size_t buf_offset, size_t buf_offset,
FpiUsbTransferCallback cb) FpiUsbTransferCallback cb)
{ {
FpiUsbTransfer *transfer = fpi_usb_transfer_new(FP_DEVICE(dev)); FpiUsbTransfer *transfer = fpi_usb_transfer_new (FP_DEVICE (dev));
FpiDeviceUpektcImg *self = FPI_DEVICE_UPEKTC_IMG(dev); FpiDeviceUpektcImg *self = FPI_DEVICE_UPEKTC_IMG (dev);
BUG_ON(buf_offset + buf_size > MAX_RESPONSE_SIZE); BUG_ON (buf_offset + buf_size > MAX_RESPONSE_SIZE);
fpi_usb_transfer_fill_bulk_full(transfer, EP_IN, fpi_usb_transfer_fill_bulk_full (transfer, EP_IN,
self->response + buf_offset, buf_size, self->response + buf_offset, buf_size,
NULL); NULL);
transfer->ssm = ssm; transfer->ssm = ssm;
fpi_usb_transfer_submit(transfer, BULK_TIMEOUT, NULL, cb, NULL); fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL, cb, NULL);
fpi_usb_transfer_unref(transfer); fpi_usb_transfer_unref (transfer);
} }
/****** CAPTURE ******/ /****** CAPTURE ******/
@ -133,246 +136,281 @@ enum capture_states {
CAPTURE_NUM_STATES, CAPTURE_NUM_STATES,
}; };
static void capture_reqs_cb(FpiUsbTransfer *transfer, FpDevice *device, static void
capture_reqs_cb (FpiUsbTransfer *transfer, FpDevice *device,
gpointer user_data, GError *error) gpointer user_data, GError *error)
{ {
if (error) { if (error)
fpi_ssm_mark_failed(transfer->ssm, error); {
fpi_ssm_mark_failed (transfer->ssm, error);
return; return;
} }
switch (fpi_ssm_get_cur_state(transfer->ssm)) { switch (fpi_ssm_get_cur_state (transfer->ssm))
{
case CAPTURE_ACK_00_28_TERM: case CAPTURE_ACK_00_28_TERM:
fpi_ssm_jump_to_state(transfer->ssm, CAPTURE_READ_DATA_TERM); fpi_ssm_jump_to_state (transfer->ssm, CAPTURE_READ_DATA_TERM);
break; break;
default: default:
fpi_ssm_jump_to_state(transfer->ssm, CAPTURE_READ_DATA); fpi_ssm_jump_to_state (transfer->ssm, CAPTURE_READ_DATA);
break; break;
} }
} }
static int upektc_img_process_image_frame(unsigned char *image_buf, unsigned char *cmd_res) static int
upektc_img_process_image_frame (unsigned char *image_buf, unsigned char *cmd_res)
{ {
int offset = 8; int offset = 8;
int len = ((cmd_res[5] & 0x0f) << 8) | (cmd_res[6]); int len = ((cmd_res[5] & 0x0f) << 8) | (cmd_res[6]);
len -= 1; len -= 1;
if (cmd_res[7] == 0x2c) { if (cmd_res[7] == 0x2c)
{
len -= 10; len -= 10;
offset += 10; offset += 10;
} }
if (cmd_res[7] == 0x20) { if (cmd_res[7] == 0x20)
len -= 4; len -= 4;
} memcpy (image_buf, cmd_res + offset, len);
memcpy(image_buf, cmd_res + offset, len);
return len; return len;
} }
static void capture_read_data_cb(FpiUsbTransfer *transfer, FpDevice *device, static void
capture_read_data_cb (FpiUsbTransfer *transfer, FpDevice *device,
gpointer user_data, GError *error) gpointer user_data, GError *error)
{ {
FpImageDevice *dev = FP_IMAGE_DEVICE(device); FpImageDevice *dev = FP_IMAGE_DEVICE (device);
FpiDeviceUpektcImg *self = FPI_DEVICE_UPEKTC_IMG(dev); FpiDeviceUpektcImg *self = FPI_DEVICE_UPEKTC_IMG (dev);
unsigned char *data = self->response; unsigned char *data = self->response;
FpImage *img; FpImage *img;
size_t response_size; size_t response_size;
if (error) { if (error)
fp_dbg("request is not completed, %s", error->message); {
fpi_ssm_mark_failed(transfer->ssm, error); fp_dbg ("request is not completed, %s", error->message);
fpi_ssm_mark_failed (transfer->ssm, error);
return; return;
} }
if (self->deactivating) { if (self->deactivating)
fp_dbg("Deactivate requested\n"); {
fpi_ssm_mark_completed(transfer->ssm); fp_dbg ("Deactivate requested\n");
fpi_ssm_mark_completed (transfer->ssm);
return; return;
} }
fp_dbg("request completed, len: %.4x", (gint)transfer->actual_length); fp_dbg ("request completed, len: %.4x", (gint) transfer->actual_length);
if (transfer->actual_length == 0) { if (transfer->actual_length == 0)
fpi_ssm_jump_to_state(transfer->ssm, {
fpi_ssm_get_cur_state(transfer->ssm)); fpi_ssm_jump_to_state (transfer->ssm,
fpi_ssm_get_cur_state (transfer->ssm));
return; return;
} }
if (fpi_ssm_get_cur_state(transfer->ssm) == CAPTURE_READ_DATA_TERM) { if (fpi_ssm_get_cur_state (transfer->ssm) == CAPTURE_READ_DATA_TERM)
fp_dbg("Terminating SSM\n"); {
fpi_ssm_mark_completed(transfer->ssm); fp_dbg ("Terminating SSM\n");
fpi_ssm_mark_completed (transfer->ssm);
return; return;
} }
if (!self->response_rest) { if (!self->response_rest)
{
response_size = ((data[5] & 0x0f) << 8) + data[6]; response_size = ((data[5] & 0x0f) << 8) + data[6];
response_size += 9; /* 7 bytes for header, 2 for CRC */ response_size += 9; /* 7 bytes for header, 2 for CRC */
if (response_size > transfer->actual_length) { if (response_size > transfer->actual_length)
fp_dbg("response_size is %lu, actual_length is %d\n", {
response_size, (gint)transfer->actual_length); fp_dbg ("response_size is %lu, actual_length is %d\n",
fp_dbg("Waiting for rest of transfer"); response_size, (gint) transfer->actual_length);
BUG_ON(self->response_rest); fp_dbg ("Waiting for rest of transfer");
BUG_ON (self->response_rest);
self->response_rest = response_size - transfer->actual_length; self->response_rest = response_size - transfer->actual_length;
fpi_ssm_jump_to_state(transfer->ssm, CAPTURE_READ_DATA); fpi_ssm_jump_to_state (transfer->ssm, CAPTURE_READ_DATA);
return; return;
} }
} }
self->response_rest = 0; self->response_rest = 0;
switch (data[4]) { switch (data[4])
{
case 0x00: case 0x00:
switch (data[7]) { switch (data[7])
{
/* No finger */ /* No finger */
case 0x28: case 0x28:
fp_dbg("18th byte is %.2x\n", data[18]); fp_dbg ("18th byte is %.2x\n", data[18]);
switch (data[18]) { switch (data[18])
{
case 0x0c: case 0x0c:
/* no finger */ /* no finger */
fpi_ssm_jump_to_state(transfer->ssm, fpi_ssm_jump_to_state (transfer->ssm,
CAPTURE_ACK_00_28); CAPTURE_ACK_00_28);
break; break;
case 0x00: case 0x00:
/* finger is present! */ /* finger is present! */
fpi_ssm_jump_to_state(transfer->ssm, fpi_ssm_jump_to_state (transfer->ssm,
CAPTURE_ACK_00_28); CAPTURE_ACK_00_28);
break; break;
case 0x1e: case 0x1e:
/* short scan */ /* short scan */
fp_err("short scan, aborting\n"); fp_err ("short scan, aborting\n");
fpi_image_device_retry_scan(dev, fpi_image_device_retry_scan (dev,
FP_DEVICE_RETRY_TOO_SHORT); FP_DEVICE_RETRY_TOO_SHORT);
fpi_image_device_report_finger_status(dev, fpi_image_device_report_finger_status (dev,
FALSE); FALSE);
fpi_ssm_jump_to_state(transfer->ssm, fpi_ssm_jump_to_state (transfer->ssm,
CAPTURE_ACK_00_28_TERM); CAPTURE_ACK_00_28_TERM);
break; break;
case 0x1d: case 0x1d:
/* too much horisontal movement */ /* too much horisontal movement */
fp_err("too much horisontal movement, aborting\n"); fp_err ("too much horisontal movement, aborting\n");
fpi_image_device_retry_scan(dev, fpi_image_device_retry_scan (dev,
FP_DEVICE_RETRY_CENTER_FINGER); FP_DEVICE_RETRY_CENTER_FINGER);
fpi_image_device_report_finger_status(dev, fpi_image_device_report_finger_status (dev,
FALSE); FALSE);
fpi_ssm_jump_to_state(transfer->ssm, fpi_ssm_jump_to_state (transfer->ssm,
CAPTURE_ACK_00_28_TERM); CAPTURE_ACK_00_28_TERM);
break; break;
default: default:
/* some error happened, cancel scan */ /* some error happened, cancel scan */
fp_err("something bad happened, stop scan\n"); fp_err ("something bad happened, stop scan\n");
fpi_image_device_retry_scan(dev, fpi_image_device_retry_scan (dev,
FP_DEVICE_RETRY); FP_DEVICE_RETRY);
fpi_image_device_report_finger_status(dev, fpi_image_device_report_finger_status (dev,
FALSE); FALSE);
fpi_ssm_jump_to_state(transfer->ssm, fpi_ssm_jump_to_state (transfer->ssm,
CAPTURE_ACK_00_28_TERM); CAPTURE_ACK_00_28_TERM);
break; break;
} }
break; break;
/* Image frame with additional info */ /* Image frame with additional info */
case 0x2c: case 0x2c:
fpi_image_device_report_finger_status(dev, fpi_image_device_report_finger_status (dev,
TRUE); TRUE);
/* Plain image frame */ /* Plain image frame */
case 0x24: case 0x24:
self->image_size += self->image_size +=
upektc_img_process_image_frame(self->image_bits + self->image_size, upektc_img_process_image_frame (self->image_bits + self->image_size,
data); data);
fpi_ssm_jump_to_state(transfer->ssm, fpi_ssm_jump_to_state (transfer->ssm,
CAPTURE_ACK_FRAME); CAPTURE_ACK_FRAME);
break; break;
/* Last image frame */ /* Last image frame */
case 0x20: case 0x20:
self->image_size += self->image_size +=
upektc_img_process_image_frame(self->image_bits + self->image_size, upektc_img_process_image_frame (self->image_bits + self->image_size,
data); data);
BUG_ON(self->image_size != IMAGE_SIZE); BUG_ON (self->image_size != IMAGE_SIZE);
fp_dbg("Image size is %lu\n", fp_dbg ("Image size is %lu\n",
self->image_size); self->image_size);
img = fp_image_new(IMAGE_WIDTH, IMAGE_HEIGHT); img = fp_image_new (IMAGE_WIDTH, IMAGE_HEIGHT);
memcpy(img->data, self->image_bits, memcpy (img->data, self->image_bits,
IMAGE_SIZE); IMAGE_SIZE);
fpi_image_device_image_captured(dev, img); fpi_image_device_image_captured (dev, img);
fpi_image_device_report_finger_status(dev, fpi_image_device_report_finger_status (dev,
FALSE); FALSE);
fpi_ssm_mark_completed(transfer->ssm); fpi_ssm_mark_completed (transfer->ssm);
break; break;
default: default:
fp_err("Unknown response!\n"); fp_err ("Unknown response!\n");
fpi_ssm_mark_failed(transfer->ssm, fpi_device_error_new (FP_DEVICE_ERROR_GENERAL)); fpi_ssm_mark_failed (transfer->ssm, fpi_device_error_new (FP_DEVICE_ERROR_GENERAL));
break; break;
} }
break; break;
case 0x08: case 0x08:
fpi_ssm_jump_to_state(transfer->ssm, CAPTURE_ACK_08); fpi_ssm_jump_to_state (transfer->ssm, CAPTURE_ACK_08);
break; break;
default: default:
fp_err("Not handled response!\n"); fp_err ("Not handled response!\n");
fpi_ssm_mark_failed(transfer->ssm, fpi_device_error_new (FP_DEVICE_ERROR_GENERAL)); fpi_ssm_mark_failed (transfer->ssm, fpi_device_error_new (FP_DEVICE_ERROR_GENERAL));
} }
} }
static void capture_run_state(FpiSsm *ssm, FpDevice *_dev, void *user_data) static void
capture_run_state (FpiSsm *ssm, FpDevice *_dev, void *user_data)
{ {
FpImageDevice *dev = user_data; FpImageDevice *dev = user_data;
FpiDeviceUpektcImg *self = FPI_DEVICE_UPEKTC_IMG(_dev); FpiDeviceUpektcImg *self = FPI_DEVICE_UPEKTC_IMG (_dev);
switch (fpi_ssm_get_cur_state(ssm)) { switch (fpi_ssm_get_cur_state (ssm))
{
case CAPTURE_INIT_CAPTURE: case CAPTURE_INIT_CAPTURE:
upektc_img_submit_req(ssm, dev, upek2020_init_capture, sizeof(upek2020_init_capture), upektc_img_submit_req (ssm, dev, upek2020_init_capture, sizeof (upek2020_init_capture),
self->seq, capture_reqs_cb); self->seq, capture_reqs_cb);
self->seq++; self->seq++;
break; break;
case CAPTURE_READ_DATA: case CAPTURE_READ_DATA:
case CAPTURE_READ_DATA_TERM: case CAPTURE_READ_DATA_TERM:
if (!self->response_rest) if (!self->response_rest)
upektc_img_read_data(ssm, dev, SHORT_RESPONSE_SIZE, 0, capture_read_data_cb); upektc_img_read_data (ssm, dev, SHORT_RESPONSE_SIZE, 0, capture_read_data_cb);
else else
upektc_img_read_data(ssm, dev, MAX_RESPONSE_SIZE - SHORT_RESPONSE_SIZE, upektc_img_read_data (ssm, dev, MAX_RESPONSE_SIZE - SHORT_RESPONSE_SIZE,
SHORT_RESPONSE_SIZE, capture_read_data_cb); SHORT_RESPONSE_SIZE, capture_read_data_cb);
break; break;
case CAPTURE_ACK_00_28: case CAPTURE_ACK_00_28:
case CAPTURE_ACK_00_28_TERM: case CAPTURE_ACK_00_28_TERM:
upektc_img_submit_req(ssm, dev, upek2020_ack_00_28, sizeof(upek2020_ack_00_28), upektc_img_submit_req (ssm, dev, upek2020_ack_00_28, sizeof (upek2020_ack_00_28),
self->seq, capture_reqs_cb); self->seq, capture_reqs_cb);
self->seq++; self->seq++;
break; break;
case CAPTURE_ACK_08: case CAPTURE_ACK_08:
upektc_img_submit_req(ssm, dev, upek2020_ack_08, sizeof(upek2020_ack_08), upektc_img_submit_req (ssm, dev, upek2020_ack_08, sizeof (upek2020_ack_08),
0, capture_reqs_cb); 0, capture_reqs_cb);
break; break;
case CAPTURE_ACK_FRAME: case CAPTURE_ACK_FRAME:
upektc_img_submit_req(ssm, dev, upek2020_ack_frame, sizeof(upek2020_ack_frame), upektc_img_submit_req (ssm, dev, upek2020_ack_frame, sizeof (upek2020_ack_frame),
self->seq, capture_reqs_cb); self->seq, capture_reqs_cb);
self->seq++; self->seq++;
break; break;
}; }
;
} }
static void capture_sm_complete(FpiSsm *ssm, FpDevice *_dev, void *user_data, GError *error_arg) static void
capture_sm_complete (FpiSsm *ssm, FpDevice *_dev, void *user_data, GError *error_arg)
{ {
FpImageDevice *dev = user_data; FpImageDevice *dev = user_data;
FpiDeviceUpektcImg *self = FPI_DEVICE_UPEKTC_IMG(_dev); FpiDeviceUpektcImg *self = FPI_DEVICE_UPEKTC_IMG (_dev);
g_autoptr(GError) error = error_arg; g_autoptr(GError) error = error_arg;
fpi_ssm_free(ssm); fpi_ssm_free (ssm);
/* Note: We assume that the error is a cancellation in the deactivation case */ /* Note: We assume that the error is a cancellation in the deactivation case */
if (self->deactivating) if (self->deactivating)
start_deactivation(dev); start_deactivation (dev);
else if (error) else if (error)
fpi_image_device_session_error (dev, g_steal_pointer (&error)); fpi_image_device_session_error (dev, g_steal_pointer (&error));
else else
start_capture(dev); start_capture (dev);
} }
static void start_capture(FpImageDevice *dev) static void
start_capture (FpImageDevice *dev)
{ {
FpiDeviceUpektcImg *self = FPI_DEVICE_UPEKTC_IMG(dev); FpiDeviceUpektcImg *self = FPI_DEVICE_UPEKTC_IMG (dev);
FpiSsm *ssm; FpiSsm *ssm;
self->image_size = 0; self->image_size = 0;
ssm = fpi_ssm_new(FP_DEVICE(dev), capture_run_state, ssm = fpi_ssm_new (FP_DEVICE (dev), capture_run_state,
CAPTURE_NUM_STATES, dev); CAPTURE_NUM_STATES, dev);
fpi_ssm_start(ssm, capture_sm_complete); fpi_ssm_start (ssm, capture_sm_complete);
} }
/****** INITIALIZATION/DEINITIALIZATION ******/ /****** INITIALIZATION/DEINITIALIZATION ******/
@ -383,68 +421,74 @@ enum deactivate_states {
DEACTIVATE_NUM_STATES, DEACTIVATE_NUM_STATES,
}; };
static void deactivate_reqs_cb(FpiUsbTransfer *transfer, FpDevice *device, static void
deactivate_reqs_cb (FpiUsbTransfer *transfer, FpDevice *device,
gpointer user_data, GError *error) gpointer user_data, GError *error)
{ {
if (!error) { if (!error)
fpi_ssm_jump_to_state(transfer->ssm, CAPTURE_READ_DATA); fpi_ssm_jump_to_state (transfer->ssm, CAPTURE_READ_DATA);
} else { else
fpi_ssm_mark_failed(transfer->ssm, error); fpi_ssm_mark_failed (transfer->ssm, error);
}
} }
/* TODO: process response properly */ /* TODO: process response properly */
static void deactivate_read_data_cb(FpiUsbTransfer *transfer, FpDevice *device, static void
deactivate_read_data_cb (FpiUsbTransfer *transfer, FpDevice *device,
gpointer user_data, GError *error) gpointer user_data, GError *error)
{ {
if (!error) { if (!error)
fpi_ssm_mark_completed(transfer->ssm); fpi_ssm_mark_completed (transfer->ssm);
} else { else
fpi_ssm_mark_failed(transfer->ssm, error); fpi_ssm_mark_failed (transfer->ssm, error);
}
} }
static void deactivate_run_state(FpiSsm *ssm, FpDevice *_dev, static void
deactivate_run_state (FpiSsm *ssm, FpDevice *_dev,
void *user_data) void *user_data)
{ {
FpImageDevice *dev = user_data; FpImageDevice *dev = user_data;
FpiDeviceUpektcImg *self = FPI_DEVICE_UPEKTC_IMG(_dev); FpiDeviceUpektcImg *self = FPI_DEVICE_UPEKTC_IMG (_dev);
switch (fpi_ssm_get_cur_state(ssm)) { switch (fpi_ssm_get_cur_state (ssm))
{
case DEACTIVATE_DEINIT: case DEACTIVATE_DEINIT:
upektc_img_submit_req(ssm, dev, upek2020_deinit, sizeof(upek2020_deinit), upektc_img_submit_req (ssm, dev, upek2020_deinit, sizeof (upek2020_deinit),
self->seq, deactivate_reqs_cb); self->seq, deactivate_reqs_cb);
self->seq++; self->seq++;
break; break;
case DEACTIVATE_READ_DEINIT_DATA: case DEACTIVATE_READ_DEINIT_DATA:
upektc_img_read_data(ssm, dev, SHORT_RESPONSE_SIZE, 0, deactivate_read_data_cb); upektc_img_read_data (ssm, dev, SHORT_RESPONSE_SIZE, 0, deactivate_read_data_cb);
break; break;
}; }
;
} }
static void deactivate_sm_complete(FpiSsm *ssm, FpDevice *_dev, static void
deactivate_sm_complete (FpiSsm *ssm, FpDevice *_dev,
void *user_data, GError *error) void *user_data, GError *error)
{ {
FpImageDevice *dev = user_data; FpImageDevice *dev = user_data;
FpiDeviceUpektcImg *self = FPI_DEVICE_UPEKTC_IMG(_dev); FpiDeviceUpektcImg *self = FPI_DEVICE_UPEKTC_IMG (_dev);
fp_dbg("Deactivate completed"); fp_dbg ("Deactivate completed");
fpi_ssm_free(ssm); fpi_ssm_free (ssm);
self->deactivating = FALSE; self->deactivating = FALSE;
fpi_image_device_deactivate_complete(dev, error); fpi_image_device_deactivate_complete (dev, error);
} }
static void start_deactivation(FpImageDevice *dev) static void
start_deactivation (FpImageDevice *dev)
{ {
FpiDeviceUpektcImg *self = FPI_DEVICE_UPEKTC_IMG(dev); FpiDeviceUpektcImg *self = FPI_DEVICE_UPEKTC_IMG (dev);
FpiSsm *ssm; FpiSsm *ssm;
self->image_size = 0; self->image_size = 0;
ssm = fpi_ssm_new(FP_DEVICE(dev), deactivate_run_state, ssm = fpi_ssm_new (FP_DEVICE (dev), deactivate_run_state,
DEACTIVATE_NUM_STATES, dev); DEACTIVATE_NUM_STATES, dev);
fpi_ssm_start(ssm, deactivate_sm_complete); fpi_ssm_start (ssm, deactivate_sm_complete);
} }
enum activate_states { enum activate_states {
@ -463,146 +507,161 @@ enum activate_states {
ACTIVATE_NUM_STATES, ACTIVATE_NUM_STATES,
}; };
static void init_reqs_ctrl_cb(FpiUsbTransfer *transfer, FpDevice *device, static void
init_reqs_ctrl_cb (FpiUsbTransfer *transfer, FpDevice *device,
gpointer user_data, GError *error) gpointer user_data, GError *error)
{ {
if (!error) { if (!error)
fpi_ssm_next_state(transfer->ssm); fpi_ssm_next_state (transfer->ssm);
} else { else
fpi_ssm_mark_failed(transfer->ssm, error); fpi_ssm_mark_failed (transfer->ssm, error);
}
} }
static void init_reqs_cb(FpiUsbTransfer *transfer, FpDevice *device, static void
init_reqs_cb (FpiUsbTransfer *transfer, FpDevice *device,
gpointer user_data, GError *error) gpointer user_data, GError *error)
{ {
if (!error) { if (!error)
fpi_ssm_next_state(transfer->ssm); fpi_ssm_next_state (transfer->ssm);
} else { else
fpi_ssm_mark_failed(transfer->ssm, error); fpi_ssm_mark_failed (transfer->ssm, error);
}
} }
/* TODO: process response properly */ /* TODO: process response properly */
static void init_read_data_cb(FpiUsbTransfer *transfer, FpDevice *device, static void
init_read_data_cb (FpiUsbTransfer *transfer, FpDevice *device,
gpointer user_data, GError *error) gpointer user_data, GError *error)
{ {
if (!error) { if (!error)
fpi_ssm_next_state(transfer->ssm); fpi_ssm_next_state (transfer->ssm);
} else { else
fpi_ssm_mark_failed(transfer->ssm, error); 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)
{ {
FpiUsbTransfer *transfer; FpiUsbTransfer *transfer;
FpImageDevice *idev = user_data; FpImageDevice *idev = user_data;
FpiDeviceUpektcImg *self = FPI_DEVICE_UPEKTC_IMG(dev); FpiDeviceUpektcImg *self = FPI_DEVICE_UPEKTC_IMG (dev);
switch (fpi_ssm_get_cur_state(ssm)) { switch (fpi_ssm_get_cur_state (ssm))
{
case ACTIVATE_CONTROL_REQ_1: case ACTIVATE_CONTROL_REQ_1:
case ACTIVATE_CONTROL_REQ_2: case ACTIVATE_CONTROL_REQ_2:
{ {
transfer = fpi_usb_transfer_new(dev); transfer = fpi_usb_transfer_new (dev);
fpi_usb_transfer_fill_control(transfer, fpi_usb_transfer_fill_control (transfer,
G_USB_DEVICE_DIRECTION_HOST_TO_DEVICE, G_USB_DEVICE_DIRECTION_HOST_TO_DEVICE,
G_USB_DEVICE_REQUEST_TYPE_VENDOR, G_USB_DEVICE_REQUEST_TYPE_VENDOR,
G_USB_DEVICE_RECIPIENT_DEVICE, G_USB_DEVICE_RECIPIENT_DEVICE,
0x0c, 0x100, 0x0400, 1); 0x0c, 0x100, 0x0400, 1);
transfer->buffer[0] = '\0'; transfer->buffer[0] = '\0';
transfer->ssm = ssm; transfer->ssm = ssm;
fpi_usb_transfer_submit(transfer, CTRL_TIMEOUT, NULL, fpi_usb_transfer_submit (transfer, CTRL_TIMEOUT, NULL,
init_reqs_ctrl_cb, NULL); init_reqs_ctrl_cb, NULL);
fpi_usb_transfer_unref(transfer); fpi_usb_transfer_unref (transfer);
} }
break; break;
case ACTIVATE_INIT_1: case ACTIVATE_INIT_1:
upektc_img_submit_req(ssm, idev, upek2020_init_1, sizeof(upek2020_init_1), upektc_img_submit_req (ssm, idev, upek2020_init_1, sizeof (upek2020_init_1),
0, init_reqs_cb); 0, init_reqs_cb);
break; break;
case ACTIVATE_INIT_2: case ACTIVATE_INIT_2:
upektc_img_submit_req(ssm, idev, upek2020_init_2, sizeof(upek2020_init_2), upektc_img_submit_req (ssm, idev, upek2020_init_2, sizeof (upek2020_init_2),
0, init_reqs_cb); 0, init_reqs_cb);
break; break;
case ACTIVATE_INIT_3: case ACTIVATE_INIT_3:
upektc_img_submit_req(ssm, idev, upek2020_init_3, sizeof(upek2020_init_3), upektc_img_submit_req (ssm, idev, upek2020_init_3, sizeof (upek2020_init_3),
0, init_reqs_cb); 0, init_reqs_cb);
break; break;
case ACTIVATE_INIT_4: case ACTIVATE_INIT_4:
upektc_img_submit_req(ssm, idev, upek2020_init_4, sizeof(upek2020_init_4), upektc_img_submit_req (ssm, idev, upek2020_init_4, sizeof (upek2020_init_4),
self->seq, init_reqs_cb); self->seq, init_reqs_cb);
/* Seq should be updated after 4th init */ /* Seq should be updated after 4th init */
self->seq++; self->seq++;
break; break;
case ACTIVATE_READ_CTRL_RESP_1: case ACTIVATE_READ_CTRL_RESP_1:
case ACTIVATE_READ_CTRL_RESP_2: case ACTIVATE_READ_CTRL_RESP_2:
case ACTIVATE_READ_INIT_1_RESP: case ACTIVATE_READ_INIT_1_RESP:
case ACTIVATE_READ_INIT_2_RESP: case ACTIVATE_READ_INIT_2_RESP:
case ACTIVATE_READ_INIT_3_RESP: case ACTIVATE_READ_INIT_3_RESP:
case ACTIVATE_READ_INIT_4_RESP: case ACTIVATE_READ_INIT_4_RESP:
upektc_img_read_data(ssm, idev, SHORT_RESPONSE_SIZE, 0, init_read_data_cb); upektc_img_read_data (ssm, idev, SHORT_RESPONSE_SIZE, 0, init_read_data_cb);
break; break;
} }
} }
static void activate_sm_complete(FpiSsm *ssm, FpDevice *_dev, static void
activate_sm_complete (FpiSsm *ssm, FpDevice *_dev,
void *user_data, GError *error) void *user_data, GError *error)
{ {
FpImageDevice *dev = user_data; FpImageDevice *dev = user_data;
fpi_ssm_free(ssm); fpi_ssm_free (ssm);
fpi_image_device_activate_complete(dev, error); fpi_image_device_activate_complete (dev, error);
if (!error) if (!error)
start_capture(dev); start_capture (dev);
} }
static void dev_activate(FpImageDevice *dev) static void
dev_activate (FpImageDevice *dev)
{ {
FpiDeviceUpektcImg *self = FPI_DEVICE_UPEKTC_IMG(dev); FpiDeviceUpektcImg *self = FPI_DEVICE_UPEKTC_IMG (dev);
FpiSsm *ssm = fpi_ssm_new(FP_DEVICE(dev), activate_run_state, FpiSsm *ssm = fpi_ssm_new (FP_DEVICE (dev), activate_run_state,
ACTIVATE_NUM_STATES, dev); ACTIVATE_NUM_STATES, dev);
self->seq = 0; self->seq = 0;
fpi_ssm_start(ssm, activate_sm_complete); fpi_ssm_start (ssm, activate_sm_complete);
} }
static void dev_deactivate(FpImageDevice *dev) static void
dev_deactivate (FpImageDevice *dev)
{ {
FpiDeviceUpektcImg *self = FPI_DEVICE_UPEKTC_IMG(dev); FpiDeviceUpektcImg *self = FPI_DEVICE_UPEKTC_IMG (dev);
self->deactivating = TRUE; self->deactivating = TRUE;
} }
static void dev_init(FpImageDevice *dev) static void
dev_init (FpImageDevice *dev)
{ {
FpiDeviceUpektcImg *self = FPI_DEVICE_UPEKTC_IMG(dev); FpiDeviceUpektcImg *self = FPI_DEVICE_UPEKTC_IMG (dev);
GError *error = NULL; GError *error = NULL;
/* 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)) { if (!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);
return; return;
} }
self->image_bits = g_malloc0 (IMAGE_SIZE * 2); self->image_bits = g_malloc0 (IMAGE_SIZE * 2);
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)
{ {
FpiDeviceUpektcImg *self = FPI_DEVICE_UPEKTC_IMG(dev); FpiDeviceUpektcImg *self = FPI_DEVICE_UPEKTC_IMG (dev);
GError *error = NULL; GError *error = NULL;
g_clear_pointer (&self->image_bits, g_free); g_clear_pointer (&self->image_bits, g_free);
g_usb_device_release_interface(fpi_device_get_usb_device(FP_DEVICE(dev)), g_usb_device_release_interface (fpi_device_get_usb_device (FP_DEVICE (dev)),
0, 0, &error); 0, 0, &error);
fpi_image_device_close_complete(dev, error); fpi_image_device_close_complete (dev, error);
} }
static int static int
discover(GUsbDevice *usb_device) discover (GUsbDevice *usb_device)
{ {
gint16 pid = g_usb_device_get_pid (usb_device); gint16 pid = g_usb_device_get_pid (usb_device);
gint16 bcd = g_usb_device_get_release (usb_device); gint16 bcd = g_usb_device_get_release (usb_device);
@ -615,19 +674,21 @@ discover(GUsbDevice *usb_device)
return 0; return 0;
} }
static const FpIdEntry id_table [ ] = { static const FpIdEntry id_table[] = {
{ .vid = 0x147e, .pid = 0x2016, { .vid = 0x147e, .pid = 0x2016, },
}, { .vid = 0x147e, .pid = 0x2020, },
{ .vid = 0x147e, .pid = 0x2020,
},
{ .vid = 0, .pid = 0, .driver_data = 0 }, { .vid = 0, .pid = 0, .driver_data = 0 },
}; };
static void fpi_device_upektc_img_init(FpiDeviceUpektcImg *self) { static void
fpi_device_upektc_img_init (FpiDeviceUpektcImg *self)
{
} }
static void fpi_device_upektc_img_class_init(FpiDeviceUpektcImgClass *klass) { static void
FpDeviceClass *dev_class = FP_DEVICE_CLASS(klass); fpi_device_upektc_img_class_init (FpiDeviceUpektcImgClass *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 = "upektc_img"; dev_class->id = "upektc_img";
dev_class->full_name = "Upek TouchChip Fingerprint Coprocessor"; dev_class->full_name = "Upek TouchChip Fingerprint Coprocessor";

View file

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

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -38,7 +38,8 @@
#define RQ_SIZE (IMG_WIDTH * ROWS_PER_RQ) #define RQ_SIZE (IMG_WIDTH * ROWS_PER_RQ)
#define IMG_SIZE (IMG_WIDTH * IMG_HEIGHT) #define IMG_SIZE (IMG_WIDTH * IMG_HEIGHT)
struct _FpDeviceVcom5s { struct _FpDeviceVcom5s
{
FpImageDevice parent; FpImageDevice parent;
int capture_iteration; int capture_iteration;
@ -46,9 +47,9 @@ struct _FpDeviceVcom5s {
gboolean loop_running; gboolean loop_running;
gboolean deactivating; gboolean deactivating;
}; };
G_DECLARE_FINAL_TYPE(FpDeviceVcom5s, fpi_device_vcom5s, FPI, DEVICE_VCOM5S, G_DECLARE_FINAL_TYPE (FpDeviceVcom5s, fpi_device_vcom5s, FPI, DEVICE_VCOM5S,
FpImageDevice); FpImageDevice);
G_DEFINE_TYPE(FpDeviceVcom5s, fpi_device_vcom5s, FP_TYPE_IMAGE_DEVICE); G_DEFINE_TYPE (FpDeviceVcom5s, fpi_device_vcom5s, FP_TYPE_IMAGE_DEVICE);
enum v5s_regs { enum v5s_regs {
/* when using gain 0x29: /* when using gain 0x29:
@ -75,62 +76,64 @@ enum v5s_cmd {
/***** REGISTER I/O *****/ /***** REGISTER I/O *****/
static void sm_write_reg_cb(FpiUsbTransfer *transfer, FpDevice *device, static void
sm_write_reg_cb (FpiUsbTransfer *transfer, FpDevice *device,
gpointer user_data, GError *error) gpointer user_data, GError *error)
{ {
if (error) if (error)
fpi_ssm_mark_failed(transfer->ssm, error); fpi_ssm_mark_failed (transfer->ssm, error);
else else
fpi_ssm_next_state(transfer->ssm); fpi_ssm_next_state (transfer->ssm);
} }
static void static void
sm_write_reg(FpiSsm *ssm, sm_write_reg (FpiSsm *ssm,
FpDevice *dev, FpDevice *dev,
unsigned char reg, unsigned char reg,
unsigned char value) unsigned char value)
{ {
FpiUsbTransfer *transfer = fpi_usb_transfer_new(dev); FpiUsbTransfer *transfer = fpi_usb_transfer_new (dev);
fp_dbg("set %02x=%02x", reg, value); fp_dbg ("set %02x=%02x", reg, value);
fpi_usb_transfer_fill_control(transfer, fpi_usb_transfer_fill_control (transfer,
G_USB_DEVICE_DIRECTION_HOST_TO_DEVICE, G_USB_DEVICE_DIRECTION_HOST_TO_DEVICE,
G_USB_DEVICE_REQUEST_TYPE_VENDOR, G_USB_DEVICE_REQUEST_TYPE_VENDOR,
G_USB_DEVICE_RECIPIENT_DEVICE, G_USB_DEVICE_RECIPIENT_DEVICE,
reg, value, 0, 0); reg, value, 0, 0);
transfer->ssm = ssm; transfer->ssm = ssm;
fpi_usb_transfer_submit(transfer, CTRL_TIMEOUT, NULL, sm_write_reg_cb, fpi_usb_transfer_submit (transfer, CTRL_TIMEOUT, NULL, sm_write_reg_cb,
NULL); NULL);
fpi_usb_transfer_unref(transfer); 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);
} }
static void static void
sm_exec_cmd(FpiSsm *ssm, 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);
}
static void
sm_exec_cmd (FpiSsm *ssm,
FpDevice *dev, FpDevice *dev,
unsigned char cmd, unsigned char cmd,
unsigned char param) unsigned char param)
{ {
FpiUsbTransfer *transfer = fpi_usb_transfer_new(dev); FpiUsbTransfer *transfer = fpi_usb_transfer_new (dev);
fp_dbg("cmd %02x param %02x", cmd, param); fp_dbg ("cmd %02x param %02x", cmd, param);
fpi_usb_transfer_fill_control(transfer, fpi_usb_transfer_fill_control (transfer,
G_USB_DEVICE_DIRECTION_DEVICE_TO_HOST, G_USB_DEVICE_DIRECTION_DEVICE_TO_HOST,
G_USB_DEVICE_REQUEST_TYPE_VENDOR, G_USB_DEVICE_REQUEST_TYPE_VENDOR,
G_USB_DEVICE_RECIPIENT_DEVICE, G_USB_DEVICE_RECIPIENT_DEVICE,
cmd, param, 0, 0); cmd, param, 0, 0);
transfer->ssm = ssm; transfer->ssm = ssm;
fpi_usb_transfer_submit(transfer, CTRL_TIMEOUT, NULL, sm_exec_cmd_cb, fpi_usb_transfer_submit (transfer, CTRL_TIMEOUT, NULL, sm_exec_cmd_cb,
NULL); NULL);
fpi_usb_transfer_unref(transfer); fpi_usb_transfer_unref (transfer);
} }
/***** FINGER DETECTION *****/ /***** FINGER DETECTION *****/
@ -145,12 +148,14 @@ sm_exec_cmd(FpiSsm *ssm,
#define DETBOX_COL_END (DETBOX_COL_START + DETBOX_COLS) #define DETBOX_COL_END (DETBOX_COL_START + DETBOX_COLS)
#define FINGER_PRESENCE_THRESHOLD 100 #define FINGER_PRESENCE_THRESHOLD 100
static gboolean finger_is_present(unsigned char *data) static gboolean
finger_is_present (unsigned char *data)
{ {
int row; int row;
guint16 imgavg = 0; guint16 imgavg = 0;
for (row = DETBOX_ROW_START; row < DETBOX_ROW_END; row++) { for (row = DETBOX_ROW_START; row < DETBOX_ROW_END; row++)
{
unsigned char *rowdata = data + (row * IMG_WIDTH); unsigned char *rowdata = data + (row * IMG_WIDTH);
guint16 rowavg = 0; guint16 rowavg = 0;
int col; int col;
@ -161,51 +166,57 @@ static gboolean finger_is_present(unsigned char *data)
imgavg += rowavg; imgavg += rowavg;
} }
imgavg /= DETBOX_ROWS; imgavg /= DETBOX_ROWS;
fp_dbg("img avg %d", imgavg); fp_dbg ("img avg %d", imgavg);
return (imgavg <= FINGER_PRESENCE_THRESHOLD); return imgavg <= FINGER_PRESENCE_THRESHOLD;
} }
/***** IMAGE ACQUISITION *****/ /***** 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, static void
capture_cb (FpiUsbTransfer *transfer, FpDevice *device,
gpointer user_data, GError *error) gpointer user_data, GError *error)
{ {
FpImageDevice *imgdev = FP_IMAGE_DEVICE(device); FpImageDevice *imgdev = FP_IMAGE_DEVICE (device);
FpDeviceVcom5s *self = FPI_DEVICE_VCOM5S(device); FpDeviceVcom5s *self = FPI_DEVICE_VCOM5S (device);
if (error) { if (error)
fpi_ssm_mark_failed(transfer->ssm, error); {
fpi_ssm_mark_failed (transfer->ssm, error);
return; return;
} }
if (++self->capture_iteration == NR_REQS) { if (++self->capture_iteration == NR_REQS)
{
FpImage *img = self->capture_img; FpImage *img = self->capture_img;
/* must clear this early, otherwise the call chain takes us into /* must clear this early, otherwise the call chain takes us into
* loopsm_complete where we would free it, when in fact we are * loopsm_complete where we would free it, when in fact we are
* supposed to be handing off this image */ * supposed to be handing off this image */
self->capture_img = NULL; self->capture_img = NULL;
fpi_image_device_report_finger_status(imgdev, fpi_image_device_report_finger_status (imgdev,
finger_is_present(img->data)); finger_is_present (img->data));
fpi_image_device_image_captured(imgdev, img); fpi_image_device_image_captured (imgdev, img);
fpi_ssm_next_state(transfer->ssm); fpi_ssm_next_state (transfer->ssm);
} else { }
capture_iterate(transfer->ssm, device); else
{
capture_iterate (transfer->ssm, device);
} }
} }
static void static void
capture_iterate(FpiSsm *ssm, capture_iterate (FpiSsm *ssm,
FpDevice *dev) FpDevice *dev)
{ {
FpDeviceVcom5s *self = FPI_DEVICE_VCOM5S(dev); FpDeviceVcom5s *self = FPI_DEVICE_VCOM5S (dev);
int iteration = self->capture_iteration; int iteration = self->capture_iteration;
FpiUsbTransfer *transfer = fpi_usb_transfer_new(FP_DEVICE(dev)); FpiUsbTransfer *transfer = fpi_usb_transfer_new (FP_DEVICE (dev));
transfer->ssm = ssm; transfer->ssm = ssm;
transfer->short_is_error = TRUE; transfer->short_is_error = TRUE;
@ -221,16 +232,16 @@ capture_iterate(FpiSsm *ssm,
static void static void
sm_do_capture(FpiSsm *ssm, sm_do_capture (FpiSsm *ssm,
FpDevice *dev) FpDevice *dev)
{ {
FpDeviceVcom5s *self = FPI_DEVICE_VCOM5S(dev); FpDeviceVcom5s *self = FPI_DEVICE_VCOM5S (dev);
FpImageDeviceClass *cls = FP_IMAGE_DEVICE_GET_CLASS (dev); FpImageDeviceClass *cls = FP_IMAGE_DEVICE_GET_CLASS (dev);
G_DEBUG_HERE(); G_DEBUG_HERE ();
self->capture_img = fp_image_new (cls->img_width, cls->img_height); self->capture_img = fp_image_new (cls->img_width, cls->img_height);
self->capture_iteration = 0; self->capture_iteration = 0;
capture_iterate(ssm, dev); capture_iterate (ssm, dev);
} }
/***** CAPTURE LOOP *****/ /***** CAPTURE LOOP *****/
@ -244,105 +255,127 @@ enum loop_states {
LOOP_NUM_STATES, 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)) { switch (fpi_ssm_get_cur_state (ssm))
{
case LOOP_SET_CONTRAST: case LOOP_SET_CONTRAST:
sm_write_reg(ssm, dev, REG_CONTRAST, 0x01); sm_write_reg (ssm, dev, REG_CONTRAST, 0x01);
break; break;
case LOOP_SET_GAIN: case LOOP_SET_GAIN:
sm_write_reg(ssm, dev, REG_GAIN, 0x29); sm_write_reg (ssm, dev, REG_GAIN, 0x29);
break; break;
case LOOP_CMD_SCAN: case LOOP_CMD_SCAN:
if (self->deactivating) { if (self->deactivating)
fp_dbg("deactivating, marking completed"); {
fpi_ssm_mark_completed(ssm); fp_dbg ("deactivating, marking completed");
} else fpi_ssm_mark_completed (ssm);
sm_exec_cmd(ssm, dev, CMD_SCAN, 0x00); }
else
{
sm_exec_cmd (ssm, dev, CMD_SCAN, 0x00);
}
break; break;
case LOOP_CAPTURE: case LOOP_CAPTURE:
sm_do_capture(ssm, dev); sm_do_capture (ssm, dev);
break; break;
case LOOP_CAPTURE_DONE: case LOOP_CAPTURE_DONE:
fpi_ssm_jump_to_state(ssm, LOOP_CMD_SCAN); fpi_ssm_jump_to_state (ssm, LOOP_CMD_SCAN);
break; break;
default: default:
g_assert_not_reached (); g_assert_not_reached ();
} }
} }
static void loopsm_complete(FpiSsm *ssm, FpDevice *dev, void *user_data, static void
loopsm_complete (FpiSsm *ssm, FpDevice *dev, void *user_data,
GError *error) GError *error)
{ {
FpImageDevice *imgdev = FP_IMAGE_DEVICE (dev); FpImageDevice *imgdev = FP_IMAGE_DEVICE (dev);
FpDeviceVcom5s *self = FPI_DEVICE_VCOM5S(dev); FpDeviceVcom5s *self = FPI_DEVICE_VCOM5S (dev);
fpi_ssm_free(ssm); fpi_ssm_free (ssm);
g_object_unref (self->capture_img); g_object_unref (self->capture_img);
self->capture_img = NULL; self->capture_img = NULL;
self->loop_running = FALSE; self->loop_running = FALSE;
if (error && !self->deactivating) if (error && !self->deactivating)
fpi_image_device_session_error(imgdev, error); fpi_image_device_session_error (imgdev, error);
else if (error) else if (error)
g_error_free (error); g_error_free (error);
if (self->deactivating) if (self->deactivating)
fpi_image_device_deactivate_complete(imgdev, NULL); 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); FpDeviceVcom5s *self = FPI_DEVICE_VCOM5S (dev);
FpiSsm *ssm = fpi_ssm_new(FP_DEVICE(dev), loop_run_state, FpiSsm *ssm = fpi_ssm_new (FP_DEVICE (dev), loop_run_state,
LOOP_NUM_STATES, dev); LOOP_NUM_STATES, dev);
self->deactivating = FALSE; self->deactivating = FALSE;
fpi_ssm_start(ssm, loopsm_complete); fpi_ssm_start (ssm, loopsm_complete);
self->loop_running = TRUE; self->loop_running = TRUE;
fpi_image_device_activate_complete(dev, NULL); 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); FpDeviceVcom5s *self = FPI_DEVICE_VCOM5S (dev);
if (self->loop_running) if (self->loop_running)
self->deactivating = TRUE; self->deactivating = TRUE;
else else
fpi_image_device_deactivate_complete(dev, NULL); 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)), g_usb_device_release_interface (fpi_device_get_usb_device (FP_DEVICE (dev)),
0, 0, &error); 0, 0, &error);
fpi_image_device_close_complete(dev, error); fpi_image_device_close_complete (dev, error);
} }
static const FpIdEntry id_table [ ] = { static const FpIdEntry id_table[] = {
{ .vid = 0x061a, .pid = 0x0110, }, { .vid = 0x061a, .pid = 0x0110, },
{ .vid = 0, .pid = 0, .driver_data = 0 }, { .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) { static void
FpDeviceClass *dev_class = FP_DEVICE_CLASS(klass); fpi_device_vcom5s_class_init (FpDeviceVcom5sClass *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 = "vcom5s"; dev_class->id = "vcom5s";
dev_class->full_name = "Veridicom 5thSense"; dev_class->full_name = "Veridicom 5thSense";
@ -358,4 +391,3 @@ static void fpi_device_vcom5s_class_init(FpDeviceVcom5sClass *klass) {
img_class->img_width = IMG_WIDTH; img_class->img_width = IMG_WIDTH;
img_class->img_height = IMG_HEIGHT; img_class->img_height = IMG_HEIGHT;
} }

View file

@ -27,21 +27,23 @@ G_DEFINE_TYPE (FpDeviceVfs0050, fpi_device_vfs0050, FP_TYPE_IMAGE_DEVICE)
/* USB functions */ /* USB functions */
/* Callback for async_write */ /* Callback for async_write */
static void async_write_callback(FpiUsbTransfer *transfer, FpDevice *device, static void
async_write_callback (FpiUsbTransfer *transfer, FpDevice *device,
gpointer user_data, GError *error) gpointer user_data, GError *error)
{ {
if (error) { if (error)
fp_err("USB write transfer: %s", error->message); {
fpi_ssm_mark_failed(transfer->ssm, error); fp_err ("USB write transfer: %s", error->message);
fpi_ssm_mark_failed (transfer->ssm, error);
return; return;
} }
fpi_ssm_next_state(transfer->ssm); fpi_ssm_next_state (transfer->ssm);
} }
/* Send data to EP1, the only out endpoint */ /* Send data to EP1, the only out endpoint */
static void static void
async_write(FpiSsm *ssm, async_write (FpiSsm *ssm,
FpDevice *dev, FpDevice *dev,
void *data, void *data,
int len) int len)
@ -49,33 +51,35 @@ async_write(FpiSsm *ssm,
FpiUsbTransfer *transfer; FpiUsbTransfer *transfer;
transfer = fpi_usb_transfer_new (FP_DEVICE (dev)); transfer = fpi_usb_transfer_new (FP_DEVICE (dev));
fpi_usb_transfer_fill_bulk_full(transfer, 0x01, data, len, NULL); fpi_usb_transfer_fill_bulk_full (transfer, 0x01, data, len, NULL);
transfer->ssm = ssm; transfer->ssm = ssm;
transfer->short_is_error = TRUE; transfer->short_is_error = TRUE;
fpi_usb_transfer_submit(transfer, VFS_USB_TIMEOUT, NULL, fpi_usb_transfer_submit (transfer, VFS_USB_TIMEOUT, NULL,
async_write_callback, NULL); async_write_callback, NULL);
fpi_usb_transfer_unref(transfer); fpi_usb_transfer_unref (transfer);
} }
/* Callback for async_read */ /* Callback for async_read */
static void async_read_callback(FpiUsbTransfer *transfer, FpDevice *device, static void
async_read_callback (FpiUsbTransfer *transfer, FpDevice *device,
gpointer user_data, GError *error) gpointer user_data, GError *error)
{ {
int ep = transfer->endpoint; int ep = transfer->endpoint;
if (error) { if (error)
fp_err("USB read transfer on endpoint %d: %s", ep - 0x80, {
fp_err ("USB read transfer on endpoint %d: %s", ep - 0x80,
error->message); error->message);
fpi_ssm_mark_failed(transfer->ssm, error); fpi_ssm_mark_failed (transfer->ssm, error);
return; return;
} }
fpi_ssm_next_state(transfer->ssm); fpi_ssm_next_state (transfer->ssm);
} }
/* Receive data from the given ep and either discard or fill the given buffer */ /* Receive data from the given ep and either discard or fill the given buffer */
static void static void
async_read(FpiSsm *ssm, async_read (FpiSsm *ssm,
FpDevice *dev, FpDevice *dev,
int ep, int ep,
void *data, void *data,
@ -90,52 +94,57 @@ async_read(FpiSsm *ssm,
transfer->ssm = ssm; transfer->ssm = ssm;
transfer->short_is_error = TRUE; transfer->short_is_error = TRUE;
if (data == NULL) { if (data == NULL)
{
data = g_malloc0 (len); data = g_malloc0 (len);
free_func = g_free; free_func = g_free;
} }
/* 0x83 is the only interrupt endpoint */ /* 0x83 is the only interrupt endpoint */
if (ep == EP3_IN) if (ep == EP3_IN)
fpi_usb_transfer_fill_interrupt_full(transfer, ep, data, len, free_func); fpi_usb_transfer_fill_interrupt_full (transfer, ep, data, len, free_func);
else else
fpi_usb_transfer_fill_bulk_full(transfer, ep, data, len, free_func); fpi_usb_transfer_fill_bulk_full (transfer, ep, data, len, free_func);
fpi_usb_transfer_submit(transfer, VFS_USB_TIMEOUT, NULL, fpi_usb_transfer_submit (transfer, VFS_USB_TIMEOUT, NULL,
async_read_callback, NULL); async_read_callback, NULL);
fpi_usb_transfer_unref(transfer); fpi_usb_transfer_unref (transfer);
} }
/* Callback for async_abort */ /* Callback for async_abort */
static void async_abort_callback(FpiUsbTransfer *transfer, FpDevice *device, static void
async_abort_callback (FpiUsbTransfer *transfer, FpDevice *device,
gpointer user_data, GError *error) gpointer user_data, GError *error)
{ {
int ep = transfer->endpoint; int ep = transfer->endpoint;
/* In normal case endpoint is empty */ /* In normal case endpoint is empty */
if (g_error_matches (error, G_USB_DEVICE_ERROR, G_USB_DEVICE_ERROR_TIMED_OUT)) { if (g_error_matches (error, G_USB_DEVICE_ERROR, G_USB_DEVICE_ERROR_TIMED_OUT))
{
g_free (error); g_free (error);
fpi_ssm_next_state(transfer->ssm); fpi_ssm_next_state (transfer->ssm);
return; return;
} }
if (error) { if (error)
fp_err("USB write transfer: %s", error->message); {
fpi_ssm_mark_failed(transfer->ssm, error); fp_err ("USB write transfer: %s", error->message);
fpi_ssm_mark_failed (transfer->ssm, error);
return; return;
} }
/* Don't stop process, only print warning */ /* Don't stop process, only print warning */
fp_warn("Endpoint %d had extra %zd bytes readable", ep - 0x80, fp_warn ("Endpoint %d had extra %zd bytes readable", ep - 0x80,
transfer->actual_length); transfer->actual_length);
fpi_ssm_jump_to_state(transfer->ssm, fpi_ssm_jump_to_state (transfer->ssm,
fpi_ssm_get_cur_state(transfer->ssm)); fpi_ssm_get_cur_state (transfer->ssm));
} }
/* Receive data from the given ep; continues to the next state once no /* Receive data from the given ep; continues to the next state once no
* more data is available. Otherwise the current state is repeated. */ * more data is available. Otherwise the current state is repeated. */
static void async_abort(FpDevice *dev, FpiSsm *ssm, int ep) static void
async_abort (FpDevice *dev, FpiSsm *ssm, int ep)
{ {
FpiUsbTransfer *transfer; FpiUsbTransfer *transfer;
@ -149,31 +158,35 @@ static void async_abort(FpDevice *dev, FpiSsm *ssm, int ep)
else else
fpi_usb_transfer_fill_bulk (transfer, ep, VFS_USB_BUFFER_SIZE); fpi_usb_transfer_fill_bulk (transfer, ep, VFS_USB_BUFFER_SIZE);
fpi_usb_transfer_submit(transfer, VFS_USB_ABORT_TIMEOUT, NULL, fpi_usb_transfer_submit (transfer, VFS_USB_ABORT_TIMEOUT, NULL,
async_abort_callback, NULL); async_abort_callback, NULL);
fpi_usb_transfer_unref(transfer); fpi_usb_transfer_unref (transfer);
} }
/* Image processing functions */ /* Image processing functions */
/* Pixel getter for fpi_assemble_lines */ /* Pixel getter for fpi_assemble_lines */
static unsigned char vfs0050_get_pixel(struct fpi_line_asmbl_ctx *ctx, static unsigned char
vfs0050_get_pixel (struct fpi_line_asmbl_ctx *ctx,
GSList * line, unsigned int x) GSList * line, unsigned int x)
{ {
return ((struct vfs_line *)line->data)->data[x]; return ((struct vfs_line *) line->data)->data[x];
} }
/* Deviation getter for fpi_assemble_lines */ /* Deviation getter for fpi_assemble_lines */
static int vfs0050_get_difference(struct fpi_line_asmbl_ctx *ctx, static int
vfs0050_get_difference (struct fpi_line_asmbl_ctx *ctx,
GSList * line_list_1, GSList * line_list_2) GSList * line_list_1, GSList * line_list_2)
{ {
struct vfs_line *line1 = line_list_1->data; struct vfs_line *line1 = line_list_1->data;
struct vfs_line *line2 = line_list_2->data; struct vfs_line *line2 = line_list_2->data;
const int shift = (VFS_IMAGE_WIDTH - VFS_NEXT_LINE_WIDTH) / 2 - 1; const int shift = (VFS_IMAGE_WIDTH - VFS_NEXT_LINE_WIDTH) / 2 - 1;
int res = 0; int res = 0;
for (int i = 0; i < VFS_NEXT_LINE_WIDTH; ++i) {
for (int i = 0; i < VFS_NEXT_LINE_WIDTH; ++i)
{
int x = int x =
(int)line1->next_line_part[i] - (int)line2->data[shift + i]; (int) line1->next_line_part[i] - (int) line2->data[shift + i];
res += x * x; res += x * x;
} }
return res; return res;
@ -182,13 +195,15 @@ static int vfs0050_get_difference(struct fpi_line_asmbl_ctx *ctx,
#define VFS_NOISE_THRESHOLD 40 #define VFS_NOISE_THRESHOLD 40
/* Checks whether line is noise or not using hardware parameters */ /* Checks whether line is noise or not using hardware parameters */
static char is_noise(struct vfs_line *line) static char
is_noise (struct vfs_line *line)
{ {
int val1 = line->noise_hash_1; int val1 = line->noise_hash_1;
int val2 = line->noise_hash_2; int val2 = line->noise_hash_2;
if (val1 > VFS_NOISE_THRESHOLD
&& val1 < 256 - VFS_NOISE_THRESHOLD if (val1 > VFS_NOISE_THRESHOLD &&
&& val2 > VFS_NOISE_THRESHOLD && val2 < 256 - VFS_NOISE_THRESHOLD) val1 < 256 - VFS_NOISE_THRESHOLD &&
val2 > VFS_NOISE_THRESHOLD && val2 < 256 - VFS_NOISE_THRESHOLD)
return 1; return 1;
return 0; return 0;
} }
@ -205,15 +220,17 @@ static struct fpi_line_asmbl_ctx assembling_ctx = {
}; };
/* Processes image before submitting */ /* Processes image before submitting */
static FpImage *prepare_image(FpDeviceVfs0050 *vdev) static FpImage *
prepare_image (FpDeviceVfs0050 *vdev)
{ {
int height = vdev->bytes / VFS_LINE_SIZE; int height = vdev->bytes / VFS_LINE_SIZE;
/* Noise cleaning. IMHO, it works pretty well /* Noise cleaning. IMHO, it works pretty well
I've not detected cases when it doesn't work or cuts a part of the finger I've not detected cases when it doesn't work or cuts a part of the finger
Noise arises at the end of scan when some water remains on the scanner */ Noise arises at the end of scan when some water remains on the scanner */
while (height > 0) { while (height > 0)
if (!is_noise(vdev->lines_buffer + height - 1)) {
if (!is_noise (vdev->lines_buffer + height - 1))
break; break;
--height; --height;
} }
@ -227,274 +244,298 @@ static FpImage *prepare_image(FpDeviceVfs0050 *vdev)
/* Building GSList */ /* Building GSList */
GSList *lines = NULL; GSList *lines = NULL;
for (int i = height - 1; i >= 0; --i) for (int i = height - 1; i >= 0; --i)
lines = g_slist_prepend(lines, vdev->lines_buffer + i); lines = g_slist_prepend (lines, vdev->lines_buffer + i);
/* Perform line assembling */ /* Perform line assembling */
FpImage *img = fpi_assemble_lines(&assembling_ctx, lines, height); FpImage *img = fpi_assemble_lines (&assembling_ctx, lines, height);
g_slist_free(lines); g_slist_free (lines);
return img; return img;
} }
/* Processes and submits image after fingerprint received */ /* Processes and submits image after fingerprint received */
static void submit_image(FpDeviceVfs0050 *self) static void
submit_image (FpDeviceVfs0050 *self)
{ {
FpImageDevice *idev = FP_IMAGE_DEVICE(self); FpImageDevice *idev = FP_IMAGE_DEVICE (self);
/* We were not asked to submit image actually */ /* We were not asked to submit image actually */
if (!self->active) if (!self->active)
return; return;
FpImage *img = prepare_image(self); FpImage *img = prepare_image (self);
if (!img) if (!img)
fpi_image_device_retry_scan(idev, FP_DEVICE_RETRY_TOO_SHORT); fpi_image_device_retry_scan (idev, FP_DEVICE_RETRY_TOO_SHORT);
else else
fpi_image_device_image_captured(idev, img); fpi_image_device_image_captured (idev, img);
/* Finger not on the scanner */ /* Finger not on the scanner */
fpi_image_device_report_finger_status(idev, FALSE); fpi_image_device_report_finger_status (idev, FALSE);
} }
/* Proto functions */ /* Proto functions */
/* SSM loop for clear_ep2 */ /* SSM loop for clear_ep2 */
static void static void
clear_ep2_ssm(FpiSsm *ssm, FpDevice *dev, void *user_data) clear_ep2_ssm (FpiSsm *ssm, FpDevice *dev, void *user_data)
{ {
char command04 = 0x04; char command04 = 0x04;
switch (fpi_ssm_get_cur_state(ssm)) { switch (fpi_ssm_get_cur_state (ssm))
{
case SUBSM1_COMMAND_04: case SUBSM1_COMMAND_04:
async_write(ssm, dev, &command04, sizeof(command04)); async_write (ssm, dev, &command04, sizeof (command04));
break; break;
case SUBSM1_RETURN_CODE: case SUBSM1_RETURN_CODE:
async_read(ssm, dev, 1, NULL, 2); async_read (ssm, dev, 1, NULL, 2);
break; break;
case SUBSM1_ABORT_2: case SUBSM1_ABORT_2:
async_abort(dev, ssm, 2); async_abort (dev, ssm, 2);
break; break;
default: default:
fp_err("Unknown SUBSM1 state"); fp_err ("Unknown SUBSM1 state");
fpi_ssm_mark_failed(ssm, fpi_device_error_new (FP_DEVICE_ERROR_PROTO)); fpi_ssm_mark_failed (ssm, fpi_device_error_new (FP_DEVICE_ERROR_PROTO));
} }
} }
/* Send command to clear EP2 */ /* Send command to clear EP2 */
static void static void
clear_ep2(FpDevice *dev, clear_ep2 (FpDevice *dev,
FpiSsm *ssm) FpiSsm *ssm)
{ {
FpiSsm *subsm = FpiSsm *subsm =
fpi_ssm_new(dev, clear_ep2_ssm, SUBSM1_STATES, NULL); fpi_ssm_new (dev, clear_ep2_ssm, SUBSM1_STATES, NULL);
fpi_ssm_start_subsm(ssm, subsm);
fpi_ssm_start_subsm (ssm, subsm);
} }
static void send_control_packet_ssm(FpiSsm *ssm, FpDevice *dev, static void
send_control_packet_ssm (FpiSsm *ssm, FpDevice *dev,
void *user_data) void *user_data)
{ {
FpDeviceVfs0050 *self = FPI_DEVICE_VFS0050(dev); FpDeviceVfs0050 *self = FPI_DEVICE_VFS0050 (dev);
switch (fpi_ssm_get_cur_state(ssm)) { switch (fpi_ssm_get_cur_state (ssm))
{
case SUBSM2_SEND_CONTROL: case SUBSM2_SEND_CONTROL:
async_write(ssm, dev, self->control_packet, async_write (ssm, dev, self->control_packet,
VFS_CONTROL_PACKET_SIZE); VFS_CONTROL_PACKET_SIZE);
break; break;
case SUBSM2_RETURN_CODE: case SUBSM2_RETURN_CODE:
async_read(ssm, dev, 1, NULL, 2); async_read (ssm, dev, 1, NULL, 2);
break; break;
case SUBSM2_SEND_COMMIT: case SUBSM2_SEND_COMMIT:
/* next_receive_* packets could be sent only in pair */ /* next_receive_* packets could be sent only in pair */
if (self->control_packet == next_receive_1) { if (self->control_packet == next_receive_1)
{
self->control_packet = next_receive_2; self->control_packet = next_receive_2;
fpi_ssm_jump_to_state(ssm, SUBSM2_SEND_CONTROL); fpi_ssm_jump_to_state (ssm, SUBSM2_SEND_CONTROL);
break; break;
} }
/* commit_out in Windows differs in each commit, but I send the same each time */ /* commit_out in Windows differs in each commit, but I send the same each time */
async_write(ssm, dev, commit_out, sizeof(commit_out)); async_write (ssm, dev, commit_out, sizeof (commit_out));
break; break;
case SUBSM2_COMMIT_RESPONSE: case SUBSM2_COMMIT_RESPONSE:
async_read(ssm, dev, 1, NULL, VFS_COMMIT_RESPONSE_SIZE); async_read (ssm, dev, 1, NULL, VFS_COMMIT_RESPONSE_SIZE);
break; break;
case SUBSM2_READ_EMPTY_INTERRUPT: case SUBSM2_READ_EMPTY_INTERRUPT:
/* I don't know how to check result, it could be different /* I don't know how to check result, it could be different
* NOTE: I guess this comment relates to the above read. */ * NOTE: I guess this comment relates to the above read. */
async_read(ssm, dev, 3, self->interrupt, VFS_INTERRUPT_SIZE); async_read (ssm, dev, 3, self->interrupt, VFS_INTERRUPT_SIZE);
break; break;
case SUBSM2_ABORT_3: case SUBSM2_ABORT_3:
/* Check that interrupt is empty */ /* Check that interrupt is empty */
if (memcmp if (memcmp
(self->interrupt, empty_interrupt, VFS_INTERRUPT_SIZE)) { (self->interrupt, empty_interrupt, VFS_INTERRUPT_SIZE))
fp_err("Unknown SUBSM2 state"); {
fpi_ssm_mark_failed(ssm, fpi_device_error_new (FP_DEVICE_ERROR_PROTO)); fp_err ("Unknown SUBSM2 state");
fpi_ssm_mark_failed (ssm, fpi_device_error_new (FP_DEVICE_ERROR_PROTO));
break; break;
} }
async_abort(dev, ssm, 3); async_abort (dev, ssm, 3);
break; break;
case SUBSM2_CLEAR_EP2: case SUBSM2_CLEAR_EP2:
/* After turn_on Windows doesn't clear EP2 */ /* After turn_on Windows doesn't clear EP2 */
if (self->control_packet != turn_on) if (self->control_packet != turn_on)
clear_ep2(dev, ssm); clear_ep2 (dev, ssm);
else else
fpi_ssm_next_state(ssm); fpi_ssm_next_state (ssm);
break; break;
default: default:
fp_err("Unknown SUBSM2 state"); fp_err ("Unknown SUBSM2 state");
fpi_ssm_mark_failed(ssm, fpi_device_error_new (FP_DEVICE_ERROR_PROTO)); fpi_ssm_mark_failed (ssm, fpi_device_error_new (FP_DEVICE_ERROR_PROTO));
} }
} }
/* Send device state control packet */ /* Send device state control packet */
static void static void
send_control_packet(FpiSsm *ssm, send_control_packet (FpiSsm *ssm,
FpDevice *dev) FpDevice *dev)
{ {
FpiSsm *subsm = FpiSsm *subsm =
fpi_ssm_new(dev, send_control_packet_ssm, fpi_ssm_new (dev, send_control_packet_ssm,
SUBSM2_STATES, NULL); SUBSM2_STATES, NULL);
fpi_ssm_start_subsm(ssm, subsm);
fpi_ssm_start_subsm (ssm, subsm);
} }
/* Clears all fprint data */ /* Clears all fprint data */
static void clear_data(FpDeviceVfs0050 *vdev) static void
clear_data (FpDeviceVfs0050 *vdev)
{ {
g_free(vdev->lines_buffer); g_free (vdev->lines_buffer);
vdev->lines_buffer = NULL; vdev->lines_buffer = NULL;
vdev->memory = vdev->bytes = 0; vdev->memory = vdev->bytes = 0;
} }
/* After receiving interrupt from EP3 */ /* After receiving interrupt from EP3 */
static void interrupt_callback(FpiUsbTransfer *transfer, FpDevice *device, static void
interrupt_callback (FpiUsbTransfer *transfer, FpDevice *device,
gpointer user_data, GError *error) gpointer user_data, GError *error)
{ {
FpDeviceVfs0050 *self = FPI_DEVICE_VFS0050(device); FpDeviceVfs0050 *self = FPI_DEVICE_VFS0050 (device);
char *interrupt = transfer->buffer; char *interrupt = transfer->buffer;
/* we expect a cancellation error when the device is deactivating /* we expect a cancellation error when the device is deactivating
* go into the SSM_CLEAR_EP2 state in that case. */ * go into the SSM_CLEAR_EP2 state in that case. */
if (!self->active && g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { if (!self->active && g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
{
g_error_free (error); g_error_free (error);
fpi_ssm_jump_to_state(transfer->ssm, SSM_CLEAR_EP2); fpi_ssm_jump_to_state (transfer->ssm, SSM_CLEAR_EP2);
return; return;
} }
if (error) { if (error)
fp_err("USB read interrupt transfer: %s", {
fp_err ("USB read interrupt transfer: %s",
error->message); error->message);
fpi_ssm_mark_failed(transfer->ssm, error); fpi_ssm_mark_failed (transfer->ssm, error);
return; return;
} }
/* Standard interrupts */ /* Standard interrupts */
if (memcmp(interrupt, interrupt1, VFS_INTERRUPT_SIZE) == 0 || if (memcmp (interrupt, interrupt1, VFS_INTERRUPT_SIZE) == 0 ||
memcmp(interrupt, interrupt2, VFS_INTERRUPT_SIZE) == 0 || memcmp (interrupt, interrupt2, VFS_INTERRUPT_SIZE) == 0 ||
memcmp(interrupt, interrupt3, VFS_INTERRUPT_SIZE) == 0) { memcmp (interrupt, interrupt3, VFS_INTERRUPT_SIZE) == 0)
{
/* Go to the next ssm stage */ /* Go to the next ssm stage */
fpi_ssm_next_state(transfer->ssm); fpi_ssm_next_state (transfer->ssm);
return; return;
} }
/* When finger is on the scanner before turn_on */ /* When finger is on the scanner before turn_on */
if (interrupt[0] == 0x01) { if (interrupt[0] == 0x01)
fp_warn("Finger is already on the scanner"); {
fp_warn ("Finger is already on the scanner");
/* Go to the next ssm stage */ /* Go to the next ssm stage */
fpi_ssm_next_state(transfer->ssm); fpi_ssm_next_state (transfer->ssm);
return; return;
} }
/* Unknown interrupt; abort the session */ /* Unknown interrupt; abort the session */
fp_err("Unknown interrupt '%02x:%02x:%02x:%02x:%02x'!", fp_err ("Unknown interrupt '%02x:%02x:%02x:%02x:%02x'!",
interrupt[0] & 0xff, interrupt[1] & 0xff, interrupt[2] & 0xff, interrupt[0] & 0xff, interrupt[1] & 0xff, interrupt[2] & 0xff,
interrupt[3] & 0xff, interrupt[4] & 0xff); interrupt[3] & 0xff, interrupt[4] & 0xff);
/* Abort ssm */ /* Abort ssm */
fpi_ssm_mark_failed(transfer->ssm, fpi_ssm_mark_failed (transfer->ssm,
fpi_device_error_new (FP_DEVICE_ERROR_PROTO)); fpi_device_error_new (FP_DEVICE_ERROR_PROTO));
} }
static void receive_callback(FpiUsbTransfer *transfer, FpDevice *device, static void
receive_callback (FpiUsbTransfer *transfer, FpDevice *device,
gpointer user_data, GError *error) gpointer user_data, GError *error)
{ {
FpDeviceVfs0050 *self = FPI_DEVICE_VFS0050(device); FpDeviceVfs0050 *self = FPI_DEVICE_VFS0050 (device);
if (error && !g_error_matches (error, G_USB_DEVICE_ERROR, G_USB_DEVICE_ERROR_TIMED_OUT)) { if (error && !g_error_matches (error, G_USB_DEVICE_ERROR, G_USB_DEVICE_ERROR_TIMED_OUT))
fp_err("USB read transfer: %s", error->message); {
fp_err ("USB read transfer: %s", error->message);
fpi_ssm_mark_failed(transfer->ssm, error); fpi_ssm_mark_failed (transfer->ssm, error);
return; return;
} }
if (error) if (error)
g_error_free (error); g_error_free (error);
/* Check if fingerprint data is over */ /* Check if fingerprint data is over */
if (transfer->actual_length == 0) { if (transfer->actual_length == 0)
fpi_ssm_next_state(transfer->ssm); {
} else { fpi_ssm_next_state (transfer->ssm);
}
else
{
self->bytes += transfer->actual_length; self->bytes += transfer->actual_length;
/* We need more data */ /* We need more data */
fpi_ssm_jump_to_state(transfer->ssm, fpi_ssm_jump_to_state (transfer->ssm,
fpi_ssm_get_cur_state(transfer->ssm)); fpi_ssm_get_cur_state (transfer->ssm));
} }
} }
/* SSM stub to prepare device to another scan after orange light was on */ /* SSM stub to prepare device to another scan after orange light was on */
static void static void
another_scan(FpDevice *dev, another_scan (FpDevice *dev,
void *data) void *data)
{ {
FpiSsm *ssm = data; FpiSsm *ssm = data;
fpi_ssm_jump_to_state(ssm, SSM_TURN_ON);
fpi_ssm_jump_to_state (ssm, SSM_TURN_ON);
} }
/* Main SSM loop */ /* Main SSM loop */
static void activate_ssm(FpiSsm *ssm, FpDevice *dev, void *user_data) static void
activate_ssm (FpiSsm *ssm, FpDevice *dev, void *user_data)
{ {
FpImageDevice *idev = FP_IMAGE_DEVICE (dev); FpImageDevice *idev = FP_IMAGE_DEVICE (dev);
FpDeviceVfs0050 *self = FPI_DEVICE_VFS0050(dev); FpDeviceVfs0050 *self = FPI_DEVICE_VFS0050 (dev);
switch (fpi_ssm_get_cur_state(ssm)) { switch (fpi_ssm_get_cur_state (ssm))
{
case SSM_INITIAL_ABORT_1: case SSM_INITIAL_ABORT_1:
async_abort(dev, ssm, 1); async_abort (dev, ssm, 1);
break; break;
case SSM_INITIAL_ABORT_2: case SSM_INITIAL_ABORT_2:
async_abort(dev, ssm, 2); async_abort (dev, ssm, 2);
break; break;
case SSM_INITIAL_ABORT_3: case SSM_INITIAL_ABORT_3:
async_abort(dev, ssm, 3); async_abort (dev, ssm, 3);
break; break;
case SSM_CLEAR_EP2: case SSM_CLEAR_EP2:
clear_ep2(dev, ssm); clear_ep2 (dev, ssm);
break; break;
case SSM_TURN_OFF: case SSM_TURN_OFF:
/* Set control_packet argument */ /* Set control_packet argument */
self->control_packet = turn_off; self->control_packet = turn_off;
send_control_packet(ssm, dev); send_control_packet (ssm, dev);
break; break;
case SSM_TURN_ON: case SSM_TURN_ON:
if (!self->active) { if (!self->active)
{
/* The only correct exit */ /* The only correct exit */
fpi_ssm_mark_completed(ssm); fpi_ssm_mark_completed (ssm);
if (self->need_report) { if (self->need_report)
fpi_image_device_deactivate_complete(idev, {
fpi_image_device_deactivate_complete (idev,
NULL); NULL);
self->need_report = 0; self->need_report = 0;
} }
@ -503,7 +544,7 @@ static void activate_ssm(FpiSsm *ssm, FpDevice *dev, void *user_data)
/* Set control_packet argument */ /* Set control_packet argument */
self->control_packet = turn_on; self->control_packet = turn_on;
send_control_packet(ssm, dev); send_control_packet (ssm, dev);
break; break;
case SSM_ASK_INTERRUPT: { case SSM_ASK_INTERRUPT: {
@ -511,8 +552,9 @@ static void activate_ssm(FpiSsm *ssm, FpDevice *dev, void *user_data)
/* Activated, light must be blinking now */ /* Activated, light must be blinking now */
/* If we first time here, report that activate completed */ /* If we first time here, report that activate completed */
if (self->need_report) { if (self->need_report)
fpi_image_device_activate_complete(idev, NULL); {
fpi_image_device_activate_complete (idev, NULL);
self->need_report = 0; self->need_report = 0;
} }
@ -528,11 +570,12 @@ static void activate_ssm(FpiSsm *ssm, FpDevice *dev, void *user_data)
fpi_usb_transfer_unref (transfer); fpi_usb_transfer_unref (transfer);
/* I've put it here to be sure that data is cleared */ /* I've put it here to be sure that data is cleared */
clear_data(self); clear_data (self);
fpi_ssm_next_state(ssm); fpi_ssm_next_state (ssm);
break; break;
} }
case SSM_WAIT_INTERRUPT: case SSM_WAIT_INTERRUPT:
/* TODO: This state is unused at this point. When we /* TODO: This state is unused at this point. When we
* are in this state, then a user cancellation will * are in this state, then a user cancellation will
@ -545,110 +588,119 @@ static void activate_ssm(FpiSsm *ssm, FpDevice *dev, void *user_data)
case SSM_RECEIVE_FINGER: { case SSM_RECEIVE_FINGER: {
FpiUsbTransfer *transfer; FpiUsbTransfer *transfer;
if (self->memory == 0) { if (self->memory == 0)
{
/* Initialize fingerprint buffer */ /* Initialize fingerprint buffer */
g_free(self->lines_buffer); g_free (self->lines_buffer);
self->memory = VFS_USB_BUFFER_SIZE; self->memory = VFS_USB_BUFFER_SIZE;
self->lines_buffer = g_malloc(self->memory); self->lines_buffer = g_malloc (self->memory);
self->bytes = 0; self->bytes = 0;
/* Finger is on the scanner */ /* Finger is on the scanner */
fpi_image_device_report_finger_status(idev, TRUE); fpi_image_device_report_finger_status (idev, TRUE);
} }
/* Increase buffer size while it's insufficient */ /* Increase buffer size while it's insufficient */
while (self->bytes + VFS_USB_BUFFER_SIZE > self->memory) { while (self->bytes + VFS_USB_BUFFER_SIZE > self->memory)
{
self->memory <<= 1; self->memory <<= 1;
self->lines_buffer = self->lines_buffer =
(struct vfs_line *)g_realloc(self->lines_buffer, (struct vfs_line *) g_realloc (self->lines_buffer,
self->memory); self->memory);
} }
/* Receive chunk of data */ /* Receive chunk of data */
transfer = fpi_usb_transfer_new (dev); transfer = fpi_usb_transfer_new (dev);
fpi_usb_transfer_fill_bulk_full(transfer, 0x82, fpi_usb_transfer_fill_bulk_full (transfer, 0x82,
(void *)self->lines_buffer + self->bytes, (void *) self->lines_buffer + self->bytes,
VFS_USB_BUFFER_SIZE, NULL); VFS_USB_BUFFER_SIZE, NULL);
transfer->ssm = ssm; transfer->ssm = ssm;
fpi_usb_transfer_submit(transfer, VFS_USB_TIMEOUT, NULL, fpi_usb_transfer_submit (transfer, VFS_USB_TIMEOUT, NULL,
receive_callback, NULL); receive_callback, NULL);
fpi_usb_transfer_unref(transfer); fpi_usb_transfer_unref (transfer);
break; break;
} }
case SSM_SUBMIT_IMAGE: case SSM_SUBMIT_IMAGE:
submit_image(self); submit_image (self);
clear_data(self); clear_data (self);
/* Wait for probable vdev->active changing */ /* Wait for probable vdev->active changing */
fpi_device_add_timeout(dev, VFS_SSM_TIMEOUT, fpi_device_add_timeout (dev, VFS_SSM_TIMEOUT,
fpi_ssm_next_state_timeout_cb, ssm); fpi_ssm_next_state_timeout_cb, ssm);
break; break;
case SSM_NEXT_RECEIVE: case SSM_NEXT_RECEIVE:
if (!self->active) { if (!self->active)
{
/* It's the last scan */ /* It's the last scan */
fpi_ssm_jump_to_state(ssm, SSM_CLEAR_EP2); fpi_ssm_jump_to_state (ssm, SSM_CLEAR_EP2);
break; break;
} }
/* Set control_packet argument */ /* Set control_packet argument */
self->control_packet = next_receive_1; self->control_packet = next_receive_1;
send_control_packet(ssm, dev); send_control_packet (ssm, dev);
break; break;
case SSM_WAIT_ANOTHER_SCAN: case SSM_WAIT_ANOTHER_SCAN:
/* Orange light is on now */ /* Orange light is on now */
fpi_device_add_timeout(dev, VFS_SSM_ORANGE_TIMEOUT, fpi_device_add_timeout (dev, VFS_SSM_ORANGE_TIMEOUT,
another_scan, ssm); another_scan, ssm);
break; break;
default: default:
fp_err("Unknown state"); fp_err ("Unknown state");
fpi_ssm_mark_failed(ssm, fpi_device_error_new (FP_DEVICE_ERROR_PROTO)); fpi_ssm_mark_failed (ssm, fpi_device_error_new (FP_DEVICE_ERROR_PROTO));
} }
} }
/* Driver functions */ /* Driver functions */
/* Callback for dev_activate ssm */ /* Callback for dev_activate ssm */
static void dev_activate_callback(FpiSsm *ssm, FpDevice *dev, static void
dev_activate_callback (FpiSsm *ssm, FpDevice *dev,
void *user_data, GError *error) void *user_data, GError *error)
{ {
FpDeviceVfs0050 *self = FPI_DEVICE_VFS0050(dev); FpDeviceVfs0050 *self = FPI_DEVICE_VFS0050 (dev);
self->ssm_active = 0; self->ssm_active = 0;
if (error) { if (error)
{
g_warning ("Unhandled device activation error: %s", error->message); g_warning ("Unhandled device activation error: %s", error->message);
g_error_free (error); g_error_free (error);
} }
fpi_ssm_free(ssm); fpi_ssm_free (ssm);
} }
/* Activate device */ /* Activate device */
static void dev_activate(FpImageDevice *idev) static void
dev_activate (FpImageDevice *idev)
{ {
FpDeviceVfs0050 *self = FPI_DEVICE_VFS0050(idev); FpDeviceVfs0050 *self = FPI_DEVICE_VFS0050 (idev);
/* Initialize flags */ /* Initialize flags */
self->active = 1; self->active = 1;
self->need_report = 1; self->need_report = 1;
self->ssm_active = 1; self->ssm_active = 1;
FpiSsm *ssm = fpi_ssm_new(FP_DEVICE(idev), activate_ssm, SSM_STATES, FpiSsm *ssm = fpi_ssm_new (FP_DEVICE (idev), activate_ssm, SSM_STATES,
idev); idev);
fpi_ssm_start(ssm, dev_activate_callback); fpi_ssm_start (ssm, dev_activate_callback);
} }
/* Deactivate device */ /* Deactivate device */
static void dev_deactivate(FpImageDevice *idev) static void
dev_deactivate (FpImageDevice *idev)
{ {
FpDeviceVfs0050 *self = FPI_DEVICE_VFS0050(idev); FpDeviceVfs0050 *self = FPI_DEVICE_VFS0050 (idev);
if (!self->ssm_active) { if (!self->ssm_active)
fpi_image_device_deactivate_complete(idev, NULL); {
fpi_image_device_deactivate_complete (idev, NULL);
return; return;
} }
@ -658,58 +710,65 @@ static void dev_deactivate(FpImageDevice *idev)
} }
/* Callback for dev_open ssm */ /* Callback for dev_open ssm */
static void dev_open_callback(FpiSsm *ssm, FpDevice *dev, void *user_data, static void
dev_open_callback (FpiSsm *ssm, FpDevice *dev, void *user_data,
GError *error) GError *error)
{ {
/* Notify open complete */ /* Notify open complete */
fpi_image_device_open_complete(FP_IMAGE_DEVICE (dev), error); fpi_image_device_open_complete (FP_IMAGE_DEVICE (dev), error);
fpi_ssm_free(ssm); fpi_ssm_free (ssm);
} }
/* Open device */ /* Open device */
static void dev_open(FpImageDevice *idev) static void
dev_open (FpImageDevice *idev)
{ {
GError *error = NULL; GError *error = NULL;
/* Claim usb interface */ /* Claim usb interface */
if (!g_usb_device_claim_interface (fpi_device_get_usb_device(FP_DEVICE(idev)), 0, 0, &error)) { if (!g_usb_device_claim_interface (fpi_device_get_usb_device (FP_DEVICE (idev)), 0, 0, &error))
{
fpi_image_device_open_complete (idev, error); fpi_image_device_open_complete (idev, error);
return; return;
} }
/* Clearing previous device state */ /* Clearing previous device state */
FpiSsm *ssm = fpi_ssm_new(FP_DEVICE(idev), activate_ssm, SSM_STATES, NULL); FpiSsm *ssm = fpi_ssm_new (FP_DEVICE (idev), activate_ssm, SSM_STATES, NULL);
fpi_ssm_start(ssm, dev_open_callback); fpi_ssm_start (ssm, dev_open_callback);
} }
/* Close device */ /* Close device */
static void dev_close(FpImageDevice *idev) static void
dev_close (FpImageDevice *idev)
{ {
GError *error = NULL; GError *error = NULL;
FpDeviceVfs0050 *self = FPI_DEVICE_VFS0050(idev); FpDeviceVfs0050 *self = FPI_DEVICE_VFS0050 (idev);
clear_data(self); clear_data (self);
/* Release usb interface */ /* Release usb interface */
g_usb_device_release_interface(fpi_device_get_usb_device(FP_DEVICE(idev)), g_usb_device_release_interface (fpi_device_get_usb_device (FP_DEVICE (idev)),
0, 0, &error); 0, 0, &error);
/* Notify close complete */ /* Notify close complete */
fpi_image_device_close_complete(idev, error); fpi_image_device_close_complete (idev, error);
} }
/* Usb id table of device */ /* Usb id table of device */
static const FpIdEntry id_table [ ] = { static const FpIdEntry id_table[] = {
{.vid = 0x138a, .pid = 0x0050, {.vid = 0x138a, .pid = 0x0050, },
},
{.vid = 0, .pid = 0, .driver_data = 0}, {.vid = 0, .pid = 0, .driver_data = 0},
}; };
static void fpi_device_vfs0050_init(FpDeviceVfs0050 *self) { static void
fpi_device_vfs0050_init (FpDeviceVfs0050 *self)
{
} }
static void fpi_device_vfs0050_class_init(FpDeviceVfs0050Class *klass) { static void
FpDeviceClass *dev_class = FP_DEVICE_CLASS(klass); fpi_device_vfs0050_class_init (FpDeviceVfs0050Class *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 = "vfs0050"; dev_class->id = "vfs0050";
dev_class->full_name = "Validity VFS0050"; dev_class->full_name = "Validity VFS0050";

View file

@ -51,7 +51,8 @@
#define EP3_IN 0x83 #define EP3_IN 0x83
/* Fingerprint horizontal line */ /* Fingerprint horizontal line */
struct vfs_line { struct vfs_line
{
/* It must be always 0x01 */ /* It must be always 0x01 */
unsigned char _0x01; unsigned char _0x01;
/* It must be always 0xfe */ /* It must be always 0xfe */
@ -75,10 +76,11 @@ struct vfs_line {
/* scan_data is 0xfb except some rare cases, it's skipped */ /* scan_data is 0xfb except some rare cases, it's skipped */
unsigned char scan_data[8]; unsigned char scan_data[8];
} __attribute__ ((__packed__)); } __attribute__((__packed__));
/* The main driver structure */ /* The main driver structure */
struct _FpDeviceVfs0050 { struct _FpDeviceVfs0050
{
FpImageDevice parent; FpImageDevice parent;
/* One if we were asked to read fingerprint, zero otherwise */ /* One if we were asked to read fingerprint, zero otherwise */

File diff suppressed because it is too large Load diff

View file

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

View file

@ -35,7 +35,8 @@ enum {
#define VFS301_FP_RECV_LEN_1 (84032) #define VFS301_FP_RECV_LEN_1 (84032)
#define VFS301_FP_RECV_LEN_2 (84096) #define VFS301_FP_RECV_LEN_2 (84096)
struct _FpDeviceVfs301 { struct _FpDeviceVfs301
{
FpImageDevice parent; FpImageDevice parent;
/* buffer to hold raw scanlines */ /* buffer to hold raw scanlines */
@ -85,7 +86,8 @@ enum {
* to the 0x02D0 messages. * to the 0x02D0 messages.
* It seems to be always the same - what is it for? Some kind of confirmation? * It seems to be always the same - what is it for? Some kind of confirmation?
*/ */
typedef struct { typedef struct
{
unsigned char sync_0x01; unsigned char sync_0x01;
unsigned char sync_0xfe; unsigned char sync_0xfe;
@ -99,7 +101,8 @@ typedef struct {
unsigned char scan[VFS301_FP_WIDTH]; unsigned char scan[VFS301_FP_WIDTH];
} vfs301_init_line_t; } vfs301_init_line_t;
typedef struct { typedef struct
{
unsigned char sync_0x01; unsigned char sync_0x01;
unsigned char sync_0xfe; unsigned char sync_0xfe;
@ -124,14 +127,16 @@ typedef struct {
unsigned char sum3[3]; unsigned char sum3[3];
} vfs301_line_t; } vfs301_line_t;
void vfs301_proto_init(FpDeviceVfs301 *dev); void vfs301_proto_init (FpDeviceVfs301 *dev);
void vfs301_proto_deinit(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... */ /** returns 0 if no event is ready, or 1 if there is one... */
int vfs301_proto_peek_event(FpDeviceVfs301 *dev); int vfs301_proto_peek_event (FpDeviceVfs301 *dev);
void vfs301_proto_process_event_start(FpDeviceVfs301 *dev); void vfs301_proto_process_event_start (FpDeviceVfs301 *dev);
int vfs301_proto_process_event_poll(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);

View file

@ -41,29 +41,33 @@
/************************** USB STUFF *****************************************/ /************************** USB STUFF *****************************************/
#ifdef DEBUG #ifdef DEBUG
static void usb_print_packet(int dir, GError *error, const guint8 *data, int length) static void
usb_print_packet (int dir, GError *error, const guint8 *data, int length)
{ {
fprintf(stderr, "%s, error %s, len %d\n", dir ? "send" : "recv", error ? error->message : "-", length); fprintf (stderr, "%s, error %s, len %d\n", dir ? "send" : "recv", error ? error->message : "-", length);
#ifdef PRINT_VERBOSE #ifdef PRINT_VERBOSE
int i; int i;
for (i = 0; i < MIN(length, 128); i++) { for (i = 0; i < MIN (length, 128); i++)
fprintf(stderr, "%.2X ", data[i]); {
fprintf (stderr, "%.2X ", data[i]);
if (i % 8 == 7) if (i % 8 == 7)
fprintf(stderr, " "); fprintf (stderr, " ");
if (i % 32 == 31) if (i % 32 == 31)
fprintf(stderr, "\n"); fprintf (stderr, "\n");
} }
#endif #endif
fprintf(stderr, "\n"); fprintf (stderr, "\n");
} }
#endif #endif
static void usb_recv(FpDeviceVfs301 *dev, guint8 endpoint, int max_bytes, FpiUsbTransfer **out, GError **error) static void
usb_recv (FpDeviceVfs301 *dev, guint8 endpoint, int max_bytes, FpiUsbTransfer **out, GError **error)
{ {
GError *err = NULL; GError *err = NULL;
g_autoptr(FpiUsbTransfer) transfer = NULL; g_autoptr(FpiUsbTransfer) transfer = NULL;
/* XXX: This function swallows any transfer errors, that is obviously /* XXX: This function swallows any transfer errors, that is obviously
@ -77,11 +81,12 @@ static void usb_recv(FpDeviceVfs301 *dev, guint8 endpoint, int max_bytes, FpiUsb
#ifdef DEBUG #ifdef DEBUG
usb_print_packet(0, err, transfer->buffer, transfer->actual_length); usb_print_packet (0, err, transfer->buffer, transfer->actual_length);
#endif #endif
if (err) { if (err)
{
if (!error) if (!error)
g_warning("Unhandled receive error: %s", err->message); g_warning ("Unhandled receive error: %s", err->message);
g_propagate_error (error, err); g_propagate_error (error, err);
} }
@ -89,9 +94,11 @@ static void usb_recv(FpDeviceVfs301 *dev, guint8 endpoint, int max_bytes, FpiUsb
*out = g_steal_pointer (&transfer); *out = g_steal_pointer (&transfer);
} }
static void usb_send(FpDeviceVfs301 *dev, const guint8 *data, gssize length, GError **error) static void
usb_send (FpDeviceVfs301 *dev, const guint8 *data, gssize length, GError **error)
{ {
GError *err = NULL; GError *err = NULL;
g_autoptr(FpiUsbTransfer) transfer = NULL; g_autoptr(FpiUsbTransfer) transfer = NULL;
/* XXX: This function swallows any transfer errors, that is obviously /* XXX: This function swallows any transfer errors, that is obviously
@ -99,15 +106,16 @@ static void usb_send(FpDeviceVfs301 *dev, const guint8 *data, gssize length, GEr
transfer = fpi_usb_transfer_new (FP_DEVICE (dev)); transfer = fpi_usb_transfer_new (FP_DEVICE (dev));
transfer->short_is_error = TRUE; transfer->short_is_error = TRUE;
fpi_usb_transfer_fill_bulk_full (transfer, VFS301_SEND_ENDPOINT, (guint8*) data, length, g_free); fpi_usb_transfer_fill_bulk_full (transfer, VFS301_SEND_ENDPOINT, (guint8 *) data, length, g_free);
fpi_usb_transfer_submit_sync (transfer, VFS301_DEFAULT_WAIT_TIMEOUT, &err); fpi_usb_transfer_submit_sync (transfer, VFS301_DEFAULT_WAIT_TIMEOUT, &err);
#ifdef DEBUG #ifdef DEBUG
usb_print_packet(1, err, data, length); usb_print_packet (1, err, data, length);
#endif #endif
if (err) { if (err)
{
g_warning ("Error while sending data, continuing anyway: %s", err->message); g_warning ("Error while sending data, continuing anyway: %s", err->message);
g_propagate_error (error, err); g_propagate_error (error, err);
} }
@ -115,7 +123,8 @@ static void usb_send(FpDeviceVfs301 *dev, const guint8 *data, gssize length, GEr
/************************** OUT MESSAGES GENERATION ***************************/ /************************** OUT MESSAGES GENERATION ***************************/
static guint8 * vfs301_proto_generate_0B(int subtype, gssize *len) static guint8 *
vfs301_proto_generate_0B (int subtype, gssize *len)
{ {
guint8 *res = g_malloc0 (39); guint8 *res = g_malloc0 (39);
guint8 *data = res; guint8 *data = res;
@ -128,16 +137,19 @@ static guint8 * vfs301_proto_generate_0B(int subtype, gssize *len)
data[20] = subtype; data[20] = subtype;
switch (subtype) { switch (subtype)
{
case 0x04: case 0x04:
data[34] = 0x9F; data[34] = 0x9F;
break; break;
case 0x05: case 0x05:
data[34] = 0xAB; data[34] = 0xAB;
/* NOTE: There was a len++ here, which could never do anything */ /* NOTE: There was a len++ here, which could never do anything */
break; break;
default: default:
g_assert_not_reached(); g_assert_not_reached ();
break; break;
} }
@ -147,7 +159,8 @@ static guint8 * vfs301_proto_generate_0B(int subtype, gssize *len)
#define HEX_TO_INT(c) \ #define HEX_TO_INT(c) \
(((c) >= '0' && (c) <= '9') ? ((c) - '0') : ((c) - 'A' + 10)) (((c) >= '0' && (c) <= '9') ? ((c) - '0') : ((c) - 'A' + 10))
static guint8 * translate_str(const char **srcL, gssize *len) static guint8 *
translate_str (const char **srcL, gssize *len)
{ {
guint8 *res = NULL; guint8 *res = NULL;
guint8 *dst; guint8 *dst;
@ -155,11 +168,12 @@ static guint8 * translate_str(const char **srcL, gssize *len)
const char *src; const char *src;
gssize src_len = 0; gssize src_len = 0;
for (src_pos = srcL; *src_pos; src_pos++) { for (src_pos = srcL; *src_pos; src_pos++)
{
gint tmp; gint tmp;
src = *src_pos; src = *src_pos;
tmp = strlen(src); tmp = strlen (src);
g_assert (tmp % 2 == 0); g_assert (tmp % 2 == 0);
src_len += tmp; src_len += tmp;
} }
@ -168,18 +182,18 @@ static guint8 * translate_str(const char **srcL, gssize *len)
res = g_malloc0 (*len); res = g_malloc0 (*len);
dst = res; dst = res;
for (src_pos = srcL; *src_pos; src_pos++) { for (src_pos = srcL; *src_pos; src_pos++)
for (src = *src_pos; *src; src += 2, dst += 1) { for (src = *src_pos; *src; src += 2, dst += 1)
*dst = (guint8) ((HEX_TO_INT (src[0]) << 4) | (HEX_TO_INT (src[1]))); *dst = (guint8) ((HEX_TO_INT (src[0]) << 4) | (HEX_TO_INT (src[1])));
}
}
return res; return res;
} }
static guint8 *vfs301_proto_generate(int type, int subtype, gssize *len) static guint8 *
vfs301_proto_generate (int type, int subtype, gssize *len)
{ {
switch (type) { switch (type)
{
case 0x01: case 0x01:
case 0x04: case 0x04:
/* After cmd 0x04 is sent, a data is received on VALIDITY_RECEIVE_ENDPOINT_CTRL. /* After cmd 0x04 is sent, a data is received on VALIDITY_RECEIVE_ENDPOINT_CTRL.
@ -199,9 +213,11 @@ static guint8 *vfs301_proto_generate(int type, int subtype, gssize *len)
return data; return data;
} }
break; break;
case 0x0B: case 0x0B:
return vfs301_proto_generate_0B(subtype, len); return vfs301_proto_generate_0B (subtype, len);
break; break;
case 0x02D0: case 0x02D0:
{ {
const char **dataLs[] = { const char **dataLs[] = {
@ -213,55 +229,62 @@ static guint8 *vfs301_proto_generate(int type, int subtype, gssize *len)
vfs301_02D0_06, vfs301_02D0_06,
vfs301_02D0_07, vfs301_02D0_07,
}; };
g_assert((int)subtype <= G_N_ELEMENTS (dataLs)); g_assert ((int) subtype <= G_N_ELEMENTS (dataLs));
return translate_str(dataLs[subtype - 1], len); return translate_str (dataLs[subtype - 1], len);
} }
break; break;
case 0x0220: case 0x0220:
switch (subtype) { switch (subtype)
{
case 1: case 1:
return translate_str(vfs301_0220_01, len); return translate_str (vfs301_0220_01, len);
break; break;
case 2: case 2:
return translate_str(vfs301_0220_02, len); return translate_str (vfs301_0220_02, len);
break; break;
case 3: case 3:
return translate_str(vfs301_0220_03, len); return translate_str (vfs301_0220_03, len);
break; break;
case 0xFA00: case 0xFA00:
case 0x2C01: case 0x2C01:
case 0x5E01: { case 0x5E01: {
guint8 *data; guint8 *data;
guint8 *field; guint8 *field;
data = translate_str(vfs301_next_scan_template, len); data = translate_str (vfs301_next_scan_template, len);
field = data + *len - (sizeof(S4_TAIL) - 1) / 2 - 4; field = data + *len - (sizeof (S4_TAIL) - 1) / 2 - 4;
g_assert (field >= data && field < data + *len); g_assert (field >= data && field < data + *len);
g_assert(field[0] == 0xDE); g_assert (field[0] == 0xDE);
g_assert(field[1] == 0xAD); g_assert (field[1] == 0xAD);
g_assert(field[2] == 0xDE); g_assert (field[2] == 0xDE);
g_assert(field[3] == 0xAD); g_assert (field[3] == 0xAD);
field[0] = (guint8)((subtype >> 8) & 0xFF); field[0] = (guint8) ((subtype >> 8) & 0xFF);
field[1] = (guint8)(subtype & 0xFF); field[1] = (guint8) (subtype & 0xFF);
field[2] = field[0]; field[2] = field[0];
field[3] = field[1]; field[3] = field[1];
return data; return data;
break; break;
} }
default: default:
g_assert_not_reached(); g_assert_not_reached ();
break; break;
} }
break; break;
case 0x06: case 0x06:
default: default:
break; break;
} }
g_assert_not_reached(); g_assert_not_reached ();
*len = 0; *len = 0;
return NULL; return NULL;
} }
@ -269,25 +292,27 @@ static guint8 *vfs301_proto_generate(int type, int subtype, gssize *len)
/************************** SCAN IMAGE PROCESSING *****************************/ /************************** SCAN IMAGE PROCESSING *****************************/
#ifdef SCAN_FINISH_DETECTION #ifdef SCAN_FINISH_DETECTION
static int img_is_finished_scan(fp_line_t *lines, int no_lines) static int
img_is_finished_scan (fp_line_t *lines, int no_lines)
{ {
int i; int i;
int j; int j;
int rv = 1; int rv = 1;
for (i = no_lines - VFS301_FP_SUM_LINES; i < no_lines; i++) { for (i = no_lines - VFS301_FP_SUM_LINES; i < no_lines; i++)
{
/* check the line for fingerprint data */ /* check the line for fingerprint data */
for (j = 0; j < sizeof(lines[i].sum2); j++) { for (j = 0; j < sizeof (lines[i].sum2); j++)
if (lines[i].sum2[j] > (VFS301_FP_SUM_MEDIAN + VFS301_FP_SUM_EMPTY_RANGE)) if (lines[i].sum2[j] > (VFS301_FP_SUM_MEDIAN + VFS301_FP_SUM_EMPTY_RANGE))
rv = 0; rv = 0;
} }
}
return rv; return rv;
} }
#endif #endif
static int scanline_diff(const guint8 *scanlines, int prev, int cur) static int
scanline_diff (const guint8 *scanlines, int prev, int cur)
{ {
const guint8 *line1 = scanlines + prev * VFS301_FP_OUTPUT_WIDTH; const guint8 *line1 = scanlines + prev * VFS301_FP_OUTPUT_WIDTH;
const guint8 *line2 = scanlines + cur * VFS301_FP_OUTPUT_WIDTH; const guint8 *line2 = scanlines + cur * VFS301_FP_OUTPUT_WIDTH;
@ -296,13 +321,14 @@ static int scanline_diff(const guint8 *scanlines, int prev, int cur)
#ifdef OUTPUT_RAW #ifdef OUTPUT_RAW
/* We only need the image, not the surrounding stuff. */ /* We only need the image, not the surrounding stuff. */
line1 = ((vfs301_line_t*)line1)->scan; line1 = ((vfs301_line_t *) line1)->scan;
line2 = ((vfs301_line_t*)line2)->scan; line2 = ((vfs301_line_t *) line2)->scan;
#endif #endif
/* TODO: This doesn't work too well when there are parallel lines in the /* TODO: This doesn't work too well when there are parallel lines in the
* fingerprint. */ * fingerprint. */
for (diff = 0, i = 0; i < VFS301_FP_WIDTH; i++) { for (diff = 0, i = 0; i < VFS301_FP_WIDTH; i++)
{
if (*line1 > *line2) if (*line1 > *line2)
diff += *line1 - *line2; diff += *line1 - *line2;
else else
@ -312,21 +338,22 @@ static int scanline_diff(const guint8 *scanlines, int prev, int cur)
line2++; line2++;
} }
return ((diff / VFS301_FP_WIDTH) > VFS301_FP_LINE_DIFF_THRESHOLD); return (diff / VFS301_FP_WIDTH) > VFS301_FP_LINE_DIFF_THRESHOLD;
} }
/** Transform the input data to a normalized fingerprint scan */ /** Transform the input data to a normalized fingerprint scan */
void vfs301_extract_image(FpDeviceVfs301 *vfs, guint8 *output, int *output_height void
) vfs301_extract_image (FpDeviceVfs301 *vfs, guint8 *output, int *output_height
)
{ {
const guint8 *scanlines = vfs->scanline_buf; const guint8 *scanlines = vfs->scanline_buf;
int last_line; int last_line;
int i; int i;
g_assert(vfs->scanline_count >= 1); g_assert (vfs->scanline_count >= 1);
*output_height = 1; *output_height = 1;
memcpy(output, scanlines, VFS301_FP_OUTPUT_WIDTH); memcpy (output, scanlines, VFS301_FP_OUTPUT_WIDTH);
last_line = 0; last_line = 0;
/* The following algorithm is quite trivial - it just picks lines that /* The following algorithm is quite trivial - it just picks lines that
@ -335,9 +362,11 @@ void vfs301_extract_image(FpDeviceVfs301 *vfs, guint8 *output, int *output_heigh
* of bi/tri-linear resampling to get the output (so that we don't get so * of bi/tri-linear resampling to get the output (so that we don't get so
* many false edges etc.). * many false edges etc.).
*/ */
for (i = 1; i < vfs->scanline_count; i++) { for (i = 1; i < vfs->scanline_count; i++)
if (scanline_diff(scanlines, last_line, i)) { {
memcpy( if (scanline_diff (scanlines, last_line, i))
{
memcpy (
output + VFS301_FP_OUTPUT_WIDTH * (*output_height), output + VFS301_FP_OUTPUT_WIDTH * (*output_height),
scanlines + VFS301_FP_OUTPUT_WIDTH * i, scanlines + VFS301_FP_OUTPUT_WIDTH * i,
VFS301_FP_OUTPUT_WIDTH VFS301_FP_OUTPUT_WIDTH
@ -348,41 +377,47 @@ void vfs301_extract_image(FpDeviceVfs301 *vfs, guint8 *output, int *output_heigh
} }
} }
static int img_process_data(int first_block, FpDeviceVfs301 *dev, const guint8 *buf, int len) static int
img_process_data (int first_block, FpDeviceVfs301 *dev, const guint8 *buf, int len)
{ {
vfs301_line_t *lines = (vfs301_line_t*)buf; vfs301_line_t *lines = (vfs301_line_t *) buf;
int no_lines = len / sizeof(vfs301_line_t); int no_lines = len / sizeof (vfs301_line_t);
int i; int i;
/*int no_nonempty;*/ /*int no_nonempty;*/
guint8 *cur_line; guint8 *cur_line;
int last_img_height; int last_img_height;
#ifdef SCAN_FINISH_DETECTION #ifdef SCAN_FINISH_DETECTION
int finished_scan; int finished_scan;
#endif #endif
if (first_block) { if (first_block)
{
last_img_height = 0; last_img_height = 0;
dev->scanline_count = no_lines; dev->scanline_count = no_lines;
} else { }
else
{
last_img_height = dev->scanline_count; last_img_height = dev->scanline_count;
dev->scanline_count += no_lines; dev->scanline_count += no_lines;
} }
dev->scanline_buf = g_realloc(dev->scanline_buf, dev->scanline_count * VFS301_FP_OUTPUT_WIDTH); dev->scanline_buf = g_realloc (dev->scanline_buf, dev->scanline_count * VFS301_FP_OUTPUT_WIDTH);
for (cur_line = dev->scanline_buf + last_img_height * VFS301_FP_OUTPUT_WIDTH, i = 0; for (cur_line = dev->scanline_buf + last_img_height * VFS301_FP_OUTPUT_WIDTH, i = 0;
i < no_lines; i < no_lines;
i++, cur_line += VFS301_FP_OUTPUT_WIDTH i++, cur_line += VFS301_FP_OUTPUT_WIDTH
) { )
{
#ifndef OUTPUT_RAW #ifndef OUTPUT_RAW
memcpy(cur_line, lines[i].scan, VFS301_FP_OUTPUT_WIDTH); memcpy (cur_line, lines[i].scan, VFS301_FP_OUTPUT_WIDTH);
#else #else
memcpy(cur_line, &lines[i], VFS301_FP_OUTPUT_WIDTH); memcpy (cur_line, &lines[i], VFS301_FP_OUTPUT_WIDTH);
#endif #endif
} }
#ifdef SCAN_FINISH_DETECTION #ifdef SCAN_FINISH_DETECTION
finished_scan = img_is_finished_scan(lines, no_lines); finished_scan = img_is_finished_scan (lines, no_lines);
return !finished_scan; return !finished_scan;
#else /* SCAN_FINISH_DETECTION */ #else /* SCAN_FINISH_DETECTION */
@ -393,44 +428,47 @@ static int img_process_data(int first_block, FpDeviceVfs301 *dev, const guint8 *
/************************** PROTOCOL STUFF ************************************/ /************************** PROTOCOL STUFF ************************************/
#define USB_RECV(from, len) \ #define USB_RECV(from, len) \
usb_recv(dev, from, len, NULL, NULL) usb_recv (dev, from, len, NULL, NULL)
#define USB_SEND(type, subtype) \ #define USB_SEND(type, subtype) \
{ \ { \
const guint8 *data; \ const guint8 *data; \
gssize len; \ gssize len; \
data = vfs301_proto_generate(type, subtype, &len); \ data = vfs301_proto_generate (type, subtype, &len); \
usb_send(dev, data, len, NULL); \ usb_send (dev, data, len, NULL); \
} }
#define RAW_DATA(x) x, sizeof(x) #define RAW_DATA(x) x, sizeof (x)
#define IS_VFS301_FP_SEQ_START(b) ((b[0] == 0x01) && (b[1] == 0xfe)) #define IS_VFS301_FP_SEQ_START(b) ((b[0] == 0x01) && (b[1] == 0xfe))
static int vfs301_proto_process_data(FpDeviceVfs301 *dev, int first_block, const guint8 *buf, gint len) static int
vfs301_proto_process_data (FpDeviceVfs301 *dev, int first_block, const guint8 *buf, gint len)
{ {
int i; int i;
if (first_block) { if (first_block)
g_assert(len >= VFS301_FP_FRAME_SIZE); {
g_assert (len >= VFS301_FP_FRAME_SIZE);
/* Skip bytes until start_sequence is found */ /* Skip bytes until start_sequence is found */
for (i = 0; i < VFS301_FP_FRAME_SIZE; i++, buf++, len--) { for (i = 0; i < VFS301_FP_FRAME_SIZE; i++, buf++, len--)
if (IS_VFS301_FP_SEQ_START(buf)) if (IS_VFS301_FP_SEQ_START (buf))
break; break;
} }
}
return img_process_data(first_block, dev, buf, len); return img_process_data (first_block, dev, buf, len);
} }
void vfs301_proto_request_fingerprint(FpDeviceVfs301 *dev) void
vfs301_proto_request_fingerprint (FpDeviceVfs301 *dev)
{ {
USB_SEND(0x0220, 0xFA00); USB_SEND (0x0220, 0xFA00);
USB_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 000000000000 */ USB_RECV (VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 000000000000 */
} }
int vfs301_proto_peek_event(FpDeviceVfs301 *dev) int
vfs301_proto_peek_event (FpDeviceVfs301 *dev)
{ {
g_autoptr(GError) error = NULL; g_autoptr(GError) error = NULL;
g_autoptr(FpiUsbTransfer) transfer = NULL; g_autoptr(FpiUsbTransfer) transfer = NULL;
@ -438,19 +476,18 @@ int vfs301_proto_peek_event(FpDeviceVfs301 *dev)
const char no_event[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; const char no_event[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
const char got_event[] = {0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00}; const char got_event[] = {0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00};
USB_SEND(0x17, -1); USB_SEND (0x17, -1);
usb_recv (dev, VFS301_RECEIVE_ENDPOINT_CTRL, 7, &transfer, &error); usb_recv (dev, VFS301_RECEIVE_ENDPOINT_CTRL, 7, &transfer, &error);
/* XXX: This is obviously not a sane error handling! */ /* XXX: This is obviously not a sane error handling! */
g_assert (!error); g_assert (!error);
if (memcmp(transfer->buffer, no_event, sizeof(no_event)) == 0) { if (memcmp (transfer->buffer, no_event, sizeof (no_event)) == 0)
return 0; return 0;
} else if (memcmp(transfer->buffer, got_event, sizeof(no_event)) == 0) { else if (memcmp (transfer->buffer, got_event, sizeof (no_event)) == 0)
return 1; return 1;
} else { else
g_assert_not_reached(); g_assert_not_reached ();
}
} }
/* XXX: We sometimes need to receive data on from two endpoints at the same /* XXX: We sometimes need to receive data on from two endpoints at the same
@ -459,49 +496,57 @@ int vfs301_proto_peek_event(FpDeviceVfs301 *dev)
*/ */
#define PARALLEL_RECEIVE(e1, l1, e2, l2) \ #define PARALLEL_RECEIVE(e1, l1, e2, l2) \
{ \ { \
g_autoptr(GError) error = NULL;\ g_autoptr(GError) error = NULL; \
usb_recv(dev, e1, l1, NULL, &error); \ usb_recv (dev, e1, l1, NULL, &error); \
usb_recv(dev, e2, l2, NULL, NULL); \ usb_recv (dev, e2, l2, NULL, NULL); \
if (g_error_matches (error, G_USB_DEVICE_ERROR, G_USB_DEVICE_ERROR_TIMED_OUT)) \ if (g_error_matches (error, G_USB_DEVICE_ERROR, G_USB_DEVICE_ERROR_TIMED_OUT)) \
usb_recv(dev, e1, l1, NULL, NULL); \ usb_recv(dev, e1, l1, NULL, NULL); \
} }
static void vfs301_proto_process_event_cb(FpiUsbTransfer *transfer, static void
vfs301_proto_process_event_cb (FpiUsbTransfer *transfer,
FpDevice *device, FpDevice *device,
gpointer user_data, GError *error) gpointer user_data, GError *error)
{ {
FpDeviceVfs301 *dev = user_data; FpDeviceVfs301 *dev = user_data;
if (error) { if (error)
{
g_warning ("Error receiving data: %s", error->message); g_warning ("Error receiving data: %s", error->message);
g_error_free (error); g_error_free (error);
dev->recv_progress = VFS301_FAILURE; dev->recv_progress = VFS301_FAILURE;
return; return;
} else if (transfer->actual_length < transfer->length) { }
else if (transfer->actual_length < transfer->length)
{
/* TODO: process the data anyway? */ /* TODO: process the data anyway? */
dev->recv_progress = VFS301_ENDED; dev->recv_progress = VFS301_ENDED;
return; return;
} else { }
else
{
FpiUsbTransfer *new; FpiUsbTransfer *new;
if (!vfs301_proto_process_data(dev, if (!vfs301_proto_process_data (dev,
transfer->length == VFS301_FP_RECV_LEN_1, transfer->length == VFS301_FP_RECV_LEN_1,
transfer->buffer, transfer->buffer,
transfer->actual_length)) { transfer->actual_length))
{
dev->recv_progress = VFS301_ENDED; dev->recv_progress = VFS301_ENDED;
return; return;
} }
new = fpi_usb_transfer_new (device); new = fpi_usb_transfer_new (device);
fpi_usb_transfer_fill_bulk(new, VFS301_RECEIVE_ENDPOINT_DATA, VFS301_FP_RECV_LEN_2); fpi_usb_transfer_fill_bulk (new, VFS301_RECEIVE_ENDPOINT_DATA, VFS301_FP_RECV_LEN_2);
fpi_usb_transfer_submit(new, VFS301_FP_RECV_TIMEOUT, NULL, fpi_usb_transfer_submit (new, VFS301_FP_RECV_TIMEOUT, NULL,
vfs301_proto_process_event_cb, NULL); vfs301_proto_process_event_cb, NULL);
fpi_usb_transfer_unref (new); fpi_usb_transfer_unref (new);
return; return;
} }
} }
void vfs301_proto_process_event_start(FpDeviceVfs301 *dev) void
vfs301_proto_process_event_start (FpDeviceVfs301 *dev)
{ {
FpiUsbTransfer *transfer; FpiUsbTransfer *transfer;
@ -526,35 +571,36 @@ void vfs301_proto_process_event_start(FpDeviceVfs301 *dev)
* o FA00 * o FA00
* o 2C01 * o 2C01
*/ */
USB_RECV(VFS301_RECEIVE_ENDPOINT_DATA, 64); USB_RECV (VFS301_RECEIVE_ENDPOINT_DATA, 64);
/* now read the fingerprint data, while there are some */ /* now read the fingerprint data, while there are some */
transfer = fpi_usb_transfer_new(FP_DEVICE (dev)); transfer = fpi_usb_transfer_new (FP_DEVICE (dev));
dev->recv_progress = VFS301_ONGOING; dev->recv_progress = VFS301_ONGOING;
fpi_usb_transfer_fill_bulk (transfer, VFS301_RECEIVE_ENDPOINT_DATA, VFS301_FP_RECV_LEN_1); fpi_usb_transfer_fill_bulk (transfer, VFS301_RECEIVE_ENDPOINT_DATA, VFS301_FP_RECV_LEN_1);
fpi_usb_transfer_submit(transfer, VFS301_FP_RECV_TIMEOUT, NULL, fpi_usb_transfer_submit (transfer, VFS301_FP_RECV_TIMEOUT, NULL,
vfs301_proto_process_event_cb, NULL); vfs301_proto_process_event_cb, NULL);
fpi_usb_transfer_unref(transfer); fpi_usb_transfer_unref (transfer);
} }
int vfs301_proto_process_event_poll(FpDeviceVfs301 *dev) int
vfs301_proto_process_event_poll (FpDeviceVfs301 *dev)
{ {
if (dev->recv_progress != VFS301_ENDED) if (dev->recv_progress != VFS301_ENDED)
return dev->recv_progress; return dev->recv_progress;
/* Finish the scan process... */ /* Finish the scan process... */
USB_SEND(0x04, -1); USB_SEND (0x04, -1);
/* the following may come in random order, data may not come at all, don't /* the following may come in random order, data may not come at all, don't
* try for too long... */ * try for too long... */
PARALLEL_RECEIVE( PARALLEL_RECEIVE (
VFS301_RECEIVE_ENDPOINT_CTRL, 2, /* 1204 */ VFS301_RECEIVE_ENDPOINT_CTRL, 2, /* 1204 */
VFS301_RECEIVE_ENDPOINT_DATA, 16384 VFS301_RECEIVE_ENDPOINT_DATA, 16384
); );
USB_SEND(0x0220, 2); USB_SEND (0x0220, 2);
PARALLEL_RECEIVE( PARALLEL_RECEIVE (
VFS301_RECEIVE_ENDPOINT_DATA, 5760, /* seems to always come */ VFS301_RECEIVE_ENDPOINT_DATA, 5760, /* seems to always come */
VFS301_RECEIVE_ENDPOINT_CTRL, 2 /* 0000 */ VFS301_RECEIVE_ENDPOINT_CTRL, 2 /* 0000 */
); );
@ -562,92 +608,94 @@ int vfs301_proto_process_event_poll(FpDeviceVfs301 *dev)
return dev->recv_progress; return dev->recv_progress;
} }
void vfs301_proto_init(FpDeviceVfs301 *dev) void
vfs301_proto_init (FpDeviceVfs301 *dev)
{ {
USB_SEND(0x01, -1); USB_SEND (0x01, -1);
USB_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 38); USB_RECV (VFS301_RECEIVE_ENDPOINT_CTRL, 38);
USB_SEND(0x0B, 0x04); USB_SEND (0x0B, 0x04);
USB_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 6); /* 000000000000 */ USB_RECV (VFS301_RECEIVE_ENDPOINT_CTRL, 6); /* 000000000000 */
USB_SEND(0x0B, 0x05); USB_SEND (0x0B, 0x05);
USB_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 7); /* 00000000000000 */ USB_RECV (VFS301_RECEIVE_ENDPOINT_CTRL, 7); /* 00000000000000 */
USB_SEND(0x19, -1); USB_SEND (0x19, -1);
USB_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 64); USB_RECV (VFS301_RECEIVE_ENDPOINT_CTRL, 64);
USB_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 4); /* 6BB4D0BC */ USB_RECV (VFS301_RECEIVE_ENDPOINT_CTRL, 4); /* 6BB4D0BC */
usb_send(dev, RAW_DATA(vfs301_06_1), NULL); usb_send (dev, RAW_DATA (vfs301_06_1), NULL);
USB_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */ USB_RECV (VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */
USB_SEND(0x01, -1); USB_SEND (0x01, -1);
USB_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 38); USB_RECV (VFS301_RECEIVE_ENDPOINT_CTRL, 38);
USB_SEND(0x1A, -1); USB_SEND (0x1A, -1);
USB_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */ USB_RECV (VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */
usb_send(dev, RAW_DATA(vfs301_06_2), NULL); usb_send (dev, RAW_DATA (vfs301_06_2), NULL);
USB_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */ USB_RECV (VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */
USB_SEND(0x0220, 1); USB_SEND (0x0220, 1);
USB_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */ USB_RECV (VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */
USB_RECV(VFS301_RECEIVE_ENDPOINT_DATA, 256); USB_RECV (VFS301_RECEIVE_ENDPOINT_DATA, 256);
USB_RECV(VFS301_RECEIVE_ENDPOINT_DATA, 32); USB_RECV (VFS301_RECEIVE_ENDPOINT_DATA, 32);
USB_SEND(0x1A, -1); USB_SEND (0x1A, -1);
USB_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */ USB_RECV (VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */
usb_send(dev, RAW_DATA(vfs301_06_3), NULL); usb_send (dev, RAW_DATA (vfs301_06_3), NULL);
USB_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */ USB_RECV (VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */
USB_SEND(0x01, -1); USB_SEND (0x01, -1);
USB_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 38); USB_RECV (VFS301_RECEIVE_ENDPOINT_CTRL, 38);
USB_SEND(0x02D0, 1); USB_SEND (0x02D0, 1);
USB_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */ USB_RECV (VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */
USB_RECV(VFS301_RECEIVE_ENDPOINT_DATA, 11648); /* 56 * vfs301_init_line_t[] */ USB_RECV (VFS301_RECEIVE_ENDPOINT_DATA, 11648); /* 56 * vfs301_init_line_t[] */
USB_SEND(0x02D0, 2); USB_SEND (0x02D0, 2);
USB_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */ USB_RECV (VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */
USB_RECV(VFS301_RECEIVE_ENDPOINT_DATA, 53248); /* 2 * 128 * vfs301_init_line_t[] */ USB_RECV (VFS301_RECEIVE_ENDPOINT_DATA, 53248); /* 2 * 128 * vfs301_init_line_t[] */
USB_SEND(0x02D0, 3); USB_SEND (0x02D0, 3);
USB_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */ USB_RECV (VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */
USB_RECV(VFS301_RECEIVE_ENDPOINT_DATA, 19968); /* 96 * vfs301_init_line_t[] */ USB_RECV (VFS301_RECEIVE_ENDPOINT_DATA, 19968); /* 96 * vfs301_init_line_t[] */
USB_SEND(0x02D0, 4); USB_SEND (0x02D0, 4);
USB_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */ USB_RECV (VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */
USB_RECV(VFS301_RECEIVE_ENDPOINT_DATA, 5824); /* 28 * vfs301_init_line_t[] */ USB_RECV (VFS301_RECEIVE_ENDPOINT_DATA, 5824); /* 28 * vfs301_init_line_t[] */
USB_SEND(0x02D0, 5); USB_SEND (0x02D0, 5);
USB_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */ USB_RECV (VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */
USB_RECV(VFS301_RECEIVE_ENDPOINT_DATA, 6656); /* 32 * vfs301_init_line_t[] */ USB_RECV (VFS301_RECEIVE_ENDPOINT_DATA, 6656); /* 32 * vfs301_init_line_t[] */
USB_SEND(0x02D0, 6); USB_SEND (0x02D0, 6);
USB_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */ USB_RECV (VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */
USB_RECV(VFS301_RECEIVE_ENDPOINT_DATA, 6656); /* 32 * vfs301_init_line_t[] */ USB_RECV (VFS301_RECEIVE_ENDPOINT_DATA, 6656); /* 32 * vfs301_init_line_t[] */
USB_SEND(0x02D0, 7); USB_SEND (0x02D0, 7);
USB_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */ USB_RECV (VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */
USB_RECV(VFS301_RECEIVE_ENDPOINT_DATA, 832); USB_RECV (VFS301_RECEIVE_ENDPOINT_DATA, 832);
usb_send(dev, RAW_DATA(vfs301_12), NULL); usb_send (dev, RAW_DATA (vfs301_12), NULL);
USB_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */ USB_RECV (VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */
USB_SEND(0x1A, -1); USB_SEND (0x1A, -1);
USB_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */ USB_RECV (VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */
usb_send(dev, RAW_DATA(vfs301_06_2), NULL); usb_send (dev, RAW_DATA (vfs301_06_2), NULL);
USB_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */ USB_RECV (VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */
USB_SEND(0x0220, 2); USB_SEND (0x0220, 2);
PARALLEL_RECEIVE( PARALLEL_RECEIVE (
VFS301_RECEIVE_ENDPOINT_CTRL, 2, /* 0000 */ VFS301_RECEIVE_ENDPOINT_CTRL, 2, /* 0000 */
VFS301_RECEIVE_ENDPOINT_DATA, 5760 VFS301_RECEIVE_ENDPOINT_DATA, 5760
); );
USB_SEND(0x1A, -1); USB_SEND (0x1A, -1);
USB_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */ USB_RECV (VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */
usb_send(dev, RAW_DATA(vfs301_06_1), NULL); usb_send (dev, RAW_DATA (vfs301_06_1), NULL);
USB_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */ USB_RECV (VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */
USB_SEND(0x1A, -1); USB_SEND (0x1A, -1);
USB_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */ USB_RECV (VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */
usb_send(dev, RAW_DATA(vfs301_06_4), NULL); usb_send (dev, RAW_DATA (vfs301_06_4), NULL);
USB_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */ USB_RECV (VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */
usb_send(dev, RAW_DATA(vfs301_24), NULL); /* turns on white */ usb_send (dev, RAW_DATA (vfs301_24), NULL); /* turns on white */
USB_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */ USB_RECV (VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */
USB_SEND(0x01, -1); USB_SEND (0x01, -1);
USB_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 38); USB_RECV (VFS301_RECEIVE_ENDPOINT_CTRL, 38);
USB_SEND(0x0220, 3); USB_SEND (0x0220, 3);
USB_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 2368); USB_RECV (VFS301_RECEIVE_ENDPOINT_CTRL, 2368);
USB_RECV(VFS301_RECEIVE_ENDPOINT_CTRL, 36); USB_RECV (VFS301_RECEIVE_ENDPOINT_CTRL, 36);
USB_RECV(VFS301_RECEIVE_ENDPOINT_DATA, 5760); USB_RECV (VFS301_RECEIVE_ENDPOINT_DATA, 5760);
} }
void vfs301_proto_deinit(FpDeviceVfs301 *dev) void
vfs301_proto_deinit (FpDeviceVfs301 *dev)
{ {
} }

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -36,7 +36,8 @@
#include <gio/gio.h> #include <gio/gio.h>
#include <gio/gunixsocketaddress.h> #include <gio/gunixsocketaddress.h>
struct _FpDeviceVirtualImage { struct _FpDeviceVirtualImage
{
FpImageDevice parent; FpImageDevice parent;
GSocketListener *listener; GSocketListener *listener;
@ -54,7 +55,8 @@ G_DECLARE_FINAL_TYPE (FpDeviceVirtualImage, fpi_device_virtual_image, FPI, DEVIC
G_DEFINE_TYPE (FpDeviceVirtualImage, fpi_device_virtual_image, FP_TYPE_IMAGE_DEVICE) G_DEFINE_TYPE (FpDeviceVirtualImage, fpi_device_virtual_image, FP_TYPE_IMAGE_DEVICE)
static void start_listen (FpDeviceVirtualImage *dev); static void start_listen (FpDeviceVirtualImage *dev);
static void recv_image (FpDeviceVirtualImage *dev, GInputStream *stream); static void recv_image (FpDeviceVirtualImage *dev,
GInputStream *stream);
static void static void
recv_image_img_recv_cb (GObject *source_object, recv_image_img_recv_cb (GObject *source_object,
@ -68,8 +70,10 @@ recv_image_img_recv_cb (GObject *source_object,
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)
if (bytes < 0) { {
if (bytes < 0)
{
g_warning ("Error receiving header for image data: %s", error->message); g_warning ("Error receiving header for image data: %s", error->message);
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
return; return;
@ -89,7 +93,7 @@ recv_image_img_recv_cb (GObject *source_object,
fpi_image_device_report_finger_status (device, FALSE); fpi_image_device_report_finger_status (device, FALSE);
/* And, listen for more images from the same client. */ /* And, listen for more images from the same client. */
recv_image(self, G_INPUT_STREAM (source_object)); recv_image (self, G_INPUT_STREAM (source_object));
} }
static void static void
@ -103,8 +107,10 @@ recv_image_hdr_recv_cb (GObject *source_object,
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)
if (bytes < 0) { {
if (bytes < 0)
{
g_warning ("Error receiving header for image data: %s", error->message); g_warning ("Error receiving header for image data: %s", error->message);
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
return; return;
@ -117,14 +123,17 @@ recv_image_hdr_recv_cb (GObject *source_object,
} }
self = FPI_DEVICE_VIRTUAL_IMAGE (user_data); self = FPI_DEVICE_VIRTUAL_IMAGE (user_data);
if (self->recv_img_hdr[0] > 5000 || self->recv_img_hdr[1] > 5000) { 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_warning ("Image header suggests an unrealistically large image, disconnecting client.");
g_io_stream_close (G_IO_STREAM (self->connection), NULL, NULL); g_io_stream_close (G_IO_STREAM (self->connection), NULL, NULL);
self->connection = NULL; self->connection = NULL;
} }
if (self->recv_img_hdr[0] < 0 || self->recv_img_hdr[1] < 0) { if (self->recv_img_hdr[0] < 0 || self->recv_img_hdr[1] < 0)
switch (self->recv_img_hdr[0]) { {
switch (self->recv_img_hdr[0])
{
case -1: case -1:
/* -1 is a retry error, just pass it through */ /* -1 is a retry error, just pass it through */
fpi_image_device_retry_scan (FP_IMAGE_DEVICE (self), self->recv_img_hdr[1]); fpi_image_device_retry_scan (FP_IMAGE_DEVICE (self), self->recv_img_hdr[1]);
@ -143,14 +152,14 @@ recv_image_hdr_recv_cb (GObject *source_object,
} }
/* And, listen for more images from the same client. */ /* And, listen for more images from the same client. */
recv_image(self, G_INPUT_STREAM (source_object)); recv_image (self, G_INPUT_STREAM (source_object));
return; return;
} }
self->recv_img = fp_image_new (self->recv_img_hdr[0], self->recv_img_hdr[1]); 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_debug ("image data: %p", self->recv_img->data);
g_input_stream_read_async (G_INPUT_STREAM (source_object), g_input_stream_read_async (G_INPUT_STREAM (source_object),
(guint8*)self->recv_img->data, (guint8 *) self->recv_img->data,
self->recv_img->width * self->recv_img->height, self->recv_img->width * self->recv_img->height,
G_PRIORITY_DEFAULT, G_PRIORITY_DEFAULT,
self->cancellable, self->cancellable,
@ -163,7 +172,7 @@ recv_image (FpDeviceVirtualImage *dev, GInputStream *stream)
{ {
g_input_stream_read_async (stream, g_input_stream_read_async (stream,
dev->recv_img_hdr, dev->recv_img_hdr,
sizeof(dev->recv_img_hdr), sizeof (dev->recv_img_hdr),
G_PRIORITY_DEFAULT, G_PRIORITY_DEFAULT,
dev->cancellable, dev->cancellable,
recv_image_hdr_recv_cb, recv_image_hdr_recv_cb,
@ -182,18 +191,20 @@ new_connection_cb (GObject *source_object, GAsyncResult *res, gpointer user_data
res, res,
NULL, NULL,
&error); &error);
if (!connection) { if (!connection)
{
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
return; return;
g_warning ("Error accepting a new connection: %s", error->message); g_warning ("Error accepting a new connection: %s", error->message);
start_listen(dev); start_listen (dev);
} }
/* Always further connections (but we disconnect them immediately /* Always further connections (but we disconnect them immediately
* if we already have a connection). */ * if we already have a connection). */
start_listen(dev); start_listen (dev);
if (dev->connection) { if (dev->connection)
{
g_io_stream_close (G_IO_STREAM (connection), NULL, NULL); g_io_stream_close (G_IO_STREAM (connection), NULL, NULL);
return; return;
} }
@ -203,7 +214,7 @@ new_connection_cb (GObject *source_object, GAsyncResult *res, gpointer user_data
recv_image (dev, stream); recv_image (dev, stream);
fp_dbg("Got a new connection!"); fp_dbg ("Got a new connection!");
} }
static void static void
@ -216,14 +227,14 @@ start_listen (FpDeviceVirtualImage *dev)
} }
static void static void
dev_init(FpImageDevice *dev) dev_init (FpImageDevice *dev)
{ {
g_autoptr(GError) error = NULL; g_autoptr(GError) error = NULL;
g_autoptr(GSocketListener) listener = NULL; g_autoptr(GSocketListener) listener = NULL;
FpDeviceVirtualImage *self = FPI_DEVICE_VIRTUAL_IMAGE (dev); FpDeviceVirtualImage *self = FPI_DEVICE_VIRTUAL_IMAGE (dev);
const char *env; const char *env;
g_autoptr(GSocketAddress) addr = NULL; g_autoptr(GSocketAddress) addr = NULL;
G_DEBUG_HERE(); G_DEBUG_HERE ();
self->client_fd = -1; self->client_fd = -1;
@ -243,7 +254,8 @@ dev_init(FpImageDevice *dev)
G_SOCKET_PROTOCOL_DEFAULT, G_SOCKET_PROTOCOL_DEFAULT,
NULL, NULL,
NULL, NULL,
&error)) { &error))
{
g_warning ("Could not listen on unix socket: %s", error->message); 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));
@ -259,18 +271,19 @@ dev_init(FpImageDevice *dev)
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_cancellable_cancel (self->cancellable);
g_clear_object (&self->cancellable); g_clear_object (&self->cancellable);
g_clear_object (&self->listener); g_clear_object (&self->listener);
g_clear_object (&self->connection); g_clear_object (&self->connection);
fpi_image_device_close_complete(dev, NULL); fpi_image_device_close_complete (dev, NULL);
} }
static void static void
@ -297,4 +310,3 @@ fpi_device_virtual_image_class_init (FpDeviceVirtualImageClass *klass)
img_class->img_open = dev_init; img_class->img_open = dev_init;
img_class->img_close = dev_deinit; img_class->img_close = dev_deinit;
} }

View file

@ -26,7 +26,8 @@
#include "fpi-image-device.h" #include "fpi-image-device.h"
/* fp_minutia structure definition */ /* fp_minutia structure definition */
struct fp_minutia { struct fp_minutia
{
int x; int x;
int y; int y;
int ex; int ex;
@ -42,7 +43,8 @@ struct fp_minutia {
}; };
/* fp_minutiae structure definition */ /* fp_minutiae structure definition */
struct fp_minutiae { struct fp_minutiae
{
int alloc; int alloc;
int num; int num;
struct fp_minutia **list; struct fp_minutia **list;

View file

@ -28,9 +28,10 @@
GHashTable *printed = NULL; 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; gint i;
fpi_get_driver_types (drivers); fpi_get_driver_types (drivers);
@ -42,7 +43,8 @@ static GList *insert_drivers (GList *list)
FpDeviceClass *cls = FP_DEVICE_CLASS (g_type_class_ref (driver)); FpDeviceClass *cls = FP_DEVICE_CLASS (g_type_class_ref (driver));
const FpIdEntry *entry; const FpIdEntry *entry;
if (cls->type != FP_DEVICE_TYPE_USB) { if (cls->type != FP_DEVICE_TYPE_USB)
{
g_type_class_unref (cls); g_type_class_unref (cls);
continue; continue;
} }
@ -53,7 +55,8 @@ static GList *insert_drivers (GList *list)
key = g_strdup_printf ("%04x:%04x", entry->vid, entry->pid); key = g_strdup_printf ("%04x:%04x", entry->vid, entry->pid);
if (g_hash_table_lookup (printed, key) != NULL) { if (g_hash_table_lookup (printed, key) != NULL)
{
g_free (key); g_free (key);
continue; continue;
} }
@ -69,7 +72,8 @@ static GList *insert_drivers (GList *list)
return list; return list;
} }
int main (int argc, char **argv) int
main (int argc, char **argv)
{ {
GList *list, *l; GList *list, *l;

View file

@ -48,7 +48,8 @@ static const FpDeviceClass whitelist = {
GHashTable *printed = NULL; GHashTable *printed = NULL;
static void print_driver (const FpDeviceClass *cls) static void
print_driver (const FpDeviceClass *cls)
{ {
const FpIdEntry *entry; const FpIdEntry *entry;
gint num_printed = 0; gint num_printed = 0;
@ -56,21 +57,22 @@ static void print_driver (const FpDeviceClass *cls)
if (cls->type != FP_DEVICE_TYPE_USB) if (cls->type != FP_DEVICE_TYPE_USB)
return; return;
for (entry = cls->id_table; entry->vid != 0; entry++) { for (entry = cls->id_table; entry->vid != 0; entry++)
{
const FpIdEntry *bl_entry; const FpIdEntry *bl_entry;
char *key; char *key;
for (bl_entry = blacklist_id_table; bl_entry->vid != 0; bl_entry++) { for (bl_entry = blacklist_id_table; bl_entry->vid != 0; bl_entry++)
if (entry->vid == bl_entry->vid && entry->pid == bl_entry->pid) { if (entry->vid == bl_entry->vid && entry->pid == bl_entry->pid)
break; break;
}
}
if (bl_entry->vid != 0) if (bl_entry->vid != 0)
continue; continue;
key = g_strdup_printf ("%04x:%04x", entry->vid, entry->pid); key = g_strdup_printf ("%04x:%04x", entry->vid, entry->pid);
if (g_hash_table_lookup (printed, key) != NULL) { if (g_hash_table_lookup (printed, key) != NULL)
{
g_free (key); g_free (key);
continue; continue;
} }
@ -91,9 +93,10 @@ static void print_driver (const FpDeviceClass *cls)
g_print ("\n"); 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)); g_autoptr(GArray) drivers = g_array_new (FALSE, FALSE, sizeof (GType));
guint i; guint i;
g_print ("%p\n", drivers); g_print ("%p\n", drivers);
@ -102,11 +105,13 @@ int main (int argc, char **argv)
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++) { for (i = 0; i < drivers->len; i++)
{
GType driver = g_array_index (drivers, GType, i); GType driver = g_array_index (drivers, GType, i);
FpDeviceClass *cls = FP_DEVICE_CLASS (g_type_class_ref (driver)); FpDeviceClass *cls = FP_DEVICE_CLASS (g_type_class_ref (driver));
if (cls->type != FP_DEVICE_TYPE_USB) { if (cls->type != FP_DEVICE_TYPE_USB)
{
g_type_class_unref (cls); g_type_class_unref (cls);
continue; continue;
} }

View file

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

View file

@ -13,7 +13,7 @@ case "$1" in
esac esac
pushd "$SRCROOT" 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=$? RES=$?
popd popd
exit $RES exit $RES