GCC Code Coverage Report


Directory: ./
File: libfprint/drivers/synaptics/synaptics.c
Date: 2024-05-04 14:54:39
Exec Total Coverage
Lines: 433 728 59.5%
Functions: 28 35 80.0%
Branches: 129 308 41.9%

Line Branch Exec Source
1 /*
2 * Copyright (C) 2019 Synaptics 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 #define FP_COMPONENT "synaptics"
20
21 #include "drivers_api.h"
22
23 #include "fpi-byte-reader.h"
24
25 #include "synaptics.h"
26 #include "bmkt_message.h"
27
28
4/5
✓ Branch 0 taken 117 times.
✓ Branch 1 taken 24 times.
✓ Branch 2 taken 117 times.
✓ Branch 3 taken 117 times.
✗ Branch 4 not taken.
750 G_DEFINE_TYPE (FpiDeviceSynaptics, fpi_device_synaptics, FP_TYPE_DEVICE)
29
30 static void init_identify_msg (FpDevice *device);
31 static void compose_and_send_identify_msg (FpDevice *device);
32
33 static const FpIdEntry id_table[] = {
34 { .vid = SYNAPTICS_VENDOR_ID, .pid = 0x00BD, },
35 { .vid = SYNAPTICS_VENDOR_ID, .pid = 0x00DF, },
36 { .vid = SYNAPTICS_VENDOR_ID, .pid = 0x00F9, },
37 { .vid = SYNAPTICS_VENDOR_ID, .pid = 0x00FC, },
38 { .vid = SYNAPTICS_VENDOR_ID, .pid = 0x00C2, },
39 { .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0100, },
40 { .vid = SYNAPTICS_VENDOR_ID, .pid = 0x00F0, },
41 { .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0103, },
42 { .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0123, },
43 { .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0124, },
44 { .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0126, },
45 { .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0129, },
46 { .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0168, },
47 { .vid = SYNAPTICS_VENDOR_ID, .pid = 0x015F, },
48 { .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0104, },
49 { .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0173, },
50 { .vid = SYNAPTICS_VENDOR_ID, .pid = 0x0106, },
51 { .vid = 0, .pid = 0, .driver_data = 0 }, /* terminating entry */
52 };
53
54
55 static void
56 52 cmd_receive_cb (FpiUsbTransfer *transfer,
57 FpDevice *device,
58 gpointer user_data,
59 GError *error)
60 {
61 52 FpiDeviceSynaptics *self = FPI_DEVICE_SYNAPTICS (device);
62 52 SynCmdMsgCallback callback = user_data;
63 52 int res;
64 52 bmkt_msg_resp_t msg_resp;
65 52 bmkt_response_t resp;
66
67
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 52 times.
52 if (error)
68 {
69 /* NOTE: assumes timeout should never happen for receiving. */
70 fpi_ssm_mark_failed (transfer->ssm, error);
71 22 return;
72 }
73
74 104 res = bmkt_parse_message_header (&transfer->buffer[SENSOR_FW_REPLY_HEADER_LEN],
75 52 transfer->actual_length - SENSOR_FW_REPLY_HEADER_LEN,
76 &msg_resp);
77
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 52 times.
52 if (res != BMKT_SUCCESS)
78 {
79 g_warning ("Corrupted message received");
80 fpi_ssm_mark_failed (transfer->ssm,
81 fpi_device_error_new (FP_DEVICE_ERROR_PROTO));
82 return;
83 }
84
85 /* Special case events */
86
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 30 times.
52 if (msg_resp.msg_id == BMKT_EVT_FINGER_REPORT)
87 {
88
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 22 times.
22 if (msg_resp.payload_len != 1)
89 {
90 g_warning ("Corrupted finger report received");
91 fpi_ssm_mark_failed (transfer->ssm,
92 fpi_device_error_new (FP_DEVICE_ERROR_PROTO));
93 return;
94 }
95
96
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 11 times.
22 if (msg_resp.payload[0] == 0x01)
97 {
98 11 self->finger_on_sensor = TRUE;
99 11 fpi_device_report_finger_status_changes (device,
100 FP_FINGER_STATUS_PRESENT,
101 FP_FINGER_STATUS_NONE);
102 }
103 else
104 {
105 11 self->finger_on_sensor = FALSE;
106 11 fpi_device_report_finger_status_changes (device,
107 FP_FINGER_STATUS_NONE,
108 FP_FINGER_STATUS_PRESENT);
109
110
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (self->cmd_complete_on_removal)
111 {
112 if (self->delay_error)
113 fpi_ssm_mark_failed (transfer->ssm,
114 g_steal_pointer (&self->delay_error));
115 else
116 fpi_ssm_mark_completed (transfer->ssm);
117 return;
118 }
119 }
120
121
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 11 times.
33 fp_dbg ("Finger is now %s the sensor", self->finger_on_sensor ? "on" : "off");
122
123 /* XXX: Call callback!?! */
124 }
125
126 52 res = bmkt_parse_message_payload (&msg_resp, &resp);
127
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 52 times.
52 if (res != BMKT_SUCCESS)
128 {
129 g_warning ("Could not parse message payload: %i", res);
130 fpi_ssm_mark_failed (transfer->ssm,
131 fpi_device_error_new (FP_DEVICE_ERROR_PROTO));
132 return;
133 }
134
135 /* Special cancellation handling */
136
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 52 times.
52 if (resp.response_id == BMKT_RSP_CANCEL_OP_OK || resp.response_id == BMKT_RSP_CANCEL_OP_FAIL)
137 {
138 if (resp.response_id == BMKT_RSP_CANCEL_OP_OK)
139 {
140 fp_dbg ("Received cancellation success response");
141 fpi_ssm_mark_failed (transfer->ssm,
142 g_error_new_literal (G_IO_ERROR,
143 G_IO_ERROR_CANCELLED,
144 "Device reported cancellation of operation"));
145 }
146 else
147 {
148 fp_dbg ("Cancellation failed, this should not happen");
149 fpi_ssm_mark_failed (transfer->ssm,
150 fpi_device_error_new (FP_DEVICE_ERROR_PROTO));
151 }
152 return;
153 }
154
155
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 30 times.
52 if (msg_resp.seq_num == 0)
156 {
157 /* XXX: Should we really abort the command on general error?
158 * The original code did not! */
159
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 22 times.
22 if (msg_resp.msg_id == BMKT_RSP_GENERAL_ERROR)
160 {
161 guint16 err;
162
163 /* XXX: It is weird that this is big endian. */
164 err = FP_READ_UINT16_BE (msg_resp.payload);
165
166 fp_warn ("Received General Error %d from the sensor", (guint) err);
167 fpi_ssm_mark_failed (transfer->ssm,
168 fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
169 "Received general error %u from device",
170 (guint) err));
171 //fpi_ssm_jump_to_state (transfer->ssm, fpi_ssm_get_cur_state (transfer->ssm));
172 return;
173 }
174 else
175 {
176 22 fp_dbg ("Received message with 0 sequence number 0x%02x, ignoring!",
177 msg_resp.msg_id);
178 22 fpi_ssm_next_state (transfer->ssm);
179 22 return;
180 }
181 }
182
183 /* We should only ever have one command running, and the sequence num needs
184 * to match. */
185
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 if (msg_resp.seq_num != self->cmd_seq_num)
186 {
187 fp_warn ("Got unexpected sequence number from device, %d instead of %d",
188 msg_resp.seq_num,
189 self->cmd_seq_num);
190 }
191
192
1/2
✓ Branch 0 taken 30 times.
✗ Branch 1 not taken.
30 if (callback)
193 30 callback (self, &resp, NULL);
194
195 /* Callback may have queued a follow up command, then we need
196 * to restart the SSM. If not, we'll finish/wait for interrupt
197 * depending on resp.complete. */
198
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 if (self->cmd_pending_transfer)
199 fpi_ssm_jump_to_state (transfer->ssm, SYNAPTICS_CMD_SEND_PENDING);
200
3/4
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 23 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 7 times.
30 else if (!resp.complete || self->cmd_complete_on_removal)
201 23 fpi_ssm_next_state (transfer->ssm); /* SYNAPTICS_CMD_WAIT_INTERRUPT */
202 else
203 7 fpi_ssm_mark_completed (transfer->ssm);
204 }
205
206 static void
207 46 cmd_interrupt_cb (FpiUsbTransfer *transfer,
208 FpDevice *device,
209 gpointer user_data,
210 GError *error)
211 {
212 46 g_debug ("interrupt transfer done");
213 46 fpi_device_critical_enter (device);
214
215
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 45 times.
46 if (error)
216 {
217
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
218 {
219 1 g_error_free (error);
220
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (FPI_DEVICE_SYNAPTICS (device)->cmd_suspended)
221 1 fpi_ssm_jump_to_state (transfer->ssm, SYNAPTICS_CMD_SUSPENDED);
222 else
223 fpi_ssm_jump_to_state (transfer->ssm, SYNAPTICS_CMD_GET_RESP);
224 1 return;
225 }
226
227 fpi_ssm_mark_failed (transfer->ssm, error);
228 return;
229 }
230
231
1/2
✓ Branch 0 taken 45 times.
✗ Branch 1 not taken.
45 if (transfer->buffer[0] & USB_ASYNC_MESSAGE_PENDING)
232 {
233 45 fpi_ssm_next_state (transfer->ssm);
234 }
235 else
236 {
237 fpi_device_critical_leave (device);
238 fpi_usb_transfer_submit (fpi_usb_transfer_ref (transfer),
239 0,
240 NULL,
241 cmd_interrupt_cb,
242 NULL);
243 }
244 }
245
246 static void
247 242 synaptics_cmd_run_state (FpiSsm *ssm,
248 FpDevice *dev)
249 {
250 242 FpiUsbTransfer *transfer;
251 242 FpiDeviceSynaptics *self = FPI_DEVICE_SYNAPTICS (dev);
252
253
7/8
✓ Branch 1 taken 52 times.
✓ Branch 2 taken 52 times.
✓ Branch 3 taken 46 times.
✓ Branch 4 taken 45 times.
✓ Branch 5 taken 45 times.
✓ Branch 6 taken 1 times.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
242 switch (fpi_ssm_get_cur_state (ssm))
254 {
255 52 case SYNAPTICS_CMD_SEND_PENDING:
256
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 45 times.
52 if (self->cmd_pending_transfer)
257 {
258 7 self->cmd_pending_transfer->ssm = ssm;
259 7 fpi_usb_transfer_submit (self->cmd_pending_transfer,
260 1000,
261 NULL,
262 fpi_ssm_usb_transfer_cb,
263 NULL);
264 7 self->cmd_pending_transfer = NULL;
265 }
266 else
267 {
268 45 fpi_ssm_next_state (ssm);
269 }
270 break;
271
272 52 case SYNAPTICS_CMD_GET_RESP:
273 52 transfer = fpi_usb_transfer_new (dev);
274 52 transfer->ssm = ssm;
275 52 fpi_usb_transfer_fill_bulk (transfer, USB_EP_REPLY, MAX_TRANSFER_LEN);
276 52 fpi_usb_transfer_submit (transfer,
277 5000,
278 NULL,
279 cmd_receive_cb,
280 fpi_ssm_get_data (ssm));
281
282 52 break;
283
284 46 case SYNAPTICS_CMD_WAIT_INTERRUPT:
285 /* Interruptions are permitted only during an interrupt transfer */
286 46 fpi_device_critical_leave (dev);
287
288 46 transfer = fpi_usb_transfer_new (dev);
289 46 transfer->ssm = ssm;
290 46 fpi_usb_transfer_fill_interrupt (transfer, USB_EP_INTERRUPT, USB_INTERRUPT_DATA_SIZE);
291 46 fpi_usb_transfer_submit (transfer,
292 0,
293 self->interrupt_cancellable,
294 cmd_interrupt_cb,
295 NULL);
296
297 46 break;
298
299 45 case SYNAPTICS_CMD_SEND_ASYNC:
300 45 transfer = fpi_usb_transfer_new (dev);
301 45 transfer->ssm = ssm;
302 45 fpi_usb_transfer_fill_bulk (transfer, USB_EP_REQUEST, SENSOR_FW_CMD_HEADER_LEN);
303 45 transfer->buffer[0] = SENSOR_CMD_ASYNCMSG_READ;
304 45 fpi_usb_transfer_submit (transfer,
305 1000,
306 NULL,
307 fpi_ssm_usb_transfer_cb,
308 NULL);
309
310 45 break;
311
312 45 case SYNAPTICS_CMD_RESTART:
313 45 fpi_ssm_jump_to_state (ssm, SYNAPTICS_CMD_SEND_PENDING);
314 45 break;
315
316 1 case SYNAPTICS_CMD_SUSPENDED:
317 /* The resume handler continues to the next state! */
318 1 fpi_device_critical_leave (dev);
319 1 fpi_device_suspend_complete (dev, NULL);
320 1 break;
321
322 1 case SYNAPTICS_CMD_RESUME:
323 1 fpi_device_critical_enter (dev);
324 1 fpi_ssm_jump_to_state (ssm, SYNAPTICS_CMD_WAIT_INTERRUPT);
325 1 break;
326 }
327 242 }
328
329 static void
330 7 cmd_ssm_done (FpiSsm *ssm, FpDevice *dev, GError *error)
331 {
332 7 FpiDeviceSynaptics *self = FPI_DEVICE_SYNAPTICS (dev);
333 7 SynCmdMsgCallback callback = fpi_ssm_get_data (ssm);
334
335 7 self->cmd_ssm = NULL;
336
337 /* Notify about the SSM failure from here instead. */
338
2/4
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 7 times.
7 if (error || self->cmd_complete_on_removal)
339 callback (self, NULL, error);
340
341 7 fpi_device_critical_leave (dev);
342 7 self->cmd_complete_on_removal = FALSE;
343 7 }
344
345 static void
346 cmd_forget_cb (FpiUsbTransfer *transfer,
347 FpDevice *device,
348 gpointer user_data,
349 GError *error)
350 {
351 if (error)
352 {
353 g_warning ("Async command sending failed: %s", error->message);
354 g_error_free (error);
355 }
356 else
357 {
358 g_debug ("Async command sent successfully");
359 }
360 }
361
362 static void
363 7 synaptics_sensor_cmd (FpiDeviceSynaptics *self,
364 gint seq_num,
365 guint8 msg_id,
366 const guint8 * payload,
367 gssize payload_len,
368 SynCmdMsgCallback callback)
369 {
370 7 FpiUsbTransfer *transfer;
371 7 guint8 real_seq_num;
372 7 gint msg_len;
373 7 gint res;
374
375 /* callback may be NULL in two cases:
376 * - seq_num == -1
377 * - a state machine is already running, continued command */
378
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 g_assert (payload || payload_len == 0);
379
380 /* seq_num of 0 means a normal command, -1 means the current commands
381 * sequence number should not be updated (i.e. second async command which
382 * may only be a cancellation currently). */
383
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 if (seq_num <= 0)
384 {
385 7 self->last_seq_num = MAX (1, (self->last_seq_num + 1) & 0xff);
386 7 real_seq_num = self->last_seq_num;
387
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 if (seq_num == 0)
388 7 self->cmd_seq_num = self->last_seq_num;
389 }
390 else
391 {
392 real_seq_num = seq_num;
393 self->last_seq_num = real_seq_num;
394 }
395 7 g_debug ("sequence number is %d", real_seq_num);
396
397 /* We calculate the exact length here (we could also just create a larger
398 * buffer instead and check the result of bmkt_compose_message. */
399 7 msg_len = BMKT_MESSAGE_HEADER_LEN + payload_len;
400
401 /* Send out the command */
402 7 transfer = fpi_usb_transfer_new (FP_DEVICE (self));
403 7 transfer->short_is_error = TRUE;
404 7 fpi_usb_transfer_fill_bulk (transfer,
405 USB_EP_REQUEST,
406 7 msg_len + SENSOR_FW_CMD_HEADER_LEN);
407
408 /* MIS sensors send ACE commands encapsulated in FW commands*/
409 7 transfer->buffer[0] = SENSOR_CMD_ACE_COMMAND;
410 7 res = bmkt_compose_message (&transfer->buffer[1],
411 &msg_len, msg_id,
412 real_seq_num,
413 payload_len,
414 payload);
415
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 g_assert (res == BMKT_SUCCESS);
416
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 g_assert (msg_len + SENSOR_FW_CMD_HEADER_LEN == transfer->length);
417
418 /* Special case for async command sending (should only be used for
419 * cancellation). */
420
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (seq_num == -1)
421 {
422 g_assert (callback == NULL);
423
424 /* We just send and forget here. */
425 fpi_usb_transfer_submit (transfer, 1000, NULL, cmd_forget_cb, NULL);
426 }
427 else
428 {
429 /* Command should be send using the state machine. */
430
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 g_assert (self->cmd_pending_transfer == NULL);
431
432
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 self->cmd_pending_transfer = g_steal_pointer (&transfer);
433
434
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (self->cmd_ssm)
435 {
436 /* Continued command, we already have an SSM with a callback.
437 * There is nothing to do in this case, the command will be
438 * sent automatically. */
439 g_assert (callback == NULL);
440 }
441 else
442 {
443 /* Start of a new command, create the state machine. */
444
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 g_assert (callback != NULL);
445
446 7 self->cmd_ssm = fpi_ssm_new (FP_DEVICE (self),
447 synaptics_cmd_run_state,
448 SYNAPTICS_CMD_NUM_STATES);
449 7 fpi_ssm_set_data (self->cmd_ssm, callback, NULL);
450
451 7 fpi_device_critical_enter (FP_DEVICE (self));
452 7 fpi_ssm_start (self->cmd_ssm, cmd_ssm_done);
453 }
454 }
455 7 }
456
457 static gboolean
458 2 parse_print_data (GVariant *data,
459 guint8 *finger,
460 const guint8 **user_id,
461 gsize *user_id_len)
462 {
463 4 g_autoptr(GVariant) user_id_var = NULL;
464
465
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 g_return_val_if_fail (data != NULL, FALSE);
466
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 g_return_val_if_fail (finger != NULL, FALSE);
467
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 g_return_val_if_fail (user_id != NULL, FALSE);
468
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 g_return_val_if_fail (user_id_len != NULL, FALSE);
469
470 2 *user_id = NULL;
471 2 *user_id_len = 0;
472
473
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (!g_variant_check_format_string (data, "(y@ay)", FALSE))
474 return FALSE;
475
476 2 g_variant_get (data,
477 "(y@ay)",
478 finger,
479 &user_id_var);
480
481 2 *user_id = g_variant_get_fixed_array (user_id_var, user_id_len, 1);
482
483
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (*user_id_len == 0 || *user_id_len > BMKT_MAX_USER_ID_LEN)
484 return FALSE;
485
486
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (*user_id_len <= 0 || *user_id[0] == ' ')
487 return FALSE;
488
489 return TRUE;
490 }
491
492 static FpPrint *
493 create_print (FpiDeviceSynaptics *self,
494 guint8 *user_id,
495 guint8 finger_id)
496 {
497 FpPrint *print;
498 g_autofree gchar *user_id_safe = NULL;
499 GVariant *data = NULL;
500 GVariant *uid = NULL;
501
502 user_id_safe = g_strndup ((char *) user_id, BMKT_MAX_USER_ID_LEN);
503
504 print = fp_print_new (FP_DEVICE (self));
505 uid = g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE,
506 user_id_safe,
507 strlen (user_id_safe),
508 1);
509 data = g_variant_new ("(y@ay)",
510 finger_id,
511 uid);
512
513 fpi_print_set_type (print, FPI_PRINT_RAW);
514 fpi_print_set_device_stored (print, TRUE);
515 g_object_set (print, "fpi-data", data, NULL);
516 g_object_set (print, "description", user_id_safe, NULL);
517
518 fpi_print_fill_from_user_id (print, user_id_safe);
519
520 return print;
521 }
522
523 static void
524 1 verify_complete_after_finger_removal (FpiDeviceSynaptics *self)
525 {
526 1 FpDevice *device = FP_DEVICE (self);
527
528
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (self->finger_on_sensor)
529 {
530 fp_dbg ("delaying verify report until after finger removal!");
531 self->cmd_complete_on_removal = TRUE;
532 }
533 else
534 {
535 1 fpi_device_verify_complete (device, NULL);
536 }
537 1 }
538
539 static void
540 3 verify_msg_cb (FpiDeviceSynaptics *self,
541 bmkt_response_t *resp,
542 GError *error)
543 {
544 3 FpDevice *device = FP_DEVICE (self);
545 3 bmkt_verify_resp_t *verify_resp;
546
547
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
3 if (self->action_starting)
548 {
549 1 fpi_device_critical_leave (device);
550 1 self->action_starting = FALSE;
551 }
552
553
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (error)
554 {
555 fpi_device_verify_complete (device, error);
556 return;
557 }
558
559
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
3 if (resp == NULL && self->cmd_complete_on_removal)
560 {
561 fpi_device_verify_complete (device, NULL);
562 return;
563 }
564
565 g_assert (resp != NULL);
566
567 3 verify_resp = &resp->response.verify_resp;
568
569
3/5
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
3 switch (resp->response_id)
570 {
571 1 case BMKT_RSP_VERIFY_READY:
572 1 fpi_device_report_finger_status_changes (device,
573 FP_FINGER_STATUS_NEEDED,
574 FP_FINGER_STATUS_NONE);
575 1 fp_info ("Place Finger on the Sensor!");
576 1 break;
577
578 1 case BMKT_RSP_CAPTURE_COMPLETE:
579 1 fp_info ("Fingerprint image capture complete!");
580 1 break;
581
582 case BMKT_RSP_VERIFY_FAIL:
583 if (resp->result == BMKT_SENSOR_STIMULUS_ERROR)
584 {
585 fp_info ("Match error occurred");
586 fpi_device_verify_report (device, FPI_MATCH_ERROR, NULL,
587 fpi_device_retry_new (FP_DEVICE_RETRY_GENERAL));
588 verify_complete_after_finger_removal (self);
589 }
590 else if (resp->result == BMKT_FP_NO_MATCH)
591 {
592 fp_info ("Print didn't match");
593 fpi_device_verify_report (device, FPI_MATCH_FAIL, NULL, NULL);
594 verify_complete_after_finger_removal (self);
595 }
596 else if (resp->result == BMKT_FP_DATABASE_NO_RECORD_EXISTS)
597 {
598 fp_info ("Print is not in database");
599 fpi_device_verify_complete (device,
600 fpi_device_error_new (FP_DEVICE_ERROR_DATA_NOT_FOUND));
601 }
602 else
603 {
604 fp_warn ("Verify has failed: %d", resp->result);
605 fpi_device_verify_complete (device,
606 fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
607 "Unexpected result from device %d",
608 resp->result));
609 }
610 break;
611
612 1 case BMKT_RSP_VERIFY_OK:
613 1 fp_info ("Verify was successful! for user: %s finger: %d score: %f",
614 verify_resp->user_id, verify_resp->finger_id, verify_resp->match_result);
615 1 fpi_device_verify_report (device, FPI_MATCH_SUCCESS, NULL, NULL);
616 1 verify_complete_after_finger_removal (self);
617 1 break;
618 }
619 }
620
621 static void
622 1 verify (FpDevice *device)
623 {
624 1 FpiDeviceSynaptics *self = FPI_DEVICE_SYNAPTICS (device);
625 1 FpPrint *print = NULL;
626
627 1 g_autoptr(GVariant) data = NULL;
628 1 guint8 finger;
629 1 const guint8 *user_id;
630 1 gsize user_id_len = 0;
631
632 1 fpi_device_get_verify_data (device, &print);
633
634 1 g_object_get (print, "fpi-data", &data, NULL);
635 1 g_debug ("data is %p", data);
636
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (!parse_print_data (data, &finger, &user_id, &user_id_len))
637 {
638 fpi_device_verify_complete (device,
639 fpi_device_error_new (FP_DEVICE_ERROR_DATA_INVALID));
640 return;
641 }
642
643 1 G_DEBUG_HERE ();
644
645 1 self->action_starting = TRUE;
646 1 fpi_device_critical_enter (device);
647
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 synaptics_sensor_cmd (self, 0, BMKT_CMD_VERIFY_USER, user_id, user_id_len, verify_msg_cb);
648 }
649
650 static void
651 identify_complete_after_finger_removal (FpiDeviceSynaptics *self, GError *error)
652 {
653 FpDevice *device = FP_DEVICE (self);
654
655 if (self->finger_on_sensor)
656 {
657 fp_dbg ("delaying identify report until after finger removal!");
658 if (error)
659 g_propagate_error (&self->delay_error, error);
660
661 self->cmd_complete_on_removal = TRUE;
662 }
663 else
664 {
665 fpi_device_identify_complete (device, error);
666 }
667 }
668
669
670 static void
671 identify_msg_cb (FpiDeviceSynaptics *self,
672 bmkt_response_t *resp,
673 GError *error)
674 {
675 FpDevice *device = FP_DEVICE (self);
676
677 if (self->action_starting)
678 {
679 fpi_device_critical_leave (device);
680 self->action_starting = FALSE;
681 }
682
683 if (error)
684 {
685 fpi_device_identify_complete (device, error);
686 return;
687 }
688
689 if (resp == NULL && self->cmd_complete_on_removal)
690 {
691 fpi_device_identify_complete (device, NULL);
692 return;
693 }
694
695 g_assert (resp != NULL);
696
697 switch (resp->response_id)
698 {
699 case BMKT_RSP_ID_READY:
700 fp_info ("Place Finger on the Sensor!");
701 break;
702
703 case BMKT_RSP_SEND_NEXT_USER_ID:
704 {
705 compose_and_send_identify_msg (device);
706 break;
707 }
708
709 case BMKT_RSP_ID_FAIL:
710 if (resp->result == BMKT_SENSOR_STIMULUS_ERROR)
711 {
712 fp_info ("Match error occurred");
713 fpi_device_identify_report (device, NULL, NULL,
714 fpi_device_retry_new (FP_DEVICE_RETRY_GENERAL));
715 identify_complete_after_finger_removal (self, NULL);
716 }
717 else if (resp->result == BMKT_FP_NO_MATCH)
718 {
719 fp_info ("Print didn't match");
720 fpi_device_identify_report (device, NULL, NULL, NULL);
721 identify_complete_after_finger_removal (self, NULL);
722 }
723 else if (resp->result == BMKT_FP_DATABASE_NO_RECORD_EXISTS || resp->result == BMKT_FP_DATABASE_EMPTY)
724 {
725 fp_info ("Print is not in database");
726 identify_complete_after_finger_removal (self, fpi_device_error_new (FP_DEVICE_ERROR_DATA_NOT_FOUND));
727 }
728 else
729 {
730 fp_warn ("identify has failed: %d", resp->result);
731 fpi_device_identify_complete (device,
732 fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
733 "Unexpected result from device %d",
734 resp->result));
735 }
736 break;
737
738 case BMKT_RSP_ID_OK:
739 {
740 FpPrint *print = NULL;
741 GPtrArray *prints = NULL;
742 g_autoptr(GVariant) data = NULL;
743 gboolean found = FALSE;
744 guint index;
745
746 print = create_print (self,
747 resp->response.id_resp.user_id,
748 resp->response.id_resp.finger_id);
749
750 fpi_device_get_identify_data (device, &prints);
751
752 found = g_ptr_array_find_with_equal_func (prints,
753 print,
754 (GEqualFunc) fp_print_equal,
755 &index);
756
757 if (found)
758 fpi_device_identify_report (device, g_ptr_array_index (prints, index), print, NULL);
759 else
760 fpi_device_identify_report (device, NULL, print, NULL);
761
762 identify_complete_after_finger_removal (self, NULL);
763 }
764 }
765 }
766
767 static void
768 identify (FpDevice *device)
769 {
770 GPtrArray *prints = NULL;
771 FpiDeviceSynaptics *self = FPI_DEVICE_SYNAPTICS (device);
772
773 fpi_device_get_identify_data (device, &prints);
774
775 /* Identify over no prints does not work for synaptics.
776 * This *may* make sense for other devices though, as identify may return
777 * a matched print even if it is not in the list of prints.
778 */
779 if (prints->len == 0)
780 {
781 fpi_device_identify_report (device, NULL, NULL, NULL);
782 fpi_device_identify_complete (device, NULL);
783 return;
784 }
785
786 self->action_starting = TRUE;
787 fpi_device_critical_enter (device);
788
789 init_identify_msg (device);
790 compose_and_send_identify_msg (device);
791 }
792
793 static void
794 init_identify_msg (FpDevice *device)
795 {
796 FpiDeviceSynaptics *self = FPI_DEVICE_SYNAPTICS (device);
797
798 self->id_idx = 0;
799 }
800
801 static void
802 compose_and_send_identify_msg (FpDevice *device)
803 {
804 FpiDeviceSynaptics *self = FPI_DEVICE_SYNAPTICS (device);
805 FpPrint *print = NULL;
806 GPtrArray *prints = NULL;
807
808 g_autoptr(GVariant) data = NULL;
809 guint8 finger;
810 const guint8 *user_id;
811 gsize user_id_len = 0;
812 g_autofree guint8 *payload = NULL;
813 guint8 payload_len = 0;
814 guint8 payloadOffset = 0;
815
816 fpi_device_get_identify_data (device, &prints);
817 if (prints->len > UINT8_MAX)
818 {
819 fpi_device_identify_complete (device,
820 fpi_device_error_new (FP_DEVICE_ERROR_DATA_INVALID));
821 return;
822 }
823 if(self->id_idx >= prints->len)
824 {
825 fp_warn ("Device asked for more prints than we are providing.");
826 fpi_device_identify_complete (device,
827 fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
828 "Unexpected index"));
829 return;
830 }
831 print = g_ptr_array_index (prints, self->id_idx);
832 g_object_get (print, "fpi-data", &data, NULL);
833 g_debug ("data is %p", data);
834 if (!parse_print_data (data, &finger, &user_id, &user_id_len))
835 {
836 fpi_device_identify_complete (device,
837 fpi_device_error_new (FP_DEVICE_ERROR_DATA_INVALID));
838 return;
839 }
840 if(self->id_idx == 0)
841 {
842 /*
843 * Construct payload.
844 * 1st byte is total number of IDs in list.
845 * 2nd byte is number of IDs in list.
846 * 1 byte for each ID length, maximum id length is 100.
847 * user_id_len bytes of each ID
848 */
849 payload_len = 2 + 1 + user_id_len;
850 payload = g_malloc0 (payload_len);
851 payload[payloadOffset] = prints->len;
852 payloadOffset += 1;
853 payload[payloadOffset] = 1; /* send one id per message */
854 payloadOffset += 1;
855 payload[payloadOffset] = user_id_len;
856 payloadOffset += 1;
857 memcpy (&payload[payloadOffset], user_id, user_id_len);
858 payloadOffset += user_id_len;
859
860 G_DEBUG_HERE ();
861
862 synaptics_sensor_cmd (self, 0, BMKT_CMD_ID_USER_IN_ORDER, payload, payloadOffset, identify_msg_cb);
863 }
864 else
865 {
866 /*
867 * 1st byte is the number of IDs
868 * 1 byte for each ID length
869 * id_length bytes for each ID
870 */
871 payload_len = 1 + 1 + user_id_len;
872 payload = g_malloc0 (payload_len);
873 payload[payloadOffset] = 1; /* send one id per message */
874 payloadOffset += 1;
875 payload[payloadOffset] = user_id_len;
876 payloadOffset += 1;
877 memcpy (&payload[payloadOffset], user_id, user_id_len);
878 payloadOffset += user_id_len;
879 synaptics_sensor_cmd (self, self->cmd_seq_num, BMKT_CMD_ID_NEXT_USER, payload, payloadOffset, NULL);
880 }
881 self->id_idx++;
882 }
883 static void
884 20 enroll_msg_cb (FpiDeviceSynaptics *self,
885 bmkt_response_t *resp,
886 GError *error)
887 {
888 20 FpDevice *device = FP_DEVICE (self);
889 20 bmkt_enroll_resp_t *enroll_resp;
890
891
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 19 times.
20 if (self->action_starting)
892 {
893 1 fpi_device_critical_leave (device);
894 1 self->action_starting = FALSE;
895 }
896
897
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20 times.
20 if (error)
898 {
899 fpi_device_enroll_complete (device, NULL, error);
900 return;
901 }
902
903 20 enroll_resp = &resp->response.enroll_resp;
904
905
4/8
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 9 times.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
20 switch (resp->response_id)
906 {
907 1 case BMKT_RSP_ENROLL_READY:
908 {
909 1 self->enroll_stage = 0;
910 1 fpi_device_report_finger_status_changes (device,
911 FP_FINGER_STATUS_NEEDED,
912 FP_FINGER_STATUS_NONE);
913 1 fp_info ("Place Finger on the Sensor!");
914 1 break;
915 }
916
917 9 case BMKT_RSP_CAPTURE_COMPLETE:
918 {
919 9 fp_info ("Fingerprint image capture complete!");
920 9 break;
921 }
922
923 9 case BMKT_RSP_ENROLL_REPORT:
924 {
925 9 gint done_stages;
926 9 fp_info ("Enrollment is %d %% ", enroll_resp->progress);
927
928 9 done_stages = (enroll_resp->progress * ENROLL_SAMPLES + 99) / 100;
929
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 1 times.
9 if (enroll_resp->progress < 100)
930 8 done_stages = MIN (done_stages, ENROLL_SAMPLES - 1);
931
932 /* Emit a retry error if there has been no discernible
933 * progress. Some firmware revisions report more required
934 * touches. */
935
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 8 times.
9 if (self->enroll_stage == done_stages)
936 {
937 1 fpi_device_enroll_progress (device,
938 done_stages,
939 NULL,
940 fpi_device_retry_new (FP_DEVICE_RETRY_GENERAL));
941 }
942
943
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 9 times.
17 while (self->enroll_stage < done_stages)
944 {
945 8 self->enroll_stage += 1;
946 8 fpi_device_enroll_progress (device, self->enroll_stage, NULL, NULL);
947 }
948 break;
949 }
950
951 case BMKT_RSP_ENROLL_PAUSED:
952 {
953 fp_info ("Enrollment has been paused!");
954 break;
955 }
956
957 case BMKT_RSP_ENROLL_RESUMED:
958 {
959 fp_info ("Enrollment has been resumed!");
960 break;
961 }
962
963 case BMKT_RSP_ENROLL_FAIL:
964 {
965 fp_info ("Enrollment has failed!: %d", resp->result);
966 if (resp->result == BMKT_FP_DATABASE_FULL)
967 {
968 fpi_device_enroll_complete (device,
969 NULL,
970 fpi_device_error_new (FP_DEVICE_ERROR_DATA_FULL));
971 }
972 else
973 {
974 fpi_device_enroll_complete (device,
975 NULL,
976 fpi_device_error_new_msg (FP_DEVICE_ERROR_GENERAL,
977 "Enrollment failed (%d)",
978 resp->result));
979 }
980 break;
981 }
982
983 1 case BMKT_RSP_ENROLL_OK:
984 {
985 1 FpPrint *print = NULL;
986
987 1 fp_info ("Enrollment was successful!");
988
989 1 fpi_device_get_enroll_data (device, &print);
990
991 1 fpi_device_enroll_complete (device, g_object_ref (print), NULL);
992 1 break;
993 }
994 }
995 }
996
997 static void
998 1 enroll (FpDevice *device)
999 {
1000 1 FpiDeviceSynaptics *self = FPI_DEVICE_SYNAPTICS (device);
1001 1 FpPrint *print = NULL;
1002 1 GVariant *data = NULL;
1003 1 GVariant *uid = NULL;
1004 1 guint finger;
1005 2 g_autofree gchar *user_id = NULL;
1006 1 gssize user_id_len;
1007 1 g_autofree guint8 *payload = NULL;
1008
1009 1 fpi_device_get_enroll_data (device, &print);
1010
1011 1 G_DEBUG_HERE ();
1012
1013 1 user_id = fpi_print_generate_user_id (print);
1014
1015 1 user_id_len = strlen (user_id);
1016 1 user_id_len = MIN (BMKT_MAX_USER_ID_LEN, user_id_len);
1017
1018 /* We currently always use finger 1 from the devices point of view */
1019 1 finger = 1;
1020
1021 1 uid = g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE,
1022 user_id,
1023 user_id_len,
1024 1);
1025 1 data = g_variant_new ("(y@ay)",
1026 finger,
1027 uid);
1028
1029 1 fpi_print_set_type (print, FPI_PRINT_RAW);
1030 1 fpi_print_set_device_stored (print, TRUE);
1031 1 g_object_set (print, "fpi-data", data, NULL);
1032 1 g_object_set (print, "description", user_id, NULL);
1033
1034 1 g_debug ("user_id: %s, finger: %d", user_id, finger);
1035
1036 1 payload = g_malloc0 (user_id_len + 2);
1037
1038 /* Backup options are not supported for Prometheus */
1039 1 payload[0] = 0;
1040 1 payload[1] = finger;
1041 1 memcpy (payload + 2, user_id, user_id_len);
1042
1043 1 self->action_starting = TRUE;
1044 1 fpi_device_critical_enter (device);
1045
1046 1 synaptics_sensor_cmd (self, 0, BMKT_CMD_ENROLL_USER, payload, user_id_len + 2, enroll_msg_cb);
1047 1 }
1048
1049 static void
1050 1 delete_msg_cb (FpiDeviceSynaptics *self,
1051 bmkt_response_t *resp,
1052 GError *error)
1053 {
1054 1 FpDevice *device = FP_DEVICE (self);
1055 1 bmkt_del_user_resp_t *del_user_resp;
1056
1057
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (error)
1058 {
1059 fpi_device_critical_leave (device);
1060 fpi_device_delete_complete (device, error);
1061 return;
1062 }
1063
1064 1 del_user_resp = &resp->response.del_user_resp;
1065
1066
1/4
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 switch (resp->response_id)
1067 {
1068 case BMKT_RSP_DELETE_PROGRESS:
1069 fp_info ("Deleting Enrolled Users is %d%% complete",
1070 del_user_resp->progress);
1071 break;
1072
1073 case BMKT_RSP_DEL_USER_FP_FAIL:
1074 fpi_device_critical_leave (device);
1075 if (resp->result == BMKT_FP_DATABASE_NO_RECORD_EXISTS ||
1076 resp->result == BMKT_FP_DATABASE_EMPTY)
1077 {
1078 fp_info ("Database no record");
1079 fpi_device_delete_complete (device, NULL);
1080 }
1081 else
1082 {
1083 fp_info ("Failed to delete enrolled user: %d", resp->result);
1084 fpi_device_delete_complete (device,
1085 fpi_device_error_new (FP_DEVICE_ERROR_GENERAL));
1086 }
1087 break;
1088
1089 1 case BMKT_RSP_DEL_USER_FP_OK:
1090 1 fp_info ("Successfully deleted enrolled user");
1091 1 fpi_device_critical_leave (device);
1092 1 fpi_device_delete_complete (device, NULL);
1093 1 break;
1094 }
1095 }
1096
1097 static void
1098 1 delete_print (FpDevice *device)
1099 {
1100 1 FpiDeviceSynaptics *self = FPI_DEVICE_SYNAPTICS (device);
1101 1 FpPrint *print = NULL;
1102
1103 1 g_autoptr(GVariant) data = NULL;
1104 1 guint8 finger;
1105 1 const guint8 *user_id;
1106 1 gsize user_id_len = 0;
1107
1/4
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 g_autofree guint8 *payload = NULL;
1108
1109 1 fpi_device_get_delete_data (device, &print);
1110
1111 1 g_object_get (print, "fpi-data", &data, NULL);
1112 1 g_debug ("data is %p", data);
1113
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (!parse_print_data (data, &finger, &user_id, &user_id_len))
1114 {
1115 fpi_device_delete_complete (device,
1116 fpi_device_error_new (FP_DEVICE_ERROR_DATA_INVALID));
1117 return;
1118 }
1119
1120 1 G_DEBUG_HERE ();
1121
1122 1 payload = g_malloc0 (1 + user_id_len);
1123 1 payload[0] = finger;
1124 1 memcpy (payload + 1, user_id, user_id_len);
1125
1126 1 fpi_device_critical_enter (device);
1127 1 synaptics_sensor_cmd (self, 0, BMKT_CMD_DEL_USER_FP, payload, user_id_len + 1, delete_msg_cb);
1128 }
1129
1130 static void
1131 3 clear_storage_msg_cb (FpiDeviceSynaptics *self,
1132 bmkt_response_t *resp,
1133 GError *error)
1134 {
1135 3 FpDevice *device = FP_DEVICE (self);
1136 3 bmkt_del_all_users_resp_t *del_all_user_resp;
1137
1138
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (error)
1139 {
1140 fpi_device_clear_storage_complete (device, error);
1141 return;
1142 }
1143 3 del_all_user_resp = &resp->response.del_all_user_resp;
1144
1145
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
3 switch (resp->response_id)
1146 {
1147 2 case BMKT_RSP_DELETE_PROGRESS:
1148 2 fp_info ("Deleting All Enrolled Users is %d%% complete",
1149 del_all_user_resp->progress);
1150 2 break;
1151
1152 case BMKT_RSP_DEL_FULL_DB_FAIL:
1153 if (resp->result == BMKT_FP_DATABASE_EMPTY)
1154 fpi_device_clear_storage_complete (device, NULL);
1155 else
1156 fpi_device_clear_storage_complete (device,
1157 fpi_device_error_new (FP_DEVICE_ERROR_GENERAL));
1158 break;
1159
1160 1 case BMKT_RSP_DEL_FULL_DB_OK:
1161 1 fp_info ("Successfully deleted all enrolled user");
1162 1 fpi_device_clear_storage_complete (device, NULL);
1163 1 break;
1164 }
1165 }
1166
1167 static void
1168 1 clear_storage (FpDevice *device)
1169 {
1170 1 FpiDeviceSynaptics *self = FPI_DEVICE_SYNAPTICS (device);
1171
1172 1 g_debug ("clear all prints in database");
1173 1 synaptics_sensor_cmd (self, 0, BMKT_CMD_DEL_FULL_DB, NULL, 0, clear_storage_msg_cb);
1174 1 return;
1175 }
1176
1177
1178 static void
1179 1 prob_msg_cb (FpiDeviceSynaptics *self,
1180 bmkt_response_t *resp,
1181 GError *error)
1182 {
1183 1 GUsbDevice *usb_dev = NULL;
1184 1 g_autofree gchar *serial = NULL;
1185 1 GError *err = NULL;
1186
1187 1 usb_dev = fpi_device_get_usb_device (FP_DEVICE (self));
1188
1189
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (error)
1190 {
1191 if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
1192 err = fpi_device_error_new_msg (FP_DEVICE_ERROR_GENERAL, "unsupported firmware version");
1193
1194 g_usb_device_close (usb_dev, NULL);
1195 fpi_device_probe_complete (FP_DEVICE (self), NULL, NULL, err);
1196 g_clear_error (&error);
1197 return;
1198 }
1199
1200
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 if (g_strcmp0 (g_getenv ("FP_DEVICE_EMULATION"), "1") == 0)
1201 1 serial = g_strdup ("emulated-device");
1202 else
1203 serial = g_usb_device_get_string_descriptor (usb_dev,
1204 g_usb_device_get_serial_number_index (usb_dev),
1205 &err);
1206
1207 /* BMKT_OPERATION_DENIED is returned if the sensor is already initialized */
1208
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (resp->result == BMKT_SUCCESS || resp->result == BMKT_OPERATION_DENIED)
1209 {
1210 1 g_usb_device_close (usb_dev, NULL);
1211 1 fpi_device_probe_complete (FP_DEVICE (self), serial, NULL, err);
1212 }
1213 else if (resp->result == BMKT_FP_SYSTEM_BUSY)
1214 {
1215 synaptics_sensor_cmd (self, self->cmd_seq_num, BMKT_CMD_CANCEL_OP, NULL, 0, NULL);
1216 }
1217 else
1218 {
1219 g_warning ("Probe fingerprint sensor failed with %d!", resp->result);
1220 g_usb_device_close (usb_dev, NULL);
1221 fpi_device_probe_complete (FP_DEVICE (self), serial, NULL, fpi_device_error_new (FP_DEVICE_ERROR_GENERAL));
1222 }
1223 }
1224
1225 static void
1226 1 dev_probe (FpDevice *device)
1227 {
1228 1 FpiDeviceSynaptics *self = FPI_DEVICE_SYNAPTICS (device);
1229 1 GUsbDevice *usb_dev;
1230
1231 1 g_autoptr(FpiUsbTransfer) transfer = NULL;
1232 1 FpiByteReader reader;
1233 1 GError *error = NULL;
1234 1 guint16 status;
1235 1 const guint8 *data;
1236 1 gboolean read_ok = TRUE;
1237
1/4
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 g_autofree gchar *serial = NULL;
1238 1 gboolean retry = TRUE;
1239
1240 1 G_DEBUG_HERE ();
1241
1242 /* Claim usb interface */
1243 1 usb_dev = fpi_device_get_usb_device (device);
1244
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (!g_usb_device_open (usb_dev, &error))
1245 {
1246 fpi_device_probe_complete (device, NULL, NULL, error);
1247 return;
1248 }
1249
1250
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (!g_usb_device_claim_interface (usb_dev, 0, 0, &error))
1251 goto err_close;
1252
1253 1 while(1)
1254 {
1255 /* TODO: Do not do this synchronous. */
1256 1 transfer = fpi_usb_transfer_new (device);
1257 1 fpi_usb_transfer_fill_bulk (transfer, USB_EP_REQUEST, SENSOR_FW_CMD_HEADER_LEN);
1258 1 transfer->short_is_error = TRUE;
1259 1 transfer->buffer[0] = SENSOR_CMD_GET_VERSION;
1260
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (!fpi_usb_transfer_submit_sync (transfer, 1000, &error))
1261 goto err_close;
1262
1263 1 g_clear_pointer (&transfer, fpi_usb_transfer_unref);
1264 1 transfer = fpi_usb_transfer_new (device);
1265 1 fpi_usb_transfer_fill_bulk (transfer, USB_EP_REPLY, 40);
1266
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (!fpi_usb_transfer_submit_sync (transfer, 1000, &error))
1267 goto err_close;
1268
1269 1 fpi_byte_reader_init (&reader, transfer->buffer, transfer->actual_length);
1270
1271
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (!fpi_byte_reader_get_uint16_le (&reader, &status))
1272 {
1273 g_warning ("Transfer in response to version query was too short");
1274 error = fpi_device_error_new (FP_DEVICE_ERROR_PROTO);
1275 goto err_close;
1276 }
1277
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (status != 0)
1278 {
1279 g_warning ("Device responded with error: %d retry: %d", status, retry);
1280 if(retry)
1281 {
1282 retry = FALSE;
1283 continue;
1284 }
1285 error = fpi_device_error_new (FP_DEVICE_ERROR_PROTO);
1286 goto err_close;
1287 }
1288 1 break;
1289 }
1290
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 read_ok &= fpi_byte_reader_get_uint32_le (&reader, &self->mis_version.build_time);
1291
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 read_ok &= fpi_byte_reader_get_uint32_le (&reader, &self->mis_version.build_num);
1292
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 read_ok &= fpi_byte_reader_get_uint8 (&reader, &self->mis_version.version_major);
1293
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 read_ok &= fpi_byte_reader_get_uint8 (&reader, &self->mis_version.version_minor);
1294
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 read_ok &= fpi_byte_reader_get_uint8 (&reader, &self->mis_version.target);
1295
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 read_ok &= fpi_byte_reader_get_uint8 (&reader, &self->mis_version.product);
1296
1297
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 read_ok &= fpi_byte_reader_get_uint8 (&reader, &self->mis_version.silicon_rev);
1298
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 read_ok &= fpi_byte_reader_get_uint8 (&reader, &self->mis_version.formal_release);
1299
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 read_ok &= fpi_byte_reader_get_uint8 (&reader, &self->mis_version.platform);
1300
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 read_ok &= fpi_byte_reader_get_uint8 (&reader, &self->mis_version.patch);
1301
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 if (fpi_byte_reader_get_data (&reader, sizeof (self->mis_version.serial_number), &data))
1302 1 memcpy (self->mis_version.serial_number, data, sizeof (self->mis_version.serial_number));
1303 else
1304 read_ok = FALSE;
1305
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 read_ok &= fpi_byte_reader_get_uint16_le (&reader, &self->mis_version.security);
1306
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 read_ok &= fpi_byte_reader_get_uint8 (&reader, &self->mis_version.iface);
1307
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 read_ok &= fpi_byte_reader_get_uint8 (&reader, &self->mis_version.device_type);
1308
1309
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!read_ok)
1310 {
1311 g_warning ("Transfer in response to version query was too short");
1312 error = fpi_device_error_new (FP_DEVICE_ERROR_PROTO);
1313 goto err_close;
1314 }
1315
1316 1 fp_dbg ("Build Time: %d", self->mis_version.build_time);
1317 1 fp_dbg ("Build Num: %d", self->mis_version.build_num);
1318 1 fp_dbg ("Version: %d.%d", self->mis_version.version_major, self->mis_version.version_minor);
1319 1 fp_dbg ("Target: %d", self->mis_version.target);
1320 1 fp_dbg ("Product: %d", self->mis_version.product);
1321
1322 1 synaptics_sensor_cmd (self, 0, BMKT_CMD_FPS_INIT, NULL, 0, prob_msg_cb);
1323
1324 1 return;
1325
1326 err_close:
1327 g_usb_device_close (usb_dev, NULL);
1328 fpi_device_probe_complete (device, NULL, NULL, error);
1329 }
1330
1331 static void
1332 1 fps_init_msg_cb (FpiDeviceSynaptics *self,
1333 bmkt_response_t *resp,
1334 GError *error)
1335 {
1336
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (error)
1337 {
1338 if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
1339 g_clear_error (&error);
1340
1341 fpi_device_open_complete (FP_DEVICE (self), error);
1342 return;
1343 }
1344
1345 /* BMKT_OPERATION_DENIED is returned if the sensor is already initialized */
1346
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (resp->result == BMKT_SUCCESS || resp->result == BMKT_OPERATION_DENIED)
1347 {
1348 1 fpi_device_open_complete (FP_DEVICE (self), NULL);
1349 }
1350 else if (resp->result == BMKT_FP_SYSTEM_BUSY)
1351 {
1352 synaptics_sensor_cmd (self, self->cmd_seq_num, BMKT_CMD_CANCEL_OP, NULL, 0, NULL);
1353 }
1354 else
1355 {
1356 g_warning ("Initializing fingerprint sensor failed with %d!", resp->result);
1357 fpi_device_open_complete (FP_DEVICE (self),
1358 fpi_device_error_new (FP_DEVICE_ERROR_GENERAL));
1359 }
1360 }
1361 static void
1362 1 fps_deinit_cb (FpiDeviceSynaptics *self,
1363 bmkt_response_t *resp,
1364 GError *error)
1365 {
1366 2 g_autoptr(GError) err = NULL;
1367
1368 /* Release usb interface */
1369 1 g_usb_device_release_interface (fpi_device_get_usb_device (FP_DEVICE (self)), 0, 0, &err);
1370
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (!error)
1371 1 error = g_steal_pointer (&err);
1372
1373
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 g_clear_object (&self->interrupt_cancellable);
1374
1375
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (!error)
1376 {
1377
1/3
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 switch (resp->response_id)
1378 {
1379 1 case BMKT_RSP_POWER_DOWN_READY:
1380 1 fp_info ("Fingerprint sensor ready to be powered down");
1381 1 break;
1382
1383 case BMKT_RSP_POWER_DOWN_FAIL:
1384 fp_info ("Failed to go to power down mode: %d", resp->result);
1385 error = fpi_device_error_new_msg (FP_DEVICE_ERROR_GENERAL,
1386 "Power down failed: %d", resp->result);
1387
1388 break;
1389 }
1390 }
1391
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 fpi_device_close_complete (FP_DEVICE (self), error);
1392 1 }
1393
1394 static void
1395 1 dev_init (FpDevice *device)
1396 {
1397 1 FpiDeviceSynaptics *self = FPI_DEVICE_SYNAPTICS (device);
1398 1 GError *error = NULL;
1399
1400 1 G_DEBUG_HERE ();
1401
1402 1 self->interrupt_cancellable = g_cancellable_new ();
1403
1404 /* Claim usb interface */
1405
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
1 if (!g_usb_device_claim_interface (fpi_device_get_usb_device (device), 0, 0, &error))
1406 goto error;
1407
1408 1 synaptics_sensor_cmd (self, 0, BMKT_CMD_FPS_INIT, NULL, 0, fps_init_msg_cb);
1409
1410 1 return;
1411
1412 error:
1413 fpi_device_open_complete (FP_DEVICE (self), error);
1414 }
1415
1416 static void
1417 1 dev_exit (FpDevice *device)
1418 {
1419 1 FpiDeviceSynaptics *self = FPI_DEVICE_SYNAPTICS (device);
1420
1421 1 G_DEBUG_HERE ();
1422
1423 1 synaptics_sensor_cmd (self, 0, BMKT_CMD_POWER_DOWN_NOTIFY, NULL, 0, fps_deinit_cb);
1424 1 }
1425
1426 static void
1427 cancel (FpDevice *dev)
1428 {
1429 FpiDeviceSynaptics *self = FPI_DEVICE_SYNAPTICS (dev);
1430
1431 /* We just send out a cancel command and hope for the best. */
1432 synaptics_sensor_cmd (self, -1, BMKT_CMD_CANCEL_OP, NULL, 0, NULL);
1433
1434 /* Cancel any current interrupt transfer (resulting us to go into
1435 * response reading mode again); then create a new cancellable
1436 * for the next transfers. */
1437 g_cancellable_cancel (self->interrupt_cancellable);
1438 g_clear_object (&self->interrupt_cancellable);
1439 self->interrupt_cancellable = g_cancellable_new ();
1440 }
1441
1442 static void
1443 1 suspend (FpDevice *dev)
1444 {
1445 1 FpiDeviceSynaptics *self = FPI_DEVICE_SYNAPTICS (dev);
1446 1 FpiDeviceAction action = fpi_device_get_current_action (dev);
1447
1448 1 g_debug ("got suspend request");
1449
1450
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (action != FPI_DEVICE_ACTION_VERIFY && action != FPI_DEVICE_ACTION_IDENTIFY)
1451 {
1452 fpi_device_suspend_complete (dev, fpi_device_error_new (FP_DEVICE_ERROR_NOT_SUPPORTED));
1453 return;
1454 }
1455
1456 /* We are guaranteed to have a cmd_ssm running at this time. */
1457
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 g_assert (self->cmd_ssm);
1458
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 g_assert (fpi_ssm_get_cur_state (self->cmd_ssm) == SYNAPTICS_CMD_WAIT_INTERRUPT);
1459 1 self->cmd_suspended = TRUE;
1460
1461 /* Cancel the current transfer.
1462 * The CMD SSM will go into the suspend state and signal readyness. */
1463 1 g_cancellable_cancel (self->interrupt_cancellable);
1464
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 g_clear_object (&self->interrupt_cancellable);
1465 1 self->interrupt_cancellable = g_cancellable_new ();
1466 }
1467
1468 static void
1469 1 resume (FpDevice *dev)
1470 {
1471 1 FpiDeviceSynaptics *self = FPI_DEVICE_SYNAPTICS (dev);
1472 1 FpiDeviceAction action = fpi_device_get_current_action (dev);
1473
1474 1 g_debug ("got resume request");
1475
1476
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (action != FPI_DEVICE_ACTION_VERIFY && action != FPI_DEVICE_ACTION_IDENTIFY)
1477 {
1478 g_assert_not_reached ();
1479 fpi_device_resume_complete (dev, fpi_device_error_new (FP_DEVICE_ERROR_NOT_SUPPORTED));
1480 return;
1481 }
1482
1483 /* We must have a suspended cmd_ssm at this point */
1484
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 g_assert (self->cmd_ssm);
1485
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 g_assert (self->cmd_suspended);
1486
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 g_assert (fpi_ssm_get_cur_state (self->cmd_ssm) == SYNAPTICS_CMD_SUSPENDED);
1487 1 self->cmd_suspended = FALSE;
1488
1489 /* Restart interrupt transfer. */
1490 1 fpi_ssm_jump_to_state (self->cmd_ssm, SYNAPTICS_CMD_RESUME);
1491
1492 1 fpi_device_resume_complete (dev, NULL);
1493 }
1494
1495 static void
1496 1 fpi_device_synaptics_init (FpiDeviceSynaptics *self)
1497 {
1498 1 }
1499
1500 static void
1501 117 fpi_device_synaptics_class_init (FpiDeviceSynapticsClass *klass)
1502 {
1503 117 FpDeviceClass *dev_class = FP_DEVICE_CLASS (klass);
1504
1505 117 dev_class->id = FP_COMPONENT;
1506 117 dev_class->full_name = SYNAPTICS_DRIVER_FULLNAME;
1507
1508 117 dev_class->type = FP_DEVICE_TYPE_USB;
1509 117 dev_class->scan_type = FP_SCAN_TYPE_PRESS;
1510 117 dev_class->id_table = id_table;
1511 117 dev_class->nr_enroll_stages = ENROLL_SAMPLES;
1512 117 dev_class->temp_hot_seconds = -1;
1513
1514 117 dev_class->open = dev_init;
1515 117 dev_class->close = dev_exit;
1516 117 dev_class->probe = dev_probe;
1517 117 dev_class->verify = verify;
1518 117 dev_class->identify = identify;
1519 117 dev_class->enroll = enroll;
1520 117 dev_class->delete = delete_print;
1521 117 dev_class->clear_storage = clear_storage;
1522 117 dev_class->cancel = cancel;
1523 117 dev_class->suspend = suspend;
1524 117 dev_class->resume = resume;
1525
1526 117 fpi_device_class_auto_initialize_features (dev_class);
1527 117 }
1528