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; }