Exemplo n.º 1
0
/** \ingroup img
 * A quick convenience function to save an image to a file in
 * <a href="http://netpbm.sourceforge.net/doc/pgm.html">PGM format</a>.
 * \param img the image to save
 * \param path the path to save the image. Existing files will be overwritten.
 * \returns 0 on success, non-zero on error.
 */
API_EXPORTED int fp_img_save_to_file(struct fp_img *img, char *path)
{
	FILE *fd = fopen(path, "w");
	size_t write_size = img->width * img->height;
	int r;

	if (!fd) {
		fp_dbg("could not open '%s' for writing: %d", path, errno);
		return -errno;
	}

	r = fprintf(fd, "P5 %d %d 255\n", img->width, img->height);
	if (r < 0) {
		fp_err("pgm header write failed, error %d", r);
		return r;
	}

	r = fwrite(img->data, 1, write_size, fd);
	if (r < write_size) {
		fp_err("short write (%d)", r);
		return -EIO;
	}

	fclose(fd);
	fp_dbg("written to '%s'", path);
	return 0;
}
Exemplo n.º 2
0
/** \ingroup img
 * Get a binarized form of a standardized scanned image. This is where the
 * fingerprint image has been "enhanced" and is a set of pure black ridges
 * on a pure white background. Internally, image processing happens on top
 * of the binarized image.
 *
 * The image must have been \ref img_std "standardized" otherwise this function
 * will fail.
 *
 * It is safe to binarize an image and free the original while continuing
 * to use the binarized version.
 *
 * You cannot binarize an image twice.
 *
 * \param img a standardized image
 * \returns a new image representing the binarized form of the original, or
 * NULL on error. Must be freed with fp_img_free() after use.
 */
API_EXPORTED struct fp_img *fp_img_binarize(struct fp_img *img)
{
	struct fp_img *ret;
	int height = img->height;
	int width = img->width;
	int imgsize = height * width;

	if (img->flags & FP_IMG_BINARIZED_FORM) {
		fp_err("image already binarized");
		return NULL;
	}

	if (!img->binarized) {
		int r = fpi_img_detect_minutiae(img);
		if (r < 0)
			return NULL;
		if (!img->binarized) {
			fp_err("no minutiae after successful detection?");
			return NULL;
		}
	}

	ret = fpi_img_new(imgsize);
	ret->flags |= FP_IMG_BINARIZED_FORM;
	ret->width = width;
	ret->height = height;
	memcpy(ret->data, img->binarized, imgsize);
	return ret;
}
Exemplo n.º 3
0
/* check image properties and resize it if necessary. potentially returns a new
 * image after freeing the old one. */
static int sanitize_image(struct fp_img_dev *imgdev, struct fp_img **_img)
{
	struct fp_driver *drv = imgdev->dev->drv;
	struct fp_img_driver *imgdrv = fpi_driver_to_img_driver(drv);
	struct fp_img *img = *_img;

	if (imgdrv->img_width > 0) {
		img->width = imgdrv->img_width;
	} else if (img->width <= 0) {
		fp_err("no image width assigned");
		return -EINVAL;
	}

	if (imgdrv->img_height > 0) {
		img->height = imgdrv->img_height;
	} else if (img->height <= 0) {
		fp_err("no image height assigned");
		return -EINVAL;
	}

	if (!fpi_img_is_sane(img)) {
		fp_err("image is not sane!");
		return -EINVAL;
	}

	return 0;
}
Exemplo n.º 4
0
/* external interface for testing */
struct fp_img_dev *global_init(void)
{
	int ret;
	struct fp_img_dev *dev;

	ret = libusb_init(&fpi_usb_ctx);
	if (ret != LIBUSB_SUCCESS) {
		fp_err("libusb_init failed %d", ret);
		goto cantclaim;
	}

	dev = malloc(sizeof(struct fp_img_dev));
	if (dev == NULL) {
		fp_err("cannot allocate memory");
		goto cantclaim;
	}

	dev->udev = libusb_open_device_with_vid_pid(fpi_usb_ctx, 0x1c7a, 0x0603);
	if (dev->udev == NULL) {
		fp_err("libusb_open_device_with_vid_pid failed");
		free(dev);
		dev = NULL;
		goto cantclaim;
	}

