diff --git a/libfprint/Makefile.am b/libfprint/Makefile.am index b86d0f8..6685665 100644 --- a/libfprint/Makefile.am +++ b/libfprint/Makefile.am @@ -48,6 +48,8 @@ EXTRA_DIST = \ drivers/aes3k.h \ drivers/driver_ids.h \ aeslib.c aeslib.h \ + assembling.c \ + assembling.h \ pixman.c \ 60-fprint-autosuspend.rules @@ -210,6 +212,8 @@ libfprint_la_SOURCES = \ imgdev.c \ poll.c \ sync.c \ + assembling.c \ + assembling.h \ $(DRIVER_SRC) \ $(OTHER_SRC) \ $(NBIS_SRC) diff --git a/libfprint/aeslib.c b/libfprint/aeslib.c index 8c0381a..978454d 100644 --- a/libfprint/aeslib.c +++ b/libfprint/aeslib.c @@ -26,6 +26,7 @@ #include #include "fp_internal.h" +#include "assembling.h" #include "aeslib.h" #define MAX_REGWRITES_PER_REQUEST 16 @@ -158,268 +159,16 @@ void aes_write_regv(struct fp_img_dev *dev, const struct aes_regwrite *regs, continue_write_regv(wdata); } -static inline unsigned char aes_get_pixel(struct aes_stripe *frame, +unsigned char aes_get_pixel(struct fpi_frame_asmbl_ctx *ctx, + struct fpi_frame *frame, unsigned int x, - unsigned int y, - unsigned int frame_width, - unsigned int frame_height) + unsigned int y) { unsigned char ret; - ret = frame->data[x * (frame_height >> 1) + (y >> 1)]; + ret = frame->data[x * (ctx->frame_height >> 1) + (y >> 1)]; ret = y % 2 ? ret >> 4 : ret & 0xf; ret *= 17; return ret; } - -static unsigned int calc_error(struct aes_stripe *first_frame, - struct aes_stripe *second_frame, - int dx, - int dy, - unsigned int frame_width, - unsigned int frame_height) -{ - unsigned int width, height; - unsigned int x1, y1, x2, y2, err, i, j; - - width = frame_width - (dx > 0 ? dx : -dx); - height = frame_height - dy; - - y1 = 0; - y2 = dy; - i = 0; - err = 0; - do { - x1 = dx < 0 ? 0 : dx; - x2 = dx < 0 ? -dx : 0; - j = 0; - - do { - unsigned char v1, v2; - - - v1 = aes_get_pixel(first_frame, x1, y1, frame_width, frame_height); - v2 = aes_get_pixel(second_frame, x2, y2, frame_width, frame_height); - err += v1 > v2 ? v1 - v2 : v2 - v1; - j++; - x1++; - x2++; - - } while (j < width); - i++; - y1++; - y2++; - } while (i < height); - - /* Normalize error */ - err *= (frame_height * frame_width); - err /= (height * width); - - if (err == 0) - return INT_MAX; - - return err; -} - -/* This function is rather CPU-intensive. It's better to use hardware - * to detect movement direction when possible. - */ -static void find_overlap(struct aes_stripe *first_frame, - struct aes_stripe *second_frame, - unsigned int *min_error, - unsigned int frame_width, - unsigned int frame_height) -{ - int dx, dy; - unsigned int err; - *min_error = INT_MAX; - - /* Seeking in horizontal and vertical dimensions, - * for horizontal dimension we'll check only 8 pixels - * in both directions. For vertical direction diff is - * rarely less than 2, so start with it. - */ - for (dy = 2; dy < frame_height; dy++) { - for (dx = -8; dx < 8; dx++) { - err = calc_error(first_frame, second_frame, - dx, dy, frame_width, frame_height); - if (err < *min_error) { - *min_error = err; - second_frame->delta_x = -dx; - second_frame->delta_y = dy; - } - } - } -} - -unsigned int aes_calc_delta(GSList *stripes, size_t num_stripes, - unsigned int frame_width, unsigned int frame_height, - gboolean reverse) -{ - GSList *list_entry = stripes; - GTimer *timer; - int frame = 1; - int height = 0; - struct aes_stripe *prev_stripe = list_entry->data; - unsigned int min_error; - - list_entry = g_slist_next(list_entry); - - timer = g_timer_new(); - do { - struct aes_stripe *cur_stripe = list_entry->data; - - if (reverse) { - find_overlap(prev_stripe, cur_stripe, &min_error, - frame_width, frame_height); - prev_stripe->delta_y = -prev_stripe->delta_y; - prev_stripe->delta_x = -prev_stripe->delta_x; - } - else - find_overlap(cur_stripe, prev_stripe, &min_error, - frame_width, frame_height); - - frame++; - height += prev_stripe->delta_y; - prev_stripe = cur_stripe; - list_entry = g_slist_next(list_entry); - - } while (frame < num_stripes); - - if (height < 0) - height = -height; - height += frame_height; - g_timer_stop(timer); - fp_dbg("calc delta completed in %f secs", g_timer_elapsed(timer, NULL)); - g_timer_destroy(timer); - - return height; -} - -static inline void aes_blit_stripe(struct fp_img *img, - struct aes_stripe *stripe, - int x, int y, unsigned int frame_width, - unsigned int frame_height) -{ - unsigned int ix, iy; - unsigned int fx, fy; - unsigned int width, height; - - /* Find intersection */ - if (x < 0) { - width = frame_width + x; - ix = 0; - fx = -x; - } else { - ix = x; - fx = 0; - width = frame_width; - } - if ((ix + width) > img->width) - width = img->width - ix; - - if (y < 0) { - iy = 0; - fy = -y; - height = frame_height + y; - } else { - iy = y; - fy = 0; - height = frame_height; - } - - if (fx > frame_width) - return; - - if (fy > frame_height) - return; - - if (ix > img->width) - return; - - if (iy > img->height) - return; - - if ((iy + height) > img->height) - height = img->height - iy; - - for (; fy < height; fy++, iy++) { - if (x < 0) { - ix = 0; - fx = -x; - } else { - ix = x; - fx = 0; - } - for (; fx < width; fx++, ix++) { - img->data[ix + (iy * img->width)] = aes_get_pixel(stripe, fx, fy, frame_width, frame_height); - } - } -} - -struct fp_img *aes_assemble(GSList *stripes, size_t stripes_len, - unsigned int frame_width, unsigned int frame_height, unsigned int img_width) -{ - GSList *stripe; - struct fp_img *img; - int height = 0; - int i, y, x; - gboolean reverse = FALSE; - struct aes_stripe *aes_stripe; - - BUG_ON(stripes_len == 0); - BUG_ON(img_width < frame_width); - - /* Calculate height */ - i = 0; - stripe = stripes; - - /* No offset for 1st image */ - aes_stripe = stripe->data; - aes_stripe->delta_x = 0; - aes_stripe->delta_y = 0; - do { - aes_stripe = stripe->data; - - height += aes_stripe->delta_y; - i++; - stripe = g_slist_next(stripe); - } while (i < stripes_len); - - fp_dbg("height is %d", height); - - if (height < 0) { - reverse = TRUE; - height = -height; - } - - /* For last frame */ - height += frame_height; - - /* Create buffer big enough for max image */ - img = fpi_img_new(img_width * height); - img->flags = FP_IMG_COLORS_INVERTED; - img->width = img_width; - img->height = height; - - /* Assemble stripes */ - i = 0; - stripe = stripes; - y = reverse ? (height - frame_height) : 0; - x = (img_width - frame_width) / 2; - - do { - aes_stripe = stripe->data; - - y += aes_stripe->delta_y; - x += aes_stripe->delta_x; - - aes_blit_stripe(img, aes_stripe, x, y, frame_width, frame_height); - - stripe = g_slist_next(stripe); - i++; - } while (i < stripes_len); - - return img; -} diff --git a/libfprint/aeslib.h b/libfprint/aeslib.h index 7721d11..2dd6cea 100644 --- a/libfprint/aeslib.h +++ b/libfprint/aeslib.h @@ -27,11 +27,8 @@ struct aes_regwrite { unsigned char value; }; -struct aes_stripe { - int delta_x; - int delta_y; - unsigned char data[0]; -}; +struct fpi_frame; +struct fpi_frame_asmbl_ctx; typedef void (*aes_write_regv_cb)(struct fp_img_dev *dev, int result, void *user_data); @@ -39,12 +36,10 @@ typedef void (*aes_write_regv_cb)(struct fp_img_dev *dev, int result, void aes_write_regv(struct fp_img_dev *dev, const struct aes_regwrite *regs, unsigned int num_regs, aes_write_regv_cb callback, void *user_data); -unsigned int aes_calc_delta(GSList *stripes, size_t stripes_len, - unsigned int frame_width, unsigned int frame_height, - gboolean reverse); - -struct fp_img *aes_assemble(GSList *stripes, size_t stripes_len, - unsigned int frame_width, unsigned int frame_height, unsigned int img_width); +unsigned char aes_get_pixel(struct fpi_frame_asmbl_ctx *ctx, + struct fpi_frame *frame, + unsigned int x, + unsigned int y); #endif diff --git a/libfprint/assembling.c b/libfprint/assembling.c new file mode 100644 index 0000000..dd8d212 --- /dev/null +++ b/libfprint/assembling.c @@ -0,0 +1,277 @@ +/* + * Image assembling routines + * Copyright (C) 2007-2008 Daniel Drake + * Copyright (C) 2015 Vasily Khoruzhick + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#define FP_COMPONENT "assembling" + +#include +#include + +#include +#include + +#include "fp_internal.h" +#include "assembling.h" + +static unsigned int calc_error(struct fpi_frame_asmbl_ctx *ctx, + struct fpi_frame *first_frame, + struct fpi_frame *second_frame, + int dx, + int dy) +{ + unsigned int width, height; + unsigned int x1, y1, x2, y2, err, i, j; + + width = ctx->frame_width - (dx > 0 ? dx : -dx); + height = ctx->frame_height - dy; + + y1 = 0; + y2 = dy; + i = 0; + err = 0; + do { + x1 = dx < 0 ? 0 : dx; + x2 = dx < 0 ? -dx : 0; + j = 0; + + do { + unsigned char v1, v2; + + + v1 = ctx->get_pixel(ctx, first_frame, x1, y1); + v2 = ctx->get_pixel(ctx, second_frame, x2, y2); + err += v1 > v2 ? v1 - v2 : v2 - v1; + j++; + x1++; + x2++; + + } while (j < width); + i++; + y1++; + y2++; + } while (i < height); + + /* Normalize error */ + err *= (ctx->frame_height * ctx->frame_width); + err /= (height * width); + + if (err == 0) + return INT_MAX; + + return err; +} + +/* This function is rather CPU-intensive. It's better to use hardware + * to detect movement direction when possible. + */ +static void find_overlap(struct fpi_frame_asmbl_ctx *ctx, + struct fpi_frame *first_frame, + struct fpi_frame *second_frame, + unsigned int *min_error) +{ + int dx, dy; + unsigned int err; + *min_error = INT_MAX; + + /* Seeking in horizontal and vertical dimensions, + * for horizontal dimension we'll check only 8 pixels + * in both directions. For vertical direction diff is + * rarely less than 2, so start with it. + */ + for (dy = 2; dy < ctx->frame_height; dy++) { + for (dx = -8; dx < 8; dx++) { + err = calc_error(ctx, first_frame, second_frame, + dx, dy); + if (err < *min_error) { + *min_error = err; + second_frame->delta_x = -dx; + second_frame->delta_y = dy; + } + } + } +} + +unsigned int fpi_do_movement_estimation(struct fpi_frame_asmbl_ctx *ctx, + GSList *stripes, size_t num_stripes, + gboolean reverse) +{ + GSList *list_entry = stripes; + GTimer *timer; + int frame = 1; + int height = 0; + struct fpi_frame *prev_stripe = list_entry->data; + unsigned int min_error; + + list_entry = g_slist_next(list_entry); + + timer = g_timer_new(); + do { + struct fpi_frame *cur_stripe = list_entry->data; + + if (reverse) { + find_overlap(ctx, prev_stripe, cur_stripe, &min_error); + prev_stripe->delta_y = -prev_stripe->delta_y; + prev_stripe->delta_x = -prev_stripe->delta_x; + } + else + find_overlap(ctx, cur_stripe, prev_stripe, &min_error); + + frame++; + height += prev_stripe->delta_y; + prev_stripe = cur_stripe; + list_entry = g_slist_next(list_entry); + + } while (frame < num_stripes); + + if (height < 0) + height = -height; + height += ctx->frame_height; + g_timer_stop(timer); + fp_dbg("calc delta completed in %f secs", g_timer_elapsed(timer, NULL)); + g_timer_destroy(timer); + + return height; +} + +static inline void aes_blit_stripe(struct fpi_frame_asmbl_ctx *ctx, + struct fp_img *img, + struct fpi_frame *stripe, + int x, int y) +{ + unsigned int ix, iy; + unsigned int fx, fy; + unsigned int width, height; + + /* Find intersection */ + if (x < 0) { + width = ctx->frame_width + x; + ix = 0; + fx = -x; + } else { + ix = x; + fx = 0; + width = ctx->frame_width; + } + if ((ix + width) > img->width) + width = img->width - ix; + + if (y < 0) { + iy = 0; + fy = -y; + height = ctx->frame_height + y; + } else { + iy = y; + fy = 0; + height = ctx->frame_height; + } + + if (fx > ctx->frame_width) + return; + + if (fy > ctx->frame_height) + return; + + if (ix > img->width) + return; + + if (iy > img->height) + return; + + if ((iy + height) > img->height) + height = img->height - iy; + + for (; fy < height; fy++, iy++) { + if (x < 0) { + ix = 0; + fx = -x; + } else { + ix = x; + fx = 0; + } + for (; fx < width; fx++, ix++) { + img->data[ix + (iy * img->width)] = ctx->get_pixel(ctx, stripe, fx, fy); + } + } +} + +struct fp_img *fpi_assemble_frames(struct fpi_frame_asmbl_ctx *ctx, + GSList *stripes, size_t stripes_len) +{ + GSList *stripe; + struct fp_img *img; + int height = 0; + int i, y, x; + gboolean reverse = FALSE; + struct fpi_frame *fpi_frame; + + BUG_ON(stripes_len == 0); + BUG_ON(ctx->image_width < ctx->frame_width); + + /* Calculate height */ + i = 0; + stripe = stripes; + + /* No offset for 1st image */ + fpi_frame = stripe->data; + fpi_frame->delta_x = 0; + fpi_frame->delta_y = 0; + do { + fpi_frame = stripe->data; + + height += fpi_frame->delta_y; + i++; + stripe = g_slist_next(stripe); + } while (i < stripes_len); + + fp_dbg("height is %d", height); + + if (height < 0) { + reverse = TRUE; + height = -height; + } + + /* For last frame */ + height += ctx->frame_height; + + /* Create buffer big enough for max image */ + img = fpi_img_new(ctx->image_width * height); + img->flags = FP_IMG_COLORS_INVERTED; + img->width = ctx->image_width; + img->height = height; + + /* Assemble stripes */ + i = 0; + stripe = stripes; + y = reverse ? (height - ctx->frame_height) : 0; + x = (ctx->image_width - ctx->frame_width) / 2; + + do { + fpi_frame = stripe->data; + + y += fpi_frame->delta_y; + x += fpi_frame->delta_x; + + aes_blit_stripe(ctx, img, fpi_frame, x, y); + + stripe = g_slist_next(stripe); + i++; + } while (i < stripes_len); + + return img; +} diff --git a/libfprint/assembling.h b/libfprint/assembling.h new file mode 100644 index 0000000..1d1905d --- /dev/null +++ b/libfprint/assembling.h @@ -0,0 +1,50 @@ +/* + * Image assembling routines + * Shared functions between libfprint Authentec drivers + * Copyright (C) 2007 Daniel Drake + * Copyright (C) 2015 Vasily Khoruzhick + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __ASSEMBLING_H__ +#define __ASSEMBLING_H__ + +#include + +struct fpi_frame { + int delta_x; + int delta_y; + unsigned char data[0]; +}; + +struct fpi_frame_asmbl_ctx { + unsigned frame_width; + unsigned frame_height; + unsigned image_width; + unsigned char (*get_pixel)(struct fpi_frame_asmbl_ctx *ctx, + struct fpi_frame *frame, + unsigned x, + unsigned y); +}; + +unsigned int fpi_do_movement_estimation(struct fpi_frame_asmbl_ctx *ctx, + GSList *stripes, size_t stripes_len, + gboolean reverse); + +struct fp_img *fpi_assemble_frames(struct fpi_frame_asmbl_ctx *ctx, + GSList *stripes, size_t stripes_len); + +#endif diff --git a/libfprint/drivers/aes1610.c b/libfprint/drivers/aes1610.c index f87a63c..d8aaeaa 100644 --- a/libfprint/drivers/aes1610.c +++ b/libfprint/drivers/aes1610.c @@ -30,6 +30,7 @@ #include +#include #include #include @@ -66,6 +67,7 @@ static int adjust_gain(unsigned char *buffer, int status); #define FRAME_WIDTH 128 #define FRAME_HEIGHT 8 #define FRAME_SIZE (FRAME_WIDTH * FRAME_HEIGHT) +#define IMAGE_WIDTH (FRAME_WIDTH + (FRAME_WIDTH / 2)) /* maximum number of frames to read during a scan */ /* FIXME reduce substantially */ #define MAX_FRAMES 350 @@ -80,6 +82,13 @@ struct aes1610_dev { uint8_t blanks_count; }; +static struct fpi_frame_asmbl_ctx assembling_ctx = { + .frame_width = FRAME_WIDTH, + .frame_height = FRAME_HEIGHT, + .image_width = IMAGE_WIDTH, + .get_pixel = aes_get_pixel, +}; + typedef void (*aes1610_read_regs_cb)(struct fp_img_dev *dev, int status, unsigned char *regs, void *user_data); @@ -580,7 +589,7 @@ static void capture_read_strip_cb(struct libusb_transfer *transfer) if (sum > 0) { /* FIXME: would preallocating strip buffers be a decent optimization? */ - struct aes_stripe *stripe = g_malloc(FRAME_WIDTH * (FRAME_HEIGHT / 2) + sizeof(struct aes_stripe)); + struct fpi_frame *stripe = g_malloc(FRAME_WIDTH * (FRAME_HEIGHT / 2) + sizeof(struct fpi_frame)); stripe->delta_x = 0; stripe->delta_y = 0; stripdata = stripe->data; @@ -618,18 +627,14 @@ static void capture_read_strip_cb(struct libusb_transfer *transfer) /* send stop capture bits */ aes_write_regv(dev, capture_stop, G_N_ELEMENTS(capture_stop), stub_capture_stop_cb, NULL); aesdev->strips = g_slist_reverse(aesdev->strips); - height = aes_calc_delta(aesdev->strips, aesdev->strips_len, - FRAME_WIDTH, FRAME_HEIGHT, FALSE); - rev_height = aes_calc_delta(aesdev->strips, aesdev->strips_len, - FRAME_WIDTH, FRAME_HEIGHT, TRUE); + height = fpi_do_movement_estimation(&assembling_ctx, aesdev->strips, aesdev->strips_len, FALSE); + rev_height = fpi_do_movement_estimation(&assembling_ctx, aesdev->strips, aesdev->strips_len, TRUE); fp_dbg("heights: %d rev: %d", height, rev_height); if (rev_height < height) { fp_dbg("Reversed direction"); - height = aes_calc_delta(aesdev->strips, aesdev->strips_len, - FRAME_WIDTH, FRAME_HEIGHT, FALSE); + height = fpi_do_movement_estimation(&assembling_ctx, aesdev->strips, aesdev->strips_len, FALSE); } - img = aes_assemble(aesdev->strips, aesdev->strips_len, - FRAME_WIDTH, FRAME_HEIGHT, FRAME_WIDTH + FRAME_WIDTH / 2); + img = fpi_assemble_frames(&assembling_ctx, aesdev->strips, aesdev->strips_len); g_slist_free_full(aesdev->strips, g_free); aesdev->strips = NULL; aesdev->strips_len = 0; @@ -843,7 +848,7 @@ struct fp_img_driver aes1610_driver = { }, .flags = 0, .img_height = -1, - .img_width = FRAME_WIDTH + FRAME_WIDTH / 2, + .img_width = IMAGE_WIDTH, .bz3_threshold = 50, diff --git a/libfprint/drivers/aes1660.c b/libfprint/drivers/aes1660.c index b221561..8e63fe3 100644 --- a/libfprint/drivers/aes1660.c +++ b/libfprint/drivers/aes1660.c @@ -28,12 +28,22 @@ #include +#include +#include + #include "aesx660.h" #include "aes1660.h" #include "driver_ids.h" #define FRAME_WIDTH 128 -#define SCALE_FACTOR 2 +#define IMAGE_WIDTH (FRAME_WIDTH + (FRAME_WIDTH / 2)) + +static struct fpi_frame_asmbl_ctx assembling_ctx = { + .frame_width = FRAME_WIDTH, + .frame_height = AESX660_FRAME_HEIGHT, + .image_width = IMAGE_WIDTH, + .get_pixel = aes_get_pixel, +}; static int dev_init(struct fp_img_dev *dev, unsigned long driver_data) { @@ -55,7 +65,7 @@ static int dev_init(struct fp_img_dev *dev, unsigned long driver_data) aesdev->init_seqs_len[1] = array_n_elements(aes1660_init_2); aesdev->start_imaging_cmd = (unsigned char *)aes1660_start_imaging_cmd; aesdev->start_imaging_cmd_len = sizeof(aes1660_start_imaging_cmd); - aesdev->frame_width = FRAME_WIDTH; + aesdev->assembling_ctx = &assembling_ctx; aesdev->extra_img_flags = FP_IMG_PARTIAL; fpi_imgdev_open_complete(dev, 0); diff --git a/libfprint/drivers/aes2501.c b/libfprint/drivers/aes2501.c index 264e2dc..426bd9e 100644 --- a/libfprint/drivers/aes2501.c +++ b/libfprint/drivers/aes2501.c @@ -28,6 +28,7 @@ #include +#include #include #include @@ -58,6 +59,7 @@ static void complete_deactivation(struct fp_img_dev *dev); #define FRAME_WIDTH 192 #define FRAME_HEIGHT 16 #define FRAME_SIZE (FRAME_WIDTH * FRAME_HEIGHT) +#define IMAGE_WIDTH (FRAME_WIDTH + (FRAME_WIDTH / 2)) /* maximum number of frames to read during a scan */ /* FIXME reduce substantially */ #define MAX_FRAMES 150 @@ -72,6 +74,13 @@ struct aes2501_dev { int no_finger_cnt; }; +static struct fpi_frame_asmbl_ctx assembling_ctx = { + .frame_width = FRAME_WIDTH, + .frame_height = FRAME_HEIGHT, + .image_width = IMAGE_WIDTH, + .get_pixel = aes_get_pixel, +}; + typedef void (*aes2501_read_regs_cb)(struct fp_img_dev *dev, int status, unsigned char *regs, void *user_data); @@ -484,18 +493,18 @@ static void capture_read_strip_cb(struct libusb_transfer *transfer) unsigned int height, rev_height; aesdev->strips = g_slist_reverse(aesdev->strips); - height = aes_calc_delta(aesdev->strips, aesdev->strips_len, - FRAME_WIDTH, FRAME_HEIGHT, FALSE); - rev_height = aes_calc_delta(aesdev->strips, aesdev->strips_len, - FRAME_WIDTH, FRAME_HEIGHT, TRUE); + height = fpi_do_movement_estimation(&assembling_ctx, + aesdev->strips, aesdev->strips_len, FALSE); + rev_height = fpi_do_movement_estimation(&assembling_ctx, + aesdev->strips, aesdev->strips_len, TRUE); fp_dbg("heights: %d rev: %d", height, rev_height); if (rev_height < height) { fp_dbg("Reversed direction"); - height = aes_calc_delta(aesdev->strips, aesdev->strips_len, - FRAME_WIDTH, FRAME_HEIGHT, FALSE); + height = fpi_do_movement_estimation(&assembling_ctx, + aesdev->strips, aesdev->strips_len, FALSE); } - img = aes_assemble(aesdev->strips, aesdev->strips_len, - FRAME_WIDTH, FRAME_HEIGHT, FRAME_WIDTH + FRAME_WIDTH / 2); + img = fpi_assemble_frames(&assembling_ctx, + aesdev->strips, aesdev->strips_len); g_slist_free_full(aesdev->strips, g_free); aesdev->strips = NULL; aesdev->strips_len = 0; @@ -509,7 +518,7 @@ static void capture_read_strip_cb(struct libusb_transfer *transfer) } else { /* obtain next strip */ /* FIXME: would preallocating strip buffers be a decent optimization? */ - struct aes_stripe *stripe = g_malloc(FRAME_WIDTH * FRAME_HEIGHT / 2 + sizeof(struct aes_stripe)); + struct fpi_frame *stripe = g_malloc(FRAME_WIDTH * FRAME_HEIGHT / 2 + sizeof(struct fpi_frame)); stripe->delta_x = 0; stripe->delta_y = 0; stripdata = stripe->data; @@ -881,7 +890,7 @@ struct fp_img_driver aes2501_driver = { }, .flags = 0, .img_height = -1, - .img_width = FRAME_WIDTH + FRAME_WIDTH / 2, + .img_width = IMAGE_WIDTH, .open = dev_init, .close = dev_deinit, diff --git a/libfprint/drivers/aes2550.c b/libfprint/drivers/aes2550.c index 29e59d1..822dbcd 100644 --- a/libfprint/drivers/aes2550.c +++ b/libfprint/drivers/aes2550.c @@ -28,6 +28,7 @@ #include +#include #include #include @@ -56,6 +57,7 @@ static void complete_deactivation(struct fp_img_dev *dev); #define FRAME_WIDTH 192 #define FRAME_HEIGHT 8 #define FRAME_SIZE (FRAME_WIDTH * FRAME_HEIGHT) +#define IMAGE_WIDTH (FRAME_WIDTH + (FRAME_WIDTH / 2)) struct aes2550_dev { GSList *strips; @@ -64,6 +66,13 @@ struct aes2550_dev { int heartbeat_cnt; }; +static struct fpi_frame_asmbl_ctx assembling_ctx = { + .frame_width = FRAME_WIDTH, + .frame_height = FRAME_HEIGHT, + .image_width = IMAGE_WIDTH, + .get_pixel = aes_get_pixel, +}; + /****** FINGER PRESENCE DETECTION ******/ static unsigned char finger_det_reqs[] = { @@ -204,7 +213,7 @@ static int process_strip_data(struct fpi_ssm *ssm, unsigned char *data) unsigned char *stripdata; struct fp_img_dev *dev = ssm->priv; struct aes2550_dev *aesdev = dev->priv; - struct aes_stripe *stripe; + struct fpi_frame *stripe; int len; if (data[0] != AES2550_EDATA_MAGIC) { @@ -215,7 +224,7 @@ static int process_strip_data(struct fpi_ssm *ssm, unsigned char *data) if (len != (AES2550_STRIP_SIZE - 3)) { fp_dbg("Bogus frame len: %.4x\n", len); } - stripe = g_malloc(FRAME_WIDTH * FRAME_HEIGHT / 2 + sizeof(struct aes_stripe)); /* 4 bits per pixel */ + stripe = g_malloc(FRAME_WIDTH * FRAME_HEIGHT / 2 + sizeof(struct fpi_frame)); /* 4 bits per pixel */ stripe->delta_x = (int8_t)data[6]; stripe->delta_y = -(int8_t)data[7]; stripdata = stripe->data; @@ -253,8 +262,8 @@ static void capture_set_idle_reqs_cb(struct libusb_transfer *transfer) struct fp_img *img; aesdev->strips = g_slist_reverse(aesdev->strips); - img = aes_assemble(aesdev->strips, aesdev->strips_len, - FRAME_WIDTH, FRAME_HEIGHT, FRAME_WIDTH + FRAME_WIDTH / 2); + img = fpi_assemble_frames(&assembling_ctx, + aesdev->strips, aesdev->strips_len); g_slist_free_full(aesdev->strips, g_free); aesdev->strips = NULL; aesdev->strips_len = 0; diff --git a/libfprint/drivers/aes2660.c b/libfprint/drivers/aes2660.c index d7b6cef..2edb765 100644 --- a/libfprint/drivers/aes2660.c +++ b/libfprint/drivers/aes2660.c @@ -28,11 +28,22 @@ #include +#include +#include + #include "aesx660.h" #include "aes2660.h" #include "driver_ids.h" #define FRAME_WIDTH 192 +#define IMAGE_WIDTH (FRAME_WIDTH + (FRAME_WIDTH / 2)) + +static struct fpi_frame_asmbl_ctx assembling_ctx = { + .frame_width = FRAME_WIDTH, + .frame_height = AESX660_FRAME_HEIGHT, + .image_width = IMAGE_WIDTH, + .get_pixel = aes_get_pixel, +}; static int dev_init(struct fp_img_dev *dev, unsigned long driver_data) { @@ -55,7 +66,7 @@ static int dev_init(struct fp_img_dev *dev, unsigned long driver_data) aesdev->init_seqs_len[1] = array_n_elements(aes2660_init_2); aesdev->start_imaging_cmd = (unsigned char *)aes2660_start_imaging_cmd; aesdev->start_imaging_cmd_len = sizeof(aes2660_start_imaging_cmd); - aesdev->frame_width = FRAME_WIDTH; + aesdev->assembling_ctx = &assembling_ctx; fpi_imgdev_open_complete(dev, 0); return 0; diff --git a/libfprint/drivers/aesx660.c b/libfprint/drivers/aesx660.c index 433ba33..278fe81 100644 --- a/libfprint/drivers/aesx660.c +++ b/libfprint/drivers/aesx660.c @@ -30,6 +30,7 @@ #include +#include #include #include @@ -41,7 +42,7 @@ static void complete_deactivation(struct fp_img_dev *dev); #define EP_IN (1 | LIBUSB_ENDPOINT_IN) #define EP_OUT (2 | LIBUSB_ENDPOINT_OUT) #define BULK_TIMEOUT 4000 -#define FRAME_HEIGHT 8 +#define FRAME_HEIGHT AESX660_FRAME_HEIGHT #define min(a, b) (((a) < (b)) ? (a) : (b)) @@ -273,12 +274,12 @@ enum capture_states { /* Returns number of processed bytes */ static int process_stripe_data(struct fpi_ssm *ssm, unsigned char *data) { - struct aes_stripe *stripe; + struct fpi_frame *stripe; unsigned char *stripdata; struct fp_img_dev *dev = ssm->priv; struct aesX660_dev *aesdev = dev->priv; - stripe = g_malloc(aesdev->frame_width * FRAME_HEIGHT / 2 + sizeof(struct aes_stripe)); /* 4 bpp */ + stripe = g_malloc(aesdev->assembling_ctx->frame_width * FRAME_HEIGHT / 2 + sizeof(struct fpi_frame)); /* 4 bpp */ stripdata = stripe->data; fp_dbg("Processing frame %.2x %.2x", data[AESX660_IMAGE_OK_OFFSET], @@ -289,7 +290,7 @@ static int process_stripe_data(struct fpi_ssm *ssm, unsigned char *data) fp_dbg("Offset to previous frame: %d %d", stripe->delta_x, stripe->delta_y); if (data[AESX660_IMAGE_OK_OFFSET] == AESX660_IMAGE_OK) { - memcpy(stripdata, data + AESX660_IMAGE_OFFSET, aesdev->frame_width * FRAME_HEIGHT / 2); + memcpy(stripdata, data + AESX660_IMAGE_OFFSET, aesdev->assembling_ctx->frame_width * FRAME_HEIGHT / 2); aesdev->strips = g_slist_prepend(aesdev->strips, stripe); aesdev->strips_len++; @@ -311,8 +312,7 @@ static void capture_set_idle_cmd_cb(struct libusb_transfer *transfer) struct fp_img *img; aesdev->strips = g_slist_reverse(aesdev->strips); - img = aes_assemble(aesdev->strips, aesdev->strips_len, - aesdev->frame_width, FRAME_HEIGHT, aesdev->frame_width + aesdev->frame_width / 2); + img = fpi_assemble_frames(aesdev->assembling_ctx, aesdev->strips, aesdev->strips_len); img->flags |= aesdev->extra_img_flags; g_slist_foreach(aesdev->strips, (GFunc) g_free, NULL); g_slist_free(aesdev->strips); diff --git a/libfprint/drivers/aesx660.h b/libfprint/drivers/aesx660.h index 044d809..2106ca2 100644 --- a/libfprint/drivers/aesx660.h +++ b/libfprint/drivers/aesx660.h @@ -41,6 +41,8 @@ #define AESX660_IMAGE_OFFSET 43 #define AESX660_BULK_TRANSFER_SIZE 4096 +#define AESX660_FRAME_HEIGHT 8 + struct aesX660_dev { GSList *strips; size_t strips_len; @@ -55,12 +57,11 @@ struct aesX660_dev { size_t buffer_max; /* Device-specific stuff */ - int h_scale_factor; struct aesX660_cmd *init_seqs[2]; size_t init_seqs_len[2]; unsigned char *start_imaging_cmd; size_t start_imaging_cmd_len; - unsigned int frame_width; + struct fpi_frame_asmbl_ctx *assembling_ctx; uint16_t extra_img_flags; };