fp-device: Add finger-status property

It can be used by drivers to report the state of the finger on sensor
This commit is contained in:
Marco Trevisan (Treviño) 2020-03-26 20:49:48 +01:00 committed by Marco Trevisan
parent ae3baadcf9
commit 42e4506b1b
8 changed files with 264 additions and 1 deletions

View file

@ -50,6 +50,7 @@ typedef struct
/* State for tasks */ /* State for tasks */
gboolean wait_for_finger; gboolean wait_for_finger;
FpFingerStatusFlags finger_status;
} FpDevicePrivate; } FpDevicePrivate;

View file

@ -46,6 +46,7 @@ enum {
PROP_OPEN, PROP_OPEN,
PROP_NR_ENROLL_STAGES, PROP_NR_ENROLL_STAGES,
PROP_SCAN_TYPE, PROP_SCAN_TYPE,
PROP_FINGER_STATUS,
PROP_FPI_ENVIRON, PROP_FPI_ENVIRON,
PROP_FPI_USB_DEVICE, PROP_FPI_USB_DEVICE,
PROP_FPI_DRIVER_DATA, PROP_FPI_DRIVER_DATA,
@ -181,6 +182,10 @@ fp_device_get_property (GObject *object,
g_value_set_enum (value, priv->scan_type); g_value_set_enum (value, priv->scan_type);
break; break;
case PROP_FINGER_STATUS:
g_value_set_enum (value, priv->finger_status);
break;
case PROP_DRIVER: case PROP_DRIVER:
g_value_set_static_string (value, FP_DEVICE_GET_CLASS (priv)->id); g_value_set_static_string (value, FP_DEVICE_GET_CLASS (priv)->id);
break; break;
@ -310,6 +315,13 @@ fp_device_class_init (FpDeviceClass *klass)
FP_TYPE_SCAN_TYPE, FP_SCAN_TYPE_SWIPE, FP_TYPE_SCAN_TYPE, FP_SCAN_TYPE_SWIPE,
G_PARAM_STATIC_STRINGS | G_PARAM_READABLE); G_PARAM_STATIC_STRINGS | G_PARAM_READABLE);
properties[PROP_FINGER_STATUS] =
g_param_spec_flags ("finger-status",
"FingerStatus",
"The status of the finger",
FP_TYPE_FINGER_STATUS_FLAGS, FP_FINGER_STATUS_NONE,
G_PARAM_STATIC_STRINGS | G_PARAM_READABLE);
properties[PROP_DRIVER] = properties[PROP_DRIVER] =
g_param_spec_string ("driver", g_param_spec_string ("driver",
"Driver", "Driver",
@ -469,6 +481,26 @@ fp_device_get_scan_type (FpDevice *device)
return priv->scan_type; return priv->scan_type;
} }
/**
* fp_device_get_finger_status:
* @device: A #FpDevice
*
* Retrieves the finger status flags for the device.
* This can be used by the UI to present the relevant feedback, although it
* is not guaranteed to be a relevant value when not performing any action.
*
* Returns: The current #FpFingerStatusFlags
*/
FpFingerStatusFlags
fp_device_get_finger_status (FpDevice *device)
{
FpDevicePrivate *priv = fp_device_get_instance_private (device);
g_return_val_if_fail (FP_IS_DEVICE (device), FP_SCAN_TYPE_SWIPE);
return priv->finger_status;
}
/** /**
* fp_device_get_nr_enroll_stages: * fp_device_get_nr_enroll_stages:
* @device: A #FpDevice * @device: A #FpDevice

View file

@ -170,6 +170,7 @@ const gchar *fp_device_get_device_id (FpDevice *device);
const gchar *fp_device_get_name (FpDevice *device); const gchar *fp_device_get_name (FpDevice *device);
gboolean fp_device_is_open (FpDevice *device); gboolean fp_device_is_open (FpDevice *device);
FpScanType fp_device_get_scan_type (FpDevice *device); FpScanType fp_device_get_scan_type (FpDevice *device);
FpFingerStatusFlags fp_device_get_finger_status (FpDevice *device);
gint fp_device_get_nr_enroll_stages (FpDevice *device); gint fp_device_get_nr_enroll_stages (FpDevice *device);
gboolean fp_device_supports_identify (FpDevice *device); gboolean fp_device_supports_identify (FpDevice *device);

View file

@ -66,6 +66,18 @@ typedef enum {
FP_FINGER_LAST = FP_FINGER_RIGHT_LITTLE, FP_FINGER_LAST = FP_FINGER_RIGHT_LITTLE,
} FpFinger; } FpFinger;
/**
* FpFingerStatusFlags:
* @FP_FINGER_STATUS_NONE: Sensor has not the finger on it, nor requires it
* @FP_FINGER_STATUS_NEEDED: Sensor waits for the finger
* @FP_FINGER_STATUS_PRESENT: Sensor has the finger on it
*/
typedef enum {
FP_FINGER_STATUS_NONE = 0,
FP_FINGER_STATUS_NEEDED = 1 << 0,
FP_FINGER_STATUS_PRESENT = 1 << 1,
} FpFingerStatusFlags;
FpPrint *fp_print_new (FpDevice *device); FpPrint *fp_print_new (FpDevice *device);
FpPrint *fp_print_new_from_data (guchar *data, FpPrint *fp_print_new_from_data (guchar *data,

View file

@ -1394,3 +1394,59 @@ fpi_device_identify_report (FpDevice *device,
if (call_cb && data->match_cb) if (call_cb && data->match_cb)
data->match_cb (device, data->match, data->print, data->match_data, data->error); data->match_cb (device, data->match, data->print, data->match_data, data->error);
} }
/**
* fpi_device_report_finger_status:
* @device: The #FpDevice
* @finger_status: The current #FpFingerStatusFlags to report
*
* Report the finger status for the @device.
* This can be used by UI to give a feedback
*
* Returns: %TRUE if changed
*/
gboolean
fpi_device_report_finger_status (FpDevice *device,
FpFingerStatusFlags finger_status)
{
FpDevicePrivate *priv = fp_device_get_instance_private (device);
g_autofree char *status_string = NULL;
if (priv->finger_status == finger_status)
return FALSE;
status_string = g_flags_to_string (FP_TYPE_FINGER_STATUS_FLAGS, finger_status);
fp_dbg ("Device reported finger status change: %s", status_string);
priv->finger_status = finger_status;
g_object_notify (G_OBJECT (device), "finger-status");
return TRUE;
}
/**
* fpi_device_report_finger_status_changes:
* @device: The #FpDevice
* @added_status: The #FpFingerStatusFlags to add
* @added_status: The #FpFingerStatusFlags to remove
*
* Report the finger status for the @device adding the @added_status flags
* and removing the @removed_status flags.
*
* This can be used by UI to give a feedback
*
* Returns: %TRUE if changed
*/
gboolean
fpi_device_report_finger_status_changes (FpDevice *device,
FpFingerStatusFlags added_status,
FpFingerStatusFlags removed_status)
{
FpDevicePrivate *priv = fp_device_get_instance_private (device);
FpFingerStatusFlags finger_status = priv->finger_status;
finger_status |= added_status;
finger_status &= ~removed_status;
return fpi_device_report_finger_status (device, finger_status);
}

View file

@ -255,4 +255,10 @@ void fpi_device_identify_report (FpDevice *device,
FpPrint *print, FpPrint *print,
GError *error); GError *error);
gboolean fpi_device_report_finger_status (FpDevice *device,
FpFingerStatusFlags finger_status);
gboolean fpi_device_report_finger_status_changes (FpDevice *device,
FpFingerStatusFlags added_status,
FpFingerStatusFlags removed_status);
G_END_DECLS G_END_DECLS

