GCC Code Coverage Report


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