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.
This commit is contained in:
Marco Trevisan (Treviño)
2026-07-23 14:36:02 +02:00
parent 87a7023831
commit 833d39ab59
+41 -14
View File
@@ -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;