GCC Code Coverage Report


Directory: ./
File: libfprint/drivers/vfs301_proto.c
Date: 2024-05-04 14:54:39
Exec Total Coverage
Lines: 266 283 94.0%
Functions: 16 16 100.0%
Branches: 67 95 70.5%

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