fpi-async.c 18.2 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
/*
 * Asynchronous I/O functionality
 * Copyright (C) 2008 Daniel Drake <dsd@gentoo.org>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */

#define FP_COMPONENT "async"

22
#include "fp_internal.h"
23
#include "fpi-async.h"
24

25 26 27 28
#include <config.h>
#include <errno.h>
#include <glib.h>

29 30 31
/**
 * SECTION:fpi-async
 * @title: Asynchronous operations reporting
32
 * @short_description: Asynchronous operations reporting functions
33 34 35 36 37
 *
 * Those functions are used by primitive drivers to report back their
 * current status. Most drivers, imaging ones, do not need to use them.
 */

38 39 40 41 42 43 44 45 46 47 48
/* Drivers call this when device initialisation has completed */
void fpi_drvcb_open_complete(struct fp_dev *dev, int status)
{
	fp_dbg("status %d", status);
	BUG_ON(dev->state != DEV_STATE_INITIALIZING);
	dev->state = (status) ? DEV_STATE_ERROR : DEV_STATE_INITIALIZED;
	opened_devices = g_slist_prepend(opened_devices, dev);
	if (dev->open_cb)
		dev->open_cb(dev, status, dev->open_cb_data);
}

49 50
/**
 * fp_async_dev_open:
51 52 53
 * @ddev: the struct #fp_dscv_dev discovered device to open
 * @callback: the callback to call when the device has been opened
 * @user_data: user data to pass to the callback
54
 *
55 56 57 58 59 60 61 62
 * Opens and initialises a device. This is the function you call in order
 * to convert a #fp_dscv_dev discovered device into an actual device handle
 * that you can perform operations with.
 *
 * The error status of the opening will be provided as an argument to the
 * #fp_dev_open_cb callback.
 *
 * Returns: 0 on success, non-zero on error
63 64
 */
API_EXPORTED int fp_async_dev_open(struct fp_dscv_dev *ddev, fp_dev_open_cb callback,
65 66
	void *user_data)
{
67
	struct fp_driver *drv;
68
	struct fp_dev *dev;
69
	libusb_device_handle *udevh;
70 71
	int r;

72
	g_return_val_if_fail(ddev != NULL, -ENODEV);
73
	g_return_val_if_fail (callback != NULL, -EINVAL);
74 75 76

	drv = ddev->drv;

77
	G_DEBUG_HERE();
78 79 80 81
	r = libusb_open(ddev->udev, &udevh);
	if (r < 0) {
		fp_err("usb_open failed, error %d", r);
		return r;
82 83 84 85 86 87 88
	}

	dev = g_malloc0(sizeof(*dev));
	dev->drv = drv;
	dev->udev = udevh;
	dev->__enroll_stage = -1;
	dev->state = DEV_STATE_INITIALIZING;
89
	dev->open_cb = callback;
90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110
	dev->open_cb_data = user_data;

	if (!drv->open) {
		fpi_drvcb_open_complete(dev, 0);
		return 0;
	}

	dev->state = DEV_STATE_INITIALIZING;
	r = drv->open(dev, ddev->driver_data);
	if (r) {
		fp_err("device initialisation failed, driver=%s", drv->name);
		libusb_close(udevh);
		g_free(dev);
	}

	return r;
}

/* Drivers call this when device deinitialisation has completed */
void fpi_drvcb_close_complete(struct fp_dev *dev)
{
111
	G_DEBUG_HERE();
112 113
	BUG_ON(dev->state != DEV_STATE_DEINITIALIZING);
	dev->state = DEV_STATE_DEINITIALIZED;
114
	fpi_timeout_cancel_all_for_dev(dev);
115 116 117 118 119 120
	libusb_close(dev->udev);
	if (dev->close_cb)
		dev->close_cb(dev, dev->close_cb_data);
	g_free(dev);
}

121 122
/**
 * fp_async_dev_close:
123 124 125 126 127 128
 * @dev: the struct #fp_dev device
 * @callback: the callback to call when the device has been closed
 * @user_data: user data to pass to the callback
 *
 * Closes a device. You must call this function when you have finished using
 * a fingerprint device.
129
 */
130
API_EXPORTED void fp_async_dev_close(struct fp_dev *dev,
131
	fp_operation_stop_cb callback, void *user_data)
