Compare commits

..

1 Commits

Author SHA1 Message Date
Bastien Nocera
197edac702 lib: Generate driver IDs, instead of hard-coding them
Instead of adding driver IDs by hand to a header file, generate the
driver ID from the (hopefully unique) name of the driver.

This means one file less for driver authors to modify, and one possible
source of merge conflicts less as well.

However, this means that already enrolled fingerprints will need to be
enrolled again, as the driver IDs will have changed compared to their
old on-disk value.
2019-06-12 16:50:01 +02:00
53 changed files with 439 additions and 539 deletions

View File

@@ -1,113 +0,0 @@
#!/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!')

View File

@@ -7,7 +7,6 @@ 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:
@@ -25,16 +24,10 @@ 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:

View File

@@ -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

27
NEWS
View File

@@ -1,33 +1,6 @@
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

View File

@@ -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/

View File

@@ -71,10 +71,7 @@
<title>Driver IDs</title> <title>Driver IDs</title>
<para> <para>
Each driver is assigned a unique ID by the project maintainer. These Each driver is assigned a unique ID automatically based on the driver name.
assignments are
<ulink url="https://gitlab.freedesktop.org/libfprint/libfprint/blob/master/libfprint/drivers/driver_ids.h">
documented in the sources</ulink> and will never change.
</para> </para>
<para> <para>

View File

