GCC Code Coverage Report


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