GCC Code Coverage Report


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 92.5% 260 / 0 / 281
Functions: 100.0% 16 / 0 / 16
Branches: 71.0% 66 / 0 / 93

libfprint/drivers/vfs301_proto.c
Line Branch Exec Source
1 /*
2 * vfs301/vfs300 fingerprint reader driver
3 * https://github.com/andree182/vfs301
4 *
5 * Copyright (c) 2011-2012 Andrej Krutak <dev@andree.sk>
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22 /*
23 * TODO:
24 * - async communication everywhere :)
25 * - protocol decyphering
26 * - what is needed and what is redundant
27 * - is some part of the initial data the firmware?
28 * - describe some interesting structures better
29 */
30 #include <errno.h>
31 #include <string.h>
32 #include <stdio.h>
33 #include <unistd.h>
34 #include <stdlib.h>
35 #include <glib.h>
36
37 #include "fpi-usb-transfer.h"
38 #include "vfs301.h"
39 #include "vfs301_proto_fragments.h"
40
41 /************************** USB STUFF *****************************************/
42
43 #ifdef DEBUG
44 static void
45 usb_print_packet (int dir, GError *error, const guint8 *data, int length)
46 {
47 fprintf (stderr, "%s, error %s, len %d\n", dir ? "send" : "recv", error ? error->message : "-", length);
48
49 #ifdef PRINT_VERBOSE
50 int i;
51
52 for (i = 0; i < MIN (length, 128); i++)
53 {
54 fprintf (stderr, "%.2X ", data[i]);
55 if (i % 8 == 7)
56 fprintf (stderr, " ");
57 if (i % 32 == 31)
58 fprintf (stderr, "\n");
59 }
60 #endif
61
62 fprintf (stderr, "\n");
63 }
64 #endif
65
66 static gboolean
67 51 usb_recv (FpDeviceVfs301 *dev, guint8 endpoint, int max_bytes, FpiUsbTransfer **out, GError **error)
68 {
69 51 GError *err = NULL;
70
71 102 g_autoptr(FpiUsbTransfer) transfer = NULL;
72
73 /* XXX: This function swallows any transfer errors, that is obviously
74 * quite bad (it used to assert on no-error)! */
75
76 51 transfer = fpi_usb_transfer_new (FP_DEVICE (dev));
77 51 transfer->short_is_error = TRUE;
78 51 fpi_usb_transfer_fill_bulk (transfer, endpoint, max_bytes);
79
80 51 fpi_usb_transfer_submit_sync (transfer, VFS301_DEFAULT_WAIT_TIMEOUT, &err);
81
82 #ifdef DEBUG
83 usb_print_packet (0, err, transfer->buffer, transfer->actual_length);
84 #endif
85
1/2
✗ Branch 5 → 6 not taken.
✓ Branch 5 → 9 taken 51 times.
51 if (err)
86 {
87 if (!error)
88 g_warning ("Unhandled receive error: %s", err->message);
89 g_propagate_error (error, err);
90
91 return FALSE;
92 }
93
94
2/2
✓ Branch 9 → 10 taken 2 times.
✓ Branch 9 → 12 taken 49 times.
51 if (out)
95 2 *out = g_steal_pointer (&transfer);
96
97 return TRUE;
98 }
99
100 FP_GNUC_ACCESS (read_only, 2, 3)
101 static void
102 35 usb_send (FpDeviceVfs301 *dev, const guint8 *data, gssize length, GError **error)
103 {
104 35 GError *err = NULL;
105
106 70 g_autoptr(FpiUsbTransfer) transfer = NULL;
107
108 /* XXX: This function swallows any transfer errors, that is obviously
109 * quite bad (it used to assert on no-error)! */
110
111 35 transfer = fpi_usb_transfer_new (FP_DEVICE (dev));
112 35 transfer->short_is_error = TRUE;
113 35 fpi_usb_transfer_fill_bulk_full (transfer, VFS301_SEND_ENDPOINT, (guint8 *) data, length, g_free);
114
115 35 fpi_usb_transfer_submit_sync (transfer, VFS301_DEFAULT_WAIT_TIMEOUT, &err);
116
117 #ifdef DEBUG
118 usb_print_packet (1, err, data, length);
119 #endif
120
121
1/2
✗ Branch 5 → 6 not taken.
✓ Branch 5 → 8 taken 35 times.
35 if (err)
122 {
123 g_warning ("Error while sending data, continuing anyway: %s", err->message);
124 g_propagate_error (error, err);
125 }
126 35 }
127
128 /************************** OUT MESSAGES GENERATION ***************************/
129
130 static guint8 *
131 2 vfs301_proto_generate_0B (int subtype, gssize *len)
132 {
133 2 guint8 *res = g_malloc0 (39);
134 2 guint8 *data = res;
135
136 2 *data = 0x0B;
137 2 *len = 1;
138 2 data++;
139
140 2 *len += 38;
141
142 2 data[20] = subtype;
143
144
2/3
✓ Branch 3 → 4 taken 1 time.
✓ Branch 3 → 5 taken 1 time.
✗ Branch 3 → 6 not taken.
2 switch (subtype)
145 {
146 1 case 0x04:
147 1 data[34] = 0x9F;
148 1 break;
149
150 1 case 0x05:
151 1 data[34] = 0xAB;
152 /* NOTE: There was a len++ here, which could never do anything */
153 1 break;
154
155 default:
156 g_assert_not_reached ();
157 break;
158 }
159
160 2 return res;
161 }
162
163 #define HEX_TO_INT(c) \
164 (((c) >= '0' && (c) <= '9') ? ((c) - '0') : ((c) - 'A' + 10))
165
166 static guint8 *
167 12 translate_str (const char **srcL, gssize *len)
168 {
169 12 guint8 *res = NULL;
170 12 guint8 *dst;
171 12 const char **src_pos;
172 12 const char *src;
173 12 gssize src_len = 0;
174
175
2/2
✓ Branch 6 → 3 taken 997 times.
✓ Branch 6 → 7 taken 12 times.
1009 for (src_pos = srcL; *src_pos; src_pos++)
176 {
177 997 gint tmp;
178
179 997 src = *src_pos;
180 997 tmp = strlen (src);
181
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 997 times.
997 g_assert (tmp % 2 == 0);
182 997 src_len += tmp;
183 }
184
185
1/2
✓ Branch 7 → 8 taken 12 times.
✗ Branch 7 → 10 not taken.
12 g_assert (src_len >= 2);
186 12 *len = src_len / 2;
187 12 res = g_malloc0 (*len);
188 12 dst = res;
189
190
2/2
✓ Branch 19 → 17 taken 997 times.
✓ Branch 19 → 20 taken 12 times.
1021 for (src_pos = srcL; *src_pos; src_pos++)
191
2/2
✓ Branch 17 → 11 taken 29062 times.
✓ Branch 17 → 18 taken 997 times.
30059 for (src = *src_pos; *src; src += 2, dst += 1)
192
4/4
✓ Branch 11 → 12 taken 25170 times.
✓ Branch 11 → 13 taken 3892 times.
✓ Branch 14 → 15 taken 2498 times.
✓ Branch 14 → 16 taken 26564 times.
29062 *dst = (guint8) ((HEX_TO_INT (src[0]) << 4) | (HEX_TO_INT (src[1])));
193
194 12 return res;
195 }
196
197 static guint8 *
198 27 vfs301_proto_generate (int type, int subtype, gssize *len)
199 {
200
4/5
✓ Branch 2 → 3 taken 13 times.
✓ Branch 2 → 5 taken 2 times.
✓ Branch 2 → 6 taken 7 times.
✓ Branch 2 → 10 taken 5 times.
✗ Branch 2 → 28 not taken.
27 switch (type)
201 {
202 13 case 0x01:
203 case 0x04:
204 /* After cmd 0x04 is sent, a data is received on VALIDITY_RECEIVE_ENDPOINT_CTRL.
205 * If it is 0x0000:
206 * additional 64B and 224B are read from _DATA, then vfs301_next_scan_FA00 is
207 * sent, 0000 received from _CTRL, and then continue with wait loop
208 * If it is 0x1204:
209 * => reinit?
210 */
211 case 0x17:
212 case 0x19:
213 case 0x1A:
214 {
215 13 guint8 *data = g_malloc0 (1);
216 13 *data = type;
217 13 *len = 1;
218 13 return data;
219 }
220
221 2 case 0x0B:
222 2 return vfs301_proto_generate_0B (subtype, len);
223
224 7 case 0x02D0:
225 {
226 7 const char **dataLs[] = {
227 vfs301_02D0_01,
228 vfs301_02D0_02,
229 vfs301_02D0_03,
230 vfs301_02D0_04,
231 vfs301_02D0_05,
232 vfs301_02D0_06,
233 vfs301_02D0_07,
234 };
235
1/2
✗ Branch 6 → 7 not taken.
✓ Branch 6 → 8 taken 7 times.
7 g_assert ((int) subtype <= G_N_ELEMENTS (dataLs));
236 7 return translate_str (dataLs[subtype - 1], len);
237 }
238
239 5 case 0x0220:
240
4/5
✓ Branch 10 → 11 taken 1 time.
✓ Branch 10 → 12 taken 2 times.
✓ Branch 10 → 13 taken 1 time.
✓ Branch 10 → 14 taken 1 time.
✗ Branch 10 → 27 not taken.
5 switch (subtype)
241 {
242 1 case 1:
243 1 return translate_str (vfs301_0220_01, len);
244
245 2 case 2:
246 2 return translate_str (vfs301_0220_02, len);
247
248 1 case 3:
249 1 return translate_str (vfs301_0220_03, len);
250
251 1 case 0xFA00:
252 case 0x2C01:
253 case 0x5E01: {
254 1 guint8 *data;
255 1 guint8 *field;
256
257 1 data = translate_str (vfs301_next_scan_template, len);
258 1 field = data + *len - (sizeof (S4_TAIL) - 1) / 2 - 4;
259
260
2/4
✓ Branch 15 → 16 taken 1 time.
✗ Branch 15 → 18 not taken.
✓ Branch 16 → 17 taken 1 time.
✗ Branch 16 → 18 not taken.
1 g_assert (field >= data && field < data + *len);
261
1/2
✓ Branch 17 → 19 taken 1 time.
✗ Branch 17 → 20 not taken.
1 g_assert (field[0] == 0xDE);
262
1/2
✓ Branch 19 → 21 taken 1 time.
✗ Branch 19 → 22 not taken.
1 g_assert (field[1] == 0xAD);
263
1/2
✓ Branch 21 → 23 taken 1 time.
✗ Branch 21 → 24 not taken.
1 g_assert (field[2] == 0xDE);
264
1/2
✓ Branch 23 → 25 taken 1 time.
✗ Branch 23 → 26 not taken.
1 g_assert (field[3] == 0xAD);
265
266 1 field[0] = (guint8) ((subtype >> 8) & 0xFF);
267 1 field[1] = (guint8) (subtype & 0xFF);
268 1 field[2] = field[0];
269 1 field[3] = field[1];
270
271 1 return data;
272 }
273
274 default:
275 g_assert_not_reached ();
276 break;
277 }
278 break;
279
280 case 0x06:
281 default:
282 break;
283 }
284
285 g_assert_not_reached ();
286 *len = 0;
287 return NULL;
288 }
289
290 /************************** SCAN IMAGE PROCESSING *****************************/
291
292 #ifdef SCAN_FINISH_DETECTION
293 static int
294 img_is_finished_scan (fp_line_t *lines, int no_lines)
295 {
296 int i;
297 int j;
298 int rv = 1;
299
300 for (i = no_lines - VFS301_FP_SUM_LINES; i < no_lines; i++)
301 {
302 /* check the line for fingerprint data */
303 for (j = 0; j < sizeof (lines[i].sum2); j++)
304 if (lines[i].sum2[j] > (VFS301_FP_SUM_MEDIAN + VFS301_FP_SUM_EMPTY_RANGE))
305 rv = 0;
306 }
307
308 return rv;
309 }
310 #endif
311
312 static int
313 874 scanline_diff (const guint8 *scanlines, int prev, int cur)
314 {
315 874 const guint8 *line1 = scanlines + prev * VFS301_FP_OUTPUT_WIDTH;
316 874 const guint8 *line2 = scanlines + cur * VFS301_FP_OUTPUT_WIDTH;
317 874 int i;
318 874 int diff;
319
320 #ifdef OUTPUT_RAW
321 /* We only need the image, not the surrounding stuff. */
322 line1 = ((vfs301_line_t *) line1)->scan;
323 line2 = ((vfs301_line_t *) line2)->scan;
324 #endif
325
326 /* TODO: This doesn't work too well when there are parallel lines in the
327 * fingerprint. */
328
2/2
✓ Branch 7 → 3 taken 174800 times.
✓ Branch 7 → 8 taken 874 times.
175674 for (diff = 0, i = 0; i < VFS301_FP_WIDTH; i++)
329 {
330
2/2
✓ Branch 3 → 4 taken 80521 times.
✓ Branch 3 → 5 taken 94279 times.
174800 if (*line1 > *line2)
331 80521 diff += *line1 - *line2;
332 else
333 94279 diff += *line2 - *line1;
334
335 174800 line1++;
336 174800 line2++;
337 }
338
339 874 return (diff / VFS301_FP_WIDTH) > VFS301_FP_LINE_DIFF_THRESHOLD;
340 }
341
342 /** Transform the input data to a normalized fingerprint scan */
343 void
344 1 vfs301_extract_image (FpDeviceVfs301 *vfs, guint8 *output, int *output_height
345 )
346 {
347 1 const guint8 *scanlines = vfs->scanline_buf;
348 1 int last_line;
349 1 int i;
350
351
2/4
✓ Branch 2 → 3 taken 1 time.
✗ Branch 2 → 4 not taken.
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 1 time.
1 if (vfs->scanline_count < 1 || scanlines == NULL)
352 {
353 *output_height = 0;
354 g_return_if_reached ();
355 }
356
357 1 *output_height = 1;
358 1 memcpy (output, scanlines, VFS301_FP_OUTPUT_WIDTH);
359 1 last_line = 0;
360
361 /* The following algorithm is quite trivial - it just picks lines that
362 * differ more than VFS301_FP_LINE_DIFF_THRESHOLD.
363 * TODO: A nicer approach would be to pick those lines and then do some kind
364 * of bi/tri-linear resampling to get the output (so that we don't get so
365 * many false edges etc.).
366 */
367
2/2
✓ Branch 9 → 6 taken 874 times.
✓ Branch 9 → 10 taken 1 time.
875 for (i = 1; i < vfs->scanline_count; i++)
368 {
369
2/2
✓ Branch 6 → 7 taken 213 times.
✓ Branch 6 → 8 taken 661 times.
874 if (scanline_diff (scanlines, last_line, i))
370 {
371 213 memcpy (
372 213 output + VFS301_FP_OUTPUT_WIDTH * (*output_height),
373 213 scanlines + VFS301_FP_OUTPUT_WIDTH * i,
374 VFS301_FP_OUTPUT_WIDTH
375 );
376 213 last_line = i;
377 213 (*output_height)++;
378 }
379 }
380 }
381
382 static int
383 3 img_process_data (int first_block, FpDeviceVfs301 *dev, const guint8 *buf, int len)
384 {
385 3 vfs301_line_t *lines = (vfs301_line_t *) buf;
386 3 int no_lines = len / sizeof (vfs301_line_t);
387 3 int i;
388 /*int no_nonempty;*/
389 3 guint8 *cur_line;
390 3 int last_img_height;
391
392 #ifdef SCAN_FINISH_DETECTION
393 int finished_scan;
394 #endif
395
396
2/2
✓ Branch 2 → 3 taken 2 times.
✓ Branch 2 → 4 taken 1 time.
3 if (first_block)
397 {
398 3 last_img_height = 0;
399 dev->scanline_count = no_lines;
400 }
401 else
402 {
403 2 last_img_height = dev->scanline_count;
404 2 dev->scanline_count += no_lines;
405 }
406
407 3 dev->scanline_buf = g_realloc (dev->scanline_buf, dev->scanline_count * VFS301_FP_OUTPUT_WIDTH);
408
409 3 for (cur_line = dev->scanline_buf + last_img_height * VFS301_FP_OUTPUT_WIDTH, i = 0;
410
2/2
✓ Branch 7 → 6 taken 875 times.
✓ Branch 7 → 8 taken 3 times.
878 i < no_lines;
411 875 i++, cur_line += VFS301_FP_OUTPUT_WIDTH
412 )
413 {
414 #ifndef OUTPUT_RAW
415 875 memcpy (cur_line, lines[i].scan, VFS301_FP_OUTPUT_WIDTH);
416 #else
417 memcpy (cur_line, &lines[i], VFS301_FP_OUTPUT_WIDTH);
418 #endif
419 }
420
421 #ifdef SCAN_FINISH_DETECTION
422 finished_scan = img_is_finished_scan (lines, no_lines);
423
424 return !finished_scan;
425 #else /* SCAN_FINISH_DETECTION */
426 3 return 1; /* Just continue until data is coming */
427 #endif
428 }
429
430 /************************** PROTOCOL STUFF ************************************/
431
432 #define USB_RECV(from, len) \
433 usb_recv (dev, from, len, NULL, NULL)
434
435 #define USB_SEND(type, subtype) \
436 { \
437 const guint8 *data; \
438 gssize len; \
439 data = vfs301_proto_generate (type, subtype, &len); \
440 usb_send (dev, data, len, NULL); \
441 }
442
443 #define RAW_DATA(x) g_memdup2 (x, sizeof (x)), sizeof (x)
444
445 #define IS_VFS301_FP_SEQ_START(b) ((b[0] == 0x01) && (b[1] == 0xfe))
446
447 static int
448 3 vfs301_proto_process_data (FpDeviceVfs301 *dev, int first_block, const guint8 *buf, gint len)
449 {
450 3 int i;
451
452
2/2
✓ Branch 2 → 3 taken 1 time.
✓ Branch 2 → 10 taken 2 times.
3 if (first_block)
453 {
454
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 9 taken 1 time.
1 if (len < VFS301_FP_FRAME_SIZE)
455 g_return_val_if_reached (img_process_data (first_block, dev, buf, 0));
456
457 /* Skip bytes until start_sequence is found */
458
1/2
✓ Branch 9 → 6 taken 225 times.
✗ Branch 9 → 10 not taken.
225 for (i = 0; i < VFS301_FP_FRAME_SIZE; i++, buf++, len--)
459
4/4
✓ Branch 6 → 7 taken 3 times.
✓ Branch 6 → 8 taken 222 times.
✓ Branch 7 → 8 taken 2 times.
✓ Branch 7 → 10 taken 1 time.
225 if (IS_VFS301_FP_SEQ_START (buf))
460 break;
461 }
462
463 3 return img_process_data (first_block, dev, buf, len);
464 }
465
466 void
467 1 vfs301_proto_request_fingerprint (FpDeviceVfs301 *dev)
468 {
469 1 USB_SEND (0x0220, 0xFA00);
470 1 USB_RECV (VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 000000000000 */
471 1 }
472
473 int
474 2 vfs301_proto_peek_event (FpDeviceVfs301 *dev,
475 GError **error)
476 {
477 4 g_autoptr(FpiUsbTransfer) transfer = NULL;
478
479 2 const char no_event[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
480 2 const char got_event[] = {0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00};
481
482 2 USB_SEND (0x17, -1);
483
1/2
✓ Branch 5 → 6 taken 2 times.
✗ Branch 5 → 10 not taken.
2 if (!usb_recv (dev, VFS301_RECEIVE_ENDPOINT_CTRL, 7, &transfer, error))
484 return -1;
485
486
2/2
✓ Branch 6 → 7 taken 1 time.
✓ Branch 6 → 10 taken 1 time.
2 if (memcmp (transfer->buffer, no_event, sizeof (no_event)) == 0)
487 return 0;
488
1/2
✗ Branch 7 → 8 not taken.
✓ Branch 7 → 10 taken 1 time.
1 else if (memcmp (transfer->buffer, got_event, sizeof (no_event)) == 0)
489 return 1;
490
491 g_set_error (error, FP_DEVICE_ERROR_PROTO, 0, "Unexpected event response");
492 return -1;
493 }
494
495 /* XXX: We sometimes need to receive data on from two endpoints at the same
496 * time. However, as this driver is currently all synchronous (yikes),
497 * we will run into timeouts randomly and need to then try again.
498 */
499 #define PARALLEL_RECEIVE(e1, l1, e2, l2) \
500 { \
501 g_autoptr(GError) error = NULL; \
502 usb_recv (dev, e1, l1, NULL, &error); \
503 usb_recv (dev, e2, l2, NULL, NULL); \
504 if (g_error_matches (error, G_USB_DEVICE_ERROR, G_USB_DEVICE_ERROR_TIMED_OUT)) \
505 usb_recv (dev, e1, l1, NULL, NULL); \
506 }
507
508 static void
509 4 vfs301_proto_process_event_cb (FpiUsbTransfer *transfer,
510 FpDevice *device,
511 gpointer user_data, GError *error)
512 {
513 4 FpDeviceVfs301 *self = FPI_DEVICE_VFS301 (device);
514
515
1/2
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 6 taken 4 times.
4 if (error)
516 {
517 g_warning ("Error receiving data: %s", error->message);
518 g_error_free (error);
519 self->recv_progress = VFS301_FAILURE;
520 return;
521 }
522
2/2
✓ Branch 6 → 7 taken 1 time.
✓ Branch 6 → 8 taken 3 times.
4 else if (transfer->actual_length < transfer->length)
523 {
524 /* TODO: process the data anyway? */
525 1 self->recv_progress = VFS301_ENDED;
526 1 return;
527 }
528 else
529 {
530 3 FpiUsbTransfer *new;
531 3 if (!vfs301_proto_process_data (self,
532 transfer->length == VFS301_FP_RECV_LEN_1,
533 3 transfer->buffer,
534 transfer->actual_length))
535 {
536 self->recv_progress = VFS301_ENDED;
537 return;
538 }
539
540 3 new = fpi_usb_transfer_new (device);
541
542 3 fpi_usb_transfer_fill_bulk (new, VFS301_RECEIVE_ENDPOINT_DATA, VFS301_FP_RECV_LEN_2);
543 3 fpi_usb_transfer_submit (new, VFS301_FP_RECV_TIMEOUT, NULL,
544 vfs301_proto_process_event_cb, NULL);
545 3 return;
546 }
547 }
548
549 void
550 1 vfs301_proto_process_event_start (FpDeviceVfs301 *dev)
551 {
552 1 FpiUsbTransfer *transfer;
553
554 /*
555 * Notes:
556 *
557 * seen next_scan order:
558 * o FA00
559 * o FA00
560 * o 2C01
561 * o FA00
562 * o FA00
563 * o 2C01
564 * o FA00
565 * o FA00
566 * o 2C01
567 * o 5E01 !?
568 * o FA00
569 * o FA00
570 * o 2C01
571 * o FA00
572 * o FA00
573 * o 2C01
574 */
575 1 USB_RECV (VFS301_RECEIVE_ENDPOINT_DATA, 64);
576
577 /* now read the fingerprint data, while there are some */
578 1 transfer = fpi_usb_transfer_new (FP_DEVICE (dev));
579 1 dev->recv_progress = VFS301_ONGOING;
580
581 1 fpi_usb_transfer_fill_bulk (transfer, VFS301_RECEIVE_ENDPOINT_DATA, VFS301_FP_RECV_LEN_1);
582 1 fpi_usb_transfer_submit (transfer, VFS301_FP_RECV_TIMEOUT, NULL,
583 vfs301_proto_process_event_cb, NULL);
584 1 }
585
586 int
587 1 vfs301_proto_process_event_poll (FpDeviceVfs301 *dev)
588 {
589
1/2
✓ Branch 2 → 3 taken 1 time.
✗ Branch 2 → 24 not taken.
1 if (dev->recv_progress != VFS301_ENDED)
590 return dev->recv_progress;
591
592 /* Finish the scan process... */
593
594 1 USB_SEND (0x04, -1);
595 /* the following may come in random order, data may not come at all, don't
596 * try for too long... */
597
1/2
✗ Branch 9 → 10 not taken.
✓ Branch 9 → 11 taken 1 time.
1 PARALLEL_RECEIVE (
598 VFS301_RECEIVE_ENDPOINT_CTRL, 2, /* 1204 */
599 VFS301_RECEIVE_ENDPOINT_DATA, 16384
600 1 );
601
602 1 USB_SEND (0x0220, 2);
603
1/2
✗ Branch 19 → 20 not taken.
✓ Branch 19 → 21 taken 1 time.
1 PARALLEL_RECEIVE (
604 VFS301_RECEIVE_ENDPOINT_DATA, 5760, /* seems to always come */
605 VFS301_RECEIVE_ENDPOINT_CTRL, 2 /* 0000 */
606 1 );
607
608 1 return dev->recv_progress;
609 }
610
611 void
612 1 vfs301_proto_init (FpDeviceVfs301 *dev)
613 {
614 1 USB_SEND (0x01, -1);
615 1 USB_RECV (VFS301_RECEIVE_ENDPOINT_CTRL, 38);
616 1 USB_SEND (0x0B, 0x04);
617 1 USB_RECV (VFS301_RECEIVE_ENDPOINT_CTRL, 6); /* 000000000000 */
618 1 USB_SEND (0x0B, 0x05);
619 1 USB_RECV (VFS301_RECEIVE_ENDPOINT_CTRL, 7); /* 00000000000000 */
620 1 USB_SEND (0x19, -1);
621 1 USB_RECV (VFS301_RECEIVE_ENDPOINT_CTRL, 64);
622 1 USB_RECV (VFS301_RECEIVE_ENDPOINT_CTRL, 4); /* 6BB4D0BC */
623 1 usb_send (dev, RAW_DATA (vfs301_06_1), NULL);
624 1 USB_RECV (VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */
625
626 1 USB_SEND (0x01, -1);
627 1 USB_RECV (VFS301_RECEIVE_ENDPOINT_CTRL, 38);
628 1 USB_SEND (0x1A, -1);
629 1 USB_RECV (VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */
630 1 usb_send (dev, RAW_DATA (vfs301_06_2), NULL);
631 1 USB_RECV (VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */
632 1 USB_SEND (0x0220, 1);
633 1 USB_RECV (VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */
634 1 USB_RECV (VFS301_RECEIVE_ENDPOINT_DATA, 256);
635 1 USB_RECV (VFS301_RECEIVE_ENDPOINT_DATA, 32);
636
637 1 USB_SEND (0x1A, -1);
638 1 USB_RECV (VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */
639 1 usb_send (dev, RAW_DATA (vfs301_06_3), NULL);
640 1 USB_RECV (VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */
641
642 1 USB_SEND (0x01, -1);
643 1 USB_RECV (VFS301_RECEIVE_ENDPOINT_CTRL, 38);
644 1 USB_SEND (0x02D0, 1);
645 1 USB_RECV (VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */
646 1 USB_RECV (VFS301_RECEIVE_ENDPOINT_DATA, 11648); /* 56 * vfs301_init_line_t[] */
647 1 USB_SEND (0x02D0, 2);
648 1 USB_RECV (VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */
649 1 USB_RECV (VFS301_RECEIVE_ENDPOINT_DATA, 53248); /* 2 * 128 * vfs301_init_line_t[] */
650 1 USB_SEND (0x02D0, 3);
651 1 USB_RECV (VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */
652 1 USB_RECV (VFS301_RECEIVE_ENDPOINT_DATA, 19968); /* 96 * vfs301_init_line_t[] */
653 1 USB_SEND (0x02D0, 4);
654 1 USB_RECV (VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */
655 1 USB_RECV (VFS301_RECEIVE_ENDPOINT_DATA, 5824); /* 28 * vfs301_init_line_t[] */
656 1 USB_SEND (0x02D0, 5);
657 1 USB_RECV (VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */
658 1 USB_RECV (VFS301_RECEIVE_ENDPOINT_DATA, 6656); /* 32 * vfs301_init_line_t[] */
659 1 USB_SEND (0x02D0, 6);
660 1 USB_RECV (VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */
661 1 USB_RECV (VFS301_RECEIVE_ENDPOINT_DATA, 6656); /* 32 * vfs301_init_line_t[] */
662 1 USB_SEND (0x02D0, 7);
663 1 USB_RECV (VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */
664 1 USB_RECV (VFS301_RECEIVE_ENDPOINT_DATA, 832);
665 1 usb_send (dev, RAW_DATA (vfs301_12), NULL);
666 1 USB_RECV (VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */
667
668 1 USB_SEND (0x1A, -1);
669 1 USB_RECV (VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */
670 1 usb_send (dev, RAW_DATA (vfs301_06_2), NULL);
671 1 USB_RECV (VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */
672 1 USB_SEND (0x0220, 2);
673
1/2
✗ Branch 84 → 85 not taken.
✓ Branch 84 → 86 taken 1 time.
1 PARALLEL_RECEIVE (
674 VFS301_RECEIVE_ENDPOINT_CTRL, 2, /* 0000 */
675 VFS301_RECEIVE_ENDPOINT_DATA, 5760
676 1 );
677
678 1 USB_SEND (0x1A, -1);
679 1 USB_RECV (VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */
680 1 usb_send (dev, RAW_DATA (vfs301_06_1), NULL);
681 1 USB_RECV (VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */
682
683 1 USB_SEND (0x1A, -1);
684 1 USB_RECV (VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */
685 1 usb_send (dev, RAW_DATA (vfs301_06_4), NULL);
686 1 USB_RECV (VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */
687 1 usb_send (dev, RAW_DATA (vfs301_24), NULL); /* turns on white */
688 1 USB_RECV (VFS301_RECEIVE_ENDPOINT_CTRL, 2); /* 0000 */
689
690 1 USB_SEND (0x01, -1);
691 1 USB_RECV (VFS301_RECEIVE_ENDPOINT_CTRL, 38);
692 1 USB_SEND (0x0220, 3);
693 1 USB_RECV (VFS301_RECEIVE_ENDPOINT_CTRL, 2368);
694 1 USB_RECV (VFS301_RECEIVE_ENDPOINT_CTRL, 36);
695 1 USB_RECV (VFS301_RECEIVE_ENDPOINT_DATA, 5760);
696 1 }
697
698 void
699 1 vfs301_proto_deinit (FpDeviceVfs301 *dev)
700 {
701 1 }
702