From a86cd51959cdb6e34ba0ddee4eed07880ac0fa2c Mon Sep 17 00:00:00 2001 From: Daniel Drake Date: Tue, 13 Nov 2007 14:32:31 +0000 Subject: [PATCH] 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. --- TODO | 2 - examples/enroll.c | 10 +++-- examples/img_capture.c | 8 ++-- examples/img_capture_continuous.c | 24 +++++------ examples/verify.c | 10 +++-- examples/verify_live.c | 10 +++-- libfprint/core.c | 66 ++++++++++++++++++++++++------- libfprint/data.c | 6 ++- libfprint/fp_internal.h | 1 + libfprint/fprint.h | 1 + 10 files changed, 94 insertions(+), 44 deletions(-) diff --git a/TODO b/TODO index eeaea7c..a137e92 100644 --- a/TODO +++ b/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" diff --git a/examples/enroll.c b/examples/enroll.c index a1062f8..97671a6 100644 --- a/examples/enroll.c +++ b/examples/enroll.c @@ -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; } diff --git a/examples/img_capture.c b/examples/img_capture.c index 794f1d1..ea494c8 100644 --- a/examples/img_capture.c +++ b/examples/img_capture.c @@ -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; } diff --git a/examples/img_capture_continuous.c b/examples/img_capture_continuous.c index 5079fe7..0f1644e 100644 --- a/examples/img_capture_continuous.c +++ b/examples/img_capture_continuous.c @@ -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; } diff --git a/examples/verify.c b/examples/verify.c index 42b07bb..ef66d5e 100644 --- a/examples/verify.c +++ b/examples/verify.c @@ -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; } diff --git a/examples/verify_live.c b/examples/verify_live.c index 5f3932b..0e1db6d 100644 --- a/examples/verify_live.c +++ b/examples/verify_live.c @@ -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; } diff --git a/libfprint/core.c b/libfprint/core.c index 1685b4b..effded9 100644 --- a/libfprint/core.c +++ b/libfprint/core.c @@ -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; +} + diff --git a/libfprint/data.c b/libfprint/data.c index 564a70d..97ed5d0 100644 --- a/libfprint/data.c +++ b/libfprint/data.c @@ -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) diff --git a/libfprint/fp_internal.h b/libfprint/fp_internal.h index 3ed42f2..435ec46 100644 --- a/libfprint/fp_internal.h +++ b/libfprint/fp_internal.h @@ -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, diff --git a/libfprint/fprint.h b/libfprint/fprint.h index 6e881da..399b5e1 100644 --- a/libfprint/fprint.h +++ b/libfprint/fprint.h @@ -183,6 +183,7 @@ void fp_img_free(struct fp_img *img); /* Library */ int fp_init(void); +void fp_exit(void); #endif