GCC Code Coverage Report


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 48.9% 89 / 0 / 182
Functions: 50.0% 5 / 0 / 10
Branches: 31.9% 23 / 0 / 72

libfprint/drivers/synaptics/bmkt_message.c
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 #include <glib.h>
20 #include "bmkt_response.h"
21 #include "bmkt_message.h"
22
23 static uint8_t
24 12 extract8 (const uint8_t *buf, int *offset)
25 {
26 12 uint8_t ret = 0;
27 12 int off = 0;
28
29 12 if (offset)
30 off = *offset;
31
32 12 ret = *(buf + off);
33
34 12 if (offset)
35 *offset += 1;
36
37 12 return ret;
38 }
39
40
41 static int
42 1 parse_error_response (bmkt_msg_resp_t *msg_resp, bmkt_response_t *resp)
43 {
44 1 if (msg_resp->payload_len != 2)
45 return BMKT_UNRECOGNIZED_MESSAGE;
46
47 1 resp->result = (msg_resp->payload[0] << 8) | msg_resp->payload[1];
48
49 1 return BMKT_SUCCESS;
50 }
51
52 static int
53 1 parse_init_ok (bmkt_msg_resp_t *msg_resp, bmkt_response_t *resp)
54 {
55 1 bmkt_init_resp_t *init_resp = &resp->response.init_resp;
56
57 1 if (msg_resp->payload_len != 1)
58 return BMKT_UNRECOGNIZED_MESSAGE;
59
60 1 init_resp->finger_presence = extract8 (msg_resp->payload, NULL);
61
62 1 return BMKT_SUCCESS;
63 }
64
65
66 static int
67 parse_fps_mode_report (bmkt_msg_resp_t *msg_resp, bmkt_response_t *resp)
68 {
69 int offset = 0;
70 bmkt_fps_mode_resp_t *fps_mode_resp = &resp->response.fps_mode_resp;
71
72 if (msg_resp->payload_len != sizeof (bmkt_fps_mode_resp_t))
73 return BMKT_UNRECOGNIZED_MESSAGE;
74
75 fps_mode_resp->mode = extract8 (msg_resp->payload, &offset);
76 fps_mode_resp->level2_mode = extract8 (msg_resp->payload, &offset);
77 fps_mode_resp->cmd_id = extract8 (msg_resp->payload, &offset);
78 fps_mode_resp->finger_presence = extract8 (msg_resp->payload, &offset);
79
80 return BMKT_SUCCESS;
81 }
82
83 static int
84 9 parse_enroll_report (bmkt_msg_resp_t *msg_resp, bmkt_response_t *resp)
85 {
86 9 bmkt_enroll_resp_t *enroll_resp = &resp->response.enroll_resp;
87
88 9 if (msg_resp->payload_len != 1)
89 return BMKT_UNRECOGNIZED_MESSAGE;
90
91 9 enroll_resp->progress = extract8 (msg_resp->payload, NULL);
92
93 9 return BMKT_SUCCESS;
94 }
95
96 static int
97 1 parse_enroll_ok (bmkt_msg_resp_t *msg_resp, bmkt_response_t *resp)
98 {
99 1 bmkt_enroll_resp_t *enroll_resp = &resp->response.enroll_resp;
100
101
1/2
✓ Branch 2 → 3 taken 1 time.
✗ Branch 2 → 4 not taken.
1 if (msg_resp->payload_len < 1 || msg_resp->payload_len > (BMKT_MAX_USER_ID_LEN + 1))
102 return BMKT_UNRECOGNIZED_MESSAGE;
103
104 1 enroll_resp->finger_id = msg_resp->payload[0];
105 1 memcpy (enroll_resp->user_id, &msg_resp->payload[1], msg_resp->payload_len - 1);
106
107 1 return BMKT_SUCCESS;
108 }
109
110 static int
111 1 parse_auth_ok (bmkt_msg_resp_t *msg_resp, bmkt_response_t *resp)
112 {
113 1 bmkt_identify_resp_t *id_resp = &resp->response.id_resp;
114
115
1/2
✓ Branch 2 → 3 taken 1 time.
✗ Branch 2 → 4 not taken.
1 if (msg_resp->payload_len < 3 || msg_resp->payload_len > (BMKT_MAX_USER_ID_LEN + 3))
116 return BMKT_UNRECOGNIZED_MESSAGE;
117
118 1 id_resp->match_result = (double) msg_resp->payload[0] + 0.01 * (double) msg_resp->payload[1];
119 1 id_resp->finger_id = msg_resp->payload[2];
120 1 memcpy (id_resp->user_id, &msg_resp->payload[3], msg_resp->payload_len - 3);
121
122 1 return BMKT_SUCCESS;
123 }
124
125 static int
126 parse_security_level_report (bmkt_msg_resp_t *msg_resp, bmkt_response_t *resp)
127 {
128 bmkt_set_sec_level_resp_t *sec_level_resp = &resp->response.sec_level_resp;
129
130 if (msg_resp->payload_len != 1)
131 return BMKT_UNRECOGNIZED_MESSAGE;
132
133 sec_level_resp->sec_level = extract8 (msg_resp->payload, NULL);
134
135 return BMKT_SUCCESS;
136 }
137
138 static int
139 2 parse_del_all_users_progress_report (bmkt_msg_resp_t *msg_resp, bmkt_response_t *resp)
140 {
141 2 bmkt_del_all_users_resp_t *del_all_users_resp = &resp->response.del_all_users_resp;
142
143 2 if (msg_resp->payload_len != 1)
144 return BMKT_UNRECOGNIZED_MESSAGE;
145
146 2 del_all_users_resp->progress = extract8 (msg_resp->payload, NULL);
147
148 2 return BMKT_SUCCESS;
149 }
150
151 static int
152 parse_db_cap_report (bmkt_msg_resp_t *msg_resp, bmkt_response_t *resp)
153 {
154 bmkt_get_db_capacity_resp_t *db_cap_resp = &resp->response.db_cap_resp;
155 int offset = 0;
156
157 if (msg_resp->payload_len < 2 || msg_resp->payload_len > 4)
158 return BMKT_UNRECOGNIZED_MESSAGE;
159
160 db_cap_resp->total = extract8 (msg_resp->payload, &offset);
161 db_cap_resp->empty = extract8 (msg_resp->payload, &offset);
162
163 if (msg_resp->payload_len == 4)
164 {
165 db_cap_resp->bad_slots = extract8 (msg_resp->payload, &offset);
166 db_cap_resp->corrupt_templates = extract8 (msg_resp->payload, &offset);
167 }
168
169 return BMKT_SUCCESS;
170 }
171
172 static int
173 parse_get_enrolled_fingers_report (bmkt_msg_resp_t *msg_resp, bmkt_response_t *resp)
174 {
175 int offset = 0;
176 int i = 0;
177
178 if (msg_resp->payload_len < 2)
179 return BMKT_UNRECOGNIZED_MESSAGE;
180
181 /* 2 bytes per finger so calculate the total number of fingers to process*/
182 int num_fingers = (msg_resp->payload_len) / 2;
183
184 bmkt_enrolled_fingers_resp_t *get_enrolled_fingers_resp = &resp->response.enrolled_fingers_resp;
185
186 if (num_fingers > (int) G_N_ELEMENTS (get_enrolled_fingers_resp->fingers))
187 {
188 g_warning ("Device reported more enrolled fingers (%d) than supported",
189 num_fingers);
190 num_fingers = G_N_ELEMENTS (get_enrolled_fingers_resp->fingers);
191 }
192
193 for (i = 0; i < num_fingers; i++)
194 {
195 get_enrolled_fingers_resp->fingers[i].finger_id = extract8 (msg_resp->payload, &offset);
196 get_enrolled_fingers_resp->fingers[i].template_status = extract8 (msg_resp->payload, &offset);
197 }
198
199 return BMKT_SUCCESS;
200 }
201 static int
202 parse_get_enrolled_users_report (bmkt_msg_resp_t *msg_resp, bmkt_response_t *resp)
203 {
204 int offset = 0;
205 int i = 0;
206
207 /* the payload is 2 bytes + template data */
208 if (msg_resp->payload_len < 2)
209 return BMKT_UNRECOGNIZED_MESSAGE;
210
211 bmkt_enroll_templates_resp_t *get_enroll_templates_resp = &resp->response.enroll_templates_resp;
212
213 get_enroll_templates_resp->total_query_messages = extract8 (msg_resp->payload, &offset);
214 get_enroll_templates_resp->query_sequence = extract8 (msg_resp->payload, &offset);
215
216 int n = 0;
217
218 for (n = 0; n < BMKT_MAX_NUM_TEMPLATES_INTERNAL_FLASH; n++)
219 {
220 if (offset >= msg_resp->payload_len)
221 break;
222 get_enroll_templates_resp->templates[n].user_id_len = extract8 (msg_resp->payload, &offset) - 2;
223 if(get_enroll_templates_resp->templates[n].user_id_len > BMKT_MAX_USER_ID_LEN)
224 return BMKT_UNRECOGNIZED_MESSAGE;
225 if (offset >= msg_resp->payload_len)
226 return BMKT_CORRUPT_MESSAGE;
227 get_enroll_templates_resp->templates[n].template_status = extract8 (msg_resp->payload, &offset);
228 if (offset >= msg_resp->payload_len)
229 return BMKT_CORRUPT_MESSAGE;
230 get_enroll_templates_resp->templates[n].finger_id = extract8 (msg_resp->payload, &offset);
231 for (i = 0; i < get_enroll_templates_resp->templates[n].user_id_len; i++)
232 {
233 if (offset >= msg_resp->payload_len)
234 return BMKT_CORRUPT_MESSAGE;
235 get_enroll_templates_resp->templates[n].user_id[i] = extract8 (msg_resp->payload, &offset);
236 }
237 get_enroll_templates_resp->templates[n].user_id[i] = '\0';
238 }
239
240 return BMKT_SUCCESS;
241 }
242
243 static int
244 parse_get_version_report (bmkt_msg_resp_t *msg_resp, bmkt_response_t *resp)
245 {
246 bmkt_get_version_resp_t *get_version_resp = &resp->response.get_version_resp;
247 int offset = 0;
248
249 if (msg_resp->payload_len != 15)
250 return BMKT_UNRECOGNIZED_MESSAGE;
251
252 memcpy (get_version_resp->part, msg_resp->payload, BMKT_PART_NUM_LEN);
253 offset += BMKT_PART_NUM_LEN;
254 get_version_resp->year = extract8 (msg_resp->payload, &offset);
255 get_version_resp->week = extract8 (msg_resp->payload, &offset);
256 get_version_resp->patch = extract8 (msg_resp->payload, &offset);
257 memcpy (get_version_resp->supplier_id, msg_resp->payload + offset, BMKT_SUPPLIER_ID_LEN);
258
259 return BMKT_SUCCESS;
260 }
261
262 int
263 7 bmkt_compose_message (uint8_t *cmd, int *cmd_len, uint8_t msg_id, uint8_t seq_num,
264 uint8_t payload_size, const uint8_t *payload)
265 {
266 7 int message_len = BMKT_MESSAGE_HEADER_LEN + payload_size;
267
268
1/2
✓ Branch 2 → 3 taken 7 times.
✗ Branch 2 → 6 not taken.
7 if (*cmd_len < message_len)
269 return BMKT_OUT_OF_MEMORY;
270
271 7 cmd[BMKT_MESSAGE_HEADER_ID_FIELD] = BMKT_MESSAGE_HEADER_ID;
272 7 cmd[BMKT_MESSAGE_SEQ_NUM_FIELD] = seq_num;
273 7 cmd[BMKT_MESSAGE_ID_FIELD] = msg_id;
274 7 cmd[BMKT_MESSAGE_PAYLOAD_LEN_FIELD] = payload_size;
275
2/2
✓ Branch 3 → 4 taken 3 times.
✓ Branch 3 → 5 taken 4 times.
7 if (payload_size > 0)
276 3 memcpy (&cmd[BMKT_MESSAGE_PAYLOAD_FIELD], payload, payload_size);
277
278 7 *cmd_len = message_len;
279
280 7 return BMKT_SUCCESS;
281 }
282
283 int
284 52 bmkt_parse_message_header (uint8_t *resp_buf, int resp_len, bmkt_msg_resp_t *msg_resp)
285 {
286
1/2
✓ Branch 2 → 3 taken 52 times.
✗ Branch 2 → 8 not taken.
52 if (resp_len < BMKT_MESSAGE_HEADER_LEN)
287 return BMKT_CORRUPT_MESSAGE;
288
289
1/2
✓ Branch 3 → 4 taken 52 times.
✗ Branch 3 → 8 not taken.
52 if (resp_buf[BMKT_MESSAGE_HEADER_ID_FIELD] != BMKT_MESSAGE_HEADER_ID)
290 return BMKT_CORRUPT_MESSAGE;
291
292 52 msg_resp->seq_num = resp_buf[BMKT_MESSAGE_SEQ_NUM_FIELD];
293 52 msg_resp->msg_id = resp_buf[BMKT_MESSAGE_ID_FIELD];
294 52 msg_resp->payload_len = resp_buf[BMKT_MESSAGE_PAYLOAD_LEN_FIELD];
295
296
1/2
✓ Branch 4 → 5 taken 52 times.
✗ Branch 4 → 8 not taken.
52 if (msg_resp->payload_len > resp_len - BMKT_MESSAGE_PAYLOAD_FIELD)
297 return BMKT_CORRUPT_MESSAGE;
298
299
2/2
✓ Branch 5 → 6 taken 38 times.
✓ Branch 5 → 7 taken 14 times.
52 if (msg_resp->payload_len > 0)
300 38 msg_resp->payload = &resp_buf[BMKT_MESSAGE_PAYLOAD_FIELD];
301 else
302 14 msg_resp->payload = NULL;
303
304 return BMKT_SUCCESS;
305 }
306
307 int
308 52 bmkt_parse_message_payload (bmkt_msg_resp_t *msg_resp, bmkt_response_t *resp)
309 {
310 52 int ret = BMKT_SUCCESS;
311
312 52 memset (resp, 0, sizeof (bmkt_response_t));
313
314 52 resp->response_id = msg_resp->msg_id;
315
316
9/16
✓ Branch 2 → 3 taken 1 time.
✓ Branch 2 → 6 taken 1 time.
✓ Branch 2 → 9 taken 2 times.
✗ Branch 2 → 10 not taken.
✗ Branch 2 → 12 not taken.
✓ Branch 2 → 15 taken 2 times.
✓ Branch 2 → 17 taken 9 times.
✓ Branch 2 → 19 taken 1 time.
✓ Branch 2 → 21 taken 1 time.
✗ Branch 2 → 23 not taken.
✗ Branch 2 → 25 not taken.
✗ Branch 2 → 27 not taken.
✗ Branch 2 → 29 not taken.
✗ Branch 2 → 30 not taken.
✓ Branch 2 → 32 taken 1 time.
✓ Branch 2 → 33 taken 34 times.
52 switch(msg_resp->msg_id)
317 {
318 case BMKT_RSP_CONTINUOUS_IMAGE_CAPTURE_FAIL:
319 case BMKT_RSP_SENSOR_MODULE_TEST_FAIL:
320 case BMKT_RSP_FPS_INIT_FAIL:
321 case BMKT_RSP_FPS_MODE_FAIL:
322 case BMKT_RSP_SET_SECURITY_LEVEL_FAIL:
323 case BMKT_RSP_GET_SECURITY_LEVEL_FAIL:
324 case BMKT_RSP_CANCEL_OP_FAIL:
325 case BMKT_RSP_ENROLL_FAIL:
326 case BMKT_RSP_ID_FAIL:
327 case BMKT_RSP_VERIFY_FAIL:
328 case BMKT_RSP_QUERY_FAIL:
329 case BMKT_RSP_DEL_USER_FP_FAIL:
330 case BMKT_RSP_DEL_FULL_DB_FAIL:
331 case BMKT_RSP_REPEAT_LAST_BMKT_RSP_FAIL:
332 case BMKT_RSP_POWER_DOWN_FAIL:
333 case BMKT_RSP_GET_VERSION_FAIL:
334 case BMKT_RSP_DISABLE_PAIRING_FAIL:
335 case BMKT_RSP_QUERY_PAIRING_FAIL:
336 case BMKT_RSP_SENSOR_STATUS_FAIL:
337 case BMKT_RSP_RETRIEVE_FINAL_RESULT_FAIL:
338
1/2
✓ Branch 3 → 4 taken 1 time.
✗ Branch 3 → 5 not taken.
1 ret = parse_error_response (msg_resp, resp);
339 1 resp->complete = 1;
340 1 break;
341
342 case BMKT_RSP_FPS_INIT_OK:
343
1/2
✓ Branch 6 → 7 taken 1 time.
✗ Branch 6 → 8 not taken.
1 ret = parse_init_ok (msg_resp, resp);
344 1 resp->complete = 1;
345 1 break;
346
347 2 case BMKT_RSP_CANCEL_OP_OK:
348 case BMKT_RSP_DEL_FULL_DB_OK:
349 case BMKT_RSP_DEL_USER_FP_OK:
350 /* responses with a payload of 0
351 so the response indicates success */
352 2 resp->result = BMKT_SUCCESS;
353 2 resp->complete = 1;
354 2 break;
355
356 case BMKT_RSP_FPS_MODE_REPORT:
357 // parse_fps_mode
358 ret = parse_fps_mode_report (msg_resp, resp);
359 resp->complete = 1;
360 break;
361
362 case BMKT_RSP_GET_SECURITY_LEVEL_REPORT:
363 case BMKT_RSP_SET_SECURITY_LEVEL_REPORT:
364 /* parse security level result */
365 ret = parse_security_level_report (msg_resp, resp);
366 resp->complete = 1;
367 break;
368
369 case BMKT_RSP_DELETE_PROGRESS:
370
1/2
✓ Branch 15 → 16 taken 2 times.
✗ Branch 15 → 33 not taken.
2 ret = parse_del_all_users_progress_report (msg_resp, resp);
371 break;
372
373 case BMKT_RSP_CAPTURE_COMPLETE:
374 resp->result = BMKT_SUCCESS;
375 break;
376
377 case BMKT_RSP_ENROLL_READY:
378 resp->result = BMKT_SUCCESS;
379 break;
380
381 case BMKT_RSP_ENROLL_REPORT:
382
1/2
✓ Branch 17 → 18 taken 9 times.
✗ Branch 17 → 33 not taken.
9 ret = parse_enroll_report (msg_resp, resp);
383 break;
384
385 1 case BMKT_RSP_ENROLL_OK:
386 1 resp->complete = 1;
387 1 ret = parse_enroll_ok (msg_resp, resp);
388 1 break;
389
390 1 case BMKT_RSP_ID_OK:
391 case BMKT_RSP_VERIFY_OK:
392 1 ret = parse_auth_ok (msg_resp, resp);
393 1 resp->complete = 1;
394 1 break;
395
396 case BMKT_RSP_GET_ENROLLED_FINGERS_REPORT:
397 ret = parse_get_enrolled_fingers_report (msg_resp, resp);
398 resp->complete = 1;
399 break;
400
401 case BMKT_RSP_DATABASE_CAPACITY_REPORT:
402 resp->complete = 1;
403 ret = parse_db_cap_report (msg_resp, resp);
404 break;
405
406 case BMKT_RSP_TEMPLATE_RECORDS_REPORT:
407 ret = parse_get_enrolled_users_report (msg_resp, resp);
408 break;
409
410 case BMKT_RSP_QUERY_RESPONSE_COMPLETE:
411 resp->complete = 1;
412 break;
413
414 case BMKT_RSP_VERSION_INFO:
415 ret = parse_get_version_report (msg_resp, resp);
416 resp->complete = 1;
417 break;
418
419 1 case BMKT_RSP_POWER_DOWN_READY:
420 1 resp->complete = 1;
421 1 break;
422 }
423
424 52 return ret;
425 }
426