Compare commits

..

1 Commits

Author SHA1 Message Date
Benjamin Berg
cb56ddba5b virtual-image: Open window for race during deactivation
This is in order to test corner cases in fprintd.
2020-10-01 14:16:22 +02:00
65 changed files with 823 additions and 3301 deletions

View File

@@ -1,10 +0,0 @@
# The commits that did automated reformatting. You can ignore them
# during git-blame with `--ignore-rev` or `--ignore-revs-file`.
#
# $ git config --add 'blame.ignoreRevsFile' '.git-blame-ignore-revs'
#
d1fb1e26f3b79e54febc94496c1184763cf2af3d
e4f9935706be4c0e3253afe251c182019ff7ccef
65e602d8c72baa7020efb62d10bf28e621feb05d
4115ae7ced77d392ee11ea55212206d9404356f0

59
NEWS
View File

@@ -1,65 +1,6 @@
This file lists notable changes in each release. For the full history of all
changes, see ChangeLog.
2020-12-01: v1.90.7 release
Highlights:
* vfs5011: Fix possible use-after-free
* goodixmoc: Add two new PIDs (0x63AC, 0x639C)
* goodixmoc: Support finger status API
* synaptics: Only identify within provided prints
* synaptics: Reject devices with old firmware during probe (#239)
2020-12-01: v1.90.6 release
This release is primarily a bugfix release for some older issues.
The major change is that fp_print_deserialize will now correctly return a
sunken reference rather than a floating one. Most API users will have
assumed this was true, and issues could happen at a later point.
If any API user worked around this libfprint bug, they will now leak the
returned print.
Highlights:
* Object reference management fixes for FpPrint and identify
* Fixed issues that caused problem on non-x86 machines (#236)
* Fix building with older GLib versions
* synaptics: Support PID 00e7
* goodix: Fix issue with long USB packages
2020-12-01: v1.90.5 release
The 1.90.4 release caused a major regression, as it included a USB hub in
UDEV the autosupend rule list.
Highlights:
* Remove USB hub from udev autosupend rules
* synaptics: Add PID 0x00c9 which is used in some HP laptops
2020-11-27: v1.90.4 release
This release contains a number of important bugfixes. On the feature side,
the USB hotplug support was improved. A lot of drivers received fixes and
improvements.
Highlights:
* Work around GUsb cancellation issue
* Redefine internal image device state machine for more robustness
* Add public finger-status reporting to FpDevice
* Rework device removal API to be convenient (#330)
* Enable powersave for unsupported USB devices
* Improvements to examples
* synaptics: Support identify operation
* synaptics: Fix possible crash when the interrupt transfer is resubmitted
* synaptics: Add support for PIDs 0x00f9, 0x00fc and 0x00c2
* elan: Add PID 0x0c4d to supported device list
* aes3k: Fix driver and add CI test (#306)
* uru4000: Fix reference counting of image transfer
* vfs301: Fix driver and add CI test (#320)
2020-06-08: v1.90.3 release
This release mostly contains support for a number of new match-on-chip

View File

@@ -91,6 +91,8 @@ FP_TYPE_PRINT
FpFinger
FpPrint
fp_print_new
fp_print_new_from_data
fp_print_to_data
fp_print_get_driver
fp_print_get_device_id
fp_print_get_device_stored

View File

@@ -76,19 +76,15 @@ on_enroll_completed (FpDevice *dev, GAsyncResult *res, void *user_data)
{
enroll_data->ret_value = EXIT_SUCCESS;
if (fp_device_has_storage (dev))
g_debug ("Device has storage, saving a print reference locally");
else
g_debug ("Device has not storage, saving print only locally");
/* Even if the device has storage, it may not be able to save all the
* metadata that the print contains, so we can always save a local copy
* containing the handle to the device print */
int r = print_data_save (print, enroll_data->finger);
if (r < 0)
if (!fp_device_has_storage (dev))
{
g_warning ("Data save failed, code %d", r);
enroll_data->ret_value = EXIT_FAILURE;
g_debug ("Device has not storage, saving locally");
int r = print_data_save (print, enroll_data->finger);
if (r < 0)
{
g_warning ("Data save failed, code %d", r);
enroll_data->ret_value = EXIT_FAILURE;
}
}
}
else

View File

@@ -1,319 +0,0 @@
/*
* Example fingerprint verification program, which verifies the
* finger which has been previously enrolled to disk.
* Copyright (C) 2020 Marco Trevisan <marco.trevisan@canonical.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#define FP_COMPONENT "example-identify"
#include <stdio.h>
#include <libfprint/fprint.h>
#include <glib-unix.h>
#include "storage.h"
#include "utilities.h"
typedef struct _IdentifyData
{
GMainLoop *loop;
GCancellable *cancellable;
unsigned int sigint_handler;
int ret_value;
} IdentifyData;
static void
identify_data_free (IdentifyData *identify_data)
{
g_clear_handle_id (&identify_data->sigint_handler, g_source_remove);
g_clear_object (&identify_data->cancellable);
g_main_loop_unref (identify_data->loop);
g_free (identify_data);
}
G_DEFINE_AUTOPTR_CLEANUP_FUNC (IdentifyData, identify_data_free)
static void
on_device_closed (FpDevice *dev, GAsyncResult *res, void *user_data)
{
IdentifyData *identify_data = user_data;
g_autoptr(GError) error = NULL;
fp_device_close_finish (dev, res, &error);
if (error)
g_warning ("Failed closing device %s", error->message);
g_main_loop_quit (identify_data->loop);
}
static void
identify_quit (FpDevice *dev,
IdentifyData *identify_data)
{
if (!fp_device_is_open (dev))
{
g_main_loop_quit (identify_data->loop);
return;
}
fp_device_close (dev, NULL, (GAsyncReadyCallback) on_device_closed, identify_data);
}
static void start_identification (FpDevice *dev,
IdentifyData *identify_data);
static void
on_identify_completed (FpDevice *dev, GAsyncResult *res, void *user_data)
{
IdentifyData *identify_data = user_data;
g_autoptr(FpPrint) print = NULL;
g_autoptr(FpPrint) match = NULL;
g_autoptr(GError) error = NULL;
char buffer[20];
if (!fp_device_identify_finish (dev, res, &match, &print, &error))
{
g_warning ("Failed to identify print: %s", error->message);
identify_data->ret_value = EXIT_FAILURE;
if (error->domain != FP_DEVICE_RETRY)
{
identify_quit (dev, identify_data);
return;
}
}
g_print ("Identify again? [Y/n]? ");
if (fgets (buffer, sizeof (buffer), stdin) &&
(buffer[0] == 'Y' || buffer[0] == 'y' || buffer[0] == '\n'))
{
start_identification (dev, identify_data);
return;
}
identify_quit (dev, identify_data);
}
static FpPrint *
get_stored_print (FpDevice *dev, FpPrint *print)
{
g_autoptr(GPtrArray) gallery = gallery_data_load (dev);
guint index;
if (g_ptr_array_find_with_equal_func (gallery, print,
(GEqualFunc) fp_print_equal,
&index))
return g_object_ref (g_ptr_array_index (gallery, index));
return NULL;
}
static void
on_identify_cb (FpDevice *dev, FpPrint *match, FpPrint *print,
gpointer user_data, GError *error)
{
IdentifyData *identify_data = user_data;
if (error)
{
g_warning ("Identify report: No finger matched, retry error reported: %s",
error->message);
return;
}
if (print && fp_print_get_image (print) &&
print_image_save (print, "identify.pgm"))
g_print ("Print image saved as identify.pgm\n");
if (match)
{
g_autoptr(FpPrint) matched_print = g_object_ref (match);
char date_str[128] = {};
identify_data->ret_value = EXIT_SUCCESS;
if (fp_print_get_device_stored (match))
{
FpPrint *stored_print = get_stored_print (dev, match);
if (stored_print)
matched_print = g_steal_pointer (&stored_print);
}
if (fp_print_get_enroll_date (matched_print))
g_date_strftime (date_str, G_N_ELEMENTS (date_str), "%Y-%m-%d\0",
fp_print_get_enroll_date (matched_print));
else
strcpy (date_str, "<unknown>");
g_debug ("Identify report: device %s matched finger %s successfully "
"with print '%s', enrolled on date %s by user %s",
fp_device_get_name (dev),
finger_to_string (fp_print_get_finger (matched_print)),
fp_print_get_description (matched_print), date_str,
fp_print_get_username (matched_print));
g_print ("IDENTIFIED!\n");
}
else
{
g_debug ("Identification report: No finger matched");
g_print ("NOT IDENTIFIED!\n");
}
}
static void
on_list_completed (FpDevice *dev, GAsyncResult *res, gpointer user_data)
{
IdentifyData *identify_data = user_data;
g_autoptr(GPtrArray) gallery = NULL;
g_autoptr(GError) error = NULL;
gallery = fp_device_list_prints_finish (dev, res, &error);
if (!error)
{
if (!gallery->len)
{
g_warning ("No prints saved on device");
identify_quit (dev, identify_data);
return;
}
g_debug ("Identifying with %u prints in gallery", gallery->len);
fp_device_identify (dev, gallery, identify_data->cancellable,
on_identify_cb, identify_data, NULL,
(GAsyncReadyCallback) on_identify_completed,
identify_data);
}
else
{
g_warning ("Loading prints failed with error %s", error->message);
identify_quit (dev, identify_data);
}
}
static void
start_identification (FpDevice *dev, IdentifyData *identify_data)
{
if (fp_device_has_storage (dev))
{
g_print ("Creating finger template, using device storage...\n");
fp_device_list_prints (dev, NULL,
(GAsyncReadyCallback) on_list_completed,
identify_data);
}
else
{
g_autoptr(GPtrArray) gallery = gallery_data_load (dev);
if (!gallery)
{
identify_quit (dev, identify_data);
return;
}
g_print ("Gallery loaded. Time to identify!\n");
fp_device_identify (dev, gallery, identify_data->cancellable,
on_identify_cb, identify_data, NULL,
(GAsyncReadyCallback) on_identify_completed,
identify_data);
}
}
static void
on_device_opened (FpDevice *dev, GAsyncResult *res, void *user_data)
{
IdentifyData *identify_data = user_data;
g_autoptr(GError) error = NULL;
if (!fp_device_open_finish (dev, res, &error))
{
g_warning ("Failed to open device: %s", error->message);
identify_quit (dev, identify_data);
return;
}
g_print ("Opened device. ");
start_identification (dev, identify_data);
}
static gboolean
sigint_cb (void *user_data)
{
IdentifyData *identify_data = user_data;
g_cancellable_cancel (identify_data->cancellable);
return G_SOURCE_CONTINUE;
}
int
main (void)
{
g_autoptr(FpContext) ctx = NULL;
g_autoptr(IdentifyData) identify_data = NULL;
GPtrArray *devices;
FpDevice *dev;
setenv ("G_MESSAGES_DEBUG", "all", 0);
setenv ("LIBUSB_DEBUG", "3", 0);
ctx = fp_context_new ();
devices = fp_context_get_devices (ctx);
if (!devices)
{
g_warning ("Impossible to get devices");
return EXIT_FAILURE;
}
dev = discover_device (devices);
if (!dev)
{
g_warning ("No devices detected.");
return EXIT_FAILURE;
}
if (!fp_device_supports_identify (dev))
{
g_warning ("Device %s does not support identification.",
fp_device_get_name (dev));
return EXIT_FAILURE;
}
identify_data = g_new0 (IdentifyData, 1);
identify_data->ret_value = EXIT_FAILURE;
identify_data->loop = g_main_loop_new (NULL, FALSE);
identify_data->cancellable = g_cancellable_new ();
identify_data->sigint_handler = g_unix_signal_add_full (G_PRIORITY_HIGH,
SIGINT,
sigint_cb,
identify_data,
NULL);
fp_device_open (dev, identify_data->cancellable,
(GAsyncReadyCallback) on_device_opened,
identify_data);
g_main_loop_run (identify_data->loop);
return identify_data->ret_value;
}

View File

@@ -1,12 +1,5 @@
examples = [
'enroll',
'identify',
'img-capture',
'manage-prints',
'verify',
]
examples = [ 'enroll', 'verify', 'manage-prints', 'img-capture' ]
foreach example: examples
executable(example,
[ example + '.c', 'storage.c', 'utilities.c' ],

View File

@@ -2,7 +2,7 @@
* Trivial storage driver for example programs
*
* Copyright (C) 2019 Benjamin Berg <bberg@redhat.com>
* Copyright (C) 2019-2020 Marco Trevisan <marco.trevisan@canonical.com>
* Copyright (C) 2019 Marco Trevisan <marco.trevisan@canonical.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -160,52 +160,6 @@ print_data_load (FpDevice *dev, FpFinger finger)
return NULL;
}
GPtrArray *
gallery_data_load (FpDevice *dev)
{
g_autoptr(GVariantDict) dict = NULL;
g_autoptr(GVariant) dict_variant = NULL;
g_autofree char *dev_prefix = NULL;
GPtrArray *gallery;
const char *driver;
const char *dev_id;
GVariantIter iter;
GVariant *value;
gchar *key;
gallery = g_ptr_array_new_with_free_func (g_object_unref);
dict = load_data ();
dict_variant = g_variant_dict_end (dict);
driver = fp_device_get_driver (dev);
dev_id = fp_device_get_device_id (dev);
dev_prefix = g_strdup_printf ("%s/%s/", driver, dev_id);
g_variant_iter_init (&iter, dict_variant);
while (g_variant_iter_loop (&iter, "{sv}", &key, &value))
{
FpPrint *print;
const guchar *stored_data;
g_autoptr(GError) error = NULL;
gsize stored_len;
if (!g_str_has_prefix (key, dev_prefix))
continue;
stored_data = (const guchar *) g_variant_get_fixed_array (value, &stored_len, 1);
print = fp_print_deserialize (stored_data, stored_len, &error);
if (error)
{
g_warning ("Error deserializing data: %s", error->message);
continue;
}
g_ptr_array_add (gallery, print);
}
return gallery;
}
FpPrint *
print_create_template (FpDevice *dev, FpFinger finger)
{

View File

@@ -24,7 +24,6 @@ int print_data_save (FpPrint *print,
FpFinger finger);
FpPrint * print_data_load (FpDevice *dev,
FpFinger finger);
GPtrArray * gallery_data_load (FpDevice *dev);
FpPrint * print_create_template (FpDevice *dev,
FpFinger finger);
gboolean print_image_save (FpPrint *print,

View File

@@ -152,26 +152,6 @@ on_match_cb (FpDevice *dev, FpPrint *match, FpPrint *print,
}
}
static FpPrint *
get_stored_print (FpDevice *dev, VerifyData *verify_data)
{
FpPrint *verify_print;
g_print ("Loading previously enrolled %s finger data...\n",
finger_to_string (verify_data->finger));
verify_print = print_data_load (dev, verify_data->finger);
if (!verify_print)
{
g_warning ("Failed to load fingerprint data");
g_warning ("Did you remember to enroll your %s finger first?",
finger_to_string (verify_data->finger));
}
return verify_print;
}
static void
on_list_completed (FpDevice *dev, GAsyncResult *res, gpointer user_data)
{
@@ -185,27 +165,15 @@ on_list_completed (FpDevice *dev, GAsyncResult *res, gpointer user_data)
if (!error)
{
FpPrint *verify_print = NULL;
g_autoptr(FpPrint) stored_print = NULL;
guint i;
if (!prints->len)
{
g_warning ("No prints saved on device");
verify_quit (dev, verify_data);
return;
}
stored_print = get_stored_print (dev, verify_data);
g_warning ("No prints saved on device");
for (i = 0; i < prints->len; ++i)
{
FpPrint *print = prints->pdata[i];
if (stored_print && fp_print_equal (stored_print, print))
/* If the private print data matches, let's use the stored print
* as it contains more metadata to show */
print = stored_print;
if (fp_print_get_finger (print) == verify_data->finger &&
g_strcmp0 (fp_print_get_username (print), g_get_user_name ()) == 0)
{
@@ -223,6 +191,8 @@ on_list_completed (FpDevice *dev, GAsyncResult *res, gpointer user_data)
if (!verify_print)
{
g_warning ("Did you remember to enroll your %s finger first?",
finger_to_string (verify_data->finger));
verify_quit (dev, verify_data);
return;
}
@@ -269,10 +239,17 @@ start_verification (FpDevice *dev, VerifyData *verify_data)
}
else
{
g_autoptr(FpPrint) verify_print = get_stored_print (dev, verify_data);
g_print ("Loading previously enrolled %s finger data...\n",
finger_to_string (verify_data->finger));
g_autoptr(FpPrint) verify_print = NULL;
verify_print = print_data_load (dev, verify_data->finger);
if (!verify_print)
{
g_warning ("Failed to load fingerprint data");
g_warning ("Did you remember to enroll your %s finger first?",
finger_to_string (verify_data->finger));
verify_quit (dev, verify_data);
return;
}

View File

@@ -135,8 +135,10 @@ generic_read_ignore_data (FpiSsm *ssm, FpDevice *dev,
size_t bytes)
{
FpiUsbTransfer *transfer = fpi_usb_transfer_new (dev);
unsigned char *data;
fpi_usb_transfer_fill_bulk (transfer, EP_IN, bytes);
data = g_malloc (bytes);
fpi_usb_transfer_fill_bulk_full (transfer, EP_IN, data, bytes, g_free);
transfer->ssm = ssm;
transfer->short_is_error = TRUE;
fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,

View File

@@ -106,9 +106,7 @@ static struct aes_regwrite init_reqs[] = {
{ 0x9e, 0x53 }, /* clear challenge word bits */
{ 0x9f, 0x6b }, /* set some challenge word bits */
{ 0, 0 },
};
static struct aes_regwrite capture_reqs[] = {
{ 0x80, 0x00 },
{ 0x81, 0x00 },
{ 0, 0 },
@@ -157,6 +155,4 @@ fpi_device_aes3500_class_init (FpiDeviceAes3500Class *klass)
aes_class->enlarge_factor = ENLARGE_FACTOR;
aes_class->init_reqs = init_reqs;
aes_class->init_reqs_len = G_N_ELEMENTS (init_reqs);
aes_class->capture_reqs = capture_reqs;
aes_class->capture_reqs_len = G_N_ELEMENTS (capture_reqs);
}

View File

@@ -42,10 +42,7 @@
typedef struct
{
/* This is used both as a flag that we are in a capture operation
* and for cancellation.
*/
GCancellable *img_capture_cancel;
GCancellable *img_trf_cancel;
} FpiDeviceAes3kPrivate;
#define CTRL_TIMEOUT 1000
@@ -86,9 +83,6 @@ img_cb (FpiUsbTransfer *transfer, FpDevice *device,
FpImage *img;
int i;
/* Image capture operation is finished (error/completed) */
g_clear_object (&priv->img_capture_cancel);
if (error)
{
if (g_error_matches (error,
@@ -97,11 +91,13 @@ img_cb (FpiUsbTransfer *transfer, FpDevice *device,
{
/* Cancellation implies we are deactivating. */
g_error_free (error);
g_clear_object (&priv->img_trf_cancel);
fpi_image_device_deactivate_complete (dev, NULL);
return;
}
fpi_image_device_session_error (dev, error);
g_clear_object (&priv->img_trf_cancel);
return;
}
@@ -126,10 +122,11 @@ img_cb (FpiUsbTransfer *transfer, FpDevice *device,
fpi_image_device_image_captured (dev, img);
/* FIXME: rather than assuming finger has gone, we should poll regs until
* it really has. */
* it really has, then restart the capture */
fpi_image_device_report_finger_status (dev, FALSE);
/* Note: The transfer is re-started when we switch to the AWAIT_FINGER_ON state. */
/* Note: We always restart the transfer, it may already be cancelled though. */
do_capture (dev);
}
static void
@@ -144,51 +141,31 @@ do_capture (FpImageDevice *dev)
fpi_usb_transfer_fill_bulk (img_trf, EP_IN, cls->data_buflen);
img_trf->short_is_error = TRUE;
fpi_usb_transfer_submit (g_steal_pointer (&img_trf), 0,
priv->img_capture_cancel,
priv->img_trf_cancel,
img_cb, NULL);
}
static void
capture_reqs_cb (FpImageDevice *dev, GError *result, void *user_data)
{
FpiDeviceAes3k *self = FPI_DEVICE_AES3K (dev);
FpiDeviceAes3kPrivate *priv = fpi_device_aes3k_get_instance_private (self);
if (result)
{
g_clear_object (&priv->img_capture_cancel);
fpi_image_device_session_error (dev, result);
return;
}
/* FIXME: we never cancel a pending capture. So we are likely leaving the
* hardware in a bad state should we abort the capture operation and the
* user does not touch the device.
* But, we don't know how we might cancel, so just leave it as is. */
do_capture (dev);
}
static void
do_capture_start (FpImageDevice *dev)
{
FpiDeviceAes3k *self = FPI_DEVICE_AES3K (dev);
FpiDeviceAes3kClass *cls = FPI_DEVICE_AES3K_GET_CLASS (self);
aes_write_regv (dev, cls->capture_reqs, cls->capture_reqs_len, capture_reqs_cb, NULL);
}
static void
init_reqs_cb (FpImageDevice *dev, GError *result, void *user_data)
{
FpiDeviceAes3kPrivate *priv = fpi_device_aes3k_get_instance_private (FPI_DEVICE_AES3K (dev));
fpi_image_device_activate_complete (dev, result);
if (!result)
{
priv->img_trf_cancel = g_cancellable_new ();
do_capture (dev);
}
}
static void
aes3k_dev_activate (FpImageDevice *dev)
{
FpiDeviceAes3k *self = FPI_DEVICE_AES3K (dev);
FpiDeviceAes3kPrivate *priv = fpi_device_aes3k_get_instance_private (self);
FpiDeviceAes3kClass *cls = FPI_DEVICE_AES3K_GET_CLASS (self);
g_assert (!priv->img_trf_cancel);
aes_write_regv (dev, cls->init_reqs, cls->init_reqs_len, init_reqs_cb, NULL);
}
@@ -198,28 +175,13 @@ aes3k_dev_deactivate (FpImageDevice *dev)
FpiDeviceAes3k *self = FPI_DEVICE_AES3K (dev);
FpiDeviceAes3kPrivate *priv = fpi_device_aes3k_get_instance_private (self);
/* If a capture is running, then deactivation finishes from the cancellation handler */
if (priv->img_capture_cancel)
g_cancellable_cancel (priv->img_capture_cancel);
/* Deactivation finishes from the cancellation handler */
if (priv->img_trf_cancel)
g_cancellable_cancel (priv->img_trf_cancel);
else
fpi_image_device_deactivate_complete (dev, NULL);
}
static void
aes3k_dev_change_state (FpImageDevice *dev, FpiImageDeviceState state)
{
FpiDeviceAes3k *self = FPI_DEVICE_AES3K (dev);
FpiDeviceAes3kPrivate *priv = fpi_device_aes3k_get_instance_private (self);
if (state == FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON)
{
g_assert (!priv->img_capture_cancel);
priv->img_capture_cancel = g_cancellable_new ();
do_capture_start (dev);
}
}
static void
fpi_device_aes3k_init (FpiDeviceAes3k *self)
{
@@ -262,7 +224,6 @@ fpi_device_aes3k_class_init (FpiDeviceAes3kClass *klass)
img_class->img_open = aes3k_dev_init;
img_class->img_close = aes3k_dev_deinit;
img_class->activate = aes3k_dev_activate;
img_class->change_state = aes3k_dev_change_state;
img_class->deactivate = aes3k_dev_deactivate;
/* Extremely low due to low image quality. */

View File

@@ -57,6 +57,4 @@ struct _FpiDeviceAes3kClass
gsize data_buflen; /* buffer length of usb bulk transfer */
struct aes_regwrite *init_reqs; /* initial values sent to device */
gsize init_reqs_len;
struct aes_regwrite *capture_reqs; /* capture values sent to device */
gsize capture_reqs_len;
};

View File

@@ -103,9 +103,7 @@ static struct aes_regwrite init_reqs[] = {
{ 0x9e, 0x53 }, /* clear challenge word bits */
{ 0x9f, 0x6b }, /* set some challenge word bits */
{ 0, 0 },
};
static struct aes_regwrite capture_reqs[] = {
{ 0x80, 0x00 },
{ 0x81, 0x00 },
{ 0, 0 },
@@ -154,6 +152,4 @@ fpi_device_aes4000_class_init (FpiDeviceAes4000Class *klass)
aes_class->enlarge_factor = ENLARGE_FACTOR;
aes_class->init_reqs = init_reqs;
aes_class->init_reqs_len = G_N_ELEMENTS (init_reqs);
aes_class->capture_reqs = capture_reqs;
aes_class->capture_reqs_len = G_N_ELEMENTS (capture_reqs);
}

View File

@@ -54,7 +54,6 @@ static void complete_deactivation (FpImageDevice *dev);
#define CALIBRATE_DATA_LEN 4
#define FINGER_DET_DATA_LEN 4
FP_GNUC_ACCESS (read_only, 3, 4)
static void
aesX660_send_cmd_timeout (FpiSsm *ssm,
FpDevice *_dev,
@@ -71,7 +70,6 @@ aesX660_send_cmd_timeout (FpiSsm *ssm,
fpi_usb_transfer_submit (transfer, timeout, NULL, callback, NULL);
}
FP_GNUC_ACCESS (read_only, 3, 4)
static void
aesX660_send_cmd (FpiSsm *ssm,
FpDevice *dev,
@@ -91,12 +89,13 @@ aesX660_read_response (FpiSsm *ssm,
FpiUsbTransferCallback callback)
{
FpiUsbTransfer *transfer = fpi_usb_transfer_new (_dev);
unsigned char *data;
GCancellable *cancel = NULL;
if (cancellable)
cancel = fpi_device_get_cancellable (_dev);
fpi_usb_transfer_fill_bulk (transfer, EP_IN, buf_len);
data = g_malloc (buf_len);
fpi_usb_transfer_fill_bulk_full (transfer, EP_IN, data, buf_len, NULL);
transfer->ssm = ssm;
transfer->short_is_error = short_is_error;
fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, cancel, callback, NULL);

View File

@@ -73,19 +73,22 @@ struct _FpiDeviceElan
/* end commands */
/* state */
gboolean active;
gboolean deactivating;
unsigned char *last_read;
unsigned char calib_atts_left;
unsigned char calib_status;
unsigned short *background;
unsigned char frame_width;
unsigned char frame_height;
unsigned char raw_frame_height;
int num_frames;
GSList *frames;
gboolean deactivating;
FpiImageDeviceState dev_state;
FpiImageDeviceState dev_state_next;
unsigned char *last_read;
unsigned char calib_atts_left;
unsigned char calib_status;
unsigned short *background;
unsigned char frame_width;
unsigned char frame_height;
unsigned char raw_frame_height;
int num_frames;
GSList *frames;
/* end state */
};
G_DECLARE_FINAL_TYPE (FpiDeviceElan, fpi_device_elan, FPI, DEVICE_ELAN,
FpImageDevice);
G_DEFINE_TYPE (FpiDeviceElan, fpi_device_elan, FP_TYPE_IMAGE_DEVICE);
static int
@@ -484,7 +487,7 @@ stop_capture_complete (FpiSsm *ssm, FpDevice *_dev, GError *error)
/* The device is inactive at this point. */
self->active = FALSE;
self->dev_state = FPI_IMAGE_DEVICE_STATE_INACTIVE;
if (self->deactivating)
{
@@ -502,14 +505,16 @@ stop_capture_complete (FpiSsm *ssm, FpDevice *_dev, GError *error)
}
static void
elan_stop_capture (FpiDeviceElan *self)
elan_stop_capture (FpDevice *dev)
{
FpiDeviceElan *self = FPI_DEVICE_ELAN (dev);
G_DEBUG_HERE ();
elan_dev_reset_state (self);
FpiSsm *ssm =
fpi_ssm_new (FP_DEVICE (self), stop_capture_run_state, STOP_CAPTURE_NUM_STATES);
fpi_ssm_new (dev, stop_capture_run_state, STOP_CAPTURE_NUM_STATES);
fpi_ssm_start (ssm, stop_capture_complete);
}
@@ -540,6 +545,8 @@ capture_run_state (FpiSsm *ssm, FpDevice *dev)
break;
case CAPTURE_READ_DATA:
self->dev_state = FPI_IMAGE_DEVICE_STATE_CAPTURE;
/* 0x55 - finger present
* 0xff - device not calibrated (probably) */
if (self->last_read && self->last_read[0] == 0x55)
@@ -607,21 +614,18 @@ capture_complete (FpiSsm *ssm, FpDevice *_dev, GError *error)
fpi_image_device_session_error (dev, error);
}
/* Note: We always stop capturing even if that may not be needed always.
* Doing this between captures appears to make it at least less likely for
* devices to end up in a bad state.
*/
elan_stop_capture (self);
}
static void
elan_capture (FpiDeviceElan *self)
elan_capture (FpDevice *dev)
{
FpiDeviceElan *self = FPI_DEVICE_ELAN (dev);
G_DEBUG_HERE ();
elan_dev_reset_state (self);
FpiSsm *ssm =
fpi_ssm_new (FP_DEVICE (self), capture_run_state, CAPTURE_NUM_STATES);
fpi_ssm_new (dev, capture_run_state, CAPTURE_NUM_STATES);
fpi_ssm_start (ssm, capture_complete);
}
@@ -773,31 +777,33 @@ calibrate_run_state (FpiSsm *ssm, FpDevice *dev)
static void
calibrate_complete (FpiSsm *ssm, FpDevice *dev, GError *error)
{
FpiDeviceElan *self = FPI_DEVICE_ELAN (dev);
G_DEBUG_HERE ();
if (error)
{
self->dev_state = FPI_IMAGE_DEVICE_STATE_INACTIVE;
fpi_image_device_session_error (FP_IMAGE_DEVICE (dev), error);
elan_stop_capture (FPI_DEVICE_ELAN (dev));
}
else
{
elan_capture (FPI_DEVICE_ELAN (dev));
elan_capture (dev);
}
}
static void
elan_calibrate (FpiDeviceElan *self)
elan_calibrate (FpDevice *dev)
{
FpiDeviceElan *self = FPI_DEVICE_ELAN (dev);
G_DEBUG_HERE ();
elan_dev_reset_state (self);
g_return_if_fail (!self->active);
self->active = TRUE;
self->calib_atts_left = ELAN_CALIBRATION_ATTEMPTS;
FpiSsm *ssm = fpi_ssm_new (FP_DEVICE (self), calibrate_run_state,
FpiSsm *ssm = fpi_ssm_new (FP_DEVICE (dev), calibrate_run_state,
CALIBRATE_NUM_STATES);
fpi_ssm_start (ssm, calibrate_complete);
@@ -952,19 +958,98 @@ dev_activate (FpImageDevice *dev)
elan_activate (dev);
}
static void
elan_change_state (FpImageDevice *idev)
{
FpDevice *dev = FP_DEVICE (idev);
FpiDeviceElan *self = FPI_DEVICE_ELAN (dev);
FpiImageDeviceState next_state = self->dev_state_next;
if (self->dev_state == next_state)
{
fp_dbg ("already in %d", next_state);
return;
}
else
{
fp_dbg ("changing to %d", next_state);
}
switch (next_state)
{
case FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON:
/* activation completed or another enroll stage started */
self->dev_state = FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON;
elan_calibrate (dev);
break;
case FPI_IMAGE_DEVICE_STATE_CAPTURE:
/* not used */
break;
case FPI_IMAGE_DEVICE_STATE_INACTIVE:
case FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_OFF:
elan_stop_capture (dev);
break;
}
}
static void
elan_change_state_async (FpDevice *dev,
void *data)
{
fp_dbg ("state change dev: %p", dev);
elan_change_state (FP_IMAGE_DEVICE (dev));
}
static void
dev_change_state (FpImageDevice *dev, FpiImageDeviceState state)
{
FpiDeviceElan *self = FPI_DEVICE_ELAN (dev);
GSource *timeout;
G_DEBUG_HERE ();
/* Note: We always calibrate even if that may not be needed always.
* Doing this for each capture appears to make it at least less likely for
* devices to end up in a bad state.
*/
if (state == FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON)
elan_calibrate (self);
/* Inactive and await finger off are equivalent for the elan driver. */
if (state == FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_OFF)
state = FPI_IMAGE_DEVICE_STATE_INACTIVE;
if (self->dev_state_next == state)
{
fp_dbg ("change to state %d already queued", state);
return;
}
switch (state)
{
case FPI_IMAGE_DEVICE_STATE_INACTIVE:
case FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON:
case FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_OFF: {
char *name;
/* schedule state change instead of calling it directly to allow all actions
* related to the previous state to complete */
self->dev_state_next = state;
timeout = fpi_device_add_timeout (FP_DEVICE (dev), 10,
elan_change_state_async,
NULL, NULL);
name = g_strdup_printf ("dev_change_state to %d", state);
g_source_set_name (timeout, name);
g_free (name);
break;
}
case FPI_IMAGE_DEVICE_STATE_CAPTURE:
/* TODO MAYBE: split capture ssm into smaller ssms and use this state */
self->dev_state = state;
self->dev_state_next = state;
break;
default:
g_assert_not_reached ();
}
}
static void
@@ -974,14 +1059,19 @@ dev_deactivate (FpImageDevice *dev)
G_DEBUG_HERE ();
if (!self->active)
/* The device is inactive already, complete the operation immediately. */
fpi_image_device_deactivate_complete (dev, NULL);
if (self->dev_state == FPI_IMAGE_DEVICE_STATE_INACTIVE)
{
/* The device is inactive already, complete the operation immediately. */
fpi_image_device_deactivate_complete (dev, NULL);
}
else
/* The device is not yet inactive, flag that we are deactivating (and
* need to signal back deactivation).
* Note that any running capture will be cancelled already if needed. */
self->deactivating = TRUE;
{
/* The device is not yet inactive, flag that we are deactivating (and
* need to signal back deactivation) and then ensure we will change
* to the inactive state eventually. */
self->deactivating = TRUE;
dev_change_state (dev, FPI_IMAGE_DEVICE_STATE_INACTIVE);
}
}
static void

View File

@@ -70,9 +70,6 @@
#define ELAN_CMD_TIMEOUT 10000
#define ELAN_FINGER_TIMEOUT 200
G_DECLARE_FINAL_TYPE (FpiDeviceElan, fpi_device_elan, FPI, DEVICE_ELAN,
FpImageDevice);
struct elan_cmd
{
unsigned char cmd[ELAN_CMD_LEN];
@@ -214,7 +211,6 @@ static const FpIdEntry elan_id_table[] = {
{.vid = ELAN_VEND_ID, .pid = 0x0c32, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c33, .driver_data = ELAN_ALL_DEV},
{.vid = ELAN_VEND_ID, .pid = 0x0c42, .driver_data = ELAN_0C42},
{.vid = ELAN_VEND_ID, .pid = 0x0c4d, .driver_data = ELAN_ALL_DEV},
{.vid = 0, .pid = 0, .driver_data = 0},
};
@@ -222,8 +218,8 @@ static void elan_cmd_done (FpiSsm *ssm);
static void elan_cmd_read (FpiSsm *ssm,
FpDevice *dev);
static void elan_calibrate (FpiDeviceElan *self);
static void elan_capture (FpiDeviceElan *self);
static void elan_calibrate (FpDevice *dev);
static void elan_capture (FpDevice *dev);
static void dev_change_state (FpImageDevice *dev,
FpiImageDeviceState state);

View File

@@ -53,7 +53,6 @@ struct _FpiDeviceGoodixMoc
pgxfp_sensor_cfg_t sensorcfg;
gint enroll_stage;
gint max_enroll_stage;
gint max_stored_prints;
GCancellable *cancellable;
GPtrArray *list_result;
guint8 template_id[TEMPLATE_ID_SIZE];
@@ -331,9 +330,7 @@ fp_verify_capture_cb (FpiDeviceGoodixMoc *self,
fpi_device_retry_new (FP_DEVICE_RETRY_GENERAL));
return;
}
fpi_device_report_finger_status_changes (FP_DEVICE (self),
FP_FINGER_STATUS_PRESENT,
FP_FINGER_STATUS_NONE);
if (resp->capture_data_resp.img_quality == 0)
{
fpi_ssm_mark_failed (self->task_ssm,
@@ -344,7 +341,6 @@ fp_verify_capture_cb (FpiDeviceGoodixMoc *self,
{
fpi_ssm_mark_failed (self->task_ssm,
fpi_device_retry_new (FP_DEVICE_RETRY_CENTER_FINGER));
return;
}
fpi_ssm_next_state (self->task_ssm);
}
@@ -354,9 +350,9 @@ fp_verify_cb (FpiDeviceGoodixMoc *self,
gxfp_cmd_response_t *resp,
GError *error)
{
g_autoptr(GPtrArray) templates = NULL;
FpDevice *device = FP_DEVICE (self);
FpPrint *print = NULL;
GPtrArray *templates = NULL;
gint cnt = 0;
gboolean find = false;
@@ -369,14 +365,15 @@ fp_verify_cb (FpiDeviceGoodixMoc *self,
{
if (fpi_device_get_current_action (device) == FPI_DEVICE_ACTION_VERIFY)
{
templates = g_ptr_array_sized_new (1);
templates = g_ptr_array_new_with_free_func (g_object_unref);
fpi_device_get_verify_data (device, &print);
g_ptr_array_add (templates, print);
g_ptr_array_add (templates, g_object_ref_sink (print));
}
else
{
fpi_device_get_identify_data (device, &templates);
g_ptr_array_ref (templates);
}
for (cnt = 0; cnt < templates->len; cnt++)
{
@@ -437,9 +434,6 @@ fp_verify_sm_run_state (FpiSsm *ssm, FpDevice *device)
switch (fpi_ssm_get_cur_state (ssm))
{
case FP_VERIFY_CAPTURE:
fpi_device_report_finger_status_changes (device,
FP_FINGER_STATUS_NEEDED,
FP_FINGER_STATUS_NONE);
goodix_sensor_cmd (self, MOC_CMD0_CAPTURE_DATA, MOC_CMD1_DEFAULT,
true,
(const guint8 *) &param,
@@ -567,13 +561,6 @@ fp_enroll_enum_cb (FpiDeviceGoodixMoc *self,
resp->result));
return;
}
if (resp->finger_list_resp.finger_num >= self->max_stored_prints)
{
fpi_ssm_mark_failed (self->task_ssm,
fpi_device_error_new (FP_DEVICE_ERROR_DATA_FULL));
return;
}
fpi_ssm_jump_to_state (self->task_ssm, FP_ENROLL_CAPTURE);
}
@@ -634,9 +621,7 @@ fp_enroll_capture_cb (FpiDeviceGoodixMoc *self,
fpi_ssm_jump_to_state (self->task_ssm, FP_ENROLL_CAPTURE);
return;
}
fpi_device_report_finger_status_changes (FP_DEVICE (self),
FP_FINGER_STATUS_PRESENT,
FP_FINGER_STATUS_NONE);
if ((resp->capture_data_resp.img_quality < self->sensorcfg->config[4]) ||
(resp->capture_data_resp.img_coverage < self->sensorcfg->config[5]))
{
@@ -758,7 +743,7 @@ fp_finger_mode_cb (FpiDeviceGoodixMoc *self,
fpi_ssm_mark_failed (self->task_ssm, error);
return;
}
/* if reach max timeout(5sec) finger not up, switch to finger up again */
/* if reach max timeout(5sec) finger not up, swtich to finger up again */
if (resp->finger_status.status == GX_ERROR_WAIT_FINGER_UP_TIMEOUT)
{
fpi_ssm_jump_to_state (self->task_ssm, FP_ENROLL_WAIT_FINGER_UP);
@@ -771,9 +756,6 @@ fp_finger_mode_cb (FpiDeviceGoodixMoc *self,
"Switch finger mode failed"));
return;
}
fpi_device_report_finger_status_changes (FP_DEVICE (self),
FP_FINGER_STATUS_NONE,
FP_FINGER_STATUS_PRESENT);
if (self->enroll_stage < self->max_enroll_stage)
{
fpi_ssm_jump_to_state (self->task_ssm, FP_ENROLL_CAPTURE);
@@ -836,9 +818,6 @@ fp_enroll_sm_run_state (FpiSsm *ssm, FpDevice *device)
break;
case FP_ENROLL_CAPTURE:
fpi_device_report_finger_status_changes (device,
FP_FINGER_STATUS_NEEDED,
FP_FINGER_STATUS_NONE);
goodix_sensor_cmd (self, MOC_CMD0_CAPTURE_DATA, MOC_CMD1_DEFAULT,
true,
(const guint8 *) &dummy,
@@ -997,7 +976,7 @@ fp_init_config_cb (FpiDeviceGoodixMoc *self,
fpi_ssm_mark_failed (self->task_ssm, error);
return;
}
self->max_stored_prints = resp->finger_config.max_stored_prints;
fpi_ssm_next_state (self->task_ssm);
}
@@ -1281,8 +1260,6 @@ gx_fp_init (FpDevice *device)
GError *error = NULL;
int ret = 0;
self->max_stored_prints = FP_MAX_FINGERNUM;
self->cancellable = g_cancellable_new ();
self->sensorcfg = g_new0 (gxfp_sensor_cfg_t, 1);
@@ -1448,8 +1425,6 @@ static const FpIdEntry id_table[] = {
{ .vid = 0x27c6, .pid = 0x5840, },
{ .vid = 0x27c6, .pid = 0x6496, },
{ .vid = 0x27c6, .pid = 0x60A2, },
{ .vid = 0x27c6, .pid = 0x63AC, },
{ .vid = 0x27c6, .pid = 0x639C, },
{ .vid = 0, .pid = 0, .driver_data = 0 }, /* terminating entry */
};

View File

@@ -229,7 +229,7 @@ gx_proto_parse_header (
memcpy (pheader, buffer, sizeof (pack_header));
pheader->len = GUINT16_FROM_LE ( *(uint16_t *) (buffer + 4));
pheader->len = GUINT16_FROM_LE (*(buffer + 4));
pheader->len -= PACKAGE_CRC_SIZE;
return 0;
@@ -294,12 +294,6 @@ gx_proto_parse_body (uint16_t cmd, uint8_t *buffer, uint32_t buffer_len, pgxfp_c
break;
case MOC_CMD0_UPDATE_CONFIG:
{
presp->finger_config.status = buffer[0];
presp->finger_config.max_stored_prints = buffer[2];
}
break;
case MOC_CMD0_COMMITENROLLMENT:
case MOC_CMD0_DELETETEMPLATE:
break;
@@ -417,7 +411,7 @@ gx_proto_init_sensor_config (pgxfp_sensor_cfg_t pconfig)
memset (pconfig, 0, sizeof (*pconfig));
//NOTICE: Do not change any value!
memcpy (&pconfig->config, sensor_config, G_N_ELEMENTS (sensor_config));
memcpy (&pconfig->config, sensor_config, 26);
pconfig->reserved[0] = 1;
gx_proto_crc32_calc ((uint8_t *) pconfig, sizeof (*pconfig) - PACKAGE_CRC_SIZE, (uint8_t *) &crc32_calc);

View File

@@ -25,7 +25,7 @@
#define PACKAGE_CRC_SIZE (4)
#define PACKAGE_HEADER_SIZE (8)
#define FP_MAX_FINGERNUM (20)
#define FP_MAX_FINGERNUM (10)
#define TEMPLATE_ID_SIZE (32)
@@ -167,11 +167,6 @@ typedef struct _fp_finger_status
uint8_t status;
} fp_finger_status_t, *pfp_finger_status_t;
typedef struct _fp_finger_config
{
uint8_t status;
uint8_t max_stored_prints;
} fp_finger_config_t, *pfp_finger_config_t;
typedef struct _fp_cmd_response
{
@@ -188,7 +183,6 @@ typedef struct _fp_cmd_response
gxfp_enum_fingerlist_t finger_list_resp;
gxfp_version_info_t version_info;
fp_finger_status_t finger_status;
fp_finger_config_t finger_config;
};
} gxfp_cmd_response_t, *pgxfp_cmd_response_t;

View File

@@ -27,18 +27,10 @@
G_DEFINE_TYPE (FpiDeviceSynaptics, fpi_device_synaptics, FP_TYPE_DEVICE)
static void init_identify_msg (FpDevice *device);
static void compose_and_send_identify_msg (FpDevice *device);
static const FpIdEntry id_table[] = {
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0xBD, },
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0xE9, },
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0xDF, },
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0xF9, },
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0xFC, },
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0xC2, },
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0xC9, },
{ .vid = SYNAPTICS_VENDOR_ID, .pid = 0xE7, },
{ .vid = 0, .pid = 0, .driver_data = 0 }, /* terminating entry */
};
@@ -87,17 +79,10 @@ cmd_receive_cb (FpiUsbTransfer *transfer,
if (msg_resp.payload[0] == 0x01)
{
self->finger_on_sensor = TRUE;
fpi_device_report_finger_status_changes (device,
FP_FINGER_STATUS_PRESENT,
FP_FINGER_STATUS_NONE);
}
else
{
self->finger_on_sensor = FALSE;
fpi_device_report_finger_status_changes (device,
FP_FINGER_STATUS_NONE,
FP_FINGER_STATUS_PRESENT);
if (self->cmd_complete_on_removal)
{
fpi_ssm_mark_completed (transfer->ssm);
@@ -124,7 +109,7 @@ cmd_receive_cb (FpiUsbTransfer *transfer,
{
if (resp.response_id == BMKT_RSP_CANCEL_OP_OK)
{
fp_dbg ("Received cancellation success response");
fp_dbg ("Received cancellation success resonse");
fpi_ssm_mark_failed (transfer->ssm,
g_error_new_literal (G_IO_ERROR,
G_IO_ERROR_CANCELLED,
@@ -209,19 +194,12 @@ cmd_interrupt_cb (FpiUsbTransfer *transfer,
fpi_ssm_mark_failed (transfer->ssm, error);
return;
}
g_clear_pointer (&error, g_error_free);
if (transfer->buffer[0] & USB_ASYNC_MESSAGE_PENDING)
{
fpi_ssm_next_state (transfer->ssm);
}
if (transfer->buffer[0] & USB_ASYNC_MESSAGE_PENDING || error)
fpi_ssm_next_state (transfer->ssm);
else
{
fpi_usb_transfer_submit (fpi_usb_transfer_ref (transfer),
0,
NULL,
cmd_interrupt_cb,
NULL);
}
fpi_usb_transfer_submit (transfer, 1000, NULL, cmd_interrupt_cb, NULL);
}
static void
@@ -454,37 +432,6 @@ parse_print_data (GVariant *data,
return TRUE;
}
static FpPrint *
create_print (FpiDeviceSynaptics *self,
guint8 *user_id,
guint8 finger_id)
{
FpPrint *print;
g_autofree gchar *user_id_safe;
GVariant *data = NULL;
GVariant *uid = NULL;
user_id_safe = g_strndup ((char *) user_id, BMKT_MAX_USER_ID_LEN);
print = fp_print_new (FP_DEVICE (self));
uid = g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE,
user_id_safe,
strlen (user_id_safe),
1);
data = g_variant_new ("(y@ay)",
finger_id,
uid);
fpi_print_set_type (print, FPI_PRINT_RAW);
fpi_print_set_device_stored (print, TRUE);
g_object_set (print, "fpi-data", data, NULL);
g_object_set (print, "description", user_id_safe, NULL);
fpi_print_fill_from_user_id (print, user_id_safe);
return print;
}
static void
list_msg_cb (FpiDeviceSynaptics *self,
bmkt_response_t *resp,
@@ -537,7 +484,10 @@ list_msg_cb (FpiDeviceSynaptics *self,
for (int n = 0; n < BMKT_MAX_NUM_TEMPLATES_INTERNAL_FLASH; n++)
{
GVariant *data = NULL;
GVariant *uid = NULL;
FpPrint *print;
gchar *userid;
if (get_enroll_templates_resp->templates[n].user_id_len == 0)
continue;
@@ -550,9 +500,23 @@ list_msg_cb (FpiDeviceSynaptics *self,
get_enroll_templates_resp->templates[n].user_id,
get_enroll_templates_resp->templates[n].finger_id);
print = create_print (self,
get_enroll_templates_resp->templates[n].user_id,
get_enroll_templates_resp->templates[n].finger_id);
userid = (gchar *) get_enroll_templates_resp->templates[n].user_id;
print = fp_print_new (FP_DEVICE (self));
uid = g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE,
get_enroll_templates_resp->templates[n].user_id,
get_enroll_templates_resp->templates[n].user_id_len,
1);
data = g_variant_new ("(y@ay)",
get_enroll_templates_resp->templates[n].finger_id,
uid);
fpi_print_set_type (print, FPI_PRINT_RAW);
fpi_print_set_device_stored (print, TRUE);
g_object_set (print, "fpi-data", data, NULL);
g_object_set (print, "description", get_enroll_templates_resp->templates[n].user_id, NULL);
fpi_print_fill_from_user_id (print, userid);
g_ptr_array_add (self->list_result, g_object_ref_sink (print));
}
@@ -622,9 +586,6 @@ verify_msg_cb (FpiDeviceSynaptics *self,
switch (resp->response_id)
{
case BMKT_RSP_VERIFY_READY:
fpi_device_report_finger_status_changes (device,
FP_FINGER_STATUS_NEEDED,
FP_FINGER_STATUS_NONE);
fp_info ("Place Finger on the Sensor!");
break;
@@ -666,7 +627,7 @@ verify_msg_cb (FpiDeviceSynaptics *self,
fp_info ("Verify was successful! for user: %s finger: %d score: %f",
verify_resp->user_id, verify_resp->finger_id, verify_resp->match_result);
fpi_device_verify_report (device, FPI_MATCH_SUCCESS, NULL, NULL);
verify_complete_after_finger_removal (self);
fpi_device_verify_complete (device, NULL);
break;
}
}
@@ -698,212 +659,6 @@ verify (FpDevice *device)
synaptics_sensor_cmd (self, 0, BMKT_CMD_VERIFY_USER, user_id, user_id_len, verify_msg_cb);
}
static void
identify_complete_after_finger_removal (FpiDeviceSynaptics *self)
{
FpDevice *device = FP_DEVICE (self);
if (self->finger_on_sensor)
{
fp_dbg ("delaying identify report until after finger removal!");
self->cmd_complete_on_removal = TRUE;
}
else
{
fpi_device_identify_complete (device, NULL);
}
}
static void
identify_msg_cb (FpiDeviceSynaptics *self,
bmkt_response_t *resp,
GError *error)
{
FpDevice *device = FP_DEVICE (self);
if (error)
{
fpi_device_identify_complete (device, error);
return;
}
if (resp == NULL && self->cmd_complete_on_removal)
{
fpi_device_identify_complete (device, NULL);
return;
}
g_assert (resp != NULL);
switch (resp->response_id)
{
case BMKT_RSP_ID_READY:
fp_info ("Place Finger on the Sensor!");
break;
case BMKT_RSP_SEND_NEXT_USER_ID:
{
compose_and_send_identify_msg (device);
break;
}
case BMKT_RSP_ID_FAIL:
if (resp->result == BMKT_SENSOR_STIMULUS_ERROR)
{
fp_info ("Match error occurred");
fpi_device_identify_report (device, NULL, NULL,
fpi_device_retry_new (FP_DEVICE_RETRY_GENERAL));
identify_complete_after_finger_removal (self);
}
else if (resp->result == BMKT_FP_NO_MATCH)
{
fp_info ("Print didn't match");
fpi_device_identify_report (device, NULL, NULL, NULL);
identify_complete_after_finger_removal (self);
}
else if (resp->result == BMKT_FP_DATABASE_NO_RECORD_EXISTS)
{
fp_info ("Print is not in database");
fpi_device_identify_complete (device,
fpi_device_error_new (FP_DEVICE_ERROR_DATA_NOT_FOUND));
}
else
{
fp_warn ("identify has failed: %d", resp->result);
fpi_device_identify_complete (device,
fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
"Unexpected result from device %d",
resp->result));
}
break;
case BMKT_RSP_ID_OK:
{
FpPrint *print = NULL;
GPtrArray *prints = NULL;
g_autoptr(GVariant) data = NULL;
gboolean found = FALSE;
guint index;
print = create_print (self,
resp->response.id_resp.user_id,
resp->response.id_resp.finger_id);
fpi_device_get_identify_data (device, &prints);
found = g_ptr_array_find_with_equal_func (prints,
print,
(GEqualFunc) fp_print_equal,
&index);
if (found)
fpi_device_identify_report (device, g_ptr_array_index (prints, index), print, NULL);
else
fpi_device_identify_report (device, NULL, print, NULL);
identify_complete_after_finger_removal (self);
}
}
}
static void
identify (FpDevice *device)
{
init_identify_msg (device);
compose_and_send_identify_msg (device);
}
static void
init_identify_msg (FpDevice *device)
{
FpiDeviceSynaptics *self = FPI_DEVICE_SYNAPTICS (device);
self->id_idx = 0;
}
static void
compose_and_send_identify_msg (FpDevice *device)
{
FpiDeviceSynaptics *self = FPI_DEVICE_SYNAPTICS (device);
FpPrint *print = NULL;
GPtrArray *prints = NULL;
g_autoptr(GVariant) data = NULL;
guint8 finger;
const guint8 *user_id;
gsize user_id_len = 0;
g_autofree guint8 *payload = NULL;
guint8 payload_len = 0;
guint8 payloadOffset = 0;
fpi_device_get_identify_data (device, &prints);
if (prints->len > UINT8_MAX)
{
fpi_device_identify_complete (device,
fpi_device_error_new (FP_DEVICE_ERROR_DATA_INVALID));
return;
}
if(self->id_idx >= prints->len)
{
fp_warn ("Device asked for more prints than we are providing.");
fpi_device_identify_complete (device,
fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
"Unexpected index"));
return;
}
print = g_ptr_array_index (prints, self->id_idx);
g_object_get (print, "fpi-data", &data, NULL);
g_debug ("data is %p", data);
if (!parse_print_data (data, &finger, &user_id, &user_id_len))
{
fpi_device_identify_complete (device,
fpi_device_error_new (FP_DEVICE_ERROR_DATA_INVALID));
return;
}
if(self->id_idx == 0)
{
/*
* Construct payload.
* 1st byte is total number of IDs in list.
* 2nd byte is number of IDs in list.
* 1 byte for each ID length, maximum id length is 100.
* user_id_len bytes of each ID
*/
payload_len = 2 + 1 + user_id_len;
payload = g_malloc0 (payload_len);
payload[payloadOffset] = prints->len;
payloadOffset += 1;
payload[payloadOffset] = 1; /* send one id per message */
payloadOffset += 1;
payload[payloadOffset] = user_id_len;
payloadOffset += 1;
memcpy (&payload[payloadOffset], user_id, user_id_len);
payloadOffset += user_id_len;
G_DEBUG_HERE ();
synaptics_sensor_cmd (self, 0, BMKT_CMD_ID_USER_IN_ORDER, payload, payloadOffset, identify_msg_cb);
}
else
{
/*
* 1st byte is the number of IDs
* 1 byte for each ID length
* id_length bytes for each ID
*/
payload_len = 1 + 1 + user_id_len;
payload = g_malloc0 (payload_len);
payload[payloadOffset] = 1; /* send one id per message */
payloadOffset += 1;
payload[payloadOffset] = user_id_len;
payloadOffset += 1;
memcpy (&payload[payloadOffset], user_id, user_id_len);
payloadOffset += user_id_len;
synaptics_sensor_cmd (self, self->cmd_seq_num, BMKT_CMD_ID_NEXT_USER, payload, payloadOffset, NULL);
}
self->id_idx++;
}
static void
enroll_msg_cb (FpiDeviceSynaptics *self,
bmkt_response_t *resp,
@@ -925,9 +680,6 @@ enroll_msg_cb (FpiDeviceSynaptics *self,
case BMKT_RSP_ENROLL_READY:
{
self->enroll_stage = 0;
fpi_device_report_finger_status_changes (device,
FP_FINGER_STATUS_NEEDED,
FP_FINGER_STATUS_NONE);
fp_info ("Place Finger on the Sensor!");
break;
}
@@ -1133,44 +885,6 @@ delete_print (FpDevice *device)
synaptics_sensor_cmd (self, 0, BMKT_CMD_DEL_USER_FP, payload, user_id_len + 1, delete_msg_cb);
}
static void
prob_msg_cb (FpiDeviceSynaptics *self,
bmkt_response_t *resp,
GError *error)
{
GUsbDevice *usb_dev = NULL;
g_autofree gchar *serial = NULL;
usb_dev = fpi_device_get_usb_device (FP_DEVICE (self));
if (error)
{
g_usb_device_close (usb_dev, NULL);
fpi_device_probe_complete (FP_DEVICE (self), NULL, NULL,
fpi_device_error_new_msg (FP_DEVICE_ERROR_GENERAL, "unsupported firmware version"));
return;
}
if (g_strcmp0 (g_getenv ("FP_DEVICE_EMULATION"), "1") == 0)
serial = g_strdup ("emulated-device");
else
serial = g_usb_device_get_string_descriptor (usb_dev,
g_usb_device_get_serial_number_index (usb_dev),
&error);
if (resp->result == BMKT_SUCCESS)
{
g_usb_device_close (usb_dev, NULL);
fpi_device_probe_complete (FP_DEVICE (self), serial, NULL, error);
}
else
{
g_warning ("Probe fingerprint sensor failed with %d!", resp->result);
g_usb_device_close (usb_dev, NULL);
fpi_device_probe_complete (FP_DEVICE (self), serial, NULL, fpi_device_error_new (FP_DEVICE_ERROR_GENERAL));
}
}
static void
dev_probe (FpDevice *device)
{
@@ -1271,7 +985,40 @@ dev_probe (FpDevice *device)
fp_dbg ("Target: %d", self->mis_version.target);
fp_dbg ("Product: %d", self->mis_version.product);
synaptics_sensor_cmd (self, 0, BMKT_CMD_FPS_INIT, NULL, 0, prob_msg_cb);
/* We need at least firmware version 10.1, and for 10.1 build 2989158 */
if (self->mis_version.version_major < 10 ||
self->mis_version.version_minor < 1 ||
(self->mis_version.version_major == 10 &&
self->mis_version.version_minor == 1 &&
self->mis_version.build_num < 2989158))
{
fp_warn ("Firmware version %d.%d with build number %d is unsupported",
self->mis_version.version_major,
self->mis_version.version_minor,
self->mis_version.build_num);
error = fpi_device_error_new_msg (FP_DEVICE_ERROR_GENERAL,
"Unsupported firmware version "
"(%d.%d with build number %d)",
self->mis_version.version_major,
self->mis_version.version_minor,
self->mis_version.build_num);
goto err_close;
}
/* This is the same as the serial_number from above, hex encoded and somewhat reordered */
/* Should we add in more, e.g. the chip revision? */
if (g_strcmp0 (g_getenv ("FP_DEVICE_EMULATION"), "1") == 0)
serial = g_strdup ("emulated-device");
else
serial = g_usb_device_get_string_descriptor (usb_dev,
g_usb_device_get_serial_number_index (usb_dev),
&error);
g_usb_device_close (usb_dev, NULL);
fpi_device_probe_complete (device, serial, NULL, error);
return;
@@ -1405,7 +1152,6 @@ fpi_device_synaptics_class_init (FpiDeviceSynapticsClass *klass)
dev_class->close = dev_exit;
dev_class->probe = dev_probe;
dev_class->verify = verify;
dev_class->identify = identify;
dev_class->enroll = enroll;
dev_class->delete = delete_print;
dev_class->cancel = cancel;

View File

@@ -110,7 +110,6 @@ struct _FpiDeviceSynaptics
FpiSsm *cmd_ssm;
FpiUsbTransfer *cmd_pending_transfer;
gboolean cmd_complete_on_removal;
guint8 id_idx;
bmkt_sensor_version_t mis_version;

View File

@@ -78,7 +78,6 @@ upektc_img_cmd_update_crc (unsigned char *cmd_buf, size_t size)
cmd_buf[size - 1] = (crc & 0xff00) >> 8;
}
FP_GNUC_ACCESS (read_only, 3, 4)
static void
upektc_img_submit_req (FpiSsm *ssm,
FpImageDevice *dev,

View File

@@ -527,6 +527,15 @@ initsm_read_msg_response_cb (FpiSsm *ssm,
fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
"Unexpected response subcommand"));
}
else if (seq != upekdev->seq)
{
fp_err ("expected response to cmd seq=%02x, got response to %02x "
"in state %d", upekdev->seq, seq,
fpi_ssm_get_cur_state (ssm));
fpi_ssm_mark_failed (ssm,
fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
"Unexpected sequence number in response"));
}
else
{
fpi_ssm_next_state (ssm);

View File

@@ -412,6 +412,18 @@ dev_change_state (FpImageDevice *dev, FpiImageDeviceState state)
{
FpiDeviceUru4000 *self = FPI_DEVICE_URU4000 (dev);
switch (state)
{
case FPI_IMAGE_DEVICE_STATE_INACTIVE:
case FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON:
case FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_OFF:
case FPI_IMAGE_DEVICE_STATE_CAPTURE:
break;
default:
g_assert_not_reached ();
}
self->activate_state = state;
if (self->img_transfer != NULL)
return;
@@ -651,11 +663,7 @@ imaging_run_state (FpiSsm *ssm, FpDevice *_dev)
case IMAGING_CAPTURE:
self->img_lines_done = 0;
self->img_block = 0;
fpi_usb_transfer_submit (fpi_usb_transfer_ref (self->img_transfer),
0,
NULL,
image_transfer_cb,
NULL);
fpi_usb_transfer_submit (self->img_transfer, 0, NULL, image_transfer_cb, NULL);
break;
@@ -791,7 +799,8 @@ imaging_complete (FpiSsm *ssm, FpDevice *dev, GError *error)
if (error)
fpi_image_device_session_error (FP_IMAGE_DEVICE (dev), error);
g_clear_pointer (&self->img_transfer, fpi_usb_transfer_unref);
/* Freed by callback or cancellation */
self->img_transfer = NULL;
g_free (self->img_data);
self->img_data = NULL;
@@ -1173,10 +1182,7 @@ deactivate_write_reg_cb (FpiUsbTransfer *transfer, FpDevice *dev,
static void
dev_deactivate (FpImageDevice *dev)
{
/* This is started/handled by execute_state_change in order to delay the
* action until after the image transfer has completed.
* We just need to override the function so that the complete handler is
* not called automatically. */
dev_change_state (dev, FPI_IMAGE_DEVICE_STATE_INACTIVE);
}
static void
@@ -1187,7 +1193,7 @@ execute_state_change (FpImageDevice *dev)
switch (self->activate_state)
{
case FPI_IMAGE_DEVICE_STATE_DEACTIVATING:
case FPI_IMAGE_DEVICE_STATE_INACTIVE:
fp_dbg ("deactivating");
self->irq_cb = NULL;
self->irq_cb_data = NULL;
@@ -1242,12 +1248,6 @@ execute_state_change (FpImageDevice *dev)
write_reg (dev, REG_MODE, MODE_AWAIT_FINGER_OFF,
change_state_write_reg_cb, NULL);
break;
/* Ignored states */
case FPI_IMAGE_DEVICE_STATE_IDLE:
case FPI_IMAGE_DEVICE_STATE_ACTIVATING:
case FPI_IMAGE_DEVICE_STATE_INACTIVE:
break;
}
}

View File

@@ -42,7 +42,6 @@ async_write_callback (FpiUsbTransfer *transfer, FpDevice *device,
}
/* Send data to EP1, the only out endpoint */
FP_GNUC_ACCESS (read_only, 3, 4)
static void
async_write (FpiSsm *ssm,
FpDevice *dev,

View File

@@ -147,6 +147,18 @@ m_loop_state (FpiSsm *ssm, FpDevice *_dev)
}
}
/* Complete loop sequential state machine */
static void
m_loop_complete (FpiSsm *ssm, FpDevice *_dev, GError *error)
{
if (error)
{
g_warning ("State machine completed with an error: %s", error->message);
g_error_free (error);
}
/* Free sequential state machine */
}
/* Exec init sequential state machine */
static void
m_init_state (FpiSsm *ssm, FpDevice *_dev)
@@ -164,7 +176,19 @@ m_init_state (FpiSsm *ssm, FpDevice *_dev)
static void
m_init_complete (FpiSsm *ssm, FpDevice *dev, GError *error)
{
FpiSsm *ssm_loop;
fpi_image_device_activate_complete (FP_IMAGE_DEVICE (dev), error);
if (!error)
{
/* Notify activate complete */
/* Start loop ssm */
ssm_loop = fpi_ssm_new (dev, m_loop_state, M_LOOP_NUM_STATES);
fpi_ssm_start (ssm_loop, m_loop_complete);
}
/* Free sequential state machine */
}
/* Activate device */
@@ -189,19 +213,6 @@ dev_deactivate (FpImageDevice *dev)
fpi_image_device_deactivate_complete (dev, NULL);
}
static void
dev_change_state (FpImageDevice *dev, FpiImageDeviceState state)
{
FpiSsm *ssm_loop;
if (state != FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON)
return;
/* Start a capture operation. */
ssm_loop = fpi_ssm_new (FP_DEVICE (dev), m_loop_state, M_LOOP_NUM_STATES);
fpi_ssm_start (ssm_loop, NULL);
}
static void
dev_open (FpImageDevice *dev)
{
@@ -262,7 +273,6 @@ fpi_device_vfs301_class_init (FpDeviceVfs301Class *klass)
img_class->img_close = dev_close;
img_class->activate = dev_activate;
img_class->deactivate = dev_deactivate;
img_class->change_state = dev_change_state;
img_class->bz3_threshold = 24;

View File

@@ -93,7 +93,6 @@ usb_recv (FpDeviceVfs301 *dev, guint8 endpoint, int max_bytes, FpiUsbTransfer **
*out = g_steal_pointer (&transfer);
}
FP_GNUC_ACCESS (read_only, 2, 3)
static void
usb_send (FpDeviceVfs301 *dev, const guint8 *data, gssize length, GError **error)
{
@@ -213,9 +212,11 @@ vfs301_proto_generate (int type, int subtype, gssize *len)
*len = 1;
return data;
}
break;
case 0x0B:
return vfs301_proto_generate_0B (subtype, len);
break;
case 0x02D0:
{
@@ -231,18 +232,22 @@ vfs301_proto_generate (int type, int subtype, gssize *len)
g_assert ((int) subtype <= G_N_ELEMENTS (dataLs));
return translate_str (dataLs[subtype - 1], len);
}
break;
case 0x0220:
switch (subtype)
{
case 1:
return translate_str (vfs301_0220_01, len);
break;
case 2:
return translate_str (vfs301_0220_02, len);
break;
case 3:
return translate_str (vfs301_0220_03, len);
break;
case 0xFA00:
case 0x2C01:
@@ -265,6 +270,7 @@ vfs301_proto_generate (int type, int subtype, gssize *len)
field[3] = field[1];
return data;
break;
}
default:
@@ -502,30 +508,30 @@ vfs301_proto_process_event_cb (FpiUsbTransfer *transfer,
FpDevice *device,
gpointer user_data, GError *error)
{
FpDeviceVfs301 *self = FPI_DEVICE_VFS301 (device);
FpDeviceVfs301 *dev = user_data;
if (error)
{
g_warning ("Error receiving data: %s", error->message);
g_error_free (error);
self->recv_progress = VFS301_FAILURE;
dev->recv_progress = VFS301_FAILURE;
return;
}
else if (transfer->actual_length < transfer->length)
{
/* TODO: process the data anyway? */
self->recv_progress = VFS301_ENDED;
dev->recv_progress = VFS301_ENDED;
return;
}
else
{
FpiUsbTransfer *new;
if (!vfs301_proto_process_data (self,
if (!vfs301_proto_process_data (dev,
transfer->length == VFS301_FP_RECV_LEN_1,
transfer->buffer,
transfer->actual_length))
{
self->recv_progress = VFS301_ENDED;
dev->recv_progress = VFS301_ENDED;
return;
}

View File

@@ -815,11 +815,13 @@ dev_close (FpImageDevice *dev)
GError *error = NULL;
FpDeviceVfs5011 *self = FPI_DEVICE_VFS5011 (dev);
;
g_usb_device_release_interface (fpi_device_get_usb_device (FP_DEVICE (dev)),
0, 0, &error);
g_free (self->capture_buffer);
g_slist_free_full (g_steal_pointer (&self->rows), g_free);
g_slist_free_full (self->rows, g_free);
fpi_image_device_close_complete (dev, error);
}

View File

@@ -42,7 +42,6 @@ struct _FpDeviceVirtualImage
GSocketListener *listener;
GSocketConnection *connection;
GCancellable *listen_cancellable;
GCancellable *cancellable;
gint socket_fd;
@@ -73,21 +72,14 @@ recv_image_img_recv_cb (GObject *source_object,
success = g_input_stream_read_all_finish (G_INPUT_STREAM (source_object), res, &bytes, &error);
/* Can't use self if the operation was cancelled. */
if (!success && g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
return;
self = FPI_DEVICE_VIRTUAL_IMAGE (user_data);
device = FP_IMAGE_DEVICE (self);
/* Consider success if we received the right amount of data, otherwise
* an error must have happened. */
if (bytes < self->recv_img->width * self->recv_img->height)
if (!success || bytes == 0)
{
if (!success)
g_warning ("Error receiving image data: %s", error->message);
else
g_warning ("Error receiving image data: end of stream before all data was read");
{
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
return;
g_warning ("Error receiving header for image data: %s", error->message);
}
self = FPI_DEVICE_VIRTUAL_IMAGE (user_data);
g_io_stream_close (G_IO_STREAM (self->connection), NULL, NULL);
@@ -95,6 +87,9 @@ recv_image_img_recv_cb (GObject *source_object,
return;
}
self = FPI_DEVICE_VIRTUAL_IMAGE (user_data);
device = FP_IMAGE_DEVICE (self);
if (self->automatic_finger)
fpi_image_device_report_finger_status (device, TRUE);
fpi_image_device_image_captured (device, g_steal_pointer (&self->recv_img));
@@ -117,7 +112,7 @@ recv_image_hdr_recv_cb (GObject *source_object,
success = g_input_stream_read_all_finish (G_INPUT_STREAM (source_object), res, &bytes, &error);
if (!success || bytes != sizeof (self->recv_img_hdr))
if (!success || bytes == 0)
{
if (!success)
{
@@ -126,10 +121,6 @@ recv_image_hdr_recv_cb (GObject *source_object,
return;
g_warning ("Error receiving header for image data: %s", error->message);
}
else if (bytes != 0)
{
g_warning ("Received incomplete header before end of stream.");
}
self = FPI_DEVICE_VIRTUAL_IMAGE (user_data);
g_io_stream_close (G_IO_STREAM (self->connection), NULL, NULL);
@@ -171,11 +162,6 @@ recv_image_hdr_recv_cb (GObject *source_object,
!!self->recv_img_hdr[1]);
break;
case -5:
/* -5 causes the device to disappear (no further data) */
fpi_device_remove (FP_DEVICE (self));
break;
default:
/* disconnect client, it didn't play fair */
g_io_stream_close (G_IO_STREAM (self->connection), NULL, NULL);
@@ -199,25 +185,15 @@ recv_image_hdr_recv_cb (GObject *source_object,
}
static void
recv_image (FpDeviceVirtualImage *self, GInputStream *stream)
recv_image (FpDeviceVirtualImage *dev, GInputStream *stream)
{
FpiImageDeviceState state;
g_object_get (self, "fpi-image-device-state", &state, NULL);
g_debug ("Starting image receive (if active), state is: %i", state);
/* Only register if the state is active. */
if (state >= FPI_IMAGE_DEVICE_STATE_IDLE)
{
g_input_stream_read_all_async (stream,
self->recv_img_hdr,
sizeof (self->recv_img_hdr),
G_PRIORITY_DEFAULT,
self->cancellable,
recv_image_hdr_recv_cb,
self);
}
g_input_stream_read_all_async (stream,
dev->recv_img_hdr,
sizeof (dev->recv_img_hdr),
G_PRIORITY_DEFAULT,
dev->cancellable,
recv_image_hdr_recv_cb,
dev);
}
static void
@@ -241,25 +217,11 @@ new_connection_cb (GObject *source_object, GAsyncResult *res, gpointer user_data
start_listen (dev);
}
/* Always accept further connections (but we disconnect them immediately
/* Always further connections (but we disconnect them immediately
* if we already have a connection). */
start_listen (dev);
if (dev->connection)
{
/* We may not have noticed that the stream was closed,
* if the device is deactivated.
* Cancel any ongoing operation on the old connection. */
g_cancellable_cancel (dev->cancellable);
g_clear_object (&dev->cancellable);
dev->cancellable = g_cancellable_new ();
g_clear_object (&dev->connection);
}
if (dev->connection)
{
g_warning ("Rejecting new connection");
g_io_stream_close (G_IO_STREAM (connection), NULL, NULL);
g_object_unref (connection);
return;
@@ -269,15 +231,16 @@ new_connection_cb (GObject *source_object, GAsyncResult *res, gpointer user_data
dev->automatic_finger = TRUE;
stream = g_io_stream_get_input_stream (G_IO_STREAM (connection));
fp_dbg ("Got a new connection!");
recv_image (dev, stream);
fp_dbg ("Got a new connection!");
}
static void
start_listen (FpDeviceVirtualImage *dev)
{
g_socket_listener_accept_async (dev->listener,
dev->listen_cancellable,
dev->cancellable,
new_connection_cb,
dev);
}
@@ -322,7 +285,6 @@ dev_init (FpImageDevice *dev)
self->listener = g_steal_pointer (&listener);
self->cancellable = g_cancellable_new ();
self->listen_cancellable = g_cancellable_new ();
start_listen (self);
@@ -338,9 +300,7 @@ dev_deinit (FpImageDevice *dev)
G_DEBUG_HERE ();
g_cancellable_cancel (self->cancellable);
g_cancellable_cancel (self->listen_cancellable);
g_clear_object (&self->cancellable);
g_clear_object (&self->listen_cancellable);
g_clear_object (&self->listener);
g_clear_object (&self->connection);
@@ -348,60 +308,18 @@ dev_deinit (FpImageDevice *dev)
fpi_device_add_timeout (FP_DEVICE (dev), 100, (FpTimeoutFunc) fpi_image_device_close_complete, NULL, NULL);
}
static void
dev_activate (FpImageDevice *dev)
{
FpDeviceVirtualImage *self = FPI_DEVICE_VIRTUAL_IMAGE (dev);
fpi_image_device_activate_complete (dev, NULL);
if (self->connection)
recv_image (self, g_io_stream_get_input_stream (G_IO_STREAM (self->connection)));
}
static void
dev_deactivate (FpImageDevice *dev)
{
FpDeviceVirtualImage *self = FPI_DEVICE_VIRTUAL_IMAGE (dev);
G_DEBUG_HERE ();
g_cancellable_cancel (self->cancellable);
g_clear_object (&self->cancellable);
self->cancellable = g_cancellable_new ();
/* XXX: Need to wait for the operation to be cancelled. */
fpi_device_add_timeout (FP_DEVICE (dev), 10, (FpTimeoutFunc) fpi_image_device_deactivate_complete, NULL, NULL);
}
static void
dev_notify_removed_cb (FpDevice *dev)
{
FpiImageDeviceState state;
gboolean removed;
g_object_get (dev,
"fpi-image-device-state", &state,
"removed", &removed,
NULL);
if (!removed || state == FPI_IMAGE_DEVICE_STATE_INACTIVE)
return;
/* This error will be converted to an FP_DEVICE_ERROR_REMOVED by the
* surrounding layers. */
fpi_image_device_session_error (FP_IMAGE_DEVICE (dev),
fpi_device_error_new (FP_DEVICE_ERROR_PROTO));
/* Delay result to open up the possibility of testing race conditions. */
fpi_device_add_timeout (FP_DEVICE (dev), 100, (FpTimeoutFunc) fpi_image_device_deactivate_complete, NULL, NULL);
}
static void
fpi_device_virtual_image_init (FpDeviceVirtualImage *self)
{
/* NOTE: This is not nice, but we can generally rely on the underlying
* system to throw errors on the transport layer.
*/
g_signal_connect (self,
"notify::removed",
G_CALLBACK (dev_notify_removed_cb),
NULL);
}
static const FpIdEntry driver_ids[] = {
@@ -423,6 +341,5 @@ fpi_device_virtual_image_class_init (FpDeviceVirtualImageClass *klass)
img_class->img_open = dev_init;
img_class->img_close = dev_deinit;
img_class->activate = dev_activate;
img_class->deactivate = dev_deactivate;
}

View File

@@ -86,60 +86,6 @@ is_driver_allowed (const gchar *driver)
return FALSE;
}
typedef struct
{
FpContext *context;
FpDevice *device;
} RemoveDeviceData;
static gboolean
remove_device_idle_cb (RemoveDeviceData *data)
{
FpContextPrivate *priv = fp_context_get_instance_private (data->context);
guint idx = 0;
g_return_val_if_fail (g_ptr_array_find (priv->devices, data->device, &idx), G_SOURCE_REMOVE);
g_signal_emit (data->context, signals[DEVICE_REMOVED_SIGNAL], 0, data->device);
g_ptr_array_remove_index_fast (priv->devices, idx);
g_free (data);
return G_SOURCE_REMOVE;
}
static void
remove_device (FpContext *context, FpDevice *device)
{
RemoveDeviceData *data;
data = g_new (RemoveDeviceData, 1);
data->context = context;
data->device = device;
g_idle_add ((GSourceFunc) remove_device_idle_cb, data);
}
static void
device_remove_on_notify_open_cb (FpContext *context, GParamSpec *pspec, FpDevice *device)
{
remove_device (context, device);
}
static void
device_removed_cb (FpContext *context, FpDevice *device)
{
gboolean open = FALSE;
g_object_get (device, "open", &open, NULL);
/* Wait for device close if the device is currently still open. */
if (open)
g_signal_connect_swapped (device, "notify::open", (GCallback) device_remove_on_notify_open_cb, context);
else
remove_device (context, device);
}
static void
async_device_init_done_cb (GObject *source_object, GAsyncResult *res, gpointer user_data)
{
@@ -164,9 +110,6 @@ async_device_init_done_cb (GObject *source_object, GAsyncResult *res, gpointer u
}
g_ptr_array_add (priv->devices, device);
g_signal_connect_swapped (device, "removed", (GCallback) device_removed_cb, context);
g_signal_emit (context, signals[DEVICE_ADDED_SIGNAL], 0, device);
}
@@ -246,7 +189,12 @@ usb_device_removed_cb (FpContext *self, GUsbDevice *device, GUsbContext *usb_ctx
continue;
if (fpi_device_get_usb_device (dev) == device)
fpi_device_remove (dev);
{
g_signal_emit (self, signals[DEVICE_REMOVED_SIGNAL], 0, dev);
g_ptr_array_remove_index_fast (priv->devices, i);
return;
}
}
}
@@ -300,10 +248,6 @@ fp_context_class_init (FpContextClass *klass)
* @device: A #FpDevice
*
* This signal is emitted when a fingerprint reader is removed.
*
* It is guaranteed that the device has been closed before this signal
* is emitted. See the #FpDevice removed signal documentation for more
* information.
**/
signals[DEVICE_REMOVED_SIGNAL] = g_signal_new ("device-removed",
G_TYPE_FROM_CLASS (klass),

View File

@@ -29,7 +29,6 @@ typedef struct
GUsbDevice *usb_device;
const gchar *virtual_env;
gboolean is_removed;
gboolean is_open;
gchar *device_id;
@@ -50,8 +49,7 @@ typedef struct
GSource *current_task_idle_return_source;
/* State for tasks */
gboolean wait_for_finger;
FpFingerStatusFlags finger_status;
gboolean wait_for_finger;
} FpDevicePrivate;

View File

@@ -44,10 +44,8 @@ enum {
PROP_DEVICE_ID,
PROP_NAME,
PROP_OPEN,
PROP_REMOVED,
PROP_NR_ENROLL_STAGES,
PROP_SCAN_TYPE,
PROP_FINGER_STATUS,
PROP_FPI_ENVIRON,
PROP_FPI_USB_DEVICE,
PROP_FPI_DRIVER_DATA,
@@ -56,13 +54,6 @@ enum {
static GParamSpec *properties[N_PROPS];
enum {
REMOVED_SIGNAL,
N_SIGNALS
};
static guint signals[N_SIGNALS] = { 0, };
/**
* fp_device_retry_quark:
*
@@ -93,8 +84,6 @@ fp_device_cancel_in_idle_cb (gpointer user_data)
cls->cancel (self);
fpi_device_report_finger_status (self, FP_FINGER_STATUS_NONE);
return G_SOURCE_REMOVE;
}
@@ -192,10 +181,6 @@ fp_device_get_property (GObject *object,
g_value_set_enum (value, priv->scan_type);
break;
case PROP_FINGER_STATUS:
g_value_set_flags (value, priv->finger_status);
break;
case PROP_DRIVER:
g_value_set_static_string (value, FP_DEVICE_GET_CLASS (priv)->id);
break;
@@ -212,10 +197,6 @@ fp_device_get_property (GObject *object,
g_value_set_boolean (value, priv->is_open);
break;
case PROP_REMOVED:
g_value_set_boolean (value, priv->is_removed);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
@@ -329,13 +310,6 @@ fp_device_class_init (FpDeviceClass *klass)
FP_TYPE_SCAN_TYPE, FP_SCAN_TYPE_SWIPE,
G_PARAM_STATIC_STRINGS | G_PARAM_READABLE);
properties[PROP_FINGER_STATUS] =
g_param_spec_flags ("finger-status",
"FingerStatus",
"The status of the finger",
FP_TYPE_FINGER_STATUS_FLAGS, FP_FINGER_STATUS_NONE,
G_PARAM_STATIC_STRINGS | G_PARAM_READABLE);
properties[PROP_DRIVER] =
g_param_spec_string ("driver",
"Driver",
@@ -363,41 +337,6 @@ fp_device_class_init (FpDeviceClass *klass)
"Whether the device is open or not", FALSE,
G_PARAM_STATIC_STRINGS | G_PARAM_READABLE);
properties[PROP_REMOVED] =
g_param_spec_boolean ("removed",
"Removed",
"Whether the device has been removed from the system", FALSE,
G_PARAM_STATIC_STRINGS | G_PARAM_READABLE);
/**
* FpDevice::removed:
* @device: the #FpDevice instance that emitted the signal
*
* This signal is emitted after the device has been removed and no operation
* is pending anymore.
*
* The API user is still required to close a removed device. The above
* guarantee means that the call to close the device can be made immediately
* from the signal handler.
*
* The close operation will return FP_DEVICE_ERROR_REMOVED, but the device
* will still be considered closed afterwards.
*
* The device will only be removed from the #FpContext after it has been
* closed by the API user.
**/
signals[REMOVED_SIGNAL] = g_signal_new ("removed",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
0,
NULL,
NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE,
0);
/* Private properties */
/**
* FpDevice::fpi-environ: (skip)
*
@@ -530,26 +469,6 @@ fp_device_get_scan_type (FpDevice *device)
return priv->scan_type;
}
/**
* fp_device_get_finger_status:
* @device: A #FpDevice
*
* Retrieves the finger status flags for the device.
* This can be used by the UI to present the relevant feedback, although it
* is not guaranteed to be a relevant value when not performing any action.
*
* Returns: The current #FpFingerStatusFlags
*/
FpFingerStatusFlags
fp_device_get_finger_status (FpDevice *device)
{
FpDevicePrivate *priv = fp_device_get_instance_private (device);
g_return_val_if_fail (FP_IS_DEVICE (device), FP_FINGER_STATUS_NONE);
return priv->finger_status;
}
/**
* fp_device_get_nr_enroll_stages:
* @device: A #FpDevice
@@ -684,7 +603,6 @@ fp_device_open (FpDevice *device,
priv->current_action = FPI_DEVICE_ACTION_OPEN;
priv->current_task = g_steal_pointer (&task);
maybe_cancel_on_cancelled (device, cancellable);
fpi_device_report_finger_status (device, FP_FINGER_STATUS_NONE);
FP_DEVICE_GET_CLASS (device)->open (device);
}
@@ -792,7 +710,7 @@ fp_device_close_finish (FpDevice *device,
* in. The driver may make use of this metadata, when e.g. storing the print on
* device memory. It is undefined whether this print is filled in by the driver
* and returned, or whether the driver will return a newly created print after
* enrollment succeeded.
* enrollment successed.
*/
void
fp_device_enroll (FpDevice *device,
@@ -1018,7 +936,6 @@ fp_device_identify (FpDevice *device,
g_autoptr(GTask) task = NULL;
FpDevicePrivate *priv = fp_device_get_instance_private (device);
FpMatchData *data;
int i;
task = g_task_new (device, cancellable, callback, user_data);
if (g_task_return_error_if_cancelled (task))
@@ -1043,13 +960,7 @@ fp_device_identify (FpDevice *device,
maybe_cancel_on_cancelled (device, cancellable);
data = g_new0 (FpMatchData, 1);
/* We cannot store the gallery directly, because the ptr array may not own
* a reference to each print. Also, the caller could in principle modify the
* GPtrArray afterwards.
*/
data->gallery = g_ptr_array_new_full (prints->len, g_object_unref);
for (i = 0; i < prints->len; i++)
g_ptr_array_add (data->gallery, g_object_ref (g_ptr_array_index (prints, i)));
data->gallery = g_ptr_array_ref (prints);
data->match_cb = match_cb;
data->match_data = match_data;
data->match_destroy = match_destroy;

View File

@@ -91,7 +91,6 @@ typedef enum {
* @FP_DEVICE_ERROR_DATA_NOT_FOUND: Requested print was not found on device
* @FP_DEVICE_ERROR_DATA_FULL: No space on device available for operation
* @FP_DEVICE_ERROR_DATA_DUPLICATE: Enrolling template duplicates storaged templates
* @FP_DEVICE_ERROR_REMOVED: The device has been removed.
*
* Error codes for device operations. More specific errors from other domains
* such as #G_IO_ERROR or #G_USB_DEVICE_ERROR may also be reported.
@@ -107,8 +106,6 @@ typedef enum {
FP_DEVICE_ERROR_DATA_NOT_FOUND,
FP_DEVICE_ERROR_DATA_FULL,
FP_DEVICE_ERROR_DATA_DUPLICATE,
/* Leave some room to add more DATA related errors */
FP_DEVICE_ERROR_REMOVED = 0x100,
} FpDeviceError;
GQuark fp_device_retry_quark (void);
@@ -173,7 +170,6 @@ const gchar *fp_device_get_device_id (FpDevice *device);
const gchar *fp_device_get_name (FpDevice *device);
gboolean fp_device_is_open (FpDevice *device);
FpScanType fp_device_get_scan_type (FpDevice *device);
FpFingerStatusFlags fp_device_get_finger_status (FpDevice *device);
gint fp_device_get_nr_enroll_stages (FpDevice *device);
gboolean fp_device_supports_identify (FpDevice *device);

View File

@@ -27,19 +27,17 @@ typedef struct
{
FpiImageDeviceState state;
gboolean active;
gboolean cancelling;
gboolean finger_present;
gboolean enroll_await_on_pending;
gint enroll_stage;
gboolean minutiae_scan_active;
GError *action_error;
FpImage *capture_image;
guint pending_activation_timeout_id;
gboolean pending_activation_timeout_waiting_finger_off;
gint bz3_threshold;
} FpImageDevicePrivate;
void fpi_image_device_activate (FpImageDevice *image_device);
void fpi_image_device_deactivate (FpImageDevice *image_device,
gboolean cancelling);
void fpi_image_device_deactivate (FpImageDevice *image_device);

View File

@@ -56,6 +56,44 @@ static guint signals[LAST_SIGNAL] = { 0 };
* - sanitize_image seems a bit odd, in particular the sizing stuff.
**/
/* Static helper functions */
static gboolean
pending_activation_timeout (gpointer user_data)
{
FpImageDevice *self = FP_IMAGE_DEVICE (user_data);
FpDevice *device = FP_DEVICE (self);
FpImageDevicePrivate *priv = fp_image_device_get_instance_private (self);
FpiDeviceAction action = fpi_device_get_current_action (device);
GError *error;
priv->pending_activation_timeout_id = 0;
if (priv->pending_activation_timeout_waiting_finger_off)
error = fpi_device_retry_new_msg (FP_DEVICE_RETRY_REMOVE_FINGER,
"Remove finger before requesting another scan operation");
else
error = fpi_device_retry_new (FP_DEVICE_RETRY_GENERAL);
if (action == FPI_DEVICE_ACTION_VERIFY)
{
fpi_device_verify_report (device, FPI_MATCH_ERROR, NULL, error);
fpi_device_verify_complete (device, NULL);
}
else if (action == FPI_DEVICE_ACTION_IDENTIFY)
{
fpi_device_identify_report (device, NULL, NULL, error);
fpi_device_identify_complete (device, NULL);
}
else
{
/* Can this happen for enroll? */
fpi_device_action_error (device, error);
}
return G_SOURCE_REMOVE;
}
/* Callbacks/vfuncs */
static void
fp_image_device_open (FpDevice *device)
@@ -74,14 +112,26 @@ fp_image_device_close (FpDevice *device)
FpImageDeviceClass *cls = FP_IMAGE_DEVICE_GET_CLASS (self);
FpImageDevicePrivate *priv = fp_image_device_get_instance_private (self);
g_assert (priv->active == FALSE);
cls->img_close (self);
/* In the close case we may need to wait/force deactivation first.
* Three possible cases:
* 1. We are inactive
* -> immediately close
* 2. We are waiting for finger off
* -> immediately deactivate
* 3. We are deactivating
* -> handled by deactivate_complete */
if (!priv->active)
cls->img_close (self);
else if (priv->state != FPI_IMAGE_DEVICE_STATE_INACTIVE)
fpi_image_device_deactivate (self);
}
static void
fp_image_device_cancel_action (FpDevice *device)
{
FpImageDevice *self = FP_IMAGE_DEVICE (device);
FpImageDevicePrivate *priv = fp_image_device_get_instance_private (self);
FpiDeviceAction action;
action = fpi_device_get_current_action (device);
@@ -92,7 +142,17 @@ fp_image_device_cancel_action (FpDevice *device)
action == FPI_DEVICE_ACTION_VERIFY ||
action == FPI_DEVICE_ACTION_IDENTIFY ||
action == FPI_DEVICE_ACTION_CAPTURE)
fpi_image_device_deactivate (self, TRUE);
{
priv->cancelling = TRUE;
fpi_image_device_deactivate (self);
priv->cancelling = FALSE;
/* XXX: Some nicer way of doing this would be good. */
fpi_device_action_error (FP_DEVICE (self),
g_error_new (G_IO_ERROR,
G_IO_ERROR_CANCELLED,
"Device operation was cancelled"));
}
}
static void
@@ -128,9 +188,27 @@ fp_image_device_start_capture_action (FpDevice *device)
}
priv->enroll_stage = 0;
/* The internal state machine guarantees both of these. */
g_assert (!priv->finger_present);
g_assert (!priv->minutiae_scan_active);
priv->enroll_await_on_pending = FALSE;
/* The device might still be deactivating from a previous call.
* In that situation, try to wait for a bit before reporting back an
* error (which will usually say that the user should remove the
* finger).
*/
if (priv->state != FPI_IMAGE_DEVICE_STATE_INACTIVE || priv->active)
{
g_debug ("Got a new request while the device was still active");
g_assert (priv->pending_activation_timeout_id == 0);
priv->pending_activation_timeout_id =
g_timeout_add (100, pending_activation_timeout, device);
if (priv->state == FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_OFF)
priv->pending_activation_timeout_waiting_finger_off = TRUE;
else
priv->pending_activation_timeout_waiting_finger_off = FALSE;
return;
}
/* And activate the device; we rely on fpi_image_device_activate_complete()
* to be called when done (or immediately). */
@@ -147,6 +225,7 @@ fp_image_device_finalize (GObject *object)
FpImageDevicePrivate *priv = fp_image_device_get_instance_private (self);
g_assert (priv->active == FALSE);
g_clear_handle_id (&priv->pending_activation_timeout_id, g_source_remove);
G_OBJECT_CLASS (fp_image_device_parent_class)->finalize (object);
}

View File

@@ -281,7 +281,7 @@ fp_image_detect_minutiae_thread_func (GTask *task,
gint map_w, map_h;
gint bw, bh, bd;
gint r;
g_autofree LFSPARMS *lfsparms = NULL;
g_autofree LFSPARMS *lfsparms;
/* Normalize the image first */
if (data->flags & FPI_IMAGE_H_FLIPPED)

View File

@@ -667,25 +667,36 @@ fp_print_serialize (FpPrint *print,
for (i = 0; i < print->prints->len; i++)
{
struct xyt_struct *xyt = g_ptr_array_index (print->prints, i);
gint j;
gint32 *col = g_new (gint32, xyt->nrows);
g_variant_builder_open (&nested, G_VARIANT_TYPE ("(aiaiai)"));
for (j = 0; j < xyt->nrows; j++)
col[j] = GINT32_TO_LE (xyt->xcol[j]);
g_variant_builder_add_value (&nested,
g_variant_new_fixed_array (G_VARIANT_TYPE_INT32,
xyt->xcol,
col,
xyt->nrows,
sizeof (xyt->xcol[0])));
sizeof (col[0])));
for (j = 0; j < xyt->nrows; j++)
col[j] = GINT32_TO_LE (xyt->ycol[j]);
g_variant_builder_add_value (&nested,
g_variant_new_fixed_array (G_VARIANT_TYPE_INT32,
xyt->ycol,
col,
xyt->nrows,
sizeof (xyt->ycol[0])));
sizeof (col[0])));
for (j = 0; j < xyt->nrows; j++)
col[j] = GINT32_TO_LE (xyt->thetacol[j]);
g_variant_builder_add_value (&nested,
g_variant_new_fixed_array (G_VARIANT_TYPE_INT32,
xyt->thetacol,
col,
xyt->nrows,
sizeof (xyt->thetacol[0])));
sizeof (col[0])));
g_variant_builder_close (&nested);
g_free (col);
}
g_variant_builder_close (&nested);
@@ -808,7 +819,6 @@ fp_print_deserialize (const guchar *data,
"device-id", device_id,
"device-stored", device_stored,
NULL);
g_object_ref_sink (result);
fpi_print_set_type (result, FPI_PRINT_NBIS);
for (i = 0; i < g_variant_n_children (prints); i++)
{
@@ -858,7 +868,6 @@ fp_print_deserialize (const guchar *data,
"device-stored", device_stored,
"fpi-data", fp_data,
NULL);
g_object_ref_sink (result);
}
else
{
@@ -877,7 +886,8 @@ fp_print_deserialize (const guchar *data,
return g_steal_pointer (&result);
invalid_format:
g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA,
"Data could not be parsed");
return NULL;
*error = g_error_new_literal (G_IO_ERROR,
G_IO_ERROR_INVALID_DATA,
"Data could not be parsed");
return FALSE;
}

View File

@@ -66,20 +66,13 @@ typedef enum {
FP_FINGER_LAST = FP_FINGER_RIGHT_LITTLE,
} FpFinger;
/**
* FpFingerStatusFlags:
* @FP_FINGER_STATUS_NONE: Sensor has not the finger on it, nor requires it
* @FP_FINGER_STATUS_NEEDED: Sensor waits for the finger
* @FP_FINGER_STATUS_PRESENT: Sensor has the finger on it
*/
typedef enum {
FP_FINGER_STATUS_NONE = 0,
FP_FINGER_STATUS_NEEDED = 1 << 0,
FP_FINGER_STATUS_PRESENT = 1 << 1,
} FpFingerStatusFlags;
FpPrint *fp_print_new (FpDevice *device);
FpPrint *fp_print_new_from_data (guchar *data,
gsize length);
gboolean fp_print_to_data (guchar **data,
gsize length);
const gchar *fp_print_get_driver (FpPrint *print);
const gchar *fp_print_get_device_id (FpPrint *print);
FpImage *fp_print_get_image (FpPrint *print);

View File

@@ -23,7 +23,6 @@
#if !GLIB_CHECK_VERSION (2, 57, 0)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (GTypeClass, g_type_class_unref);
G_DEFINE_AUTOPTR_CLEANUP_FUNC (GEnumClass, g_type_class_unref);
G_DEFINE_AUTOPTR_CLEANUP_FUNC (GFlagsClass, g_type_class_unref);
G_DEFINE_AUTOPTR_CLEANUP_FUNC (GParamSpec, g_param_spec_unref);
#else
/* Re-define G_SOURCE_FUNC as we are technically not allowed to use it with
@@ -38,9 +37,3 @@ typedef struct _FpDeviceClass FpDeviceClass;
G_DEFINE_AUTOPTR_CLEANUP_FUNC (FpDeviceClass, g_type_class_unref);
G_DEFINE_AUTOPTR_CLEANUP_FUNC (GDate, g_date_free);
#endif
#if __GNUC__ > 10 || (__GNUC__ == 10 && __GNUC_MINOR__ >= 1)
#define FP_GNUC_ACCESS(m, p, s) __attribute__((access (m, p, s)))
#else
#define FP_GNUC_ACCESS(m, p, s)
#endif

View File

@@ -139,10 +139,6 @@ fpi_device_error_new (FpDeviceError error)
msg = "This finger has already enrolled, please try a different finger";
break;
case FP_DEVICE_ERROR_REMOVED:
msg = "This device has been removed from the system.";
break;
default:
g_warning ("Unsupported error, returning general error instead!");
error = FP_DEVICE_ERROR_GENERAL;
@@ -580,49 +576,6 @@ fpi_device_get_cancellable (FpDevice *device)
return g_task_get_cancellable (priv->current_task);
}
static void
emit_removed_on_task_completed (FpDevice *device)
{
g_signal_emit_by_name (device, "removed");
}
/**
* fpi_device_remove:
* @device: The #FpDevice
*
* Called to signal to the #FpDevice that it has been unplugged (physically
* removed from the system).
*
* For USB devices, this API is called automatically by #FpContext.
*/
void
fpi_device_remove (FpDevice *device)
{
FpDevicePrivate *priv = fp_device_get_instance_private (device);
g_return_if_fail (FP_IS_DEVICE (device));
g_return_if_fail (!priv->is_removed);
priv->is_removed = TRUE;
g_object_notify (G_OBJECT (device), "removed");
/* If there is a pending action, we wait for it to fail, otherwise we
* immediately emit the "removed" signal. */
if (priv->current_task)
{
g_signal_connect_object (priv->current_task,
"notify::completed",
(GCallback) emit_removed_on_task_completed,
device,
G_CONNECT_SWAPPED);
}
else
{
g_signal_emit_by_name (device, "removed");
}
}
/**
* fpi_device_action_error:
* @device: The #FpDevice
@@ -738,7 +691,6 @@ fp_device_task_return_in_idle_cb (gpointer user_data)
FpDeviceTaskReturnData *data = user_data;
FpDevicePrivate *priv = fp_device_get_instance_private (data->device);
g_autofree char *action_str = NULL;
FpiDeviceAction action;
g_autoptr(GTask) task = NULL;
@@ -747,24 +699,9 @@ fp_device_task_return_in_idle_cb (gpointer user_data)
g_debug ("Completing action %s in idle!", action_str);
task = g_steal_pointer (&priv->current_task);
action = priv->current_action;
priv->current_action = FPI_DEVICE_ACTION_NONE;
priv->current_task_idle_return_source = NULL;
/* Return FP_DEVICE_ERROR_REMOVED if the device is removed,
* with the exception of a successful open, which is an odd corner case. */
if (priv->is_removed &&
((action != FPI_DEVICE_ACTION_OPEN) ||
(action == FPI_DEVICE_ACTION_OPEN && data->type == FP_DEVICE_TASK_RETURN_ERROR)))
{
g_task_return_error (task, fpi_device_error_new (FP_DEVICE_ERROR_REMOVED));
/* NOTE: The removed signal will be emitted from the GTask
* notify::completed if that is necessary. */
return G_SOURCE_REMOVE;
}
switch (data->type)
{
case FP_DEVICE_TASK_RETURN_INT:
@@ -776,17 +713,16 @@ fp_device_task_return_in_idle_cb (gpointer user_data)
break;
case FP_DEVICE_TASK_RETURN_OBJECT:
g_task_return_pointer (task, g_steal_pointer (&data->result),
g_object_unref);
g_task_return_pointer (task, data->result, g_object_unref);
break;
case FP_DEVICE_TASK_RETURN_PTR_ARRAY:
g_task_return_pointer (task, g_steal_pointer (&data->result),
g_task_return_pointer (task, data->result,
(GDestroyNotify) g_ptr_array_unref);
break;
case FP_DEVICE_TASK_RETURN_ERROR:
g_task_return_error (task, g_steal_pointer (&data->result));
g_task_return_error (task, data->result);
break;
default:
@@ -799,30 +735,6 @@ fp_device_task_return_in_idle_cb (gpointer user_data)
static void
fpi_device_task_return_data_free (FpDeviceTaskReturnData *data)
{
if (data->result)
{
switch (data->type)
{
case FP_DEVICE_TASK_RETURN_INT:
case FP_DEVICE_TASK_RETURN_BOOL:
break;
case FP_DEVICE_TASK_RETURN_OBJECT:
g_clear_object ((GObject **) &data->result);
break;
case FP_DEVICE_TASK_RETURN_PTR_ARRAY:
g_clear_pointer ((GPtrArray **) &data->result, g_ptr_array_unref);
break;
case FP_DEVICE_TASK_RETURN_ERROR:
g_clear_error ((GError **) &data->result);
break;
default:
g_assert_not_reached ();
}
}
g_object_unref (data->device);
g_free (data);
}
@@ -875,7 +787,6 @@ fpi_device_probe_complete (FpDevice *device,
g_debug ("Device reported probe completion");
clear_device_cancel_action (device);
fpi_device_report_finger_status (device, FP_FINGER_STATUS_NONE);
if (!error)
{
@@ -918,7 +829,6 @@ fpi_device_open_complete (FpDevice *device, GError *error)
g_debug ("Device reported open completion");
clear_device_cancel_action (device);
fpi_device_report_finger_status (device, FP_FINGER_STATUS_NONE);
if (!error)
{
@@ -952,7 +862,6 @@ fpi_device_close_complete (FpDevice *device, GError *error)
g_debug ("Device reported close completion");
clear_device_cancel_action (device);
fpi_device_report_finger_status (device, FP_FINGER_STATUS_NONE);
switch (priv->type)
{
@@ -976,17 +885,17 @@ fpi_device_close_complete (FpDevice *device, GError *error)
return;
}
/* Always consider the device closed. Drivers should try hard to close the
* device. Generally, e.g. cancellations should be ignored.
*/
priv->is_open = FALSE;
g_object_notify (G_OBJECT (device), "open");
if (!error)
fpi_device_return_task_in_idle (device, FP_DEVICE_TASK_RETURN_BOOL,
GUINT_TO_POINTER (TRUE));
{
priv->is_open = FALSE;
g_object_notify (G_OBJECT (device), "open");
fpi_device_return_task_in_idle (device, FP_DEVICE_TASK_RETURN_BOOL,
GUINT_TO_POINTER (TRUE));
}
else
fpi_device_return_task_in_idle (device, FP_DEVICE_TASK_RETURN_ERROR, error);
{
fpi_device_return_task_in_idle (device, FP_DEVICE_TASK_RETURN_ERROR, error);
}
}
/**
@@ -1009,14 +918,12 @@ fpi_device_enroll_complete (FpDevice *device, FpPrint *print, GError *error)
g_debug ("Device reported enroll completion");
clear_device_cancel_action (device);
fpi_device_report_finger_status (device, FP_FINGER_STATUS_NONE);
if (!error)
{
if (FP_IS_PRINT (print))
{
FpiPrintType print_type;
g_autofree char *finger_str = NULL;
g_object_get (print, "fpi-type", &print_type, NULL);
if (print_type == FPI_PRINT_UNDEFINED)
@@ -1030,9 +937,6 @@ fpi_device_enroll_complete (FpDevice *device, FpPrint *print, GError *error)
return;
}
finger_str = g_enum_to_string (FP_TYPE_FINGER, fp_print_get_finger (print));
g_debug ("Print for finger %s enrolled", finger_str);
fpi_device_return_task_in_idle (device, FP_DEVICE_TASK_RETURN_OBJECT, print);
}
else
@@ -1081,7 +985,6 @@ fpi_device_verify_complete (FpDevice *device,
data = g_task_get_task_data (priv->current_task);
clear_device_cancel_action (device);
fpi_device_report_finger_status (device, FP_FINGER_STATUS_NONE);
if (!error)
{
@@ -1141,7 +1044,6 @@ fpi_device_identify_complete (FpDevice *device,
data = g_task_get_task_data (priv->current_task);
clear_device_cancel_action (device);
fpi_device_report_finger_status (device, FP_FINGER_STATUS_NONE);
if (!error)
{
@@ -1157,7 +1059,7 @@ fpi_device_identify_complete (FpDevice *device,
}
else
{
fpi_device_return_task_in_idle (device, FP_DEVICE_TASK_RETURN_BOOL, GUINT_TO_POINTER (TRUE));
fpi_device_return_task_in_idle (device, FP_DEVICE_TASK_RETURN_INT, GINT_TO_POINTER (TRUE));
}
}
else
@@ -1198,7 +1100,6 @@ fpi_device_capture_complete (FpDevice *device,
g_debug ("Device reported capture completion");
clear_device_cancel_action (device);
fpi_device_report_finger_status (device, FP_FINGER_STATUS_NONE);
if (!error)
{
@@ -1244,7 +1145,6 @@ fpi_device_delete_complete (FpDevice *device,
g_debug ("Device reported deletion completion");
clear_device_cancel_action (device);
fpi_device_report_finger_status (device, FP_FINGER_STATUS_NONE);
if (!error)
fpi_device_return_task_in_idle (device, FP_DEVICE_TASK_RETURN_BOOL,
@@ -1279,7 +1179,6 @@ fpi_device_list_complete (FpDevice *device,
g_debug ("Device reported listing completion");
clear_device_cancel_action (device);
fpi_device_report_finger_status (device, FP_FINGER_STATUS_NONE);
if (prints && error)
{
@@ -1495,59 +1394,3 @@ fpi_device_identify_report (FpDevice *device,
if (call_cb && data->match_cb)
data->match_cb (device, data->match, data->print, data->match_data, data->error);
}
/**
* fpi_device_report_finger_status:
* @device: The #FpDevice
* @finger_status: The current #FpFingerStatusFlags to report
*
* Report the finger status for the @device.
* This can be used by UI to give a feedback
*
* Returns: %TRUE if changed
*/
gboolean
fpi_device_report_finger_status (FpDevice *device,
FpFingerStatusFlags finger_status)
{
FpDevicePrivate *priv = fp_device_get_instance_private (device);
g_autofree char *status_string = NULL;
if (priv->finger_status == finger_status)
return FALSE;
status_string = g_flags_to_string (FP_TYPE_FINGER_STATUS_FLAGS, finger_status);
fp_dbg ("Device reported finger status change: %s", status_string);
priv->finger_status = finger_status;
g_object_notify (G_OBJECT (device), "finger-status");
return TRUE;
}
/**
* fpi_device_report_finger_status_changes:
* @device: The #FpDevice
* @added_status: The #FpFingerStatusFlags to add
* @added_status: The #FpFingerStatusFlags to remove
*
* Report the finger status for the @device adding the @added_status flags
* and removing the @removed_status flags.
*
* This can be used by UI to give a feedback
*
* Returns: %TRUE if changed
*/
gboolean
fpi_device_report_finger_status_changes (FpDevice *device,
FpFingerStatusFlags added_status,
FpFingerStatusFlags removed_status)
{
FpDevicePrivate *priv = fp_device_get_instance_private (device);
FpFingerStatusFlags finger_status = priv->finger_status;
finger_status |= added_status;
finger_status &= ~removed_status;
return fpi_device_report_finger_status (device, finger_status);
}

View File

@@ -202,7 +202,6 @@ void fpi_device_get_delete_data (FpDevice *device,
FpPrint **print);
GCancellable *fpi_device_get_cancellable (FpDevice *device);
void fpi_device_remove (FpDevice *device);
GSource * fpi_device_add_timeout (FpDevice *device,
gint interval,
@@ -256,10 +255,4 @@ void fpi_device_identify_report (FpDevice *device,
FpPrint *print,
GError *error);
gboolean fpi_device_report_finger_status (FpDevice *device,
FpFingerStatusFlags finger_status);
gboolean fpi_device_report_finger_status_changes (FpDevice *device,
FpFingerStatusFlags added_status,
FpFingerStatusFlags removed_status);
G_END_DECLS

View File

@@ -41,9 +41,6 @@ fp_image_device_get_instance_private (FpImageDevice *self)
g_type_class_get_instance_private_offset (img_class));
}
static void fp_image_device_change_state (FpImageDevice *self,
FpiImageDeviceState state);
/* Private shared functions */
void
@@ -54,105 +51,67 @@ fpi_image_device_activate (FpImageDevice *self)
g_assert (!priv->active);
/* We don't have a neutral ACTIVE state, but we always will
* go into WAIT_FINGER_ON afterwards. */
priv->state = FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON;
g_object_notify (G_OBJECT (self), "fpi-image-device-state");
/* We might have been waiting for deactivation to finish before
* starting the next operation. */
g_clear_handle_id (&priv->pending_activation_timeout_id, g_source_remove);
fp_dbg ("Activating image device");
fp_image_device_change_state (self, FPI_IMAGE_DEVICE_STATE_ACTIVATING);
cls->activate (self);
}
void
fpi_image_device_deactivate (FpImageDevice *self, gboolean cancelling)
fpi_image_device_deactivate (FpImageDevice *self)
{
FpDevice *device = FP_DEVICE (self);
FpImageDevicePrivate *priv = fp_image_device_get_instance_private (self);
FpImageDeviceClass *cls = FP_IMAGE_DEVICE_GET_CLASS (device);
if (!priv->active || priv->state == FPI_IMAGE_DEVICE_STATE_DEACTIVATING)
if (!priv->active || priv->state == FPI_IMAGE_DEVICE_STATE_INACTIVE)
{
/* XXX: We currently deactivate both from minutiae scan result
* and finger off report. */
fp_dbg ("Already deactivated, ignoring request.");
return;
}
if (!cancelling && priv->state != FPI_IMAGE_DEVICE_STATE_IDLE)
g_warning ("Deactivating image device while it is not idle, this should not happen.");
if (!priv->cancelling && priv->state == FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON)
g_warning ("Deactivating image device while waiting for finger, this should not happen.");
priv->state = FPI_IMAGE_DEVICE_STATE_INACTIVE;
g_object_notify (G_OBJECT (self), "fpi-image-device-state");
fp_dbg ("Deactivating image device");
fp_image_device_change_state (self, FPI_IMAGE_DEVICE_STATE_DEACTIVATING);
cls->deactivate (self);
}
/* Static helper functions */
/* This should not be called directly to activate/deactivate the device! */
static void
fp_image_device_change_state (FpImageDevice *self, FpiImageDeviceState state)
{
FpImageDevicePrivate *priv = fp_image_device_get_instance_private (self);
g_autofree char *prev_state_str = NULL;
g_autofree char *state_str = NULL;
gboolean transition_is_valid = FALSE;
gint i;
struct
{
FpiImageDeviceState from;
FpiImageDeviceState to;
} valid_transitions[] = {
{ FPI_IMAGE_DEVICE_STATE_INACTIVE, FPI_IMAGE_DEVICE_STATE_ACTIVATING },
/* Cannot change to inactive using this function. */
g_assert (state != FPI_IMAGE_DEVICE_STATE_INACTIVE);
{ FPI_IMAGE_DEVICE_STATE_ACTIVATING, FPI_IMAGE_DEVICE_STATE_IDLE },
{ FPI_IMAGE_DEVICE_STATE_ACTIVATING, FPI_IMAGE_DEVICE_STATE_INACTIVE },
{ FPI_IMAGE_DEVICE_STATE_IDLE, FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON },
{ FPI_IMAGE_DEVICE_STATE_IDLE, FPI_IMAGE_DEVICE_STATE_CAPTURE }, /* raw mode -- currently not supported */
{ FPI_IMAGE_DEVICE_STATE_IDLE, FPI_IMAGE_DEVICE_STATE_DEACTIVATING },
{ FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON, FPI_IMAGE_DEVICE_STATE_CAPTURE },
{ FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON, FPI_IMAGE_DEVICE_STATE_DEACTIVATING }, /* cancellation */
{ FPI_IMAGE_DEVICE_STATE_CAPTURE, FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_OFF },
{ FPI_IMAGE_DEVICE_STATE_CAPTURE, FPI_IMAGE_DEVICE_STATE_IDLE }, /* raw mode -- currently not supported */
{ FPI_IMAGE_DEVICE_STATE_CAPTURE, FPI_IMAGE_DEVICE_STATE_DEACTIVATING }, /* cancellation */
{ FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_OFF, FPI_IMAGE_DEVICE_STATE_IDLE },
{ FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_OFF, FPI_IMAGE_DEVICE_STATE_DEACTIVATING }, /* cancellation */
{ FPI_IMAGE_DEVICE_STATE_DEACTIVATING, FPI_IMAGE_DEVICE_STATE_INACTIVE },
};
/* We might have been waiting for the finger to go OFF to start the
* next operation. */
g_clear_handle_id (&priv->pending_activation_timeout_id, g_source_remove);
prev_state_str = g_enum_to_string (FPI_TYPE_IMAGE_DEVICE_STATE, priv->state);
state_str = g_enum_to_string (FPI_TYPE_IMAGE_DEVICE_STATE, state);
fp_dbg ("Image device internal state change from %s to %s",
prev_state_str, state_str);
for (i = 0; i < G_N_ELEMENTS (valid_transitions); i++)
{
if (valid_transitions[i].from == priv->state && valid_transitions[i].to == state)
{
transition_is_valid = TRUE;
break;
}
}
if (!transition_is_valid)
g_warning ("Internal state machine issue: transition from %s to %s should not happen!",
prev_state_str, state_str);
priv->state = state;
g_object_notify (G_OBJECT (self), "fpi-image-device-state");
g_signal_emit_by_name (self, "fpi-image-device-state-changed", priv->state);
if (state == FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON)
{
fpi_device_report_finger_status_changes (FP_DEVICE (self),
FP_FINGER_STATUS_NEEDED,
FP_FINGER_STATUS_NONE);
}
else if (state == FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_OFF)
{
fpi_device_report_finger_status_changes (FP_DEVICE (self),
FP_FINGER_STATUS_NONE,
FP_FINGER_STATUS_NEEDED);
}
}
static void
@@ -160,75 +119,15 @@ fp_image_device_enroll_maybe_await_finger_on (FpImageDevice *self)
{
FpImageDevicePrivate *priv = fp_image_device_get_instance_private (self);
/* We wait for both the minutiae scan to complete and the finger to
* be removed before we switch to AWAIT_FINGER_ON. */
if (priv->minutiae_scan_active || priv->finger_present)
return;
fp_image_device_change_state (self, FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON);
}
static void
fp_image_device_maybe_complete_action (FpImageDevice *self, GError *error)
{
FpImageDevicePrivate *priv = fp_image_device_get_instance_private (self);
FpDevice *device = FP_DEVICE (self);
FpiDeviceAction action;
if (error)
if (priv->enroll_await_on_pending)
{
/* Keep the first error we encountered, but not if it is of type retry */
if (priv->action_error && !(priv->action_error->domain == FP_DEVICE_RETRY))
{
g_warning ("Will complete with first error, new error was: %s", error->message);
g_clear_error (&error);
}
else
{
g_clear_error (&priv->action_error);
priv->action_error = error;
}
}
/* Do not complete if the device is still active or a minutiae scan is pending. */
if (priv->active || priv->minutiae_scan_active)
return;
if (!priv->action_error)
g_cancellable_set_error_if_cancelled (fpi_device_get_cancellable (device), &priv->action_error);
if (priv->action_error)
{
fpi_device_action_error (device, g_steal_pointer (&priv->action_error));
g_clear_object (&priv->capture_image);
return;
}
/* We are done, report the result. */
action = fpi_device_get_current_action (FP_DEVICE (self));
if (action == FPI_DEVICE_ACTION_ENROLL)
{
FpPrint *enroll_print;
fpi_device_get_enroll_data (device, &enroll_print);
fpi_device_enroll_complete (device, g_object_ref (enroll_print), NULL);
}
else if (action == FPI_DEVICE_ACTION_VERIFY)
{
fpi_device_verify_complete (device, NULL);
}
else if (action == FPI_DEVICE_ACTION_IDENTIFY)
{
fpi_device_identify_complete (device, NULL);
}
else if (action == FPI_DEVICE_ACTION_CAPTURE)
{
fpi_device_capture_complete (device, g_steal_pointer (&priv->capture_image), NULL);
priv->enroll_await_on_pending = FALSE;
fp_image_device_change_state (self, FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON);
}
else
{
g_assert_not_reached ();
fp_dbg ("Awaiting finger on");
priv->enroll_await_on_pending = TRUE;
}
}
@@ -244,16 +143,14 @@ fpi_image_device_minutiae_detected (GObject *source_object, GAsyncResult *res, g
FpiDeviceAction action;
/* Note: We rely on the device to not disappear during an operation. */
priv = fp_image_device_get_instance_private (FP_IMAGE_DEVICE (device));
priv->minutiae_scan_active = FALSE;
if (!fp_image_detect_minutiae_finish (image, res, &error))
{
/* Cancel operation . */
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
{
fp_image_device_maybe_complete_action (self, g_steal_pointer (&error));
fpi_image_device_deactivate (self, TRUE);
fpi_device_action_error (device, g_steal_pointer (&error));
fpi_image_device_deactivate (self);
return;
}
@@ -264,12 +161,13 @@ fpi_image_device_minutiae_detected (GObject *source_object, GAsyncResult *res, g
error = fpi_device_retry_new_msg (FP_DEVICE_RETRY_GENERAL, "Minutiae detection failed, please retry");
}
priv = fp_image_device_get_instance_private (FP_IMAGE_DEVICE (device));
action = fpi_device_get_current_action (device);
if (action == FPI_DEVICE_ACTION_CAPTURE)
{
priv->capture_image = g_steal_pointer (&image);
fp_image_device_maybe_complete_action (self, g_steal_pointer (&error));
fpi_device_capture_complete (device, g_steal_pointer (&image), error);
fpi_image_device_deactivate (self);
return;
}
@@ -283,9 +181,8 @@ fpi_image_device_minutiae_detected (GObject *source_object, GAsyncResult *res, g
if (error->domain != FP_DEVICE_RETRY)
{
fp_image_device_maybe_complete_action (self, g_steal_pointer (&error));
/* We might not yet be deactivating, if we are enrolling. */
fpi_image_device_deactivate (self, TRUE);
fpi_device_action_error (device, error);
fpi_image_device_deactivate (self);
return;
}
}
@@ -308,8 +205,8 @@ fpi_image_device_minutiae_detected (GObject *source_object, GAsyncResult *res, g
/* Start another scan or deactivate. */
if (priv->enroll_stage == IMG_ENROLL_STAGES)
{
fp_image_device_maybe_complete_action (self, g_steal_pointer (&error));
fpi_image_device_deactivate (self, FALSE);
fpi_device_enroll_complete (device, g_object_ref (enroll_print), NULL);
fpi_image_device_deactivate (self);
}
else
{
@@ -329,8 +226,8 @@ fpi_image_device_minutiae_detected (GObject *source_object, GAsyncResult *res, g
if (!error || error->domain == FP_DEVICE_RETRY)
fpi_device_verify_report (device, result, g_steal_pointer (&print), g_steal_pointer (&error));
fp_image_device_maybe_complete_action (self, g_steal_pointer (&error));
fpi_device_verify_complete (device, error);
fpi_image_device_deactivate (self);
}
else if (action == FPI_DEVICE_ACTION_IDENTIFY)
{
@@ -352,8 +249,8 @@ fpi_image_device_minutiae_detected (GObject *source_object, GAsyncResult *res, g
if (!error || error->domain == FP_DEVICE_RETRY)
fpi_device_identify_report (device, result, g_steal_pointer (&print), g_steal_pointer (&error));
fp_image_device_maybe_complete_action (self, g_steal_pointer (&error));
fpi_device_identify_complete (device, error);
fpi_image_device_deactivate (self);
}
else
{
@@ -408,19 +305,6 @@ fpi_image_device_report_finger_status (FpImageDevice *self,
FpImageDevicePrivate *priv = fp_image_device_get_instance_private (self);
FpiDeviceAction action;
if (present)
{
fpi_device_report_finger_status_changes (device,
FP_FINGER_STATUS_PRESENT,
FP_FINGER_STATUS_NONE);
}
else
{
fpi_device_report_finger_status_changes (device,
FP_FINGER_STATUS_NONE,
FP_FINGER_STATUS_PRESENT);
}
if (priv->state == FPI_IMAGE_DEVICE_STATE_INACTIVE)
{
/* Do we really want to always ignore such reports? We could
@@ -439,23 +323,27 @@ fpi_image_device_report_finger_status (FpImageDevice *self,
g_debug ("Image device reported finger status: %s", present ? "on" : "off");
priv->finger_present = present;
if (present && priv->state == FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON)
{
fp_image_device_change_state (self, FPI_IMAGE_DEVICE_STATE_CAPTURE);
}
else if (!present && priv->state == FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_OFF)
{
/* If we are in the non-enroll case, we always deactivate.
*
* In the enroll case, the decision can only be made after minutiae
* detection has finished.
*/
fp_image_device_change_state (self, FPI_IMAGE_DEVICE_STATE_IDLE);
/* We need to deactivate or continue to await finger */
/* There are three possible situations:
* 1. We are deactivating the device and the action is still in progress
* (minutiae detection).
* 2. We are still deactivating the device after an action completed
* 3. We were waiting for finger removal to start the new action
* Either way, we always end up deactivating except for the enroll case.
*
* The enroll case is special as AWAIT_FINGER_ON should only happen after
* minutiae detection to prevent deactivation (without cancellation)
* from the AWAIT_FINGER_ON state.
*/
if (action != FPI_DEVICE_ACTION_ENROLL)
fpi_image_device_deactivate (self, FALSE);
fpi_image_device_deactivate (self);
else
fp_image_device_enroll_maybe_await_finger_on (self);
}
@@ -490,9 +378,9 @@ fpi_image_device_image_captured (FpImageDevice *self, FpImage *image)
action == FPI_DEVICE_ACTION_IDENTIFY ||
action == FPI_DEVICE_ACTION_CAPTURE);
g_debug ("Image device captured an image");
fp_image_device_change_state (self, FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_OFF);
priv->minutiae_scan_active = TRUE;
g_debug ("Image device captured an image");
/* XXX: We also detect minutiae in capture mode, we solely do this
* to normalize the image which will happen as a by-product. */
@@ -500,9 +388,6 @@ fpi_image_device_image_captured (FpImageDevice *self, FpImage *image)
fpi_device_get_cancellable (FP_DEVICE (self)),
fpi_image_device_minutiae_detected,
self);
/* XXX: This is wrong if we add support for raw capture mode. */
fp_image_device_change_state (self, FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_OFF);
}
/**
@@ -538,27 +423,36 @@ fpi_image_device_retry_scan (FpImageDevice *self, FpDeviceRetry retry)
g_debug ("Reporting retry during enroll");
fpi_device_enroll_progress (FP_DEVICE (self), priv->enroll_stage, NULL, error);
/* Wait for finger removal and re-touch.
* TODO: Do we need to check that the finger is already off? */
priv->enroll_await_on_pending = TRUE;
fp_image_device_change_state (self, FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_OFF);
}
else if (action == FPI_DEVICE_ACTION_VERIFY)
{
fpi_device_verify_report (FP_DEVICE (self), FPI_MATCH_ERROR, NULL, error);
fp_image_device_maybe_complete_action (self, NULL);
fpi_image_device_deactivate (self, TRUE);
priv->cancelling = TRUE;
fpi_image_device_deactivate (self);
priv->cancelling = FALSE;
fpi_device_verify_complete (FP_DEVICE (self), NULL);
}
else if (action == FPI_DEVICE_ACTION_IDENTIFY)
{
fpi_device_identify_report (FP_DEVICE (self), NULL, NULL, error);
fp_image_device_maybe_complete_action (self, NULL);
fpi_image_device_deactivate (self, TRUE);
priv->cancelling = TRUE;
fpi_image_device_deactivate (self);
priv->cancelling = FALSE;
fpi_device_identify_complete (FP_DEVICE (self), NULL);
}
else
{
/* The capture case where there is no early reporting. */
g_debug ("Abort current operation due to retry (no early-reporting)");
fp_image_device_maybe_complete_action (self, error);
fpi_image_device_deactivate (self, TRUE);
/* We abort the operation and let the surrounding code retry in the
* non-enroll case (this is identical to a session error). */
g_debug ("Abort current operation due to retry (non-enroll case)");
priv->cancelling = TRUE;
fpi_image_device_deactivate (self);
priv->cancelling = FALSE;
fpi_device_action_error (FP_DEVICE (self), error);
}
}
@@ -617,8 +511,10 @@ fpi_image_device_session_error (FpImageDevice *self, GError *error)
if (error->domain == FP_DEVICE_RETRY)
g_warning ("Driver should report retries using fpi_image_device_retry_scan!");
fp_image_device_maybe_complete_action (self, error);
fpi_image_device_deactivate (self, TRUE);
priv->cancelling = TRUE;
fpi_image_device_deactivate (self);
priv->cancelling = FALSE;
fpi_device_action_error (FP_DEVICE (self), error);
}
/**
@@ -637,7 +533,6 @@ fpi_image_device_activate_complete (FpImageDevice *self, GError *error)
action = fpi_device_get_current_action (FP_DEVICE (self));
g_return_if_fail (priv->active == FALSE);
g_return_if_fail (priv->state == FPI_IMAGE_DEVICE_STATE_ACTIVATING);
g_return_if_fail (action == FPI_DEVICE_ACTION_ENROLL ||
action == FPI_DEVICE_ACTION_VERIFY ||
action == FPI_DEVICE_ACTION_IDENTIFY ||
@@ -656,7 +551,6 @@ fpi_image_device_activate_complete (FpImageDevice *self, GError *error)
/* We always want to capture at this point, move to AWAIT_FINGER
* state. */
fp_image_device_change_state (self, FPI_IMAGE_DEVICE_STATE_IDLE);
fp_image_device_change_state (self, FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON);
}
@@ -671,20 +565,36 @@ void
fpi_image_device_deactivate_complete (FpImageDevice *self, GError *error)
{
FpImageDevicePrivate *priv = fp_image_device_get_instance_private (self);
FpImageDeviceClass *cls = FP_IMAGE_DEVICE_GET_CLASS (self);
FpiDeviceAction action;
g_return_if_fail (priv->active == TRUE);
g_return_if_fail (priv->state == FPI_IMAGE_DEVICE_STATE_DEACTIVATING);
g_return_if_fail (priv->state == FPI_IMAGE_DEVICE_STATE_INACTIVE);
g_debug ("Image device deactivation completed");
priv->active = FALSE;
/* Assume finger was removed. */
priv->finger_present = FALSE;
/* Deactivation completed. As we deactivate in the background
* there may already be a new task pending. Check whether we
* need to do anything. */
action = fpi_device_get_current_action (FP_DEVICE (self));
fp_image_device_change_state (self, FPI_IMAGE_DEVICE_STATE_INACTIVE);
/* Special case, if we should be closing, but didn't due to a running
* deactivation, then do so now. */
if (action == FPI_DEVICE_ACTION_CLOSE)
{
cls->img_close (self);
return;
}
fp_image_device_maybe_complete_action (self, error);
/* We might be waiting to be able to activate again. */
if (priv->pending_activation_timeout_id)
{
g_clear_handle_id (&priv->pending_activation_timeout_id, g_source_remove);
priv->pending_activation_timeout_id =
g_idle_add ((GSourceFunc) fpi_image_device_activate, self);
}
}
/**
@@ -710,8 +620,6 @@ fpi_image_device_open_complete (FpImageDevice *self, GError *error)
priv->state = FPI_IMAGE_DEVICE_STATE_INACTIVE;
g_object_notify (G_OBJECT (self), "fpi-image-device-state");
fpi_device_report_finger_status (FP_DEVICE (self), FP_FINGER_STATUS_NONE);
fpi_device_open_complete (FP_DEVICE (self), error);
}

View File

@@ -25,9 +25,6 @@
/**
* FpiImageDeviceState:
* @FPI_IMAGE_DEVICE_STATE_INACTIVE: inactive
* @FPI_IMAGE_DEVICE_STATE_ACTIVATING: State during activate callback
* @FPI_IMAGE_DEVICE_STATE_IDLE: Activated but idle
* @FPI_IMAGE_DEVICE_STATE_DEACTIVATING: State during deactivate callback
* @FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON: waiting for the finger to be pressed or swiped
* @FPI_IMAGE_DEVICE_STATE_CAPTURE: capturing an image
* @FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_OFF: waiting for the finger to be removed
@@ -38,33 +35,9 @@
* The driver needs to call fpi_image_device_report_finger_status() to move
* between the different states. Note that the capture state might be entered
* unconditionally if the device supports raw capturing.
*
* A usual run would look like:
* - inactive -> activating: activate vfunc is called
* - activating -> idle: fpi_image_device_activate_complete()
* - idle -> await-finger-on
* - await-finger-on -> capture: fpi_image_device_report_finger_status()
* - capture -> await-finger-off: fpi_image_device_image_captured()
* - await-finger-off -> idle: fpi_image_device_report_finger_status()
* - idle -> deactivating: deactivate vfunc is called
* - deactivating -> inactive: fpi_image_device_deactivate_complete()
*
* Raw mode is currently not supported (not waiting for finger), but in that
* case the following transitions are valid:
* - idle -> capture
* - capture -> idle
*
* Also valid are these transitions in case of errors or cancellations:
* - activating -> inactive: fpi_image_device_activate_complete()
* - await-finger-on -> deactivating: deactivate vfunc is called
* - capture -> deactivating: deactivate vfunc is called
* - await-finger-off -> deactivating: deactivate vfunc is called
*/
typedef enum {
FPI_IMAGE_DEVICE_STATE_INACTIVE,
FPI_IMAGE_DEVICE_STATE_ACTIVATING,
FPI_IMAGE_DEVICE_STATE_DEACTIVATING,
FPI_IMAGE_DEVICE_STATE_IDLE,
FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON,
FPI_IMAGE_DEVICE_STATE_CAPTURE,
FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_OFF,
@@ -85,6 +58,11 @@ typedef enum {
* finger or image capture). Implementing this is optional, it can e.g. be
* used to flash an LED when waiting for a finger.
*
* These are the main entry points for image based drivers. For all but the
* change_state vfunc, implementations *must* eventually call the corresponding
* function to finish the operation. It is also acceptable to call the generic
*
*
* These are the main entry points for drivers to implement. Drivers may not
* implement all of these entry points if they do not support the operation
* (or a default implementation is sufficient).

View File

@@ -74,7 +74,7 @@
* upon success (or fails).
*
* Your completion callback should examine the return value of
* fpi_ssm_get_error() in order to determine whether the #FpiSsm completed or
* fpi_ssm_get_error() in ordater to determine whether the #FpiSsm completed or
* failed. An error code of zero indicates successful completion.
*/

View File

@@ -354,24 +354,6 @@ transfer_finish_cb (GObject *source_object, GAsyncResult *res, gpointer user_dat
fpi_usb_transfer_unref (transfer);
}
static gboolean
transfer_cancel_cb (FpiUsbTransfer *transfer)
{
GError *error;
FpiUsbTransferCallback callback;
error = g_error_new_literal (G_IO_ERROR,
G_IO_ERROR_CANCELLED,
"Transfer was cancelled before being started");
callback = transfer->callback;
transfer->callback = NULL;
transfer->actual_length = -1;
callback (transfer, transfer->device, transfer->user_data, error);
fpi_usb_transfer_unref (transfer);
return G_SOURCE_REMOVE;
}
/**
* fpi_usb_transfer_submit:
@@ -405,18 +387,6 @@ fpi_usb_transfer_submit (FpiUsbTransfer *transfer,
log_transfer (transfer, TRUE, NULL);
/* Work around libgusb cancellation issue, see
* https://github.com/hughsie/libgusb/pull/42
* should be fixed with libgusb 0.3.7.
* Note that this is not race free, we rely on libfprint and API users
* not cancelling from a different thread here.
*/
if (cancellable && g_cancellable_is_cancelled (cancellable))
{
g_idle_add ((GSourceFunc) transfer_cancel_cb, transfer);
return;
}
switch (transfer->type)
{
case FP_TRANSFER_BULK:

View File

@@ -20,7 +20,6 @@
#pragma once
#include <gusb.h>
#include "fpi-compat.h"
#include "fpi-device.h"
G_BEGIN_DECLS
@@ -116,7 +115,6 @@ void fpi_usb_transfer_fill_bulk (FpiUsbTransfer *transfer,
guint8 endpoint,
gsize length);
FP_GNUC_ACCESS (read_only, 3, 4)
void fpi_usb_transfer_fill_bulk_full (FpiUsbTransfer *transfer,
guint8 endpoint,
guint8 *buffer,
@@ -136,7 +134,6 @@ void fpi_usb_transfer_fill_interrupt (FpiUsbTransfer *transfer,
guint8 endpoint,
gsize length);
FP_GNUC_ACCESS (read_only, 3, 4)
void fpi_usb_transfer_fill_interrupt_full (FpiUsbTransfer *transfer,
guint8 endpoint,
guint8 *buffer,

View File

@@ -25,78 +25,11 @@
#include "fpi-device.h"
static const FpIdEntry whitelist_id_table[] = {
/* Currently known and unsupported devices.
* You can generate this list from the wiki page using e.g.:
* gio cat https://gitlab.freedesktop.org/libfprint/wiki/-/wikis/Unsupported-Devices.md | sed -n 's!|.*\([0-9a-fA-F]\{4\}\):\([0-9a-fA-F]\{4\}\).*|.*! { .vid = 0x\1, .pid = 0x\2 },!p'
*/
{ .vid = 0x04f3, .pid = 0x036b },
{ .vid = 0x04f3, .pid = 0x0c00 },
{ .vid = 0x04f3, .pid = 0x0c4b },
{ .vid = 0x04f3, .pid = 0x0c4c },
{ .vid = 0x04f3, .pid = 0x0c4f },
{ .vid = 0x04f3, .pid = 0x0c57 },
{ .vid = 0x04f3, .pid = 0x2706 },
{ .vid = 0x06cb, .pid = 0x0081 },
{ .vid = 0x06cb, .pid = 0x0088 },
{ .vid = 0x06cb, .pid = 0x008a },
{ .vid = 0x06cb, .pid = 0x009a },
{ .vid = 0x06cb, .pid = 0x009b },
{ .vid = 0x06cb, .pid = 0x00a2 },
{ .vid = 0x06cb, .pid = 0x00b7 },
{ .vid = 0x06cb, .pid = 0x00bb },
{ .vid = 0x06cb, .pid = 0x00be },
{ .vid = 0x06cb, .pid = 0x00c2 },
{ .vid = 0x06cb, .pid = 0x00c9 },
{ .vid = 0x06cb, .pid = 0x00cb },
{ .vid = 0x06cb, .pid = 0x00d8 },
{ .vid = 0x06cb, .pid = 0x00da },
{ .vid = 0x06cb, .pid = 0x00e7 },
{ .vid = 0x0a5c, .pid = 0x5801 },
{ .vid = 0x0a5c, .pid = 0x5805 },
{ .vid = 0x0a5c, .pid = 0x5834 },
{ .vid = 0x0a5c, .pid = 0x5843 },
{ .vid = 0x10a5, .pid = 0x0007 },
{ .vid = 0x1188, .pid = 0x9545 },
{ .vid = 0x138a, .pid = 0x0007 },
{ .vid = 0x138a, .pid = 0x003a },
{ .vid = 0x138a, .pid = 0x003c },
{ .vid = 0x138a, .pid = 0x003d },
{ .vid = 0x138a, .pid = 0x003f },
{ .vid = 0x138a, .pid = 0x0090 },
/* Unsupported (for now) Validity Sensors finger print readers */
{ .vid = 0x138a, .pid = 0x0090 }, /* Found on e.g. Lenovo T460s */
{ .vid = 0x138a, .pid = 0x0091 },
{ .vid = 0x138a, .pid = 0x0092 },
{ .vid = 0x138a, .pid = 0x0094 },
{ .vid = 0x138a, .pid = 0x0097 },
{ .vid = 0x138a, .pid = 0x009d },
{ .vid = 0x138a, .pid = 0x00ab },
{ .vid = 0x147e, .pid = 0x1002 },
{ .vid = 0x1491, .pid = 0x0088 },
{ .vid = 0x16d1, .pid = 0x1027 },
{ .vid = 0x1c7a, .pid = 0x0300 },
{ .vid = 0x1c7a, .pid = 0x0570 },
{ .vid = 0x1c7a, .pid = 0x0575 },
{ .vid = 0x27c6, .pid = 0x5042 },
{ .vid = 0x27c6, .pid = 0x5110 },
{ .vid = 0x27c6, .pid = 0x5117 },
{ .vid = 0x27c6, .pid = 0x5201 },
{ .vid = 0x27c6, .pid = 0x521d },
{ .vid = 0x27c6, .pid = 0x5301 },
{ .vid = 0x27c6, .pid = 0x530c },
{ .vid = 0x27c6, .pid = 0x532d },
{ .vid = 0x27c6, .pid = 0x533c },
{ .vid = 0x27c6, .pid = 0x5381 },
{ .vid = 0x27c6, .pid = 0x5385 },
{ .vid = 0x27c6, .pid = 0x538c },
{ .vid = 0x27c6, .pid = 0x538d },
{ .vid = 0x27c6, .pid = 0x5395 },
{ .vid = 0x27c6, .pid = 0x5584 },
{ .vid = 0x27c6, .pid = 0x55a2 },
{ .vid = 0x27c6, .pid = 0x55a4 },
{ .vid = 0x27c6, .pid = 0x55b4 },
{ .vid = 0x27c6, .pid = 0x5740 },
{ .vid = 0x2808, .pid = 0x9338 },
{ .vid = 0x298d, .pid = 0x2033 },
{ .vid = 0x3538, .pid = 0x0930 },
{ .vid = 0x138a, .pid = 0x0097 }, /* Found on e.g. Lenovo T470s */
{ .vid = 0 },
};

View File

@@ -234,8 +234,6 @@ libnbis = static_library('nbis',
'-Wno-error=redundant-decls',
'-Wno-redundant-decls',
'-Wno-discarded-qualifiers',
'-Wno-array-bounds',
'-Wno-array-parameter',
]),
install: false)

View File

@@ -1,5 +1,5 @@
project('libfprint', [ 'c', 'cpp' ],
version: '1.90.7',
version: '1.90.3',
license: 'LGPLv2.1+',
default_options: [
'buildtype=debugoptimized',

53
tests/README-umockdev Normal file
View File

@@ -0,0 +1,53 @@
To create a new umockdev test, you should:
1. Decide on what to test, the easiest case is just using the existing
capture test case.
2. Find the USB device you are testing with lsusb, e.g.:
Bus 001 Device 005: ID 138a:0090 Validity Sensors, Inc. VFS7500 Touch Fingerprint Sensor
This means we need to record USB device /dev/bus/usb/001/005
3. Run "umockdev-record /dev/bus/usb/001/005 >device"
This records the information about device, it should be placed into test/DRIVER/device
4. Run the test, for a capture test this would be:
umockdev-record -i /dev/bus/usb/001/005=capture.ioctl -- ./capture.py capture.png
This will create a capture.ioctl and capture.png file.
Please set the FP_DEVICE_EMULATION=1 environment variable. You may need
to adjust the driver to adapt to the emulated environment (mainly if it
uses random numbers, see synaptics.c for an example).
5. Place all files into the driver subdirectory test/DRIVER,
i.e. device, capture.ioctl, capture.png
6. Add glue to meson.build
7. Test whether everything works as expected
Please note, there is no need to use a real finger print in this case. If
you would like to avoid submitting your own fingerprint then please just
use e.g. the side of your finger, arm, or anything else that will produce
an image with the device.
Note that umockdev-record groups URBs aggressively. In most cases, manual
intervention is unfortunately required. In most cases, drivers do a chain
of commands like e.g. A then B each with a different reply. Umockdev will
create a file like:
A
reply 1
reply 2
B
reply 1
reply 2
which then needs to be re-ordered to be:
A
reply 1
B
reply 1
A
reply 2
B
reply 2
Other changes may be needed to get everything working. For example the elan
driver relies on a timeout that is not reported correctly. In this case the
driver works around it by interpreting the protocol error differently in
the virtual environment.

View File

@@ -27,7 +27,7 @@ A new 'capture' test is created by means of `capture.py` script:
- `export LD_PRELOAD=<meson-build-dir>/libfprint/libfprint-2.so`
- `export GI_TYPELIB_PATH=<meson-build-dir>/libfprint`
Also, sometimes the driver must be adapted to the emulated environment
Also, sometimes the driver must be adopted to the emulated environment
(mainly if it uses random numbers, see `synaptics.c` for an example).
Set the following environment variable to enable this adaptation:
- `export FP_DEVICE_EMULATION=1`
@@ -41,11 +41,6 @@ A new 'capture' test is created by means of `capture.py` script:
The following USB device is used in the example above:
`/dev/bus/usb/001/005`.
For the following commands, it is assumed that the user that's
running the commands has full access to the device node, whether
by running the commands as `root`, or changing the permissions for
that device node.
4. Record information about this device:
`umockdev-record /dev/bus/usb/001/005 > DRIVER/device`

View File

@@ -20,21 +20,11 @@ d.open_sync()
template = FPrint.Print.new(d)
def enroll_progress(*args):
assert d.get_finger_status() == FPrint.FingerStatusFlags.NEEDED
print('enroll progress: ' + str(args))
def identify_done(dev, res):
global identified
identified = True
identify_match, identify_print = dev.identify_finish(res)
print('indentification_done: ', identify_match, identify_print)
assert identify_match.equal(identify_print)
# List, enroll, list, verify, identify, delete
print("enrolling")
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
p = d.enroll_sync(template, None, enroll_progress, None)
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
print("enroll done")
print("listing")
@@ -43,31 +33,17 @@ print("listing done")
assert len(stored) == 1
assert stored[0].equal(p)
print("verifying")
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
verify_res, verify_print = d.verify_sync(p)
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
print("verify done")
del p
assert verify_res == True
identified = False
deserialized_prints = []
for p in stored:
deserialized_prints.append(FPrint.Print.deserialize(p.serialize()))
assert deserialized_prints[-1].equal(p)
del stored
print('async identifying')
d.identify(deserialized_prints, callback=identify_done)
del deserialized_prints
while not identified:
ctx.iteration(True)
print("identifying")
identify_match, identify_print = d.identify_sync(stored)
print("identify done")
assert identify_match.equal(identify_print)
print("deleting")
d.delete_print_sync(p)
print("delete done")
d.close_sync()
del d

View File

@@ -21,7 +21,6 @@ drivers_tests = [
'elan',
'synaptics',
'vfs0050',
'vfs301',
'vfs5011',
'goodixmoc',
]

View File

@@ -4,16 +4,14 @@ USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 01
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 40 38 0 00009C37FE5C669C2D000A01014101C10000D11BB7134A090FA1000000000100000000000003
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 5 5 0 A7FE011100
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE01130100
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 5 5 0 A7FE021100
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE02130100
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 37 37 0 A7FE03512000014650312D30303030303030302D302D30303030303030302D6E6F626F6479
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE035400
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 37 37 0 A7FE02512000014650312D30303030303030302D302D30303030303030302D6E6F626F6479
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE025400
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE036000
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE026000
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101
@@ -22,13 +20,13 @@ USBDEVFS_REAPURBNDELAY 0 3 1 0 0 37 37 0 A7FE03512000014650312D30303030303030302
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910100
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 05000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE0355010C
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE0255010C
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE036000
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE026000
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101
@@ -37,19 +35,19 @@ USBDEVFS_REAPURBNDELAY 0 3 1 0 0 37 37 0 A7FE03512000014650312D30303030303030302
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910100
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 05000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE03550119
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE02550119
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE036000
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE026000
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE03550125
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE02550125
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 05000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910100
@@ -58,13 +56,13 @@ USBDEVFS_REAPURBNDELAY 0 3 1 0 0 37 37 0 A7FE03512000014650312D30303030303030302
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE036000
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE026000
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE03550125
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE02550125
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 05000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910100
@@ -73,13 +71,13 @@ USBDEVFS_REAPURBNDELAY 0 3 1 0 0 37 37 0 A7FE03512000014650312D30303030303030302
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE036000
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE026000
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE03550132
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE02550132
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 05000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910100
@@ -88,13 +86,13 @@ USBDEVFS_REAPURBNDELAY 0 3 1 0 0 37 37 0 A7FE03512000014650312D30303030303030302
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE036000
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE026000
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE0355013E
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE0255013E
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 05000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910100
@@ -103,13 +101,13 @@ USBDEVFS_REAPURBNDELAY 0 3 1 0 0 37 37 0 A7FE03512000014650312D30303030303030302
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE036000
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE026000
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE0355013E
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE0255013E
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 05000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910100
@@ -118,13 +116,13 @@ USBDEVFS_REAPURBNDELAY 0 3 1 0 0 37 37 0 A7FE03512000014650312D30303030303030302
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE036000
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE026000
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE0355014B
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE0255014B
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 05000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910100
@@ -133,7 +131,7 @@ USBDEVFS_REAPURBNDELAY 0 3 1 0 0 37 37 0 A7FE03512000014650312D30303030303030302
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE036000
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE026000
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101
@@ -142,13 +140,13 @@ USBDEVFS_REAPURBNDELAY 0 3 1 0 0 37 37 0 A7FE03512000014650312D30303030303030302
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910100
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 05000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE03550157
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE02550157
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000000
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE036000
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE026000
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101
@@ -157,21 +155,21 @@ USBDEVFS_REAPURBNDELAY 0 3 1 0 0 37 37 0 A7FE03512000014650312D30303030303030302
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910100
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 05000000000100
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE03550164
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE02550164
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 05000000000100
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 37 0 0000FE03591F014650312D30303030303030302D302D30303030303030302D6E6F626F6479
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 37 0 0000FE02591F014650312D30303030303030302D302D30303030303030302D6E6F626F6479
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 5 5 0 A7FE047100
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 41 0 0000FE04752301012007014650312D30303030303030302D302D30303030303030302D6E6F626F6479
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 5 5 0 A7FE047200
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE047600
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 35 35 0 A7FE05651E4650312D30303030303030302D302D30303030303030302D6E6F626F6479
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE056600
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 5 5 0 A7FE037100
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 41 0 0000FE03752301012007014650312D30303030303030302D302D30303030303030302D6E6F626F6479
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 5 5 0 A7FE037200
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE037600
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 35 35 0 A7FE04651E4650312D30303030303030302D302D30303030303030302D6E6F626F6479
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE046600
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000000
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE056000
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE046000
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 06000000000100
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910101
@@ -180,9 +178,9 @@ USBDEVFS_REAPURBNDELAY 0 3 1 0 0 35 35 0 A7FE05651E4650312D30303030303030302D302
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 7 0 0000FE00910100
USBDEVFS_REAPURBNDELAY 0 1 131 0 0 7 7 0 05000000000100
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 1 1 0 A8
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 39 0 0000FE0568214F2B014650312D30303030303030302D302D30303030303030302D6E6F626F6479
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 36 36 0 A7FE06811F014650312D30303030303030302D302D30303030303030302D6E6F626F6479
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 37 0 0000FE06831F014650312D30303030303030302D302D30303030303030302D6E6F626F6479
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 5 5 0 A7FE07A100
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE07A200
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 39 0 0000FE0468214F2B014650312D30303030303030302D302D30303030303030302D6E6F626F6479
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 36 36 0 A7FE05811F014650312D30303030303030302D302D30303030303030302D6E6F626F6479
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 37 0 0000FE05831F014650312D30303030303030302D302D30303030303030302D6E6F626F6479
USBDEVFS_REAPURBNDELAY 0 3 1 0 0 5 5 0 A7FE06A100
USBDEVFS_REAPURBNDELAY 0 3 129 0 0 266 6 0 0000FE06A200

View File

@@ -20,14 +20,11 @@ d.open_sync()
template = FPrint.Print.new(d)
def enroll_progress(*args):
assert d.get_finger_status() == FPrint.FingerStatusFlags.NEEDED
print('enroll progress: ' + str(args))
# List, enroll, list, verify, delete, list
print("enrolling")
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
p = d.enroll_sync(template, None, enroll_progress, None)
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
print("enroll done")
print("listing")
@@ -36,9 +33,7 @@ print("listing done")
assert len(stored) == 1
assert stored[0].equal(p)
print("verifying")
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
verify_res, verify_print = d.verify_sync(p)
assert d.get_finger_status() == FPrint.FingerStatusFlags.NONE
print("verify done")
assert verify_res == True

View File

@@ -20,7 +20,6 @@
#include <libfprint/fprint.h>
#include "test-utils.h"
#include "fpi-device.h"
static void
test_context_new (void)
@@ -93,296 +92,6 @@ test_context_enumerates_new_devices (void)
fpt_teardown_virtual_device_environment ();
}
#define DEV_REMOVED_CB 1
#define CTX_DEVICE_REMOVED_CB 2
static void
device_removed_cb (FpDevice *device, FptContext *tctx)
{
g_assert_nonnull (device);
g_assert_true (device == tctx->device);
g_assert_null (tctx->user_data);
tctx->user_data = GINT_TO_POINTER (DEV_REMOVED_CB);
}
static void
context_device_removed_cb (FpContext *ctx, FpDevice *device, FptContext *tctx)
{
g_assert_nonnull (device);
g_assert_true (device == tctx->device);
/* "device-removed" on context is always after "removed" on device */
g_assert_cmpint (GPOINTER_TO_INT (tctx->user_data), ==, DEV_REMOVED_CB);
tctx->user_data = GINT_TO_POINTER (CTX_DEVICE_REMOVED_CB);
}
static void
test_context_remove_device_closed (void)
{
g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_imgdev ();
gboolean removed;
tctx->user_data = NULL;
g_signal_connect (tctx->device, "removed", (GCallback) device_removed_cb, tctx);
g_signal_connect (tctx->fp_context, "device-removed", (GCallback) context_device_removed_cb, tctx);
/* Triggering remove on closed device. */
fpi_device_remove (tctx->device);
g_assert_nonnull (tctx->device);
g_object_get (tctx->device, "removed", &removed, NULL);
g_assert_true (removed);
g_assert_cmpint (GPOINTER_TO_INT (tctx->user_data), ==, DEV_REMOVED_CB);
/* device-removed is dispatched from idle. */
while (g_main_context_iteration (NULL, FALSE))
{
}
/* The device is now destroyed and device-removed was called. */
g_assert_null (tctx->device);
g_assert_cmpint (GPOINTER_TO_INT (tctx->user_data), ==, CTX_DEVICE_REMOVED_CB);
fpt_teardown_virtual_device_environment ();
}
static void
close_done_cb (GObject *device, GAsyncResult *res, gpointer user_data)
{
g_autoptr(FpPrint) print = NULL;
GError **error = user_data;
g_assert_nonnull (error);
g_assert_false (fp_device_close_finish (FP_DEVICE (device), res, error));
g_assert_null (print);
g_assert_nonnull (*error);
}
static void
test_context_remove_device_closing (void)
{
g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_imgdev ();
g_autoptr(GError) close_error = NULL;
g_autoptr(GError) error = NULL;
gboolean removed;
tctx->user_data = NULL;
g_signal_connect (tctx->device, "removed", (GCallback) device_removed_cb, tctx);
g_signal_connect (tctx->fp_context, "device-removed", (GCallback) context_device_removed_cb, tctx);
fp_device_open_sync (tctx->device, NULL, &error);
g_assert_no_error (error);
/* Triggering remove on device that is being closed. */
fp_device_close (tctx->device, NULL, close_done_cb, &close_error);
fpi_device_remove (tctx->device);
/* Removed but not yet notified*/
g_assert_nonnull (tctx->device);
g_object_get (tctx->device, "removed", &removed, NULL);
g_assert_true (removed);
g_assert_null (tctx->user_data);
/* Running the mainloop now will cause the close to fail eventually. */
while (!close_error)
g_main_context_iteration (NULL, TRUE);
g_assert_error (close_error, FP_DEVICE_ERROR, FP_DEVICE_ERROR_REMOVED);
/* Now the removed callback has been called already. */
g_assert_nonnull (tctx->device);
g_assert_cmpint (GPOINTER_TO_INT (tctx->user_data), ==, DEV_REMOVED_CB);
/* While device-removed needs another idle iteration. */
while (g_main_context_iteration (NULL, FALSE))
{
}
g_assert_null (tctx->device);
g_assert_cmpint (GPOINTER_TO_INT (tctx->user_data), ==, CTX_DEVICE_REMOVED_CB);
fpt_teardown_virtual_device_environment ();
}
static void
test_context_remove_device_open (void)
{
g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_imgdev ();
g_autoptr(GError) error = NULL;
gboolean removed = FALSE;
tctx->user_data = NULL;
g_signal_connect (tctx->fp_context, "device-removed", (GCallback) context_device_removed_cb, tctx);
g_signal_connect (tctx->device, "removed", (GCallback) device_removed_cb, tctx);
fp_device_open_sync (tctx->device, NULL, &error);
g_assert_no_error (error);
/* Triggering remove on open device. */
fpi_device_remove (tctx->device);
g_assert_nonnull (tctx->device);
g_object_get (tctx->device, "removed", &removed, NULL);
g_assert_true (removed);
g_assert_cmpint (GPOINTER_TO_INT (tctx->user_data), ==, DEV_REMOVED_CB);
/* At this point, the "removed" cb on the device should have been called!
* Iterating the mainloop will not change anything.
*/
while (g_main_context_iteration (NULL, FALSE))
{
}
g_assert_cmpint (GPOINTER_TO_INT (tctx->user_data), ==, DEV_REMOVED_CB);
/* On close, the device will be removed from the context,
* but only a main loop iteration later. */
fp_device_close_sync (tctx->device, NULL, &error);
g_assert_error (error, FP_DEVICE_ERROR, FP_DEVICE_ERROR_REMOVED);
g_assert_nonnull (tctx->device);
g_assert_cmpint (GPOINTER_TO_INT (tctx->user_data), ==, DEV_REMOVED_CB);
while (g_main_context_iteration (NULL, FALSE))
{
}
g_assert_null (tctx->device);
g_assert_cmpint (GPOINTER_TO_INT (tctx->user_data), ==, CTX_DEVICE_REMOVED_CB);
fpt_teardown_virtual_device_environment ();
}
static void
open_done_cb (GObject *device, GAsyncResult *res, gpointer user_data)
{
g_autoptr(GError) error = NULL;
g_autoptr(FpPrint) print = NULL;
gboolean *data = user_data;
g_assert_true (fp_device_open_finish (FP_DEVICE (device), res, &error));
g_assert_null (print);
g_assert_null (error);
*data = TRUE;
}
static void
test_context_remove_device_opening (void)
{
g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_imgdev ();
g_autoptr(GError) close_error = NULL;
gboolean open_done = FALSE;
gboolean removed;
tctx->user_data = NULL;
g_signal_connect (tctx->device, "removed", (GCallback) device_removed_cb, tctx);
g_signal_connect (tctx->fp_context, "device-removed", (GCallback) context_device_removed_cb, tctx);
fp_device_open (tctx->device, NULL, open_done_cb, &open_done);
g_assert_false (open_done);
fpi_device_remove (tctx->device);
/* Removed but not yet notified*/
g_assert_nonnull (tctx->device);
g_object_get (tctx->device, "removed", &removed, NULL);
g_assert_true (removed);
g_assert_null (tctx->user_data);
/* Running the mainloop now will cause the open to *succeed* despite removal! */
while (!open_done)
g_main_context_iteration (NULL, TRUE);
/* Now the removed callback has been called already. */
g_assert_nonnull (tctx->device);
g_assert_cmpint (GPOINTER_TO_INT (tctx->user_data), ==, DEV_REMOVED_CB);
fp_device_close_sync (tctx->device, NULL, &close_error);
g_assert_error (close_error, FP_DEVICE_ERROR, FP_DEVICE_ERROR_REMOVED);
g_assert_nonnull (tctx->device);
g_assert_cmpint (GPOINTER_TO_INT (tctx->user_data), ==, DEV_REMOVED_CB);
/* The device-removed signal needs an idle iteration. */
while (g_main_context_iteration (NULL, FALSE))
{
}
g_assert_null (tctx->device);
g_assert_cmpint (GPOINTER_TO_INT (tctx->user_data), ==, CTX_DEVICE_REMOVED_CB);
fpt_teardown_virtual_device_environment ();
}
static void
enroll_done_cb (GObject *device, GAsyncResult *res, gpointer user_data)
{
g_autoptr(FpPrint) print = NULL;
GError **error = user_data;
g_assert_nonnull (error);
print = fp_device_enroll_finish (FP_DEVICE (device), res, error);
g_assert_null (print);
g_assert_nonnull (*error);
}
static void
test_context_remove_device_active (void)
{
g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_imgdev ();
g_autoptr(GError) error = NULL;
g_autoptr(GCancellable) cancellable = NULL;
g_autoptr(GError) enroll_error = NULL;
FpPrint *template;
gboolean removed = FALSE;
tctx->user_data = NULL;
g_signal_connect (tctx->fp_context, "device-removed", (GCallback) context_device_removed_cb, tctx);
g_signal_connect (tctx->device, "removed", (GCallback) device_removed_cb, tctx);
fp_device_open_sync (tctx->device, NULL, &error);
g_assert_no_error (error);
/* Start an enroll that we can cancel/fail later.
* NOTE: We need to cancel explicitly as remove() does not trigger a failure!
*/
template = fp_print_new (tctx->device);
cancellable = g_cancellable_new ();
fp_device_enroll (tctx->device, template, cancellable, NULL, NULL, NULL, enroll_done_cb, &enroll_error);
/* Triggering remove on active device. */
fpi_device_remove (tctx->device);
/* The removed property has changed, but the cb has *not* been called yet. */
g_assert_nonnull (tctx->device);
g_object_get (tctx->device, "removed", &removed, NULL);
g_assert_true (removed);
g_assert_null (tctx->user_data);
/* Running the mainloop now will cause the operation to fail eventually. */
while (!enroll_error)
g_main_context_iteration (NULL, TRUE);
/* The virtual image device throws an PROTO error internally,
* but we should still receive a REMOVED error here. */
g_assert_error (enroll_error, FP_DEVICE_ERROR, FP_DEVICE_ERROR_REMOVED);
g_assert_cmpint (GPOINTER_TO_INT (tctx->user_data), ==, DEV_REMOVED_CB);
/* Now we close the device, state remains unchanged mostly. */
fp_device_close_sync (tctx->device, NULL, &error);
g_assert_error (error, FP_DEVICE_ERROR, FP_DEVICE_ERROR_REMOVED);
g_assert_nonnull (tctx->device);
g_assert_cmpint (GPOINTER_TO_INT (tctx->user_data), ==, DEV_REMOVED_CB);
/* And "device-removed" is called */
while (g_main_context_iteration (NULL, FALSE))
{
}
g_assert_null (tctx->device);
g_assert_cmpint (GPOINTER_TO_INT (tctx->user_data), ==, CTX_DEVICE_REMOVED_CB);
fpt_teardown_virtual_device_environment ();
}
int
main (int argc, char *argv[])
{
@@ -392,11 +101,6 @@ main (int argc, char *argv[])
g_test_add_func ("/context/no-devices", test_context_has_no_devices);
g_test_add_func ("/context/has-virtual-device", test_context_has_virtual_device);
g_test_add_func ("/context/enumerates-new-devices", test_context_enumerates_new_devices);
g_test_add_func ("/context/remove-device-closed", test_context_remove_device_closed);
g_test_add_func ("/context/remove-device-closing", test_context_remove_device_closing);
g_test_add_func ("/context/remove-device-open", test_context_remove_device_open);
g_test_add_func ("/context/remove-device-opening", test_context_remove_device_opening);
g_test_add_func ("/context/remove-device-active", test_context_remove_device_active);
return g_test_run ();
}

View File

@@ -178,15 +178,6 @@ test_device_get_scan_type (void)
g_assert_cmpint (fp_device_get_scan_type (tctx->device), ==, FP_SCAN_TYPE_SWIPE);
}
static void
test_device_get_finger_status (void)
{
g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_imgdev ();
fp_device_open_sync (tctx->device, NULL, NULL);
g_assert_cmpint (fp_device_get_finger_status (tctx->device), ==, FP_FINGER_STATUS_NONE);
}
static void
test_device_get_nr_enroll_stages (void)
{
@@ -238,7 +229,6 @@ main (int argc, char *argv[])
g_test_add_func ("/device/sync/get_device_id", test_device_get_device_id);
g_test_add_func ("/device/sync/get_name", test_device_get_name);
g_test_add_func ("/device/sync/get_scan_type", test_device_get_scan_type);
g_test_add_func ("/device/sync/get_finger_status", test_device_get_finger_status);
g_test_add_func ("/device/sync/get_nr_enroll_stages", test_device_get_nr_enroll_stages);
g_test_add_func ("/device/sync/supports_identify", test_device_supports_identify);
g_test_add_func ("/device/sync/supports_capture", test_device_supports_capture);

View File

@@ -89,29 +89,6 @@ auto_reset_device_class_cleanup (FpAutoResetClass *dev_class)
}
G_DEFINE_AUTOPTR_CLEANUP_FUNC (FpAutoResetClass, auto_reset_device_class_cleanup)
static void
assert_equal_galleries (GPtrArray *g1,
GPtrArray *g2)
{
unsigned i;
g_assert ((g1 && g2) || (!g1 || !g1));
if (g1 == g2)
return;
g_assert_cmpuint (g1->len, ==, g2->len);
for (i = 0; i < g1->len; i++)
{
FpPrint *print = g_ptr_array_index (g1, i);
g_assert_true (g_ptr_array_find_with_equal_func (g2, print, (GEqualFunc)
fp_print_equal, NULL));
}
}
static void
on_device_notify (FpDevice *device, GParamSpec *spec, gpointer user_data)
{
@@ -121,43 +98,6 @@ on_device_notify (FpDevice *device, GParamSpec *spec, gpointer user_data)
fake_dev->user_data = g_param_spec_ref (spec);
}
static FpPrint *
make_fake_print (FpDevice *device,
GVariant *print_data)
{
FpPrint *enrolled_print = fp_print_new (device);
fpi_print_set_type (enrolled_print, FPI_PRINT_RAW);
if (!print_data)
print_data = g_variant_new_string ("Test print private data");
g_object_set (G_OBJECT (enrolled_print), "fpi-data", print_data, NULL);
return enrolled_print;
}
static FpPrint *
make_fake_print_reffed (FpDevice *device,
GVariant *print_data)
{
return g_object_ref_sink (make_fake_print (device, print_data));
}
static GPtrArray *
make_fake_prints_gallery (FpDevice *device,
size_t size)
{
GPtrArray *array;
size_t i;
array = g_ptr_array_new_full (size, g_object_unref);
for (i = 0; i < size; i++)
g_ptr_array_add (array, make_fake_print_reffed (device, g_variant_new_uint64 (i)));
return array;
}
/* Tests */
static void
@@ -260,160 +200,6 @@ test_driver_set_scan_type_swipe (void)
g_assert_cmpstr (pspec->name, ==, "scan-type");
}
static void
test_driver_finger_status_inactive (void)
{
g_autoptr(FpDevice) device = g_object_new (FPI_TYPE_DEVICE_FAKE, NULL);
FpiDeviceFake *fake_dev = FPI_DEVICE_FAKE (device);
FpFingerStatusFlags finger_status;
g_signal_connect (device, "notify::finger-status", G_CALLBACK (on_device_notify), NULL);
g_assert_false (fpi_device_report_finger_status (device, FP_FINGER_STATUS_NONE));
g_assert_cmpuint (fp_device_get_finger_status (device), ==, FP_FINGER_STATUS_NONE);
g_object_get (fake_dev, "finger-status", &finger_status, NULL);
g_assert_cmpuint (finger_status, ==, FP_FINGER_STATUS_NONE);
g_assert (fake_dev->last_called_function != on_device_notify);
g_assert_null (g_steal_pointer (&fake_dev->user_data));
}
static void
test_driver_finger_status_needed (void)
{
g_autoptr(FpDevice) device = g_object_new (FPI_TYPE_DEVICE_FAKE, NULL);
g_autoptr(GParamSpec) pspec = NULL;
FpiDeviceFake *fake_dev = FPI_DEVICE_FAKE (device);
FpFingerStatusFlags finger_status;
g_signal_connect (device, "notify::finger-status", G_CALLBACK (on_device_notify), NULL);
g_assert_true (fpi_device_report_finger_status (device, FP_FINGER_STATUS_NEEDED));
g_assert_cmpuint (fp_device_get_finger_status (device), ==, FP_FINGER_STATUS_NEEDED);
g_object_get (fake_dev, "finger-status", &finger_status, NULL);
g_assert_cmpuint (finger_status, ==, FP_FINGER_STATUS_NEEDED);
g_assert (fake_dev->last_called_function == on_device_notify);
pspec = g_steal_pointer (&fake_dev->user_data);
g_assert_cmpstr (pspec->name, ==, "finger-status");
fake_dev->last_called_function = NULL;
g_assert_false (fpi_device_report_finger_status (device, FP_FINGER_STATUS_NEEDED));
g_assert_null (fake_dev->last_called_function);
g_assert_null (g_steal_pointer (&fake_dev->user_data));
}
static void
test_driver_finger_status_present (void)
{
g_autoptr(FpDevice) device = g_object_new (FPI_TYPE_DEVICE_FAKE, NULL);
g_autoptr(GParamSpec) pspec = NULL;
FpiDeviceFake *fake_dev = FPI_DEVICE_FAKE (device);
FpFingerStatusFlags finger_status;
g_signal_connect (device, "notify::finger-status", G_CALLBACK (on_device_notify), NULL);
g_assert_true (fpi_device_report_finger_status (device, FP_FINGER_STATUS_PRESENT));
g_assert_cmpuint (fp_device_get_finger_status (device), ==, FP_FINGER_STATUS_PRESENT);
g_object_get (fake_dev, "finger-status", &finger_status, NULL);
g_assert_cmpuint (finger_status, ==, FP_FINGER_STATUS_PRESENT);
g_assert (fake_dev->last_called_function == on_device_notify);
pspec = g_steal_pointer (&fake_dev->user_data);
g_assert_cmpstr (pspec->name, ==, "finger-status");
fake_dev->last_called_function = NULL;
g_assert_false (fpi_device_report_finger_status (device, FP_FINGER_STATUS_PRESENT));
g_assert_null (fake_dev->last_called_function);
g_assert_null (g_steal_pointer (&fake_dev->user_data));
}
static void
driver_finger_status_changes_check (FpDevice *device, gboolean add)
{
FpiDeviceFake *fake_dev = FPI_DEVICE_FAKE (device);
g_autoptr(GFlagsClass) status_class = g_type_class_ref (FP_TYPE_FINGER_STATUS_FLAGS);
guint expected_status;
guint initial_value;
guint i;
gulong signal_id;
if (add)
initial_value = FP_FINGER_STATUS_NONE;
else
initial_value = status_class->mask;
g_assert_cmpuint (fp_device_get_finger_status (device), ==, initial_value);
signal_id = g_signal_connect (device, "notify::finger-status",
G_CALLBACK (on_device_notify), NULL);
for (i = 0, expected_status = initial_value; i < status_class->n_values; ++i)
{
g_autoptr(GParamSpec) pspec = NULL;
FpFingerStatusFlags finger_status = status_class->values[i].value;
FpFingerStatusFlags added_status = add ? finger_status : FP_FINGER_STATUS_NONE;
FpFingerStatusFlags removed_status = add ? FP_FINGER_STATUS_NONE : finger_status;
gboolean ret;
fake_dev->last_called_function = NULL;
ret = fpi_device_report_finger_status_changes (device,
added_status,
removed_status);
if (finger_status != FP_FINGER_STATUS_NONE)
g_assert_true (ret);
else
g_assert_false (ret);
expected_status |= added_status;
expected_status &= ~removed_status;
g_assert_cmpuint (fp_device_get_finger_status (device), ==, expected_status);
if (finger_status != FP_FINGER_STATUS_NONE)
{
g_assert (fake_dev->last_called_function == on_device_notify);
pspec = g_steal_pointer (&fake_dev->user_data);
g_assert_cmpstr (pspec->name, ==, "finger-status");
}
fake_dev->last_called_function = NULL;
g_assert_false (fpi_device_report_finger_status_changes (device,
added_status,
removed_status));
g_assert_null (fake_dev->last_called_function);
g_assert_null (g_steal_pointer (&fake_dev->user_data));
}
if (add)
g_assert_cmpuint (fp_device_get_finger_status (device), ==, status_class->mask);
else
g_assert_cmpuint (fp_device_get_finger_status (device), ==, FP_FINGER_STATUS_NONE);
fake_dev->last_called_function = NULL;
g_assert_false (fpi_device_report_finger_status_changes (device,
FP_FINGER_STATUS_NONE,
FP_FINGER_STATUS_NONE));
g_assert_null (fake_dev->last_called_function);
g_assert_null (g_steal_pointer (&fake_dev->user_data));
g_signal_handler_disconnect (device, signal_id);
}
static void
test_driver_finger_status_changes (void)
{
g_autoptr(FpDevice) device = g_object_new (FPI_TYPE_DEVICE_FAKE, NULL);
driver_finger_status_changes_check (device, TRUE);
driver_finger_status_changes_check (device, FALSE);
}
static void
test_driver_get_nr_enroll_stages (void)
{
@@ -607,12 +393,12 @@ test_driver_open (void)
g_assert (fake_dev->last_called_function != dev_class->probe);
g_assert_true (fp_device_open_sync (device, NULL, &error));
fp_device_open_sync (device, NULL, &error);
g_assert (fake_dev->last_called_function == dev_class->open);
g_assert_no_error (error);
g_assert_true (fp_device_is_open (device));
g_assert_true (fp_device_close_sync (FP_DEVICE (device), NULL, &error));
fp_device_close_sync (FP_DEVICE (device), NULL, &error);
g_assert_no_error (error);
}
@@ -625,7 +411,7 @@ test_driver_open_error (void)
FpiDeviceFake *fake_dev = FPI_DEVICE_FAKE (device);
fake_dev->ret_error = fpi_device_error_new (FP_DEVICE_ERROR_GENERAL);
g_assert_false (fp_device_open_sync (device, NULL, &error));
fp_device_open_sync (device, NULL, &error);
g_assert (fake_dev->last_called_function == dev_class->open);
g_assert_error (error, FP_DEVICE_ERROR, FP_DEVICE_ERROR_GENERAL);
g_assert_false (fp_device_is_open (device));
@@ -640,7 +426,7 @@ test_driver_close (void)
FpDeviceClass *dev_class = FP_DEVICE_GET_CLASS (device);
FpiDeviceFake *fake_dev = FPI_DEVICE_FAKE (device);
g_assert_true (fp_device_close_sync (device, NULL, &error));
fp_device_close_sync (device, NULL, &error);
g_assert (fake_dev->last_called_function == dev_class->close);
g_assert_no_error (error);
@@ -656,12 +442,12 @@ test_driver_close_error (void)
FpiDeviceFake *fake_dev = FPI_DEVICE_FAKE (device);
fake_dev->ret_error = fpi_device_error_new (FP_DEVICE_ERROR_GENERAL);
g_assert_false (fp_device_close_sync (device, NULL, &error));
fp_device_close_sync (device, NULL, &error);
g_assert (fake_dev->last_called_function == dev_class->close);
g_assert_error (error, FP_DEVICE_ERROR, FP_DEVICE_ERROR_GENERAL);
g_assert (error == g_steal_pointer (&fake_dev->ret_error));
g_assert_false (fp_device_is_open (device));
g_assert_true (fp_device_is_open (device));
}
static void
@@ -743,7 +529,7 @@ test_driver_enroll_error_no_print (void)
"*Driver passed an error but also provided a print, returning error*");
fake_dev->ret_error = fpi_device_error_new (FP_DEVICE_ERROR_GENERAL);
fake_dev->ret_print = make_fake_print_reffed (device, NULL);
fake_dev->ret_print = fp_print_new (device);
g_object_add_weak_pointer (G_OBJECT (fake_dev->ret_print),
(gpointer) (&fake_dev->ret_print));
out_print =
@@ -834,8 +620,7 @@ test_driver_enroll_progress_vfunc (FpDevice *device)
expected_data->completed_stages =
g_random_int_range (fp_device_get_nr_enroll_stages (device), G_MAXINT32);
expected_data->print = make_fake_print_reffed (device,
g_variant_new_int32 (expected_data->completed_stages));
expected_data->print = fp_print_new (device);
expected_data->error = NULL;
error = fpi_device_error_new (FP_DEVICE_ERROR_GENERAL);
@@ -893,11 +678,10 @@ test_driver_enroll_progress (void)
typedef struct
{
gboolean called;
FpPrint *match;
FpPrint *print;
GPtrArray *gallery;
GError *error;
gboolean called;
FpPrint *match;
FpPrint *print;
GError *error;
} MatchCbData;
static void
@@ -940,14 +724,6 @@ test_driver_match_cb (FpDevice *device,
if (match)
g_assert_no_error (error);
/* Compar gallery if this is an identify operation */
if (data->gallery)
{
FpiDeviceFake *fake_dev = FPI_DEVICE_FAKE (device);
g_assert_false (fake_dev->action_data == data->gallery);
assert_equal_galleries (fake_dev->action_data, data->gallery);
}
}
static void
@@ -955,7 +731,7 @@ test_driver_verify (void)
{
g_autoptr(GError) error = NULL;
g_autoptr(FpAutoCloseDevice) device = auto_close_fake_device_new ();
g_autoptr(FpPrint) enrolled_print = make_fake_print_reffed (device, NULL);
g_autoptr(FpPrint) enrolled_print = g_object_ref_sink (fp_print_new (device));
g_autoptr(FpPrint) out_print = NULL;
g_autoptr(MatchCbData) match_data = g_new0 (MatchCbData, 1);
FpDeviceClass *dev_class = FP_DEVICE_GET_CLASS (device);
@@ -963,9 +739,9 @@ test_driver_verify (void)
gboolean match;
fake_dev->ret_result = FPI_MATCH_SUCCESS;
g_assert_true (fp_device_verify_sync (device, enrolled_print, NULL,
test_driver_match_cb, match_data,
&match, &out_print, &error));
fp_device_verify_sync (device, enrolled_print, NULL,
test_driver_match_cb, match_data,
&match, &out_print, &error);
g_assert (fake_dev->last_called_function == dev_class->verify);
g_assert (fake_dev->action_data == enrolled_print);
@@ -985,18 +761,17 @@ test_driver_verify_fail (void)
{
g_autoptr(GError) error = NULL;
g_autoptr(FpAutoCloseDevice) device = auto_close_fake_device_new ();
g_autoptr(FpPrint) enrolled_print = NULL;
g_autoptr(FpPrint) enrolled_print = g_object_ref_sink (fp_print_new (device));
g_autoptr(FpPrint) out_print = NULL;
g_autoptr(MatchCbData) match_data = g_new0 (MatchCbData, 1);
FpDeviceClass *dev_class = FP_DEVICE_GET_CLASS (device);
FpiDeviceFake *fake_dev = FPI_DEVICE_FAKE (device);
gboolean match;
enrolled_print = make_fake_print_reffed (device, g_variant_new_uint64 (3));
fake_dev->ret_result = FPI_MATCH_FAIL;
g_assert_true (fp_device_verify_sync (device, enrolled_print, NULL,
test_driver_match_cb, match_data,
&match, &out_print, &error));
fp_device_verify_sync (device, enrolled_print, NULL,
test_driver_match_cb, match_data,
&match, &out_print, &error);
g_assert (fake_dev->last_called_function == dev_class->verify);
g_assert_no_error (error);
@@ -1015,7 +790,7 @@ test_driver_verify_retry (void)
{
g_autoptr(GError) error = NULL;
g_autoptr(FpAutoCloseDevice) device = auto_close_fake_device_new ();
g_autoptr(FpPrint) enrolled_print = make_fake_print_reffed (device, NULL);
g_autoptr(FpPrint) enrolled_print = g_object_ref_sink (fp_print_new (device));
g_autoptr(FpPrint) out_print = NULL;
g_autoptr(MatchCbData) match_data = g_new0 (MatchCbData, 1);
FpDeviceClass *dev_class = FP_DEVICE_GET_CLASS (device);
@@ -1024,9 +799,9 @@ test_driver_verify_retry (void)
fake_dev->ret_result = FPI_MATCH_ERROR;
fake_dev->ret_error = fpi_device_retry_new (FP_DEVICE_RETRY_GENERAL);
g_assert_false (fp_device_verify_sync (device, enrolled_print, NULL,
test_driver_match_cb, match_data,
&match, &out_print, &error));
fp_device_verify_sync (device, enrolled_print, NULL,
test_driver_match_cb, match_data,
&match, &out_print, &error);
g_assert_true (match_data->called);
g_assert_null (match_data->match);
@@ -1043,7 +818,7 @@ test_driver_verify_error (void)
{
g_autoptr(GError) error = NULL;
g_autoptr(FpAutoCloseDevice) device = auto_close_fake_device_new ();
g_autoptr(FpPrint) enrolled_print = make_fake_print_reffed (device, NULL);
g_autoptr(FpPrint) enrolled_print = g_object_ref_sink (fp_print_new (device));
g_autoptr(FpPrint) out_print = NULL;
g_autoptr(MatchCbData) match_data = g_new0 (MatchCbData, 1);
FpDeviceClass *dev_class = FP_DEVICE_GET_CLASS (device);
@@ -1052,9 +827,9 @@ test_driver_verify_error (void)
fake_dev->ret_result = FPI_MATCH_ERROR;
fake_dev->ret_error = fpi_device_error_new (FP_DEVICE_ERROR_GENERAL);
g_assert_false (fp_device_verify_sync (device, enrolled_print, NULL,
test_driver_match_cb, match_data,
&match, &out_print, &error));
fp_device_verify_sync (device, enrolled_print, NULL,
test_driver_match_cb, match_data,
&match, &out_print, &error);
g_assert_false (match_data->called);
g_assert_null (match_data->match);
@@ -1082,16 +857,16 @@ test_driver_verify_not_reported (void)
dev_class->verify = fake_device_verify_immediate_complete;
device = g_object_new (FPI_TYPE_DEVICE_FAKE, NULL);
enrolled_print = make_fake_print_reffed (device, NULL);
enrolled_print = g_object_ref_sink (fp_print_new (device));
g_assert_true (fp_device_open_sync (device, NULL, NULL));
g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_WARNING,
"*reported successful verify complete*not report*result*");
g_assert_false (fp_device_verify_sync (device, enrolled_print, NULL,
NULL, NULL,
NULL, NULL, &error));
fp_device_verify_sync (device, enrolled_print, NULL,
NULL, NULL,
NULL, NULL, &error);
g_assert_error (error, FP_DEVICE_ERROR, FP_DEVICE_ERROR_GENERAL);
@@ -1125,7 +900,7 @@ test_driver_verify_report_no_callback (void)
dev_class->verify = fake_device_verify_complete_error;
device = g_object_new (FPI_TYPE_DEVICE_FAKE, NULL);
fake_dev = FPI_DEVICE_FAKE (device);
enrolled_print = make_fake_print_reffed (device, NULL);
enrolled_print = g_object_ref_sink (fp_print_new (device));
g_assert_true (fp_device_open_sync (device, NULL, NULL));
@@ -1134,9 +909,9 @@ test_driver_verify_report_no_callback (void)
fake_dev->ret_result = FPI_MATCH_ERROR;
fake_dev->ret_error = fpi_device_error_new (FP_DEVICE_ERROR_NOT_SUPPORTED);
g_assert_false (fp_device_verify_sync (device, enrolled_print, NULL,
test_driver_match_cb, match_data,
&match, &print, &error));
fp_device_verify_sync (device, enrolled_print, NULL,
test_driver_match_cb, match_data,
&match, &print, &error);
g_test_assert_expected_messages ();
@@ -1165,7 +940,7 @@ test_driver_verify_complete_retry (void)
dev_class->verify = fake_device_verify_complete_error;
device = g_object_new (FPI_TYPE_DEVICE_FAKE, NULL);
fake_dev = FPI_DEVICE_FAKE (device);
enrolled_print = make_fake_print_reffed (device, NULL);
enrolled_print = g_object_ref_sink (fp_print_new (device));
g_assert_true (fp_device_open_sync (device, NULL, NULL));
@@ -1175,8 +950,8 @@ test_driver_verify_complete_retry (void)
test_driver_match_data_clear (match_data);
fake_dev->ret_result = FPI_MATCH_FAIL;
fake_dev->ret_error = fpi_device_retry_new (FP_DEVICE_RETRY_TOO_SHORT);
g_assert_false (fp_device_verify_sync (device, enrolled_print, NULL, test_driver_match_cb,
match_data, &match, &print, &error));
fp_device_verify_sync (device, enrolled_print, NULL, test_driver_match_cb,
match_data, &match, &print, &error);
g_test_assert_expected_messages ();
g_assert_true (error == g_steal_pointer (&fake_dev->ret_error));
@@ -1197,8 +972,8 @@ test_driver_verify_complete_retry (void)
fake_dev->ret_result = FPI_MATCH_FAIL;
fake_dev->ret_error = fpi_device_retry_new (FP_DEVICE_RETRY_TOO_SHORT);
fake_dev->user_data = g_error_copy (fake_dev->ret_error);
g_assert_false (fp_device_verify_sync (device, enrolled_print, NULL, test_driver_match_cb,
match_data, &match, &print, &error));
fp_device_verify_sync (device, enrolled_print, NULL, test_driver_match_cb,
match_data, &match, &print, &error);
g_test_assert_expected_messages ();
g_assert_true (error != g_steal_pointer (&fake_dev->ret_error));
@@ -1219,8 +994,8 @@ test_driver_verify_complete_retry (void)
fake_dev->ret_error = fpi_device_retry_new (FP_DEVICE_RETRY_TOO_SHORT);
fake_dev->user_data = g_error_copy (fake_dev->ret_error);
g_assert_false (fp_device_verify_sync (device, enrolled_print, NULL, test_driver_match_cb,
match_data, &match, &print, &error));
fp_device_verify_sync (device, enrolled_print, NULL, test_driver_match_cb,
match_data, &match, &print, &error);
g_test_assert_expected_messages ();
g_assert_true (error != g_steal_pointer (&fake_dev->ret_error));
@@ -1239,8 +1014,8 @@ test_driver_verify_complete_retry (void)
test_driver_match_data_clear (match_data);
fake_dev->ret_result = FPI_MATCH_ERROR;
g_assert_false (fp_device_verify_sync (device, enrolled_print, NULL, test_driver_match_cb,
match_data, &match, &print, &error));
fp_device_verify_sync (device, enrolled_print, NULL, test_driver_match_cb,
match_data, &match, &print, &error);
g_test_assert_expected_messages ();
g_assert_true (error != g_steal_pointer (&fake_dev->ret_error));
@@ -1258,12 +1033,12 @@ test_driver_verify_complete_retry (void)
test_driver_match_data_clear (match_data);
fake_dev->ret_result = FPI_MATCH_ERROR;
fake_dev->ret_error = fpi_device_retry_new (FP_DEVICE_RETRY_TOO_SHORT);
fake_dev->ret_print = make_fake_print (device, NULL);
fake_dev->ret_print = fp_print_new (device);
g_object_add_weak_pointer (G_OBJECT (fake_dev->ret_print),
(gpointer) (&fake_dev->ret_print));
g_assert_false (fp_device_verify_sync (device, enrolled_print, NULL, test_driver_match_cb,
match_data, &match, &print, &error));
fp_device_verify_sync (device, enrolled_print, NULL, test_driver_match_cb,
match_data, &match, &print, &error);
g_test_assert_expected_messages ();
g_assert_error (error, FP_DEVICE_RETRY, FP_DEVICE_RETRY_TOO_SHORT);
@@ -1312,23 +1087,25 @@ test_driver_identify (void)
g_autoptr(FpPrint) print = NULL;
g_autoptr(FpPrint) matched_print = NULL;
g_autoptr(FpAutoCloseDevice) device = auto_close_fake_device_new ();
g_autoptr(GPtrArray) prints = make_fake_prints_gallery (device, 500);
g_autoptr(GPtrArray) prints = g_ptr_array_new_with_free_func (g_object_unref);
g_autoptr(MatchCbData) match_data = g_new0 (MatchCbData, 1);
FpDeviceClass *dev_class = FP_DEVICE_GET_CLASS (device);
FpiDeviceFake *fake_dev = FPI_DEVICE_FAKE (device);
FpPrint *expected_matched;
unsigned int i;
for (i = 0; i < 500; ++i)
g_ptr_array_add (prints, g_object_ref_sink (fp_print_new (device)));
expected_matched = g_ptr_array_index (prints, g_random_int_range (0, 499));
fp_print_set_description (expected_matched, "fake-verified");
g_assert_true (fp_device_supports_identify (device));
match_data->gallery = prints;
fake_dev->ret_print = make_fake_print (device, NULL);
g_assert_true (fp_device_identify_sync (device, prints, NULL,
test_driver_match_cb, match_data,
&matched_print, &print, &error));
fake_dev->ret_print = fp_print_new (device);
fp_device_identify_sync (device, prints, NULL,
test_driver_match_cb, match_data,
&matched_print, &print, &error);
g_assert_true (match_data->called);
g_assert_nonnull (match_data->match);
@@ -1336,6 +1113,7 @@ test_driver_identify (void)
g_assert_true (match_data->print == print);
g_assert (fake_dev->last_called_function == dev_class->identify);
g_assert (fake_dev->action_data == prints);
g_assert_no_error (error);
g_assert (print != NULL && print == fake_dev->ret_print);
@@ -1349,17 +1127,21 @@ test_driver_identify_fail (void)
g_autoptr(FpPrint) print = NULL;
g_autoptr(FpPrint) matched_print = NULL;
g_autoptr(FpAutoCloseDevice) device = auto_close_fake_device_new ();
g_autoptr(GPtrArray) prints = make_fake_prints_gallery (device, 500);
g_autoptr(GPtrArray) prints = g_ptr_array_new_with_free_func (g_object_unref);
g_autoptr(MatchCbData) match_data = g_new0 (MatchCbData, 1);
FpDeviceClass *dev_class = FP_DEVICE_GET_CLASS (device);
FpiDeviceFake *fake_dev = FPI_DEVICE_FAKE (device);
unsigned int i;
for (i = 0; i < 500; ++i)
g_ptr_array_add (prints, g_object_ref_sink (fp_print_new (device)));
g_assert_true (fp_device_supports_identify (device));
fake_dev->ret_print = make_fake_print (device, NULL);
g_assert_true (fp_device_identify_sync (device, prints, NULL,
test_driver_match_cb, match_data,
&matched_print, &print, &error));
fake_dev->ret_print = fp_print_new (device);
fp_device_identify_sync (device, prints, NULL,
test_driver_match_cb, match_data,
&matched_print, &print, &error);
g_assert_true (match_data->called);
g_assert_null (match_data->match);
@@ -1381,11 +1163,15 @@ test_driver_identify_retry (void)
g_autoptr(FpPrint) print = NULL;
g_autoptr(FpPrint) matched_print = NULL;
g_autoptr(FpAutoCloseDevice) device = auto_close_fake_device_new ();
g_autoptr(GPtrArray) prints = make_fake_prints_gallery (device, 500);
g_autoptr(GPtrArray) prints = g_ptr_array_new_with_free_func (g_object_unref);
g_autoptr(MatchCbData) match_data = g_new0 (MatchCbData, 1);
FpDeviceClass *dev_class = FP_DEVICE_GET_CLASS (device);
FpiDeviceFake *fake_dev = FPI_DEVICE_FAKE (device);
FpPrint *expected_matched;
unsigned int i;
for (i = 0; i < 500; ++i)
g_ptr_array_add (prints, g_object_ref_sink (fp_print_new (device)));
expected_matched = g_ptr_array_index (prints, g_random_int_range (0, 499));
fp_print_set_description (expected_matched, "fake-verified");
@@ -1393,9 +1179,9 @@ test_driver_identify_retry (void)
g_assert_true (fp_device_supports_identify (device));
fake_dev->ret_error = fpi_device_retry_new (FP_DEVICE_RETRY_GENERAL);
g_assert_false (fp_device_identify_sync (device, prints, NULL,
test_driver_match_cb, match_data,
&matched_print, &print, &error));
fp_device_identify_sync (device, prints, NULL,
test_driver_match_cb, match_data,
&matched_print, &print, &error);
g_assert_true (match_data->called);
g_assert_null (match_data->match);
@@ -1415,11 +1201,15 @@ test_driver_identify_error (void)
g_autoptr(FpPrint) print = NULL;
g_autoptr(FpPrint) matched_print = NULL;
g_autoptr(FpAutoCloseDevice) device = auto_close_fake_device_new ();
g_autoptr(GPtrArray) prints = make_fake_prints_gallery (device, 500);
g_autoptr(GPtrArray) prints = g_ptr_array_new_with_free_func (g_object_unref);
g_autoptr(MatchCbData) match_data = g_new0 (MatchCbData, 1);
FpDeviceClass *dev_class = FP_DEVICE_GET_CLASS (device);
FpiDeviceFake *fake_dev = FPI_DEVICE_FAKE (device);
FpPrint *expected_matched;
unsigned int i;
for (i = 0; i < 500; ++i)
g_ptr_array_add (prints, g_object_ref_sink (fp_print_new (device)));
expected_matched = g_ptr_array_index (prints, g_random_int_range (0, 499));
fp_print_set_description (expected_matched, "fake-verified");
@@ -1427,9 +1217,9 @@ test_driver_identify_error (void)
g_assert_true (fp_device_supports_identify (device));
fake_dev->ret_error = fpi_device_error_new (FP_DEVICE_ERROR_GENERAL);
g_assert_false (fp_device_identify_sync (device, prints, NULL,
test_driver_match_cb, match_data,
&matched_print, &print, &error));
fp_device_identify_sync (device, prints, NULL,
test_driver_match_cb, match_data,
&matched_print, &print, &error);
g_assert_false (match_data->called);
g_assert_null (match_data->match);
@@ -1453,21 +1243,24 @@ test_driver_identify_not_reported (void)
{
g_autoptr(FpAutoResetClass) dev_class = auto_reset_device_class ();
g_autoptr(FpAutoCloseDevice) device = NULL;
g_autoptr(GPtrArray) prints = NULL;
g_autoptr(GPtrArray) prints = g_ptr_array_new_with_free_func (g_object_unref);
g_autoptr(GError) error = NULL;
unsigned int i;
dev_class->identify = fake_device_identify_immediate_complete;
device = g_object_new (FPI_TYPE_DEVICE_FAKE, NULL);
prints = make_fake_prints_gallery (device, 500);
for (i = 0; i < 500; ++i)
g_ptr_array_add (prints, g_object_ref_sink (fp_print_new (device)));
g_assert_true (fp_device_open_sync (device, NULL, NULL));
g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_WARNING,
"*reported successful identify complete*not report*result*");
g_assert_false (fp_device_identify_sync (device, prints, NULL,
NULL, NULL,
NULL, NULL, &error));
fp_device_identify_sync (device, prints, NULL,
NULL, NULL,
NULL, NULL, &error);
g_assert_error (error, FP_DEVICE_ERROR, FP_DEVICE_ERROR_GENERAL);
@@ -1490,18 +1283,21 @@ static void
test_driver_identify_complete_retry (void)
{
g_autoptr(FpAutoResetClass) dev_class = auto_reset_device_class ();
g_autoptr(GPtrArray) prints = NULL;
g_autoptr(GPtrArray) prints = g_ptr_array_new_with_free_func (g_object_unref);
g_autoptr(MatchCbData) match_data = g_new0 (MatchCbData, 1);
g_autoptr(FpAutoCloseDevice) device = NULL;
g_autoptr(FpPrint) print = NULL;
g_autoptr(FpPrint) match = NULL;
g_autoptr(GError) error = NULL;
FpiDeviceFake *fake_dev;
int i;
dev_class->identify = fake_device_identify_complete_error;
device = g_object_new (FPI_TYPE_DEVICE_FAKE, NULL);
fake_dev = FPI_DEVICE_FAKE (device);
prints = make_fake_prints_gallery (device, 500);
for (i = 0; i < 500; ++i)
g_ptr_array_add (prints, g_object_ref_sink (fp_print_new (device)));
g_assert_true (fp_device_open_sync (device, NULL, NULL));
@@ -1513,9 +1309,8 @@ test_driver_identify_complete_retry (void)
fake_dev->ret_error = fpi_device_retry_new (FP_DEVICE_RETRY_TOO_SHORT);
fake_dev->user_data = g_error_copy (fake_dev->ret_error);
g_assert_false (fp_device_identify_sync (device, prints, NULL,
test_driver_match_cb, match_data,
&match, &print, &error));
fp_device_identify_sync (device, prints, NULL, test_driver_match_cb, match_data,
&match, &print, &error);
g_test_assert_expected_messages ();
g_assert_true (error != g_steal_pointer (&fake_dev->ret_error));
@@ -1531,12 +1326,11 @@ test_driver_identify_complete_retry (void)
"*Driver reported a match to a print that was not in the gallery*");
test_driver_match_data_clear (match_data);
fake_dev->ret_match = make_fake_print_reffed (device, NULL);
fake_dev->ret_match = fp_print_new (device);
g_object_add_weak_pointer (G_OBJECT (fake_dev->ret_match),
(gpointer) (&fake_dev->ret_match));
g_assert_true (fp_device_identify_sync (device, prints, NULL,
test_driver_match_cb, match_data,
&match, &print, &error));
fp_device_identify_sync (device, prints, NULL, test_driver_match_cb, match_data,
&match, &print, &error);
g_test_assert_expected_messages ();
g_object_unref (fake_dev->ret_match);
@@ -1555,12 +1349,11 @@ test_driver_identify_complete_retry (void)
test_driver_match_data_clear (match_data);
fake_dev->ret_error = fpi_device_retry_new (FP_DEVICE_RETRY_REMOVE_FINGER);
fake_dev->ret_match = prints->pdata[0];
fake_dev->ret_print = make_fake_print (device, NULL);
fake_dev->ret_print = fp_print_new (device);
g_object_add_weak_pointer (G_OBJECT (fake_dev->ret_print),
(gpointer) (&fake_dev->ret_print));
g_assert_false (fp_device_identify_sync (device, prints, NULL,
test_driver_match_cb, match_data,
&match, &print, &error));
fp_device_identify_sync (device, prints, NULL, test_driver_match_cb, match_data,
&match, &print, &error);
g_test_assert_expected_messages ();
g_assert_error (error, FP_DEVICE_RETRY, FP_DEVICE_RETRY_REMOVE_FINGER);
@@ -1578,7 +1371,7 @@ test_driver_identify_report_no_callback (void)
{
g_autoptr(FpAutoResetClass) dev_class = auto_reset_device_class ();
g_autoptr(MatchCbData) match_data = g_new0 (MatchCbData, 1);
g_autoptr(GPtrArray) prints = NULL;
g_autoptr(GPtrArray) prints = g_ptr_array_new_with_free_func (g_object_unref);
g_autoptr(FpAutoCloseDevice) device = NULL;
G_GNUC_UNUSED g_autoptr(FpPrint) enrolled_print = NULL;
g_autoptr(FpPrint) print = NULL;
@@ -1589,8 +1382,7 @@ test_driver_identify_report_no_callback (void)
dev_class->identify = fake_device_identify_complete_error;
device = g_object_new (FPI_TYPE_DEVICE_FAKE, NULL);
fake_dev = FPI_DEVICE_FAKE (device);
prints = make_fake_prints_gallery (device, 0);
enrolled_print = make_fake_print_reffed (device, NULL);
enrolled_print = g_object_ref_sink (fp_print_new (device));
g_assert_true (fp_device_open_sync (device, NULL, NULL));
@@ -1598,9 +1390,9 @@ test_driver_identify_report_no_callback (void)
"*Driver reported a verify error that was not in the retry domain*");
fake_dev->ret_error = fpi_device_error_new (FP_DEVICE_ERROR_NOT_SUPPORTED);
g_assert_false (fp_device_identify_sync (device, prints, NULL,
test_driver_match_cb, match_data,
&match, &print, &error));
fp_device_identify_sync (device, prints, NULL,
test_driver_match_cb, match_data,
&match, &print, &error);
g_test_assert_expected_messages ();
@@ -1717,10 +1509,15 @@ test_driver_list (void)
{
g_autoptr(GError) error = NULL;
g_autoptr(FpAutoCloseDevice) device = auto_close_fake_device_new ();
g_autoptr(GPtrArray) prints = make_fake_prints_gallery (device, 500);
FpDeviceClass *dev_class = FP_DEVICE_GET_CLASS (device);
FpiDeviceFake *fake_dev = FPI_DEVICE_FAKE (device);
g_autoptr(GPtrArray) prints = g_ptr_array_new_with_free_func (g_object_unref);
unsigned int i;
for (i = 0; i < 500; ++i)
g_ptr_array_add (prints, fp_print_new (device));
fake_dev->ret_list = g_steal_pointer (&prints);
prints = fp_device_list_prints_sync (device, NULL, &error);
@@ -1773,7 +1570,7 @@ test_driver_delete (void)
{
g_autoptr(GError) error = NULL;
g_autoptr(FpAutoCloseDevice) device = auto_close_fake_device_new ();
g_autoptr(FpPrint) enrolled_print = make_fake_print_reffed (device, NULL);
g_autoptr(FpPrint) enrolled_print = fp_print_new (device);
FpDeviceClass *dev_class = FP_DEVICE_GET_CLASS (device);
FpiDeviceFake *fake_dev = FPI_DEVICE_FAKE (device);
gboolean ret;
@@ -1790,7 +1587,7 @@ test_driver_delete_error (void)
{
g_autoptr(GError) error = NULL;
g_autoptr(FpAutoCloseDevice) device = auto_close_fake_device_new ();
g_autoptr(FpPrint) enrolled_print = make_fake_print_reffed (device, NULL);
g_autoptr(FpPrint) enrolled_print = fp_print_new (device);
FpDeviceClass *dev_class = FP_DEVICE_GET_CLASS (device);
FpiDeviceFake *fake_dev = FPI_DEVICE_FAKE (device);
gboolean ret;
@@ -1858,7 +1655,7 @@ test_driver_cancel (void)
device = auto_close_fake_device_new ();
fake_dev = FPI_DEVICE_FAKE (device);
cancellable = g_cancellable_new ();
enrolled_print = make_fake_print_reffed (device, NULL);
enrolled_print = fp_print_new (device);
fp_device_delete_print (device, enrolled_print, cancellable,
on_driver_cancel_delete, &completed);
@@ -1876,11 +1673,11 @@ test_driver_cancel_fail (void)
g_autoptr(GError) error = NULL;
g_autoptr(FpAutoCloseDevice) device = auto_close_fake_device_new ();
g_autoptr(GCancellable) cancellable = g_cancellable_new ();
g_autoptr(FpPrint) enrolled_print = make_fake_print_reffed (device, NULL);
g_autoptr(FpPrint) enrolled_print = fp_print_new (device);
FpDeviceClass *dev_class = FP_DEVICE_GET_CLASS (device);
FpiDeviceFake *fake_dev = FPI_DEVICE_FAKE (device);
g_assert_true (fp_device_delete_print_sync (device, enrolled_print, cancellable, &error));
fp_device_delete_print_sync (device, enrolled_print, cancellable, &error);
g_assert (fake_dev->last_called_function == dev_class->delete);
g_cancellable_cancel (cancellable);
@@ -1951,7 +1748,7 @@ test_driver_action_get_cancellable_open (void)
fake_dev = FPI_DEVICE_FAKE (device);
cancellable = g_cancellable_new ();
g_assert_true (fp_device_open_sync (device, cancellable, NULL));
fp_device_open_sync (device, cancellable, NULL);
g_assert (fake_dev->last_called_function == test_driver_action_get_cancellable_open_vfunc);
}
@@ -2110,8 +1907,8 @@ static void
test_driver_action_error_all (void)
{
g_autoptr(FpAutoCloseDevice) device = g_object_new (FPI_TYPE_DEVICE_FAKE, NULL);
g_autoptr(FpPrint) enrolled_print = make_fake_print_reffed (device, NULL);
g_autoptr(GPtrArray) prints = make_fake_prints_gallery (device, 0);
g_autoptr(FpPrint) enrolled_print = g_object_ref_sink (fp_print_new (device));
g_autoptr(GPtrArray) prints = g_ptr_array_new_with_free_func (g_object_unref);
g_autoptr(GError) error = NULL;
FpDeviceClass *dev_class = FP_DEVICE_GET_CLASS (device);
FpiDeviceFake *fake_dev;
@@ -2131,6 +1928,12 @@ test_driver_action_error_all (void)
fake_dev->return_action_error = TRUE;
fake_dev->ret_error = fpi_device_error_new (FP_DEVICE_ERROR_DATA_INVALID);
g_assert_false (fp_device_close_sync (device, NULL, &error));
g_assert_true (fake_dev->last_called_function == dev_class->close);
g_assert_error (error, FP_DEVICE_ERROR, FP_DEVICE_ERROR_DATA_INVALID);
g_clear_error (&error);
fake_dev->ret_error = fpi_device_error_new (FP_DEVICE_ERROR_DATA_INVALID);
g_assert_null (fp_device_enroll_sync (device, fp_print_new (device), NULL,
NULL, NULL, &error));
@@ -2169,21 +1972,14 @@ test_driver_action_error_all (void)
g_assert_true (fake_dev->last_called_function == dev_class->delete);
g_assert_error (error, FP_DEVICE_ERROR, FP_DEVICE_ERROR_DATA_INVALID);
g_clear_error (&error);
/* Test close last, as we can't operate on a closed device. */
fake_dev->ret_error = fpi_device_error_new (FP_DEVICE_ERROR_DATA_INVALID);
g_assert_false (fp_device_close_sync (device, NULL, &error));
g_assert_true (fake_dev->last_called_function == dev_class->close);
g_assert_error (error, FP_DEVICE_ERROR, FP_DEVICE_ERROR_DATA_INVALID);
g_clear_error (&error);
}
static void
test_driver_action_error_fallback_all (void)
{
g_autoptr(FpAutoCloseDevice) device = g_object_new (FPI_TYPE_DEVICE_FAKE, NULL);
g_autoptr(FpPrint) enrolled_print = make_fake_print_reffed (device, NULL);
g_autoptr(GPtrArray) prints = make_fake_prints_gallery (device, 0);
g_autoptr(FpPrint) enrolled_print = g_object_ref_sink (fp_print_new (device));
g_autoptr(GPtrArray) prints = g_ptr_array_new_with_free_func (g_object_unref);
g_autoptr(GError) error = NULL;
FpDeviceClass *dev_class = FP_DEVICE_GET_CLASS (device);
FpiDeviceFake *fake_dev;
@@ -2209,6 +2005,16 @@ test_driver_action_error_fallback_all (void)
"error function*");
fake_dev->return_action_error = TRUE;
g_assert_false (fp_device_close_sync (device, NULL, &error));
g_test_assert_expected_messages ();
g_assert_true (fake_dev->last_called_function == dev_class->close);
g_assert_error (error, FP_DEVICE_ERROR, FP_DEVICE_ERROR_GENERAL);
g_clear_error (&error);
g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_WARNING,
"*Device failed to pass an error to generic action "
"error function*");
g_assert_null (fp_device_enroll_sync (device, fp_print_new (device), NULL,
NULL, NULL, &error));
g_test_assert_expected_messages ();
@@ -2268,17 +2074,6 @@ test_driver_action_error_fallback_all (void)
g_assert_true (fake_dev->last_called_function == dev_class->delete);
g_assert_error (error, FP_DEVICE_ERROR, FP_DEVICE_ERROR_GENERAL);
g_clear_error (&error);
/* Test close last, as we can't operate on a closed device. */
g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_WARNING,
"*Device failed to pass an error to generic action "
"error function*");
g_assert_false (fp_device_close_sync (device, NULL, &error));
g_test_assert_expected_messages ();
g_assert_true (fake_dev->last_called_function == dev_class->close);
g_assert_error (error, FP_DEVICE_ERROR, FP_DEVICE_ERROR_GENERAL);
g_clear_error (&error);
}
static void
@@ -2412,10 +2207,6 @@ main (int argc, char *argv[])
g_test_add_func ("/driver/get_scan_type/swipe", test_driver_get_scan_type_swipe);
g_test_add_func ("/driver/set_scan_type/press", test_driver_set_scan_type_press);
g_test_add_func ("/driver/set_scan_type/swipe", test_driver_set_scan_type_swipe);
g_test_add_func ("/driver/finger_status/inactive", test_driver_finger_status_inactive);
g_test_add_func ("/driver/finger_status/waiting", test_driver_finger_status_needed);
g_test_add_func ("/driver/finger_status/present", test_driver_finger_status_present);
g_test_add_func ("/driver/finger_status/changes", test_driver_finger_status_changes);
g_test_add_func ("/driver/get_nr_enroll_stages", test_driver_get_nr_enroll_stages);
g_test_add_func ("/driver/set_nr_enroll_stages", test_driver_set_nr_enroll_stages);
g_test_add_func ("/driver/supports_identify", test_driver_supports_identify);

6
tests/umockdev-test.py Normal file → Executable file
View File

@@ -87,12 +87,6 @@ try:
if os.path.exists(os.path.join(ddir, "custom.ioctl")):
custom()
except Exception as e:
# Store created output files for inspection (in the build directory)
outdir = os.path.join('errors', os.path.basename(ddir))
shutil.copytree(tmpdir, outdir, dirs_exist_ok=True)
raise e
finally:
shutil.rmtree(tmpdir)

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

Before

Width:  |  Height:  |  Size: 58 KiB

View File

@@ -1,307 +0,0 @@
P: /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.3
N: bus/usb/002/005=12011001FF10FF088A130500900C0000000109022700010100A0320904000003FF000000070501024000000705810240000007058202400000
E: DEVNAME=/dev/bus/usb/002/005
E: DEVTYPE=usb_device
E: DRIVER=usb
E: PRODUCT=138a/5/c90
E: TYPE=255/16/255
E: BUSNUM=002
E: DEVNUM=005
E: MAJOR=189
E: MINOR=132
E: SUBSYSTEM=usb
E: ID_VENDOR=138a
E: ID_VENDOR_ENC=138a
E: ID_VENDOR_ID=138a
E: ID_MODEL=0005
E: ID_MODEL_ENC=0005
E: ID_MODEL_ID=0005
E: ID_REVISION=0c90
E: ID_SERIAL=138a_0005
E: ID_BUS=usb
E: ID_USB_INTERFACES=:ff0000:
E: ID_VENDOR_FROM_DATABASE=Validity Sensors, Inc.
E: ID_MODEL_FROM_DATABASE=VFS301 Fingerprint Reader
E: ID_PATH=pci-0000:00:1d.0-usb-0:1.3
E: ID_PATH_TAG=pci-0000_00_1d_0-usb-0_1_3
E: LIBFPRINT_DRIVER=Validity VFS301
A: authorized=1
A: avoid_reset_quirk=0
A: bConfigurationValue=1
A: bDeviceClass=ff
A: bDeviceProtocol=ff
A: bDeviceSubClass=10
A: bMaxPacketSize0=8
A: bMaxPower=100mA
A: bNumConfigurations=1
A: bNumInterfaces= 1
A: bcdDevice=0c90
A: bmAttributes=a0
A: busnum=2
A: configuration=
H: descriptors=12011001FF10FF088A130500900C0000000109022700010100A0320904000003FF000000070501024000000705810240000007058202400000
A: dev=189:132
A: devnum=5
A: devpath=1.3
L: driver=../../../../../../bus/usb/drivers/usb
A: idProduct=0005
A: idVendor=138a
A: ltm_capable=no
A: maxchild=0
L: port=../2-1:1.0/2-1-port3
A: power/active_duration=1612976
A: power/async=enabled
A: power/autosuspend=2
A: power/autosuspend_delay_ms=2000
A: power/connected_duration=2159928
A: power/control=auto
A: power/level=auto
A: power/persist=1
A: power/runtime_active_kids=0
A: power/runtime_active_time=1612851
A: power/runtime_enabled=enabled
A: power/runtime_status=active
A: power/runtime_suspended_time=546887
A: power/runtime_usage=0
A: power/wakeup=disabled
A: power/wakeup_abort_count=
A: power/wakeup_active=
A: power/wakeup_active_count=
A: power/wakeup_count=
A: power/wakeup_expire_count=
A: power/wakeup_last_time_ms=
A: power/wakeup_max_time_ms=
A: power/wakeup_total_time_ms=
A: quirks=0x0
A: removable=fixed
A: rx_lanes=1
A: speed=12
A: tx_lanes=1
A: urbnum=7
A: version= 1.10
P: /devices/pci0000:00/0000:00:1d.0/usb2/2-1
N: bus/usb/002/002=12010002090001408780200000000000000109021900010100E0000904000001090000000705810302000C
E: DEVNAME=/dev/bus/usb/002/002
E: DEVTYPE=usb_device
E: DRIVER=usb
E: PRODUCT=8087/20/0
E: TYPE=9/0/1
E: BUSNUM=002
E: DEVNUM=002
E: MAJOR=189
E: MINOR=129
E: SUBSYSTEM=usb
E: ID_VENDOR=8087
E: ID_VENDOR_ENC=8087
E: ID_VENDOR_ID=8087
E: ID_MODEL=0020
E: ID_MODEL_ENC=0020
E: ID_MODEL_ID=0020
E: ID_REVISION=0000
E: ID_SERIAL=8087_0020
E: ID_BUS=usb
E: ID_USB_INTERFACES=:090000:
E: ID_VENDOR_FROM_DATABASE=Intel Corp.
E: ID_MODEL_FROM_DATABASE=Integrated Rate Matching Hub
E: ID_PATH=pci-0000:00:1d.0-usb-0:1
E: ID_PATH_TAG=pci-0000_00_1d_0-usb-0_1
E: ID_FOR_SEAT=usb-pci-0000_00_1d_0-usb-0_1
E: TAGS=:seat:
A: authorized=1
A: avoid_reset_quirk=0
A: bConfigurationValue=1
A: bDeviceClass=09
A: bDeviceProtocol=01
A: bDeviceSubClass=00
A: bMaxPacketSize0=64
A: bMaxPower=0mA
A: bNumConfigurations=1
A: bNumInterfaces= 1
A: bcdDevice=0000
A: bmAttributes=e0
A: busnum=2
A: configuration=
H: descriptors=12010002090001408780200000000000000109021900010100E0000904000001090000000705810302000C
A: dev=189:129
A: devnum=2
A: devpath=1
L: driver=../../../../../bus/usb/drivers/usb
A: idProduct=0020
A: idVendor=8087
A: ltm_capable=no
A: maxchild=8
L: port=../2-0:1.0/usb2-port1
A: power/active_duration=2160820
A: power/async=enabled
A: power/autosuspend=0
A: power/autosuspend_delay_ms=0
A: power/connected_duration=2160824
A: power/control=auto
A: power/level=auto
A: power/runtime_active_kids=3
A: power/runtime_active_time=2160531
A: power/runtime_enabled=enabled
A: power/runtime_status=active
A: power/runtime_suspended_time=0
A: power/runtime_usage=0
A: power/wakeup=disabled
A: power/wakeup_abort_count=
A: power/wakeup_active=
A: power/wakeup_active_count=
A: power/wakeup_count=
A: power/wakeup_expire_count=
A: power/wakeup_last_time_ms=
A: power/wakeup_max_time_ms=
A: power/wakeup_total_time_ms=
A: quirks=0x0
A: removable=fixed
A: rx_lanes=1
A: speed=480
A: tx_lanes=1
A: urbnum=75
A: version= 2.00
P: /devices/pci0000:00/0000:00:1d.0/usb2
N: bus/usb/002/001=12010002090000406B1D020004050302010109021900010100E0000904000001090000000705810304000C
E: DEVNAME=/dev/bus/usb/002/001
E: DEVTYPE=usb_device
E: DRIVER=usb
E: PRODUCT=1d6b/2/504
E: TYPE=9/0/0
E: BUSNUM=002
E: DEVNUM=001
E: MAJOR=189
E: MINOR=128
E: SUBSYSTEM=usb
E: ID_VENDOR=Linux_5.4.0-48-generic_ehci_hcd
E: ID_VENDOR_ENC=Linux\x205.4.0-48-generic\x20ehci_hcd
E: ID_VENDOR_ID=1d6b
E: ID_MODEL=EHCI_Host_Controller
E: ID_MODEL_ENC=EHCI\x20Host\x20Controller
E: ID_MODEL_ID=0002
E: ID_REVISION=0504
E: ID_SERIAL=Linux_5.4.0-48-generic_ehci_hcd_EHCI_Host_Controller_0000:00:1d.0
E: ID_SERIAL_SHORT=0000:00:1d.0
E: ID_BUS=usb
E: ID_USB_INTERFACES=:090000:
E: ID_VENDOR_FROM_DATABASE=Linux Foundation
E: ID_MODEL_FROM_DATABASE=2.0 root hub
E: ID_PATH=pci-0000:00:1d.0
E: ID_PATH_TAG=pci-0000_00_1d_0
E: ID_FOR_SEAT=usb-pci-0000_00_1d_0
E: TAGS=:seat:
A: authorized=1
A: authorized_default=1
A: avoid_reset_quirk=0
A: bConfigurationValue=1
A: bDeviceClass=09
A: bDeviceProtocol=00
A: bDeviceSubClass=00
A: bMaxPacketSize0=64
A: bMaxPower=0mA
A: bNumConfigurations=1
A: bNumInterfaces= 1
A: bcdDevice=0504
A: bmAttributes=e0
A: busnum=2
A: configuration=
H: descriptors=12010002090000406B1D020004050302010109021900010100E0000904000001090000000705810304000C
A: dev=189:128
A: devnum=1
A: devpath=0
L: driver=../../../../bus/usb/drivers/usb
A: idProduct=0002
A: idVendor=1d6b
A: interface_authorized_default=1
A: ltm_capable=no
A: manufacturer=Linux 5.4.0-48-generic ehci_hcd
A: maxchild=3
A: power/active_duration=2161060
A: power/async=enabled
A: power/autosuspend=0
A: power/autosuspend_delay_ms=0
A: power/connected_duration=2161060
A: power/control=auto
A: power/level=auto
A: power/runtime_active_kids=1
A: power/runtime_active_time=2161035
A: power/runtime_enabled=enabled
A: power/runtime_status=active
A: power/runtime_suspended_time=0
A: power/runtime_usage=0
A: power/wakeup=disabled
A: power/wakeup_abort_count=
A: power/wakeup_active=
A: power/wakeup_active_count=
A: power/wakeup_count=
A: power/wakeup_expire_count=
A: power/wakeup_last_time_ms=
A: power/wakeup_max_time_ms=
A: power/wakeup_total_time_ms=
A: product=EHCI Host Controller
A: quirks=0x0
A: removable=unknown
A: rx_lanes=1
A: serial=0000:00:1d.0
A: speed=480
A: tx_lanes=1
A: urbnum=26
A: version= 2.00
P: /devices/pci0000:00/0000:00:1d.0
E: DRIVER=ehci-pci
E: PCI_CLASS=C0320
E: PCI_ID=8086:3B34
E: PCI_SUBSYS_ID=103C:7001
E: PCI_SLOT_NAME=0000:00:1d.0
E: MODALIAS=pci:v00008086d00003B34sv0000103Csd00007001bc0Csc03i20
E: SUBSYSTEM=pci
E: ID_PCI_CLASS_FROM_DATABASE=Serial bus controller
E: ID_PCI_SUBCLASS_FROM_DATABASE=USB controller
E: ID_PCI_INTERFACE_FROM_DATABASE=EHCI
E: ID_VENDOR_FROM_DATABASE=Intel Corporation
E: ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset USB2 Enhanced Host Controller
A: ari_enabled=0
A: broken_parity_status=0
A: class=0x0c0320
A: companion=
H: config=8680343B060090020520030C00000000005810DB0000000000000000000000000000000000000000000000003C1001700000000050000000000000000B010000
A: consistent_dma_mask_bits=32
A: d3cold_allowed=1
A: device=0x3b34
A: dma_mask_bits=32
L: driver=../../../bus/pci/drivers/ehci-pci
A: driver_override=(null)
A: enable=1
A: irq=21
A: local_cpulist=0-7
A: local_cpus=ff
A: modalias=pci:v00008086d00003B34sv0000103Csd00007001bc0Csc03i20
A: msi_bus=1
A: numa_node=-1
A: pools=poolinfo - 0.1\nehci_sitd 0 0 96 0\nehci_itd 0 0 192 0\nehci_qh 12 42 96 1\nehci_qtd 13 84 96 2\nbuffer-2048 0 0 2048 0\nbuffer-512 0 0 512 0\nbuffer-128 2 32 128 1\nbuffer-32 0 0 32 0
A: power/async=enabled
A: power/control=on
A: power/runtime_active_kids=1
A: power/runtime_active_time=2161633
A: power/runtime_enabled=forbidden
A: power/runtime_status=active
A: power/runtime_suspended_time=0
A: power/runtime_usage=1
A: power/wakeup=enabled
A: power/wakeup_abort_count=0
A: power/wakeup_active=0
A: power/wakeup_active_count=0
A: power/wakeup_count=0
A: power/wakeup_expire_count=0
A: power/wakeup_last_time_ms=0
A: power/wakeup_max_time_ms=0
A: power/wakeup_total_time_ms=0
A: resource=0x00000000db105800 0x00000000db105bff 0x0000000000040200\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000
A: revision=0x05
A: subsystem_device=0x7001
A: subsystem_vendor=0x103c
A: uframe_periodic_max=100
A: vendor=0x8086

View File

@@ -172,7 +172,6 @@ class VirtualImage(unittest.TestCase):
def done_cb(dev, res):
print("Enroll done")
fp = dev.enroll_finish(res)
self.assertEqual(self.dev.get_finger_status(), FPrint.FingerStatusFlags.NONE)
self._enrolled = fp
template = FPrint.Print.new(self.dev)
@@ -183,7 +182,6 @@ class VirtualImage(unittest.TestCase):
date = GLib.Date()
date.set_dmy(*datetime.get_ymd()[::-1])
template.props.enroll_date = date
self.assertEqual(self.dev.get_finger_status(), FPrint.FingerStatusFlags.NONE)
self.dev.enroll(template, None, progress_cb, tuple(), done_cb)
# Note: Assumes 5 enroll steps for this device!
@@ -194,36 +192,25 @@ class VirtualImage(unittest.TestCase):
# Test the image-device path where the finger is removed after
# the minutiae scan is completed.
self.send_finger_automatic(False)
self.assertEqual(self.dev.get_finger_status(), FPrint.FingerStatusFlags.NEEDED)
self.send_finger_report(True)
self.assertEqual(self.dev.get_finger_status(),
FPrint.FingerStatusFlags.NEEDED | FPrint.FingerStatusFlags.PRESENT)
self.send_image(image)
while self._step < 2:
ctx.iteration(True)
self.send_finger_report(False)
self.assertEqual(self.dev.get_finger_status(), FPrint.FingerStatusFlags.NEEDED)
self.send_finger_automatic(True)
self.send_image(image)
while self._step < 3:
ctx.iteration(True)
self.assertEqual(self.dev.get_finger_status(), FPrint.FingerStatusFlags.NEEDED)
self.send_image(image)
while self._step < 4:
ctx.iteration(True)
self.assertEqual(self.dev.get_finger_status(), FPrint.FingerStatusFlags.NEEDED)
self.send_image(image)
while self._enrolled is None:
ctx.iteration(True)
self.assertEqual(self.dev.get_finger_status(), FPrint.FingerStatusFlags.NONE)
return self._enrolled
def test_enroll_verify(self):