Gentoo Websites Logo
Go to: Gentoo Home Documentation Forums Lists Bugs Planet Store Wiki Get Gentoo!
View | Details | Raw Unified | Return to bug 531698 | Differences between
and this patch

Collapse All | Expand All

(-)a/configure.ac (-19 / +64 lines)
Lines 1-5 Link Here
1
AC_INIT([libfprint], [0.5.1])
1
AC_INIT([libfprint], [0.5.1])
2
AM_INIT_AUTOMAKE([1.11 no-dist-gzip dist-xz check-news])
2
AM_INIT_AUTOMAKE([1.11 no-dist-gzip dist-xz check-news subdir-objects])
3
AC_CONFIG_MACRO_DIR([m4])
3
AC_CONFIG_MACRO_DIR([m4])
4
AC_CONFIG_SRCDIR([libfprint/core.c])
4
AC_CONFIG_SRCDIR([libfprint/core.c])
5
AC_CONFIG_HEADERS([config.h])
5
AC_CONFIG_HEADERS([config.h])
Lines 23-33 AC_SUBST(lt_major) Link Here
23
AC_SUBST(lt_revision)
23
AC_SUBST(lt_revision)
24
AC_SUBST(lt_age)
24
AC_SUBST(lt_age)
25
25
26
all_drivers="upeke2 upekts upektc upeksonly vcom5s uru4000 fdu2000 aes1610 aes1660 aes2501 aes2550 aes2660 aes4000 vfs101 vfs301"
26
all_drivers="upekts upektc upeksonly vcom5s uru4000 fdu2000 aes1610 aes1660 aes2501 aes2550 aes2660 aes3500 aes4000 vfs101 vfs301 upektc_img etes603 vfs0050"
27
27
28
require_imaging='no'
28
require_imaging='no'
29
require_aeslib='no'
29
require_aeslib='no'
30
require_aesX660='no'
30
require_aesX660='no'
31
require_aes3k='no'
31
enable_upeke2='no'
32
enable_upeke2='no'
32
enable_upekts='no'
33
enable_upekts='no'
33
enable_upektc='no'
34
enable_upektc='no'
Lines 40-48 enable_aes1660='no' Link Here
40
enable_aes2501='no'
41
enable_aes2501='no'
41
enable_aes2550='no'
42
enable_aes2550='no'
42
enable_aes2660='no'
43
enable_aes2660='no'
44
enable_aes3500='no'
43
enable_aes4000='no'
45
enable_aes4000='no'
44
enable_vfs101='no'
46
enable_vfs101='no'
45
enable_vfs301='no'
47
enable_vfs301='no'
48
enable_upektc_img='no'
49
enable_etes603='no'
50
enable_vfs0050='no'
46
51
47
AC_ARG_WITH([drivers],[AS_HELP_STRING([--with-drivers],
52
AC_ARG_WITH([drivers],[AS_HELP_STRING([--with-drivers],
48
	[List of drivers to enable])],
53
	[List of drivers to enable])],
Lines 55-60 fi Link Here
55
60
56
for driver in `echo ${drivers} | sed -e 's/,/ /g' -e 's/,$//g'`; do
61
for driver in `echo ${drivers} | sed -e 's/,/ /g' -e 's/,$//g'`; do
57
	case ${driver} in
62
	case ${driver} in
63
                vfs0050)
64
                        AC_DEFINE([ENABLE_VFS0050], [], [Build Validity 0050 driver])
65
                        enable_vfs0050="yes"
66
                ;;
58
		upekts)
67
		upekts)
59
			AC_DEFINE([ENABLE_UPEKTS], [], [Build UPEK TouchStrip driver])
68
			AC_DEFINE([ENABLE_UPEKTS], [], [Build UPEK TouchStrip driver])
60
			enable_upekts="yes"
69
			enable_upekts="yes"
Lines 111-120 for driver in `echo ${drivers} | sed -e 's/,/ /g' -e 's/,$//g'`; do Link Here
111
			require_aesX660="yes"
120
			require_aesX660="yes"
112
			enable_aes2660="yes"
121
			enable_aes2660="yes"
113
		;;
122
		;;
123
		aes3500)
124
			AC_DEFINE([ENABLE_AES3500], [], [Build AuthenTec AES3500 driver])
125
			require_aeslib="yes"
126
			require_imaging="yes"
127
			require_aes3k="yes"
128
			enable_aes3500="yes"
129
		;;
114
		aes4000)
130
		aes4000)
115
			AC_DEFINE([ENABLE_AES4000], [], [Build AuthenTec AES4000 driver])
131
			AC_DEFINE([ENABLE_AES4000], [], [Build AuthenTec AES4000 driver])
116
			require_aeslib="yes"
132
			require_aeslib="yes"
117
			require_imaging="yes"
133
			require_imaging="yes"
134
			require_aes3k="yes"
118
			enable_aes4000="yes"
135
			enable_aes4000="yes"
119
		;;
136
		;;
120
		vfs101)
137
		vfs101)
Lines 125-130 for driver in `echo ${drivers} | sed -e 's/,/ /g' -e 's/,$//g'`; do Link Here
125
			AC_DEFINE([ENABLE_VFS301], [], [Build Validity VFS301/VFS300 driver])
142
			AC_DEFINE([ENABLE_VFS301], [], [Build Validity VFS301/VFS300 driver])
126
			enable_vfs301="yes"
143
			enable_vfs301="yes"
127
		;;
144
		;;
145
		upektc_img)
146
			AC_DEFINE([ENABLE_UPEKTC_IMG], [], [Build Upek TouchChip Fingerprint Coprocessor driver])
147
			enable_upektc_img="yes"
148
		;;
149
		etes603)
150
			AC_DEFINE([ENABLE_ETES603], [], [Build EgisTec ES603 driver])
151
			enable_etes603="yes"
152
		;;
128
	esac
153
	esac
129
done
154
done
130
155
Lines 140-150 AM_CONDITIONAL([ENABLE_AES1660], [test "$enable_aes1660" = "yes"]) Link Here
140
AM_CONDITIONAL([ENABLE_AES2501], [test "$enable_aes2501" = "yes"])
165
AM_CONDITIONAL([ENABLE_AES2501], [test "$enable_aes2501" = "yes"])
141
AM_CONDITIONAL([ENABLE_AES2550], [test "$enable_aes2550" = "yes"])
166
AM_CONDITIONAL([ENABLE_AES2550], [test "$enable_aes2550" = "yes"])
142
AM_CONDITIONAL([ENABLE_AES2660], [test "$enable_aes2660" = "yes"])
167
AM_CONDITIONAL([ENABLE_AES2660], [test "$enable_aes2660" = "yes"])
168
AM_CONDITIONAL([ENABLE_AES3500], [test "$enable_aes3500" = "yes"])
143
AM_CONDITIONAL([ENABLE_AES4000], [test "$enable_aes4000" = "yes"])
169
AM_CONDITIONAL([ENABLE_AES4000], [test "$enable_aes4000" = "yes"])
144
AM_CONDITIONAL([REQUIRE_AESLIB], [test "$require_aeslib" = "yes"])
170
AM_CONDITIONAL([REQUIRE_AESLIB], [test "$require_aeslib" = "yes"])
145
AM_CONDITIONAL([REQUIRE_AESX660], [test "$require_aesX660" = "yes"])
171
AM_CONDITIONAL([REQUIRE_AESX660], [test "$require_aesX660" = "yes"])
172
AM_CONDITIONAL([REQUIRE_AES3K], [test "$require_aes3k" = "yes"])
146
AM_CONDITIONAL([ENABLE_VFS101], [test "$enable_vfs101" = "yes"])
173
AM_CONDITIONAL([ENABLE_VFS101], [test "$enable_vfs101" = "yes"])
147
AM_CONDITIONAL([ENABLE_VFS301], [test "$enable_vfs301" = "yes"])
174
AM_CONDITIONAL([ENABLE_VFS301], [test "$enable_vfs301" = "yes"])
175
AM_CONDITIONAL([ENABLE_UPEKTC_IMG], [test "$enable_upektc_img" = "yes"])
176
AM_CONDITIONAL([ENABLE_ETES603], [test "$enable_etes603" = "yes"])
177
AM_CONDITIONAL([ENABLE_VFS0050], [test "$enable_vfs0050" = "yes"])
148
178
149
179
150
PKG_CHECK_MODULES(LIBUSB, [libusb-1.0 >= 0.9.1])
180
PKG_CHECK_MODULES(LIBUSB, [libusb-1.0 >= 0.9.1])
Lines 160-167 PKG_CHECK_MODULES(GLIB, [glib-2.0 >= 2.28]) Link Here
160
AC_SUBST(GLIB_CFLAGS)
190
AC_SUBST(GLIB_CFLAGS)
161
AC_SUBST(GLIB_LIBS)
191
AC_SUBST(GLIB_LIBS)
162
192
163
imagemagick_found=no
193
pixman_found=no
164
gdkpixbuf_found=no
165
194
166
AC_ARG_ENABLE(udev-rules,
195
AC_ARG_ENABLE(udev-rules,
167
	AC_HELP_STRING([--enable-udev-rules],[Update the udev rules]),
196
	AC_HELP_STRING([--enable-udev-rules],[Update the udev rules]),
Lines 189-208 AC_MSG_NOTICE([installing udev rules in ${ac_with_udev_rules_dir}]) Link Here
189
AC_SUBST([udev_rulesdir],[${ac_with_udev_rules_dir}])
218
AC_SUBST([udev_rulesdir],[${ac_with_udev_rules_dir}])
190
219
191
if test "$require_imaging" = "yes"; then
220
if test "$require_imaging" = "yes"; then
192
	PKG_CHECK_MODULES(IMAGING, gthread-2.0 gdk-pixbuf-2.0, [gdkpixbuf_found=yes], [gdkpixbuf_found=no])
221
	PKG_CHECK_MODULES(IMAGING, pixman-1, [pixman_found=yes], [pixman_found=no])
193
	if test "$gdkpixbuf_found" != "yes"; then
222
	if test "$pixman_found" != "yes"; then
194
		PKG_CHECK_MODULES(IMAGING, ImageMagick, [imagemagick_found=yes], [imagemagick_found=no])
223
		AC_MSG_ERROR([pixman is required for imaging support])
195
	fi
224
	fi
196
fi
225
fi
197
226
198
if test "$require_imaging" = "yes"; then
227
AM_CONDITIONAL([REQUIRE_PIXMAN], [test "$pixman_found" = "yes"])
199
	if test "$gdkpixbuf_found" != "yes" && test "$imagemagick_found" != "yes"; then
200
		AC_MSG_ERROR([gdk-pixbuf or ImageMagick is required for imaging support])
201
	fi
202
fi
203
204
AM_CONDITIONAL([REQUIRE_GDKPIXBUF], [test "$gdkpixbuf_found" = "yes"])
205
AM_CONDITIONAL([REQUIRE_IMAGEMAGICK], [test "$imagemagick_found" = "yes"])
206
AC_SUBST(IMAGING_CFLAGS)
228
AC_SUBST(IMAGING_CFLAGS)
207
AC_SUBST(IMAGING_LIBS)
229
AC_SUBST(IMAGING_LIBS)
208
230
Lines 272-286 AM_CFLAGS="-std=gnu99 $inline_cflags -Wall -Wundef -Wunused -Wstrict-prototypes Link Here
272
AC_SUBST(AM_CFLAGS)
294
AC_SUBST(AM_CFLAGS)
273
295
274
if test "$require_imaging" = "yes"; then
296
if test "$require_imaging" = "yes"; then
275
	if test x$gdkpixbuf_found != no; then
297
	if test x$pixman_found != no; then
276
		AC_MSG_NOTICE([** Using gdk-pixbuf for imaging])
298
		AC_MSG_NOTICE([** Using pixman for imaging])
277
	else
278
		AC_MSG_NOTICE([** Using ImageMagick for imaging])
279
	fi
299
	fi
280
else
300
else
281
	AC_MSG_NOTICE([   Imaging support disabled])
301
	AC_MSG_NOTICE([   Imaging support disabled])
282
fi
302
fi
283
303
304
if test x$enable_vfs0050 != xno ; then
305
        AC_MSG_NOTICE([** vfs0050 driver enabled])
306
else
307
        AC_MSG_NOTICE([   vfs0050 driver disabled])
308
fi
284
if test x$enable_upekts != xno ; then
309
if test x$enable_upekts != xno ; then
285
	AC_MSG_NOTICE([** upekts driver enabled])
310
	AC_MSG_NOTICE([** upekts driver enabled])
286
else
311
else
Lines 341-346 if test x$enable_aes2660 != xno ; then Link Here
341
else
366
else
342
	AC_MSG_NOTICE([   aes2660 driver disabled])
367
	AC_MSG_NOTICE([   aes2660 driver disabled])
343
fi
368
fi
369
if test x$enable_aes3500 != xno ; then
370
	AC_MSG_NOTICE([** aes3500 driver enabled])
371
else
372
	AC_MSG_NOTICE([   aes3500 driver disabled])
373
fi
344
if test x$enable_aes4000 != xno ; then
374
if test x$enable_aes4000 != xno ; then
345
	AC_MSG_NOTICE([** aes4000 driver enabled])
375
	AC_MSG_NOTICE([** aes4000 driver enabled])
346
else
376
else
Lines 356-361 if test x$enable_vfs301 != xno ; then Link Here
356
else
386
else
357
	AC_MSG_NOTICE([   vfs301 driver disabled])
387
	AC_MSG_NOTICE([   vfs301 driver disabled])
358
fi
388
fi
389
if test x$enable_upektc_img != xno ; then
390
	AC_MSG_NOTICE([** upektc_img driver enabled])
391
else
392
	AC_MSG_NOTICE([   upektc_img driver disabled])
393
fi
394
if test x$enable_etes603 != xno ; then
395
	AC_MSG_NOTICE([** etes603 driver enabled])
396
else
397
	AC_MSG_NOTICE([   etes603 driver disabled])
398
fi
359
if test x$require_aeslib != xno ; then
399
if test x$require_aeslib != xno ; then
360
	AC_MSG_NOTICE([** aeslib helper functions enabled])
400
	AC_MSG_NOTICE([** aeslib helper functions enabled])
361
else
401
else
Lines 366-371 if test x$require_aesX660 != xno ; then Link Here
366
else
406
else
367
	AC_MSG_NOTICE([   aesX660 common routines disabled])
407
	AC_MSG_NOTICE([   aesX660 common routines disabled])
368
fi
408
fi
409
if test x$require_aes3k != xno ; then
410
	AC_MSG_NOTICE([** aes3k common routines enabled])
411
else
412
	AC_MSG_NOTICE([   aes3k common routines disabled])
413
fi
369
414
370
AC_CONFIG_FILES([libfprint.pc] [Makefile] [libfprint/Makefile] [examples/Makefile] [doc/Makefile])
415
AC_CONFIG_FILES([libfprint.pc] [Makefile] [libfprint/Makefile] [examples/Makefile] [doc/Makefile])
371
AC_OUTPUT
416
AC_OUTPUT
(-)a/libfprint/Makefile.am (-9 / +32 lines)
Lines 12-22 AES1660_SRC = drivers/aes1660.c drivers/aes1660.h Link Here
12
AES2501_SRC = drivers/aes2501.c drivers/aes2501.h
12
AES2501_SRC = drivers/aes2501.c drivers/aes2501.h
13
AES2550_SRC = drivers/aes2550.c drivers/aes2550.h
13
AES2550_SRC = drivers/aes2550.c drivers/aes2550.h
14
AES2660_SRC = drivers/aes2660.c drivers/aes2660.h
14
AES2660_SRC = drivers/aes2660.c drivers/aes2660.h
15
AES3500_SRC = drivers/aes3500.c
15
AES4000_SRC = drivers/aes4000.c
16
AES4000_SRC = drivers/aes4000.c
16
FDU2000_SRC = drivers/fdu2000.c
17
FDU2000_SRC = drivers/fdu2000.c
17
VCOM5S_SRC = drivers/vcom5s.c
18
VCOM5S_SRC = drivers/vcom5s.c
18
VFS101_SRC = drivers/vfs101.c
19
VFS101_SRC = drivers/vfs101.c
19
VFS301_SRC = drivers/vfs301.c drivers/vfs301_proto.c  drivers/vfs301_proto.h drivers/vfs301_proto_fragments.h
20
VFS301_SRC = drivers/vfs301.c drivers/vfs301_proto.c  drivers/vfs301_proto.h drivers/vfs301_proto_fragments.h
21
UPEKTC_IMG_SRC = drivers/upektc_img.c drivers/upektc_img.h
22
ETES603_SRC = drivers/etes603.c
23
VFS0050_SRC = drivers/vfs0050.c drivers/vfs0050.h
20
24
21
EXTRA_DIST = \
25
EXTRA_DIST = \
22
	$(UPEKE2_SRC)		\
26
	$(UPEKE2_SRC)		\
Lines 29-45 EXTRA_DIST = \ Link Here
29
	$(AES2501_SRC)		\
33
	$(AES2501_SRC)		\
30
	$(AES2550_SRC)		\
34
	$(AES2550_SRC)		\
31
	$(AES2660_SRC)		\
35
	$(AES2660_SRC)		\
36
	$(AES3500_SRC)		\
32
	$(AES4000_SRC)		\
37
	$(AES4000_SRC)		\
33
	$(FDU2000_SRC)		\
38
	$(FDU2000_SRC)		\
34
	$(VCOM5S_SRC)		\
39
	$(VCOM5S_SRC)		\
35
	$(VFS101_SRC)		\
40
	$(VFS101_SRC)		\
36
	$(VFS301_SRC)		\
41
	$(VFS301_SRC)		\
42
	$(UPEKTC_IMG_SRC)	\
43
	$(ETES603_SRC)		\
44
        $(VFS0050_SRC)          \
37
	drivers/aesx660.c	\
45
	drivers/aesx660.c	\
38
	drivers/aesx660.h	\
46
	drivers/aesx660.h	\
47
	drivers/aes3k.c 	\
48
	drivers/aes3k.h 	\
39
	drivers/driver_ids.h	\
49
	drivers/driver_ids.h	\
40
	aeslib.c aeslib.h	\
50
	aeslib.c aeslib.h	\
41
	imagemagick.c		\
51
	pixman.c		\
42
	gdkpixbuf.c		\
43
	60-fprint-autosuspend.rules
52
	60-fprint-autosuspend.rules
44
53
45
DRIVER_SRC =
54
DRIVER_SRC =
Lines 87-93 libfprint_la_LDFLAGS = -version-info @lt_major@:@lt_revision@:@lt_age@ Link Here
87
libfprint_la_LIBADD = -lm $(LIBUSB_LIBS) $(GLIB_LIBS) $(CRYPTO_LIBS)
96
libfprint_la_LIBADD = -lm $(LIBUSB_LIBS) $(GLIB_LIBS) $(CRYPTO_LIBS)
88
97
89
fprint_list_udev_rules_SOURCES = fprint-list-udev-rules.c
98
fprint_list_udev_rules_SOURCES = fprint-list-udev-rules.c
90
fprint_list_udev_rules_CFLAGS = -fvisibility=hidden -I$(srcdir)/nbis/include $(LIBUSB_CFLAGS) $(GLIB_CFLAGS) $(IMAGEMAGICK_CFLAGS) $(CRYPTO_CFLAGS) $(AM_CFLAGS)
99
fprint_list_udev_rules_CFLAGS = -fvisibility=hidden -I$(srcdir)/nbis/include $(LIBUSB_CFLAGS) $(GLIB_CFLAGS) $(CRYPTO_CFLAGS) $(AM_CFLAGS)
91
fprint_list_udev_rules_LDADD = $(builddir)/libfprint.la $(GLIB_LIBS)
100
fprint_list_udev_rules_LDADD = $(builddir)/libfprint.la $(GLIB_LIBS)
92
101
93
udev_rules_DATA = 60-fprint-autosuspend.rules
102
udev_rules_DATA = 60-fprint-autosuspend.rules
Lines 145-150 if ENABLE_AES2660 Link Here
145
DRIVER_SRC += $(AES2660_SRC)
154
DRIVER_SRC += $(AES2660_SRC)
146
endif
155
endif
147
156
157
if ENABLE_AES3500
158
DRIVER_SRC += $(AES3500_SRC)
159
endif
160
148
if ENABLE_AES4000
161
if ENABLE_AES4000
149
DRIVER_SRC += $(AES4000_SRC)
162
DRIVER_SRC += $(AES4000_SRC)
150
endif
163
endif
Lines 157-170 if ENABLE_VFS301 Link Here
157
DRIVER_SRC += $(VFS301_SRC)
170
DRIVER_SRC += $(VFS301_SRC)
158
endif
171
endif
159
172
160
if REQUIRE_IMAGEMAGICK
173
if ENABLE_UPEKTC_IMG
161
OTHER_SRC += imagemagick.c
174
DRIVER_SRC += $(UPEKTC_IMG_SRC)
162
libfprint_la_CFLAGS += $(IMAGING_CFLAGS)
175
endif
163
libfprint_la_LIBADD += $(IMAGING_LIBS)
176
177
if ENABLE_ETES603
178
DRIVER_SRC += $(ETES603_SRC)
179
endif
180
181
if ENABLE_VFS0050
182
DRIVER_SRC += $(VFS0050_SRC)
164
endif
183
endif
165
184
166
if REQUIRE_GDKPIXBUF
185
if REQUIRE_PIXMAN
167
OTHER_SRC += gdkpixbuf.c
186
OTHER_SRC += pixman.c
168
libfprint_la_CFLAGS += $(IMAGING_CFLAGS)
187
libfprint_la_CFLAGS += $(IMAGING_CFLAGS)
169
libfprint_la_LIBADD += $(IMAGING_LIBS)
188
libfprint_la_LIBADD += $(IMAGING_LIBS)
170
endif
189
endif
Lines 177-182 if REQUIRE_AESX660 Link Here
177
OTHER_SRC += drivers/aesx660.c drivers/aesx660.h
196
OTHER_SRC += drivers/aesx660.c drivers/aesx660.h
178
endif
197
endif
179
198
199
if REQUIRE_AES3K
200
OTHER_SRC += drivers/aes3k.c drivers/aes3k.h
201
endif
202
180
libfprint_la_SOURCES =	\
203
libfprint_la_SOURCES =	\
181
	fp_internal.h	\
204
	fp_internal.h	\
182
	async.c		\
205
	async.c		\
(-)a/libfprint/async.c (+98 lines)
Lines 412-414 void fpi_drvcb_identify_stopped(struct fp_dev *dev) Link Here
412
		dev->identify_stop_cb(dev, dev->identify_stop_cb_data);
412
		dev->identify_stop_cb(dev, dev->identify_stop_cb_data);
413
}
413
}
414
414
415
API_EXPORTED int fp_async_capture_start(struct fp_dev *dev, int unconditional,
416
	fp_capture_cb callback, void *user_data)
417
{
418
	struct fp_driver *drv = dev->drv;
419
	int r;
420
421
	fp_dbg("");
422
	if (!drv->capture_start)
423
		return -ENOTSUP;
424
425
	dev->state = DEV_STATE_CAPTURE_STARTING;
426
	dev->capture_cb = callback;
427
	dev->capture_cb_data = user_data;
428
	dev->unconditional_capture = unconditional;
429
430
	r = drv->capture_start(dev);
431
	if (r < 0) {
432
		dev->capture_cb = NULL;
433
		dev->state = DEV_STATE_ERROR;
434
		fp_err("failed to start verification, error %d", r);
435
	}
436
	return r;
437
}
438
439
/* Drivers call this when capture has started */
440
void fpi_drvcb_capture_started(struct fp_dev *dev, int status)
441
{
442
	fp_dbg("");
443
	BUG_ON(dev->state != DEV_STATE_CAPTURE_STARTING);
444
	if (status) {
445
		if (status > 0) {
446
			status = -status;
447
			fp_dbg("adjusted to %d", status);
448
		}
449
		dev->state = DEV_STATE_ERROR;
450
		if (dev->capture_cb)
451
			dev->capture_cb(dev, status, NULL, dev->capture_cb_data);
452
	} else {
453
		dev->state = DEV_STATE_CAPTURING;
454
	}
455
}
456
457
/* Drivers call this to report a capture result (which might mark completion) */
458
void fpi_drvcb_report_capture_result(struct fp_dev *dev, int result,
459
	struct fp_img *img)
460
{
461
	fp_dbg("result %d", result);
462
	BUG_ON(dev->state != DEV_STATE_CAPTURING);
463
	if (result < 0 || result == FP_CAPTURE_COMPLETE)
464
		dev->state = DEV_STATE_CAPTURE_DONE;
465
466
	if (dev->capture_cb)
467
		dev->capture_cb(dev, result, img, dev->capture_cb_data);
468
	else
469
		fp_dbg("ignoring capture result as no callback is subscribed");
470
}
471
472
/* Drivers call this when capture has stopped */
473
void fpi_drvcb_capture_stopped(struct fp_dev *dev)
474
{
475
	fp_dbg("");
476
	BUG_ON(dev->state != DEV_STATE_CAPTURE_STOPPING);
477
	dev->state = DEV_STATE_INITIALIZED;
478
	if (dev->capture_stop_cb)
479
		dev->capture_stop_cb(dev, dev->capture_stop_cb_data);
480
}
481
482
API_EXPORTED int fp_async_capture_stop(struct fp_dev *dev,
483
	fp_capture_stop_cb callback, void *user_data)
484
{
485
	struct fp_driver *drv = dev->drv;
486
	int r;
487
488
	fp_dbg("");
489
	BUG_ON(dev->state != DEV_STATE_ERROR
490
		&& dev->state != DEV_STATE_CAPTURING
491
		&& dev->state != DEV_STATE_CAPTURE_DONE);
492
493
	dev->capture_cb = NULL;
494
	dev->capture_stop_cb = callback;
495
	dev->capture_stop_cb_data = user_data;
496
	dev->state = DEV_STATE_CAPTURE_STOPPING;
497
498
	if (!drv->capture_start)
499
		return -ENOTSUP;
500
	if (!drv->capture_stop) {
501
		dev->state = DEV_STATE_INITIALIZED;
502
		fpi_drvcb_capture_stopped(dev);
503
		return 0;
504
	}
505
506
	r = drv->capture_stop(dev);
507
	if (r < 0) {
508
		fp_err("failed to stop verification");
509
		dev->capture_stop_cb = NULL;
510
	}
511
	return r;
512
}
(-)a/libfprint/core.c (-33 / +13 lines)
Lines 349-354 static struct fp_driver * const primitive_drivers[] = { Link Here
349
};
349
};
350
350
351
static struct fp_img_driver * const img_drivers[] = {
351
static struct fp_img_driver * const img_drivers[] = {
352
#ifdef ENABLE_AES3500
353
	&aes3500_driver,
354
#endif
352
#ifdef ENABLE_AES4000
355
#ifdef ENABLE_AES4000
353
	&aes4000_driver,
356
	&aes4000_driver,
354
#endif
357
#endif
Lines 386-391 static struct fp_img_driver * const img_drivers[] = { Link Here
386
#ifdef ENABLE_UPEKTC
389
#ifdef ENABLE_UPEKTC
387
	&upektc_driver,
390
	&upektc_driver,
388
#endif
391
#endif
392
#ifdef ENABLE_UPEKTC_IMG
393
	&upektc_img_driver,
394
#endif
395
#ifdef ENABLE_ETES603
396
	&etes603_driver,
397
#endif
398
#ifdef ENABLE_VFS0050
399
        &vfs0050_driver,
400
#endif
389
/*#ifdef ENABLE_FDU2000
401
/*#ifdef ENABLE_FDU2000
390
	&fdu2000_driver,
402
	&fdu2000_driver,
391
#endif
403
#endif
Lines 801-807 static struct fp_img_dev *dev_to_img_dev(struct fp_dev *dev) Link Here
801
 */
813
 */
802
API_EXPORTED int fp_dev_supports_imaging(struct fp_dev *dev)
814
API_EXPORTED int fp_dev_supports_imaging(struct fp_dev *dev)
803
{
815
{
804
	return dev->drv->type == DRIVER_IMAGING;
816
	return dev->drv->capture_start != NULL;
805
}
817
}
806
818
807
/** \ingroup dev
819
/** \ingroup dev
Lines 817-854 API_EXPORTED int fp_dev_supports_identification(struct fp_dev *dev) Link Here
817
}
829
}
818
830
819
/** \ingroup dev
831
/** \ingroup dev
820
 * Captures an \ref img "image" from a device. The returned image is the raw
821
 * image provided by the device, you may wish to \ref img_std "standardize" it.
822
 *
823
 * If set, the <tt>unconditional</tt> flag indicates that the device should
824
 * capture an image unconditionally, regardless of whether a finger is there
825
 * or not. If unset, this function will block until a finger is detected on
826
 * the sensor.
827
 *
828
 * \param dev the device
829
 * \param unconditional whether to unconditionally capture an image, or to only capture when a finger is detected
830
 * \param image a location to return the captured image. Must be freed with
831
 * fp_img_free() after use.
832
 * \return 0 on success, non-zero on error. -ENOTSUP indicates that either the
833
 * unconditional flag was set but the device does not support this, or that the
834
 * device does not support imaging.
835
 * \sa fp_dev_supports_imaging()
836
 */
837
API_EXPORTED int fp_dev_img_capture(struct fp_dev *dev, int unconditional,
838
	struct fp_img **image)
839
{
840
	struct fp_img_dev *imgdev = dev_to_img_dev(dev);
841
	if (!imgdev) {
842
		fp_dbg("image capture on non-imaging device");
843
		return -ENOTSUP;
844
	}
845
846
	//return fpi_imgdev_capture(imgdev, unconditional, image);
847
	/* FIXME reimplement async */
848
	return -ENOTSUP;
849
}
850
851
/** \ingroup dev
852
 * Gets the expected width of images that will be captured from the device.
832
 * Gets the expected width of images that will be captured from the device.
853
 * This function will return -1 for devices that are not
833
 * This function will return -1 for devices that are not
854
 * \ref imaging "imaging devices". If the width of images from this device
834
 * \ref imaging "imaging devices". If the width of images from this device
(-)a/libfprint/data.c (-31 / +130 lines)
Lines 95-115 static const char *finger_num_to_str(enum fp_finger finger) Link Here
95
#endif
95
#endif
96
96
97
static struct fp_print_data *print_data_new(uint16_t driver_id,
97
static struct fp_print_data *print_data_new(uint16_t driver_id,
98
	uint32_t devtype, enum fp_print_data_type type, size_t length)
98
	uint32_t devtype, enum fp_print_data_type type)
99
{
99
{
100
	struct fp_print_data *data = g_malloc0(sizeof(*data) + length);
100
	struct fp_print_data *data = g_malloc0(sizeof(*data));
101
	fp_dbg("length=%zd driver=%02x devtype=%04x", length, driver_id, devtype);
101
	fp_dbg("driver=%02x devtype=%04x", driver_id, devtype);
102
	data->driver_id = driver_id;
102
	data->driver_id = driver_id;
103
	data->devtype = devtype;
103
	data->devtype = devtype;
104
	data->type = type;
104
	data->type = type;
105
	data->length = length;
106
	return data;
105
	return data;
107
}
106
}
108
107
109
struct fp_print_data *fpi_print_data_new(struct fp_dev *dev, size_t length)
108
void fpi_print_data_item_free(struct fp_print_data_item *item)
109
{
110
	g_free(item);
111
}
112
113
struct fp_print_data_item *fpi_print_data_item_new(size_t length)
114
{
115
	struct fp_print_data_item *item = g_malloc(sizeof(*item) + length);
116
	item->length = length;
117
118
	return item;
119
}
120
121
struct fp_print_data *fpi_print_data_new(struct fp_dev *dev)
110
{
122
{
111
	return print_data_new(dev->drv->id, dev->devtype,
123
	return print_data_new(dev->drv->id, dev->devtype,
112
		fpi_driver_get_data_type(dev->drv), length);
124
		fpi_driver_get_data_type(dev->drv));
113
}
125
}
114
126
115
/** \ingroup print_data
127
/** \ingroup print_data
Lines 124-150 struct fp_print_data *fpi_print_data_new(struct fp_dev *dev, size_t length) Link Here
124
API_EXPORTED size_t fp_print_data_get_data(struct fp_print_data *data,
136
API_EXPORTED size_t fp_print_data_get_data(struct fp_print_data *data,
125
	unsigned char **ret)
137
	unsigned char **ret)
126
{
138
{
127
	struct fpi_print_data_fp1 *buf;
139
	struct fpi_print_data_fp2 *out_data;
128
	size_t buflen;
140
	struct fpi_print_data_item_fp2 *out_item;
141
	struct fp_print_data_item *item;
142
	size_t buflen = 0;
143
	GSList *list_item;
144
	unsigned char *buf;
129
145
130
	fp_dbg("");
146
	fp_dbg("");
131
147
132
	buflen = sizeof(*buf) + data->length;
148
	list_item = data->prints;
133
	buf = malloc(buflen);
149
	while (list_item) {
134
	if (!buf)
150
		item = list_item->data;
135
		return 0;
151
		buflen += sizeof(*out_item);
136
152
		buflen += item->length;
137
	*ret = (unsigned char *) buf;
153
		list_item = g_slist_next(list_item);
138
	buf->prefix[0] = 'F';
154
	}
139
	buf->prefix[1] = 'P';
155
140
	buf->prefix[2] = '1';
156
	buflen += sizeof(*out_data);
141
	buf->driver_id = GUINT16_TO_LE(data->driver_id);
157
	out_data = g_malloc(buflen);
142
	buf->devtype = GUINT32_TO_LE(data->devtype);
158
143
	buf->data_type = data->type;
159
	*ret = (unsigned char *) out_data;
144
	memcpy(buf->data, data->data, data->length);
160
	buf = out_data->data;
161
	out_data->prefix[0] = 'F';
162
	out_data->prefix[1] = 'P';
163
	out_data->prefix[2] = '2';
164
	out_data->driver_id = GUINT16_TO_LE(data->driver_id);
165
	out_data->devtype = GUINT32_TO_LE(data->devtype);
166
	out_data->data_type = data->type;
167
168
	list_item = data->prints;
169
	while (list_item) {
170
		item = list_item->data;
171
		out_item = (struct fpi_print_data_item_fp2 *)buf;
172
		out_item->length = GUINT32_TO_LE(item->length);
173
		/* FIXME: fp_print_data_item->data content is not endianess agnostic */
174
		memcpy(out_item->data, item->data, item->length);
175
		buf += sizeof(*out_item);
176
		buf += item->length;
177
		list_item = g_slist_next(list_item);
178
	}
179
145
	return buflen;
180
	return buflen;
146
}
181
}
147
182
183
static struct fp_print_data *fpi_print_data_from_fp1_data(unsigned char *buf,
184
	size_t buflen)
