GCC Code Coverage Report


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