GCC Code Coverage Report


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 81.3% 552 / 0 / 679
Functions: 100.0% 45 / 0 / 45
Branches: 56.5% 143 / 0 / 253

libfprint/drivers/realtek/realtek.c
Line Branch Exec Source
1 /*
2 * Copyright (C) 2022-2023 Realtek Corp.
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 #define FP_COMPONENT "realtek"
20
21 #include "drivers_api.h"
22
23 #include "fpi-byte-reader.h"
24
25 #include "realtek.h"
26
27
4/6
fpi_device_realtek_class_intern_init:
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 125 times.
fpi_device_realtek_get_type:
✓ Branch 2 → 3 taken 125 times.
✓ Branch 2 → 7 taken 24 times.
✓ Branch 4 → 5 taken 125 times.
✗ Branch 4 → 7 not taken.
399 G_DEFINE_TYPE (FpiDeviceRealtek, fpi_device_realtek, FP_TYPE_DEVICE)
28
29 static const FpIdEntry id_table[] = {
30 { .vid = 0x0bda, .pid = 0x5813, },
31 { .vid = 0x0bda, .pid = 0x5816, },
32 { .vid = 0x2541, .pid = 0xfa03, },
33 { .vid = 0x3274, .pid = 0x9003, },
34 { .vid = 0, .pid = 0, .driver_data = 0 }, /* terminating entry */
35 };
36
37 static gboolean
38 2 parse_print_data (GVariant *data,
39 guint8 *finger,
40 const guint8 **user_id,
41 gsize *user_id_len)
42 {
43 4 g_autoptr(GVariant) user_id_var = NULL;
44
45
1/2
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 4 taken 2 times.
2 g_return_val_if_fail (data, FALSE);
46
1/2
✓ Branch 4 → 5 taken 2 times.
✗ Branch 4 → 6 not taken.
2 g_return_val_if_fail (finger, FALSE);
47
1/2
✓ Branch 5 → 7 taken 2 times.
✗ Branch 5 → 8 not taken.
2 g_return_val_if_fail (user_id, FALSE);
48
1/2
✓ Branch 7 → 9 taken 2 times.
✗ Branch 7 → 11 not taken.
2 g_return_val_if_fail (user_id_len, FALSE);
49
50 2 *user_id = NULL;
51 2 *user_id_len = 0;
52 2 *finger = 0;
53
54
1/2
✓ Branch 10 → 12 taken 2 times.
✗ Branch 10 → 18 not taken.
2 if (!g_variant_check_format_string (data, "(y@ay)", FALSE))
55 return FALSE;
56
57 2 g_variant_get (data,
58 "(y@ay)",
59 finger,
60 &user_id_var);
61
62 2 *user_id = g_variant_get_fixed_array (user_id_var, user_id_len, 1);
63
64
1/2
✓ Branch 14 → 15 taken 2 times.
✗ Branch 14 → 18 not taken.
2 if (*user_id_len == 0 || *user_id_len > DEFAULT_UID_LEN)
65 return FALSE;
66
67
1/2
✓ Branch 15 → 16 taken 2 times.
✗ Branch 15 → 18 not taken.
2 if (*user_id[0] == '\0' || *user_id[0] == ' ')
68 return FALSE;
69
70
1/2
✗ Branch 16 → 17 not taken.
✓ Branch 16 → 18 taken 2 times.
2 if (*finger != SUB_FINGER_01)
71 return FALSE;
72
73 return TRUE;
74 }
75
76 static void
77 96 fp_cmd_ssm_done_data_free (CommandData *data)
78 {
79 96 g_free (data);
80 96 }
81
82 /* data callbacks */
83
84 static void
85 28 fp_task_ssm_generic_cb (FpiDeviceRealtek *self,
86 uint8_t *buffer_in,
87 GError *error)
88 {
89
1/2
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 5 taken 28 times.
28 if (error)
90 {
91 fpi_ssm_mark_failed (self->task_ssm, error);
92 return;
93 }
94
95 28 fpi_ssm_next_state (self->task_ssm);
96 }
97
98 static void
99 2 fp_get_device_info_cb (FpiDeviceRealtek *self,
100 uint8_t *buffer_in,
101 GError *error)
102 {
103
1/2
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 5 taken 2 times.
2 if (error)
104 {
105 fpi_ssm_mark_failed (self->task_ssm, error);
106 return;
107 }
108
109 2 self->template_len = TEMPLATE_LEN_COMMON;
110
111 2 fpi_ssm_next_state (self->task_ssm);
112 }
113
114 static void
115 2 fp_update_template_cb (FpiDeviceRealtek *self,
116 uint8_t *buffer_in,
117 GError *error)
118 {
119
1/2
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 5 taken 2 times.
2 if (error)
120 {
121 fpi_ssm_mark_failed (self->task_ssm, error);
122 return;
123 }
124
125 2 fpi_ssm_jump_to_state (self->task_ssm, FP_RTK_VERIFY_NUM_STATES);
126 }
127
128 static void
129 2 fp_enroll_commit_cb (FpiDeviceRealtek *self,
130 uint8_t *buffer_in,
131 GError *error)
132 {
133
1/2
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 5 taken 2 times.
2 if (error)
134 {
135 fpi_ssm_mark_failed (self->task_ssm, error);
136 return;
137 }
138
139 2 fpi_ssm_jump_to_state (self->task_ssm, FP_RTK_ENROLL_NUM_STATES);
140 }
141
142 static void
143 22 fp_finish_capture_cb (FpiDeviceRealtek *self,
144 uint8_t *buffer_in,
145 GError *error)
146 {
147
1/2
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 5 taken 22 times.
22 if (error)
148 {
149 fpi_ssm_mark_failed (self->task_ssm, error);
150 return;
151 }
152
153 /* We hope this polling CMD can be completed before the action is cancelled */
154 22 GCancellable *cancellable = fpi_device_get_cancellable (FP_DEVICE (self));
155
1/2
✗ Branch 7 → 8 not taken.
✓ Branch 7 → 11 taken 22 times.
22 if (g_cancellable_is_cancelled (cancellable))
156 {
157 fpi_ssm_mark_failed (self->task_ssm,
158 fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
159 "Action is cancelled!"));
160 return;
161 }
162
163 22 gint capture_status = buffer_in[0];
164
1/2
✓ Branch 11 → 12 taken 22 times.
✗ Branch 11 → 14 not taken.
22 if (capture_status == 0)
165 {
166 22 fpi_device_report_finger_status_changes (FP_DEVICE (self),
167 FP_FINGER_STATUS_PRESENT,
168 FP_FINGER_STATUS_NEEDED);
169 22 fpi_ssm_next_state (self->task_ssm);
170 }
171 else
172 {
173 fpi_ssm_jump_to_state (self->task_ssm,
174 fpi_ssm_get_cur_state (self->task_ssm));
175 }
176 }
177
178 static void
179 22 fp_accept_sample_cb (FpiDeviceRealtek *self,
180 uint8_t *buffer_in,
181 GError *error)
182 {
183 22 fpi_device_report_finger_status_changes (FP_DEVICE (self),
184 FP_FINGER_STATUS_NONE,
185 FP_FINGER_STATUS_PRESENT);
186
187
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 6 taken 22 times.
22 if (error)
188 {
189 fpi_ssm_mark_failed (self->task_ssm, error);
190 return;
191 }
192
193 22 gint in_status = buffer_in[0];
194
195
2/2
✓ Branch 6 → 7 taken 4 times.
✓ Branch 6 → 9 taken 18 times.
22 if (self->fp_purpose != FP_RTK_PURPOSE_ENROLL)
196 {
197 /* verify or identify purpose process */
198 4 fpi_ssm_next_state (self->task_ssm);
199 4 return;
200 }
201 else
202 {
203 /* enroll purpose process */
204
1/2
✗ Branch 9 → 10 not taken.
✓ Branch 9 → 13 taken 18 times.
18 if (in_status == FP_RTK_CMD_ERR)
205 {
206 fpi_ssm_mark_failed (self->task_ssm,
207 fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
208 "Command error!"));
209 return;
210 }
211
212
2/2
✓ Branch 13 → 14 taken 16 times.
✓ Branch 13 → 23 taken 2 times.
18 if (self->enroll_stage < self->max_enroll_stage)
213 {
214
1/2
✓ Branch 14 → 15 taken 16 times.
✗ Branch 14 → 17 not taken.
16 if (in_status == FP_RTK_SUCCESS)
215 {
216 16 self->enroll_stage++;
217 16 fpi_device_enroll_progress (FP_DEVICE (self), self->enroll_stage, NULL, NULL);
218 16 fpi_ssm_jump_to_state (self->task_ssm, FP_RTK_ENROLL_CAPTURE);
219 }
220 else if (in_status == FP_RTK_MATCH_FAIL)
221 {
222 fpi_ssm_mark_failed (self->task_ssm,
223 fpi_device_error_new_msg (FP_DEVICE_ERROR_DATA_INVALID,
224 "InStatus invalid!"));
225 }
226 else
227 {
228 fpi_device_enroll_progress (FP_DEVICE (self),
229 self->enroll_stage,
230 NULL,
231 fpi_device_retry_new (FP_DEVICE_RETRY_GENERAL));
232
233 fpi_ssm_jump_to_state (self->task_ssm, FP_RTK_ENROLL_CAPTURE);
234 }
235 return;
236 }
237
238
1/2
✗ Branch 23 → 24 not taken.
✓ Branch 23 → 27 taken 2 times.
2 if (in_status != FP_RTK_SUCCESS)
239 {
240 fpi_ssm_mark_failed (self->task_ssm,
241 fpi_device_error_new_msg (FP_DEVICE_ERROR_DATA_INVALID,
242 "Enrollment failed (status 0x%02x)",
243 in_status));
244 return;
245 }
246
247 2 fpi_ssm_next_state (self->task_ssm);
248 }
249 }
250
251 static FpPrint *
252 6 fp_print_from_data (FpiDeviceRealtek *self, uint8_t *buffer)
253 {
254 6 FpPrint *print;
255 6 GVariant *data;
256 6 GVariant *uid;
257 6 guint finger;
258 6 gsize userid_len;
259 12 g_autofree gchar *userid = NULL;
260
261 6 userid = g_strndup ((gchar *) buffer + 1, DEFAULT_UID_LEN);
262 6 finger = *(buffer);
263
264 6 print = fp_print_new (FP_DEVICE (self));
265 6 userid_len = MIN (DEFAULT_UID_LEN, strlen (userid));
266
267 6 uid = g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE,
268 userid,
269 userid_len,
270 1);
271
272 6 data = g_variant_new ("(y@ay)",
273 finger,
274 uid);
275
276 6 fpi_print_set_type (print, FPI_PRINT_RAW);
277 6 fpi_print_set_device_stored (print, TRUE);
278 6 g_object_set (print, "fpi-data", data, NULL);
279 6 g_object_set (print, "description", userid, NULL);
280 6 fpi_print_fill_from_user_id (print, userid);
281
282 6 return print;
283 }
284
285 static void
286 4 fp_identify_feature_cb (FpiDeviceRealtek *self,
287 uint8_t *buffer_in,
288 GError *error)
289 {
290 4 FpDevice *device = FP_DEVICE (self);
291 4 FpPrint *match = NULL;
292 4 FpPrint *print = NULL;
293 4 FpiDeviceAction current_action;
294
295 4 g_autoptr(GPtrArray) templates = NULL;
296 4 gboolean found = FALSE;
297
298 4 current_action = fpi_device_get_current_action (device);
299
300
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 4 times.
4 if (error)
301 {
302 fpi_ssm_mark_failed (self->task_ssm, error);
303 return;
304 }
305
306 4 gint in_status = buffer_in[0];
307
1/2
✗ Branch 5 → 6 not taken.
✓ Branch 5 → 9 taken 4 times.
4 if (in_status == FP_RTK_CMD_ERR)
308 {
309 fpi_ssm_mark_failed (self->task_ssm,
310 fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
311 "Command error!"));
312 return;
313 }
314
315
1/2
✗ Branch 9 → 10 not taken.
✓ Branch 9 → 13 taken 4 times.
4 if (in_status >= FP_RTK_TOO_HIGH && in_status <= FP_RTK_MERGE_FAILURE)
316 {
317 fpi_ssm_mark_failed (self->task_ssm,
318 fpi_device_retry_new (FP_DEVICE_RETRY_GENERAL));
319 return;
320 }
321
322
1/2
✓ Branch 13 → 14 taken 4 times.
✗ Branch 13 → 32 not taken.
4 if (in_status == FP_RTK_SUCCESS)
323 {
324 4 match = fp_print_from_data (self, buffer_in + 1);
325
326
2/2
✓ Branch 15 → 16 taken 2 times.
✓ Branch 15 → 19 taken 2 times.
4 if (current_action == FPI_DEVICE_ACTION_VERIFY)
327 {
328 2 templates = g_ptr_array_sized_new (1);
329 2 fpi_device_get_verify_data (device, &print);
330 2 g_ptr_array_add (templates, print);
331 }
332 else
333 {
334 2 fpi_device_get_identify_data (device, &templates);
335 2 g_ptr_array_ref (templates);
336 }
337
338
1/2
✓ Branch 25 → 22 taken 4 times.
✗ Branch 25 → 26 not taken.
4 for (gint cnt = 0; cnt < templates->len; cnt++)
339 {
340 4 print = g_ptr_array_index (templates, cnt);
341
342
1/2
✗ Branch 23 → 24 not taken.
✓ Branch 23 → 26 taken 4 times.
4 if (fp_print_equal (print, match))
343 {
344 found = TRUE;
345 break;
346 }
347 }
348
349
1/2
✓ Branch 26 → 27 taken 4 times.
✗ Branch 26 → 32 not taken.
4 if (found)
350 {
351
2/2
✓ Branch 27 → 28 taken 2 times.
✓ Branch 27 → 30 taken 2 times.
4 if (current_action == FPI_DEVICE_ACTION_VERIFY)
352 {
353 2 fpi_device_verify_report (device, FPI_MATCH_SUCCESS, match, error);
354 2 fpi_ssm_next_state (self->task_ssm);
355 }
356 else
357 {
358 2 fpi_device_identify_report (device, print, match, error);
359 2 fpi_ssm_jump_to_state (self->task_ssm, FP_RTK_VERIFY_NUM_STATES);
360 }
361 return;
362 }
363 }
364
365 if (!found)
366 {
367 if (current_action == FPI_DEVICE_ACTION_VERIFY)
368 fpi_device_verify_report (device, FPI_MATCH_FAIL, NULL, error);
369 else
370 fpi_device_identify_report (device, NULL, NULL, error);
371
372 fpi_ssm_jump_to_state (self->task_ssm, FP_RTK_VERIFY_NUM_STATES);
373 }
374 }
375
376 static void
377 2 fp_get_delete_pos_cb (FpiDeviceRealtek *self,
378 uint8_t *buffer_in,
379 GError *error)
380 {
381 2 FpPrint *print = NULL;
382
383 2 g_autoptr(GVariant) data = NULL;
384 2 gsize user_id_len = 0;
385 2 const guint8 *user_id;
386 2 guint8 finger;
387 2 gboolean found = FALSE;
388 2 gchar temp_userid[DEFAULT_UID_LEN + 1] = {0};
389
390
1/2
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 4 taken 2 times.
2 if (error)
391 {
392 fpi_ssm_mark_failed (self->task_ssm, error);
393 return;
394 }
395
396 2 fpi_device_get_delete_data (FP_DEVICE (self), &print);
397 2 g_object_get (print, "fpi-data", &data, NULL);
398
399
1/2
✗ Branch 7 → 8 not taken.
✓ Branch 7 → 18 taken 2 times.
2 if (!parse_print_data (data, &finger, &user_id, &user_id_len))
400 {
401 fpi_device_delete_complete (FP_DEVICE (self),
402 fpi_device_error_new (FP_DEVICE_ERROR_DATA_INVALID));
403 return;
404 }
405
406
1/2
✓ Branch 18 → 11 taken 2 times.
✗ Branch 18 → 19 not taken.
2 for (gint i = 0; i < self->template_num; i++)
407 {
408
1/2
✓ Branch 11 → 12 taken 2 times.
✗ Branch 11 → 17 not taken.
2 if (buffer_in[i * self->template_len] != 0)
409 {
410 2 memcpy (temp_userid, buffer_in + i * self->template_len + UID_OFFSET, DEFAULT_UID_LEN);
411
1/2
✓ Branch 14 → 15 taken 2 times.
✗ Branch 14 → 17 not taken.
2 if (g_strcmp0 (fp_print_get_description (print), (const char *) temp_userid) == 0)
412 {
413 2 self->pos_index = i;
414 2 found = TRUE;
415 2 break;
416 }
417 }
418 }
419
420 2 if (!found)
421 {
422 fpi_ssm_mark_failed (self->task_ssm,
423 fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
424 "Get template position failed!"));
425 return;
426 }
427
428
1/2
✓ Branch 16 → 22 taken 2 times.
✗ Branch 16 → 23 not taken.
2 fpi_ssm_next_state (self->task_ssm);
429 }
430
431 static void
432 2 fp_get_enroll_num_cb (FpiDeviceRealtek *self,
433 uint8_t *buffer_in,
434 GError *error)
435 {
436
1/2
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 5 taken 2 times.
2 if (error)
437 {
438 fpi_ssm_mark_failed (self->task_ssm, error);
439 return;
440 }
441
442 2 self->template_num = buffer_in[1];
443
444 2 fpi_ssm_next_state (self->task_ssm);
445 }
446
447 static void
448 4 fp_verify_get_template_cb (FpiDeviceRealtek *self,
449 uint8_t *buffer_in,
450 GError *error)
451 {
452
1/2
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 5 taken 4 times.
4 if (error)
453 {
454 fpi_ssm_mark_failed (self->task_ssm, error);
455 return;
456 }
457
458 4 fpi_ssm_next_state (self->task_ssm);
459 }
460
461 static void
462 2 fp_enroll_get_template_cb (FpiDeviceRealtek *self,
463 uint8_t *buffer_in,
464 GError *error)
465 {
466 2 g_autofree guchar *seq_list = NULL;
467 2 gboolean found = FALSE;
468
469
1/2
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 9 taken 2 times.
2 if (error)
470 {
471 fpi_ssm_mark_failed (self->task_ssm, error);
472 return;
473 }
474
475
1/2
✓ Branch 9 → 5 taken 2 times.
✗ Branch 9 → 10 not taken.
2 for (gint i = 0; i < self->template_num; i++)
476 {
477
1/2
✓ Branch 5 → 6 taken 2 times.
✗ Branch 5 → 8 not taken.
2 if (buffer_in[i * self->template_len] == 0)
478 {
479 2 self->pos_index = i;
480 2 found = TRUE;
481 2 break;
482 }
483 }
484
485 2 if (!found)
486 {
487 fpi_ssm_mark_failed (self->task_ssm,
488 fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
489 "No free template was found!"));
490 return;
491 }
492
493 2 fpi_ssm_next_state (self->task_ssm);
494 }
495
496 static void
497 2 fp_check_duplicate_cb (FpiDeviceRealtek *self,
498 uint8_t *buffer_in,
499 GError *error)
500 {
501
1/2
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 5 taken 2 times.
2 if (error)
502 {
503 fpi_ssm_mark_failed (self->task_ssm, error);
504 return;
505 }
506
507 2 gint in_status = buffer_in[0];
508
1/2
✗ Branch 5 → 6 not taken.
✓ Branch 5 → 9 taken 2 times.
2 if (in_status == FP_RTK_CMD_ERR)
509 {
510 fpi_ssm_mark_failed (self->task_ssm,
511 fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
512 "Command error!"));
513 return;
514 }
515
516
1/2
✗ Branch 9 → 10 not taken.
✓ Branch 9 → 12 taken 2 times.
2 if (in_status == FP_RTK_SUCCESS)
517 {
518 fpi_ssm_mark_failed (self->task_ssm,
519 fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
520 "Current fingerprint is duplicate!"));
521 }
522
1/2
✓ Branch 12 → 13 taken 2 times.
✗ Branch 12 → 14 not taken.
2 else if (in_status == FP_RTK_MATCH_FAIL)
523 {
524 2 fpi_ssm_next_state (self->task_ssm);
525 }
526 else
527 {
528 fpi_ssm_mark_failed (self->task_ssm,
529 fpi_device_error_new_msg (FP_DEVICE_ERROR_DATA_INVALID,
530 "InStatus invalid!"));
531 }
532 }
533
534 static void
535 2 fp_list_cb (FpiDeviceRealtek *self,
536 uint8_t *buffer_in,
537 GError *error)
538 {
539 2 gboolean found = FALSE;
540
541 2 g_autoptr(GPtrArray) list_result = NULL;
542
543
1/2
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 5 taken 2 times.
2 if (error)
544 {
545 fpi_device_list_complete (FP_DEVICE (self), NULL, error);
546 return;
547 }
548
549 2 list_result = g_ptr_array_new_with_free_func (g_object_unref);
550
551
2/2
✓ Branch 12 → 7 taken 10 times.
✓ Branch 12 → 13 taken 2 times.
14 for (gint i = 0; i < self->template_num; i++)
552 {
553
2/2
✓ Branch 7 → 8 taken 2 times.
✓ Branch 7 → 11 taken 8 times.
10 if (buffer_in[i * self->template_len] != 0)
554 {
555 2 FpPrint *print = NULL;
556 2 print = fp_print_from_data (self, buffer_in + i * self->template_len + SUBFACTOR_OFFSET);
557 2 g_ptr_array_add (list_result, g_object_ref_sink (print));
558 2 found = TRUE;
559 }
560 }
561
562
1/2
✗ Branch 13 → 14 not taken.
✓ Branch 13 → 17 taken 2 times.
2 if (!found)
563 {
564 fpi_device_list_complete (FP_DEVICE (self),
565 g_steal_pointer (&list_result),
566 fpi_device_error_new_msg (FP_DEVICE_ERROR_DATA_FULL,
567 "Database is empty"));
568 return;
569 }
570
571 2 fp_info ("Query templates complete!");
572 2 fpi_device_list_complete (FP_DEVICE (self),
573 2 g_steal_pointer (&list_result),
574 NULL);
575 }
576
577 static void
578 2 fp_clear_storage_cb (FpiDeviceRealtek *self,
579 uint8_t *buffer_in,
580 GError *error)
581 {
582 2 FpDevice *device = FP_DEVICE (self);
583
584
1/2
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 5 taken 2 times.
2 if (error)
585 {
586 fpi_device_clear_storage_complete (device, error);
587 return;
588 }
589
590 2 fp_info ("Successfully cleared storage");
591 2 fpi_device_clear_storage_complete (device, NULL);
592 }
593
594
595 static gint
596 96 parse_status (guint8 *buffer, gint status_type)
597 {
598 96 switch (status_type)
599 {
600 case FP_RTK_MSG_NO_STATUS:
601 return 0;
602 68 break;
603
604 68 case FP_RTK_MSG_DEFAULT:
605 68 return buffer[0];
606 break;
607
608 default:
609 return 1;
610 68 break;
611 }
612 }
613
614 static void
615 158 fp_cmd_receive_cb (FpiUsbTransfer *transfer,
616 FpDevice *device,
617 gpointer user_data,
618 GError *error)
619 {
620 158 FpiDeviceRealtek *self = FPI_DEVICE_REALTEK (device);
621 158 CommandData *data = user_data;
622 158 gint ssm_state = 0;
623 158 gint status_flag = 1;
624
625
1/2
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 5 taken 158 times.
158 if (error)
626 {
627 fpi_ssm_mark_failed (transfer->ssm, error);
628 return;
629 }
630
1/2
✗ Branch 5 → 6 not taken.
✓ Branch 5 → 9 taken 158 times.
158 if (data == NULL)
631 {
632 fpi_ssm_mark_failed (transfer->ssm,
633 fpi_device_error_new (FP_DEVICE_ERROR_GENERAL));
634 return;
635 }
636
637 158 ssm_state = fpi_ssm_get_cur_state (transfer->ssm);
638
639 /* skip zero length package */
640
1/2
✗ Branch 10 → 11 not taken.
✓ Branch 10 → 13 taken 158 times.
158 if (transfer->actual_length == 0)
641 {
642 fpi_ssm_jump_to_state (transfer->ssm, ssm_state);
643 return;
644 }
645
646 /* get data */
647
2/2
✓ Branch 13 → 14 taken 62 times.
✓ Branch 13 → 22 taken 96 times.
158 if (ssm_state == FP_RTK_CMD_TRANS_DATA)
648 {
649 62 g_autofree guchar *read_buf = NULL;
650
651
1/2
✗ Branch 14 → 15 not taken.
✓ Branch 14 → 18 taken 62 times.
62 if ((gsize) transfer->actual_length < self->trans_data_len)
652 {
653 fpi_ssm_mark_failed (transfer->ssm,
654 fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
655 "Truncated data received"));
656 return;
657 }
658
659 62 read_buf = g_malloc0 (sizeof (guchar) * (self->trans_data_len));
660 62 memcpy (read_buf, transfer->buffer, self->trans_data_len);
661 62 self->read_data = g_steal_pointer (&read_buf);
662
663 62 fpi_ssm_next_state (transfer->ssm);
664 62 return;
665 }
666
667 /* get status */
668
2/3
✓ Branch 22 → 23 taken 68 times.
✗ Branch 22 → 24 not taken.
✓ Branch 22 → 27 taken 28 times.
96 status_flag = parse_status (transfer->buffer, self->message_type);
669
1/2
✗ Branch 23 → 24 not taken.
✓ Branch 23 → 27 taken 68 times.
68 if (status_flag != 0)
670 {
671 fpi_ssm_mark_failed (transfer->ssm,
672 fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
673 "Status check failed"));
674 return;
675 }
676
677
1/2
✓ Branch 27 → 28 taken 96 times.
✗ Branch 27 → 29 not taken.
96 if (data->callback)
678 96 data->callback (self, self->read_data, NULL);
679
680
2/2
✓ Branch 29 → 30 taken 62 times.
✓ Branch 29 → 31 taken 34 times.
96 if (self->read_data)
681 62 g_clear_pointer (&self->read_data, g_free);
682
683 96 fpi_ssm_mark_completed (transfer->ssm);
684 }
685
686 static void
687 288 fp_cmd_run_state (FpiSsm *ssm, FpDevice *dev)
688 {
689 288 FpiUsbTransfer *transfer = NULL;
690 288 FpiDeviceRealtek *self = FPI_DEVICE_REALTEK (dev);
691
692
3/4
✓ Branch 3 → 4 taken 96 times.
✓ Branch 3 → 7 taken 96 times.
✓ Branch 3 → 22 taken 96 times.
✗ Branch 3 → 27 not taken.
288 switch (fpi_ssm_get_cur_state (ssm))
693 {
694 96 case FP_RTK_CMD_SEND:
695
1/2
✓ Branch 4 → 5 taken 96 times.
✗ Branch 4 → 6 not taken.
96 if (self->cmd_transfer)
696 {
697 96 self->cmd_transfer->ssm = ssm;
698 96 fpi_usb_transfer_submit (g_steal_pointer (&self->cmd_transfer),
699 CMD_TIMEOUT,
700 NULL,
701 fpi_ssm_usb_transfer_cb,
702 NULL);
703 }
704 else
705 {
706 fpi_ssm_next_state (ssm);
707 }
708 break;
709
710 96 case FP_RTK_CMD_TRANS_DATA:
711
2/2
✓ Branch 7 → 8 taken 32 times.
✓ Branch 7 → 10 taken 64 times.
96 if (self->cmd_type == FP_RTK_CMD_BULK_ONLY)
712 {
713 32 fpi_ssm_jump_to_state (ssm, FP_RTK_CMD_GET_STATUS);
714 32 break;
715 }
716
717
2/2
✓ Branch 10 → 11 taken 2 times.
✓ Branch 10 → 14 taken 62 times.
64 if (self->cmd_type == FP_RTK_CMD_BULK_WRITE)
718 {
719
1/2
✓ Branch 11 → 12 taken 2 times.
✗ Branch 11 → 13 not taken.
2 if (self->data_transfer)
720 {
721 2 self->data_transfer->ssm = ssm;
722 2 fpi_usb_transfer_submit (g_steal_pointer (&self->data_transfer),
723 DATA_TIMEOUT,
724 NULL,
725 fpi_ssm_usb_transfer_cb,
726 NULL);
727 }
728 else
729 {
730 fpi_ssm_next_state (ssm);
731 }
732 }
733 else /* CMD_READ */
734 {
735 62 transfer = fpi_usb_transfer_new (dev);
736 62 transfer->ssm = ssm;
737 62 fpi_usb_transfer_fill_bulk (transfer, EP_IN, EP_IN_MAX_BUF_SIZE);
738
739 124 fpi_usb_transfer_submit (transfer,
740
2/2
✓ Branch 19 → 20 taken 60 times.
✓ Branch 19 → 21 taken 2 times.
62 self->cmd_cancellable ? 0 : DATA_TIMEOUT,
741
2/2
✓ Branch 17 → 18 taken 2 times.
✓ Branch 17 → 19 taken 60 times.
62 self->cmd_cancellable ? fpi_device_get_cancellable (dev) : NULL,
742 fp_cmd_receive_cb,
743 fpi_ssm_get_data (ssm));
744 }
745 break;
746
747 96 case FP_RTK_CMD_GET_STATUS:
748 96 transfer = fpi_usb_transfer_new (dev);
749 96 transfer->ssm = ssm;
750 96 fpi_usb_transfer_fill_bulk (transfer, EP_IN, EP_IN_MAX_BUF_SIZE);
751 96 fpi_usb_transfer_submit (transfer,
752 STATUS_TIMEOUT,
753 NULL,
754 fp_cmd_receive_cb,
755 fpi_ssm_get_data (ssm));
756 96 break;
757 }
758 288 }
759
760 static void
761 96 fp_cmd_ssm_done (FpiSsm *ssm, FpDevice *dev, GError *error)
762 {
763 96 FpiDeviceRealtek *self = FPI_DEVICE_REALTEK (dev);
764 96 CommandData *data = fpi_ssm_get_data (ssm);
765
766 96 self->cmd_ssm = NULL;
767
768
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 7 taken 96 times.
96 if (error)
769 {
770 if (data->callback)
771 data->callback (self, NULL, error);
772 else
773 g_error_free (error);
774 }
775 96 }
776
777 static FpiUsbTransfer *
778 98 prepare_bulk_transfer (FpDevice *dev,
779 guint8 *data,
780 gsize data_len,
781 GDestroyNotify free_func)
782 {
783 196 g_autoptr(FpiUsbTransfer) transfer = NULL;
784
785
1/2
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 4 taken 98 times.
98 g_return_val_if_fail (data || data_len == 0, NULL);
786
787 98 transfer = fpi_usb_transfer_new (dev);
788
789 98 fpi_usb_transfer_fill_bulk_full (transfer,
790 EP_OUT,
791 data,
792 data_len,
793 free_func);
794
795 98 return g_steal_pointer (&transfer);
796 }
797
798
799 static void
800 2 fp_ctrl_cmd_cb (FpiUsbTransfer *transfer,
801 FpDevice *device,
802 gpointer user_data,
803 GError *error)
804 {
805 2 FpiDeviceRealtek *self = FPI_DEVICE_REALTEK (device);
806
1/2
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 4 taken 2 times.
4 g_autofree CommandData *data = g_steal_pointer (&user_data);
807
808
1/2
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 4 taken 2 times.
2 g_return_if_fail (data != NULL);
809
810
1/2
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 2 times.
2 if (error)
811 {
812 fpi_ssm_mark_failed (transfer->ssm, error);
813 return;
814 }
815
816
1/2
✗ Branch 6 → 7 not taken.
✓ Branch 6 → 9 taken 2 times.
2 if (transfer->direction == G_USB_DEVICE_DIRECTION_HOST_TO_DEVICE)
817 {
818 if (data->callback)
819 data->callback (self, NULL, NULL);
820 }
821 else
822 {
823
1/2
✗ Branch 9 → 10 not taken.
✓ Branch 9 → 14 taken 2 times.
2 if (transfer->actual_length == 0)
824 {
825 fp_info ("Control transfer receive data failed!");
826 fpi_ssm_mark_failed (transfer->ssm,
827 fpi_device_error_new (FP_DEVICE_ERROR_DATA_INVALID));
828 return;
829 }
830
831
1/2
✓ Branch 14 → 15 taken 2 times.
✗ Branch 14 → 16 not taken.
2 if (data->callback)
832 2 data->callback (self, transfer->buffer, NULL);
833 }
834 }
835
836 static void
837 2 rtk_send_ctrl_cmd (FpiDeviceRealtek *self,
838 struct rtk_cmd_ctrl *ctrl_cmd,
839 guint8 *cmd_data,
840 SynCmdMsgCallback callback)
841 {
842 2 FpiUsbTransfer *transfer = NULL;
843 2 g_autofree CommandData *data = g_new0 (CommandData, 1);
844
845 2 data->callback = callback;
846
847 2 transfer = fpi_usb_transfer_new (FP_DEVICE (self));
848 2 fpi_usb_transfer_fill_control (transfer,
849 2 ctrl_cmd->direction,
850 G_USB_DEVICE_REQUEST_TYPE_VENDOR,
851 G_USB_DEVICE_RECIPIENT_DEVICE,
852 2 ctrl_cmd->request,
853 2 ctrl_cmd->value,
854 2 ctrl_cmd->index,
855 2 ctrl_cmd->len);
856
857 2 transfer->ssm = self->task_ssm;
858
2/4
✓ Branch 5 → 6 taken 2 times.
✗ Branch 5 → 9 not taken.
✗ Branch 6 → 7 not taken.
✓ Branch 6 → 9 taken 2 times.
2 if (ctrl_cmd->direction == G_USB_DEVICE_DIRECTION_DEVICE_TO_HOST &&
859 cmd_data != NULL && ctrl_cmd->len != 0)
860 memcpy (transfer->buffer, cmd_data, ctrl_cmd->len);
861
862 2 fpi_usb_transfer_submit (transfer,
863 CMD_TIMEOUT,
864 NULL,
865 fp_ctrl_cmd_cb,
866 g_steal_pointer (&data));
867 2 }
868
869 static void
870 96 rtk_sensor_bulk_cmd (FpiDeviceRealtek *self,
871 guint8 *cmd,
872 guint8 *trans_data,
873 FpRtkMsgType message_type,
874 gboolean bwait_data_delay,
875 SynCmdMsgCallback callback)
876 {
877 192 g_autoptr(FpiUsbTransfer) cmd_transfer = NULL;
878 192 g_autoptr(FpiUsbTransfer) data_transfer = NULL;
879 96 CommandData *data = g_new0 (CommandData, 1);
880
881 96 self->cmd_type = GET_BULK_CMD_TYPE (cmd[0]);
882 96 self->message_type = message_type;
883 96 self->trans_data_len = GET_TRANS_DATA_LEN (cmd[11], cmd[10]);
884 96 self->cmd_cancellable = bwait_data_delay;
885
886 96 cmd_transfer = prepare_bulk_transfer (FP_DEVICE (self), cmd, FP_RTK_CMD_BULK_TOTAL_LEN, NULL);
887
2/2
✓ Branch 4 → 5 taken 2 times.
✓ Branch 4 → 8 taken 94 times.
96 self->cmd_transfer = g_steal_pointer (&cmd_transfer);
888
889
3/4
✓ Branch 4 → 5 taken 2 times.
✓ Branch 4 → 8 taken 94 times.
✓ Branch 5 → 6 taken 2 times.
✗ Branch 5 → 8 not taken.
96 if ((self->cmd_type == FP_RTK_CMD_BULK_WRITE) && trans_data)
890 {
891 2 data_transfer = prepare_bulk_transfer (FP_DEVICE (self), trans_data, self->trans_data_len, g_free);
892 2 self->data_transfer = g_steal_pointer (&data_transfer);
893 }
894
895 96 self->cmd_ssm = fpi_ssm_new (FP_DEVICE (self),
896 fp_cmd_run_state,
897 FP_RTK_CMD_NUM_STATES);
898
899 96 data->callback = callback;
900 96 fpi_ssm_set_data (self->cmd_ssm, data, (GDestroyNotify) fp_cmd_ssm_done_data_free);
901
902 96 fpi_ssm_start (self->cmd_ssm, fp_cmd_ssm_done);
903 96 }
904
905 static void
906 4 fp_verify_ssm_done (FpiSsm *ssm, FpDevice *dev, GError *error)
907 {
908 4 FpiDeviceRealtek *self = FPI_DEVICE_REALTEK (dev);
909
910 4 fp_info ("Verify complete!");
911
912
1/2
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 4 times.
4 if (fpi_ssm_get_error (ssm))
913 error = fpi_ssm_get_error (ssm);
914
915
1/4
✗ Branch 6 → 7 not taken.
✓ Branch 6 → 13 taken 4 times.
✗ Branch 8 → 9 not taken.
✗ Branch 8 → 13 not taken.
4 if (error && error->domain == FP_DEVICE_RETRY)
916 {
917 if (fpi_device_get_current_action (dev) == FPI_DEVICE_ACTION_VERIFY)
918 fpi_device_verify_report (dev, FPI_MATCH_ERROR, NULL, g_steal_pointer (&error));
919 else
920 fpi_device_identify_report (dev, NULL, NULL, g_steal_pointer (&error));
921 }
922
923
2/2
✓ Branch 14 → 15 taken 2 times.
✓ Branch 14 → 16 taken 2 times.
4 if (fpi_device_get_current_action (dev) == FPI_DEVICE_ACTION_VERIFY)
924 2 fpi_device_verify_complete (dev, error);
925 else
926 2 fpi_device_identify_complete (dev, error);
927
928 4 self->task_ssm = NULL;
929 4 }
930
931 static void
932 2 fp_enroll_ssm_done (FpiSsm *ssm, FpDevice *dev, GError *error)
933 {
934 2 FpiDeviceRealtek *self = FPI_DEVICE_REALTEK (dev);
935 2 FpPrint *print = NULL;
936
937 2 fp_info ("Enrollment complete!");
938
939
1/2
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 2 times.
2 if (fpi_ssm_get_error (ssm))
940 error = fpi_ssm_get_error (ssm);
941
942
1/2
✗ Branch 6 → 7 not taken.
✓ Branch 6 → 8 taken 2 times.
2 if (error)
943 {
944 fpi_device_enroll_complete (dev, NULL, error);
945 self->task_ssm = NULL;
946 return;
947 }
948
949 2 fpi_device_get_enroll_data (FP_DEVICE (self), &print);
950 2 fpi_device_enroll_complete (FP_DEVICE (self), g_object_ref (print), NULL);
951 2 self->task_ssm = NULL;
952 }
953
954 static void
955 2 fp_init_ssm_done (FpiSsm *ssm, FpDevice *dev, GError *error)
956 {
957 2 FpiDeviceRealtek *self = FPI_DEVICE_REALTEK (dev);
958
959 2 fp_info ("Init complete!");
960
961
1/2
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 2 times.
2 if (fpi_ssm_get_error (ssm))
962 error = fpi_ssm_get_error (ssm);
963
964 2 fpi_device_open_complete (dev, error);
965 2 self->task_ssm = NULL;
966 2 }
967
968 static void
969 2 fp_delete_ssm_done (FpiSsm *ssm, FpDevice *dev, GError *error)
970 {
971 2 FpiDeviceRealtek *self = FPI_DEVICE_REALTEK (dev);
972
973 2 fp_info ("Delete print complete!");
974
975
1/2
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 2 times.
2 if (fpi_ssm_get_error (ssm))
976 error = fpi_ssm_get_error (ssm);
977
978 2 fpi_device_delete_complete (dev, error);
979 2 self->task_ssm = NULL;
980 2 }
981
982 static void
983 22 fp_verify_sm_run_state (FpiSsm *ssm, FpDevice *device)
984 {
985 22 FpiDeviceRealtek *self = FPI_DEVICE_REALTEK (device);
986 22 guint8 *cmd_buf = NULL;
987
988
6/8
✓ Branch 3 → 4 taken 4 times.
✓ Branch 3 → 10 taken 4 times.
✓ Branch 3 → 13 taken 4 times.
✓ Branch 3 → 15 taken 4 times.
✓ Branch 3 → 17 taken 4 times.
✓ Branch 3 → 19 taken 2 times.
✗ Branch 3 → 21 not taken.
✗ Branch 3 → 23 not taken.
22 switch (fpi_ssm_get_cur_state (ssm))
989 {
990 4 case FP_RTK_VERIFY_GET_TEMPLATE:
991
1/2
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 8 taken 4 times.
4 if (self->template_num <= 0)
992 {
993 fpi_ssm_mark_failed (ssm,
994 fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
995 "No templates enrolled"));
996 break;
997 }
998
999 4 co_get_template.data_len[0] = GET_LEN_L (self->template_len * self->template_num);
1000 4 co_get_template.data_len[1] = GET_LEN_H (self->template_len * self->template_num);
1001 4 cmd_buf = (guint8 *) &co_get_template;
1002 4 rtk_sensor_bulk_cmd (self, cmd_buf, NULL, FP_RTK_MSG_DEFAULT, 0, fp_verify_get_template_cb);
1003 4 break;
1004
1005 4 case FP_RTK_VERIFY_CAPTURE:
1006 4 fpi_device_report_finger_status_changes (device,
1007 FP_FINGER_STATUS_NEEDED,
1008 FP_FINGER_STATUS_NONE);
1009
1010 4 cmd_buf = (guint8 *) &co_start_capture;
1011 4 rtk_sensor_bulk_cmd (self, cmd_buf, NULL, FP_RTK_MSG_DEFAULT, 0, fp_task_ssm_generic_cb);
1012 4 break;
1013
1014 4 case FP_RTK_VERIFY_FINISH_CAPTURE:
1015 4 cmd_buf = (guint8 *) &co_finish_capture;
1016 4 rtk_sensor_bulk_cmd (self, cmd_buf, NULL, FP_RTK_MSG_DEFAULT, 0, fp_finish_capture_cb);
1017 4 break;
1018
1019 4 case FP_RTK_VERIFY_ACCEPT_SAMPLE:
1020 4 co_accept_sample.param[0] = self->fp_purpose;
1021 4 cmd_buf = (guint8 *) &co_accept_sample;
1022 4 rtk_sensor_bulk_cmd (self, cmd_buf, NULL, FP_RTK_MSG_NO_STATUS, 0, fp_accept_sample_cb);
1023 4 break;
1024
1025 4 case FP_RTK_VERIFY_INDENTIFY_FEATURE:
1026 4 cmd_buf = (guint8 *) &nor_identify_feature;
1027 4 rtk_sensor_bulk_cmd (self, cmd_buf, NULL, FP_RTK_MSG_NO_STATUS, 0, fp_identify_feature_cb);
1028 4 break;
1029
1030 2 case FP_RTK_VERIFY_UPDATE_TEMPLATE:
1031 2 cmd_buf = (guint8 *) &co_update_template;
1032 2 rtk_sensor_bulk_cmd (self, cmd_buf, NULL, FP_RTK_MSG_DEFAULT, 0, fp_update_template_cb);
1033 2 break;
1034
1035 case FP_RTK_VERIFY_CANCEL_CAPTURE:
1036 co_cancel_capture.param[0] = self->fp_purpose;
1037 cmd_buf = (guint8 *) &co_cancel_capture;
1038 rtk_sensor_bulk_cmd (self, cmd_buf, NULL, FP_RTK_MSG_DEFAULT, 0, fp_task_ssm_generic_cb);
1039 break;
1040 }
1041 22 }
1042
1043 static void
1044 62 fp_enroll_sm_run_state (FpiSsm *ssm, FpDevice *device)
1045 {
1046 124 g_autofree gchar *user_id = NULL;
1047 62 g_autofree guint8 *payload = NULL;
1048 62 FpiDeviceRealtek *self = FPI_DEVICE_REALTEK (device);
1049 62 FpPrint *print = NULL;
1050 62 guint8 *cmd_buf = NULL;
1051 62 GVariant *uid = NULL;
1052 62 GVariant *data = NULL;
1053 62 gsize user_id_len;
1054 62 guint finger;
1055
1056
7/9
✓ Branch 3 → 4 taken 2 times.
✓ Branch 3 → 10 taken 2 times.
✓ Branch 3 → 12 taken 18 times.
✓ Branch 3 → 15 taken 18 times.
✓ Branch 3 → 17 taken 18 times.
✓ Branch 3 → 19 taken 2 times.
✓ Branch 3 → 21 taken 2 times.
✗ Branch 3 → 33 not taken.
✗ Branch 3 → 34 not taken.
62 switch (fpi_ssm_get_cur_state (ssm))
1057 {
1058 2 case FP_RTK_ENROLL_GET_TEMPLATE:
1059
1/2
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 8 taken 2 times.
2 if (self->template_num <= 0)
1060 {
1061 fpi_ssm_mark_failed (ssm,
1062 fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
1063 "No templates enrolled"));
1064 break;
1065 }
1066
1067 2 co_get_template.data_len[0] = GET_LEN_L (self->template_len * self->template_num);
1068 2 co_get_template.data_len[1] = GET_LEN_H (self->template_len * self->template_num);
1069
1070 2 cmd_buf = (guint8 *) &co_get_template;
1071 2 rtk_sensor_bulk_cmd (self, cmd_buf, NULL, FP_RTK_MSG_DEFAULT, 0, fp_enroll_get_template_cb);
1072 2 break;
1073
1074 2 case FP_RTK_ENROLL_BEGIN_POS:
1075 2 nor_enroll_begin.param[0] = self->pos_index;
1076 2 cmd_buf = (guint8 *) &nor_enroll_begin;
1077 2 rtk_sensor_bulk_cmd (self, cmd_buf, NULL, FP_RTK_MSG_DEFAULT, 0, fp_task_ssm_generic_cb);
1078 2 break;
1079
1080 18 case FP_RTK_ENROLL_CAPTURE:
1081 18 fpi_device_report_finger_status_changes (device,
1082 FP_FINGER_STATUS_NEEDED,
1083 FP_FINGER_STATUS_NONE);
1084
1085 18 cmd_buf = (guint8 *) &co_start_capture;
1086 18 rtk_sensor_bulk_cmd (self, cmd_buf, NULL, FP_RTK_MSG_DEFAULT, 0, fp_task_ssm_generic_cb);
1087 18 break;
1088
1089 18 case FP_RTK_ENROLL_FINISH_CAPTURE:
1090 18 cmd_buf = (guint8 *) &co_finish_capture;
1091 18 rtk_sensor_bulk_cmd (self, cmd_buf, NULL, FP_RTK_MSG_DEFAULT, 0, fp_finish_capture_cb);
1092 18 break;
1093
1094 18 case FP_RTK_ENROLL_ACCEPT_SAMPLE:
1095 18 co_accept_sample.param[0] = self->fp_purpose;
1096 18 cmd_buf = (guint8 *) &co_accept_sample;
1097 18 rtk_sensor_bulk_cmd (self, cmd_buf, NULL, FP_RTK_MSG_NO_STATUS, 0, fp_accept_sample_cb);
1098 18 break;
1099
1100 2 case FP_RTK_ENROLL_CHECK_DUPLICATE:
1101 2 cmd_buf = (guint8 *) &co_check_duplicate;
1102 2 rtk_sensor_bulk_cmd (self, cmd_buf, NULL, FP_RTK_MSG_NO_STATUS, 0, fp_check_duplicate_cb);
1103 2 break;
1104
1105 2 case FP_RTK_ENROLL_COMMIT:
1106 2 gchar *valid_uid = NULL;
1107 2 gint payload_len;
1108
1109 2 payload_len = UID_PAYLOAD_LEN_DEFAULT;
1110
1111 2 fpi_device_get_enroll_data (device, &print);
1112 2 user_id = fpi_print_generate_user_id (print);
1113 2 user_id_len = MIN (DEFAULT_UID_LEN, strlen (user_id));
1114
1115 2 payload = g_malloc0 (payload_len);
1116 2 memcpy (payload, user_id, user_id_len);
1117 2 valid_uid = (gchar *) payload;
1118
1119 2 finger = SUB_FINGER_01;
1120 2 uid = g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE,
1121 valid_uid,
1122 user_id_len,
1123 1);
1124 2 data = g_variant_new ("(y@ay)",
1125 finger,
1126 uid);
1127
1128 2 fpi_print_set_type (print, FPI_PRINT_RAW);
1129 2 fpi_print_set_device_stored (print, TRUE);
1130 2 g_object_set (print, "fpi-data", data, NULL);
1131 2 g_object_set (print, "description", valid_uid, NULL);
1132
1133 2 g_debug ("user_id: %s, finger: 0x%x", user_id, finger);
1134
1135 2 nor_enroll_commit.param[0] = SUB_FINGER_01;
1136 2 nor_enroll_commit.data_len[0] = GET_LEN_L (payload_len);
1137 2 nor_enroll_commit.data_len[1] = GET_LEN_H (payload_len);
1138
1139 2 cmd_buf = (guint8 *) &nor_enroll_commit;
1140 2 rtk_sensor_bulk_cmd (self, cmd_buf, g_steal_pointer (&payload),
1141 FP_RTK_MSG_DEFAULT, 1, fp_enroll_commit_cb);
1142 2 break;
1143
1144 case FP_RTK_ENROLL_CANCEL_CAPTURE:
1145 co_cancel_capture.param[0] = self->fp_purpose;
1146 cmd_buf = (guint8 *) &co_cancel_capture;
1147 rtk_sensor_bulk_cmd (self, cmd_buf, NULL, FP_RTK_MSG_DEFAULT, 0, fp_task_ssm_generic_cb);
1148 }
1149 62 }
1150
1151 static void
1152 6 fp_init_sm_run_state (FpiSsm *ssm, FpDevice *device)
1153 {
1154 6 FpiDeviceRealtek *self = FPI_DEVICE_REALTEK (device);
1155 6 guint8 *cmd_buf = NULL;
1156
1157
3/4
✓ Branch 3 → 4 taken 2 times.
✓ Branch 3 → 6 taken 2 times.
✓ Branch 3 → 8 taken 2 times.
✗ Branch 3 → 10 not taken.
6 switch (fpi_ssm_get_cur_state (ssm))
1158 {
1159 2 case FP_RTK_INIT_GET_DEVICE_INFO:
1160 2 rtk_send_ctrl_cmd (self, &get_device_info, NULL, fp_get_device_info_cb);
1161 2 break;
1162
1163 2 case FP_RTK_INIT_SELECT_OS:
1164 2 co_select_system.param[0] = 0x01;
1165 2 cmd_buf = (guint8 *) &co_select_system;
1166 2 rtk_sensor_bulk_cmd (self, cmd_buf, NULL, FP_RTK_MSG_DEFAULT, 0, fp_task_ssm_generic_cb);
1167 2 break;
1168
1169 2 case FP_RTK_INIT_GET_ENROLL_NUM:
1170 2 cmd_buf = (guint8 *) &co_get_enroll_num;
1171 2 rtk_sensor_bulk_cmd (self, cmd_buf, NULL, FP_RTK_MSG_DEFAULT, 0, fp_get_enroll_num_cb);
1172 2 break;
1173 }
1174 6 }
1175
1176 static void
1177 4 fp_delete_sm_run_state (FpiSsm *ssm, FpDevice *device)
1178 {
1179 4 FpiDeviceRealtek *self = FPI_DEVICE_REALTEK (device);
1180 4 guint8 *cmd_buf = NULL;
1181
1182
2/3
✓ Branch 3 → 4 taken 2 times.
✓ Branch 3 → 10 taken 2 times.
✗ Branch 3 → 12 not taken.
4 switch (fpi_ssm_get_cur_state (ssm))
1183 {
1184 2 case FP_RTK_DELETE_GET_POS:
1185
1/2
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 8 taken 2 times.
2 if (self->template_num <= 0)
1186 {
1187 fpi_ssm_mark_failed (ssm,
1188 fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
1189 "No templates enrolled"));
1190 break;
1191 }
1192
1193 2 co_get_template.data_len[0] = GET_LEN_L (self->template_len * self->template_num);
1194 2 co_get_template.data_len[1] = GET_LEN_H (self->template_len * self->template_num);
1195
1196 2 cmd_buf = (guint8 *) &co_get_template;
1197 2 rtk_sensor_bulk_cmd (self, cmd_buf, NULL, FP_RTK_MSG_DEFAULT, 0, fp_get_delete_pos_cb);
1198 2 break;
1199
1200 2 case FP_RTK_DELETE_PRINT:
1201 2 co_delete_record.param[0] = self->pos_index;
1202 2 cmd_buf = (guint8 *) &co_delete_record;
1203 2 rtk_sensor_bulk_cmd (self, cmd_buf, NULL, FP_RTK_MSG_DEFAULT, 0, fp_task_ssm_generic_cb);
1204 2 break;
1205 }
1206 4 }
1207
1208
1209 static void
1210 4 identify_verify (FpDevice *device)
1211 {
1212 4 FpiDeviceRealtek *self = FPI_DEVICE_REALTEK (device);
1213 4 FpiDeviceAction current_action;
1214
1215 4 G_DEBUG_HERE ();
1216 4 current_action = fpi_device_get_current_action (device);
1217
1218
1/2
✗ Branch 5 → 6 not taken.
✓ Branch 5 → 7 taken 4 times.
4 g_assert (current_action == FPI_DEVICE_ACTION_VERIFY ||
1219 current_action == FPI_DEVICE_ACTION_IDENTIFY);
1220
1221 4 self->fp_purpose = FP_RTK_PURPOSE_IDENTIFY;
1222
1223
1/2
✓ Branch 7 → 8 taken 4 times.
✗ Branch 7 → 11 not taken.
4 g_assert (!self->task_ssm);
1224
1225 4 self->task_ssm = fpi_ssm_new_full (device,
1226 fp_verify_sm_run_state,
1227 FP_RTK_VERIFY_NUM_STATES,
1228 FP_RTK_VERIFY_CANCEL_CAPTURE,
1229 "Verify & Identify");
1230
1231 4 fpi_ssm_start (self->task_ssm, fp_verify_ssm_done);
1232 4 }
1233
1234 static void
1235 2 enroll (FpDevice *device)
1236 {
1237 2 FpiDeviceRealtek *self = FPI_DEVICE_REALTEK (device);
1238
1239 2 G_DEBUG_HERE ();
1240 2 self->enroll_stage = 0;
1241 2 self->fp_purpose = FP_RTK_PURPOSE_ENROLL;
1242
1243
1/2
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 2 times.
2 g_assert (!self->task_ssm);
1244
1245 2 self->task_ssm = fpi_ssm_new_full (device,
1246 fp_enroll_sm_run_state,
1247 FP_RTK_ENROLL_NUM_STATES,
1248 FP_RTK_ENROLL_CANCEL_CAPTURE,
1249 "Enroll");
1250
1251 2 fpi_ssm_start (self->task_ssm, fp_enroll_ssm_done);
1252 2 }
1253
1254 static void
1255 2 dev_probe (FpDevice *device)
1256 {
1257 2 GUsbDevice *usb_dev;
1258 2 GError *error = NULL;
1259 2 g_autofree gchar *product = NULL;
1260 2 FpiDeviceRealtek *self = FPI_DEVICE_REALTEK (device);
1261
1262 2 G_DEBUG_HERE ();
1263 /* Claim usb interface */
1264 2 usb_dev = fpi_device_get_usb_device (device);
1265
1/2
✗ Branch 6 → 7 not taken.
✓ Branch 6 → 8 taken 2 times.
2 if (!g_usb_device_open (usb_dev, &error))
1266 {
1267 fpi_device_probe_complete (device, NULL, NULL, error);
1268 return;
1269 }
1270
1271
1/2
✗ Branch 9 → 10 not taken.
✓ Branch 9 → 13 taken 2 times.
2 if (!g_usb_device_reset (usb_dev, &error))
1272 {
1273 g_usb_device_close (usb_dev, NULL);
1274 fpi_device_probe_complete (device, NULL, NULL, error);
1275 return;
1276 }
1277
1278
1/2
✗ Branch 14 → 15 not taken.
✓ Branch 14 → 18 taken 2 times.
2 if (!g_usb_device_claim_interface (usb_dev, 0, 0, &error))
1279 {
1280 g_usb_device_close (usb_dev, NULL);
1281 fpi_device_probe_complete (device, NULL, NULL, error);
1282 return;
1283 }
1284
1285 2 product = g_usb_device_get_string_descriptor (usb_dev,
1286 g_usb_device_get_product_index (usb_dev),
1287 &error);
1288
1289
1/2
✓ Branch 20 → 21 taken 2 times.
✗ Branch 20 → 22 not taken.
2 if (product)
1290 2 fp_dbg ("Device name: %s", product);
1291
1292 2 self->max_enroll_stage = MAX_ENROLL_SAMPLES;
1293 2 fpi_device_set_nr_enroll_stages (device, self->max_enroll_stage);
1294
1295 2 g_usb_device_release_interface (fpi_device_get_usb_device (FP_DEVICE (device)), 0, 0, NULL);
1296 2 g_usb_device_close (usb_dev, NULL);
1297
1298 2 fpi_device_probe_complete (device, NULL, product, error);
1299 }
1300
1301 static void
1302 2 dev_init (FpDevice *device)
1303 {
1304 2 FpiDeviceRealtek *self = FPI_DEVICE_REALTEK (device);
1305 2 GError *error = NULL;
1306
1307 2 G_DEBUG_HERE ();
1308
1/2
✗ Branch 6 → 7 not taken.
✓ Branch 6 → 8 taken 2 times.
2 if (!g_usb_device_reset (fpi_device_get_usb_device (device), &error))
1309 {
1310 fpi_device_open_complete (FP_DEVICE (self), error);
1311 return;
1312 }
1313
1314 /* Claim usb interface */
1315
1/2
✗ Branch 10 → 11 not taken.
✓ Branch 10 → 13 taken 2 times.
2 if (!g_usb_device_claim_interface (fpi_device_get_usb_device (device), 0, 0, &error))
1316 {
1317 fpi_device_open_complete (FP_DEVICE (self), error);
1318 return;
1319 }
1320
1321
1/2
✗ Branch 13 → 14 not taken.
✓ Branch 13 → 15 taken 2 times.
2 g_assert (!self->task_ssm);
1322
1323 2 self->task_ssm = fpi_ssm_new_full (device,
1324 fp_init_sm_run_state,
1325 FP_RTK_INIT_NUM_STATES,
1326 FP_RTK_INIT_NUM_STATES,
1327 "Init");
1328
1329 2 fpi_ssm_start (self->task_ssm, fp_init_ssm_done);
1330 }
1331
1332 static void
1333 2 dev_exit (FpDevice *device)
1334 {
1335 2 FpiDeviceRealtek *self = FPI_DEVICE_REALTEK (device);
1336
1337 4 g_autoptr(GError) release_error = NULL;
1338
1339 2 G_DEBUG_HERE ();
1340
1341 2 g_usb_device_release_interface (fpi_device_get_usb_device (FP_DEVICE (self)), 0, 0, &release_error);
1342
1343
1/2
✗ Branch 7 → 8 not taken.
✓ Branch 7 → 9 taken 2 times.
2 fpi_device_close_complete (device, release_error);
1344 2 }
1345
1346 static void
1347 2 delete_print (FpDevice *device)
1348 {
1349 2 FpiDeviceRealtek *self = FPI_DEVICE_REALTEK (device);
1350
1351 2 G_DEBUG_HERE ();
1352
1353
1/2
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 2 times.
2 g_assert (!self->task_ssm);
1354
1355 2 self->task_ssm = fpi_ssm_new_full (device,
1356 fp_delete_sm_run_state,
1357 FP_RTK_DELETE_NUM_STATES,
1358 FP_RTK_DELETE_NUM_STATES,
1359 "Delete print");
1360
1361 2 fpi_ssm_start (self->task_ssm, fp_delete_ssm_done);
1362 2 }
1363
1364 static void
1365 2 clear_storage (FpDevice *device)
1366 {
1367 2 FpiDeviceRealtek *self = FPI_DEVICE_REALTEK (device);
1368 2 guint8 *cmd_buf = NULL;
1369
1370 2 G_DEBUG_HERE ();
1371 2 co_delete_record.param[0] = 0xff;
1372 2 cmd_buf = (guint8 *) &co_delete_record;
1373 2 rtk_sensor_bulk_cmd (self, cmd_buf, NULL, FP_RTK_MSG_DEFAULT, 0, fp_clear_storage_cb);
1374 2 }
1375
1376 static void
1377 2 list_print (FpDevice *device)
1378 {
1379 2 FpiDeviceRealtek *self = FPI_DEVICE_REALTEK (device);
1380 2 guint8 *cmd_buf = NULL;
1381
1382 2 G_DEBUG_HERE ();
1383
1384
1/2
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 8 taken 2 times.
2 if (self->template_num < 0)
1385 {
1386 fpi_device_list_complete (device, NULL,
1387 fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
1388 "Get template number failed!"));
1389 return;
1390 }
1391
1392
1/2
✗ Branch 8 → 9 not taken.
✓ Branch 8 → 11 taken 2 times.
2 if (self->template_num == 0)
1393 {
1394 g_autoptr(GPtrArray) list_result = g_ptr_array_new_with_free_func (g_object_unref);
1395 fpi_device_list_complete (device, g_steal_pointer (&list_result), NULL);
1396 return;
1397 }
1398
1399 2 co_get_template.data_len[0] = GET_LEN_L (self->template_len * self->template_num);
1400 2 co_get_template.data_len[1] = GET_LEN_H (self->template_len * self->template_num);
1401
1402 2 cmd_buf = (guint8 *) &co_get_template;
1403 2 rtk_sensor_bulk_cmd (self, cmd_buf, NULL, FP_RTK_MSG_DEFAULT, 1, fp_list_cb);
1404 }
1405
1406 static void
1407 2 fpi_device_realtek_init (FpiDeviceRealtek *self)
1408 {
1409 2 }
1410
1411 static void
1412 125 fpi_device_realtek_class_init (FpiDeviceRealtekClass *klass)
1413 {
1414 125 FpDeviceClass *dev_class = FP_DEVICE_CLASS (klass);
1415
1416 125 dev_class->id = FP_COMPONENT;
1417 125 dev_class->full_name = "Realtek MOC Fingerprint Sensor";
1418
1419 125 dev_class->type = FP_DEVICE_TYPE_USB;
1420 125 dev_class->scan_type = FP_SCAN_TYPE_PRESS;
1421 125 dev_class->id_table = id_table;
1422 125 dev_class->nr_enroll_stages = MAX_ENROLL_SAMPLES;
1423 125 dev_class->temp_hot_seconds = -1;
1424
1425 125 dev_class->open = dev_init;
1426 125 dev_class->close = dev_exit;
1427 125 dev_class->probe = dev_probe;
1428 125 dev_class->verify = identify_verify;
1429 125 dev_class->identify = identify_verify;
1430 125 dev_class->enroll = enroll;
1431 125 dev_class->delete = delete_print;
1432 125 dev_class->clear_storage = clear_storage;
1433 125 dev_class->list = list_print;
1434
1435 125 fpi_device_class_auto_initialize_features (dev_class);
1436 125 }
1437