GCC Code Coverage Report


Directory: ./
File: libfprint/drivers/fpcmoc/fpc.c
Date: 2024-05-04 14:54:39
Exec Total Coverage
Lines: 719 957 75.1%
Functions: 43 48 89.6%
Branches: 153 310 49.4%

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