From 7b683443942299629d0e1839a7f55537a8eb389f Mon Sep 17 00:00:00 2001 From: Benjamin Berg Date: Wed, 4 Dec 2019 15:50:06 +0100 Subject: [PATCH] image-device: Prevent deactivation when waiting for finger At the end of enroll, the image device would put the driver into the AWAIT_FINGER_ON state and then deactivate the device afterwards. Doing this adds additional complexity to drivers which would need to handle both cancellation and normal deactivation from that state. Only put the device into the AWAIT_FINGER_ON state when we know that another enroll stage is needed. This avoids the critical state transition simplifying the driver state machine. Fixes: #203 Fixes: 689aff023253e4ca970c9f76f9e4209188175d3d --- libfprint/fp-image-device.c | 31 ++++++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/libfprint/fp-image-device.c b/libfprint/fp-image-device.c index e45b6a9..26c3cb0 100644 --- a/libfprint/fp-image-device.c +++ b/libfprint/fp-image-device.c @@ -51,6 +51,7 @@ typedef struct FpImageDeviceState state; gboolean active; + gboolean enroll_await_on_pending; gint enroll_stage; guint pending_activation_timeout_id; @@ -256,6 +257,7 @@ fp_image_device_start_capture_action (FpDevice *device) } priv->enroll_stage = 0; + priv->enroll_await_on_pending = FALSE; /* The device might still be deactivating from a previous call. * In that situation, try to wait for a bit before reporting back an @@ -385,6 +387,22 @@ fp_image_device_init (FpImageDevice *self) } +static void +fp_image_device_enroll_maybe_await_finger_on (FpImageDevice *self) +{ + FpImageDevicePrivate *priv = fp_image_device_get_instance_private (self); + + if (priv->enroll_await_on_pending) + { + priv->enroll_await_on_pending = FALSE; + fp_image_device_change_state (self, FP_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON); + } + else + { + priv->enroll_await_on_pending = TRUE; + } +} + static void fpi_image_device_minutiae_detected (GObject *source_object, GAsyncResult *res, gpointer user_data) { @@ -446,11 +464,16 @@ fpi_image_device_minutiae_detected (GObject *source_object, GAsyncResult *res, g fpi_device_enroll_progress (device, priv->enroll_stage, g_steal_pointer (&print), error); + /* Start another scan or deactivate. */ if (priv->enroll_stage == IMG_ENROLL_STAGES) { fpi_device_enroll_complete (device, g_object_ref (enroll_print), NULL); fp_image_device_deactivate (device); } + else + { + fp_image_device_enroll_maybe_await_finger_on (FP_IMAGE_DEVICE (device)); + } } else if (action == FP_DEVICE_ACTION_VERIFY) { @@ -572,13 +595,15 @@ fpi_image_device_report_finger_status (FpImageDevice *self, * 2. We are still deactivating the device after an action completed * 3. We were waiting for finger removal to start the new action * Either way, we always end up deactivating except for the enroll case. - * XXX: This is not quite correct though, as we assume we need another finger - * scan even though we might be processing the last one (successfully). + * + * The enroll case is special as AWAIT_FINGER_ON should only happen after + * minutiae detection to prevent deactivation (without cancellation) + * from the AWAIT_FINGER_ON state. */ if (action != FP_DEVICE_ACTION_ENROLL) fp_image_device_deactivate (device); else - fp_image_device_change_state (self, FP_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON); + fp_image_device_enroll_maybe_await_finger_on (self); } }