2 * AuthenTec AES2501 driver for libfprint
3 * Copyright (C) 2007 Daniel Drake <dsd@gentoo.org>
4 * Copyright (C) 2007 Cyrille Bagard
5 * Copyright (C) 2007 Vasily Khoruzhick
7 * Based on code from http://home.gna.org/aes2501, relicensed with permission
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.
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.
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
24 #define FP_COMPONENT "aes2501"
31 #include <fp_internal.h>
34 /* FIXME these need checking */
35 #define EP_IN (1 | USB_ENDPOINT_IN)
36 #define EP_OUT (2 | USB_ENDPOINT_OUT)
38 #define BULK_TIMEOUT 4000
41 * The AES2501 is an imaging device using a swipe-type sensor. It samples
42 * the finger at preprogrammed intervals, sending a 192x16 frame to the
44 * Unless the user is scanning their finger unreasonably fast, the frames
45 * *will* overlap. The implementation below detects this overlap and produces
46 * a contiguous image as the end result.
47 * The fact that the user determines the length of the swipe (and hence the
48 * number of useful frames) and also the fact that overlap varies means that
49 * images returned from this driver vary in height.
52 #define FRAME_WIDTH 192
53 #define FRAME_HEIGHT 16
54 #define FRAME_SIZE (FRAME_WIDTH * FRAME_HEIGHT)
55 /* maximum number of frames to read during a scan */
56 /* FIXME reduce substantially */
57 #define MAX_FRAMES 150
59 struct aes2501_regwrite
{
64 static int write_reg(struct fp_img_dev
*dev
, unsigned char reg
,
67 unsigned char data
[] = { reg
, value
};
70 fp_dbg("%02x=%02x", reg
, value
);
71 r
= usb_bulk_write(dev
->udev
, EP_OUT
, data
, sizeof(data
), BULK_TIMEOUT
);
73 fp_err("bulk write error %d", r
);
75 } else if (r
< sizeof(data
)) {
76 fp_err("unexpected short write %d/%d", r
, sizeof(data
));
83 static int write_regv(struct fp_img_dev
*dev
, struct aes2501_regwrite
*regs
,
89 /* FIXME: could combine multiple writes into a single transaction */
91 for (i
= 0; i
< num
; i
++) {
92 r
= write_reg(dev
, regs
[i
].reg
, regs
[i
].value
);
99 static int read_data(struct fp_img_dev
*dev
, unsigned char *data
, size_t len
)
102 fp_dbg("len=%zd", len
);
104 r
= usb_bulk_read(dev
->udev
, EP_IN
, data
, len
, BULK_TIMEOUT
);
106 fp_err("bulk read error %d", r
);
108 } else if (r
< len
) {
109 fp_err("unexpected short read %d/%zd", r
, len
);
115 static int read_regs(struct fp_img_dev
*dev
, unsigned char *data
)
120 r
= write_reg(dev
, AES2501_REG_CTRL2
, AES2501_CTRL2_READ_REGS
);
124 return read_data(dev
, data
, 126);
127 static const struct aes2501_regwrite init_1
[] = {
128 { AES2501_REG_CTRL1
, AES2501_CTRL1_MASTER_RESET
},
129 { 0xb0, 0x27 }, /* Reserved? */
130 { AES2501_REG_CTRL1
, AES2501_CTRL1_MASTER_RESET
},
131 { AES2501_REG_EXCITCTRL
, 0x40 },
132 { 0xff, 0x00 }, /* Reserved? */
133 { 0xff, 0x00 }, /* Reserved? */
134 { 0xff, 0x00 }, /* Reserved? */
135 { 0xff, 0x00 }, /* Reserved? */
136 { 0xff, 0x00 }, /* Reserved? */
137 { 0xff, 0x00 }, /* Reserved? */
138 { 0xff, 0x00 }, /* Reserved? */
139 { 0xff, 0x00 }, /* Reserved? */
140 { 0xff, 0x00 }, /* Reserved? */
141 { 0xff, 0x00 }, /* Reserved? */
142 { 0xff, 0x00 }, /* Reserved? */
143 { AES2501_REG_CTRL1
, AES2501_CTRL1_MASTER_RESET
},
144 { AES2501_REG_EXCITCTRL
, 0x40 },
145 { AES2501_REG_DETCTRL
,
146 AES2501_DETCTRL_DRATE_CONTINUOUS
| AES2501_DETCTRL_SDELAY_31_MS
},
147 { AES2501_REG_COLSCAN
, AES2501_COLSCAN_SRATE_128_US
},
148 { AES2501_REG_MEASDRV
,
149 AES2501_MEASDRV_MDRIVE_0_325
| AES2501_MEASDRV_MEASURE_SQUARE
},
150 { AES2501_REG_MEASFREQ
, AES2501_MEASFREQ_2M
},
151 { AES2501_REG_DEMODPHASE1
, DEMODPHASE_NONE
},
152 { AES2501_REG_DEMODPHASE2
, DEMODPHASE_NONE
},
153 { AES2501_REG_CHANGAIN
,
154 AES2501_CHANGAIN_STAGE2_4X
| AES2501_CHANGAIN_STAGE1_16X
},
155 { AES2501_REG_ADREFHI
, 0x44 },
156 { AES2501_REG_ADREFLO
, 0x34 },
157 { AES2501_REG_STRTCOL
, 0x16 },
158 { AES2501_REG_ENDCOL
, 0x16 },
159 { AES2501_REG_DATFMT
, AES2501_DATFMT_BIN_IMG
| 0x08 },
160 { AES2501_REG_TREG1
, 0x70 },
163 { AES2501_REG_TREGC
, AES2501_TREGC_ENABLE
},
164 { AES2501_REG_TREGD
, 0x1a },
165 { AES2501_REG_CTRL1
, AES2501_CTRL1_REG_UPDATE
},
166 { AES2501_REG_CTRL2
, AES2501_CTRL2_SET_ONE_SHOT
},
167 { AES2501_REG_LPONT
, AES2501_LPONT_MIN_VALUE
},
170 static const struct aes2501_regwrite init_2
[] = {
171 { AES2501_REG_CTRL1
, AES2501_CTRL1_MASTER_RESET
},
172 { AES2501_REG_EXCITCTRL
, 0x40 },
173 { AES2501_REG_CTRL1
, AES2501_CTRL1_MASTER_RESET
},
174 { AES2501_REG_AUTOCALOFFSET
, 0x41 },
175 { AES2501_REG_EXCITCTRL
, 0x42 },
176 { AES2501_REG_DETCTRL
, 0x53 },
177 { AES2501_REG_CTRL1
, AES2501_CTRL1_REG_UPDATE
},
180 static const struct aes2501_regwrite init_3
[] = {
182 { AES2501_REG_CTRL1
, AES2501_CTRL1_MASTER_RESET
},
183 { AES2501_REG_AUTOCALOFFSET
, 0x41 },
184 { AES2501_REG_EXCITCTRL
, 0x42 },
185 { AES2501_REG_DETCTRL
, 0x53 },
186 { AES2501_REG_CTRL1
, AES2501_CTRL1_REG_UPDATE
},
189 static const struct aes2501_regwrite init_4
[] = {
190 { AES2501_REG_CTRL1
, AES2501_CTRL1_MASTER_RESET
},
191 { AES2501_REG_EXCITCTRL
, 0x40 },
193 { AES2501_REG_ENDROW
, 0x0a },
194 { AES2501_REG_CTRL1
, AES2501_CTRL1_REG_UPDATE
},
195 { AES2501_REG_DETCTRL
, 0x45 },
196 { AES2501_REG_AUTOCALOFFSET
, 0x41 },
199 static const struct aes2501_regwrite init_5
[] = {
201 { AES2501_REG_CTRL1
, AES2501_CTRL1_MASTER_RESET
},
202 { AES2501_REG_EXCITCTRL
, 0x40 },
204 { AES2501_REG_CTRL1
, AES2501_CTRL1_MASTER_RESET
},
205 { AES2501_REG_EXCITCTRL
, 0x40 },
206 { AES2501_REG_CTRL1
, AES2501_CTRL1_MASTER_RESET
},
207 { AES2501_REG_EXCITCTRL
, 0x40 },
208 { AES2501_REG_CTRL1
, AES2501_CTRL1_MASTER_RESET
},
209 { AES2501_REG_EXCITCTRL
, 0x40 },
210 { AES2501_REG_CTRL1
, AES2501_CTRL1_MASTER_RESET
},
211 { AES2501_REG_EXCITCTRL
, 0x40 },
212 { AES2501_REG_CTRL1
, AES2501_CTRL1_MASTER_RESET
},
213 { AES2501_REG_EXCITCTRL
, 0x40 },
214 { AES2501_REG_CTRL1
, AES2501_CTRL1_SCAN_RESET
},
215 { AES2501_REG_CTRL1
, AES2501_CTRL1_SCAN_RESET
},
218 static int do_init(struct fp_img_dev
*dev
)
220 unsigned char buffer
[128];
224 /* part 1, probably not needed */
225 r
= write_regv(dev
, init_1
, ARRAY_SIZE(init_1
));
229 r
= read_data(dev
, buffer
, 20);
234 r
= write_regv(dev
, init_2
, ARRAY_SIZE(init_2
));
238 r
= read_regs(dev
, buffer
);
243 fp_dbg("reg 0xaf = %x", buffer
[0x5f]);
245 while (buffer
[0x5f] == 0x6b) {
246 r
= write_regv(dev
, init_3
, ARRAY_SIZE(init_3
));
249 r
= read_regs(dev
, buffer
);
257 r
= write_regv(dev
, init_4
, ARRAY_SIZE(init_4
));
262 return write_regv(dev
, init_5
, ARRAY_SIZE(init_5
));
265 static int dev_init(struct fp_img_dev
*dev
, unsigned long driver_data
)
269 r
= usb_claim_interface(dev
->udev
, 0);
271 fp_err("could not claim interface 0");
275 /* FIXME check endpoints */
280 static void dev_exit(struct fp_img_dev
*dev
)
282 usb_release_interface(dev
->udev
, 0);
285 static const struct aes2501_regwrite finger_det_reqs
[] = {
286 { AES2501_REG_CTRL1
, AES2501_CTRL1_MASTER_RESET
},
287 { AES2501_REG_EXCITCTRL
, 0x40 },
288 { AES2501_REG_DETCTRL
,
289 AES2501_DETCTRL_DRATE_CONTINUOUS
| AES2501_DETCTRL_SDELAY_31_MS
},
290 { AES2501_REG_COLSCAN
, AES2501_COLSCAN_SRATE_128_US
},
291 { AES2501_REG_MEASDRV
, AES2501_MEASDRV_MDRIVE_0_325
| AES2501_MEASDRV_MEASURE_SQUARE
},
292 { AES2501_REG_MEASFREQ
, AES2501_MEASFREQ_2M
},
293 { AES2501_REG_DEMODPHASE1
, DEMODPHASE_NONE
},
294 { AES2501_REG_DEMODPHASE2
, DEMODPHASE_NONE
},
295 { AES2501_REG_CHANGAIN
,
296 AES2501_CHANGAIN_STAGE2_4X
| AES2501_CHANGAIN_STAGE1_16X
},
297 { AES2501_REG_ADREFHI
, 0x44 },
298 { AES2501_REG_ADREFLO
, 0x34 },
299 { AES2501_REG_STRTCOL
, 0x16 },
300 { AES2501_REG_ENDCOL
, 0x16 },
301 { AES2501_REG_DATFMT
, AES2501_DATFMT_BIN_IMG
| 0x08 },
302 { AES2501_REG_TREG1
, 0x70 },
305 { AES2501_REG_TREGC
, AES2501_TREGC_ENABLE
},
306 { AES2501_REG_TREGD
, 0x1a },
307 { AES2501_REG_CTRL1
, AES2501_CTRL1_REG_UPDATE
},
308 { AES2501_REG_CTRL2
, AES2501_CTRL2_SET_ONE_SHOT
},
309 { AES2501_REG_LPONT
, AES2501_LPONT_MIN_VALUE
},
312 static int detect_finger(struct fp_img_dev
*dev
)
314 unsigned char buffer
[22];
319 r
= write_regv(dev
, finger_det_reqs
, ARRAY_SIZE(finger_det_reqs
));
323 r
= read_data(dev
, buffer
, 20);
327 for (i
= 1; i
< 9; i
++)
328 sum
+= (buffer
[i
] & 0xf) + (buffer
[i
] >> 4);
333 static int await_finger_on(struct fp_img_dev
*dev
)
337 r
= detect_finger(dev
);
339 return (r
< 0) ? r
: 0;
342 /* Read the value of a specific register from a register dump */
343 static int regval_from_dump(unsigned char *data
, uint8_t target
)
345 if (*data
!= FIRST_AES2501_REG
) {
346 fp_err("not a register dump");
350 if (!(FIRST_AES2501_REG
<= target
&& target
<= LAST_AES2501_REG
)) {
351 fp_err("out of range");
355 target
-= FIRST_AES2501_REG
;
357 return data
[target
+ 1];
360 static int sum_histogram_values(unsigned char *data
, uint8_t threshold
)
364 uint16_t *histogram
= (uint16_t *)(data
+ 1);
369 if (threshold
> 0x0f)
372 /* FIXME endianness */
373 for (i
= threshold
; i
< 16; i
++)
379 /* find overlapping parts of frames */
380 static unsigned int find_overlap(unsigned char *first_frame
,
381 unsigned char *second_frame
)
384 unsigned int min_error
= 255 * FRAME_SIZE
;
385 unsigned int not_overlapped_height
= 0;
386 for (dy
= 0; dy
< FRAME_HEIGHT
; dy
++) {
387 /* Calculating difference (error) between parts of frames */
389 unsigned int error
= 0;
390 for (i
= 0; i
< FRAME_WIDTH
* (FRAME_HEIGHT
- dy
); i
++) {
391 /* Using ? operator to avoid abs function */
392 error
+= first_frame
[i
] > second_frame
[i
] ?
393 (first_frame
[i
] - second_frame
[i
]) :
394 (second_frame
[i
] - first_frame
[i
]);
397 /* Normalize error */
400 if (error
< min_error
) {
402 not_overlapped_height
= dy
;
404 first_frame
+= FRAME_WIDTH
;
407 return not_overlapped_height
;
410 /* assemble a series of frames into a single image */
411 static unsigned int assemble(unsigned char *input
, unsigned char *output
,
414 uint8_t *assembled
= output
;
416 uint32_t image_height
= FRAME_HEIGHT
;
421 /* Rotating given data by 90 degrees
422 * Taken from document describing aes2501 image format
423 * TODO: move reversing detection here */
425 for (frame
= 0; frame
< num_strips
; frame
++) {
427 for (column
= 0; column
< FRAME_WIDTH
; column
++) {
429 for (row
= 0; row
< (FRAME_HEIGHT
/ 2); row
++) {
430 output
[FRAME_WIDTH
* ( 2 * row
) + column
] = *input
& 0x0F;
431 output
[FRAME_WIDTH
* ( 2 * row
+ 1) + column
] = *input
>> 4;
436 output
+= FRAME_SIZE
;
439 /* Detecting where frames overlaped */
441 for (frame
= 1; frame
< num_strips
; frame
++) {
444 output
+= FRAME_SIZE
;
445 not_overlapped
= find_overlap(assembled
, output
);
446 image_height
+= not_overlapped
;
447 assembled
+= FRAME_WIDTH
* not_overlapped
;
448 memcpy(assembled
, output
, FRAME_SIZE
);
453 static const struct aes2501_regwrite capture_reqs_1
[] = {
454 { AES2501_REG_CTRL1
, AES2501_CTRL1_MASTER_RESET
},
455 { AES2501_REG_EXCITCTRL
, 0x40 },
456 { AES2501_REG_DETCTRL
,
457 AES2501_DETCTRL_SDELAY_31_MS
| AES2501_DETCTRL_DRATE_CONTINUOUS
},
458 { AES2501_REG_COLSCAN
, AES2501_COLSCAN_SRATE_128_US
},
459 { AES2501_REG_DEMODPHASE2
, 0x7c },
460 { AES2501_REG_MEASDRV
,
461 AES2501_MEASDRV_MEASURE_SQUARE
| AES2501_MEASDRV_MDRIVE_0_325
},
462 { AES2501_REG_DEMODPHASE1
, 0x24 },
463 { AES2501_REG_CHWORD1
, 0x00 },
464 { AES2501_REG_CHWORD2
, 0x6c },
465 { AES2501_REG_CHWORD3
, 0x09 },
466 { AES2501_REG_CHWORD4
, 0x54 },
467 { AES2501_REG_CHWORD5
, 0x78 },
472 { AES2501_REG_CTRL1
, AES2501_CTRL1_REG_UPDATE
},
473 { AES2501_REG_IMAGCTRL
,
474 AES2501_IMAGCTRL_TST_REG_ENABLE
| AES2501_IMAGCTRL_HISTO_DATA_ENABLE
|
475 AES2501_IMAGCTRL_IMG_DATA_DISABLE
},
476 { AES2501_REG_STRTCOL
, 0x10 },
477 { AES2501_REG_ENDCOL
, 0x1f },
478 { AES2501_REG_CHANGAIN
,
479 AES2501_CHANGAIN_STAGE1_2X
| AES2501_CHANGAIN_STAGE2_2X
},
480 { AES2501_REG_ADREFHI
, 0x70 },
481 { AES2501_REG_ADREFLO
, 0x20 },
482 { AES2501_REG_CTRL2
, AES2501_CTRL2_SET_ONE_SHOT
},
483 { AES2501_REG_LPONT
, AES2501_LPONT_MIN_VALUE
},
486 static const struct aes2501_regwrite capture_reqs_2
[] = {
487 { AES2501_REG_IMAGCTRL
,
488 AES2501_IMAGCTRL_TST_REG_ENABLE
| AES2501_IMAGCTRL_HISTO_DATA_ENABLE
|
489 AES2501_IMAGCTRL_IMG_DATA_DISABLE
},
490 { AES2501_REG_STRTCOL
, 0x10 },
491 { AES2501_REG_ENDCOL
, 0x1f },
492 { AES2501_REG_CHANGAIN
, AES2501_CHANGAIN_STAGE1_16X
},
493 { AES2501_REG_ADREFHI
, 0x70 },
494 { AES2501_REG_ADREFLO
, 0x20 },
495 { AES2501_REG_CTRL2
, AES2501_CTRL2_SET_ONE_SHOT
},
498 static const struct aes2501_regwrite strip_scan_reqs
[] = {
499 { AES2501_REG_IMAGCTRL
,
500 AES2501_IMAGCTRL_TST_REG_ENABLE
| AES2501_IMAGCTRL_HISTO_DATA_ENABLE
},
501 { AES2501_REG_STRTCOL
, 0x00 },
502 { AES2501_REG_ENDCOL
, 0x2f },
503 { AES2501_REG_CHANGAIN
, AES2501_CHANGAIN_STAGE1_16X
},
504 { AES2501_REG_ADREFHI
, 0x5b },
505 { AES2501_REG_ADREFLO
, 0x20 },
506 { AES2501_REG_CTRL2
, AES2501_CTRL2_SET_ONE_SHOT
},
509 static int capture(struct fp_img_dev
*dev
, gboolean unconditional
,
514 unsigned int nstrips
;
515 unsigned char *cooked
;
516 unsigned char *imgptr
;
517 unsigned char buf
[1705];
521 /* FIXME can do better here in terms of buffer management? */
524 r
= write_regv(dev
, capture_reqs_1
, ARRAY_SIZE(capture_reqs_1
));
528 r
= read_data(dev
, buf
, 159);
532 r
= write_regv(dev
, capture_reqs_2
, ARRAY_SIZE(capture_reqs_2
));
536 r
= read_data(dev
, buf
, 159);
540 /* FIXME: use histogram data above for gain calibration (0x8e xx) */
542 img
= fpi_img_new((3 * MAX_FRAMES
* FRAME_SIZE
) / 2);
544 cooked
= imgptr
+ (MAX_FRAMES
* FRAME_SIZE
) / 2;
546 for (nstrips
= 0; nstrips
< MAX_FRAMES
; nstrips
++) {
549 r
= write_regv(dev
, strip_scan_reqs
, ARRAY_SIZE(strip_scan_reqs
));
552 r
= read_data(dev
, buf
, 1705);
555 memcpy(imgptr
, buf
+ 1, 192*8);
558 threshold
= regval_from_dump((buf
+ 1 + 192*8 + 1 + 16*2 + 1 + 8),
565 sum
= sum_histogram_values((buf
+ 1 + 192*8), threshold
& 0x0f);
570 fp_dbg("sum=%d", sum
);
574 if (nstrips
== MAX_FRAMES
)
575 fp_warn("swiping finger too slow?");
577 img
->height
= assemble(img
->data
, cooked
, nstrips
);
578 for (i
= 0; i
< img
->height
* FRAME_WIDTH
; i
++)
579 img
->data
[i
] = (cooked
[i
] << 4) | 0xf;
581 img
= fpi_img_resize(img
, img
->height
* FRAME_WIDTH
);
582 img
->flags
= FP_IMG_V_FLIPPED
| FP_IMG_H_FLIPPED
| FP_IMG_COLORS_INVERTED
;
590 static const struct usb_id id_table
[] = {
591 { .vendor
= 0x08ff, .product
= 0x2580 },
595 struct fp_img_driver aes2501_driver
= {
598 .name
= FP_COMPONENT
,
599 .full_name
= "AuthenTec AES2501",
600 .id_table
= id_table
,
606 /* temporarily lowered until image quality improves */
611 .await_finger_on
= await_finger_on
,