GCC Code Coverage Report


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 88.9% 216 / 0 / 243
Functions: 100.0% 21 / 0 / 21
Branches: 59.4% 38 / 0 / 64

libfprint/drivers/aes2550.c
Line Branch Exec Source
1 /*
2 * AuthenTec AES2550/AES2810 driver for libfprint
3 * Copyright (C) 2007-2008 Daniel Drake <dsd@gentoo.org>
4 * Copyright (C) 2007 Cyrille Bagard
5 * Copyright (C) 2007-2012 Vasily Khoruzhick
6 *
7 * Based on AES2501 driver
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 */
23
24 #define FP_COMPONENT "aes2550"
25
26 #include "drivers_api.h"
27 #include "aes2550.h"
28 #include "aeslib.h"
29
30 static void start_capture (FpImageDevice *dev);
31 static void complete_deactivation (FpImageDevice *dev);
32
33 #define EP_IN (1 | FPI_USB_ENDPOINT_IN)
34 #define EP_OUT (2 | FPI_USB_ENDPOINT_OUT)
35 #define BULK_TIMEOUT 4000
36
37 /*
38 * The AES2550 is an imaging device using a swipe-type sensor. It samples
39 * the finger at preprogrammed intervals, sending a 192x16 frame to the
40 * computer.
41 * Unless the user is scanning their finger unreasonably fast, the frames
42 * *will* overlap. The implementation below detects this overlap and produces
43 * a contiguous image as the end result.
44 * The fact that the user determines the length of the swipe (and hence the
45 * number of useful frames) and also the fact that overlap varies means that
46 * images returned from this driver vary in height.
47 */
48
49 #define FRAME_WIDTH 192
50 #define FRAME_HEIGHT 8
51 #define FRAME_SIZE (FRAME_WIDTH * FRAME_HEIGHT)
52 #define IMAGE_WIDTH (FRAME_WIDTH + (FRAME_WIDTH / 2))
53
54 struct _FpiDeviceAes2550
55 {
56 FpImageDevice parent;
57
58 GSList *strips;
59 size_t strips_len;
60 gboolean active;
61 gboolean deactivating;
62 int heartbeat_cnt;
63 };
64 G_DECLARE_FINAL_TYPE (FpiDeviceAes2550, fpi_device_aes2550, FPI, DEVICE_AES2550,
65 FpImageDevice);
66
4/6
fpi_device_aes2550_class_intern_init:
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 127 times.
fpi_device_aes2550_get_type:
✓ Branch 2 → 3 taken 127 times.
✓ Branch 2 → 7 taken 24 times.
✓ Branch 4 → 5 taken 127 times.
✗ Branch 4 → 7 not taken.
405 G_DEFINE_TYPE (FpiDeviceAes2550, fpi_device_aes2550, FP_TYPE_IMAGE_DEVICE);
67
68 static struct fpi_frame_asmbl_ctx assembling_ctx = {
69 .frame_width = FRAME_WIDTH,
70 .frame_height = FRAME_HEIGHT,
71 .image_width = IMAGE_WIDTH,
72 .get_pixel = aes_get_pixel,
73 };
74
75 /****** FINGER PRESENCE DETECTION ******/
76
77 static unsigned char finger_det_reqs[] = {
78 0x80, AES2550_REG80_MASTER_RESET,
79 0x95, (8 << AES2550_REG95_COL_SCANNED_OFS) | (1 << AES2550_REG95_EPIX_AVG_OFS),
80 0xad, 0x00,
81 0xbd, (0 << AES2550_REGBD_LPO_IN_15_8_OFS),
82 0xbe, (0 << AES2550_REGBE_LPO_IN_7_0_OFS),
83 0xcf, AES2550_REGCF_INTERFERENCE_CHK_EN,
84 AES2550_CMD_HEARTBEAT, 0x00, 0x01, 0x00, /* Heart beat off */
85 AES2550_CMD_RUN_FD,
86 };
87
88 static void start_finger_detection (FpImageDevice *dev);
89
90 static void
91 3890 finger_det_data_cb (FpiUsbTransfer *transfer, FpDevice *device,
92 gpointer user_data, GError *error)
93 {
94 3890 FpImageDevice *dev = FP_IMAGE_DEVICE (device);
95 3890 FpiDeviceAes2550 *self = FPI_DEVICE_AES2550 (device);
96 3890 unsigned char *data = transfer->buffer;
97
98
1/2
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 6 taken 3890 times.
3890 if (error)
99 {
100 /* The finger-detect loop is broken; it no longer has a pending
101 * operation. Clear the active flag so that the deactivation
102 * triggered by the session error (or an in-flight cancellation)
103 * can complete. */
104 self->active = FALSE;
105
106 if (self->deactivating)
107 complete_deactivation (dev);
108 else
109 fpi_image_device_session_error (dev, error);
110 return;
111 }
112
113 3890 fp_dbg ("transfer completed, len: %.4x, data: %.2x %.2x",
114 (gint) transfer->actual_length, (int) data[0], (int) data[1]);
115
116 /* Check if we got 2 bytes, reg address 0x83 and its value */
117
4/6
✓ Branch 7 → 8 taken 3890 times.
✗ Branch 7 → 12 not taken.
✓ Branch 8 → 9 taken 3890 times.
✗ Branch 8 → 12 not taken.
✓ Branch 9 → 10 taken 2 times.
✓ Branch 9 → 12 taken 3888 times.
3890 if ((transfer->actual_length >= 2) && (data[0] == 0x83) && (data[1] & AES2550_REG83_FINGER_PRESENT))
118 {
119 /* finger present, start capturing */
120 2 fpi_image_device_report_finger_status (dev, TRUE);
121 2 start_capture (dev);
122 }
123 else
124 {
125 /* no finger, poll for a new histogram */
126 3888 start_finger_detection (dev);
127 }
128 }
129
130 static void
131 3890 finger_det_reqs_cb (FpiUsbTransfer *t, FpDevice *device,
132 gpointer user_data, GError *error)
133 {
134 3890 FpiUsbTransfer *transfer;
135 3890 FpImageDevice *dev = FP_IMAGE_DEVICE (device);
136 3890 FpiDeviceAes2550 *self = FPI_DEVICE_AES2550 (device);
137
138
1/2
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 6 taken 3890 times.
3890 if (error)
139 {
140 /* The finger-detect loop is broken; it no longer has a pending
141 * operation. Clear the active flag so that the deactivation
142 * triggered by the session error (or an in-flight cancellation)
143 * can complete. */
144 self->active = FALSE;
145
146 if (self->deactivating)
147 complete_deactivation (dev);
148 else
149 fpi_image_device_session_error (dev, error);
150 return;
151 }
152
153 3890 transfer = fpi_usb_transfer_new (device);
154 /* 2 bytes of result */
155 3890 fpi_usb_transfer_fill_bulk (transfer, EP_IN, AES2550_EP_IN_BUF_SIZE);
156 3890 fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
157 finger_det_data_cb, NULL);
158 }
159
160 static void
161 3890 start_finger_detection (FpImageDevice *dev)
162 {
163 3890 FpiDeviceAes2550 *self = FPI_DEVICE_AES2550 (dev);
164 3890 FpiUsbTransfer *transfer;
165
166 3890 G_DEBUG_HERE ();
167
168
1/2
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 7 taken 3890 times.
3890 if (self->deactivating)
169 {
170 complete_deactivation (dev);
171 return;
172 }
173
174 3890 transfer = fpi_usb_transfer_new (FP_DEVICE (dev));
175 3890 transfer->short_is_error = TRUE;
176 3890 fpi_usb_transfer_fill_bulk_full (transfer, EP_OUT, finger_det_reqs,
177 sizeof (finger_det_reqs), NULL);
178 3890 fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
179 finger_det_reqs_cb, NULL);
180 }
181
182 /****** CAPTURE ******/
183
184 static unsigned char capture_reqs[] = {
185 0x80, AES2550_REG80_MASTER_RESET,
186 0x80, (1 << AES2550_REG80_SENSOR_MODE_OFS) | (AES2550_REG80_HGC_ENABLE),
187 0x85, AES2550_REG85_FLUSH_PER_FRAME,
188 0x8f, AES2550_REG8F_AUTH_DISABLE | AES2550_REG8F_EHISTO_DISABLE,
189 0xbf, AES2550_REGBF_RSR_DIR_UPDOWN_MOTION | AES2550_REGBF_RSR_LEVEL_SUPER_RSR,
190 0xcf, (3 << AES2550_REGCF_INTERFERENCE_AVG_OFFS) | AES2550_REGCF_INTERFERENCE_AVG_EN,
191 0xdc, (1 << AES2550_REGDC_BP_NUM_REF_SWEEP_OFS),
192 AES2550_CMD_HEARTBEAT, 0x00, 0x01, 0x03, /* Heart beat cmd, 3 * 16 cycles without sending image */
193 AES2550_CMD_GET_ENROLL_IMG,
194 };
195
196 static unsigned char capture_set_idle_reqs[] = {
197 0x80, AES2550_REG80_MASTER_RESET,
198 AES2550_CMD_HEARTBEAT, 0x00, 0x01, 0x00, /* Heart beat off */
199 AES2550_CMD_SET_IDLE_MODE,
200 };
201
202 enum capture_states {
203 CAPTURE_WRITE_REQS,
204 CAPTURE_READ_DATA,
205 CAPTURE_SET_IDLE,
206 CAPTURE_NUM_STATES,
207 };
208
209 /* Returns number of processed bytes */
210 static gboolean
211 135 process_strip_data (FpiSsm *ssm, FpImageDevice *dev,
212 unsigned char *data)
213 {
214 135 unsigned char *stripdata;
215 135 FpiDeviceAes2550 *self = FPI_DEVICE_AES2550 (dev);
216 135 struct fpi_frame *stripe;
217 135 int len;
218
219
1/2
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 5 taken 135 times.
135 if (data[0] != AES2550_EDATA_MAGIC)
220 {
221 fp_dbg ("Bogus magic: %.2x", (int) (data[0]));
222 return FALSE;
223 }
224 135 len = data[1] * 256 + data[2];
225
1/2
✗ Branch 5 → 6 not taken.
✓ Branch 5 → 7 taken 135 times.
135 if (len != (AES2550_STRIP_SIZE - 3))
226 fp_dbg ("Bogus frame len: %.4x", len);
227 135 stripe = g_malloc0 (FRAME_WIDTH * FRAME_HEIGHT / 2 + sizeof (struct fpi_frame)); /* 4 bits per pixel */
228 135 stripe->delta_x = (int8_t) data[6];
229 135 stripe->delta_y = -(int8_t) data[7];
230 135 stripdata = stripe->data;
231 135 memcpy (stripdata, data + 33, FRAME_WIDTH * FRAME_HEIGHT / 2);
232 135 self->strips = g_slist_prepend (self->strips, stripe);
233 135 self->strips_len++;
234
235 135 fp_dbg ("deltas: %dx%d", stripe->delta_x, stripe->delta_y);
236
237 135 return TRUE;
238 }
239
240 static void
241 2 capture_set_idle_reqs_cb (FpiUsbTransfer *transfer,
242 FpDevice *device, gpointer user_data,
243 GError *error)
244 {
245 2 FpImageDevice *dev = FP_IMAGE_DEVICE (device);
246 2 FpiDeviceAes2550 *self = FPI_DEVICE_AES2550 (dev);
247
248
3/4
✓ Branch 2 → 3 taken 2 times.
✗ Branch 2 → 14 not taken.
✓ Branch 3 → 4 taken 1 time.
✓ Branch 3 → 11 taken 1 time.
2 if (!error && self->strips_len)
249 1 {
250 1 FpImage *img;
251
252 1 self->strips = g_slist_reverse (self->strips);
253 1 img = fpi_assemble_frames (&assembling_ctx, self->strips);
254 1 img->flags |= FPI_IMAGE_PARTIAL;
255 1 g_slist_free_full (self->strips, g_free);
256 1 self->strips = NULL;
257 1 self->strips_len = 0;
258 1 fpi_image_device_image_captured (dev, img);
259 1 fpi_image_device_report_finger_status (dev, FALSE);
260 /* marking machine complete will re-trigger finger detection loop */
261 1 fpi_ssm_mark_completed (transfer->ssm);
262 }
263 1 else if (!error)
264 {
265 /* No image frames were captured (e.g. user tapped without swiping).
266 * Such case is quite easy to happen, since Super RSR is enabled and
267 * thus "Slices with 0-3 pixels of Y motion are discarded" according
268 * to the design specification manual. */
269 1 fpi_image_device_retry_scan (dev, FP_DEVICE_RETRY_TOO_SHORT);
270 1 fpi_image_device_report_finger_status (dev, FALSE);
271 1 fpi_ssm_mark_completed (transfer->ssm);
272 }
273 else
274 {
275 fpi_ssm_mark_failed (transfer->ssm, error);
276 }
277 2 }
278
279 static void
280 143 capture_read_data_cb (FpiUsbTransfer *transfer, FpDevice *device,
281 gpointer user_data, GError *error)
282 {
283 143 FpImageDevice *dev = FP_IMAGE_DEVICE (device);
284 143 FpiDeviceAes2550 *self = FPI_DEVICE_AES2550 (dev);
285 143 unsigned char *data = transfer->buffer;
286
287
1/2
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 5 taken 143 times.
143 if (error)
288 {
289 fpi_ssm_mark_failed (transfer->ssm, error);
290 return;
291 }
292
293 143 fp_dbg ("request completed, len: %.4x", (gint) transfer->actual_length);
294
2/2
✓ Branch 6 → 7 taken 142 times.
✓ Branch 6 → 8 taken 1 time.
143 if (transfer->actual_length >= 2)
295 142 fp_dbg ("data: %.2x %.2x", (int) data[0], (int) data[1]);
296
297
3/3
✓ Branch 8 → 9 taken 135 times.
✓ Branch 8 → 17 taken 7 times.
✓ Branch 8 → 22 taken 1 time.
143 switch (transfer->actual_length)
298 {
299 135 case AES2550_STRIP_SIZE:
300
1/2
✗ Branch 10 → 11 not taken.
✓ Branch 10 → 15 taken 135 times.
135 if (!process_strip_data (transfer->ssm, dev, data))
301 {
302 fp_dbg ("Processing strip data failed");
303 fpi_ssm_mark_failed (transfer->ssm,
304 fpi_device_error_new (FP_DEVICE_ERROR_PROTO));
305 return;
306 }
307 135 self->heartbeat_cnt = 0;
308 135 fpi_ssm_jump_to_state (transfer->ssm, CAPTURE_READ_DATA);
309 135 break;
310
311 7 case AES2550_HEARTBEAT_SIZE:
312
1/2
✓ Branch 17 → 18 taken 7 times.
✗ Branch 17 → 25 not taken.
7 if (data[0] == AES2550_HEARTBEAT_MAGIC)
313 {
314 /* No data for a long time => finger was removed or there's no movement */
315 7 self->heartbeat_cnt++;
316
2/2
✓ Branch 18 → 19 taken 2 times.
✓ Branch 18 → 21 taken 5 times.
7 if (self->heartbeat_cnt == 3)
317 {
318 /* Got 3 heartbeat message, that's enough to consider that finger was removed,
319 * assemble image and submit it to the library */
320 2 fp_dbg ("Got 3 heartbeats => finger removed");
321 2 fpi_ssm_next_state (transfer->ssm);
322 }
323 else
324 {
325 5 fpi_ssm_jump_to_state (transfer->ssm,
326 CAPTURE_READ_DATA);
327 }
328 }
329 break;
330
331 1 default:
332 1 fp_dbg ("Short frame %d, skip",
333 (gint) transfer->actual_length);
334 1 fpi_ssm_jump_to_state (transfer->ssm, CAPTURE_READ_DATA);
335 1 break;
336 }
337 }
338
339 static void
340 147 capture_run_state (FpiSsm *ssm, FpDevice *dev)
341 {
342
3/4
✓ Branch 3 → 4 taken 2 times.
✓ Branch 3 → 8 taken 143 times.
✓ Branch 3 → 12 taken 2 times.
✗ Branch 3 → 16 not taken.
147 switch (fpi_ssm_get_cur_state (ssm))
343 {
344 2 case CAPTURE_WRITE_REQS:
345 {
346 2 FpiUsbTransfer *transfer = fpi_usb_transfer_new (dev);
347
348 2 fpi_usb_transfer_fill_bulk_full (transfer, EP_OUT, capture_reqs,
349 sizeof (capture_reqs), NULL);
350 2 transfer->ssm = ssm;
351 2 transfer->short_is_error = TRUE;
352 2 fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
353 fpi_ssm_usb_transfer_cb, NULL);
354 }
355 2 break;
356
357 143 case CAPTURE_READ_DATA:
358 {
359 143 FpiUsbTransfer *transfer = fpi_usb_transfer_new (dev);
360
361 143 fpi_usb_transfer_fill_bulk (transfer, EP_IN, AES2550_EP_IN_BUF_SIZE);
362 143 transfer->ssm = ssm;
363 143 fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
364 capture_read_data_cb, NULL);
365 }
366 143 break;
367
368 2 case CAPTURE_SET_IDLE:
369 {
370 2 FpiUsbTransfer *transfer = fpi_usb_transfer_new (dev);
371
372 2 fpi_usb_transfer_fill_bulk_full (transfer, EP_OUT,
373 capture_set_idle_reqs,
374 sizeof (capture_set_idle_reqs),
375 NULL);
376 2 transfer->ssm = ssm;
377 2 transfer->short_is_error = TRUE;
378 2 fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
379 capture_set_idle_reqs_cb, NULL);
380 }
381 2 break;
382 }
383 147 ;
384 147 }
385
386 static void
387 2 capture_sm_complete (FpiSsm *ssm, FpDevice *_dev, GError *error)
388 {
389 2 FpiDeviceAes2550 *self = FPI_DEVICE_AES2550 (_dev);
390 2 FpImageDevice *dev = FP_IMAGE_DEVICE (self);
391
392 2 fp_dbg ("Capture completed");
393
394
1/2
✓ Branch 3 → 4 taken 2 times.
✗ Branch 3 → 7 not taken.
2 if (self->deactivating)
395 {
396 2 complete_deactivation (dev);
397
1/2
✗ Branch 5 → 6 not taken.
✓ Branch 5 → 10 taken 2 times.
2 g_clear_pointer (&error, g_error_free);
398 }
399 else if (error)
400 {
401 /* The capture SSM has terminated, so no completion handler is left
402 * to observe the deactivation that the session error triggers.
403 * Clear the active flag so dev_deactivate() completes it directly.
404 */
405 self->active = FALSE;
406 fpi_image_device_session_error (dev, error);
407 }
408 else
409 {
410 start_finger_detection (dev);
411 }
412 2 }
413
414 static void
415 2 start_capture (FpImageDevice *dev)
416 {
417 2 FpiDeviceAes2550 *self = FPI_DEVICE_AES2550 (dev);
418 2 FpiSsm *ssm;
419
420
1/2
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 5 taken 2 times.
2 if (self->deactivating)
421 {
422 complete_deactivation (dev);
423 return;
424 }
425
426 2 self->heartbeat_cnt = 0;
427 2 ssm = fpi_ssm_new (FP_DEVICE (dev), capture_run_state, CAPTURE_NUM_STATES);
428 2 G_DEBUG_HERE ();
429 2 fpi_ssm_start (ssm, capture_sm_complete);
430 }
431
432 /****** INITIALIZATION/DEINITIALIZATION ******/
433
434 static unsigned char init_reqs[] = {
435 0x80, AES2550_REG80_MASTER_RESET, /* Master reset */
436 0x80, (1 << AES2550_REG80_SENSOR_MODE_OFS) | (AES2550_REG80_FORCE_FINGER_PRESENT),
437 0x85, AES2550_REG85_FLUSH_PER_FRAME,
438 0xa8, AES2550_REGA8_DIG_BIT_EN,
439 0x81, AES2550_REG81_NSHOT,
440 };
441
442 static unsigned char calibrate_reqs[] = {
443 0x80, AES2550_REG80_MASTER_RESET, /* Master reset */
444 AES2550_CMD_CALIBRATE,
445 AES2550_CMD_READ_CALIBRATION_DATA,
446 };
447
448 enum activate_states {
449 WRITE_INIT,
450 READ_DATA,
451 CALIBRATE,
452 READ_CALIB_TABLE,
453 ACTIVATE_NUM_STATES,
454 };
455
456 /* TODO: use calibration table, datasheet is rather terse on that
457 * need more info for implementation */
458 static void
459 2 calibrate_read_data_cb (FpiUsbTransfer *transfer, FpDevice *device,
460 gpointer user_data, GError *error)
461 {
462 2 fpi_ssm_usb_transfer_cb (transfer, device, user_data, error);
463 2 }
464
465 static void
466 8 activate_run_state (FpiSsm *ssm, FpDevice *dev)
467 {
468
4/5
✓ Branch 3 → 4 taken 2 times.
✓ Branch 3 → 8 taken 2 times.
✓ Branch 3 → 12 taken 2 times.
✓ Branch 3 → 16 taken 2 times.
✗ Branch 3 → 20 not taken.
8 switch (fpi_ssm_get_cur_state (ssm))
469 {
470 2 case WRITE_INIT:
471 {
472 2 FpiUsbTransfer *transfer = fpi_usb_transfer_new (dev);
473
474 2 fpi_usb_transfer_fill_bulk_full (transfer, EP_OUT, init_reqs,
475 sizeof (init_reqs), NULL);
476 2 transfer->ssm = ssm;
477 2 transfer->short_is_error = TRUE;
478 2 fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
479 fpi_ssm_usb_transfer_cb, NULL);
480 }
481 2 break;
482
483 2 case READ_DATA:
484 {
485 2 FpiUsbTransfer *transfer = fpi_usb_transfer_new (dev);
486
487 2 fpi_usb_transfer_fill_bulk (transfer, EP_IN, AES2550_EP_IN_BUF_SIZE);
488 2 transfer->ssm = ssm;
489 2 fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
490 fpi_ssm_usb_transfer_cb, NULL);
491 }
492 2 break;
493
494 2 case CALIBRATE:
495 {
496 2 FpiUsbTransfer *transfer = fpi_usb_transfer_new (dev);
497
498 2 fpi_usb_transfer_fill_bulk_full (transfer, EP_OUT,
499 calibrate_reqs,
500 sizeof (calibrate_reqs), NULL);
501 2 transfer->ssm = ssm;
502 2 transfer->short_is_error = TRUE;
503 2 fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
504 fpi_ssm_usb_transfer_cb, NULL);
505 }
506 2 break;
507
508 2 case READ_CALIB_TABLE:
509 {
510 2 FpiUsbTransfer *transfer = fpi_usb_transfer_new (dev);
511
512 2 fpi_usb_transfer_fill_bulk (transfer, EP_IN, AES2550_EP_IN_BUF_SIZE);
513 2 transfer->ssm = ssm;
514 2 fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
515 calibrate_read_data_cb, NULL);
516 }
517 2 break;
518 }
519 8 }
520
521 static void
522 2 activate_sm_complete (FpiSsm *ssm, FpDevice *_dev, GError *error)
523 {
524 2 FpiDeviceAes2550 *self = FPI_DEVICE_AES2550 (_dev);
525 2 FpImageDevice *dev = FP_IMAGE_DEVICE (_dev);
526
527 2 fpi_image_device_activate_complete (dev, error);
528
529
1/2
✓ Branch 3 → 4 taken 2 times.
✗ Branch 3 → 5 not taken.
2 if (!error)
530 {
531 2 self->active = TRUE;
532 2 start_finger_detection (dev);
533 }
534 2 }
535
536 static void
537 2 dev_activate (FpImageDevice *dev)
538 {
539 2 FpiSsm *ssm = fpi_ssm_new (FP_DEVICE (dev), activate_run_state,
540 ACTIVATE_NUM_STATES);
541
542 2 fpi_ssm_start (ssm, activate_sm_complete);
543 2 }
544
545 static void
546 2 dev_deactivate (FpImageDevice *dev)
547 {
548 2 FpiDeviceAes2550 *self = FPI_DEVICE_AES2550 (dev);
549
550
1/2
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 5 taken 2 times.
2 if (!self->active)
551 {
552 /* No operation is pending, so complete it right away. */
553 complete_deactivation (dev);
554 return;
555 }
556
557 2 self->deactivating = TRUE;
558 }
559
560 static void
561 2 complete_deactivation (FpImageDevice *dev)
562 {
563 2 FpiDeviceAes2550 *self = FPI_DEVICE_AES2550 (dev);
564
565 2 G_DEBUG_HERE ();
566
567 2 self->deactivating = FALSE;
568 2 self->active = FALSE;
569 2 g_slist_free (self->strips);
570 2 self->strips = NULL;
571 2 self->strips_len = 0;
572 2 fpi_image_device_deactivate_complete (dev, NULL);
573 2 }
574
575 static void
576 2 dev_init (FpImageDevice *dev)
577 {
578 2 GError *error = NULL;
579
580 /* TODO check that device has endpoints we're using */
581
582 2 g_usb_device_claim_interface (fpi_device_get_usb_device (FP_DEVICE (dev)), 0, 0, &error);
583
584 2 fpi_image_device_open_complete (dev, error);
585 2 }
586
587 static void
588 2 dev_deinit (FpImageDevice *dev)
589 {
590 2 GError *error = NULL;
591
592 2 g_usb_device_release_interface (fpi_device_get_usb_device (FP_DEVICE (dev)),
593 0, 0, &error);
594 2 fpi_image_device_close_complete (dev, error);
595 2 }
596
597 static const FpIdEntry id_table[] = {
598 { .vid = 0x08ff, .pid = 0x2550, },/* AES2550 */
599 { .vid = 0x08ff, .pid = 0x2810, },/* AES2810 */
600 { .vid = 0, .pid = 0, .driver_data = 0 },
601 };
602
603 static void
604 2 fpi_device_aes2550_init (FpiDeviceAes2550 *self)
605 {
606 2 }
607 static void
608 127 fpi_device_aes2550_class_init (FpiDeviceAes2550Class *klass)
609 {
610 127 FpDeviceClass *dev_class = FP_DEVICE_CLASS (klass);
611 127 FpImageDeviceClass *img_class = FP_IMAGE_DEVICE_CLASS (klass);
612
613 127 dev_class->id = "aes2550";
614 127 dev_class->full_name = "AuthenTec AES2550/AES2810";
615 127 dev_class->type = FP_DEVICE_TYPE_USB;
616 127 dev_class->id_table = id_table;
617 127 dev_class->scan_type = FP_SCAN_TYPE_SWIPE;
618
619 127 img_class->img_open = dev_init;
620 127 img_class->img_close = dev_deinit;
621 127 img_class->activate = dev_activate;
622 127 img_class->deactivate = dev_deactivate;
623
624 127 img_class->img_width = FRAME_WIDTH + FRAME_WIDTH / 2;
625 127 img_class->img_height = -1;
626 }
627