elan: Simplify elan driver internal state machine
The elan driver always "deactivates" the device after a cpature run. We can simplify the while internal state into a single "active" state and rely on the image device driving this state machine correctly. i.e.: * We start a callibrate/capture/deactivate when we go into the AWAIT_FINGER_ON state * We only store the fact that we are active and want to deactivate * We rely on the image device never going into the AWAIT_FINGER_ON state without first waiting for the finger to be off (which implies deactivation).
This commit is contained in:
parent
3ee5536a13
commit
a748f4d30f
2 changed files with 38 additions and 141 deletions
|
@ -73,22 +73,19 @@ struct _FpiDeviceElan
|
||||||
/* end commands */
|
/* end commands */
|
||||||
|
|
||||||
/* state */
|
/* state */
|
||||||
gboolean deactivating;
|
gboolean active;
|
||||||
FpiImageDeviceState dev_state;
|
gboolean deactivating;
|
||||||
FpiImageDeviceState dev_state_next;
|
unsigned char *last_read;
|
||||||
unsigned char *last_read;
|
unsigned char calib_atts_left;
|
||||||
unsigned char calib_atts_left;
|
unsigned char calib_status;
|
||||||
unsigned char calib_status;
|
unsigned short *background;
|
||||||
unsigned short *background;
|
unsigned char frame_width;
|
||||||
unsigned char frame_width;
|
unsigned char frame_height;
|
||||||
unsigned char frame_height;
|
unsigned char raw_frame_height;
|
||||||
unsigned char raw_frame_height;
|
int num_frames;
|
||||||
int num_frames;
|
GSList *frames;
|
||||||
GSList *frames;
|
|
||||||
/* end state */
|
/* end state */
|
||||||
};
|
};
|
||||||
G_DECLARE_FINAL_TYPE (FpiDeviceElan, fpi_device_elan, FPI, DEVICE_ELAN,
|
|
||||||
FpImageDevice);
|
|
||||||
G_DEFINE_TYPE (FpiDeviceElan, fpi_device_elan, FP_TYPE_IMAGE_DEVICE);
|
G_DEFINE_TYPE (FpiDeviceElan, fpi_device_elan, FP_TYPE_IMAGE_DEVICE);
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -487,7 +484,7 @@ stop_capture_complete (FpiSsm *ssm, FpDevice *_dev, GError *error)
|
||||||
|
|
||||||
|
|
||||||
/* The device is inactive at this point. */
|
/* The device is inactive at this point. */
|
||||||
self->dev_state = FPI_IMAGE_DEVICE_STATE_INACTIVE;
|
self->active = FALSE;
|
||||||
|
|
||||||
if (self->deactivating)
|
if (self->deactivating)
|
||||||
{
|
{
|
||||||
|
@ -505,16 +502,14 @@ stop_capture_complete (FpiSsm *ssm, FpDevice *_dev, GError *error)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
elan_stop_capture (FpDevice *dev)
|
elan_stop_capture (FpiDeviceElan *self)
|
||||||
{
|
{
|
||||||
FpiDeviceElan *self = FPI_DEVICE_ELAN (dev);
|
|
||||||
|
|
||||||
G_DEBUG_HERE ();
|
G_DEBUG_HERE ();
|
||||||
|
|
||||||
elan_dev_reset_state (self);
|
elan_dev_reset_state (self);
|
||||||
|
|
||||||
FpiSsm *ssm =
|
FpiSsm *ssm =
|
||||||
fpi_ssm_new (dev, stop_capture_run_state, STOP_CAPTURE_NUM_STATES);
|
fpi_ssm_new (FP_DEVICE (self), stop_capture_run_state, STOP_CAPTURE_NUM_STATES);
|
||||||
|
|
||||||
fpi_ssm_start (ssm, stop_capture_complete);
|
fpi_ssm_start (ssm, stop_capture_complete);
|
||||||
}
|
}
|
||||||
|
@ -545,8 +540,6 @@ capture_run_state (FpiSsm *ssm, FpDevice *dev)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CAPTURE_READ_DATA:
|
case CAPTURE_READ_DATA:
|
||||||
self->dev_state = FPI_IMAGE_DEVICE_STATE_CAPTURE;
|
|
||||||
|
|
||||||
/* 0x55 - finger present
|
/* 0x55 - finger present
|
||||||
* 0xff - device not calibrated (probably) */
|
* 0xff - device not calibrated (probably) */
|
||||||
if (self->last_read && self->last_read[0] == 0x55)
|
if (self->last_read && self->last_read[0] == 0x55)
|
||||||
|
@ -614,18 +607,17 @@ capture_complete (FpiSsm *ssm, FpDevice *_dev, GError *error)
|
||||||
fpi_image_device_session_error (dev, error);
|
fpi_image_device_session_error (dev, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
elan_stop_capture (self);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
elan_capture (FpDevice *dev)
|
elan_capture (FpiDeviceElan *self)
|
||||||
{
|
{
|
||||||
FpiDeviceElan *self = FPI_DEVICE_ELAN (dev);
|
|
||||||
|
|
||||||
G_DEBUG_HERE ();
|
G_DEBUG_HERE ();
|
||||||
|
|
||||||
elan_dev_reset_state (self);
|
elan_dev_reset_state (self);
|
||||||
FpiSsm *ssm =
|
FpiSsm *ssm =
|
||||||
fpi_ssm_new (dev, capture_run_state, CAPTURE_NUM_STATES);
|
fpi_ssm_new (FP_DEVICE (self), capture_run_state, CAPTURE_NUM_STATES);
|
||||||
|
|
||||||
fpi_ssm_start (ssm, capture_complete);
|
fpi_ssm_start (ssm, capture_complete);
|
||||||
}
|
}
|
||||||
|
@ -777,33 +769,31 @@ calibrate_run_state (FpiSsm *ssm, FpDevice *dev)
|
||||||
static void
|
static void
|
||||||
calibrate_complete (FpiSsm *ssm, FpDevice *dev, GError *error)
|
calibrate_complete (FpiSsm *ssm, FpDevice *dev, GError *error)
|
||||||
{
|
{
|
||||||
FpiDeviceElan *self = FPI_DEVICE_ELAN (dev);
|
|
||||||
|
|
||||||
G_DEBUG_HERE ();
|
G_DEBUG_HERE ();
|
||||||
|
|
||||||
if (error)
|
if (error)
|
||||||
{
|
{
|
||||||
self->dev_state = FPI_IMAGE_DEVICE_STATE_INACTIVE;
|
|
||||||
fpi_image_device_session_error (FP_IMAGE_DEVICE (dev), error);
|
fpi_image_device_session_error (FP_IMAGE_DEVICE (dev), error);
|
||||||
|
elan_stop_capture (FPI_DEVICE_ELAN (dev));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
elan_capture (dev);
|
elan_capture (FPI_DEVICE_ELAN (dev));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
elan_calibrate (FpDevice *dev)
|
elan_calibrate (FpiDeviceElan *self)
|
||||||
{
|
{
|
||||||
FpiDeviceElan *self = FPI_DEVICE_ELAN (dev);
|
|
||||||
|
|
||||||
G_DEBUG_HERE ();
|
G_DEBUG_HERE ();
|
||||||
|
|
||||||
elan_dev_reset_state (self);
|
elan_dev_reset_state (self);
|
||||||
|
|
||||||
|
g_return_if_fail (!self->active);
|
||||||
|
self->active = TRUE;
|
||||||
self->calib_atts_left = ELAN_CALIBRATION_ATTEMPTS;
|
self->calib_atts_left = ELAN_CALIBRATION_ATTEMPTS;
|
||||||
|
|
||||||
FpiSsm *ssm = fpi_ssm_new (FP_DEVICE (dev), calibrate_run_state,
|
FpiSsm *ssm = fpi_ssm_new (FP_DEVICE (self), calibrate_run_state,
|
||||||
CALIBRATE_NUM_STATES);
|
CALIBRATE_NUM_STATES);
|
||||||
|
|
||||||
fpi_ssm_start (ssm, calibrate_complete);
|
fpi_ssm_start (ssm, calibrate_complete);
|
||||||
|
@ -958,106 +948,15 @@ dev_activate (FpImageDevice *dev)
|
||||||
elan_activate (dev);
|
elan_activate (dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
elan_change_state (FpImageDevice *idev)
|
|
||||||
{
|
|
||||||
FpDevice *dev = FP_DEVICE (idev);
|
|
||||||
FpiDeviceElan *self = FPI_DEVICE_ELAN (dev);
|
|
||||||
FpiImageDeviceState next_state = self->dev_state_next;
|
|
||||||
|
|
||||||
if (self->dev_state == next_state)
|
|
||||||
{
|
|
||||||
fp_dbg ("already in %d", next_state);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
fp_dbg ("changing to %d", next_state);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (next_state)
|
|
||||||
{
|
|
||||||
case FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON:
|
|
||||||
/* activation completed or another enroll stage started */
|
|
||||||
self->dev_state = FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON;
|
|
||||||
elan_calibrate (dev);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case FPI_IMAGE_DEVICE_STATE_IDLE:
|
|
||||||
case FPI_IMAGE_DEVICE_STATE_ACTIVATING:
|
|
||||||
case FPI_IMAGE_DEVICE_STATE_INACTIVE:
|
|
||||||
case FPI_IMAGE_DEVICE_STATE_CAPTURE:
|
|
||||||
/* not used */
|
|
||||||
break;
|
|
||||||
|
|
||||||
case FPI_IMAGE_DEVICE_STATE_DEACTIVATING:
|
|
||||||
case FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_OFF:
|
|
||||||
elan_stop_capture (dev);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
elan_change_state_async (FpDevice *dev,
|
|
||||||
void *data)
|
|
||||||
{
|
|
||||||
fp_dbg ("state change dev: %p", dev);
|
|
||||||
elan_change_state (FP_IMAGE_DEVICE (dev));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
dev_change_state (FpImageDevice *dev, FpiImageDeviceState state)
|
dev_change_state (FpImageDevice *dev, FpiImageDeviceState state)
|
||||||
{
|
{
|
||||||
FpiDeviceElan *self = FPI_DEVICE_ELAN (dev);
|
FpiDeviceElan *self = FPI_DEVICE_ELAN (dev);
|
||||||
GSource *timeout;
|
|
||||||
|
|
||||||
G_DEBUG_HERE ();
|
G_DEBUG_HERE ();
|
||||||
|
|
||||||
/* Inactive and await finger off are equivalent for the elan driver. */
|
if (state == FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON)
|
||||||
if (state == FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_OFF)
|
elan_calibrate (self);
|
||||||
state = FPI_IMAGE_DEVICE_STATE_DEACTIVATING;
|
|
||||||
|
|
||||||
/* The internal state may already be inactive, ignore deactivation then. */
|
|
||||||
if (self->dev_state_next == FPI_IMAGE_DEVICE_STATE_INACTIVE &&
|
|
||||||
state == FPI_IMAGE_DEVICE_STATE_DEACTIVATING)
|
|
||||||
state = FPI_IMAGE_DEVICE_STATE_INACTIVE;
|
|
||||||
|
|
||||||
if (self->dev_state_next == state)
|
|
||||||
{
|
|
||||||
fp_dbg ("change to state %d already queued", state);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (state)
|
|
||||||
{
|
|
||||||
case FPI_IMAGE_DEVICE_STATE_DEACTIVATING:
|
|
||||||
case FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_ON:
|
|
||||||
case FPI_IMAGE_DEVICE_STATE_AWAIT_FINGER_OFF: {
|
|
||||||
char *name;
|
|
||||||
|
|
||||||
/* schedule state change instead of calling it directly to allow all actions
|
|
||||||
* related to the previous state to complete */
|
|
||||||
self->dev_state_next = state;
|
|
||||||
timeout = fpi_device_add_timeout (FP_DEVICE (dev), 10,
|
|
||||||
elan_change_state_async,
|
|
||||||
NULL, NULL);
|
|
||||||
|
|
||||||
name = g_strdup_printf ("dev_change_state to %d", state);
|
|
||||||
g_source_set_name (timeout, name);
|
|
||||||
g_free (name);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case FPI_IMAGE_DEVICE_STATE_IDLE:
|
|
||||||
case FPI_IMAGE_DEVICE_STATE_ACTIVATING:
|
|
||||||
case FPI_IMAGE_DEVICE_STATE_INACTIVE:
|
|
||||||
case FPI_IMAGE_DEVICE_STATE_CAPTURE:
|
|
||||||
/* TODO MAYBE: split capture ssm into smaller ssms and use this state */
|
|
||||||
self->dev_state = state;
|
|
||||||
self->dev_state_next = state;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -1067,19 +966,14 @@ dev_deactivate (FpImageDevice *dev)
|
||||||
|
|
||||||
G_DEBUG_HERE ();
|
G_DEBUG_HERE ();
|
||||||
|
|
||||||
if (self->dev_state == FPI_IMAGE_DEVICE_STATE_INACTIVE)
|
if (!self->active)
|
||||||
{
|
/* The device is inactive already, complete the operation immediately. */
|
||||||
/* The device is inactive already, complete the operation immediately. */
|
fpi_image_device_deactivate_complete (dev, NULL);
|
||||||
fpi_image_device_deactivate_complete (dev, NULL);
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
/* The device is not yet inactive, flag that we are deactivating (and
|
||||||
/* The device is not yet inactive, flag that we are deactivating (and
|
* need to signal back deactivation).
|
||||||
* need to signal back deactivation) and then ensure we will change
|
* Note that any running capture will be cancelled already if needed. */
|
||||||
* to the inactive state eventually. */
|
self->deactivating = TRUE;
|
||||||
self->deactivating = TRUE;
|
|
||||||
dev_change_state (dev, FPI_IMAGE_DEVICE_STATE_DEACTIVATING);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
|
@ -70,6 +70,9 @@
|
||||||
#define ELAN_CMD_TIMEOUT 10000
|
#define ELAN_CMD_TIMEOUT 10000
|
||||||
#define ELAN_FINGER_TIMEOUT 200
|
#define ELAN_FINGER_TIMEOUT 200
|
||||||
|
|
||||||
|
G_DECLARE_FINAL_TYPE (FpiDeviceElan, fpi_device_elan, FPI, DEVICE_ELAN,
|
||||||
|
FpImageDevice);
|
||||||
|
|
||||||
struct elan_cmd
|
struct elan_cmd
|
||||||
{
|
{
|
||||||
unsigned char cmd[ELAN_CMD_LEN];
|
unsigned char cmd[ELAN_CMD_LEN];
|
||||||
|
@ -218,8 +221,8 @@ static void elan_cmd_done (FpiSsm *ssm);
|
||||||
static void elan_cmd_read (FpiSsm *ssm,
|
static void elan_cmd_read (FpiSsm *ssm,
|
||||||
FpDevice *dev);
|
FpDevice *dev);
|
||||||
|
|
||||||
static void elan_calibrate (FpDevice *dev);
|
static void elan_calibrate (FpiDeviceElan *self);
|
||||||
static void elan_capture (FpDevice *dev);
|
static void elan_capture (FpiDeviceElan *self);
|
||||||
|
|
||||||
static void dev_change_state (FpImageDevice *dev,
|
static void dev_change_state (FpImageDevice *dev,
|
||||||
FpiImageDeviceState state);
|
FpiImageDeviceState state);
|
||||||
|
|
Loading…
Reference in a new issue