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:
Daniel Drake 2007-11-13 14:32:31 +00:00
parent a76f55db0d
commit a86cd51959
10 changed files with 94 additions and 44 deletions

2
TODO
View file

@ -4,8 +4,6 @@ identification
test suite against NFIQ compliance set test suite against NFIQ compliance set
make library optionally asynchronous and maybe thread-safe make library optionally asynchronous and maybe thread-safe
nbis cleanups 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 API function to determine if img device supports uncond. capture
race-free way of saying "save this print but don't overwrite" race-free way of saying "save this print but don't overwrite"

View file

@ -92,7 +92,7 @@ struct fp_print_data *enroll(struct fp_dev *dev) {
int main(void) int main(void)
{ {
int r; int r = 1;
struct fp_dscv_dev *ddev; struct fp_dscv_dev *ddev;
struct fp_dscv_dev **discovered_devs; struct fp_dscv_dev **discovered_devs;
struct fp_dev *dev; struct fp_dev *dev;
@ -113,20 +113,20 @@ int main(void)
discovered_devs = fp_discover_devs(); discovered_devs = fp_discover_devs();
if (!discovered_devs) { if (!discovered_devs) {
fprintf(stderr, "Could not discover devices\n"); fprintf(stderr, "Could not discover devices\n");
exit(1); goto out;
} }
ddev = discover_device(discovered_devs); ddev = discover_device(discovered_devs);
if (!ddev) { if (!ddev) {
fprintf(stderr, "No devices detected.\n"); fprintf(stderr, "No devices detected.\n");
exit(1); goto out;
} }
dev = fp_dev_open(ddev); dev = fp_dev_open(ddev);
fp_dscv_devs_free(discovered_devs); fp_dscv_devs_free(discovered_devs);
if (!dev) { if (!dev) {
fprintf(stderr, "Could not open device.\n"); fprintf(stderr, "Could not open device.\n");
exit(1); goto out;
} }
printf("Opened device. It's now time to enroll your finger.\n\n"); 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); fp_print_data_free(data);
out_close: out_close:
fp_dev_close(dev); fp_dev_close(dev);
out:
fp_exit();
return r; return r;
} }

View file

@ -54,20 +54,20 @@ int main(void)
discovered_devs = fp_discover_devs(); discovered_devs = fp_discover_devs();
if (!discovered_devs) { if (!discovered_devs) {
fprintf(stderr, "Could not discover devices\n"); fprintf(stderr, "Could not discover devices\n");
exit(1); goto out;
} }
ddev = discover_device(discovered_devs); ddev = discover_device(discovered_devs);
if (!ddev) { if (!ddev) {
fprintf(stderr, "No devices detected.\n"); fprintf(stderr, "No devices detected.\n");
exit(1); goto out;
} }
dev = fp_dev_open(ddev); dev = fp_dev_open(ddev);
fp_dscv_devs_free(discovered_devs); fp_dscv_devs_free(discovered_devs);
if (!dev) { if (!dev) {
fprintf(stderr, "Could not open device.\n"); fprintf(stderr, "Could not open device.\n");
exit(1); goto out;
} }
if (!fp_dev_supports_imaging(dev)) { if (!fp_dev_supports_imaging(dev)) {
@ -100,6 +100,8 @@ int main(void)
r = 0; r = 0;
out_close: out_close:
fp_dev_close(dev); fp_dev_close(dev);
out:
fp_exit();
return r; return r;
} }

View file

