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
This commit is contained in:
parent
aeca32fc12
commit
2bba4fb073
6 changed files with 278 additions and 48 deletions
|
@ -412,3 +412,101 @@ void fpi_drvcb_identify_stopped(struct fp_dev *dev)
|
||||||
dev->identify_stop_cb(dev, dev->identify_stop_cb_data);
|
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;
|
||||||
|
}
|
||||||
|
|
|
@ -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)
|
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
|
/** \ingroup dev
|
||||||
|
@ -819,38 +819,6 @@ API_EXPORTED int fp_dev_supports_identification(struct fp_dev *dev)
|
||||||
return dev->drv->identify_start != NULL;
|
return dev->drv->identify_start != NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** \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
|
/** \ingroup dev
|
||||||
* Gets the expected width of images that will be captured from the device.
|
* Gets the expected width of images that will be captured from the device.
|
||||||
* This function will return -1 for devices that are not
|
* This function will return -1 for devices that are not
|
||||||
|
|
|
@ -91,6 +91,10 @@ enum fp_dev_state {
|
||||||
DEV_STATE_IDENTIFYING,
|
DEV_STATE_IDENTIFYING,
|
||||||
DEV_STATE_IDENTIFY_DONE,
|
DEV_STATE_IDENTIFY_DONE,
|
||||||
DEV_STATE_IDENTIFY_STOPPING,
|
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);
|
struct fp_driver **fprint_get_drivers (void);
|
||||||
|
@ -108,8 +112,8 @@ struct fp_dev {
|
||||||
|
|
||||||
/* drivers should not mess with any of the below */
|
/* drivers should not mess with any of the below */
|
||||||
enum fp_dev_state state;
|
enum fp_dev_state state;
|
||||||
|
|
||||||
int __enroll_stage;
|
int __enroll_stage;
|
||||||
|
int unconditional_capture;
|
||||||
|
|
||||||
/* async I/O callbacks and data */
|
/* async I/O callbacks and data */
|
||||||
/* FIXME: convert this to generic state operational data mechanism? */
|
/* FIXME: convert this to generic state operational data mechanism? */
|
||||||
|
@ -129,6 +133,10 @@ struct fp_dev {
|
||||||
void *identify_cb_data;
|
void *identify_cb_data;
|
||||||
fp_identify_stop_cb identify_stop_cb;
|
fp_identify_stop_cb identify_stop_cb;
|
||||||
void *identify_stop_cb_data;
|
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? */
|
/* FIXME: better place to put this? */
|
||||||
struct fp_print_data **identify_gallery;
|
struct fp_print_data **identify_gallery;
|
||||||
|
@ -146,6 +154,7 @@ enum fp_imgdev_action {
|
||||||
IMG_ACTION_ENROLL,
|
IMG_ACTION_ENROLL,
|
||||||
IMG_ACTION_VERIFY,
|
IMG_ACTION_VERIFY,
|
||||||
IMG_ACTION_IDENTIFY,
|
IMG_ACTION_IDENTIFY,
|
||||||
|
IMG_ACTION_CAPTURE,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum fp_imgdev_enroll_state {
|
enum fp_imgdev_enroll_state {
|
||||||
|
@ -179,8 +188,6 @@ struct fp_img_dev {
|
||||||
void *priv;
|
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_width(struct fp_img_dev *imgdev);
|
||||||
int fpi_imgdev_get_img_height(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 (*verify_stop)(struct fp_dev *dev, gboolean iterating);
|
||||||
int (*identify_start)(struct fp_dev *dev);
|
int (*identify_start)(struct fp_dev *dev);
|
||||||
int (*identify_stop)(struct fp_dev *dev, gboolean iterating);
|
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);
|
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);
|
size_t match_offset, struct fp_img *img);
|
||||||
void fpi_drvcb_identify_stopped(struct fp_dev *dev);
|
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 */
|
/* for image drivers */
|
||||||
void fpi_imgdev_open_complete(struct fp_img_dev *imgdev, int status);
|
void fpi_imgdev_open_complete(struct fp_img_dev *imgdev, int status);
|
||||||
void fpi_imgdev_close_complete(struct fp_img_dev *imgdev);
|
void fpi_imgdev_close_complete(struct fp_img_dev *imgdev);
|
||||||
|
|
|
@ -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_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);
|
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_supports_imaging(struct fp_dev *dev);
|
||||||
int fp_dev_img_capture(struct fp_dev *dev, int unconditional,
|
int fp_dev_img_capture(struct fp_dev *dev, int unconditional,
|
||||||
struct fp_img **image);
|
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,
|
int fp_async_identify_stop(struct fp_dev *dev, fp_identify_stop_cb callback,
|
||||||
void *user_data);
|
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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -163,6 +163,9 @@ void fpi_imgdev_report_finger_status(struct fp_img_dev *imgdev,
|
||||||
imgdev->identify_match_offset, img);
|
imgdev->identify_match_offset, img);
|
||||||
fp_print_data_free(data);
|
fp_print_data_free(data);
|
||||||
break;
|
break;
|
||||||
|
case IMG_ACTION_CAPTURE:
|
||||||
|
fpi_drvcb_report_capture_result(imgdev->dev, r, img);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
fp_err("unhandled action %d", imgdev->action);
|
fp_err("unhandled action %d", imgdev->action);
|
||||||
break;
|
break;
|
||||||
|
@ -231,18 +234,20 @@ void fpi_imgdev_image_captured(struct fp_img_dev *imgdev, struct fp_img *img)
|
||||||
|
|
||||||
fp_img_standardize(img);
|
fp_img_standardize(img);
|
||||||
imgdev->acquire_img = img;
|
imgdev->acquire_img = img;
|
||||||
r = fpi_img_to_print_data(imgdev, img, &print);
|
if (imgdev->action != IMG_ACTION_CAPTURE) {
|
||||||
if (r < 0) {
|
r = fpi_img_to_print_data(imgdev, img, &print);
|
||||||
fp_dbg("image to print data conversion error: %d", r);
|
if (r < 0) {
|
||||||
imgdev->action_result = FP_ENROLL_RETRY;
|
fp_dbg("image to print data conversion error: %d", r);
|
||||||
goto next_state;
|
imgdev->action_result = FP_ENROLL_RETRY;
|
||||||
} else if (img->minutiae->num < MIN_ACCEPTABLE_MINUTIAE) {
|
goto next_state;
|
||||||
fp_dbg("not enough minutiae, %d/%d", img->minutiae->num,
|
} else if (img->minutiae->num < MIN_ACCEPTABLE_MINUTIAE) {
|
||||||
MIN_ACCEPTABLE_MINUTIAE);
|
fp_dbg("not enough minutiae, %d/%d", img->minutiae->num,
|
||||||
fp_print_data_free(print);
|
MIN_ACCEPTABLE_MINUTIAE);
|
||||||
/* depends on FP_ENROLL_RETRY == FP_VERIFY_RETRY */
|
fp_print_data_free(print);
|
||||||
imgdev->action_result = FP_ENROLL_RETRY;
|
/* depends on FP_ENROLL_RETRY == FP_VERIFY_RETRY */
|
||||||
goto next_state;
|
imgdev->action_result = FP_ENROLL_RETRY;
|
||||||
|
goto next_state;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
imgdev->acquire_data = print;
|
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:
|
case IMG_ACTION_IDENTIFY:
|
||||||
identify_process_img(imgdev);
|
identify_process_img(imgdev);
|
||||||
break;
|
break;
|
||||||
|
case IMG_ACTION_CAPTURE:
|
||||||
|
imgdev->action_result = FP_CAPTURE_COMPLETE;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
BUG();
|
BUG();
|
||||||
break;
|
break;
|
||||||
|
@ -280,6 +288,9 @@ void fpi_imgdev_session_error(struct fp_img_dev *imgdev, int error)
|
||||||
case IMG_ACTION_IDENTIFY:
|
case IMG_ACTION_IDENTIFY:
|
||||||
fpi_drvcb_report_identify_result(imgdev->dev, error, 0, NULL);
|
fpi_drvcb_report_identify_result(imgdev->dev, error, 0, NULL);
|
||||||
break;
|
break;
|
||||||
|
case IMG_ACTION_CAPTURE:
|
||||||
|
fpi_drvcb_report_capture_result(imgdev->dev, error, NULL);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
fp_err("unhandled action %d", imgdev->action);
|
fp_err("unhandled action %d", imgdev->action);
|
||||||
break;
|
break;
|
||||||
|
@ -300,6 +311,9 @@ void fpi_imgdev_activate_complete(struct fp_img_dev *imgdev, int status)
|
||||||
case IMG_ACTION_IDENTIFY:
|
case IMG_ACTION_IDENTIFY:
|
||||||
fpi_drvcb_identify_started(imgdev->dev, status);
|
fpi_drvcb_identify_started(imgdev->dev, status);
|
||||||
break;
|
break;
|
||||||
|
case IMG_ACTION_CAPTURE:
|
||||||
|
fpi_drvcb_capture_started(imgdev->dev, status);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
fp_err("unhandled action %d", imgdev->action);
|
fp_err("unhandled action %d", imgdev->action);
|
||||||
return;
|
return;
|
||||||
|
@ -325,6 +339,9 @@ void fpi_imgdev_deactivate_complete(struct fp_img_dev *imgdev)
|
||||||
case IMG_ACTION_IDENTIFY:
|
case IMG_ACTION_IDENTIFY:
|
||||||
fpi_drvcb_identify_stopped(imgdev->dev);
|
fpi_drvcb_identify_stopped(imgdev->dev);
|
||||||
break;
|
break;
|
||||||
|
case IMG_ACTION_CAPTURE:
|
||||||
|
fpi_drvcb_capture_stopped(imgdev->dev);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
fp_err("unhandled action %d", imgdev->action);
|
fp_err("unhandled action %d", imgdev->action);
|
||||||
break;
|
break;
|
||||||
|
@ -421,6 +438,14 @@ static int img_dev_identify_start(struct fp_dev *dev)
|
||||||
return generic_acquire_start(dev, IMG_ACTION_IDENTIFY);
|
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)
|
static int img_dev_enroll_stop(struct fp_dev *dev)
|
||||||
{
|
{
|
||||||
struct fp_img_dev *imgdev = dev->priv;
|
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;
|
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)
|
void fpi_img_driver_setup(struct fp_img_driver *idriver)
|
||||||
{
|
{
|
||||||
idriver->driver.type = DRIVER_IMAGING;
|
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.verify_stop = img_dev_verify_stop;
|
||||||
idriver->driver.identify_start = img_dev_identify_start;
|
idriver->driver.identify_start = img_dev_identify_start;
|
||||||
idriver->driver.identify_stop = img_dev_identify_stop;
|
idriver->driver.identify_stop = img_dev_identify_stop;
|
||||||
|
idriver->driver.capture_start = img_dev_capture_start;
|
||||||
|
idriver->driver.capture_stop = img_dev_capture_stop;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -512,3 +512,100 @@ err:
|
||||||
return r;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue