From 8553f2e41c41ab3f3df04638cc2c14e766ab84f0 Mon Sep 17 00:00:00 2001 From: Igor Filatov Date: Tue, 17 Jul 2018 09:02:47 +0300 Subject: [PATCH] elan: Send stop cmd and recalibrate after each capture This seems to fix the lock-up issue with 0903 --- libfprint/drivers/elan.c | 77 +++++++++++++++++++++++----------------- 1 file changed, 44 insertions(+), 33 deletions(-) diff --git a/libfprint/drivers/elan.c b/libfprint/drivers/elan.c index 97f4c34..8457405 100644 --- a/libfprint/drivers/elan.c +++ b/libfprint/drivers/elan.c @@ -435,32 +435,49 @@ static void elan_run_cmd(struct fpi_ssm *ssm, const struct elan_cmd *cmd, fpi_ssm_mark_aborted(ssm, r); } -enum deactivate_states { - DEACTIVATE, - DEACTIVATE_NUM_STATES, +enum stop_capture_states { + STOP_CAPTURE, + 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(); switch (fpi_ssm_get_cur_state(ssm)) { - case DEACTIVATE: + case STOP_CAPTURE: elan_run_cmd(ssm, &stop_cmd, ELAN_CMD_TIMEOUT); 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 elan_dev *elandev = fpi_imgdev_get_user_data(dev); + int error = fpi_ssm_get_error(ssm); 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); @@ -468,10 +485,11 @@ static void elan_deactivate(struct fp_img_dev *dev) elan_dev_reset(elandev); - struct fpi_ssm *ssm = fpi_ssm_new(fpi_imgdev_get_dev(dev), deactivate_run_state, - DEACTIVATE_NUM_STATES); + struct fpi_ssm *ssm = + 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_start(ssm, deactivate_complete); + fpi_ssm_start(ssm, stop_capture_complete); } enum capture_states { @@ -550,19 +568,6 @@ static void capture_complete(struct fpi_ssm *ssm) else 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); } @@ -692,7 +697,7 @@ static void calibrate_complete(struct fpi_ssm *ssm) if (fpi_ssm_get_error(ssm) != -ECANCELED) - fpi_imgdev_activate_complete(dev, fpi_ssm_get_error(ssm)); + elan_capture(dev); fpi_ssm_free(ssm); } @@ -772,10 +777,7 @@ static void activate_complete(struct fpi_ssm *ssm) G_DEBUG_HERE(); if (fpi_ssm_get_error(ssm) != -ECANCELED) { - if (fpi_ssm_get_error(ssm)) - fpi_imgdev_activate_complete(dev, fpi_ssm_get_error(ssm)); - else - elan_calibrate(dev); + fpi_imgdev_activate_complete(dev, fpi_ssm_get_error(ssm)); } fpi_ssm_free(ssm); @@ -825,6 +827,13 @@ static int dev_init(struct fp_img_dev *dev, unsigned long driver_data) 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) { 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; case IMGDEV_STATE_AWAIT_FINGER_ON: /* activation completed or another enroll stage started */ - elan_capture(dev); + elan_calibrate(dev); break; case IMGDEV_STATE_CAPTURE: - case IMGDEV_STATE_AWAIT_FINGER_OFF: + /* not used */ break; + case IMGDEV_STATE_AWAIT_FINGER_OFF: + elan_stop_capture(dev); } 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) { case IMGDEV_STATE_INACTIVE: case IMGDEV_STATE_AWAIT_FINGER_ON: + case IMGDEV_STATE_AWAIT_FINGER_OFF: /* schedule state change instead of calling it directly to allow all actions * related to the previous state to complete */ 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; case IMGDEV_STATE_CAPTURE: - case IMGDEV_STATE_AWAIT_FINGER_OFF: - /* TODO MAYBE: split capture ssm into smaller ssms and use these states */ + /* TODO MAYBE: split capture ssm into smaller ssms and use this state */ elandev->dev_state = state; elandev->dev_state_next = state; break;