Clean up on exit, and convert to singly-linked-lists
This adds fp_exit() to the public API, intended to be called while the driving app is shutting down.
This commit is contained in:
parent
a76f55db0d
commit
a86cd51959
10 changed files with 94 additions and 44 deletions
2
TODO
2
TODO
|
@ -4,8 +4,6 @@ identification
|
|||
test suite against NFIQ compliance set
|
||||
make library optionally asynchronous and maybe thread-safe
|
||||
nbis cleanups
|
||||
track open devices, so we can close them during libfprint close
|
||||
free memory during libfprint close
|
||||
API function to determine if img device supports uncond. capture
|
||||
race-free way of saying "save this print but don't overwrite"
|
||||
|
||||
|
|
|
@ -92,7 +92,7 @@ struct fp_print_data *enroll(struct fp_dev *dev) {
|
|||
|
||||
int main(void)
|
||||
{
|
||||
int r;
|
||||
int r = 1;
|
||||
struct fp_dscv_dev *ddev;
|
||||
struct fp_dscv_dev **discovered_devs;
|
||||
struct fp_dev *dev;
|
||||
|
@ -113,20 +113,20 @@ int main(void)
|
|||
discovered_devs = fp_discover_devs();
|
||||
if (!discovered_devs) {
|
||||
fprintf(stderr, "Could not discover devices\n");
|
||||
exit(1);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ddev = discover_device(discovered_devs);
|
||||
if (!ddev) {
|
||||
fprintf(stderr, "No devices detected.\n");
|
||||
exit(1);
|
||||
goto out;
|
||||
}
|
||||
|
||||
dev = fp_dev_open(ddev);
|
||||
fp_dscv_devs_free(discovered_devs);
|
||||
if (!dev) {
|
||||
fprintf(stderr, "Could not open device.\n");
|
||||
exit(1);
|
||||
goto out;
|
||||
}
|
||||
|
||||
printf("Opened device. It's now time to enroll your finger.\n\n");
|
||||
|
@ -141,6 +141,8 @@ int main(void)
|
|||
fp_print_data_free(data);
|
||||
out_close:
|
||||
fp_dev_close(dev);
|
||||
out:
|
||||
fp_exit();
|
||||
return r;
|
||||
}
|
||||
|
||||
|
|
|
@ -54,20 +54,20 @@ int main(void)
|
|||
discovered_devs = fp_discover_devs();
|
||||
if (!discovered_devs) {
|
||||
fprintf(stderr, "Could not discover devices\n");
|
||||
exit(1);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ddev = discover_device(discovered_devs);
|
||||
if (!ddev) {
|
||||
fprintf(stderr, "No devices detected.\n");
|
||||
exit(1);
|
||||
goto out;
|
||||
}
|
||||
|
||||
dev = fp_dev_open(ddev);
|
||||
fp_dscv_devs_free(discovered_devs);
|
||||
if (!dev) {
|
||||
fprintf(stderr, "Could not open device.\n");
|
||||
exit(1);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!fp_dev_supports_imaging(dev)) {
|
||||
|
@ -100,6 +100,8 @@ int main(void)
|
|||
r = 0;
|
||||
out_close:
|
||||
fp_dev_close(dev);
|
||||
out:
|
||||
fp_exit();
|
||||
return r;
|
||||
}
|
||||
|
||||
|
|
|
@ -153,25 +153,25 @@ int main(void)
|
|||
discovered_devs = fp_discover_devs();
|
||||
if (!discovered_devs) {
|
||||
fprintf(stderr, "Could not discover devices\n");
|
||||
exit(1);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ddev = discover_device(discovered_devs);
|
||||
if (!ddev) {
|
||||
fprintf(stderr, "No devices detected.\n");
|
||||
exit(1);
|
||||
goto out;
|
||||
}
|
||||
|
||||
dev = fp_dev_open(ddev);
|
||||
fp_dscv_devs_free(discovered_devs);
|
||||
if (!dev) {
|
||||
fprintf(stderr, "Could not open device.\n");
|
||||
exit(1);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!fp_dev_supports_imaging(dev)) {
|
||||
fprintf(stderr, "this device does not have imaging capabilities.\n");
|
||||
goto out;
|
||||
goto out_close;
|
||||
}
|
||||
|
||||
img_width = fp_dev_get_img_width(dev);
|
||||
|
@ -179,24 +179,24 @@ int main(void)
|
|||
if (img_width <= 0 || img_height <= 0) {
|
||||
fprintf(stderr, "this device returns images with variable dimensions,"
|
||||
" this example does not support that.\n");
|
||||
goto out;
|
||||
goto out_close;
|
||||
}
|
||||
framebuffer = malloc(img_width * img_height * 2);
|
||||
if (!framebuffer)
|
||||
goto out;
|
||||
goto out_close;
|
||||
|
||||
/* make the window */
|
||||
display = XOpenDisplay(getenv("DISPLAY"));
|
||||
if(display == NULL) {
|
||||
fprintf(stderr,"Could not open display \"%s\"\n",
|
||||
getenv("DISPLAY"));
|
||||
goto out;
|
||||
goto out_close;
|
||||
}
|
||||
|
||||
QueryXv();
|
||||
|
||||
if (adaptor < 0)
|
||||
goto out;
|
||||
goto out_close;
|
||||
|
||||
window = XCreateSimpleWindow(display, DefaultRootWindow(display), 0, 0,
|
||||
img_width, img_height, 0,
|
||||
|
@ -216,7 +216,7 @@ int main(void)
|
|||
r = fp_dev_img_capture(dev, 1, &img);
|
||||
if (r) {
|
||||
fprintf(stderr, "image capture failed, code %d\n", r);
|
||||
goto out;
|
||||
goto out_close;
|
||||
}
|
||||
if (standardize)
|
||||
fp_img_standardize(img);
|
||||
|
@ -234,7 +234,7 @@ int main(void)
|
|||
case XK_q:
|
||||
case XK_Q:
|
||||
r = 0;
|
||||
goto out;
|
||||
goto out_close;
|
||||
break;
|
||||
case XK_s:
|
||||
case XK_S:
|
||||
|
@ -245,7 +245,7 @@ int main(void)
|
|||
}
|
||||
|
||||
r = 0;
|
||||
out:
|
||||
out_close:
|
||||
if (framebuffer)
|
||||
free(framebuffer);
|
||||
fp_dev_close(dev);
|
||||
|
@ -253,6 +253,8 @@ out:
|
|||
XUnmapWindow(display, window);
|
||||
if (display != NULL)
|
||||
XFlush(display);
|
||||
out:
|
||||
fp_exit();
|
||||
return r;
|
||||
}
|
||||
|
||||
|
|
|
@ -76,7 +76,7 @@ int verify(struct fp_dev *dev, struct fp_print_data *data)
|
|||
|
||||
int main(void)
|
||||
{
|
||||
int r;
|
||||
int r = 1;
|
||||
struct fp_dscv_dev *ddev;
|
||||
struct fp_dscv_dev **discovered_devs;
|
||||
struct fp_dev *dev;
|
||||
|
@ -91,20 +91,20 @@ int main(void)
|
|||
discovered_devs = fp_discover_devs();
|
||||
if (!discovered_devs) {
|
||||
fprintf(stderr, "Could not discover devices\n");
|
||||
exit(1);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ddev = discover_device(discovered_devs);
|
||||
if (!ddev) {
|
||||
fprintf(stderr, "No devices detected.\n");
|
||||
exit(1);
|
||||
goto out;
|
||||
}
|
||||
|
||||
dev = fp_dev_open(ddev);
|
||||
fp_dscv_devs_free(discovered_devs);
|
||||
if (!dev) {
|
||||
fprintf(stderr, "Could not open device.\n");
|
||||
exit(1);
|
||||
goto out;
|
||||
}
|
||||
|
||||
printf("Opened device. Loading previously enrolled right index finger "
|
||||
|
@ -132,6 +132,8 @@ int main(void)
|
|||
fp_print_data_free(data);
|
||||
out_close:
|
||||
fp_dev_close(dev);
|
||||
out:
|
||||
fp_exit();
|
||||
return r;
|
||||
}
|
||||
|
||||
|
|
|
@ -126,7 +126,7 @@ int verify(struct fp_dev *dev, struct fp_print_data *data)
|
|||
|
||||
int main(void)
|
||||
{
|
||||
int r;
|
||||
int r = 1;
|
||||
struct fp_dscv_dev *ddev;
|
||||
struct fp_dscv_dev **discovered_devs;
|
||||
struct fp_dev *dev;
|
||||
|
@ -141,20 +141,20 @@ int main(void)
|
|||
discovered_devs = fp_discover_devs();
|
||||
if (!discovered_devs) {
|
||||
fprintf(stderr, "Could not discover devices\n");
|
||||
exit(1);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ddev = discover_device(discovered_devs);
|
||||
if (!ddev) {
|
||||
fprintf(stderr, "No devices detected.\n");
|
||||
exit(1);
|
||||
goto out;
|
||||
}
|
||||
|
||||
dev = fp_dev_open(ddev);
|
||||
fp_dscv_devs_free(discovered_devs);
|
||||
if (!dev) {
|
||||
fprintf(stderr, "Could not open device.\n");
|
||||
exit(1);
|
||||
goto out;
|
||||
}
|
||||
|
||||
printf("Opened device. It's now time to enroll your finger.\n\n");
|
||||
|
@ -181,6 +181,8 @@ int main(void)
|
|||
fp_print_data_free(data);
|
||||
out_close:
|
||||
fp_dev_close(dev);
|
||||
out:
|
||||
fp_exit();
|
||||
return r;
|
||||
}
|
||||
|
||||
|
|
|
@ -276,7 +276,8 @@
|
|||
* circumstances, you don't have to worry about driver IDs at all.
|
||||
*/
|
||||
|
||||
static GList *registered_drivers = NULL;
|
||||
static GSList *registered_drivers = NULL;
|
||||
static GSList *opened_devices = NULL;
|
||||
|
||||
void fpi_log(enum fpi_log_level level, const char *component,
|
||||
const char *function, const char *format, ...)
|
||||
|
@ -323,7 +324,7 @@ static void register_driver(struct fp_driver *drv)
|
|||
fp_err("not registering driver %s: driver ID is 0");
|
||||
return;
|
||||
}
|
||||
registered_drivers = g_list_prepend(registered_drivers, (gpointer) drv);
|
||||
registered_drivers = g_slist_prepend(registered_drivers, (gpointer) drv);
|
||||
fp_dbg("registered driver %s", drv->name);
|
||||
}
|
||||
|
||||
|
@ -353,7 +354,7 @@ static void register_drivers(void)
|
|||
static struct fp_driver *find_supporting_driver(struct usb_device *udev,
|
||||
const struct usb_id **usb_id)
|
||||
{
|
||||
GList *elem = registered_drivers;
|
||||
GSList *elem = registered_drivers;
|
||||
|
||||
do {
|
||||
struct fp_driver *drv = elem->data;
|
||||
|
@ -367,7 +368,7 @@ static struct fp_driver *find_supporting_driver(struct usb_device *udev,
|
|||
*usb_id = id;
|
||||
return drv;
|
||||
}
|
||||
} while (elem = g_list_next(elem));
|
||||
} while (elem = g_slist_next(elem));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -405,7 +406,7 @@ static struct fp_dscv_dev *discover_dev(struct usb_device *udev)
|
|||
*/
|
||||
API_EXPORTED struct fp_dscv_dev **fp_discover_devs(void)
|
||||
{
|
||||
GList *tmplist = NULL;
|
||||
GSList *tmplist = NULL;
|
||||
struct fp_dscv_dev **list;
|
||||
struct usb_device *udev;
|
||||
struct usb_bus *bus;
|
||||
|
@ -418,7 +419,7 @@ API_EXPORTED struct fp_dscv_dev **fp_discover_devs(void)
|
|||
usb_find_devices();
|
||||
|
||||
/* Check each device against each driver, temporarily storing successfully
|
||||
* discovered devices in a GList.
|
||||
* discovered devices in a GSList.
|
||||
*
|
||||
* Quite inefficient but excusable as we'll only be dealing with small
|
||||
* sets of drivers against small sets of USB devices */
|
||||
|
@ -427,23 +428,23 @@ API_EXPORTED struct fp_dscv_dev **fp_discover_devs(void)
|
|||
struct fp_dscv_dev *ddev = discover_dev(udev);
|
||||
if (!ddev)
|
||||
continue;
|
||||
tmplist = g_list_prepend(tmplist, (gpointer) ddev);
|
||||
tmplist = g_slist_prepend(tmplist, (gpointer) ddev);
|
||||
dscv_count++;
|
||||
}
|
||||
|
||||
/* Convert our temporary GList into a standard NULL-terminated pointer
|
||||
/* Convert our temporary GSList into a standard NULL-terminated pointer
|
||||
* array. */
|
||||
list = g_malloc(sizeof(*list) * (dscv_count + 1));
|
||||
if (dscv_count > 0) {
|
||||
GList *elem = tmplist;
|
||||
GSList *elem = tmplist;
|
||||
int i = 0;
|
||||
do {
|
||||
list[i++] = elem->data;
|
||||
} while (elem = g_list_next(elem));
|
||||
} while (elem = g_slist_next(elem));
|
||||
}
|
||||
list[dscv_count] = NULL; /* NULL-terminate */
|
||||
|
||||
g_list_free(tmplist);
|
||||
g_slist_free(tmplist);
|
||||
return list;
|
||||
}
|
||||
|
||||
|
@ -601,9 +602,19 @@ API_EXPORTED struct fp_dev *fp_dev_open(struct fp_dscv_dev *ddev)
|
|||
}
|
||||
|
||||
fp_dbg("");
|
||||
opened_devices = g_slist_prepend(opened_devices, (gpointer) dev);
|
||||
return dev;
|
||||
}
|
||||
|
||||
/* performs close operation without modifying opened_devices list */
|
||||
static void do_close(struct fp_dev *dev)
|
||||
{
|
||||
if (dev->drv->exit)
|
||||
dev->drv->exit(dev);
|
||||
usb_close(dev->udev);
|
||||
g_free(dev);
|
||||
}
|
||||
|
||||
/** \ingroup dev
|
||||
* Close a device. You must call this function when you are finished using
|
||||
* a fingerprint device.
|
||||
|
@ -612,10 +623,11 @@ API_EXPORTED struct fp_dev *fp_dev_open(struct fp_dscv_dev *ddev)
|
|||
API_EXPORTED void fp_dev_close(struct fp_dev *dev)
|
||||
{
|
||||
fp_dbg("");
|
||||
if (dev->drv->exit)
|
||||
dev->drv->exit(dev);
|
||||
usb_close(dev->udev);
|
||||
g_free(dev);
|
||||
|
||||
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);
|
||||
do_close(dev);
|
||||
}
|
||||
|
||||
/** \ingroup dev
|
||||
|
@ -986,3 +998,27 @@ API_EXPORTED int fp_init(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/** \ingroup core
|
||||
* Deinitialise libfprint. This function should be called during your program
|
||||
* exit sequence. You must not use any libfprint functions after calling this
|
||||
* function, unless you call fp_init() again.
|
||||
*/
|
||||
API_EXPORTED void fp_exit(void)
|
||||
{
|
||||
GSList *elem = opened_devices;
|
||||
fp_dbg("");
|
||||
|
||||
if (elem != NULL) {
|
||||
do {
|
||||
fp_dbg("naughty app left a device open on exit!");
|
||||
do_close((struct fp_dev *) elem->data);
|
||||
} while (elem = g_slist_next(elem));
|
||||
g_slist_free(opened_devices);
|
||||
opened_devices = NULL;
|
||||
}
|
||||
|
||||
fpi_data_exit();
|
||||
g_slist_free(registered_drivers);
|
||||
registered_drivers = NULL;
|
||||
}
|
||||
|
||||
|
|
|
@ -45,7 +45,6 @@
|
|||
* in any fashion that suits you.
|
||||
*/
|
||||
|
||||
/* FIXME: should free this during library shutdown */
|
||||
static char *base_store = NULL;
|
||||
|
||||
static void storage_setup(void)
|
||||
|
@ -63,6 +62,11 @@ static void storage_setup(void)
|
|||
/* FIXME handle failure */
|
||||
}
|
||||
|
||||
void fpi_data_exit(void)
|
||||
{
|
||||
g_free(base_store);
|
||||
}
|
||||
|
||||
#define FP_FINGER_IS_VALID(finger) \
|
||||
((finger) >= LEFT_THUMB && (finger) <= RIGHT_LITTLE)
|
||||
|
||||
|
|
|
@ -182,6 +182,7 @@ struct fpi_print_data_fp1 {
|
|||
unsigned char data[0];
|
||||
} __attribute__((__packed__));
|
||||
|
||||
void fpi_data_exit(void);
|
||||
struct fp_print_data *fpi_print_data_new(struct fp_dev *dev, size_t length);
|
||||
gboolean fpi_print_data_compatible(uint16_t driver_id1, uint32_t devtype1,
|
||||
enum fp_print_data_type type1, uint16_t driver_id2, uint32_t devtype2,
|
||||
|
|
|
@ -183,6 +183,7 @@ void fp_img_free(struct fp_img *img);
|
|||
|
||||
/* Library */
|
||||
int fp_init(void);
|
||||
void fp_exit(void);
|
||||
|
||||
#endif
|
||||
|
||||
|
|
Loading…
Reference in a new issue