GCC Code Coverage Report


Directory: ./
File: libfprint/drivers/upeksonly.c
Date: 2024-05-04 14:54:39
Exec Total Coverage
Lines: 16 689 2.3%
Functions: 3 45 6.7%
Branches: 4 250 1.6%

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/5
✓ Branch 0 taken 117 times.
✓ Branch 1 taken 24 times.
✓ Branch 2 taken 117 times.
✓ Branch 3 taken 117 times.
✗ Branch 4 not taken.
750 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 117 fpi_device_upeksonly_class_init (FpiDeviceUpeksonlyClass *klass)
1483 {
1484 117 FpDeviceClass *dev_class = FP_DEVICE_CLASS (klass);
1485 117 FpImageDeviceClass *img_class = FP_IMAGE_DEVICE_CLASS (klass);
1486
1487 117 dev_class->id = "upeksonly";
1488 117 dev_class->full_name = "UPEK TouchStrip Sensor-Only";
1489 117 dev_class->type = FP_DEVICE_TYPE_USB;
1490 117 dev_class->id_table = id_table;
1491 117 dev_class->scan_type = FP_SCAN_TYPE_SWIPE;
1492
1493 117 dev_class->usb_discover = dev_discover;
1494
1495 117 img_class->img_open = dev_init;
1496 117 img_class->img_close = dev_deinit;
1497 117 img_class->activate = dev_activate;
1498 117 img_class->deactivate = dev_deactivate;
1499
1500 117 img_class->img_width = -1;
1501 117 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