132
{
133 134 135 136 137
	struct fp_driver *drv;

	g_return_if_fail (dev != NULL);

	drv = dev->drv;
138

139 140
	g_return_if_fail (drv->close != NULL);

141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169
	if (g_slist_index(opened_devices, (gconstpointer) dev) == -1)
		fp_err("device %p not in opened list!", dev);
	opened_devices = g_slist_remove(opened_devices, (gconstpointer) dev);

	dev->close_cb = callback;
	dev->close_cb_data = user_data;
	dev->state = DEV_STATE_DEINITIALIZING;
	drv->close(dev);
}

/* Drivers call this when enrollment has started */
void fpi_drvcb_enroll_started(struct fp_dev *dev, int status)
{
	fp_dbg("status %d", status);
	BUG_ON(dev->state != DEV_STATE_ENROLL_STARTING);
	if (status) {
		if (status > 0) {
			status = -status;
			fp_dbg("adjusted to %d", status);
		}
		dev->state = DEV_STATE_ERROR;
		if (dev->enroll_stage_cb)
			dev->enroll_stage_cb(dev, status, NULL, NULL,
				dev->enroll_stage_cb_data);
	} else {
		dev->state = DEV_STATE_ENROLLING;
	}
}

170 171
/**
 * fp_async_enroll_start:
172 173 174
 * @dev: the struct #fp_dev device
 * @callback: the callback to call for each stage of the enrollment
 * @user_data: user data to pass to the callback
175
 *
176 177 178 179 180
 * Starts an enrollment and calls @callback for each enrollment stage.
 * See [Enrolling](libfprint-Devices-operations.html#enrolling)
 * for an explanation of enroll stages.
 *
 * Returns: 0 on success, non-zero on error
181
 */
182 183 184
API_EXPORTED int fp_async_enroll_start(struct fp_dev *dev,
	fp_enroll_stage_cb callback, void *user_data)
{
185
	struct fp_driver *drv;
186 187
	int r;

188
	g_return_val_if_fail(dev != NULL, -ENODEV);
189
	g_return_val_if_fail (callback != NULL, -EINVAL);
190 191 192

	drv = dev->drv;

193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233
	if (!dev->nr_enroll_stages || !drv->enroll_start) {
		fp_err("driver %s has 0 enroll stages or no enroll func",
			drv->name);
		return -ENOTSUP;
	}

	fp_dbg("starting enrollment");
	dev->enroll_stage_cb = callback;
	dev->enroll_stage_cb_data = user_data;

	dev->state = DEV_STATE_ENROLL_STARTING;
	r = drv->enroll_start(dev);
	if (r < 0) {
		dev->enroll_stage_cb = NULL;
		fp_err("failed to start enrollment");
		dev->state = DEV_STATE_ERROR;
	}

	return r;
}

/* Drivers call this when an enroll stage has completed */
void fpi_drvcb_enroll_stage_completed(struct fp_dev *dev, int result,
	struct fp_print_data *data, struct fp_img *img)
{
	BUG_ON(dev->state != DEV_STATE_ENROLLING);
	fp_dbg("result %d", result);
	if (!dev->enroll_stage_cb) {
		fp_dbg("ignoring enroll result as no callback is subscribed");
		return;
	}
	if (result == FP_ENROLL_COMPLETE && !data) {
		fp_err("BUG: complete but no data?");
		result = FP_ENROLL_FAIL;
	}
	dev->enroll_stage_cb(dev, result, data, img, dev->enroll_stage_cb_data);
}

/* Drivers call this when enrollment has stopped */
void fpi_drvcb_enroll_stopped(struct fp_dev *dev)
{
234
	G_DEBUG_HERE();
235 236 237 238 239 240
	BUG_ON(dev->state != DEV_STATE_ENROLL_STOPPING);
	dev->state = DEV_STATE_INITIALIZED;
	if (dev->enroll_stop_cb)
		dev->enroll_stop_cb(dev, dev->enroll_stop_cb_data);
}

241 242
/**
 * fp_async_enroll_stop:
243 244 245 246 247
 * @dev: the struct #fp_dev device
 * @callback: the callback to call when the enrollment has been cancelled
 * @user_data: user data to pass to the callback
 *
 * Stops an ongoing enrollment started with fp_async_enroll_start().
248
 *
249
 * Returns: 0 on success, non-zero on error
250
 */
