diff --git a/libfprint/drv.c b/libfprint/drv.c index 3055e99e..9ee54cfe 100644 --- a/libfprint/drv.c +++ b/libfprint/drv.c @@ -360,6 +360,7 @@ void fpi_ssm_free(struct fpi_ssm *machine) /* Invoke the state handler */ static void __ssm_call_handler(struct fpi_ssm *machine) { + fp_dbg("%p entering state %d", machine, machine->cur_state); machine->handler(machine); } @@ -374,11 +375,33 @@ void fpi_ssm_start(struct fpi_ssm *ssm, ssm_completed_fn callback) __ssm_call_handler(ssm); } +static void __subsm_complete(struct fpi_ssm *ssm) +{ + struct fpi_ssm *parent = ssm->parentsm; + BUG_ON(!parent); + if (ssm->error) + fpi_ssm_mark_aborted(parent, ssm->error); + else + fpi_ssm_next_state(parent); + 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. */ +void fpi_ssm_start_subsm(struct fpi_ssm *parent, struct fpi_ssm *child) +{ + child->parentsm = parent; + fpi_ssm_start(child, __subsm_complete); +} + /* Mark a ssm as completed successfully. */ void fpi_ssm_mark_completed(struct fpi_ssm *machine) { BUG_ON(machine->completed); machine->completed = TRUE; + fp_dbg("%p completed with status %d", machine, machine->error); if (machine->callback) machine->callback(machine); } diff --git a/libfprint/fp_internal.h b/libfprint/fp_internal.h index ee1230b9..e9676e86 100644 --- a/libfprint/fp_internal.h +++ b/libfprint/fp_internal.h @@ -338,6 +338,7 @@ typedef void (*ssm_handler_fn)(struct fpi_ssm *ssm); * abortion error conditions. */ struct fpi_ssm { struct fp_dev *dev; + struct fpi_ssm *parentsm; void *priv; int nr_states; int cur_state; @@ -353,6 +354,7 @@ struct fpi_ssm *fpi_ssm_new(struct fp_dev *dev, ssm_handler_fn handler, int nr_states); void fpi_ssm_free(struct fpi_ssm *machine); void fpi_ssm_start(struct fpi_ssm *machine, ssm_completed_fn callback); +void fpi_ssm_start_subsm(struct fpi_ssm *parent, struct fpi_ssm *child); int fpi_ssm_has_completed(struct fpi_ssm *machine); /* for drivers */