GCC Code Coverage Report


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