It's very unlikely that people have more than one fingerprint reader on their computers and being actively used.
The current design of fprint library loads all the drivers as built-ins. On systems with smaller memory (such as embedded systems), a few KBs are also important. This commit adds basic API for loading/unloading modules. Right now, only the drivers are treated as loadable modules. The implementation is just a wrapper around dlopen()/dlsym() API. The design derives from the linux kernel's implementation of loadable modules. Signed-off-by: Kunal Gangakhedkar <kunal.gangakhed...@gmail.com> --- libfprint/module.c | 148 ++++++++++++++++++++++++++++++++++++++++++++++++++++ libfprint/module.h | 57 ++++++++++++++++++++ 2 files changed, 205 insertions(+) create mode 100644 libfprint/module.c create mode 100644 libfprint/module.h diff --git a/libfprint/module.c b/libfprint/module.c new file mode 100644 index 0000000..05368af --- /dev/null +++ b/libfprint/module.c @@ -0,0 +1,148 @@ +/* + * Support for dynamically loading drivers + * Copyright (C) 2012 Kunal Gangakhedkar <kunal.gangakhed...@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <errno.h> +#include <string.h> +#include <dlfcn.h> + +#include <glib.h> +#include <config.h> +#include <fp_internal.h> + +#include "module.h" + +static GSList *modules = NULL; + +static int module_exists(const char *mod_path, GSList **entry); + +API_EXPORTED int load_module(const char *mod_path) +{ + int rc = 0; + initcall_t init_call = NULL; + exitcall_t exit_call = NULL; + struct fp_mod *mod = NULL; + void *handle = NULL; + + if (module_exists(mod_path, NULL)) { + fp_info("Module '%s' already loaded - skipping..\n", mod_path); + return rc; + } + + handle = dlopen(mod_path, RTLD_LAZY); + if (!handle) { + fp_err("failed to load module %s\n", dlerror()); + return errno; + } + + init_call = (initcall_t)dlsym(handle, "init_mod"); + if (!init_call) { + fp_err("failed to get init call pointer: %s\n", dlerror()); + rc = errno; + goto close_lib; + } + + exit_call = (exitcall_t)dlsym(handle, "cleanup_mod"); + + mod = g_malloc0(sizeof(*mod)); + mod->init = init_call; + mod->exit = exit_call; + mod->handle = handle; + strncpy(mod->path, mod_path, MODULE_PATH_LEN); + + /* + * TODO: + * For now, copy the file path into name. + * When we add support for MODULE_NAME(), we need to change this + * to copy the actual module name. + */ + strncpy(mod->name, mod_path, MODULE_NAME_LEN); + + rc = init_call(); + if (rc < 0) { + /* Init routine failed. Abort loading of module.. */ + fp_warn("module '%s' returned %d - aborting loading", mod->name, rc); + g_free(mod); + } else { + modules = g_slist_prepend(modules, (gpointer) mod); + } + goto out; + +close_lib: + dlclose(handle); +out: + return rc; +} + +API_EXPORTED int unload_module(const char *mod_path) +{ + GSList *entry = NULL; + struct fp_mod *mod = NULL; + int rc = 0; + + if (!module_exists(mod_path, &entry)) { + fp_err("Module '%s' not found. Perhaps not loaded?\n", mod_path); + return -ENOENT; + } + + mod = (struct fp_mod*)entry->data; + + modules = g_slist_delete_link(modules, entry); + + if (mod->exit) { + mod->exit(); + } + + rc = dlclose(mod->handle); + if (rc < 0) { + /* + * This is a potential memory leak. + * The loaded library is dangling here. + * Hopefully, sensible OS will clean it out when the main process + * terminates. + */ + fp_dbg("Failed to unload module '%s': %s\n", mod->name, dlerror()); + } + + if (entry) + entry = NULL; + + g_free(mod); + mod = NULL; + + return rc; +} + +static int module_exists(const char *mod_path, GSList **entry) +{ + GSList *elem = modules; + + if (g_slist_length(elem) == 0) + return 0; + + do { + struct fp_mod *mod = (struct fp_mod*)elem->data; + if (strncmp(mod->path, mod_path, MODULE_PATH_LEN) == 0) { + if (entry) + *entry = elem; + return 1; + } + } while ((elem = g_slist_next(elem))); + + return 0; +} diff --git a/libfprint/module.h b/libfprint/module.h new file mode 100644 index 0000000..f9cd74e --- /dev/null +++ b/libfprint/module.h @@ -0,0 +1,57 @@ +/* + * Support for dynamically loading drivers + * Copyright (C) 2012 Kunal Gangakhedkar <kunal.gangakhed...@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __FPRINT_MODULE_H__ +#define __FPRINT_MODULE_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <sys/param.h> +#include <config.h> + +#define MODULE_PATH_LEN MAXPATHLEN +#define MODULE_NAME_LEN MODULE_PATH_LEN + +typedef int (*initcall_t)(void); +typedef void (*exitcall_t)(void); + +struct fp_mod { + char name[MODULE_NAME_LEN]; + char path[MODULE_PATH_LEN]; + initcall_t init; + exitcall_t exit; + void *handle; +}; + +#define module_init(initfn) \ + API_EXPORTED int init_mod(void) __attribute__((alias(#initfn))); + +#define module_exit(exitfn) \ + API_EXPORTED int cleanup_mod(void) __attribute__((alias(#exitfn))); + +int load_module(const char *modpath); +int unload_module(const char *modpath); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __FPRINT_MODULE_H__ */ -- 1.7.9.5 _______________________________________________ fprint mailing list fprint@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/fprint