2530 lines
74 KiB
Diff
2530 lines
74 KiB
Diff
|
From 3b368f67de150199ba2dfb083ab22e7fd2e4204f Mon Sep 17 00:00:00 2001
|
||
|
From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= <mail@3v1n0.net>
|
||
|
Date: Tue, 10 Dec 2019 20:24:04 +0100
|
||
|
Subject: [PATCH 105/181] fp-device: Move fpi code into its own unit that can
|
||
|
be compiled a part
|
||
|
|
||
|
In order to be able to test the private device code (used by drivers) we
|
||
|
need to have that split a part in a different .c file so that we can compile
|
||
|
it alone and link with it both the shared library and the test executables.
|
||
|
|
||
|
Redefine fp_device_get_instance_private for private usage, not to move
|
||
|
the private struct as part of FpDevice.
|
||
|
---
|
||
|
libfprint/fp-device-private.h | 65 ++
|
||
|
libfprint/fp-device.c | 1186 +--------------------------------
|
||
|
libfprint/fpi-device.c | 1177 ++++++++++++++++++++++++++++++++
|
||
|
libfprint/meson.build | 1 +
|
||
|
4 files changed, 1245 insertions(+), 1184 deletions(-)
|
||
|
create mode 100644 libfprint/fp-device-private.h
|
||
|
create mode 100644 libfprint/fpi-device.c
|
||
|
|
||
|
diff --git a/libfprint/fp-device-private.h b/libfprint/fp-device-private.h
|
||
|
new file mode 100644
|
||
|
index 0000000..65fb1cb
|
||
|
--- /dev/null
|
||
|
+++ b/libfprint/fp-device-private.h
|
||
|
@@ -0,0 +1,65 @@
|
||
|
+/*
|
||
|
+ * FpDevice - A fingerprint reader device
|
||
|
+ * Copyright (C) 2019 Benjamin Berg <bberg@redhat.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
|
||
|
+ * 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
|
||
|
+ */
|
||
|
+
|
||
|
+#pragma once
|
||
|
+
|
||
|
+#include "fpi-device.h"
|
||
|
+
|
||
|
+typedef struct
|
||
|
+{
|
||
|
+ FpDeviceType type;
|
||
|
+
|
||
|
+ GUsbDevice *usb_device;
|
||
|
+ const gchar *virtual_env;
|
||
|
+
|
||
|
+ gboolean is_open;
|
||
|
+
|
||
|
+ gchar *device_id;
|
||
|
+ gchar *device_name;
|
||
|
+ FpScanType scan_type;
|
||
|
+
|
||
|
+ guint64 driver_data;
|
||
|
+
|
||
|
+ gint nr_enroll_stages;
|
||
|
+ GSList *sources;
|
||
|
+
|
||
|
+ /* We always make sure that only one task is run at a time. */
|
||
|
+ FpDeviceAction current_action;
|
||
|
+ GTask *current_task;
|
||
|
+ GAsyncReadyCallback current_user_cb;
|
||
|
+ gulong current_cancellable_id;
|
||
|
+ GSource *current_idle_cancel_source;
|
||
|
+ GSource *current_task_idle_return_source;
|
||
|
+
|
||
|
+ /* State for tasks */
|
||
|
+ gboolean wait_for_finger;
|
||
|
+} FpDevicePrivate;
|
||
|
+
|
||
|
+
|
||
|
+typedef struct
|
||
|
+{
|
||
|
+ FpPrint *print;
|
||
|
+
|
||
|
+ FpEnrollProgress enroll_progress_cb;
|
||
|
+ gpointer enroll_progress_data;
|
||
|
+ GDestroyNotify enroll_progress_destroy;
|
||
|
+} FpEnrollData;
|
||
|
+
|
||
|
+void enroll_data_free (FpEnrollData *enroll_data);
|
||
|
diff --git a/libfprint/fp-device.c b/libfprint/fp-device.c
|
||
|
index 91a3aae..c49e5a9 100644
|
||
|
--- a/libfprint/fp-device.c
|
||
|
+++ b/libfprint/fp-device.c
|
||
|
@@ -21,17 +21,7 @@
|
||
|
#define FP_COMPONENT "device"
|
||
|
#include "fpi-log.h"
|
||
|
|
||
|
-#include "fpi-device.h"
|
||
|
-
|
||
|
-/**
|
||
|
- * SECTION: fp-device
|
||
|
- * @title: FpDevice
|
||
|
- * @short_description: Fingerprint device handling
|
||
|
- *
|
||
|
- * The #FpDevice object allows you to interact with fingerprint readers.
|
||
|
- * Befor doing any other operation you need to fp_device_open() the device
|
||
|
- * and after you are done you need to fp_device_close() it again.
|
||
|
- */
|
||
|
+#include "fp-device-private.h"
|
||
|
|
||
|
/**
|
||
|
* SECTION: fpi-device
|
||
|
@@ -46,36 +36,6 @@
|
||
|
* Also see the public #FpDevice routines.
|
||
|
*/
|
||
|
|
||
|
-typedef struct
|
||
|
-{
|
||
|
- FpDeviceType type;
|
||
|
-
|
||
|
- GUsbDevice *usb_device;
|
||
|
- const gchar *virtual_env;
|
||
|
-
|
||
|
- gboolean is_open;
|
||
|
-
|
||
|
- gchar *device_id;
|
||
|
- gchar *device_name;
|
||
|
- FpScanType scan_type;
|
||
|
-
|
||
|
- guint64 driver_data;
|
||
|
-
|
||
|
- gint nr_enroll_stages;
|
||
|
- GSList *sources;
|
||
|
-
|
||
|
- /* We always make sure that only one task is run at a time. */
|
||
|
- FpDeviceAction current_action;
|
||
|
- GTask *current_task;
|
||
|
- GAsyncReadyCallback current_user_cb;
|
||
|
- gulong current_cancellable_id;
|
||
|
- GSource *current_idle_cancel_source;
|
||
|
- GSource *current_task_idle_return_source;
|
||
|
-
|
||
|
- /* State for tasks */
|
||
|
- gboolean wait_for_finger;
|
||
|
-} FpDevicePrivate;
|
||
|
-
|
||
|
static void fp_device_async_initable_iface_init (GAsyncInitableIface *iface);
|
||
|
|
||
|
G_DEFINE_TYPE_EXTENDED (FpDevice, fp_device, G_TYPE_OBJECT, G_TYPE_FLAG_ABSTRACT,
|
||
|
@@ -99,27 +59,6 @@ enum {
|
||
|
|
||
|
static GParamSpec *properties[N_PROPS];
|
||
|
|
||
|
-typedef struct
|
||
|
-{
|
||
|
- FpPrint *print;
|
||
|
-
|
||
|
- FpEnrollProgress enroll_progress_cb;
|
||
|
- gpointer enroll_progress_data;
|
||
|
- GDestroyNotify enroll_progress_destroy;
|
||
|
-} FpEnrollData;
|
||
|
-
|
||
|
-static void
|
||
|
-enroll_data_free (gpointer free_data)
|
||
|
-{
|
||
|
- FpEnrollData *data = free_data;
|
||
|
-
|
||
|
- if (data->enroll_progress_destroy)
|
||
|
- data->enroll_progress_destroy (data->enroll_progress_data);
|
||
|
- data->enroll_progress_data = NULL;
|
||
|
- g_clear_object (&data->print);
|
||
|
- g_free (data);
|
||
|
-}
|
||
|
-
|
||
|
/**
|
||
|
* fp_device_retry_quark:
|
||
|
*
|
||
|
@@ -134,150 +73,6 @@ G_DEFINE_QUARK (fp - device - retry - quark, fp_device_retry)
|
||
|
**/
|
||
|
G_DEFINE_QUARK (fp - device - error - quark, fp_device_error)
|
||
|
|
||
|
-/**
|
||
|
- * fpi_device_retry_new:
|
||
|
- * @error: The #FpDeviceRetry error value describing the issue
|
||
|
- *
|
||
|
- * Create a new retry error code for use with fpi_device_verify_complete()
|
||
|
- * and similar calls.
|
||
|
- */
|
||
|
-GError *
|
||
|
-fpi_device_retry_new (FpDeviceRetry error)
|
||
|
-{
|
||
|
- const gchar *msg;
|
||
|
-
|
||
|
- switch (error)
|
||
|
- {
|
||
|
- case FP_DEVICE_RETRY_GENERAL:
|
||
|
- msg = "Please try again.";
|
||
|
- break;
|
||
|
-
|
||
|
- case FP_DEVICE_RETRY_TOO_SHORT:
|
||
|
- msg = "The swipe was too short, please try again.";
|
||
|
- break;
|
||
|
-
|
||
|
- case FP_DEVICE_RETRY_CENTER_FINGER:
|
||
|
- msg = "The finger was not centered properly, please try again.";
|
||
|
- break;
|
||
|
-
|
||
|
- case FP_DEVICE_RETRY_REMOVE_FINGER:
|
||
|
- msg = "Please try again after removing the finger first.";
|
||
|
- break;
|
||
|
-
|
||
|
- default:
|
||
|
- g_warning ("Unsupported error, returning general error instead!");
|
||
|
- error = FP_DEVICE_RETRY_GENERAL;
|
||
|
- msg = "Please try again.";
|
||
|
- }
|
||
|
-
|
||
|
- return g_error_new_literal (FP_DEVICE_RETRY, error, msg);
|
||
|
-}
|
||
|
-
|
||
|
-/**
|
||
|
- * fpi_device_error_new:
|
||
|
- * @error: The #FpDeviceRetry error value describing the issue
|
||
|
- *
|
||
|
- * Create a new error code for use with fpi_device_verify_complete() and
|
||
|
- * similar calls.
|
||
|
- */
|
||
|
-GError *
|
||
|
-fpi_device_error_new (FpDeviceError error)
|
||
|
-{
|
||
|
- const gchar *msg;
|
||
|
-
|
||
|
- switch (error)
|
||
|
- {
|
||
|
- case FP_DEVICE_ERROR_GENERAL:
|
||
|
- msg = "An unspecified error occured!";
|
||
|
- break;
|
||
|
-
|
||
|
- case FP_DEVICE_ERROR_NOT_SUPPORTED:
|
||
|
- msg = "The operation is not supported on this device!";
|
||
|
- break;
|
||
|
-
|
||
|
- case FP_DEVICE_ERROR_NOT_OPEN:
|
||
|
- msg = "The device needs to be opened first!";
|
||
|
- break;
|
||
|
-
|
||
|
- case FP_DEVICE_ERROR_ALREADY_OPEN:
|
||
|
- msg = "The device has already been opened!";
|
||
|
- break;
|
||
|
-
|
||
|
- case FP_DEVICE_ERROR_BUSY:
|
||
|
- msg = "The device is still busy with another operation, please try again later.";
|
||
|
- break;
|
||
|
-
|
||
|
- case FP_DEVICE_ERROR_PROTO:
|
||
|
- msg = "The driver encountered a protocol error with the device.";
|
||
|
- break;
|
||
|
-
|
||
|
- case FP_DEVICE_ERROR_DATA_INVALID:
|
||
|
- msg = "Passed (print) data is not valid.";
|
||
|
- break;
|
||
|
-
|
||
|
- case FP_DEVICE_ERROR_DATA_FULL:
|
||
|
- msg = "On device storage space is full.";
|
||
|
- break;
|
||
|
-
|
||
|
- case FP_DEVICE_ERROR_DATA_NOT_FOUND:
|
||
|
- msg = "Print was not found on the devices storage.";
|
||
|
- break;
|
||
|
-
|
||
|
- default:
|
||
|
- g_warning ("Unsupported error, returning general error instead!");
|
||
|
- error = FP_DEVICE_ERROR_GENERAL;
|
||
|
- msg = "An unspecified error occured!";
|
||
|
- }
|
||
|
-
|
||
|
- return g_error_new_literal (FP_DEVICE_ERROR, error, msg);
|
||
|
-}
|
||
|
-
|
||
|
-/**
|
||
|
- * fpi_device_retry_new_msg:
|
||
|
- * @error: The #FpDeviceRetry error value describing the issue
|
||
|
- * @msg: Custom message to use
|
||
|
- *
|
||
|
- * Create a new retry error code for use with fpi_device_verify_complete()
|
||
|
- * and similar calls.
|
||
|
- */
|
||
|
-GError *
|
||
|
-fpi_device_retry_new_msg (FpDeviceRetry device_error,
|
||
|
- const gchar *msg,
|
||
|
- ...)
|
||
|
-{
|
||
|
- GError *error;
|
||
|
- va_list args;
|
||
|
-
|
||
|
- va_start (args, msg);
|
||
|
- error = g_error_new_valist (FP_DEVICE_RETRY, device_error, msg, args);
|
||
|
- va_end (args);
|
||
|
-
|
||
|
- return error;
|
||
|
-}
|
||
|
-
|
||
|
-/**
|
||
|
- * fpi_device_error_new_msg:
|
||
|
- * @error: The #FpDeviceRetry error value describing the issue
|
||
|
- * @msg: Custom message to use
|
||
|
- *
|
||
|
- * Create a new error code for use with fpi_device_verify_complete()
|
||
|
- * and similar calls.
|
||
|
- */
|
||
|
-GError *
|
||
|
-fpi_device_error_new_msg (FpDeviceError device_error,
|
||
|
- const gchar *msg,
|
||
|
- ...)
|
||
|
-{
|
||
|
- GError *error;
|
||
|
- va_list args;
|
||
|
-
|
||
|
- va_start (args, msg);
|
||
|
- error = g_error_new_valist (FP_DEVICE_ERROR, device_error, msg, args);
|
||
|
- va_end (args);
|
||
|
-
|
||
|
- return error;
|
||
|
-}
|
||
|
-
|
||
|
static gboolean
|
||
|
fp_device_cancel_in_idle_cb (gpointer user_data)
|
||
|
{
|
||
|
@@ -330,21 +125,6 @@ maybe_cancel_on_cancelled (FpDevice *device,
|
||
|
NULL);
|
||
|
}
|
||
|
|
||
|
-static void
|
||
|
-clear_device_cancel_action (FpDevice *device)
|
||
|
-{
|
||
|
- FpDevicePrivate *priv = fp_device_get_instance_private (device);
|
||
|
-
|
||
|
- g_clear_pointer (&priv->current_idle_cancel_source, g_source_destroy);
|
||
|
-
|
||
|
- if (priv->current_cancellable_id)
|
||
|
- {
|
||
|
- g_cancellable_disconnect (g_task_get_cancellable (priv->current_task),
|
||
|
- priv->current_cancellable_id);
|
||
|
- priv->current_cancellable_id = 0;
|
||
|
- }
|
||
|
-}
|
||
|
-
|
||
|
static void
|
||
|
fp_device_constructed (GObject *object)
|
||
|
{
|
||
|
@@ -976,7 +756,7 @@ fp_device_enroll (FpDevice *device,
|
||
|
data->enroll_progress_data = progress_data;
|
||
|
|
||
|
// Attach the progress data as task data so that it is destroyed
|
||
|
- g_task_set_task_data (priv->current_task, data, enroll_data_free);
|
||
|
+ g_task_set_task_data (priv->current_task, data, (GDestroyNotify) enroll_data_free);
|
||
|
|
||
|
FP_DEVICE_GET_CLASS (device)->enroll (device);
|
||
|
}
|
||
|
@@ -1406,968 +1186,6 @@ fp_device_list_prints_finish (FpDevice *device,
|
||
|
return g_task_propagate_pointer (G_TASK (result), error);
|
||
|
}
|
||
|
|
||
|
-typedef struct
|
||
|
-{
|
||
|
- GSource source;
|
||
|
- FpDevice *device;
|
||
|
-} FpDeviceTimeoutSource;
|
||
|
-
|
||
|
-static void
|
||
|
-timeout_finalize (GSource *source)
|
||
|
-{
|
||
|
- FpDeviceTimeoutSource *timeout_source = (FpDeviceTimeoutSource *) source;
|
||
|
- FpDevicePrivate *priv;
|
||
|
-
|
||
|
- priv = fp_device_get_instance_private (timeout_source->device);
|
||
|
- priv->sources = g_slist_remove (priv->sources, source);
|
||
|
-}
|
||
|
-
|
||
|
-static gboolean
|
||
|
-timeout_dispatch (GSource *source, GSourceFunc gsource_func, gpointer user_data)
|
||
|
-{
|
||
|
- FpDeviceTimeoutSource *timeout_source = (FpDeviceTimeoutSource *) source;
|
||
|
- FpTimeoutFunc callback = (FpTimeoutFunc) gsource_func;
|
||
|
-
|
||
|
- callback (timeout_source->device, user_data);
|
||
|
-
|
||
|
- return G_SOURCE_REMOVE;
|
||
|
-}
|
||
|
-
|
||
|
-static GSourceFuncs timeout_funcs = {
|
||
|
- NULL, /* prepare */
|
||
|
- NULL, /* check */
|
||
|
- timeout_dispatch,
|
||
|
- timeout_finalize,
|
||
|
- NULL, NULL
|
||
|
-};
|
||
|
-
|
||
|
-/* Private API functions */
|
||
|
-
|
||
|
-/**
|
||
|
- * fpi_device_set_nr_enroll_stages:
|
||
|
- * @device: The #FpDevice
|
||
|
- * @enroll_stages: The number of enroll stages
|
||
|
- *
|
||
|
- * Updates the reported number of enroll stages that the device needs.
|
||
|
- * If all supported devices have the same number of stages, then the
|
||
|
- * value can simply be set in the class.
|
||
|
- */
|
||
|
-void
|
||
|
-fpi_device_set_nr_enroll_stages (FpDevice *device,
|
||
|
- gint enroll_stages)
|
||
|
-{
|
||
|
- FpDevicePrivate *priv = fp_device_get_instance_private (device);
|
||
|
-
|
||
|
- g_return_if_fail (FP_IS_DEVICE (device));
|
||
|
-
|
||
|
- priv->nr_enroll_stages = enroll_stages;
|
||
|
- g_object_notify_by_pspec (G_OBJECT (device), properties[PROP_NR_ENROLL_STAGES]);
|
||
|
-}
|
||
|
-
|
||
|
-/**
|
||
|
- * fpi_device_set_scan_type:
|
||
|
- * @device: The #FpDevice
|
||
|
- * @scan_type: The scan type of the device
|
||
|
- *
|
||
|
- * Updates the the scan type of the device from the default.
|
||
|
- * If all supported devices have the same scan type, then the
|
||
|
- * value can simply be set in the class.
|
||
|
- */
|
||
|
-void
|
||
|
-fpi_device_set_scan_type (FpDevice *device,
|
||
|
- FpScanType scan_type)
|
||
|
-{
|
||
|
- FpDevicePrivate *priv = fp_device_get_instance_private (device);
|
||
|
-
|
||
|
- g_return_if_fail (FP_IS_DEVICE (device));
|
||
|
-
|
||
|
- priv->scan_type = scan_type;
|
||
|
- g_object_notify_by_pspec (G_OBJECT (device), properties[PROP_SCAN_TYPE]);
|
||
|
-}
|
||
|
-
|
||
|
-/**
|
||
|
- * fpi_device_add_timeout:
|
||
|
- * @device: The #FpDevice
|
||
|
- * @interval: The interval in milliseconds
|
||
|
- * @func: The #FpTimeoutFunc to call on timeout
|
||
|
- * @user_data: (nullable): User data to pass to the callback
|
||
|
- * @destroy_notify: (nullable): #GDestroyNotify for @user_data
|
||
|
- *
|
||
|
- * Register a timeout to run. Drivers should always make sure that timers are
|
||
|
- * cancelled when appropriate.
|
||
|
- *
|
||
|
- * Returns: (transfer none): A newly created and attached #GSource
|
||
|
- */
|
||
|
-GSource *
|
||
|
-fpi_device_add_timeout (FpDevice *device,
|
||
|
- gint interval,
|
||
|
- FpTimeoutFunc func,
|
||
|
- gpointer user_data,
|
||
|
- GDestroyNotify destroy_notify)
|
||
|
-{
|
||
|
- FpDevicePrivate *priv = fp_device_get_instance_private (device);
|
||
|
- FpDeviceTimeoutSource *source;
|
||
|
-
|
||
|
- source = (FpDeviceTimeoutSource *) g_source_new (&timeout_funcs,
|
||
|
- sizeof (FpDeviceTimeoutSource));
|
||
|
- source->device = device;
|
||
|
-
|
||
|
- g_source_attach (&source->source, NULL);
|
||
|
- g_source_set_callback (&source->source, (GSourceFunc) func, user_data, destroy_notify);
|
||
|
- g_source_set_ready_time (&source->source,
|
||
|
- g_source_get_time (&source->source) + interval * (guint64) 1000);
|
||
|
- priv->sources = g_slist_prepend (priv->sources, source);
|
||
|
- g_source_unref (&source->source);
|
||
|
-
|
||
|
- return &source->source;
|
||
|
-}
|
||
|
-
|
||
|
-/**
|
||
|
- * fpi_device_get_usb_device:
|
||
|
- * @device: The #FpDevice
|
||
|
- *
|
||
|
- * Get the #GUsbDevice for this #FpDevice. Only permissible to call if the
|
||
|
- * #FpDevice is of type %FP_DEVICE_TYPE_USB.
|
||
|
- *
|
||
|
- * Returns: The #GUsbDevice
|
||
|
- */
|
||
|
-GUsbDevice *
|
||
|
-fpi_device_get_usb_device (FpDevice *device)
|
||
|
-{
|
||
|
- FpDevicePrivate *priv = fp_device_get_instance_private (device);
|
||
|
-
|
||
|
- g_return_val_if_fail (FP_IS_DEVICE (device), NULL);
|
||
|
- g_return_val_if_fail (priv->type == FP_DEVICE_TYPE_USB, NULL);
|
||
|
-
|
||
|
- return priv->usb_device;
|
||
|
-}
|
||
|
-
|
||
|
-/**
|
||
|
- * fpi_device_get_virtual_env:
|
||
|
- * @device: The #FpDevice
|
||
|
- *
|
||
|
- * Get the value of the environment variable that caused the virtual #FpDevice to be
|
||
|
- * generated. Only permissible to call if the #FpDevice is of type %FP_DEVICE_TYPE_VIRTUAL.
|
||
|
- *
|
||
|
- * Returns: The value of the environment variable
|
||
|
- */
|
||
|
-const gchar *
|
||
|
-fpi_device_get_virtual_env (FpDevice *device)
|
||
|
-{
|
||
|
- FpDevicePrivate *priv = fp_device_get_instance_private (device);
|
||
|
-
|
||
|
- g_return_val_if_fail (FP_IS_DEVICE (device), NULL);
|
||
|
- g_return_val_if_fail (priv->type == FP_DEVICE_TYPE_VIRTUAL, NULL);
|
||
|
-
|
||
|
- return priv->virtual_env;
|
||
|
-}
|
||
|
-
|
||
|
-/**
|
||
|
- * fpi_device_get_current_action:
|
||
|
- * @device: The #FpDevice
|
||
|
- *
|
||
|
- * Get the currently ongoing action or %FP_DEVICE_ACTION_NONE if there
|
||
|
- * is no operation at this time.
|
||
|
- *
|
||
|
- * This is useful for drivers that might share code paths between different
|
||
|
- * actions (e.g. verify and identify) and want to find out again later which
|
||
|
- * action was started in the beginning.
|
||
|
- *
|
||
|
- * Returns: The ongoing #FpDeviceAction
|
||
|
- */
|
||
|
-FpDeviceAction
|
||
|
-fpi_device_get_current_action (FpDevice *device)
|
||
|
-{
|
||
|
- FpDevicePrivate *priv = fp_device_get_instance_private (device);
|
||
|
-
|
||
|
- g_return_val_if_fail (FP_IS_DEVICE (device), FP_DEVICE_ACTION_NONE);
|
||
|
-
|
||
|
- return priv->current_action;
|
||
|
-}
|
||
|
-
|
||
|
-/**
|
||
|
- * fpi_device_action_is_cancelled:
|
||
|
- * @device: The #FpDevice
|
||
|
- *
|
||
|
- * Checks whether the current action has been cancelled by the user.
|
||
|
- * This is equivalent to first getting the cancellable using
|
||
|
- * fpi_device_get_cancellable() and then checking whether it has been
|
||
|
- * cancelled (if it is non-NULL).
|
||
|
- *
|
||
|
- * Returns: %TRUE if action should be cancelled
|
||
|
- */
|
||
|
-gboolean
|
||
|
-fpi_device_action_is_cancelled (FpDevice *device)
|
||
|
-{
|
||
|
- FpDevicePrivate *priv = fp_device_get_instance_private (device);
|
||
|
- GCancellable *cancellable;
|
||
|
-
|
||
|
- g_return_val_if_fail (FP_IS_DEVICE (device), TRUE);
|
||
|
- g_return_val_if_fail (priv->current_action != FP_DEVICE_ACTION_NONE, TRUE);
|
||
|
-
|
||
|
- cancellable = g_task_get_cancellable (priv->current_task);
|
||
|
-
|
||
|
- return cancellable ? g_cancellable_is_cancelled (cancellable) : FALSE;
|
||
|
-}
|
||
|
-
|
||
|
-/**
|
||
|
- * fpi_device_get_driver_data:
|
||
|
- * @device: The #FpDevice
|
||
|
- *
|
||
|
- * Returns: The driver data from the #FpIdEntry table entry
|
||
|
- */
|
||
|
-guint64
|
||
|
-fpi_device_get_driver_data (FpDevice *device)
|
||
|
-{
|
||
|
- FpDevicePrivate *priv = fp_device_get_instance_private (device);
|
||
|
-
|
||
|
- g_return_val_if_fail (FP_IS_DEVICE (device), 0);
|
||
|
-
|
||
|
- return priv->driver_data;
|
||
|
-}
|
||
|
-
|
||
|
-/**
|
||
|
- * fpi_device_get_enroll_data:
|
||
|
- * @device: The #FpDevice
|
||
|
- * @print: (out) (transfer none): The user provided template print
|
||
|
- *
|
||
|
- * Get data for enrollment.
|
||
|
- */
|
||
|
-void
|
||
|
-fpi_device_get_enroll_data (FpDevice *device,
|
||
|
- FpPrint **print)
|
||
|
-{
|
||
|
- FpDevicePrivate *priv = fp_device_get_instance_private (device);
|
||
|
- FpEnrollData *data;
|
||
|
-
|
||
|
- g_return_if_fail (FP_IS_DEVICE (device));
|
||
|
- g_return_if_fail (priv->current_action == FP_DEVICE_ACTION_ENROLL);
|
||
|
-
|
||
|
- data = g_task_get_task_data (priv->current_task);
|
||
|
- g_assert (data);
|
||
|
-
|
||
|
- if (print)
|
||
|
- *print = data->print;
|
||
|
-}
|
||
|
-
|
||
|
-/**
|
||
|
- * fpi_device_get_capture_data:
|
||
|
- * @device: The #FpDevice
|
||
|
- * @wait_for_finger: (out): Whether to wait for finger or not
|
||
|
- *
|
||
|
- * Get data for capture.
|
||
|
- */
|
||
|
-void
|
||
|
-fpi_device_get_capture_data (FpDevice *device,
|
||
|
- gboolean *wait_for_finger)
|
||
|
-{
|
||
|
- FpDevicePrivate *priv = fp_device_get_instance_private (device);
|
||
|
-
|
||
|
- g_return_if_fail (FP_IS_DEVICE (device));
|
||
|
- g_return_if_fail (priv->current_action == FP_DEVICE_ACTION_CAPTURE);
|
||
|
-
|
||
|
- if (wait_for_finger)
|
||
|
- *wait_for_finger = priv->wait_for_finger;
|
||
|
-}
|
||
|
-
|
||
|
-/**
|
||
|
- * fpi_device_get_verify_data:
|
||
|
- * @device: The #FpDevice
|
||
|
- * @print: (out) (transfer none): The enrolled print
|
||
|
- *
|
||
|
- * Get data for verify.
|
||
|
- */
|
||
|
-void
|
||
|
-fpi_device_get_verify_data (FpDevice *device,
|
||
|
- FpPrint **print)
|
||
|
-{
|
||
|
- FpDevicePrivate *priv = fp_device_get_instance_private (device);
|
||
|
-
|
||
|
- g_return_if_fail (FP_IS_DEVICE (device));
|
||
|
- g_return_if_fail (priv->current_action == FP_DEVICE_ACTION_VERIFY);
|
||
|
-
|
||
|
- if (print)
|
||
|
- *print = g_task_get_task_data (priv->current_task);
|
||
|
-}
|
||
|
-
|
||
|
-/**
|
||
|
- * fpi_device_get_identify_data:
|
||
|
- * @device: The #FpDevice
|
||
|
- * @prints: (out) (transfer none) (element-type FpPrint): The gallery of prints
|
||
|
- *
|
||
|
- * Get data for identify.
|
||
|
- */
|
||
|
-void
|
||
|
-fpi_device_get_identify_data (FpDevice *device,
|
||
|
- GPtrArray **prints)
|
||
|
-{
|
||
|
- FpDevicePrivate *priv = fp_device_get_instance_private (device);
|
||
|
-
|
||
|
- g_return_if_fail (FP_IS_DEVICE (device));
|
||
|
- g_return_if_fail (priv->current_action == FP_DEVICE_ACTION_IDENTIFY);
|
||
|
-
|
||
|
- if (prints)
|
||
|
- *prints = g_task_get_task_data (priv->current_task);
|
||
|
-}
|
||
|
-
|
||
|
-/**
|
||
|
- * fpi_device_get_delete_data:
|
||
|
- * @device: The #FpDevice
|
||
|
- * @print: (out) (transfer none): The print to delete
|
||
|
- *
|
||
|
- * Get data for delete.
|
||
|
- */
|
||
|
-void
|
||
|
-fpi_device_get_delete_data (FpDevice *device,
|
||
|
- FpPrint **print)
|
||
|
-{
|
||
|
- FpDevicePrivate *priv = fp_device_get_instance_private (device);
|
||
|
-
|
||
|
- g_return_if_fail (FP_IS_DEVICE (device));
|
||
|
- g_return_if_fail (priv->current_action == FP_DEVICE_ACTION_DELETE);
|
||
|
-
|
||
|
- if (print)
|
||
|
- *print = g_task_get_task_data (priv->current_task);
|
||
|
-}
|
||
|
-
|
||
|
-/**
|
||
|
- * fpi_device_get_cancellable:
|
||
|
- * @device: The #FpDevice
|
||
|
- *
|
||
|
- * Retrieve the #GCancellable that may cancel the currently ongoing operation. This
|
||
|
- * is primarily useful to pass directly to e.g. fpi_usb_transfer_submit() for cancellable
|
||
|
- * transfers.
|
||
|
- * In many cases the cancel vfunc may be more convenient to react to cancellation in some
|
||
|
- * way.
|
||
|
- *
|
||
|
- * Returns: (transfer none): The #GCancellable for the current action.
|
||
|
- */
|
||
|
-GCancellable *
|
||
|
-fpi_device_get_cancellable (FpDevice *device)
|
||
|
-{
|
||
|
- FpDevicePrivate *priv = fp_device_get_instance_private (device);
|
||
|
-
|
||
|
- g_return_val_if_fail (FP_IS_DEVICE (device), NULL);
|
||
|
- g_return_val_if_fail (priv->current_action != FP_DEVICE_ACTION_NONE, NULL);
|
||
|
-
|
||
|
- return g_task_get_cancellable (priv->current_task);
|
||
|
-}
|
||
|
-
|
||
|
-/**
|
||
|
- * fpi_device_action_error:
|
||
|
- * @device: The #FpDevice
|
||
|
- * @error: The #GError to return
|
||
|
- *
|
||
|
- * Finish an ongoing action with an error. This is the same as calling
|
||
|
- * the corresponding complete function such as fpi_device_open_complete()
|
||
|
- * with an error set. If possible, use the correct complete function as
|
||
|
- * that results in improved error detection.
|
||
|
- */
|
||
|
-void
|
||
|
-fpi_device_action_error (FpDevice *device,
|
||
|
- GError *error)
|
||
|
-{
|
||
|
- FpDevicePrivate *priv = fp_device_get_instance_private (device);
|
||
|
-
|
||
|
- g_return_if_fail (FP_IS_DEVICE (device));
|
||
|
- g_return_if_fail (priv->current_action != FP_DEVICE_ACTION_NONE);
|
||
|
-
|
||
|
- if (error != NULL)
|
||
|
- {
|
||
|
- g_debug ("Device reported generic error during action; action was: %i", priv->current_action);
|
||
|
- }
|
||
|
- else
|
||
|
- {
|
||
|
- g_warning ("Device failed to pass an error to generic action error function");
|
||
|
- error = fpi_device_error_new_msg (FP_DEVICE_ERROR_GENERAL, "Device reported error but did not provide an error condition");
|
||
|
- }
|
||
|
-
|
||
|
-
|
||
|
- switch (priv->current_action)
|
||
|
- {
|
||
|
- case FP_DEVICE_ACTION_PROBE:
|
||
|
- fpi_device_probe_complete (device, NULL, NULL, error);
|
||
|
- break;
|
||
|
-
|
||
|
- case FP_DEVICE_ACTION_OPEN:
|
||
|
- fpi_device_open_complete (device, error);
|
||
|
- break;
|
||
|
-
|
||
|
- case FP_DEVICE_ACTION_CLOSE:
|
||
|
- fpi_device_close_complete (device, error);
|
||
|
- break;
|
||
|
-
|
||
|
- case FP_DEVICE_ACTION_ENROLL:
|
||
|
- fpi_device_enroll_complete (device, NULL, error);
|
||
|
- break;
|
||
|
-
|
||
|
- case FP_DEVICE_ACTION_VERIFY:
|
||
|
- fpi_device_verify_complete (device, FPI_MATCH_ERROR, NULL, error);
|
||
|
- break;
|
||
|
-
|
||
|
- case FP_DEVICE_ACTION_IDENTIFY:
|
||
|
- fpi_device_identify_complete (device, NULL, NULL, error);
|
||
|
- break;
|
||
|
-
|
||
|
- case FP_DEVICE_ACTION_CAPTURE:
|
||
|
- fpi_device_capture_complete (device, NULL, error);
|
||
|
- break;
|
||
|
-
|
||
|
- case FP_DEVICE_ACTION_DELETE:
|
||
|
- fpi_device_delete_complete (device, error);
|
||
|
- break;
|
||
|
-
|
||
|
- case FP_DEVICE_ACTION_LIST:
|
||
|
- fpi_device_list_complete (device, NULL, error);
|
||
|
- break;
|
||
|
-
|
||
|
- default:
|
||
|
- case FP_DEVICE_ACTION_NONE:
|
||
|
- g_return_if_reached ();
|
||
|
- break;
|
||
|
- }
|
||
|
-}
|
||
|
-
|
||
|
-typedef enum _FpDeviceTaskReturnType {
|
||
|
- FP_DEVICE_TASK_RETURN_INT,
|
||
|
- FP_DEVICE_TASK_RETURN_BOOL,
|
||
|
- FP_DEVICE_TASK_RETURN_OBJECT,
|
||
|
- FP_DEVICE_TASK_RETURN_PTR_ARRAY,
|
||
|
- FP_DEVICE_TASK_RETURN_ERROR,
|
||
|
-} FpDeviceTaskReturnType;
|
||
|
-
|
||
|
-typedef struct _FpDeviceTaskReturnData
|
||
|
-{
|
||
|
- FpDevice *device;
|
||
|
- FpDeviceTaskReturnType type;
|
||
|
- gpointer result;
|
||
|
-} FpDeviceTaskReturnData;
|
||
|
-
|
||
|
-static gboolean
|
||
|
-fp_device_task_return_in_idle_cb (gpointer user_data)
|
||
|
-{
|
||
|
- FpDeviceTaskReturnData *data = user_data;
|
||
|
- FpDevicePrivate *priv = fp_device_get_instance_private (data->device);
|
||
|
-
|
||
|
- g_autoptr(GTask) task = NULL;
|
||
|
-
|
||
|
- g_debug ("Completing action %d in idle!", priv->current_action);
|
||
|
-
|
||
|
- task = g_steal_pointer (&priv->current_task);
|
||
|
- priv->current_action = FP_DEVICE_ACTION_NONE;
|
||
|
- priv->current_task_idle_return_source = NULL;
|
||
|
-
|
||
|
- switch (data->type)
|
||
|
- {
|
||
|
- case FP_DEVICE_TASK_RETURN_INT:
|
||
|
- g_task_return_int (task, GPOINTER_TO_INT (data->result));
|
||
|
- break;
|
||
|
-
|
||
|
- case FP_DEVICE_TASK_RETURN_BOOL:
|
||
|
- g_task_return_boolean (task, GPOINTER_TO_UINT (data->result));
|
||
|
- break;
|
||
|
-
|
||
|
- case FP_DEVICE_TASK_RETURN_OBJECT:
|
||
|
- g_task_return_pointer (task, data->result, g_object_unref);
|
||
|
- break;
|
||
|
-
|
||
|
- case FP_DEVICE_TASK_RETURN_PTR_ARRAY:
|
||
|
- g_task_return_pointer (task, data->result,
|
||
|
- (GDestroyNotify) g_ptr_array_unref);
|
||
|
- break;
|
||
|
-
|
||
|
- case FP_DEVICE_TASK_RETURN_ERROR:
|
||
|
- g_task_return_error (task, data->result);
|
||
|
- break;
|
||
|
-
|
||
|
- default:
|
||
|
- g_assert_not_reached ();
|
||
|
- }
|
||
|
-
|
||
|
- return G_SOURCE_REMOVE;
|
||
|
-}
|
||
|
-
|
||
|
-static void
|
||
|
-fp_device_task_return_data_free (FpDeviceTaskReturnData *data)
|
||
|
-{
|
||
|
- g_object_unref (data->device);
|
||
|
- g_free (data);
|
||
|
-}
|
||
|
-
|
||
|
-static void
|
||
|
-fp_device_return_task_in_idle (FpDevice *device,
|
||
|
- FpDeviceTaskReturnType return_type,
|
||
|
- gpointer return_data)
|
||
|
-{
|
||
|
- FpDevicePrivate *priv = fp_device_get_instance_private (device);
|
||
|
- FpDeviceTaskReturnData *data;
|
||
|
-
|
||
|
- data = g_new0 (FpDeviceTaskReturnData, 1);
|
||
|
- data->device = g_object_ref (device);
|
||
|
- data->type = return_type;
|
||
|
- data->result = return_data;
|
||
|
-
|
||
|
- priv->current_task_idle_return_source = g_idle_source_new ();
|
||
|
- g_source_set_priority (priv->current_task_idle_return_source,
|
||
|
- g_task_get_priority (priv->current_task));
|
||
|
- g_source_set_callback (priv->current_task_idle_return_source,
|
||
|
- fp_device_task_return_in_idle_cb,
|
||
|
- data,
|
||
|
- (GDestroyNotify) fp_device_task_return_data_free);
|
||
|
-
|
||
|
- g_source_attach (priv->current_task_idle_return_source, NULL);
|
||
|
- g_source_unref (priv->current_task_idle_return_source);
|
||
|
-}
|
||
|
-
|
||
|
-/**
|
||
|
- * fpi_device_probe_complete:
|
||
|
- * @device: The #FpDevice
|
||
|
- * @device_id: Unique ID for the device or %NULL
|
||
|
- * @device_name: Human readable name or %NULL for driver name
|
||
|
- * @error: The #GError or %NULL on success
|
||
|
- *
|
||
|
- * Finish an ongoing probe operation. If error is %NULL success is assumed.
|
||
|
- */
|
||
|
-void
|
||
|
-fpi_device_probe_complete (FpDevice *device,
|
||
|
- const gchar *device_id,
|
||
|
- const gchar *device_name,
|
||
|
- GError *error)
|
||
|
-{
|
||
|
- FpDevicePrivate *priv = fp_device_get_instance_private (device);
|
||
|
-
|
||
|
- g_return_if_fail (FP_IS_DEVICE (device));
|
||
|
- g_return_if_fail (priv->current_action == FP_DEVICE_ACTION_PROBE);
|
||
|
-
|
||
|
- g_debug ("Device reported probe completion");
|
||
|
-
|
||
|
- clear_device_cancel_action (device);
|
||
|
-
|
||
|
- if (!error)
|
||
|
- {
|
||
|
- if (device_id)
|
||
|
- {
|
||
|
- g_clear_pointer (&priv->device_id, g_free);
|
||
|
- priv->device_id = g_strdup (device_id);
|
||
|
- g_object_notify_by_pspec (G_OBJECT (device), properties[PROP_DEVICE_ID]);
|
||
|
- }
|
||
|
- if (device_name)
|
||
|
- {
|
||
|
- g_clear_pointer (&priv->device_name, g_free);
|
||
|
- priv->device_name = g_strdup (device_name);
|
||
|
- g_object_notify_by_pspec (G_OBJECT (device), properties[PROP_NAME]);
|
||
|
- }
|
||
|
- fp_device_return_task_in_idle (device, FP_DEVICE_TASK_RETURN_BOOL,
|
||
|
- GUINT_TO_POINTER (TRUE));
|
||
|
- }
|
||
|
- else
|
||
|
- {
|
||
|
- fp_device_return_task_in_idle (device, FP_DEVICE_TASK_RETURN_ERROR, error);
|
||
|
- }
|
||
|
-}
|
||
|
-
|
||
|
-/**
|
||
|
- * fpi_device_open_complete:
|
||
|
- * @device: The #FpDevice
|
||
|
- * @error: The #GError or %NULL on success
|
||
|
- *
|
||
|
- * Finish an ongoing open operation. If error is %NULL success is assumed.
|
||
|
- */
|
||
|
-void
|
||
|
-fpi_device_open_complete (FpDevice *device, GError *error)
|
||
|
-{
|
||
|
- FpDevicePrivate *priv = fp_device_get_instance_private (device);
|
||
|
-
|
||
|
- g_return_if_fail (FP_IS_DEVICE (device));
|
||
|
- g_return_if_fail (priv->current_action == FP_DEVICE_ACTION_OPEN);
|
||
|
-
|
||
|
- g_debug ("Device reported open completion");
|
||
|
-
|
||
|
- clear_device_cancel_action (device);
|
||
|
-
|
||
|
- if (!error)
|
||
|
- {
|
||
|
- priv->is_open = TRUE;
|
||
|
- g_object_notify_by_pspec (G_OBJECT (device), properties[PROP_OPEN]);
|
||
|
- }
|
||
|
-
|
||
|
- if (!error)
|
||
|
- fp_device_return_task_in_idle (device, FP_DEVICE_TASK_RETURN_BOOL,
|
||
|
- GUINT_TO_POINTER (TRUE));
|
||
|
- else
|
||
|
- fp_device_return_task_in_idle (device, FP_DEVICE_TASK_RETURN_ERROR, error);
|
||
|
-}
|
||
|
-
|
||
|
-/**
|
||
|
- * fpi_device_close_complete:
|
||
|
- * @device: The #FpDevice
|
||
|
- * @error: The #GError or %NULL on success
|
||
|
- *
|
||
|
- * Finish an ongoing close operation. If error is %NULL success is assumed.
|
||
|
- */
|
||
|
-void
|
||
|
-fpi_device_close_complete (FpDevice *device, GError *error)
|
||
|
-{
|
||
|
- GError *nested_error = NULL;
|
||
|
- FpDevicePrivate *priv = fp_device_get_instance_private (device);
|
||
|
-
|
||
|
- g_return_if_fail (FP_IS_DEVICE (device));
|
||
|
- g_return_if_fail (priv->current_action == FP_DEVICE_ACTION_CLOSE);
|
||
|
-
|
||
|
- g_debug ("Device reported close completion");
|
||
|
-
|
||
|
- clear_device_cancel_action (device);
|
||
|
- priv->is_open = FALSE;
|
||
|
- g_object_notify_by_pspec (G_OBJECT (device), properties[PROP_OPEN]);
|
||
|
-
|
||
|
- switch (priv->type)
|
||
|
- {
|
||
|
- case FP_DEVICE_TYPE_USB:
|
||
|
- if (!g_usb_device_close (priv->usb_device, &nested_error))
|
||
|
- {
|
||
|
- if (error == NULL)
|
||
|
- error = nested_error;
|
||
|
- fp_device_return_task_in_idle (device, FP_DEVICE_TASK_RETURN_ERROR, error);
|
||
|
- return;
|
||
|
- }
|
||
|
- break;
|
||
|
-
|
||
|
- case FP_DEVICE_TYPE_VIRTUAL:
|
||
|
- break;
|
||
|
-
|
||
|
- default:
|
||
|
- g_assert_not_reached ();
|
||
|
- fp_device_return_task_in_idle (device, FP_DEVICE_TASK_RETURN_ERROR,
|
||
|
- fpi_device_error_new (FP_DEVICE_ERROR_GENERAL));
|
||
|
- return;
|
||
|
- }
|
||
|
-
|
||
|
- if (!error)
|
||
|
- fp_device_return_task_in_idle (device, FP_DEVICE_TASK_RETURN_BOOL,
|
||
|
- GUINT_TO_POINTER (TRUE));
|
||
|
- else
|
||
|
- fp_device_return_task_in_idle (device, FP_DEVICE_TASK_RETURN_ERROR, error);
|
||
|
-}
|
||
|
-
|
||
|
-/**
|
||
|
- * fpi_device_enroll_complete:
|
||
|
- * @device: The #FpDevice
|
||
|
- * @print: (nullable) (transfer full): The #FpPrint or %NULL on failure
|
||
|
- * @error: The #GError or %NULL on success
|
||
|
- *
|
||
|
- * Finish an ongoing enroll operation. The #FpPrint can be stored by the
|
||
|
- * caller for later verification.
|
||
|
- */
|
||
|
-void
|
||
|
-fpi_device_enroll_complete (FpDevice *device, FpPrint *print, GError *error)
|
||
|
-{
|
||
|
- FpDevicePrivate *priv = fp_device_get_instance_private (device);
|
||
|
-
|
||
|
- g_return_if_fail (FP_IS_DEVICE (device));
|
||
|
- g_return_if_fail (priv->current_action == FP_DEVICE_ACTION_ENROLL);
|
||
|
-
|
||
|
- g_debug ("Device reported enroll completion");
|
||
|
-
|
||
|
- clear_device_cancel_action (device);
|
||
|
-
|
||
|
- if (!error)
|
||
|
- {
|
||
|
- if (FP_IS_PRINT (print))
|
||
|
- {
|
||
|
- fp_device_return_task_in_idle (device, FP_DEVICE_TASK_RETURN_OBJECT, print);
|
||
|
- }
|
||
|
- else
|
||
|
- {
|
||
|
- g_warning ("Driver did not provide a valid print and failed to provide an error!");
|
||
|
- error = fpi_device_error_new_msg (FP_DEVICE_ERROR_GENERAL,
|
||
|
- "Driver failed to provide print data!");
|
||
|
- fp_device_return_task_in_idle (device, FP_DEVICE_TASK_RETURN_ERROR, error);
|
||
|
- }
|
||
|
- }
|
||
|
- else
|
||
|
- {
|
||
|
- fp_device_return_task_in_idle (device, FP_DEVICE_TASK_RETURN_ERROR, error);
|
||
|
- if (FP_IS_PRINT (print))
|
||
|
- {
|
||
|
- g_warning ("Driver passed an error but also provided a print, returning error!");
|
||
|
- g_object_unref (print);
|
||
|
- }
|
||
|
- }
|
||
|
-}
|
||
|
-
|
||
|
-/**
|
||
|
- * fpi_device_verify_complete:
|
||
|
- * @device: The #FpDevice
|
||
|
- * @result: The #FpiMatchResult of the operation
|
||
|
- * @print: The scanned #FpPrint
|
||
|
- * @error: A #GError if result is %FPI_MATCH_ERROR
|
||
|
- *
|
||
|
- * Finish an ongoing verify operation. The returned print should be
|
||
|
- * representing the new scan and not the one passed for verification.
|
||
|
- */
|
||
|
-void
|
||
|
-fpi_device_verify_complete (FpDevice *device,
|
||
|
- FpiMatchResult result,
|
||
|
- FpPrint *print,
|
||
|
- GError *error)
|
||
|
-{
|
||
|
- FpDevicePrivate *priv = fp_device_get_instance_private (device);
|
||
|
-
|
||
|
- g_return_if_fail (FP_IS_DEVICE (device));
|
||
|
- g_return_if_fail (priv->current_action == FP_DEVICE_ACTION_VERIFY);
|
||
|
-
|
||
|
- g_debug ("Device reported verify completion");
|
||
|
-
|
||
|
- clear_device_cancel_action (device);
|
||
|
-
|
||
|
- g_object_set_data_full (G_OBJECT (priv->current_task),
|
||
|
- "print",
|
||
|
- print,
|
||
|
- g_object_unref);
|
||
|
-
|
||
|
- if (!error)
|
||
|
- {
|
||
|
- if (result != FPI_MATCH_ERROR)
|
||
|
- {
|
||
|
- fp_device_return_task_in_idle (device, FP_DEVICE_TASK_RETURN_INT,
|
||
|
- GINT_TO_POINTER (result));
|
||
|
- }
|
||
|
- else
|
||
|
- {
|
||
|
- g_warning ("Driver did not provide an error for a failed verify operation!");
|
||
|
- error = fpi_device_error_new_msg (FP_DEVICE_ERROR_GENERAL,
|
||
|
- "Driver failed to provide an error!");
|
||
|
- fp_device_return_task_in_idle (device, FP_DEVICE_TASK_RETURN_ERROR, error);
|
||
|
- }
|
||
|
- }
|
||
|
- else
|
||
|
- {
|
||
|
- fp_device_return_task_in_idle (device, FP_DEVICE_TASK_RETURN_ERROR, error);
|
||
|
- if (result != FPI_MATCH_ERROR)
|
||
|
- {
|
||
|
- g_warning ("Driver passed an error but also provided a match result, returning error!");
|
||
|
- g_object_unref (print);
|
||
|
- }
|
||
|
- }
|
||
|
-}
|
||
|
-
|
||
|
-/**
|
||
|
- * fpi_device_identify_complete:
|
||
|
- * @device: The #FpDevice
|
||
|
- * @match: The matching #FpPrint from the passed gallery, or %NULL if none matched
|
||
|
- * @print: The scanned #FpPrint, may be %NULL
|
||
|
- * @error: The #GError or %NULL on success
|
||
|
- *
|
||
|
- * Finish an ongoing identify operation. The match that was identified is
|
||
|
- * returned in @match. The @print parameter returns the newly created scan
|
||
|
- * that was used for matching.
|
||
|
- */
|
||
|
-void
|
||
|
-fpi_device_identify_complete (FpDevice *device,
|
||
|
- FpPrint *match,
|
||
|
- FpPrint *print,
|
||
|
- GError *error)
|
||
|
-{
|
||
|
- FpDevicePrivate *priv = fp_device_get_instance_private (device);
|
||
|
-
|
||
|
- g_return_if_fail (FP_IS_DEVICE (device));
|
||
|
- g_return_if_fail (priv->current_action == FP_DEVICE_ACTION_IDENTIFY);
|
||
|
-
|
||
|
- g_debug ("Device reported identify completion");
|
||
|
-
|
||
|
- clear_device_cancel_action (device);
|
||
|
-
|
||
|
- g_object_set_data_full (G_OBJECT (priv->current_task),
|
||
|
- "print",
|
||
|
- print,
|
||
|
- g_object_unref);
|
||
|
- g_object_set_data_full (G_OBJECT (priv->current_task),
|
||
|
- "match",
|
||
|
- match,
|
||
|
- g_object_unref);
|
||
|
- if (!error)
|
||
|
- {
|
||
|
- fp_device_return_task_in_idle (device, FP_DEVICE_TASK_RETURN_BOOL,
|
||
|
- GUINT_TO_POINTER (TRUE));
|
||
|
- }
|
||
|
- else
|
||
|
- {
|
||
|
- fp_device_return_task_in_idle (device, FP_DEVICE_TASK_RETURN_ERROR, error);
|
||
|
- if (match)
|
||
|
- {
|
||
|
- g_warning ("Driver passed an error but also provided a match result, returning error!");
|
||
|
- g_clear_object (&match);
|
||
|
- }
|
||
|
- }
|
||
|
-}
|
||
|
-
|
||
|
-
|
||
|
-/**
|
||
|
- * fpi_device_capture_complete:
|
||
|
- * @device: The #FpDevice
|
||
|
- * @image: The #FpImage, or %NULL on error
|
||
|
- * @error: The #GError or %NULL on success
|
||
|
- *
|
||
|
- * Finish an ongoing capture operation.
|
||
|
- */
|
||
|
-void
|
||
|
-fpi_device_capture_complete (FpDevice *device,
|
||
|
- FpImage *image,
|
||
|
- GError *error)
|
||
|
-{
|
||
|
- FpDevicePrivate *priv = fp_device_get_instance_private (device);
|
||
|
-
|
||
|
- g_return_if_fail (FP_IS_DEVICE (device));
|
||
|
- g_return_if_fail (priv->current_action == FP_DEVICE_ACTION_CAPTURE);
|
||
|
-
|
||
|
- g_debug ("Device reported capture completion");
|
||
|
-
|
||
|
- clear_device_cancel_action (device);
|
||
|
-
|
||
|
- if (!error)
|
||
|
- {
|
||
|
- if (image)
|
||
|
- {
|
||
|
- fp_device_return_task_in_idle (device, FP_DEVICE_TASK_RETURN_OBJECT, image);
|
||
|
- }
|
||
|
- else
|
||
|
- {
|
||
|
- g_warning ("Driver did not provide an error for a failed capture operation!");
|
||
|
- error = fpi_device_error_new_msg (FP_DEVICE_ERROR_GENERAL,
|
||
|
- "Driver failed to provide an error!");
|
||
|
- fp_device_return_task_in_idle (device, FP_DEVICE_TASK_RETURN_ERROR, error);
|
||
|
- }
|
||
|
- }
|
||
|
- else
|
||
|
- {
|
||
|
- fp_device_return_task_in_idle (device, FP_DEVICE_TASK_RETURN_ERROR, error);
|
||
|
- if (image)
|
||
|
- {
|
||
|
- g_warning ("Driver passed an error but also provided an image, returning error!");
|
||
|
- g_clear_object (&image);
|
||
|
- }
|
||
|
- }
|
||
|
-}
|
||
|
-
|
||
|
-/**
|
||
|
- * fpi_device_delete_complete:
|
||
|
- * @device: The #FpDevice
|
||
|
- * @error: The #GError or %NULL on success
|
||
|
- *
|
||
|
- * Finish an ongoing delete operation.
|
||
|
- */
|
||
|
-void
|
||
|
-fpi_device_delete_complete (FpDevice *device,
|
||
|
- GError *error)
|
||
|
-{
|
||
|
- FpDevicePrivate *priv = fp_device_get_instance_private (device);
|
||
|
-
|
||
|
- g_return_if_fail (FP_IS_DEVICE (device));
|
||
|
- g_return_if_fail (priv->current_action == FP_DEVICE_ACTION_DELETE);
|
||
|
-
|
||
|
- g_debug ("Device reported deletion completion");
|
||
|
-
|
||
|
- clear_device_cancel_action (device);
|
||
|
-
|
||
|
- if (!error)
|
||
|
- fp_device_return_task_in_idle (device, FP_DEVICE_TASK_RETURN_BOOL,
|
||
|
- GUINT_TO_POINTER (TRUE));
|
||
|
- else
|
||
|
- fp_device_return_task_in_idle (device, FP_DEVICE_TASK_RETURN_ERROR, error);
|
||
|
-}
|
||
|
-
|
||
|
-/**
|
||
|
- * fpi_device_list_complete:
|
||
|
- * @device: The #FpDevice
|
||
|
- * @prints: (element-type FpPrint) (transfer container): Possibly empty array of prints or %NULL on error
|
||
|
- * @error: The #GError or %NULL on success
|
||
|
- *
|
||
|
- * Finish an ongoing list operation.
|
||
|
- *
|
||
|
- * Please note that the @prints array will be free'ed using
|
||
|
- * g_ptr_array_unref() and the elements are destroyed automatically.
|
||
|
- * As such, you must use g_ptr_array_new_with_free_func() with
|
||
|
- * g_object_unref() as free func to create the array.
|
||
|
- */
|
||
|
-void
|
||
|
-fpi_device_list_complete (FpDevice *device,
|
||
|
- GPtrArray *prints,
|
||
|
- GError *error)
|
||
|
-{
|
||
|
- FpDevicePrivate *priv = fp_device_get_instance_private (device);
|
||
|
-
|
||
|
- g_return_if_fail (FP_IS_DEVICE (device));
|
||
|
- g_return_if_fail (priv->current_action == FP_DEVICE_ACTION_LIST);
|
||
|
-
|
||
|
- g_debug ("Device reported listing completion");
|
||
|
-
|
||
|
- clear_device_cancel_action (device);
|
||
|
-
|
||
|
- if (prints && error)
|
||
|
- {
|
||
|
- g_warning ("Driver reported back prints and error, ignoring prints");
|
||
|
- g_clear_pointer (&prints, g_ptr_array_unref);
|
||
|
- }
|
||
|
- else if (!prints && !error)
|
||
|
- {
|
||
|
- g_warning ("Driver did not pass array but failed to provide an error");
|
||
|
- error = fpi_device_error_new_msg (FP_DEVICE_ERROR_GENERAL,
|
||
|
- "Driver failed to provide a list of prints");
|
||
|
- }
|
||
|
-
|
||
|
- if (!error)
|
||
|
- fp_device_return_task_in_idle (device, FP_DEVICE_TASK_RETURN_PTR_ARRAY, prints);
|
||
|
- else
|
||
|
- fp_device_return_task_in_idle (device, FP_DEVICE_TASK_RETURN_ERROR, error);
|
||
|
-}
|
||
|
-
|
||
|
-/**
|
||
|
- * fpi_device_enroll_progress:
|
||
|
- * @device: The #FpDevice
|
||
|
- * @completed_stages: The number of stages that are completed at this point
|
||
|
- * @print: The #FpPrint for the newly completed stage or %NULL on failure
|
||
|
- * @error: The #GError or %NULL on success
|
||
|
- *
|
||
|
- * Notify about the progress of the enroll operation. This is important for UI interaction.
|
||
|
- * The passed error may be used if a scan needs to be retried, use fpi_device_retry_new().
|
||
|
- */
|
||
|
-void
|
||
|
-fpi_device_enroll_progress (FpDevice *device,
|
||
|
- gint completed_stages,
|
||
|
- FpPrint *print,
|
||
|
- GError *error)
|
||
|
-{
|
||
|
- FpDevicePrivate *priv = fp_device_get_instance_private (device);
|
||
|
- FpEnrollData *data;
|
||
|
-
|
||
|
- g_return_if_fail (FP_IS_DEVICE (device));
|
||
|
- g_return_if_fail (priv->current_action == FP_DEVICE_ACTION_ENROLL);
|
||
|
- g_return_if_fail (error == NULL || error->domain == FP_DEVICE_RETRY);
|
||
|
-
|
||
|
- g_debug ("Device reported enroll progress, reported %i of %i have been completed", completed_stages, priv->nr_enroll_stages);
|
||
|
-
|
||
|
- if (error && print)
|
||
|
- {
|
||
|
- g_warning ("Driver passed an error and also provided a print, returning error!");
|
||
|
- g_clear_object (&print);
|
||
|
- }
|
||
|
-
|
||
|
- data = g_task_get_task_data (priv->current_task);
|
||
|
-
|
||
|
- if (data->enroll_progress_cb)
|
||
|
- {
|
||
|
- data->enroll_progress_cb (device,
|
||
|
- completed_stages,
|
||
|
- print,
|
||
|
- data->enroll_progress_data,
|
||
|
- error);
|
||
|
- }
|
||
|
-
|
||
|
- g_clear_error (&error);
|
||
|
- g_clear_object (&print);
|
||
|
-}
|
||
|
-
|
||
|
-
|
||
|
static void
|
||
|
async_result_ready (GObject *source_object, GAsyncResult *res, gpointer user_data)
|
||
|
{
|
||
|
diff --git a/libfprint/fpi-device.c b/libfprint/fpi-device.c
|
||
|
new file mode 100644
|
||
|
index 0000000..3eee062
|
||
|
--- /dev/null
|
||
|
+++ b/libfprint/fpi-device.c
|
||
|
@@ -0,0 +1,1177 @@
|
||
|
+/*
|
||
|
+ * FpDevice - A fingerprint reader device - Private APIs
|
||
|
+ * Copyright (C) 2019 Benjamin Berg <bberg@redhat.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
|
||
|
+ * 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 "device"
|
||
|
+#include "fpi-log.h"
|
||
|
+
|
||
|
+#include "fp-device-private.h"
|
||
|
+
|
||
|
+/**
|
||
|
+ * SECTION: fpi-device
|
||
|
+ * @title: Internal FpDevice
|
||
|
+ * @short_description: Internal device routines
|
||
|
+ *
|
||
|
+ * The methods that are availabe for drivers to manipulate a device. See
|
||
|
+ * #FpDeviceClass for more information. Also note that most of these are
|
||
|
+ * not relevant for image based devices, see #FpImageDeviceClass in that
|
||
|
+ * case.
|
||
|
+ *
|
||
|
+ * Also see the public #FpDevice routines.
|
||
|
+ */
|
||
|
+
|
||
|
+/* Manually redefine what G_DEFINE_* macro does */
|
||
|
+static inline gpointer
|
||
|
+fp_device_get_instance_private (FpDevice *self)
|
||
|
+{
|
||
|
+ FpDeviceClass *dev_class = g_type_class_peek_static (FP_TYPE_DEVICE);
|
||
|
+
|
||
|
+ return G_STRUCT_MEMBER_P (self,
|
||
|
+ g_type_class_get_instance_private_offset (dev_class));
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * fpi_device_retry_new:
|
||
|
+ * @error: The #FpDeviceRetry error value describing the issue
|
||
|
+ *
|
||
|
+ * Create a new retry error code for use with fpi_device_verify_complete()
|
||
|
+ * and similar calls.
|
||
|
+ */
|
||
|
+GError *
|
||
|
+fpi_device_retry_new (FpDeviceRetry error)
|
||
|
+{
|
||
|
+ const gchar *msg;
|
||
|
+
|
||
|
+ switch (error)
|
||
|
+ {
|
||
|
+ case FP_DEVICE_RETRY_GENERAL:
|
||
|
+ msg = "Please try again.";
|
||
|
+ break;
|
||
|
+
|
||
|
+ case FP_DEVICE_RETRY_TOO_SHORT:
|
||
|
+ msg = "The swipe was too short, please try again.";
|
||
|
+ break;
|
||
|
+
|
||
|
+ case FP_DEVICE_RETRY_CENTER_FINGER:
|
||
|
+ msg = "The finger was not centered properly, please try again.";
|
||
|
+ break;
|
||
|
+
|
||
|
+ case FP_DEVICE_RETRY_REMOVE_FINGER:
|
||
|
+ msg = "Please try again after removing the finger first.";
|
||
|
+ break;
|
||
|
+
|
||
|
+ default:
|
||
|
+ g_warning ("Unsupported error, returning general error instead!");
|
||
|
+ error = FP_DEVICE_RETRY_GENERAL;
|
||
|
+ msg = "Please try again.";
|
||
|
+ }
|
||
|
+
|
||
|
+ return g_error_new_literal (FP_DEVICE_RETRY, error, msg);
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * fpi_device_error_new:
|
||
|
+ * @error: The #FpDeviceRetry error value describing the issue
|
||
|
+ *
|
||
|
+ * Create a new error code for use with fpi_device_verify_complete() and
|
||
|
+ * similar calls.
|
||
|
+ */
|
||
|
+GError *
|
||
|
+fpi_device_error_new (FpDeviceError error)
|
||
|
+{
|
||
|
+ const gchar *msg;
|
||
|
+
|
||
|
+ switch (error)
|
||
|
+ {
|
||
|
+ case FP_DEVICE_ERROR_GENERAL:
|
||
|
+ msg = "An unspecified error occured!";
|
||
|
+ break;
|
||
|
+
|
||
|
+ case FP_DEVICE_ERROR_NOT_SUPPORTED:
|
||
|
+ msg = "The operation is not supported on this device!";
|
||
|
+ break;
|
||
|
+
|
||
|
+ case FP_DEVICE_ERROR_NOT_OPEN:
|
||
|
+ msg = "The device needs to be opened first!";
|
||
|
+ break;
|
||
|
+
|
||
|
+ case FP_DEVICE_ERROR_ALREADY_OPEN:
|
||
|
+ msg = "The device has already been opened!";
|
||
|
+ break;
|
||
|
+
|
||
|
+ case FP_DEVICE_ERROR_BUSY:
|
||
|
+ msg = "The device is still busy with another operation, please try again later.";
|
||
|
+ break;
|
||
|
+
|
||
|
+ case FP_DEVICE_ERROR_PROTO:
|
||
|
+ msg = "The driver encountered a protocol error with the device.";
|
||
|
+ break;
|
||
|
+
|
||
|
+ case FP_DEVICE_ERROR_DATA_INVALID:
|
||
|
+ msg = "Passed (print) data is not valid.";
|
||
|
+ break;
|
||
|
+
|
||
|
+ case FP_DEVICE_ERROR_DATA_FULL:
|
||
|
+ msg = "On device storage space is full.";
|
||
|
+ break;
|
||
|
+
|
||
|
+ case FP_DEVICE_ERROR_DATA_NOT_FOUND:
|
||
|
+ msg = "Print was not found on the devices storage.";
|
||
|
+ break;
|
||
|
+
|
||
|
+ default:
|
||
|
+ g_warning ("Unsupported error, returning general error instead!");
|
||
|
+ error = FP_DEVICE_ERROR_GENERAL;
|
||
|
+ msg = "An unspecified error occured!";
|
||
|
+ }
|
||
|
+
|
||
|
+ return g_error_new_literal (FP_DEVICE_ERROR, error, msg);
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * fpi_device_retry_new_msg:
|
||
|
+ * @error: The #FpDeviceRetry error value describing the issue
|
||
|
+ * @msg: Custom message to use with printf-style formatting
|
||
|
+ * @...: args for @msg
|
||
|
+ *
|
||
|
+ * Create a new retry error code for use with fpi_device_verify_complete()
|
||
|
+ * and similar calls.
|
||
|
+ */
|
||
|
+GError *
|
||
|
+fpi_device_retry_new_msg (FpDeviceRetry device_error,
|
||
|
+ const gchar *msg,
|
||
|
+ ...)
|
||
|
+{
|
||
|
+ GError *error;
|
||
|
+ va_list args;
|
||
|
+
|
||
|
+ va_start (args, msg);
|
||
|
+ error = g_error_new_valist (FP_DEVICE_RETRY, device_error, msg, args);
|
||
|
+ va_end (args);
|
||
|
+
|
||
|
+ return error;
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * fpi_device_error_new_msg:
|
||
|
+ * @error: The #FpDeviceRetry error value describing the issue
|
||
|
+ * @msg: Custom message to use with printf-style formatting
|
||
|
+ * @...: args for @msg
|
||
|
+ *
|
||
|
+ * Create a new error code for use with fpi_device_verify_complete()
|
||
|
+ * and similar calls.
|
||
|
+ */
|
||
|
+GError *
|
||
|
+fpi_device_error_new_msg (FpDeviceError device_error,
|
||
|
+ const gchar *msg,
|
||
|
+ ...)
|
||
|
+{
|
||
|
+ GError *error;
|
||
|
+ va_list args;
|
||
|
+
|
||
|
+ va_start (args, msg);
|
||
|
+ error = g_error_new_valist (FP_DEVICE_ERROR, device_error, msg, args);
|
||
|
+ va_end (args);
|
||
|
+
|
||
|
+ return error;
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * fpi_device_set_nr_enroll_stages:
|
||
|
+ * @device: The #FpDevice
|
||
|
+ * @enroll_stages: The number of enroll stages
|
||
|
+ *
|
||
|
+ * Updates the reported number of enroll stages that the device needs.
|
||
|
+ * If all supported devices have the same number of stages, then the
|
||
|
+ * value can simply be set in the class.
|
||
|
+ */
|
||
|
+void
|
||
|
+fpi_device_set_nr_enroll_stages (FpDevice *device,
|
||
|
+ gint enroll_stages)
|
||
|
+{
|
||
|
+ FpDevicePrivate *priv = fp_device_get_instance_private (device);
|
||
|
+
|
||
|
+ g_return_if_fail (FP_IS_DEVICE (device));
|
||
|
+
|
||
|
+ priv->nr_enroll_stages = enroll_stages;
|
||
|
+ g_object_notify (G_OBJECT (device), "nr-enroll-stages");
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * fpi_device_set_scan_type:
|
||
|
+ * @device: The #FpDevice
|
||
|
+ * @scan_type: The scan type of the device
|
||
|
+ *
|
||
|
+ * Updates the the scan type of the device from the default.
|
||
|
+ * If all supported devices have the same scan type, then the
|
||
|
+ * value can simply be set in the class.
|
||
|
+ */
|
||
|
+void
|
||
|
+fpi_device_set_scan_type (FpDevice *device,
|
||
|
+ FpScanType scan_type)
|
||
|
+{
|
||
|
+ FpDevicePrivate *priv = fp_device_get_instance_private (device);
|
||
|
+
|
||
|
+ g_return_if_fail (FP_IS_DEVICE (device));
|
||
|
+
|
||
|
+ priv->scan_type = scan_type;
|
||
|
+ g_object_notify (G_OBJECT (device), "scan-type");
|
||
|
+}
|
||
|
+
|
||
|
+typedef struct
|
||
|
+{
|
||
|
+ GSource source;
|
||
|
+ FpDevice *device;
|
||
|
+} FpDeviceTimeoutSource;
|
||
|
+
|
||
|
+static void
|
||
|
+timeout_finalize (GSource *source)
|
||
|
+{
|
||
|
+ FpDeviceTimeoutSource *timeout_source = (FpDeviceTimeoutSource *) source;
|
||
|
+ FpDevicePrivate *priv;
|
||
|
+
|
||
|
+ priv = fp_device_get_instance_private (timeout_source->device);
|
||
|
+ priv->sources = g_slist_remove (priv->sources, source);
|
||
|
+}
|
||
|
+
|
||
|
+static gboolean
|
||
|
+timeout_dispatch (GSource *source, GSourceFunc gsource_func, gpointer user_data)
|
||
|
+{
|
||
|
+ FpDeviceTimeoutSource *timeout_source = (FpDeviceTimeoutSource *) source;
|
||
|
+ FpTimeoutFunc callback = (FpTimeoutFunc) gsource_func;
|
||
|
+
|
||
|
+ callback (timeout_source->device, user_data);
|
||
|
+
|
||
|
+ return G_SOURCE_REMOVE;
|
||
|
+}
|
||
|
+
|
||
|
+static GSourceFuncs timeout_funcs = {
|
||
|
+ NULL, /* prepare */
|
||
|
+ NULL, /* check */
|
||
|
+ timeout_dispatch,
|
||
|
+ timeout_finalize,
|
||
|
+ NULL, NULL
|
||
|
+};
|
||
|
+
|
||
|
+/**
|
||
|
+ * fpi_device_add_timeout:
|
||
|
+ * @device: The #FpDevice
|
||
|
+ * @interval: The interval in milliseconds
|
||
|
+ * @func: The #FpTimeoutFunc to call on timeout
|
||
|
+ * @user_data: (nullable): User data to pass to the callback
|
||
|
+ * @destroy_notify: (nullable): #GDestroyNotify for @user_data
|
||
|
+ *
|
||
|
+ * Register a timeout to run. Drivers should always make sure that timers are
|
||
|
+ * cancelled when appropriate.
|
||
|
+ *
|
||
|
+ * Returns: (transfer none): A newly created and attached #GSource
|
||
|
+ */
|
||
|
+GSource *
|
||
|
+fpi_device_add_timeout (FpDevice *device,
|
||
|
+ gint interval,
|
||
|
+ FpTimeoutFunc func,
|
||
|
+ gpointer user_data,
|
||
|
+ GDestroyNotify destroy_notify)
|
||
|
+{
|
||
|
+ FpDevicePrivate *priv = fp_device_get_instance_private (device);
|
||
|
+ FpDeviceTimeoutSource *source;
|
||
|
+
|
||
|
+ source = (FpDeviceTimeoutSource *) g_source_new (&timeout_funcs,
|
||
|
+ sizeof (FpDeviceTimeoutSource));
|
||
|
+ source->device = device;
|
||
|
+
|
||
|
+ g_source_attach (&source->source, NULL);
|
||
|
+ g_source_set_callback (&source->source, (GSourceFunc) func, user_data, destroy_notify);
|
||
|
+ g_source_set_ready_time (&source->source,
|
||
|
+ g_source_get_time (&source->source) + interval * (guint64) 1000);
|
||
|
+ priv->sources = g_slist_prepend (priv->sources, source);
|
||
|
+ g_source_unref (&source->source);
|
||
|
+
|
||
|
+ return &source->source;
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * fpi_device_get_usb_device:
|
||
|
+ * @device: The #FpDevice
|
||
|
+ *
|
||
|
+ * Get the #GUsbDevice for this #FpDevice. Only permissible to call if the
|
||
|
+ * #FpDevice is of type %FP_DEVICE_TYPE_USB.
|
||
|
+ *
|
||
|
+ * Returns: The #GUsbDevice
|
||
|
+ */
|
||
|
+GUsbDevice *
|
||
|
+fpi_device_get_usb_device (FpDevice *device)
|
||
|
+{
|
||
|
+ FpDevicePrivate *priv = fp_device_get_instance_private (device);
|
||
|
+
|
||
|
+ g_return_val_if_fail (FP_IS_DEVICE (device), NULL);
|
||
|
+ g_return_val_if_fail (priv->type == FP_DEVICE_TYPE_USB, NULL);
|
||
|
+
|
||
|
+ return priv->usb_device;
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * fpi_device_get_virtual_env:
|
||
|
+ * @device: The #FpDevice
|
||
|
+ *
|
||
|
+ * Get the value of the environment variable that caused the virtual #FpDevice to be
|
||
|
+ * generated. Only permissible to call if the #FpDevice is of type %FP_DEVICE_TYPE_VIRTUAL.
|
||
|
+ *
|
||
|
+ * Returns: The value of the environment variable
|
||
|
+ */
|
||
|
+const gchar *
|
||
|
+fpi_device_get_virtual_env (FpDevice *device)
|
||
|
+{
|
||
|
+ FpDevicePrivate *priv = fp_device_get_instance_private (device);
|
||
|
+
|
||
|
+ g_return_val_if_fail (FP_IS_DEVICE (device), NULL);
|
||
|
+ g_return_val_if_fail (priv->type == FP_DEVICE_TYPE_VIRTUAL, NULL);
|
||
|
+
|
||
|
+ return priv->virtual_env;
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * fpi_device_get_current_action:
|
||
|
+ * @device: The #FpDevice
|
||
|
+ *
|
||
|
+ * Get the currently ongoing action or %FP_DEVICE_ACTION_NONE if there
|
||
|
+ * is no operation at this time.
|
||
|
+ *
|
||
|
+ * This is useful for drivers that might share code paths between different
|
||
|
+ * actions (e.g. verify and identify) and want to find out again later which
|
||
|
+ * action was started in the beginning.
|
||
|
+ *
|
||
|
+ * Returns: The ongoing #FpDeviceAction
|
||
|
+ */
|
||
|
+FpDeviceAction
|
||
|
+fpi_device_get_current_action (FpDevice *device)
|
||
|
+{
|
||
|
+ FpDevicePrivate *priv = fp_device_get_instance_private (device);
|
||
|
+
|
||
|
+ g_return_val_if_fail (FP_IS_DEVICE (device), FP_DEVICE_ACTION_NONE);
|
||
|
+
|
||
|
+ return priv->current_action;
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * fpi_device_action_is_cancelled:
|
||
|
+ * @device: The #FpDevice
|
||
|
+ *
|
||
|
+ * Checks whether the current action has been cancelled by the user.
|
||
|
+ * This is equivalent to first getting the cancellable using
|
||
|
+ * fpi_device_get_cancellable() and then checking whether it has been
|
||
|
+ * cancelled (if it is non-NULL).
|
||
|
+ *
|
||
|
+ * Returns: %TRUE if action should be cancelled
|
||
|
+ */
|
||
|
+gboolean
|
||
|
+fpi_device_action_is_cancelled (FpDevice *device)
|
||
|
+{
|
||
|
+ FpDevicePrivate *priv = fp_device_get_instance_private (device);
|
||
|
+ GCancellable *cancellable;
|
||
|
+
|
||
|
+ g_return_val_if_fail (FP_IS_DEVICE (device), TRUE);
|
||
|
+ g_return_val_if_fail (priv->current_action != FP_DEVICE_ACTION_NONE, TRUE);
|
||
|
+
|
||
|
+ cancellable = g_task_get_cancellable (priv->current_task);
|
||
|
+
|
||
|
+ return cancellable ? g_cancellable_is_cancelled (cancellable) : FALSE;
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * fpi_device_get_driver_data:
|
||
|
+ * @device: The #FpDevice
|
||
|
+ *
|
||
|
+ * Returns: The driver data from the #FpIdEntry table entry
|
||
|
+ */
|
||
|
+guint64
|
||
|
+fpi_device_get_driver_data (FpDevice *device)
|
||
|
+{
|
||
|
+ FpDevicePrivate *priv = fp_device_get_instance_private (device);
|
||
|
+
|
||
|
+ g_return_val_if_fail (FP_IS_DEVICE (device), 0);
|
||
|
+
|
||
|
+ return priv->driver_data;
|
||
|
+}
|
||
|
+
|
||
|
+void
|
||
|
+enroll_data_free (FpEnrollData *data)
|
||
|
+{
|
||
|
+ if (data->enroll_progress_destroy)
|
||
|
+ data->enroll_progress_destroy (data->enroll_progress_data);
|
||
|
+ data->enroll_progress_data = NULL;
|
||
|
+ g_clear_object (&data->print);
|
||
|
+ g_free (data);
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * fpi_device_get_enroll_data:
|
||
|
+ * @device: The #FpDevice
|
||
|
+ * @print: (out) (transfer none): The user provided template print
|
||
|
+ *
|
||
|
+ * Get data for enrollment.
|
||
|
+ */
|
||
|
+void
|
||
|
+fpi_device_get_enroll_data (FpDevice *device,
|
||
|
+ FpPrint **print)
|
||
|
+{
|
||
|
+ FpDevicePrivate *priv = fp_device_get_instance_private (device);
|
||
|
+ FpEnrollData *data;
|
||
|
+
|
||
|
+ g_return_if_fail (FP_IS_DEVICE (device));
|
||
|
+ g_return_if_fail (priv->current_action == FP_DEVICE_ACTION_ENROLL);
|
||
|
+
|
||
|
+ data = g_task_get_task_data (priv->current_task);
|
||
|
+ g_assert (data);
|
||
|
+
|
||
|
+ if (print)
|
||
|
+ *print = data->print;
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * fpi_device_get_capture_data:
|
||
|
+ * @device: The #FpDevice
|
||
|
+ * @wait_for_finger: (out): Whether to wait for finger or not
|
||
|
+ *
|
||
|
+ * Get data for capture.
|
||
|
+ */
|
||
|
+void
|
||
|
+fpi_device_get_capture_data (FpDevice *device,
|
||
|
+ gboolean *wait_for_finger)
|
||
|
+{
|
||
|
+ FpDevicePrivate *priv = fp_device_get_instance_private (device);
|
||
|
+
|
||
|
+ g_return_if_fail (FP_IS_DEVICE (device));
|
||
|
+ g_return_if_fail (priv->current_action == FP_DEVICE_ACTION_CAPTURE);
|
||
|
+
|
||
|
+ if (wait_for_finger)
|
||
|
+ *wait_for_finger = priv->wait_for_finger;
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * fpi_device_get_verify_data:
|
||
|
+ * @device: The #FpDevice
|
||
|
+ * @print: (out) (transfer none): The enrolled print
|
||
|
+ *
|
||
|
+ * Get data for verify.
|
||
|
+ */
|
||
|
+void
|
||
|
+fpi_device_get_verify_data (FpDevice *device,
|
||
|
+ FpPrint **print)
|
||
|
+{
|
||
|
+ FpDevicePrivate *priv = fp_device_get_instance_private (device);
|
||
|
+
|
||
|
+ g_return_if_fail (FP_IS_DEVICE (device));
|
||
|
+ g_return_if_fail (priv->current_action == FP_DEVICE_ACTION_VERIFY);
|
||
|
+
|
||
|
+ if (print)
|
||
|
+ *print = g_task_get_task_data (priv->current_task);
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * fpi_device_get_identify_data:
|
||
|
+ * @device: The #FpDevice
|
||
|
+ * @prints: (out) (transfer none) (element-type FpPrint): The gallery of prints
|
||
|
+ *
|
||
|
+ * Get data for identify.
|
||
|
+ */
|
||
|
+void
|
||
|
+fpi_device_get_identify_data (FpDevice *device,
|
||
|
+ GPtrArray **prints)
|
||
|
+{
|
||
|
+ FpDevicePrivate *priv = fp_device_get_instance_private (device);
|
||
|
+
|
||
|
+ g_return_if_fail (FP_IS_DEVICE (device));
|
||
|
+ g_return_if_fail (priv->current_action == FP_DEVICE_ACTION_IDENTIFY);
|
||
|
+
|
||
|
+ if (prints)
|
||
|
+ *prints = g_task_get_task_data (priv->current_task);
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * fpi_device_get_delete_data:
|
||
|
+ * @device: The #FpDevice
|
||
|
+ * @print: (out) (transfer none): The print to delete
|
||
|
+ *
|
||
|
+ * Get data for delete.
|
||
|
+ */
|
||
|
+void
|
||
|
+fpi_device_get_delete_data (FpDevice *device,
|
||
|
+ FpPrint **print)
|
||
|
+{
|
||
|
+ FpDevicePrivate *priv = fp_device_get_instance_private (device);
|
||
|
+
|
||
|
+ g_return_if_fail (FP_IS_DEVICE (device));
|
||
|
+ g_return_if_fail (priv->current_action == FP_DEVICE_ACTION_DELETE);
|
||
|
+
|
||
|
+ if (print)
|
||
|
+ *print = g_task_get_task_data (priv->current_task);
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * fpi_device_get_cancellable:
|
||
|
+ * @device: The #FpDevice
|
||
|
+ *
|
||
|
+ * Retrieve the #GCancellable that may cancel the currently ongoing operation. This
|
||
|
+ * is primarily useful to pass directly to e.g. fpi_usb_transfer_submit() for cancellable
|
||
|
+ * transfers.
|
||
|
+ * In many cases the cancel vfunc may be more convenient to react to cancellation in some
|
||
|
+ * way.
|
||
|
+ *
|
||
|
+ * Returns: (transfer none): The #GCancellable for the current action.
|
||
|
+ */
|
||
|
+GCancellable *
|
||
|
+fpi_device_get_cancellable (FpDevice *device)
|
||
|
+{
|
||
|
+ FpDevicePrivate *priv = fp_device_get_instance_private (device);
|
||
|
+
|
||
|
+ g_return_val_if_fail (FP_IS_DEVICE (device), NULL);
|
||
|
+ g_return_val_if_fail (priv->current_action != FP_DEVICE_ACTION_NONE, NULL);
|
||
|
+
|
||
|
+ return g_task_get_cancellable (priv->current_task);
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * fpi_device_action_error:
|
||
|
+ * @device: The #FpDevice
|
||
|
+ * @error: The #GError to return
|
||
|
+ *
|
||
|
+ * Finish an ongoing action with an error. This is the same as calling
|
||
|
+ * the corresponding complete function such as fpi_device_open_complete()
|
||
|
+ * with an error set. If possible, use the correct complete function as
|
||
|
+ * that results in improved error detection.
|
||
|
+ */
|
||
|
+void
|
||
|
+fpi_device_action_error (FpDevice *device,
|
||
|
+ GError *error)
|
||
|
+{
|
||
|
+ FpDevicePrivate *priv = fp_device_get_instance_private (device);
|
||
|
+
|
||
|
+ g_return_if_fail (FP_IS_DEVICE (device));
|
||
|
+ g_return_if_fail (priv->current_action != FP_DEVICE_ACTION_NONE);
|
||
|
+
|
||
|
+ if (error != NULL)
|
||
|
+ {
|
||
|
+ g_debug ("Device reported generic error during action; action was: %i", priv->current_action);
|
||
|
+ }
|
||
|
+ else
|
||
|
+ {
|
||
|
+ g_warning ("Device failed to pass an error to generic action error function");
|
||
|
+ error = fpi_device_error_new_msg (FP_DEVICE_ERROR_GENERAL, "Device reported error but did not provide an error condition");
|
||
|
+ }
|
||
|
+
|
||
|
+
|
||
|
+ switch (priv->current_action)
|
||
|
+ {
|
||
|
+ case FP_DEVICE_ACTION_PROBE:
|
||
|
+ fpi_device_probe_complete (device, NULL, NULL, error);
|
||
|
+ break;
|
||
|
+
|
||
|
+ case FP_DEVICE_ACTION_OPEN:
|
||
|
+ fpi_device_open_complete (device, error);
|
||
|
+ break;
|
||
|
+
|
||
|
+ case FP_DEVICE_ACTION_CLOSE:
|
||
|
+ fpi_device_close_complete (device, error);
|
||
|
+ break;
|
||
|
+
|
||
|
+ case FP_DEVICE_ACTION_ENROLL:
|
||
|
+ fpi_device_enroll_complete (device, NULL, error);
|
||
|
+ break;
|
||
|
+
|
||
|
+ case FP_DEVICE_ACTION_VERIFY:
|
||
|
+ fpi_device_verify_complete (device, FPI_MATCH_ERROR, NULL, error);
|
||
|
+ break;
|
||
|
+
|
||
|
+ case FP_DEVICE_ACTION_IDENTIFY:
|
||
|
+ fpi_device_identify_complete (device, NULL, NULL, error);
|
||
|
+ break;
|
||
|
+
|
||
|
+ case FP_DEVICE_ACTION_CAPTURE:
|
||
|
+ fpi_device_capture_complete (device, NULL, error);
|
||
|
+ break;
|
||
|
+
|
||
|
+ case FP_DEVICE_ACTION_DELETE:
|
||
|
+ fpi_device_delete_complete (device, error);
|
||
|
+ break;
|
||
|
+
|
||
|
+ case FP_DEVICE_ACTION_LIST:
|
||
|
+ fpi_device_list_complete (device, NULL, error);
|
||
|
+ break;
|
||
|
+
|
||
|
+ default:
|
||
|
+ case FP_DEVICE_ACTION_NONE:
|
||
|
+ g_return_if_reached ();
|
||
|
+ break;
|
||
|
+ }
|
||
|
+}
|
||
|
+
|
||
|
+static void
|
||
|
+clear_device_cancel_action (FpDevice *device)
|
||
|
+{
|
||
|
+ FpDevicePrivate *priv = fp_device_get_instance_private (device);
|
||
|
+
|
||
|
+ g_clear_pointer (&priv->current_idle_cancel_source, g_source_destroy);
|
||
|
+
|
||
|
+ if (priv->current_cancellable_id)
|
||
|
+ {
|
||
|
+ g_cancellable_disconnect (g_task_get_cancellable (priv->current_task),
|
||
|
+ priv->current_cancellable_id);
|
||
|
+ priv->current_cancellable_id = 0;
|
||
|
+ }
|
||
|
+}
|
||
|
+
|
||
|
+typedef enum _FpDeviceTaskReturnType {
|
||
|
+ FP_DEVICE_TASK_RETURN_INT,
|
||
|
+ FP_DEVICE_TASK_RETURN_BOOL,
|
||
|
+ FP_DEVICE_TASK_RETURN_OBJECT,
|
||
|
+ FP_DEVICE_TASK_RETURN_PTR_ARRAY,
|
||
|
+ FP_DEVICE_TASK_RETURN_ERROR,
|
||
|
+} FpDeviceTaskReturnType;
|
||
|
+
|
||
|
+typedef struct _FpDeviceTaskReturnData
|
||
|
+{
|
||
|
+ FpDevice *device;
|
||
|
+ FpDeviceTaskReturnType type;
|
||
|
+ gpointer result;
|
||
|
+} FpDeviceTaskReturnData;
|
||
|
+
|
||
|
+static gboolean
|
||
|
+fp_device_task_return_in_idle_cb (gpointer user_data)
|
||
|
+{
|
||
|
+ FpDeviceTaskReturnData *data = user_data;
|
||
|
+ FpDevicePrivate *priv = fp_device_get_instance_private (data->device);
|
||
|
+
|
||
|
+ g_autoptr(GTask) task = NULL;
|
||
|
+
|
||
|
+ g_debug ("Completing action %d in idle!", priv->current_action);
|
||
|
+
|
||
|
+ task = g_steal_pointer (&priv->current_task);
|
||
|
+ priv->current_action = FP_DEVICE_ACTION_NONE;
|
||
|
+ priv->current_task_idle_return_source = NULL;
|
||
|
+
|
||
|
+ switch (data->type)
|
||
|
+ {
|
||
|
+ case FP_DEVICE_TASK_RETURN_INT:
|
||
|
+ g_task_return_int (task, GPOINTER_TO_INT (data->result));
|
||
|
+ break;
|
||
|
+
|
||
|
+ case FP_DEVICE_TASK_RETURN_BOOL:
|
||
|
+ g_task_return_boolean (task, GPOINTER_TO_UINT (data->result));
|
||
|
+ break;
|
||
|
+
|
||
|
+ case FP_DEVICE_TASK_RETURN_OBJECT:
|
||
|
+ g_task_return_pointer (task, data->result, g_object_unref);
|
||
|
+ break;
|
||
|
+
|
||
|
+ case FP_DEVICE_TASK_RETURN_PTR_ARRAY:
|
||
|
+ g_task_return_pointer (task, data->result,
|
||
|
+ (GDestroyNotify) g_ptr_array_unref);
|
||
|
+ break;
|
||
|
+
|
||
|
+ case FP_DEVICE_TASK_RETURN_ERROR:
|
||
|
+ g_task_return_error (task, data->result);
|
||
|
+ break;
|
||
|
+
|
||
|
+ default:
|
||
|
+ g_assert_not_reached ();
|
||
|
+ }
|
||
|
+
|
||
|
+ return G_SOURCE_REMOVE;
|
||
|
+}
|
||
|
+
|
||
|
+static void
|
||
|
+fpi_device_task_return_data_free (FpDeviceTaskReturnData *data)
|
||
|
+{
|
||
|
+ g_object_unref (data->device);
|
||
|
+ g_free (data);
|
||
|
+}
|
||
|
+
|
||
|
+static void
|
||
|
+fpi_device_return_task_in_idle (FpDevice *device,
|
||
|
+ FpDeviceTaskReturnType return_type,
|
||
|
+ gpointer return_data)
|
||
|
+{
|
||
|
+ FpDevicePrivate *priv = fp_device_get_instance_private (device);
|
||
|
+ FpDeviceTaskReturnData *data;
|
||
|
+
|
||
|
+ data = g_new0 (FpDeviceTaskReturnData, 1);
|
||
|
+ data->device = g_object_ref (device);
|
||
|
+ data->type = return_type;
|
||
|
+ data->result = return_data;
|
||
|
+
|
||
|
+ priv->current_task_idle_return_source = g_idle_source_new ();
|
||
|
+ g_source_set_priority (priv->current_task_idle_return_source,
|
||
|
+ g_task_get_priority (priv->current_task));
|
||
|
+ g_source_set_callback (priv->current_task_idle_return_source,
|
||
|
+ fp_device_task_return_in_idle_cb,
|
||
|
+ data,
|
||
|
+ (GDestroyNotify) fpi_device_task_return_data_free);
|
||
|
+
|
||
|
+ g_source_attach (priv->current_task_idle_return_source, NULL);
|
||
|
+ g_source_unref (priv->current_task_idle_return_source);
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * fpi_device_probe_complete:
|
||
|
+ * @device: The #FpDevice
|
||
|
+ * @device_id: Unique ID for the device or %NULL
|
||
|
+ * @device_name: Human readable name or %NULL for driver name
|
||
|
+ * @error: The #GError or %NULL on success
|
||
|
+ *
|
||
|
+ * Finish an ongoing probe operation. If error is %NULL success is assumed.
|
||
|
+ */
|
||
|
+void
|
||
|
+fpi_device_probe_complete (FpDevice *device,
|
||
|
+ const gchar *device_id,
|
||
|
+ const gchar *device_name,
|
||
|
+ GError *error)
|
||
|
+{
|
||
|
+ FpDevicePrivate *priv = fp_device_get_instance_private (device);
|
||
|
+
|
||
|
+ g_return_if_fail (FP_IS_DEVICE (device));
|
||
|
+ g_return_if_fail (priv->current_action == FP_DEVICE_ACTION_PROBE);
|
||
|
+
|
||
|
+ g_debug ("Device reported probe completion");
|
||
|
+
|
||
|
+ clear_device_cancel_action (device);
|
||
|
+
|
||
|
+ if (!error)
|
||
|
+ {
|
||
|
+ if (device_id)
|
||
|
+ {
|
||
|
+ g_clear_pointer (&priv->device_id, g_free);
|
||
|
+ priv->device_id = g_strdup (device_id);
|
||
|
+ g_object_notify (G_OBJECT (device), "device-id");
|
||
|
+ }
|
||
|
+ if (device_name)
|
||
|
+ {
|
||
|
+ g_clear_pointer (&priv->device_name, g_free);
|
||
|
+ priv->device_name = g_strdup (device_name);
|
||
|
+ g_object_notify (G_OBJECT (device), "name");
|
||
|
+ }
|
||
|
+ 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_open_complete:
|
||
|
+ * @device: The #FpDevice
|
||
|
+ * @error: The #GError or %NULL on success
|
||
|
+ *
|
||
|
+ * Finish an ongoing open operation. If error is %NULL success is assumed.
|
||
|
+ */
|
||
|
+void
|
||
|
+fpi_device_open_complete (FpDevice *device, GError *error)
|
||
|
+{
|
||
|
+ FpDevicePrivate *priv = fp_device_get_instance_private (device);
|
||
|
+
|
||
|
+ g_return_if_fail (FP_IS_DEVICE (device));
|
||
|
+ g_return_if_fail (priv->current_action == FP_DEVICE_ACTION_OPEN);
|
||
|
+
|
||
|
+ g_debug ("Device reported open completion");
|
||
|
+
|
||
|
+ clear_device_cancel_action (device);
|
||
|
+
|
||
|
+ if (!error)
|
||
|
+ {
|
||
|
+ priv->is_open = TRUE;
|
||
|
+ 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));
|
||
|
+ else
|
||
|
+ fpi_device_return_task_in_idle (device, FP_DEVICE_TASK_RETURN_ERROR, error);
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * fpi_device_close_complete:
|
||
|
+ * @device: The #FpDevice
|
||
|
+ * @error: The #GError or %NULL on success
|
||
|
+ *
|
||
|
+ * Finish an ongoing close operation. If error is %NULL success is assumed.
|
||
|
+ */
|
||
|
+void
|
||
|
+fpi_device_close_complete (FpDevice *device, GError *error)
|
||
|
+{
|
||
|
+ GError *nested_error = NULL;
|
||
|
+ FpDevicePrivate *priv = fp_device_get_instance_private (device);
|
||
|
+
|
||
|
+ g_return_if_fail (FP_IS_DEVICE (device));
|
||
|
+ g_return_if_fail (priv->current_action == FP_DEVICE_ACTION_CLOSE);
|
||
|
+
|
||
|
+ g_debug ("Device reported close completion");
|
||
|
+
|
||
|
+ clear_device_cancel_action (device);
|
||
|
+ priv->is_open = FALSE;
|
||
|
+ g_object_notify (G_OBJECT (device), "open");
|
||
|
+
|
||
|
+ switch (priv->type)
|
||
|
+ {
|
||
|
+ case FP_DEVICE_TYPE_USB:
|
||
|
+ if (!g_usb_device_close (priv->usb_device, &nested_error))
|
||
|
+ {
|
||
|
+ if (error == NULL)
|
||
|
+ error = nested_error;
|
||
|
+ fpi_device_return_task_in_idle (device, FP_DEVICE_TASK_RETURN_ERROR, error);
|
||
|
+ return;
|
||
|
+ }
|
||
|
+ break;
|
||
|
+
|
||
|
+ case FP_DEVICE_TYPE_VIRTUAL:
|
||
|
+ break;
|
||
|
+
|
||
|
+ default:
|
||
|
+ g_assert_not_reached ();
|
||
|
+ fpi_device_return_task_in_idle (device, FP_DEVICE_TASK_RETURN_ERROR,
|
||
|
+ fpi_device_error_new (FP_DEVICE_ERROR_GENERAL));
|
||
|
+ return;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (!error)
|
||
|
+ 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_enroll_complete:
|
||
|
+ * @device: The #FpDevice
|
||
|
+ * @print: (nullable) (transfer full): The #FpPrint or %NULL on failure
|
||
|
+ * @error: The #GError or %NULL on success
|
||
|
+ *
|
||
|
+ * Finish an ongoing enroll operation. The #FpPrint can be stored by the
|
||
|
+ * caller for later verification.
|
||
|
+ */
|
||
|
+void
|
||
|
+fpi_device_enroll_complete (FpDevice *device, FpPrint *print, GError *error)
|
||
|
+{
|
||
|
+ FpDevicePrivate *priv = fp_device_get_instance_private (device);
|
||
|
+
|
||
|
+ g_return_if_fail (FP_IS_DEVICE (device));
|
||
|
+ g_return_if_fail (priv->current_action == FP_DEVICE_ACTION_ENROLL);
|
||
|
+
|
||
|
+ g_debug ("Device reported enroll completion");
|
||
|
+
|
||
|
+ clear_device_cancel_action (device);
|
||
|
+
|
||
|
+ if (!error)
|
||
|
+ {
|
||
|
+ if (FP_IS_PRINT (print))
|
||
|
+ {
|
||
|
+ fpi_device_return_task_in_idle (device, FP_DEVICE_TASK_RETURN_OBJECT, print);
|
||
|
+ }
|
||
|
+ else
|
||
|
+ {
|
||
|
+ g_warning ("Driver did not provide a valid print and failed to provide an error!");
|
||
|
+ error = fpi_device_error_new_msg (FP_DEVICE_ERROR_GENERAL,
|
||
|
+ "Driver failed to provide print data!");
|
||
|
+ fpi_device_return_task_in_idle (device, FP_DEVICE_TASK_RETURN_ERROR, error);
|
||
|
+ }
|
||
|
+ }
|
||
|
+ else
|
||
|
+ {
|
||
|
+ fpi_device_return_task_in_idle (device, FP_DEVICE_TASK_RETURN_ERROR, error);
|
||
|
+ if (FP_IS_PRINT (print))
|
||
|
+ {
|
||
|
+ g_warning ("Driver passed an error but also provided a print, returning error!");
|
||
|
+ g_object_unref (print);
|
||
|
+ }
|
||
|
+ }
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * fpi_device_verify_complete:
|
||
|
+ * @device: The #FpDevice
|
||
|
+ * @result: The #FpiMatchResult of the operation
|
||
|
+ * @print: The scanned #FpPrint
|
||
|
+ * @error: A #GError if result is %FPI_MATCH_ERROR
|
||
|
+ *
|
||
|
+ * Finish an ongoing verify operation. The returned print should be
|
||
|
+ * representing the new scan and not the one passed for verification.
|
||
|
+ */
|
||
|
+void
|
||
|
+fpi_device_verify_complete (FpDevice *device,
|
||
|
+ FpiMatchResult result,
|
||
|
+ FpPrint *print,
|
||
|
+ GError *error)
|
||
|
+{
|
||
|
+ FpDevicePrivate *priv = fp_device_get_instance_private (device);
|
||
|
+
|
||
|
+ g_return_if_fail (FP_IS_DEVICE (device));
|
||
|
+ g_return_if_fail (priv->current_action == FP_DEVICE_ACTION_VERIFY);
|
||
|
+
|
||
|
+ g_debug ("Device reported verify completion");
|
||
|
+
|
||
|
+ clear_device_cancel_action (device);
|
||
|
+
|
||
|
+ g_object_set_data_full (G_OBJECT (priv->current_task),
|
||
|
+ "print",
|
||
|
+ print,
|
||
|
+ g_object_unref);
|
||
|
+
|
||
|
+ if (!error)
|
||
|
+ {
|
||
|
+ if (result != FPI_MATCH_ERROR)
|
||
|
+ {
|
||
|
+ fpi_device_return_task_in_idle (device, FP_DEVICE_TASK_RETURN_INT,
|
||
|
+ GINT_TO_POINTER (result));
|
||
|
+ }
|
||
|
+ else
|
||
|
+ {
|
||
|
+ g_warning ("Driver did not provide an error for a failed verify operation!");
|
||
|
+ error = fpi_device_error_new_msg (FP_DEVICE_ERROR_GENERAL,
|
||
|
+ "Driver failed to provide an error!");
|
||
|
+ fpi_device_return_task_in_idle (device, FP_DEVICE_TASK_RETURN_ERROR, error);
|
||
|
+ }
|
||
|
+ }
|
||
|
+ else
|
||
|
+ {
|
||
|
+ fpi_device_return_task_in_idle (device, FP_DEVICE_TASK_RETURN_ERROR, error);
|
||
|
+ if (result != FPI_MATCH_ERROR)
|
||
|
+ {
|
||
|
+ g_warning ("Driver passed an error but also provided a match result, returning error!");
|
||
|
+ g_object_unref (print);
|
||
|
+ }
|
||
|
+ }
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * fpi_device_identify_complete:
|
||
|
+ * @device: The #FpDevice
|
||
|
+ * @match: The matching #FpPrint from the passed gallery, or %NULL if none matched
|
||
|
+ * @print: The scanned #FpPrint, may be %NULL
|
||
|
+ * @error: The #GError or %NULL on success
|
||
|
+ *
|
||
|
+ * Finish an ongoing identify operation. The match that was identified is
|
||
|
+ * returned in @match. The @print parameter returns the newly created scan
|
||
|
+ * that was used for matching.
|
||
|
+ */
|
||
|
+void
|
||
|
+fpi_device_identify_complete (FpDevice *device,
|
||
|
+ FpPrint *match,
|
||
|
+ FpPrint *print,
|
||
|
+ GError *error)
|
||
|
+{
|
||
|
+ FpDevicePrivate *priv = fp_device_get_instance_private (device);
|
||
|
+
|
||
|
+ g_return_if_fail (FP_IS_DEVICE (device));
|
||
|
+ g_return_if_fail (priv->current_action == FP_DEVICE_ACTION_IDENTIFY);
|
||
|
+
|
||
|
+ g_debug ("Device reported identify completion");
|
||
|
+
|
||
|
+ clear_device_cancel_action (device);
|
||
|
+
|
||
|
+ g_object_set_data_full (G_OBJECT (priv->current_task),
|
||
|
+ "print",
|
||
|
+ print,
|
||
|
+ g_object_unref);
|
||
|
+ g_object_set_data_full (G_OBJECT (priv->current_task),
|
||
|
+ "match",
|
||
|
+ match,
|
||
|
+ g_object_unref);
|
||
|
+ if (!error)
|
||
|
+ {
|
||
|
+ 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);
|
||
|
+ if (match)
|
||
|
+ {
|
||
|
+ g_warning ("Driver passed an error but also provided a match result, returning error!");
|
||
|
+ g_clear_object (&match);
|
||
|
+ }
|
||
|
+ }
|
||
|
+}
|
||
|
+
|
||
|
+
|
||
|
+/**
|
||
|
+ * fpi_device_capture_complete:
|
||
|
+ * @device: The #FpDevice
|
||
|
+ * @image: The #FpImage, or %NULL on error
|
||
|
+ * @error: The #GError or %NULL on success
|
||
|
+ *
|
||
|
+ * Finish an ongoing capture operation.
|
||
|
+ */
|
||
|
+void
|
||
|
+fpi_device_capture_complete (FpDevice *device,
|
||
|
+ FpImage *image,
|
||
|
+ GError *error)
|
||
|
+{
|
||
|
+ FpDevicePrivate *priv = fp_device_get_instance_private (device);
|
||
|
+
|
||
|
+ g_return_if_fail (FP_IS_DEVICE (device));
|
||
|
+ g_return_if_fail (priv->current_action == FP_DEVICE_ACTION_CAPTURE);
|
||
|
+
|
||
|
+ g_debug ("Device reported capture completion");
|
||
|
+
|
||
|
+ clear_device_cancel_action (device);
|
||
|
+
|
||
|
+ if (!error)
|
||
|
+ {
|
||
|
+ if (image)
|
||
|
+ {
|
||
|
+ fpi_device_return_task_in_idle (device, FP_DEVICE_TASK_RETURN_OBJECT, image);
|
||
|
+ }
|
||
|
+ else
|
||
|
+ {
|
||
|
+ g_warning ("Driver did not provide an error for a failed capture operation!");
|
||
|
+ error = fpi_device_error_new_msg (FP_DEVICE_ERROR_GENERAL,
|
||
|
+ "Driver failed to provide an error!");
|
||
|
+ fpi_device_return_task_in_idle (device, FP_DEVICE_TASK_RETURN_ERROR, error);
|
||
|
+ }
|
||
|
+ }
|
||
|
+ else
|
||
|
+ {
|
||
|
+ fpi_device_return_task_in_idle (device, FP_DEVICE_TASK_RETURN_ERROR, error);
|
||
|
+ if (image)
|
||
|
+ {
|
||
|
+ g_warning ("Driver passed an error but also provided an image, returning error!");
|
||
|
+ g_clear_object (&image);
|
||
|
+ }
|
||
|
+ }
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * fpi_device_delete_complete:
|
||
|
+ * @device: The #FpDevice
|
||
|
+ * @error: The #GError or %NULL on success
|
||
|
+ *
|
||
|
+ * Finish an ongoing delete operation.
|
||
|
+ */
|
||
|
+void
|
||
|
+fpi_device_delete_complete (FpDevice *device,
|
||
|
+ GError *error)
|
||
|
+{
|
||
|
+ FpDevicePrivate *priv = fp_device_get_instance_private (device);
|
||
|
+
|
||
|
+ g_return_if_fail (FP_IS_DEVICE (device));
|
||
|
+ g_return_if_fail (priv->current_action == FP_DEVICE_ACTION_DELETE);
|
||
|
+
|
||
|
+ g_debug ("Device reported deletion completion");
|
||
|
+
|
||
|
+ clear_device_cancel_action (device);
|
||
|
+
|
||
|
+ if (!error)
|
||
|
+ 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_list_complete:
|
||
|
+ * @device: The #FpDevice
|
||
|
+ * @prints: (element-type FpPrint) (transfer container): Possibly empty array of prints or %NULL on error
|
||
|
+ * @error: The #GError or %NULL on success
|
||
|
+ *
|
||
|
+ * Finish an ongoing list operation.
|
||
|
+ *
|
||
|
+ * Please note that the @prints array will be free'ed using
|
||
|
+ * g_ptr_array_unref() and the elements are destroyed automatically.
|
||
|
+ * As such, you must use g_ptr_array_new_with_free_func() with
|
||
|
+ * g_object_unref() as free func to create the array.
|
||
|
+ */
|
||
|
+void
|
||
|
+fpi_device_list_complete (FpDevice *device,
|
||
|
+ GPtrArray *prints,
|
||
|
+ GError *error)
|
||
|
+{
|
||
|
+ FpDevicePrivate *priv = fp_device_get_instance_private (device);
|
||
|
+
|
||
|
+ g_return_if_fail (FP_IS_DEVICE (device));
|
||
|
+ g_return_if_fail (priv->current_action == FP_DEVICE_ACTION_LIST);
|
||
|
+
|
||
|
+ g_debug ("Device reported listing completion");
|
||
|
+
|
||
|
+ clear_device_cancel_action (device);
|
||
|
+
|
||
|
+ if (prints && error)
|
||
|
+ {
|
||
|
+ g_warning ("Driver reported back prints and error, ignoring prints");
|
||
|
+ g_clear_pointer (&prints, g_ptr_array_unref);
|
||
|
+ }
|
||
|
+ else if (!prints && !error)
|
||
|
+ {
|
||
|
+ g_warning ("Driver did not pass array but failed to provide an error");
|
||
|
+ error = fpi_device_error_new_msg (FP_DEVICE_ERROR_GENERAL,
|
||
|
+ "Driver failed to provide a list of prints");
|
||
|
+ }
|
||
|
+
|
||
|
+ if (!error)
|
||
|
+ fpi_device_return_task_in_idle (device, FP_DEVICE_TASK_RETURN_PTR_ARRAY, prints);
|
||
|
+ else
|
||
|
+ fpi_device_return_task_in_idle (device, FP_DEVICE_TASK_RETURN_ERROR, error);
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * fpi_device_enroll_progress:
|
||
|
+ * @device: The #FpDevice
|
||
|
+ * @completed_stages: The number of stages that are completed at this point
|
||
|
+ * @print: The #FpPrint for the newly completed stage or %NULL on failure
|
||
|
+ * @error: The #GError or %NULL on success
|
||
|
+ *
|
||
|
+ * Notify about the progress of the enroll operation. This is important for UI interaction.
|
||
|
+ * The passed error may be used if a scan needs to be retried, use fpi_device_retry_new().
|
||
|
+ */
|
||
|
+void
|
||
|
+fpi_device_enroll_progress (FpDevice *device,
|
||
|
+ gint completed_stages,
|
||
|
+ FpPrint *print,
|
||
|
+ GError *error)
|
||
|
+{
|
||
|
+ FpDevicePrivate *priv = fp_device_get_instance_private (device);
|
||
|
+ FpEnrollData *data;
|
||
|
+
|
||
|
+ g_return_if_fail (FP_IS_DEVICE (device));
|
||
|
+ g_return_if_fail (priv->current_action == FP_DEVICE_ACTION_ENROLL);
|
||
|
+ g_return_if_fail (error == NULL || error->domain == FP_DEVICE_RETRY);
|
||
|
+
|
||
|
+ g_debug ("Device reported enroll progress, reported %i of %i have been completed", completed_stages, priv->nr_enroll_stages);
|
||
|
+
|
||
|
+ if (error && print)
|
||
|
+ {
|
||
|
+ g_warning ("Driver passed an error and also provided a print, returning error!");
|
||
|
+ g_clear_object (&print);
|
||
|
+ }
|
||
|
+
|
||
|
+ data = g_task_get_task_data (priv->current_task);
|
||
|
+
|
||
|
+ if (data->enroll_progress_cb)
|
||
|
+ {
|
||
|
+ data->enroll_progress_cb (device,
|
||
|
+ completed_stages,
|
||
|
+ print,
|
||
|
+ data->enroll_progress_data,
|
||
|
+ error);
|
||
|
+ }
|
||
|
+
|
||
|
+ g_clear_error (&error);
|
||
|
+ g_clear_object (&print);
|
||
|
+}
|
||
|
diff --git a/libfprint/meson.build b/libfprint/meson.build
|
||
|
index 1e98e2d..4a34cbd 100644
|
||
|
--- a/libfprint/meson.build
|
||
|
+++ b/libfprint/meson.build
|
||
|
@@ -8,6 +8,7 @@ libfprint_sources = [
|
||
|
|
||
|
libfprint_private_sources = [
|
||
|
'fpi-assembling.c',
|
||
|
+ 'fpi-device.c',
|
||
|
'fpi-ssm.c',
|
||
|
'fpi-usb-transfer.c',
|
||
|
'fpi-byte-reader.c',
|
||
|
--
|
||
|
2.24.1
|
||
|
|