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;