GCC Code Coverage Report


Directory: ./
File: libfprint/drivers/synaptics/synaptics.c
Date: 2025-12-06 02:24:24
Exec Total Coverage
Lines: 434 732 59.3%
Functions: 28 35 80.0%
Branches: 129 309 41.7%

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