From 29be0672975732ea7785b418c5af108f869c6c62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Tue, 17 Dec 2019 00:48:49 +0100 Subject: [PATCH 01/10] TOD: Add TOuch Drivers loader --- libfprint/fp-context.c | 12 +++ libfprint/meson.build | 4 + libfprint/tod/libfprint-tod.ver | 6 ++ libfprint/tod/meson.build | 89 ++++++++++++++++++ libfprint/tod/tod-shared-loader.c | 148 ++++++++++++++++++++++++++++++ libfprint/tod/tod-shared-loader.h | 28 ++++++ meson.build | 2 + meson_options.txt | 5 + 8 files changed, 294 insertions(+) create mode 100644 libfprint/tod/libfprint-tod.ver create mode 100644 libfprint/tod/meson.build create mode 100644 libfprint/tod/tod-shared-loader.c create mode 100644 libfprint/tod/tod-shared-loader.h diff --git a/libfprint/fp-context.c b/libfprint/fp-context.c index 0e7c17f7..5dc37000 100644 --- a/libfprint/fp-context.c +++ b/libfprint/fp-context.c @@ -24,6 +24,11 @@ #include "fpi-device.h" #include +#include +#ifdef HAVE_LIBFPRINT_TOD +#include "tod/tod-shared-loader.h" +#endif + /** * SECTION: fp-context * @title: FpContext @@ -215,6 +220,8 @@ fp_context_finalize (GObject *object) g_object_run_dispose (G_OBJECT (priv->usb_ctx)); g_clear_object (&priv->usb_ctx); + fpi_tod_shared_drivers_unregister (); + G_OBJECT_CLASS (fp_context_parent_class)->finalize (object); } @@ -266,11 +273,16 @@ static void fp_context_init (FpContext *self) { g_autoptr(GError) error = NULL; + g_autoptr(GArray) shared_drivers = NULL; FpContextPrivate *priv = fp_context_get_instance_private (self); guint i; priv->drivers = fpi_get_driver_types (); + fpi_tod_shared_drivers_register (); + shared_drivers = fpi_tod_shared_drivers_get (); + g_array_prepend_vals (priv->drivers, shared_drivers->data, shared_drivers->len); + if (get_drivers_whitelist_env ()) { for (i = 0; i < priv->drivers->len;) diff --git a/libfprint/meson.build b/libfprint/meson.build index 50df8a0c..8cfef8c6 100644 --- a/libfprint/meson.build +++ b/libfprint/meson.build @@ -234,6 +234,10 @@ libfprint_private = static_library('fprint-private', link_with: libnbis, install: false) +if get_option('tod') + subdir('tod') +endif + libfprint_drivers = static_library('fprint-drivers', sources: drivers_sources, c_args: drivers_cflags, diff --git a/libfprint/tod/libfprint-tod.ver b/libfprint/tod/libfprint-tod.ver new file mode 100644 index 00000000..d18569f1 --- /dev/null +++ b/libfprint/tod/libfprint-tod.ver @@ -0,0 +1,6 @@ +LIBFPRINT_TOD_1.0.0 { +global: + fpi_*; +local: + *; +}; diff --git a/libfprint/tod/meson.build b/libfprint/tod/meson.build new file mode 100644 index 00000000..b864b598 --- /dev/null +++ b/libfprint/tod/meson.build @@ -0,0 +1,89 @@ +tod_soversion = 1 +tod_version = '@0@.0'.format(tod_soversion) +tod_versioned_path = '-'.join(tod_version.split('.')) +tod_subpath = meson.project_name() / 'tod-@0@'.format(tod_versioned_path) +tod_modules_prefix = get_option('libdir') / tod_subpath + +tod_conf = configuration_data() +tod_conf.set_quoted('TOD_DRIVERS_DIR', + get_option('prefix') / get_option('libdir') / tod_subpath) +configure_file(output: 'tod-config.h', configuration: tod_conf) + +gmodule_dep = dependency('gmodule-2.0', version: '>=' + glib_min_version) +deps += gmodule_dep + +mapfile = files('libfprint-tod.ver') + +libfprint_tod_private = static_library('fprint-tod-private', + sources: [ + 'tod-shared-loader.c', + ], + include_directories: include_directories('..'), + link_with: libfprint_private, + dependencies: deps, + install: false, +) + +tod_sources = [] +foreach source: libfprint_private_sources + tod_sources += '..' / source +endforeach + +libfprint_tod = library('fprint-tod', + sources: [ + tod_sources, + ], + soversion: (soversion * 100) + tod_soversion, + include_directories: include_directories('..'), + version: '@0@.'.format(soversion) + tod_version, + link_args: [ + '-Wl,--version-script,@0@/@1@'.format(meson.source_root(), mapfile[0]), + '-Wl,--unresolved-symbols=ignore-in-object-files' + ], + link_depends: mapfile, + link_with: [libfprint_private], + dependencies: deps, + install: true) + +deps += declare_dependency( + link_with: [ + libfprint_tod, + libfprint_tod_private, + ] +) + +pkgconfig = import('pkgconfig') +pkgconfig.generate(libfprint_tod, + name: 'libfprint-tod', + filebase: 'libfprint@0@-tod-@1@'.format(soversion, tod_versioned_path), + description: 'Private Libfprint Touch Drivers API', + version: meson.project_version() + '.@0@'.format(tod_version), + subdirs: tod_subpath, + requires_private: [ + meson.project_name() + '@0@'.format(soversion), + ], + variables: [ + 'tod_driversdir=${libdir}/@0@'.format(tod_subpath) + ] +) + +tod_headers = [] +extra_libfprint_headers = [ + 'drivers_api.h', +] + +foreach header: libfprint_private_headers + extra_libfprint_headers + tod_headers += '..' / header +endforeach + +custom_target('tod_fpi_enums_headers', + depends: fpi_enums, + input: fpi_enums_h, + output: 'fpi-enums.h', + command: ['cp', '@INPUT@', '-v', '@OUTPUT@'], + install: true, + install_dir: get_option('includedir') / tod_subpath) + +install_headers(tod_headers, + subdir: tod_subpath +) diff --git a/libfprint/tod/tod-shared-loader.c b/libfprint/tod/tod-shared-loader.c new file mode 100644 index 00000000..842e72dc --- /dev/null +++ b/libfprint/tod/tod-shared-loader.c @@ -0,0 +1,148 @@ +/* + * Shared library loader for libfprint + * Copyright (C) 2019 Marco Trevisan + * + * 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 + */ + +#define FP_COMPONENT "tod" + +#include + +#include "tod-shared-loader.h" +#include "fpi-device.h" +#include "fpi-log.h" +#include "tod-config.h" + +#define FPI_TOD_ENTRY_GTYPE_GETTER "fpi_tod_shared_driver_get_type" + +static GArray *shared_drivers = NULL; +static GList *shared_modules = NULL; + +typedef GModule FpiTodModule; +typedef GType (*FpiTodShardDriverTypeGetter) (void); + +G_DEFINE_AUTOPTR_CLEANUP_FUNC (FpiTodModule, g_module_close); + +static const char * +get_tod_drivers_dir (void) +{ + const char *tod_env_path = g_getenv ("FP_TOD_DRIVERS_DIR"); + + if (!tod_env_path || *tod_env_path == '\0') + return TOD_DRIVERS_DIR; + + return tod_env_path; +} + +void +fpi_tod_shared_drivers_register (void) +{ + const char *dirname; + const char *basename; + + g_autoptr(GError) error = NULL; + g_autoptr(GDir) dir = NULL; + gpointer symbol; + + g_assert_null (shared_drivers); + + dirname = get_tod_drivers_dir (); + dir = g_dir_open (dirname, 0, &error); + + shared_drivers = g_array_new (TRUE, FALSE, sizeof (GType)); + + if (error) + { + fp_dbg ("Impossible to load the shared drivers dir %s", error->message); + return; + } + + while ((basename = g_dir_read_name (dir)) != NULL) + { + g_autoptr(FpiTodModule) module = NULL; + g_autoptr(GTypeClass) type_class = NULL; + g_autofree char *module_path = NULL; + FpiTodShardDriverTypeGetter type_getter; + FpDeviceClass *cls; + GType driver; + + if (!g_str_has_suffix (basename, ".so")) + continue; + + module_path = g_build_filename (dirname, basename, NULL); + + if (!g_file_test (module_path, G_FILE_TEST_IS_REGULAR)) + continue; + + fp_dbg ("Opening driver %s", module_path); + + module = g_module_open (module_path, G_MODULE_BIND_LAZY | G_MODULE_BIND_LOCAL); + + if (!module) + { + fp_err ("Impossible to load module %s: %s", module_path, + g_module_error ()); + continue; + } + + if (!g_module_symbol (module, FPI_TOD_ENTRY_GTYPE_GETTER, &symbol)) + { + fp_err ("Library %s doesn't expose the required entry point symbol", + module_path); + continue; + } + + type_getter = symbol; + driver = type_getter (); + fp_dbg ("Found TOD entry point symbol %p, GType is %lu", symbol, driver); + + if (!G_TYPE_IS_OBJECT (driver) || !g_type_is_a (driver, FP_TYPE_DEVICE)) + { + fp_err ("Library %s returned GType (%lu) doesn't represent a device", + module_path, driver); + continue; + } + + type_class = g_type_class_ref (driver); + g_assert_true (g_type_check_class_is_a (type_class, FP_TYPE_DEVICE)); + + cls = FP_DEVICE_CLASS (type_class); + + fp_dbg ("Loading driver %s (%s)", cls->id, cls->full_name); + g_array_append_val (shared_drivers, driver); + + shared_modules = g_list_prepend (shared_modules, + g_steal_pointer (&module)); + } +} + +void +fpi_tod_shared_drivers_unregister (void) +{ + g_clear_pointer (&shared_drivers, g_array_unref); + + if (g_strcmp0 (g_getenv ("FP_TOD_KEEP_MODULES_OPEN"), "TRUE") != 0) + { + g_list_free_full (shared_modules, (GDestroyNotify) g_module_close); + shared_modules = NULL; + } +} + +GArray * +fpi_tod_shared_drivers_get (void) +{ + return g_array_ref (shared_drivers); +} diff --git a/libfprint/tod/tod-shared-loader.h b/libfprint/tod/tod-shared-loader.h new file mode 100644 index 00000000..8ed2e811 --- /dev/null +++ b/libfprint/tod/tod-shared-loader.h @@ -0,0 +1,28 @@ +/* + * Shared library loader for libfprint + * Copyright (C) 2019 Marco Trevisan + * + * 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 + */ + +#pragma once + +#include + + +void fpi_tod_shared_drivers_register (void); +void fpi_tod_shared_drivers_unregister (void); + +GArray *fpi_tod_shared_drivers_get (void); diff --git a/meson.build b/meson.build index c42cf2d6..2612ed52 100644 --- a/meson.build +++ b/meson.build @@ -187,6 +187,8 @@ if get_option('gtk-examples') endif endif +libfprint_conf.set10('HAVE_LIBFPRINT_TOD', get_option('tod')) + configure_file(output: 'config.h', configuration: libfprint_conf) subdir('libfprint') diff --git a/meson_options.txt b/meson_options.txt index 746efdc7..d059ae59 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -22,3 +22,8 @@ option('doc', description: 'Whether to build the API documentation', type: 'boolean', value: true) + +option('tod', + description: 'Whether to build the TOD library', + type: 'boolean', + value: true) From d998fb436ef11420adbe7ff3e821e0c50c07f92c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Tue, 17 Dec 2019 03:51:39 +0100 Subject: [PATCH 02/10] tests: Add TOD unit tests re-using the fake-driver --- tests/meson.build | 42 ++++++ tests/test-device-fake-tod.c | 28 ++++ tests/test-device-fake-tod.h | 25 ++++ tests/test-fp-context-tod.c | 101 +++++++++++++ tests/test-fp-device-tod.c | 270 +++++++++++++++++++++++++++++++++++ 5 files changed, 466 insertions(+) create mode 100644 tests/test-device-fake-tod.c create mode 100644 tests/test-device-fake-tod.h create mode 100644 tests/test-fp-context-tod.c create mode 100644 tests/test-fp-device-tod.c diff --git a/tests/meson.build b/tests/meson.build index b4022a4e..6a5eaffb 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -109,3 +109,45 @@ if valgrind.found() valgrind.path(), glib_suppressions, python_suppressions) ]) endif + +if get_option('tod') + tod_envs = envs + tod_envs.set('FP_TOD_DRIVERS_DIR', meson.current_build_dir()) + tod_envs.set('FP_TOD_KEEP_MODULES_OPEN', 'TRUE') + tod_envs.set('FP_VIRTUAL_FAKE_DEVICE', 'yes') + tod_envs.append('FP_DRIVERS_WHITELIST', 'fake_test_dev') + + fake_driver = shared_module('device-fake-tod-driver', + sources: [ + 'test-device-fake-tod.c', + ], + link_with: [ + test_utils, + libfprint_tod, + ], + include_directories: include_directories('../libfprint'), + dependencies: deps, + install: false + ) + + tod_unit_tests = [ + 'fp-context-tod', + 'fp-device-tod', + ] + + foreach test_name: tod_unit_tests + basename = 'test-' + test_name + test_exe = executable(basename, + sources: basename + '.c', + dependencies: libfprint_private_dep, + c_args: common_cflags, + link_with: test_utils, + ) + test(test_name, + find_program('test-runner.sh'), + suite: ['unit-tests', 'tod'], + args: [test_exe], + env: tod_envs, + ) + endforeach +endif diff --git a/tests/test-device-fake-tod.c b/tests/test-device-fake-tod.c new file mode 100644 index 00000000..aea73870 --- /dev/null +++ b/tests/test-device-fake-tod.c @@ -0,0 +1,28 @@ +/* + * Virtual driver for device debugging + * + * Copyright (C) 2019 Marco Trevisan + * + * 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 "test-device-fake-tod.h" +#include "test-device-fake.h" + +GType +fpi_tod_shared_driver_get_type (void) +{ + return fpi_device_fake_get_type (); +} diff --git a/tests/test-device-fake-tod.h b/tests/test-device-fake-tod.h new file mode 100644 index 00000000..36602125 --- /dev/null +++ b/tests/test-device-fake-tod.h @@ -0,0 +1,25 @@ +/* + * Virtual driver for device debugging + * + * Copyright (C) 2019 Marco Trevisan + * + * 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 + */ + +#pragma once + +#include + +GType fpi_tod_shared_driver_get_type (void); diff --git a/tests/test-fp-context-tod.c b/tests/test-fp-context-tod.c new file mode 100644 index 00000000..abafc62d --- /dev/null +++ b/tests/test-fp-context-tod.c @@ -0,0 +1,101 @@ +/* + * FpContext Unit tests + * Copyright (C) 2019 Marco Trevisan + * + * 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 + +static void +test_context_new (void) +{ + g_autoptr(FpContext) context = fp_context_new (); + g_assert_true (FP_CONTEXT (context)); +} + +static void +test_context_has_no_devices (void) +{ + g_autoptr(FpContext) context = NULL; + GPtrArray *devices; + const char *old_drivers_dir = g_getenv ("FP_TOD_DRIVERS_DIR"); + + g_setenv ("FP_TOD_DRIVERS_DIR", "__HOPEFULLY_AN_INVALID_PATH", TRUE); + context = fp_context_new (); + devices = fp_context_get_devices (context); + g_setenv ("FP_TOD_DRIVERS_DIR", old_drivers_dir, TRUE); + + g_assert_nonnull (devices); + g_assert_cmpuint (devices->len, ==, 0); +} + +static void +test_context_has_fake_device (void) +{ + g_autoptr(FpContext) context = NULL; + FpDevice *fake_device = NULL; + GPtrArray *devices; + unsigned int i; + + context = fp_context_new (); + devices = fp_context_get_devices (context); + + g_assert_nonnull (devices); + g_assert_cmpuint (devices->len, ==, 1); + + for (i = 0; i < devices->len; ++i) + { + FpDevice *device = devices->pdata[i]; + + if (g_strcmp0 (fp_device_get_driver (device), "fake_test_dev") == 0) + { + fake_device = device; + break; + } + } + + g_assert_true (FP_IS_DEVICE (fake_device)); +} + +static void +test_context_enumerates_new_devices (void) +{ + g_autoptr(FpContext) context = NULL; + GPtrArray *devices; + + context = fp_context_new (); + + fp_context_enumerate (context); + devices = fp_context_get_devices (context); + + g_assert_nonnull (devices); + g_assert_cmpuint (devices->len, ==, 1); +} + +int +main (int argc, char *argv[]) +{ + g_test_init (&argc, &argv, NULL); + + g_assert_nonnull (g_getenv ("FP_TOD_DRIVERS_DIR")); + + g_test_add_func ("/context/new", test_context_new); + g_test_add_func ("/context/no-devices", test_context_has_no_devices); + g_test_add_func ("/context/has-virtual-device", test_context_has_fake_device); + g_test_add_func ("/context/enumerates-new-devices", test_context_enumerates_new_devices); + + return g_test_run (); +} diff --git a/tests/test-fp-device-tod.c b/tests/test-fp-device-tod.c new file mode 100644 index 00000000..d1a132b7 --- /dev/null +++ b/tests/test-fp-device-tod.c @@ -0,0 +1,270 @@ +/* + * FpDevice Unit tests + * Copyright (C) 2019 Marco Trevisan + * + * 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 + +#include "test-utils.h" + +static FptContext * +fpt_context_new_with_fake_dev (void) +{ + FptContext *tctx; + GPtrArray *devices; + unsigned int i; + + tctx = fpt_context_new (); + devices = fp_context_get_devices (tctx->fp_context); + + g_assert_nonnull (devices); + g_assert_cmpuint (devices->len, ==, 1); + + for (i = 0; i < devices->len; ++i) + { + FpDevice *device = devices->pdata[i]; + + if (g_strcmp0 (fp_device_get_driver (device), "fake_test_dev") == 0) + { + tctx->device = device; + break; + } + } + + g_assert_true (FP_IS_DEVICE (tctx->device)); + g_object_add_weak_pointer (G_OBJECT (tctx->device), (gpointer) & tctx->device); + + return tctx; +} + +static void +on_device_opened (FpDevice *dev, GAsyncResult *res, FptContext *tctx) +{ + g_autoptr(GError) error = NULL; + + g_assert_true (fp_device_open_finish (dev, res, &error)); + g_assert_no_error (error); + g_assert_true (fp_device_is_open (tctx->device)); + + tctx->user_data = GUINT_TO_POINTER (TRUE); +} + +static void +test_device_open_async (void) +{ + g_autoptr(FptContext) tctx = fpt_context_new_with_fake_dev (); + + fp_device_open (tctx->device, NULL, (GAsyncReadyCallback) on_device_opened, tctx); + + while (!GPOINTER_TO_UINT (tctx->user_data)) + g_main_context_iteration (NULL, TRUE); +} + +static void +on_device_closed (FpDevice *dev, GAsyncResult *res, FptContext *tctx) +{ + g_autoptr(GError) error = NULL; + + g_assert_true (fp_device_close_finish (dev, res, &error)); + g_assert_no_error (error); + g_assert_false (fp_device_is_open (tctx->device)); + + tctx->user_data = GUINT_TO_POINTER (TRUE); +} + +static void +test_device_close_async (void) +{ + g_autoptr(FptContext) tctx = fpt_context_new_with_fake_dev (); + + fp_device_open (tctx->device, NULL, (GAsyncReadyCallback) on_device_opened, tctx); + while (!tctx->user_data) + g_main_context_iteration (NULL, TRUE); + + tctx->user_data = GUINT_TO_POINTER (FALSE); + fp_device_close (tctx->device, NULL, (GAsyncReadyCallback) on_device_closed, tctx); + + while (!GPOINTER_TO_UINT (tctx->user_data)) + g_main_context_iteration (NULL, TRUE); +} + +static void +test_device_open_sync (void) +{ + g_autoptr(GError) error = NULL; + g_autoptr(FptContext) tctx = fpt_context_new_with_fake_dev (); + + fp_device_open_sync (tctx->device, NULL, &error); + g_assert_no_error (error); + g_assert_true (fp_device_is_open (tctx->device)); + + fp_device_open_sync (tctx->device, NULL, &error); + g_assert_error (error, FP_DEVICE_ERROR, FP_DEVICE_ERROR_ALREADY_OPEN); +} + +static void +on_open_notify (FpDevice *rdev, GParamSpec *spec, FptContext *tctx) +{ + g_assert_cmpstr (spec->name, ==, "open"); + tctx->user_data = GUINT_TO_POINTER (TRUE); +} + +static void +test_device_open_sync_notify (void) +{ + g_autoptr(GError) error = NULL; + g_autoptr(FptContext) tctx = fpt_context_new_with_fake_dev (); + + g_signal_connect (tctx->device, "notify::open", G_CALLBACK (on_open_notify), tctx); + fp_device_open_sync (tctx->device, NULL, &error); + g_assert_no_error (error); + g_assert_true (GPOINTER_TO_INT (tctx->user_data)); +} + +static void +test_device_close_sync (void) +{ + g_autoptr(GError) error = NULL; + g_autoptr(FptContext) tctx = fpt_context_new_with_fake_dev (); + + fp_device_open_sync (tctx->device, NULL, NULL); + fp_device_close_sync (tctx->device, NULL, &error); + g_assert_no_error (error); + g_assert_false (fp_device_is_open (tctx->device)); + + fp_device_close_sync (tctx->device, NULL, &error); + g_assert_error (error, FP_DEVICE_ERROR, FP_DEVICE_ERROR_NOT_OPEN); +} + +static void +on_close_notify (FpDevice *rdev, GParamSpec *spec, FptContext *tctx) +{ + g_assert_cmpstr (spec->name, ==, "open"); + tctx->user_data = GUINT_TO_POINTER (TRUE); +} + +static void +test_device_close_sync_notify (void) +{ + g_autoptr(GError) error = NULL; + g_autoptr(FptContext) tctx = fpt_context_new_with_fake_dev (); + + fp_device_open_sync (tctx->device, NULL, NULL); + + g_signal_connect (tctx->device, "notify::open", G_CALLBACK (on_close_notify), tctx); + fp_device_close_sync (tctx->device, NULL, &error); + g_assert_no_error (error); + g_assert_true (GPOINTER_TO_INT (tctx->user_data)); +} + +static void +test_device_get_driver (void) +{ + g_autoptr(FptContext) tctx = fpt_context_new_with_fake_dev (); + + fp_device_open_sync (tctx->device, NULL, NULL); + g_assert_cmpstr (fp_device_get_driver (tctx->device), ==, "fake_test_dev"); +} + +static void +test_device_get_device_id (void) +{ + g_autoptr(FptContext) tctx = fpt_context_new_with_fake_dev (); + + fp_device_open_sync (tctx->device, NULL, NULL); + g_assert_cmpstr (fp_device_get_device_id (tctx->device), ==, "fake_test_dev"); +} + +static void +test_device_get_name (void) +{ + g_autoptr(FptContext) tctx = fpt_context_new_with_fake_dev (); + + fp_device_open_sync (tctx->device, NULL, NULL); + g_assert_cmpstr (fp_device_get_name (tctx->device), ==, + "Virtual device for debugging"); +} + +static void +test_device_get_scan_type (void) +{ + g_autoptr(FptContext) tctx = fpt_context_new_with_fake_dev (); + + fp_device_open_sync (tctx->device, NULL, NULL); + g_assert_cmpint (fp_device_get_scan_type (tctx->device), ==, FP_SCAN_TYPE_PRESS); +} + +static void +test_device_get_nr_enroll_stages (void) +{ + g_autoptr(FptContext) tctx = fpt_context_new_with_fake_dev (); + + fp_device_open_sync (tctx->device, NULL, NULL); + g_assert_cmpuint (fp_device_get_nr_enroll_stages (tctx->device), ==, 5); +} + +static void +test_device_supports_identify (void) +{ + g_autoptr(FptContext) tctx = fpt_context_new_with_fake_dev (); + + fp_device_open_sync (tctx->device, NULL, NULL); + g_assert_true (fp_device_supports_identify (tctx->device)); +} + +static void +test_device_supports_capture (void) +{ + g_autoptr(FptContext) tctx = fpt_context_new_with_fake_dev (); + + fp_device_open_sync (tctx->device, NULL, NULL); + g_assert_true (fp_device_supports_capture (tctx->device)); +} + +static void +test_device_has_storage (void) +{ + g_autoptr(FptContext) tctx = fpt_context_new_with_fake_dev (); + + fp_device_open_sync (tctx->device, NULL, NULL); + g_assert_true (fp_device_has_storage (tctx->device)); +} + +int +main (int argc, char *argv[]) +{ + g_test_init (&argc, &argv, NULL); + + g_assert_nonnull (g_getenv ("FP_TOD_DRIVERS_DIR")); + + g_test_add_func ("/device/async/open", test_device_open_async); + g_test_add_func ("/device/async/close", test_device_close_async); + g_test_add_func ("/device/sync/open", test_device_open_sync); + g_test_add_func ("/device/sync/open/notify", test_device_open_sync_notify); + g_test_add_func ("/device/sync/close", test_device_close_sync); + g_test_add_func ("/device/sync/close/notify", test_device_close_sync_notify); + g_test_add_func ("/device/sync/get_driver", test_device_get_driver); + g_test_add_func ("/device/sync/get_device_id", test_device_get_device_id); + g_test_add_func ("/device/sync/get_name", test_device_get_name); + g_test_add_func ("/device/sync/get_scan_type", test_device_get_scan_type); + g_test_add_func ("/device/sync/get_nr_enroll_stages", test_device_get_nr_enroll_stages); + g_test_add_func ("/device/sync/supports_identify", test_device_supports_identify); + g_test_add_func ("/device/sync/supports_capture", test_device_supports_capture); + g_test_add_func ("/device/sync/has_storage", test_device_has_storage); + + return g_test_run (); +} From 4e972724a88e5713fba826400934653209e9a70c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Tue, 17 Dec 2019 04:33:20 +0100 Subject: [PATCH 03/10] fp-image: Remove config.h inclusion in fpi-header --- libfprint/fp-image.c | 1 + libfprint/fpi-image.c | 9 +++++++-- libfprint/fpi-image.h | 3 --- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/libfprint/fp-image.c b/libfprint/fp-image.c index ac70d68d..6b63a438 100644 --- a/libfprint/fp-image.c +++ b/libfprint/fp-image.c @@ -23,6 +23,7 @@ #include "fpi-image.h" #include "fpi-log.h" +#include #include /** diff --git a/libfprint/fpi-image.c b/libfprint/fpi-image.c index 83440376..1fb88656 100644 --- a/libfprint/fpi-image.c +++ b/libfprint/fpi-image.c @@ -24,6 +24,7 @@ #include "fpi-log.h" #include +#include #if HAVE_PIXMAN #include @@ -108,12 +109,12 @@ fpi_mean_sq_diff_norm (const guint8 *buf1, return res / size; } -#if HAVE_PIXMAN FpImage * fpi_image_resize (FpImage *orig_img, guint w_factor, guint h_factor) { +#if HAVE_PIXMAN int new_width = orig_img->width * w_factor; int new_height = orig_img->height * h_factor; pixman_image_t *orig, *resized; @@ -146,5 +147,9 @@ fpi_image_resize (FpImage *orig_img, pixman_image_unref (resized); return newimg; -} +#else + fp_err ("Libfprint compiled without pixman support, impossible to resize"); + + return NULL; #endif +} diff --git a/libfprint/fpi-image.h b/libfprint/fpi-image.h index dd6dbf88..2855c78f 100644 --- a/libfprint/fpi-image.h +++ b/libfprint/fpi-image.h @@ -20,7 +20,6 @@ #pragma once -#include #include "fp-image.h" /** @@ -76,8 +75,6 @@ gint fpi_mean_sq_diff_norm (const guint8 *buf1, const guint8 *buf2, gint size); -#if HAVE_PIXMAN FpImage *fpi_image_resize (FpImage *orig, guint w_factor, guint h_factor); -#endif From d078c7817130a503f6577e318f96df6521586877 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Tue, 17 Dec 2019 20:07:02 +0100 Subject: [PATCH 04/10] fpi: Add paddings to the private structs --- libfprint/fpi-assembling.h | 1 + libfprint/fpi-device.h | 8 ++++++++ libfprint/fpi-image-device.h | 4 ++++ libfprint/fpi-usb-transfer.h | 4 ++++ 4 files changed, 17 insertions(+) diff --git a/libfprint/fpi-assembling.h b/libfprint/fpi-assembling.h index 295e3159..6e1b7071 100644 --- a/libfprint/fpi-assembling.h +++ b/libfprint/fpi-assembling.h @@ -110,6 +110,7 @@ struct fpi_line_asmbl_ctx unsigned char (*get_pixel)(struct fpi_line_asmbl_ctx *ctx, GSList *line, unsigned int x); + gpointer _padding_dummy[32]; }; FpImage *fpi_assemble_lines (struct fpi_line_asmbl_ctx *ctx, diff --git a/libfprint/fpi-device.h b/libfprint/fpi-device.h index 3d66ee58..fa8ddf15 100644 --- a/libfprint/fpi-device.h +++ b/libfprint/fpi-device.h @@ -45,6 +45,10 @@ struct _FpIdEntry const gchar *virtual_envvar; }; guint64 driver_data; + + /*< private >*/ + /* padding for future expansion */ + gpointer _padding_dummy[16]; }; /** @@ -129,6 +133,10 @@ struct _FpDeviceClass void (*delete) (FpDevice * device); void (*cancel) (FpDevice *device); + + /*< private >*/ + /* padding for future expansion */ + gpointer _padding_dummy[32]; }; /** diff --git a/libfprint/fpi-image-device.h b/libfprint/fpi-image-device.h index 155390de..864cb905 100644 --- a/libfprint/fpi-image-device.h +++ b/libfprint/fpi-image-device.h @@ -93,6 +93,10 @@ struct _FpImageDeviceClass void (*change_state) (FpImageDevice *dev, FpiImageDeviceState state); void (*deactivate) (FpImageDevice *dev); + + /*< private >*/ + /* padding for future expansion */ + gpointer _padding_dummy[32]; }; void fpi_image_device_set_bz3_threshold (FpImageDevice *self, diff --git a/libfprint/fpi-usb-transfer.h b/libfprint/fpi-usb-transfer.h index 09d22e85..c69acfcb 100644 --- a/libfprint/fpi-usb-transfer.h +++ b/libfprint/fpi-usb-transfer.h @@ -101,6 +101,10 @@ struct _FpiUsbTransfer /* Data free function */ GDestroyNotify free_buffer; + + /*< private >*/ + /* padding for future expansion */ + gpointer _padding_dummy[32]; }; GType fpi_usb_transfer_get_type (void) G_GNUC_CONST; From 337fe867e99f97de5ab14d695e5d401c8c2fdba6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Thu, 16 Jan 2020 12:37:54 +0100 Subject: [PATCH 05/10] tod-shared-loader: Only allow drivers starting with "lib" prefix --- libfprint/tod/tod-shared-loader.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libfprint/tod/tod-shared-loader.c b/libfprint/tod/tod-shared-loader.c index 842e72dc..3fb04209 100644 --- a/libfprint/tod/tod-shared-loader.c +++ b/libfprint/tod/tod-shared-loader.c @@ -79,6 +79,9 @@ fpi_tod_shared_drivers_register (void) FpDeviceClass *cls; GType driver; + if (!g_str_has_prefix (basename, "lib")) + continue; + if (!g_str_has_suffix (basename, ".so")) continue; From 7b7fc2423ea35c47176408e9d13c0c2f35cc0956 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Thu, 27 Feb 2020 05:58:26 +0100 Subject: [PATCH 06/10] tod: Simplify the lib versioning as per upstream libname based on soname No need to keep track of both revisions, as now that's part of the name --- libfprint/tod/meson.build | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/libfprint/tod/meson.build b/libfprint/tod/meson.build index b864b598..58c48680 100644 --- a/libfprint/tod/meson.build +++ b/libfprint/tod/meson.build @@ -1,7 +1,5 @@ tod_soversion = 1 -tod_version = '@0@.0'.format(tod_soversion) -tod_versioned_path = '-'.join(tod_version.split('.')) -tod_subpath = meson.project_name() / 'tod-@0@'.format(tod_versioned_path) +tod_subpath = versioned_libname / 'tod-@0@'.format(tod_soversion) tod_modules_prefix = get_option('libdir') / tod_subpath tod_conf = configuration_data() @@ -29,13 +27,12 @@ foreach source: libfprint_private_sources tod_sources += '..' / source endforeach -libfprint_tod = library('fprint-tod', +libfprint_tod = library(versioned_libname.split('lib')[1] + '-tod', sources: [ tod_sources, ], - soversion: (soversion * 100) + tod_soversion, + soversion: tod_soversion, include_directories: include_directories('..'), - version: '@0@.'.format(soversion) + tod_version, link_args: [ '-Wl,--version-script,@0@/@1@'.format(meson.source_root(), mapfile[0]), '-Wl,--unresolved-symbols=ignore-in-object-files' @@ -54,13 +51,13 @@ deps += declare_dependency( pkgconfig = import('pkgconfig') pkgconfig.generate(libfprint_tod, - name: 'libfprint-tod', - filebase: 'libfprint@0@-tod-@1@'.format(soversion, tod_versioned_path), + name: versioned_libname + '-tod', + filebase: '@0@-tod-@1@'.format(versioned_libname, tod_soversion), description: 'Private Libfprint Touch Drivers API', - version: meson.project_version() + '.@0@'.format(tod_version), + version: meson.project_version() + '+tod@0@'.format(tod_soversion), subdirs: tod_subpath, requires_private: [ - meson.project_name() + '@0@'.format(soversion), + versioned_libname, ], variables: [ 'tod_driversdir=${libdir}/@0@'.format(tod_subpath) From 19225aaa3e3a92b44f9d397d6bc03924989e9c1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Thu, 27 Feb 2020 06:03:21 +0100 Subject: [PATCH 07/10] meson: Add fpi-compat.h to the private headers --- libfprint/meson.build | 1 + 1 file changed, 1 insertion(+) diff --git a/libfprint/meson.build b/libfprint/meson.build index de37fdac..322a2fcc 100644 --- a/libfprint/meson.build +++ b/libfprint/meson.build @@ -31,6 +31,7 @@ libfprint_private_headers = [ 'fpi-byte-reader.h', 'fpi-byte-utils.h', 'fpi-byte-writer.h', + 'fpi-compat.h', 'fpi-context.h', 'fpi-device.h', 'fpi-image-device.h', From b2a78ddadcf4ba70204f72e348f406925c3beb69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Fri, 28 Feb 2020 17:47:34 +0100 Subject: [PATCH 08/10] README.tod.md: Add a basic readme file --- README.tod.md | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 README.tod.md diff --git a/README.tod.md b/README.tod.md new file mode 100644 index 00000000..34d71a8b --- /dev/null +++ b/README.tod.md @@ -0,0 +1,9 @@ +### libfprint-TOD - libfprint for Touch OEM Drivers + +This is a light fork of libfprint to expose internal Drivers API in order to +create drivers as shared libraries. + +Fork is hosted at: https://gitlab.freedesktop.org/3v1n0/libfprint/tree/tod + +An example driver implementation is available: + - https://gitlab.freedesktop.org/3v1n0/libfprint-tod-example-driver From b1cf057468a4a5a72da1a7e484f86a45b04ac580 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Fri, 28 Feb 2020 15:23:51 +0100 Subject: [PATCH 09/10] Bump libfprint-tod version to v1.90.1+tod1 --- NEWS.tod.md | 25 +++++++++++++++++++++++++ meson.build | 2 +- 2 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 NEWS.tod.md diff --git a/NEWS.tod.md b/NEWS.tod.md new file mode 100644 index 00000000..66e764ff --- /dev/null +++ b/NEWS.tod.md @@ -0,0 +1,25 @@ +### libfprint-TOD v1 + +- First public release +- Based on [libfprint 1.90.1](https://gitlab.freedesktop.org/libfprint/libfprint/-/releases#v1.90.1) +- Bumped TOD version to 1 + +### Highlights of the Drivers API changes + +Both the driver and external APIs have changed, as both the verify and the identify functions now have early reporting mechanisms. + +- Added API for early report of matching results or retry errors +- Verify and identification completion functions have been simplified +- Support variadic arguments in error functions +- Various re-definitions of ownership handling +- Add convenience API to change state after a timeout +- Add unit tests for all the drivers API + +### Drivers required changes +As per the early report mechanism, drivers need to adapt, in particular: + - New pkg-config dependency name is `libfprint-2-tod-1` + - Verification and Identification API for non-image drivers has changed and drivers need to both `report` the result of the action and complete it: + - `fpi_device_{verify,identify}_report` must inform whether a match/no-match or identification happened or report a *retry error*. + - `fpi_device_{verify,identify}_complete` must be called once the device has completed the verification / identification process, in case reporting device errors (not retry ones!) + +You can see examples of changes needed in the [reference example driver](https://gitlab.freedesktop.org/3v1n0/libfprint-tod-example-driver/-/commit/8308f84f7d1cfd1b9ed0936c13c73b43a4a46772) or the [upstream synaptics driver](https://gitlab.freedesktop.org/libfprint/libfprint/-/merge_requests/112/diffs) diff --git a/meson.build b/meson.build index 8d35d925..ccc68fec 100644 --- a/meson.build +++ b/meson.build @@ -1,5 +1,5 @@ project('libfprint', [ 'c', 'cpp' ], - version: '1.90.1', + version: '1.90.1+tod1', license: 'LGPLv2.1+', default_options: [ 'buildtype=debugoptimized', From 0442d58a113aac435d6ebee0ac015f52d0eb9129 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Fri, 28 Feb 2020 17:56:53 +0100 Subject: [PATCH 10/10] New upstream version 1.90.1+tod1