@@ -17,7 +17,6 @@ private_headers = [
'aes2660.h', 'aes2660.h',
'aes3k.h', 'aes3k.h',
'aesx660.h', 'aesx660.h',
'driver_ids.h',
'elan.h', 'elan.h',
'upek_proto.h', 'upek_proto.h',
'upeksonly.h', 'upeksonly.h',

View File

@@ -24,8 +24,6 @@
#include <libfprint/fprint.h> #include <libfprint/fprint.h>
#include "storage.h"
struct fp_dscv_dev *discover_device(struct fp_dscv_dev **discovered_devs) struct fp_dscv_dev *discover_device(struct fp_dscv_dev **discovered_devs)
{ {
struct fp_dscv_dev *ddev = discovered_devs[0]; struct fp_dscv_dev *ddev = discovered_devs[0];
@@ -144,7 +142,10 @@ int main(void)
if (!data) if (!data)
goto out_close; goto out_close;
r = print_data_save(data, RIGHT_INDEX); #pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
r = fp_print_data_save(data, RIGHT_INDEX);
#pragma GCC diagnostic pop
if (r < 0) if (r < 0)
fprintf(stderr, "Data save failed, code %d\n", r); fprintf(stderr, "Data save failed, code %d\n", r);

View File

@@ -2,8 +2,8 @@
examples = [ 'verify_live', 'enroll', 'verify', 'img_capture' ] examples = [ 'verify_live', 'enroll', 'verify', 'img_capture' ]
foreach example: examples foreach example: examples
executable(example, executable(example,
[example + '.c', 'storage.c'], example + '.c',
dependencies: [libfprint_dep, glib_dep], dependencies: libfprint_dep,
include_directories: [ include_directories: [
root_inc, root_inc,
], ],

View File

@@ -1,136 +0,0 @@
/*
* Trivial storage driver for example programs
*
* Copyright (C) 2019 Benjamin Berg <bberg@redhat.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
*/
#include <glib.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <libfprint/fprint.h>
#define STORAGE_FILE "test-storage.variant"
static char *
get_print_data_descriptor (struct fp_print_data *data, struct fp_dev *dev, enum fp_finger finger)
{
gint drv_id;
gint devtype;
if (data) {
drv_id = fp_print_data_get_driver_id (data);
devtype = fp_print_data_get_devtype (data);
} else {
drv_id = fp_driver_get_driver_id(fp_dev_get_driver (dev));
devtype = fp_dev_get_devtype (dev);
}
return g_strdup_printf("%x/%08x/%x",
drv_id,
devtype,
finger);
}
static GVariantDict*
load_data(void)
{
GVariantDict *res;
GVariant *var;
gchar *contents = NULL;
gssize length = 0;
if (!g_file_get_contents (STORAGE_FILE, &contents, &length, NULL)) {
g_warning ("Error loading storage, assuming it is empty");
return g_variant_dict_new(NULL);
}
var = g_variant_new_from_data (G_VARIANT_TYPE_VARDICT, contents, length, FALSE, NULL, NULL);
res = g_variant_dict_new(var);
g_variant_unref(var);
return res;
}
static int
save_data(GVariant *data)
{
const gchar *contents = NULL;
gsize length;
length = g_variant_get_size(data);
contents = (gchar*) g_variant_get_data (data);
if (!g_file_set_contents (STORAGE_FILE, contents, length, NULL)) {
g_warning ("Error saving storage,!");
return -1;
}
g_variant_ref_sink(data);
g_variant_unref(data);
return 0;
}
int
print_data_save(struct fp_print_data *fp_data, enum fp_finger finger)
{
gchar *descr = get_print_data_descriptor (fp_data, NULL, finger);
GVariantDict *dict;
GVariant *val;
guchar *data;
gsize size;
int res;
dict = load_data();
size = fp_print_data_get_data(fp_data, &data);
val = g_variant_new_fixed_array (G_VARIANT_TYPE("y"), data, size, 1);
g_variant_dict_insert_value (dict, descr, val);
res = save_data(g_variant_dict_end(dict));
g_variant_dict_unref(dict);
return res;
}
struct fp_print_data*
print_data_load(struct fp_dev *dev, enum fp_finger finger)
{
gchar *descr = get_print_data_descriptor (NULL, dev, finger);
GVariantDict *dict;
guchar *stored_data;
gsize stored_len;
GVariant *val;
struct fp_print_data *res = NULL;
dict = load_data();
val = g_variant_dict_lookup_value (dict, descr, G_VARIANT_TYPE ("ay"));
if (val) {
stored_data = (guchar*) g_variant_get_fixed_array (val, &stored_len, 1);
res = fp_print_data_from_data(stored_data, stored_len);
g_variant_unref(val);
}
g_variant_dict_unref(dict);
g_free(descr);
return res;
}

View File

@@ -1,27 +0,0 @@
/*
* Trivial storage driver for example programs
*
* Copyright (C) 2019 Benjamin Berg <bberg@redhat.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 __STORAGE_H
#define __STORAGE_H
int print_data_save(struct fp_print_data *fp_data, enum fp_finger finger);
struct fp_print_data* print_data_load(struct fp_dev *dev, enum fp_finger finger);
#endif /* __STORAGE_H */

View File

@@ -24,8 +24,6 @@
#include <libfprint/fprint.h> #include <libfprint/fprint.h>
#include "storage.h"
struct fp_dscv_dev *discover_device(struct fp_dscv_dev **discovered_devs) struct fp_dscv_dev *discover_device(struct fp_dscv_dev **discovered_devs)
{ {
struct fp_dscv_dev *ddev = discovered_devs[0]; struct fp_dscv_dev *ddev = discovered_devs[0];
@@ -119,8 +117,11 @@ int main(void)
printf("Opened device. Loading previously enrolled right index finger " printf("Opened device. Loading previously enrolled right index finger "
"data...\n"); "data...\n");
data = print_data_load(dev, RIGHT_INDEX); #pragma GCC diagnostic push
if (!data) { #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
r = fp_print_data_load(dev, RIGHT_INDEX, &data);
#pragma GCC diagnostic pop
if (r != 0) {
fprintf(stderr, "Failed to load fingerprint, error %d\n", r); fprintf(stderr, "Failed to load fingerprint, error %d\n", r);
fprintf(stderr, "Did you remember to enroll your right index finger " fprintf(stderr, "Did you remember to enroll your right index finger "
"first?\n"); "first?\n");

View File

@@ -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 {
@@ -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");
@@ -749,7 +749,7 @@ static void activate_sm_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_d
fpi_ssm_free(ssm); fpi_ssm_free(ssm);
} }
static int dev_activate(struct fp_img_dev *dev) static int dev_activate(struct fp_img_dev *dev, enum fp_imgdev_state state)
{ {
struct aes1610_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev)); struct aes1610_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev));
fpi_ssm *ssm = fpi_ssm_new(FP_DEV(dev), activate_run_state, fpi_ssm *ssm = fpi_ssm_new(FP_DEV(dev), activate_run_state,
@@ -817,7 +817,6 @@ static const struct usb_id id_table[] = {
struct fp_img_driver aes1610_driver = { struct fp_img_driver aes1610_driver = {
.driver = { .driver = {
.id = AES1610_ID,
.name = FP_COMPONENT, .name = FP_COMPONENT,
.full_name = "AuthenTec AES1610", .full_name = "AuthenTec AES1610",
.id_table = id_table, .id_table = id_table,

View File

@@ -94,7 +94,6 @@ static const struct usb_id id_table[] = {
struct fp_img_driver aes1660_driver = { struct fp_img_driver aes1660_driver = {
.driver = { .driver = {
.id = AES1660_ID,
.name = FP_COMPONENT, .name = FP_COMPONENT,
.full_name = "AuthenTec AES1660", .full_name = "AuthenTec AES1660",
.id_table = id_table, .id_table = id_table,

View File

@@ -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 {
@@ -792,7 +792,7 @@ static void activate_sm_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_d
fpi_ssm_free(ssm); fpi_ssm_free(ssm);
} }
static int dev_activate(struct fp_img_dev *dev) static int dev_activate(struct fp_img_dev *dev, enum fp_imgdev_state state)
{ {
struct aes2501_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev)); struct aes2501_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev));
fpi_ssm *ssm = fpi_ssm_new(FP_DEV(dev), activate_run_state, fpi_ssm *ssm = fpi_ssm_new(FP_DEV(dev), activate_run_state,
@@ -859,7 +859,6 @@ static const struct usb_id id_table[] = {
struct fp_img_driver aes2501_driver = { struct fp_img_driver aes2501_driver = {
.driver = { .driver = {
.id = AES2501_ID,
.name = FP_COMPONENT, .name = FP_COMPONENT,
.full_name = "AuthenTec AES2501", .full_name = "AuthenTec AES2501",
.id_table = id_table, .id_table = id_table,

View File

@@ -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 {

View File

@@ -447,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;
@@ -541,7 +541,7 @@ static void activate_sm_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_d
fpi_ssm_free(ssm); fpi_ssm_free(ssm);
} }
static int dev_activate(struct fp_img_dev *dev) static int dev_activate(struct fp_img_dev *dev, enum fp_imgdev_state state)
{ {
fpi_ssm *ssm = fpi_ssm_new(FP_DEV(dev), activate_run_state, fpi_ssm *ssm = fpi_ssm_new(FP_DEV(dev), activate_run_state,
ACTIVATE_NUM_STATES, dev); ACTIVATE_NUM_STATES, dev);
@@ -603,7 +603,6 @@ static const struct usb_id id_table[] = {
struct fp_img_driver aes2550_driver = { struct fp_img_driver aes2550_driver = {
.driver = { .driver = {
.id = AES2550_ID,
.name = FP_COMPONENT, .name = FP_COMPONENT,
.full_name = "AuthenTec AES2550/AES2810", .full_name = "AuthenTec AES2550/AES2810",
.id_table = id_table, .id_table = id_table,

View File

@@ -97,7 +97,6 @@ static const struct usb_id id_table[] = {
struct fp_img_driver aes2660_driver = { struct fp_img_driver aes2660_driver = {
.driver = { .driver = {
.id = AES2660_ID,
.name = FP_COMPONENT, .name = FP_COMPONENT,
.full_name = "AuthenTec AES2660", .full_name = "AuthenTec AES2660",
.id_table = id_table, .id_table = id_table,

View File

@@ -162,7 +162,6 @@ static const struct usb_id id_table[] = {
struct fp_img_driver aes3500_driver = { struct fp_img_driver aes3500_driver = {
.driver = { .driver = {
.id = AES3500_ID,
.name = FP_COMPONENT, .name = FP_COMPONENT,
.full_name = "AuthenTec AES3500", .full_name = "AuthenTec AES3500",
.id_table = id_table, .id_table = id_table,

View File

@@ -137,7 +137,7 @@ static void init_reqs_cb(struct fp_img_dev *dev, int result, void *user_data)
do_capture(dev); do_capture(dev);
} }
int aes3k_dev_activate(struct fp_img_dev *dev) int aes3k_dev_activate(struct fp_img_dev *dev, enum fp_imgdev_state state)
{ {
struct aes3k_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev)); struct aes3k_dev *aesdev = FP_INSTANCE_DATA(FP_DEV(dev));
aes_write_regv(dev, aesdev->init_reqs, aesdev->init_reqs_len, init_reqs_cb, NULL); aes_write_regv(dev, aesdev->init_reqs, aesdev->init_reqs_len, init_reqs_cb, NULL);

View File

@@ -52,7 +52,7 @@ struct aes3k_dev {
}; };
int aes3k_dev_activate(struct fp_img_dev *dev); int aes3k_dev_activate(struct fp_img_dev *dev, enum fp_imgdev_state state);
void aes3k_dev_deactivate(struct fp_img_dev *dev); void aes3k_dev_deactivate(struct fp_img_dev *dev);
#endif #endif

View File

@@ -159,7 +159,6 @@ static const struct usb_id id_table[] = {
struct fp_img_driver aes4000_driver = { struct fp_img_driver aes4000_driver = {
.driver = { .driver = {
.id = AES4000_ID,
.name = FP_COMPONENT, .name = FP_COMPONENT,
.full_name = "AuthenTec AES4000", .full_name = "AuthenTec AES4000",
.id_table = id_table, .id_table = id_table,

View File

@@ -53,15 +53,12 @@ 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);
g_free(wdata); else if (transfer->length != transfer->actual_length)
} else if (transfer->length != transfer->actual_length) {
wdata->callback(wdata->imgdev, -EPROTO, wdata->user_data); wdata->callback(wdata->imgdev, -EPROTO, wdata->user_data);
g_free(wdata); else
} 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);
@@ -112,7 +109,6 @@ 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)
@@ -136,7 +132,6 @@ 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;
} }
@@ -160,6 +155,8 @@ 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,

View File

@@ -589,7 +589,7 @@ static void activate_sm_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_d
start_finger_detection(dev); start_finger_detection(dev);
} }
int aesX660_dev_activate(struct fp_img_dev *dev) int aesX660_dev_activate(struct fp_img_dev *dev, enum fp_imgdev_state state)
{ {
fpi_ssm *ssm = fpi_ssm_new(FP_DEV(dev), activate_run_state, fpi_ssm *ssm = fpi_ssm_new(FP_DEV(dev), activate_run_state,
ACTIVATE_NUM_STATES, dev); ACTIVATE_NUM_STATES, dev);

View File

@@ -116,7 +116,7 @@ static const unsigned char calibrate_cmd[] = {
0x06, 0x06,
}; };
int aesX660_dev_activate(struct fp_img_dev *dev); int aesX660_dev_activate(struct fp_img_dev *dev, enum fp_imgdev_state state);
void aesX660_dev_deactivate(struct fp_img_dev *dev); void aesX660_dev_deactivate(struct fp_img_dev *dev);
#endif #endif

View File

@@ -1,47 +0,0 @@
/*
* Driver IDs
* Copyright (C) 2012 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 __DRIVER_IDS
#define __DRIVER_IDS
enum {
UPEKTS_ID = 1,
URU4000_ID = 2,
AES4000_ID = 3,
AES2501_ID = 4,
UPEKTC_ID = 5,
AES1610_ID = 6,
/* FDU2000_ID = 7, */
VCOM5S_ID = 8,
UPEKSONLY_ID = 9,
VFS101_ID = 10,
VFS301_ID = 11,
AES2550_ID = 12,
/* UPEKE2_ID = 13 */
AES1660_ID = 14,
AES2660_ID = 15,
AES3500_ID = 16,
UPEKTC_IMG_ID = 17,
ETES603_ID = 18,
VFS5011_ID = 19,
VFS0050_ID = 20,
ELAN_ID = 21,
};
#endif

View File

@@ -293,22 +293,23 @@ 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 *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; for (int i = 0; i < ELAN_SKIP_LAST_FRAMES; i++)
raw_frames = g_slist_nth(elandev->frames, ELAN_SKIP_LAST_FRAMES); elandev->frames = g_slist_next(elandev->frames);
elandev->num_frames -= ELAN_SKIP_LAST_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(elandev->frames, (GFunc) elandev->process_frame,
fpi_do_movement_estimation(&assembling_ctx, frames, num_frames); &frames);
img = fpi_assemble_frames(&assembling_ctx, frames, num_frames); fpi_do_movement_estimation(&assembling_ctx, frames,
elandev->num_frames);
img = fpi_assemble_frames(&assembling_ctx, frames, elandev->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,8 +425,7 @@ 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 command 0x%x 0x%x for this device (for devices 0x%x but device is 0x%x)", fp_dbg("skipping for this device");
cmd->cmd[0], cmd->cmd[1], cmd->devices, elandev->dev_type);
elan_cmd_done(ssm); elan_cmd_done(ssm);
return; return;
} }
@@ -874,7 +874,7 @@ static void dev_deinit(struct fp_img_dev *dev)
fpi_imgdev_close_complete(dev); fpi_imgdev_close_complete(dev);
} }
static int dev_activate(struct fp_img_dev *dev) static int dev_activate(struct fp_img_dev *dev, enum fp_imgdev_state state)
{ {
G_DEBUG_HERE(); G_DEBUG_HERE();
elan_activate(dev); elan_activate(dev);
@@ -970,7 +970,6 @@ static void dev_deactivate(struct fp_img_dev *dev)
struct fp_img_driver elan_driver = { struct fp_img_driver elan_driver = {
.driver = { .driver = {
.id = ELAN_ID,
.name = FP_COMPONENT, .name = FP_COMPONENT,
.full_name = "ElanTech Fingerprint Sensor", .full_name = "ElanTech Fingerprint Sensor",
.id_table = elan_id_table, .id_table = elan_id_table,

View File

@@ -36,7 +36,6 @@
#define FP_COMPONENT "etes603" #define FP_COMPONENT "etes603"
#include "drivers_api.h" #include "drivers_api.h"
#include "driver_ids.h"
/* libusb defines */ /* libusb defines */
#define EP_IN 0x81 #define EP_IN 0x81
@@ -1316,7 +1315,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,
@@ -1390,13 +1389,19 @@ static void m_init_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
fpi_ssm_free(ssm); fpi_ssm_free(ssm);
} }
static int dev_activate(struct fp_img_dev *idev) static int dev_activate(struct fp_img_dev *idev, enum fp_imgdev_state state)
{ {
struct etes603_dev *dev = FP_INSTANCE_DATA(FP_DEV(idev)); struct etes603_dev *dev = FP_INSTANCE_DATA(FP_DEV(idev));
fpi_ssm *ssm; fpi_ssm *ssm;
g_assert(dev); g_assert(dev);
if (state != IMGDEV_STATE_AWAIT_FINGER_ON) {
fp_err("The driver is in an unexpected state: %d.", state);
fpi_imgdev_activate_complete(idev, 1);
return -1;
}
/* Reset info and data */ /* Reset info and data */
dev->is_active = TRUE; dev->is_active = TRUE;
@@ -1472,7 +1477,6 @@ static const struct usb_id id_table[] = {
struct fp_img_driver etes603_driver = { struct fp_img_driver etes603_driver = {
.driver = { .driver = {
.id = ETES603_ID,
.name = FP_COMPONENT, .name = FP_COMPONENT,
.full_name = "EgisTec ES603", .full_name = "EgisTec ES603",
.id_table = id_table, .id_table = id_table,

317
libfprint/drivers/fdu2000.c Normal file
View File

@@ -0,0 +1,317 @@
/*
* Secugen FDU2000 driver for libfprint
* Copyright (C) 2007 Gustavo Chain <g@0xff.cl>
*
* 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 "fdu2000"
#include "drivers_api.h"
#ifndef HAVE_MEMMEM
gpointer
memmem(const gpointer haystack, size_t haystack_len, const gpointer needle, size_t needle_len) {
const gchar *begin;
const char *const last_possible = (const char *) haystack + haystack_len - needle_len;
/* The first occurrence of the empty string is deemed to occur at
* the beginning of the string. */
if (needle_len == 0)
return (void *) haystack;
/* Sanity check, otherwise the loop might search through the whole
* memory. */
if (haystack_len < needle_len)
return NULL;
for (begin = (const char *) haystack; begin <= last_possible; ++begin)
if (begin[0] == ((const char *) needle)[0] &&
!memcmp((const void *) &begin[1],
(const void *) ((const char *) needle + 1),
needle_len - 1))
return (void *) begin;
return NULL;
}
#endif /* HAVE_MEMMEM */
#define EP_IMAGE ( 0x02 | LIBUSB_ENDPOINT_IN )
#define EP_REPLY ( 0x01 | LIBUSB_ENDPOINT_IN )
#define EP_CMD ( 0x01 | LIBUSB_ENDPOINT_OUT )
#define BULK_TIMEOUT 200
/* fdu_req[] index */
typedef enum {
CAPTURE_READY,
CAPTURE_READ,
CAPTURE_END,
LED_OFF,
LED_ON
} req_index;
#define CMD_LEN 2
#define ACK_LEN 8
static const struct fdu2000_req {
const gchar cmd[CMD_LEN]; // Command to send
const gchar ack[ACK_LEN]; // Expected ACK
const guint ack_len; // ACK has variable length
} fdu_req[] = {
/* Capture */
{
.cmd = { 0x00, 0x04 },
.ack = { 0x00, 0x04, 0x01, 0x01 },
.ack_len = 4
},
{
.cmd = { 0x00, 0x01 },
.ack = { 0x00, 0x01, 0x01, 0x01 },
.ack_len = 4
},
{
.cmd = { 0x00, 0x05 },
.ack = { 0x00, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },
.ack_len = 8
},
/* Led */
{
.cmd = { 0x05, 0x00 },
.ack = {},
.ack_len = 0
},
{
.cmd = { 0x05, 0x01 },
.ack = {},
.ack_len = 0
}
};
/*
* Write a command and verify reponse
*/
static gint
bulk_write_safe(libusb_dev_handle *dev, req_index rIndex) {
gchar reponse[ACK_LEN];
gint r;
gchar *cmd = (gchar *)fdu_req[rIndex].cmd;
gchar *ack = (gchar *)fdu_req[rIndex].ack;
gint ack_len = fdu_req[rIndex].ack_len;
struct libusb_bulk_transfer wrmsg = {
.endpoint = EP_CMD,
.data = cmd,
.length = sizeof(cmd),
};
struct libusb_bulk_transfer readmsg = {
.endpoint = EP_REPLY,
.data = reponse,
.length = sizeof(reponse),
};
int trf;
r = libusb_bulk_transfer(dev, &wrmsg, &trf, BULK_TIMEOUT);
if (r < 0)
return r;
if (ack_len == 0)
return 0;
/* Check reply from FP */
r = libusb_bulk_transfer(dev, &readmsg, &trf, BULK_TIMEOUT);
if (r < 0)
return r;
if (!strncmp(ack, reponse, ack_len))
return 0;
fp_err("Expected different ACK from dev");
return 1; /* Error */
}
static gint
capture(struct fp_img_dev *dev, gboolean unconditional,
struct fp_img **ret)
{
#define RAW_IMAGE_WIDTH 398
#define RAW_IMAGE_HEIGTH 301
#define RAW_IMAGE_SIZE (RAW_IMAGE_WIDTH * RAW_IMAGE_HEIGTH)
struct fp_img *img = NULL;
int bytes, r;
const gchar SOF[] = { 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x0c, 0x07 }; // Start of frame
const gchar SOL[] = { 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x0b, 0x06 }; // Start of line + { L L } (L: Line num) (8 nibbles)
gchar *buffer = g_malloc0(RAW_IMAGE_SIZE * 6);
gchar *image;
gchar *p;
guint offset;
struct libusb_bulk_transfer msg = {
.endpoint = EP_IMAGE,
.data = buffer,
.length = RAW_IMAGE_SIZE * 6,
};
image = g_malloc0(RAW_IMAGE_SIZE);
if ((r = bulk_write_safe(fpi_dev_get_usb_dev(FP_DEV(dev)), LED_ON))) {
fp_err("Command: LED_ON");
goto out;
}
if ((r = bulk_write_safe(fpi_dev_get_usb_dev(FP_DEV(dev)), CAPTURE_READY))) {
fp_err("Command: CAPTURE_READY");
goto out;
}
read:
if ((r = bulk_write_safe(fpi_dev_get_usb_dev(FP_DEV(dev)), CAPTURE_READ))) {
fp_err("Command: CAPTURE_READ");
goto out;
}
/* Now we are ready to read from dev */
r = libusb_bulk_transfer(fpi_dev_get_usb_dev(FP_DEV(dev)), &msg, &bytes, BULK_TIMEOUT * 10);
if (r < 0 || bytes < 1)
goto read;
/*
* Find SOF (start of line)
*/
p = memmem(buffer, RAW_IMAGE_SIZE * 6,
(const gpointer)SOF, sizeof SOF);
fp_dbg("Read %d byte/s from dev", bytes);
if (!p)
goto out;
p += sizeof SOF;
int i = 0;
bytes = 0;
while(p) {
if ( i >= RAW_IMAGE_HEIGTH )
break;
offset = p - buffer;
p = memmem(p, (RAW_IMAGE_SIZE * 6) - (offset),
(const gpointer)SOL, sizeof SOL);
if (p) {
p += sizeof SOL + 4;
int j;
for (j = 0; j < RAW_IMAGE_WIDTH; j++) {
/*
* Convert from 4 to 8 bits
* The SECUGEN-FDU2000 has 4 lines of data, so we need to join 2 bytes into 1
*/
*(image + bytes + j) = *(p + (j * 2) + 0) << 4 & 0xf0;
*(image + bytes + j) |= *(p + (j * 2) + 1) & 0x0f;
}
p += RAW_IMAGE_WIDTH * 2;
bytes += RAW_IMAGE_WIDTH;
i++;
}
}
if ((r = bulk_write_safe(fpi_dev_get_usb_dev(FP_DEV(dev)), CAPTURE_END))) {
fp_err("Command: CAPTURE_END");
goto out;
}
if ((r = bulk_write_safe(fpi_dev_get_usb_dev(FP_DEV(dev)), LED_OFF))) {
fp_err("Command: LED_OFF");
goto out;
}
img = fpi_img_new_for_imgdev(dev);
memcpy(img->data, image, RAW_IMAGE_SIZE);
img->flags = FP_IMG_COLORS_INVERTED | FP_IMG_V_FLIPPED | FP_IMG_H_FLIPPED;
*ret = img;
out:
g_free(buffer);
g_free(image);
return r;
}
static
gint dev_init(struct fp_img_dev *dev, unsigned long driver_data)
{
gint r;
//if ( (r = usb_set_configuration(fpi_dev_get_usb_dev(FP_DEV(dev)), 1)) < 0 )
// goto out;
if ( (r = libusb_claim_interface(fpi_dev_get_usb_dev(FP_DEV(dev)), 0)) < 0 ) {
fp_err("could not claim interface 0: %s", libusb_error_name(r));
return r;
}
//if ( (r = usb_set_altinterface(fpi_dev_get_usb_dev(FP_DEV(dev)), 1)) < 0 )
// goto out;
//if ( (r = usb_clear_halt(fpi_dev_get_usb_dev(FP_DEV(dev)), EP_CMD)) < 0 )
// goto out;
/* Make sure sensor mode is not capture_{ready|read} */
if ((r = bulk_write_safe(fpi_dev_get_usb_dev(FP_DEV(dev)), CAPTURE_END))) {
fp_err("Command: CAPTURE_END");
goto out;
}
if ((r = bulk_write_safe(fpi_dev_get_usb_dev(FP_DEV(dev)), LED_OFF))) {
fp_err("Command: LED_OFF");
goto out;
}
return 0;
out:
fp_err("could not init dev");
return r;
}
static
void dev_exit(struct fp_img_dev *dev)
{
if (bulk_write_safe(fpi_dev_get_usb_dev(FP_DEV(dev)), CAPTURE_END))
fp_err("Command: CAPTURE_END");
libusb_release_interface(fpi_dev_get_usb_dev(FP_DEV(dev)), 0);
}
static const struct usb_id id_table[] = {
{ .vendor = 0x1162, .product = 0x0300 },
{ 0, 0, 0, },
};
struct fp_img_driver fdu2000_driver = {
.driver = {
.name = FP_COMPONENT,
.full_name = "Secugen FDU 2000",
.id_table = id_table,
.scan_type = FP_SCAN_TYPE_PRESS,
},
.img_height = RAW_IMAGE_HEIGTH,
.img_width = RAW_IMAGE_WIDTH,
.bz3_threshold = 23,
.init = dev_init,
.exit = dev_exit,
.capture = capture,
};

View File

@@ -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;
@@ -1268,7 +1268,7 @@ static void initsm_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
fpi_ssm_start(sdev->loopsm, loopsm_complete); fpi_ssm_start(sdev->loopsm, loopsm_complete);
} }
static int dev_activate(struct fp_img_dev *dev) static int dev_activate(struct fp_img_dev *dev, enum fp_imgdev_state state)
{ {
struct sonly_dev *sdev = FP_INSTANCE_DATA(FP_DEV(dev)); struct sonly_dev *sdev = FP_INSTANCE_DATA(FP_DEV(dev));
fpi_ssm *ssm = NULL; fpi_ssm *ssm = NULL;
@@ -1345,7 +1345,6 @@ static const struct usb_id id_table[] = {
struct fp_img_driver upeksonly_driver = { struct fp_img_driver upeksonly_driver = {
.driver = { .driver = {
.id = UPEKSONLY_ID,
.name = FP_COMPONENT, .name = FP_COMPONENT,
.full_name = "UPEK TouchStrip Sensor-Only", .full_name = "UPEK TouchStrip Sensor-Only",
.id_table = id_table, .id_table = id_table,

View File

@@ -377,7 +377,7 @@ static void start_capture(struct fp_img_dev *dev)
fpi_ssm_start(ssm, capture_sm_complete); fpi_ssm_start(ssm, capture_sm_complete);
} }
static int dev_activate(struct fp_img_dev *dev) static int dev_activate(struct fp_img_dev *dev, enum fp_imgdev_state state)
{ {
struct upektc_dev *upekdev = FP_INSTANCE_DATA(FP_DEV(dev)); struct upektc_dev *upekdev = FP_INSTANCE_DATA(FP_DEV(dev));
fpi_ssm *ssm = fpi_ssm_new(FP_DEV(dev), activate_run_state, fpi_ssm *ssm = fpi_ssm_new(FP_DEV(dev), activate_run_state,
@@ -460,7 +460,6 @@ static const struct usb_id id_table[] = {
struct fp_img_driver upektc_driver = { struct fp_img_driver upektc_driver = {
.driver = { .driver = {
.id = UPEKTC_ID,
.name = FP_COMPONENT, .name = FP_COMPONENT,
.full_name = "UPEK TouchChip/Eikon Touch 300", .full_name = "UPEK TouchChip/Eikon Touch 300",
.id_table = id_table, .id_table = id_table,

View File

@@ -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;
} }
@@ -567,7 +567,7 @@ static void activate_sm_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_d
start_capture(dev); start_capture(dev);
} }
static int dev_activate(struct fp_img_dev *dev) static int dev_activate(struct fp_img_dev *dev, enum fp_imgdev_state state)
{ {
struct upektc_img_dev *upekdev = FP_INSTANCE_DATA(FP_DEV(dev)); struct upektc_img_dev *upekdev = FP_INSTANCE_DATA(FP_DEV(dev));
fpi_ssm *ssm = fpi_ssm_new(FP_DEV(dev), activate_run_state, fpi_ssm *ssm = fpi_ssm_new(FP_DEV(dev), activate_run_state,
@@ -628,7 +628,6 @@ static const struct usb_id id_table[] = {
struct fp_img_driver upektc_img_driver = { struct fp_img_driver upektc_img_driver = {
.driver = { .driver = {
.id = UPEKTC_IMG_ID,
.name = FP_COMPONENT, .name = FP_COMPONENT,
.full_name = "Upek TouchChip Fingerprint Coprocessor", .full_name = "Upek TouchChip Fingerprint Coprocessor",
.id_table = id_table, .id_table = id_table,

View File

@@ -1421,7 +1421,6 @@ static const struct usb_id id_table[] = {
}; };
struct fp_driver upekts_driver = { struct fp_driver upekts_driver = {
.id = UPEKTS_ID,
.name = FP_COMPONENT, .name = FP_COMPONENT,
.full_name = "UPEK TouchStrip", .full_name = "UPEK TouchStrip",
.id_table = id_table, .id_table = id_table,

View File

@@ -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);
} }
@@ -1161,10 +1161,20 @@ static void activate_initsm_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *us
int r = fpi_ssm_get_error(ssm); int r = fpi_ssm_get_error(ssm);
fpi_ssm_free(ssm); fpi_ssm_free(ssm);
if (r) {
fpi_imgdev_activate_complete(dev, r);
return;
}
r = execute_state_change(dev);
fpi_imgdev_activate_complete(dev, r); fpi_imgdev_activate_complete(dev, r);
} }
static int dev_activate(struct fp_img_dev *dev) /* FIXME: having state parameter here is kinda useless, will we ever
* see a scenario where the parameter is useful so early on in the activation
* process? asynchronity means that it'll only be used in a later function
* call. */
static int dev_activate(struct fp_img_dev *dev, enum fp_imgdev_state state)
{ {
struct uru4k_dev *urudev = FP_INSTANCE_DATA(FP_DEV(dev)); struct uru4k_dev *urudev = FP_INSTANCE_DATA(FP_DEV(dev));
fpi_ssm *ssm; fpi_ssm *ssm;
@@ -1175,6 +1185,7 @@ static int dev_activate(struct fp_img_dev *dev)
return r; return r;
urudev->scanpwr_irq_timeouts = 0; urudev->scanpwr_irq_timeouts = 0;
urudev->activate_state = state;
ssm = fpi_ssm_new(FP_DEV(dev), init_run_state, INIT_NUM_STATES, dev); ssm = fpi_ssm_new(FP_DEV(dev), init_run_state, INIT_NUM_STATES, dev);
fpi_ssm_start(ssm, activate_initsm_complete); fpi_ssm_start(ssm, activate_initsm_complete);
return 0; return 0;
@@ -1417,7 +1428,6 @@ static const struct usb_id id_table[] = {
struct fp_img_driver uru4000_driver = { struct fp_img_driver uru4000_driver = {
.driver = { .driver = {
.id = URU4000_ID,
.name = FP_COMPONENT, .name = FP_COMPONENT,
.full_name = "Digital Persona U.are.U 4000/4000B/4500", .full_name = "Digital Persona U.are.U 4000/4000B/4500",
.id_table = id_table, .id_table = id_table,

View File

@@ -302,7 +302,7 @@ static void loopsm_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
fpi_imgdev_deactivate_complete(dev); fpi_imgdev_deactivate_complete(dev);
} }
static int dev_activate(struct fp_img_dev *dev) static int dev_activate(struct fp_img_dev *dev, enum fp_imgdev_state state)
{ {
struct v5s_dev *vdev = FP_INSTANCE_DATA(FP_DEV(dev)); struct v5s_dev *vdev = FP_INSTANCE_DATA(FP_DEV(dev));
fpi_ssm *ssm = fpi_ssm_new(FP_DEV(dev), loop_run_state, fpi_ssm *ssm = fpi_ssm_new(FP_DEV(dev), loop_run_state,
@@ -357,7 +357,6 @@ static const struct usb_id id_table[] = {
struct fp_img_driver vcom5s_driver = { struct fp_img_driver vcom5s_driver = {
.driver = { .driver = {
.id = VCOM5S_ID,
.name = FP_COMPONENT, .name = FP_COMPONENT,
.full_name = "Veridicom 5thSense", .full_name = "Veridicom 5thSense",
.id_table = id_table, .id_table = id_table,

View File

@@ -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,
@@ -684,7 +684,7 @@ static void dev_activate_callback(fpi_ssm *ssm, struct fp_dev *_dev, void *user_
} }
/* Activate device */ /* Activate device */
static int dev_activate(struct fp_img_dev *idev) static int dev_activate(struct fp_img_dev *idev, enum fp_imgdev_state state)
{ {
struct vfs_dev_t *vdev = FP_INSTANCE_DATA(FP_DEV(idev)); struct vfs_dev_t *vdev = FP_INSTANCE_DATA(FP_DEV(idev));
@@ -770,7 +770,6 @@ static const struct usb_id id_table[] = {
struct fp_img_driver vfs0050_driver = { struct fp_img_driver vfs0050_driver = {
/* Driver specification */ /* Driver specification */
.driver = { .driver = {
.id = VFS0050_ID,
.name = FP_COMPONENT, .name = FP_COMPONENT,
.full_name = "Validity VFS0050", .full_name = "Validity VFS0050",
.id_table = id_table, .id_table = id_table,

View File

@@ -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;
@@ -1424,7 +1424,7 @@ static void m_init_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
} }
/* Activate device */ /* Activate device */
static int dev_activate(struct fp_img_dev *dev) static int dev_activate(struct fp_img_dev *dev, enum fp_imgdev_state state)
{ {
struct vfs101_dev *vdev = FP_INSTANCE_DATA(FP_DEV(dev)); struct vfs101_dev *vdev = FP_INSTANCE_DATA(FP_DEV(dev));
fpi_ssm *ssm; fpi_ssm *ssm;
@@ -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();
@@ -1526,7 +1526,6 @@ struct fp_img_driver vfs101_driver =
/* Driver specification */ /* Driver specification */
.driver = .driver =
{ {
.id = VFS101_ID,
.name = FP_COMPONENT, .name = FP_COMPONENT,
.full_name = "Validity VFS101", .full_name = "Validity VFS101",
.id_table = id_table, .id_table = id_table,

View File

@@ -191,7 +191,7 @@ static void m_init_complete(fpi_ssm *ssm, struct fp_dev *_dev, void *user_data)
} }
/* Activate device */ /* Activate device */
static int dev_activate(struct fp_img_dev *dev) static int dev_activate(struct fp_img_dev *dev, enum fp_imgdev_state state)
{ {
fpi_ssm *ssm; fpi_ssm *ssm;
@@ -268,7 +268,6 @@ struct fp_img_driver vfs301_driver =
/* Driver specification */ /* Driver specification */
.driver = .driver =
{ {
.id = VFS301_ID,
.name = FP_COMPONENT, .name = FP_COMPONENT,
.full_name = "Validity VFS301", .full_name = "Validity VFS301",
.id_table = id_table, .id_table = id_table,

View File

@@ -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];

View File

@@ -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?

View File

@@ -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);
memmove(data->lastline, linebuf, VFS5011_LINE_SIZE); g_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",
@@ -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);
} }
@@ -846,7 +846,7 @@ static void start_scan(struct fp_img_dev *dev)
fp_dbg("ssm done, getting out"); fp_dbg("ssm done, getting out");
} }
static int dev_activate(struct fp_img_dev *dev) static int dev_activate(struct fp_img_dev *dev, enum fp_imgdev_state state)
{ {
struct vfs5011_data *data; struct vfs5011_data *data;
@@ -887,7 +887,6 @@ static const struct usb_id id_table[] = {
struct fp_img_driver vfs5011_driver = { struct fp_img_driver vfs5011_driver = {
.driver = { .driver = {
.id = VFS5011_ID,
.name = "vfs5011", .name = "vfs5011",
.full_name = "Validity VFS5011", .full_name = "Validity VFS5011",
.id_table = id_table, .id_table = id_table,

View File

@@ -34,6 +34,5 @@
#include "fpi-usb.h" #include "fpi-usb.h"
#include "fpi-img.h" #include "fpi-img.h"
#include "fpi-assembling.h" #include "fpi-assembling.h"
#include "drivers/driver_ids.h"
#endif #endif

View File

@@ -35,7 +35,6 @@
#include "fpi-dev-img.h" #include "fpi-dev-img.h"
#include "fpi-data.h" #include "fpi-data.h"
#include "fpi-img.h" #include "fpi-img.h"
#include "drivers/driver_ids.h"
/* Global variables */ /* Global variables */
extern libusb_context *fpi_usb_ctx; extern libusb_context *fpi_usb_ctx;
@@ -145,8 +144,6 @@ struct fp_img_dev {
size_t identify_match_offset; size_t identify_match_offset;
}; };
/* fp_driver structure definition */
/* fp_img_driver structure definition */ /* fp_img_driver structure definition */
#define container_of(ptr, type, member) ({ \ #define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \ const typeof( ((type *)0)->member ) *__mptr = (ptr); \

View File

@@ -365,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;
memmove(sortbuf, data+i1, (i2-i1+1)*sizeof(int)); g_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];
} }
@@ -480,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;
memmove(img->data, output, ctx->line_width * line_ind); g_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;

View File

@@ -387,21 +387,9 @@ 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);
@@ -523,21 +511,9 @@ 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);

View File

@@ -137,10 +137,13 @@ GSList *opened_devices = NULL;
static GSList *registered_drivers = NULL; static GSList *registered_drivers = NULL;
#define DRV_ID(drv) g_str_hash(drv->name)
static void register_driver(struct fp_driver *drv) static void register_driver(struct fp_driver *drv)
{ {
if (drv->id == 0) { if (drv->name == NULL ||
fp_err("not registering driver %s: driver ID is 0", drv->name); strlen(drv->name) <= 2) {
fp_err("not registering driver %s, name is too short or absent", drv->name);
return; return;
} }
registered_drivers = g_slist_prepend(registered_drivers, (gpointer) drv); registered_drivers = g_slist_prepend(registered_drivers, (gpointer) drv);
@@ -411,7 +414,7 @@ API_EXPORTED int fp_dscv_dev_supports_print_data(struct fp_dscv_dev *dev,
g_return_val_if_fail(dev, 0); g_return_val_if_fail(dev, 0);
g_return_val_if_fail(print, 0); g_return_val_if_fail(print, 0);
return fpi_print_data_compatible(dev->drv->id, dev->devtype, return fpi_print_data_compatible(DRV_ID(dev->drv), dev->devtype,
fpi_driver_get_data_type(dev->drv), print->driver_id, print->devtype, fpi_driver_get_data_type(dev->drv), print->driver_id, print->devtype,
print->type); print->type);
} }
@@ -434,7 +437,7 @@ API_EXPORTED int fp_dscv_dev_supports_dscv_print(struct fp_dscv_dev *dev,
g_return_val_if_fail(dev, 0); g_return_val_if_fail(dev, 0);
g_return_val_if_fail(print, 0); g_return_val_if_fail(print, 0);
return fpi_print_data_compatible(dev->drv->id, dev->devtype, 0, return fpi_print_data_compatible(DRV_ID(dev->drv), dev->devtype, 0,
print->driver_id, print->devtype, 0); print->driver_id, print->devtype, 0);
} }
@@ -559,7 +562,7 @@ API_EXPORTED int fp_dev_supports_print_data(struct fp_dev *dev,
g_return_val_if_fail(dev, 0); g_return_val_if_fail(dev, 0);
g_return_val_if_fail(data, 0); g_return_val_if_fail(data, 0);
return fpi_print_data_compatible(dev->drv->id, dev->devtype, return fpi_print_data_compatible(DRV_ID(dev->drv), dev->devtype,
fpi_driver_get_data_type(dev->drv), data->driver_id, data->devtype, fpi_driver_get_data_type(dev->drv), data->driver_id, data->devtype,
data->type); data->type);
} }
@@ -582,7 +585,7 @@ API_EXPORTED int fp_dev_supports_dscv_print(struct fp_dev *dev,
g_return_val_if_fail(dev, 0); g_return_val_if_fail(dev, 0);
g_return_val_if_fail(print, 0); g_return_val_if_fail(print, 0);
return fpi_print_data_compatible(dev->drv->id, dev->devtype, return fpi_print_data_compatible(DRV_ID(dev->drv), dev->devtype,
0, print->driver_id, print->devtype, 0); 0, print->driver_id, print->devtype, 0);
} }
@@ -628,7 +631,7 @@ API_EXPORTED uint16_t fp_driver_get_driver_id(struct fp_driver *drv)
{ {
g_return_val_if_fail(drv, 0); g_return_val_if_fail(drv, 0);
return drv->id; return DRV_ID(drv);
} }
/** /**

View File

@@ -68,7 +68,6 @@ enum fp_driver_type {
}; };
struct fp_driver { struct fp_driver {
const uint16_t id;
const char *name; const char *name;
const char *full_name; const char *full_name;
const struct usb_id * const id_table; const struct usb_id * const id_table;
@@ -110,7 +109,7 @@ struct fp_img_driver {
/* Device operations */ /* Device operations */
int (*open)(struct fp_img_dev *dev, unsigned long driver_data); int (*open)(struct fp_img_dev *dev, unsigned long driver_data);
void (*close)(struct fp_img_dev *dev); void (*close)(struct fp_img_dev *dev);
int (*activate)(struct fp_img_dev *dev); int (*activate)(struct fp_img_dev *dev, enum fp_imgdev_state state);
int (*change_state)(struct fp_img_dev *dev, enum fp_imgdev_state state); int (*change_state)(struct fp_img_dev *dev, enum fp_imgdev_state state);
void (*deactivate)(struct fp_img_dev *dev); void (*deactivate)(struct fp_img_dev *dev);
}; };

View File

@@ -148,7 +148,7 @@ struct fp_print_data_item *fpi_print_data_item_new(size_t length)
struct fp_print_data *fpi_print_data_new(struct fp_dev *dev) struct fp_print_data *fpi_print_data_new(struct fp_dev *dev)
{ {
return print_data_new(dev->drv->id, dev->devtype, return print_data_new(fp_driver_get_driver_id(dev->drv), dev->devtype,
fpi_driver_get_data_type(dev->drv)); fpi_driver_get_data_type(dev->drv));
} }
@@ -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);
@@ -349,7 +349,7 @@ static char *__get_path_to_print(uint16_t driver_id, uint32_t devtype,
static char *get_path_to_print(struct fp_dev *dev, enum fp_finger finger) static char *get_path_to_print(struct fp_dev *dev, enum fp_finger finger)
{ {
return __get_path_to_print(dev->drv->id, dev->devtype, finger); return __get_path_to_print(fp_driver_get_driver_id(dev->drv), dev->devtype, finger);
} }
/** /**

View File

@@ -485,15 +485,9 @@ 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();
action = imgdev->action; switch (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;
@@ -510,6 +504,9 @@ 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)
@@ -536,14 +533,14 @@ int fpi_imgdev_get_img_height(struct fp_img_dev *imgdev)
return height; return height;
} }
static int dev_activate(struct fp_img_dev *imgdev) static int dev_activate(struct fp_img_dev *imgdev, enum fp_imgdev_state state)
{ {
struct fp_driver *drv = FP_DEV(imgdev)->drv; struct fp_driver *drv = FP_DEV(imgdev)->drv;
struct fp_img_driver *imgdrv = fpi_driver_to_img_driver(drv); struct fp_img_driver *imgdrv = fpi_driver_to_img_driver(drv);
if (!imgdrv->activate) if (!imgdrv->activate)
return 0; return 0;
return imgdrv->activate(imgdev); return imgdrv->activate(imgdev, state);
} }
static void dev_deactivate(struct fp_img_dev *imgdev) static void dev_deactivate(struct fp_img_dev *imgdev)
@@ -565,7 +562,7 @@ static int generic_acquire_start(struct fp_dev *dev, int action)
imgdev->action_state = IMG_ACQUIRE_STATE_ACTIVATING; imgdev->action_state = IMG_ACQUIRE_STATE_ACTIVATING;
imgdev->enroll_stage = 0; imgdev->enroll_stage = 0;
r = dev_activate(imgdev); r = dev_activate(imgdev, IMGDEV_STATE_AWAIT_FINGER_ON);
if (r < 0) if (r < 0)
fp_err("activation failed with error %d", r); fp_err("activation failed with error %d", r);

View File

@@ -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));

View File

@@ -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

View File

@@ -97,6 +97,9 @@ foreach driver: drivers
aeslib = true aeslib = true
aes3k = true aes3k = true
endif endif
if driver == 'fdu2000'
drivers_sources += [ 'drivers/fdu2000.c' ]
endif
if driver == 'vcom5s' if driver == 'vcom5s'
drivers_sources += [ 'drivers/vcom5s.c' ] drivers_sources += [ 'drivers/vcom5s.c' ]
endif endif

View File

@@ -1,5 +1,5 @@
project('libfprint', [ 'c', 'cpp' ], project('libfprint', [ 'c', 'cpp' ],
version: '1.0', version: '0.99.0',
license: 'LGPLv2.1+', license: 'LGPLv2.1+',
default_options: [ default_options: [
'buildtype=debugoptimized', 'buildtype=debugoptimized',
@@ -27,9 +27,7 @@ common_cflags = cc.get_supported_arguments([
'-Wstrict-prototypes', '-Wstrict-prototypes',
'-Werror-implicit-function-declaration', '-Werror-implicit-function-declaration',
'-Wno-pointer-sign', '-Wno-pointer-sign',
'-Wshadow', '-Wshadow'
'-DGLIB_VERSION_MIN_REQUIRED=GLIB_VERSION_2_50',
'-DGLIB_VERSION_MAX_ALLOWED=GLIB_VERSION_2_50',
]) ])
# maintaining compatibility with the previous libtool versioning # maintaining compatibility with the previous libtool versioning
@@ -41,7 +39,7 @@ revision = 0
libversion = '@0@.@1@.@2@'.format(soversion, current, revision) libversion = '@0@.@1@.@2@'.format(soversion, current, revision)
# Dependencies # Dependencies
glib_dep = dependency('glib-2.0', version: '>= 2.50') glib_dep = dependency('glib-2.0', version: '>= 2.28')
libusb_dep = dependency('libusb-1.0', version: '>= 0.9.1') libusb_dep = dependency('libusb-1.0', version: '>= 0.9.1')
mathlib_dep = cc.find_library('m', required: false) mathlib_dep = cc.find_library('m', required: false)