View file

@ -178,6 +178,15 @@ test_device_get_scan_type (void)
g_assert_cmpint (fp_device_get_scan_type (tctx->device), ==, FP_SCAN_TYPE_SWIPE); g_assert_cmpint (fp_device_get_scan_type (tctx->device), ==, FP_SCAN_TYPE_SWIPE);
} }
static void
test_device_get_finger_status (void)
{
g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_imgdev ();
fp_device_open_sync (tctx->device, NULL, NULL);
g_assert_cmpint (fp_device_get_finger_status (tctx->device), ==, FP_FINGER_STATUS_NONE);
}
static void static void
test_device_get_nr_enroll_stages (void) test_device_get_nr_enroll_stages (void)
{ {
@ -229,6 +238,7 @@ main (int argc, char *argv[])
g_test_add_func ("/device/sync/get_device_id", test_device_get_device_id); 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_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_scan_type", test_device_get_scan_type);
g_test_add_func ("/device/sync/get_finger_status", test_device_get_finger_status);
g_test_add_func ("/device/sync/get_nr_enroll_stages", test_device_get_nr_enroll_stages); 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_identify", test_device_supports_identify);
g_test_add_func ("/device/sync/supports_capture", test_device_supports_capture); g_test_add_func ("/device/sync/supports_capture", test_device_supports_capture);

View file

@ -200,6 +200,147 @@ test_driver_set_scan_type_swipe (void)
g_assert_cmpstr (pspec->name, ==, "scan-type"); g_assert_cmpstr (pspec->name, ==, "scan-type");
} }
static void
test_driver_finger_status_inactive (void)
{
g_autoptr(FpDevice) device = g_object_new (FPI_TYPE_DEVICE_FAKE, NULL);
FpiDeviceFake *fake_dev = FPI_DEVICE_FAKE (device);
g_signal_connect (device, "notify::finger-status", G_CALLBACK (on_device_notify), NULL);
g_assert_false (fpi_device_report_finger_status (device, FP_FINGER_STATUS_NONE));
g_assert_cmpuint (fp_device_get_finger_status (device), ==, FP_FINGER_STATUS_NONE);
g_assert (fake_dev->last_called_function != on_device_notify);
g_assert_null (g_steal_pointer (&fake_dev->user_data));
}
static void
test_driver_finger_status_needed (void)
{
g_autoptr(FpDevice) device = g_object_new (FPI_TYPE_DEVICE_FAKE, NULL);
g_autoptr(GParamSpec) pspec = NULL;
FpiDeviceFake *fake_dev = FPI_DEVICE_FAKE (device);
g_signal_connect (device, "notify::finger-status", G_CALLBACK (on_device_notify), NULL);
g_assert_true (fpi_device_report_finger_status (device, FP_FINGER_STATUS_NEEDED));
g_assert_cmpuint (fp_device_get_finger_status (device), ==, FP_FINGER_STATUS_NEEDED);
g_assert (fake_dev->last_called_function == on_device_notify);
pspec = g_steal_pointer (&fake_dev->user_data);
g_assert_cmpstr (pspec->name, ==, "finger-status");
fake_dev->last_called_function = NULL;
g_assert_false (fpi_device_report_finger_status (device, FP_FINGER_STATUS_NEEDED));
g_assert_null (fake_dev->last_called_function);
g_assert_null (g_steal_pointer (&fake_dev->user_data));
}
static void
test_driver_finger_status_present (void)
{
g_autoptr(FpDevice) device = g_object_new (FPI_TYPE_DEVICE_FAKE, NULL);
g_autoptr(GParamSpec) pspec = NULL;
FpiDeviceFake *fake_dev = FPI_DEVICE_FAKE (device);
g_signal_connect (device, "notify::finger-status", G_CALLBACK (on_device_notify), NULL);
g_assert_true (fpi_device_report_finger_status (device, FP_FINGER_STATUS_PRESENT));
g_assert_cmpuint (fp_device_get_finger_status (device), ==, FP_FINGER_STATUS_PRESENT);
g_assert (fake_dev->last_called_function == on_device_notify);
pspec = g_steal_pointer (&fake_dev->user_data);
g_assert_cmpstr (pspec->name, ==, "finger-status");
fake_dev->last_called_function = NULL;
g_assert_false (fpi_device_report_finger_status (device, FP_FINGER_STATUS_PRESENT));
g_assert_null (fake_dev->last_called_function);
g_assert_null (g_steal_pointer (&fake_dev->user_data));
}
static void
driver_finger_status_changes_check (FpDevice *device, gboolean add)
{
FpiDeviceFake *fake_dev = FPI_DEVICE_FAKE (device);
g_autoptr(GFlagsClass) status_class = g_type_class_ref (FP_TYPE_FINGER_STATUS_FLAGS);
guint expected_status;
guint initial_value;
guint i;
gulong signal_id;
if (add)
initial_value = FP_FINGER_STATUS_NONE;
else
initial_value = status_class->mask;
g_assert_cmpuint (fp_device_get_finger_status (device), ==, initial_value);
signal_id = g_signal_connect (device, "notify::finger-status",
G_CALLBACK (on_device_notify), NULL);
for (i = 0, expected_status = initial_value; i < status_class->n_values; ++i)
{
g_autoptr(GParamSpec) pspec = NULL;
FpFingerStatusFlags finger_status = status_class->values[i].value;
FpFingerStatusFlags added_status = add ? finger_status : FP_FINGER_STATUS_NONE;
FpFingerStatusFlags removed_status = add ? FP_FINGER_STATUS_NONE : finger_status;
gboolean ret;
fake_dev->last_called_function = NULL;
ret = fpi_device_report_finger_status_changes (device,
added_status,
removed_status);
if (finger_status != FP_FINGER_STATUS_NONE)
g_assert_true (ret);
else
g_assert_false (ret);
expected_status |= added_status;
expected_status &= ~removed_status;
g_assert_cmpuint (fp_device_get_finger_status (device), ==, expected_status);
if (finger_status != FP_FINGER_STATUS_NONE)
{
g_assert (fake_dev->last_called_function == on_device_notify);
pspec = g_steal_pointer (&fake_dev->user_data);
g_assert_cmpstr (pspec->name, ==, "finger-status");
}
fake_dev->last_called_function = NULL;
g_assert_false (fpi_device_report_finger_status_changes (device,
added_status,
removed_status));
g_assert_null (fake_dev->last_called_function);
g_assert_null (g_steal_pointer (&fake_dev->user_data));
}
if (add)
g_assert_cmpuint (fp_device_get_finger_status (device), ==, status_class->mask);
else
g_assert_cmpuint (fp_device_get_finger_status (device), ==, FP_FINGER_STATUS_NONE);
fake_dev->last_called_function = NULL;
g_assert_false (fpi_device_report_finger_status_changes (device,
FP_FINGER_STATUS_NONE,
FP_FINGER_STATUS_NONE));
g_assert_null (fake_dev->last_called_function);
g_assert_null (g_steal_pointer (&fake_dev->user_data));
g_signal_handler_disconnect (device, signal_id);
}
static void
test_driver_finger_status_changes (void)
{
g_autoptr(FpDevice) device = g_object_new (FPI_TYPE_DEVICE_FAKE, NULL);
driver_finger_status_changes_check (device, TRUE);
driver_finger_status_changes_check (device, FALSE);
}
static void static void
test_driver_get_nr_enroll_stages (void) test_driver_get_nr_enroll_stages (void)
{ {
@ -2207,6 +2348,10 @@ main (int argc, char *argv[])
g_test_add_func ("/driver/get_scan_type/swipe", test_driver_get_scan_type_swipe); g_test_add_func ("/driver/get_scan_type/swipe", test_driver_get_scan_type_swipe);
g_test_add_func ("/driver/set_scan_type/press", test_driver_set_scan_type_press); g_test_add_func ("/driver/set_scan_type/press", test_driver_set_scan_type_press);
g_test_add_func ("/driver/set_scan_type/swipe", test_driver_set_scan_type_swipe); g_test_add_func ("/driver/set_scan_type/swipe", test_driver_set_scan_type_swipe);
g_test_add_func ("/driver/finger_status/inactive", test_driver_finger_status_inactive);
g_test_add_func ("/driver/finger_status/waiting", test_driver_finger_status_needed);
g_test_add_func ("/driver/finger_status/present", test_driver_finger_status_present);
g_test_add_func ("/driver/finger_status/changes", test_driver_finger_status_changes);
g_test_add_func ("/driver/get_nr_enroll_stages", test_driver_get_nr_enroll_stages); g_test_add_func ("/driver/get_nr_enroll_stages", test_driver_get_nr_enroll_stages);
g_test_add_func ("/driver/set_nr_enroll_stages", test_driver_set_nr_enroll_stages); g_test_add_func ("/driver/set_nr_enroll_stages", test_driver_set_nr_enroll_stages);
g_test_add_func ("/driver/supports_identify", test_driver_supports_identify); g_test_add_func ("/driver/supports_identify", test_driver_supports_identify);