185
{
186
	size_t print_data_len;
187
	struct fp_print_data *data;
188
	struct fp_print_data_item *item;
189
	struct fpi_print_data_fp2 *raw = (struct fpi_print_data_fp2 *) buf;
190
191
	print_data_len = buflen - sizeof(*raw);
192
	data = print_data_new(GUINT16_FROM_LE(raw->driver_id),
193
		GUINT32_FROM_LE(raw->devtype), raw->data_type);
194
	item = fpi_print_data_item_new(print_data_len);
195
	/* FIXME: fp_print_data->data content is not endianess agnostic */
196
	memcpy(item->data, raw->data, print_data_len);
197
	data->prints = g_slist_prepend(data->prints, item);
198
199
	return data;
200
}
201
202
static struct fp_print_data *fpi_print_data_from_fp2_data(unsigned char *buf,
203
	size_t buflen)
204
{
205
	size_t total_data_len, item_len;
206
	struct fp_print_data *data;
207
	struct fp_print_data_item *item;
208
	struct fpi_print_data_fp2 *raw = (struct fpi_print_data_fp2 *) buf;
209
	unsigned char *raw_buf;
210
	struct fpi_print_data_item_fp2 *raw_item;
211
212
	total_data_len = buflen - sizeof(*raw);
213
	data = print_data_new(GUINT16_FROM_LE(raw->driver_id),
214
		GUINT32_FROM_LE(raw->devtype), raw->data_type);
215
	raw_buf = raw->data;
216
	while (total_data_len) {
217
		if (total_data_len < sizeof(*raw_item))
218
			break;
219
		total_data_len -= sizeof(*raw_item);
220
221
		raw_item = (struct fpi_print_data_item_fp2 *)raw_buf;
222
		item_len = GUINT32_FROM_LE(raw_item->length);
223
		fp_dbg("item len %d, total_data_len %d", item_len, total_data_len);
224
		if (total_data_len < item_len) {
225
			fp_err("corrupted fingerprint data");
226
			break;
227
		}
228
		total_data_len -= item_len;
229
230
		item = fpi_print_data_item_new(item_len);
231
		/* FIXME: fp_print_data->data content is not endianess agnostic */
232
		memcpy(item->data, raw_item->data, item_len);
233
		data->prints = g_slist_prepend(data->prints, item);
234
235
		raw_buf += sizeof(*raw_item);
236
		raw_buf += item_len;
237
	}
238
239
	if (g_slist_length(data->prints) == 0) {
240
		fp_print_data_free(data);
241
		data = NULL;
242
	}
243
244
	return data;
245
246
}
247
148
/** \ingroup print_data
248
/** \ingroup print_data
149
 * Load a stored print from a data buffer. The contents of said buffer must
249
 * Load a stored print from a data buffer. The contents of said buffer must
150
 * be the untouched contents of a buffer previously supplied to you by the
250
 * be the untouched contents of a buffer previously supplied to you by the
Lines 157-180 API_EXPORTED size_t fp_print_data_get_data(struct fp_print_data *data, Link Here
157
API_EXPORTED struct fp_print_data *fp_print_data_from_data(unsigned char *buf,
257
API_EXPORTED struct fp_print_data *fp_print_data_from_data(unsigned char *buf,
158
	size_t buflen)
258
	size_t buflen)
159
{
259
{
160
	struct fpi_print_data_fp1 *raw = (struct fpi_print_data_fp1 *) buf;
260
	struct fpi_print_data_fp2 *raw = (struct fpi_print_data_fp2 *) buf;
161
	size_t print_data_len;
162
	struct fp_print_data *data;
163
261
164
	fp_dbg("buffer size %zd", buflen);
262
	fp_dbg("buffer size %zd", buflen);
165
	if (buflen < sizeof(*raw))
263
	if (buflen < sizeof(*raw))
166
		return NULL;
264
		return NULL;
167
265
168
	if (strncmp(raw->prefix, "FP1", 3) != 0) {
266
	if (strncmp(raw->prefix, "FP1", 3) == 0) {
267
		return fpi_print_data_from_fp1_data(buf, buflen);
268
	} else if (strncmp(raw->prefix, "FP2", 3) == 0) {
269
		return fpi_print_data_from_fp2_data(buf, buflen);
270
	} else {
169
		fp_dbg("bad header prefix");
271
		fp_dbg("bad header prefix");
170
		return NULL;
171
	}
272
	}
172
273
173
	print_data_len = buflen - sizeof(*raw);
274
	return NULL;
174
	data = print_data_new(GUINT16_FROM_LE(raw->driver_id),
175
		GUINT32_FROM_LE(raw->devtype), raw->data_type, print_data_len);
176
	memcpy(data->data, raw->data, print_data_len);
177
	return data;
178
}
275
}
179
276
180
static char *get_path_to_storedir(uint16_t driver_id, uint32_t devtype)
277
static char *get_path_to_storedir(uint16_t driver_id, uint32_t devtype)
Lines 405-410 API_EXPORTED int fp_print_data_from_dscv_print(struct fp_dscv_print *print, Link Here
405
 */
502
 */
