GCC Code Coverage Report


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 74.7% 718 / 0 / 961
Functions: 89.6% 43 / 0 / 48
Branches: 48.9% 153 / 0 / 313

libfprint/drivers/fpcmoc/fpc.c
Line Branch Exec Source
1 /*
2 * Copyright (c) 2022 Fingerprint Cards AB <tech@fingerprints.com>
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18
19 #include "drivers_api.h"
20 #include "fpc.h"
21
22 #define FP_COMPONENT "fpcmoc"
23 #define MAX_ENROLL_SAMPLES (25)
24 #define CTRL_TIMEOUT (2000)
25 #define DATA_TIMEOUT (5000)
26
27 /* Usb port setting */
28 #define EP_IN (1 | FPI_USB_ENDPOINT_IN)
29 #define EP_IN_MAX_BUF_SIZE (2048)
30
31 struct _FpiDeviceFpcMoc
32 {
33 FpDevice parent;
34 FpiSsm *task_ssm;
35 FpiSsm *cmd_ssm;
36 gboolean cmd_suspended;
37 gint enroll_stage;
38 gint immobile_stage;
39 gint max_enroll_stage;
40 gint max_immobile_stage;
41 gint max_stored_prints;
42 guint cmd_data_timeout;
43 guint8 *dbid;
44 gboolean do_cleanup;
45 GCancellable *interrupt_cancellable;
46 };
47
48
4/6
fpi_device_fpcmoc_class_intern_init:
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 122 times.
fpi_device_fpcmoc_get_type:
✓ Branch 2 → 3 taken 122 times.
✓ Branch 2 → 7 taken 24 times.
✓ Branch 4 → 5 taken 122 times.
✗ Branch 4 → 7 not taken.
390 G_DEFINE_TYPE (FpiDeviceFpcMoc, fpi_device_fpcmoc, FP_TYPE_DEVICE);
49
50 typedef void (*SynCmdMsgCallback) (FpiDeviceFpcMoc *self,
51 void *resp,
52 GError *error);
53
54 typedef struct
55 {
56 FpcCmdType cmdtype;
57 guint8 request;
58 guint16 value;
59 guint16 index;
60 guint8 *data;
61 gsize data_len;
62 SynCmdMsgCallback callback;
63 } CommandData;
64
65 static const FpIdEntry id_table[] = {
66 { .vid = 0x10A5, .pid = 0xFFE0, },
67 { .vid = 0x10A5, .pid = 0xA305, },
68 { .vid = 0x10A5, .pid = 0xA306, },
69 { .vid = 0x10A5, .pid = 0xDA04, },
70 { .vid = 0x10A5, .pid = 0xD805, },
71 { .vid = 0x10A5, .pid = 0xD205, },
72 { .vid = 0x10A5, .pid = 0x9524, },
73 { .vid = 0x10A5, .pid = 0x9544, },
74 { .vid = 0x10A5, .pid = 0xC844, },
75 { .vid = 0x10A5, .pid = 0x9B24, },
76 /* terminating entry */
77 { .vid = 0, .pid = 0, .driver_data = 0 },
78 };
79
80 static void
81 fpc_suspend_resume_cb (FpiUsbTransfer *transfer,
82 FpDevice *device,
83 gpointer user_data,
84 GError *error)
85 {
86 int ssm_state = fpi_ssm_get_cur_state (transfer->ssm);
87
88 fp_dbg ("%s current ssm state: %d", G_STRFUNC, ssm_state);
89
90 if (ssm_state == FPC_CMD_SUSPENDED)
91 {
92 if (error)
93 fpi_ssm_mark_failed (transfer->ssm, error);
94
95 fpi_device_suspend_complete (device, error);
96 /* The resume handler continues to the next state! */
97 }
98 else if (ssm_state == FPC_CMD_RESUME)
99 {
100 if (error)
101 fpi_ssm_mark_failed (transfer->ssm, error);
102 else
103 fpi_ssm_jump_to_state (transfer->ssm, FPC_CMD_GET_DATA);
104
105 fpi_device_resume_complete (device, error);
106 }
107 }
108
109 static void
110 103 fpc_cmd_receive_cb (FpiUsbTransfer *transfer,
111 FpDevice *device,
112 gpointer user_data,
113 GError *error)
114 {
115 103 FpiDeviceFpcMoc *self = FPI_DEVICE_FPCMOC (device);
116 103 CommandData *data = user_data;
117 103 int ssm_state = 0;
118
119
1/4
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 9 taken 103 times.
✗ Branch 5 → 6 not taken.
✗ Branch 5 → 9 not taken.
103 if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED) && (self->cmd_suspended))
120 {
121 g_error_free (error);
122 fpi_ssm_jump_to_state (transfer->ssm, FPC_CMD_SUSPENDED);
123 return;
124 }
125
126
1/2
✗ Branch 9 → 10 not taken.
✓ Branch 9 → 12 taken 103 times.
103 if (error)
127 {
128 fpi_ssm_mark_failed (transfer->ssm, error);
129 return;
130 }
131
132
1/2
✗ Branch 12 → 13 not taken.
✓ Branch 12 → 16 taken 103 times.
103 if (data == NULL)
133 {
134 fpi_ssm_mark_failed (transfer->ssm,
135 fpi_device_error_new (FP_DEVICE_ERROR_GENERAL));
136 return;
137 }
138
139 103 ssm_state = fpi_ssm_get_cur_state (transfer->ssm);
140 103 fp_dbg ("%s current ssm request: %d state: %d", G_STRFUNC, data->request, ssm_state);
141
142 /* clean cmd_ssm except capture command for suspend/resume case */
143
4/4
✓ Branch 18 → 19 taken 66 times.
✓ Branch 18 → 20 taken 37 times.
✓ Branch 19 → 20 taken 49 times.
✓ Branch 19 → 21 taken 17 times.
103 if (ssm_state != FPC_CMD_SEND || data->request != FPC_CMD_ARM)
144 86 self->cmd_ssm = NULL;
145
146
2/2
✓ Branch 21 → 22 taken 7 times.
✓ Branch 21 → 26 taken 96 times.
103 if (data->cmdtype == FPC_CMDTYPE_TO_DEVICE)
147 {
148 /* It should not receive any data. */
149
1/2
✓ Branch 22 → 23 taken 7 times.
✗ Branch 22 → 24 not taken.
7 if (data->callback)
150 7 data->callback (self, NULL, NULL);
151
152 7 fpi_ssm_mark_completed (transfer->ssm);
153 7 return;
154 }
155
2/2
✓ Branch 26 → 27 taken 74 times.
✓ Branch 26 → 42 taken 22 times.
96 else if (data->cmdtype == FPC_CMDTYPE_TO_DEVICE_EVTDATA)
156 {
157
2/2
✓ Branch 27 → 28 taken 37 times.
✓ Branch 27 → 30 taken 37 times.
74 if (ssm_state == FPC_CMD_SEND)
158 {
159 37 fpi_ssm_next_state (transfer->ssm);
160 37 return;
161 }
162
163
1/2
✓ Branch 30 → 31 taken 37 times.
✗ Branch 30 → 56 not taken.
37 if (ssm_state == FPC_CMD_GET_DATA)
164 {
165 37 fpc_cmd_response_t evt_data = {0};
166 37 fp_dbg ("%s recv evt data length: %ld", G_STRFUNC, transfer->actual_length);
167
1/2
✗ Branch 32 → 33 not taken.
✓ Branch 32 → 37 taken 37 times.
37 if (transfer->actual_length == 0)
168 {
169 fp_err ("%s Expect data but actual_length = 0", G_STRFUNC);
170 fpi_ssm_mark_failed (transfer->ssm,
171 fpi_device_error_new (FP_DEVICE_ERROR_DATA_INVALID));
172 return;
173 }
174
175 37 memcpy (&evt_data, transfer->buffer, transfer->actual_length);
176
177
1/2
✓ Branch 37 → 38 taken 37 times.
✗ Branch 37 → 39 not taken.
37 if (data->callback)
178 37 data->callback (self, (guint8 *) &evt_data, NULL);
179
180 37 fpi_ssm_mark_completed (transfer->ssm);
181 37 return;
182 }
183 }
184
1/2
✓ Branch 42 → 43 taken 22 times.
✗ Branch 42 → 52 not taken.
22 else if (data->cmdtype == FPC_CMDTYPE_FROM_DEVICE)
185 {
186
1/2
✗ Branch 43 → 44 not taken.
✓ Branch 43 → 48 taken 22 times.
22 if (transfer->actual_length == 0)
187 {
188 fp_err ("%s Expect data but actual_length = 0", G_STRFUNC);
189 fpi_ssm_mark_failed (transfer->ssm,
190 fpi_device_error_new (FP_DEVICE_ERROR_DATA_INVALID));
191 return;
192 }
193
194
1/2
✓ Branch 48 → 49 taken 22 times.
✗ Branch 48 → 50 not taken.
22 if (data->callback)
195 22 data->callback (self, transfer->buffer, NULL);
196
197 22 fpi_ssm_mark_completed (transfer->ssm);
198 22 return;
199 }
200 else
201 {
202 fp_err ("%s incorrect cmdtype (%x) ", G_STRFUNC, data->cmdtype);
203 fpi_ssm_mark_failed (transfer->ssm,
204 fpi_device_error_new (FP_DEVICE_ERROR_DATA_INVALID));
205 return;
206 }
207
208 /* should not run here... */
209 fpi_ssm_mark_failed (transfer->ssm,
210 fpi_device_error_new (FP_DEVICE_ERROR_GENERAL));
211 }
212
213 static void
214 66 fpc_send_ctrl_cmd (FpDevice *dev)
215 {
216 66 FpiUsbTransfer *transfer = NULL;
217 66 FpiDeviceFpcMoc *self = FPI_DEVICE_FPCMOC (dev);
218 66 CommandData *cmd_data = fpi_ssm_get_data (self->cmd_ssm);
219 66 FpcCmdType cmdtype = FPC_CMDTYPE_UNKNOWN;
220
221
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 7 taken 66 times.
66 if (!cmd_data)
222 {
223 fp_err ("%s No cmd_data is set ", G_STRFUNC);
224 fpi_ssm_mark_failed (self->cmd_ssm,
225 fpi_device_error_new (FP_DEVICE_ERROR_GENERAL));
226 }
227
228 66 cmdtype = cmd_data->cmdtype;
229
230
4/4
✓ Branch 7 → 8 taken 44 times.
✓ Branch 7 → 17 taken 22 times.
✓ Branch 8 → 9 taken 24 times.
✓ Branch 8 → 13 taken 20 times.
66 if ((cmdtype != FPC_CMDTYPE_FROM_DEVICE) && cmd_data->data_len &&
231
1/2
✗ Branch 9 → 10 not taken.
✓ Branch 9 → 13 taken 24 times.
24 (cmd_data->data == NULL))
232 {
233 fp_err ("%s data buffer is null but len is not! ", G_STRFUNC);
234 fpi_ssm_mark_failed (self->cmd_ssm,
235 fpi_device_error_new (FP_DEVICE_ERROR_GENERAL));
236 }
237
238
1/2
✗ Branch 13 → 14 not taken.
✓ Branch 13 → 17 taken 44 times.
44 if (cmdtype == FPC_CMDTYPE_UNKNOWN)
239 {
240 fp_err ("%s unknown cmd type ", G_STRFUNC);
241 fpi_ssm_mark_failed (self->cmd_ssm,
242 fpi_device_error_new (FP_DEVICE_ERROR_DATA_INVALID));
243 }
244
245 66 fp_dbg ("%s CMD: 0x%x, value: 0x%x, index: %x type: %d", G_STRFUNC,
246 cmd_data->request, cmd_data->value, cmd_data->index, cmdtype);
247
248 66 transfer = fpi_usb_transfer_new (dev);
249 66 fpi_usb_transfer_fill_control (transfer,
250 ((cmdtype == FPC_CMDTYPE_FROM_DEVICE) ?
251 (G_USB_DEVICE_DIRECTION_DEVICE_TO_HOST) :
252 (G_USB_DEVICE_DIRECTION_HOST_TO_DEVICE)),
253 G_USB_DEVICE_REQUEST_TYPE_VENDOR,
254 G_USB_DEVICE_RECIPIENT_DEVICE,
255 cmd_data->request,
256 cmd_data->value,
257 cmd_data->index,
258 cmd_data->data_len);
259
260 66 transfer->ssm = self->cmd_ssm;
261
2/2
✓ Branch 20 → 21 taken 44 times.
✓ Branch 20 → 24 taken 22 times.
66 if (cmdtype != FPC_CMDTYPE_FROM_DEVICE &&
262
2/2
✓ Branch 21 → 22 taken 24 times.
✓ Branch 21 → 24 taken 20 times.
44 cmd_data->data != NULL &&
263
1/2
✓ Branch 22 → 23 taken 24 times.
✗ Branch 22 → 24 not taken.
24 cmd_data->data_len != 0)
264 24 memcpy (transfer->buffer, cmd_data->data, cmd_data->data_len);
265
266 66 fpi_usb_transfer_submit (transfer, CTRL_TIMEOUT, NULL,
267 fpc_cmd_receive_cb,
268 fpi_ssm_get_data (transfer->ssm));
269 66 }
270
271 static void
272 66 fpc_cmd_ssm_done (FpiSsm *ssm, FpDevice *dev, GError *error)
273 {
274 66 FpiDeviceFpcMoc *self = FPI_DEVICE_FPCMOC (dev);
275 66 CommandData *data;
276
277 66 self->cmd_ssm = NULL;
278 /* Notify about the SSM failure from here instead. */
279
1/2
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 7 taken 66 times.
66 if (error)
280 {
281 fp_err ("%s error: %s ", G_STRFUNC, error->message);
282 data = fpi_ssm_get_data (ssm);
283 if (data->callback)
284 data->callback (self, NULL, error);
285 }
286 66 }
287
288 static void
289 103 fpc_cmd_run_state (FpiSsm *ssm,
290 FpDevice *dev)
291 {
292 103 FpiUsbTransfer *transfer = NULL;
293 103 FpiDeviceFpcMoc *self = FPI_DEVICE_FPCMOC (dev);
294
295
2/5
✓ Branch 3 → 4 taken 66 times.
✓ Branch 3 → 6 taken 37 times.
✗ Branch 3 → 11 not taken.
✗ Branch 3 → 15 not taken.
✗ Branch 3 → 19 not taken.
103 switch (fpi_ssm_get_cur_state (ssm))
296 {
297 66 case FPC_CMD_SEND:
298 66 fpc_send_ctrl_cmd (dev);
299 66 break;
300
301 37 case FPC_CMD_GET_DATA:
302 37 transfer = fpi_usb_transfer_new (dev);
303 37 transfer->ssm = ssm;
304 37 fpi_usb_transfer_fill_bulk (transfer, EP_IN, EP_IN_MAX_BUF_SIZE);
305 37 fpi_usb_transfer_submit (transfer,
306 self->cmd_data_timeout,
307 self->interrupt_cancellable,
308 fpc_cmd_receive_cb,
309 fpi_ssm_get_data (ssm));
310 37 break;
311
312 case FPC_CMD_SUSPENDED:
313 transfer = fpi_usb_transfer_new (dev);
314 transfer->ssm = ssm;
315 fpi_usb_transfer_fill_control (transfer,
316 G_USB_DEVICE_DIRECTION_HOST_TO_DEVICE,
317 G_USB_DEVICE_REQUEST_TYPE_VENDOR,
318 G_USB_DEVICE_RECIPIENT_DEVICE,
319 FPC_CMD_INDICATE_S_STATE,
320 FPC_HOST_MS_SX,
321 0,
322 0);
323
324 fpi_usb_transfer_submit (transfer, CTRL_TIMEOUT, NULL,
325 fpc_suspend_resume_cb, NULL);
326 break;
327
328 case FPC_CMD_RESUME:
329 transfer = fpi_usb_transfer_new (dev);
330 transfer->ssm = ssm;
331 fpi_usb_transfer_fill_control (transfer,
332 G_USB_DEVICE_DIRECTION_HOST_TO_DEVICE,
333 G_USB_DEVICE_REQUEST_TYPE_VENDOR,
334 G_USB_DEVICE_RECIPIENT_DEVICE,
335 FPC_CMD_INDICATE_S_STATE,
336 FPC_HOST_MS_S0,
337 0,
338 0);
339
340 fpi_usb_transfer_submit (transfer, CTRL_TIMEOUT, NULL,
341 fpc_suspend_resume_cb, NULL);
342 break;
343 }
344
345 103 }
346
347 static void
348 66 fpc_sensor_cmd (FpiDeviceFpcMoc *self,
349 gboolean wait_data_delay,
350 CommandData *cmd_data)
351 {
352 66 CommandData *data = NULL;
353
354
1/2
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 4 taken 66 times.
66 g_return_if_fail (cmd_data);
355
1/2
✓ Branch 4 → 5 taken 66 times.
✗ Branch 4 → 7 not taken.
66 g_return_if_fail (cmd_data->cmdtype != FPC_CMDTYPE_UNKNOWN);
356
357 66 data = g_memdup2 (cmd_data, sizeof (CommandData));
358
359
2/2
✓ Branch 6 → 8 taken 17 times.
✓ Branch 6 → 9 taken 49 times.
66 g_clear_object (&self->interrupt_cancellable);
360
361
2/2
✓ Branch 9 → 10 taken 17 times.
✓ Branch 9 → 12 taken 49 times.
66 if (wait_data_delay)
362 {
363 17 self->cmd_data_timeout = 0;
364 17 self->interrupt_cancellable = g_cancellable_new ();
365 }
366 else
367 {
368 49 self->cmd_data_timeout = DATA_TIMEOUT;
369 }
370
371
1/2
✓ Branch 13 → 14 taken 66 times.
✗ Branch 13 → 17 not taken.
66 g_assert (self->cmd_ssm == NULL);
372 66 self->cmd_ssm = fpi_ssm_new (FP_DEVICE (self),
373 fpc_cmd_run_state,
374 FPC_CMD_NUM_STATES);
375
376 66 fpi_ssm_set_data (self->cmd_ssm, data, g_free);
377 66 fpi_ssm_start (self->cmd_ssm, fpc_cmd_ssm_done);
378 }
379
380 static void
381 1 fpc_dev_release_interface (FpiDeviceFpcMoc *self,
382 GError *error)
383 {
384 1 g_autoptr(GError) release_error = NULL;
385
386 /* Release usb interface */
387 1 g_usb_device_release_interface (fpi_device_get_usb_device (FP_DEVICE (self)),
388 0, 0, &release_error);
389 /* Retain passed error if set, otherwise propagate error from release. */
390
1/2
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 9 taken 1 time.
1 if (error)
391 {
392 fpi_device_close_complete (FP_DEVICE (self), error);
393 return;
394 }
395
396 /* Notify close complete */
397
1/2
✗ Branch 10 → 11 not taken.
✓ Branch 10 → 12 taken 1 time.
1 fpi_device_close_complete (FP_DEVICE (self), g_steal_pointer (&release_error));
398 }
399
400 static gboolean
401 57 check_data (void *data, GError **error)
402 {
403
1/2
✓ Branch 2 → 3 taken 57 times.
✗ Branch 2 → 7 not taken.
57 if (*error != NULL)
404 return FALSE;
405
406
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 7 taken 57 times.
57 if (data == NULL)
407 {
408 g_propagate_error (error,
409 fpi_device_error_new (FP_DEVICE_ERROR_DATA_INVALID));
410 return FALSE;
411 }
412
413 return TRUE;
414 }
415
416 static void
417 36 fpc_evt_cb (FpiDeviceFpcMoc *self,
418 void *data,
419 GError *error)
420 {
421 36 pfpc_cmd_response_t presp = NULL;
422
423
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 7 taken 36 times.
36 if (!check_data (data, &error))
424 {
425 fp_err ("%s error: %s", G_STRFUNC, error->message);
426 fpi_ssm_mark_failed (self->task_ssm, error);
427 return;
428 }
429
430 36 presp = (pfpc_cmd_response_t) data;
431
432
4/5
✓ Branch 7 → 8 taken 1 time.
✓ Branch 7 → 14 taken 1 time.
✓ Branch 7 → 16 taken 17 times.
✓ Branch 7 → 22 taken 17 times.
✗ Branch 7 → 25 not taken.
36 switch (presp->evt_hdr.cmdid)
433 {
434 1 case FPC_EVT_FID_DATA:
435 1 fp_dbg ("%s Enum Fids: status = %d, NumFids = %d", G_STRFUNC,
436 presp->evt_enum_fids.status, presp->evt_enum_fids.num_ids);
437
2/4
✓ Branch 9 → 10 taken 1 time.
✗ Branch 9 → 11 not taken.
✗ Branch 10 → 11 not taken.
✓ Branch 10 → 29 taken 1 time.
1 if (presp->evt_enum_fids.status || (presp->evt_enum_fids.num_ids > FPC_TEMPLATES_MAX))
438 {
439 fpi_ssm_mark_failed (self->task_ssm,
440 fpi_device_error_new_msg (FP_DEVICE_ERROR_DATA_INVALID,
441 "Get Fids failed"));
442 return;
443 }
444 break;
445
446 1 case FPC_EVT_INIT_RESULT:
447 1 fp_dbg ("%s INIT: status=%d, Sensor = %d, HWID = 0x%04X, WxH = %d x %d", G_STRFUNC,
448 presp->evt_inited.hdr.status, presp->evt_inited.sensor,
449 presp->evt_inited.hw_id, presp->evt_inited.img_w, presp->evt_inited.img_h);
450
451 1 fp_dbg ("%s INIT: FW version: %s", G_STRFUNC, (gchar *) presp->evt_inited.fw_version);
452 1 break;
453
454 17 case FPC_EVT_FINGER_DWN:
455 17 fp_dbg ("%s Got finger down event (%d)", G_STRFUNC, presp->evt_hdr.status);
456 17 fpi_device_report_finger_status_changes (FP_DEVICE (self),
457 FP_FINGER_STATUS_PRESENT,
458 FP_FINGER_STATUS_NONE);
459
1/2
✗ Branch 18 → 19 not taken.
✓ Branch 18 → 29 taken 17 times.
17 if (presp->evt_hdr.status != 0)
460 {
461 /* Redo the current task state if capture failed */
462 fpi_ssm_jump_to_state (self->task_ssm, fpi_ssm_get_cur_state (self->task_ssm));
463 return;
464 }
465 break;
466
467 17 case FPC_EVT_IMG:
468 17 fp_dbg ("%s Got capture event", G_STRFUNC);
469 17 fpi_device_report_finger_status_changes (FP_DEVICE (self),
470 FP_FINGER_STATUS_NONE,
471 FP_FINGER_STATUS_PRESENT);
472 17 break;
473
474 default:
475 fpi_ssm_mark_failed (self->task_ssm,
476 fpi_device_error_new_msg (FP_DEVICE_ERROR_GENERAL,
477 "Unknown Evt (0x%x)!", presp->evt_hdr.cmdid));
478 return;
479 }
480
481 36 fpi_ssm_next_state (self->task_ssm);
482 }
483
484 static void
485 3 fpc_do_abort_cb (FpiDeviceFpcMoc *self,
486 void *data,
487 GError *error)
488 {
489
1/2
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 6 taken 3 times.
3 if (error)
490 {
491 fp_err ("%s error: %s ", G_STRFUNC, error->message);
492 fpi_ssm_mark_failed (self->task_ssm, error);
493 return;
494 }
495
496 3 fp_dbg ("%s Do abort for reasons", G_STRFUNC);
497 3 fpi_ssm_next_state (self->task_ssm);
498 }
499
500 static void
501 fpc_do_cleanup_cb (FpiDeviceFpcMoc *self,
502 void *data,
503 GError *error)
504 {
505 if (error)
506 {
507 fp_err ("%s error: %s ", G_STRFUNC, error->message);
508 fpi_ssm_mark_failed (self->task_ssm, error);
509 return;
510 }
511
512 fp_dbg ("%s Do cleanup for reasons", G_STRFUNC);
513 self->do_cleanup = FALSE;
514 fpi_ssm_next_state (self->task_ssm);
515 }
516
517 static void
518 1 fpc_template_delete_cb (FpiDeviceFpcMoc *self,
519 void *resp,
520 GError *error)
521 {
522 1 FpDevice *device = FP_DEVICE (self);
523
524 1 fpi_device_delete_complete (device, error);
525 1 }
526
527 static gboolean
528 1 parse_print_data (GVariant *data,
529 guint8 *finger,
530 const guint8 **user_id,
531 gsize *user_id_len)
532 {
533 2 g_autoptr(GVariant) user_id_var = NULL;
534
535
1/2
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 4 taken 1 time.
1 g_return_val_if_fail (data, FALSE);
536
1/2
✓ Branch 4 → 5 taken 1 time.
✗ Branch 4 → 6 not taken.
1 g_return_val_if_fail (finger, FALSE);
537
1/2
✓ Branch 5 → 7 taken 1 time.
✗ Branch 5 → 8 not taken.
1 g_return_val_if_fail (user_id, FALSE);
538
1/2
✓ Branch 7 → 9 taken 1 time.
✗ Branch 7 → 11 not taken.
1 g_return_val_if_fail (user_id_len, FALSE);
539
540 1 *user_id = NULL;
541 1 *user_id_len = 0;
542 1 *finger = FPC_SUBTYPE_NOINFORMATION;
543
544
1/2
✓ Branch 10 → 12 taken 1 time.
✗ Branch 10 → 19 not taken.
1 if (!g_variant_check_format_string (data, "(y@ay)", FALSE))
545 return FALSE;
546
547 1 g_variant_get (data,
548 "(y@ay)",
549 finger,
550 &user_id_var);
551
552 1 *user_id = g_variant_get_fixed_array (user_id_var, user_id_len, 1);
553
554
1/2
✓ Branch 14 → 15 taken 1 time.
✗ Branch 14 → 19 not taken.
1 if (*user_id_len == 0 || *user_id_len > SECURITY_MAX_SID_SIZE)
555 return FALSE;
556
557
2/4
✓ Branch 15 → 16 taken 1 time.
✗ Branch 15 → 19 not taken.
✓ Branch 16 → 17 taken 1 time.
✗ Branch 16 → 19 not taken.
1 if (*user_id_len <= 0 || *user_id[0] == '\0' || *user_id[0] == ' ')
558 return FALSE;
559
560
1/2
✗ Branch 17 → 18 not taken.
✓ Branch 17 → 19 taken 1 time.
1 if (*finger != FPC_SUBTYPE_RESERVED)
561 return FALSE;
562
563 return TRUE;
564 }
565
566 /******************************************************************************
567 *
568 * fpc_template_xxx Function
569 *
570 *****************************************************************************/
571 static FpPrint *
572 3 fpc_print_from_data (FpiDeviceFpcMoc *self, fpc_fid_data_t *fid_data)
573 {
574 3 FpPrint *print = NULL;
575 3 GVariant *data;
576 3 GVariant *uid;
577 6 g_autofree gchar *userid = NULL;
578
579 3 userid = g_strndup ((gchar *) fid_data->identity, fid_data->identity_size);
580 3 print = fp_print_new (FP_DEVICE (self));
581
582 6 uid = g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE,
583 fid_data->identity,
584 3 fid_data->identity_size,
585 1);
586
587 6 data = g_variant_new ("(y@ay)",
588 3 fid_data->subfactor,
589 uid);
590
591 3 fpi_print_set_type (print, FPI_PRINT_RAW);
592 3 fpi_print_set_device_stored (print, TRUE);
593 3 g_object_set (print, "fpi-data", data, NULL);
594 3 g_object_set (print, "description", userid, NULL);
595 3 fpi_print_fill_from_user_id (print, userid);
596
597 3 return print;
598 }
599
600 static void
601 1 fpc_template_list_cb (FpiDeviceFpcMoc *self,
602 void *data,
603 GError *error)
604 {
605 1 g_autoptr(GPtrArray) list_result = NULL;
606 1 FpDevice *device = FP_DEVICE (self);
607 1 pfpc_cmd_response_t presp = NULL;
608
609
1/2
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 5 taken 1 time.
1 if (error)
610 {
611 fpi_device_list_complete (FP_DEVICE (self), NULL, error);
612 return;
613 }
614
615
1/2
✗ Branch 5 → 6 not taken.
✓ Branch 5 → 9 taken 1 time.
1 if (data == NULL)
616 {
617 fpi_device_list_complete (FP_DEVICE (self),
618 NULL,
619 fpi_device_error_new_msg (FP_DEVICE_ERROR_DATA_INVALID,
620 "Data is null"));
621 return;
622 }
623
624 1 presp = (pfpc_cmd_response_t) data;
625
1/2
✗ Branch 9 → 10 not taken.
✓ Branch 9 → 13 taken 1 time.
1 if (presp->evt_hdr.cmdid != FPC_EVT_FID_DATA)
626 {
627 fpi_device_list_complete (FP_DEVICE (self),
628 NULL,
629 fpi_device_error_new_msg (FP_DEVICE_ERROR_DATA_INVALID,
630 "Recv evt is incorrect: 0x%x",
631 presp->evt_hdr.cmdid));
632 return;
633 }
634
635
1/2
✗ Branch 13 → 14 not taken.
✓ Branch 13 → 17 taken 1 time.
1 if (presp->evt_enum_fids.num_ids > FPC_TEMPLATES_MAX)
636 {
637 fpi_device_list_complete (FP_DEVICE (self),
638 NULL,
639 fpi_device_error_new_msg (FP_DEVICE_ERROR_DATA_FULL,
640 "Database is full"));
641 return;
642 }
643
644 1 list_result = g_ptr_array_new_with_free_func (g_object_unref);
645
646
1/2
✗ Branch 18 → 19 not taken.
✓ Branch 18 → 30 taken 1 time.
1 if (presp->evt_enum_fids.num_ids == 0)
647 {
648 fp_info ("Database is empty");
649 fpi_device_list_complete (device,
650 g_steal_pointer (&list_result),
651 NULL);
652 return;
653 }
654
655
2/2
✓ Branch 30 → 22 taken 1 time.
✓ Branch 30 → 31 taken 1 time.
2 for (int n = 0; n < presp->evt_enum_fids.num_ids; n++)
656 {
657 1 FpPrint *print = NULL;
658 1 fpc_fid_data_t *fid_data = &presp->evt_enum_fids.fid_data[n];
659
660
1/2
✗ Branch 22 → 23 not taken.
✓ Branch 22 → 26 taken 1 time.
1 if ((fid_data->subfactor != FPC_SUBTYPE_RESERVED) &&
661 (fid_data->identity_type != FPC_IDENTITY_TYPE_RESERVED))
662 {
663 fp_info ("Incompatible template found (0x%x, 0x%x)",
664 fid_data->subfactor, fid_data->identity_type);
665 continue;
666 }
667
668 1 print = fpc_print_from_data (self, fid_data);
669
670 1 g_ptr_array_add (list_result, g_object_ref_sink (print));
671 }
672
673 1 fp_info ("Query templates complete!");
674 1 fpi_device_list_complete (device,
675 1 g_steal_pointer (&list_result),
676 NULL);
677 }
678
679 /******************************************************************************
680 *
681 * fpc_enroll_xxxx Function
682 *
683 *****************************************************************************/
684
685 static void
686 1 fpc_enroll_create_cb (FpiDeviceFpcMoc *self,
687 void *data,
688 GError *error)
689 {
690 1 FPC_BEGIN_ENROL *presp = NULL;
691
692
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 7 taken 1 time.
1 if (!check_data (data, &error))
693 {
694 fp_err ("%s error: %s ", G_STRFUNC, error->message);
695 fpi_ssm_mark_failed (self->task_ssm, error);
696 return;
697 }
698
699 1 presp = (FPC_BEGIN_ENROL *) data;
700
1/2
✗ Branch 7 → 8 not taken.
✓ Branch 7 → 10 taken 1 time.
1 if (presp->status != 0)
701 {
702 error = fpi_device_error_new_msg (FP_DEVICE_ERROR_GENERAL,
703 "End Enroll failed: %d",
704 presp->status);
705 }
706
707
1/2
✗ Branch 10 → 11 not taken.
✓ Branch 10 → 14 taken 1 time.
1 if (error)
708 {
709 fp_err ("%s error: %s ", G_STRFUNC, error->message);
710 fpi_ssm_mark_failed (self->task_ssm, error);
711 return;
712 }
713 else
714 {
715 1 self->do_cleanup = TRUE;
716 1 fpi_ssm_next_state (self->task_ssm);
717 }
718 }
719
720 static void
721 15 fpc_enroll_update_cb (FpiDeviceFpcMoc *self,
722 void *data,
723 GError *error)
724 {
725 15 FPC_ENROL *presp = NULL;
726
727
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 7 taken 15 times.
15 if (!check_data (data, &error))
728 {
729 fp_err ("%s error: %s ", G_STRFUNC, error->message);
730 fpi_ssm_mark_failed (self->task_ssm, error);
731 return;
732 }
733
734 15 presp = (FPC_ENROL *) data;
735 15 fp_dbg ("Enrol Update status: %d, remaining: %d", presp->status, presp->remaining);
736
3/8
✗ Branch 8 → 9 not taken.
✗ Branch 8 → 11 not taken.
✓ Branch 8 → 13 taken 1 time.
✓ Branch 8 → 16 taken 3 times.
✓ Branch 8 → 27 taken 11 times.
✗ Branch 8 → 31 not taken.
✗ Branch 8 → 34 not taken.
✗ Branch 8 → 37 not taken.
15 switch (presp->status)
737 {
738 case FPC_ENROL_STATUS_FAILED_COULD_NOT_COMPLETE:
739 error = fpi_device_error_new (FP_DEVICE_ERROR_GENERAL);
740 break;
741
742 case FPC_ENROL_STATUS_FAILED_ALREADY_ENROLED:
743 error = fpi_device_error_new (FP_DEVICE_ERROR_DATA_DUPLICATE);
744 break;
745
746 1 case FPC_ENROL_STATUS_COMPLETED:
747 1 self->enroll_stage++;
748 1 fpi_device_enroll_progress (FP_DEVICE (self), self->enroll_stage, NULL, NULL);
749 1 fpi_ssm_jump_to_state (self->task_ssm, FPC_ENROLL_COMPLETE);
750 1 return;
751
752 3 case FPC_ENROL_STATUS_IMAGE_TOO_SIMILAR:
753 3 fp_dbg ("Sample overlapping ratio is too High");
754 /* here should tips remove finger and try again */
755
1/2
✗ Branch 17 → 18 not taken.
✓ Branch 17 → 24 taken 3 times.
3 if (self->max_immobile_stage)
756 {
757 self->immobile_stage++;
758 if (self->immobile_stage > self->max_immobile_stage)
759 {
760 fp_dbg ("Skip similar handle due to customer enrollment %d(%d)",
761 self->immobile_stage, self->max_immobile_stage);
762 /* Skip too similar handle, treat as normal enroll progress. */
763 self->enroll_stage++;
764 fpi_device_enroll_progress (FP_DEVICE (self), self->enroll_stage, NULL, NULL);
765 /* Used for customer enrollment scheme */
766 if (self->enroll_stage >= (self->max_enroll_stage - self->max_immobile_stage))
767 {
768 fpi_ssm_jump_to_state (self->task_ssm, FPC_ENROLL_COMPLETE);
769 return;
770 }
771 break;
772 }
773 }
774 3 fpi_device_enroll_progress (FP_DEVICE (self),
775 self->enroll_stage,
776 NULL,
777 fpi_device_retry_new (FP_DEVICE_RETRY_REMOVE_FINGER));
778 3 break;
779
780 11 case FPC_ENROL_STATUS_PROGRESS:
781 11 self->enroll_stage++;
782 11 fpi_device_enroll_progress (FP_DEVICE (self), self->enroll_stage, NULL, NULL);
783 /* Used for customer enrollment scheme */
784
1/2
✗ Branch 28 → 29 not taken.
✓ Branch 28 → 40 taken 11 times.
11 if (self->enroll_stage >= (self->max_enroll_stage - self->max_immobile_stage))
785 {
786 fpi_ssm_jump_to_state (self->task_ssm, FPC_ENROLL_COMPLETE);
787 return;
788 }
789 break;
790
791 case FPC_ENROL_STATUS_IMAGE_LOW_COVERAGE:
792 fpi_device_enroll_progress (FP_DEVICE (self),
793 self->enroll_stage,
794 NULL,
795 fpi_device_retry_new (FP_DEVICE_RETRY_CENTER_FINGER));
796 break;
797
798 case FPC_ENROL_STATUS_IMAGE_LOW_QUALITY:
799 fpi_device_enroll_progress (FP_DEVICE (self),
800 self->enroll_stage,
801 NULL,
802 fpi_device_retry_new (FP_DEVICE_RETRY_TOO_SHORT));
803 break;
804
805 default:
806 fp_err ("%s Unknown result code: %d ", G_STRFUNC, presp->status);
807 error = fpi_device_error_new_msg (FP_DEVICE_ERROR_GENERAL,
808 "Enroll failed: %d",
809 presp->status);
810 break;
811 }
812
813
1/2
✗ Branch 40 → 41 not taken.
✓ Branch 40 → 44 taken 14 times.
14 if (error)
814 {
815 fp_err ("%s error: %s ", G_STRFUNC, error->message);
816 fpi_ssm_mark_failed (self->task_ssm, error);
817 return;
818 }
819 else
820 {
821 14 fpi_ssm_jump_to_state (self->task_ssm, FPC_ENROLL_CAPTURE);
822 }
823 }
824
825 static void
826 1 fpc_enroll_complete_cb (FpiDeviceFpcMoc *self,
827 void *data,
828 GError *error)
829 {
830 1 FPC_END_ENROL *presp = NULL;
831
832 1 self->do_cleanup = FALSE;
833
834
1/2
✓ Branch 3 → 4 taken 1 time.
✗ Branch 3 → 8 not taken.
1 if (check_data (data, &error))
835 {
836 1 presp = (FPC_END_ENROL *) data;
837
1/2
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 7 taken 1 time.
1 if (presp->status != 0)
838 {
839 error = fpi_device_error_new_msg (FP_DEVICE_ERROR_GENERAL,
840 "End Enroll failed: %d",
841 presp->status);
842 }
843 else
844 {
845 1 fp_dbg ("Enrol End status: %d, fid: 0x%x",
846 presp->status, presp->fid);
847 }
848 }
849
850
1/2
✗ Branch 8 → 9 not taken.
✓ Branch 8 → 12 taken 1 time.
1 if (error)
851 {
852 fp_err ("%s error: %s ", G_STRFUNC, error->message);
853 fpi_ssm_mark_failed (self->task_ssm, error);
854 return;
855 }
856 else
857 {
858 1 fpi_ssm_next_state (self->task_ssm);
859 }
860 }
861
862 static void
863 1 fpc_enroll_check_duplicate_cb (FpiDeviceFpcMoc *self,
864 void *data,
865 GError *error)
866 {
867 1 FPC_IDENTIFY *presp = NULL;
868
869
1/2
✓ Branch 3 → 4 taken 1 time.
✗ Branch 3 → 11 not taken.
1 if (check_data (data, &error))
870 {
871 1 presp = (FPC_IDENTIFY *) data;
872
1/4
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 11 taken 1 time.
✗ Branch 5 → 6 not taken.
✗ Branch 5 → 11 not taken.
1 if ((presp->status == 0) && (presp->subfactor == FPC_SUBTYPE_RESERVED) &&
873 (presp->identity_type == FPC_IDENTITY_TYPE_RESERVED) &&
874 (presp->identity_size <= SECURITY_MAX_SID_SIZE))
875 {
876 fp_info ("%s Got a duplicated template", G_STRFUNC);
877 error = fpi_device_error_new (FP_DEVICE_ERROR_DATA_DUPLICATE);
878 }
879 }
880
881
1/2
✗ Branch 11 → 12 not taken.
✓ Branch 11 → 15 taken 1 time.
1 if (error)
882 {
883 fp_err ("%s error: %s ", G_STRFUNC, error->message);
884 fpi_ssm_mark_failed (self->task_ssm, error);
885 return;
886 }
887 else
888 {
889 1 fpi_ssm_next_state (self->task_ssm);
890 }
891
892 }
893
894 static void
895 1 fpc_enroll_bindid_cb (FpiDeviceFpcMoc *self,
896 void *data,
897 GError *error)
898 {
899
1/2
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 6 taken 1 time.
1 if (error)
900 {
901 fp_err ("%s error: %s ", G_STRFUNC, error->message);
902 fpi_ssm_mark_failed (self->task_ssm, error);
903 return;
904 }
905
906 1 fpi_ssm_next_state (self->task_ssm);
907 }
908
909 static void
910 1 fpc_enroll_commit_cb (FpiDeviceFpcMoc *self,
911 void *data,
912 GError *error)
913 {
914 1 gint32 *result = NULL;
915
916
1/2
✓ Branch 3 → 4 taken 1 time.
✗ Branch 3 → 7 not taken.
1 if (check_data (data, &error))
917 {
918 1 result = (gint32 *) data;
919
1/2
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 7 taken 1 time.
1 if (*result != 0)
920 {
921 error = fpi_device_error_new_msg (FP_DEVICE_ERROR_DATA_FULL,
922 "Save DB failed: %d",
923 *result);
924 }
925 }
926
927
1/2
✗ Branch 7 → 8 not taken.
✓ Branch 7 → 11 taken 1 time.
1 if (error)
928 {
929 fp_err ("%s error: %s ", G_STRFUNC, error->message);
930 fpi_ssm_mark_failed (self->task_ssm, error);
931 return;
932 }
933 else
934 {
935 1 fpi_ssm_mark_completed (self->task_ssm);
936 }
937 }
938
939
940 static void
941 53 fpc_enroll_sm_run_state (FpiSsm *ssm, FpDevice *device)
942 {
943 53 FpiDeviceFpcMoc *self = FPI_DEVICE_FPCMOC (device);
944 53 CommandData cmd_data = {0};
945 53 gsize recv_data_len = 0;
946
947
11/12
✓ Branch 3 → 4 taken 1 time.
✓ Branch 3 → 6 taken 1 time.
✓ Branch 3 → 8 taken 15 times.
✓ Branch 3 → 11 taken 15 times.
✓ Branch 3 → 13 taken 15 times.
✓ Branch 3 → 15 taken 1 time.
✓ Branch 3 → 17 taken 1 time.
✓ Branch 3 → 19 taken 1 time.
✓ Branch 3 → 32 taken 1 time.
✓ Branch 3 → 34 taken 1 time.
✓ Branch 3 → 36 taken 1 time.
✗ Branch 3 → 39 not taken.
53 switch (fpi_ssm_get_cur_state (ssm))
948 {
949 1 case FPC_ENROLL_ENUM:
950 {
951 1 FPC_FID_DATA pquery_data = {0};
952 1 gsize query_data_len = 0;
953 1 guint32 wildcard_value = FPC_IDENTITY_WILDCARD;
954 1 query_data_len = sizeof (FPC_FID_DATA);
955 1 pquery_data.identity_type = FPC_IDENTITY_TYPE_WILDCARD;
956 1 pquery_data.reserved = 16;
957 1 pquery_data.identity_size = sizeof (wildcard_value);
958 1 pquery_data.subfactor = (guint32) FPC_SUBTYPE_ANY;
959 1 memcpy (&pquery_data.data[0],
960 &wildcard_value, pquery_data.identity_size);
961
962 1 cmd_data.cmdtype = FPC_CMDTYPE_TO_DEVICE_EVTDATA;
963 1 cmd_data.request = FPC_CMD_ENUM;
964 1 cmd_data.value = 0x0;
965 1 cmd_data.index = 0x0;
966 1 cmd_data.data = (guint8 *) &pquery_data;
967 1 cmd_data.data_len = query_data_len;
968 1 cmd_data.callback = fpc_evt_cb;
969
970 1 fpc_sensor_cmd (self, FALSE, &cmd_data);
971 }
972 1 break;
973
974 1 case FPC_ENROLL_CREATE:
975 {
976 1 recv_data_len = sizeof (FPC_BEGIN_ENROL);
977 1 cmd_data.cmdtype = FPC_CMDTYPE_FROM_DEVICE;
978 1 cmd_data.request = FPC_CMD_BEGIN_ENROL;
979 1 cmd_data.value = 0x0;
980 1 cmd_data.index = 0x0;
981 1 cmd_data.data = NULL;
982 1 cmd_data.data_len = recv_data_len;
983 1 cmd_data.callback = fpc_enroll_create_cb;
984
985 1 fpc_sensor_cmd (self, FALSE, &cmd_data);
986 }
987 1 break;
988
989 15 case FPC_ENROLL_CAPTURE:
990 {
991 15 guint32 capture_id = FPC_CAPTUREID_RESERVED;
992 15 fpi_device_report_finger_status_changes (device,
993 FP_FINGER_STATUS_NEEDED,
994 FP_FINGER_STATUS_NONE);
995 15 cmd_data.cmdtype = FPC_CMDTYPE_TO_DEVICE_EVTDATA;
996 15 cmd_data.request = FPC_CMD_ARM;
997 15 cmd_data.value = 0x1;
998 15 cmd_data.index = 0x0;
999 15 cmd_data.data = (guint8 *) &capture_id;
1000 15 cmd_data.data_len = sizeof (guint32);
1001 15 cmd_data.callback = fpc_evt_cb;
1002
1003 15 fpc_sensor_cmd (self, TRUE, &cmd_data);
1004 }
1005 15 break;
1006
1007 15 case FPC_ENROLL_GET_IMG:
1008 {
1009 15 cmd_data.cmdtype = FPC_CMDTYPE_TO_DEVICE_EVTDATA;
1010 15 cmd_data.request = FPC_CMD_GET_IMG;
1011 15 cmd_data.value = 0x0;
1012 15 cmd_data.index = 0x0;
1013 15 cmd_data.data = NULL;
1014 15 cmd_data.data_len = 0;
1015 15 cmd_data.callback = fpc_evt_cb;
1016
1017 15 fpc_sensor_cmd (self, FALSE, &cmd_data);
1018 }
1019 15 break;
1020
1021 15 case FPC_ENROLL_UPDATE:
1022 {
1023 15 recv_data_len = sizeof (FPC_ENROL);
1024 15 cmd_data.cmdtype = FPC_CMDTYPE_FROM_DEVICE;
1025 15 cmd_data.request = FPC_CMD_ENROL;
1026 15 cmd_data.value = 0x0;
1027 15 cmd_data.index = 0x0;
1028 15 cmd_data.data = NULL;
1029 15 cmd_data.data_len = recv_data_len;
1030 15 cmd_data.callback = fpc_enroll_update_cb;
1031
1032 15 fpc_sensor_cmd (self, FALSE, &cmd_data);
1033 }
1034 15 break;
1035
1036 1 case FPC_ENROLL_COMPLETE:
1037 {
1038 1 recv_data_len = sizeof (FPC_END_ENROL);
1039 1 cmd_data.cmdtype = FPC_CMDTYPE_FROM_DEVICE;
1040 1 cmd_data.request = FPC_CMD_END_ENROL;
1041 1 cmd_data.value = 0x0;
1042 1 cmd_data.index = 0x0;
1043 1 cmd_data.data = NULL;
1044 1 cmd_data.data_len = recv_data_len;
1045 1 cmd_data.callback = fpc_enroll_complete_cb;
1046
1047 1 fpc_sensor_cmd (self, FALSE, &cmd_data);
1048 }
1049 1 break;
1050
1051 1 case FPC_ENROLL_CHECK_DUPLICATE:
1052 {
1053 1 recv_data_len = sizeof (FPC_IDENTIFY);
1054 1 cmd_data.cmdtype = FPC_CMDTYPE_FROM_DEVICE;
1055 1 cmd_data.request = FPC_CMD_IDENTIFY;
1056 1 cmd_data.value = 0x0;
1057 1 cmd_data.index = 0x0;
1058 1 cmd_data.data = NULL;
1059 1 cmd_data.data_len = recv_data_len;
1060 1 cmd_data.callback = fpc_enroll_check_duplicate_cb;
1061
1062 1 fpc_sensor_cmd (self, FALSE, &cmd_data);
1063 }
1064 1 break;
1065
1066 1 case FPC_ENROLL_BINDID:
1067 {
1068 1 FPC_FID_DATA data = {0};
1069 1 gsize data_len = 0;
1070 1 FpPrint *print = NULL;
1071 1 GVariant *fpi_data = NULL;
1072 1 GVariant *uid = NULL;
1073 1 guint finger = FPC_SUBTYPE_RESERVED;
1074 2 g_autofree gchar *user_id = NULL;
1075 1 gssize user_id_len;
1076 1 g_autofree guint8 *payload = NULL;
1077
1078 1 fpi_device_get_enroll_data (device, &print);
1079
1080 1 user_id = fpi_print_generate_user_id (print);
1081
1082 1 user_id_len = strlen (user_id);
1083 1 user_id_len = MIN (SECURITY_MAX_SID_SIZE, user_id_len);
1084
1085 1 uid = g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE,
1086 user_id,
1087 user_id_len,
1088 1);
1089 1 fpi_data = g_variant_new ("(y@ay)",
1090 finger,
1091 uid);
1092
1093 1 fpi_print_set_type (print, FPI_PRINT_RAW);
1094 1 fpi_print_set_device_stored (print, TRUE);
1095 1 g_object_set (print, "fpi-data", fpi_data, NULL);
1096 1 g_object_set (print, "description", user_id, NULL);
1097
1098 1 fp_dbg ("user_id: %s, finger: 0x%x", user_id, finger);
1099
1100 1 data_len = sizeof (FPC_FID_DATA);
1101 1 data.identity_type = FPC_IDENTITY_TYPE_RESERVED;
1102 1 data.reserved = 16;
1103 1 data.identity_size = user_id_len;
1104 1 data.subfactor = (guint32) finger;
1105 1 memcpy (&data.data[0],
1106 user_id, user_id_len);
1107
1108 1 cmd_data.cmdtype = FPC_CMDTYPE_TO_DEVICE;
1109 1 cmd_data.request = FPC_CMD_BIND_IDENTITY;
1110 1 cmd_data.value = 0x0;
1111 1 cmd_data.index = 0x0;
1112 1 cmd_data.data = (guint8 *) &data;
1113 1 cmd_data.data_len = data_len;
1114 1 cmd_data.callback = fpc_enroll_bindid_cb;
1115
1116 1 fpc_sensor_cmd (self, FALSE, &cmd_data);
1117 }
1118 1 break;
1119
1120 1 case FPC_ENROLL_COMMIT:
1121 {
1122 1 recv_data_len = sizeof (gint32);
1123 1 cmd_data.cmdtype = FPC_CMDTYPE_FROM_DEVICE;
1124 1 cmd_data.request = FPC_CMD_STORE_DB;
1125 1 cmd_data.value = 0x0;
1126 1 cmd_data.index = 0x0;
1127 1 cmd_data.data = NULL;
1128 1 cmd_data.data_len = recv_data_len;
1129 1 cmd_data.callback = fpc_enroll_commit_cb;
1130
1131 1 fpc_sensor_cmd (self, FALSE, &cmd_data);
1132 }
1133 1 break;
1134
1135 1 case FPC_ENROLL_DICARD:
1136 {
1137 1 cmd_data.cmdtype = FPC_CMDTYPE_TO_DEVICE;
1138 1 cmd_data.request = FPC_CMD_ABORT;
1139 1 cmd_data.value = 0x1;
1140 1 cmd_data.index = 0x0;
1141 1 cmd_data.data = NULL;
1142 1 cmd_data.data_len = 0;
1143 1 cmd_data.callback = fpc_do_abort_cb;
1144 1 fpc_sensor_cmd (self, FALSE, &cmd_data);
1145 }
1146 1 break;
1147
1148 1 case FPC_ENROLL_CLEANUP:
1149 {
1150
1/2
✗ Branch 36 → 37 not taken.
✓ Branch 36 → 38 taken 1 time.
1 if (self->do_cleanup == TRUE)
1151 {
1152 recv_data_len = sizeof (FPC_END_ENROL);
1153 cmd_data.cmdtype = FPC_CMDTYPE_FROM_DEVICE;
1154 cmd_data.request = FPC_CMD_END_ENROL;
1155 cmd_data.value = 0x0;
1156 cmd_data.index = 0x0;
1157 cmd_data.data = NULL;
1158 cmd_data.data_len = recv_data_len;
1159 cmd_data.callback = fpc_do_cleanup_cb;
1160 fpc_sensor_cmd (self, FALSE, &cmd_data);
1161 }
1162 else
1163 {
1164 1 fpi_ssm_next_state (self->task_ssm);
1165 }
1166 }
1167 break;
1168 }
1169 53 }
1170
1171 static void
1172 1 fpc_enroll_ssm_done (FpiSsm *ssm, FpDevice *dev, GError *error)
1173 {
1174 1 FpiDeviceFpcMoc *self = FPI_DEVICE_FPCMOC (dev);
1175 1 FpPrint *print = NULL;
1176
1177 1 fp_info ("Enrollment complete!");
1178
1179
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 1 time.
1 if (error)
1180 {
1181 fpi_device_enroll_complete (dev, NULL, g_steal_pointer (&error));
1182 self->task_ssm = NULL;
1183 return;
1184 }
1185
1186 1 fpi_device_get_enroll_data (FP_DEVICE (self), &print);
1187 1 fpi_device_enroll_complete (FP_DEVICE (self), g_object_ref (print), NULL);
1188 1 self->task_ssm = NULL;
1189 }
1190
1191 /******************************************************************************
1192 *
1193 * fpc_verify_xxx function
1194 *
1195 *****************************************************************************/
1196
1197 static void
1198 2 fpc_verify_cb (FpiDeviceFpcMoc *self,
1199 void *data,
1200 GError *error)
1201 {
1202 2 g_autoptr(GPtrArray) templates = NULL;
1203 2 FpDevice *device = FP_DEVICE (self);
1204 2 gboolean found = FALSE;
1205 2 FpiDeviceAction current_action;
1206 2 FPC_IDENTIFY *presp = NULL;
1207
1208
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 6 taken 2 times.
2 if (!check_data (data, &error))
1209 {
1210 fp_err ("%s error: %s ", G_STRFUNC, error->message);
1211 fpi_ssm_mark_failed (self->task_ssm, error);
1212 return;
1213 }
1214
1215 2 presp = (FPC_IDENTIFY *) data;
1216 2 current_action = fpi_device_get_current_action (device);
1217
1218
1/2
✗ Branch 7 → 8 not taken.
✓ Branch 7 → 9 taken 2 times.
2 g_assert (current_action == FPI_DEVICE_ACTION_VERIFY ||
1219 current_action == FPI_DEVICE_ACTION_IDENTIFY);
1220
1221
2/4
✓ Branch 9 → 10 taken 2 times.
✗ Branch 9 → 32 not taken.
✓ Branch 10 → 11 taken 2 times.
✗ Branch 10 → 32 not taken.
2 if ((presp->status == 0) && (presp->subfactor == FPC_SUBTYPE_RESERVED) &&
1222
1/2
✓ Branch 11 → 12 taken 2 times.
✗ Branch 11 → 32 not taken.
2 (presp->identity_type == FPC_IDENTITY_TYPE_RESERVED) &&
1223
1/2
✓ Branch 12 → 13 taken 2 times.
✗ Branch 12 → 32 not taken.
2 (presp->identity_size <= SECURITY_MAX_SID_SIZE))
1224 {
1225 2 FpPrint *match = NULL;
1226 2 FpPrint *print = NULL;
1227 2 gint cnt = 0;
1228 2 fpc_fid_data_t fid_data = {0};
1229
1230 2 fid_data.subfactor = presp->subfactor;
1231 2 fid_data.identity_type = presp->identity_type;
1232 2 fid_data.identity_size = presp->identity_size;
1233 2 memcpy (fid_data.identity, &presp->data[0],
1234 fid_data.identity_size);
1235
1236 2 match = fpc_print_from_data (self, &fid_data);
1237
1238
2/2
✓ Branch 14 → 15 taken 1 time.
✓ Branch 14 → 18 taken 1 time.
2 if (current_action == FPI_DEVICE_ACTION_VERIFY)
1239 {
1240 1 templates = g_ptr_array_sized_new (1);
1241 1 fpi_device_get_verify_data (device, &print);
1242 1 g_ptr_array_add (templates, print);
1243 }
1244 else
1245 {
1246 1 fpi_device_get_identify_data (device, &templates);
1247 1 g_ptr_array_ref (templates);
1248 }
1249
1250
1/2
✓ Branch 24 → 21 taken 2 times.
✗ Branch 24 → 25 not taken.
2 for (cnt = 0; cnt < templates->len; cnt++)
1251 {
1252 2 print = g_ptr_array_index (templates, cnt);
1253
1254
1/2
✗ Branch 22 → 23 not taken.
✓ Branch 22 → 25 taken 2 times.
2 if (fp_print_equal (print, match))
1255 {
1256 found = TRUE;
1257 break;
1258 }
1259 }
1260
1261
1/2
✓ Branch 25 → 26 taken 2 times.
✗ Branch 25 → 31 not taken.
2 if (found)
1262 {
1263
2/2
✓ Branch 26 → 27 taken 1 time.
✓ Branch 26 → 28 taken 1 time.
2 if (current_action == FPI_DEVICE_ACTION_VERIFY)
1264 1 fpi_device_verify_report (device, FPI_MATCH_SUCCESS, match, error);
1265 else
1266 1 fpi_device_identify_report (device, print, match, error);
1267
1268 2 fpi_ssm_mark_completed (self->task_ssm);
1269 2 return;
1270 }
1271 }
1272
1273 if (!found)
1274 {
1275 if (current_action == FPI_DEVICE_ACTION_VERIFY)
1276 fpi_device_verify_report (device, FPI_MATCH_FAIL, NULL, error);
1277 else
1278 fpi_device_identify_report (device, NULL, NULL, error);
1279 }
1280
1281 /* This is the last state for verify/identify */
1282 fpi_ssm_mark_completed (self->task_ssm);
1283 }
1284
1285 static void
1286 8 fpc_verify_sm_run_state (FpiSsm *ssm, FpDevice *device)
1287 {
1288 8 FpiDeviceFpcMoc *self = FPI_DEVICE_FPCMOC (device);
1289 8 CommandData cmd_data = {0};
1290
1291
4/5
✓ Branch 3 → 4 taken 2 times.
✓ Branch 3 → 7 taken 2 times.
✓ Branch 3 → 9 taken 2 times.
✓ Branch 3 → 11 taken 2 times.
✗ Branch 3 → 13 not taken.
8 switch (fpi_ssm_get_cur_state (ssm))
1292 {
1293 2 case FPC_VERIFY_CAPTURE:
1294 {
1295 2 guint32 capture_id = FPC_CAPTUREID_RESERVED;
1296 2 fpi_device_report_finger_status_changes (device,
1297 FP_FINGER_STATUS_NEEDED,
1298 FP_FINGER_STATUS_NONE);
1299 2 cmd_data.cmdtype = FPC_CMDTYPE_TO_DEVICE_EVTDATA;
1300 2 cmd_data.request = FPC_CMD_ARM;
1301 2 cmd_data.value = 0x1;
1302 2 cmd_data.index = 0x0;
1303 2 cmd_data.data = (guint8 *) &capture_id;
1304 2 cmd_data.data_len = sizeof (guint32);
1305 2 cmd_data.callback = fpc_evt_cb;
1306
1307 2 fpc_sensor_cmd (self, TRUE, &cmd_data);
1308 }
1309 2 break;
1310
1311 2 case FPC_VERIFY_GET_IMG:
1312 {
1313 2 cmd_data.cmdtype = FPC_CMDTYPE_TO_DEVICE_EVTDATA;
1314 2 cmd_data.request = FPC_CMD_GET_IMG;
1315 2 cmd_data.value = 0x0;
1316 2 cmd_data.index = 0x0;
1317 2 cmd_data.data = NULL;
1318 2 cmd_data.data_len = 0;
1319 2 cmd_data.callback = fpc_evt_cb;
1320
1321 2 fpc_sensor_cmd (self, FALSE, &cmd_data);
1322 }
1323 2 break;
1324
1325 2 case FPC_VERIFY_IDENTIFY:
1326 {
1327 2 gsize recv_data_len = sizeof (FPC_IDENTIFY);
1328 2 cmd_data.cmdtype = FPC_CMDTYPE_FROM_DEVICE;
1329 2 cmd_data.request = FPC_CMD_IDENTIFY;
1330 2 cmd_data.value = 0x0;
1331 2 cmd_data.index = 0x0;
1332 2 cmd_data.data = NULL;
1333 2 cmd_data.data_len = recv_data_len;
1334 2 cmd_data.callback = fpc_verify_cb;
1335
1336 2 fpc_sensor_cmd (self, FALSE, &cmd_data);
1337 }
1338 2 break;
1339
1340 2 case FPC_VERIFY_CANCEL:
1341 {
1342 2 cmd_data.cmdtype = FPC_CMDTYPE_TO_DEVICE;
1343 2 cmd_data.request = FPC_CMD_ABORT;
1344 2 cmd_data.value = 0x1;
1345 2 cmd_data.index = 0x0;
1346 2 cmd_data.data = NULL;
1347 2 cmd_data.data_len = 0;
1348 2 cmd_data.callback = fpc_do_abort_cb;
1349 2 fpc_sensor_cmd (self, FALSE, &cmd_data);
1350
1351 }
1352 2 break;
1353 }
1354 8 }
1355
1356 static void
1357 2 fpc_verify_ssm_done (FpiSsm *ssm, FpDevice *dev, GError *error)
1358 {
1359 2 FpiDeviceFpcMoc *self = FPI_DEVICE_FPCMOC (dev);
1360
1361 2 fp_info ("Verify_identify complete!");
1362
1363
1/4
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 10 taken 2 times.
✗ Branch 5 → 6 not taken.
✗ Branch 5 → 10 not taken.
2 if (error && error->domain == FP_DEVICE_RETRY)
1364 {
1365 if (fpi_device_get_current_action (dev) == FPI_DEVICE_ACTION_VERIFY)
1366 fpi_device_verify_report (dev, FPI_MATCH_ERROR, NULL, g_steal_pointer (&error));
1367 else
1368 fpi_device_identify_report (dev, NULL, NULL, g_steal_pointer (&error));
1369 }
1370
1371
2/2
✓ Branch 11 → 12 taken 1 time.
✓ Branch 11 → 13 taken 1 time.
2 if (fpi_device_get_current_action (dev) == FPI_DEVICE_ACTION_VERIFY)
1372 1 fpi_device_verify_complete (dev, g_steal_pointer (&error));
1373 else
1374 1 fpi_device_identify_complete (dev, g_steal_pointer (&error));
1375
1376 2 self->task_ssm = NULL;
1377 2 }
1378
1379 /******************************************************************************
1380 *
1381 * fpc_init_xxx function
1382 *
1383 *****************************************************************************/
1384 static void
1385 2 fpc_clear_storage_cb (FpiDeviceFpcMoc *self,
1386 void *resp,
1387 GError *error)
1388 {
1389
1/2
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 6 taken 2 times.
2 if (error)
1390 {
1391 fp_err ("%s error: %s ", G_STRFUNC, error->message);
1392 fpi_ssm_mark_failed (self->task_ssm, error);
1393 return;
1394 }
1395
1396 2 fpi_ssm_next_state (self->task_ssm);
1397
1398 }
1399
1400 static void
1401 2 fpc_clear_sm_run_state (FpiSsm *ssm, FpDevice *device)
1402 {
1403 2 FpiDeviceFpcMoc *self = FPI_DEVICE_FPCMOC (device);
1404 2 CommandData cmd_data = {0};
1405 2 FPC_DB_OP data = {0};
1406 2 gsize data_len = 0;
1407
1408
2/3
✓ Branch 3 → 4 taken 1 time.
✓ Branch 3 → 8 taken 1 time.
✗ Branch 3 → 12 not taken.
2 switch (fpi_ssm_get_cur_state (ssm))
1409 {
1410 1 case FPC_CLEAR_DELETE_DB:
1411 {
1412
1/2
✓ Branch 4 → 5 taken 1 time.
✗ Branch 4 → 6 not taken.
1 if (self->dbid)
1413 {
1414 1 data_len = sizeof (FPC_DB_OP);
1415 1 data.database_id_size = FPC_DB_ID_LEN;
1416 1 data.reserved = 8;
1417 1 memcpy (&data.data[0], self->dbid, FPC_DB_ID_LEN);
1418 1 cmd_data.cmdtype = FPC_CMDTYPE_TO_DEVICE;
1419 1 cmd_data.request = FPC_CMD_DELETE_DB;
1420 1 cmd_data.value = 0x0;
1421 1 cmd_data.index = 0x0;
1422 1 cmd_data.data = (guint8 *) &data;
1423 1 cmd_data.data_len = data_len;
1424 1 cmd_data.callback = fpc_clear_storage_cb;
1425 1 fpc_sensor_cmd (self, FALSE, &cmd_data);
1426 }
1427 else
1428 {
1429 fpi_ssm_mark_failed (self->task_ssm,
1430 fpi_device_error_new_msg (FP_DEVICE_ERROR_NOT_SUPPORTED,
1431 "No DBID found"));
1432 }
1433
1434 }
1435 break;
1436
1437 1 case FPC_CLEAR_CREATE_DB:
1438 {
1439
1/2
✓ Branch 8 → 9 taken 1 time.
✗ Branch 8 → 10 not taken.
1 if (self->dbid)
1440 {
1441 1 data_len = sizeof (FPC_DB_OP);
1442 1 data.database_id_size = FPC_DB_ID_LEN;
1443 1 data.reserved = 8;
1444 1 memcpy (&data.data[0], self->dbid, FPC_DB_ID_LEN);
1445 1 cmd_data.cmdtype = FPC_CMDTYPE_TO_DEVICE;
1446 1 cmd_data.request = FPC_CMD_LOAD_DB;
1447 1 cmd_data.value = 0x1;
1448 1 cmd_data.index = 0x0;
1449 1 cmd_data.data = (guint8 *) &data;
1450 1 cmd_data.data_len = data_len;
1451 1 cmd_data.callback = fpc_clear_storage_cb;
1452 1 fpc_sensor_cmd (self, FALSE, &cmd_data);
1453 }
1454 else
1455 {
1456 fpi_ssm_mark_failed (self->task_ssm,
1457 fpi_device_error_new_msg (FP_DEVICE_ERROR_NOT_SUPPORTED,
1458 "No DBID found"));
1459 }
1460 }
1461 break;
1462 }
1463 2 }
1464
1465 static void
1466 1 fpc_clear_ssm_done (FpiSsm *ssm, FpDevice *dev, GError *error)
1467 {
1468 1 FpiDeviceFpcMoc *self = FPI_DEVICE_FPCMOC (dev);
1469
1470 1 fp_info ("Clear Storage complete!");
1471
1472 1 fpi_device_clear_storage_complete (dev, g_steal_pointer (&error));
1473 1 self->task_ssm = NULL;
1474 1 }
1475
1476 /******************************************************************************
1477 *
1478 * fpc_init_xxx function
1479 *
1480 *****************************************************************************/
1481
1482 static void
1483 1 fpc_init_load_db_cb (FpiDeviceFpcMoc *self,
1484 void *data,
1485 GError *error)
1486 {
1487 1 FPC_LOAD_DB *presp = NULL;
1488
1489
1/2
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 6 taken 1 time.
1 if (error)
1490 {
1491 fp_err ("%s error: %s ", G_STRFUNC, error->message);
1492 fpi_ssm_mark_failed (self->task_ssm, error);
1493 return;
1494 }
1495
1496
1/2
✗ Branch 6 → 7 not taken.
✓ Branch 6 → 10 taken 1 time.
1 if (data == NULL)
1497 {
1498 fpi_ssm_mark_failed (self->task_ssm,
1499 fpi_device_error_new (FP_DEVICE_ERROR_DATA_INVALID));
1500 return;
1501 }
1502 1 presp = (FPC_LOAD_DB *) data;
1503
1/2
✗ Branch 10 → 11 not taken.
✓ Branch 10 → 14 taken 1 time.
1 if (presp->status)
1504 {
1505 fp_err ("%s Load DB failed: %d - Expect to create a new one", G_STRFUNC, presp->status);
1506 fpi_ssm_next_state (self->task_ssm);
1507 return;
1508 }
1509
1510
1/2
✗ Branch 14 → 15 not taken.
✓ Branch 14 → 16 taken 1 time.
1 g_clear_pointer (&self->dbid, g_free);
1511 1 self->dbid = g_memdup2 (presp->data, FPC_DB_ID_LEN);
1512
1/2
✗ Branch 17 → 18 not taken.
✓ Branch 17 → 21 taken 1 time.
1 if (self->dbid == NULL)
1513 {
1514 fpi_ssm_mark_failed (self->task_ssm, fpi_device_error_new (FP_DEVICE_ERROR_GENERAL));
1515 return;
1516 }
1517
1518 1 fp_dbg ("%s got dbid size: %d", G_STRFUNC, presp->database_id_size);
1519 1 fp_dbg ("%s dbid: 0x%02x%02x%02x%02x-%02x%02x-%02x%02x-" \
1520 "%02x%02x-%02x%02x%02x%02x%02x%02x",
1521 G_STRFUNC,
1522 presp->data[0], presp->data[1],
1523 presp->data[2], presp->data[3],
1524 presp->data[4], presp->data[5],
1525 presp->data[6], presp->data[7],
1526 presp->data[8], presp->data[9],
1527 presp->data[10], presp->data[11],
1528 presp->data[12], presp->data[13],
1529 presp->data[14], presp->data[15]);
1530 1 fpi_ssm_mark_completed (self->task_ssm);
1531 }
1532
1533 static void
1534 2 fpc_init_sm_run_state (FpiSsm *ssm, FpDevice *device)
1535 {
1536 2 FpiDeviceFpcMoc *self = FPI_DEVICE_FPCMOC (device);
1537 2 guint32 session_id = FPC_SESSIONID_RESERVED;
1538 2 CommandData cmd_data = {0};
1539
1540
2/3
✓ Branch 3 → 4 taken 1 time.
✓ Branch 3 → 6 taken 1 time.
✗ Branch 3 → 8 not taken.
2 switch (fpi_ssm_get_cur_state (ssm))
1541 {
1542 1 case FPC_INIT:
1543 1 cmd_data.cmdtype = FPC_CMDTYPE_TO_DEVICE_EVTDATA;
1544 1 cmd_data.request = FPC_CMD_INIT;
1545 1 cmd_data.value = 0x1;
1546 1 cmd_data.index = 0x0;
1547 1 cmd_data.data = (guint8 *) &session_id;
1548 1 cmd_data.data_len = sizeof (session_id);
1549 1 cmd_data.callback = fpc_evt_cb;
1550
1551 1 fpc_sensor_cmd (self, FALSE, &cmd_data);
1552 1 break;
1553
1554 1 case FPC_INIT_LOAD_DB:
1555 {
1556 1 gsize recv_data_len = sizeof (FPC_LOAD_DB);
1557 1 cmd_data.cmdtype = FPC_CMDTYPE_FROM_DEVICE;
1558 1 cmd_data.request = FPC_CMD_LOAD_DB;
1559 1 cmd_data.value = 0x0;
1560 1 cmd_data.index = 0x0;
1561 1 cmd_data.data = NULL;
1562 1 cmd_data.data_len = recv_data_len;
1563 1 cmd_data.callback = fpc_init_load_db_cb;
1564
1565 1 fpc_sensor_cmd (self, FALSE, &cmd_data);
1566 }
1567 1 break;
1568 }
1569 2 }
1570
1571 static void
1572 1 fpc_init_ssm_done (FpiSsm *ssm, FpDevice *dev, GError *error)
1573 {
1574 1 FpiDeviceFpcMoc *self = FPI_DEVICE_FPCMOC (dev);
1575
1576 1 fpi_device_open_complete (dev, g_steal_pointer (&error));
1577 1 self->task_ssm = NULL;
1578 1 }
1579
1580 /******************************************************************************
1581 *
1582 * Interface Function
1583 *
1584 *****************************************************************************/
1585
1586 static void
1587 1 fpc_dev_probe (FpDevice *device)
1588 {
1589 1 GUsbDevice *usb_dev;
1590 1 GError *error = NULL;
1591 1 FpiDeviceFpcMoc *self = FPI_DEVICE_FPCMOC (device);
1592 1 g_autofree gchar *product = NULL;
1593 1 gint product_id = 0;
1594
1595 1 fp_dbg ("%s enter --> ", G_STRFUNC);
1596
1597 /* Claim usb interface */
1598 1 usb_dev = fpi_device_get_usb_device (device);
1599
1/2
✗ Branch 5 → 6 not taken.
✓ Branch 5 → 8 taken 1 time.
1 if (!g_usb_device_open (usb_dev, &error))
1600 {
1601 fp_dbg ("%s g_usb_device_open failed %s", G_STRFUNC, error->message);
1602 fpi_device_probe_complete (device, NULL, NULL, error);
1603 return;
1604 }
1605
1606
1/2
✗ Branch 9 → 10 not taken.
✓ Branch 9 → 14 taken 1 time.
1 if (!g_usb_device_reset (usb_dev, &error))
1607 {
1608 fp_dbg ("%s g_usb_device_reset failed %s", G_STRFUNC, error->message);
1609 g_usb_device_close (usb_dev, NULL);
1610 fpi_device_probe_complete (device, NULL, NULL, error);
1611 return;
1612 }
1613
1614
1/2
✗ Branch 15 → 16 not taken.
✓ Branch 15 → 20 taken 1 time.
1 if (!g_usb_device_claim_interface (usb_dev, 0, 0, &error))
1615 {
1616 fp_dbg ("%s g_usb_device_claim_interface failed %s", G_STRFUNC, error->message);
1617 g_usb_device_close (usb_dev, NULL);
1618 fpi_device_probe_complete (device, NULL, NULL, error);
1619 return;
1620 }
1621
1622 1 product = g_usb_device_get_string_descriptor (usb_dev,
1623 g_usb_device_get_product_index (usb_dev),
1624 &error);
1625
1/2
✓ Branch 22 → 23 taken 1 time.
✗ Branch 22 → 24 not taken.
1 if (product)
1626 1 fp_dbg ("Device name: %s", product);
1627
1628
1/2
✗ Branch 24 → 25 not taken.
✓ Branch 24 → 31 taken 1 time.
1 if (error)
1629 {
1630 fp_dbg ("%s g_usb_device_get_string_descriptor failed %s", G_STRFUNC, error->message);
1631 g_usb_device_release_interface (fpi_device_get_usb_device (FP_DEVICE (device)),
1632 0, 0, NULL);
1633 g_usb_device_close (usb_dev, NULL);
1634 fpi_device_probe_complete (device, NULL, NULL, error);
1635 return;
1636 }
1637
1638 1 product_id = g_usb_device_get_pid (usb_dev);
1639 /* Reserved for customer enroll scheme */
1640 1 self->max_immobile_stage = 0; /* By default is not customer enrollment */
1641
1/2
✓ Branch 32 → 33 taken 1 time.
✗ Branch 32 → 34 not taken.
1 switch (product_id)
1642 {
1643 1 case 0xFFE0:
1644 case 0xA305:
1645 case 0xA306:
1646 case 0xD805:
1647 case 0xDA04:
1648 case 0xD205:
1649 case 0x9524:
1650 case 0x9544:
1651 case 0xC844:
1652 1 self->max_enroll_stage = MAX_ENROLL_SAMPLES;
1653 1 break;
1654
1655 default:
1656 fp_warn ("Device %x is not supported", product_id);
1657 self->max_enroll_stage = MAX_ENROLL_SAMPLES;
1658 break;
1659 }
1660 1 fpi_device_set_nr_enroll_stages (device, self->max_enroll_stage);
1661 1 g_usb_device_release_interface (fpi_device_get_usb_device (FP_DEVICE (device)),
1662 0, 0, NULL);
1663 1 g_usb_device_close (usb_dev, NULL);
1664 1 fpi_device_probe_complete (device, NULL, product, error);
1665 }
1666
1667 static void
1668 1 fpc_dev_open (FpDevice *device)
1669 {
1670 1 FpiDeviceFpcMoc *self = FPI_DEVICE_FPCMOC (device);
1671 1 GError *error = NULL;
1672
1673 1 fp_dbg ("%s enter -->", G_STRFUNC);
1674
1/2
✗ Branch 5 → 6 not taken.
✓ Branch 5 → 7 taken 1 time.
1 if (!g_usb_device_reset (fpi_device_get_usb_device (device), &error))
1675 {
1676 fpi_device_open_complete (FP_DEVICE (self), error);
1677 return;
1678 }
1679
1680 /* Claim usb interface */
1681
1/2
✗ Branch 9 → 10 not taken.
✓ Branch 9 → 12 taken 1 time.
1 if (!g_usb_device_claim_interface (fpi_device_get_usb_device (device), 0, 0, &error))
1682 {
1683 fpi_device_open_complete (FP_DEVICE (self), error);
1684 return;
1685 }
1686
1687 1 self->task_ssm = fpi_ssm_new (device, fpc_init_sm_run_state,
1688 FPC_INIT_NUM_STATES);
1689
1690 1 fpi_ssm_start (self->task_ssm, fpc_init_ssm_done);
1691 }
1692
1693 static void
1694 1 fpc_dev_close (FpDevice *device)
1695 {
1696 1 FpiDeviceFpcMoc *self = FPI_DEVICE_FPCMOC (device);
1697
1698 1 fp_dbg ("%s enter -->", G_STRFUNC);
1699
1/2
✓ Branch 3 → 4 taken 1 time.
✗ Branch 3 → 5 not taken.
1 g_clear_pointer (&self->dbid, g_free);
1700 1 g_cancellable_cancel (self->interrupt_cancellable);
1701
1/2
✗ Branch 6 → 7 not taken.
✓ Branch 6 → 8 taken 1 time.
1 g_clear_object (&self->interrupt_cancellable);
1702 1 fpc_dev_release_interface (self, NULL);
1703 1 }
1704
1705 static void
1706 2 fpc_dev_verify_identify (FpDevice *device)
1707 {
1708 2 FpiDeviceFpcMoc *self = FPI_DEVICE_FPCMOC (device);
1709
1710 2 fp_dbg ("%s enter -->", G_STRFUNC);
1711 2 self->task_ssm = fpi_ssm_new_full (device, fpc_verify_sm_run_state,
1712 FPC_VERIFY_NUM_STATES,
1713 FPC_VERIFY_CANCEL,
1714 "verify_identify");
1715
1716 2 fpi_ssm_start (self->task_ssm, fpc_verify_ssm_done);
1717 2 }
1718
1719 static void
1720 1 fpc_dev_enroll (FpDevice *device)
1721 {
1722 1 FpiDeviceFpcMoc *self = FPI_DEVICE_FPCMOC (device);
1723
1724 1 fp_dbg ("%s enter -->", G_STRFUNC);
1725
1726 1 self->enroll_stage = 0;
1727 1 self->immobile_stage = 0;
1728 1 self->task_ssm = fpi_ssm_new_full (device, fpc_enroll_sm_run_state,
1729 FPC_ENROLL_NUM_STATES,
1730 FPC_ENROLL_DICARD,
1731 "enroll");
1732
1733 1 fpi_ssm_start (self->task_ssm, fpc_enroll_ssm_done);
1734 1 }
1735
1736 static void
1737 1 fpc_dev_template_list (FpDevice *device)
1738 {
1739 1 FpiDeviceFpcMoc *self = FPI_DEVICE_FPCMOC (device);
1740 1 CommandData cmd_data = {0};
1741 1 FPC_FID_DATA pquery_data = {0};
1742 1 gsize query_data_len = 0;
1743 1 guint32 wildcard_value = FPC_IDENTITY_WILDCARD;
1744
1745 1 fp_dbg ("%s enter -->", G_STRFUNC);
1746
1747 1 query_data_len = sizeof (FPC_FID_DATA);
1748 1 pquery_data.identity_type = FPC_IDENTITY_TYPE_WILDCARD;
1749 1 pquery_data.reserved = 16;
1750 1 pquery_data.identity_size = sizeof (wildcard_value);
1751 1 pquery_data.subfactor = (guint32) FPC_SUBTYPE_ANY;
1752 1 memcpy (&pquery_data.data[0],
1753 &wildcard_value, pquery_data.identity_size);
1754
1755 1 cmd_data.cmdtype = FPC_CMDTYPE_TO_DEVICE_EVTDATA;
1756 1 cmd_data.request = FPC_CMD_ENUM;
1757 1 cmd_data.value = 0x0;
1758 1 cmd_data.index = 0x0;
1759 1 cmd_data.data = (guint8 *) &pquery_data;
1760 1 cmd_data.data_len = query_data_len;
1761 1 cmd_data.callback = fpc_template_list_cb;
1762
1763 1 fpc_sensor_cmd (self, FALSE, &cmd_data);
1764 1 }
1765
1766 static void
1767 fpc_dev_suspend (FpDevice *device)
1768 {
1769 FpiDeviceFpcMoc *self = FPI_DEVICE_FPCMOC (device);
1770 FpiDeviceAction action = fpi_device_get_current_action (device);
1771
1772 fp_dbg ("%s enter -->", G_STRFUNC);
1773
1774 if (action != FPI_DEVICE_ACTION_VERIFY && action != FPI_DEVICE_ACTION_IDENTIFY)
1775 {
1776 fpi_device_suspend_complete (device, fpi_device_error_new (FP_DEVICE_ERROR_NOT_SUPPORTED));
1777 return;
1778 }
1779
1780 g_assert (self->cmd_ssm);
1781 g_assert (fpi_ssm_get_cur_state (self->cmd_ssm) == FPC_CMD_GET_DATA);
1782 self->cmd_suspended = TRUE;
1783 g_cancellable_cancel (self->interrupt_cancellable);
1784 }
1785
1786 static void
1787 fpc_dev_resume (FpDevice *device)
1788 {
1789 FpiDeviceFpcMoc *self = FPI_DEVICE_FPCMOC (device);
1790 FpiDeviceAction action = fpi_device_get_current_action (device);
1791
1792 fp_dbg ("%s enter -->", G_STRFUNC);
1793
1794 if (action != FPI_DEVICE_ACTION_VERIFY && action != FPI_DEVICE_ACTION_IDENTIFY)
1795 {
1796 g_assert_not_reached ();
1797 fpi_device_resume_complete (device, fpi_device_error_new (FP_DEVICE_ERROR_NOT_SUPPORTED));
1798 return;
1799 }
1800
1801 g_assert (self->cmd_ssm);
1802 g_assert (self->cmd_suspended);
1803 g_assert (fpi_ssm_get_cur_state (self->cmd_ssm) == FPC_CMD_SUSPENDED);
1804 self->cmd_suspended = FALSE;
1805
1806 g_clear_object (&self->interrupt_cancellable);
1807 self->interrupt_cancellable = g_cancellable_new ();
1808 fpi_ssm_jump_to_state (self->cmd_ssm, FPC_CMD_RESUME);
1809 }
1810
1811 static void
1812 fpc_dev_cancel (FpDevice *device)
1813 {
1814 FpiDeviceFpcMoc *self = FPI_DEVICE_FPCMOC (device);
1815
1816 fp_dbg ("%s enter -->", G_STRFUNC);
1817 g_cancellable_cancel (self->interrupt_cancellable);
1818 }
1819
1820 static void
1821 1 fpc_dev_template_delete (FpDevice *device)
1822 {
1823 1 FpiDeviceFpcMoc *self = FPI_DEVICE_FPCMOC (device);
1824 1 CommandData cmd_data = {0};
1825 1 FpPrint *print = NULL;
1826
1827 1 g_autoptr(GVariant) fpi_data = NULL;
1828 1 FPC_FID_DATA data = {0};
1829 1 gsize data_len = 0;
1830 1 guint8 finger = FPC_SUBTYPE_NOINFORMATION;
1831 1 const guint8 *user_id;
1832 1 gsize user_id_len = 0;
1833
1834 1 fp_dbg ("%s enter -->", G_STRFUNC);
1835
1836 1 fpi_device_get_delete_data (device, &print);
1837
1838 1 g_object_get (print, "fpi-data", &fpi_data, NULL);
1839
1840
1/2
✗ Branch 6 → 7 not taken.
✓ Branch 6 → 12 taken 1 time.
1 if (!parse_print_data (fpi_data, &finger, &user_id, &user_id_len))
1841 {
1842 fpi_device_delete_complete (device,
1843 fpi_device_error_new (FP_DEVICE_ERROR_DATA_INVALID));
1844 return;
1845 }
1846
1847 1 data_len = sizeof (FPC_FID_DATA);
1848 1 data.identity_type = FPC_IDENTITY_TYPE_RESERVED;
1849 1 data.reserved = 16;
1850 1 data.identity_size = user_id_len;
1851 1 data.subfactor = (guint32) finger;
1852 1 memcpy (&data.data[0], user_id, user_id_len);
1853 1 cmd_data.cmdtype = FPC_CMDTYPE_TO_DEVICE;
1854 1 cmd_data.request = FPC_CMD_DELETE_TEMPLATE;
1855 1 cmd_data.value = 0x0;
1856 1 cmd_data.index = 0x0;
1857 1 cmd_data.data = (guint8 *) &data;
1858 1 cmd_data.data_len = data_len;
1859 1 cmd_data.callback = fpc_template_delete_cb;
1860
1861 1 fpc_sensor_cmd (self, FALSE, &cmd_data);
1862
1/2
✓ Branch 14 → 15 taken 1 time.
✗ Branch 14 → 16 not taken.
1 fp_dbg ("%s exit <--", G_STRFUNC);
1863 }
1864
1865 static void
1866 1 fpc_dev_clear_storage (FpDevice *device)
1867 {
1868 1 FpiDeviceFpcMoc *self = FPI_DEVICE_FPCMOC (device);
1869
1870 1 fp_dbg ("%s enter -->", G_STRFUNC);
1871 1 self->task_ssm = fpi_ssm_new_full (device, fpc_clear_sm_run_state,
1872 FPC_CLEAR_NUM_STATES,
1873 FPC_CLEAR_NUM_STATES,
1874 "Clear storage");
1875
1876 1 fpi_ssm_start (self->task_ssm, fpc_clear_ssm_done);
1877 1 }
1878
1879 static void
1880 1 fpi_device_fpcmoc_init (FpiDeviceFpcMoc *self)
1881 {
1882 1 fp_dbg ("%s enter -->", G_STRFUNC);
1883 1 G_DEBUG_HERE ();
1884 1 }
1885
1886 static void
1887 122 fpi_device_fpcmoc_class_init (FpiDeviceFpcMocClass *klass)
1888 {
1889 122 FpDeviceClass *dev_class = FP_DEVICE_CLASS (klass);
1890
1891 122 dev_class->id = FP_COMPONENT;
1892 122 dev_class->full_name = "FPC MOC Fingerprint Sensor";
1893 122 dev_class->type = FP_DEVICE_TYPE_USB;
1894 122 dev_class->scan_type = FP_SCAN_TYPE_PRESS;
1895 122 dev_class->id_table = id_table;
1896 122 dev_class->nr_enroll_stages = MAX_ENROLL_SAMPLES;
1897 122 dev_class->temp_hot_seconds = -1;
1898
1899 122 dev_class->open = fpc_dev_open;
1900 122 dev_class->close = fpc_dev_close;
1901 122 dev_class->probe = fpc_dev_probe;
1902 122 dev_class->enroll = fpc_dev_enroll;
1903 122 dev_class->delete = fpc_dev_template_delete;
1904 122 dev_class->list = fpc_dev_template_list;
1905 122 dev_class->verify = fpc_dev_verify_identify;
1906 122 dev_class->identify = fpc_dev_verify_identify;
1907 122 dev_class->suspend = fpc_dev_suspend;
1908 122 dev_class->resume = fpc_dev_resume;
1909 122 dev_class->clear_storage = fpc_dev_clear_storage;
1910 122 dev_class->cancel = fpc_dev_cancel;
1911
1912 122 fpi_device_class_auto_initialize_features (dev_class);
1913 122 dev_class->features |= FP_DEVICE_FEATURE_DUPLICATES_CHECK;
1914 122 }
1915