From 10e934e234cde597c92b27282dd7549995a7f7da Mon Sep 17 00:00:00 2001
From: Bastien Nocera <hadess@hadess.net>
Date: Wed, 5 Sep 2018 13:11:51 +0200
Subject: [PATCH] lib: Add fpi_ssm API documentation

---
 doc/libfprint-docs.xml     |   5 +-
 doc/libfprint-sections.txt |  22 +++++
 libfprint/fpi-ssm.c        | 166 ++++++++++++++++++++++++++++++-------
 libfprint/fpi-ssm.h        |  31 +++++--
 4 files changed, 183 insertions(+), 41 deletions(-)

diff --git a/doc/libfprint-docs.xml b/doc/libfprint-docs.xml
index e56f4b7..8f8622d 100644
--- a/doc/libfprint-docs.xml
+++ b/doc/libfprint-docs.xml
@@ -24,7 +24,7 @@
   </part>
 
   <part>
-    <title>API Documentation</title>
+    <title>Library API Documentation</title>
     <xi:include href="xml/events.xml"/>
     <xi:include href="xml/discovery.xml"/>
 
@@ -36,11 +36,10 @@
     <xi:include href="xml/img.xml"/>
   </part>
 
-  <!--
   <part>
     <title>Writing Drivers</title>
+    <xi:include href="xml/fpi-ssm.xml"/>
   </part>
-  -->
 
   <index id="api-index">
     <title>API Index</title>
diff --git a/doc/libfprint-sections.txt b/doc/libfprint-sections.txt
index a429495..332a8fa 100644
--- a/doc/libfprint-sections.txt
+++ b/doc/libfprint-sections.txt
@@ -140,3 +140,25 @@ fp_img_get_minutiae
 <INCLUDE>fprint.h</INCLUDE>
 <FILE>poll</FILE>
 </SECTION>
+
+<SECTION>
+<INCLUDE>fpi-ssm.h</INCLUDE>
+<FILE>fpi-ssm</FILE>
+fpi_ssm
+ssm_completed_fn
+ssm_handler_fn
+
+fpi_ssm_new
+fpi_ssm_free
+fpi_ssm_start
+fpi_ssm_start_subsm
+
+fpi_ssm_next_state
+fpi_ssm_jump_to_state
+fpi_ssm_mark_completed
+fpi_ssm_mark_aborted
+fpi_ssm_set_user_data
+fpi_ssm_get_user_data
+fpi_ssm_get_error
+fpi_ssm_get_cur_state
+</SECTION>
diff --git a/libfprint/fpi-ssm.c b/libfprint/fpi-ssm.c
index 0266989..aa6ad93 100644
--- a/libfprint/fpi-ssm.c
+++ b/libfprint/fpi-ssm.c
@@ -25,27 +25,31 @@
 #include <config.h>
 #include <errno.h>
 
-/* SSM: sequential state machine
+/**
+ * SECTION:fpi-ssm
+ * @title: Sequential state machine
+ *
  * Asynchronous driver design encourages some kind of state machine behind it.
  * In most cases, the state machine is entirely linear - you only go to the
- * next state, you never jump or go backwards. The SSM functions help you
+ * next state, you never jump or go backwards. The #fpi_ssm functions help you
  * implement such a machine.
  *
- * e.g. S1 --> S2 --> S3 --> S4
- * S1 is the start state
+ * e.g. `S1` ↦ `S2` ↦ `S3` ↦ `S4`
+ *
+ * `S1` is the start state
  * 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.
+ * implicit edges linking one state to every other state.
  *
- * To create a ssm, you pass a state handler function and the total number of
- * states (4 in the above example).
+ * To create an #fpi_ssm, you pass a state handler function and the total number of
+ * states (4 in the above example) to fpi_ssm_new(). Note that the state numbers
+ * start at zero, making them match the first value in a C enumeration.
  *
- * To start a ssm, you pass in a completion callback function which gets
- * called when the ssm completes (both on error and on failure).
+ * To start a ssm, you pass in a completion callback function to fpi_ssm_start()
+ * which gets called when the ssm completes (both on error and on failure).
  *
  * To iterate to the next state, call fpi_ssm_next_state(). It is legal to
  * attempt to iterate beyond the final state - this is equivalent to marking
@@ -57,21 +61,20 @@
  * To mark failed completion of a SSM, call fpi_ssm_mark_aborted() from any
  * state. You must pass a non-zero error code.
  *
- * Your state handling function looks at ssm->cur_state in order to determine
- * the current state and hence which operations to perform (a switch statement
- * is appropriate).
- * Typically, the state handling function fires off an asynchronous libusb
- * transfer, and the callback function iterates the machine to the next state
- * upon success (or aborts the machine on transfer failure).
+ * Your state handling function looks at the return value of
+ * fpi_ssm_get_cur_state() in order to determine the current state and hence
+ * which operations to perform (a switch statement is appropriate).
  *
- * Your completion callback should examine ssm->error in order to determine
- * whether the ssm completed or failed. An error code of zero indicates
- * successful completion.
+ * Typically, the state handling function fires off an asynchronous
+ * communication with the device (such as a libsub transfer), and the
+ * callback function iterates the machine to the next state
+ * upon success (or aborts the machine on failure).
+ *
+ * Your completion callback should examine the return value of
+ * fpi_ssm_get_error() in order to determine whether the #fpi_ssm completed or
+ * failed. An error code of zero indicates successful completion.
  */
 