406
API_EXPORTED void fp_print_data_free(struct fp_print_data *data)
503
API_EXPORTED void fp_print_data_free(struct fp_print_data *data)
407
{
504
{
505
	if (data)
506
		g_slist_free_full(data->prints, (GDestroyNotify)fpi_print_data_item_free);
408
	g_free(data);
507
	g_free(data);
409
}
508
}
410
509
(-)a/libfprint/drivers/aes1660.c (-6 lines)
Lines 104-115 struct fp_img_driver aes1660_driver = { Link Here
104
	.img_height = -1,
104
	.img_height = -1,
105
	.img_width = FRAME_WIDTH * SCALE_FACTOR,
105
	.img_width = FRAME_WIDTH * SCALE_FACTOR,
106
106
107
	/* temporarily lowered until we sort out image processing code
108
	 * binarized scan quality is good, minutiae detection is accurate,
109
	 * it's just that we get fewer minutiae than other scanners (less scanning
110
	 * area) */
111
	.bz3_threshold = 25,
112
113
	.open = dev_init,
107
	.open = dev_init,
114
	.close = dev_deinit,
108
	.close = dev_deinit,
115
	.activate = aesX660_dev_activate,
109
	.activate = aesX660_dev_activate,
(-)a/libfprint/drivers/aes3500.c (+188 lines)
Line 0 Link Here
1
/*
2
 * AuthenTec AES3500 driver for libfprint
3
 *
4
 * AES3500 is a press-typed sensor, which captures image in 128x128
5
 * pixels.
6
 *
7
 * Thanks Rafael Toledo for the Windows driver and the help.
8
 *
9
 * This work is derived from Daniel Drake's AES4000 driver.
10
 *
11
 * Copyright (C) 2011-2013 Juvenn Woo <machese@gmail.com>
12
 * Copyright (C) 2007-2008 Daniel Drake <dsd@gentoo.org>
13
 *
14
 * This library is free software; you can redistribute it and/or modify
15
 * it under the terms of the GNU Lesser General Public License as
16
 * published by the Free Software Foundation; either version 2.1 of the
17
 * License, or (at your option) any later version.
18
 *
19
 * This library is distributed in the hope that it will be useful, but
20
 * WITHOUT ANY WARRANTY; without even the implied warranty of
21
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22
 * Lesser General Public License for more details.
23
 *
24
 * You should have received a copy of the GNU Lesser General Public
25
 * License along with this library; if not, write to the Free Software
26
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
27
 * 02110-1301 USA
28
 */
29
30
#define FP_COMPONENT "aes3500"
31
32
#include <errno.h>
33
34
#include <glib.h>
35
#include <libusb.h>
36
37
#include <aeslib.h>
38
#include <fp_internal.h>
39
40
#include "aes3k.h"
41
#include "driver_ids.h"
42
43
#define DATA_BUFLEN	0x2089
44
45
/* image size = FRAME_WIDTH x FRAME_WIDTH */
46
#define FRAME_WIDTH 	128
47
#define FRAME_SIZE	(FRAME_WIDTH * AES3K_FRAME_HEIGHT / 2)
48
#define FRAME_NUMBER	(FRAME_WIDTH / AES3K_FRAME_HEIGHT)
49
#define ENLARGE_FACTOR 	2
50
51
52
static struct aes_regwrite init_reqs[] = {
53
	/* master reset */
54
	{ 0x80, 0x01 },
55
	{ 0, 0 },
56
	{ 0x80, 0x00 },
57
	{ 0, 0 },
58
59
	{ 0x81, 0x00 },
60
	{ 0x80, 0x00 },
61
	{ 0, 0 },
62
63
	/* scan reset */
64
	{ 0x80, 0x02 },
65
	{ 0, 0 },
66
	{ 0x80, 0x00 },
67
	{ 0, 0 },
68
69
	/* disable register buffering */
70
	{ 0x80, 0x04 },
71
	{ 0, 0 },
72
	{ 0x80, 0x00 },
73
	{ 0, 0 },
74
75
	{ 0x81, 0x00 },
76
	{ 0, 0 },
77
	/* windows driver reads registers now (81 02) */
78
	{ 0x80, 0x00 },
79
	{ 0x81, 0x00 },
80
81
	/* set excitation bias current: 2mhz drive ring frequency,
82
	 * 4V drive ring voltage, 16.5mA excitation bias */
83
	{ 0x82, 0x04 },
84
85
	/* continuously sample drive ring for finger detection,
86
	 * 62.50ms debounce delay */
87
	{ 0x83, 0x13 },
88
89
	{ 0x84, 0x07 }, /* set calibration resistance to 12 kiloohms */
90
	{ 0x85, 0x3d }, /* set calibration capacitance */
91
	{ 0x86, 0x03 }, /* detect drive voltage */
92
	{ 0x87, 0x01 }, /* set detection frequency to 125khz */
93
	{ 0x88, 0x02 }, /* set column scan period */
94
	{ 0x89, 0x02 }, /* set measure drive */
95
	{ 0x8a, 0x33 }, /* set measure frequency and sense amplifier bias */
96
	{ 0x8b, 0x33 }, /* set matrix pattern */
97
	{ 0x8c, 0x0f }, /* set demodulation phase 1 */
98
	{ 0x8d, 0x04 }, /* set demodulation phase 2 */
99
	{ 0x8e, 0x23 }, /* set sensor gain */
100
	{ 0x8f, 0x07 }, /* set image parameters */
101
	{ 0x90, 0x00 }, /* carrier offset null */
102
	{ 0x91, 0x1c }, /* set A/D reference high */
103
	{ 0x92, 0x08 }, /* set A/D reference low */
104
	{ 0x93, 0x00 }, /* set start row to 0 */
105
	{ 0x94, 0x07 }, /* set end row */
106
	{ 0x95, 0x00 }, /* set start column to 0 */
107
	{ 0x96, 0x1f }, /* set end column */
108
	{ 0x97, 0x04 }, /* data format and thresholds */
109
	{ 0x98, 0x28 }, /* image data control */
110
	{ 0x99, 0x00 }, /* disable general purpose outputs */
111
	{ 0x9a, 0x0b }, /* set initial scan state */
112
	{ 0x9b, 0x00 }, /* clear challenge word bits */
113
	{ 0x9c, 0x00 }, /* clear challenge word bits */
114
	{ 0x9d, 0x09 }, /* set some challenge word bits */
115
	{ 0x9e, 0x53 }, /* clear challenge word bits */
116
	{ 0x9f, 0x6b }, /* set some challenge word bits */
117
	{ 0, 0 },
118
119
	{ 0x80, 0x00 },
120
	{ 0x81, 0x00 },
121
	{ 0, 0 },
122
	{ 0x81, 0x04 },
123
	{ 0, 0 },
124
	{ 0x81, 0x00 },
125
};
126
127
static int dev_init(struct fp_img_dev *dev, unsigned long driver_data)
128
{
129
	int r;
130
	struct aes3k_dev *aesdev;
131
132
	r = libusb_claim_interface(dev->udev, 0);
133
	if (r < 0)
134
		fp_err("could not claim interface 0");
135
136
	aesdev = dev->priv = g_malloc0(sizeof(struct aes3k_dev));
137
138
	if (!aesdev)
139
		return -ENOMEM;
140
141
	if (r == 0)
142
		aesdev->data_buflen = DATA_BUFLEN;
143
		aesdev->frame_width = FRAME_WIDTH;
144
		aesdev->frame_size = FRAME_SIZE;
145
		aesdev->frame_number = FRAME_NUMBER;
146
		aesdev->enlarge_factor = ENLARGE_FACTOR;
147
		aesdev->init_reqs = init_reqs;
148
		aesdev->init_reqs_len = G_N_ELEMENTS(init_reqs);
149
		fpi_imgdev_open_complete(dev, 0);
150
151
	return r;
152
}
153
154
static void dev_deinit(struct fp_img_dev *dev)
155
{
156
	struct aes3k_dev *aesdev = dev->priv;
157
	g_free(aesdev);
158
	libusb_release_interface(dev->udev, 0);
159
	fpi_imgdev_close_complete(dev);
160
}
161
162
163
static const struct usb_id id_table[] = {
164
	{ .vendor = 0x08ff, .product = 0x5731 },
165
	{ 0, 0, 0, },
166
};
167
168
struct fp_img_driver aes3500_driver = {
169
	.driver = {
170
		.id = AES3500_ID,
171
		.name = FP_COMPONENT,
172
		.full_name = "AuthenTec AES3500",
173
		.id_table = id_table,
174
		.scan_type = FP_SCAN_TYPE_PRESS,
175
	},
176
	.flags = 0,
177
	.img_height = FRAME_WIDTH * ENLARGE_FACTOR,
178
	.img_width = FRAME_WIDTH * ENLARGE_FACTOR,
179
180
	/* temporarily lowered until image quality improves */
181
	.bz3_threshold = 9,
182
183
	.open = dev_init,
184
	.close = dev_deinit,
185
	.activate = aes3k_dev_activate,
186
	.deactivate = aes3k_dev_deactivate,
187
};
188
(-)a/libfprint/drivers/aes3k.c (+155 lines)
Line 0 Link Here
1
/*
2
 * AuthenTec AES3500/AES4000 common routines
3
 *
4
 * The AES3500 and AES4000 sensors are press-typed, and could capture
5
 * fingerprint images in 128x128 and 96x96 pixels respectively. They
6
 * share a same communication interface: a number of frames are
7
 * transferred and captured, from which a final image could be
8
 * assembled. Each frame has fixed height of 16 pixels.
9
 *
10
 * As the imaging area is a bit small, only a part of finger could be
11
 * captured, the detected minutiae are not so many that the NBIS
12
 * matching works not so good. The verification rate is very low at the
13
 * moment.
14
 *
15
 * This work is derived from Daniel Drake's AES4000 driver.
16
 *
17
 * Copyright (C) 2013 Juvenn Woo <machese@gmail.com>
18
 * Copyright (C) 2007-2008 Daniel Drake <dsd@gentoo.org>
19
 *
20
 * This library is free software; you can redistribute it and/or modify
21
 * it under the terms of the GNU Lesser General Public License as
22
 * published by the Free Software Foundation; either version 2.1 of the
23
 * License, or (at your option) any later version.
24
 *
25
 * This library is distributed in the hope that it will be useful, but
26
 * WITHOUT ANY WARRANTY; without even the implied warranty of
27
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
28
 * Lesser General Public License for more details.
29
 *
30
 * You should have received a copy of the GNU Lesser General Public
31
 * License along with this library; if not, write to the Free Software
32
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
33
 * 02110-1301 USA
34
 *
35
 */
36
37
#define FP_COMPONENT "aes3k"
38
39
#include <errno.h>
40
41
#include <glib.h>
42
#include <libusb.h>
43
44
#include <aeslib.h>
45
#include <fp_internal.h>
46
47
#include "aes3k.h"
48
49
#define CTRL_TIMEOUT	1000
50
#define EP_IN		(1 | LIBUSB_ENDPOINT_IN)
51
#define EP_OUT		(2 | LIBUSB_ENDPOINT_OUT)
52
53
static void do_capture(struct fp_img_dev *dev);
54
55
static void img_cb(struct libusb_transfer *transfer)
56
{
57
	struct fp_img_dev *dev = transfer->user_data;
58
	struct aes3k_dev *aesdev = dev->priv;
59
	unsigned char *ptr = transfer->buffer;
60
	struct fp_img *tmp;
61
	struct fp_img *img;
62
	int i;
63
64
	if (transfer->status == LIBUSB_TRANSFER_CANCELLED) {
65
		goto err;
66
	} else if (transfer->status != LIBUSB_TRANSFER_COMPLETED) {
67
		fpi_imgdev_session_error(dev, -EIO);
68
		goto err;
69
	} else if (transfer->length != transfer->actual_length) {
70
		fpi_imgdev_session_error(dev, -EPROTO);
71
		goto err;
72
	}
73
74
	fpi_imgdev_report_finger_status(dev, TRUE);
75
76
	tmp = fpi_img_new(aesdev->frame_width * aesdev->frame_width);
77
	tmp->width = aesdev->frame_width;
78
	tmp->height = aesdev->frame_width;
79
	tmp->flags = FP_IMG_COLORS_INVERTED | FP_IMG_V_FLIPPED | FP_IMG_H_FLIPPED;
80
	for (i = 0; i < aesdev->frame_number; i++) {
81
		fp_dbg("frame header byte %02x", *ptr);
82
		ptr++;
83
		aes_assemble_image(ptr, aesdev->frame_width, AES3K_FRAME_HEIGHT, tmp->data + (i * aesdev->frame_width * AES3K_FRAME_HEIGHT));
84
		ptr += aesdev->frame_size;
85
	}
86
87
	/* FIXME: this is an ugly hack to make the image big enough for NBIS
88
	 * to process reliably */
89
	img = fpi_im_resize(tmp, aesdev->enlarge_factor, aesdev->enlarge_factor);
90
	fp_img_free(tmp);
91
	fpi_imgdev_image_captured(dev, img);
92
93
	/* FIXME: rather than assuming finger has gone, we should poll regs until
94
	 * it really has, then restart the capture */
95
	fpi_imgdev_report_finger_status(dev, FALSE);
96
97
	do_capture(dev);
98
99
err:
100
	g_free(transfer->buffer);
101
	aesdev->img_trf = NULL;
102
	libusb_free_transfer(transfer);
103
}
104
105
static void do_capture(struct fp_img_dev *dev)
106
{
107
	struct aes3k_dev *aesdev = dev->priv;
108
	unsigned char *data;
109
	int r;
110
111
	aesdev->img_trf = libusb_alloc_transfer(0);
112
	if (!aesdev->img_trf) {
113
		fpi_imgdev_session_error(dev, -EIO);
114
		return;
115
	}
116
117
	data = g_malloc(aesdev->data_buflen);
118
	libusb_fill_bulk_transfer(aesdev->img_trf, dev->udev, EP_IN, data,
119
		aesdev->data_buflen, img_cb, dev, 0);
120
121
	r = libusb_submit_transfer(aesdev->img_trf);
122
	if (r < 0) {
123
		g_free(data);
124
		libusb_free_transfer(aesdev->img_trf);
125
		aesdev->img_trf = NULL;
126
		fpi_imgdev_session_error(dev, r);
127
	}
128
}
129
130
static void init_reqs_cb(struct fp_img_dev *dev, int result, void *user_data)
131
{
132
	fpi_imgdev_activate_complete(dev, result);
133
	if (result == 0)
134
		do_capture(dev);
135
}
136
137
int aes3k_dev_activate(struct fp_img_dev *dev, enum fp_imgdev_state state)
138
{
139
	struct aes3k_dev *aesdev = dev->priv;
140
	aes_write_regv(dev, aesdev->init_reqs, aesdev->init_reqs_len, init_reqs_cb, NULL);
141
	return 0;
142
}
143
144
void aes3k_dev_deactivate(struct fp_img_dev *dev)
145
{
146
	struct aes3k_dev *aesdev = dev->priv;
147
148
	/* FIXME: should wait for cancellation to complete before returning
149
	 * from deactivation, otherwise app may legally exit before we've
150
	 * cleaned up */
151
	if (aesdev->img_trf)
152
		libusb_cancel_transfer(aesdev->img_trf);
153
	fpi_imgdev_deactivate_complete(dev);
154
}
155
(-)a/libfprint/drivers/aes3k.h (+58 lines)
Line 0 Link Here
1
/*
2
 * AuthenTec AES3500/AES4000 common routines
3
 *
4
 * The AES3500 and AES4000 sensors are press-typed, and could capture
5
 * fingerprint images in 128x128 and 96x96 pixels respectively. They
6
 * share a same communication interface: a number of frames are
7
 * transferred and captured, from which a final image could be
8
 * assembled. Each frame has fixed height of 16 pixels.
9
 *
10
 * As the imaging area is a bit small, only a part of finger could be
11
 * captured, the detected minutiae are not so many that the NBIS
12
 * matching works not so good. The verification rate is very low at the
13
 * moment.
14
 *
15
 * This work is derived from Daniel Drake's AES4000 driver.
16
 *
17
 * Copyright (C) 2013 Juvenn Woo <machese@gmail.com>
18
 * Copyright (C) 2007-2008 Daniel Drake <dsd@gentoo.org>
19
 *
20
 * This library is free software; you can redistribute it and/or modify
21
 * it under the terms of the GNU Lesser General Public License as
22
 * published by the Free Software Foundation; either version 2.1 of the
23
 * License, or (at your option) any later version.
24
 *
25
 * This library is distributed in the hope that it will be useful, but
26
 * WITHOUT ANY WARRANTY; without even the implied warranty of
27
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
28
 * Lesser General Public License for more details.
29
 *
30
 * You should have received a copy of the GNU Lesser General Public
31
 * License along with this library; if not, write to the Free Software
32
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
33
 * 02110-1301 USA
34
 *
35
 */
36
37
#ifndef __AES3K_H
38
#define __AES3K_H
39
40
#define AES3K_FRAME_HEIGHT	16
41
42
struct aes3k_dev {
43
	struct libusb_transfer *img_trf;
44
	size_t frame_width;  /* image size = frame_width x frame_width */
45
	size_t frame_size;   /* 4 bits/pixel: frame_width x AES3K_FRAME_HEIGHT / 2 */
46
	size_t frame_number; /* number of frames */
47
	size_t enlarge_factor;
48
49
	size_t data_buflen;             /* buffer length of usb bulk transfer */
50
	struct aes_regwrite *init_reqs; /* initial values sent to device */
51
	size_t init_reqs_len;
52
};
53
54
55
int aes3k_dev_activate(struct fp_img_dev *dev, enum fp_imgdev_state state);
56
void aes3k_dev_deactivate(struct fp_img_dev *dev);
57
58
#endif
(-)a/libfprint/drivers/aes4000.c (-121 / +34 lines)
Lines 1-5 Link Here
1
/*
1
/*
2
 * AuthenTec AES4000 driver for libfprint
2
 * AuthenTec AES4000 driver for libfprint
3
 *
4
 * AES4000 is a press-typed sensor, which captures image in 96x96
5
 * pixels.
6
 *
7
 * This work is derived from Daniel Drake's AES4000 driver.
8
 *
9
 * Copyright (C) 2013 Juvenn Woo <machese@gmail.com>
3
 * Copyright (C) 2007-2008 Daniel Drake <dsd@gentoo.org>
10
 * Copyright (C) 2007-2008 Daniel Drake <dsd@gentoo.org>
4
 *
11
 *
5
 * This library is free software; you can redistribute it and/or
12
 * This library is free software; you can redistribute it and/or
Lines 27-50 Link Here
27
#include <aeslib.h>
34
#include <aeslib.h>
28
#include <fp_internal.h>
35
#include <fp_internal.h>
29
36
37
#include "aes3k.h"
30
#include "driver_ids.h"
38
#include "driver_ids.h"
31
39
32
#define CTRL_TIMEOUT	1000
40
#define DATA_BUFLEN	0x1259
33
#define EP_IN			(1 | LIBUSB_ENDPOINT_IN)
34
#define EP_OUT			(2 | LIBUSB_ENDPOINT_OUT)
35
#define DATA_BUFLEN		0x1259
36
#define NR_SUBARRAYS	6
37
#define SUBARRAY_LEN	768
38
41
39
#define IMG_HEIGHT 96
42
/* image size = FRAME_WIDTH x FRAME_WIDTH */
40
#define IMG_WIDTH 96
43
#define FRAME_WIDTH 	96
41
#define ENLARGE_FACTOR 3
44
#define FRAME_SIZE	(FRAME_WIDTH * AES3K_FRAME_HEIGHT / 2)
45
#define FRAME_NUMBER	(FRAME_WIDTH / AES3K_FRAME_HEIGHT)
46
#define ENLARGE_FACTOR 	3
42
47
43
struct aes4k_dev {
44
	struct libusb_transfer *img_trf;
45
};
46
48
47
static const struct aes_regwrite init_reqs[] = {
49
static struct aes_regwrite init_reqs[] = {
48
	/* master reset */
50
	/* master reset */
49
	{ 0x80, 0x01 },
51
	{ 0x80, 0x01 },
50
	{ 0, 0 },
52
	{ 0, 0 },
Lines 119-237 static const struct aes_regwrite init_reqs[] = { Link Here
119
	{ 0x81, 0x00 },
121
	{ 0x81, 0x00 },
120
};
122
};
121
123
122
static void do_capture(struct fp_img_dev *dev);
123
124
static void img_cb(struct libusb_transfer *transfer)
125
{
126
	struct fp_img_dev *dev = transfer->user_data;
127
	struct aes4k_dev *aesdev = dev->priv;
128
	unsigned char *ptr = transfer->buffer;
129
	struct fp_img *tmp;
130
	struct fp_img *img;
131
	int i;
132
133
	if (transfer->status == LIBUSB_TRANSFER_CANCELLED) {
134
		goto err;
135
	} else if (transfer->status != LIBUSB_TRANSFER_COMPLETED) {
136
		fpi_imgdev_session_error(dev, -EIO);
137
		goto err;
138
	} else if (transfer->length != transfer->actual_length) {
139
		fpi_imgdev_session_error(dev, -EPROTO);
140
		goto err;
141
	}
142
143
	fpi_imgdev_report_finger_status(dev, TRUE);
144
145
	tmp = fpi_img_new(IMG_WIDTH * IMG_HEIGHT);
146
	tmp->width = IMG_WIDTH;
147
	tmp->height = IMG_HEIGHT;
148
	tmp->flags = FP_IMG_COLORS_INVERTED | FP_IMG_V_FLIPPED | FP_IMG_H_FLIPPED;
149
	for (i = 0; i < NR_SUBARRAYS; i++) {
150
		fp_dbg("subarray header byte %02x", *ptr);
151
		ptr++;
152
		aes_assemble_image(ptr, 96, 16, tmp->data + (i * 96 * 16));
153
		ptr += SUBARRAY_LEN;
154
	}
155
156
	/* FIXME: this is an ugly hack to make the image big enough for NBIS
157
	 * to process reliably */
158
	img = fpi_im_resize(tmp, ENLARGE_FACTOR, ENLARGE_FACTOR);
159
	fp_img_free(tmp);
160
	fpi_imgdev_image_captured(dev, img);
161
162
	/* FIXME: rather than assuming finger has gone, we should poll regs until
163
	 * it really has, then restart the capture */
164
	fpi_imgdev_report_finger_status(dev, FALSE);
165
166
	do_capture(dev);
167
168
err:
169
	g_free(transfer->buffer);
170
	aesdev->img_trf = NULL;
171
	libusb_free_transfer(transfer);
172
}
173
174
static void do_capture(struct fp_img_dev *dev)
175
{
176
	struct aes4k_dev *aesdev = dev->priv;
177
	unsigned char *data;
178
	int r;
179
180
	aesdev->img_trf = libusb_alloc_transfer(0);
181
	if (!aesdev->img_trf) {
182
		fpi_imgdev_session_error(dev, -EIO);
183
		return;
184
	}
185
186
	data = g_malloc(DATA_BUFLEN);
187
	libusb_fill_bulk_transfer(aesdev->img_trf, dev->udev, EP_IN, data,
188
		DATA_BUFLEN, img_cb, dev, 0);
189
190
	r = libusb_submit_transfer(aesdev->img_trf);
191
	if (r < 0) {
192
		g_free(data);
193
		libusb_free_transfer(aesdev->img_trf);
194
		aesdev->img_trf = NULL;
195
		fpi_imgdev_session_error(dev, r);
196
	}
197
}
198
199
static void init_reqs_cb(struct fp_img_dev *dev, int result, void *user_data)
200
{
201
	fpi_imgdev_activate_complete(dev, result);
202
	if (result == 0)
203
		do_capture(dev);
204
}
205
206
static int dev_activate(struct fp_img_dev *dev, enum fp_imgdev_state state)
207
{
208
	aes_write_regv(dev, init_reqs, G_N_ELEMENTS(init_reqs), init_reqs_cb, NULL);
209
	return 0;
210
}
211
212
static void dev_deactivate(struct fp_img_dev *dev)
213
{
214
	struct aes4k_dev *aesdev = dev->priv;
215
216
	/* FIXME: should wait for cancellation to complete before returning
217
	 * from deactivation, otherwise app may legally exit before we've
218
	 * cleaned up */
219
	if (aesdev->img_trf)
220
		libusb_cancel_transfer(aesdev->img_trf);
221
	fpi_imgdev_deactivate_complete(dev);
222
}
223
224
static int dev_init(struct fp_img_dev *dev, unsigned long driver_data)
124
static int dev_init(struct fp_img_dev *dev, unsigned long driver_data)
225
{
125
{
226
	int r;
126
	int r;
127
	struct aes3k_dev *aesdev;
227
128
228
	r = libusb_claim_interface(dev->udev, 0);
129
	r = libusb_claim_interface(dev->udev, 0);
229
	if (r < 0)
130
	if (r < 0)
230
		fp_err("could not claim interface 0");
131
		fp_err("could not claim interface 0");
231
132
232
	dev->priv = g_malloc0(sizeof(struct aes4k_dev));
133
	aesdev = dev->priv = g_malloc0(sizeof(struct aes3k_dev));
134
135
	if (!aesdev)
136
		return -ENOMEM;
233
137
234
	if (r == 0)
138
	if (r == 0)
139
		aesdev->data_buflen = DATA_BUFLEN;
140
		aesdev->frame_width = FRAME_WIDTH;
141
		aesdev->frame_size = FRAME_SIZE;
142
		aesdev->frame_number = FRAME_NUMBER;
143
		aesdev->enlarge_factor = ENLARGE_FACTOR;
144
		aesdev->init_reqs = init_reqs;
145
		aesdev->init_reqs_len = G_N_ELEMENTS(init_reqs);
235
		fpi_imgdev_open_complete(dev, 0);
146
		fpi_imgdev_open_complete(dev, 0);
236
147
237
	return r;
148
	return r;
Lines 239-249 static int dev_init(struct fp_img_dev *dev, unsigned long driver_data) Link Here
239
150
240
static void dev_deinit(struct fp_img_dev *dev)
151
static void dev_deinit(struct fp_img_dev *dev)
241
{
152
{
242
	g_free(dev->priv);
153
	struct aes3k_dev *aesdev = dev->priv;
154
	g_free(aesdev);
243
	libusb_release_interface(dev->udev, 0);
155
	libusb_release_interface(dev->udev, 0);
244
	fpi_imgdev_close_complete(dev);
156
	fpi_imgdev_close_complete(dev);
245
}
157
}
246
158
159
247
static const struct usb_id id_table[] = {
160
static const struct usb_id id_table[] = {
248
	{ .vendor = 0x08ff, .product = 0x5501 },
161
	{ .vendor = 0x08ff, .product = 0x5501 },
249
	{ 0, 0, 0, },
162
	{ 0, 0, 0, },
Lines 258-272 struct fp_img_driver aes4000_driver = { Link Here
258
		.scan_type = FP_SCAN_TYPE_PRESS,
171
		.scan_type = FP_SCAN_TYPE_PRESS,
259
	},
172
	},
260
	.flags = 0,
173
	.flags = 0,
261
	.img_height = IMG_HEIGHT * ENLARGE_FACTOR,
174
	.img_height = FRAME_WIDTH * ENLARGE_FACTOR,
262
	.img_width = IMG_WIDTH * ENLARGE_FACTOR,
175
	.img_width = FRAME_WIDTH * ENLARGE_FACTOR,
263
176
264
	/* temporarily lowered until image quality improves */
177
	/* temporarily lowered until image quality improves */
265
	.bz3_threshold = 9,
178
	.bz3_threshold = 9,
266
179
267
	.open = dev_init,
180
	.open = dev_init,
268
	.close = dev_deinit,
181
	.close = dev_deinit,
269
	.activate = dev_activate,
182
	.activate = aes3k_dev_activate,
270
	.deactivate = dev_deactivate,
183
	.deactivate = aes3k_dev_deactivate,
271
};
184
};
272
185
(-)a/libfprint/drivers/driver_ids.h (+4 lines)
Lines 36-41 enum { Link Here
36
	UPEKE2_ID	= 13,
36
	UPEKE2_ID	= 13,
37
	AES1660_ID	= 14,
37
	AES1660_ID	= 14,
38
	AES2660_ID	= 15,
38
	AES2660_ID	= 15,
39
	AES3500_ID	= 16,
40
	UPEKTC_IMG_ID	= 17,
41
	ETES603_ID	= 18,
42
        VFS0050_ID      = 19,
39
};
43
};
40
44
41
#endif
45
#endif
(-)a/libfprint/drivers/etes603.c (+1513 lines)
Line 0 Link Here
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
#include <string.h>
37
#include <stdint.h>
38
#include <stdarg.h>
39
#include <errno.h>
40
#include <assert.h>
41
#include <libusb.h>
42
#include <glib.h>
43
44
#define FP_COMPONENT "etes603"
45
#include <fp_internal.h>
46
#include "driver_ids.h"
47
48
/* libusb defines */
49
#define EP_IN              0x81
50
#define EP_OUT             0x02
51
/* Note that 1000 ms is usually enough but with CMD_READ_FE could be longer
52
 * since the sensor is waiting motion. */
53
#define BULK_TIMEOUT       1000
54
55
/* es603 defines */
56
#define FRAME_WIDTH        192  /* pixels per row */
57
#define FRAME_HEIGHT       4    /* number of rows */
58
#define FRAME_SIZE         384  /* size in bytes (4 bits per pixels) */
59
#define FE_WIDTH           256  /* pixels per row for Fly-Estimation */
60
#define FE_HEIGHT          500  /* number of rows for Fly-Estimation */
61
#define FE_SIZE            64000 /* size in bytes (4 bits per pixels) */
62
63
#define GAIN_SMALL_INIT    0x23 /* Initial small gain */
64
#define VRT_MAX	           0x3F /* Maximum value for VRT */
65
#define VRB_MAX            0x3A /* Maximum value for VRB */
66
#define DTVRT_MAX          0x3A /* Maximum value for DTVRT */
67
#define DCOFFSET_MIN       0x00 /* Minimum value for DCoffset */
68
#define DCOFFSET_MAX       0x35 /* Maximum value for DCoffset */
69
70
/* es603 commands */
71
#define CMD_READ_REG       0x01
72
#define CMD_WRITE_REG      0x02
73
#define CMD_READ_FRAME     0x03 /* Read the sensor area */
74
#define CMD_READ_FE        0x06 /* Read a fingerprint using Fly-Estimation */
75
#define CMD_20             0x20 /* ? */
76
#define CMD_25             0x25 /* ? */
77
#define CMD_60             0x60 /* ? */
78
79
#define CMD_OK             0x01 /* Command successfully executed */
80
81
/* es603 registers */
82
#define REG_MAX            0x18 /* Maximum number of registers in one message */
83
#define REG_MODE_CONTROL   0x02 /* Mode control */
84
#define REG_03             0x03 /* Contact register? */
85
#define REG_04             0x04 /* ? */
86
#define REG_10             0x10 /* MVS FRMBUF control */
87
#define REG_1A             0x1A /* ? */
88
/* BEGIN init sensor */
89
#define REG_20             0x20 /* (def: 0x00) */
90
#define REG_21             0x21 /* Small gain (def: 0x23) */
91
#define REG_22             0x22 /* Normal gain (def: 0x21) */
92
#define REG_23             0x23 /* Large gain (def: 0x20) */
93
#define REG_24             0x24 /* (def: 0x14) */
94
#define REG_25             0x25 /* (def: 0x6A) */
95
#define REG_26             0x26 /* VRB again? (def: 0x00) */
96
#define REG_27             0x27 /* VRT again? (def: 0x00) */
97
#define REG_28             0x28 /* (def: 0x00) */
98
#define REG_29             0x29 /* (def: 0xC0) */
99
#define REG_2A             0x2A /* (def: 0x50) */
100
#define REG_2B             0x2B /* (def: 0x50) */
101
#define REG_2C             0x2C /* (def: 0x4D) */
102
#define REG_2D             0x2D /* (def: 0x03) */
103
#define REG_2E             0x2E /* (def: 0x06) */
104
#define REG_2F             0x2F /* (def: 0x06) */
105
#define REG_30             0x30 /* (def: 0x10) */
106
#define REG_31             0x31 /* (def: 0x02) */
107
#define REG_32             0x32 /* (def: 0x14) */
108
#define REG_33             0x33 /* (def: 0x34) */
109
#define REG_34             0x34 /* (def: 0x01) */
110
#define REG_35             0x35 /* (def: 0x08) */
111
#define REG_36             0x36 /* (def: 0x03) */
112
#define REG_37             0x37 /* (def: 0x21) */
113
/* END init sensor */
114
115
#define REG_ENC1           0x41 /* Encryption 1 */
116
#define REG_ENC2           0x42
117
#define REG_ENC3           0x43
118
#define REG_ENC4           0x44
119
#define REG_ENC5           0x45
120
#define REG_ENC6           0x46
121
#define REG_ENC7           0x47
122
#define REG_ENC8           0x48 /* Encryption 8 */
123
124
#define REG_50             0x50 /* ? For contact detection */
125
#define REG_51             0x51 /* ? */
126
#define REG_59             0x59 /* ? */
127
#define REG_5A             0x5A /* ? */
128
#define REG_5B             0x5B /* ? */
129
130
#define REG_INFO0          0x70 /* Sensor model byte0 */
131
#define REG_INFO1          0x71 /* Sensor model byte1 */
132
#define REG_INFO2          0x72 /* Sensor model byte2 */
133
#define REG_INFO3          0x73 /* Sensor model byte3 */
134
135
#define REG_GAIN           0xE0
136
#define REG_VRT            0xE1
137
#define REG_VRB            0xE2
138
#define REG_DTVRT          0xE3 /* used for contact detection */
139
#define REG_VCO_CONTROL    0xE5 /* 0x13 (IDLE?), 0x14 (REALTIME) */
140
#define REG_DCOFFSET       0xE6
141
142
#define REG_F0             0xF0 /* ? init:0x00 close:0x01 */
143
#define REG_F2             0xF2 /* ? init:0x00 close:0x4E */
144
145
#define REG_MODE_SLEEP     0x30 /* Sleep mode */
146
#define REG_MODE_CONTACT   0x31 /* Contact mode */
147
#define REG_MODE_SENSOR    0x33 /* Sensor mode */
148
#define REG_MODE_FP        0x34 /* FingerPrint mode (Fly-Estimation®) */
149
150
#define REG_VCO_IDLE       0x13
151
#define REG_VCO_RT         0x14 /* Realtime */
152
153
/* The size of the message header is 5 plus 1 for the command. */
154
#define MSG_HDR_SIZE       6
155
156
/* This structure must be packed because it is a the raw message sent. */
157
struct egis_msg {
158
	uint8_t magic[5]; /* out: 'EGIS' 0x09 / in: 'SIGE' 0x0A */
159
	uint8_t cmd;
160
	union {
161
		struct {
162
			uint8_t nb;
163
			uint8_t regs[REG_MAX];
164
		} egis_readreg;
165
		struct {
166
			uint8_t regs[REG_MAX];
167
		} sige_readreg;
168
		struct {
169
			uint8_t nb;
170
			struct {
171
				uint8_t reg;
172
				uint8_t val;
173
			} regs[REG_MAX];
174
		} egis_writereg;
175
		struct {
176
			uint8_t length_factor;
177
			uint8_t length;
178
			uint8_t use_gvv;
179
			uint8_t gain;
180
			uint8_t vrt;
181
			uint8_t vrb;
182
		} egis_readf;
183
		struct {
184
			uint8_t len[2];
185
			uint8_t val[3];
186
		} egis_readfp;
187
		struct {
188
			uint8_t val[5];
189
		} sige_misc;
190
		uint8_t padding[0x40-6]; /* Ensure size of 0x40 */
191
	};
192
} __attribute__((packed));
193
194
195
/* Structure to keep information between asynchronous functions. */
196
struct etes603_dev {
197
	uint8_t regs[256];
198
	struct egis_msg *req;
199
	size_t req_len;
200
	struct egis_msg *ans;
201
	size_t ans_len;
202
203
	uint8_t *fp;
204
	uint16_t fp_height;
205
206
	uint8_t tunedc_min;
207
	uint8_t tunedc_max;
208
209
	/* Device parameters */
210
	uint8_t gain;
211
	uint8_t dcoffset;
212
	uint8_t vrt;
213
	uint8_t vrb;
214
215
	unsigned int is_active;
216
};
217
218
static void m_start_fingerdetect(struct fp_img_dev *idev);
219
/*
220
 * Prepare the header of the message to be sent to the device.
221
 */
222
static void msg_header_prepare(struct egis_msg *msg)
223
{
224
	msg->magic[0] = 'E';
225
	msg->magic[1] = 'G';
226
	msg->magic[2] = 'I';
227
	msg->magic[3] = 'S';
228
	msg->magic[4] = 0x09;
229
}
230
231
/*
232
 * Check that the header of the received message is correct.
233
 */
234
static int msg_header_check(struct egis_msg *msg)
235
{
236
	if (msg->magic[0] == 'S' && msg->magic[1] == 'I'
237
	    && msg->magic[2] == 'G' && msg->magic[3] == 'E'
238
	    && msg->magic[4] == 0x0A)
239
		return 0;
240
	return -1;
241
}
242
243
/*
244
 * Prepare message to ask for a frame.
245
 */
246
static void msg_get_frame(struct etes603_dev *dev,
247
	uint8_t use_gvv, uint8_t gain, uint8_t vrt, uint8_t vrb)
248
{
249
	struct egis_msg *msg = dev->req;
250
	msg_header_prepare(msg);
251
	msg->cmd = CMD_READ_FRAME;
252
	msg->egis_readf.length_factor = 0x01;
253
	/* length should be 0xC0 */
254
	msg->egis_readf.length = FRAME_WIDTH;
255
	msg->egis_readf.use_gvv = use_gvv;
256
	/* if use_gvv is set, gain/vrt/vrb are used */
257
	msg->egis_readf.gain = gain;
258
	msg->egis_readf.vrt = vrt;
259
	msg->egis_readf.vrb = vrb;
260
261
	dev->req_len = MSG_HDR_SIZE + 6;
262
	dev->ans_len = FRAME_SIZE;
263
}
264
265
/*
266
 * Prepare message to ask for a fingerprint frame.
267
 */
268
static void msg_get_fp(struct etes603_dev *dev, uint8_t len0, uint8_t len1,
269
	uint8_t v2, uint8_t v3, uint8_t v4)
270
{
271
	struct egis_msg *msg = dev->req;
272
	msg_header_prepare(msg);
273
	msg->cmd = CMD_READ_FE;
274
	/* Unknown values and always same on captured frames.
275
	 * 1st 2nd bytes is unsigned short for height, but only on value range
276
	 * 0x01 0xF4 (500), 0x02 0x00 (512), 0x02 0xF4 (756) are ok
277
	 */
278
	msg->egis_readfp.len[0] = len0;
279
	msg->egis_readfp.len[1] = len1;
280
	/* 3rd byte : ?? but changes frame size
281
	 * 4th byte : 0x00 -> can change width
282
	 * 5th byte : motion sensibility?
283
	 */
284
	msg->egis_readfp.val[0] = v2;
285
	msg->egis_readfp.val[1] = v3;
286
	msg->egis_readfp.val[2] = v4;
287
288
	dev->req_len = MSG_HDR_SIZE + 5;
289
	dev->ans_len = FE_SIZE;
290
}
291
292
/*
293
 * Prepare message to read registers from the sensor.
294
 * Variadic argument pattern: int reg, ...
295
 */
296
static void msg_get_regs(struct etes603_dev *dev, int n_args, ... )
297
{
298
	struct egis_msg *msg = dev->req;
299
	va_list ap;
300
	int i;
301
302
	assert(n_args > 0 && n_args <= REG_MAX);
303
304
	msg_header_prepare(msg);
305
	msg->cmd = CMD_READ_REG;
306
	msg->egis_readreg.nb = n_args;
307
	va_start(ap, n_args);
308
	for (i = 0; i < n_args; i++) {
309
		msg->egis_readreg.regs[i] = va_arg(ap, int);
310
	}
311
	va_end(ap);
312
313
	dev->req_len = MSG_HDR_SIZE + 1 + n_args;
314
	dev->ans_len = MSG_HDR_SIZE + 1 + n_args;
315
}
316
317
/*
318
 * Parse the result of read register command.
319
 */
320
static int msg_parse_regs(struct etes603_dev *dev)
321
{
322
	size_t i, n_args;
323
	struct egis_msg *msg_req = dev->req;
324
	struct egis_msg *msg_ans = dev->ans;
325
	n_args = dev->ans_len - MSG_HDR_SIZE;
326
327
	if (msg_header_check(msg_ans)) {
328
		return -1;
329
	}
330
	if (msg_ans->cmd != CMD_OK) {
331
		return -2;
332
	}
333
334
	for (i = 0; i < n_args; i++) {
335
		int reg = msg_req->egis_readreg.regs[i];
336
		dev->regs[reg] = msg_ans->sige_readreg.regs[i];
337
	}
338
	return 0;
339
}
340
341
/*
342
 * Prepare message to write sensor's registers.
343
 * Variadic arguments are: int reg, int val, ...
344
 */
345
static void msg_set_regs(struct etes603_dev *dev, int n_args, ...)
346
{
347
	struct egis_msg *msg = dev->req;
348
	va_list ap;
349
	int i;
350
351
	assert(n_args != 0 && n_args % 2 == 0 && n_args <= REG_MAX * 2);
352
353
	msg_header_prepare(msg);
354
	msg->cmd = CMD_WRITE_REG;
355
	msg->egis_writereg.nb = n_args / 2;
356
357
	va_start(ap, n_args);
358
	for (i = 0; i < n_args / 2; i++) {
359
		msg->egis_writereg.regs[i].reg = va_arg(ap, int);
360
		msg->egis_writereg.regs[i].val = va_arg(ap, int);
361
	}
362
	va_end(ap);
363
364
	dev->req_len = MSG_HDR_SIZE + 1 + n_args;
365
	dev->ans_len = MSG_HDR_SIZE + 1;
366
}
367
368
static int msg_check_ok(struct etes603_dev *dev)
369
{
370
	struct egis_msg *msg = dev->ans;
371
	if (msg_header_check(msg)) {
372
		goto err;
373
	}
374
	if (msg->cmd != CMD_OK) {
375
		goto err;
376
	}
377
	return 0;
378
err:
379
	return -1;
380
}
381
382
/*
383
 * Check the model of the sensor.
384
 */
385
static int check_info(struct etes603_dev *dev)
386
{
387
	if (dev->regs[0x70] == 0x4A && dev->regs[0x71] == 0x44
388
	    && dev->regs[0x72] == 0x49 && dev->regs[0x73] == 0x31)
389
		return 0;
390
	fp_err("unknown device parameters (REG_70:%02X REG_71:%02X "
391
		"REG_FIRMWARE:%02X REG_VERSION:%02X)",
392
		dev->regs[0x70], dev->regs[0x71], dev->regs[0x72],
393
		dev->regs[0x73]);
394
	return -1;
395
}
396
397
static void msg_get_cmd20(struct etes603_dev *dev)
398
{
399
	struct egis_msg *msg = dev->req;
400
	msg_header_prepare(msg);
401
	msg->cmd = CMD_20;
402
	dev->req_len = MSG_HDR_SIZE;
403
}
404
405
static int msg_check_cmd20(struct etes603_dev *dev)
406
{
407
	struct egis_msg *msg = dev->ans;
408
	if (msg_header_check(msg)) {
409
		fp_err("msg_header_check failed");
410
		return -1;
411
	}
412
	/* status or flashtype/flashinfo or ? */
413
	if (msg->cmd != 0x05
414
	    || msg->sige_misc.val[0] != 0x00
415
	    || msg->sige_misc.val[1] != 0x00) {
416
		fp_warn("unexpected answer CMD_20 from device(%02X %02X %02X)",
417
			msg->cmd, msg->sige_misc.val[0], msg->sige_misc.val[1]);
418
	}
419
420
	return 0;
421
}
422
423
static void msg_get_cmd25(struct etes603_dev *dev)
424
{
425
	struct egis_msg *msg = dev->req;
426
	msg_header_prepare(msg);
427
	msg->cmd = CMD_25;
428
	dev->req_len = MSG_HDR_SIZE;
429
}
430
431
static int msg_check_cmd25(struct etes603_dev *dev)
432
{
433
	struct egis_msg *msg = dev->ans;
434
	if (msg_header_check(msg)) {
435
		fp_err("msg_header_check failed");
436
		goto err;
437
	}
438
	if (msg->cmd != CMD_OK) {
439
		fp_err("CMD_OK failed");
440
		goto err;
441
	}
442
	/* flashtype or status or ? */
443
	if (msg->sige_misc.val[0] != 0x00) {
444
		fp_warn("unexpected answer for CMD_25 (%02X)",
445
			msg->sige_misc.val[0]);
446
	}
447
	return 0;
448
err:
449
	return -1;
450
}
451
452
static void msg_set_mode_control(struct etes603_dev *dev, uint8_t mode)
453
{
454
	msg_set_regs(dev, 2, REG_MODE_CONTROL, mode);
455
}
456
457
458
/* Processing functions */
459
460
/*
461
 * Return the brightness of a 4bpp frame
462
 */
463
static unsigned int process_get_brightness(uint8_t *f, size_t s)
464
{
465
	unsigned int i, sum = 0;
466
	for (i = 0; i < s; i++) {
467
		sum += f[i] >> 4;
468
		sum += f[i] & 0x0F;
469
	}
470
	return sum;
471
}
472
473
/*
474
 * Return the histogram of a 4bpp frame
475
 */
476
static void process_hist(uint8_t *f, size_t s, float stat[5])
477
{
478
	float hist[16];
479
	float black_mean, white_mean;
480
	int i;
481
	/* Clean histogram */
482
	for (i = 0; i < 16; i++)
483
		hist[i] = 0.0;
484
	for (i = 0; i < s; i++) {
485
		hist[f[i] >> 4]++;
486
		hist[f[i] & 0x0F]++;
487
	}
488
	/* histogram average */
489
	for (i = 0; i < 16; i++) {
490
		hist[i] = hist[i] / (s * 2);
491
	}
492
	/* Average black/white pixels (full black and full white pixels
493
	 * are excluded). */
494
	black_mean = white_mean = 0.0;
495
	for (i = 1; i < 8; i++)
496
		black_mean += hist[i];
497
	for (i = 8; i < 15; i++)
498
		white_mean += hist[i];
499
	stat[0] = hist[0];
500
	stat[1] = black_mean;
501
	stat[2] = black_mean+white_mean;
502
	stat[3] = white_mean;
503
	stat[4] = hist[15];
504
	fp_dbg("fullb=%6f black=%6f grey=%6f white=%6f fullw=%6f",
505
		hist[0], black_mean, black_mean+white_mean, white_mean,
506
		hist[15]);
507
}
508
509
/*
510
 * Return true if the frame is almost empty.
511
 */
512
static int process_frame_empty(uint8_t *frame, size_t size)
513
{
514
	unsigned int sum = process_get_brightness(frame, size);
515
	/* Allow an average of 'threshold' luminosity per pixel */
516
	if (sum < size)
517
		return 1;
518
	return 0;
519
}
520
521
/* Transform 4 bits image to 8 bits image */
522
static void process_4to8_bpp(uint8_t *input, unsigned int input_size,
523
	uint8_t *output)
524
{
525
	unsigned int i, j = 0;
526
	for (i = 0; i < input_size; i++, j += 2) {
527
		/* 16 gray levels transform to 256 levels using << 4 */
528
		output[j] = input[i] & 0xF0;
529
		output[j+1] = input[i] << 4;
530
	}
531
}
532
533
/*
534
 * Remove duplicated lines at the end of a fingerprint.
535
 */
536
static void process_remove_fp_end(struct etes603_dev *dev)
537
{
538
	unsigned int i;
539
	/* 2 last lines with Fly-Estimation are the empty pattern. */
540
	uint8_t *pattern = dev->fp + (dev->fp_height - 2) * FE_WIDTH / 2;
541
	for (i = 2; i < dev->fp_height; i+= 2) {
542
		if (memcmp(pattern, pattern - (i * FE_WIDTH / 2), FE_WIDTH))
543
			break;
544
	}
545
	dev->fp_height -= i;
546
	fp_dbg("Removing %d empty lines from image", i - 2);
547
}
548
549
static void reset_param(struct etes603_dev *dev)
550
{
551
	dev->dcoffset = 0;
552
	dev->vrt = 0;
553
	dev->vrb = 0;
554
	dev->gain = 0;
555
}
556
557
558
/* Asynchronous stuff */
559
560
enum {
561
	INIT_CHECK_INFO_REQ,
562
	INIT_CHECK_INFO_ANS,
563
	INIT_CMD20_REQ,
564
	INIT_CMD20_ANS,
565
	INIT_CMD25_REQ,
566
	INIT_CMD25_ANS,
567
	INIT_SENSOR_REQ,
568
	INIT_SENSOR_ANS,
569
	INIT_ENC_REQ,
570
	INIT_ENC_ANS,
571
	INIT_REGS_REQ,
572
	INIT_REGS_ANS,
573
	INIT_NUM_STATES
574
};
575
576
enum {
577
	TUNEDC_INIT,
578
	TUNEDC_SET_DCOFFSET_REQ,
579
	TUNEDC_SET_DCOFFSET_ANS,
580
	TUNEDC_GET_FRAME_REQ,
581
	TUNEDC_GET_FRAME_ANS,
582
	TUNEDC_FINAL_SET_REG2122_REQ,
583
	TUNEDC_FINAL_SET_REG2122_ANS,
584
	TUNEDC_FINAL_SET_GAIN_REQ,
585
	TUNEDC_FINAL_SET_GAIN_ANS,
586
	TUNEDC_FINAL_SET_DCOFFSET_REQ,
587
	TUNEDC_FINAL_SET_DCOFFSET_ANS,
588
	TUNEDC_NUM_STATES
589
};
590
591
enum {
592
	TUNEVRB_INIT,
593
	TUNEVRB_GET_GAIN_REQ,
594
	TUNEVRB_GET_GAIN_ANS,
595
	TUNEVRB_GET_DCOFFSET_REQ,
596
	TUNEVRB_GET_DCOFFSET_ANS,
597
	TUNEVRB_SET_DCOFFSET_REQ,
598
	TUNEVRB_SET_DCOFFSET_ANS,
599
	TUNEVRB_FRAME_REQ,
600
	TUNEVRB_FRAME_ANS,
601
	TUNEVRB_FINAL_SET_DCOFFSET_REQ,
602
	TUNEVRB_FINAL_SET_DCOFFSET_ANS,
603
	TUNEVRB_FINAL_SET_REG2627_REQ,
604
	TUNEVRB_FINAL_SET_REG2627_ANS,
605
	TUNEVRB_FINAL_SET_GAINVRTVRB_REQ,
606
	TUNEVRB_FINAL_SET_GAINVRTVRB_ANS,
607
	TUNEVRB_FINAL_SET_MODE_SLEEP_REQ,
608
	TUNEVRB_FINAL_SET_MODE_SLEEP_ANS,
609
	TUNEVRB_NUM_STATES
610
};
611
612
enum {
613
	FGR_FPA_INIT_SET_MODE_SLEEP_REQ,
614
	FGR_FPA_INIT_SET_MODE_SLEEP_ANS,
615
	FGR_FPA_INIT_SET_DCOFFSET_REQ,
616
	FGR_FPA_INIT_SET_DCOFFSET_ANS,
617
	FGR_FPA_INIT_SET_GAINVRTVRB_REQ,
618
	FGR_FPA_INIT_SET_GAINVRTVRB_ANS,
619
	FGR_FPA_INIT_SET_VCO_CONTROL_RT_REQ,
620
	FGR_FPA_INIT_SET_VCO_CONTROL_RT_ANS,
621
	FGR_FPA_INIT_SET_REG04_REQ,
622
	FGR_FPA_INIT_SET_REG04_ANS,
623
	FGR_FPA_INIT_SET_MODE_SENSOR_REQ,
624
	FGR_FPA_INIT_SET_MODE_SENSOR_ANS,
625
	FGR_FPA_GET_FRAME_REQ,
626
	FGR_FPA_GET_FRAME_ANS,
627
	FGR_NUM_STATES
628
};
629
630
enum {
631
	CAP_FP_INIT_SET_REG10_REQ,
632
	CAP_FP_INIT_SET_REG10_ANS,
633
	CAP_FP_INIT_SET_MODE_FP_REQ,
634
	CAP_FP_INIT_SET_MODE_FP_ANS,
635
	CAP_FP_GET_FP_REQ,
636
	CAP_FP_GET_FP_ANS,
637
	CAP_NUM_STATES
638
};
639
640
enum {
641
	EXIT_SET_REGS_REQ,
642
	EXIT_SET_REGS_ANS,
643
	EXIT_NUM_STATES
644
};
645
646
static int async_tx(struct fp_img_dev *idev, unsigned int ep, void *cb,
647
	void *cb_arg)
648
{
649
	struct etes603_dev *dev = idev->priv;
650
	struct libusb_transfer *transfer = libusb_alloc_transfer(0);
651
	unsigned char *buffer;
652
	int length;
653
654
	if (!transfer)
655
		return -ENOMEM;
656
657
	if (ep == EP_OUT) {
658
		buffer = (unsigned char *)dev->req;
659
		length = dev->req_len;
660
	} else if (ep == EP_IN) {
661
		buffer = (unsigned char *)dev->ans;
662
		length = dev->ans_len;
663
	} else {
664
		return -EIO;
665
	}
666
	libusb_fill_bulk_transfer(transfer, idev->udev, ep, buffer, length,
667
				  cb, cb_arg, BULK_TIMEOUT);
668
669
	if (libusb_submit_transfer(transfer)) {
670
		libusb_free_transfer(transfer);
671
		return -EIO;
672
	}
673
	return 0;
674
}
675
676
677
static void async_tx_cb(struct libusb_transfer *transfer)
678
{
679
	struct fpi_ssm *ssm = transfer->user_data;
680
	struct fp_img_dev *idev = ssm->priv;
681
	struct etes603_dev *dev = idev->priv;
682
683
	if (transfer->status != LIBUSB_TRANSFER_COMPLETED) {
684
		fp_warn("transfer is not completed (status=%d)",
685
			transfer->status);
686
		fpi_ssm_mark_aborted(ssm, -EIO);
687
		libusb_free_transfer(transfer);
688
	} else {
689
		unsigned char endpoint = transfer->endpoint;
690
		int actual_length = transfer->actual_length;
691
		int length = transfer->length;
692
		/* Freeing now transfer since fpi_ssm_* functions are not
693
		 * returning directly. */
694
		libusb_free_transfer(transfer);
695
		if (endpoint == EP_OUT) {
696
			if (length != actual_length)
697
				fp_warn("length %d != actual_length %d",
698
					length, actual_length);
699
			/* Chained with the answer */
700
			if (async_tx(idev, EP_IN, async_tx_cb, ssm))
701
				fpi_ssm_mark_aborted(ssm, -EIO);
702
		} else if (endpoint == EP_IN) {
703
			dev->ans_len = actual_length;
704
			fpi_ssm_next_state(ssm);
705
		}
706
	}
707
}
708
709
static void m_exit_state(struct fpi_ssm *ssm)
710
{
711
	struct fp_img_dev *idev = ssm->priv;
712
	struct etes603_dev *dev = idev->priv;
713
714
	switch (ssm->cur_state) {
715
	case EXIT_SET_REGS_REQ:
716
		msg_set_regs(dev, 4, REG_VCO_CONTROL, REG_VCO_IDLE,
717
			     REG_MODE_CONTROL, REG_MODE_SLEEP);
718
		if (async_tx(idev, EP_OUT, async_tx_cb, ssm))
719
			goto err;
720
		break;
721
	case EXIT_SET_REGS_ANS:
722
		if (msg_check_ok(dev))
723
			goto err;
724
		fpi_ssm_mark_completed(ssm);
725
		break;
726
	default:
727
		fp_err("Unknown state %d", ssm->cur_state);
728
		goto err;
729
		break;
730
	}
731
732
	return;
733
err:
734
	fpi_ssm_mark_aborted(ssm, -EIO);
735
}
736
737
static void m_exit_complete(struct fpi_ssm *ssm)
738
{
739
	struct fp_img_dev *idev = ssm->priv;
740
741
	if (ssm->error) {
742
		fp_err("Error switching the device to idle state");
743
	} else {
744
		fp_dbg("The device is now in idle state");
745
	}
746
	fpi_imgdev_deactivate_complete(idev);
747
	fpi_ssm_free(ssm);
748
}
749
750
static void m_exit_start(struct fp_img_dev *idev)
751
{
752
	struct fpi_ssm *ssm = fpi_ssm_new(idev->dev, m_exit_state,
753
					  EXIT_NUM_STATES);
754
	fp_dbg("Switching device to idle mode");
755
	ssm->priv = idev;
756
	fpi_ssm_start(ssm, m_exit_complete);
757
}
758
759
static void m_capture_state(struct fpi_ssm *ssm)
760
{
761
	struct fp_img_dev *idev = ssm->priv;
762
	struct etes603_dev *dev = idev->priv;
763
764
	if (dev->is_active == FALSE) {
765
		fpi_ssm_mark_completed(ssm);
766
		return;
767
	}
768
769
	switch (ssm->cur_state) {
770
	case CAP_FP_INIT_SET_REG10_REQ:
771
		/* Reset fingerprint */
772
		fp_dbg("Capturing a fingerprint...");
773
		memset(dev->fp, 0, FE_SIZE * 2);
774
		dev->fp_height = 0;
775
		msg_set_regs(dev, 2, REG_10, 0x92);
776
		if (async_tx(idev, EP_OUT, async_tx_cb, ssm))
777
			goto err;
778
		break;
779
	case CAP_FP_INIT_SET_REG10_ANS:
780
		if (msg_check_ok(dev))
781
			goto err;
782
		fpi_ssm_next_state(ssm);
783
		break;
784
	case CAP_FP_INIT_SET_MODE_FP_REQ:
785
		msg_set_mode_control(dev, REG_MODE_FP);
786
		if (async_tx(idev, EP_OUT, async_tx_cb, ssm))
787
			goto err;
788
		break;
789
	case CAP_FP_INIT_SET_MODE_FP_ANS:
790
		if (msg_check_ok(dev))
791
			goto err;
792
		fp_dbg("Capturing a 1st frame...");
793
		fpi_ssm_next_state(ssm);
794
		break;
795
	case CAP_FP_GET_FP_REQ:
796
		msg_get_fp(dev, 0x01, 0xF4, 0x02, 0x01, 0x64);
797
		if (async_tx(idev, EP_OUT, async_tx_cb, ssm))
798
			goto err;
799
		break;
800
	case CAP_FP_GET_FP_ANS:
801
		memcpy(dev->fp + dev->fp_height * FE_WIDTH / 2, dev->ans,
802
			FE_SIZE);
803
		dev->fp_height += FE_HEIGHT;
804
		if (dev->fp_height <= FE_HEIGHT) {
805
			/* 2 lines are at least removed each time */
806
			dev->fp_height -= 2;
807
			fp_dbg("Capturing a 2nd frame...");
808
			fpi_ssm_jump_to_state(ssm, CAP_FP_GET_FP_REQ);
809
		} else {
810
			struct fp_img *img;
811
			unsigned int img_size;
812
			/* Remove empty parts 2 times for the 2 frames */
813
			process_remove_fp_end(dev);
814
			process_remove_fp_end(dev);
815
			img_size = dev->fp_height * FE_WIDTH;
816
			img = fpi_img_new(img_size);
817
			/* Images received are white on black, so invert it. */
818
			/* TODO detect sweep direction */
819
			img->flags = FP_IMG_COLORS_INVERTED | FP_IMG_V_FLIPPED;
820
			img->height = dev->fp_height;
821
			process_4to8_bpp(dev->fp, img_size / 2, img->data);
822
			fp_dbg("Sending the raw fingerprint image (%dx%d)",
823
				img->width, img->height);
824
			fpi_imgdev_image_captured(idev, img);
825
			fpi_imgdev_report_finger_status(idev, FALSE);
826
			fpi_ssm_mark_completed(ssm);
827
		}
828
		break;
829
	default:
830
		fp_err("Unknown state %d", ssm->cur_state);
831
		goto err;
832
		break;
833
	}
834
835
	return;
836
err:
837
	fpi_ssm_mark_aborted(ssm, -EIO);
838
}
839
840
static void m_capture_complete(struct fpi_ssm *ssm)
841
{
842
	struct fp_img_dev *idev = ssm->priv;
843
	struct etes603_dev *dev = idev->priv;
844
845
	if (ssm->error) {
846
		if (idev->action_state != IMG_ACQUIRE_STATE_DEACTIVATING) {
847
			fp_err("Error while capturing fingerprint "
848
				"(ssm->error=%d)", ssm->error);
849
			fpi_imgdev_session_error(idev, ssm->error);
850
		}
851
	}
852
	fpi_ssm_free(ssm);
853
854
	if (dev->is_active == TRUE) {
855
		fp_dbg("Device is still active, restarting finger detection");
856
		m_start_fingerdetect(idev);
857
	} else {
858
		fp_dbg("And it's over.");
859
	}
860
}
861
862
static void m_finger_state(struct fpi_ssm *ssm)
863
{
864
	struct fp_img_dev *idev = ssm->priv;
865
	struct etes603_dev *dev = idev->priv;
866
867
	if (dev->is_active == FALSE) {
868
		fpi_ssm_mark_completed(ssm);
869
		return;
870
	}
871
872
	switch (ssm->cur_state) {
873
	case FGR_FPA_INIT_SET_MODE_SLEEP_REQ:
874
		msg_set_mode_control(dev, REG_MODE_SLEEP);
875
		if (async_tx(idev, EP_OUT, async_tx_cb, ssm))
876
			goto err;
877
		break;
878
	case FGR_FPA_INIT_SET_MODE_SLEEP_ANS:
879
		if (msg_check_ok(dev))
880
			goto err;
881
		fpi_ssm_next_state(ssm);
882
		break;
883
	case FGR_FPA_INIT_SET_DCOFFSET_REQ:
884
		msg_set_regs(dev, 2, REG_DCOFFSET, dev->dcoffset);
885
		if (async_tx(idev, EP_OUT, async_tx_cb, ssm))
886
			goto err;
887
		break;
888
	case FGR_FPA_INIT_SET_DCOFFSET_ANS:
889
		if (msg_check_ok(dev))
890
			goto err;
891
		fpi_ssm_next_state(ssm);
892
		break;
893
	case FGR_FPA_INIT_SET_GAINVRTVRB_REQ:
894
		msg_set_regs(dev, 6, REG_GAIN, dev->gain, REG_VRT, dev->vrt,
895
			REG_VRB, dev->vrb);
896
		if (async_tx(idev, EP_OUT, async_tx_cb, ssm))
897
			goto err;
898
		break;
899
	case FGR_FPA_INIT_SET_GAINVRTVRB_ANS:
900
		if (msg_check_ok(dev))
901
			goto err;
902
		fpi_ssm_next_state(ssm);
903
		break;
904
	case FGR_FPA_INIT_SET_VCO_CONTROL_RT_REQ:
905
		msg_set_regs(dev, 2, REG_VCO_CONTROL, REG_VCO_RT);
906
		if (async_tx(idev, EP_OUT, async_tx_cb, ssm))
907
			goto err;
908
		break;
909
	case FGR_FPA_INIT_SET_VCO_CONTROL_RT_ANS:
910
		if (msg_check_ok(dev))
911
			goto err;
912
		fpi_ssm_next_state(ssm);
913
		break;
914
	case FGR_FPA_INIT_SET_REG04_REQ:
915
		msg_set_regs(dev, 2, REG_04, 0x00);
916
		if (async_tx(idev, EP_OUT, async_tx_cb, ssm))
917
			goto err;
918
		break;
919
	case FGR_FPA_INIT_SET_REG04_ANS:
920
		if (msg_check_ok(dev))
921
			goto err;
922
		fpi_ssm_next_state(ssm);
923
		break;
924
	case FGR_FPA_INIT_SET_MODE_SENSOR_REQ:
925
		msg_set_mode_control(dev, REG_MODE_SENSOR);
926
		if (async_tx(idev, EP_OUT, async_tx_cb, ssm))
927
			goto err;
928
		break;
929
	case FGR_FPA_INIT_SET_MODE_SENSOR_ANS:
930
		if (msg_check_ok(dev))
931
			goto err;
932
		fpi_ssm_next_state(ssm);
933
		break;
934
	case FGR_FPA_GET_FRAME_REQ:
935
		msg_get_frame(dev, 0x00, 0x00, 0x00, 0x00);
936
		if (async_tx(idev, EP_OUT, async_tx_cb, ssm))
937
			goto err;
938
		break;
939
	case FGR_FPA_GET_FRAME_ANS:
940
		if (process_frame_empty((uint8_t *)dev->ans, FRAME_SIZE)) {
941
			fpi_ssm_jump_to_state(ssm, FGR_FPA_GET_FRAME_REQ);
942
		} else {
943
			fpi_imgdev_report_finger_status(idev, TRUE);
944
			fpi_ssm_mark_completed(ssm);
945
		}
946
		break;
947
	default:
948
		fp_err("Unknown state %d", ssm->cur_state);
949
		goto err;
950
		break;
951
	}
952
953
	return;
954
err:
955
	fpi_ssm_mark_aborted(ssm, -EIO);
956
}
957
958
static void m_finger_complete(struct fpi_ssm *ssm)
959
{
960
	struct fp_img_dev *idev = ssm->priv;
961
	struct etes603_dev *dev = idev->priv;
962
963
	if (!ssm->error) {
964
		struct fpi_ssm *ssm_cap;
965
		ssm_cap = fpi_ssm_new(idev->dev, m_capture_state,
966
				CAP_NUM_STATES);
967
		ssm_cap->priv = idev;
968
		fpi_ssm_start(ssm_cap, m_capture_complete);
969
	} else {
970
		if (idev->action_state != IMG_ACQUIRE_STATE_DEACTIVATING) {
971
			fp_err("Error while capturing fingerprint "
972
				"(ssm->error=%d)", ssm->error);
973
			fpi_imgdev_session_error(idev, -4);
974
		}
975
		dev->is_active = FALSE;
976
	}
977
978
	fpi_ssm_free(ssm);
979
}
980
981
static void m_start_fingerdetect(struct fp_img_dev *idev)
982
{
983
	struct fpi_ssm *ssmf;
984
	ssmf = fpi_ssm_new(idev->dev, m_finger_state, FGR_NUM_STATES);
985
	ssmf->priv = idev;
986
	fpi_ssm_start(ssmf, m_finger_complete);
987
}
988
989
/*
990
 * Tune value of VRT and VRB for contrast and brightness.
991
 */
992
static void m_tunevrb_state(struct fpi_ssm *ssm)
993
{
994
	struct fp_img_dev *idev = ssm->priv;
995
	struct etes603_dev *dev = idev->priv;
996
	float hist[5];
997
998
	if (dev->is_active == FALSE) {
999
		fpi_ssm_mark_completed(ssm);
1000
		return;
1001
	}
1002
1003
	switch (ssm->cur_state) {
1004
	case TUNEVRB_INIT:
1005
		fp_dbg("Tuning of VRT/VRB");
1006
		assert(dev->dcoffset);
1007
		/* VRT(reg E1)=0x0A and VRB(reg E2)=0x10 are starting values */
1008
		dev->vrt = 0x0A;
1009
		dev->vrb = 0x10;
1010
		fpi_ssm_next_state(ssm);
1011
		break;
1012
	case TUNEVRB_GET_GAIN_REQ:
1013
		msg_get_regs(dev, 1, REG_GAIN);
1014
		if (async_tx(idev, EP_OUT, async_tx_cb, ssm))
1015
			goto err;
1016
		break;
1017
	case TUNEVRB_GET_GAIN_ANS:
1018
		if (msg_parse_regs(dev))
1019
			goto err;
1020
		fpi_ssm_next_state(ssm);
1021
		break;
1022
	case TUNEVRB_GET_DCOFFSET_REQ:
1023
		msg_get_regs(dev, 1, REG_DCOFFSET);
1024
		if (async_tx(idev, EP_OUT, async_tx_cb, ssm))
1025
			goto err;
1026
		break;
1027
	case TUNEVRB_GET_DCOFFSET_ANS:
1028
		if (msg_parse_regs(dev))
1029
			goto err;
1030
		fpi_ssm_next_state(ssm);
1031
		break;
1032
	case TUNEVRB_SET_DCOFFSET_REQ:
1033
		/* Reduce DCoffset by 1 to allow tuning */
1034
		msg_set_regs(dev, 2, REG_DCOFFSET, dev->dcoffset - 1);
1035
		if (async_tx(idev, EP_OUT, async_tx_cb, ssm))
1036
			goto err;
1037
		break;
1038
	case TUNEVRB_SET_DCOFFSET_ANS:
1039
		if (msg_check_ok(dev))
1040
			goto err;
1041
		fpi_ssm_next_state(ssm);
1042
		break;
1043
	case TUNEVRB_FRAME_REQ:
1044
		fp_dbg("Testing VRT=0x%02X VRB=0x%02X", dev->vrt, dev->vrb);
1045
		msg_get_frame(dev, 0x01, dev->gain, dev->vrt, dev->vrb);
1046
		if (async_tx(idev, EP_OUT, async_tx_cb, ssm))
1047
			goto err;
1048
		break;
1049
	case TUNEVRB_FRAME_ANS:
1050
		process_hist((uint8_t *)dev->ans, FRAME_SIZE, hist);
1051
		/* Note that this tuning could probably be improved */
1052
		if (hist[0] + hist[1] > 0.95) {
1053
			if (dev->vrt <= 0 || dev->vrb <= 0) {
1054
				fp_dbg("Image is too dark, reducing DCOffset");
1055
				dev->dcoffset--;
1056
				fpi_ssm_jump_to_state(ssm, TUNEVRB_INIT);
1057
			} else {
1058
				dev->vrt--;
1059
				dev->vrb--;
1060
				fpi_ssm_jump_to_state(ssm, TUNEVRB_FRAME_REQ);
1061
			}
1062
			break;
1063
		}
1064
		if (hist[4] > 0.95) {
1065
			fp_dbg("Image is too bright, increasing DCOffset");
1066
			dev->dcoffset++;
1067
			fpi_ssm_jump_to_state(ssm, TUNEVRB_INIT);
1068
			break;
1069
		}
1070
		if (hist[4] + hist[3] > 0.4) {
1071
			if (dev->vrt >= 2 * dev->vrb - 0x0a) {
1072
				dev->vrt++; dev->vrb++;
1073
			} else {
1074
				dev->vrt++;
1075
			}
1076
			/* Check maximum for vrt/vrb */
1077
			/* TODO if maximum is reached, leave with an error? */
1078
			if (dev->vrt > VRT_MAX)
1079
				dev->vrt = VRT_MAX;
1080
			if (dev->vrb > VRB_MAX)
1081
				dev->vrb = VRB_MAX;
1082
			fpi_ssm_jump_to_state(ssm, TUNEVRB_FRAME_REQ);
1083
			break;
1084
		}
1085
		fpi_ssm_next_state(ssm);
1086
		break;
1087
	case TUNEVRB_FINAL_SET_DCOFFSET_REQ:
1088
		fp_dbg("-> VRT=0x%02X VRB=0x%02X", dev->vrt, dev->vrb);
1089
		/* Reset the DCOffset */
1090
		msg_set_regs(dev, 2, REG_DCOFFSET, dev->dcoffset);
1091
		if (async_tx(idev, EP_OUT, async_tx_cb, ssm))
1092
			goto err;
1093
		break;
1094
	case TUNEVRB_FINAL_SET_DCOFFSET_ANS:
1095
		if (msg_check_ok(dev))
1096
			goto err;
1097
		fpi_ssm_next_state(ssm);
1098
		break;
1099
	case TUNEVRB_FINAL_SET_REG2627_REQ:
1100
		/* In traces, REG_26/REG_27 are set. purpose? values? */
1101
		msg_set_regs(dev, 4, REG_26, 0x11, REG_27, 0x00);
1102
		if (async_tx(idev, EP_OUT, async_tx_cb, ssm))
1103
			goto err;
1104
		break;
1105
	case TUNEVRB_FINAL_SET_REG2627_ANS:
1106
		if (msg_check_ok(dev))
1107
			goto err;
1108
		fpi_ssm_next_state(ssm);
1109
		break;
1110
	case TUNEVRB_FINAL_SET_GAINVRTVRB_REQ:
1111
		/* Set Gain/VRT/VRB values found */
1112
		msg_set_regs(dev, 6, REG_GAIN, dev->gain, REG_VRT, dev->vrt,
1113
			     REG_VRB, dev->vrb);
1114
		if (async_tx(idev, EP_OUT, async_tx_cb, ssm))
1115
			goto err;
1116
		break;
1117
	case TUNEVRB_FINAL_SET_GAINVRTVRB_ANS:
1118
		if (msg_check_ok(dev))
1119
			goto err;
1120
		/* In traces, Gain/VRT/VRB are read again. */
1121
		fpi_ssm_next_state(ssm);
1122
		break;
1123
	case TUNEVRB_FINAL_SET_MODE_SLEEP_REQ:
1124
		msg_set_mode_control(dev, REG_MODE_SLEEP);
1125
		if (async_tx(idev, EP_OUT, async_tx_cb, ssm))
1126
			goto err;
1127
		break;
1128
	case TUNEVRB_FINAL_SET_MODE_SLEEP_ANS:
1129
		if (msg_check_ok(dev))
1130
			goto err;
1131
		fpi_ssm_mark_completed(ssm);
1132
		break;
1133
	default:
1134
		fp_err("Unknown state %d", ssm->cur_state);
1135
		goto err;
1136
		break;
1137
	}
1138
1139
	return;
1140
err:
1141
	fpi_ssm_mark_aborted(ssm, -EIO);
1142
}
1143
1144
static void m_tunevrb_complete(struct fpi_ssm *ssm)
1145
{
1146
	struct fp_img_dev *idev = ssm->priv;
1147
1148
	fpi_imgdev_activate_complete(idev, ssm->error != 0);
1149
	if (!ssm->error) {
1150
		fp_dbg("Tuning is done. Starting finger detection.");
1151
		m_start_fingerdetect(idev);
1152
	} else {
1153
		struct etes603_dev *dev = idev->priv;
1154
		fp_err("Error while tuning VRT");
1155
		dev->is_active = FALSE;
1156
		reset_param(dev);
1157
		fpi_imgdev_session_error(idev, -3);
1158
	}
1159
	fpi_ssm_free(ssm);
1160
}
1161
1162
/*
1163
 * This function tunes the DCoffset value and adjusts the gain value if
1164
 * required.
1165
 */
1166
static void m_tunedc_state(struct fpi_ssm *ssm)
1167
{
1168
	struct fp_img_dev *idev = ssm->priv;
1169
	struct etes603_dev *dev = idev->priv;
1170
1171
	if (dev->is_active == FALSE) {
1172
		fpi_ssm_mark_completed(ssm);
1173
		return;
1174
	}
1175
1176
	/* TODO To get better results, tuning could be done 3 times as in
1177
	 * captured traffic to make sure that the value is correct. */
1178
	/* The default gain should work but it may reach a DCOffset limit so in
1179
	 * this case we decrease the gain. */
1180
	switch (ssm->cur_state) {
1181
	case TUNEDC_INIT:
1182
		/* reg_e0 = 0x23 is sensor normal/small gain */
1183
		dev->gain = GAIN_SMALL_INIT;
1184
		dev->tunedc_min = DCOFFSET_MIN;
1185
		dev->tunedc_max = DCOFFSET_MAX;
1186
		fp_dbg("Tuning DCoffset");
1187
		fpi_ssm_next_state(ssm);
1188
		break;
1189
	case TUNEDC_SET_DCOFFSET_REQ:
1190
		/* Dichotomic search to find at which value the frame becomes
1191
		 * almost black. */
1192
		dev->dcoffset = (dev->tunedc_max + dev->tunedc_min) / 2;
1193
		fp_dbg("Testing DCoffset=0x%02X Gain=0x%02X", dev->dcoffset,
1194
			dev->gain);
1195
		msg_set_regs(dev, 2, REG_DCOFFSET, dev->dcoffset);
1196
		if (async_tx(idev, EP_OUT, async_tx_cb, ssm))
1197
			goto err;
1198
		break;
1199
	case TUNEDC_SET_DCOFFSET_ANS:
1200
		if (msg_check_ok(dev))
1201
			goto err;
1202
		fpi_ssm_next_state(ssm);
1203
		break;
1204
	case TUNEDC_GET_FRAME_REQ:
1205
		/* vrt:0x15 vrb:0x10 are constant in all tuning frames. */
1206
		msg_get_frame(dev, 0x01, dev->gain, 0x15, 0x10);
1207
		if (async_tx(idev, EP_OUT, async_tx_cb, ssm))
1208
			goto err;
1209
		break;
1210
	case TUNEDC_GET_FRAME_ANS:
1211
		if (process_frame_empty((uint8_t *)dev->ans, FRAME_WIDTH))
1212
			dev->tunedc_max = dev->dcoffset;
1213
		else
1214
			dev->tunedc_min = dev->dcoffset;
1215
		if (dev->tunedc_min + 1 < dev->tunedc_max) {
1216
			fpi_ssm_jump_to_state(ssm, TUNEDC_SET_DCOFFSET_REQ);
1217
		} else if (dev->tunedc_max < DCOFFSET_MAX) {
1218
			dev->dcoffset = dev->tunedc_max + 1;
1219
			fpi_ssm_next_state(ssm);
1220
		} else {
1221
			dev->gain--;
1222
			fpi_ssm_jump_to_state(ssm, TUNEDC_SET_DCOFFSET_REQ);
1223
		}
1224
		break;
1225
	case TUNEDC_FINAL_SET_REG2122_REQ:
1226
		fp_dbg("-> DCoffset=0x%02X Gain=0x%02X", dev->dcoffset,
1227
			dev->gain);
1228
		/* ??? how reg21 / reg22 are calculated */
1229
		msg_set_regs(dev, 4, REG_21, 0x23, REG_22, 0x21);
1230
		if (async_tx(idev, EP_OUT, async_tx_cb, ssm))
1231
			goto err;
1232
		break;
1233
	case TUNEDC_FINAL_SET_REG2122_ANS:
1234
		if (msg_check_ok(dev))
1235
			goto err;
1236
		fpi_ssm_next_state(ssm);
1237
		break;
1238
	case TUNEDC_FINAL_SET_GAIN_REQ:
1239
		msg_set_regs(dev, 2, REG_GAIN, dev->gain);
1240
		if (async_tx(idev, EP_OUT, async_tx_cb, ssm))
1241
			goto err;
1242
		break;
1243
	case TUNEDC_FINAL_SET_GAIN_ANS:
1244
		fpi_ssm_next_state(ssm);
1245
		break;
1246
	case TUNEDC_FINAL_SET_DCOFFSET_REQ:
1247
		msg_set_regs(dev, 2, REG_DCOFFSET, dev->dcoffset);
1248
		if (async_tx(idev, EP_OUT, async_tx_cb, ssm))
1249
			goto err;
1250
		break;
1251
	case TUNEDC_FINAL_SET_DCOFFSET_ANS:
1252
		/* In captured traffic, read GAIN, VRT, and VRB registers. */
1253
		if (msg_check_ok(dev))
1254
			goto err;
1255
		fpi_ssm_mark_completed(ssm);
1256
		break;
1257
	default:
1258
		fp_err("Unknown state %d", ssm->cur_state);
1259
		goto err;
1260
		break;
1261
	}
1262
1263
	return;
1264
err:
1265
	fpi_ssm_mark_aborted(ssm, -EIO);
1266
1267
}
1268
1269
static void m_tunedc_complete(struct fpi_ssm *ssm)
1270
{
1271
	struct fp_img_dev *idev = ssm->priv;
1272
	if (!ssm->error) {
1273
		struct fpi_ssm *ssm_tune;
1274
		ssm_tune = fpi_ssm_new(idev->dev, m_tunevrb_state,
1275
					TUNEVRB_NUM_STATES);
1276
		ssm_tune->priv = idev;
1277
		fpi_ssm_start(ssm_tune, m_tunevrb_complete);
1278
	} else {
1279
		struct etes603_dev *dev = idev->priv;
1280
		fp_err("Error while tuning DCOFFSET");
1281
		dev->is_active = FALSE;
1282
		reset_param(dev);
1283
		fpi_imgdev_session_error(idev, -2);
1284
	}
1285
	fpi_ssm_free(ssm);
1286
}
1287
1288
static void m_init_state(struct fpi_ssm *ssm)
1289
{
1290
	struct fp_img_dev *idev = ssm->priv;
1291
	struct etes603_dev *dev = idev->priv;
1292
1293
	if (dev->is_active == FALSE) {
1294
		fpi_ssm_mark_completed(ssm);
1295
		return;
1296
	}
1297
1298
	switch (ssm->cur_state) {
1299
	case INIT_CHECK_INFO_REQ:
1300
		msg_get_regs(dev, 4, REG_INFO0, REG_INFO1, REG_INFO2,
1301
			     REG_INFO3);
1302
		if (async_tx(idev, EP_OUT, async_tx_cb, ssm))
1303
			goto err;
1304
		break;
1305
	case INIT_CHECK_INFO_ANS:
1306
		if (msg_parse_regs(dev))
1307
			goto err;
1308
		if (check_info(dev))
1309
			goto err;
1310
		fpi_ssm_next_state(ssm);
1311
		break;
1312
	case INIT_CMD20_REQ:
1313
		msg_get_cmd20(dev);
1314
		if (async_tx(idev, EP_OUT, async_tx_cb, ssm))
1315
			goto err;
1316
		break;
1317
	case INIT_CMD20_ANS:
1318
		if (msg_check_cmd20(dev))
1319
			goto err;
1320
		fpi_ssm_next_state(ssm);
1321
		break;
1322
	case INIT_CMD25_REQ:
1323
		msg_get_cmd25(dev);
1324
		if (async_tx(idev, EP_OUT, async_tx_cb, ssm))
1325
			goto err;
1326
		break;
1327
	case INIT_CMD25_ANS:
1328
		if (msg_check_cmd25(dev))
1329
			goto err;
1330
		fpi_ssm_next_state(ssm);
1331
		break;
1332
	case INIT_SENSOR_REQ:
1333
		/* In captured traffic, those are splitted. */
1334
		msg_set_regs(dev, 18, REG_MODE_CONTROL, REG_MODE_SLEEP,
1335
			REG_50, 0x0F, REG_GAIN, 0x04, REG_VRT, 0x08,
1336
			REG_VRB, 0x0D, REG_VCO_CONTROL, REG_VCO_RT,
1337
			REG_DCOFFSET, 0x36, REG_F0, 0x00, REG_F2, 0x00);
1338
		if (async_tx(idev, EP_OUT, async_tx_cb, ssm))
1339
			goto err;
1340
		break;
1341
	case INIT_SENSOR_ANS:
1342
		if (msg_check_ok(dev))
1343
			goto err;
1344
		fpi_ssm_next_state(ssm);
1345
		break;
1346
	case INIT_ENC_REQ:
1347
		/* Initialize encryption registers without encryption. */
1348
		/* Set registers from 0x41 to 0x48 (0x8 regs) */
1349
		msg_set_regs(dev, 16, REG_ENC1, 0x12, REG_ENC2, 0x34,
1350
		     REG_ENC3, 0x56, REG_ENC4, 0x78, REG_ENC5, 0x90,
1351
		     REG_ENC6, 0xAB, REG_ENC7, 0xCD, REG_ENC8, 0xEF);
1352
		if (async_tx(idev, EP_OUT, async_tx_cb, ssm))
1353
			goto err;
1354
		break;
1355
	case INIT_ENC_ANS:
1356
		if (msg_check_ok(dev))
1357
			goto err;
1358
		fpi_ssm_next_state(ssm);
1359
		break;
1360
	case INIT_REGS_REQ:
1361
		/* Set register from 0x20 to 0x37 (0x18 regs) */
1362
		msg_set_regs(dev, 48,
1363
		     REG_20, 0x00, REG_21, 0x23, REG_22, 0x21, REG_23, 0x20,
1364
		     REG_24, 0x14, REG_25, 0x6A, REG_26, 0x00, REG_27, 0x00,
1365
		     REG_28, 0x00, REG_29, 0xC0, REG_2A, 0x50, REG_2B, 0x50,
1366
		     REG_2C, 0x4D, REG_2D, 0x03, REG_2E, 0x06, REG_2F, 0x06,
1367
		     REG_30, 0x10, REG_31, 0x02, REG_32, 0x14, REG_33, 0x34,
1368
		     REG_34, 0x01, REG_35, 0x08, REG_36, 0x03, REG_37, 0x21);
1369
		if (async_tx(idev, EP_OUT, async_tx_cb, ssm))
1370
			goto err;
1371
		break;
1372
	case INIT_REGS_ANS:
1373
		if (msg_check_ok(dev))
1374
			goto err;
1375
		fpi_ssm_mark_completed(ssm);
1376
		break;
1377
	default:
1378
		fp_err("Unknown state %d", ssm->cur_state);
1379
		goto err;
1380
		break;
1381
	}
1382
1383
	return;
1384
err:
1385
	fpi_ssm_mark_aborted(ssm, -EIO);
1386
1387
}
1388
1389
static void m_init_complete(struct fpi_ssm *ssm)
1390
{
1391
	struct fp_img_dev *idev = ssm->priv;
1392
	if (!ssm->error) {
1393
		struct fpi_ssm *ssm_tune;
1394
		ssm_tune = fpi_ssm_new(idev->dev, m_tunedc_state,
1395
					TUNEDC_NUM_STATES);
1396
		ssm_tune->priv = idev;
1397
		fpi_ssm_start(ssm_tune, m_tunedc_complete);
1398
	} else {
1399
		struct etes603_dev *dev = idev->priv;
1400
		fp_err("Error initializing the device");
1401
		dev->is_active = FALSE;
1402
		reset_param(dev);
1403
		fpi_imgdev_session_error(idev, -1);
1404
	}
1405
	fpi_ssm_free(ssm);
1406
}
1407
1408
static int dev_activate(struct fp_img_dev *idev, enum fp_imgdev_state state)
1409
{
1410
	struct etes603_dev *dev = idev->priv;
1411
	struct fpi_ssm *ssm;
1412
1413
	assert(dev);
1414
1415
	if (state != IMGDEV_STATE_AWAIT_FINGER_ON) {
1416
		fp_err("The driver is in an unexpected state: %d.", state);
1417
		fpi_imgdev_activate_complete(idev, 1);
1418
		return -1;
1419
	}
1420
1421
	/* Reset info and data */
1422
	dev->is_active = TRUE;
1423
1424
	if (dev->dcoffset == 0) {
1425
		fp_dbg("Tuning device...");
1426
		ssm = fpi_ssm_new(idev->dev, m_init_state, INIT_NUM_STATES);
1427
		ssm->priv = idev;
1428
		fpi_ssm_start(ssm, m_init_complete);
1429
	} else {
1430
		fp_dbg("Using previous tuning (DCOFFSET=0x%02X,VRT=0x%02X,"
1431
			"VRB=0x%02X,GAIN=0x%02X).", dev->dcoffset, dev->vrt,
1432
			dev->vrb, dev->gain);
1433
		fpi_imgdev_activate_complete(idev, 0);
1434
		ssm = fpi_ssm_new(idev->dev, m_finger_state, FGR_NUM_STATES);
1435
		ssm->priv = idev;
1436
		fpi_ssm_start(ssm, m_finger_complete);
1437
	}
1438
	return 0;
1439
}
1440
1441
static void dev_deactivate(struct fp_img_dev *idev)
1442
{
1443
	struct etes603_dev *dev = idev->priv;
1444
1445
	fp_dbg("deactivating");
1446
1447
	/* this can be called even if still activated. */
1448
	if (dev->is_active == TRUE) {
1449
		dev->is_active = FALSE;
1450
		m_exit_start(idev);
1451
	}
1452
}
1453
1454
static int dev_open(struct fp_img_dev *idev, unsigned long driver_data)
1455
{
1456
	int ret;
1457
	struct etes603_dev *dev;
1458
1459
	dev = g_malloc0(sizeof(struct etes603_dev));
1460
	idev->priv = dev;
1461
1462
	dev->req = g_malloc(sizeof(struct egis_msg));
1463
	dev->ans = g_malloc(FE_SIZE);
1464
	dev->fp = g_malloc(FE_SIZE * 4);
1465
1466
	ret = libusb_claim_interface(idev->udev, 0);
1467
	if (ret != LIBUSB_SUCCESS) {
1468
		fp_err("libusb_claim_interface failed on interface 0 "
1469
		       "(err=%d)", ret);
1470
		return ret;
1471
	}
1472
1473
	fpi_imgdev_open_complete(idev, 0);
1474
	return 0;
1475
}
1476
1477
static void dev_close(struct fp_img_dev *idev)
1478
{
1479
	struct etes603_dev *dev = idev->priv;
1480
1481
	g_free(dev->req);
1482
	g_free(dev->ans);
1483
	g_free(dev->fp);
1484
	g_free(dev);
1485
1486
	libusb_release_interface(idev->udev, 0);
1487
	fpi_imgdev_close_complete(idev);
1488
}
1489
1490
static const struct usb_id id_table[] = {
1491
	/* EgisTec (aka Lightuning) ES603 */
1492
	{ .vendor = 0x1c7a, .product = 0x0603},
1493
	{ 0, 0, 0, },
1494
};
1495
1496
struct fp_img_driver etes603_driver = {
1497
	.driver = {
1498
		.id = ETES603_ID,
1499
		.name = FP_COMPONENT,
1500
		.full_name = "EgisTec ES603",
1501
		.id_table = id_table,
1502
		.scan_type = FP_SCAN_TYPE_SWIPE,
1503
	},
1504
	.flags = 0,
1505
	.img_height = -1,
1506
	.img_width = 256,
1507
1508
	.open = dev_open,
1509
	.close = dev_close,
1510
	.activate = dev_activate,
1511
	.deactivate = dev_deactivate,
1512
};
1513
(-)a/libfprint/drivers/upeke2.c (-9 / +8 lines)
Lines 48-54 Link Here
48
48
49
enum {
49
enum {
50
        UPEKE2_2016,
50
        UPEKE2_2016,
51
        UPEKE2_2020,
52
};
51
};
53
52
54
struct upeke2_dev {
53
struct upeke2_dev {
Lines 856-864 static int discover(struct libusb_device_descriptor *dsc, uint32_t *devtype) Link Here
856
	if (dsc->idProduct == 0x2016 && dsc->bcdDevice == 2)
855
	if (dsc->idProduct == 0x2016 && dsc->bcdDevice == 2)
857
		return 1;
856
		return 1;
858
857
859
	if (dsc->idProduct == 0x2020 && dsc->bcdDevice == 1)
860
		return 1;
861
862
	return 0;
858
	return 0;
863
}
859
}
864
860
Lines 1076-1081 static void e_handle_resp02(struct fp_dev *dev, unsigned char *data, Link Here
1076
	size_t data_len)
1072
	size_t data_len)
1077
{
1073
{
1078
	struct fp_print_data *fdata = NULL;
1074
	struct fp_print_data *fdata = NULL;
1075
	struct fp_print_data_item *item = NULL;
1079
	int result = -EPROTO;
1076
	int result = -EPROTO;
1080
1077
1081
	if (data_len < sizeof(scan_comp)) {
1078
	if (data_len < sizeof(scan_comp)) {
Lines 1084-1092 static void e_handle_resp02(struct fp_dev *dev, unsigned char *data, Link Here
1084
		fp_err("unrecognised data prefix %x %x %x %x %x",
1081
		fp_err("unrecognised data prefix %x %x %x %x %x",
1085
			data[0], data[1], data[2], data[3], data[4]);
1082
			data[0], data[1], data[2], data[3], data[4]);
1086
	} else {
1083
	} else {
1087
		fdata = fpi_print_data_new(dev, data_len - sizeof(scan_comp));
1084
		fdata = fpi_print_data_new(dev);
1088
		memcpy(fdata->data, data + sizeof(scan_comp),
1085
		item = fpi_print_data_item_new(data_len - sizeof(scan_comp));
1086
		memcpy(item->data, data + sizeof(scan_comp),
1089
			data_len - sizeof(scan_comp));
1087
			data_len - sizeof(scan_comp));
1088
		fdata->prints = g_slist_prepend(fdata->prints, item);
1090
1089
1091
		result = FP_ENROLL_COMPLETE;
1090
		result = FP_ENROLL_COMPLETE;
1092
	}
1091
	}
Lines 1248-1259 static void verify_start_sm_run_state(struct fpi_ssm *ssm) Link Here
1248
		break;
1247
		break;
1249
	case VERIFY_INIT: ;
1248
	case VERIFY_INIT: ;
1250
		struct fp_print_data *print = dev->verify_data;
1249
		struct fp_print_data *print = dev->verify_data;
1251
		size_t data_len = sizeof(verify_hdr) + print->length;
1250
		struct fp_print_data_item *item = print->prints->data;
1251
		size_t data_len = sizeof(verify_hdr) + item->length;
1252
		unsigned char *data = g_malloc(data_len);
1252
		unsigned char *data = g_malloc(data_len);
1253
		struct libusb_transfer *transfer;
1253
		struct libusb_transfer *transfer;
1254
1254
1255
		memcpy(data, verify_hdr, sizeof(verify_hdr));
1255
		memcpy(data, verify_hdr, sizeof(verify_hdr));
1256
		memcpy(data + sizeof(verify_hdr), print->data, print->length);
1256
		memcpy(data + sizeof(verify_hdr), item->data, item->length);
1257
		transfer = alloc_send_cmd28_transfer(dev, 0x03, data, data_len,
1257
		transfer = alloc_send_cmd28_transfer(dev, 0x03, data, data_len,
1258
			verify_init_2803_cb, ssm);
1258
			verify_init_2803_cb, ssm);
1259
		g_free(data);
1259
		g_free(data);
Lines 1461-1467 static int verify_stop(struct fp_dev *dev, gboolean iterating) Link Here
1461
1461
1462
static const struct usb_id id_table[] = {
1462
static const struct usb_id id_table[] = {
1463
	{ .vendor = 0x147e, .product = 0x2016, .driver_data = UPEKE2_2016 },
1463
	{ .vendor = 0x147e, .product = 0x2016, .driver_data = UPEKE2_2016 },
1464
	{ .vendor = 0x147e, .product = 0x2020, .driver_data = UPEKE2_2020 },
1465
	{ 0, 0, 0, }, /* terminating entry */
1464
	{ 0, 0, 0, }, /* terminating entry */
1466
};
1465
};
1467
1466
(-)a/libfprint/drivers/upektc_img.c (+659 lines)
Line 0 Link Here
1
/*
2
 * UPEK TouchChip driver for libfprint
3
 * Copyright (C) 2013 Vasily Khoruzhick <anarsoul@gmail.com>
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
#define FP_COMPONENT "upekts_img"
21
22
#include <errno.h>
23
#include <string.h>
24
25
#include <libusb.h>
26
27
#include <aeslib.h>
28
#include <fp_internal.h>
29
30
#include "upektc_img.h"
31
#include "driver_ids.h"
32
33
static void start_capture(struct fp_img_dev *dev);
34
static void start_deactivation(struct fp_img_dev *dev);
35
36
#define EP_IN			(1 | LIBUSB_ENDPOINT_IN)
37
#define EP_OUT			(2 | LIBUSB_ENDPOINT_OUT)
38
#define CTRL_TIMEOUT		4000
39
#define BULK_TIMEOUT		4000
40
41
#define IMAGE_WIDTH		144
42
#define IMAGE_HEIGHT		384
43
#define IMAGE_SIZE		(IMAGE_WIDTH * IMAGE_HEIGHT)
44
45
#define MAX_CMD_SIZE		64
46
#define MAX_RESPONSE_SIZE	2052
47
#define SHORT_RESPONSE_SIZE	64
48
49
struct upekts_img_dev {
50
	unsigned char cmd[MAX_CMD_SIZE];
51
	unsigned char response[MAX_RESPONSE_SIZE];
52
	unsigned char image_bits[IMAGE_SIZE * 2];
53
	unsigned char seq;
54
	size_t image_size;
55
	size_t response_rest;
56
	gboolean deactivating;
57
};
58
59
/****** HELPERS ******/
60
61
static const uint16_t crc_table[256] = {
62
	0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
63
	0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
64
	0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
65
	0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
66
	0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
67
	0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
68
	0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
69
	0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
70
	0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
71
	0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
72
	0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
73
	0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
74
	0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
75
	0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
76
	0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
77
	0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
78
	0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
79
	0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
80
	0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
81
	0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
82
	0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
83
	0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
84
	0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
85
	0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
86
	0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
87
	0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
88
	0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
89
	0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
90
	0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
91
	0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
92
	0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
93
	0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
94
};
95
96
static uint16_t udf_crc(unsigned char *buffer, size_t size)
97
{
98
	uint16_t crc = 0;
99
	while (size--)
100
	crc = (uint16_t) ((crc << 8) ^
101
			crc_table[((crc >> 8) & 0x00ff) ^ *buffer++]);
102
	return crc;
103
}
104
105
static void upektc_img_cmd_fix_seq(unsigned char *cmd_buf, unsigned char seq)
106
{
107
	uint8_t byte;
108
109
	byte = cmd_buf[5];
110
	byte &= 0x0f;
111
	byte |= (seq << 4);
112
	cmd_buf[5] = byte;
113
}
114
115
static void upektc_img_cmd_update_crc(unsigned char *cmd_buf, size_t size)
116
{
117
	/* CRC does not cover Ciao prefix (4 bytes) and CRC location (2 bytes) */
118
	uint16_t crc = udf_crc(cmd_buf + 4, size - 6);
119
120
	cmd_buf[size - 2] = (crc & 0x00ff);
121
	cmd_buf[size - 1] = (crc & 0xff00) >> 8;
122
}
123
124
static void upektc_img_submit_req(struct fpi_ssm *ssm,
125
	const unsigned char *buf, size_t buf_size, unsigned char seq,
126
	libusb_transfer_cb_fn cb)
127
{
128
	struct fp_img_dev *dev = ssm->priv;
129
	struct upekts_img_dev *upekdev = dev->priv;
130
	struct libusb_transfer *transfer = libusb_alloc_transfer(0);
131
	int r;
132
133
	BUG_ON(buf_size > MAX_CMD_SIZE);
134
135
	if (!transfer) {
136
		fpi_ssm_mark_aborted(ssm, -ENOMEM);
137
		return;
138
	}
139
140
	transfer->flags |= LIBUSB_TRANSFER_FREE_TRANSFER;
141
142
	memcpy(upekdev->cmd, buf, buf_size);
143
	upektc_img_cmd_fix_seq(upekdev->cmd, seq);
144
	upektc_img_cmd_update_crc(upekdev->cmd, buf_size);
145
146
	libusb_fill_bulk_transfer(transfer, dev->udev, EP_OUT, upekdev->cmd, buf_size,
147
		cb, ssm, BULK_TIMEOUT);
148
149
	r = libusb_submit_transfer(transfer);
150
	if (r < 0) {
151
		libusb_free_transfer(transfer);
152
		fpi_ssm_mark_aborted(ssm, r);
153
	}
154
}
155
156
static void upektc_img_read_data(struct fpi_ssm *ssm, size_t buf_size, size_t buf_offset, libusb_transfer_cb_fn cb)
157
{
158
	struct libusb_transfer *transfer = libusb_alloc_transfer(0);
159
	struct fp_img_dev *dev = ssm->priv;
160
	struct upekts_img_dev *upekdev = dev->priv;
161
	int r;
162
163
	if (!transfer) {
164
		fpi_ssm_mark_aborted(ssm, -ENOMEM);
165
		return;
166
	}
167
168
	BUG_ON(buf_size > MAX_RESPONSE_SIZE);
169
170
	transfer->flags |= LIBUSB_TRANSFER_FREE_TRANSFER;
171
172
	libusb_fill_bulk_transfer(transfer, dev->udev, EP_IN, upekdev->response + buf_offset, buf_size,
173
		cb, ssm, BULK_TIMEOUT);
174
175
	r = libusb_submit_transfer(transfer);
176
	if (r < 0) {
177
		libusb_free_transfer(transfer);
178
		fpi_ssm_mark_aborted(ssm, r);
179
	}
180
}
181
182
/****** CAPTURE ******/
183
184
enum capture_states {
185
	CAPTURE_INIT_CAPTURE,
186
	CAPTURE_READ_DATA,
187
	CAPTURE_ACK_00_28,
188
	CAPTURE_ACK_08,
189
	CAPTURE_ACK_FRAME,
190
	CAPTURE_NUM_STATES,
191
};
192
193
static void capture_reqs_cb(struct libusb_transfer *transfer)
194
{
195
	struct fpi_ssm *ssm = transfer->user_data;
196
197
	if ((transfer->status == LIBUSB_TRANSFER_COMPLETED) &&
198
		(transfer->length == transfer->actual_length)) {
199
		fpi_ssm_jump_to_state(ssm, CAPTURE_READ_DATA);
200
	} else {
201
		fpi_ssm_mark_aborted(ssm, -EIO);
202
	}
203
}
204
205
static int upektc_img_process_image_frame(unsigned char *image_buf, unsigned char *cmd_res)
206
{
207
	int offset = 8;
208
	int len = ((cmd_res[5] & 0x0f) << 8) | (cmd_res[6]);
209
210
	len -= 1;
211
	if (cmd_res[7] == 0x2c) {
212
		len -= 10;
213
		offset += 10;
214
	}
215
	if (cmd_res[7] == 0x20) {
216
		len -= 4;
217
	}
218
	memcpy(image_buf, cmd_res + offset, len);
219
220
	return len;
221
}
222
223
static void capture_read_data_cb(struct libusb_transfer *transfer)
224
{
225
	struct fpi_ssm *ssm = transfer->user_data;
226
	struct fp_img_dev *dev = ssm->priv;
227
	struct upekts_img_dev *upekdev = dev->priv;
228
	unsigned char *data = upekdev->response;
229
	struct fp_img *img;
230
	size_t response_size;
231
232
	if (transfer->status != LIBUSB_TRANSFER_COMPLETED) {
233
		fp_dbg("request is not completed, %d", transfer->status);
234
		fpi_ssm_mark_aborted(ssm, -EIO);
235
		return;
236
	}
237
238
	if (upekdev->deactivating) {
239
		fp_dbg("Deactivate requested\n");
240
		fpi_ssm_mark_completed(ssm);
241
		return;
242
	}
243
244
	fp_dbg("request completed, len: %.4x", transfer->actual_length);
245
	if (transfer->actual_length == 0) {
246
		fpi_ssm_jump_to_state(ssm, CAPTURE_READ_DATA);
247
		return;
248
	}
249
250
	if (!upekdev->response_rest) {
251
		response_size = ((data[5] & 0x0f) << 8) + data[6];
252
		response_size += 9; /* 7 bytes for header, 2 for CRC */
253
		if (response_size > transfer->actual_length) {
254
			fp_dbg("response_size is %d, actual_length is %d\n",
255
				response_size, transfer->actual_length);
256
			fp_dbg("Waiting for rest of transfer");
257
			BUG_ON(upekdev->response_rest);
258
			upekdev->response_rest = response_size - transfer->actual_length;
259
			fpi_ssm_jump_to_state(ssm, CAPTURE_READ_DATA);
260
			return;
261
		}
262
	}
263
	upekdev->response_rest = 0;
264
265
	switch (data[4]) {
266
	case 0x00:
267
		switch (data[7]) {
268
			/* No finger */
269
			case 0x28:
270
				fpi_ssm_jump_to_state(ssm, CAPTURE_ACK_00_28);
271
				break;
272
			/* Image frame with additional info */
273
			case 0x2c:
274
				fpi_imgdev_report_finger_status(dev, TRUE);
275
			/* Plain image frame */
276
			case 0x24:
277
				upekdev->image_size +=
278
					upektc_img_process_image_frame(upekdev->image_bits + upekdev->image_size,
279
						data);
280
				fpi_ssm_jump_to_state(ssm, CAPTURE_ACK_FRAME);
281
				break;
282
			/* Last image frame */
283
			case 0x20:
284
				upekdev->image_size +=
285
					upektc_img_process_image_frame(upekdev->image_bits + upekdev->image_size,
286
						data);
287
				BUG_ON(upekdev->image_size != IMAGE_SIZE);
288
				fp_dbg("Image size is %d\n", upekdev->image_size);
289
				img = fpi_img_new(IMAGE_SIZE);
290
				memcpy(img->data, upekdev->image_bits, IMAGE_SIZE);
291
				fpi_imgdev_image_captured(dev, img);
292
				fpi_imgdev_report_finger_status(dev, FALSE);
293
				fpi_ssm_mark_completed(ssm);
294
				break;
295
			default:
296
				fp_err("Uknown response!\n");
297
				fpi_ssm_mark_aborted(ssm, -EIO);
298
				break;
299
		}
300
		break;
301
	case 0x08:
302
		fpi_ssm_jump_to_state(ssm, CAPTURE_ACK_08);
303
		break;
304
	default:
305
		fp_err("Not handled response!\n");
306
		fpi_ssm_mark_aborted(ssm, -EIO);
307
	}
308
}
309
310
static void capture_run_state(struct fpi_ssm *ssm)
311
{
312
	struct fp_img_dev *dev = ssm->priv;
313
	struct upekts_img_dev *upekdev = dev->priv;
314
315
	switch (ssm->cur_state) {
316
	case CAPTURE_INIT_CAPTURE:
317
		upektc_img_submit_req(ssm, upek2020_init_capture, sizeof(upek2020_init_capture),
318
			upekdev->seq, capture_reqs_cb);
319
			upekdev->seq++;
320
		break;
321
	case CAPTURE_READ_DATA:
322
		if (!upekdev->response_rest)
323
			upektc_img_read_data(ssm, SHORT_RESPONSE_SIZE, 0, capture_read_data_cb);
324
		else
325
			upektc_img_read_data(ssm, MAX_RESPONSE_SIZE - SHORT_RESPONSE_SIZE,
326
			SHORT_RESPONSE_SIZE, capture_read_data_cb);
327
		break;
328
	case CAPTURE_ACK_00_28:
329
		upektc_img_submit_req(ssm, upek2020_ack_00_28, sizeof(upek2020_ack_00_28),
330
			upekdev->seq, capture_reqs_cb);
331
			upekdev->seq++;
332
		break;
333
	case CAPTURE_ACK_08:
334
		upektc_img_submit_req(ssm, upek2020_ack_08, sizeof(upek2020_ack_08),
335
			0, capture_reqs_cb);
336
		break;
337
	case CAPTURE_ACK_FRAME:
338
		upektc_img_submit_req(ssm, upek2020_ack_frame, sizeof(upek2020_ack_frame),
339
			upekdev->seq, capture_reqs_cb);
340
			upekdev->seq++;
341
		break;
342
	};
343
}
344
345
static void capture_sm_complete(struct fpi_ssm *ssm)
346
{
347
	struct fp_img_dev *dev = ssm->priv;
348
	struct upekts_img_dev *upekdev = dev->priv;
349
	int err = ssm->error;
350
351
	fp_dbg("Capture completed, %d", err);
352
	fpi_ssm_free(ssm);
353
354
	if (upekdev->deactivating)
355
		start_deactivation(dev);
356
	else if (err)
357
		fpi_imgdev_session_error(dev, err);
358
	else
359
		start_capture(dev);
360
}
361
362
static void start_capture(struct fp_img_dev *dev)
363
{
364
	struct upekts_img_dev *upekdev = dev->priv;
365
	struct fpi_ssm *ssm;
366
367
	upekdev->image_size = 0;
368
369
	ssm = fpi_ssm_new(dev->dev, capture_run_state, CAPTURE_NUM_STATES);
370
	ssm->priv = dev;
371
	fpi_ssm_start(ssm, capture_sm_complete);
372
}
373
374
/****** INITIALIZATION/DEINITIALIZATION ******/
375
376
enum deactivate_states {
377
	DEACTIVATE_DEINIT,
378
	DEACTIVATE_READ_DEINIT_DATA,
379
	DEACTIVATE_NUM_STATES,
380
};
381
382
static void deactivate_reqs_cb(struct libusb_transfer *transfer)
383
{
384
	struct fpi_ssm *ssm = transfer->user_data;
385
386
	if ((transfer->status == LIBUSB_TRANSFER_COMPLETED) &&
387
		(transfer->length == transfer->actual_length)) {
388
		fpi_ssm_jump_to_state(ssm, CAPTURE_READ_DATA);
389
	} else {
390
		fpi_ssm_mark_aborted(ssm, -EIO);
391
	}
392
}
393
394
/* TODO: process response properly */
395
static void deactivate_read_data_cb(struct libusb_transfer *transfer)
396
{
397
	struct fpi_ssm *ssm = transfer->user_data;
398
399
	if (transfer->status == LIBUSB_TRANSFER_COMPLETED) {
400
		fpi_ssm_mark_completed(ssm);
401
	} else {
402
		fpi_ssm_mark_aborted(ssm, -EIO);
403
	}
404
}
405
406
static void deactivate_run_state(struct fpi_ssm *ssm)
407
{
408
	struct fp_img_dev *dev = ssm->priv;
409
	struct upekts_img_dev *upekdev = dev->priv;
410
411
	switch (ssm->cur_state) {
412
	case DEACTIVATE_DEINIT:
413
		upektc_img_submit_req(ssm, upek2020_deinit, sizeof(upek2020_deinit),
414
			upekdev->seq, deactivate_reqs_cb);
415
		upekdev->seq++;
416
		break;
417
	case DEACTIVATE_READ_DEINIT_DATA:
418
		upektc_img_read_data(ssm, SHORT_RESPONSE_SIZE, 0, deactivate_read_data_cb);
419
		break;
420
	};
421
}
422
423
static void deactivate_sm_complete(struct fpi_ssm *ssm)
424
{
425
	struct fp_img_dev *dev = ssm->priv;
426
	struct upekts_img_dev *upekdev = dev->priv;
427
	int err = ssm->error;
428
429
	fp_dbg("Deactivate completed");
430
	fpi_ssm_free(ssm);
431
432
	if (err) {
433
		fpi_imgdev_session_error(dev, err);
434
		return;
435
	}
436
437
	upekdev->deactivating = FALSE;
438
	fpi_imgdev_deactivate_complete(dev);
439
}
440
441
static void start_deactivation(struct fp_img_dev *dev)
442
{
443
	struct upekts_img_dev *upekdev = dev->priv;
444
	struct fpi_ssm *ssm;
445
446
	upekdev->image_size = 0;
447
448
	ssm = fpi_ssm_new(dev->dev, deactivate_run_state, DEACTIVATE_NUM_STATES);
449
	ssm->priv = dev;
450
	fpi_ssm_start(ssm, deactivate_sm_complete);
451
}
452
453
enum activate_states {
454
	ACTIVATE_CONTROL_REQ_1,
455
	ACTIVATE_READ_CTRL_RESP_1,
456
	ACTIVATE_INIT_1,
457
	ACTIVATE_READ_INIT_1_RESP,
458
	ACTIVATE_INIT_2,
459
	ACTIVATE_READ_INIT_2_RESP,
460
	ACTIVATE_CONTROL_REQ_2,
461
	ACTIVATE_READ_CTRL_RESP_2,
462
	ACTIVATE_INIT_3,
463
	ACTIVATE_READ_INIT_3_RESP,
464
	ACTIVATE_INIT_4,
465
	ACTIVATE_READ_INIT_4_RESP,
466
	ACTIVATE_NUM_STATES,
467
};
468
469
static void init_reqs_ctrl_cb(struct libusb_transfer *transfer)
470
{
471
	struct fpi_ssm *ssm = transfer->user_data;
472
473
	if (transfer->status == LIBUSB_TRANSFER_COMPLETED) {
474
		fpi_ssm_next_state(ssm);
475
	} else {
476
		fpi_ssm_mark_aborted(ssm, -EIO);
477
	}
478
}
479
480
static void init_reqs_cb(struct libusb_transfer *transfer)
481
{
482
	struct fpi_ssm *ssm = transfer->user_data;
483
484
	if ((transfer->status == LIBUSB_TRANSFER_COMPLETED) &&
485
		(transfer->length == transfer->actual_length)) {
486
		fpi_ssm_next_state(ssm);
487
	} else {
488
		fpi_ssm_mark_aborted(ssm, -EIO);
489
	}
490
}
491
492
/* TODO: process response properly */
493
static void init_read_data_cb(struct libusb_transfer *transfer)
494
{
495
	struct fpi_ssm *ssm = transfer->user_data;
496
497
	if (transfer->status == LIBUSB_TRANSFER_COMPLETED) {
498
		fpi_ssm_next_state(ssm);
499
	} else {
500
		fpi_ssm_mark_aborted(ssm, -EIO);
501
	}
502
}
503
504
static void activate_run_state(struct fpi_ssm *ssm)
505
{
506
	struct libusb_transfer *transfer;
507
	struct fp_img_dev *dev = ssm->priv;
508
	struct upekts_img_dev *upekdev = dev->priv;
509
	int r;
510
511
	switch (ssm->cur_state) {
512
	case ACTIVATE_CONTROL_REQ_1:
513
	case ACTIVATE_CONTROL_REQ_2:
514
	{
515
		unsigned char *data;
516
517
		transfer = libusb_alloc_transfer(0);
518
		if (!transfer) {
519
			fpi_ssm_mark_aborted(ssm, -ENOMEM);
520
			break;
521
		}
522
		transfer->flags |= LIBUSB_TRANSFER_FREE_BUFFER |
523
			LIBUSB_TRANSFER_FREE_TRANSFER;
524
525
		data = g_malloc0(LIBUSB_CONTROL_SETUP_SIZE + 1);
526
		libusb_fill_control_setup(data,
527
			LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE, 0x0c, 0x100, 0x0400, 1);
528
		libusb_fill_control_transfer(transfer, ssm->dev->udev, data,
529
			init_reqs_ctrl_cb, ssm, CTRL_TIMEOUT);
530
		r = libusb_submit_transfer(transfer);
531
		if (r < 0) {
532
			g_free(data);
533
			libusb_free_transfer(transfer);
534
			fpi_ssm_mark_aborted(ssm, r);
535
		}
536
	}
537
	break;
538
	case ACTIVATE_INIT_1:
539
		upektc_img_submit_req(ssm, upek2020_init_1, sizeof(upek2020_init_1),
540
			0, init_reqs_cb);
541
	break;
542
	case ACTIVATE_INIT_2:
543
		upektc_img_submit_req(ssm, upek2020_init_2, sizeof(upek2020_init_2),
544
			0, init_reqs_cb);
545
	break;
546
	case ACTIVATE_INIT_3:
547
		upektc_img_submit_req(ssm, upek2020_init_3, sizeof(upek2020_init_3),
548
			0, init_reqs_cb);
549
	break;
550
	case ACTIVATE_INIT_4:
551
		upektc_img_submit_req(ssm, upek2020_init_4, sizeof(upek2020_init_4),
552
			upekdev->seq, init_reqs_cb);
553
		/* Seq should be updated after 4th init */
554
		upekdev->seq++;
555
	break;
556
	case ACTIVATE_READ_CTRL_RESP_1:
557
	case ACTIVATE_READ_CTRL_RESP_2:
558
	case ACTIVATE_READ_INIT_1_RESP:
559
	case ACTIVATE_READ_INIT_2_RESP:
560
	case ACTIVATE_READ_INIT_3_RESP:
561
	case ACTIVATE_READ_INIT_4_RESP:
562
		upektc_img_read_data(ssm, SHORT_RESPONSE_SIZE, 0, init_read_data_cb);
563
	break;
564
	}
565
}
566
567
static void activate_sm_complete(struct fpi_ssm *ssm)
568
{
569
	struct fp_img_dev *dev = ssm->priv;
570
	int err = ssm->error;
571
572
	fpi_ssm_free(ssm);
573
	fp_dbg("%s status %d", __func__, err);
574
	fpi_imgdev_activate_complete(dev, err);
575
576
	if (!err)
577
		start_capture(dev);
578
}
579
580
static int dev_activate(struct fp_img_dev *dev, enum fp_imgdev_state state)
581
{
582
	struct upekts_img_dev *upekdev = dev->priv;
583
	struct fpi_ssm *ssm = fpi_ssm_new(dev->dev, activate_run_state,
584
		ACTIVATE_NUM_STATES);
585
	ssm->priv = dev;
586
	upekdev->seq = 0;
587
	fpi_ssm_start(ssm, activate_sm_complete);
588
	return 0;
589
}
590
591
static void dev_deactivate(struct fp_img_dev *dev)
592
{
593
	struct upekts_img_dev *upekdev = dev->priv;
594
595
	upekdev->deactivating = TRUE;
596
}
597
598
static int dev_init(struct fp_img_dev *dev, unsigned long driver_data)
599
{
600
	/* TODO check that device has endpoints we're using */
601
	int r;
602
603
	r = libusb_claim_interface(dev->udev, 0);
604
	if (r < 0) {
605
		fp_err("could not claim interface 0");
606
		return r;
607
	}
608
609
	dev->priv = g_malloc0(sizeof(struct upekts_img_dev));
610
	fpi_imgdev_open_complete(dev, 0);
611
	return 0;
612
}
613
614
static void dev_deinit(struct fp_img_dev *dev)
615
{
616
	g_free(dev->priv);
617
	libusb_release_interface(dev->udev, 0);
618
	fpi_imgdev_close_complete(dev);
619
}
620
621
static int discover(struct libusb_device_descriptor *dsc, uint32_t *devtype)
622
{
623
	if (dsc->idProduct == 0x2020 && dsc->bcdDevice == 1)
624
		return 1;
625
#ifndef ENABLE_UPEKE2
626
	if (dsc->idProduct == 0x2016 && dsc->bcdDevice == 2)
627
		return 1;
628
#endif
629
630
	return 0;
631
}
632
633
static const struct usb_id id_table[] = {
634
#ifndef ENABLE_UPEKE2
635
	{ .vendor = 0x147e, .product = 0x2016 },
636
#endif
637
	{ .vendor = 0x147e, .product = 0x2020 },
638
	{ 0, 0, 0, },
639
};
640
641
struct fp_img_driver upektc_img_driver = {
642
	.driver = {
643
		.id = UPEKTC_IMG_ID,
644
		.name = FP_COMPONENT,
645
		.full_name = "Upek TouchChip Fingerprint Coprocessor",
646
		.id_table = id_table,
647
		.scan_type = FP_SCAN_TYPE_SWIPE,
648
		.discover = discover,
649
	},
650
	.flags = 0,
651
	.img_height = IMAGE_HEIGHT,
652
	.img_width = IMAGE_WIDTH,
653
	.bz3_threshold = 70,
654
655
	.open = dev_init,
656
	.close = dev_deinit,
657
	.activate = dev_activate,
658
	.deactivate = dev_deactivate,
659
};
(-)a/libfprint/drivers/upektc_img.h (+144 lines)
Line 0 Link Here
1
/*
2
 * Upek TouchChip Fingerprint Coprocessor definitions
3
 * Copyright (c) 2013 Vasily Khoruzhick <anarsoul@gmail.com>
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
#ifndef __UPEKTC_IMG_H
21
#define __UPEKTC_IMG_H
22
23
static const unsigned char upek2020_init_1[] = {
24
'C', 'i', 'a', 'o',
25
0x04,
26
0x00, 0x0d,
27
0x01, 0x00, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
28
0x01, 0x00, 0x00, 0x00,
29
0xda, 0xc1
30
};
31
32
static const unsigned char upek2020_init_2[] = {
33
0x43, 0x69, 0x61, 0x6f,
34
0x07,
35
0x00, 0x01,
36
0x01,
37
0x3d, 0x72
38
};
39
40
static const unsigned char upek2020_init_3[] = {
41
'C', 'i', 'a', 'o',
42
0x04,
43
0x00, 0x0d,
44
0x01, 0x00, 0xbc, 0x02, 0x00, 0x00, 0x00, 0x00, 0x01,
45
0x01, 0x00, 0x00, 0x00,
46
0x55, 0x2f
47
};
48
49
static const unsigned char upek2020_init_4[] = {
50
'C', 'i', 'a', 'o',
51
0x00,
52
0x00, 0x07,
53
0x28, 0x04, 0x00, 0x00, 0x00, 0x06, 0x04,
54
0xc0, 0xd6
55
};
56
57
static const unsigned char upek2020_deinit[] = {
58
'C', 'i', 'a', 'o',
59
0x07,
60
0x00, 0x01,
61
0x01,
62
0x3d,
63
0x72
64
};
65
66
static const unsigned char upek2020_init_capture[] = {
67
'C', 'i', 'a', 'o',
68
0x00,
69
0x00, 0x0e, /* Seq = 7, len = 0x00e */
70
0x28, /* CMD = 0x28 */
71
0x0b, 0x00,  /* Inner len = 0x000b */
72
0x00, 0x00,
73
0x0e, /* SUBCMD = 0x0e */
74
0x02,
75
0xfe, 0xff, 0xff, 0xff, /* timeout = -2 = 0xfffffffe = infinite time */
76
0x02,
77
0x00, /* Wait for acceptable finger */
78
0x02,
79
0x14, 0x9a /* CRC */
80
};
81
82
#if 0
83
static const unsigned char finger_status[] = {
84
'C', 'i', 'a', 'o',
85
0x00,
86
0x70, 0x14, /* Seq = 7, len = 0x014 */
87
0x28, /* CMD = 0x28 */
88
0x11, 0x00, /* Inner len = 0x0011 */
89
0x00, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, 0x00,
90
0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
91
0x00,
92
0x26, 0x03, /* CRC */
93
0x00, 0x00, 0x00, /* Rest is garbage */
94
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
95
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
96
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
97
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
98
};
99
#endif
100
101
static const unsigned char upek2020_ack_00_28[] = {
102
'C', 'i', 'a', 'o',
103
0x00,
104
0x80, 0x08, /* Seq = 8, len = 0x008 */
105
0x28, /* CMD = 0x28 */
106
0x05, 0x00, /* Inner len = 0x0005 */
107
0x00, 0x00, 0x00, 0x30, 0x01,
108
0x6a, 0xc4 /* CRC */
109
};
110
111
#if 0
112
/* No seq should be tracked here */
113
static const unsigned char got_finger[] = {
114
'C', 'i', 'a', 'o',
115
0x08,
116
0x00, 0x00, /* Seq = 0, len = 0x000 */
117
0xa1, 0xa9, /* CRC */
118
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Rest is garbage */
119
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
120
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
121
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
122
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
123
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
124
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
125
};
126
#endif
127
128
/* No seq should be put in there */
129
static const unsigned char upek2020_ack_08[] = {
130
'C', 'i', 'a', 'o',
131
0x09,
132
0x00, 0x00, /* Seq = 0, len = 0x0 */
133
0x91, 0x9e /* CRC */
134
};
135
136
static const unsigned char upek2020_ack_frame[] = {
137
'C', 'i', 'a', 'o',
138
0x00,
139
0x50, 0x01, /* Seq = 5, len = 0x001 */
140
0x30,
141
0xac, 0x5b /* CRC */
142
};
143
144
#endif
(-)a/libfprint/drivers/upekts.c (-4 / +8 lines)
Lines 1077-1082 static void e_handle_resp02(struct fp_dev *dev, unsigned char *data, Link Here
1077
	size_t data_len)
1077
	size_t data_len)
1078
{
1078
{
1079
	struct fp_print_data *fdata = NULL;
1079
	struct fp_print_data *fdata = NULL;
1080
	struct fp_print_data_item *item = NULL;
1080
	int result = -EPROTO;
1081
	int result = -EPROTO;
1081
1082
1082
	if (data_len < sizeof(scan_comp)) {
1083
	if (data_len < sizeof(scan_comp)) {
Lines 1085-1093 static void e_handle_resp02(struct fp_dev *dev, unsigned char *data, Link Here
1085
		fp_err("unrecognised data prefix %x %x %x %x %x",
1086
		fp_err("unrecognised data prefix %x %x %x %x %x",
1086
			data[0], data[1], data[2], data[3], data[4]);
1087
			data[0], data[1], data[2], data[3], data[4]);
1087
	} else {
1088
	} else {
1088
		fdata = fpi_print_data_new(dev, data_len - sizeof(scan_comp));
1089
		fdata = fpi_print_data_new(dev);
1089
		memcpy(fdata->data, data + sizeof(scan_comp),
1090
		item = fpi_print_data_item_new(data_len - sizeof(scan_comp));
1091
		memcpy(item->data, data + sizeof(scan_comp),
1090
			data_len - sizeof(scan_comp));
1092
			data_len - sizeof(scan_comp));
1093
		fdata->prints = g_slist_prepend(fdata->prints, item);
1091
1094
1092
		result = FP_ENROLL_COMPLETE;
1095
		result = FP_ENROLL_COMPLETE;
1093
	}
1096
	}
Lines 1249-1260 static void verify_start_sm_run_state(struct fpi_ssm *ssm) Link Here
1249
		break;
1252
		break;
1250
	case VERIFY_INIT: ;
1253
	case VERIFY_INIT: ;
1251
		struct fp_print_data *print = dev->verify_data;
1254
		struct fp_print_data *print = dev->verify_data;
1252
		size_t data_len = sizeof(verify_hdr) + print->length;
1255
		struct fp_print_data_item *item = print->prints->data;
1256
		size_t data_len = sizeof(verify_hdr) + item->length;
1253
		unsigned char *data = g_malloc(data_len);
1257
		unsigned char *data = g_malloc(data_len);
1254
		struct libusb_transfer *transfer;
1258
		struct libusb_transfer *transfer;
1255
1259
1256
		memcpy(data, verify_hdr, sizeof(verify_hdr));
1260
		memcpy(data, verify_hdr, sizeof(verify_hdr));
1257
		memcpy(data + sizeof(verify_hdr), print->data, print->length);
1261
		memcpy(data + sizeof(verify_hdr), item->data, item->length);
1258
		transfer = alloc_send_cmd28_transfer(dev, 0x03, data, data_len,
1262
		transfer = alloc_send_cmd28_transfer(dev, 0x03, data, data_len,
1259
			verify_init_2803_cb, ssm);
1263
			verify_init_2803_cb, ssm);
1260
		g_free(data);
1264
		g_free(data);
(-)a/libfprint/drivers/vfs0050.c (+587 lines)
Line 0 Link Here
1
#define FP_COMPONENT "vfs0050"
2
3
#include <errno.h>
4
#include <stdlib.h>
5
#include <string.h>
6
#include <stdio.h>
7
#include <assert.h>
8
#include <pixman.h>
9
#include <math.h>
10
11
#include <fp_internal.h>
12
13
#include "vfs0050.h"
14
#include "driver_ids.h"
15
16
static int is_noise(struct vfs0050_line *a)
17
{
18
    int i;
19
    int total_white = 0;
20
    int total_black = 0;
21
    for (i = 0; i < VFS0050_IMG_WIDTH; i++) {
22
        if (a->row[i] >= WHITE_THRESH)
23
            total_white++;
24
        if (a->row[i] <= BLACK_THRESH)
25
            total_black++;
26
    }
27
    if (total_black < 5 && total_white < 5) {
28
        return 1;
29
    }
30
    return 0;
31
}
32
33
static void process_image_data(struct fp_img_dev *dev, char **output, int *output_height)
34
{
35
    //pixman stuff taken from libfprint/pixman.c, adapted for my purposes.
36
    pixman_image_t *orig, *resized;
37
    pixman_transform_t transform;
38
    struct vfs0050_dev *vfs_dev = dev->priv;
39
    struct vfs0050_line *line, *calibration_line;
40
    char *buf = malloc(vfs_dev->scanbuf_idx);
41
    int lines = vfs_dev->scanbuf_idx / VFS0050_FRAME_SIZE;
42
    int i, x, sum, last_sum, diff;
43
    int new_height;
44
    //just grab one around middle, there should be 100
45
    calibration_line = (struct vfs0050_line *) ((char *) vfs_dev->calbuf + (50 * VFS0050_FRAME_SIZE));
46
47
    new_height = 0;
48
    for (i = 0; i < lines; i++) {
49
        line = (struct vfs0050_line *) ((char *) vfs_dev->scanbuf + (i * VFS0050_FRAME_SIZE));
50
        if (!is_noise(line))
51
            memcpy(buf + (new_height++ * VFS0050_IMG_WIDTH), line->row, VFS0050_IMG_WIDTH);
52
        else
53
            fp_dbg("removed noise at line: %d\n", i);
54
    }
55
56
    orig = pixman_image_create_bits(PIXMAN_a8, VFS0050_IMG_WIDTH, new_height, (uint32_t *) buf, VFS0050_IMG_WIDTH);
57
    new_height *= VFS0050_SCALE_FACTOR; //scale for resized image
58
    resized = pixman_image_create_bits(PIXMAN_a8, VFS0050_IMG_WIDTH, new_height, NULL, VFS0050_IMG_WIDTH);
59
    pixman_transform_init_identity(&transform);
60
    pixman_transform_scale(NULL, &transform, pixman_int_to_fixed(1), pixman_double_to_fixed(0.2));
61
    pixman_image_set_transform(orig, &transform);
62
    pixman_image_set_filter(orig, PIXMAN_FILTER_BEST, NULL, 0);
63
    pixman_image_composite32(PIXMAN_OP_SRC,
64
            orig,
65
            NULL,
66
            resized,
67
            0, 0,
68
            0, 0,
69
            0, 0,
70
            VFS0050_IMG_WIDTH, new_height
71
            );
72
    memcpy(buf, pixman_image_get_data(resized), VFS0050_IMG_WIDTH * new_height);
73
74
    pixman_image_unref(orig);
75
    pixman_image_unref(resized);
76
77
    *output_height = new_height;
78
    *output = buf;
79
}
80
81
static void tmp_writeout_buf(struct fp_img_dev *dev)
82
{
83
    struct vfs0050_dev *vfs_dev = dev->priv;
84
    FILE *fp = fopen("/tmp/test.pgm", "w");
85
    if (!fp) {
86
        return;
87
    }
88
    struct vfs0050_line *line;
89
    int i, x;
90
    char tmpbuf[100];
91
    fwrite("P2\n", 3, 1, fp);
92
    sprintf(tmpbuf, "%d %d\n", VFS0050_IMG_WIDTH + 32, (vfs_dev->scanbuf_idx / VFS0050_FRAME_SIZE));
93
    fwrite(tmpbuf, strlen(tmpbuf), 1, fp);
94
    fwrite("255\n", 4, 1, fp);
95
    for (i = 0; i < (vfs_dev->scanbuf_idx / VFS0050_FRAME_SIZE); i++) {
96
        line = (struct vfs0050_line *) ((char *) vfs_dev->scanbuf + (i * VFS0050_FRAME_SIZE));
97
        for (x = 0; x < VFS0050_IMG_WIDTH + 32; x++) {
98
            sprintf(tmpbuf, "%d\t", line->row[x] & 0xff);
99
            fwrite(tmpbuf, strlen(tmpbuf), 1, fp);
100
        }
101
        fwrite("\n", 1, 1, fp);
102
    }
103
    fclose(fp);
104
}
105
106
static int submit_image(struct fp_img_dev *dev)
107
{
108
    struct vfs0050_dev *vfs_dev = dev->priv;
109
    struct fp_img *img = NULL;
110
    int final_height;
111
    char *processed_image;
112
    tmp_writeout_buf(dev);
113
    
114
    process_image_data(dev, &processed_image, &final_height); //the fun part
115
116
    img = fpi_img_new(VFS0050_IMG_WIDTH * final_height);
117
    if (img == NULL)
118
        return 0;
119
120
    memcpy(img->data, processed_image, final_height * VFS0050_IMG_WIDTH);
121
    free(processed_image);
122
    img->width = VFS0050_IMG_WIDTH;
123
    img->height = final_height;
124
    img->flags = FP_IMG_V_FLIPPED;
125
    fpi_imgdev_image_captured(dev, img);
126
    return 1;
127
}
128
129
//activate ssm states
130
enum {
131
    M_ACTIVATE_START,
132
    M_ACTIVATE_1_STEP2,
133
    M_ACTIVATE_1_SINGLE_READ,
134
    M_ACTIVATE_2_SEND,
135
    M_ACTIVATE_EP1_DRAIN,
136
    M_ACTIVATE_EP3_INT1,
137
    M_ACTIVATE_AWAIT_FINGER,
138
    M_ACTIVATE_RECEIVE_FINGERPRINT,
139
    M_ACTIVATE_POST_RECEIVE,
140
    M_ACTIVATE_NUMSTATES
141
};
142
143
static void async_sleep_cb(void *data)
144
{
145
    struct fpi_ssm *ssm = data;
146
    struct fp_img_dev *dev = ssm->priv;
147
    struct vfs0050_dev *vfs_dev = dev->priv;
148
    if (vfs_dev->is_active) {
149
        fpi_ssm_jump_to_state(ssm, M_ACTIVATE_START);
150
    } else {
151
        fpi_ssm_next_state(ssm);
152
    }
153
}
154
155
static void state_activate_cb(struct libusb_transfer *transfer)
156
{
157
    struct fpi_ssm *ssm = transfer->user_data;
158
    struct fp_img_dev *dev = ssm->priv;
159
    struct vfs0050_dev *vfs_dev = dev->priv;
160
    switch (ssm->cur_state) {
161
    case M_ACTIVATE_1_SINGLE_READ:
162
        //check bytes are 0x00 and 0x00
163
        if (vfs_dev->tmpbuf[0] != 0x00 || vfs_dev->tmpbuf[1] != 0x00) {
164
            fp_dbg("unexpected bytes back from endpoint in M_ACTIVATE_1_SINGLE_READ");
165
            libusb_free_transfer(transfer);
166
            fpi_ssm_jump_to_state(ssm, M_ACTIVATE_START);
167
            break;
168
        }
169
        libusb_free_transfer(transfer);
170
        fpi_ssm_next_state(ssm);
171
        break;
172
    case M_ACTIVATE_2_SEND:
173
        vfs_dev->activate_offset += transfer->actual_length;
174
        if (vfs_dev->activate_offset == sizeof(vfs0050_activate2)) { //finished sending this activation section
175
            fpi_ssm_next_state(ssm);
176
            break;
177
        }
178
        fpi_ssm_jump_to_state(ssm, M_ACTIVATE_2_SEND);
179
        break;
180
    case M_ACTIVATE_EP1_DRAIN:
181
        //just draining this data, not sure what it does yet.
182
        if (transfer->actual_length < 64) {
183
            libusb_free_transfer(transfer);
184
            fpi_ssm_next_state(ssm);
185
            break;
186
        }
187
        libusb_free_transfer(transfer);
188
        fpi_ssm_jump_to_state(ssm, M_ACTIVATE_EP1_DRAIN);
189
        break;
190
    case M_ACTIVATE_EP3_INT1:
191
        if (transfer->actual_length != 5) {
192
            fp_dbg("unexpected length for interrupt transfer in M_ACTIVATE_EP3_INT1");
193
            //TODO: fail here, exit ssm
194
        }
195
        fpi_ssm_next_state(ssm);
196
        break;
197
    case M_ACTIVATE_AWAIT_FINGER:
198
        //if we got here, it's time to read fingerprint data.
199
        //interrupt data should be 02 00 0e 00 f0
200
        if (vfs_dev->is_active) {
201
            if (transfer->actual_length != 5) {
202
                fp_dbg("unexpected length for interrupt transfer in M_ACTIVATE_AWAIT_FINGER");
203
                //TODO: fail here, exit ssm.
204
            }
205
            if (memcmp(vfs_dev->tmpbuf, vfs0050_valid_interrupt, 5) != 0) {
206
                fp_dbg("invalid interrupt data in M_ACTIVATE_AWAIT_FINGER");
207
                //TODO: fail here, exit ssm.
208
            }
209
            fpi_imgdev_report_finger_status(dev, TRUE); //report finger on to libfprint
210
            fpi_ssm_next_state(ssm);
211
        } else {
212
            fpi_ssm_mark_completed(ssm);
213
            //break fall through
214
        }
215
        break;
216
    case M_ACTIVATE_RECEIVE_FINGERPRINT:
217
        if (transfer->actual_length == 0) {
218
            libusb_free_transfer(transfer);
219
            fpi_ssm_next_state(ssm);
220
            break;
221
        }
222
        vfs_dev->scanbuf_idx += transfer->actual_length;
223
        libusb_free_transfer(transfer);
224
        fpi_ssm_jump_to_state(ssm, M_ACTIVATE_RECEIVE_FINGERPRINT);
225
        break;
226
    default:
227
        libusb_free_transfer(transfer);
228
        fpi_ssm_next_state(ssm);
229
        break;
230
    }
231
}
232
233
static void state_activate(struct fpi_ssm *ssm)
234
{
235
    struct libusb_transfer *transfer;
236
    struct fp_img_dev *dev = ssm->priv;
237
    struct vfs0050_dev *vfs_dev = dev->priv;
238
    int to_send;
239
    switch (ssm->cur_state) {
240
    case M_ACTIVATE_START:
241
        vfs_dev->activate_offset = 0;
242
        transfer = libusb_alloc_transfer(0);
243
        libusb_fill_bulk_transfer(transfer, dev->udev, EP1_OUT, vfs0050_activate1, 64, state_activate_cb, ssm, BULK_TIMEOUT);
244
        libusb_submit_transfer(transfer);
245
        break;
246
    case M_ACTIVATE_1_STEP2:
247
        transfer = libusb_alloc_transfer(0);
248
        libusb_fill_bulk_transfer(transfer, dev->udev, EP1_OUT, vfs0050_activate1 + 64, 61, state_activate_cb, ssm, BULK_TIMEOUT);
249
        libusb_submit_transfer(transfer);
250
        break;
251
    case M_ACTIVATE_1_SINGLE_READ:
252
        transfer = libusb_alloc_transfer(0);
253
        libusb_fill_bulk_transfer(transfer, dev->udev, EP1_IN, vfs_dev->tmpbuf, 64, state_activate_cb, ssm, BULK_TIMEOUT);
254
        libusb_submit_transfer(transfer);
255
        break;
256
    case M_ACTIVATE_2_SEND:
257
        to_send = sizeof(vfs0050_activate2) - vfs_dev->activate_offset;
258
        to_send = to_send >= 64 ? 64 : to_send;
259
        transfer = libusb_alloc_transfer(0);
260
        libusb_fill_bulk_transfer(transfer, dev->udev, EP1_OUT, vfs0050_activate2 + vfs_dev->activate_offset, to_send, state_activate_cb, ssm, BULK_TIMEOUT);
261
        libusb_submit_transfer(transfer);
262
        break;
263
    case M_ACTIVATE_EP1_DRAIN:
264
        transfer = libusb_alloc_transfer(0);
265
        libusb_fill_bulk_transfer(transfer, dev->udev, EP1_IN, vfs_dev->tmpbuf, 64, state_activate_cb, ssm, BULK_TIMEOUT);
266
        libusb_submit_transfer(transfer);
267
        break;
268
    case M_ACTIVATE_EP3_INT1: //first interrupt, should be 5 x 0x00
269
        transfer = libusb_alloc_transfer(0);
270
        libusb_fill_interrupt_transfer(transfer, dev->udev, EP3_IN, vfs_dev->tmpbuf, 8, state_activate_cb, ssm, INTERRUPT_TIMEOUT1);
271
        libusb_submit_transfer(transfer);
272
        break;
273
    case M_ACTIVATE_AWAIT_FINGER:
274
        //this sets up infinite wait for interrupt.  When the interrupt occurs, we're ready to read data on EP2.
275
        if (!vfs_dev->is_active) {
276
            vfs_dev->is_active = 1;
277
            fpi_imgdev_activate_complete(dev, 0); //notify libfprint activation complete.
278
        }
279
        transfer = libusb_alloc_transfer(0);
280
        libusb_fill_interrupt_transfer(transfer, dev->udev, EP3_IN, vfs_dev->tmpbuf, 8, state_activate_cb, ssm, INTERRUPT_TIMEOUT_NONE);
281
        libusb_submit_transfer(transfer);
282
        break;
283
    case M_ACTIVATE_RECEIVE_FINGERPRINT:
284
        if (vfs_dev->scanbuf_idx + 64 >= vfs_dev->scanbuf_sz) {
285
            vfs_dev->scanbuf_sz <<= 1;
286
            vfs_dev->scanbuf = g_realloc(vfs_dev->scanbuf, vfs_dev->scanbuf_sz);
287
        }
288
        transfer = libusb_alloc_transfer(0);
289
        libusb_fill_bulk_transfer(transfer, dev->udev, EP2_IN, vfs_dev->scanbuf + vfs_dev->scanbuf_idx, 64, state_activate_cb, ssm, 500);
290
        libusb_submit_transfer(transfer);
291
        break;
292
    case M_ACTIVATE_POST_RECEIVE:
293
        submit_image(dev);
294
        fpi_imgdev_report_finger_status(dev, FALSE);
295
        vfs_dev->activate_offset = 0;
296
        vfs_dev->scanbuf_idx = 0;
297
        fpi_timeout_add(300, async_sleep_cb, ssm); //wait a bit and see if we're swiping again.
298
        break;
299
300
    }
301
}
302
303
static void state_activate_complete(struct fpi_ssm *ssm)
304
{
305
    fpi_ssm_free(ssm);
306
}
307
308
//init ssm states
309
enum {
310
    M_INIT_START,
311
    M_INIT_1_ONGOING,
312
    M_INIT_1_STEP2,
313
    M_INIT_1_STEP3,
314
    M_INIT_1_STEP4,
315
    M_INIT_2_ONGOING,
316
    M_INIT_2_RECV_EP1_ONGOING,
317
    M_INIT_2_RECV_EP2_ONGOING, //TODO: this looks like some sensor calibration data, could be useful later.
318
    M_INIT_2_COMPLETE,
319
    M_INIT_NUMSTATES,
320
};
321
322
static void state_init_cb(struct libusb_transfer *transfer)
323
{
324
    struct fpi_ssm *ssm = transfer->user_data;
325
    struct fp_img_dev *dev = ssm->priv;
326
    struct vfs0050_dev *vfs_dev = dev->priv;
327
    //TODO: check for transfer errors in tranfer->status
328
    switch (ssm->cur_state) {
329
    case M_INIT_1_ONGOING:
330
        vfs_dev->init1_offset += transfer->actual_length;
331
        libusb_free_transfer(transfer);
332
        if (vfs_dev->init1_offset == sizeof(vfs0050_init1)) { //done transferring this initialization section
333
            fpi_ssm_next_state(ssm);
334
            break;
335
        }
336
        fpi_ssm_jump_to_state(ssm, M_INIT_1_ONGOING);
337
        break;
338
    case M_INIT_2_ONGOING:
339
        vfs_dev->init2_offset += transfer->actual_length;
340
        libusb_free_transfer(transfer);
341
        if (vfs_dev->init2_offset == sizeof(vfs0050_init2)) { //done transferring this initialization section
342
            fpi_ssm_next_state(ssm);
343
            break;
344
        }
345
        fpi_ssm_jump_to_state(ssm, M_INIT_2_ONGOING);
346
        break;
347
    case M_INIT_2_RECV_EP1_ONGOING:
348
        //we wait for a timeout here indicating no more data to receive.
349
        if (transfer->actual_length < 64) {
350
            fpi_ssm_next_state(ssm);
351
            break;
352
        }
353
        fpi_ssm_jump_to_state(ssm, M_INIT_2_RECV_EP1_ONGOING);
354
        break;
355
    case M_INIT_2_RECV_EP2_ONGOING:
356
        vfs_dev->calbuf_idx += transfer->actual_length;
357
        if (transfer->actual_length < 64) {
358
            fpi_ssm_next_state(ssm);
359
            break;
360
        }
361
        fpi_ssm_jump_to_state(ssm, M_INIT_2_RECV_EP2_ONGOING);
362
        break;
363
    default:
364
        libusb_free_transfer(transfer);
365
        fpi_ssm_next_state(ssm);
366
        break;
367
    }
368
    
369
}
370
371
static void state_init(struct fpi_ssm *ssm)
372
{
373
    int transferred;
374
    int to_send;
375
    struct libusb_transfer *transfer;
376
    struct fp_img_dev *dev = ssm->priv;
377
    struct vfs0050_dev *vfs_dev = dev->priv;
378
    switch (ssm->cur_state) {
379
    case M_INIT_START:
380
        //couple of synchronous transfers here in the beginning, don't think this hurts much.
381
        vfs_dev->tmpbuf[0] = 0x1a;
382
        libusb_bulk_transfer(dev->udev, EP1_OUT, vfs_dev->tmpbuf, 1, &transferred, BULK_TIMEOUT);
383
        libusb_bulk_transfer(dev->udev, EP1_IN, vfs_dev->tmpbuf, 64, &transferred, BULK_TIMEOUT);
384
        fpi_ssm_next_state(ssm);
385
        break;
386
    case M_INIT_1_ONGOING:
387
        to_send = sizeof(vfs0050_init1) - vfs_dev->init1_offset;
388
        to_send = to_send >= 64 ? 64 : to_send;
389
        assert(to_send > 0);
390
        transfer = libusb_alloc_transfer(0);
391
        libusb_fill_bulk_transfer(transfer, dev->udev, EP1_OUT, vfs0050_init1 + vfs_dev->init1_offset, to_send, state_init_cb, ssm, BULK_TIMEOUT);
392
        libusb_submit_transfer(transfer);
393
        break;
394
    case M_INIT_1_STEP2:
395
        transfer = libusb_alloc_transfer(0);
396
        libusb_fill_bulk_transfer(transfer, dev->udev, EP1_IN, vfs_dev->tmpbuf, 64, state_init_cb, ssm, BULK_TIMEOUT);
397
        libusb_submit_transfer(transfer);
398
        break;
399
    case M_INIT_1_STEP3:
400
        vfs_dev->tmpbuf[0] = 0x01;
401
        transfer = libusb_alloc_transfer(0);
402
        libusb_fill_bulk_transfer(transfer, dev->udev, EP1_OUT, vfs_dev->tmpbuf, 1, state_init_cb, ssm, BULK_TIMEOUT);
403
        libusb_submit_transfer(transfer);
404
        break;
405
    case M_INIT_1_STEP4:
406
        transfer = libusb_alloc_transfer(0);
407
        libusb_fill_bulk_transfer(transfer, dev->udev, EP1_IN, vfs_dev->tmpbuf, 64, state_init_cb, ssm, BULK_TIMEOUT);
408
        libusb_submit_transfer(transfer);
409
        break;
410
    case M_INIT_2_ONGOING:
411
        to_send = sizeof(vfs0050_init2) - vfs_dev->init2_offset;
412
        to_send = to_send >= 64 ? 64 : to_send;
413
        assert(to_send > 0);
414
        transfer = libusb_alloc_transfer(0);
415
        libusb_fill_bulk_transfer(transfer, dev->udev, EP1_OUT, vfs0050_init2 + vfs_dev->init2_offset, to_send, state_init_cb, ssm, BULK_TIMEOUT);
416
        libusb_submit_transfer(transfer);
417
        break;
418
    case M_INIT_2_RECV_EP1_ONGOING:
419
        transfer = libusb_alloc_transfer(0);
420
        libusb_fill_bulk_transfer(transfer, dev->udev, EP1_IN, vfs_dev->tmpbuf, 64, state_init_cb, ssm, BULK_TIMEOUT);
421
        libusb_submit_transfer(transfer);
422
        break;
423
    case M_INIT_2_RECV_EP2_ONGOING:
424
        if (vfs_dev->calbuf_idx + 64 >= vfs_dev->calbuf_sz) {
425
            vfs_dev->calbuf_sz <<= 1;
426
            vfs_dev->calbuf = g_realloc(vfs_dev->calbuf, vfs_dev->calbuf_sz);
427
        }
428
        transfer = libusb_alloc_transfer(0);
429
        libusb_fill_bulk_transfer(transfer, dev->udev, EP2_IN, vfs_dev->calbuf + vfs_dev->calbuf_idx, 64, state_init_cb, ssm, BULK_TIMEOUT);
430
        libusb_submit_transfer(transfer);
431
        break;
432
    default:
433
        fpi_ssm_mark_completed(ssm);
434
        break;
435
    }
436
}
437
438
static void state_init_complete(struct fpi_ssm *ssm)
439
{
440
    struct fp_img_dev *dev = ssm->priv;
441
    fpi_imgdev_open_complete(dev, 0);
442
    fpi_ssm_free(ssm);
443
}
444
445
static void generic_async_cb(struct libusb_transfer *t)
446
{
447
    libusb_free_transfer(t);
448
}
449
450
static void dev_deactivate(struct fp_img_dev *dev)
451
{
452
    struct vfs0050_dev *vfs_dev = dev->priv;
453
    int err = 0;
454
    int tmpoffset;
455
    int to_send;
456
    struct libusb_transfer *t;
457
    vfs_dev->is_active = 0;
458
    //EP2 IN
459
    t = libusb_alloc_transfer(0);
460
    libusb_fill_bulk_transfer(t, dev->udev, EP2_IN, vfs_dev->tmpbuf, 64, generic_async_cb, NULL, 100);
461
    libusb_submit_transfer(t);
462
    //EP1_IN
463
    t = libusb_alloc_transfer(0);
464
    libusb_fill_bulk_transfer(t, dev->udev, EP1_IN, vfs_dev->tmpbuf, 64, generic_async_cb, NULL, 100);
465
    libusb_submit_transfer(t);
466
    //EP1_OUT
467
    t = libusb_alloc_transfer(0);
468
    vfs_dev->tmpbuf[0] = 0x04;
469
    libusb_fill_bulk_transfer(t, dev->udev, EP1_OUT, vfs_dev->tmpbuf, 1, generic_async_cb, NULL, 100);
470
    libusb_submit_transfer(t);
471
    //EP1_IN
472
    t = libusb_alloc_transfer(0);
473
    libusb_fill_bulk_transfer(t, dev->udev, EP1_IN, vfs_dev->tmpbuf, 64, generic_async_cb, NULL, 100);
474
    libusb_submit_transfer(t);
475
    //EP1_OUT
476
    t = libusb_alloc_transfer(0);
477
    libusb_fill_bulk_transfer(t, dev->udev, EP1_OUT, vfs0050_deactivate1, 64, generic_async_cb, NULL, 100);
478
    libusb_submit_transfer(t);
479
    //EP1_OUT
480
    t = libusb_alloc_transfer(0);
481
    libusb_fill_bulk_transfer(t, dev->udev, EP1_OUT, &vfs0050_deactivate1[64], 61, generic_async_cb, NULL, 100);
482
    libusb_submit_transfer(t);
483
    tmpoffset = 0;
484
    do {
485
        to_send = sizeof(vfs0050_activate2) - tmpoffset;
486
        to_send = to_send >= 64 ? 64 : to_send;
487
        t = libusb_alloc_transfer(0);
488
        libusb_fill_bulk_transfer(t, dev->udev, EP1_OUT, vfs0050_activate2 + tmpoffset, to_send, generic_async_cb, NULL, 100);
489
        libusb_submit_transfer(t);
490
        tmpoffset += err;
491
    } while (err == 64);
492
    do {
493
        t = libusb_alloc_transfer(0);
494
        libusb_fill_bulk_transfer(t, dev->udev, EP1_IN, vfs_dev->tmpbuf, 64, generic_async_cb, NULL, 100);
495
        libusb_submit_transfer(t);
496
    } while(err == 64);
497
    t = libusb_alloc_transfer(0);
498
    libusb_fill_bulk_transfer(t, dev->udev, EP1_IN, vfs_dev->tmpbuf, 64, generic_async_cb, NULL, 100);
499
    libusb_submit_transfer(t);
500
    //TODO: finish this, leaves device in inconsistent state.
501
    fpi_imgdev_deactivate_complete(dev);
502
}
503
504
static int dev_activate(struct fp_img_dev *dev, enum fp_imgdev_state state)
505
{
506
    fp_dbg("dev_activate called");
507
    struct fpi_ssm *activate_ssm;
508
    activate_ssm = fpi_ssm_new(dev->dev, state_activate, M_ACTIVATE_NUMSTATES);
509
    activate_ssm->priv = dev;
510
    fpi_ssm_start(activate_ssm, state_activate_complete);
511
    return 0;
512
}
513
514
static int dev_open(struct fp_img_dev *dev, unsigned long driver_data)
515
{
516
    struct fpi_ssm *init_ssm;
517
    struct vfs0050_dev *vdev = NULL;
518
    int r;
519
    fp_dbg("dev_open called");
520
    //TODO: this is probably frowned upon :/ but right now a reset is the only
521
    // way for me to know I'm working with a clean slate and the rest of this will work.
522
    // Will be trying to reverse engineer more of the protocol so I can avoid resetting
523
    // the device each time it's opened.
524
    libusb_reset_device(dev->udev);
525
526
    r = libusb_claim_interface(dev->udev, 0);
527
    if (r < 0) {
528
        fp_err("could not claim interface 0");
529
        return r;
530
    }
531
    libusb_control_transfer(dev->udev, 0x00, 0x09, 0x0001, 0, NULL, 0, 100);
532
533
534
    vdev = g_malloc0(sizeof(struct vfs0050_dev));
535
    vdev->scanbuf = g_malloc0(VFS0050_INITIAL_SCANBUF_SIZE);
536
    vdev->scanbuf_sz = VFS0050_INITIAL_SCANBUF_SIZE;
537
    vdev->calbuf = g_malloc0(VFS0050_INITIAL_SCANBUF_SIZE);
538
    vdev->calbuf_sz = VFS0050_INITIAL_SCANBUF_SIZE;
539
    dev->priv = vdev;
540
    init_ssm = fpi_ssm_new(dev->dev, state_init, M_INIT_NUMSTATES);
541
    init_ssm->priv = dev;
542
    fpi_ssm_start(init_ssm, state_init_complete);
543
544
    return 0;
545
}
546
547
static void dev_close(struct fp_img_dev *dev)
548
{
549
    fp_dbg("dev_close called");
550
    //release private structure
551
    g_free(((struct vfs0050_dev *)dev->priv)->calbuf);
552
    g_free(((struct vfs0050_dev *)dev->priv)->scanbuf);
553
    g_free(dev->priv);
554
555
    libusb_release_interface(dev->udev, 0);
556
557
    fpi_imgdev_close_complete(dev);
558
}
559
560
561
static const struct usb_id id_table[] =
562
{
563
    { .vendor = 0x138a, .product = 0x0050 },
564
    { 0, 0, 0 },
565
};
566
567
struct fp_img_driver vfs0050_driver =
568
{
569
    .driver =
570
    {
571
        .id = VFS0050_ID,
572
        .name = FP_COMPONENT,
573
        .full_name = "Validity 0050",
574
        .id_table = id_table,
575
        .scan_type = FP_SCAN_TYPE_SWIPE,
576
    },
577
578
    .flags = 0,
579
    .img_width = VFS0050_IMG_WIDTH,
580
    .img_height = -1,
581
    .bz3_threshold = 24,
582
583
    .open = dev_open,
584
    .close = dev_close,
585
    .activate = dev_activate,
586
    .deactivate = dev_deactivate,
587
};
(-)a/libfprint/drivers/vfs0050.h (+404 lines)
Line 0 Link Here
1
#define BULK_TIMEOUT 100
2
#define INTERRUPT_TIMEOUT1 300
3
#define INTERRUPT_TIMEOUT_NONE 0
4
#define VFS0050_FRAME_SIZE 148
5
#define VFS0050_IMG_WIDTH 100
6
#define VFS0050_INITIAL_SCANBUF_SIZE (1 << 19)
7
#define VFS0050_SCALE_FACTOR 0.20
8
#define WHITE_THRESH 200
9
#define BLACK_THRESH 50
10
#define EP1_OUT 0x01
11
#define EP1_IN  0x81
12
#define EP2_OUT 0x02
13
#define EP2_IN  0x82
14
#define EP3_OUT 0x03
15
#define EP3_IN  0x83
16
17
struct vfs0050_dev {
18
    int init1_offset;
19
    int init2_offset;
20
    int activate_offset;
21
    char tmpbuf[100];
22
    char *calbuf;
23
    int calbuf_idx;
24
    int calbuf_sz;
25
    char *scanbuf;
26
    int scanbuf_idx;
27
    int scanbuf_sz;
28
    int is_active;
29
};
30
31
struct vfs0050_line {
32
	unsigned char _0x01;
33
	unsigned char _0xfe;
34
	unsigned char _low;
35
	unsigned char _high;
36
	unsigned char _0x08;
37
	unsigned char _0xb8; //not sure what this is for
38
	unsigned char _0x00;
39
	unsigned char _counter; //not sure what this is either.
40
	unsigned char row[100]; //grayscale data
41
	unsigned char mag[32]; //magnified portion of scan
42
	unsigned char sums[8];
43
} __attribute__((__packed__));
44
45
static unsigned char vfs0050_valid_interrupt[] =
46
{
47
    0x02, 0x00, 0x0e, 0x00, 0xf0
48
};
49
50
static unsigned char vfs0050_init1[] =
51
{
52
	0x36, 0x38, 0x2b, 0x5c, 0x70, 0xac, 0x73, 0x69,
53
	0x12, 0xc9, 0xe0, 0xbc, 0xfa, 0x88, 0x10, 0xc7,
54
	0x98, 0xbf, 0x52, 0xe3, 0xd5, 0xbc, 0x99, 0x9f,
55
	0x73, 0x48, 0x06, 0xba, 0xe0, 0x11, 0x0e, 0x87,
56
	0x87, 0xb5, 0x18, 0x95, 0x63, 0x98, 0xae, 0x00,
57
	0xc2, 0x67, 0xd5, 0x05, 0x5d, 0x66, 0xd6, 0xb3,
58
	0x3f, 0xb7, 0xa7, 0xa0, 0x61, 0x5b, 0x1d, 0xa0,
59
	0x36, 0xc6, 0xe1, 0x78, 0x0d, 0x86, 0x72, 0x84, //end block 1
60
	0xd2, 0xf3, 0xd9, 0xb9, 0x78, 0xd8, 0xde, 0xad,
61
	0x7a, 0x45, 0x3c, 0x96, 0x08, 0x2d, 0xc6, 0xae,
62
	0xc3, 0x3d, 0x8c, 0x6e, 0x5a, 0xfd, 0x91, 0x90,
63
	0x0d, 0x78, 0x98, 0xf1, 0x28, 0x67, 0x15, 0x80,
64
	0xea, 0x7b, 0xa9, 0xbd, 0xe0, 0x4b, 0x54, 0x8f,
65
	0x91, 0xea, 0x2a, 0x99, 0x38, 0xaf, 0x52, 0x11,
66
	0xc8, 0x34, 0x17, 0x42, 0xb8, 0xea, 0xd3, 0x8e,
67
	0xbc, 0x6a, 0xaa, 0x54, 0x3e, 0x77, 0x44, 0xd6, //end block 2
68
	0x4a, 0x46, 0x04, 0xa5, 0x33, 0xe1, 0x86, 0xfd,
69
	0xed, 0x80, 0xa8, 0x12, 0x3a, 0xc2, 0x29, 0x3e,
70
	0xce, 0x9e, 0x00, 0xe7, 0xb3, 0xb5, 0x11, 0x2b,
71
	0x50, 0x6c, 0x2c, 0x5e, 0x33, 0x17, 0xf5, 0x8b,
72
	0xc4, 0x0f, 0x25, 0x65, 0x87, 0x0d, 0x88, 0x3c,
73
	0x30, 0xad, 0x9b, 0x40, 0x8a, 0x6c, 0x60, 0xc9,
74
	0xf4, 0x03, 0xc1, 0x0f, 0x0e, 0x08, 0xa1, 0x81,
75
	0x5e, 0x6a, 0x79, 0x3f, 0x7a, 0xf6, 0x18, 0x7e, //end block 3
76
	0x30, 0x98, 0xf1, 0x25, 0xcb, 0xbd, 0xb9, 0xae,
77
	0x5b, 0xeb, 0xa7, 0xea, 0x7c, 0xb6, 0x6f, 0x06,
78
	0x0f, 0xaa, 0xe5, 0xd6, 0xe3, 0x46, 0x83, 0xa3,
79
	0xe1, 0x66, 0x38, 0x70, 0xb0, 0x5c, 0x3e, 0xe3,
80
	0xe0, 0x50, 0x25, 0x60, 0x98, 0x08, 0xa8, 0x86,
81
	0xc9, 0xdc, 0xbc, 0xaf, 0x02, 0x54, 0xfc, 0xad,
82
	0x8d, 0x9f, 0x87, 0x5a, 0x2f, 0x4a, 0xea, 0x92,
83
	0x71, 0x5d, 0x88, 0x64, 0xeb, 0xb0, 0x98, 0x27, //end block 4
84
	0x96, 0xd5, 0x1f, 0x80, 0x44, 0xe3, 0x0f, 0x95,
85
	0x95, 0xcb, 0x43, 0xb0, 0xca, 0xbf, 0xac, 0xd9,
86
	0x70, 0xe8, 0xc6, 0xf9, 0x4a, 0x94, 0xf7, 0x6c,
87
	0x8d, 0x46, 0x97, 0x63, 0x85, 0xb9, 0x85, 0xae,
88
	0x3c, 0xe0, 0xa2, 0xad, 0xd7, 0x36, 0x27, 0xcf,
89
	0xa1, 0x1f, 0x18, 0x34, 0xf9, 0xff, 0x52, 0xc7,
90
	0xae, 0x60, 0x2d, 0xa5, 0x76, 0x79, 0x42, 0xfb,
91
	0xa8, 0x52, 0xa8, 0x08, 0x37, 0x79, 0x96, 0x7e, //end block 5
92
	0x33, 0x1d, 0xd0, 0x6f, 0xc6, 0x13, 0x43, 0xdb,
93
	0xb0, 0xa9, 0xdd, 0x1c, 0x7a, 0x8a, 0xce, 0xe8,
94
	0xb6, 0xf9, 0x23, 0x43, 0x47, 0x1d, 0xd8, 0xbf,
95
	0xb3, 0x68, 0x66, 0x55, 0x92, 0xae, 0x7a, 0x76,
96
	0x54, 0xcf, 0x2c, 0xfc, 0x11, 0xf1, 0xd2, 0x08,
97
	0x27, 0xd9, 0x23, 0x5c, 0x3c, 0x0a, 0xde, 0x7c,
98
	0xd9, 0x26, 0x4b, 0x24, 0x5d, 0xc2, 0xbf, 0xe9,
99
	0x50, 0x87, 0xda, 0x2d, 0xfd, 0x5e, 0x20, 0x66, //end block 6
100
	0x08, 0x9d, 0xe2, 0xa6, 0xc1, 0xc7, 0x0e, 0x86,
101
	0xcb, 0xe0, 0xe7, 0x56, 0x82, 0xf1, 0x7e, 0x7e,
102
	0x4a, 0xb3, 0x42, 0x8d, 0x25, 0xec, 0x1e, 0xb1,
103
	0x44, 0x17, 0xdf, 0xb3, 0x06, 0xf4, 0x60, 0x3d,
104
	0x68, 0x36, 0x45, 0xa5, 0xee, 0x5b, 0xea, 0xc3,
105
	0x5d, 0x67, 0x51, 0x14, 0xdc, 0xcc, 0x6b, 0x9d,
106
	0xd3, 0x01, 0xdb, 0x99, 0xc7, 0x85, 0x15, 0x68,
107
	0xe5, 0x04, 0xe4, 0x12, 0xd4, 0x83, 0x44, 0x7d, //end block 7
108
	0xe8, 0x7c, 0x6c, 0xaa, 0xaa, 0xd2, 0x97, 0x5b,
109
	0xae, 0xac, 0x03, 0xac, 0x3c, 0x73, 0xd6, 0x16,
110
	0x72, 0x29, 0xc7, 0x2a, 0x57, 0xbc, 0x3e, 0xdc,
111
	0x2e, 0xaf, 0xd2, 0x1a, 0x03, 0x76, 0x39, 0x9d,
112
	0x3f, 0x66, 0xe5, 0xcc, 0x32, 0x0d, 0xd8, 0x58,
113
	0x4b, 0xa4, 0xa2, 0x39, 0xe2, 0xe8, 0xb7, 0x44,
114
	0x33, 0xab, 0x7c, 0x49, 0xf6, 0xe4, 0x24, 0xc4,
115
	0x7c, 0xa9, 0x07, 0x31, 0x93, 0x16, 0xb4, 0x31, //end block 8
116
	0x38, 0x5d, 0x13, 0x0b, 0x8f, 0x46, 0xa8, 0x77,
117
	0xb2, 0x86, 0x15, 0x2c, 0xa7, 0x6a, 0x04, 0xb1,
118
	0x4c, 0xdd, 0xc8, 0xe0, 0x26, 0xc5, 0xa3, 0x4d,
119
	0x6a, 0x94, 0x57, 0x1f, 0x85, 0x83, 0x8f, 0x05,
120
	0xe3, 0xd9, 0x3d, 0x3c, 0x54, 0x96, 0x05, 0xec,
121
	0xf8, 0x25, 0xea, 0x84, 0x9f, 0x5d, 0x3f, 0x4a,
122
	0xa1, 0x89, 0x86, 0x9f, 0xb7, 0x73, 0x49, 0x6c,
123
	0x8e, 0xcf, 0x9c, 0x88, 0xb6, 0xce, 0x18, 0x15, //end block 9
124
	0x93, 0xe0, 0x17, 0x9a, 0x69, 0x57, 0xd1, 0xb6,
125
	0x25, 0xf9, 0x62, 0xd2, 0xba, 0x2c, 0xcb, 0xe6,
126
	0x5f, 0xe5, 0xb4, 0x18, 0xe8, 0x65, 0x46, 0x7d,
127
	0x06, 0x36, 0x85, 0x74, 0xc4, 0x1d, 0x62, 0xf1,
128
	0x50, 0x54, 0x9a, 0x02, 0xda, 0x4b, 0x67, 0x70,
129
	0xfd, 0x00
130
};
131
static unsigned char vfs0050_init2[] = 
132
{
133
	0x02, 0x94, 0x00, 0x64, 0x00, 0x20, 0x00, 0x08,
134
	0x00, 0x2c, 0x03, 0x00, 0x30, 0x1b, 0x00, 0x00,
135
	0x00, 0x20, 0x00, 0x08, 0x00, 0x20, 0x03, 0x00,
136
	0x30, 0x3d, 0x10, 0x00, 0x00, 0x20, 0x00, 0x08,
137
	0x00, 0x18, 0x03, 0x00, 0x30, 0x00, 0x00, 0x00,
138
	0x00, 0x20, 0x00, 0x08, 0x00, 0x24, 0x03, 0x00,
139
	0x30, 0x08, 0x00, 0x00, 0x00, 0x20, 0x00, 0x08,
140
	0x00, 0x28, 0x03, 0x00, 0x30, 0x08, 0x00, 0x00, //end block 1
141
	0x00, 0x20, 0x00, 0x08, 0x00, 0x30, 0x03, 0x00,
142
	0x30, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x08,
143
	0x00, 0x38, 0x03, 0x00, 0x30, 0x00, 0x00, 0x00,
144
	0x00, 0x20, 0x00, 0x08, 0x00, 0x3c, 0x03, 0x00,
145
	0x30, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x08,
146
	0x00, 0x44, 0x03, 0x00, 0x30, 0x14, 0x00, 0x00,
147
	0x00, 0x20, 0x00, 0x08, 0x00, 0x48, 0x03, 0x00,
148
	0x30, 0x01, 0x04, 0x02, 0x00, 0x20, 0x00, 0x08, //end block 2
149
	0x00, 0x4c, 0x03, 0x00, 0x30, 0x01, 0x0c, 0x02,
150
	0x00, 0x20, 0x00, 0x08, 0x00, 0x54, 0x03, 0x00,
151
	0x30, 0x20, 0x00, 0x00, 0x00, 0x20, 0x00, 0x08,
152
	0x00, 0x5c, 0x03, 0x00, 0x30, 0x90, 0x01, 0x02,
153
	0x00, 0x20, 0x00, 0x08, 0x00, 0x60, 0x03, 0x00,
154
	0x30, 0x2c, 0x01, 0x19, 0x00, 0x20, 0x00, 0x08,
155
	0x00, 0x64, 0x03, 0x00, 0x30, 0x00, 0x00, 0x00,
156
	0x00, 0x20, 0x00, 0x08, 0x00, 0x6c, 0x03, 0x00, //end block 3
157
	0x30, 0x1e, 0x00, 0x00, 0x00, 0x20, 0x00, 0x08,
158
	0x00, 0x70, 0x03, 0x00, 0x30, 0x21, 0x80, 0x00,
159
	0x00, 0x20, 0x00, 0x08, 0x00, 0x78, 0x03, 0x00,
160
	0x30, 0x09, 0x00, 0x02, 0x00, 0x20, 0x00, 0x08,
161
	0x00, 0x7c, 0x03, 0x00, 0x30, 0x0b, 0x00, 0x19,
162
	0x00, 0x20, 0x00, 0x08, 0x00, 0x80, 0x03, 0x00,
163
	0x30, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x08,
164
	0x00, 0x84, 0x03, 0x00, 0x30, 0x3a, 0x00, 0x00, //end block 4
165
	0x00, 0x20, 0x00, 0x08, 0x00, 0x88, 0x03, 0x00,
166
	0x30, 0x14, 0x00, 0x00, 0x00, 0x20, 0x00, 0x08,
167
	0x00, 0x8c, 0x03, 0x00, 0x30, 0x02, 0x00, 0x00,
168
	0x00, 0x20, 0x00, 0x08, 0x00, 0x90, 0x03, 0x00,
169
	0x30, 0x02, 0x00, 0x00, 0x00, 0x20, 0x00, 0x08,
170
	0x00, 0x94, 0x03, 0x00, 0x30, 0x08, 0x00, 0x00,
171
	0x00, 0x20, 0x00, 0x08, 0x00, 0x98, 0x03, 0x00,
172
	0x30, 0x00, 0x00, 0xa1, 0x01, 0x20, 0x00, 0x08, //end block 5
173
	0x00, 0x9c, 0x03, 0x00, 0x30, 0x00, 0x00, 0xa1,
174
	0x01, 0x20, 0x00, 0x08, 0x00, 0xa8, 0x03, 0x00,
175
	0x30, 0x64, 0x01, 0x00, 0x00, 0x20, 0x00, 0x08,
176
	0x00, 0xac, 0x03, 0x00, 0x30, 0x64, 0x01, 0x00,
177
	0x00, 0x20, 0x00, 0x08, 0x00, 0xb0, 0x03, 0x00,
178
	0x30, 0x00, 0x01, 0x00, 0x00, 0x20, 0x00, 0x08,
179
	0x00, 0xb4, 0x03, 0x00, 0x30, 0x00, 0x01, 0x00,
180
	0x00, 0x20, 0x00, 0x08, 0x00, 0xb8, 0x03, 0x00, //end block 6
181
	0x30, 0x05, 0x00, 0x00, 0x00, 0x20, 0x00, 0x08,
182
	0x00, 0xbc, 0x03, 0x00, 0x30, 0x05, 0x00, 0x00,
183
	0x00, 0x20, 0x00, 0x08, 0x00, 0xc0, 0x03, 0x00,
184
	0x30, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x08,
185
	0x00, 0x84, 0x03, 0x00, 0x30, 0x3b, 0x00, 0x00,
186
	0x00, 0x20, 0x00, 0x08, 0x00, 0x08, 0x07, 0x00,
187
	0x30, 0x03, 0x00, 0x00, 0x00, 0x20, 0x00, 0x08,
188
	0x00, 0x0c, 0x07, 0x00, 0x30, 0x00, 0x00, 0x00, //end block 7
189
	0x00, 0x20, 0x00, 0x08, 0x00, 0x14, 0x07, 0x00,
190
	0x30, 0x20, 0x00, 0x00, 0x00, 0x20, 0x00, 0x08,
191
	0x00, 0x1c, 0x07, 0x00, 0x30, 0x1a, 0x00, 0x00,
192
	0x00, 0x20, 0x00, 0x08, 0x00, 0x70, 0x0d, 0x00,
193
	0x30, 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x28,
194
	0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
195
	0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
196
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //end block 8
197
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
198
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
199
	0x00, 0x02, 0x00, 0x90, 0x00, 0x00, 0x00, 0x2b,
200
	0xff, 0x2b, 0xff, 0x2b, 0xed, 0x00, 0x00, 0x2b,
201
	0xfb, 0x00, 0x00, 0x2b, 0xc5, 0x00, 0x00, 0x2b,
202
	0x05, 0x80, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00,
203
	0x00, 0x24, 0xd3, 0x2e, 0xc0, 0x2c, 0x3b, 0x08,
204
	0xf0, 0x3b, 0x09, 0x24, 0xbb, 0x3b, 0x0b, 0x24, //end block 9
205
	0xaa, 0x3b, 0x1f, 0xf8, 0x00, 0x3b, 0x3f, 0xf0,
206
	0x00, 0x3b, 0x35, 0xc0, 0x00, 0x38, 0x80, 0x2c,
207
	0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x38,
208
	0x80, 0x2c, 0x70, 0x00, 0x00, 0x00, 0x00, 0xc0,
209
	0x3a, 0x80, 0x2c, 0x70, 0x00, 0x00, 0x00, 0x00,
210
	0xc0, 0x3b, 0x0a, 0x80, 0x2e, 0x83, 0x24, 0xdb,
211
	0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x2c,
212
	0x31, 0x83, 0x2c, 0x70, 0x00, 0x00, 0x00, 0x00, //end block 10
213
	0xcb, 0x33, 0x1b, 0x83, 0x2c, 0x70, 0x00, 0x00,
214
	0x00, 0x00, 0xcb, 0x31, 0x83, 0x2c, 0x70, 0x00,
215
	0x00, 0x00, 0x00, 0xcb, 0x00, 0x33, 0x1e, 0x83,
216
	0x2e, 0x25, 0xff, 0xc4, 0x00, 0x2f, 0x06, 0x84,
217
	0x2e, 0x00, 0x00, 0x10, 0x20, 0x29, 0x00, 0x04,
218
	0x00, 0x10, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00,
219
	0x00, 0x21, 0x00, 0x10, 0x00, 0x48, 0x03, 0x00,
220
	0x30, 0xff, 0xf0, 0xff, 0xff, 0x00, 0x00, 0x00, //end block 11
221
	0x00, 0x00, 0x04, 0x00, 0x00, 0x21, 0x00, 0x10,
222
	0x00, 0x4c, 0x03, 0x00, 0x30, 0xff, 0xf0, 0xff,
223
	0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00,
224
	0x00, 0x21, 0x00, 0x10, 0x00, 0x20, 0x03, 0x00,
225
	0x30, 0x7f, 0x00, 0xfc, 0xff, 0x00, 0x00, 0x00,
226
	0x00, 0x80, 0x10, 0x00, 0x00, 0x20, 0x00, 0x08,
227
	0x00, 0x24, 0x03, 0x00, 0x30, 0x04, 0x00, 0x00,
228
	0x00, 0x20, 0x00, 0x08, 0x00, 0x1c, 0x07, 0x00, //end block 12
229
	0x30, 0x1a, 0x00, 0x00, 0x00, 0x21, 0x00, 0x10,
230
	0x00, 0x20, 0x03, 0x00, 0x30, 0xc3, 0xff, 0xff,
231
	0xff, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00,
232
	0x00, 0x20, 0x00, 0x08, 0x00, 0x80, 0x03, 0x00,
233
	0x30, 0x01, 0x00, 0x00, 0x00
234
};
235
236
static unsigned char vfs0050_activate1[] =
237
{
238
      0x39, 0x20, 0xbf, 0x02, 0x00, 0xf4, 0x01, 0x00,
239
      0x00, 0x01, 0xd1, 0x00, 0x20, 0xd1, 0xd1, 0x00,
240
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
241
      0x00, 0xf4, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00,
242
      0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
243
      0x00, 0x00, 0x00, 0x00, 0x00, 0xf4, 0x01, 0x00,
244
      0x00, 0x02, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
245
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //end block 1
246
      0x00, 0xf4, 0x01, 0x00, 0x00, 0x02, 0xd1, 0x00,
247
      0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
248
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
249
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
250
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
251
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
252
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
253
      0x00, 0x00, 0x00, 0x00, 0x00
254
};
255
256
static unsigned char vfs0050_deactivate1[] =
257
{
258
    0x39, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
259
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
260
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
261
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
262
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
263
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
264
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
265
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //end block 1
266
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
267
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
268
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
269
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
270
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
271
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
272
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
273
    0x00, 0x00, 0x00, 0x00, 0x00
274
};
275
276
static unsigned char vfs0050_activate2[] =
277
{
278
      0x02, 0x94, 0x00, 0x00, 0x00, 0x20, 0x00, 0x08,
279
      0x00, 0x2c, 0x03, 0x00, 0x30, 0x1b, 0x00, 0x00,
280
      0x00, 0x20, 0x00, 0x08, 0x00, 0x20, 0x03, 0x00,
281
      0x30, 0x3d, 0x10, 0x00, 0x00, 0x20, 0x00, 0x08,
282
      0x00, 0x18, 0x03, 0x00, 0x30, 0x00, 0x00, 0x00,
283
      0x00, 0x20, 0x00, 0x08, 0x00, 0x24, 0x03, 0x00,
284
      0x30, 0x08, 0x00, 0x00, 0x00, 0x20, 0x00, 0x08,
285
      0x00, 0x28, 0x03, 0x00, 0x30, 0x08, 0x00, 0x00, //end block 1
286
      0x00, 0x20, 0x00, 0x08, 0x00, 0x30, 0x03, 0x00,
287
      0x30, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x08,
288
      0x00, 0x38, 0x03, 0x00, 0x30, 0x00, 0x00, 0x00,
289
      0x00, 0x20, 0x00, 0x08, 0x00, 0x3c, 0x03, 0x00,
290
      0x30, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x08,
291
      0x00, 0x44, 0x03, 0x00, 0x30, 0x14, 0x00, 0x00,
292
      0x00, 0x20, 0x00, 0x08, 0x00, 0x48, 0x03, 0x00,
293
      0x30, 0x01, 0x04, 0x02, 0x00, 0x20, 0x00, 0x08, //end block 2
294
      0x00, 0x4c, 0x03, 0x00, 0x30, 0x01, 0x0c, 0x02,
295
      0x00, 0x20, 0x00, 0x08, 0x00, 0x54, 0x03, 0x00,
296
      0x30, 0x20, 0x00, 0x00, 0x00, 0x20, 0x00, 0x08,
297
      0x00, 0x5c, 0x03, 0x00, 0x30, 0x90, 0x01, 0x02,
298
      0x00, 0x20, 0x00, 0x08, 0x00, 0x60, 0x03, 0x00,
299
      0x30, 0x2c, 0x01, 0x19, 0x00, 0x20, 0x00, 0x08,
300
      0x00, 0x64, 0x03, 0x00, 0x30, 0x00, 0x00, 0x00,
301
      0x00, 0x20, 0x00, 0x08, 0x00, 0x6c, 0x03, 0x00, //end block 3
302
      0x30, 0x1e, 0x00, 0x00, 0x00, 0x20, 0x00, 0x08,
303
      0x00, 0x70, 0x03, 0x00, 0x30, 0x21, 0x80, 0x00,
304
      0x00, 0x20, 0x00, 0x08, 0x00, 0x78, 0x03, 0x00,
305
      0x30, 0x09, 0x00, 0x02, 0x00, 0x20, 0x00, 0x08,
306
      0x00, 0x7c, 0x03, 0x00, 0x30, 0x0b, 0x00, 0x19,
307
      0x00, 0x20, 0x00, 0x08, 0x00, 0x80, 0x03, 0x00,
308
      0x30, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x08,
309
      0x00, 0x84, 0x03, 0x00, 0x30, 0x3a, 0x00, 0x00, //end block 4
310
      0x00, 0x20, 0x00, 0x08, 0x00, 0x88, 0x03, 0x00,
311
      0x30, 0x14, 0x00, 0x00, 0x00, 0x20, 0x00, 0x08,
312
      0x00, 0x8c, 0x03, 0x00, 0x30, 0x02, 0x00, 0x00,
313
      0x00, 0x20, 0x00, 0x08, 0x00, 0x90, 0x03, 0x00,
314
      0x30, 0x02, 0x00, 0x00, 0x00, 0x20, 0x00, 0x08,
315
      0x00, 0x94, 0x03, 0x00, 0x30, 0x08, 0x00, 0x00,
316
      0x00, 0x20, 0x00, 0x08, 0x00, 0x98, 0x03, 0x00,
317
      0x30, 0x00, 0x00, 0xa1, 0x01, 0x20, 0x00, 0x08, //end block 5
318
      0x00, 0x9c, 0x03, 0x00, 0x30, 0x00, 0x00, 0xa1,
319
      0x01, 0x20, 0x00, 0x08, 0x00, 0xa8, 0x03, 0x00,
320
      0x30, 0x64, 0x01, 0x00, 0x00, 0x20, 0x00, 0x08,
321
      0x00, 0xac, 0x03, 0x00, 0x30, 0x64, 0x01, 0x00,
322
      0x00, 0x20, 0x00, 0x08, 0x00, 0xb0, 0x03, 0x00,
323
      0x30, 0x00, 0x01, 0x00, 0x00, 0x20, 0x00, 0x08,
324
      0x00, 0xb4, 0x03, 0x00, 0x30, 0x00, 0x01, 0x00,
325
      0x00, 0x20, 0x00, 0x08, 0x00, 0xb8, 0x03, 0x00, //end block 6
326
      0x30, 0x05, 0x00, 0x00, 0x00, 0x20, 0x00, 0x08,
327
      0x00, 0xbc, 0x03, 0x00, 0x30, 0x05, 0x00, 0x00,
328
      0x00, 0x20, 0x00, 0x08, 0x00, 0xc0, 0x03, 0x00,
329
      0x30, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x08,
330
      0x00, 0x84, 0x03, 0x00, 0x30, 0x3b, 0x00, 0x00,
331
      0x00, 0x20, 0x00, 0x08, 0x00, 0x08, 0x07, 0x00,
332
      0x30, 0x03, 0x00, 0x00, 0x00, 0x20, 0x00, 0x08,
333
      0x00, 0x0c, 0x07, 0x00, 0x30, 0x00, 0x00, 0x00, //end block 7
334
      0x00, 0x20, 0x00, 0x08, 0x00, 0x14, 0x07, 0x00,
335
      0x30, 0x20, 0x00, 0x00, 0x00, 0x20, 0x00, 0x08,
336
      0x00, 0x1c, 0x07, 0x00, 0x30, 0x1a, 0x00, 0x00,
337
      0x00, 0x20, 0x00, 0x08, 0x00, 0x70, 0x0d, 0x00,
338
      0x30, 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x28,
339
      0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
340
      0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
341
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //end block 8
342
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
343
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
344
      0x00, 0x02, 0x00, 0x90, 0x00, 0x00, 0x00, 0x2b,
345
      0xff, 0x2b, 0xff, 0x2b, 0xed, 0x00, 0x00, 0x2b,
346
      0xfb, 0x00, 0x00, 0x2b, 0xc5, 0x00, 0x00, 0x2b,
347
      0x05, 0x80, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00,
348
      0x00, 0x24, 0xd3, 0x2e, 0xc0, 0x2c, 0x3b, 0x08,
349
      0xf0, 0x3b, 0x09, 0x24, 0xbb, 0x3b, 0x0b, 0x24, //end block 9
350
      0xaa, 0x3b, 0x1f, 0xf8, 0x00, 0x3b, 0x3f, 0xf0,
351
      0x00, 0x3b, 0x35, 0xc0, 0x00, 0x38, 0x80, 0x2c,
352
      0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x38,
353
      0x80, 0x2c, 0x70, 0x00, 0x00, 0x00, 0x00, 0xc0,
354
      0x3a, 0x80, 0x2c, 0x70, 0x00, 0x00, 0x00, 0x00,
355
      0xc0, 0x3b, 0x0a, 0x80, 0x2e, 0x83, 0x24, 0xdb,
356
      0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x2c,
357
      0x31, 0x83, 0x2c, 0x70, 0x00, 0x00, 0x00, 0x00, //end block 10
358
      0xcb, 0x33, 0x1b, 0x83, 0x2c, 0x70, 0x00, 0x00,
359
      0x00, 0x00, 0xcb, 0x31, 0x83, 0x2c, 0x70, 0x00,
360
      0x00, 0x00, 0x00, 0xcb, 0x00, 0x33, 0x1e, 0x83,
361
      0x2e, 0x25, 0xff, 0xc4, 0x00, 0x2f, 0x06, 0x84,
362
      0x2e, 0x00, 0x00, 0x10, 0x20, 0x29, 0x00, 0x04,
363
      0x00, 0x10, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00,
364
      0x00, 0x21, 0x00, 0x10, 0x00, 0x48, 0x03, 0x00,
365
      0x30, 0xff, 0xf0, 0xff, 0xff, 0x00, 0x00, 0x00, //end block 11
366
      0x00, 0x00, 0x04, 0x00, 0x00, 0x21, 0x00, 0x10,
367
      0x00, 0x4c, 0x03, 0x00, 0x30, 0xff, 0xf0, 0xff,
368
      0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00,
369
      0x00, 0x21, 0x00, 0x10, 0x00, 0x20, 0x03, 0x00,
370
      0x30, 0x7f, 0x00, 0xfc, 0xff, 0x00, 0x00, 0x00,
371
      0x00, 0x80, 0x10, 0x00, 0x00, 0x20, 0x00, 0x08,
372
      0x00, 0x24, 0x03, 0x00, 0x30, 0x04, 0x00, 0x00,
373
      0x00, 0x20, 0x00, 0x08, 0x00, 0x1c, 0x07, 0x00, //end block 12
374
      0x30, 0x1a, 0x00, 0x00, 0x00, 0x21, 0x00, 0x10,
375
      0x00, 0x20, 0x03, 0x00, 0x30, 0xc3, 0xff, 0xff,
376
      0xff, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00,
377
      0x00, 0x20, 0x00, 0x08, 0x00, 0x80, 0x03, 0x00,
378
      0x30, 0x02, 0x00, 0x00, 0x00, 0x24, 0x00, 0x8c,
379
      0x00, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77,
380
      0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77,
381
      0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, //end block 13
382
      0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77,
383
      0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77,
384
      0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77,
385
      0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77,
386
      0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77,
387
      0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77,
388
      0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77,
389
      0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, //end block 14
390
      0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77,
391
      0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77,
392
      0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77,
393
      0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77,
394
      0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77,
395
      0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77,
396
      0x77, 0x77, 0x77, 0x77, 0x77, 0x26, 0x00, 0x28,
397
      0x00, 0xff, 0x00, 0x0f, 0x00, 0xf0, 0xf0, 0x0f, //end block 15
398
      0x00, 0x20, 0x00, 0x00, 0x00, 0x30, 0x01, 0x02,
399
      0x00, 0x2c, 0x01, 0x28, 0x00, 0x20, 0x80, 0x00,
400
      0x00, 0x0a, 0x00, 0x02, 0x00, 0x0b, 0x00, 0x19,
401
      0x00, 0x40, 0x1f, 0x10, 0x27, 0x00, 0x0f, 0x03,
402
      0x00
403
};
404
(-)a/libfprint/drivers/vfs101.c (-7 / +1 lines)
Lines 64-72 Link Here
64
/* Best image contrast */
64
/* Best image contrast */
65
#define VFS_IMG_BEST_CONRAST	128
65
#define VFS_IMG_BEST_CONRAST	128
66
66
67
/* Number of enroll stages */
68
#define VFS_NR_ENROLL		3
69
70
/* Device parameters address */
67
/* Device parameters address */
71
#define VFS_PAR_000E			0x000e
68
#define VFS_PAR_000E			0x000e
72
#define VFS_PAR_0011			0x0011
69
#define VFS_PAR_0011			0x0011
Lines 656-662 static int action_completed(struct fp_img_dev *dev) Link Here
656
	struct vfs101_dev *vdev = dev->priv;
653
	struct vfs101_dev *vdev = dev->priv;
657
654
658
	if ((dev->action == IMG_ACTION_ENROLL) &&
655
	if ((dev->action == IMG_ACTION_ENROLL) &&
659
		(vdev->enroll_stage < VFS_NR_ENROLL))
656
		(vdev->enroll_stage < 1))
660
		/* Enroll not completed, return false */
657
		/* Enroll not completed, return false */
661
		return FALSE;
658
		return FALSE;
662
659
Lines 1511-1519 static int dev_open(struct fp_img_dev *dev, unsigned long driver_data) Link Here
1511
		return r;
1508
		return r;
1512
	}
1509
	}
1513
1510
1514
	/* Set enroll stage number */
1515
	dev->dev->nr_enroll_stages = VFS_NR_ENROLL;
1516
1517
	/* Initialize private structure */
1511
	/* Initialize private structure */
1518
	vdev = g_malloc0(sizeof(struct vfs101_dev));
1512
	vdev = g_malloc0(sizeof(struct vfs101_dev));
1519
	vdev->seqnum = -1;
1513
	vdev->seqnum = -1;
(-)a/libfprint/drivers/vfs301.c (-3 lines)
Lines 244-252 static int dev_open(struct fp_img_dev *dev, unsigned long driver_data) Link Here
244
		return r;
244
		return r;
245
	}
245
	}
246
246
247
	/* Set enroll stage number */
248
	dev->dev->nr_enroll_stages = 1;
249
250
	/* Initialize private structure */
247
	/* Initialize private structure */
251
	vdev = g_malloc0(sizeof(vfs301_dev_t));
248
	vdev = g_malloc0(sizeof(vfs301_dev_t));
252
	dev->priv = vdev;
249
	dev->priv = vdev;
(-)a/libfprint/fp_internal.h (-7 / +45 lines)
Lines 91-96 enum fp_dev_state { Link Here
91
	DEV_STATE_IDENTIFYING,
91
	DEV_STATE_IDENTIFYING,
92
	DEV_STATE_IDENTIFY_DONE,
92
	DEV_STATE_IDENTIFY_DONE,
93
	DEV_STATE_IDENTIFY_STOPPING,
93
	DEV_STATE_IDENTIFY_STOPPING,
94
	DEV_STATE_CAPTURE_STARTING,
95
	DEV_STATE_CAPTURING,
96
	DEV_STATE_CAPTURE_DONE,
97
	DEV_STATE_CAPTURE_STOPPING,
94
};
98
};
95
99
96
struct fp_driver **fprint_get_drivers (void);
100
struct fp_driver **fprint_get_drivers (void);
Lines 108-115 struct fp_dev { Link Here
108
112
109
	/* drivers should not mess with any of the below */
113
	/* drivers should not mess with any of the below */
110
	enum fp_dev_state state;
114
	enum fp_dev_state state;
111
112
	int __enroll_stage;
115
	int __enroll_stage;
116
	int unconditional_capture;
113
117
114
	/* async I/O callbacks and data */
118
	/* async I/O callbacks and data */
115
	/* FIXME: convert this to generic state operational data mechanism? */
119
	/* FIXME: convert this to generic state operational data mechanism? */
Lines 129-134 struct fp_dev { Link Here
129
	void *identify_cb_data;
133
	void *identify_cb_data;
130
	fp_identify_stop_cb identify_stop_cb;
134
	fp_identify_stop_cb identify_stop_cb;
131
	void *identify_stop_cb_data;
135
	void *identify_stop_cb_data;
136
	fp_capture_cb capture_cb;
137
	void *capture_cb_data;
138
	fp_capture_stop_cb capture_stop_cb;
139
	void *capture_stop_cb_data;
132
140
133
	/* FIXME: better place to put this? */
141
	/* FIXME: better place to put this? */
134
	struct fp_print_data **identify_gallery;
142
	struct fp_print_data **identify_gallery;
Lines 146-151 enum fp_imgdev_action { Link Here
146
	IMG_ACTION_ENROLL,
154
	IMG_ACTION_ENROLL,
147
	IMG_ACTION_VERIFY,
155
	IMG_ACTION_VERIFY,
148
	IMG_ACTION_IDENTIFY,
156
	IMG_ACTION_IDENTIFY,
157
	IMG_ACTION_CAPTURE,
149
};
158
};
150
159
151
enum fp_imgdev_enroll_state {
160
enum fp_imgdev_enroll_state {
Lines 170-176 struct fp_img_dev { Link Here
170
	int action_state;
179
	int action_state;
171
180
172
	struct fp_print_data *acquire_data;
181
	struct fp_print_data *acquire_data;
182
	struct fp_print_data *enroll_data;
173
	struct fp_img *acquire_img;
183
	struct fp_img *acquire_img;
184
	int enroll_stage;
174
	int action_result;
185
	int action_result;
175
186
176
	/* FIXME: better place to put this? */
187
	/* FIXME: better place to put this? */
Lines 179-186 struct fp_img_dev { Link Here
179
	void *priv;
190
	void *priv;
180
};
191
};
181
192
182
int fpi_imgdev_capture(struct fp_img_dev *imgdev, int unconditional,
183
	struct fp_img **image);
184
int fpi_imgdev_get_img_width(struct fp_img_dev *imgdev);
193
int fpi_imgdev_get_img_width(struct fp_img_dev *imgdev);
185
int fpi_imgdev_get_img_height(struct fp_img_dev *imgdev);
194
int fpi_imgdev_get_img_height(struct fp_img_dev *imgdev);
186
195
Lines 215-220 struct fp_driver { Link Here
215
	int (*verify_stop)(struct fp_dev *dev, gboolean iterating);
224
	int (*verify_stop)(struct fp_dev *dev, gboolean iterating);
216
	int (*identify_start)(struct fp_dev *dev);
225
	int (*identify_start)(struct fp_dev *dev);
217
	int (*identify_stop)(struct fp_dev *dev, gboolean iterating);
226
	int (*identify_stop)(struct fp_dev *dev, gboolean iterating);
227
	int (*capture_start)(struct fp_dev *dev);
228
	int (*capture_stop)(struct fp_dev *dev);
218
};
229
};
219
230
220
enum fp_print_data_type fpi_driver_get_data_type(struct fp_driver *drv);
231
enum fp_print_data_type fpi_driver_get_data_type(struct fp_driver *drv);
Lines 267-272 extern struct fp_img_driver aes2550_driver; Link Here
267
#ifdef ENABLE_AES2660
278
#ifdef ENABLE_AES2660
268
extern struct fp_img_driver aes2660_driver;
279
extern struct fp_img_driver aes2660_driver;
269
#endif
280
#endif
281
#ifdef ENABLE_AES3500
282
extern struct fp_img_driver aes3500_driver;
283
#endif
270
#ifdef ENABLE_AES4000
284
#ifdef ENABLE_AES4000
271
extern struct fp_img_driver aes4000_driver;
285
extern struct fp_img_driver aes4000_driver;
272
#endif
286
#endif
Lines 282-287 extern struct fp_img_driver vfs101_driver; Link Here
282
#ifdef ENABLE_VFS301
296
#ifdef ENABLE_VFS301
283
extern struct fp_img_driver vfs301_driver;
297
extern struct fp_img_driver vfs301_driver;
284
#endif
298
#endif
299
#ifdef ENABLE_UPEKTC_IMG
300
extern struct fp_img_driver upektc_img_driver;
301
#endif
302
#ifdef ENABLE_ETES603
303
extern struct fp_img_driver etes603_driver;
304
#endif
305
#ifdef ENABLE_VFS0050
306
extern struct fp_img_driver vfs0050_driver;
307
#endif
285
308
286
extern libusb_context *fpi_usb_ctx;
309
extern libusb_context *fpi_usb_ctx;
287
extern GSList *opened_devices;
310
extern GSList *opened_devices;
Lines 310-324 enum fp_print_data_type { Link Here
310
	PRINT_DATA_NBIS_MINUTIAE,
333
	PRINT_DATA_NBIS_MINUTIAE,
311
};
334
};
312
335
336
struct fp_print_data_item {
337
	size_t length;
338
	unsigned char data[0];
339
};
340
313
struct fp_print_data {
341
struct fp_print_data {
314
	uint16_t driver_id;
342
	uint16_t driver_id;
315
	uint32_t devtype;
343
	uint32_t devtype;
316
	enum fp_print_data_type type;
344
	enum fp_print_data_type type;
317
	size_t length;
345
	GSList *prints;
318
	unsigned char data[0];
319
};
346
};
320
347
321
struct fpi_print_data_fp1 {
348
struct fpi_print_data_fp2 {
322
	char prefix[3];
349
	char prefix[3];
323
	uint16_t driver_id;
350
	uint16_t driver_id;
324
	uint32_t devtype;
351
	uint32_t devtype;
Lines 326-333 struct fpi_print_data_fp1 { Link Here
326
	unsigned char data[0];
353
	unsigned char data[0];
327
} __attribute__((__packed__));
354
} __attribute__((__packed__));
328
355
356
struct fpi_print_data_item_fp2 {
357
	uint32_t length;
358
	unsigned char data[0];
359
} __attribute__((__packed__));
360
329
void fpi_data_exit(void);
361
void fpi_data_exit(void);
330
struct fp_print_data *fpi_print_data_new(struct fp_dev *dev, size_t length);
362
struct fp_print_data *fpi_print_data_new(struct fp_dev *dev);
363
struct fp_print_data_item *fpi_print_data_item_new(size_t length);
331
gboolean fpi_print_data_compatible(uint16_t driver_id1, uint32_t devtype1,
364
gboolean fpi_print_data_compatible(uint16_t driver_id1, uint32_t devtype1,
332
	enum fp_print_data_type type1, uint16_t driver_id2, uint32_t devtype2,
365
	enum fp_print_data_type type1, uint16_t driver_id2, uint32_t devtype2,
333
	enum fp_print_data_type type2);
366
	enum fp_print_data_type type2);
Lines 436-441 void fpi_drvcb_report_identify_result(struct fp_dev *dev, int result, Link Here
436
	size_t match_offset, struct fp_img *img);
469
	size_t match_offset, struct fp_img *img);
437
void fpi_drvcb_identify_stopped(struct fp_dev *dev);
470
void fpi_drvcb_identify_stopped(struct fp_dev *dev);
438
471
472
void fpi_drvcb_capture_started(struct fp_dev *dev, int status);
473
void fpi_drvcb_report_capture_result(struct fp_dev *dev, int result,
474
	struct fp_img *img);
475
void fpi_drvcb_capture_stopped(struct fp_dev *dev);
476
439
/* for image drivers */
477
/* for image drivers */
440
void fpi_imgdev_open_complete(struct fp_img_dev *imgdev, int status);
478
void fpi_imgdev_open_complete(struct fp_img_dev *imgdev, int status);
441
void fpi_imgdev_close_complete(struct fp_img_dev *imgdev);
479
void fpi_imgdev_close_complete(struct fp_img_dev *imgdev);
(-)a/libfprint/fprint.h (+18 lines)
Lines 107-112 uint32_t fp_dev_get_devtype(struct fp_dev *dev); Link Here
107
int fp_dev_supports_print_data(struct fp_dev *dev, struct fp_print_data *data);
107
int fp_dev_supports_print_data(struct fp_dev *dev, struct fp_print_data *data);
108
int fp_dev_supports_dscv_print(struct fp_dev *dev, struct fp_dscv_print *print);
108
int fp_dev_supports_dscv_print(struct fp_dev *dev, struct fp_dscv_print *print);
109
109
110
/** \ingroup dev
111
 * Image capture result codes returned from fp_dev_img_capture().
112
 */
113
enum fp_capture_result {
114
	/** Capture completed successfully, the capture data has been
115
	 * returned to the caller. */
116
	FP_CAPTURE_COMPLETE = 0,
117
	/** Capture failed for some reason */
118
	FP_CAPTURE_FAIL,
119
};
120
110
int fp_dev_supports_imaging(struct fp_dev *dev);
121
int fp_dev_supports_imaging(struct fp_dev *dev);
111
int fp_dev_img_capture(struct fp_dev *dev, int unconditional,
122
int fp_dev_img_capture(struct fp_dev *dev, int unconditional,
112
	struct fp_img **image);
123
	struct fp_img **image);
Lines 340-345 typedef void (*fp_identify_stop_cb)(struct fp_dev *dev, void *user_data); Link Here
340
int fp_async_identify_stop(struct fp_dev *dev, fp_identify_stop_cb callback,
351
int fp_async_identify_stop(struct fp_dev *dev, fp_identify_stop_cb callback,
341
	void *user_data);
352
	void *user_data);
342
353
354
typedef void (*fp_capture_cb)(struct fp_dev *dev, int result,
355
	struct fp_img *img, void *user_data);
356
int fp_async_capture_start(struct fp_dev *dev, int unconditional, fp_capture_cb callback, void *user_data);
357
358
typedef void (*fp_capture_stop_cb)(struct fp_dev *dev, void *user_data);
359
int fp_async_capture_stop(struct fp_dev *dev, fp_capture_stop_cb callback, void *user_data);
360
343
#ifdef __cplusplus
361
#ifdef __cplusplus
344
}
362
}
345
#endif
363
#endif
(-)a/libfprint/gdkpixbuf.c (-88 lines)
Lines 1-88 Link Here
1
/*
2
 * Imaging utility functions for libfprint
3
 * Copyright (C) 2007-2008 Daniel Drake <dsd@gentoo.org>
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
#include <errno.h>
21
#include <gdk-pixbuf/gdk-pixbuf.h>
22
23
#include "fp_internal.h"
24
25
struct fp_img *fpi_im_resize(struct fp_img *img, unsigned int w_factor, unsigned int h_factor)
26
{
27
	int new_width = img->width * w_factor;
28
	int new_height = img->height * h_factor;
29
	GdkPixbuf *orig, *resized;
30
	struct fp_img *newimg;
31
	guchar *pixels;
32
	guint y;
33
	int rowstride;
34
35
	g_type_init ();
36
37
	/* It is possible to implement resizing using a simple algorithm, however
38
	 * we use gdk-pixbuf because it applies some kind of smoothing to the
39
	 * result, which improves matching performances in my experiments. */