	if (dev_init(dev, 0x0603))
		dev = NULL;

cantclaim:
	return dev;
}
Exemplo n.º 5
0
static int capture(struct fp_img_dev *dev, gboolean unconditional,
	struct fp_img **ret)
{
	int i;
	int r;
	struct fp_img *img;
	unsigned char *data;
	unsigned char *ptr;

	r = aes_write_regv(dev, init_reqs, G_N_ELEMENTS(init_reqs));
	if (r < 0)
		return r;

	img = fpi_img_new_for_imgdev(dev);
	data = g_malloc(DATA_BUFLEN);
	ptr = data;

	/* See the timeout explanation in the uru4000 driver for the reasoning
	 * behind this silly loop. */
retry:
	r = usb_bulk_read(dev->udev, EP_IN, data, DATA_BUFLEN, 1000);
	if (r == -ETIMEDOUT)
		goto retry;

	if (r < 0) {
		fp_err("data read failed, error %d", r);
		goto err;
	} else if (r < DATA_BUFLEN) {
		fp_err("short data read (%d)", r);
		r = -EIO;
		goto err;
	}

	for (i = 0; i < NR_SUBARRAYS; i++) {
		fp_dbg("subarray header byte %02x", *ptr);
		ptr++;
		aes_assemble_image(ptr, 96, 16, img->data + (i * 96 * 16));
		ptr += SUBARRAY_LEN;
	}

	img->flags = FP_IMG_COLORS_INVERTED | FP_IMG_V_FLIPPED | FP_IMG_H_FLIPPED;
	*ret = img;
	g_free(data);
	return 0;
err:
	g_free(data);
	fp_img_free(img);
	return r;
}
Exemplo n.º 6
0
static int load_from_file(char *path, struct fp_print_data **data)
{
	gsize length;
	gchar *contents;
	GError *err = NULL;
	struct fp_print_data *fdata;

	fp_dbg("from %s", path);
	g_file_get_contents(path, &contents, &length, &err);
	if (err) {
		int r = err->code;
		fp_err("%s load failed: %s", path, err->message);
		g_error_free(err);
		/* FIXME interpret more error codes */
		if (r == G_FILE_ERROR_NOENT)
			return -ENOENT;
		else
			return r;
	}

	fdata = fp_print_data_from_data(contents, length);
	g_free(contents);
	if (!fdata)
		return -EIO;
	*data = fdata;
	return 0;
}
Exemplo n.º 7
0
void fpi_imgdev_deactivate_complete(struct fp_img_dev *imgdev)
{
	fp_dbg("");

	switch (imgdev->action) {
	case IMG_ACTION_ENROLL:
		fpi_drvcb_enroll_stopped(imgdev->dev);
		break;
	case IMG_ACTION_VERIFY:
		fpi_drvcb_verify_stopped(imgdev->dev);
		break;
	case IMG_ACTION_IDENTIFY:
		fpi_drvcb_identify_stopped(imgdev->dev);
		break;
	case IMG_ACTION_CAPTURE:
		fpi_drvcb_capture_stopped(imgdev->dev);
		break;
	default:
		fp_err("unhandled action %d", imgdev->action);
		break;
	}

	imgdev->action = IMG_ACTION_NONE;
	imgdev->action_state = 0;
}
Exemplo n.º 8
0
void fpi_imgdev_activate_complete(struct fp_img_dev *imgdev, int status)
{
	fp_dbg("status %d", status);

	switch (imgdev->action) {
	case IMG_ACTION_ENROLL:
		fpi_drvcb_enroll_started(imgdev->dev, status);
		break;
	case IMG_ACTION_VERIFY:
		fpi_drvcb_verify_started(imgdev->dev, status);
		break;
	case IMG_ACTION_IDENTIFY:
		fpi_drvcb_identify_started(imgdev->dev, status);
		break;
	case IMG_ACTION_CAPTURE:
		fpi_drvcb_capture_started(imgdev->dev, status);
		break;
	default:
		fp_err("unhandled action %d", imgdev->action);
		return;
	}

	if (status == 0) {
		imgdev->action_state = IMG_ACQUIRE_STATE_AWAIT_FINGER_ON;
		dev_change_state(imgdev, IMGDEV_STATE_AWAIT_FINGER_ON);
	}
}
Exemplo n.º 9
0
/** \ingroup print_data
 * Loads a previously stored print from disk. The print must have been saved
 * earlier using the fp_print_data_save() function.
 *
 * A return code of -ENOENT indicates that the fingerprint requested could not
 * be found. Other error codes (both positive and negative) are possible for
 * obscure error conditions (e.g. corruption).
 *
 * \param dev the device you are loading the print for
 * \param finger the finger of the file you are loading
 * \param data output location to put the corresponding stored print. Must be
 * freed with fp_print_data_free() after use.
 * \returns 0 on success, non-zero on error
 */
