[Fingerforce-commits] [libfprint] 10/20: Implement image capture (both synchronous and asynchronous variants)

Didier Raboud odyx at alioth.debian.org
Sun Sep 29 13:43:37 UTC 2013


This is an automated email from the git hooks/post-receive script.

odyx pushed a commit to branch master
in repository libfprint.

commit 2bba4fb0733e97a4f3aca44b170159c5b92cf5b5
Author: Vasily Khoruzhick <anarsoul at gmail.com>
Date:   Fri Feb 8 14:38:13 2013 +0300

    Implement image capture (both synchronous and asynchronous variants)
    
    fp_dev_img_capture() is not implemented and returns -ENOTSUPP for all devices
    since migration to asynchronous model. This commit implement missing functionality
---
 libfprint/async.c       |   98 +++++++++++++++++++++++++++++++++++++++++++++++
 libfprint/core.c        |   34 +---------------
 libfprint/fp_internal.h |   20 ++++++++--
 libfprint/fprint.h      |   18 +++++++++
 libfprint/imgdev.c      |   59 ++++++++++++++++++++++------
 libfprint/sync.c        |   97 ++++++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 278 insertions(+), 48 deletions(-)

diff --git a/libfprint/async.c b/libfprint/async.c
index 67e3481..128b7e9 100644
--- a/libfprint/async.c
+++ b/libfprint/async.c
@@ -412,3 +412,101 @@ void fpi_drvcb_identify_stopped(struct fp_dev *dev)
 		dev->identify_stop_cb(dev, dev->identify_stop_cb_data);
 }
 
