From f3d17a24f921ac15369e1a20c35f9b41de69a8ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Fri, 26 Jun 2026 14:16:02 +0200 Subject: [PATCH] egis_etu905: Decouple SSM and command data from device While most of commands should run separated, others such as cancellation can run concurrently so we cannot share command data in the device structure, but it has to be rather per command. Move it there --- libfprint/drivers/egismoc/egis_etu905.c | 74 +++++++++++-------------- 1 file changed, 33 insertions(+), 41 deletions(-) diff --git a/libfprint/drivers/egismoc/egis_etu905.c b/libfprint/drivers/egismoc/egis_etu905.c index 84c6dd4b..3827df8f 100644 --- a/libfprint/drivers/egismoc/egis_etu905.c +++ b/libfprint/drivers/egismoc/egis_etu905.c @@ -29,12 +29,10 @@ struct _FpiDeviceEgisEtu905 { - FpDevice parent; - FpiSsm *task_ssm; - FpiSsm *cmd_ssm; - FpiUsbTransfer *cmd_transfer; - GPtrArray *enrolled_ids; - gint max_enroll_stages; + FpDevice parent; + FpiSsm *task_ssm; + GPtrArray *enrolled_ids; + gint max_enroll_stages; }; G_DEFINE_TYPE (FpiDeviceEgisEtu905, fpi_device_egis_etu905, FP_TYPE_DEVICE); @@ -53,6 +51,7 @@ typedef void (*SynCmdMsgCallback) (FpDevice *device, typedef struct egis_etu905_command_data { SynCmdMsgCallback callback; + FpiUsbTransfer *cmd_transfer; guchar *buffer_in; gsize length_in; } CommandData; @@ -60,6 +59,7 @@ typedef struct egis_etu905_command_data static void egis_etu905_command_data_free (CommandData *data) { + g_clear_pointer (&data->cmd_transfer, fpi_usb_transfer_unref); g_free (data->buffer_in); g_free (data); } @@ -248,15 +248,16 @@ egis_etu905_cmd_run_state (FpiSsm *ssm, FpDevice *device) { g_autoptr(FpiUsbTransfer) transfer = NULL; - FpiDeviceEgisEtu905 *self = FPI_DEVICE_EGIS_ETU905 (device); + CommandData *data = fpi_ssm_get_data (ssm); switch (fpi_ssm_get_cur_state (ssm)) { case CMD_SEND: - if (self->cmd_transfer) + if (data->cmd_transfer) { - self->cmd_transfer->ssm = ssm; - fpi_usb_transfer_submit (g_steal_pointer (&self->cmd_transfer), + transfer = g_steal_pointer (&data->cmd_transfer); + transfer->ssm = ssm; + fpi_usb_transfer_submit (g_steal_pointer (&transfer), EGIS_ETU905_USB_SEND_TIMEOUT, fpi_device_get_cancellable (device), fpi_ssm_usb_transfer_cb, @@ -291,15 +292,8 @@ egis_etu905_cmd_ssm_done (FpiSsm *ssm, GError *error) { g_autoptr(GError) local_error = error; - FpiDeviceEgisEtu905 *self = FPI_DEVICE_EGIS_ETU905 (device); CommandData *data = fpi_ssm_get_data (ssm); - g_assert (self->cmd_ssm == ssm); - g_assert (!self->cmd_transfer || self->cmd_transfer->ssm == ssm); - - self->cmd_ssm = NULL; - self->cmd_transfer = NULL; - if (data && data->callback) { data->callback (device, @@ -338,8 +332,8 @@ egis_etu905_exec_cmd (FpDevice *device, { g_auto(FpiByteWriter) writer = {0}; g_autoptr(FpiUsbTransfer) transfer = NULL; - FpiDeviceEgisEtu905 *self = FPI_DEVICE_EGIS_ETU905 (device); g_autofree CommandData *data = NULL; + FpiSsm *ssm = NULL; gsize buffer_out_length = 0; gboolean written = TRUE; guint16 check_value; @@ -382,37 +376,35 @@ egis_etu905_exec_cmd (FpDevice *device, if (cmd_destroy) g_clear_pointer (&cmd, cmd_destroy); - g_assert (self->cmd_ssm == NULL); - self->cmd_ssm = fpi_ssm_new (device, - egis_etu905_cmd_run_state, - CMD_STATES); - + /* The command runs on its own dedicated SSM, carrying all its state (the + * outgoing transfer and the response buffer) via the SSM data. Nothing is + * shared on the device instance, so commands issued from different contexts + * (e.g. an in-progress operation and a cancellation) cannot collide. */ data = g_new0 (CommandData, 1); data->callback = callback; - fpi_ssm_set_data (self->cmd_ssm, g_steal_pointer (&data), - (GDestroyNotify) egis_etu905_command_data_free); - if (!written) + if (written) { - fpi_ssm_start (self->cmd_ssm, egis_etu905_cmd_ssm_done); - fpi_ssm_mark_failed (self->cmd_ssm, - fpi_device_error_new (FP_DEVICE_ERROR_PROTO)); - return; + transfer = fpi_usb_transfer_new (device); + fpi_usb_transfer_set_short_error (transfer, TRUE); + + fpi_usb_transfer_fill_bulk_full (transfer, + EGIS_ETU905_EP_CMD_OUT, + fpi_byte_writer_reset_and_get_data (&writer), + buffer_out_length, + g_free); + + data->cmd_transfer = g_steal_pointer (&transfer); } - transfer = fpi_usb_transfer_new (device); - fpi_usb_transfer_set_short_error (transfer, TRUE); - transfer->ssm = self->cmd_ssm; + ssm = fpi_ssm_new (device, egis_etu905_cmd_run_state, CMD_STATES); + fpi_ssm_set_data (ssm, g_steal_pointer (&data), + (GDestroyNotify) egis_etu905_command_data_free); - fpi_usb_transfer_fill_bulk_full (transfer, - EGIS_ETU905_EP_CMD_OUT, - fpi_byte_writer_reset_and_get_data (&writer), - buffer_out_length, - g_free); + fpi_ssm_start (ssm, egis_etu905_cmd_ssm_done); - g_assert (self->cmd_transfer == NULL); - self->cmd_transfer = g_steal_pointer (&transfer); - fpi_ssm_start (self->cmd_ssm, egis_etu905_cmd_ssm_done); + if (!written) + fpi_ssm_mark_failed (ssm, fpi_device_error_new (FP_DEVICE_ERROR_PROTO)); } static void