libfprint/SOURCES/0058-fpi-ssm-Add-possibilit...

228 lines
7.2 KiB
Diff

From d35cadd5fd81067bfc5bf6f5595b98d4227ad190 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= <mail@3v1n0.net>
Date: Fri, 22 Nov 2019 17:19:27 +0100
Subject: [PATCH 058/181] fpi-ssm: Add possibility to jump to a state (or next
one) with delay
This allows to have an automatic cleanup of the timeout source when the
the callback is reached and to avoid to do further state changes in the
middle.
---
doc/libfprint-sections.txt | 3 +
libfprint/fpi-ssm.c | 118 +++++++++++++++++++++++++++++++++++++
libfprint/fpi-ssm.h | 6 ++
3 files changed, 127 insertions(+)
diff --git a/doc/libfprint-sections.txt b/doc/libfprint-sections.txt
index 0abe584..9fb01bd 100644
--- a/doc/libfprint-sections.txt
+++ b/doc/libfprint-sections.txt
@@ -215,7 +215,10 @@ fpi_ssm_free
fpi_ssm_start
fpi_ssm_start_subsm
fpi_ssm_next_state
+fpi_ssm_next_state_delayed
fpi_ssm_jump_to_state
+fpi_ssm_jump_to_state_delayed
+fpi_ssm_cancel_delayed_state_change
fpi_ssm_mark_completed
fpi_ssm_mark_failed
fpi_ssm_set_data
diff --git a/libfprint/fpi-ssm.c b/libfprint/fpi-ssm.c
index 5299e2d..38186d2 100644
--- a/libfprint/fpi-ssm.c
+++ b/libfprint/fpi-ssm.c
@@ -87,6 +87,7 @@ struct _FpiSsm
int nr_states;
int cur_state;
gboolean completed;
+ GSource *timeout;
GError *error;
FpiSsmCompletedCallback callback;
FpiSsmHandlerCallback handler;
@@ -170,6 +171,7 @@ fpi_ssm_free (FpiSsm *machine)
if (machine->ssm_data_destroy)
g_clear_pointer (&machine->ssm_data, machine->ssm_data_destroy);
g_clear_pointer (&machine->error, g_error_free);
+ g_clear_pointer (&machine->timeout, g_source_destroy);
g_free (machine);
}
@@ -231,7 +233,9 @@ __subsm_complete (FpiSsm *ssm, FpDevice *_dev, GError *error)
void
fpi_ssm_start_subsm (FpiSsm *parent, FpiSsm *child)
{
+ BUG_ON (parent->timeout);
child->parentsm = parent;
+ g_clear_pointer (&parent->timeout, g_source_destroy);
fpi_ssm_start (child, __subsm_complete);
}
@@ -246,7 +250,12 @@ void
fpi_ssm_mark_completed (FpiSsm *machine)
{
BUG_ON (machine->completed);
+ BUG_ON (machine->timeout);
+ BUG_ON (machine->timeout != NULL);
+
+ g_clear_pointer (&machine->timeout, g_source_destroy);
machine->completed = TRUE;
+
if (machine->error)
fp_dbg ("%p completed with error: %s", machine, machine->error->message);
else
@@ -297,6 +306,10 @@ fpi_ssm_next_state (FpiSsm *machine)
g_return_if_fail (machine != NULL);
BUG_ON (machine->completed);
+ BUG_ON (machine->timeout != NULL);
+
+ g_clear_pointer (&machine->timeout, g_source_destroy);
+
machine->cur_state++;
if (machine->cur_state == machine->nr_states)
fpi_ssm_mark_completed (machine);
@@ -304,6 +317,56 @@ fpi_ssm_next_state (FpiSsm *machine)
__ssm_call_handler (machine);
}
+void
+fpi_ssm_cancel_delayed_state_change (FpiSsm *machine)
+{
+ g_return_if_fail (machine);
+ BUG_ON (machine->completed);
+ BUG_ON (machine->timeout == NULL);
+
+ g_clear_pointer (&machine->timeout, g_source_destroy);
+}
+
+static void
+on_device_timeout_next_state (FpDevice *dev,
+ gpointer user_data)
+{
+ FpiSsm *machine = user_data;
+
+ machine->timeout = NULL;
+ fpi_ssm_next_state (machine);
+}
+
+/**
+ * fpi_ssm_next_state_delayed:
+ * @machine: an #FpiSsm state machine
+ * @delay: the milliseconds to wait before switching to the next state
+ *
+ * Iterate to next state of a state machine with a delay of @delay ms. If the
+ * current state is the last state, then the state machine will be marked as
+ * completed, as if calling fpi_ssm_mark_completed().
+ */
+void
+fpi_ssm_next_state_delayed (FpiSsm *machine,
+ int delay)
+{
+ g_autofree char *source_name = NULL;
+
+ g_return_if_fail (machine != NULL);
+ BUG_ON (machine->completed);
+ BUG_ON (machine->timeout != NULL);
+
+ g_clear_pointer (&machine->timeout, g_source_destroy);
+ machine->timeout = fpi_device_add_timeout (machine->dev, delay,
+ on_device_timeout_next_state,
+ machine);
+
+ source_name = g_strdup_printf ("[%s] ssm %p jump to next state %d",
+ fp_device_get_device_id (machine->dev),
+ machine, machine->cur_state + 1);
+ g_source_set_name (machine->timeout, source_name);
+}
+
/**
* fpi_ssm_jump_to_state:
* @machine: an #FpiSsm state machine
@@ -318,10 +381,65 @@ fpi_ssm_jump_to_state (FpiSsm *machine, int state)
{
BUG_ON (machine->completed);
BUG_ON (state < 0 || state >= machine->nr_states);
+ BUG_ON (machine->timeout != NULL);
+
+ g_clear_pointer (&machine->timeout, g_source_destroy);
machine->cur_state = state;
__ssm_call_handler (machine);
}
+typedef struct
+{
+ FpiSsm *machine;
+ int next_state;
+} FpiSsmJumpToStateDelayedData;
+
+static void
+on_device_timeout_jump_to_state (FpDevice *dev,
+ gpointer user_data)
+{
+ FpiSsmJumpToStateDelayedData *data = user_data;
+
+ data->machine->timeout = NULL;
+ fpi_ssm_jump_to_state (data->machine, data->next_state);
+}
+
+/**
+ * fpi_ssm_jump_to_state_delayed:
+ * @machine: an #FpiSsm state machine
+ * @state: the state to jump to
+ * @delay: the milliseconds to wait before switching to @state state
+ *
+ * Jump to the @state state with a delay of @delay milliseconds, bypassing
+ * intermediary states.
+ */
+void
+fpi_ssm_jump_to_state_delayed (FpiSsm *machine,
+ int state,
+ int delay)
+{
+ FpiSsmJumpToStateDelayedData *data;
+ g_autofree char *source_name = NULL;
+
+ g_return_if_fail (machine != NULL);
+ BUG_ON (machine->completed);
+ BUG_ON (machine->timeout != NULL);
+
+ data = g_new0 (FpiSsmJumpToStateDelayedData, 1);
+ data->machine = machine;
+ data->next_state = state;
+
+ g_clear_pointer (&machine->timeout, g_source_destroy);
+ machine->timeout = fpi_device_add_timeout_full (machine->dev, delay,
+ on_device_timeout_jump_to_state,
+ data, g_free);
+
+ source_name = g_strdup_printf ("[%s] ssm %p jump to state %d",
+ fp_device_get_device_id (machine->dev),
+ machine, state);
+ g_source_set_name (machine->timeout, source_name);
+}
+
/**
* fpi_ssm_get_cur_state:
* @machine: an #FpiSsm state machine
diff --git a/libfprint/fpi-ssm.h b/libfprint/fpi-ssm.h
index 57e7d10..05e6cf0 100644
--- a/libfprint/fpi-ssm.h
+++ b/libfprint/fpi-ssm.h
@@ -73,6 +73,12 @@ void fpi_ssm_start_subsm (FpiSsm *parent,
void fpi_ssm_next_state (FpiSsm *machine);
void fpi_ssm_jump_to_state (FpiSsm *machine,
int state);
+void fpi_ssm_next_state_delayed (FpiSsm *machine,
+ int delay);
+void fpi_ssm_jump_to_state_delayed (FpiSsm *machine,
+ int state,
+ int delay);
+void fpi_ssm_cancel_delayed_state_change (FpiSsm *machine);
void fpi_ssm_mark_completed (FpiSsm *machine);
void fpi_ssm_mark_failed (FpiSsm *machine,
GError *error);
--
2.24.1