Tag fingerprint devices in HAL
[libfprint.git] / libfprint / async.c
blob67e3481e348d5ab6df6b6662c5e784cedb9b6e25
1 /*
2 * Asynchronous I/O functionality
3 * Copyright (C) 2008 Daniel Drake <dsd@gentoo.org>
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 #define FP_COMPONENT "async"
22 #include <config.h>
23 #include <errno.h>
24 #include <glib.h>
26 #include "fp_internal.h"
28 /* Drivers call this when device initialisation has completed */
29 void fpi_drvcb_open_complete(struct fp_dev *dev, int status)
31 fp_dbg("status %d", status);
32 BUG_ON(dev->state != DEV_STATE_INITIALIZING);
33 dev->state = (status) ? DEV_STATE_ERROR : DEV_STATE_INITIALIZED;
34 opened_devices = g_slist_prepend(opened_devices, dev);
35 if (dev->open_cb)
36 dev->open_cb(dev, status, dev->open_cb_data);
39 API_EXPORTED int fp_async_dev_open(struct fp_dscv_dev *ddev, fp_dev_open_cb cb,
40 void *user_data)
42 struct fp_driver *drv = ddev->drv;
43 struct fp_dev *dev;
44 libusb_device_handle *udevh;
45 int r;
47 fp_dbg("");
48 r = libusb_open(ddev->udev, &udevh);
49 if (r < 0) {
50 fp_err("usb_open failed, error %d", r);
51 return r;
54 dev = g_malloc0(sizeof(*dev));
55 dev->drv = drv;
56 dev->udev = udevh;
57 dev->__enroll_stage = -1;
58 dev->state = DEV_STATE_INITIALIZING;
59 dev->open_cb = cb;
60 dev->open_cb_data = user_data;
62 if (!drv->open) {
63 fpi_drvcb_open_complete(dev, 0);
64 return 0;
67 dev->state = DEV_STATE_INITIALIZING;
68 r = drv->open(dev, ddev->driver_data);
69 if (r) {
70 fp_err("device initialisation failed, driver=%s", drv->name);
71 libusb_close(udevh);
72 g_free(dev);
75 return r;
78 /* Drivers call this when device deinitialisation has completed */
79 void fpi_drvcb_close_complete(struct fp_dev *dev)
81 fp_dbg("");
82 BUG_ON(dev->state != DEV_STATE_DEINITIALIZING);
83 dev->state = DEV_STATE_DEINITIALIZED;
84 libusb_close(dev->udev);
85 if (dev->close_cb)
86 dev->close_cb(dev, dev->close_cb_data);
87 g_free(dev);
90 API_EXPORTED void fp_async_dev_close(struct fp_dev *dev,
91 fp_dev_close_cb callback, void *user_data)
93 struct fp_driver *drv = dev->drv;
95 if (g_slist_index(opened_devices, (gconstpointer) dev) == -1)
96 fp_err("device %p not in opened list!", dev);
97 opened_devices = g_slist_remove(opened_devices, (gconstpointer) dev);
99 dev->close_cb = callback;
100 dev->close_cb_data = user_data;
102 if (!drv->close) {
103 fpi_drvcb_close_complete(dev);
104 return;
107 dev->state = DEV_STATE_DEINITIALIZING;
108 drv->close(dev);
111 /* Drivers call this when enrollment has started */
112 void fpi_drvcb_enroll_started(struct fp_dev *dev, int status)
114 fp_dbg("status %d", status);
115 BUG_ON(dev->state != DEV_STATE_ENROLL_STARTING);
116 if (status) {
117 if (status > 0) {
118 status = -status;
119 fp_dbg("adjusted to %d", status);
121 dev->state = DEV_STATE_ERROR;
122 if (dev->enroll_stage_cb)
123 dev->enroll_stage_cb(dev, status, NULL, NULL,
124 dev->enroll_stage_cb_data);
125 } else {
126 dev->state = DEV_STATE_ENROLLING;
130 API_EXPORTED int fp_async_enroll_start(struct fp_dev *dev,
131 fp_enroll_stage_cb callback, void *user_data)
133 struct fp_driver *drv = dev->drv;
134 int r;
136 if (!dev->nr_enroll_stages || !drv->enroll_start) {
137 fp_err("driver %s has 0 enroll stages or no enroll func",
138 drv->name);
139 return -ENOTSUP;
142 fp_dbg("starting enrollment");
143 dev->enroll_stage_cb = callback;
144 dev->enroll_stage_cb_data = user_data;
146 dev->state = DEV_STATE_ENROLL_STARTING;
147 r = drv->enroll_start(dev);
148 if (r < 0) {
149 dev->enroll_stage_cb = NULL;
150 fp_err("failed to start enrollment");
151 dev->state = DEV_STATE_ERROR;
154 return r;
157 /* Drivers call this when an enroll stage has completed */
158 void fpi_drvcb_enroll_stage_completed(struct fp_dev *dev, int result,
159 struct fp_print_data *data, struct fp_img *img)
161 BUG_ON(dev->state != DEV_STATE_ENROLLING);
162 fp_dbg("result %d", result);
163 if (!dev->enroll_stage_cb) {
164 fp_dbg("ignoring enroll result as no callback is subscribed");
165 return;
167 if (result == FP_ENROLL_COMPLETE && !data) {
168 fp_err("BUG: complete but no data?");
169 result = FP_ENROLL_FAIL;
171 dev->enroll_stage_cb(dev, result, data, img, dev->enroll_stage_cb_data);
174 /* Drivers call this when enrollment has stopped */
175 void fpi_drvcb_enroll_stopped(struct fp_dev *dev)
177 fp_dbg("");
178 BUG_ON(dev->state != DEV_STATE_ENROLL_STOPPING);
179 dev->state = DEV_STATE_INITIALIZED;
180 if (dev->enroll_stop_cb)
181 dev->enroll_stop_cb(dev, dev->enroll_stop_cb_data);
184 API_EXPORTED int fp_async_enroll_stop(struct fp_dev *dev,
185 fp_enroll_stop_cb callback, void *user_data)
187 struct fp_driver *drv = dev->drv;
188 int r;
190 fp_dbg("");
191 if (!drv->enroll_start)
192 return -ENOTSUP;
194 dev->enroll_stage_cb = NULL;
195 dev->enroll_stop_cb = callback;
196 dev->enroll_stop_cb_data = user_data;
197 dev->state = DEV_STATE_ENROLL_STOPPING;
199 if (!drv->enroll_stop) {
200 fpi_drvcb_enroll_stopped(dev);
201 return 0;
204 r = drv->enroll_stop(dev);
205 if (r < 0) {
206 fp_err("failed to stop enrollment");
207 dev->enroll_stop_cb = NULL;
210 return r;
213 API_EXPORTED int fp_async_verify_start(struct fp_dev *dev,
214 struct fp_print_data *data, fp_verify_cb callback, void *user_data)
216 struct fp_driver *drv = dev->drv;
217 int r;
219 fp_dbg("");
220 if (!drv->verify_start)
221 return -ENOTSUP;
223 dev->state = DEV_STATE_VERIFY_STARTING;
224 dev->verify_cb = callback;
225 dev->verify_cb_data = user_data;
226 dev->verify_data = data;
228 r = drv->verify_start(dev);
229 if (r < 0) {
230 dev->verify_cb = NULL;
231 dev->state = DEV_STATE_ERROR;
232 fp_err("failed to start verification, error %d", r);
234 return r;
237 /* Drivers call this when verification has started */
238 void fpi_drvcb_verify_started(struct fp_dev *dev, int status)
240 fp_dbg("");
241 BUG_ON(dev->state != DEV_STATE_VERIFY_STARTING);
242 if (status) {
243 if (status > 0) {
244 status = -status;
245 fp_dbg("adjusted to %d", status);
247 dev->state = DEV_STATE_ERROR;
248 if (dev->verify_cb)
249 dev->verify_cb(dev, status, NULL, dev->verify_cb_data);
250 } else {
251 dev->state = DEV_STATE_VERIFYING;
255 /* Drivers call this to report a verify result (which might mark completion) */
256 void fpi_drvcb_report_verify_result(struct fp_dev *dev, int result,
257 struct fp_img *img)
259 fp_dbg("result %d", result);
260 BUG_ON(dev->state != DEV_STATE_VERIFYING);
261 if (result < 0 || result == FP_VERIFY_NO_MATCH
262 || result == FP_VERIFY_MATCH)
263 dev->state = DEV_STATE_VERIFY_DONE;
265 if (dev->verify_cb)
266 dev->verify_cb(dev, result, img, dev->verify_cb_data);
267 else
268 fp_dbg("ignoring verify result as no callback is subscribed");
271 /* Drivers call this when verification has stopped */
272 void fpi_drvcb_verify_stopped(struct fp_dev *dev)
274 fp_dbg("");
275 BUG_ON(dev->state != DEV_STATE_VERIFY_STOPPING);
276 dev->state = DEV_STATE_INITIALIZED;
277 if (dev->verify_stop_cb)
278 dev->verify_stop_cb(dev, dev->verify_stop_cb_data);
281 API_EXPORTED int fp_async_verify_stop(struct fp_dev *dev,
282 fp_verify_stop_cb callback, void *user_data)
284 struct fp_driver *drv = dev->drv;
285 gboolean iterating = (dev->state == DEV_STATE_VERIFYING);
286 int r;
288 fp_dbg("");
289 BUG_ON(dev->state != DEV_STATE_ERROR
290 && dev->state != DEV_STATE_VERIFYING
291 && dev->state != DEV_STATE_VERIFY_DONE);
293 dev->verify_cb = NULL;
294 dev->verify_stop_cb = callback;
295 dev->verify_stop_cb_data = user_data;
296 dev->state = DEV_STATE_VERIFY_STOPPING;
298 if (!drv->verify_start)
299 return -ENOTSUP;
300 if (!drv->verify_stop) {
301 dev->state = DEV_STATE_INITIALIZED;
302 fpi_drvcb_verify_stopped(dev);
303 return 0;
306 r = drv->verify_stop(dev, iterating);
307 if (r < 0) {
308 fp_err("failed to stop verification");
309 dev->verify_stop_cb = NULL;
311 return r;
314 API_EXPORTED int fp_async_identify_start(struct fp_dev *dev,
315 struct fp_print_data **gallery, fp_identify_cb callback, void *user_data)
317 struct fp_driver *drv = dev->drv;
318 int r;
320 fp_dbg("");
321 if (!drv->identify_start)
322 return -ENOTSUP;
323 dev->state = DEV_STATE_IDENTIFY_STARTING;
324 dev->identify_cb = callback;
325 dev->identify_cb_data = user_data;
326 dev->identify_gallery = gallery;
328 r = drv->identify_start(dev);
329 if (r < 0) {
330 fp_err("identify_start failed with error %d", r);
331 dev->identify_cb = NULL;
332 dev->state = DEV_STATE_ERROR;
334 return r;
337 /* Driver-lib: identification has started, expect results soon */
338 void fpi_drvcb_identify_started(struct fp_dev *dev, int status)
340 fp_dbg("status %d", status);
341 BUG_ON(dev->state != DEV_STATE_IDENTIFY_STARTING);
342 if (status) {
343 if (status > 0) {
344 status = -status;
345 fp_dbg("adjusted to %d", status);
347 dev->state = DEV_STATE_ERROR;
348 if (dev->identify_cb)
349 dev->identify_cb(dev, status, 0, NULL, dev->identify_cb_data);
350 } else {
351 dev->state = DEV_STATE_IDENTIFYING;
355 /* Drivers report an identify result (which might mark completion) */
356 void fpi_drvcb_report_identify_result(struct fp_dev *dev, int result,
357 size_t match_offset, struct fp_img *img)
359 fp_dbg("result %d", result);
360 BUG_ON(dev->state != DEV_STATE_IDENTIFYING
361 && dev->state != DEV_STATE_ERROR);
362 if (result < 0 || result == FP_VERIFY_NO_MATCH
363 || result == FP_VERIFY_MATCH)
364 dev->state = DEV_STATE_IDENTIFY_DONE;
366 if (dev->identify_cb)
367 dev->identify_cb(dev, result, match_offset, img, dev->identify_cb_data);
368 else
369 fp_dbg("ignoring verify result as no callback is subscribed");
372 API_EXPORTED int fp_async_identify_stop(struct fp_dev *dev,
373 fp_identify_stop_cb callback, void *user_data)
375 struct fp_driver *drv = dev->drv;
376 gboolean iterating = (dev->state == DEV_STATE_IDENTIFYING);
377 int r;
379 fp_dbg("");
380 BUG_ON(dev->state != DEV_STATE_IDENTIFYING
381 && dev->state != DEV_STATE_IDENTIFY_DONE);
383 dev->state = DEV_STATE_IDENTIFY_STOPPING;
384 dev->identify_cb = NULL;
385 dev->identify_stop_cb = callback;
386 dev->identify_stop_cb_data = user_data;
388 if (!drv->identify_start)
389 return -ENOTSUP;
390 if (!drv->identify_stop) {
391 dev->state = DEV_STATE_INITIALIZED;
392 fpi_drvcb_identify_stopped(dev);
393 return 0;
396 r = drv->identify_stop(dev, iterating);
397 if (r < 0) {
398 fp_err("failed to stop identification");
399 dev->identify_stop_cb = NULL;
402 return r;
405 /* Drivers call this when identification has stopped */
406 void fpi_drvcb_identify_stopped(struct fp_dev *dev)
408 fp_dbg("");
409 BUG_ON(dev->state != DEV_STATE_IDENTIFY_STOPPING);
410 dev->state = DEV_STATE_INITIALIZED;
411 if (dev->identify_stop_cb)
412 dev->identify_stop_cb(dev, dev->identify_stop_cb_data);