GCC Code Coverage Report


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