@ -153,25 +153,25 @@ int main(void)
discovered_devs = fp_discover_devs(); discovered_devs = fp_discover_devs();
if (!discovered_devs) { if (!discovered_devs) {
fprintf(stderr, "Could not discover devices\n"); fprintf(stderr, "Could not discover devices\n");
exit(1); goto out;
} }
ddev = discover_device(discovered_devs); ddev = discover_device(discovered_devs);
if (!ddev) { if (!ddev) {
fprintf(stderr, "No devices detected.\n"); fprintf(stderr, "No devices detected.\n");
exit(1); goto out;
} }
dev = fp_dev_open(ddev); dev = fp_dev_open(ddev);
fp_dscv_devs_free(discovered_devs); fp_dscv_devs_free(discovered_devs);
if (!dev) { if (!dev) {
fprintf(stderr, "Could not open device.\n"); fprintf(stderr, "Could not open device.\n");
exit(1); goto out;
} }
if (!fp_dev_supports_imaging(dev)) { if (!fp_dev_supports_imaging(dev)) {
fprintf(stderr, "this device does not have imaging capabilities.\n"); fprintf(stderr, "this device does not have imaging capabilities.\n");
goto out; goto out_close;
} }
img_width = fp_dev_get_img_width(dev); img_width = fp_dev_get_img_width(dev);
@ -179,24 +179,24 @@ int main(void)
if (img_width <= 0 || img_height <= 0) { if (img_width <= 0 || img_height <= 0) {
fprintf(stderr, "this device returns images with variable dimensions," fprintf(stderr, "this device returns images with variable dimensions,"
" this example does not support that.\n"); " this example does not support that.\n");
goto out; goto out_close;
} }
framebuffer = malloc(img_width * img_height * 2); framebuffer = malloc(img_width * img_height * 2);
if (!framebuffer) if (!framebuffer)
goto out; goto out_close;
/* make the window */ /* make the window */
display = XOpenDisplay(getenv("DISPLAY")); display = XOpenDisplay(getenv("DISPLAY"));
if(display == NULL) { if(display == NULL) {
fprintf(stderr,"Could not open display \"%s\"\n", fprintf(stderr,"Could not open display \"%s\"\n",
getenv("DISPLAY")); getenv("DISPLAY"));
goto out; goto out_close;
} }
QueryXv(); QueryXv();
if (adaptor < 0) if (adaptor < 0)
goto out; goto out_close;
window = XCreateSimpleWindow(display, DefaultRootWindow(display), 0, 0, window = XCreateSimpleWindow(display, DefaultRootWindow(display), 0, 0,
img_width, img_height, 0, img_width, img_height, 0,
@ -216,7 +216,7 @@ int main(void)
r = fp_dev_img_capture(dev, 1, &img); r = fp_dev_img_capture(dev, 1, &img);
if (r) { if (r) {
fprintf(stderr, "image capture failed, code %d\n", r); fprintf(stderr, "image capture failed, code %d\n", r);
goto out; goto out_close;
} }
if (standardize) if (standardize)
fp_img_standardize(img); fp_img_standardize(img);
@ -234,7 +234,7 @@ int main(void)
case XK_q: case XK_q:
case XK_Q: case XK_Q:
r = 0; r = 0;
goto out; goto out_close;
break; break;
case XK_s: case XK_s:
case XK_S: case XK_S:
@ -245,7 +245,7 @@ int main(void)
} }
r = 0; r = 0;
out: out_close:
if (framebuffer) if (framebuffer)
free(framebuffer); free(framebuffer);
fp_dev_close(dev); fp_dev_close(dev);
@ -253,6 +253,8 @@ out:
XUnmapWindow(display, window); XUnmapWindow(display, window);
if (display != NULL) if (display != NULL)
XFlush(display); XFlush(display);
out:
fp_exit();
return r; return r;
} }

View file

