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

Reply via email to