1 /*
2 * Validity Sensors, Inc. VFS5011 Fingerprint Reader driver for libfprint
3 * Copyright (C) 2013 Arseniy Lartsev <arseniy@chalmers.se>
4 * AceLan Kao <acelan.kao@canonical.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 <stdio.h>
22 #include <errno.h>
23 #include <string.h>
24 #include <libusb.h>
25 #include <fp_internal.h>
26 #include <assembling.h>
27 #include "driver_ids.h"
28
29 #include "vfs5011_proto.h"
30
31 /* =================== sync/async USB transfer sequence ==================== */
32
33 enum {
34 ACTION_SEND,
35 ACTION_RECEIVE,
36 };
37
38 struct usb_action {
39 int type;
40 const char *name;
41 int endpoint;
42 int size;
43 unsigned char *data;
44 int correct_reply_size;
45 };
46
47 #define SEND(ENDPOINT, COMMAND) \
48 { \
49 .type = ACTION_SEND, \
50 .endpoint = ENDPOINT, \
51 .name = #COMMAND, \
52 .size = sizeof(COMMAND), \
53 .data = COMMAND \
54 },
55
56 #define RECV(ENDPOINT, SIZE) \
57 { \
58 .type = ACTION_RECEIVE, \
59 .endpoint = ENDPOINT, \
60 .size = SIZE, \
61 .data = NULL \
62 },
63
64 #define RECV_CHECK(ENDPOINT, SIZE, EXPECTED) \
65 { \
66 .type = ACTION_RECEIVE, \
67 .endpoint = ENDPOINT, \
68 .size = SIZE, \
69 .data = EXPECTED, \
70 .correct_reply_size = sizeof(EXPECTED) \
71 },
72
73 struct usbexchange_data {
74 int stepcount;
75 struct fp_img_dev *device;
76 struct usb_action *actions;
77 void *receive_buf;
78 int timeout;
79 };
80
81 static void start_scan(struct fp_img_dev *dev);
82
async_send_cb(struct libusb_transfer * transfer)83 static void async_send_cb(struct libusb_transfer *transfer)
84 {
85 struct fpi_ssm *ssm = transfer->user_data;
86 struct usbexchange_data *data = (struct usbexchange_data *)ssm->priv;
87 struct usb_action *action;
88
89 if (ssm->cur_state >= data->stepcount) {
90 fp_err("Radiation detected!");
91 fpi_imgdev_session_error(data->device, -EINVAL);
92 fpi_ssm_mark_aborted(ssm, -EINVAL);
93 goto out;
94 }
95
96 action = &data->actions[ssm->cur_state];
97 if (action->type != ACTION_SEND) {
98 fp_err("Radiation detected!");
99 fpi_imgdev_session_error(data->device, -EINVAL);
100 fpi_ssm_mark_aborted(ssm, -EINVAL);
101 goto out;
102 }
103
104 if (transfer->status != LIBUSB_TRANSFER_COMPLETED) {
105 /* Transfer not completed, return IO error */
106 fp_err("transfer not completed, status = %d", transfer->status);
107 fpi_imgdev_session_error(data->device, -EIO);
108 fpi_ssm_mark_aborted(ssm, -EIO);
109 goto out;
110 }
111 if (transfer->length != transfer->actual_length) {
112 /* Data sended mismatch with expected, return protocol error */
113 fp_err("length mismatch, got %d, expected %d",
114 transfer->actual_length, transfer->length);
115 fpi_imgdev_session_error(data->device, -EIO);
116 fpi_ssm_mark_aborted(ssm, -EIO);
117 goto out;
118 }
119
120 /* success */
121 fpi_ssm_next_state(ssm);
122
123 out:
124 libusb_free_transfer(transfer);
125 }
126
async_recv_cb(struct libusb_transfer * transfer)127 static void async_recv_cb(struct libusb_transfer *transfer)
128 {
129 struct fpi_ssm *ssm = transfer->user_data;
130 struct usbexchange_data *data = (struct usbexchange_data *)ssm->priv;
131 struct usb_action *action;
132
133 if (transfer->status != LIBUSB_TRANSFER_COMPLETED) {
134 /* Transfer not completed, return IO error */
135 fp_err("transfer not completed, status = %d", transfer->status);
136 fpi_imgdev_session_error(data->device, -EIO);
137 fpi_ssm_mark_aborted(ssm, -EIO);
138 goto out;
139 }
140
141 if (ssm->cur_state >= data->stepcount) {
142 fp_err("Radiation detected!");
143 fpi_imgdev_session_error(data->device, -EINVAL);
144 fpi_ssm_mark_aborted(ssm, -EINVAL);
145 goto out;
146 }
147
148 action = &data->actions[ssm->cur_state];
149 if (action->type != ACTION_RECEIVE) {
150 fp_err("Radiation detected!");
151 fpi_imgdev_session_error(data->device, -EINVAL);
152 fpi_ssm_mark_aborted(ssm, -EINVAL);
153 goto out;
154 }
155
156 if (action->data != NULL) {
157 if (transfer->actual_length != action->correct_reply_size) {
158 fp_err("Got %d bytes instead of %d",
159 transfer->actual_length,
160 action->correct_reply_size);
161 fpi_imgdev_session_error(data->device, -EIO);
162 fpi_ssm_mark_aborted(ssm, -EIO);
163 goto out;
164 }
165 if (memcmp(transfer->buffer, action->data,
166 action->correct_reply_size) != 0) {
167 fp_dbg("Wrong reply:");
168 fpi_imgdev_session_error(data->device, -EIO);
169 fpi_ssm_mark_aborted(ssm, -EIO);
170 goto out;
171 }
172 } else
173 fp_dbg("Got %d bytes out of %d", transfer->actual_length,
174 transfer->length);
175
176 fpi_ssm_next_state(ssm);
177 out:
178 libusb_free_transfer(transfer);
179 }
180
usbexchange_loop(struct fpi_ssm * ssm)181 static void usbexchange_loop(struct fpi_ssm *ssm)
182 {
183 struct usbexchange_data *data = (struct usbexchange_data *)ssm->priv;
184 if (ssm->cur_state >= data->stepcount) {
185 fp_err("Bug detected: state %d out of range, only %d steps",
186 ssm->cur_state, data->stepcount);
187 fpi_imgdev_session_error(data->device, -EINVAL);
188 fpi_ssm_mark_aborted(ssm, -EINVAL);
189 return;
190 }
191
192 struct usb_action *action = &data->actions[ssm->cur_state];
193 struct libusb_transfer *transfer;
194 int ret = -EINVAL;
195
196 switch (action->type) {
197 case ACTION_SEND:
198 fp_dbg("Sending %s", action->name);
199 transfer = libusb_alloc_transfer(0);
200 if (transfer == NULL) {
201 fp_err("Failed to allocate transfer");
202 fpi_imgdev_session_error(data->device, -ENOMEM);
203 fpi_ssm_mark_aborted(ssm, -ENOMEM);
204 return;
205 }
206 libusb_fill_bulk_transfer(transfer, data->device->udev,
207 action->endpoint, action->data,
208 action->size, async_send_cb, ssm,
209 data->timeout);
210 ret = libusb_submit_transfer(transfer);
211 break;
212
213 case ACTION_RECEIVE:
214 fp_dbg("Receiving %d bytes", action->size);
215 transfer = libusb_alloc_transfer(0);
216 if (transfer == NULL) {
217 fp_err("Failed to allocate transfer");
218 fpi_imgdev_session_error(data->device, -ENOMEM);
219 fpi_ssm_mark_aborted(ssm, -ENOMEM);
220 return;
221 }
222 libusb_fill_bulk_transfer(transfer, data->device->udev,
223 action->endpoint, data->receive_buf,
224 action->size, async_recv_cb, ssm,
225 data->timeout);
226 ret = libusb_submit_transfer(transfer);
227 break;
228
229 default:
230 fp_err("Bug detected: invalid action %d", action->type);
231 fpi_imgdev_session_error(data->device, -EINVAL);
232 fpi_ssm_mark_aborted(ssm, -EINVAL);
233 return;
234 }
235
236 if (ret != 0) {
237 fp_err("USB transfer error: %s", strerror(ret));
238 fpi_imgdev_session_error(data->device, ret);
239 fpi_ssm_mark_aborted(ssm, ret);
240 }
241 }
242
usb_exchange_async(struct fpi_ssm * ssm,struct usbexchange_data * data)243 static void usb_exchange_async(struct fpi_ssm *ssm,
244 struct usbexchange_data *data)
245 {
246 struct fpi_ssm *subsm = fpi_ssm_new(data->device->dev,
247 usbexchange_loop,
248 data->stepcount);
249 subsm->priv = data;
250 fpi_ssm_start_subsm(ssm, subsm);
251 }
252
253 /* ====================== utils ======================= */
254
255 /* Calculade squared standand deviation of sum of two lines */
vfs5011_get_deviation2(struct fpi_line_asmbl_ctx * ctx,GSList * row1,GSList * row2)256 static int vfs5011_get_deviation2(struct fpi_line_asmbl_ctx *ctx, GSList *row1, GSList *row2)
257 {
258 unsigned char *buf1, *buf2;
259 int res = 0, mean = 0, i;
260 const int size = 64;
261
262 buf1 = row1->data + 56;
263 buf2 = row2->data + 168;
264
265 for (i = 0; i < size; i++)
266 mean += (int)buf1[i] + (int)buf2[i];
267
268 mean /= size;
269
270 for (i = 0; i < size; i++) {
271 int dev = (int)buf1[i] + (int)buf2[i] - mean;
272 res += dev*dev;
273 }
274
275 return res / size;
276 }
277
vfs5011_get_pixel(struct fpi_line_asmbl_ctx * ctx,GSList * row,unsigned x)278 static unsigned char vfs5011_get_pixel(struct fpi_line_asmbl_ctx *ctx,
279 GSList *row,
280 unsigned x)
281 {
282 unsigned char *data = row->data + 8;
283
284 return data[x];
285 }
286
287 /* ====================== main stuff ======================= */
288
289 enum {
290 CAPTURE_LINES = 256,
291 MAXLINES = 2000,
292 MAX_CAPTURE_LINES = 100000,
293 };
294
295 static struct fpi_line_asmbl_ctx assembling_ctx = {
296 .line_width = VFS5011_IMAGE_WIDTH,
297 .max_height = MAXLINES,
298 .resolution = 10,
299 .median_filter_size = 25,
300 .max_search_offset = 30,
301 .get_deviation = vfs5011_get_deviation2,
302 .get_pixel = vfs5011_get_pixel,
303 };
304
305 struct vfs5011_data {
306 unsigned char *total_buffer;
307 unsigned char *capture_buffer;
308 unsigned char *row_buffer;
309 unsigned char *lastline;
310 GSList *rows;
311 int lines_captured, lines_recorded, empty_lines;
312 int max_lines_captured, max_lines_recorded;
313 int lines_total, lines_total_allocated;
314 gboolean loop_running;
315 gboolean deactivating;
316 struct usbexchange_data init_sequence;
317 struct libusb_transfer *flying_transfer;
318 };
319
320 enum {
321 DEV_ACTIVATE_REQUEST_FPRINT,
322 DEV_ACTIVATE_INIT_COMPLETE,
323 DEV_ACTIVATE_READ_DATA,
324 DEV_ACTIVATE_DATA_COMPLETE,
325 DEV_ACTIVATE_PREPARE_NEXT_CAPTURE,
326 DEV_ACTIVATE_NUM_STATES
327 };
328
329 enum {
330 DEV_OPEN_START,
331 DEV_OPEN_NUM_STATES
332 };
333
capture_init(struct vfs5011_data * data,int max_captured,int max_recorded)334 static void capture_init(struct vfs5011_data *data, int max_captured,
335 int max_recorded)
336 {
337 fp_dbg("capture_init");
338 data->lastline = NULL;
339 data->lines_captured = 0;
340 data->lines_recorded = 0;
341 data->empty_lines = 0;
342 data->lines_total = 0;
343 data->lines_total_allocated = 0;
344 data->total_buffer = NULL;
345 data->max_lines_captured = max_captured;
346 data->max_lines_recorded = max_recorded;
347 }
348
process_chunk(struct vfs5011_data * data,int transferred)349 static int process_chunk(struct vfs5011_data *data, int transferred)
350 {
351 enum {
352 DEVIATION_THRESHOLD = 15*15,
353 DIFFERENCE_THRESHOLD = 600,
354 STOP_CHECK_LINES = 50
355 };
356
357 fp_dbg("process_chunk: got %d bytes", transferred);
358 int lines_captured = transferred/VFS5011_LINE_SIZE;
359 int i;
360
361 for (i = 0; i < lines_captured; i++) {
362 unsigned char *linebuf = data->capture_buffer
363 + i * VFS5011_LINE_SIZE;
364
365 if (fpi_std_sq_dev(linebuf + 8, VFS5011_IMAGE_WIDTH)
366 < DEVIATION_THRESHOLD) {
367 if (data->lines_captured == 0)
368 continue;
369 else
370 data->empty_lines++;
371 } else
372 data->empty_lines = 0;
373 if (data->empty_lines >= STOP_CHECK_LINES) {
374 fp_dbg("process_chunk: got %d empty lines, finishing",
375 data->empty_lines);
376 return 1;
377 }
378
379 data->lines_captured++;
380 if (data->lines_captured > data->max_lines_captured) {
381 fp_dbg("process_chunk: captured %d lines, finishing",
382 data->lines_captured);
383 return 1;
384 }
385
386 if ((data->lastline == NULL)
387 || (fpi_mean_sq_diff_norm(
388 data->lastline + 8,
389 linebuf + 8,
390 VFS5011_IMAGE_WIDTH) >= DIFFERENCE_THRESHOLD)) {
391 data->lastline = g_malloc(VFS5011_LINE_SIZE);
392 data->rows = g_slist_prepend(data->rows, data->lastline);
393 g_memmove(data->lastline, linebuf, VFS5011_LINE_SIZE);
394 data->lines_recorded++;
395 if (data->lines_recorded >= data->max_lines_recorded) {
396 fp_dbg("process_chunk: recorded %d lines, finishing",
397 data->lines_recorded);
398 return 1;
399 }
400 }
401 }
402 return 0;
403 }
404
submit_image(struct fpi_ssm * ssm,struct vfs5011_data * data)405 void submit_image(struct fpi_ssm *ssm, struct vfs5011_data *data)
406 {
407 struct fp_img_dev *dev = (struct fp_img_dev *)ssm->priv;
408 struct fp_img *img;
409
410 data->rows = g_slist_reverse(data->rows);
411
412 img = fpi_assemble_lines(&assembling_ctx, data->rows, data->lines_recorded);
413
414 g_slist_free_full(data->rows, g_free);
415 data->rows = NULL;
416
417 fp_dbg("Image captured, commiting");
418
419 fpi_imgdev_image_captured(dev, img);
420 }
421
chunk_capture_callback(struct libusb_transfer * transfer)422 static void chunk_capture_callback(struct libusb_transfer *transfer)
423 {
424 struct fpi_ssm *ssm = (struct fpi_ssm *)transfer->user_data;
425 struct fp_img_dev *dev = (struct fp_img_dev *)ssm->priv;
426 struct vfs5011_data *data = (struct vfs5011_data *)dev->priv;
427
428 if ((transfer->status == LIBUSB_TRANSFER_COMPLETED) ||
429 (transfer->status == LIBUSB_TRANSFER_TIMED_OUT)) {
430
431 if (transfer->actual_length > 0)
432 fpi_imgdev_report_finger_status(dev, TRUE);
433
434 if (process_chunk(data, transfer->actual_length))
435 fpi_ssm_jump_to_state(ssm, DEV_ACTIVATE_DATA_COMPLETE);
436 else
437 fpi_ssm_jump_to_state(ssm, DEV_ACTIVATE_READ_DATA);
438 } else {
439 if (!data->deactivating) {
440 fp_err("Failed to capture data");
441 fpi_ssm_mark_aborted(ssm, -1);
442 } else {
443 fpi_ssm_mark_completed(ssm);
444 }
445 }
446 libusb_free_transfer(transfer);
447 data->flying_transfer = NULL;
448 }
449
capture_chunk_async(struct vfs5011_data * data,libusb_device_handle * handle,int nline,int timeout,struct fpi_ssm * ssm)450 static int capture_chunk_async(struct vfs5011_data *data,
451 libusb_device_handle *handle, int nline,
452 int timeout, struct fpi_ssm *ssm)
453 {
454 fp_dbg("capture_chunk_async: capture %d lines, already have %d",
455 nline, data->lines_recorded);
456 enum {
457 DEVIATION_THRESHOLD = 15*15,
458 DIFFERENCE_THRESHOLD = 600,
459 STOP_CHECK_LINES = 50
460 };
461
462 data->flying_transfer = libusb_alloc_transfer(0);
463 libusb_fill_bulk_transfer(data->flying_transfer, handle, VFS5011_IN_ENDPOINT_DATA,
464 data->capture_buffer,
465 nline * VFS5011_LINE_SIZE,
466 chunk_capture_callback, ssm, timeout);
467 return libusb_submit_transfer(data->flying_transfer);
468 }
469
async_sleep_cb(void * data)470 static void async_sleep_cb(void *data)
471 {
472 struct fpi_ssm *ssm = data;
473
474 fpi_ssm_next_state(ssm);
475 }
476
477 /*
478 * Device initialization. Windows driver only does it when the device is
479 * plugged in, but it doesn't harm to do this every time before scanning the
480 * image.
481 */
482 struct usb_action vfs5011_initialization[] = {
483 SEND(VFS5011_OUT_ENDPOINT, vfs5011_cmd_01)
484 RECV(VFS5011_IN_ENDPOINT_CTRL, 64)
485
486 SEND(VFS5011_OUT_ENDPOINT, vfs5011_cmd_19)
487 RECV(VFS5011_IN_ENDPOINT_CTRL, 64)
488 RECV(VFS5011_IN_ENDPOINT_CTRL, 64) /* B5C457F9 */
489
490 SEND(VFS5011_OUT_ENDPOINT, vfs5011_init_00)
491 RECV(VFS5011_IN_ENDPOINT_CTRL, 64) /* 0000FFFFFFFF */
492
493 SEND(VFS5011_OUT_ENDPOINT, vfs5011_init_01)
494 RECV(VFS5011_IN_ENDPOINT_CTRL, 64) /* 0000FFFFFFFFFF */
495
496 SEND(VFS5011_OUT_ENDPOINT, vfs5011_init_02)
497 /* 0000 */
498 RECV_CHECK(VFS5011_IN_ENDPOINT_CTRL, 64, VFS5011_NORMAL_CONTROL_REPLY)
499
500 SEND(VFS5011_OUT_ENDPOINT, vfs5011_cmd_01)
501 RECV(VFS5011_IN_ENDPOINT_CTRL, 64)
502
503 SEND(VFS5011_OUT_ENDPOINT, vfs5011_cmd_1A)
504 /* 0000 */
505 RECV_CHECK(VFS5011_IN_ENDPOINT_CTRL, 64, VFS5011_NORMAL_CONTROL_REPLY)
506
507 SEND(VFS5011_OUT_ENDPOINT, vfs5011_init_03)
508 /* 0000 */
509 RECV_CHECK(VFS5011_IN_ENDPOINT_CTRL, 64, VFS5011_NORMAL_CONTROL_REPLY)
510
511 SEND(VFS5011_OUT_ENDPOINT, vfs5011_init_04)
512 /* 0000 */
513 RECV_CHECK(VFS5011_IN_ENDPOINT_CTRL, 64, VFS5011_NORMAL_CONTROL_REPLY)
514 RECV(VFS5011_IN_ENDPOINT_DATA, 256)
515 RECV(VFS5011_IN_ENDPOINT_DATA, 64)
516
517 SEND(VFS5011_OUT_ENDPOINT, vfs5011_cmd_1A)
518 /* 0000 */
519 RECV_CHECK(VFS5011_IN_ENDPOINT_CTRL, 64, VFS5011_NORMAL_CONTROL_REPLY)
520
521 SEND(VFS5011_OUT_ENDPOINT, vfs5011_init_05)
522 /* 0000 */
523 RECV_CHECK(VFS5011_IN_ENDPOINT_CTRL, 64, VFS5011_NORMAL_CONTROL_REPLY)
524
525 SEND(VFS5011_OUT_ENDPOINT, vfs5011_cmd_01)
526 RECV(VFS5011_IN_ENDPOINT_CTRL, 64)
527
528 SEND(VFS5011_OUT_ENDPOINT, vfs5011_init_06)
529 /* 0000 */
530 RECV_CHECK(VFS5011_IN_ENDPOINT_CTRL, 64, VFS5011_NORMAL_CONTROL_REPLY)
531 RECV(VFS5011_IN_ENDPOINT_DATA, 17216)
532 RECV(VFS5011_IN_ENDPOINT_DATA, 32)
533
534 SEND(VFS5011_OUT_ENDPOINT, vfs5011_init_07)
535 /* 0000 */
536 RECV_CHECK(VFS5011_IN_ENDPOINT_CTRL, 64, VFS5011_NORMAL_CONTROL_REPLY)
537 RECV(VFS5011_IN_ENDPOINT_DATA, 45056)
538
539 SEND(VFS5011_OUT_ENDPOINT, vfs5011_init_08)
540 /* 0000 */
541 RECV_CHECK(VFS5011_IN_ENDPOINT_CTRL, 64, VFS5011_NORMAL_CONTROL_REPLY)
542 RECV(VFS5011_IN_ENDPOINT_DATA, 16896)
543
544 SEND(VFS5011_OUT_ENDPOINT, vfs5011_init_09)
545 /* 0000 */
546 RECV_CHECK(VFS5011_IN_ENDPOINT_CTRL, 64, VFS5011_NORMAL_CONTROL_REPLY)
547 RECV(VFS5011_IN_ENDPOINT_DATA, 4928)
548
549 SEND(VFS5011_OUT_ENDPOINT, vfs5011_init_10)
550 /* 0000 */
551 RECV_CHECK(VFS5011_IN_ENDPOINT_CTRL, 64, VFS5011_NORMAL_CONTROL_REPLY)
552 RECV(VFS5011_IN_ENDPOINT_DATA, 5632)
553
554 SEND(VFS5011_OUT_ENDPOINT, vfs5011_init_11)
555 /* 0000 */
556 RECV_CHECK(VFS5011_IN_ENDPOINT_CTRL, 64, VFS5011_NORMAL_CONTROL_REPLY)
557 RECV(VFS5011_IN_ENDPOINT_DATA, 5632)
558
559 SEND(VFS5011_OUT_ENDPOINT, vfs5011_init_12)
560 /* 0000 */
561 RECV_CHECK(VFS5011_IN_ENDPOINT_CTRL, 64, VFS5011_NORMAL_CONTROL_REPLY)
562 RECV(VFS5011_IN_ENDPOINT_DATA, 3328)
563 RECV(VFS5011_IN_ENDPOINT_DATA, 64)
564
565 SEND(VFS5011_OUT_ENDPOINT, vfs5011_init_13)
566 /* 0000 */
567 RECV_CHECK(VFS5011_IN_ENDPOINT_CTRL, 64, VFS5011_NORMAL_CONTROL_REPLY)
568
569 SEND(VFS5011_OUT_ENDPOINT, vfs5011_cmd_1A)
570 /* 0000 */
571 RECV_CHECK(VFS5011_IN_ENDPOINT_CTRL, 64, VFS5011_NORMAL_CONTROL_REPLY)
572
573 SEND(VFS5011_OUT_ENDPOINT, vfs5011_init_03)
574 /* 0000 */
575 RECV_CHECK(VFS5011_IN_ENDPOINT_CTRL, 64, VFS5011_NORMAL_CONTROL_REPLY)
576
577 SEND(VFS5011_OUT_ENDPOINT, vfs5011_init_14)
578 /* 0000 */
579 RECV_CHECK(VFS5011_IN_ENDPOINT_CTRL, 64, VFS5011_NORMAL_CONTROL_REPLY)
580 RECV(VFS5011_IN_ENDPOINT_DATA, 4800)
581
582 SEND(VFS5011_OUT_ENDPOINT, vfs5011_cmd_1A)
583 /* 0000 */
584 RECV_CHECK(VFS5011_IN_ENDPOINT_CTRL, 64, VFS5011_NORMAL_CONTROL_REPLY)
585
586 SEND(VFS5011_OUT_ENDPOINT, vfs5011_init_02)
587 /* 0000 */
588 RECV_CHECK(VFS5011_IN_ENDPOINT_CTRL, 64, VFS5011_NORMAL_CONTROL_REPLY)
589
590 SEND(VFS5011_OUT_ENDPOINT, vfs5011_cmd_27)
591 RECV(VFS5011_IN_ENDPOINT_CTRL, 64)
592
593 SEND(VFS5011_OUT_ENDPOINT, vfs5011_cmd_1A)
594 /* 0000 */
595 RECV_CHECK(VFS5011_IN_ENDPOINT_CTRL, 64, VFS5011_NORMAL_CONTROL_REPLY)
596
597 SEND(VFS5011_OUT_ENDPOINT, vfs5011_init_15)
598 /* 0000 */
599 RECV_CHECK(VFS5011_IN_ENDPOINT_CTRL, 64, VFS5011_NORMAL_CONTROL_REPLY)
600
601 SEND(VFS5011_OUT_ENDPOINT, vfs5011_init_16)
602 RECV(VFS5011_IN_ENDPOINT_CTRL, 2368)
603 RECV(VFS5011_IN_ENDPOINT_CTRL, 64)
604 RECV(VFS5011_IN_ENDPOINT_DATA, 4800)
605
606 SEND(VFS5011_OUT_ENDPOINT, vfs5011_init_17)
607 /* 0000 */
608 RECV_CHECK(VFS5011_IN_ENDPOINT_CTRL, 64, VFS5011_NORMAL_CONTROL_REPLY)
609
610 SEND(VFS5011_OUT_ENDPOINT, vfs5011_init_18)
611 /* 0000 */
612 RECV_CHECK(VFS5011_IN_ENDPOINT_CTRL, 64, VFS5011_NORMAL_CONTROL_REPLY)
613
614 /*
615 * Windows driver does this and it works
616 * But in this driver this call never returns...
617 * RECV(VFS5011_IN_ENDPOINT_CTRL2, 8) //00D3054000
618 */
619 };
620
621 /* Initiate recording the image */
622 struct usb_action vfs5011_initiate_capture[] = {
623 SEND(VFS5011_OUT_ENDPOINT, vfs5011_cmd_04)
624 RECV(VFS5011_IN_ENDPOINT_DATA, 64)
625 RECV(VFS5011_IN_ENDPOINT_DATA, 84032)
626 RECV_CHECK(VFS5011_IN_ENDPOINT_CTRL, 64, VFS5011_NORMAL_CONTROL_REPLY)
627
628 SEND(VFS5011_OUT_ENDPOINT, vfs5011_cmd_1A)
629 RECV_CHECK(VFS5011_IN_ENDPOINT_CTRL, 64, VFS5011_NORMAL_CONTROL_REPLY)
630
631 SEND(VFS5011_OUT_ENDPOINT, vfs5011_prepare_00)
632 RECV_CHECK(VFS5011_IN_ENDPOINT_CTRL, 64, VFS5011_NORMAL_CONTROL_REPLY)
633
634 SEND(VFS5011_OUT_ENDPOINT, vfs5011_cmd_1A)
635 RECV_CHECK(VFS5011_IN_ENDPOINT_CTRL, 64, VFS5011_NORMAL_CONTROL_REPLY)
636
637 SEND(VFS5011_OUT_ENDPOINT, vfs5011_prepare_01)
638 RECV_CHECK(VFS5011_IN_ENDPOINT_CTRL, 64, VFS5011_NORMAL_CONTROL_REPLY)
639
640 SEND(VFS5011_OUT_ENDPOINT, vfs5011_prepare_02)
641 RECV(VFS5011_IN_ENDPOINT_CTRL, 2368)
642 RECV(VFS5011_IN_ENDPOINT_CTRL, 64)
643 RECV(VFS5011_IN_ENDPOINT_DATA, 4800)
644
645 SEND(VFS5011_OUT_ENDPOINT, vfs5011_prepare_03)
646 RECV_CHECK(VFS5011_IN_ENDPOINT_CTRL, 64, VFS5011_NORMAL_CONTROL_REPLY)
647 /*
648 * Windows driver does this and it works
649 * But in this driver this call never returns...
650 * RECV(VFS5011_IN_ENDPOINT_CTRL2, 8);
651 */
652
653 SEND(VFS5011_OUT_ENDPOINT, vfs5011_prepare_04)
654 RECV_CHECK(VFS5011_IN_ENDPOINT_CTRL, 2368, VFS5011_NORMAL_CONTROL_REPLY)
655
656 /*
657 * Windows driver does this and it works
658 * But in this driver this call never returns...
659 * RECV(VFS5011_IN_ENDPOINT_CTRL2, 8);
660 */
661 };
662
663 /* ====================== lifprint interface ======================= */
664
activate_loop(struct fpi_ssm * ssm)665 static void activate_loop(struct fpi_ssm *ssm)
666 {
667 enum {READ_TIMEOUT = 0};
668
669 struct fp_img_dev *dev = (struct fp_img_dev *)ssm->priv;
670 struct vfs5011_data *data = (struct vfs5011_data *)dev->priv;
671 int r;
672 struct fpi_timeout *timeout;
673
674 fp_dbg("main_loop: state %d", ssm->cur_state);
675
676 if (data->deactivating) {
677 fp_dbg("deactivating, marking completed");
678 fpi_ssm_mark_completed(ssm);
679 return;
680 }
681
682 switch (ssm->cur_state) {
683 case DEV_ACTIVATE_REQUEST_FPRINT:
684 data->init_sequence.stepcount =
685 array_n_elements(vfs5011_initiate_capture);
686 data->init_sequence.actions = vfs5011_initiate_capture;
687 data->init_sequence.device = dev;
688 if (data->init_sequence.receive_buf == NULL)
689 data->init_sequence.receive_buf =
690 g_malloc0(VFS5011_RECEIVE_BUF_SIZE);
691 data->init_sequence.timeout = 1000;
692 usb_exchange_async(ssm, &data->init_sequence);
693 break;
694
695 case DEV_ACTIVATE_INIT_COMPLETE:
696 if (data->init_sequence.receive_buf != NULL)
697 g_free(data->init_sequence.receive_buf);
698 data->init_sequence.receive_buf = NULL;
699 capture_init(data, MAX_CAPTURE_LINES, MAXLINES);
700 fpi_imgdev_activate_complete(dev, 0);
701 fpi_ssm_next_state(ssm);
702 break;
703
704 case DEV_ACTIVATE_READ_DATA:
705 r = capture_chunk_async(data, dev->udev, CAPTURE_LINES,
706 READ_TIMEOUT, ssm);
707 if (r != 0) {
708 fp_err("Failed to capture data");
709 fpi_imgdev_session_error(dev, r);
710 fpi_ssm_mark_aborted(ssm, r);
711 }
712 break;
713
714 case DEV_ACTIVATE_DATA_COMPLETE:
715 timeout = fpi_timeout_add(1, async_sleep_cb, ssm);
716
717 if (timeout == NULL) {
718 /* Failed to add timeout */
719 fp_err("failed to add timeout");
720 fpi_imgdev_session_error(dev, -1);
721 fpi_ssm_mark_aborted(ssm, -1);
722 }
723 break;
724
725 case DEV_ACTIVATE_PREPARE_NEXT_CAPTURE:
726 data->init_sequence.stepcount =
727 array_n_elements(vfs5011_initiate_capture);
728 data->init_sequence.actions = vfs5011_initiate_capture;
729 data->init_sequence.device = dev;
730 if (data->init_sequence.receive_buf == NULL)
731 data->init_sequence.receive_buf =
732 g_malloc0(VFS5011_RECEIVE_BUF_SIZE);
733 data->init_sequence.timeout = VFS5011_DEFAULT_WAIT_TIMEOUT;
734 usb_exchange_async(ssm, &data->init_sequence);
735 break;
736
737 }
738 }
739
activate_loop_complete(struct fpi_ssm * ssm)740 static void activate_loop_complete(struct fpi_ssm *ssm)
741 {
742 struct fp_img_dev *dev = (struct fp_img_dev *)ssm->priv;
743 struct vfs5011_data *data = (struct vfs5011_data *)dev->priv;
744 int r = ssm->error;
745
746 fp_dbg("finishing");
747 if (data->init_sequence.receive_buf != NULL)
748 g_free(data->init_sequence.receive_buf);
749 data->init_sequence.receive_buf = NULL;
750 /* We don't want to submit image if we're in deactivating process */
751 if (!data->deactivating) {
752 submit_image(ssm, data);
753 fpi_imgdev_report_finger_status(dev, FALSE);
754 }
755 fpi_ssm_free(ssm);
756
757 data->loop_running = FALSE;
758
759 if (data->deactivating) {
760 fpi_imgdev_deactivate_complete(dev);
761 } else if (r) {
762 fpi_imgdev_session_error(dev, r);
763 } else {
764 start_scan(dev);
765 }
766 }
767
768
open_loop(struct fpi_ssm * ssm)769 static void open_loop(struct fpi_ssm *ssm)
770 {
771 struct fp_img_dev *dev = (struct fp_img_dev *)ssm->priv;
772 struct vfs5011_data *data = (struct vfs5011_data *)dev->priv;
773
774 switch (ssm->cur_state) {
775 case DEV_OPEN_START:
776 data->init_sequence.stepcount =
777 array_n_elements(vfs5011_initialization);
778 data->init_sequence.actions = vfs5011_initialization;
779 data->init_sequence.device = dev;
780 data->init_sequence.receive_buf =
781 g_malloc0(VFS5011_RECEIVE_BUF_SIZE);
782 data->init_sequence.timeout = VFS5011_DEFAULT_WAIT_TIMEOUT;
783 usb_exchange_async(ssm, &data->init_sequence);
784 break;
785 };
786 }
787
open_loop_complete(struct fpi_ssm * ssm)788 static void open_loop_complete(struct fpi_ssm *ssm)
789 {
790 struct fp_img_dev *dev = (struct fp_img_dev *)ssm->priv;
791 struct vfs5011_data *data = (struct vfs5011_data *)dev->priv;
792
793 g_free(data->init_sequence.receive_buf);
794 data->init_sequence.receive_buf = NULL;
795
796 fpi_imgdev_open_complete(dev, 0);
797 fpi_ssm_free(ssm);
798 }
799
dev_open(struct fp_img_dev * dev,unsigned long driver_data)800 static int dev_open(struct fp_img_dev *dev, unsigned long driver_data)
801 {
802
803 struct vfs5011_data *data;
804 int r;
805
806 data = (struct vfs5011_data *)g_malloc0(sizeof(*data));
807 data->capture_buffer =
808 (unsigned char *)g_malloc0(CAPTURE_LINES * VFS5011_LINE_SIZE);
809 dev->priv = data;
810
811 r = libusb_reset_device(dev->udev);
812 if (r != 0) {
813 fp_err("Failed to reset the device");
814 return r;
815 }
816
817 r = libusb_claim_interface(dev->udev, 0);
818 if (r != 0) {
819 fp_err("Failed to claim interface: %s", libusb_error_name(r));
820 return r;
821 }
822
823 struct fpi_ssm *ssm;
824 ssm = fpi_ssm_new(dev->dev, open_loop, DEV_OPEN_NUM_STATES);
825 ssm->priv = dev;
826 fpi_ssm_start(ssm, open_loop_complete);
827
828 return 0;
829 }
830
dev_close(struct fp_img_dev * dev)831 static void dev_close(struct fp_img_dev *dev)
832 {
833 libusb_release_interface(dev->udev, 0);
834 struct vfs5011_data *data = (struct vfs5011_data *)dev->priv;
835 if (data != NULL) {
836 g_free(data->capture_buffer);
837 g_slist_free_full(data->rows, g_free);
838 g_free(data);
839 }
840 fpi_imgdev_close_complete(dev);
841 }
842
start_scan(struct fp_img_dev * dev)843 static void start_scan(struct fp_img_dev *dev)
844 {
845 struct vfs5011_data *data = (struct vfs5011_data *)dev->priv;
846 struct fpi_ssm *ssm;
847
848 data->loop_running = TRUE;
849 fp_dbg("creating ssm");
850 ssm = fpi_ssm_new(dev->dev, activate_loop, DEV_ACTIVATE_NUM_STATES);
851 ssm->priv = dev;
852 fp_dbg("starting ssm");
853 fpi_ssm_start(ssm, activate_loop_complete);
854 fp_dbg("ssm done, getting out");
855 }
856
dev_activate(struct fp_img_dev * dev,enum fp_imgdev_state state)857 static int dev_activate(struct fp_img_dev *dev, enum fp_imgdev_state state)
858 {
859 struct vfs5011_data *data = (struct vfs5011_data *)dev->priv;
860
861 fp_dbg("device initialized");
862 data->deactivating = FALSE;
863
864 start_scan(dev);
865
866 return 0;
867 }
868
dev_deactivate(struct fp_img_dev * dev)869 static void dev_deactivate(struct fp_img_dev *dev)
870 {
871 int r;
872 struct vfs5011_data *data = dev->priv;
873 if (data->loop_running) {
874 data->deactivating = TRUE;
875 if (data->flying_transfer) {
876 r = libusb_cancel_transfer(data->flying_transfer);
877 if (r < 0)
878 fp_dbg("cancel failed error %d", r);
879 }
880 } else
881 fpi_imgdev_deactivate_complete(dev);
882 }
883
884 static const struct usb_id id_table[] = {
885 { .vendor = 0x138a, .product = 0x0010 /* Validity device from some Toshiba laptops */ },
886 { .vendor = 0x138a, .product = 0x0011 /* vfs5011 */ },
887 { .vendor = 0x138a, .product = 0x0017 /* Validity device from Lenovo T440 laptops */ },
888 { .vendor = 0x138a, .product = 0x0018 /* one more Validity device */ },
889 { 0, 0, 0, },
890 };
891
892 struct fp_img_driver vfs5011_driver = {
893 .driver = {
894 .id = VFS5011_ID,
895 .name = "vfs5011",
896 .full_name = "Validity VFS5011",
897 .id_table = id_table,
898 .scan_type = FP_SCAN_TYPE_SWIPE,
899 },
900
901 .flags = 0,
902 .img_width = VFS5011_IMAGE_WIDTH,
903 .img_height = -1,
904 .bz3_threshold = 20,
905
906 .open = dev_open,
907 .close = dev_close,
908 .activate = dev_activate,
909 .deactivate = dev_deactivate,
910 };
911
912