251
API_EXPORTED int fp_async_enroll_stop(struct fp_dev *dev,
252
	fp_operation_stop_cb callback, void *user_data)
253
{
254
	struct fp_driver *drv;
255 256
	int r;

257 258 259 260
	g_return_val_if_fail(dev != NULL, -ENODEV);

	drv = dev->drv;

261
	G_DEBUG_HERE();
262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283
	if (!drv->enroll_start)
		return -ENOTSUP;

	dev->enroll_stage_cb = NULL;
	dev->enroll_stop_cb = callback;
	dev->enroll_stop_cb_data = user_data;
	dev->state = DEV_STATE_ENROLL_STOPPING;

	if (!drv->enroll_stop) {
		fpi_drvcb_enroll_stopped(dev);
		return 0;
	}

	r = drv->enroll_stop(dev);
	if (r < 0) {
		fp_err("failed to stop enrollment");
		dev->enroll_stop_cb = NULL;
	}

	return r;
}

284 285
/**
 * fp_async_verify_start:
286 287 288 289 290 291 292 293 294
 * @dev: the struct #fp_dev device
 * @data: the print to verify against. Must have been previously
 * enrolled with a device compatible to the device selected to perform the scan
 * @callback: the callback to call when the verification has finished
 * @user_data: user data to pass to the callback
 *
 * Starts a verification and calls @callback when the verification has
 * finished. See fp_verify_finger_img() for the synchronous API. When the
 * @callback has been called, you must call fp_async_verify_stop().
295
 *
296
 * Returns: 0 on success, non-zero on error
297
 */
298
API_EXPORTED int fp_async_verify_start(struct fp_dev *dev,
299
	struct fp_print_data *data, fp_img_operation_cb callback, void *user_data)
300
{
301
	struct fp_driver *drv;
302 303
	int r;

304
	g_return_val_if_fail(dev != NULL, -ENODEV);
305
	g_return_val_if_fail (callback != NULL, -EINVAL);
306 307 308

	drv = dev->drv;

309
	G_DEBUG_HERE();
310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329
	if (!drv->verify_start)
		return -ENOTSUP;

	dev->state = DEV_STATE_VERIFY_STARTING;
	dev->verify_cb = callback;
	dev->verify_cb_data = user_data;
	dev->verify_data = data;

	r = drv->verify_start(dev);
	if (r < 0) {
		dev->verify_cb = NULL;
		dev->state = DEV_STATE_ERROR;
		fp_err("failed to start verification, error %d", r);
	}
	return r;
}

/* Drivers call this when verification has started */
void fpi_drvcb_verify_started(struct fp_dev *dev, int status)
{
330
	G_DEBUG_HERE();
331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363
	BUG_ON(dev->state != DEV_STATE_VERIFY_STARTING);
	if (status) {
		if (status > 0) {
			status = -status;
			fp_dbg("adjusted to %d", status);
		}
		dev->state = DEV_STATE_ERROR;
		if (dev->verify_cb)
			dev->verify_cb(dev, status, NULL, dev->verify_cb_data);
	} else {
		dev->state = DEV_STATE_VERIFYING;
	}
}

/* Drivers call this to report a verify result (which might mark completion) */
void fpi_drvcb_report_verify_result(struct fp_dev *dev, int result,
	struct fp_img *img)
{
	fp_dbg("result %d", result);
	BUG_ON(dev->state != DEV_STATE_VERIFYING);
	if (result < 0 || result == FP_VERIFY_NO_MATCH
			|| result == FP_VERIFY_MATCH)
		dev->state = DEV_STATE_VERIFY_DONE;

	if (dev->verify_cb)
		dev->verify_cb(dev, result, img, dev->verify_cb_data);
	else
		fp_dbg("ignoring verify result as no callback is subscribed");
}

/* Drivers call this when verification has stopped */
void fpi_drvcb_verify_stopped(struct fp_dev *dev)
{
364
	G_DEBUG_HERE();
365 366 367 368 369 370
	BUG_ON(dev->state != DEV_STATE_VERIFY_STOPPING);
	dev->state = DEV_STATE_INITIALIZED;
	if (dev->verify_stop_cb)
		dev->verify_stop_cb(dev, dev->verify_stop_cb_data);
}

371 372
/**
 * fp_async_verify_stop:
373 374 375
 * @dev: the struct #fp_dev device
 * @callback: the callback to call to finish a verification
 * @user_data: user data to pass to the callback
376
 *
377 378 379
 * Finishes an ongoing verification started with fp_async_verify_start().
 *
 * Returns: 0 on success, non-zero on error
380
 */