+API_EXPORTED int fp_async_capture_start(struct fp_dev *dev, int unconditional,
+	fp_capture_cb callback, void *user_data)
+{
+	struct fp_driver *drv = dev->drv;
+	int r;
+
+	fp_dbg("");
+	if (!drv->capture_start)
+		return -ENOTSUP;
+
+	dev->state = DEV_STATE_CAPTURE_STARTING;
+	dev->capture_cb = callback;
+	dev->capture_cb_data = user_data;
+	dev->unconditional_capture = unconditional;
+
+	r = drv->capture_start(dev);
+	if (r < 0) {
+		dev->capture_cb = NULL;
+		dev->state = DEV_STATE_ERROR;
+		fp_err("failed to start verification, error %d", r);
+	}
+	return r;
+}
+
+/* Drivers call this when capture has started */
+void fpi_drvcb_capture_started(struct fp_dev *dev, int status)
+{
+	fp_dbg("");
+	BUG_ON(dev->state != DEV_STATE_CAPTURE_STARTING);
+	if (status) {
+		if (status > 0) {
+			status = -status;
+			fp_dbg("adjusted to %d", status);
+		}
+		dev->state = DEV_STATE_ERROR;
+		if (dev->capture_cb)
+			dev->capture_cb(dev, status, NULL, dev->capture_cb_data);
+	} else {
+		dev->state = DEV_STATE_CAPTURING;
+	}
+}
+
+/* Drivers call this to report a capture result (which might mark completion) */
+void fpi_drvcb_report_capture_result(struct fp_dev *dev, int result,
+	struct fp_img *img)
+{
+	fp_dbg("result %d", result);
+	BUG_ON(dev->state != DEV_STATE_CAPTURING);
+	if (result < 0 || result == FP_CAPTURE_COMPLETE)
+		dev->state = DEV_STATE_CAPTURE_DONE;
+
+	if (dev->capture_cb)
+		dev->capture_cb(dev, result, img, dev->capture_cb_data);
+	else
+		fp_dbg("ignoring capture result as no callback is subscribed");
+}
+
+/* Drivers call this when capture has stopped */
+void fpi_drvcb_capture_stopped(struct fp_dev *dev)
+{
+	fp_dbg("");
+	BUG_ON(dev->state != DEV_STATE_CAPTURE_STOPPING);
+	dev->state = DEV_STATE_INITIALIZED;
+	if (dev->capture_stop_cb)
+		dev->capture_stop_cb(dev, dev->capture_stop_cb_data);
+}
+
+API_EXPORTED int fp_async_capture_stop(struct fp_dev *dev,
+	fp_capture_stop_cb callback, void *user_data)
+{
+	struct fp_driver *drv = dev->drv;
+	int r;
+
+	fp_dbg("");
+	BUG_ON(dev->state != DEV_STATE_ERROR
+		&& dev->state != DEV_STATE_CAPTURING
+		&& dev->state != DEV_STATE_CAPTURE_DONE);
+
+	dev->capture_cb = NULL;
+	dev->capture_stop_cb = callback;
+	dev->capture_stop_cb_data = user_data;
+	dev->state = DEV_STATE_CAPTURE_STOPPING;
+
+	if (!drv->capture_start)
+		return -ENOTSUP;
+	if (!drv->capture_stop) {
+		dev->state = DEV_STATE_INITIALIZED;
+		fpi_drvcb_capture_stopped(dev);
+		return 0;
+	}
+
+	r = drv->capture_stop(dev);
+	if (r < 0) {
+		fp_err("failed to stop verification");
+		dev->capture_stop_cb = NULL;
+	}
+	return r;
+}
diff --git a/libfprint/core.c b/libfprint/core.c
index 584e762..f6faab2 100644
--- a/libfprint/core.c
+++ b/libfprint/core.c
@@ -804,7 +804,7 @@ static struct fp_img_dev *dev_to_img_dev(struct fp_dev *dev)
  */
 API_EXPORTED int fp_dev_supports_imaging(struct fp_dev *dev)
 {
-	return dev->drv->type == DRIVER_IMAGING;
+	return dev->drv->capture_start != NULL;
 }
 
 /** \ingroup dev
@@ -820,38 +820,6 @@ API_EXPORTED int fp_dev_supports_identification(struct fp_dev *dev)
 }
 
 /** \ingroup dev
- * Captures an \ref img "image" from a device. The returned image is the raw
- * image provided by the device, you may wish to \ref img_std "standardize" it.
- *
- * If set, the <tt>unconditional</tt> flag indicates that the device should
- * capture an image unconditionally, regardless of whether a finger is there
- * or not. If unset, this function will block until a finger is detected on
- * the sensor.
- *
- * \param dev the device
- * \param unconditional whether to unconditionally capture an image, or to only capture when a finger is detected
- * \param image a location to return the captured image. Must be freed with
- * fp_img_free() after use.
- * \return 0 on success, non-zero on error. -ENOTSUP indicates that either the
- * unconditional flag was set but the device does not support this, or that the
- * device does not support imaging.
- * \sa fp_dev_supports_imaging()
- */
-API_EXPORTED int fp_dev_img_capture(struct fp_dev *dev, int unconditional,
-	struct fp_img **image)
-{
-	struct fp_img_dev *imgdev = dev_to_img_dev(dev);
-	if (!imgdev) {
-		fp_dbg("image capture on non-imaging device");
-		return -ENOTSUP;
-	}
-
-	//return fpi_imgdev_capture(imgdev, unconditional, image);
-	/* FIXME reimplement async */
-	return -ENOTSUP;
-}
-
-/** \ingroup dev
  * Gets the expected width of images that will be captured from the device.
  * This function will return -1 for devices that are not
  * \ref imaging "imaging devices". If the width of images from this device
diff --git a/libfprint/fp_internal.h b/libfprint/fp_internal.h
index a8a26a9..c383c66 100644
--- a/libfprint/fp_internal.h
+++ b/libfprint/fp_internal.h
@@ -91,6 +91,10 @@ enum fp_dev_state {
 	DEV_STATE_IDENTIFYING,
 	DEV_STATE_IDENTIFY_DONE,
 	DEV_STATE_IDENTIFY_STOPPING,
+	DEV_STATE_CAPTURE_STARTING,
+	DEV_STATE_CAPTURING,
+	DEV_STATE_CAPTURE_DONE,
+	DEV_STATE_CAPTURE_STOPPING,
 };
 
 struct fp_driver **fprint_get_drivers (void);
@@ -108,8 +112,8 @@ struct fp_dev {
 
 	/* drivers should not mess with any of the below */
 	enum fp_dev_state state;
-
 	int __enroll_stage;
+	int unconditional_capture;
 
 	/* async I/O callbacks and data */
 	/* FIXME: convert this to generic state operational data mechanism? */
