GCC Code Coverage Report


Directory: ./
File: libfprint/drivers/etes603.c
Date: 2024-09-16 14:36:32
Exec Total Coverage
Lines: 15 734 2.0%
Functions: 3 37 8.1%
Branches: 4 275 1.5%

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/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 (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 n_args = dev->ans_len - MSG_HDR_SIZE;
342
343 if (msg_header_check (msg_ans))
344 return -1;
345 if (msg_ans->cmd != CMD_OK)
346 return -2;
347
348 for (i = 0; i < n_args; i++)
349 {
350 int reg = msg_req->egis_readreg.regs[i];
351 dev->regs[reg] = msg_ans->sige_readreg.regs[i];
352 }
353 return 0;
354 }
355
356 /*
357 * Prepare message to write sensor's registers.
358 * Variadic arguments are: int reg, int val, ...
359 */
360 static void
361 msg_set_regs (FpiDeviceEtes603 *self, int n_args, ...)
362 {
363 struct egis_msg *msg = self->req;
364 va_list ap;
365 int i;
366
367 g_assert (n_args != 0 && n_args % 2 == 0 && n_args <= REG_MAX * 2);
368
369 msg_header_prepare (msg);
370 msg->cmd = CMD_WRITE_REG;
371 msg->egis_writereg.nb = n_args / 2;
372
373 va_start (ap, n_args);
374 for (i = 0; i < n_args / 2; i++)
375 {
376 msg->egis_writereg.regs[i].reg = va_arg (ap, int);
377 msg->egis_writereg.regs[i].val = va_arg (ap, int);
378 }
379 va_end (ap);
380
381 self->req_len = MSG_HDR_SIZE + 1 + n_args;
382 self->ans_len = MSG_HDR_SIZE + 1;
383 }
384
385 static int
386 msg_check_ok (FpiDeviceEtes603 *dev)
387 {
388 struct egis_msg *msg = dev->ans;
389
390 if (msg_header_check (msg))
391 goto err;
392 if (msg->cmd != CMD_OK)
393 goto err;
394 return 0;
395 err:
396 return -1;
397 }
398
399 /*
400 * Check the model of the sensor.
401 */
402 static int
403 check_info (FpiDeviceEtes603 *dev)
404 {
405 if (dev->regs[0x70] == 0x4A && dev->regs[0x71] == 0x44 &&
406 dev->regs[0x72] == 0x49 && dev->regs[0x73] == 0x31)
407 return 0;
408 fp_err ("unknown device parameters (REG_70:%02X REG_71:%02X "
409 "REG_FIRMWARE:%02X REG_VERSION:%02X)",
410 dev->regs[0x70], dev->regs[0x71], dev->regs[0x72],
411 dev->regs[0x73]);
412 return -1;
413 }
414
415 static void
416 msg_get_cmd20 (FpiDeviceEtes603 *dev)
417 {
418 struct egis_msg *msg = dev->req;
419
420 msg_header_prepare (msg);
421 msg->cmd = CMD_20;
422 dev->req_len = MSG_HDR_SIZE;
423 }
424
425 static int
426 msg_check_cmd20 (FpiDeviceEtes603 *dev)
427 {
428 struct egis_msg *msg = dev->ans;
429
430 if (msg_header_check (msg))
431 {
432 fp_err ("msg_header_check failed");
433 return -1;
434 }
435 /* status or flashtype/flashinfo or ? */
436 if (msg->cmd != 0x05 ||
437 msg->sige_misc.val[0] != 0x00 ||
438 msg->sige_misc.val[1] != 0x00)
439 fp_warn ("unexpected answer CMD_20 from device(%02X %02X %02X)",
440 msg->cmd, msg->sige_misc.val[0], msg->sige_misc.val[1]);
441
442 return 0;
443 }
444
445 static void
446 msg_get_cmd25 (FpiDeviceEtes603 *dev)
447 {
448 struct egis_msg *msg = dev->req;
449
450 msg_header_prepare (msg);
451 msg->cmd = CMD_25;
452 dev->req_len = MSG_HDR_SIZE;
453 }
454
455 static int
456 msg_check_cmd25 (FpiDeviceEtes603 *dev)
457 {
458 struct egis_msg *msg = dev->ans;
459
460 if (msg_header_check (msg))
461 {
462 fp_err ("msg_header_check failed");
463 goto err;
464 }
465 if (msg->cmd != CMD_OK)
466 {
467 fp_err ("CMD_OK failed");
468 goto err;
469 }
470 /* flashtype or status or ? */
471 if (msg->sige_misc.val[0] != 0x00)
472 fp_warn ("unexpected answer for CMD_25 (%02X)",
473 msg->sige_misc.val[0]);
474 return 0;
475 err:
476 return -1;
477 }
478
479 static void
480 msg_set_mode_control (FpiDeviceEtes603 *self, guint8 mode)
481 {
482 msg_set_regs (self, 2, REG_MODE_CONTROL, mode);
483 }
484
485
486 /* Processing functions */
487
488 /*
489 * Return the brightness of a 4bpp frame
490 */
491 static unsigned int
492 process_get_brightness (guint8 *f, size_t s)
493 {
494 unsigned int i, sum = 0;
495
496 for (i = 0; i < s; i++)
497 {
498 sum += f[i] >> 4;
499 sum += f[i] & 0x0F;
500 }
501 return sum;
502 }
503
504 /*
505 * Return the histogram of a 4bpp frame
506 */
507 static void
508 process_hist (guint8 *f, size_t s, float stat[5])
509 {
510 float hist[16];
511 float black_mean, white_mean;
512 int i;
513
514 /* Clean histogram */
515 for (i = 0; i < 16; i++)
516 hist[i] = 0.0;
517 for (i = 0; i < s; i++)
518 {
519 hist[f[i] >> 4]++;
520 hist[f[i] & 0x0F]++;
521 }
522 /* histogram average */
523 for (i = 0; i < 16; i++)
524 hist[i] = hist[i] / (s * 2);
525 /* Average black/white pixels (full black and full white pixels
526 * are excluded). */
527 black_mean = white_mean = 0.0;
528 for (i = 1; i < 8; i++)
529 black_mean += hist[i];
530 for (i = 8; i < 15; i++)
531 white_mean += hist[i];
532 stat[0] = hist[0];
533 stat[1] = black_mean;
534 stat[2] = black_mean + white_mean;
535 stat[3] = white_mean;
536 stat[4] = hist[15];
537 fp_dbg ("fullb=%6f black=%6f grey=%6f white=%6f fullw=%6f",
538 hist[0], black_mean, black_mean + white_mean, white_mean,
539 hist[15]);
540 }
541
542 /*
543 * Return true if the frame is almost empty.
544 */
545 static int
546 process_frame_empty (guint8 *frame, size_t size)
547 {
548 unsigned int sum = process_get_brightness (frame, size);
549
550 /* Allow an average of 'threshold' luminosity per pixel */
551 if (sum < size)
552 return 1;
553 return 0;
554 }
555
556 /* Transform 4 bits image to 8 bits image */
557 static void
558 process_4to8_bpp (guint8 *input, unsigned int input_size,
559 guint8 *output)
560 {
561 unsigned int i, j = 0;
562
563 for (i = 0; i < input_size; i++, j += 2)
564 {
565 /* 16 gray levels transform to 256 levels using << 4 */
566 output[j] = input[i] & 0xF0;
567 output[j + 1] = input[i] << 4;
568 }
569 }
570
571 /*
572 * Remove duplicated lines at the end of a fingerprint.
573 */
574 static void
575 process_removefpi_end (FpiDeviceEtes603 *dev)
576 {
577 unsigned int i;
578 /* 2 last lines with Fly-Estimation are the empty pattern. */
579 guint8 *pattern = dev->fp + (dev->fp_height - 2) * FE_WIDTH / 2;
580
581 for (i = 2; i < dev->fp_height; i += 2)
582 if (memcmp (pattern, pattern - (i * FE_WIDTH / 2), FE_WIDTH))
583 break;
584 dev->fp_height -= i;
585 fp_dbg ("Removing %d empty lines from image", i - 2);
586 }
587
588 static void
589 reset_param (FpiDeviceEtes603 *dev)
590 {
591 dev->dcoffset = 0;
592 dev->vrt = 0;
593 dev->vrb = 0;
594 dev->gain = 0;
595 }
596
597
598 /* Asynchronous stuff */
599
600 enum {
601 INIT_CHECK_INFO_REQ,
602 INIT_CHECK_INFO_ANS,
603 INIT_CMD20_REQ,
604 INIT_CMD20_ANS,
605 INIT_CMD25_REQ,
606 INIT_CMD25_ANS,
607 INIT_SENSOR_REQ,
608 INIT_SENSOR_ANS,
609 INIT_ENC_REQ,
610 INIT_ENC_ANS,
611 INIT_REGS_REQ,
612 INIT_REGS_ANS,
613 INIT_NUM_STATES
614 };
615
616 enum {
617 TUNEDC_INIT,
618 TUNEDC_SET_DCOFFSET_REQ,
619 TUNEDC_SET_DCOFFSET_ANS,
620 TUNEDC_GET_FRAME_REQ,
621 TUNEDC_GET_FRAME_ANS,
622 TUNEDC_FINAL_SET_REG2122_REQ,
623 TUNEDC_FINAL_SET_REG2122_ANS,
624 TUNEDC_FINAL_SET_GAIN_REQ,
625 TUNEDC_FINAL_SET_GAIN_ANS,
626 TUNEDC_FINAL_SET_DCOFFSET_REQ,
627 TUNEDC_FINAL_SET_DCOFFSET_ANS,
628 TUNEDC_NUM_STATES
629 };
630
631 enum {
632 TUNEVRB_INIT,
633 TUNEVRB_GET_GAIN_REQ,
634 TUNEVRB_GET_GAIN_ANS,
635 TUNEVRB_GET_DCOFFSET_REQ,
636 TUNEVRB_GET_DCOFFSET_ANS,
637 TUNEVRB_SET_DCOFFSET_REQ,
638 TUNEVRB_SET_DCOFFSET_ANS,
639 TUNEVRB_FRAME_REQ,
640 TUNEVRB_FRAME_ANS,
641 TUNEVRB_FINAL_SET_DCOFFSET_REQ,
642 TUNEVRB_FINAL_SET_DCOFFSET_ANS,
643 TUNEVRB_FINAL_SET_REG2627_REQ,
644 TUNEVRB_FINAL_SET_REG2627_ANS,
645 TUNEVRB_FINAL_SET_GAINVRTVRB_REQ,
646 TUNEVRB_FINAL_SET_GAINVRTVRB_ANS,
647 TUNEVRB_FINAL_SET_MODE_SLEEP_REQ,
648 TUNEVRB_FINAL_SET_MODE_SLEEP_ANS,
649 TUNEVRB_NUM_STATES
650 };
651
652 enum {
653 FGR_FPA_INIT_SET_MODE_SLEEP_REQ,
654 FGR_FPA_INIT_SET_MODE_SLEEP_ANS,
655 FGR_FPA_INIT_SET_DCOFFSET_REQ,
656 FGR_FPA_INIT_SET_DCOFFSET_ANS,
657 FGR_FPA_INIT_SET_GAINVRTVRB_REQ,
658 FGR_FPA_INIT_SET_GAINVRTVRB_ANS,
659 FGR_FPA_INIT_SET_VCO_CONTROL_RT_REQ,
660 FGR_FPA_INIT_SET_VCO_CONTROL_RT_ANS,
661 FGR_FPA_INIT_SET_REG04_REQ,
662 FGR_FPA_INIT_SET_REG04_ANS,
663 FGR_FPA_INIT_SET_MODE_SENSOR_REQ,
664 FGR_FPA_INIT_SET_MODE_SENSOR_ANS,
665 FGR_FPA_GET_FRAME_REQ,
666 FGR_FPA_GET_FRAME_ANS,
667 FGR_NUM_STATES
668 };
669
670 enum {
671 CAP_FP_INIT_SET_REG10_REQ,
672 CAP_FP_INIT_SET_REG10_ANS,
673 CAP_FP_INIT_SET_MODE_FP_REQ,
674 CAP_FP_INIT_SET_MODE_FP_ANS,
675 CAP_FP_GET_FP_REQ,
676 CAP_FP_GET_FP_ANS,
677 CAP_NUM_STATES
678 };
679
680 enum {
681 EXIT_SET_REGS_REQ,
682 EXIT_SET_REGS_ANS,
683 EXIT_NUM_STATES
684 };
685
686 static void
687 async_tx (FpDevice *dev, unsigned int ep, void *cb,
688 FpiSsm *ssm)
689 {
690 FpiDeviceEtes603 *self = FPI_DEVICE_ETES603 (dev);
691 FpiUsbTransfer *transfer = fpi_usb_transfer_new (dev);
692 unsigned char *buffer = NULL;
693 int length;
694
695 if (ep == EP_OUT)
696 {
697 buffer = (unsigned char *) self->req;
698 length = self->req_len;
699 }
700 else if (ep == EP_IN)
701 {
702 buffer = (unsigned char *) self->ans;
703 length = self->ans_len;
704 }
705 else
706 {
707 g_assert_not_reached ();
708 }
709 transfer->ssm = ssm;
710 fpi_usb_transfer_fill_bulk_full (transfer, ep, buffer, length, NULL);
711 fpi_usb_transfer_submit (transfer, BULK_TIMEOUT, NULL, cb, NULL);
712 }
713
714
715 static void
716 async_tx_cb (FpiUsbTransfer *transfer, FpDevice *device,
717 gpointer user_data, GError *error)
718 {
719 FpImageDevice *idev = FP_IMAGE_DEVICE (device);
720 FpiDeviceEtes603 *self = FPI_DEVICE_ETES603 (idev);
721
722 if (error)
723 {
724 fp_warn ("transfer is not completed (result: %s)",
725 error->message);
726 fpi_ssm_mark_failed (transfer->ssm, error);
727 }
728 else
729 {
730 unsigned char endpoint = transfer->endpoint;
731 int actual_length = transfer->actual_length;
732 int length = transfer->length;
733
734 if (endpoint == EP_OUT)
735 {
736 if (length != actual_length)
737 fp_warn ("length %d != actual_length %d",
738 length, actual_length);
739
740 /* Chained with the answer */
741 async_tx (device, EP_IN, async_tx_cb, transfer->ssm);
742 }
743 else if (endpoint == EP_IN)
744 {
745 self->ans_len = actual_length;
746 fpi_ssm_next_state (transfer->ssm);
747 }
748 }
749 }
750
751 static void
752 m_exit_state (FpiSsm *ssm, FpDevice *dev)
753 {
754 FpiDeviceEtes603 *self = FPI_DEVICE_ETES603 (dev);
755
756 switch (fpi_ssm_get_cur_state (ssm))
757 {
758 case EXIT_SET_REGS_REQ:
759 msg_set_regs (self, 4, REG_VCO_CONTROL, REG_VCO_IDLE,
760 REG_MODE_CONTROL, REG_MODE_SLEEP);
761 async_tx (dev, EP_OUT, async_tx_cb, ssm);
762 break;
763
764 case EXIT_SET_REGS_ANS:
765 if (msg_check_ok (self))
766 goto err;
767 fpi_ssm_mark_completed (ssm);
768 break;
769
770 default:
771 g_assert_not_reached ();
772 break;
773 }
774
775 return;
776 err:
777 fpi_ssm_mark_failed (ssm, fpi_device_error_new (FP_DEVICE_ERROR_PROTO));
778 }
779
780 static void
781 m_exit_complete (FpiSsm *ssm, FpDevice *dev, GError *error)
782 {
783 FpImageDevice *idev = FP_IMAGE_DEVICE (dev);
784
785 if (error)
786 fp_err ("Error switching the device to idle state");
787 else
788 fp_dbg ("The device is now in idle state");
789 fpi_image_device_deactivate_complete (idev, error);
790 }
791
792 static void
793 m_exit_start (FpImageDevice *idev)
794 {
795 FpiDeviceEtes603 *self = FPI_DEVICE_ETES603 (idev);
796 FpiSsm *ssm = fpi_ssm_new (FP_DEVICE (idev), m_exit_state, EXIT_NUM_STATES);
797
798 self->is_active = FALSE;
799 fp_dbg ("Switching device to idle mode");
800 fpi_ssm_start (ssm, m_exit_complete);
801 }
802
803 static void
804 m_capture_state (FpiSsm *ssm, FpDevice *dev)
805 {
806 FpImageDevice *idev = FP_IMAGE_DEVICE (dev);
807 FpiDeviceEtes603 *self = FPI_DEVICE_ETES603 (dev);
808
809 if (self->is_active == FALSE)
810 {
811 fpi_ssm_mark_completed (ssm);
812 return;
813 }
814
815 switch (fpi_ssm_get_cur_state (ssm))
816 {
817 case CAP_FP_INIT_SET_REG10_REQ:
818 /* Reset fingerprint */
819 fp_dbg ("Capturing a fingerprint...");
820 memset (self->fp, 0, FE_SIZE * 2);
821 self->fp_height = 0;
822 msg_set_regs (self, 2, REG_10, 0x92);
823 async_tx (dev, EP_OUT, async_tx_cb, ssm);
824 break;
825
826 case CAP_FP_INIT_SET_REG10_ANS:
827 if (msg_check_ok (self))
828 goto err;
829 fpi_ssm_next_state (ssm);
830 break;
831
832 case CAP_FP_INIT_SET_MODE_FP_REQ:
833 msg_set_mode_control (self, REG_MODE_FP);
834 async_tx (dev, EP_OUT, async_tx_cb, ssm);
835 break;
836
837 case CAP_FP_INIT_SET_MODE_FP_ANS:
838 if (msg_check_ok (self))
839 goto err;
840 fp_dbg ("Capturing a 1st frame...");
841 fpi_ssm_next_state (ssm);
842 break;
843
844 case CAP_FP_GET_FP_REQ:
845 msg_get_fp (self, 0x01, 0xF4, 0x02, 0x01, 0x64);
846 async_tx (dev, EP_OUT, async_tx_cb, ssm);
847 break;
848
849 case CAP_FP_GET_FP_ANS:
850 memcpy (self->fp + self->fp_height * FE_WIDTH / 2, self->ans,
851 FE_SIZE);
852 self->fp_height += FE_HEIGHT;
853 if (self->fp_height <= FE_HEIGHT)
854 {
855 /* 2 lines are at least removed each time */
856 self->fp_height -= 2;
857 fp_dbg ("Capturing a 2nd frame...");
858 fpi_ssm_jump_to_state (ssm, CAP_FP_GET_FP_REQ);
859 }
860 else
861 {
862 /* Remove empty parts 2 times for the 2 frames */
863 process_removefpi_end (self);
864 process_removefpi_end (self);
865
866 if (self->fp_height >= FE_WIDTH)
867 {
868 FpImage *img = fp_image_new (FE_WIDTH, self->fp_height);
869 unsigned int img_size = self->fp_height * FE_WIDTH;
870
871 /* Images received are white on black, so invert it. */
872 /* TODO detect sweep direction */
873 img->flags = FPI_IMAGE_COLORS_INVERTED | FPI_IMAGE_V_FLIPPED;
874 img->height = self->fp_height;
875 process_4to8_bpp (self->fp, img_size / 2, img->data);
876 fp_dbg ("Sending the raw fingerprint image (%dx%d)",
877 img->width, img->height);
878 fpi_image_device_image_captured (idev, img);
879 }
880 else
881 {
882 fpi_image_device_retry_scan (idev, FP_DEVICE_RETRY_TOO_SHORT);
883 }
884
885 fpi_image_device_report_finger_status (idev, FALSE);
886 fpi_ssm_mark_completed (ssm);
887 }
888 break;
889
890 default:
891 g_assert_not_reached ();
892 break;
893 }
894
895 return;
896 err:
897 fpi_ssm_mark_failed (ssm, fpi_device_error_new (FP_DEVICE_ERROR_PROTO));
898 }
899
900 static void
901 m_capture_complete (FpiSsm *ssm, FpDevice *dev, GError *error)
902 {
903 FpImageDevice *idev = FP_IMAGE_DEVICE (dev);
904 FpiDeviceEtes603 *self = FPI_DEVICE_ETES603 (dev);
905
906 if (error)
907 {
908 if (self->is_active)
909 {
910 fp_err ("Error while capturing fingerprint "
911 "(%s)", error->message);
912 fpi_image_device_session_error (idev, error);
913 }
914 else
915 {
916 g_error_free (error);
917 }
918 }
919
920 if (self->is_active == TRUE)
921 {
922 fp_dbg ("Device is still active, restarting finger detection");
923 m_start_fingerdetect (idev);
924 }
925 else
926 {
927 fp_dbg ("And it's over.");
928 m_exit_start (idev);
929 }
930 }
931
932 static void
933 m_finger_state (FpiSsm *ssm, FpDevice *dev)
934 {
935 FpiDeviceEtes603 *self = FPI_DEVICE_ETES603 (dev);
936
937 if (self->is_active == FALSE)
938 {
939 fpi_ssm_mark_completed (ssm);
940 return;
941 }
942
943 switch (fpi_ssm_get_cur_state (ssm))
944 {
945 case FGR_FPA_INIT_SET_MODE_SLEEP_REQ:
946 msg_set_mode_control (self, REG_MODE_SLEEP);
947 async_tx (dev, EP_OUT, async_tx_cb, ssm);
948 break;
949
950 case FGR_FPA_INIT_SET_MODE_SLEEP_ANS:
951 if (msg_check_ok (self))
952 goto err;
953 fpi_ssm_next_state (ssm);
954 break;
955
956 case FGR_FPA_INIT_SET_DCOFFSET_REQ:
957 msg_set_regs (self, 2, REG_DCOFFSET, self->dcoffset);
958 async_tx (dev, EP_OUT, async_tx_cb, ssm);
959 break;
960
961 case FGR_FPA_INIT_SET_DCOFFSET_ANS:
962 if (msg_check_ok (self))
963 goto err;
964 fpi_ssm_next_state (ssm);
965 break;
966
967 case FGR_FPA_INIT_SET_GAINVRTVRB_REQ:
968 msg_set_regs (self, 6, REG_GAIN, self->gain, REG_VRT,
969 self->vrt,
970 REG_VRB, self->vrb);
971 async_tx (dev, EP_OUT, async_tx_cb, ssm);
972 break;
973
974 case FGR_FPA_INIT_SET_GAINVRTVRB_ANS:
975 if (msg_check_ok (self))
976 goto err;
977 fpi_ssm_next_state (ssm);
978 break;
979
980 case FGR_FPA_INIT_SET_VCO_CONTROL_RT_REQ:
981 msg_set_regs (self, 2, REG_VCO_CONTROL, REG_VCO_RT);
982 async_tx (dev, EP_OUT, async_tx_cb, ssm);
983 break;
984
985 case FGR_FPA_INIT_SET_VCO_CONTROL_RT_ANS:
986 if (msg_check_ok (self))
987 goto err;
988 fpi_ssm_next_state (ssm);
989 break;
990
991 case FGR_FPA_INIT_SET_REG04_REQ:
992 msg_set_regs (self, 2, REG_04, 0x00);
993 async_tx (dev, EP_OUT, async_tx_cb, ssm);
994 break;
995
996 case FGR_FPA_INIT_SET_REG04_ANS:
997 if (msg_check_ok (self))
998 goto err;
999 fpi_ssm_next_state (ssm);
1000 break;
1001
1002 case FGR_FPA_INIT_SET_MODE_SENSOR_REQ:
1003 msg_set_mode_control (self, REG_MODE_SENSOR);
1004 async_tx (dev, EP_OUT, async_tx_cb, ssm);
1005 break;
1006
1007 case FGR_FPA_INIT_SET_MODE_SENSOR_ANS:
1008 if (msg_check_ok (self))
1009 goto err;
1010 fpi_ssm_next_state (ssm);
1011 break;
1012
1013 case FGR_FPA_GET_FRAME_REQ:
1014 msg_get_frame (self, 0x00, 0x00, 0x00, 0x00);
1015 async_tx (dev, EP_OUT, async_tx_cb, ssm);
1016 break;
1017
1018 case FGR_FPA_GET_FRAME_ANS:
1019 if (process_frame_empty ((guint8 *) self->ans, FRAME_SIZE))
1020 {
1021 fpi_ssm_jump_to_state (ssm, FGR_FPA_GET_FRAME_REQ);
1022 }
1023 else
1024 {
1025 fpi_image_device_report_finger_status (FP_IMAGE_DEVICE (dev), TRUE);
1026 fpi_ssm_mark_completed (ssm);
1027 }
1028 break;
1029
1030 default:
1031 g_assert_not_reached ();
1032 break;
1033 }
1034
1035 return;
1036 err:
1037 fpi_ssm_mark_failed (ssm, fpi_device_error_new (FP_DEVICE_ERROR_PROTO));
1038 }
1039
1040 static void
1041 m_finger_complete (FpiSsm *ssm, FpDevice *dev, GError *error)
1042 {
1043 FpImageDevice *idev = FP_IMAGE_DEVICE (dev);
1044 FpiDeviceEtes603 *self = FPI_DEVICE_ETES603 (dev);
1045
1046 if (!error)
1047 {
1048 FpiSsm *ssm_cap;
1049 ssm_cap = fpi_ssm_new (dev, m_capture_state, CAP_NUM_STATES);
1050 fpi_ssm_start (ssm_cap, m_capture_complete);
1051 }
1052 else
1053 {
1054 if (self->is_active)
1055 {
1056 fp_err ("Error while capturing fingerprint "
1057 "(%s)", error->message);
1058 fpi_image_device_session_error (idev, error);
1059 }
1060 else
1061 {
1062 m_exit_start (idev);
1063 g_error_free (error);
1064 }
1065 self->is_active = FALSE;
1066 }
1067
1068 }
1069
1070 static void
1071 m_start_fingerdetect (FpImageDevice *idev)
1072 {
1073 FpiSsm *ssmf;
1074
1075 ssmf = fpi_ssm_new (FP_DEVICE (idev), m_finger_state, FGR_NUM_STATES);
1076 fpi_ssm_start (ssmf, m_finger_complete);
1077 }
1078
1079 /*
1080 * Tune value of VRT and VRB for contrast and brightness.
1081 */
1082 static void
1083 m_tunevrb_state (FpiSsm *ssm, FpDevice *dev)
1084 {
1085 FpiDeviceEtes603 *self = FPI_DEVICE_ETES603 (dev);
1086 float hist[5];
1087
1088 if (self->is_active == FALSE)
1089 {
1090 fpi_ssm_mark_completed (ssm);
1091 return;
1092 }
1093
1094 switch (fpi_ssm_get_cur_state (ssm))
1095 {
1096 case TUNEVRB_INIT:
1097 fp_dbg ("Tuning of VRT/VRB");
1098 g_assert (self->dcoffset);
1099 /* VRT(reg E1)=0x0A and VRB(reg E2)=0x10 are starting values */
1100 self->vrt = 0x0A;
1101 self->vrb = 0x10;
1102 fpi_ssm_next_state (ssm);
1103 break;
1104
1105 case TUNEVRB_GET_GAIN_REQ:
1106 msg_get_regs (self, 1, REG_GAIN);
1107 async_tx (dev, EP_OUT, async_tx_cb, ssm);
1108 break;
1109
1110 case TUNEVRB_GET_GAIN_ANS:
1111 if (msg_parse_regs (self))
1112 goto err;
1113 fpi_ssm_next_state (ssm);
1114 break;
1115
1116 case TUNEVRB_GET_DCOFFSET_REQ:
1117 msg_get_regs (self, 1, REG_DCOFFSET);
1118 async_tx (dev, EP_OUT, async_tx_cb, ssm);
1119 break;
1120
1121 case TUNEVRB_GET_DCOFFSET_ANS:
1122 if (msg_parse_regs (self))
1123 goto err;
1124 fpi_ssm_next_state (ssm);
1125 break;
1126
1127 case TUNEVRB_SET_DCOFFSET_REQ:
1128 /* Reduce DCoffset by 1 to allow tuning */
1129 msg_set_regs (self, 2, REG_DCOFFSET, self->dcoffset - 1);
1130 async_tx (dev, EP_OUT, async_tx_cb, ssm);
1131 break;
1132
1133 case TUNEVRB_SET_DCOFFSET_ANS:
1134 if (msg_check_ok (self))
1135 goto err;
1136 fpi_ssm_next_state (ssm);
1137 break;
1138
1139 case TUNEVRB_FRAME_REQ:
1140 fp_dbg ("Testing VRT=0x%02X VRB=0x%02X", self->vrt, self->vrb);
1141 msg_get_frame (self, 0x01, self->gain, self->vrt, self->vrb);
1142 async_tx (dev, EP_OUT, async_tx_cb, ssm);
1143 break;
1144
1145 case TUNEVRB_FRAME_ANS:
1146 process_hist ((guint8 *) self->ans, FRAME_SIZE, hist);
1147 /* Note that this tuning could probably be improved */
1148 if (hist[0] + hist[1] > 0.95)
1149 {
1150 if (self->vrt <= 0 || self->vrb <= 0)
1151 {
1152 fp_dbg ("Image is too dark, reducing DCOffset");
1153 self->dcoffset--;
1154 fpi_ssm_jump_to_state (ssm, TUNEVRB_INIT);
1155 }
1156 else
1157 {
1158 self->vrt--;
1159 self->vrb--;
1160 fpi_ssm_jump_to_state (ssm, TUNEVRB_FRAME_REQ);
1161 }
1162 break;
1163 }
1164 if (hist[4] > 0.95)
1165 {
1166 fp_dbg ("Image is too bright, increasing DCOffset");
1167 self->dcoffset++;
1168 fpi_ssm_jump_to_state (ssm, TUNEVRB_INIT);
1169 break;
1170 }
1171 if (hist[4] + hist[3] > 0.4)
1172 {
1173 if (self->vrt >= 2 * self->vrb - 0x0a)
1174 {
1175 self->vrt++;
1176 self->vrb++;
1177 }
1178 else
1179 {
1180 self->vrt++;
1181 }
1182 /* Check maximum for vrt/vrb */
1183 /* TODO if maximum is reached, leave with an error? */
1184 if (self->vrt > VRT_MAX)
1185 self->vrt = VRT_MAX;
1186 if (self->vrb > VRB_MAX)
1187 self->vrb = VRB_MAX;
1188 fpi_ssm_jump_to_state (ssm, TUNEVRB_FRAME_REQ);
1189 break;
1190 }
1191 fpi_ssm_next_state (ssm);
1192 break;
1193
1194 case TUNEVRB_FINAL_SET_DCOFFSET_REQ:
1195 fp_dbg ("-> VRT=0x%02X VRB=0x%02X", self->vrt, self->vrb);
1196 /* Reset the DCOffset */
1197 msg_set_regs (self, 2, REG_DCOFFSET, self->dcoffset);
1198 async_tx (dev, EP_OUT, async_tx_cb, ssm);
1199 break;
1200
1201 case TUNEVRB_FINAL_SET_DCOFFSET_ANS:
1202 if (msg_check_ok (self))
1203 goto err;
1204 fpi_ssm_next_state (ssm);
1205 break;
1206
1207 case TUNEVRB_FINAL_SET_REG2627_REQ:
1208 /* In traces, REG_26/REG_27 are set. purpose? values? */
1209 msg_set_regs (self, 4, REG_26, 0x11, REG_27, 0x00);
1210 async_tx (dev, EP_OUT, async_tx_cb, ssm);
1211 break;
1212
1213 case TUNEVRB_FINAL_SET_REG2627_ANS:
1214 if (msg_check_ok (self))
1215 goto err;
1216 fpi_ssm_next_state (ssm);
1217 break;
1218
1219 case TUNEVRB_FINAL_SET_GAINVRTVRB_REQ:
1220 /* Set Gain/VRT/VRB values found */
1221 msg_set_regs (self, 6, REG_GAIN, self->gain, REG_VRT,
1222 self->vrt,
1223 REG_VRB, self->vrb);
1224 async_tx (dev, EP_OUT, async_tx_cb, ssm);
1225 break;
1226
1227 case TUNEVRB_FINAL_SET_GAINVRTVRB_ANS:
1228 if (msg_check_ok (self))
1229 goto err;
1230 /* In traces, Gain/VRT/VRB are read again. */
1231 fpi_ssm_next_state (ssm);
1232 break;
1233
1234 case TUNEVRB_FINAL_SET_MODE_SLEEP_REQ:
1235 msg_set_mode_control (self, REG_MODE_SLEEP);
1236 async_tx (dev, EP_OUT, async_tx_cb, ssm);
1237 break;
1238
1239 case TUNEVRB_FINAL_SET_MODE_SLEEP_ANS:
1240 if (msg_check_ok (self))
1241 goto err;
1242 fpi_ssm_mark_completed (ssm);
1243 break;
1244
1245 default:
1246 g_assert_not_reached ();
1247 break;
1248 }
1249
1250 return;
1251 err:
1252 fpi_ssm_mark_failed (ssm, fpi_device_error_new (FP_DEVICE_ERROR_PROTO));
1253 }
1254
1255 static void
1256 m_tunevrb_complete (FpiSsm *ssm, FpDevice *dev, GError *error)
1257 {
1258 FpiDeviceEtes603 *self = FPI_DEVICE_ETES603 (dev);
1259 FpImageDevice *idev = FP_IMAGE_DEVICE (dev);
1260
1261 fpi_image_device_activate_complete (idev, error);
1262 if (!error)
1263 {
1264 fp_dbg ("Tuning is done. Starting finger detection.");
1265 m_start_fingerdetect (idev);
1266 }
1267
1268 if (!self->is_active)
1269 m_exit_start (idev);
1270
1271 }
1272
1273 /*
1274 * This function tunes the DCoffset value and adjusts the gain value if
1275 * required.
1276 */
1277 static void
1278 m_tunedc_state (FpiSsm *ssm, FpDevice *dev)
1279 {
1280 FpiDeviceEtes603 *self = FPI_DEVICE_ETES603 (dev);
1281
1282 if (self->is_active == FALSE)
1283 {
1284 fpi_ssm_mark_completed (ssm);
1285 return;
1286 }
1287
1288 /* TODO To get better results, tuning could be done 3 times as in
1289 * captured traffic to make sure that the value is correct. */
1290 /* The default gain should work but it may reach a DCOffset limit so in
1291 * this case we decrease the gain. */
1292 switch (fpi_ssm_get_cur_state (ssm))
1293 {
1294 case TUNEDC_INIT:
1295 /* reg_e0 = 0x23 is sensor normal/small gain */
1296 self->gain = GAIN_SMALL_INIT;
1297 self->tunedc_min = DCOFFSET_MIN;
1298 self->tunedc_max = DCOFFSET_MAX;
1299 fp_dbg ("Tuning DCoffset");
1300 fpi_ssm_next_state (ssm);
1301 break;
1302
1303 case TUNEDC_SET_DCOFFSET_REQ:
1304 /* Dichotomic search to find at which value the frame becomes
1305 * almost black. */
1306 self->dcoffset = (self->tunedc_max + self->tunedc_min) / 2;
1307 fp_dbg ("Testing DCoffset=0x%02X Gain=0x%02X", self->dcoffset,
1308 self->gain);
1309 msg_set_regs (self, 2, REG_DCOFFSET, self->dcoffset);
1310 async_tx (dev, EP_OUT, async_tx_cb, ssm);
1311 break;
1312
1313 case TUNEDC_SET_DCOFFSET_ANS:
1314 if (msg_check_ok (self))
1315 goto err;
1316 fpi_ssm_next_state (ssm);
1317 break;
1318
1319 case TUNEDC_GET_FRAME_REQ:
1320 /* vrt:0x15 vrb:0x10 are constant in all tuning frames. */
1321 msg_get_frame (self, 0x01, self->gain, 0x15, 0x10);
1322 async_tx (dev, EP_OUT, async_tx_cb, ssm);
1323 break;
1324
1325 case TUNEDC_GET_FRAME_ANS:
1326 if (process_frame_empty ((guint8 *) self->ans, FRAME_WIDTH))
1327 self->tunedc_max = self->dcoffset;
1328 else
1329 self->tunedc_min = self->dcoffset;
1330 if (self->tunedc_min + 1 < self->tunedc_max)
1331 {
1332 fpi_ssm_jump_to_state (ssm, TUNEDC_SET_DCOFFSET_REQ);
1333 }
1334 else if (self->tunedc_max < DCOFFSET_MAX)
1335 {
1336 self->dcoffset = self->tunedc_max + 1;
1337 fpi_ssm_next_state (ssm);
1338 }
1339 else
1340 {
1341 self->gain--;
1342 fpi_ssm_jump_to_state (ssm, TUNEDC_SET_DCOFFSET_REQ);
1343 }
1344 break;
1345
1346 case TUNEDC_FINAL_SET_REG2122_REQ:
1347 fp_dbg ("-> DCoffset=0x%02X Gain=0x%02X", self->dcoffset,
1348 self->gain);
1349 /* ??? how reg21 / reg22 are calculated */
1350 msg_set_regs (self, 4, REG_21, 0x23, REG_22, 0x21);
1351 async_tx (dev, EP_OUT, async_tx_cb, ssm);
1352 break;
1353
1354 case TUNEDC_FINAL_SET_REG2122_ANS:
1355 if (msg_check_ok (self))
1356 goto err;
1357 fpi_ssm_next_state (ssm);
1358 break;
1359
1360 case TUNEDC_FINAL_SET_GAIN_REQ:
1361 msg_set_regs (self, 2, REG_GAIN, self->gain);
1362 async_tx (dev, EP_OUT, async_tx_cb, ssm);
1363 break;
1364
1365 case TUNEDC_FINAL_SET_GAIN_ANS:
1366 fpi_ssm_next_state (ssm);
1367 break;
1368
1369 case TUNEDC_FINAL_SET_DCOFFSET_REQ:
1370 msg_set_regs (self, 2, REG_DCOFFSET, self->dcoffset);
1371 async_tx (dev, EP_OUT, async_tx_cb, ssm);
1372 break;
1373
1374 case TUNEDC_FINAL_SET_DCOFFSET_ANS:
1375 /* In captured traffic, read GAIN, VRT, and VRB registers. */
1376 if (msg_check_ok (self))
1377 goto err;
1378 fpi_ssm_mark_completed (ssm);
1379 break;
1380
1381 default:
1382 g_assert_not_reached ();
1383 break;
1384 }
1385
1386 return;
1387 err:
1388 fpi_ssm_mark_failed (ssm, fpi_device_error_new (FP_DEVICE_ERROR_PROTO));
1389 }
1390
1391 static void
1392 m_tunedc_complete (FpiSsm *ssm, FpDevice *dev, GError *error)
1393 {
1394 FpiDeviceEtes603 *self = FPI_DEVICE_ETES603 (dev);
1395 FpImageDevice *idev = FP_IMAGE_DEVICE (dev);
1396
1397 if (!error)
1398 {
1399 FpiSsm *ssm_tune;
1400 ssm_tune = fpi_ssm_new (FP_DEVICE (idev), m_tunevrb_state,
1401 TUNEVRB_NUM_STATES);
1402 fpi_ssm_start (ssm_tune, m_tunevrb_complete);
1403 }
1404 else
1405 {
1406 fp_err ("Error while tuning DCOFFSET");
1407 reset_param (FPI_DEVICE_ETES603 (dev));
1408 fpi_image_device_session_error (idev, error);
1409 }
1410
1411 if (!self->is_active)
1412 m_exit_start (idev);
1413
1414 }
1415
1416 static void
1417 m_init_state (FpiSsm *ssm, FpDevice *dev)
1418 {
1419 FpiDeviceEtes603 *self = FPI_DEVICE_ETES603 (dev);
1420
1421 if (self->is_active == FALSE)
1422 {
1423 fpi_ssm_mark_completed (ssm);
1424 return;
1425 }
1426
1427 switch (fpi_ssm_get_cur_state (ssm))
1428 {
1429 case INIT_CHECK_INFO_REQ:
1430 msg_get_regs (self, 4, REG_INFO0, REG_INFO1, REG_INFO2,
1431 REG_INFO3);
1432 async_tx (dev, EP_OUT, async_tx_cb, ssm);
1433 break;
1434
1435 case INIT_CHECK_INFO_ANS:
1436 if (msg_parse_regs (self))
1437 goto err;
1438 if (check_info (self))
1439 goto err;
1440 fpi_ssm_next_state (ssm);
1441 break;
1442
1443 case INIT_CMD20_REQ:
1444 msg_get_cmd20 (self);
1445 async_tx (dev, EP_OUT, async_tx_cb, ssm);
1446 break;
1447
1448 case INIT_CMD20_ANS:
1449 if (msg_check_cmd20 (self))
1450 goto err;
1451 fpi_ssm_next_state (ssm);
1452 break;
1453
1454 case INIT_CMD25_REQ:
1455 msg_get_cmd25 (self);
1456 async_tx (dev, EP_OUT, async_tx_cb, ssm);
1457 break;
1458
1459 case INIT_CMD25_ANS:
1460 if (msg_check_cmd25 (self))
1461 goto err;
1462 fpi_ssm_next_state (ssm);
1463 break;
1464
1465 case INIT_SENSOR_REQ:
1466 /* In captured traffic, those are split. */
1467 msg_set_regs (self, 18, REG_MODE_CONTROL, REG_MODE_SLEEP,
1468 REG_50, 0x0F, REG_GAIN, 0x04, REG_VRT, 0x08,
1469 REG_VRB, 0x0D, REG_VCO_CONTROL, REG_VCO_RT,
1470 REG_DCOFFSET, 0x36, REG_F0, 0x00, REG_F2, 0x00);
1471 async_tx (dev, EP_OUT, async_tx_cb, ssm);
1472 break;
1473
1474 case INIT_SENSOR_ANS:
1475 if (msg_check_ok (self))
1476 goto err;
1477 fpi_ssm_next_state (ssm);
1478 break;
1479
1480 case INIT_ENC_REQ:
1481 /* Initialize encryption registers without encryption. */
1482 /* Set registers from 0x41 to 0x48 (0x8 regs) */
1483 msg_set_regs (self, 16, REG_ENC1, 0x12, REG_ENC2, 0x34,
1484 REG_ENC3, 0x56, REG_ENC4, 0x78, REG_ENC5, 0x90,
1485 REG_ENC6, 0xAB, REG_ENC7, 0xCD, REG_ENC8, 0xEF);
1486 async_tx (dev, EP_OUT, async_tx_cb, ssm);
1487 break;
1488
1489 case INIT_ENC_ANS:
1490 if (msg_check_ok (self))
1491 goto err;
1492 fpi_ssm_next_state (ssm);
1493 break;
1494
1495 case INIT_REGS_REQ:
1496 /* Set register from 0x20 to 0x37 (0x18 regs) */
1497 msg_set_regs (self, 48,
1498 REG_20, 0x00, REG_21, 0x23, REG_22, 0x21, REG_23,
1499 0x20,
1500 REG_24, 0x14, REG_25, 0x6A, REG_26, 0x00, REG_27,
1501 0x00,
1502 REG_28, 0x00, REG_29, 0xC0, REG_2A, 0x50, REG_2B,
1503 0x50,
1504 REG_2C, 0x4D, REG_2D, 0x03, REG_2E, 0x06, REG_2F,
1505 0x06,
1506 REG_30, 0x10, REG_31, 0x02, REG_32, 0x14, REG_33,
1507 0x34,
1508 REG_34, 0x01, REG_35, 0x08, REG_36, 0x03, REG_37,
1509 0x21);
1510 async_tx (dev, EP_OUT, async_tx_cb, ssm);
1511 break;
1512
1513 case INIT_REGS_ANS:
1514 if (msg_check_ok (self))
1515 goto err;
1516 fpi_ssm_mark_completed (ssm);
1517 break;
1518
1519 default:
1520 g_assert_not_reached ();
1521 break;
1522 }
1523
1524 return;
1525 err:
1526 fpi_ssm_mark_failed (ssm, fpi_device_error_new (FP_DEVICE_ERROR_PROTO));
1527 }
1528
1529 static void
1530 m_init_complete (FpiSsm *ssm, FpDevice *dev, GError *error)
1531 {
1532 FpImageDevice *idev = FP_IMAGE_DEVICE (dev);
1533
1534 if (!error)
1535 {
1536 FpiSsm *ssm_tune;
1537 ssm_tune = fpi_ssm_new (FP_DEVICE (idev), m_tunedc_state,
1538 TUNEDC_NUM_STATES);
1539 fpi_ssm_start (ssm_tune, m_tunedc_complete);
1540 }
1541 else
1542 {
1543 fp_err ("Error initializing the device");
1544 reset_param (FPI_DEVICE_ETES603 (dev));
1545 fpi_image_device_session_error (idev, error);
1546 }
1547 }
1548
1549 static void
1550 dev_activate (FpImageDevice *idev)
1551 {
1552 FpiDeviceEtes603 *self = FPI_DEVICE_ETES603 (idev);
1553 FpiSsm *ssm;
1554
1555 g_assert (self);
1556
1557 /* Reset info and data */
1558 self->is_active = TRUE;
1559
1560 if (self->dcoffset == 0)
1561 {
1562 fp_dbg ("Tuning device...");
1563 ssm = fpi_ssm_new (FP_DEVICE (idev), m_init_state, INIT_NUM_STATES);
1564 fpi_ssm_start (ssm, m_init_complete);
1565 }
1566 else
1567 {
1568 fp_dbg ("Using previous tuning (DCOFFSET=0x%02X,VRT=0x%02X,"
1569 "VRB=0x%02X,GAIN=0x%02X).", self->dcoffset, self->vrt,
1570 self->vrb, self->gain);
1571 fpi_image_device_activate_complete (idev, NULL);
1572 ssm = fpi_ssm_new (FP_DEVICE (idev), m_finger_state, FGR_NUM_STATES);
1573 fpi_ssm_start (ssm, m_finger_complete);
1574 }
1575 }
1576
1577 static void
1578 dev_deactivate (FpImageDevice *idev)
1579 {
1580 FpiDeviceEtes603 *self = FPI_DEVICE_ETES603 (idev);
1581
1582 fp_dbg ("deactivating");
1583
1584 /* this can be called even if still activated. */
1585 if (self->is_active == TRUE)
1586 self->is_active = FALSE;
1587 else
1588 m_exit_start (idev);
1589 }
1590
1591 static void
1592 dev_open (FpImageDevice *idev)
1593 {
1594 GError *error = NULL;
1595 FpiDeviceEtes603 *self = FPI_DEVICE_ETES603 (idev);
1596
1597 if (!g_usb_device_claim_interface (fpi_device_get_usb_device (FP_DEVICE (idev)), 0, 0, &error))
1598 {
1599 fpi_image_device_open_complete (idev, error);
1600 return;
1601 }
1602
1603 self->req = g_malloc (sizeof (struct egis_msg));
1604 self->ans = g_malloc (FE_SIZE);
1605 self->fp = g_malloc (FE_SIZE * 4);
1606
1607 fpi_image_device_open_complete (idev, NULL);
1608 }
1609
1610 static void
1611 dev_close (FpImageDevice *idev)
1612 {
1613 GError *error = NULL;
1614 FpiDeviceEtes603 *self = FPI_DEVICE_ETES603 (idev);
1615
1616 g_free (self->req);
1617 g_free (self->ans);
1618 g_free (self->fp);
1619
1620 g_usb_device_release_interface (fpi_device_get_usb_device (FP_DEVICE (idev)),
1621 0, 0, &error);
1622 fpi_image_device_close_complete (idev, error);
1623 }
1624
1625 static const FpIdEntry id_table[] = {
1626 /* EgisTec (aka Lightuning) ES603 */
1627 { .vid = 0x1c7a, .pid = 0x0603, },
1628 { .vid = 0, .pid = 0, .driver_data = 0 },
1629 };
1630
1631 static void
1632 fpi_device_etes603_init (FpiDeviceEtes603 *self)
1633 {
1634 }
1635 static void
1636 120 fpi_device_etes603_class_init (FpiDeviceEtes603Class *klass)
1637 {
1638 120 FpDeviceClass *dev_class = FP_DEVICE_CLASS (klass);
1639 120 FpImageDeviceClass *img_class = FP_IMAGE_DEVICE_CLASS (klass);
1640
1641 120 dev_class->id = "etes603";
1642 120 dev_class->full_name = "EgisTec ES603";
1643 120 dev_class->type = FP_DEVICE_TYPE_USB;
1644 120 dev_class->id_table = id_table;
1645 120 dev_class->scan_type = FP_SCAN_TYPE_SWIPE;
1646
1647 120 img_class->img_open = dev_open;
1648 120 img_class->img_close = dev_close;
1649 120 img_class->activate = dev_activate;
1650 120 img_class->deactivate = dev_deactivate;
1651
1652 120 img_class->img_width = 256;
1653 120 img_class->img_height = -1;
1654 }
1655