API_EXPORTED int fp_print_data_load(struct fp_dev *dev,
	enum fp_finger finger, struct fp_print_data **data)
{
	gchar *path;
	struct fp_print_data *fdata;
	int r;

	if (!base_store)
		storage_setup();

	path = get_path_to_print(dev, finger);
	r = load_from_file(path, &fdata);
	g_free(path);
	if (r)
		return r;

	if (!fp_dev_supports_print_data(dev, fdata)) {
		fp_err("print data is not compatible!");
		fp_print_data_free(fdata);
		return -EINVAL;
	}

	*data = fdata;
	return 0;
}
Exemplo n.º 10
0
static int dev_open(struct fp_img_dev *dev, unsigned long driver_data)
{
    struct fpi_ssm *init_ssm;
    struct vfs0050_dev *vdev = NULL;
    int r;
    fp_dbg("dev_open called");
    //TODO: this is probably frowned upon :/ but right now a reset is the only
    // way for me to know I'm working with a clean slate and the rest of this will work.
    // Will be trying to reverse engineer more of the protocol so I can avoid resetting
    // the device each time it's opened.
    libusb_reset_device(dev->udev);

    r = libusb_claim_interface(dev->udev, 0);
    if (r < 0) {
        fp_err("could not claim interface 0");
        return r;
    }
    libusb_control_transfer(dev->udev, 0x00, 0x09, 0x0001, 0, NULL, 0, 100);


    vdev = g_malloc0(sizeof(struct vfs0050_dev));
    vdev->scanbuf = g_malloc0(VFS0050_INITIAL_SCANBUF_SIZE);
    vdev->scanbuf_sz = VFS0050_INITIAL_SCANBUF_SIZE;
    vdev->calbuf = g_malloc0(VFS0050_INITIAL_SCANBUF_SIZE);
    vdev->calbuf_sz = VFS0050_INITIAL_SCANBUF_SIZE;
    dev->priv = vdev;
    init_ssm = fpi_ssm_new(dev->dev, state_init, M_INIT_NUMSTATES);
    init_ssm->priv = dev;
    fpi_ssm_start(init_ssm, state_init_complete);

    return 0;
}
Exemplo n.º 11
0
/** \ingroup dev
 * Performs an enroll stage. See \ref enrolling for an explanation of enroll
 * stages.
 *
 * If no enrollment is in process, this kicks of the process and runs the
 * first stage. If an enrollment is already in progress, calling this
 * function runs the next stage, which may well be the last.
 *
 * A negative error code may be returned from any stage. When this occurs,
 * further calls to the enroll function will start a new enrollment process,
 * i.e. a negative error code indicates that the enrollment process has been
 * aborted. These error codes only ever indicate unexpected internal errors
 * or I/O problems.
 *
 * The RETRY codes from #fp_enroll_result may be returned from any enroll
 * stage. These codes indicate that the scan was not succesful in that the
 * user did not position their finger correctly or similar. When a RETRY code
 * is returned, the enrollment stage is <b>not</b> advanced, so the next call
 * into this function will retry the current stage again. The current stage may
 * need to be retried several times.
 *
 * The fp_enroll_result#FP_ENROLL_FAIL code may be returned from any enroll
 * stage. This code indicates that even though the scans themselves have been
 * acceptable, data processing applied to these scans produces incomprehensible
 * results. In other words, the user may have been scanning a different finger
 * for each stage or something like that. Like negative error codes, this
 * return code indicates that the enrollment process has been aborted.
 *
 * The fp_enroll_result#FP_ENROLL_PASS code will only ever be returned for
 * non-final stages. This return code indicates that the scan was acceptable
 * and the next call into this function will advance onto the next enroll
 * stage.
 *
 * The fp_enroll_result#FP_ENROLL_COMPLETE code will only ever be returned
 * from the final enroll stage. It indicates that enrollment completed
 * successfully, and that print_data has been assigned to point to the
 * resultant enrollment data. The print_data parameter will not be modified
 * during any other enrollment stages, hence it is actually legal to pass NULL
 * as this argument for all but the final stage.
 * 
 * If the device is an imaging device, it can also return the image from
 * the scan, even when the enroll fails with a RETRY or FAIL code. It is legal
 * to call this function even on non-imaging devices, just don't expect them to
 * provide images.
 *
 * \param dev the device
 * \param print_data a location to return the resultant enrollment data from
 * the final stage. Must be freed with fp_print_data_free() after use.
 * \param img location to store the scan image. accepts NULL for no image
 * storage. If an image is returned, it must be freed with fp_img_free() after
 * use.
 * \return negative code on error, otherwise a code from #fp_enroll_result
 */