@ -76,7 +76,7 @@ int verify(struct fp_dev *dev, struct fp_print_data *data)
int main(void) int main(void)
{ {
int r; int r = 1;
struct fp_dscv_dev *ddev; struct fp_dscv_dev *ddev;
struct fp_dscv_dev **discovered_devs; struct fp_dscv_dev **discovered_devs;
struct fp_dev *dev; struct fp_dev *dev;
@ -91,20 +91,20 @@ int main(void)
discovered_devs = fp_discover_devs(); discovered_devs = fp_discover_devs();
if (!discovered_devs) { if (!discovered_devs) {
fprintf(stderr, "Could not discover devices\n"); fprintf(stderr, "Could not discover devices\n");
exit(1); goto out;
} }
ddev = discover_device(discovered_devs); ddev = discover_device(discovered_devs);
if (!ddev) { if (!ddev) {
fprintf(stderr, "No devices detected.\n"); fprintf(stderr, "No devices detected.\n");
exit(1); goto out;
} }
dev = fp_dev_open(ddev); dev = fp_dev_open(ddev);
fp_dscv_devs_free(discovered_devs); fp_dscv_devs_free(discovered_devs);
if (!dev) { if (!dev) {
fprintf(stderr, "Could not open device.\n"); fprintf(stderr, "Could not open device.\n");
exit(1); goto out;
} }
printf("Opened device. Loading previously enrolled right index finger " printf("Opened device. Loading previously enrolled right index finger "
@ -132,6 +132,8 @@ int main(void)
fp_print_data_free(data); fp_print_data_free(data);
out_close: out_close:
fp_dev_close(dev); fp_dev_close(dev);
out:
fp_exit();
return r; return r;
} }

View file

@ -126,7 +126,7 @@ int verify(struct fp_dev *dev, struct fp_print_data *data)
int main(void) int main(void)
{ {
int r; int r = 1;
struct fp_dscv_dev *ddev; struct fp_dscv_dev *ddev;
struct fp_dscv_dev **discovered_devs; struct fp_dscv_dev **discovered_devs;
struct fp_dev *dev; struct fp_dev *dev;
@ -141,20 +141,20 @@ int main(void)
discovered_devs = fp_discover_devs(); discovered_devs = fp_discover_devs();
if (!discovered_devs) { if (!discovered_devs) {
fprintf(stderr, "Could not discover devices\n"); fprintf(stderr, "Could not discover devices\n");
exit(1); goto out;
} }
ddev = discover_device(discovered_devs); ddev = discover_device(discovered_devs);
if (!ddev) { if (!ddev) {
fprintf(stderr, "No devices detected.\n"); fprintf(stderr, "No devices detected.\n");
exit(1); goto out;
} }
dev = fp_dev_open(ddev); dev = fp_dev_open(ddev);
fp_dscv_devs_free(discovered_devs); fp_dscv_devs_free(discovered_devs);
if (!dev) { if (!dev) {
fprintf(stderr, "Could not open device.\n"); fprintf(stderr, "Could not open device.\n");
exit(1); goto out;
} }
printf("Opened device. It's now time to enroll your finger.\n\n"); 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); fp_print_data_free(data);
out_close: out_close:
fp_dev_close(dev); fp_dev_close(dev);
out:
fp_exit();
return r; return r;
} }

View file

@ -276,7 +276,8 @@
* circumstances, you don't have to worry about driver IDs at all. * 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, void fpi_log(enum fpi_log_level level, const char *component,
const char *function, const char *format, ...) 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"); fp_err("not registering driver %s: driver ID is 0");
return; 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); 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, static struct fp_driver *find_supporting_driver(struct usb_device *udev,
const struct usb_id **usb_id) const struct usb_id **usb_id)
{ {
GList *elem = registered_drivers; GSList *elem = registered_drivers;
do { do {
struct fp_driver *drv = elem->data; struct fp_driver *drv = elem->data;
@ -367,7 +368,7 @@ static struct fp_driver *find_supporting_driver(struct usb_device *udev,
*usb_id = id; *usb_id = id;
return drv; return drv;
} }
} while (elem = g_list_next(elem)); } while (elem = g_slist_next(elem));
return NULL; 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) API_EXPORTED struct fp_dscv_dev **fp_discover_devs(void)
{ {
GList *tmplist = NULL; GSList *tmplist = NULL;
struct fp_dscv_dev **list; struct fp_dscv_dev **list;
struct usb_device *udev; struct usb_device *udev;
struct usb_bus *bus; struct usb_bus *bus;
@ -418,7 +419,7 @@ API_EXPORTED struct fp_dscv_dev **fp_discover_devs(void)
usb_find_devices(); usb_find_devices();
/* Check each device against each driver, temporarily storing successfully /* 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 * Quite inefficient but excusable as we'll only be dealing with small
* sets of drivers against small sets of USB devices */ * 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); struct fp_dscv_dev *ddev = discover_dev(udev);
if (!ddev) if (!ddev)
continue; continue;
tmplist = g_list_prepend(tmplist, (gpointer) ddev); tmplist = g_slist_prepend(tmplist, (gpointer) ddev);
dscv_count++; dscv_count++;
} }
/* Convert our temporary GList into a standard NULL-terminated pointer /* Convert our temporary GSList into a standard NULL-terminated pointer
* array. */ * array. */
list = g_malloc(sizeof(*list) * (dscv_count + 1)); list = g_malloc(sizeof(*list) * (dscv_count + 1));
if (dscv_count > 0) { if (dscv_count > 0) {
GList *elem = tmplist; GSList *elem = tmplist;
int i = 0; int i = 0;
do { do {
list[i++] = elem->data; list[i++] = elem->data;
} while (elem = g_list_next(elem)); } while (elem = g_slist_next(elem));
} }
list[dscv_count] = NULL; /* NULL-terminate */ list[dscv_count] = NULL; /* NULL-terminate */
g_list_free(tmplist); g_slist_free(tmplist);
return list; return list;
} }
@ -601,9 +602,19 @@ API_EXPORTED struct fp_dev *fp_dev_open(struct fp_dscv_dev *ddev)
} }
fp_dbg(""); fp_dbg("");
opened_devices = g_slist_prepend(opened_devices, (gpointer) dev);
return 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 /** \ingroup dev
* Close a device. You must call this function when you are finished using * Close a device. You must call this function when you are finished using
* a fingerprint device. * 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) API_EXPORTED void fp_dev_close(struct fp_dev *dev)
{ {
fp_dbg(""); fp_dbg("");
if (dev->drv->exit)
dev->drv->exit(dev); if (g_slist_index(opened_devices, (gconstpointer) dev) == -1)
usb_close(dev->udev); fp_err("device %p not in opened list!", dev);
g_free(dev); opened_devices = g_slist_remove(opened_devices, (gconstpointer) dev);
do_close(dev);
} }
/** \ingroup dev /** \ingroup dev
@ -986,3 +998,27 @@ API_EXPORTED int fp_init(void)
return 0; 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;
}

View file

@ -45,7 +45,6 @@
* in any fashion that suits you. * in any fashion that suits you.
*/ */
/* FIXME: should free this during library shutdown */
static char *base_store = NULL; static char *base_store = NULL;
static void storage_setup(void) static void storage_setup(void)
@ -63,6 +62,11 @@ static void storage_setup(void)
/* FIXME handle failure */ /* FIXME handle failure */
} }
void fpi_data_exit(void)
{
g_free(base_store);
}
#define FP_FINGER_IS_VALID(finger) \ #define FP_FINGER_IS_VALID(finger) \
((finger) >= LEFT_THUMB && (finger) <= RIGHT_LITTLE) ((finger) >= LEFT_THUMB && (finger) <= RIGHT_LITTLE)

View file

@ -182,6 +182,7 @@ struct fpi_print_data_fp1 {
unsigned char data[0]; unsigned char data[0];
} __attribute__((__packed__)); } __attribute__((__packed__));
void fpi_data_exit(void);
struct fp_print_data *fpi_print_data_new(struct fp_dev *dev, size_t length); 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, 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, enum fp_print_data_type type1, uint16_t driver_id2, uint32_t devtype2,

View file

@ -183,6 +183,7 @@ void fp_img_free(struct fp_img *img);
/* Library */ /* Library */
int fp_init(void); int fp_init(void);
void fp_exit(void);
#endif #endif