40
41
	/* Create the original pixbuf, and fill it in from the grayscale data */
42
	orig = gdk_pixbuf_new (GDK_COLORSPACE_RGB,
43
			       FALSE,
44
			       8,
45
			       img->width,
46
			       img->height);
47
	rowstride = gdk_pixbuf_get_rowstride (orig);
48
	pixels = gdk_pixbuf_get_pixels (orig);
49
	for (y = 0; y < img->height; y++) {
50
		guint x;
51
		for (x = 0; x < img->width; x++) {
52
			guchar *p, *r;
53
54
			p = pixels + y * rowstride + x * 3;
55
			r = img->data + y * img->width + x;
56
			p[0] = r[0];
57
			p[1] = r[0];
58
			p[2] = r[0];
59
		}
60
	}
61
62
	/* Resize the pixbuf, and create the new fp_img */
63
	resized = gdk_pixbuf_scale_simple (orig, new_width, new_height, GDK_INTERP_HYPER);
64
	g_object_unref (orig);
65
66
	newimg = fpi_img_new(new_width * new_height);
67
	newimg->width = new_width;
68
	newimg->height = new_height;
69
	newimg->flags = img->flags;
70
71
	rowstride = gdk_pixbuf_get_rowstride (resized);
72
	pixels = gdk_pixbuf_get_pixels (resized);