API_EXPORTED int fp_enroll_finger_img(struct fp_dev *dev,
	struct fp_print_data **print_data, struct fp_img **img)
{
	struct fp_driver *drv = dev->drv;
	int stage = dev->__enroll_stage;
	gboolean final = FALSE;
	gboolean stopped = FALSE;
	struct sync_enroll_data *edata = NULL;
	int r;
	fp_dbg("");

	/* FIXME __enroll_stage is ugly, can we replace it by some function that
	 * says whether we're enrolling or not, and then put __enroll_stage into
	 * edata? */

	if (stage == -1) {
		edata = g_malloc0(sizeof(struct sync_enroll_data));
		r = fp_async_enroll_start(dev, sync_enroll_cb, edata);
		if (r < 0) {
			g_free(edata);
			return r;
		}

		dev->__enroll_stage = ++stage;
	} else if (stage >= dev->nr_enroll_stages) {
		fp_err("exceeding number of enroll stages for device claimed by "
			"driver %s (%d stages)", drv->name, dev->nr_enroll_stages);
		dev->__enroll_stage = -1;
		r = -EINVAL;
		final = TRUE;
Exemplo n.º 12
0
static int dev_open(struct fp_img_dev *dev, unsigned long driver_data)
{
	vfs301_dev_t *vdev = NULL;
	int r;

	/* Claim usb interface */
	r = libusb_claim_interface(dev->udev, 0);
	if (r < 0) {
		/* Interface not claimed, return error */
		fp_err("could not claim interface 0");
		return r;
	}

	/* Set enroll stage number */
	dev->dev->nr_enroll_stages = 1;

	/* Initialize private structure */
	vdev = g_malloc0(sizeof(vfs301_dev_t));
	dev->priv = vdev;

	vdev->scanline_buf = malloc(0);
	vdev->scanline_count = 0;

	/* Notify open complete */
	fpi_imgdev_open_complete(dev, 0);

	return 0;
}
Exemplo n.º 13
0
int fpi_img_to_print_data(struct fp_img_dev *imgdev, struct fp_img *img,
	struct fp_print_data **ret)
{
	struct fp_print_data *print;
	int r;

	if (!img->minutiae) {
		r = fpi_img_detect_minutiae(img);
		if (r < 0)
			return r;
		if (!img->minutiae) {
			fp_err("no minutiae after successful detection?");
			return -ENOENT;
		}
	}

	/* FIXME: space is wasted if we dont hit the max minutiae count. would
	 * be good to make this dynamic. */
	print = fpi_print_data_new(imgdev->dev, sizeof(struct xyt_struct));
	print->type = PRINT_DATA_NBIS_MINUTIAE;
	minutiae_to_xyt(img->minutiae, img->width, img->height, print->data);

	/* FIXME: the print buffer at this point is endian-specific, and will
	 * only work when loaded onto machines with identical endianness. not good!
	 * data format should be platform-independent. */
	*ret = print;

	return 0;
}
Exemplo n.º 14
0
static int dev_init(struct fp_img_dev *dev, unsigned long driver_data)
{
	/* TODO check that device has endpoints we're using */
	int r;
	struct aesX660_dev *aesdev;

	r = libusb_claim_interface(dev->udev, 0);
	if (r < 0) {
		fp_err("could not claim interface 0");
		return r;
	}

	dev->priv = aesdev = g_malloc0(sizeof(struct aesX660_dev));
	aesdev->buffer = g_malloc0(AES1660_FRAME_SIZE + AESX660_HEADER_SIZE);
	aesdev->init_seqs[0] = aes1660_init_1;
	aesdev->init_seqs_len[0] = array_n_elements(aes1660_init_1);
	aesdev->init_seqs[1] = aes1660_init_2;
	aesdev->init_seqs_len[1] = array_n_elements(aes1660_init_2);
	aesdev->start_imaging_cmd = (unsigned char *)aes1660_start_imaging_cmd;
	aesdev->start_imaging_cmd_len = sizeof(aes1660_start_imaging_cmd);
	aesdev->frame_width = FRAME_WIDTH;
	aesdev->extra_img_flags = FP_IMG_PARTIAL; 

	fpi_imgdev_open_complete(dev, 0);
	return 0;
}
Exemplo n.º 15
0
static int dev_init(struct fp_img_dev *dev, unsigned long driver_data)
{
	int r;
	struct aes3k_dev *aesdev;

	r = libusb_claim_interface(dev->udev, 0);
	if (r < 0)
		fp_err("could not claim interface 0");

	aesdev = dev->priv = g_malloc0(sizeof(struct aes3k_dev));

	if (!aesdev)
		return -ENOMEM;

	if (r == 0)
		aesdev->data_buflen = DATA_BUFLEN;
		aesdev->frame_width = FRAME_WIDTH;
		aesdev->frame_size = FRAME_SIZE;
		aesdev->frame_number = FRAME_NUMBER;
		aesdev->enlarge_factor = ENLARGE_FACTOR;
		aesdev->init_reqs = init_reqs;
		aesdev->init_reqs_len = G_N_ELEMENTS(init_reqs);
		fpi_imgdev_open_complete(dev, 0);

	return r;
}
Exemplo n.º 16
0
int fpi_img_detect_minutiae(struct fp_img *img)
{
	struct fp_minutiae *minutiae;
	int r;
	int *direction_map, *low_contrast_map, *low_flow_map;
	int *high_curve_map, *quality_map;
	int map_w, map_h;
	unsigned char *bdata;
	int bw, bh, bd;
	GTimer *timer;

	if (img->flags & FP_IMG_STANDARDIZATION_FLAGS) {
		fp_err("cant detect minutiae for non-standardized image");
		return -EINVAL;
	}

	/* Remove convex hull points from partial image */
	if (img->flags & FP_IMG_PARTIAL)
		g_lfsparms_V2.remove_convex_hull_pts = TRUE;
	else
		g_lfsparms_V2.remove_convex_hull_pts = FALSE;

	/* 25.4 mm per inch */
	timer = g_timer_new();
	r = get_minutiae(&minutiae, &quality_map, &direction_map,
                         &low_contrast_map, &low_flow_map, &high_curve_map,
                         &map_w, &map_h, &bdata, &bw, &bh, &bd,
                         img->data, img->width, img->height, 8,
						 DEFAULT_PPI / (double)25.4, &g_lfsparms_V2);
	g_timer_stop(timer);
	fp_dbg("minutiae scan completed in %f secs", g_timer_elapsed(timer, NULL));
	g_timer_destroy(timer);
	if (r) {
		fp_err("get minutiae failed, code %d", r);
		return r;
	}
	fp_dbg("detected %d minutiae", minutiae->num);
	img->minutiae = minutiae;
	img->binarized = bdata;

	free(quality_map);
	free(direction_map);
	free(low_contrast_map);
	free(low_flow_map);
	free(high_curve_map);
	return minutiae->num;
}
Exemplo n.º 17
0
static void register_driver(struct fp_driver *drv)
{
	if (drv->id == 0) {
		fp_err("not registering driver %s: driver ID is 0", drv->name);
		return;
	}
	registered_drivers = g_slist_prepend(registered_drivers, (gpointer) drv);
	fp_dbg("registered driver %s", drv->name);
}
Exemplo n.º 18
0
/** \ingroup print_data
 * Saves a stored print to disk, assigned to a specific finger. Even though
 * you are limited to storing only the 10 human fingers, this is a
 * per-device-type limit. For example, you can store the users right index
 * finger from a DigitalPersona scanner, and you can also save the right index
 * finger from a UPEK scanner. When you later come to load the print, the right
 * one will be automatically selected.
 *
 * This function will unconditionally overwrite a fingerprint previously
 * saved for the same finger and device type. The print is saved in a hidden
 * directory beneath the current user's home directory.
 * \param data the stored print to save to disk
 * \param finger the finger that this print corresponds to
 * \returns 0 on success, non-zero on error.
 */
API_EXPORTED int fp_print_data_save(struct fp_print_data *data,
	enum fp_finger finger)
{
	GError *err = NULL;
	char *path;
	char *dirpath;
	unsigned char *buf;
	size_t len;
	int r;

	if (!base_store)
		storage_setup();

	fp_dbg("save %s print from driver %04x", finger_num_to_str(finger),
		data->driver_id);
	len = fp_print_data_get_data(data, &buf);
	if (!len)
		return -ENOMEM;

	path = __get_path_to_print(data->driver_id, data->devtype, finger);
	dirpath = g_path_get_dirname(path);
	r = g_mkdir_with_parents(dirpath, DIR_PERMS);
	if (r < 0) {
		fp_err("couldn't create storage directory");
		g_free(path);
		g_free(dirpath);
		return r;
	}

	fp_dbg("saving to %s", path);
	g_file_set_contents(path, buf, len, &err);
	free(buf);
	g_free(dirpath);
	g_free(path);
	if (err) {
		r = err->code;
		fp_err("save failed: %s", err->message);
		g_error_free(err);
		/* FIXME interpret error codes */
		return r;
	}

	return 0;
}
Exemplo n.º 19
0
static int dev_init(struct fp_img_dev *dev, unsigned long driver_data)
{
	int r;

	r = usb_claim_interface(dev->udev, 0);
	if (r < 0) {
		fp_err("could not claim interface 0");
		return r;
	}

	return 0;
}
Exemplo n.º 20
0
enum fp_print_data_type fpi_driver_get_data_type(struct fp_driver *drv)
{
	switch (drv->type) {
	case DRIVER_PRIMITIVE:
		return PRINT_DATA_RAW;
	case DRIVER_IMAGING:
		return PRINT_DATA_NBIS_MINUTIAE;
	default:
		fp_err("unrecognised drv type %d", drv->type);
		return PRINT_DATA_RAW;
	}
}
Exemplo n.º 21
0
static int dev_init(struct fp_img_dev *dev, unsigned long driver_data)
{
	/* TODO check that device has endpoints we're using */
	int r;
	struct upektc_dev *upekdev;

	r = libusb_claim_interface(dev->udev, 0);
	if (r < 0) {
		fp_err("could not claim interface 0: %s", libusb_error_name(r));
		return r;
	}

	dev->priv = upekdev = g_malloc0(sizeof(struct upektc_dev));
	switch (driver_data) {
	case UPEKTC_2015:
		upekdev->ep_in = UPEKTC_EP_IN;
		upekdev->ep_out = UPEKTC_EP_OUT;
		upekdev->setup_commands = upektc_setup_commands;
		upekdev->setup_commands_len = array_n_elements(upektc_setup_commands);
		upekdev->sum_threshold = UPEKTC_SUM_THRESHOLD;
		break;
	case UPEKTC_3001:
		upekdev->ep_in = UPEKET_EP_IN;
		upekdev->ep_out = UPEKET_EP_OUT;
		upekdev->setup_commands = upeket_setup_commands;
		upekdev->setup_commands_len = array_n_elements(upeket_setup_commands);
		upekdev->sum_threshold = UPEKET_SUM_THRESHOLD;
		break;
	default:
		fp_err("Device variant %d is not known\n", driver_data);
		g_free(upekdev);
		dev->priv = NULL;
		return -ENODEV;
		break;
	}
	fpi_imgdev_open_complete(dev, 0);
	return 0;
}
Exemplo n.º 22
0
static int dev_init(struct fp_img_dev *dev, unsigned long driver_data)
{
	int r;
	dev->priv = g_malloc0(sizeof(struct v5s_dev));

	r = libusb_claim_interface(dev->udev, 0);
	if (r < 0)
		fp_err("could not claim interface 0: %s", libusb_error_name(r));

	if (r == 0)
		fpi_imgdev_open_complete(dev, 0);

	return r;
}
Exemplo n.º 23
0
void fpi_imgdev_report_finger_status(struct fp_img_dev *imgdev,
	gboolean present)
{
	int r = imgdev->action_result;
	struct fp_print_data *data = imgdev->acquire_data;
	struct fp_img *img = imgdev->acquire_img;

	fp_dbg(present ? "finger on sensor" : "finger removed");

	if (present && imgdev->action_state == IMG_ACQUIRE_STATE_AWAIT_FINGER_ON) {
		dev_change_state(imgdev, IMGDEV_STATE_CAPTURE);
		imgdev->action_state = IMG_ACQUIRE_STATE_AWAIT_IMAGE;
		return;
	} else if (present
			|| imgdev->action_state != IMG_ACQUIRE_STATE_AWAIT_FINGER_OFF) {
		fp_dbg("ignoring status report");
		return;
	}

	/* clear these before reporting results to avoid complications with
	 * call cascading in and out of the library */
	imgdev->acquire_img = NULL;
	imgdev->acquire_data = NULL;

	/* finger removed, report results */
	switch (imgdev->action) {
	case IMG_ACTION_ENROLL:
		fp_dbg("reporting enroll result");
		fpi_drvcb_enroll_stage_completed(imgdev->dev, r, data, img);
		if (r > 0 && r != FP_ENROLL_COMPLETE && r != FP_ENROLL_FAIL) {
			imgdev->action_result = 0;
			imgdev->action_state = IMG_ACQUIRE_STATE_AWAIT_FINGER_ON;
			dev_change_state(imgdev, IMG_ACQUIRE_STATE_AWAIT_FINGER_ON);
		}
		break;
	case IMG_ACTION_VERIFY:
		fpi_drvcb_report_verify_result(imgdev->dev, r, img);
		fp_print_data_free(data);
		break;
	case IMG_ACTION_IDENTIFY:
		fpi_drvcb_report_identify_result(imgdev->dev, r,
			imgdev->identify_match_offset, img);
		fp_print_data_free(data);
		break;
	default:
		fp_err("unhandled action %d", imgdev->action);
		break;
	}
}
Exemplo n.º 24
0
int fpi_img_compare_print_data(struct fp_print_data *enrolled_print,
	struct fp_print_data *new_print)
{
	int score, max_score = 0, probe_len;
	struct xyt_struct *pstruct = NULL;
	struct xyt_struct *gstruct = NULL;
	struct fp_print_data_item *data_item;
	GSList *list_item;

	if (enrolled_print->type != PRINT_DATA_NBIS_MINUTIAE ||
	     new_print->type != PRINT_DATA_NBIS_MINUTIAE) {
		fp_err("invalid print format");
		return -EINVAL;
	}

	if (g_slist_length(new_print->prints) != 1) {
		fp_err("new_print contains more than one sample, is it enrolled print?");
		return -EINVAL;
	}

	data_item = new_print->prints->data;
	pstruct = (struct xyt_struct *)data_item->data;

	probe_len = bozorth_probe_init(pstruct);
	list_item = enrolled_print->prints;
	do {
		data_item = list_item->data;
		gstruct = (struct xyt_struct *)data_item->data;
		score = bozorth_to_gallery(probe_len, pstruct, gstruct);
		fp_dbg("score %d", score);
		max_score = max(score, max_score);
		list_item = g_slist_next(list_item);
	} while (list_item);

	return max_score;
}
Exemplo n.º 25
0
static int generic_acquire_start(struct fp_dev *dev, int action)
{
	struct fp_img_dev *imgdev = dev->priv;
	int r;
	fp_dbg("action %d", action);
	imgdev->action = action;
	imgdev->action_state = IMG_ACQUIRE_STATE_ACTIVATING;

	r = dev_activate(imgdev, IMGDEV_STATE_AWAIT_FINGER_ON);
	if (r < 0)
		fp_err("activation failed with error %d", r);

	return r;

}
Exemplo n.º 26
0
/* Submit asynchronous sleep */
static void async_sleep(unsigned int msec, struct fpi_ssm *ssm)
{
	struct fp_img_dev *dev = ssm->priv;
	struct fpi_timeout *timeout;

	/* Add timeout */
	timeout = fpi_timeout_add(msec, async_sleep_cb, ssm);

	if (timeout == NULL) {
		/* Failed to add timeout */
		fp_err("failed to add timeout");
		fpi_imgdev_session_error(dev, -ETIME);
		fpi_ssm_mark_aborted(ssm, -ETIME);
	}
}
Exemplo n.º 27
0
static int dev_init(struct fp_img_dev *dev, unsigned long driver_data)
{
	int r;

	r = libusb_claim_interface(dev->udev, 0);
	if (r < 0) {
		fp_err("could not claim interface 0");
		return r;
	}

	//dev->dev->nr_enroll_stages=3;

	dev->priv = g_malloc0(sizeof(struct etss801u_dev));
	fpi_imgdev_open_complete(dev, 0);
	return 0;
}
Exemplo n.º 28
0
static struct fp_print_data *fpi_print_data_from_fp2_data(unsigned char *buf,
	size_t buflen)
{
	size_t total_data_len, item_len;
	struct fp_print_data *data;
	struct fp_print_data_item *item;
	struct fpi_print_data_fp2 *raw = (struct fpi_print_data_fp2 *) buf;
	unsigned char *raw_buf;
	struct fpi_print_data_item_fp2 *raw_item;

	total_data_len = buflen - sizeof(*raw);
	data = print_data_new(GUINT16_FROM_LE(raw->driver_id),
		GUINT32_FROM_LE(raw->devtype), raw->data_type);
	raw_buf = raw->data;
	while (total_data_len) {
		if (total_data_len < sizeof(*raw_item))
			break;
		total_data_len -= sizeof(*raw_item);

		raw_item = (struct fpi_print_data_item_fp2 *)raw_buf;
		item_len = GUINT32_FROM_LE(raw_item->length);
		fp_dbg("item len %d, total_data_len %d", item_len, total_data_len);
		if (total_data_len < item_len) {
			fp_err("corrupted fingerprint data");
			break;
		}
		total_data_len -= item_len;

		item = fpi_print_data_item_new(item_len);
		/* FIXME: fp_print_data->data content is not endianess agnostic */
		memcpy(item->data, raw_item->data, item_len);
		data->prints = g_slist_prepend(data->prints, item);

		raw_buf += sizeof(*raw_item);
		raw_buf += item_len;
	}

	if (g_slist_length(data->prints) == 0) {
		fp_print_data_free(data);
		data = NULL;
	}

	return data;

}
Exemplo n.º 29
0
void fpi_imgdev_session_error(struct fp_img_dev *imgdev, int error)
{
	fp_dbg("error %d", error);
	BUG_ON(error == 0);
	switch (imgdev->action) {
	case IMG_ACTION_ENROLL:
		fpi_drvcb_enroll_stage_completed(imgdev->dev, error, NULL, NULL);
		break;
	case IMG_ACTION_VERIFY:
		fpi_drvcb_report_verify_result(imgdev->dev, error, NULL);
		break;
	case IMG_ACTION_IDENTIFY:
		fpi_drvcb_report_identify_result(imgdev->dev, error, 0, NULL);
		break;
	default:
		fp_err("unhandled action %d", imgdev->action);
		break;
	}
}
Exemplo n.º 30
0
struct fp_img *fpi_im_resize(struct fp_img *img, unsigned int factor)
{
	Image *mimg;
	Image *resized;
	ExceptionInfo exception;
	MagickBooleanType ret;
	int new_width = img->width * factor;
	int new_height = img->height * factor;
	struct fp_img *newimg;

	/* It is possible to implement resizing using a simple algorithm, however
	 * we use ImageMagick because it applies some kind of smoothing to the
	 * result, which improves matching performances in my experiments. */

	if (!IsMagickInstantiated())
		InitializeMagick(NULL);
	
	GetExceptionInfo(&exception);
	mimg = ConstituteImage(img->width, img->height, "I", CharPixel, img->data,
		&exception);

	GetExceptionInfo(&exception);
	resized = ResizeImage(mimg, new_width, new_height, 0, 1.0, &exception);

	newimg = fpi_img_new(new_width * new_height);
	newimg->width = new_width;
	newimg->height = new_height;
	newimg->flags = img->flags;

	GetExceptionInfo(&exception);
	ret = ExportImagePixels(resized, 0, 0, new_width, new_height, "I",
		CharPixel, newimg->data, &exception);
	if (ret != MagickTrue) {
		fp_err("export failed");
		return NULL;
	}

	DestroyImage(mimg);
	DestroyImage(resized);

	return newimg;
}