mirror of
https://gitlab.freedesktop.org/libfprint/libfprint.git
synced 2025-11-15 07:38:12 +00:00
Introduce an early reporting mechanism for verify and match
It is a good idea to report match results early, to e.g. log in a user
immediately even if more device interaction is needed. Add new _full
variants for the verify/identify functions, with a corresponding
callback. Also move driver result reporting into new
fpi_device_{identify,verify}_report functions and remove the reporting
from the fpi_device_{identify,verify}_complete calls.
Basic updates to code is done in places. Only the upekts driver is
actually modified from a behaviour point of view. The image driver code
should be restructured quite a bit to split the reporting and only
report completion after device deactivation. This should simplifiy the
code quite a bit again.
This commit is contained in:
@@ -420,6 +420,23 @@ enroll_data_free (FpEnrollData *data)
|
||||
g_free (data);
|
||||
}
|
||||
|
||||
void
|
||||
match_data_free (FpMatchData *data)
|
||||
{
|
||||
g_clear_object (&data->print);
|
||||
g_clear_object (&data->match);
|
||||
g_clear_error (&data->error);
|
||||
|
||||
if (data->match_destroy)
|
||||
data->match_destroy (data->match_data);
|
||||
data->match_data = NULL;
|
||||
|
||||
g_clear_object (&data->enrolled_print);
|
||||
g_clear_pointer (&data->gallery, g_ptr_array_unref);
|
||||
|
||||
g_free (data);
|
||||
}
|
||||
|
||||
/**
|
||||
* fpi_device_get_enroll_data:
|
||||
* @device: The #FpDevice
|
||||
@@ -476,12 +493,16 @@ fpi_device_get_verify_data (FpDevice *device,
|
||||
FpPrint **print)
|
||||
{
|
||||
FpDevicePrivate *priv = fp_device_get_instance_private (device);
|
||||
FpMatchData *data;
|
||||
|
||||
g_return_if_fail (FP_IS_DEVICE (device));
|
||||
g_return_if_fail (priv->current_action == FPI_DEVICE_ACTION_VERIFY);
|
||||
|
||||
data = g_task_get_task_data (priv->current_task);
|
||||
g_assert (data);
|
||||
|
||||
if (print)
|
||||
*print = g_task_get_task_data (priv->current_task);
|
||||
*print = data->enrolled_print;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -496,12 +517,16 @@ fpi_device_get_identify_data (FpDevice *device,
|
||||
GPtrArray **prints)
|
||||
{
|
||||
FpDevicePrivate *priv = fp_device_get_instance_private (device);
|
||||
FpMatchData *data;
|
||||
|
||||
g_return_if_fail (FP_IS_DEVICE (device));
|
||||
g_return_if_fail (priv->current_action == FPI_DEVICE_ACTION_IDENTIFY);
|
||||
|
||||
data = g_task_get_task_data (priv->current_task);
|
||||
g_assert (data);
|
||||
|
||||
if (prints)
|
||||
*prints = g_task_get_task_data (priv->current_task);
|
||||
*prints = data->gallery;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -596,11 +621,11 @@ fpi_device_action_error (FpDevice *device,
|
||||
break;
|
||||
|
||||
case FPI_DEVICE_ACTION_VERIFY:
|
||||
fpi_device_verify_complete (device, FPI_MATCH_ERROR, NULL, error);
|
||||
fpi_device_verify_complete (device, error);
|
||||
break;
|
||||
|
||||
case FPI_DEVICE_ACTION_IDENTIFY:
|
||||
fpi_device_identify_complete (device, NULL, NULL, error);
|
||||
fpi_device_identify_complete (device, error);
|
||||
break;
|
||||
|
||||
case FPI_DEVICE_ACTION_CAPTURE:
|
||||
@@ -907,67 +932,65 @@ fpi_device_enroll_complete (FpDevice *device, FpPrint *print, GError *error)
|
||||
/**
|
||||
* fpi_device_verify_complete:
|
||||
* @device: The #FpDevice
|
||||
* @result: The #FpiMatchResult of the operation
|
||||
* @print: (transfer floating) The scanned #FpPrint
|
||||
* @error: A #GError if result is %FPI_MATCH_ERROR
|
||||
*
|
||||
* Finish an ongoing verify operation. The returned print should be
|
||||
* representing the new scan and not the one passed for verification.
|
||||
*
|
||||
* Note that @error should only be set for actual errors. In the case
|
||||
* of retry errors, report these using fpi_device_verify_report()
|
||||
* and then call this function without any error argument.
|
||||
*/
|
||||
void
|
||||
fpi_device_verify_complete (FpDevice *device,
|
||||
FpiMatchResult result,
|
||||
FpPrint *print,
|
||||
GError *error)
|
||||
fpi_device_verify_complete (FpDevice *device,
|
||||
GError *error)
|
||||
{
|
||||
FpDevicePrivate *priv = fp_device_get_instance_private (device);
|
||||
FpMatchData *data;
|
||||
|
||||
g_return_if_fail (FP_IS_DEVICE (device));
|
||||
g_return_if_fail (priv->current_action == FPI_DEVICE_ACTION_VERIFY);
|
||||
|
||||
g_debug ("Device reported verify completion");
|
||||
|
||||
data = g_task_get_task_data (priv->current_task);
|
||||
|
||||
clear_device_cancel_action (device);
|
||||
|
||||
if (print)
|
||||
g_object_ref_sink (print);
|
||||
|
||||
g_object_set_data_full (G_OBJECT (priv->current_task),
|
||||
"print",
|
||||
print,
|
||||
g_object_unref);
|
||||
|
||||
if (!error)
|
||||
{
|
||||
if (result != FPI_MATCH_ERROR)
|
||||
if (!data->result_reported)
|
||||
{
|
||||
fpi_device_return_task_in_idle (device, FP_DEVICE_TASK_RETURN_INT,
|
||||
GINT_TO_POINTER (result));
|
||||
g_warning ("Driver reported successful verify complete but did not report the result earlier. Reporting error instead");
|
||||
fpi_device_return_task_in_idle (device, FP_DEVICE_TASK_RETURN_ERROR,
|
||||
fpi_device_error_new (FP_DEVICE_ERROR_GENERAL));
|
||||
}
|
||||
else if (data->error)
|
||||
{
|
||||
fpi_device_return_task_in_idle (device, FP_DEVICE_TASK_RETURN_ERROR, g_steal_pointer (&data->error));
|
||||
}
|
||||
else
|
||||
{
|
||||
g_warning ("Driver did not provide an error for a failed verify operation!");
|
||||
error = fpi_device_error_new_msg (FP_DEVICE_ERROR_GENERAL,
|
||||
"Driver failed to provide an error!");
|
||||
fpi_device_return_task_in_idle (device, FP_DEVICE_TASK_RETURN_ERROR, error);
|
||||
fpi_device_return_task_in_idle (device, FP_DEVICE_TASK_RETURN_INT,
|
||||
GINT_TO_POINTER (data->match != NULL ? FPI_MATCH_SUCCESS : FPI_MATCH_FAIL));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fpi_device_return_task_in_idle (device, FP_DEVICE_TASK_RETURN_ERROR, error);
|
||||
if (result != FPI_MATCH_ERROR)
|
||||
/* Replace a retry error with a general error, this is a driver bug. */
|
||||
if (error->domain == FP_DEVICE_RETRY)
|
||||
{
|
||||
g_warning ("Driver passed an error but also provided a match result, returning error!");
|
||||
g_object_unref (print);
|
||||
g_warning ("Driver reported a retry error to fpi_device_verify_complete; reporting operation failure instead!");
|
||||
g_clear_error (&error);
|
||||
error = fpi_device_error_new (FP_DEVICE_ERROR_GENERAL);
|
||||
}
|
||||
fpi_device_return_task_in_idle (device, FP_DEVICE_TASK_RETURN_ERROR, error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* fpi_device_identify_complete:
|
||||
* @device: The #FpDevice
|
||||
* @match: (transfer none): The matching #FpPrint from the passed gallery, or %NULL if none matched
|
||||
* @print: (transfer floating): The scanned #FpPrint, may be %NULL
|
||||
* @error: The #GError or %NULL on success
|
||||
*
|
||||
* Finish an ongoing identify operation. The match that was identified is
|
||||
@@ -976,46 +999,47 @@ fpi_device_verify_complete (FpDevice *device,
|
||||
*/
|
||||
void
|
||||
fpi_device_identify_complete (FpDevice *device,
|
||||
FpPrint *match,
|
||||
FpPrint *print,
|
||||
GError *error)
|
||||
{
|
||||
FpDevicePrivate *priv = fp_device_get_instance_private (device);
|
||||
FpMatchData *data;
|
||||
|
||||
g_return_if_fail (FP_IS_DEVICE (device));
|
||||
g_return_if_fail (priv->current_action == FPI_DEVICE_ACTION_IDENTIFY);
|
||||
|
||||
g_debug ("Device reported identify completion");
|
||||
|
||||
data = g_task_get_task_data (priv->current_task);
|
||||
|
||||
clear_device_cancel_action (device);
|
||||
|
||||
if (match)
|
||||
g_object_ref (match);
|
||||
|
||||
if (print)
|
||||
g_object_ref_sink (print);
|
||||
|
||||
g_object_set_data_full (G_OBJECT (priv->current_task),
|
||||
"print",
|
||||
print,
|
||||
g_object_unref);
|
||||
g_object_set_data_full (G_OBJECT (priv->current_task),
|
||||
"match",
|
||||
match,
|
||||
g_object_unref);
|
||||
if (!error)
|
||||
{
|
||||
fpi_device_return_task_in_idle (device, FP_DEVICE_TASK_RETURN_BOOL,
|
||||
GUINT_TO_POINTER (TRUE));
|
||||
if (!data->result_reported)
|
||||
{
|
||||
g_warning ("Driver reported successful identify complete but did not report the result earlier. Reporting error instead");
|
||||
fpi_device_return_task_in_idle (device, FP_DEVICE_TASK_RETURN_ERROR,
|
||||
fpi_device_error_new (FP_DEVICE_ERROR_GENERAL));
|
||||
}
|
||||
else if (data->error)
|
||||
{
|
||||
fpi_device_return_task_in_idle (device, FP_DEVICE_TASK_RETURN_ERROR, g_steal_pointer (&data->error));
|
||||
}
|
||||
else
|
||||
{
|
||||
fpi_device_return_task_in_idle (device, FP_DEVICE_TASK_RETURN_INT, GINT_TO_POINTER (TRUE));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fpi_device_return_task_in_idle (device, FP_DEVICE_TASK_RETURN_ERROR, error);
|
||||
if (match)
|
||||
/* Replace a retry error with a general error, this is a driver bug. */
|
||||
if (error->domain == FP_DEVICE_RETRY)
|
||||
{
|
||||
g_warning ("Driver passed an error but also provided a match result, returning error!");
|
||||
g_clear_object (&match);
|
||||
g_warning ("Driver reported a retry error to fpi_device_identify_complete; reporting operation failure instead!");
|
||||
g_clear_error (&error);
|
||||
error = fpi_device_error_new (FP_DEVICE_ERROR_GENERAL);
|
||||
}
|
||||
fpi_device_return_task_in_idle (device, FP_DEVICE_TASK_RETURN_ERROR, error);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1187,3 +1211,151 @@ fpi_device_enroll_progress (FpDevice *device,
|
||||
g_clear_error (&error);
|
||||
g_clear_object (&print);
|
||||
}
|
||||
|
||||
/**
|
||||
* fpi_device_verify_report:
|
||||
* @device: The #FpDevice
|
||||
* @result: The #FpiMatchResult of the operation
|
||||
* @print: (transfer floating) The scanned #FpPrint
|
||||
* @error: A #GError if result is %FPI_MATCH_ERROR
|
||||
*
|
||||
* Report the result of a verify operation. Note that the passed @error must be
|
||||
* a retry error with the %FP_DEVICE_RETRY domain. For all other error cases,
|
||||
* the error should passed to fpi_device_verify_complete().
|
||||
*/
|
||||
void
|
||||
fpi_device_verify_report (FpDevice *device,
|
||||
FpiMatchResult result,
|
||||
FpPrint *print,
|
||||
GError *error)
|
||||
{
|
||||
FpDevicePrivate *priv = fp_device_get_instance_private (device);
|
||||
FpMatchData *data = g_task_get_task_data (priv->current_task);
|
||||
gboolean call_cb = TRUE;
|
||||
|
||||
g_return_if_fail (FP_IS_DEVICE (device));
|
||||
g_return_if_fail (priv->current_action == FPI_DEVICE_ACTION_VERIFY);
|
||||
g_return_if_fail (data->result_reported == FALSE);
|
||||
|
||||
data->result_reported = TRUE;
|
||||
|
||||
g_debug ("Device reported verify result");
|
||||
|
||||
if (print)
|
||||
print = g_object_ref_sink (print);
|
||||
|
||||
if (error || result == FPI_MATCH_ERROR)
|
||||
{
|
||||
if (result != FPI_MATCH_ERROR)
|
||||
g_warning ("Driver reported an error code without setting match result to error!");
|
||||
|
||||
if (error == NULL)
|
||||
{
|
||||
g_warning ("Driver reported an error without specifying a retry code, assuming general retry error!");
|
||||
error = fpi_device_retry_new (FP_DEVICE_RETRY_GENERAL);
|
||||
}
|
||||
|
||||
if (print)
|
||||
{
|
||||
g_warning ("Driver reported a print together with an error!");
|
||||
g_clear_object (&print);
|
||||
}
|
||||
|
||||
data->error = error;
|
||||
|
||||
if (error->domain != FP_DEVICE_RETRY)
|
||||
{
|
||||
g_warning ("Driver reported a verify error that was not in the retry domain, delaying report!");
|
||||
call_cb = FALSE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (result == FPI_MATCH_SUCCESS)
|
||||
{
|
||||
fpi_device_get_verify_data (device, &data->match);
|
||||
g_object_ref (data->match);
|
||||
}
|
||||
|
||||
data->print = g_steal_pointer (&print);
|
||||
}
|
||||
|
||||
if (call_cb && data->match_cb)
|
||||
data->match_cb (device, data->error == NULL, data->match, data->print, data->match_data, data->error);
|
||||
}
|
||||
|
||||
/**
|
||||
* fpi_device_identify_report:
|
||||
* @device: The #FpDevice
|
||||
* @match: (transfer none): The #FpPrint from the gallery that matched
|
||||
* @print: (transfer floating): The scanned #FpPrint
|
||||
* @error: A #GError if result is %FPI_MATCH_ERROR
|
||||
*
|
||||
* Report the result of a identify operation. Note that the passed @error must be
|
||||
* a retry error with the %FP_DEVICE_RETRY domain. For all other error cases,
|
||||
* the error should passed to fpi_device_identify_complete().
|
||||
*/
|
||||
void
|
||||
fpi_device_identify_report (FpDevice *device,
|
||||
FpPrint *match,
|
||||
FpPrint *print,
|
||||
GError *error)
|
||||
{
|
||||
FpDevicePrivate *priv = fp_device_get_instance_private (device);
|
||||
FpMatchData *data = g_task_get_task_data (priv->current_task);
|
||||
gboolean call_cb = TRUE;
|
||||
|
||||
g_return_if_fail (FP_IS_DEVICE (device));
|
||||
g_return_if_fail (priv->current_action == FPI_DEVICE_ACTION_IDENTIFY);
|
||||
g_return_if_fail (data->result_reported == FALSE);
|
||||
|
||||
data->result_reported = TRUE;
|
||||
|
||||
if (match)
|
||||
g_object_ref (match);
|
||||
|
||||
if (print)
|
||||
print = g_object_ref_sink (print);
|
||||
|
||||
if (match && !g_ptr_array_find (data->gallery, match, NULL))
|
||||
{
|
||||
g_warning ("Driver reported a match to a print that was not in the gallery, ignoring match.");
|
||||
g_clear_object (&match);
|
||||
}
|
||||
|
||||
g_debug ("Device reported identify result");
|
||||
|
||||
if (error)
|
||||
{
|
||||
if (match != NULL)
|
||||
{
|
||||
g_warning ("Driver reported an error code but also provided a match!");
|
||||
g_clear_object (&match);
|
||||
}
|
||||
|
||||
if (print)
|
||||
{
|
||||
g_warning ("Driver reported a print together with an error!");
|
||||
g_clear_object (&print);
|
||||
}
|
||||
|
||||
data->error = error;
|
||||
|
||||
if (error->domain != FP_DEVICE_RETRY)
|
||||
{
|
||||
g_warning ("Driver reported a verify error that was not in the retry domain, delaying report!");
|
||||
call_cb = FALSE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (match)
|
||||
data->match = g_steal_pointer (&match);
|
||||
|
||||
if (print)
|
||||
data->print = g_steal_pointer (&print);
|
||||
}
|
||||
|
||||
if (call_cb && data->match_cb)
|
||||
data->match_cb (device, data->error == NULL, data->match, data->print, data->match_data, data->error);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user