GCC Code Coverage Report


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