Basic image driver foundations
[libfprint.git] / libfprint / core.c
blob24a9adc54bb6ef5268dbebbe8458bfb66d13f8ff
1 /*
2 * Core functions for libfprint
3 * Copyright (C) 2007 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 #include <config.h>
21 #include <errno.h>
22 #include <stdio.h>
24 #include <glib.h>
25 #include <usb.h>
27 #include "fp_internal.h"
29 static GList *registered_drivers = NULL;
31 void fpi_log(enum fpi_log_level level, const char *component,
32 const char *function, const char *format, ...)
34 va_list args;
35 FILE *stream = stdout;
36 const char *prefix;
38 switch (level) {
39 case LOG_LEVEL_INFO:
40 prefix = "info";
41 break;
42 case LOG_LEVEL_WARNING:
43 stream = stderr;
44 prefix = "warning";
45 break;
46 case LOG_LEVEL_ERROR:
47 stream = stderr;
48 prefix = "error";
49 break;
50 case LOG_LEVEL_DEBUG:
51 stream = stderr;
52 prefix = "debug";
53 break;
54 default:
55 stream = stderr;
56 prefix = "unknown";
57 break;
60 fprintf(stream, "%s:%s [%s] ", component ? component : "fp", prefix,
61 function);
63 va_start (args, format);
64 vfprintf(stream, format, args);
65 va_end (args);
67 fprintf(stream, "\n");
70 static void register_driver(struct fp_driver *drv)
72 registered_drivers = g_list_prepend(registered_drivers, (gpointer) drv);
73 fp_dbg("registered driver %s", drv->name);
76 static struct fp_driver * const primitive_drivers[] = {
77 &upekts_driver,
80 static struct fp_img_driver * const img_drivers[] = {
81 &uru4000_driver,
84 static void register_drivers(void)
86 unsigned int i;
88 for (i = 0; i < ARRAY_SIZE(primitive_drivers); i++)
89 register_driver(primitive_drivers[i]);
91 for (i = 0; i < ARRAY_SIZE(img_drivers); i++) {
92 struct fp_img_driver *imgdriver = img_drivers[i];
93 fpi_img_driver_setup(imgdriver);
94 register_driver(&imgdriver->driver);
98 static struct fp_driver *find_supporting_driver(struct usb_device *udev)
100 GList *elem = registered_drivers;
102 do {
103 struct fp_driver *drv = elem->data;
104 const struct usb_id *id;
106 for (id = drv->id_table; id->vendor; id++)
107 if (udev->descriptor.idVendor == id->vendor &&
108 udev->descriptor.idProduct == id->product) {
109 fp_dbg("driver %s supports USB device %04x:%04x",
110 drv->name, id->vendor, id->product);
111 return drv;
113 } while (elem = g_list_next(elem));
114 return NULL;
117 API_EXPORTED struct fp_dscv_dev **fp_discover_devs(void)
119 GList *tmplist = NULL;
120 struct fp_dscv_dev **list;
121 struct usb_device *udev;
122 struct usb_bus *bus;
123 int dscv_count = 0;
125 if (registered_drivers == NULL)
126 return NULL;
128 usb_find_busses();
129 usb_find_devices();
131 /* Check each device against each driver, temporarily storing successfully
132 * discovered devices in a GList.
134 * Quite inefficient but excusable as we'll only be dealing with small
135 * sets of drivers against small sets of USB devices */
136 for (bus = usb_get_busses(); bus; bus = bus->next)
137 for (udev = bus->devices; udev; udev = udev->next) {
138 struct fp_driver *drv = find_supporting_driver(udev);
139 struct fp_dscv_dev *ddev;
140 if (!drv)
141 continue;
142 ddev = g_malloc0(sizeof(*ddev));
143 ddev->drv = drv;
144 ddev->udev = udev;
145 tmplist = g_list_prepend(tmplist, (gpointer) ddev);
146 dscv_count++;
149 /* Convert our temporary GList into a standard NULL-terminated pointer
150 * array. */
151 list = g_malloc(sizeof(*list) * (dscv_count + 1));
152 if (dscv_count > 0) {
153 GList *elem = tmplist;
154 int i = 0;
155 do {
156 list[i++] = elem->data;
157 } while (elem = g_list_next(elem));
159 list[dscv_count] = NULL; /* NULL-terminate */
161 g_list_free(tmplist);
162 return list;
165 API_EXPORTED void fp_dscv_devs_free(struct fp_dscv_dev **devs)
167 int i;
168 if (!devs)
169 return;
171 for (i = 0; devs[i]; i++)
172 g_free(devs[i]);
173 g_free(devs);
176 API_EXPORTED struct fp_driver *fp_dscv_dev_get_driver(struct fp_dscv_dev *dev)
178 return dev->drv;
181 API_EXPORTED struct fp_dev *fp_dev_open(struct fp_dscv_dev *ddev)
183 struct fp_dev *dev;
184 struct fp_driver *drv = ddev->drv;
185 int r;
187 usb_dev_handle *udevh = usb_open(ddev->udev);
188 if (!udevh) {
189 fp_err("usb_open failed");
190 return NULL;
193 dev = g_malloc0(sizeof(*dev));
194 dev->drv = drv;
195 dev->udev = udevh;
196 dev->__enroll_stage = -1;
198 if (drv->init) {
199 r = drv->init(dev);
200 if (r) {
201 fp_err("device initialisation failed, driver=%s", drv->name);
202 usb_close(udevh);
203 g_free(dev);
204 return NULL;
208 fp_dbg("");
209 return dev;
212 API_EXPORTED void fp_dev_close(struct fp_dev *dev)
214 fp_dbg("");
215 if (dev->drv->exit)
216 dev->drv->exit(dev);
217 usb_close(dev->udev);
218 g_free(dev);
221 API_EXPORTED struct fp_driver *fp_dev_get_driver(struct fp_dev *dev)
223 return dev->drv;
226 API_EXPORTED int fp_dev_get_nr_enroll_stages(struct fp_dev *dev)
228 return dev->nr_enroll_stages;
231 API_EXPORTED const char *fp_driver_get_name(struct fp_driver *drv)
233 return drv->name;
236 API_EXPORTED const char *fp_driver_get_full_name(struct fp_driver *drv)
238 return drv->full_name;
241 API_EXPORTED int fp_enroll_finger(struct fp_dev *dev,
242 struct fp_print_data **print_data)
244 struct fp_driver *drv = dev->drv;
245 int ret;
246 int stage = dev->__enroll_stage;
247 gboolean initial = FALSE;
249 if (!dev->nr_enroll_stages || !drv->enroll) {
250 fp_err("driver %s has 0 enroll stages or no enroll func",
251 drv->name);
252 return -ENOTSUP;
255 if (stage == -1) {
256 initial = TRUE;
257 dev->__enroll_stage = ++stage;
260 if (stage >= dev->nr_enroll_stages) {
261 fp_err("exceeding number of enroll stages for device claimed by "
262 "driver %s (%d stages)", drv->name, dev->nr_enroll_stages);
263 dev->__enroll_stage = -1;
264 return -EINVAL;
266 fp_dbg("%s will handle enroll stage %d/%d%s", drv->name, stage,
267 dev->nr_enroll_stages - 1, initial ? " (initial)" : "");
269 ret = drv->enroll(dev, initial, stage, print_data);
270 if (ret < 0) {
271 fp_err("enroll failed with code %d", ret);
272 dev->__enroll_stage = -1;
273 return ret;
275 switch (ret) {
276 case FP_ENROLL_PASS:
277 fp_dbg("enroll stage passed");
278 dev->__enroll_stage = stage + 1;
279 break;
280 case FP_ENROLL_COMPLETE:
281 fp_dbg("enroll complete");
282 dev->__enroll_stage = -1;
283 break;
284 case FP_ENROLL_RETRY:
285 fp_dbg("enroll should retry");
286 break;
287 case FP_ENROLL_RETRY_TOO_SHORT:
288 fp_dbg("swipe was too short, enroll should retry");
289 break;
290 case FP_ENROLL_RETRY_CENTER_FINGER:
291 fp_dbg("finger was not centered, enroll should retry");
292 break;
293 case FP_ENROLL_RETRY_REMOVE_FINGER:
294 fp_dbg("scan failed, remove finger and retry");
295 break;
296 case FP_ENROLL_FAIL:
297 fp_err("enroll failed");
298 dev->__enroll_stage = -1;
299 break;
300 default:
301 fp_err("unrecognised return code %d", ret);
302 dev->__enroll_stage = -1;
303 return -EINVAL;
305 return ret;
308 API_EXPORTED int fp_verify_finger(struct fp_dev *dev,
309 struct fp_print_data *enrolled_print)
311 struct fp_driver *drv = dev->drv;
312 int r;
314 if (!enrolled_print) {
315 fp_err("no print given");
316 return -EINVAL;
319 if (!drv->verify) {
320 fp_err("driver %s has no verify func", drv->name);
321 return -EINVAL;
324 if (!fpi_print_data_compatible(dev, enrolled_print)) {
325 fp_err("print is not compatible with device");
326 return -EINVAL;
329 fp_dbg("to be handled by %s", drv->name);
330 r = drv->verify(dev, enrolled_print);
331 if (r < 0) {
332 fp_dbg("verify error %d", r);
333 return r;
336 switch (r) {
337 case FP_VERIFY_NO_MATCH:
338 fp_dbg("result: no match");
339 break;
340 case FP_VERIFY_MATCH:
341 fp_dbg("result: match");
342 break;
343 case FP_VERIFY_RETRY:
344 fp_dbg("verify should retry");
345 break;
346 case FP_VERIFY_RETRY_TOO_SHORT:
347 fp_dbg("swipe was too short, verify should retry");
348 break;
349 case FP_VERIFY_RETRY_CENTER_FINGER:
350 fp_dbg("finger was not centered, verify should retry");
351 break;
352 case FP_VERIFY_RETRY_REMOVE_FINGER:
353 fp_dbg("scan failed, remove finger and retry");
354 break;
355 default:
356 fp_err("unrecognised return code %d", r);
357 return -EINVAL;
360 return r;
363 API_EXPORTED int fp_init(void)
365 fp_dbg("");
366 usb_init();
367 register_drivers();
368 return 0;