GCC Code Coverage Report


Directory: ./
File: libfprint/drivers/focaltech_moc/focaltech_moc.c
Date: 2025-12-06 02:24:24
Exec Total Coverage
Lines: 701 800 87.6%
Functions: 48 48 100.0%
Branches: 147 248 59.3%

Line Branch Exec Source
1 /*
2 * Copyright (C) 2022 FocalTech Electronics Inc
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18
19 #include "focaltech_moc.h"
20
21 #include <ctype.h>
22
23 #define FP_COMPONENT "focaltech_moc"
24
25 #include "drivers_api.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 (FpiDeviceFocaltechMoc, fpi_device_focaltech_moc, FP_TYPE_DEVICE)
28
29 static const FpIdEntry id_table[] = {
30 { .vid = 0x2808, .pid = 0x9e48, },
31 { .vid = 0x2808, .pid = 0xd979, },
32 { .vid = 0x2808, .pid = 0xa27a, },
33 { .vid = 0x2808, .pid = 0xa959, },
34 { .vid = 0x2808, .pid = 0xa99a, },
35 { .vid = 0x2808, .pid = 0xa57a, },
36 { .vid = 0x2808, .pid = 0xa78a, },
37 { .vid = 0x2808, .pid = 0x1579, },
38 { .vid = 0, .pid = 0, .driver_data = 0 }, /* terminating entry */
39 };
40
41 typedef void (*SynCmdMsgCallback) (FpiDeviceFocaltechMoc *self,
42 uint8_t *buffer_in,
43 gsize length_in,
44 GError *error);
45
46 typedef struct
47 {
48 SynCmdMsgCallback callback;
49 } CommandData;
50
51 typedef struct
52 {
53 uint8_t h;
54 uint8_t l;
55 } FpCmdLen;
56
57 typedef struct
58 {
59 uint8_t magic;
60 FpCmdLen len;
61 } FpCmdHeader;
62
63 typedef struct
64 {
65 FpCmdHeader header;
66 uint8_t code;
67 uint8_t payload[0];
68 } FpCmd;
69
70 typedef struct
71 {
72 #if (G_BYTE_ORDER == G_LITTLE_ENDIAN)
73 uint8_t b0;
74 uint8_t b1;
75 #else
76 uint8_t b1;
77 uint8_t b0;
78 #endif
79 } u16_bytes_t;
80
81 typedef union
82 {
83 u16_bytes_t s;
84 uint16_t v;
85 } u_u16_bytes_t;
86
87 static inline uint16_t
88 82 get_u16_from_u8_lh (uint8_t l, uint8_t h)
89 {
90 82 u_u16_bytes_t u_u16_bytes;
91
92 82 u_u16_bytes.v = 0;
93 82 u_u16_bytes.s.b0 = l;
94 82 u_u16_bytes.s.b1 = h;
95
96 82 return u_u16_bytes.v;
97 }
98
99 static inline uint8_t
100 82 get_u8_l_from_u16 (uint16_t v)
101 {
102 82 u_u16_bytes_t u_u16_bytes;
103
104 82 u_u16_bytes.v = v;
105
106 82 return u_u16_bytes.s.b0;
107 }
108
109 static inline uint8_t
110 82 get_u8_h_from_u16 (uint16_t v)
111 {
112 82 u_u16_bytes_t u_u16_bytes;
113
114 82 u_u16_bytes.v = v;
115
116 82 return u_u16_bytes.s.b1;
117 }
118
119 static uint8_t
120 164 fp_cmd_bcc (uint8_t *data, uint16_t len)
121 {
122 164 int i;
123 164 uint8_t bcc = 0;
124
125
4/4
✓ Branch 0 (9→8) taken 3570 times.
✓ Branch 1 (9→10) taken 82 times.
✓ Branch 2 (7→6) taken 1810 times.
✓ Branch 3 (7→8) taken 82 times.
5544 for (i = 0; i < len; i++)
126 5380 bcc ^= data[i];
127
128 164 return bcc;
129 }
130
131 static uint8_t *
132 82 focaltech_moc_compose_cmd (uint8_t cmd, const uint8_t *data, uint16_t len)
133 {
134 164 g_autofree uint8_t *cmd_buf = NULL;
135 82 FpCmd *fp_cmd = NULL;
136 82 uint8_t *bcc = NULL;
137 82 uint16_t header_len = len + sizeof (*bcc);
138
139 82 cmd_buf = g_new0 (uint8_t, sizeof (FpCmd) + header_len);
140
141 82 fp_cmd = (FpCmd *) cmd_buf;
142
143 82 fp_cmd->header.magic = 0x02;
144 82 fp_cmd->header.len.l = get_u8_l_from_u16 (header_len);
145 82 fp_cmd->header.len.h = get_u8_h_from_u16 (header_len);
146 82 fp_cmd->code = cmd;
147
148
2/2
✓ Branch 0 (3→4) taken 62 times.
✓ Branch 1 (3→5) taken 20 times.
82 if (data != NULL)
149 62 memcpy (fp_cmd->payload, data, len);
150
151 82 bcc = fp_cmd->payload + len;
152 82 *bcc = fp_cmd_bcc ((uint8_t *) &fp_cmd->header.len, bcc - (uint8_t *) &fp_cmd->header.len);
153
154 82 return g_steal_pointer (&cmd_buf);
155 }
156
157 static int
158 82 focaltech_moc_check_cmd (uint8_t *response_buf, uint16_t len)
159 {
160 82 int ret = -1;
161 82 FpCmd *fp_cmd = NULL;
162 82 uint8_t *bcc = NULL;
163 82 uint16_t header_len;
164 82 uint16_t data_len;
165
166 82 fp_cmd = (FpCmd *) response_buf;
167
168
1/2
✗ Branch 0 (2→3) not taken.
✓ Branch 1 (2→4) taken 82 times.
82 if (len < sizeof (FpCmd) + sizeof (*bcc))
169 return ret;
170
171
1/2
✗ Branch 0 (4→3) not taken.
✓ Branch 1 (4→5) taken 82 times.
82 if (fp_cmd->header.magic != 0x02)
172 return ret;
173
174 82 header_len = get_u16_from_u8_lh (fp_cmd->header.len.l, fp_cmd->header.len.h);
175
176
1/2
✗ Branch 0 (5→3) not taken.
✓ Branch 1 (5→6) taken 82 times.
82 if (header_len < sizeof (*bcc))
177 return ret;
178
179
1/2
✗ Branch 0 (6→3) not taken.
✓ Branch 1 (6→7) taken 82 times.
82 if ((sizeof (FpCmd) + header_len) > len)
180 return ret;
181
182 82 data_len = header_len - sizeof (*bcc);
183
184 82 bcc = fp_cmd->payload + data_len;
185
186 82 if (fp_cmd_bcc ((uint8_t *) &fp_cmd->header.len,
187
1/2
✗ Branch 0 (10→3) not taken.
✓ Branch 1 (10→11) taken 82 times.
82 bcc - (uint8_t *) &fp_cmd->header.len) != *bcc)
188 return ret;
189
190 82 ret = 0;
191 return ret;
192 }
193
194 static void
195 82 fp_cmd_receive_cb (FpiUsbTransfer *transfer,
196 FpDevice *device,
197 gpointer userdata,
198 GError *error)
199 {
200 82 FpiDeviceFocaltechMoc *self = FPI_DEVICE_FOCALTECH_MOC (device);
201 82 CommandData *data = userdata;
202 82 int ssm_state = 0;
203
204
1/2
✗ Branch 0 (2→3) not taken.
✓ Branch 1 (2→5) taken 82 times.
82 if (error)
205 {
206 fpi_ssm_mark_failed (transfer->ssm, g_steal_pointer (&error));
207 return;
208 }
209
210
1/2
✗ Branch 0 (5→6) not taken.
✓ Branch 1 (5→9) taken 82 times.
82 if (data == NULL)
211 {
212 fpi_ssm_mark_failed (transfer->ssm,
213 fpi_device_error_new (FP_DEVICE_ERROR_GENERAL));
214 return;
215 }
216
217 82 ssm_state = fpi_ssm_get_cur_state (transfer->ssm);
218
219 /* skip zero length package */
220
1/2
✗ Branch 0 (10→11) not taken.
✓ Branch 1 (10→13) taken 82 times.
82 if (transfer->actual_length == 0)
221 {
222 fpi_ssm_jump_to_state (transfer->ssm, ssm_state);
223 return;
224 }
225
226
1/2
✗ Branch 0 (13→14) not taken.
✓ Branch 1 (13→17) taken 82 times.
82 if (focaltech_moc_check_cmd (transfer->buffer, transfer->actual_length) != 0)
227 {
228 fpi_ssm_mark_failed (transfer->ssm,
229 fpi_device_error_new (FP_DEVICE_ERROR_GENERAL));
230 return;
231 }
232
233
1/2
✓ Branch 0 (17→18) taken 82 times.
✗ Branch 1 (17→19) not taken.
82 if (data->callback)
234 82 data->callback (self, transfer->buffer, transfer->actual_length, NULL);
235
236 82 fpi_ssm_mark_completed (transfer->ssm);
237 }
238
239 typedef enum {
240 FOCALTECH_CMD_SEND = 0,
241 FOCALTECH_CMD_GET,
242 FOCALTECH_CMD_NUM_STATES,
243 } FocaltechCmdState;
244
245 static void
246 164 fp_cmd_run_state (FpiSsm *ssm,
247 FpDevice *device)
248 {
249 164 FpiUsbTransfer *transfer;
250 164 FpiDeviceFocaltechMoc *self = FPI_DEVICE_FOCALTECH_MOC (device);
251
252
2/3
✓ Branch 0 (3→4) taken 82 times.
✓ Branch 1 (3→7) taken 82 times.
✗ Branch 2 (3→22) not taken.
164 switch (fpi_ssm_get_cur_state (ssm))
253 {
254 82 case FOCALTECH_CMD_SEND:
255
1/2
✓ Branch 0 (4→5) taken 82 times.
✗ Branch 1 (4→6) not taken.
82 if (self->cmd_transfer)
256 {
257 82 self->cmd_transfer->ssm = ssm;
258 82 fpi_usb_transfer_submit (g_steal_pointer (&self->cmd_transfer),
259 FOCALTECH_MOC_CMD_TIMEOUT,
260 NULL,
261 fpi_ssm_usb_transfer_cb,
262 NULL);
263 }
264 else
265 {
266 fpi_ssm_next_state (ssm);
267 }
268
269 break;
270
271 82 case FOCALTECH_CMD_GET:
272
1/2
✗ Branch 0 (7→8) not taken.
✓ Branch 1 (7→13) taken 82 times.
82 if (self->cmd_len_in == 0)
273 {
274 CommandData *data = fpi_ssm_get_data (ssm);
275
276 if (data->callback)
277 data->callback (self, NULL, 0, 0);
278
279 fpi_ssm_mark_completed (ssm);
280 return;
281 }
282
283 82 transfer = fpi_usb_transfer_new (device);
284 82 transfer->ssm = ssm;
285 82 fpi_usb_transfer_fill_bulk (transfer, self->bulk_in_ep, self->cmd_len_in);
286 82 fpi_usb_transfer_submit (transfer,
287
1/2
✗ Branch 0 (18→19) not taken.
✓ Branch 1 (18→20) taken 82 times.
82 self->cmd_cancelable ? 0 : FOCALTECH_MOC_CMD_TIMEOUT,
288
1/2
✓ Branch 0 (16→17) taken 82 times.
✗ Branch 1 (16→18) not taken.
82 self->cmd_cancelable ? fpi_device_get_cancellable (device) : NULL,
289 fp_cmd_receive_cb,
290 fpi_ssm_get_data (ssm));
291 82 break;
292
293 }
294
295 }
296
297 static void
298 82 fp_cmd_ssm_done (FpiSsm *ssm, FpDevice *device, GError *error)
299 {
300 164 g_autoptr(GError) local_error = error;
301 82 FpiDeviceFocaltechMoc *self = FPI_DEVICE_FOCALTECH_MOC (device);
302 82 CommandData *data = fpi_ssm_get_data (ssm);
303
304 82 self->cmd_ssm = NULL;
305
306
1/4
✗ Branch 0 (3→4) not taken.
✓ Branch 1 (3→7) taken 82 times.
✗ Branch 2 (4→5) not taken.
✗ Branch 3 (4→6) not taken.
82 if (local_error && data->callback)
307 data->callback (self, NULL, 0, g_steal_pointer (&local_error));
308 82 }
309
310 static void
311 82 fp_cmd_ssm_done_data_free (CommandData *data)
312 {
313 82 g_free (data);
314 82 }
315
316 static void
317 82 focaltech_moc_get_cmd (FpDevice *device, guint8 *buffer_out,
318 gsize length_out, gsize length_in,
319 gboolean can_be_cancelled,
320 SynCmdMsgCallback callback)
321 {
322 82 FpiDeviceFocaltechMoc *self = FPI_DEVICE_FOCALTECH_MOC (device);
323
324 164 g_autoptr(FpiUsbTransfer) transfer = NULL;
325 82 CommandData *data = g_new0 (CommandData, 1);
326
327 82 transfer = fpi_usb_transfer_new (device);
328 82 transfer->short_is_error = TRUE;
329 82 fpi_usb_transfer_fill_bulk_full (transfer, self->bulk_out_ep, buffer_out,
330 length_out, g_free);
331 82 data->callback = callback;
332
333 82 self->cmd_transfer = g_steal_pointer (&transfer);
334 82 self->cmd_len_in = length_in + 1;
335 82 self->cmd_cancelable = can_be_cancelled;
336
337 82 self->cmd_ssm = fpi_ssm_new (FP_DEVICE (self),
338 fp_cmd_run_state,
339 FOCALTECH_CMD_NUM_STATES);
340
341 82 fpi_ssm_set_data (self->cmd_ssm, data, (GDestroyNotify) fp_cmd_ssm_done_data_free);
342
343 82 fpi_ssm_start (self->cmd_ssm, fp_cmd_ssm_done);
344 82 }
345
346 struct UserId
347 {
348 uint8_t uid[32];
349 };
350
351 static void
352 5 fprint_set_uid (FpPrint *print, uint8_t *uid, size_t size)
353 {
354 5 GVariant *var_uid;
355 5 GVariant *var_data;
356
357 5 var_uid = g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE, uid, size, 1);
358 5 var_data = g_variant_new ("(@ay)", var_uid);
359 5 fpi_print_set_type (print, FPI_PRINT_RAW);
360 5 fpi_print_set_device_stored (print, TRUE);
361 5 g_object_set (print, "fpi-data", var_data, NULL);
362 5 }
363
364 enum enroll_states {
365 ENROLL_RSP_RETRY,
366 ENROLL_RSP_ENROLL_REPORT,
367 ENROLL_RSP_ENROLL_OK,
368 ENROLL_RSP_ENROLL_CANCEL_REPORT,
369 };
370
371 static void
372 12 enroll_status_report (FpiDeviceFocaltechMoc *self, int enroll_status_id,
373 int data, GError *error)
374 {
375 12 FpDevice *device = FP_DEVICE (self);
376
377
3/5
✓ Branch 0 (2→3) taken 1 times.
✓ Branch 1 (2→6) taken 10 times.
✓ Branch 2 (2→8) taken 1 times.
✗ Branch 3 (2→13) not taken.
✗ Branch 4 (2→15) not taken.
12 switch (enroll_status_id)
378 {
379 1 case ENROLL_RSP_RETRY:
380 {
381 1 fpi_device_enroll_progress (device, self->num_frames, NULL,
382 fpi_device_retry_new (FP_DEVICE_RETRY_CENTER_FINGER));
383 1 break;
384 }
385
386 10 case ENROLL_RSP_ENROLL_REPORT:
387 {
388 10 fpi_device_enroll_progress (device, self->num_frames, NULL, NULL);
389 10 break;
390 }
391
392 1 case ENROLL_RSP_ENROLL_OK:
393 {
394 1 FpPrint *print = NULL;
395 1 fp_info ("Enrollment was successful!");
396 1 fpi_device_get_enroll_data (device, &print);
397 1 fpi_device_enroll_complete (device, g_object_ref (print), NULL);
398 1 break;
399 }
400
401 case ENROLL_RSP_ENROLL_CANCEL_REPORT:
402 {
403 fpi_device_enroll_complete (device, NULL,
404 fpi_device_error_new_msg (FP_DEVICE_ERROR_GENERAL,
405 "Enrollment failed (%d) (ENROLL_RSP_ENROLL_CANCEL_REPORT)",
406 data));
407 }
408 }
409 12 }
410
411 static void
412 5 task_ssm_done (FpiSsm *ssm, FpDevice *device, GError *error)
413 {
414 5 FpiDeviceFocaltechMoc *self = FPI_DEVICE_FOCALTECH_MOC (device);
415
416 5 self->num_frames = 0;
417 5 self->task_ssm = NULL;
418
419
1/2
✗ Branch 0 (2→3) not taken.
✓ Branch 1 (2→4) taken 5 times.
5 if (error)
420 fpi_device_action_error (device, g_steal_pointer (&error));
421 5 }
422
423 static const char *
424 2 get_g_usb_device_direction_des (GUsbDeviceDirection dir)
425 {
426 2 switch (dir)
427 {
428 case G_USB_DEVICE_DIRECTION_DEVICE_TO_HOST:
429 return "G_USB_DEVICE_DIRECTION_DEVICE_TO_HOST";
430
431 1 case G_USB_DEVICE_DIRECTION_HOST_TO_DEVICE:
432 1 return "G_USB_DEVICE_DIRECTION_HOST_TO_DEVICE";
433
434 default:
435 return "unknown";
436 }
437 }
438
439 static int
440 2 usb_claim_interface_probe (FpDevice *device, int claim, GError **error)
441 {
442 4 g_autoptr(GPtrArray) interfaces = NULL;
443 2 FpiDeviceFocaltechMoc *self = FPI_DEVICE_FOCALTECH_MOC (device);
444 2 int ret = -1;
445 2 int i;
446
447 2 interfaces = g_usb_device_get_interfaces (fpi_device_get_usb_device (device), error);
448
449
2/2
✓ Branch 0 (48→4) taken 2 times.
✓ Branch 1 (48→49) taken 2 times.
6 for (i = 0; i < interfaces->len; i++)
450 {
451 2 GUsbInterface *cur_iface = g_ptr_array_index (interfaces, i);
452 4 g_autoptr(GPtrArray) endpoints = g_usb_interface_get_endpoints (cur_iface);
453
454 2 fp_dbg ("class:%x, subclass:%x, protocol:%x",
455 g_usb_interface_get_class (cur_iface),
456 g_usb_interface_get_subclass (cur_iface),
457 g_usb_interface_get_protocol (cur_iface));
458
459
2/2
✓ Branch 0 (9→32) taken 1 times.
✓ Branch 1 (9→37) taken 1 times.
2 if (claim == 1)
460 {
461 int j;
462
463
2/2
✓ Branch 0 (32→10) taken 2 times.
✓ Branch 1 (32→33) taken 1 times.
3 for (j = 0; j < endpoints->len; j++)
464 {
465 2 GUsbEndpoint *endpoint = g_ptr_array_index (endpoints, j);
466 2 GBytes *bytes = g_usb_endpoint_get_extra (endpoint);
467
468 2 fp_dbg ("bytes size:%ld", g_bytes_get_size (bytes));
469
470
2/3
✓ Branch 0 (14→15) taken 1 times.
✗ Branch 1 (14→16) not taken.
✓ Branch 2 (14→17) taken 1 times.
3 fp_dbg ("kind:%x, max packet size:%d, poll interval:%d, refresh:%x, "
471 "sync address:%x, address:%x, number:%d, direction:%s",
472 g_usb_endpoint_get_kind (endpoint),
473 g_usb_endpoint_get_maximum_packet_size (endpoint),
474 g_usb_endpoint_get_polling_interval (endpoint),
475 g_usb_endpoint_get_refresh (endpoint),
476 g_usb_endpoint_get_synch_address (endpoint),
477 g_usb_endpoint_get_address (endpoint),
478 g_usb_endpoint_get_number (endpoint),
479 get_g_usb_device_direction_des (g_usb_endpoint_get_direction (endpoint)));
480
481
2/2
✓ Branch 0 (26→27) taken 1 times.
✓ Branch 1 (26→29) taken 1 times.
2 if (g_usb_endpoint_get_direction (endpoint) == G_USB_DEVICE_DIRECTION_DEVICE_TO_HOST)
482 1 self->bulk_in_ep = g_usb_endpoint_get_address (endpoint);
483 else
484 1 self->bulk_out_ep = g_usb_endpoint_get_address (endpoint);
485 }
486
487
1/2
✓ Branch 0 (36→41) taken 1 times.
✗ Branch 1 (36→44) not taken.
1 if (!g_usb_device_claim_interface (fpi_device_get_usb_device (device),
488 1 g_usb_interface_get_number (cur_iface),
489 0, error))
490 return ret;
491 }
492
1/2
✓ Branch 0 (40→41) taken 1 times.
✗ Branch 1 (40→44) not taken.
1 else if (!g_usb_device_release_interface (fpi_device_get_usb_device (device),
493 1 g_usb_interface_get_number (cur_iface),
494 0, error))
495 {
496 return ret;
497 }
498
499
500 }
501
502 2 ret = 0;
503
504 return ret;
505 }
506
507 static void
508 1 task_ssm_init_done (FpiSsm *ssm, FpDevice *device, GError *error)
509 {
510 1 FpiDeviceFocaltechMoc *self = FPI_DEVICE_FOCALTECH_MOC (device);
511
512
1/2
✗ Branch 0 (2→3) not taken.
✓ Branch 1 (2→4) taken 1 times.
1 if (error)
513 usb_claim_interface_probe (device, 0, &error);
514
515 1 fpi_device_open_complete (FP_DEVICE (self), g_steal_pointer (&error));
516 1 }
517
518 struct EnrollTimes
519 {
520 uint8_t enroll_times;
521 };
522
523 static void
524 1 focaltech_moc_get_enroll_times (FpiDeviceFocaltechMoc *self,
525 uint8_t *buffer_in,
526 gsize length_in,
527 GError *error)
528 {
529 1 FpCmd *fp_cmd = NULL;
530 1 struct EnrollTimes *enroll_times = NULL;
531
532
1/2
✗ Branch 0 (2→3) not taken.
✓ Branch 1 (2→5) taken 1 times.
1 if (error)
533 {
534 fpi_ssm_mark_failed (self->task_ssm, error);
535 return;
536 }
537
538 1 fp_cmd = (FpCmd *) buffer_in;
539 1 enroll_times = (struct EnrollTimes *) (fp_cmd + 1);
540
541
1/2
✗ Branch 0 (5→6) not taken.
✓ Branch 1 (5→8) taken 1 times.
1 if (fp_cmd->code != 0x04)
542 {
543 fpi_ssm_mark_failed (self->task_ssm,
544 fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
545 "Can't get response!!"));
546 }
547 else
548 {
549 1 fp_dbg ("focaltechmoc enroll_times: %d", enroll_times->enroll_times + 1);
550 1 fpi_device_set_nr_enroll_stages (FP_DEVICE (self), enroll_times->enroll_times + 1);
551 1 fpi_ssm_next_state (self->task_ssm);
552 }
553 }
554
555 static void
556 4 focaltech_moc_release_finger (FpiDeviceFocaltechMoc *self,
557 uint8_t *buffer_in,
558 gsize length_in,
559 GError *error)
560 {
561 4 FpCmd *fp_cmd = NULL;
562
563
1/2
✗ Branch 0 (2→3) not taken.
✓ Branch 1 (2→5) taken 4 times.
4 if (error)
564 {
565 fpi_ssm_mark_failed (self->task_ssm, error);
566 return;
567 }
568
569 4 fp_cmd = (FpCmd *) buffer_in;
570
571
1/2
✗ Branch 0 (5→6) not taken.
✓ Branch 1 (5→8) taken 4 times.
4 if (fp_cmd->code != 0x04)
572 {
573 fpi_ssm_mark_failed (self->task_ssm,
574 fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
575 "Can't get response!!"));
576 }
577 else
578 {
579 4 fpi_ssm_next_state (self->task_ssm);
580 }
581 }
582
583 enum dev_init_states {
584 DEV_INIT_GET_ENROLL_TIMES,
585 DEV_INIT_RELEASE_FINGER,
586 DEV_INIT_STATES,
587 };
588
589 static void
590 2 dev_init_handler (FpiSsm *ssm, FpDevice *device)
591 {
592 2 guint8 *cmd_buf = NULL;
593 2 uint16_t cmd_len = 0;
594 2 uint16_t resp_len = 0;
595
596
2/3
✓ Branch 0 (3→4) taken 1 times.
✓ Branch 1 (3→7) taken 1 times.
✗ Branch 2 (3→10) not taken.
2 switch (fpi_ssm_get_cur_state (ssm))
597 {
598 1 case DEV_INIT_GET_ENROLL_TIMES:
599 1 cmd_len = 0;
600 1 resp_len = sizeof (struct EnrollTimes);
601 1 cmd_buf = focaltech_moc_compose_cmd (0xa5, NULL, cmd_len);
602 1 focaltech_moc_get_cmd (device, cmd_buf,
603 sizeof (FpCmd) + cmd_len + sizeof (uint8_t),
604 sizeof (FpCmd) + resp_len + sizeof (uint8_t),
605 1,
606 focaltech_moc_get_enroll_times);
607 1 break;
608
609 1 case DEV_INIT_RELEASE_FINGER:
610 {
611 1 uint8_t d1 = 0x78;
612 1 cmd_len = sizeof (d1);
613 1 resp_len = 0;
614 1 cmd_buf = focaltech_moc_compose_cmd (0x82, &d1, cmd_len);
615 1 focaltech_moc_get_cmd (device, cmd_buf,
616 sizeof (FpCmd) + cmd_len + sizeof (uint8_t),
617 sizeof (FpCmd) + resp_len + sizeof (uint8_t),
618 1,
619 focaltech_moc_release_finger);
620 1 break;
621 }
622 }
623 2 }
624
625 static void
626 1 focaltech_moc_open (FpDevice *device)
627 {
628 1 FpiDeviceFocaltechMoc *self = FPI_DEVICE_FOCALTECH_MOC (device);
629 1 GError *error = NULL;
630
631
1/2
✗ Branch 0 (4→5) not taken.
✓ Branch 1 (4→6) taken 1 times.
1 if (!g_usb_device_reset (fpi_device_get_usb_device (device), &error))
632 {
633 fpi_device_open_complete (FP_DEVICE (self), g_steal_pointer (&error));
634 return;
635 }
636
637
1/2
✗ Branch 0 (7→8) not taken.
✓ Branch 1 (7→10) taken 1 times.
1 if (usb_claim_interface_probe (device, 1, &error) != 0)
638 {
639 fpi_device_open_complete (FP_DEVICE (self), g_steal_pointer (&error));
640 return;
641 }
642
643 1 self->task_ssm = fpi_ssm_new (FP_DEVICE (self), dev_init_handler, DEV_INIT_STATES);
644 1 fpi_ssm_start (self->task_ssm, task_ssm_init_done);
645 }
646
647 static void
648 1 task_ssm_exit_done (FpiSsm *ssm, FpDevice *device, GError *error)
649 {
650 1 FpiDeviceFocaltechMoc *self = FPI_DEVICE_FOCALTECH_MOC (device);
651
652
1/2
✓ Branch 0 (2→3) taken 1 times.
✗ Branch 1 (2→7) not taken.
1 if (!error)
653 {
654 1 GError *local_error = NULL;
655
656
1/2
✗ Branch 0 (4→5) not taken.
✓ Branch 1 (4→6) taken 1 times.
1 if (usb_claim_interface_probe (device, 0, &local_error) < 0)
657 g_propagate_error (&error, g_steal_pointer (&local_error));
658 }
659
660 1 fpi_device_close_complete (FP_DEVICE (self), error);
661 1 self->task_ssm = NULL;
662 1 }
663
664 enum dev_exit_states {
665 DEV_EXIT_START,
666 DEV_EXIT_STATES,
667 };
668
669 static void
670 1 dev_exit_handler (FpiSsm *ssm, FpDevice *device)
671 {
672 1 FpiDeviceFocaltechMoc *self = FPI_DEVICE_FOCALTECH_MOC (device);
673
674
1/2
✓ Branch 0 (3→4) taken 1 times.
✗ Branch 1 (3→6) not taken.
1 switch (fpi_ssm_get_cur_state (ssm))
675 {
676 1 case DEV_EXIT_START:
677 1 fpi_ssm_next_state (self->task_ssm);
678 1 break;
679
680 default:
681 1 g_assert_not_reached ();
682 }
683 1 }
684
685 static void
686 1 focaltech_moc_close (FpDevice *device)
687 {
688 1 FpiDeviceFocaltechMoc *self = FPI_DEVICE_FOCALTECH_MOC (device);
689
690 1 fp_info ("Focaltechmoc dev_exit");
691 1 self->task_ssm = fpi_ssm_new (FP_DEVICE (self), dev_exit_handler, DEV_EXIT_STATES);
692 1 fpi_ssm_start (self->task_ssm, task_ssm_exit_done);
693 1 }
694
695 enum identify_states {
696 MOC_IDENTIFY_RELEASE_FINGER,
697 MOC_IDENTIFY_WAIT_FINGER,
698 MOC_IDENTIFY_WAIT_FINGER_DELAY,
699 MOC_IDENTIFY_CAPTURE,
700 MOC_IDENTIFY_MATCH,
701 MOC_IDENTIFY_NUM_STATES,
702 };
703
704 static void
705 8 focaltech_moc_identify_wait_finger_cb (FpiDeviceFocaltechMoc *self,
706 uint8_t *buffer_in,
707 gsize length_in,
708 GError *error)
709 {
710 8 FpCmd *fp_cmd = NULL;
711 8 uint8_t *finger_status = NULL;
712
713
1/2
✗ Branch 0 (2→3) not taken.
✓ Branch 1 (2→5) taken 8 times.
8 if (error)
714 {
715 fpi_ssm_mark_failed (self->task_ssm, error);
716 return;
717 }
718
719 8 fp_cmd = (FpCmd *) buffer_in;
720 8 finger_status = (uint8_t *) (fp_cmd + 1);
721
722
1/2
✗ Branch 0 (5→6) not taken.
✓ Branch 1 (5→8) taken 8 times.
8 if (fp_cmd->code != 0x04)
723 {
724 fpi_ssm_mark_failed (self->task_ssm,
725 fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
726 "Can't get response!!"));
727 }
728 else
729 {
730
731
2/2
✓ Branch 0 (8→9) taken 2 times.
✓ Branch 1 (8→10) taken 6 times.
8 if (*finger_status == 0x01)
732 2 fpi_ssm_jump_to_state (self->task_ssm, MOC_IDENTIFY_CAPTURE);
733 else
734 6 fpi_ssm_jump_to_state (self->task_ssm, MOC_IDENTIFY_WAIT_FINGER_DELAY);
735 }
736 }
737
738 static void
739 6 focaltech_moc_identify_wait_finger_delay (FpDevice *device,
740 void *user_data)
741 {
742 6 FpiDeviceFocaltechMoc *self = FPI_DEVICE_FOCALTECH_MOC (device);
743
744 6 fpi_ssm_jump_to_state (self->task_ssm, MOC_IDENTIFY_WAIT_FINGER);
745 6 }
746
747 enum FprintError {
748 ERROR_NONE,
749 ERROR_QUALITY,
750 ERROR_SHORT,
751 ERROR_LEFT,
752 ERROR_RIGHT,
753 ERROR_NONFINGER,
754 ERROR_NOMOVE,
755 ERROR_OTHER,
756 };
757
758 struct CaptureResult
759 {
760 uint8_t error;
761 uint8_t remain;
762 };
763
764 static void
765 2 focaltech_moc_identify_capture_cb (FpiDeviceFocaltechMoc *self,
766 uint8_t *buffer_in,
767 gsize length_in,
768 GError *error)
769 {
770 2 FpCmd *fp_cmd = NULL;
771 2 struct CaptureResult *capture_result = NULL;
772
773
1/2
✗ Branch 0 (2→3) not taken.
✓ Branch 1 (2→5) taken 2 times.
2 if (error)
774 {
775 fpi_ssm_mark_failed (self->task_ssm, error);
776 return;
777 }
778
779 2 fp_cmd = (FpCmd *) buffer_in;
780 2 capture_result = (struct CaptureResult *) (fp_cmd + 1);
781
782
1/2
✗ Branch 0 (5→6) not taken.
✓ Branch 1 (5→8) taken 2 times.
2 if (fp_cmd->code != 0x04)
783 {
784 fpi_ssm_mark_failed (self->task_ssm,
785 fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
786 "Can't get response!!"));
787 }
788 else
789 {
790
1/2
✓ Branch 0 (8→9) taken 2 times.
✗ Branch 1 (8→10) not taken.
2 if (capture_result->error == ERROR_NONE)
791 {
792 2 fpi_ssm_next_state (self->task_ssm);
793 }
794 else
795 {
796 if (fpi_device_get_current_action (FP_DEVICE (self)) == FPI_DEVICE_ACTION_VERIFY)
797 {
798 fpi_device_verify_report (FP_DEVICE (self), FPI_MATCH_ERROR, NULL, error);
799 fpi_device_verify_complete (FP_DEVICE (self), NULL);
800 }
801 else
802 {
803 fpi_device_identify_report (FP_DEVICE (self), NULL, NULL, error);
804 fpi_device_identify_complete (FP_DEVICE (self), NULL);
805 }
806
807 fpi_ssm_mark_failed (self->task_ssm, fpi_device_retry_new (FP_DEVICE_RETRY_GENERAL));
808 }
809 }
810 }
811
812 static void
813 2 identify_status_report (FpiDeviceFocaltechMoc *self, FpPrint *print, GError *error)
814 {
815 2 FpDevice *device = FP_DEVICE (self);
816
817
1/2
✗ Branch 0 (2→3) not taken.
✓ Branch 1 (2→9) taken 2 times.
2 if (print == NULL)
818 {
819 if (fpi_device_get_current_action (device) == FPI_DEVICE_ACTION_IDENTIFY)
820 {
821 fpi_device_identify_report (device, NULL, NULL, NULL);
822 fpi_device_identify_complete (device, NULL);
823 }
824 else
825 {
826 fpi_device_verify_report (device, FPI_MATCH_FAIL, NULL, NULL);
827 fpi_device_verify_complete (device, NULL);
828 }
829 }
830 else
831 {
832
2/2
✓ Branch 0 (10→11) taken 1 times.
✓ Branch 1 (10→18) taken 1 times.
2 if (fpi_device_get_current_action (device) == FPI_DEVICE_ACTION_IDENTIFY)
833 {
834 1 GPtrArray *prints;
835 1 gboolean found = FALSE;
836 1 guint index;
837
838 1 fpi_device_get_identify_data (device, &prints);
839 1 found = g_ptr_array_find_with_equal_func (prints,
840 print,
841 (GEqualFunc) fp_print_equal,
842 &index);
843
844
1/2
✓ Branch 0 (13→14) taken 1 times.
✗ Branch 1 (13→15) not taken.
1 if (found)
845 1 fpi_device_identify_report (device, g_ptr_array_index (prints, index), print, NULL);
846 else
847 fpi_device_identify_report (device, NULL, print, NULL);
848
849 1 fpi_device_identify_complete (device, NULL);
850 }
851 else
852 {
853 1 FpPrint *verify_print = NULL;
854 1 fpi_device_get_verify_data (device, &verify_print);
855
856
1/2
✓ Branch 0 (20→21) taken 1 times.
✗ Branch 1 (20→22) not taken.
1 if (fp_print_equal (verify_print, print))
857 1 fpi_device_verify_report (device, FPI_MATCH_SUCCESS, print, NULL);
858 else
859 fpi_device_verify_report (device, FPI_MATCH_FAIL, print, NULL);
860
861 1 fpi_device_verify_complete (device, NULL);
862 }
863 }
864 2 }
865
866 static void
867 2 focaltech_moc_identify_match_cb (FpiDeviceFocaltechMoc *self,
868 uint8_t *buffer_in,
869 gsize length_in,
870 GError *error)
871 {
872 2 FpCmd *fp_cmd = NULL;
873 2 struct UserId *user_id = NULL;
874 2 FpPrint *print = NULL;
875
876 2 fp_cmd = (FpCmd *) buffer_in;
877 2 user_id = (struct UserId *) (fp_cmd + 1);
878
879
1/2
✗ Branch 0 (2→3) not taken.
✓ Branch 1 (2→5) taken 2 times.
2 if (error)
880 {
881 fpi_ssm_mark_failed (self->task_ssm, error);
882 return;
883 }
884
885
1/2
✓ Branch 0 (5→6) taken 2 times.
✗ Branch 1 (5→8) not taken.
2 if (fp_cmd->code == 0x04)
886 {
887 2 print = fp_print_new (FP_DEVICE (self));
888 2 fprint_set_uid (print, user_id->uid, sizeof (user_id->uid));
889 }
890
891 2 identify_status_report (self, print, error);
892
893 2 fpi_ssm_next_state (self->task_ssm);
894 }
895
896 static void
897 20 focaltech_identify_run_state (FpiSsm *ssm, FpDevice *device)
898 {
899 20 guint8 *cmd_buf = NULL;
900 20 uint16_t cmd_len = 0;
901 20 uint16_t resp_len = 0;
902
903
5/6
✓ Branch 0 (3→4) taken 2 times.
✓ Branch 1 (3→7) taken 8 times.
✓ Branch 2 (3→10) taken 6 times.
✓ Branch 3 (3→12) taken 2 times.
✓ Branch 4 (3→15) taken 2 times.
✗ Branch 5 (3→18) not taken.
20 switch (fpi_ssm_get_cur_state (ssm))
904 {
905 2 case MOC_IDENTIFY_RELEASE_FINGER:
906 {
907 2 uint8_t d1 = 0x78;
908 2 cmd_len = sizeof (d1);
909 2 resp_len = 0;
910 2 cmd_buf = focaltech_moc_compose_cmd (0x82, &d1, cmd_len);
911 2 focaltech_moc_get_cmd (device, cmd_buf,
912 sizeof (FpCmd) + cmd_len + sizeof (uint8_t),
913 sizeof (FpCmd) + resp_len + sizeof (uint8_t),
914 1,
915 focaltech_moc_release_finger);
916 2 break;
917 }
918
919 8 case MOC_IDENTIFY_WAIT_FINGER:
920 {
921 8 uint8_t data = 0x02;
922 8 cmd_len = sizeof (uint8_t);
923 8 resp_len = sizeof (uint8_t);
924 8 cmd_buf = focaltech_moc_compose_cmd (0x80, &data, cmd_len);
925 8 focaltech_moc_get_cmd (device, cmd_buf,
926 sizeof (FpCmd) + cmd_len + sizeof (uint8_t),
927 sizeof (FpCmd) + resp_len + sizeof (uint8_t),
928 1,
929 focaltech_moc_identify_wait_finger_cb);
930 8 break;
931 }
932
933 6 case MOC_IDENTIFY_WAIT_FINGER_DELAY:
934 6 fpi_device_add_timeout (device, 50,
935 focaltech_moc_identify_wait_finger_delay,
936 NULL, NULL);
937 6 break;
938
939 2 case MOC_IDENTIFY_CAPTURE:
940 2 cmd_len = 0;
941 2 resp_len = sizeof (struct CaptureResult);
942 2 cmd_buf = focaltech_moc_compose_cmd (0xa6, NULL, cmd_len);
943 2 focaltech_moc_get_cmd (device, cmd_buf,
944 sizeof (FpCmd) + cmd_len + sizeof (uint8_t),
945 sizeof (FpCmd) + resp_len + sizeof (uint8_t),
946 1,
947 focaltech_moc_identify_capture_cb);
948 2 break;
949
950 2 case MOC_IDENTIFY_MATCH:
951 2 cmd_len = 0;
952 2 resp_len = sizeof (struct UserId);
953 2 cmd_buf = focaltech_moc_compose_cmd (0xaa, NULL, cmd_len);
954 2 focaltech_moc_get_cmd (device, cmd_buf,
955 sizeof (FpCmd) + cmd_len + sizeof (uint8_t),
956 sizeof (FpCmd) + resp_len + sizeof (uint8_t),
957 1,
958 focaltech_moc_identify_match_cb);
959 2 break;
960 }
961 20 }
962
963 static void
964 2 focaltech_moc_identify (FpDevice *device)
965 {
966 2 FpiDeviceFocaltechMoc *self = FPI_DEVICE_FOCALTECH_MOC (device);
967
968 2 self->task_ssm = fpi_ssm_new (device,
969 focaltech_identify_run_state,
970 MOC_IDENTIFY_NUM_STATES);
971 2 fpi_ssm_start (self->task_ssm, task_ssm_done);
972 2 }
973
974 enum moc_enroll_states {
975 MOC_ENROLL_GET_ENROLLED_INFO,
976 MOC_ENROLL_GET_ENROLLED_LIST,
977 MOC_ENROLL_RELEASE_FINGER,
978 MOC_ENROLL_START_ENROLL,
979 MOC_ENROLL_WAIT_FINGER,
980 MOC_ENROLL_WAIT_FINGER_DELAY,
981 MOC_ENROLL_ENROLL_CAPTURE,
982 MOC_ENROLL_SET_ENROLLED_INFO,
983 MOC_ENROLL_COMMIT_RESULT,
984 MOC_ENROLL_NUM_STATES,
985 };
986
987 struct EnrolledInfoItem
988 {
989 uint8_t uid[FOCALTECH_MOC_UID_PREFIX_LENGTH];
990 uint8_t user_id[FOCALTECH_MOC_USER_ID_LENGTH];
991 };
992
993 struct UserDes
994 {
995 uint8_t finger;
996 char username[FOCALTECH_MOC_USER_ID_LENGTH];
997 };
998
999 struct EnrolledInfo
1000 {
1001 uint8_t actived[FOCALTECH_MOC_MAX_FINGERS];
1002 struct EnrolledInfoItem items[FOCALTECH_MOC_MAX_FINGERS];
1003 struct UserId user_id[FOCALTECH_MOC_MAX_FINGERS];
1004 struct UserDes user_des[FOCALTECH_MOC_MAX_FINGERS];
1005 };
1006
1007 typedef struct
1008 {
1009 GPtrArray *list_result;
1010 struct EnrolledInfo *enrolled_info;
1011 } FpActionData;
1012
1013 struct EnrolledInfoSetData
1014 {
1015 uint8_t data;
1016 struct EnrolledInfoItem items[FOCALTECH_MOC_MAX_FINGERS];
1017 };
1018
1019 static void
1020 3 fp_action_ssm_done_data_free (FpActionData *data)
1021 {
1022
2/2
✓ Branch 0 (2→3) taken 2 times.
✓ Branch 1 (2→4) taken 1 times.
3 g_clear_pointer (&data->list_result, g_ptr_array_unref);
1023
1/2
✓ Branch 0 (4→5) taken 3 times.
✗ Branch 1 (4→6) not taken.
3 g_clear_pointer (&data->enrolled_info, g_free);
1024 3 g_free (data);
1025 3 }
1026
1027 static void
1028 3 focaltech_moc_get_enrolled_info_cb (FpiDeviceFocaltechMoc *self,
1029 uint8_t *buffer_in,
1030 gsize length_in,
1031 GError *error)
1032 {
1033 3 FpCmd *fp_cmd = NULL;
1034 3 struct EnrolledInfoItem *items = NULL;
1035 3 FpActionData *data = fpi_ssm_get_data (self->task_ssm);
1036
1037
1/2
✗ Branch 0 (3→4) not taken.
✓ Branch 1 (3→6) taken 3 times.
3 if (error)
1038 {
1039 fpi_ssm_mark_failed (self->task_ssm, error);
1040 return;
1041 }
1042
1043 3 fp_cmd = (FpCmd *) buffer_in;
1044 3 items = (struct EnrolledInfoItem *) (fp_cmd + 1);
1045
1046
1/2
✗ Branch 0 (6→7) not taken.
✓ Branch 1 (6→9) taken 3 times.
3 if (fp_cmd->code != 0x04)
1047 {
1048 fpi_ssm_mark_failed (self->task_ssm,
1049 fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
1050 "Can't get response!!"));
1051 }
1052 else
1053 {
1054 3 memcpy (&data->enrolled_info->items[0], items,
1055 FOCALTECH_MOC_MAX_FINGERS * sizeof (struct EnrolledInfoItem));
1056 3 fpi_ssm_next_state (self->task_ssm);
1057 }
1058 }
1059
1060 struct UidList
1061 {
1062 uint8_t actived[FOCALTECH_MOC_MAX_FINGERS];
1063 struct UserId uid[FOCALTECH_MOC_MAX_FINGERS];
1064 };
1065
1066 static int
1067 5 focaltech_moc_get_enrolled_info_item (FpiDeviceFocaltechMoc *self,
1068 uint8_t *uid,
1069 struct EnrolledInfoItem **pitem, int *index)
1070 {
1071 5 FpActionData *data = fpi_ssm_get_data (self->task_ssm);
1072 5 int ret = -1;
1073 5 int i;
1074
1075
2/2
✓ Branch 0 (7→4) taken 23 times.
✓ Branch 1 (7→8) taken 2 times.
30 for (i = 0; i < FOCALTECH_MOC_MAX_FINGERS; i++)
1076 {
1077 23 struct EnrolledInfoItem *item = &data->enrolled_info->items[i];
1078
1079
2/2
✓ Branch 0 (4→5) taken 3 times.
✓ Branch 1 (4→6) taken 20 times.
23 if (memcmp (item->uid, uid, FOCALTECH_MOC_UID_PREFIX_LENGTH) == 0)
1080 {
1081 3 data->enrolled_info->actived[i] = 1;
1082 3 *pitem = item;
1083 3 *index = i;
1084 3 ret = 0;
1085 3 break;
1086 }
1087 }
1088
1089 5 return ret;
1090 }
1091
1092 static void
1093 3 focaltech_moc_get_enrolled_list_cb (FpiDeviceFocaltechMoc *self,
1094 uint8_t *buffer_in,
1095 gsize length_in,
1096 GError *error)
1097 {
1098 3 FpCmd *fp_cmd = NULL;
1099 3 struct UidList *uid_list = NULL;
1100
1101
1/2
✗ Branch 0 (2→3) not taken.
✓ Branch 1 (2→5) taken 3 times.
3 if (error)
1102 {
1103 fpi_ssm_mark_failed (self->task_ssm, error);
1104 return;
1105 }
1106
1107 3 fp_cmd = (FpCmd *) buffer_in;
1108 3 uid_list = (struct UidList *) (fp_cmd + 1);
1109
1110
1/2
✗ Branch 0 (5→6) not taken.
✓ Branch 1 (5→8) taken 3 times.
3 if (fp_cmd->code != 0x04)
1111 {
1112 fpi_ssm_mark_failed (self->task_ssm,
1113 fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
1114 "Can't get response!!"));
1115 }
1116 else
1117 {
1118 3 FpActionData *data = fpi_ssm_get_data (self->task_ssm);
1119 3 int i;
1120
1121
2/2
✓ Branch 0 (28→10) taken 30 times.
✓ Branch 1 (28→32) taken 3 times.
36 for (i = 0; i < FOCALTECH_MOC_MAX_FINGERS; i++)
1122 {
1123
2/2
✓ Branch 0 (10→11) taken 2 times.
✓ Branch 1 (10→27) taken 28 times.
30 if (uid_list->actived[i] != 0)
1124 {
1125 2 struct UserId *user_id = &uid_list->uid[i];
1126 2 FpPrint *print = fp_print_new (FP_DEVICE (self));
1127 2 struct EnrolledInfoItem *item = NULL;
1128 2 int index;
1129
1130 2 fp_info ("focaltechmoc add slot: %d", i);
1131
1132 2 fprint_set_uid (print, user_id->uid, sizeof (user_id->uid));
1133
1134
1/2
✓ Branch 0 (15→16) taken 2 times.
✗ Branch 1 (15→24) not taken.
2 if (focaltech_moc_get_enrolled_info_item (self, user_id->uid, &item, &index) == 0)
1135 {
1136 2 g_autofree gchar *userid_safe = NULL;
1137 2 const gchar *username;
1138 2 userid_safe = g_strndup ((const char *) &item->user_id, FOCALTECH_MOC_USER_ID_LENGTH);
1139 2 fp_dbg ("%s", userid_safe);
1140 2 fpi_print_fill_from_user_id (print, userid_safe);
1141 2 memcpy (data->enrolled_info->user_id[index].uid, user_id->uid, 32);
1142 2 data->enrolled_info->user_des[index].finger = fp_print_get_finger (print);
1143 2 username = fp_print_get_username (print);
1144
1145
1/2
✗ Branch 0 (21→22) not taken.
✓ Branch 1 (21→23) taken 2 times.
2 if (username != NULL)
1146 strncpy (data->enrolled_info->user_des[index].username, username, 64);
1147 }
1148
1149 2 g_ptr_array_add (data->list_result, g_object_ref_sink (print));
1150 }
1151 }
1152
1153
2/2
✓ Branch 0 (32→29) taken 30 times.
✓ Branch 1 (32→33) taken 3 times.
33 for (i = 0; i < FOCALTECH_MOC_MAX_FINGERS; i++)
1154 {
1155 30 struct EnrolledInfoItem *item = &data->enrolled_info->items[i];
1156
1157
2/2
✓ Branch 0 (29→30) taken 28 times.
✓ Branch 1 (29→31) taken 2 times.
30 if (data->enrolled_info->actived[i] == 0)
1158 28 memset (item, 0, sizeof (struct EnrolledInfoItem));
1159 }
1160
1161 3 fpi_ssm_next_state (self->task_ssm);
1162 }
1163 }
1164
1165 static void
1166 43 focaltech_moc_enroll_wait_finger_cb (FpiDeviceFocaltechMoc *self,
1167 uint8_t *buffer_in,
1168 gsize length_in,
1169 GError *error)
1170 {
1171 43 FpCmd *fp_cmd = NULL;
1172 43 uint8_t *finger_status = NULL;
1173
1174
1/2
✗ Branch 0 (2→3) not taken.
✓ Branch 1 (2→5) taken 43 times.
43 if (error)
1175 {
1176 fpi_ssm_mark_failed (self->task_ssm, error);
1177 return;
1178 }
1179
1180 43 fp_cmd = (FpCmd *) buffer_in;
1181 43 finger_status = (uint8_t *) (fp_cmd + 1);
1182
1183
1/2
✗ Branch 0 (5→6) not taken.
✓ Branch 1 (5→7) taken 43 times.
43 if (fp_cmd->code != 0x04)
1184 {
1185 fpi_ssm_jump_to_state (self->task_ssm, MOC_ENROLL_WAIT_FINGER_DELAY);
1186 }
1187 else
1188 {
1189
1190
2/2
✓ Branch 0 (7→8) taken 11 times.
✓ Branch 1 (7→9) taken 32 times.
43 if (*finger_status == 0x01)
1191 11 fpi_ssm_jump_to_state (self->task_ssm, MOC_ENROLL_ENROLL_CAPTURE);
1192 else
1193 32 fpi_ssm_jump_to_state (self->task_ssm, MOC_ENROLL_WAIT_FINGER_DELAY);
1194 }
1195 }
1196
1197 static void
1198 32 focaltech_moc_enroll_wait_finger_delay (FpDevice *device,
1199 void *user_data
1200 )
1201 {
1202 32 FpiDeviceFocaltechMoc *self = FPI_DEVICE_FOCALTECH_MOC (device);
1203
1204 32 fpi_ssm_jump_to_state (self->task_ssm, MOC_ENROLL_WAIT_FINGER);
1205 32 }
1206
1207 static void
1208 1 focaltech_moc_start_enroll_cb (FpiDeviceFocaltechMoc *self,
1209 uint8_t *buffer_in,
1210 gsize length_in,
1211 GError *error)
1212 {
1213 1 FpCmd *fp_cmd = NULL;
1214 1 struct UserId *user_id = NULL;
1215 1 FpPrint *print = NULL;
1216 1 struct EnrolledInfoItem *item = NULL;
1217 1 int index;
1218
1219
1/2
✗ Branch 0 (2→3) not taken.
✓ Branch 1 (2→4) taken 1 times.
1 if (error)
1220 {
1221 fpi_ssm_mark_failed (self->task_ssm, error);
1222 return;
1223 }
1224
1225 1 fp_cmd = (FpCmd *) buffer_in;
1226 1 user_id = (struct UserId *) (fp_cmd + 1);
1227
1228
1/2
✗ Branch 0 (4→5) not taken.
✓ Branch 1 (4→11) taken 1 times.
1 if (fp_cmd->code != 0x04)
1229 {
1230 if (fp_cmd->code == 0x05)
1231 {
1232 fpi_ssm_mark_failed (self->task_ssm,
1233 fpi_device_error_new_msg (FP_DEVICE_ERROR_DATA_FULL,
1234 "device data full!!"));
1235 }
1236 else
1237 {
1238 fpi_ssm_mark_failed (self->task_ssm,
1239 fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
1240 "Can't get response!!"));
1241 }
1242 return;
1243 }
1244
1245
1/2
✗ Branch 0 (12→13) not taken.
✓ Branch 1 (12→15) taken 1 times.
1 if (focaltech_moc_get_enrolled_info_item (self, user_id->uid, &item, &index) == 0)
1246 {
1247 fpi_ssm_mark_failed (self->task_ssm,
1248 fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
1249 "uid error!!"));
1250 }
1251 else
1252 {
1253 1 FpActionData *data = fpi_ssm_get_data (self->task_ssm);
1254 1 g_autofree gchar *userid_safe = NULL;
1255 1 gsize userid_len;
1256 1 uint8_t found = 0;
1257 1 int i;
1258 1 struct EnrolledInfoItem *free_item = NULL;
1259
1260
1/2
✓ Branch 0 (19→17) taken 1 times.
✗ Branch 1 (19→20) not taken.
2 for (i = 0; i < FOCALTECH_MOC_MAX_FINGERS; i++)
1261 {
1262 1 item = &data->enrolled_info->items[i];
1263
1264
1/2
✗ Branch 0 (17→18) not taken.
✓ Branch 1 (17→22) taken 1 times.
1 if (data->enrolled_info->actived[i] == 0)
1265 {
1266 1 found = 1;
1267 1 free_item = item;
1268 1 break;
1269 }
1270 }
1271
1272 1 if (found == 0)
1273 {
1274 fpi_ssm_mark_failed (self->task_ssm,
1275 fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
1276 "no uid slot!!"));
1277 }
1278 else
1279 {
1280 1 fpi_device_get_enroll_data (FP_DEVICE (self), &print);
1281 1 fprint_set_uid (print, user_id->uid, sizeof (user_id->uid));
1282 1 userid_safe = fpi_print_generate_user_id (print);
1283 1 userid_len = strlen (userid_safe);
1284 1 userid_len = MIN (FOCALTECH_MOC_USER_ID_LENGTH, userid_len);
1285 1 fp_info ("focaltechmoc user id: %s", userid_safe);
1286 1 memcpy (free_item->uid, user_id->uid, FOCALTECH_MOC_UID_PREFIX_LENGTH);
1287 1 memcpy (free_item->user_id, userid_safe, userid_len);
1288 1 fpi_ssm_next_state (self->task_ssm);
1289 }
1290 }
1291 }
1292
1293 static void
1294 11 focaltech_moc_enroll_capture_cb (FpiDeviceFocaltechMoc *self,
1295 uint8_t *buffer_in,
1296 gsize length_in,
1297 GError *error)
1298 {
1299 11 FpCmd *fp_cmd = NULL;
1300 11 struct CaptureResult *capture_result = NULL;
1301
1302
1/2
✗ Branch 0 (2→3) not taken.
✓ Branch 1 (2→5) taken 11 times.
11 if (error)
1303 {
1304 fpi_ssm_mark_failed (self->task_ssm, error);
1305 return;
1306 }
1307
1308 11 fp_cmd = (FpCmd *) buffer_in;
1309 11 capture_result = (struct CaptureResult *) (fp_cmd + 1);
1310
1311
1/2
✗ Branch 0 (5→6) not taken.
✓ Branch 1 (5→8) taken 11 times.
11 if (fp_cmd->code != 0x04)
1312 {
1313 fpi_ssm_mark_failed (self->task_ssm,
1314 fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
1315 "Can't get response!!"));
1316 }
1317 else
1318 {
1319
2/2
✓ Branch 0 (8→9) taken 10 times.
✓ Branch 1 (8→11) taken 1 times.
11 if (capture_result->error == ERROR_NONE)
1320 {
1321 10 self->num_frames += 1;
1322 10 enroll_status_report (self, ENROLL_RSP_ENROLL_REPORT, self->num_frames, NULL);
1323 10 fp_info ("focaltechmoc remain: %d", capture_result->remain);
1324 }
1325 else
1326 {
1327 1 enroll_status_report (self, ENROLL_RSP_RETRY, self->num_frames, NULL);
1328 }
1329
1330
2/2
✓ Branch 0 (13→14) taken 1 times.
✓ Branch 1 (13→15) taken 10 times.
11 if (self->num_frames == fp_device_get_nr_enroll_stages (FP_DEVICE (self)))
1331 1 fpi_ssm_next_state (self->task_ssm);
1332 else
1333 10 fpi_ssm_jump_to_state (self->task_ssm, MOC_ENROLL_WAIT_FINGER);
1334 }
1335 }
1336
1337 static void
1338 2 focaltech_moc_set_enrolled_info_cb (FpiDeviceFocaltechMoc *self,
1339 uint8_t *buffer_in,
1340 gsize length_in,
1341 GError *error)
1342 {
1343 2 FpCmd *fp_cmd = NULL;
1344
1345
1/2
✗ Branch 0 (2→3) not taken.
✓ Branch 1 (2→5) taken 2 times.
2 if (error)
1346 {
1347 fpi_ssm_mark_failed (self->task_ssm, error);
1348 return;
1349 }
1350
1351 2 fp_cmd = (FpCmd *) buffer_in;
1352
1353
1/2
✗ Branch 0 (5→6) not taken.
✓ Branch 1 (5→9) taken 2 times.
2 if (fp_cmd->code != 0x04)
1354 {
1355 fpi_ssm_mark_failed (self->task_ssm,
1356 fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
1357 "Can't get response!!"));
1358 return;
1359 }
1360
1361 2 fpi_ssm_next_state (self->task_ssm);
1362 }
1363
1364 static void
1365 1 focaltech_moc_commit_cb (FpiDeviceFocaltechMoc *self,
1366 uint8_t *buffer_in,
1367 gsize length_in,
1368 GError *error)
1369 {
1370 1 FpCmd *fp_cmd = NULL;
1371
1372
1/2
✗ Branch 0 (2→3) not taken.
✓ Branch 1 (2→5) taken 1 times.
1 if (error)
1373 {
1374 fpi_ssm_mark_failed (self->task_ssm, error);
1375 return;
1376 }
1377
1378 1 fp_cmd = (FpCmd *) buffer_in;
1379
1380
1/2
✗ Branch 0 (5→6) not taken.
✓ Branch 1 (5→8) taken 1 times.
1 if (fp_cmd->code != 0x04)
1381 {
1382 fpi_ssm_mark_failed (self->task_ssm,
1383 fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
1384 "Can't get response!!"));
1385 }
1386 else
1387 {
1388 1 fp_info ("focaltech_moc_commit_cb success");
1389 1 enroll_status_report (self, ENROLL_RSP_ENROLL_OK, self->num_frames, NULL);
1390 1 fpi_ssm_next_state (self->task_ssm);
1391 }
1392 }
1393
1394 static void
1395 92 focaltech_enroll_run_state (FpiSsm *ssm, FpDevice *device)
1396 {
1397 92 FpiDeviceFocaltechMoc *self = FPI_DEVICE_FOCALTECH_MOC (device);
1398 92 guint8 *cmd_buf = NULL;
1399 92 uint16_t cmd_len = 0;
1400 92 uint16_t resp_len = 0;
1401
1402
9/10
✓ Branch 0 (3→4) taken 1 times.
✓ Branch 1 (3→7) taken 1 times.
✓ Branch 2 (3→10) taken 1 times.
✓ Branch 3 (3→13) taken 1 times.
✓ Branch 4 (3→16) taken 43 times.
✓ Branch 5 (3→19) taken 32 times.
✓ Branch 6 (3→21) taken 11 times.
✓ Branch 7 (3→24) taken 1 times.
✓ Branch 8 (3→29) taken 1 times.
✗ Branch 9 (3→49) not taken.
92 switch (fpi_ssm_get_cur_state (ssm))
1403 {
1404 1 case MOC_ENROLL_GET_ENROLLED_INFO:
1405 {
1406 1 uint8_t data = 0x00;
1407 1 cmd_len = sizeof (uint8_t);
1408 1 resp_len = sizeof (struct EnrolledInfoItem) * FOCALTECH_MOC_MAX_FINGERS;
1409 1 cmd_buf = focaltech_moc_compose_cmd (0xaf, &data, cmd_len);
1410 1 focaltech_moc_get_cmd (device, cmd_buf,
1411 sizeof (FpCmd) + cmd_len + sizeof (uint8_t),
1412 sizeof (FpCmd) + resp_len + sizeof (uint8_t),
1413 1,
1414 focaltech_moc_get_enrolled_info_cb);
1415 1 break;
1416 }
1417
1418 1 case MOC_ENROLL_GET_ENROLLED_LIST:
1419 {
1420 1 cmd_len = 0;
1421 1 resp_len = sizeof (struct UidList);
1422 1 cmd_buf = focaltech_moc_compose_cmd (0xab, NULL, cmd_len);
1423 1 focaltech_moc_get_cmd (device, cmd_buf,
1424 sizeof (FpCmd) + cmd_len + sizeof (uint8_t),
1425 sizeof (FpCmd) + resp_len + sizeof (uint8_t),
1426 1,
1427 focaltech_moc_get_enrolled_list_cb);
1428 1 break;
1429 }
1430
1431 1 case MOC_ENROLL_RELEASE_FINGER:
1432 {
1433 1 uint8_t d1 = 0x78;
1434 1 cmd_len = sizeof (d1);
1435 1 resp_len = 0;
1436 1 cmd_buf = focaltech_moc_compose_cmd (0x82, &d1, cmd_len);
1437 1 focaltech_moc_get_cmd (device, cmd_buf,
1438 sizeof (FpCmd) + cmd_len + sizeof (uint8_t),
1439 sizeof (FpCmd) + resp_len + sizeof (uint8_t),
1440 1,
1441 focaltech_moc_release_finger);
1442 1 break;
1443 }
1444
1445 1 case MOC_ENROLL_START_ENROLL:
1446 1 cmd_len = 0;
1447 1 resp_len = sizeof (struct UserId);
1448 1 cmd_buf = focaltech_moc_compose_cmd (0xa9, NULL, cmd_len);
1449 1 focaltech_moc_get_cmd (device, cmd_buf,
1450 sizeof (FpCmd) + cmd_len + sizeof (uint8_t),
1451 sizeof (FpCmd) + resp_len + sizeof (uint8_t),
1452 1,
1453 focaltech_moc_start_enroll_cb);
1454 1 break;
1455
1456
1457 43 case MOC_ENROLL_WAIT_FINGER:
1458 {
1459 43 uint8_t data = 0x02;
1460 43 cmd_len = sizeof (uint8_t);
1461 43 resp_len = sizeof (uint8_t);
1462 43 cmd_buf = focaltech_moc_compose_cmd (0x80, &data, cmd_len);
1463 43 focaltech_moc_get_cmd (device, cmd_buf,
1464 sizeof (FpCmd) + cmd_len + sizeof (uint8_t),
1465 sizeof (FpCmd) + resp_len + sizeof (uint8_t),
1466 1,
1467 focaltech_moc_enroll_wait_finger_cb);
1468 43 break;
1469 }
1470
1471 32 case MOC_ENROLL_WAIT_FINGER_DELAY:
1472 32 fpi_device_add_timeout (device, 50,
1473 focaltech_moc_enroll_wait_finger_delay,
1474 NULL, NULL);
1475 32 break;
1476
1477 11 case MOC_ENROLL_ENROLL_CAPTURE:
1478 11 cmd_len = 0;
1479 11 resp_len = sizeof (struct CaptureResult);
1480 11 cmd_buf = focaltech_moc_compose_cmd (0xa6, NULL, cmd_len);
1481 11 focaltech_moc_get_cmd (device, cmd_buf,
1482 sizeof (FpCmd) + cmd_len + sizeof (uint8_t),
1483 sizeof (FpCmd) + resp_len + sizeof (uint8_t),
1484 1,
1485 focaltech_moc_enroll_capture_cb);
1486 11 break;
1487
1488 1 case MOC_ENROLL_SET_ENROLLED_INFO:
1489 {
1490 1 g_autofree struct EnrolledInfoSetData *set_data = NULL;
1491 1 FpActionData *data = fpi_ssm_get_data (self->task_ssm);
1492
1493 1 cmd_len = sizeof (struct EnrolledInfoSetData);
1494 1 resp_len = 0;
1495 1 set_data = (struct EnrolledInfoSetData *) g_malloc0 (cmd_len);
1496 1 set_data->data = 0x01;
1497 1 memcpy (&set_data->items[0], &data->enrolled_info->items[0],
1498 FOCALTECH_MOC_MAX_FINGERS * sizeof (struct EnrolledInfoItem));
1499 1 cmd_buf = focaltech_moc_compose_cmd (0xaf, (const uint8_t *) set_data, cmd_len);
1500 1 focaltech_moc_get_cmd (device, cmd_buf,
1501 sizeof (FpCmd) + cmd_len + sizeof (uint8_t),
1502 sizeof (FpCmd) + resp_len + sizeof (uint8_t),
1503 1,
1504 focaltech_moc_set_enrolled_info_cb);
1505 1 break;
1506 }
1507
1508 1 case MOC_ENROLL_COMMIT_RESULT:
1509 {
1510 1 FpPrint *print = NULL;
1511 1 g_autoptr(GVariant) data = NULL;
1512
1/4
✗ Branch 0 (37→38) not taken.
✗ Branch 1 (37→39) not taken.
✓ Branch 2 (46→47) taken 1 times.
✗ Branch 3 (46→48) not taken.
1 g_autoptr(GVariant) user_id_var = NULL;
1513 1 const guint8 *user_id;
1514 1 gsize user_id_len = 0;
1515
1516 1 fpi_device_get_enroll_data (FP_DEVICE (self), &print);
1517 1 g_object_get (print, "fpi-data", &data, NULL);
1518
1519
1/2
✗ Branch 0 (32→33) not taken.
✓ Branch 1 (32→40) taken 1 times.
1 if (!g_variant_check_format_string (data, "(@ay)", FALSE))
1520 {
1521 fpi_ssm_mark_failed (ssm, fpi_device_error_new (FP_DEVICE_ERROR_DATA_INVALID));
1522 return;
1523 }
1524
1525 1 g_variant_get (data,
1526 "(@ay)",
1527 &user_id_var);
1528 1 user_id = g_variant_get_fixed_array (user_id_var, &user_id_len, 1);
1529
1530 1 cmd_len = user_id_len;
1531 1 resp_len = 0;
1532 1 cmd_buf = focaltech_moc_compose_cmd (0xa3, user_id, cmd_len);
1533 1 focaltech_moc_get_cmd (device, cmd_buf,
1534 1 sizeof (FpCmd) + cmd_len + sizeof (uint8_t),
1535 sizeof (FpCmd) + resp_len + sizeof (uint8_t),
1536 1,
1537 focaltech_moc_commit_cb);
1538
1/2
✓ Branch 0 (44→45) taken 1 times.
✗ Branch 1 (44→46) not taken.
1 break;
1539 }
1540 }
1541 }
1542
1543 static void
1544 1 focaltech_moc_enroll (FpDevice *device)
1545 {
1546 1 FpiDeviceFocaltechMoc *self = FPI_DEVICE_FOCALTECH_MOC (device);
1547 1 FpActionData *data = g_new0 (FpActionData, 1);
1548
1549 1 data->enrolled_info = g_new0 (struct EnrolledInfo, 1);
1550 1 data->list_result = g_ptr_array_new_with_free_func (g_object_unref);
1551
1552 1 self->task_ssm = fpi_ssm_new (FP_DEVICE (self),
1553 focaltech_enroll_run_state,
1554 MOC_ENROLL_NUM_STATES);
1555 1 fpi_ssm_set_data (self->task_ssm, data, (GDestroyNotify) fp_action_ssm_done_data_free);
1556 1 fpi_ssm_start (self->task_ssm, task_ssm_done);
1557 1 }
1558
1559 static void
1560 1 focaltech_moc_delete_cb (FpiDeviceFocaltechMoc *self,
1561 uint8_t *buffer_in,
1562 gsize length_in,
1563 GError *error)
1564 {
1565 1 FpCmd *fp_cmd = NULL;
1566
1567
1/2
✗ Branch 0 (2→3) not taken.
✓ Branch 1 (2→5) taken 1 times.
1 if (error)
1568 {
1569 fpi_ssm_mark_failed (self->task_ssm, error);
1570 return;
1571 }
1572
1573 1 fp_cmd = (FpCmd *) buffer_in;
1574
1575
1/2
✗ Branch 0 (5→6) not taken.
✓ Branch 1 (5→8) taken 1 times.
1 if (fp_cmd->code != 0x04)
1576 {
1577 fpi_ssm_mark_failed (self->task_ssm,
1578 fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
1579 "Can't get response!!"));
1580 }
1581 else
1582 {
1583 1 FpActionData *data = fpi_ssm_get_data (self->task_ssm);
1584 1 int ssm_state;
1585
1586
1/2
✓ Branch 0 (9→10) taken 1 times.
✗ Branch 1 (9→12) not taken.
1 if (self->delete_slot != -1)
1587 {
1588 1 fp_dbg ("delete slot %d", self->delete_slot);
1589 1 data->enrolled_info->actived[self->delete_slot] = 0;
1590 1 memset (&data->enrolled_info->items[self->delete_slot], 0, sizeof (struct EnrolledInfoItem));
1591 1 memset (&data->enrolled_info->user_id[self->delete_slot], 0, sizeof (struct UserId));
1592 1 memset (&data->enrolled_info->user_des[self->delete_slot], 0, sizeof (struct UserDes));
1593 }
1594
1595 1 ssm_state = fpi_ssm_get_cur_state (self->task_ssm);
1596 1 fpi_ssm_jump_to_state (self->task_ssm, ssm_state);
1597 }
1598 }
1599
1600 enum delete_states {
1601 MOC_DELETE_GET_ENROLLED_INFO,
1602 MOC_DELETE_GET_ENROLLED_LIST,
1603 MOC_DELETE_SET_ENROLLED_INFO,
1604 MOC_DELETE_BY_UID,
1605 MOC_DELETE_BY_USER_INFO,
1606 MOC_DELETE_NUM_STATES,
1607 };
1608
1609 static void
1610 6 focaltech_delete_run_state (FpiSsm *ssm, FpDevice *device)
1611 {
1612 6 guint8 *cmd_buf = NULL;
1613 6 uint16_t cmd_len = 0;
1614 6 uint16_t resp_len = 0;
1615
1616
5/6
✓ Branch 0 (3→4) taken 1 times.
✓ Branch 1 (3→7) taken 1 times.
✓ Branch 2 (3→10) taken 1 times.
✓ Branch 3 (3→15) taken 2 times.
✓ Branch 4 (3→40) taken 1 times.
✗ Branch 5 (3→60) not taken.
6 switch (fpi_ssm_get_cur_state (ssm))
1617 {
1618 1 case MOC_DELETE_GET_ENROLLED_INFO:
1619 {
1620 1 uint8_t data = 0x00;
1621 1 cmd_len = sizeof (uint8_t);
1622 1 resp_len = sizeof (struct EnrolledInfoItem) * FOCALTECH_MOC_MAX_FINGERS;
1623 1 cmd_buf = focaltech_moc_compose_cmd (0xaf, &data, cmd_len);
1624 1 focaltech_moc_get_cmd (device, cmd_buf,
1625 sizeof (FpCmd) + cmd_len + sizeof (uint8_t),
1626 sizeof (FpCmd) + resp_len + sizeof (uint8_t),
1627 1,
1628 focaltech_moc_get_enrolled_info_cb);
1629 1 break;
1630 }
1631
1632 1 case MOC_DELETE_GET_ENROLLED_LIST:
1633 {
1634 1 cmd_len = 0;
1635 1 resp_len = sizeof (struct UidList) + sizeof (struct UserId) * FOCALTECH_MOC_MAX_FINGERS;
1636 1 cmd_buf = focaltech_moc_compose_cmd (0xab, NULL, cmd_len);
1637 1 focaltech_moc_get_cmd (device, cmd_buf,
1638 sizeof (FpCmd) + cmd_len + sizeof (uint8_t),
1639 sizeof (FpCmd) + resp_len + sizeof (uint8_t),
1640 1,
1641 focaltech_moc_get_enrolled_list_cb);
1642 1 break;
1643 }
1644
1645 case MOC_DELETE_SET_ENROLLED_INFO:
1646 {
1647 1 FpiDeviceFocaltechMoc *self = FPI_DEVICE_FOCALTECH_MOC (device);
1648 1 g_autofree struct EnrolledInfoSetData *set_data = NULL;
1649 1 FpActionData *data = fpi_ssm_get_data (self->task_ssm);
1650
1651 1 cmd_len = sizeof (struct EnrolledInfoSetData);
1652 1 resp_len = 0;
1653 1 set_data = (struct EnrolledInfoSetData *) g_malloc0 (cmd_len);
1654 1 set_data->data = 0x01;
1655 1 memcpy (&set_data->items[0], &data->enrolled_info->items[0], FOCALTECH_MOC_MAX_FINGERS * sizeof (struct EnrolledInfoItem));
1656 1 cmd_buf = focaltech_moc_compose_cmd (0xaf, (const uint8_t *) set_data, cmd_len);
1657 1 focaltech_moc_get_cmd (device, cmd_buf,
1658 sizeof (FpCmd) + cmd_len + sizeof (uint8_t),
1659 sizeof (FpCmd) + resp_len + sizeof (uint8_t),
1660 1,
1661 focaltech_moc_set_enrolled_info_cb);
1662 1 break;
1663 }
1664
1665 case MOC_DELETE_BY_UID:
1666 {
1667 2 FpiDeviceFocaltechMoc *self = FPI_DEVICE_FOCALTECH_MOC (device);
1668 2 FpPrint *print = NULL;
1669 2 g_autoptr(GVariant) data = NULL;
1670
1/4
✗ Branch 0 (23→24) not taken.
✗ Branch 1 (23→25) not taken.
✓ Branch 2 (37→38) taken 2 times.
✗ Branch 3 (37→39) not taken.
2 g_autoptr(GVariant) user_id_var = NULL;
1671 2 const guint8 *user_id;
1672 2 gsize user_id_len = 0;
1673 2 struct EnrolledInfoItem *item = NULL;
1674 2 int index;
1675
1676 2 self->delete_slot = -1;
1677 2 fpi_device_get_delete_data (device, &print);
1678 2 g_object_get (print, "fpi-data", &data, NULL);
1679
1680
1/2
✗ Branch 0 (18→19) not taken.
✓ Branch 1 (18→26) taken 2 times.
2 if (!g_variant_check_format_string (data, "(@ay)", FALSE))
1681 {
1682 fpi_device_delete_complete (device,
1683 fpi_device_error_new (FP_DEVICE_ERROR_DATA_INVALID));
1684 return;
1685 }
1686
1687 2 g_variant_get (data, "(@ay)", &user_id_var);
1688 2 user_id = g_variant_get_fixed_array (user_id_var, &user_id_len, 1);
1689
1690
2/2
✓ Branch 0 (29→30) taken 1 times.
✓ Branch 1 (29→31) taken 1 times.
2 if (focaltech_moc_get_enrolled_info_item (self, (uint8_t *) user_id, &item, &index) == 0)
1691 1 self->delete_slot = index;
1692
1693
2/2
✓ Branch 0 (31→32) taken 1 times.
✓ Branch 1 (31→34) taken 1 times.
2 if (self->delete_slot != -1)
1694 {
1695 1 cmd_len = sizeof (struct UserId);
1696 1 resp_len = 0;
1697 1 cmd_buf = focaltech_moc_compose_cmd (0xa8, user_id, cmd_len);
1698 1 focaltech_moc_get_cmd (device, cmd_buf,
1699 sizeof (FpCmd) + cmd_len + sizeof (uint8_t),
1700 sizeof (FpCmd) + resp_len + sizeof (uint8_t),
1701 1,
1702 focaltech_moc_delete_cb);
1703 }
1704 else
1705 {
1706 1 fpi_ssm_next_state (self->task_ssm);
1707 }
1708
1709
1/2
✓ Branch 0 (35→36) taken 2 times.
✗ Branch 1 (35→37) not taken.
2 break;
1710 }
1711
1712 case MOC_DELETE_BY_USER_INFO:
1713 {
1714 1 FpiDeviceFocaltechMoc *self = FPI_DEVICE_FOCALTECH_MOC (device);
1715 1 FpActionData *data = fpi_ssm_get_data (self->task_ssm);
1716 1 FpPrint *print = NULL;
1717 1 const guint8 *user_id;
1718 1 const gchar *username;
1719 1 uint8_t finger;
1720 1 int i;
1721
1722 1 self->delete_slot = -1;
1723 1 fpi_device_get_delete_data (device, &print);
1724 1 username = fp_print_get_username (print);
1725 1 finger = fp_print_get_finger (print);
1726
1727
2/2
✓ Branch 0 (53→45) taken 10 times.
✓ Branch 1 (53→54) taken 1 times.
11 for (i = 0; i < FOCALTECH_MOC_MAX_FINGERS; i++)
1728 {
1729 10 struct UserDes *user_des = &data->enrolled_info->user_des[i];
1730
1731
1/2
✓ Branch 0 (45→46) taken 10 times.
✗ Branch 1 (45→47) not taken.
10 if (username == NULL)
1732 10 continue;
1733
1734 if (strncmp (user_des->username, username, FOCALTECH_MOC_USER_ID_LENGTH) != 0)
1735 continue;
1736
1737 if (finger != user_des->finger)
1738 continue;
1739
1740 self->delete_slot = i;
1741 }
1742
1743
1/2
✗ Branch 0 (54→55) not taken.
✓ Branch 1 (54→57) taken 1 times.
1 if (self->delete_slot != -1)
1744 {
1745 user_id = (const guint8 *) &data->enrolled_info->user_id[self->delete_slot].uid[0];
1746 cmd_len = sizeof (struct UserId);
1747 resp_len = 0;
1748 cmd_buf = focaltech_moc_compose_cmd (0xa8, user_id, cmd_len);
1749 focaltech_moc_get_cmd (device, cmd_buf,
1750 sizeof (FpCmd) + cmd_len + sizeof (uint8_t),
1751 sizeof (FpCmd) + resp_len + sizeof (uint8_t),
1752 1,
1753 focaltech_moc_delete_cb);
1754 }
1755 else
1756 {
1757 1 fpi_device_delete_complete (FP_DEVICE (self), NULL);
1758 1 fpi_ssm_next_state (self->task_ssm);
1759 }
1760
1761 1 break;
1762 }
1763 }
1764 }
1765
1766 static void
1767 1 focaltech_moc_delete_print (FpDevice *device)
1768 {
1769 1 FpiDeviceFocaltechMoc *self = FPI_DEVICE_FOCALTECH_MOC (device);
1770 1 FpActionData *data = g_new0 (FpActionData, 1);
1771
1772 1 data->enrolled_info = g_new0 (struct EnrolledInfo, 1);
1773 1 data->list_result = g_ptr_array_new_with_free_func (g_object_unref);
1774
1775 1 self->task_ssm = fpi_ssm_new (device,
1776 focaltech_delete_run_state,
1777 MOC_DELETE_NUM_STATES);
1778 1 fpi_ssm_set_data (self->task_ssm, data, (GDestroyNotify) fp_action_ssm_done_data_free);
1779 1 fpi_ssm_start (self->task_ssm, task_ssm_done);
1780 1 }
1781
1782 enum moc_list_states {
1783 MOC_LIST_GET_ENROLLED_INFO,
1784 MOC_LIST_GET_ENROLLED_LIST,
1785 MOC_LIST_REPORT,
1786 MOC_LIST_NUM_STATES,
1787 };
1788
1789 static void
1790 3 focaltech_list_run_state (FpiSsm *ssm, FpDevice *device)
1791 {
1792 3 FpiDeviceFocaltechMoc *self = FPI_DEVICE_FOCALTECH_MOC (device);
1793 3 guint8 *cmd_buf = NULL;
1794 3 uint16_t cmd_len = 0;
1795 3 uint16_t resp_len = 0;
1796
1797
3/4
✓ Branch 0 (3→4) taken 1 times.
✓ Branch 1 (3→7) taken 1 times.
✓ Branch 2 (3→10) taken 1 times.
✗ Branch 3 (3→14) not taken.
3 switch (fpi_ssm_get_cur_state (ssm))
1798 {
1799 1 case MOC_LIST_GET_ENROLLED_INFO:
1800 {
1801 1 uint8_t data = 0x00;
1802 1 cmd_len = sizeof (uint8_t);
1803 1 resp_len = sizeof (struct EnrolledInfoItem) * FOCALTECH_MOC_MAX_FINGERS;
1804 1 cmd_buf = focaltech_moc_compose_cmd (0xaf, &data, cmd_len);
1805 1 focaltech_moc_get_cmd (device, cmd_buf,
1806 sizeof (FpCmd) + cmd_len + sizeof (uint8_t),
1807 sizeof (FpCmd) + resp_len + sizeof (uint8_t),
1808 1,
1809 focaltech_moc_get_enrolled_info_cb);
1810 1 break;
1811 }
1812
1813 1 case MOC_LIST_GET_ENROLLED_LIST:
1814 {
1815 1 cmd_len = 0;
1816 1 resp_len = sizeof (struct UidList) + sizeof (struct UserId) * FOCALTECH_MOC_MAX_FINGERS;
1817 1 cmd_buf = focaltech_moc_compose_cmd (0xab, NULL, cmd_len);
1818 1 focaltech_moc_get_cmd (device, cmd_buf,
1819 sizeof (FpCmd) + cmd_len + sizeof (uint8_t),
1820 sizeof (FpCmd) + resp_len + sizeof (uint8_t),
1821 1,
1822 focaltech_moc_get_enrolled_list_cb);
1823 1 break;
1824 }
1825
1826 1 case MOC_LIST_REPORT:
1827 {
1828 1 FpActionData *data = fpi_ssm_get_data (self->task_ssm);
1829 1 fpi_device_list_complete (FP_DEVICE (self), g_steal_pointer (&data->list_result), NULL);
1830 1 fpi_ssm_next_state (self->task_ssm);
1831 1 break;
1832 }
1833 }
1834 3 }
1835
1836 static void
1837 1 focaltech_moc_list (FpDevice *device)
1838 {
1839 1 FpiDeviceFocaltechMoc *self = FPI_DEVICE_FOCALTECH_MOC (device);
1840 1 FpActionData *data = g_new0 (FpActionData, 1);
1841
1842 1 data->enrolled_info = g_new0 (struct EnrolledInfo, 1);
1843 1 data->list_result = g_ptr_array_new_with_free_func (g_object_unref);
1844 1 self->task_ssm = fpi_ssm_new (device,
1845 focaltech_list_run_state,
1846 MOC_LIST_NUM_STATES);
1847 1 fpi_ssm_set_data (self->task_ssm, data, (GDestroyNotify) fp_action_ssm_done_data_free);
1848 1 fpi_ssm_start (self->task_ssm, task_ssm_done);
1849 1 }
1850
1851 static void
1852 1 fpi_device_focaltech_moc_init (FpiDeviceFocaltechMoc *self)
1853 {
1854 1 G_DEBUG_HERE ();
1855 1 }
1856
1857 static void
1858 121 fpi_device_focaltech_moc_class_init (FpiDeviceFocaltechMocClass *klass)
1859 {
1860 121 FpDeviceClass *dev_class = FP_DEVICE_CLASS (klass);
1861
1862 121 dev_class->id = FP_COMPONENT;
1863 121 dev_class->full_name = FOCALTECH_MOC_DRIVER_FULLNAME;
1864
1865 121 dev_class->type = FP_DEVICE_TYPE_USB;
1866 121 dev_class->scan_type = FP_SCAN_TYPE_PRESS;
1867 121 dev_class->id_table = id_table;
1868 121 dev_class->nr_enroll_stages = FOCALTECH_MOC_MAX_FINGERS;
1869 121 dev_class->temp_hot_seconds = -1;
1870
1871 121 dev_class->open = focaltech_moc_open;
1872 121 dev_class->close = focaltech_moc_close;
1873 121 dev_class->verify = focaltech_moc_identify;
1874 121 dev_class->enroll = focaltech_moc_enroll;
1875 121 dev_class->identify = focaltech_moc_identify;
1876 121 dev_class->delete = focaltech_moc_delete_print;
1877 121 dev_class->list = focaltech_moc_list;
1878
1879 121 fpi_device_class_auto_initialize_features (dev_class);
1880 121 }
1881