Blame SOURCES/0105-fp-device-Move-fpi-code-into-its-own-unit-that-can-b.patch

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