From 20509027676a12f68e68707102b4f6a480007cce Mon Sep 17 00:00:00 2001 From: saeedark Date: Sun, 26 Oct 2025 20:49:20 +0330 Subject: [PATCH] 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, +};