lib: Add fpi_ssm API documentation
This commit is contained in:
parent
48b9e6c517
commit
10e934e234
4 changed files with 183 additions and 41 deletions
|
@ -24,7 +24,7 @@
|
||||||
</part>
|
</part>
|
||||||
|
|
||||||
<part>
|
<part>
|
||||||
<title>API Documentation</title>
|
<title>Library API Documentation</title>
|
||||||
<xi:include href="xml/events.xml"/>
|
<xi:include href="xml/events.xml"/>
|
||||||
<xi:include href="xml/discovery.xml"/>
|
<xi:include href="xml/discovery.xml"/>
|
||||||
|
|
||||||
|
@ -36,11 +36,10 @@
|
||||||
<xi:include href="xml/img.xml"/>
|
<xi:include href="xml/img.xml"/>
|
||||||
</part>
|
</part>
|
||||||
|
|
||||||
<!--
|
|
||||||
<part>
|
<part>
|
||||||
<title>Writing Drivers</title>
|
<title>Writing Drivers</title>
|
||||||
|
<xi:include href="xml/fpi-ssm.xml"/>
|
||||||
</part>
|
</part>
|
||||||
-->
|
|
||||||
|
|
||||||
<index id="api-index">
|
<index id="api-index">
|
||||||
<title>API Index</title>
|
<title>API Index</title>
|
||||||
|
|
|
@ -140,3 +140,25 @@ fp_img_get_minutiae
|
||||||
<INCLUDE>fprint.h</INCLUDE>
|
<INCLUDE>fprint.h</INCLUDE>
|
||||||
<FILE>poll</FILE>
|
<FILE>poll</FILE>
|
||||||
</SECTION>
|
</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>
|
||||||
|
|
|
@ -25,27 +25,31 @@
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
#include <errno.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.
|
* 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
|
* 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.
|
* implement such a machine.
|
||||||
*
|
*
|
||||||
* e.g. S1 --> S2 --> S3 --> S4
|
* e.g. `S1` ↦ `S2` ↦ `S3` ↦ `S4`
|
||||||
* S1 is the start state
|
*
|
||||||
|
* `S1` is the start state
|
||||||
* There is also an implicit error state and an implicit accepting state
|
* There is also an implicit error state and an implicit accepting state
|
||||||
* (both with implicit edges from every state).
|
* (both with implicit edges from every state).
|
||||||
*
|
*
|
||||||
* You can also jump to any arbitrary state (while marking completion of the
|
* 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
|
* 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
|
* implicit edges linking one state to every other state.
|
||||||
* the "state machine" description at this point.
|
|
||||||
*
|
*
|
||||||
* To create a ssm, you pass a state handler function and the total number of
|
* To create an #fpi_ssm, you pass a state handler function and the total number of
|
||||||
* states (4 in the above example).
|
* 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
|
* To start a ssm, you pass in a completion callback function to fpi_ssm_start()
|
||||||
* called when the ssm completes (both on error and on failure).
|
* 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
|
* 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
|
* 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
|
* To mark failed completion of a SSM, call fpi_ssm_mark_aborted() from any
|
||||||
* state. You must pass a non-zero error code.
|
* state. You must pass a non-zero error code.
|
||||||
*
|
*
|
||||||
* Your state handling function looks at ssm->cur_state in order to determine
|
* Your state handling function looks at the return value of
|
||||||
* the current state and hence which operations to perform (a switch statement
|
* fpi_ssm_get_cur_state() in order to determine the current state and hence
|
||||||
* is appropriate).
|
* 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 completion callback should examine ssm->error in order to determine
|
* Typically, the state handling function fires off an asynchronous
|
||||||
* whether the ssm completed or failed. An error code of zero indicates
|
* communication with the device (such as a libsub transfer), and the
|
||||||
* successful completion.
|
* 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 fpi_ssm {
|
||||||
struct fp_dev *dev;
|
struct fp_dev *dev;
|
||||||
fpi_ssm *parentsm;
|
fpi_ssm *parentsm;
|
||||||
|
@ -84,7 +87,17 @@ struct fpi_ssm {
|
||||||
ssm_handler_fn handler;
|
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,
|
fpi_ssm *fpi_ssm_new(struct fp_dev *dev, ssm_handler_fn handler,
|
||||||
int nr_states)
|
int nr_states)
|
||||||
{
|
{
|
||||||
|
@ -99,12 +112,29 @@ fpi_ssm *fpi_ssm_new(struct fp_dev *dev, ssm_handler_fn handler,
|
||||||
return machine;
|
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 *
|
struct fp_dev *
|
||||||
fpi_ssm_get_dev(fpi_ssm *machine)
|
fpi_ssm_get_dev(fpi_ssm *machine)
|
||||||
{
|
{
|
||||||
return machine->dev;
|
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
|
void
|
||||||
fpi_ssm_set_user_data(fpi_ssm *machine,
|
fpi_ssm_set_user_data(fpi_ssm *machine,
|
||||||
void *user_data)
|
void *user_data)
|
||||||
|
@ -112,13 +142,28 @@ fpi_ssm_set_user_data(fpi_ssm *machine,
|
||||||
machine->priv = user_data;
|
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 *
|
void *
|
||||||
fpi_ssm_get_user_data(fpi_ssm *machine)
|
fpi_ssm_get_user_data(fpi_ssm *machine)
|
||||||
{
|
{
|
||||||
return machine->priv;
|
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)
|
void fpi_ssm_free(fpi_ssm *machine)
|
||||||
{
|
{
|
||||||
if (!machine)
|
if (!machine)
|
||||||
|
@ -133,7 +178,15 @@ static void __ssm_call_handler(fpi_ssm *machine)
|
||||||
machine->handler(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)
|
void fpi_ssm_start(fpi_ssm *ssm, ssm_completed_fn callback)
|
||||||
{
|
{
|
||||||
BUG_ON(!ssm->completed);
|
BUG_ON(!ssm->completed);
|
||||||
|
@ -155,17 +208,30 @@ static void __subsm_complete(fpi_ssm *ssm)
|
||||||
fpi_ssm_free(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
|
* fpi_ssm_start_subsm:
|
||||||
* will be aborted with the same error code. the child will be automatically
|
* @parent: an #fpi_ssm state machine
|
||||||
* freed upon completion/abortion. */
|
* @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)
|
void fpi_ssm_start_subsm(fpi_ssm *parent, fpi_ssm *child)
|
||||||
{
|
{
|
||||||
child->parentsm = parent;
|
child->parentsm = parent;
|
||||||
fpi_ssm_start(child, __subsm_complete);
|
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)
|
void fpi_ssm_mark_completed(fpi_ssm *machine)
|
||||||
{
|
{
|
||||||
BUG_ON(machine->completed);
|
BUG_ON(machine->completed);
|
||||||
|
@ -175,7 +241,13 @@ void fpi_ssm_mark_completed(fpi_ssm *machine)
|
||||||
machine->callback(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)
|
void fpi_ssm_mark_aborted(fpi_ssm *machine, int error)
|
||||||
{
|
{
|
||||||
fp_dbg("error %d from state %d", error, machine->cur_state);
|
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);
|
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)
|
void fpi_ssm_next_state(fpi_ssm *machine)
|
||||||
{
|
{
|
||||||
BUG_ON(machine->completed);
|
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)
|
void fpi_ssm_jump_to_state(fpi_ssm *machine, int state)
|
||||||
{
|
{
|
||||||
BUG_ON(machine->completed);
|
BUG_ON(machine->completed);
|
||||||
|
@ -204,11 +289,28 @@ void fpi_ssm_jump_to_state(fpi_ssm *machine, int state)
|
||||||
__ssm_call_handler(machine);
|
__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)
|
int fpi_ssm_get_cur_state(fpi_ssm *machine)
|
||||||
{
|
{
|
||||||
return machine->cur_state;
|
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)
|
int fpi_ssm_get_error(fpi_ssm *machine)
|
||||||
{
|
{
|
||||||
return machine->error;
|
return machine->error;
|
||||||
|
|
|
@ -30,19 +30,38 @@
|
||||||
|
|
||||||
/* async drv <--> lib comms */
|
/* 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 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
|
* ssm_completed_fn:
|
||||||
* abortion error conditions. */
|
* @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 */
|
/* for library and drivers */
|
||||||
fpi_ssm *fpi_ssm_new(struct fp_dev *dev, ssm_handler_fn handler,
|
fpi_ssm *fpi_ssm_new(struct fp_dev *dev, ssm_handler_fn handler,
|
||||||
int nr_states);
|
int nr_states);
|
||||||
void fpi_ssm_free(fpi_ssm *machine);
|
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);
|
void fpi_ssm_start_subsm(fpi_ssm *parent, fpi_ssm *child);
|
||||||
|
|
||||||
/* for drivers */
|
/* for drivers */
|
||||||
|
|
Loading…
Reference in a new issue