GCC Code Coverage Report


Directory: ./
File: libfprint/drivers/realtek/realtek.c
Date: 2024-09-16 14:36:32
Exec Total Coverage
Lines: 552 663 83.3%
Functions: 45 45 100.0%
Branches: 140 246 56.9%

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