381
API_EXPORTED int fp_async_verify_stop(struct fp_dev *dev,
382
	fp_operation_stop_cb callback, void *user_data)
383
{
384
	struct fp_driver *drv;
385 386 387
	gboolean iterating = (dev->state == DEV_STATE_VERIFYING);
	int r;

388 389 390 391
	g_return_val_if_fail(dev != NULL, -ENODEV);

	drv = dev->drv;

392
	G_DEBUG_HERE();
393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417
	BUG_ON(dev->state != DEV_STATE_ERROR
		&& dev->state != DEV_STATE_VERIFYING
		&& dev->state != DEV_STATE_VERIFY_DONE);

	dev->verify_cb = NULL;
	dev->verify_stop_cb = callback;
	dev->verify_stop_cb_data = user_data;
	dev->state = DEV_STATE_VERIFY_STOPPING;

	if (!drv->verify_start)
		return -ENOTSUP;
	if (!drv->verify_stop) {
		dev->state = DEV_STATE_INITIALIZED;
		fpi_drvcb_verify_stopped(dev);
		return 0;
	}

	r = drv->verify_stop(dev, iterating);
	if (r < 0) {
		fp_err("failed to stop verification");
		dev->verify_stop_cb = NULL;
	}
	return r;
}

418 419
/**
 * fp_async_identify_start:
420 421 422 423 424 425 426 427 428
 * @dev: the struct #fp_dev device
 * @gallery: NULL-terminated array of pointers to the prints to
 * identify against. Each one must have been previously enrolled with a device
 * compatible to the device selected to perform the scan
 * @callback: the callback to call when the identification has finished
 * @user_data: user data to pass to the callback
 *
 * Performs a new scan and verifies it against a previously enrolled print.
 * See also: fp_verify_finger_img()
429
 *
430
 * Returns: 0 on success, non-zero on error
431
 */
432 433 434
API_EXPORTED int fp_async_identify_start(struct fp_dev *dev,
	struct fp_print_data **gallery, fp_identify_cb callback, void *user_data)
{
435
	struct fp_driver *drv;
436 437
	int r;

438
	g_return_val_if_fail(dev != NULL, -ENODEV);
439
	g_return_val_if_fail (callback != NULL, -EINVAL);
440 441 442

	drv = dev->drv;

443
	G_DEBUG_HERE();
444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494
	if (!drv->identify_start)
		return -ENOTSUP;
	dev->state = DEV_STATE_IDENTIFY_STARTING;
	dev->identify_cb = callback;
	dev->identify_cb_data = user_data;
	dev->identify_gallery = gallery;

	r = drv->identify_start(dev);
	if (r < 0) {
		fp_err("identify_start failed with error %d", r);
		dev->identify_cb = NULL;
		dev->state = DEV_STATE_ERROR;
	}
	return r;
}

/* Driver-lib: identification has started, expect results soon */
void fpi_drvcb_identify_started(struct fp_dev *dev, int status)
{
	fp_dbg("status %d", status);
	BUG_ON(dev->state != DEV_STATE_IDENTIFY_STARTING);
	if (status) {
		if (status > 0) {
			status = -status;
			fp_dbg("adjusted to %d", status);
		}
		dev->state = DEV_STATE_ERROR;
		if (dev->identify_cb)
			dev->identify_cb(dev, status, 0, NULL, dev->identify_cb_data);
	} else {
		dev->state = DEV_STATE_IDENTIFYING;
	}
}

/* Drivers report an identify result (which might mark completion) */
void fpi_drvcb_report_identify_result(struct fp_dev *dev, int result,
	size_t match_offset, struct fp_img *img)
{
	fp_dbg("result %d", result);
	BUG_ON(dev->state != DEV_STATE_IDENTIFYING
		&& dev->state != DEV_STATE_ERROR);
	if (result < 0 || result == FP_VERIFY_NO_MATCH
			|| result == FP_VERIFY_MATCH)
		dev->state = DEV_STATE_IDENTIFY_DONE;

	if (dev->identify_cb)
		dev->identify_cb(dev, result, match_offset, img, dev->identify_cb_data);
	else
		fp_dbg("ignoring verify result as no callback is subscribed");
}

