From 77e95aa545724146d764b83066199d0e306ea4f0 Mon Sep 17 00:00:00 2001 From: Vincent Huang Date: Fri, 9 Apr 2021 17:23:13 +0800 Subject: [PATCH] fp-device: Add fp_device_clear_storage and clear_storage vfunc --- doc/libfprint-2-sections.txt | 3 + libfprint/drivers/virtual-device-storage.c | 21 ++++ libfprint/fp-device.c | 115 +++++++++++++++++++++ libfprint/fp-device.h | 13 ++- libfprint/fpi-device.c | 45 ++++++-- libfprint/fpi-device.h | 6 ++ tests/test-device-fake.c | 18 ++++ tests/test-fpi-device.c | 48 ++++++--- tests/virtual-device.py | 2 +- 9 files changed, 248 insertions(+), 23 deletions(-) diff --git a/doc/libfprint-2-sections.txt b/doc/libfprint-2-sections.txt index 77fd3f37..f705f6ac 100644 --- a/doc/libfprint-2-sections.txt +++ b/doc/libfprint-2-sections.txt @@ -49,6 +49,7 @@ fp_device_identify fp_device_capture fp_device_delete_print fp_device_list_prints +fp_device_clear_storage fp_device_open_finish fp_device_close_finish fp_device_enroll_finish @@ -57,6 +58,7 @@ fp_device_identify_finish fp_device_capture_finish fp_device_delete_print_finish fp_device_list_prints_finish +fp_device_clear_storage_finish fp_device_open_sync fp_device_close_sync fp_device_enroll_sync @@ -65,6 +67,7 @@ fp_device_identify_sync fp_device_capture_sync fp_device_delete_print_sync fp_device_list_prints_sync +fp_device_clear_storage_sync FpDevice diff --git a/libfprint/drivers/virtual-device-storage.c b/libfprint/drivers/virtual-device-storage.c index cc67d8c5..a4fda051 100644 --- a/libfprint/drivers/virtual-device-storage.c +++ b/libfprint/drivers/virtual-device-storage.c @@ -160,6 +160,26 @@ dev_list (FpDevice *dev) fpi_device_list_complete (dev, get_stored_prints (vdev), NULL); } +static void +dev_clear_storage (FpDevice *dev) +{ + g_autoptr(GPtrArray) prints_list = NULL; + g_autoptr(GError) error = NULL; + FpDeviceVirtualDevice *vdev = FP_DEVICE_VIRTUAL_DEVICE (dev); + + process_cmds (vdev, FALSE, &error); + if (should_wait_for_command (vdev, error)) + return; + + if (error && !g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND)) + { + fpi_device_clear_storage_complete (dev, g_steal_pointer (&error)); + return; + } + + fpi_device_clear_storage_complete (dev, NULL); +} + static void dev_delete (FpDevice *dev) { @@ -244,6 +264,7 @@ fpi_device_virtual_device_storage_class_init (FpDeviceVirtualDeviceStorageClass dev_class->identify = dev_identify; dev_class->list = dev_list; dev_class->delete = dev_delete; + dev_class->clear_storage = dev_clear_storage; fpi_device_class_auto_initialize_features (dev_class); dev_class->features |= FP_DEVICE_FEATURE_DUPLICATES_CHECK; diff --git a/libfprint/fp-device.c b/libfprint/fp-device.c index bf405855..325da8eb 100644 --- a/libfprint/fp-device.c +++ b/libfprint/fp-device.c @@ -1412,6 +1412,93 @@ fp_device_list_prints_finish (FpDevice *device, return g_task_propagate_pointer (G_TASK (result), error); } +/** + * fp_device_clear_storage: + * @device: a #FpDevice + * @cancellable: (nullable): a #GCancellable, or %NULL + * @callback: the function to call on completion + * @user_data: the data to pass to @callback + * + * Start an asynchronous operation to delete all prints from the device. + * The callback will be called once the operation has finished. Retrieve + * the result with fp_device_clear_storage_finish(). + * + * This only makes sense on devices that store prints on-chip, but is safe + * to always call. + */ +void +fp_device_clear_storage (FpDevice *device, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + g_autoptr(GTask) task = NULL; + FpDevicePrivate *priv = fp_device_get_instance_private (device); + FpDeviceClass *cls = FP_DEVICE_GET_CLASS (device); + + task = g_task_new (device, cancellable, callback, user_data); + if (g_task_return_error_if_cancelled (task)) + return; + + if (!priv->is_open) + { + g_task_return_error (task, + fpi_device_error_new (FP_DEVICE_ERROR_NOT_OPEN)); + return; + } + + if (priv->current_task) + { + g_task_return_error (task, + fpi_device_error_new (FP_DEVICE_ERROR_BUSY)); + return; + } + + if (!(cls->features & FP_DEVICE_FEATURE_STORAGE)) + { + g_task_return_error (task, + fpi_device_error_new_msg (FP_DEVICE_ERROR_NOT_SUPPORTED, + "Device has no storage.")); + return; + } + + if (!(cls->features & FP_DEVICE_FEATURE_STORAGE_CLEAR)) + { + g_task_return_error (task, + fpi_device_error_new_msg (FP_DEVICE_ERROR_NOT_SUPPORTED, + "Device doesn't support clearing storage.")); + return; + } + + priv->current_action = FPI_DEVICE_ACTION_CLEAR_STORAGE; + priv->current_task = g_steal_pointer (&task); + maybe_cancel_on_cancelled (device, cancellable); + + cls->clear_storage (device); + + return; +} + +/** + * fp_device_clear_storage_finish: + * @device: A #FpDevice + * @result: A #GAsyncResult + * @error: Return location for errors, or %NULL to ignore + * + * Finish an asynchronous operation to delete all enrolled prints. + * + * See fp_device_clear_storage(). + * + * Returns: (type void): %FALSE on error, %TRUE otherwise + */ +gboolean +fp_device_clear_storage_finish (FpDevice *device, + GAsyncResult *result, + GError **error) +{ + return g_task_propagate_boolean (G_TASK (result), error); +} + static void async_result_ready (GObject *source_object, GAsyncResult *res, gpointer user_data) { @@ -1716,3 +1803,31 @@ fp_device_has_feature (FpDevice *device, return (fp_device_get_features (device) & feature) == feature; } + +/** + * fp_device_clear_storage_sync: + * @device: a #FpDevice + * @cancellable: (nullable): a #GCancellable, or %NULL + * @error: Return location for errors, or %NULL to ignore + * + * Clear sensor storage. + * + * Returns: (type void): %FALSE on error, %TRUE otherwise + */ +gboolean +fp_device_clear_storage_sync (FpDevice *device, + GCancellable *cancellable, + GError **error) +{ + g_autoptr(GAsyncResult) task = NULL; + + g_return_val_if_fail (FP_IS_DEVICE (device), FALSE); + + fp_device_clear_storage (device, + cancellable, + async_result_ready, &task); + while (!task) + g_main_context_iteration (NULL, TRUE); + + return fp_device_clear_storage_finish (device, task, error); +} diff --git a/libfprint/fp-device.h b/libfprint/fp-device.h index 603ffdce..5d224f82 100644 --- a/libfprint/fp-device.h +++ b/libfprint/fp-device.h @@ -261,6 +261,11 @@ void fp_device_list_prints (FpDevice *device, GAsyncReadyCallback callback, gpointer user_data); +void fp_device_clear_storage (FpDevice *device, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); + gboolean fp_device_open_finish (FpDevice *device, GAsyncResult *result, GError **error); @@ -289,7 +294,9 @@ gboolean fp_device_delete_print_finish (FpDevice *device, GPtrArray * fp_device_list_prints_finish (FpDevice *device, GAsyncResult *result, GError **error); - +gboolean fp_device_clear_storage_finish (FpDevice *device, + GAsyncResult *result, + GError **error); gboolean fp_device_open_sync (FpDevice *device, GCancellable *cancellable, @@ -330,7 +337,9 @@ gboolean fp_device_delete_print_sync (FpDevice *device, GPtrArray * fp_device_list_prints_sync (FpDevice *device, GCancellable *cancellable, GError **error); - +gboolean fp_device_clear_storage_sync (FpDevice *device, + GCancellable *cancellable, + GError **error); /* Deprecated functions */ G_DEPRECATED_FOR (fp_device_get_features) gboolean fp_device_supports_identify (FpDevice *device); diff --git a/libfprint/fpi-device.c b/libfprint/fpi-device.c index 78a7939a..f1dab29c 100644 --- a/libfprint/fpi-device.c +++ b/libfprint/fpi-device.c @@ -68,16 +68,16 @@ fpi_device_class_auto_initialize_features (FpDeviceClass *device_class) device_class->features |= FP_DEVICE_FEATURE_IDENTIFY; if (device_class->list) - { - device_class->features |= FP_DEVICE_FEATURE_STORAGE; - device_class->features |= FP_DEVICE_FEATURE_STORAGE_LIST; - } + device_class->features |= FP_DEVICE_FEATURE_STORAGE_LIST; if (device_class->delete) - { - device_class->features |= FP_DEVICE_FEATURE_STORAGE; - device_class->features |= FP_DEVICE_FEATURE_STORAGE_DELETE; - } + device_class->features |= FP_DEVICE_FEATURE_STORAGE_DELETE; + + if (device_class->clear_storage) + device_class->features |= FP_DEVICE_FEATURE_STORAGE_CLEAR; + + if (device_class->delete && (device_class->list || device_class->clear_storage)) + device_class->features |= FP_DEVICE_FEATURE_STORAGE; } /** @@ -1378,6 +1378,35 @@ fpi_device_list_complete (FpDevice *device, } /** + * fpi_device_clear_storage_complete: + * @device: The #FpDevice + * @error: The #GError or %NULL on success + * + * Finish an ongoing clear_storage operation. + */ +void +fpi_device_clear_storage_complete (FpDevice *device, + GError *error) +{ + FpDevicePrivate *priv = fp_device_get_instance_private (device); + + g_return_if_fail (FP_IS_DEVICE (device)); + g_return_if_fail (priv->current_action == FPI_DEVICE_ACTION_CLEAR_STORAGE); + + g_debug ("Device reported deletion completion"); + + clear_device_cancel_action (device); + fpi_device_report_finger_status (device, FP_FINGER_STATUS_NONE); + + if (!error) + fpi_device_return_task_in_idle (device, FP_DEVICE_TASK_RETURN_BOOL, + GUINT_TO_POINTER (TRUE)); + else + fpi_device_return_task_in_idle (device, FP_DEVICE_TASK_RETURN_ERROR, error); +} + +/** + * fpi_device_enroll_progress: * @device: The #FpDevice * @completed_stages: The number of stages that are completed at this point diff --git a/libfprint/fpi-device.h b/libfprint/fpi-device.h index f669d293..4412c78b 100644 --- a/libfprint/fpi-device.h +++ b/libfprint/fpi-device.h @@ -101,6 +101,7 @@ struct _FpIdEntry * @capture: Start a capture operation * @list: List prints stored on the device * @delete: Delete a print from the device + * @clear_storage: Delete all prints from the device * @cancel: Called on cancellation, this is a convenience to not need to handle * the #GCancellable directly by using fpi_device_get_cancellable(). * @@ -152,6 +153,7 @@ struct _FpDeviceClass void (*capture) (FpDevice *device); void (*list) (FpDevice *device); void (*delete) (FpDevice * device); + void (*clear_storage) (FpDevice * device); void (*cancel) (FpDevice *device); }; @@ -180,6 +182,7 @@ typedef void (*FpTimeoutFunc) (FpDevice *device, * @FPI_DEVICE_ACTION_CAPTURE: Device is currently capturing an image. * @FPI_DEVICE_ACTION_LIST: Device stored prints are being queried. * @FPI_DEVICE_ACTION_DELETE: Device stored print is being deleted. + * @FPI_DEVICE_ACTION_CLEAR_STORAGE: Device stored prints are being deleted. * * Current active action of the device. A driver can retrieve the action. */ @@ -194,6 +197,7 @@ typedef enum { FPI_DEVICE_ACTION_CAPTURE, FPI_DEVICE_ACTION_LIST, FPI_DEVICE_ACTION_DELETE, + FPI_DEVICE_ACTION_CLEAR_STORAGE, } FpiDeviceAction; GUsbDevice *fpi_device_get_usb_device (FpDevice *device); @@ -271,6 +275,8 @@ void fpi_device_delete_complete (FpDevice *device, void fpi_device_list_complete (FpDevice *device, GPtrArray *prints, GError *error); +void fpi_device_clear_storage_complete (FpDevice *device, + GError *error); void fpi_device_enroll_progress (FpDevice *device, gint completed_stages, diff --git a/tests/test-device-fake.c b/tests/test-device-fake.c index 1feeb183..2a7d936a 100644 --- a/tests/test-device-fake.c +++ b/tests/test-device-fake.c @@ -243,6 +243,23 @@ fpi_device_fake_delete (FpDevice *device) fpi_device_delete_complete (device, fake_dev->ret_error); } +static void +fpi_device_fake_clear_storage (FpDevice *device) +{ + FpiDeviceFake *fake_dev = FPI_DEVICE_FAKE (device); + + fake_dev->last_called_function = fpi_device_fake_clear_storage; + g_assert_cmpuint (fpi_device_get_current_action (device), ==, FPI_DEVICE_ACTION_CLEAR_STORAGE); + + if (fake_dev->return_action_error) + { + fpi_device_action_error (device, fake_dev->ret_error); + return; + } + + fpi_device_clear_storage_complete (device, fake_dev->ret_error); +} + static void fpi_device_fake_cancel (FpDevice *device) { @@ -279,6 +296,7 @@ fpi_device_fake_class_init (FpiDeviceFakeClass *klass) dev_class->list = fpi_device_fake_list; dev_class->delete = fpi_device_fake_delete; dev_class->cancel = fpi_device_fake_cancel; + dev_class->clear_storage = fpi_device_fake_clear_storage; fpi_device_class_auto_initialize_features (dev_class); } diff --git a/tests/test-fpi-device.c b/tests/test-fpi-device.c index 8bb51f2d..b2cfa549 100644 --- a/tests/test-fpi-device.c +++ b/tests/test-fpi-device.c @@ -586,7 +586,7 @@ test_driver_initial_features (void) g_assert_true (dev_class->features & FP_DEVICE_FEATURE_STORAGE); g_assert_true (dev_class->features & FP_DEVICE_FEATURE_STORAGE_LIST); g_assert_true (dev_class->features & FP_DEVICE_FEATURE_STORAGE_DELETE); - g_assert_false (dev_class->features & FP_DEVICE_FEATURE_STORAGE_CLEAR); + g_assert_true (dev_class->features & FP_DEVICE_FEATURE_STORAGE_CLEAR); g_assert_true (fp_device_has_feature (device, FP_DEVICE_FEATURE_CAPTURE)); g_assert_true (fp_device_has_feature (device, FP_DEVICE_FEATURE_IDENTIFY)); @@ -595,7 +595,7 @@ test_driver_initial_features (void) g_assert_true (fp_device_has_feature (device, FP_DEVICE_FEATURE_STORAGE)); g_assert_true (fp_device_has_feature (device, FP_DEVICE_FEATURE_STORAGE_LIST)); g_assert_true (fp_device_has_feature (device, FP_DEVICE_FEATURE_STORAGE_DELETE)); - g_assert_false (fp_device_has_feature (device, FP_DEVICE_FEATURE_STORAGE_CLEAR)); + g_assert_true (fp_device_has_feature (device, FP_DEVICE_FEATURE_STORAGE_CLEAR)); g_assert_cmpuint (fp_device_get_features (device), ==, @@ -604,7 +604,8 @@ test_driver_initial_features (void) FP_DEVICE_FEATURE_VERIFY | FP_DEVICE_FEATURE_STORAGE | FP_DEVICE_FEATURE_STORAGE_LIST | - FP_DEVICE_FEATURE_STORAGE_DELETE); + FP_DEVICE_FEATURE_STORAGE_DELETE | + FP_DEVICE_FEATURE_STORAGE_CLEAR); } static void @@ -617,6 +618,7 @@ test_driver_initial_features_none (void) dev_class->verify = NULL; dev_class->identify = NULL; dev_class->delete = NULL; + dev_class->clear_storage = NULL; dev_class->features = FP_DEVICE_FEATURE_NONE; fpi_device_class_auto_initialize_features (dev_class); @@ -650,7 +652,7 @@ test_driver_initial_features_no_capture (void) g_assert_true (dev_class->features & FP_DEVICE_FEATURE_STORAGE); g_assert_true (dev_class->features & FP_DEVICE_FEATURE_STORAGE_LIST); g_assert_true (dev_class->features & FP_DEVICE_FEATURE_STORAGE_DELETE); - g_assert_false (dev_class->features & FP_DEVICE_FEATURE_STORAGE_CLEAR); + g_assert_true (dev_class->features & FP_DEVICE_FEATURE_STORAGE_CLEAR); } static void @@ -671,7 +673,7 @@ test_driver_initial_features_no_verify (void) g_assert_true (dev_class->features & FP_DEVICE_FEATURE_STORAGE); g_assert_true (dev_class->features & FP_DEVICE_FEATURE_STORAGE_LIST); g_assert_true (dev_class->features & FP_DEVICE_FEATURE_STORAGE_DELETE); - g_assert_false (dev_class->features & FP_DEVICE_FEATURE_STORAGE_CLEAR); + g_assert_true (dev_class->features & FP_DEVICE_FEATURE_STORAGE_CLEAR); } static void @@ -692,7 +694,7 @@ test_driver_initial_features_no_identify (void) g_assert_true (dev_class->features & FP_DEVICE_FEATURE_STORAGE); g_assert_true (dev_class->features & FP_DEVICE_FEATURE_STORAGE_LIST); g_assert_true (dev_class->features & FP_DEVICE_FEATURE_STORAGE_DELETE); - g_assert_false (dev_class->features & FP_DEVICE_FEATURE_STORAGE_CLEAR); + g_assert_true (dev_class->features & FP_DEVICE_FEATURE_STORAGE_CLEAR); } static void @@ -700,7 +702,6 @@ test_driver_initial_features_no_storage (void) { g_autoptr(FpAutoResetClass) dev_class = auto_reset_device_class (); - dev_class->list = NULL; dev_class->delete = NULL; dev_class->features = FP_DEVICE_FEATURE_NONE; @@ -712,9 +713,9 @@ test_driver_initial_features_no_storage (void) g_assert_true (dev_class->features & FP_DEVICE_FEATURE_VERIFY); g_assert_false (dev_class->features & FP_DEVICE_FEATURE_DUPLICATES_CHECK); g_assert_false (dev_class->features & FP_DEVICE_FEATURE_STORAGE); - g_assert_false (dev_class->features & FP_DEVICE_FEATURE_STORAGE_LIST); + g_assert_true (dev_class->features & FP_DEVICE_FEATURE_STORAGE_LIST); g_assert_false (dev_class->features & FP_DEVICE_FEATURE_STORAGE_DELETE); - g_assert_false (dev_class->features & FP_DEVICE_FEATURE_STORAGE_CLEAR); + g_assert_true (dev_class->features & FP_DEVICE_FEATURE_STORAGE_CLEAR); } static void @@ -735,7 +736,7 @@ test_driver_initial_features_no_list (void) g_assert_true (dev_class->features & FP_DEVICE_FEATURE_STORAGE); g_assert_false (dev_class->features & FP_DEVICE_FEATURE_STORAGE_LIST); g_assert_true (dev_class->features & FP_DEVICE_FEATURE_STORAGE_DELETE); - g_assert_false (dev_class->features & FP_DEVICE_FEATURE_STORAGE_CLEAR); + g_assert_true (dev_class->features & FP_DEVICE_FEATURE_STORAGE_CLEAR); } static void @@ -743,7 +744,28 @@ test_driver_initial_features_no_delete (void) { g_autoptr(FpAutoResetClass) dev_class = auto_reset_device_class (); - dev_class->list = NULL; + dev_class->delete = NULL; + dev_class->features = FP_DEVICE_FEATURE_NONE; + + fpi_device_class_auto_initialize_features (dev_class); + + g_assert_cmpuint (dev_class->features, !=, FP_DEVICE_FEATURE_NONE); + g_assert_true (dev_class->features & FP_DEVICE_FEATURE_CAPTURE); + g_assert_true (dev_class->features & FP_DEVICE_FEATURE_IDENTIFY); + g_assert_true (dev_class->features & FP_DEVICE_FEATURE_VERIFY); + g_assert_false (dev_class->features & FP_DEVICE_FEATURE_DUPLICATES_CHECK); + g_assert_false (dev_class->features & FP_DEVICE_FEATURE_STORAGE); + g_assert_true (dev_class->features & FP_DEVICE_FEATURE_STORAGE_LIST); + g_assert_false (dev_class->features & FP_DEVICE_FEATURE_STORAGE_DELETE); + g_assert_true (dev_class->features & FP_DEVICE_FEATURE_STORAGE_CLEAR); +} + +static void +test_driver_initial_features_no_clear (void) +{ + g_autoptr(FpAutoResetClass) dev_class = auto_reset_device_class (); + + dev_class->clear_storage = NULL; dev_class->features = FP_DEVICE_FEATURE_NONE; fpi_device_class_auto_initialize_features (dev_class); @@ -754,7 +776,7 @@ test_driver_initial_features_no_delete (void) g_assert_true (dev_class->features & FP_DEVICE_FEATURE_VERIFY); g_assert_false (dev_class->features & FP_DEVICE_FEATURE_DUPLICATES_CHECK); g_assert_true (dev_class->features & FP_DEVICE_FEATURE_STORAGE); - g_assert_false (dev_class->features & FP_DEVICE_FEATURE_STORAGE_LIST); + g_assert_true (dev_class->features & FP_DEVICE_FEATURE_STORAGE_LIST); g_assert_true (dev_class->features & FP_DEVICE_FEATURE_STORAGE_DELETE); g_assert_false (dev_class->features & FP_DEVICE_FEATURE_STORAGE_CLEAR); } @@ -2787,6 +2809,8 @@ main (int argc, char *argv[]) g_test_add_func ("/driver/initial_features/no_storage", test_driver_initial_features_no_storage); g_test_add_func ("/driver/initial_features/no_list", test_driver_initial_features_no_list); g_test_add_func ("/driver/initial_features/no_delete", test_driver_initial_features_no_delete); + g_test_add_func ("/driver/initial_features/no_clear", test_driver_initial_features_no_clear); + g_test_add_func ("/driver/probe", test_driver_probe); g_test_add_func ("/driver/probe/error", test_driver_probe_error); diff --git a/tests/virtual-device.py b/tests/virtual-device.py index d6046399..2089f2a8 100644 --- a/tests/virtual-device.py +++ b/tests/virtual-device.py @@ -1029,7 +1029,7 @@ class VirtualDeviceStorage(VirtualDevice): self.assertTrue(self.dev.has_feature(FPrint.DeviceFeature.STORAGE)) self.assertTrue(self.dev.has_feature(FPrint.DeviceFeature.STORAGE_LIST)) self.assertTrue(self.dev.has_feature(FPrint.DeviceFeature.STORAGE_DELETE)) - self.assertFalse(self.dev.has_feature(FPrint.DeviceFeature.STORAGE_CLEAR)) + self.assertTrue(self.dev.has_feature(FPrint.DeviceFeature.STORAGE_CLEAR)) def test_duplicate_enroll(self): self.enroll_print('testprint', FPrint.Finger.LEFT_LITTLE)