elan: Use IMGDEV_STATE_* events instead of pre-set capture path
This commit is contained in:
parent
c3b1c982bc
commit
b28b006d61
2 changed files with 109 additions and 53 deletions
|
@ -69,7 +69,8 @@ struct elan_dev {
|
||||||
/* end commands */
|
/* end commands */
|
||||||
|
|
||||||
/* state */
|
/* state */
|
||||||
gboolean deactivating;
|
enum fp_imgdev_state dev_state;
|
||||||
|
enum fp_imgdev_state 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;
|
||||||
|
@ -96,7 +97,6 @@ static void elan_dev_reset(struct elan_dev *elandev)
|
||||||
elandev->cmd = NULL;
|
elandev->cmd = NULL;
|
||||||
elandev->cmd_timeout = ELAN_CMD_TIMEOUT;
|
elandev->cmd_timeout = ELAN_CMD_TIMEOUT;
|
||||||
|
|
||||||
elandev->deactivating = FALSE;
|
|
||||||
elandev->calib_status = 0;
|
elandev->calib_status = 0;
|
||||||
|
|
||||||
g_free(elandev->last_read);
|
g_free(elandev->last_read);
|
||||||
|
@ -314,6 +314,7 @@ static void elan_cmd_cb(struct libusb_transfer *transfer)
|
||||||
case LIBUSB_TRANSFER_CANCELLED:
|
case LIBUSB_TRANSFER_CANCELLED:
|
||||||
fp_dbg("transfer cancelled");
|
fp_dbg("transfer cancelled");
|
||||||
fpi_ssm_mark_aborted(ssm, -ECANCELED);
|
fpi_ssm_mark_aborted(ssm, -ECANCELED);
|
||||||
|
elan_deactivate(dev);
|
||||||
break;
|
break;
|
||||||
case LIBUSB_TRANSFER_TIMED_OUT:
|
case LIBUSB_TRANSFER_TIMED_OUT:
|
||||||
fp_dbg("transfer timed out");
|
fp_dbg("transfer timed out");
|
||||||
|
@ -377,8 +378,7 @@ static void elan_run_cmd(struct fpi_ssm *ssm, const struct elan_cmd *cmd,
|
||||||
if (cmd_timeout != -1)
|
if (cmd_timeout != -1)
|
||||||
elandev->cmd_timeout = cmd_timeout;
|
elandev->cmd_timeout = cmd_timeout;
|
||||||
|
|
||||||
if (elandev->dev_type && cmd->devices
|
if (cmd->devices != ELAN_ALL_DEV && !(cmd->devices & elandev->dev_type)) {
|
||||||
&& !(cmd->devices & elandev->dev_type)) {
|
|
||||||
fp_dbg("skipping for this device");
|
fp_dbg("skipping for this device");
|
||||||
elan_cmd_done(ssm);
|
elan_cmd_done(ssm);
|
||||||
return;
|
return;
|
||||||
|
@ -463,10 +463,11 @@ static void capture_run_state(struct fpi_ssm *ssm)
|
||||||
/* 0x55 - finger present
|
/* 0x55 - finger present
|
||||||
* 0xff - device not calibrated (probably) */
|
* 0xff - device not calibrated (probably) */
|
||||||
if (elandev->last_read && elandev->last_read[0] == 0x55) {
|
if (elandev->last_read && elandev->last_read[0] == 0x55) {
|
||||||
|
if (elandev->dev_state == IMGDEV_STATE_AWAIT_FINGER_ON)
|
||||||
fpi_imgdev_report_finger_status(dev, TRUE);
|
fpi_imgdev_report_finger_status(dev, TRUE);
|
||||||
elan_run_cmd(ssm, &get_image_cmd, ELAN_CMD_TIMEOUT);
|
elan_run_cmd(ssm, &get_image_cmd, ELAN_CMD_TIMEOUT);
|
||||||
} else
|
} else
|
||||||
fpi_ssm_mark_aborted(ssm, FP_VERIFY_RETRY);
|
fpi_ssm_mark_aborted(ssm, -EBADMSG);
|
||||||
break;
|
break;
|
||||||
case CAPTURE_CHECK_ENOUGH_FRAMES:
|
case CAPTURE_CHECK_ENOUGH_FRAMES:
|
||||||
elan_save_img_frame(elandev);
|
elan_save_img_frame(elandev);
|
||||||
|
@ -481,11 +482,6 @@ static void capture_run_state(struct fpi_ssm *ssm)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void elan_capture_async(void *data)
|
|
||||||
{
|
|
||||||
elan_capture((struct fp_img_dev *)data);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void capture_complete(struct fpi_ssm *ssm)
|
static void capture_complete(struct fpi_ssm *ssm)
|
||||||
{
|
{
|
||||||
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
|
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
|
||||||
|
@ -493,36 +489,38 @@ static void capture_complete(struct fpi_ssm *ssm)
|
||||||
|
|
||||||
G_DEBUG_HERE();
|
G_DEBUG_HERE();
|
||||||
|
|
||||||
if (elandev->deactivating)
|
if (fpi_ssm_get_error(ssm) == -ECANCELED) {
|
||||||
elan_deactivate(dev);
|
fpi_ssm_free(ssm);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* either max frames captured or timed out waiting for the next frame */
|
/* either max frames captured or timed out waiting for the next frame */
|
||||||
else if (!fpi_ssm_get_error(ssm)
|
if (!fpi_ssm_get_error(ssm)
|
||||||
|| (fpi_ssm_get_error(ssm) == -ETIMEDOUT
|
|| (fpi_ssm_get_error(ssm) == -ETIMEDOUT
|
||||||
&& fpi_ssm_get_cur_state(ssm) == CAPTURE_WAIT_FINGER))
|
&& fpi_ssm_get_cur_state(ssm) == CAPTURE_WAIT_FINGER))
|
||||||
if (elandev->num_frames >= ELAN_MIN_FRAMES) {
|
if (elandev->num_frames >= ELAN_MIN_FRAMES)
|
||||||
elan_submit_image(dev);
|
elan_submit_image(dev);
|
||||||
fpi_imgdev_report_finger_status(dev, FALSE);
|
else {
|
||||||
} else {
|
|
||||||
fp_dbg("swipe too short: want >= %d frames, got %d",
|
fp_dbg("swipe too short: want >= %d frames, got %d",
|
||||||
ELAN_MIN_FRAMES, elandev->num_frames);
|
ELAN_MIN_FRAMES, elandev->num_frames);
|
||||||
fpi_imgdev_session_error(dev,
|
fpi_imgdev_abort_scan(dev, FP_VERIFY_RETRY_TOO_SHORT);
|
||||||
FP_VERIFY_RETRY_TOO_SHORT);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* other error
|
/* other error
|
||||||
* It says "...session_error" but repotring 1 during verification
|
* It says "...abort_scan" but reporting 1 during verification makes it
|
||||||
* makes it successful! */
|
* successful! */
|
||||||
else
|
else
|
||||||
fpi_imgdev_session_error(dev, FP_VERIFY_NO_MATCH);
|
fpi_imgdev_abort_scan(dev, fpi_ssm_get_error(ssm));
|
||||||
|
|
||||||
/* When enrolling the lib won't restart the capture after a stage has
|
/* this procedure must be called regardless of outcome because it advances
|
||||||
* completed, so we need to keep feeding it images till it's had enough.
|
* dev_state to AWAIT_FINGER_ON under the hood... */
|
||||||
* But after that it can't finalize enrollemnt until this callback exits.
|
fpi_imgdev_report_finger_status(dev, FALSE);
|
||||||
* That's why we schedule elan_capture instead of running it directly. */
|
|
||||||
if (fpi_dev_get_dev_state(fpi_imgdev_get_dev(dev)) == DEV_STATE_ENROLLING
|
/* ...but only on enroll! If verify or identify fails because of short swipe,
|
||||||
&& !fpi_timeout_add(10, elan_capture_async, dev))
|
* we need to do it manually. It feels like libfprint or the application
|
||||||
fpi_imgdev_session_error(dev, -ETIME);
|
* should know better if they want to retry, but they don't. */
|
||||||
|
if (elandev->dev_state != IMGDEV_STATE_INACTIVE)
|
||||||
|
dev_change_state(dev, IMGDEV_STATE_AWAIT_FINGER_ON);
|
||||||
|
|
||||||
fpi_ssm_free(ssm);
|
fpi_ssm_free(ssm);
|
||||||
}
|
}
|
||||||
|
@ -648,18 +646,12 @@ static void calibrate_run_state(struct fpi_ssm *ssm)
|
||||||
static void calibrate_complete(struct fpi_ssm *ssm)
|
static void calibrate_complete(struct fpi_ssm *ssm)
|
||||||
{
|
{
|
||||||
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
|
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
|
||||||
struct elan_dev *elandev = fpi_imgdev_get_user_data(dev);
|
|
||||||
|
|
||||||
G_DEBUG_HERE();
|
G_DEBUG_HERE();
|
||||||
|
|
||||||
if (elandev->deactivating)
|
|
||||||
elan_deactivate(dev);
|
if (fpi_ssm_get_error(ssm) != -ECANCELED)
|
||||||
else if (fpi_ssm_get_error(ssm))
|
|
||||||
fpi_imgdev_activate_complete(dev, fpi_ssm_get_error(ssm));
|
fpi_imgdev_activate_complete(dev, fpi_ssm_get_error(ssm));
|
||||||
else {
|
|
||||||
fpi_imgdev_activate_complete(dev, 0);
|
|
||||||
elan_capture(dev);
|
|
||||||
}
|
|
||||||
|
|
||||||
fpi_ssm_free(ssm);
|
fpi_ssm_free(ssm);
|
||||||
}
|
}
|
||||||
|
@ -730,16 +722,15 @@ static void activate_run_state(struct fpi_ssm *ssm)
|
||||||
static void activate_complete(struct fpi_ssm *ssm)
|
static void activate_complete(struct fpi_ssm *ssm)
|
||||||
{
|
{
|
||||||
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
|
struct fp_img_dev *dev = fpi_ssm_get_user_data(ssm);
|
||||||
struct elan_dev *elandev = fpi_imgdev_get_user_data(dev);
|
|
||||||
|
|
||||||
G_DEBUG_HERE();
|
G_DEBUG_HERE();
|
||||||
|
|
||||||
if (elandev->deactivating)
|
if (fpi_ssm_get_error(ssm) != -ECANCELED) {
|
||||||
elan_deactivate(dev);
|
if (fpi_ssm_get_error(ssm))
|
||||||
else if (fpi_ssm_get_error(ssm))
|
|
||||||
fpi_imgdev_activate_complete(dev, fpi_ssm_get_error(ssm));
|
fpi_imgdev_activate_complete(dev, fpi_ssm_get_error(ssm));
|
||||||
else
|
else
|
||||||
elan_calibrate(dev);
|
elan_calibrate(dev);
|
||||||
|
}
|
||||||
|
|
||||||
fpi_ssm_free(ssm);
|
fpi_ssm_free(ssm);
|
||||||
}
|
}
|
||||||
|
@ -808,18 +799,80 @@ static int dev_activate(struct fp_img_dev *dev, enum fp_imgdev_state state)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dev_deactivate(struct fp_img_dev *dev)
|
static void elan_change_state(struct fp_img_dev *dev)
|
||||||
|
{
|
||||||
|
struct elan_dev *elandev = fpi_imgdev_get_user_data(dev);
|
||||||
|
enum fp_imgdev_state next_state = elandev->dev_state_next;
|
||||||
|
|
||||||
|
if (elandev->dev_state == next_state) {
|
||||||
|
fp_dbg("already in %d", next_state);
|
||||||
|
return;
|
||||||
|
} else
|
||||||
|
fp_dbg("changing to %d", next_state);
|
||||||
|
|
||||||
|
switch (next_state) {
|
||||||
|
case IMGDEV_STATE_INACTIVE:
|
||||||
|
if (elandev->cur_transfer)
|
||||||
|
/* deactivation will complete in transfer callback */
|
||||||
|
libusb_cancel_transfer(elandev->cur_transfer);
|
||||||
|
else
|
||||||
|
elan_deactivate(dev);
|
||||||
|
break;
|
||||||
|
case IMGDEV_STATE_AWAIT_FINGER_ON:
|
||||||
|
/* activation completed or another enroll stage started */
|
||||||
|
elan_capture(dev);
|
||||||
|
break;
|
||||||
|
case IMGDEV_STATE_CAPTURE:
|
||||||
|
case IMGDEV_STATE_AWAIT_FINGER_OFF:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
elandev->dev_state = next_state;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void elan_change_state_async(void *data)
|
||||||
|
{
|
||||||
|
elan_change_state((struct fp_img_dev *)data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int dev_change_state(struct fp_img_dev *dev, enum fp_imgdev_state state)
|
||||||
{
|
{
|
||||||
struct elan_dev *elandev = fpi_imgdev_get_user_data(dev);
|
struct elan_dev *elandev = fpi_imgdev_get_user_data(dev);
|
||||||
|
|
||||||
G_DEBUG_HERE();
|
G_DEBUG_HERE();
|
||||||
|
|
||||||
elandev->deactivating = TRUE;
|
switch (state) {
|
||||||
|
case IMGDEV_STATE_INACTIVE:
|
||||||
|
case IMGDEV_STATE_AWAIT_FINGER_ON:
|
||||||
|
/* schedule state change instead of calling it directly to allow all actions
|
||||||
|
* related to the previous state to complete */
|
||||||
|
elandev->dev_state_next = state;
|
||||||
|
if (!fpi_timeout_add(10, elan_change_state_async, dev)) {
|
||||||
|
fpi_imgdev_session_error(dev, -ETIME);
|
||||||
|
return -ETIME;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case IMGDEV_STATE_CAPTURE:
|
||||||
|
case IMGDEV_STATE_AWAIT_FINGER_OFF:
|
||||||
|
/* TODO MAYBE: split capture ssm into smaller ssms and use these states */
|
||||||
|
elandev->dev_state = state;
|
||||||
|
elandev->dev_state_next = state;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
fp_err("unrecognized state %d", state);
|
||||||
|
fpi_imgdev_session_error(dev, -EINVAL);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
if (elandev->cur_transfer)
|
/* as of time of writing libfprint never checks the return value */
|
||||||
libusb_cancel_transfer(elandev->cur_transfer);
|
return 0;
|
||||||
else
|
}
|
||||||
elan_deactivate(dev);
|
|
||||||
|
static void dev_deactivate(struct fp_img_dev *dev)
|
||||||
|
{
|
||||||
|
G_DEBUG_HERE();
|
||||||
|
|
||||||
|
dev_change_state(dev, IMGDEV_STATE_INACTIVE);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct fp_img_driver elan_driver = {
|
struct fp_img_driver elan_driver = {
|
||||||
|
@ -838,4 +891,5 @@ struct fp_img_driver elan_driver = {
|
||||||
.close = dev_deinit,
|
.close = dev_deinit,
|
||||||
.activate = dev_activate,
|
.activate = dev_activate,
|
||||||
.deactivate = dev_deactivate,
|
.deactivate = dev_deactivate,
|
||||||
|
.change_state = dev_change_state,
|
||||||
};
|
};
|
||||||
|
|
|
@ -130,7 +130,7 @@ static const struct elan_cmd led_on_cmd = {
|
||||||
.cmd = {0x40, 0x31},
|
.cmd = {0x40, 0x31},
|
||||||
.response_len = ELAN_CMD_SKIP_READ,
|
.response_len = ELAN_CMD_SKIP_READ,
|
||||||
.response_in = ELAN_EP_CMD_IN,
|
.response_in = ELAN_EP_CMD_IN,
|
||||||
.devices = ELAN_0907,
|
.devices = ELAN_ALL_DEV,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* wait for finger
|
/* wait for finger
|
||||||
|
@ -214,4 +214,6 @@ static void elan_calibrate(struct fp_img_dev *dev);
|
||||||
static void elan_capture(struct fp_img_dev *dev);
|
static void elan_capture(struct fp_img_dev *dev);
|
||||||
static void elan_deactivate(struct fp_img_dev *dev);
|
static void elan_deactivate(struct fp_img_dev *dev);
|
||||||
|
|
||||||
|
static int dev_change_state(struct fp_img_dev *dev, enum fp_imgdev_state state);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue