From 7c97dcd985fb97192c753f5c113c2c0a932f8640 Mon Sep 17 00:00:00 2001 From: Benjamin Berg Date: Mon, 11 Jul 2022 19:41:43 +0200 Subject: [PATCH 1/3] device: Add API for perstistent data storage API consumers should fetch the persistent data when they are done and store it to disk. It is undefined when this data is updated by the driver, but in general, it should only be updated once the first time a device is used. --- doc/libfprint-2-sections.txt | 2 + libfprint/fp-device-private.h | 1 + libfprint/fp-device.c | 160 ++++++++++++++++++++++++++++++++++ libfprint/fp-device.h | 9 ++ tests/test-fp-device.c | 48 ++++++++++ 5 files changed, 220 insertions(+) diff --git a/doc/libfprint-2-sections.txt b/doc/libfprint-2-sections.txt index 0fb0cfab..f7ee7805 100644 --- a/doc/libfprint-2-sections.txt +++ b/doc/libfprint-2-sections.txt @@ -40,6 +40,8 @@ fp_device_has_feature fp_device_has_storage fp_device_supports_identify fp_device_supports_capture +fp_device_get_persistent_data +fp_device_set_persistent_data fp_device_is_open fp_device_open fp_device_close diff --git a/libfprint/fp-device-private.h b/libfprint/fp-device-private.h index 1c3702fa..22165de3 100644 --- a/libfprint/fp-device-private.h +++ b/libfprint/fp-device-private.h @@ -61,6 +61,7 @@ typedef struct FpDeviceFeature features; guint64 driver_data; + GVariant *persistent_data; gint nr_enroll_stages; GSList *sources; diff --git a/libfprint/fp-device.c b/libfprint/fp-device.c index ab06e7f5..1b1f9a82 100644 --- a/libfprint/fp-device.c +++ b/libfprint/fp-device.c @@ -54,6 +54,7 @@ enum { PROP_FPI_UDEV_DATA_SPIDEV, PROP_FPI_UDEV_DATA_HIDRAW, PROP_FPI_DRIVER_DATA, + PROP_FPI_PERSISTENT_DATA, N_PROPS }; @@ -235,6 +236,8 @@ fp_device_finalize (GObject *object) g_clear_pointer (&priv->udev_data.spidev_path, g_free); g_clear_pointer (&priv->udev_data.hidraw_path, g_free); + g_clear_pointer (&priv->persistent_data, g_variant_unref); + G_OBJECT_CLASS (fp_device_parent_class)->finalize (object); } @@ -304,6 +307,10 @@ fp_device_get_property (GObject *object, g_value_set_string (value, NULL); break; + case PROP_FPI_PERSISTENT_DATA: + g_value_set_variant (value, priv->persistent_data); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } @@ -354,6 +361,11 @@ fp_device_set_property (GObject *object, priv->driver_data = g_value_get_uint64 (value); break; + case PROP_FPI_PERSISTENT_DATA: + g_clear_pointer (&priv->persistent_data, g_variant_unref); + priv->persistent_data = g_value_dup_variant (value); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } @@ -594,6 +606,21 @@ fp_device_class_init (FpDeviceClass *klass) 0, G_PARAM_STATIC_STRINGS | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY); + /** + * FpDevice::fpi-persistent-data: (skip) + * + * This property is only for internal purposes. + * + * Stability: private + */ + properties[PROP_FPI_PERSISTENT_DATA] = + g_param_spec_variant ("fpi-persistent-data", + "Persistent Driver Data", + "Private: Previously stored data for the device", + G_VARIANT_TYPE_ANY, + NULL, + G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE); + g_object_class_install_properties (object_class, N_PROPS, properties); } @@ -739,6 +766,139 @@ fp_device_get_temperature (FpDevice *device) return priv->temp_current; } +/** + * fp_device_get_persistent_data: + * @device: A #FpDevice + * @data: (array length=length) (transfer full) (out): Return location for data pointer + * @length: (transfer full) (out): Length of @data + * @error: Return location for error + * + * Retrieves persistent data that should be stored for this device. Storage + * needs to be device specific, i.e. device ID and driver must match when + * restored. + * + * Returns: (type void): %TRUE on success + */ +gboolean +fp_device_get_persistent_data (FpDevice *device, + guchar **data, + gsize *length, + GError **error) +{ + g_autoptr(GVariant) res = NULL; + FpDevicePrivate *priv = fp_device_get_instance_private (device); + + g_assert (data); + g_assert (length); + + if (priv->persistent_data == NULL) + { + *data = NULL; + *length = 0; + + return TRUE; + } + + /* Version + variant from driver */ + res = g_variant_new ("(issv)", + 1, + fp_device_get_driver (device), + priv->device_id, + priv->persistent_data); + + *length = g_variant_get_size (res); + *data = g_malloc (*length); + g_variant_store (res, *data); + + return TRUE; +} + +/** + * fp_device_get_persistent_data: + * @device: A #FpDevice + * @data: (array length=length) (transfer none): Persistent Data + * @length: (transfer none): Length of @data + * @error: Return location for error + * + * Load persistent data from storage. This function should be called after + * a device was discovered and before it is opened for the first time. It is + * an error to call it if data has already been set (or generated by the + * driver). + * + * Note that the driver may update the data. The API user should retrieve the + * value when done with the device and store it in a persistent location. + * + * Returns: (type void): %TRUE on success + */ +gboolean +fp_device_set_persistent_data (FpDevice *device, + guchar *data, + gsize length, + GError **error) +{ + g_autoptr(GVariant) stored = NULL; + g_autoptr(GVariant) loaded = NULL; + FpDevicePrivate *priv = fp_device_get_instance_private (device); + guchar *copy; + gint version; + const gchar *device_id; + const gchar *driver; + + if (priv->is_open) + { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, + "Data can only be set right after device creation"); + return FALSE; + } + + if (priv->persistent_data) + { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_EXISTS, + "Data has already been set"); + return FALSE; + } + + if (length == 0) + { + g_clear_pointer (&priv->persistent_data, g_variant_unref); + g_object_notify_by_pspec (G_OBJECT (device), properties[PROP_FPI_PERSISTENT_DATA]); + return TRUE; + } + g_assert (data); + + copy = g_memdup2 (data, length); + stored = g_variant_new_from_data (G_VARIANT_TYPE ("(issv)"), copy, length, FALSE, g_free, copy); + + if (!stored) + { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA, + "Data could not be parsed"); + return FALSE; + } + + g_variant_get (stored, "(issv)", &version, &driver, &device_id, &loaded); + if (version != 1) + { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA, + "Unknown data storage version"); + return FALSE; + } + + if (g_strcmp0 (device_id, priv->device_id) != 0 || + g_strcmp0 (driver, fp_device_get_driver (device)) != 0) + { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA, + "Driver or device ID mismatch!"); + return FALSE; + } + + g_clear_pointer (&priv->persistent_data, g_variant_unref); + priv->persistent_data = g_steal_pointer (&loaded); + g_object_notify_by_pspec (G_OBJECT (device), properties[PROP_FPI_PERSISTENT_DATA]); + + return TRUE; +} + /** * fp_device_supports_identify: * @device: A #FpDevice diff --git a/libfprint/fp-device.h b/libfprint/fp-device.h index e82cb535..0187564a 100644 --- a/libfprint/fp-device.h +++ b/libfprint/fp-device.h @@ -233,6 +233,15 @@ FpDeviceFeature fp_device_get_features (FpDevice *device); gboolean fp_device_has_feature (FpDevice *device, FpDeviceFeature feature); +gboolean fp_device_get_persistent_data (FpDevice *device, + guchar **data, + gsize *length, + GError **error); +gboolean fp_device_set_persistent_data (FpDevice *device, + guchar *data, + gsize length, + GError **error); + /* Opening the device */ void fp_device_open (FpDevice *device, GCancellable *cancellable, diff --git a/tests/test-fp-device.c b/tests/test-fp-device.c index dbaec9b2..38f4cbb1 100644 --- a/tests/test-fp-device.c +++ b/tests/test-fp-device.c @@ -262,6 +262,53 @@ test_device_identify_null_prints (void) g_assert_error (error, FP_DEVICE_ERROR, FP_DEVICE_ERROR_DATA_INVALID); } +static void +test_device_persistent_data (void) +{ + g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_device (FPT_VIRTUAL_DEVICE_IMAGE); + g_autoptr(GVariant) initial = NULL; + g_autoptr(GVariant) loaded = NULL; + g_autoptr(GError) error = NULL; + guint8 *data = (guint8 *) 0xdeadbeef; + gsize length = 1; + + initial = g_variant_ref_sink (g_variant_new ("(s)", "stored data")); + + g_assert_true (fp_device_get_persistent_data (tctx->device, &data, &length, &error)); + g_assert_cmpint (length, ==, 0); + g_assert_null (data); + g_assert_no_error (error); + + /* Use the fact that this is a property that we can poke from the outside. */ + g_object_set (tctx->device, "fpi-persistent-data", initial, NULL); + + /* Works now */ + g_assert_true (fp_device_get_persistent_data (tctx->device, &data, &length, &error)); + g_assert_cmpint (length, !=, 0); + g_assert_nonnull (data); + g_assert_no_error (error); + + /* We can't load the data, as data has been set already. */ + g_assert_false (fp_device_set_persistent_data (tctx->device, data, length, &error)); + g_assert_error (error, G_IO_ERROR, G_IO_ERROR_EXISTS); + g_clear_pointer (&error, g_error_free); + + /* Abuse that we can "load" again if the data is set to NULL. + * This is an implementation detail and just a lack of error checking. */ + g_object_set (tctx->device, "fpi-persistent-data", NULL, NULL); + + /* Incomplete data, causes parsing error */ + g_assert_false (fp_device_set_persistent_data (tctx->device, data, 5, &error)); + g_assert_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA); + g_clear_pointer (&error, g_error_free); + + g_assert_true (fp_device_set_persistent_data (tctx->device, data, length, &error)); + g_assert_no_error (error); + + g_object_get (tctx->device, "fpi-persistent-data", &loaded, NULL); + g_assert_cmpvariant (initial, loaded); +} + int main (int argc, char *argv[]) { @@ -284,6 +331,7 @@ main (int argc, char *argv[]) g_test_add_func ("/device/sync/has_storage", test_device_has_storage); g_test_add_func ("/device/sync/identify/cancelled", test_device_identify_cancelled); g_test_add_func ("/device/sync/identify/null-prints", test_device_identify_null_prints); + g_test_add_func ("/device/persistent_data", test_device_persistent_data); return g_test_run (); } From 20509027676a12f68e68707102b4f6a480007cce Mon Sep 17 00:00:00 2001 From: saeedark Date: Sun, 26 Oct 2025 20:49:20 +0330 Subject: [PATCH 2/3] fix: calibration for egis0570 --- libfprint/drivers/egis0570.c | 1002 +++++++++++++++++++++++++++++++++- libfprint/drivers/egis0570.h | 415 ++++++++++++++ 2 files changed, 1399 insertions(+), 18 deletions(-) diff --git a/libfprint/drivers/egis0570.c b/libfprint/drivers/egis0570.c index 0ff607da..a4d36eb3 100644 --- a/libfprint/drivers/egis0570.c +++ b/libfprint/drivers/egis0570.c @@ -18,29 +18,75 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include +#include + +#include #define FP_COMPONENT "egis0570" #include "egis0570.h" #include "drivers_api.h" +#include "fp-device.h" /* Packet types */ #define PKT_TYPE_INIT 0 #define PKT_TYPE_REPEAT 1 /* Struct */ +struct CalibrationContext +{ + gboolean img_resp; + int pkt_size; + guint8 *pkt_ptr; + + int cal_step; + + + guint8 req_packet[EGIS0570_PKTSIZE]; + guint8 *calibration_images; + guint8 cal_img_idx; + + guint8 rng_pkt_low; + guint8 rng_pkt_high; + + gint8 repeat_step; + + guint8 pkt_02_value; + + guint8 bs_steps; + guint8 bs_condition; + guint8 bs_mid; + guint8 bs_twos; + guint8 bs_zeros; + guint8 bs_lows[EGIS0570_CAL_BS_ELM]; + guint8 bs_highs[EGIS0570_CAL_BS_ELM]; + unsigned int bs_row_sums[EGIS0570_CAL_BS_ELM]; + guint8 bs_pkts[EGIS0570_CAL_BS_ELM * EGIS0570_PKTSIZE]; + +}; + struct _FpDeviceEgis0570 { - FpImageDevice parent; + FpImageDevice parent; - gboolean running; - gboolean stop; + gboolean running; + gboolean stop; + gboolean calibrating; + gboolean save_resp; - GSList *strips; - guint8 *background; - gsize strips_len; + guint8 resp_state; + guint8 saved_resp; - int pkt_num; - int pkt_type; + GSList *strips; + guint8 *background; + gsize strips_len; + + int pkt_num; + int pkt_type; + + guint8 query_pkts[EGIS0570_INIT_TOTAL][EGIS0570_PKTSIZE]; + guint8 *persistent_data; + struct CalibrationContext *cal_ctx; }; G_DECLARE_FINAL_TYPE (FpDeviceEgis0570, fpi_device_egis0570, FPI, DEVICE_EGIS0570, FpImageDevice); G_DEFINE_TYPE (FpDeviceEgis0570, fpi_device_egis0570, FP_TYPE_IMAGE_DEVICE); @@ -58,10 +104,29 @@ static struct fpi_frame_asmbl_ctx assembling_ctx = { .get_pixel = egis_get_pixel, }; + +enum sm_caliberation_states { + SM_CAL_INIT, + SM_CAL_STEP_LOGIC, + SM_CAL_STATIC_PKT, + SM_CAL_REQ, + SM_CAL_RESP, + SM_CAL_RNG_PKT_REQ, + SM_CAL_RNG_PKT_RESP, + SM_CAL_BS_PK_REQ, + SM_CAL_BS_PK_RESP, + SM_CAL_CHK_NEW_CNF_REQ, + SM_CAL_CHK_NEW_CNF_RESP, + SM_CAL_DONE, + SM_CAL_NUM, +}; + + /* * Service */ + static gboolean is_last_pkt (FpDevice *dev) { @@ -72,9 +137,16 @@ is_last_pkt (FpDevice *dev) gboolean r; - r = ((type == PKT_TYPE_INIT) && (num == (EGIS0570_INIT_TOTAL - 1))); - r |= ((type == PKT_TYPE_REPEAT) && (num == (EGIS0570_REPEAT_TOTAL - 1))); - + if (self->calibrating) + { + struct CalibrationContext *cal_ctx = self->cal_ctx; + r = (cal_ctx->pkt_size - 1) == num; + } + else + { + r = ((type == PKT_TYPE_INIT) && (num == (EGIS0570_INIT_TOTAL - 1))); + r |= ((type == PKT_TYPE_REPEAT) && (num == (EGIS0570_REPEAT_TOTAL - 1))); + } return r; } @@ -221,11 +293,51 @@ recv_data_resp (FpiSsm *ssm, FpDevice *dev) fpi_usb_transfer_submit (transfer, EGIS0570_TIMEOUT, NULL, data_resp_cb, NULL); } + +static void +data_cal_resp_cb (FpiUsbTransfer *transfer, FpDevice *dev, gpointer user_data, GError *error) +{ + FpDeviceEgis0570 *self = FPI_DEVICE_EGIS0570 (dev); + struct CalibrationContext *cal_ctx = self->cal_ctx; + + if (error) + { + fpi_ssm_mark_failed (transfer->ssm, error); + return; + } + + // assert bound ? + memcpy (cal_ctx->calibration_images + (cal_ctx->cal_img_idx * EGIS0570_IMGSIZE), transfer->buffer, EGIS0570_IMGSIZE); + cal_ctx->cal_img_idx++; + + fpi_ssm_jump_to_state (transfer->ssm, SM_CAL_STEP_LOGIC); +} + +static void +recv_cal_data_resp (FpiSsm *ssm, FpDevice *dev) +{ + FpiUsbTransfer *transfer = fpi_usb_transfer_new (dev); + + fpi_usb_transfer_fill_bulk (transfer, EGIS0570_EPIN, EGIS0570_CAL_INPSIZE); + + transfer->ssm = ssm; + transfer->short_is_error = TRUE; + + fpi_usb_transfer_submit (transfer, EGIS0570_TIMEOUT, NULL, data_cal_resp_cb, NULL); +} + static void cmd_resp_cb (FpiUsbTransfer *transfer, FpDevice *dev, gpointer user_data, GError *error) { + FpDeviceEgis0570 *self = FPI_DEVICE_EGIS0570 (dev); + if (error) fpi_ssm_mark_failed (transfer->ssm, error); + + if (self->save_resp) + self->saved_resp = transfer->buffer[5]; + + fpi_ssm_jump_to_state (transfer->ssm, self->resp_state); } static void @@ -236,6 +348,7 @@ recv_cmd_resp (FpiSsm *ssm, FpDevice *dev) fpi_usb_transfer_fill_bulk (transfer, EGIS0570_EPIN, EGIS0570_PKTSIZE); transfer->ssm = ssm; + transfer->short_is_error = TRUE; fpi_usb_transfer_submit (transfer, EGIS0570_TIMEOUT, NULL, cmd_resp_cb, NULL); } @@ -276,7 +389,9 @@ ssm_run_state (FpiSsm *ssm, FpDevice *dev) switch (fpi_ssm_get_cur_state (ssm)) { case SM_INIT: + self->calibrating = FALSE; self->pkt_type = PKT_TYPE_INIT; + self->save_resp = FALSE; fpi_ssm_next_state (ssm); break; @@ -296,7 +411,7 @@ ssm_run_state (FpiSsm *ssm, FpDevice *dev) case SM_REQ: if (self->pkt_type == PKT_TYPE_INIT) - send_cmd_req (ssm, dev, init_pkts[self->pkt_num]); + send_cmd_req (ssm, dev, self->query_pkts[self->pkt_num]); else send_cmd_req (ssm, dev, repeat_pkts[self->pkt_num]); break; @@ -304,9 +419,9 @@ ssm_run_state (FpiSsm *ssm, FpDevice *dev) case SM_RESP: if (is_last_pkt (dev) == FALSE) { - recv_cmd_resp (ssm, dev); self->pkt_num += 1; - fpi_ssm_jump_to_state (ssm, SM_REQ); + self->resp_state = SM_REQ; + recv_cmd_resp (ssm, dev); } else { @@ -330,6 +445,779 @@ ssm_run_state (FpiSsm *ssm, FpDevice *dev) } } +/* + * Calibration + */ + + +static void +set_ctx_pkts_type (FpDeviceEgis0570 *self, guint8 * element_ptr) +{ + self->pkt_type = -1; + fp_dbg ("Error in indexing should not happen"); + for (guint8 i = 0; i < EGIS0570_CAL_STATIC_LIST_SIZEOF; i++) + { + if (EGIS0570_CAL_STATIC_LIST[i] == element_ptr) + { + self->pkt_type = i; + fp_dbg ("said index %d", i); + break; + } + } +} + +static void +set_ctx_pkts (FpDeviceEgis0570 *self) +{ + struct CalibrationContext *cal_ctx = self->cal_ctx; + + self->pkt_num = 0; + cal_ctx->pkt_ptr = EGIS0570_CAL_STATIC_LIST[self->pkt_type]; + cal_ctx->pkt_size = EGIS0570_CAL_STATIC_LIST_SIZE[self->pkt_type]; +} + + +static void +check_black_white_values (struct CalibrationContext *cal_ctx) +{ + guint8 * white_img = cal_ctx->calibration_images + (0 * EGIS0570_IMGSIZE); + guint8 * black_img = cal_ctx->calibration_images + (1 * EGIS0570_IMGSIZE); + + for (size_t i = 0; i < EGIS0570_IMGSIZE; i++) + { + if (white_img[i] != 0xfe || black_img[i] != 0x00) + { + fp_dbg ("Black and white values are not right!"); + break; + } + } +} + + +static void +sum_pictures (guint8 * data, unsigned int * sums, guint8 f_idx, guint8 l_idx) +{ + for (guint8 pic_idx = f_idx; pic_idx <= l_idx; pic_idx++) + { + for (guint8 i = IMG_COL_IGNORE ; i < EGIS0570_IMGWIDTH - IMG_COL_IGNORE ; i++) + { + sums[0] += data[pic_idx * EGIS0570_IMGSIZE + i]; + sums[1] += data[pic_idx * EGIS0570_IMGSIZE + i + 1 * EGIS0570_IMGWIDTH]; + sums[2] += data[pic_idx * EGIS0570_IMGSIZE + i + 2 * EGIS0570_IMGWIDTH]; + sums[3] += data[pic_idx * EGIS0570_IMGSIZE + i + 3 * EGIS0570_IMGWIDTH]; + sums[4] += data[pic_idx * EGIS0570_IMGSIZE + i + 4 * EGIS0570_IMGWIDTH]; + sums[5] += data[pic_idx * EGIS0570_IMGSIZE + i + 5 * EGIS0570_IMGWIDTH]; + sums[6] += data[pic_idx * EGIS0570_IMGSIZE + i + 28 * EGIS0570_IMGWIDTH]; + } + } +} + +static void +apply_next_step_setting (FpiSsm *ssm, FpDeviceEgis0570 *self) +{ + struct CalibrationContext *cal_ctx = self->cal_ctx; + + cal_ctx->cal_step++; + cal_ctx->pkt_size = 0; + cal_ctx->img_resp = FALSE; + + self->pkt_num = 0; + self->pkt_type = -1; + self->save_resp = FALSE; + + if (cal_ctx->cal_step == EGIS0570_CAL_PROC_SIZEOF) + { + fp_dbg ("something went wrong."); + return; + } + fp_dbg ("Procedure Index %d", cal_ctx->cal_step); + + switch (calibration_procedure[cal_ctx->cal_step]) + { + case CAL_CONF_PKT: + set_ctx_pkts_type (self, *EGIS0570_CAL_CONFIGURATION_MODE_PKT); + fpi_ssm_jump_to_state (ssm, SM_CAL_STATIC_PKT); + break; + + case CAL_PKT_ZERO_RNG: + set_ctx_pkts_type (self, *EGIS0570_CAL_PKT_ZERO_RANGE); + fpi_ssm_jump_to_state (ssm, SM_CAL_STATIC_PKT); + break; + + case CAL_CAPT_AREA: + set_ctx_pkts_type (self, *EGIS0570_CAL_CAPTURING_AREA); + fpi_ssm_jump_to_state (ssm, SM_CAL_STATIC_PKT); + break; + + case CAL_SENS_AND_EMIT: + set_ctx_pkts_type (self, *EGIS0570_CAL_SENSOR_AND_EMITTER); + fpi_ssm_jump_to_state (ssm, SM_CAL_STATIC_PKT); + break; + + case CAL_RNG_20_58: + cal_ctx->rng_pkt_low = 0x20; + cal_ctx->rng_pkt_high = 0x58; + cal_ctx->req_packet[4] = 0x01; + cal_ctx->req_packet[6] = 0x00; + fpi_ssm_jump_to_state (ssm, SM_CAL_RNG_PKT_REQ); + break; + + case CAL_RNG_60_D0: + cal_ctx->rng_pkt_low = 0x60; + cal_ctx->rng_pkt_high = 0xd0; + cal_ctx->req_packet[4] = 0x01; + cal_ctx->req_packet[6] = 0x00; + fpi_ssm_jump_to_state (ssm, SM_CAL_RNG_PKT_REQ); + break; + + case CAL_WHITE_SET: + set_ctx_pkts_type (self, *EGIS0570_CAL_WHITE_SETTING); + fpi_ssm_jump_to_state (ssm, SM_CAL_STATIC_PKT); + break; + + case CAL_BLACK_WHITE_GET_IMG: + set_ctx_pkts_type (self, *EGIS0570_CAL_BLACK_WHITE_GET_IMAGE); + cal_ctx->img_resp = TRUE; + fpi_ssm_jump_to_state (ssm, SM_CAL_STATIC_PKT); + break; + + case CAL_BLACK_WHITE_AFTER_IMAGE: + set_ctx_pkts_type (self, *EGIS0570_CAL_BLACK_WHITE_AFTER_IMAGE); + fpi_ssm_jump_to_state (ssm, SM_CAL_STATIC_PKT); + break; + + case CAL_BLACK_SET: + set_ctx_pkts_type (self, *EGIS0570_CAL_BLACK_SETTING); + fpi_ssm_jump_to_state (ssm, SM_CAL_STATIC_PKT); + break; + + case CAL_CHECK_BLACK_WHITE: + check_black_white_values (cal_ctx); + fpi_ssm_jump_to_state (ssm, SM_CAL_STEP_LOGIC); + break; + + case CAL_5_ROWS_ZEROS: + /* repeat this case*/ + if (cal_ctx->repeat_step == 0) + { + cal_ctx->repeat_step--; + fpi_ssm_jump_to_state (ssm, SM_CAL_STEP_LOGIC); + break; + } + cal_ctx->cal_step--; + if (cal_ctx->repeat_step == -1) + cal_ctx->repeat_step = 12; + /* end repeat */ + + if (cal_ctx->repeat_step % 2) + cal_ctx->rng_pkt_low = 0x58 - ((12 - cal_ctx->repeat_step) / 2); + else + cal_ctx->rng_pkt_low = 0x20 + ((12 - cal_ctx->repeat_step) / 2); + + cal_ctx->rng_pkt_high = cal_ctx->rng_pkt_low; + cal_ctx->req_packet[4] = 0x01; + cal_ctx->req_packet[6] = 0x00; + cal_ctx->repeat_step--; + fpi_ssm_jump_to_state (ssm, SM_CAL_RNG_PKT_REQ); + break; + + case CAL_BLACK_WHITE_CLEAR: + set_ctx_pkts_type (self, *EGIS0570_CAL_BLACK_WHITE_CLEAR); + fpi_ssm_jump_to_state (ssm, SM_CAL_STATIC_PKT); + break; + + case CAL_RNG_60_D1: + cal_ctx->rng_pkt_low = 0x60; + cal_ctx->rng_pkt_high = 0xd1; + cal_ctx->req_packet[4] = 0x01; + cal_ctx->req_packet[6] = 0x00; + fpi_ssm_jump_to_state (ssm, SM_CAL_RNG_PKT_REQ); + break; + + case CAL_MID_BLACK_SET: + set_ctx_pkts_type (self, *EGIS0570_CAL_MIDDLE_BLACK_SETTING); + fpi_ssm_jump_to_state (ssm, SM_CAL_STATIC_PKT); + break; + + case CAL_GET_IMG: + set_ctx_pkts_type (self, *EGIS0570_CAL_GET_IMAGE); + cal_ctx->img_resp = TRUE; + fpi_ssm_jump_to_state (ssm, SM_CAL_STATIC_PKT); + break; + + case CAL_AFTER_IMG: + set_ctx_pkts_type (self, *EGIS0570_CAL_AFTER_IMAGE); + fpi_ssm_jump_to_state (ssm, SM_CAL_STATIC_PKT); + break; + + case CAL_GET_9: + /* repeat this case*/ + if (cal_ctx->repeat_step == 0) + { + cal_ctx->repeat_step--; + fpi_ssm_jump_to_state (ssm, SM_CAL_STEP_LOGIC); + break; + } + cal_ctx->cal_step--; + if (cal_ctx->repeat_step == -1) + cal_ctx->repeat_step = 9 * 3; // 27 + /* end repeat */ + + if (cal_ctx->repeat_step % 3 == 0) + { + set_ctx_pkts_type (self, *EGIS0570_CAL_REPEAT); + } + else if (cal_ctx->repeat_step % 3 == 2) + { + set_ctx_pkts_type (self, *EGIS0570_CAL_GET_IMAGE); + cal_ctx->img_resp = TRUE; + } + else + { + set_ctx_pkts_type (self, *EGIS0570_CAL_AFTER_IMAGE); + } + cal_ctx->repeat_step--; + fpi_ssm_jump_to_state (ssm, SM_CAL_STATIC_PKT); + break; + + + case CAL_GET_21: + /* repeat this case*/ + if (cal_ctx->repeat_step == 0) + { + cal_ctx->repeat_step--; + fpi_ssm_jump_to_state (ssm, SM_CAL_STEP_LOGIC); + break; + } + cal_ctx->cal_step--; + if (cal_ctx->repeat_step == -1) + cal_ctx->repeat_step = 21 * 3; // 27 + /* end repeat */ + + if (cal_ctx->repeat_step % 3 == 0) + { + set_ctx_pkts_type (self, *EGIS0570_CAL_REPEAT); + } + else if (cal_ctx->repeat_step % 3 == 2) + { + set_ctx_pkts_type (self, *EGIS0570_CAL_GET_IMAGE); + cal_ctx->img_resp = TRUE; + } + else + { + set_ctx_pkts_type (self, *EGIS0570_CAL_AFTER_IMAGE); + } + cal_ctx->repeat_step--; + fpi_ssm_jump_to_state (ssm, SM_CAL_STATIC_PKT); + break; + + case CAL_BORDER_WHITE_SET: + set_ctx_pkts_type (self, *EGIS0570_CAL_BORDER_WHITE_SETTING); + fpi_ssm_jump_to_state (ssm, SM_CAL_STATIC_PKT); + break; + + + case CAL_FIRST_BS_SET: + cal_ctx->bs_steps = 0; + cal_ctx->bs_condition = 0x7f; + cal_ctx->bs_mid = 0; + + for (guint8 i = 0; i < EGIS0570_CAL_BS_ELM; i++) + { + cal_ctx->bs_lows[i] = 0x00; + cal_ctx->bs_highs[i] = 0xff; + cal_ctx->bs_row_sums[i] = 0x00; + for (guint8 k = 0; k < EGIS0570_PKTSIZE; k++) + cal_ctx->bs_pkts[i * EGIS0570_PKTSIZE + k] = init_pkts[i * 2][k]; + cal_ctx->bs_pkts[(i + 1) * EGIS0570_PKTSIZE - 1] = 0x00; + } + cal_ctx->bs_pkts[EGIS0570_CAL_BS_ELM * EGIS0570_PKTSIZE - 2] = 0x3c; + + set_ctx_pkts_type (self, *EGIS0570_CAL_FIRST_BS_SETTING); + fpi_ssm_jump_to_state (ssm, SM_CAL_STATIC_PKT); + break; + + + case CAL_BS_CHK_SET: + if (cal_ctx->bs_condition && cal_ctx->bs_steps < 8) + { + cal_ctx->bs_steps++; + fp_dbg ("CALIBERATION: BINARY SEARCH: CONDITION: %b, STEPS: %d", cal_ctx->bs_condition, cal_ctx->bs_steps); + for (guint8 i = 0; i < EGIS0570_CAL_BS_ELM; i++) + { + fp_dbg ("CALIBERATION: BINARY SEARCH: %d: LOW: %x, HIGH: %x", i, cal_ctx->bs_lows[i], cal_ctx->bs_highs[i]); + cal_ctx->bs_row_sums[i] = 0; + } + + fpi_ssm_jump_to_state (ssm, SM_CAL_BS_PK_REQ); + } + else + { + cal_ctx->cal_step += 6;// Based on calibration_procedure. + fpi_ssm_jump_to_state (ssm, SM_CAL_STEP_LOGIC); + } + break; + + case CAL_PKT_02: + cal_ctx->rng_pkt_low = 0x02; + cal_ctx->rng_pkt_high = 0x02; + cal_ctx->req_packet[4] = 0x00; + cal_ctx->req_packet[6] = cal_ctx->pkt_02_value; + cal_ctx->pkt_02_value = 0xff; + fpi_ssm_jump_to_state (ssm, SM_CAL_RNG_PKT_REQ); + break; + + case CAL_BEFORE_IMG: + set_ctx_pkts_type (self, *EGIS0570_CAL_BEFORE_GET_IMAGE); + fpi_ssm_jump_to_state (ssm, SM_CAL_STATIC_PKT); + break; + + case CAL_BS_JUMP: + sum_pictures (cal_ctx->calibration_images, cal_ctx->bs_row_sums, cal_ctx->cal_img_idx - 10, cal_ctx->cal_img_idx - 1); + + for (guint8 i = 0; i < EGIS0570_CAL_BS_ELM; i++) + { + cal_ctx->bs_row_sums[i] /= 10 * (EGIS0570_IMGWIDTH - (2 * IMG_COL_IGNORE)); + fp_dbg ("CALIBERATION: BINARY SEARCH: %d: PKT: %x, ROW_SUM: %d", i, cal_ctx->bs_pkts[i * EGIS0570_PKTSIZE + 6], cal_ctx->bs_row_sums[i]); + if (cal_ctx->bs_row_sums[i] >= TARGET_UPPER + (SIDE_DIFF * (i < 6))) + cal_ctx->bs_lows[i] = cal_ctx->bs_pkts[i * EGIS0570_PKTSIZE + 6] + ((cal_ctx->bs_highs[i] - cal_ctx->bs_lows[i]) == 1); + else if (cal_ctx->bs_row_sums[i] <= TARGET_LOWER + (SIDE_DIFF * (i < 6))) + cal_ctx->bs_highs[i] = cal_ctx->bs_pkts[i * EGIS0570_PKTSIZE + 6]; + else + cal_ctx->bs_condition = cal_ctx->bs_condition & (0x7f - (1 << i)); + } + + cal_ctx->cal_step = cal_ctx->cal_step - 7;// Based on calibration_procedure. + fpi_ssm_jump_to_state (ssm, SM_CAL_STEP_LOGIC); + break; + + case CAL_BS_END: + if (cal_ctx->bs_steps >= 8) + fp_dbg ("CALIBERATION: ERROR EXTRA STEPS ON BINARY SEARCH."); + + /* save in list */ + for (guint8 i = 0; i < EGIS0570_CAL_BS_ELM; i++) + { + self->persistent_data[i] = ((cal_ctx->bs_pkts[6 * EGIS0570_PKTSIZE + 6] * (i < 6)) > cal_ctx->bs_pkts[i * EGIS0570_PKTSIZE + 6]) ? 0x00 : (cal_ctx->bs_pkts[i * EGIS0570_PKTSIZE + 6] - (cal_ctx->bs_pkts[6 * EGIS0570_PKTSIZE + 6] * (i < 6))); + fp_dbg ("CALIBERATION: SAVED presistenet data %x", self->persistent_data[i]); + } + fpi_ssm_jump_to_state (ssm, SM_CAL_STEP_LOGIC); + break; + + + case CAL_PKT_15_0: + cal_ctx->rng_pkt_low = 0x15; + cal_ctx->rng_pkt_high = 0x15; + cal_ctx->req_packet[4] = 0x01; + cal_ctx->req_packet[6] = 0x00; + fpi_ssm_jump_to_state (ssm, SM_CAL_RNG_PKT_REQ); + break; + + case CAL_PKT_16_3C: + cal_ctx->rng_pkt_low = 0x16; + cal_ctx->rng_pkt_high = 0x16; + cal_ctx->req_packet[4] = 0x01; + cal_ctx->req_packet[6] = self->persistent_data[6]; + fpi_ssm_jump_to_state (ssm, SM_CAL_RNG_PKT_REQ); + break; + + case CAL_CHK_NEW_CONF: + for (guint8 i = 0; i < (EGIS0570_CAL_BS_ELM - 1); i++) + cal_ctx->bs_pkts[i * EGIS0570_PKTSIZE + 6] = self->persistent_data[i]; + cal_ctx->pkt_02_value = 0x00; + fpi_ssm_jump_to_state (ssm, SM_CAL_CHK_NEW_CNF_REQ); + break; + + case CAL_NO_IMG_CAP_AREA: + set_ctx_pkts_type (self, *EGIS0570_CAL_NO_IMAGE_CAPTURING_AREA); + fpi_ssm_jump_to_state (ssm, SM_CAL_STATIC_PKT); + break; + + case CAL_NO_IMG_SET_0: + set_ctx_pkts_type (self, *EGIS0570_CAL_NO_IMAGE_SETTING_0); + fpi_ssm_jump_to_state (ssm, SM_CAL_STATIC_PKT); + break; + + case CAL_NO_IMG_03_1C: + self->save_resp = TRUE; + cal_ctx->rng_pkt_low = 0x03; + cal_ctx->rng_pkt_high = 0x03; + cal_ctx->req_packet[4] = 0x00; + cal_ctx->req_packet[6] = 0x1C; + fpi_ssm_jump_to_state (ssm, SM_CAL_RNG_PKT_REQ); + break; + + case CAL_NO_CHK_03_80: + if (self->saved_resp != 0x80) + fp_dbg ("unexpected value (%x)for 0x00 0x03 0x1c -> 0x80.", self->saved_resp); + fpi_ssm_jump_to_state (ssm, SM_CAL_STEP_LOGIC); + break; + + case CAL_NO_SET_03_80: + cal_ctx->rng_pkt_low = 0x03; + cal_ctx->rng_pkt_high = 0x03; + cal_ctx->req_packet[4] = 0x01; + cal_ctx->req_packet[6] = self->saved_resp; + fpi_ssm_jump_to_state (ssm, SM_CAL_RNG_PKT_REQ); + break; + + case CAL_NO_IMG_14_BS_SET: + cal_ctx->bs_steps = 0; + cal_ctx->bs_condition = 0x01; + cal_ctx->bs_mid = 0; + cal_ctx->bs_lows[0] = 0x00; + cal_ctx->bs_highs[0] = 0x3f; + + set_ctx_pkts_type (self, *EGIS0570_CAL_NO_IMAGE_BINARY_14_SETTING); + fpi_ssm_jump_to_state (ssm, SM_CAL_STATIC_PKT); + break; + + + case CAL_NO_IMG_14_BS_CHK_SET: + if (cal_ctx->bs_condition && cal_ctx->bs_steps < 6 ) + { + cal_ctx->bs_twos = 0; + cal_ctx->bs_zeros = 0; + cal_ctx->bs_steps++; + + fp_dbg ("CALIBERATION: NO IMAGE 14/16: CONDITION: %b, STEPS: %d", cal_ctx->bs_condition, cal_ctx->bs_steps); + fp_dbg ("CALIBERATION: NO IMAGE 14/16: LOW: %x, HIGH: %x", cal_ctx->bs_lows[0], cal_ctx->bs_highs[0]); + + self->save_resp = FALSE; + cal_ctx->rng_pkt_low = 0x14; + cal_ctx->rng_pkt_high = 0x14; + cal_ctx->req_packet[4] = 0x01; + cal_ctx->req_packet[6] = cal_ctx->bs_lows[0] + ((cal_ctx->bs_highs[0] - cal_ctx->bs_lows[0]) / 2); + fpi_ssm_jump_to_state (ssm, SM_CAL_RNG_PKT_REQ); + } + else + { + cal_ctx->cal_step += 3; // Based on calibration_procedure. // + fpi_ssm_jump_to_state (ssm, SM_CAL_STEP_LOGIC); + } + break; + + + case CAL_NO_IMG_16_BS_CHK_SET_15: + if (cal_ctx->bs_condition && cal_ctx->bs_steps < 7) + { + cal_ctx->bs_twos = 0; + cal_ctx->bs_zeros = 0; + cal_ctx->bs_steps++; + + fp_dbg ("CALIBERATION: NO IMAGE 14/16: CONDITION: %b, STEPS: %d", cal_ctx->bs_condition, cal_ctx->bs_steps); + fp_dbg ("CALIBERATION: NO IMAGE 14/16: LOW: %x, HIGH: %x", cal_ctx->bs_lows[0], cal_ctx->bs_highs[0]); + + self->save_resp = FALSE; + cal_ctx->rng_pkt_low = 0x15; + cal_ctx->rng_pkt_high = 0x15; + cal_ctx->req_packet[4] = 0x01; + cal_ctx->req_packet[6] = 0x00; + fpi_ssm_jump_to_state (ssm, SM_CAL_RNG_PKT_REQ); + } + else + { + cal_ctx->cal_step += 4; // Based on calibration_procedure. + fpi_ssm_jump_to_state (ssm, SM_CAL_STEP_LOGIC); + } + break; + + case CAL_NO_IMG_16_BS_SET_16: + self->save_resp = FALSE; + cal_ctx->rng_pkt_low = 0x16; + cal_ctx->rng_pkt_high = 0x16; + cal_ctx->req_packet[4] = 0x01; + cal_ctx->req_packet[6] = cal_ctx->bs_lows[0] + ((cal_ctx->bs_highs[0] - cal_ctx->bs_lows[0]) / 2); + fpi_ssm_jump_to_state (ssm, SM_CAL_RNG_PKT_REQ); + break; + + case CAL_NO_IMG_PRE_FIRST: + set_ctx_pkts_type (self, *EGIS0570_CAL_NO_IMAGE_PRE_FIRST); + fpi_ssm_jump_to_state (ssm, SM_CAL_STATIC_PKT); + break; + + case CAL_NO_IMG_GET_8: + /* repeat this case*/ + if (cal_ctx->repeat_step == 0) + { + + if (self->saved_resp == 0x02) + cal_ctx->bs_twos++; + else if(self->saved_resp == 0x00) + cal_ctx->bs_zeros++; + else + fp_dbg ("unexpected value for no img 14/16 request (%x)", self->saved_resp); + + cal_ctx->repeat_step--; + fpi_ssm_jump_to_state (ssm, SM_CAL_STEP_LOGIC); + break; + } + cal_ctx->cal_step--; + if (cal_ctx->repeat_step == -1) + cal_ctx->repeat_step = 8; + /* end repeat */ + + if (cal_ctx->repeat_step < 8) + { + if (self->saved_resp == 0x02) + cal_ctx->bs_twos++; + else if(self->saved_resp == 0x00) + cal_ctx->bs_zeros++; + else + fp_dbg ("unexpected value for no img 14/16 request (%x)", self->saved_resp); + } + + set_ctx_pkts_type (self, *EGIS0570_CAL_NO_IMAGE_REQUEST); + self->save_resp = TRUE; + cal_ctx->repeat_step--; + fpi_ssm_jump_to_state (ssm, SM_CAL_STATIC_PKT); + break; + + + case CAL_NO_IMG_14_BS_JUMP: + if (cal_ctx->bs_twos > cal_ctx->bs_zeros) + cal_ctx->bs_highs[0] = cal_ctx->req_packet[6]; + else if (cal_ctx->bs_twos < cal_ctx->bs_zeros) + cal_ctx->bs_lows[0] = cal_ctx->req_packet[6]; + else + cal_ctx->bs_condition = 0x00; + + fp_dbg ("no image bs 14/16: twos: %d, zeros: %d.", cal_ctx->bs_twos, cal_ctx->bs_zeros); + + cal_ctx->cal_step = cal_ctx->cal_step - 4;// Based on calibration_procedure. + fpi_ssm_jump_to_state (ssm, SM_CAL_STEP_LOGIC); + break; + + + case CAL_NO_IMG_16_BS_JUMP: + if (cal_ctx->bs_twos > cal_ctx->bs_zeros) + cal_ctx->bs_highs[0] = cal_ctx->req_packet[6]; + else if (cal_ctx->bs_twos < cal_ctx->bs_zeros) + cal_ctx->bs_lows[0] = cal_ctx->req_packet[6]; + else + cal_ctx->bs_condition = 0x00; + + fp_dbg ("no image bs 14/16: twos: %d, zeros: %d.", cal_ctx->bs_twos, cal_ctx->bs_zeros); + + cal_ctx->cal_step = cal_ctx->cal_step - 5;// Based on calibration_procedure. + fpi_ssm_jump_to_state (ssm, SM_CAL_STEP_LOGIC); + break; + + case CAL_NO_IMG_14_BS_END: + if (cal_ctx->bs_steps >= 6) + fp_dbg ("CALIBERATION: ERROR EXTRA STEPS ON BINARY SEARCH."); + + /* save in list */ + fp_dbg ("NO BS 14 found value (%x), set value (0x00)", cal_ctx->req_packet[6]); + self->persistent_data[8] = 0x00; + + fpi_ssm_jump_to_state (ssm, SM_CAL_STEP_LOGIC); + break; + + case CAL_NO_IMG_16_BS_SET: + cal_ctx->bs_steps = 0; + cal_ctx->bs_condition = 0x01; + cal_ctx->bs_mid = 0; + cal_ctx->bs_lows[0] = 0x00; + cal_ctx->bs_highs[0] = 0x7f; + + fpi_ssm_jump_to_state (ssm, SM_CAL_STEP_LOGIC); + break; + + case CAL_NO_IMG_16_BS_END: + if (cal_ctx->bs_steps >= 7) + fp_dbg ("CALIBERATION: ERROR EXTRA STEPS ON BINARY SEARCH."); + + /* save in list */ + fp_dbg ("NO BS 16 found value (%x), set value (0x0a)", cal_ctx->req_packet[6]); + self->persistent_data[7] = 0x0a; + + fpi_ssm_jump_to_state (ssm, SM_CAL_STEP_LOGIC); + break; + + case CAL_END: + fpi_ssm_jump_to_state (ssm, SM_CAL_DONE); + break; + + default: + g_assert_not_reached (); + } +} + +static void +ssm_cal_run_state (FpiSsm *ssm, FpDevice *dev) +{ + FpDeviceEgis0570 *self = FPI_DEVICE_EGIS0570 (dev); + struct CalibrationContext *cal_ctx = self->cal_ctx; + + switch (fpi_ssm_get_cur_state (ssm)) + { + case SM_CAL_INIT: + cal_ctx->cal_step = -1; + cal_ctx->repeat_step = -1; + cal_ctx->calibration_images = g_malloc (EGIS0570_CAL_IMG_TOT * EGIS0570_IMGSIZE); + memcpy (cal_ctx->req_packet, EGIS0570_CAL_NO_IMAGE_REQUEST[1], EGIS0570_PKTSIZE); + cal_ctx->cal_img_idx = 0; + cal_ctx->pkt_02_value = 0xff; + + self->pkt_num = 0; + self->pkt_type = 0; + self->persistent_data = g_malloc0 (PRESISTENT_DATA_LENGTH); + self->save_resp = FALSE; + self->saved_resp = 0x00; + fpi_ssm_next_state (ssm); + break; + + case SM_CAL_STEP_LOGIC: + apply_next_step_setting (ssm, self); + break; + + case SM_CAL_STATIC_PKT: + set_ctx_pkts (self); + fpi_ssm_next_state (ssm); + break; + + case SM_CAL_REQ: + send_cmd_req (ssm, dev, cal_ctx->pkt_ptr + (EGIS0570_PKTSIZE * self->pkt_num)); + break; + + case SM_CAL_RESP: + if (is_last_pkt (dev) == FALSE) + { + self->pkt_num += 1; + self->resp_state = SM_CAL_REQ; + recv_cmd_resp (ssm, dev); + } + else + { + if (cal_ctx->img_resp) + { + recv_cal_data_resp (ssm, dev); + } + else + { + self->resp_state = SM_CAL_STEP_LOGIC; + recv_cmd_resp (ssm, dev); + } + } + break; + + case SM_CAL_RNG_PKT_REQ: + if (cal_ctx->rng_pkt_low <= cal_ctx->rng_pkt_high) + { + cal_ctx->req_packet[5] = cal_ctx->rng_pkt_low; + send_cmd_req (ssm, dev, cal_ctx->req_packet); + } + else + { + fpi_ssm_jump_to_state (ssm, SM_CAL_STEP_LOGIC); + } + break; + + case SM_CAL_RNG_PKT_RESP: + cal_ctx->rng_pkt_low++; + self->resp_state = SM_CAL_RNG_PKT_REQ; + recv_cmd_resp (ssm, dev); + break; + + + case SM_CAL_BS_PK_REQ: + if (self->pkt_num < EGIS0570_CAL_BS_ELM) + { + if (cal_ctx->bs_condition & (1 << self->pkt_num)) + { + cal_ctx->bs_mid = cal_ctx->bs_lows[self->pkt_num] + ((cal_ctx->bs_highs[self->pkt_num] - cal_ctx->bs_lows[self->pkt_num]) / 2); + cal_ctx->bs_pkts[self->pkt_num * EGIS0570_PKTSIZE + 6] = cal_ctx->bs_mid; + cal_ctx->pkt_02_value = (cal_ctx->pkt_02_value > cal_ctx->bs_mid) ? cal_ctx->bs_mid : cal_ctx->pkt_02_value; + send_cmd_req (ssm, dev, cal_ctx->bs_pkts + (self->pkt_num * EGIS0570_PKTSIZE)); + } + else + { + self->pkt_num++; + fpi_ssm_jump_to_state (ssm, SM_CAL_BS_PK_REQ); + } + } + else + { + fpi_ssm_jump_to_state (ssm, SM_CAL_STEP_LOGIC); + } + break; + + case SM_CAL_BS_PK_RESP: + self->pkt_num += 1; + self->resp_state = SM_CAL_BS_PK_REQ; + recv_cmd_resp (ssm, dev); + break; + + case SM_CAL_CHK_NEW_CNF_REQ: + if (self->pkt_num == (EGIS0570_CAL_BS_ELM * 2 - 1)) + { + fpi_ssm_jump_to_state (ssm, SM_CAL_STEP_LOGIC); + } + else + { + if (self->pkt_num < 6) + { + send_cmd_req (ssm, dev, cal_ctx->bs_pkts + (self->pkt_num * EGIS0570_PKTSIZE)); + } + else if (self->pkt_num < 12) + { + cal_ctx->bs_pkts[(self->pkt_num - 6) * EGIS0570_PKTSIZE + 5] = 0x58 - (self->pkt_num - 6); + send_cmd_req (ssm, dev, cal_ctx->bs_pkts + ((self->pkt_num - 6) * EGIS0570_PKTSIZE)); + } + else + { + cal_ctx->bs_pkts[6 * EGIS0570_PKTSIZE + 6] = 0x00; + send_cmd_req (ssm, dev, cal_ctx->bs_pkts + (6 * EGIS0570_PKTSIZE)); + } + } + break; + + case SM_CAL_CHK_NEW_CNF_RESP: + self->pkt_num += 1; + self->resp_state = SM_CAL_CHK_NEW_CNF_REQ; + recv_cmd_resp (ssm, dev); + break; + + case SM_CAL_DONE: + g_clear_pointer (&cal_ctx->calibration_images, g_free); + fpi_ssm_mark_completed (ssm); + break; + + default: + g_assert_not_reached (); + } +} + +static void +set_query_pkts (FpDeviceEgis0570 *self, guchar * data) +{ + // 20, 58 + self->query_pkts[0][6] = data[0]; + self->query_pkts[1][6] = data[0]; + // 21, 57 + self->query_pkts[2][6] = data[1]; + self->query_pkts[3][6] = data[1]; + // 22, 56 + self->query_pkts[4][6] = data[2]; + self->query_pkts[5][6] = data[2]; + // 23, 55 + self->query_pkts[6][6] = data[3]; + self->query_pkts[7][6] = data[3]; + // 24, 54 + self->query_pkts[8][6] = data[4]; + self->query_pkts[9][6] = data[4]; + // 25, 53 + self->query_pkts[10][6] = data[5]; + self->query_pkts[11][6] = data[5]; + // 16 + self->query_pkts[12][6] = data[6]; + // 9 + self->query_pkts[13][6] = data[7]; + // 14 + self->query_pkts[14][6] = data[8]; +} + /* * Activation */ @@ -362,6 +1250,47 @@ dev_activate (FpImageDevice *dev) fpi_image_device_activate_complete (dev, NULL); } + +/* + * Calibration Activation + */ + +static void +cal_loop_complete (FpiSsm *ssm, FpDevice *dev, GError *error) +{ + FpImageDevice *img_dev = FP_IMAGE_DEVICE (dev); + FpDeviceEgis0570 *self = FPI_DEVICE_EGIS0570 (dev); + + set_query_pkts (self, self->persistent_data); + + GError *save_error = NULL; + fp_device_set_persistent_data (dev, self->persistent_data, PRESISTENT_DATA_LENGTH, &save_error); + + if (save_error) + fpi_image_device_session_error (img_dev, save_error); + + g_clear_pointer (&self->persistent_data, g_free); + + g_clear_pointer (&self->cal_ctx, g_free); + + if (error) + fpi_image_device_session_error (img_dev, error); + + fpi_image_device_open_complete (img_dev, error); +} + +static void +cal_activate (FpImageDevice *dev) +{ + FpiSsm *ssm = fpi_ssm_new (FP_DEVICE (dev), ssm_cal_run_state, SM_CAL_NUM); + FpDeviceEgis0570 *self = FPI_DEVICE_EGIS0570 (dev); + + self->calibrating = TRUE; + self->cal_ctx = malloc (sizeof (struct CalibrationContext)); + + fpi_ssm_start (ssm, cal_loop_complete); +} + /* * Opening */ @@ -373,7 +1302,42 @@ dev_init (FpImageDevice *dev) g_usb_device_claim_interface (fpi_device_get_usb_device (FP_DEVICE (dev)), 0, 0, &error); - fpi_image_device_open_complete (dev, error); + FpDeviceEgis0570 *self = FPI_DEVICE_EGIS0570 (dev); + memcpy (self->query_pkts, init_pkts, EGIS0570_INIT_TOTAL * EGIS0570_PKTSIZE); + fp_dbg ("initialization"); + + switch (fpi_device_get_driver_data (FP_DEVICE (dev))) + { + case PACKET_VERSION_1: + fpi_image_device_open_complete (dev, error); + fp_dbg ("static driver"); + break; + + case PACKET_CALIBRATION: + fp_dbg ("calibration driver"); + + gsize length; + // check if caliberation happend + if (fp_device_get_persistent_data (FP_DEVICE (dev), &self->persistent_data, &length, &error)) + { + if (length == PRESISTENT_DATA_LENGTH) + { + fp_dbg ("saved data"); + + set_query_pkts (self, self->persistent_data); + + fpi_image_device_open_complete (dev, error); + } + else + { + fp_dbg ("no Saved data, len is: %ld", length); + g_clear_pointer (&self->persistent_data, g_free); + cal_activate (dev); + } + } + break; + } + } /* @@ -410,9 +1374,11 @@ dev_deactivate (FpImageDevice *dev) */ static const FpIdEntry id_table[] = { - { .vid = 0x1c7a, .pid = 0x0570, }, - { .vid = 0x1c7a, .pid = 0x0571, }, - { .vid = 0, .pid = 0, }, + { .vid = 0x1c7a, .pid = 0x0570, .driver_data = PACKET_VERSION_1}, + { .vid = 0x1c7a, .pid = 0x0570, .driver_data = PACKET_CALIBRATION}, + { .vid = 0x1c7a, .pid = 0x0571, .driver_data = PACKET_VERSION_1}, + { .vid = 0x1c7a, .pid = 0x0571, .driver_data = PACKET_CALIBRATION}, + { .vid = 0, .pid = 0, .driver_data = 0}, }; static void diff --git a/libfprint/drivers/egis0570.h b/libfprint/drivers/egis0570.h index 2c8f0457..6227ef13 100644 --- a/libfprint/drivers/egis0570.h +++ b/libfprint/drivers/egis0570.h @@ -18,10 +18,13 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "drivers_api.h" + #ifndef __EGIS0570_H #define __EGIS0570_H 1 + /* * Device data */ @@ -54,6 +57,33 @@ #define EGIS0570_INIT_TOTAL (sizeof ((init_pkts)) / sizeof ((init_pkts[0]))) +// static unsigned char init_pkts[][EGIS0570_PKTSIZE] = +// { +// { 0x45, 0x47, 0x49, 0x53, 0x01, 0x20, 0x3f }, +// { 0x45, 0x47, 0x49, 0x53, 0x01, 0x58, 0x3f }, +// { 0x45, 0x47, 0x49, 0x53, 0x01, 0x21, 0x09 }, +// { 0x45, 0x47, 0x49, 0x53, 0x01, 0x57, 0x09 }, +// { 0x45, 0x47, 0x49, 0x53, 0x01, 0x22, 0x03 }, +// { 0x45, 0x47, 0x49, 0x53, 0x01, 0x56, 0x03 }, +// { 0x45, 0x47, 0x49, 0x53, 0x01, 0x23, 0x01 }, +// { 0x45, 0x47, 0x49, 0x53, 0x01, 0x55, 0x01 }, +// { 0x45, 0x47, 0x49, 0x53, 0x01, 0x24, 0x01 }, +// { 0x45, 0x47, 0x49, 0x53, 0x01, 0x54, 0x01 }, +// { 0x45, 0x47, 0x49, 0x53, 0x01, 0x16, 0x3e }, +// { 0x45, 0x47, 0x49, 0x53, 0x01, 0x09, 0x0b }, +// { 0x45, 0x47, 0x49, 0x53, 0x01, 0x14, 0x03 }, +// { 0x45, 0x47, 0x49, 0x53, 0x01, 0x15, 0x00 }, +// { 0x45, 0x47, 0x49, 0x53, 0x01, 0x02, 0x0f }, +// { 0x45, 0x47, 0x49, 0x53, 0x01, 0x10, 0x00 }, +// { 0x45, 0x47, 0x49, 0x53, 0x01, 0x11, 0x38 }, +// { 0x45, 0x47, 0x49, 0x53, 0x01, 0x12, 0x00 }, +// { 0x45, 0x47, 0x49, 0x53, 0x01, 0x13, 0x71 }, +// { 0x45, 0x47, 0x49, 0x53, 0x01, 0x03, 0x80 }, +// { 0x45, 0x47, 0x49, 0x53, 0x00, 0x02, 0x80 }, +// { 0x45, 0x47, 0x49, 0x53, 0x01, 0x02, 0x2f }, +// { 0x45, 0x47, 0x49, 0x53, 0x06, 0x00, 0xfe } /* image returned after this packet */ +// }; + static unsigned char init_pkts[][EGIS0570_PKTSIZE] = { { 0x45, 0x47, 0x49, 0x53, 0x01, 0x20, 0x3f }, @@ -66,6 +96,8 @@ static unsigned char init_pkts[][EGIS0570_PKTSIZE] = { 0x45, 0x47, 0x49, 0x53, 0x01, 0x55, 0x01 }, { 0x45, 0x47, 0x49, 0x53, 0x01, 0x24, 0x01 }, { 0x45, 0x47, 0x49, 0x53, 0x01, 0x54, 0x01 }, + { 0x45, 0x47, 0x49, 0x53, 0x01, 0x25, 0x00 }, + { 0x45, 0x47, 0x49, 0x53, 0x01, 0x53, 0x00 }, { 0x45, 0x47, 0x49, 0x53, 0x01, 0x16, 0x3e }, { 0x45, 0x47, 0x49, 0x53, 0x01, 0x09, 0x0b }, { 0x45, 0x47, 0x49, 0x53, 0x01, 0x14, 0x03 }, @@ -175,3 +207,386 @@ static unsigned char repeat_pkts[][EGIS0570_PKTSIZE] = #define EGIS0570_RESIZE 2 #endif + + +// Calibration + +enum driver_version { + NONE, + PACKET_VERSION_1, + PACKET_CALIBRATION, +}; + +#define PRESISTENT_DATA_LENGTH 9 +#define EGIS0570_CAL_IMG_TOT 124 +#define EGIS0570_CAL_INPSIZE 6528 +#define EGIS0570_CAL_BS_ELM 7 + + +#define IMG_COL_IGNORE 23 +#define TARGET_UPPER 80 +#define TARGET_LOWER 70 +// #define SIDE_DIFF (-10) +#define SIDE_DIFF (+5) + +/* static pkts */ +static guint8 EGIS0570_CAL_CONFIGURATION_MODE_PKT[][EGIS0570_PKTSIZE] = +{ + {0x45, 0x47, 0x49, 0x53, 0x01, 0x0d, 0x00}, + {0x45, 0x47, 0x49, 0x53, 0x01, 0x0e, 0x00}, + {0x45, 0x47, 0x49, 0x53, 0x01, 0x02, 0x1f}, + {0x45, 0x47, 0x49, 0x53, 0x01, 0x05, 0x08}, + {0x45, 0x47, 0x49, 0x53, 0x01, 0x03, 0xff} +}; + +static guint8 EGIS0570_CAL_PKT_ZERO_RANGE[][EGIS0570_PKTSIZE] = +{ + {0x45, 0x47, 0x49, 0x53, 0x01, 0x01, 0x10}, + {0x45, 0x47, 0x49, 0x53, 0x01, 0x02, 0x00}, + {0x45, 0x47, 0x49, 0x53, 0x01, 0x03, 0x80}, + {0x45, 0x47, 0x49, 0x53, 0x01, 0x04, 0x00}, + {0x45, 0x47, 0x49, 0x53, 0x01, 0x05, 0x08}, + {0x45, 0x47, 0x49, 0x53, 0x01, 0x06, 0x00}, + {0x45, 0x47, 0x49, 0x53, 0x01, 0x07, 0x00}, + {0x45, 0x47, 0x49, 0x53, 0x01, 0x08, 0x00}, + {0x45, 0x47, 0x49, 0x53, 0x01, 0x09, 0x0a}, + {0x45, 0x47, 0x49, 0x53, 0x01, 0x0a, 0x00}, + {0x45, 0x47, 0x49, 0x53, 0x01, 0x0b, 0x00}, + {0x45, 0x47, 0x49, 0x53, 0x01, 0x0c, 0xff}, + {0x45, 0x47, 0x49, 0x53, 0x01, 0x0d, 0x00}, + {0x45, 0x47, 0x49, 0x53, 0x01, 0x0e, 0x00} +}; + + +static guint8 EGIS0570_CAL_CAPTURING_AREA[][EGIS0570_PKTSIZE] = +{ + {0x45, 0x47, 0x49, 0x53, 0x01, 0x10, 0x00}, + {0x45, 0x47, 0x49, 0x53, 0x01, 0x11, 0x38}, + {0x45, 0x47, 0x49, 0x53, 0x01, 0x12, 0x00}, + {0x45, 0x47, 0x49, 0x53, 0x01, 0x13, 0x71} +}; + +static guint8 EGIS0570_CAL_SENSOR_AND_EMITTER[][EGIS0570_PKTSIZE] = +{ + {0x45, 0x47, 0x49, 0x53, 0x01, 0x14, 0x15}, + {0x45, 0x47, 0x49, 0x53, 0x01, 0x15, 0x00}, + {0x45, 0x47, 0x49, 0x53, 0x01, 0x16, 0x08} +}; + + +static guint8 EGIS0570_CAL_WHITE_SETTING[][EGIS0570_PKTSIZE] = +{ + {0x45, 0x47, 0x49, 0x53, 0x01, 0x09, 0x0f}, + {0x45, 0x47, 0x49, 0x53, 0x01, 0x14, 0x3f}, + {0x45, 0x47, 0x49, 0x53, 0x01, 0x15, 0x00}, + {0x45, 0x47, 0x49, 0x53, 0x01, 0x16, 0x00}, + {0x45, 0x47, 0x49, 0x53, 0x00, 0x02, 0x00} +}; + +static guint8 EGIS0570_CAL_BLACK_WHITE_GET_IMAGE[][EGIS0570_PKTSIZE] = +{ + {0x45, 0x47, 0x49, 0x53, 0x01, 0x02, 0x20}, + {0x45, 0x47, 0x49, 0x53, 0x06, 0x00, 0x33} +}; + +static guint8 EGIS0570_CAL_BLACK_WHITE_AFTER_IMAGE[][EGIS0570_PKTSIZE] = +{ + {0x45, 0x47, 0x49, 0x53, 0x01, 0x02, 0x00} +}; + +static guint8 EGIS0570_CAL_BLACK_SETTING[][EGIS0570_PKTSIZE] = +{ + {0x45, 0x47, 0x49, 0x53, 0x01, 0x09, 0x00}, + {0x45, 0x47, 0x49, 0x53, 0x01, 0x14, 0x00}, + {0x45, 0x47, 0x49, 0x53, 0x01, 0x15, 0x03}, + {0x45, 0x47, 0x49, 0x53, 0x01, 0x16, 0xff}, + {0x45, 0x47, 0x49, 0x53, 0x00, 0x02, 0xff} +}; + +static guint8 EGIS0570_CAL_BLACK_WHITE_CLEAR[][EGIS0570_PKTSIZE] = +{ + {0x45, 0x47, 0x49, 0x53, 0x01, 0x15, 0x00}, + {0x45, 0x47, 0x49, 0x53, 0x01, 0x16, 0x00}, + {0x45, 0x47, 0x49, 0x53, 0x01, 0x09, 0x00}, + {0x45, 0x47, 0x49, 0x53, 0x01, 0x14, 0x00}, + {0x45, 0x47, 0x49, 0x53, 0x01, 0x02, 0x0f}, + {0x45, 0x47, 0x49, 0x53, 0x01, 0x03, 0x80}, + {0x45, 0x47, 0x49, 0x53, 0x01, 0x09, 0x00}, + {0x45, 0x47, 0x49, 0x53, 0x01, 0x14, 0x00}, + {0x45, 0x47, 0x49, 0x53, 0x01, 0x15, 0x00}, + {0x45, 0x47, 0x49, 0x53, 0x01, 0x16, 0x00} +}; + + +static guint8 EGIS0570_CAL_MIDDLE_BLACK_SETTING[][EGIS0570_PKTSIZE] = +{ + {0x45, 0x47, 0x49, 0x53, 0x01, 0x09, 0x0a}, + {0x45, 0x47, 0x49, 0x53, 0x01, 0x15, 0x00}, + {0x45, 0x47, 0x49, 0x53, 0x01, 0x16, 0x7f}, + {0x45, 0x47, 0x49, 0x53, 0x00, 0x02, 0x7f}, + {0x45, 0x47, 0x49, 0x53, 0x01, 0x02, 0x2f} +}; + +static guint8 EGIS0570_CAL_GET_IMAGE[][EGIS0570_PKTSIZE] = +{ + {0x45, 0x47, 0x49, 0x53, 0x06, 0x00, 0x33} +}; + +static guint8 EGIS0570_CAL_AFTER_IMAGE[][EGIS0570_PKTSIZE] = +{ + {0x45, 0x47, 0x49, 0x53, 0x01, 0x02, 0x0f} +}; + +static guint8 EGIS0570_CAL_REPEAT[][EGIS0570_PKTSIZE] = +{ + {0x45, 0x47, 0x49, 0x53, 0x00, 0x02, 0x0f}, + {0x45, 0x47, 0x49, 0x53, 0x01, 0x02, 0x2f} +}; + +static guint8 EGIS0570_CAL_BORDER_WHITE_SETTING[][EGIS0570_PKTSIZE] = +{ + {0x45, 0x47, 0x49, 0x53, 0x01, 0x09, 0x0a}, + {0x45, 0x47, 0x49, 0x53, 0x01, 0x15, 0x00}, + {0x45, 0x47, 0x49, 0x53, 0x01, 0x16, 0x3f}, + {0x45, 0x47, 0x49, 0x53, 0x00, 0x02, 0x3f}, + {0x45, 0x47, 0x49, 0x53, 0x01, 0x02, 0x2f} +}; + + +static guint8 EGIS0570_CAL_FIRST_BS_SETTING[][EGIS0570_PKTSIZE] = +{ + {0x45, 0x47, 0x49, 0x53, 0x01, 0x15, 0x00}, + {0x45, 0x47, 0x49, 0x53, 0x01, 0x16, 0x00}, +}; + +static guint8 EGIS0570_CAL_BEFORE_GET_IMAGE[][EGIS0570_PKTSIZE] = +{ + {0x45, 0x47, 0x49, 0x53, 0x01, 0x02, 0x2f} +}; + +static guint8 EGIS0570_CAL_NO_IMAGE_CAPTURING_AREA[][EGIS0570_PKTSIZE] = +{ + {0x45, 0x47, 0x49, 0x53, 0x01, 0x10, 0x1c}, + {0x45, 0x47, 0x49, 0x53, 0x01, 0x11, 0x1c}, + {0x45, 0x47, 0x49, 0x53, 0x01, 0x12, 0x31}, + {0x45, 0x47, 0x49, 0x53, 0x01, 0x13, 0x40} +}; + +static guint8 EGIS0570_CAL_NO_IMAGE_SETTING_0[][EGIS0570_PKTSIZE] = +{ + {0x45, 0x47, 0x49, 0x53, 0x01, 0x09, 0x05}, + {0x45, 0x47, 0x49, 0x53, 0x01, 0x14, 0x00}, + {0x45, 0x47, 0x49, 0x53, 0x01, 0x15, 0x00}, + {0x45, 0x47, 0x49, 0x53, 0x01, 0x16, 0x00}, + {0x45, 0x47, 0x49, 0x53, 0x01, 0x08, 0x1c} +}; + +static guint8 EGIS0570_CAL_NO_IMAGE_BINARY_14_SETTING[][EGIS0570_PKTSIZE] = +{ + {0x45, 0x47, 0x49, 0x53, 0x01, 0x0b, 0x00}, + {0x45, 0x47, 0x49, 0x53, 0x01, 0x0c, 0xff}, + {0x45, 0x47, 0x49, 0x53, 0x01, 0x0d, 0x00}, + {0x45, 0x47, 0x49, 0x53, 0x01, 0x0e, 0xff}, + {0x45, 0x47, 0x49, 0x53, 0x01, 0x02, 0x1d}, + {0x45, 0x47, 0x49, 0x53, 0x01, 0x04, 0x00} +}; + +static guint8 EGIS0570_CAL_NO_IMAGE_PRE_FIRST[][EGIS0570_PKTSIZE] = +{ + {0x45, 0x47, 0x49, 0x53, 0x01, 0x01, 0x00}, + {0x45, 0x47, 0x49, 0x53, 0x00, 0x01, 0x00} +}; + + +static guint8 EGIS0570_CAL_NO_IMAGE_REQUEST[][EGIS0570_PKTSIZE] = +{ + {0x45, 0x47, 0x49, 0x53, 0x01, 0x01, 0x00}, + {0x45, 0x47, 0x49, 0x53, 0x00, 0x01, 0x00}, + {0x45, 0x47, 0x49, 0x53, 0x00, 0x01, 0x00} +}; + + +#define EGIS0570_CAL_STATIC_LIST_SIZEOF (sizeof ((EGIS0570_CAL_STATIC_LIST)) / sizeof ((EGIS0570_CAL_STATIC_LIST[0]))) + +static guint8 * EGIS0570_CAL_STATIC_LIST[] = { + *EGIS0570_CAL_CONFIGURATION_MODE_PKT, + *EGIS0570_CAL_PKT_ZERO_RANGE, + *EGIS0570_CAL_CAPTURING_AREA, + *EGIS0570_CAL_SENSOR_AND_EMITTER, + *EGIS0570_CAL_WHITE_SETTING, + *EGIS0570_CAL_BLACK_WHITE_GET_IMAGE, + *EGIS0570_CAL_BLACK_WHITE_AFTER_IMAGE, + *EGIS0570_CAL_BLACK_SETTING, + *EGIS0570_CAL_BLACK_WHITE_CLEAR, + *EGIS0570_CAL_MIDDLE_BLACK_SETTING, + *EGIS0570_CAL_GET_IMAGE, + *EGIS0570_CAL_AFTER_IMAGE, + *EGIS0570_CAL_REPEAT, + *EGIS0570_CAL_BORDER_WHITE_SETTING, + *EGIS0570_CAL_FIRST_BS_SETTING, + *EGIS0570_CAL_BEFORE_GET_IMAGE, + *EGIS0570_CAL_NO_IMAGE_CAPTURING_AREA, + *EGIS0570_CAL_NO_IMAGE_SETTING_0, + *EGIS0570_CAL_NO_IMAGE_BINARY_14_SETTING, + *EGIS0570_CAL_NO_IMAGE_PRE_FIRST, + *EGIS0570_CAL_NO_IMAGE_REQUEST, +}; + + +#define EGIS0570_HELPER_PKT_SIZEOF(x) (sizeof (x) / sizeof (x[0])) + +static guint8 EGIS0570_CAL_STATIC_LIST_SIZE[] = { + EGIS0570_HELPER_PKT_SIZEOF (EGIS0570_CAL_CONFIGURATION_MODE_PKT), + EGIS0570_HELPER_PKT_SIZEOF (EGIS0570_CAL_PKT_ZERO_RANGE), + EGIS0570_HELPER_PKT_SIZEOF (EGIS0570_CAL_CAPTURING_AREA), + EGIS0570_HELPER_PKT_SIZEOF (EGIS0570_CAL_SENSOR_AND_EMITTER), + EGIS0570_HELPER_PKT_SIZEOF (EGIS0570_CAL_WHITE_SETTING), + EGIS0570_HELPER_PKT_SIZEOF (EGIS0570_CAL_BLACK_WHITE_GET_IMAGE), + EGIS0570_HELPER_PKT_SIZEOF (EGIS0570_CAL_BLACK_WHITE_AFTER_IMAGE), + EGIS0570_HELPER_PKT_SIZEOF (EGIS0570_CAL_BLACK_SETTING), + EGIS0570_HELPER_PKT_SIZEOF (EGIS0570_CAL_BLACK_WHITE_CLEAR), + EGIS0570_HELPER_PKT_SIZEOF (EGIS0570_CAL_MIDDLE_BLACK_SETTING), + EGIS0570_HELPER_PKT_SIZEOF (EGIS0570_CAL_GET_IMAGE), + EGIS0570_HELPER_PKT_SIZEOF (EGIS0570_CAL_AFTER_IMAGE), + EGIS0570_HELPER_PKT_SIZEOF (EGIS0570_CAL_REPEAT), + EGIS0570_HELPER_PKT_SIZEOF (EGIS0570_CAL_BORDER_WHITE_SETTING), + EGIS0570_HELPER_PKT_SIZEOF (EGIS0570_CAL_FIRST_BS_SETTING), + EGIS0570_HELPER_PKT_SIZEOF (EGIS0570_CAL_BEFORE_GET_IMAGE), + EGIS0570_HELPER_PKT_SIZEOF (EGIS0570_CAL_NO_IMAGE_CAPTURING_AREA), + EGIS0570_HELPER_PKT_SIZEOF (EGIS0570_CAL_NO_IMAGE_SETTING_0), + EGIS0570_HELPER_PKT_SIZEOF (EGIS0570_CAL_NO_IMAGE_BINARY_14_SETTING), + EGIS0570_HELPER_PKT_SIZEOF (EGIS0570_CAL_NO_IMAGE_PRE_FIRST), + EGIS0570_HELPER_PKT_SIZEOF (EGIS0570_CAL_NO_IMAGE_REQUEST), +}; + + +/* Calibration logic */ +enum cal_proc_en { + CAL_CONF_PKT, + CAL_PKT_ZERO_RNG, + CAL_CAPT_AREA, + CAL_SENS_AND_EMIT, + CAL_RNG_20_58, + CAL_RNG_60_D0, + CAL_WHITE_SET, + CAL_BLACK_WHITE_GET_IMG, + CAL_BLACK_WHITE_AFTER_IMAGE, + CAL_BLACK_SET, + CAL_CHECK_BLACK_WHITE, + CAL_5_ROWS_ZEROS, + CAL_BLACK_WHITE_CLEAR, + CAL_RNG_60_D1, + CAL_MID_BLACK_SET, + CAL_GET_IMG, + CAL_AFTER_IMG, + CAL_GET_9, + CAL_BORDER_WHITE_SET, + CAL_FIRST_BS_SET, + CAL_BS_CHK_SET, + CAL_PKT_02, + CAL_BEFORE_IMG, + CAL_BS_JUMP, + CAL_BS_END, + CAL_PKT_15_0, + CAL_PKT_16_3C, + CAL_CHK_NEW_CONF, + CAL_GET_21, + CAL_NO_IMG_CAP_AREA, + CAL_NO_IMG_SET_0, + CAL_NO_IMG_03_1C, + CAL_NO_CHK_03_80, + CAL_NO_SET_03_80, + CAL_NO_IMG_14_BS_SET, + CAL_NO_IMG_14_BS_CHK_SET, + CAL_NO_IMG_PRE_FIRST, + CAL_NO_IMG_GET_8, + CAL_NO_IMG_14_BS_JUMP, + CAL_NO_IMG_14_BS_END, + CAL_NO_IMG_16_BS_SET, + CAL_NO_IMG_16_BS_CHK_SET_15, + CAL_NO_IMG_16_BS_SET_16, + CAL_NO_IMG_16_BS_JUMP, + CAL_NO_IMG_16_BS_END, + + + CAL_END, +}; + + +#define EGIS0570_CAL_PROC_SIZEOF (sizeof ((calibration_procedure)) / sizeof ((calibration_procedure[0]))) + +static guint8 calibration_procedure[] = { + // conf + CAL_CONF_PKT, + // sensor check + CAL_PKT_ZERO_RNG, + CAL_CAPT_AREA, + CAL_SENS_AND_EMIT, + CAL_RNG_20_58, + CAL_RNG_60_D0, + CAL_WHITE_SET, + CAL_BLACK_WHITE_GET_IMG, + CAL_BLACK_WHITE_AFTER_IMAGE, + CAL_BLACK_SET, + CAL_BLACK_WHITE_GET_IMG, + CAL_BLACK_WHITE_AFTER_IMAGE, + CAL_CHECK_BLACK_WHITE, + // not binary 16 + CAL_CAPT_AREA, + CAL_5_ROWS_ZEROS, + CAL_BLACK_WHITE_CLEAR, + CAL_RNG_20_58, + CAL_RNG_60_D1, + CAL_MID_BLACK_SET, + CAL_GET_IMG, + CAL_AFTER_IMG, + CAL_GET_9, + CAL_BORDER_WHITE_SET, + CAL_GET_IMG, + CAL_AFTER_IMG, + CAL_GET_9, + // binary + CAL_FIRST_BS_SET, + CAL_BS_CHK_SET, // 0 + CAL_PKT_02, // 1 + CAL_BEFORE_IMG, // 2 + CAL_GET_IMG, // 3 + CAL_AFTER_IMG, // 4 + CAL_GET_9, // 5 + CAL_BS_JUMP, // 6 + CAL_BS_END, // 7 + // check pictures. + CAL_PKT_15_0, + CAL_PKT_16_3C, + CAL_CHK_NEW_CONF, + CAL_PKT_02, + CAL_BEFORE_IMG, + CAL_GET_IMG, + CAL_AFTER_IMG, + CAL_GET_21, + // no image 14 + CAL_NO_IMG_CAP_AREA, + CAL_NO_IMG_SET_0, + CAL_NO_IMG_03_1C, + CAL_NO_CHK_03_80, + CAL_NO_SET_03_80, + CAL_NO_IMG_14_BS_SET, + CAL_NO_IMG_14_BS_CHK_SET, // 0 + CAL_NO_IMG_PRE_FIRST, // 1 + CAL_NO_IMG_GET_8, // 2 + CAL_NO_IMG_14_BS_JUMP, // 3 + CAL_NO_IMG_14_BS_END, // 4 + // no image 16 + CAL_NO_IMG_16_BS_SET, + CAL_NO_IMG_16_BS_CHK_SET_15, // 0 + CAL_NO_IMG_16_BS_SET_16, // 1 + CAL_NO_IMG_PRE_FIRST, // 2 + CAL_NO_IMG_GET_8, // 3 + CAL_NO_IMG_16_BS_JUMP, // 4 + CAL_NO_IMG_16_BS_END, // 5 + // end + CAL_CONF_PKT, + CAL_CONF_PKT, + + CAL_END, +}; From 05f763102346fc5f1afcf5ea90281c0b3844332a Mon Sep 17 00:00:00 2001 From: saeedark Date: Tue, 28 Oct 2025 17:18:58 +0330 Subject: [PATCH 3/3] chore: clean up --- libfprint/drivers/egis0570.c | 29 +++++++++++++++++------------ libfprint/drivers/egis0570.h | 6 +++--- 2 files changed, 20 insertions(+), 15 deletions(-) diff --git a/libfprint/drivers/egis0570.c b/libfprint/drivers/egis0570.c index a4d36eb3..5eec4bd6 100644 --- a/libfprint/drivers/egis0570.c +++ b/libfprint/drivers/egis0570.c @@ -454,16 +454,16 @@ static void set_ctx_pkts_type (FpDeviceEgis0570 *self, guint8 * element_ptr) { self->pkt_type = -1; - fp_dbg ("Error in indexing should not happen"); for (guint8 i = 0; i < EGIS0570_CAL_STATIC_LIST_SIZEOF; i++) { if (EGIS0570_CAL_STATIC_LIST[i] == element_ptr) { self->pkt_type = i; - fp_dbg ("said index %d", i); - break; + fp_dbg ("ptr said index %d", i); + return; } } + fp_dbg ("messed up list for static packets"); } static void @@ -527,7 +527,7 @@ apply_next_step_setting (FpiSsm *ssm, FpDeviceEgis0570 *self) if (cal_ctx->cal_step == EGIS0570_CAL_PROC_SIZEOF) { - fp_dbg ("something went wrong."); + fp_dbg ("calibration step is higher thatn expected."); return; } fp_dbg ("Procedure Index %d", cal_ctx->cal_step); @@ -741,6 +741,7 @@ apply_next_step_setting (FpiSsm *ssm, FpDeviceEgis0570 *self) case CAL_BS_CHK_SET: if (cal_ctx->bs_condition && cal_ctx->bs_steps < 8) { + cal_ctx->cal_img_idx = 0; cal_ctx->bs_steps++; fp_dbg ("CALIBERATION: BINARY SEARCH: CONDITION: %b, STEPS: %d", cal_ctx->bs_condition, cal_ctx->bs_steps); for (guint8 i = 0; i < EGIS0570_CAL_BS_ELM; i++) @@ -806,6 +807,8 @@ apply_next_step_setting (FpiSsm *ssm, FpDeviceEgis0570 *self) case CAL_PKT_15_0: + cal_ctx->cal_img_idx = 0; + cal_ctx->rng_pkt_low = 0x15; cal_ctx->rng_pkt_high = 0x15; cal_ctx->req_packet[4] = 0x01; @@ -829,6 +832,8 @@ apply_next_step_setting (FpiSsm *ssm, FpDeviceEgis0570 *self) break; case CAL_NO_IMG_CAP_AREA: + cal_ctx->cal_img_idx = 0; + set_ctx_pkts_type (self, *EGIS0570_CAL_NO_IMAGE_CAPTURING_AREA); fpi_ssm_jump_to_state (ssm, SM_CAL_STATIC_PKT); break; @@ -880,8 +885,8 @@ apply_next_step_setting (FpiSsm *ssm, FpDeviceEgis0570 *self) cal_ctx->bs_zeros = 0; cal_ctx->bs_steps++; - fp_dbg ("CALIBERATION: NO IMAGE 14/16: CONDITION: %b, STEPS: %d", cal_ctx->bs_condition, cal_ctx->bs_steps); - fp_dbg ("CALIBERATION: NO IMAGE 14/16: LOW: %x, HIGH: %x", cal_ctx->bs_lows[0], cal_ctx->bs_highs[0]); + fp_dbg ("CALIBERATION: NO IMAGE 14: CONDITION: %b, STEPS: %d", cal_ctx->bs_condition, cal_ctx->bs_steps); + fp_dbg ("CALIBERATION: NO IMAGE 14: LOW: %x, HIGH: %x", cal_ctx->bs_lows[0], cal_ctx->bs_highs[0]); self->save_resp = FALSE; cal_ctx->rng_pkt_low = 0x14; @@ -905,8 +910,8 @@ apply_next_step_setting (FpiSsm *ssm, FpDeviceEgis0570 *self) cal_ctx->bs_zeros = 0; cal_ctx->bs_steps++; - fp_dbg ("CALIBERATION: NO IMAGE 14/16: CONDITION: %b, STEPS: %d", cal_ctx->bs_condition, cal_ctx->bs_steps); - fp_dbg ("CALIBERATION: NO IMAGE 14/16: LOW: %x, HIGH: %x", cal_ctx->bs_lows[0], cal_ctx->bs_highs[0]); + fp_dbg ("CALIBERATION: NO IMAGE 16: CONDITION: %b, STEPS: %d", cal_ctx->bs_condition, cal_ctx->bs_steps); + fp_dbg ("CALIBERATION: NO IMAGE 16: LOW: %x, HIGH: %x", cal_ctx->bs_lows[0], cal_ctx->bs_highs[0]); self->save_resp = FALSE; cal_ctx->rng_pkt_low = 0x15; @@ -982,7 +987,7 @@ apply_next_step_setting (FpiSsm *ssm, FpDeviceEgis0570 *self) else cal_ctx->bs_condition = 0x00; - fp_dbg ("no image bs 14/16: twos: %d, zeros: %d.", cal_ctx->bs_twos, cal_ctx->bs_zeros); + fp_dbg ("no image bs 14: twos: %d, zeros: %d.", cal_ctx->bs_twos, cal_ctx->bs_zeros); cal_ctx->cal_step = cal_ctx->cal_step - 4;// Based on calibration_procedure. fpi_ssm_jump_to_state (ssm, SM_CAL_STEP_LOGIC); @@ -997,7 +1002,7 @@ apply_next_step_setting (FpiSsm *ssm, FpDeviceEgis0570 *self) else cal_ctx->bs_condition = 0x00; - fp_dbg ("no image bs 14/16: twos: %d, zeros: %d.", cal_ctx->bs_twos, cal_ctx->bs_zeros); + fp_dbg ("no image bs 16: twos: %d, zeros: %d.", cal_ctx->bs_twos, cal_ctx->bs_zeros); cal_ctx->cal_step = cal_ctx->cal_step - 5;// Based on calibration_procedure. fpi_ssm_jump_to_state (ssm, SM_CAL_STEP_LOGIC); @@ -1374,10 +1379,10 @@ dev_deactivate (FpImageDevice *dev) */ static const FpIdEntry id_table[] = { - { .vid = 0x1c7a, .pid = 0x0570, .driver_data = PACKET_VERSION_1}, { .vid = 0x1c7a, .pid = 0x0570, .driver_data = PACKET_CALIBRATION}, - { .vid = 0x1c7a, .pid = 0x0571, .driver_data = PACKET_VERSION_1}, + // { .vid = 0x1c7a, .pid = 0x0570, .driver_data = PACKET_VERSION_1}, { .vid = 0x1c7a, .pid = 0x0571, .driver_data = PACKET_CALIBRATION}, + // { .vid = 0x1c7a, .pid = 0x0571, .driver_data = PACKET_VERSION_1}, { .vid = 0, .pid = 0, .driver_data = 0}, }; diff --git a/libfprint/drivers/egis0570.h b/libfprint/drivers/egis0570.h index 6227ef13..a974c434 100644 --- a/libfprint/drivers/egis0570.h +++ b/libfprint/drivers/egis0570.h @@ -212,13 +212,13 @@ static unsigned char repeat_pkts[][EGIS0570_PKTSIZE] = // Calibration enum driver_version { - NONE, - PACKET_VERSION_1, PACKET_CALIBRATION, + PACKET_VERSION_1, + NONE, }; #define PRESISTENT_DATA_LENGTH 9 -#define EGIS0570_CAL_IMG_TOT 124 +#define EGIS0570_CAL_IMG_TOT 22 //124 #define EGIS0570_CAL_INPSIZE 6528 #define EGIS0570_CAL_BS_ELM 7