GCC Code Coverage Report


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 2.6% 18 / 0 / 691
Functions: 6.7% 3 / 0 / 45
Branches: 1.6% 4 / 0 / 251

libfprint/drivers/upeksonly.c
Line Branch Exec Source
1 /*
2 * UPEK TouchStrip Sensor-Only driver for libfprint
3 * Copyright (C) 2008 Daniel Drake <dsd@gentoo.org>
4 *
5 * TCS4C (USB ID 147e:1000) support:
6 * Copyright (C) 2010 Hugo Grostabussiat <dw23.devel@gmail.com>
7 *
8 * TCRD5B (USB ID 147e:1001) support:
9 * Copyright (C) 2014 Vasily Khoruzhick <anarsoul@gmail.com>
10 *
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
14 * version 2.1 of the License, or (at your option) any later version.
15 *
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
20 *
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this library; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 */
25
26 #define FP_COMPONENT "upeksonly"
27
28 #include "drivers_api.h"
29 #include "upeksonly.h"
30
31 #define CTRL_TIMEOUT 1000
32 #define NUM_BULK_TRANSFERS 24
33 #define MAX_ROWS 2048
34 #define MIN_ROWS 64
35
36 #define BLANK_THRESHOLD 250
37 #define FINGER_PRESENT_THRESHOLD 32
38 #define FINGER_REMOVED_THRESHOLD 100
39 #define DIFF_THRESHOLD 13
40
41 enum {
42 UPEKSONLY_2016,
43 UPEKSONLY_1000,
44 UPEKSONLY_1001,
45 };
46
47 enum sonly_kill_transfers_action {
48 NOT_KILLING = 0,
49
50 /* report an image session error */
51 IMG_SESSION_ERROR,
52
53 /* iterate a SSM to the next state */
54 ITERATE_SSM,
55 };
56
57 enum sonly_fs {
58 AWAIT_FINGER,
59 FINGER_DETECTED,
60 FINGER_REMOVED,
61 };
62
63 struct _FpiDeviceUpeksonly
64 {
65 FpImageDevice parent;
66
67 gboolean capturing;
68 gboolean deactivating;
69 guint8 read_reg_result;
70
71 int dev_model;
72 int img_width;
73
74 FpiSsm *loopsm;
75
76 /* Do we really need multiple concurrent transfers? */
77 GCancellable *img_cancellable;
78 GPtrArray *img_transfers;
79 int num_flying;
80
81 GSList *rows;
82 unsigned num_rows;
83 unsigned char *rowbuf;
84 int rowbuf_offset;
85
86 int wraparounds;
87 int num_blank;
88 int num_nonblank;
89 enum sonly_fs finger_state;
90 int last_seqnum;
91
92 enum sonly_kill_transfers_action killing_transfers;
93 GError *kill_error;
94 FpiSsm *kill_ssm;
95
96 struct fpi_line_asmbl_ctx assembling_ctx;
97 };
98 G_DECLARE_FINAL_TYPE (FpiDeviceUpeksonly, fpi_device_upeksonly, FPI,
99 DEVICE_UPEKSONLY, FpImageDevice);
100
4/6
fpi_device_upeksonly_class_intern_init:
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 128 times.
fpi_device_upeksonly_get_type:
✓ Branch 2 → 3 taken 128 times.
✓ Branch 2 → 7 taken 24 times.
✓ Branch 4 → 5 taken 128 times.
✗ Branch 4 → 7 not taken.
408 G_DEFINE_TYPE (FpiDeviceUpeksonly, fpi_device_upeksonly, FP_TYPE_IMAGE_DEVICE);
101
102
103 /* Calculate squared standard deviation of sum of two lines */
104 static int
105 ✗ upeksonly_get_deviation2 (struct fpi_line_asmbl_ctx *ctx,
106 GSList *line1, GSList *line2)
107 {
108 ✗ unsigned char *buf1 = line1->data, *buf2 = line2->data;
109 ✗ int res = 0, mean = 0, i;
110
111 ✗ g_assert (ctx->line_width > 0);
112
113 ✗ for (i = 0; i < ctx->line_width; i += 2)
114 ✗ mean += (int) buf1[i + 1] + (int) buf2[i];
115
116 ✗ mean /= (ctx->line_width / 2);
117
118 ✗ for (i = 0; i < ctx->line_width; i += 2)
119 {
120 ✗ int dev = (int) buf1[i + 1] + (int) buf2[i] - mean;
121 ✗ res += dev * dev;
122 }
123
124 ✗ return res / (ctx->line_width / 2);
125 }
126
127
128 static unsigned char
129 ✗ upeksonly_get_pixel (struct fpi_line_asmbl_ctx *ctx,
130 GSList *row,
131 unsigned x)
132 {
133 ✗ unsigned char *buf;
134 ✗ unsigned offset;
135
136 /* The scans from this device are rolled right by two columns */
137 ✗ if (x < ctx->line_width - 2)
138 ✗ offset = x + 2;
139 ✗ else if ((x > ctx->line_width - 2) && (x < ctx->line_width))
140 ✗ offset = x - (ctx->line_width - 2);
141 else
142 return 0;
143 /* Each 2nd pixel is shifted 2 pixels down */
144 ✗ if ((!(x & 1)) && g_slist_next (row) && g_slist_next (g_slist_next (row)))
145 ✗ buf = g_slist_next (g_slist_next (row))->data;
146 else
147 ✗ buf = row->data;
148
149 ✗ return buf[offset];
150 }
151
152 /***** IMAGE PROCESSING *****/
153
154 static void
155 ✗ free_img_transfers (FpiDeviceUpeksonly *sdev)
156 {
157 ✗ g_cancellable_cancel (sdev->img_cancellable);
158 ✗ g_clear_object (&sdev->img_cancellable);
159 ✗ g_clear_pointer (&sdev->img_transfers, g_ptr_array_unref);
160 ✗ }
161
162 static void
163 ✗ last_transfer_killed (FpImageDevice *dev)
164 {
165 ✗ FpiDeviceUpeksonly *self = FPI_DEVICE_UPEKSONLY (dev);
166
167 ✗ switch (self->killing_transfers)
168 {
169 ✗ case ITERATE_SSM:
170 ✗ fp_dbg ("iterate ssm");
171 ✗ fpi_ssm_next_state (self->kill_ssm);
172 ✗ return;
173
174 ✗ case IMG_SESSION_ERROR:
175 ✗ fp_dbg ("session error %s", self->kill_error->message);
176 ✗ fpi_image_device_session_error (dev, g_steal_pointer (&self->kill_error));
177 ✗ return;
178
179 case NOT_KILLING:
180 default:
181 return;
182 }
183 }
184
185 static void
186 ✗ cancel_img_transfers (FpImageDevice *dev)
187 {
188 ✗ FpiDeviceUpeksonly *self = FPI_DEVICE_UPEKSONLY (dev);
189
190 ✗ g_cancellable_cancel (self->img_cancellable);
191
192 ✗ if (self->num_flying == 0)
193 ✗ last_transfer_killed (dev);
194 ✗ }
195
196 static gboolean
197 ✗ is_capturing (FpiDeviceUpeksonly *sdev)
198 {
199 ✗ return sdev->num_rows < MAX_ROWS && (sdev->finger_state != FINGER_REMOVED);
200 }
201
202 static void
203 ✗ handoff_img (FpImageDevice *dev)
204 {
205 ✗ FpiDeviceUpeksonly *self = FPI_DEVICE_UPEKSONLY (dev);
206 ✗ FpImage *img;
207
208 ✗ GSList *elem = self->rows;
209
210 ✗ if (!elem)
211 {
212 ✗ fp_err ("no rows?");
213 ✗ return;
214 }
215
216 ✗ self->rows = g_slist_reverse (self->rows);
217
218 ✗ fp_dbg ("%u rows", self->num_rows);
219 ✗ img = fpi_assemble_lines (&self->assembling_ctx, self->rows, self->num_rows);
220
221 ✗ g_slist_free_full (self->rows, g_free);
222 ✗ self->rows = NULL;
223
224 ✗ fpi_image_device_image_captured (dev, img);
225 ✗ fpi_image_device_report_finger_status (dev, FALSE);
226
227 ✗ self->killing_transfers = ITERATE_SSM;
228 ✗ self->kill_ssm = self->loopsm;
229 ✗ cancel_img_transfers (dev);
230 }
231
232 static void
233 ✗ row_complete (FpImageDevice *dev)
234 {
235 ✗ FpiDeviceUpeksonly *self = FPI_DEVICE_UPEKSONLY (dev);
236
237 ✗ self->rowbuf_offset = -1;
238
239 ✗ if (self->num_rows > 0)
240 {
241 ✗ unsigned char *lastrow = self->rows->data;
242 ✗ int std_sq_dev, mean_sq_diff;
243
244 ✗ std_sq_dev = fpi_std_sq_dev (self->rowbuf, self->img_width);
245 ✗ mean_sq_diff = fpi_mean_sq_diff_norm (lastrow, self->rowbuf,
246 ✗ self->img_width);
247
248 ✗ switch (self->finger_state)
249 {
250 ✗ case AWAIT_FINGER:
251 ✗ if (self->deactivating)
252 {
253 ✗ self->killing_transfers = ITERATE_SSM;
254 ✗ self->kill_ssm = self->loopsm;
255 ✗ cancel_img_transfers (dev);
256 }
257 ✗ fp_dbg ("std_sq_dev: %d", std_sq_dev);
258 ✗ if (std_sq_dev > BLANK_THRESHOLD)
259 ✗ self->num_nonblank++;
260 else
261 self->num_nonblank = 0;
262
263 ✗ if (self->num_nonblank > FINGER_PRESENT_THRESHOLD)
264 {
265 ✗ self->finger_state = FINGER_DETECTED;
266 ✗ fpi_image_device_report_finger_status (dev,
267 TRUE);
268 }
269 else
270 {
271 return;
272 }
273 ✗ break;
274
275 case FINGER_DETECTED:
276 case FINGER_REMOVED:
277 default:
278 break;
279 }
280
281 ✗ if (std_sq_dev > BLANK_THRESHOLD)
282 {
283 ✗ self->num_blank = 0;
284 }
285 else
286 {
287 ✗ self->num_blank++;
288 /* Don't consider the scan complete unless there's at least
289 * MIN_ROWS recorded or very long blank read occurred.
290 *
291 * Typical problem spot: one brief touch before starting the
292 * actual scan. Happens most commonly if scan is started
293 * from before the first joint resulting in a gap after the initial touch.
294 */
295 ✗ if (self->num_blank > FINGER_REMOVED_THRESHOLD)
296 {
297 ✗ self->finger_state = FINGER_REMOVED;
298 ✗ fp_dbg ("detected finger removal. Blank rows: %d, Full rows: %u",
299 self->num_blank, self->num_rows);
300 ✗ handoff_img (dev);
301 ✗ return;
302 }
303 }
304 ✗ fp_dbg ("mean_sq_diff: %d, std_sq_dev: %d", mean_sq_diff, std_sq_dev);
305 ✗ fp_dbg ("num_blank: %d", self->num_blank);
306 ✗ if (mean_sq_diff < DIFF_THRESHOLD)
307 return;
308 }
309
310 ✗ switch (self->finger_state)
311 {
312 ✗ case AWAIT_FINGER:
313 ✗ if (!self->num_rows)
314 {
315 ✗ self->rows = g_slist_prepend (self->rows, self->rowbuf);
316 ✗ self->num_rows++;
317 }
318 else
319 {
320 return;
321 }
322 ✗ break;
323
324 ✗ case FINGER_DETECTED:
325 case FINGER_REMOVED:
326 ✗ self->rows = g_slist_prepend (self->rows, self->rowbuf);
327 ✗ self->num_rows++;
328 ✗ break;
329 }
330 ✗ self->rowbuf = NULL;
331
332 ✗ if (self->num_rows >= MAX_ROWS)
333 {
334 ✗ fp_dbg ("row limit met");
335 ✗ handoff_img (dev);
336 }
337 }
338
339 /* add data to row buffer */
340 static void
341 ✗ add_to_rowbuf (FpImageDevice *dev, unsigned char *data, int size)
342 {
343 ✗ FpiDeviceUpeksonly *self = FPI_DEVICE_UPEKSONLY (dev);
344
345 ✗ memcpy (self->rowbuf + self->rowbuf_offset, data, size);
346 ✗ self->rowbuf_offset += size;
347 ✗ if (self->rowbuf_offset >= self->img_width)
348 ✗ row_complete (dev);
349
350 ✗ }
351
352 static void
353 ✗ start_new_row (FpiDeviceUpeksonly *self, unsigned char *data,
354 int size)
355 {
356 ✗ if (!self->rowbuf)
357 ✗ self->rowbuf = g_malloc (self->img_width);
358 ✗ memcpy (self->rowbuf, data, size);
359 ✗ self->rowbuf_offset = size;
360 ✗ }
361
362 /* returns number of bytes left to be copied into rowbuf (capped to 62)
363 * or -1 if we aren't capturing anything */
364 static int
365 ✗ rowbuf_remaining (FpiDeviceUpeksonly *sdev)
366 {
367 ✗ int r;
368
369 ✗ if (sdev->rowbuf_offset == -1)
370 return -1;
371
372 ✗ r = sdev->img_width - sdev->rowbuf_offset;
373 ✗ if (r > 62)
374 r = 62;
375 return r;
376 }
377
378 static void
379 ✗ handle_packet (FpImageDevice *dev, unsigned char *data)
380 {
381 ✗ FpiDeviceUpeksonly *self = FPI_DEVICE_UPEKSONLY (dev);
382 ✗ guint16 seqnum = data[0] << 8 | data[1];
383 ✗ int abs_base_addr;
384 ✗ int for_rowbuf;
385 ✗ int next_row_addr;
386 ✗ int diff;
387 ✗ unsigned char dummy_data[62];
388
389 /* Init dummy data to something neutral */
390 ✗ memset (dummy_data, 204, 62);
391
392 ✗ data += 2; /* skip sequence number */
393 ✗ if (seqnum != self->last_seqnum + 1)
394 {
395 ✗ if (seqnum != 0 && self->last_seqnum != 16383)
396 {
397 ✗ int missing_data = seqnum - self->last_seqnum;
398 ✗ int i;
399 ✗ fp_warn ("lost %d packets of data between %d and %d", missing_data,
400 self->last_seqnum, seqnum );
401
402 /* Minimize distortions for readers that lose a lot of packets */
403 ✗ for (i = 1; i < missing_data; i++)
404 {
405 ✗ abs_base_addr = (self->last_seqnum + 1) * 62;
406
407 /* If possible take the replacement data from last row */
408 ✗ if (self->num_rows > 1)
409 {
410 ✗ int row_left = self->img_width - self->rowbuf_offset;
411 ✗ unsigned char *last_row = g_slist_nth_data (self->rows,
412 0);
413
414 ✗ if (row_left >= 62)
415 {
416 ✗ memcpy (dummy_data,
417 ✗ last_row + self->rowbuf_offset,
418 62);
419 }
420 else
421 {
422 ✗ memcpy (dummy_data,
423 ✗ last_row + self->rowbuf_offset,
424 row_left);
425 ✗ memcpy (dummy_data + row_left, last_row, 62 - row_left);
426 }
427 }
428
429 ✗ fp_warn ("adding dummy input for %d, i=%d",
430 self->last_seqnum + i, i);
431 ✗ for_rowbuf = rowbuf_remaining (self);
432 ✗ if (for_rowbuf != -1)
433 {
434 ✗ add_to_rowbuf (dev, dummy_data, for_rowbuf);
435 /* row boundary */
436 ✗ if (for_rowbuf < 62)
437 {
438 ✗ start_new_row (self,
439 dummy_data + for_rowbuf,
440 62 - for_rowbuf);
441 }
442 }
443 ✗ else if (abs_base_addr % self->img_width == 0)
444 {
445 ✗ start_new_row (self, dummy_data, 62);
446 }
447 else
448 {
449 /* does the data in the packet reside on a row boundary?
450 * if so capture it */
451 ✗ next_row_addr = ((abs_base_addr / self->img_width) + 1) * self->img_width;
452 ✗ diff = next_row_addr - abs_base_addr;
453 ✗ if (diff < 62)
454 ✗ start_new_row (self,
455 dummy_data + diff,
456 62 - diff);
457 }
458 ✗ self->last_seqnum = self->last_seqnum + 1;
459 }
460 }
461 }
462 ✗ if (seqnum <= self->last_seqnum)
463 {
464 ✗ fp_dbg ("detected wraparound");
465 ✗ self->wraparounds++;
466 }
467
468 ✗ self->last_seqnum = seqnum;
469 ✗ seqnum += self->wraparounds * 16384;
470 ✗ abs_base_addr = seqnum * 62;
471
472 /* are we already capturing a row? if so append the data to the
473 * row buffer */
474 ✗ for_rowbuf = rowbuf_remaining (self);
475 ✗ if (for_rowbuf != -1)
476 {
477 ✗ add_to_rowbuf (dev, data, for_rowbuf);
478 /*row boundary*/
479 ✗ if (for_rowbuf < 62)
480 ✗ start_new_row (self, data + for_rowbuf,
481 62 - for_rowbuf);
482 ✗ return;
483 }
484
485 /* does the packet START on a boundary? if so we want it in full */
486 ✗ if (abs_base_addr % self->img_width == 0)
487 {
488 ✗ start_new_row (self, data, 62);
489 ✗ return;
490 }
491
492 /* does the data in the packet reside on a row boundary?
493 * if so capture it */
494 ✗ next_row_addr = ((abs_base_addr / self->img_width) + 1) * self->img_width;
495 ✗ diff = next_row_addr - abs_base_addr;
496 ✗ if (diff < 62)
497 ✗ start_new_row (self, data + diff, 62 - diff);
498 }
499
500 static void
501 ✗ img_data_cb (FpiUsbTransfer *transfer, FpDevice *device,
502 gpointer user_data, GError *error)
503 {
504 ✗ FpImageDevice *dev = FP_IMAGE_DEVICE (device);
505 ✗ FpiDeviceUpeksonly *self = FPI_DEVICE_UPEKSONLY (dev);
506 ✗ int i;
507
508 ✗ self->num_flying--;
509
510 ✗ if (self->killing_transfers)
511 {
512 ✗ if (self->num_flying == 0)
513 ✗ last_transfer_killed (dev);
514
515 /* don't care about error or success if we're terminating */
516 ✗ g_clear_error (&error);
517 ✗ return;
518 }
519
520 /* NOTE: The old code assume 4096 bytes are received each time
521 * but there is no reason we need to enforce that. However, we
522 * always need full lines. */
523 ✗ if (transfer->actual_length % 64 != 0)
524 ✗ error = fpi_device_error_new_msg (FP_DEVICE_ERROR_PROTO,
525 "Data packets need to be multiple of 64 bytes, got %zi bytes",
526 transfer->actual_length);
527
528 ✗ if (error)
529 {
530 ✗ fp_warn ("bad status %s, terminating session", error->message);
531 ✗ self->killing_transfers = IMG_SESSION_ERROR;
532
533 /* This cannot really happen, but just in case. */
534 ✗ if (!self->kill_error)
535 ✗ self->kill_error = error;
536 else
537 ✗ g_error_free (error);
538
539 ✗ cancel_img_transfers (dev);
540 ✗ return;
541 }
542
543 /* there are 64 packets in the transfer buffer
544 * each packet is 64 bytes in length
545 * the first 2 bytes are a sequence number
546 * then there are 62 bytes for image data
547 */
548 ✗ for (i = 0; i + 64 <= transfer->actual_length; i += 64)
549 {
550 ✗ if (!is_capturing (self))
551 return;
552 ✗ handle_packet (dev, transfer->buffer + i);
553 }
554
555 ✗ if (is_capturing (self))
556 {
557 ✗ fpi_usb_transfer_submit (fpi_usb_transfer_ref (transfer),
558 0,
559 self->img_cancellable,
560 img_data_cb,
561 user_data);
562 ✗ self->num_flying++;
563 }
564 }
565
566 /***** STATE MACHINE HELPERS *****/
567
568 struct write_regs_data
569 {
570 FpDevice *dev;
571 FpiSsm *ssm;
572 FpiUsbTransfer *transfer;
573 const struct sonly_regwrite *regs;
574 size_t num_regs;
575 size_t regs_written;
576 };
577
578 static void
579 ✗ write_regs_finished (struct write_regs_data *wrdata, GError *error)
580 {
581 ✗ if (!error)
582 ✗ fpi_ssm_next_state (wrdata->ssm);
583 else
584 ✗ fpi_ssm_mark_failed (wrdata->ssm, error);
585
586 ✗ g_free (wrdata);
587 ✗ }
588
589 static void write_regs_iterate (struct write_regs_data *wrdata);
590
591 static void
592 ✗ write_regs_cb (FpiUsbTransfer *transfer, FpDevice *device,
593 gpointer user_data, GError *error)
594 {
595 ✗ struct write_regs_data *wrdata = user_data;
596
597 ✗ if (error)
598 {
599 ✗ write_regs_finished (wrdata, error);
600 ✗ return;
601 }
602
603 ✗ wrdata->regs_written++;
604 ✗ write_regs_iterate (wrdata);
605 }
606
607 static void
608 ✗ write_regs_iterate (struct write_regs_data *wrdata)
609 {
610 ✗ FpiUsbTransfer *transfer;
611 ✗ const struct sonly_regwrite *regwrite;
612
613 ✗ if (wrdata->regs_written >= wrdata->num_regs)
614 {
615 ✗ write_regs_finished (wrdata, NULL);
616 ✗ return;
617 }
618
619 ✗ regwrite = &wrdata->regs[wrdata->regs_written];
620 ✗ fp_dbg ("set %02x=%02x", regwrite->reg, regwrite->value);
621
622 ✗ transfer = fpi_usb_transfer_new (wrdata->dev);
623 ✗ fpi_usb_transfer_fill_control (transfer,
624 G_USB_DEVICE_DIRECTION_HOST_TO_DEVICE,
625 G_USB_DEVICE_REQUEST_TYPE_VENDOR,
626 G_USB_DEVICE_RECIPIENT_DEVICE,
627 0x0c,
628 0,
629 ✗ regwrite->reg,
630 1);
631 ✗ transfer->short_is_error = TRUE;
632 ✗ transfer->ssm = wrdata->ssm;
633 ✗ transfer->buffer[0] = regwrite->value;
634
635 ✗ fpi_usb_transfer_submit (transfer, CTRL_TIMEOUT, NULL, write_regs_cb, wrdata);
636 }
637
638 static void
639 ✗ sm_write_regs (FpiSsm *ssm,
640 FpDevice *dev,
641 const struct sonly_regwrite *regs,
642 size_t num_regs)
643 {
644 ✗ struct write_regs_data *wrdata = g_malloc (sizeof (*wrdata));
645
646 ✗ wrdata->ssm = ssm;
647 ✗ wrdata->regs = regs;
648 ✗ wrdata->num_regs = num_regs;
649 ✗ wrdata->regs_written = 0;
650 ✗ wrdata->dev = dev;
651
652 ✗ write_regs_iterate (wrdata);
653 ✗ }
654
655 static void
656 ✗ sm_write_reg (FpiSsm *ssm,
657 FpImageDevice *dev,
658 guint8 reg,
659 guint8 value)
660 {
661 ✗ FpiUsbTransfer *transfer = fpi_usb_transfer_new (FP_DEVICE (dev));
662
663 ✗ fp_dbg ("set %02x=%02x", reg, value);
664 ✗ fpi_usb_transfer_fill_control (transfer,
665 G_USB_DEVICE_DIRECTION_HOST_TO_DEVICE,
666 G_USB_DEVICE_REQUEST_TYPE_VENDOR,
667 G_USB_DEVICE_RECIPIENT_DEVICE,
668 0x0c,
669 0,
670 reg,
671 1);
672 ✗ transfer->short_is_error = TRUE;
673 ✗ transfer->ssm = ssm;
674 ✗ transfer->buffer[0] = value;
675
676 ✗ fpi_usb_transfer_submit (transfer, CTRL_TIMEOUT, NULL,
677 fpi_ssm_usb_transfer_cb, NULL);
678 ✗ }
679
680 static void
681 ✗ sm_read_reg_cb (FpiUsbTransfer *transfer, FpDevice *device,
682 gpointer user_data, GError *error)
683 {
684 ✗ FpImageDevice *dev = FP_IMAGE_DEVICE (device);
685 ✗ FpiDeviceUpeksonly *self = FPI_DEVICE_UPEKSONLY (dev);
686
687 ✗ if (error)
688 {
689 ✗ fpi_ssm_mark_failed (transfer->ssm, error);
690 }
691 else
692 {
693 ✗ self->read_reg_result = transfer->buffer[0];
694 ✗ fp_dbg ("read reg result = %02x", self->read_reg_result);
695 ✗ fpi_ssm_next_state (transfer->ssm);
696 }
697 ✗ }
698
699 static void
700 ✗ sm_read_reg (FpiSsm *ssm,
701 FpImageDevice *dev,
702 guint8 reg)
703 {
704 ✗ FpiUsbTransfer *transfer = fpi_usb_transfer_new (FP_DEVICE (dev));
705
706 ✗ fp_dbg ("read reg %02x", reg);
707 ✗ fpi_usb_transfer_fill_control (transfer,
708 G_USB_DEVICE_DIRECTION_DEVICE_TO_HOST,
709 G_USB_DEVICE_REQUEST_TYPE_VENDOR,
710 G_USB_DEVICE_RECIPIENT_DEVICE,
711 0x0c,
712 0,
713 reg,
714 8);
715 ✗ transfer->ssm = ssm;
716 ✗ transfer->short_is_error = TRUE;
717 ✗ fpi_usb_transfer_submit (transfer,
718 CTRL_TIMEOUT,
719 NULL,
720 sm_read_reg_cb,
721 NULL);
722 ✗ }
723
724 static void
725 ✗ sm_await_intr_cb (FpiUsbTransfer *transfer, FpDevice *device,
726 gpointer user_data, GError *error)
727 {
728 ✗ FpImageDevice *dev = FP_IMAGE_DEVICE (device);
729 ✗ FpiDeviceUpeksonly *self = FPI_DEVICE_UPEKSONLY (dev);
730
731 ✗ if (error)
732 {
733 ✗ fpi_ssm_mark_failed (transfer->ssm, error);
734 ✗ return;
735 }
736
737 ✗ fp_dbg ("interrupt received: %02x %02x %02x %02x",
738 transfer->buffer[0], transfer->buffer[1],
739 transfer->buffer[2], transfer->buffer[3]);
740
741 ✗ self->finger_state = FINGER_DETECTED;
742 ✗ fpi_image_device_report_finger_status (dev, TRUE);
743 ✗ fpi_ssm_next_state (transfer->ssm);
744 }
745
746 static void
747 ✗ sm_await_intr (FpiSsm *ssm,
748 FpImageDevice *dev)
749 {
750 ✗ FpiUsbTransfer *transfer = fpi_usb_transfer_new (FP_DEVICE (dev));
751
752 ✗ G_DEBUG_HERE ();
753
754 ✗ fpi_usb_transfer_fill_interrupt (transfer, 0x83, 4);
755 ✗ transfer->short_is_error = TRUE;
756 ✗ transfer->ssm = ssm;
757
758 /* NOTE: This was changed to be cancellable with the version 2 port! */
759 ✗ fpi_usb_transfer_submit (transfer,
760 0,
761 fpi_device_get_cancellable (FP_DEVICE (dev)),
762 sm_await_intr_cb,
763 NULL);
764 ✗ }
765
766 /***** AWAIT FINGER *****/
767
768 enum awfsm_2016_states {
769 AWFSM_2016_WRITEV_1,
770 AWFSM_2016_READ_01,
771 AWFSM_2016_WRITE_01,
772 AWFSM_2016_WRITEV_2,
773 AWFSM_2016_READ_13,
774 AWFSM_2016_WRITE_13,
775 AWFSM_2016_WRITEV_3,
776 AWFSM_2016_READ_07,
777 AWFSM_2016_WRITE_07,
778 AWFSM_2016_WRITEV_4,
779 AWFSM_2016_NUM_STATES,
780 };
781
782 enum awfsm_1000_states {
783 AWFSM_1000_WRITEV_1,
784 AWFSM_1000_WRITEV_2,
785 AWFSM_1000_NUM_STATES,
786 };
787
788 static void
789 ✗ awfsm_2016_run_state (FpiSsm *ssm, FpDevice *_dev)
790 {
791 ✗ FpImageDevice *dev = FP_IMAGE_DEVICE (_dev);
792 ✗ FpiDeviceUpeksonly *self = FPI_DEVICE_UPEKSONLY (_dev);
793
794 ✗ switch (fpi_ssm_get_cur_state (ssm))
795 {
796 ✗ case AWFSM_2016_WRITEV_1:
797 ✗ sm_write_regs (ssm, _dev, awfsm_2016_writev_1, G_N_ELEMENTS (awfsm_2016_writev_1));
798 ✗ break;
799
800 ✗ case AWFSM_2016_READ_01:
801 ✗ sm_read_reg (ssm, dev, 0x01);
802 ✗ break;
803
804 ✗ case AWFSM_2016_WRITE_01:
805 ✗ if (self->read_reg_result != 0xc6)
806 ✗ sm_write_reg (ssm, dev, 0x01, 0x46);
807 else
808 ✗ sm_write_reg (ssm, dev, 0x01, 0xc6);
809 break;
810
811 ✗ case AWFSM_2016_WRITEV_2:
812 ✗ sm_write_regs (ssm, _dev, awfsm_2016_writev_2, G_N_ELEMENTS (awfsm_2016_writev_2));
813 ✗ break;
814
815 ✗ case AWFSM_2016_READ_13:
816 ✗ sm_read_reg (ssm, dev, 0x13);
817 ✗ break;
818
819 ✗ case AWFSM_2016_WRITE_13:
820 ✗ if (self->read_reg_result != 0x45)
821 ✗ sm_write_reg (ssm, dev, 0x13, 0x05);
822 else
823 ✗ sm_write_reg (ssm, dev, 0x13, 0x45);
824 break;
825
826 ✗ case AWFSM_2016_WRITEV_3:
827 ✗ sm_write_regs (ssm, _dev, awfsm_2016_writev_3, G_N_ELEMENTS (awfsm_2016_writev_3));
828 ✗ break;
829
830 ✗ case AWFSM_2016_READ_07:
831 ✗ sm_read_reg (ssm, dev, 0x07);
832 ✗ break;
833
834 ✗ case AWFSM_2016_WRITE_07:
835 ✗ if (self->read_reg_result != 0x10 && self->read_reg_result != 0x90)
836 ✗ fp_warn ("odd reg7 value %x", self->read_reg_result);
837 ✗ sm_write_reg (ssm, dev, 0x07, self->read_reg_result);
838 ✗ break;
839
840 ✗ case AWFSM_2016_WRITEV_4:
841 ✗ sm_write_regs (ssm, _dev, awfsm_2016_writev_4, G_N_ELEMENTS (awfsm_2016_writev_4));
842 ✗ break;
843 }
844 ✗ }
845
846 static void
847 ✗ awfsm_1000_run_state (FpiSsm *ssm, FpDevice *_dev)
848 {
849 ✗ switch (fpi_ssm_get_cur_state (ssm))
850 {
851 ✗ case AWFSM_1000_WRITEV_1:
852 ✗ sm_write_regs (ssm, _dev, awfsm_1000_writev_1, G_N_ELEMENTS (awfsm_1000_writev_1));
853 ✗ break;
854
855 ✗ case AWFSM_1000_WRITEV_2:
856 ✗ sm_write_regs (ssm, _dev, awfsm_1000_writev_2, G_N_ELEMENTS (awfsm_1000_writev_2));
857 ✗ break;
858 }
859 ✗ }
860
861 /***** CAPTURE MODE *****/
862
863 enum capsm_2016_states {
864 CAPSM_2016_INIT,
865 CAPSM_2016_WRITE_15,
866 CAPSM_2016_WRITE_30,
867 CAPSM_2016_FIRE_BULK,
868 CAPSM_2016_WRITEV,
869 CAPSM_2016_NUM_STATES,
870 };
871
872 enum capsm_1000_states {
873 CAPSM_1000_INIT,
874 CAPSM_1000_FIRE_BULK,
875 CAPSM_1000_WRITEV,
876 CAPSM_1000_NUM_STATES,
877 };
878
879 enum capsm_1001_states {
880 CAPSM_1001_INIT,
881 CAPSM_1001_FIRE_BULK,
882 CAPSM_1001_WRITEV_1,
883 CAPSM_1001_WRITEV_2,
884 CAPSM_1001_WRITEV_3,
885 CAPSM_1001_WRITEV_4,
886 CAPSM_1001_WRITEV_5,
887 CAPSM_1001_NUM_STATES,
888 };
889
890 static void
891 ✗ capsm_fire_bulk (FpiSsm *ssm,
892 FpDevice *dev)
893 {
894 ✗ FpiDeviceUpeksonly *self = FPI_DEVICE_UPEKSONLY (dev);
895 ✗ int i;
896
897 ✗ g_assert (self->capturing == FALSE);
898
899 ✗ g_clear_object (&self->img_cancellable);
900 ✗ self->img_cancellable = g_cancellable_new ();
901 ✗ for (i = 0; i < self->img_transfers->len; i++)
902 {
903 ✗ fpi_usb_transfer_submit (fpi_usb_transfer_ref (g_ptr_array_index (self->img_transfers, i)),
904 0,
905 self->img_cancellable,
906 img_data_cb,
907 NULL);
908 ✗ self->num_flying++;
909 }
910 ✗ self->capturing = TRUE;
911 ✗ fpi_ssm_next_state (ssm);
912 ✗ }
913
914 static void
915 ✗ capsm_2016_run_state (FpiSsm *ssm, FpDevice *_dev)
916 {
917 ✗ FpImageDevice *dev = FP_IMAGE_DEVICE (_dev);
918 ✗ FpiDeviceUpeksonly *self = FPI_DEVICE_UPEKSONLY (_dev);
919
920 ✗ switch (fpi_ssm_get_cur_state (ssm))
921 {
922 ✗ case CAPSM_2016_INIT:
923 ✗ self->rowbuf_offset = -1;
924 ✗ self->num_rows = 0;
925 ✗ self->wraparounds = -1;
926 ✗ self->num_blank = 0;
927 ✗ self->num_nonblank = 0;
928 ✗ self->finger_state = FINGER_DETECTED;
929 ✗ self->last_seqnum = 16383;
930 ✗ self->killing_transfers = 0;
931 ✗ fpi_ssm_next_state (ssm);
932 ✗ break;
933
934 ✗ case CAPSM_2016_WRITE_15:
935 ✗ sm_write_reg (ssm, dev, 0x15, 0x20);
936 ✗ break;
937
938 ✗ case CAPSM_2016_WRITE_30:
939 ✗ sm_write_reg (ssm, dev, 0x30, 0xe0);
940 ✗ break;
941
942 ✗ case CAPSM_2016_FIRE_BULK:;
943 ✗ capsm_fire_bulk (ssm, _dev);
944 ✗ break;
945
946 ✗ case CAPSM_2016_WRITEV:
947 ✗ sm_write_regs (ssm, _dev, capsm_2016_writev, G_N_ELEMENTS (capsm_2016_writev));
948 ✗ break;
949 }
950 ✗ }
951
952 static void
953 ✗ capsm_1000_run_state (FpiSsm *ssm, FpDevice *_dev)
954 {
955 ✗ FpiDeviceUpeksonly *self = FPI_DEVICE_UPEKSONLY (_dev);
956
957 ✗ switch (fpi_ssm_get_cur_state (ssm))
958 {
959 ✗ case CAPSM_1000_INIT:
960 ✗ self->rowbuf_offset = -1;
961 ✗ self->num_rows = 0;
962 ✗ self->wraparounds = -1;
963 ✗ self->num_blank = 0;
964 ✗ self->num_nonblank = 0;
965 ✗ self->finger_state = FINGER_DETECTED;
966 ✗ self->last_seqnum = 16383;
967 ✗ self->killing_transfers = 0;
968 ✗ fpi_ssm_next_state (ssm);
969 ✗ break;
970
971 ✗ case CAPSM_1000_FIRE_BULK:;
972 ✗ capsm_fire_bulk (ssm, _dev);
973 ✗ break;
974
975 ✗ case CAPSM_1000_WRITEV:
976 ✗ sm_write_regs (ssm, _dev, capsm_1000_writev, G_N_ELEMENTS (capsm_1000_writev));
977 ✗ break;
978 }
979 ✗ }
980
981 static void
982 ✗ capsm_1001_run_state (FpiSsm *ssm, FpDevice *_dev)
983 {
984 ✗ FpiDeviceUpeksonly *self = FPI_DEVICE_UPEKSONLY (_dev);
985
986 ✗ switch (fpi_ssm_get_cur_state (ssm))
987 {
988 ✗ case CAPSM_1001_INIT:
989 ✗ self->rowbuf_offset = -1;
990 ✗ self->num_rows = 0;
991 ✗ self->wraparounds = -1;
992 ✗ self->num_blank = 0;
993 ✗ self->num_nonblank = 0;
994 ✗ self->finger_state = AWAIT_FINGER;
995 ✗ self->last_seqnum = 16383;
996 ✗ self->killing_transfers = 0;
997 ✗ fpi_ssm_next_state (ssm);
998 ✗ break;
999
1000 ✗ case CAPSM_1001_FIRE_BULK:;
1001 ✗ capsm_fire_bulk (ssm, _dev);
1002 ✗ break;
1003
1004 ✗ case CAPSM_1001_WRITEV_1:
1005 ✗ sm_write_regs (ssm, _dev, capsm_1001_writev_1, G_N_ELEMENTS (capsm_1001_writev_1));
1006 ✗ break;
1007
1008 ✗ case CAPSM_1001_WRITEV_2:
1009 ✗ sm_write_regs (ssm, _dev, capsm_1001_writev_2, G_N_ELEMENTS (capsm_1001_writev_2));
1010 ✗ break;
1011
1012 ✗ case CAPSM_1001_WRITEV_3:
1013 ✗ sm_write_regs (ssm, _dev, capsm_1001_writev_3, G_N_ELEMENTS (capsm_1001_writev_3));
1014 ✗ break;
1015
1016 ✗ case CAPSM_1001_WRITEV_4:
1017 ✗ sm_write_regs (ssm, _dev, capsm_1001_writev_4, G_N_ELEMENTS (capsm_1001_writev_4));
1018 ✗ break;
1019
1020 ✗ case CAPSM_1001_WRITEV_5:
1021 ✗ sm_write_regs (ssm, _dev, capsm_1001_writev_5, G_N_ELEMENTS (capsm_1001_writev_5));
1022 ✗ break;
1023 }
1024 ✗ }
1025
1026 /***** DEINITIALIZATION *****/
1027
1028 enum deinitsm_2016_states {
1029 DEINITSM_2016_WRITEV,
1030 DEINITSM_2016_NUM_STATES,
1031 };
1032
1033 enum deinitsm_1000_states {
1034 DEINITSM_1000_WRITEV,
1035 DEINITSM_1000_NUM_STATES,
1036 };
1037
1038 enum deinitsm_1001_states {
1039 DEINITSM_1001_WRITEV,
1040 DEINITSM_1001_NUM_STATES,
1041 };
1042
1043 static void
1044 ✗ deinitsm_2016_run_state (FpiSsm *ssm, FpDevice *_dev)
1045 {
1046 ✗ switch (fpi_ssm_get_cur_state (ssm))
1047 {
1048 ✗ case DEINITSM_2016_WRITEV:
1049 ✗ sm_write_regs (ssm, _dev, deinitsm_2016_writev, G_N_ELEMENTS (deinitsm_2016_writev));
1050 ✗ break;
1051 }
1052 ✗ }
1053
1054 static void
1055 ✗ deinitsm_1000_run_state (FpiSsm *ssm, FpDevice *_dev)
1056 {
1057 ✗ switch (fpi_ssm_get_cur_state (ssm))
1058 {
1059 ✗ case DEINITSM_1000_WRITEV:
1060 ✗ sm_write_regs (ssm, _dev, deinitsm_1000_writev, G_N_ELEMENTS (deinitsm_1000_writev));
1061 ✗ break;
1062 }
1063 ✗ }
1064
1065 static void
1066 ✗ deinitsm_1001_run_state (FpiSsm *ssm, FpDevice *_dev)
1067 {
1068 ✗ switch (fpi_ssm_get_cur_state (ssm))
1069 {
1070 ✗ case DEINITSM_1001_WRITEV:
1071 ✗ sm_write_regs (ssm, _dev, deinitsm_1001_writev, G_N_ELEMENTS (deinitsm_1001_writev));
1072 ✗ break;
1073 }
1074 ✗ }
1075
1076 /***** INITIALIZATION *****/
1077
1078 enum initsm_2016_states {
1079 INITSM_2016_WRITEV_1,
1080 INITSM_2016_READ_09,
1081 INITSM_2016_WRITE_09,
1082 INITSM_2016_READ_13,
1083 INITSM_2016_WRITE_13,
1084 INITSM_2016_WRITE_04,
1085 INITSM_2016_WRITE_05,
1086 INITSM_2016_NUM_STATES,
1087 };
1088
1089 enum initsm_1000_states {
1090 INITSM_1000_WRITEV_1,
1091 INITSM_1000_NUM_STATES,
1092 };
1093
1094 enum initsm_1001_states {
1095 INITSM_1001_WRITEV_1,
1096 INITSM_1001_WRITEV_2,
1097 INITSM_1001_WRITEV_3,
1098 INITSM_1001_WRITEV_4,
1099 INITSM_1001_WRITEV_5,
1100 INITSM_1001_NUM_STATES,
1101 };
1102
1103 static void
1104 ✗ initsm_2016_run_state (FpiSsm *ssm, FpDevice *_dev)
1105 {
1106 ✗ FpImageDevice *dev = FP_IMAGE_DEVICE (_dev);
1107 ✗ FpiDeviceUpeksonly *self = FPI_DEVICE_UPEKSONLY (_dev);
1108
1109 ✗ switch (fpi_ssm_get_cur_state (ssm))
1110 {
1111 ✗ case INITSM_2016_WRITEV_1:
1112 ✗ sm_write_regs (ssm, _dev, initsm_2016_writev_1, G_N_ELEMENTS (initsm_2016_writev_1));
1113 ✗ break;
1114
1115 ✗ case INITSM_2016_READ_09:
1116 ✗ sm_read_reg (ssm, dev, 0x09);
1117 ✗ break;
1118
1119 ✗ case INITSM_2016_WRITE_09:
1120 ✗ sm_write_reg (ssm, dev, 0x09, self->read_reg_result & ~0x08);
1121 ✗ break;
1122
1123 ✗ case INITSM_2016_READ_13:
1124 ✗ sm_read_reg (ssm, dev, 0x13);
1125 ✗ break;
1126
1127 ✗ case INITSM_2016_WRITE_13:
1128 ✗ sm_write_reg (ssm, dev, 0x13, self->read_reg_result & ~0x10);
1129 ✗ break;
1130
1131 ✗ case INITSM_2016_WRITE_04:
1132 ✗ sm_write_reg (ssm, dev, 0x04, 0x00);
1133 ✗ break;
1134
1135 ✗ case INITSM_2016_WRITE_05:
1136 ✗ sm_write_reg (ssm, dev, 0x05, 0x00);
1137 ✗ break;
1138 }
1139 ✗ }
1140
1141 static void
1142 ✗ initsm_1000_run_state (FpiSsm *ssm, FpDevice *_dev)
1143 {
1144 ✗ switch (fpi_ssm_get_cur_state (ssm))
1145 {
1146 ✗ case INITSM_1000_WRITEV_1:
1147 ✗ sm_write_regs (ssm, _dev, initsm_1000_writev_1, G_N_ELEMENTS (initsm_1000_writev_1));
1148 ✗ break;
1149 }
1150 ✗ }
1151
1152 static void
1153 ✗ initsm_1001_run_state (FpiSsm *ssm, FpDevice *_dev)
1154 {
1155 ✗ switch (fpi_ssm_get_cur_state (ssm))
1156 {
1157 ✗ case INITSM_1001_WRITEV_1:
1158 ✗ sm_write_regs (ssm, _dev, initsm_1001_writev_1, G_N_ELEMENTS (initsm_1001_writev_1));
1159 ✗ break;
1160
1161 ✗ case INITSM_1001_WRITEV_2:
1162 ✗ sm_write_regs (ssm, _dev, initsm_1001_writev_2, G_N_ELEMENTS (initsm_1001_writev_2));
1163 ✗ break;
1164
1165 ✗ case INITSM_1001_WRITEV_3:
1166 ✗ sm_write_regs (ssm, _dev, initsm_1001_writev_3, G_N_ELEMENTS (initsm_1001_writev_3));
1167 ✗ break;
1168
1169 ✗ case INITSM_1001_WRITEV_4:
1170 ✗ sm_write_regs (ssm, _dev, initsm_1001_writev_4, G_N_ELEMENTS (initsm_1001_writev_4));
1171 ✗ break;
1172
1173 ✗ case INITSM_1001_WRITEV_5:
1174 ✗ sm_write_regs (ssm, _dev, initsm_1001_writev_5, G_N_ELEMENTS (initsm_1001_writev_5));
1175 ✗ break;
1176 }
1177 ✗ }
1178
1179 /***** CAPTURE LOOP *****/
1180
1181 enum loopsm_states {
1182 LOOPSM_RUN_AWFSM,
1183 LOOPSM_AWAIT_FINGER,
1184 LOOPSM_RUN_CAPSM,
1185 LOOPSM_CAPTURE,
1186 LOOPSM_RUN_DEINITSM,
1187 LOOPSM_FINAL,
1188 LOOPSM_NUM_STATES,
1189 };
1190
1191 static void
1192 ✗ loopsm_run_state (FpiSsm *ssm, FpDevice *_dev)
1193 {
1194 ✗ FpImageDevice *dev = FP_IMAGE_DEVICE (_dev);
1195 ✗ FpiDeviceUpeksonly *self = FPI_DEVICE_UPEKSONLY (_dev);
1196
1197 ✗ switch (fpi_ssm_get_cur_state (ssm))
1198 {
1199 ✗ case LOOPSM_RUN_AWFSM:;
1200 ✗ switch (self->dev_model)
1201 {
1202 ✗ case UPEKSONLY_1001:
1203 ✗ if (self->deactivating)
1204 ✗ fpi_ssm_mark_completed (ssm);
1205 else
1206 ✗ fpi_ssm_next_state (ssm);
1207 break;
1208
1209 ✗ default:
1210 ✗ if (self->deactivating)
1211 {
1212 ✗ fpi_ssm_mark_completed (ssm);
1213 }
1214 else
1215 {
1216 ✗ FpiSsm *awfsm = NULL;
1217 ✗ switch (self->dev_model)
1218 {
1219 case UPEKSONLY_2016:
1220 ✗ awfsm = fpi_ssm_new (FP_DEVICE (dev),
1221 awfsm_2016_run_state,
1222 AWFSM_2016_NUM_STATES);
1223 ✗ break;
1224
1225 case UPEKSONLY_1000:
1226 ✗ awfsm = fpi_ssm_new (FP_DEVICE (dev),
1227 awfsm_1000_run_state,
1228 AWFSM_1000_NUM_STATES);
1229 ✗ break;
1230
1231 ✗ default:
1232 ✗ g_assert_not_reached ();
1233 }
1234 ✗ fpi_ssm_start_subsm (ssm, awfsm);
1235 }
1236 break;
1237 }
1238 break;
1239
1240 ✗ case LOOPSM_AWAIT_FINGER:
1241 ✗ switch (self->dev_model)
1242 {
1243 ✗ case UPEKSONLY_1001:
1244 ✗ fpi_ssm_next_state (ssm);
1245 ✗ break;
1246
1247 ✗ default:
1248 ✗ sm_await_intr (ssm, dev);
1249 ✗ break;
1250 }
1251 break;
1252
1253 ✗ case LOOPSM_RUN_CAPSM:;
1254 ✗ FpiSsm *capsm = NULL;
1255 ✗ switch (self->dev_model)
1256 {
1257 case UPEKSONLY_2016:
1258 ✗ capsm = fpi_ssm_new (FP_DEVICE (dev),
1259 capsm_2016_run_state,
1260 CAPSM_2016_NUM_STATES);
1261 ✗ break;
1262
1263 case UPEKSONLY_1000:
1264 ✗ capsm = fpi_ssm_new (FP_DEVICE (dev),
1265 capsm_1000_run_state,
1266 CAPSM_1000_NUM_STATES);
1267 ✗ break;
1268
1269 case UPEKSONLY_1001:
1270 ✗ capsm = fpi_ssm_new (FP_DEVICE (dev),
1271 capsm_1001_run_state,
1272 CAPSM_1001_NUM_STATES);
1273 ✗ break;
1274
1275 ✗ default:
1276 ✗ g_assert_not_reached ();
1277 }
1278 ✗ fpi_ssm_start_subsm (ssm, capsm);
1279 ✗ break;
1280
1281 case LOOPSM_CAPTURE:
1282 break;
1283
1284 ✗ case LOOPSM_RUN_DEINITSM:;
1285 ✗ FpiSsm *deinitsm = NULL;
1286 ✗ switch (self->dev_model)
1287 {
1288 case UPEKSONLY_2016:
1289 ✗ deinitsm = fpi_ssm_new (FP_DEVICE (dev),
1290 deinitsm_2016_run_state,
1291 DEINITSM_2016_NUM_STATES);
1292 ✗ break;
1293
1294 case UPEKSONLY_1000:
1295 ✗ deinitsm = fpi_ssm_new (FP_DEVICE (dev),
1296 deinitsm_1000_run_state,
1297 DEINITSM_1000_NUM_STATES);
1298 ✗ break;
1299
1300 case UPEKSONLY_1001:
1301 ✗ deinitsm = fpi_ssm_new (FP_DEVICE (dev),
1302 deinitsm_1001_run_state,
1303 DEINITSM_1001_NUM_STATES);
1304 ✗ break;
1305
1306 ✗ default:
1307 ✗ g_assert_not_reached ();
1308 }
1309 ✗ self->capturing = FALSE;
1310 ✗ fpi_ssm_start_subsm (ssm, deinitsm);
1311 ✗ break;
1312
1313 ✗ case LOOPSM_FINAL:
1314 ✗ fpi_ssm_jump_to_state (ssm, LOOPSM_RUN_AWFSM);
1315 ✗ break;
1316 }
1317
1318 ✗ }
1319
1320 /***** DRIVER STUFF *****/
1321
1322 static void
1323 ✗ deactivate_done (FpImageDevice *dev, GError *error)
1324 {
1325 ✗ FpiDeviceUpeksonly *self = FPI_DEVICE_UPEKSONLY (dev);
1326
1327 ✗ G_DEBUG_HERE ();
1328 ✗ free_img_transfers (self);
1329 ✗ g_free (self->rowbuf);
1330 ✗ self->rowbuf = NULL;
1331
1332 ✗ g_slist_free_full (self->rows, g_free);
1333 ✗ self->rows = NULL;
1334
1335 ✗ fpi_image_device_deactivate_complete (dev, error);
1336 ✗ }
1337
1338 static void
1339 ✗ dev_deactivate (FpImageDevice *dev)
1340 {
1341 ✗ FpiDeviceUpeksonly *self = FPI_DEVICE_UPEKSONLY (dev);
1342
1343 ✗ if (!self->capturing)
1344 {
1345 ✗ deactivate_done (dev, NULL);
1346 ✗ return;
1347 }
1348
1349 ✗ self->deactivating = TRUE;
1350 ✗ self->killing_transfers = ITERATE_SSM;
1351 ✗ self->kill_ssm = self->loopsm;
1352 ✗ cancel_img_transfers (dev);
1353 }
1354
1355 static void
1356 ✗ loopsm_complete (FpiSsm *ssm, FpDevice *_dev, GError *error)
1357 {
1358 ✗ FpImageDevice *dev = FP_IMAGE_DEVICE (_dev);
1359 ✗ FpiDeviceUpeksonly *self = FPI_DEVICE_UPEKSONLY (_dev);
1360
1361
1362 ✗ if (self->deactivating)
1363 {
1364 ✗ deactivate_done (dev, error);
1365 ✗ return;
1366 }
1367
1368 ✗ if (error)
1369 {
1370 ✗ fpi_image_device_session_error (dev, error);
1371 ✗ return;
1372 }
1373 }
1374
1375 static void
1376 ✗ initsm_complete (FpiSsm *ssm, FpDevice *_dev, GError *error)
1377 {
1378 ✗ FpImageDevice *dev = FP_IMAGE_DEVICE (_dev);
1379 ✗ FpiDeviceUpeksonly *self = FPI_DEVICE_UPEKSONLY (_dev);
1380
1381 ✗ fpi_image_device_activate_complete (dev, error);
1382 ✗ if (error)
1383 return;
1384
1385 ✗ self->loopsm = fpi_ssm_new (FP_DEVICE (dev), loopsm_run_state,
1386 LOOPSM_NUM_STATES);
1387 ✗ fpi_ssm_start (self->loopsm, loopsm_complete);
1388 }
1389
1390 static void
1391 ✗ dev_activate (FpImageDevice *dev)
1392 {
1393 ✗ FpiDeviceUpeksonly *self = FPI_DEVICE_UPEKSONLY (dev);
1394 ✗ FpiSsm *ssm = NULL;
1395 ✗ int i;
1396
1397 ✗ self->deactivating = FALSE;
1398 ✗ self->capturing = FALSE;
1399
1400 ✗ self->num_flying = 0;
1401 ✗ self->img_transfers = g_ptr_array_new_with_free_func ((GFreeFunc) fpi_usb_transfer_unref);
1402
1403 /* This might seem odd, but we do need multiple in-flight URBs so that
1404 * we never stop polling the device for more data.
1405 */
1406 ✗ for (i = 0; i < NUM_BULK_TRANSFERS; i++)
1407 {
1408 ✗ FpiUsbTransfer *transfer;
1409
1410 ✗ transfer = fpi_usb_transfer_new (FP_DEVICE (dev));
1411 ✗ fpi_usb_transfer_fill_bulk (transfer, 0x81, 4096);
1412
1413 ✗ g_ptr_array_add (self->img_transfers, transfer);
1414 }
1415
1416 ✗ switch (self->dev_model)
1417 {
1418 case UPEKSONLY_2016:
1419 ✗ ssm = fpi_ssm_new (FP_DEVICE (dev), initsm_2016_run_state,
1420 INITSM_2016_NUM_STATES);
1421 ✗ break;
1422
1423 case UPEKSONLY_1000:
1424 ✗ ssm = fpi_ssm_new (FP_DEVICE (dev), initsm_1000_run_state,
1425 INITSM_1000_NUM_STATES);
1426 ✗ break;
1427
1428 case UPEKSONLY_1001:
1429 ✗ ssm = fpi_ssm_new (FP_DEVICE (dev), initsm_1001_run_state,
1430 INITSM_1001_NUM_STATES);
1431 ✗ break;
1432
1433 ✗ default:
1434 ✗ g_assert_not_reached ();
1435 }
1436 ✗ fpi_ssm_start (ssm, initsm_complete);
1437 ✗ }
1438
1439 static void dev_init (FpImageDevice *dev);
1440
1441 static void
1442 ✗ dev_deinit (FpImageDevice *dev)
1443 {
1444 ✗ GError *error = NULL;
1445
1446 ✗ g_usb_device_release_interface (fpi_device_get_usb_device (FP_DEVICE (dev)),
1447 0, 0, &error);
1448 ✗ fpi_image_device_close_complete (dev, error);
1449 ✗ }
1450
1451 static gint
1452 ✗ dev_discover (GUsbDevice *usb_device)
1453 {
1454 ✗ guint16 pid = g_usb_device_get_pid (usb_device);
1455 ✗ guint16 bcd = g_usb_device_get_release (usb_device);
1456
1457 ✗ if (pid == 0x2016)
1458 ✗ if (bcd == 1) /* Revision 1 is what we're interested in */
1459 return 1;
1460 ✗ if (pid == 0x1000)
1461 ✗ if (bcd == 0x0033) /* Looking for revision 0.33 */
1462 return 1;
1463
1464 ✗ if (pid == 0x1001)
1465 ✗ return 1;
1466
1467 return 0;
1468 }
1469
1470 static const FpIdEntry id_table[] = {
1471 { .vid = 0x147e, .pid = 0x2016, .driver_data = UPEKSONLY_2016 },
1472 { .vid = 0x147e, .pid = 0x1000, .driver_data = UPEKSONLY_1000 },
1473 { .vid = 0x147e, .pid = 0x1001, .driver_data = UPEKSONLY_1001 },
1474 { .vid = 0, .pid = 0, .driver_data = 0 },
1475 };
1476
1477 static void
1478 ✗ fpi_device_upeksonly_init (FpiDeviceUpeksonly *self)
1479 {
1480 ✗ }
1481 static void
1482 128 fpi_device_upeksonly_class_init (FpiDeviceUpeksonlyClass *klass)
1483 {
1484 128 FpDeviceClass *dev_class = FP_DEVICE_CLASS (klass);
1485 128 FpImageDeviceClass *img_class = FP_IMAGE_DEVICE_CLASS (klass);
1486
1487 128 dev_class->id = "upeksonly";
1488 128 dev_class->full_name = "UPEK TouchStrip Sensor-Only";
1489 128 dev_class->type = FP_DEVICE_TYPE_USB;
1490 128 dev_class->id_table = id_table;
1491 128 dev_class->scan_type = FP_SCAN_TYPE_SWIPE;
1492
1493 128 dev_class->usb_discover = dev_discover;
1494
1495 128 img_class->img_open = dev_init;
1496 128 img_class->img_close = dev_deinit;
1497 128 img_class->activate = dev_activate;
1498 128 img_class->deactivate = dev_deactivate;
1499
1500 128 img_class->img_width = -1;
1501 128 img_class->img_height = -1;
1502 }
1503
1504 static void
1505 ✗ dev_init (FpImageDevice *dev)
1506 {
1507 ✗ GError *error = NULL;
1508 ✗ FpiDeviceUpeksonly *self = FPI_DEVICE_UPEKSONLY (dev);
1509
1510 ✗ if (!g_usb_device_set_configuration (fpi_device_get_usb_device (FP_DEVICE (dev)), 1, &error))
1511 {
1512 ✗ fp_err ("could not set configuration 1");
1513 ✗ fpi_image_device_open_complete (dev, error);
1514 }
1515
1516 ✗ if (!g_usb_device_claim_interface (fpi_device_get_usb_device (FP_DEVICE (dev)), 0, 0, &error))
1517 {
1518 ✗ fpi_image_device_open_complete (dev, error);
1519 ✗ return;
1520 }
1521
1522 ✗ self->assembling_ctx.max_height = 1024;
1523 ✗ self->assembling_ctx.resolution = 8;
1524 ✗ self->assembling_ctx.median_filter_size = 25;
1525 ✗ self->assembling_ctx.max_search_offset = 30;
1526 ✗ self->assembling_ctx.get_deviation = upeksonly_get_deviation2;
1527 ✗ self->assembling_ctx.get_pixel = upeksonly_get_pixel;
1528
1529 ✗ self = FPI_DEVICE_UPEKSONLY (dev);
1530 ✗ self->dev_model = (int) fpi_device_get_driver_data (FP_DEVICE (dev));
1531 ✗ switch (self->dev_model)
1532 {
1533 ✗ case UPEKSONLY_1000:
1534 ✗ self->img_width = IMG_WIDTH_1000;
1535 ✗ self->assembling_ctx.line_width = IMG_WIDTH_1000;
1536 ✗ break;
1537
1538 ✗ case UPEKSONLY_1001:
1539 ✗ self->img_width = IMG_WIDTH_1001;
1540 ✗ self->assembling_ctx.line_width = IMG_WIDTH_1001;
1541
1542 /* The sensor resolution is too low for the normal threshold. */
1543 ✗ fpi_image_device_set_bz3_threshold (dev, 25);
1544 ✗ break;
1545
1546 ✗ case UPEKSONLY_2016:
1547 ✗ self->img_width = IMG_WIDTH_2016;
1548 ✗ self->assembling_ctx.line_width = IMG_WIDTH_2016;
1549 ✗ break;
1550
1551 ✗ default:
1552 ✗ g_assert_not_reached ();
1553 }
1554 ✗ fpi_image_device_open_complete (dev, NULL);
1555 }
1556