495 496
/**
 * fp_async_identify_stop:
497 498 499 500 501
 * @dev: the struct #fp_dev device
 * @callback: the callback to call when the identification has stopped
 * @user_data: user data to pass to the callback
 *
 * Stops an ongoing identification started with fp_async_identify_start().
502
 *
503
 * Returns: 0 on success, non-zero on error
504
 */
505
API_EXPORTED int fp_async_identify_stop(struct fp_dev *dev,
506
	fp_operation_stop_cb callback, void *user_data)
507
{
508
	struct fp_driver *drv;
509 510 511
	gboolean iterating = (dev->state == DEV_STATE_IDENTIFYING);
	int r;

512 513 514 515
	g_return_val_if_fail(dev != NULL, -ENODEV);

	drv = dev->drv;

516
	G_DEBUG_HERE();
517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544
	BUG_ON(dev->state != DEV_STATE_IDENTIFYING
		&& dev->state != DEV_STATE_IDENTIFY_DONE);

	dev->state = DEV_STATE_IDENTIFY_STOPPING;
	dev->identify_cb = NULL;
	dev->identify_stop_cb = callback;
	dev->identify_stop_cb_data = user_data;

	if (!drv->identify_start)
		return -ENOTSUP;	
	if (!drv->identify_stop) {
		dev->state = DEV_STATE_INITIALIZED;
		fpi_drvcb_identify_stopped(dev);
		return 0;
	}

	r = drv->identify_stop(dev, iterating);
	if (r < 0) {
		fp_err("failed to stop identification");
		dev->identify_stop_cb = NULL;
	}

	return r;
}

/* Drivers call this when identification has stopped */
void fpi_drvcb_identify_stopped(struct fp_dev *dev)
{
545
	G_DEBUG_HERE();
546 547 548 549 550 551
	BUG_ON(dev->state != DEV_STATE_IDENTIFY_STOPPING);
	dev->state = DEV_STATE_INITIALIZED;
	if (dev->identify_stop_cb)
		dev->identify_stop_cb(dev, dev->identify_stop_cb_data);
}

552 553
/**
 * fp_async_capture_start:
554 555 556 557
 * @dev: the struct #fp_dev device
 * @unconditional: whether to unconditionally capture an image, or to only capture when a finger is detected
 * @callback: the callback to call when the capture has finished
 * @user_data: user data to pass to the callback
558
 *
559 560 561 562 563 564
 * Start the capture of an #fp_img from a device. When the @callback has been called,
 * you must call fp_async_capture_stop().
 *
 * Returns: 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
565
 */
566
API_EXPORTED int fp_async_capture_start(struct fp_dev *dev, int unconditional,
567
	fp_img_operation_cb callback, void *user_data)
568
{
569
	struct fp_driver *drv;
570 571
	int r;

572
	g_return_val_if_fail(dev != NULL, -ENODEV);
573
	g_return_val_if_fail (callback != NULL, -EINVAL);
574 575 576

	drv = dev->drv;

577
	G_DEBUG_HERE();
578 579 580 581 582 583 584 585 586 587 588 589
	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;
590
		fp_err("failed to start capture, error %d", r);
591 592 593 594 595 596 597
	}
	return r;
}

/* Drivers call this when capture has started */
void fpi_drvcb_capture_started(struct fp_dev *dev, int status)
{
598
	G_DEBUG_HERE();
599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630
	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)
{
631
	G_DEBUG_HERE();
632 633 634 635 636 637
	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);
}

638 639
/**
 * fp_async_capture_stop:
640 641 642 643 644
 * @dev: the struct #fp_dev device
 * @callback: the callback to call when the capture has been stopped
 * @user_data: user data to pass to the callback
 *
 * Stops an ongoing verification started with fp_async_capture_start().
645
 *
646
 * Returns: 0 on success, non-zero on error
647
 */
648
API_EXPORTED int fp_async_capture_stop(struct fp_dev *dev,
649
	fp_operation_stop_cb callback, void *user_data)
650
{
651
	struct fp_driver *drv;
652 653
	int r;

654 655 656 657
	g_return_val_if_fail(dev != NULL, -ENODEV);

	drv = dev->drv;

658
	G_DEBUG_HERE();
659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677
	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) {
678
		fp_err("failed to stop capture");
679 680 681 682
		dev->capture_stop_cb = NULL;
	}
	return r;
}