Merge branch 'iafilatov/libfprint-elan-prepare-merge' into 'master'

elan: Send stop cmd and recalibrate after each capture

See merge request libfprint/libfprint!11
This commit is contained in:
Bastien Nocera 2018-08-10 12:36:01 +00:00
commit a96509f286

View file

@ -435,32 +435,49 @@ static void elan_run_cmd(struct fpi_ssm *ssm, const struct elan_cmd *cmd,
fpi_ssm_mark_aborted(ssm, r); fpi_ssm_mark_aborted(ssm, r);
} }
enum deactivate_states { enum stop_capture_states {
DEACTIVATE, STOP_CAPTURE,
DEACTIVATE_NUM_STATES, STOP_CAPTURE_NUM_STATES,
}; };
static void deactivate_run_state(struct fpi_ssm *ssm) static void stop_capture_run_state(struct fpi_ssm *ssm)
{ {
G_DEBUG_HERE(); G_DEBUG_HERE();
switch (fpi_ssm_get_cur_state(ssm)) { switch (fpi_ssm_get_cur_state(ssm)) {
case DEACTIVATE: case STOP_CAPTURE:
elan_run_cmd(ssm, &stop_cmd, ELAN_CMD_TIMEOUT); elan_run_cmd(ssm, &stop_cmd, ELAN_CMD_TIMEOUT);
break; break;
} }
} }
static void deactivate_complete(struct fpi_ssm *ssm) static void stop_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);
struct elan_dev *elandev = fpi_imgdev_get_user_data(dev);
int error = fpi_ssm_get_error(ssm);
G_DEBUG_HERE(); G_DEBUG_HERE();
fpi_imgdev_deactivate_complete(dev); fpi_ssm_free(ssm);
if (!error) {
fpi_imgdev_report_finger_status(dev, FALSE);
/* If verify or identify fails because of short swipe, we need to restart
* capture manually. It feels like libfprint or the application should know
* better if they want to retry, but they don't. Unless we've been asked to
* deactivate, try to re-enter the capture loop. Since state change is
* async, there's still a chance to be deactivated by another pending
* event. */
if (elandev->dev_state_next != IMGDEV_STATE_INACTIVE)
dev_change_state(dev, IMGDEV_STATE_AWAIT_FINGER_ON);
} else if (error != -ECANCELED)
fpi_imgdev_abort_scan(dev, error);
} }
static void elan_deactivate(struct fp_img_dev *dev) static void elan_stop_capture(struct fp_img_dev *dev)
{ {
struct elan_dev *elandev = fpi_imgdev_get_user_data(dev); struct elan_dev *elandev = fpi_imgdev_get_user_data(dev);
@ -468,10 +485,11 @@ static void elan_deactivate(struct fp_img_dev *dev)
elan_dev_reset(elandev); elan_dev_reset(elandev);
struct fpi_ssm *ssm = fpi_ssm_new(fpi_imgdev_get_dev(dev), deactivate_run_state, struct fpi_ssm *ssm =
DEACTIVATE_NUM_STATES); fpi_ssm_new(fpi_imgdev_get_dev(dev), stop_capture_run_state,
STOP_CAPTURE_NUM_STATES);
fpi_ssm_set_user_data(ssm, dev); fpi_ssm_set_user_data(ssm, dev);
fpi_ssm_start(ssm, deactivate_complete); fpi_ssm_start(ssm, stop_capture_complete);
} }
enum capture_states { enum capture_states {
@ -550,19 +568,6 @@ static void capture_complete(struct fpi_ssm *ssm)
else else
fpi_imgdev_abort_scan(dev, fpi_ssm_get_error(ssm)); fpi_imgdev_abort_scan(dev, fpi_ssm_get_error(ssm));
/* this procedure must be called regardless of outcome because it advances
* dev_state to AWAIT_FINGER_ON under the hood... */
fpi_imgdev_report_finger_status(dev, FALSE);
/* ...but only on enroll! If verify or identify fails because of short swipe,
* we need to do it manually. It feels like libfprint or the application
* should know better if they want to retry, but they don't. Unless we've
* been asked to deactivate, try to re-enter the capture loop. Since state
* change is async, there's still a chance to be deactivated by another
* pending event. */
if (elandev->dev_state_next != IMGDEV_STATE_INACTIVE)
dev_change_state(dev, IMGDEV_STATE_AWAIT_FINGER_ON);
fpi_ssm_free(ssm); fpi_ssm_free(ssm);
} }
@ -692,7 +697,7 @@ static void calibrate_complete(struct fpi_ssm *ssm)
if (fpi_ssm_get_error(ssm) != -ECANCELED) if (fpi_ssm_get_error(ssm) != -ECANCELED)
fpi_imgdev_activate_complete(dev, fpi_ssm_get_error(ssm)); elan_capture(dev);
fpi_ssm_free(ssm); fpi_ssm_free(ssm);
} }
@ -772,10 +777,7 @@ static void activate_complete(struct fpi_ssm *ssm)
G_DEBUG_HERE(); G_DEBUG_HERE();
if (fpi_ssm_get_error(ssm) != -ECANCELED) { if (fpi_ssm_get_error(ssm) != -ECANCELED) {
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
elan_calibrate(dev);
} }
fpi_ssm_free(ssm); fpi_ssm_free(ssm);
@ -825,6 +827,13 @@ static int dev_init(struct fp_img_dev *dev, unsigned long driver_data)
return 0; return 0;
} }
static void elan_deactivate(struct fp_img_dev *dev)
{
G_DEBUG_HERE();
fpi_imgdev_deactivate_complete(dev);
}
static void dev_deinit(struct fp_img_dev *dev) static void dev_deinit(struct fp_img_dev *dev)
{ {
struct elan_dev *elandev = fpi_imgdev_get_user_data(dev); struct elan_dev *elandev = fpi_imgdev_get_user_data(dev);
@ -866,11 +875,13 @@ static void elan_change_state(struct fp_img_dev *dev)
break; break;
case IMGDEV_STATE_AWAIT_FINGER_ON: case IMGDEV_STATE_AWAIT_FINGER_ON:
/* activation completed or another enroll stage started */ /* activation completed or another enroll stage started */
elan_capture(dev); elan_calibrate(dev);
break; break;
case IMGDEV_STATE_CAPTURE: case IMGDEV_STATE_CAPTURE:
case IMGDEV_STATE_AWAIT_FINGER_OFF: /* not used */
break; break;
case IMGDEV_STATE_AWAIT_FINGER_OFF:
elan_stop_capture(dev);
} }
elandev->dev_state = next_state; elandev->dev_state = next_state;
@ -890,6 +901,7 @@ static int dev_change_state(struct fp_img_dev *dev, enum fp_imgdev_state state)
switch (state) { switch (state) {
case IMGDEV_STATE_INACTIVE: case IMGDEV_STATE_INACTIVE:
case IMGDEV_STATE_AWAIT_FINGER_ON: case IMGDEV_STATE_AWAIT_FINGER_ON:
case IMGDEV_STATE_AWAIT_FINGER_OFF:
/* schedule state change instead of calling it directly to allow all actions /* schedule state change instead of calling it directly to allow all actions
* related to the previous state to complete */ * related to the previous state to complete */
elandev->dev_state_next = state; elandev->dev_state_next = state;
@ -899,8 +911,7 @@ static int dev_change_state(struct fp_img_dev *dev, enum fp_imgdev_state state)
} }
break; break;
case IMGDEV_STATE_CAPTURE: case IMGDEV_STATE_CAPTURE:
case IMGDEV_STATE_AWAIT_FINGER_OFF: /* TODO MAYBE: split capture ssm into smaller ssms and use this state */
/* TODO MAYBE: split capture ssm into smaller ssms and use these states */
elandev->dev_state = state; elandev->dev_state = state;
elandev->dev_state_next = state; elandev->dev_state_next = state;
break; break;