From 833d39ab59f8ed65892de2a94699e667efdf2264 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Thu, 23 Jul 2026 14:13:23 +0200 Subject: [PATCH] aes2550: Complete deactivation from dev_deactivate on broken loops The driver relied on a running finger-detection or capture callback to observe the deactivating flag and call complete_deactivation(). When the async loop was broken by a session error from a terminal callback (such as capture_sm_complete), no further iteration was left to notice the flag, so the deactivation never completed. Rather than scatter complete_deactivation() calls after every fpi_image_device_session_error(), track whether an operation is actually pending with an "active" flag and let dev_deactivate() complete the request itself when nothing is in flight. This keeps the deactivation lifecycle owned by dev_deactivate. --- libfprint/drivers/aes2550.c | 55 +++++++++++++++++++++++++++---------- 1 file changed, 41 insertions(+), 14 deletions(-) diff --git a/libfprint/drivers/aes2550.c b/libfprint/drivers/aes2550.c index 950f5d14..6c432e78 100644 --- a/libfprint/drivers/aes2550.c +++ b/libfprint/drivers/aes2550.c @@ -57,6 +57,7 @@ struct _FpiDeviceAes2550 GSList *strips; size_t strips_len; + gboolean active; gboolean deactivating; int heartbeat_cnt; }; @@ -91,14 +92,21 @@ finger_det_data_cb (FpiUsbTransfer *transfer, FpDevice *device, gpointer user_data, GError *error) { FpImageDevice *dev = FP_IMAGE_DEVICE (device); + FpiDeviceAes2550 *self = FPI_DEVICE_AES2550 (device); unsigned char *data = transfer->buffer; if (error) { - /* Ensure deactivation completes even though the finger-detect - * loop is broken by the session error. */ - fpi_image_device_session_error (dev, error); - complete_deactivation (dev); + /* The finger-detect loop is broken; it no longer has a pending + * operation. Clear the active flag so that the deactivation + * triggered by the session error (or an in-flight cancellation) + * can complete. */ + self->active = FALSE; + + if (self->deactivating) + complete_deactivation (dev); + else + fpi_image_device_session_error (dev, error); return; } @@ -125,13 +133,20 @@ finger_det_reqs_cb (FpiUsbTransfer *t, FpDevice *device, { FpiUsbTransfer *transfer; FpImageDevice *dev = FP_IMAGE_DEVICE (device); + FpiDeviceAes2550 *self = FPI_DEVICE_AES2550 (device); if (error) { - /* Ensure deactivation completes even though the finger-detect - * loop is broken by the session error. */ - fpi_image_device_session_error (dev, error); - complete_deactivation (dev); + /* The finger-detect loop is broken; it no longer has a pending + * operation. Clear the active flag so that the deactivation + * triggered by the session error (or an in-flight cancellation) + * can complete. */ + self->active = FALSE; + + if (self->deactivating) + complete_deactivation (dev); + else + fpi_image_device_session_error (dev, error); return; } @@ -383,12 +398,12 @@ capture_sm_complete (FpiSsm *ssm, FpDevice *_dev, GError *error) } else if (error) { - /* fpi_image_device_session_error() will trigger dev_deactivate() - * which sets the deactivating flag. Since the SSM is terminating, - * complete_deactivation() must be called here to avoid a deadlock - * where nothing checks the deactivating flag. */ + /* The capture SSM has terminated, so no completion handler is left + * to observe the deactivation that the session error triggers. + * Clear the active flag so dev_deactivate() completes it directly. + */ + self->active = FALSE; fpi_image_device_session_error (dev, error); - complete_deactivation (dev); } else { @@ -506,12 +521,16 @@ activate_run_state (FpiSsm *ssm, FpDevice *dev) static void activate_sm_complete (FpiSsm *ssm, FpDevice *_dev, GError *error) { + FpiDeviceAes2550 *self = FPI_DEVICE_AES2550 (_dev); FpImageDevice *dev = FP_IMAGE_DEVICE (_dev); fpi_image_device_activate_complete (dev, error); if (!error) - start_finger_detection (dev); + { + self->active = TRUE; + start_finger_detection (dev); + } } static void @@ -528,6 +547,13 @@ dev_deactivate (FpImageDevice *dev) { FpiDeviceAes2550 *self = FPI_DEVICE_AES2550 (dev); + if (!self->active) + { + /* No operation is pending, so complete it right away. */ + complete_deactivation (dev); + return; + } + self->deactivating = TRUE; } @@ -539,6 +565,7 @@ complete_deactivation (FpImageDevice *dev) G_DEBUG_HERE (); self->deactivating = FALSE; + self->active = FALSE; g_slist_free (self->strips); self->strips = NULL; self->strips_len = 0;