73
	for (y = 0; y < newimg->height; y++) {
74
		guint x;
75
		for (x = 0; x < newimg->width; x++) {
76
			guchar *p, *r;
77
78
			r = newimg->data + y * newimg->width + x;
79
			p = pixels + y * rowstride + x * 3;
80
			r[0] = p[0];
81
		}
82
	}
83
84
	g_object_unref (resized);
85
86
	return newimg;
87
}
88
(-)a/libfprint/imagemagick.c (-67 lines)
Lines 1-67 Link Here
1
/*
2
 * Imaging utility functions for libfprint
3
 * Copyright (C) 2007-2008 Daniel Drake <dsd@gentoo.org>
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
#include <errno.h>
21
#include <magick/ImageMagick.h>
22
23
#include "fp_internal.h"
24
25
struct fp_img *fpi_im_resize(struct fp_img *img, unsigned int w_factor, unsigned int h_factor)
26
{
27
	Image *mimg;
28
	Image *resized;
29
	ExceptionInfo exception;
30
	MagickBooleanType ret;
31
	int new_width = img->width * w_factor;
32
	int new_height = img->height * h_factor;
33
	struct fp_img *newimg;
34
35
	/* It is possible to implement resizing using a simple algorithm, however
36
	 * we use ImageMagick because it applies some kind of smoothing to the
37
	 * result, which improves matching performances in my experiments. */
