GCC Code Coverage Report


Directory: ./
File: libfprint/drivers/fpcmoc/fpc.c
Date: 2026-02-20 04:10:22
Exec Total Coverage
Lines: 716 958 74.7%
Functions: 43 48 89.6%
Branches: 152 311 48.9%

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