GCC Code Coverage Report


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 2.3% 17 / 0 / 745
Functions: 8.1% 3 / 0 / 37
Branches: 1.4% 4 / 0 / 290

libfprint/drivers/etes603.c
Line Branch Exec Source
1 /*
2 * EgisTec ES603 driver for libfprint
3 * Copyright (C) 2012 Patrick Marlier
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20 /* EgisTec ES603 device information
21 * Sensor area: 192 x 4 pixels
22 * Sensor gray: 16 gray levels/sensor pixel
23 * Sensor resolution: 508 dpi
24 * USB Manufacturer ID: 1C7A
25 * USB Product ID: 0603
26 *
27 * Possible compatibility LTT-SS500/SS501
28 *
29 * Extra features not present in this driver (see https://code.google.com/p/etes603):
30 * Tuning of DTVRT for contact detection
31 * Contact detection via capacitance
32 * Capture mode using assembled frames (usually better quality)
33 *
34 */
35
36 #define FP_COMPONENT "etes603"
37
38 #include "drivers_api.h"
39
40 /* libusb defines */
41 #define EP_IN 0x81
42 #define EP_OUT 0x02
43 /* Note that 1000 ms is usually enough but with CMD_READ_FE could be longer
44 * since the sensor is waiting motion. */
45 #define BULK_TIMEOUT 1000
46
47 /* es603 defines */
48 #define FRAME_WIDTH 192 /* pixels per row */
49 #define FRAME_HEIGHT 4 /* number of rows */
50 #define FRAME_SIZE 384 /* size in bytes (4 bits per pixels) */
51 #define FE_WIDTH 256 /* pixels per row for Fly-Estimation */
52 #define FE_HEIGHT 500 /* number of rows for Fly-Estimation */
53 #define FE_SIZE 64000 /* size in bytes (4 bits per pixels) */
54
55 #define GAIN_SMALL_INIT 0x23 /* Initial small gain */
56 #define VRT_MAX 0x3F /* Maximum value for VRT */
57 #define VRB_MAX 0x3A /* Maximum value for VRB */
58 #define DTVRT_MAX 0x3A /* Maximum value for DTVRT */
59 #define DCOFFSET_MIN 0x00 /* Minimum value for DCoffset */
60 #define DCOFFSET_MAX 0x35 /* Maximum value for DCoffset */
61
62 /* es603 commands */
63 #define CMD_READ_REG 0x01
64 #define CMD_WRITE_REG 0x02
65 #define CMD_READ_FRAME 0x03 /* Read the sensor area */
66 #define CMD_READ_FE 0x06 /* Read a fingerprint using Fly-Estimation */
67 #define CMD_20 0x20 /* ? */
68 #define CMD_25 0x25 /* ? */
69 #define CMD_60 0x60 /* ? */
70
71 #define CMD_OK 0x01 /* Command successfully executed */
72
73 /* es603 registers */
74 #define REG_MAX 0x18 /* Maximum number of registers in one message */
75 #define REG_MODE_CONTROL 0x02 /* Mode control */
76 #define REG_03 0x03 /* Contact register? */
77 #define REG_04 0x04 /* ? */
78 #define REG_10 0x10 /* MVS FRMBUF control */
79 #define REG_1A 0x1A /* ? */
80 /* BEGIN init sensor */
81 #define REG_20 0x20 /* (def: 0x00) */
82 #define REG_21 0x21 /* Small gain (def: 0x23) */
83 #define REG_22 0x22 /* Normal gain (def: 0x21) */
84 #define REG_23 0x23 /* Large gain (def: 0x20) */
85 #define REG_24 0x24 /* (def: 0x14) */
86 #define REG_25 0x25 /* (def: 0x6A) */
87 #define REG_26 0x26 /* VRB again? (def: 0x00) */
88 #define REG_27 0x27 /* VRT again? (def: 0x00) */
89 #define REG_28 0x28 /* (def: 0x00) */
90 #define REG_29 0x29 /* (def: 0xC0) */
91 #define REG_2A 0x2A /* (def: 0x50) */
92 #define REG_2B 0x2B /* (def: 0x50) */
93 #define REG_2C 0x2C /* (def: 0x4D) */
94 #define REG_2D 0x2D /* (def: 0x03) */
95 #define REG_2E 0x2E /* (def: 0x06) */
96 #define REG_2F 0x2F /* (def: 0x06) */
97 #define REG_30 0x30 /* (def: 0x10) */
98 #define REG_31 0x31 /* (def: 0x02) */
99 #define REG_32 0x32 /* (def: 0x14) */
100 #define REG_33 0x33 /* (def: 0x34) */
101 #define REG_34 0x34 /* (def: 0x01) */
102 #define REG_35 0x35 /* (def: 0x08) */
103 #define REG_36 0x36 /* (def: 0x03) */
104 #define REG_37 0x37 /* (def: 0x21) */
105 /* END init sensor */
106
107 #define REG_ENC1 0x41 /* Encryption 1 */
108 #define REG_ENC2 0x42
109 #define REG_ENC3 0x43
110 #define REG_ENC4 0x44
111 #define REG_ENC5 0x45
112 #define REG_ENC6 0x46
113 #define REG_ENC7 0x47
114 #define REG_ENC8 0x48 /* Encryption 8 */
115
116 #define REG_50 0x50 /* ? For contact detection */
117 #define REG_51 0x51 /* ? */
118 #define REG_59 0x59 /* ? */
119 #define REG_5A 0x5A /* ? */
120 #define REG_5B 0x5B /* ? */
121
122 #define REG_INFO0 0x70 /* Sensor model byte0 */
123 #define REG_INFO1 0x71 /* Sensor model byte1 */
124 #define REG_INFO2 0x72 /* Sensor model byte2 */
125 #define REG_INFO3 0x73 /* Sensor model byte3 */
126
127 #define REG_GAIN 0xE0
128 #define REG_VRT 0xE1
129 #define REG_VRB 0xE2
130 #define REG_DTVRT 0xE3 /* used for contact detection */
131 #define REG_VCO_CONTROL 0xE5 /* 0x13 (IDLE?), 0x14 (REALTIME) */
132 #define REG_DCOFFSET 0xE6
133
134 #define REG_F0 0xF0 /* ? init:0x00 close:0x01 */
135 #define REG_F2 0xF2 /* ? init:0x00 close:0x4E */
136
137 #define REG_MODE_SLEEP 0x30 /* Sleep mode */
138 #define REG_MODE_CONTACT 0x31 /* Contact mode */
139 #define REG_MODE_SENSOR 0x33 /* Sensor mode */
140 #define REG_MODE_FP 0x34 /* FingerPrint mode (Fly-Estimation®) */
141
142 #define REG_VCO_IDLE 0x13
143 #define REG_VCO_RT 0x14 /* Realtime */
144
145 /* The size of the message header is 5 plus 1 for the command. */
146 #define MSG_HDR_SIZE 6
147
148 /* This structure must be packed because it is a the raw message sent. */
149 struct egis_msg
150 {
151 guint8 magic[5]; /* out: 'EGIS' 0x09 / in: 'SIGE' 0x0A */
152 guint8 cmd;
153 union
154 {
155 struct
156 {
157 guint8 nb;
158 guint8 regs[REG_MAX];
159 } egis_readreg;
160 struct
161 {
162 guint8 regs[REG_MAX];
163 } sige_readreg;
164 struct
165 {
166 guint8 nb;
167 struct
168 {
169 guint8 reg;
170 guint8 val;
171 } regs[REG_MAX];
172 } egis_writereg;
173 struct
174 {
175 guint8 length_factor;
176 guint8 length;
177 guint8 use_gvv;
178 guint8 gain;
179 guint8 vrt;
180 guint8 vrb;
181 } egis_readf;
182 struct
183 {
184 guint8 len[2];
185 guint8 val[3];
186 } egis_readfp;
187 struct
188 {
189 guint8 val[5];
190 } sige_misc;
191 guint8 padding[0x40 - 6]; /* Ensure size of 0x40 */
192 };
193 } __attribute__((packed));
194
195
196 /* Structure to keep information between asynchronous functions. */
197 struct _FpiDeviceEtes603
198 {
199 FpImageDevice parent;
200
201 guint8 regs[256];
202 struct egis_msg *req;
203 size_t req_len;
204 struct egis_msg *ans;
205 size_t ans_len;
206
207 guint8 *fp;
208 guint16 fp_height;
209
210 guint8 tunedc_min;
211 guint8 tunedc_max;
212
213 /* Device parameters */
214 guint8 gain;
215 guint8 dcoffset;
216 guint8 vrt;
217 guint8 vrb;
218
219 unsigned int is_active;
220 };
221 G_DECLARE_FINAL_TYPE (FpiDeviceEtes603, fpi_device_etes603, FPI, DEVICE_ETES603,
222 FpImageDevice);
223
4/6
fpi_device_etes603_class_intern_init:
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 125 times.
fpi_device_etes603_get_type:
✓ Branch 2 → 3 taken 125 times.
✓ Branch 2 → 7 taken 24 times.
✓ Branch 4 → 5 taken 125 times.
✗ Branch 4 → 7 not taken.
399 G_DEFINE_TYPE (FpiDeviceEtes603, fpi_device_etes603, FP_TYPE_IMAGE_DEVICE);
224
225 static void m_start_fingerdetect (FpImageDevice *idev);
226 /*
227 * Prepare the header of the message to be sent to the device.
228 */
229 static void
230 msg_header_prepare (struct egis_msg *msg)
231 {
232 msg->magic[0] = 'E';
233 msg->magic[1] = 'G';
234 msg->magic[2] = 'I';
235 msg->magic[3] = 'S';
236 msg->magic[4] = 0x09;
237 }
238
239 /*
240 * Check that the header of the received message is correct.
241 */
242 static int
243 msg_header_check (struct egis_msg *msg)
244 {
245 if (msg->magic[0] == 'S' && msg->magic[1] == 'I' &&
246 msg->magic[2] == 'G' && msg->magic[3] == 'E' &&
247 msg->magic[4] == 0x0A)
248 return 0;
249 return -1;
250 }
251
252 /*
253 * Prepare message to ask for a frame.
254 */
255 static void
256 msg_get_frame (FpiDeviceEtes603 *self,
257 guint8 use_gvv, guint8 gain, guint8 vrt,
258 guint8 vrb)
259 {
260 struct egis_msg *msg = self->req;
261
262 msg_header_prepare (msg);
263 msg->cmd = CMD_READ_FRAME;
264 msg->egis_readf.length_factor = 0x01;
265 /* length should be 0xC0 */
266 msg->egis_readf.length = FRAME_WIDTH;
267 msg->egis_readf.use_gvv = use_gvv;
268 /* if use_gvv is set, gain/vrt/vrb are used */
269 msg->egis_readf.gain = gain;
270 msg->egis_readf.vrt = vrt;
271 msg->egis_readf.vrb = vrb;
272
273 self->req_len = MSG_HDR_SIZE + 6;
274 self->ans_len = FRAME_SIZE;
275 }
276
277 /*
278 * Prepare message to ask for a fingerprint frame.
279 */
280 static void
281 msg_get_fp (FpiDeviceEtes603 *self, guint8 len0, guint8 len1,
282 guint8 v2, guint8 v3, guint8 v4)
283 {
284 struct egis_msg *msg = self->req;
285
286 msg_header_prepare (msg);
287 msg->cmd = CMD_READ_FE;
288 /* Unknown values and always same on captured frames.
289 * 1st 2nd bytes is unsigned short for height, but only on value range
290 * 0x01 0xF4 (500), 0x02 0x00 (512), 0x02 0xF4 (756) are ok
291 */
292 msg->egis_readfp.len[0] = len0;
293 msg->egis_readfp.len[1] = len1;
294 /* 3rd byte : ?? but changes frame size
295 * 4th byte : 0x00 -> can change width
296 * 5th byte : motion sensibility?
297 */
298 msg->egis_readfp.val[0] = v2;
299 msg->egis_readfp.val[1] = v3;
300 msg->egis_readfp.val[2] = v4;
301
302 self->req_len = MSG_HDR_SIZE + 5;
303 self->ans_len = FE_SIZE;
304 }
305
306 /*
307 * Prepare message to read registers from the sensor.
308 * Variadic argument pattern: int reg, ...
309 */
310 static void
311 msg_get_regs (FpiDeviceEtes603 *self, int n_args, ... )
312 {
313 struct egis_msg *msg = self->req;
314 va_list ap;
315 int i;
316
317 g_assert (n_args > 0 && n_args <= REG_MAX);
318
319 msg_header_prepare (msg);
320 msg->cmd = CMD_READ_REG;
321 msg->egis_readreg.nb = n_args;
322 va_start (ap, n_args);
323 for (i = 0; i < n_args; i++)
324 msg->egis_readreg.regs[i] = va_arg (ap, int);
325 va_end (ap);
326
327 self->req_len = MSG_HDR_SIZE + 1 + n_args;
328 self->ans_len = MSG_HDR_SIZE + 1 + n_args;
329 }
330
331 /*
332 * Parse the result of read register command.
333 */
334 static int
335 msg_parse_regs (FpiDeviceEtes603 *dev)
336 {
337 size_t i, n_args;
338 struct egis_msg *msg_req = dev->req;
339 struct egis_msg *msg_ans = dev->ans;
340
341 g_return_val_if_fail (dev->ans_len >= MSG_HDR_SIZE, -1);
342
343 n_args = dev->ans_len - MSG_HDR_SIZE;
344 if (n_args > REG_MAX)
345 {
346 g_warn_if_reached ();
347 n_args = REG_MAX;
348 }
349
350 if (msg_header_check (msg_ans))
351 return -1;
352 if (msg_ans->cmd != CMD_OK)
353 return -2;
354
355 for (i = 0; i < n_args; i++)
356 {
357 int reg = msg_req->egis_readreg.regs[i];
358 dev->regs[reg] = msg_ans->sige_readreg.regs[i];
359 }
360 return 0;
361 }
362
363 /*
364 * Prepare message to write sensor's registers.
365 * Variadic arguments are: int reg, int val, ...
366 */
367 static void
368 msg_set_regs (FpiDeviceEtes603 *self, int n_args, ...)
369 {
370 struct egis_msg *msg = self->req;
371 va_list ap;
372 int i;
373
374 g_assert (n_args != 0 && n_args % 2 == 0 && n_args <= REG_MAX * 2);
375
376 msg_header_prepare (msg);
377 msg->cmd = CMD_WRITE_REG;
378 msg->egis_writereg.nb = n_args / 2;
379
380 va_start (ap, n_args);
381 for (i = 0; i < n_args / 2; i++)
382 {
383 msg->egis_writereg.regs[i].reg = va_arg (ap, int);
384 msg->egis_writereg.regs[i].val = va_arg (ap, int);
385 }
386 va_end (ap);
387
388 self->req_len = MSG_HDR_SIZE + 1 + n_args;
389 self->ans_len = MSG_HDR_SIZE + 1;
390 }
391
392 static int
393 msg_check_ok (FpiDeviceEtes603 *dev)
394 {
395 struct egis_msg *msg = dev->ans;
396
397 if (msg_header_check (msg))
398 goto err;
399 if (msg->cmd != CMD_OK)
400 goto err;
401 return 0;
402 err:
403 return -1;
404 }
405
406 /*
407 * Check the model of the sensor.
408 */
409 static int
410 check_info (FpiDeviceEtes603 *dev)
411 {
412 if (dev->regs[0x70] == 0x4A && dev->regs[0x71] == 0x44 &&
413 dev->regs[0x72] == 0x49 && dev->regs[0x73] == 0x31)
414 return 0;
415 fp_err ("unknown device parameters (REG_70:%02X REG_71:%02X "
416 "REG_FIRMWARE:%02X REG_VERSION:%02X)",
417 dev->regs[0x70], dev->regs[0x71], dev->regs[0x72],
418 dev->regs[0x73]);
419 return -1;
420 }
421
422 static void
423 msg_get_cmd20 (FpiDeviceEtes603 *dev)
424 {
425 struct egis_msg *msg = dev->req;
426
427 msg_header_prepare (msg);
428 msg->cmd = CMD_20;
429 dev->req_len = MSG_HDR_SIZE;
430 }
431
432 static int
433 msg_check_cmd20 (FpiDeviceEtes603 *dev)
434 {
435 struct egis_msg *msg = dev->ans;
436
437 if (msg_header_check (msg))
438 {
439 fp_err ("msg_header_check failed");
440 return -1;
441 }
442 /* status or flashtype/flashinfo or ? */
443 if (msg->cmd != 0x05 ||
444 msg->sige_misc.val[0] != 0x00 ||
445 msg->sige_misc.val[1] != 0x00)
446 fp_warn ("unexpected answer CMD_20 from device(%02X %02X %02X)",
447 msg->cmd, msg->sige_misc.val[0], msg->sige_misc.val[1]);
448
449 return 0;
450 }
451
452 static void
453 msg_get_cmd25 (FpiDeviceEtes603 *dev)
454 {
455 struct egis_msg *msg = dev->req;
456
457 msg_header_prepare (msg);
458 msg->cmd = CMD_25;
459 dev->req_len = MSG_HDR_SIZE;
460 }
461
462 static int
463 msg_check_cmd25 (FpiDeviceEtes603 *dev)
464 {
465 struct egis_msg *msg = dev->ans;
466
467 if (msg_header_check (msg))
468 {
469 fp_err ("msg_header_check failed");
470 goto err;
471 }
472 if (msg->cmd != CMD_OK)
473 {
474 fp_err ("CMD_OK failed");
475 goto err;
476 }
477 /* flashtype or status or ? */
478 if (msg->sige_misc.val[0] != 0x00)
479 fp_warn ("unexpected answer for CMD_25 (%02X)",
480 msg->sige_misc.val[0]);
481 return 0;
482 err:
483 return -1;
484 }
485
486 static void
487 msg_set_mode_control (FpiDeviceEtes603 *self, guint8 mode)
488 {
489 msg_set_regs (self, 2, REG_MODE_CONTROL, mode);
490 }
491
492
493 /* Processing functions */
494
495 /*
496 * Return the brightness of a 4bpp frame
497 */
498 static unsigned int
499 process_get_brightness (guint8 *f, size_t s)
500 {
501 unsigned int i, sum = 0;
502
503 for (i = 0; i < s; i++)
504 {
505 sum += f[i] >> 4;
506 sum += f[i] & 0x0F;
507 }
508 return sum;
509 }
510
511 /*
512 * Return the histogram of a 4bpp frame
513 */
514 static void
515 process_hist (guint8 *f, size_t s, float stat[5])
516 {
517 float hist[16];
518 float black_mean, white_mean;
519 int i;
520
521 /* Clean histogram */
522 for (i = 0; i < 16; i++)
523 hist[i] = 0.0;
524 for (i = 0; i < s; i++)
525 {
526 hist[f[i] >> 4]++;
527 hist[f[i] & 0x0F]++;
528 }
529 /* histogram average */
530 for (i = 0; i < 16; i++)
531 hist[i] = hist[i] / (s * 2);
532 /* Average black/white pixels (full black and full white pixels
533 * are excluded). */
534 black_mean = white_mean = 0.0;
535 for (i = 1; i < 8; i++)
536 black_mean += hist[i];
537 for (i = 8; i < 15; i++)
538 white_mean += hist[i];
539 stat[0] = hist[0];
540 stat[1] = black_mean;
541 stat[2] = black_mean + white_mean;
542 stat[3] = white_mean;
543 stat[4] = hist[15];
544 fp_dbg ("fullb=%6f black=%6f grey=%6f white=%6f fullw=%6f",
545 hist[0], black_mean, black_mean + white_mean, white_mean,
546 hist[15]);
547 }
548
549 /*
550 * Return true if the frame is almost empty.
551 */
552 static int
553 process_frame_empty (guint8 *frame, size_t size)
554 {
555 unsigned int sum = process_get_brightness (frame, size);
556
557 /* Allow an average of 'threshold' luminosity per pixel */
558 if (sum < size)
559 return 1;
560 return 0;
561 }
562
563 /* Transform 4 bits image to 8 bits image */
564 static void
565 process_4to8_bpp (guint8 *input, unsigned int input_size,
566 guint8 *output)
567 {
568 unsigned int i, j = 0;
569
570 for (i = 0; i < input_size; i++, j += 2)
571 {
572 /* 16 gray levels transform to 256 levels using << 4 */
573 output[j] = input[i] & 0xF0;
574 output[j + 1] = input[i] << 4;
575 }
576 }
577
578 /*
579 * Remove duplicated lines at the end of a fingerprint.
580 */
581 static void
582 process_removefpi_end (FpiDeviceEtes603 *dev)
583 {
584 unsigned int i;
585
586 /* Need at least the 2-line empty pattern to compare against. */
587 if (dev->fp_height < 2)
588 g_return_if_reached ();
589
590 /* 2 last lines with Fly-Estimation are the empty pattern. */
591 guint8 *pattern = dev->fp + (dev->fp_height - 2) * FE_WIDTH / 2;
592
593 for (i = 2; i < dev->fp_height; i += 2)
594 if (memcmp (pattern, pattern - (i * FE_WIDTH / 2), FE_WIDTH))
595 break;
596
597 if (i > dev->fp_height)
598 {
599 g_warn_if_reached ();
600 i = dev->fp_height;
601 }
602
603 dev->fp_height -= i;
604 fp_dbg ("Removing %d empty lines from image", i - 2);
605 }
606
607 static void
608 reset_param (FpiDeviceEtes603 *dev)
609 {
610 dev->dcoffset = 0;
611 dev->vrt = 0;
612 dev->vrb = 0;
613 dev->gain = 0;
614 }
615
616
617 /* Asynchronous stuff */
618
619 enum {
620 INIT_CHECK_INFO_REQ,
621 INIT_CHECK_INFO_ANS,
622 INIT_CMD20_REQ,
623 INIT_CMD20_ANS,
624 INIT_CMD25_REQ,
625 INIT_CMD25_ANS,
626 INIT_SENSOR_REQ,
627 INIT_SENSOR_ANS,
628 INIT_ENC_REQ,
629 INIT_ENC_ANS,
630 INIT_REGS_REQ,
631 INIT_REGS_ANS,
632 INIT_NUM_STATES
633 };
634
635 enum {
636 TUNEDC_INIT,
637 TUNEDC_SET_DCOFFSET_REQ,
638 TUNEDC_SET_DCOFFSET_ANS,
639 TUNEDC_GET_FRAME_REQ,
640 TUNEDC_GET_FRAME_ANS,
641 TUNEDC_FINAL_SET_REG2122_REQ,
642 TUNEDC_FINAL_SET_REG2122_ANS,
643 TUNEDC_FINAL_SET_GAIN_REQ,
644 TUNEDC_FINAL_SET_GAIN_ANS,
645 TUNEDC_FINAL_SET_DCOFFSET_REQ,
646 TUNEDC_FINAL_SET_DCOFFSET_ANS,
647 TUNEDC_NUM_STATES
648 };
649
650 enum {
651 TUNEVRB_INIT,
652 TUNEVRB_GET_GAIN_REQ,
653 TUNEVRB_GET_GAIN_ANS,
654 TUNEVRB_GET_DCOFFSET_REQ,
655 TUNEVRB_GET_DCOFFSET_ANS,
656 TUNEVRB_SET_DCOFFSET_REQ,
657 TUNEVRB_SET_DCOFFSET_ANS,
658 TUNEVRB_FRAME_REQ,
659 TUNEVRB_FRAME_ANS,
660 TUNEVRB_FINAL_SET_DCOFFSET_REQ,
661 TUNEVRB_FINAL_SET_DCOFFSET_ANS,
662 TUNEVRB_FINAL_SET_REG2627_REQ,
663 TUNEVRB_FINAL_SET_REG2627_ANS,
664 TUNEVRB_FINAL_SET_GAINVRTVRB_REQ,
665 TUNEVRB_FINAL_SET_GAINVRTVRB_ANS,
666 TUNEVRB_FINAL_SET_MODE_SLEEP_REQ,
667 TUNEVRB_FINAL_SET_MODE_SLEEP_ANS,
668 TUNEVRB_NUM_STATES
669 };
670
671 enum {
672 FGR_FPA_INIT_SET_MODE_SLEEP_REQ,
673 FGR_FPA_INIT_SET_MODE_SLEEP_ANS,
674 FGR_FPA_INIT_SET_DCOFFSET_REQ,
675 FGR_FPA_INIT_SET_DCOFFSET_ANS,
676 FGR_FPA_INIT_SET_GAINVRTVRB_REQ,
677 FGR_FPA_INIT_SET_GAINVRTVRB_ANS,
678 FGR_FPA_INIT_SET_VCO_CONTROL_RT_REQ,
679 FGR_FPA_INIT_SET_VCO_CONTROL_RT_ANS,
680 FGR_FPA_INIT_SET_REG04_REQ,
681 FGR_FPA_INIT_SET_REG04_ANS,
682 FGR_FPA_INIT_SET_MODE_SENSOR_REQ,
683 FGR_FPA_INIT_SET_MODE_SENSOR_ANS,
684 FGR_FPA_GET_FRAME_REQ,
685 FGR_FPA_GET_FRAME_ANS,
686 FGR_NUM_STATES
687 };
688
689 enum {
690 CAP_FP_INIT_SET_REG10_REQ,
691 CAP_FP_INIT_SET_REG10_ANS,
692 CAP_FP_INIT_SET_MODE_FP_REQ,
693 CAP_FP_INIT_SET_MODE_FP_ANS,
694 CAP_FP_GET_FP_REQ,
695 CAP_FP_GET_FP_ANS,
696 CAP_NUM_STATES
697 };
698
699 enum {
700 EXIT_SET_REGS_REQ,
701 EXIT_SET_REGS_ANS,
702 EXIT_NUM_STATES
703 };
704
705 static void
706 async_tx (FpDevice *dev, unsigned int ep, void *cb,
707 FpiSsm *ssm)
708 {
709 FpiDeviceEtes603 *self = FPI_DEVICE_ETES603 (dev);
710 FpiUsbTransfer *transfer = fpi_usb_transfer_new (dev);
711 unsigned char *buffer = NULL;
712 int length;
713
714 if (ep == EP_OUT)
715 {
716 buffer = (unsigned char *) self->req;
717 length = self->req_len;
718 }
719 else if (ep == EP_IN)
720 {
721 buffer = (unsigned char *) self->ans;
722 length = self->ans_len;
723 }
724 else
725 {
726 g_assert_not_reached ();
727 }
728 transfer->ssm = ssm;
729 fpi_usb_transfer_fill_bulk_full (transfer, ep, buffer, length, NULL);
730 fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL, cb, NULL);
731 }
732
733
734 static void
735 async_tx_cb (FpiUsbTransfer *transfer, FpDevice *device,
736 gpointer user_data, GError *error)
737 {
738 FpImageDevice *idev = FP_IMAGE_DEVICE (device);
739 FpiDeviceEtes603 *self = FPI_DEVICE_ETES603 (idev);
740
741 if (error)
742 {
743 fp_warn ("transfer is not completed (result: %s)",
744 error->message);
745 fpi_ssm_mark_failed (transfer->ssm, error);
746 }
747 else
748 {
749 unsigned char endpoint = transfer->endpoint;
750 int actual_length = transfer->actual_length;
751 int length = transfer->length;
752
753 if (endpoint == EP_OUT)
754 {
755 if (length != actual_length)
756 fp_warn ("length %d != actual_length %d",
757 length, actual_length);
758
759 /* Chained with the answer */
760 async_tx (device, EP_IN, async_tx_cb, transfer->ssm);
761 }
762 else if (endpoint == EP_IN)
763 {
764 self->ans_len = actual_length;
765 fpi_ssm_next_state (transfer->ssm);
766 }
767 }
768 }
769
770 static void
771 m_exit_state (FpiSsm *ssm, FpDevice *dev)
772 {
773 FpiDeviceEtes603 *self = FPI_DEVICE_ETES603 (dev);
774
775 switch (fpi_ssm_get_cur_state (ssm))
776 {
777 case EXIT_SET_REGS_REQ:
778 msg_set_regs (self, 4, REG_VCO_CONTROL, REG_VCO_IDLE,
779 REG_MODE_CONTROL, REG_MODE_SLEEP);
780 async_tx (dev, EP_OUT, async_tx_cb, ssm);
781 break;
782
783 case EXIT_SET_REGS_ANS:
784 if (msg_check_ok (self))
785 goto err;
786 fpi_ssm_mark_completed (ssm);
787 break;
788
789 default:
790 g_assert_not_reached ();
791 break;
792 }
793
794 return;
795 err:
796 fpi_ssm_mark_failed (ssm, fpi_device_error_new (FP_DEVICE_ERROR_PROTO));
797 }
798
799 static void
800 m_exit_complete (FpiSsm *ssm, FpDevice *dev, GError *error)
801 {
802 FpImageDevice *idev = FP_IMAGE_DEVICE (dev);
803
804 if (error)
805 fp_err ("Error switching the device to idle state");
806 else
807 fp_dbg ("The device is now in idle state");
808 fpi_image_device_deactivate_complete (idev, error);
809 }
810
811 static void
812 m_exit_start (FpImageDevice *idev)
813 {
814 FpiDeviceEtes603 *self = FPI_DEVICE_ETES603 (idev);
815 FpiSsm *ssm = fpi_ssm_new (FP_DEVICE (idev), m_exit_state, EXIT_NUM_STATES);
816
817 self->is_active = FALSE;
818 fp_dbg ("Switching device to idle mode");
819 fpi_ssm_start (ssm, m_exit_complete);
820 }
821
822 static void
823 m_capture_state (FpiSsm *ssm, FpDevice *dev)
824 {
825 FpImageDevice *idev = FP_IMAGE_DEVICE (dev);
826 FpiDeviceEtes603 *self = FPI_DEVICE_ETES603 (dev);
827
828 if (self->is_active == FALSE)
829 {
830 fpi_ssm_mark_completed (ssm);
831 return;
832 }
833
834 switch (fpi_ssm_get_cur_state (ssm))
835 {
836 case CAP_FP_INIT_SET_REG10_REQ:
837 /* Reset fingerprint */
838 fp_dbg ("Capturing a fingerprint...");
839 memset (self->fp, 0, FE_SIZE * 2);
840 self->fp_height = 0;
841 msg_set_regs (self, 2, REG_10, 0x92);
842 async_tx (dev, EP_OUT, async_tx_cb, ssm);
843 break;
844
845 case CAP_FP_INIT_SET_REG10_ANS:
846 if (msg_check_ok (self))
847 goto err;
848 fpi_ssm_next_state (ssm);
849 break;
850
851 case CAP_FP_INIT_SET_MODE_FP_REQ:
852 msg_set_mode_control (self, REG_MODE_FP);
853 async_tx (dev, EP_OUT, async_tx_cb, ssm);
854 break;
855
856 case CAP_FP_INIT_SET_MODE_FP_ANS:
857 if (msg_check_ok (self))
858 goto err;
859 fp_dbg ("Capturing a 1st frame...");
860 fpi_ssm_next_state (ssm);
861 break;
862
863 case CAP_FP_GET_FP_REQ:
864 msg_get_fp (self, 0x01, 0xF4, 0x02, 0x01, 0x64);
865 async_tx (dev, EP_OUT, async_tx_cb, ssm);
866 break;
867
868 case CAP_FP_GET_FP_ANS:
869 memcpy (self->fp + self->fp_height * FE_WIDTH / 2, self->ans,
870 FE_SIZE);
871 self->fp_height += FE_HEIGHT;
872 if (self->fp_height <= FE_HEIGHT)
873 {
874 /* 2 lines are at least removed each time */
875 self->fp_height -= 2;
876 fp_dbg ("Capturing a 2nd frame...");
877 fpi_ssm_jump_to_state (ssm, CAP_FP_GET_FP_REQ);
878 }
879 else
880 {
881 /* Remove empty parts 2 times for the 2 frames */
882 process_removefpi_end (self);
883 process_removefpi_end (self);
884
885 if (self->fp_height >= FE_WIDTH)
886 {
887 FpImage *img = fp_image_new (FE_WIDTH, self->fp_height);
888 unsigned int img_size = self->fp_height * FE_WIDTH;
889
890 /* Images received are white on black, so invert it. */
891 /* TODO detect sweep direction */
892 img->flags = FPI_IMAGE_COLORS_INVERTED | FPI_IMAGE_V_FLIPPED;
893 img->height = self->fp_height;
894 process_4to8_bpp (self->fp, img_size / 2, img->data);
895 fp_dbg ("Sending the raw fingerprint image (%dx%d)",
896 img->width, img->height);
897 fpi_image_device_image_captured (idev, img);
898 }
899 else
900 {
901 fpi_image_device_retry_scan (idev, FP_DEVICE_RETRY_TOO_SHORT);
902 }
903
904 fpi_image_device_report_finger_status (idev, FALSE);
905 fpi_ssm_mark_completed (ssm);
906 }
907 break;
908
909 default:
910 g_assert_not_reached ();
911 break;
912 }
913
914 return;
915 err:
916 fpi_ssm_mark_failed (ssm, fpi_device_error_new (FP_DEVICE_ERROR_PROTO));
917 }
918
919 static void
920 m_capture_complete (FpiSsm *ssm, FpDevice *dev, GError *error)
921 {
922 FpImageDevice *idev = FP_IMAGE_DEVICE (dev);
923 FpiDeviceEtes603 *self = FPI_DEVICE_ETES603 (dev);
924
925 if (error)
926 {
927 if (self->is_active)
928 {
929 fp_err ("Error while capturing fingerprint "
930 "(%s)", error->message);
931 fpi_image_device_session_error (idev, error);
932 }
933 else
934 {
935 g_error_free (error);
936 }
937 }
938
939 if (self->is_active == TRUE)
940 {
941 fp_dbg ("Device is still active, restarting finger detection");
942 m_start_fingerdetect (idev);
943 }
944 else
945 {
946 fp_dbg ("And it's over.");
947 m_exit_start (idev);
948 }
949 }
950
951 static void
952 m_finger_state (FpiSsm *ssm, FpDevice *dev)
953 {
954 FpiDeviceEtes603 *self = FPI_DEVICE_ETES603 (dev);
955
956 if (self->is_active == FALSE)
957 {
958 fpi_ssm_mark_completed (ssm);
959 return;
960 }
961
962 switch (fpi_ssm_get_cur_state (ssm))
963 {
964 case FGR_FPA_INIT_SET_MODE_SLEEP_REQ:
965 msg_set_mode_control (self, REG_MODE_SLEEP);
966 async_tx (dev, EP_OUT, async_tx_cb, ssm);
967 break;
968
969 case FGR_FPA_INIT_SET_MODE_SLEEP_ANS:
970 if (msg_check_ok (self))
971 goto err;
972 fpi_ssm_next_state (ssm);
973 break;
974
975 case FGR_FPA_INIT_SET_DCOFFSET_REQ:
976 msg_set_regs (self, 2, REG_DCOFFSET, self->dcoffset);
977 async_tx (dev, EP_OUT, async_tx_cb, ssm);
978 break;
979
980 case FGR_FPA_INIT_SET_DCOFFSET_ANS:
981 if (msg_check_ok (self))
982 goto err;
983 fpi_ssm_next_state (ssm);
984 break;
985
986 case FGR_FPA_INIT_SET_GAINVRTVRB_REQ:
987 msg_set_regs (self, 6, REG_GAIN, self->gain, REG_VRT,
988 self->vrt,
989 REG_VRB, self->vrb);
990 async_tx (dev, EP_OUT, async_tx_cb, ssm);
991 break;
992
993 case FGR_FPA_INIT_SET_GAINVRTVRB_ANS:
994 if (msg_check_ok (self))
995 goto err;
996 fpi_ssm_next_state (ssm);
997 break;
998
999 case FGR_FPA_INIT_SET_VCO_CONTROL_RT_REQ:
1000 msg_set_regs (self, 2, REG_VCO_CONTROL, REG_VCO_RT);
1001 async_tx (dev, EP_OUT, async_tx_cb, ssm);
1002 break;
1003
1004 case FGR_FPA_INIT_SET_VCO_CONTROL_RT_ANS:
1005 if (msg_check_ok (self))
1006 goto err;
1007 fpi_ssm_next_state (ssm);
1008 break;
1009
1010 case FGR_FPA_INIT_SET_REG04_REQ:
1011 msg_set_regs (self, 2, REG_04, 0x00);
1012 async_tx (dev, EP_OUT, async_tx_cb, ssm);
1013 break;
1014
1015 case FGR_FPA_INIT_SET_REG04_ANS:
1016 if (msg_check_ok (self))
1017 goto err;
1018 fpi_ssm_next_state (ssm);
1019 break;
1020
1021 case FGR_FPA_INIT_SET_MODE_SENSOR_REQ:
1022 msg_set_mode_control (self, REG_MODE_SENSOR);
1023 async_tx (dev, EP_OUT, async_tx_cb, ssm);
1024 break;
1025
1026 case FGR_FPA_INIT_SET_MODE_SENSOR_ANS:
1027 if (msg_check_ok (self))
1028 goto err;
1029 fpi_ssm_next_state (ssm);
1030 break;
1031
1032 case FGR_FPA_GET_FRAME_REQ:
1033 msg_get_frame (self, 0x00, 0x00, 0x00, 0x00);
1034 async_tx (dev, EP_OUT, async_tx_cb, ssm);
1035 break;
1036
1037 case FGR_FPA_GET_FRAME_ANS:
1038 if (process_frame_empty ((guint8 *) self->ans, FRAME_SIZE))
1039 {
1040 fpi_ssm_jump_to_state (ssm, FGR_FPA_GET_FRAME_REQ);
1041 }
1042 else
1043 {
1044 fpi_image_device_report_finger_status (FP_IMAGE_DEVICE (dev), TRUE);
1045 fpi_ssm_mark_completed (ssm);
1046 }
1047 break;
1048
1049 default:
1050 g_assert_not_reached ();
1051 break;
1052 }
1053
1054 return;
1055 err:
1056 fpi_ssm_mark_failed (ssm, fpi_device_error_new (FP_DEVICE_ERROR_PROTO));
1057 }
1058
1059 static void
1060 m_finger_complete (FpiSsm *ssm, FpDevice *dev, GError *error)
1061 {
1062 FpImageDevice *idev = FP_IMAGE_DEVICE (dev);
1063 FpiDeviceEtes603 *self = FPI_DEVICE_ETES603 (dev);
1064
1065 if (!error)
1066 {
1067 FpiSsm *ssm_cap;
1068 ssm_cap = fpi_ssm_new (dev, m_capture_state, CAP_NUM_STATES);
1069 fpi_ssm_start (ssm_cap, m_capture_complete);
1070 }
1071 else
1072 {
1073 if (self->is_active)
1074 {
1075 fp_err ("Error while capturing fingerprint "
1076 "(%s)", error->message);
1077 fpi_image_device_session_error (idev, error);
1078 }
1079 else
1080 {
1081 m_exit_start (idev);
1082 g_error_free (error);
1083 }
1084 self->is_active = FALSE;
1085 }
1086
1087 }
1088
1089 static void
1090 m_start_fingerdetect (FpImageDevice *idev)
1091 {
1092 FpiSsm *ssmf;
1093
1094 ssmf = fpi_ssm_new (FP_DEVICE (idev), m_finger_state, FGR_NUM_STATES);
1095 fpi_ssm_start (ssmf, m_finger_complete);
1096 }
1097
1098 /*
1099 * Tune value of VRT and VRB for contrast and brightness.
1100 */
1101 static void
1102 m_tunevrb_state (FpiSsm *ssm, FpDevice *dev)
1103 {
1104 FpiDeviceEtes603 *self = FPI_DEVICE_ETES603 (dev);
1105 float hist[5];
1106
1107 if (self->is_active == FALSE)
1108 {
1109 fpi_ssm_mark_completed (ssm);
1110 return;
1111 }
1112
1113 switch (fpi_ssm_get_cur_state (ssm))
1114 {
1115 case TUNEVRB_INIT:
1116 fp_dbg ("Tuning of VRT/VRB");
1117 g_assert (self->dcoffset);
1118 /* VRT(reg E1)=0x0A and VRB(reg E2)=0x10 are starting values */
1119 self->vrt = 0x0A;
1120 self->vrb = 0x10;
1121 fpi_ssm_next_state (ssm);
1122 break;
1123
1124 case TUNEVRB_GET_GAIN_REQ:
1125 msg_get_regs (self, 1, REG_GAIN);
1126 async_tx (dev, EP_OUT, async_tx_cb, ssm);
1127 break;
1128
1129 case TUNEVRB_GET_GAIN_ANS:
1130 if (msg_parse_regs (self))
1131 goto err;
1132 fpi_ssm_next_state (ssm);
1133 break;
1134
1135 case TUNEVRB_GET_DCOFFSET_REQ:
1136 msg_get_regs (self, 1, REG_DCOFFSET);
1137 async_tx (dev, EP_OUT, async_tx_cb, ssm);
1138 break;
1139
1140 case TUNEVRB_GET_DCOFFSET_ANS:
1141 if (msg_parse_regs (self))
1142 goto err;
1143 fpi_ssm_next_state (ssm);
1144 break;
1145
1146 case TUNEVRB_SET_DCOFFSET_REQ:
1147 /* Reduce DCoffset by 1 to allow tuning */
1148 msg_set_regs (self, 2, REG_DCOFFSET, self->dcoffset - 1);
1149 async_tx (dev, EP_OUT, async_tx_cb, ssm);
1150 break;
1151
1152 case TUNEVRB_SET_DCOFFSET_ANS:
1153 if (msg_check_ok (self))
1154 goto err;
1155 fpi_ssm_next_state (ssm);
1156 break;
1157
1158 case TUNEVRB_FRAME_REQ:
1159 fp_dbg ("Testing VRT=0x%02X VRB=0x%02X", self->vrt, self->vrb);
1160 msg_get_frame (self, 0x01, self->gain, self->vrt, self->vrb);
1161 async_tx (dev, EP_OUT, async_tx_cb, ssm);
1162 break;
1163
1164 case TUNEVRB_FRAME_ANS:
1165 process_hist ((guint8 *) self->ans, FRAME_SIZE, hist);
1166 /* Note that this tuning could probably be improved */
1167 if (hist[0] + hist[1] > 0.95)
1168 {
1169 if (self->vrt <= 0 || self->vrb <= 0)
1170 {
1171 fp_dbg ("Image is too dark, reducing DCOffset");
1172 self->dcoffset--;
1173 fpi_ssm_jump_to_state (ssm, TUNEVRB_INIT);
1174 }
1175 else
1176 {
1177 self->vrt--;
1178 self->vrb--;
1179 fpi_ssm_jump_to_state (ssm, TUNEVRB_FRAME_REQ);
1180 }
1181 break;
1182 }
1183 if (hist[4] > 0.95)
1184 {
1185 fp_dbg ("Image is too bright, increasing DCOffset");
1186 self->dcoffset++;
1187 fpi_ssm_jump_to_state (ssm, TUNEVRB_INIT);
1188 break;
1189 }
1190 if (hist[4] + hist[3] > 0.4)
1191 {
1192 if (self->vrt >= 2 * self->vrb - 0x0a)
1193 {
1194 self->vrt++;
1195 self->vrb++;
1196 }
1197 else
1198 {
1199 self->vrt++;
1200 }
1201 /* Check maximum for vrt/vrb */
1202 /* TODO if maximum is reached, leave with an error? */
1203 if (self->vrt > VRT_MAX)
1204 self->vrt = VRT_MAX;
1205 if (self->vrb > VRB_MAX)
1206 self->vrb = VRB_MAX;
1207 fpi_ssm_jump_to_state (ssm, TUNEVRB_FRAME_REQ);
1208 break;
1209 }
1210 fpi_ssm_next_state (ssm);
1211 break;
1212
1213 case TUNEVRB_FINAL_SET_DCOFFSET_REQ:
1214 fp_dbg ("-> VRT=0x%02X VRB=0x%02X", self->vrt, self->vrb);
1215 /* Reset the DCOffset */
1216 msg_set_regs (self, 2, REG_DCOFFSET, self->dcoffset);
1217 async_tx (dev, EP_OUT, async_tx_cb, ssm);
1218 break;
1219
1220 case TUNEVRB_FINAL_SET_DCOFFSET_ANS:
1221 if (msg_check_ok (self))
1222 goto err;
1223 fpi_ssm_next_state (ssm);
1224 break;
1225
1226 case TUNEVRB_FINAL_SET_REG2627_REQ:
1227 /* In traces, REG_26/REG_27 are set. purpose? values? */
1228 msg_set_regs (self, 4, REG_26, 0x11, REG_27, 0x00);
1229 async_tx (dev, EP_OUT, async_tx_cb, ssm);
1230 break;
1231
1232 case TUNEVRB_FINAL_SET_REG2627_ANS:
1233 if (msg_check_ok (self))
1234 goto err;
1235 fpi_ssm_next_state (ssm);
1236 break;
1237
1238 case TUNEVRB_FINAL_SET_GAINVRTVRB_REQ:
1239 /* Set Gain/VRT/VRB values found */
1240 msg_set_regs (self, 6, REG_GAIN, self->gain, REG_VRT,
1241 self->vrt,
1242 REG_VRB, self->vrb);
1243 async_tx (dev, EP_OUT, async_tx_cb, ssm);
1244 break;
1245
1246 case TUNEVRB_FINAL_SET_GAINVRTVRB_ANS:
1247 if (msg_check_ok (self))
1248 goto err;
1249 /* In traces, Gain/VRT/VRB are read again. */
1250 fpi_ssm_next_state (ssm);
1251 break;
1252
1253 case TUNEVRB_FINAL_SET_MODE_SLEEP_REQ:
1254 msg_set_mode_control (self, REG_MODE_SLEEP);
1255 async_tx (dev, EP_OUT, async_tx_cb, ssm);
1256 break;
1257
1258 case TUNEVRB_FINAL_SET_MODE_SLEEP_ANS:
1259 if (msg_check_ok (self))
1260 goto err;
1261 fpi_ssm_mark_completed (ssm);
1262 break;
1263
1264 default:
1265 g_assert_not_reached ();
1266 break;
1267 }
1268
1269 return;
1270 err:
1271 fpi_ssm_mark_failed (ssm, fpi_device_error_new (FP_DEVICE_ERROR_PROTO));
1272 }
1273
1274 static void
1275 m_tunevrb_complete (FpiSsm *ssm, FpDevice *dev, GError *error)
1276 {
1277 FpiDeviceEtes603 *self = FPI_DEVICE_ETES603 (dev);
1278 FpImageDevice *idev = FP_IMAGE_DEVICE (dev);
1279
1280 fpi_image_device_activate_complete (idev, error);
1281 if (!error)
1282 {
1283 fp_dbg ("Tuning is done. Starting finger detection.");
1284 m_start_fingerdetect (idev);
1285 }
1286
1287 if (!self->is_active)
1288 m_exit_start (idev);
1289
1290 }
1291
1292 /*
1293 * This function tunes the DCoffset value and adjusts the gain value if
1294 * required.
1295 */
1296 static void
1297 m_tunedc_state (FpiSsm *ssm, FpDevice *dev)
1298 {
1299 FpiDeviceEtes603 *self = FPI_DEVICE_ETES603 (dev);
1300
1301 if (self->is_active == FALSE)
1302 {
1303 fpi_ssm_mark_completed (ssm);
1304 return;
1305 }
1306
1307 /* TODO To get better results, tuning could be done 3 times as in
1308 * captured traffic to make sure that the value is correct. */
1309 /* The default gain should work but it may reach a DCOffset limit so in
1310 * this case we decrease the gain. */
1311 switch (fpi_ssm_get_cur_state (ssm))
1312 {
1313 case TUNEDC_INIT:
1314 /* reg_e0 = 0x23 is sensor normal/small gain */
1315 self->gain = GAIN_SMALL_INIT;
1316 self->tunedc_min = DCOFFSET_MIN;
1317 self->tunedc_max = DCOFFSET_MAX;
1318 fp_dbg ("Tuning DCoffset");
1319 fpi_ssm_next_state (ssm);
1320 break;
1321
1322 case TUNEDC_SET_DCOFFSET_REQ:
1323 /* Dichotomic search to find at which value the frame becomes
1324 * almost black. */
1325 self->dcoffset = (self->tunedc_max + self->tunedc_min) / 2;
1326 fp_dbg ("Testing DCoffset=0x%02X Gain=0x%02X", self->dcoffset,
1327 self->gain);
1328 msg_set_regs (self, 2, REG_DCOFFSET, self->dcoffset);
1329 async_tx (dev, EP_OUT, async_tx_cb, ssm);
1330 break;
1331
1332 case TUNEDC_SET_DCOFFSET_ANS:
1333 if (msg_check_ok (self))
1334 goto err;
1335 fpi_ssm_next_state (ssm);
1336 break;
1337
1338 case TUNEDC_GET_FRAME_REQ:
1339 /* vrt:0x15 vrb:0x10 are constant in all tuning frames. */
1340 msg_get_frame (self, 0x01, self->gain, 0x15, 0x10);
1341 async_tx (dev, EP_OUT, async_tx_cb, ssm);
1342 break;
1343
1344 case TUNEDC_GET_FRAME_ANS:
1345 if (process_frame_empty ((guint8 *) self->ans, FRAME_WIDTH))
1346 self->tunedc_max = self->dcoffset;
1347 else
1348 self->tunedc_min = self->dcoffset;
1349 if (self->tunedc_min + 1 < self->tunedc_max)
1350 {
1351 fpi_ssm_jump_to_state (ssm, TUNEDC_SET_DCOFFSET_REQ);
1352 }
1353 else if (self->tunedc_max < DCOFFSET_MAX)
1354 {
1355 self->dcoffset = self->tunedc_max + 1;
1356 fpi_ssm_next_state (ssm);
1357 }
1358 else
1359 {
1360 self->gain--;
1361 fpi_ssm_jump_to_state (ssm, TUNEDC_SET_DCOFFSET_REQ);
1362 }
1363 break;
1364
1365 case TUNEDC_FINAL_SET_REG2122_REQ:
1366 fp_dbg ("-> DCoffset=0x%02X Gain=0x%02X", self->dcoffset,
1367 self->gain);
1368 /* ??? how reg21 / reg22 are calculated */
1369 msg_set_regs (self, 4, REG_21, 0x23, REG_22, 0x21);
1370 async_tx (dev, EP_OUT, async_tx_cb, ssm);
1371 break;
1372
1373 case TUNEDC_FINAL_SET_REG2122_ANS:
1374 if (msg_check_ok (self))
1375 goto err;
1376 fpi_ssm_next_state (ssm);
1377 break;
1378
1379 case TUNEDC_FINAL_SET_GAIN_REQ:
1380 msg_set_regs (self, 2, REG_GAIN, self->gain);
1381 async_tx (dev, EP_OUT, async_tx_cb, ssm);
1382 break;
1383
1384 case TUNEDC_FINAL_SET_GAIN_ANS:
1385 fpi_ssm_next_state (ssm);
1386 break;
1387
1388 case TUNEDC_FINAL_SET_DCOFFSET_REQ:
1389 msg_set_regs (self, 2, REG_DCOFFSET, self->dcoffset);
1390 async_tx (dev, EP_OUT, async_tx_cb, ssm);
1391 break;
1392
1393 case TUNEDC_FINAL_SET_DCOFFSET_ANS:
1394 /* In captured traffic, read GAIN, VRT, and VRB registers. */
1395 if (msg_check_ok (self))
1396 goto err;
1397 fpi_ssm_mark_completed (ssm);
1398 break;
1399
1400 default:
1401 g_assert_not_reached ();
1402 break;
1403 }
1404
1405 return;
1406 err:
1407 fpi_ssm_mark_failed (ssm, fpi_device_error_new (FP_DEVICE_ERROR_PROTO));
1408 }
1409
1410 static void
1411 m_tunedc_complete (FpiSsm *ssm, FpDevice *dev, GError *error)
1412 {
1413 FpiDeviceEtes603 *self = FPI_DEVICE_ETES603 (dev);
1414 FpImageDevice *idev = FP_IMAGE_DEVICE (dev);
1415
1416 if (!error)
1417 {
1418 FpiSsm *ssm_tune;
1419 ssm_tune = fpi_ssm_new (FP_DEVICE (idev), m_tunevrb_state,
1420 TUNEVRB_NUM_STATES);
1421 fpi_ssm_start (ssm_tune, m_tunevrb_complete);
1422 }
1423 else
1424 {
1425 fp_err ("Error while tuning DCOFFSET");
1426 reset_param (FPI_DEVICE_ETES603 (dev));
1427 fpi_image_device_session_error (idev, error);
1428 }
1429
1430 if (!self->is_active)
1431 m_exit_start (idev);
1432
1433 }
1434
1435 static void
1436 m_init_state (FpiSsm *ssm, FpDevice *dev)
1437 {
1438 FpiDeviceEtes603 *self = FPI_DEVICE_ETES603 (dev);
1439
1440 if (self->is_active == FALSE)
1441 {
1442 fpi_ssm_mark_completed (ssm);
1443 return;
1444 }
1445
1446 switch (fpi_ssm_get_cur_state (ssm))
1447 {
1448 case INIT_CHECK_INFO_REQ:
1449 msg_get_regs (self, 4, REG_INFO0, REG_INFO1, REG_INFO2,
1450 REG_INFO3);
1451 async_tx (dev, EP_OUT, async_tx_cb, ssm);
1452 break;
1453
1454 case INIT_CHECK_INFO_ANS:
1455 if (msg_parse_regs (self))
1456 goto err;
1457 if (check_info (self))
1458 goto err;
1459 fpi_ssm_next_state (ssm);
1460 break;
1461
1462 case INIT_CMD20_REQ:
1463 msg_get_cmd20 (self);
1464 async_tx (dev, EP_OUT, async_tx_cb, ssm);
1465 break;
1466
1467 case INIT_CMD20_ANS:
1468 if (msg_check_cmd20 (self))
1469 goto err;
1470 fpi_ssm_next_state (ssm);
1471 break;
1472
1473 case INIT_CMD25_REQ:
1474 msg_get_cmd25 (self);
1475 async_tx (dev, EP_OUT, async_tx_cb, ssm);
1476 break;
1477
1478 case INIT_CMD25_ANS:
1479 if (msg_check_cmd25 (self))
1480 goto err;
1481 fpi_ssm_next_state (ssm);
1482 break;
1483
1484 case INIT_SENSOR_REQ:
1485 /* In captured traffic, those are split. */
1486 msg_set_regs (self, 18, REG_MODE_CONTROL, REG_MODE_SLEEP,
1487 REG_50, 0x0F, REG_GAIN, 0x04, REG_VRT, 0x08,
1488 REG_VRB, 0x0D, REG_VCO_CONTROL, REG_VCO_RT,
1489 REG_DCOFFSET, 0x36, REG_F0, 0x00, REG_F2, 0x00);
1490 async_tx (dev, EP_OUT, async_tx_cb, ssm);
1491 break;
1492
1493 case INIT_SENSOR_ANS:
1494 if (msg_check_ok (self))
1495 goto err;
1496 fpi_ssm_next_state (ssm);
1497 break;
1498
1499 case INIT_ENC_REQ:
1500 /* Initialize encryption registers without encryption. */
1501 /* Set registers from 0x41 to 0x48 (0x8 regs) */
1502 msg_set_regs (self, 16, REG_ENC1, 0x12, REG_ENC2, 0x34,
1503 REG_ENC3, 0x56, REG_ENC4, 0x78, REG_ENC5, 0x90,
1504 REG_ENC6, 0xAB, REG_ENC7, 0xCD, REG_ENC8, 0xEF);
1505 async_tx (dev, EP_OUT, async_tx_cb, ssm);
1506 break;
1507
1508 case INIT_ENC_ANS:
1509 if (msg_check_ok (self))
1510 goto err;
1511 fpi_ssm_next_state (ssm);
1512 break;
1513
1514 case INIT_REGS_REQ:
1515 /* Set register from 0x20 to 0x37 (0x18 regs) */
1516 msg_set_regs (self, 48,
1517 REG_20, 0x00, REG_21, 0x23, REG_22, 0x21, REG_23,
1518 0x20,
1519 REG_24, 0x14, REG_25, 0x6A, REG_26, 0x00, REG_27,
1520 0x00,
1521 REG_28, 0x00, REG_29, 0xC0, REG_2A, 0x50, REG_2B,
1522 0x50,
1523 REG_2C, 0x4D, REG_2D, 0x03, REG_2E, 0x06, REG_2F,
1524 0x06,
1525 REG_30, 0x10, REG_31, 0x02, REG_32, 0x14, REG_33,
1526 0x34,
1527 REG_34, 0x01, REG_35, 0x08, REG_36, 0x03, REG_37,
1528 0x21);
1529 async_tx (dev, EP_OUT, async_tx_cb, ssm);
1530 break;
1531
1532 case INIT_REGS_ANS:
1533 if (msg_check_ok (self))
1534 goto err;
1535 fpi_ssm_mark_completed (ssm);
1536 break;
1537
1538 default:
1539 g_assert_not_reached ();
1540 break;
1541 }
1542
1543 return;
1544 err:
1545 fpi_ssm_mark_failed (ssm, fpi_device_error_new (FP_DEVICE_ERROR_PROTO));
1546 }
1547
1548 static void
1549 m_init_complete (FpiSsm *ssm, FpDevice *dev, GError *error)
1550 {
1551 FpImageDevice *idev = FP_IMAGE_DEVICE (dev);
1552
1553 if (!error)
1554 {
1555 FpiSsm *ssm_tune;
1556 ssm_tune = fpi_ssm_new (FP_DEVICE (idev), m_tunedc_state,
1557 TUNEDC_NUM_STATES);
1558 fpi_ssm_start (ssm_tune, m_tunedc_complete);
1559 }
1560 else
1561 {
1562 fp_err ("Error initializing the device");
1563 reset_param (FPI_DEVICE_ETES603 (dev));
1564 fpi_image_device_session_error (idev, error);
1565 }
1566 }
1567
1568 static void
1569 dev_activate (FpImageDevice *idev)
1570 {
1571 FpiDeviceEtes603 *self = FPI_DEVICE_ETES603 (idev);
1572 FpiSsm *ssm;
1573
1574 g_assert (self);
1575
1576 /* Reset info and data */
1577 self->is_active = TRUE;
1578
1579 if (self->dcoffset == 0)
1580 {
1581 fp_dbg ("Tuning device...");
1582 ssm = fpi_ssm_new (FP_DEVICE (idev), m_init_state, INIT_NUM_STATES);
1583 fpi_ssm_start (ssm, m_init_complete);
1584 }
1585 else
1586 {
1587 fp_dbg ("Using previous tuning (DCOFFSET=0x%02X,VRT=0x%02X,"
1588 "VRB=0x%02X,GAIN=0x%02X).", self->dcoffset, self->vrt,
1589 self->vrb, self->gain);
1590 fpi_image_device_activate_complete (idev, NULL);
1591 ssm = fpi_ssm_new (FP_DEVICE (idev), m_finger_state, FGR_NUM_STATES);
1592 fpi_ssm_start (ssm, m_finger_complete);
1593 }
1594 }
1595
1596 static void
1597 dev_deactivate (FpImageDevice *idev)
1598 {
1599 FpiDeviceEtes603 *self = FPI_DEVICE_ETES603 (idev);
1600
1601 fp_dbg ("deactivating");
1602
1603 /* this can be called even if still activated. */
1604 if (self->is_active == TRUE)
1605 self->is_active = FALSE;
1606 else
1607 m_exit_start (idev);
1608 }
1609
1610 static void
1611 dev_open (FpImageDevice *idev)
1612 {
1613 GError *error = NULL;
1614 FpiDeviceEtes603 *self = FPI_DEVICE_ETES603 (idev);
1615
1616 if (!g_usb_device_claim_interface (fpi_device_get_usb_device (FP_DEVICE (idev)), 0, 0, &error))
1617 {
1618 fpi_image_device_open_complete (idev, error);
1619 return;
1620 }
1621
1622 self->req = g_malloc (sizeof (struct egis_msg));
1623 self->ans = g_malloc (FE_SIZE);
1624 self->fp = g_malloc (FE_SIZE * 4);
1625
1626 fpi_image_device_open_complete (idev, NULL);
1627 }
1628
1629 static void
1630 dev_close (FpImageDevice *idev)
1631 {
1632 GError *error = NULL;
1633 FpiDeviceEtes603 *self = FPI_DEVICE_ETES603 (idev);
1634
1635 g_free (self->req);
1636 g_free (self->ans);
1637 g_free (self->fp);
1638
1639 g_usb_device_release_interface (fpi_device_get_usb_device (FP_DEVICE (idev)),
1640 0, 0, &error);
1641 fpi_image_device_close_complete (idev, error);
1642 }
1643
1644 static const FpIdEntry id_table[] = {
1645 /* EgisTec (aka Lightuning) ES603 */
1646 { .vid = 0x1c7a, .pid = 0x0603, },
1647 { .vid = 0, .pid = 0, .driver_data = 0 },
1648 };
1649
1650 static void
1651 fpi_device_etes603_init (FpiDeviceEtes603 *self)
1652 {
1653 }
1654 static void
1655 125 fpi_device_etes603_class_init (FpiDeviceEtes603Class *klass)
1656 {
1657 125 FpDeviceClass *dev_class = FP_DEVICE_CLASS (klass);
1658 125 FpImageDeviceClass *img_class = FP_IMAGE_DEVICE_CLASS (klass);
1659
1660 125 dev_class->id = "etes603";
1661 125 dev_class->full_name = "EgisTec ES603";
1662 125 dev_class->type = FP_DEVICE_TYPE_USB;
1663 125 dev_class->id_table = id_table;
1664 125 dev_class->scan_type = FP_SCAN_TYPE_SWIPE;
1665
1666 125 img_class->img_open = dev_open;
1667 125 img_class->img_close = dev_close;
1668 125 img_class->activate = dev_activate;
1669 125 img_class->deactivate = dev_deactivate;
1670
1671 125 img_class->img_width = 256;
1672 125 img_class->img_height = -1;
1673 }
1674