GCC Code Coverage Report


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 92.9% 645 / 0 / 694
Functions: 100.0% 69 / 0 / 69
Branches: 71.5% 288 / 0 / 403

libfprint/fp-device.c
Line Branch Exec Source
1 /*
2 * FpDevice - A fingerprint reader device
3 * Copyright (C) 2019 Benjamin Berg <bberg@redhat.com>
4 * Copyright (C) 2019 Marco Trevisan <marco.trevisan@canonical.com>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21 #define FP_COMPONENT "device"
22 #include "fpi-log.h"
23
24 #include "fp-device-private.h"
25
26 /**
27 * SECTION: fp-device
28 * @title: FpDevice
29 * @short_description: Fingerpint device routines
30 *
31 * These are the public #FpDevice routines.
32 */
33
34 static void fp_device_async_initable_iface_init (GAsyncInitableIface *iface);
35
36
4/6
fp_device_class_intern_init:
✓ Branch 3 → 4 taken 128 times.
✗ Branch 3 → 5 not taken.
fp_device_get_type:
✓ Branch 2 → 3 taken 128 times.
✓ Branch 2 → 7 taken 1695827 times.
✓ Branch 4 → 5 taken 128 times.
✗ Branch 4 → 7 not taken.
1709064 G_DEFINE_TYPE_EXTENDED (FpDevice, fp_device, G_TYPE_OBJECT, G_TYPE_FLAG_ABSTRACT,
37 G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_INITABLE,
38 fp_device_async_initable_iface_init)
39 G_ADD_PRIVATE (FpDevice))
40
41 enum {
42 PROP_0,
43 PROP_DRIVER,
44 PROP_DEVICE_ID,
45 PROP_NAME,
46 PROP_OPEN,
47 PROP_REMOVED,
48 PROP_NR_ENROLL_STAGES,
49 PROP_SCAN_TYPE,
50 PROP_FINGER_STATUS,
51 PROP_TEMPERATURE,
52 PROP_FPI_ENVIRON,
53 PROP_FPI_USB_DEVICE,
54 PROP_FPI_UDEV_DATA_SPIDEV,
55 PROP_FPI_UDEV_DATA_HIDRAW,
56 PROP_FPI_DRIVER_DATA,
57 N_PROPS
58 };
59
60 static GParamSpec *properties[N_PROPS];
61
62 enum {
63 REMOVED_SIGNAL,
64 N_SIGNALS
65 };
66
67 static guint signals[N_SIGNALS] = { 0, };
68
69 /**
70 * fp_device_retry_quark:
71 *
72 * Return value: Quark representing a retryable error.
73 **/
74
2/2
✓ Branch 2 → 3 taken 50 times.
✓ Branch 2 → 5 taken 396 times.
446 G_DEFINE_QUARK (fp - device - retry - quark, fp_device_retry)
75
76 /**
77 * fp_device_error_quark:
78 *
79 * Return value: Quark representing a device error.
80 **/
81
2/2
✓ Branch 2 → 3 taken 56 times.
✓ Branch 2 → 5 taken 301 times.
357 G_DEFINE_QUARK (fp - device - error - quark, fp_device_error)
82
83 static gboolean
84 12 fp_device_cancel_in_idle_cb (gpointer user_data)
85 {
86 12 FpDevice *self = user_data;
87
1/2
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 4 taken 12 times.
12 FpDeviceClass *cls = FP_DEVICE_GET_CLASS (self);
88 12 FpDevicePrivate *priv = fp_device_get_instance_private (self);
89
90
1/2
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 4 taken 12 times.
12 g_assert (cls->cancel);
91
1/2
✓ Branch 4 → 5 taken 12 times.
✗ Branch 4 → 7 not taken.
12 g_assert (priv->current_action != FPI_DEVICE_ACTION_NONE);
92
93 12 g_debug ("Idle cancelling on ongoing operation!");
94
95 12 priv->current_idle_cancel_source = NULL;
96
97
2/2
✓ Branch 6 → 8 taken 1 time.
✓ Branch 6 → 9 taken 11 times.
12 if (priv->critical_section)
98 1 priv->cancel_queued = TRUE;
99 else
100 11 cls->cancel (self);
101
102 12 fpi_device_report_finger_status (self, FP_FINGER_STATUS_NONE);
103
104 12 return G_SOURCE_REMOVE;
105 }
106
107 /* Notify the class that the task was cancelled; this should be connected
108 * with the GTask as the user_data object for automatic cleanup together
109 * with the task. */
110 static void
111 16 fp_device_cancelled_cb (GCancellable *cancellable, FpDevice *self)
112 {
113 16 FpDevicePrivate *priv = fp_device_get_instance_private (self);
114
115 16 priv->current_idle_cancel_source = g_idle_source_new ();
116 16 g_source_set_callback (priv->current_idle_cancel_source,
117 fp_device_cancel_in_idle_cb,
118 self,
119 NULL);
120 16 g_source_attach (priv->current_idle_cancel_source,
121 g_task_get_context (priv->current_task));
122 16 g_source_unref (priv->current_idle_cancel_source);
123 16 }
124
125 /* Forward the external task cancellable to the internal one. */
126 static void
127 12 fp_device_task_cancelled_cb (GCancellable *cancellable, FpDevice *self)
128 {
129 12 FpDevicePrivate *priv = fp_device_get_instance_private (self);
130
131 12 g_cancellable_cancel (priv->current_cancellable);
132 12 }
133
134 static void
135 925 setup_task_cancellable (FpDevice *device)
136 {
137 925 FpDevicePrivate *priv = fp_device_get_instance_private (device);
138 925 FpDeviceClass *cls = FP_DEVICE_GET_CLASS (device);
139
140 /* Create an internal cancellable and hook it up. */
141 925 priv->current_cancellable = g_cancellable_new ();
142
2/2
✓ Branch 3 → 4 taken 861 times.
✓ Branch 3 → 6 taken 64 times.
925 if (cls->cancel)
143 {
144 861 priv->current_cancellable_id = g_cancellable_connect (priv->current_cancellable,
145 G_CALLBACK (fp_device_cancelled_cb),
146 device,
147 NULL);
148 }
149
150 /* Task cancellable is the externally visible one, make our internal one
151 * a slave of the external one. */
152
2/2
✓ Branch 7 → 8 taken 179 times.
✓ Branch 7 → 11 taken 746 times.
925 if (g_task_get_cancellable (priv->current_task))
153 {
154 179 priv->current_task_cancellable_id = g_cancellable_connect (g_task_get_cancellable (priv->current_task),
155 G_CALLBACK (fp_device_task_cancelled_cb),
156 device,
157 NULL);
158 }
159 925 }
160
161 static void
162 259 fp_device_constructed (GObject *object)
163 {
164 259 FpDevice *self = (FpDevice *) object;
165
1/2
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 4 taken 259 times.
259 FpDeviceClass *cls = FP_DEVICE_GET_CLASS (self);
166 259 FpDevicePrivate *priv = fp_device_get_instance_private (self);
167
168
1/2
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 4 taken 259 times.
259 g_assert (cls->features != FP_DEVICE_FEATURE_NONE);
169
170 259 priv->type = cls->type;
171
1/2
✓ Branch 4 → 5 taken 259 times.
✗ Branch 4 → 6 not taken.
259 if (cls->nr_enroll_stages)
172 259 priv->nr_enroll_stages = cls->nr_enroll_stages;
173 259 priv->scan_type = cls->scan_type;
174 259 priv->features = cls->features;
175
1/2
✗ Branch 6 → 7 not taken.
✓ Branch 6 → 8 taken 259 times.
259 priv->device_name = g_strdup (cls->full_name);
176 259 priv->device_id = g_strdup ("0");
177
178
2/2
✓ Branch 15 → 16 taken 1 time.
✓ Branch 15 → 18 taken 258 times.
259 if (cls->temp_hot_seconds > 0)
179 {
180 1 priv->temp_hot_seconds = cls->temp_hot_seconds;
181 1 priv->temp_cold_seconds = cls->temp_cold_seconds;
182
1/2
✗ Branch 16 → 17 not taken.
✓ Branch 16 → 21 taken 1 time.
1 g_assert (priv->temp_cold_seconds > 0);
183 }
184
2/2
✓ Branch 18 → 19 taken 248 times.
✓ Branch 18 → 20 taken 10 times.
258 else if (cls->temp_hot_seconds == 0)
185 {
186 248 priv->temp_hot_seconds = DEFAULT_TEMP_HOT_SECONDS;
187 248 priv->temp_cold_seconds = DEFAULT_TEMP_COLD_SECONDS;
188 }
189 else
190 {
191 /* Temperature management disabled */
192 10 priv->temp_hot_seconds = -1;
193 10 priv->temp_cold_seconds = -1;
194 }
195
196 /* Start out at not completely cold (i.e. assume we are only at the upper
197 * bound of COLD).
198 * To be fair, the warm-up from 0 to WARM should be really short either way.
199 *
200 * Note that a call to fpi_device_update_temp() is not needed here as no
201 * timeout must be registered.
202 */
203 259 priv->temp_current = FP_TEMPERATURE_COLD;
204 259 priv->temp_current_ratio = TEMP_COLD_THRESH;
205 259 priv->temp_last_update = g_get_monotonic_time ();
206 259 priv->temp_last_active = FALSE;
207
208 259 G_OBJECT_CLASS (fp_device_parent_class)->constructed (object);
209 259 }
210
211 static void
212 251 fp_device_finalize (GObject *object)
213 {
214 251 FpDevice *self = (FpDevice *) object;
215 251 FpDevicePrivate *priv = fp_device_get_instance_private (self);
216
217
1/2
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 4 taken 251 times.
251 g_assert (priv->current_action == FPI_DEVICE_ACTION_NONE);
218
1/2
✓ Branch 4 → 5 taken 251 times.
✗ Branch 4 → 6 not taken.
251 g_assert (priv->current_task == NULL);
219
1/2
✗ Branch 5 → 7 not taken.
✓ Branch 5 → 8 taken 251 times.
251 if (priv->is_open)
220 g_warning ("User destroyed open device! Not cleaning up properly!");
221
222
2/2
✓ Branch 8 → 9 taken 75 times.
✓ Branch 8 → 10 taken 176 times.
251 g_clear_pointer (&priv->temp_timeout, g_source_destroy);
223
224
1/2
✗ Branch 10 → 11 not taken.
✓ Branch 10 → 12 taken 251 times.
251 g_clear_slist (&priv->sources, (GDestroyNotify) g_source_destroy);
225
226
1/2
✗ Branch 12 → 13 not taken.
✓ Branch 12 → 14 taken 251 times.
251 g_clear_pointer (&priv->current_idle_cancel_source, g_source_destroy);
227
1/2
✗ Branch 14 → 15 not taken.
✓ Branch 14 → 16 taken 251 times.
251 g_clear_pointer (&priv->current_task_idle_return_source, g_source_destroy);
228
1/2
✗ Branch 16 → 17 not taken.
✓ Branch 16 → 18 taken 251 times.
251 g_clear_pointer (&priv->critical_section_flush_source, g_source_destroy);
229
230
1/2
✓ Branch 18 → 19 taken 251 times.
✗ Branch 18 → 20 not taken.
251 g_clear_pointer (&priv->device_id, g_free);
231
1/2
✓ Branch 20 → 21 taken 251 times.
✗ Branch 20 → 22 not taken.
251 g_clear_pointer (&priv->device_name, g_free);
232
233
2/2
✓ Branch 22 → 23 taken 29 times.
✓ Branch 22 → 24 taken 222 times.
251 g_clear_object (&priv->usb_device);
234
2/2
✓ Branch 24 → 25 taken 108 times.
✓ Branch 24 → 26 taken 143 times.
251 g_clear_pointer (&priv->virtual_env, g_free);
235
2/2
✓ Branch 26 → 27 taken 1 time.
✓ Branch 26 → 28 taken 250 times.
251 g_clear_pointer (&priv->udev_data.spidev_path, g_free);
236
2/2
✓ Branch 28 → 29 taken 1 time.
✓ Branch 28 → 30 taken 250 times.
251 g_clear_pointer (&priv->udev_data.hidraw_path, g_free);
237
238 251 G_OBJECT_CLASS (fp_device_parent_class)->finalize (object);
239 251 }
240
241 static void
242 182 fp_device_get_property (GObject *object,
243 guint prop_id,
244 GValue *value,
245 GParamSpec *pspec)
246 {
247 182 FpDevice *self = FP_DEVICE (object);
248 182 FpDevicePrivate *priv = fp_device_get_instance_private (self);
249
9/13
✓ Branch 2 → 3 taken 1 time.
✓ Branch 2 → 5 taken 1 time.
✓ Branch 2 → 7 taken 3 times.
✗ Branch 2 → 9 not taken.
✓ Branch 2 → 11 taken 1 time.
✓ Branch 2 → 13 taken 1 time.
✓ Branch 2 → 15 taken 1 time.
✓ Branch 2 → 17 taken 8 times.
✓ Branch 2 → 19 taken 165 times.
✓ Branch 2 → 21 taken 1 time.
✗ Branch 2 → 23 not taken.
✗ Branch 2 → 26 not taken.
✗ Branch 2 → 29 not taken.
182 FpDeviceClass *cls = FP_DEVICE_GET_CLASS (self);
250
251
9/13
✓ Branch 2 → 3 taken 1 time.
✓ Branch 2 → 5 taken 1 time.
✓ Branch 2 → 7 taken 3 times.
✗ Branch 2 → 9 not taken.
✓ Branch 2 → 11 taken 1 time.
✓ Branch 2 → 13 taken 1 time.
✓ Branch 2 → 15 taken 1 time.
✓ Branch 2 → 17 taken 8 times.
✓ Branch 2 → 19 taken 165 times.
✓ Branch 2 → 21 taken 1 time.
✗ Branch 2 → 23 not taken.
✗ Branch 2 → 26 not taken.
✗ Branch 2 → 29 not taken.
182 switch (prop_id)
252 {
253 1 case PROP_NR_ENROLL_STAGES:
254 1 g_value_set_uint (value, priv->nr_enroll_stages);
255 1 break;
256
257 1 case PROP_SCAN_TYPE:
258 1 g_value_set_enum (value, priv->scan_type);
259 1 break;
260
261 3 case PROP_FINGER_STATUS:
262 3 g_value_set_flags (value, priv->finger_status);
263 3 break;
264
265 case PROP_TEMPERATURE:
266 g_value_set_enum (value, priv->temp_current);
267 break;
268
269 case PROP_DRIVER:
270 1 g_value_set_static_string (value, FP_DEVICE_GET_CLASS (self)->id);
271 1 break;
272
273 1 case PROP_DEVICE_ID:
274 1 g_value_set_string (value, priv->device_id);
275 1 break;
276
277 1 case PROP_NAME:
278 1 g_value_set_string (value, priv->device_name);
279 1 break;
280
281 8 case PROP_OPEN:
282 8 g_value_set_boolean (value, priv->is_open);
283 8 break;
284
285 165 case PROP_REMOVED:
286 165 g_value_set_boolean (value, priv->is_removed);
287 165 break;
288
289 1 case PROP_FPI_USB_DEVICE:
290 1 g_value_set_object (value, priv->usb_device);
291 1 break;
292
293 case PROP_FPI_UDEV_DATA_SPIDEV:
294 if (cls->type == FP_DEVICE_TYPE_UDEV)
295 g_value_set_string (value, priv->udev_data.spidev_path);
296 else
297 g_value_set_string (value, NULL);
298 break;
299
300 case PROP_FPI_UDEV_DATA_HIDRAW:
301 if (cls->type == FP_DEVICE_TYPE_UDEV)
302 g_value_set_string (value, priv->udev_data.hidraw_path);
303 else
304 g_value_set_string (value, NULL);
305 break;
306
307 default:
308 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
309 }
310 182 }
311
312 static void
313 1295 fp_device_set_property (GObject *object,
314 guint prop_id,
315 const GValue *value,
316 GParamSpec *pspec)
317 {
318 1295 FpDevice *self = FP_DEVICE (object);
319 1295 FpDevicePrivate *priv = fp_device_get_instance_private (self);
320
5/6
✓ Branch 2 → 3 taken 259 times.
✓ Branch 2 → 9 taken 259 times.
✓ Branch 2 → 15 taken 259 times.
✓ Branch 2 → 21 taken 259 times.
✓ Branch 2 → 27 taken 259 times.
✗ Branch 2 → 29 not taken.
1295 FpDeviceClass *cls = FP_DEVICE_GET_CLASS (self);
321
322 /* _construct has not run yet, so we cannot use priv->type. */
323
5/6
✓ Branch 2 → 3 taken 259 times.
✓ Branch 2 → 9 taken 259 times.
✓ Branch 2 → 15 taken 259 times.
✓ Branch 2 → 21 taken 259 times.
✓ Branch 2 → 27 taken 259 times.
✗ Branch 2 → 29 not taken.
1295 switch (prop_id)
324 {
325 259 case PROP_FPI_ENVIRON:
326
2/2
✓ Branch 3 → 4 taken 227 times.
✓ Branch 3 → 6 taken 32 times.
259 if (cls->type == FP_DEVICE_TYPE_VIRTUAL)
327 227 priv->virtual_env = g_value_dup_string (value);
328 else
329
1/2
✗ Branch 7 → 8 not taken.
✓ Branch 7 → 32 taken 32 times.
32 g_assert (g_value_get_string (value) == NULL);
330 break;
331
332 259 case PROP_FPI_USB_DEVICE:
333
2/2
✓ Branch 9 → 10 taken 31 times.
✓ Branch 9 → 12 taken 228 times.
259 if (cls->type == FP_DEVICE_TYPE_USB)
334 31 priv->usb_device = g_value_dup_object (value);
335 else
336
1/2
✗ Branch 13 → 14 not taken.
✓ Branch 13 → 32 taken 228 times.
228 g_assert (g_value_get_object (value) == NULL);
337 break;
338
339 259 case PROP_FPI_UDEV_DATA_SPIDEV:
340
2/2
✓ Branch 15 → 16 taken 1 time.
✓ Branch 15 → 18 taken 258 times.
259 if (cls->type == FP_DEVICE_TYPE_UDEV)
341 1 priv->udev_data.spidev_path = g_value_dup_string (value);
342 else
343
1/2
✗ Branch 19 → 20 not taken.
✓ Branch 19 → 32 taken 258 times.
258 g_assert (g_value_get_string (value) == NULL);
344 break;
345
346 259 case PROP_FPI_UDEV_DATA_HIDRAW:
347
2/2
✓ Branch 21 → 22 taken 1 time.
✓ Branch 21 → 24 taken 258 times.
259 if (cls->type == FP_DEVICE_TYPE_UDEV)
348 1 priv->udev_data.hidraw_path = g_value_dup_string (value);
349 else
350
1/2
✗ Branch 25 → 26 not taken.
✓ Branch 25 → 32 taken 258 times.
258 g_assert (g_value_get_string (value) == NULL);
351 break;
352
353 259 case PROP_FPI_DRIVER_DATA:
354 259 priv->driver_data = g_value_get_uint64 (value);
355 259 break;
356
357 default:
358 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
359 }
360 1295 }
361
362 static void
363 150 device_idle_probe_cb (FpDevice *self, gpointer user_data)
364 {
365 /* This should not be an idle handler, see comment where it is registered.
366 *
367 * This effectively disables USB "persist" for us, and possibly turns off
368 * USB wakeup if it was enabled for some reason.
369 */
370 150 fpi_device_configure_wakeup (self, FALSE);
371
372
2/2
✓ Branch 3 → 4 taken 90 times.
✓ Branch 3 → 5 taken 60 times.
150 if (!FP_DEVICE_GET_CLASS (self)->probe)
373 90 fpi_device_probe_complete (self, NULL, NULL, NULL);
374 else
375 60 FP_DEVICE_GET_CLASS (self)->probe (self);
376
377 150 return;
378 }
379
380 static void
381 150 fp_device_async_initable_init_async (GAsyncInitable *initable,
382 int io_priority,
383 GCancellable *cancellable,
384 GAsyncReadyCallback callback,
385 gpointer user_data)
386 {
387 150 g_autoptr(GTask) task = NULL;
388 150 FpDevice *self = FP_DEVICE (initable);
389 150 FpDevicePrivate *priv = fp_device_get_instance_private (self);
390
391 /* It is next to impossible to call async_init at the wrong time. */
392
1/2
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 4 taken 150 times.
150 g_assert (!priv->is_open);
393
1/2
✓ Branch 4 → 5 taken 150 times.
✗ Branch 4 → 8 not taken.
150 g_assert (!priv->current_task);
394
395 150 task = g_task_new (self, cancellable, callback, user_data);
396
1/2
✗ Branch 7 → 9 not taken.
✓ Branch 7 → 11 taken 150 times.
150 if (g_task_return_error_if_cancelled (task))
397 return;
398
399 150 priv->current_action = FPI_DEVICE_ACTION_PROBE;
400 150 priv->current_task = g_steal_pointer (&task);
401 150 setup_task_cancellable (self);
402
403 /* We push this into an idle handler for compatibility with libgusb
404 * 0.3.7 and before.
405 * See https://github.com/hughsie/libgusb/pull/50
406 */
407 150 g_source_set_name (fpi_device_add_timeout (self, 0, device_idle_probe_cb, NULL, NULL),
408 "libusb probe in idle");
409 }
410
411 static gboolean
412 148 fp_device_async_initable_init_finish (GAsyncInitable *initable,
413 GAsyncResult *res,
414 GError **error)
415 {
416 148 return g_task_propagate_boolean (G_TASK (res), error);
417 }
418
419 static void
420 128 fp_device_async_initable_iface_init (GAsyncInitableIface *iface)
421 {
422 128 iface->init_async = fp_device_async_initable_init_async;
423 128 iface->init_finish = fp_device_async_initable_init_finish;
424 128 }
425
426 static void
427 128 fp_device_class_init (FpDeviceClass *klass)
428 {
429 128 GObjectClass *object_class = G_OBJECT_CLASS (klass);
430
431 128 object_class->constructed = fp_device_constructed;
432 128 object_class->finalize = fp_device_finalize;
433 128 object_class->get_property = fp_device_get_property;
434 128 object_class->set_property = fp_device_set_property;
435
436 256 properties[PROP_NR_ENROLL_STAGES] =
437 128 g_param_spec_uint ("nr-enroll-stages",
438 "EnrollStages",
439 "Number of enroll stages needed on the device",
440 0, G_MAXUINT,
441 0,
442 G_PARAM_STATIC_STRINGS | G_PARAM_READABLE);
443
444 256 properties[PROP_SCAN_TYPE] =
445 128 g_param_spec_enum ("scan-type",
446 "ScanType",
447 "The scan type of the device",
448 FP_TYPE_SCAN_TYPE, FP_SCAN_TYPE_SWIPE,
449 G_PARAM_STATIC_STRINGS | G_PARAM_READABLE);
450
451 256 properties[PROP_FINGER_STATUS] =
452 128 g_param_spec_flags ("finger-status",
453 "FingerStatus",
454 "The status of the finger",
455 FP_TYPE_FINGER_STATUS_FLAGS, FP_FINGER_STATUS_NONE,
456 G_PARAM_STATIC_STRINGS | G_PARAM_READABLE);
457
458 256 properties[PROP_TEMPERATURE] =
459 128 g_param_spec_enum ("temperature",
460 "Temperature",
461 "The temperature estimation for device to prevent overheating.",
462 FP_TYPE_TEMPERATURE, FP_TEMPERATURE_COLD,
463 G_PARAM_STATIC_STRINGS | G_PARAM_READABLE);
464
465 256 properties[PROP_DRIVER] =
466 128 g_param_spec_string ("driver",
467 "Driver",
468 "String describing the driver",
469 NULL,
470 G_PARAM_STATIC_STRINGS | G_PARAM_READABLE);
471
472 256 properties[PROP_DEVICE_ID] =
473 128 g_param_spec_string ("device-id",
474 "Device ID",
475 "String describing the device, often generic but may be a serial number",
476 "",
477 G_PARAM_STATIC_STRINGS | G_PARAM_READABLE);
478
479 256 properties[PROP_NAME] =
480 128 g_param_spec_string ("name",
481 "Device Name",
482 "Human readable name for the device",
483 NULL,
484 G_PARAM_STATIC_STRINGS | G_PARAM_READABLE);
485
486 /**
487 * FpDevice:open: (getter is_open):
488 */
489 256 properties[PROP_OPEN] =
490 128 g_param_spec_boolean ("open",
491 "Opened",
492 "Whether the device is open or not", FALSE,
493 G_PARAM_STATIC_STRINGS | G_PARAM_READABLE);
494
495 256 properties[PROP_REMOVED] =
496 128 g_param_spec_boolean ("removed",
497 "Removed",
498 "Whether the device has been removed from the system", FALSE,
499 G_PARAM_STATIC_STRINGS | G_PARAM_READABLE);
500
501 /**
502 * FpDevice::removed:
503 * @device: the #FpDevice instance that emitted the signal
504 *
505 * This signal is emitted after the device has been removed and no operation
506 * is pending anymore.
507 *
508 * The API user is still required to close a removed device. The above
509 * guarantee means that the call to close the device can be made immediately
510 * from the signal handler.
511 *
512 * The close operation will return FP_DEVICE_ERROR_REMOVED, but the device
513 * will still be considered closed afterwards.
514 *
515 * The device will only be removed from the #FpContext after it has been
516 * closed by the API user.
517 **/
518 128 signals[REMOVED_SIGNAL] = g_signal_new ("removed",
519 G_TYPE_FROM_CLASS (klass),
520 G_SIGNAL_RUN_LAST,
521 0,
522 NULL,
523 NULL,
524 g_cclosure_marshal_VOID__VOID,
525 G_TYPE_NONE,
526 0);
527
528 /* Private properties */
529
530 /**
531 * FpDevice::fpi-environ: (skip)
532 *
533 * This property is only for internal purposes.
534 *
535 * Stability: private
536 */
537 256 properties[PROP_FPI_ENVIRON] =
538 128 g_param_spec_string ("fpi-environ",
539 "Virtual Environment",
540 "Private: The environment variable for the virtual device",
541 NULL,
542 G_PARAM_STATIC_STRINGS | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY);
543
544 /**
545 * FpDevice::fpi-usb-device: (skip)
546 *
547 * This property is only for internal purposes.
548 *
549 * Stability: private
550 */
551 256 properties[PROP_FPI_USB_DEVICE] =
552 128 g_param_spec_object ("fpi-usb-device",
553 "USB Device",
554 "Private: The USB device for the device",
555 G_USB_TYPE_DEVICE,
556 G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
557 /**
558 * FpDevice::fpi-udev-data-spidev: (skip)
559 *
560 * This property is only for internal purposes.
561 *
562 * Stability: private
563 */
564 256 properties[PROP_FPI_UDEV_DATA_SPIDEV] =
565 128 g_param_spec_string ("fpi-udev-data-spidev",
566 "Udev data: spidev path",
567 "Private: The path to /dev/spidevN.M",
568 NULL,
569 G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
570 /**
571 * FpDevice::fpi-udev-data-hidraw: (skip)
572 *
573 * This property is only for internal purposes.
574 *
575 * Stability: private
576 */
577 256 properties[PROP_FPI_UDEV_DATA_HIDRAW] =
578 128 g_param_spec_string ("fpi-udev-data-hidraw",
579 "Udev data: hidraw path",
580 "Private: The path to /dev/hidrawN",
581 NULL,
582 G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
583
584 /**
585 * FpDevice::fpi-driver-data: (skip)
586 *
587 * This property is only for internal purposes.
588 *
589 * Stability: private
590 */
591 256 properties[PROP_FPI_DRIVER_DATA] =
592 128 g_param_spec_uint64 ("fpi-driver-data",
593 "Driver Data",
594 "Private: The driver data from the ID table entry",
595 0,
596 G_MAXUINT64,
597 0,
598 G_PARAM_STATIC_STRINGS | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY);
599
600 128 g_object_class_install_properties (object_class, N_PROPS, properties);
601 128 }
602
603 static void
604 259 fp_device_init (FpDevice *self)
605 {
606 259 }
607
608 /**
609 * fp_device_get_driver:
610 * @device: A #FpDevice
611 *
612 * Returns: (transfer none): The ID of the driver
613 */
614 const gchar *
615 27798 fp_device_get_driver (FpDevice *device)
616 {
617
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 27798 times.
27798 g_return_val_if_fail (FP_IS_DEVICE (device), NULL);
618
619 27798 return FP_DEVICE_GET_CLASS (device)->id;
620 }
621
622 /**
623 * fp_device_get_device_id:
624 * @device: A #FpDevice
625 *
626 * Returns: (transfer none): The ID of the device
627 */
628 const gchar *
629 6363 fp_device_get_device_id (FpDevice *device)
630 {
631 6363 FpDevicePrivate *priv = fp_device_get_instance_private (device);
632
633
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 6363 times.
6363 g_return_val_if_fail (FP_IS_DEVICE (device), NULL);
634
635 6363 return priv->device_id;
636 }
637
638 /**
639 * fp_device_get_name:
640 * @device: A #FpDevice
641 *
642 * Returns: (transfer none): The human readable name of the device
643 */
644 const gchar *
645 193 fp_device_get_name (FpDevice *device)
646 {
647 193 FpDevicePrivate *priv = fp_device_get_instance_private (device);
648
649
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 193 times.
193 g_return_val_if_fail (FP_IS_DEVICE (device), NULL);
650
651 193 return priv->device_name;
652 }
653
654 /**
655 * fp_device_is_open:
656 * @device: A #FpDevice
657 *
658 * Returns: Whether the device is open or not
659 */
660 gboolean
661 504 fp_device_is_open (FpDevice *device)
662 {
663 504 FpDevicePrivate *priv = fp_device_get_instance_private (device);
664
665
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 504 times.
504 g_return_val_if_fail (FP_IS_DEVICE (device), FALSE);
666
667 504 return priv->is_open;
668 }
669
670 /**
671 * fp_device_get_scan_type:
672 * @device: A #FpDevice
673 *
674 * Retrieves the scan type of the device.
675 *
676 * Returns: The #FpScanType
677 */
678 FpScanType
679 14 fp_device_get_scan_type (FpDevice *device)
680 {
681 14 FpDevicePrivate *priv = fp_device_get_instance_private (device);
682
683
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 14 times.
14 g_return_val_if_fail (FP_IS_DEVICE (device), FP_SCAN_TYPE_SWIPE);
684
685 14 return priv->scan_type;
686 }
687
688 /**
689 * fp_device_get_finger_status:
690 * @device: A #FpDevice
691 *
692 * Retrieves the finger status flags for the device.
693 * This can be used by the UI to present the relevant feedback, although it
694 * is not guaranteed to be a relevant value when not performing any action.
695 *
696 * Returns: The current #FpFingerStatusFlags
697 */
698 FpFingerStatusFlags
699 874 fp_device_get_finger_status (FpDevice *device)
700 {
701 874 FpDevicePrivate *priv = fp_device_get_instance_private (device);
702
703
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 874 times.
874 g_return_val_if_fail (FP_IS_DEVICE (device), FP_FINGER_STATUS_NONE);
704
705 874 return priv->finger_status;
706 }
707
708 /**
709 * fp_device_get_nr_enroll_stages:
710 * @device: A #FpDevice
711 *
712 * Retrieves the number of enroll stages for this device.
713 *
714 * Returns: The number of enroll stages
715 */
716 gint
717 519 fp_device_get_nr_enroll_stages (FpDevice *device)
718 {
719 519 FpDevicePrivate *priv = fp_device_get_instance_private (device);
720
721
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 519 times.
519 g_return_val_if_fail (FP_IS_DEVICE (device), -1);
722
723 519 return priv->nr_enroll_stages;
724 }
725
726 /**
727 * fp_device_get_temperature:
728 * @device: A #FpDevice
729 *
730 * Retrieves simple temperature information for device. It is not possible
731 * to use a device when this is #FP_TEMPERATURE_HOT.
732 *
733 * Returns: The current temperature estimation.
734 */
735 FpTemperature
736 16 fp_device_get_temperature (FpDevice *device)
737 {
738 16 FpDevicePrivate *priv = fp_device_get_instance_private (device);
739
740
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 16 times.
16 g_return_val_if_fail (FP_IS_DEVICE (device), -1);
741
742 16 return priv->temp_current;
743 }
744
745 /**
746 * fp_device_supports_identify:
747 * @device: A #FpDevice
748 *
749 * Check whether the device supports identification.
750 *
751 * Returns: Whether the device supports identification
752 * Deprecated: 1.92.0: Use fp_device_has_feature() instead.
753 */
754 gboolean
755 42 fp_device_supports_identify (FpDevice *device)
756 {
757 42 FpDeviceClass *cls = FP_DEVICE_GET_CLASS (device);
758 42 FpDevicePrivate *priv = fp_device_get_instance_private (device);
759
760
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 6 taken 42 times.
42 g_return_val_if_fail (FP_IS_DEVICE (device), FALSE);
761
762
4/4
✓ Branch 6 → 5 taken 11 times.
✓ Branch 6 → 7 taken 31 times.
✓ Branch 7 → 5 taken 1 time.
✓ Branch 7 → 8 taken 30 times.
42 return cls->identify && !!(priv->features & FP_DEVICE_FEATURE_IDENTIFY);
763 }
764
765 /**
766 * fp_device_supports_capture:
767 * @device: A #FpDevice
768 *
769 * Check whether the device supports capturing images.
770 *
771 * Returns: Whether the device supports image capture
772 * Deprecated: 1.92.0: Use fp_device_has_feature() instead.
773 */
774 gboolean
775 5 fp_device_supports_capture (FpDevice *device)
776 {
777 5 FpDeviceClass *cls = FP_DEVICE_GET_CLASS (device);
778 5 FpDevicePrivate *priv = fp_device_get_instance_private (device);
779
780
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 6 taken 5 times.
5 g_return_val_if_fail (FP_IS_DEVICE (device), FALSE);
781
782
3/4
✓ Branch 6 → 5 taken 3 times.
✓ Branch 6 → 7 taken 2 times.
✗ Branch 7 → 5 not taken.
✓ Branch 7 → 8 taken 2 times.
5 return cls->capture && !!(priv->features & FP_DEVICE_FEATURE_CAPTURE);
783 }
784
785 /**
786 * fp_device_has_storage:
787 * @device: A #FpDevice
788 *
789 * Whether the device has on-chip storage. If it has, you can list the
790 * prints stored on the with fp_device_list_prints() and you should
791 * always delete prints from the device again using
792 * fp_device_delete_print().
793 * Deprecated: 1.92.0: Use fp_device_has_feature() instead.
794 */
795 gboolean
796 6 fp_device_has_storage (FpDevice *device)
797 {
798 6 FpDevicePrivate *priv = fp_device_get_instance_private (device);
799
800
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 6 times.
6 g_return_val_if_fail (FP_IS_DEVICE (device), FALSE);
801
802 6 return !!(priv->features & FP_DEVICE_FEATURE_STORAGE);
803 }
804
805 /**
806 * fp_device_open:
807 * @device: a #FpDevice
808 * @cancellable: (nullable): a #GCancellable, or %NULL
809 * @callback: the function to call on completion
810 * @user_data: the data to pass to @callback
811 *
812 * Start an asynchronous operation to open the device. The callback will
813 * be called once the operation has finished. Retrieve the result with
814 * fp_device_open_finish().
815 */
816 void
817 222 fp_device_open (FpDevice *device,
818 GCancellable *cancellable,
819 GAsyncReadyCallback callback,
820 gpointer user_data)
821 {
822 222 g_autoptr(GTask) task = NULL;
823 222 FpDevicePrivate *priv = fp_device_get_instance_private (device);
824 222 GError *error = NULL;
825
826 222 task = g_task_new (device, cancellable, callback, user_data);
827
1/2
✓ Branch 4 → 5 taken 222 times.
✗ Branch 4 → 24 not taken.
222 if (g_task_return_error_if_cancelled (task))
828 return;
829
830
2/2
✓ Branch 5 → 6 taken 1 time.
✓ Branch 5 → 8 taken 221 times.
222 if (priv->is_open)
831 {
832 1 g_task_return_error (task,
833 fpi_device_error_new (FP_DEVICE_ERROR_ALREADY_OPEN));
834 1 return;
835 }
836
837
3/4
✓ Branch 8 → 9 taken 220 times.
✓ Branch 8 → 10 taken 1 time.
✗ Branch 9 → 10 not taken.
✓ Branch 9 → 13 taken 220 times.
221 if (priv->current_task || priv->is_suspended)
838 {
839 1 g_task_return_error (task,
840 fpi_device_error_new (FP_DEVICE_ERROR_BUSY));
841 1 return;
842 }
843
844
2/3
✓ Branch 13 → 14 taken 29 times.
✗ Branch 13 → 18 not taken.
✓ Branch 13 → 19 taken 191 times.
220 switch (priv->type)
845 {
846 29 case FP_DEVICE_TYPE_USB:
847
1/2
✗ Branch 15 → 16 not taken.
✓ Branch 15 → 19 taken 29 times.
29 if (!g_usb_device_open (priv->usb_device, &error))
848 {
849 g_task_return_error (task, error);
850 return;
851 }
852 break;
853
854 case FP_DEVICE_TYPE_VIRTUAL:
855 case FP_DEVICE_TYPE_UDEV:
856 break;
857
858 default:
859 g_assert_not_reached ();
860 g_task_return_error (task, fpi_device_error_new (FP_DEVICE_ERROR_GENERAL));
861 return;
862 }
863
864 220 priv->current_action = FPI_DEVICE_ACTION_OPEN;
865 220 priv->current_task = g_steal_pointer (&task);
866 220 setup_task_cancellable (device);
867 220 fpi_device_report_finger_status (device, FP_FINGER_STATUS_NONE);
868
869 220 FP_DEVICE_GET_CLASS (device)->open (device);
870 }
871
872 /**
873 * fp_device_open_finish:
874 * @device: A #FpDevice
875 * @result: A #GAsyncResult
876 * @error: Return location for errors, or %NULL to ignore
877 *
878 * Finish an asynchronous operation to open the device.
879 * See fp_device_open().
880 *
881 * Returns: (type void): %FALSE on error, %TRUE otherwise
882 */
883 gboolean
884 221 fp_device_open_finish (FpDevice *device,
885 GAsyncResult *result,
886 GError **error)
887 {
888 221 return g_task_propagate_boolean (G_TASK (result), error);
889 }
890
891 /**
892 * fp_device_close:
893 * @device: a #FpDevice
894 * @cancellable: (nullable): a #GCancellable, or %NULL
895 * @callback: the function to call on completion
896 * @user_data: the data to pass to @callback
897 *
898 * Start an asynchronous operation to close the device. The callback will
899 * be called once the operation has finished. Retrieve the result with
900 * fp_device_close_finish().
901 */
902 void
903 219 fp_device_close (FpDevice *device,
904 GCancellable *cancellable,
905 GAsyncReadyCallback callback,
906 gpointer user_data)
907 {
908 213 g_autoptr(GTask) task = NULL;
909 219 FpDevicePrivate *priv = fp_device_get_instance_private (device);
910
911 219 task = g_task_new (device, cancellable, callback, user_data);
912
1/2
✓ Branch 4 → 5 taken 219 times.
✗ Branch 4 → 16 not taken.
219 if (g_task_return_error_if_cancelled (task))
913 return;
914
915
2/2
✓ Branch 5 → 6 taken 4 times.
✓ Branch 5 → 8 taken 215 times.
219 if (!priv->is_open)
916 {
917 4 g_task_return_error (task,
918 fpi_device_error_new (FP_DEVICE_ERROR_NOT_OPEN));
919 4 return;
920 }
921
922
3/4
✓ Branch 8 → 9 taken 213 times.
✓ Branch 8 → 10 taken 2 times.
✗ Branch 9 → 10 not taken.
✓ Branch 9 → 13 taken 213 times.
215 if (priv->current_task || priv->is_suspended)
923 {
924 2 g_task_return_error (task,
925 fpi_device_error_new (FP_DEVICE_ERROR_BUSY));
926 2 return;
927 }
928
929 213 priv->current_action = FPI_DEVICE_ACTION_CLOSE;
930 213 priv->current_task = g_steal_pointer (&task);
931 213 setup_task_cancellable (device);
932
933 213 FP_DEVICE_GET_CLASS (device)->close (device);
934 }
935
936 /**
937 * fp_device_close_finish:
938 * @device: A #FpDevice
939 * @result: A #GAsyncResult
940 * @error: Return location for errors, or %NULL to ignore
941 *
942 * Finish an asynchronous operation to close the device.
943 * See fp_device_close().
944 *
945 * Returns: (type void): %FALSE on error, %TRUE otherwise
946 */
947 gboolean
948 211 fp_device_close_finish (FpDevice *device,
949 GAsyncResult *result,
950 GError **error)
951 {
952 211 return g_task_propagate_boolean (G_TASK (result), error);
953 }
954
955 /**
956 * fp_device_suspend:
957 * @device: a #FpDevice
958 * @cancellable: (nullable): a #GCancellable, or %NULL, currently not used
959 * @callback: the function to call on completion
960 * @user_data: the data to pass to @callback
961 *
962 * Prepare the device for system suspend. Retrieve the result with
963 * fp_device_suspend_finish().
964 *
965 * The suspend method can be called at any time (even if the device is not
966 * opened) and must be paired with a corresponding resume call. It is undefined
967 * when or how any ongoing operation is finished. This call might wait for an
968 * ongoing operation to finish, might cancel the ongoing operation or may
969 * prepare the device so that the host is resumed when the operation can be
970 * finished.
971 *
972 * If an ongoing operation must be cancelled then it will complete with an error
973 * code of #FP_DEVICE_ERROR_BUSY before the suspend async routine finishes.
974 *
975 * Any operation started while the device is suspended will fail with
976 * #FP_DEVICE_ERROR_BUSY, this includes calls to open or close the device.
977 */
978 void
979 7 fp_device_suspend (FpDevice *device,
980 GCancellable *cancellable,
981 GAsyncReadyCallback callback,
982 gpointer user_data)
983 {
984 7 g_autoptr(GTask) task = NULL;
985 7 FpDevicePrivate *priv = fp_device_get_instance_private (device);
986
987 7 task = g_task_new (device, cancellable, callback, user_data);
988
989
2/4
✓ Branch 3 → 4 taken 7 times.
✗ Branch 3 → 5 not taken.
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 7 taken 7 times.
7 if (priv->suspend_resume_task || priv->is_suspended)
990 {
991 g_task_return_error (task,
992 fpi_device_error_new (FP_DEVICE_ERROR_BUSY));
993 return;
994 }
995
996
1/2
✗ Branch 7 → 8 not taken.
✓ Branch 7 → 11 taken 7 times.
7 if (priv->is_removed)
997 {
998 g_task_return_error (task,
999 fpi_device_error_new (FP_DEVICE_ERROR_REMOVED));
1000 return;
1001 }
1002
1003 7 priv->suspend_resume_task = g_steal_pointer (&task);
1004
1005 7 fpi_device_suspend (device);
1006 }
1007
1008 /**
1009 * fp_device_suspend_finish:
1010 * @device: A #FpDevice
1011 * @result: A #GAsyncResult
1012 * @error: Return location for errors, or %NULL to ignore
1013 *
1014 * Finish an asynchronous operation to prepare the device for suspend.
1015 * See fp_device_suspend().
1016 *
1017 * The API user should accept an error of #FP_DEVICE_ERROR_NOT_SUPPORTED.
1018 *
1019 * Returns: (type void): %FALSE on error, %TRUE otherwise
1020 */
1021 gboolean
1022 6 fp_device_suspend_finish (FpDevice *device,
1023 GAsyncResult *result,
1024 GError **error)
1025 {
1026 6 return g_task_propagate_boolean (G_TASK (result), error);
1027 }
1028
1029 /**
1030 * fp_device_resume:
1031 * @device: a #FpDevice
1032 * @cancellable: (nullable): a #GCancellable, or %NULL, currently not used
1033 * @callback: the function to call on completion
1034 * @user_data: the data to pass to @callback
1035 *
1036 * Resume device after system suspend. Retrieve the result with
1037 * fp_device_suspend_finish().
1038 *
1039 * Note that it is not defined when any ongoing operation may return (success or
1040 * error). You must be ready to handle this before, during or after the
1041 * resume operation.
1042 */
1043 void
1044 7 fp_device_resume (FpDevice *device,
1045 GCancellable *cancellable,
1046 GAsyncReadyCallback callback,
1047 gpointer user_data)
1048 {
1049 7 g_autoptr(GTask) task = NULL;
1050 7 FpDevicePrivate *priv = fp_device_get_instance_private (device);
1051
1052 7 task = g_task_new (device, cancellable, callback, user_data);
1053
1054
2/4
✓ Branch 3 → 4 taken 7 times.
✗ Branch 3 → 5 not taken.
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 7 taken 7 times.
7 if (priv->suspend_resume_task || !priv->is_suspended)
1055 {
1056 g_task_return_error (task,
1057 fpi_device_error_new (FP_DEVICE_ERROR_BUSY));
1058 return;
1059 }
1060
1061
1/2
✗ Branch 7 → 8 not taken.
✓ Branch 7 → 11 taken 7 times.
7 if (priv->is_removed)
1062 {
1063 g_task_return_error (task,
1064 fpi_device_error_new (FP_DEVICE_ERROR_REMOVED));
1065 return;
1066 }
1067
1068 7 priv->suspend_resume_task = g_steal_pointer (&task);
1069
1070 7 fpi_device_resume (device);
1071 }
1072
1073 /**
1074 * fp_device_resume_finish:
1075 * @device: A #FpDevice
1076 * @result: A #GAsyncResult
1077 * @error: Return location for errors, or %NULL to ignore
1078 *
1079 * Finish an asynchronous operation to resume the device after suspend.
1080 * See fp_device_resume().
1081 *
1082 * The API user should accept an error of #FP_DEVICE_ERROR_NOT_SUPPORTED.
1083 *
1084 * Returns: (type void): %FALSE on error, %TRUE otherwise
1085 */
1086 gboolean
1087 6 fp_device_resume_finish (FpDevice *device,
1088 GAsyncResult *result,
1089 GError **error)
1090 {
1091 6 return g_task_propagate_boolean (G_TASK (result), error);
1092 }
1093
1094 static void
1095 67 enroll_data_free (FpEnrollData *data)
1096 {
1097
2/2
✓ Branch 2 → 3 taken 31 times.
✓ Branch 2 → 4 taken 36 times.
67 if (data->enroll_progress_destroy)
1098 31 data->enroll_progress_destroy (data->enroll_progress_data);
1099 67 data->enroll_progress_data = NULL;
1100
1/2
✓ Branch 4 → 5 taken 67 times.
✗ Branch 4 → 6 not taken.
67 g_clear_object (&data->print);
1101 67 g_free (data);
1102 67 }
1103
1104 /**
1105 * fp_device_enroll:
1106 * @device: a #FpDevice
1107 * @template_print: (transfer floating): a #FpPrint
1108 * @cancellable: (nullable): a #GCancellable, or %NULL
1109 * @progress_cb: (nullable) (closure progress_data) (scope notified): progress reporting callback
1110 * @progress_data: user data for @progress_cb
1111 * @progress_destroy: (destroy progress_data): Destroy notify for @progress_data
1112 * @callback: (scope async): the function to call on completion
1113 * @user_data: the data to pass to @callback
1114 *
1115 * Start an asynchronous operation to enroll a print. The callback will
1116 * be called once the operation has finished. Retrieve the result with
1117 * fp_device_enroll_finish().
1118 *
1119 * The @template_print parameter is a #FpPrint with available metadata filled
1120 * in and, optionally, with existing fingerprint data to be updated with newly
1121 * enrolled fingerprints if a device driver supports it. The driver may make use
1122 * of the metadata, when e.g. storing the print on device memory. It is undefined
1123 * whether this print is filled in by the driver and returned, or whether the
1124 * driver will return a newly created print after enrollment succeeded.
1125 */
1126 void
1127 72 fp_device_enroll (FpDevice *device,
1128 FpPrint *template_print,
1129 GCancellable *cancellable,
1130 FpEnrollProgress progress_cb,
1131 gpointer progress_data,
1132 GDestroyNotify progress_destroy,
1133 GAsyncReadyCallback callback,
1134 gpointer user_data)
1135 {
1136 72 g_autoptr(GTask) task = NULL;
1137 72 FpDevicePrivate *priv = fp_device_get_instance_private (device);
1138 72 FpEnrollData *data;
1139 72 FpiPrintType print_type;
1140
1141 72 task = g_task_new (device, cancellable, callback, user_data);
1142
1/2
✓ Branch 4 → 5 taken 72 times.
✗ Branch 4 → 43 not taken.
72 if (g_task_return_error_if_cancelled (task))
1143 return;
1144
1145
2/2
✓ Branch 5 → 6 taken 1 time.
✓ Branch 5 → 8 taken 71 times.
72 if (!priv->is_open)
1146 {
1147 1 g_task_return_error (task,
1148 fpi_device_error_new (FP_DEVICE_ERROR_NOT_OPEN));
1149 1 return;
1150 }
1151
1152
3/4
✓ Branch 8 → 9 taken 70 times.
✓ Branch 8 → 10 taken 1 time.
✗ Branch 9 → 10 not taken.
✓ Branch 9 → 13 taken 70 times.
71 if (priv->current_task || priv->is_suspended)
1153 {
1154 1 g_task_return_error (task,
1155 fpi_device_error_new (FP_DEVICE_ERROR_BUSY));
1156 1 return;
1157 }
1158
1159
1/2
✗ Branch 14 → 15 not taken.
✓ Branch 14 → 18 taken 70 times.
70 if (!FP_IS_PRINT (template_print))
1160 {
1161 g_task_return_error (task,
1162 fpi_device_error_new_msg (FP_DEVICE_ERROR_DATA_INVALID,
1163 "User did not pass a print template!"));
1164 return;
1165 }
1166
1167 70 g_object_get (template_print, "fpi-type", &print_type, NULL);
1168
2/2
✓ Branch 19 → 20 taken 5 times.
✓ Branch 19 → 30 taken 65 times.
70 if (print_type != FPI_PRINT_UNDEFINED)
1169 {
1170
2/2
✓ Branch 21 → 22 taken 1 time.
✓ Branch 21 → 25 taken 4 times.
5 if (!fp_device_has_feature (device, FP_DEVICE_FEATURE_UPDATE_PRINT))
1171 {
1172 1 g_task_return_error (task,
1173 fpi_device_error_new_msg (FP_DEVICE_ERROR_DATA_INVALID,
1174 "A device does not support print updates!"));
1175 1 return;
1176 }
1177
2/2
✓ Branch 26 → 27 taken 2 times.
✓ Branch 26 → 30 taken 2 times.
4 if (!fp_print_compatible (template_print, device))
1178 {
1179 2 g_task_return_error (task,
1180 fpi_device_error_new_msg (FP_DEVICE_ERROR_DATA_INVALID,
1181 "The print and device must have a matching driver and device id"
1182 " for a fingerprint update to succeed"));
1183 2 return;
1184 }
1185 }
1186
1187 67 fpi_device_update_temp (device, TRUE);
1188
1/2
✗ Branch 31 → 32 not taken.
✓ Branch 31 → 36 taken 67 times.
67 if (priv->temp_current == FP_TEMPERATURE_HOT)
1189 {
1190 g_task_return_error (task, fpi_device_error_new (FP_DEVICE_ERROR_TOO_HOT));
1191 fpi_device_update_temp (device, FALSE);
1192 return;
1193 }
1194
1195 67 priv->current_action = FPI_DEVICE_ACTION_ENROLL;
1196 67 priv->current_task = g_steal_pointer (&task);
1197 67 setup_task_cancellable (device);
1198
1199 67 data = g_new0 (FpEnrollData, 1);
1200 67 data->print = g_object_ref_sink (template_print);
1201 67 data->enroll_progress_cb = progress_cb;
1202 67 data->enroll_progress_data = progress_data;
1203 67 data->enroll_progress_destroy = progress_destroy;
1204
1205 // Attach the progress data as task data so that it is destroyed
1206 67 g_task_set_task_data (priv->current_task, data, (GDestroyNotify) enroll_data_free);
1207
1208 67 FP_DEVICE_GET_CLASS (device)->enroll (device);
1209 }
1210
1211 /**
1212 * fp_device_enroll_finish:
1213 * @device: A #FpDevice
1214 * @result: A #GAsyncResult
1215 * @error: Return location for errors, or %NULL to ignore
1216 *
1217 * Finish an asynchronous operation to enroll a print. You should check
1218 * for an error of type %FP_DEVICE_RETRY to prompt the user again if there
1219 * was an interaction issue.
1220 * See fp_device_enroll().
1221 *
1222 * Returns: (transfer full): The enrolled #FpPrint, or %NULL on error
1223 */
1224 FpPrint *
1225 72 fp_device_enroll_finish (FpDevice *device,
1226 GAsyncResult *result,
1227 GError **error)
1228 {
1229 72 return g_task_propagate_pointer (G_TASK (result), error);
1230 }
1231
1232 static void
1233 128 match_data_free (FpMatchData *data)
1234 {
1235
2/2
✓ Branch 2 → 3 taken 74 times.
✓ Branch 2 → 4 taken 54 times.
128 g_clear_object (&data->print);
1236
2/2
✓ Branch 4 → 5 taken 46 times.
✓ Branch 4 → 6 taken 82 times.
128 g_clear_object (&data->match);
1237 128 g_clear_error (&data->error);
1238
1239
2/2
✓ Branch 7 → 8 taken 18 times.
✓ Branch 7 → 9 taken 110 times.
128 if (data->match_destroy)
1240 18 data->match_destroy (data->match_data);
1241 128 data->match_data = NULL;
1242
1243
2/2
✓ Branch 9 → 10 taken 34 times.
✓ Branch 9 → 11 taken 94 times.
128 g_clear_object (&data->enrolled_print);
1244
2/2
✓ Branch 11 → 12 taken 75 times.
✓ Branch 11 → 13 taken 53 times.
128 g_clear_pointer (&data->gallery, g_ptr_array_unref);
1245
1246 128 g_free (data);
1247 128 }
1248
1249 static void
1250 30 on_verify_identification (GObject *source_object,
1251 GAsyncResult *result,
1252 gpointer user_data)
1253 {
1254 30 g_autoptr(FpPrint) match = NULL;
1255
3/4
✗ Branch 11 → 12 not taken.
✓ Branch 11 → 13 taken 11 times.
✓ Branch 23 → 24 taken 16 times.
✓ Branch 23 → 25 taken 3 times.
30 g_autoptr(FpPrint) print = NULL;
1256
2/4
✗ Branch 9 → 10 not taken.
✓ Branch 9 → 11 taken 11 times.
✗ Branch 21 → 22 not taken.
✓ Branch 21 → 23 taken 19 times.
30 g_autoptr(GError) error = NULL;
1257
2/4
✗ Branch 7 → 8 not taken.
✓ Branch 7 → 9 taken 11 times.
✗ Branch 19 → 20 not taken.
✓ Branch 19 → 21 taken 19 times.
60 g_autoptr(GTask) verify_task = G_TASK (g_steal_pointer (&user_data));
1258 30 FpDevice *device = FP_DEVICE (source_object);
1259 30 FpMatchData *match_data;
1260
1261
2/2
✓ Branch 3 → 4 taken 11 times.
✓ Branch 3 → 14 taken 19 times.
30 if (!fp_device_identify_finish (device, result, &match, &print, &error))
1262 {
1263 11 g_task_return_error (verify_task, g_steal_pointer (&error));
1264
1/2
✓ Branch 5 → 6 taken 11 times.
✗ Branch 5 → 7 not taken.
11 return;
1265 }
1266
1267 19 match_data = g_new0 (FpMatchData, 1);
1268 19 match_data->print = g_steal_pointer (&print);
1269
1270 19 g_task_set_task_data (verify_task, g_steal_pointer (&match_data),
1271 (GDestroyNotify) match_data_free);
1272
1273
1/2
✓ Branch 17 → 18 taken 19 times.
✗ Branch 17 → 19 not taken.
19 g_task_return_int (verify_task, match ? FPI_MATCH_SUCCESS : FPI_MATCH_FAIL);
1274 }
1275
1276 /**
1277 * fp_device_verify:
1278 * @device: a #FpDevice
1279 * @enrolled_print: a #FpPrint to verify
1280 * @cancellable: (nullable): a #GCancellable, or %NULL
1281 * @match_cb: (nullable) (scope notified) (closure match_data): match reporting callback
1282 * @match_data: user data for @match_cb
1283 * @match_destroy: (destroy match_data): Destroy notify for @match_data
1284 * @callback: the function to call on completion
1285 * @user_data: the data to pass to @callback
1286 *
1287 * Start an asynchronous operation to verify a print. The callback will
1288 * be called once the operation has finished. Retrieve the result with
1289 * fp_device_verify_finish().
1290 */
1291 void
1292 72 fp_device_verify (FpDevice *device,
1293 FpPrint *enrolled_print,
1294 GCancellable *cancellable,
1295 FpMatchCb match_cb,
1296 gpointer match_data,
1297 GDestroyNotify match_destroy,
1298 GAsyncReadyCallback callback,
1299 gpointer user_data)
1300 {
1301 38 g_autoptr(GTask) task = NULL;
1302 72 FpDevicePrivate *priv = fp_device_get_instance_private (device);
1303 72 FpDeviceClass *cls = FP_DEVICE_GET_CLASS (device);
1304 72 FpMatchData *data;
1305
1306 72 task = g_task_new (device, cancellable, callback, user_data);
1307
1/2
✓ Branch 4 → 5 taken 72 times.
✗ Branch 4 → 39 not taken.
72 if (g_task_return_error_if_cancelled (task))
1308 return;
1309
1310
2/2
✓ Branch 5 → 6 taken 1 time.
✓ Branch 5 → 8 taken 71 times.
72 if (!priv->is_open)
1311 {
1312 1 g_task_return_error (task,
1313 fpi_device_error_new (FP_DEVICE_ERROR_NOT_OPEN));
1314 1 return;
1315 }
1316
1317
3/4
✓ Branch 8 → 9 taken 70 times.
✓ Branch 8 → 10 taken 1 time.
✗ Branch 9 → 10 not taken.
✓ Branch 9 → 13 taken 70 times.
71 if (priv->current_task || priv->is_suspended)
1318 {
1319 1 g_task_return_error (task,
1320 fpi_device_error_new (FP_DEVICE_ERROR_BUSY));
1321 1 return;
1322 }
1323
1324
3/4
✓ Branch 13 → 14 taken 31 times.
✓ Branch 13 → 15 taken 39 times.
✓ Branch 14 → 15 taken 31 times.
✗ Branch 14 → 16 not taken.
70 if ((!cls->verify && !cls->identify) ||
1325
2/2
✓ Branch 15 → 16 taken 2 times.
✓ Branch 15 → 19 taken 68 times.
70 !(priv->features & FP_DEVICE_FEATURE_VERIFY))
1326 {
1327 2 g_task_return_error (task,
1328 fpi_device_error_new_msg (FP_DEVICE_ERROR_NOT_SUPPORTED,
1329 "Device has no verification support"));
1330 2 return;
1331 }
1332
1333
2/2
✓ Branch 19 → 20 taken 30 times.
✓ Branch 19 → 27 taken 38 times.
68 if (!cls->verify)
1334 {
1335
1/2
✓ Branch 39 → 40 taken 4 times.
✗ Branch 39 → 41 not taken.
34 g_autoptr(GPtrArray) prints = NULL;
1336
1337
1/2
✗ Branch 20 → 21 not taken.
✓ Branch 20 → 22 taken 30 times.
30 g_assert (cls->identify);
1338
1339 30 prints = g_ptr_array_sized_new (1);
1340 30 g_ptr_array_add (prints, enrolled_print);
1341
1342 30 fp_device_identify (device, prints, cancellable, match_cb, match_data,
1343 match_destroy, on_verify_identification,
1344 g_steal_pointer (&task));
1345
1/2
✓ Branch 25 → 26 taken 30 times.
✗ Branch 25 → 41 not taken.
30 return;
1346 }
1347
1348 38 fpi_device_update_temp (device, TRUE);
1349
1/2
✗ Branch 28 → 29 not taken.
✓ Branch 28 → 33 taken 38 times.
38 if (priv->temp_current == FP_TEMPERATURE_HOT)
1350 {
1351 g_task_return_error (task, fpi_device_error_new (FP_DEVICE_ERROR_TOO_HOT));
1352 fpi_device_update_temp (device, FALSE);
1353 return;
1354 }
1355
1356 38 priv->current_action = FPI_DEVICE_ACTION_VERIFY;
1357 38 priv->current_task = g_steal_pointer (&task);
1358 38 setup_task_cancellable (device);
1359
1360 38 data = g_new0 (FpMatchData, 1);
1361 38 data->enrolled_print = g_object_ref (enrolled_print);
1362 38 data->match_cb = match_cb;
1363 38 data->match_data = match_data;
1364 38 data->match_destroy = match_destroy;
1365
1366 // Attach the match data as task data so that it is destroyed
1367 38 g_task_set_task_data (priv->current_task, data, (GDestroyNotify) match_data_free);
1368
1369 38 cls->verify (device);
1370 }
1371
1372 /**
1373 * fp_device_verify_finish:
1374 * @device: A #FpDevice
1375 * @result: A #GAsyncResult
1376 * @match: (out): Whether the user presented the correct finger
1377 * @print: (out) (transfer full) (nullable): Location to store the scanned print, or %NULL to ignore
1378 * @error: Return location for errors, or %NULL to ignore
1379 *
1380 * Finish an asynchronous operation to verify an enrolled print. You should check
1381 * for an error of type %FP_DEVICE_RETRY to prompt the user again if there
1382 * was an interaction issue.
1383 *
1384 * With @print you can fetch the newly created print and retrieve the image data if available.
1385 *
1386 * See fp_device_verify().
1387 *
1388 * Returns: (type void): %FALSE on error, %TRUE otherwise
1389 */
1390 gboolean
1391 71 fp_device_verify_finish (FpDevice *device,
1392 GAsyncResult *result,
1393 gboolean *match,
1394 FpPrint **print,
1395 GError **error)
1396 {
1397 71 gint res;
1398
1399 71 res = g_task_propagate_int (G_TASK (result), error);
1400
1401
2/2
✓ Branch 3 → 4 taken 67 times.
✓ Branch 3 → 9 taken 4 times.
71 if (print)
1402 {
1403 67 FpMatchData *data;
1404
1405 67 data = g_task_get_task_data (G_TASK (result));
1406
1407
2/2
✓ Branch 5 → 6 taken 53 times.
✓ Branch 5 → 7 taken 14 times.
67 *print = data ? data->print : NULL;
1408
2/2
✓ Branch 7 → 8 taken 29 times.
✓ Branch 7 → 9 taken 38 times.
67 if (*print)
1409 29 g_object_ref (*print);
1410 }
1411
1412
2/2
✓ Branch 9 → 10 taken 67 times.
✓ Branch 9 → 11 taken 4 times.
71 if (match)
1413 67 *match = res == FPI_MATCH_SUCCESS;
1414
1415 71 return res != FPI_MATCH_ERROR;
1416 }
1417
1418 /**
1419 * fp_device_identify:
1420 * @device: a #FpDevice
1421 * @prints: (element-type FpPrint) (transfer none): #GPtrArray of #FpPrint
1422 * @cancellable: (nullable): a #GCancellable, or %NULL
1423 * @match_cb: (nullable) (scope notified) (closure match_data): match reporting callback
1424 * @match_data: user data for @match_cb
1425 * @match_destroy: (destroy match_data): Destroy notify for @match_data
1426 * @callback: the function to call on completion
1427 * @user_data: the data to pass to @callback
1428 *
1429 * Start an asynchronous operation to identify prints. The callback will
1430 * be called once the operation has finished. Retrieve the result with
1431 * fp_device_identify_finish().
1432 */
1433 void
1434 85 fp_device_identify (FpDevice *device,
1435 GPtrArray *prints,
1436 GCancellable *cancellable,
1437 FpMatchCb match_cb,
1438 gpointer match_data,
1439 GDestroyNotify match_destroy,
1440 GAsyncReadyCallback callback,
1441 gpointer user_data)
1442 {
1443 79 g_autoptr(GTask) task = NULL;
1444 85 FpDevicePrivate *priv = fp_device_get_instance_private (device);
1445 85 FpDeviceClass *cls = FP_DEVICE_GET_CLASS (device);
1446 85 FpMatchData *data;
1447
1448 85 task = g_task_new (device, cancellable, callback, user_data);
1449
2/2
✓ Branch 4 → 5 taken 84 times.
✓ Branch 4 → 35 taken 1 time.
85 if (g_task_return_error_if_cancelled (task))
1450 return;
1451
1452
2/2
✓ Branch 5 → 6 taken 1 time.
✓ Branch 5 → 8 taken 83 times.
84 if (!priv->is_open)
1453 {
1454 1 g_task_return_error (task,
1455 fpi_device_error_new (FP_DEVICE_ERROR_NOT_OPEN));
1456 1 return;
1457 }
1458
1459
3/4
✓ Branch 8 → 9 taken 82 times.
✓ Branch 8 → 10 taken 1 time.
✗ Branch 9 → 10 not taken.
✓ Branch 9 → 13 taken 82 times.
83 if (priv->current_task || priv->is_suspended)
1460 {
1461 1 g_task_return_error (task,
1462 fpi_device_error_new (FP_DEVICE_ERROR_BUSY));
1463 1 return;
1464 }
1465
1466
3/4
✓ Branch 13 → 14 taken 81 times.
✓ Branch 13 → 15 taken 1 time.
✗ Branch 14 → 15 not taken.
✓ Branch 14 → 18 taken 81 times.
82 if (!cls->identify || !(priv->features & FP_DEVICE_FEATURE_IDENTIFY))
1467 {
1468 1 g_task_return_error (task,
1469 fpi_device_error_new_msg (FP_DEVICE_ERROR_NOT_SUPPORTED,
1470 "Device has not identification support"));
1471 1 return;
1472 }
1473
1474
2/2
✓ Branch 18 → 19 taken 1 time.
✓ Branch 18 → 22 taken 80 times.
81 if (prints == NULL)
1475 {
1476 1 g_task_return_error (task,
1477 fpi_device_error_new_msg (FP_DEVICE_ERROR_DATA_INVALID,
1478 "Invalid gallery array"));
1479 1 return;
1480 }
1481
1482 80 fpi_device_update_temp (device, TRUE);
1483
2/2
✓ Branch 23 → 24 taken 1 time.
✓ Branch 23 → 28 taken 79 times.
80 if (priv->temp_current == FP_TEMPERATURE_HOT)
1484 {
1485 1 g_task_return_error (task, fpi_device_error_new (FP_DEVICE_ERROR_TOO_HOT));
1486 1 fpi_device_update_temp (device, FALSE);
1487 1 return;
1488 }
1489
1490 79 priv->current_action = FPI_DEVICE_ACTION_IDENTIFY;
1491 79 priv->current_task = g_steal_pointer (&task);
1492 79 setup_task_cancellable (device);
1493
1494 79 data = g_new0 (FpMatchData, 1);
1495 /* We cannot store the gallery directly, because the ptr array may not own
1496 * a reference to each print. Also, the caller could in principle modify the
1497 * GPtrArray afterwards.
1498 */
1499 79 data->gallery = g_ptr_array_copy (prints, (GCopyFunc) g_object_ref, NULL);
1500 79 g_ptr_array_set_free_func (data->gallery, g_object_unref);
1501
1502 79 data->match_cb = match_cb;
1503 79 data->match_data = match_data;
1504 79 data->match_destroy = match_destroy;
1505
1506 // Attach the match data as task data so that it is destroyed
1507 79 g_task_set_task_data (priv->current_task, data, (GDestroyNotify) match_data_free);
1508
1509 79 cls->identify (device);
1510 }
1511
1512 /**
1513 * fp_device_identify_finish:
1514 * @device: A #FpDevice
1515 * @result: A #GAsyncResult
1516 * @match: (out) (transfer full) (nullable): Location for the matched #FpPrint, or %NULL
1517 * @print: (out) (transfer full) (nullable): Location for the new #FpPrint, or %NULL
1518 * @error: Return location for errors, or %NULL to ignore
1519 *
1520 * Finish an asynchronous operation to identify a print. You should check
1521 * for an error of type %FP_DEVICE_RETRY to prompt the user again if there
1522 * was an interaction issue.
1523 *
1524 * Use @match to find the print that matched. With @print you can fetch the
1525 * newly created print and retrieve the image data if available.
1526 *
1527 * See fp_device_identify().
1528 *
1529 * Returns: (type void): %FALSE on error, %TRUE otherwise
1530 */
1531 gboolean
1532 85 fp_device_identify_finish (FpDevice *device,
1533 GAsyncResult *result,
1534 FpPrint **match,
1535 FpPrint **print,
1536 GError **error)
1537 {
1538 85 FpMatchData *data;
1539
1540 85 data = g_task_get_task_data (G_TASK (result));
1541
1542
2/2
✓ Branch 3 → 4 taken 79 times.
✓ Branch 3 → 8 taken 6 times.
85 if (print)
1543 {
1544
2/2
✓ Branch 4 → 5 taken 74 times.
✓ Branch 4 → 6 taken 5 times.
79 *print = data ? data->print : NULL;
1545
2/2
✓ Branch 6 → 7 taken 44 times.
✓ Branch 6 → 8 taken 35 times.
79 if (*print)
1546 44 g_object_ref (*print);
1547 }
1548
2/2
✓ Branch 8 → 9 taken 79 times.
✓ Branch 8 → 13 taken 6 times.
85 if (match)
1549 {
1550
2/2
✓ Branch 9 → 10 taken 74 times.
✓ Branch 9 → 11 taken 5 times.
79 *match = data ? data->match : NULL;
1551
2/2
✓ Branch 11 → 12 taken 38 times.
✓ Branch 11 → 13 taken 41 times.
79 if (*match)
1552 38 g_object_ref (*match);
1553 }
1554
1555 85 return g_task_propagate_boolean (G_TASK (result), error);
1556 }
1557
1558 /**
1559 * fp_device_capture:
1560 * @device: a #FpDevice
1561 * @wait_for_finger: Whether to wait for a finger or not
1562 * @cancellable: (nullable): a #GCancellable, or %NULL
1563 * @callback: the function to call on completion
1564 * @user_data: the data to pass to @callback
1565 *
1566 * Start an asynchronous operation to capture an image. The callback will
1567 * be called once the operation has finished. Retrieve the result with
1568 * fp_device_capture_finish().
1569 */
1570 void
1571 26 fp_device_capture (FpDevice *device,
1572 gboolean wait_for_finger,
1573 GCancellable *cancellable,
1574 GAsyncReadyCallback callback,
1575 gpointer user_data)
1576 {
1577 21 g_autoptr(GTask) task = NULL;
1578 26 FpDevicePrivate *priv = fp_device_get_instance_private (device);
1579 26 FpDeviceClass *cls = FP_DEVICE_GET_CLASS (device);
1580
1581 26 task = g_task_new (device, cancellable, callback, user_data);
1582
1/2
✓ Branch 4 → 5 taken 26 times.
✗ Branch 4 → 27 not taken.
26 if (g_task_return_error_if_cancelled (task))
1583 return;
1584
1585
2/2
✓ Branch 5 → 6 taken 1 time.
✓ Branch 5 → 8 taken 25 times.
26 if (!priv->is_open)
1586 {
1587 1 g_task_return_error (task,
1588 fpi_device_error_new (FP_DEVICE_ERROR_NOT_OPEN));
1589 1 return;
1590 }
1591
1592
3/4
✓ Branch 8 → 9 taken 24 times.
✓ Branch 8 → 10 taken 1 time.
✗ Branch 9 → 10 not taken.
✓ Branch 9 → 13 taken 24 times.
25 if (priv->current_task || priv->is_suspended)
1593 {
1594 1 g_task_return_error (task,
1595 fpi_device_error_new (FP_DEVICE_ERROR_BUSY));
1596 1 return;
1597 }
1598
1599
4/4
✓ Branch 13 → 14 taken 22 times.
✓ Branch 13 → 15 taken 2 times.
✓ Branch 14 → 15 taken 1 time.
✓ Branch 14 → 18 taken 21 times.
24 if (!cls->capture || !(priv->features & FP_DEVICE_FEATURE_CAPTURE))
1600 {
1601 3 g_task_return_error (task,
1602 fpi_device_error_new_msg (FP_DEVICE_ERROR_NOT_SUPPORTED,
1603 "Device has no verification support"));
1604 3 return;
1605 }
1606
1607 21 fpi_device_update_temp (device, TRUE);
1608
1/2
✗ Branch 19 → 20 not taken.
✓ Branch 19 → 24 taken 21 times.
21 if (priv->temp_current == FP_TEMPERATURE_HOT)
1609 {
1610 g_task_return_error (task, fpi_device_error_new (FP_DEVICE_ERROR_TOO_HOT));
1611 fpi_device_update_temp (device, FALSE);
1612 return;
1613 }
1614
1615 21 priv->current_action = FPI_DEVICE_ACTION_CAPTURE;
1616 21 priv->current_task = g_steal_pointer (&task);
1617 21 setup_task_cancellable (device);
1618
1619 21 priv->wait_for_finger = wait_for_finger;
1620
1621 21 cls->capture (device);
1622 }
1623
1624 /**
1625 * fp_device_capture_finish:
1626 * @device: A #FpDevice
1627 * @result: A #GAsyncResult
1628 * @error: Return location for errors, or %NULL to ignore
1629 *
1630 * Finish an asynchronous operation to capture an image. You should check
1631 * for an error of type %FP_DEVICE_RETRY to prompt the user again if there
1632 * was an interaction issue.
1633 *
1634 * See fp_device_capture().
1635 *
1636 * Returns: (transfer full): #FpImage or %NULL on error
1637 */
1638 FpImage *
1639 26 fp_device_capture_finish (FpDevice *device,
1640 GAsyncResult *result,
1641 GError **error)
1642 {
1643 26 return g_task_propagate_pointer (G_TASK (result), error);
1644 }
1645
1646 /**
1647 * fp_device_delete_print:
1648 * @device: a #FpDevice
1649 * @enrolled_print: a #FpPrint to delete
1650 * @cancellable: (nullable): a #GCancellable, or %NULL
1651 * @callback: the function to call on completion
1652 * @user_data: the data to pass to @callback
1653 *
1654 * Start an asynchronous operation to delete a print from the device.
1655 * The callback will be called once the operation has finished. Retrieve
1656 * the result with fp_device_delete_print_finish().
1657 *
1658 * This only makes sense on devices that store prints on-chip, but is safe
1659 * to always call.
1660 */
1661 void
1662 27 fp_device_delete_print (FpDevice *device,
1663 FpPrint *enrolled_print,
1664 GCancellable *cancellable,
1665 GAsyncReadyCallback callback,
1666 gpointer user_data)
1667 {
1668 24 g_autoptr(GTask) task = NULL;
1669 27 FpDevicePrivate *priv = fp_device_get_instance_private (device);
1670 27 FpDeviceClass *cls = FP_DEVICE_GET_CLASS (device);
1671
1672 27 task = g_task_new (device, cancellable, callback, user_data);
1673
1/2
✓ Branch 4 → 5 taken 27 times.
✗ Branch 4 → 22 not taken.
27 if (g_task_return_error_if_cancelled (task))
1674 return;
1675
1676
2/2
✓ Branch 5 → 6 taken 1 time.
✓ Branch 5 → 8 taken 26 times.
27 if (!priv->is_open)
1677 {
1678 1 g_task_return_error (task,
1679 fpi_device_error_new (FP_DEVICE_ERROR_NOT_OPEN));
1680 1 return;
1681 }
1682
1683
3/4
✓ Branch 8 → 9 taken 25 times.
✓ Branch 8 → 10 taken 1 time.
✗ Branch 9 → 10 not taken.
✓ Branch 9 → 13 taken 25 times.
26 if (priv->current_task || priv->is_suspended)
1684 {
1685 1 g_task_return_error (task,
1686 fpi_device_error_new (FP_DEVICE_ERROR_BUSY));
1687 1 return;
1688 }
1689
1690 /* Succeed immediately if delete is not implemented. */
1691
3/4
✓ Branch 13 → 14 taken 25 times.
✗ Branch 13 → 15 not taken.
✓ Branch 14 → 15 taken 1 time.
✓ Branch 14 → 17 taken 24 times.
25 if (!cls->delete || !(priv->features & FP_DEVICE_FEATURE_STORAGE_DELETE))
1692 {
1693 1 g_task_return_boolean (task, TRUE);
1694 1 return;
1695 }
1696
1697 24 priv->current_action = FPI_DEVICE_ACTION_DELETE;
1698 24 priv->current_task = g_steal_pointer (&task);
1699 24 setup_task_cancellable (device);
1700
1701 24 g_task_set_task_data (priv->current_task,
1702 g_object_ref (enrolled_print),
1703 g_object_unref);
1704
1705 24 cls->delete (device);
1706 }
1707
1708 /**
1709 * fp_device_delete_print_finish:
1710 * @device: A #FpDevice
1711 * @result: A #GAsyncResult
1712 * @error: Return location for errors, or %NULL to ignore
1713 *
1714 * Finish an asynchronous operation to delete an enrolled print.
1715 *
1716 * See fp_device_delete_print().
1717 *
1718 * Returns: (type void): %FALSE on error, %TRUE otherwise
1719 */
1720 gboolean
1721 27 fp_device_delete_print_finish (FpDevice *device,
1722 GAsyncResult *result,
1723 GError **error)
1724 {
1725 27 return g_task_propagate_boolean (G_TASK (result), error);
1726 }
1727
1728 /**
1729 * fp_device_list_prints:
1730 * @device: a #FpDevice
1731 * @cancellable: (nullable): a #GCancellable, or %NULL
1732 * @callback: the function to call on completion
1733 * @user_data: the data to pass to @callback
1734 *
1735 * Start an asynchronous operation to list all prints stored on the device.
1736 * This only makes sense on devices that store prints on-chip.
1737 *
1738 * Retrieve the result with fp_device_list_prints_finish().
1739 */
1740 void
1741 55 fp_device_list_prints (FpDevice *device,
1742 GCancellable *cancellable,
1743 GAsyncReadyCallback callback,
1744 gpointer user_data)
1745 {
1746 52 g_autoptr(GTask) task = NULL;
1747 55 FpDevicePrivate *priv = fp_device_get_instance_private (device);
1748 55 FpDeviceClass *cls = FP_DEVICE_GET_CLASS (device);
1749
1750 55 task = g_task_new (device, cancellable, callback, user_data);
1751
1/2
✓ Branch 4 → 5 taken 55 times.
✗ Branch 4 → 21 not taken.
55 if (g_task_return_error_if_cancelled (task))
1752 return;
1753
1754
2/2
✓ Branch 5 → 6 taken 1 time.
✓ Branch 5 → 8 taken 54 times.
55 if (!priv->is_open)
1755 {
1756 1 g_task_return_error (task,
1757 fpi_device_error_new (FP_DEVICE_ERROR_NOT_OPEN));
1758 1 return;
1759 }
1760
1761
3/4
✓ Branch 8 → 9 taken 53 times.
✓ Branch 8 → 10 taken 1 time.
✗ Branch 9 → 10 not taken.
✓ Branch 9 → 13 taken 53 times.
54 if (priv->current_task || priv->is_suspended)
1762 {
1763 1 g_task_return_error (task,
1764 fpi_device_error_new (FP_DEVICE_ERROR_BUSY));
1765 1 return;
1766 }
1767
1768
3/4
✓ Branch 13 → 14 taken 53 times.
✗ Branch 13 → 15 not taken.
✓ Branch 14 → 15 taken 1 time.
✓ Branch 14 → 18 taken 52 times.
53 if (!cls->list || !(priv->features & FP_DEVICE_FEATURE_STORAGE))
1769 {
1770 1 g_task_return_error (task,
1771 fpi_device_error_new_msg (FP_DEVICE_ERROR_NOT_SUPPORTED,
1772 "Device has no storage"));
1773 1 return;
1774 }
1775
1776 52 priv->current_action = FPI_DEVICE_ACTION_LIST;
1777 52 priv->current_task = g_steal_pointer (&task);
1778 52 setup_task_cancellable (device);
1779
1780 52 cls->list (device);
1781 }
1782
1783 /**
1784 * fp_device_list_prints_finish:
1785 * @device: A #FpDevice
1786 * @result: A #GAsyncResult
1787 * @error: Return location for errors, or %NULL to ignore
1788 *
1789 * Finish an asynchronous operation to list all device stored prints.
1790 *
1791 * See fp_device_list_prints().
1792 *
1793 * Returns: (element-type FpPrint) (transfer container): Array of prints or %NULL on error
1794 */
1795 GPtrArray *
1796 55 fp_device_list_prints_finish (FpDevice *device,
1797 GAsyncResult *result,
1798 GError **error)
1799 {
1800 55 return g_task_propagate_pointer (G_TASK (result), error);
1801 }
1802
1803 /**
1804 * fp_device_clear_storage:
1805 * @device: a #FpDevice
1806 * @cancellable: (nullable): a #GCancellable, or %NULL
1807 * @callback: the function to call on completion
1808 * @user_data: the data to pass to @callback
1809 *
1810 * Start an asynchronous operation to delete all prints from the device.
1811 * The callback will be called once the operation has finished. Retrieve
1812 * the result with fp_device_clear_storage_finish().
1813 *
1814 * This only makes sense on devices that store prints on-chip, but is safe
1815 * to always call.
1816 */
1817 void
1818 61 fp_device_clear_storage (FpDevice *device,
1819 GCancellable *cancellable,
1820 GAsyncReadyCallback callback,
1821 gpointer user_data)
1822 {
1823 122 g_autoptr(GTask) task = NULL;
1824 61 FpDevicePrivate *priv = fp_device_get_instance_private (device);
1825 61 FpDeviceClass *cls = FP_DEVICE_GET_CLASS (device);
1826
1827 61 task = g_task_new (device, cancellable, callback, user_data);
1828
1/2
✓ Branch 4 → 5 taken 61 times.
✗ Branch 4 → 23 not taken.
61 if (g_task_return_error_if_cancelled (task))
1829 return;
1830
1831
1/2
✗ Branch 5 → 6 not taken.
✓ Branch 5 → 8 taken 61 times.
61 if (!priv->is_open)
1832 {
1833 g_task_return_error (task,
1834 fpi_device_error_new (FP_DEVICE_ERROR_NOT_OPEN));
1835 return;
1836 }
1837
1838
1/2
✗ Branch 8 → 9 not taken.
✓ Branch 8 → 12 taken 61 times.
61 if (priv->current_task)
1839 {
1840 g_task_return_error (task,
1841 fpi_device_error_new (FP_DEVICE_ERROR_BUSY));
1842 return;
1843 }
1844
1845
1/2
✗ Branch 12 → 13 not taken.
✓ Branch 12 → 16 taken 61 times.
61 if (!(priv->features & FP_DEVICE_FEATURE_STORAGE))
1846 {
1847 g_task_return_error (task,
1848 fpi_device_error_new_msg (FP_DEVICE_ERROR_NOT_SUPPORTED,
1849 "Device has no storage."));
1850 return;
1851 }
1852
1853
1/2
✗ Branch 16 → 17 not taken.
✓ Branch 16 → 20 taken 61 times.
61 if (!(priv->features & FP_DEVICE_FEATURE_STORAGE_CLEAR))
1854 {
1855 g_task_return_error (task,
1856 fpi_device_error_new_msg (FP_DEVICE_ERROR_NOT_SUPPORTED,
1857 "Device doesn't support clearing storage."));
1858 return;
1859 }
1860
1861 61 priv->current_action = FPI_DEVICE_ACTION_CLEAR_STORAGE;
1862 61 priv->current_task = g_steal_pointer (&task);
1863 61 setup_task_cancellable (device);
1864
1865 61 cls->clear_storage (device);
1866
1867 61 return;
1868 }
1869
1870 /**
1871 * fp_device_clear_storage_finish:
1872 * @device: A #FpDevice
1873 * @result: A #GAsyncResult
1874 * @error: Return location for errors, or %NULL to ignore
1875 *
1876 * Finish an asynchronous operation to delete all enrolled prints.
1877 *
1878 * See fp_device_clear_storage().
1879 *
1880 * Returns: (type void): %FALSE on error, %TRUE otherwise
1881 */
1882 gboolean
1883 61 fp_device_clear_storage_finish (FpDevice *device,
1884 GAsyncResult *result,
1885 GError **error)
1886 {
1887 61 return g_task_propagate_boolean (G_TASK (result), error);
1888 }
1889
1890 static void
1891 704 async_result_ready (GObject *source_object, GAsyncResult *res, gpointer user_data)
1892 {
1893 704 GTask **task = user_data;
1894
1895 704 *task = g_object_ref (G_TASK (res));
1896 704 }
1897
1898 /**
1899 * fp_device_open_sync:
1900 * @device: a #FpDevice
1901 * @cancellable: (nullable): a #GCancellable, or %NULL
1902 * @error: Return location for errors, or %NULL to ignore
1903 *
1904 * Open the device synchronously.
1905 *
1906 * Returns: (type void): %FALSE on error, %TRUE otherwise
1907 */
1908 gboolean
1909 212 fp_device_open_sync (FpDevice *device,
1910 GCancellable *cancellable,
1911 GError **error)
1912 {
1913 424 g_autoptr(GAsyncResult) task = NULL;
1914
1915
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 212 times.
212 g_return_val_if_fail (FP_IS_DEVICE (device), FALSE);
1916
1917 212 fp_device_open (device, cancellable, async_result_ready, &task);
1918
2/2
✓ Branch 8 → 7 taken 455 times.
✓ Branch 8 → 9 taken 212 times.
667 while (!task)
1919 455 g_main_context_iteration (NULL, TRUE);
1920
1921 212 return fp_device_open_finish (device, task, error);
1922 }
1923
1924 /**
1925 * fp_device_close_sync:
1926 * @device: a #FpDevice
1927 * @cancellable: (nullable): a #GCancellable, or %NULL
1928 * @error: Return location for errors, or %NULL to ignore
1929 *
1930 * Close the device synchronously.
1931 *
1932 * Returns: (type void): %FALSE on error, %TRUE otherwise
1933 */
1934 gboolean
1935 207 fp_device_close_sync (FpDevice *device,
1936 GCancellable *cancellable,
1937 GError **error)
1938 {
1939 414 g_autoptr(GAsyncResult) task = NULL;
1940
1941
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 207 times.
207 g_return_val_if_fail (FP_IS_DEVICE (device), FALSE);
1942
1943 207 fp_device_close (device, cancellable, async_result_ready, &task);
1944
2/2
✓ Branch 8 → 7 taken 291 times.
✓ Branch 8 → 9 taken 207 times.
498 while (!task)
1945 291 g_main_context_iteration (NULL, TRUE);
1946
1947 207 return fp_device_close_finish (device, task, error);
1948 }
1949
1950 /**
1951 * fp_device_enroll_sync:
1952 * @device: a #FpDevice
1953 * @template_print: (transfer floating): A #FpPrint to fill in or use
1954 * as a template.
1955 * @cancellable: (nullable): a #GCancellable, or %NULL
1956 * @progress_cb: (nullable) (scope call): progress reporting callback
1957 * @progress_data: user data for @progress_cb
1958 * @error: Return location for errors, or %NULL to ignore
1959 *
1960 * Enroll a new print. See fp_device_enroll(). It is undefined whether
1961 * @template_print is updated or a newly created #FpPrint is returned.
1962 *
1963 * Returns:(transfer full): A #FpPrint on success, %NULL otherwise
1964 */
1965 FpPrint *
1966 40 fp_device_enroll_sync (FpDevice *device,
1967 FpPrint *template_print,
1968 GCancellable *cancellable,
1969 FpEnrollProgress progress_cb,
1970 gpointer progress_data,
1971 GError **error)
1972 {
1973 80 g_autoptr(GAsyncResult) task = NULL;
1974
1975
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 40 times.
40 g_return_val_if_fail (FP_IS_DEVICE (device), FALSE);
1976
1977 40 fp_device_enroll (device, template_print, cancellable,
1978 progress_cb, progress_data, NULL,
1979 async_result_ready, &task);
1980
2/2
✓ Branch 8 → 7 taken 3536 times.
✓ Branch 8 → 9 taken 40 times.
3576 while (!task)
1981 3536 g_main_context_iteration (NULL, TRUE);
1982
1983 40 return fp_device_enroll_finish (device, task, error);
1984 }
1985
1986 /**
1987 * fp_device_verify_sync:
1988 * @device: a #FpDevice
1989 * @enrolled_print: a #FpPrint to verify
1990 * @cancellable: (nullable): a #GCancellable, or %NULL
1991 * @match_cb: (nullable) (scope call) (closure match_data): match reporting callback
1992 * @match_data: user data for @match_cb
1993 * @match: (out): Whether the user presented the correct finger
1994 * @print: (out) (transfer full) (nullable): Location to store the scanned print, or %NULL to ignore
1995 * @error: Return location for errors, or %NULL to ignore
1996 *
1997 * Verify a given print synchronously.
1998 *
1999 * Returns: (type void): %FALSE on error, %TRUE otherwise
2000 */
2001 gboolean
2002 51 fp_device_verify_sync (FpDevice *device,
2003 FpPrint *enrolled_print,
2004 GCancellable *cancellable,
2005 FpMatchCb match_cb,
2006 gpointer match_data,
2007 gboolean *match,
2008 FpPrint **print,
2009 GError **error)
2010 {
2011 102 g_autoptr(GAsyncResult) task = NULL;
2012
2013
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 51 times.
51 g_return_val_if_fail (FP_IS_DEVICE (device), FALSE);
2014
2015 51 fp_device_verify (device,
2016 enrolled_print,
2017 cancellable,
2018 match_cb, match_data, NULL,
2019 async_result_ready, &task);
2020
2/2
✓ Branch 8 → 7 taken 426 times.
✓ Branch 8 → 9 taken 51 times.
477 while (!task)
2021 426 g_main_context_iteration (NULL, TRUE);
2022
2023 51 return fp_device_verify_finish (device, task, match, print, error);
2024 }
2025
2026 /**
2027 * fp_device_identify_sync:
2028 * @device: a #FpDevice
2029 * @prints: (element-type FpPrint) (transfer none): #GPtrArray of #FpPrint
2030 * @cancellable: (nullable): a #GCancellable, or %NULL
2031 * @match_cb: (nullable) (scope call) (closure match_data): match reporting callback
2032 * @match_data: user data for @match_cb
2033 * @match: (out) (transfer full) (nullable): Location for the matched #FpPrint, or %NULL
2034 * @print: (out) (transfer full) (nullable): Location for the new #FpPrint, or %NULL
2035 * @error: Return location for errors, or %NULL to ignore
2036 *
2037 * Identify a print synchronously.
2038 *
2039 * Returns: (type void): %FALSE on error, %TRUE otherwise
2040 */
2041 gboolean
2042 21 fp_device_identify_sync (FpDevice *device,
2043 GPtrArray *prints,
2044 GCancellable *cancellable,
2045 FpMatchCb match_cb,
2046 gpointer match_data,
2047 FpPrint **match,
2048 FpPrint **print,
2049 GError **error)
2050 {
2051 42 g_autoptr(GAsyncResult) task = NULL;
2052
2053
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 21 times.
21 g_return_val_if_fail (FP_IS_DEVICE (device), FALSE);
2054
2055 21 fp_device_identify (device,
2056 prints,
2057 cancellable,
2058 match_cb, match_data, NULL,
2059 async_result_ready, &task);
2060
2/2
✓ Branch 8 → 7 taken 33 times.
✓ Branch 8 → 9 taken 21 times.
54 while (!task)
2061 33 g_main_context_iteration (NULL, TRUE);
2062
2063 21 return fp_device_identify_finish (device, task, match, print, error);
2064 }
2065
2066
2067 /**
2068 * fp_device_capture_sync:
2069 * @device: a #FpDevice
2070 * @wait_for_finger: Whether to wait for a finger or not
2071 * @cancellable: (nullable): a #GCancellable, or %NULL
2072 * @error: Return location for errors, or %NULL to ignore
2073 *
2074 * Start an synchronous operation to capture an image.
2075 *
2076 * Returns: (transfer full): A new #FpImage or %NULL on error
2077 */
2078 FpImage *
2079 25 fp_device_capture_sync (FpDevice *device,
2080 gboolean wait_for_finger,
2081 GCancellable *cancellable,
2082 GError **error)
2083 {
2084 50 g_autoptr(GAsyncResult) task = NULL;
2085
2086
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 25 times.
25 g_return_val_if_fail (FP_IS_DEVICE (device), FALSE);
2087
2088 25 fp_device_capture (device,
2089 wait_for_finger,
2090 cancellable,
2091 async_result_ready, &task);
2092
2/2
✓ Branch 8 → 7 taken 24684 times.
✓ Branch 8 → 9 taken 25 times.
24709 while (!task)
2093 24684 g_main_context_iteration (NULL, TRUE);
2094
2095 25 return fp_device_capture_finish (device, task, error);
2096 }
2097
2098 /**
2099 * fp_device_delete_print_sync:
2100 * @device: a #FpDevice
2101 * @enrolled_print: a #FpPrint to verify
2102 * @cancellable: (nullable): a #GCancellable, or %NULL
2103 * @error: Return location for errors, or %NULL to ignore
2104 *
2105 * Delete a given print from the device.
2106 *
2107 * Returns: (type void): %FALSE on error, %TRUE otherwise
2108 */
2109 gboolean
2110 25 fp_device_delete_print_sync (FpDevice *device,
2111 FpPrint *enrolled_print,
2112 GCancellable *cancellable,
2113 GError **error)
2114 {
2115 50 g_autoptr(GAsyncResult) task = NULL;
2116
2117
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 25 times.
25 g_return_val_if_fail (FP_IS_DEVICE (device), FALSE);
2118
2119 25 fp_device_delete_print (device,
2120 enrolled_print,
2121 cancellable,
2122 async_result_ready, &task);
2123
2/2
✓ Branch 8 → 7 taken 92 times.
✓ Branch 8 → 9 taken 25 times.
117 while (!task)
2124 92 g_main_context_iteration (NULL, TRUE);
2125
2126 25 return fp_device_delete_print_finish (device, task, error);
2127 }
2128
2129 /**
2130 * fp_device_list_prints_sync:
2131 * @device: a #FpDevice
2132 * @cancellable: (nullable): a #GCancellable, or %NULL
2133 * @error: Return location for errors, or %NULL to ignore
2134 *
2135 * List device stored prints synchronously.
2136 *
2137 * Returns: (element-type FpPrint) (transfer container): Array of prints, or %NULL on error
2138 */
2139 GPtrArray *
2140 54 fp_device_list_prints_sync (FpDevice *device,
2141 GCancellable *cancellable,
2142 GError **error)
2143 {
2144 108 g_autoptr(GAsyncResult) task = NULL;
2145
2146
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 54 times.
54 g_return_val_if_fail (FP_IS_DEVICE (device), FALSE);
2147
2148 54 fp_device_list_prints (device,
2149 NULL,
2150 async_result_ready, &task);
2151
2/2
✓ Branch 8 → 7 taken 195 times.
✓ Branch 8 → 9 taken 54 times.
249 while (!task)
2152 195 g_main_context_iteration (NULL, TRUE);
2153
2154 54 return fp_device_list_prints_finish (device, task, error);
2155 }
2156
2157
2158 /**
2159 * fp_device_clear_storage_sync:
2160 * @device: a #FpDevice
2161 * @cancellable: (nullable): a #GCancellable, or %NULL
2162 * @error: Return location for errors, or %NULL to ignore
2163 *
2164 * Clear sensor storage.
2165 *
2166 * Returns: (type void): %FALSE on error, %TRUE otherwise
2167 */
2168 gboolean
2169 61 fp_device_clear_storage_sync (FpDevice *device,
2170 GCancellable *cancellable,
2171 GError **error)
2172 {
2173 122 g_autoptr(GAsyncResult) task = NULL;
2174
2175
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 61 times.
61 g_return_val_if_fail (FP_IS_DEVICE (device), FALSE);
2176
2177 61 fp_device_clear_storage (device,
2178 cancellable,
2179 async_result_ready, &task);
2180
2/2
✓ Branch 8 → 7 taken 127 times.
✓ Branch 8 → 9 taken 61 times.
188 while (!task)
2181 127 g_main_context_iteration (NULL, TRUE);
2182
2183 61 return fp_device_clear_storage_finish (device, task, error);
2184 }
2185
2186 /**
2187 * fp_device_suspend_sync:
2188 * @device: a #FpDevice
2189 * @cancellable: (nullable): a #GCancellable, or %NULL, currently not used
2190 * @error: Return location for errors, or %NULL to ignore
2191 *
2192 * Prepare device for suspend.
2193 *
2194 * Returns: (type void): %FALSE on error, %TRUE otherwise
2195 */
2196 gboolean
2197 4 fp_device_suspend_sync (FpDevice *device,
2198 GCancellable *cancellable,
2199 GError **error)
2200 {
2201 8 g_autoptr(GAsyncResult) task = NULL;
2202
2203
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 4 times.
4 g_return_val_if_fail (FP_IS_DEVICE (device), FALSE);
2204
2205 4 fp_device_suspend (device, cancellable, async_result_ready, &task);
2206
2/2
✓ Branch 8 → 7 taken 10 times.
✓ Branch 8 → 9 taken 4 times.
14 while (!task)
2207 10 g_main_context_iteration (NULL, TRUE);
2208
2209 4 return fp_device_suspend_finish (device, task, error);
2210 }
2211
2212 /**
2213 * fp_device_resume_sync:
2214 * @device: a #FpDevice
2215 * @cancellable: (nullable): a #GCancellable, or %NULL, currently not used
2216 * @error: Return location for errors, or %NULL to ignore
2217 *
2218 * Resume device after suspend.
2219 *
2220 * Returns: (type void): %FALSE on error, %TRUE otherwise
2221 */
2222 gboolean
2223 4 fp_device_resume_sync (FpDevice *device,
2224 GCancellable *cancellable,
2225 GError **error)
2226 {
2227 8 g_autoptr(GAsyncResult) task = NULL;
2228
2229
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 4 times.
4 g_return_val_if_fail (FP_IS_DEVICE (device), FALSE);
2230
2231 4 fp_device_resume (device, cancellable, async_result_ready, &task);
2232
2/2
✓ Branch 8 → 7 taken 5 times.
✓ Branch 8 → 9 taken 4 times.
9 while (!task)
2233 5 g_main_context_iteration (NULL, TRUE);
2234
2235 4 return fp_device_resume_finish (device, task, error);
2236 }
2237
2238 /**
2239 * fp_device_get_features:
2240 * @device: a #FpDevice
2241 *
2242 * Gets the #FpDeviceFeature's supported by the @device.
2243 *
2244 * Returns: #FpDeviceFeature flags of supported features
2245 */
2246 FpDeviceFeature
2247 362 fp_device_get_features (FpDevice *device)
2248 {
2249 362 FpDevicePrivate *priv = fp_device_get_instance_private (device);
2250
2251
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 362 times.
362 g_return_val_if_fail (FP_IS_DEVICE (device), FP_DEVICE_FEATURE_NONE);
2252
2253 362 return priv->features;
2254 }
2255
2256 /**
2257 * fp_device_has_feature:
2258 * @device: a #FpDevice
2259 * @feature: #FpDeviceFeature flags to check against device supported features
2260 *
2261 * Checks if @device supports the requested #FpDeviceFeature's.
2262 * See fp_device_get_features()
2263 *
2264 * Returns: %TRUE if supported, %FALSE otherwise
2265 */
2266 gboolean
2267 296 fp_device_has_feature (FpDevice *device,
2268 FpDeviceFeature feature)
2269 {
2270
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 296 times.
296 g_return_val_if_fail (FP_IS_DEVICE (device), FALSE);
2271
2272
1/2
✗ Branch 5 → 6 not taken.
✓ Branch 5 → 8 taken 296 times.
296 if (feature == FP_DEVICE_FEATURE_NONE)
2273 return fp_device_get_features (device) == feature;
2274
2275 296 return (fp_device_get_features (device) & feature) == feature;
2276 }
2277