@@ -129,6 +133,10 @@ struct fp_dev {
 	void *identify_cb_data;
 	fp_identify_stop_cb identify_stop_cb;
 	void *identify_stop_cb_data;
+	fp_capture_cb capture_cb;
+	void *capture_cb_data;
+	fp_capture_stop_cb capture_stop_cb;
+	void *capture_stop_cb_data;
 
 	/* FIXME: better place to put this? */
 	struct fp_print_data **identify_gallery;
@@ -146,6 +154,7 @@ enum fp_imgdev_action {
 	IMG_ACTION_ENROLL,
 	IMG_ACTION_VERIFY,
 	IMG_ACTION_IDENTIFY,
+	IMG_ACTION_CAPTURE,
 };
 
 enum fp_imgdev_enroll_state {
@@ -179,8 +188,6 @@ struct fp_img_dev {
 	void *priv;
 };
 
-int fpi_imgdev_capture(struct fp_img_dev *imgdev, int unconditional,
-	struct fp_img **image);
 int fpi_imgdev_get_img_width(struct fp_img_dev *imgdev);
 int fpi_imgdev_get_img_height(struct fp_img_dev *imgdev);
 
@@ -215,6 +222,8 @@ struct fp_driver {
 	int (*verify_stop)(struct fp_dev *dev, gboolean iterating);
 	int (*identify_start)(struct fp_dev *dev);
 	int (*identify_stop)(struct fp_dev *dev, gboolean iterating);
+	int (*capture_start)(struct fp_dev *dev);
+	int (*capture_stop)(struct fp_dev *dev);
 };
 
 enum fp_print_data_type fpi_driver_get_data_type(struct fp_driver *drv);
@@ -439,6 +448,11 @@ void fpi_drvcb_report_identify_result(struct fp_dev *dev, int result,
 	size_t match_offset, struct fp_img *img);
 void fpi_drvcb_identify_stopped(struct fp_dev *dev);
 
+void fpi_drvcb_capture_started(struct fp_dev *dev, int status);
+void fpi_drvcb_report_capture_result(struct fp_dev *dev, int result,
+	struct fp_img *img);
+void fpi_drvcb_capture_stopped(struct fp_dev *dev);
+
 /* for image drivers */
 void fpi_imgdev_open_complete(struct fp_img_dev *imgdev, int status);
 void fpi_imgdev_close_complete(struct fp_img_dev *imgdev);
diff --git a/libfprint/fprint.h b/libfprint/fprint.h
index 99fa1e1..af1d686 100644
--- a/libfprint/fprint.h
+++ b/libfprint/fprint.h
@@ -107,6 +107,17 @@ uint32_t fp_dev_get_devtype(struct fp_dev *dev);
 int fp_dev_supports_print_data(struct fp_dev *dev, struct fp_print_data *data);
 int fp_dev_supports_dscv_print(struct fp_dev *dev, struct fp_dscv_print *print);
 
+/** \ingroup dev
+ * Image capture result codes returned from fp_dev_img_capture().
+ */
+enum fp_capture_result {
+	/** Capture completed successfully, the capture data has been
+	 * returned to the caller. */
+	FP_CAPTURE_COMPLETE = 0,
+	/** Capture failed for some reason */
+	FP_CAPTURE_FAIL,
+};
+
 int fp_dev_supports_imaging(struct fp_dev *dev);
 int fp_dev_img_capture(struct fp_dev *dev, int unconditional,
 	struct fp_img **image);
@@ -340,6 +351,13 @@ typedef void (*fp_identify_stop_cb)(struct fp_dev *dev, void *user_data);
 int fp_async_identify_stop(struct fp_dev *dev, fp_identify_stop_cb callback,
 	void *user_data);
 
+typedef void (*fp_capture_cb)(struct fp_dev *dev, int result,
+	struct fp_img *img, void *user_data);
+int fp_async_capture_start(struct fp_dev *dev, int unconditional, fp_capture_cb callback, void *user_data);
+
+typedef void (*fp_capture_stop_cb)(struct fp_dev *dev, void *user_data);
+int fp_async_capture_stop(struct fp_dev *dev, fp_capture_stop_cb callback, void *user_data);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/libfprint/imgdev.c b/libfprint/imgdev.c
index 1ed3f6d..f83ea11 100644
--- a/libfprint/imgdev.c
+++ b/libfprint/imgdev.c
@@ -163,6 +163,9 @@ void fpi_imgdev_report_finger_status(struct fp_img_dev *imgdev,
 			imgdev->identify_match_offset, img);
 		fp_print_data_free(data);
 		break;
+	case IMG_ACTION_CAPTURE:
+		fpi_drvcb_report_capture_result(imgdev->dev, r, img);
+		break;
 	default:
 		fp_err("unhandled action %d", imgdev->action);
 		break;
@@ -231,18 +234,20 @@ void fpi_imgdev_image_captured(struct fp_img_dev *imgdev, struct fp_img *img)
 
 	fp_img_standardize(img);
 	imgdev->acquire_img = img;
-	r = fpi_img_to_print_data(imgdev, img, &print);
-	if (r < 0) {
-		fp_dbg("image to print data conversion error: %d", r);
-		imgdev->action_result = FP_ENROLL_RETRY;
-		goto next_state;
-	} else if (img->minutiae->num < MIN_ACCEPTABLE_MINUTIAE) {
-		fp_dbg("not enough minutiae, %d/%d", img->minutiae->num,
-			MIN_ACCEPTABLE_MINUTIAE);
-		fp_print_data_free(print);
-		/* depends on FP_ENROLL_RETRY == FP_VERIFY_RETRY */
-		imgdev->action_result = FP_ENROLL_RETRY;
-		goto next_state;
+	if (imgdev->action != IMG_ACTION_CAPTURE) {
+		r = fpi_img_to_print_data(imgdev, img, &print);
+		if (r < 0) {
+			fp_dbg("image to print data conversion error: %d", r);
+			imgdev->action_result = FP_ENROLL_RETRY;
+			goto next_state;
+		} else if (img->minutiae->num < MIN_ACCEPTABLE_MINUTIAE) {
+			fp_dbg("not enough minutiae, %d/%d", img->minutiae->num,
+				MIN_ACCEPTABLE_MINUTIAE);
+			fp_print_data_free(print);
+			/* depends on FP_ENROLL_RETRY == FP_VERIFY_RETRY */
+			imgdev->action_result = FP_ENROLL_RETRY;
+			goto next_state;
+		}
 	}
 
 	imgdev->acquire_data = print;
@@ -256,6 +261,9 @@ void fpi_imgdev_image_captured(struct fp_img_dev *imgdev, struct fp_img *img)
 	case IMG_ACTION_IDENTIFY:
 		identify_process_img(imgdev);
 		break;
+	case IMG_ACTION_CAPTURE:
+		imgdev->action_result = FP_CAPTURE_COMPLETE;
+		break;
 	default:
 		BUG();
 		break;
@@ -280,6 +288,9 @@ void fpi_imgdev_session_error(struct fp_img_dev *imgdev, int error)
 	case IMG_ACTION_IDENTIFY:
 		fpi_drvcb_report_identify_result(imgdev->dev, error, 0, NULL);
 		break;
+	case IMG_ACTION_CAPTURE:
+		fpi_drvcb_report_capture_result(imgdev->dev, error, NULL);
+		break;
 	default:
 		fp_err("unhandled action %d", imgdev->action);
 		break;
@@ -300,6 +311,9 @@ void fpi_imgdev_activate_complete(struct fp_img_dev *imgdev, int status)
 	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;
@@ -325,6 +339,9 @@ void fpi_imgdev_deactivate_complete(struct fp_img_dev *imgdev)
 	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;
@@ -421,6 +438,14 @@ static int img_dev_identify_start(struct fp_dev *dev)
 	return generic_acquire_start(dev, IMG_ACTION_IDENTIFY);
 }
 
+static int img_dev_capture_start(struct fp_dev *dev)
+{
+	/* Unconditional capture is not supported yet */
+	if (dev->unconditional_capture)
+		return -ENOTSUP;
+	return generic_acquire_start(dev, IMG_ACTION_CAPTURE);
+}
+
 static int img_dev_enroll_stop(struct fp_dev *dev)
 {
 	struct fp_img_dev *imgdev = dev->priv;
@@ -446,6 +471,14 @@ static int img_dev_identify_stop(struct fp_dev *dev, gboolean iterating)
 	return 0;
 }
 
+static int img_dev_capture_stop(struct fp_dev *dev)
+{
+	struct fp_img_dev *imgdev = dev->priv;
+	BUG_ON(imgdev->action != IMG_ACTION_CAPTURE);
+	generic_acquire_stop(imgdev);
+	return 0;
+}
+
 void fpi_img_driver_setup(struct fp_img_driver *idriver)
 {
 	idriver->driver.type = DRIVER_IMAGING;
@@ -457,5 +490,7 @@ void fpi_img_driver_setup(struct fp_img_driver *idriver)
 	idriver->driver.verify_stop = img_dev_verify_stop;
 	idriver->driver.identify_start = img_dev_identify_start;
 	idriver->driver.identify_stop = img_dev_identify_stop;
+	idriver->driver.capture_start = img_dev_capture_start;
+	idriver->driver.capture_stop = img_dev_capture_stop;
 }
 
diff --git a/libfprint/sync.c b/libfprint/sync.c
index ca2f302..b3b2898 100644
--- a/libfprint/sync.c
+++ b/libfprint/sync.c
@@ -512,3 +512,100 @@ err:
 	return r;
 }
 
+struct sync_capture_data {
+	gboolean populated;
+	int result;
+	struct fp_img *img;
+};
+
+static void sync_capture_cb(struct fp_dev *dev, int result, struct fp_img *img,
+	void *user_data)
+{
+	struct sync_capture_data *vdata = user_data;
+	vdata->result = result;
+	vdata->img = img;
+	vdata->populated = TRUE;
+}
+
+static void capture_stop_cb(struct fp_dev *dev, void *user_data)
+{
+	gboolean *stopped = user_data;
+	fp_dbg("");
+	*stopped = TRUE;
+}
+/** \ingroup dev
+ * Captures an \ref img "image" from a device. The returned image is the raw
+ * image provided by the device, you may wish to \ref img_std "standardize" it.
+ *
+ * If set, the <tt>unconditional</tt> flag indicates that the device should
+ * capture an image unconditionally, regardless of whether a finger is there
+ * or not. If unset, this function will block until a finger is detected on
+ * the sensor.
+ *
+ * \param dev the device
+ * \param unconditional whether to unconditionally capture an image, or to only capture when a finger is detected
+ * \param img a location to return the captured image. Must be freed with
+ * fp_img_free() after use.
+ * \return 0 on success, non-zero on error. -ENOTSUP indicates that either the
+ * unconditional flag was set but the device does not support this, or that the
+ * device does not support imaging.
+ * \sa fp_dev_supports_imaging()
+ */
+API_EXPORTED int fp_dev_img_capture(struct fp_dev *dev, int unconditional,
+	struct fp_img **img)
+{
+	struct sync_capture_data *vdata;
+	gboolean stopped = FALSE;
+	int r;
+
+	if (!dev->drv->capture_start) {
+		fp_dbg("image capture is not supported on %s device", dev->drv->name);
+		return -ENOTSUP;
+	}
+
+	fp_dbg("to be handled by %s", dev->drv->name);
+	vdata = g_malloc0(sizeof(struct sync_capture_data));
+	r = fp_async_capture_start(dev, unconditional, sync_capture_cb, vdata);
+	if (r < 0) {
+		fp_dbg("capture_start error %d", r);
+		g_free(vdata);
+		return r;
+	}
+
+	while (!vdata->populated) {
+		r = fp_handle_events();
+		if (r < 0) {
+			g_free(vdata);
+			goto err;
+		}
+	}
+
+	if (img)
+		*img = vdata->img;
+	else
+		fp_img_free(vdata->img);
+
+	r = vdata->result;
+	g_free(vdata);
+	switch (r) {
+	case FP_CAPTURE_COMPLETE:
+		fp_dbg("result: complete");
+		break;
+	case FP_CAPTURE_FAIL:
+		fp_dbg("result: fail");
+		break;
+	default:
+		fp_err("unrecognised return code %d", r);
+		r = -EINVAL;
+	}
+
+err:
+	fp_dbg("ending capture");
+	if (fp_async_capture_stop(dev, capture_stop_cb, &stopped) == 0)
+		while (!stopped)
+			if (fp_handle_events() < 0)
+				break;
+
+	return r;
+}
+

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/fingerforce/libfprint.git



More information about the Fingerforce-commits mailing list