GCC Code Coverage Report


Directory: ./
File: libfprint/drivers/focaltech_moc/focaltech_moc.c
Date: 2024-09-16 14:36:32
Exec Total Coverage
Lines: 700 801 87.4%
Functions: 48 48 100.0%
Branches: 148 249 59.4%

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