GCC Code Coverage Report


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