lib: move frame assembling routines into a separate file and make them usable by non-aes drivers
Frame assembling routines are not aes-specific, so move them into a separate file and add an accessor for peeking a pixel.
This commit is contained in:
parent
6664f87d8f
commit
e40f7bd1f7
12 changed files with 422 additions and 302 deletions
|
@ -48,6 +48,8 @@ EXTRA_DIST = \
|
||||||
drivers/aes3k.h \
|
drivers/aes3k.h \
|
||||||
drivers/driver_ids.h \
|
drivers/driver_ids.h \
|
||||||
aeslib.c aeslib.h \
|
aeslib.c aeslib.h \
|
||||||
|
assembling.c \
|
||||||
|
assembling.h \
|
||||||
pixman.c \
|
pixman.c \
|
||||||
60-fprint-autosuspend.rules
|
60-fprint-autosuspend.rules
|
||||||
|
|
||||||
|
@ -210,6 +212,8 @@ libfprint_la_SOURCES = \
|
||||||
imgdev.c \
|
imgdev.c \
|
||||||
poll.c \
|
poll.c \
|
||||||
sync.c \
|
sync.c \
|
||||||
|
assembling.c \
|
||||||
|
assembling.h \
|
||||||
$(DRIVER_SRC) \
|
$(DRIVER_SRC) \
|
||||||
$(OTHER_SRC) \
|
$(OTHER_SRC) \
|
||||||
$(NBIS_SRC)
|
$(NBIS_SRC)
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
|
|
||||||
#include "fp_internal.h"
|
#include "fp_internal.h"
|
||||||
|
#include "assembling.h"
|
||||||
#include "aeslib.h"
|
#include "aeslib.h"
|
||||||
|
|
||||||
#define MAX_REGWRITES_PER_REQUEST 16
|
#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);
|
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 x,
|
||||||
unsigned int y,
|
unsigned int y)
|
||||||
unsigned int frame_width,
|
|
||||||
unsigned int frame_height)
|
|
||||||
{
|
{
|
||||||
unsigned char ret;
|
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 = y % 2 ? ret >> 4 : ret & 0xf;
|
||||||
ret *= 17;
|
ret *= 17;
|
||||||
|
|
||||||
return ret;
|
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;
|
|
||||||
}
|
|
||||||
|
|
|
@ -27,11 +27,8 @@ struct aes_regwrite {
|
||||||
unsigned char value;
|
unsigned char value;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct aes_stripe {
|
struct fpi_frame;
|
||||||
int delta_x;
|
struct fpi_frame_asmbl_ctx;
|
||||||
int delta_y;
|
|
||||||
unsigned char data[0];
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef void (*aes_write_regv_cb)(struct fp_img_dev *dev, int result,
|
typedef void (*aes_write_regv_cb)(struct fp_img_dev *dev, int result,
|
||||||
void *user_data);
|
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,
|
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 num_regs, aes_write_regv_cb callback, void *user_data);
|
||||||
|
|
||||||
unsigned int aes_calc_delta(GSList *stripes, size_t stripes_len,
|
unsigned char aes_get_pixel(struct fpi_frame_asmbl_ctx *ctx,
|
||||||
unsigned int frame_width, unsigned int frame_height,
|
struct fpi_frame *frame,
|
||||||
gboolean reverse);
|
unsigned int x,
|
||||||
|
unsigned int y);
|
||||||
struct fp_img *aes_assemble(GSList *stripes, size_t stripes_len,
|
|
||||||
unsigned int frame_width, unsigned int frame_height, unsigned int img_width);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
277
libfprint/assembling.c
Normal file
277
libfprint/assembling.c
Normal file
|
@ -0,0 +1,277 @@
|
||||||
|
/*
|
||||||
|
* Image assembling routines
|
||||||
|
* Copyright (C) 2007-2008 Daniel Drake <dsd@gentoo.org>
|
||||||
|
* Copyright (C) 2015 Vasily Khoruzhick <anarsoul@gmail.com>
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define FP_COMPONENT "assembling"
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <libusb.h>
|
||||||
|
#include <glib.h>
|
||||||
|
|
||||||
|
#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;
|
||||||
|
}
|
50
libfprint/assembling.h
Normal file
50
libfprint/assembling.h
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
/*
|
||||||
|
* Image assembling routines
|
||||||
|
* Shared functions between libfprint Authentec drivers
|
||||||
|
* Copyright (C) 2007 Daniel Drake <dsd@gentoo.org>
|
||||||
|
* Copyright (C) 2015 Vasily Khoruzhick <anarsoul@gmail.com>
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __ASSEMBLING_H__
|
||||||
|
#define __ASSEMBLING_H__
|
||||||
|
|
||||||
|
#include <fp_internal.h>
|
||||||
|
|
||||||
|
struct fpi_frame {
|
||||||
|
int delta_x;
|
||||||
|
int delta_y;
|
||||||
|
unsigned char data[0];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct fpi_frame_asmbl_ctx {
|
||||||
|
unsigned frame_width;
|
||||||
|
unsigned frame_height;
|
||||||
|
unsigned image_width;
|
||||||
|
unsigned char (*get_pixel)(struct fpi_frame_asmbl_ctx *ctx,
|
||||||
|
struct fpi_frame *frame,
|
||||||
|
unsigned x,
|
||||||
|
unsigned y);
|
||||||
|
};
|
||||||
|
|
||||||
|
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
|
|
@ -30,6 +30,7 @@
|
||||||
|
|
||||||
#include <libusb.h>
|
#include <libusb.h>
|
||||||
|
|
||||||
|
#include <assembling.h>
|
||||||
#include <aeslib.h>
|
#include <aeslib.h>
|
||||||
#include <fp_internal.h>
|
#include <fp_internal.h>
|
||||||
|
|
||||||
|
@ -66,6 +67,7 @@ static int adjust_gain(unsigned char *buffer, int status);
|
||||||
#define FRAME_WIDTH 128
|
#define FRAME_WIDTH 128
|
||||||
#define FRAME_HEIGHT 8
|
#define FRAME_HEIGHT 8
|
||||||
#define FRAME_SIZE (FRAME_WIDTH * FRAME_HEIGHT)
|
#define FRAME_SIZE (FRAME_WIDTH * FRAME_HEIGHT)
|
||||||
|
#define IMAGE_WIDTH (FRAME_WIDTH + (FRAME_WIDTH / 2))
|
||||||
/* maximum number of frames to read during a scan */
|
/* maximum number of frames to read during a scan */
|
||||||
/* FIXME reduce substantially */
|
/* FIXME reduce substantially */
|
||||||
#define MAX_FRAMES 350
|
#define MAX_FRAMES 350
|
||||||
|
@ -80,6 +82,13 @@ struct aes1610_dev {
|
||||||
uint8_t blanks_count;
|
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,
|
typedef void (*aes1610_read_regs_cb)(struct fp_img_dev *dev, int status,
|
||||||
unsigned char *regs, void *user_data);
|
unsigned char *regs, void *user_data);
|
||||||
|
|
||||||
|
@ -580,7 +589,7 @@ static void capture_read_strip_cb(struct libusb_transfer *transfer)
|
||||||
|
|
||||||
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 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_x = 0;
|
||||||
stripe->delta_y = 0;
|
stripe->delta_y = 0;
|
||||||
stripdata = stripe->data;
|
stripdata = stripe->data;
|
||||||
|
@ -618,18 +627,14 @@ static void capture_read_strip_cb(struct libusb_transfer *transfer)
|
||||||
/* 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);
|
||||||
aesdev->strips = g_slist_reverse(aesdev->strips);
|
aesdev->strips = g_slist_reverse(aesdev->strips);
|
||||||
height = aes_calc_delta(aesdev->strips, aesdev->strips_len,
|
height = fpi_do_movement_estimation(&assembling_ctx, aesdev->strips, aesdev->strips_len, FALSE);
|
||||||
FRAME_WIDTH, FRAME_HEIGHT, FALSE);
|
rev_height = fpi_do_movement_estimation(&assembling_ctx, aesdev->strips, aesdev->strips_len, TRUE);
|
||||||
rev_height = aes_calc_delta(aesdev->strips, aesdev->strips_len,
|
|
||||||
FRAME_WIDTH, FRAME_HEIGHT, TRUE);
|
|
||||||
fp_dbg("heights: %d rev: %d", height, rev_height);
|
fp_dbg("heights: %d rev: %d", height, rev_height);
|
||||||
if (rev_height < height) {
|
if (rev_height < height) {
|
||||||
fp_dbg("Reversed direction");
|
fp_dbg("Reversed direction");
|
||||||
height = aes_calc_delta(aesdev->strips, aesdev->strips_len,
|
height = fpi_do_movement_estimation(&assembling_ctx, aesdev->strips, aesdev->strips_len, FALSE);
|
||||||
FRAME_WIDTH, FRAME_HEIGHT, FALSE);
|
|
||||||
}
|
}
|
||||||
img = aes_assemble(aesdev->strips, aesdev->strips_len,
|
img = fpi_assemble_frames(&assembling_ctx, aesdev->strips, aesdev->strips_len);
|
||||||
FRAME_WIDTH, FRAME_HEIGHT, FRAME_WIDTH + FRAME_WIDTH / 2);
|
|
||||||
g_slist_free_full(aesdev->strips, g_free);
|
g_slist_free_full(aesdev->strips, g_free);
|
||||||
aesdev->strips = NULL;
|
aesdev->strips = NULL;
|
||||||
aesdev->strips_len = 0;
|
aesdev->strips_len = 0;
|
||||||
|
@ -843,7 +848,7 @@ struct fp_img_driver aes1610_driver = {
|
||||||
},
|
},
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.img_height = -1,
|
.img_height = -1,
|
||||||
.img_width = FRAME_WIDTH + FRAME_WIDTH / 2,
|
.img_width = IMAGE_WIDTH,
|
||||||
|
|
||||||
.bz3_threshold = 50,
|
.bz3_threshold = 50,
|
||||||
|
|
||||||
|
|
|
@ -28,12 +28,22 @@
|
||||||
|
|
||||||
#include <fp_internal.h>
|
#include <fp_internal.h>
|
||||||
|
|
||||||
|
#include <assembling.h>
|
||||||
|
#include <aeslib.h>
|
||||||
|
|
||||||
#include "aesx660.h"
|
#include "aesx660.h"
|
||||||
#include "aes1660.h"
|
#include "aes1660.h"
|
||||||
#include "driver_ids.h"
|
#include "driver_ids.h"
|
||||||
|
|
||||||
#define FRAME_WIDTH 128
|
#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)
|
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->init_seqs_len[1] = array_n_elements(aes1660_init_2);
|
||||||
aesdev->start_imaging_cmd = (unsigned char *)aes1660_start_imaging_cmd;
|
aesdev->start_imaging_cmd = (unsigned char *)aes1660_start_imaging_cmd;
|
||||||
aesdev->start_imaging_cmd_len = sizeof(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;
|
aesdev->extra_img_flags = FP_IMG_PARTIAL;
|
||||||
|
|
||||||
fpi_imgdev_open_complete(dev, 0);
|
fpi_imgdev_open_complete(dev, 0);
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
|
|
||||||
#include <libusb.h>
|
#include <libusb.h>
|
||||||
|
|
||||||
|
#include <assembling.h>
|
||||||
#include <aeslib.h>
|
#include <aeslib.h>
|
||||||
#include <fp_internal.h>
|
#include <fp_internal.h>
|
||||||
|
|
||||||
|
@ -58,6 +59,7 @@ static void complete_deactivation(struct fp_img_dev *dev);
|
||||||
#define FRAME_WIDTH 192
|
#define FRAME_WIDTH 192
|
||||||
#define FRAME_HEIGHT 16
|
#define FRAME_HEIGHT 16
|
||||||
#define FRAME_SIZE (FRAME_WIDTH * FRAME_HEIGHT)
|
#define FRAME_SIZE (FRAME_WIDTH * FRAME_HEIGHT)
|
||||||
|
#define IMAGE_WIDTH (FRAME_WIDTH + (FRAME_WIDTH / 2))
|
||||||
/* maximum number of frames to read during a scan */
|
/* maximum number of frames to read during a scan */
|
||||||
/* FIXME reduce substantially */
|
/* FIXME reduce substantially */
|
||||||
#define MAX_FRAMES 150
|
#define MAX_FRAMES 150
|
||||||
|
@ -72,6 +74,13 @@ struct aes2501_dev {
|
||||||
int no_finger_cnt;
|
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,
|
typedef void (*aes2501_read_regs_cb)(struct fp_img_dev *dev, int status,
|
||||||
unsigned char *regs, void *user_data);
|
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;
|
unsigned int height, rev_height;
|
||||||
|
|
||||||
aesdev->strips = g_slist_reverse(aesdev->strips);
|
aesdev->strips = g_slist_reverse(aesdev->strips);
|
||||||
height = aes_calc_delta(aesdev->strips, aesdev->strips_len,
|
height = fpi_do_movement_estimation(&assembling_ctx,
|
||||||
FRAME_WIDTH, FRAME_HEIGHT, FALSE);
|
aesdev->strips, aesdev->strips_len, FALSE);
|
||||||
rev_height = aes_calc_delta(aesdev->strips, aesdev->strips_len,
|
rev_height = fpi_do_movement_estimation(&assembling_ctx,
|
||||||
FRAME_WIDTH, FRAME_HEIGHT, TRUE);
|
aesdev->strips, aesdev->strips_len, TRUE);
|
||||||
fp_dbg("heights: %d rev: %d", height, rev_height);
|
fp_dbg("heights: %d rev: %d", height, rev_height);
|
||||||
if (rev_height < height) {
|
if (rev_height < height) {
|
||||||
fp_dbg("Reversed direction");
|
fp_dbg("Reversed direction");
|
||||||
height = aes_calc_delta(aesdev->strips, aesdev->strips_len,
|
height = fpi_do_movement_estimation(&assembling_ctx,
|
||||||
FRAME_WIDTH, FRAME_HEIGHT, FALSE);
|
aesdev->strips, aesdev->strips_len, FALSE);
|
||||||
}
|
}
|
||||||
img = aes_assemble(aesdev->strips, aesdev->strips_len,
|
img = fpi_assemble_frames(&assembling_ctx,
|
||||||
FRAME_WIDTH, FRAME_HEIGHT, FRAME_WIDTH + FRAME_WIDTH / 2);
|
aesdev->strips, aesdev->strips_len);
|
||||||
g_slist_free_full(aesdev->strips, g_free);
|
g_slist_free_full(aesdev->strips, g_free);
|
||||||
aesdev->strips = NULL;
|
aesdev->strips = NULL;
|
||||||
aesdev->strips_len = 0;
|
aesdev->strips_len = 0;
|
||||||
|
@ -509,7 +518,7 @@ static void capture_read_strip_cb(struct libusb_transfer *transfer)
|
||||||
} else {
|
} 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 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_x = 0;
|
||||||
stripe->delta_y = 0;
|
stripe->delta_y = 0;
|
||||||
stripdata = stripe->data;
|
stripdata = stripe->data;
|
||||||
|
@ -881,7 +890,7 @@ struct fp_img_driver aes2501_driver = {
|
||||||
},
|
},
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.img_height = -1,
|
.img_height = -1,
|
||||||
.img_width = FRAME_WIDTH + FRAME_WIDTH / 2,
|
.img_width = IMAGE_WIDTH,
|
||||||
|
|
||||||
.open = dev_init,
|
.open = dev_init,
|
||||||
.close = dev_deinit,
|
.close = dev_deinit,
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
|
|
||||||
#include <libusb.h>
|
#include <libusb.h>
|
||||||
|
|
||||||
|
#include <assembling.h>
|
||||||
#include <aeslib.h>
|
#include <aeslib.h>
|
||||||
#include <fp_internal.h>
|
#include <fp_internal.h>
|
||||||
|
|
||||||
|
@ -56,6 +57,7 @@ static void complete_deactivation(struct fp_img_dev *dev);
|
||||||
#define FRAME_WIDTH 192
|
#define FRAME_WIDTH 192
|
||||||
#define FRAME_HEIGHT 8
|
#define FRAME_HEIGHT 8
|
||||||
#define FRAME_SIZE (FRAME_WIDTH * FRAME_HEIGHT)
|
#define FRAME_SIZE (FRAME_WIDTH * FRAME_HEIGHT)
|
||||||
|
#define IMAGE_WIDTH (FRAME_WIDTH + (FRAME_WIDTH / 2))
|
||||||
|
|
||||||
struct aes2550_dev {
|
struct aes2550_dev {
|
||||||
GSList *strips;
|
GSList *strips;
|
||||||
|
@ -64,6 +66,13 @@ struct aes2550_dev {
|
||||||
int heartbeat_cnt;
|
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 ******/
|
/****** FINGER PRESENCE DETECTION ******/
|
||||||
|
|
||||||
static unsigned char finger_det_reqs[] = {
|
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;
|
unsigned char *stripdata;
|
||||||
struct fp_img_dev *dev = ssm->priv;
|
struct fp_img_dev *dev = ssm->priv;
|
||||||
struct aes2550_dev *aesdev = dev->priv;
|
struct aes2550_dev *aesdev = dev->priv;
|
||||||
struct aes_stripe *stripe;
|
struct fpi_frame *stripe;
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
if (data[0] != AES2550_EDATA_MAGIC) {
|
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)) {
|
if (len != (AES2550_STRIP_SIZE - 3)) {
|
||||||
fp_dbg("Bogus frame len: %.4x\n", len);
|
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_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;
|
||||||
|
@ -253,8 +262,8 @@ static void capture_set_idle_reqs_cb(struct libusb_transfer *transfer)
|
||||||
struct fp_img *img;
|
struct fp_img *img;
|
||||||
|
|
||||||
aesdev->strips = g_slist_reverse(aesdev->strips);
|
aesdev->strips = g_slist_reverse(aesdev->strips);
|
||||||
img = aes_assemble(aesdev->strips, aesdev->strips_len,
|
img = fpi_assemble_frames(&assembling_ctx,
|
||||||
FRAME_WIDTH, FRAME_HEIGHT, FRAME_WIDTH + FRAME_WIDTH / 2);
|
aesdev->strips, aesdev->strips_len);
|
||||||
g_slist_free_full(aesdev->strips, g_free);
|
g_slist_free_full(aesdev->strips, g_free);
|
||||||
aesdev->strips = NULL;
|
aesdev->strips = NULL;
|
||||||
aesdev->strips_len = 0;
|
aesdev->strips_len = 0;
|
||||||
|
|
|
@ -28,11 +28,22 @@
|
||||||
|
|
||||||
#include <fp_internal.h>
|
#include <fp_internal.h>
|
||||||
|
|
||||||
|
#include <assembling.h>
|
||||||
|
#include <aeslib.h>
|
||||||
|
|
||||||
#include "aesx660.h"
|
#include "aesx660.h"
|
||||||
#include "aes2660.h"
|
#include "aes2660.h"
|
||||||
#include "driver_ids.h"
|
#include "driver_ids.h"
|
||||||
|
|
||||||
#define FRAME_WIDTH 192
|
#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)
|
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->init_seqs_len[1] = array_n_elements(aes2660_init_2);
|
||||||
aesdev->start_imaging_cmd = (unsigned char *)aes2660_start_imaging_cmd;
|
aesdev->start_imaging_cmd = (unsigned char *)aes2660_start_imaging_cmd;
|
||||||
aesdev->start_imaging_cmd_len = sizeof(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);
|
fpi_imgdev_open_complete(dev, 0);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
|
|
||||||
#include <libusb.h>
|
#include <libusb.h>
|
||||||
|
|
||||||
|
#include <assembling.h>
|
||||||
#include <aeslib.h>
|
#include <aeslib.h>
|
||||||
#include <fp_internal.h>
|
#include <fp_internal.h>
|
||||||
|
|
||||||
|
@ -41,7 +42,7 @@ static void complete_deactivation(struct fp_img_dev *dev);
|
||||||
#define EP_IN (1 | LIBUSB_ENDPOINT_IN)
|
#define EP_IN (1 | LIBUSB_ENDPOINT_IN)
|
||||||
#define EP_OUT (2 | LIBUSB_ENDPOINT_OUT)
|
#define EP_OUT (2 | LIBUSB_ENDPOINT_OUT)
|
||||||
#define BULK_TIMEOUT 4000
|
#define BULK_TIMEOUT 4000
|
||||||
#define FRAME_HEIGHT 8
|
#define FRAME_HEIGHT AESX660_FRAME_HEIGHT
|
||||||
|
|
||||||
#define min(a, b) (((a) < (b)) ? (a) : (b))
|
#define min(a, b) (((a) < (b)) ? (a) : (b))
|
||||||
|
|
||||||
|
@ -273,12 +274,12 @@ enum capture_states {
|
||||||
/* Returns number of processed bytes */
|
/* Returns number of processed bytes */
|
||||||
static int process_stripe_data(struct fpi_ssm *ssm, unsigned char *data)
|
static int process_stripe_data(struct fpi_ssm *ssm, unsigned char *data)
|
||||||
{
|
{
|
||||||
struct aes_stripe *stripe;
|
struct fpi_frame *stripe;
|
||||||
unsigned char *stripdata;
|
unsigned char *stripdata;
|
||||||
struct fp_img_dev *dev = ssm->priv;
|
struct fp_img_dev *dev = ssm->priv;
|
||||||
struct aesX660_dev *aesdev = dev->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;
|
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],
|
||||||
|
@ -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);
|
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, 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 = g_slist_prepend(aesdev->strips, stripe);
|
||||||
aesdev->strips_len++;
|
aesdev->strips_len++;
|
||||||
|
@ -311,8 +312,7 @@ static void capture_set_idle_cmd_cb(struct libusb_transfer *transfer)
|
||||||
struct fp_img *img;
|
struct fp_img *img;
|
||||||
|
|
||||||
aesdev->strips = g_slist_reverse(aesdev->strips);
|
aesdev->strips = g_slist_reverse(aesdev->strips);
|
||||||
img = aes_assemble(aesdev->strips, aesdev->strips_len,
|
img = fpi_assemble_frames(aesdev->assembling_ctx, aesdev->strips, aesdev->strips_len);
|
||||||
aesdev->frame_width, FRAME_HEIGHT, aesdev->frame_width + aesdev->frame_width / 2);
|
|
||||||
img->flags |= aesdev->extra_img_flags;
|
img->flags |= aesdev->extra_img_flags;
|
||||||
g_slist_foreach(aesdev->strips, (GFunc) g_free, NULL);
|
g_slist_foreach(aesdev->strips, (GFunc) g_free, NULL);
|
||||||
g_slist_free(aesdev->strips);
|
g_slist_free(aesdev->strips);
|
||||||
|
|
|
@ -41,6 +41,8 @@
|
||||||
#define AESX660_IMAGE_OFFSET 43
|
#define AESX660_IMAGE_OFFSET 43
|
||||||
#define AESX660_BULK_TRANSFER_SIZE 4096
|
#define AESX660_BULK_TRANSFER_SIZE 4096
|
||||||
|
|
||||||
|
#define AESX660_FRAME_HEIGHT 8
|
||||||
|
|
||||||
struct aesX660_dev {
|
struct aesX660_dev {
|
||||||
GSList *strips;
|
GSList *strips;
|
||||||
size_t strips_len;
|
size_t strips_len;
|
||||||
|
@ -55,12 +57,11 @@ struct aesX660_dev {
|
||||||
size_t buffer_max;
|
size_t buffer_max;
|
||||||
|
|
||||||
/* Device-specific stuff */
|
/* Device-specific stuff */
|
||||||
int h_scale_factor;
|
|
||||||
struct aesX660_cmd *init_seqs[2];
|
struct aesX660_cmd *init_seqs[2];
|
||||||
size_t init_seqs_len[2];
|
size_t init_seqs_len[2];
|
||||||
unsigned char *start_imaging_cmd;
|
unsigned char *start_imaging_cmd;
|
||||||
size_t start_imaging_cmd_len;
|
size_t start_imaging_cmd_len;
|
||||||
unsigned int frame_width;
|
struct fpi_frame_asmbl_ctx *assembling_ctx;
|
||||||
uint16_t extra_img_flags;
|
uint16_t extra_img_flags;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue