228 lines
7.2 KiB
Diff
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
|
|
|