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 (-1 / +12 lines)
Lines 23-29 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="upekts upektc upeksonly vcom5s uru4000 fdu2000 aes1610 aes1660 aes2501 aes2550 aes2660 aes3500 aes4000 vfs101 vfs301 vfs5011 upektc_img etes603"
26
all_drivers="upekts upektc upeksonly vcom5s uru4000 fdu2000 aes1610 aes1660 aes2501 aes2550 aes2660 aes3500 aes4000 vfs101 vfs301 vfs5011 upektc_img etes603 vfs0050"
27
27
28
require_imaging='no'
28
require_imaging='no'
29
require_aeslib='no'
29
require_aeslib='no'
Lines 48-53 enable_vfs301='no' Link Here
48
enable_vfs5011='no'
48
enable_vfs5011='no'
49
enable_upektc_img='no'
49
enable_upektc_img='no'
50
enable_etes603='no'
50
enable_etes603='no'
51
enable_vfs0050='no'
51
52
52
AC_ARG_WITH([drivers],[AS_HELP_STRING([--with-drivers],
53
AC_ARG_WITH([drivers],[AS_HELP_STRING([--with-drivers],
53
	[List of drivers to enable])],
54
	[List of drivers to enable])],
Lines 150-155 for driver in `echo ${drivers} | sed -e 's/,/ /g' -e 's/,$//g'`; do Link Here
150
			AC_DEFINE([ENABLE_ETES603], [], [Build EgisTec ES603 driver])
151
			AC_DEFINE([ENABLE_ETES603], [], [Build EgisTec ES603 driver])
151
			enable_etes603="yes"
152
			enable_etes603="yes"
152
		;;
153
		;;
154
		vfs0050)
155
			AC_DEFINE([ENABLE_VFS0050], [], [Build Validity VFS0050 driver])
156
			enable_vfs0050="yes"
157
		;;
153
	esac
158
	esac
154
done
159
done
155
160
Lines 175-180 AM_CONDITIONAL([ENABLE_VFS301], [test "$enable_vfs301" = "yes"]) Link Here
175
AM_CONDITIONAL([ENABLE_VFS5011], [test "$enable_vfs5011" = "yes"])
180
AM_CONDITIONAL([ENABLE_VFS5011], [test "$enable_vfs5011" = "yes"])
176
AM_CONDITIONAL([ENABLE_UPEKTC_IMG], [test "$enable_upektc_img" = "yes"])
181
AM_CONDITIONAL([ENABLE_UPEKTC_IMG], [test "$enable_upektc_img" = "yes"])
177
AM_CONDITIONAL([ENABLE_ETES603], [test "$enable_etes603" = "yes"])
182
AM_CONDITIONAL([ENABLE_ETES603], [test "$enable_etes603" = "yes"])
183
AM_CONDITIONAL([ENABLE_VFS0050], [test "$enable_vfs0050" = "yes"])
178
184
179
185
180
PKG_CHECK_MODULES(LIBUSB, [libusb-1.0 >= 0.9.1])
186
PKG_CHECK_MODULES(LIBUSB, [libusb-1.0 >= 0.9.1])
Lines 396-401 if test x$enable_etes603 != xno ; then Link Here
396
else
402
else
397
	AC_MSG_NOTICE([   etes603 driver disabled])
403
	AC_MSG_NOTICE([   etes603 driver disabled])
398
fi
404
fi
405
if test x$enable_vfs0050 != xno ; then
406
	AC_MSG_NOTICE([** vfs0050 driver enabled])
407
else
408
	AC_MSG_NOTICE([   vfs0050 driver disabled])
409
fi
399
if test x$require_aeslib != xno ; then
410
if test x$require_aeslib != xno ; then
400
	AC_MSG_NOTICE([** aeslib helper functions enabled])
411
	AC_MSG_NOTICE([** aeslib helper functions enabled])
401
else
412
else
(-)a/libfprint/Makefile.am (+6 lines)
Lines 21-26 VFS301_SRC = drivers/vfs301.c drivers/vfs301_proto.c drivers/vfs301_proto.h dri Link Here
21
VFS5011_SRC = drivers/vfs5011.c drivers/vfs5011_proto.h
21
VFS5011_SRC = drivers/vfs5011.c drivers/vfs5011_proto.h
22
UPEKTC_IMG_SRC = drivers/upektc_img.c drivers/upektc_img.h
22
UPEKTC_IMG_SRC = drivers/upektc_img.c drivers/upektc_img.h
23
ETES603_SRC = drivers/etes603.c
23
ETES603_SRC = drivers/etes603.c
24
VFS0050_SRC = drivers/vfs0050.c drivers/vfs0050.h
24
25
25
EXTRA_DIST = \
26
EXTRA_DIST = \
26
	$(UPEKE2_SRC)		\
27
	$(UPEKE2_SRC)		\
Lines 42-47 EXTRA_DIST = \ Link Here
42
	$(VFS5011_SRC)		\
43
	$(VFS5011_SRC)		\
43
	$(UPEKTC_IMG_SRC)	\
44
	$(UPEKTC_IMG_SRC)	\
44
	$(ETES603_SRC)		\
45
	$(ETES603_SRC)		\
46
	$(VFS0050_SRC)		\
45
	drivers/aesx660.c	\
47
	drivers/aesx660.c	\
46
	drivers/aesx660.h	\
48
	drivers/aesx660.h	\
47
	drivers/aes3k.c 	\
49
	drivers/aes3k.c 	\
Lines 182-187 if ENABLE_ETES603 Link Here
182
DRIVER_SRC += $(ETES603_SRC)
184
DRIVER_SRC += $(ETES603_SRC)
183
endif
185
endif
184
186
187
if ENABLE_VFS0050
188
DRIVER_SRC += $(VFS0050_SRC)
189
endif
190
185
if REQUIRE_PIXMAN
191
if REQUIRE_PIXMAN
186
OTHER_SRC += pixman.c
192
OTHER_SRC += pixman.c
187
libfprint_la_CFLAGS += $(IMAGING_CFLAGS)
193
libfprint_la_CFLAGS += $(IMAGING_CFLAGS)
(-)a/libfprint/core.c (+3 lines)
Lines 398-403 static struct fp_img_driver * const img_drivers[] = { Link Here
398
#ifdef ENABLE_ETES603
398
#ifdef ENABLE_ETES603
399
	&etes603_driver,
399
	&etes603_driver,
400
#endif
400
#endif
401
#ifdef ENABLE_VFS0050
402
	&vfs0050_driver,
403
#endif
401
/*#ifdef ENABLE_FDU2000
404
/*#ifdef ENABLE_FDU2000
402
	&fdu2000_driver,
405
	&fdu2000_driver,
403
#endif
406
#endif
(-)a/libfprint/drivers/driver_ids.h (+1 lines)
Lines 40-45 enum { Link Here
40
	UPEKTC_IMG_ID	= 17,
40
	UPEKTC_IMG_ID	= 17,
41
	ETES603_ID	= 18,
41
	ETES603_ID	= 18,
42
	VFS5011_ID	= 19,
42
	VFS5011_ID	= 19,
43
	VFS0050_ID	= 20,
43
};
44
};
44
45
45
#endif
46
#endif
(-)a/libfprint/drivers/vfs0050.c (+761 lines)
Line 0 Link Here
1
/*
2
 * Validity VFS0050 driver for libfprint
3
 * Copyright (C) 2015 Konstantin Semenov <zemen17@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 "vfs0050"
21
22
#include <errno.h>
23
#include <fp_internal.h>
24
#include "driver_ids.h"
25
26
#include <memory.h>
27
28
#include "vfs0050.h"
29
30
/* USB functions */
31
32
/* Callback for async_write */
33
static void async_write_callback(struct libusb_transfer *transfer)
34
{
35
	struct fpi_ssm *ssm = transfer->user_data;
36
	struct fp_img_dev *idev = ssm->priv;
37
38
	int transferred = transfer->actual_length, error =
39
	    transfer->status, len = transfer->length;
40
41
	libusb_free_transfer(transfer);
42
43
	if (error != 0) {
44
		fp_err("USB write transfer: %s", libusb_error_name(error));
45
		fpi_imgdev_session_error(idev, -EIO);
46
		fpi_ssm_mark_aborted(ssm, -EIO);
47
		return;
48
	}
49
50
	if (transferred != len) {
51
		fp_err("Written only %d of %d bytes", transferred, len);
52
		fpi_imgdev_session_error(idev, -EIO);
53
		fpi_ssm_mark_aborted(ssm, -EIO);
54
		return;
55
	}
56
57
	fpi_ssm_next_state(ssm);
58
}
59
60
/* Send data to EP1, the only out endpoint */
61
static void async_write(struct fpi_ssm *ssm, void *data, int len)
62
{
63
	struct fp_img_dev *idev = ssm->priv;
64
	struct libusb_device_handle *udev = idev->udev;
65
	struct vfs_dev_t *vdev = idev->priv;
66
67
	vdev->transfer = libusb_alloc_transfer(0);
68
	libusb_fill_bulk_transfer(vdev->transfer, udev, 0x01, data, len,
69
				  async_write_callback, ssm, VFS_USB_TIMEOUT);
70
	libusb_submit_transfer(vdev->transfer);
71
}
72
73
/* Callback for async_read */
74
static void async_read_callback(struct libusb_transfer *transfer)
75
{
76
	struct fpi_ssm *ssm = transfer->user_data;
77
	struct fp_img_dev *idev = ssm->priv;
78
79
	int transferred = transfer->actual_length, error =
80
	    transfer->status, len = transfer->length;
81
	int ep = transfer->endpoint;
82
83
	libusb_free_transfer(transfer);
84
85
	if (error != 0) {
86
		fp_err("USB read transfer on endpoint %d: %s", ep - 0x80,
87
		       libusb_error_name(error));
88
		fpi_imgdev_session_error(idev, -EIO);
89
		fpi_ssm_mark_aborted(ssm, -EIO);
90
		return;
91
	}
92
93
	if (transferred != len) {
94
		fp_err("Received %d instead of %d bytes", transferred, len);
95
		fpi_imgdev_session_error(idev, -EIO);
96
		fpi_ssm_mark_aborted(ssm, -EIO);
97
		return;
98
	}
99
100
	fpi_ssm_next_state(ssm);
101
}
102
103
/* Receive data from the given ep and compare with expected */
104
static void async_read(struct fpi_ssm *ssm, int ep, void *data, int len)
105
{
106
	struct fp_img_dev *idev = ssm->priv;
107
	struct libusb_device_handle *udev = idev->udev;
108
	struct vfs_dev_t *vdev = idev->priv;
109
110
	ep += 0x80;
111
112
	vdev->transfer = libusb_alloc_transfer(0);
113
114
	/* 0x83 is the only interrupt endpoint */
115
	if (ep == 0x83)
116
		libusb_fill_interrupt_transfer(vdev->transfer, udev, ep, data,
117
					       len, async_read_callback, ssm,
118
					       VFS_USB_TIMEOUT);
119
	else
120
		libusb_fill_bulk_transfer(vdev->transfer, udev, ep, data, len,
121
					  async_read_callback, ssm,
122
					  VFS_USB_TIMEOUT);
123
	libusb_submit_transfer(vdev->transfer);
124
}
125
126
/* Callback for async_read */
127
static void async_abort_callback(struct libusb_transfer *transfer)
128
{
129
	struct fpi_ssm *ssm = transfer->user_data;
130
	struct fp_img_dev *idev = ssm->priv;
131
132
	int transferred = transfer->actual_length, error = transfer->status;
133
	int ep = transfer->endpoint;
134
135
	/* Free trash buffer, we don't need it */
136
	g_free(transfer->buffer);
137
	libusb_free_transfer(transfer);
138
139
	/* In normal case endpoint is empty */
140
	if (error == LIBUSB_TRANSFER_TIMED_OUT) {
141
		fpi_ssm_next_state(ssm);
142
		return;
143
	}
144
145
	if (error != 0) {
146
		fp_err("USB write transfer: %s", libusb_error_name(error));
147
		fpi_imgdev_session_error(idev, -EIO);
148
		fpi_ssm_mark_aborted(ssm, -EIO);
149
		return;
150
	}
151
152
	/* Don't stop process, only print warning */
153
	if (transferred > 0)
154
		fp_warn("Endpoint %d had extra %d bytes", ep - 0x80,
155
			transferred);
156
157
	fpi_ssm_jump_to_state(ssm, ssm->cur_state);
158
}
159
160
/* Receive data from the given ep and compare with expected */
161
static void async_abort(struct fpi_ssm *ssm, int ep)
162
{
163
	struct fp_img_dev *idev = ssm->priv;
164
	struct libusb_device_handle *udev = idev->udev;
165
	struct vfs_dev_t *vdev = idev->priv;
166
167
	int len = VFS_USB_BUFFER_SIZE;
168
	unsigned char *data = g_malloc(VFS_USB_BUFFER_SIZE);
169
170
	ep += 0x80;
171
172
	vdev->transfer = libusb_alloc_transfer(0);
173
174
	/* 0x83 is the only interrupt endpoint */
175
	if (ep == 0x83)
176
		libusb_fill_interrupt_transfer(vdev->transfer, udev, ep, data,
177
					       len, async_abort_callback, ssm,
178
					       VFS_USB_ABORT_TIMEOUT);
179
	else
180
		libusb_fill_bulk_transfer(vdev->transfer, udev, ep, data, len,
181
					  async_abort_callback, ssm,
182
					  VFS_USB_ABORT_TIMEOUT);
183
	libusb_submit_transfer(vdev->transfer);
184
}
185
186
/* Proto functions */
187
188
/* SSM loop for clear_ep2 */
189
static void clear_ep2_ssm(struct fpi_ssm *ssm)
190
{
191
	struct fp_img_dev *idev = ssm->priv;
192
193
	short result;
194
	char command04 = 0x04;
195
196
	switch (ssm->cur_state) {
197
	case SUBSM1_COMMAND_04:
198
		async_write(ssm, &command04, sizeof(command04));
199
		break;
200
201
	case SUBSM1_RETURN_CODE:
202
		async_read(ssm, 1, &result, sizeof(result));
203
		break;
204
205
	case SUBSM1_ABORT_2:
206
		async_abort(ssm, 2);
207
		break;
208
209
	default:
210
		fp_err("Unknown SUBSM1 state");
211
		fpi_imgdev_session_error(idev, -EIO);
212
		fpi_ssm_mark_aborted(ssm, -EIO);
213
	}
214
}
215
216
/* Send command to clear EP2 */
217
static void clear_ep2(struct fpi_ssm *ssm)
218
{
219
	struct fp_img_dev *idev = ssm->priv;
220
221
	struct fpi_ssm *subsm =
222
	    fpi_ssm_new(idev->dev, clear_ep2_ssm, SUBSM1_STATES);
223
	subsm->priv = idev;
224
	fpi_ssm_start_subsm(ssm, subsm);
225
}
226
227
static void send_control_packet_ssm(struct fpi_ssm *ssm)
228
{
229
	struct fp_img_dev *idev = ssm->priv;
230
	struct vfs_dev_t *vdev = idev->priv;
231
232
	short result;
233
	unsigned char *commit_result = NULL;
234
235
	switch (ssm->cur_state) {
236
	case SUBSM2_SEND_CONTROL:
237
		async_write(ssm, vdev->control_packet, VFS_CONTROL_PACKET_SIZE);
238
		break;
239
240
	case SUBSM2_RETURN_CODE:
241
		async_read(ssm, 1, &result, sizeof(result));
242
		break;
243
244
	case SUBSM2_SEND_COMMIT:
245
		/* next_receive_* packets could be sent only in pair */
246
		if (vdev->control_packet == next_receive_1) {
247
			vdev->control_packet = next_receive_2;
248
			fpi_ssm_jump_to_state(ssm, SUBSM2_SEND_CONTROL);
249
			break;
250
		}
251
		/* commit_out in Windows differs in each commit, but I send the same each time */
252
		async_write(ssm, commit_out, sizeof(commit_out));
253
		break;
254
255
	case SUBSM2_COMMIT_RESPONSE:
256
		commit_result = g_malloc(VFS_COMMIT_RESPONSE_SIZE);
257
		async_read(ssm, 1, commit_result, VFS_COMMIT_RESPONSE_SIZE);
258
		break;
259
260
	case SUBSM2_READ_EMPTY_INTERRUPT:
261
		/* I don't know how to check result, it could be different */
262
		g_free(commit_result);
263
264
		async_read(ssm, 3, vdev->interrupt, VFS_INTERRUPT_SIZE);
265
		break;
266
267
	case SUBSM2_ABORT_3:
268
		/* Check that interrupt is empty */
269
		if (memcmp
270
		    (vdev->interrupt, empty_interrupt, VFS_INTERRUPT_SIZE)) {
271
			fp_err("Unknown SUBSM2 state");
272
			fpi_imgdev_session_error(idev, -EIO);
273
			fpi_ssm_mark_aborted(ssm, -EIO);
274
			break;
275
		}
276
		async_abort(ssm, 3);
277
		break;
278
279
	case SUBSM2_CLEAR_EP2:
280
		/* After turn_on Windows doesn't clear EP2 */
281
		if (vdev->control_packet != turn_on)
282
			clear_ep2(ssm);
283
		else
284
			fpi_ssm_next_state(ssm);
285
		break;
286
287
	default:
288
		fp_err("Unknown SUBSM2 state");
289
		fpi_imgdev_session_error(idev, -EIO);
290
		fpi_ssm_mark_aborted(ssm, -EIO);
291
	}
292
}
293
294
/* Send device state control packet */
295
static void send_control_packet(struct fpi_ssm *ssm)
296
{
297
	struct fp_img_dev *idev = ssm->priv;
298
299
	struct fpi_ssm *subsm =
300
	    fpi_ssm_new(idev->dev, send_control_packet_ssm, SUBSM2_STATES);
301
	subsm->priv = idev;
302
	fpi_ssm_start_subsm(ssm, subsm);
303
}
304
305
/* Clears all fprint data */
306
static void clear_data(struct vfs_dev_t *vdev)
307
{
308
	if (vdev->data != NULL)
309
		g_free(vdev->data);
310
	vdev->data = NULL;
311
	vdev->memory = vdev->bytes = 0;
312
}
313
314
#define VFS_NOISE_THRESHOLD 50
315
316
/* Processes image before submitting. This function needs to be improved */
317
static void prepare_image(struct fp_img *img, struct vfs_line *data)
318
{
319
	/* TODO: clean other falanges from print */
320
321
	/* Noise cleaning. IMHO, it works pretty well
322
	   I've not detected cases when it doesn't work or cuts a part of the finger
323
	   Noise arises at the end of scan when some water remains on the scanner */
324
	while (img->height > 0) {
325
		int val1 = data[img->height - 1].noise_hash_1;
326
		int val2 = data[img->height - 1].noise_hash_2;
327
		if (val1 > VFS_NOISE_THRESHOLD
328
		    && val1 < 256 - VFS_NOISE_THRESHOLD
329
		    && val2 > VFS_NOISE_THRESHOLD
330
		    && val2 < 256 - VFS_NOISE_THRESHOLD)
331
			break;
332
		--img->height;
333
	}
334
	fpi_img_resize(img, img->width * img->height);
335
336
	/* If image is not good enough */
337
	if (img->height < img->width) {
338
		img->height = img->width;
339
		fpi_img_resize(img, img->width * img->height);
340
		memset(img->data, 0, img->width * img->height);
341
		return;
342
	}
343
344
	/* Pixman downscaling(too big images are processed slow or cause segfault during minutae detection)
345
	   TODO: make scaling uniform using timeline data from last eight bytes */
346
347
	if (img->height > VFS_MAX_HEIGHT)
348
		fpi_im_downscale(img, 1.0,
349
				 (double)VFS_MAX_HEIGHT / img->height);
350
}
351
352
/* Creates image from raw scanner data */
353
static struct fp_img *get_raw_image(struct vfs_dev_t *vdev)
354
{
355
	struct vfs_line *data = (struct vfs_line *)vdev->data;
356
	int height = vdev->bytes / VFS_IMAGE_WIDTH;
357
	int width = VFS_RESULT_IMAGE_WIDTH;
358
359
	struct fp_img *img = fpi_img_new(width * height);
360
	img->width = width, img->height = height;
361
	img->flags = FP_IMG_V_FLIPPED;
362
	for (int x = 0; x < height; ++x)
363
		memcpy(img->data + x * width, data[x].data, width);
364
365
	return img;
366
}
367
368
/* Processes and submits image after fingerprint received */
369
static void submit_image(struct fp_img_dev *idev)
370
{
371
	struct vfs_dev_t *vdev = idev->priv;
372
373
	/* We were not asked to submit image actually */
374
	if (!vdev->active)
375
		return;
376
377
	struct fp_img *img = get_raw_image(vdev);
378
	prepare_image(img, (struct vfs_line *)vdev->data);
379
380
	fpi_imgdev_image_captured(idev, img);
381
382
	/* Finger not on the scanner */
383
	fpi_imgdev_report_finger_status(idev, 0);
384
}
385
386
/* After receiving interrupt from EP3 */
387
static void interrupt_callback(struct libusb_transfer *transfer)
388
{
389
	struct fpi_ssm *ssm = transfer->user_data;
390
	struct fp_img_dev *idev = ssm->priv;
391
	struct vfs_dev_t *vdev = idev->priv;
392
393
	char *interrupt = vdev->interrupt;
394
	int error = transfer->status, transferred = transfer->actual_length;
395
396
	libusb_free_transfer(transfer);
397
398
	vdev->wait_interrupt = 0;
399
400
	/* When we have cancelled transfer, error is ok actually */
401
	if (!vdev->active && error == LIBUSB_TRANSFER_CANCELLED)
402
		return;
403
404
	if (error != 0) {
405
		fp_err("USB read interrupt transfer: %s",
406
		       libusb_error_name(error));
407
		fpi_imgdev_session_error(idev, -EIO);
408
		fpi_ssm_mark_aborted(ssm, -EIO);
409
		return;
410
	}
411
412
	/* Interrupt size is VFS_INTERRUPT_SIZE bytes in all known cases */
413
	if (transferred != VFS_INTERRUPT_SIZE) {
414
		fp_err("Unknown interrupt size %d", transferred);
415
		libusb_free_transfer(transfer);
416
		/* Abort ssm */
417
		fpi_imgdev_session_error(idev, -EIO);
418
		fpi_ssm_mark_aborted(ssm, -EIO);
419
		return;
420
	}
421
422
	if (memcmp(interrupt, interrupt2, VFS_INTERRUPT_SIZE) == 0) {
423
		/* Go to the next ssm stage */
424
		fpi_ssm_next_state(ssm);
425
		return;
426
	}
427
428
	if (memcmp(interrupt, interrupt3, VFS_INTERRUPT_SIZE) == 0) {
429
		/* Go to the next ssm stage */
430
		fpi_ssm_next_state(ssm);
431
		return;
432
	}
433
434
	/* Standard interrupt */
435
	if (memcmp(interrupt, interrupt1, VFS_INTERRUPT_SIZE) == 0) {
436
		/* Go to the next ssm stage */
437
		fpi_ssm_next_state(ssm);
438
		return;
439
	}
440
441
	/* When finger is on the scanner before turn_on */
442
	if (interrupt[0] == 0x01) {
443
		fp_warn("Finger is already on the scanner");
444
445
		/* Go to the next ssm stage */
446
		fpi_ssm_next_state(ssm);
447
		return;
448
	}
449
450
	/* TODO: handle all interrupts */
451
	fp_err("Unknown interrupt '%02x:%02x:%02x:%02x:%02x'!",
452
	       interrupt[0] & 0xff, interrupt[1] & 0xff, interrupt[2] & 0xff,
453
	       interrupt[3] & 0xff, interrupt[4] & 0xff);
454
455
	/* Abort ssm */
456
	fpi_imgdev_session_error(idev, -EIO);
457
	fpi_ssm_mark_aborted(ssm, -EIO);
458
}
459
460
static void receive_callback(struct libusb_transfer *transfer)
461
{
462
	struct fpi_ssm *ssm = transfer->user_data;
463
	struct fp_img_dev *idev = ssm->priv;
464
	struct vfs_dev_t *vdev = idev->priv;
465
466
	int transferred = transfer->actual_length, error = transfer->status;
467
468
	libusb_free_transfer(transfer);
469
470
	if (error != 0 && error != LIBUSB_TRANSFER_TIMED_OUT) {
471
		fp_err("USB read transfer: %s", libusb_error_name(error));
472
473
		fpi_imgdev_session_error(idev, -EIO);
474
		fpi_ssm_mark_aborted(ssm, -EIO);
475
		return;
476
	}
477
478
	/* Check if fingerprint data is over */
479
	if (transferred == 0)
480
		fpi_ssm_next_state(ssm);
481
	else {
482
		/* We need more data */
483
		vdev->bytes += transferred;
484
		fpi_ssm_jump_to_state(ssm, ssm->cur_state);
485
	}
486
}
487
488
/* Stub to keep SSM alive when waiting an interrupt */
489
static void wait_interrupt(void *data)
490
{
491
	struct fpi_ssm *ssm = data;
492
	struct fp_img_dev *idev = ssm->priv;
493
	struct vfs_dev_t *vdev = idev->priv;
494
495
	/* Keep sleeping while this flag is on */
496
	if (vdev->wait_interrupt)
497
		fpi_ssm_jump_to_state(ssm, ssm->cur_state);
498
}
499
500
/* SSM stub to prepare device to another scan after orange light was on */
501
static void another_scan(void *data)
502
{
503
	struct fpi_ssm *ssm = data;
504
	fpi_ssm_jump_to_state(ssm, SSM_TURN_ON);
505
}
506
507
/* Another SSM stub to continue after waiting for probable vdev->active changes */
508
static void scan_completed(void *data)
509
{
510
	struct fpi_ssm *ssm = data;
511
	fpi_ssm_next_state(ssm);
512
}
513
514
/* Main SSM loop */
515
static void activate_ssm(struct fpi_ssm *ssm)
516
{
517
	struct fp_img_dev *idev = ssm->priv;
518
	struct libusb_device_handle *udev = idev->udev;
519
	struct vfs_dev_t *vdev = idev->priv;
520
521
	switch (ssm->cur_state) {
522
	case SSM_INITIAL_ABORT_1:
523
		async_abort(ssm, 1);
524
		break;
525
526
	case SSM_INITIAL_ABORT_2:
527
		async_abort(ssm, 2);
528
		break;
529
530
	case SSM_INITIAL_ABORT_3:
531
		async_abort(ssm, 3);
532
		break;
533
534
	case SSM_CLEAR_EP2:
535
		clear_ep2(ssm);
536
		break;
537
538
	case SSM_TURN_OFF:
539
		/* Set control_packet argument */
540
		vdev->control_packet = turn_off;
541
542
		send_control_packet(ssm);
543
		break;
544
545
	case SSM_TURN_ON:
546
		if (!vdev->active) {
547
			/* The only correct exit */
548
			fpi_ssm_mark_completed(ssm);
549
550
			if (vdev->need_report) {
551
				fpi_imgdev_deactivate_complete(idev);
552
				vdev->need_report = 0;
553
			}
554
			break;
555
		}
556
		/* Set control_packet argument */
557
		vdev->control_packet = turn_on;
558
559
		send_control_packet(ssm);
560
		break;
561
562
	case SSM_ASK_INTERRUPT:
563
		/* Activated, light must be blinking now */
564
565
		/* If we first time here, report that activate completed */
566
		if (vdev->need_report) {
567
			fpi_imgdev_activate_complete(idev, 0);
568
			vdev->need_report = 0;
569
		}
570
571
		/* Asyncronously enquire an interrupt */
572
		vdev->transfer = libusb_alloc_transfer(0);
573
		libusb_fill_interrupt_transfer(vdev->transfer, udev, 0x83,
574
					       vdev->interrupt,
575
					       VFS_INTERRUPT_SIZE,
576
					       interrupt_callback, ssm, 0);
577
		libusb_submit_transfer(vdev->transfer);
578
579
		/* This flag could be turned off only in callback function */
580
		vdev->wait_interrupt = 1;
581
582
		/* I've put it here to be sure that data is cleared */
583
		clear_data(vdev);
584
585
		fpi_ssm_next_state(ssm);
586
		break;
587
588
	case SSM_WAIT_INTERRUPT:
589
		/* Check if user had interrupted the process */
590
		if (!vdev->active) {
591
			libusb_cancel_transfer(vdev->transfer);
592
			fpi_ssm_jump_to_state(ssm, SSM_CLEAR_EP2);
593
			break;
594
		}
595
596
		if (vdev->wait_interrupt)
597
			fpi_timeout_add(VFS_SSM_TIMEOUT, wait_interrupt, ssm);
598
		break;
599
600
	case SSM_RECEIVE_FINGER:
601
		if (vdev->memory == 0) {
602
			/* Initialize fingerprint buffer */
603
			if (vdev->data != NULL)
604
				g_free(vdev->data);
605
			vdev->memory = VFS_USB_BUFFER_SIZE;
606
			vdev->data = g_malloc(vdev->memory);
607
			vdev->bytes = 0;
608
609
			/* Finger is on the scanner */
610
			fpi_imgdev_report_finger_status(idev, 1);
611
		}
612
613
		/* Increase buffer size while it's insufficient */
614
		while (vdev->bytes + VFS_USB_BUFFER_SIZE > vdev->memory) {
615
			vdev->memory <<= 1;
616
			vdev->data =
617
			    (unsigned char *)g_realloc(vdev->data,
618
						       vdev->memory);
619
		}
620
621
		/* Receive chunk of data */
622
		vdev->transfer = libusb_alloc_transfer(0);
623
		libusb_fill_bulk_transfer(vdev->transfer, udev, 0x82,
624
					  vdev->data + vdev->bytes,
625
					  VFS_USB_BUFFER_SIZE, receive_callback,
626
					  ssm, VFS_USB_TIMEOUT);
627
		libusb_submit_transfer(vdev->transfer);
628
		break;
629
630
	case SSM_SUBMIT_IMAGE:
631
		submit_image(idev);
632
		clear_data(vdev);
633
634
		/* Wait for probable vdev->active changing */
635
		fpi_timeout_add(VFS_SSM_TIMEOUT, scan_completed, ssm);
636
		break;
637
638
	case SSM_NEXT_RECEIVE:
639
		if (!vdev->active) {
640
			/* It's the last scan */
641
			fpi_ssm_jump_to_state(ssm, SSM_CLEAR_EP2);
642
			break;
643
		}
644
645
		/* Set control_packet argument */
646
		vdev->control_packet = next_receive_1;
647
648
		send_control_packet(ssm);
649
		break;
650
651
	case SSM_WAIT_ANOTHER_SCAN:
652
		/* Orange light is on now */
653
		fpi_timeout_add(VFS_SSM_ORANGE_TIMEOUT, another_scan, ssm);
654
		break;
655
656
	default:
657
		fp_err("Unknown state");
658
		fpi_imgdev_session_error(idev, -EIO);
659
		fpi_ssm_mark_aborted(ssm, -EIO);
660
	}
661
}
662
663
/* Driver functions */
664
665
/* Activate device */
666
static int dev_activate(struct fp_img_dev *idev, enum fp_imgdev_state state)
667
{
668
	struct vfs_dev_t *vdev = idev->priv;
669
670
	/* Initialize flags */
671
	vdev->active = 1;
672
	vdev->need_report = 1;
673
674
	struct fpi_ssm *ssm = fpi_ssm_new(idev->dev, activate_ssm, SSM_STATES);
675
	ssm->priv = idev;
676
	fpi_ssm_start(ssm, fpi_ssm_free);
677
	return 0;
678
}
679
680
/* Deactivate device */
681
static void dev_deactivate(struct fp_img_dev *idev)
682
{
683
	struct vfs_dev_t *vdev = idev->priv;
684
685
	/* Initialize flags */
686
	vdev->active = 0;
687
	vdev->need_report = 1;
688
}
689
690
/* Callback for dev_open ssm */
691
static void dev_open_callback(struct fpi_ssm *ssm)
692
{
693
	/* Notify open complete */
694
	fpi_imgdev_open_complete((struct fp_img_dev *)ssm->priv, 0);
695
	fpi_ssm_free(ssm);
696
}
697
698
/* Open device */
699
static int dev_open(struct fp_img_dev *idev, unsigned long driver_data)
700
{
701
	/* Claim usb interface */
702
	int error = libusb_claim_interface(idev->udev, 0);
703
	if (error < 0) {
704
		/* Interface not claimed, return error */
705
		fp_err("could not claim interface 0");
706
		return error;
707
	}
708
709
	/* Initialize private structure */
710
	struct vfs_dev_t *vdev = g_malloc0(sizeof(struct vfs_dev_t));
711
	idev->priv = vdev;
712
713
	/* Clearing previous device state */
714
	struct fpi_ssm *ssm = fpi_ssm_new(idev->dev, activate_ssm, SSM_STATES);
715
	ssm->priv = idev;
716
	fpi_ssm_start(ssm, dev_open_callback);
717
	return 0;
718
}
719
720
/* Close device */
721
static void dev_close(struct fp_img_dev *idev)
722
{
723
	/* Release private structure */
724
	g_free(idev->priv);
725
726
	/* Release usb interface */
727
	libusb_release_interface(idev->udev, 0);
728
729
	/* Notify close complete */
730
	fpi_imgdev_close_complete(idev);
731
}
732
733
/* Usb id table of device */
734
static const struct usb_id id_table[] = {
735
	{.vendor = 0x138a,.product = 0x0050},
736
	{0, 0, 0,},
737
};
738
739
/* Device driver definition */
740
struct fp_img_driver vfs0050_driver = {
741
	/* Driver specification */
742
	.driver = {
743
		   .id = VFS0050_ID,
744
		   .name = FP_COMPONENT,
745
		   .full_name = "Validity VFS0050",
746
		   .id_table = id_table,
747
		   .scan_type = FP_SCAN_TYPE_SWIPE,
748
		   },
749
750
	/* Image specification */
751
	.flags = 0,
752
	.img_width = VFS_RESULT_IMAGE_WIDTH,
753
	.img_height = -1,
754
	.bz3_threshold = 24,
755
756
	/* Routine specification */
757
	.open = dev_open,
758
	.close = dev_close,
759
	.activate = dev_activate,
760
	.deactivate = dev_deactivate,
761
};
(-)a/libfprint/drivers/vfs0050.h (+374 lines)
Line 0 Link Here
1
/*
2
 * Validity VFS0050 driver for libfprint
3
 * Copyright (C) 2015 Konstantin Semenov <zemen17@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
/* Timeout for all send/recv operations, except interrupt waiting and abort */
21
#define VFS_USB_TIMEOUT 100
22
/* Timeout for usb abort */
23
#define VFS_USB_ABORT_TIMEOUT 20
24
/* Default timeout for SSM timers */
25
#define VFS_SSM_TIMEOUT 100
26
/* Timeout for orange light */
27
#define VFS_SSM_ORANGE_TIMEOUT 700
28
29
/* Buffer size for abort and fprint receiving */
30
#define VFS_USB_BUFFER_SIZE 65536
31
32
/* Do not touch this parameters! */
33
34
/* Width from scanner including extra data */
35
#define VFS_IMAGE_WIDTH 148
36
/* Only fprint image width from scanner */
37
#define VFS_RESULT_IMAGE_WIDTH 100
38
/* Maximum result image height */
39
#define VFS_MAX_HEIGHT 600
40
/* Size of control packets: turn_on, turn_off, next_receive_*  */
41
#define VFS_CONTROL_PACKET_SIZE 125
42
/* Size of result of commit */
43
#define VFS_COMMIT_RESPONSE_SIZE 1106
44
/* Size of interrupt from EP3 */
45
#define VFS_INTERRUPT_SIZE 5
46
47
/* Fingerprint horizontal line */
48
struct vfs_line {
49
	/* It must be always 0x01 */
50
	unsigned char _0x01;
51
	/* It must be always 0xfe */
52
	unsigned char _0xfe;
53
54
	/* line number starting from some number in Little-Endian */
55
	unsigned short id;
56
57
	/* Some hashes which are useful to detect noise */
58
	unsigned char noise_hash_1;
59
	unsigned char noise_hash_2;
60
61
	/* The first byte of _somedata is always 0x00, the second is strange useless cyclic line number */
62
	unsigned short _somedata;
63
64
	/* Fingerprint image */
65
	unsigned char data[VFS_RESULT_IMAGE_WIDTH];
66
67
	/* Narrow fingerprint part from the center, diagonally, currently it's skipped */
68
	unsigned char extra[32];
69
70
	/* scan_data is 0xfb except some rare cases, it seems that it's timeline but currently it's skipped too */
71
	unsigned char scan_data[8];
72
} __attribute__ ((__packed__));
73
74
/* The main driver structure */
75
struct vfs_dev_t {
76
	/* One if we were asked to read fingerprint, zero otherwise */
77
	char active;
78
79
	/* Control packet parameter for send_control_packet */
80
	unsigned char *control_packet;
81
82
	/* Current async transfer */
83
	struct libusb_transfer *transfer;
84
85
	/* Should we call fpi_imgdev_activate_complete or fpi_imgdev_deactivate_complete */
86
	char need_report;
87
88
	/* Should we wait more for interrupt */
89
	char wait_interrupt;
90
91
	/* Received fingerprint data */
92
	unsigned char *data;
93
94
	/* Current number of received bytes and current memory used by data */
95
	int bytes, memory;
96
97
	/* Received interrupt data */
98
	unsigned char interrupt[8];
99
};
100
101
/* SSM states for clear_ep2 */
102
enum SUBSM1 {
103
	SUBSM1_COMMAND_04,
104
	SUBSM1_RETURN_CODE,
105
	SUBSM1_ABORT_2,
106
107
	SUBSM1_STATES,
108
};
109
110
/* SSM states for control */
111
enum SUBSM2 {
112
	SUBSM2_SEND_CONTROL,
113
	SUBSM2_RETURN_CODE,	/* If next_receive, send another control packet */
114
115
	SUBSM2_SEND_COMMIT,
116
	SUBSM2_COMMIT_RESPONSE,
117
	SUBSM2_READ_EMPTY_INTERRUPT,
118
	SUBSM2_ABORT_3,
119
	SUBSM2_CLEAR_EP2,
120
121
	SUBSM2_STATES,
122
};
123
124
/* SSM states for activate_ssm */
125
enum SSM_STATE {
126
	SSM_INITIAL_ABORT_1,
127
	SSM_INITIAL_ABORT_2,
128
	SSM_INITIAL_ABORT_3,
129
	SSM_CLEAR_EP2,
130
	SSM_TURN_OFF,
131
132
	/* Here the device is turned off; if not active, complete ssm */
133
	SSM_TURN_ON,
134
135
	SSM_ASK_INTERRUPT,
136
	SSM_WAIT_INTERRUPT,
137
138
	SSM_RECEIVE_FINGER,
139
	SSM_SUBMIT_IMAGE,
140
141
	/* If not active, jump to CLEAR_EP2 */
142
	SSM_NEXT_RECEIVE,
143
	SSM_WAIT_ANOTHER_SCAN,
144
	/* Jump to TURN_ON */
145
146
	SSM_STATES
147
};
148
149
/* Blocks of data from USB sniffer */
150
151
/* Turns on the light */
152
static unsigned char turn_on[] = {
153
	0x39, 0x20, 0xBF, 0x02, 0x00, 0xF4, 0x01, 0x00, 0x00, 0x01, 0xD1, 0x00,
154
	    0x20, 0xD1, 0xD1, 0x00,
155
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF4, 0x01, 0x00,
156
	    0x00, 0x01, 0x00, 0x00,
157
	0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
158
	    0x00, 0xF4, 0x01, 0x00,
159
	0x00, 0x02, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
160
	    0x00, 0x00, 0x00, 0x00,
161
	0x00, 0xF4, 0x01, 0x00, 0x00, 0x02, 0xD1, 0x00, 0x20, 0x00, 0x00, 0x00,
162
	    0x00, 0x00, 0x00, 0x00,
163
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
164
	    0x00, 0x00, 0x00, 0x00,
165
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
166
	    0x00, 0x00, 0x00, 0x00,
167
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
168
	    0x00,
169
};
170
171
/* Power off */
172
static unsigned char turn_off[] = {
173
	0x39, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
174
	    0x00, 0x00, 0x00, 0x00,
175
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
176
	    0x00, 0x00, 0x00, 0x00,
177
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
178
	    0x00, 0x00, 0x00, 0x00,
179
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
180
	    0x00, 0x00, 0x00, 0x00,
181
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
182
	    0x00, 0x00, 0x00, 0x00,
183
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
184
	    0x00, 0x00, 0x00, 0x00,
185
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
186
	    0x00, 0x00, 0x00, 0x00,
187
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
188
	    0x00,
189
};
190
191
/* Turns on orange light */
192
static unsigned char next_receive_1[] = {
193
	0x39, 0xB8, 0x0B, 0x00, 0x00, 0xB8, 0x0B, 0x00, 0x00, 0x01, 0xD1, 0x00,
194
	    0x20, 0x00, 0x00, 0x00,
195
	0x00, 0x00, 0x00, 0x00, 0x00, 0xD1, 0xD1, 0x00, 0x00, 0x00, 0x00, 0x00,
196
	    0x00, 0x01, 0x00, 0x00,
197
	0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
198
	    0x00, 0x00, 0x00, 0x00,
199
	0x00, 0x02, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
200
	    0x00, 0x00, 0x00, 0x00,
201
	0x00, 0xB8, 0x0B, 0x00, 0x00, 0x02, 0xD1, 0x00, 0x20, 0x00, 0x00, 0x00,
202
	    0x00, 0x00, 0x00, 0x00,
203
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
204
	    0x00, 0x00, 0x00, 0x00,
205
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
206
	    0x00, 0x00, 0x00, 0x00,
207
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
208
	    0x00,
209
};
210
211
/* Packet directly after next_receive_1 */
212
static unsigned char next_receive_2[] = {
213
	0x39, 0xE8, 0x03, 0x00, 0x00, 0xE8, 0x03, 0x00, 0x00, 0x01, 0xD1, 0x00,
214
	    0x20, 0x00, 0x00, 0x00,
215
	0x00, 0x00, 0x00, 0x00, 0x00, 0xD1, 0xD1, 0x00, 0x00, 0x00, 0x00, 0x00,
216
	    0x00, 0x01, 0x00, 0x00,
217
	0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
218
	    0x00, 0x00, 0x00, 0x00,
219
	0x00, 0x02, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
220
	    0x00, 0x00, 0x00, 0x00,
221
	0x00, 0xE8, 0x03, 0x00, 0x00, 0x02, 0xD1, 0x00, 0x20, 0x00, 0x00, 0x00,
222
	    0x00, 0x00, 0x00, 0x00,
223
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
224
	    0x00, 0x00, 0x00, 0x00,
225
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
226
	    0x00, 0x00, 0x00, 0x00,
227
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
228
	    0x00,
229
};
230
231
/* Commit message */
232
static unsigned char commit_out[] = {
233
	0x02, 0x94, 0x00, 0x00, 0x00, 0x20, 0x00, 0x08, 0x00, 0x2C, 0x03, 0x00,
234
	    0x30, 0x1B, 0x00, 0x00,
235
	0x00, 0x20, 0x00, 0x08, 0x00, 0x20, 0x03, 0x00, 0x30, 0x3D, 0x10, 0x00,
236
	    0x00, 0x20, 0x00, 0x08,
237
	0x00, 0x18, 0x03, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x08,
238
	    0x00, 0x24, 0x03, 0x00,
239
	0x30, 0x08, 0x00, 0x00, 0x00, 0x20, 0x00, 0x08, 0x00, 0x28, 0x03, 0x00,
240
	    0x30, 0x08, 0x00, 0x00,
241
	0x00, 0x20, 0x00, 0x08, 0x00, 0x30, 0x03, 0x00, 0x30, 0x00, 0x00, 0x00,
242
	    0x00, 0x20, 0x00, 0x08,
243
	0x00, 0x38, 0x03, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x08,
244
	    0x00, 0x3C, 0x03, 0x00,
245
	0x30, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x08, 0x00, 0x44, 0x03, 0x00,
246
	    0x30, 0x14, 0x00, 0x00,
247
	0x00, 0x20, 0x00, 0x08, 0x00, 0x48, 0x03, 0x00, 0x30, 0x01, 0x04, 0x02,
248
	    0x00, 0x20, 0x00, 0x08,
249
	0x00, 0x4C, 0x03, 0x00, 0x30, 0x01, 0x0C, 0x02, 0x00, 0x20, 0x00, 0x08,
250
	    0x00, 0x54, 0x03, 0x00,
251
	0x30, 0x20, 0x00, 0x00, 0x00, 0x20, 0x00, 0x08, 0x00, 0x5C, 0x03, 0x00,
252
	    0x30, 0x90, 0x01, 0x02,
253
	0x00, 0x20, 0x00, 0x08, 0x00, 0x60, 0x03, 0x00, 0x30, 0x2C, 0x01, 0x19,
254
	    0x00, 0x20, 0x00, 0x08,
255
	0x00, 0x64, 0x03, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x08,
256
	    0x00, 0x6C, 0x03, 0x00,
257
	0x30, 0x1E, 0x00, 0x00, 0x00, 0x20, 0x00, 0x08, 0x00, 0x70, 0x03, 0x00,
258
	    0x30, 0x21, 0x80, 0x00,
259
	0x00, 0x20, 0x00, 0x08, 0x00, 0x78, 0x03, 0x00, 0x30, 0x09, 0x00, 0x02,
260
	    0x00, 0x20, 0x00, 0x08,
261
	0x00, 0x7C, 0x03, 0x00, 0x30, 0x0B, 0x00, 0x19, 0x00, 0x20, 0x00, 0x08,
262
	    0x00, 0x80, 0x03, 0x00,
263
	0x30, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x08, 0x00, 0x84, 0x03, 0x00,
264
	    0x30, 0x3A, 0x00, 0x00,
265
	0x00, 0x20, 0x00, 0x08, 0x00, 0x88, 0x03, 0x00, 0x30, 0x14, 0x00, 0x00,
266
	    0x00, 0x20, 0x00, 0x08,
267
	0x00, 0x8C, 0x03, 0x00, 0x30, 0x02, 0x00, 0x00, 0x00, 0x20, 0x00, 0x08,
268
	    0x00, 0x90, 0x03, 0x00,
269
	0x30, 0x02, 0x00, 0x00, 0x00, 0x20, 0x00, 0x08, 0x00, 0x94, 0x03, 0x00,
270
	    0x30, 0x08, 0x00, 0x00,
271
	0x00, 0x20, 0x00, 0x08, 0x00, 0x98, 0x03, 0x00, 0x30, 0x00, 0x00, 0xA1,
272
	    0x01, 0x20, 0x00, 0x08,
273
	0x00, 0x9C, 0x03, 0x00, 0x30, 0x00, 0x00, 0xA1, 0x01, 0x20, 0x00, 0x08,
274
	    0x00, 0xA8, 0x03, 0x00,
275
	0x30, 0x64, 0x01, 0x00, 0x00, 0x20, 0x00, 0x08, 0x00, 0xAC, 0x03, 0x00,
276
	    0x30, 0x64, 0x01, 0x00,
277
	0x00, 0x20, 0x00, 0x08, 0x00, 0xB0, 0x03, 0x00, 0x30, 0x00, 0x01, 0x00,
278
	    0x00, 0x20, 0x00, 0x08,
279
	0x00, 0xB4, 0x03, 0x00, 0x30, 0x00, 0x01, 0x00, 0x00, 0x20, 0x00, 0x08,
280
	    0x00, 0xB8, 0x03, 0x00,
281
	0x30, 0x05, 0x00, 0x00, 0x00, 0x20, 0x00, 0x08, 0x00, 0xBC, 0x03, 0x00,
282
	    0x30, 0x05, 0x00, 0x00,
283
	0x00, 0x20, 0x00, 0x08, 0x00, 0xC0, 0x03, 0x00, 0x30, 0x00, 0x00, 0x00,
284
	    0x00, 0x20, 0x00, 0x08,
285
	0x00, 0x84, 0x03, 0x00, 0x30, 0x3B, 0x00, 0x00, 0x00, 0x20, 0x00, 0x08,
286
	    0x00, 0x08, 0x07, 0x00,
287
	0x30, 0x03, 0x00, 0x00, 0x00, 0x20, 0x00, 0x08, 0x00, 0x0C, 0x07, 0x00,
288
	    0x30, 0x00, 0x00, 0x00,
289
	0x00, 0x20, 0x00, 0x08, 0x00, 0x14, 0x07, 0x00, 0x30, 0x20, 0x00, 0x00,
290
	    0x00, 0x20, 0x00, 0x08,
291
	0x00, 0x1C, 0x07, 0x00, 0x30, 0x1A, 0x00, 0x00, 0x00, 0x20, 0x00, 0x08,
292
	    0x00, 0x70, 0x0D, 0x00,
293
	0x30, 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x28, 0x00, 0x10, 0x00, 0x00,
294
	    0x00, 0x00, 0x00, 0x00,
295
	0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
296
	    0x00, 0x00, 0x00, 0x00,
297
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
298
	    0x00, 0x00, 0x00, 0x00,
299
	0x00, 0x02, 0x00, 0x90, 0x00, 0x00, 0x00, 0x2B, 0xFF, 0x2B, 0xFF, 0x2B,
300
	    0xED, 0x00, 0x00, 0x2B,
301
	0xFB, 0x00, 0x00, 0x2B, 0xC5, 0x00, 0x00, 0x2B, 0x05, 0x80, 0x70, 0x00,
302
	    0x00, 0x00, 0x00, 0x00,
303
	0x00, 0x24, 0xD3, 0x2E, 0xC0, 0x2C, 0x3B, 0x08, 0xF0, 0x3B, 0x09, 0x24,
304
	    0xBB, 0x3B, 0x0B, 0x24,
305
	0xAA, 0x3B, 0x1F, 0xF8, 0x00, 0x3B, 0x3F, 0xF0, 0x00, 0x3B, 0x35, 0xC0,
306
	    0x00, 0x38, 0x80, 0x2C,
307
	0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x38, 0x80, 0x2C, 0x70, 0x00,
308
	    0x00, 0x00, 0x00, 0xC0,
309
	0x3A, 0x80, 0x2C, 0x70, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x3B, 0x0A, 0x80,
310
	    0x2E, 0x83, 0x24, 0xDB,
311
	0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0xC3, 0x2C, 0x31, 0x83, 0x2C, 0x70,
312
	    0x00, 0x00, 0x00, 0x00,
313
	0xCB, 0x33, 0x1B, 0x83, 0x2C, 0x70, 0x00, 0x00, 0x00, 0x00, 0xCB, 0x31,
314
	    0x83, 0x2C, 0x70, 0x00,
315
	0x00, 0x00, 0x00, 0xCB, 0x00, 0x33, 0x1E, 0x83, 0x2E, 0x25, 0xFF, 0xC4,
316
	    0x00, 0x2F, 0x06, 0x84,
317
	0x2E, 0x00, 0x00, 0x10, 0x20, 0x29, 0x00, 0x04, 0x00, 0x10, 0x00, 0x00,
318
	    0x00, 0x23, 0x00, 0x00,
319
	0x00, 0x21, 0x00, 0x10, 0x00, 0x48, 0x03, 0x00, 0x30, 0xFF, 0xF0, 0xFF,
320
	    0xFF, 0x00, 0x00, 0x00,
321
	0x00, 0x00, 0x04, 0x00, 0x00, 0x21, 0x00, 0x10, 0x00, 0x4C, 0x03, 0x00,
322
	    0x30, 0xFF, 0xF0, 0xFF,
323
	0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x21, 0x00, 0x10,
324
	    0x00, 0x20, 0x03, 0x00,
325
	0x30, 0x7F, 0x00, 0xFC, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x80, 0x10, 0x00,
326
	    0x00, 0x20, 0x00, 0x08,
327
	0x00, 0x24, 0x03, 0x00, 0x30, 0x08, 0x00, 0x00, 0x00, 0x20, 0x00, 0x08,
328
	    0x00, 0x1C, 0x07, 0x00,
329
	0x30, 0x1A, 0x00, 0x00, 0x00, 0x21, 0x00, 0x10, 0x00, 0x20, 0x03, 0x00,
330
	    0x30, 0xC3, 0xFF, 0xFF,
331
	0xFF, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x20, 0x00, 0x08,
332
	    0x00, 0x80, 0x03, 0x00,
333
	0x30, 0x02, 0x00, 0x00, 0x00, 0x24, 0x00, 0x84, 0x00, 0x31, 0x65, 0x77,
334
	    0x77, 0x77, 0x78, 0x88,
335
	0x77, 0x77, 0x76, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x78, 0x77, 0x67,
336
	    0x66, 0x66, 0x66, 0x66,
337
	0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x76, 0x67, 0x66, 0x66, 0x66, 0x66,
338
	    0x66, 0x77, 0x66, 0x66,
339
	0x66, 0x66, 0x67, 0x66, 0x66, 0x66, 0x66, 0x66, 0x76, 0x76, 0x66, 0x56,
340
	    0x66, 0x66, 0x56, 0x55,
341
	0x65, 0x66, 0x66, 0x66, 0x65, 0x66, 0x66, 0x55, 0x66, 0x66, 0x65, 0x66,
342
	    0x76, 0x76, 0x77, 0x77,
343
	0x66, 0x66, 0x66, 0x76, 0x67, 0x66, 0x77, 0x67, 0x66, 0x66, 0x66, 0x56,
344
	    0x65, 0x66, 0x65, 0x66,
345
	0x66, 0x55, 0x55, 0x54, 0x55, 0x65, 0x66, 0x66, 0x66, 0x76, 0x77, 0x87,
346
	    0x88, 0x77, 0x66, 0x66,
347
	0x66, 0x66, 0x66, 0x66, 0x66, 0x65, 0x66, 0x55, 0x55, 0x65, 0x56, 0x55,
348
	    0x55, 0x55, 0x54, 0x45,
349
	0x54, 0x55, 0x55, 0x55, 0x66, 0x66, 0x66, 0x66, 0x66, 0x77, 0x77, 0x77,
350
	    0x66, 0x26, 0x00, 0x28,
351
	0x00, 0xFF, 0x00, 0x0F, 0x00, 0xF0, 0xF0, 0x0F, 0x00, 0x20, 0x00, 0x00,
352
	    0x00, 0x30, 0x01, 0x02,
353
	0x00, 0x2C, 0x01, 0x28, 0x00, 0x20, 0x80, 0x00, 0x00, 0x0A, 0x00, 0x02,
354
	    0x00, 0x0B, 0x00, 0x19,
355
	0x00, 0x40, 0x1F, 0x10, 0x27, 0x00, 0x0F, 0x03, 0x00,
356
};
357
358
/* Known interrupts */
359
360
static unsigned char empty_interrupt[] = {
361
	0x00, 0x00, 0x00, 0x00, 0x00,
362
};
363
364
static unsigned char interrupt1[] = {
365
	0x02, 0x00, 0x0E, 0x00, 0xF0,
366
};
367
368
static unsigned char interrupt2[] = {
369
	0x02, 0x04, 0x0A, 0x00, 0xF0,
370
};
371
372
static unsigned char interrupt3[] = {
373
	0x02, 0x00, 0x0A, 0x00, 0xF0,
374
};
(-)a/libfprint/fp_internal.h (+4 lines)
Lines 305-310 extern struct fp_img_driver upektc_img_driver; Link Here
305
#ifdef ENABLE_ETES603
305
#ifdef ENABLE_ETES603
306
extern struct fp_img_driver etes603_driver;
306
extern struct fp_img_driver etes603_driver;
307
#endif
307
#endif
308
#ifdef ENABLE_VFS0050
309
extern struct fp_img_driver vfs0050_driver;
310
#endif
308
311
309
extern libusb_context *fpi_usb_ctx;
312
extern libusb_context *fpi_usb_ctx;
310
extern GSList *opened_devices;
313
extern GSList *opened_devices;
Lines 402-407 int fpi_img_compare_print_data(struct fp_print_data *enrolled_print, Link Here
402
int fpi_img_compare_print_data_to_gallery(struct fp_print_data *print,
405
int fpi_img_compare_print_data_to_gallery(struct fp_print_data *print,
403
	struct fp_print_data **gallery, int match_threshold, size_t *match_offset);
406
	struct fp_print_data **gallery, int match_threshold, size_t *match_offset);
404
struct fp_img *fpi_im_resize(struct fp_img *img, unsigned int w_factor, unsigned int h_factor);
407
struct fp_img *fpi_im_resize(struct fp_img *img, unsigned int w_factor, unsigned int h_factor);
408
void fpi_im_downscale(struct fp_img *img, double w_factor, double h_factor);
405
409
406
/* polling and timeouts */
410
/* polling and timeouts */
407
411
(-)a/libfprint/fprint-list-udev-rules.c (-1 / +2 lines)
Lines 74-80 static void print_driver (struct fp_driver *driver) Link Here
74
	if (num_printed == 0)
74
	if (num_printed == 0)
75
	    printf ("# %s\n", driver->full_name);
75
	    printf ("# %s\n", driver->full_name);
76
76
77
	printf ("SUBSYSTEM==\"usb\", ATTRS{idVendor}==\"%04x\", ATTRS{idProduct}==\"%04x\", ATTRS{dev}==\"*\", TEST==\"power/control\", ATTR{power/control}=\"auto\"\n", driver->id_table[i].vendor, driver->id_table[i].product);
77
	printf ("SUBSYSTEM==\"usb\", ATTRS{idVendor}==\"%04x\", ATTRS{idProduct}==\"%04x\", ATTRS{dev}==\"*\", TEST==\"power/control\", ATTR{power/control}=\"auto\"\n, MODE=\"0666\"\n", driver->id_table[i].vendor, driver->id_table[i].product);
78
	printf ("SUBSYSTEM==\"usb\", ATTRS{idVendor}==\"%04x\", ATTRS{idProduct}==\"%04x\", ENV{LIBFPRINT_DRIVER}=\"%s\"\n", driver->id_table[i].vendor, driver->id_table[i].product, driver->full_name);
78
	num_printed++;
79
	num_printed++;
79
    }
80
    }
80
81
(-)a/libfprint/imgdev.c (+9 lines)
Lines 165-170 void fpi_imgdev_report_finger_status(struct fp_img_dev *imgdev, Link Here
165
	case IMG_ACTION_VERIFY:
165
	case IMG_ACTION_VERIFY:
166
		fpi_drvcb_report_verify_result(imgdev->dev, r, img);
166
		fpi_drvcb_report_verify_result(imgdev->dev, r, img);
167
		fp_print_data_free(data);
167
		fp_print_data_free(data);
168
169
		/* the callback can cancel verifying, so recheck current
170
		 * action and the status to see if retry is needed */
171
		if (imgdev->action == IMG_ACTION_VERIFY &&
172
		    r > 0 && r != FP_VERIFY_MATCH && r != FP_VERIFY_NO_MATCH) {
173
			imgdev->action_result = 0;
174
			imgdev->action_state = IMG_ACQUIRE_STATE_AWAIT_FINGER_ON;
175
			dev_change_state(imgdev, IMGDEV_STATE_AWAIT_FINGER_ON);
176
		}
168
		break;
177
		break;
169
	case IMG_ACTION_IDENTIFY:
178
	case IMG_ACTION_IDENTIFY:
170
		fpi_drvcb_report_identify_result(imgdev->dev, r,
179
		fpi_drvcb_report_identify_result(imgdev->dev, r,
(-)a/libfprint/pixman.c (+35 lines)
Lines 61-63 struct fp_img *fpi_im_resize(struct fp_img *img, unsigned int w_factor, unsigned Link Here
61
	return newimg;
61
	return newimg;
62
}
62
}
63
63
64
void fpi_im_downscale(struct fp_img *img, double w_factor, double h_factor)
65
{
66
	int new_width = img->width * w_factor;
67
	int new_height = img->height * h_factor;
68
69
	pixman_image_t *orig, *resized;
70
	pixman_transform_t transform;
71
72
	orig = pixman_image_create_bits(PIXMAN_a8, img->width, img->height, (uint32_t *)img->data, img->width);
73
	resized = pixman_image_create_bits(PIXMAN_a8, new_width, new_height, NULL, new_width);
74
75
	pixman_transform_init_identity(&transform);
76
	pixman_transform_scale(NULL, &transform, pixman_double_to_fixed(w_factor), pixman_double_to_fixed(h_factor));
77
	pixman_image_set_transform(orig, &transform);
78
	pixman_image_set_filter(orig, PIXMAN_FILTER_BEST, NULL, 0);
79
	pixman_image_composite32(PIXMAN_OP_SRC,
80
		orig, /* src */
81
		NULL, /* mask */
82
		resized, /* dst */
83
		0, 0, /* src x y */
84
		0, 0, /* mask x y */
85
		0, 0, /* dst x y */
86
		new_width, new_height /* width height */
87
		);
88
89
    fpi_img_resize(img, new_width * new_height);
90
	img->width = new_width;
91
	img->height = new_height;
92
93
	memcpy(img->data, pixman_image_get_data(resized), new_width * new_height);
94
95
	pixman_image_unref(orig);
96
	pixman_image_unref(resized);
97
}
98

Return to bug 531698