GCC Code Coverage Report


Directory: ./
File: libfprint/drivers/aesx660.c
Date: 2024-05-04 14:54:39
Exec Total Coverage
Lines: 10 349 2.9%
Functions: 3 27 11.1%
Branches: 3 102 2.9%

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
3/5
✓ Branch 0 taken 117 times.
✓ Branch 1 taken 234 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 117 times.
✗ Branch 4 not taken.
936 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 fp_dbg ("Got frame, type %.2x payload of size %.4lx",
388 priv->stripe_packet->data[AESX660_RESPONSE_TYPE_OFFSET],
389 (long) payload_length);
390
391 still_needed_len = MAX (0, AESX660_HEADER_SIZE + payload_length - (gssize) priv->stripe_packet->len);
392 copy_len = MIN (actual_length, still_needed_len);
393 g_byte_array_append (priv->stripe_packet, data, copy_len);
394 data += copy_len;
395 actual_length -= copy_len;
396
397 /* Do we have a full packet including the payload? */
398 if (priv->stripe_packet->len < payload_length + AESX660_HEADER_SIZE)
399 break;
400
401 finger_missing |= process_stripe_data (transfer->ssm,
402 self,
403 priv->stripe_packet->data,
404 priv->stripe_packet->len);
405
406 g_byte_array_set_size (priv->stripe_packet, 0);
407 }
408
409 fp_dbg ("finger %s", finger_missing ? "missing" : "present");
410
411 if (finger_missing)
412 fpi_ssm_next_state (transfer->ssm);
413 else
414 fpi_ssm_jump_to_state (transfer->ssm, CAPTURE_READ_STRIPE_DATA);
415 }
416
417 static void
418 capture_run_state (FpiSsm *ssm, FpDevice *_dev)
419 {
420 FpiDeviceAesX660 *self = FPI_DEVICE_AES_X660 (_dev);
421 FpiDeviceAesX660Private *priv = fpi_device_aes_x660_get_instance_private (self);
422 FpiDeviceAesX660Class *cls = FPI_DEVICE_AES_X660_GET_CLASS (self);
423
424 switch (fpi_ssm_get_cur_state (ssm))
425 {
426 case CAPTURE_SEND_LED_CMD:
427 aesX660_send_cmd (ssm, _dev, led_solid_cmd, sizeof (led_solid_cmd),
428 fpi_ssm_usb_transfer_cb);
429 break;
430
431 case CAPTURE_SEND_CAPTURE_CMD:
432 g_byte_array_set_size (priv->stripe_packet, 0);
433 aesX660_send_cmd (ssm, _dev, cls->start_imaging_cmd,
434 cls->start_imaging_cmd_len,
435 fpi_ssm_usb_transfer_cb);
436 break;
437
438 case CAPTURE_READ_STRIPE_DATA:
439 aesX660_read_response (ssm, _dev, FALSE, FALSE, AESX660_BULK_TRANSFER_SIZE,
440 capture_read_stripe_data_cb);
441 break;
442
443 case CAPTURE_SET_IDLE:
444 fp_dbg ("Got %" G_GSIZE_FORMAT " frames", priv->strips_len);
445 aesX660_send_cmd (ssm, _dev, set_idle_cmd, sizeof (set_idle_cmd),
446 capture_set_idle_cmd_cb);
447 break;
448 }
449 }
450
451 static void
452 capture_sm_complete (FpiSsm *ssm, FpDevice *device, GError *error)
453 {
454 FpiDeviceAesX660 *self = FPI_DEVICE_AES_X660 (device);
455 FpiDeviceAesX660Private *priv = fpi_device_aes_x660_get_instance_private (self);
456
457 fp_dbg ("Capture completed");
458
459 if (priv->deactivating)
460 {
461 complete_deactivation (FP_IMAGE_DEVICE (device));
462 if (error)
463 g_error_free (error);
464 }
465 else if (error)
466 {
467 fpi_image_device_session_error (FP_IMAGE_DEVICE (device), error);
468 }
469 else
470 {
471 start_finger_detection (FP_IMAGE_DEVICE (device));
472 }
473 }
474
475 static void
476 start_capture (FpImageDevice *dev)
477 {
478 FpiDeviceAesX660 *self = FPI_DEVICE_AES_X660 (dev);
479 FpiDeviceAesX660Private *priv = fpi_device_aes_x660_get_instance_private (self);
480 FpiSsm *ssm;
481
482 if (priv->deactivating)
483 {
484 complete_deactivation (dev);
485 return;
486 }
487
488 ssm = fpi_ssm_new (FP_DEVICE (dev), capture_run_state, CAPTURE_NUM_STATES);
489 G_DEBUG_HERE ();
490 fpi_ssm_start (ssm, capture_sm_complete);
491 }
492
493 /****** INITIALIZATION/DEINITIALIZATION ******/
494
495 enum activate_states {
496 ACTIVATE_SET_IDLE,
497 ACTIVATE_SEND_READ_ID_CMD,
498 ACTIVATE_READ_ID,
499 ACTIVATE_SEND_CALIBRATE_CMD,
500 ACTIVATE_READ_CALIBRATE_DATA,
501 ACTIVATE_SEND_INIT_CMD,
502 ACTIVATE_READ_INIT_RESPONSE,
503 ACTIVATE_NUM_STATES,
504 };
505
506 static void
507 activate_read_id_cb (FpiUsbTransfer *transfer, FpDevice *device,
508 gpointer user_data, GError *error)
509 {
510 FpiDeviceAesX660 *self = FPI_DEVICE_AES_X660 (device);
511 FpiDeviceAesX660Private *priv = fpi_device_aes_x660_get_instance_private (self);
512 FpiDeviceAesX660Class *cls = FPI_DEVICE_AES_X660_GET_CLASS (self);
513 unsigned char *data = transfer->buffer;
514
515 if (error)
516 {
517 fp_dbg ("read_id cmd failed");
518 fpi_ssm_mark_failed (transfer->ssm, error);
519 return;
520 }
521 /* ID was read correctly */
522 if (data[0] == 0x07)
523 {
524 fp_dbg ("Sensor device id: %.2x%2x, bcdDevice: %.2x.%.2x, init status: %.2x",
525 data[4], data[3], data[5], data[6], data[7]);
526 }
527 else
528 {
529 fp_dbg ("Bogus read ID response: %.2x", data[AESX660_RESPONSE_TYPE_OFFSET]);
530 fpi_ssm_mark_failed (transfer->ssm,
531 fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
532 "Bogus read ID response %.2x",
533 data[AESX660_RESPONSE_TYPE_OFFSET]));
534 return;
535 }
536
537 switch (priv->init_seq_idx)
538 {
539 case 0:
540 priv->init_seq = cls->init_seqs[0];
541 priv->init_seq_len = cls->init_seqs_len[0];
542 priv->init_seq_idx = 1;
543 priv->init_cmd_idx = 0;
544 /* Do calibration only after 1st init sequence */
545 fpi_ssm_jump_to_state (transfer->ssm, ACTIVATE_SEND_INIT_CMD);
546 break;
547
548 case 1:
549 priv->init_seq = cls->init_seqs[1];
550 priv->init_seq_len = cls->init_seqs_len[1];
551 priv->init_seq_idx = 2;
552 priv->init_cmd_idx = 0;
553 fpi_ssm_next_state (transfer->ssm);
554 break;
555
556 default:
557 fp_dbg ("Failed to init device! init status: %.2x", data[7]);
558 fpi_ssm_mark_failed (transfer->ssm,
559 fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
560 "Failed to init device %.2x",
561 data[7]));
562 break;
563 }
564 }
565
566 static void
567 activate_read_init_cb (FpiUsbTransfer *transfer, FpDevice *device,
568 gpointer user_data, GError *error)
569 {
570 FpiDeviceAesX660 *self = FPI_DEVICE_AES_X660 (device);
571 FpiDeviceAesX660Private *priv = fpi_device_aes_x660_get_instance_private (self);
572 unsigned char *data = transfer->buffer;
573
574 fp_dbg ("read_init_cb");
575
576 if (error)
577 {
578 fp_dbg ("read_init transfer status: %s, actual_len: %d", error->message,
579 (gint) transfer->actual_length);
580 fpi_ssm_mark_failed (transfer->ssm, error);
581 return;
582 }
583 /* ID was read correctly */
584 if (data[0] != 0x42 || data[3] != 0x01)
585 {
586 fp_dbg ("Bogus read init response: %.2x %.2x", data[0],
587 data[3]);
588 fpi_ssm_mark_failed (transfer->ssm,
589 fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
590 "Bogus read init response: "
591 "%.2x %.2x", data[0], data[3]));
592 return;
593 }
594 priv->init_cmd_idx++;
595 if (priv->init_cmd_idx == priv->init_seq_len)
596 {
597 if (priv->init_seq_idx < 2)
598 fpi_ssm_jump_to_state (transfer->ssm,
599 ACTIVATE_SEND_READ_ID_CMD);
600 else
601 fpi_ssm_mark_completed (transfer->ssm);
602 return;
603 }
604
605 fpi_ssm_jump_to_state (transfer->ssm, ACTIVATE_SEND_INIT_CMD);
606 }
607
608 static void
609 activate_run_state (FpiSsm *ssm, FpDevice *_dev)
610 {
611 FpiDeviceAesX660 *self = FPI_DEVICE_AES_X660 (_dev);
612 FpiDeviceAesX660Private *priv = fpi_device_aes_x660_get_instance_private (self);
613
614 switch (fpi_ssm_get_cur_state (ssm))
615 {
616 case ACTIVATE_SET_IDLE:
617 priv->init_seq_idx = 0;
618 fp_dbg ("Activate: set idle");
619 aesX660_send_cmd (ssm, _dev, set_idle_cmd, sizeof (set_idle_cmd),
620 fpi_ssm_usb_transfer_cb);
621 break;
622
623 case ACTIVATE_SEND_READ_ID_CMD:
624 fp_dbg ("Activate: read ID");
625 aesX660_send_cmd (ssm, _dev, read_id_cmd, sizeof (read_id_cmd),
626 fpi_ssm_usb_transfer_cb);
627 break;
628
629 case ACTIVATE_READ_ID:
630 aesX660_read_response (ssm, _dev, TRUE, FALSE, ID_LEN, activate_read_id_cb);
631 break;
632
633 case ACTIVATE_SEND_INIT_CMD:
634 fp_dbg ("Activate: send init seq #%d cmd #%d",
635 priv->init_seq_idx,
636 priv->init_cmd_idx);
637 aesX660_send_cmd (ssm, _dev,
638 priv->init_seq[priv->init_cmd_idx].cmd,
639 priv->init_seq[priv->init_cmd_idx].len,
640 fpi_ssm_usb_transfer_cb);
641 break;
642
643 case ACTIVATE_READ_INIT_RESPONSE:
644 fp_dbg ("Activate: read init response");
645 aesX660_read_response (ssm, _dev, TRUE, FALSE, INIT_LEN, activate_read_init_cb);
646 break;
647
648 case ACTIVATE_SEND_CALIBRATE_CMD:
649 aesX660_send_cmd (ssm, _dev, calibrate_cmd, sizeof (calibrate_cmd),
650 fpi_ssm_usb_transfer_cb);
651 break;
652
653 case ACTIVATE_READ_CALIBRATE_DATA:
654 aesX660_read_response (ssm, _dev, TRUE, FALSE, CALIBRATE_DATA_LEN, aesX660_read_calibrate_data_cb);
655 break;
656 }
657 }
658
659 static void
660 activate_sm_complete (FpiSsm *ssm, FpDevice *_dev, GError *error)
661 {
662 fpi_image_device_activate_complete (FP_IMAGE_DEVICE (_dev), error);
663
664 if (!error)
665 start_finger_detection (FP_IMAGE_DEVICE (_dev));
666 }
667
668 static void
669 aesX660_dev_activate (FpImageDevice *dev)
670 {
671 FpiSsm *ssm = fpi_ssm_new (FP_DEVICE (dev), activate_run_state,
672 ACTIVATE_NUM_STATES);
673
674 fpi_ssm_start (ssm, activate_sm_complete);
675 }
676
677 static void
678 aesX660_dev_deactivate (FpImageDevice *dev)
679 {
680 FpiDeviceAesX660 *self = FPI_DEVICE_AES_X660 (dev);
681 FpiDeviceAesX660Private *priv = fpi_device_aes_x660_get_instance_private (self);
682
683 priv->deactivating = TRUE;
684 }
685
686 static void
687 aesX660_dev_init (FpImageDevice *dev)
688 {
689 FpiDeviceAesX660 *self = FPI_DEVICE_AES_X660 (dev);
690 FpiDeviceAesX660Private *priv = fpi_device_aes_x660_get_instance_private (self);
691 GError *error = NULL;
692
693 g_usb_device_claim_interface (fpi_device_get_usb_device (FP_DEVICE (dev)), 0, 0, &error);
694
695 priv->stripe_packet = g_byte_array_new ();
696
697 fpi_image_device_open_complete (dev, error);
698 }
699
700 static void
701 aesX660_dev_deinit (FpImageDevice *dev)
702 {
703 FpiDeviceAesX660 *self = FPI_DEVICE_AES_X660 (dev);
704 FpiDeviceAesX660Private *priv = fpi_device_aes_x660_get_instance_private (self);
705 GError *error = NULL;
706
707 g_usb_device_release_interface (fpi_device_get_usb_device (FP_DEVICE (dev)),
708 0, 0, &error);
709
710 g_clear_pointer (&priv->stripe_packet, g_byte_array_unref);
711
712 fpi_image_device_close_complete (dev, error);
713 }
714
715
716 static void
717 complete_deactivation (FpImageDevice *dev)
718 {
719 FpiDeviceAesX660 *self = FPI_DEVICE_AES_X660 (dev);
720 FpiDeviceAesX660Private *priv = fpi_device_aes_x660_get_instance_private (self);
721
722 G_DEBUG_HERE ();
723
724 priv->deactivating = FALSE;
725 g_slist_free (priv->strips);
726 priv->strips = NULL;
727 priv->strips_len = 0;
728 fpi_image_device_deactivate_complete (dev, NULL);
729 }
730
731 static void
732 fpi_device_aes_x660_init (FpiDeviceAesX660 *self)
733 {
734 }
735
736 static void
737 117 fpi_device_aes_x660_class_init (FpiDeviceAesX660Class *klass)
738 {
739 117 FpDeviceClass *dev_class = FP_DEVICE_CLASS (klass);
740 117 FpImageDeviceClass *img_class = FP_IMAGE_DEVICE_CLASS (klass);
741
742 117 dev_class->type = FP_DEVICE_TYPE_USB;
743 117 dev_class->scan_type = FP_SCAN_TYPE_SWIPE;
744
745 117 img_class->img_open = aesX660_dev_init;
746 117 img_class->img_close = aesX660_dev_deinit;
747 117 img_class->activate = aesX660_dev_activate;
748 117 img_class->deactivate = aesX660_dev_deactivate;
749
750 /* Everything else is set by the subclasses. */
751 }
752