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
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
, ...)
35 FILE *stream
= stdout
;
42 case LOG_LEVEL_WARNING
:
60 fprintf(stream
, "%s:%s [%s] ", component
? component
: "fp", prefix
,
63 va_start (args
, format
);
64 vfprintf(stream
, format
, 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
[] = {
80 static struct fp_img_driver
* const img_drivers
[] = {
84 static void register_drivers(void)
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
;
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
);
113 } while (elem
= g_list_next(elem
));
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
;
125 if (registered_drivers
== NULL
)
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
;
142 ddev
= g_malloc0(sizeof(*ddev
));
145 tmplist
= g_list_prepend(tmplist
, (gpointer
) ddev
);
149 /* Convert our temporary GList into a standard NULL-terminated pointer
151 list
= g_malloc(sizeof(*list
) * (dscv_count
+ 1));
152 if (dscv_count
> 0) {
153 GList
*elem
= tmplist
;
156 list
[i
++] = elem
->data
;
157 } while (elem
= g_list_next(elem
));
159 list
[dscv_count
] = NULL
; /* NULL-terminate */
161 g_list_free(tmplist
);
165 API_EXPORTED
void fp_dscv_devs_free(struct fp_dscv_dev
**devs
)
171 for (i
= 0; devs
[i
]; i
++)
176 API_EXPORTED
struct fp_driver
*fp_dscv_dev_get_driver(struct fp_dscv_dev
*dev
)
181 API_EXPORTED
struct fp_dev
*fp_dev_open(struct fp_dscv_dev
*ddev
)
184 struct fp_driver
*drv
= ddev
->drv
;
187 usb_dev_handle
*udevh
= usb_open(ddev
->udev
);
189 fp_err("usb_open failed");
193 dev
= g_malloc0(sizeof(*dev
));
196 dev
->__enroll_stage
= -1;
201 fp_err("device initialisation failed, driver=%s", drv
->name
);
212 API_EXPORTED
void fp_dev_close(struct fp_dev
*dev
)
217 usb_close(dev
->udev
);
221 API_EXPORTED
struct fp_driver
*fp_dev_get_driver(struct fp_dev
*dev
)
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
)
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
;
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",
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;
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
);
271 fp_err("enroll failed with code %d", ret
);
272 dev
->__enroll_stage
= -1;
277 fp_dbg("enroll stage passed");
278 dev
->__enroll_stage
= stage
+ 1;
280 case FP_ENROLL_COMPLETE
:
281 fp_dbg("enroll complete");
282 dev
->__enroll_stage
= -1;
284 case FP_ENROLL_RETRY
:
285 fp_dbg("enroll should retry");
287 case FP_ENROLL_RETRY_TOO_SHORT
:
288 fp_dbg("swipe was too short, enroll should retry");
290 case FP_ENROLL_RETRY_CENTER_FINGER
:
291 fp_dbg("finger was not centered, enroll should retry");
293 case FP_ENROLL_RETRY_REMOVE_FINGER
:
294 fp_dbg("scan failed, remove finger and retry");
297 fp_err("enroll failed");
298 dev
->__enroll_stage
= -1;
301 fp_err("unrecognised return code %d", ret
);
302 dev
->__enroll_stage
= -1;
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
;
314 if (!enrolled_print
) {
315 fp_err("no print given");
320 fp_err("driver %s has no verify func", drv
->name
);
324 if (!fpi_print_data_compatible(dev
, enrolled_print
)) {
325 fp_err("print is not compatible with device");
329 fp_dbg("to be handled by %s", drv
->name
);
330 r
= drv
->verify(dev
, enrolled_print
);
332 fp_dbg("verify error %d", r
);
337 case FP_VERIFY_NO_MATCH
:
338 fp_dbg("result: no match");
340 case FP_VERIFY_MATCH
:
341 fp_dbg("result: match");
343 case FP_VERIFY_RETRY
:
344 fp_dbg("verify should retry");
346 case FP_VERIFY_RETRY_TOO_SHORT
:
347 fp_dbg("swipe was too short, verify should retry");
349 case FP_VERIFY_RETRY_CENTER_FINGER
:
350 fp_dbg("finger was not centered, verify should retry");
352 case FP_VERIFY_RETRY_REMOVE_FINGER
:
353 fp_dbg("scan failed, remove finger and retry");
356 fp_err("unrecognised return code %d", r
);
363 API_EXPORTED
int fp_init(void)