mirror of
https://gitlab.freedesktop.org/libfprint/libfprint.git
synced 2025-11-15 07:38:12 +00:00
Compare commits
1 Commits
wip/hadess
...
benzea/fix
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
400cacf867 |
25
HACKING.md
25
HACKING.md
@@ -3,29 +3,8 @@
|
|||||||
## GLib
|
## GLib
|
||||||
|
|
||||||
Although the library uses GLib internally, libfprint is designed to provide
|
Although the library uses GLib internally, libfprint is designed to provide
|
||||||
a completely neutral interface to its application users. So, the public
|
a completely neutral interface to it's application users. So, the public
|
||||||
APIs should never return GLib data types.
|
APIs should never return GLib data types or anything like that.
|
||||||
|
|
||||||
## License clarification
|
|
||||||
|
|
||||||
Although this library's license could allow for shims that hook up into
|
|
||||||
proprietary blobs to add driver support for some unsupported devices, the
|
|
||||||
intent of the original authors, and of current maintainers of the library,
|
|
||||||
was for this license to allow _integration into_ proprietary stacks, not
|
|
||||||
_integration of_ proprietary code in the library.
|
|
||||||
|
|
||||||
As such, no code to integrate proprietary drivers will be accepted in libfprint
|
|
||||||
upstream. Proprietary drivers would make it impossible to debug problems in
|
|
||||||
libfprint, as we wouldn't know what the proprietary driver does behind the
|
|
||||||
library's back. The closed source nature of drivers is usually used to hide
|
|
||||||
parts of the hardware setup, such as encryption keys, or protocols, in order
|
|
||||||
to protect the hardware's integrity. Unfortunately, this is only [security through
|
|
||||||
obscurity](https://en.wikipedia.org/wiki/Security_through_obscurity).
|
|
||||||
|
|
||||||
We however encourage potential contributors to take advantage of libfprint's
|
|
||||||
source availability to create such shims to make it easier to reverse-engineer
|
|
||||||
proprietary drivers in order to create new free software drivers, to the extent
|
|
||||||
permitted by local laws.
|
|
||||||
|
|
||||||
## Two-faced-ness
|
## Two-faced-ness
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +0,0 @@
|
|||||||
This project and its community follow the [Freedesktop.org code of conduct]
|
|
||||||
|
|
||||||
[Freedesktop.org code of conduct]: https://www.freedesktop.org/wiki/CodeOfConduct/
|
|
||||||
@@ -404,7 +404,7 @@ static unsigned char list_BD_values[10] = {
|
|||||||
/*
|
/*
|
||||||
* Adjust the gain according to the histogram data
|
* Adjust the gain according to the histogram data
|
||||||
* 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 occured
|
||||||
* 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)
|
||||||
{
|
{
|
||||||
@@ -412,7 +412,7 @@ static int adjust_gain(unsigned char *buffer, int status)
|
|||||||
static int pos_list_BE = 0;
|
static int pos_list_BE = 0;
|
||||||
static int pos_list_BD = 0;
|
static int pos_list_BD = 0;
|
||||||
|
|
||||||
// This is the first adjustment (we begin acquisition)
|
// This is the first adjustement (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
|
||||||
@@ -534,7 +534,7 @@ static void restore_gain(void)
|
|||||||
|
|
||||||
/* capture SM movement:
|
/* capture SM movement:
|
||||||
* request and read strip,
|
* request and read strip,
|
||||||
* jump back to request UNLESS there's no finger, in which case exit SM,
|
* jump back to request UNLESS theres no finger, in which case exit SM,
|
||||||
* report lack of finger presence, and move to finger detection */
|
* report lack of finger presence, and move to finger detection */
|
||||||
|
|
||||||
enum capture_states {
|
enum capture_states {
|
||||||
@@ -611,8 +611,8 @@ 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);
|
||||||
fpi_do_movement_estimation(&assembling_ctx, aesdev->strips);
|
fpi_do_movement_estimation(&assembling_ctx, aesdev->strips, aesdev->strips_len);
|
||||||
img = fpi_assemble_frames(&assembling_ctx, aesdev->strips);
|
img = fpi_assemble_frames(&assembling_ctx, aesdev->strips, aesdev->strips_len);
|
||||||
img->flags |= FP_IMG_PARTIAL;
|
img->flags |= FP_IMG_PARTIAL;
|
||||||
g_slist_free_full(aesdev->strips, g_free);
|
g_slist_free_full(aesdev->strips, g_free);
|
||||||
aesdev->strips = NULL;
|
aesdev->strips = NULL;
|
||||||
@@ -728,7 +728,7 @@ static void activate_run_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_dat
|
|||||||
struct fp_img_dev *dev = user_data;
|
struct fp_img_dev *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 theres 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");
|
||||||
|
|||||||
@@ -415,7 +415,7 @@ static struct aes_regwrite strip_scan_reqs[] = {
|
|||||||
/* capture SM movement:
|
/* capture SM movement:
|
||||||
* write reqs and read data 1 + 2,
|
* write reqs and read data 1 + 2,
|
||||||
* request and read strip,
|
* request and read strip,
|
||||||
* jump back to request UNLESS there's no finger, in which case exit SM,
|
* jump back to request UNLESS theres no finger, in which case exit SM,
|
||||||
* report lack of finger presence, and move to finger detection */
|
* report lack of finger presence, and move to finger detection */
|
||||||
|
|
||||||
enum capture_states {
|
enum capture_states {
|
||||||
@@ -482,8 +482,10 @@ static void capture_read_strip_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);
|
||||||
fpi_do_movement_estimation(&assembling_ctx, aesdev->strips);
|
fpi_do_movement_estimation(&assembling_ctx,
|
||||||
img = fpi_assemble_frames(&assembling_ctx, aesdev->strips);
|
aesdev->strips, aesdev->strips_len);
|
||||||
|
img = fpi_assemble_frames(&assembling_ctx,
|
||||||
|
aesdev->strips, aesdev->strips_len);
|
||||||
img->flags |= FP_IMG_PARTIAL;
|
img->flags |= FP_IMG_PARTIAL;
|
||||||
g_slist_free_full(aesdev->strips, g_free);
|
g_slist_free_full(aesdev->strips, g_free);
|
||||||
aesdev->strips = NULL;
|
aesdev->strips = NULL;
|
||||||
|
|||||||
@@ -109,7 +109,7 @@ enum aes2501_mesure_drive {
|
|||||||
|
|
||||||
/* Select (1=square | 0=sine) wave drive during measure */
|
/* Select (1=square | 0=sine) wave drive during measure */
|
||||||
#define AES2501_MEASDRV_SQUARE 0x20
|
#define AES2501_MEASDRV_SQUARE 0x20
|
||||||
/* 0 = use measure drive setting, 1 = when sine wave is selected */
|
/* 0 = use mesure drive setting, 1 = when sine wave is selected */
|
||||||
#define AES2501_MEASDRV_MEASURE_SQUARE 0x10
|
#define AES2501_MEASDRV_MEASURE_SQUARE 0x10
|
||||||
|
|
||||||
enum aes2501_measure_freq {
|
enum aes2501_measure_freq {
|
||||||
|
|||||||
@@ -244,7 +244,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 = fpi_assemble_frames(&assembling_ctx, aesdev->strips);
|
img = fpi_assemble_frames(&assembling_ctx,
|
||||||
|
aesdev->strips, aesdev->strips_len);
|
||||||
img->flags |= FP_IMG_PARTIAL;
|
img->flags |= FP_IMG_PARTIAL;
|
||||||
g_slist_free_full(aesdev->strips, g_free);
|
g_slist_free_full(aesdev->strips, g_free);
|
||||||
aesdev->strips = NULL;
|
aesdev->strips = NULL;
|
||||||
@@ -446,7 +447,7 @@ static void init_read_data_cb(struct libusb_transfer *transfer)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* 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 implementaion */
|
||||||
static void calibrate_read_data_cb(struct libusb_transfer *transfer)
|
static void calibrate_read_data_cb(struct libusb_transfer *transfer)
|
||||||
{
|
{
|
||||||
fpi_ssm *ssm = transfer->user_data;
|
fpi_ssm *ssm = transfer->user_data;
|
||||||
|
|||||||
@@ -305,7 +305,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 = fpi_assemble_frames(aesdev->assembling_ctx, aesdev->strips);
|
img = fpi_assemble_frames(aesdev->assembling_ctx, aesdev->strips, aesdev->strips_len);
|
||||||
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);
|
||||||
|
|||||||
@@ -293,22 +293,24 @@ static void elan_process_frame_thirds(unsigned short *raw_frame,
|
|||||||
static void elan_submit_image(struct fp_img_dev *dev)
|
static void elan_submit_image(struct fp_img_dev *dev)
|
||||||
{
|
{
|
||||||
struct elan_dev *elandev = FP_INSTANCE_DATA(FP_DEV(dev));
|
struct elan_dev *elandev = FP_INSTANCE_DATA(FP_DEV(dev));
|
||||||
int num_frames;
|
GSList *input_frames;
|
||||||
GSList *raw_frames;
|
|
||||||
GSList *frames = NULL;
|
GSList *frames = NULL;
|
||||||
struct fp_img *img;
|
struct fp_img *img;
|
||||||
|
|
||||||
G_DEBUG_HERE();
|
G_DEBUG_HERE();
|
||||||
|
|
||||||
num_frames = elandev->num_frames - ELAN_SKIP_LAST_FRAMES;
|
input_frames = elandev->frames;
|
||||||
raw_frames = g_slist_nth(elandev->frames, ELAN_SKIP_LAST_FRAMES);
|
for (int i = 0; i < ELAN_SKIP_LAST_FRAMES; i++)
|
||||||
|
input_frames = g_slist_next (input_frames);
|
||||||
|
|
||||||
assembling_ctx.frame_width = elandev->frame_width;
|
assembling_ctx.frame_width = elandev->frame_width;
|
||||||
assembling_ctx.frame_height = elandev->frame_height;
|
assembling_ctx.frame_height = elandev->frame_height;
|
||||||
assembling_ctx.image_width = elandev->frame_width * 3 / 2;
|
assembling_ctx.image_width = elandev->frame_width * 3 / 2;
|
||||||
g_slist_foreach(raw_frames, (GFunc) elandev->process_frame, &frames);
|
g_slist_foreach(input_frames, (GFunc) elandev->process_frame,
|
||||||
fpi_do_movement_estimation(&assembling_ctx, frames);
|
&frames);
|
||||||
img = fpi_assemble_frames(&assembling_ctx, frames);
|
fpi_do_movement_estimation(&assembling_ctx, frames,
|
||||||
|
elandev->num_frames);
|
||||||
|
img = fpi_assemble_frames(&assembling_ctx, frames, elandev->num_frames - ELAN_SKIP_LAST_FRAMES);
|
||||||
|
|
||||||
img->flags |= FP_IMG_PARTIAL;
|
img->flags |= FP_IMG_PARTIAL;
|
||||||
fpi_imgdev_image_captured(dev, img);
|
fpi_imgdev_image_captured(dev, img);
|
||||||
|
|||||||
@@ -1316,7 +1316,7 @@ static void m_init_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
|
|||||||
fpi_ssm_next_state(ssm);
|
fpi_ssm_next_state(ssm);
|
||||||
break;
|
break;
|
||||||
case INIT_SENSOR_REQ:
|
case INIT_SENSOR_REQ:
|
||||||
/* In captured traffic, those are split. */
|
/* In captured traffic, those are splitted. */
|
||||||
msg_set_regs(dev, 18, REG_MODE_CONTROL, REG_MODE_SLEEP,
|
msg_set_regs(dev, 18, REG_MODE_CONTROL, REG_MODE_SLEEP,
|
||||||
REG_50, 0x0F, REG_GAIN, 0x04, REG_VRT, 0x08,
|
REG_50, 0x0F, REG_GAIN, 0x04, REG_VRT, 0x08,
|
||||||
REG_VRB, 0x0D, REG_VCO_CONTROL, REG_VCO_RT,
|
REG_VRB, 0x0D, REG_VCO_CONTROL, REG_VCO_RT,
|
||||||
|
|||||||
@@ -136,7 +136,7 @@ static unsigned char upeksonly_get_pixel(struct fpi_line_asmbl_ctx *ctx,
|
|||||||
unsigned char *buf;
|
unsigned char *buf;
|
||||||
unsigned offset;
|
unsigned offset;
|
||||||
|
|
||||||
/* The scans from this device are rolled right by two columns */
|
/* The scans from this device are rolled right by two colums */
|
||||||
if (x < ctx->line_width - 2)
|
if (x < ctx->line_width - 2)
|
||||||
offset = x + 2;
|
offset = x + 2;
|
||||||
else if ((x > ctx->line_width - 2) && (x < ctx->line_width))
|
else if ((x > ctx->line_width - 2) && (x < ctx->line_width))
|
||||||
@@ -296,12 +296,12 @@ static void row_complete(struct fp_img_dev *dev)
|
|||||||
sdev->num_blank = 0;
|
sdev->num_blank = 0;
|
||||||
} else {
|
} else {
|
||||||
sdev->num_blank++;
|
sdev->num_blank++;
|
||||||
/* Don't consider the scan complete unless there's at least
|
/* Don't consider the scan complete unless theres at least
|
||||||
* MIN_ROWS recorded or very long blank read occurred.
|
* MIN_ROWS recorded or very long blank read occurred.
|
||||||
*
|
*
|
||||||
* Typical problem spot: one brief touch before starting the
|
* Typical problem spot: one brief touch before starting the
|
||||||
* actual scan. Happens most commonly if scan is started
|
* actual scan. Happens most commonly if scan is started
|
||||||
* from before the first joint resulting in a gap after the initial touch.
|
* from before the first joint resulting in a gap after the inital touch.
|
||||||
*/
|
*/
|
||||||
if (sdev->num_blank > FINGER_REMOVED_THRESHOLD) {
|
if (sdev->num_blank > FINGER_REMOVED_THRESHOLD) {
|
||||||
sdev->finger_state = FINGER_REMOVED;
|
sdev->finger_state = FINGER_REMOVED;
|
||||||
|
|||||||
@@ -287,7 +287,7 @@ static void capture_read_data_cb(struct libusb_transfer *transfer)
|
|||||||
fpi_ssm_mark_completed(ssm);
|
fpi_ssm_mark_completed(ssm);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
fp_err("Unknown response!\n");
|
fp_err("Uknown response!\n");
|
||||||
fpi_ssm_mark_failed(ssm, -EIO);
|
fpi_ssm_mark_failed(ssm, -EIO);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -668,7 +668,7 @@ static uint32_t do_decode(uint8_t *data, int num_bytes, uint32_t key)
|
|||||||
data[i] = data[i+1] ^ xorbyte;
|
data[i] = data[i+1] ^ xorbyte;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* the final byte is implicitly zero */
|
/* the final byte is implictly zero */
|
||||||
data[i] = 0;
|
data[i] = 0;
|
||||||
return update_key(key);
|
return update_key(key);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -577,7 +577,7 @@ static void activate_ssm(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
|
|||||||
vdev->need_report = 0;
|
vdev->need_report = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Asynchronously enquire an interrupt */
|
/* Asyncronously enquire an interrupt */
|
||||||
vdev->transfer = fpi_usb_alloc();
|
vdev->transfer = fpi_usb_alloc();
|
||||||
vdev->transfer->flags |= LIBUSB_TRANSFER_FREE_TRANSFER;
|
vdev->transfer->flags |= LIBUSB_TRANSFER_FREE_TRANSFER;
|
||||||
libusb_fill_interrupt_transfer(vdev->transfer, usb_dev, 0x83,
|
libusb_fill_interrupt_transfer(vdev->transfer, usb_dev, 0x83,
|
||||||
|
|||||||
@@ -47,7 +47,7 @@
|
|||||||
/* Minimum image height */
|
/* Minimum image height */
|
||||||
#define VFS_IMG_MIN_HEIGHT 200
|
#define VFS_IMG_MIN_HEIGHT 200
|
||||||
|
|
||||||
/* Scan level threshold */
|
/* Scan level thresold */
|
||||||
#define VFS_IMG_SLT_BEGIN 768
|
#define VFS_IMG_SLT_BEGIN 768
|
||||||
#define VFS_IMG_SLT_END 64
|
#define VFS_IMG_SLT_END 64
|
||||||
#define VFS_IMG_SLT_LINES 4
|
#define VFS_IMG_SLT_LINES 4
|
||||||
@@ -641,7 +641,7 @@ static int action_completed(struct fp_img_dev *dev)
|
|||||||
|
|
||||||
#define offset(x, y) ((x) + ((y) * VFS_FRAME_SIZE))
|
#define offset(x, y) ((x) + ((y) * VFS_FRAME_SIZE))
|
||||||
|
|
||||||
/* Screen image to remove noise and find bottom line and height of image */
|
/* Screen image to remove noise and find bottom line and height od image */
|
||||||
static void img_screen(struct vfs101_dev *vdev)
|
static void img_screen(struct vfs101_dev *vdev)
|
||||||
{
|
{
|
||||||
int y, x, count, top;
|
int y, x, count, top;
|
||||||
@@ -654,7 +654,7 @@ static void img_screen(struct vfs101_dev *vdev)
|
|||||||
|
|
||||||
/* Image returned from sensor can contain many empty lines,
|
/* Image returned from sensor can contain many empty lines,
|
||||||
* for remove these lines compare byte 282-283 (scan level information)
|
* for remove these lines compare byte 282-283 (scan level information)
|
||||||
* with two different thresholds, one for the begin of finger image and
|
* with two differents threshold, one for the begin of finger image and
|
||||||
* one for the end. To increase stability of the code use a counter
|
* one for the end. To increase stability of the code use a counter
|
||||||
* of lines that satisfy the threshold.
|
* of lines that satisfy the threshold.
|
||||||
*/
|
*/
|
||||||
@@ -700,7 +700,7 @@ static void img_screen(struct vfs101_dev *vdev)
|
|||||||
|
|
||||||
vdev->height = top - vdev->bottom + 1;
|
vdev->height = top - vdev->bottom + 1;
|
||||||
|
|
||||||
/* Check max height */
|
/* Checkk max height */
|
||||||
if (vdev->height > VFS_IMG_MAX_HEIGHT)
|
if (vdev->height > VFS_IMG_MAX_HEIGHT)
|
||||||
vdev->height = VFS_IMG_MAX_HEIGHT;
|
vdev->height = VFS_IMG_MAX_HEIGHT;
|
||||||
|
|
||||||
@@ -1178,7 +1178,7 @@ static void m_init_state(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
|
|||||||
switch (fpi_ssm_get_cur_state(ssm))
|
switch (fpi_ssm_get_cur_state(ssm))
|
||||||
{
|
{
|
||||||
case M_INIT_0_RECV_DIRTY:
|
case M_INIT_0_RECV_DIRTY:
|
||||||
/* Recv eventually dirty data */
|
/* Recv eventualy dirty data */
|
||||||
vdev->ignore_error = TRUE;
|
vdev->ignore_error = TRUE;
|
||||||
async_recv(ssm, dev);
|
async_recv(ssm, dev);
|
||||||
break;
|
break;
|
||||||
@@ -1463,7 +1463,7 @@ static void dev_deactivate(struct fp_img_dev *dev)
|
|||||||
/* Reset active state */
|
/* Reset active state */
|
||||||
vdev->active = FALSE;
|
vdev->active = FALSE;
|
||||||
|
|
||||||
/* Handle eventually existing events */
|
/* Handle eventualy existing events */
|
||||||
while (vdev->transfer)
|
while (vdev->transfer)
|
||||||
fp_handle_events();
|
fp_handle_events();
|
||||||
|
|
||||||
|
|||||||
@@ -109,7 +109,7 @@ typedef struct {
|
|||||||
|
|
||||||
unsigned char scan[VFS301_FP_WIDTH];
|
unsigned char scan[VFS301_FP_WIDTH];
|
||||||
|
|
||||||
/* A offsetted, stretched, inverted copy of scan... probably could
|
/* A offseted, stretched, inverted copy of scan... probably could
|
||||||
* serve finger motion speed detection?
|
* serve finger motion speed detection?
|
||||||
* Seems to be subdivided to some 10B + 53B + 1B blocks */
|
* Seems to be subdivided to some 10B + 53B + 1B blocks */
|
||||||
unsigned char mirror[64];
|
unsigned char mirror[64];
|
||||||
|
|||||||
@@ -1147,7 +1147,7 @@ static const unsigned char vfs301_24[] = { /* 119 B */
|
|||||||
*
|
*
|
||||||
* The contents of PACKET() inside this blob seems to be some kind
|
* The contents of PACKET() inside this blob seems to be some kind
|
||||||
* of a micro-program, which specifies which columns contain what. LE seems
|
* of a micro-program, which specifies which columns contain what. LE seems
|
||||||
* to be used also here. Not necessarily is 1 output column described
|
* to be used also here. Not neccessarily is 1 output column described
|
||||||
* by 1 operation. For example the vfs301_line_t::sum section seems
|
* by 1 operation. For example the vfs301_line_t::sum section seems
|
||||||
* to perform 2 operations for each column - probably some kind of diff between
|
* to perform 2 operations for each column - probably some kind of diff between
|
||||||
* input lines?
|
* input lines?
|
||||||
|
|||||||
@@ -405,7 +405,7 @@ submit_image(fpi_ssm *ssm,
|
|||||||
g_slist_free_full(data->rows, g_free);
|
g_slist_free_full(data->rows, g_free);
|
||||||
data->rows = NULL;
|
data->rows = NULL;
|
||||||
|
|
||||||
fp_dbg("Image captured, committing");
|
fp_dbg("Image captured, commiting");
|
||||||
|
|
||||||
fpi_imgdev_image_captured(dev, img);
|
fpi_imgdev_image_captured(dev, img);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -121,12 +121,13 @@ static void find_overlap(struct fpi_frame_asmbl_ctx *ctx,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static unsigned int do_movement_estimation(struct fpi_frame_asmbl_ctx *ctx,
|
static unsigned int do_movement_estimation(struct fpi_frame_asmbl_ctx *ctx,
|
||||||
GSList *stripes, gboolean reverse)
|
GSList *stripes, size_t num_stripes,
|
||||||
|
gboolean reverse)
|
||||||
{
|
{
|
||||||
GSList *l;
|
GSList *list_entry = stripes;
|
||||||
GTimer *timer;
|
GTimer *timer;
|
||||||
guint num_frames = 0;
|
int frame = 1;
|
||||||
struct fpi_frame *prev_stripe;
|
struct fpi_frame *prev_stripe = list_entry->data;
|
||||||
unsigned int min_error;
|
unsigned int min_error;
|
||||||
/* Max error is width * height * 255, for AES2501 which has the largest
|
/* Max error is width * height * 255, for AES2501 which has the largest
|
||||||
* sensor its 192*16*255 = 783360. So for 32bit value it's ~5482 frame before
|
* sensor its 192*16*255 = 783360. So for 32bit value it's ~5482 frame before
|
||||||
@@ -134,34 +135,39 @@ static unsigned int do_movement_estimation(struct fpi_frame_asmbl_ctx *ctx,
|
|||||||
*/
|
*/
|
||||||
unsigned long long total_error = 0;
|
unsigned long long total_error = 0;
|
||||||
|
|
||||||
|
list_entry = g_slist_next(list_entry);
|
||||||
|
|
||||||
timer = g_timer_new();
|
timer = g_timer_new();
|
||||||
prev_stripe = stripes->data;
|
do {
|
||||||
for (l = stripes; l != NULL; l = l->next, num_frames++) {
|
struct fpi_frame *cur_stripe = list_entry->data;
|
||||||
struct fpi_frame *cur_stripe = l->data;
|
|
||||||
|
|
||||||
if (reverse) {
|
if (reverse) {
|
||||||
find_overlap(ctx, prev_stripe, cur_stripe, &min_error);
|
find_overlap(ctx, prev_stripe, cur_stripe, &min_error);
|
||||||
cur_stripe->delta_y = -cur_stripe->delta_y;
|
cur_stripe->delta_y = -cur_stripe->delta_y;
|
||||||
cur_stripe->delta_x = -cur_stripe->delta_x;
|
cur_stripe->delta_x = -cur_stripe->delta_x;
|
||||||
} else {
|
|
||||||
find_overlap(ctx, cur_stripe, prev_stripe, &min_error);
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
find_overlap(ctx, cur_stripe, prev_stripe, &min_error);
|
||||||
total_error += min_error;
|
total_error += min_error;
|
||||||
|
|
||||||
|
frame++;
|
||||||
prev_stripe = cur_stripe;
|
prev_stripe = cur_stripe;
|
||||||
}
|
list_entry = g_slist_next(list_entry);
|
||||||
|
|
||||||
|
} while (frame < num_stripes);
|
||||||
|
|
||||||
g_timer_stop(timer);
|
g_timer_stop(timer);
|
||||||
fp_dbg("calc delta completed in %f secs", g_timer_elapsed(timer, NULL));
|
fp_dbg("calc delta completed in %f secs", g_timer_elapsed(timer, NULL));
|
||||||
g_timer_destroy(timer);
|
g_timer_destroy(timer);
|
||||||
|
|
||||||
return total_error / num_frames;
|
return total_error / num_stripes;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* fpi_do_movement_estimation:
|
* fpi_do_movement_estimation:
|
||||||
* @ctx: #fpi_frame_asmbl_ctx - frame assembling context
|
* @ctx: #fpi_frame_asmbl_ctx - frame assembling context
|
||||||
* @stripes: a singly-linked list of #fpi_frame
|
* @stripes: a singly-linked list of #fpi_frame
|
||||||
|
* @num_stripes: number of items in @stripes to process
|
||||||
*
|
*
|
||||||
* fpi_do_movement_estimation() estimates the movement between adjacent
|
* fpi_do_movement_estimation() estimates the movement between adjacent
|
||||||
* frames, populating @delta_x and @delta_y values for each #fpi_frame.
|
* frames, populating @delta_x and @delta_y values for each #fpi_frame.
|
||||||
@@ -169,17 +175,19 @@ static unsigned int do_movement_estimation(struct fpi_frame_asmbl_ctx *ctx,
|
|||||||
* This function is used for devices that don't do movement estimation
|
* This function is used for devices that don't do movement estimation
|
||||||
* in hardware. If hardware movement estimation is supported, the driver
|
* in hardware. If hardware movement estimation is supported, the driver
|
||||||
* should populate @delta_x and @delta_y instead.
|
* should populate @delta_x and @delta_y instead.
|
||||||
|
*
|
||||||
|
* Note that @num_stripes might be shorter than the length of the list,
|
||||||
|
* if some stripes should be skipped.
|
||||||
*/
|
*/
|
||||||
void fpi_do_movement_estimation(struct fpi_frame_asmbl_ctx *ctx,
|
void fpi_do_movement_estimation(struct fpi_frame_asmbl_ctx *ctx,
|
||||||
GSList *stripes)
|
GSList *stripes, size_t num_stripes)
|
||||||
{
|
{
|
||||||
int err, rev_err;
|
int err, rev_err;
|
||||||
|
err = do_movement_estimation(ctx, stripes, num_stripes, FALSE);
|
||||||
err = do_movement_estimation(ctx, stripes, FALSE);
|
rev_err = do_movement_estimation(ctx, stripes, num_stripes, TRUE);
|
||||||
rev_err = do_movement_estimation(ctx, stripes, TRUE);
|
|
||||||
fp_dbg("errors: %d rev: %d", err, rev_err);
|
fp_dbg("errors: %d rev: %d", err, rev_err);
|
||||||
if (err < rev_err) {
|
if (err < rev_err) {
|
||||||
do_movement_estimation(ctx, stripes, FALSE);
|
do_movement_estimation(ctx, stripes, num_stripes, FALSE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -248,34 +256,45 @@ static inline void aes_blit_stripe(struct fpi_frame_asmbl_ctx *ctx,
|
|||||||
* fpi_assemble_frames:
|
* fpi_assemble_frames:
|
||||||
* @ctx: #fpi_frame_asmbl_ctx - frame assembling context
|
* @ctx: #fpi_frame_asmbl_ctx - frame assembling context
|
||||||
* @stripes: linked list of #fpi_frame
|
* @stripes: linked list of #fpi_frame
|
||||||
|
* @num_stripes: number of items in @stripes to process
|
||||||
*
|
*
|
||||||
* fpi_assemble_frames() assembles individual frames into a single image.
|
* fpi_assemble_frames() assembles individual frames into a single image.
|
||||||
* It expects @delta_x and @delta_y of #fpi_frame to be populated.
|
* It expects @delta_x and @delta_y of #fpi_frame to be populated.
|
||||||
*
|
*
|
||||||
|
* Note that @num_stripes might be shorter than the length of the list,
|
||||||
|
* if some stripes should be skipped.
|
||||||
|
*
|
||||||
* Returns: a newly allocated #fp_img.
|
* Returns: a newly allocated #fp_img.
|
||||||
*/
|
*/
|
||||||
struct fp_img *fpi_assemble_frames(struct fpi_frame_asmbl_ctx *ctx,
|
struct fp_img *fpi_assemble_frames(struct fpi_frame_asmbl_ctx *ctx,
|
||||||
GSList *stripes)
|
GSList *stripes, size_t num_stripes)
|
||||||
{
|
{
|
||||||
GSList *l;
|
GSList *stripe;
|
||||||
struct fp_img *img;
|
struct fp_img *img;
|
||||||
int height = 0;
|
int height = 0;
|
||||||
int y, x;
|
int i, y, x;
|
||||||
gboolean reverse = FALSE;
|
gboolean reverse = FALSE;
|
||||||
struct fpi_frame *fpi_frame;
|
struct fpi_frame *fpi_frame;
|
||||||
|
|
||||||
//FIXME g_return_if_fail
|
//FIXME g_return_if_fail
|
||||||
|
BUG_ON(num_stripes == 0);
|
||||||
BUG_ON(ctx->image_width < ctx->frame_width);
|
BUG_ON(ctx->image_width < ctx->frame_width);
|
||||||
|
|
||||||
|
/* Calculate height */
|
||||||
|
i = 0;
|
||||||
|
stripe = stripes;
|
||||||
|
|
||||||
/* No offset for 1st image */
|
/* No offset for 1st image */
|
||||||
fpi_frame = stripes->data;
|
fpi_frame = stripe->data;
|
||||||
fpi_frame->delta_x = 0;
|
fpi_frame->delta_x = 0;
|
||||||
fpi_frame->delta_y = 0;
|
fpi_frame->delta_y = 0;
|
||||||
for (l = stripes; l != NULL; l = l->next) {
|
do {
|
||||||
fpi_frame = l->data;
|
fpi_frame = stripe->data;
|
||||||
|
|
||||||
height += fpi_frame->delta_y;
|
height += fpi_frame->delta_y;
|
||||||
}
|
i++;
|
||||||
|
stripe = g_slist_next(stripe);
|
||||||
|
} while (i < num_stripes);
|
||||||
|
|
||||||
fp_dbg("height is %d", height);
|
fp_dbg("height is %d", height);
|
||||||
|
|
||||||
@@ -295,11 +314,13 @@ struct fp_img *fpi_assemble_frames(struct fpi_frame_asmbl_ctx *ctx,
|
|||||||
img->height = height;
|
img->height = height;
|
||||||
|
|
||||||
/* Assemble stripes */
|
/* Assemble stripes */
|
||||||
|
i = 0;
|
||||||
|
stripe = stripes;
|
||||||
y = reverse ? (height - ctx->frame_height) : 0;
|
y = reverse ? (height - ctx->frame_height) : 0;
|
||||||
x = (ctx->image_width - ctx->frame_width) / 2;
|
x = (ctx->image_width - ctx->frame_width) / 2;
|
||||||
|
|
||||||
for (l = stripes; l != NULL; l = l->next) {
|
do {
|
||||||
fpi_frame = l->data;
|
fpi_frame = stripe->data;
|
||||||
|
|
||||||
if(reverse) {
|
if(reverse) {
|
||||||
y += fpi_frame->delta_y;
|
y += fpi_frame->delta_y;
|
||||||
@@ -312,7 +333,10 @@ struct fp_img *fpi_assemble_frames(struct fpi_frame_asmbl_ctx *ctx,
|
|||||||
y += fpi_frame->delta_y;
|
y += fpi_frame->delta_y;
|
||||||
x += fpi_frame->delta_x;
|
x += fpi_frame->delta_x;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
stripe = g_slist_next(stripe);
|
||||||
|
i++;
|
||||||
|
} while (i < num_stripes);
|
||||||
|
|
||||||
return img;
|
return img;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -63,10 +63,10 @@ struct fpi_frame_asmbl_ctx {
|
|||||||
};
|
};
|
||||||
|
|
||||||
void fpi_do_movement_estimation(struct fpi_frame_asmbl_ctx *ctx,
|
void fpi_do_movement_estimation(struct fpi_frame_asmbl_ctx *ctx,
|
||||||
GSList *stripes);
|
GSList *stripes, size_t num_stripes);
|
||||||
|
|
||||||
struct fp_img *fpi_assemble_frames(struct fpi_frame_asmbl_ctx *ctx,
|
struct fp_img *fpi_assemble_frames(struct fpi_frame_asmbl_ctx *ctx,
|
||||||
GSList *stripes);
|
GSList *stripes, size_t num_stripes);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* fpi_line_asmbl_ctx:
|
* fpi_line_asmbl_ctx:
|
||||||
|
|||||||
@@ -214,7 +214,7 @@ API_EXPORTED size_t fp_print_data_get_data(struct fp_print_data *data,
|
|||||||
item = list_item->data;
|
item = list_item->data;
|
||||||
out_item = (struct fpi_print_data_item_fp2 *)buf;
|
out_item = (struct fpi_print_data_item_fp2 *)buf;
|
||||||
out_item->length = GUINT32_TO_LE(item->length);
|
out_item->length = GUINT32_TO_LE(item->length);
|
||||||
/* FIXME: fp_print_data_item->data content is not endianness agnostic */
|
/* FIXME: fp_print_data_item->data content is not endianess agnostic */
|
||||||
memcpy(out_item->data, item->data, item->length);
|
memcpy(out_item->data, item->data, item->length);
|
||||||
buf += sizeof(*out_item);
|
buf += sizeof(*out_item);
|
||||||
buf += item->length;
|
buf += item->length;
|
||||||
@@ -236,7 +236,7 @@ static struct fp_print_data *fpi_print_data_from_fp1_data(unsigned char *buf,
|
|||||||
data = print_data_new(GUINT16_FROM_LE(raw->driver_id),
|
data = print_data_new(GUINT16_FROM_LE(raw->driver_id),
|
||||||
GUINT32_FROM_LE(raw->devtype), raw->data_type);
|
GUINT32_FROM_LE(raw->devtype), raw->data_type);
|
||||||
item = fpi_print_data_item_new(print_data_len);
|
item = fpi_print_data_item_new(print_data_len);
|
||||||
/* FIXME: fp_print_data->data content is not endianness agnostic */
|
/* FIXME: fp_print_data->data content is not endianess agnostic */
|
||||||
memcpy(item->data, raw->data, print_data_len);
|
memcpy(item->data, raw->data, print_data_len);
|
||||||
data->prints = g_slist_prepend(data->prints, item);
|
data->prints = g_slist_prepend(data->prints, item);
|
||||||
|
|
||||||
@@ -272,7 +272,7 @@ static struct fp_print_data *fpi_print_data_from_fp2_data(unsigned char *buf,
|
|||||||
total_data_len -= item_len;
|
total_data_len -= item_len;
|
||||||
|
|
||||||
item = fpi_print_data_item_new(item_len);
|
item = fpi_print_data_item_new(item_len);
|
||||||
/* FIXME: fp_print_data->data content is not endianness agnostic */
|
/* FIXME: fp_print_data->data content is not endianess agnostic */
|
||||||
memcpy(item->data, raw_item->data, item_len);
|
memcpy(item->data, raw_item->data, item_len);
|
||||||
data->prints = g_slist_prepend(data->prints, item);
|
data->prints = g_slist_prepend(data->prints, item);
|
||||||
|
|
||||||
|
|||||||
@@ -405,7 +405,7 @@ int fpi_img_to_print_data(struct fp_img_dev *imgdev, struct fp_img *img,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* FIXME: space is wasted if we don't hit the max minutiae count. would
|
/* FIXME: space is wasted if we dont hit the max minutiae count. would
|
||||||
* be good to make this dynamic. */
|
* be good to make this dynamic. */
|
||||||
print = fpi_print_data_new(FP_DEV(imgdev));
|
print = fpi_print_data_new(FP_DEV(imgdev));
|
||||||
item = fpi_print_data_item_new(sizeof(struct xyt_struct));
|
item = fpi_print_data_item_new(sizeof(struct xyt_struct));
|
||||||
|
|||||||
@@ -149,7 +149,7 @@ static void enroll_stop_cb(struct fp_dev *dev, void *user_data)
|
|||||||
* or I/O problems.
|
* or I/O problems.
|
||||||
*
|
*
|
||||||
* The RETRY codes from #fp_enroll_result may be returned from any enroll
|
* The RETRY codes from #fp_enroll_result may be returned from any enroll
|
||||||
* stage. These codes indicate that the scan was not successful in that the
|
* stage. These codes indicate that the scan was not succesful in that the
|
||||||
* user did not position their finger correctly or similar. When a RETRY code
|
* user did not position their finger correctly or similar. When a RETRY code
|
||||||
* is returned, the enrollment stage is <emphasis role="strong">not</emphasis> advanced, so the next call
|
* is returned, the enrollment stage is <emphasis role="strong">not</emphasis> advanced, so the next call
|
||||||
* into this function will retry the current stage again. The current stage may
|
* into this function will retry the current stage again. The current stage may
|
||||||
|
|||||||
Reference in New Issue
Block a user