From 0aaffcee33015163d79320433cfd9d9c5941143a Mon Sep 17 00:00:00 2001
From: Daniel Drake <dsd@cs.manchester.ac.uk>
Date: Fri, 15 Feb 2008 18:09:14 +0000
Subject: [PATCH] Allow jumping to arbitrary state in a SSM

This is looking less and less like a simple state machine now, but it's
proving a useful model!
---
 libfprint/drv.c         | 15 ++++++++++++++-
 libfprint/fp_internal.h |  1 +
 2 files changed, 15 insertions(+), 1 deletion(-)

diff --git a/libfprint/drv.c b/libfprint/drv.c
index bb92126..f1cc6c5 100644
--- a/libfprint/drv.c
+++ b/libfprint/drv.c
@@ -297,6 +297,11 @@ void fpi_drvcb_identify_stopped(struct fp_dev *dev)
  * There is also an implicit error state and an implicit accepting state
  * (both with implicit edges from every state).
  *
+ * You can also jump to any arbitrary state (while marking completion of the
+ * current state) while the machine is running. In other words there are
+ * implicit edges linking one state to every other state. OK, we're stretching
+ * the "state machine" description at this point.
+ *
  * To create a ssm, you pass a state handler function and the total number of
  * states (4 in the above example).
  *
@@ -377,7 +382,7 @@ void fpi_ssm_mark_completed(struct fpi_ssm *machine)
 /* Mark a ssm as aborted with error. */
 void fpi_ssm_mark_aborted(struct fpi_ssm *machine, int error)
 {
-	fp_dbg("error %d", error);
+	fp_dbg("error %d from state %d", error, machine->cur_state);
 	BUG_ON(error == 0);
 	machine->error = error;
 	fpi_ssm_mark_completed(machine);
@@ -395,3 +400,11 @@ void fpi_ssm_next_state(struct fpi_ssm *machine)
 	}
 }
 
+void fpi_ssm_jump_to_state(struct fpi_ssm *machine, int state)
+{
+	BUG_ON(machine->completed);
+	BUG_ON(state >= machine->nr_states);
+	machine->cur_state = state;
+	__ssm_call_handler(machine);
+}
+
diff --git a/libfprint/fp_internal.h b/libfprint/fp_internal.h
index 6164672..dc6a503 100644
--- a/libfprint/fp_internal.h
+++ b/libfprint/fp_internal.h
@@ -349,6 +349,7 @@ int fpi_ssm_has_completed(struct fpi_ssm *machine);
 
 /* for drivers */
 void fpi_ssm_next_state(struct fpi_ssm *machine);
+void fpi_ssm_jump_to_state(struct fpi_ssm *machine, int state);
 void fpi_ssm_mark_completed(struct fpi_ssm *machine);
 void fpi_ssm_mark_aborted(struct fpi_ssm *machine, int error);