38
39
	if (!IsMagickInstantiated())
40
		InitializeMagick(NULL);
41
	
42
	GetExceptionInfo(&exception);
43
	mimg = ConstituteImage(img->width, img->height, "I", CharPixel, img->data,
44
		&exception);
45
46
	GetExceptionInfo(&exception);
47
	resized = ResizeImage(mimg, new_width, new_height, 0, 1.0, &exception);
48
49
	newimg = fpi_img_new(new_width * new_height);
50
	newimg->width = new_width;
51
	newimg->height = new_height;
52
	newimg->flags = img->flags;
53
54
	GetExceptionInfo(&exception);
55
	ret = ExportImagePixels(resized, 0, 0, new_width, new_height, "I",
56
		CharPixel, newimg->data, &exception);
57
	if (ret != MagickTrue) {
58
		fp_err("export failed");
59
		return NULL;
60
	}
61
62
	DestroyImage(mimg);
63
	DestroyImage(resized);
64
65
	return newimg;
66
}
67
(-)a/libfprint/img.c (-22 / +56 lines)
Lines 313-318 int fpi_img_to_print_data(struct fp_img_dev *imgdev, struct fp_img *img, Link Here
313
	struct fp_print_data **ret)
313
	struct fp_print_data **ret)
314
{
314
{
315
	struct fp_print_data *print;
315
	struct fp_print_data *print;
316
	struct fp_print_data_item *item;
316
	int r;
317
	int r;
317
318
318
	if (!img->minutiae) {
319
	if (!img->minutiae) {
Lines 327-335 int fpi_img_to_print_data(struct fp_img_dev *imgdev, struct fp_img *img, Link Here
327
328
328
	/* FIXME: space is wasted if we dont hit the max minutiae count. would
329
	/* FIXME: space is wasted if we dont hit the max minutiae count. would
329
	 * be good to make this dynamic. */
330
	 * be good to make this dynamic. */
330
	print = fpi_print_data_new(imgdev->dev, sizeof(struct xyt_struct));
331
	print = fpi_print_data_new(imgdev->dev);
332
	item = fpi_print_data_item_new(sizeof(struct xyt_struct));
331
	print->type = PRINT_DATA_NBIS_MINUTIAE;
333
	print->type = PRINT_DATA_NBIS_MINUTIAE;
332
	minutiae_to_xyt(img->minutiae, img->width, img->height, print->data);
334
	minutiae_to_xyt(img->minutiae, img->width, img->height, item->data);
335
	print->prints = g_slist_prepend(print->prints, item);
333
336
334
	/* FIXME: the print buffer at this point is endian-specific, and will
337
	/* FIXME: the print buffer at this point is endian-specific, and will
335
	 * only work when loaded onto machines with identical endianness. not good!
338
	 * only work when loaded onto machines with identical endianness. not good!
Lines 342-383 int fpi_img_to_print_data(struct fp_img_dev *imgdev, struct fp_img *img, Link Here
342
int fpi_img_compare_print_data(struct fp_print_data *enrolled_print,
345
int fpi_img_compare_print_data(struct fp_print_data *enrolled_print,
343
	struct fp_print_data *new_print)
346
	struct fp_print_data *new_print)
344
{
347
{
345
	struct xyt_struct *gstruct = (struct xyt_struct *) enrolled_print->data;
348
	int score, max_score = 0, probe_len;
346
	struct xyt_struct *pstruct = (struct xyt_struct *) new_print->data;
349
	struct xyt_struct *pstruct = NULL;
347
	GTimer *timer;
350
	struct xyt_struct *gstruct = NULL;
348
	int r;
351
	struct fp_print_data_item *data_item;
352
	GSList *list_item;
349
353
350
	if (enrolled_print->type != PRINT_DATA_NBIS_MINUTIAE ||
354
	if (enrolled_print->type != PRINT_DATA_NBIS_MINUTIAE ||
351
			new_print->type != PRINT_DATA_NBIS_MINUTIAE) {
355
	     new_print->type != PRINT_DATA_NBIS_MINUTIAE) {
352
		fp_err("invalid print format");
356
		fp_err("invalid print format");
353
		return -EINVAL;
357
		return -EINVAL;
354
	}
358
	}
355
359
356
	timer = g_timer_new();
360
	if (g_slist_length(new_print->prints) != 1) {
357
	r = bozorth_main(pstruct, gstruct);
361
		fp_err("new_print contains more than one sample, is it enrolled print?");
358
	g_timer_stop(timer);
362
		return -EINVAL;
359
	fp_dbg("bozorth processing took %f seconds, score=%d",
363
	}
360
		g_timer_elapsed(timer, NULL), r);
361
	g_timer_destroy(timer);
362
364
363
	return r;
365
	data_item = new_print->prints->data;
366
	pstruct = (struct xyt_struct *)data_item->data;
367
368
	probe_len = bozorth_probe_init(pstruct);
369
	list_item = enrolled_print->prints;
370
	do {
371
		data_item = list_item->data;
372
		gstruct = (struct xyt_struct *)data_item->data;
373
		score = bozorth_to_gallery(probe_len, pstruct, gstruct);
374
		fp_dbg("score %d", score);
375
		max_score = max(score, max_score);
376
		list_item = g_slist_next(list_item);
377
	} while (list_item);
378
379
	return max_score;
364
}
380
}
365
381
366
int fpi_img_compare_print_data_to_gallery(struct fp_print_data *print,
382
int fpi_img_compare_print_data_to_gallery(struct fp_print_data *print,
367
	struct fp_print_data **gallery, int match_threshold, size_t *match_offset)
383
	struct fp_print_data **gallery, int match_threshold, size_t *match_offset)
368
{
384
{
369
	struct xyt_struct *pstruct = (struct xyt_struct *) print->data;
385
	struct xyt_struct *pstruct;
386
	struct xyt_struct *gstruct;
370
	struct fp_print_data *gallery_print;
387
	struct fp_print_data *gallery_print;
371
	int probe_len = bozorth_probe_init(pstruct);
388
	struct fp_print_data_item *data_item;
389
	int probe_len;
372
	size_t i = 0;
390
	size_t i = 0;
391
	int r;
392
	GSList *list_item;
393
394
	if (g_slist_length(print->prints) != 1) {
395
		fp_err("new_print contains more than one sample, is it enrolled print?");
396
		return -EINVAL;
397
	}
398
399
	data_item = print->prints->data;
400
	pstruct = (struct xyt_struct *)data_item->data;
373
401
402
	probe_len = bozorth_probe_init(pstruct);
374
	while ((gallery_print = gallery[i++])) {
403
	while ((gallery_print = gallery[i++])) {
375
		struct xyt_struct *gstruct = (struct xyt_struct *) gallery_print->data;
404
		list_item = gallery_print->prints;
376
		int r = bozorth_to_gallery(probe_len, pstruct, gstruct);
405
		do {
377
		if (r >= match_threshold) {
406
			data_item = list_item->data;
378
			*match_offset = i - 1;
407
			gstruct = (struct xyt_struct *)data_item->data;
379
			return FP_VERIFY_MATCH;
408
			r = bozorth_to_gallery(probe_len, pstruct, gstruct);
380
		}
409
			if (r >= match_threshold) {
410
				*match_offset = i - 1;
411
				return FP_VERIFY_MATCH;
412
			}
413
			list_item = g_slist_next(list_item);
414
		} while (list_item);
381
	}
415
	}
382
	return FP_VERIFY_NO_MATCH;
416
	return FP_VERIFY_NO_MATCH;
383
}
417
}
(-)a/libfprint/imgdev.c (-15 / +76 lines)
Lines 25-30 Link Here
25
25
26
#define MIN_ACCEPTABLE_MINUTIAE 10
26
#define MIN_ACCEPTABLE_MINUTIAE 10
27
#define BOZORTH3_DEFAULT_THRESHOLD 40
27
#define BOZORTH3_DEFAULT_THRESHOLD 40
28
#define IMG_ENROLL_STAGES 5
28
29
29
static int img_dev_open(struct fp_dev *dev, unsigned long driver_data)
30
static int img_dev_open(struct fp_dev *dev, unsigned long driver_data)
30
{
31
{
Lines 33-40 static int img_dev_open(struct fp_dev *dev, unsigned long driver_data) Link Here
33
	int r = 0;
34
	int r = 0;
34
35
35
	imgdev->dev = dev;
36
	imgdev->dev = dev;
37
	imgdev->enroll_stage = 0;
36
	dev->priv = imgdev;
38
	dev->priv = imgdev;
37
	dev->nr_enroll_stages = 1;
39
	dev->nr_enroll_stages = IMG_ENROLL_STAGES;
38
40
39
	/* for consistency in driver code, allow udev access through imgdev */
41
	/* for consistency in driver code, allow udev access through imgdev */
40
	imgdev->udev = dev->udev;
42
	imgdev->udev = dev->udev;
Lines 144-150 void fpi_imgdev_report_finger_status(struct fp_img_dev *imgdev, Link Here
144
	switch (imgdev->action) {
146
	switch (imgdev->action) {
145
	case IMG_ACTION_ENROLL:
147
	case IMG_ACTION_ENROLL:
146
		fp_dbg("reporting enroll result");
148
		fp_dbg("reporting enroll result");
147
		fpi_drvcb_enroll_stage_completed(imgdev->dev, r, data, img);
149
		data = imgdev->enroll_data;
150
		if (r == FP_ENROLL_COMPLETE) {
151
			imgdev->enroll_data = NULL;
152
		}
153
		fpi_drvcb_enroll_stage_completed(imgdev->dev, r,
154
			r == FP_ENROLL_COMPLETE ? data : NULL,
155
			img);
148
		/* the callback can cancel enrollment, so recheck current
156
		/* the callback can cancel enrollment, so recheck current
149
		 * action and the status to see if retry is needed */
157
		 * action and the status to see if retry is needed */
150
		if (imgdev->action == IMG_ACTION_ENROLL &&
158
		if (imgdev->action == IMG_ACTION_ENROLL &&
Lines 163-168 void fpi_imgdev_report_finger_status(struct fp_img_dev *imgdev, Link Here
163
			imgdev->identify_match_offset, img);
171
			imgdev->identify_match_offset, img);
164
		fp_print_data_free(data);
172
		fp_print_data_free(data);
165
		break;
173
		break;
174
	case IMG_ACTION_CAPTURE:
175
		fpi_drvcb_report_capture_result(imgdev->dev, r, img);
176
		break;
166
	default:
177
	default:
167
		fp_err("unhandled action %d", imgdev->action);
178
		fp_err("unhandled action %d", imgdev->action);
168
		break;
179
		break;
Lines 231-254 void fpi_imgdev_image_captured(struct fp_img_dev *imgdev, struct fp_img *img) Link Here
231
242
232
	fp_img_standardize(img);
243
	fp_img_standardize(img);
233
	imgdev->acquire_img = img;
244
	imgdev->acquire_img = img;
234
	r = fpi_img_to_print_data(imgdev, img, &print);
245
	if (imgdev->action != IMG_ACTION_CAPTURE) {
235
	if (r < 0) {
246
		r = fpi_img_to_print_data(imgdev, img, &print);
236
		fp_dbg("image to print data conversion error: %d", r);
247
		if (r < 0) {
237
		imgdev->action_result = FP_ENROLL_RETRY;
248
			fp_dbg("image to print data conversion error: %d", r);
238
		goto next_state;
249
			imgdev->action_result = FP_ENROLL_RETRY;
239
	} else if (img->minutiae->num < MIN_ACCEPTABLE_MINUTIAE) {
250
			goto next_state;
240
		fp_dbg("not enough minutiae, %d/%d", img->minutiae->num,
251
		} else if (img->minutiae->num < MIN_ACCEPTABLE_MINUTIAE) {
241
			MIN_ACCEPTABLE_MINUTIAE);
252
			fp_dbg("not enough minutiae, %d/%d", img->minutiae->num,
242
		fp_print_data_free(print);
253
				MIN_ACCEPTABLE_MINUTIAE);
243
		/* depends on FP_ENROLL_RETRY == FP_VERIFY_RETRY */
254
			fp_print_data_free(print);
244
		imgdev->action_result = FP_ENROLL_RETRY;
255
			/* depends on FP_ENROLL_RETRY == FP_VERIFY_RETRY */
245
		goto next_state;
256
			imgdev->action_result = FP_ENROLL_RETRY;
257
			goto next_state;
258
		}
246
	}
259
	}
247
260
248
	imgdev->acquire_data = print;
261
	imgdev->acquire_data = print;
249
	switch (imgdev->action) {
262
	switch (imgdev->action) {
250
	case IMG_ACTION_ENROLL:
263
	case IMG_ACTION_ENROLL:
251
		imgdev->action_result = FP_ENROLL_COMPLETE;
264
		if (!imgdev->enroll_data) {
265
			imgdev->enroll_data = fpi_print_data_new(imgdev->dev);
266
		}
267
		BUG_ON(g_slist_length(print->prints) != 1);
268
		/* Move print data from acquire data into enroll_data */
269
		imgdev->enroll_data->prints =
270
			g_slist_prepend(imgdev->enroll_data->prints, print->prints->data);
271
		print->prints = g_slist_remove(print->prints, print->prints->data);
272
273
		fp_print_data_free(imgdev->acquire_data);
274
		imgdev->acquire_data = NULL;
275
		imgdev->enroll_stage++;
276
		if (imgdev->enroll_stage == imgdev->dev->nr_enroll_stages)
277
			imgdev->action_result = FP_ENROLL_COMPLETE;
278
		else
279
			imgdev->action_result = FP_ENROLL_PASS;
252
		break;
280
		break;
253
	case IMG_ACTION_VERIFY:
281
	case IMG_ACTION_VERIFY:
254
		verify_process_img(imgdev);
282
		verify_process_img(imgdev);
Lines 256-261 void fpi_imgdev_image_captured(struct fp_img_dev *imgdev, struct fp_img *img) Link Here
256
	case IMG_ACTION_IDENTIFY:
284
	case IMG_ACTION_IDENTIFY:
257
		identify_process_img(imgdev);
285
		identify_process_img(imgdev);
258
		break;
286
		break;
287
	case IMG_ACTION_CAPTURE:
288
		imgdev->action_result = FP_CAPTURE_COMPLETE;
289
		break;
259
	default:
290
	default:
260
		BUG();
291
		BUG();
261
		break;
292
		break;
Lines 280-285 void fpi_imgdev_session_error(struct fp_img_dev *imgdev, int error) Link Here
280
	case IMG_ACTION_IDENTIFY:
311
	case IMG_ACTION_IDENTIFY:
281
		fpi_drvcb_report_identify_result(imgdev->dev, error, 0, NULL);
312
		fpi_drvcb_report_identify_result(imgdev->dev, error, 0, NULL);
282
		break;
313
		break;
314
	case IMG_ACTION_CAPTURE:
315
		fpi_drvcb_report_capture_result(imgdev->dev, error, NULL);
316
		break;
283
	default:
317
	default:
284
		fp_err("unhandled action %d", imgdev->action);
318
		fp_err("unhandled action %d", imgdev->action);
285
		break;
319
		break;
Lines 300-305 void fpi_imgdev_activate_complete(struct fp_img_dev *imgdev, int status) Link Here
300
	case IMG_ACTION_IDENTIFY:
334
	case IMG_ACTION_IDENTIFY:
301
		fpi_drvcb_identify_started(imgdev->dev, status);
335
		fpi_drvcb_identify_started(imgdev->dev, status);
302
		break;
336
		break;
337
	case IMG_ACTION_CAPTURE:
338
		fpi_drvcb_capture_started(imgdev->dev, status);
339
		break;
303
	default:
340
	default:
304
		fp_err("unhandled action %d", imgdev->action);
341
		fp_err("unhandled action %d", imgdev->action);
305
		return;
342
		return;
Lines 325-330 void fpi_imgdev_deactivate_complete(struct fp_img_dev *imgdev) Link Here
325
	case IMG_ACTION_IDENTIFY:
362
	case IMG_ACTION_IDENTIFY:
326
		fpi_drvcb_identify_stopped(imgdev->dev);
363
		fpi_drvcb_identify_stopped(imgdev->dev);
327
		break;
364
		break;
365
	case IMG_ACTION_CAPTURE:
366
		fpi_drvcb_capture_stopped(imgdev->dev);
367
		break;
328
	default:
368
	default:
329
		fp_err("unhandled action %d", imgdev->action);
369
		fp_err("unhandled action %d", imgdev->action);
330
		break;
370
		break;
Lines 385-390 static int generic_acquire_start(struct fp_dev *dev, int action) Link Here
385
	fp_dbg("action %d", action);
425
	fp_dbg("action %d", action);
386
	imgdev->action = action;
426
	imgdev->action = action;
387
	imgdev->action_state = IMG_ACQUIRE_STATE_ACTIVATING;
427
	imgdev->action_state = IMG_ACQUIRE_STATE_ACTIVATING;
428
	imgdev->enroll_stage = 0;
388
429
389
	r = dev_activate(imgdev, IMGDEV_STATE_AWAIT_FINGER_ON);
430
	r = dev_activate(imgdev, IMGDEV_STATE_AWAIT_FINGER_ON);
390
	if (r < 0)
431
	if (r < 0)
Lines 400-407 static void generic_acquire_stop(struct fp_img_dev *imgdev) Link Here
400
	dev_deactivate(imgdev);
441
	dev_deactivate(imgdev);
401
442
402
	fp_print_data_free(imgdev->acquire_data);
443
	fp_print_data_free(imgdev->acquire_data);
444
	fp_print_data_free(imgdev->enroll_data);
403
	fp_img_free(imgdev->acquire_img);
445
	fp_img_free(imgdev->acquire_img);
404
	imgdev->acquire_data = NULL;
446
	imgdev->acquire_data = NULL;
447
	imgdev->enroll_data = NULL;
405
	imgdev->acquire_img = NULL;
448
	imgdev->acquire_img = NULL;
406
	imgdev->action_result = 0;
449
	imgdev->action_result = 0;
407
}
450
}
Lines 421-426 static int img_dev_identify_start(struct fp_dev *dev) Link Here
421
	return generic_acquire_start(dev, IMG_ACTION_IDENTIFY);
464
	return generic_acquire_start(dev, IMG_ACTION_IDENTIFY);
422
}
465
}
423
466
467
static int img_dev_capture_start(struct fp_dev *dev)
468
{
469
	/* Unconditional capture is not supported yet */
470
	if (dev->unconditional_capture)
471
		return -ENOTSUP;
472
	return generic_acquire_start(dev, IMG_ACTION_CAPTURE);
473
}
474
424
static int img_dev_enroll_stop(struct fp_dev *dev)
475
static int img_dev_enroll_stop(struct fp_dev *dev)
425
{
476
{
426
	struct fp_img_dev *imgdev = dev->priv;
477
	struct fp_img_dev *imgdev = dev->priv;
Lines 446-451 static int img_dev_identify_stop(struct fp_dev *dev, gboolean iterating) Link Here
446
	return 0;
497
	return 0;
447
}
498
}
448
499
500
static int img_dev_capture_stop(struct fp_dev *dev)
501
{
502
	struct fp_img_dev *imgdev = dev->priv;
503
	BUG_ON(imgdev->action != IMG_ACTION_CAPTURE);
504
	generic_acquire_stop(imgdev);
505
	return 0;
506
}
507
449
void fpi_img_driver_setup(struct fp_img_driver *idriver)
508
void fpi_img_driver_setup(struct fp_img_driver *idriver)
450
{
509
{
451
	idriver->driver.type = DRIVER_IMAGING;
510
	idriver->driver.type = DRIVER_IMAGING;
Lines 457-461 void fpi_img_driver_setup(struct fp_img_driver *idriver) Link Here
457
	idriver->driver.verify_stop = img_dev_verify_stop;
516
	idriver->driver.verify_stop = img_dev_verify_stop;
458
	idriver->driver.identify_start = img_dev_identify_start;
517
	idriver->driver.identify_start = img_dev_identify_start;
459
	idriver->driver.identify_stop = img_dev_identify_stop;
518
	idriver->driver.identify_stop = img_dev_identify_stop;
519
	idriver->driver.capture_start = img_dev_capture_start;
520
	idriver->driver.capture_stop = img_dev_capture_stop;
460
}
521
}
461
522
(-)a/libfprint/pixman.c (+63 lines)
Line 0 Link Here
1
/*
2
 * Imaging utility functions for libfprint
3
 * Copyright (C) 2007-2008 Daniel Drake <dsd@gentoo.org>
4
 * Copyright (C) 2013 Vasily Khoruzhick <anarsoul@gmail.com>
5
 *
6
 * This library is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU Lesser General Public
8
 * License as published by the Free Software Foundation; either
9
 * version 2.1 of the License, or (at your option) any later version.
10
 *
11
 * This library is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
 * Lesser General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU Lesser General Public
17
 * License along with this library; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19
 */
20
21
#include <pixman.h>
22
#include <string.h>
23
24
#include "fp_internal.h"
25
26
struct fp_img *fpi_im_resize(struct fp_img *img, unsigned int w_factor, unsigned int h_factor)
27
{
28
	int new_width = img->width * w_factor;
29
	int new_height = img->height * h_factor;
30
	pixman_image_t *orig, *resized;
31
	pixman_transform_t transform;
32
	struct fp_img *newimg;
33
34
	orig = pixman_image_create_bits(PIXMAN_a8, img->width, img->height, (uint32_t *)img->data, img->width);
35
	resized = pixman_image_create_bits(PIXMAN_a8, new_width, new_height, NULL, new_width);
36
37
	pixman_transform_init_identity(&transform);
38
	pixman_transform_scale(NULL, &transform, pixman_int_to_fixed(w_factor), pixman_int_to_fixed(h_factor));
39
	pixman_image_set_transform(orig, &transform);
40
	pixman_image_set_filter(orig, PIXMAN_FILTER_BILINEAR, NULL, 0);
41
	pixman_image_composite32(PIXMAN_OP_SRC,
42
		orig, /* src */
43
		NULL, /* mask */
44
		resized, /* dst */
45
		0, 0, /* src x y */
46
		0, 0, /* mask x y */
47
		0, 0, /* dst x y */
48
		new_width, new_height /* width height */
49
		);
50
51
	newimg = fpi_img_new(new_width * new_height);
52
	newimg->width = new_width;
53
	newimg->height = new_height;
54
	newimg->flags = img->flags;
55
56
	memcpy(newimg->data, pixman_image_get_data(resized), new_width * new_height);
57
58
	pixman_image_unref(orig);
59
	pixman_image_unref(resized);
60
61
	return newimg;
62
}
63
(-)a/libfprint/sync.c (+97 lines)
Lines 512-514 err: Link Here
512
	return r;
512
	return r;
513
}
513
}
514
514
515
struct sync_capture_data {
516
	gboolean populated;
517
	int result;
518
	struct fp_img *img;
519
};
520
521
static void sync_capture_cb(struct fp_dev *dev, int result, struct fp_img *img,
522
	void *user_data)
523
{
524
	struct sync_capture_data *vdata = user_data;
525
	vdata->result = result;
526
	vdata->img = img;
527
	vdata->populated = TRUE;
528
}
529
530
static void capture_stop_cb(struct fp_dev *dev, void *user_data)
531
{
532
	gboolean *stopped = user_data;
533
	fp_dbg("");
534
	*stopped = TRUE;
535
}
536
/** \ingroup dev
537
 * Captures an \ref img "image" from a device. The returned image is the raw
538
 * image provided by the device, you may wish to \ref img_std "standardize" it.
539
 *
540
 * If set, the <tt>unconditional</tt> flag indicates that the device should
541
 * capture an image unconditionally, regardless of whether a finger is there
542
 * or not. If unset, this function will block until a finger is detected on
543
 * the sensor.
544
 *
545
 * \param dev the device
546
 * \param unconditional whether to unconditionally capture an image, or to only capture when a finger is detected
547
 * \param img a location to return the captured image. Must be freed with
548
 * fp_img_free() after use.
549
 * \return 0 on success, non-zero on error. -ENOTSUP indicates that either the
550
 * unconditional flag was set but the device does not support this, or that the
551
 * device does not support imaging.
552
 * \sa fp_dev_supports_imaging()
553
 */
554
API_EXPORTED int fp_dev_img_capture(struct fp_dev *dev, int unconditional,
555
	struct fp_img **img)
556
{
557
	struct sync_capture_data *vdata;
558
	gboolean stopped = FALSE;
559
	int r;
560
561
	if (!dev->drv->capture_start) {
562
		fp_dbg("image capture is not supported on %s device", dev->drv->name);
563
		return -ENOTSUP;
564
	}
565
566
	fp_dbg("to be handled by %s", dev->drv->name);
567
	vdata = g_malloc0(sizeof(struct sync_capture_data));
568
	r = fp_async_capture_start(dev, unconditional, sync_capture_cb, vdata);
569
	if (r < 0) {
570
		fp_dbg("capture_start error %d", r);
571
		g_free(vdata);
572
		return r;
573
	}
574
575
	while (!vdata->populated) {
576
		r = fp_handle_events();
577
		if (r < 0) {
578
			g_free(vdata);
579
			goto err;
580
		}
581
	}
582
583
	if (img)
584
		*img = vdata->img;
585
	else
586
		fp_img_free(vdata->img);
587
588
	r = vdata->result;
589
	g_free(vdata);
590
	switch (r) {
591
	case FP_CAPTURE_COMPLETE:
592
		fp_dbg("result: complete");
593
		break;
594
	case FP_CAPTURE_FAIL:
595
		fp_dbg("result: fail");
596
		break;
597
	default:
598
		fp_err("unrecognised return code %d", r);
599
		r = -EINVAL;
600
	}
601
602
err:
603
	fp_dbg("ending capture");
604
	if (fp_async_capture_stop(dev, capture_stop_cb, &stopped) == 0)
605
		while (!stopped)
606
			if (fp_handle_events() < 0)
607
				break;
608
609
	return r;
610
}
611

Return to bug 531698