GCC Code Coverage Report


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 3.4% 12 / 0 / 356
Functions: 11.1% 3 / 0 / 27
Branches: 3.7% 4 / 0 / 107

libfprint/drivers/aesx660.c
Line Branch Exec Source
1 /*
2 * AuthenTec AES1660/AES2660 common routines
3 * Copyright (C) 2007-2008 Daniel Drake <dsd@gentoo.org>
4 * Copyright (C) 2007 Cyrille Bagard
5 * Copyright (C) 2007-2008,2012 Vasily Khoruzhick
6 *
7 * Based on AES2550 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 "aesX660"
25
26 #include "drivers_api.h"
27 #include "aeslib.h"
28 #include "aesx660.h"
29
30 typedef struct
31 {
32 GByteArray *stripe_packet;
33 GSList *strips;
34 size_t strips_len;
35 gboolean deactivating;
36 struct aesX660_cmd *init_seq;
37 size_t init_seq_len;
38 unsigned int init_cmd_idx;
39 unsigned int init_seq_idx;
40 } FpiDeviceAesX660Private;
41
42
4/6
fpi_device_aes_x660_class_intern_init:
✓ Branch 3 → 4 taken 125 times.
✗ Branch 3 → 5 not taken.
fpi_device_aes_x660_get_type:
✓ Branch 2 → 3 taken 125 times.
✓ Branch 2 → 7 taken 125 times.
✓ Branch 4 → 5 taken 125 times.
✗ Branch 4 → 7 not taken.
500 G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (FpiDeviceAesX660, fpi_device_aes_x660, FP_TYPE_IMAGE_DEVICE);
43
44 static void start_capture (FpImageDevice *dev);
45 static void complete_deactivation (FpImageDevice *dev);
46
47 #define EP_IN (1 | FPI_USB_ENDPOINT_IN)
48 #define EP_OUT (2 | FPI_USB_ENDPOINT_OUT)
49 #define BULK_TIMEOUT 4000
50 #define FRAME_HEIGHT AESX660_FRAME_HEIGHT
51
52 #define ID_LEN 8
53 #define INIT_LEN 4
54 #define CALIBRATE_DATA_LEN 4
55 #define FINGER_DET_DATA_LEN 4
56
57 FP_GNUC_ACCESS (read_only, 3, 4)
58 static void
59 aesX660_send_cmd_timeout (FpiSsm *ssm,
60 FpDevice *_dev,
61 const unsigned char *cmd,
62 size_t cmd_len,
63 FpiUsbTransferCallback callback,
64 int timeout)
65 {
66 FpiUsbTransfer *transfer = fpi_usb_transfer_new (_dev);
67
68 fpi_usb_transfer_fill_bulk_full (transfer, EP_OUT, (unsigned char *) cmd,
69 cmd_len, NULL);
70 transfer->ssm = ssm;
71 fpi_usb_transfer_submit (transfer, timeout, NULL, callback, NULL);
72 }
73
74 FP_GNUC_ACCESS (read_only, 3, 4)
75 static void
76 aesX660_send_cmd (FpiSsm *ssm,
77 FpDevice *dev,
78 const unsigned char *cmd,
79 size_t cmd_len,
80 FpiUsbTransferCallback callback)
81 {
82 return aesX660_send_cmd_timeout (ssm, dev, cmd, cmd_len, callback, BULK_TIMEOUT);
83 }
84
85 static void
86 aesX660_read_response (FpiSsm *ssm,
87 FpDevice *_dev,
88 gboolean short_is_error,
89 gboolean cancellable,
90 size_t buf_len,
91 FpiUsbTransferCallback callback)
92 {
93 FpiUsbTransfer *transfer = fpi_usb_transfer_new (_dev);
94 GCancellable *cancel = NULL;
95
96 if (cancellable)
97 cancel = fpi_device_get_cancellable (_dev);
98
99 fpi_usb_transfer_fill_bulk (transfer, EP_IN, buf_len);
100 transfer->ssm = ssm;
101 transfer->short_is_error = short_is_error;
102 fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, cancel, callback, NULL);
103 }
104
105 static void
106 aesX660_read_calibrate_data_cb (FpiUsbTransfer *transfer,
107 FpDevice *device,
108 gpointer user_data, GError *error)
109 {
110 unsigned char *data = transfer->buffer;
111
112 if (error)
113 {
114 fpi_ssm_mark_failed (transfer->ssm, error);
115 return;
116 }
117 /* Calibrate response was read correctly? */
118 if (data[AESX660_RESPONSE_TYPE_OFFSET] != AESX660_CALIBRATE_RESPONSE)
119 {
120 fp_dbg ("Bogus calibrate response: %.2x", data[0]);
121 fpi_ssm_mark_failed (transfer->ssm,
122 fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
123 "Bogus calibrate "
124 "response: %.2x",
125 data[0]));
126 return;
127 }
128
129 fpi_ssm_next_state (transfer->ssm);
130 }
131
132 /****** FINGER PRESENCE DETECTION ******/
133
134 enum finger_det_states {
135 FINGER_DET_SEND_LED_CMD,
136 FINGER_DET_SEND_FD_CMD,
137 FINGER_DET_READ_FD_DATA,
138 FINGER_DET_SET_IDLE,
139 FINGER_DET_NUM_STATES,
140 };
141
142 static void
143 finger_det_read_fd_data_cb (FpiUsbTransfer *transfer,
144 FpDevice *device, gpointer user_data,
145 GError *error)
146 {
147 FpiDeviceAesX660 *self = FPI_DEVICE_AES_X660 (device);
148 FpiDeviceAesX660Private *priv = fpi_device_aes_x660_get_instance_private (self);
149 unsigned char *data = transfer->buffer;
150
151 if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
152 {
153 fpi_ssm_next_state (transfer->ssm);
154 return;
155 }
156
157 if (error)
158 {
159 fp_dbg ("Failed to read FD data");
160 fpi_ssm_mark_failed (transfer->ssm, error);
161 return;
162 }
163
164 if (data[AESX660_RESPONSE_TYPE_OFFSET] != AESX660_FINGER_DET_RESPONSE)
165 {
166 fp_dbg ("Bogus FD response: %.2x", data[0]);
167 fpi_ssm_mark_failed (transfer->ssm,
168 fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
169 "Bogus FD response %.2x",
170 data[0]));
171 return;
172 }
173
174 if (data[AESX660_FINGER_PRESENT_OFFSET] == AESX660_FINGER_PRESENT || priv->deactivating)
175 {
176 /* Finger present or we're deactivating... */
177 fpi_ssm_next_state (transfer->ssm);
178 }
179 else
180 {
181 fp_dbg ("Wait for finger returned %.2x as result",
182 data[AESX660_FINGER_PRESENT_OFFSET]);
183 fpi_ssm_jump_to_state (transfer->ssm, FINGER_DET_SEND_FD_CMD);
184 }
185 }
186
187 static void
188 finger_det_set_idle_cmd_cb (FpiUsbTransfer *transfer,
189 FpDevice *device, gpointer user_data,
190 GError *error)
191 {
192 if (!error)
193 fpi_ssm_mark_completed (transfer->ssm);
194 else
195 fpi_ssm_mark_failed (transfer->ssm, error);
196 }
197
198 static void
199 finger_det_sm_complete (FpiSsm *ssm, FpDevice *_dev, GError *error)
200 {
201 FpImageDevice *dev = FP_IMAGE_DEVICE (_dev);
202 FpiDeviceAesX660 *self = FPI_DEVICE_AES_X660 (_dev);
203 FpiDeviceAesX660Private *priv = fpi_device_aes_x660_get_instance_private (self);
204
205 fp_dbg ("Finger detection completed");
206 fpi_image_device_report_finger_status (dev, TRUE);
207
208 if (priv->deactivating)
209 {
210 complete_deactivation (dev);
211 if (error)
212 g_error_free (error);
213 }
214 else if (error)
215 {
216 fpi_image_device_session_error (dev, error);
217 }
218 else
219 {
220 fpi_image_device_report_finger_status (dev, TRUE);
221 start_capture (dev);
222 }
223 }
224
225 static void
226 finger_det_run_state (FpiSsm *ssm, FpDevice *dev)
227 {
228 switch (fpi_ssm_get_cur_state (ssm))
229 {
230 case FINGER_DET_SEND_LED_CMD:
231 aesX660_send_cmd (ssm, dev, led_blink_cmd, sizeof (led_blink_cmd),
232 fpi_ssm_usb_transfer_cb);
233 break;
234
235 case FINGER_DET_SEND_FD_CMD:
236 aesX660_send_cmd_timeout (ssm, dev, wait_for_finger_cmd, sizeof (wait_for_finger_cmd),
237 fpi_ssm_usb_transfer_cb, 0);
238 break;
239
240 case FINGER_DET_READ_FD_DATA:
241 aesX660_read_response (ssm, dev, TRUE, TRUE, FINGER_DET_DATA_LEN, finger_det_read_fd_data_cb);
242 break;
243
244 case FINGER_DET_SET_IDLE:
245 aesX660_send_cmd (ssm, dev, set_idle_cmd, sizeof (set_idle_cmd),
246 finger_det_set_idle_cmd_cb);
247 break;
248 }
249 }
250
251 static void
252 start_finger_detection (FpImageDevice *dev)
253 {
254 FpiDeviceAesX660 *self = FPI_DEVICE_AES_X660 (dev);
255 FpiDeviceAesX660Private *priv = fpi_device_aes_x660_get_instance_private (self);
256 FpiSsm *ssm;
257
258 if (priv->deactivating)
259 {
260 complete_deactivation (dev);
261 return;
262 }
263
264 ssm = fpi_ssm_new (FP_DEVICE (dev), finger_det_run_state,
265 FINGER_DET_NUM_STATES);
266 fpi_ssm_start (ssm, finger_det_sm_complete);
267 }
268
269 /****** CAPTURE ******/
270
271 enum capture_states {
272 CAPTURE_SEND_LED_CMD,
273 CAPTURE_SEND_CAPTURE_CMD,
274 CAPTURE_READ_STRIPE_DATA,
275 CAPTURE_SET_IDLE,
276 CAPTURE_NUM_STATES,
277 };
278
279 /* Returns number of processed bytes */
280 static int
281 process_stripe_data (FpiSsm *ssm, FpiDeviceAesX660 *self,
282 unsigned char *data, gsize length)
283 {
284 FpiDeviceAesX660Private *priv = fpi_device_aes_x660_get_instance_private (self);
285 FpiDeviceAesX660Class *cls = FPI_DEVICE_AES_X660_GET_CLASS (self);
286 struct fpi_frame *stripe;
287 unsigned char *stripdata;
288
289 if (length < AESX660_IMAGE_OFFSET + cls->assembling_ctx->frame_width * FRAME_HEIGHT / 2)
290 {
291 fp_warn ("Received stripe data is too short, got %zi expected %i bytes!",
292 length,
293 AESX660_IMAGE_OFFSET + cls->assembling_ctx->frame_width * FRAME_HEIGHT / 2);
294 return 0;
295 }
296
297 stripe = g_malloc (cls->assembling_ctx->frame_width * FRAME_HEIGHT / 2 + sizeof (struct fpi_frame)); /* 4 bpp */
298 stripdata = stripe->data;
299
300 fp_dbg ("Processing frame %.2x %.2x", data[AESX660_IMAGE_OK_OFFSET],
301 data[AESX660_LAST_FRAME_OFFSET]);
302
303 stripe->delta_x = (int8_t) data[AESX660_FRAME_DELTA_X_OFFSET];
304 stripe->delta_y = -(int8_t) data[AESX660_FRAME_DELTA_Y_OFFSET];
305 fp_dbg ("Offset to previous frame: %d %d", stripe->delta_x, stripe->delta_y);
306
307 if (data[AESX660_IMAGE_OK_OFFSET] == AESX660_IMAGE_OK)
308 {
309 memcpy (stripdata, data + AESX660_IMAGE_OFFSET, cls->assembling_ctx->frame_width * FRAME_HEIGHT / 2);
310
311 priv->strips = g_slist_prepend (priv->strips, stripe);
312 priv->strips_len++;
313 return data[AESX660_LAST_FRAME_OFFSET] & AESX660_LAST_FRAME_BIT;
314 }
315
316 g_free (stripe);
317 return 0;
318 }
319
320 static void
321 capture_set_idle_cmd_cb (FpiUsbTransfer *transfer, FpDevice *device,
322 gpointer user_data, GError *error)
323 {
324 FpImageDevice *dev = FP_IMAGE_DEVICE (device);
325 FpiDeviceAesX660 *self = FPI_DEVICE_AES_X660 (device);
326 FpiDeviceAesX660Private *priv = fpi_device_aes_x660_get_instance_private (self);
327 FpiDeviceAesX660Class *cls = FPI_DEVICE_AES_X660_GET_CLASS (self);
328
329 if (!error)
330 {
331 FpImage *img;
332
333 priv->strips = g_slist_reverse (priv->strips);
334 img = fpi_assemble_frames (cls->assembling_ctx, priv->strips);
335 img->flags |= FPI_IMAGE_PARTIAL;
336 g_slist_foreach (priv->strips, (GFunc) g_free, NULL);
337 g_slist_free (priv->strips);
338 priv->strips = NULL;
339 priv->strips_len = 0;
340 fpi_image_device_image_captured (dev, img);
341 fpi_image_device_report_finger_status (dev, FALSE);
342 fpi_ssm_mark_completed (transfer->ssm);
343 }
344 else
345 {
346 fpi_ssm_mark_failed (transfer->ssm, error);
347 }
348 }
349
350 static void
351 capture_read_stripe_data_cb (FpiUsbTransfer *transfer,
352 FpDevice *device, gpointer user_data,
353 GError *error)
354 {
355 FpiDeviceAesX660 *self = FPI_DEVICE_AES_X660 (device);
356 FpiDeviceAesX660Private *priv = fpi_device_aes_x660_get_instance_private (self);
357 unsigned char *data = transfer->buffer;
358 int finger_missing = 0;
359 size_t actual_length = transfer->actual_length;
360
361 if (error)
362 {
363 g_byte_array_set_size (priv->stripe_packet, 0);
364 fpi_ssm_mark_failed (transfer->ssm, error);
365 return;
366 }
367
368 fp_dbg ("Got %" G_GSIZE_FORMAT " bytes of data", actual_length);
369 while (actual_length)
370 {
371 gssize payload_length;
372 gssize still_needed_len;
373 gssize copy_len;
374
375 still_needed_len = MAX (0, AESX660_HEADER_SIZE - (gssize) priv->stripe_packet->len);
376 copy_len = MIN (actual_length, still_needed_len);
377 g_byte_array_append (priv->stripe_packet, data, copy_len);
378 data += copy_len;
379 actual_length -= copy_len;
380
381 /* Do we have a full header? */
382 if (priv->stripe_packet->len < AESX660_HEADER_SIZE)
383 break;
384
385 payload_length = priv->stripe_packet->data[AESX660_RESPONSE_SIZE_LSB_OFFSET] +
386 (priv->stripe_packet->data[AESX660_RESPONSE_SIZE_MSB_OFFSET] << 8);
387
388 if (payload_length > AESX660_BULK_TRANSFER_SIZE)
389 {
390 fp_dbg ("Oversized payload length %" G_GSSIZE_FORMAT ", discarding",
391 payload_length);
392 g_byte_array_set_size (priv->stripe_packet, 0);
393 break;
394 }
395
396 fp_dbg ("Got frame, type %.2x payload of size %.4lx",
397 priv->stripe_packet->data[AESX660_RESPONSE_TYPE_OFFSET],
398 (long) payload_length);
399
400 still_needed_len = MAX (0, AESX660_HEADER_SIZE + payload_length - (gssize) priv->stripe_packet->len);
401 copy_len = MIN (actual_length, still_needed_len);
402 g_byte_array_append (priv->stripe_packet, data, copy_len);
403 data += copy_len;
404 actual_length -= copy_len;
405
406 /* Do we have a full packet including the payload? */
407 if (priv->stripe_packet->len < payload_length + AESX660_HEADER_SIZE)
408 break;
409
410 finger_missing |= process_stripe_data (transfer->ssm,
411 self,
412 priv->stripe_packet->data,
413 priv->stripe_packet->len);
414
415 g_byte_array_set_size (priv->stripe_packet, 0);
416 }
417
418 fp_dbg ("finger %s", finger_missing ? "missing" : "present");
419
420 if (finger_missing)
421 fpi_ssm_next_state (transfer->ssm);
422 else
423 fpi_ssm_jump_to_state (transfer->ssm, CAPTURE_READ_STRIPE_DATA);
424 }
425
426 static void
427 capture_run_state (FpiSsm *ssm, FpDevice *_dev)
428 {
429 FpiDeviceAesX660 *self = FPI_DEVICE_AES_X660 (_dev);
430 FpiDeviceAesX660Private *priv = fpi_device_aes_x660_get_instance_private (self);
431 FpiDeviceAesX660Class *cls = FPI_DEVICE_AES_X660_GET_CLASS (self);
432
433 switch (fpi_ssm_get_cur_state (ssm))
434 {
435 case CAPTURE_SEND_LED_CMD:
436 aesX660_send_cmd (ssm, _dev, led_solid_cmd, sizeof (led_solid_cmd),
437 fpi_ssm_usb_transfer_cb);
438 break;
439
440 case CAPTURE_SEND_CAPTURE_CMD:
441 g_byte_array_set_size (priv->stripe_packet, 0);
442 aesX660_send_cmd (ssm, _dev, cls->start_imaging_cmd,
443 cls->start_imaging_cmd_len,
444 fpi_ssm_usb_transfer_cb);
445 break;
446
447 case CAPTURE_READ_STRIPE_DATA:
448 aesX660_read_response (ssm, _dev, FALSE, FALSE, AESX660_BULK_TRANSFER_SIZE,
449 capture_read_stripe_data_cb);
450 break;
451
452 case CAPTURE_SET_IDLE:
453 fp_dbg ("Got %" G_GSIZE_FORMAT " frames", priv->strips_len);
454 aesX660_send_cmd (ssm, _dev, set_idle_cmd, sizeof (set_idle_cmd),
455 capture_set_idle_cmd_cb);
456 break;
457 }
458 }
459
460 static void
461 capture_sm_complete (FpiSsm *ssm, FpDevice *device, GError *error)
462 {
463 FpiDeviceAesX660 *self = FPI_DEVICE_AES_X660 (device);
464 FpiDeviceAesX660Private *priv = fpi_device_aes_x660_get_instance_private (self);
465
466 fp_dbg ("Capture completed");
467
468 if (priv->deactivating)
469 {
470 complete_deactivation (FP_IMAGE_DEVICE (device));
471 if (error)
472 g_error_free (error);
473 }
474 else if (error)
475 {
476 fpi_image_device_session_error (FP_IMAGE_DEVICE (device), error);
477 }
478 else
479 {
480 start_finger_detection (FP_IMAGE_DEVICE (device));
481 }
482 }
483
484 static void
485 start_capture (FpImageDevice *dev)
486 {
487 FpiDeviceAesX660 *self = FPI_DEVICE_AES_X660 (dev);
488 FpiDeviceAesX660Private *priv = fpi_device_aes_x660_get_instance_private (self);
489 FpiSsm *ssm;
490
491 if (priv->deactivating)
492 {
493 complete_deactivation (dev);
494 return;
495 }
496
497 ssm = fpi_ssm_new (FP_DEVICE (dev), capture_run_state, CAPTURE_NUM_STATES);
498 G_DEBUG_HERE ();
499 fpi_ssm_start (ssm, capture_sm_complete);
500 }
501
502 /****** INITIALIZATION/DEINITIALIZATION ******/
503
504 enum activate_states {
505 ACTIVATE_SET_IDLE,
506 ACTIVATE_SEND_READ_ID_CMD,
507 ACTIVATE_READ_ID,
508 ACTIVATE_SEND_CALIBRATE_CMD,
509 ACTIVATE_READ_CALIBRATE_DATA,
510 ACTIVATE_SEND_INIT_CMD,
511 ACTIVATE_READ_INIT_RESPONSE,
512 ACTIVATE_NUM_STATES,
513 };
514
515 static void
516 activate_read_id_cb (FpiUsbTransfer *transfer, FpDevice *device,
517 gpointer user_data, GError *error)
518 {
519 FpiDeviceAesX660 *self = FPI_DEVICE_AES_X660 (device);
520 FpiDeviceAesX660Private *priv = fpi_device_aes_x660_get_instance_private (self);
521 FpiDeviceAesX660Class *cls = FPI_DEVICE_AES_X660_GET_CLASS (self);
522 unsigned char *data = transfer->buffer;
523
524 if (error)
525 {
526 fp_dbg ("read_id cmd failed");
527 fpi_ssm_mark_failed (transfer->ssm, error);
528 return;
529 }
530 /* ID was read correctly */
531 if (data[0] == 0x07)
532 {
533 fp_dbg ("Sensor device id: %.2x%2x, bcdDevice: %.2x.%.2x, init status: %.2x",
534 data[4], data[3], data[5], data[6], data[7]);
535 }
536 else
537 {
538 fp_dbg ("Bogus read ID response: %.2x", data[AESX660_RESPONSE_TYPE_OFFSET]);
539 fpi_ssm_mark_failed (transfer->ssm,
540 fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
541 "Bogus read ID response %.2x",
542 data[AESX660_RESPONSE_TYPE_OFFSET]));
543 return;
544 }
545
546 switch (priv->init_seq_idx)
547 {
548 case 0:
549 priv->init_seq = cls->init_seqs[0];
550 priv->init_seq_len = cls->init_seqs_len[0];
551 priv->init_seq_idx = 1;
552 priv->init_cmd_idx = 0;
553 /* Do calibration only after 1st init sequence */
554 fpi_ssm_jump_to_state (transfer->ssm, ACTIVATE_SEND_INIT_CMD);
555 break;
556
557 case 1:
558 priv->init_seq = cls->init_seqs[1];
559 priv->init_seq_len = cls->init_seqs_len[1];
560 priv->init_seq_idx = 2;
561 priv->init_cmd_idx = 0;
562 fpi_ssm_next_state (transfer->ssm);
563 break;
564
565 default:
566 fp_dbg ("Failed to init device! init status: %.2x", data[7]);
567 fpi_ssm_mark_failed (transfer->ssm,
568 fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
569 "Failed to init device %.2x",
570 data[7]));
571 break;
572 }
573 }
574
575 static void
576 activate_read_init_cb (FpiUsbTransfer *transfer, FpDevice *device,
577 gpointer user_data, GError *error)
578 {
579 FpiDeviceAesX660 *self = FPI_DEVICE_AES_X660 (device);
580 FpiDeviceAesX660Private *priv = fpi_device_aes_x660_get_instance_private (self);
581 unsigned char *data = transfer->buffer;
582
583 fp_dbg ("read_init_cb");
584
585 if (error)
586 {
587 fp_dbg ("read_init transfer status: %s, actual_len: %d", error->message,
588 (gint) transfer->actual_length);
589 fpi_ssm_mark_failed (transfer->ssm, error);
590 return;
591 }
592 /* ID was read correctly */
593 if (data[0] != 0x42 || data[3] != 0x01)
594 {
595 fp_dbg ("Bogus read init response: %.2x %.2x", data[0],
596 data[3]);
597 fpi_ssm_mark_failed (transfer->ssm,
598 fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
599 "Bogus read init response: "
600 "%.2x %.2x", data[0], data[3]));
601 return;
602 }
603 priv->init_cmd_idx++;
604 if (priv->init_cmd_idx == priv->init_seq_len)
605 {
606 if (priv->init_seq_idx < 2)
607 fpi_ssm_jump_to_state (transfer->ssm,
608 ACTIVATE_SEND_READ_ID_CMD);
609 else
610 fpi_ssm_mark_completed (transfer->ssm);
611 return;
612 }
613
614 fpi_ssm_jump_to_state (transfer->ssm, ACTIVATE_SEND_INIT_CMD);
615 }
616
617 static void
618 activate_run_state (FpiSsm *ssm, FpDevice *_dev)
619 {
620 FpiDeviceAesX660 *self = FPI_DEVICE_AES_X660 (_dev);
621 FpiDeviceAesX660Private *priv = fpi_device_aes_x660_get_instance_private (self);
622
623 switch (fpi_ssm_get_cur_state (ssm))
624 {
625 case ACTIVATE_SET_IDLE:
626 priv->init_seq_idx = 0;
627 fp_dbg ("Activate: set idle");
628 aesX660_send_cmd (ssm, _dev, set_idle_cmd, sizeof (set_idle_cmd),
629 fpi_ssm_usb_transfer_cb);
630 break;
631
632 case ACTIVATE_SEND_READ_ID_CMD:
633 fp_dbg ("Activate: read ID");
634 aesX660_send_cmd (ssm, _dev, read_id_cmd, sizeof (read_id_cmd),
635 fpi_ssm_usb_transfer_cb);
636 break;
637
638 case ACTIVATE_READ_ID:
639 aesX660_read_response (ssm, _dev, TRUE, FALSE, ID_LEN, activate_read_id_cb);
640 break;
641
642 case ACTIVATE_SEND_INIT_CMD:
643 fp_dbg ("Activate: send init seq #%d cmd #%d",
644 priv->init_seq_idx,
645 priv->init_cmd_idx);
646 aesX660_send_cmd (ssm, _dev,
647 priv->init_seq[priv->init_cmd_idx].cmd,
648 priv->init_seq[priv->init_cmd_idx].len,
649 fpi_ssm_usb_transfer_cb);
650 break;
651
652 case ACTIVATE_READ_INIT_RESPONSE:
653 fp_dbg ("Activate: read init response");
654 aesX660_read_response (ssm, _dev, TRUE, FALSE, INIT_LEN, activate_read_init_cb);
655 break;
656
657 case ACTIVATE_SEND_CALIBRATE_CMD:
658 aesX660_send_cmd (ssm, _dev, calibrate_cmd, sizeof (calibrate_cmd),
659 fpi_ssm_usb_transfer_cb);
660 break;
661
662 case ACTIVATE_READ_CALIBRATE_DATA:
663 aesX660_read_response (ssm, _dev, TRUE, FALSE, CALIBRATE_DATA_LEN, aesX660_read_calibrate_data_cb);
664 break;
665 }
666 }
667
668 static void
669 activate_sm_complete (FpiSsm *ssm, FpDevice *_dev, GError *error)
670 {
671 fpi_image_device_activate_complete (FP_IMAGE_DEVICE (_dev), error);
672
673 if (!error)
674 start_finger_detection (FP_IMAGE_DEVICE (_dev));
675 }
676
677 static void
678 aesX660_dev_activate (FpImageDevice *dev)
679 {
680 FpiSsm *ssm = fpi_ssm_new (FP_DEVICE (dev), activate_run_state,
681 ACTIVATE_NUM_STATES);
682
683 fpi_ssm_start (ssm, activate_sm_complete);
684 }
685
686 static void
687 aesX660_dev_deactivate (FpImageDevice *dev)
688 {
689 FpiDeviceAesX660 *self = FPI_DEVICE_AES_X660 (dev);
690 FpiDeviceAesX660Private *priv = fpi_device_aes_x660_get_instance_private (self);
691
692 priv->deactivating = TRUE;
693 }
694
695 static void
696 aesX660_dev_init (FpImageDevice *dev)
697 {
698 FpiDeviceAesX660 *self = FPI_DEVICE_AES_X660 (dev);
699 FpiDeviceAesX660Private *priv = fpi_device_aes_x660_get_instance_private (self);
700 GError *error = NULL;
701
702 g_usb_device_claim_interface (fpi_device_get_usb_device (FP_DEVICE (dev)), 0, 0, &error);
703
704 priv->stripe_packet = g_byte_array_new ();
705
706 fpi_image_device_open_complete (dev, error);
707 }
708
709 static void
710 aesX660_dev_deinit (FpImageDevice *dev)
711 {
712 FpiDeviceAesX660 *self = FPI_DEVICE_AES_X660 (dev);
713 FpiDeviceAesX660Private *priv = fpi_device_aes_x660_get_instance_private (self);
714 GError *error = NULL;
715
716 g_usb_device_release_interface (fpi_device_get_usb_device (FP_DEVICE (dev)),
717 0, 0, &error);
718
719 g_clear_pointer (&priv->stripe_packet, g_byte_array_unref);
720
721 fpi_image_device_close_complete (dev, error);
722 }
723
724
725 static void
726 complete_deactivation (FpImageDevice *dev)
727 {
728 FpiDeviceAesX660 *self = FPI_DEVICE_AES_X660 (dev);
729 FpiDeviceAesX660Private *priv = fpi_device_aes_x660_get_instance_private (self);
730
731 G_DEBUG_HERE ();
732
733 priv->deactivating = FALSE;
734 g_slist_free_full (priv->strips, g_free);
735 priv->strips = NULL;
736 priv->strips_len = 0;
737 fpi_image_device_deactivate_complete (dev, NULL);
738 }
739
740 static void
741 fpi_device_aes_x660_init (FpiDeviceAesX660 *self)
742 {
743 }
744
745 static void
746 125 fpi_device_aes_x660_class_init (FpiDeviceAesX660Class *klass)
747 {
748 125 FpDeviceClass *dev_class = FP_DEVICE_CLASS (klass);
749 125 FpImageDeviceClass *img_class = FP_IMAGE_DEVICE_CLASS (klass);
750
751 125 dev_class->type = FP_DEVICE_TYPE_USB;
752 125 dev_class->scan_type = FP_SCAN_TYPE_SWIPE;
753
754 125 img_class->img_open = aesX660_dev_init;
755 125 img_class->img_close = aesX660_dev_deinit;
756 125 img_class->activate = aesX660_dev_activate;
757 125 img_class->deactivate = aesX660_dev_deactivate;
758
759 /* Everything else is set by the subclasses. */
760 }
761