int fpc1020_capture_buffer(fpc1020_data_t *fpc1020, u8 *data, size_t offset, size_t image_size_bytes) { int error = 0; dev_dbg(&fpc1020->spi->dev, "%s\n", __func__); error = fpc1020_cmd(fpc1020, FPC1020_CMD_CAPTURE_IMAGE, FPC_1020_IRQ_REG_BIT_FIFO_NEW_DATA); if (error < 0) goto out_error; error = fpc1020_fetch_image(fpc1020, data, offset, image_size_bytes, (size_t)fpc1020->huge_buffer_size); if (error < 0) goto out_error; return 0; out_error: dev_dbg(&fpc1020->spi->dev, "%s FAILED %d\n", __func__, error); return error; }
/* -------------------------------------------------------------------- */ int cal_thredhold(fpc1020_data_t *fpc1020) { int error = 0; int i =0; int sum =0; error = fpc1020_cmd(fpc1020,FPC1020_CMD_CAPTURE_IMAGE,FPC_1020_IRQ_REG_BIT_FIFO_NEW_DATA); if (error < 0) goto out_error; fpc1020->capture.state = FPC1020_CAPTURE_STATE_FETCH; memset(fpc1020->huge_buffer, 0 ,64); error = fpc1020_fetch_image(fpc1020, fpc1020->huge_buffer, 0, (size_t)64, (size_t)fpc1020->huge_buffer_size); if (error < 0) goto out_error; for (i = 0; i<64 ; i++) { sum += ((255 - *(fpc1020->huge_buffer+i)) >> 4); } sum = sum>>1; printk("fingerprint sum =%d\n",sum); out_error: return (error >= 0) ? sum : error; }
int fpc1020_capture_wait_finger_down(fpc1020_data_t *fpc1020) { int error = 0; int thold = 32; int addthred = 30; if( fpc1020->setup.finger_auto_threshold ){ error = fpc1020_read_irq(fpc1020, true); if (error < 0) goto out_error; error = fpc1020_cmd(fpc1020, FPC1020_CMD_FINGER_PRESENT_QUERY, FPC_1020_IRQ_REG_BIT_COMMAND_DONE); if (error < 0) goto out_error; error = fpc1020_capture_set_crop(fpc1020,fpc1020->setup.wakeup_detect_cols[0],1,fpc1020->setup.wakeup_detect_rows[0],8); if (error < 0) goto out_error; error = cal_thredhold(fpc1020); if (error < 0) goto out_error; thold = error; error = fpc1020_capture_set_crop(fpc1020,fpc1020->setup.wakeup_detect_cols[1],1,fpc1020->setup.wakeup_detect_rows[1],8); if (error < 0) goto out_error; error = cal_thredhold(fpc1020); if (error < 0) goto out_error; if(error > thold) thold = error; thold += addthred; if(thold < fpc1020->fp_thredhold && thold >= addthred) fpc1020->fp_thredhold = thold; printk("fingerprint fp_thredhold =%d default_hold=%d det1=[%d,1,%d,8] det2=[%d,1,%d,8]\n",\ fpc1020->fp_thredhold,fpc1020->setup.finger_detect_threshold,\ fpc1020->setup.wakeup_detect_cols[0],fpc1020->setup.wakeup_detect_rows[0],\ fpc1020->setup.wakeup_detect_cols[1],fpc1020->setup.wakeup_detect_rows[1]); fpc1020_wake_up(fpc1020); fpc1020_write_sensor_setup(fpc1020); } error = fpc1020_wait_finger_present(fpc1020); fpc1020_read_irq(fpc1020, true); out_error: return (error >= 0) ? 0 : error; }
int fpc1020_capture_task(fpc1020_data_t *fpc1020) { struct timespec ts_t1, ts_t2, ts_t3, ts_delta; int time_settings_us[FPC1020_BUFFER_MAX_IMAGES]; int time_capture_us[FPC1020_BUFFER_MAX_IMAGES]; int time_capture_sum_us; int error = 0; bool wait_finger_down = false; bool wait_finger_up = false; bool adjust_settings; fpc1020_capture_mode_t mode = fpc1020->capture.current_mode; int current_capture, capture_count; int image_offset; size_t image_byte_size; fpc1020->capture.state = FPC1020_CAPTURE_STATE_WRITE_SETTINGS; error = fpc1020_wake_up(fpc1020); if (error < 0) goto out_error; switch (mode) { case FPC1020_MODE_WAIT_AND_CAPTURE: wait_finger_down = wait_finger_up = true; case FPC1020_MODE_SINGLE_CAPTURE: case FPC1020_MODE_SINGLE_CAPTURE_CAL: capture_count = fpc1020->setup.capture_count; adjust_settings = true; error = fpc1020_write_capture_setup(fpc1020); break; case FPC1020_MODE_CHECKERBOARD_TEST_NORM: capture_count = 1; adjust_settings = false; error = fpc1020_write_cb_test_setup(fpc1020, false); break; case FPC1020_MODE_CHECKERBOARD_TEST_INV: capture_count = 1; adjust_settings = false; error = fpc1020_write_cb_test_setup(fpc1020, true); break; case FPC1020_MODE_BOARD_TEST_ONE: capture_count = 1; adjust_settings = false; error = fpc1020_write_test_setup(fpc1020, 0xffff); break; case FPC1020_MODE_BOARD_TEST_ZERO: capture_count = 1; adjust_settings = false; error = fpc1020_write_test_setup(fpc1020, 0x0000); break; case FPC1020_MODE_WAIT_FINGER_DOWN: wait_finger_down = true; capture_count = 0; adjust_settings = false; error = fpc1020_write_capture_setup(fpc1020); break; case FPC1020_MODE_WAIT_FINGER_UP: wait_finger_up = true; capture_count = 0; adjust_settings = false; error = fpc1020_write_capture_setup(fpc1020); break; case FPC1020_MODE_IDLE: default: capture_count = 0; adjust_settings = false; error = -EINVAL; break; } if (error < 0) goto out_error; error = fpc1020_capture_set_crop(fpc1020, fpc1020->setup.capture_col_start, fpc1020->setup.capture_col_groups, fpc1020->setup.capture_row_start, fpc1020->setup.capture_row_count); if (error < 0) goto out_error; image_byte_size = fpc1020_calc_image_size(fpc1020); dev_dbg(&fpc1020->spi->dev, "Start capture, mode %d, (%d frames)\n", mode, capture_count); if (!wait_finger_down) fpc1020->capture.deferred_finger_up = false; if (wait_finger_down) { error = fpc1020_capture_finger_detect_settings(fpc1020); if (error < 0) goto out_error; } if (wait_finger_down && fpc1020->capture.deferred_finger_up) { fpc1020->capture.state = FPC1020_CAPTURE_STATE_WAIT_FOR_FINGER_UP; dev_dbg(&fpc1020->spi->dev, "Waiting for (deferred) finger up\n"); error = fpc1020_capture_wait_finger_up(fpc1020); if (error < 0) goto out_error; dev_dbg(&fpc1020->spi->dev, "Finger up\n"); fpc1020->capture.deferred_finger_up = false; } if (wait_finger_down) { fpc1020->capture.state = FPC1020_CAPTURE_STATE_WAIT_FOR_FINGER_DOWN; error = fpc1020_capture_wait_finger_down(fpc1020); if (error < 0) goto out_error; dev_dbg(&fpc1020->spi->dev, "Finger down\n"); if (mode == FPC1020_MODE_WAIT_FINGER_DOWN) { fpc1020->capture.available_bytes = 4; fpc1020->huge_buffer[0] = 'F'; fpc1020->huge_buffer[1] = ':'; fpc1020->huge_buffer[2] = 'D'; fpc1020->huge_buffer[3] = 'N'; } } current_capture = 0; image_offset = 0; fpc1020->diag.last_capture_time = 0; if (mode == FPC1020_MODE_SINGLE_CAPTURE_CAL) { error = fpc1020_capture_set_sample_mode(fpc1020, true); if (error) goto out_error; } while (capture_count && (error >= 0)) { getnstimeofday(&ts_t1); fpc1020->capture.state = FPC1020_CAPTURE_STATE_ACQUIRE; dev_dbg(&fpc1020->spi->dev, "Capture, frame #%d \n", current_capture + 1); error = (!adjust_settings) ? 0 : fpc1020_capture_settings(fpc1020, current_capture); if (error < 0) goto out_error; getnstimeofday(&ts_t2); error = fpc1020_cmd(fpc1020, FPC1020_CMD_CAPTURE_IMAGE, FPC_1020_IRQ_REG_BIT_FIFO_NEW_DATA); if (error < 0) goto out_error; fpc1020->capture.state = FPC1020_CAPTURE_STATE_FETCH; error = fpc1020_fetch_image(fpc1020, fpc1020->huge_buffer, image_offset, image_byte_size, (size_t)fpc1020->huge_buffer_size); if (error < 0) goto out_error; fpc1020->capture.available_bytes += (error >= 0) ? (int)image_byte_size : 0; fpc1020->capture.last_error = error; getnstimeofday(&ts_t3); ts_delta = timespec_sub(ts_t2, ts_t1); time_settings_us[current_capture] = ts_delta.tv_sec * USEC_PER_SEC + (ts_delta.tv_nsec / NSEC_PER_USEC); ts_delta = timespec_sub(ts_t3, ts_t2); time_capture_us[current_capture] = ts_delta.tv_sec * USEC_PER_SEC + (ts_delta.tv_nsec / NSEC_PER_USEC); capture_count--; current_capture++; image_offset += (int)image_byte_size; } error = fpc1020_capture_set_sample_mode(fpc1020, false); if (error) goto out_error; if (mode != FPC1020_MODE_WAIT_FINGER_UP) wake_up_interruptible(&fpc1020->capture.wq_data_avail); if (wait_finger_up) { fpc1020->capture.state = FPC1020_CAPTURE_STATE_WAIT_FOR_FINGER_UP; error = fpc1020_capture_finger_detect_settings(fpc1020); if (error < 0) goto out_error; error = fpc1020_capture_wait_finger_up(fpc1020); if(error == -EINTR) { dev_dbg(&fpc1020->spi->dev, "Finger up check interrupted\n"); fpc1020->capture.deferred_finger_up = true; goto out_interrupted; } else if (error < 0) goto out_error; if (mode == FPC1020_MODE_WAIT_FINGER_UP) { fpc1020->capture.available_bytes = 4; fpc1020->huge_buffer[0] = 'F'; fpc1020->huge_buffer[1] = ':'; fpc1020->huge_buffer[2] = 'U'; fpc1020->huge_buffer[3] = 'P'; wake_up_interruptible(&fpc1020->capture.wq_data_avail); } dev_dbg(&fpc1020->spi->dev, "Finger up\n"); } out_interrupted: capture_count = 0; time_capture_sum_us = 0; while (current_capture){ current_capture--; dev_dbg(&fpc1020->spi->dev, "Frame #%d acq. time %d+%d=%d (us)\n", capture_count + 1, time_settings_us[capture_count], time_capture_us[capture_count], time_settings_us[capture_count] + time_capture_us[capture_count]); time_capture_sum_us += time_settings_us[capture_count]; time_capture_sum_us += time_capture_us[capture_count]; capture_count++; } fpc1020->diag.last_capture_time = time_capture_sum_us / 1000; dev_dbg(&fpc1020->spi->dev, "Total acq. time %d (us)\n", time_capture_sum_us); out_error: fpc1020->capture.last_error = error; if (error) { fpc1020->capture.state = FPC1020_CAPTURE_STATE_FAILED; dev_err(&fpc1020->spi->dev, "%s %s %d\n", __func__, (error == -EINTR) ? "TERMINATED" : "FAILED", error); } else { fpc1020->capture.state = FPC1020_CAPTURE_STATE_COMPLETED; dev_dbg(&fpc1020->spi->dev, "%s OK\n", __func__); } return error; }
/* -------------------------------------------------------------------- */ int fpc1020_capture_task(fpc1020_data_t *fpc1020) { int error = 0; bool wait_finger_down = false; bool wait_finger_up = false; bool adjust_settings; fpc1020_capture_mode_t mode = fpc1020->capture.current_mode; int current_capture, capture_count; int image_offset; size_t image_byte_size; fpc1020->capture.state = FPC1020_CAPTURE_STATE_WRITE_SETTINGS; error = fpc1020_wake_up(fpc1020); if (error < 0) goto out_error; switch (mode) { case FPC1020_MODE_WAIT_AND_CAPTURE: wait_finger_down = wait_finger_up = true; case FPC1020_MODE_SINGLE_CAPTURE: case FPC1020_MODE_WAIT_FINGER_UP_AND_CAPTURE: capture_count = fpc1020->setup.capture_count; adjust_settings = true; error = fpc1020_write_capture_setup(fpc1020); break; case FPC1020_MODE_CHECKERBOARD_TEST_NORM: capture_count = 1; adjust_settings = false; error = fpc1020_write_test_setup(fpc1020, 0xaa55); break; case FPC1020_MODE_CHECKERBOARD_TEST_INV: capture_count = 1; adjust_settings = false; error = fpc1020_write_test_setup(fpc1020, 0x55aa); break; case FPC1020_MODE_BOARD_TEST_ONE: capture_count = 1; adjust_settings = false; error = fpc1020_write_test_setup(fpc1020, 0xffff); break; case FPC1020_MODE_BOARD_TEST_ZERO: capture_count = 1; adjust_settings = false; error = fpc1020_write_test_setup(fpc1020, 0x0000); break; case FPC1020_MODE_WAIT_FINGER_DOWN: wait_finger_down = true; capture_count = 0; adjust_settings = false; error = fpc1020_write_capture_setup(fpc1020); break; case FPC1020_MODE_WAIT_FINGER_UP: wait_finger_up = true; capture_count = 0; adjust_settings = false; error = fpc1020_write_capture_setup(fpc1020); break; case FPC1020_MODE_IDLE: default: capture_count = 0; adjust_settings = false; error = -EINVAL; break; } if (error < 0) goto out_error; if(mode == FPC1020_MODE_CHECKERBOARD_TEST_NORM || mode == FPC1020_MODE_CHECKERBOARD_TEST_INV || mode == FPC1020_MODE_BOARD_TEST_ONE || mode == FPC1020_MODE_BOARD_TEST_ZERO){ error = fpc1020_capture_set_crop_selftest(fpc1020); image_byte_size = fpc1020_calc_image_size_selftest(fpc1020); } else{ error = fpc1020_capture_set_crop(fpc1020, fpc1020->setup.capture_col_start, fpc1020->setup.capture_col_groups, fpc1020->setup.capture_row_start, fpc1020->setup.capture_row_count); image_byte_size = fpc1020_calc_image_size(fpc1020); } if (error < 0) goto out_error; dev_dbg(&fpc1020->spi->dev, "Start capture, mode %d, (%d frames)\n", mode, capture_count); if (wait_finger_down) { fpc1020->capture.state = FPC1020_CAPTURE_STATE_WAIT_FOR_FINGER_DOWN; error = fpc1020_capture_wait_finger_down(fpc1020); if (error < 0) goto out_error; dev_dbg(&fpc1020->spi->dev, "Finger down\n"); if (mode == FPC1020_MODE_WAIT_FINGER_DOWN) { fpc1020->capture.available_bytes = 4; fpc1020->huge_buffer[0] = 'F'; fpc1020->huge_buffer[1] = ':'; fpc1020->huge_buffer[2] = 'D'; fpc1020->huge_buffer[3] = 'N'; } } current_capture = 0; image_offset = 0; if(mode != FPC1020_MODE_WAIT_FINGER_DOWN && mode !=FPC1020_MODE_WAIT_FINGER_UP){ while (capture_count && (error >= 0)) { fpc1020->capture.state = FPC1020_CAPTURE_STATE_ACQUIRE; dev_dbg(&fpc1020->spi->dev,"Capture, frame %d \n",current_capture + 1); error = (!adjust_settings) ? 0 : fpc1020_capture_settings(fpc1020, current_capture); if (error < 0) goto out_error; error = fpc1020_cmd(fpc1020, FPC1020_CMD_CAPTURE_IMAGE, FPC_1020_IRQ_REG_BIT_FIFO_NEW_DATA); if (error < 0) goto out_error; fpc1020->capture.state = FPC1020_CAPTURE_STATE_FETCH; error = fpc1020_fetch_image(fpc1020, fpc1020->huge_buffer, image_offset, image_byte_size, (size_t)fpc1020->huge_buffer_size); if (error < 0) goto out_error; fpc1020->capture.available_bytes += (int)image_byte_size; fpc1020->capture.last_error = error; capture_count--; current_capture++; image_offset += (int)image_byte_size; } } if (mode != FPC1020_MODE_WAIT_FINGER_UP) wake_up_interruptible(&fpc1020->capture.wq_data_avail); if (wait_finger_up) { fpc1020->capture.state = FPC1020_CAPTURE_STATE_WAIT_FOR_FINGER_UP; error = fpc1020_capture_wait_finger_up(fpc1020); if (error < 0) goto out_error; if (mode == FPC1020_MODE_WAIT_FINGER_UP) { fpc1020->capture.available_bytes = 4; fpc1020->huge_buffer[0] = 'F'; fpc1020->huge_buffer[1] = ':'; fpc1020->huge_buffer[2] = 'U'; fpc1020->huge_buffer[3] = 'P'; wake_up_interruptible(&fpc1020->capture.wq_data_avail); } dev_dbg(&fpc1020->spi->dev, "Finger up\n"); } out_error: fpc1020->capture.last_error = error; if (error < 0) { fpc1020->capture.state = FPC1020_CAPTURE_STATE_FAILED; dev_err(&fpc1020->spi->dev, "%s FAILED %d\n", __func__, error); } else { fpc1020->capture.state = FPC1020_CAPTURE_STATE_COMPLETED; dev_err(&fpc1020->spi->dev, "%s OK\n", __func__); } return error; }