Commit a86cd519 authored by Daniel Drake's avatar Daniel Drake

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.
parent a76f55db
......@@ -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
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment