diff --git a/doc/libfprint-2-sections.txt b/doc/libfprint-2-sections.txt index 37fddf3..998ea2e 100644 --- a/doc/libfprint-2-sections.txt +++ b/doc/libfprint-2-sections.txt @@ -131,6 +131,7 @@ fpi_get_driver_types FpDeviceClass FpTimeoutFunc FpiDeviceAction +FpiDeviceFeature FpIdEntry FpiDeviceUdevSubtypeFlags fpi_device_get_usb_device @@ -168,6 +169,7 @@ fpi_device_enroll_progress fpi_device_verify_report fpi_device_identify_report fpi_device_list_complete +fpi_device_class_auto_initialize_features
diff --git a/libfprint/drivers/goodixmoc/goodix.c b/libfprint/drivers/goodixmoc/goodix.c index 77278c6..b57ee3c 100644 --- a/libfprint/drivers/goodixmoc/goodix.c +++ b/libfprint/drivers/goodixmoc/goodix.c @@ -1579,4 +1579,7 @@ fpi_device_goodixmoc_class_init (FpiDeviceGoodixMocClass *klass) dev_class->cancel = gx_fp_cancel; dev_class->verify = gx_fp_verify_identify; dev_class->identify = gx_fp_verify_identify; + + fpi_device_class_auto_initialize_features (dev_class); + dev_class->features |= FPI_DEVICE_FEATURE_DUPLICATES_CHECK; } diff --git a/libfprint/drivers/synaptics/synaptics.c b/libfprint/drivers/synaptics/synaptics.c index bb113cb..7f24d1d 100644 --- a/libfprint/drivers/synaptics/synaptics.c +++ b/libfprint/drivers/synaptics/synaptics.c @@ -1405,4 +1405,6 @@ fpi_device_synaptics_class_init (FpiDeviceSynapticsClass *klass) dev_class->delete = delete_print; dev_class->cancel = cancel; dev_class->list = list; + + fpi_device_class_auto_initialize_features (dev_class); } diff --git a/libfprint/drivers/upekts.c b/libfprint/drivers/upekts.c index 3471cf7..cf02161 100644 --- a/libfprint/drivers/upekts.c +++ b/libfprint/drivers/upekts.c @@ -1555,4 +1555,6 @@ fpi_device_upekts_class_init (FpiDeviceUpektsClass *klass) dev_class->verify = verify; dev_class->enroll = enroll; /* dev_class->cancel = cancel; */ + + fpi_device_class_auto_initialize_features (dev_class); } diff --git a/libfprint/drivers/virtual-device-storage.c b/libfprint/drivers/virtual-device-storage.c index 34e8971..9591dcc 100644 --- a/libfprint/drivers/virtual-device-storage.c +++ b/libfprint/drivers/virtual-device-storage.c @@ -244,4 +244,7 @@ fpi_device_virtual_device_storage_class_init (FpDeviceVirtualDeviceStorageClass dev_class->identify = dev_identify; dev_class->list = dev_list; dev_class->delete = dev_delete; + + fpi_device_class_auto_initialize_features (dev_class); + dev_class->features |= FPI_DEVICE_FEATURE_DUPLICATES_CHECK; } diff --git a/libfprint/drivers/virtual-device.c b/libfprint/drivers/virtual-device.c index 1a31b77..55962ad 100644 --- a/libfprint/drivers/virtual-device.c +++ b/libfprint/drivers/virtual-device.c @@ -776,4 +776,6 @@ fpi_device_virtual_device_class_init (FpDeviceVirtualDeviceClass *klass) dev_class->verify = dev_verify; dev_class->enroll = dev_enroll; dev_class->cancel = dev_cancel; + + fpi_device_class_auto_initialize_features (dev_class); } diff --git a/libfprint/fp-device.c b/libfprint/fp-device.c index 251ed83..7b0a659 100644 --- a/libfprint/fp-device.c +++ b/libfprint/fp-device.c @@ -140,6 +140,8 @@ fp_device_constructed (GObject *object) FpDeviceClass *cls = FP_DEVICE_GET_CLASS (self); FpDevicePrivate *priv = fp_device_get_instance_private (self); + g_assert (cls->features != FPI_DEVICE_FEATURE_NONE); + priv->type = cls->type; if (cls->nr_enroll_stages) priv->nr_enroll_stages = cls->nr_enroll_stages; @@ -627,7 +629,7 @@ fp_device_supports_identify (FpDevice *device) g_return_val_if_fail (FP_IS_DEVICE (device), FALSE); - return cls->identify != NULL; + return cls->identify && !!(cls->features & FPI_DEVICE_FEATURE_IDENTIFY); } /** @@ -645,7 +647,7 @@ fp_device_supports_capture (FpDevice *device) g_return_val_if_fail (FP_IS_DEVICE (device), FALSE); - return cls->capture != NULL; + return cls->capture && !!(cls->features & FPI_DEVICE_FEATURE_CAPTURE); } /** @@ -664,7 +666,7 @@ fp_device_has_storage (FpDevice *device) g_return_val_if_fail (FP_IS_DEVICE (device), FALSE); - return cls->list != NULL; + return !!(cls->features & FPI_DEVICE_FEATURE_STORAGE); } /** @@ -1254,6 +1256,7 @@ fp_device_delete_print (FpDevice *device, { 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)) @@ -1274,7 +1277,7 @@ fp_device_delete_print (FpDevice *device, } /* Succeed immediately if delete is not implemented. */ - if (!FP_DEVICE_GET_CLASS (device)->delete) + if (!cls->delete || !(cls->features & FPI_DEVICE_FEATURE_STORAGE_DELETE)) { g_task_return_boolean (task, TRUE); return; @@ -1288,7 +1291,7 @@ fp_device_delete_print (FpDevice *device, g_object_ref (enrolled_print), g_object_unref); - FP_DEVICE_GET_CLASS (device)->delete (device); + cls->delete (device); } /** diff --git a/libfprint/fp-image-device.c b/libfprint/fp-image-device.c index 0200796..82e69f9 100644 --- a/libfprint/fp-image-device.c +++ b/libfprint/fp-image-device.c @@ -220,6 +220,8 @@ fp_image_device_class_init (FpImageDeviceClass *klass) fp_device_class->cancel = fp_image_device_cancel_action; + fpi_device_class_auto_initialize_features (fp_device_class); + /* Default implementations */ klass->activate = fp_image_device_default_activate; klass->deactivate = fp_image_device_default_deactivate; diff --git a/libfprint/fpi-device.c b/libfprint/fpi-device.c index 9f334e2..f6da050 100644 --- a/libfprint/fpi-device.c +++ b/libfprint/fpi-device.c @@ -46,6 +46,40 @@ fp_device_get_instance_private (FpDevice *self) g_type_class_get_instance_private_offset (dev_class)); } +/** + * fpi_device_class_auto_initialize_features: + * + * Initializes the #FpDeviceClass @features flags checking what device vfuncs + * are implemented. + * Drivers should call this at the end of the class initialization. + */ +void +fpi_device_class_auto_initialize_features (FpDeviceClass *device_class) +{ + g_return_if_fail (FP_IS_DEVICE_CLASS (device_class)); + + if (device_class->capture) + device_class->features |= FPI_DEVICE_FEATURE_CAPTURE; + + if (device_class->verify) + device_class->features |= FPI_DEVICE_FEATURE_VERIFY; + + if (device_class->identify) + device_class->features |= FPI_DEVICE_FEATURE_IDENTIFY; + + if (device_class->list) + { + device_class->features |= FPI_DEVICE_FEATURE_STORAGE; + device_class->features |= FPI_DEVICE_FEATURE_STORAGE_LIST; + } + + if (device_class->delete) + { + device_class->features |= FPI_DEVICE_FEATURE_STORAGE; + device_class->features |= FPI_DEVICE_FEATURE_STORAGE_DELETE; + } +} + /** * fpi_device_retry_new: * @error: The #FpDeviceRetry error value describing the issue diff --git a/libfprint/fpi-device.h b/libfprint/fpi-device.h index 669ce15..38a4574 100644 --- a/libfprint/fpi-device.h +++ b/libfprint/fpi-device.h @@ -69,6 +69,30 @@ struct _FpIdEntry guint64 driver_data; }; +/** + * FpiDeviceFeature: + * @FPI_DEVICE_FEATURE_NONE: Device does not support any feature + * @FPI_DEVICE_FEATURE_CAPTURE: Supports image capture + * @FPI_DEVICE_FEATURE_IDENTIFY: Supports finger identification + * @FPI_DEVICE_FEATURE_VERIFY: Supports finger verification + * @FPI_DEVICE_FEATURE_STORAGE: Device has a persistent storage + * @FPI_DEVICE_FEATURE_STORAGE_LIST: Supports listing the storage templates + * @FPI_DEVICE_FEATURE_STORAGE_DELETE: Supports deleting stored templates + * @FPI_DEVICE_FEATURE_STORAGE_CLEAR: Supports clearing the whole storage + * @FPI_DEVICE_FEATURE_DUPLICATES_CHECK: Natively supports duplicates detection + */ +typedef enum /*< flags >*/ { + FPI_DEVICE_FEATURE_NONE = 0, + FPI_DEVICE_FEATURE_CAPTURE = 1 << 0, + FPI_DEVICE_FEATURE_IDENTIFY = 1 << 1, + FPI_DEVICE_FEATURE_VERIFY = 1 << 2, + FPI_DEVICE_FEATURE_STORAGE = 1 << 3, + FPI_DEVICE_FEATURE_STORAGE_LIST = 1 << 4, + FPI_DEVICE_FEATURE_STORAGE_DELETE = 1 << 5, + FPI_DEVICE_FEATURE_STORAGE_CLEAR = 1 << 6, + FPI_DEVICE_FEATURE_DUPLICATES_CHECK = 1 << 7, +} FpiDeviceFeature; + /** * FpDeviceClass: * @id: ID string for the driver. Should be a valid C identifier and should @@ -76,6 +100,8 @@ struct _FpIdEntry * @full_name: Human readable description of the driver * @type: The type of driver * @id_table: The table of IDs to bind the driver to + * @features: The features the device supports, it can be initialized using + * fpi_device_class_auto_initialize_features() on @class_init. * @nr_enroll_stages: The number of enroll stages supported devices need; use * fpi_device_set_nr_enroll_stages() from @probe if this is dynamic. * @scan_type: The scan type of supported devices; use @@ -133,6 +159,7 @@ struct _FpDeviceClass const gchar *full_name; FpDeviceType type; const FpIdEntry *id_table; + FpiDeviceFeature features; /* Defaults for device properties */ gint nr_enroll_stages; @@ -153,6 +180,8 @@ struct _FpDeviceClass void (*cancel) (FpDevice *device); }; +void fpi_device_class_auto_initialize_features (FpDeviceClass *device_class); + /** * FpTimeoutFunc: * @device: The #FpDevice passed to fpi_device_add_timeout() diff --git a/tests/test-device-fake.c b/tests/test-device-fake.c index 2341581..1feeb18 100644 --- a/tests/test-device-fake.c +++ b/tests/test-device-fake.c @@ -279,4 +279,6 @@ 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; + + fpi_device_class_auto_initialize_features (dev_class); } diff --git a/tests/test-fpi-device.c b/tests/test-fpi-device.c index ab5a108..a6b7285 100644 --- a/tests/test-fpi-device.c +++ b/tests/test-fpi-device.c @@ -506,6 +506,175 @@ test_driver_get_driver_data (void) g_assert_cmpuint (fpi_device_get_driver_data (device), ==, driver_data); } +static void +test_driver_initial_features (void) +{ + g_autoptr(FpDevice) device = g_object_new (FPI_TYPE_DEVICE_FAKE, NULL); + FpDeviceClass *dev_class = FP_DEVICE_GET_CLASS (device); + + g_assert_cmpuint (dev_class->features, !=, FPI_DEVICE_FEATURE_NONE); + g_assert_true (dev_class->features & FPI_DEVICE_FEATURE_CAPTURE); + g_assert_true (dev_class->features & FPI_DEVICE_FEATURE_IDENTIFY); + g_assert_true (dev_class->features & FPI_DEVICE_FEATURE_VERIFY); + g_assert_false (dev_class->features & FPI_DEVICE_FEATURE_DUPLICATES_CHECK); + g_assert_true (dev_class->features & FPI_DEVICE_FEATURE_STORAGE); + g_assert_true (dev_class->features & FPI_DEVICE_FEATURE_STORAGE_LIST); + g_assert_true (dev_class->features & FPI_DEVICE_FEATURE_STORAGE_DELETE); + g_assert_false (dev_class->features & FPI_DEVICE_FEATURE_STORAGE_CLEAR); +} + +static void +test_driver_initial_features_none (void) +{ + g_autoptr(FpAutoResetClass) dev_class = auto_reset_device_class (); + + dev_class->list = NULL; + dev_class->capture = NULL; + dev_class->verify = NULL; + dev_class->identify = NULL; + dev_class->delete = NULL; + dev_class->features = FPI_DEVICE_FEATURE_NONE; + + fpi_device_class_auto_initialize_features (dev_class); + + g_assert_cmpuint (dev_class->features, ==, FPI_DEVICE_FEATURE_NONE); + g_assert_false (dev_class->features & FPI_DEVICE_FEATURE_CAPTURE); + g_assert_false (dev_class->features & FPI_DEVICE_FEATURE_IDENTIFY); + g_assert_false (dev_class->features & FPI_DEVICE_FEATURE_VERIFY); + g_assert_false (dev_class->features & FPI_DEVICE_FEATURE_DUPLICATES_CHECK); + g_assert_false (dev_class->features & FPI_DEVICE_FEATURE_STORAGE); + g_assert_false (dev_class->features & FPI_DEVICE_FEATURE_STORAGE_LIST); + g_assert_false (dev_class->features & FPI_DEVICE_FEATURE_STORAGE_DELETE); + g_assert_false (dev_class->features & FPI_DEVICE_FEATURE_STORAGE_CLEAR); +} + +static void +test_driver_initial_features_no_capture (void) +{ + g_autoptr(FpAutoResetClass) dev_class = auto_reset_device_class (); + + dev_class->capture = NULL; + dev_class->features = FPI_DEVICE_FEATURE_NONE; + + fpi_device_class_auto_initialize_features (dev_class); + + g_assert_cmpuint (dev_class->features, !=, FPI_DEVICE_FEATURE_NONE); + g_assert_false (dev_class->features & FPI_DEVICE_FEATURE_CAPTURE); + g_assert_true (dev_class->features & FPI_DEVICE_FEATURE_IDENTIFY); + g_assert_true (dev_class->features & FPI_DEVICE_FEATURE_VERIFY); + g_assert_false (dev_class->features & FPI_DEVICE_FEATURE_DUPLICATES_CHECK); + g_assert_true (dev_class->features & FPI_DEVICE_FEATURE_STORAGE); + g_assert_true (dev_class->features & FPI_DEVICE_FEATURE_STORAGE_LIST); + g_assert_true (dev_class->features & FPI_DEVICE_FEATURE_STORAGE_DELETE); + g_assert_false (dev_class->features & FPI_DEVICE_FEATURE_STORAGE_CLEAR); +} + +static void +test_driver_initial_features_no_verify (void) +{ + g_autoptr(FpAutoResetClass) dev_class = auto_reset_device_class (); + + dev_class->verify = NULL; + dev_class->features = FPI_DEVICE_FEATURE_NONE; + + fpi_device_class_auto_initialize_features (dev_class); + + g_assert_cmpuint (dev_class->features, !=, FPI_DEVICE_FEATURE_NONE); + g_assert_true (dev_class->features & FPI_DEVICE_FEATURE_CAPTURE); + g_assert_true (dev_class->features & FPI_DEVICE_FEATURE_IDENTIFY); + g_assert_false (dev_class->features & FPI_DEVICE_FEATURE_VERIFY); + g_assert_false (dev_class->features & FPI_DEVICE_FEATURE_DUPLICATES_CHECK); + g_assert_true (dev_class->features & FPI_DEVICE_FEATURE_STORAGE); + g_assert_true (dev_class->features & FPI_DEVICE_FEATURE_STORAGE_LIST); + g_assert_true (dev_class->features & FPI_DEVICE_FEATURE_STORAGE_DELETE); + g_assert_false (dev_class->features & FPI_DEVICE_FEATURE_STORAGE_CLEAR); +} + +static void +test_driver_initial_features_no_identify (void) +{ + g_autoptr(FpAutoResetClass) dev_class = auto_reset_device_class (); + + dev_class->identify = NULL; + dev_class->features = FPI_DEVICE_FEATURE_NONE; + + fpi_device_class_auto_initialize_features (dev_class); + + g_assert_cmpuint (dev_class->features, !=, FPI_DEVICE_FEATURE_NONE); + g_assert_true (dev_class->features & FPI_DEVICE_FEATURE_CAPTURE); + g_assert_false (dev_class->features & FPI_DEVICE_FEATURE_IDENTIFY); + g_assert_true (dev_class->features & FPI_DEVICE_FEATURE_VERIFY); + g_assert_false (dev_class->features & FPI_DEVICE_FEATURE_DUPLICATES_CHECK); + g_assert_true (dev_class->features & FPI_DEVICE_FEATURE_STORAGE); + g_assert_true (dev_class->features & FPI_DEVICE_FEATURE_STORAGE_LIST); + g_assert_true (dev_class->features & FPI_DEVICE_FEATURE_STORAGE_DELETE); + g_assert_false (dev_class->features & FPI_DEVICE_FEATURE_STORAGE_CLEAR); +} + +static void +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 = FPI_DEVICE_FEATURE_NONE; + + fpi_device_class_auto_initialize_features (dev_class); + + g_assert_cmpuint (dev_class->features, !=, FPI_DEVICE_FEATURE_NONE); + g_assert_true (dev_class->features & FPI_DEVICE_FEATURE_CAPTURE); + g_assert_true (dev_class->features & FPI_DEVICE_FEATURE_IDENTIFY); + g_assert_true (dev_class->features & FPI_DEVICE_FEATURE_VERIFY); + g_assert_false (dev_class->features & FPI_DEVICE_FEATURE_DUPLICATES_CHECK); + g_assert_false (dev_class->features & FPI_DEVICE_FEATURE_STORAGE); + g_assert_false (dev_class->features & FPI_DEVICE_FEATURE_STORAGE_LIST); + g_assert_false (dev_class->features & FPI_DEVICE_FEATURE_STORAGE_DELETE); + g_assert_false (dev_class->features & FPI_DEVICE_FEATURE_STORAGE_CLEAR); +} + +static void +test_driver_initial_features_no_list (void) +{ + g_autoptr(FpAutoResetClass) dev_class = auto_reset_device_class (); + + dev_class->list = NULL; + dev_class->features = FPI_DEVICE_FEATURE_NONE; + + fpi_device_class_auto_initialize_features (dev_class); + + g_assert_cmpuint (dev_class->features, !=, FPI_DEVICE_FEATURE_NONE); + g_assert_true (dev_class->features & FPI_DEVICE_FEATURE_CAPTURE); + g_assert_true (dev_class->features & FPI_DEVICE_FEATURE_IDENTIFY); + g_assert_true (dev_class->features & FPI_DEVICE_FEATURE_VERIFY); + g_assert_false (dev_class->features & FPI_DEVICE_FEATURE_DUPLICATES_CHECK); + g_assert_true (dev_class->features & FPI_DEVICE_FEATURE_STORAGE); + g_assert_false (dev_class->features & FPI_DEVICE_FEATURE_STORAGE_LIST); + g_assert_true (dev_class->features & FPI_DEVICE_FEATURE_STORAGE_DELETE); + g_assert_false (dev_class->features & FPI_DEVICE_FEATURE_STORAGE_CLEAR); +} + +static void +test_driver_initial_features_no_delete (void) +{ + g_autoptr(FpAutoResetClass) dev_class = auto_reset_device_class (); + + dev_class->list = NULL; + dev_class->features = FPI_DEVICE_FEATURE_NONE; + + fpi_device_class_auto_initialize_features (dev_class); + + g_assert_cmpuint (dev_class->features, !=, FPI_DEVICE_FEATURE_NONE); + g_assert_true (dev_class->features & FPI_DEVICE_FEATURE_CAPTURE); + g_assert_true (dev_class->features & FPI_DEVICE_FEATURE_IDENTIFY); + g_assert_true (dev_class->features & FPI_DEVICE_FEATURE_VERIFY); + g_assert_false (dev_class->features & FPI_DEVICE_FEATURE_DUPLICATES_CHECK); + g_assert_true (dev_class->features & FPI_DEVICE_FEATURE_STORAGE); + g_assert_false (dev_class->features & FPI_DEVICE_FEATURE_STORAGE_LIST); + g_assert_true (dev_class->features & FPI_DEVICE_FEATURE_STORAGE_DELETE); + g_assert_false (dev_class->features & FPI_DEVICE_FEATURE_STORAGE_CLEAR); +} + static void on_driver_probe_async (GObject *initable, GAsyncResult *res, gpointer user_data) { @@ -1311,7 +1480,7 @@ test_driver_do_not_support_identify (void) g_autoptr(FpAutoResetClass) dev_class = auto_reset_device_class (); g_autoptr(FpDevice) device = NULL; - dev_class->identify = NULL; + dev_class->features &= ~FPI_DEVICE_FEATURE_IDENTIFY; device = g_object_new (FPI_TYPE_DEVICE_FAKE, NULL); g_assert_false (fp_device_supports_identify (device)); @@ -1639,6 +1808,7 @@ test_driver_supports_capture (void) g_autoptr(FpAutoResetClass) dev_class = auto_reset_device_class (); g_autoptr(FpDevice) device = NULL; + dev_class->features |= FPI_DEVICE_FEATURE_CAPTURE; dev_class->capture = fake_device_stub_capture; device = g_object_new (FPI_TYPE_DEVICE_FAKE, NULL); @@ -1651,6 +1821,7 @@ test_driver_do_not_support_capture (void) g_autoptr(FpAutoResetClass) dev_class = auto_reset_device_class (); g_autoptr(FpDevice) device = NULL; + dev_class->features &= ~FPI_DEVICE_FEATURE_CAPTURE; dev_class->capture = NULL; device = g_object_new (FPI_TYPE_DEVICE_FAKE, NULL); @@ -1695,18 +1866,13 @@ test_driver_capture_error (void) g_assert_null (image); } -static void -fake_device_stub_list (FpDevice *device) -{ -} - static void test_driver_has_storage (void) { g_autoptr(FpAutoResetClass) dev_class = auto_reset_device_class (); g_autoptr(FpDevice) device = NULL; - dev_class->list = fake_device_stub_list; + dev_class->features |= FPI_DEVICE_FEATURE_STORAGE; device = g_object_new (FPI_TYPE_DEVICE_FAKE, NULL); g_assert_true (fp_device_has_storage (device)); @@ -1718,7 +1884,7 @@ test_driver_has_not_storage (void) g_autoptr(FpAutoResetClass) dev_class = auto_reset_device_class (); g_autoptr(FpDevice) device = NULL; - dev_class->list = NULL; + dev_class->features &= ~FPI_DEVICE_FEATURE_STORAGE; device = g_object_new (FPI_TYPE_DEVICE_FAKE, NULL); g_assert_false (fp_device_has_storage (device)); @@ -1770,7 +1936,7 @@ test_driver_list_no_storage (void) g_autoptr(GPtrArray) prints = NULL; g_autoptr(GError) error = NULL; - dev_class->list = NULL; + dev_class->features &= ~FPI_DEVICE_FEATURE_STORAGE; device = auto_close_fake_device_new (); g_assert_false (fp_device_has_storage (device)); @@ -2439,6 +2605,14 @@ main (int argc, char *argv[]) g_test_add_func ("/driver/get_usb_device", test_driver_get_usb_device); g_test_add_func ("/driver/get_virtual_env", test_driver_get_virtual_env); g_test_add_func ("/driver/get_driver_data", test_driver_get_driver_data); + g_test_add_func ("/driver/initial_features", test_driver_initial_features); + g_test_add_func ("/driver/initial_features/none", test_driver_initial_features_none); + g_test_add_func ("/driver/initial_features/no_capture", test_driver_initial_features_no_capture); + g_test_add_func ("/driver/initial_features/no_verify", test_driver_initial_features_no_verify); + g_test_add_func ("/driver/initial_features/no_identify", test_driver_initial_features_no_identify); + 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/probe", test_driver_probe); g_test_add_func ("/driver/probe/error", test_driver_probe_error);