-/* sequential state machine: state machine that iterates sequentially over
- * a predefined series of states. can be aborted by either completion or
- * abortion error conditions. */
 struct fpi_ssm {
 	struct fp_dev *dev;
 	fpi_ssm *parentsm;
@@ -84,7 +87,17 @@ struct fpi_ssm {
 	ssm_handler_fn handler;
 };
 
-/* Allocate a new ssm */
+/**
+ * fpi_ssm_new:
+ * @dev: a #fp_dev fingerprint device
+ * @handler: the callback function
+ * @nr_states: the number of states
+ *
+ * Allocate a new ssm, with @nr_states states. The @handler callback
+ * will be called after each state transition.
+ *
+ * Returns: a new #fpi_ssm state machine
+ */
 fpi_ssm *fpi_ssm_new(struct fp_dev *dev, ssm_handler_fn handler,
 	int nr_states)
 {
@@ -99,12 +112,29 @@ fpi_ssm *fpi_ssm_new(struct fp_dev *dev, ssm_handler_fn handler,
 	return machine;
 }
 
+/**
+ * fpi_ssm_get_dev:
+ * @machine: an #fpi_ssm state machine
+ *
+ * Returns the #fp_dev attached to the #fpi_ssm as passed
+ * in fpi_ssm_new().
+ *
+ * Returns: a struct #fp_dev
+ */
 struct fp_dev *
 fpi_ssm_get_dev(fpi_ssm *machine)
 {
 	return machine->dev;
 }
 
+/**
+ * fpi_ssm_set_user_data:
+ * @machine: an #fpi_ssm state machine
+ * @user_data: a pointer to user data
+ *
+ * Set a user data pointer in the #fpi_ssm structure, to be
+ * retrieved with fpi_ssm_get_user_data() at a later point.
+ */
 void
 fpi_ssm_set_user_data(fpi_ssm *machine,
 	void *user_data)
@@ -112,13 +142,28 @@ fpi_ssm_set_user_data(fpi_ssm *machine,
 	machine->priv = user_data;
 }
 
+/**
+ * fpi_ssm_get_user_data:
+ * @machine: an #fpi_ssm state machine
+ *
+ * Retrieve the pointer to user data set with
+ * fpi_ssm_set_user_data().
+ *
+ * Returns: a pointer
+ */
 void *
 fpi_ssm_get_user_data(fpi_ssm *machine)
 {
 	return machine->priv;
 }
 
-/* Free a ssm */
+/**
+ * fpi_ssm_free:
+ * @machine: an #fpi_ssm state machine
+ *
+ * Frees a state machine. This does not call any error or success
+ * callbacks, so you need to do this yourself.
+ */
 void fpi_ssm_free(fpi_ssm *machine)
 {
 	if (!machine)
@@ -133,7 +178,15 @@ static void __ssm_call_handler(fpi_ssm *machine)
 	machine->handler(machine);
 }
 
-/* Start a ssm. You can also restart a completed or aborted ssm. */
+/**
+ * fpi_ssm_start:
+ * @ssm: an #fpi_ssm state machine
+ * @callback: the #ssm_completed_fn callback to call on completion
+ *
+ * Starts a state machine. You can also use this function to restart
+ * a completed or aborted state machine. The @callback will be called
+ * on completion.
+ */
 void fpi_ssm_start(fpi_ssm *ssm, ssm_completed_fn callback)
 {
 	BUG_ON(!ssm->completed);
@@ -155,17 +208,30 @@ static void __subsm_complete(fpi_ssm *ssm)
 	fpi_ssm_free(ssm);
 }
 
-/* start a SSM as a child of another. if the child completes successfully, the
- * parent will be advanced to the next state. if the child aborts, the parent
- * will be aborted with the same error code. the child will be automatically
- * freed upon completion/abortion. */
+/**
+ * fpi_ssm_start_subsm:
+ * @parent: an #fpi_ssm state machine
+ * @child: an #fpi_ssm state machine
+ *
+ * Starts a state machine as a child of another. if the child completes
+ * successfully, the parent will be advanced to the next state. if the
+ * child aborts, the parent will be aborted with the same error code.
+ *
+ * The child will be automatically freed upon completion or abortion.
+ */
 void fpi_ssm_start_subsm(fpi_ssm *parent, fpi_ssm *child)
 {
 	child->parentsm = parent;
 	fpi_ssm_start(child, __subsm_complete);
 }
 
-/* Mark a ssm as completed successfully. */
+/**
+ * fpi_ssm_mark_completed:
+ * @machine: an #fpi_ssm state machine
+ *
+ * Mark a ssm as completed successfully. The callback set when creating
+ * the state machine with fpi_ssm_new() will be called synchronously.
+ */
 void fpi_ssm_mark_completed(fpi_ssm *machine)
 {
 	BUG_ON(machine->completed);
@@ -175,7 +241,13 @@ void fpi_ssm_mark_completed(fpi_ssm *machine)
 		machine->callback(machine);
 }
 
-/* Mark a ssm as aborted with error. */
+/**
+ * fpi_ssm_mark_aborted:
+ * @machine: an #fpi_ssm state machine
+ * @error: the error code
+ *
+ * Mark a state machine as aborted with error.
+ */
 void fpi_ssm_mark_aborted(fpi_ssm *machine, int error)
 {
 	fp_dbg("error %d from state %d", error, machine->cur_state);
@@ -184,7 +256,14 @@ void fpi_ssm_mark_aborted(fpi_ssm *machine, int error)
 	fpi_ssm_mark_completed(machine);
 }
 
-/* Iterate to next state of a ssm */
+/**
+ * fpi_ssm_next_state:
+ * @machine: an #fpi_ssm state machine
+ *
+ * Iterate to next state of a state machine. 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(fpi_ssm *machine)
 {
 	BUG_ON(machine->completed);
@@ -196,6 +275,12 @@ void fpi_ssm_next_state(fpi_ssm *machine)
 	}
 }
 
+/**
+ * fpi_ssm_jump_to_state:
+ * @machine: an #fpi_ssm state machine
+ * @state: the state to jump to
+ *
+ */
 void fpi_ssm_jump_to_state(fpi_ssm *machine, int state)
 {
 	BUG_ON(machine->completed);
@@ -204,11 +289,28 @@ void fpi_ssm_jump_to_state(fpi_ssm *machine, int state)
 	__ssm_call_handler(machine);
 }
 
+/**
+ * fpi_ssm_get_cur_state:
+ * @machine: an #fpi_ssm state machine
+ *
+ * Returns the value of the current state. Note that states are
+ * 0-indexed, so a value of 0 means “the first state”.
+ *
+ * Returns: the current state.
+ */
 int fpi_ssm_get_cur_state(fpi_ssm *machine)
 {
 	return machine->cur_state;
 }
 
+/**
+ * fpi_ssm_get_error:
+ * @machine: an #fpi_ssm state machine
+ *
+ * Returns the error code set by fpi_ssm_mark_aborted().
+ *
+ * Returns: a error code
+ */
 int fpi_ssm_get_error(fpi_ssm *machine)
 {
 	return machine->error;
diff --git a/libfprint/fpi-ssm.h b/libfprint/fpi-ssm.h
index ebc6b71..37a626b 100644
--- a/libfprint/fpi-ssm.h
+++ b/libfprint/fpi-ssm.h
@@ -30,19 +30,38 @@
 
 /* async drv <--> lib comms */
 
+/**
+ * fpi_ssm:
+ *
+ * Sequential state machine that iterates sequentially over
+ * a predefined series of states. Can be aborted by either completion or
+ * abortion error conditions.
+ */
 typedef struct fpi_ssm fpi_ssm;
-typedef void (*ssm_completed_fn)(fpi_ssm *ssm);
-typedef void (*ssm_handler_fn)(fpi_ssm *ssm);
 
-/* sequential state machine: state machine that iterates sequentially over
- * a predefined series of states. can be aborted by either completion or
- * abortion error conditions. */
+/**
+ * ssm_completed_fn:
+ * @ssm: a #fpi_ssm state machine
+ *
+ * The callback called when a state machine completes successfully,
+ * as set when calling fpi_ssm_start().
+ */
+typedef void (*ssm_completed_fn)(fpi_ssm *ssm);
+
+/**
+ * ssm_handler_fn:
+ * @ssm: a #fpi_ssm state machine
+ *
+ * The callback called when a state machine transitions from one
+ * state to the next, as set when calling fpi_ssm_new().
+ */
+typedef void (*ssm_handler_fn)(fpi_ssm *ssm);
 
 /* for library and drivers */
 fpi_ssm *fpi_ssm_new(struct fp_dev *dev, ssm_handler_fn handler,
 	int nr_states);
 void fpi_ssm_free(fpi_ssm *machine);
-void fpi_ssm_start(fpi_ssm *machine, ssm_completed_fn callback);
+void fpi_ssm_start(fpi_ssm *ssm, ssm_completed_fn callback);
 void fpi_ssm_start_subsm(fpi_ssm *parent, fpi_ssm *child);
 
 /* for drivers */