GCC Code Coverage Report


Directory: ./
File: libfprint/drivers/realtek/realtek.c
Date: 2025-12-06 02:24:24
Exec Total Coverage
Lines: 551 662 83.2%
Functions: 45 45 100.0%
Branches: 139 245 56.7%

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