1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
|
diff --git a/libfprint/drivers/goodixtls/goodix55x4.c b/libfprint/drivers/goodixtls/goodix55x4.c
index 20db582..a40a97b 100644
--- a/libfprint/drivers/goodixtls/goodix55x4.c
+++ b/libfprint/drivers/goodixtls/goodix55x4.c
@@ -53,6 +53,18 @@
(GOODIX55X4_HEIGHT * GOODIX55X4_SCAN_WIDTH) / 4 * 6
#define GOODIX55X4_CAP_FRAMES 1 // Number of frames we capture per swipe
+// The MCU's FDT down reply doesn't actually block until a real touch on
+// this firmware - it's an instantaneous check regardless of the
+// configured threshold. Touch detection is done here instead, by
+// polling captured frames and diffing them against the calibration
+// background (empty_img) until real content appears.
+#define GOODIX55X4_FINGER_DETECT_MAX_ATTEMPTS 100
+#define GOODIX55X4_FINGER_DETECT_POLL_DELAY_MS 100
+// Average per-pixel absolute difference (12-bit pixels, 0-4095) needed
+// to call a frame a real touch. Validated against real 55b4 hardware:
+// background noise sits around 4-5, a real touch around 750+.
+#define GOODIX55X4_FINGER_DETECT_DIFF_THRESHOLD 100
+
typedef unsigned short Goodix55X4Pix;
struct _FpiDeviceGoodixTls55X4 {
@@ -61,6 +73,7 @@ struct _FpiDeviceGoodixTls55X4 {
guint8 *otp;
GSList *frames;
+ guint poll_attempts;
Goodix55X4Pix empty_img[GOODIX55X4_FRAME_SIZE];
};
@@ -480,6 +493,16 @@ postprocess_frame(Goodix55X4Pix frame[GOODIX55X4_FRAME_SIZE],
return sum != 0;
}
+static double
+frame_diff_score(Goodix55X4Pix frame[GOODIX55X4_FRAME_SIZE],
+ Goodix55X4Pix background[GOODIX55X4_FRAME_SIZE]) {
+ guint64 sum = 0;
+ for (int i = 0; i != GOODIX55X4_FRAME_SIZE; ++i) {
+ sum += ABS((int)frame[i] - (int)background[i]);
+ }
+ return (double)sum / GOODIX55X4_FRAME_SIZE;
+}
+
typedef struct _frame_processing_info {
FpiDeviceGoodixTls55X4 *dev;
GSList **frames;
@@ -502,6 +525,11 @@ static void save_frame(FpiDeviceGoodixTls55X4 *self, guint8 *raw) {
self->frames = g_slist_append(self->frames, frame);
}
+static void retry_finger_poll(FpDevice *dev, gpointer user_data) {
+ FpiSsm *ssm = user_data;
+ fpi_ssm_jump_to_state(ssm, SCAN_STAGE_SWITCH_TO_FDT_MODE);
+}
+
static void scan_on_read_img(FpDevice *dev, guint8 *data, guint16 len,
gpointer ssm, GError *err) {
g_print("SCAN_ON_READ_IMG\n");
@@ -511,6 +539,26 @@ static void scan_on_read_img(FpDevice *dev, guint8 *data, guint16 len,
}
FpiDeviceGoodixTls55X4 *self = FPI_DEVICE_GOODIXTLS55X4(dev);
+
+ Goodix55X4Pix candidate[GOODIX55X4_FRAME_SIZE];
+ decode_frame(candidate, data);
+
+ double diff = frame_diff_score(candidate, self->empty_img);
+ g_print("Finger-detect poll: diff vs background = %.1f\n", diff);
+
+ if (diff < GOODIX55X4_FINGER_DETECT_DIFF_THRESHOLD) {
+ if (++self->poll_attempts >= GOODIX55X4_FINGER_DETECT_MAX_ATTEMPTS) {
+ fpi_ssm_mark_failed(ssm,
+ fpi_device_retry_new(FP_DEVICE_RETRY_GENERAL));
+ return;
+ }
+
+ fpi_device_add_timeout(dev, GOODIX55X4_FINGER_DETECT_POLL_DELAY_MS,
+ retry_finger_poll, ssm, NULL);
+ return;
+ }
+
+ self->poll_attempts = 0;
save_frame(self, data);
if (g_slist_length(self->frames) <= GOODIX55X4_CAP_FRAMES) {
fpi_ssm_jump_to_state(ssm, SCAN_STAGE_SWITCH_TO_FDT_MODE);
@@ -772,6 +820,7 @@ static void sleep_complete(FpiSsm *ssm, FpDevice *dev, GError *error) {
}
static void scan_start(FpiDeviceGoodixTls55X4 *dev) {
+ dev->poll_attempts = 0;
fpi_ssm_start(fpi_ssm_new(FP_DEVICE(dev), scan_run_state, SCAN_STAGE_NUM),
scan_complete);
}
|