Example #1
0
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;
}