GCC Code Coverage Report


Directory: ./
File: libfprint/drivers/aes1610.c
Date: 2024-09-16 14:36:32
Exec Total Coverage
Lines: 16 279 5.7%
Functions: 3 23 13.0%
Branches: 4 94 4.3%

Line Branch Exec Source
1 /*
2 * AuthenTec AES1610 driver for libfprint
3 * Copyright (C) 2007-2008 Daniel Drake <dsd@gentoo.org>
4 * Copyright (C) 2007 Cyrille Bagard
5 * Copyright (C) 2007 Vasily Khoruzhick
6 * Copyright (C) 2009 Guido Grazioli <guido.grazioli@gmail.com>
7 * Copyright (C) 2012 Vasily Khoruzhick <anarsoul@gmail.com>
8 *
9 * Based on code from libfprint aes2501 driver.
10 *
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
14 * version 2.1 of the License, or (at your option) any later version.
15 *
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
20 *
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this library; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 */
25
26 #define FP_COMPONENT "aes1610"
27
28 #include "drivers_api.h"
29 #include "aeslib.h"
30
31 static void start_capture (FpImageDevice *dev);
32 static void complete_deactivation (FpImageDevice *dev);
33 static int adjust_gain (unsigned char *buffer,
34 int status);
35
36 #define FIRST_AES1610_REG 0x1B
37 #define LAST_AES1610_REG 0xFF
38
39 #define GAIN_STATUS_FIRST 1
40 #define GAIN_STATUS_NORMAL 2
41
42 /* FIXME these need checking */
43 #define EP_IN (1 | FPI_USB_ENDPOINT_IN)
44 #define EP_OUT (2 | FPI_USB_ENDPOINT_OUT)
45
46 #define BULK_TIMEOUT 4000
47
48 #define FINGER_DETECTION_LEN 19
49 #define STRIP_CAPTURE_LEN 665
50
51 /*
52 * The AES1610 is an imaging device using a swipe-type sensor. It samples
53 * the finger at preprogrammed intervals, sending a 128x8 frame to the
54 * computer.
55 * Unless the user is scanning their finger unreasonably fast, the frames
56 * *will* overlap. The implementation below detects this overlap and produces
57 * a contiguous image as the end result.
58 * The fact that the user determines the length of the swipe (and hence the
59 * number of useful frames) and also the fact that overlap varies means that
60 * images returned from this driver vary in height.
61 */
62
63 #define FRAME_WIDTH 128
64 #define FRAME_HEIGHT 8
65 #define FRAME_SIZE (FRAME_WIDTH * FRAME_HEIGHT)
66 #define IMAGE_WIDTH (FRAME_WIDTH + (FRAME_WIDTH / 2))
67 /* maximum number of frames to read during a scan */
68 /* FIXME reduce substantially */
69 #define MAX_FRAMES 350
70
71 /****** GENERAL FUNCTIONS ******/
72
73 struct _FpiDeviceAes1610
74 {
75 FpImageDevice parent;
76
77 guint8 read_regs_retry_count;
78 GSList *strips;
79 gsize strips_len;
80 gboolean deactivating;
81 guint8 blanks_count;
82 };
83 G_DECLARE_FINAL_TYPE (FpiDeviceAes1610, fpi_device_aes1610, FPI, DEVICE_AES1610,
84 FpImageDevice);
85
4/5
✓ Branch 0 taken 120 times.
✓ Branch 1 taken 24 times.
✓ Branch 2 taken 120 times.
✓ Branch 3 taken 120 times.
✗ Branch 4 not taken.
768 G_DEFINE_TYPE (FpiDeviceAes1610, fpi_device_aes1610, FP_TYPE_IMAGE_DEVICE);
86
87 static struct fpi_frame_asmbl_ctx assembling_ctx = {
88 .frame_width = FRAME_WIDTH,
89 .frame_height = FRAME_HEIGHT,
90 .image_width = IMAGE_WIDTH,
91 .get_pixel = aes_get_pixel,
92 };
93
94 typedef void (*aes1610_read_regs_cb)(FpImageDevice *dev,
95 int status,
96 unsigned char *regs,
97 void *user_data);
98
99 struct aes1610_read_regs
100 {
101 FpImageDevice *dev;
102 aes1610_read_regs_cb callback;
103 struct aes_regwrite *regwrite;
104 void *user_data;
105 };
106
107 /* FIXME: what to do here? */
108 static void
109 stub_capture_stop_cb (FpImageDevice *dev, GError *error,
110 void *user_data)
111 {
112 if (error)
113 {
114 fp_warn ("Error stopping capture: %s", error->message);
115 g_error_free (error);
116 }
117 }
118
119 static void
120 generic_write_regv_cb (FpImageDevice *dev, GError *error,
121 void *user_data)
122 {
123 FpiSsm *ssm = user_data;
124
125 if (!error)
126 fpi_ssm_next_state (ssm);
127 else
128 fpi_ssm_mark_failed (ssm, error);
129 }
130
131 /* read the specified number of bytes from the IN endpoint but throw them
132 * away, then increment the SSM */
133 static void
134 generic_read_ignore_data (FpiSsm *ssm, FpDevice *dev,
135 size_t bytes)
136 {
137 FpiUsbTransfer *transfer = fpi_usb_transfer_new (dev);
138
139 fpi_usb_transfer_fill_bulk (transfer, EP_IN, bytes);
140 transfer->ssm = ssm;
141 transfer->short_is_error = TRUE;
142 fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
143 fpi_ssm_usb_transfer_cb, NULL);
144 }
145
146 /****** FINGER PRESENCE DETECTION ******/
147
148
149 static const struct aes_regwrite finger_det_reqs[] = {
150 { 0x80, 0x01 },
151 { 0x80, 0x12 },
152 { 0x85, 0x00 },
153 { 0x8A, 0x00 },
154 { 0x8B, 0x0E },
155 { 0x8C, 0x90 },
156 { 0x8D, 0x83 },
157 { 0x8E, 0x07 },
158 { 0x8F, 0x07 },
159 { 0x96, 0x00 },
160 { 0x97, 0x48 },
161 { 0xA1, 0x00 },
162 { 0xA2, 0x50 },
163 { 0xA6, 0xE4 },
164 { 0xAD, 0x08 },
165 { 0xAE, 0x5B },
166 { 0xAF, 0x54 },
167 { 0xB1, 0x28 },
168 { 0xB5, 0xAB },
169 { 0xB6, 0x0E },
170 { 0x1B, 0x2D },
171 { 0x81, 0x04 }
172 };
173
174 static void start_finger_detection (FpImageDevice *dev);
175
176 static void
177 finger_det_data_cb (FpiUsbTransfer *transfer, FpDevice *device,
178 gpointer user_data, GError *error)
179 {
180 FpImageDevice *dev = FP_IMAGE_DEVICE (device);
181 unsigned char *data = transfer->buffer;
182 int i;
183 int sum = 0;
184
185 if (error)
186 {
187 fpi_image_device_session_error (dev, error);
188 return;
189 }
190
191 /* examine histogram to determine finger presence */
192 for (i = 3; i < 17; i++)
193 sum += (data[i] & 0xf) + (data[i] >> 4);
194 if (sum > 20)
195 {
196 /* reset default gain */
197 adjust_gain (data, GAIN_STATUS_FIRST);
198 /* finger present, start capturing */
199 fpi_image_device_report_finger_status (dev, TRUE);
200 start_capture (dev);
201 }
202 else
203 {
204 /* no finger, poll for a new histogram */
205 start_finger_detection (dev);
206 }
207 }
208
209 static void
210 finger_det_reqs_cb (FpImageDevice *dev, GError *error,
211 void *user_data)
212 {
213 FpiUsbTransfer *transfer;
214
215 if (error)
216 {
217 fpi_image_device_session_error (dev, error);
218 return;
219 }
220
221 transfer = fpi_usb_transfer_new (FP_DEVICE (dev));
222 fpi_usb_transfer_fill_bulk (transfer, EP_IN, FINGER_DETECTION_LEN);
223 transfer->short_is_error = TRUE;
224 fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
225 finger_det_data_cb, NULL);
226 }
227
228 static void
229 start_finger_detection (FpImageDevice *dev)
230 {
231 FpiDeviceAes1610 *self = FPI_DEVICE_AES1610 (dev);
232
233 if (self->deactivating)
234 {
235 complete_deactivation (dev);
236 return;
237 }
238
239 aes_write_regv (dev, finger_det_reqs, G_N_ELEMENTS (finger_det_reqs), finger_det_reqs_cb, NULL);
240
241 }
242
243 /****** CAPTURE ******/
244
245 static struct aes_regwrite capture_reqs[] = {
246 { 0x80, 0x01 },
247 { 0x80, 0x12 },
248 { 0x84, 0x01 },
249 { 0x85, 0x00 },
250 { 0x89, 0x64 },
251 { 0x8A, 0x00 },
252 { 0x8B, 0x0E },
253 { 0x8C, 0x90 },
254 { 0xBE, 0x23 },
255 { 0x29, 0x04 },
256 { 0x2A, 0xFF },
257 { 0x96, 0x00 },
258 { 0x98, 0x03 },
259 { 0x99, 0x00 },
260 { 0x9C, 0xA5 },
261 { 0x9D, 0x40 },
262 { 0x9E, 0xC6 },
263 { 0x9F, 0x8E },
264 { 0xA2, 0x50 },
265 { 0xA3, 0xF0 },
266 { 0xAD, 0x08 },
267 { 0xBD, 0x4F },
268 { 0xAF, 0x54 },
269 { 0xB1, 0x08 },
270 { 0xB5, 0xAB },
271 { 0x1B, 0x2D },
272 { 0xB6, 0x4E },
273 { 0xB8, 0x70 },
274 { 0x2B, 0xB3 },
275 { 0x2C, 0x5D },
276 { 0x2D, 0x98 },
277 { 0x2E, 0xB0 },
278 { 0x2F, 0x20 },
279 { 0xA2, 0xD0 },
280 { 0x1D, 0x21 },
281 { 0x1E, 0xBE },
282 { 0x1C, 0x00 },
283 { 0x1D, 0x30 },
284 { 0x1E, 0x29 },
285 { 0x1C, 0x01 },
286 { 0x1D, 0x00 },
287 { 0x1E, 0x9E },
288 { 0x1C, 0x02 },
289 { 0x1D, 0x30 },
290 { 0x1E, 0xBB },
291 { 0x1C, 0x03 },
292 { 0x1D, 0x00 },
293 { 0x1E, 0x9D },
294 { 0x1C, 0x04 },
295 { 0x1D, 0x22 },
296 { 0x1E, 0xFF },
297 { 0x1C, 0x05 },
298 { 0x1D, 0x1B },
299 { 0x1E, 0x4E },
300 { 0x1C, 0x06 },
301 { 0x1D, 0x16 },
302 { 0x1E, 0x28 },
303 { 0x1C, 0x07 },
304 { 0x1D, 0x22 },
305 { 0x1E, 0xFF },
306 { 0x1C, 0x08 },
307 { 0x1D, 0x15 },
308 { 0x1E, 0xF1 },
309 { 0x1C, 0x09 },
310 { 0x1D, 0x30 },
311 { 0x1E, 0xD5 },
312 { 0x1C, 0x0A },
313 { 0x1D, 0x00 },
314 { 0x1E, 0x9E },
315 { 0x1C, 0x0B },
316 { 0x1D, 0x17 },
317 { 0x1E, 0x9D },
318 { 0x1C, 0x0C },
319 { 0x1D, 0x28 },
320 { 0x1E, 0xD7 },
321 { 0x1C, 0x0D },
322 { 0x1D, 0x17 },
323 { 0x1E, 0xD7 },
324 { 0x1C, 0x0E },
325 { 0x1D, 0x0A },
326 { 0x1E, 0xCB },
327 { 0x1C, 0x0F },
328 { 0x1D, 0x24 },
329 { 0x1E, 0x14 },
330 { 0x1C, 0x10 },
331 { 0x1D, 0x17 },
332 { 0x1E, 0x85 },
333 { 0x1C, 0x11 },
334 { 0x1D, 0x15 },
335 { 0x1E, 0x71 },
336 { 0x1C, 0x12 },
337 { 0x1D, 0x2B },
338 { 0x1E, 0x36 },
339 { 0x1C, 0x13 },
340 { 0x1D, 0x12 },
341 { 0x1E, 0x06 },
342 { 0x1C, 0x14 },
343 { 0x1D, 0x30 },
344 { 0x1E, 0x97 },
345 { 0x1C, 0x15 },
346 { 0x1D, 0x21 },
347 { 0x1E, 0x32 },
348 { 0x1C, 0x16 },
349 { 0x1D, 0x06 },
350 { 0x1E, 0xE6 },
351 { 0x1C, 0x17 },
352 { 0x1D, 0x16 },
353 { 0x1E, 0x06 },
354 { 0x1C, 0x18 },
355 { 0x1D, 0x30 },
356 { 0x1E, 0x01 },
357 { 0x1C, 0x19 },
358 { 0x1D, 0x21 },
359 { 0x1E, 0x37 },
360 { 0x1C, 0x1A },
361 { 0x1D, 0x00 },
362 { 0x1E, 0x08 },
363 { 0x1C, 0x1B },
364 { 0x1D, 0x80 },
365 { 0x1E, 0xD5 },
366 { 0xA2, 0x50 },
367 { 0xA2, 0x50 },
368 { 0x81, 0x01 }
369 };
370
371 static struct aes_regwrite strip_scan_reqs[] = {
372 { 0xBE, 0x23 },
373 { 0x29, 0x04 },
374 { 0x2A, 0xFF },
375 { 0xBD, 0x4F },
376 { 0xFF, 0x00 }
377 };
378
379 static const struct aes_regwrite capture_stop[] = {
380 { 0x81, 0x00 }
381 };
382
383 /*
384 * The different possible values for 0xBE register */
385 static unsigned char list_BE_values[10] = {
386 0x23, 0x43, 0x63, 0x64, 0x65, 0x67, 0x6A, 0x6B
387 };
388
389 /*
390 * The different possible values for 0xBD register */
391 static unsigned char list_BD_values[10] = {
392 0x28, 0x2b, 0x30, 0x3b, 0x45, 0x49, 0x4B
393 };
394
395 /*
396 * Adjust the gain according to the histogram data
397 * 0xbd, 0xbe, 0x29 and 0x2A registers are affected
398 * Returns 0 if no problem occurred
399 * TODO: This is a basic support for gain. It needs testing/tweaking. */
400 static int
401 adjust_gain (unsigned char *buffer, int status)
402 {
403 // The position in the array of possible values for 0xBE and 0xBD registers
404 static int pos_list_BE = 0;
405 static int pos_list_BD = 0;
406
407 // This is the first adjustment (we begin acquisition)
408 // We adjust strip_scan_reqs for future strips and capture_reqs that is sent just after this step
409 if (status == GAIN_STATUS_FIRST)
410 {
411 if (buffer[1] > 0x78) // maximum gain needed
412 {
413 strip_scan_reqs[0].value = 0x6B;
414 strip_scan_reqs[1].value = 0x06;
415 strip_scan_reqs[2].value = 0x35;
416 strip_scan_reqs[3].value = 0x4B;
417 }
418 else if (buffer[1] > 0x55)
419 {
420 strip_scan_reqs[0].value = 0x63;
421 strip_scan_reqs[1].value = 0x15;
422 strip_scan_reqs[2].value = 0x35;
423 strip_scan_reqs[3].value = 0x3b;
424 }
425 else if (buffer[1] > 0x40 || buffer[16] > 0x19)
426 {
427 strip_scan_reqs[0].value = 0x43;
428 strip_scan_reqs[1].value = 0x13;
429 strip_scan_reqs[2].value = 0x35;
430 strip_scan_reqs[3].value = 0x30;
431 }
432 else // minimum gain needed
433 {
434 strip_scan_reqs[0].value = 0x23;
435 strip_scan_reqs[1].value = 0x07;
436 strip_scan_reqs[2].value = 0x35;
437 strip_scan_reqs[3].value = 0x28;
438 }
439
440 // Now copy this values in capture_reqs
441 capture_reqs[8].value = strip_scan_reqs[0].value;
442 capture_reqs[9].value = strip_scan_reqs[1].value;
443 capture_reqs[10].value = strip_scan_reqs[2].value;
444 capture_reqs[21].value = strip_scan_reqs[3].value;
445
446 fp_dbg ("first gain: %x %x %x %x %x %x %x %x", strip_scan_reqs[0].reg, strip_scan_reqs[0].value, strip_scan_reqs[1].reg, strip_scan_reqs[1].value, strip_scan_reqs[2].reg, strip_scan_reqs[2].value, strip_scan_reqs[3].reg, strip_scan_reqs[3].value);
447 }
448 // Every 2/3 strips
449 // We try to soften big changes of the gain (at least for 0xBE and 0xBD
450 // FIXME: This softenning will need testing and tweaking too
451 else if (status == GAIN_STATUS_NORMAL)
452 {
453 if (buffer[514] > 0x78) // maximum gain needed
454 {
455 if (pos_list_BE < 7)
456 pos_list_BE++;
457
458 if (pos_list_BD < 6)
459 pos_list_BD++;
460
461 strip_scan_reqs[1].value = 0x04;
462 strip_scan_reqs[2].value = 0x35;
463 }
464 else if (buffer[514] > 0x55)
465 {
466 if (pos_list_BE < 2)
467 pos_list_BE++;
468 else if (pos_list_BE > 2)
469 pos_list_BE--;
470
471 if (pos_list_BD < 2)
472 pos_list_BD++;
473 else if (pos_list_BD > 2)
474 pos_list_BD--;
475
476 strip_scan_reqs[1].value = 0x15;
477 strip_scan_reqs[2].value = 0x35;
478 }
479 else if (buffer[514] > 0x40 || buffer[529] > 0x19)
480 {
481 if (pos_list_BE < 1)
482 pos_list_BE++;
483 else if (pos_list_BE > 1)
484 pos_list_BE--;
485
486 if (pos_list_BD < 1)
487 pos_list_BD++;
488 else if (pos_list_BD > 1)
489 pos_list_BD--;
490
491 strip_scan_reqs[1].value = 0x13;
492 strip_scan_reqs[2].value = 0x35;
493 }
494 else // minimum gain needed
495 {
496 if (pos_list_BE > 0)
497 pos_list_BE--;
498
499 if (pos_list_BD > 0)
500 pos_list_BD--;
501
502 strip_scan_reqs[1].value = 0x07;
503 strip_scan_reqs[2].value = 0x35;
504 }
505
506 strip_scan_reqs[0].value = list_BE_values[pos_list_BE];
507 strip_scan_reqs[3].value = list_BD_values[pos_list_BD];
508
509 fp_dbg ("gain: %x %x %x %x %x %x %x %x", strip_scan_reqs[0].reg, strip_scan_reqs[0].value, strip_scan_reqs[1].reg, strip_scan_reqs[1].value, strip_scan_reqs[2].reg, strip_scan_reqs[2].value, strip_scan_reqs[3].reg, strip_scan_reqs[3].value);
510 }
511 // Unknown status
512 else
513 {
514 fp_err ("Unexpected gain status.");
515 return 1;
516 }
517
518 return 0;
519 }
520
521 /*
522 * Restore the default gain values */
523 static void
524 restore_gain (void)
525 {
526 strip_scan_reqs[0].value = list_BE_values[0];
527 strip_scan_reqs[1].value = 0x04;
528 strip_scan_reqs[2].value = 0xFF;
529 strip_scan_reqs[3].value = list_BD_values[0];
530
531 capture_reqs[8].value = list_BE_values[0];
532 capture_reqs[9].value = 0x04;
533 capture_reqs[10].value = 0xFF;
534 capture_reqs[21].value = list_BD_values[0];
535 }
536
537
538 /* capture SM movement:
539 * request and read strip,
540 * jump back to request UNLESS there's no finger, in which case exit SM,
541 * report lack of finger presence, and move to finger detection */
542
543 enum capture_states {
544 CAPTURE_WRITE_REQS,
545 CAPTURE_READ_DATA,
546 CAPTURE_REQUEST_STRIP,
547 CAPTURE_READ_STRIP,
548 CAPTURE_NUM_STATES,
549 };
550
551 static void
552 capture_read_strip_cb (FpiUsbTransfer *transfer, FpDevice *device,
553 gpointer user_data, GError *error)
554 {
555 unsigned char *stripdata;
556 FpImageDevice *dev = FP_IMAGE_DEVICE (device);
557 FpiDeviceAes1610 *self = FPI_DEVICE_AES1610 (dev);
558 unsigned char *data = transfer->buffer;
559 gint sum, i;
560
561 if (error)
562 {
563 fpi_ssm_mark_failed (transfer->ssm, error);
564 return;
565 }
566
567 /* FIXME: would preallocating strip buffers be a decent optimization? */
568
569 sum = 0;
570 for (i = 516; i < 530; i++)
571 /* histogram[i] = number of pixels of value i
572 Only the pixel values from 10 to 15 are used to detect finger. */
573 sum += data[i];
574
575 fp_dbg ("sum=%d", sum);
576 if (sum > 0)
577 {
578 /* FIXME: would preallocating strip buffers be a decent optimization? */
579 struct fpi_frame *stripe = g_malloc (FRAME_WIDTH * (FRAME_HEIGHT / 2) + sizeof (struct fpi_frame));
580 stripe->delta_x = 0;
581 stripe->delta_y = 0;
582 stripdata = stripe->data;
583 memcpy (stripdata, data + 1, FRAME_WIDTH * (FRAME_HEIGHT / 2));
584 self->strips = g_slist_prepend (self->strips, stripe);
585 self->strips_len++;
586 self->blanks_count = 0;
587 }
588 else
589 {
590 /* FIXME: 0 might be too low as a threshold */
591 /* FIXME: sometimes we get 0 in the middle of a scan, should we wait for
592 * a few consecutive zeroes? */
593
594 /* sum cannot be negative, so is 0 */
595 self->blanks_count++;
596 fp_dbg ("got blank frame");
597 }
598
599
600 /* use histogram data above for gain calibration (0xbd, 0xbe, 0x29 and 0x2A ) */
601 adjust_gain (data, GAIN_STATUS_NORMAL);
602
603 /* stop capturing if MAX_FRAMES is reached */
604 if (self->blanks_count > 10 || g_slist_length (self->strips) >= MAX_FRAMES)
605 {
606 FpImage *img;
607
608 fp_dbg ("sending stop capture.... blanks=%d frames=%d",
609 self->blanks_count, g_slist_length (self->strips));
610 /* send stop capture bits */
611 aes_write_regv (dev, capture_stop, G_N_ELEMENTS (capture_stop), stub_capture_stop_cb, NULL);
612 self->strips = g_slist_reverse (self->strips);
613 fpi_do_movement_estimation (&assembling_ctx, self->strips);
614 img = fpi_assemble_frames (&assembling_ctx, self->strips);
615 img->flags |= FPI_IMAGE_PARTIAL;
616
617 g_slist_free_full (self->strips, g_free);
618 self->strips = NULL;
619 self->strips_len = 0;
620 self->blanks_count = 0;
621 fpi_image_device_image_captured (dev, img);
622 fpi_image_device_report_finger_status (dev, FALSE);
623 /* marking machine complete will re-trigger finger detection loop */
624 fpi_ssm_mark_completed (transfer->ssm);
625 /* Acquisition finished: restore default gain values */
626 restore_gain ();
627 }
628 else
629 {
630 /* obtain next strip */
631 fpi_ssm_jump_to_state (transfer->ssm, CAPTURE_REQUEST_STRIP);
632 }
633 }
634
635 static void
636 capture_run_state (FpiSsm *ssm, FpDevice *_dev)
637 {
638 FpImageDevice *dev = FP_IMAGE_DEVICE (_dev);
639 FpiDeviceAes1610 *self = FPI_DEVICE_AES1610 (_dev);
640
641 switch (fpi_ssm_get_cur_state (ssm))
642 {
643 case CAPTURE_WRITE_REQS:
644 fp_dbg ("write reqs");
645 aes_write_regv (dev, capture_reqs, G_N_ELEMENTS (capture_reqs),
646 generic_write_regv_cb, ssm);
647 break;
648
649 case CAPTURE_READ_DATA:
650 fp_dbg ("read data");
651 generic_read_ignore_data (ssm, _dev, STRIP_CAPTURE_LEN);
652 break;
653
654 case CAPTURE_REQUEST_STRIP:
655 fp_dbg ("request strip");
656 if (self->deactivating)
657 fpi_ssm_mark_completed (ssm);
658 else
659 aes_write_regv (dev, strip_scan_reqs, G_N_ELEMENTS (strip_scan_reqs),
660 generic_write_regv_cb, ssm);
661 break;
662
663 case CAPTURE_READ_STRIP:;
664 FpiUsbTransfer *transfer = fpi_usb_transfer_new (_dev);
665
666 fpi_usb_transfer_fill_bulk (transfer, EP_IN, STRIP_CAPTURE_LEN);
667 transfer->ssm = ssm;
668 transfer->short_is_error = TRUE;
669 fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL,
670 capture_read_strip_cb, NULL);
671 break;
672 }
673 ;
674 }
675
676 static void
677 capture_sm_complete (FpiSsm *ssm, FpDevice *_dev, GError *error)
678 {
679 FpImageDevice *dev = FP_IMAGE_DEVICE (_dev);
680 FpiDeviceAes1610 *self = FPI_DEVICE_AES1610 (_dev);
681
682 G_DEBUG_HERE ();
683 if (self->deactivating)
684 {
685 complete_deactivation (dev);
686 if (error)
687 g_error_free (error);
688 }
689 else if (error)
690 {
691 fpi_image_device_session_error (dev, error);
692 }
693 else
694 {
695 start_finger_detection (dev);
696 }
697 }
698
699 static void
700 start_capture (FpImageDevice *dev)
701 {
702 FpiDeviceAes1610 *self = FPI_DEVICE_AES1610 (dev);
703 FpiSsm *ssm;
704
705 if (self->deactivating)
706 {
707 complete_deactivation (dev);
708 return;
709 }
710
711 ssm = fpi_ssm_new (FP_DEVICE (dev), capture_run_state,
712 CAPTURE_NUM_STATES);
713 G_DEBUG_HERE ();
714 fpi_ssm_start (ssm, capture_sm_complete);
715 }
716
717 /****** INITIALIZATION/DEINITIALIZATION ******/
718
719 static const struct aes_regwrite init[] = {
720 { 0x82, 0x00 }
721 };
722
723 /*
724 static const struct aes_regwrite stop_reader[] = {
725 { 0xFF, 0x00 }
726 };
727 */
728
729 enum activate_states {
730 WRITE_INIT,
731 ACTIVATE_NUM_STATES,
732 };
733
734 static void
735 activate_run_state (FpiSsm *ssm, FpDevice *_dev)
736 {
737 FpImageDevice *dev = FP_IMAGE_DEVICE (_dev);
738
739 /* activation on aes1610 seems much more straightforward compared to aes2501 */
740 /* verify there's anything missing here */
741 switch (fpi_ssm_get_cur_state (ssm))
742 {
743 case WRITE_INIT:
744 fp_dbg ("write init");
745 aes_write_regv (dev, init, G_N_ELEMENTS (init), generic_write_regv_cb, ssm);
746 break;
747 }
748 }
749
750 /* jump to finger detection */
751 static void
752 activate_sm_complete (FpiSsm *ssm, FpDevice *_dev, GError *error)
753 {
754 FpImageDevice *dev = FP_IMAGE_DEVICE (_dev);
755
756 fpi_image_device_activate_complete (dev, error);
757
758 if (!error)
759 start_finger_detection (dev);
760 }
761
762 static void
763 dev_activate (FpImageDevice *dev)
764 {
765 FpiDeviceAes1610 *self = FPI_DEVICE_AES1610 (dev);
766 FpiSsm *ssm = fpi_ssm_new (FP_DEVICE (dev), activate_run_state,
767 ACTIVATE_NUM_STATES);
768
769 self->read_regs_retry_count = 0;
770 fpi_ssm_start (ssm, activate_sm_complete);
771 }
772
773 static void
774 dev_deactivate (FpImageDevice *dev)
775 {
776 FpiDeviceAes1610 *self = FPI_DEVICE_AES1610 (dev);
777
778 /* FIXME: audit cancellation points, probably need more, specifically
779 * in error handling paths? */
780 self->deactivating = TRUE;
781 }
782
783 static void
784 complete_deactivation (FpImageDevice *dev)
785 {
786 FpiDeviceAes1610 *self = FPI_DEVICE_AES1610 (dev);
787
788 G_DEBUG_HERE ();
789
790 /* FIXME: if we're in the middle of a scan, we should cancel the scan.
791 * maybe we can do this with a master reset, unconditionally? */
792
793 self->deactivating = FALSE;
794 g_slist_free (self->strips);
795 self->strips = NULL;
796 self->strips_len = 0;
797 self->blanks_count = 0;
798 fpi_image_device_deactivate_complete (dev, NULL);
799 }
800
801 static void
802 dev_init (FpImageDevice *dev)
803 {
804 GError *error = NULL;
805
806 /* FIXME check endpoints */
807
808 if (!g_usb_device_claim_interface (fpi_device_get_usb_device (FP_DEVICE (dev)), 0, 0, &error))
809 {
810 fpi_image_device_open_complete (dev, error);
811 return;
812 }
813
814 fpi_image_device_open_complete (dev, NULL);
815 }
816
817 static void
818 dev_deinit (FpImageDevice *dev)
819 {
820 GError *error = NULL;
821
822 g_usb_device_release_interface (fpi_device_get_usb_device (FP_DEVICE (dev)),
823 0, 0, &error);
824 fpi_image_device_close_complete (dev, error);
825 }
826
827 static const FpIdEntry id_table[] = {
828 { .vid = 0x08ff, .pid = 0x1600, },/* AES1600 */
829 { .vid = 0, .pid = 0, .driver_data = 0 },
830 };
831
832 static void
833 fpi_device_aes1610_init (FpiDeviceAes1610 *self)
834 {
835 }
836 static void
837 120 fpi_device_aes1610_class_init (FpiDeviceAes1610Class *klass)
838 {
839 120 FpDeviceClass *dev_class = FP_DEVICE_CLASS (klass);
840 120 FpImageDeviceClass *img_class = FP_IMAGE_DEVICE_CLASS (klass);
841
842 120 dev_class->id = "aes1610";
843 120 dev_class->full_name = "AuthenTec AES1610";
844 120 dev_class->type = FP_DEVICE_TYPE_USB;
845 120 dev_class->id_table = id_table;
846 120 dev_class->scan_type = FP_SCAN_TYPE_SWIPE;
847
848 120 img_class->img_open = dev_init;
849 120 img_class->img_close = dev_deinit;
850 120 img_class->activate = dev_activate;
851 120 img_class->deactivate = dev_deactivate;
852
853 120 img_class->bz3_threshold = 20;
854
855 120 img_class->img_width = IMAGE_WIDTH;
856 120 img_class->img_height = -1;
857 }
858