mirror of
https://gitlab.freedesktop.org/libfprint/libfprint.git
synced 2025-11-15 07:38:12 +00:00
Compare commits
8 Commits
wip/hadess
...
libfprint-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
823f2c1067 | ||
|
|
19732341d6 | ||
|
|
0e44eb4c1c | ||
|
|
50461b4d7d | ||
|
|
c11126181e | ||
|
|
658c301e3c | ||
|
|
dce52ed081 | ||
|
|
f309f586c9 |
113
.ci/check-abi
Executable file
113
.ci/check-abi
Executable file
@@ -0,0 +1,113 @@
|
|||||||
|
#!/usr/bin/python3
|
||||||
|
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import contextlib
|
||||||
|
import os
|
||||||
|
import shutil
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
|
||||||
|
|
||||||
|
def format_title(title):
|
||||||
|
box = {
|
||||||
|
'tl': '╔', 'tr': '╗', 'bl': '╚', 'br': '╝', 'h': '═', 'v': '║',
|
||||||
|
}
|
||||||
|
hline = box['h'] * (len(title) + 2)
|
||||||
|
|
||||||
|
return '\n'.join([
|
||||||
|
f"{box['tl']}{hline}{box['tr']}",
|
||||||
|
f"{box['v']} {title} {box['v']}",
|
||||||
|
f"{box['bl']}{hline}{box['br']}",
|
||||||
|
])
|
||||||
|
|
||||||
|
|
||||||
|
def rm_rf(path):
|
||||||
|
try:
|
||||||
|
shutil.rmtree(path)
|
||||||
|
except FileNotFoundError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def sanitize_path(name):
|
||||||
|
return name.replace('/', '-')
|
||||||
|
|
||||||
|
|
||||||
|
def get_current_revision():
|
||||||
|
revision = subprocess.check_output(['git', 'rev-parse', '--abbrev-ref', 'HEAD'],
|
||||||
|
encoding='utf-8').strip()
|
||||||
|
|
||||||
|
if revision == 'HEAD':
|
||||||
|
# This is a detached HEAD, get the commit hash
|
||||||
|
revision = subprocess.check_output(['git', 'rev-parse', 'HEAD']).strip().decode('utf-8')
|
||||||
|
|
||||||
|
return revision
|
||||||
|
|
||||||
|
|
||||||
|
@contextlib.contextmanager
|
||||||
|
def checkout_git_revision(revision):
|
||||||
|
current_revision = get_current_revision()
|
||||||
|
subprocess.check_call(['git', 'checkout', '-q', revision])
|
||||||
|
|
||||||
|
try:
|
||||||
|
yield
|
||||||
|
finally:
|
||||||
|
subprocess.check_call(['git', 'checkout', '-q', current_revision])
|
||||||
|
|
||||||
|
|
||||||
|
def build_install(revision):
|
||||||
|
build_dir = '_build'
|
||||||
|
dest_dir = os.path.abspath(sanitize_path(revision))
|
||||||
|
print(format_title(f'# Building and installing {revision} in {dest_dir}'),
|
||||||
|
end='\n\n', flush=True)
|
||||||
|
|
||||||
|
with checkout_git_revision(revision):
|
||||||
|
rm_rf(build_dir)
|
||||||
|
rm_rf(revision)
|
||||||
|
|
||||||
|
subprocess.check_call(['meson', build_dir,
|
||||||
|
'--prefix=/usr', '--libdir=lib',
|
||||||
|
'-Dx11-examples=false', '-Ddoc=false', '-Dgtk-examples=false'])
|
||||||
|
subprocess.check_call(['ninja', '-v', '-C', build_dir])
|
||||||
|
subprocess.check_call(['ninja', '-v', '-C', build_dir, 'install'],
|
||||||
|
env={'DESTDIR': dest_dir})
|
||||||
|
|
||||||
|
return dest_dir
|
||||||
|
|
||||||
|
|
||||||
|
def compare(old_tree, new_tree):
|
||||||
|
print(format_title(f'# Comparing the two ABIs'), end='\n\n', flush=True)
|
||||||
|
|
||||||
|
old_headers = os.path.join(old_tree, 'usr', 'include')
|
||||||
|
old_lib = os.path.join(old_tree, 'usr', 'lib', 'libfprint.so')
|
||||||
|
|
||||||
|
new_headers = os.path.join(new_tree, 'usr', 'include')
|
||||||
|
new_lib = os.path.join(new_tree, 'usr', 'lib', 'libfprint.so')
|
||||||
|
|
||||||
|
subprocess.check_call([
|
||||||
|
'abidiff', '--headers-dir1', old_headers, '--headers-dir2', new_headers,
|
||||||
|
'--drop-private-types', '--fail-no-debug-info', '--no-added-syms', old_lib, new_lib])
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
|
||||||
|
parser.add_argument('old', help='the previous revision, considered the reference')
|
||||||
|
parser.add_argument('new', help='the new revision, to compare to the reference')
|
||||||
|
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
if args.old == args.new:
|
||||||
|
print("Let's not waste time comparing something to itself")
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
old_tree = build_install(args.old)
|
||||||
|
new_tree = build_install(args.new)
|
||||||
|
|
||||||
|
try:
|
||||||
|
compare(old_tree, new_tree)
|
||||||
|
|
||||||
|
except Exception:
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
print(f'Hurray! {args.old} and {args.new} are ABI-compatible!')
|
||||||
@@ -7,6 +7,7 @@ variables:
|
|||||||
DEPENDENCIES: libusb1-devel glib2-devel nss-devel pixman-devel systemd meson gtk-doc
|
DEPENDENCIES: libusb1-devel glib2-devel nss-devel pixman-devel systemd meson gtk-doc
|
||||||
gcc gcc-c++ glibc-devel libX11-devel libXv-devel gtk3-devel flatpak-builder
|
gcc gcc-c++ glibc-devel libX11-devel libXv-devel gtk3-devel flatpak-builder
|
||||||
BUNDLE: "org.freedesktop.libfprint.Demo.flatpak"
|
BUNDLE: "org.freedesktop.libfprint.Demo.flatpak"
|
||||||
|
LAST_ABI_BREAK: "056ea541ddc97f5806cffbd99a12dc87e4da3546"
|
||||||
|
|
||||||
.build_one_driver_template: &build_one_driver
|
.build_one_driver_template: &build_one_driver
|
||||||
script:
|
script:
|
||||||
@@ -24,10 +25,16 @@ variables:
|
|||||||
- ninja -C _build
|
- ninja -C _build
|
||||||
- ninja -C _build install
|
- ninja -C _build install
|
||||||
|
|
||||||
|
.build_template: &check_abi
|
||||||
|
script:
|
||||||
|
- dnf update -y --nogpgcheck && dnf install -y --nogpgcheck $DEPENDENCIES doxygen libabigail git
|
||||||
|
- ./.ci/check-abi ${LAST_ABI_BREAK} $(git rev-parse HEAD)
|
||||||
|
|
||||||
build:
|
build:
|
||||||
stage: build
|
stage: build
|
||||||
<<: *build_one_driver
|
<<: *build_one_driver
|
||||||
<<: *build
|
<<: *build
|
||||||
|
<<: *check_abi
|
||||||
|
|
||||||
.flatpak_script_template: &flatpak_script
|
.flatpak_script_template: &flatpak_script
|
||||||
script:
|
script:
|
||||||
|
|||||||
27
NEWS
27
NEWS
@@ -1,6 +1,33 @@
|
|||||||
This file lists notable changes in each release. For the full history of all
|
This file lists notable changes in each release. For the full history of all
|
||||||
changes, see ChangeLog.
|
changes, see ChangeLog.
|
||||||
|
|
||||||
|
2019-08-08: v1.0 release
|
||||||
|
* Library:
|
||||||
|
- Add guards to the public API and require GLib 2.50
|
||||||
|
- Deprecate print storage API
|
||||||
|
- Better documentation for fp_discover_devs()
|
||||||
|
- Remove unused internal fpi_timeout_cancel_for_dev()
|
||||||
|
- Remove state from fp_img_driver activate handler
|
||||||
|
- Bug fixes related to restarting a failed verification immediately
|
||||||
|
|
||||||
|
* Drivers:
|
||||||
|
- The Elan driver received a lot of bug fixes including a fix for a
|
||||||
|
hang when verifying prints with fprintd, quirks for some devices,
|
||||||
|
a memory leak fix and support for 04f3:0c42
|
||||||
|
- Fix a probable crash in all the AES drivers
|
||||||
|
- Add support for Lenovo Preferred Pro Keyboard (KUF1256) to vfs5011
|
||||||
|
- Prevent hang during enroll process in etes603 driver
|
||||||
|
- Fix possible integer overflow in uru4000
|
||||||
|
- Work-around SELinux AVC warnings when uru4000 driver starts
|
||||||
|
- Remove long-unmaintained and broken fdu2000 driver
|
||||||
|
|
||||||
|
* Tools/Examples:
|
||||||
|
- Fix examples not working due to an overly strict check
|
||||||
|
- Fix crash in GTK demo when there's no supported devices
|
||||||
|
- Disable GTK demo until we have a USB Flatpak portal
|
||||||
|
- Remove sleep() in enroll example which caused a crash in some drivers
|
||||||
|
- Add a simple storage implementation example
|
||||||
|
|
||||||
2018-12-14: v0.99.0 release
|
2018-12-14: v0.99.0 release
|
||||||
* Library:
|
* Library:
|
||||||
- All the internal API for device driver writers is now covered by the
|
- All the internal API for device driver writers is now covered by the
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -53,12 +53,15 @@ static void write_regv_trf_complete(struct libusb_transfer *transfer)
|
|||||||
{
|
{
|
||||||
struct write_regv_data *wdata = transfer->user_data;
|
struct write_regv_data *wdata = transfer->user_data;
|
||||||
|
|
||||||
if (transfer->status != LIBUSB_TRANSFER_COMPLETED)
|
if (transfer->status != LIBUSB_TRANSFER_COMPLETED) {
|
||||||
wdata->callback(wdata->imgdev, -EIO, wdata->user_data);
|
wdata->callback(wdata->imgdev, -EIO, wdata->user_data);
|
||||||
else if (transfer->length != transfer->actual_length)
|
g_free(wdata);
|
||||||
|
} else if (transfer->length != transfer->actual_length) {
|
||||||
wdata->callback(wdata->imgdev, -EPROTO, wdata->user_data);
|
wdata->callback(wdata->imgdev, -EPROTO, wdata->user_data);
|
||||||
else
|
g_free(wdata);
|
||||||
|
} else {
|
||||||
continue_write_regv(wdata);
|
continue_write_regv(wdata);
|
||||||
|
}
|
||||||
|
|
||||||
g_free(transfer->buffer);
|
g_free(transfer->buffer);
|
||||||
libusb_free_transfer(transfer);
|
libusb_free_transfer(transfer);
|
||||||
@@ -109,6 +112,7 @@ static void continue_write_regv(struct write_regv_data *wdata)
|
|||||||
if (offset >= wdata->num_regs) {
|
if (offset >= wdata->num_regs) {
|
||||||
fp_dbg("all registers written");
|
fp_dbg("all registers written");
|
||||||
wdata->callback(wdata->imgdev, 0, wdata->user_data);
|
wdata->callback(wdata->imgdev, 0, wdata->user_data);
|
||||||
|
g_free(wdata);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (wdata->regs[offset].reg)
|
if (wdata->regs[offset].reg)
|
||||||
@@ -132,6 +136,7 @@ static void continue_write_regv(struct write_regv_data *wdata)
|
|||||||
r = do_write_regv(wdata, upper_bound);
|
r = do_write_regv(wdata, upper_bound);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
wdata->callback(wdata->imgdev, r, wdata->user_data);
|
wdata->callback(wdata->imgdev, r, wdata->user_data);
|
||||||
|
g_free(wdata);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -155,8 +160,6 @@ void aes_write_regv(struct fp_img_dev *dev, const struct aes_regwrite *regs,
|
|||||||
wdata->callback = callback;
|
wdata->callback = callback;
|
||||||
wdata->user_data = user_data;
|
wdata->user_data = user_data;
|
||||||
continue_write_regv(wdata);
|
continue_write_regv(wdata);
|
||||||
|
|
||||||
g_free(wdata);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned char aes_get_pixel(struct fpi_frame_asmbl_ctx *ctx,
|
unsigned char aes_get_pixel(struct fpi_frame_asmbl_ctx *ctx,
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -307,8 +307,8 @@ static void elan_submit_image(struct fp_img_dev *dev)
|
|||||||
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(raw_frames, (GFunc) elandev->process_frame, &frames);
|
||||||
fpi_do_movement_estimation(&assembling_ctx, frames);
|
fpi_do_movement_estimation(&assembling_ctx, frames, num_frames);
|
||||||
img = fpi_assemble_frames(&assembling_ctx, frames);
|
img = fpi_assemble_frames(&assembling_ctx, frames, num_frames);
|
||||||
|
|
||||||
img->flags |= FP_IMG_PARTIAL;
|
img->flags |= FP_IMG_PARTIAL;
|
||||||
fpi_imgdev_image_captured(dev, img);
|
fpi_imgdev_image_captured(dev, img);
|
||||||
@@ -424,7 +424,8 @@ elan_run_cmd(fpi_ssm *ssm,
|
|||||||
elandev->cmd_timeout = cmd_timeout;
|
elandev->cmd_timeout = cmd_timeout;
|
||||||
|
|
||||||
if (cmd->devices != ELAN_ALL_DEV && !(cmd->devices & elandev->dev_type)) {
|
if (cmd->devices != ELAN_ALL_DEV && !(cmd->devices & elandev->dev_type)) {
|
||||||
fp_dbg("skipping for this device");
|
fp_dbg("skipping command 0x%x 0x%x for this device (for devices 0x%x but device is 0x%x)",
|
||||||
|
cmd->cmd[0], cmd->cmd[1], cmd->devices, elandev->dev_type);
|
||||||
elan_cmd_done(ssm);
|
elan_cmd_done(ssm);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -371,7 +371,7 @@ static int process_chunk(struct vfs5011_data *data, int transferred)
|
|||||||
VFS5011_IMAGE_WIDTH) >= DIFFERENCE_THRESHOLD)) {
|
VFS5011_IMAGE_WIDTH) >= DIFFERENCE_THRESHOLD)) {
|
||||||
data->lastline = g_malloc(VFS5011_LINE_SIZE);
|
data->lastline = g_malloc(VFS5011_LINE_SIZE);
|
||||||
data->rows = g_slist_prepend(data->rows, data->lastline);
|
data->rows = g_slist_prepend(data->rows, data->lastline);
|
||||||
g_memmove(data->lastline, linebuf, VFS5011_LINE_SIZE);
|
memmove(data->lastline, linebuf, VFS5011_LINE_SIZE);
|
||||||
data->lines_recorded++;
|
data->lines_recorded++;
|
||||||
if (data->lines_recorded >= data->max_lines_recorded) {
|
if (data->lines_recorded >= data->max_lines_recorded) {
|
||||||
fp_dbg("process_chunk: recorded %d lines, finishing",
|
fp_dbg("process_chunk: recorded %d lines, finishing",
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
@@ -341,7 +365,7 @@ static void median_filter(int *data, int size, int filtersize)
|
|||||||
i1 = 0;
|
i1 = 0;
|
||||||
if (i2 >= size)
|
if (i2 >= size)
|
||||||
i2 = size-1;
|
i2 = size-1;
|
||||||
g_memmove(sortbuf, data+i1, (i2-i1+1)*sizeof(int));
|
memmove(sortbuf, data+i1, (i2-i1+1)*sizeof(int));
|
||||||
g_qsort_with_data(sortbuf, i2-i1+1, sizeof(int), cmpint, NULL);
|
g_qsort_with_data(sortbuf, i2-i1+1, sizeof(int), cmpint, NULL);
|
||||||
result[i] = sortbuf[(i2-i1+1)/2];
|
result[i] = sortbuf[(i2-i1+1)/2];
|
||||||
}
|
}
|
||||||
@@ -456,7 +480,7 @@ out:
|
|||||||
img->height = line_ind;
|
img->height = line_ind;
|
||||||
img->width = ctx->line_width;
|
img->width = ctx->line_width;
|
||||||
img->flags = FP_IMG_V_FLIPPED;
|
img->flags = FP_IMG_V_FLIPPED;
|
||||||
g_memmove(img->data, output, ctx->line_width * line_ind);
|
memmove(img->data, output, ctx->line_width * line_ind);
|
||||||
g_free(offsets);
|
g_free(offsets);
|
||||||
g_free(output);
|
g_free(output);
|
||||||
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:
|
||||||
|
|||||||
@@ -387,9 +387,21 @@ API_EXPORTED int fp_async_verify_stop(struct fp_dev *dev,
|
|||||||
|
|
||||||
g_return_val_if_fail(dev != NULL, -ENODEV);
|
g_return_val_if_fail(dev != NULL, -ENODEV);
|
||||||
|
|
||||||
|
G_DEBUG_HERE();
|
||||||
|
|
||||||
|
if (dev->state == DEV_STATE_VERIFY_STOPPING) {
|
||||||
|
fp_dbg ("Already stopping verification, returning -EINPROGRESS");
|
||||||
|
return -EINPROGRESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dev->state == DEV_STATE_INITIALIZED) {
|
||||||
|
if (callback)
|
||||||
|
callback(dev, user_data);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
drv = dev->drv;
|
drv = dev->drv;
|
||||||
|
|
||||||
G_DEBUG_HERE();
|
|
||||||
BUG_ON(dev->state != DEV_STATE_ERROR
|
BUG_ON(dev->state != DEV_STATE_ERROR
|
||||||
&& dev->state != DEV_STATE_VERIFYING
|
&& dev->state != DEV_STATE_VERIFYING
|
||||||
&& dev->state != DEV_STATE_VERIFY_DONE);
|
&& dev->state != DEV_STATE_VERIFY_DONE);
|
||||||
@@ -511,9 +523,21 @@ API_EXPORTED int fp_async_identify_stop(struct fp_dev *dev,
|
|||||||
|
|
||||||
g_return_val_if_fail(dev != NULL, -ENODEV);
|
g_return_val_if_fail(dev != NULL, -ENODEV);
|
||||||
|
|
||||||
|
G_DEBUG_HERE();
|
||||||
|
|
||||||
|
if (dev->state == DEV_STATE_IDENTIFY_STOPPING) {
|
||||||
|
fp_dbg ("Already stopping identification, returning -EINPROGRESS");
|
||||||
|
return -EINPROGRESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dev->state == DEV_STATE_INITIALIZED) {
|
||||||
|
if (callback)
|
||||||
|
callback(dev, user_data);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
drv = dev->drv;
|
drv = dev->drv;
|
||||||
|
|
||||||
G_DEBUG_HERE();
|
|
||||||
BUG_ON(dev->state != DEV_STATE_IDENTIFYING
|
BUG_ON(dev->state != DEV_STATE_IDENTIFYING
|
||||||
&& dev->state != DEV_STATE_IDENTIFY_DONE);
|
&& dev->state != DEV_STATE_IDENTIFY_DONE);
|
||||||
|
|
||||||
|
|||||||
@@ -485,9 +485,15 @@ void fpi_imgdev_activate_complete(struct fp_img_dev *imgdev, int status)
|
|||||||
*/
|
*/
|
||||||
void fpi_imgdev_deactivate_complete(struct fp_img_dev *imgdev)
|
void fpi_imgdev_deactivate_complete(struct fp_img_dev *imgdev)
|
||||||
{
|
{
|
||||||
|
enum fp_imgdev_action action;
|
||||||
|
|
||||||
G_DEBUG_HERE();
|
G_DEBUG_HERE();
|
||||||
|
|
||||||
switch (imgdev->action) {
|
action = imgdev->action;
|
||||||
|
imgdev->action = IMG_ACTION_NONE;
|
||||||
|
imgdev->action_state = 0;
|
||||||
|
|
||||||
|
switch (action) {
|
||||||
case IMG_ACTION_ENROLL:
|
case IMG_ACTION_ENROLL:
|
||||||
fpi_drvcb_enroll_stopped(FP_DEV(imgdev));
|
fpi_drvcb_enroll_stopped(FP_DEV(imgdev));
|
||||||
break;
|
break;
|
||||||
@@ -504,9 +510,6 @@ void fpi_imgdev_deactivate_complete(struct fp_img_dev *imgdev)
|
|||||||
fp_err("unhandled action %d", imgdev->action);
|
fp_err("unhandled action %d", imgdev->action);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
imgdev->action = IMG_ACTION_NONE;
|
|
||||||
imgdev->action_state = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int fpi_imgdev_get_img_width(struct fp_img_dev *imgdev)
|
int fpi_imgdev_get_img_width(struct fp_img_dev *imgdev)
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
project('libfprint', [ 'c', 'cpp' ],
|
project('libfprint', [ 'c', 'cpp' ],
|
||||||
version: '0.99.0',
|
version: '1.0',
|
||||||
license: 'LGPLv2.1+',
|
license: 'LGPLv2.1+',
|
||||||
default_options: [
|
default_options: [
|
||||||
'buildtype=debugoptimized',
|
'buildtype=debugoptimized',
|
||||||
|
|||||||
Reference in New Issue
Block a user