GCC Code Coverage Report


Directory: ./
File: libfprint/drivers/fpcmoc/fpc.c
Date: 2025-03-01 04:11:53
Exec Total Coverage
Lines: 719 959 75.0%
Functions: 43 48 89.6%
Branches: 152 309 49.2%

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